From fcb98e91a1e521b895cb58e8ac424f51dfd4e96a Mon Sep 17 00:00:00 2001
From: Pu Zhibing <393733352@qq.com>
Date: 星期二, 18 二月 2025 18:27:02 +0800
Subject: [PATCH] 提交基础版本

---
 ruoyi-admin/src/main/resources/static/js/jquery.tmpl.js                                                                       |  492 
 ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaException.java                                              |   16 
 ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/CacheService.java                                               |   84 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileTypeUtils.java                                                     |   76 
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserOnlineMapper.java                                                   |   52 
 ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/editable/bootstrap-editable.css                    |  674 
 ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/reorder-rows/jquery.tablednd.js                    |  603 
 ruoyi-admin/src/main/resources/static/ajax/libs/summernote/summernote.css                                                     |   13 
 ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordNotMatchException.java                                 |   16 
 ruoyi-admin/src/main/resources/static/ajax/libs/datapicker/bootstrap-datetimepicker.css                                       |  418 
 ruoyi-admin/src/main/resources/static/img/progress.png                                                                        |    0 
 ruoyi-admin/src/main/resources/templates/demo/form/jasny.html                                                                 |  118 
 ruoyi-admin/src/main/resources/templates/demo/table/refresh.html                                                              |   79 
 ruoyi-admin/src/main/resources/static/css/font-awesome.min.css                                                                |    4 
 ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-fileinput/loading.gif                                               |    0 
 ruoyi-admin/src/main/resources/static/fonts/fontawesome-webfont.woff2                                                         |    0 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/html/HTMLFilter.java                                                        |  570 
 ruoyi-generator/src/main/resources/vm/html/list.html.vm                                                                       |  154 
 ruoyi-admin/src/main/resources/static/ajax/libs/flot/jquery.flot.pie.js                                                       |  750 
 ruoyi-admin/src/main/resources/static/img/blue.png                                                                            |    0 
 ruoyi-admin/src/main/resources/static/ruoyi/js/ry-ui.js                                                                       | 1793 
 ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/PermitAllUrlProperties.java                               |  151 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/UUID.java                                                              |  484 
 ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/metro/zTreeStyle.css                                     |  107 
 ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/tree/bootstrap-table-tree.min.js                   |    5 
 ruoyi-admin/src/main/resources/templates/system/dept/tree.html                                                                |   52 
 ruoyi-admin/src/main/resources/templates/system/config/add.html                                                               |   79 
 ruoyi-common/src/main/java/com/ruoyi/common/core/context/PermissionContextHolder.java                                         |   27 
 ruoyi-admin/src/main/resources/templates/system/role/edit.html                                                                |  183 
 ruoyi-generator/pom.xml                                                                                                       |   40 
 ruoyi-admin/src/main/resources/templates/demo/table/subdata.html                                                              |  242 
 ruoyi-common/src/main/java/com/ruoyi/common/json/JSON.java                                                                    |  187 
 ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/DictService.java                                                |   46 
 ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/simple/img/zTreeStandard.png                             |    0 
 ruoyi-admin/src/main/resources/templates/register.html                                                                        |   81 
 ruoyi-generator/src/main/resources/vm/java/sub-domain.java.vm                                                                 |   76 
 ruoyi-admin/src/main/resources/templates/demo/table/search.html                                                               |  202 
 ruoyi-admin/src/main/resources/templates/system/menu/menu.html                                                                |  161 
 ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessType.java                                                           |   59 
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysConfigMapper.java                                                       |   76 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/demo/controller/DemoDialogController.java                                  |   98 
 ruoyi-admin/src/main/resources/static/favicon.ico                                                                             |    0 
 ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java                                               |  129 
 ruoyi-admin/src/main/resources/templates/system/menu/tree.html                                                                |   49 
 ruoyi-admin/src/main/resources/templates/system/user/resetPwd.html                                                            |   51 
 ruoyi-system/src/main/resources/mapper/system/SysConfigMapper.xml                                                             |  117 
 ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/simple/img/left_menu.gif                                 |    0 
 ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/web/session/OnlineWebSessionManager.java                              |  175 
 ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobLogController.java                                               |  103 
 ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/diy/1_open.png                               |    0 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java                                               |  165 
 ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-select/bootstrap-select.min.css                                     |    6 
 ruoyi-admin/src/main/resources/static/fonts/fontawesome-webfont.ttf                                                           |    0 
 ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserException.java                                                 |   18 
 pom.xml                                                                                                                       |  290 
 ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/reorder-columns/jquery.dragtable.js                |   22 
 ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java                                                      |   85 
 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysPostService.java                                                      |   91 
 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java                                                    |   82 
 doc/若依环境使用手册.docx                                                                                                             |    0 
 ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Mem.java                                                  |   61 
 ruoyi-admin/src/main/resources/templates/demo/modal/table/parent.html                                                         |  102 
 ruoyi-framework/src/main/java/com/ruoyi/framework/config/I18nConfig.java                                                      |   43 
 ruoyi-system/src/main/resources/mapper/system/SysNoticeMapper.xml                                                             |   85 
 ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/metro/img/metro.gif                                      |    0 
 ruoyi-common/src/main/java/com/ruoyi/common/enums/UserStatus.java                                                             |   30 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/DesensitizedUtil.java                                                       |   49 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java                                                              |  191 
 ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excels.java                                                            |   18 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java                                              |  198 
 ruoyi-admin/src/main/resources/static/fonts/FontAwesome.otf                                                                   |    0 
 ruoyi-admin/src/main/resources/static/fonts/iconfont.svg                                                                      |  405 
 ruoyi-admin/src/main/resources/templates/system/role/dataScope.html                                                           |  137 
 sql/quartz.sql                                                                                                                |  174 
 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysLogininfor.java                                                         |  159 
 ruoyi-admin/src/main/resources/static/ajax/libs/duallistbox/bootstrap-duallistbox.js                                          |  844 
 ruoyi-admin/src/main/resources/static/ajax/libs/validate/messages_zh.js                                                       |   25 
 ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java                                                        |   28 
 ruoyi-admin/src/main/resources/templates/demo/form/cards.html                                                                 |  319 
 ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java                                               |  229 
 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java                                                      |  139 
 ruoyi-admin/src/main/resources/templates/demo/table/cookie.html                                                               |   78 
 ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/diy/4.png                                    |    0 
 ruoyi-admin/src/main/resources/templates/demo/table/other.html                                                                |  106 
 ruoyi-admin/src/main/resources/templates/system/dict/data/add.html                                                            |  100 
 ruoyi-generator/src/main/resources/vm/sql/sql.vm                                                                              |   22 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/demo/controller/DemoOperateController.java                                 |  326 
 ruoyi-admin/src/main/resources/static/js/resize-tabs.js                                                                       |    1 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java                                               |   90 
 ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/service/SysLoginService.java                                          |  188 
 ruoyi-admin/src/main/resources/templates/system/user/profile/avatar.html                                                      |  261 
 ruoyi-admin/src/main/resources/static/ajax/libs/select2/select2.css                                                           |  481 
 ruoyi-admin/src/main/resources/static/ruoyi.png                                                                               |    0 
 ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobLogServiceImpl.java                                            |   88 
 ruoyi-common/src/main/java/com/ruoyi/common/constant/ShiroConstants.java                                                      |   79 
 ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java                                                                     |   30 
 ruoyi-admin/src/main/resources/templates/demo/operate/edit.html                                                               |   79 
 ruoyi-common/src/main/java/com/ruoyi/common/config/ServerConfig.java                                                          |   33 
 ruoyi-admin/src/main/resources/templates/system/notice/add.html                                                               |   98 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/CacheUtils.java                                                             |  197 
 ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/web/CustomShiroFilterFactoryBean.java                                 |   85 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java                                             |   82 
 bin/run.bat                                                                                                                   |   14 
 bin/package.bat                                                                                                               |   12 
 ruoyi-admin/src/main/resources/templates/demo/form/labels_tips.html                                                           |  237 
 ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/columns/bootstrap-table-fixed-columns.js           |    5 
 LICENSE                                                                                                                       |   20 
 ruoyi-common/src/main/java/com/ruoyi/common/exception/file/InvalidExtensionException.java                                     |   80 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/MapDataUtil.java                                                            |   54 
 ruoyi-admin/src/main/resources/templates/demo/form/tabs_panels.html                                                           |  353 
 ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java                                               |   34 
 ruoyi-admin/src/main/resources/templates/system/post/post.html                                                                |  120 
 ruoyi-admin/src/main/resources/static/js/cron.js                                                                              |  926 
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserPostMapper.java                                                     |   44 
 ruoyi-admin/src/main/resources/templates/system/post/add.html                                                                 |   97 
 ruoyi-generator/src/main/resources/vm/java/service.java.vm                                                                    |   73 
 ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJob.java                                                                |  169 
 ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/ScheduleUtils.java                                                           |  141 
 ruoyi-admin/src/main/resources/static/fonts/fontawesome-webfont.eot                                                           |    0 
 ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessStatus.java                                                         |   19 
 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserRole.java                                                           |   46 
 ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileException.java                                                 |   19 
 ruoyi-admin/src/main/resources/templates/demo/table/params.html                                                               |  158 
 ruoyi-admin/src/main/resources/templates/demo/form/upload.html                                                                |   75 
 ruoyi-admin/src/main/resources/templates/index-topnav.html                                                                    |  450 
 ruoyi-admin/src/main/resources/templates/demo/table/fixedColumns.html                                                         |  145 
 ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileUploadException.java                                           |   61 
 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserPost.java                                                           |   46 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/demo/controller/DemoIconController.java                                    |   35 
 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/AjaxResult.java                                                       |  227 
 ruoyi-admin/src/main/resources/static/file/rml.txt                                                                            |    1 
 ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java                                                        |  114 
 ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Jvm.java                                                  |  130 
 ruoyi-admin/src/main/resources/templates/demo/form/datetime.html                                                              |  237 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/LogUtils.java                                                               |  135 
 ruoyi-admin/src/main/resources/static/ajax/libs/select2/select2.js                                                            | 6108 ++
 ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java                                                |  182 
 ruoyi-common/src/main/java/com/ruoyi/common/xss/XssHttpServletRequestWrapper.java                                             |   39 
 ruoyi-admin/src/main/resources/templates/demo/form/cxselect.html                                                              |  161 
 ruoyi-admin/src/main/resources/static/ajax/libs/report/echarts/echarts-all.min.js                                             |   52 
 ruoyi-admin/src/main/resources/static/ajax/libs/fullscreen/jquery.fullscreen.js                                               |  182 
 ruoyi-admin/src/main/resources/static/js/jquery.i18n.properties.min.js                                                        |   13 
 ruoyi-admin/src/main/resources/static/img/profile.jpg                                                                         |    0 
 ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/zTreeStandard.png                            |    0 
 ruoyi-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java                                                      |   29 
 ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java                                                     |  422 
 ruoyi-quartz/src/main/java/com/ruoyi/quartz/config/ScheduleConfig.java                                                        |   57 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysPostServiceImpl.java                                              |  181 
 ruoyi-admin/src/main/resources/static/ajax/libs/typeahead/bootstrap-typeahead.min.js                                          |    1 
 ruoyi-admin/src/main/resources/static/css/bootstrap.min.css                                                                   |    5 
 ruoyi-system/src/main/resources/mapper/system/SysUserOnlineMapper.xml                                                         |   57 
 ruoyi-admin/src/main/resources/static/ajax/libs/blockUI/jquery.blockUI.js                                                     |  620 
 ruoyi-admin/src/main/resources/templates/demo/form/autocomplete.html                                                          |  323 
 ruoyi-admin/src/main/resources/templates/error/service.html                                                                   |   20 
 ruoyi-system/src/main/resources/mapper/system/SysDictTypeMapper.xml                                                           |  105 
 ruoyi-admin/src/main/resources/static/fonts/glyphicons-halflings-regular.eot                                                  |    0 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/TestController.java                                                   |  183 
 ruoyi-admin/src/main/resources/static/fonts/iconfont.ttf                                                                      |    0 
 ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java                                |   83 
 ruoyi-generator/src/main/resources/vm/java/domain.java.vm                                                                     |  105 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysCaptchaController.java                                           |   92 
 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleMenu.java                                                           |   46 
 ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/js/jquery.ztree.exedit-3.5.js                                | 1178 
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleDeptMapper.java                                                     |   44 
 ruoyi-common/src/main/java/com/ruoyi/common/config/datasource/DynamicDataSourceContextHolder.java                             |   45 
 ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/diy/3.png                                    |    0 
 ruoyi-admin/src/main/resources/templates/system/post/edit.html                                                                |  104 
 ruoyi-admin/src/main/resources/static/ajax/libs/summernote/font/summernote.woff2                                              |    0 
 ruoyi-admin/src/main/resources/templates/demo/table/image.html                                                                |   79 
 ruoyi-quartz/src/main/resources/mapper/quartz/SysJobLogMapper.xml                                                             |   94 
 ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/mobile/bootstrap-table-mobile.js                   |  123 
 ruoyi-system/src/main/resources/mapper/system/SysOperLogMapper.xml                                                            |   86 
 ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java                                                 |   58 
 ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/bootstrap-table.min.css                                       |    6 
 ruoyi-generator/src/main/resources/templates/tool/gen/importTable.html                                                        |   95 
 ruoyi-admin/src/main/resources/templates/system/dict/type/tree.html                                                           |   42 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java                                       |   94 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/Threads.java                                                                |   99 
 ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java                                   |  149 
 ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/js/jquery.ztree.excheck-3.5.js                               |  624 
 ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Cpu.java                                                  |  101 
 ruoyi-framework/src/main/java/com/ruoyi/framework/config/CaptchaConfig.java                                                   |   83 
 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserOnlineService.java                                                |   75 
 ruoyi-admin/src/main/resources/static/ruoyi/login.js                                                                          |   98 
 ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml                                                  |  127 
 ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobServiceImpl.java                                               |  263 
 ruoyi-admin/src/main/resources/templates/demo/table/headerStyle.html                                                          |   91 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserOnlineServiceImpl.java                                        |  140 
 ruoyi-generator/src/main/resources/vm/xml/mapper.xml.vm                                                                       |  152 
 ruoyi-admin/src/main/resources/templates/monitor/online/online.html                                                           |  152 
 ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/locale/bootstrap-table-zh-CN.js                               |  109 
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java                                                         |  124 
 ruoyi-admin/src/main/resources/static/ajax/libs/layui/layui.min.js                                                            |    2 
 ruoyi-admin/src/main/resources/templates/demo/table/asynTree.html                                                             |   85 
 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java                                                   |  211 
 ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml                                                               |  134 
 ruoyi-admin/src/main/resources/templates/skin.html                                                                            |  165 
 ry.sh                                                                                                                         |   86 
 ruoyi-admin/src/main/resources/static/ruoyi/index.js                                                                          |  667 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanValidators.java                                                    |   24 
 ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java                                                        |   67 
 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/CxSelect.java                                                         |   69 
 ruoyi-admin/src/main/resources/static/ajax/libs/validate/jquery.validate.min.js                                               |    4 
 ruoyi-admin/src/main/resources/static/js/plugins/slimscroll/jquery.slimscroll.min.js                                          |    8 
 ruoyi-system/src/main/resources/mapper/system/SysLogininforMapper.xml                                                         |   56 
 ruoyi-admin/src/main/resources/static/ajax/libs/iCheck/green-login.png                                                        |    0 
 ruoyi-admin/src/main/resources/static/ajax/libs/layer/theme/moon/default.png                                                  |    0 
 ruoyi-admin/src/main/resources/templates/demo/table/event.html                                                                |  133 
 ruoyi-common/src/main/java/com/ruoyi/common/xss/Xss.java                                                                      |   27 
 ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-select/bootstrap-select.min.js                                      |    8 
 ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/tree/bootstrap-table-tree.js                       | 1087 
 ruoyi-common/src/main/java/com/ruoyi/common/exception/GlobalException.java                                                    |   58 
 ruoyi-admin/src/main/resources/static/fonts/glyphicons-halflings-regular.svg                                                  |  288 
 ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml                                                               |  231 
 ruoyi-common/src/main/java/com/ruoyi/common/core/text/CharsetKit.java                                                         |   86 
 ruoyi-admin/src/main/resources/static/ruoyi/css/ry-ui.css                                                                     | 1218 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/AddressUtils.java                                                           |   54 
 ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java                                                  |  373 
 ruoyi-common/src/main/java/com/ruoyi/common/exception/ServiceException.java                                                   |   58 
 ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/PermissionsAspect.java                                              |   30 
 ruoyi-admin/src/main/resources/templates/demo/modal/table.html                                                                |  124 
 ruoyi-generator/src/main/java/com/ruoyi/generator/service/impl/GenTableServiceImpl.java                                       |  534 
 ruoyi-admin/src/main/resources/templates/system/dept/dept.html                                                                |  112 
 ruoyi-admin/src/main/resources/static/ajax/libs/summernote/font/summernote.eot                                                |    0 
 ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java                                                           |  122 
 ruoyi-framework/src/main/java/com/ruoyi/framework/config/DruidConfig.java                                                     |  128 
 ruoyi-admin/src/main/resources/static/css/zen-checkbox.css                                                                    |  149 
 ruoyi-admin/src/main/resources/static/ajax/libs/flot/jquery.flot.symbol.js                                                    |   71 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/CookieUtils.java                                                            |  138 
 ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/diy/2.png                                    |    0 
 ruoyi-framework/src/main/java/com/ruoyi/framework/manager/ShutdownManager.java                                                |   87 
 ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/session/OnlineSessionFactory.java                                     |   42 
 ruoyi-quartz/src/main/resources/templates/monitor/job/edit.html                                                               |  111 
 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java                                                      |  117 
 ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/resizable/bootstrap-table-resizable.js             |   68 
 ruoyi-admin/src/main/resources/templates/demo/form/basic.html                                                                 |  593 
 ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/realm/UserRealm.java                                                  |  158 
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictDataMapper.java                                                     |   95 
 ruoyi-common/src/main/java/com/ruoyi/common/enums/OnlineStatus.java                                                           |   24 
 ruoyi-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml                                                           |   34 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/file/MimeTypeUtils.java                                                     |   59 
 ruoyi-admin/src/main/resources/templates/demo/icon/glyphicons.html                                                            | 1364 
 ruoyi-admin/src/main/resources/templates/demo/operate/table.html                                                              |  125 
 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java                                                       |   63 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java                                              |  156 
 ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/service/SysShiroService.java                                          |   62 
 ruoyi-common/src/main/java/com/ruoyi/common/json/JSONObject.java                                                              |  749 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/file/ImageUtils.java                                                        |   98 
 ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml                                                        |  204 
 ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/web/filter/captcha/CaptchaValidateFilter.java                         |   79 
 ruoyi-generator/src/main/java/com/ruoyi/generator/service/impl/GenTableColumnServiceImpl.java                                 |   69 
 ruoyi-common/src/main/java/com/ruoyi/common/exception/DemoModeException.java                                                  |   15 
 ruoyi-admin/src/main/resources/static/ajax/libs/duallistbox/bootstrap-duallistbox.css                                         |   86 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java                                                   |  232 
 ruoyi-admin/src/main/resources/static/fonts/iconfont.woff                                                                     |    0 
 ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/diy/9.png                                    |    0 
 ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/JobInvokeUtil.java                                                           |  182 
 ruoyi-admin/src/main/resources/templates/demo/modal/table/radio.html                                                          |   86 
 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java                                                       |  118 
 ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java                                                        |  385 
 ruoyi-generator/src/main/resources/vm/html/tree.html.vm                                                                       |   51 
 ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/ConfigService.java                                              |   28 
 ruoyi-admin/src/main/resources/templates/demo/report/echarts.html                                                             | 1264 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java                                                            |   70 
 ruoyi-admin/src/main/resources/templates/demo/report/peity.html                                                               |  206 
 ruoyi-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java                                                         |   89 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/security/Md5Utils.java                                                      |   67 
 ruoyi-generator/src/main/java/com/ruoyi/generator/config/GenConfig.java                                                       |   87 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/demo/controller/DemoFormController.java                                    |  399 
 ruoyi-admin/src/main/resources/static/ajax/libs/jasny/jasny-bootstrap.min.css                                                 |    7 
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysLogininforMapper.java                                                   |   42 
 ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/web/filter/LogoutFilter.java                                          |   90 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java                                            |  219 
 ruoyi-admin/src/main/resources/static/img/user.png                                                                            |    0 
 ruoyi-admin/src/main/resources/static/ajax/libs/select2/select2.min.css                                                       |    1 
 ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/simple/img/left_menu.png                                 |    0 
 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysLogininforService.java                                                |   40 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/demo/controller/DemoReportController.java                                  |   53 
 ruoyi-admin/src/main/resources/templates/system/user/edit.html                                                                |  225 
 ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserBlockedException.java                                          |   16 
 ruoyi-admin/src/main/resources/templates/demo/modal/table/check.html                                                          |   86 
 ruoyi-admin/src/main/resources/templates/monitor/operlog/detail.html                                                          |   69 
 ruoyi-generator/src/main/resources/generator.yml                                                                              |   13 
 README.md                                                                                                                     |  101 
 ruoyi-admin/src/main/resources/static/fonts/Simple-Line-Icons.woff2                                                           |    0 
 ruoyi-admin/src/main/resources/banner.txt                                                                                     |   24 
 ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/editable/bootstrap-table-editable.js               |  189 
 ruoyi-admin/src/main/resources/templates/demo/table/curd.html                                                                 |  178 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/security/PermissionUtils.java                                               |  118 
 ruoyi-admin/src/main/resources/templates/demo/form/summernote.html                                                            |   93 
 ruoyi-common/src/main/java/com/ruoyi/common/core/text/StrFormatter.java                                                       |   92 
 ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/web/session/SpringSessionValidationScheduler.java                     |  131 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/Arith.java                                                                  |  114 
 ruoyi-admin/src/main/resources/static/ajax/libs/cxselect/jquery.cxselect.min.js                                               |   11 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/demo/controller/DemoTableController.java                                   | 1023 
 ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-fileinput/fileinput.min.css                                         |   13 
 ruoyi-admin/src/main/resources/static/ajax/libs/validate/jquery.validate.extend.js                                            |  189 
 ruoyi-admin/src/main/resources/static/fonts/iconfont.eot                                                                      |    0 
 ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/AbstractQuartzJob.java                                                       |  107 
 ruoyi-common/src/main/java/com/ruoyi/common/constant/ScheduleConstants.java                                                   |   50 
 ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/editable/clear.png                                 |    0 
 ruoyi-admin/src/main/resources/static/fonts/glyphicons-halflings-regular.ttf                                                  |    0 
 ruoyi-admin/src/main/resources/templates/system/dict/type/type.html                                                           |  148 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/IpUtils.java                                                                |  370 
 ruoyi-admin/src/main/resources/static/ajax/libs/report/sparkline/jquery.sparkline.min.js                                      |    5 
 ruoyi-admin/src/main/resources/static/fonts/fontawesome-webfont.svg                                                           | 2671 +
 ruoyi-admin/src/main/resources/static/ajax/libs/suggest/bootstrap-suggest.js                                                  | 1180 
 ruoyi-common/src/main/java/com/ruoyi/common/core/text/Convert.java                                                            | 1010 
 ruoyi-admin/src/main/resources/templates/system/user/add.html                                                                 |  259 
 ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-select/bootstrap-select.js                                          | 3247 +
 ruoyi-admin/src/main/resources/templates/monitor/cache/cache.html                                                             |  184 
 ruoyi-admin/src/main/resources/static/ajax/libs/jsonview/jquery.jsonview.css                                                  |   50 
 ruoyi-admin/src/main/resources/static/ajax/libs/iCheck/green@2x.png                                                           |    0 
 ruoyi-generator/src/main/resources/vm/html/edit.html.vm                                                                       |  416 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOperLogServiceImpl.java                                           |   77 
 ruoyi-admin/src/main/resources/static/ajax/libs/highlight/default.min.css                                                     |   79 
 ruoyi-admin/src/main/resources/templates/demo/table/groupHeader.html                                                          |   80 
 ruoyi-admin/src/main/resources/templates/demo/table/textSearch.html                                                           |  112 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java                                              |  410 
 ruoyi-admin/src/main/resources/templates/demo/form/button.html                                                                |  620 
 ruoyi-admin/src/main/resources/static/ajax/libs/layer/theme/moon/style.css                                                    |  169 
 ruoyi-quartz/src/main/resources/templates/monitor/job/detail.html                                                             |   99 
 ruoyi-admin/src/main/resources/static/css/skins.css                                                                           | 1028 
 ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/service/SysPasswordService.java                                       |   85 
 ruoyi-admin/src/main/resources/templates/system/config/edit.html                                                              |   83 
 ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/editable/bootstrap-editable.min.js                 |    7 
 ruoyi-admin/src/main/resources/templates/system/notice/edit.html                                                              |  103 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java                                                            |  676 
 ruoyi-admin/src/main/resources/templates/demo/modal/table/frame1.html                                                         |   53 
 ruoyi-framework/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java                                               |   20 
 ruoyi-system/src/main/resources/mapper/system/SysPostMapper.xml                                                               |  110 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java                                              |  324 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java                                          |  188 
 ruoyi-admin/src/main/resources/templates/system/role/add.html                                                                 |  174 
 ruoyi-framework/src/main/java/com/ruoyi/framework/config/KaptchaTextCreator.java                                              |   76 
 ruoyi-admin/src/main/resources/static/ajax/libs/iCheck/green.png                                                              |    0 
 ruoyi-admin/src/main/resources/static/fonts/zenicon.woff                                                                      |    0 
 ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordRetryLimitExceedException.java                         |   16 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java                                          |   90 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/ShiroUtils.java                                                             |   86 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java                                              |  418 
 ruoyi-common/src/main/java/com/ruoyi/common/enums/DesensitizedType.java                                                       |   59 
 ruoyi-admin/src/main/resources/static/ajax/libs/jasny/jasny-bootstrap.js                                                      |  324 
 ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-fileinput/loading-sm.gif                                            |    0 
 ruoyi-admin/src/main/resources/static/ajax/libs/flot/curvedLines.js                                                           |  315 
 ruoyi-admin/src/main/resources/static/css/style.min.css                                                                       |    1 
 ruoyi-admin/src/main/resources/templates/demo/operate/other.html                                                              |   77 
 ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java                                               |  309 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java                                                           |  216 
 ruoyi-admin/src/main/java/com/ruoyi/RuoYiServletInitializer.java                                                              |   18 
 ruoyi-admin/src/main/resources/static/js/jquery.min.js                                                                        |    2 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanUtils.java                                                         |  110 
 ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-select/bootstrap-select.css                                         |  459 
 ruoyi-quartz/pom.xml                                                                                                          |   40 
 ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/editable/loading.gif                               |    0 
 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java                                                   |  203 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/html/EscapeUtil.java                                                        |  167 
 ruoyi-admin/src/main/resources/static/ajax/libs/beautifyhtml/beautifyhtml.js                                                  |  617 
 ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java                                                         |   33 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java                                          |  113 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java                                       |   88 
 ruoyi-generator/src/main/resources/vm/java/controller.java.vm                                                                 |  203 
 ruoyi-admin/src/main/resources/static/ajax/libs/duallistbox/bootstrap-duallistbox.min.css                                     |    9 
 ruoyi-admin/src/main/resources/templates/system/dept/add.html                                                                 |  130 
 ruoyi-admin/src/main/resources/static/fonts/glyphicons-halflings-regular.woff2                                                |    0 
 ruoyi-admin/src/main/resources/static/fonts/glyphicons-halflings-regular.woff                                                 |    0 
 ruoyi-common/src/main/java/com/ruoyi/common/annotation/Anonymous.java                                                         |   19 
 ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java                                    |   55 
 sql/ruoyi.html                                                                                                                | 2890 +
 ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/web/filter/sync/SyncOnlineSessionFilter.java                          |   39 
 ruoyi-admin/src/main/resources/static/ajax/libs/flot/jquery.flot.resize.js                                                    |   60 
 ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSource.java                                           |   27 
 ruoyi-quartz/src/main/resources/templates/monitor/job/cron.html                                                               | 1172 
 ruoyi-quartz/src/main/resources/templates/monitor/job/jobLog.html                                                             |  138 
 ruoyi-admin/src/main/resources/templates/demo/table/multi.html                                                                |  224 
 ruoyi-admin/src/main/resources/templates/demo/table/reorderRows.html                                                          |   91 
 ruoyi-admin/src/main/resources/static/ajax/libs/highlight/highlight.min.js                                                    | 1102 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelHandlerAdapter.java                                                |   24 
 ruoyi-generator/src/main/resources/vm/html/add.html.vm                                                                        |  403 
 ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/diy/8.png                                    |    0 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java                                                         |  274 
 ruoyi-admin/src/main/resources/templates/system/dept/edit.html                                                                |  138 
 ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Sys.java                                                  |   84 
 ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/js/jquery.ztree.exhide-3.5.js                                |  366 
 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnline.java                                                         |  177 
 ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/auto-refresh/bootstrap-table-auto-refresh.js       |   95 
 ruoyi-admin/src/main/resources/templates/demo/table/exportSelected.html                                                       |  120 
 ruoyi-common/src/main/java/com/ruoyi/common/exception/user/BlackListException.java                                            |   16 
 ruoyi-admin/src/main/resources/static/img/login-background.jpg                                                                |    0 
 ruoyi-admin/src/main/resources/templates/demo/report/metrics.html                                                             |  478 
 ruoyi-admin/src/main/resources/static/ajax/libs/datapicker/bootstrap-datetimepicker.min.css                                   |    9 
 ruoyi-admin/src/main/resources/static/ajax/libs/summernote/font/summernote.ttf                                                |    0 
 ruoyi-admin/src/main/resources/templates/monitor/server/server.html                                                           |  258 
 ruoyi-admin/src/main/resources/static/ajax/libs/summernote/summernote.js                                                      | 10227 +++
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java                                              |  328 
 ruoyi-quartz/src/main/resources/templates/monitor/job/job.html                                                                |  198 
 ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobService.java                                                       |  102 
 ruoyi-admin/src/main/resources/static/css/login.min.css                                                                       |    1 
 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOperLog.java                                                            |  292 
 ruoyi-admin/src/main/resources/static/ajax/libs/cropper/cropper.css                                                           |  304 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java                                          |  122 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/Seq.java                                                               |   86 
 bin/clean.bat                                                                                                                 |   12 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java                                                          | 1900 
 ruoyi-admin/src/main/resources/static/css/style.css                                                                           | 7047 ++
 ruoyi-admin/src/main/resources/templates/system/dict/data/data.html                                                           |  152 
 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/Ztree.java                                                            |  104 
 ruoyi-admin/src/main/resources/static/img/loading-upload.gif                                                                  |    0 
 ruoyi-admin/src/main/resources/static/img/loading.gif                                                                         |    0 
 ruoyi-admin/src/main/resources/static/ajax/libs/iCheck/custom.css                                                             |   72 
 ruoyi-admin/src/main/resources/static/ajax/libs/jsonview/jquery.jsonview.js                                                   |  250 
 ruoyi-framework/pom.xml                                                                                                       |   82 
 ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/rememberMe/CustomCookieRememberMeManager.java                         |   79 
 ruoyi-common/src/main/java/com/ruoyi/common/exception/user/RoleBlockedException.java                                          |   16 
 ruoyi-admin/src/main/resources/static/ajax/libs/flot/jquery.flot.spline.js                                                    |  212 
 ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/print/bootstrap-table-print.js                     |  312 
 ruoyi-admin/src/main/resources/templates/system/user/authRole.html                                                            |  114 
 ruoyi-admin/src/main/resources/templates/monitor/logininfor/logininfor.html                                                   |  146 
 ruoyi-admin/src/main/resources/templates/demo/table/remember.html                                                             |   86 
 ruoyi-admin/src/main/resources/templates/demo/table/virtualScroll.html                                                        |   98 
 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java                                                      |  166 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java                                              |  568 
 ruoyi-admin/src/main/resources/templates/system/role/authUser.html                                                            |  142 
 ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzJobExecution.java                                                      |   19 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java                                              |  189 
 ruoyi-admin/src/main/resources/static/ajax/libs/select2/select2-bootstrap.min.css                                             |    7 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/SwaggerController.java                                                |   24 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/BuildController.java                                                  |   26 
 ruoyi-admin/src/main/resources/static/ajax/libs/select2/select2.min.js                                                        |    8 
 ruoyi-admin/src/main/resources/templates/demo/table/footer.html                                                               |   95 
 ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-fileinput/fileinput.min.js                                          |   11 
 ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileNameLengthLimitExceededException.java                          |   16 
 ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/js/jquery.ztree.all-3.5.js                                   | 3820 +
 ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java                                                           |  124 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/demo/domain/CustomerModel.java                                             |  116 
 ruoyi-admin/src/main/resources/templates/demo/table/child.html                                                                |  116 
 ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java                                               |   72 
 ruoyi-admin/src/main/resources/static/ajax/libs/layer/layer.min.js                                                            |    2 
 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java                                                   |  385 
 ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileSizeLimitExceededException.java                                |   16 
 ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java                                                          |  252 
 ruoyi-admin/src/main/resources/templates/system/user/deptTree.html                                                            |   51 
 ruoyi-admin/src/main/resources/static/ajax/libs/smartwizard/jquery.smartWizard.min.js                                         |   13 
 ruoyi-generator/src/main/resources/vm/html/list-tree.html.vm                                                                  |  155 
 ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/diy/7.png                                    |    0 
 ruoyi-admin/src/main/resources/static/ajax/libs/validate/additional-methods.min.js                                            |    4 
 ruoyi-admin/src/main/resources/templates/demo/table/resizable.html                                                            |   87 
 ry.bat                                                                                                                        |   67 
 ruoyi-framework/src/main/java/com/ruoyi/framework/config/FilterConfig.java                                                    |   44 
 ruoyi-admin/src/main/resources/static/js/plugins/metisMenu/jquery.metisMenu.js                                                |   10 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/security/CipherUtils.java                                                   |   36 
 ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/CronUtils.java                                                               |   94 
 ruoyi-system/src/main/resources/mapper/system/SysUserRoleMapper.xml                                                           |   48 
 ruoyi-admin/src/main/resources/templates/system/menu/edit.html                                                                |  224 
 ruoyi-admin/src/main/resources/static/js/three.min.js                                                                         |  767 
 ruoyi-admin/src/main/resources/templates/monitor/operlog/operlog.html                                                         |  188 
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysPostMapper.java                                                         |   83 
 ruoyi-admin/src/main/resources/templates/demo/table/button.html                                                               |   92 
 ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java                                                       |   73 
 ruoyi-quartz/src/main/resources/templates/monitor/job/add.html                                                                |  100 
 ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/locale/bootstrap-table-zh-CN.min.js                           |    1 
 ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/zTreeStandard.gif                            |    0 
 ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/session/OnlineSessionDAO.java                                         |  117 
 .gitignore                                                                                                                    |   46 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/demo/domain/GoodsModel.java                                                |   99 
 ruoyi-admin/src/main/resources/static/ajax/libs/flot/jquery.flot.tooltip.min.js                                               |   12 
 ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordRetryLimitCountException.java                          |   16 
 ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/DruidProperties.java                                      |   89 
 ruoyi-admin/src/main/resources/static/html/ie.html                                                                            |   46 
 ruoyi-admin/src/main/resources/static/ajax/libs/report/peity/jquery.peity.min.js                                              |   13 
 ruoyi-admin/src/main/resources/static/css/jquery.contextMenu.min.css                                                          |   15 
 ruoyi-admin/src/main/resources/templates/error/500.html                                                                       |   28 
 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOperLogService.java                                                   |   48 
 ruoyi-admin/src/main/resources/templates/demo/icon/fontawesome.html                                                           | 1054 
 ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/metro/img/line_conn.png                                  |    0 
 ruoyi-admin/src/main/resources/templates/lock.html                                                                            |  208 
 ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml                                                               |  158 
 ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/simple/img/loading.gif                                   |    0 
 ruoyi-admin/src/main/resources/templates/index.html                                                                           |  384 
 ruoyi-admin/src/main/resources/static/ajax/libs/cropper/cropper.js                                                            | 3631 +
 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java                                               |  176 
 ruoyi-admin/src/main/resources/static/js/bootstrap.min.js                                                                     |    6 
 ruoyi-admin/src/main/resources/templates/demo/form/duallistbox.html                                                           |   65 
 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java                                                      |  214 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/DruidController.java                                               |   26 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java                                              |  355 
 ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableSupport.java                                                       |   56 
 ruoyi-admin/src/main/resources/templates/demo/form/progress_bars.html                                                         |   91 
 ruoyi-common/src/main/java/com/ruoyi/common/exception/job/TaskException.java                                                  |   34 
 ruoyi-admin/src/main/resources/static/ajax/libs/cropper/cropper.min.js                                                        |   10 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/spring/SpringUtils.java                                                     |  159 
 ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJobLog.java                                                             |  155 
 ruoyi-admin/src/main/resources/mybatis/mybatis-config.xml                                                                     |   20 
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMenuMapper.java                                                     |   44 
 ruoyi-admin/src/main/resources/static/ajax/libs/layer/css/layer.css                                                           |  286 
 ruoyi-admin/src/main/resources/templates/demo/operate/detail.html                                                             |   71 
 ruoyi-admin/src/main/resources/templates/system/dict/type/edit.html                                                           |   79 
 ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/PermissionService.java                                          |  262 
 ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/metro/img/metro.png                                      |    0 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/MessageUtils.java                                                           |   26 
 ruoyi-admin/src/main/resources/application-druid.yml                                                                          |   61 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/IdUtils.java                                                           |   49 
 ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/zTreeStyle.css                                   |  102 
 ruoyi-admin/src/main/resources/templates/error/unauth.html                                                                    |   28 
 ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java                                                      |  255 
 ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/reorder-columns/bootstrap-table-reorder-columns.js |  212 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java                                            |  125 
 ruoyi-admin/src/main/resources/static/ajax/libs/cropper/cropper.min.css                                                       |    9 
 ruoyi-admin/src/main/resources/static/img/locked.png                                                                          |    0 
 ruoyi-admin/src/main/resources/templates/demo/form/select.html                                                                |  148 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/demo/domain/UserOperateModel.java                                          |  149 
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java                                                         |  117 
 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java                                               |   94 
 ruoyi-common/src/main/java/com/ruoyi/common/xss/XssFilter.java                                                                |   74 
 ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/export/tableExport.min.js                          |   92 
 ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm                                                                |  213 
 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java                                                             |  110 
 ruoyi-admin/src/main/resources/static/fonts/fontawesome-webfont.woff                                                          |    0 
 ruoyi-framework/src/main/java/com/ruoyi/framework/manager/AsyncManager.java                                                   |   55 
 ruoyi-admin/src/main/resources/static/ajax/libs/summernote/font/summernote.woff                                               |    0 
 ruoyi-admin/src/main/resources/templates/demo/form/invoice.html                                                               |  122 
 ruoyi-admin/src/main/resources/templates/main_v1.html                                                                         |  336 
 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/R.java                                                                |  114 
 ruoyi-common/src/main/java/com/ruoyi/common/enums/OperatorType.java                                                           |   24 
 ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/session/OnlineSession.java                                            |  165 
 ruoyi-admin/src/main/resources/templates/include.html                                                                         |  227 
 ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/service/SysRegisterService.java                                       |   83 
 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java                                                             |  102 
 ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/metro/img/loading.gif                                    |    0 
 ruoyi-admin/src/main/resources/templates/demo/table/print.html                                                                |  131 
 ruoyi-admin/src/main/resources/templates/system/notice/notice.html                                                            |  121 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/ExceptionUtil.java                                                          |   67 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java                                          |  260 
 ruoyi-admin/src/main/resources/templates/error/404.html                                                                       |   27 
 ruoyi-admin/src/main/resources/templates/system/user/user.html                                                                |  296 
 ruoyi-admin/src/main/resources/static/ajax/libs/summernote/summernote.min.js                                                  |    2 
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java                                                         |   84 
 ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzDisallowConcurrentExecution.java                                       |   21 
 ruoyi-common/src/main/java/com/ruoyi/common/config/serializer/SensitiveJsonSerializer.java                                    |   64 
 ruoyi-admin/src/main/resources/application.yml                                                                                |  142 
 ruoyi-admin/src/main/resources/static/i18n/messages.properties                                                                |   37 
 ruoyi-admin/src/main/resources/templates/demo/table/data.html                                                                 |   76 
 ruoyi-admin/src/main/resources/static/ajax/libs/cxselect/jquery.cxselect.js                                                   |  406 
 ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobLogService.java                                                    |   56 
 ruoyi-admin/src/main/resources/templates/demo/modal/table/frame2.html                                                         |   24 
 ruoyi-admin/src/main/resources/templates/demo/form/timeline.html                                                              |  113 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/reflect/ReflectUtils.java                                                   |  410 
 ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/SysFile.java                                              |  114 
 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysNoticeService.java                                                    |   52 
 ruoyi-admin/src/main/resources/ehcache/ehcache-shiro.xml                                                                      |   91 
 ruoyi-admin/src/main/resources/templates/tool/build/build.html                                                                |  168 
 ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/reorder-rows/bootstrap-table-reorder-rows.js       |  145 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysNoticeServiceImpl.java                                            |   82 
 ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/custom-view/bootstrap-table-custom-view.js         |  135 
 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java                                                   |  214 
 ruoyi-generator/src/main/resources/templates/tool/gen/gen.html                                                                |  219 
 ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/Server.java                                                      |  241 
 sql/ry_20240601.sql                                                                                                           |  722 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java                                                         |  291 
 ruoyi-admin/src/main/resources/templates/demo/table/pageGo.html                                                               |   77 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java                                        |   66 
 ruoyi-admin/src/main/resources/static/ajax/libs/jquery-layout/jquery.layout-latest.js                                         |    2 
 ruoyi-admin/src/main/resources/templates/demo/modal/dialog.html                                                               |  215 
 ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-fileinput/fileinput.js                                              | 6681 ++
 ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/simple/img/line_conn.gif                                 |    0 
 ruoyi-admin/src/main/resources/templates/system/role/selectUser.html                                                          |  113 
 ruoyi-admin/src/main/resources/templates/demo/table/dynamicColumns.html                                                       |  123 
 ruoyi-admin/src/main/resources/templates/demo/table/customView.html                                                           |  122 
 ruoyi-admin/src/main/resources/static/js/jquery-ui-1.10.4.min.js                                                              |   12 
 ruoyi-quartz/src/main/resources/mapper/quartz/SysJobMapper.xml                                                                |  111 
 ruoyi-admin/src/main/resources/templates/demo/form/localrefresh.html                                                          |   61 
 ruoyi-admin/src/main/resources/static/ajax/libs/datapicker/bootstrap-datetimepicker.js                                        | 1978 
 ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/web/filter/kickout/KickoutSessionFilter.java                          |  176 
 ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-fileinput/fileinput.css                                             |  688 
 ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/diy/6.png                                    |    0 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysIndexController.java                                             |  178 
 ruoyi-admin/src/main/resources/templates/demo/table/editable.html                                                             |  128 
 ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/line_conn.gif                                |    0 
 ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/resizable/jquery.resizableColumns.min.js           |    8 
 ruoyi-admin/src/main/resources/templates/demo/form/sortable.html                                                              |  198 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/PageUtils.java                                                              |   35 
 ruoyi-admin/src/main/resources/static/ajax/libs/suggest/bootstrap-suggest.min.js                                              |    9 
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysNoticeMapper.java                                                       |   52 
 ruoyi-admin/src/main/resources/templates/demo/modal/layer.html                                                                |  288 
 ruoyi-admin/src/main/resources/static/ruoyi/register.js                                                                       |   86 
 ruoyi-admin/src/main/resources/templates/system/user/profile/resetPwd.html                                                    |  105 
 ruoyi-common/src/main/java/com/ruoyi/common/enums/DataSourceType.java                                                         |   19 
 ruoyi-system/pom.xml                                                                                                          |   28 
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java                                                     |   70 
 sql/ruoyi.pdm                                                                                                                 | 4851 +
 ruoyi-system/src/main/resources/mapper/system/SysRoleDeptMapper.xml                                                           |   34 
 ruoyi-common/src/main/java/com/ruoyi/common/exception/base/BaseException.java                                                 |   97 
 ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/cookie/bootstrap-table-cookie.js                   |  606 
 ruoyi-generator/src/main/resources/vm/java/mapper.java.vm                                                                     |   91 
 ruoyi-common/src/main/java/com/ruoyi/common/annotation/Sensitive.java                                                         |   24 
 ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java                                                                  |   28 
 ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/util/AuthorizationUtils.java                                          |   30 
 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleDept.java                                                           |   46 
 ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/metro/img/line_conn.gif                                  |    0 
 ruoyi-admin/src/main/resources/templates/main.html                                                                            | 1793 
 ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/loading.gif                                  |    0 
 ruoyi-admin/src/main/resources/templates/demo/form/validate.html                                                              |  193 
 ruoyi-admin/src/main/resources/templates/demo/form/grid.html                                                                  |  432 
 ruoyi-generator/src/main/resources/templates/tool/gen/createTable.html                                                        |   30 
 ruoyi-system/src/main/resources/mapper/system/SysDictDataMapper.xml                                                           |  123 
 ruoyi-admin/src/main/resources/static/img/qr_code.png                                                                         |    0 
 ruoyi-generator/src/main/resources/templates/tool/gen/edit.html                                                               |  620 
 ruoyi-admin/src/main/resources/templates/system/dict/data/edit.html                                                           |  101 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java                                                              |  246 
 ruoyi-common/src/main/java/com/ruoyi/common/constant/PermissionConstants.java                                                 |   27 
 ruoyi-admin/src/main/resources/templates/system/dict/type/add.html                                                            |   75 
 ruoyi-admin/src/main/resources/static/img/pay.png                                                                             |    0 
 ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/simple/img/zTreeStandard.gif                             |    0 
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictTypeMapper.java                                                     |   83 
 ruoyi-admin/src/main/resources/static/ajax/libs/summernote/summernote-zh-CN.js                                                |  155 
 ruoyi-admin/src/main/resources/static/ajax/libs/typeahead/bootstrap-typeahead.js                                              |  774 
 ruoyi-framework/src/main/java/com/ruoyi/framework/config/ShiroConfig.java                                                     |  424 
 ruoyi-admin/src/main/resources/static/ajax/libs/layui/css/modules/laydate.css                                                 |    2 
 ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/web/filter/online/OnlineSessionFilter.java                            |   99 
 ruoyi-admin/src/main/resources/static/css/login.css                                                                           |  175 
 ruoyi-admin/src/main/resources/static/ajax/libs/jasny/jasny-bootstrap.css                                                     |  620 
 ruoyi-admin/src/main/resources/static/ajax/libs/datapicker/bootstrap-datetimepicker.min.js                                    |    1 
 ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserNotExistsException.java                                        |   16 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java                                            |  158 
 ruoyi-admin/src/main/resources/templates/system/config/config.html                                                            |  148 
 ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobLogMapper.java                                                       |   64 
 ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/log v3.x.txt                                                 |  170 
 ruoyi-admin/src/main/resources/static/ajax/libs/layui/modules/laydate.js                                                      |    2 
 ruoyi-admin/src/main/resources/logback.xml                                                                                    |   93 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java                                           |  181 
 ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/simple/zTreeStyle.css                                    |  118 
 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictDataService.java                                                  |   60 
 ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml                                                               |  191 
 ruoyi-admin/src/main/resources/templates/system/role/role.html                                                                |  190 
 ruoyi-admin/src/main/resources/static/css/animate.min.css                                                                     |   12 
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java                                                         |  132 
 ruoyi-admin/src/main/resources/static/ajax/libs/flot/jquery.flot.js                                                           | 2599 
 ruoyi-admin/src/main/resources/templates/system/notice/view.html                                                              |   27 
 ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java                                                             |  197 
 ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobMapper.java                                                          |   67 
 ruoyi-admin/src/main/resources/static/ruoyi/js/common.js                                                                      |  587 
 ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/diy/5.png                                    |    0 
 ruoyi-admin/src/main/resources/templates/demo/table/detail.html                                                               |   86 
 ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/diy/1_close.png                              |    0 
 ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java                                                  |   91 
 ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/js/jquery.ztree.core-3.5.js                                  | 1650 
 ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserDeleteException.java                                           |   16 
 ruoyi-common/src/main/java/com/ruoyi/common/annotation/Log.java                                                               |   50 
 ruoyi-admin/src/main/resources/static/ajax/libs/iCheck/icheck.min.js                                                          |   11 
 ruoyi-admin/src/main/resources/static/ajax/libs/smartwizard/smart_wizard_all.min.css                                          |   11 
 ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/export/bootstrap-table-export.js                   |  335 
 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java                                                  |  107 
 ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/bootstrap-table.min.js                                        |    6 
 ruoyi-common/src/main/java/com/ruoyi/common/config/thread/ThreadPoolConfig.java                                               |   63 
 ruoyi-admin/src/main/resources/static/ajax/libs/jasny/jasny-bootstrap.min.js                                                  |    6 
 ruoyi-framework/src/main/java/com/ruoyi/framework/config/MyBatisConfig.java                                                   |  132 
 ruoyi-admin/src/main/resources/templates/demo/table/reorderColumns.html                                                       |   84 
 ruoyi-system/src/main/resources/mapper/system/SysUserPostMapper.xml                                                           |   34 
 ruoyi-admin/src/main/resources/templates/demo/modal/form.html                                                                 |  102 
 ruoyi-admin/src/main/resources/templates/system/menu/add.html                                                                 |  196 
 ruoyi-admin/src/main/resources/templates/demo/form/wizard.html                                                                |  339 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/ServerController.java                                              |   31 
 ruoyi-admin/src/main/resources/templates/demo/operate/add.html                                                                |   78 
 ruoyi-admin/src/main/resources/templates/demo/table/export.html                                                               |   85 
 ruoyi-admin/src/main/resources/static/js/jquery.contextMenu.min.js                                                            |    1 
 ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableColumnMapper.java                                            |   60 
 ruoyi-admin/pom.xml                                                                                                           |  135 
 ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobController.java                                                  |  248 
 ruoyi-admin/src/main/resources/templates/login.html                                                                           |   82 
 ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableColumnService.java                                         |   44 
 ruoyi-admin/src/main/resources/static/ajax/libs/jquery-layout/jquery.layout-latest.css                                        |    1 
 ruoyi-common/src/main/java/com/ruoyi/common/xss/XssValidator.java                                                             |   39 
 ruoyi-common/pom.xml                                                                                                          |  100 
 ruoyi-framework/src/main/java/com/ruoyi/framework/manager/factory/AsyncFactory.java                                           |  136 
 ruoyi-admin/src/main/resources/templates/system/menu/icon.html                                                                |  928 
 ruoyi-admin/src/main/resources/templates/system/user/profile/profile.html                                                     |  299 
 ruoyi-admin/src/main/resources/templates/demo/report/sparkline.html                                                           |  232 
 ruoyi-admin/src/main/resources/templates/system/user/view.html                                                                |  161 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRegisterController.java                                          |   46 
 ruoyi-common/src/main/java/com/ruoyi/common/exception/UtilException.java                                                      |   26 
 ruoyi-admin/src/main/resources/static/ajax/libs/duallistbox/bootstrap-duallistbox.min.js                                      |   10 
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOperLogMapper.java                                                      |   48 
 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysPost.java                                                               |  122 
 683 files changed, 158,466 insertions(+), 2 deletions(-)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..09bdfea
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,46 @@
+######################################################################
+# 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
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..8564f29
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2018 RuoYi
+
+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/README.md b/README.md
index fede3a5..0f173b7 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,101 @@
-## sangeshenbian
+<p align="center">
+	<img alt="logo" src="https://oscimg.oschina.net/oscnet/up-dd77653d7c9f197dd9d93684f3c8dcfbab6.png">
+</p>
+<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v4.8.0</h1>
+<h4 align="center">基于SpringBoot开发的轻量级Java快速开发框架</h4>
+<p align="center">
+	<a href="https://gitee.com/y_project/RuoYi/stargazers"><img src="https://gitee.com/y_project/RuoYi/badge/star.svg?theme=gvp"></a>
+	<a href="https://gitee.com/y_project/RuoYi"><img src="https://img.shields.io/badge/RuoYi-v4.8.0-brightgreen.svg"></a>
+	<a href="https://gitee.com/y_project/RuoYi/blob/master/LICENSE"><img src="https://img.shields.io/github/license/mashape/apistatus.svg"></a>
+</p>
 
-三个身边
+## 平台简介
 
+一直想做一款后台管理系统,看了很多优秀的开源项目但是发现没有合适的。于是利用空闲休息时间开始自己写了一套后台系统。如此有了若依。她可以用于所有的Web应用程序,如网站管理后台,网站会员中心,CMS,CRM,OA。所有前端后台代码封装过后十分精简易上手,出错概率低。同时支持移动客户端访问。系统会陆续更新一些实用功能。
+
+性别男,若依是给女儿取的名字(寓意:你若不离不弃,我必生死相依)
+
+若依是一套全部开源的快速开发平台,毫无保留给个人及企业免费使用。
+
+* 前端基于 [Hplus(H+)](https://gitee.com/hplus_admin/hplus) 后台主题 UI 框架。
+* 前后端分离版本,请移步[RuoYi-Vue](https://gitee.com/y_project/RuoYi-Vue),微服务版本,请移步[RuoYi-Cloud](https://gitee.com/y_project/RuoYi-Cloud)
+* 阿里云折扣场:[点我进入](http://aly.ruoyi.vip),腾讯云秒杀场:[点我进入](http://txy.ruoyi.vip)&nbsp;&nbsp;
+
+## 内置功能
+
+1.  用户管理:用户是系统操作者,该功能主要完成系统用户配置。
+2.  部门管理:配置系统组织机构(公司、部门、小组),树结构展现支持数据权限。
+3.  岗位管理:配置系统用户所属担任职务。
+4.  菜单管理:配置系统菜单,操作权限,按钮权限标识等。
+5.  角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。
+6.  字典管理:对系统中经常使用的一些较为固定的数据进行维护。
+7.  参数管理:对系统动态配置常用参数。
+8.  通知公告:系统通知公告信息发布维护。
+9.  操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。
+10. 登录日志:系统登录日志记录查询包含登录异常。
+11. 在线用户:当前系统中活跃用户状态监控。
+12. 定时任务:在线(添加、修改、删除)任务调度包含执行结果日志。
+13. 代码生成:前后端代码的生成(java、html、xml、sql)支持CRUD下载 。
+14. 系统接口:根据业务代码自动生成相关的api接口文档。
+15. 服务监控:监视当前系统CPU、内存、磁盘、堆栈等相关信息。
+16. 缓存监控:对系统的缓存查询,删除、清空等操作。
+17. 在线构建器:拖动表单元素生成相应的HTML代码。
+18. 连接池监视:监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈。
+
+## 在线体验
+
+- admin/admin123  
+- 陆陆续续收到一些打赏,为了更好的体验已用于演示服务器升级。谢谢各位小伙伴。
+
+演示地址:http://ruoyi.vip  
+文档地址:http://doc.ruoyi.vip
+
+## 演示图
+
+<table>
+    <tr>
+        <td><img src="https://oscimg.oschina.net/oscnet/up-42e518aa72a24d228427a1261cb3679f395.png"/></td>
+        <td><img src="https://oscimg.oschina.net/oscnet/up-7f20dd0edba25e5187c5c4dd3ec7d3d9797.png"/></td>
+    </tr>
+    <tr>
+        <td><img src="https://oscimg.oschina.net/oscnet/up-2dae3d87f6a8ca05057db059cd9a411d51d.png"/></td>
+        <td><img src="https://oscimg.oschina.net/oscnet/up-ea4d98423471e55fba784694e45d12bd4bb.png"/></td>
+    </tr>
+    <tr>
+        <td><img src="https://oscimg.oschina.net/oscnet/up-7f6c6e9f5873efca09bd2870ee8468b8fce.png"/></td>
+        <td><img src="https://oscimg.oschina.net/oscnet/up-c708b65f2c382a03f69fe1efa8d341e6cff.png"/></td>
+    </tr>
+	<tr>
+        <td><img src="https://oscimg.oschina.net/oscnet/up-9ab586c47dd5c7b92bca0d727962c90e3b8.png"/></td>
+        <td><img src="https://oscimg.oschina.net/oscnet/up-ef954122a2080e02013112db21754b955c6.png"/></td>
+    </tr>	 
+    <tr>
+        <td><img src="https://oscimg.oschina.net/oscnet/up-088edb4d531e122415a1e2342bccb1a9691.png"/></td>
+        <td><img src="https://oscimg.oschina.net/oscnet/up-f886fe19bd820c0efae82f680223cac196c.png"/></td>
+    </tr>
+	<tr>
+        <td><img src="https://oscimg.oschina.net/oscnet/up-c7a2eb71fa65d6e660294b4bccca613d638.png"/></td>
+        <td><img src="https://oscimg.oschina.net/oscnet/up-e60137fb0787defe613bd83331dc4755a70.png"/></td>
+    </tr>
+	<tr>
+        <td><img src="https://oscimg.oschina.net/oscnet/up-7c51c1b5758f0a0f92ed3c60469b7526f9f.png"/></td>
+        <td><img src="https://oscimg.oschina.net/oscnet/up-15181aed45bb2461aa97b594cbf2f86ea5f.png"/></td>
+    </tr>
+	<tr>
+        <td><img src="https://oscimg.oschina.net/oscnet/up-83326ad52ea63f67233d126226738054d98.png"/></td>
+        <td><img src="https://oscimg.oschina.net/oscnet/up-3bd6d31e913b70df00107db51d64ef81df7.png"/></td>
+    </tr>
+	<tr>
+        <td><img src="https://oscimg.oschina.net/oscnet/up-70a2225836bc82042a6785edf6299e2586a.png"/></td>
+        <td><img src="https://oscimg.oschina.net/oscnet/up-0184d6ab01fdc6667a14327fcaf8b46345d.png"/></td>
+    </tr>
+	<tr>
+        <td><img src="https://oscimg.oschina.net/oscnet/up-64d8086dc2c02c8f71170290482f7640098.png"/></td>
+        <td><img src="https://oscimg.oschina.net/oscnet/up-5e4daac0bb59612c5038448acbcef235e3a.png"/></td>
+    </tr>
+</table>
+
+
+## 若依交流群
+
+QQ群: [![加入QQ群](https://img.shields.io/badge/已满-1389287-blue.svg)](https://jq.qq.com/?_wv=1027&k=5HBAaYN)  [![加入QQ群](https://img.shields.io/badge/已满-1679294-blue.svg)](https://jq.qq.com/?_wv=1027&k=5cHeRVW)  [![加入QQ群](https://img.shields.io/badge/已满-1529866-blue.svg)](https://jq.qq.com/?_wv=1027&k=53R0L5Z)  [![加入QQ群](https://img.shields.io/badge/已满-1772718-blue.svg)](https://jq.qq.com/?_wv=1027&k=5g75dCU)  [![加入QQ群](https://img.shields.io/badge/已满-1366522-blue.svg)](https://jq.qq.com/?_wv=1027&k=58cPoHA)  [![加入QQ群](https://img.shields.io/badge/已满-1382251-blue.svg)](https://jq.qq.com/?_wv=1027&k=5Ofd4Pb)  [![加入QQ群](https://img.shields.io/badge/已满-1145125-blue.svg)](https://jq.qq.com/?_wv=1027&k=5yugASz)  [![加入QQ群](https://img.shields.io/badge/已满-86752435-blue.svg)](https://jq.qq.com/?_wv=1027&k=5Rf3d2P)  [![加入QQ群](https://img.shields.io/badge/已满-134072510-blue.svg)](https://jq.qq.com/?_wv=1027&k=5ZIjaeP)  [![加入QQ群](https://img.shields.io/badge/已满-210336300-blue.svg)](https://jq.qq.com/?_wv=1027&k=5CJw1jY)  [![加入QQ群](https://img.shields.io/badge/已满-339522636-blue.svg)](https://jq.qq.com/?_wv=1027&k=5omzbKc)  [![加入QQ群](https://img.shields.io/badge/已满-130035985-blue.svg)](https://jq.qq.com/?_wv=1027&k=qPIKBb7s)  [![加入QQ群](https://img.shields.io/badge/已满-143151071-blue.svg)](https://jq.qq.com/?_wv=1027&k=4NsjKbtU)  [![加入QQ群](https://img.shields.io/badge/已满-158781320-blue.svg)](https://jq.qq.com/?_wv=1027&k=VD2pkz2G)  [![加入QQ群](https://img.shields.io/badge/已满-201531282-blue.svg)](https://jq.qq.com/?_wv=1027&k=HlshFwkJ)  [![加入QQ群](https://img.shields.io/badge/已满-101526938-blue.svg)](https://jq.qq.com/?_wv=1027&k=0ARRrO9V)  [![加入QQ群](https://img.shields.io/badge/已满-264355400-blue.svg)](https://jq.qq.com/?_wv=1027&k=up9k3ZXJ)  [![加入QQ群](https://img.shields.io/badge/已满-298522656-blue.svg)](https://jq.qq.com/?_wv=1027&k=540WfdEr)  [![加入QQ群](https://img.shields.io/badge/已满-139845794-blue.svg)](https://jq.qq.com/?_wv=1027&k=ss91fC4t)  [![加入QQ群](https://img.shields.io/badge/已满-185760789-blue.svg)](https://jq.qq.com/?_wv=1027&k=Cqd66IKe) [![加入QQ群](https://img.shields.io/badge/已满-175104288-blue.svg)](https://jq.qq.com/?_wv=1027&k=7FplYUnR) [![加入QQ群](https://img.shields.io/badge/已满-174942938-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=lqMHu_5Fskm7H2S1vNAQTtzAUokVydwc&authKey=ptw0Fpch5pbNocML3CIJKKqZBaq2DI7cusKuzIgfMNiY3t9Pvd9hP%2BA8WYx3yaY1&noverify=0&group_code=174942938) [![加入QQ群](https://img.shields.io/badge/已满-287843737-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=blYlRDmwZXSXI5pVrPPU7ZJ1stFJ6Q2Q&authKey=ForGBWffHVlPt9NE3d7g4DoOIouBh%2BqvAj2lp1CLReHfZAUaK7SRrdwsChKpRJDJ&noverify=0&group_code=287843737) [![加入QQ群](https://img.shields.io/badge/232896766-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=KTVAIhggR3rR3uZWK9A8kR4yYNREQ4jo&authKey=An4DUV9e7uK8I8VgBbp949z0ypQoDrOoqvVg%2FWOr2vuNNDMZUAMPvqHor6TFMIgz&noverify=0&group_code=232896766)
\ 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..41efbd0
--- /dev/null
+++ b/bin/run.bat
@@ -0,0 +1,14 @@
+@echo off
+echo.
+echo [��Ϣ] ʹ��Jar��������Web���̡�
+echo.
+
+cd %~dp0
+cd ../ruoyi-admin/target
+
+set JAVA_OPTS=-Xms256m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m
+
+java -jar %JAVA_OPTS% ruoyi-admin.jar
+
+cd bin
+pause
\ No newline at end of file
diff --git "a/doc/\350\213\245\344\276\235\347\216\257\345\242\203\344\275\277\347\224\250\346\211\213\345\206\214.docx" "b/doc/\350\213\245\344\276\235\347\216\257\345\242\203\344\275\277\347\224\250\346\211\213\345\206\214.docx"
new file mode 100644
index 0000000..fa5b62d
--- /dev/null
+++ "b/doc/\350\213\245\344\276\235\347\216\257\345\242\203\344\275\277\347\224\250\346\211\213\345\206\214.docx"
Binary files differ
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..b2b651d
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,290 @@
+<?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.ruoyi</groupId>
+    <artifactId>ruoyi</artifactId>
+    <version>4.8.0</version>
+
+    <name>ruoyi</name>
+    <url>http://www.ruoyi.vip</url>
+    <description>若依管理系统</description>
+    
+    <properties>
+        <ruoyi.version>4.8.0</ruoyi.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>
+        <spring-boot.version>2.5.15</spring-boot.version>
+        <shiro.version>1.13.0</shiro.version>
+        <thymeleaf.extras.shiro.version>2.1.0</thymeleaf.extras.shiro.version>
+        <druid.version>1.2.23</druid.version>
+        <bitwalker.version>1.21</bitwalker.version>
+        <kaptcha.version>2.3.3</kaptcha.version>
+        <swagger.version>3.0.0</swagger.version>
+        <pagehelper.boot.version>1.4.7</pagehelper.boot.version>
+        <fastjson.version>1.2.83</fastjson.version>
+        <oshi.version>6.6.5</oshi.version>
+        <commons.io.version>2.16.1</commons.io.version>
+        <poi.version>4.1.2</poi.version>
+        <velocity.version>2.3</velocity.version>
+        <!-- override dependency version -->
+        <tomcat.version>9.0.96</tomcat.version>
+        <logback.version>1.2.13</logback.version>
+        <spring-framework.version>5.3.39</spring-framework.version>
+    </properties>
+
+    <!-- 依赖声明 -->
+    <dependencyManagement>
+        <dependencies>
+
+            <!-- 覆盖SpringFramework的依赖配置-->
+            <dependency>
+                <groupId>org.springframework</groupId>
+                <artifactId>spring-framework-bom</artifactId>
+                <version>${spring-framework.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+
+            <!-- SpringBoot的依赖配置-->
+            <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-dependencies</artifactId>
+                <version>${spring-boot.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+
+            <!-- 覆盖logback的依赖配置-->
+            <dependency>
+                <groupId>ch.qos.logback</groupId>
+                <artifactId>logback-core</artifactId>
+                <version>${logback.version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>ch.qos.logback</groupId>
+                <artifactId>logback-classic</artifactId>
+                <version>${logback.version}</version>
+            </dependency>
+
+            <!-- 覆盖tomcat的依赖配置-->
+            <dependency>
+                <groupId>org.apache.tomcat.embed</groupId>
+                <artifactId>tomcat-embed-core</artifactId>
+                <version>${tomcat.version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>org.apache.tomcat.embed</groupId>
+                <artifactId>tomcat-embed-el</artifactId>
+                <version>${tomcat.version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>org.apache.tomcat.embed</groupId>
+                <artifactId>tomcat-embed-websocket</artifactId>
+                <version>${tomcat.version}</version>
+            </dependency>
+
+            <!-- 阿里数据库连接池 -->
+            <dependency>
+                <groupId>com.alibaba</groupId>
+                <artifactId>druid-spring-boot-starter</artifactId>
+                <version>${druid.version}</version>
+            </dependency>
+            
+            <!-- 验证码 -->
+            <dependency>
+                <groupId>pro.fessional</groupId>
+                <artifactId>kaptcha</artifactId>
+                <version>${kaptcha.version}</version>
+            </dependency>
+
+            <!-- Shiro核心框架 -->
+            <dependency>
+                <groupId>org.apache.shiro</groupId>
+                <artifactId>shiro-core</artifactId>
+                <version>${shiro.version}</version>
+            </dependency>
+
+            <!-- Shiro使用Spring框架 -->
+            <dependency>
+                <groupId>org.apache.shiro</groupId>
+                <artifactId>shiro-spring</artifactId>
+                <version>${shiro.version}</version>
+            </dependency>
+
+            <!-- Shiro使用EhCache缓存框架 -->
+            <dependency>
+                <groupId>org.apache.shiro</groupId>
+                <artifactId>shiro-ehcache</artifactId>
+                <version>${shiro.version}</version>
+            </dependency>
+
+            <!-- thymeleaf模板引擎和shiro框架的整合 -->
+            <dependency>
+                <groupId>com.github.theborakompanioni</groupId>
+                <artifactId>thymeleaf-extras-shiro</artifactId>
+                <version>${thymeleaf.extras.shiro.version}</version>
+            </dependency>
+
+            <!-- 解析客户端操作系统、浏览器等 -->
+            <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代码生成使用模板 -->
+            <dependency>
+                <groupId>org.apache.velocity</groupId>
+                <artifactId>velocity-engine-core</artifactId>
+                <version>${velocity.version}</version>
+            </dependency>
+
+            <!-- 阿里JSON解析器 -->
+            <dependency>
+                <groupId>com.alibaba</groupId>
+                <artifactId>fastjson</artifactId>
+                <version>${fastjson.version}</version>
+            </dependency>
+
+            <!-- 定时任务-->
+            <dependency>
+                <groupId>com.ruoyi</groupId>
+                <artifactId>ruoyi-quartz</artifactId>
+                <version>${ruoyi.version}</version>
+            </dependency>
+
+            <!-- 代码生成-->
+            <dependency>
+                <groupId>com.ruoyi</groupId>
+                <artifactId>ruoyi-generator</artifactId>
+                <version>${ruoyi.version}</version>
+            </dependency>
+
+            <!-- 核心模块-->
+            <dependency>
+                <groupId>com.ruoyi</groupId>
+                <artifactId>ruoyi-framework</artifactId>
+                <version>${ruoyi.version}</version>
+            </dependency>
+
+            <!-- 系统模块-->
+            <dependency>
+                <groupId>com.ruoyi</groupId>
+                <artifactId>ruoyi-system</artifactId>
+                <version>${ruoyi.version}</version>
+            </dependency>
+
+            <!-- 通用工具-->
+            <dependency>
+                <groupId>com.ruoyi</groupId>
+                <artifactId>ruoyi-common</artifactId>
+                <version>${ruoyi.version}</version>
+            </dependency>
+
+        </dependencies>
+    </dependencyManagement>
+
+    <modules>
+        <module>ruoyi-admin</module>
+        <module>ruoyi-framework</module>
+        <module>ruoyi-system</module>
+        <module>ruoyi-quartz</module>
+        <module>ruoyi-generator</module>
+        <module>ruoyi-common</module>
+    </modules>
+    <packaging>pom</packaging>
+
+
+    <dependencies>
+
+    </dependencies>
+
+    <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/ruoyi-admin/pom.xml b/ruoyi-admin/pom.xml
new file mode 100644
index 0000000..f1cc343
--- /dev/null
+++ b/ruoyi-admin/pom.xml
@@ -0,0 +1,135 @@
+<?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>ruoyi</artifactId>
+        <groupId>com.ruoyi</groupId>
+        <version>4.8.0</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <packaging>jar</packaging>
+    <artifactId>ruoyi-admin</artifactId>
+
+    <description>
+        web服务入口
+    </description>
+
+    <dependencies>
+
+        <!-- SpringBoot集成thymeleaf模板 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-thymeleaf</artifactId>
+        </dependency>
+
+        <!-- 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>
+
+        <!-- 核心模块-->
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-framework</artifactId>
+        </dependency>
+
+        <!-- 定时任务-->
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-quartz</artifactId>
+        </dependency>
+
+        <!-- 代码生成-->
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-generator</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.0.0</version>   
+                <configuration>
+                    <failOnMissingWebXml>false</failOnMissingWebXml>
+                    <warName>${project.artifactId}</warName>
+                </configuration>   
+            </plugin>   
+            <!-- YUI Compressor (CSS/JS压缩) 
+            <plugin>
+                <groupId>net.alchim31.maven</groupId>
+                <artifactId>yuicompressor-maven-plugin</artifactId>
+                <version>1.5.1</version>
+                <executions>
+                    <execution>
+                        <phase>prepare-package</phase>
+                        <goals>
+                            <goal>compress</goal>
+                        </goals>
+                    </execution>
+                </executions>
+                <configuration>
+                    <encoding>UTF-8</encoding>
+                    <jswarn>false</jswarn>
+                    <nosuffix>true</nosuffix>
+                    <linebreakpos>50000</linebreakpos>
+                    <sourceDirectory>src/main/resources/static</sourceDirectory>
+                    <force>true</force>
+                    <includes>
+                        <include>**/*.js</include>
+                        <include>**/*.css</include>
+                    </includes>
+                    <excludes>
+                        <exclude>**/*.min.js</exclude>
+                        <exclude>**/*.min.css</exclude>
+                        <exclude>**/fileinput.js</exclude>
+                        <exclude>**/validate/**</exclude>
+                        <exclude>**/bootstrap-table/**</exclude>
+                    </excludes>
+                </configuration>
+            </plugin> -->
+        </plugins>
+        <finalName>${project.artifactId}</finalName>
+    </build>
+
+</project>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java b/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java
new file mode 100644
index 0000000..0e890c1
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java
@@ -0,0 +1,30 @@
+package com.ruoyi;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+
+/**
+ * 启动程序
+ * 
+ * @author ruoyi
+ */
+@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
+public class RuoYiApplication
+{
+    public static void main(String[] args)
+    {
+        // System.setProperty("spring.devtools.restart.enabled", "false");
+        SpringApplication.run(RuoYiApplication.class, args);
+        System.out.println("(♥◠‿◠)ノ゙  若依启动成功   ლ(´ڡ`ლ)゙  \n" +
+                " .-------.       ____     __        \n" +
+                " |  _ _   \\      \\   \\   /  /    \n" +
+                " | ( ' )  |       \\  _. /  '       \n" +
+                " |(_ o _) /        _( )_ .'         \n" +
+                " | (_,_).' __  ___(_ o _)'          \n" +
+                " |  |\\ \\  |  ||   |(_,_)'         \n" +
+                " |  | \\ `'   /|   `-'  /           \n" +
+                " |  |  \\    /  \\      /           \n" +
+                " ''-'   `'-'    `-..-'              ");
+    }
+}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/RuoYiServletInitializer.java b/ruoyi-admin/src/main/java/com/ruoyi/RuoYiServletInitializer.java
new file mode 100644
index 0000000..6de67dc
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/RuoYiServletInitializer.java
@@ -0,0 +1,18 @@
+package com.ruoyi;
+
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
+
+/**
+ * web容器中进行部署
+ * 
+ * @author ruoyi
+ */
+public class RuoYiServletInitializer extends SpringBootServletInitializer
+{
+    @Override
+    protected SpringApplicationBuilder configure(SpringApplicationBuilder application)
+    {
+        return application.sources(RuoYiApplication.class);
+    }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java
new file mode 100644
index 0000000..ff7bac1
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java
@@ -0,0 +1,165 @@
+package com.ruoyi.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.stereotype.Controller;
+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.ResponseBody;
+import org.springframework.web.multipart.MultipartFile;
+import com.ruoyi.common.config.RuoYiConfig;
+import com.ruoyi.common.config.ServerConfig;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.file.FileUploadUtils;
+import com.ruoyi.common.utils.file.FileUtils;
+
+/**
+ * 通用请求处理
+ * 
+ * @author ruoyi
+ */
+@Controller
+@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 = RuoYiConfig.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")
+    @ResponseBody
+    public AjaxResult uploadFile(MultipartFile file) throws Exception
+    {
+        try
+        {
+            // 上传文件路径
+            String filePath = RuoYiConfig.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")
+    @ResponseBody
+    public AjaxResult uploadFiles(List<MultipartFile> files) throws Exception
+    {
+        try
+        {
+            // 上传文件路径
+            String filePath = RuoYiConfig.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 = RuoYiConfig.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/ruoyi-admin/src/main/java/com/ruoyi/web/controller/demo/controller/DemoDialogController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/demo/controller/DemoDialogController.java
new file mode 100644
index 0000000..3030057
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/demo/controller/DemoDialogController.java
@@ -0,0 +1,98 @@
+package com.ruoyi.web.controller.demo.controller;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+/**
+ * 模态窗口
+ * 
+ * @author ruoyi
+ */
+@Controller
+@RequestMapping("/demo/modal")
+public class DemoDialogController
+{
+    private String prefix = "demo/modal";
+
+    /**
+     * 模态窗口
+     */
+    @GetMapping("/dialog")
+    public String dialog()
+    {
+        return prefix + "/dialog";
+    }
+
+    /**
+     * 弹层组件
+     */
+    @GetMapping("/layer")
+    public String layer()
+    {
+        return prefix + "/layer";
+    }
+
+    /**
+     * 表单
+     */
+    @GetMapping("/form")
+    public String form()
+    {
+        return prefix + "/form";
+    }
+
+    /**
+     * 表格
+     */
+    @GetMapping("/table")
+    public String table()
+    {
+        return prefix + "/table";
+    }
+
+    /**
+     * 表格check
+     */
+    @GetMapping("/check")
+    public String check()
+    {
+        return prefix + "/table/check";
+    }
+
+    /**
+     * 表格radio
+     */
+    @GetMapping("/radio")
+    public String radio()
+    {
+        return prefix + "/table/radio";
+    }
+
+    /**
+     * 表格回传父窗体
+     */
+    @GetMapping("/parent")
+    public String parent()
+    {
+        return prefix + "/table/parent";
+    }
+
+    /**
+     * 多层窗口frame1
+     */
+    @GetMapping("/frame1")
+    public String frame1()
+    {
+        return prefix + "/table/frame1";
+    }
+
+    /**
+     * 多层窗口frame2
+     */
+    @GetMapping("/frame2")
+    public String frame2()
+    {
+        return prefix + "/table/frame2";
+    }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/demo/controller/DemoFormController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/demo/controller/DemoFormController.java
new file mode 100644
index 0000000..7cc6faa
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/demo/controller/DemoFormController.java
@@ -0,0 +1,399 @@
+package com.ruoyi.web.controller.demo.controller;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+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.ResponseBody;
+import com.alibaba.fastjson.JSON;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.CxSelect;
+import com.ruoyi.common.json.JSONObject;
+import com.ruoyi.common.json.JSONObject.JSONArray;
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * 表单相关
+ * 
+ * @author ruoyi
+ */
+@Controller
+@RequestMapping("/demo/form")
+public class DemoFormController
+{
+    private String prefix = "demo/form";
+
+    private final static List<UserFormModel> users = new ArrayList<UserFormModel>();
+    {
+        users.add(new UserFormModel(1, "1000001", "测试1", "15888888888"));
+        users.add(new UserFormModel(2, "1000002", "测试2", "15666666666"));
+        users.add(new UserFormModel(3, "1000003", "测试3", "15666666666"));
+        users.add(new UserFormModel(4, "1000004", "测试4", "15666666666"));
+        users.add(new UserFormModel(5, "1000005", "测试5", "15666666666"));
+    }
+
+    /**
+     * 按钮页
+     */
+    @GetMapping("/button")
+    public String button()
+    {
+        return prefix + "/button";
+    }
+
+    /**
+     * 下拉框
+     */
+    @GetMapping("/select")
+    public String select()
+    {
+        return prefix + "/select";
+    }
+
+    /**
+     * 时间轴
+     */
+    @GetMapping("/timeline")
+    public String timeline()
+    {
+        return prefix + "/timeline";
+    }
+
+    /**
+     * 进度条
+     */
+    @GetMapping("/progress_bars")
+    public String progress_bars()
+    {
+        return prefix + "/progress_bars";
+    }
+
+    /**
+     * 表单校验
+     */
+    @GetMapping("/validate")
+    public String validate()
+    {
+        return prefix + "/validate";
+    }
+
+    /**
+     * 功能扩展(包含文件上传)
+     */
+    @GetMapping("/jasny")
+    public String jasny()
+    {
+        return prefix + "/jasny";
+    }
+
+    /**
+     * 拖动排序
+     */
+    @GetMapping("/sortable")
+    public String sortable()
+    {
+        return prefix + "/sortable";
+    }
+
+    /**
+     * 单据打印
+     */
+    @GetMapping("/invoice")
+    public String invoice()
+    {
+        return prefix + "/invoice";
+    }
+
+    /**
+     * 标签 & 提示
+     */
+    @GetMapping("/labels_tips")
+    public String labels_tips()
+    {
+        return prefix + "/labels_tips";
+    }
+
+    /**
+     * 选项卡 & 面板
+     */
+    @GetMapping("/tabs_panels")
+    public String tabs_panels()
+    {
+        return prefix + "/tabs_panels";
+    }
+
+    /**
+     * 栅格
+     */
+    @GetMapping("/grid")
+    public String grid()
+    {
+        return prefix + "/grid";
+    }
+
+    /**
+     * 表单向导
+     */
+    @GetMapping("/wizard")
+    public String wizard()
+    {
+        return prefix + "/wizard";
+    }
+
+    /**
+     * 文件上传
+     */
+    @GetMapping("/upload")
+    public String upload()
+    {
+        return prefix + "/upload";
+    }
+
+    /**
+     * 日期和时间页
+     */
+    @GetMapping("/datetime")
+    public String datetime()
+    {
+        return prefix + "/datetime";
+    }
+
+    /**
+     * 左右互选组件
+     */
+    @GetMapping("/duallistbox")
+    public String duallistbox()
+    {
+        return prefix + "/duallistbox";
+    }
+
+    /**
+     * 基本表单
+     */
+    @GetMapping("/basic")
+    public String basic()
+    {
+        return prefix + "/basic";
+    }
+
+    /**
+     * 卡片列表
+     */
+    @GetMapping("/cards")
+    public String cards()
+    {
+        return prefix + "/cards";
+    }
+
+    /**
+     * summernote 富文本编辑器
+     */
+    @GetMapping("/summernote")
+    public String summernote()
+    {
+        return prefix + "/summernote";
+    }
+
+    /**
+     * 搜索自动补全
+     */
+    @GetMapping("/autocomplete")
+    public String autocomplete()
+    {
+        return prefix + "/autocomplete";
+    }
+
+    /**
+     * 多级联动下拉
+     */
+    @GetMapping("/cxselect")
+    public String cxselect(ModelMap mmap)
+    {
+        CxSelect cxSelectTB = new CxSelect();
+        cxSelectTB.setN("淘宝");
+        cxSelectTB.setV("taobao");
+        CxSelect cxSelectTm = new CxSelect();
+        cxSelectTm.setN("天猫");
+        cxSelectTm.setV("tm");
+        CxSelect cxSelectJhs = new CxSelect();
+        cxSelectJhs.setN("聚划算");
+        cxSelectJhs.setV("jhs");
+        List<CxSelect> tmList = new ArrayList<CxSelect>();
+        tmList.add(cxSelectTm);
+        tmList.add(cxSelectJhs);
+        cxSelectTB.setS(tmList);
+
+        CxSelect cxSelectJD = new CxSelect();
+        cxSelectJD.setN("京东");
+        cxSelectJD.setV("jd");
+        CxSelect cxSelectCs = new CxSelect();
+        cxSelectCs.setN("京东超市");
+        cxSelectCs.setV("jdcs");
+        CxSelect cxSelectSx = new CxSelect();
+        cxSelectSx.setN("京东生鲜");
+        cxSelectSx.setV("jdsx");
+        List<CxSelect> jdList = new ArrayList<CxSelect>();
+        jdList.add(cxSelectCs);
+        jdList.add(cxSelectSx);
+        cxSelectJD.setS(jdList);
+
+        List<CxSelect> cxList = new ArrayList<CxSelect>();
+        cxList.add(cxSelectTB);
+        cxList.add(cxSelectJD);
+
+        mmap.put("data", JSON.toJSON(cxList));
+        return prefix + "/cxselect";
+    }
+
+    /**
+     * 局部刷新
+     */
+    @GetMapping("/localrefresh")
+    public String localRefresh(ModelMap mmap)
+    {
+        JSONArray list = new JSONArray();
+        JSONObject item = new JSONObject();
+        item.put("name", "这条任务数据是由ModelMap传递到页面的,点击添加按钮后会将这条数据替换为新数据");
+        item.put("type", "默认");
+        item.put("date", "2020.06.10");
+        list.add(item);
+        mmap.put("tasks", list);
+        mmap.put("min", 2);
+        mmap.put("max", 10);
+        return prefix + "/localrefresh";
+    }
+
+    /**
+     * 局部刷新-添加任务
+     * 
+     * @param fragment 页面中的模板名称
+     * @param taskName 任务名称
+     */
+    @PostMapping("/localrefresh/task")
+    public String localRefreshTask(String fragment, String taskName, ModelMap mmap)
+    {
+        JSONArray list = new JSONArray();
+        JSONObject item = new JSONObject();
+        item.put("name", StringUtils.defaultIfBlank(taskName, "通过电话销售过程中了解各盛市的设备仪器使用、采购情况及相关重要追踪人"));
+        item.put("type", "新增");
+        item.put("date", "2018.06.10");
+        list.add(item);
+        item = new JSONObject();
+        item.put("name", "提高自己电话营销技巧,灵活专业地与客户进行电话交流");
+        item.put("type", "新增");
+        item.put("date", "2018.06.12");
+        list.add(item);
+        mmap.put("tasks", list);
+        return prefix + "/localrefresh::" + fragment;
+    }
+
+    /**
+     * 模拟数据
+     */
+    @GetMapping("/cityData")
+    @ResponseBody
+    public String cityData()
+    {
+        String data = "[{\"n\":\"湖南省\",\"s\":[{\"n\":\"长沙市\",\"s\":[{\"n\":\"芙蓉区\"},{\"n\":\"天心区\"},{\"n\":\"岳麓区\"},{\"n\":\"开福区\"},{\"n\":\"雨花区\"},{\"n\":\"望城区\"},{\"n\":\"长沙县\"},{\"n\":\"宁乡县\"},{\"n\":\"浏阳市\"}]},{\"n\":\"株洲市\",\"s\":[{\"n\":\"荷塘区\"},{\"n\":\"芦淞区\"},{\"n\":\"石峰区\"},{\"n\":\"天元区\"},{\"n\":\"株洲县\"},{\"n\":\"攸县\"},{\"n\":\"茶陵县\"},{\"n\":\"炎陵县\"},{\"n\":\"醴陵市\"}]},{\"n\":\"湘潭市\",\"s\":[{\"n\":\"雨湖区\"},{\"n\":\"岳塘区\"},{\"n\":\"湘潭县\"},{\"n\":\"湘乡市\"},{\"n\":\"韶山市\"}]},{\"n\":\"衡阳市\",\"s\":[{\"n\":\"珠晖区\"},{\"n\":\"雁峰区\"},{\"n\":\"石鼓区\"},{\"n\":\"蒸湘区\"},{\"n\":\"南岳区\"},{\"n\":\"衡阳县\"},{\"n\":\"衡南县\"},{\"n\":\"衡山县\"},{\"n\":\"衡东县\"},{\"n\":\"祁东县\"},{\"n\":\"耒阳市\"},{\"n\":\"常宁市\"}]},{\"n\":\"邵阳市\",\"s\":[{\"n\":\"双清区\"},{\"n\":\"大祥区\"},{\"n\":\"北塔区\"},{\"n\":\"邵东县\"},{\"n\":\"新邵县\"},{\"n\":\"邵阳县\"},{\"n\":\"隆回县\"},{\"n\":\"洞口县\"},{\"n\":\"绥宁县\"},{\"n\":\"新宁县\"},{\"n\":\"城步苗族自治县\"},{\"n\":\"武冈市\"}]},{\"n\":\"岳阳市\",\"s\":[{\"n\":\"岳阳楼区\"},{\"n\":\"云溪区\"},{\"n\":\"君山区\"},{\"n\":\"岳阳县\"},{\"n\":\"华容县\"},{\"n\":\"湘阴县\"},{\"n\":\"平江县\"},{\"n\":\"汨罗市\"},{\"n\":\"临湘市\"}]},{\"n\":\"常德市\",\"s\":[{\"n\":\"武陵区\"},{\"n\":\"鼎城区\"},{\"n\":\"安乡县\"},{\"n\":\"汉寿县\"},{\"n\":\"澧县\"},{\"n\":\"临澧县\"},{\"n\":\"桃源县\"},{\"n\":\"石门县\"},{\"n\":\"津市市\"}]},{\"n\":\"张家界市\",\"s\":[{\"n\":\"永定区\"},{\"n\":\"武陵源区\"},{\"n\":\"慈利县\"},{\"n\":\"桑植县\"}]},{\"n\":\"益阳市\",\"s\":[{\"n\":\"资阳区\"},{\"n\":\"赫山区\"},{\"n\":\"南县\"},{\"n\":\"桃江县\"},{\"n\":\"安化县\"},{\"n\":\"沅江市\"}]},{\"n\":\"郴州市\",\"s\":[{\"n\":\"北湖区\"},{\"n\":\"苏仙区\"},{\"n\":\"桂阳县\"},{\"n\":\"宜章县\"},{\"n\":\"永兴县\"},{\"n\":\"嘉禾县\"},{\"n\":\"临武县\"},{\"n\":\"汝城县\"},{\"n\":\"桂东县\"},{\"n\":\"安仁县\"},{\"n\":\"资兴市\"}]},{\"n\":\"永州市\",\"s\":[{\"n\":\"零陵区\"},{\"n\":\"冷水滩区\"},{\"n\":\"祁阳县\"},{\"n\":\"东安县\"},{\"n\":\"双牌县\"},{\"n\":\"道县\"},{\"n\":\"江永县\"},{\"n\":\"宁远县\"},{\"n\":\"蓝山县\"},{\"n\":\"新田县\"},{\"n\":\"江华瑶族自治县\"}]},{\"n\":\"怀化市\",\"s\":[{\"n\":\"鹤城区\"},{\"n\":\"中方县\"},{\"n\":\"沅陵县\"},{\"n\":\"辰溪县\"},{\"n\":\"溆浦县\"},{\"n\":\"会同县\"},{\"n\":\"麻阳苗族自治县\"},{\"n\":\"新晃侗族自治县\"},{\"n\":\"芷江侗族自治县\"},{\"n\":\"靖州苗族侗族自治县\"},{\"n\":\"通道侗族自治县\"},{\"n\":\"洪江市\"}]},{\"n\":\"娄底市\",\"s\":[{\"n\":\"娄星区\"},{\"n\":\"双峰县\"},{\"n\":\"新化县\"},{\"n\":\"冷水江市\"},{\"n\":\"涟源市\"}]},{\"n\":\"湘西土家族苗族自治州\",\"s\":[{\"n\":\"吉首市\"},{\"n\":\"泸溪县\"},{\"n\":\"凤凰县\"},{\"n\":\"花垣县\"},{\"n\":\"保靖县\"},{\"n\":\"古丈县\"},{\"n\":\"永顺县\"},{\"n\":\"龙山县\"}]}]},{\"n\":\"广东省\",\"s\":[{\"n\":\"广州市\",\"s\":[{\"n\":\"荔湾区\"},{\"n\":\"越秀区\"},{\"n\":\"海珠区\"},{\"n\":\"天河区\"},{\"n\":\"白云区\"},{\"n\":\"黄埔区\"},{\"n\":\"番禺区\"},{\"n\":\"花都区\"},{\"n\":\"南沙区\"},{\"n\":\"萝岗区\"},{\"n\":\"增城市\"},{\"n\":\"从化市\"}]},{\"n\":\"韶关市\",\"s\":[{\"n\":\"武江区\"},{\"n\":\"浈江区\"},{\"n\":\"曲江区\"},{\"n\":\"始兴县\"},{\"n\":\"仁化县\"},{\"n\":\"翁源县\"},{\"n\":\"乳源瑶族自治县\"},{\"n\":\"新丰县\"},{\"n\":\"乐昌市\"},{\"n\":\"南雄市\"}]},{\"n\":\"深圳市\",\"s\":[{\"n\":\"罗湖区\"},{\"n\":\"福田区\"},{\"n\":\"南山区\"},{\"n\":\"宝安区\"},{\"n\":\"龙岗区\"},{\"n\":\"盐田区\"}]},{\"n\":\"珠海市\",\"s\":[{\"n\":\"香洲区\"},{\"n\":\"斗门区\"},{\"n\":\"金湾区\"}]},{\"n\":\"汕头市\",\"s\":[{\"n\":\"龙湖区\"},{\"n\":\"金平区\"},{\"n\":\"濠江区\"},{\"n\":\"潮阳区\"},{\"n\":\"潮南区\"},{\"n\":\"澄海区\"},{\"n\":\"南澳县\"}]},{\"n\":\"佛山市\",\"s\":[{\"n\":\"禅城区\"},{\"n\":\"南海区\"},{\"n\":\"顺德区\"},{\"n\":\"三水区\"},{\"n\":\"高明区\"}]},{\"n\":\"江门市\",\"s\":[{\"n\":\"蓬江区\"},{\"n\":\"江海区\"},{\"n\":\"新会区\"},{\"n\":\"台山市\"},{\"n\":\"开平市\"},{\"n\":\"鹤山市\"},{\"n\":\"恩平市\"}]},{\"n\":\"湛江市\",\"s\":[{\"n\":\"赤坎区\"},{\"n\":\"霞山区\"},{\"n\":\"坡头区\"},{\"n\":\"麻章区\"},{\"n\":\"遂溪县\"},{\"n\":\"徐闻县\"},{\"n\":\"廉江市\"},{\"n\":\"雷州市\"},{\"n\":\"吴川市\"}]},{\"n\":\"茂名市\",\"s\":[{\"n\":\"茂南区\"},{\"n\":\"茂港区\"},{\"n\":\"电白县\"},{\"n\":\"高州市\"},{\"n\":\"化州市\"},{\"n\":\"信宜市\"}]},{\"n\":\"肇庆市\",\"s\":[{\"n\":\"端州区\"},{\"n\":\"鼎湖区\"},{\"n\":\"广宁县\"},{\"n\":\"怀集县\"},{\"n\":\"封开县\"},{\"n\":\"德庆县\"},{\"n\":\"高要市\"},{\"n\":\"四会市\"}]},{\"n\":\"惠州市\",\"s\":[{\"n\":\"惠城区\"},{\"n\":\"惠阳区\"},{\"n\":\"博罗县\"},{\"n\":\"惠东县\"},{\"n\":\"龙门县\"}]},{\"n\":\"梅州市\",\"s\":[{\"n\":\"梅江区\"},{\"n\":\"梅县\"},{\"n\":\"大埔县\"},{\"n\":\"丰顺县\"},{\"n\":\"五华县\"},{\"n\":\"平远县\"},{\"n\":\"蕉岭县\"},{\"n\":\"兴宁市\"}]},{\"n\":\"汕尾市\",\"s\":[{\"n\":\"城区\"},{\"n\":\"海丰县\"},{\"n\":\"陆河县\"},{\"n\":\"陆丰市\"}]},{\"n\":\"河源市\",\"s\":[{\"n\":\"源城区\"},{\"n\":\"紫金县\"},{\"n\":\"龙川县\"},{\"n\":\"连平县\"},{\"n\":\"和平县\"},{\"n\":\"东源县\"}]},{\"n\":\"阳江市\",\"s\":[{\"n\":\"江城区\"},{\"n\":\"阳西县\"},{\"n\":\"阳东县\"},{\"n\":\"阳春市\"}]},{\"n\":\"清远市\",\"s\":[{\"n\":\"清城区\"},{\"n\":\"清新区\"},{\"n\":\"佛冈县\"},{\"n\":\"阳山县\"},{\"n\":\"连山壮族瑶族自治县\"},{\"n\":\"连南瑶族自治县\"},{\"n\":\"英德市\"},{\"n\":\"连州市\"}]},{\"n\":\"东莞市\"},{\"n\":\"中山市\"},{\"n\":\"潮州市\",\"s\":[{\"n\":\"湘桥区\"},{\"n\":\"潮安区\"},{\"n\":\"饶平县\"}]},{\"n\":\"揭阳市\",\"s\":[{\"n\":\"榕城区\"},{\"n\":\"揭东区\"},{\"n\":\"揭西县\"},{\"n\":\"惠来县\"},{\"n\":\"普宁市\"}]},{\"n\":\"云浮市\",\"s\":[{\"n\":\"云城区\"},{\"n\":\"新兴县\"},{\"n\":\"郁南县\"},{\"n\":\"云安县\"},{\"n\":\"罗定市\"}]}]}]";
+        return data;
+    }
+
+    /**
+     * 获取用户数据
+     */
+    @GetMapping("/userModel")
+    @ResponseBody
+    public AjaxResult userModel()
+    {
+        AjaxResult ajax = new AjaxResult();
+
+        ajax.put("code", 200);
+        ajax.put("value", users);
+        return ajax;
+    }
+
+    /**
+     * 获取数据集合
+     */
+    @GetMapping("/collection")
+    @ResponseBody
+    public AjaxResult collection()
+    {
+        String[] array = { "ruoyi 1", "ruoyi 2", "ruoyi 3", "ruoyi 4", "ruoyi 5" };
+        AjaxResult ajax = new AjaxResult();
+        ajax.put("value", array);
+        return ajax;
+    }
+}
+
+class UserFormModel
+{
+    /** 用户ID */
+    private int userId;
+
+    /** 用户编号 */
+    private String userCode;
+
+    /** 用户姓名 */
+    private String userName;
+
+    /** 用户手机 */
+    private String userPhone;
+
+    public UserFormModel()
+    {
+
+    }
+
+    public UserFormModel(int userId, String userCode, String userName, String userPhone)
+    {
+        this.userId = userId;
+        this.userCode = userCode;
+        this.userName = userName;
+        this.userPhone = userPhone;
+    }
+
+    public int getUserId()
+    {
+        return userId;
+    }
+
+    public void setUserId(int userId)
+    {
+        this.userId = userId;
+    }
+
+    public String getUserCode()
+    {
+        return userCode;
+    }
+
+    public void setUserCode(String userCode)
+    {
+        this.userCode = userCode;
+    }
+
+    public String getUserName()
+    {
+        return userName;
+    }
+
+    public void setUserName(String userName)
+    {
+        this.userName = userName;
+    }
+
+    public String getUserPhone()
+    {
+        return userPhone;
+    }
+
+    public void setUserPhone(String userPhone)
+    {
+        this.userPhone = userPhone;
+    }
+
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/demo/controller/DemoIconController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/demo/controller/DemoIconController.java
new file mode 100644
index 0000000..b6884cc
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/demo/controller/DemoIconController.java
@@ -0,0 +1,35 @@
+package com.ruoyi.web.controller.demo.controller;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+/**
+ * 图标相关
+ * 
+ * @author ruoyi
+ */
+@Controller
+@RequestMapping("/demo/icon")
+public class DemoIconController
+{
+    private String prefix = "demo/icon";
+
+    /**
+     * FontAwesome图标
+     */
+    @GetMapping("/fontawesome")
+    public String fontAwesome()
+    {
+        return prefix + "/fontawesome";
+    }
+
+    /**
+     * Glyphicons图标
+     */
+    @GetMapping("/glyphicons")
+    public String glyphicons()
+    {
+        return prefix + "/glyphicons";
+    }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/demo/controller/DemoOperateController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/demo/controller/DemoOperateController.java
new file mode 100644
index 0000000..18cb90a
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/demo/controller/DemoOperateController.java
@@ -0,0 +1,326 @@
+package com.ruoyi.web.controller.demo.controller;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+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.ResponseBody;
+import org.springframework.web.multipart.MultipartFile;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.PageDomain;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.core.page.TableSupport;
+import com.ruoyi.common.core.text.Convert;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.web.controller.demo.domain.CustomerModel;
+import com.ruoyi.web.controller.demo.domain.UserOperateModel;
+
+/**
+ * 操作控制
+ * 
+ * @author ruoyi
+ */
+@Controller
+@RequestMapping("/demo/operate")
+public class DemoOperateController extends BaseController
+{
+    private String prefix = "demo/operate";
+
+    private final static Map<Integer, UserOperateModel> users = new LinkedHashMap<Integer, UserOperateModel>();
+    {
+        users.put(1, new UserOperateModel(1, "1000001", "测试1", "0", "15888888888", "ry@qq.com", 150.0, "0"));
+        users.put(2, new UserOperateModel(2, "1000002", "测试2", "1", "15666666666", "ry@qq.com", 180.0, "1"));
+        users.put(3, new UserOperateModel(3, "1000003", "测试3", "0", "15666666666", "ry@qq.com", 110.0, "1"));
+        users.put(4, new UserOperateModel(4, "1000004", "测试4", "1", "15666666666", "ry@qq.com", 220.0, "1"));
+        users.put(5, new UserOperateModel(5, "1000005", "测试5", "0", "15666666666", "ry@qq.com", 140.0, "1"));
+        users.put(6, new UserOperateModel(6, "1000006", "测试6", "1", "15666666666", "ry@qq.com", 330.0, "1"));
+        users.put(7, new UserOperateModel(7, "1000007", "测试7", "0", "15666666666", "ry@qq.com", 160.0, "1"));
+        users.put(8, new UserOperateModel(8, "1000008", "测试8", "1", "15666666666", "ry@qq.com", 170.0, "1"));
+        users.put(9, new UserOperateModel(9, "1000009", "测试9", "0", "15666666666", "ry@qq.com", 180.0, "1"));
+        users.put(10, new UserOperateModel(10, "1000010", "测试10", "0", "15666666666", "ry@qq.com", 210.0, "1"));
+        users.put(11, new UserOperateModel(11, "1000011", "测试11", "1", "15666666666", "ry@qq.com", 110.0, "1"));
+        users.put(12, new UserOperateModel(12, "1000012", "测试12", "0", "15666666666", "ry@qq.com", 120.0, "1"));
+        users.put(13, new UserOperateModel(13, "1000013", "测试13", "1", "15666666666", "ry@qq.com", 380.0, "1"));
+        users.put(14, new UserOperateModel(14, "1000014", "测试14", "0", "15666666666", "ry@qq.com", 280.0, "1"));
+        users.put(15, new UserOperateModel(15, "1000015", "测试15", "0", "15666666666", "ry@qq.com", 570.0, "1"));
+        users.put(16, new UserOperateModel(16, "1000016", "测试16", "1", "15666666666", "ry@qq.com", 260.0, "1"));
+        users.put(17, new UserOperateModel(17, "1000017", "测试17", "1", "15666666666", "ry@qq.com", 210.0, "1"));
+        users.put(18, new UserOperateModel(18, "1000018", "测试18", "1", "15666666666", "ry@qq.com", 340.0, "1"));
+        users.put(19, new UserOperateModel(19, "1000019", "测试19", "1", "15666666666", "ry@qq.com", 160.0, "1"));
+        users.put(20, new UserOperateModel(20, "1000020", "测试20", "1", "15666666666", "ry@qq.com", 220.0, "1"));
+        users.put(21, new UserOperateModel(21, "1000021", "测试21", "1", "15666666666", "ry@qq.com", 120.0, "1"));
+        users.put(22, new UserOperateModel(22, "1000022", "测试22", "1", "15666666666", "ry@qq.com", 130.0, "1"));
+        users.put(23, new UserOperateModel(23, "1000023", "测试23", "1", "15666666666", "ry@qq.com", 490.0, "1"));
+        users.put(24, new UserOperateModel(24, "1000024", "测试24", "1", "15666666666", "ry@qq.com", 570.0, "1"));
+        users.put(25, new UserOperateModel(25, "1000025", "测试25", "1", "15666666666", "ry@qq.com", 250.0, "1"));
+        users.put(26, new UserOperateModel(26, "1000026", "测试26", "1", "15666666666", "ry@qq.com", 250.0, "1"));
+    }
+
+    /**
+     * 表格
+     */
+    @GetMapping("/table")
+    public String table()
+    {
+        return prefix + "/table";
+    }
+
+    /**
+     * 其他
+     */
+    @GetMapping("/other")
+    public String other()
+    {
+        return prefix + "/other";
+    }
+
+    /**
+     * 查询数据
+     */
+    @PostMapping("/list")
+    @ResponseBody
+    public TableDataInfo list(UserOperateModel userModel)
+    {
+        TableDataInfo rspData = new TableDataInfo();
+        List<UserOperateModel> userList = new ArrayList<UserOperateModel>(users.values());
+        // 查询条件过滤
+        if (StringUtils.isNotEmpty(userModel.getSearchValue()))
+        {
+            userList.clear();
+            for (Map.Entry<Integer, UserOperateModel> entry : users.entrySet())
+            {
+                if (entry.getValue().getUserName().equals(userModel.getSearchValue()))
+                {
+                    userList.add(entry.getValue());
+                }
+            }
+        }
+        else if (StringUtils.isNotEmpty(userModel.getUserName()))
+        {
+            userList.clear();
+            for (Map.Entry<Integer, UserOperateModel> entry : users.entrySet())
+            {
+                if (entry.getValue().getUserName().equals(userModel.getUserName()))
+                {
+                    userList.add(entry.getValue());
+                }
+            }
+        }
+        PageDomain pageDomain = TableSupport.buildPageRequest();
+        if (null == pageDomain.getPageNum() || null == pageDomain.getPageSize())
+        {
+            rspData.setRows(userList);
+            rspData.setTotal(userList.size());
+            return rspData;
+        }
+        Integer pageNum = (pageDomain.getPageNum() - 1) * 10;
+        Integer pageSize = pageDomain.getPageNum() * 10;
+        if (pageSize > userList.size())
+        {
+            pageSize = userList.size();
+        }
+        rspData.setRows(userList.subList(pageNum, pageSize));
+        rspData.setTotal(userList.size());
+        return rspData;
+    }
+
+    /**
+     * 新增用户
+     */
+    @GetMapping("/add")
+    public String add(ModelMap mmap)
+    {
+        return prefix + "/add";
+    }
+
+    /**
+     * 新增保存用户
+     */
+    @PostMapping("/add")
+    @ResponseBody
+    public AjaxResult addSave(UserOperateModel user)
+    {
+        Integer userId = users.size() + 1;
+        user.setUserId(userId);
+        return AjaxResult.success(users.put(userId, user));
+    }
+
+    /**
+     * 新增保存主子表信息
+     */
+    @PostMapping("/customer/add")
+    @ResponseBody
+    public AjaxResult addSave(CustomerModel customerModel)
+    {
+        System.out.println(customerModel.toString());
+        return AjaxResult.success();
+    }
+
+    /**
+     * 修改用户
+     */
+    @GetMapping("/edit/{userId}")
+    public String edit(@PathVariable("userId") Integer userId, ModelMap mmap)
+    {
+        mmap.put("user", users.get(userId));
+        return prefix + "/edit";
+    }
+
+    /**
+     * 修改保存用户
+     */
+    @PostMapping("/edit")
+    @ResponseBody
+    public AjaxResult editSave(UserOperateModel user)
+    {
+        return AjaxResult.success(users.put(user.getUserId(), user));
+    }
+
+    /**
+     * 导出
+     */
+    @PostMapping("/export")
+    @ResponseBody
+    public AjaxResult export(UserOperateModel user)
+    {
+        List<UserOperateModel> list = new ArrayList<UserOperateModel>(users.values());
+        ExcelUtil<UserOperateModel> util = new ExcelUtil<UserOperateModel>(UserOperateModel.class);
+        return util.exportExcel(list, "用户数据");
+    }
+
+    /**
+     * 下载模板
+     */
+    @GetMapping("/importTemplate")
+    @ResponseBody
+    public AjaxResult importTemplate()
+    {
+        ExcelUtil<UserOperateModel> util = new ExcelUtil<UserOperateModel>(UserOperateModel.class);
+        return util.importTemplateExcel("用户数据");
+    }
+
+    /**
+     * 导入数据
+     */
+    @PostMapping("/importData")
+    @ResponseBody
+    public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception
+    {
+        ExcelUtil<UserOperateModel> util = new ExcelUtil<UserOperateModel>(UserOperateModel.class);
+        List<UserOperateModel> userList = util.importExcel(file.getInputStream());
+        String message = importUser(userList, updateSupport);
+        return AjaxResult.success(message);
+    }
+
+    /**
+     * 删除用户
+     */
+    @PostMapping("/remove")
+    @ResponseBody
+    public AjaxResult remove(String ids)
+    {
+        Integer[] userIds = Convert.toIntArray(ids);
+        for (Integer userId : userIds)
+        {
+            users.remove(userId);
+        }
+        return AjaxResult.success();
+    }
+
+    /**
+     * 查看详细
+     */
+    @GetMapping("/detail/{userId}")
+    public String detail(@PathVariable("userId") Integer userId, ModelMap mmap)
+    {
+        mmap.put("user", users.get(userId));
+        return prefix + "/detail";
+    }
+
+    @PostMapping("/clean")
+    @ResponseBody
+    public AjaxResult clean()
+    {
+        users.clear();
+        return success();
+    }
+
+    /**
+     * 导入用户数据
+     * 
+     * @param userList 用户数据列表
+     * @param isUpdateSupport 是否更新支持,如果已存在,则进行更新数据
+     * @return 结果
+     */
+    public String importUser(List<UserOperateModel> userList, Boolean isUpdateSupport)
+    {
+        if (StringUtils.isNull(userList) || userList.size() == 0)
+        {
+            throw new ServiceException("导入用户数据不能为空!");
+        }
+        int successNum = 0;
+        int failureNum = 0;
+        StringBuilder successMsg = new StringBuilder();
+        StringBuilder failureMsg = new StringBuilder();
+        for (UserOperateModel user : userList)
+        {
+            try
+            {
+                // 验证是否存在这个用户
+                boolean userFlag = false;
+                for (Map.Entry<Integer, UserOperateModel> entry : users.entrySet())
+                {
+                    if (entry.getValue().getUserName().equals(user.getUserName()))
+                    {
+                        userFlag = true;
+                        break;
+                    }
+                }
+                if (!userFlag)
+                {
+                    Integer userId = users.size() + 1;
+                    user.setUserId(userId);
+                    users.put(userId, user);
+                    successNum++;
+                    successMsg.append("<br/>" + successNum + "、用户 " + user.getUserName() + " 导入成功");
+                }
+                else if (isUpdateSupport)
+                {
+                    users.put(user.getUserId(), 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());
+            }
+        }
+        if (failureNum > 0)
+        {
+            failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:");
+            throw new ServiceException(failureMsg.toString());
+        }
+        else
+        {
+            successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:");
+        }
+        return successMsg.toString();
+    }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/demo/controller/DemoReportController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/demo/controller/DemoReportController.java
new file mode 100644
index 0000000..6101008
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/demo/controller/DemoReportController.java
@@ -0,0 +1,53 @@
+package com.ruoyi.web.controller.demo.controller;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+/**
+ * 报表
+ * 
+ * @author ruoyi
+ */
+@Controller
+@RequestMapping("/demo/report")
+public class DemoReportController
+{
+    private String prefix = "demo/report";
+
+    /**
+     * 百度ECharts
+     */
+    @GetMapping("/echarts")
+    public String echarts()
+    {
+        return prefix + "/echarts";
+    }
+
+    /**
+     * 图表插件
+     */
+    @GetMapping("/peity")
+    public String peity()
+    {
+        return prefix + "/peity";
+    }
+
+    /**
+     * 线状图插件
+     */
+    @GetMapping("/sparkline")
+    public String sparkline()
+    {
+        return prefix + "/sparkline";
+    }
+
+    /**
+     * 图表组合
+     */
+    @GetMapping("/metrics")
+    public String metrics()
+    {
+        return prefix + "/metrics";
+    }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/demo/controller/DemoTableController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/demo/controller/DemoTableController.java
new file mode 100644
index 0000000..bd15891
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/demo/controller/DemoTableController.java
@@ -0,0 +1,1023 @@
+package com.ruoyi.web.controller.demo.controller;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+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.ResponseBody;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.annotation.Excel.ColumnType;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.BaseEntity;
+import com.ruoyi.common.core.page.PageDomain;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.core.page.TableSupport;
+import com.ruoyi.common.core.text.Convert;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+
+/**
+ * 表格相关
+ * 
+ * @author ruoyi
+ */
+@Controller
+@RequestMapping("/demo/table")
+public class DemoTableController extends BaseController
+{
+    private String prefix = "demo/table";
+
+    private final static List<UserTableModel> users = new ArrayList<UserTableModel>();
+    {
+        users.add(new UserTableModel(1, "1000001", "测试1", "0", "15888888888", "ry@qq.com", 150.0, "0"));
+        users.add(new UserTableModel(2, "1000002", "测试2", "1", "15666666666", "ry@qq.com", 180.0, "1"));
+        users.add(new UserTableModel(3, "1000003", "测试3", "0", "15666666666", "ry@qq.com", 110.0, "1"));
+        users.add(new UserTableModel(4, "1000004", "测试4", "1", "15666666666", "ry@qq.com", 220.0, "1"));
+        users.add(new UserTableModel(5, "1000005", "测试5", "0", "15666666666", "ry@qq.com", 140.0, "1"));
+        users.add(new UserTableModel(6, "1000006", "测试6", "1", "15666666666", "ry@qq.com", 330.0, "1"));
+        users.add(new UserTableModel(7, "1000007", "测试7", "0", "15666666666", "ry@qq.com", 160.0, "1"));
+        users.add(new UserTableModel(8, "1000008", "测试8", "1", "15666666666", "ry@qq.com", 170.0, "1"));
+        users.add(new UserTableModel(9, "1000009", "测试9", "0", "15666666666", "ry@qq.com", 180.0, "1"));
+        users.add(new UserTableModel(10, "1000010", "测试10", "0", "15666666666", "ry@qq.com", 210.0, "1"));
+        users.add(new UserTableModel(11, "1000011", "测试11", "1", "15666666666", "ry@qq.com", 110.0, "1"));
+        users.add(new UserTableModel(12, "1000012", "测试12", "0", "15666666666", "ry@qq.com", 120.0, "1"));
+        users.add(new UserTableModel(13, "1000013", "测试13", "1", "15666666666", "ry@qq.com", 380.0, "1"));
+        users.add(new UserTableModel(14, "1000014", "测试14", "0", "15666666666", "ry@qq.com", 280.0, "1"));
+        users.add(new UserTableModel(15, "1000015", "测试15", "0", "15666666666", "ry@qq.com", 570.0, "1"));
+        users.add(new UserTableModel(16, "1000016", "测试16", "1", "15666666666", "ry@qq.com", 260.0, "1"));
+        users.add(new UserTableModel(17, "1000017", "测试17", "1", "15666666666", "ry@qq.com", 210.0, "1"));
+        users.add(new UserTableModel(18, "1000018", "测试18", "1", "15666666666", "ry@qq.com", 340.0, "1"));
+        users.add(new UserTableModel(19, "1000019", "测试19", "1", "15666666666", "ry@qq.com", 160.0, "1"));
+        users.add(new UserTableModel(20, "1000020", "测试20", "1", "15666666666", "ry@qq.com", 220.0, "1"));
+        users.add(new UserTableModel(21, "1000021", "测试21", "1", "15666666666", "ry@qq.com", 120.0, "1"));
+        users.add(new UserTableModel(22, "1000022", "测试22", "1", "15666666666", "ry@qq.com", 130.0, "1"));
+        users.add(new UserTableModel(23, "1000023", "测试23", "1", "15666666666", "ry@qq.com", 490.0, "1"));
+        users.add(new UserTableModel(24, "1000024", "测试24", "1", "15666666666", "ry@qq.com", 570.0, "1"));
+        users.add(new UserTableModel(25, "1000025", "测试25", "1", "15666666666", "ry@qq.com", 250.0, "1"));
+        users.add(new UserTableModel(26, "1000026", "测试26", "1", "15666666666", "ry@qq.com", 250.0, "1"));
+    }
+
+    private final static List<AreaModel> areas = new ArrayList<AreaModel>();
+    {
+        areas.add(new AreaModel(1, 0, "广东省", "440000", "GDS", "GuangDongSheng", 1));
+        areas.add(new AreaModel(2, 0, "湖南省", "430000", "HNS", "HuNanSheng", 1));
+        areas.add(new AreaModel(3, 0, "河南省", "410000", "HNS", "HeNanSheng", 0));
+        areas.add(new AreaModel(4, 0, "湖北省", "420000", "HBS", "HuBeiSheng", 0));
+        areas.add(new AreaModel(5, 0, "辽宁省", "210000", "LNS", "LiaoNingSheng", 0));
+        areas.add(new AreaModel(6, 0, "山东省", "370000", "SDS", "ShanDongSheng", 0));
+        areas.add(new AreaModel(7, 0, "陕西省", "610000", "SXS", "ShanXiSheng", 0));
+        areas.add(new AreaModel(8, 0, "贵州省", "520000", "GZS", "GuiZhouSheng", 0));
+        areas.add(new AreaModel(9,  0, "上海市", "310000", "SHS", "ShangHaiShi", 0));
+        areas.add(new AreaModel(10, 0, "重庆市", "500000", "CQS", "ChongQingShi", 0));
+        areas.add(new AreaModel(11, 0, "若依省", "666666", "YYS", "RuoYiSheng", 0));
+        areas.add(new AreaModel(12, 0, "安徽省", "340000", "AHS", "AnHuiSheng", 0));
+        areas.add(new AreaModel(13, 0, "福建省", "350000", "FJS", "FuJianSheng", 0));
+        areas.add(new AreaModel(14, 0, "海南省", "460000", "HNS", "HaiNanSheng", 0));
+        areas.add(new AreaModel(15, 0, "江苏省", "320000", "JSS", "JiangSuSheng", 0));
+        areas.add(new AreaModel(16, 0, "青海省", "630000", "QHS", "QingHaiSheng", 0));
+        areas.add(new AreaModel(17, 0, "广西壮族自治区", "450000", "GXZZZZQ", "GuangXiZhuangZuZiZhiQu", 0));
+        areas.add(new AreaModel(18, 0, "宁夏回族自治区", "640000", "NXHZZZQ", "NingXiaHuiZuZiZhiQu", 0));
+        areas.add(new AreaModel(19, 0, "内蒙古自治区", "150000", "NMGZZQ", "NeiMengGuZiZhiQu", 0));
+        areas.add(new AreaModel(20, 0, "新疆维吾尔自治区", "650000", "XJWWEZZQ", "XinJiangWeiWuErZiZhiQu", 0));
+        areas.add(new AreaModel(21, 0, "江西省", "360000", "JXS", "JiangXiSheng", 0));
+        areas.add(new AreaModel(22, 0, "浙江省", "330000", "ZJS", "ZheJiangSheng", 0));
+        areas.add(new AreaModel(23, 0, "河北省", "130000", "HBS", "HeBeiSheng", 0));
+        areas.add(new AreaModel(24, 0, "天津市", "120000", "TJS", "TianJinShi", 0));
+        areas.add(new AreaModel(25, 0, "山西省", "140000", "SXS", "ShanXiSheng", 0));
+        areas.add(new AreaModel(26, 0, "台湾省", "710000", "TWS", "TaiWanSheng", 0));
+        areas.add(new AreaModel(27, 0, "甘肃省", "620000", "GSS", "GanSuSheng", 0));
+        areas.add(new AreaModel(28, 0, "四川省", "510000", "SCS", "SiChuanSheng", 0));
+        areas.add(new AreaModel(29, 0, "云南省", "530000", "YNS", "YunNanSheng", 0));
+        areas.add(new AreaModel(30, 0, "北京市", "110000", "BJS", "BeiJingShi", 0));
+        areas.add(new AreaModel(31, 0, "香港特别行政区", "810000", "XGTBXZQ", "XiangGangTeBieXingZhengQu", 0));
+        areas.add(new AreaModel(32, 0, "澳门特别行政区", "820000", "AMTBXZQ", "AoMenTeBieXingZhengQu", 0));
+        
+        areas.add(new AreaModel(100, 1, "深圳市", "440300", "SZS", "ShenZhenShi", 1));
+        areas.add(new AreaModel(101, 1, "广州市", "440100", "GZS", "GuangZhouShi", 0));
+        areas.add(new AreaModel(102, 1, "东莞市", "441900", "DGS", "DongGuanShi", 0));
+        areas.add(new AreaModel(103, 2, "长沙市", "410005", "CSS", "ChangShaShi", 1));
+        areas.add(new AreaModel(104, 2, "岳阳市", "414000", "YYS", "YueYangShi", 0));
+        
+        areas.add(new AreaModel(1000, 100, "龙岗区", "518172", "LGQ", "LongGangQu", 0));
+        areas.add(new AreaModel(1001, 100, "南山区", "518051", "NSQ", "NanShanQu", 0));
+        areas.add(new AreaModel(1002, 100, "宝安区", "518101", "BAQ", "BaoAnQu", 0));
+        areas.add(new AreaModel(1003, 100, "福田区", "518081", "FTQ", "FuTianQu", 0));
+        areas.add(new AreaModel(1004, 103, "天心区", "410004", "TXQ", "TianXinQu", 0));
+        areas.add(new AreaModel(1005, 103, "开福区", "410008", "KFQ", "KaiFuQu", 0));
+        areas.add(new AreaModel(1006, 103, "芙蓉区", "410011", "FRQ", "FuRongQu", 0));
+        areas.add(new AreaModel(1007, 103, "雨花区", "410011", "YHQ", "YuHuaQu", 0));
+    }
+
+    private final static List<UserTableColumn> columns = new ArrayList<UserTableColumn>();
+    {
+        columns.add(new UserTableColumn("用户ID", "userId"));
+        columns.add(new UserTableColumn("用户编号", "userCode"));
+        columns.add(new UserTableColumn("用户姓名", "userName"));
+        columns.add(new UserTableColumn("用户手机", "userPhone"));
+        columns.add(new UserTableColumn("用户邮箱", "userEmail"));
+        columns.add(new UserTableColumn("用户状态", "status"));
+    }
+    
+    private final static List<DocumentModel> documents = new ArrayList<DocumentModel>();
+    {
+        documents.add(new DocumentModel(1, "247-XW·2024-D10-0001", "新闻热线[2024]000001", "索尼射击游戏《Concord》停止运营,玩家将获全额退款", "索尼宣布多人射击游戏《Concord》将于9月6日停止运营,玩家将获得全额退款。游戏总监Ryan Ellis在给玩家的信中表示,这款游戏首次发布“并没有像我们预期的那样顺利”。《Concord》的开发历时8年,投资超过1.5亿美元。游戏在Steam平台的售价为40美元,采用买断制销售模式。据SteamDB统计,游戏上市后的最高同时在线人数为697人。"));
+        documents.add(new DocumentModel(2, "247-XW·2024-D30-0002", "新闻热线[2024]000002", "网红账号被封,央媒:如此炫富毒瘤早就该拔了", "在社交平台上分享自己的生活日常,本来无可厚非。但无底线地展示物欲、宣扬拜金,取笑甚至嘲讽工薪者的烟火生活,就会遮蔽普通人的平凡质朴和坚韧奋斗,在无形中消解芸芸众生脚踏实地、自立自强的社会正气。对这种助长金钱至上、刺激公众焦虑,既污染网络生态,又撕裂社会和谐的炫富“毒瘤”,必须坚决拔除之。在国家有关部门的部署下,近日,多个网络平台开展“不良价值导向内容专项治理”行动,对“奢靡浪费”“炫富拜金”等问题从严打击,倡导理性、文明的消费观和价值观。"));
+        documents.add(new DocumentModel(3, "CT01-XW·2024-Y-0003", "新闻热线[2024]000003", "重庆一夫妻被骗至缅甸,家属:两人已被解救,预计很快能回国", "5月25日,重庆一对夫妻在前往泰国后失联,疑被诈骗集团骗至缅甸的消息引发广泛关注。警方已对此事立案调查,而这对夫妻的亲属则每天生活在焦急和不安之中。亲属:家都瘫痪了,事情一经曝光,迅速登上了热搜,成为公众热议的话题。据了解,这对夫妻原计划是去泰国谈生意,但不幸的是,他们的泰国之行变成了一场噩梦。亲属李先生透露,4月14日,他们夫妻二人抵达泰国,不久后便疑似被人以10万元的价格卖到缅甸,目前被困在缅甸妙瓦底的一个电信诈骗园区。"));
+        documents.add(new DocumentModel(4, "CT01-XW·2024-Y-0004", "新闻热线[2024]000004", "江滨社区联合派出所、金霞消防站开展电动自行车安全隐患夜查活动", "近日,长沙市开福区江滨社区联合派出所、金霞消防站深入居民小区、单位场所,以电动车自行车火灾防范为重点,开展消防安全夜查行动。此次夜查紧紧围绕老旧居民区、“三合一”场所、沿街门店、夜间经营使用场所等场所开展监督检查,重点检查电动自行车违规停放充电、堵塞疏散通道和安全出口,架空层违规作为电动自行车停放充电场所,电动自行车违规“进楼入户”“飞线充电”,电动自行车擅自改装等五大类问题。"));
+        documents.add(new DocumentModel(5, "CT01-XW·2024-Y-0005", "新闻热线[2024]000005", "《黑神话》让海外玩家迷上“悟空”", "备受全球玩家瞩目的首款国产3A游戏《黑神话:悟空》日前正式发布。精美绝伦的东方美学世界、精彩纷呈的中国神话故事、酣畅淋漓的游戏体验,这款游戏为全球玩家带来一场视觉与文化的双重盛宴。从“悟空”成功出海的背后,海外人士看到了中国游戏产业的巨大进步,感受到了中国文化的多元精彩,并对下一个“悟空”的诞生及更多中国文化产品走向世界充满期待。"));
+        documents.add(new DocumentModel(6, "CT01-XW·2024-Y-0006", "新闻热线[2024]000006", "市场状况充满挑战!极星宣布裁员全球约15%的员工", "据路透社报道,极星周五以“充满挑战的市场状况”为由,宣布计划在全球范围内裁减约450个职位。此次裁员之际,许多人都对电动汽车需求降温表示担忧,而且极星预计汽车业务最早将在2025年开始实现收支平衡。极星发言人表示:“作为该商业计划的一部分,我们需要调整我们的业务和运营规模。” “这涉及减少外部支出,遗憾的是,还包括我们的员工数量。”该公司还表示,希望减少对沃尔沃及其母公司吉利外部融资的依赖,最近还表示希望削减成本并提高电动汽车的利润率。"));
+        documents.add(new DocumentModel(7, "CT01-XW·2024-Y-0007", "新闻热线[2024]000007", "浙江隐秘富豪涉百亿非法集资案,部分资金流入新造车公司", "5月10日、11日,上海北广投资管理有限公司(下称“北广投”)非法集资案在上海黄浦区人民法院一审公开开庭审理,北广投实控人周敏、法定代表人朱江等30余名中高管被控非法吸收公众存款罪。根据财新报道,这一案件中,非法集资的资金有部分流入了两家新能源车企——爱驰汽车、万象汽车。同时,有多位投资人引述与经侦部门沟通时的说法称,该案事发时未兑付金额有130余亿元,其中去往广微控股45亿元、万象汽车63亿元、爱驰汽车15亿元。"));
+        documents.add(new DocumentModel(8, "CT01-XW·2024-Y-0008", "新闻热线[2024]000008", "特斯拉宣布Model Y升级:搭载HW4.0硬件,售价仍25.89万元起", "2月1日,特斯拉官方宣布ModelY升级。外观上,新增ModelY专属色“快银车漆”,并采用烈焰红代替中国红、星空灰代替冷光银;性能上,ModelY全系配备全新一代自动辅助驾驶硬件(HW4.0),通过搭载超远距离双目摄像头,ModelY的最远探测距离达424米。由此,特斯拉全系车型均配备了自动辅助驾驶硬件HW4.0。在售价方面,特斯拉中国官网显示,ModelY车型依然保持原价。ModelY后轮驱动版25.89万元起、ModelY长续航版29.99万元起、ModelY高性能版售价36.39万元起。"));
+        documents.add(new DocumentModel(9, "CT01-XW·2024-D10-0009", "新闻热线[2024]000009", "华为手机归来,谁最受伤?", "低迷周期下的智能手机市场在2023年下半年迎来了华为的回归,这也给本就竞争激烈的市场环境带来了更大变数。1月29日,有消息称,华为已注册“星耀手机”品牌商标,定位中端手机市场,但上述消息并未获得华为方面确认。“目前星耀的相关信息我们看到了,但是没有获得产品信息以及启动线下铺货的通知。对于和其他品牌的二选一问题,听其他省份的经销商说过,但目前(华为渠道)这边也没有更多动作。”一位广东区域的华为核心经销商对记者说。但华为手机的反扑已经开始。在多家调研机构公布的2023年四季度智能手机出货数据中,华为手机的量正在明显上升,当季增幅在35%到47%之间。不过,从全年数据来看,并未登上前五榜单。"));
+        documents.add(new DocumentModel(10, "CT01-XW·2024-D10-0010", "新闻热线[2024]000010", "疯狂裁员的硅谷大厂:除了AI,其它都是将就", "放眼望去,近期科技企业财报形势一片大好,裁员浪潮却仍在不断蔓延。国内职场动态看脉脉,那硅谷裁员情况就得看layoff.fyi了。数据显示,2024年,103家科技企业进行了裁员,28963位员工失去了饭碗。其中,电子支付公司PayPal大笔一挥,裁掉2500人,微软则在开年就裁掉1900人。回望2023年,谷歌、Meta、亚马逊、微软均为裁员重灾区,裁员人数在一万左右。具体而言,谷歌近日披露的财报指出,2023年谷歌解雇了12000多名员工,光是在遣散费和其他费用上就花费了21亿美元。而且裁员费用还在不断增加,2024年刚过去一个月,谷歌就已经花费了7亿美元用来裁员。"));
+        documents.add(new DocumentModel(11, "CT01-XW·2024-D30-0011", "新闻热线[2024]000011", "国产手机品牌重新崛起背后:市场正在逐步恢复活力,竞争也愈发激烈", "2024年伊始,随着全球经济的逐渐复苏,手机消费市场也展现出勃勃生机。中国信通院最新数据显示,2023年中国市场手机出货量实现了6.5%的同比增长,其中5G手机增长势头更为强劲,占比高达82.8%。1月25日,国际数据公司(IDC)发布了最新手机季度跟踪报告,揭示了中国智能手机市场在2023年第四季度的出货量情况。报告显示,该季度中国智能手机市场出货量达到了约7363万台,同比增长1.2%。这是在连续十个季度同比下降后,中国智能手机市场首次实现反弹。这一积极信号表明,市场正在逐步恢复活力,各大品牌之间的竞争也愈发激烈。"));
+        documents.add(new DocumentModel(12, "CT01-XW·2024-D30-0012", "新闻热线[2024]000012", "SpaceX将于1月31日向国际空间站发射天鹅号货运飞船", "1月29日消息,美国太空探索技术公司SpaceX计划于当地时间1月30日,利用“猎鹰9号”火箭从佛罗里达州肯尼迪航天中心发射诺斯罗普·格鲁曼公司的“天鹅号”货运飞船至国际空间站。此次任务是执行NG-20商业补给,将运送约8200多磅的物资、设备及科学实验器材。"));
+    }
+
+    /**
+     * 搜索相关
+     */
+    @GetMapping("/search")
+    public String search()
+    {
+        return prefix + "/search";
+    }
+
+    /**
+     * 数据汇总
+     */
+    @GetMapping("/footer")
+    public String footer()
+    {
+        return prefix + "/footer";
+    }
+
+    /**
+     * 组合表头
+     */
+    @GetMapping("/groupHeader")
+    public String groupHeader()
+    {
+        return prefix + "/groupHeader";
+    }
+
+    /**
+     * 表格导出
+     */
+    @GetMapping("/export")
+    public String export()
+    {
+        return prefix + "/export";
+    }
+
+    /**
+     * 表格导出选择列
+     */
+    @GetMapping("/exportSelected")
+    public String exportSelected()
+    {
+        return prefix + "/exportSelected";
+    }
+
+    /**
+     * 导出数据
+     */
+    @PostMapping("/exportData")
+    @ResponseBody
+    public AjaxResult exportSelected(UserTableModel userModel, String userIds)
+    {
+        List<UserTableModel> userList = new ArrayList<UserTableModel>(Arrays.asList(new UserTableModel[users.size()]));
+        Collections.copy(userList, users);
+
+        // 条件过滤
+        if (StringUtils.isNotEmpty(userIds))
+        {
+            userList.clear();
+            for (Long userId : Convert.toLongArray(userIds))
+            {
+                for (UserTableModel user : users)
+                {
+                    if (user.getUserId() == userId)
+                    {
+                        userList.add(user);
+                    }
+                }
+            }
+        }
+        ExcelUtil<UserTableModel> util = new ExcelUtil<UserTableModel>(UserTableModel.class);
+        return util.exportExcel(userList, "用户数据");
+    }
+
+    /**
+     * 翻页记住选择
+     */
+    @GetMapping("/remember")
+    public String remember()
+    {
+        return prefix + "/remember";
+    }
+
+    /**
+     * 表格保存状态
+     */
+    @GetMapping("/cookie")
+    public String cookie()
+    {
+        return prefix + "/cookie";
+    }
+
+    /**
+     * 跳转至指定页
+     */
+    @GetMapping("/pageGo")
+    public String pageGo()
+    {
+        return prefix + "/pageGo";
+    }
+
+    /**
+     * 自定义查询参数
+     */
+    @GetMapping("/params")
+    public String params()
+    {
+        return prefix + "/params";
+    }
+
+    /**
+     * 多表格
+     */
+    @GetMapping("/multi")
+    public String multi()
+    {
+        return prefix + "/multi";
+    }
+
+    /**
+     * 点击按钮加载表格
+     */
+    @GetMapping("/button")
+    public String button()
+    {
+        return prefix + "/button";
+    }
+
+    /**
+     * 直接加载表格数据
+     */
+    @GetMapping("/data")
+    public String data(ModelMap mmap)
+    {
+        mmap.put("users", users);
+        return prefix + "/data";
+    }
+
+    /**
+     * 表格冻结列
+     */
+    @GetMapping("/fixedColumns")
+    public String fixedColumns()
+    {
+        return prefix + "/fixedColumns";
+    }
+
+    /**
+     * 自定义触发事件
+     */
+    @GetMapping("/event")
+    public String event()
+    {
+        return prefix + "/event";
+    }
+
+    /**
+     * 表格细节视图
+     */
+    @GetMapping("/detail")
+    public String detail()
+    {
+        return prefix + "/detail";
+    }
+
+    /**
+     * 表格父子视图
+     */
+    @GetMapping("/child")
+    public String child()
+    {
+        return prefix + "/child";
+    }
+
+    /**
+     * 表格图片预览
+     */
+    @GetMapping("/image")
+    public String image()
+    {
+        return prefix + "/image";
+    }
+
+    /**
+     * 动态增删改查
+     */
+    @GetMapping("/curd")
+    public String curd()
+    {
+        return prefix + "/curd";
+    }
+
+    /**
+     * 表格行拖拽操作
+     */
+    @GetMapping("/reorderRows")
+    public String reorderRows()
+    {
+        return prefix + "/reorderRows";
+    }
+
+    /**
+     * 表格列拖拽操作
+     */
+    @GetMapping("/reorderColumns")
+    public String reorderColumns()
+    {
+        return prefix + "/reorderColumns";
+    }
+
+    /**
+     * 表格列宽拖动
+     */
+    @GetMapping("/resizable")
+    public String resizable()
+    {
+        return prefix + "/resizable";
+    }
+
+    /**
+     * 表格行内编辑操作
+     */
+    @GetMapping("/editable")
+    public String editable()
+    {
+        return prefix + "/editable";
+    }
+
+    /**
+     * 主子表提交
+     */
+    @GetMapping("/subdata")
+    public String subdata()
+    {
+        return prefix + "/subdata";
+    }
+
+    /**
+     * 表格自动刷新
+     */
+    @GetMapping("/refresh")
+    public String refresh()
+    {
+        return prefix + "/refresh";
+    }
+
+    /**
+     * 表格打印配置
+     */
+    @GetMapping("/print")
+    public String print()
+    {
+        return prefix + "/print";
+    }
+
+    /**
+     * 表格标题格式化
+     */
+    @GetMapping("/headerStyle")
+    public String headerStyle()
+    {
+        return prefix + "/headerStyle";
+    }
+
+    /**
+     * 表格动态列
+     */
+    @GetMapping("/dynamicColumns")
+    public String dynamicColumns()
+    {
+        return prefix + "/dynamicColumns";
+    }
+
+    /**
+     * 表格虚拟滚动
+     */
+    @GetMapping("/virtualScroll")
+    public String virtualScroll()
+    {
+        return prefix + "/virtualScroll";
+    }
+
+    /**
+     * 自定义视图分页
+     */
+    @GetMapping("/customView")
+    public String customView()
+    {
+        return prefix + "/customView";
+    }
+
+    /**
+     * 全文索引
+     */
+    @GetMapping("/textSearch")
+    public String textSearch()
+    {
+        return prefix + "/textSearch";
+    }
+
+    /**
+     * 异步加载表格树
+     */
+    @GetMapping("/asynTree")
+    public String asynTree()
+    {
+        return prefix + "/asynTree";
+    }
+
+    /**
+     * 表格其他操作
+     */
+    @GetMapping("/other")
+    public String other()
+    {
+        return prefix + "/other";
+    }
+
+    /**
+     * 动态获取列
+     */
+    @PostMapping("/ajaxColumns")
+    @ResponseBody
+    public AjaxResult ajaxColumns(UserTableColumn userColumn)
+    {
+        List<UserTableColumn> columnList = new ArrayList<UserTableColumn>(Arrays.asList(new UserTableColumn[columns.size()]));
+        Collections.copy(columnList, columns);
+        if (userColumn != null && "userBalance".equals(userColumn.getField()))
+        {
+            columnList.add(new UserTableColumn("用户余额", "userBalance"));
+        }
+        return AjaxResult.success(columnList);
+    }
+
+    /**
+     * 查询数据
+     */
+    @PostMapping("/list")
+    @ResponseBody
+    public TableDataInfo list(UserTableModel userModel)
+    {
+        TableDataInfo rspData = new TableDataInfo();
+        List<UserTableModel> userList = new ArrayList<UserTableModel>(Arrays.asList(new UserTableModel[users.size()]));
+        Collections.copy(userList, users);
+        // 查询条件过滤
+        if (StringUtils.isNotEmpty(userModel.getUserName()))
+        {
+            userList.clear();
+            for (UserTableModel user : users)
+            {
+                if (user.getUserName().equals(userModel.getUserName()))
+                {
+                    userList.add(user);
+                }
+            }
+        }
+        PageDomain pageDomain = TableSupport.buildPageRequest();
+        if (null == pageDomain.getPageNum() || null == pageDomain.getPageSize())
+        {
+            rspData.setRows(userList);
+            rspData.setTotal(userList.size());
+            return rspData;
+        }
+        Integer pageNum = (pageDomain.getPageNum() - 1) * 10;
+        Integer pageSize = pageDomain.getPageNum() * 10;
+        if (pageSize > userList.size())
+        {
+            pageSize = userList.size();
+        }
+        rspData.setRows(userList.subList(pageNum, pageSize));
+        rspData.setTotal(userList.size());
+        return rspData;
+    }
+
+    /**
+     * 查询全文索引数据
+     */
+    @PostMapping("/text/list")
+    @ResponseBody
+    public TableDataInfo textList(BaseEntity baseEntity)
+    {
+        TableDataInfo rspData = new TableDataInfo();
+        List<DocumentModel> documentList = new ArrayList<DocumentModel>(Arrays.asList(new DocumentModel[documents.size()]));
+        Collections.copy(documentList, documents);
+        // 查询条件过滤
+        if (StringUtils.isNotEmpty(baseEntity.getSearchValue()))
+        {
+            documentList.clear();
+            for (DocumentModel document : documents)
+            {
+                boolean indexFlag = false;
+                if (document.getTitle().contains(baseEntity.getSearchValue()))
+                {
+                    indexFlag = true;
+                    document.setTitle(document.getTitle().replace(baseEntity.getSearchValue(), "<font color=\"red\">" + baseEntity.getSearchValue() + "</font>"));
+                }
+                if (document.getContent().contains(baseEntity.getSearchValue()))
+                {
+                    indexFlag = true;
+                    document.setContent(document.getContent().replace(baseEntity.getSearchValue(), "<font color=\"red\">" + baseEntity.getSearchValue() + "</font>"));
+                }
+                if (indexFlag)
+                {
+                    documentList.add(document);
+                }
+            }
+        }
+        PageDomain pageDomain = TableSupport.buildPageRequest();
+        if (null == pageDomain.getPageNum() || null == pageDomain.getPageSize())
+        {
+            rspData.setRows(documentList);
+            rspData.setTotal(documentList.size());
+            return rspData;
+        }
+        Integer pageNum = (pageDomain.getPageNum() - 1) * 10;
+        Integer pageSize = pageDomain.getPageNum() * 10;
+        if (pageSize > documentList.size())
+        {
+            pageSize = documentList.size();
+        }
+        rspData.setRows(documentList.subList(pageNum, pageSize));
+        rspData.setTotal(documentList.size());
+        return rspData;
+    }
+
+    /**
+     * 查询树表数据
+     */
+    @PostMapping("/tree/list")
+    @ResponseBody
+    public TableDataInfo treeList(AreaModel areaModel)
+    {
+        TableDataInfo rspData = new TableDataInfo();
+        List<AreaModel> areaList = new ArrayList<AreaModel>(Arrays.asList(new AreaModel[areas.size()]));
+        // 默认查询条件 parentId 0
+        Collections.copy(areaList, areas);
+        areaList.clear();
+        if (StringUtils.isNotEmpty(areaModel.getAreaName()))
+        {
+            for (AreaModel area : areas)
+            {
+                if (area.getParentId() == 0 && area.getAreaName().equals(areaModel.getAreaName()))
+                {
+                    areaList.add(area);
+                }
+            }
+        }
+        else
+        {
+            for (AreaModel area : areas)
+            {
+                if (area.getParentId() == 0)
+                {
+                    areaList.add(area);
+                }
+            }
+        }
+        PageDomain pageDomain = TableSupport.buildPageRequest();
+        Integer pageNum = (pageDomain.getPageNum() - 1) * pageDomain.getPageSize();
+        Integer pageSize = pageDomain.getPageNum() * pageDomain.getPageSize();
+        if (pageSize > areaList.size())
+        {
+            pageSize = areaList.size();
+        }
+        rspData.setRows(areaList.subList(pageNum, pageSize));
+        rspData.setTotal(areaList.size());
+        return rspData;
+    }
+
+    /**
+     * 查询树表子节点数据
+     */
+    @PostMapping("/tree/listChild")
+    @ResponseBody
+    public List<AreaModel> listChild(AreaModel areaModel)
+    {
+        List<AreaModel> areaList = new ArrayList<AreaModel>(Arrays.asList(new AreaModel[areas.size()]));
+        // 查询条件 parentId
+        Collections.copy(areaList, areas);
+        areaList.clear();
+        if (StringUtils.isNotEmpty(areaModel.getAreaName()))
+        {
+            for (AreaModel area : areas)
+            {
+                if (area.getParentId().intValue() == areaModel.getParentId().intValue() && area.getAreaName().equals(areaModel.getAreaName()))
+                {
+                    areaList.add(area);
+                }
+            }
+        }
+        else
+        {
+            for (AreaModel area : areas)
+            {
+                if (area.getParentId().intValue() == areaModel.getParentId().intValue())
+                {
+                    areaList.add(area);
+                }
+            }
+        }
+        return areaList;
+    }
+}
+
+class UserTableColumn
+{
+    /** 表头 */
+    private String title;
+    /** 字段 */
+    private String field;
+
+    public UserTableColumn()
+    {
+
+    }
+
+    public UserTableColumn(String title, String field)
+    {
+        this.title = title;
+        this.field = field;
+    }
+
+    public String getTitle()
+    {
+        return title;
+    }
+
+    public void setTitle(String title)
+    {
+        this.title = title;
+    }
+
+    public String getField()
+    {
+        return field;
+    }
+
+    public void setField(String field)
+    {
+        this.field = field;
+    }
+}
+
+class UserTableModel
+{
+    /** 用户ID */
+    private int userId;
+
+    /** 用户编号 */
+    @Excel(name = "用户编号", cellType = ColumnType.NUMERIC)
+    private String userCode;
+
+    /** 用户姓名 */
+    @Excel(name = "用户姓名")
+    private String userName;
+
+    /** 用户性别 */
+    private String userSex;
+
+    /** 用户手机 */
+    @Excel(name = "用户手机")
+    private String userPhone;
+
+    /** 用户邮箱 */
+    @Excel(name = "用户邮箱")
+    private String userEmail;
+
+    /** 用户余额 */
+    @Excel(name = "用户余额", cellType = ColumnType.NUMERIC)
+    private double userBalance;
+
+    /** 用户状态(0正常 1停用) */
+    private String status;
+
+    /** 创建时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+
+    public UserTableModel()
+    {
+
+    }
+
+    public UserTableModel(int userId, String userCode, String userName, String userSex, String userPhone,
+            String userEmail, double userBalance, String status)
+    {
+        this.userId = userId;
+        this.userCode = userCode;
+        this.userName = userName;
+        this.userSex = userSex;
+        this.userPhone = userPhone;
+        this.userEmail = userEmail;
+        this.userBalance = userBalance;
+        this.status = status;
+        this.createTime = DateUtils.getNowDate();
+    }
+
+    public int getUserId()
+    {
+        return userId;
+    }
+
+    public void setUserId(int userId)
+    {
+        this.userId = userId;
+    }
+
+    public String getUserCode()
+    {
+        return userCode;
+    }
+
+    public void setUserCode(String userCode)
+    {
+        this.userCode = userCode;
+    }
+
+    public String getUserName()
+    {
+        return userName;
+    }
+
+    public void setUserName(String userName)
+    {
+        this.userName = userName;
+    }
+
+    public String getUserSex()
+    {
+        return userSex;
+    }
+
+    public void setUserSex(String userSex)
+    {
+        this.userSex = userSex;
+    }
+
+    public String getUserPhone()
+    {
+        return userPhone;
+    }
+
+    public void setUserPhone(String userPhone)
+    {
+        this.userPhone = userPhone;
+    }
+
+    public String getUserEmail()
+    {
+        return userEmail;
+    }
+
+    public void setUserEmail(String userEmail)
+    {
+        this.userEmail = userEmail;
+    }
+
+    public double getUserBalance()
+    {
+        return userBalance;
+    }
+
+    public void setUserBalance(double userBalance)
+    {
+        this.userBalance = userBalance;
+    }
+
+    public String getStatus()
+    {
+        return status;
+    }
+
+    public void setStatus(String status)
+    {
+        this.status = status;
+    }
+
+    public Date getCreateTime()
+    {
+        return createTime;
+    }
+
+    public void setCreateTime(Date createTime)
+    {
+        this.createTime = createTime;
+    }
+}
+class AreaModel
+{
+    /** 编号 */
+    private Long id;
+
+    /** 父编号 */
+    private Long parentId;
+
+    /** 区域名称 */
+    private String areaName;
+
+    /** 区域代码 */
+    private String areaCode;
+
+    /** 名称首字母 */
+    private String simplePy;
+
+    /** 名称全拼 */
+    private String pinYin;
+
+    /** 是否有子节点(0无 1有) */
+    private Integer isTreeLeaf = 1;
+
+    public AreaModel()
+    {
+
+    }
+
+    public AreaModel(int id, int parentId, String areaName, String areaCode, String simplePy, String pinYin, Integer isTreeLeaf)
+    {
+        this.id = Long.valueOf(id);
+        this.parentId = Long.valueOf(parentId);
+        this.areaName = areaName;
+        this.areaCode = areaCode;
+        this.simplePy = simplePy;
+        this.pinYin = pinYin;
+        this.isTreeLeaf = isTreeLeaf;
+    }
+
+    public Long getId()
+    {
+        return id;
+    }
+
+    public void setId(Long id)
+    {
+        this.id = id;
+    }
+
+    public Long getParentId()
+    {
+        return parentId;
+    }
+
+    public void setParentId(Long parentId)
+    {
+        this.parentId = parentId;
+    }
+
+    public String getAreaName()
+    {
+        return areaName;
+    }
+
+    public void setAreaName(String areaName)
+    {
+        this.areaName = areaName;
+    }
+
+    public String getAreaCode()
+    {
+        return areaCode;
+    }
+
+    public void setAreaCode(String areaCode)
+    {
+        this.areaCode = areaCode;
+    }
+
+    public String getSimplePy()
+    {
+        return simplePy;
+    }
+
+    public void setSimplePy(String simplePy)
+    {
+        this.simplePy = simplePy;
+    }
+
+    public String getPinYin()
+    {
+        return pinYin;
+    }
+
+    public void setPinYin(String pinYin)
+    {
+        this.pinYin = pinYin;
+    }
+
+    public Integer getIsTreeLeaf()
+    {
+        return isTreeLeaf;
+    }
+
+    public void setIsTreeLeaf(Integer isTreeLeaf)
+    {
+        this.isTreeLeaf = isTreeLeaf;
+    }
+}
+
+class DocumentModel
+{
+    /** 编号 */
+    private int tableId;
+
+    /** 档号 */
+    private String archiveNo;
+
+    /** 文件编号 */
+    private String docNo;
+
+    /** 标题 */
+    private String title;
+
+    /** 内容 */
+    private String content;
+
+    public DocumentModel()
+    {
+
+    }
+
+    public DocumentModel(int tableId, String archiveNo, String docNo, String title, String content)
+    {
+        this.tableId = tableId;
+        this.archiveNo = archiveNo;
+        this.docNo = docNo;
+        this.title = title;
+        this.content = content;
+    }
+
+    public int getTableId()
+    {
+        return tableId;
+    }
+
+    public String getArchiveNo()
+    {
+        return archiveNo;
+    }
+
+    public String getDocNo()
+    {
+        return docNo;
+    }
+
+    public String getTitle()
+    {
+        return title;
+    }
+
+    public String getContent()
+    {
+        return content;
+    }
+
+    public void setTableId(int tableId)
+    {
+        this.tableId = tableId;
+    }
+
+    public void setArchiveNo(String archiveNo)
+    {
+        this.archiveNo = archiveNo;
+    }
+
+    public void setDocNo(String docNo)
+    {
+        this.docNo = docNo;
+    }
+
+    public void setTitle(String title)
+    {
+        this.title = title;
+    }
+
+    public void setContent(String content)
+    {
+        this.content = content;
+    }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/demo/domain/CustomerModel.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/demo/domain/CustomerModel.java
new file mode 100644
index 0000000..5e7d6e5
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/demo/domain/CustomerModel.java
@@ -0,0 +1,116 @@
+package com.ruoyi.web.controller.demo.domain;
+
+import java.util.List;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+/**
+ * 客户测试信息
+ * 
+ * @author ruoyi
+ */
+public class CustomerModel
+{
+    /**
+     * 客户姓名
+     */
+    private String name;
+
+    /**
+     * 客户手机
+     */
+    private String phonenumber;
+
+    /**
+     * 客户性别
+     */
+    private String sex;
+
+    /**
+     * 客户生日
+     */
+    private String birthday;
+
+    /**
+     * 客户描述
+     */
+    private String remark;
+
+    /**
+     * 商品信息
+     */
+    private List<GoodsModel> goods;
+
+    public String getName()
+    {
+        return name;
+    }
+
+    public void setName(String name)
+    {
+        this.name = name;
+    }
+
+    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 getBirthday()
+    {
+        return birthday;
+    }
+
+    public void setBirthday(String birthday)
+    {
+        this.birthday = birthday;
+    }
+
+    public String getRemark()
+    {
+        return remark;
+    }
+
+    public void setRemark(String remark)
+    {
+        this.remark = remark;
+    }
+
+    public List<GoodsModel> getGoods()
+    {
+        return goods;
+    }
+
+    public void setGoods(List<GoodsModel> goods)
+    {
+        this.goods = goods;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("name", getName())
+            .append("phonenumber", getPhonenumber())
+            .append("sex", getSex())
+            .append("birthday", getBirthday())
+            .append("goods", getGoods())
+            .append("remark", getRemark())
+            .toString();
+    }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/demo/domain/GoodsModel.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/demo/domain/GoodsModel.java
new file mode 100644
index 0000000..b25542a
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/demo/domain/GoodsModel.java
@@ -0,0 +1,99 @@
+package com.ruoyi.web.controller.demo.domain;
+
+import java.util.Date;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+/**
+ * 商品测试信息
+ * 
+ * @author ruoyi
+ */
+public class GoodsModel
+{
+    /**
+     * 商品名称
+     */
+    private String name;
+
+    /**
+     * 商品重量
+     */
+    private Integer weight;
+
+    /**
+     * 商品价格
+     */
+    private Double price;
+    
+    /**
+     * 商品日期
+     */
+    private Date date;
+
+    /**
+     * 商品种类
+     */
+    private String type;
+
+    public String getName()
+    {
+        return name;
+    }
+
+    public void setName(String name)
+    {
+        this.name = name;
+    }
+
+    public Integer getWeight()
+    {
+        return weight;
+    }
+
+    public void setWeight(Integer weight)
+    {
+        this.weight = weight;
+    }
+
+    public Double getPrice()
+    {
+        return price;
+    }
+
+    public void setPrice(Double price)
+    {
+        this.price = price;
+    }
+
+    public Date getDate()
+    {
+        return date;
+    }
+
+    public void setDate(Date date)
+    {
+        this.date = date;
+    }
+
+    public String getType()
+    {
+        return type;
+    }
+
+    public void setType(String type)
+    {
+        this.type = type;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("name", getName())
+            .append("weight", getWeight())
+            .append("price", getPrice())
+            .append("date", getDate())
+            .append("type", getType())
+            .toString();
+    }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/demo/domain/UserOperateModel.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/demo/domain/UserOperateModel.java
new file mode 100644
index 0000000..8b158aa
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/demo/domain/UserOperateModel.java
@@ -0,0 +1,149 @@
+package com.ruoyi.web.controller.demo.domain;
+
+import java.util.Date;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.annotation.Excel.Type;
+import com.ruoyi.common.core.domain.BaseEntity;
+import com.ruoyi.common.utils.DateUtils;
+
+public class UserOperateModel extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    private int userId;
+
+    @Excel(name = "用户编号")
+    private String userCode;
+
+    @Excel(name = "用户姓名")
+    private String userName;
+
+    @Excel(name = "用户性别", readConverterExp = "0=男,1=女,2=未知")
+    private String userSex;
+
+    @Excel(name = "用户手机")
+    private String userPhone;
+
+    @Excel(name = "用户邮箱")
+    private String userEmail;
+
+    @Excel(name = "用户余额")
+    private double userBalance;
+
+    @Excel(name = "用户状态", readConverterExp = "0=正常,1=停用")
+    private String status;
+
+    @Excel(name = "创建时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT)
+    private Date createTime;
+
+    public UserOperateModel()
+    {
+
+    }
+
+    public UserOperateModel(int userId, String userCode, String userName, String userSex, String userPhone,
+            String userEmail, double userBalance, String status)
+    {
+        this.userId = userId;
+        this.userCode = userCode;
+        this.userName = userName;
+        this.userSex = userSex;
+        this.userPhone = userPhone;
+        this.userEmail = userEmail;
+        this.userBalance = userBalance;
+        this.status = status;
+        this.createTime = DateUtils.getNowDate();
+    }
+
+    public int getUserId()
+    {
+        return userId;
+    }
+
+    public void setUserId(int userId)
+    {
+        this.userId = userId;
+    }
+
+    public String getUserCode()
+    {
+        return userCode;
+    }
+
+    public void setUserCode(String userCode)
+    {
+        this.userCode = userCode;
+    }
+
+    public String getUserName()
+    {
+        return userName;
+    }
+
+    public void setUserName(String userName)
+    {
+        this.userName = userName;
+    }
+
+    public String getUserSex()
+    {
+        return userSex;
+    }
+
+    public void setUserSex(String userSex)
+    {
+        this.userSex = userSex;
+    }
+
+    public String getUserPhone()
+    {
+        return userPhone;
+    }
+
+    public void setUserPhone(String userPhone)
+    {
+        this.userPhone = userPhone;
+    }
+
+    public String getUserEmail()
+    {
+        return userEmail;
+    }
+
+    public void setUserEmail(String userEmail)
+    {
+        this.userEmail = userEmail;
+    }
+
+    public double getUserBalance()
+    {
+        return userBalance;
+    }
+
+    public void setUserBalance(double userBalance)
+    {
+        this.userBalance = userBalance;
+    }
+
+    public String getStatus()
+    {
+        return status;
+    }
+
+    public void setStatus(String status)
+    {
+        this.status = status;
+    }
+
+    @Override
+    public Date getCreateTime()
+    {
+        return createTime;
+    }
+
+    @Override
+    public void setCreateTime(Date createTime)
+    {
+        this.createTime = createTime;
+    }
+}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java
new file mode 100644
index 0000000..baeb2b8
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java
@@ -0,0 +1,90 @@
+package com.ruoyi.web.controller.monitor;
+
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+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.ResponseBody;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.framework.web.service.CacheService;
+
+/**
+ * 缓存监控
+ * 
+ * @author ruoyi
+ */
+@Controller
+@RequestMapping("/monitor/cache")
+public class CacheController extends BaseController
+{
+    private String prefix = "monitor/cache";
+
+    @Autowired
+    private CacheService cacheService;
+
+    @RequiresPermissions("monitor:cache:view")
+    @GetMapping()
+    public String cache(ModelMap mmap)
+    {
+        mmap.put("cacheNames", cacheService.getCacheNames());
+        return prefix + "/cache";
+    }
+
+    @RequiresPermissions("monitor:cache:view")
+    @PostMapping("/getNames")
+    public String getCacheNames(String fragment, ModelMap mmap)
+    {
+        mmap.put("cacheNames", cacheService.getCacheNames());
+        return prefix + "/cache::" + fragment;
+    }
+
+    @RequiresPermissions("monitor:cache:view")
+    @PostMapping("/getKeys")
+    public String getCacheKeys(String fragment, String cacheName, ModelMap mmap)
+    {
+        mmap.put("cacheName", cacheName);
+        mmap.put("cacheKeys", cacheService.getCacheKeys(cacheName));
+        return prefix + "/cache::" + fragment;
+    }
+
+    @RequiresPermissions("monitor:cache:view")
+    @PostMapping("/getValue")
+    public String getCacheValue(String fragment, String cacheName, String cacheKey, ModelMap mmap)
+    {
+        mmap.put("cacheName", cacheName);
+        mmap.put("cacheKey", cacheKey);
+        mmap.put("cacheValue", cacheService.getCacheValue(cacheName, cacheKey));
+        return prefix + "/cache::" + fragment;
+    }
+
+    @RequiresPermissions("monitor:cache:view")
+    @PostMapping("/clearCacheName")
+    @ResponseBody
+    public AjaxResult clearCacheName(String cacheName, ModelMap mmap)
+    {
+        cacheService.clearCacheName(cacheName);
+        return AjaxResult.success();
+    }
+
+    @RequiresPermissions("monitor:cache:view")
+    @PostMapping("/clearCacheKey")
+    @ResponseBody
+    public AjaxResult clearCacheKey(String cacheName, String cacheKey, ModelMap mmap)
+    {
+        cacheService.clearCacheKey(cacheName, cacheKey);
+        return AjaxResult.success();
+    }
+
+    @RequiresPermissions("monitor:cache:view")
+    @GetMapping("/clearAll")
+    @ResponseBody
+    public AjaxResult clearAll(ModelMap mmap)
+    {
+        cacheService.clearAll();
+        return AjaxResult.success();
+    }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/DruidController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/DruidController.java
new file mode 100644
index 0000000..a51bf20
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/DruidController.java
@@ -0,0 +1,26 @@
+package com.ruoyi.web.controller.monitor;
+
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import com.ruoyi.common.core.controller.BaseController;
+
+/**
+ * druid 监控
+ * 
+ * @author ruoyi
+ */
+@Controller
+@RequestMapping("/monitor/data")
+public class DruidController extends BaseController
+{
+    private String prefix = "/druid";
+
+    @RequiresPermissions("monitor:data:view")
+    @GetMapping()
+    public String index()
+    {
+        return redirect(prefix + "/index.html");
+    }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/ServerController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/ServerController.java
new file mode 100644
index 0000000..386b5c7
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/ServerController.java
@@ -0,0 +1,31 @@
+package com.ruoyi.web.controller.monitor;
+
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.framework.web.domain.Server;
+
+/**
+ * 服务器监控
+ * 
+ * @author ruoyi
+ */
+@Controller
+@RequestMapping("/monitor/server")
+public class ServerController extends BaseController
+{
+    private String prefix = "monitor/server";
+
+    @RequiresPermissions("monitor:server:view")
+    @GetMapping()
+    public String server(ModelMap mmap) throws Exception
+    {
+        Server server = new Server();
+        server.copyTo();
+        mmap.put("server", server);
+        return prefix + "/server";
+    }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java
new file mode 100644
index 0000000..0d30e42
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java
@@ -0,0 +1,94 @@
+package com.ruoyi.web.controller.monitor;
+
+import java.util.List;
+import com.ruoyi.framework.shiro.service.SysPasswordService;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+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.ResponseBody;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.system.domain.SysLogininfor;
+import com.ruoyi.system.service.ISysLogininforService;
+
+/**
+ * 系统访问记录
+ * 
+ * @author ruoyi
+ */
+@Controller
+@RequestMapping("/monitor/logininfor")
+public class SysLogininforController extends BaseController
+{
+    private String prefix = "monitor/logininfor";
+
+    @Autowired
+    private ISysLogininforService logininforService;
+
+    @Autowired
+    private SysPasswordService passwordService;
+
+    @RequiresPermissions("monitor:logininfor:view")
+    @GetMapping()
+    public String logininfor()
+    {
+        return prefix + "/logininfor";
+    }
+
+    @RequiresPermissions("monitor:logininfor:list")
+    @PostMapping("/list")
+    @ResponseBody
+    public TableDataInfo list(SysLogininfor logininfor)
+    {
+        startPage();
+        List<SysLogininfor> list = logininforService.selectLogininforList(logininfor);
+        return getDataTable(list);
+    }
+
+    @Log(title = "登录日志", businessType = BusinessType.EXPORT)
+    @RequiresPermissions("monitor:logininfor:export")
+    @PostMapping("/export")
+    @ResponseBody
+    public AjaxResult export(SysLogininfor logininfor)
+    {
+        List<SysLogininfor> list = logininforService.selectLogininforList(logininfor);
+        ExcelUtil<SysLogininfor> util = new ExcelUtil<SysLogininfor>(SysLogininfor.class);
+        return util.exportExcel(list, "登录日志");
+    }
+
+    @RequiresPermissions("monitor:logininfor:remove")
+    @Log(title = "登录日志", businessType = BusinessType.DELETE)
+    @PostMapping("/remove")
+    @ResponseBody
+    public AjaxResult remove(String ids)
+    {
+        return toAjax(logininforService.deleteLogininforByIds(ids));
+    }
+    
+    @RequiresPermissions("monitor:logininfor:remove")
+    @Log(title = "登录日志", businessType = BusinessType.CLEAN)
+    @PostMapping("/clean")
+    @ResponseBody
+    public AjaxResult clean()
+    {
+        logininforService.cleanLogininfor();
+        return success();
+    }
+
+    @RequiresPermissions("monitor:logininfor:unlock")
+    @Log(title = "账户解锁", businessType = BusinessType.OTHER)
+    @PostMapping("/unlock")
+    @ResponseBody
+    public AjaxResult unlock(String loginName)
+    {
+        passwordService.clearLoginRecordCache(loginName);
+        return success();
+    }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java
new file mode 100644
index 0000000..cddd972
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java
@@ -0,0 +1,90 @@
+package com.ruoyi.web.controller.monitor;
+
+import java.util.List;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+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.ResponseBody;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.system.domain.SysOperLog;
+import com.ruoyi.system.service.ISysOperLogService;
+
+/**
+ * 操作日志记录
+ * 
+ * @author ruoyi
+ */
+@Controller
+@RequestMapping("/monitor/operlog")
+public class SysOperlogController extends BaseController
+{
+    private String prefix = "monitor/operlog";
+
+    @Autowired
+    private ISysOperLogService operLogService;
+
+    @RequiresPermissions("monitor:operlog:view")
+    @GetMapping()
+    public String operlog()
+    {
+        return prefix + "/operlog";
+    }
+
+    @RequiresPermissions("monitor:operlog:list")
+    @PostMapping("/list")
+    @ResponseBody
+    public TableDataInfo list(SysOperLog operLog)
+    {
+        startPage();
+        List<SysOperLog> list = operLogService.selectOperLogList(operLog);
+        return getDataTable(list);
+    }
+
+    @Log(title = "操作日志", businessType = BusinessType.EXPORT)
+    @RequiresPermissions("monitor:operlog:export")
+    @PostMapping("/export")
+    @ResponseBody
+    public AjaxResult export(SysOperLog operLog)
+    {
+        List<SysOperLog> list = operLogService.selectOperLogList(operLog);
+        ExcelUtil<SysOperLog> util = new ExcelUtil<SysOperLog>(SysOperLog.class);
+        return util.exportExcel(list, "操作日志");
+    }
+
+    @Log(title = "操作日志", businessType = BusinessType.DELETE)
+    @RequiresPermissions("monitor:operlog:remove")
+    @PostMapping("/remove")
+    @ResponseBody
+    public AjaxResult remove(String ids)
+    {
+        return toAjax(operLogService.deleteOperLogByIds(ids));
+    }
+
+    @RequiresPermissions("monitor:operlog:detail")
+    @GetMapping("/detail/{operId}")
+    public String detail(@PathVariable("operId") Long operId, ModelMap mmap)
+    {
+        mmap.put("operLog", operLogService.selectOperLogById(operId));
+        return prefix + "/detail";
+    }
+    
+    @Log(title = "操作日志", businessType = BusinessType.CLEAN)
+    @RequiresPermissions("monitor:operlog:remove")
+    @PostMapping("/clean")
+    @ResponseBody
+    public AjaxResult clean()
+    {
+        operLogService.cleanOperLog();
+        return success();
+    }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java
new file mode 100644
index 0000000..19435e9
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java
@@ -0,0 +1,88 @@
+package com.ruoyi.web.controller.monitor;
+
+import java.util.List;
+import org.apache.shiro.authz.annotation.Logical;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+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.ResponseBody;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.core.text.Convert;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.enums.OnlineStatus;
+import com.ruoyi.common.utils.ShiroUtils;
+import com.ruoyi.framework.shiro.session.OnlineSession;
+import com.ruoyi.framework.shiro.session.OnlineSessionDAO;
+import com.ruoyi.system.domain.SysUserOnline;
+import com.ruoyi.system.service.ISysUserOnlineService;
+
+/**
+ * 在线用户监控
+ * 
+ * @author ruoyi
+ */
+@Controller
+@RequestMapping("/monitor/online")
+public class SysUserOnlineController extends BaseController
+{
+    private String prefix = "monitor/online";
+
+    @Autowired
+    private ISysUserOnlineService userOnlineService;
+
+    @Autowired
+    private OnlineSessionDAO onlineSessionDAO;
+
+    @RequiresPermissions("monitor:online:view")
+    @GetMapping()
+    public String online()
+    {
+        return prefix + "/online";
+    }
+
+    @RequiresPermissions("monitor:online:list")
+    @PostMapping("/list")
+    @ResponseBody
+    public TableDataInfo list(SysUserOnline userOnline)
+    {
+        startPage();
+        List<SysUserOnline> list = userOnlineService.selectUserOnlineList(userOnline);
+        return getDataTable(list);
+    }
+
+    @RequiresPermissions(value = { "monitor:online:batchForceLogout", "monitor:online:forceLogout" }, logical = Logical.OR)
+    @Log(title = "在线用户", businessType = BusinessType.FORCE)
+    @PostMapping("/batchForceLogout")
+    @ResponseBody
+    public AjaxResult batchForceLogout(String ids)
+    {
+        for (String sessionId : Convert.toStrArray(ids))
+        {
+            SysUserOnline online = userOnlineService.selectOnlineById(sessionId);
+            if (online == null)
+            {
+                return error("用户已下线");
+            }
+            OnlineSession onlineSession = (OnlineSession) onlineSessionDAO.readSession(online.getSessionId());
+            if (onlineSession == null)
+            {
+                return error("用户已下线");
+            }
+            if (sessionId.equals(ShiroUtils.getSessionId()))
+            {
+                return error("当前登录用户无法强退");
+            }
+            onlineSessionDAO.delete(onlineSession);
+            online.setStatus(OnlineStatus.off_line);
+            userOnlineService.saveOnline(online);
+            userOnlineService.removeUserCache(online.getLoginName(), sessionId);
+        }
+        return success();
+    }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysCaptchaController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysCaptchaController.java
new file mode 100644
index 0000000..739c469
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysCaptchaController.java
@@ -0,0 +1,92 @@
+package com.ruoyi.web.controller.system;
+
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import javax.annotation.Resource;
+import javax.imageio.ImageIO;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.servlet.ModelAndView;
+import com.google.code.kaptcha.Constants;
+import com.google.code.kaptcha.Producer;
+import com.ruoyi.common.core.controller.BaseController;
+
+/**
+ * 图片验证码(支持算术形式)
+ * 
+ * @author ruoyi
+ */
+@Controller
+@RequestMapping("/captcha")
+public class SysCaptchaController extends BaseController
+{
+    @Resource(name = "captchaProducer")
+    private Producer captchaProducer;
+
+    @Resource(name = "captchaProducerMath")
+    private Producer captchaProducerMath;
+
+    /**
+     * 验证码生成
+     */
+    @GetMapping(value = "/captchaImage")
+    public ModelAndView getKaptchaImage(HttpServletRequest request, HttpServletResponse response)
+    {
+        ServletOutputStream out = null;
+        try
+        {
+            HttpSession session = request.getSession();
+            response.setDateHeader("Expires", 0);
+            response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
+            response.addHeader("Cache-Control", "post-check=0, pre-check=0");
+            response.setHeader("Pragma", "no-cache");
+            response.setContentType("image/jpeg");
+
+            String type = request.getParameter("type");
+            String capStr = null;
+            String code = null;
+            BufferedImage bi = null;
+            if ("math".equals(type))
+            {
+                String capText = captchaProducerMath.createText();
+                capStr = capText.substring(0, capText.lastIndexOf("@"));
+                code = capText.substring(capText.lastIndexOf("@") + 1);
+                bi = captchaProducerMath.createImage(capStr);
+            }
+            else if ("char".equals(type))
+            {
+                capStr = code = captchaProducer.createText();
+                bi = captchaProducer.createImage(capStr);
+            }
+            session.setAttribute(Constants.KAPTCHA_SESSION_KEY, code);
+            out = response.getOutputStream();
+            ImageIO.write(bi, "jpg", out);
+            out.flush();
+
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+        finally
+        {
+            try
+            {
+                if (out != null)
+                {
+                    out.close();
+                }
+            }
+            catch (IOException e)
+            {
+                e.printStackTrace();
+            }
+        }
+        return null;
+    }
+}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java
new file mode 100644
index 0000000..6a2adda
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java
@@ -0,0 +1,158 @@
+package com.ruoyi.web.controller.system;
+
+import java.util.List;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+import org.springframework.validation.annotation.Validated;
+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.ResponseBody;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.system.domain.SysConfig;
+import com.ruoyi.system.service.ISysConfigService;
+
+/**
+ * 参数配置 信息操作处理
+ * 
+ * @author ruoyi
+ */
+@Controller
+@RequestMapping("/system/config")
+public class SysConfigController extends BaseController
+{
+    private String prefix = "system/config";
+
+    @Autowired
+    private ISysConfigService configService;
+
+    @RequiresPermissions("system:config:view")
+    @GetMapping()
+    public String config()
+    {
+        return prefix + "/config";
+    }
+
+    /**
+     * 查询参数配置列表
+     */
+    @RequiresPermissions("system:config:list")
+    @PostMapping("/list")
+    @ResponseBody
+    public TableDataInfo list(SysConfig config)
+    {
+        startPage();
+        List<SysConfig> list = configService.selectConfigList(config);
+        return getDataTable(list);
+    }
+
+    @Log(title = "参数管理", businessType = BusinessType.EXPORT)
+    @RequiresPermissions("system:config:export")
+    @PostMapping("/export")
+    @ResponseBody
+    public AjaxResult export(SysConfig config)
+    {
+        List<SysConfig> list = configService.selectConfigList(config);
+        ExcelUtil<SysConfig> util = new ExcelUtil<SysConfig>(SysConfig.class);
+        return util.exportExcel(list, "参数数据");
+    }
+
+    /**
+     * 新增参数配置
+     */
+    @RequiresPermissions("system:config:add")
+    @GetMapping("/add")
+    public String add()
+    {
+        return prefix + "/add";
+    }
+
+    /**
+     * 新增保存参数配置
+     */
+    @RequiresPermissions("system:config:add")
+    @Log(title = "参数管理", businessType = BusinessType.INSERT)
+    @PostMapping("/add")
+    @ResponseBody
+    public AjaxResult addSave(@Validated SysConfig config)
+    {
+        if (!configService.checkConfigKeyUnique(config))
+        {
+            return error("新增参数'" + config.getConfigName() + "'失败,参数键名已存在");
+        }
+        config.setCreateBy(getLoginName());
+        return toAjax(configService.insertConfig(config));
+    }
+
+    /**
+     * 修改参数配置
+     */
+    @RequiresPermissions("system:config:edit")
+    @GetMapping("/edit/{configId}")
+    public String edit(@PathVariable("configId") Long configId, ModelMap mmap)
+    {
+        mmap.put("config", configService.selectConfigById(configId));
+        return prefix + "/edit";
+    }
+
+    /**
+     * 修改保存参数配置
+     */
+    @RequiresPermissions("system:config:edit")
+    @Log(title = "参数管理", businessType = BusinessType.UPDATE)
+    @PostMapping("/edit")
+    @ResponseBody
+    public AjaxResult editSave(@Validated SysConfig config)
+    {
+        if (!configService.checkConfigKeyUnique(config))
+        {
+            return error("修改参数'" + config.getConfigName() + "'失败,参数键名已存在");
+        }
+        config.setUpdateBy(getLoginName());
+        return toAjax(configService.updateConfig(config));
+    }
+
+    /**
+     * 删除参数配置
+     */
+    @RequiresPermissions("system:config:remove")
+    @Log(title = "参数管理", businessType = BusinessType.DELETE)
+    @PostMapping("/remove")
+    @ResponseBody
+    public AjaxResult remove(String ids)
+    {
+        configService.deleteConfigByIds(ids);
+        return success();
+    }
+
+    /**
+     * 刷新参数缓存
+     */
+    @RequiresPermissions("system:config:remove")
+    @Log(title = "参数管理", businessType = BusinessType.CLEAN)
+    @GetMapping("/refreshCache")
+    @ResponseBody
+    public AjaxResult refreshCache()
+    {
+        configService.resetConfigCache();
+        return success();
+    }
+
+    /**
+     * 校验参数键名
+     */
+    @PostMapping("/checkConfigKeyUnique")
+    @ResponseBody
+    public boolean checkConfigKeyUnique(SysConfig config)
+    {
+        return configService.checkConfigKeyUnique(config);
+    }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java
new file mode 100644
index 0000000..c842fe5
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java
@@ -0,0 +1,189 @@
+package com.ruoyi.web.controller.system;
+
+import java.util.List;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+import org.springframework.validation.annotation.Validated;
+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.ResponseBody;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.constant.UserConstants;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.Ztree;
+import com.ruoyi.common.core.domain.entity.SysDept;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.system.service.ISysDeptService;
+
+/**
+ * 部门信息
+ * 
+ * @author ruoyi
+ */
+@Controller
+@RequestMapping("/system/dept")
+public class SysDeptController extends BaseController
+{
+    private String prefix = "system/dept";
+
+    @Autowired
+    private ISysDeptService deptService;
+
+    @RequiresPermissions("system:dept:view")
+    @GetMapping()
+    public String dept()
+    {
+        return prefix + "/dept";
+    }
+
+    @RequiresPermissions("system:dept:list")
+    @PostMapping("/list")
+    @ResponseBody
+    public List<SysDept> list(SysDept dept)
+    {
+        List<SysDept> deptList = deptService.selectDeptList(dept);
+        return deptList;
+    }
+
+    /**
+     * 新增部门
+     */
+    @RequiresPermissions("system:dept:add")
+    @GetMapping("/add/{parentId}")
+    public String add(@PathVariable("parentId") Long parentId, ModelMap mmap)
+    {
+        if (!getSysUser().isAdmin())
+        {
+            parentId = getSysUser().getDeptId();
+        }
+        mmap.put("dept", deptService.selectDeptById(parentId));
+        return prefix + "/add";
+    }
+
+    /**
+     * 新增保存部门
+     */
+    @Log(title = "部门管理", businessType = BusinessType.INSERT)
+    @RequiresPermissions("system:dept:add")
+    @PostMapping("/add")
+    @ResponseBody
+    public AjaxResult addSave(@Validated SysDept dept)
+    {
+        if (!deptService.checkDeptNameUnique(dept))
+        {
+            return error("新增部门'" + dept.getDeptName() + "'失败,部门名称已存在");
+        }
+        dept.setCreateBy(getLoginName());
+        return toAjax(deptService.insertDept(dept));
+    }
+
+    /**
+     * 修改部门
+     */
+    @RequiresPermissions("system:dept:edit")
+    @GetMapping("/edit/{deptId}")
+    public String edit(@PathVariable("deptId") Long deptId, ModelMap mmap)
+    {
+        deptService.checkDeptDataScope(deptId);
+        SysDept dept = deptService.selectDeptById(deptId);
+        if (StringUtils.isNotNull(dept) && 100L == deptId)
+        {
+            dept.setParentName("无");
+        }
+        mmap.put("dept", dept);
+        return prefix + "/edit";
+    }
+
+    /**
+     * 修改保存部门
+     */
+    @Log(title = "部门管理", businessType = BusinessType.UPDATE)
+    @RequiresPermissions("system:dept:edit")
+    @PostMapping("/edit")
+    @ResponseBody
+    public AjaxResult editSave(@Validated 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 AjaxResult.error("该部门包含未停用的子部门!");
+        }
+        dept.setUpdateBy(getLoginName());
+        return toAjax(deptService.updateDept(dept));
+    }
+
+    /**
+     * 删除
+     */
+    @Log(title = "部门管理", businessType = BusinessType.DELETE)
+    @RequiresPermissions("system:dept:remove")
+    @GetMapping("/remove/{deptId}")
+    @ResponseBody
+    public AjaxResult remove(@PathVariable("deptId") Long deptId)
+    {
+        if (deptService.selectDeptCount(deptId) > 0)
+        {
+            return AjaxResult.warn("存在下级部门,不允许删除");
+        }
+        if (deptService.checkDeptExistUser(deptId))
+        {
+            return AjaxResult.warn("部门存在用户,不允许删除");
+        }
+        deptService.checkDeptDataScope(deptId);
+        return toAjax(deptService.deleteDeptById(deptId));
+    }
+
+    /**
+     * 校验部门名称
+     */
+    @PostMapping("/checkDeptNameUnique")
+    @ResponseBody
+    public boolean checkDeptNameUnique(SysDept dept)
+    {
+        return deptService.checkDeptNameUnique(dept);
+    }
+
+    /**
+     * 选择部门树
+     * 
+     * @param deptId 部门ID
+     * @param excludeId 排除ID
+     */
+    @RequiresPermissions("system:dept:list")
+    @GetMapping(value = { "/selectDeptTree/{deptId}", "/selectDeptTree/{deptId}/{excludeId}" })
+    public String selectDeptTree(@PathVariable("deptId") Long deptId, @PathVariable(value = "excludeId", required = false) Long excludeId, ModelMap mmap)
+    {
+        mmap.put("dept", deptService.selectDeptById(deptId));
+        mmap.put("excludeId", excludeId);
+        return prefix + "/tree";
+    }
+
+    /**
+     * 加载部门列表树(排除下级)
+     */
+    @RequiresPermissions("system:dept:list")
+    @GetMapping("/treeData/{excludeId}")
+    @ResponseBody
+    public List<Ztree> treeDataExcludeChild(@PathVariable(value = "excludeId", required = false) Long excludeId)
+    {
+        SysDept dept = new SysDept();
+        dept.setExcludeId(excludeId);
+        List<Ztree> ztrees = deptService.selectDeptTreeExcludeChild(dept);
+        return ztrees;
+    }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java
new file mode 100644
index 0000000..36ab009
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java
@@ -0,0 +1,122 @@
+package com.ruoyi.web.controller.system;
+
+import java.util.List;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+import org.springframework.validation.annotation.Validated;
+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.ResponseBody;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.entity.SysDictData;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.system.service.ISysDictDataService;
+
+/**
+ * 数据字典信息
+ * 
+ * @author ruoyi
+ */
+@Controller
+@RequestMapping("/system/dict/data")
+public class SysDictDataController extends BaseController
+{
+    private String prefix = "system/dict/data";
+
+    @Autowired
+    private ISysDictDataService dictDataService;
+
+    @RequiresPermissions("system:dict:view")
+    @GetMapping()
+    public String dictData()
+    {
+        return prefix + "/data";
+    }
+
+    @PostMapping("/list")
+    @RequiresPermissions("system:dict:list")
+    @ResponseBody
+    public TableDataInfo list(SysDictData dictData)
+    {
+        startPage();
+        List<SysDictData> list = dictDataService.selectDictDataList(dictData);
+        return getDataTable(list);
+    }
+
+    @Log(title = "字典数据", businessType = BusinessType.EXPORT)
+    @RequiresPermissions("system:dict:export")
+    @PostMapping("/export")
+    @ResponseBody
+    public AjaxResult export(SysDictData dictData)
+    {
+        List<SysDictData> list = dictDataService.selectDictDataList(dictData);
+        ExcelUtil<SysDictData> util = new ExcelUtil<SysDictData>(SysDictData.class);
+        return util.exportExcel(list, "字典数据");
+    }
+
+    /**
+     * 新增字典类型
+     */
+    @RequiresPermissions("system:dict:add")
+    @GetMapping("/add/{dictType}")
+    public String add(@PathVariable("dictType") String dictType, ModelMap mmap)
+    {
+        mmap.put("dictType", dictType);
+        return prefix + "/add";
+    }
+
+    /**
+     * 新增保存字典类型
+     */
+    @Log(title = "字典数据", businessType = BusinessType.INSERT)
+    @RequiresPermissions("system:dict:add")
+    @PostMapping("/add")
+    @ResponseBody
+    public AjaxResult addSave(@Validated SysDictData dict)
+    {
+        dict.setCreateBy(getLoginName());
+        return toAjax(dictDataService.insertDictData(dict));
+    }
+
+    /**
+     * 修改字典类型
+     */
+    @RequiresPermissions("system:dict:edit")
+    @GetMapping("/edit/{dictCode}")
+    public String edit(@PathVariable("dictCode") Long dictCode, ModelMap mmap)
+    {
+        mmap.put("dict", dictDataService.selectDictDataById(dictCode));
+        return prefix + "/edit";
+    }
+
+    /**
+     * 修改保存字典类型
+     */
+    @Log(title = "字典数据", businessType = BusinessType.UPDATE)
+    @RequiresPermissions("system:dict:edit")
+    @PostMapping("/edit")
+    @ResponseBody
+    public AjaxResult editSave(@Validated SysDictData dict)
+    {
+        dict.setUpdateBy(getLoginName());
+        return toAjax(dictDataService.updateDictData(dict));
+    }
+
+    @Log(title = "字典数据", businessType = BusinessType.DELETE)
+    @RequiresPermissions("system:dict:remove")
+    @PostMapping("/remove")
+    @ResponseBody
+    public AjaxResult remove(String ids)
+    {
+        dictDataService.deleteDictDataByIds(ids);
+        return success();
+    }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java
new file mode 100644
index 0000000..495116b
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java
@@ -0,0 +1,188 @@
+package com.ruoyi.web.controller.system;
+
+import java.util.List;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+import org.springframework.validation.annotation.Validated;
+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.ResponseBody;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.Ztree;
+import com.ruoyi.common.core.domain.entity.SysDictType;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.system.service.ISysDictTypeService;
+
+/**
+ * 数据字典信息
+ * 
+ * @author ruoyi
+ */
+@Controller
+@RequestMapping("/system/dict")
+public class SysDictTypeController extends BaseController
+{
+    private String prefix = "system/dict/type";
+
+    @Autowired
+    private ISysDictTypeService dictTypeService;
+
+    @RequiresPermissions("system:dict:view")
+    @GetMapping()
+    public String dictType()
+    {
+        return prefix + "/type";
+    }
+
+    @PostMapping("/list")
+    @RequiresPermissions("system:dict:list")
+    @ResponseBody
+    public TableDataInfo list(SysDictType dictType)
+    {
+        startPage();
+        List<SysDictType> list = dictTypeService.selectDictTypeList(dictType);
+        return getDataTable(list);
+    }
+
+    @Log(title = "字典类型", businessType = BusinessType.EXPORT)
+    @RequiresPermissions("system:dict:export")
+    @PostMapping("/export")
+    @ResponseBody
+    public AjaxResult export(SysDictType dictType)
+    {
+
+        List<SysDictType> list = dictTypeService.selectDictTypeList(dictType);
+        ExcelUtil<SysDictType> util = new ExcelUtil<SysDictType>(SysDictType.class);
+        return util.exportExcel(list, "字典类型");
+    }
+
+    /**
+     * 新增字典类型
+     */
+    @RequiresPermissions("system:dict:add")
+    @GetMapping("/add")
+    public String add()
+    {
+        return prefix + "/add";
+    }
+
+    /**
+     * 新增保存字典类型
+     */
+    @Log(title = "字典类型", businessType = BusinessType.INSERT)
+    @RequiresPermissions("system:dict:add")
+    @PostMapping("/add")
+    @ResponseBody
+    public AjaxResult addSave(@Validated SysDictType dict)
+    {
+        if (!dictTypeService.checkDictTypeUnique(dict))
+        {
+            return error("新增字典'" + dict.getDictName() + "'失败,字典类型已存在");
+        }
+        dict.setCreateBy(getLoginName());
+        return toAjax(dictTypeService.insertDictType(dict));
+    }
+
+    /**
+     * 修改字典类型
+     */
+    @RequiresPermissions("system:dict:edit")
+    @GetMapping("/edit/{dictId}")
+    public String edit(@PathVariable("dictId") Long dictId, ModelMap mmap)
+    {
+        mmap.put("dict", dictTypeService.selectDictTypeById(dictId));
+        return prefix + "/edit";
+    }
+
+    /**
+     * 修改保存字典类型
+     */
+    @Log(title = "字典类型", businessType = BusinessType.UPDATE)
+    @RequiresPermissions("system:dict:edit")
+    @PostMapping("/edit")
+    @ResponseBody
+    public AjaxResult editSave(@Validated SysDictType dict)
+    {
+        if (!dictTypeService.checkDictTypeUnique(dict))
+        {
+            return error("修改字典'" + dict.getDictName() + "'失败,字典类型已存在");
+        }
+        dict.setUpdateBy(getLoginName());
+        return toAjax(dictTypeService.updateDictType(dict));
+    }
+
+    @Log(title = "字典类型", businessType = BusinessType.DELETE)
+    @RequiresPermissions("system:dict:remove")
+    @PostMapping("/remove")
+    @ResponseBody
+    public AjaxResult remove(String ids)
+    {
+        dictTypeService.deleteDictTypeByIds(ids);
+        return success();
+    }
+
+    /**
+     * 刷新字典缓存
+     */
+    @RequiresPermissions("system:dict:remove")
+    @Log(title = "字典类型", businessType = BusinessType.CLEAN)
+    @GetMapping("/refreshCache")
+    @ResponseBody
+    public AjaxResult refreshCache()
+    {
+        dictTypeService.resetDictCache();
+        return success();
+    }
+
+    /**
+     * 查询字典详细
+     */
+    @RequiresPermissions("system:dict:list")
+    @GetMapping("/detail/{dictId}")
+    public String detail(@PathVariable("dictId") Long dictId, ModelMap mmap)
+    {
+        mmap.put("dict", dictTypeService.selectDictTypeById(dictId));
+        mmap.put("dictList", dictTypeService.selectDictTypeAll());
+        return "system/dict/data/data";
+    }
+
+    /**
+     * 校验字典类型
+     */
+    @PostMapping("/checkDictTypeUnique")
+    @ResponseBody
+    public boolean checkDictTypeUnique(SysDictType dictType)
+    {
+        return dictTypeService.checkDictTypeUnique(dictType);
+    }
+
+    /**
+     * 选择字典树
+     */
+    @GetMapping("/selectDictTree/{columnId}/{dictType}")
+    public String selectDeptTree(@PathVariable("columnId") Long columnId, @PathVariable("dictType") String dictType, ModelMap mmap)
+    {
+        mmap.put("columnId", columnId);
+        mmap.put("dict", dictTypeService.selectDictTypeByType(dictType));
+        return prefix + "/tree";
+    }
+
+    /**
+     * 加载字典列表树
+     */
+    @GetMapping("/treeData")
+    @ResponseBody
+    public List<Ztree> treeData()
+    {
+        List<Ztree> ztrees = dictTypeService.selectDictTree(new SysDictType());
+        return ztrees;
+    }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysIndexController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysIndexController.java
new file mode 100644
index 0000000..667fea5
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysIndexController.java
@@ -0,0 +1,178 @@
+package com.ruoyi.web.controller.system;
+
+import java.util.Date;
+import java.util.List;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+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.ResponseBody;
+import com.ruoyi.common.config.RuoYiConfig;
+import com.ruoyi.common.constant.ShiroConstants;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.entity.SysMenu;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.core.text.Convert;
+import com.ruoyi.common.utils.CookieUtils;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.ServletUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.framework.shiro.service.SysPasswordService;
+import com.ruoyi.system.service.ISysConfigService;
+import com.ruoyi.system.service.ISysMenuService;
+
+/**
+ * 首页 业务处理
+ * 
+ * @author ruoyi
+ */
+@Controller
+public class SysIndexController extends BaseController
+{
+    @Autowired
+    private ISysMenuService menuService;
+
+    @Autowired
+    private ISysConfigService configService;
+
+    @Autowired
+    private SysPasswordService passwordService;
+
+    // 系统首页
+    @GetMapping("/index")
+    public String index(ModelMap mmap)
+    {
+        // 取身份信息
+        SysUser user = getSysUser();
+        // 根据用户id取出菜单
+        List<SysMenu> menus = menuService.selectMenusByUser(user);
+        mmap.put("menus", menus);
+        mmap.put("user", user);
+        mmap.put("sideTheme", configService.selectConfigByKey("sys.index.sideTheme"));
+        mmap.put("skinName", configService.selectConfigByKey("sys.index.skinName"));
+        Boolean footer = Convert.toBool(configService.selectConfigByKey("sys.index.footer"), true);
+        Boolean tagsView = Convert.toBool(configService.selectConfigByKey("sys.index.tagsView"), true);
+        mmap.put("footer", footer);
+        mmap.put("tagsView", tagsView);
+        mmap.put("mainClass", contentMainClass(footer, tagsView));
+        mmap.put("copyrightYear", RuoYiConfig.getCopyrightYear());
+        mmap.put("demoEnabled", RuoYiConfig.isDemoEnabled());
+        mmap.put("isDefaultModifyPwd", initPasswordIsModify(user.getPwdUpdateDate()));
+        mmap.put("isPasswordExpired", passwordIsExpiration(user.getPwdUpdateDate()));
+        mmap.put("isMobile", ServletUtils.checkAgentIsMobile(ServletUtils.getRequest().getHeader("User-Agent")));
+
+        // 菜单导航显示风格
+        String menuStyle = configService.selectConfigByKey("sys.index.menuStyle");
+        // 移动端,默认使左侧导航菜单,否则取默认配置
+        String indexStyle = ServletUtils.checkAgentIsMobile(ServletUtils.getRequest().getHeader("User-Agent")) ? "index" : menuStyle;
+
+        // 优先Cookie配置导航菜单
+        Cookie[] cookies = ServletUtils.getRequest().getCookies();
+        for (Cookie cookie : cookies)
+        {
+            if (StringUtils.isNotEmpty(cookie.getName()) && "nav-style".equalsIgnoreCase(cookie.getName()))
+            {
+                indexStyle = cookie.getValue();
+                break;
+            }
+        }
+        String webIndex = "topnav".equalsIgnoreCase(indexStyle) ? "index-topnav" : "index";
+        return webIndex;
+    }
+
+    // 锁定屏幕
+    @GetMapping("/lockscreen")
+    public String lockscreen(ModelMap mmap)
+    {
+        mmap.put("user", getSysUser());
+        ServletUtils.getSession().setAttribute(ShiroConstants.LOCK_SCREEN, true);
+        return "lock";
+    }
+
+    // 解锁屏幕
+    @PostMapping("/unlockscreen")
+    @ResponseBody
+    public AjaxResult unlockscreen(String password)
+    {
+        SysUser user = getSysUser();
+        if (StringUtils.isNull(user))
+        {
+            return AjaxResult.error("服务器超时,请重新登录");
+        }
+        if (passwordService.matches(user, password))
+        {
+            ServletUtils.getSession().removeAttribute(ShiroConstants.LOCK_SCREEN);
+            return AjaxResult.success();
+        }
+        return AjaxResult.error("密码不正确,请重新输入。");
+    }
+
+    // 切换主题
+    @GetMapping("/system/switchSkin")
+    public String switchSkin()
+    {
+        return "skin";
+    }
+
+    // 切换菜单
+    @GetMapping("/system/menuStyle/{style}")
+    public void menuStyle(@PathVariable String style, HttpServletResponse response)
+    {
+        CookieUtils.setCookie(response, "nav-style", style);
+    }
+
+    // 系统介绍
+    @GetMapping("/system/main")
+    public String main(ModelMap mmap)
+    {
+        mmap.put("version", RuoYiConfig.getVersion());
+        return "main";
+    }
+
+    // content-main class
+    public String contentMainClass(Boolean footer, Boolean tagsView)
+    {
+        if (!footer && !tagsView)
+        {
+            return "tagsview-footer-hide";
+        }
+        else if (!footer)
+        {
+            return "footer-hide";
+        }
+        else if (!tagsView)
+        {
+            return "tagsview-hide";
+        }
+        return StringUtils.EMPTY;
+    }
+
+    // 检查初始密码是否提醒修改
+    public boolean initPasswordIsModify(Date pwdUpdateDate)
+    {
+        Integer initPasswordModify = Convert.toInt(configService.selectConfigByKey("sys.account.initPasswordModify"));
+        return initPasswordModify != null && initPasswordModify == 1 && pwdUpdateDate == null;
+    }
+
+    // 检查密码是否过期
+    public boolean passwordIsExpiration(Date pwdUpdateDate)
+    {
+        Integer passwordValidateDays = Convert.toInt(configService.selectConfigByKey("sys.account.passwordValidateDays"));
+        if (passwordValidateDays != null && passwordValidateDays > 0)
+        {
+            if (StringUtils.isNull(pwdUpdateDate))
+            {
+                // 如果从未修改过初始密码,直接提醒过期
+                return true;
+            }
+            Date nowDate = DateUtils.getNowDate();
+            return DateUtils.differentDaysByMillisecond(nowDate, pwdUpdateDate) > passwordValidateDays;
+        }
+        return false;
+    }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java
new file mode 100644
index 0000000..55aecae
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java
@@ -0,0 +1,82 @@
+package com.ruoyi.web.controller.system;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.authc.AuthenticationException;
+import org.apache.shiro.authc.UsernamePasswordToken;
+import org.apache.shiro.subject.Subject;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.text.Convert;
+import com.ruoyi.common.utils.ServletUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.framework.web.service.ConfigService;
+
+/**
+ * 登录验证
+ * 
+ * @author ruoyi
+ */
+@Controller
+public class SysLoginController extends BaseController
+{
+    /**
+     * 是否开启记住我功能
+     */
+    @Value("${shiro.rememberMe.enabled: false}")
+    private boolean rememberMe;
+
+    @Autowired
+    private ConfigService configService;
+
+    @GetMapping("/login")
+    public String login(HttpServletRequest request, HttpServletResponse response, ModelMap mmap)
+    {
+        // 如果是Ajax请求,返回Json字符串。
+        if (ServletUtils.isAjaxRequest(request))
+        {
+            return ServletUtils.renderString(response, "{\"code\":\"1\",\"msg\":\"未登录或登录超时。请重新登录\"}");
+        }
+        // 是否开启记住我
+        mmap.put("isRemembered", rememberMe);
+        // 是否开启用户注册
+        mmap.put("isAllowRegister", Convert.toBool(configService.getKey("sys.account.registerUser"), false));
+        return "login";
+    }
+
+    @PostMapping("/login")
+    @ResponseBody
+    public AjaxResult ajaxLogin(String username, String password, Boolean rememberMe)
+    {
+        UsernamePasswordToken token = new UsernamePasswordToken(username, password, rememberMe);
+        Subject subject = SecurityUtils.getSubject();
+        try
+        {
+            subject.login(token);
+            return success();
+        }
+        catch (AuthenticationException e)
+        {
+            String msg = "用户或密码错误";
+            if (StringUtils.isNotEmpty(e.getMessage()))
+            {
+                msg = e.getMessage();
+            }
+            return error(msg);
+        }
+    }
+
+    @GetMapping("/unauth")
+    public String unauth()
+    {
+        return "error/unauth";
+    }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java
new file mode 100644
index 0000000..44960cb
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java
@@ -0,0 +1,198 @@
+package com.ruoyi.web.controller.system;
+
+import java.util.List;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+import org.springframework.validation.annotation.Validated;
+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.ResponseBody;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.Ztree;
+import com.ruoyi.common.core.domain.entity.SysMenu;
+import com.ruoyi.common.core.domain.entity.SysRole;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.ShiroUtils;
+import com.ruoyi.framework.shiro.util.AuthorizationUtils;
+import com.ruoyi.system.service.ISysMenuService;
+
+/**
+ * 菜单信息
+ * 
+ * @author ruoyi
+ */
+@Controller
+@RequestMapping("/system/menu")
+public class SysMenuController extends BaseController
+{
+    private String prefix = "system/menu";
+
+    @Autowired
+    private ISysMenuService menuService;
+
+    @RequiresPermissions("system:menu:view")
+    @GetMapping()
+    public String menu()
+    {
+        return prefix + "/menu";
+    }
+
+    @RequiresPermissions("system:menu:list")
+    @PostMapping("/list")
+    @ResponseBody
+    public List<SysMenu> list(SysMenu menu)
+    {
+        Long userId = ShiroUtils.getUserId();
+        List<SysMenu> menuList = menuService.selectMenuList(menu, userId);
+        return menuList;
+    }
+
+    /**
+     * 删除菜单
+     */
+    @Log(title = "菜单管理", businessType = BusinessType.DELETE)
+    @RequiresPermissions("system:menu:remove")
+    @GetMapping("/remove/{menuId}")
+    @ResponseBody
+    public AjaxResult remove(@PathVariable("menuId") Long menuId)
+    {
+        if (menuService.selectCountMenuByParentId(menuId) > 0)
+        {
+            return AjaxResult.warn("存在子菜单,不允许删除");
+        }
+        if (menuService.selectCountRoleMenuByMenuId(menuId) > 0)
+        {
+            return AjaxResult.warn("菜单已分配,不允许删除");
+        }
+        AuthorizationUtils.clearAllCachedAuthorizationInfo();
+        return toAjax(menuService.deleteMenuById(menuId));
+    }
+
+    /**
+     * 新增
+     */
+    @RequiresPermissions("system:menu:add")
+    @GetMapping("/add/{parentId}")
+    public String add(@PathVariable("parentId") Long parentId, ModelMap mmap)
+    {
+        SysMenu menu = null;
+        if (0L != parentId)
+        {
+            menu = menuService.selectMenuById(parentId);
+        }
+        else
+        {
+            menu = new SysMenu();
+            menu.setMenuId(0L);
+            menu.setMenuName("主目录");
+        }
+        mmap.put("menu", menu);
+        return prefix + "/add";
+    }
+
+    /**
+     * 新增保存菜单
+     */
+    @Log(title = "菜单管理", businessType = BusinessType.INSERT)
+    @RequiresPermissions("system:menu:add")
+    @PostMapping("/add")
+    @ResponseBody
+    public AjaxResult addSave(@Validated SysMenu menu)
+    {
+        if (!menuService.checkMenuNameUnique(menu))
+        {
+            return error("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
+        }
+        menu.setCreateBy(getLoginName());
+        AuthorizationUtils.clearAllCachedAuthorizationInfo();
+        return toAjax(menuService.insertMenu(menu));
+    }
+
+    /**
+     * 修改菜单
+     */
+    @RequiresPermissions("system:menu:edit")
+    @GetMapping("/edit/{menuId}")
+    public String edit(@PathVariable("menuId") Long menuId, ModelMap mmap)
+    {
+        mmap.put("menu", menuService.selectMenuById(menuId));
+        return prefix + "/edit";
+    }
+
+    /**
+     * 修改保存菜单
+     */
+    @Log(title = "菜单管理", businessType = BusinessType.UPDATE)
+    @RequiresPermissions("system:menu:edit")
+    @PostMapping("/edit")
+    @ResponseBody
+    public AjaxResult editSave(@Validated SysMenu menu)
+    {
+        if (!menuService.checkMenuNameUnique(menu))
+        {
+            return error("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
+        }
+        menu.setUpdateBy(getLoginName());
+        AuthorizationUtils.clearAllCachedAuthorizationInfo();
+        return toAjax(menuService.updateMenu(menu));
+    }
+
+    /**
+     * 选择菜单图标
+     */
+    @GetMapping("/icon")
+    public String icon()
+    {
+        return prefix + "/icon";
+    }
+
+    /**
+     * 校验菜单名称
+     */
+    @PostMapping("/checkMenuNameUnique")
+    @ResponseBody
+    public boolean checkMenuNameUnique(SysMenu menu)
+    {
+        return menuService.checkMenuNameUnique(menu);
+    }
+
+    /**
+     * 加载角色菜单列表树
+     */
+    @GetMapping("/roleMenuTreeData")
+    @ResponseBody
+    public List<Ztree> roleMenuTreeData(SysRole role)
+    {
+        Long userId = ShiroUtils.getUserId();
+        List<Ztree> ztrees = menuService.roleMenuTreeData(role, userId);
+        return ztrees;
+    }
+
+    /**
+     * 加载所有菜单列表树
+     */
+    @GetMapping("/menuTreeData")
+    @ResponseBody
+    public List<Ztree> menuTreeData()
+    {
+        Long userId = ShiroUtils.getUserId();
+        List<Ztree> ztrees = menuService.menuTreeData(userId);
+        return ztrees;
+    }
+
+    /**
+     * 选择菜单树
+     */
+    @GetMapping("/selectMenuTree/{menuId}")
+    public String selectMenuTree(@PathVariable("menuId") Long menuId, ModelMap mmap)
+    {
+        mmap.put("menu", menuService.selectMenuById(menuId));
+        return prefix + "/tree";
+    }
+}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java
new file mode 100644
index 0000000..96d0fa4
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java
@@ -0,0 +1,125 @@
+package com.ruoyi.web.controller.system;
+
+import java.util.List;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+import org.springframework.validation.annotation.Validated;
+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.ResponseBody;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.system.domain.SysNotice;
+import com.ruoyi.system.service.ISysNoticeService;
+
+/**
+ * 公告 信息操作处理
+ * 
+ * @author ruoyi
+ */
+@Controller
+@RequestMapping("/system/notice")
+public class SysNoticeController extends BaseController
+{
+    private String prefix = "system/notice";
+
+    @Autowired
+    private ISysNoticeService noticeService;
+
+    @RequiresPermissions("system:notice:view")
+    @GetMapping()
+    public String notice()
+    {
+        return prefix + "/notice";
+    }
+
+    /**
+     * 查询公告列表
+     */
+    @RequiresPermissions("system:notice:list")
+    @PostMapping("/list")
+    @ResponseBody
+    public TableDataInfo list(SysNotice notice)
+    {
+        startPage();
+        List<SysNotice> list = noticeService.selectNoticeList(notice);
+        return getDataTable(list);
+    }
+
+    /**
+     * 新增公告
+     */
+    @RequiresPermissions("system:notice:add")
+    @GetMapping("/add")
+    public String add()
+    {
+        return prefix + "/add";
+    }
+
+    /**
+     * 新增保存公告
+     */
+    @RequiresPermissions("system:notice:add")
+    @Log(title = "通知公告", businessType = BusinessType.INSERT)
+    @PostMapping("/add")
+    @ResponseBody
+    public AjaxResult addSave(@Validated SysNotice notice)
+    {
+        notice.setCreateBy(getLoginName());
+        return toAjax(noticeService.insertNotice(notice));
+    }
+
+    /**
+     * 修改公告
+     */
+    @RequiresPermissions("system:notice:edit")
+    @GetMapping("/edit/{noticeId}")
+    public String edit(@PathVariable("noticeId") Long noticeId, ModelMap mmap)
+    {
+        mmap.put("notice", noticeService.selectNoticeById(noticeId));
+        return prefix + "/edit";
+    }
+
+    /**
+     * 修改保存公告
+     */
+    @RequiresPermissions("system:notice:edit")
+    @Log(title = "通知公告", businessType = BusinessType.UPDATE)
+    @PostMapping("/edit")
+    @ResponseBody
+    public AjaxResult editSave(@Validated SysNotice notice)
+    {
+        notice.setUpdateBy(getLoginName());
+        return toAjax(noticeService.updateNotice(notice));
+    }
+
+    /**
+     * 查询公告详细
+     */
+    @RequiresPermissions("system:notice:list")
+    @GetMapping("/view/{noticeId}")
+    public String view(@PathVariable("noticeId") Long noticeId, ModelMap mmap)
+    {
+        mmap.put("notice", noticeService.selectNoticeById(noticeId));
+        return prefix + "/view";
+    }
+
+    /**
+     * 删除公告
+     */
+    @RequiresPermissions("system:notice:remove")
+    @Log(title = "通知公告", businessType = BusinessType.DELETE)
+    @PostMapping("/remove")
+    @ResponseBody
+    public AjaxResult remove(String ids)
+    {
+        return toAjax(noticeService.deleteNoticeByIds(ids));
+    }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java
new file mode 100644
index 0000000..9835a57
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java
@@ -0,0 +1,156 @@
+package com.ruoyi.web.controller.system;
+
+import java.util.List;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+import org.springframework.validation.annotation.Validated;
+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.ResponseBody;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.system.domain.SysPost;
+import com.ruoyi.system.service.ISysPostService;
+
+/**
+ * 岗位信息操作处理
+ * 
+ * @author ruoyi
+ */
+@Controller
+@RequestMapping("/system/post")
+public class SysPostController extends BaseController
+{
+    private String prefix = "system/post";
+
+    @Autowired
+    private ISysPostService postService;
+
+    @RequiresPermissions("system:post:view")
+    @GetMapping()
+    public String operlog()
+    {
+        return prefix + "/post";
+    }
+
+    @RequiresPermissions("system:post:list")
+    @PostMapping("/list")
+    @ResponseBody
+    public TableDataInfo list(SysPost post)
+    {
+        startPage();
+        List<SysPost> list = postService.selectPostList(post);
+        return getDataTable(list);
+    }
+
+    @Log(title = "岗位管理", businessType = BusinessType.EXPORT)
+    @RequiresPermissions("system:post:export")
+    @PostMapping("/export")
+    @ResponseBody
+    public AjaxResult export(SysPost post)
+    {
+        List<SysPost> list = postService.selectPostList(post);
+        ExcelUtil<SysPost> util = new ExcelUtil<SysPost>(SysPost.class);
+        return util.exportExcel(list, "岗位数据");
+    }
+
+    @RequiresPermissions("system:post:remove")
+    @Log(title = "岗位管理", businessType = BusinessType.DELETE)
+    @PostMapping("/remove")
+    @ResponseBody
+    public AjaxResult remove(String ids)
+    {
+        return toAjax(postService.deletePostByIds(ids));
+    }
+
+    /**
+     * 新增岗位
+     */
+    @RequiresPermissions("system:post:add")
+    @GetMapping("/add")
+    public String add()
+    {
+        return prefix + "/add";
+    }
+
+    /**
+     * 新增保存岗位
+     */
+    @RequiresPermissions("system:post:add")
+    @Log(title = "岗位管理", businessType = BusinessType.INSERT)
+    @PostMapping("/add")
+    @ResponseBody
+    public AjaxResult addSave(@Validated SysPost post)
+    {
+        if (!postService.checkPostNameUnique(post))
+        {
+            return error("新增岗位'" + post.getPostName() + "'失败,岗位名称已存在");
+        }
+        else if (!postService.checkPostCodeUnique(post))
+        {
+            return error("新增岗位'" + post.getPostName() + "'失败,岗位编码已存在");
+        }
+        post.setCreateBy(getLoginName());
+        return toAjax(postService.insertPost(post));
+    }
+
+    /**
+     * 修改岗位
+     */
+    @RequiresPermissions("system:post:edit")
+    @GetMapping("/edit/{postId}")
+    public String edit(@PathVariable("postId") Long postId, ModelMap mmap)
+    {
+        mmap.put("post", postService.selectPostById(postId));
+        return prefix + "/edit";
+    }
+
+    /**
+     * 修改保存岗位
+     */
+    @RequiresPermissions("system:post:edit")
+    @Log(title = "岗位管理", businessType = BusinessType.UPDATE)
+    @PostMapping("/edit")
+    @ResponseBody
+    public AjaxResult editSave(@Validated SysPost post)
+    {
+        if (!postService.checkPostNameUnique(post))
+        {
+            return error("修改岗位'" + post.getPostName() + "'失败,岗位名称已存在");
+        }
+        else if (!postService.checkPostCodeUnique(post))
+        {
+            return error("修改岗位'" + post.getPostName() + "'失败,岗位编码已存在");
+        }
+        post.setUpdateBy(getLoginName());
+        return toAjax(postService.updatePost(post));
+    }
+
+    /**
+     * 校验岗位名称
+     */
+    @PostMapping("/checkPostNameUnique")
+    @ResponseBody
+    public boolean checkPostNameUnique(SysPost post)
+    {
+        return postService.checkPostNameUnique(post);
+    }
+
+    /**
+     * 校验岗位编码
+     */
+    @PostMapping("/checkPostCodeUnique")
+    @ResponseBody
+    public boolean checkPostCodeUnique(SysPost post)
+    {
+        return postService.checkPostCodeUnique(post);
+    }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java
new file mode 100644
index 0000000..e95868a
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java
@@ -0,0 +1,181 @@
+package com.ruoyi.web.controller.system;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+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.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.multipart.MultipartFile;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.config.RuoYiConfig;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.ShiroUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.file.FileUploadUtils;
+import com.ruoyi.common.utils.file.MimeTypeUtils;
+import com.ruoyi.framework.shiro.service.SysPasswordService;
+import com.ruoyi.system.service.ISysUserService;
+
+/**
+ * 个人信息 业务处理
+ * 
+ * @author ruoyi
+ */
+@Controller
+@RequestMapping("/system/user/profile")
+public class SysProfileController extends BaseController
+{
+    private static final Logger log = LoggerFactory.getLogger(SysProfileController.class);
+
+    private String prefix = "system/user/profile";
+
+    @Autowired
+    private ISysUserService userService;
+    
+    @Autowired
+    private SysPasswordService passwordService;
+
+    /**
+     * 个人信息
+     */
+    @GetMapping()
+    public String profile(ModelMap mmap)
+    {
+        SysUser user = getSysUser();
+        mmap.put("user", user);
+        mmap.put("roleGroup", userService.selectUserRoleGroup(user.getUserId()));
+        mmap.put("postGroup", userService.selectUserPostGroup(user.getUserId()));
+        return prefix + "/profile";
+    }
+
+    @GetMapping("/checkPassword")
+    @ResponseBody
+    public boolean checkPassword(String password)
+    {
+        SysUser user = getSysUser();
+        return passwordService.matches(user, password);
+    }
+
+    @GetMapping("/resetPwd")
+    public String resetPwd(ModelMap mmap)
+    {
+        SysUser user = getSysUser();
+        mmap.put("user", userService.selectUserById(user.getUserId()));
+        return prefix + "/resetPwd";
+    }
+
+    @Log(title = "重置密码", businessType = BusinessType.UPDATE)
+    @PostMapping("/resetPwd")
+    @ResponseBody
+    public AjaxResult resetPwd(String oldPassword, String newPassword)
+    {
+        SysUser user = getSysUser();
+        if (!passwordService.matches(user, oldPassword))
+        {
+            return error("修改密码失败,旧密码错误");
+        }
+        if (passwordService.matches(user, newPassword))
+        {
+            return error("新密码不能与旧密码相同");
+        }
+        user.setSalt(ShiroUtils.randomSalt());
+        user.setPassword(passwordService.encryptPassword(user.getLoginName(), newPassword, user.getSalt()));
+        user.setPwdUpdateDate(DateUtils.getNowDate());
+        if (userService.resetUserPwd(user) > 0)
+        {
+            setSysUser(userService.selectUserById(user.getUserId()));
+            return success();
+        }
+        return error("修改密码异常,请联系管理员");
+    }
+
+    /**
+     * 修改用户
+     */
+    @GetMapping("/edit")
+    public String edit(ModelMap mmap)
+    {
+        SysUser user = getSysUser();
+        mmap.put("user", userService.selectUserById(user.getUserId()));
+        return prefix + "/edit";
+    }
+
+    /**
+     * 修改头像
+     */
+    @GetMapping("/avatar")
+    public String avatar(ModelMap mmap)
+    {
+        SysUser user = getSysUser();
+        mmap.put("user", userService.selectUserById(user.getUserId()));
+        return prefix + "/avatar";
+    }
+
+    /**
+     * 修改用户
+     */
+    @Log(title = "个人信息", businessType = BusinessType.UPDATE)
+    @PostMapping("/update")
+    @ResponseBody
+    public AjaxResult update(SysUser user)
+    {
+        SysUser currentUser = getSysUser();
+        currentUser.setUserName(user.getUserName());
+        currentUser.setEmail(user.getEmail());
+        currentUser.setPhonenumber(user.getPhonenumber());
+        currentUser.setSex(user.getSex());
+        if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(currentUser))
+        {
+            return error("修改用户'" + currentUser.getLoginName() + "'失败,手机号码已存在");
+        }
+        else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(currentUser))
+        {
+            return error("修改用户'" + currentUser.getLoginName() + "'失败,邮箱账号已存在");
+        }
+        if (userService.updateUserInfo(currentUser) > 0)
+        {
+            setSysUser(userService.selectUserById(currentUser.getUserId()));
+            return success();
+        }
+        return error();
+    }
+
+    /**
+     * 保存头像
+     */
+    @Log(title = "个人信息", businessType = BusinessType.UPDATE)
+    @PostMapping("/updateAvatar")
+    @ResponseBody
+    public AjaxResult updateAvatar(@RequestParam("avatarfile") MultipartFile file)
+    {
+        SysUser currentUser = getSysUser();
+        try
+        {
+            if (!file.isEmpty())
+            {
+                String avatar = FileUploadUtils.upload(RuoYiConfig.getAvatarPath(), file, MimeTypeUtils.IMAGE_EXTENSION);
+                currentUser.setAvatar(avatar);
+                if (userService.updateUserInfo(currentUser) > 0)
+                {
+                    setSysUser(userService.selectUserById(currentUser.getUserId()));
+                    return success();
+                }
+            }
+            return error();
+        }
+        catch (Exception e)
+        {
+            log.error("修改头像失败!", e);
+            return error(e.getMessage());
+        }
+    }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRegisterController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRegisterController.java
new file mode 100644
index 0000000..e8dc001
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRegisterController.java
@@ -0,0 +1,46 @@
+package com.ruoyi.web.controller.system;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.framework.shiro.service.SysRegisterService;
+import com.ruoyi.system.service.ISysConfigService;
+
+/**
+ * 注册验证
+ * 
+ * @author ruoyi
+ */
+@Controller
+public class SysRegisterController extends BaseController
+{
+    @Autowired
+    private SysRegisterService registerService;
+
+    @Autowired
+    private ISysConfigService configService;
+
+    @GetMapping("/register")
+    public String register()
+    {
+        return "register";
+    }
+
+    @PostMapping("/register")
+    @ResponseBody
+    public AjaxResult ajaxRegister(SysUser 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/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java
new file mode 100644
index 0000000..b853146
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java
@@ -0,0 +1,324 @@
+package com.ruoyi.web.controller.system;
+
+import java.util.List;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+import org.springframework.validation.annotation.Validated;
+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.ResponseBody;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.Ztree;
+import com.ruoyi.common.core.domain.entity.SysRole;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.framework.shiro.util.AuthorizationUtils;
+import com.ruoyi.system.domain.SysUserRole;
+import com.ruoyi.system.service.ISysDeptService;
+import com.ruoyi.system.service.ISysRoleService;
+import com.ruoyi.system.service.ISysUserService;
+
+/**
+ * 角色信息
+ * 
+ * @author ruoyi
+ */
+@Controller
+@RequestMapping("/system/role")
+public class SysRoleController extends BaseController
+{
+    private String prefix = "system/role";
+
+    @Autowired
+    private ISysRoleService roleService;
+
+    @Autowired
+    private ISysUserService userService;
+
+    @Autowired
+    private ISysDeptService deptService;
+
+    @RequiresPermissions("system:role:view")
+    @GetMapping()
+    public String role()
+    {
+        return prefix + "/role";
+    }
+
+    @RequiresPermissions("system:role:list")
+    @PostMapping("/list")
+    @ResponseBody
+    public TableDataInfo list(SysRole role)
+    {
+        startPage();
+        List<SysRole> list = roleService.selectRoleList(role);
+        return getDataTable(list);
+    }
+
+    @Log(title = "角色管理", businessType = BusinessType.EXPORT)
+    @RequiresPermissions("system:role:export")
+    @PostMapping("/export")
+    @ResponseBody
+    public AjaxResult export(SysRole role)
+    {
+        List<SysRole> list = roleService.selectRoleList(role);
+        ExcelUtil<SysRole> util = new ExcelUtil<SysRole>(SysRole.class);
+        return util.exportExcel(list, "角色数据");
+    }
+
+    /**
+     * 新增角色
+     */
+    @RequiresPermissions("system:role:add")
+    @GetMapping("/add")
+    public String add()
+    {
+        return prefix + "/add";
+    }
+
+    /**
+     * 新增保存角色
+     */
+    @RequiresPermissions("system:role:add")
+    @Log(title = "角色管理", businessType = BusinessType.INSERT)
+    @PostMapping("/add")
+    @ResponseBody
+    public AjaxResult addSave(@Validated SysRole role)
+    {
+        if (!roleService.checkRoleNameUnique(role))
+        {
+            return error("新增角色'" + role.getRoleName() + "'失败,角色名称已存在");
+        }
+        else if (!roleService.checkRoleKeyUnique(role))
+        {
+            return error("新增角色'" + role.getRoleName() + "'失败,角色权限已存在");
+        }
+        role.setCreateBy(getLoginName());
+        AuthorizationUtils.clearAllCachedAuthorizationInfo();
+        return toAjax(roleService.insertRole(role));
+
+    }
+
+    /**
+     * 修改角色
+     */
+    @RequiresPermissions("system:role:edit")
+    @GetMapping("/edit/{roleId}")
+    public String edit(@PathVariable("roleId") Long roleId, ModelMap mmap)
+    {
+        roleService.checkRoleDataScope(roleId);
+        mmap.put("role", roleService.selectRoleById(roleId));
+        return prefix + "/edit";
+    }
+
+    /**
+     * 修改保存角色
+     */
+    @RequiresPermissions("system:role:edit")
+    @Log(title = "角色管理", businessType = BusinessType.UPDATE)
+    @PostMapping("/edit")
+    @ResponseBody
+    public AjaxResult editSave(@Validated 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(getLoginName());
+        AuthorizationUtils.clearAllCachedAuthorizationInfo();
+        return toAjax(roleService.updateRole(role));
+    }
+
+    /**
+     * 角色分配数据权限
+     */
+    @GetMapping("/authDataScope/{roleId}")
+    public String authDataScope(@PathVariable("roleId") Long roleId, ModelMap mmap)
+    {
+        mmap.put("role", roleService.selectRoleById(roleId));
+        return prefix + "/dataScope";
+    }
+
+    /**
+     * 保存角色分配数据权限
+     */
+    @RequiresPermissions("system:role:edit")
+    @Log(title = "角色管理", businessType = BusinessType.UPDATE)
+    @PostMapping("/authDataScope")
+    @ResponseBody
+    public AjaxResult authDataScopeSave(SysRole role)
+    {
+        roleService.checkRoleAllowed(role);
+        roleService.checkRoleDataScope(role.getRoleId());
+        role.setUpdateBy(getLoginName());
+        if (roleService.authDataScope(role) > 0)
+        {
+            setSysUser(userService.selectUserById(getUserId()));
+            return success();
+        }
+        return error();
+    }
+
+    @RequiresPermissions("system:role:remove")
+    @Log(title = "角色管理", businessType = BusinessType.DELETE)
+    @PostMapping("/remove")
+    @ResponseBody
+    public AjaxResult remove(String ids)
+    {
+        return toAjax(roleService.deleteRoleByIds(ids));
+    }
+
+    /**
+     * 校验角色名称
+     */
+    @PostMapping("/checkRoleNameUnique")
+    @ResponseBody
+    public boolean checkRoleNameUnique(SysRole role)
+    {
+        return roleService.checkRoleNameUnique(role);
+    }
+
+    /**
+     * 校验角色权限
+     */
+    @PostMapping("/checkRoleKeyUnique")
+    @ResponseBody
+    public boolean checkRoleKeyUnique(SysRole role)
+    {
+        return roleService.checkRoleKeyUnique(role);
+    }
+
+    /**
+     * 选择菜单树
+     */
+    @GetMapping("/selectMenuTree")
+    public String selectMenuTree()
+    {
+        return prefix + "/tree";
+    }
+
+    /**
+     * 角色状态修改
+     */
+    @Log(title = "角色管理", businessType = BusinessType.UPDATE)
+    @RequiresPermissions("system:role:edit")
+    @PostMapping("/changeStatus")
+    @ResponseBody
+    public AjaxResult changeStatus(SysRole role)
+    {
+        roleService.checkRoleAllowed(role);
+        roleService.checkRoleDataScope(role.getRoleId());
+        return toAjax(roleService.changeStatus(role));
+    }
+
+    /**
+     * 分配用户
+     */
+    @RequiresPermissions("system:role:edit")
+    @GetMapping("/authUser/{roleId}")
+    public String authUser(@PathVariable("roleId") Long roleId, ModelMap mmap)
+    {
+        mmap.put("role", roleService.selectRoleById(roleId));
+        return prefix + "/authUser";
+    }
+
+    /**
+     * 查询已分配用户角色列表
+     */
+    @RequiresPermissions("system:role:list")
+    @PostMapping("/authUser/allocatedList")
+    @ResponseBody
+    public TableDataInfo allocatedList(SysUser user)
+    {
+        startPage();
+        List<SysUser> list = userService.selectAllocatedList(user);
+        return getDataTable(list);
+    }
+
+    /**
+     * 取消授权
+     */
+    @RequiresPermissions("system:role:edit")
+    @Log(title = "角色管理", businessType = BusinessType.GRANT)
+    @PostMapping("/authUser/cancel")
+    @ResponseBody
+    public AjaxResult cancelAuthUser(SysUserRole userRole)
+    {
+        return toAjax(roleService.deleteAuthUser(userRole));
+    }
+
+    /**
+     * 批量取消授权
+     */
+    @RequiresPermissions("system:role:edit")
+    @Log(title = "角色管理", businessType = BusinessType.GRANT)
+    @PostMapping("/authUser/cancelAll")
+    @ResponseBody
+    public AjaxResult cancelAuthUserAll(Long roleId, String userIds)
+    {
+        return toAjax(roleService.deleteAuthUsers(roleId, userIds));
+    }
+
+    /**
+     * 选择用户
+     */
+    @RequiresPermissions("system:role:list")
+    @GetMapping("/authUser/selectUser/{roleId}")
+    public String selectUser(@PathVariable("roleId") Long roleId, ModelMap mmap)
+    {
+        mmap.put("role", roleService.selectRoleById(roleId));
+        return prefix + "/selectUser";
+    }
+
+    /**
+     * 查询未分配用户角色列表
+     */
+    @RequiresPermissions("system:role:list")
+    @PostMapping("/authUser/unallocatedList")
+    @ResponseBody
+    public TableDataInfo unallocatedList(SysUser user)
+    {
+        startPage();
+        List<SysUser> list = userService.selectUnallocatedList(user);
+        return getDataTable(list);
+    }
+
+    /**
+     * 批量选择用户授权
+     */
+    @RequiresPermissions("system:role:edit")
+    @Log(title = "角色管理", businessType = BusinessType.GRANT)
+    @PostMapping("/authUser/selectAll")
+    @ResponseBody
+    public AjaxResult selectAuthUserAll(Long roleId, String userIds)
+    {
+        roleService.checkRoleDataScope(roleId);
+        return toAjax(roleService.insertAuthUsers(roleId, userIds));
+    }
+
+    /**
+     * 加载角色部门(数据权限)列表树
+     */
+    @RequiresPermissions("system:role:edit")
+    @GetMapping("/deptTreeData")
+    @ResponseBody
+    public List<Ztree> deptTreeData(SysRole role)
+    {
+        List<Ztree> ztrees = deptService.roleDeptTreeData(role);
+        return ztrees;
+    }
+}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java
new file mode 100644
index 0000000..094cc58
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java
@@ -0,0 +1,355 @@
+package com.ruoyi.web.controller.system;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+import org.springframework.validation.annotation.Validated;
+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.ResponseBody;
+import org.springframework.web.multipart.MultipartFile;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.Ztree;
+import com.ruoyi.common.core.domain.entity.SysDept;
+import com.ruoyi.common.core.domain.entity.SysRole;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.core.text.Convert;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.ShiroUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.framework.shiro.service.SysPasswordService;
+import com.ruoyi.framework.shiro.util.AuthorizationUtils;
+import com.ruoyi.system.service.ISysDeptService;
+import com.ruoyi.system.service.ISysPostService;
+import com.ruoyi.system.service.ISysRoleService;
+import com.ruoyi.system.service.ISysUserService;
+
+/**
+ * 用户信息
+ * 
+ * @author ruoyi
+ */
+@Controller
+@RequestMapping("/system/user")
+public class SysUserController extends BaseController
+{
+    private String prefix = "system/user";
+
+    @Autowired
+    private ISysUserService userService;
+
+    @Autowired
+    private ISysRoleService roleService;
+    
+    @Autowired
+    private ISysDeptService deptService;
+
+    @Autowired
+    private ISysPostService postService;
+
+    @Autowired
+    private SysPasswordService passwordService;
+
+    @RequiresPermissions("system:user:view")
+    @GetMapping()
+    public String user()
+    {
+        return prefix + "/user";
+    }
+
+    @RequiresPermissions("system:user:list")
+    @PostMapping("/list")
+    @ResponseBody
+    public TableDataInfo list(SysUser user)
+    {
+        startPage();
+        List<SysUser> list = userService.selectUserList(user);
+        return getDataTable(list);
+    }
+
+    @Log(title = "用户管理", businessType = BusinessType.EXPORT)
+    @RequiresPermissions("system:user:export")
+    @PostMapping("/export")
+    @ResponseBody
+    public AjaxResult export(SysUser user)
+    {
+        List<SysUser> list = userService.selectUserList(user);
+        ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
+        return util.exportExcel(list, "用户数据");
+    }
+
+    @Log(title = "用户管理", businessType = BusinessType.IMPORT)
+    @RequiresPermissions("system:user:import")
+    @PostMapping("/importData")
+    @ResponseBody
+    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 message = userService.importUser(userList, updateSupport, getLoginName());
+        return AjaxResult.success(message);
+    }
+
+    @RequiresPermissions("system:user:view")
+    @GetMapping("/importTemplate")
+    @ResponseBody
+    public AjaxResult importTemplate()
+    {
+        ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
+        return util.importTemplateExcel("用户数据");
+    }
+
+    /**
+     * 新增用户
+     */
+    @RequiresPermissions("system:user:add")
+    @GetMapping("/add")
+    public String add(ModelMap mmap)
+    {
+        mmap.put("roles", roleService.selectRoleAll().stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
+        mmap.put("posts", postService.selectPostAll());
+        return prefix + "/add";
+    }
+
+    /**
+     * 新增保存用户
+     */
+    @RequiresPermissions("system:user:add")
+    @Log(title = "用户管理", businessType = BusinessType.INSERT)
+    @PostMapping("/add")
+    @ResponseBody
+    public AjaxResult addSave(@Validated SysUser user)
+    {
+        deptService.checkDeptDataScope(user.getDeptId());
+        roleService.checkRoleDataScope(user.getRoleIds());
+        if (!userService.checkLoginNameUnique(user))
+        {
+            return error("新增用户'" + user.getLoginName() + "'失败,登录账号已存在");
+        }
+        else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user))
+        {
+            return error("新增用户'" + user.getLoginName() + "'失败,手机号码已存在");
+        }
+        else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user))
+        {
+            return error("新增用户'" + user.getLoginName() + "'失败,邮箱账号已存在");
+        }
+        user.setSalt(ShiroUtils.randomSalt());
+        user.setPassword(passwordService.encryptPassword(user.getLoginName(), user.getPassword(), user.getSalt()));
+        user.setPwdUpdateDate(DateUtils.getNowDate());
+        user.setCreateBy(getLoginName());
+        return toAjax(userService.insertUser(user));
+    }
+
+    /**
+     * 修改用户
+     */
+    @RequiresPermissions("system:user:edit")
+    @GetMapping("/edit/{userId}")
+    public String edit(@PathVariable("userId") Long userId, ModelMap mmap)
+    {
+        userService.checkUserDataScope(userId);
+        List<SysRole> roles = roleService.selectRolesByUserId(userId);
+        mmap.put("user", userService.selectUserById(userId));
+        mmap.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
+        mmap.put("posts", postService.selectPostsByUserId(userId));
+        return prefix + "/edit";
+    }
+
+    /**
+     * 查询用户详细
+     */
+    @RequiresPermissions("system:user:list")
+    @GetMapping("/view/{userId}")
+    public String view(@PathVariable("userId") Long userId, ModelMap mmap)
+    {
+        userService.checkUserDataScope(userId);
+        mmap.put("user", userService.selectUserById(userId));
+        mmap.put("roleGroup", userService.selectUserRoleGroup(userId));
+        mmap.put("postGroup", userService.selectUserPostGroup(userId));
+        return prefix + "/view";
+    }
+
+    /**
+     * 修改保存用户
+     */
+    @RequiresPermissions("system:user:edit")
+    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
+    @PostMapping("/edit")
+    @ResponseBody
+    public AjaxResult editSave(@Validated SysUser user)
+    {
+        userService.checkUserAllowed(user);
+        userService.checkUserDataScope(user.getUserId());
+        deptService.checkDeptDataScope(user.getDeptId());
+        roleService.checkRoleDataScope(user.getRoleIds());
+        if (!userService.checkLoginNameUnique(user))
+        {
+            return error("修改用户'" + user.getLoginName() + "'失败,登录账号已存在");
+        }
+        else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user))
+        {
+            return error("修改用户'" + user.getLoginName() + "'失败,手机号码已存在");
+        }
+        else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user))
+        {
+            return error("修改用户'" + user.getLoginName() + "'失败,邮箱账号已存在");
+        }
+        user.setUpdateBy(getLoginName());
+        AuthorizationUtils.clearAllCachedAuthorizationInfo();
+        return toAjax(userService.updateUser(user));
+    }
+
+    @RequiresPermissions("system:user:resetPwd")
+    @GetMapping("/resetPwd/{userId}")
+    public String resetPwd(@PathVariable("userId") Long userId, ModelMap mmap)
+    {
+        mmap.put("user", userService.selectUserById(userId));
+        return prefix + "/resetPwd";
+    }
+
+    @RequiresPermissions("system:user:resetPwd")
+    @Log(title = "重置密码", businessType = BusinessType.UPDATE)
+    @PostMapping("/resetPwd")
+    @ResponseBody
+    public AjaxResult resetPwdSave(SysUser user)
+    {
+        userService.checkUserAllowed(user);
+        userService.checkUserDataScope(user.getUserId());
+        user.setSalt(ShiroUtils.randomSalt());
+        user.setPassword(passwordService.encryptPassword(user.getLoginName(), user.getPassword(), user.getSalt()));
+        if (userService.resetUserPwd(user) > 0)
+        {
+            if (ShiroUtils.getUserId().longValue() == user.getUserId().longValue())
+            {
+                setSysUser(userService.selectUserById(user.getUserId()));
+            }
+            return success();
+        }
+        return error();
+    }
+
+    /**
+     * 进入授权角色页
+     */
+    @RequiresPermissions("system:user:edit")
+    @GetMapping("/authRole/{userId}")
+    public String authRole(@PathVariable("userId") Long userId, ModelMap mmap)
+    {
+        SysUser user = userService.selectUserById(userId);
+        // 获取用户所属的角色列表
+        List<SysRole> roles = roleService.selectRolesByUserId(userId);
+        mmap.put("user", user);
+        mmap.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
+        return prefix + "/authRole";
+    }
+
+    /**
+     * 用户授权角色
+     */
+    @RequiresPermissions("system:user:edit")
+    @Log(title = "用户管理", businessType = BusinessType.GRANT)
+    @PostMapping("/authRole/insertAuthRole")
+    @ResponseBody
+    public AjaxResult insertAuthRole(Long userId, Long[] roleIds)
+    {
+        userService.checkUserDataScope(userId);
+        roleService.checkRoleDataScope(roleIds);
+        userService.insertUserAuth(userId, roleIds);
+        AuthorizationUtils.clearAllCachedAuthorizationInfo();
+        return success();
+    }
+
+    @RequiresPermissions("system:user:remove")
+    @Log(title = "用户管理", businessType = BusinessType.DELETE)
+    @PostMapping("/remove")
+    @ResponseBody
+    public AjaxResult remove(String ids)
+    {
+        if (ArrayUtils.contains(Convert.toLongArray(ids), getUserId()))
+        {
+            return error("当前用户不能删除");
+        }
+        return toAjax(userService.deleteUserByIds(ids));
+    }
+
+    /**
+     * 校验用户名
+     */
+    @PostMapping("/checkLoginNameUnique")
+    @ResponseBody
+    public boolean checkLoginNameUnique(SysUser user)
+    {
+        return userService.checkLoginNameUnique(user);
+    }
+
+    /**
+     * 校验手机号码
+     */
+    @PostMapping("/checkPhoneUnique")
+    @ResponseBody
+    public boolean checkPhoneUnique(SysUser user)
+    {
+        return userService.checkPhoneUnique(user);
+    }
+
+    /**
+     * 校验email邮箱
+     */
+    @PostMapping("/checkEmailUnique")
+    @ResponseBody
+    public boolean checkEmailUnique(SysUser user)
+    {
+        return userService.checkEmailUnique(user);
+    }
+
+    /**
+     * 用户状态修改
+     */
+    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
+    @RequiresPermissions("system:user:edit")
+    @PostMapping("/changeStatus")
+    @ResponseBody
+    public AjaxResult changeStatus(SysUser user)
+    {
+        userService.checkUserAllowed(user);
+        userService.checkUserDataScope(user.getUserId());
+        return toAjax(userService.changeStatus(user));
+    }
+
+    /**
+     * 加载部门列表树
+     */
+    @RequiresPermissions("system:user:list")
+    @GetMapping("/deptTreeData")
+    @ResponseBody
+    public List<Ztree> deptTreeData()
+    {
+        List<Ztree> ztrees = deptService.selectDeptTree(new SysDept());
+        return ztrees;
+    }
+
+    /**
+     * 选择部门树
+     * 
+     * @param deptId 部门ID
+     */
+    @RequiresPermissions("system:user:list")
+    @GetMapping("/selectDeptTree/{deptId}")
+    public String selectDeptTree(@PathVariable("deptId") Long deptId, ModelMap mmap)
+    {
+        mmap.put("dept", deptService.selectDeptById(deptId));
+        return prefix + "/deptTree";
+    }
+}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/BuildController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/BuildController.java
new file mode 100644
index 0000000..4d3c128
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/BuildController.java
@@ -0,0 +1,26 @@
+package com.ruoyi.web.controller.tool;
+
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import com.ruoyi.common.core.controller.BaseController;
+
+/**
+ * build 表单构建
+ * 
+ * @author ruoyi
+ */
+@Controller
+@RequestMapping("/tool/build")
+public class BuildController extends BaseController
+{
+    private String prefix = "tool/build";
+
+    @RequiresPermissions("tool:build:view")
+    @GetMapping()
+    public String build()
+    {
+        return prefix + "/build";
+    }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/SwaggerController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/SwaggerController.java
new file mode 100644
index 0000000..de2ae6c
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/SwaggerController.java
@@ -0,0 +1,24 @@
+package com.ruoyi.web.controller.tool;
+
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import com.ruoyi.common.core.controller.BaseController;
+
+/**
+ * swagger 接口
+ * 
+ * @author ruoyi
+ */
+@Controller
+@RequestMapping("/tool/swagger")
+public class SwaggerController extends BaseController
+{
+    @RequiresPermissions("tool:swagger:view")
+    @GetMapping()
+    public String index()
+    {
+        return redirect("/swagger-ui/index.html");
+    }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/TestController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/TestController.java
new file mode 100644
index 0000000..b4f6bac
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/TestController.java
@@ -0,0 +1,183 @@
+package com.ruoyi.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.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.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 ruoyi
+ */
+@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/ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java b/ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java
new file mode 100644
index 0000000..e18d2cc
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java
@@ -0,0 +1,67 @@
+package com.ruoyi.web.core.config;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import com.ruoyi.common.config.RuoYiConfig;
+import io.swagger.annotations.ApiOperation;
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.service.Contact;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+
+/**
+ * Swagger2的接口配置
+ * 
+ * @author ruoyi
+ */
+@Configuration
+public class SwaggerConfig
+{
+    /** 是否开启swagger */
+    @Value("${swagger.enabled}")
+    private boolean enabled;
+    
+    /**
+     * 创建API
+     */
+    @Bean
+    public Docket createRestApi()
+    {
+        return new Docket(DocumentationType.OAS_30)
+                // 是否启用Swagger
+                .enable(enabled)
+                // 用来创建该API的基本信息,展示在文档的页面中(自定义展示的信息)
+                .apiInfo(apiInfo())
+                // 设置哪些接口暴露给Swagger展示
+                .select()
+                // 扫描所有有注解的api,用这种方式更灵活
+                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
+                // 扫描指定包中的swagger注解
+                //.apis(RequestHandlerSelectors.basePackage("com.ruoyi.project.tool.swagger"))
+                // 扫描所有 .apis(RequestHandlerSelectors.any())
+                .paths(PathSelectors.any())
+                .build();
+    }
+
+    /**
+     * 添加摘要信息
+     */
+    private ApiInfo apiInfo()
+    {
+        // 用ApiInfoBuilder进行定制
+        return new ApiInfoBuilder()
+                // 设置标题
+                .title("标题:若依管理系统_接口文档")
+                // 描述
+                .description("描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...")
+                // 作者信息
+                .contact(new Contact(RuoYiConfig.getName(), null, null))
+                // 版本
+                .version("版本号:" + RuoYiConfig.getVersion())
+                .build();
+    }
+}
diff --git a/ruoyi-admin/src/main/resources/application-druid.yml b/ruoyi-admin/src/main/resources/application-druid.yml
new file mode 100644
index 0000000..1801059
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/application-druid.yml
@@ -0,0 +1,61 @@
+# 数据源配置
+spring:
+    datasource:
+        type: com.alibaba.druid.pool.DruidDataSource
+        driverClassName: com.mysql.cj.jdbc.Driver
+        druid:
+            # 主库数据源
+            master:
+                url: jdbc:mysql://localhost:3306/ry?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                username: root
+                password: password
+            # 从库数据源
+            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
+            testWhileIdle: true
+            testOnBorrow: false
+            testOnReturn: false
+            webStatFilter: 
+                enabled: true
+            statViewServlet:
+                enabled: true
+                # 设置白名单,不填则允许所有访问
+                allow:
+                url-pattern: /druid/*
+                # 控制台管理用户名和密码
+                login-username: ruoyi
+                login-password: 123456
+            filter:
+                stat:
+                    enabled: true
+                    # 慢SQL记录
+                    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/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml
new file mode 100644
index 0000000..8fee864
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/application.yml
@@ -0,0 +1,142 @@
+# 项目相关配置
+ruoyi:
+  # 名称
+  name: RuoYi
+  # 版本
+  version: 4.8.0
+  # 版权年份
+  copyrightYear: 2025
+  # 实例演示开关
+  demoEnabled: true
+  # 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
+  profile: D:/ruoyi/uploadPath
+  # 获取ip地址开关
+  addressEnabled: false
+
+# 开发环境配置
+server:
+  # 服务器的HTTP端口,默认为80
+  port: 80
+  servlet:
+    # 应用的访问路径
+    context-path: /
+  tomcat:
+    # tomcat的URI编码
+    uri-encoding: UTF-8
+    # 连接数满后的排队数,默认为100
+    accept-count: 1000
+    threads:
+      # tomcat最大线程数,默认为200
+      max: 800
+      # Tomcat启动初始化的线程数,默认值10
+      min-spare: 100
+ 
+# 日志配置
+logging:
+  level:
+    com.ruoyi: debug
+    org.springframework: warn
+
+# 用户配置
+user:
+  password:
+    # 密码错误{maxRetryCount}次锁定10分钟
+    maxRetryCount: 5
+
+# Spring配置
+spring:
+  # 模板引擎
+  thymeleaf:
+    mode: HTML
+    encoding: utf-8
+    # 禁用缓存
+    cache: false
+  # 资源信息
+  messages:
+    # 国际化资源文件路径
+    basename: static/i18n/messages
+  jackson:
+    time-zone: GMT+8
+    date-format: yyyy-MM-dd HH:mm:ss
+  profiles:
+    active: druid
+  # 文件上传
+  servlet:
+    multipart:
+      # 单个文件大小
+      max-file-size: 10MB
+      # 设置总上传的文件大小
+      max-request-size: 20MB
+  # 服务模块
+  devtools:
+    restart:
+      # 热部署开关
+      enabled: true
+
+# MyBatis
+mybatis:
+  # 搜索指定包别名
+  typeAliasesPackage: com.ruoyi.**.domain
+  # 配置mapper的扫描,找到所有的mapper.xml映射文件
+  mapperLocations: classpath*:mapper/**/*Mapper.xml
+  # 加载全局的配置文件
+  configLocation: classpath:mybatis/mybatis-config.xml
+
+# PageHelper分页插件
+pagehelper:
+  helperDialect: mysql
+  supportMethodsArguments: true
+  params: count=countSql
+
+# Shiro
+shiro:
+  user:
+    # 登录地址
+    loginUrl: /login
+    # 权限认证失败地址
+    unauthorizedUrl: /unauth
+    # 首页地址
+    indexUrl: /index
+    # 验证码开关
+    captchaEnabled: true
+    # 验证码类型 math 数字计算 char 字符验证
+    captchaType: math
+  cookie:
+    # 设置Cookie的域名 默认空,即当前访问的域名
+    domain:
+    # 设置cookie的有效访问路径
+    path: /
+    # 设置HttpOnly属性
+    httpOnly: true
+    # 设置Cookie的过期时间,天为单位
+    maxAge: 30
+    # 设置密钥,务必保持唯一性(生成方式,直接拷贝到main运行即可)Base64.encodeToString(CipherUtils.generateNewKey(128, "AES").getEncoded()) (默认启动生成随机秘钥,随机秘钥会导致之前客户端RememberMe Cookie无效,如设置固定秘钥RememberMe Cookie则有效)
+    cipherKey:
+  session:
+    # Session超时时间,-1代表永不过期(默认30分钟)
+    expireTime: 30
+    # 同步session到数据库的周期(默认1分钟)
+    dbSyncPeriod: 1
+    # 相隔多久检查一次session的有效性,默认就是10分钟
+    validationInterval: 10
+    # 同一个用户最大会话数,比如2的意思是同一个账号允许最多同时两个人登录(默认-1不限制)
+    maxSession: -1
+    # 踢出之前登录的/之后登录的用户,默认踢出之前登录的用户
+    kickoutAfter: false
+  rememberMe:
+    # 是否开启记住我
+    enabled: true
+
+# 防止XSS攻击
+xss:
+  # 过滤开关
+  enabled: true
+  # 排除链接(多个用逗号分隔)
+  excludes: /system/notice/*
+  # 匹配链接
+  urlPatterns: /system/*,/monitor/*,/tool/*
+
+# Swagger配置
+swagger:
+  # 是否开启swagger
+  enabled: true
diff --git a/ruoyi-admin/src/main/resources/banner.txt b/ruoyi-admin/src/main/resources/banner.txt
new file mode 100644
index 0000000..0931cb8
--- /dev/null
+++ b/ruoyi-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/ruoyi-admin/src/main/resources/ehcache/ehcache-shiro.xml b/ruoyi-admin/src/main/resources/ehcache/ehcache-shiro.xml
new file mode 100644
index 0000000..7bf080f
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/ehcache/ehcache-shiro.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ehcache name="ruoyi" updateCheck="false">
+
+    <!-- 磁盘缓存位置 -->
+    <diskStore path="java.io.tmpdir"/>
+    
+    <!-- maxEntriesLocalHeap:堆内存中最大缓存对象数,0没有限制 -->
+    <!-- maxElementsInMemory: 在内存中缓存的element的最大数目。-->
+    <!-- eternal:elements是否永久有效,如果为true,timeouts将被忽略,element将永不过期 -->
+    <!-- timeToIdleSeconds:失效前的空闲秒数,当eternal为false时,这个属性才有效,0为不限制 -->
+    <!-- timeToLiveSeconds:失效前的存活秒数,创建时间到失效时间的间隔为存活时间,当eternal为false时,这个属性才有效,0为不限制 -->
+    <!-- overflowToDisk: 如果内存中数据超过内存限制,是否要缓存到磁盘上 -->
+    <!-- statistics:是否收集统计信息。如果需要监控缓存使用情况,应该打开这个选项。默认为关闭(统计会影响性能)。设置statistics="true"开启统计 -->
+    
+    <!-- 默认缓存 -->
+    <defaultCache
+            maxEntriesLocalHeap="1000"
+            eternal="false"
+            timeToIdleSeconds="3600"
+            timeToLiveSeconds="3600"
+            overflowToDisk="false">
+    </defaultCache>
+
+    <!-- 登录记录缓存 锁定10分钟 -->
+    <cache name="loginRecordCache"
+           maxEntriesLocalHeap="2000"
+           eternal="false"
+           timeToIdleSeconds="600"
+           timeToLiveSeconds="0"
+           overflowToDisk="false"
+           statistics="false">
+    </cache>
+
+    <!-- 系统活跃用户缓存 -->
+    <cache name="sys-userCache"
+           maxEntriesLocalHeap="10000"
+           overflowToDisk="false"
+           eternal="false"
+           diskPersistent="false"
+           timeToLiveSeconds="0"
+           timeToIdleSeconds="0"
+           statistics="false">
+    </cache>
+    
+    <!-- 系统用户授权缓存  没必要过期 -->
+    <cache name="sys-authCache"
+           maxEntriesLocalHeap="10000"
+           overflowToDisk="false"
+           eternal="false"
+           diskPersistent="false"
+           timeToLiveSeconds="0"
+           timeToIdleSeconds="0"
+           memoryStoreEvictionPolicy="LRU"
+           statistics="false"/>
+    
+    <!-- 系统缓存 -->
+    <cache name="sys-cache"
+           maxEntriesLocalHeap="1000"
+           eternal="true"
+           overflowToDisk="true"
+           statistics="false">
+    </cache>
+    
+    <!-- 系统参数缓存 -->
+    <cache name="sys-config"
+           maxEntriesLocalHeap="1000"
+           eternal="true"
+           overflowToDisk="true"
+           statistics="false">
+    </cache>
+    
+    <!-- 系统字典缓存 -->
+    <cache name="sys-dict"
+           maxEntriesLocalHeap="1000"
+           eternal="true"
+           overflowToDisk="true"
+           statistics="false">
+    </cache>
+    
+    <!-- 系统会话缓存 -->
+    <cache name="shiro-activeSessionCache"
+           maxEntriesLocalHeap="10000"
+           overflowToDisk="false"
+           eternal="false"
+           diskPersistent="false"
+           timeToLiveSeconds="0"
+           timeToIdleSeconds="0"
+           statistics="false"/>
+    
+</ehcache>
+	
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/logback.xml b/ruoyi-admin/src/main/resources/logback.xml
new file mode 100644
index 0000000..a360583
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/logback.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+    <!-- 日志存放路径 -->
+	<property name="log.path" value="/home/ruoyi/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.ruoyi" 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/ruoyi-admin/src/main/resources/mybatis/mybatis-config.xml b/ruoyi-admin/src/main/resources/mybatis/mybatis-config.xml
new file mode 100644
index 0000000..ac47c03
--- /dev/null
+++ b/ruoyi-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/ruoyi-admin/src/main/resources/static/ajax/libs/beautifyhtml/beautifyhtml.js b/ruoyi-admin/src/main/resources/static/ajax/libs/beautifyhtml/beautifyhtml.js
new file mode 100644
index 0000000..ea69dec
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/beautifyhtml/beautifyhtml.js
@@ -0,0 +1,617 @@
+/*jshint curly:true, eqeqeq:true, laxbreak:true, noempty:false */
+/*
+
+  The MIT License (MIT)
+
+  Copyright (c) 2007-2013 Einar Lielmanis and contributors.
+
+  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.
+
+
+ Style HTML
+---------------
+
+  Written by Nochum Sossonko, (nsossonko@hotmail.com)
+
+  Based on code initially developed by: Einar Lielmanis, <elfz@laacz.lv>
+    http://jsbeautifier.org/
+
+  Usage:
+    style_html(html_source);
+
+    style_html(html_source, options);
+
+  The options are:
+    indent_size (default 4)          — indentation size,
+    indent_char (default space)      — character to indent with,
+    max_char (default 250)            -  maximum amount of characters per line (0 = disable)
+    brace_style (default "collapse") - "collapse" | "expand" | "end-expand"
+            put braces on the same line as control statements (default), or put braces on own line (Allman / ANSI style), or just put end braces on own line.
+    unformatted (defaults to inline tags) - list of tags, that shouldn't be reformatted
+    indent_scripts (default normal)  - "keep"|"separate"|"normal"
+
+    e.g.
+
+    style_html(html_source, {
+      'indent_size': 2,
+      'indent_char': ' ',
+      'max_char': 78,
+      'brace_style': 'expand',
+      'unformatted': ['a', 'sub', 'sup', 'b', 'i', 'u']
+    });
+*/
+
+(function() {
+
+    function style_html(html_source, options, js_beautify, css_beautify) {
+    //Wrapper function to invoke all the necessary constructors and deal with the output.
+
+      var multi_parser,
+          indent_size,
+          indent_character,
+          max_char,
+          brace_style,
+          unformatted;
+
+      options = options || {};
+      indent_size = options.indent_size || 4;
+      indent_character = options.indent_char || ' ';
+      brace_style = options.brace_style || 'collapse';
+      max_char = options.max_char === 0 ? Infinity : options.max_char || 250;
+      unformatted = options.unformatted || ['a', 'span', 'bdo', 'em', 'strong', 'dfn', 'code', 'samp', 'kbd', 'var', 'cite', 'abbr', 'acronym', 'q', 'sub', 'sup', 'tt', 'i', 'b', 'big', 'small', 'u', 's', 'strike', 'font', 'ins', 'del', 'pre', 'address', 'dt', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'];
+
+      function Parser() {
+
+        this.pos = 0; //Parser position
+        this.token = '';
+        this.current_mode = 'CONTENT'; //reflects the current Parser mode: TAG/CONTENT
+        this.tags = { //An object to hold tags, their position, and their parent-tags, initiated with default values
+          parent: 'parent1',
+          parentcount: 1,
+          parent1: ''
+        };
+        this.tag_type = '';
+        this.token_text = this.last_token = this.last_text = this.token_type = '';
+
+        this.Utils = { //Uilities made available to the various functions
+          whitespace: "\n\r\t ".split(''),
+          single_token: 'br,input,link,meta,!doctype,basefont,base,area,hr,wbr,param,img,isindex,?xml,embed,?php,?,?='.split(','), //all the single tags for HTML
+          extra_liners: 'head,body,/html'.split(','), //for tags that need a line of whitespace before them
+          in_array: function (what, arr) {
+            for (var i=0; i<arr.length; i++) {
+              if (what === arr[i]) {
+                return true;
+              }
+            }
+            return false;
+          }
+        };
+
+        this.get_content = function () { //function to capture regular content between tags
+
+          var input_char = '',
+              content = [],
+              space = false; //if a space is needed
+
+          while (this.input.charAt(this.pos) !== '<') {
+            if (this.pos >= this.input.length) {
+              return content.length?content.join(''):['', 'TK_EOF'];
+            }
+
+            input_char = this.input.charAt(this.pos);
+            this.pos++;
+            this.line_char_count++;
+
+            if (this.Utils.in_array(input_char, this.Utils.whitespace)) {
+              if (content.length) {
+                space = true;
+              }
+              this.line_char_count--;
+              continue; //don't want to insert unnecessary space
+            }
+            else if (space) {
+              if (this.line_char_count >= this.max_char) { //insert a line when the max_char is reached
+                content.push('\n');
+                for (var i=0; i<this.indent_level; i++) {
+                  content.push(this.indent_string);
+                }
+                this.line_char_count = 0;
+              }
+              else{
+                content.push(' ');
+                this.line_char_count++;
+              }
+              space = false;
+            }
+            content.push(input_char); //letter at-a-time (or string) inserted to an array
+          }
+          return content.length?content.join(''):'';
+        };
+
+        this.get_contents_to = function (name) { //get the full content of a script or style to pass to js_beautify
+          if (this.pos === this.input.length) {
+            return ['', 'TK_EOF'];
+          }
+          var input_char = '';
+          var content = '';
+          var reg_match = new RegExp('</' + name + '\\s*>', 'igm');
+          reg_match.lastIndex = this.pos;
+          var reg_array = reg_match.exec(this.input);
+          var end_script = reg_array?reg_array.index:this.input.length; //absolute end of script
+          if(this.pos < end_script) { //get everything in between the script tags
+            content = this.input.substring(this.pos, end_script);
+            this.pos = end_script;
+          }
+          return content;
+        };
+
+        this.record_tag = function (tag){ //function to record a tag and its parent in this.tags Object
+          if (this.tags[tag + 'count']) { //check for the existence of this tag type
+            this.tags[tag + 'count']++;
+            this.tags[tag + this.tags[tag + 'count']] = this.indent_level; //and record the present indent level
+          }
+          else { //otherwise initialize this tag type
+            this.tags[tag + 'count'] = 1;
+            this.tags[tag + this.tags[tag + 'count']] = this.indent_level; //and record the present indent level
+          }
+          this.tags[tag + this.tags[tag + 'count'] + 'parent'] = this.tags.parent; //set the parent (i.e. in the case of a div this.tags.div1parent)
+          this.tags.parent = tag + this.tags[tag + 'count']; //and make this the current parent (i.e. in the case of a div 'div1')
+        };
+
+        this.retrieve_tag = function (tag) { //function to retrieve the opening tag to the corresponding closer
+          if (this.tags[tag + 'count']) { //if the openener is not in the Object we ignore it
+            var temp_parent = this.tags.parent; //check to see if it's a closable tag.
+            while (temp_parent) { //till we reach '' (the initial value);
+              if (tag + this.tags[tag + 'count'] === temp_parent) { //if this is it use it
+                break;
+              }
+              temp_parent = this.tags[temp_parent + 'parent']; //otherwise keep on climbing up the DOM Tree
+            }
+            if (temp_parent) { //if we caught something
+              this.indent_level = this.tags[tag + this.tags[tag + 'count']]; //set the indent_level accordingly
+              this.tags.parent = this.tags[temp_parent + 'parent']; //and set the current parent
+            }
+            delete this.tags[tag + this.tags[tag + 'count'] + 'parent']; //delete the closed tags parent reference...
+            delete this.tags[tag + this.tags[tag + 'count']]; //...and the tag itself
+            if (this.tags[tag + 'count'] === 1) {
+              delete this.tags[tag + 'count'];
+            }
+            else {
+              this.tags[tag + 'count']--;
+            }
+          }
+        };
+
+        this.get_tag = function (peek) { //function to get a full tag and parse its type
+          var input_char = '',
+              content = [],
+              comment = '',
+              space = false,
+              tag_start, tag_end,
+              orig_pos = this.pos,
+              orig_line_char_count = this.line_char_count;
+
+          peek = peek !== undefined ? peek : false;
+
+          do {
+            if (this.pos >= this.input.length) {
+              if (peek) {
+                this.pos = orig_pos;
+                this.line_char_count = orig_line_char_count;
+              }
+              return content.length?content.join(''):['', 'TK_EOF'];
+            }
+
+            input_char = this.input.charAt(this.pos);
+            this.pos++;
+            this.line_char_count++;
+
+            if (this.Utils.in_array(input_char, this.Utils.whitespace)) { //don't want to insert unnecessary space
+              space = true;
+              this.line_char_count--;
+              continue;
+            }
+
+            if (input_char === "'" || input_char === '"') {
+              if (!content[1] || content[1] !== '!') { //if we're in a comment strings don't get treated specially
+                input_char += this.get_unformatted(input_char);
+                space = true;
+              }
+            }
+
+            if (input_char === '=') { //no space before =
+              space = false;
+            }
+
+            if (content.length && content[content.length-1] !== '=' && input_char !== '>' && space) {
+                //no space after = or before >
+              if (this.line_char_count >= this.max_char) {
+                this.print_newline(false, content);
+                this.line_char_count = 0;
+              }
+              else {
+                content.push(' ');
+                this.line_char_count++;
+              }
+              space = false;
+            }
+            if (input_char === '<') {
+              tag_start = this.pos - 1;
+            }
+            content.push(input_char); //inserts character at-a-time (or string)
+          } while (input_char !== '>');
+
+          var tag_complete = content.join('');
+          var tag_index;
+          if (tag_complete.indexOf(' ') !== -1) { //if there's whitespace, thats where the tag name ends
+            tag_index = tag_complete.indexOf(' ');
+          }
+          else { //otherwise go with the tag ending
+            tag_index = tag_complete.indexOf('>');
+          }
+          var tag_check = tag_complete.substring(1, tag_index).toLowerCase();
+          if (tag_complete.charAt(tag_complete.length-2) === '/' ||
+            this.Utils.in_array(tag_check, this.Utils.single_token)) { //if this tag name is a single tag type (either in the list or has a closing /)
+            if ( ! peek) {
+              this.tag_type = 'SINGLE';
+            }
+          }
+          else if (tag_check === 'script') { //for later script handling
+            if ( ! peek) {
+              this.record_tag(tag_check);
+              this.tag_type = 'SCRIPT';
+            }
+          }
+          else if (tag_check === 'style') { //for future style handling (for now it justs uses get_content)
+            if ( ! peek) {
+              this.record_tag(tag_check);
+              this.tag_type = 'STYLE';
+            }
+          }
+          else if (this.is_unformatted(tag_check, unformatted)) { // do not reformat the "unformatted" tags
+            comment = this.get_unformatted('</'+tag_check+'>', tag_complete); //...delegate to get_unformatted function
+            content.push(comment);
+            // Preserve collapsed whitespace either before or after this tag.
+            if (tag_start > 0 && this.Utils.in_array(this.input.charAt(tag_start - 1), this.Utils.whitespace)){
+                content.splice(0, 0, this.input.charAt(tag_start - 1));
+            }
+            tag_end = this.pos - 1;
+            if (this.Utils.in_array(this.input.charAt(tag_end + 1), this.Utils.whitespace)){
+                content.push(this.input.charAt(tag_end + 1));
+            }
+            this.tag_type = 'SINGLE';
+          }
+          else if (tag_check.charAt(0) === '!') { //peek for <!-- comment
+            if (tag_check.indexOf('[if') !== -1) { //peek for <!--[if conditional comment
+              if (tag_complete.indexOf('!IE') !== -1) { //this type needs a closing --> so...
+                comment = this.get_unformatted('-->', tag_complete); //...delegate to get_unformatted
+                content.push(comment);
+              }
+              if ( ! peek) {
+                this.tag_type = 'START';
+              }
+            }
+            else if (tag_check.indexOf('[endif') !== -1) {//peek for <!--[endif end conditional comment
+              this.tag_type = 'END';
+              this.unindent();
+            }
+            else if (tag_check.indexOf('[cdata[') !== -1) { //if it's a <[cdata[ comment...
+              comment = this.get_unformatted(']]>', tag_complete); //...delegate to get_unformatted function
+              content.push(comment);
+              if ( ! peek) {
+                this.tag_type = 'SINGLE'; //<![CDATA[ comments are treated like single tags
+              }
+            }
+            else {
+              comment = this.get_unformatted('-->', tag_complete);
+              content.push(comment);
+              this.tag_type = 'SINGLE';
+            }
+          }
+          else if ( ! peek) {
+            if (tag_check.charAt(0) === '/') { //this tag is a double tag so check for tag-ending
+              this.retrieve_tag(tag_check.substring(1)); //remove it and all ancestors
+              this.tag_type = 'END';
+            }
+            else { //otherwise it's a start-tag
+              this.record_tag(tag_check); //push it on the tag stack
+              this.tag_type = 'START';
+            }
+            if (this.Utils.in_array(tag_check, this.Utils.extra_liners)) { //check if this double needs an extra line
+              this.print_newline(true, this.output);
+            }
+          }
+
+          if (peek) {
+            this.pos = orig_pos;
+            this.line_char_count = orig_line_char_count;
+          }
+
+          return content.join(''); //returns fully formatted tag
+        };
+
+        this.get_unformatted = function (delimiter, orig_tag) { //function to return unformatted content in its entirety
+
+          if (orig_tag && orig_tag.toLowerCase().indexOf(delimiter) !== -1) {
+            return '';
+          }
+          var input_char = '';
+          var content = '';
+          var space = true;
+          do {
+
+            if (this.pos >= this.input.length) {
+              return content;
+            }
+
+            input_char = this.input.charAt(this.pos);
+            this.pos++;
+
+            if (this.Utils.in_array(input_char, this.Utils.whitespace)) {
+              if (!space) {
+                this.line_char_count--;
+                continue;
+              }
+              if (input_char === '\n' || input_char === '\r') {
+                content += '\n';
+                /*  Don't change tab indention for unformatted blocks.  If using code for html editing, this will greatly affect <pre> tags if they are specified in the 'unformatted array'
+                for (var i=0; i<this.indent_level; i++) {
+                  content += this.indent_string;
+                }
+                space = false; //...and make sure other indentation is erased
+                */
+                this.line_char_count = 0;
+                continue;
+              }
+            }
+            content += input_char;
+            this.line_char_count++;
+            space = true;
+
+
+          } while (content.toLowerCase().indexOf(delimiter) === -1);
+          return content;
+        };
+
+        this.get_token = function () { //initial handler for token-retrieval
+          var token;
+
+          if (this.last_token === 'TK_TAG_SCRIPT' || this.last_token === 'TK_TAG_STYLE') { //check if we need to format javascript
+           var type = this.last_token.substr(7);
+           token = this.get_contents_to(type);
+            if (typeof token !== 'string') {
+              return token;
+            }
+            return [token, 'TK_' + type];
+          }
+          if (this.current_mode === 'CONTENT') {
+            token = this.get_content();
+            if (typeof token !== 'string') {
+              return token;
+            }
+            else {
+              return [token, 'TK_CONTENT'];
+            }
+          }
+
+          if (this.current_mode === 'TAG') {
+            token = this.get_tag();
+            if (typeof token !== 'string') {
+              return token;
+            }
+            else {
+              var tag_name_type = 'TK_TAG_' + this.tag_type;
+              return [token, tag_name_type];
+            }
+          }
+        };
+
+        this.get_full_indent = function (level) {
+          level = this.indent_level + level || 0;
+          if (level < 1) {
+            return '';
+          }
+
+          return Array(level + 1).join(this.indent_string);
+        };
+
+        this.is_unformatted = function(tag_check, unformatted) {
+            //is this an HTML5 block-level link?
+            if (!this.Utils.in_array(tag_check, unformatted)){
+                return false;
+            }
+
+            if (tag_check.toLowerCase() !== 'a' || !this.Utils.in_array('a', unformatted)){
+                return true;
+            }
+
+            //at this point we have an  tag; is its first child something we want to remain
+            //unformatted?
+            var next_tag = this.get_tag(true /* peek. */);
+
+            // tets next_tag to see if it is just html tag (no external content)
+            var tag = (next_tag || "").match(/^\s*<\s*\/?([a-z]*)\s*[^>]*>\s*$/);
+
+            // if next_tag comes back but is not an isolated tag, then
+            // let's treat the 'a' tag as having content
+            // and respect the unformatted option
+            if (!tag || this.Utils.in_array(tag, unformatted)){
+                return true;
+            } else {
+                return false;
+            }
+        };
+
+        this.printer = function (js_source, indent_character, indent_size, max_char, brace_style) { //handles input/output and some other printing functions
+
+          this.input = js_source || ''; //gets the input for the Parser
+          this.output = [];
+          this.indent_character = indent_character;
+          this.indent_string = '';
+          this.indent_size = indent_size;
+          this.brace_style = brace_style;
+          this.indent_level = 0;
+          this.max_char = max_char;
+          this.line_char_count = 0; //count to see if max_char was exceeded
+
+          for (var i=0; i<this.indent_size; i++) {
+            this.indent_string += this.indent_character;
+          }
+
+          this.print_newline = function (ignore, arr) {
+            this.line_char_count = 0;
+            if (!arr || !arr.length) {
+              return;
+            }
+            if (!ignore) { //we might want the extra line
+              while (this.Utils.in_array(arr[arr.length-1], this.Utils.whitespace)) {
+                arr.pop();
+              }
+            }
+            arr.push('\n');
+            for (var i=0; i<this.indent_level; i++) {
+              arr.push(this.indent_string);
+            }
+          };
+
+          this.print_token = function (text) {
+            this.output.push(text);
+          };
+
+          this.indent = function () {
+            this.indent_level++;
+          };
+
+          this.unindent = function () {
+            if (this.indent_level > 0) {
+              this.indent_level--;
+            }
+          };
+        };
+        return this;
+      }
+
+      /*_____________________--------------------_____________________*/
+
+      multi_parser = new Parser(); //wrapping functions Parser
+      multi_parser.printer(html_source, indent_character, indent_size, max_char, brace_style); //initialize starting values
+
+      while (true) {
+          var t = multi_parser.get_token();
+          multi_parser.token_text = t[0];
+          multi_parser.token_type = t[1];
+
+        if (multi_parser.token_type === 'TK_EOF') {
+          break;
+        }
+
+        switch (multi_parser.token_type) {
+          case 'TK_TAG_START':
+            multi_parser.print_newline(false, multi_parser.output);
+            multi_parser.print_token(multi_parser.token_text);
+            multi_parser.indent();
+            multi_parser.current_mode = 'CONTENT';
+            break;
+          case 'TK_TAG_STYLE':
+          case 'TK_TAG_SCRIPT':
+            multi_parser.print_newline(false, multi_parser.output);
+            multi_parser.print_token(multi_parser.token_text);
+            multi_parser.current_mode = 'CONTENT';
+            break;
+          case 'TK_TAG_END':
+            //Print new line only if the tag has no content and has child
+            if (multi_parser.last_token === 'TK_CONTENT' && multi_parser.last_text === '') {
+                var tag_name = multi_parser.token_text.match(/\w+/)[0];
+                var tag_extracted_from_last_output = multi_parser.output[multi_parser.output.length -1].match(/<\s*(\w+)/);
+                if (tag_extracted_from_last_output === null || tag_extracted_from_last_output[1] !== tag_name) {
+                    multi_parser.print_newline(true, multi_parser.output);
+                }
+            }
+            multi_parser.print_token(multi_parser.token_text);
+            multi_parser.current_mode = 'CONTENT';
+            break;
+          case 'TK_TAG_SINGLE':
+            // Don't add a newline before elements that should remain unformatted.
+            var tag_check = multi_parser.token_text.match(/^\s*<([a-z]+)/i);
+            if (!tag_check || !multi_parser.Utils.in_array(tag_check[1], unformatted)){
+                multi_parser.print_newline(false, multi_parser.output);
+            }
+            multi_parser.print_token(multi_parser.token_text);
+            multi_parser.current_mode = 'CONTENT';
+            break;
+          case 'TK_CONTENT':
+            if (multi_parser.token_text !== '') {
+              multi_parser.print_token(multi_parser.token_text);
+            }
+            multi_parser.current_mode = 'TAG';
+            break;
+          case 'TK_STYLE':
+          case 'TK_SCRIPT':
+            if (multi_parser.token_text !== '') {
+              multi_parser.output.push('\n');
+              var text = multi_parser.token_text,
+                  _beautifier,
+                  script_indent_level = 1;
+              if (multi_parser.token_type === 'TK_SCRIPT') {
+                _beautifier = typeof js_beautify === 'function' && js_beautify;
+              } else if (multi_parser.token_type === 'TK_STYLE') {
+                _beautifier = typeof css_beautify === 'function' && css_beautify;
+              }
+
+              if (options.indent_scripts === "keep") {
+                script_indent_level = 0;
+              } else if (options.indent_scripts === "separate") {
+                script_indent_level = -multi_parser.indent_level;
+              }
+
+              var indentation = multi_parser.get_full_indent(script_indent_level);
+              if (_beautifier) {
+                // call the Beautifier if avaliable
+                text = _beautifier(text.replace(/^\s*/, indentation), options);
+              } else {
+                // simply indent the string otherwise
+                var white = text.match(/^\s*/)[0];
+                var _level = white.match(/[^\n\r]*$/)[0].split(multi_parser.indent_string).length - 1;
+                var reindent = multi_parser.get_full_indent(script_indent_level -_level);
+                text = text.replace(/^\s*/, indentation)
+                       .replace(/\r\n|\r|\n/g, '\n' + reindent)
+                       .replace(/\s*$/, '');
+              }
+              if (text) {
+                multi_parser.print_token(text);
+                multi_parser.print_newline(true, multi_parser.output);
+              }
+            }
+            multi_parser.current_mode = 'TAG';
+            break;
+        }
+        multi_parser.last_token = multi_parser.token_type;
+        multi_parser.last_text = multi_parser.token_text;
+      }
+      return multi_parser.output.join('');
+    }
+
+    // If we're running a web page and don't have either of the above, add our one global
+    window.html_beautify = function(html_source, options) {
+        return style_html(html_source, options, window.js_beautify, window.css_beautify);
+    };
+
+}());
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/blockUI/jquery.blockUI.js b/ruoyi-admin/src/main/resources/static/ajax/libs/blockUI/jquery.blockUI.js
new file mode 100644
index 0000000..552613d
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/blockUI/jquery.blockUI.js
@@ -0,0 +1,620 @@
+/*!
+ * jQuery blockUI plugin
+ * Version 2.70.0-2014.11.23
+ * Requires jQuery v1.7 or later
+ *
+ * Examples at: http://malsup.com/jquery/block/
+ * Copyright (c) 2007-2013 M. Alsup
+ * Dual licensed under the MIT and GPL licenses:
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * Thanks to Amir-Hossein Sobhi for some excellent contributions!
+ */
+
+;(function() {
+/*jshint eqeqeq:false curly:false latedef:false */
+"use strict";
+
+	function setup($) {
+		$.fn._fadeIn = $.fn.fadeIn;
+
+		var noOp = $.noop || function() {};
+
+		// this bit is to ensure we don't call setExpression when we shouldn't (with extra muscle to handle
+		// confusing userAgent strings on Vista)
+		var msie = /MSIE/.test(navigator.userAgent);
+		var ie6  = /MSIE 6.0/.test(navigator.userAgent) && ! /MSIE 8.0/.test(navigator.userAgent);
+		var mode = document.documentMode || 0;
+		var setExpr = $.isFunction( document.createElement('div').style.setExpression );
+
+		// global $ methods for blocking/unblocking the entire page
+		$.blockUI   = function(opts) { install(window, opts); };
+		$.unblockUI = function(opts) { remove(window, opts); };
+
+		// convenience method for quick growl-like notifications  (http://www.google.com/search?q=growl)
+		$.growlUI = function(title, message, timeout, onClose) {
+			var $m = $('<div class="growlUI"></div>');
+			if (title) $m.append('<h1>'+title+'</h1>');
+			if (message) $m.append('<h2>'+message+'</h2>');
+			if (timeout === undefined) timeout = 3000;
+
+			// Added by konapun: Set timeout to 30 seconds if this growl is moused over, like normal toast notifications
+			var callBlock = function(opts) {
+				opts = opts || {};
+
+				$.blockUI({
+					message: $m,
+					fadeIn : typeof opts.fadeIn  !== 'undefined' ? opts.fadeIn  : 700,
+					fadeOut: typeof opts.fadeOut !== 'undefined' ? opts.fadeOut : 1000,
+					timeout: typeof opts.timeout !== 'undefined' ? opts.timeout : timeout,
+					centerY: false,
+					showOverlay: false,
+					onUnblock: onClose,
+					css: $.blockUI.defaults.growlCSS
+				});
+			};
+
+			callBlock();
+			var nonmousedOpacity = $m.css('opacity');
+			$m.mouseover(function() {
+				callBlock({
+					fadeIn: 0,
+					timeout: 30000
+				});
+
+				var displayBlock = $('.blockMsg');
+				displayBlock.stop(); // cancel fadeout if it has started
+				displayBlock.fadeTo(300, 1); // make it easier to read the message by removing transparency
+			}).mouseout(function() {
+				$('.blockMsg').fadeOut(1000);
+			});
+			// End konapun additions
+		};
+
+		// plugin method for blocking element content
+		$.fn.block = function(opts) {
+			if ( this[0] === window ) {
+				$.blockUI( opts );
+				return this;
+			}
+			var fullOpts = $.extend({}, $.blockUI.defaults, opts || {});
+			this.each(function() {
+				var $el = $(this);
+				if (fullOpts.ignoreIfBlocked && $el.data('blockUI.isBlocked'))
+					return;
+				$el.unblock({ fadeOut: 0 });
+			});
+
+			return this.each(function() {
+				if ($.css(this,'position') == 'static') {
+					this.style.position = 'relative';
+					$(this).data('blockUI.static', true);
+				}
+				this.style.zoom = 1; // force 'hasLayout' in ie
+				install(this, opts);
+			});
+		};
+
+		// plugin method for unblocking element content
+		$.fn.unblock = function(opts) {
+			if ( this[0] === window ) {
+				$.unblockUI( opts );
+				return this;
+			}
+			return this.each(function() {
+				remove(this, opts);
+			});
+		};
+
+		$.blockUI.version = 2.70; // 2nd generation blocking at no extra cost!
+
+		// override these in your code to change the default behavior and style
+		$.blockUI.defaults = {
+			// message displayed when blocking (use null for no message)
+			message:  '<div class="loaderbox"><div class="loading-activity"></div> 加载中......</div>',
+
+			title: null,		// title string; only used when theme == true
+			draggable: true,	// only used when theme == true (requires jquery-ui.js to be loaded)
+
+			theme: false, // set to true to use with jQuery UI themes
+
+			// styles for the message when blocking; if you wish to disable
+			// these and use an external stylesheet then do this in your code:
+			// $.blockUI.defaults.css = {};
+			css: {
+				padding:	0,
+				margin:		0,
+				width:		'30%',
+				top:		'40%',
+				left:		'35%',
+				textAlign:	'center',
+				color:		'#000',
+				border:		'0px',
+				backgroundColor:'transparent',
+				cursor:		'wait'
+			},
+
+			// minimal style set used when themes are used
+			themedCSS: {
+				width:	'30%',
+				top:	'40%',
+				left:	'35%'
+			},
+
+			// styles for the overlay
+			overlayCSS:  {
+				backgroundColor:	'#000',
+				opacity:			0.6,
+				cursor:				'wait'
+			},
+
+			// style to replace wait cursor before unblocking to correct issue
+			// of lingering wait cursor
+			cursorReset: 'default',
+
+			// styles applied when using $.growlUI
+			growlCSS: {
+				width:		'350px',
+				top:		'10px',
+				left:		'',
+				right:		'10px',
+				border:		'none',
+				padding:	'5px',
+				opacity:	0.6,
+				cursor:		'default',
+				color:		'#fff',
+				backgroundColor: '#000',
+				'-webkit-border-radius':'10px',
+				'-moz-border-radius':	'10px',
+				'border-radius':		'10px'
+			},
+
+			// IE issues: 'about:blank' fails on HTTPS and javascript:false is s-l-o-w
+			// (hat tip to Jorge H. N. de Vasconcelos)
+			/*jshint scripturl:true */
+			iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank',
+
+			// force usage of iframe in non-IE browsers (handy for blocking applets)
+			forceIframe: false,
+
+			// z-index for the blocking overlay
+			baseZ: 1000,
+
+			// set these to true to have the message automatically centered
+			centerX: true, // <-- only effects element blocking (page block controlled via css above)
+			centerY: true,
+
+			// allow body element to be stetched in ie6; this makes blocking look better
+			// on "short" pages.  disable if you wish to prevent changes to the body height
+			allowBodyStretch: true,
+
+			// enable if you want key and mouse events to be disabled for content that is blocked
+			bindEvents: true,
+
+			// be default blockUI will supress tab navigation from leaving blocking content
+			// (if bindEvents is true)
+			constrainTabKey: true,
+
+			// fadeIn time in millis; set to 0 to disable fadeIn on block
+			fadeIn:  200,
+
+			// fadeOut time in millis; set to 0 to disable fadeOut on unblock
+			fadeOut:  400,
+
+			// time in millis to wait before auto-unblocking; set to 0 to disable auto-unblock
+			timeout: 0,
+
+			// disable if you don't want to show the overlay
+			showOverlay: true,
+
+			// if true, focus will be placed in the first available input field when
+			// page blocking
+			focusInput: true,
+
+            // elements that can receive focus
+            focusableElements: ':input:enabled:visible',
+
+			// suppresses the use of overlay styles on FF/Linux (due to performance issues with opacity)
+			// no longer needed in 2012
+			// applyPlatformOpacityRules: true,
+
+			// callback method invoked when fadeIn has completed and blocking message is visible
+			onBlock: null,
+
+			// callback method invoked when unblocking has completed; the callback is
+			// passed the element that has been unblocked (which is the window object for page
+			// blocks) and the options that were passed to the unblock call:
+			//	onUnblock(element, options)
+			onUnblock: null,
+
+			// callback method invoked when the overlay area is clicked.
+			// setting this will turn the cursor to a pointer, otherwise cursor defined in overlayCss will be used.
+			onOverlayClick: null,
+
+			// don't ask; if you really must know: http://groups.google.com/group/jquery-en/browse_thread/thread/36640a8730503595/2f6a79a77a78e493#2f6a79a77a78e493
+			quirksmodeOffsetHack: 4,
+
+			// class name of the message block
+			blockMsgClass: 'blockMsg',
+
+			// if it is already blocked, then ignore it (don't unblock and reblock)
+			ignoreIfBlocked: false
+		};
+
+		// private data and functions follow...
+
+		var pageBlock = null;
+		var pageBlockEls = [];
+
+		function install(el, opts) {
+			var css, themedCSS;
+			var full = (el == window);
+			var msg = (opts && opts.message !== undefined ? opts.message : undefined);
+			opts = $.extend({}, $.blockUI.defaults, opts || {});
+
+			if (opts.ignoreIfBlocked && $(el).data('blockUI.isBlocked'))
+				return;
+
+			opts.overlayCSS = $.extend({}, $.blockUI.defaults.overlayCSS, opts.overlayCSS || {});
+			css = $.extend({}, $.blockUI.defaults.css, opts.css || {});
+			if (opts.onOverlayClick)
+				opts.overlayCSS.cursor = 'pointer';
+
+			themedCSS = $.extend({}, $.blockUI.defaults.themedCSS, opts.themedCSS || {});
+			msg = msg === undefined ? opts.message : msg;
+
+			// remove the current block (if there is one)
+			if (full && pageBlock)
+				remove(window, {fadeOut:0});
+
+			// if an existing element is being used as the blocking content then we capture
+			// its current place in the DOM (and current display style) so we can restore
+			// it when we unblock
+			if (msg && typeof msg != 'string' && (msg.parentNode || msg.jquery)) {
+				var node = msg.jquery ? msg[0] : msg;
+				var data = {};
+				$(el).data('blockUI.history', data);
+				data.el = node;
+				data.parent = node.parentNode;
+				data.display = node.style.display;
+				data.position = node.style.position;
+				if (data.parent)
+					data.parent.removeChild(node);
+			}
+
+			$(el).data('blockUI.onUnblock', opts.onUnblock);
+			var z = opts.baseZ;
+
+			// blockUI uses 3 layers for blocking, for simplicity they are all used on every platform;
+			// layer1 is the iframe layer which is used to supress bleed through of underlying content
+			// layer2 is the overlay layer which has opacity and a wait cursor (by default)
+			// layer3 is the message content that is displayed while blocking
+			var lyr1, lyr2, lyr3, s;
+			if (msie || opts.forceIframe)
+				lyr1 = $('<iframe class="blockUI" style="z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;position:absolute;width:100%;height:100%;top:0;left:0" src="'+opts.iframeSrc+'"></iframe>');
+			else
+				lyr1 = $('<div class="blockUI" style="display:none"></div>');
+
+			if (opts.theme)
+				lyr2 = $('<div class="blockUI blockOverlay ui-widget-overlay" style="z-index:'+ (z++) +';display:none"></div>');
+			else
+				lyr2 = $('<div class="blockUI blockOverlay" style="z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;width:100%;height:100%;top:0;left:0"></div>');
+
+			if (opts.theme && full) {
+				s = '<div class="blockUI ' + opts.blockMsgClass + ' blockPage ui-dialog ui-widget ui-corner-all" style="z-index:'+(z+10)+';display:none;position:fixed">';
+				if ( opts.title ) {
+					s += '<div class="ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle">'+(opts.title || '&nbsp;')+'</div>';
+				}
+				s += '<div class="ui-widget-content ui-dialog-content"></div>';
+				s += '</div>';
+			}
+			else if (opts.theme) {
+				s = '<div class="blockUI ' + opts.blockMsgClass + ' blockElement ui-dialog ui-widget ui-corner-all" style="z-index:'+(z+10)+';display:none;position:absolute">';
+				if ( opts.title ) {
+					s += '<div class="ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle">'+(opts.title || '&nbsp;')+'</div>';
+				}
+				s += '<div class="ui-widget-content ui-dialog-content"></div>';
+				s += '</div>';
+			}
+			else if (full) {
+				s = '<div class="blockUI ' + opts.blockMsgClass + ' blockPage" style="z-index:'+(z+10)+';display:none;position:fixed"></div>';
+			}
+			else {
+				s = '<div class="blockUI ' + opts.blockMsgClass + ' blockElement" style="z-index:'+(z+10)+';display:none;position:absolute"></div>';
+			}
+			lyr3 = $(s);
+
+			// if we have a message, style it
+			if (msg) {
+				if (opts.theme) {
+					lyr3.css(themedCSS);
+					lyr3.addClass('ui-widget-content');
+				}
+				else
+					lyr3.css(css);
+			}
+
+			// style the overlay
+			if (!opts.theme /*&& (!opts.applyPlatformOpacityRules)*/)
+				lyr2.css(opts.overlayCSS);
+			lyr2.css('position', full ? 'fixed' : 'absolute');
+
+			// make iframe layer transparent in IE
+			if (msie || opts.forceIframe)
+				lyr1.css('opacity',0.0);
+
+			//$([lyr1[0],lyr2[0],lyr3[0]]).appendTo(full ? 'body' : el);
+			var layers = [lyr1,lyr2,lyr3], $par = full ? $('body') : $(el);
+			$.each(layers, function() {
+				this.appendTo($par);
+			});
+
+			if (opts.theme && opts.draggable && $.fn.draggable) {
+				lyr3.draggable({
+					handle: '.ui-dialog-titlebar',
+					cancel: 'li'
+				});
+			}
+
+			// ie7 must use absolute positioning in quirks mode and to account for activex issues (when scrolling)
+			var expr = setExpr && (!$.support.boxModel || $('object,embed', full ? null : el).length > 0);
+			if (ie6 || expr) {
+				// give body 100% height
+				if (full && opts.allowBodyStretch && $.support.boxModel)
+					$('html,body').css('height','100%');
+
+				// fix ie6 issue when blocked element has a border width
+				if ((ie6 || !$.support.boxModel) && !full) {
+					var t = sz(el,'borderTopWidth'), l = sz(el,'borderLeftWidth');
+					var fixT = t ? '(0 - '+t+')' : 0;
+					var fixL = l ? '(0 - '+l+')' : 0;
+				}
+
+				// simulate fixed position
+				$.each(layers, function(i,o) {
+					var s = o[0].style;
+					s.position = 'absolute';
+					if (i < 2) {
+						if (full)
+							s.setExpression('height','Math.max(document.body.scrollHeight, document.body.offsetHeight) - (jQuery.support.boxModel?0:'+opts.quirksmodeOffsetHack+') + "px"');
+						else
+							s.setExpression('height','this.parentNode.offsetHeight + "px"');
+						if (full)
+							s.setExpression('width','jQuery.support.boxModel && document.documentElement.clientWidth || document.body.clientWidth + "px"');
+						else
+							s.setExpression('width','this.parentNode.offsetWidth + "px"');
+						if (fixL) s.setExpression('left', fixL);
+						if (fixT) s.setExpression('top', fixT);
+					}
+					else if (opts.centerY) {
+						if (full) s.setExpression('top','(document.documentElement.clientHeight || document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (blah = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"');
+						s.marginTop = 0;
+					}
+					else if (!opts.centerY && full) {
+						var top = (opts.css && opts.css.top) ? parseInt(opts.css.top, 10) : 0;
+						var expression = '((document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + '+top+') + "px"';
+						s.setExpression('top',expression);
+					}
+				});
+			}
+
+			// show the message
+			if (msg) {
+				if (opts.theme)
+					lyr3.find('.ui-widget-content').append(msg);
+				else
+					lyr3.append(msg);
+				if (msg.jquery || msg.nodeType)
+					$(msg).show();
+			}
+
+			if ((msie || opts.forceIframe) && opts.showOverlay)
+				lyr1.show(); // opacity is zero
+			if (opts.fadeIn) {
+				var cb = opts.onBlock ? opts.onBlock : noOp;
+				var cb1 = (opts.showOverlay && !msg) ? cb : noOp;
+				var cb2 = msg ? cb : noOp;
+				if (opts.showOverlay)
+					lyr2._fadeIn(opts.fadeIn, cb1);
+				if (msg)
+					lyr3._fadeIn(opts.fadeIn, cb2);
+			}
+			else {
+				if (opts.showOverlay)
+					lyr2.show();
+				if (msg)
+					lyr3.show();
+				if (opts.onBlock)
+					opts.onBlock.bind(lyr3)();
+			}
+
+			// bind key and mouse events
+			bind(1, el, opts);
+
+			if (full) {
+				pageBlock = lyr3[0];
+				pageBlockEls = $(opts.focusableElements,pageBlock);
+				if (opts.focusInput)
+					setTimeout(focus, 20);
+			}
+			else
+				center(lyr3[0], opts.centerX, opts.centerY);
+
+			if (opts.timeout) {
+				// auto-unblock
+				var to = setTimeout(function() {
+					if (full)
+						$.unblockUI(opts);
+					else
+						$(el).unblock(opts);
+				}, opts.timeout);
+				$(el).data('blockUI.timeout', to);
+			}
+		}
+
+		// remove the block
+		function remove(el, opts) {
+			var count;
+			var full = (el == window);
+			var $el = $(el);
+			var data = $el.data('blockUI.history');
+			var to = $el.data('blockUI.timeout');
+			if (to) {
+				clearTimeout(to);
+				$el.removeData('blockUI.timeout');
+			}
+			opts = $.extend({}, $.blockUI.defaults, opts || {});
+			bind(0, el, opts); // unbind events
+
+			if (opts.onUnblock === null) {
+				opts.onUnblock = $el.data('blockUI.onUnblock');
+				$el.removeData('blockUI.onUnblock');
+			}
+
+			var els;
+			if (full) // crazy selector to handle odd field errors in ie6/7
+				els = $('body').children().filter('.blockUI').add('body > .blockUI');
+			else
+				els = $el.find('>.blockUI');
+
+			// fix cursor issue
+			if ( opts.cursorReset ) {
+				if ( els.length > 1 )
+					els[1].style.cursor = opts.cursorReset;
+				if ( els.length > 2 )
+					els[2].style.cursor = opts.cursorReset;
+			}
+
+			if (full)
+				pageBlock = pageBlockEls = null;
+
+			if (opts.fadeOut) {
+				count = els.length;
+				els.stop().fadeOut(opts.fadeOut, function() {
+					if ( --count === 0)
+						reset(els,data,opts,el);
+				});
+			}
+			else
+				reset(els, data, opts, el);
+		}
+
+		// move blocking element back into the DOM where it started
+		function reset(els,data,opts,el) {
+			var $el = $(el);
+			if ( $el.data('blockUI.isBlocked') )
+				return;
+
+			els.each(function(i,o) {
+				// remove via DOM calls so we don't lose event handlers
+				if (this.parentNode)
+					this.parentNode.removeChild(this);
+			});
+
+			if (data && data.el) {
+				data.el.style.display = data.display;
+				data.el.style.position = data.position;
+				data.el.style.cursor = 'default'; // #59
+				if (data.parent)
+					data.parent.appendChild(data.el);
+				$el.removeData('blockUI.history');
+			}
+
+			if ($el.data('blockUI.static')) {
+				$el.css('position', 'static'); // #22
+			}
+
+			if (typeof opts.onUnblock == 'function')
+				opts.onUnblock(el,opts);
+
+			// fix issue in Safari 6 where block artifacts remain until reflow
+			var body = $(document.body), w = body.width(), cssW = body[0].style.width;
+			body.width(w-1).width(w);
+			body[0].style.width = cssW;
+		}
+
+		// bind/unbind the handler
+		function bind(b, el, opts) {
+			var full = el == window, $el = $(el);
+
+			// don't bother unbinding if there is nothing to unbind
+			if (!b && (full && !pageBlock || !full && !$el.data('blockUI.isBlocked')))
+				return;
+
+			$el.data('blockUI.isBlocked', b);
+
+			// don't bind events when overlay is not in use or if bindEvents is false
+			if (!full || !opts.bindEvents || (b && !opts.showOverlay))
+				return;
+
+			// bind anchors and inputs for mouse and key events
+			var events = 'mousedown mouseup keydown keypress keyup touchstart touchend touchmove';
+			if (b)
+				$(document).bind(events, opts, handler);
+			else
+				$(document).unbind(events, handler);
+
+		// former impl...
+		//		var $e = $('a,:input');
+		//		b ? $e.bind(events, opts, handler) : $e.unbind(events, handler);
+		}
+
+		// event handler to suppress keyboard/mouse events when blocking
+		function handler(e) {
+			// allow tab navigation (conditionally)
+			if (e.type === 'keydown' && e.keyCode && e.keyCode == 9) {
+				if (pageBlock && e.data.constrainTabKey) {
+					var els = pageBlockEls;
+					var fwd = !e.shiftKey && e.target === els[els.length-1];
+					var back = e.shiftKey && e.target === els[0];
+					if (fwd || back) {
+						setTimeout(function(){focus(back);},10);
+						return false;
+					}
+				}
+			}
+			var opts = e.data;
+			var target = $(e.target);
+			if (target.hasClass('blockOverlay') && opts.onOverlayClick)
+				opts.onOverlayClick(e);
+
+			// allow events within the message content
+			if (target.parents('div.' + opts.blockMsgClass).length > 0)
+				return true;
+
+			// allow events for content that is not being blocked
+			return target.parents().children().filter('div.blockUI').length === 0;
+		}
+
+		function focus(back) {
+			if (!pageBlockEls)
+				return;
+			var e = pageBlockEls[back===true ? pageBlockEls.length-1 : 0];
+			if (e)
+				e.focus();
+		}
+
+		function center(el, x, y) {
+			var p = el.parentNode, s = el.style;
+			var l = ((p.offsetWidth - el.offsetWidth)/2) - sz(p,'borderLeftWidth');
+			var t = ((p.offsetHeight - el.offsetHeight)/2) - sz(p,'borderTopWidth');
+			if (x) s.left = l > 0 ? (l+'px') : '0';
+			if (y) s.top  = t > 0 ? (t+'px') : '0';
+		}
+
+		function sz(el, p) {
+			return parseInt($.css(el,p),10)||0;
+		}
+
+	}
+
+
+	/*global define:true */
+	if (typeof define === 'function' && define.amd && define.amd.jQuery) {
+		define(['jquery'], setup);
+	} else {
+		setup(jQuery);
+	}
+
+})();
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-fileinput/fileinput.css b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-fileinput/fileinput.css
new file mode 100644
index 0000000..6334b65
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-fileinput/fileinput.css
@@ -0,0 +1,688 @@
+/*!
+ * bootstrap-fileinput v5.5.2
+ * http://plugins.krajee.com/file-input
+ *
+ * Krajee default styling for bootstrap-fileinput.
+ *
+ * Author: Kartik Visweswaran
+ * Copyright: 2014 - 2022, Kartik Visweswaran, Krajee.com
+ *
+ * Licensed under the BSD-3-Clause
+ * https://github.com/kartik-v/bootstrap-fileinput/blob/master/LICENSE.md
+ */
+
+.file-loading input[type=file],
+input[type=file].file-loading {
+    width: 0;
+    height: 0;
+}
+
+.file-no-browse {
+    position: absolute;
+    left: 50%;
+    bottom: 20%;
+    width: 1px;
+    height: 1px;
+    font-size: 0;
+    opacity: 0;
+    border: none;
+    background: none;
+    outline: none;
+    box-shadow: none;
+}
+
+.kv-hidden,
+.file-caption-icon,
+.file-zoom-dialog .modal-header:before,
+.file-zoom-dialog .modal-header:after,
+.file-input-new .file-preview,
+.file-input-new .close,
+.file-input-new .glyphicon-file,
+.file-input-new .fileinput-remove-button,
+.file-input-new .fileinput-upload-button,
+.file-input-new .no-browse .input-group-btn,
+.file-input-ajax-new .fileinput-remove-button,
+.file-input-ajax-new .fileinput-upload-button,
+.file-input-ajax-new .no-browse .input-group-btn,
+.hide-content .kv-file-content,
+.is-locked .fileinput-upload-button,
+.is-locked .fileinput-remove-button {
+    display: none;
+}
+
+.file-caption .input-group {
+    align-items: center;
+}
+
+.btn-file input[type=file],
+.file-caption-icon,
+.file-preview .fileinput-remove,
+.krajee-default .file-thumb-progress,
+.file-zoom-dialog .btn-navigate,
+.file-zoom-dialog .floating-buttons {
+    position: absolute;
+}
+
+.file-caption-icon .kv-caption-icon {
+    line-height: inherit;
+}
+
+.file-input,
+.file-loading:before,
+.btn-file,
+.file-caption,
+.file-preview,
+.krajee-default.file-preview-frame,
+.krajee-default .file-thumbnail-footer,
+.file-zoom-dialog .modal-dialog {
+    position: relative;
+}
+
+.file-error-message pre,
+.file-error-message ul,
+.krajee-default .file-actions,
+.krajee-default .file-other-error {
+    text-align: left;
+}
+
+.file-error-message pre,
+.file-error-message ul {
+    margin: 0;
+}
+
+.krajee-default .file-drag-handle,
+.krajee-default .file-upload-indicator {
+    float: left;
+    margin-top: 10px;
+    width: 16px;
+    height: 16px;
+}
+
+.file-thumb-progress .progress,
+.file-thumb-progress .progress-bar {
+    font-family: Verdana, Helvetica, sans-serif;
+    font-size: 0.7rem;
+}
+
+.krajee-default .file-thumb-progress .progress,
+.kv-upload-progress .progress {
+    background-color: #ccc;
+}
+
+.krajee-default .file-caption-info,
+.krajee-default .file-size-info {
+    display: block;
+    white-space: nowrap;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    width: 160px;
+    height: 15px;
+    margin: auto;
+}
+
+.file-zoom-content > .file-object.type-video,
+.file-zoom-content > .file-object.type-flash,
+.file-zoom-content > .file-object.type-image {
+    max-width: 100%;
+    max-height: 100%;
+    width: auto;
+}
+
+.file-zoom-content > .file-object.type-video,
+.file-zoom-content > .file-object.type-flash {
+    height: 100%;
+}
+
+.file-zoom-content > .file-object.type-pdf,
+.file-zoom-content > .file-object.type-html,
+.file-zoom-content > .file-object.type-text,
+.file-zoom-content > .file-object.type-default {
+    width: 100%;
+}
+
+.file-loading:before {
+    content: " Loading...";
+    display: inline-block;
+    padding-left: 20px;
+    line-height: 16px;
+    font-size: 13px;
+    font-variant: small-caps;
+    color: #999;
+    background: transparent url(loading.gif) top left no-repeat;
+}
+
+.file-object {
+    margin: 0 0 -5px 0;
+    padding: 0;
+}
+
+.btn-file {
+    overflow: hidden;
+}
+
+.btn-file input[type=file] {
+    top: 0;
+    left: 0;
+    min-width: 100%;
+    min-height: 100%;
+    text-align: right;
+    opacity: 0;
+    background: none repeat scroll 0 0 transparent;
+    cursor: inherit;
+    display: block;
+}
+
+.btn-file ::-ms-browse {
+    font-size: 10000px;
+    width: 100%;
+    height: 100%;
+}
+
+.file-caption.icon-visible .file-caption-icon {
+    display: inline-block;
+}
+
+.file-caption.icon-visible .file-caption-name {
+    padding-left: 25px;
+}
+
+.file-caption.icon-visible > .input-group-lg .file-caption-name {
+    padding-left: 30px;
+}
+
+.file-caption.icon-visible > .input-group-sm .file-caption-name {
+    padding-left: 22px;
+}
+
+.file-caption-name:not(.file-caption-disabled) {
+    background-color: transparent;
+}
+
+.file-caption-name.file-processing {
+    font-style: italic;
+    border-color: #bbb;
+    opacity: 0.5;
+}
+
+.file-caption-icon {
+    padding: 7px 5px;
+    left: 4px;
+}
+
+.input-group-lg .file-caption-icon {
+    font-size: 1.25rem;
+}
+
+.input-group-sm .file-caption-icon {
+    font-size: 0.875rem;
+    padding: 0.25rem;
+}
+
+.file-error-message {
+    color: #a94442;
+    background-color: #f2dede;
+    margin: 5px;
+    border: 1px solid #ebccd1;
+    border-radius: 4px;
+    padding: 15px;
+}
+
+.file-error-message pre {
+    margin: 5px 0;
+}
+
+.file-caption-disabled {
+    background-color: #eee;
+    cursor: not-allowed;
+    opacity: 1;
+}
+
+.file-preview {
+    border-radius: 5px;
+    border: 1px solid #ddd;
+    padding: 8px;
+    width: 100%;
+    margin-bottom: 5px;
+}
+
+.file-preview .btn-xs {
+    padding: 1px 5px;
+    font-size: 12px;
+    line-height: 1.5;
+    border-radius: 3px;
+}
+
+.file-preview .fileinput-remove {
+    top: 1px;
+    right: 1px;
+    line-height: 10px;
+}
+
+.file-preview .clickable {
+    cursor: pointer;
+}
+
+.file-preview-image {
+    font: 40px Impact, Charcoal, sans-serif;
+    color: #008000;
+    width: auto;
+    height: auto;
+    max-width: 100%;
+    max-height: 100%;
+}
+
+.krajee-default.file-preview-frame {
+    margin: 8px;
+    border: 1px solid rgba(0, 0, 0, 0.2);
+    box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.2);
+    padding: 6px;
+    float: left;
+    text-align: center;
+
+}
+
+.krajee-default.file-preview-frame .kv-file-content {
+    width: 213px;
+    height: 160px;
+}
+
+.krajee-default.file-preview-frame .kv-file-content.kv-pdf-rendered {
+    width: 400px;
+}
+
+.krajee-default.file-preview-frame[data-template="audio"] .kv-file-content {
+    width: 240px;
+    height: 55px;
+}
+
+.krajee-default.file-preview-frame .file-thumbnail-footer {
+    height: 70px;
+}
+
+.krajee-default.file-preview-frame:not(.file-preview-error):hover {
+    border: 1px solid rgba(0, 0, 0, 0.3);
+    box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.4);
+}
+
+.krajee-default .file-preview-text {
+    color: #428bca;
+    border: 1px solid #ddd;
+    outline: none;
+    resize: none;
+}
+
+.krajee-default .file-preview-html {
+    border: 1px solid #ddd;
+}
+
+.krajee-default .file-other-icon {
+    font-size: 6em;
+    line-height: 1;
+}
+
+.krajee-default .file-footer-buttons {
+    float: right;
+}
+
+.krajee-default .file-footer-caption {
+    display: block;
+    text-align: center;
+    padding-top: 4px;
+    font-size: 11px;
+    color: #999;
+    margin-bottom: 30px;
+}
+
+.file-upload-stats {
+    font-size: 10px;
+    text-align: center;
+    width: 100%;
+}
+
+.kv-upload-progress .file-upload-stats {
+    font-size: 12px;
+    margin: -10px 0 5px;
+}
+
+.krajee-default .file-preview-error {
+    opacity: 0.65;
+    box-shadow: none;
+}
+
+.krajee-default .file-thumb-progress {
+    top: 37px;
+    left: 0;
+    right: 0;
+}
+
+.krajee-default.kvsortable-ghost {
+    background: #e1edf7;
+    border: 2px solid #a1abff;
+}
+
+.krajee-default .file-preview-other:hover {
+    opacity: 0.8;
+}
+
+.krajee-default .file-preview-frame:not(.file-preview-error) .file-footer-caption:hover {
+    color: #000;
+}
+
+.kv-upload-progress .progress {
+    height: 20px;
+    margin: 10px 0;
+    overflow: hidden;
+}
+
+.kv-upload-progress .progress-bar {
+    height: 20px;
+    font-family: Verdana, Helvetica, sans-serif;
+}
+
+
+/*noinspection CssOverwrittenProperties*/
+
+.file-zoom-dialog .file-other-icon {
+    font-size: 22em;
+    font-size: 50vmin;
+}
+
+.file-zoom-dialog .modal-dialog {
+    width: auto;
+}
+
+.file-zoom-dialog .modal-header {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+}
+
+.file-zoom-dialog .btn-navigate {
+    margin: 0 0.1rem;
+    padding: 0;
+    font-size: 1.2rem;
+    width: 2.4rem;
+    height: 2.4rem;
+    top: 50%;
+    border-radius: 50%;
+    text-align: center;
+}
+
+.btn-navigate * {
+    width: auto;
+}
+
+.file-zoom-dialog .floating-buttons {
+    top: 5px;
+    right: 10px;
+}
+
+.file-zoom-dialog .btn-kv-prev {
+    left: 0;
+}
+
+.file-zoom-dialog .btn-kv-next {
+    right: 0;
+}
+
+.file-zoom-dialog .kv-zoom-header {
+    padding: 0.5rem;
+}
+
+.file-zoom-dialog .kv-zoom-body {
+    padding: 0.25rem;
+}
+
+.file-zoom-dialog .kv-zoom-description {
+    position: absolute;
+    opacity: 0.8;
+    font-size: 0.8rem;
+    background-color: #1a1a1a;
+    padding: 1rem;
+    text-align: center;
+    border-radius: 0.5rem;
+    color: #fff;
+    left: 15%;
+    right: 15%;
+    bottom: 15%;
+}
+
+.file-zoom-dialog .kv-desc-hide {
+    float: right;
+    color: #fff;
+    padding: 0 0.1rem;
+    background: none;
+    border: none;
+}
+
+.file-zoom-dialog .kv-desc-hide:hover {
+    opacity: 0.7;
+}
+
+.file-zoom-dialog .kv-desc-hide:focus {
+    opacity: 0.9;
+}
+
+.file-input-new .no-browse .form-control {
+    border-top-right-radius: 4px;
+    border-bottom-right-radius: 4px;
+}
+
+.file-input-ajax-new .no-browse .form-control {
+    border-top-right-radius: 4px;
+    border-bottom-right-radius: 4px;
+}
+
+.file-caption {
+    width: 100%;
+    position: relative;
+}
+
+.file-thumb-loading {
+    background: transparent url(loading.gif) no-repeat scroll center center content-box !important;
+}
+
+.file-drop-zone {
+    border: 1px dashed #aaa;
+    min-height: 260px;
+    border-radius: 4px;
+    text-align: center;
+    vertical-align: middle;
+    margin: 12px 15px 12px 12px;
+    padding: 5px;
+}
+
+.file-drop-zone.clickable:hover {
+    border: 2px dashed #999;
+}
+
+.file-drop-zone.clickable:focus {
+    border: 2px solid #5acde2;
+}
+
+.file-drop-zone .file-preview-thumbnails {
+    cursor: default;
+}
+
+.file-drop-zone-title {
+    color: #aaa;
+    font-size: 1.6em;
+    text-align: center;
+    padding: 85px 10px;
+    cursor: default;
+}
+
+.file-highlighted {
+    border: 2px dashed #999 !important;
+    background-color: #eee;
+}
+
+.file-uploading {
+    background: url(loading-sm.gif) no-repeat center bottom 10px;
+    opacity: 0.65;
+}
+
+.file-zoom-fullscreen .modal-dialog {
+    min-width: 100%;
+    margin: 0;
+}
+
+.file-zoom-fullscreen .modal-content {
+    border-radius: 0;
+    box-shadow: none;
+    min-height: 100vh;
+}
+
+.file-zoom-fullscreen .kv-zoom-body {
+    overflow-y: auto;
+}
+
+.floating-buttons {
+    z-index: 3000;
+}
+
+.floating-buttons .btn-kv {
+    margin-left: 3px;
+    z-index: 3000;
+}
+
+.kv-zoom-actions {
+    min-width: 140px;
+}
+
+.kv-zoom-actions .btn-kv {
+    margin-left: 3px;
+}
+
+.file-zoom-content {
+    text-align: center;
+    white-space: nowrap;
+    min-height: 300px;
+}
+
+.file-zoom-content:hover {
+    background: transparent;
+}
+
+.file-zoom-content .file-preview-image {
+    max-height: 100%;
+}
+
+.file-zoom-content .file-preview-video {
+    max-height: 100%;
+}
+
+.file-zoom-content > .file-object.type-image {
+    height: auto;
+    min-height: inherit;
+}
+
+.file-zoom-content > .file-object.type-audio {
+    width: auto;
+    height: 30px;
+}
+
+@media (min-width: 576px) {
+    .file-zoom-dialog .modal-dialog {
+        max-width: 500px;
+    }
+}
+
+@media (min-width: 992px) {
+    .file-zoom-dialog .modal-lg {
+        max-width: 800px;
+    }
+}
+
+@media (max-width: 767px) {
+    .file-preview-thumbnails {
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        flex-direction: column;
+    }
+
+    .file-zoom-dialog .modal-header {
+        flex-direction: column;
+    }
+}
+
+@media (max-width: 350px) {
+    .krajee-default.file-preview-frame:not([data-template="audio"]) .kv-file-content {
+        width: 160px;
+    }
+}
+
+@media (max-width: 420px) {
+    .krajee-default.file-preview-frame .kv-file-content.kv-pdf-rendered {
+        width: 100%;
+    }
+}
+
+.file-loading[dir=rtl]:before {
+    background: transparent url(loading.gif) top right no-repeat;
+    padding-left: 0;
+    padding-right: 20px;
+}
+
+.clickable .file-drop-zone-title {
+    cursor: pointer;
+}
+
+.file-sortable .file-drag-handle:hover {
+    opacity: 0.7;
+}
+
+.file-sortable .file-drag-handle {
+    cursor: grab;
+    opacity: 1;
+}
+
+.file-grabbing,
+.file-grabbing * {
+    cursor: not-allowed !important;
+}
+
+.file-grabbing .file-preview-thumbnails * {
+    cursor: grabbing !important;
+}
+
+.file-preview-frame.sortable-chosen {
+    background-color: #d9edf7;
+    border-color: #17a2b8;
+    box-shadow: none !important;
+}
+
+.file-preview .kv-zoom-cache {
+    display: none;
+}
+
+.file-preview-other-frame, .file-preview-object, .kv-file-content, .kv-zoom-body {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+}
+
+.btn-kv-rotate,
+.kv-file-rotate {
+    display: none;
+}
+
+.rotatable:not(.hide-rotate) .btn-kv-rotate,
+.rotatable:not(.hide-rotate) .kv-file-rotate {
+    display: inline-block;
+}
+
+.rotatable .file-zoom-detail,
+.rotatable .kv-file-content,
+.rotatable .kv-file-content > :first-child {
+    transform-origin: center center;
+}
+
+.rotate-animate {
+    transition: transform 0.3s ease;
+}
+
+.kv-overflow-hidden {
+    overflow: hidden;
+}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-fileinput/fileinput.js b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-fileinput/fileinput.js
new file mode 100644
index 0000000..75466c0
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-fileinput/fileinput.js
@@ -0,0 +1,6681 @@
+/*!
+ * bootstrap-fileinput v5.5.2
+ * http://plugins.krajee.com/file-input
+ *
+ * Author: Kartik Visweswaran
+ * Copyright: 2014 - 2022, Kartik Visweswaran, Krajee.com
+ *
+ * Licensed under the BSD-3-Clause
+ * https://github.com/kartik-v/bootstrap-fileinput/blob/master/LICENSE.md
+ */
+(function (factory) {
+    'use strict';
+    if (typeof define === 'function' && define.amd) {
+        define(['jquery'], factory);
+    } else if (typeof module === 'object' && typeof module.exports === 'object') {
+        factory(require('jquery'));
+    } else {
+        factory(window.jQuery);
+    }
+}(function ($) {
+    'use strict';
+
+    $.fn.fileinputLocales = {};
+    $.fn.fileinputThemes = {};
+
+    if (!$.fn.fileinputBsVersion) {
+        $.fn.fileinputBsVersion = (window.bootstrap && window.bootstrap.Alert && window.bootstrap.Alert.VERSION) ||
+            (window.Alert && window.Alert.VERSION) || '3.x.x';
+    }
+
+    String.prototype.setTokens = function (replacePairs) {
+        var str = this.toString(), key, re;
+        for (key in replacePairs) {
+            if (replacePairs.hasOwnProperty(key)) {
+                re = new RegExp('\{' + key + '\}', 'g');
+                str = str.replace(re, replacePairs[key]);
+            }
+        }
+        return str;
+    };
+
+    if (!Array.prototype.flatMap) { // polyfill flatMap
+        Array.prototype.flatMap = function (lambda) {
+            return [].concat(this.map(lambda));
+        };
+    }
+
+    var $h, FileInput;
+
+    // fileinput helper object for all global variables and internal helper methods
+    $h = {
+        FRAMES: '.kv-preview-thumb',
+        SORT_CSS: 'file-sortable',
+        INIT_FLAG: 'init-',
+        SCRIPT_SRC: document && document.currentScript && document.currentScript.src || null,
+        OBJECT_PARAMS: '<param name="controller" value="true" />\n' +
+            '<param name="allowFullScreen" value="true" />\n' +
+            '<param name="allowScriptAccess" value="always" />\n' +
+            '<param name="autoPlay" value="false" />\n' +
+            '<param name="autoStart" value="false" />\n' +
+            '<param name="quality" value="high" />\n',
+        DEFAULT_PREVIEW: '<div class="file-preview-other">\n' +
+            '<span class="{previewFileIconClass}">{previewFileIcon}</span>\n' +
+            '</div>',
+        MODAL_ID: 'kvFileinputModal',
+        MODAL_EVENTS: ['show', 'shown', 'hide', 'hidden', 'loaded'],
+        logMessages: {
+            ajaxError: '{status}: {error}. Error Details: {text}.',
+            badDroppedFiles: 'Error scanning dropped files!',
+            badExifParser: 'Error loading the piexif.js library. {details}',
+            badInputType: 'The input "type" must be set to "file" for initializing the "bootstrap-fileinput" plugin.',
+            exifWarning: 'To avoid this warning, either set "autoOrientImage" to "false" OR ensure you have loaded ' +
+                'the "piexif.js" library correctly on your page before the "fileinput.js" script.',
+            invalidChunkSize: 'Invalid upload chunk size: "{chunkSize}". Resumable uploads are disabled.',
+            invalidThumb: 'Invalid thumb frame with id: "{id}".',
+            noResumableSupport: 'The browser does not support resumable or chunk uploads.',
+            noUploadUrl: 'The "uploadUrl" is not set. Ajax uploads and resumable uploads have been disabled.',
+            retryStatus: 'Retrying upload for chunk # {chunk} for {filename}... retry # {retry}.',
+            chunkQueueError: 'Could not push task to ajax pool for chunk index # {index}.',
+            resumableMaxRetriesReached: 'Maximum resumable ajax retries ({n}) reached.',
+            resumableRetryError: 'Could not retry the resumable request (try # {n})... aborting.',
+            resumableAborting: 'Aborting / cancelling the resumable request.',
+            resumableRequestError: 'Error processing resumable request. {msg}'
+
+        },
+        objUrl: window.URL || window.webkitURL,
+        getZoomPlaceholder: function () { // used to prevent 404 errors in URL parsing
+            var src = $h.SCRIPT_SRC, srcPath, zoomVar = '?kvTemp__2873389129__=';
+            if (!src) {
+                return zoomVar;
+            }
+            srcPath = src.substring(0, src.lastIndexOf("/"));
+            return srcPath.substring(0, srcPath.lastIndexOf("/") + 1) + 'img/loading.gif' + zoomVar;
+        },
+        isBs: function (ver) {
+            var chk = $.trim(($.fn.fileinputBsVersion || '') + '');
+            ver = parseInt(ver, 10);
+            if (!chk) {
+                return ver === 4;
+            }
+            return ver === parseInt(chk.charAt(0), 10);
+
+        },
+        defaultButtonCss: function (fill) {
+            return 'btn-default btn-' + (fill ? '' : 'outline-') + 'secondary';
+        },
+        now: function () {
+            return new Date().getTime();
+        },
+        round: function (num) {
+            num = parseFloat(num);
+            return isNaN(num) ? 0 : Math.floor(Math.round(num));
+        },
+        getArray: function (obj) {
+            var i, arr = [], len = obj && obj.length || 0;
+            for (i = 0; i < len; i++) {
+                arr.push(obj[i]);
+            }
+            return arr;
+        },
+        getFileRelativePath: function (file) {
+            /** @namespace file.relativePath */
+            /** @namespace file.webkitRelativePath */
+            return String(file.newPath || file.relativePath || file.webkitRelativePath || $h.getFileName(file) || null);
+
+        },
+        getFileId: function (file, generateFileId) {
+            var relativePath = $h.getFileRelativePath(file);
+            if (typeof generateFileId === 'function') {
+                return generateFileId(file);
+            }
+            if (!file) {
+                return null;
+            }
+            if (!relativePath) {
+                return null;
+            }
+            return (file.size + '_' + encodeURIComponent(relativePath).replace(/%/g, '_'));
+        },
+        getFrameSelector: function (id, selector) {
+            selector = selector || '';
+            return '[id="' + id + '"]' + selector;
+        },
+        getZoomSelector: function (id, selector) {
+            return $h.getFrameSelector('zoom-' + id, selector);
+        },
+        getFrameElement: function ($element, id, selector) {
+            return $element.find($h.getFrameSelector(id, selector));
+        },
+        getZoomElement: function ($element, id, selector) {
+            return $element.find($h.getZoomSelector(id, selector));
+        },
+        getElapsed: function (seconds) {
+            var delta = seconds, out = '', result = {}, structure = {
+                year: 31536000,
+                month: 2592000,
+                week: 604800, // uncomment row to ignore
+                day: 86400,   // feel free to add your own row
+                hour: 3600,
+                minute: 60,
+                second: 1
+            };
+            $h.getObjectKeys(structure).forEach(function (key) {
+                result[key] = Math.floor(delta / structure[key]);
+                delta -= result[key] * structure[key];
+            });
+            $.each(result, function (key, value) {
+                if (value > 0) {
+                    out += (out ? ' ' : '') + value + key.substring(0, 1);
+                }
+            });
+            return out;
+        },
+        debounce: function (func, delay) {
+            var inDebounce;
+            return function () {
+                var args = arguments, context = this;
+                clearTimeout(inDebounce);
+                inDebounce = setTimeout(function () {
+                    func.apply(context, args);
+                }, delay);
+            };
+        },
+        stopEvent: function (e) {
+            e.stopPropagation();
+            e.preventDefault();
+        },
+        getFileName: function (file) {
+            /** @namespace file.fileName */
+            return file ? (file.fileName || file.name || '') : ''; // some confusion in different versions of Firefox
+        },
+        createObjectURL: function (data) {
+            if ($h.objUrl && $h.objUrl.createObjectURL && data) {
+                return $h.objUrl.createObjectURL(data);
+            }
+            return '';
+        },
+        revokeObjectURL: function (data) {
+            if ($h.objUrl && $h.objUrl.revokeObjectURL && data) {
+                $h.objUrl.revokeObjectURL(data);
+            }
+        },
+        compare: function (input, str, exact) {
+            return input !== undefined && (exact ? input === str : input.match(str));
+        },
+        isIE: function (ver) {
+            var div, status;
+            // check for IE versions < 11
+            if (navigator.appName !== 'Microsoft Internet Explorer') {
+                return false;
+            }
+            if (ver === 10) {
+                return new RegExp('msie\\s' + ver, 'i').test(navigator.userAgent);
+            }
+            div = document.createElement('div');
+            div.innerHTML = '<!--[if IE ' + ver + ']> <i></i> <![endif]-->';
+            status = div.getElementsByTagName('i').length;
+            document.body.appendChild(div);
+            div.parentNode.removeChild(div);
+            return status;
+        },
+        canOrientImage: function ($el) {
+            var $img = $(document.createElement('img')).css({width: '1px', height: '1px'}).insertAfter($el),
+                flag = $img.css('image-orientation');
+            $img.remove();
+            return !!flag;
+        },
+        canAssignFilesToInput: function () {
+            var input = document.createElement('input');
+            try {
+                input.type = 'file';
+                input.files = null;
+                return true;
+            } catch (err) {
+                return false;
+            }
+        },
+        getDragDropFolders: function (items) {
+            var i, item, len = items ? items.length : 0, folders = 0;
+            if (len > 0 && items[0].webkitGetAsEntry()) {
+                for (i = 0; i < len; i++) {
+                    item = items[i].webkitGetAsEntry();
+                    if (item && item.isDirectory) {
+                        folders++;
+                    }
+                }
+            }
+            return folders;
+        },
+        initModal: function ($modal) {
+            var $body = $('body');
+            if ($body.length) {
+                $modal.appendTo($body);
+            }
+        },
+        isFunction: function (v) {
+            return typeof v === 'function';
+        },
+        isEmpty: function (value, trim) {
+            if (value === undefined || value === null || value === '') {
+                return true;
+            }
+            if ($h.isString(value) && trim) {
+                return $.trim(value) === '';
+            }
+            if ($h.isArray(value)) {
+                return value.length === 0;
+            }
+            if ($.isPlainObject(value) && $.isEmptyObject(value)) {
+                return true;
+            }
+            return false;
+        },
+        isArray: function (a) {
+            return Array.isArray(a) || Object.prototype.toString.call(a) === '[object Array]';
+        },
+        isString: function (a) {
+            return Object.prototype.toString.call(a) === '[object String]';
+        },
+        ifSet: function (needle, haystack, def) {
+            def = def || '';
+            return (haystack && typeof haystack === 'object' && needle in haystack) ? haystack[needle] : def;
+        },
+        cleanArray: function (arr) {
+            if (!(arr instanceof Array)) {
+                arr = [];
+            }
+            return arr.filter(function (e) {
+                return (e !== undefined && e !== null);
+            });
+        },
+        spliceArray: function (arr, index, reverseOrder) {
+            var i, j = 0, out = [], newArr;
+            if (!(arr instanceof Array)) {
+                return [];
+            }
+            newArr = $.extend(true, [], arr);
+            if (reverseOrder) {
+                newArr.reverse();
+            }
+            for (i = 0; i < newArr.length; i++) {
+                if (i !== index) {
+                    out[j] = newArr[i];
+                    j++;
+                }
+            }
+            if (reverseOrder) {
+                out.reverse();
+            }
+            return out;
+        },
+        getNum: function (num, def) {
+            def = def || 0;
+            if (typeof num === 'number') {
+                return num;
+            }
+            if (typeof num === 'string') {
+                num = parseFloat(num);
+            }
+            return isNaN(num) ? def : num;
+        },
+        hasFileAPISupport: function () {
+            return !!(window.File && window.FileReader);
+        },
+        hasDragDropSupport: function () {
+            var div = document.createElement('div');
+            /** @namespace div.draggable */
+            /** @namespace div.ondragstart */
+            /** @namespace div.ondrop */
+            return !$h.isIE(9) &&
+                (div.draggable !== undefined || (div.ondragstart !== undefined && div.ondrop !== undefined));
+        },
+        hasFileUploadSupport: function () {
+            return $h.hasFileAPISupport() && window.FormData;
+        },
+        hasBlobSupport: function () {
+            try {
+                return !!window.Blob && Boolean(new Blob());
+            } catch (e) {
+                return false;
+            }
+        },
+        hasArrayBufferViewSupport: function () {
+            try {
+                return new Blob([new Uint8Array(100)]).size === 100;
+            } catch (e) {
+                return false;
+            }
+        },
+        hasResumableUploadSupport: function () {
+            /** @namespace Blob.prototype.webkitSlice */
+            /** @namespace Blob.prototype.mozSlice */
+            return $h.hasFileUploadSupport() && $h.hasBlobSupport() && $h.hasArrayBufferViewSupport() &&
+                (!!Blob.prototype.webkitSlice || !!Blob.prototype.mozSlice || !!Blob.prototype.slice || false);
+        },
+        dataURI2Blob: function (dataURI) {
+            var BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder ||
+                    window.MSBlobBuilder, canBlob = $h.hasBlobSupport(), byteStr, arrayBuffer, intArray, i, mimeStr, bb,
+                canProceed = (canBlob || BlobBuilder) && window.atob && window.ArrayBuffer && window.Uint8Array;
+            if (!canProceed) {
+                return null;
+            }
+            if (dataURI.split(',')[0].indexOf('base64') >= 0) {
+                byteStr = atob(dataURI.split(',')[1]);
+            } else {
+                byteStr = decodeURIComponent(dataURI.split(',')[1]);
+            }
+            arrayBuffer = new ArrayBuffer(byteStr.length);
+            intArray = new Uint8Array(arrayBuffer);
+            for (i = 0; i < byteStr.length; i += 1) {
+                intArray[i] = byteStr.charCodeAt(i);
+            }
+            mimeStr = dataURI.split(',')[0].split(':')[1].split(';')[0];
+            if (canBlob) {
+                return new Blob([$h.hasArrayBufferViewSupport() ? intArray : arrayBuffer], {type: mimeStr});
+            }
+            bb = new BlobBuilder();
+            bb.append(arrayBuffer);
+            return bb.getBlob(mimeStr);
+        },
+        arrayBuffer2String: function (buffer) {
+            if (window.TextDecoder) {
+                return new TextDecoder('utf-8').decode(buffer);
+            }
+            var array = Array.prototype.slice.apply(new Uint8Array(buffer)), out = '', i = 0, len, c, char2, char3;
+            len = array.length;
+            while (i < len) {
+                c = array[i++];
+                switch (c >> 4) { // jshint ignore:line
+                    case 0:
+                    case 1:
+                    case 2:
+                    case 3:
+                    case 4:
+                    case 5:
+                    case 6:
+                    case 7:
+                        // 0xxxxxxx
+                        out += String.fromCharCode(c);
+                        break;
+                    case 12:
+                    case 13:
+                        // 110x xxxx   10xx xxxx
+                        char2 = array[i++];
+                        out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F)); // jshint ignore:line
+                        break;
+                    case 14:
+                        // 1110 xxxx  10xx xxxx  10xx xxxx
+                        char2 = array[i++];
+                        char3 = array[i++];
+                        out += String.fromCharCode(((c & 0x0F) << 12) | // jshint ignore:line
+                            ((char2 & 0x3F) << 6) |  // jshint ignore:line
+                            ((char3 & 0x3F) << 0)); // jshint ignore:line
+                        break;
+                }
+            }
+            return out;
+        },
+        isHtml: function (str) {
+            var a = document.createElement('div');
+            a.innerHTML = str;
+            for (var c = a.childNodes, i = c.length; i--;) {
+                if (c[i].nodeType === 1) {
+                    return true;
+                }
+            }
+            return false;
+        },
+        isPdf: function (str) {
+            if ($h.isEmpty(str)) {
+                return false;
+            }
+            str = str.toString().trim().replace(/\n/g, ' ');
+            if (str.length === 0) {
+                return false;
+            }
+        },
+        isSvg: function (str) {
+            if ($h.isEmpty(str)) {
+                return false;
+            }
+            str = str.toString().trim().replace(/\n/g, ' ');
+            if (str.length === 0) {
+                return false;
+            }
+            return str.match(/^\s*<\?xml/i) && (str.match(/<!DOCTYPE svg/i) || str.match(/<svg/i));
+        },
+        getMimeType: function (sign, contents, type) {
+            var signature = sign || "";
+            switch (signature) {
+                case 'ffd8ffe0':
+                case 'ffd8ffe1':
+                case 'ffd8ffe2':
+                    return 'image/jpeg';
+                case '89504e47':
+                    return 'image/png';
+                case '47494638':
+                    return 'image/gif';
+                case '49492a00':
+                    return 'image/tiff';
+                case '52494646':
+                    return 'image/webp';
+                case '41433130':
+                    return 'image/vnd.dwg';
+                case '66747970':
+                    return 'video/3gp';
+                case '4f676753':
+                    return 'video/ogg';
+                case '1a45dfa3':
+                    return 'video/mkv';
+                case '000001ba':
+                case '000001b3':
+                    return 'video/mpeg';
+                case '3026b275':
+                    return 'video/wmv';
+                case '25504446':
+                    return 'application/pdf';
+                case '25215053':
+                    return 'application/ps';
+                case '504b0304':
+                case '504b0506':
+                case '504b0508':
+                    return 'application/zip';
+                case '377abcaf':
+                    return 'application/7z';
+                case '75737461':
+                    return 'application/tar';
+                case '7801730d':
+                    return 'application/dmg';
+                default:
+                    switch (signature.substring(0, 6)) {
+                        case '435753':
+                            return 'application/x-shockwave-flash';
+                        case '494433':
+                            return 'audio/mp3';
+                        case '425a68':
+                            return 'application/bzip';
+                        default:
+                            switch (signature.substring(0, 4)) {
+                                case '424d':
+                                    return 'image/bmp';
+                                case 'fffb':
+                                    return 'audio/mp3';
+                                case '4d5a':
+                                    return 'application/exe';
+                                case '1f9d':
+                                case '1fa0':
+                                    return 'application/zip';
+                                case '1f8b':
+                                    return 'application/gzip';
+                                default:
+                                    return contents && !contents.match(
+                                        /[^\u0000-\u007f]/) ? 'application/text-plain' : type;
+                            }
+                    }
+            }
+        },
+        addCss: function ($el, css) {
+            $el.removeClass(css).addClass(css);
+        },
+        getElement: function (options, param, value) {
+            return ($h.isEmpty(options) || $h.isEmpty(options[param])) ? value : $(options[param]);
+        },
+        createElement: function (str, tag) {
+            tag = tag || 'div';
+            return $($.parseHTML('<' + tag + '>' + str + '</' + tag + '>'));
+        },
+        uniqId: function () {
+            return (new Date().getTime() + Math.floor(Math.random() * Math.pow(10, 15))).toString(36);
+        },
+        cspBuffer: {
+            CSP_ATTRIB: 'data-csp-01928735', // a randomly named temporary attribute to store the CSP elem id
+            domElementsStyles: {},
+            stash: function (htmlString) {
+                var self = this, outerDom = $.parseHTML('<div>' + htmlString + '</div>'), $el = $(outerDom);
+                $el.find('[style]').each(function (key, elem) {
+                    var $elem = $(elem), styleDeclaration = $elem[0].style, id = $h.uniqId(), styles = {};
+                    if (styleDeclaration && styleDeclaration.length) {
+                        $(styleDeclaration).each(function () {
+                            styles[this] = styleDeclaration[this];
+                        });
+                        self.domElementsStyles[id] = styles;
+                        $elem.removeAttr('style').attr(self.CSP_ATTRIB, id);
+                    }
+                });
+                $el.filter('*').removeAttr('style');                   // make sure all style attr are removed
+                var values = Object.values ? Object.values(outerDom) : Object.keys(outerDom).map(function (itm) {
+                    return outerDom[itm];
+                });
+                return values.flatMap(function (elem) {
+                    return elem.innerHTML;
+                }).join('');
+            },
+            apply: function (domElement) {
+                var self = this, $el = $(domElement);
+                $el.find('[' + self.CSP_ATTRIB + ']').each(function (key, elem) {
+                    var $elem = $(elem), id = $elem.attr(self.CSP_ATTRIB), styles = self.domElementsStyles[id];
+                    if (styles) {
+                        $elem.css(styles);
+                    }
+                    $elem.removeAttr(self.CSP_ATTRIB);
+                });
+                self.domElementsStyles = {};
+            }
+        },
+        setHtml: function ($elem, htmlString) {
+            var buf = $h.cspBuffer;
+            $elem.html(buf.stash(htmlString));
+            buf.apply($elem);
+            return $elem;
+        },
+        htmlEncode: function (str, undefVal) {
+            if (str === undefined) {
+                return undefVal || null;
+            }
+            return str.replace(/&/g, '&amp;')
+                .replace(/</g, '&lt;')
+                .replace(/>/g, '&gt;')
+                .replace(/"/g, '&quot;')
+                .replace(/'/g, '&apos;');
+        },
+        replaceTags: function (str, tags) {
+            var out = str;
+            if (!tags) {
+                return out;
+            }
+            $.each(tags, function (key, value) {
+                if (typeof value === 'function') {
+                    value = value();
+                }
+                out = out.split(key).join(value);
+            });
+            return out;
+        },
+        cleanMemory: function ($thumb) {
+            var data = $thumb.is('img') ? $thumb.attr('src') : $thumb.find('source').attr('src');
+            $h.revokeObjectURL(data);
+        },
+        findFileName: function (filePath) {
+            var sepIndex = filePath.lastIndexOf('/');
+            if (sepIndex === -1) {
+                sepIndex = filePath.lastIndexOf('\\');
+            }
+            return filePath.split(filePath.substring(sepIndex, sepIndex + 1)).pop();
+        },
+        checkFullScreen: function () {
+            return document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement ||
+                document.msFullscreenElement;
+        },
+        toggleFullScreen: function (maximize) {
+            var doc = document, de = doc.documentElement, isFullScreen = $h.checkFullScreen();
+            if (de && maximize && !isFullScreen) {
+                if (de.requestFullscreen) {
+                    de.requestFullscreen();
+                } else {
+                    if (de.msRequestFullscreen) {
+                        de.msRequestFullscreen();
+                    } else {
+                        if (de.mozRequestFullScreen) {
+                            de.mozRequestFullScreen();
+                        } else {
+                            if (de.webkitRequestFullscreen) {
+                                de.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
+                            }
+                        }
+                    }
+                }
+            } else {
+                if (isFullScreen) {
+                    if (doc.exitFullscreen) {
+                        doc.exitFullscreen();
+                    } else {
+                        if (doc.msExitFullscreen) {
+                            doc.msExitFullscreen();
+                        } else {
+                            if (doc.mozCancelFullScreen) {
+                                doc.mozCancelFullScreen();
+                            } else {
+                                if (doc.webkitExitFullscreen) {
+                                    doc.webkitExitFullscreen();
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        },
+        moveArray: function (arr, oldIndex, newIndex, reverseOrder) {
+            var newArr = $.extend(true, [], arr);
+            if (reverseOrder) {
+                newArr.reverse();
+            }
+            if (newIndex >= newArr.length) {
+                var k = newIndex - newArr.length;
+                while ((k--) + 1) {
+                    newArr.push(undefined);
+                }
+            }
+            newArr.splice(newIndex, 0, newArr.splice(oldIndex, 1)[0]);
+            if (reverseOrder) {
+                newArr.reverse();
+            }
+            return newArr;
+        },
+        closeButton: function (css) {
+            css = ($h.isBs(5) ? 'btn-close' : 'close') + (css ? ' ' + css : '');
+            return '<button type="button" class="' + css + '" aria-label="Close">\n' +
+                ($h.isBs(5) ? '' : '  <span aria-hidden="true">&times;</span>\n') +
+                '</button>';
+        },
+        getRotation: function (value) {
+            switch (value) {
+                case 2:
+                    return 'rotateY(180deg)';
+                case 3:
+                    return 'rotate(180deg)';
+                case 4:
+                    return 'rotate(180deg) rotateY(180deg)';
+                case 5:
+                    return 'rotate(270deg) rotateY(180deg)';
+                case 6:
+                    return 'rotate(90deg)';
+                case 7:
+                    return 'rotate(90deg) rotateY(180deg)';
+                case 8:
+                    return 'rotate(270deg)';
+                default:
+                    return '';
+            }
+        },
+        setTransform: function (el, val) {
+            if (!el) {
+                return;
+            }
+            el.style.transform = val;
+            el.style.webkitTransform = val;
+            el.style['-moz-transform'] = val;
+            el.style['-ms-transform'] = val;
+            el.style['-o-transform'] = val;
+        },
+        getObjectKeys: function (obj) {
+            var keys = [];
+            if (obj) {
+                $.each(obj, function (key) {
+                    keys.push(key);
+                });
+            }
+            return keys;
+        },
+        getObjectSize: function (obj) {
+            return $h.getObjectKeys(obj).length;
+        },
+        /**
+         * Small dependency injection for the task manager
+         * https://gist.github.com/fearphage/4341799
+         */
+        whenAll: function (array) {
+            var s = [].slice, resolveValues = arguments.length === 1 && $h.isArray(array) ? array : s.call(arguments),
+                deferred = $.Deferred(), i, failed = 0, value, length = resolveValues.length,
+                remaining = length, rejectContexts, rejectValues, resolveContexts, updateFunc;
+            rejectContexts = rejectValues = resolveContexts = Array(length);
+            updateFunc = function (index, contexts, values) {
+                return function () {
+                    if (values !== resolveValues) {
+                        failed++;
+                    }
+                    deferred.notifyWith(contexts[index] = this, values[index] = s.call(arguments));
+                    if (!(--remaining)) {
+                        deferred[(!failed ? 'resolve' : 'reject') + 'With'](contexts, values);
+                    }
+                };
+            };
+            for (i = 0; i < length; i++) {
+                if ((value = resolveValues[i]) && $.isFunction(value.promise)) {
+                    value.promise()
+                        .done(updateFunc(i, resolveContexts, resolveValues))
+                        .fail(updateFunc(i, rejectContexts, rejectValues));
+                } else {
+                    deferred.notifyWith(this, value);
+                    --remaining;
+                }
+            }
+            if (!remaining) {
+                deferred.resolveWith(resolveContexts, resolveValues);
+            }
+            return deferred.promise();
+        }
+    };
+    FileInput = function (element, options) {
+        var self = this;
+        self.$element = $(element);
+        self.$parent = self.$element.parent();
+        if (!self._validate()) {
+            return;
+        }
+        self.isPreviewable = $h.hasFileAPISupport();
+        self.isIE9 = $h.isIE(9);
+        self.isIE10 = $h.isIE(10);
+        if (self.isPreviewable || self.isIE9) {
+            self._init(options);
+            self._listen();
+        }
+        self.$element.removeClass('file-loading');
+    };
+
+    FileInput.prototype = {
+        constructor: FileInput,
+        _cleanup: function () {
+            var self = this;
+            self.reader = null;
+            self.clearFileStack();
+            self.fileBatchCompleted = true;
+            self.isError = false;
+            self.isDuplicateError = false;
+            self.isPersistentError = false;
+            self.cancelling = false;
+            self.paused = false;
+            self.lastProgress = 0;
+            self._initAjax();
+        },
+        _isAborted: function () {
+            var self = this;
+            return self.cancelling || self.paused;
+        },
+        _initAjax: function () {
+            var self = this, tm = self.taskManager = {
+                pool: {},
+                addPool: function (id) {
+                    return (tm.pool[id] = new tm.TasksPool(id));
+                },
+                getPool: function (id) {
+                    return tm.pool[id];
+                },
+                addTask: function (id, logic) { // add standalone task directly from task manager
+                    return new tm.Task(id, logic);
+                },
+                TasksPool: function (id) {
+                    var tp = this;
+                    tp.id = id;
+                    tp.cancelled = false;
+                    tp.cancelledDeferrer = $.Deferred();
+                    tp.tasks = {};
+                    tp.addTask = function (id, logic) {
+                        return (tp.tasks[id] = new tm.Task(id, logic));
+                    };
+                    tp.size = function () {
+                        return $h.getObjectSize(tp.tasks);
+                    };
+                    tp.run = function (maxThreads) {
+                        var i = 0, failed = false, task, tasksList = $h.getObjectKeys(tp.tasks).map(function (key) {
+                            return tp.tasks[key];
+                        }), tasksDone = [], deferred = $.Deferred(), enqueue, callback;
+
+                        if (tp.cancelled) {
+                            tp.cancelledDeferrer.resolve();
+                            return deferred.reject();
+                        }
+                        // if run all at once
+                        if (!maxThreads) {
+                            var tasksDeferredList = $h.getObjectKeys(tp.tasks).map(function (key) {
+                                return tp.tasks[key].deferred;
+                            });
+                            // when all are done
+                            $h.whenAll(tasksDeferredList).done(function () {
+                                var argv = $h.getArray(arguments);
+                                if (!tp.cancelled) {
+                                    deferred.resolve.apply(null, argv);
+                                    tp.cancelledDeferrer.reject();
+                                } else {
+                                    deferred.reject.apply(null, argv);
+                                    tp.cancelledDeferrer.resolve();
+                                }
+                            }).fail(function () {
+                                var argv = $h.getArray(arguments);
+                                deferred.reject.apply(null, argv);
+                                if (!tp.cancelled) {
+                                    tp.cancelledDeferrer.reject();
+                                } else {
+                                    tp.cancelledDeferrer.resolve();
+                                }
+                            });
+                            // run all tasks
+                            $.each(tp.tasks, function (id) {
+                                task = tp.tasks[id];
+                                task.run();
+                            });
+                            return deferred;
+                        }
+                        enqueue = function (task) {
+                            $.when(task.deferred)
+                                .fail(function () {
+                                    failed = true;
+                                    callback.apply(null, arguments);
+                                })
+                                .always(callback);
+                        };
+                        callback = function () {
+                            var argv = $h.getArray(arguments);
+                            // notify a task just ended
+                            deferred.notify(argv);
+                            tasksDone.push(argv);
+                            if (tp.cancelled) {
+                                deferred.reject.apply(null, tasksDone);
+                                tp.cancelledDeferrer.resolve();
+                                return;
+                            }
+                            if (tasksDone.length === tp.size()) {
+                                if (failed) {
+                                    deferred.reject.apply(null, tasksDone);
+                                } else {
+                                    deferred.resolve.apply(null, tasksDone);
+                                }
+                            }
+                            // if there are any tasks remaining
+                            if (tasksList.length) {
+                                task = tasksList.shift();
+                                enqueue(task);
+                                task.run();
+                            }
+                        };
+                        // run the first "maxThreads" tasks
+                        while (tasksList.length && i++ < maxThreads) {
+                            task = tasksList.shift();
+                            enqueue(task);
+                            task.run();
+                        }
+                        return deferred;
+                    };
+                    tp.cancel = function () {
+                        tp.cancelled = true;
+                        return tp.cancelledDeferrer;
+                    };
+                },
+                Task: function (id, logic) {
+                    var tk = this;
+                    tk.id = id;
+                    tk.deferred = $.Deferred();
+                    tk.logic = logic;
+                    tk.context = null;
+                    tk.run = function () {
+                        var argv = $h.getArray(arguments);
+                        argv.unshift(tk.deferred);     // add deferrer as first argument
+                        logic.apply(tk.context, argv); // run task
+                        return tk.deferred;            // return deferrer
+                    };
+                    tk.runWithContext = function (context) {
+                        tk.context = context;
+                        return tk.run();
+                    };
+                }
+            };
+            self.ajaxQueue = [];
+            self.ajaxRequests = [];
+            self.ajaxPool = null;
+            self.ajaxAborted = false;
+        },
+        _init: function (options, refreshMode) {
+            var self = this, f, $el = self.$element, $cont, t, tmp;
+            self.options = options;
+            self.zoomPlaceholder = $h.getZoomPlaceholder();
+            self.canOrientImage = $h.canOrientImage($el);
+            $.each(options, function (key, value) {
+                switch (key) {
+                    case 'minFileCount':
+                    case 'maxFileCount':
+                    case 'maxTotalFileCount':
+                    case 'minFileSize':
+                    case 'maxFileSize':
+                    case 'maxFilePreviewSize':
+                    case 'resizeQuality':
+                    case 'resizeIfSizeMoreThan':
+                    case 'progressUploadThreshold':
+                    case 'initialPreviewCount':
+                    case 'zoomModalHeight':
+                    case 'minImageHeight':
+                    case 'maxImageHeight':
+                    case 'minImageWidth':
+                    case 'maxImageWidth':
+                    case 'bytesToKB':
+                        self[key] = $h.getNum(value);
+                        break;
+                    default:
+                        self[key] = value;
+                        break;
+                }
+            });
+            if (!self.bytesToKB || self.bytesToKB <= 0) {
+                self.bytesToKB = 1024;
+            }
+            if (self.errorCloseButton === undefined) {
+                self.errorCloseButton = $h.closeButton('kv-error-close' + ($h.isBs(5) ? '  float-end' : ''));
+            }
+            if (self.maxTotalFileCount > 0 && self.maxTotalFileCount < self.maxFileCount) {
+                self.maxTotalFileCount = self.maxFileCount;
+            }
+            if (self.rtl) { // swap buttons for rtl
+                tmp = self.previewZoomButtonIcons.prev;
+                self.previewZoomButtonIcons.prev = self.previewZoomButtonIcons.next;
+                self.previewZoomButtonIcons.next = tmp;
+            }
+            // validate chunk threads to not exceed maxAjaxThreads
+            if (!isNaN(self.maxAjaxThreads) && self.maxAjaxThreads < self.resumableUploadOptions.maxThreads) {
+                self.resumableUploadOptions.maxThreads = self.maxAjaxThreads;
+            }
+            self._initFileManager();
+            if (typeof self.autoOrientImage === 'function') {
+                self.autoOrientImage = self.autoOrientImage();
+            }
+            if (typeof self.autoOrientImageInitial === 'function') {
+                self.autoOrientImageInitial = self.autoOrientImageInitial();
+            }
+            if (!refreshMode) {
+                self._cleanup();
+            }
+            self.duplicateErrors = [];
+            self.$form = $el.closest('form');
+            self._initTemplateDefaults();
+            self.uploadFileAttr = !$h.isEmpty($el.attr('name')) ? $el.attr('name') : 'file_data';
+            t = self._getLayoutTemplate('progress');
+            self.progressTemplate = t.replace('{class}', self.progressClass);
+            self.progressInfoTemplate = t.replace('{class}', self.progressInfoClass);
+            self.progressPauseTemplate = t.replace('{class}', self.progressPauseClass);
+            self.progressCompleteTemplate = t.replace('{class}', self.progressCompleteClass);
+            self.progressErrorTemplate = t.replace('{class}', self.progressErrorClass);
+            self.isDisabled = $el.attr('disabled') || $el.attr('readonly');
+            if (self.isDisabled) {
+                $el.attr('disabled', true);
+            }
+            self.isClickable = self.browseOnZoneClick && self.showPreview &&
+                (self.dropZoneEnabled || !$h.isEmpty(self.defaultPreviewContent));
+            self.isAjaxUpload = $h.hasFileUploadSupport() && !$h.isEmpty(self.uploadUrl);
+            self.dropZoneEnabled = $h.hasDragDropSupport() && self.dropZoneEnabled;
+            if (!self.isAjaxUpload) {
+                self.dropZoneEnabled = self.dropZoneEnabled && $h.canAssignFilesToInput();
+            }
+            self.slug = typeof options.slugCallback === 'function' ? options.slugCallback : self._slugDefault;
+            self.mainTemplate = self.showCaption ? self._getLayoutTemplate('main1') : self._getLayoutTemplate('main2');
+            self.captionTemplate = self._getLayoutTemplate('caption');
+            self.previewGenericTemplate = self._getPreviewTemplate('generic');
+            if (!self.imageCanvas && self.resizeImage && (self.maxImageWidth || self.maxImageHeight)) {
+                self.imageCanvas = document.createElement('canvas');
+                self.imageCanvasContext = self.imageCanvas.getContext('2d');
+            }
+            if ($h.isEmpty($el.attr('id'))) {
+                $el.attr('id', $h.uniqId());
+            }
+            self.namespace = '.fileinput_' + $el.attr('id').replace(/-/g, '_');
+            if (self.$container === undefined) {
+                self.$container = self._createContainer();
+            } else {
+                self._refreshContainer();
+            }
+            $cont = self.$container;
+            self.$dropZone = $cont.find('.file-drop-zone');
+            self.$progress = $cont.find('.kv-upload-progress');
+            self.$btnUpload = $cont.find('.fileinput-upload');
+            self.$captionContainer = $h.getElement(options, 'elCaptionContainer', $cont.find('.file-caption'));
+            self.$caption = $h.getElement(options, 'elCaptionText', $cont.find('.file-caption-name'));
+            if (!$h.isEmpty(self.msgPlaceholder)) {
+                f = $el.attr('multiple') ? self.filePlural : self.fileSingle;
+                self.$caption.attr('placeholder', self.msgPlaceholder.replace('{files}', f));
+            }
+            self.$captionIcon = self.$captionContainer.find('.file-caption-icon');
+            self.$previewContainer = $h.getElement(options, 'elPreviewContainer', $cont.find('.file-preview'));
+            self.$preview = $h.getElement(options, 'elPreviewImage', $cont.find('.file-preview-thumbnails'));
+            self.$previewStatus = $h.getElement(options, 'elPreviewStatus', $cont.find('.file-preview-status'));
+            self.$errorContainer = $h.getElement(options, 'elErrorContainer',
+                self.$previewContainer.find('.kv-fileinput-error'));
+            self._validateDisabled();
+            if (!$h.isEmpty(self.msgErrorClass)) {
+                $h.addCss(self.$errorContainer, self.msgErrorClass);
+            }
+            if (!refreshMode) {
+                self._resetErrors();
+                self.$errorContainer.hide();
+                self.previewInitId = 'thumb-' + $el.attr('id');
+                self._initPreviewCache();
+                self._initPreview(true);
+                self._initPreviewActions();
+                if (self.$parent.hasClass('file-loading')) {
+                    self.$container.insertBefore(self.$parent);
+                    self.$parent.remove();
+                }
+            } else {
+                if (!self._errorsExist()) {
+                    self.$errorContainer.hide();
+                }
+            }
+            self._setFileDropZoneTitle();
+            if ($el.attr('disabled')) {
+                self.disable();
+            }
+            self._initZoom();
+            if (self.hideThumbnailContent) {
+                $h.addCss(self.$preview, 'hide-content');
+            }
+        },
+        _initFileManager: function () {
+            var self = this;
+            self.uploadStartTime = $h.now();
+            self.fileManager = {
+                stack: {},
+                filesProcessed: [],
+                errors: [],
+                loadedImages: {},
+                totalImages: 0,
+                totalFiles: null,
+                totalSize: null,
+                uploadedSize: 0,
+                stats: {},
+                bpsLog: [],
+                bps: 0,
+                initStats: function (id) {
+                    var data = {started: $h.now()};
+                    if (id) {
+                        self.fileManager.stats[id] = data;
+                    } else {
+                        self.fileManager.stats = data;
+                    }
+                },
+                getUploadStats: function (id, loaded, total) {
+                    var fm = self.fileManager,
+                        started = id ? fm.stats[id] && fm.stats[id].started || $h.now() : self.uploadStartTime,
+                        elapsed = ($h.now() - started) / 1000, bps = Math.ceil(elapsed ? loaded / elapsed : 0),
+                        pendingBytes = total - loaded, out, delay = fm.bpsLog.length ? self.bitrateUpdateDelay : 0;
+                    setTimeout(function () {
+                        var i, j = 0, n = 0, len, beg;
+                        fm.bpsLog.push(bps);
+                        fm.bpsLog.sort(function (a, b) {
+                            return a - b;
+                        });
+                        len = fm.bpsLog.length;
+                        beg = len > 10 ? len - 10 : Math.ceil(len / 2);
+                        for (i = len; i > beg; i--) {
+                            n = parseFloat(fm.bpsLog[i]);
+                            j++;
+                        }
+                        fm.bps = (j > 0 ? n / j : 0) * 64;
+                    }, delay);
+                    out = {
+                        fileId: id,
+                        started: started,
+                        elapsed: elapsed,
+                        loaded: loaded,
+                        total: total,
+                        bps: fm.bps,
+                        bitrate: self._getSize(fm.bps, false, self.bitRateUnits),
+                        pendingBytes: pendingBytes
+                    };
+                    if (id) {
+                        fm.stats[id] = out;
+                    } else {
+                        fm.stats = out;
+                    }
+                    return out;
+                },
+                exists: function (id) {
+                    return $.inArray(id, self.fileManager.getIdList()) !== -1;
+                },
+                count: function () {
+                    return self.fileManager.getIdList().length;
+                },
+                total: function () {
+                    var fm = self.fileManager;
+                    if (!fm.totalFiles) {
+                        fm.totalFiles = fm.count();
+                    }
+                    return fm.totalFiles;
+                },
+                getTotalSize: function () {
+                    var fm = self.fileManager;
+                    if (fm.totalSize) {
+                        return fm.totalSize;
+                    }
+                    fm.totalSize = 0;
+                    $.each(self.getFileStack(), function (id, f) {
+                        var size = parseFloat(f.size);
+                        fm.totalSize += isNaN(size) ? 0 : size;
+                    });
+                    return fm.totalSize;
+                },
+                add: function (file, id) {
+                    if (!id) {
+                        id = self.fileManager.getId(file);
+                    }
+                    if (!id) {
+                        return;
+                    }
+                    self.fileManager.stack[id] = {
+                        file: file,
+                        name: $h.getFileName(file),
+                        relativePath: $h.getFileRelativePath(file),
+                        size: file.size,
+                        nameFmt: self._getFileName(file, ''),
+                        sizeFmt: self._getSize(file.size)
+                    };
+                },
+                remove: function ($thumb) {
+                    var id = self._getThumbFileId($thumb);
+                    self.fileManager.removeFile(id);
+                },
+                removeFile: function (id) {
+                    var fm = self.fileManager;
+                    if (!id) {
+                        return;
+                    }
+                    delete fm.stack[id];
+                    delete fm.loadedImages[id];
+                },
+                move: function (idFrom, idTo) {
+                    var result = {}, stack = self.fileManager.stack;
+                    if (!idFrom && !idTo || idFrom === idTo) {
+                        return;
+                    }
+                    $.each(stack, function (k, v) {
+                        if (k !== idFrom) {
+                            result[k] = v;
+                        }
+                        if (k === idTo) {
+                            result[idFrom] = stack[idFrom];
+                        }
+                    });
+                    self.fileManager.stack = result;
+                },
+                list: function () {
+                    var files = [];
+                    $.each(self.getFileStack(), function (k, v) {
+                        if (v && v.file) {
+                            files.push(v.file);
+                        }
+                    });
+                    return files;
+                },
+                isPending: function (id) {
+                    return $.inArray(id, self.fileManager.filesProcessed) === -1 && self.fileManager.exists(id);
+                },
+                isProcessed: function () {
+                    var filesProcessed = true, fm = self.fileManager;
+                    $.each(self.getFileStack(), function (id) {
+                        if (fm.isPending(id)) {
+                            filesProcessed = false;
+                        }
+                    });
+                    return filesProcessed;
+                },
+                clear: function () {
+                    var fm = self.fileManager;
+                    self.isDuplicateError = false;
+                    self.isPersistentError = false;
+                    fm.totalFiles = null;
+                    fm.totalSize = null;
+                    fm.uploadedSize = 0;
+                    fm.stack = {};
+                    fm.errors = [];
+                    fm.filesProcessed = [];
+                    fm.stats = {};
+                    fm.bpsLog = [];
+                    fm.bps = 0;
+                    fm.clearImages();
+                },
+                clearImages: function () {
+                    self.fileManager.loadedImages = {};
+                    self.fileManager.totalImages = 0;
+                },
+                addImage: function (id, config) {
+                    self.fileManager.loadedImages[id] = config;
+                },
+                removeImage: function (id) {
+                    delete self.fileManager.loadedImages[id];
+                },
+                getImageIdList: function () {
+                    return $h.getObjectKeys(self.fileManager.loadedImages);
+                },
+                getImageCount: function () {
+                    return self.fileManager.getImageIdList().length;
+                },
+                getId: function (file) {
+                    return self._getFileId(file);
+                },
+                getIndex: function (id) {
+                    return self.fileManager.getIdList().indexOf(id);
+                },
+                getThumb: function (id) {
+                    var $thumb = null;
+                    self._getThumbs().each(function () {
+                        var $t = $(this);
+                        if (self._getThumbFileId($t) === id) {
+                            $thumb = $t;
+                        }
+                    });
+                    return $thumb;
+                },
+                getThumbIndex: function ($thumb) {
+                    var id = self._getThumbFileId($thumb);
+                    return self.fileManager.getIndex(id);
+                },
+                getIdList: function () {
+                    return $h.getObjectKeys(self.fileManager.stack);
+                },
+                getFile: function (id) {
+                    return self.fileManager.stack[id] || null;
+                },
+                getFileName: function (id, fmt) {
+                    var file = self.fileManager.getFile(id);
+                    if (!file) {
+                        return '';
+                    }
+                    return fmt ? (file.nameFmt || '') : file.name || '';
+                },
+                getFirstFile: function () {
+                    var ids = self.fileManager.getIdList(), id = ids && ids.length ? ids[0] : null;
+                    return self.fileManager.getFile(id);
+                },
+                setFile: function (id, file) {
+                    if (self.fileManager.getFile(id)) {
+                        self.fileManager.stack[id].file = file;
+                    } else {
+                        self.fileManager.add(file, id);
+                    }
+                },
+                setProcessed: function (id) {
+                    self.fileManager.filesProcessed.push(id);
+                },
+                getProgress: function () {
+                    var total = self.fileManager.total(), filesProcessed = self.fileManager.filesProcessed.length;
+                    if (!total) {
+                        return 0;
+                    }
+                    return Math.ceil(filesProcessed / total * 100);
+
+                },
+                setProgress: function (id, pct) {
+                    var f = self.fileManager.getFile(id);
+                    if (!isNaN(pct) && f) {
+                        f.progress = pct;
+                    }
+                }
+            };
+        },
+        _setUploadData: function (fd, config) {
+            var self = this;
+            $.each(config, function (key, value) {
+                var param = self.uploadParamNames[key] || key;
+                if ($h.isArray(value)) {
+                    fd.append(param, value[0], value[1]);
+                } else {
+                    fd.append(param, value);
+                }
+            });
+        },
+        _initResumableUpload: function () {
+            var self = this, opts = self.resumableUploadOptions, logs = $h.logMessages, rm, fm = self.fileManager;
+            if (!self.enableResumableUpload) {
+                return;
+            }
+            if (opts.fallback !== false && typeof opts.fallback !== 'function') {
+                opts.fallback = function (s) {
+                    s._log(logs.noResumableSupport);
+                    s.enableResumableUpload = false;
+                };
+            }
+            if (!$h.hasResumableUploadSupport() && opts.fallback !== false) {
+                opts.fallback(self);
+                return;
+            }
+            if (!self.uploadUrl && self.enableResumableUpload) {
+                self._log(logs.noUploadUrl);
+                self.enableResumableUpload = false;
+                return;
+
+            }
+            opts.chunkSize = parseFloat(opts.chunkSize);
+            if (opts.chunkSize <= 0 || isNaN(opts.chunkSize)) {
+                self._log(logs.invalidChunkSize, {chunkSize: opts.chunkSize});
+                self.enableResumableUpload = false;
+                return;
+            }
+            rm = self.resumableManager = {
+                init: function (id, f, index) {
+                    rm.logs = [];
+                    rm.stack = [];
+                    rm.error = '';
+                    rm.id = id;
+                    rm.file = f.file;
+                    rm.fileName = f.name;
+                    rm.fileIndex = index;
+                    rm.completed = false;
+                    rm.lastProgress = 0;
+                    if (self.showPreview) {
+                        rm.$thumb = fm.getThumb(id) || null;
+                        rm.$progress = rm.$btnDelete = null;
+                        if (rm.$thumb && rm.$thumb.length) {
+                            rm.$progress = rm.$thumb.find('.file-thumb-progress');
+                            rm.$btnDelete = rm.$thumb.find('.kv-file-remove');
+                        }
+                    }
+                    rm.chunkSize = opts.chunkSize * self.bytesToKB;
+                    rm.chunkCount = rm.getTotalChunks();
+                },
+                setAjaxError: function (jqXHR, textStatus, errorThrown, isTest) {
+                    if (jqXHR.responseJSON && jqXHR.responseJSON.error) {
+                        errorThrown = jqXHR.responseJSON.error.toString();
+                    }
+                    if (!isTest) {
+                        rm.error = errorThrown;
+                    }
+                    if (opts.showErrorLog) {
+                        self._log(logs.ajaxError, {
+                            status: jqXHR.status,
+                            error: errorThrown,
+                            text: jqXHR.responseText || ''
+                        });
+                    }
+                },
+                reset: function () {
+                    rm.stack = [];
+                    rm.chunksProcessed = {};
+                },
+                setProcessed: function (status) {
+                    var id = rm.id, msg, $thumb = rm.$thumb, $prog = rm.$progress, hasThumb = $thumb && $thumb.length,
+                        params = {id: hasThumb ? $thumb.attr('id') : '', index: fm.getIndex(id), fileId: id}, tokens,
+                        skipErrorsAndProceed = self.resumableUploadOptions.skipErrorsAndProceed;
+                    rm.completed = true;
+                    rm.lastProgress = 0;
+                    if (hasThumb) {
+                        $thumb.removeClass('file-uploading');
+                    }
+                    if (status === 'success') {
+                        fm.uploadedSize += rm.file.size;
+                        if (self.showPreview) {
+                            self._setProgress(101, $prog);
+                            self._setThumbStatus($thumb, 'Success');
+                            self._initUploadSuccess(rm.chunksProcessed[id].data, $thumb);
+                        }
+                        fm.removeFile(id);
+                        delete rm.chunksProcessed[id];
+                        self._raise('fileuploaded', [params.id, params.index, params.fileId]);
+                        if (fm.isProcessed()) {
+                            self._setProgress(101);
+                        }
+                    } else {
+                        if (status !== 'cancel') {
+                            if (self.showPreview) {
+                                self._setThumbStatus($thumb, 'Error');
+                                self._setPreviewError($thumb, true);
+                                self._setProgress(101, $prog, self.msgProgressError);
+                                self._setProgress(101, self.$progress, self.msgProgressError);
+                                self.cancelling = !skipErrorsAndProceed;
+                            }
+                            if (!self.$errorContainer.find('li[data-file-id="' + params.fileId + '"]').length) {
+                                tokens = {file: rm.fileName, max: opts.maxRetries, error: rm.error};
+                                msg = self.msgResumableUploadRetriesExceeded.setTokens(tokens);
+                                $.extend(params, tokens);
+                                self._showFileError(msg, params, 'filemaxretries');
+                                if (skipErrorsAndProceed) {
+                                    fm.removeFile(id);
+                                    delete rm.chunksProcessed[id];
+                                    if (fm.isProcessed()) {
+                                        self._setProgress(101);
+                                    }
+                                }
+                            }
+                        }
+                    }
+                    if (fm.isProcessed()) {
+                        rm.reset();
+                    }
+                },
+                check: function () {
+                    var status = true;
+                    $.each(rm.logs, function (index, value) {
+                        if (!value) {
+                            status = false;
+                            return false;
+                        }
+                    });
+                },
+                processedResumables: function () {
+                    var logs = rm.logs, i, count = 0;
+                    if (!logs || !logs.length) {
+                        return 0;
+                    }
+                    for (i = 0; i < logs.length; i++) {
+                        if (logs[i] === true) {
+                            count++;
+                        }
+                    }
+                    return count;
+                },
+                getUploadedSize: function () {
+                    var size = rm.processedResumables() * rm.chunkSize;
+                    return size > rm.file.size ? rm.file.size : size;
+                },
+                getTotalChunks: function () {
+                    var chunkSize = parseFloat(rm.chunkSize);
+                    if (!isNaN(chunkSize) && chunkSize > 0) {
+                        return Math.ceil(rm.file.size / chunkSize);
+                    }
+                    return 0;
+                },
+                getProgress: function () {
+                    var chunksProcessed = rm.processedResumables(), total = rm.chunkCount;
+                    if (total === 0) {
+                        return 0;
+                    }
+                    return Math.ceil(chunksProcessed / total * 100);
+                },
+                checkAborted: function (intervalId) {
+                    if (self._isAborted()) {
+                        clearInterval(intervalId);
+                        self.unlock();
+                    }
+                },
+                upload: function () {
+                    var ids = fm.getIdList(), flag = 'new', intervalId;
+                    intervalId = setInterval(function () {
+                        var id;
+                        rm.checkAborted(intervalId);
+                        if (flag === 'new') {
+                            self.lock();
+                            flag = 'processing';
+                            id = ids.shift();
+                            fm.initStats(id);
+                            if (fm.stack[id]) {
+                                rm.init(id, fm.stack[id], fm.getIndex(id));
+                                rm.processUpload();
+                            }
+                        }
+                        if (!fm.isPending(id) && rm.completed) {
+                            flag = 'new';
+                        }
+                        if (fm.isProcessed()) {
+                            var $initThumbs = self.$preview.find('.file-preview-initial');
+                            if ($initThumbs.length) {
+                                $h.addCss($initThumbs, $h.SORT_CSS);
+                                self._initSortable();
+                            }
+                            clearInterval(intervalId);
+                            self._clearFileInput();
+                            self.unlock();
+                            setTimeout(function () {
+                                var data = self.previewCache.data;
+                                if (data) {
+                                    self.initialPreview = data.content;
+                                    self.initialPreviewConfig = data.config;
+                                    self.initialPreviewThumbTags = data.tags;
+                                }
+                                self._raise('filebatchuploadcomplete', [
+                                    self.initialPreview,
+                                    self.initialPreviewConfig,
+                                    self.initialPreviewThumbTags,
+                                    self._getExtraData()
+                                ]);
+                            }, self.processDelay);
+                        }
+                    }, self.processDelay);
+                },
+                uploadResumable: function () {
+                    var i, pool, tm = self.taskManager, total = rm.chunkCount;
+                    pool = tm.addPool(rm.id);
+                    for (i = 0; i < total; i++) {
+                        rm.logs[i] = !!(rm.chunksProcessed[rm.id] && rm.chunksProcessed[rm.id][i]);
+                        if (!rm.logs[i]) {
+                            rm.pushAjax(i, 0);
+                        }
+                    }
+                    pool.run(opts.maxThreads)
+                        .done(function () {
+                            rm.setProcessed('success');
+                        })
+                        .fail(function () {
+                            rm.setProcessed(pool.cancelled ? 'cancel' : 'error');
+                        });
+                },
+                processUpload: function () {
+                    var fd, f, id = rm.id, fnBefore, fnSuccess, fnError, fnComplete, outData;
+                    if (!opts.testUrl) {
+                        rm.uploadResumable();
+                        return;
+                    }
+                    fd = new FormData();
+                    f = fm.stack[id];
+                    self._setUploadData(fd, {
+                        fileId: id,
+                        fileName: f.fileName,
+                        fileSize: f.size,
+                        fileRelativePath: f.relativePath,
+                        chunkSize: rm.chunkSize,
+                        chunkCount: rm.chunkCount
+                    });
+                    fnBefore = function (jqXHR) {
+                        outData = self._getOutData(fd, jqXHR);
+                        self._raise('filetestbeforesend', [id, fm, rm, outData]);
+                    };
+                    fnSuccess = function (data, textStatus, jqXHR) {
+                        outData = self._getOutData(fd, jqXHR, data);
+                        var pNames = self.uploadParamNames, chunksUploaded = pNames.chunksUploaded || 'chunksUploaded',
+                            params = [id, fm, rm, outData];
+                        if (!data[chunksUploaded] || !$h.isArray(data[chunksUploaded])) {
+                            self._raise('filetesterror', params);
+                        } else {
+                            if (!rm.chunksProcessed[id]) {
+                                rm.chunksProcessed[id] = {};
+                            }
+                            $.each(data[chunksUploaded], function (key, index) {
+                                rm.logs[index] = true;
+                                rm.chunksProcessed[id][index] = true;
+                            });
+                            rm.chunksProcessed[id].data = data;
+                            self._raise('filetestsuccess', params);
+                        }
+                        rm.uploadResumable();
+                    };
+                    fnError = function (jqXHR, textStatus, errorThrown) {
+                        outData = self._getOutData(fd, jqXHR);
+                        self._raise('filetestajaxerror', [id, fm, rm, outData]);
+                        rm.setAjaxError(jqXHR, textStatus, errorThrown, true);
+                        rm.uploadResumable();
+                    };
+                    fnComplete = function () {
+                        self._raise('filetestcomplete', [id, fm, rm, self._getOutData(fd)]);
+                    };
+                    self._ajaxSubmit(fnBefore, fnSuccess, fnComplete, fnError, fd, id, rm.fileIndex, opts.testUrl);
+                },
+                pushAjax: function (index, retry) {
+                    var tm = self.taskManager, pool = tm.getPool(rm.id);
+                    pool.addTask(pool.size() + 1, function (deferrer) {
+                        // use fifo chunk stack
+                        var arr = rm.stack.shift(), index;
+                        index = arr[0];
+                        if (!rm.chunksProcessed[rm.id] || !rm.chunksProcessed[rm.id][index]) {
+                            rm.sendAjax(index, arr[1], deferrer);
+                        } else {
+                            self._log(logs.chunkQueueError, {index: index});
+                        }
+                    });
+                    rm.stack.push([index, retry]);
+                },
+                sendAjax: function (index, retry, deferrer) {
+                    var f, chunkSize = rm.chunkSize, id = rm.id, file = rm.file, $thumb = rm.$thumb,
+                        msgs = $h.logMessages, $btnDelete = rm.$btnDelete, logError = function (msg, tokens) {
+                            if (tokens) {
+                                msg = msg.setTokens(tokens);
+                            }
+                            msg = msgs.resumableRequestError.setTokens({msg: msg});
+                            self._log(msg);
+                            deferrer.reject(msg);
+                        };
+                    if (rm.chunksProcessed[id] && rm.chunksProcessed[id][index]) {
+                        return;
+                    }
+                    if (retry > opts.maxRetries) {
+                        logError(msgs.resumableMaxRetriesReached, {n: opts.maxRetries});
+                        rm.setProcessed('error');
+                        return;
+                    }
+                    var fd, outData, fnBefore, fnSuccess, fnError, fnComplete, slice = file.slice ? 'slice' :
+                            (file.mozSlice ? 'mozSlice' : (file.webkitSlice ? 'webkitSlice' : 'slice')),
+                        blob = file[slice](chunkSize * index, chunkSize * (index + 1));
+                    fd = new FormData();
+                    f = fm.stack[id];
+                    self._setUploadData(fd, {
+                        chunkCount: rm.chunkCount,
+                        chunkIndex: index,
+                        chunkSize: chunkSize,
+                        chunkSizeStart: chunkSize * index,
+                        fileBlob: [blob, rm.fileName],
+                        fileId: id,
+                        fileName: rm.fileName,
+                        fileRelativePath: f.relativePath,
+                        fileSize: file.size,
+                        retryCount: retry
+                    });
+                    if (rm.$progress && rm.$progress.length) {
+                        rm.$progress.show();
+                    }
+                    fnBefore = function (jqXHR) {
+                        outData = self._getOutData(fd, jqXHR);
+                        if (self.showPreview) {
+                            if (!$thumb.hasClass('file-preview-success')) {
+                                self._setThumbStatus($thumb, 'Loading');
+                                $h.addCss($thumb, 'file-uploading');
+                            }
+                            $btnDelete.attr('disabled', true);
+                        }
+                        self._raise('filechunkbeforesend', [id, index, retry, fm, rm, outData]);
+                    };
+                    fnSuccess = function (data, textStatus, jqXHR) {
+                        if (self._isAborted()) {
+                            logError(msgs.resumableAborting);
+                            return;
+                        }
+                        outData = self._getOutData(fd, jqXHR, data);
+                        var paramNames = self.uploadParamNames, chunkIndex = paramNames.chunkIndex || 'chunkIndex',
+                            params = [id, index, retry, fm, rm, outData];
+                        if (data.error) {
+                            if (opts.showErrorLog) {
+                                self._log(logs.retryStatus, {
+                                    retry: retry + 1,
+                                    filename: rm.fileName,
+                                    chunk: index
+                                });
+                            }
+                            self._raise('filechunkerror', params);
+                            rm.pushAjax(index, retry + 1);
+                            rm.error = data.error;
+                            logError(data.error);
+                        } else {
+                            rm.logs[data[chunkIndex]] = true;
+                            if (!rm.chunksProcessed[id]) {
+                                rm.chunksProcessed[id] = {};
+                            }
+                            rm.chunksProcessed[id][data[chunkIndex]] = true;
+                            rm.chunksProcessed[id].data = data;
+                            deferrer.resolve.call(null, data);
+                            self._raise('filechunksuccess', params);
+                            rm.check();
+                        }
+                    };
+                    fnError = function (jqXHR, textStatus, errorThrown) {
+                        if (self._isAborted()) {
+                            logError(msgs.resumableAborting);
+                            return;
+                        }
+                        outData = self._getOutData(fd, jqXHR);
+                        rm.setAjaxError(jqXHR, textStatus, errorThrown);
+                        self._raise('filechunkajaxerror', [id, index, retry, fm, rm, outData]);
+                        rm.pushAjax(index, retry + 1);                        // push another task
+                        logError(msgs.resumableRetryError, {n: retry - 1}); // resolve the current task
+                    };
+                    fnComplete = function () {
+                        if (!self._isAborted()) {
+                            self._raise('filechunkcomplete', [id, index, retry, fm, rm, self._getOutData(fd)]);
+                        }
+                    };
+                    self._ajaxSubmit(fnBefore, fnSuccess, fnComplete, fnError, fd, id, rm.fileIndex);
+                }
+            };
+            rm.reset();
+        },
+        _initTemplateDefaults: function () {
+            var self = this, tMain1, tMain2, tPreview, tFileIcon, tClose, tCaption, tBtnDefault, tBtnLink, tBtnBrowse,
+                tModalMain, tModal, tProgress, tSize, tFooter, tActions, tActionDelete, tActionUpload, tActionDownload,
+                tActionZoom, tActionDrag, tIndicator, tTagBef, tTagBef1, tTagBef2, tTagAft, tGeneric, tHtml, tImage,
+                tText, tOffice, tGdocs, tVideo, tAudio, tFlash, tObject, tPdf, tOther, tStyle, tZoomCache, vDefaultDim,
+                tActionRotate, tStats, tModalLabel, tDescClose, renderObject = function (type, mime) {
+                    return '<object class="kv-preview-data file-preview-' + type + '" title="{caption}" ' +
+                        'data="{data}" type="' + mime + '"' + tStyle + '>\n' + $h.DEFAULT_PREVIEW + '\n</object>\n';
+                }, defBtnCss1 = 'btn btn-sm btn-kv ' + $h.defaultButtonCss();
+            tMain1 = '{preview}\n' +
+                '<div class="kv-upload-progress kv-hidden"></div><div class="clearfix"></div>\n' +
+                '<div class="file-caption {class}">\n' +
+                '  <div class="input-group {inputGroupClass}">\n' +
+                '      {caption}\n<span class="file-caption-icon"></span>\n' +
+                ($h.isBs(5) ? '' : '<div class="input-group-btn input-group-append">\n') +
+                '      {remove}\n' +
+                '      {cancel}\n' +
+                '      {pause}\n' +
+                '      {upload}\n' +
+                '      {browse}\n' +
+                ($h.isBs(5) ? '' : '    </div>\n') +
+                '  </div>';
+            '</div>';
+            tMain2 = '{preview}\n<div class="kv-upload-progress kv-hidden"></div>\n<div class="clearfix"></div>\n' +
+                '<span class="{class}">{remove}\n{cancel}\n{upload}\n{browse}\n</span>';
+            tPreview = '<div class="file-preview {class}">\n' +
+                '  {close}' +
+                '  <div class="{dropClass} clearfix">\n' +
+                '    <div class="file-preview-thumbnails clearfix">\n' +
+                '    </div>\n' +
+                '    <div class="file-preview-status text-center text-success"></div>\n' +
+                '    <div class="kv-fileinput-error"></div>\n' +
+                '  </div>\n' +
+                '</div>';
+            tClose = $h.closeButton('fileinput-remove');
+            tFileIcon = '<i class="glyphicon glyphicon-file"></i>';
+            // noinspection HtmlUnknownAttribute
+            tCaption = '<input readonly class="file-caption-name form-control {class}">\n';
+            //noinspection HtmlUnknownAttribute
+            tBtnDefault = '<button type="{type}" title="{title}" class="{css}" ' +
+                '{status} {tabIndexConfig}>{icon} {label}</button>';
+            //noinspection HtmlUnknownTarget,HtmlUnknownAttribute
+            tBtnLink = '<a href="{href}" title="{title}" class="{css}" {status} {tabIndexConfig}>{icon} {label}</a>';
+            //noinspection HtmlUnknownAttribute
+            tBtnBrowse = '<div class="{css}" {status} {tabIndexConfig}>{icon} {label}</div>';
+            tModalLabel = $h.MODAL_ID + 'Label';
+            tModalMain = '<div id="' + $h.MODAL_ID + '" class="file-zoom-dialog modal fade" ' +
+                'aria-labelledby="' + tModalLabel + '" {tabIndexConfig}></div>';
+            tModal = '<div class="modal-dialog modal-lg{rtl}" role="document">\n' +
+                '  <div class="modal-content">\n' +
+                '    <div class="modal-header kv-zoom-header">\n' +
+                '      <h6 class="modal-title kv-zoom-title" id="' + tModalLabel + '"><span class="kv-zoom-caption"></span> <span class="kv-zoom-size"></span></h6>\n' +
+                '      <div class="kv-zoom-actions">{toggleheader}{fullscreen}{borderless}{close}</div>\n' +
+                '    </div>\n' +
+                '    <div class="floating-buttons"></div>\n' +
+                '    <div class="kv-zoom-body file-zoom-content {zoomFrameClass}"></div>\n' + '{prev} {next}\n' +
+                '    <div class="kv-zoom-description"></div>\n' +
+                '  </div>\n' +
+                '</div>\n';
+            tDescClose = '<button type="button" class="kv-desc-hide" aria-label="Close">{closeIcon}</button>';
+            tProgress = '<div class="progress">\n' +
+                '    <div class="{class}" role="progressbar"' +
+                ' aria-valuenow="{percent}" aria-valuemin="0" aria-valuemax="100" style="width:{percent}%;">\n' +
+                '        {status}\n' +
+                '     </div>\n' +
+                '</div>{stats}';
+            tStats = '<div class="text-primary file-upload-stats">' +
+                '<span class="pending-time">{pendingTime}</span> ' +
+                '<span class="upload-speed">{uploadSpeed}</span>' +
+                '</div>';
+            tSize = ' <samp>({sizeText})</samp>';
+            tFooter = '<div class="file-thumbnail-footer">\n' +
+                '    <div class="file-footer-caption" title="{caption}">\n' +
+                '        <div class="file-caption-info">{caption}</div>\n' +
+                '        <div class="file-size-info">{size}</div>\n' +
+                '    </div>\n' +
+                '    {progress}\n{indicator}\n{actions}\n' +
+                '</div>';
+            tActions = '<div class="file-actions">\n' +
+                '    <div class="file-footer-buttons">\n' +
+                '        {rotate} {download} {upload} {delete} {zoom} {other}' +
+                '    </div>\n' +
+                '</div>\n' +
+                '{drag}\n' +
+                '<div class="clearfix"></div>';
+            //noinspection HtmlUnknownAttribute
+            tActionDelete = '<button type="button" class="kv-file-remove {removeClass}" ' +
+                'title="{removeTitle}" {dataUrl}{dataKey}>{removeIcon}</button>\n';
+            tActionUpload = '<button type="button" class="kv-file-upload {uploadClass}" title="{uploadTitle}">' +
+                '{uploadIcon}</button>';
+            tActionRotate = '<button type="button" class="kv-file-rotate {rotateClass}" title="{rotateTitle}">' +
+                '{rotateIcon}</button>';
+            tActionDownload = '<a class="kv-file-download {downloadClass}" title="{downloadTitle}" ' +
+                'href="{downloadUrl}" download="{caption}" target="_blank">{downloadIcon}</a>';
+            tActionZoom = '<button type="button" class="kv-file-zoom {zoomClass}" ' +
+                'title="{zoomTitle}">{zoomIcon}</button>';
+            tActionDrag = '<span class="file-drag-handle {dragClass}" title="{dragTitle}">{dragIcon}</span>';
+            tIndicator = '<div class="file-upload-indicator" title="{indicatorTitle}">{indicator}</div>';
+            tTagBef = '<div class="file-preview-frame {frameClass}" id="{previewId}" data-fileindex="{fileindex}"' +
+                ' data-fileid="{fileid}" data-filename="{filename}" data-template="{template}" data-zoom="{zoomData}"';
+            tTagBef1 = tTagBef + '><div class="kv-file-content">\n';
+            tTagBef2 = tTagBef + ' title="{caption}"><div class="kv-file-content">\n';
+            tTagAft = '</div>{footer}\n{zoomCache}</div>\n';
+            tGeneric = '{content}\n';
+            tStyle = ' {style}';
+            tHtml = renderObject('html', 'text/html');
+            tText = renderObject('text', 'text/plain;charset=UTF-8');
+            tPdf = renderObject('pdf', 'application/pdf');
+            tImage = '<img src="{data}" class="file-preview-image kv-preview-data" title="{title}" alt="{alt}"' +
+                tStyle + '>\n';
+            tOffice = '<iframe class="kv-preview-data file-preview-office" ' +
+                'src="https://view.officeapps.live.com/op/embed.aspx?src={data}"' + tStyle + '></iframe>';
+            tGdocs = '<iframe class="kv-preview-data file-preview-gdocs" ' +
+                'src="https://docs.google.com/gview?url={data}&embedded=true"' + tStyle + '></iframe>';
+            tVideo = '<video class="kv-preview-data file-preview-video" controls' + tStyle + '>\n' +
+                '<source src="{data}" type="{type}">\n' + $h.DEFAULT_PREVIEW + '\n</video>\n';
+            tAudio = '<!--suppress ALL --><audio class="kv-preview-data file-preview-audio" controls' + tStyle + '>\n<source src="{data}" ' +
+                'type="{type}">\n' + $h.DEFAULT_PREVIEW + '\n</audio>\n';
+            tFlash = '<embed class="kv-preview-data file-preview-flash" src="{data}" type="application/x-shockwave-flash"' + tStyle + '>\n';
+            tObject = '<object class="kv-preview-data file-preview-object file-object {typeCss}" ' +
+                'data="{data}" type="{type}"' + tStyle + '>\n' + '<param name="movie" value="{caption}" />\n' +
+                $h.OBJECT_PARAMS + ' ' + $h.DEFAULT_PREVIEW + '\n</object>\n';
+            tOther = '<div class="kv-preview-data file-preview-other-frame"' + tStyle + '>\n' + $h.DEFAULT_PREVIEW + '\n</div>\n';
+            tZoomCache = '<div class="kv-zoom-cache">{zoomContent}</div>';
+            vDefaultDim = {width: '100%', height: '100%', 'min-height': '480px'};
+            if (self._isPdfRendered()) {
+                tPdf = self.pdfRendererTemplate.replace('{renderer}', self._encodeURI(self.pdfRendererUrl));
+            }
+            self.defaults = {
+                layoutTemplates: {
+                    main1: tMain1,
+                    main2: tMain2,
+                    preview: tPreview,
+                    close: tClose,
+                    fileIcon: tFileIcon,
+                    caption: tCaption,
+                    modalMain: tModalMain,
+                    modal: tModal,
+                    descriptionClose: tDescClose,
+                    progress: tProgress,
+                    stats: tStats,
+                    size: tSize,
+                    footer: tFooter,
+                    indicator: tIndicator,
+                    actions: tActions,
+                    actionDelete: tActionDelete,
+                    actionRotate: tActionRotate,
+                    actionUpload: tActionUpload,
+                    actionDownload: tActionDownload,
+                    actionZoom: tActionZoom,
+                    actionDrag: tActionDrag,
+                    btnDefault: tBtnDefault,
+                    btnLink: tBtnLink,
+                    btnBrowse: tBtnBrowse,
+                    zoomCache: tZoomCache
+                },
+                previewMarkupTags: {
+                    tagBefore1: tTagBef1,
+                    tagBefore2: tTagBef2,
+                    tagAfter: tTagAft
+                },
+                previewContentTemplates: {
+                    generic: tGeneric,
+                    html: tHtml,
+                    image: tImage,
+                    text: tText,
+                    office: tOffice,
+                    gdocs: tGdocs,
+                    video: tVideo,
+                    audio: tAudio,
+                    flash: tFlash,
+                    object: tObject,
+                    pdf: tPdf,
+                    other: tOther
+                },
+                allowedPreviewTypes: ['image', 'html', 'text', 'video', 'audio', 'flash', 'pdf', 'object'],
+                previewTemplates: {},
+                previewSettings: {
+                    image: {width: 'auto', height: 'auto', 'max-width': '100%', 'max-height': '100%'},
+                    html: {width: '213px', height: '160px'},
+                    text: {width: '213px', height: '160px'},
+                    office: {width: '213px', height: '160px'},
+                    gdocs: {width: '213px', height: '160px'},
+                    video: {width: '213px', height: '160px'},
+                    audio: {width: '100%', height: '30px'},
+                    flash: {width: '213px', height: '160px'},
+                    object: {width: '213px', height: '160px'},
+                    pdf: {width: '100%', height: '160px', 'position': 'relative'},
+                    other: {width: '213px', height: '160px'}
+                },
+                previewSettingsSmall: {
+                    image: {width: 'auto', height: 'auto', 'max-width': '100%', 'max-height': '100%'},
+                    html: {width: '100%', height: '160px'},
+                    text: {width: '100%', height: '160px'},
+                    office: {width: '100%', height: '160px'},
+                    gdocs: {width: '100%', height: '160px'},
+                    video: {width: '100%', height: 'auto'},
+                    audio: {width: '100%', height: '30px'},
+                    flash: {width: '100%', height: 'auto'},
+                    object: {width: '100%', height: 'auto'},
+                    pdf: {width: '100%', height: '160px'},
+                    other: {width: '100%', height: '160px'}
+                },
+                previewZoomSettings: {
+                    image: {width: 'auto', height: 'auto', 'max-width': '100%', 'max-height': '100%'},
+                    html: vDefaultDim,
+                    text: vDefaultDim,
+                    office: {width: '100%', height: '100%', 'max-width': '100%', 'min-height': '480px'},
+                    gdocs: {width: '100%', height: '100%', 'max-width': '100%', 'min-height': '480px'},
+                    video: {width: 'auto', height: '100%', 'max-width': '100%'},
+                    audio: {width: '100%', height: '30px'},
+                    flash: {width: 'auto', height: '480px'},
+                    object: {width: 'auto', height: '100%', 'max-width': '100%', 'min-height': '480px'},
+                    pdf: vDefaultDim,
+                    other: {width: 'auto', height: '100%', 'min-height': '480px'}
+                },
+                mimeTypeAliases: {
+                    'video/quicktime': 'video/mp4'
+                },
+                fileTypeSettings: {
+                    image: function (vType, vName) {
+                        return ($h.compare(vType, 'image.*') && !$h.compare(vType, /(tiff?|wmf)$/i) ||
+                            $h.compare(vName, /\.(gif|png|jpe?g)$/i));
+                    },
+                    html: function (vType, vName) {
+                        return $h.compare(vType, 'text/html') || $h.compare(vName, /\.(htm|html)$/i);
+                    },
+                    office: function (vType, vName) {
+                        return $h.compare(vType, /(word|excel|powerpoint|office)$/i) ||
+                            $h.compare(vName, /\.(docx?|xlsx?|pptx?|pps|potx?)$/i);
+                    },
+                    gdocs: function (vType, vName) {
+                        return $h.compare(vType, /(word|excel|powerpoint|office|iwork-pages|tiff?)$/i) ||
+                            $h.compare(vName,
+                                /\.(docx?|xlsx?|pptx?|pps|potx?|rtf|ods|odt|pages|ai|dxf|ttf|tiff?|wmf|e?ps)$/i);
+                    },
+                    text: function (vType, vName) {
+                        return $h.compare(vType, 'text.*') || $h.compare(vName, /\.(xml|javascript)$/i) ||
+                            $h.compare(vName, /\.(txt|md|nfo|ini|json|php|js|css)$/i);
+                    },
+                    video: function (vType, vName) {
+                        return $h.compare(vType, 'video.*') && ($h.compare(vType, /(ogg|mp4|mp?g|mov|webm|3gp)$/i) ||
+                            $h.compare(vName, /\.(og?|mp4|webm|mp?g|mov|3gp)$/i));
+                    },
+                    audio: function (vType, vName) {
+                        return $h.compare(vType, 'audio.*') && ($h.compare(vName, /(ogg|mp3|mp?g|wav)$/i) ||
+                            $h.compare(vName, /\.(og?|mp3|mp?g|wav)$/i));
+                    },
+                    flash: function (vType, vName) {
+                        return $h.compare(vType, 'application/x-shockwave-flash', true) || $h.compare(vName,
+                            /\.(swf)$/i);
+                    },
+                    pdf: function (vType, vName) {
+                        return $h.compare(vType, 'application/pdf', true) || $h.compare(vName, /\.(pdf)$/i);
+                    },
+                    object: function () {
+                        return true;
+                    },
+                    other: function () {
+                        return true;
+                    }
+                },
+                fileActionSettings: {
+                    showRemove: true,
+                    showUpload: true,
+                    showDownload: true,
+                    showZoom: true,
+                    showDrag: true,
+                    showRotate: false,
+                    removeIcon: '<i class="glyphicon glyphicon-trash"></i>',
+                    removeClass: defBtnCss1,
+                    removeErrorClass: 'btn btn-sm btn-kv btn-danger',
+                    removeTitle: 'Remove file',
+                    uploadIcon: '<i class="glyphicon glyphicon-upload"></i>',
+                    uploadClass: defBtnCss1,
+                    uploadTitle: 'Upload file',
+                    uploadRetryIcon: '<i class="glyphicon glyphicon-repeat"></i>',
+                    uploadRetryTitle: 'Retry upload',
+                    downloadIcon: '<i class="glyphicon glyphicon-download"></i>',
+                    downloadClass: defBtnCss1,
+                    downloadTitle: 'Download file',
+                    rotateIcon: '<i class="glyphicon glyphicon-repeat"></i>',
+                    rotateClass: defBtnCss1,
+                    rotateTitle: 'Rotate 90 deg. clockwise',
+                    zoomIcon: '<i class="glyphicon glyphicon-zoom-in"></i>',
+                    zoomClass: defBtnCss1,
+                    zoomTitle: 'View Details',
+                    dragIcon: '<i class="glyphicon glyphicon-move"></i>',
+                    dragClass: 'text-primary',
+                    dragTitle: 'Move / Rearrange',
+                    dragSettings: {},
+                    indicatorNew: '<i class="glyphicon glyphicon-plus-sign text-warning"></i>',
+                    indicatorSuccess: '<i class="glyphicon glyphicon-ok-sign text-success"></i>',
+                    indicatorError: '<i class="glyphicon glyphicon-exclamation-sign text-danger"></i>',
+                    indicatorLoading: '<i class="glyphicon glyphicon-hourglass text-muted"></i>',
+                    indicatorPaused: '<i class="glyphicon glyphicon-pause text-primary"></i>',
+                    indicatorNewTitle: 'Not uploaded yet',
+                    indicatorSuccessTitle: 'Uploaded',
+                    indicatorErrorTitle: 'Upload Error',
+                    indicatorLoadingTitle: 'Uploading &hellip;',
+                    indicatorPausedTitle: 'Upload Paused'
+                }
+            };
+            $.each(self.defaults, function (key, setting) {
+                if (key === 'allowedPreviewTypes') {
+                    if (self.allowedPreviewTypes === undefined) {
+                        self.allowedPreviewTypes = setting;
+                    }
+                    return;
+                }
+                self[key] = $.extend(true, {}, setting, self[key]);
+            });
+            self._initPreviewTemplates();
+        },
+        _initPreviewTemplates: function () {
+            var self = this, tags = self.previewMarkupTags, tagBef, tagAft = tags.tagAfter;
+            $.each(self.previewContentTemplates, function (key, value) {
+                if ($h.isEmpty(self.previewTemplates[key])) {
+                    tagBef = tags.tagBefore2;
+                    if (key === 'generic' || key === 'image') {
+                        tagBef = tags.tagBefore1;
+                    }
+                    if (self._isPdfRendered() && key === 'pdf') {
+                        tagBef = tagBef.replace('kv-file-content', 'kv-file-content kv-pdf-rendered');
+                    }
+                    self.previewTemplates[key] = tagBef + value + tagAft;
+                }
+            });
+        },
+        _initPreviewCache: function () {
+            var self = this;
+            self.previewCache = {
+                data: {},
+                init: function () {
+                    var content = self.initialPreview;
+                    if (content.length > 0 && !$h.isArray(content)) {
+                        content = content.split(self.initialPreviewDelimiter);
+                    }
+                    self.previewCache.data = {
+                        content: content,
+                        config: self.initialPreviewConfig,
+                        tags: self.initialPreviewThumbTags
+                    };
+                },
+                count: function (skipNull) {
+                    if (!self.previewCache.data || !self.previewCache.data.content) {
+                        return 0;
+                    }
+                    if (skipNull) {
+                        var chk = self.previewCache.data.content.filter(function (n) {
+                            return n !== null;
+                        });
+                        return chk.length;
+                    }
+                    return self.previewCache.data.content.length;
+                },
+                get: function (i, isDisabled) {
+                    var ind = $h.INIT_FLAG + i, data = self.previewCache.data, config = data.config[i],
+                        content = data.content[i], out, $tmp, cat, ftr,
+                        fname, ftype, frameClass, asData = $h.ifSet('previewAsData', config, self.initialPreviewAsData),
+                        a = config ? {title: config.title || null, alt: config.alt || null} : {title: null, alt: null},
+                        parseTemplate = function (cat, dat, fname, ftype, ftr, ind, fclass, t) {
+                            var fc = ' file-preview-initial ' + $h.SORT_CSS + (fclass ? ' ' + fclass : ''),
+                                id = self.previewInitId + '-' + ind,
+                                fileId = config && config.fileId || id;
+                            /** @namespace config.zoomData */
+                            return self._generatePreviewTemplate(cat, dat, fname, ftype, id, fileId, false, null, null, fc,
+                                ftr, ind, t, a, config && config.zoomData || dat);
+                        };
+                    if (!content || !content.length) {
+                        return '';
+                    }
+                    isDisabled = isDisabled === undefined ? true : isDisabled;
+                    cat = $h.ifSet('type', config, self.initialPreviewFileType || 'generic');
+                    fname = $h.ifSet('filename', config, $h.ifSet('caption', config));
+                    ftype = $h.ifSet('filetype', config, cat);
+                    ftr = self.previewCache.footer(i, isDisabled, (config && config.size || null));
+                    frameClass = $h.ifSet('frameClass', config);
+                    if (asData) {
+                        out = parseTemplate(cat, content, fname, ftype, ftr, ind, frameClass);
+                    } else {
+                        out = parseTemplate('generic', content, fname, ftype, ftr, ind, frameClass, cat)
+                            .setTokens({'content': data.content[i]});
+                    }
+                    if (data.tags.length && data.tags[i]) {
+                        out = $h.replaceTags(out, data.tags[i]);
+                    }
+                    /** @namespace config.frameAttr */
+                    if (!$h.isEmpty(config) && !$h.isEmpty(config.frameAttr)) {
+                        $tmp = $h.createElement(out);
+                        $tmp.find('.file-preview-initial').attr(config.frameAttr);
+                        out = $tmp.html();
+                        $tmp.remove();
+                    }
+                    return out;
+                },
+                clean: function (data) {
+                    data.content = $h.cleanArray(data.content);
+                    data.config = $h.cleanArray(data.config);
+                    data.tags = $h.cleanArray(data.tags);
+                    self.previewCache.data = data;
+                },
+                add: function (content, config, tags, append) {
+                    var data = self.previewCache.data, index;
+                    if (!content || !content.length) {
+                        return 0;
+                    }
+                    index = content.length - 1;
+                    if (!$h.isArray(content)) {
+                        content = content.split(self.initialPreviewDelimiter);
+                    }
+                    if (append && data.content) {
+                        index = data.content.push(content[0]) - 1;
+                        data.config[index] = config;
+                        data.tags[index] = tags;
+                    } else {
+                        data.content = content;
+                        data.config = config;
+                        data.tags = tags;
+                    }
+                    self.previewCache.clean(data);
+                    return index;
+                },
+                set: function (content, config, tags, append) {
+                    var data = self.previewCache.data, i, chk;
+                    if (!content || !content.length) {
+                        return;
+                    }
+                    if (!$h.isArray(content)) {
+                        content = content.split(self.initialPreviewDelimiter);
+                    }
+                    chk = content.filter(function (n) {
+                        return n !== null;
+                    });
+                    if (!chk.length) {
+                        return;
+                    }
+                    if (data.content === undefined) {
+                        data.content = [];
+                    }
+                    if (data.config === undefined) {
+                        data.config = [];
+                    }
+                    if (data.tags === undefined) {
+                        data.tags = [];
+                    }
+                    if (append) {
+                        for (i = 0; i < content.length; i++) {
+                            if (content[i]) {
+                                data.content.push(content[i]);
+                            }
+                        }
+                        for (i = 0; i < config.length; i++) {
+                            if (config[i]) {
+                                data.config.push(config[i]);
+                            }
+                        }
+                        for (i = 0; i < tags.length; i++) {
+                            if (tags[i]) {
+                                data.tags.push(tags[i]);
+                            }
+                        }
+                    } else {
+                        data.content = content;
+                        data.config = config;
+                        data.tags = tags;
+                    }
+                    self.previewCache.clean(data);
+                },
+                unset: function (index) {
+                    var chk = self.previewCache.count(), rev = self.reversePreviewOrder;
+                    if (!chk) {
+                        return;
+                    }
+                    if (chk === 1) {
+                        self.previewCache.data.content = [];
+                        self.previewCache.data.config = [];
+                        self.previewCache.data.tags = [];
+                        self.initialPreview = [];
+                        self.initialPreviewConfig = [];
+                        self.initialPreviewThumbTags = [];
+                        return;
+                    }
+                    self.previewCache.data.content = $h.spliceArray(self.previewCache.data.content, index, rev);
+                    self.previewCache.data.config = $h.spliceArray(self.previewCache.data.config, index, rev);
+                    self.previewCache.data.tags = $h.spliceArray(self.previewCache.data.tags, index, rev);
+                    var data = $.extend(true, {}, self.previewCache.data);
+                    self.previewCache.clean(data);
+                },
+                out: function () {
+                    var html = '', caption, len = self.previewCache.count(), i, content;
+                    if (len === 0) {
+                        return {content: '', caption: ''};
+                    }
+                    for (i = 0; i < len; i++) {
+                        content = self.previewCache.get(i);
+                        html = self.reversePreviewOrder ? (content + html) : (html + content);
+                    }
+                    caption = self._getMsgSelected(len);
+                    return {content: html, caption: caption};
+                },
+                footer: function (i, isDisabled, size) {
+                    var data = self.previewCache.data || {};
+                    if ($h.isEmpty(data.content)) {
+                        return '';
+                    }
+                    if ($h.isEmpty(data.config) || $h.isEmpty(data.config[i])) {
+                        data.config[i] = {};
+                    }
+                    isDisabled = isDisabled === undefined ? true : isDisabled;
+                    var config = data.config[i], caption = $h.ifSet('caption', config), a,
+                        width = $h.ifSet('width', config, 'auto'), url = $h.ifSet('url', config, false),
+                        key = $h.ifSet('key', config, null), fileId = $h.ifSet('fileId', config, null),
+                        fs = self.fileActionSettings, initPreviewShowDel = self.initialPreviewShowDelete || false,
+                        downloadInitialUrl = !self.initialPreviewDownloadUrl ? '' :
+                            self.initialPreviewDownloadUrl + '?key=' + key + (fileId ? '&fileId=' + fileId : ''),
+                        dUrl = config.downloadUrl || downloadInitialUrl,
+                        dFil = config.filename || config.caption || '',
+                        initPreviewShowDwl = !!(dUrl),
+                        sDel = $h.ifSet('showRemove', config, initPreviewShowDel),
+                        sRot = $h.ifSet('showRotate', config, $h.ifSet('showRotate', fs, true)),
+                        sDwl = $h.ifSet('showDownload', config, $h.ifSet('showDownload', fs, initPreviewShowDwl)),
+                        sZm = $h.ifSet('showZoom', config, $h.ifSet('showZoom', fs, true)),
+                        sDrg = $h.ifSet('showDrag', config, $h.ifSet('showDrag', fs, true)),
+                        dis = (url === false) && isDisabled;
+                    sDwl = sDwl && config.downloadUrl !== false && !!dUrl;
+                    a = self._renderFileActions(config, false, sDwl, sDel, sRot, sZm, sDrg, dis, url, key, true, dUrl, dFil);
+                    return self._getLayoutTemplate('footer').setTokens({
+                        'progress': self._renderThumbProgress(),
+                        'actions': a,
+                        'caption': caption,
+                        'size': self._getSize(size),
+                        'width': width,
+                        'indicator': ''
+                    });
+                }
+            };
+            self.previewCache.init();
+        },
+        _isPdfRendered: function () {
+            var self = this, useLib = self.usePdfRenderer,
+                flag = typeof useLib === 'function' ? useLib() : !!useLib;
+            return flag && self.pdfRendererUrl;
+        },
+        _handler: function ($el, event, callback) {
+            var self = this, ns = self.namespace, ev = event.split(' ').join(ns + ' ') + ns;
+            if (!$el || !$el.length) {
+                return;
+            }
+            $el.off(ev).on(ev, callback);
+        },
+        _encodeURI: function (vUrl) {
+            var self = this;
+            return self.encodeUrl ? encodeURI(vUrl) : vUrl;
+        },
+        _log: function (msg, tokens) {
+            var self = this, id = self.$element.attr('id');
+            if (!self.showConsoleLogs) {
+                return;
+            }
+            if (id) {
+                msg = '"' + id + '": ' + msg;
+            }
+            msg = 'bootstrap-fileinput: ' + msg;
+            if (typeof tokens === 'object') {
+                msg = msg.setTokens(tokens);
+            }
+            if (window.console && typeof window.console.log !== 'undefined') {
+                window.console.log(msg);
+            } else {
+                window.alert(msg);
+            }
+        },
+        _validate: function () {
+            var self = this, status = self.$element.attr('type') === 'file';
+            if (!status) {
+                self._log($h.logMessages.badInputType);
+            }
+            return status;
+        },
+        _errorsExist: function () {
+            var self = this, $err, $errList = self.$errorContainer.find('li');
+            if ($errList.length) {
+                return true;
+            }
+            $err = $h.createElement(self.$errorContainer.html());
+            $err.find('.kv-error-close').remove();
+            $err.find('ul').remove();
+            return !!$.trim($err.text()).length;
+        },
+        _errorHandler: function (evt, caption) {
+            var self = this, err = evt.target.error, showError = function (msg) {
+                self._showError(msg.replace('{name}', caption));
+            };
+            /** @namespace err.NOT_FOUND_ERR */
+            /** @namespace err.SECURITY_ERR */
+            /** @namespace err.NOT_READABLE_ERR */
+            if (err.code === err.NOT_FOUND_ERR) {
+                showError(self.msgFileNotFound);
+            } else {
+                if (err.code === err.SECURITY_ERR) {
+                    showError(self.msgFileSecured);
+                } else {
+                    if (err.code === err.NOT_READABLE_ERR) {
+                        showError(self.msgFileNotReadable);
+                    } else {
+                        if (err.code === err.ABORT_ERR) {
+                            showError(self.msgFilePreviewAborted);
+                        } else {
+                            showError(self.msgFilePreviewError);
+                        }
+                    }
+                }
+            }
+        },
+        _addError: function (msg) {
+            var self = this, $error = self.$errorContainer;
+            if (msg && $error.length) {
+                $h.setHtml($error, self.errorCloseButton + msg);
+                self._handler($error.find('.kv-error-close'), 'click', function () {
+                    setTimeout(function () {
+                        if (self.showPreview && !self.getFrames().length) {
+                            self.clear();
+                        }
+                        $error.fadeOut('slow');
+                    }, self.processDelay);
+                });
+            }
+        },
+        _setValidationError: function (css) {
+            var self = this;
+            css = (css ? css + ' ' : '') + 'has-error';
+            self.$container.removeClass(css).addClass('has-error');
+            $h.addCss(self.$caption, 'is-invalid');
+        },
+        _resetErrors: function (fade) {
+            var self = this, $error = self.$errorContainer, history = self.resumableUploadOptions.retainErrorHistory;
+            if (self.isPersistentError || (self.enableResumableUpload && history && !self.clearInput)) {
+                return;
+            }
+            self.clearInput = false;
+            self.isError = false;
+            self.$container.removeClass('has-error');
+            self.$caption.removeClass('is-invalid is-valid file-processing');
+            $error.html('');
+            if (fade) {
+                $error.fadeOut('slow');
+            } else {
+                $error.hide();
+            }
+        },
+        _showFolderError: function (folders) {
+            var self = this, $error = self.$errorContainer, msg;
+            if (!folders) {
+                return;
+            }
+            if (!self.isAjaxUpload) {
+                self._clearFileInput();
+            }
+            msg = self.msgFoldersNotAllowed.replace('{n}', folders);
+            self._addError(msg);
+            self._setValidationError();
+            $error.fadeIn(self.fadeDelay);
+            self._raise('filefoldererror', [folders, msg]);
+        },
+        showUserError: function (msg, params, retainErrorHistory) {
+            var self = this, fileName;
+            if (!self.uploadInitiated) {
+                return;
+            }
+            if (!params || !params.fileId) {
+                if (!retainErrorHistory) {
+                    self.$errorContainer.html('');
+                }
+            } else {
+                if (!retainErrorHistory) {
+                    self.$errorContainer.find('[data-file-id="' + params.fileId + '"]').remove();
+                }
+                fileName = self.fileManager.getFileName(params.fileId);
+                if (fileName) {
+                    msg = '<b>' + fileName + ':</b> ' + msg;
+                }
+            }
+            self._showFileError(msg, params, 'fileusererror');
+        },
+        _showFileError: function (msg, params, event) {
+            var self = this, $error = self.$errorContainer, ev = event || 'fileuploaderror',
+                fId = params && params.fileId || '', e = params && params.id ?
+                    '<li data-thumb-id="' + params.id + '" data-file-id="' + fId + '">' + msg + '</li>' :
+                    '<li>' + msg + '</li>';
+
+            if ($error.find('ul').length === 0) {
+                self._addError('<ul>' + e + '</ul>');
+            } else {
+                $error.find('ul').append(e);
+            }
+            $error.fadeIn(self.fadeDelay);
+            self._raise(ev, [params, msg]);
+            self._setValidationError('file-input-new');
+            return true;
+        },
+        _showError: function (msg, params, event) {
+            var self = this, $error = self.$errorContainer, ev = event || 'fileerror';
+            params = params || {};
+            params.reader = self.reader;
+            self._addError(msg);
+            $error.fadeIn(self.fadeDelay);
+            self._raise(ev, [params, msg]);
+            if (!self.isAjaxUpload) {
+                self._clearFileInput();
+            }
+            self._setValidationError('file-input-new');
+            self.$btnUpload.attr('disabled', true);
+            return true;
+        },
+        _noFilesError: function (params) {
+            var self = this, label = self.minFileCount > 1 ? self.filePlural : self.fileSingle,
+                msg = self.msgFilesTooLess.replace('{n}', self.minFileCount).replace('{files}', label),
+                $error = self.$errorContainer;
+            msg = '<li>' + msg + '</li>';
+            if ($error.find('ul').length === 0) {
+                self._addError('<ul>' + msg + '</ul>');
+            } else {
+                $error.find('ul').append(msg);
+            }
+            self.isError = true;
+            self._updateFileDetails(0);
+            $error.fadeIn(self.fadeDelay);
+            self._raise('fileerror', [params, msg]);
+            self._clearFileInput();
+            self._setValidationError();
+        },
+        _parseError: function (operation, jqXHR, errorThrown, fileName) {
+            /** @namespace jqXHR.responseJSON */
+            var self = this, errMsg = $.trim(errorThrown + ''), textPre, errText, text;
+            errText = jqXHR.responseJSON && jqXHR.responseJSON.error ? jqXHR.responseJSON.error.toString() : '';
+            text = errText ? errText : jqXHR.responseText;
+            if (self.cancelling && self.msgUploadAborted) {
+                errMsg = self.msgUploadAborted;
+            }
+            if (self.showAjaxErrorDetails && text) {
+                if (errText) {
+                    errMsg = $.trim(errText + '');
+                } else {
+                    text = $.trim(text.replace(/\n\s*\n/g, '\n'));
+                    textPre = text.length ? '<pre>' + text + '</pre>' : '';
+                    errMsg += errMsg ? textPre : text;
+                }
+            }
+            if (!errMsg) {
+                errMsg = self.msgAjaxError.replace('{operation}', operation);
+            }
+            self.cancelling = false;
+            return fileName ? '<b>' + fileName + ': </b>' + errMsg : errMsg;
+        },
+        _parseFileType: function (type, name) {
+            var self = this, isValid, vType, cat, i, types = self.allowedPreviewTypes || [];
+            if (type === 'application/text-plain') {
+                return 'text';
+            }
+            for (i = 0; i < types.length; i++) {
+                cat = types[i];
+                isValid = self.fileTypeSettings[cat];
+                vType = isValid(type, name) ? cat : '';
+                if (!$h.isEmpty(vType)) {
+                    return vType;
+                }
+            }
+            return 'other';
+        },
+        _getPreviewIcon: function (fname) {
+            var self = this, ext, out = null;
+            if (fname && fname.indexOf('.') > -1) {
+                ext = fname.split('.').pop();
+                if (self.previewFileIconSettings) {
+                    out = self.previewFileIconSettings[ext] || self.previewFileIconSettings[ext.toLowerCase()] || null;
+                }
+                if (self.previewFileExtSettings) {
+                    $.each(self.previewFileExtSettings, function (key, func) {
+                        if (self.previewFileIconSettings[key] && func(ext)) {
+                            out = self.previewFileIconSettings[key];
+                            //noinspection UnnecessaryReturnStatementJS
+                            return;
+                        }
+                    });
+                }
+            }
+            return out || self.previewFileIcon;
+        },
+        _parseFilePreviewIcon: function (content, fname) {
+            var self = this, icn = self._getPreviewIcon(fname), out = content;
+            if (out.indexOf('{previewFileIcon}') > -1) {
+                out = out.setTokens({'previewFileIconClass': self.previewFileIconClass, 'previewFileIcon': icn});
+            }
+            return out;
+        },
+        _raise: function (event, params) {
+            var self = this, e = $.Event(event);
+            if (params !== undefined) {
+                self.$element.trigger(e, params);
+            } else {
+                self.$element.trigger(e);
+            }
+            var out = e.result, isAborted = out === false;
+            if (e.isDefaultPrevented() || isAborted) {
+                return false;
+            }
+            if (e.type === 'filebatchpreupload' && (out || isAborted)) {
+                self.ajaxAborted = out;
+                return false;
+            }
+            switch (event) {
+                // ignore these events
+                case 'filebatchuploadcomplete':
+                case 'filebatchuploadsuccess':
+                case 'fileuploaded':
+                case 'fileclear':
+                case 'filecleared':
+                case 'filereset':
+                case 'fileerror':
+                case 'filefoldererror':
+                case 'filecustomerror':
+                case 'filesuccessremove':
+                    break;
+                // receive data response via `filecustomerror` event`
+                default:
+                    if (!self.ajaxAborted) {
+                        self.ajaxAborted = out;
+                    }
+                    break;
+            }
+            return true;
+        },
+        _listenFullScreen: function (isFullScreen) {
+            var self = this, $modal = self.$modal, $btnFull, $btnBord;
+            if (!$modal || !$modal.length) {
+                return;
+            }
+            $btnFull = $modal && $modal.find('.btn-kv-fullscreen');
+            $btnBord = $modal && $modal.find('.btn-kv-borderless');
+            if (!$btnFull.length || !$btnBord.length) {
+                return;
+            }
+            $btnFull.removeClass('active').attr('aria-pressed', 'false');
+            $btnBord.removeClass('active').attr('aria-pressed', 'false');
+            if (isFullScreen) {
+                $btnFull.addClass('active').attr('aria-pressed', 'true');
+            } else {
+                $btnBord.addClass('active').attr('aria-pressed', 'true');
+            }
+            if ($modal.hasClass('file-zoom-fullscreen')) {
+                self._maximizeZoomDialog();
+            } else {
+                if (isFullScreen) {
+                    self._maximizeZoomDialog();
+                } else {
+                    $btnBord.removeClass('active').attr('aria-pressed', 'false');
+                }
+            }
+        },
+        _listen: function () {
+            var self = this, $el = self.$element, $form = self.$form, $cont = self.$container, fullScreenEv;
+            self._handler($el, 'click', function (e) {
+                self._initFileSelected();
+                if ($el.hasClass('file-no-browse')) {
+                    if ($el.data('zoneClicked')) {
+                        $el.data('zoneClicked', false);
+                    } else {
+                        e.preventDefault();
+                    }
+                }
+            });
+            self._handler($el, 'change', $.proxy(self._change, self));
+            self._handler(self.$caption, 'paste', $.proxy(self.paste, self));
+            if (self.showBrowse) {
+                self._handler(self.$btnFile, 'click', $.proxy(self._browse, self));
+                self._handler(self.$btnFile, 'keypress', function (e) {
+                    var keycode = e.keyCode || e.which;
+                    if (keycode === 13) {
+                        $el.trigger('click');
+                        self._browse(e);
+                    }
+                });
+            }
+            self._handler($cont.find('.fileinput-remove:not([disabled])'), 'click', $.proxy(self.clear, self));
+            self._handler($cont.find('.fileinput-cancel'), 'click', $.proxy(self.cancel, self));
+            self._handler($cont.find('.fileinput-pause'), 'click', $.proxy(self.pause, self));
+            self._initDragDrop();
+            self._handler($form, 'reset', $.proxy(self.clear, self));
+            if (!self.isAjaxUpload) {
+                self._handler($form, 'submit', $.proxy(self._submitForm, self));
+            }
+            self._handler(self.$container.find('.fileinput-upload'), 'click', $.proxy(self._uploadClick, self));
+            self._handler($(window), 'resize', function () {
+                self._listenFullScreen(screen.width === window.innerWidth && screen.height === window.innerHeight);
+            });
+            fullScreenEv = 'webkitfullscreenchange mozfullscreenchange fullscreenchange MSFullscreenChange';
+            self._handler($(document), fullScreenEv, function () {
+                self._listenFullScreen($h.checkFullScreen());
+            });
+            self.$caption.on('focus', function () {
+                self.$captionContainer.focus();
+            });
+            self._autoFitContent();
+            self._initClickable();
+            self._refreshPreview();
+        },
+        _autoFitContent: function () {
+            var width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth,
+                self = this, config = width < 400 ? (self.previewSettingsSmall || self.defaults.previewSettingsSmall) :
+                    (self.previewSettings || self.defaults.previewSettings), sel;
+            $.each(config, function (cat, settings) {
+                sel = '.file-preview-frame .file-preview-' + cat;
+                self.$preview.find(sel + '.kv-preview-data,' + sel + ' .kv-preview-data').css(settings);
+            });
+        },
+        _scanDroppedItems: function (item, files, path) {
+            path = path || '';
+            var self = this, i, dirReader, readDir, errorHandler = function (e) {
+                self._log($h.logMessages.badDroppedFiles);
+                self._log(e);
+            };
+            if (item.isFile) {
+                item.file(function (file) {
+                    if (path) {
+                        file.newPath = path + file.name;
+                    }
+                    files.push(file);
+                }, errorHandler);
+            } else {
+                if (item.isDirectory) {
+                    dirReader = item.createReader();
+                    readDir = function () {
+                        dirReader.readEntries(function (entries) {
+                            if (entries && entries.length > 0) {
+                                for (i = 0; i < entries.length; i++) {
+                                    self._scanDroppedItems(entries[i], files, path + item.name + '/');
+                                }
+                                // recursively call readDir() again, since browser can only handle first 100 entries.
+                                readDir();
+                            }
+                            return null;
+                        }, errorHandler);
+                    };
+                    readDir();
+                }
+            }
+
+        },
+        _initDragDrop: function () {
+            var self = this, $zone = self.$dropZone;
+            if (self.dropZoneEnabled && self.showPreview) {
+                self._handler($zone, 'dragenter dragover', $.proxy(self._zoneDragEnter, self));
+                self._handler($zone, 'dragleave', $.proxy(self._zoneDragLeave, self));
+                self._handler($zone, 'drop', $.proxy(self._zoneDrop, self));
+                self._handler($(document), 'dragenter dragover drop', self._zoneDragDropInit);
+            }
+        },
+        _zoneDragDropInit: function (e) {
+            e.stopPropagation();
+            e.preventDefault();
+        },
+        _zoneDragEnter: function (e) {
+            var self = this, dt = e.originalEvent.dataTransfer, hasFiles = $.inArray('Files', dt.types) > -1;
+            self._zoneDragDropInit(e);
+            if (self.isDisabled || !hasFiles) {
+                dt.effectAllowed = 'none';
+                dt.dropEffect = 'none';
+                return;
+            }
+            dt.dropEffect = 'copy';
+            if (self._raise('fileDragEnter', {'sourceEvent': e, 'files': dt.types.Files})) {
+                $h.addCss(self.$dropZone, 'file-highlighted');
+            }
+        },
+        _zoneDragLeave: function (e) {
+            var self = this;
+            self._zoneDragDropInit(e);
+            if (self.isDisabled) {
+                return;
+            }
+            if (self._raise('fileDragLeave', {'sourceEvent': e})) {
+                self.$dropZone.removeClass('file-highlighted');
+            }
+
+        },
+        _dropFiles: function (e, files) {
+            var self = this, $el = self.$element;
+            if (!self.isAjaxUpload) {
+                self.changeTriggered = true;
+                $el.get(0).files = files;
+                setTimeout(function () {
+                    self.changeTriggered = false;
+                    $el.trigger('change' + self.namespace);
+                }, self.processDelay);
+            } else {
+                self._change(e, files);
+            }
+            self.$dropZone.removeClass('file-highlighted');
+        },
+        _zoneDrop: function (e) {
+            /** @namespace e.originalEvent.dataTransfer */
+            var self = this, i, $el = self.$element, dt = e.originalEvent.dataTransfer,
+                files = dt.files, items = dt.items, folders = $h.getDragDropFolders(items);
+            e.preventDefault();
+            if (self.isDisabled || $h.isEmpty(files)) {
+                return;
+            }
+            if (!self._raise('fileDragDrop', {'sourceEvent': e, 'files': files})) {
+                return;
+            }
+            if (folders > 0) {
+                if (!self.isAjaxUpload) {
+                    self._showFolderError(folders);
+                    return;
+                }
+                files = [];
+                for (i = 0; i < items.length; i++) {
+                    var item = items[i].webkitGetAsEntry();
+                    if (item) {
+                        self._scanDroppedItems(item, files);
+                    }
+                }
+                setTimeout(function () {
+                    self._dropFiles(e, files);
+                }, 500);
+            } else {
+                self._dropFiles(e, files);
+            }
+        },
+        _uploadClick: function (e) {
+            var self = this, $btn = self.$container.find('.fileinput-upload'), $form,
+                isEnabled = !$btn.hasClass('disabled') && $h.isEmpty($btn.attr('disabled'));
+            if (e && e.isDefaultPrevented()) {
+                return;
+            }
+            if (!self.isAjaxUpload) {
+                if (isEnabled && $btn.attr('type') !== 'submit') {
+                    e.preventDefault();
+                    $form = $btn.closest('form');
+                    // downgrade to normal form submit if possible
+                    if ($form.length) {
+                        $form.trigger('submit');
+                    }
+                }
+                return;
+            }
+            e.preventDefault();
+            if (isEnabled) {
+                self.upload();
+            }
+        },
+        _submitForm: function () {
+            var self = this;
+            return self._isFileSelectionValid() && !self._abort({});
+        },
+        _clearPreview: function () {
+            var self = this,
+                $thumbs = self.showUploadedThumbs ? self.getFrames(':not(.file-preview-success)') : self.getFrames();
+            $thumbs.each(function () {
+                var $thumb = $(this);
+                $thumb.remove();
+            });
+            if (!self.getFrames().length || !self.showPreview) {
+                self._resetUpload();
+            }
+            self._validateDefaultPreview();
+        },
+        _initSortable: function () {
+            var self = this, $el = self.$preview, settings, selector = '.' + $h.SORT_CSS, $cont, $body = $('body'),
+                $html = $('html'), rev = self.reversePreviewOrder, Sortable = window.Sortable, beginGrab, endGrab;
+            if (!Sortable || $el.find(selector).length === 0) {
+                return;
+            }
+            $cont = $body.length ? $body : ($html.length ? $html : self.$container);
+            beginGrab = function () {
+                $cont.addClass('file-grabbing');
+            };
+            endGrab = function () {
+                $cont.removeClass('file-grabbing');
+            };
+            settings = {
+                handle: '.drag-handle-init',
+                dataIdAttr: 'data-fileid',
+                animation: 600,
+                draggable: selector,
+                scroll: false,
+                forceFallback: true,
+                onChoose: beginGrab,
+                onStart: beginGrab,
+                onUnchoose: endGrab,
+                onEnd: endGrab,
+                onSort: function (e) {
+                    var oldIndex = e.oldIndex, newIndex = e.newIndex, i = 0, len = self.initialPreviewConfig.length,
+                        exceedsLast = len > 0 && newIndex >= len, $item = $(e.item), $first;
+                    if (exceedsLast) {
+                        newIndex = len - 1;
+                    }
+                    self.initialPreview = $h.moveArray(self.initialPreview, oldIndex, newIndex, rev);
+                    self.initialPreviewConfig = $h.moveArray(self.initialPreviewConfig, oldIndex, newIndex, rev);
+                    self.previewCache.init();
+                    self.getFrames('.file-preview-initial').each(function () {
+                        $(this).attr('data-fileindex', $h.INIT_FLAG + i);
+                        i++;
+                    });
+                    if (exceedsLast) {
+                        $first = self.getFrames(':not(.file-preview-initial):first');
+                        if ($first.length) {
+                            $item.slideUp(function () {
+                                $item.insertBefore($first).slideDown();
+                            });
+                        }
+                    }
+                    self._raise('filesorted', {
+                        previewId: $item.attr('id'),
+                        'oldIndex': oldIndex,
+                        'newIndex': newIndex,
+                        stack: self.initialPreviewConfig
+                    });
+                },
+            };
+            $.extend(true, settings, self.fileActionSettings.dragSettings);
+            if (self.sortable) {
+                self.sortable.destroy();
+            }
+            self.sortable = Sortable.create($el[0], settings);
+        },
+        _setPreviewContent: function (content) {
+            var self = this;
+            $h.setHtml(self.$preview, content);
+            self._autoFitContent();
+        },
+        _initPreviewImageOrientations: function () {
+            var self = this, i = 0, canOrientImage = self.canOrientImage;
+            if (!self.autoOrientImageInitial && !canOrientImage) {
+                return;
+            }
+            self.getFrames('.file-preview-initial').each(function () {
+                var $thumb = $(this), $img, $zoomImg, id, config = self.initialPreviewConfig[i];
+                /** @namespace config.exif */
+                if (config && config.exif && config.exif.Orientation) {
+                    id = $thumb.attr('id');
+                    $img = $thumb.find('>.kv-file-content img');
+                    $zoomImg = self._getZoom(id, ' >.kv-file-content img');
+                    if (canOrientImage) {
+                        $img.css('image-orientation', (self.autoOrientImageInitial ? 'from-image' : 'none'));
+                    } else {
+                        self.setImageOrientation($img, $zoomImg, config.exif.Orientation, $thumb);
+                    }
+                }
+                i++;
+            });
+        },
+        _initPreview: function (isInit) {
+            var self = this, cap = self.initialCaption || '', out;
+            if (!self.previewCache.count(true)) {
+                self._clearPreview();
+                if (isInit) {
+                    self._setCaption(cap);
+                } else {
+                    self._initCaption();
+                }
+                return;
+            }
+            out = self.previewCache.out();
+            cap = isInit && self.initialCaption ? self.initialCaption : out.caption;
+            self._setPreviewContent(out.content);
+            self._setInitThumbAttr();
+            self._setCaption(cap);
+            self._initSortable();
+            if (!$h.isEmpty(out.content)) {
+                self.$container.removeClass('file-input-new');
+            }
+            self._initPreviewImageOrientations();
+        },
+        _getZoomButton: function (type) {
+            var self = this, label = self.previewZoomButtonIcons[type], css = self.previewZoomButtonClasses[type],
+                title = ' title="' + (self.previewZoomButtonTitles[type] || '') + '" ', tag = $h.isBs(5) ? 'bs-' : '',
+                params = title + (type === 'close' ? ' data-' + tag + 'dismiss="modal" aria-hidden="true"' : '');
+            if (type === 'fullscreen' || type === 'borderless' || type === 'toggleheader') {
+                params += ' data-toggle="button" aria-pressed="false" autocomplete="off"';
+            }
+            return '<button type="button" class="' + css + ' btn-kv-' + type + '"' + params + '>' + label + '</button>';
+        },
+        _getModalContent: function () {
+            var self = this;
+            return self._getLayoutTemplate('modal').setTokens({
+                'rtl': self.rtl ? ' kv-rtl' : '',
+                'zoomFrameClass': self.frameClass,
+                'prev': self._getZoomButton('prev'),
+                'next': self._getZoomButton('next'),
+                'rotate': self._getZoomButton('rotate'),
+                'toggleheader': self._getZoomButton('toggleheader'),
+                'fullscreen': self._getZoomButton('fullscreen'),
+                'borderless': self._getZoomButton('borderless'),
+                'close': self._getZoomButton('close')
+            });
+        },
+        _listenModalEvent: function (event) {
+            var self = this, $modal = self.$modal, getParams = function (e) {
+                return {
+                    sourceEvent: e,
+                    previewId: $modal.data('previewId'),
+                    modal: $modal
+                };
+            };
+            $modal.on(event + '.bs.modal', function (e) {
+                if (e.namespace !== 'bs.modal') {
+                    return;
+                }
+                var $btnFull = $modal.find('.btn-fullscreen'), $btnBord = $modal.find('.btn-borderless');
+                if ($modal.data('fileinputPluginId') === self.$element.attr('id')) {
+                    self._raise('filezoom' + event, getParams(e));
+                }
+                if (event === 'shown') {
+                    self._handleRotation($modal, $modal.find('.file-zoom-detail'), $modal.data('angle'));
+                    $btnBord.removeClass('active').attr('aria-pressed', 'false');
+                    $btnFull.removeClass('active').attr('aria-pressed', 'false');
+                    if ($modal.hasClass('file-zoom-fullscreen')) {
+                        self._maximizeZoomDialog();
+                        if ($h.checkFullScreen()) {
+                            $btnFull.addClass('active').attr('aria-pressed', 'true');
+                        } else {
+                            $btnBord.addClass('active').attr('aria-pressed', 'true');
+                        }
+                    }
+                }
+            });
+        },
+        _initZoom: function () {
+            var self = this, $dialog, modalMain = self._getLayoutTemplate('modalMain'), modalId = '#' + $h.MODAL_ID;
+            modalMain = self._setTabIndex('modal', modalMain);
+            if (!self.showPreview) {
+                return;
+            }
+            self.$modal = $(modalId);
+            if (!self.$modal || !self.$modal.length) {
+                $dialog = $h.createElement($h.cspBuffer.stash(modalMain)).insertAfter(self.$container);
+                self.$modal = $(modalId).insertBefore($dialog);
+                $h.cspBuffer.apply(self.$modal);
+                $dialog.remove();
+            }
+            $h.initModal(self.$modal);
+            self.$modal.html($h.cspBuffer.stash(self._getModalContent()));
+            $h.cspBuffer.apply(self.$modal);
+            $.each($h.MODAL_EVENTS, function (key, event) {
+                self._listenModalEvent(event);
+            });
+        },
+        _initZoomButtons: function () {
+            var self = this, $modal = self.$modal, previewId = $modal.data('previewId') || '', $first, $last,
+                thumbs = self.getFrames().toArray(), len = thumbs.length, $prev = $modal.find('.btn-kv-prev'),
+                $next = $modal.find('.btn-kv-next'), $rotate = $modal.find('.btn-kv-rotate');
+            if (thumbs.length < 2) {
+                $prev.hide();
+                $next.hide();
+                return;
+            } else {
+                $prev.show();
+                $next.show();
+            }
+            if (!len) {
+                return;
+            }
+            $first = $(thumbs[0]);
+            $last = $(thumbs[len - 1]);
+            $prev.removeAttr('disabled');
+            $next.removeAttr('disabled');
+            if (self.reversePreviewOrder) {
+                [$prev, $next] = [$next, $prev]; // swap
+            }
+            if ($first.length && $first.attr('id') === previewId) {
+                $prev.attr('disabled', true);
+            }
+            if ($last.length && $last.attr('id') === previewId) {
+                $next.attr('disabled', true);
+            }
+        },
+        _maximizeZoomDialog: function () {
+            var self = this, $modal = self.$modal, $head = $modal.find('.modal-header:visible'),
+                $foot = $modal.find('.modal-footer:visible'), $body = $modal.find('.kv-zoom-body'),
+                h = $(window).height(), diff = 0;
+            $modal.addClass('file-zoom-fullscreen');
+            if ($head && $head.length) {
+                h -= $head.outerHeight(true);
+            }
+            if ($foot && $foot.length) {
+                h -= $foot.outerHeight(true);
+            }
+            if ($body && $body.length) {
+                diff = $body.outerHeight(true) - $body.height();
+                h -= diff;
+            }
+            $modal.find('.kv-zoom-body').height(h);
+        },
+        _resizeZoomDialog: function (fullScreen) {
+            var self = this, $modal = self.$modal, $btnFull = $modal.find('.btn-kv-fullscreen'),
+                $btnBord = $modal.find('.btn-kv-borderless');
+            if ($modal.hasClass('file-zoom-fullscreen')) {
+                $h.toggleFullScreen(false);
+                if (!fullScreen) {
+                    if (!$btnFull.hasClass('active')) {
+                        $modal.removeClass('file-zoom-fullscreen');
+                        self.$modal.find('.kv-zoom-body').css('height', self.zoomModalHeight);
+                    } else {
+                        $btnFull.removeClass('active').attr('aria-pressed', 'false');
+                    }
+                } else {
+                    if (!$btnFull.hasClass('active')) {
+                        $modal.removeClass('file-zoom-fullscreen');
+                        self._resizeZoomDialog(true);
+                        if ($btnBord.hasClass('active')) {
+                            $btnBord.removeClass('active').attr('aria-pressed', 'false');
+                        }
+                    }
+                }
+            } else {
+                if (!fullScreen) {
+                    self._maximizeZoomDialog();
+                    return;
+                }
+                $h.toggleFullScreen(true);
+            }
+            $modal.focus();
+        },
+        _setZoomContent: function ($frame, navigate) {
+            var self = this, $content, tmplt, body, title, $body, $dataEl, config, previewId = $frame.attr('id'),
+                $zoomPreview = self._getZoom(previewId), $modal = self.$modal, $tmp, desc, $desc,
+                $btnFull = $modal.find('.btn-kv-fullscreen'), $btnBord = $modal.find('.btn-kv-borderless'), cap, size,
+                $btnTogh = $modal.find('.btn-kv-toggleheader'), dir = navigate === 'prev' ? 'Left' : 'Right',
+                slideIn = 'slideIn' + dir, slideOut = 'slideOut' + dir, parsed, zoomData = $frame.data('zoom');
+            if (zoomData) {
+                zoomData = decodeURIComponent(zoomData);
+                parsed = $zoomPreview.html().replace(self.zoomPlaceholder, '').setTokens({zoomData: zoomData});
+                $zoomPreview.html(parsed);
+                $frame.data('zoom', '');
+                $zoomPreview.attr('data-zoom', zoomData);
+            }
+            tmplt = $zoomPreview.attr('data-template') || 'generic';
+            $content = $zoomPreview.find('.kv-file-content');
+            body = $content.length ? $content.html() : '';
+            cap = $frame.data('caption') || self.msgZoomModalHeading;
+            size = $frame.data('size') || '';
+            desc = $frame.data('description') || '';
+            $modal.find('.kv-zoom-caption').attr('title', cap).html(cap);
+            $modal.find('.kv-zoom-size').html(size);
+            $desc = $modal.find('.kv-zoom-description').hide();
+            if (desc) {
+                if (self.showDescriptionClose) {
+                    desc = self._getLayoutTemplate('descriptionClose').setTokens({
+                        closeIcon: self.previewZoomButtonIcons.close
+                    }) + '</button>' + desc;
+                }
+                $desc.show().html(desc);
+                if (self.showDescriptionClose) {
+                    self._handler($modal.find('.kv-desc-hide'), 'click', function () {
+                        $(this).parent().fadeOut('fast', function () {
+                            $modal.focus();
+                        });
+                    });
+                }
+            }
+            $body = $modal.find('.kv-zoom-body');
+            $modal.removeClass('kv-single-content');
+            if (navigate) {
+                $tmp = $body.addClass('file-thumb-loading').clone().insertAfter($body);
+                $h.setHtml($body, body).hide();
+                $tmp.fadeOut('fast', function () {
+                    $body.fadeIn('fast', function () {
+                        $body.removeClass('file-thumb-loading');
+                    });
+                    $tmp.remove();
+                });
+            } else {
+                $h.setHtml($body, body);
+            }
+            config = self.previewZoomSettings[tmplt];
+            if (config) {
+                $dataEl = $body.find('.kv-preview-data');
+                $h.addCss($dataEl, 'file-zoom-detail');
+                $.each(config, function (key, value) {
+                    $dataEl.css(key, value);
+                    if (($dataEl.attr('width') && key === 'width') || ($dataEl.attr('height') && key === 'height')) {
+                        $dataEl.removeAttr(key);
+                    }
+                });
+            }
+            $modal.data('previewId', previewId);
+            self._handler($modal.find('.btn-kv-prev'), 'click', function () {
+                self._zoomSlideShow('prev', previewId);
+            });
+            self._handler($modal.find('.btn-kv-next'), 'click', function () {
+                self._zoomSlideShow('next', previewId);
+            });
+            self._handler($btnFull, 'click', function () {
+                self._resizeZoomDialog(true);
+            });
+            self._handler($btnBord, 'click', function () {
+                self._resizeZoomDialog(false);
+            });
+            self._handler($btnTogh, 'click', function () {
+                var $header = $modal.find('.modal-header'), $floatBar = $modal.find('.floating-buttons'),
+                    ht, $actions = $header.find('.kv-zoom-actions'), resize = function (height) {
+                        var $body = self.$modal.find('.kv-zoom-body'), h = self.zoomModalHeight;
+                        if ($modal.hasClass('file-zoom-fullscreen')) {
+                            h = $body.outerHeight(true);
+                            if (!height) {
+                                h = h - $header.outerHeight(true);
+                            }
+                        }
+                        $body.css('height', height ? h + height : h);
+                    };
+                if ($header.is(':visible')) {
+                    ht = $header.outerHeight(true);
+                    $header.slideUp('slow', function () {
+                        $actions.find('.btn').appendTo($floatBar);
+                        resize(ht);
+                    });
+                } else {
+                    $floatBar.find('.btn').appendTo($actions);
+                    $header.slideDown('slow', function () {
+                        resize();
+                    });
+                }
+                $modal.focus();
+            });
+            self._handler($modal, 'keydown', function (e) {
+                var key = e.which || e.keyCode, delay = self.processDelay + 1, $prev = $(this).find('.btn-kv-prev'),
+                    $next = $(this).find('.btn-kv-next'), vId = $(this).data('previewId'), vPrevKey, vNextKey;
+                [vPrevKey, vNextKey] = self.rtl ? [39, 37] : [37, 39];
+                $.each({prev: [$prev, vPrevKey], next: [$next, vNextKey]}, function (direction, config) {
+                    var $btn = config[0], vKey = config[1];
+                    if (key === vKey && $btn.length) {
+                        $modal.focus();
+                        if (!$btn.attr('disabled')) {
+                            $btn.blur();
+                            setTimeout(function () {
+                                $btn.focus();
+                                self._zoomSlideShow(direction, vId);
+                                setTimeout(function () {
+                                    if ($btn.attr('disabled')) {
+                                        $modal.focus();
+                                    }
+                                }, delay);
+                            }, delay);
+                        }
+                    }
+                });
+            });
+        },
+        _showModal: function ($frame) {
+            var self = this, $modal = self.$modal, $content, css, angle;
+            if (!$frame || !$frame.length) {
+                return;
+            }
+            $h.initModal($modal);
+            $h.setHtml($modal, self._getModalContent());
+            self._setZoomContent($frame);
+            $modal.removeClass('rotatable');
+            $modal.data({backdrop: false, fileinputPluginId: self.$element.attr('id')});
+            $modal.find('.kv-zoom-body').css('height', self.zoomModalHeight);
+            $content = $frame.find('.kv-file-content > :first-child');
+            if ($content.length) {
+                css = $content.css('transform');
+                if (css) {
+                    $modal.find('.file-zoom-detail').css('transform', css);
+                }
+            }
+            if ($frame.hasClass('rotatable')) {
+                $modal.addClass('rotatable');
+            }
+            if ($frame.data('angle')) {
+                $modal.data('angle', $frame.data('angle'));
+            }
+            angle = ($frame.data('angle') || 0);
+            $modal.modal('show');
+            self._initZoomButtons();
+            self._initRotateZoom($frame, $content);
+        },
+        _zoomPreview: function ($btn) {
+            var self = this, $frame;
+            if (!$btn.length) {
+                throw 'Cannot zoom to detailed preview!';
+            }
+            $frame = $btn.closest($h.FRAMES);
+            self._showModal($frame);
+        },
+        _zoomSlideShow: function (dir, previewId) {
+            var self = this, $modal = self.$modal, $btn = $modal.find('.kv-zoom-actions .btn-kv-' + dir), $targFrame, i,
+                $thumb, thumbsData = self.getFrames().toArray(), thumbs = [], len = thumbsData.length, out, angle,
+                $content;
+            if (self.reversePreviewOrder) {
+                dir = dir === 'prev' ? 'next' : 'prev';
+            }
+            if ($btn.attr('disabled')) {
+                return;
+            }
+            for (i = 0; i < len; i++) {
+                $thumb = $(thumbsData[i]);
+                if ($thumb && $thumb.length && $thumb.find('.kv-file-zoom:visible').length) {
+                    thumbs.push(thumbsData[i]);
+                }
+            }
+            len = thumbs.length;
+            for (i = 0; i < len; i++) {
+                if ($(thumbs[i]).attr('id') === previewId) {
+                    out = dir === 'prev' ? i - 1 : i + 1;
+                    break;
+                }
+            }
+            if (out < 0 || out >= len || !thumbs[out]) {
+                return;
+            }
+            $targFrame = $(thumbs[out]);
+            if ($targFrame.length) {
+                self._setZoomContent($targFrame, dir);
+            }
+            self._initZoomButtons();
+            if ($targFrame.length && $targFrame.hasClass('rotatable')) {
+                angle = $targFrame.data('angle') || 0;
+                $modal.addClass('rotatable').data('angle', angle);
+                $content = $targFrame.find('.kv-file-content > :first-child');
+                self._initRotateZoom($targFrame, $content);
+            } else {
+                $modal.removeClass('rotatable').removeData('angle');
+            }
+            self._raise('filezoom' + dir, {'previewId': previewId, modal: self.$modal});
+        },
+        _initZoomButton: function () {
+            var self = this;
+            self.$preview.find('.kv-file-zoom').each(function () {
+                var $el = $(this);
+                self._handler($el, 'click', function () {
+                    self._zoomPreview($el);
+                });
+            });
+        },
+        _inputFileCount: function () {
+            return this.$element[0].files.length;
+        },
+        _refreshPreview: function () {
+            var self = this, files;
+            if ((!self._inputFileCount() && !self.isAjaxUpload) || !self.showPreview || !self.isPreviewable) {
+                return;
+            }
+            if (self.isAjaxUpload) {
+                if (self.fileManager.count() > 0) {
+                    files = $.extend(true, [], self.getFileList());
+                    self.fileManager.clear();
+                    self._clearFileInput();
+                } else {
+                    files = self.$element[0].files;
+                }
+            } else {
+                files = self.$element[0].files;
+            }
+            if (files && files.length) {
+                self.readFiles(files);
+            }
+        },
+        _clearObjects: function ($el) {
+            $el.find('video audio').each(function () {
+                this.pause();
+                $(this).remove();
+            });
+            $el.find('img object div').each(function () {
+                $(this).remove();
+            });
+        },
+        _clearFileInput: function () {
+            var self = this, $el = self.$element, $srcFrm, $tmpFrm, $tmpEl;
+            if (!self._inputFileCount()) {
+                return;
+            }
+            $srcFrm = $el.closest('form');
+            $tmpFrm = $(document.createElement('form'));
+            $tmpEl = $(document.createElement('div'));
+            $el.before($tmpEl);
+            if ($srcFrm.length) {
+                $srcFrm.after($tmpFrm);
+            } else {
+                $tmpEl.after($tmpFrm);
+            }
+            $tmpFrm.append($el).trigger('reset');
+            $tmpEl.before($el).remove();
+            $tmpFrm.remove();
+        },
+        _resetUpload: function () {
+            var self = this;
+            self.uploadInitiated = false;
+            self.uploadStartTime = $h.now();
+            self.uploadCache = [];
+            self.$btnUpload.removeAttr('disabled');
+            self._setProgress(0);
+            self._hideProgress();
+            self._resetErrors(false);
+            self._initAjax();
+            self.fileManager.clearImages();
+            self._resetCanvas();
+            if (self.overwriteInitial) {
+                self.initialPreview = [];
+                self.initialPreviewConfig = [];
+                self.initialPreviewThumbTags = [];
+                self.previewCache.data = {
+                    content: [],
+                    config: [],
+                    tags: []
+                };
+            }
+        },
+        _resetCanvas: function () {
+            var self = this;
+            if (self.imageCanvas && self.imageCanvasContext) {
+                self.imageCanvasContext.clearRect(0, 0, self.imageCanvas.width, self.imageCanvas.height);
+            }
+        },
+        _hasInitialPreview: function () {
+            var self = this;
+            return !self.overwriteInitial && self.previewCache.count(true);
+        },
+        _resetPreview: function () {
+            var self = this, out, cap, $div, hasSuc = self.showUploadedThumbs, hasErr = !self.removeFromPreviewOnError,
+                includeProcessed = (hasSuc || hasErr) && self.isDuplicateError;
+            if (self.previewCache.count(true)) {
+                out = self.previewCache.out();
+                if (includeProcessed) {
+                    $div = $h.createElement('').insertAfter(self.$container);
+                    self.getFrames().each(function () {
+                        var $thumb = $(this);
+                        if ((hasSuc && $thumb.hasClass('file-preview-success')) ||
+                            (hasErr && $thumb.hasClass('file-preview-error'))) {
+                            $div.append($thumb);
+                        }
+                    });
+                }
+                self._setPreviewContent(out.content);
+                self._setInitThumbAttr();
+                cap = self.initialCaption ? self.initialCaption : out.caption;
+                self._setCaption(cap);
+                if (includeProcessed) {
+                    $div.contents().appendTo(self.$preview);
+                    $div.remove();
+                }
+            } else {
+                self._clearPreview();
+                self._initCaption();
+            }
+            if (self.showPreview) {
+                self._initZoom();
+                self._initSortable();
+            }
+            self.isDuplicateError = false;
+        },
+        _clearDefaultPreview: function () {
+            var self = this;
+            self.$preview.find('.file-default-preview').remove();
+        },
+        _validateDefaultPreview: function () {
+            var self = this;
+            if (!self.showPreview || $h.isEmpty(self.defaultPreviewContent)) {
+                return;
+            }
+            self._setPreviewContent('<div class="file-default-preview">' + self.defaultPreviewContent + '</div>');
+            self.$container.removeClass('file-input-new');
+            self._initClickable();
+        },
+        _resetPreviewThumbs: function (isAjax) {
+            var self = this, out;
+            if (isAjax) {
+                self._clearPreview();
+                self.clearFileStack();
+                return;
+            }
+            if (self._hasInitialPreview()) {
+                out = self.previewCache.out();
+                self._setPreviewContent(out.content);
+                self._setInitThumbAttr();
+                self._setCaption(out.caption);
+                self._initPreviewActions();
+            } else {
+                self._clearPreview();
+            }
+        },
+        _getLayoutTemplate: function (t) {
+            var self = this, template = self.layoutTemplates[t];
+            if ($h.isEmpty(self.customLayoutTags)) {
+                return template;
+            }
+            return $h.replaceTags(template, self.customLayoutTags);
+        },
+        _getPreviewTemplate: function (t) {
+            var self = this, templates = self.previewTemplates, template = templates[t] || templates.other;
+            if ($h.isEmpty(self.customPreviewTags)) {
+                return template;
+            }
+            return $h.replaceTags(template, self.customPreviewTags);
+        },
+        _getOutData: function (formdata, jqXHR, responseData, filesData) {
+            var self = this;
+            jqXHR = jqXHR || {};
+            responseData = responseData || {};
+            filesData = filesData || self.fileManager.list();
+            return {
+                formdata: formdata,
+                files: filesData,
+                filenames: self.filenames,
+                filescount: self.getFilesCount(),
+                extra: self._getExtraData(),
+                response: responseData,
+                reader: self.reader,
+                jqXHR: jqXHR
+            };
+        },
+        _getMsgSelected: function (n, processing) {
+            var self = this, strFiles = n === 1 ? self.fileSingle : self.filePlural;
+            return n > 0 ? self.msgSelected.replace('{n}', n).replace('{files}', strFiles) :
+                (processing ? self.msgProcessing : self.msgNoFilesSelected);
+        },
+        _getFrame: function (id, skipWarning) {
+            var self = this, $frame = $h.getFrameElement(self.$preview, id);
+            if (self.showPreview && !skipWarning && !$frame.length) {
+                self._log($h.logMessages.invalidThumb, {id: id});
+            }
+            return $frame;
+        },
+        _getZoom: function (id, selector) {
+            var self = this, $frame = $h.getZoomElement(self.$preview, id, selector);
+            if (self.showPreview && !$frame.length) {
+                self._log($h.logMessages.invalidThumb, {id: id});
+            }
+            return $frame;
+        },
+        _getThumbs: function (css) {
+            css = css || '';
+            return this.getFrames(':not(.file-preview-initial)' + css);
+        },
+        _getThumbId: function (fileId) {
+            var self = this;
+            return self.previewInitId + '-' + fileId;
+        },
+        _getExtraData: function (fileId, index) {
+            var self = this, data = self.uploadExtraData;
+            if (typeof self.uploadExtraData === 'function') {
+                data = self.uploadExtraData(fileId, index);
+            }
+            return data;
+        },
+        _initXhr: function (xhrobj, fileId) {
+            var self = this, fm = self.fileManager, func = function (event) {
+                var pct = 0, total = event.total, loaded = event.loaded || event.position,
+                    stats = fm.getUploadStats(fileId, loaded, total);
+                /** @namespace event.lengthComputable */
+                if (event.lengthComputable && !self.enableResumableUpload) {
+                    pct = $h.round(loaded / total * 100);
+                }
+                if (fileId) {
+                    self._setFileUploadStats(fileId, pct, stats);
+                } else {
+                    self._setProgress(pct, null, null, self._getStats(stats));
+                }
+                self._raise('fileajaxprogress', [stats]);
+            };
+            if (xhrobj.upload) {
+                if (self.progressDelay) {
+                    func = $h.debounce(func, self.progressDelay);
+                }
+                xhrobj.upload.addEventListener('progress', func, false);
+            }
+            return xhrobj;
+        },
+        _initAjaxSettings: function () {
+            var self = this;
+            self._ajaxSettings = $.extend(true, {}, self.ajaxSettings);
+            self._ajaxDeleteSettings = $.extend(true, {}, self.ajaxDeleteSettings);
+        },
+        _mergeAjaxCallback: function (funcName, srcFunc, type) {
+            var self = this, settings = self._ajaxSettings, flag = self.mergeAjaxCallbacks, targFunc;
+            if (type === 'delete') {
+                settings = self._ajaxDeleteSettings;
+                flag = self.mergeAjaxDeleteCallbacks;
+            }
+            targFunc = settings[funcName];
+            if (flag && typeof targFunc === 'function') {
+                if (flag === 'before') {
+                    settings[funcName] = function () {
+                        targFunc.apply(this, arguments);
+                        srcFunc.apply(this, arguments);
+                    };
+                } else {
+                    settings[funcName] = function () {
+                        srcFunc.apply(this, arguments);
+                        targFunc.apply(this, arguments);
+                    };
+                }
+            } else {
+                settings[funcName] = srcFunc;
+            }
+        },
+        _ajaxSubmit: function (fnBefore, fnSuccess, fnComplete, fnError, formdata, fileId, index, vUrl) {
+            var self = this, settings, defaults, data, tm = self.taskManager;
+            if (!self._raise('filepreajax', [formdata, fileId, index])) {
+                return;
+            }
+            formdata.append('initialPreview', JSON.stringify(self.initialPreview));
+            formdata.append('initialPreviewConfig', JSON.stringify(self.initialPreviewConfig));
+            formdata.append('initialPreviewThumbTags', JSON.stringify(self.initialPreviewThumbTags));
+            self._initAjaxSettings();
+            self._mergeAjaxCallback('beforeSend', fnBefore);
+            self._mergeAjaxCallback('success', fnSuccess);
+            self._mergeAjaxCallback('complete', fnComplete);
+            self._mergeAjaxCallback('error', fnError);
+            vUrl = vUrl || self.uploadUrlThumb || self.uploadUrl;
+            if (typeof vUrl === 'function') {
+                vUrl = vUrl();
+            }
+            data = self._getExtraData(fileId, index) || {};
+            if (typeof data === 'object') {
+                $.each(data, function (key, value) {
+                    formdata.append(key, value);
+                });
+            }
+            defaults = {
+                xhr: function () {
+                    var xhrobj = $.ajaxSettings.xhr();
+                    return self._initXhr(xhrobj, fileId);
+                },
+                url: self._encodeURI(vUrl),
+                type: 'POST',
+                dataType: 'json',
+                data: formdata,
+                cache: false,
+                processData: false,
+                contentType: false
+            };
+            settings = $.extend(true, {}, defaults, self._ajaxSettings);
+            self.ajaxQueue.push(settings);
+            tm.addTask(fileId + '-' + index, function () {
+                var self = this.self, config, xhr;
+                config = self.ajaxQueue.shift();
+                xhr = $.ajax(config);
+                self.ajaxRequests.push(xhr);
+            }).runWithContext({self: self});
+        },
+        _mergeArray: function (prop, content) {
+            var self = this, arr1 = $h.cleanArray(self[prop]), arr2 = $h.cleanArray(content);
+            self[prop] = arr1.concat(arr2);
+        },
+        _initUploadSuccess: function (out, $thumb, allFiles) {
+            var self = this, append, data, index, $div, content, config, tags, id, i;
+            if (!self.showPreview || typeof out !== 'object' || $.isEmptyObject(out)) {
+                self._resetCaption();
+                return;
+            }
+            if (out.initialPreview !== undefined && out.initialPreview.length > 0) {
+                self.hasInitData = true;
+                content = out.initialPreview || [];
+                config = out.initialPreviewConfig || [];
+                tags = out.initialPreviewThumbTags || [];
+                append = out.append === undefined || out.append;
+                if (content.length > 0 && !$h.isArray(content)) {
+                    content = content.split(self.initialPreviewDelimiter);
+                }
+                if (content.length) {
+                    self._mergeArray('initialPreview', content);
+                    self._mergeArray('initialPreviewConfig', config);
+                    self._mergeArray('initialPreviewThumbTags', tags);
+                }
+                if ($thumb !== undefined) {
+                    if (!allFiles) {
+                        index = self.previewCache.add(content[0], config[0], tags[0], append);
+                        data = self.previewCache.get(index, false);
+                        $div = $h.createElement(data).hide().appendTo($thumb);
+                        $thumb.fadeOut('slow', function () {
+                            var $newThumb = $div.find('> .file-preview-frame');
+                            if ($newThumb && $newThumb.length) {
+                                $newThumb.insertBefore($thumb).fadeIn('slow').css('display:inline-block');
+                            }
+                            self._initPreviewActions();
+                            self._clearFileInput();
+                            $thumb.remove();
+                            $div.remove();
+                            self._initSortable();
+                        });
+                    } else {
+                        id = $thumb.attr('id');
+                        i = self._getUploadCacheIndex(id);
+                        if (i !== null) {
+                            self.uploadCache[i] = {
+                                id: id,
+                                content: content[0],
+                                config: config[0] || [],
+                                tags: tags[0] || [],
+                                append: append
+                            };
+                        }
+                    }
+                } else {
+                    self.previewCache.set(content, config, tags, append);
+                    self._initPreview();
+                    self._initPreviewActions();
+                }
+            }
+            self._resetCaption();
+        },
+        _getUploadCacheIndex: function (id) {
+            var self = this, i, len = self.uploadCache.length, config;
+            for (i = 0; i < len; i++) {
+                config = self.uploadCache[i];
+                if (config.id === id) {
+                    return i;
+                }
+            }
+            return null;
+        },
+        _initSuccessThumbs: function () {
+            var self = this;
+            if (!self.showPreview) {
+                return;
+            }
+            setTimeout(function () {
+                self._getThumbs($h.FRAMES + '.file-preview-success').each(function () {
+                    var $thumb = $(this), $remove = $thumb.find('.kv-file-remove');
+                    $remove.removeAttr('disabled');
+                    self._handler($remove, 'click', function () {
+                        var id = $thumb.attr('id'),
+                            out = self._raise('filesuccessremove', [id, $thumb.attr('data-fileindex')]);
+                        $h.cleanMemory($thumb);
+                        if (out === false) {
+                            return;
+                        }
+                        self.$caption.attr('title', '');
+                        $thumb.fadeOut('slow', function () {
+                            var fm = self.fileManager;
+                            $thumb.remove();
+                            if (!self.getFrames().length) {
+                                self.reset();
+                            }
+                        });
+                    });
+                });
+            }, self.processDelay);
+        },
+        _updateInitialPreview: function () {
+            var self = this, u = self.uploadCache;
+            if (self.showPreview) {
+                $.each(u, function (key, setting) {
+                    self.previewCache.add(setting.content, setting.config, setting.tags, setting.append);
+                });
+                if (self.hasInitData) {
+                    self._initPreview();
+                    self._initPreviewActions();
+                }
+            }
+        },
+        _getThumbFileId: function ($thumb) {
+            var self = this;
+            if (self.showPreview && $thumb !== undefined) {
+                return $thumb.attr('data-fileid');
+            }
+            return null;
+        },
+        _getThumbFile: function ($thumb) {
+            var self = this, id = self._getThumbFileId($thumb);
+            return id ? self.fileManager.getFile(id) : null;
+        },
+        _uploadSingle: function (i, id, isBatch, deferrer) {
+            var self = this, fm = self.fileManager, count = fm.count(), formdata = new FormData(), outData,
+                previewId = self._getThumbId(id), $thumb, chkComplete, $btnUpload, $btnDelete,
+                hasPostData = count > 0 || !$.isEmptyObject(self.uploadExtraData), uploadFailed, $prog, fnBefore,
+                errMsg, fnSuccess, fnComplete, fnError, updateUploadLog, op = self.ajaxOperations.uploadThumb,
+                fileObj = fm.getFile(id), params = {id: previewId, index: i, fileId: id},
+                fileName = self.fileManager.getFileName(id, true), resolve = function () {
+                    if (deferrer && deferrer.resolve) {
+                        deferrer.resolve();
+                    }
+                }, reject = function () {
+                    if (deferrer && deferrer.reject) {
+                        deferrer.reject();
+                    }
+                };
+            if (self.enableResumableUpload) { // not enabled for resumable uploads
+                return;
+            }
+            self.uploadInitiated = true;
+            if (self.showPreview) {
+                $thumb = fm.getThumb(id);
+                $prog = $thumb.find('.file-thumb-progress');
+                $btnUpload = $thumb.find('.kv-file-upload');
+                $btnDelete = $thumb.find('.kv-file-remove');
+                $prog.show();
+            }
+            if (count === 0 || !hasPostData || (self.showPreview && $btnUpload && $btnUpload.hasClass('disabled')) ||
+                self._abort(params)) {
+                return;
+            }
+            updateUploadLog = function () {
+                if (!uploadFailed) {
+                    fm.removeFile(id);
+                } else {
+                    fm.errors.push(id);
+                }
+                fm.setProcessed(id);
+                if (fm.isProcessed()) {
+                    self.fileBatchCompleted = true;
+                    chkComplete();
+                }
+            };
+            chkComplete = function () {
+                var $initThumbs;
+                if (!self.fileBatchCompleted) {
+                    return;
+                }
+                setTimeout(function () {
+                    var triggerReset = fm.count() === 0, errCount = fm.errors.length;
+                    self._updateInitialPreview();
+                    self.unlock(triggerReset);
+                    if (triggerReset) {
+                        self._clearFileInput();
+                    }
+                    $initThumbs = self.$preview.find('.file-preview-initial');
+                    if (self.uploadAsync && $initThumbs.length) {
+                        $h.addCss($initThumbs, $h.SORT_CSS);
+                        self._initSortable();
+                    }
+                    self._raise('filebatchuploadcomplete', [fm.stack, self._getExtraData()]);
+                    if (!self.retryErrorUploads || errCount === 0) {
+                        fm.clear();
+                    }
+                    self._setProgress(101);
+                    self.ajaxAborted = false;
+                    self.uploadInitiated = false;
+                }, self.processDelay);
+            };
+            fnBefore = function (jqXHR) {
+                outData = self._getOutData(formdata, jqXHR);
+                fm.initStats(id);
+                self.fileBatchCompleted = false;
+                if (!isBatch) {
+                    self.ajaxAborted = false;
+                }
+                if (self.showPreview) {
+                    if (!$thumb.hasClass('file-preview-success')) {
+                        self._setThumbStatus($thumb, 'Loading');
+                        $h.addCss($thumb, 'file-uploading');
+                    }
+                    $btnUpload.attr('disabled', true);
+                    $btnDelete.attr('disabled', true);
+                }
+                if (!isBatch) {
+                    self.lock();
+                }
+                if (fm.errors.indexOf(id) !== -1) {
+                    delete fm.errors[id];
+                }
+                self._raise('filepreupload', [outData, previewId, i, self._getThumbFileId($thumb)]);
+                $.extend(true, params, outData);
+                if (self._abort(params)) {
+                    jqXHR.abort();
+
+                    if (!isBatch) {
+                        self._setThumbStatus($thumb, 'New');
+                        $thumb.removeClass('file-uploading');
+                        $btnUpload.removeAttr('disabled');
+                        $btnDelete.removeAttr('disabled');
+                    }
+                    self._setProgressCancelled();
+                }
+            };
+            fnSuccess = function (data, textStatus, jqXHR) {
+                var pid = self.showPreview && $thumb.attr('id') ? $thumb.attr('id') : previewId;
+                outData = self._getOutData(formdata, jqXHR, data);
+                $.extend(true, params, outData);
+                setTimeout(function () {
+                    if ($h.isEmpty(data) || $h.isEmpty(data.error)) {
+                        if (self.showPreview) {
+                            self._setThumbStatus($thumb, 'Success');
+                            $btnUpload.hide();
+                            self._initUploadSuccess(data, $thumb, isBatch);
+                            self._setProgress(101, $prog);
+                        }
+                        self._raise('fileuploaded', [outData, pid, i, self._getThumbFileId($thumb)]);
+                        if (!isBatch) {
+                            self.fileManager.remove($thumb);
+                        } else {
+                            updateUploadLog();
+                            resolve();
+                        }
+                    } else {
+                        uploadFailed = true;
+                        errMsg = self._parseError(op, jqXHR, self.msgUploadError, self.fileManager.getFileName(id));
+                        self._showFileError(errMsg, params);
+                        self._setPreviewError($thumb, true);
+                        if (!self.retryErrorUploads) {
+                            $btnUpload.hide();
+                        }
+                        if (isBatch) {
+                            updateUploadLog();
+                            resolve();
+                        }
+                        self._setProgress(101, self._getFrame(pid).find('.file-thumb-progress'),
+                            self.msgUploadError);
+                    }
+                }, self.processDelay);
+            };
+            fnComplete = function () {
+                if (self.showPreview) {
+                    $btnUpload.removeAttr('disabled');
+                    $btnDelete.removeAttr('disabled');
+                    $thumb.removeClass('file-uploading');
+                }
+                if (!isBatch) {
+                    self.unlock(false);
+                    self._clearFileInput();
+                } else {
+                    chkComplete();
+                }
+                self._initSuccessThumbs();
+            };
+            fnError = function (jqXHR, textStatus, errorThrown) {
+                errMsg = self._parseError(op, jqXHR, errorThrown, self.fileManager.getFileName(id));
+                uploadFailed = true;
+                setTimeout(function () {
+                    var $prog;
+                    if (isBatch) {
+                        updateUploadLog();
+                        reject();
+                    }
+                    self.fileManager.setProgress(id, 100);
+                    self._setPreviewError($thumb, true);
+                    if (!self.retryErrorUploads) {
+                        $btnUpload.hide();
+                    }
+                    $.extend(true, params, self._getOutData(formdata, jqXHR));
+                    self._setProgress(101, self.$progress, self.msgAjaxProgressError.replace('{operation}', op));
+                    $prog = self.showPreview && $thumb ? $thumb.find('.file-thumb-progress') : '';
+                    self._setProgress(101, $prog, self.msgUploadError);
+                    self._showFileError(errMsg, params);
+                }, self.processDelay);
+            };
+            self._setFileData(formdata, fileObj.file, fileName, id);
+            self._setUploadData(formdata, {fileId: id});
+            self._ajaxSubmit(fnBefore, fnSuccess, fnComplete, fnError, formdata, id, i);
+        },
+        _setFileData: function (formdata, file, fileName, fileId) {
+            var self = this, preProcess = self.preProcessUpload;
+            if (preProcess && typeof preProcess === 'function') {
+                formdata.append(self.uploadFileAttr, preProcess(fileId, file));
+            } else {
+                formdata.append(self.uploadFileAttr, file, fileName);
+            }
+        },
+        _checkBatchPreupload: function (outData, jqXHR) {
+            var self = this, out = self._raise('filebatchpreupload', [outData]);
+            if (out) {
+                return true;
+            }
+            self._abort(outData);
+            if (jqXHR) {
+                jqXHR.abort();
+            }
+            self._getThumbs().each(function () {
+                var $thumb = $(this), $btnUpload = $thumb.find('.kv-file-upload'),
+                    $btnDelete = $thumb.find('.kv-file-remove');
+                if ($thumb.hasClass('file-preview-loading')) {
+                    self._setThumbStatus($thumb, 'New');
+                    $thumb.removeClass('file-uploading');
+                }
+                $btnUpload.removeAttr('disabled');
+                $btnDelete.removeAttr('disabled');
+            });
+            self._setProgressCancelled();
+            return false;
+        },
+        _uploadBatch: function () {
+            var self = this, fm = self.fileManager, total = fm.total(), params = {}, fnBefore, fnSuccess, fnError,
+                fnComplete, hasPostData = total > 0 || !$.isEmptyObject(self.uploadExtraData), errMsg,
+                setAllUploaded, formdata = new FormData(), op = self.ajaxOperations.uploadBatch;
+            if (total === 0 || !hasPostData || self._abort(params)) {
+                return;
+            }
+            setAllUploaded = function () {
+                self.fileManager.clear();
+                self._clearFileInput();
+            };
+            fnBefore = function (jqXHR) {
+                self.lock();
+                fm.initStats();
+                var outData = self._getOutData(formdata, jqXHR);
+                self.ajaxAborted = false;
+                if (self.showPreview) {
+                    self._getThumbs().each(function () {
+                        var $thumb = $(this), $btnUpload = $thumb.find('.kv-file-upload'),
+                            $btnDelete = $thumb.find('.kv-file-remove');
+                        if (!$thumb.hasClass('file-preview-success')) {
+                            self._setThumbStatus($thumb, 'Loading');
+                            $h.addCss($thumb, 'file-uploading');
+                        }
+                        $btnUpload.attr('disabled', true);
+                        $btnDelete.attr('disabled', true);
+                    });
+                }
+                self._checkBatchPreupload(outData, jqXHR);
+            };
+            fnSuccess = function (data, textStatus, jqXHR) {
+                /** @namespace data.errorkeys */
+                var outData = self._getOutData(formdata, jqXHR, data), key = 0,
+                    $thumbs = self._getThumbs(':not(.file-preview-success)'),
+                    keys = $h.isEmpty(data) || $h.isEmpty(data.errorkeys) ? [] : data.errorkeys;
+
+                if ($h.isEmpty(data) || $h.isEmpty(data.error)) {
+                    self._raise('filebatchuploadsuccess', [outData]);
+                    setAllUploaded();
+                    if (self.showPreview) {
+                        $thumbs.each(function () {
+                            var $thumb = $(this);
+                            self._setThumbStatus($thumb, 'Success');
+                            $thumb.removeClass('file-uploading');
+                            $thumb.find('.kv-file-upload').hide().removeAttr('disabled');
+                        });
+                        self._initUploadSuccess(data);
+                    } else {
+                        self.reset();
+                    }
+                    self._setProgress(101);
+                } else {
+                    if (self.showPreview) {
+                        $thumbs.each(function () {
+                            var $thumb = $(this);
+                            $thumb.removeClass('file-uploading');
+                            $thumb.find('.kv-file-upload').removeAttr('disabled');
+                            $thumb.find('.kv-file-remove').removeAttr('disabled');
+                            if (keys.length === 0 || $.inArray(key, keys) !== -1) {
+                                self._setPreviewError($thumb, true);
+                                if (!self.retryErrorUploads) {
+                                    $thumb.find('.kv-file-upload').hide();
+                                    self.fileManager.remove($thumb);
+                                }
+                            } else {
+                                $thumb.find('.kv-file-upload').hide();
+                                self._setThumbStatus($thumb, 'Success');
+                                self.fileManager.remove($thumb);
+                            }
+                            if (!$thumb.hasClass('file-preview-error') || self.retryErrorUploads) {
+                                key++;
+                            }
+                        });
+                        self._initUploadSuccess(data);
+                    }
+                    errMsg = self._parseError(op, jqXHR, self.msgUploadError);
+                    self._showFileError(errMsg, outData, 'filebatchuploaderror');
+                    self._setProgress(101, self.$progress, self.msgUploadError);
+                }
+            };
+            fnComplete = function () {
+                self.unlock();
+                self._initSuccessThumbs();
+                self._clearFileInput();
+                self._raise('filebatchuploadcomplete', [self.fileManager.stack, self._getExtraData()]);
+            };
+            fnError = function (jqXHR, textStatus, errorThrown) {
+                var outData = self._getOutData(formdata, jqXHR);
+                errMsg = self._parseError(op, jqXHR, errorThrown);
+                self._showFileError(errMsg, outData, 'filebatchuploaderror');
+                self.uploadFileCount = total - 1;
+                if (!self.showPreview) {
+                    return;
+                }
+                self._getThumbs().each(function () {
+                    var $thumb = $(this);
+                    $thumb.removeClass('file-uploading');
+                    if (self._getThumbFile($thumb)) {
+                        self._setPreviewError($thumb);
+                    }
+                });
+                self._getThumbs().removeClass('file-uploading');
+                self._getThumbs(' .kv-file-upload').removeAttr('disabled');
+                self._getThumbs(' .kv-file-delete').removeAttr('disabled');
+                self._setProgress(101, self.$progress, self.msgAjaxProgressError.replace('{operation}', op));
+            };
+            var ctr = 0;
+            $.each(self.fileManager.stack, function (key, data) {
+                if (!$h.isEmpty(data.file)) {
+                    self._setFileData(formdata, data.file, (data.nameFmt || ('untitled_' + ctr)), key);
+                }
+                ctr++;
+            });
+            self._ajaxSubmit(fnBefore, fnSuccess, fnComplete, fnError, formdata);
+        },
+        _uploadExtraOnly: function () {
+            var self = this, params = {}, fnBefore, fnSuccess, fnComplete, fnError, formdata = new FormData(), errMsg,
+                op = self.ajaxOperations.uploadExtra;
+            fnBefore = function (jqXHR) {
+                self.lock();
+                var outData = self._getOutData(formdata, jqXHR);
+                self._setProgress(50);
+                params.data = outData;
+                params.xhr = jqXHR;
+                self._checkBatchPreupload(outData, jqXHR);
+            };
+            fnSuccess = function (data, textStatus, jqXHR) {
+                var outData = self._getOutData(formdata, jqXHR, data);
+                if ($h.isEmpty(data) || $h.isEmpty(data.error)) {
+                    self._raise('filebatchuploadsuccess', [outData]);
+                    self._clearFileInput();
+                    self._initUploadSuccess(data);
+                    self._setProgress(101);
+                } else {
+                    errMsg = self._parseError(op, jqXHR, self.msgUploadError);
+                    self._showFileError(errMsg, outData, 'filebatchuploaderror');
+                }
+            };
+            fnComplete = function () {
+                self.unlock();
+                self._clearFileInput();
+                self._raise('filebatchuploadcomplete', [self.fileManager.stack, self._getExtraData()]);
+            };
+            fnError = function (jqXHR, textStatus, errorThrown) {
+                var outData = self._getOutData(formdata, jqXHR);
+                errMsg = self._parseError(op, jqXHR, errorThrown);
+                params.data = outData;
+                self._showFileError(errMsg, outData, 'filebatchuploaderror');
+                self._setProgress(101, self.$progress, self.msgAjaxProgressError.replace('{operation}', op));
+            };
+            self._ajaxSubmit(fnBefore, fnSuccess, fnComplete, fnError, formdata);
+        },
+        _deleteFileIndex: function ($frame) {
+            var self = this, ind = $frame.attr('data-fileindex'), rev = self.reversePreviewOrder;
+            if (ind.substring(0, 5) === $h.INIT_FLAG) {
+                ind = parseInt(ind.replace($h.INIT_FLAG, ''));
+                self.initialPreview = $h.spliceArray(self.initialPreview, ind, rev);
+                self.initialPreviewConfig = $h.spliceArray(self.initialPreviewConfig, ind, rev);
+                self.initialPreviewThumbTags = $h.spliceArray(self.initialPreviewThumbTags, ind, rev);
+                self.getFrames().each(function () {
+                    var $nFrame = $(this), nInd = $nFrame.attr('data-fileindex');
+                    if (nInd.substring(0, 5) === $h.INIT_FLAG) {
+                        nInd = parseInt(nInd.replace($h.INIT_FLAG, ''));
+                        if (nInd > ind) {
+                            nInd--;
+                            $nFrame.attr('data-fileindex', $h.INIT_FLAG + nInd);
+                        }
+                    }
+                });
+            }
+        },
+        _resetCaption: function () {
+            var self = this;
+            setTimeout(function () {
+                var cap = '', n, chk = self.previewCache.count(true), len = self.fileManager.count(), file,
+                    incomplete = ':not(.file-preview-success):not(.file-preview-error)', cfg,
+                    hasThumb = self.showPreview && self.getFrames(incomplete).length;
+                if (len === 0 && chk === 0 && !hasThumb) {
+                    self.reset();
+                } else {
+                    n = chk + len;
+                    if (n > 1) {
+                        cap = self._getMsgSelected(n);
+                    } else {
+                        if (len === 0) {
+                            cfg = self.initialPreviewConfig[0];
+                            cap = '';
+                            if (cfg) {
+                                cap = cfg.caption || cfg.filename || '';
+                            }
+                            if (!cap) {
+                                cap = self._getMsgSelected(n);
+                            }
+                        } else {
+                            file = self.fileManager.getFirstFile();
+                            cap = file ? file.nameFmt : '_';
+                        }
+                    }
+                    self._setCaption(cap);
+                }
+            }, self.processDelay);
+        },
+        _handleRotation: function ($el, $content, angle) {
+            var self = this, css, newCss, addCss = '', scale = 1, elContent = $content[0], quadrant, transform, h, w,
+                wNew, $parent = $content.parent(), hParent, wParent, $body = $('body'), bodyExists = !!$body.length;
+            if (bodyExists) {
+                $body.addClass('kv-overflow-hidden');
+            }
+            if (!$content.length || $el.hasClass('hide-rotate')) {
+                if (bodyExists) {
+                    $body.removeClass('kv-overflow-hidden');
+                }
+                return;
+            }
+            transform = $content.css('transform');
+            if (transform) {
+                $content.css('transform', 'none');
+            }
+            if (transform) {
+                $content.css('transform', transform);
+            }
+            angle = angle || 0;
+            quadrant = angle % 360;
+            css = 'rotate(' + angle + 'deg)';
+            newCss = 'rotate(' + quadrant + 'deg)';
+            addCss = '';
+            if (quadrant === 90 || quadrant === 270) {
+                w = elContent.naturalWidth || $content.outerWidth() || 0;
+                h = elContent.naturalHeight || $content.outerHeight() || 0;
+                scale = w > h && w != 0 ? (h / w).toFixed(2) : 1;
+                if ($parent.length) {
+                    hParent = $parent.height();
+                    wParent = $parent.width();
+                    wNew = Math.min(w, wParent);
+                    if (hParent > scale * wNew) {
+                        scale = wNew > hParent && wNew != 0 ? (hParent / wNew).toFixed(2) : 1;
+                    }
+                }
+                if (scale !== 1) {
+                    addCss = ' scale(' + scale + ')';
+                }
+            }
+            $content.addClass('rotate-animate').css('transform', css + addCss);
+            setTimeout(function () {
+                $content.removeClass('rotate-animate').css('transform', newCss + addCss);
+                if (bodyExists) {
+                    $body.removeClass('kv-overflow-hidden');
+                }
+                $el.data('angle', quadrant);
+            }, self.fadeDelay);
+        },
+        _initRotateButton: function () {
+            var self = this;
+            self.getFrames('.rotatable .kv-file-rotate').each(function () {
+                var $el = $(this), $frame = $el.closest($h.FRAMES),
+                    $content = $frame.find('.kv-file-content > :first-child');
+                self._handler($el, 'click', function () {
+                    var angle = ($frame.data('angle') || 0) + 90;
+                    self._handleRotation($frame, $content, angle);
+                });
+            });
+        },
+        _initRotateZoom: function ($frame, $content) {
+            var self = this, $modal = self.$modal, $rotate = $modal.find('.btn-kv-rotate'),
+                angle = $frame.data('angle');
+            $modal.data('angle', angle);
+            if ($rotate.length) {
+                $rotate.off('click');
+                if ($modal.hasClass('rotatable')) {
+                    $rotate.on('click', function () {
+                        angle = ($modal.data('angle') || 0) + 90;
+                        $modal.data('angle', angle);
+                        self._handleRotation($modal, $modal.find('.file-zoom-detail'), angle);
+                        self._handleRotation($frame, $content, angle);
+                        if ($frame.hasClass('hide-rotate')) {
+                            $frame.data('angle', angle);
+                        }
+                    });
+                }
+            }
+        },
+        _initFileActions: function () {
+            var self = this;
+            if (!self.showPreview) {
+                return;
+            }
+            self._initZoomButton();
+            self._initRotateButton();
+            self.getFrames(' .kv-file-remove').each(function () {
+                var $el = $(this), $frame = $el.closest($h.FRAMES), hasError, id = $frame.attr('id'),
+                    ind = $frame.attr('data-fileindex'), status, fm = self.fileManager;
+                self._handler($el, 'click', function () {
+                    status = self._raise('filepreremove', [id, ind]);
+                    if (status === false || !self._validateMinCount()) {
+                        return false;
+                    }
+                    hasError = $frame.hasClass('file-preview-error');
+                    $h.cleanMemory($frame);
+                    $frame.fadeOut('slow', function () {
+                        self.fileManager.remove($frame);
+                        self._clearObjects($frame);
+                        $frame.remove();
+                        if (id && hasError) {
+                            self.$errorContainer.find('li[data-thumb-id="' + id + '"]').fadeOut('fast', function () {
+                                $(this).remove();
+                                if (!self._errorsExist()) {
+                                    self._resetErrors();
+                                }
+                            });
+                        }
+                        self._clearFileInput();
+                        self._resetCaption();
+                        self._raise('fileremoved', [id, ind]);
+                    });
+                });
+            });
+            self.getFrames(' .kv-file-upload').each(function () {
+                var $el = $(this);
+                self._handler($el, 'click', function () {
+                    var $frame = $el.closest($h.FRAMES), fileId = self._getThumbFileId($frame);
+                    self._hideProgress();
+                    if ($frame.hasClass('file-preview-error') && !self.retryErrorUploads) {
+                        return;
+                    }
+                    self._uploadSingle(self.fileManager.getIndex(fileId), fileId, false);
+                });
+            });
+        },
+        _initPreviewActions: function () {
+            var self = this, $preview = self.$preview, deleteExtraData = self.deleteExtraData || {},
+                btnRemove = $h.FRAMES + ' .kv-file-remove', settings = self.fileActionSettings,
+                origClass = settings.removeClass, errClass = settings.removeErrorClass,
+                resetProgress = function () {
+                    var hasFiles = self.isAjaxUpload ? self.previewCache.count(true) : self._inputFileCount();
+                    if (!self.getFrames().length && !hasFiles) {
+                        self._setCaption('');
+                        self.reset();
+                        self.initialCaption = '';
+                    } else {
+                        self._resetCaption();
+                    }
+                };
+            self._initZoomButton();
+            self._initRotateButton();
+            $preview.find(btnRemove).each(function () {
+                var $el = $(this), vUrl = $el.data('url') || self.deleteUrl, vKey = $el.data('key'), errMsg, fnBefore,
+                    fnSuccess, fnError, op = self.ajaxOperations.deleteThumb;
+                if ($h.isEmpty(vUrl) || vKey === undefined) {
+                    return;
+                }
+                if (typeof vUrl === 'function') {
+                    vUrl = vUrl();
+                }
+                var $frame = $el.closest($h.FRAMES), cache = self.previewCache.data, settings, params, config,
+                    fileName, extraData, index = $frame.attr('data-fileindex');
+                index = parseInt(index.replace($h.INIT_FLAG, ''));
+                config = $h.isEmpty(cache.config) && $h.isEmpty(cache.config[index]) ? null : cache.config[index];
+                extraData = $h.isEmpty(config) || $h.isEmpty(config.extra) ? deleteExtraData : config.extra;
+                fileName = config && (config.filename || config.caption) || '';
+                if (typeof extraData === 'function') {
+                    extraData = extraData();
+                }
+                params = {id: $el.attr('id'), key: vKey, extra: extraData};
+                fnBefore = function (jqXHR) {
+                    self.ajaxAborted = false;
+                    self._raise('filepredelete', [vKey, jqXHR, extraData]);
+                    if (self._abort()) {
+                        jqXHR.abort();
+                    } else {
+                        $el.removeClass(errClass);
+                        $h.addCss($frame, 'file-uploading');
+                        $h.addCss($el, 'disabled ' + origClass);
+                    }
+                };
+                fnSuccess = function (data, textStatus, jqXHR) {
+                    var n, cap;
+                    if (!$h.isEmpty(data) && !$h.isEmpty(data.error)) {
+                        params.jqXHR = jqXHR;
+                        params.response = data;
+                        errMsg = self._parseError(op, jqXHR, self.msgDeleteError, fileName);
+                        self._showFileError(errMsg, params, 'filedeleteerror');
+                        $frame.removeClass('file-uploading');
+                        $el.removeClass('disabled ' + origClass).addClass(errClass);
+                        resetProgress();
+                        return;
+                    }
+                    $frame.removeClass('file-uploading').addClass('file-deleted');
+                    $frame.fadeOut('slow', function () {
+                        index = parseInt(($frame.attr('data-fileindex')).replace($h.INIT_FLAG, ''));
+                        self.previewCache.unset(index);
+                        self._deleteFileIndex($frame);
+                        n = self.previewCache.count(true);
+                        cap = n > 0 ? self._getMsgSelected(n) : '';
+                        self._setCaption(cap);
+                        self._raise('filedeleted', [vKey, jqXHR, extraData]);
+                        self._clearObjects($frame);
+                        $frame.remove();
+                        resetProgress();
+                    });
+                };
+                fnError = function (jqXHR, textStatus, errorThrown) {
+                    var errMsg = self._parseError(op, jqXHR, errorThrown, fileName);
+                    params.jqXHR = jqXHR;
+                    params.response = {};
+                    self._showFileError(errMsg, params, 'filedeleteerror');
+                    $frame.removeClass('file-uploading');
+                    $el.removeClass('disabled ' + origClass).addClass(errClass);
+                    resetProgress();
+                };
+                self._initAjaxSettings();
+                self._mergeAjaxCallback('beforeSend', fnBefore, 'delete');
+                self._mergeAjaxCallback('success', fnSuccess, 'delete');
+                self._mergeAjaxCallback('error', fnError, 'delete');
+                settings = $.extend(true, {}, {
+                    url: self._encodeURI(vUrl),
+                    type: 'POST',
+                    dataType: 'json',
+                    data: $.extend(true, {}, {key: vKey}, extraData)
+                }, self._ajaxDeleteSettings);
+                self._handler($el, 'click', function () {
+                    if (!self._validateMinCount()) {
+                        return false;
+                    }
+                    self.ajaxAborted = false;
+                    self._raise('filebeforedelete', [vKey, extraData]);
+                    if (self.ajaxAborted instanceof Promise) {
+                        self.ajaxAborted.then(function (result) {
+                            if (!result) {
+                                $.ajax(settings);
+                            }
+                        });
+                    } else {
+                        if (!self.ajaxAborted) {
+                            $.ajax(settings);
+                        }
+                    }
+                });
+            });
+        },
+        _hideFileIcon: function () {
+            var self = this;
+            if (self.overwriteInitial) {
+                self.$captionContainer.removeClass('icon-visible');
+            }
+        },
+        _showFileIcon: function () {
+            var self = this;
+            $h.addCss(self.$captionContainer, 'icon-visible');
+        },
+        _getSize: function (bytes, skipTemplate, sizeUnits) {
+            var self = this, size = parseFloat(bytes), i = 0, factor = self.bytesToKB, func = self.fileSizeGetter, out,
+                sizeHuman = size, newSize;
+            if (!$.isNumeric(bytes) || !$.isNumeric(size)) {
+                return '';
+            }
+            if (typeof func === 'function') {
+                out = func(size);
+            } else {
+                if (!sizeUnits) {
+                    sizeUnits = self.sizeUnits;
+                }
+                if (size > 0) {
+                    while (sizeHuman >= factor) {
+                        sizeHuman /= factor;
+                        ++i;
+                    }
+                    if (!sizeUnits[i]) {
+                        sizeHuman = size;
+                        i = 0;
+                    }
+                }
+                newSize = sizeHuman.toFixed(2);
+                if (newSize == sizeHuman) {
+                    newSize = sizeHuman;
+                }
+                out = newSize + ' ' + sizeUnits[i];
+            }
+            return skipTemplate ? out : self._getLayoutTemplate('size').replace('{sizeText}', out);
+        },
+        _getFileType: function (ftype) {
+            var self = this;
+            return self.mimeTypeAliases[ftype] || ftype;
+        },
+        _generatePreviewTemplate: function (
+            cat,
+            data,
+            fname,
+            ftype,
+            previewId,
+            fileId,
+            isError,
+            size,
+            fnameUpdated,
+            frameClass,
+            foot,
+            ind,
+            templ,
+            attrs,
+            zoomData
+        ) {
+            var self = this, caption = self.slug(fname), prevContent, zoomContent = '', styleAttribs = '',
+                filename = fnameUpdated || fname, isIconic, ext = filename.split('.').pop().toLowerCase(),
+                screenW = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth,
+                config, title = caption, alt = caption, typeCss = 'type-default', getContent, addFrameCss,
+                footer = foot || self._renderFileFooter(cat, caption, size, 'auto', isError), isRotatable,
+                alwaysPreview = $.inArray(ext, self.alwaysPreviewFileExtensions) !== -1,
+                forcePrevIcon = self.preferIconicPreview && !alwaysPreview,
+                forceZoomIcon = self.preferIconicZoomPreview && !alwaysPreview, newCat = forcePrevIcon ? 'other' : cat;
+            config = screenW < 400 ? (self.previewSettingsSmall[newCat] || self.defaults.previewSettingsSmall[newCat]) :
+                (self.previewSettings[newCat] || self.defaults.previewSettings[newCat]);
+            if (config) {
+                $.each(config, function (key, val) {
+                    styleAttribs += key + ':' + val + ';';
+                });
+            }
+            getContent = function (vCat, vData, zoom, frameCss, vZoomData) {
+                var id = zoom ? 'zoom-' + previewId : previewId, tmplt = self._getPreviewTemplate(vCat),
+                    css = (frameClass || '') + ' ' + frameCss, tokens;
+                if (self.frameClass) {
+                    css = self.frameClass + ' ' + css;
+                }
+                if (zoom) {
+                    css = css.replace(' ' + $h.SORT_CSS, '');
+                }
+                tmplt = self._parseFilePreviewIcon(tmplt, fname);
+                if (cat === 'object' && !ftype) {
+                    $.each(self.defaults.fileTypeSettings, function (key, func) {
+                        if (key === 'object' || key === 'other') {
+                            return;
+                        }
+                        if (func(fname, ftype)) {
+                            typeCss = 'type-' + key;
+                        }
+                    });
+                }
+                if (!$h.isEmpty(attrs)) {
+                    if (attrs.title !== undefined && attrs.title !== null) {
+                        title = attrs.title;
+                    }
+                    if (attrs.alt !== undefined && attrs.alt !== null) {
+                        alt = title = attrs.alt;
+                    }
+                }
+                tokens = {
+                    'previewId': id,
+                    'caption': caption,
+                    'title': title,
+                    'alt': alt,
+                    'frameClass': css,
+                    'type': self._getFileType(ftype),
+                    'fileindex': ind,
+                    'fileid': fileId || '',
+                    'filename': filename,
+                    'typeCss': typeCss,
+                    'footer': footer,
+                    'data': vData,
+//                  'data': zoom && vZoomData ? self.zoomPlaceholder + '{zoomData}' : vData,
+                    'template': templ || cat,
+                    'style': styleAttribs ? 'style="' + styleAttribs + '"' : '',
+                    'zoomData': vZoomData ? encodeURIComponent(vZoomData) : ''
+                };
+                if (zoom) {
+                    tokens.zoomCache = '';
+                    tokens.zoomData = '{zoomData}';
+                }
+                return tmplt.setTokens(tokens);
+            };
+            ind = ind || previewId.slice(previewId.lastIndexOf('-') + 1);
+            isRotatable = self.fileActionSettings.showRotate && $.inArray(ext, self.rotatableFileExtensions) !== -1;
+            if (self.fileActionSettings.showZoom) {
+                addFrameCss = 'kv-zoom-thumb';
+                if (isRotatable) {
+                    addFrameCss += ' rotatable' + (forceZoomIcon ? ' hide-rotate' : '');
+                }
+                zoomContent = getContent((forceZoomIcon ? 'other' : cat), data, true, addFrameCss, zoomData);
+            }
+            zoomContent = '\n' + self._getLayoutTemplate('zoomCache').replace('{zoomContent}', zoomContent);
+            if (typeof self.sanitizeZoomCache === 'function') {
+                zoomContent = self.sanitizeZoomCache(zoomContent);
+            }
+            addFrameCss = 'kv-preview-thumb';
+            if (isRotatable) {
+                isIconic = forcePrevIcon || self.hideThumbnailContent || !!self.previewFileIconSettings[ext];
+                addFrameCss += ' rotatable' + (isIconic ? ' hide-rotate' : '');
+            }
+            prevContent = getContent((forcePrevIcon ? 'other' : cat), data, false, addFrameCss, zoomData);
+            return prevContent.setTokens({zoomCache: zoomContent});
+        },
+        _addToPreview: function ($preview, content) {
+            var self = this, $el;
+            content = $h.cspBuffer.stash(content);
+            $el = self.reversePreviewOrder ? $preview.prepend(content) : $preview.append(content);
+            $h.cspBuffer.apply($preview);
+            return $el;
+        },
+        _previewDefault: function (file, isDisabled) {
+            var self = this, $preview = self.$preview;
+            if (!self.showPreview) {
+                return;
+            }
+            var fname = $h.getFileName(file), ftype = file ? file.type : '', content, size = file.size || 0,
+                caption = self._getFileName(file, ''), isError = isDisabled === true && !self.isAjaxUpload,
+                data = $h.createObjectURL(file), fileId = self.fileManager.getId(file),
+                previewId = self._getThumbId(fileId);
+            self._clearDefaultPreview();
+            content = self._generatePreviewTemplate('other', data, fname, ftype, previewId, fileId, isError, size);
+            self._addToPreview($preview, content);
+            self._setThumbAttr(previewId, caption, size);
+            if (isDisabled === true && self.isAjaxUpload) {
+                self._setThumbStatus(self._getFrame(previewId), 'Error');
+            }
+        },
+        _previewFile: function (i, file, theFile, data, fileInfo) {
+            if (!this.showPreview) {
+                return;
+            }
+            var self = this, fname = $h.getFileName(file), ftype = fileInfo.type, content,
+                caption = fileInfo.name, cat = self._parseFileType(ftype, fname), $preview = self.$preview,
+                fsize = file.size || 0, iData = cat === 'image' ? theFile.target.result : data, fm = self.fileManager,
+                fileId = fm.getId(file), previewId = self._getThumbId(fileId);
+            /** @namespace window.DOMPurify */
+            content = self._generatePreviewTemplate(cat, iData, fname, ftype, previewId, fileId, false, fsize, fileInfo.filename);
+            self._clearDefaultPreview();
+            self._addToPreview($preview, content);
+            var $thumb = self._getFrame(previewId);
+            self._validateImageOrientation($thumb.find('img'), file, previewId, fileId, caption, ftype, fsize, iData);
+            self._setThumbAttr(previewId, caption, fsize);
+            self._initSortable();
+        },
+        _setThumbAttr: function (id, caption, size, description) {
+            var self = this, $frame = self._getFrame(id);
+            if ($frame.length) {
+                size = size && size > 0 ? self._getSize(size) : '';
+                $frame.data({'caption': caption, 'size': size, 'description': description || ''});
+            }
+        },
+        _setInitThumbAttr: function () {
+            var self = this, data = self.previewCache.data, len = self.previewCache.count(true), config,
+                caption, size, description, previewId;
+            if (len === 0) {
+                return;
+            }
+            for (var i = 0; i < len; i++) {
+                config = data.config[i];
+                previewId = self.previewInitId + '-' + $h.INIT_FLAG + i;
+                caption = $h.ifSet('caption', config, $h.ifSet('filename', config));
+                size = $h.ifSet('size', config);
+                description = $h.ifSet('description', config);
+                self._setThumbAttr(previewId, caption, size, description);
+            }
+        },
+        _slugDefault: function (text) {
+            // noinspection RegExpRedundantEscape
+            return $h.isEmpty(text, true) ? '' : String(text).replace(/[\[\]\/\{}:;#%=\(\)\*\+\?\\\^\$\|<>&"']/g, '_');
+        },
+        _updateFileDetails: function (numFiles) {
+            var self = this, $el = self.$element, label, n, log, nFiles, file,
+                name = ($h.isIE(9) && $h.findFileName($el.val())) || ($el[0].files[0] && $el[0].files[0].name);
+            if (!name && self.fileManager.count() > 0) {
+                file = self.fileManager.getFirstFile();
+                label = file.nameFmt;
+            } else {
+                label = name ? self.slug(name) : '_';
+            }
+            n = self.isAjaxUpload ? self.fileManager.count() : numFiles;
+            nFiles = self.previewCache.count(true) + n;
+            log = n === 1 ? label : self._getMsgSelected(nFiles, !self.isAjaxUpload && !self.isError);
+            if (self.isError) {
+                self.$previewContainer.removeClass('file-thumb-loading');
+                self._initCapStatus();
+                self.$previewStatus.html('');
+                self.$captionContainer.removeClass('icon-visible');
+            } else {
+                self._showFileIcon();
+            }
+            self._setCaption(log, self.isError);
+            self.$container.removeClass('file-input-new file-input-ajax-new');
+            self._raise('fileselect', [numFiles, label]);
+            if (self.previewCache.count(true)) {
+                self._initPreviewActions();
+            }
+        },
+        _setThumbStatus: function ($thumb, status) {
+            var self = this;
+            if (!self.showPreview) {
+                return;
+            }
+            var icon = 'indicator' + status, msg = icon + 'Title',
+                css = 'file-preview-' + status.toLowerCase(),
+                $indicator = $thumb.find('.file-upload-indicator'),
+                config = self.fileActionSettings;
+            $thumb.removeClass('file-preview-success file-preview-error file-preview-paused file-preview-loading');
+            if (status === 'Success') {
+                $thumb.find('.file-drag-handle').remove();
+            }
+            $h.setHtml($indicator, config[icon]);
+            $indicator.attr('title', config[msg]);
+            $thumb.addClass(css);
+            if (status === 'Error' && !self.retryErrorUploads) {
+                $thumb.find('.kv-file-upload').attr('disabled', true);
+            }
+        },
+        _setProgressCancelled: function () {
+            var self = this;
+            self._setProgress(101, self.$progress, self.msgCancelled);
+        },
+        _setProgress: function (p, $el, error, stats) {
+            var self = this;
+            $el = $el || self.$progress;
+            if (!$el.length) {
+                return;
+            }
+            var pct = Math.min(p, 100), out, pctLimit = self.progressUploadThreshold,
+                t = p <= 100 ? self.progressTemplate : self.progressCompleteTemplate,
+                template = pct < 100 ? self.progressTemplate :
+                    (error ? (self.paused ? self.progressPauseTemplate : self.progressErrorTemplate) : t);
+            if (p >= 100) {
+                stats = '';
+            }
+            if (!$h.isEmpty(template)) {
+                if (pctLimit && pct > pctLimit && p <= 100) {
+                    out = template.setTokens({'percent': pctLimit, 'status': self.msgUploadThreshold});
+                } else {
+                    out = template.setTokens({'percent': pct, 'status': (p > 100 ? self.msgUploadEnd : pct + '%')});
+                }
+                stats = stats || '';
+                out = out.setTokens({stats: stats});
+                $h.setHtml($el, out);
+                if (error) {
+                    $h.setHtml($el.find('[role="progressbar"]'), error);
+                }
+            }
+        },
+        _hasFiles: function () {
+            var el = this.$element[0];
+            return !!(el && el.files && el.files.length);
+        },
+        _setFileDropZoneTitle: function () {
+            var self = this, $zone = self.$container.find('.file-drop-zone'), title = self.dropZoneTitle, strFiles;
+            if (self.isClickable) {
+                strFiles = $h.isEmpty(self.$element.attr('multiple')) ? self.fileSingle : self.filePlural;
+                title += self.dropZoneClickTitle.replace('{files}', strFiles);
+            }
+            $zone.find('.' + self.dropZoneTitleClass).remove();
+            if (!self.showPreview || $zone.length === 0 || self.fileManager.count() > 0 || !self.dropZoneEnabled ||
+                self.previewCache.count() > 0 || (!self.isAjaxUpload && self._hasFiles())) {
+                return;
+            }
+            if ($zone.find($h.FRAMES).length === 0 && $h.isEmpty(self.defaultPreviewContent)) {
+                $zone.prepend('<div class="' + self.dropZoneTitleClass + '">' + title + '</div>');
+            }
+            self.$container.removeClass('file-input-new');
+            $h.addCss(self.$container, 'file-input-ajax-new');
+        },
+        _getStats: function (stats) {
+            var self = this, pendingTime, t;
+            if (!self.showUploadStats || !stats || !stats.bitrate) {
+                return '';
+            }
+            t = self._getLayoutTemplate('stats');
+            pendingTime = (!stats.elapsed || !stats.bps) ? self.msgCalculatingTime :
+                self.msgPendingTime.setTokens({time: $h.getElapsed(Math.ceil(stats.pendingBytes / stats.bps))});
+
+            return t.setTokens({
+                uploadSpeed: stats.bitrate,
+                pendingTime: pendingTime
+            });
+        },
+        _setResumableProgress: function (pct, stats, $thumb) {
+            var self = this, rm = self.resumableManager, obj = $thumb ? rm : self,
+                $prog = $thumb ? $thumb.find('.file-thumb-progress') : null;
+            if (obj.lastProgress === 0) {
+                obj.lastProgress = pct;
+            }
+            if (pct < obj.lastProgress) {
+                pct = obj.lastProgress;
+            }
+            self._setProgress(pct, $prog, null, self._getStats(stats));
+            obj.lastProgress = pct;
+        },
+        _toggleResumableProgress: function (template, message) {
+            var self = this, $progress = self.$progress;
+            if ($progress && $progress.length) {
+                $h.setHtml($progress, template.setTokens({
+                    percent: 101,
+                    status: message,
+                    stats: ''
+                }));
+            }
+        },
+        _setFileUploadStats: function (id, pct, stats) {
+            var self = this, $prog = self.$progress;
+            if (!self.showPreview && (!$prog || !$prog.length)) {
+                return;
+            }
+            var fm = self.fileManager, rm = self.resumableManager, $thumb = fm.getThumb(id), pctTot,
+                totUpSize = 0, totSize = fm.getTotalSize(), totStats = $.extend(true, {}, stats);
+            if (self.enableResumableUpload) {
+                var loaded = stats.loaded, currUplSize = rm.getUploadedSize(), currTotSize = rm.file.size, totLoaded;
+                loaded += currUplSize;
+                totLoaded = fm.uploadedSize + loaded;
+                pct = $h.round(100 * loaded / currTotSize);
+                stats.pendingBytes = currTotSize - currUplSize;
+                self._setResumableProgress(pct, stats, $thumb);
+                pctTot = Math.floor(100 * totLoaded / totSize);
+                totStats.pendingBytes = totSize - totLoaded;
+                self._setResumableProgress(pctTot, totStats);
+            } else {
+                fm.setProgress(id, pct);
+                $prog = $thumb && $thumb.length ? $thumb.find('.file-thumb-progress') : null;
+                self._setProgress(pct, $prog, null, self._getStats(stats));
+                $.each(fm.stats, function (id, cfg) {
+                    totUpSize += cfg.loaded;
+                });
+                totStats.pendingBytes = totSize - totUpSize;
+                pctTot = $h.round(totUpSize / totSize * 100);
+                self._setProgress(pctTot, null, null, self._getStats(totStats));
+            }
+        },
+        _validateMinCount: function () {
+            var self = this, len = self.isAjaxUpload ? self.fileManager.count() : self._inputFileCount();
+            if (self.validateInitialCount && self.minFileCount > 0 && self._getFileCount(len - 1) < self.minFileCount) {
+                self._noFilesError({});
+                return false;
+            }
+            return true;
+        },
+        _getFileCount: function (fileCount, includeInitial) {
+            var self = this, addCount = 0;
+            if (includeInitial === undefined) {
+                includeInitial = self.validateInitialCount && !self.overwriteInitial;
+            }
+            if (includeInitial) {
+                addCount = self.previewCache.count(true);
+                fileCount += addCount;
+            }
+            return fileCount;
+        },
+        _getFileId: function (file) {
+            return $h.getFileId(file, this.generateFileId);
+        },
+        _getFileName: function (file, defaultValue) {
+            var self = this, fileName = $h.getFileName(file);
+            return fileName ? self.slug(fileName) : defaultValue;
+        },
+        _getFileNames: function (skipNull) {
+            var self = this;
+            return self.filenames.filter(function (n) {
+                return (skipNull ? n !== undefined : n !== undefined && n !== null);
+            });
+        },
+        _setPreviewError: function ($thumb, keepFile) {
+            var self = this, removeFrame = self.removeFromPreviewOnError && !self.retryErrorUploads;
+            if (!keepFile || removeFrame) {
+                self.fileManager.remove($thumb);
+            }
+            if (!self.showPreview) {
+                return;
+            }
+            if (removeFrame) {
+                $thumb.remove();
+                return;
+            } else {
+                self._setThumbStatus($thumb, 'Error');
+            }
+            self._refreshUploadButton($thumb);
+        },
+        _refreshUploadButton: function ($thumb) {
+            var self = this, $btn = $thumb.find('.kv-file-upload'), cfg = self.fileActionSettings,
+                icon = cfg.uploadIcon, title = cfg.uploadTitle;
+            if (!$btn.length) {
+                return;
+            }
+            if (self.retryErrorUploads) {
+                icon = cfg.uploadRetryIcon;
+                title = cfg.uploadRetryTitle;
+            }
+            $btn.attr('title', title);
+            $h.setHtml($btn, icon);
+        },
+        _isValidSize: function (size, type, $image, $thumb, filename, params) {
+            var self = this, msg, dim, $img, tag = size === 'Small' ? 'min' : 'max', limit = self[tag + 'Image' + type];
+            if ($h.isEmpty(limit) || !$image.length) {
+                return true;
+            }
+            $img = $image[0];
+            dim = (type === 'Width') ? $img.naturalWidth || $img.width : $img.naturalHeight || $img.height;
+            if (size === 'Small' ? dim >= limit : dim <= limit) {
+                return true;
+            }
+            msg = self['msgImage' + type + size] || 'Image "{name}" has a size validation error (limit "{size}").';
+            self._showFileError(msg.setTokens({'name': filename, 'size': limit, 'dimension': dim}), params);
+            self._setPreviewError($thumb);
+            self.fileManager.remove($thumb);
+            self._clearFileInput();
+            return false;
+        },
+        _getExifObj: function (data) {
+            var self = this, exifObj, error = $h.logMessages.exifWarning;
+            if (data.slice(0, 23) !== 'data:image/jpeg;base64,' && data.slice(0, 22) !== 'data:image/jpg;base64,') {
+                exifObj = null;
+                return;
+            }
+            try {
+                exifObj = window.piexif ? window.piexif.load(data) : null;
+            } catch (err) {
+                exifObj = null;
+                error = err && err.message || '';
+            }
+            if (!exifObj && self.showExifErrorLog) {
+                self._log($h.logMessages.badExifParser, {details: error});
+            }
+            return exifObj;
+        },
+        setImageOrientation: function ($img, $zoomImg, value, $thumb) {
+            var self = this, invalidImg = !$img || !$img.length, invalidZoomImg = !$zoomImg || !$zoomImg.length, $mark,
+                isHidden = false, $div, zoomOnly = invalidImg && $thumb && $thumb.attr('data-template') === 'image', ev;
+            if (invalidImg && invalidZoomImg) {
+                return;
+            }
+            ev = 'load.fileinputimageorient';
+            if (zoomOnly) {
+                $img = $zoomImg;
+                $zoomImg = null;
+                $img.css(self.previewSettings.image);
+                $div = $(document.createElement('div')).appendTo($thumb.find('.kv-file-content'));
+                $mark = $(document.createElement('span')).insertBefore($img);
+                $img.css('visibility', 'hidden').removeClass('file-zoom-detail').appendTo($div);
+            } else {
+                isHidden = !$img.is(':visible');
+            }
+            $img.off(ev).on(ev, function () {
+                if (isHidden) {
+                    self.$preview.removeClass('hide-content');
+                    $thumb.find('.kv-file-content').css('visibility', 'hidden');
+                }
+                var img = $img[0], zoomImg = $zoomImg && $zoomImg.length ? $zoomImg[0] : null,
+                    h = img.offsetHeight, w = img.offsetWidth, r = $h.getRotation(value);
+                if (isHidden) {
+                    $thumb.find('.kv-file-content').css('visibility', 'visible');
+                    self.$preview.addClass('hide-content');
+                }
+                $img.data('orientation', value);
+                if (zoomImg) {
+                    $zoomImg.data('orientation', value);
+                }
+                if (value < 5) {
+                    $h.setTransform(img, r);
+                    $h.setTransform(zoomImg, r);
+                    return;
+                }
+                var offsetAngle = Math.atan(w / h), origFactor = Math.sqrt(Math.pow(h, 2) + Math.pow(w, 2)),
+                    scale = !origFactor ? 1 : (h / Math.cos(Math.PI / 2 + offsetAngle)) / origFactor,
+                    s = ' scale(' + Math.abs(scale) + ')';
+                $h.setTransform(img, r + s);
+                $h.setTransform(zoomImg, r + s);
+                if (zoomOnly) {
+                    $img.css('visibility', 'visible').insertAfter($mark).addClass('file-zoom-detail');
+                    $mark.remove();
+                    $div.remove();
+                }
+            });
+        },
+        _validateImageOrientation: function ($img, file, previewId, fileId, caption, ftype, fsize, iData) {
+            var self = this, exifObj = null, value, autoOrientImage = self.autoOrientImage, selector;
+            exifObj = self._getExifObj(iData);
+            if (self.canOrientImage) {
+                $img.css('image-orientation', (autoOrientImage ? 'from-image' : 'none'));
+                self._validateImage(previewId, fileId, caption, ftype, fsize, iData, exifObj);
+                return;
+            }
+            selector = $h.getZoomSelector(previewId, ' img');
+            value = exifObj ? exifObj['0th'][piexif.ImageIFD.Orientation] : null; // jshint ignore:line
+            if (!value) {
+                self._validateImage(previewId, fileId, caption, ftype, fsize, iData, exifObj);
+                return;
+            }
+            self.setImageOrientation($img, $(selector), value, self._getFrame(previewId));
+            self._raise('fileimageoriented', {'$img': $img, 'file': file});
+            self._validateImage(previewId, fileId, caption, ftype, fsize, iData, exifObj);
+        },
+        _validateImage: function (previewId, fileId, fname, ftype, fsize, iData, exifObj) {
+            var self = this, $preview = self.$preview, params, w1, w2, $thumb = self._getFrame(previewId),
+                i = $thumb.attr('data-fileindex'), $img = $thumb.find('img');
+            fname = fname || 'Untitled';
+            $img.one('load', function () {
+                if ($img.data('validated')) {
+                    return;
+                }
+                $img.data('validated', true);
+                w1 = $thumb.width();
+                w2 = $preview.width();
+                if (w1 > w2) {
+                    $img.css('width', '100%');
+                }
+                params = {ind: i, id: previewId, fileId: fileId};
+                setTimeout(function () {
+                    var isValidWidth, isValidHeight;
+                    isValidWidth = self._isValidSize('Small', 'Width', $img, $thumb, fname, params);
+                    isValidHeight = self._isValidSize('Small', 'Height', $img, $thumb, fname, params);
+                    if (!self.resizeImage) {
+                        isValidWidth = isValidWidth && self._isValidSize('Large', 'Width', $img, $thumb, fname, params);
+                        isValidHeight = isValidHeight && self._isValidSize('Large', 'Height', $img, $thumb, fname, params);
+                    }
+                    self._raise('fileimageloaded', [previewId]);
+                    $thumb.data('exif', exifObj);
+                    if (isValidWidth && isValidHeight) {
+                        self.fileManager.addImage(fileId, {
+                            ind: i,
+                            img: $img,
+                            thumb: $thumb,
+                            pid: previewId,
+                            typ: ftype,
+                            siz: fsize,
+                            validated: false,
+                            imgData: iData,
+                            exifObj: exifObj
+                        });
+                        self._validateAllImages();
+                    }
+                }, self.processDelay);
+            }).one('error', function () {
+                self._raise('fileimageloaderror', [previewId]);
+            });
+        },
+        _validateAllImages: function () {
+            var self = this, counter = {val: 0}, numImgs = self.fileManager.getImageCount(), fsize,
+                minSize = self.resizeIfSizeMoreThan;
+            if (numImgs !== self.fileManager.totalImages) {
+                return;
+            }
+            self._raise('fileimagesloaded');
+            if (!self.resizeImage) {
+                return;
+            }
+            $.each(self.fileManager.loadedImages, function (id, config) {
+                if (!config.validated) {
+                    fsize = config.siz;
+                    if (fsize && fsize > minSize * self.bytesToKB) {
+                        self._getResizedImage(id, config, counter, numImgs);
+                    }
+                    config.validated = true;
+                }
+            });
+        },
+        _getResizedImage: function (id, config, counter, numImgs) {
+            var self = this, img = $(config.img)[0], width = img.naturalWidth, height = img.naturalHeight, blob,
+                ratio = 1, maxWidth = self.maxImageWidth || width, maxHeight = self.maxImageHeight || height,
+                isValidImage = !!(width && height), chkWidth, chkHeight, canvas = self.imageCanvas, dataURI,
+                context = self.imageCanvasContext, type = config.typ, pid = config.pid, ind = config.ind,
+                $thumb = config.thumb, throwError, msg, exifObj = config.exifObj, exifStr, file, params, evParams;
+            throwError = function (msg, params, ev) {
+                if (self.isAjaxUpload) {
+                    self._showFileError(msg, params, ev);
+                } else {
+                    self._showError(msg, params, ev);
+                }
+                self._setPreviewError($thumb);
+            };
+            file = self.fileManager.getFile(id);
+            params = {id: pid, 'index': ind, fileId: id};
+            evParams = [id, pid, ind];
+            if (!file || !isValidImage || (width <= maxWidth && height <= maxHeight)) {
+                if (isValidImage && file) {
+                    self._raise('fileimageresized', evParams);
+                }
+                counter.val++;
+                if (counter.val === numImgs) {
+                    self._raise('fileimagesresized');
+                }
+                if (!isValidImage) {
+                    throwError(self.msgImageResizeError, params, 'fileimageresizeerror');
+                    return;
+                }
+            }
+            type = type || self.resizeDefaultImageType;
+            chkWidth = width > maxWidth;
+            chkHeight = height > maxHeight;
+            if (self.resizePreference === 'width') {
+                ratio = chkWidth ? maxWidth / width : (chkHeight ? maxHeight / height : 1);
+            } else {
+                ratio = chkHeight ? maxHeight / height : (chkWidth ? maxWidth / width : 1);
+            }
+            self._resetCanvas();
+            width *= ratio;
+            height *= ratio;
+            canvas.width = width;
+            canvas.height = height;
+            try {
+                context.drawImage(img, 0, 0, width, height);
+                dataURI = canvas.toDataURL(type, self.resizeQuality);
+                if (exifObj) {
+                    exifStr = window.piexif.dump(exifObj);
+                    dataURI = window.piexif.insert(exifStr, dataURI);
+                }
+                blob = $h.dataURI2Blob(dataURI);
+                self.fileManager.setFile(id, blob);
+                self._raise('fileimageresized', evParams);
+                counter.val++;
+                if (counter.val === numImgs) {
+                    self._raise('fileimagesresized', [undefined, undefined]);
+                }
+                if (!(blob instanceof Blob)) {
+                    throwError(self.msgImageResizeError, params, 'fileimageresizeerror');
+                }
+            } catch (err) {
+                counter.val++;
+                if (counter.val === numImgs) {
+                    self._raise('fileimagesresized', [undefined, undefined]);
+                }
+                msg = self.msgImageResizeException.replace('{errors}', err.message);
+                throwError(msg, params, 'fileimageresizeexception');
+            }
+        },
+        _showProgress: function () {
+            var self = this;
+            if (self.$progress && self.$progress.length) {
+                self.$progress.show();
+            }
+        },
+        _hideProgress: function () {
+            var self = this;
+            if (self.$progress && self.$progress.length) {
+                self.$progress.hide();
+            }
+        },
+        _initBrowse: function ($container) {
+            var self = this, $el = self.$element;
+            if (self.showBrowse) {
+                self.$btnFile = $container.find('.btn-file').append($el);
+            } else {
+                $el.appendTo($container).attr('tabindex', -1);
+                $h.addCss($el, 'file-no-browse');
+            }
+        },
+        _initClickable: function () {
+            var self = this, $zone, $tmpZone;
+            if (!self.isClickable) {
+                return;
+            }
+            $zone = self.$dropZone;
+            if (!self.isAjaxUpload) {
+                $tmpZone = self.$preview.find('.file-default-preview');
+                if ($tmpZone.length) {
+                    $zone = $tmpZone;
+                }
+            }
+
+            $h.addCss($zone, 'clickable');
+            $zone.attr('tabindex', -1);
+            self._handler($zone, 'click', function (e) {
+                var $tar = $(e.target);
+                if (!self.$errorContainer.is(':visible') && (!$tar.parents(
+                    '.file-preview-thumbnails').length || $tar.parents(
+                    '.file-default-preview').length)) {
+                    self.$element.data('zoneClicked', true).trigger('click');
+                    $zone.blur();
+                }
+            });
+        },
+        _initCaption: function () {
+            var self = this, cap = self.initialCaption || '';
+            if (self.overwriteInitial || $h.isEmpty(cap)) {
+                self.$caption.val('');
+                return false;
+            }
+            self._setCaption(cap);
+            return true;
+        },
+        _setCaption: function (content, isError) {
+            var self = this, title, out, icon, n, cap, file;
+            if (!self.$caption.length) {
+                return;
+            }
+            self.$captionContainer.removeClass('icon-visible');
+            if (isError) {
+                title = $('<div>' + self.msgValidationError + '</div>').text();
+                n = self.fileManager.count();
+                if (n) {
+                    file = self.fileManager.getFirstFile();
+                    cap = n === 1 && file ? file.nameFmt : self._getMsgSelected(n);
+                } else {
+                    cap = self._getMsgSelected(self.msgNo);
+                }
+                out = $h.isEmpty(content) ? cap : content;
+                icon = '<span class="' + self.msgValidationErrorClass + '">' + self.msgValidationErrorIcon + '</span>';
+            } else {
+                if ($h.isEmpty(content)) {
+                    self.$caption.attr('title', '');
+                    return;
+                }
+                title = $('<div>' + content + '</div>').text();
+                out = title;
+                icon = self._getLayoutTemplate('fileIcon');
+            }
+            self.$captionContainer.addClass('icon-visible');
+            self.$caption.attr('title', title).val(out);
+            $h.setHtml(self.$captionIcon, icon);
+        },
+        _createContainer: function () {
+            var self = this, attribs = {'class': 'file-input file-input-new' + (self.rtl ? ' kv-rtl' : '')},
+                $container = $h.createElement($h.cspBuffer.stash(self._renderMain()));
+            $h.cspBuffer.apply($container);
+            $container.insertBefore(self.$element).attr(attribs);
+            self._initBrowse($container);
+            if (self.theme) {
+                $container.addClass('theme-' + self.theme);
+            }
+            return $container;
+        },
+        _refreshContainer: function () {
+            var self = this, $container = self.$container, $el = self.$element;
+            $el.insertAfter($container);
+            $h.setHtml($container, self._renderMain());
+            self._initBrowse($container);
+            self._validateDisabled();
+        },
+        _validateDisabled: function () {
+            var self = this;
+            self.$caption.attr({readonly: self.isDisabled});
+        },
+        _setTabIndex: function (type, html) {
+            var self = this, index = self.tabIndexConfig[type];
+            return html.setTokens({
+                tabIndexConfig: index === undefined || index === null ? '' : 'tabindex="' + index + '"'
+            });
+        },
+        _renderMain: function () {
+            var self = this,
+                dropCss = self.dropZoneEnabled ? ' file-drop-zone' : 'file-drop-disabled',
+                close = !self.showClose ? '' : self._getLayoutTemplate('close'),
+                preview = !self.showPreview ? '' : self._getLayoutTemplate('preview')
+                    .setTokens({'class': self.previewClass, 'dropClass': dropCss}),
+                css = self.isDisabled ? self.captionClass + ' file-caption-disabled' : self.captionClass,
+                caption = self.captionTemplate.setTokens({'class': css + ' kv-fileinput-caption'});
+            caption = self._setTabIndex('caption', caption);
+            return self.mainTemplate.setTokens({
+                'class': self.mainClass + (!self.showBrowse && self.showCaption ? ' no-browse' : ''),
+                'inputGroupClass': self.inputGroupClass,
+                'preview': preview,
+                'close': close,
+                'caption': caption,
+                'upload': self._renderButton('upload'),
+                'remove': self._renderButton('remove'),
+                'cancel': self._renderButton('cancel'),
+                'pause': self._renderButton('pause'),
+                'browse': self._renderButton('browse')
+            });
+
+        },
+        _renderButton: function (type) {
+            var self = this, tmplt = self._getLayoutTemplate('btnDefault'), css = self[type + 'Class'],
+                title = self[type + 'Title'], icon = self[type + 'Icon'], label = self[type + 'Label'],
+                status = self.isDisabled ? ' disabled' : '', btnType = 'button';
+            switch (type) {
+                case 'remove':
+                    if (!self.showRemove) {
+                        return '';
+                    }
+                    break;
+                case 'cancel':
+                    if (!self.showCancel) {
+                        return '';
+                    }
+                    css += ' kv-hidden';
+                    break;
+                case 'pause':
+                    if (!self.showPause) {
+                        return '';
+                    }
+                    css += ' kv-hidden';
+                    break;
+                case 'upload':
+                    if (!self.showUpload) {
+                        return '';
+                    }
+                    if (self.isAjaxUpload && !self.isDisabled) {
+                        tmplt = self._getLayoutTemplate('btnLink').replace('{href}', self.uploadUrl);
+                    } else {
+                        btnType = 'submit';
+                    }
+                    break;
+                case 'browse':
+                    if (!self.showBrowse) {
+                        return '';
+                    }
+                    tmplt = self._getLayoutTemplate('btnBrowse');
+                    break;
+                default:
+                    return '';
+            }
+            tmplt = self._setTabIndex(type, tmplt);
+
+            css += type === 'browse' ? ' btn-file' : ' fileinput-' + type + ' fileinput-' + type + '-button';
+            if (!$h.isEmpty(label)) {
+                label = ' <span class="' + self.buttonLabelClass + '">' + label + '</span>';
+            }
+            return tmplt.setTokens({
+                'type': btnType, 'css': css, 'title': title, 'status': status, 'icon': icon, 'label': label
+            });
+        },
+        _renderThumbProgress: function () {
+            var self = this;
+            return '<div class="file-thumb-progress kv-hidden">' +
+                self.progressInfoTemplate.setTokens({percent: 101, status: self.msgUploadBegin, stats: ''}) +
+                '</div>';
+        },
+        _renderFileFooter: function (cat, caption, size, width, isError) {
+            var self = this, config = self.fileActionSettings, rem = config.showRemove, drg = config.showDrag,
+                upl = config.showUpload, rot = config.showRotate, zoom = config.showZoom, out, params,
+                template = self._getLayoutTemplate('footer'), tInd = self._getLayoutTemplate('indicator'),
+                ind = isError ? config.indicatorError : config.indicatorNew,
+                title = isError ? config.indicatorErrorTitle : config.indicatorNewTitle,
+                indicator = tInd.setTokens({'indicator': ind, 'indicatorTitle': title});
+            size = self._getSize(size);
+            params = {type: cat, caption: caption, size: size, width: width, progress: '', indicator: indicator};
+            if (self.isAjaxUpload) {
+                params.progress = self._renderThumbProgress();
+                params.actions = self._renderFileActions(params, upl, false, rem, rot, zoom, drg, false, false, false);
+            } else {
+                params.actions = self._renderFileActions(params, false, false, false, false, zoom, drg, false, false, false);
+            }
+            out = template.setTokens(params);
+            out = $h.replaceTags(out, self.previewThumbTags);
+            return out;
+        },
+        _renderFileActions: function (
+            cfg,
+            showUpl,
+            showDwn,
+            showDel,
+            showRot,
+            showZoom,
+            showDrag,
+            disabled,
+            url,
+            key,
+            isInit,
+            dUrl,
+            dFile
+        ) {
+            var self = this;
+            if (!cfg.type && isInit) {
+                cfg.type = 'image';
+            }
+            if (self.enableResumableUpload) {
+                showUpl = false;
+            } else {
+                if (typeof showUpl === 'function') {
+                    showUpl = showUpl(cfg);
+                }
+            }
+            if (typeof showDwn === 'function') {
+                showDwn = showDwn(cfg);
+            }
+            if (typeof showDel === 'function') {
+                showDel = showDel(cfg);
+            }
+            if (typeof showZoom === 'function') {
+                showZoom = showZoom(cfg);
+            }
+            if (typeof showDrag === 'function') {
+                showDrag = showDrag(cfg);
+            }
+            if (typeof showRot === 'function') {
+                showRot = showRot(cfg);
+            }
+            if (!showUpl && !showDwn && !showDel && !showRot && !showZoom && !showDrag) {
+                return '';
+            }
+            var vUrl = url === false ? '' : ' data-url="' + url + '"', btnZoom = '', btnDrag = '', btnRotate = '', css,
+                vKey = key === false ? '' : ' data-key="' + key + '"', btnDelete = '', btnUpload = '', btnDownload = '',
+                template = self._getLayoutTemplate('actions'), config = self.fileActionSettings,
+                otherButtons = self.otherActionButtons.setTokens({'dataKey': vKey, 'key': key}),
+                removeClass = disabled ? config.removeClass + ' disabled' : config.removeClass;
+            if (showDel) {
+                btnDelete = self._getLayoutTemplate('actionDelete').setTokens({
+                    'removeClass': removeClass,
+                    'removeIcon': config.removeIcon,
+                    'removeTitle': config.removeTitle,
+                    'dataUrl': vUrl,
+                    'dataKey': vKey,
+                    'key': key
+                });
+            }
+            if (showRot) {
+                btnRotate = self._getLayoutTemplate('actionRotate').setTokens({
+                    'rotateClass': config.rotateClass,
+                    'rotateIcon': config.rotateIcon,
+                    'rotateTitle': config.rotateTitle
+                });
+            }
+            if (showUpl) {
+                btnUpload = self._getLayoutTemplate('actionUpload').setTokens({
+                    'uploadClass': config.uploadClass,
+                    'uploadIcon': config.uploadIcon,
+                    'uploadTitle': config.uploadTitle
+                });
+            }
+            if (showDwn) {
+                btnDownload = self._getLayoutTemplate('actionDownload').setTokens({
+                    'downloadClass': config.downloadClass,
+                    'downloadIcon': config.downloadIcon,
+                    'downloadTitle': config.downloadTitle,
+                    'downloadUrl': dUrl || self.initialPreviewDownloadUrl
+                });
+                btnDownload = btnDownload.setTokens({'filename': dFile, 'key': key});
+            }
+            if (showZoom) {
+                btnZoom = self._getLayoutTemplate('actionZoom').setTokens({
+                    'zoomClass': config.zoomClass,
+                    'zoomIcon': config.zoomIcon,
+                    'zoomTitle': config.zoomTitle
+                });
+            }
+            if (showDrag && isInit) {
+                css = 'drag-handle-init ' + config.dragClass;
+                btnDrag = self._getLayoutTemplate('actionDrag').setTokens({
+                    'dragClass': css,
+                    'dragTitle': config.dragTitle,
+                    'dragIcon': config.dragIcon
+                });
+            }
+            return template.setTokens({
+                'delete': btnDelete,
+                'upload': btnUpload,
+                'download': btnDownload,
+                'rotate': btnRotate,
+                'zoom': btnZoom,
+                'drag': btnDrag,
+                'other': otherButtons
+            });
+        },
+        _browse: function (e) {
+            var self = this;
+            if (e && e.isDefaultPrevented() || !self._raise('filebrowse')) {
+                return;
+            }
+            if (self.isError && !self.isAjaxUpload) {
+                self.clear();
+            }
+            if (self.focusCaptionOnBrowse) {
+                self.$captionContainer.focus();
+            }
+        },
+        _change: function (e) {
+            var self = this;
+            $(document.body).off('focusin.fileinput focusout.fileinput');
+            if (self.changeTriggered) {
+                self._toggleLoading('hide');
+                return;
+            }
+            self._toggleLoading('show');
+            var $el = self.$element, isDragDrop = arguments.length > 1, isAjaxUpload = self.isAjaxUpload,
+                tfiles, files = isDragDrop ? arguments[1] : $el[0].files, ctr = self.fileManager.count(),
+                total, initCount, len, isSingleUpl = $h.isEmpty($el.attr('multiple')),
+                maxCount = !isAjaxUpload && isSingleUpl ? 1 : self.maxFileCount, maxTotCount = self.maxTotalFileCount,
+                inclAll = maxTotCount > 0 && maxTotCount > maxCount, flagSingle = (isSingleUpl && ctr > 0),
+                throwError = function (mesg, file, previewId, index) {
+                    var p1 = $.extend(true, {}, self._getOutData(null, {}, {}, files), {id: previewId, index: index}),
+                        p2 = {id: previewId, index: index, file: file, files: files};
+                    self.isPersistentError = true;
+                    self._toggleLoading('hide');
+                    return isAjaxUpload ? self._showFileError(mesg, p1) : self._showError(mesg, p2);
+                },
+                maxCountCheck = function (n, m, all) {
+                    var msg = all ? self.msgTotalFilesTooMany : self.msgFilesTooMany;
+                    msg = msg.replace('{m}', m).replace('{n}', n);
+                    self.isError = throwError(msg, null, null, null);
+                    self.$captionContainer.removeClass('icon-visible');
+                    self._setCaption('', true);
+                    self.$container.removeClass('file-input-new file-input-ajax-new');
+                };
+            self.reader = null;
+            self._resetUpload();
+            self._hideFileIcon();
+            if (self.dropZoneEnabled) {
+                self.$container.find('.file-drop-zone .' + self.dropZoneTitleClass).remove();
+            }
+            if (!isAjaxUpload) {
+                if (e.target && e.target.files === undefined) {
+                    files = e.target.value ? [{name: e.target.value.replace(/^.+\\/, '')}] : [];
+                } else {
+                    files = e.target.files || {};
+                }
+            }
+            tfiles = files;
+            if ($h.isEmpty(tfiles) || tfiles.length === 0) {
+                if (!isAjaxUpload) {
+                    self.clear();
+                }
+                self._raise('fileselectnone');
+                return;
+            }
+            self._resetErrors();
+            len = tfiles.length;
+            initCount = isAjaxUpload ? (self.fileManager.count() + len) : len;
+            total = self._getFileCount(initCount, inclAll ? false : undefined);
+            if (maxCount > 0 && total > maxCount) {
+                if (!self.autoReplace || len > maxCount) {
+                    maxCountCheck((self.autoReplace && len > maxCount ? len : total), maxCount);
+                    return;
+                }
+                if (total > maxCount) {
+                    self._resetPreviewThumbs(isAjaxUpload);
+                }
+
+            } else {
+                if (inclAll) {
+                    total = self._getFileCount(initCount, true);
+                    if (maxTotCount > 0 && total > maxTotCount) {
+                        if (!self.autoReplace || len > maxCount) {
+                            maxCountCheck((self.autoReplace && len > maxTotCount ? len : total), maxTotCount, true);
+                            return;
+                        }
+                        if (total > maxCount) {
+                            self._resetPreviewThumbs(isAjaxUpload);
+                        }
+                    }
+                }
+                if (!isAjaxUpload || flagSingle) {
+                    self._resetPreviewThumbs(false);
+                    if (flagSingle) {
+                        self.clearFileStack();
+                    }
+                } else {
+                    if (isAjaxUpload && ctr === 0 && (!self.previewCache.count(true) || self.overwriteInitial)) {
+                        self._resetPreviewThumbs(true);
+                    }
+                }
+            }
+            if (self.autoReplace) {
+                self._getThumbs().each(function () {
+                    var $thumb = $(this);
+                    if ($thumb.hasClass('file-preview-success') || $thumb.hasClass('file-preview-error')) {
+                        $thumb.remove();
+                    }
+                });
+            }
+            self.readFiles(tfiles);
+            self._toggleLoading('hide');
+        },
+        _abort: function (params) {
+            var self = this, data;
+            if (self.ajaxAborted && typeof self.ajaxAborted === 'object' && self.ajaxAborted.message !== undefined) {
+                data = $.extend(true, {}, self._getOutData(null), params);
+                data.abortData = self.ajaxAborted.data || {};
+                data.abortMessage = self.ajaxAborted.message;
+                self._setProgress(101, self.$progress, self.msgCancelled);
+                self._showFileError(self.ajaxAborted.message, data, 'filecustomerror');
+                self.cancel();
+                self.unlock();
+                return true;
+            }
+            return !!self.ajaxAborted;
+        },
+        _resetFileStack: function () {
+            var self = this, i = 0;
+            self._getThumbs().each(function () {
+                var $thumb = $(this), ind = $thumb.attr('data-fileindex'), pid = $thumb.attr('id');
+                if (ind === '-1' || ind === -1) {
+                    return;
+                }
+                if (!self._getThumbFile($thumb)) {
+                    $thumb.attr({'data-fileindex': i});
+                    i++;
+                } else {
+                    $thumb.attr({'data-fileindex': '-1'});
+                }
+                self._getZoom(pid).attr({
+                    'data-fileindex': $thumb.attr('data-fileindex')
+                });
+            });
+        },
+        _isFileSelectionValid: function (cnt) {
+            var self = this;
+            cnt = cnt || 0;
+            if (self.required && !self.getFilesCount()) {
+                self.$errorContainer.html('');
+                self._showFileError(self.msgFileRequired);
+                return false;
+            }
+            if (self.minFileCount > 0 && self._getFileCount(cnt) < self.minFileCount) {
+                self._noFilesError({});
+                return false;
+            }
+            return true;
+        },
+        _canPreview: function (file) {
+            var self = this;
+            if (!file || !self.showPreview || !self.$preview || !self.$preview.length) {
+                return false;
+            }
+            var name = file.name || '', type = file.type || '', size = (file.size || 0) / self.bytesToKB,
+                cat = self._parseFileType(type, name), allowedTypes, allowedMimes, allowedExts, skipPreview,
+                types = self.allowedPreviewTypes, mimes = self.allowedPreviewMimeTypes,
+                exts = self.allowedPreviewExtensions || [], dTypes = self.disabledPreviewTypes,
+                dMimes = self.disabledPreviewMimeTypes, dExts = self.disabledPreviewExtensions || [],
+                maxSize = self.maxFilePreviewSize && parseFloat(self.maxFilePreviewSize) || 0,
+                expAllExt = new RegExp('\\.(' + exts.join('|') + ')$', 'i'),
+                expDisExt = new RegExp('\\.(' + dExts.join('|') + ')$', 'i');
+            allowedTypes = !types || types.indexOf(cat) !== -1;
+            allowedMimes = !mimes || mimes.indexOf(type) !== -1;
+            allowedExts = !exts.length || $h.compare(name, expAllExt);
+            skipPreview = (dTypes && dTypes.indexOf(cat) !== -1) || (dMimes && dMimes.indexOf(type) !== -1) ||
+                (dExts.length && $h.compare(name, expDisExt)) || (maxSize && !isNaN(maxSize) && size > maxSize);
+            return !skipPreview && (allowedTypes || allowedMimes || allowedExts);
+        },
+        addToStack: function (file, id) {
+            var self = this;
+            self.stackIsUpdating = true;
+            self.fileManager.add(file, id);
+            self._refreshPreview();
+            self.stackIsUpdating = false;
+        },
+        clearFileStack: function () {
+            var self = this;
+            self.fileManager.clear();
+            self._initResumableUpload();
+            if (self.enableResumableUpload) {
+                if (self.showPause === null) {
+                    self.showPause = true;
+                }
+                if (self.showCancel === null) {
+                    self.showCancel = false;
+                }
+            } else {
+                self.showPause = false;
+                if (self.showCancel === null) {
+                    self.showCancel = true;
+                }
+            }
+            return self.$element;
+        },
+        getFileStack: function () {
+            return this.fileManager.stack;
+        },
+        getFileList: function () {
+            return this.fileManager.list();
+        },
+        getFilesSize: function () {
+            return this.fileManager.getTotalSize();
+        },
+        getFilesCount: function (includeInitial) {
+            var self = this, len = self.isAjaxUpload ? self.fileManager.count() : self._inputFileCount();
+            if (includeInitial) {
+                len += self.previewCache.count(true);
+            }
+            return self._getFileCount(len);
+        },
+        _initCapStatus: function (status) {
+            var self = this, $cap = self.$caption;
+            $cap.removeClass('is-valid file-processing');
+            if (!status) {
+                return;
+            }
+            if (status === 'processing') {
+                $cap.addClass('file-processing');
+            } else {
+                $cap.addClass('is-valid');
+            }
+        },
+        _toggleLoading: function (type) {
+            var self = this;
+            self.$previewStatus.html(type === 'hide' ? '' : self.msgProcessing);
+            self.$container.removeClass('file-thumb-loading');
+            self._initCapStatus(type === 'hide' ? '' : 'processing');
+            if (type !== 'hide') {
+                if (self.dropZoneEnabled) {
+                    self.$container.find('.file-drop-zone .' + self.dropZoneTitleClass).remove();
+                }
+                self.$container.addClass('file-thumb-loading');
+            }
+        },
+        _initFileSelected: function () {
+            var self = this, $el = self.$element, $body = $(document.body), ev = 'focusin.fileinput focusout.fileinput';
+            if ($body.length) {
+                $body.off(ev).on('focusout.fileinput', function () {
+                    self._toggleLoading('show');
+                }).on('focusin.fileinput', function () {
+                    setTimeout(function () {
+                        if (!$el.val()) {
+                            self._setFileDropZoneTitle();
+                        }
+                        $body.off(ev);
+                        self._toggleLoading('hide');
+                    }, 2500);
+                });
+            } else {
+                self._toggleLoading('hide');
+            }
+        },
+        readFiles: function (files) {
+            this.reader = new FileReader();
+            var self = this, reader = self.reader, $container = self.$previewContainer,
+                $status = self.$previewStatus, msgLoading = self.msgLoading, msgProgress = self.msgProgress,
+                previewInitId = self.previewInitId, numFiles = files.length, settings = self.fileTypeSettings,
+                readFile, fileTypes = self.allowedFileTypes, typLen = fileTypes ? fileTypes.length : 0,
+                fileExt = self.allowedFileExtensions, strExt = $h.isEmpty(fileExt) ? '' : fileExt.join(', '),
+                throwError = function (msg, file, previewId, index, fileId) {
+                    var $thumb, p1 = $.extend(true, {}, self._getOutData(null, {}, {}, files),
+                            {id: previewId, index: index, fileId: fileId}),
+                        p2 = {id: previewId, index: index, fileId: fileId, file: file, files: files};
+                    self._previewDefault(file, true);
+                    $thumb = self._getFrame(previewId, true);
+                    self._toggleLoading('hide');
+                    if (self.isAjaxUpload) {
+                        setTimeout(function () {
+                            readFile(index + 1);
+                        }, self.processDelay);
+                    } else {
+                        self.unlock();
+                        numFiles = 0;
+                    }
+                    if (self.removeFromPreviewOnError && $thumb.length) {
+                        $thumb.remove();
+                    } else {
+                        self._initFileActions();
+                        $thumb.find('.kv-file-upload').remove();
+                    }
+                    self.isPersistentError = true;
+                    self.isError = self.isAjaxUpload ? self._showFileError(msg, p1) : self._showError(msg, p2);
+                    self._updateFileDetails(numFiles);
+                };
+            self.fileManager.clearImages();
+            $.each(files, function (key, file) {
+                var func = self.fileTypeSettings.image;
+                if (func && func(file.type)) {
+                    self.fileManager.totalImages++;
+                }
+            });
+            readFile = function (i) {
+                var $error = self.$errorContainer, errors, fm = self.fileManager;
+                if (i >= numFiles) {
+                    self.unlock();
+                    if (self.duplicateErrors.length) {
+                        errors = '<li>' + self.duplicateErrors.join('</li><li>') + '</li>';
+                        if ($error.find('ul').length === 0) {
+                            $h.setHtml($error, self.errorCloseButton + '<ul>' + errors + '</ul>');
+                        } else {
+                            $error.find('ul').append(errors);
+                        }
+                        $error.fadeIn(self.fadeDelay);
+                        self._handler($error.find('.kv-error-close'), 'click', function () {
+                            $error.fadeOut(self.fadeDelay);
+                        });
+                        self.duplicateErrors = [];
+                    }
+                    if (self.isAjaxUpload) {
+                        self._raise('filebatchselected', [fm.stack]);
+                        if (fm.count() === 0 && !self.isError) {
+                            self.reset();
+                        }
+                    } else {
+                        self._raise('filebatchselected', [files]);
+                    }
+                    $container.removeClass('file-thumb-loading');
+                    self._initCapStatus('valid');
+                    $status.html('');
+                    return;
+                }
+                self.lock(true);
+                var file = files[i], id, previewId, fileProcessed,
+                    fSize = (file && file.size || 0), sizeHuman = self._getSize(fSize, true), j, msg,
+                    fnImage = settings.image, chk, typ, typ1, typ2, caption, fileSize = fSize / self.bytesToKB,
+                    fileExtExpr = '', previewData, fileCount = 0, strTypes = '', fileId, canLoad,
+                    fileReaderAborted = false, func, knownTypes = 0, isImage, processFileLoaded, initFileData;
+                initFileData = function (dataSource) {
+                    dataSource = dataSource || file;
+                    id = fileId = self._getFileId(file);
+                    previewId = previewInitId + '-' + id;
+                    previewData = $h.createObjectURL(dataSource);
+                    caption = self._getFileName(file, '');
+                };
+                processFileLoaded = function () {
+                    var isImageResized = !!fm.loadedImages[id], msg = msgProgress.setTokens({
+                        'index': i + 1,
+                        'files': numFiles,
+                        'percent': 50,
+                        'name': caption
+                    });
+                    setTimeout(function () {
+                        $status.html(msg);
+                        self._updateFileDetails(numFiles);
+                        if (self.getFilesCount(true) > 0 && self.getFrames(':visible')) {
+                            self.$dropZone.find('.' + self.dropZoneTitleClass).remove();
+                        }
+                        readFile(i + 1);
+                    }, self.processDelay);
+                    if (self._raise('fileloaded', [file, previewId, id, i, reader]) && self.isAjaxUpload) {
+                        if (!isImageResized) {
+                            fm.add(file);
+                        }
+                    } else {
+                        if (isImageResized) {
+                            fm.removeFile(id);
+                        }
+                    }
+                };
+                if (!file) {
+                    return;
+                }
+                initFileData();
+
+                if (typLen > 0) {
+                    for (j = 0; j < typLen; j++) {
+                        typ1 = fileTypes[j];
+                        typ2 = self.msgFileTypes[typ1] || typ1;
+                        strTypes += j === 0 ? typ2 : ', ' + typ2;
+                    }
+                }
+                if (caption === false) {
+                    readFile(i + 1);
+                    return;
+                }
+                if (caption.length === 0) {
+                    msg = self.msgInvalidFileName.replace('{name}', $h.htmlEncode($h.getFileName(file), '[unknown]'));
+                    throwError(msg, file, previewId, i, fileId);
+                    return;
+                }
+                if (!$h.isEmpty(fileExt)) {
+                    fileExtExpr = new RegExp('\\.(' + fileExt.join('|') + ')$', 'i');
+                }
+                if (self.isAjaxUpload && fm.exists(fileId) || self._getFrame(previewId, true).length) {
+                    var p2 = {id: previewId, index: i, fileId: fileId, file: file, files: files};
+                    msg = self.msgDuplicateFile.setTokens({name: caption, size: sizeHuman});
+                    if (self.isAjaxUpload) {
+                        if (!self.stackIsUpdating) {
+                            self.duplicateErrors.push(msg);
+                            self.isDuplicateError = true;
+                            self._raise('fileduplicateerror', [file, fileId, caption, sizeHuman, previewId, i]);
+                        }
+                        readFile(i + 1);
+                        self._updateFileDetails(numFiles);
+                    } else {
+                        self._showError(msg, p2);
+                        self.unlock();
+                        numFiles = 0;
+                        self._clearFileInput();
+                        self.reset();
+                        self._updateFileDetails(numFiles);
+                    }
+                    return;
+                }
+                if (self.maxFileSize > 0 && fileSize > self.maxFileSize) {
+                    msg = self.msgSizeTooLarge.setTokens({
+                        'name': caption,
+                        'size': sizeHuman,
+                        'maxSize': self._getSize(self.maxFileSize * self.bytesToKB, true)
+                    });
+                    throwError(msg, file, previewId, i, fileId);
+                    return;
+                }
+                if (self.minFileSize !== null && fileSize <= $h.getNum(self.minFileSize)) {
+                    msg = self.msgSizeTooSmall.setTokens({
+                        'name': caption,
+                        'size': sizeHuman,
+                        'minSize': self._getSize(self.minFileSize * self.bytesToKB, true)
+                    });
+                    throwError(msg, file, previewId, i, fileId);
+                    return;
+                }
+                if (!$h.isEmpty(fileTypes) && $h.isArray(fileTypes)) {
+                    for (j = 0; j < fileTypes.length; j += 1) {
+                        typ = fileTypes[j];
+                        func = settings[typ];
+                        fileCount += !func || (typeof func !== 'function') ? 0 : (func(file.type,
+                            $h.getFileName(file)) ? 1 : 0);
+                    }
+                    if (fileCount === 0) {
+                        msg = self.msgInvalidFileType.setTokens({name: caption, types: strTypes});
+                        throwError(msg, file, previewId, i, fileId);
+                        return;
+                    }
+                }
+                if (fileCount === 0 && !$h.isEmpty(fileExt) && $h.isArray(fileExt) && !$h.isEmpty(fileExtExpr)) {
+                    chk = $h.compare(caption, fileExtExpr);
+                    fileCount += $h.isEmpty(chk) ? 0 : chk.length;
+                    if (fileCount === 0) {
+                        msg = self.msgInvalidFileExtension.setTokens({name: caption, extensions: strExt});
+                        throwError(msg, file, previewId, i, fileId);
+                        return;
+                    }
+                }
+                if (!self._canPreview(file)) {
+                    canLoad = self._raise('filebeforeload', [file, i, reader]);
+                    if (self.isAjaxUpload && canLoad) {
+                        fm.add(file);
+                    }
+                    if (self.showPreview && canLoad) {
+                        $container.addClass('file-thumb-loading');
+                        self._initCapStatus('processing');
+                        self._previewDefault(file);
+                        self._initFileActions();
+                    }
+                    setTimeout(function () {
+                        if (canLoad) {
+                            self._updateFileDetails(numFiles);
+                        }
+                        readFile(i + 1);
+                        self._raise('fileloaded', [file, previewId, id, i]);
+                    }, 10);
+                    return;
+                }
+                isImage = fnImage(file.type, caption);
+                $status.html(msgLoading.replace('{index}', i + 1).replace('{files}', numFiles));
+                $container.addClass('file-thumb-loading');
+                self._initCapStatus('processing');
+                reader.onerror = function (evt) {
+                    self._errorHandler(evt, caption);
+                };
+                reader.onload = function (theFile) {
+                    var hex, fileInfo, fileData, byte, bytes = [], contents, mime,
+                        processPreview = function (fType, ext) {
+                            if ($h.isEmpty(fType)) { // look for ascii text content
+                                contents = $h.arrayBuffer2String(reader.result);
+                                fType = $h.isSvg(contents) ? 'image/svg+xml' : $h.getMimeType(hex, contents, file.type);
+                            }
+                            fileInfo = {'name': caption, 'type': fType || ''};
+                            if (ext && typeof File !== "undefined") {
+                                try {
+                                    var fName = fileInfo.filename = caption + '.' + ext;
+                                    fileProcessed = new File([file], fName, {type: fileInfo.type});
+                                    initFileData(fileProcessed);
+                                } catch (err) {
+                                }
+                            }
+                            isImage = fnImage(fType, '');
+                            if (isImage) {
+                                var newReader = new FileReader();
+                                newReader.onerror = function (theFileNew) {
+                                    self._errorHandler(theFileNew, caption);
+                                };
+                                newReader.onload = function (theFileNew) {
+                                    if (self.isAjaxUpload && !self._raise('filebeforeload', [file, i, reader])) {
+                                        fileReaderAborted = true;
+                                        self._resetCaption();
+                                        reader.abort();
+                                        $status.html('');
+                                        $container.removeClass('file-thumb-loading');
+                                        self._initCapStatus('valid');
+                                        self.enable();
+                                        return;
+                                    }
+                                    self._previewFile(i, file, theFileNew, previewData, fileInfo);
+                                    self._initFileActions();
+                                    processFileLoaded();
+                                };
+                                newReader.readAsDataURL(file);
+                                return;
+                            }
+                            if (self.isAjaxUpload && !self._raise('filebeforeload', [file, i, reader])) {
+                                fileReaderAborted = true;
+                                self._resetCaption();
+                                reader.abort();
+                                $status.html('');
+                                $container.removeClass('file-thumb-loading');
+                                self._initCapStatus('valid');
+                                self.enable();
+                                return;
+                            }
+                            self._previewFile(i, file, theFile, previewData, fileInfo);
+                            self._initFileActions();
+                            processFileLoaded();
+                        };
+                    mime = file.type;
+                    fileInfo = {'name': caption, 'type': mime};
+                    $.each(settings, function (k, f) {
+                        if (k !== 'object' && k !== 'other' && typeof f === 'function' && f(mime, caption)) {
+                            knownTypes++;
+                        }
+                    });
+                    if (typeof FileTypeParser !== "undefined") {
+                        fileData = new Uint8Array(theFile.target.result);
+                        new FileTypeParser().parse(fileData).then(function (result) {
+                            processPreview(result && result.mime || mime, result && result.ext || '');
+                        });
+                    } else {
+                        if (knownTypes === 0) { // auto detect mime types from content if no known file types detected
+                            fileData = new Uint8Array(theFile.target.result);
+                            for (j = 0; j < fileData.length; j++) {
+                                byte = fileData[j].toString(16);
+                                bytes.push(byte);
+                            }
+                            hex = bytes.join('').toLowerCase().substring(0, 8);
+                            mime = $h.getMimeType(hex, '', '');
+                        }
+                        processPreview(mime);
+                    }
+                };
+                reader.onprogress = function (data) {
+                    if (data.lengthComputable) {
+                        var fact = (data.loaded / data.total) * 100, progress = Math.ceil(fact);
+                        msg = msgProgress.setTokens({
+                            'index': i + 1,
+                            'files': numFiles,
+                            'percent': progress,
+                            'name': caption
+                        });
+                        setTimeout(function () {
+                            if (!fileReaderAborted) {
+                                $status.html(msg);
+                            }
+                        }, self.processDelay);
+                    }
+                };
+                reader.readAsArrayBuffer(file);
+            };
+
+            readFile(0);
+            self._updateFileDetails(numFiles);
+        },
+        lock: function (selectMode) {
+            var self = this, $container = self.$container;
+            self._resetErrors();
+            self.disable();
+            if (!selectMode && self.showCancel) {
+                $container.find('.fileinput-cancel').show();
+            }
+            if (!selectMode && self.showPause) {
+                $container.find('.fileinput-pause').show();
+            }
+            self._initCapStatus('processing');
+            self._raise('filelock', [self.fileManager.stack, self._getExtraData()]);
+            return self.$element;
+        },
+        unlock: function (reset) {
+            var self = this, $container = self.$container;
+            if (reset === undefined) {
+                reset = true;
+            }
+            self.enable();
+            $container.removeClass('is-locked');
+            if (self.showCancel) {
+                $container.find('.fileinput-cancel').hide();
+            }
+            if (self.showPause) {
+                $container.find('.fileinput-pause').hide();
+            }
+            if (reset) {
+                self._resetFileStack();
+            }
+            self._initCapStatus();
+            self._raise('fileunlock', [self.fileManager.stack, self._getExtraData()]);
+            return self.$element;
+        },
+        resume: function () {
+            var self = this, fm = self.fileManager, flag = false, rm = self.resumableManager;
+            fm.bpsLog = [];
+            fm.bps = 0;
+            if (!self.enableResumableUpload) {
+                return self.$element;
+            }
+            if (self.paused) {
+                self._toggleResumableProgress(self.progressPauseTemplate, self.msgUploadResume);
+            } else {
+                flag = true;
+            }
+            self.paused = false;
+            if (flag) {
+                self._toggleResumableProgress(self.progressInfoTemplate, self.msgUploadBegin);
+            }
+            setTimeout(function () {
+                rm.upload();
+            }, self.processDelay);
+            return self.$element;
+        },
+        paste: function (e) {
+            var self = this, ev = e.originalEvent, files = ev.clipboardData && ev.clipboardData.files || null;
+            if (files) {
+                self._dropFiles(e, files);
+            }
+            return self.$element;
+        },
+        pause: function () {
+            var self = this, rm = self.resumableManager, xhr = self.ajaxRequests, len = xhr.length, i,
+                pct = rm.getProgress(), actions = self.fileActionSettings, tm = self.taskManager,
+                pool = tm.getPool(rm.id);
+            if (!self.enableResumableUpload) {
+                return self.$element;
+            } else {
+                if (pool) {
+                    pool.cancel();
+                }
+            }
+            self._raise('fileuploadpaused', [self.fileManager, rm]);
+            if (len > 0) {
+                for (i = 0; i < len; i += 1) {
+                    self.paused = true;
+                    xhr[i].abort();
+                }
+            }
+            if (self.showPreview) {
+                self._getThumbs().each(function () {
+                    var $thumb = $(this), t = self._getLayoutTemplate('stats'), stats,
+                        $indicator = $thumb.find('.file-upload-indicator');
+                    $thumb.removeClass('file-uploading');
+                    if ($indicator.attr('title') === actions.indicatorLoadingTitle) {
+                        self._setThumbStatus($thumb, 'Paused');
+                        stats = t.setTokens({pendingTime: self.msgPaused, uploadSpeed: ''});
+                        self.paused = true;
+                        self._setProgress(pct, $thumb.find('.file-thumb-progress'), pct + '%', stats);
+                    }
+                    if (!self._getThumbFile($thumb)) {
+                        $thumb.find('.kv-file-remove').removeClass('disabled').removeAttr('disabled');
+                    }
+                });
+            }
+            self._setProgress(101, self.$progress, self.msgPaused);
+            return self.$element;
+        },
+        cancel: function () {
+            var self = this, xhr = self.ajaxRequests,
+                rm = self.resumableManager, tm = self.taskManager,
+                pool = rm ? tm.getPool(rm.id) : undefined, len = xhr.length, i;
+            if (self.enableResumableUpload && pool) {
+                pool.cancel().done(function () {
+                    self._setProgressCancelled();
+                });
+                rm.reset();
+                self._raise('fileuploadcancelled', [self.fileManager, rm]);
+            } else {
+                if (self.ajaxPool) {
+                    self.ajaxPool.cancel();
+                }
+                self._raise('fileuploadcancelled', [self.fileManager]);
+            }
+            self._initAjax();
+            if (len > 0) {
+                for (i = 0; i < len; i += 1) {
+                    self.cancelling = true;
+                    xhr[i].abort();
+                }
+            }
+            self._getThumbs().each(function () {
+                var $thumb = $(this), $prog = $thumb.find('.file-thumb-progress');
+                $thumb.removeClass('file-uploading');
+                self._setProgress(0, $prog);
+                $prog.hide();
+                if (!self._getThumbFile($thumb)) {
+                    $thumb.find('.kv-file-upload').removeClass('disabled').removeAttr('disabled');
+                    $thumb.find('.kv-file-remove').removeClass('disabled').removeAttr('disabled');
+                }
+                self.unlock();
+            });
+            setTimeout(function () {
+                self._setProgressCancelled();
+            }, self.processDelay);
+            return self.$element;
+        },
+        clear: function () {
+            var self = this, cap;
+            if (!self._raise('fileclear')) {
+                return;
+            }
+            self.clearInput = true;
+            self.$btnUpload.removeAttr('disabled');
+            self._getThumbs().find('video,audio,img').each(function () {
+                $h.cleanMemory($(this));
+            });
+            self._clearFileInput();
+            self._resetUpload();
+            self.clearFileStack();
+            self.isDuplicateError = false;
+            self.isPersistentError = false;
+            self._resetErrors(true);
+            if (self._hasInitialPreview()) {
+                self._showFileIcon();
+                self._resetPreview();
+                self._initPreviewActions();
+                self.$container.removeClass('file-input-new');
+            } else {
+                self._getThumbs().each(function () {
+                    self._clearObjects($(this));
+                });
+                if (self.isAjaxUpload) {
+                    self.previewCache.data = {};
+                }
+                self.$preview.html('');
+                cap = (!self.overwriteInitial && self.initialCaption.length > 0) ? self.initialCaption : '';
+                self.$caption.attr('title', '').val(cap);
+                $h.addCss(self.$container, 'file-input-new');
+                self._validateDefaultPreview();
+            }
+            if (self.$container.find($h.FRAMES).length === 0) {
+                if (!self._initCaption()) {
+                    self.$captionContainer.removeClass('icon-visible');
+                }
+            }
+            self._hideFileIcon();
+            if (self.focusCaptionOnClear) {
+                self.$captionContainer.focus();
+            }
+            self._setFileDropZoneTitle();
+            self._raise('filecleared');
+            return self.$element;
+        },
+        reset: function () {
+            var self = this;
+            if (!self._raise('filereset')) {
+                return;
+            }
+            self.lastProgress = 0;
+            self._resetPreview();
+            self.$container.find('.fileinput-filename').text('');
+            $h.addCss(self.$container, 'file-input-new');
+            if (self.getFrames().length) {
+                self.$container.removeClass('file-input-new');
+            }
+            self.clearFileStack();
+            self._setFileDropZoneTitle();
+            return self.$element;
+        },
+        disable: function () {
+            var self = this, $container = self.$container;
+            self.isDisabled = true;
+            self._raise('filedisabled');
+            self.$element.attr('disabled', 'disabled');
+            $container.addClass('is-locked');
+            $h.addCss($container.find('.btn-file'), 'disabled');
+            $container.find('.kv-fileinput-caption').addClass('file-caption-disabled');
+            $container.find('.fileinput-remove, .fileinput-upload, .file-preview-frame button')
+                .attr('disabled', true);
+            self._initDragDrop();
+            return self.$element;
+        },
+        enable: function () {
+            var self = this, $container = self.$container;
+            self.isDisabled = false;
+            self._raise('fileenabled');
+            self.$element.removeAttr('disabled');
+            $container.removeClass('is-locked');
+            $container.find('.kv-fileinput-caption').removeClass('file-caption-disabled');
+            $container.find('.fileinput-remove, .fileinput-upload, .file-preview-frame button')
+                .removeAttr('disabled');
+            $container.find('.btn-file').removeClass('disabled');
+            self._initDragDrop();
+            return self.$element;
+        },
+        upload: function () {
+            var self = this, fm = self.fileManager, totLen = fm.count(), i, outData, tm = self.taskManager,
+                hasExtraData = !$.isEmptyObject(self._getExtraData());
+            fm.bpsLog = [];
+            fm.bps = 0;
+            if (!self.isAjaxUpload || self.isDisabled || !self._isFileSelectionValid(totLen)) {
+                return;
+            }
+            self.lastProgress = 0;
+            self._resetUpload();
+            if (totLen === 0 && !hasExtraData) {
+                self._showFileError(self.msgUploadEmpty);
+                return;
+            }
+            self.cancelling = false;
+            self.uploadInitiated = true;
+            self._showProgress();
+            self.lock();
+            if (totLen === 0 && hasExtraData) {
+                self._setProgress(2);
+                self._uploadExtraOnly();
+                return;
+            }
+            if (self.enableResumableUpload) {
+                return self.resume();
+            }
+            if (self.uploadAsync || self.enableResumableUpload) {
+                outData = self._getOutData(null);
+                if (!self._checkBatchPreupload(outData)) {
+                    return;
+                }
+                self.fileBatchCompleted = false;
+                self.uploadCache = [];
+                $.each(self.getFileStack(), function (id) {
+                    var previewId = self._getThumbId(id);
+                    self.uploadCache.push({id: previewId, content: null, config: null, tags: null, append: true});
+                });
+                self.$preview.find('.file-preview-initial').removeClass($h.SORT_CSS);
+                self._initSortable();
+            }
+            self._setProgress(2);
+            self.hasInitData = false;
+            if (self.uploadAsync) {
+                i = 0;
+                var pool = self.ajaxPool = tm.addPool($h.uniqId());
+                $.each(self.getFileStack(), function (id) {
+                    pool.addTask(id + i, function (deferrer) {
+                        self._uploadSingle(i, id, true, deferrer);
+                    });
+                    i++;
+                });
+
+                pool.run(self.maxAjaxThreads).done(function () {
+                    self._log('Async upload batch completed successfully.');
+                    self._raise('filebatchuploadsuccess', [fm.stack, self._getExtraData()]);
+                }).fail(function () {
+                    self._log('Async upload batch completed with errors.');
+                    self._raise('filebatchuploaderror', [fm.stack, self._getExtraData()]);
+                });
+                return;
+            }
+            self._uploadBatch();
+            return self.$element;
+        },
+        destroy: function () {
+            var self = this, $form = self.$form, $cont = self.$container, $el = self.$element, ns = self.namespace;
+            $(document).off(ns);
+            $(window).off(ns);
+            if ($form && $form.length) {
+                $form.off(ns);
+            }
+            if (self.isAjaxUpload) {
+                self._clearFileInput();
+            }
+            self._cleanup();
+            self._initPreviewCache();
+            $el.insertBefore($cont).off(ns).removeData();
+            $cont.off().remove();
+            return $el;
+        },
+        refresh: function (options) {
+            var self = this, $el = self.$element;
+            if (typeof options !== 'object' || $h.isEmpty(options)) {
+                options = self.options;
+            } else {
+                options = $.extend(true, {}, self.options, options);
+            }
+            self._init(options, true);
+            self._listen();
+            return $el;
+        },
+        zoom: function (frameId) {
+            var self = this, $frame = self._getFrame(frameId);
+            self._showModal($frame);
+        },
+        getExif: function (frameId) {
+            var self = this, $frame = self._getFrame(frameId);
+            return $frame && $frame.data('exif') || null;
+        },
+        getFrames: function (cssFilter) {
+            var self = this, $frames;
+            cssFilter = cssFilter || '';
+            $frames = self.$preview.find($h.FRAMES + cssFilter);
+            if (self.reversePreviewOrder) {
+                $frames = $($frames.get().reverse());
+            }
+            return $frames;
+        },
+        getPreview: function () {
+            var self = this;
+            return {
+                content: self.initialPreview,
+                config: self.initialPreviewConfig,
+                tags: self.initialPreviewThumbTags
+            };
+        }
+    };
+
+    $.fn.fileinput = function (option) {
+        if (!$h.hasFileAPISupport() && !$h.isIE(9)) {
+            return;
+        }
+        var args = Array.apply(null, arguments), retvals = [];
+        args.shift();
+        this.each(function () {
+            var self = $(this), data = self.data('fileinput'), options = typeof option === 'object' && option,
+                theme = options.theme || self.data('theme'), l = {}, t = {},
+                lang = options.language || self.data('language') || $.fn.fileinput.defaults.language || 'en', opt;
+            if (!data) {
+                if (theme) {
+                    t = $.fn.fileinputThemes[theme] || {};
+                }
+                if (lang !== 'en' && !$h.isEmpty($.fn.fileinputLocales[lang])) {
+                    l = $.fn.fileinputLocales[lang] || {};
+                }
+                opt = $.extend(true, {}, $.fn.fileinput.defaults, t, $.fn.fileinputLocales.en, l, options, self.data());
+                data = new FileInput(this, opt);
+                self.data('fileinput', data);
+            }
+
+            if (typeof option === 'string') {
+                retvals.push(data[option].apply(data, args));
+            }
+        });
+        switch (retvals.length) {
+            case 0:
+                return this;
+            case 1:
+                return retvals[0];
+            default:
+                return retvals;
+        }
+    };
+
+    var IFRAME_ATTRIBS = 'class="kv-preview-data file-preview-pdf" src="{renderer}?file={data}" {style}',
+        defBtnCss1 = 'btn btn-sm btn-kv ' + $h.defaultButtonCss(), defBtnCss2 = 'btn ' + $h.defaultButtonCss();
+
+    $.fn.fileinput.defaults = {
+        language: 'zh',
+        bytesToKB: 1024,
+        showCaption: true,
+        showBrowse: true,
+        showPreview: true,
+        showRemove: true,
+        showUpload: true,
+        showUploadStats: true,
+        showCancel: null,
+        showPause: null,
+        showClose: true,
+        showUploadedThumbs: true,
+        showConsoleLogs: false,
+        browseOnZoneClick: false,
+        autoReplace: false,
+        showDescriptionClose: true,
+        autoOrientImage: function () { // applicable for JPEG images only and non ios safari
+            var ua = window.navigator.userAgent, webkit = !!ua.match(/WebKit/i),
+                iOS = !!ua.match(/iP(od|ad|hone)/i), iOSSafari = iOS && webkit && !ua.match(/CriOS/i);
+            return !iOSSafari;
+        },
+        autoOrientImageInitial: true,
+        showExifErrorLog: false,
+        required: false,
+        rtl: false,
+        hideThumbnailContent: false,
+        encodeUrl: true,
+        focusCaptionOnBrowse: true,
+        focusCaptionOnClear: true,
+        generateFileId: null,
+        previewClass: '',
+        captionClass: '',
+        frameClass: 'krajee-default',
+        mainClass: '',
+        inputGroupClass: '',
+        mainTemplate: null,
+        fileSizeGetter: null,
+        initialCaption: '',
+        initialPreview: [],
+        initialPreviewDelimiter: '*$$*',
+        initialPreviewAsData: false,
+        initialPreviewFileType: 'image',
+        initialPreviewConfig: [],
+        initialPreviewThumbTags: [],
+        previewThumbTags: {},
+        initialPreviewShowDelete: true,
+        initialPreviewDownloadUrl: '',
+        removeFromPreviewOnError: false,
+        deleteUrl: '',
+        deleteExtraData: {},
+        overwriteInitial: true,
+        sanitizeZoomCache: function (content) {
+            var $container = $h.createElement(content);
+            $container.find('input,textarea,select,datalist,form,.file-thumbnail-footer').remove();
+            return $container.html();
+        },
+        previewZoomButtonIcons: {
+            prev: '<i class="glyphicon glyphicon-triangle-left"></i>',
+            next: '<i class="glyphicon glyphicon-triangle-right"></i>',
+            toggleheader: '<i class="glyphicon glyphicon-resize-vertical"></i>',
+            fullscreen: '<i class="glyphicon glyphicon-fullscreen"></i>',
+            borderless: '<i class="glyphicon glyphicon-resize-full"></i>',
+            close: '<i class="glyphicon glyphicon-remove"></i>'
+        },
+        previewZoomButtonClasses: {
+            prev: 'btn btn-default btn-outline-secondary btn-navigate',
+            next: 'btn btn-default btn-outline-secondary btn-navigate',
+            rotate: defBtnCss1,
+            toggleheader: defBtnCss1,
+            fullscreen: defBtnCss1,
+            borderless: defBtnCss1,
+            close: defBtnCss1
+        },
+        previewTemplates: {},
+        previewContentTemplates: {},
+        preferIconicPreview: false,
+        preferIconicZoomPreview: false,
+        alwaysPreviewFileExtensions: [],
+        rotatableFileExtensions: ['jpg', 'jpeg', 'png', 'gif'],
+        allowedFileTypes: null,
+        allowedFileExtensions: null,
+        allowedPreviewTypes: undefined,
+        allowedPreviewMimeTypes: null,
+        allowedPreviewExtensions: null,
+        disabledPreviewTypes: undefined,
+        disabledPreviewExtensions: ['msi', 'exe', 'com', 'zip', 'rar', 'app', 'vb', 'scr'],
+        disabledPreviewMimeTypes: null,
+        defaultPreviewContent: null,
+        customLayoutTags: {},
+        customPreviewTags: {},
+        previewFileIcon: '<i class="bi-file-earmark-fill"></i>',
+        previewFileIconClass: 'file-other-icon',
+        previewFileIconSettings: {},
+        previewFileExtSettings: {},
+        buttonLabelClass: 'hidden-xs',
+        browseIcon: '<i class="bi-folder2-open"></i> ',
+        browseClass: 'btn btn-primary',
+        removeIcon: '<i class="bi-trash"></i>',
+        removeClass: defBtnCss2,
+        cancelIcon: '<i class="bi-slash-circle"></i>',
+        cancelClass: defBtnCss2,
+        pauseIcon: '<i class="bi-pause-fill"></i>',
+        pauseClass: defBtnCss2,
+        uploadIcon: '<i class="bi-upload"></i>',
+        uploadClass: defBtnCss2,
+        uploadUrl: null,
+        uploadUrlThumb: null,
+        uploadAsync: true,
+        uploadParamNames: {
+            chunkCount: 'chunkCount',
+            chunkIndex: 'chunkIndex',
+            chunkSize: 'chunkSize',
+            chunkSizeStart: 'chunkSizeStart',
+            chunksUploaded: 'chunksUploaded',
+            fileBlob: 'fileBlob',
+            fileId: 'fileId',
+            fileName: 'fileName',
+            fileRelativePath: 'fileRelativePath',
+            fileSize: 'fileSize',
+            retryCount: 'retryCount'
+        },
+        maxAjaxThreads: 5,
+        fadeDelay: 800,
+        processDelay: 100,
+        bitrateUpdateDelay: 500,
+        queueDelay: 10, // must be lesser than process delay
+        progressDelay: 0, // must be lesser than process delay
+        enableResumableUpload: false,
+        resumableUploadOptions: {
+            fallback: null,
+            testUrl: null, // used for checking status of chunks/ files previously / partially uploaded
+            chunkSize: 2048, // in KB
+            maxThreads: 4,
+            maxRetries: 3,
+            showErrorLog: true,
+            retainErrorHistory: false, // when set to true, display complete error history always unless user explicitly resets upload
+            skipErrorsAndProceed: false // when set to true, files with errors will be skipped and upload will continue with other files
+        },
+        uploadExtraData: {},
+        zoomModalHeight: 485, // 5px more than the default preview content heights set for text, html, pdf etc.
+        minImageWidth: null,
+        minImageHeight: null,
+        maxImageWidth: null,
+        maxImageHeight: null,
+        resizeImage: false,
+        resizePreference: 'width',
+        resizeQuality: 0.92,
+        resizeDefaultImageType: 'image/jpeg',
+        resizeIfSizeMoreThan: 0, // in KB
+        minFileSize: -1,
+        maxFileSize: 0,
+        maxFilePreviewSize: 25600, // 25 MB
+        minFileCount: 0,
+        maxFileCount: 0,
+        maxTotalFileCount: 0,
+        validateInitialCount: false,
+        msgValidationErrorClass: 'text-danger',
+        msgValidationErrorIcon: '<i class="glyphicon glyphicon-exclamation-sign"></i> ',
+        msgErrorClass: 'file-error-message',
+        progressThumbClass: 'progress-bar progress-bar-striped active progress-bar-animated',
+        progressClass: 'progress-bar bg-success progress-bar-success progress-bar-striped active progress-bar-animated',
+        progressInfoClass: 'progress-bar bg-info progress-bar-info progress-bar-striped active progress-bar-animated',
+        progressCompleteClass: 'progress-bar bg-success progress-bar-success',
+        progressPauseClass: 'progress-bar bg-primary progress-bar-primary progress-bar-striped active progress-bar-animated',
+        progressErrorClass: 'progress-bar bg-danger progress-bar-danger',
+        progressUploadThreshold: 99,
+        previewFileType: 'image',
+        elCaptionContainer: null,
+        elCaptionText: null,
+        elPreviewContainer: null,
+        elPreviewImage: null,
+        elPreviewStatus: null,
+        elErrorContainer: null,
+        errorCloseButton: undefined,
+        slugCallback: null,
+        dropZoneEnabled: true,
+        dropZoneTitleClass: 'file-drop-zone-title',
+        fileActionSettings: {},
+        otherActionButtons: '',
+        textEncoding: 'UTF-8',
+        preProcessUpload: null,
+        ajaxSettings: {},
+        ajaxDeleteSettings: {},
+        showAjaxErrorDetails: true,
+        mergeAjaxCallbacks: false,
+        mergeAjaxDeleteCallbacks: false,
+        retryErrorUploads: true,
+        reversePreviewOrder: false,
+        usePdfRenderer: function () {
+            var isIE11 = !!window.MSInputMethodContext && !!document.documentMode;
+            return !!navigator.userAgent.match(/(iPod|iPhone|iPad|Android)/i) || isIE11;
+        },
+        pdfRendererUrl: '',
+        pdfRendererTemplate: '<iframe ' + IFRAME_ATTRIBS + '></iframe>',
+        tabIndexConfig: {
+            browse: 500,
+            remove: 500,
+            upload: 500,
+            cancel: null,
+            pause: null,
+            modal: -1
+        }
+    };
+
+    // noinspection HtmlUnknownAttribute
+    $.fn.fileinputLocales.en = {
+        sizeUnits: ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
+        bitRateUnits: ['B/s', 'KB/s', 'MB/s', 'GB/s', 'TB/s', 'PB/s', 'EB/s', 'ZB/s', 'YB/s'],
+        fileSingle: 'file',
+        filePlural: 'files',
+        browseLabel: 'Browse &hellip;',
+        removeLabel: 'Remove',
+        removeTitle: 'Clear all unprocessed files',
+        cancelLabel: 'Cancel',
+        cancelTitle: 'Abort ongoing upload',
+        pauseLabel: 'Pause',
+        pauseTitle: 'Pause ongoing upload',
+        uploadLabel: 'Upload',
+        uploadTitle: 'Upload selected files',
+        msgNo: 'No',
+        msgNoFilesSelected: 'No files selected',
+        msgCancelled: 'Cancelled',
+        msgPaused: 'Paused',
+        msgPlaceholder: 'Select {files} ...',
+        msgZoomModalHeading: 'Detailed Preview',
+        msgFileRequired: 'You must select a file to upload.',
+        msgSizeTooSmall: 'File "{name}" (<b>{size}</b>) is too small and must be larger than <b>{minSize}</b>.',
+        msgSizeTooLarge: 'File "{name}" (<b>{size}</b>) exceeds maximum allowed upload size of <b>{maxSize}</b>.',
+        msgFilesTooLess: 'You must select at least <b>{n}</b> {files} to upload.',
+        msgFilesTooMany: 'Number of files selected for upload <b>({n})</b> exceeds maximum allowed limit of <b>{m}</b>.',
+        msgTotalFilesTooMany: 'You can upload a maximum of <b>{m}</b> files (<b>{n}</b> files detected).',
+        msgFileNotFound: 'File "{name}" not found!',
+        msgFileSecured: 'Security restrictions prevent reading the file "{name}".',
+        msgFileNotReadable: 'File "{name}" is not readable.',
+        msgFilePreviewAborted: 'File preview aborted for "{name}".',
+        msgFilePreviewError: 'An error occurred while reading the file "{name}".',
+        msgInvalidFileName: 'Invalid or unsupported characters in file name "{name}".',
+        msgInvalidFileType: 'Invalid type for file "{name}". Only "{types}" files are supported.',
+        msgInvalidFileExtension: 'Invalid extension for file "{name}". Only "{extensions}" files are supported.',
+        msgFileTypes: {
+            'image': 'image',
+            'html': 'HTML',
+            'text': 'text',
+            'video': 'video',
+            'audio': 'audio',
+            'flash': 'flash',
+            'pdf': 'PDF',
+            'object': 'object'
+        },
+        msgUploadAborted: 'The file upload was aborted',
+        msgUploadThreshold: 'Processing &hellip;',
+        msgUploadBegin: 'Initializing &hellip;',
+        msgUploadEnd: 'Done',
+        msgUploadResume: 'Resuming upload &hellip;',
+        msgUploadEmpty: 'No valid data available for upload.',
+        msgUploadError: 'Upload Error',
+        msgDeleteError: 'Delete Error',
+        msgProgressError: 'Error',
+        msgValidationError: 'Validation Error',
+        msgLoading: 'Loading file {index} of {files} &hellip;',
+        msgProgress: 'Loading file {index} of {files} - {name} - {percent}% completed.',
+        msgSelected: '{n} {files} selected',
+        msgProcessing: 'Processing ...',
+        msgFoldersNotAllowed: 'Drag & drop files only! {n} folder(s) dropped were skipped.',
+        msgImageWidthSmall: 'Width of image file "{name}" must be at least <b>{size} px</b> (detected <b>{dimension} px</b>).',
+        msgImageHeightSmall: 'Height of image file "{name}" must be at least <b>{size} px</b> (detected <b>{dimension} px</b>).',
+        msgImageWidthLarge: 'Width of image file "{name}" cannot exceed <b>{size} px</b> (detected <b>{dimension} px</b>).',
+        msgImageHeightLarge: 'Height of image file "{name}" cannot exceed <b>{size} px</b> (detected <b>{dimension} px</b>).',
+        msgImageResizeError: 'Could not get the image dimensions to resize.',
+        msgImageResizeException: 'Error while resizing the image.<pre>{errors}</pre>',
+        msgAjaxError: 'Something went wrong with the {operation} operation. Please try again later!',
+        msgAjaxProgressError: '{operation} failed',
+        msgDuplicateFile: 'File "{name}" of same size "{size}" has already been selected earlier. Skipping duplicate selection.',
+        msgResumableUploadRetriesExceeded: 'Upload aborted beyond <b>{max}</b> retries for file <b>{file}</b>! Error Details: <pre>{error}</pre>',
+        msgPendingTime: '{time} remaining',
+        msgCalculatingTime: 'calculating time remaining',
+        ajaxOperations: {
+            deleteThumb: 'file delete',
+            uploadThumb: 'file upload',
+            uploadBatch: 'batch file upload',
+            uploadExtra: 'form data upload'
+        },
+        dropZoneTitle: 'Drag & drop files here &hellip;',
+        dropZoneClickTitle: '<br>(or click to select {files})',
+        previewZoomButtonTitles: {
+            prev: 'View previous file',
+            next: 'View next file',
+            rotate: 'Rotate 90 deg. clockwise',
+            toggleheader: 'Toggle header',
+            fullscreen: 'Toggle full screen',
+            borderless: 'Toggle borderless mode',
+            close: 'Close detailed preview'
+        }
+    };
+    
+    $.fn.fileinputLocales.zh = {
+    		sizeUnits: ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'], 
+            bitRateUnits: ['B/s', 'KB/s', 'MB/s', 'GB/s', 'TB/s', 'PB/s', 'EB/s', 'ZB/s', 'YB/s'],
+            fileSingle: '文件',
+            filePlural: '个文件',
+            browseLabel: '选择 &hellip;',
+            removeLabel: '移除',
+            removeTitle: '清除选中文件',
+            cancelLabel: '取消',
+            cancelTitle: '取消进行中的上传',
+            pauseLabel: '暂停',
+            pauseTitle: '暂停上传',
+            uploadLabel: '上传',
+            uploadTitle: '上传选中文件',
+            msgNo: '没有',
+            msgNoFilesSelected: '未选择文件',
+            msgPaused: '已暂停',
+            msgCancelled: '取消',
+            msgPlaceholder: '选择 {files} ...',
+            msgZoomModalHeading: '详细预览',
+            msgFileRequired: '必须选择一个文件上传.',
+            msgSizeTooSmall: '文件 "{name}" (<b>{size}</b>) 必须大于限定大小 <b>{minSize}</b>.',
+            msgSizeTooLarge: '文件 "{name}" (<b>{size}</b>) 超过了允许大小 <b>{maxSize}</b>.',
+            msgFilesTooLess: '你必须选择最少 <b>{n}</b> {files} 来上传. ',
+            msgFilesTooMany: '选择的上传文件个数 <b>({n})</b> 超出最大文件的限制个数 <b>{m}</b>.',
+            msgTotalFilesTooMany: '你最多可以上传 <b>{m}</b> 个文件 (当前有<b>{n}</b> 个文件).',
+            msgFileNotFound: '文件 "{name}" 未找到!',
+            msgFileSecured: '安全限制,为了防止读取文件 "{name}".',
+            msgFileNotReadable: '文件 "{name}" 不可读.',
+            msgFilePreviewAborted: '取消 "{name}" 的预览.',
+            msgFilePreviewError: '读取 "{name}" 时出现了一个错误.',
+            msgInvalidFileName: '文件名 "{name}" 包含非法字符.',
+            msgInvalidFileType: '不正确的类型 "{name}". 只支持 "{types}" 类型的文件.',
+            msgInvalidFileExtension: '不正确的文件扩展名 "{name}". 只支持 "{extensions}" 的文件扩展名.',
+            msgFileTypes: {
+                'image': 'image',
+                'html': 'HTML',
+                'text': 'text',
+                'video': 'video',
+                'audio': 'audio',
+                'flash': 'flash',
+                'pdf': 'PDF',
+                'object': 'object'
+            },
+            msgUploadAborted: '该文件上传被中止',
+            msgUploadThreshold: '处理中 &hellip;',
+            msgUploadBegin: '正在初始化 &hellip;',
+            msgUploadEnd: '完成',
+            msgUploadResume: '继续上传 &hellip;',
+            msgUploadEmpty: '无效的文件上传.',
+            msgUploadError: '上传出错',
+            msgDeleteError: '删除出错',
+            msgProgressError: '上传出错',
+            msgValidationError: '验证错误',
+            msgLoading: '加载第 {index} 文件 共 {files} &hellip;',
+            msgProgress: '加载第 {index} 文件 共 {files} - {name} - {percent}% 完成.',
+            msgSelected: '{n} {files} 选中',
+            msgProcessing: '处理中 ...',
+            msgFoldersNotAllowed: '只支持拖拽文件! 跳过 {n} 拖拽的文件夹.',
+            msgImageWidthSmall: '图像文件的"{name}"的宽度必须是至少{size}像素.',
+            msgImageHeightSmall: '图像文件的"{name}"的高度必须至少为{size}像素.',
+            msgImageWidthLarge: '图像文件"{name}"的宽度不能超过{size}像素.',
+            msgImageHeightLarge: '图像文件"{name}"的高度不能超过{size}像素.',
+            msgImageResizeError: '无法获取的图像尺寸调整。',
+            msgImageResizeException: '调整图像大小时发生错误。<pre>{errors}</pre>',
+            msgAjaxError: '{operation} 发生错误. 请重试!',
+            msgAjaxProgressError: '{operation} 失败',
+            msgDuplicateFile: '文件 "{name}",大小 "{size}" 已经被选中.忽略相同的文件.',
+            msgResumableUploadRetriesExceeded:  '文件 <b>{file}</b> 上传失败超过 <b>{max}</b> 次重试 ! 错误详情: <pre>{error}</pre>',
+            msgPendingTime: '{time} 剩余',
+            msgCalculatingTime: '计算剩余时间',
+            ajaxOperations: {
+                deleteThumb: '删除文件',
+                uploadThumb: '上传文件',
+                uploadBatch: '批量上传',
+                uploadExtra: '表单数据上传'
+            },
+            dropZoneTitle: '拖拽文件到这里 &hellip;<br>支持多文件同时上传',
+            dropZoneClickTitle: '<br>(或点击{files}按钮选择文件)',
+            fileActionSettings: {
+                removeTitle: '删除文件',
+                uploadTitle: '上传文件',
+                downloadTitle: '下载文件',
+                uploadRetryTitle: '重试',
+                rotateTitle: '顺时针旋转90度',
+                zoomTitle: '查看详情',
+                dragTitle: '移动 / 重置',
+                indicatorNewTitle: '没有上传',
+                indicatorSuccessTitle: '上传',
+                indicatorErrorTitle: '上传错误',
+                indicatorPausedTitle: '上传已暂停',
+                indicatorLoadingTitle:  '上传 &hellip;'
+            },
+            previewZoomButtonTitles: {
+                prev: '预览上一个文件',
+                next: '预览下一个文件',
+                rotate: '顺时针旋转90度',
+                toggleheader: '缩放',
+                fullscreen: '全屏',
+                borderless: '无边界模式',
+                close: '关闭当前预览'
+            }
+        };
+
+    $.fn.fileinput.Constructor = FileInput;
+
+    /**
+     * Convert automatically file inputs with class 'file' into a bootstrap fileinput control.
+     */
+    $(document).ready(function () {
+        var $input = $('input.file[type=file]');
+        if ($input.length) {
+            $input.fileinput();
+        }
+    });
+}));
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-fileinput/fileinput.min.css b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-fileinput/fileinput.min.css
new file mode 100644
index 0000000..f8a3cd5
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-fileinput/fileinput.min.css
@@ -0,0 +1,13 @@
+/*!
+ * bootstrap-fileinput v5.5.2
+ * http://plugins.krajee.com/file-input
+ *
+ * Krajee default styling for bootstrap-fileinput.
+ *
+ * Author: Kartik Visweswaran
+ * Copyright: 2014 - 2022, Kartik Visweswaran, Krajee.com
+ *
+ * Licensed under the BSD-3-Clause
+ * https://github.com/kartik-v/bootstrap-fileinput/blob/master/LICENSE.md
+ */
+ .file-loading input[type=file],input[type=file].file-loading{width:0;height:0;}.file-no-browse{position:absolute;left:50%;bottom:20%;width:1px;height:1px;font-size:0;opacity:0;border:none;background:none;outline:none;box-shadow:none;}.kv-hidden,.file-caption-icon,.file-zoom-dialog .modal-header:before,.file-zoom-dialog .modal-header:after,.file-input-new .file-preview,.file-input-new .close,.file-input-new .glyphicon-file,.file-input-new .fileinput-remove-button,.file-input-new .fileinput-upload-button,.file-input-new .no-browse .input-group-btn,.file-input-ajax-new .fileinput-remove-button,.file-input-ajax-new .fileinput-upload-button,.file-input-ajax-new .no-browse .input-group-btn,.hide-content .kv-file-content,.is-locked .fileinput-upload-button,.is-locked .fileinput-remove-button{display:none;}.file-caption .input-group{align-items:center;}.btn-file input[type=file],.file-caption-icon,.file-preview .fileinput-remove,.krajee-default .file-thumb-progress,.file-zoom-dialog .btn-navigate,.file-zoom-dialog .floating-buttons{position:absolute;}.file-caption-icon .kv-caption-icon{line-height:inherit;}.file-input,.file-loading:before,.btn-file,.file-caption,.file-preview,.krajee-default.file-preview-frame,.krajee-default .file-thumbnail-footer,.file-zoom-dialog .modal-dialog{position:relative;}.file-error-message pre,.file-error-message ul,.krajee-default .file-actions,.krajee-default .file-other-error{text-align:left;}.file-error-message pre,.file-error-message ul{margin:0;}.krajee-default .file-drag-handle,.krajee-default .file-upload-indicator{float:left;margin-top:10px;width:16px;height:16px;}.file-thumb-progress .progress,.file-thumb-progress .progress-bar{font-family:Verdana,Helvetica,sans-serif;font-size:0.7rem;}.krajee-default .file-thumb-progress .progress,.kv-upload-progress .progress{background-color:#ccc;}.krajee-default .file-caption-info,.krajee-default .file-size-info{display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;width:160px;height:15px;margin:auto;}.file-zoom-content > .file-object.type-video,.file-zoom-content > .file-object.type-flash,.file-zoom-content > .file-object.type-image{max-width:100%;max-height:100%;width:auto;}.file-zoom-content > .file-object.type-video,.file-zoom-content > .file-object.type-flash{height:100%;}.file-zoom-content > .file-object.type-pdf,.file-zoom-content > .file-object.type-html,.file-zoom-content > .file-object.type-text,.file-zoom-content > .file-object.type-default{width:100%;}.file-loading:before{content:" Loading...";display:inline-block;padding-left:20px;line-height:16px;font-size:13px;font-variant:small-caps;color:#999;background:transparent url(loading.gif) top left no-repeat;}.file-object{margin:0 0 -5px 0;padding:0;}.btn-file{overflow:hidden;}.btn-file input[type=file]{top:0;left:0;min-width:100%;min-height:100%;text-align:right;opacity:0;background:none repeat scroll 0 0 transparent;cursor:inherit;display:block;}.btn-file::-ms-browse{font-size:10000px;width:100%;height:100%;}.file-caption.icon-visible .file-caption-icon{display:inline-block;}.file-caption.icon-visible .file-caption-name{padding-left:25px;}.file-caption.icon-visible > .input-group-lg .file-caption-name{padding-left:30px;}.file-caption.icon-visible > .input-group-sm .file-caption-name{padding-left:22px;}.file-caption-name:not(.file-caption-disabled){background-color:transparent;}.file-caption-name.file-processing{font-style:italic;border-color:#bbb;opacity:0.5;}.file-caption-icon{padding:7px 5px;left:4px;}.input-group-lg .file-caption-icon{font-size:1.25rem;}.input-group-sm .file-caption-icon{font-size:0.875rem;padding:0.25rem;}.file-error-message{color:#a94442;background-color:#f2dede;margin:5px;border:1px solid #ebccd1;border-radius:4px;padding:15px;}.file-error-message pre{margin:5px 0;}.file-caption-disabled{background-color:#eee;cursor:not-allowed;opacity:1;}.file-preview{border-radius:5px;border:1px solid #ddd;padding:8px;width:100%;margin-bottom:5px;}.file-preview .btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px;}.file-preview .fileinput-remove{top:1px;right:1px;line-height:10px;}.file-preview .clickable{cursor:pointer;}.file-preview-image{font:40px Impact,Charcoal,sans-serif;color:#008000;width:auto;height:auto;max-width:100%;max-height:100%;}.krajee-default.file-preview-frame{margin:8px;border:1px solid rgba(0,0,0,0.2);box-shadow:0 0 10px 0 rgba(0,0,0,0.2);padding:6px;float:left;text-align:center;}.krajee-default.file-preview-frame .kv-file-content{width:213px;height:160px;}.krajee-default.file-preview-frame .kv-file-content.kv-pdf-rendered{width:400px;}.krajee-default.file-preview-frame[data-template="audio"] .kv-file-content{width:240px;height:55px;}.krajee-default.file-preview-frame .file-thumbnail-footer{height:70px;}.krajee-default.file-preview-frame:not(.file-preview-error):hover{border:1px solid rgba(0,0,0,0.3);box-shadow:0 0 10px 0 rgba(0,0,0,0.4);}.krajee-default .file-preview-text{color:#428bca;border:1px solid #ddd;outline:none;resize:none;}.krajee-default .file-preview-html{border:1px solid #ddd;}.krajee-default .file-other-icon{font-size:6em;line-height:1;}.krajee-default .file-footer-buttons{float:right;}.krajee-default .file-footer-caption{display:block;text-align:center;padding-top:4px;font-size:11px;color:#999;margin-bottom:30px;}.file-upload-stats{font-size:10px;text-align:center;width:100%;}.kv-upload-progress .file-upload-stats{font-size:12px;margin:-10px 0 5px;}.krajee-default .file-preview-error{opacity:0.65;box-shadow:none;}.krajee-default .file-thumb-progress{top:37px;left:0;right:0;}.krajee-default.kvsortable-ghost{background:#e1edf7;border:2px solid #a1abff;}.krajee-default .file-preview-other:hover{opacity:0.8;}.krajee-default .file-preview-frame:not(.file-preview-error) .file-footer-caption:hover{color:#000;}.kv-upload-progress .progress{height:20px;margin:10px 0;overflow:hidden;}.kv-upload-progress .progress-bar{height:20px;font-family:Verdana,Helvetica,sans-serif;}.file-zoom-dialog .file-other-icon{font-size:22em;font-size:50vmin;}.file-zoom-dialog .modal-dialog{width:auto;}.file-zoom-dialog .modal-header{display:flex;align-items:center;justify-content:space-between;}.file-zoom-dialog .btn-navigate{margin:0 0.1rem;padding:0;font-size:1.2rem;width:2.4rem;height:2.4rem;top:50%;border-radius:50%;text-align:center;}.btn-navigate *{width:auto;}.file-zoom-dialog .floating-buttons{top:5px;right:10px;}.file-zoom-dialog .btn-kv-prev{left:0;}.file-zoom-dialog .btn-kv-next{right:0;}.file-zoom-dialog .kv-zoom-header{padding:0.5rem;}.file-zoom-dialog .kv-zoom-body{padding:0.25rem;}.file-zoom-dialog .kv-zoom-description{position:absolute;opacity:0.8;font-size:0.8rem;background-color:#1a1a1a;padding:1rem;text-align:center;border-radius:0.5rem;color:#fff;left:15%;right:15%;bottom:15%;}.file-zoom-dialog .kv-desc-hide{float:right;color:#fff;padding:0 0.1rem;background:none;border:none;}.file-zoom-dialog .kv-desc-hide:hover{opacity:0.7;}.file-zoom-dialog .kv-desc-hide:focus{opacity:0.9;}.file-input-new .no-browse .form-control{border-top-right-radius:4px;border-bottom-right-radius:4px;}.file-input-ajax-new .no-browse .form-control{border-top-right-radius:4px;border-bottom-right-radius:4px;}.file-caption{width:100%;position:relative;}.file-thumb-loading{background:transparent url(loading.gif) no-repeat scroll center center content-box !important;}.file-drop-zone{border:1px dashed #aaa;min-height:260px;border-radius:4px;text-align:center;vertical-align:middle;margin:12px 15px 12px 12px;padding:5px;}.file-drop-zone.clickable:hover{border:2px dashed #999;}.file-drop-zone.clickable:focus{border:2px solid #5acde2;}.file-drop-zone .file-preview-thumbnails{cursor:default;}.file-drop-zone-title{color:#aaa;font-size:1.6em;text-align:center;padding:85px 10px;cursor:default;}.file-highlighted{border:2px dashed #999 !important;background-color:#eee;}.file-uploading{background:url(loading-sm.gif) no-repeat center bottom 10px;opacity:0.65;}.file-zoom-fullscreen .modal-dialog{min-width:100%;margin:0;}.file-zoom-fullscreen .modal-content{border-radius:0;box-shadow:none;min-height:100vh;}.file-zoom-fullscreen .kv-zoom-body{overflow-y:auto;}.floating-buttons{z-index:3000;}.floating-buttons .btn-kv{margin-left:3px;z-index:3000;}.kv-zoom-actions{min-width:140px;}.kv-zoom-actions .btn-kv{margin-left:3px;}.file-zoom-content{text-align:center;white-space:nowrap;min-height:300px;}.file-zoom-content:hover{background:transparent;}.file-zoom-content .file-preview-image{max-height:100%;}.file-zoom-content .file-preview-video{max-height:100%;}.file-zoom-content > .file-object.type-image{height:auto;min-height:inherit;}.file-zoom-content > .file-object.type-audio{width:auto;height:30px;}@media (min-width:576px){.file-zoom-dialog .modal-dialog{max-width:500px;}}@media (min-width:992px){.file-zoom-dialog .modal-lg{max-width:800px;}}@media (max-width:767px){.file-preview-thumbnails{display:flex;justify-content:center;align-items:center;flex-direction:column;}.file-zoom-dialog .modal-header{flex-direction:column;}}@media (max-width:350px){.krajee-default.file-preview-frame:not([data-template="audio"]) .kv-file-content{width:160px;}}@media (max-width:420px){.krajee-default.file-preview-frame .kv-file-content.kv-pdf-rendered{width:100%;}}.file-loading[dir=rtl]:before{background:transparent url(loading.gif) top right no-repeat;padding-left:0;padding-right:20px;}.clickable .file-drop-zone-title{cursor:pointer;}.file-sortable .file-drag-handle:hover{opacity:0.7;}.file-sortable .file-drag-handle{cursor:grab;opacity:1;}.file-grabbing,.file-grabbing *{cursor:not-allowed !important;}.file-grabbing .file-preview-thumbnails *{cursor:grabbing !important;}.file-preview-frame.sortable-chosen{background-color:#d9edf7;border-color:#17a2b8;box-shadow:none !important;}.file-preview .kv-zoom-cache{display:none;}.file-preview-other-frame,.file-preview-object,.kv-file-content,.kv-zoom-body{display:flex;align-items:center;justify-content:center;}.btn-kv-rotate,.kv-file-rotate{display:none;}.rotatable:not(.hide-rotate) .btn-kv-rotate,.rotatable:not(.hide-rotate) .kv-file-rotate{display:inline-block;}.rotatable .file-zoom-detail,.rotatable .kv-file-content,.rotatable .kv-file-content >:first-child{transform-origin:center center;}.rotate-animate{transition:transform 0.3s ease;}.kv-overflow-hidden{overflow:hidden;}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-fileinput/fileinput.min.js b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-fileinput/fileinput.min.js
new file mode 100644
index 0000000..72bf6bf
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-fileinput/fileinput.min.js
@@ -0,0 +1,11 @@
+/*!
+ * bootstrap-fileinput v5.5.2
+ * http://plugins.krajee.com/file-input
+ *
+ * Author: Kartik Visweswaran
+ * Copyright: 2014 - 2022, Kartik Visweswaran, Krajee.com
+ *
+ * Licensed under the BSD-3-Clause
+ * https://github.com/kartik-v/bootstrap-fileinput/blob/master/LICENSE.md
+ */
+(function(factory){'use strict';if(typeof define==='function'&&define.amd){define(['jquery'],factory)}else if(typeof module==='object'&&typeof module.exports==='object'){factory(require('jquery'))}else{factory(window.jQuery)}}(function($){'use strict';$.fn.fileinputLocales={};$.fn.fileinputThemes={};if(!$.fn.fileinputBsVersion){$.fn.fileinputBsVersion=(window.bootstrap&&window.bootstrap.Alert&&window.bootstrap.Alert.VERSION)||(window.Alert&&window.Alert.VERSION)||'3.x.x'}String.prototype.setTokens=function(replacePairs){var str=this.toString(),key,re;for(key in replacePairs){if(replacePairs.hasOwnProperty(key)){re=new RegExp('\{'+key+'\}','g');str=str.replace(re,replacePairs[key])}}return str};if(!Array.prototype.flatMap){Array.prototype.flatMap=function(lambda){return[].concat(this.map(lambda))}}var $h,FileInput;$h={FRAMES:'.kv-preview-thumb',SORT_CSS:'file-sortable',INIT_FLAG:'init-',SCRIPT_SRC:document&&document.currentScript&&document.currentScript.src||null,OBJECT_PARAMS:'<param name="controller" value="true" />\n<param name="allowFullScreen" value="true" />\n<param name="allowScriptAccess" value="always" />\n<param name="autoPlay" value="false" />\n<param name="autoStart" value="false" />\n<param name="quality" value="high" />\n',DEFAULT_PREVIEW:'<div class="file-preview-other">\n<span class="{previewFileIconClass}">{previewFileIcon}</span>\n</div>',MODAL_ID:'kvFileinputModal',MODAL_EVENTS:['show','shown','hide','hidden','loaded'],logMessages:{ajaxError:'{status}: {error}. Error Details: {text}.',badDroppedFiles:'Error scanning dropped files!',badExifParser:'Error loading the piexif.js library. {details}',badInputType:'The input "type" must be set to "file" for initializing the "bootstrap-fileinput" plugin.',exifWarning:'To avoid this warning, either set "autoOrientImage" to "false" OR ensure you have loaded the "piexif.js" library correctly on your page before the "fileinput.js" script.',invalidChunkSize:'Invalid upload chunk size: "{chunkSize}". Resumable uploads are disabled.',invalidThumb:'Invalid thumb frame with id: "{id}".',noResumableSupport:'The browser does not support resumable or chunk uploads.',noUploadUrl:'The "uploadUrl" is not set. Ajax uploads and resumable uploads have been disabled.',retryStatus:'Retrying upload for chunk # {chunk} for {filename}... retry # {retry}.',chunkQueueError:'Could not push task to ajax pool for chunk index # {index}.',resumableMaxRetriesReached:'Maximum resumable ajax retries ({n}) reached.',resumableRetryError:'Could not retry the resumable request (try # {n})... aborting.',resumableAborting:'Aborting / cancelling the resumable request.',resumableRequestError:'Error processing resumable request. {msg}'},objUrl:window.URL||window.webkitURL,getZoomPlaceholder:function(){var src=$h.SCRIPT_SRC,srcPath,zoomVar='?kvTemp__2873389129__=';if(!src){return zoomVar}srcPath=src.substring(0,src.lastIndexOf("/"));return srcPath.substring(0,srcPath.lastIndexOf("/")+1)+'img/loading.gif'+zoomVar},isBs:function(ver){var chk=$.trim(($.fn.fileinputBsVersion||'')+'');ver=parseInt(ver,10);if(!chk){return ver===4}return ver===parseInt(chk.charAt(0),10)},defaultButtonCss:function(fill){return'btn-default btn-'+(fill?'':'outline-')+'secondary'},now:function(){return new Date().getTime()},round:function(num){num=parseFloat(num);return isNaN(num)?0:Math.floor(Math.round(num))},getArray:function(obj){var i,arr=[],len=obj&&obj.length||0;for(i=0;i<len;i++){arr.push(obj[i])}return arr},getFileRelativePath:function(file){return String(file.newPath||file.relativePath||file.webkitRelativePath||$h.getFileName(file)||null)},getFileId:function(file,generateFileId){var relativePath=$h.getFileRelativePath(file);if(typeof generateFileId==='function'){return generateFileId(file)}if(!file){return null}if(!relativePath){return null}return(file.size+'_'+encodeURIComponent(relativePath).replace(/%/g,'_'))},getFrameSelector:function(id,selector){selector=selector||'';return'[id="'+id+'"]'+selector},getZoomSelector:function(id,selector){return $h.getFrameSelector('zoom-'+id,selector)},getFrameElement:function($element,id,selector){return $element.find($h.getFrameSelector(id,selector))},getZoomElement:function($element,id,selector){return $element.find($h.getZoomSelector(id,selector))},getElapsed:function(seconds){var delta=seconds,out='',result={},structure={year:31536000,month:2592000,week:604800,day:86400,hour:3600,minute:60,second:1};$h.getObjectKeys(structure).forEach(function(key){result[key]=Math.floor(delta/structure[key]);delta-=result[key]*structure[key]});$.each(result,function(key,value){if(value>0){out+=(out?' ':'')+value+key.substring(0,1)}});return out},debounce:function(func,delay){var inDebounce;return function(){var args=arguments,context=this;clearTimeout(inDebounce);inDebounce=setTimeout(function(){func.apply(context,args)},delay)}},stopEvent:function(e){e.stopPropagation();e.preventDefault()},getFileName:function(file){return file?(file.fileName||file.name||''):''},createObjectURL:function(data){if($h.objUrl&&$h.objUrl.createObjectURL&&data){return $h.objUrl.createObjectURL(data)}return''},revokeObjectURL:function(data){if($h.objUrl&&$h.objUrl.revokeObjectURL&&data){$h.objUrl.revokeObjectURL(data)}},compare:function(input,str,exact){return input!==undefined&&(exact?input===str:input.match(str))},isIE:function(ver){var div,status;if(navigator.appName!=='Microsoft Internet Explorer'){return false}if(ver===10){return new RegExp('msie\\s'+ver,'i').test(navigator.userAgent)}div=document.createElement('div');div.innerHTML='<!--[if IE '+ver+']> <i></i> <![endif]-->';status=div.getElementsByTagName('i').length;document.body.appendChild(div);div.parentNode.removeChild(div);return status},canOrientImage:function($el){var $img=$(document.createElement('img')).css({width:'1px',height:'1px'}).insertAfter($el),flag=$img.css('image-orientation');$img.remove();return!!flag},canAssignFilesToInput:function(){var input=document.createElement('input');try{input.type='file';input.files=null;return true}catch(err){return false}},getDragDropFolders:function(items){var i,item,len=items?items.length:0,folders=0;if(len>0&&items[0].webkitGetAsEntry()){for(i=0;i<len;i++){item=items[i].webkitGetAsEntry();if(item&&item.isDirectory){folders++}}}return folders},initModal:function($modal){var $body=$('body');if($body.length){$modal.appendTo($body)}},isFunction:function(v){return typeof v==='function'},isEmpty:function(value,trim){if(value===undefined||value===null||value===''){return true}if($h.isString(value)&&trim){return $.trim(value)===''}if($h.isArray(value)){return value.length===0}if($.isPlainObject(value)&&$.isEmptyObject(value)){return true}return false},isArray:function(a){return Array.isArray(a)||Object.prototype.toString.call(a)==='[object Array]'},isString:function(a){return Object.prototype.toString.call(a)==='[object String]'},ifSet:function(needle,haystack,def){def=def||'';return(haystack&&typeof haystack==='object'&&needle in haystack)?haystack[needle]:def},cleanArray:function(arr){if(!(arr instanceof Array)){arr=[]}return arr.filter(function(e){return(e!==undefined&&e!==null)})},spliceArray:function(arr,index,reverseOrder){var i,j=0,out=[],newArr;if(!(arr instanceof Array)){return[]}newArr=$.extend(true,[],arr);if(reverseOrder){newArr.reverse()}for(i=0;i<newArr.length;i++){if(i!==index){out[j]=newArr[i];j++}}if(reverseOrder){out.reverse()}return out},getNum:function(num,def){def=def||0;if(typeof num==='number'){return num}if(typeof num==='string'){num=parseFloat(num)}return isNaN(num)?def:num},hasFileAPISupport:function(){return!!(window.File&&window.FileReader)},hasDragDropSupport:function(){var div=document.createElement('div');return!$h.isIE(9)&&(div.draggable!==undefined||(div.ondragstart!==undefined&&div.ondrop!==undefined))},hasFileUploadSupport:function(){return $h.hasFileAPISupport()&&window.FormData},hasBlobSupport:function(){try{return!!window.Blob&&Boolean(new Blob())}catch(e){return false}},hasArrayBufferViewSupport:function(){try{return new Blob([new Uint8Array(100)]).size===100}catch(e){return false}},hasResumableUploadSupport:function(){return $h.hasFileUploadSupport()&&$h.hasBlobSupport()&&$h.hasArrayBufferViewSupport()&&(!!Blob.prototype.webkitSlice||!!Blob.prototype.mozSlice||!!Blob.prototype.slice||false)},dataURI2Blob:function(dataURI){var BlobBuilder=window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder||window.MSBlobBuilder,canBlob=$h.hasBlobSupport(),byteStr,arrayBuffer,intArray,i,mimeStr,bb,canProceed=(canBlob||BlobBuilder)&&window.atob&&window.ArrayBuffer&&window.Uint8Array;if(!canProceed){return null}if(dataURI.split(',')[0].indexOf('base64')>=0){byteStr=atob(dataURI.split(',')[1])}else{byteStr=decodeURIComponent(dataURI.split(',')[1])}arrayBuffer=new ArrayBuffer(byteStr.length);intArray=new Uint8Array(arrayBuffer);for(i=0;i<byteStr.length;i+=1){intArray[i]=byteStr.charCodeAt(i)}mimeStr=dataURI.split(',')[0].split(':')[1].split(';')[0];if(canBlob){return new Blob([$h.hasArrayBufferViewSupport()?intArray:arrayBuffer],{type:mimeStr})}bb=new BlobBuilder();bb.append(arrayBuffer);return bb.getBlob(mimeStr)},arrayBuffer2String:function(buffer){if(window.TextDecoder){return new TextDecoder('utf-8').decode(buffer)}var array=Array.prototype.slice.apply(new Uint8Array(buffer)),out='',i=0,len,c,char2,char3;len=array.length;while(i<len){c=array[i++];switch(c>>4){case 0:case 1:case 2:case 3:case 4:case 5:case 6:case 7:out+=String.fromCharCode(c);break;case 12:case 13:char2=array[i++];out+=String.fromCharCode(((c&0x1F)<<6)|(char2&0x3F));break;case 14:char2=array[i++];char3=array[i++];out+=String.fromCharCode(((c&0x0F)<<12)|((char2&0x3F)<<6)|((char3&0x3F)<<0));break}}return out},isHtml:function(str){var a=document.createElement('div');a.innerHTML=str;for(var c=a.childNodes,i=c.length;i--;){if(c[i].nodeType===1){return true}}return false},isPdf:function(str){if($h.isEmpty(str)){return false}str=str.toString().trim().replace(/\n/g,' ');if(str.length===0){return false}},isSvg:function(str){if($h.isEmpty(str)){return false}str=str.toString().trim().replace(/\n/g,' ');if(str.length===0){return false}return str.match(/^\s*<\?xml/i)&&(str.match(/<!DOCTYPE svg/i)||str.match(/<svg/i))},getMimeType:function(sign,contents,type){var signature=sign||"";switch(signature){case'ffd8ffe0':case'ffd8ffe1':case'ffd8ffe2':return'image/jpeg';case'89504e47':return'image/png';case'47494638':return'image/gif';case'49492a00':return'image/tiff';case'52494646':return'image/webp';case'41433130':return'image/vnd.dwg';case'66747970':return'video/3gp';case'4f676753':return'video/ogg';case'1a45dfa3':return'video/mkv';case'000001ba':case'000001b3':return'video/mpeg';case'3026b275':return'video/wmv';case'25504446':return'application/pdf';case'25215053':return'application/ps';case'504b0304':case'504b0506':case'504b0508':return'application/zip';case'377abcaf':return'application/7z';case'75737461':return'application/tar';case'7801730d':return'application/dmg';default:switch(signature.substring(0,6)){case'435753':return'application/x-shockwave-flash';case'494433':return'audio/mp3';case'425a68':return'application/bzip';default:switch(signature.substring(0,4)){case'424d':return'image/bmp';case'fffb':return'audio/mp3';case'4d5a':return'application/exe';case'1f9d':case'1fa0':return'application/zip';case'1f8b':return'application/gzip';default:return contents&&!contents.match(/[^\u0000-\u007f]/)?'application/text-plain':type}}}},addCss:function($el,css){$el.removeClass(css).addClass(css)},getElement:function(options,param,value){return($h.isEmpty(options)||$h.isEmpty(options[param]))?value:$(options[param])},createElement:function(str,tag){tag=tag||'div';return $($.parseHTML('<'+tag+'>'+str+'</'+tag+'>'))},uniqId:function(){return(new Date().getTime()+Math.floor(Math.random()*Math.pow(10,15))).toString(36)},cspBuffer:{CSP_ATTRIB:'data-csp-01928735',domElementsStyles:{},stash:function(htmlString){var self=this,outerDom=$.parseHTML('<div>'+htmlString+'</div>'),$el=$(outerDom);$el.find('[style]').each(function(key,elem){var $elem=$(elem),styleDeclaration=$elem[0].style,id=$h.uniqId(),styles={};if(styleDeclaration&&styleDeclaration.length){$(styleDeclaration).each(function(){styles[this]=styleDeclaration[this]});self.domElementsStyles[id]=styles;$elem.removeAttr('style').attr(self.CSP_ATTRIB,id)}});$el.filter('*').removeAttr('style');var values=Object.values?Object.values(outerDom):Object.keys(outerDom).map(function(itm){return outerDom[itm]});return values.flatMap(function(elem){return elem.innerHTML}).join('')},apply:function(domElement){var self=this,$el=$(domElement);$el.find('['+self.CSP_ATTRIB+']').each(function(key,elem){var $elem=$(elem),id=$elem.attr(self.CSP_ATTRIB),styles=self.domElementsStyles[id];if(styles){$elem.css(styles)}$elem.removeAttr(self.CSP_ATTRIB)});self.domElementsStyles={}}},setHtml:function($elem,htmlString){var buf=$h.cspBuffer;$elem.html(buf.stash(htmlString));buf.apply($elem);return $elem},htmlEncode:function(str,undefVal){if(str===undefined){return undefVal||null}return str.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;').replace(/'/g,'&apos;')},replaceTags:function(str,tags){var out=str;if(!tags){return out}$.each(tags,function(key,value){if(typeof value==='function'){value=value()}out=out.split(key).join(value)});return out},cleanMemory:function($thumb){var data=$thumb.is('img')?$thumb.attr('src'):$thumb.find('source').attr('src');$h.revokeObjectURL(data)},findFileName:function(filePath){var sepIndex=filePath.lastIndexOf('/');if(sepIndex===-1){sepIndex=filePath.lastIndexOf('\\')}return filePath.split(filePath.substring(sepIndex,sepIndex+1)).pop()},checkFullScreen:function(){return document.fullscreenElement||document.mozFullScreenElement||document.webkitFullscreenElement||document.msFullscreenElement},toggleFullScreen:function(maximize){var doc=document,de=doc.documentElement,isFullScreen=$h.checkFullScreen();if(de&&maximize&&!isFullScreen){if(de.requestFullscreen){de.requestFullscreen()}else{if(de.msRequestFullscreen){de.msRequestFullscreen()}else{if(de.mozRequestFullScreen){de.mozRequestFullScreen()}else{if(de.webkitRequestFullscreen){de.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT)}}}}}else{if(isFullScreen){if(doc.exitFullscreen){doc.exitFullscreen()}else{if(doc.msExitFullscreen){doc.msExitFullscreen()}else{if(doc.mozCancelFullScreen){doc.mozCancelFullScreen()}else{if(doc.webkitExitFullscreen){doc.webkitExitFullscreen()}}}}}}},moveArray:function(arr,oldIndex,newIndex,reverseOrder){var newArr=$.extend(true,[],arr);if(reverseOrder){newArr.reverse()}if(newIndex>=newArr.length){var k=newIndex-newArr.length;while((k--)+1){newArr.push(undefined)}}newArr.splice(newIndex,0,newArr.splice(oldIndex,1)[0]);if(reverseOrder){newArr.reverse()}return newArr},closeButton:function(css){css=($h.isBs(5)?'btn-close':'close')+(css?' '+css:'');return'<button type="button" class="'+css+'" aria-label="Close">\n'+($h.isBs(5)?'':'  <span aria-hidden="true">&times;</span>\n')+'</button>'},getRotation:function(value){switch(value){case 2:return'rotateY(180deg)';case 3:return'rotate(180deg)';case 4:return'rotate(180deg) rotateY(180deg)';case 5:return'rotate(270deg) rotateY(180deg)';case 6:return'rotate(90deg)';case 7:return'rotate(90deg) rotateY(180deg)';case 8:return'rotate(270deg)';default:return''}},setTransform:function(el,val){if(!el){return}el.style.transform=val;el.style.webkitTransform=val;el.style['-moz-transform']=val;el.style['-ms-transform']=val;el.style['-o-transform']=val},getObjectKeys:function(obj){var keys=[];if(obj){$.each(obj,function(key){keys.push(key)})}return keys},getObjectSize:function(obj){return $h.getObjectKeys(obj).length},whenAll:function(array){var s=[].slice,resolveValues=arguments.length===1&&$h.isArray(array)?array:s.call(arguments),deferred=$.Deferred(),i,failed=0,value,length=resolveValues.length,remaining=length,rejectContexts,rejectValues,resolveContexts,updateFunc;rejectContexts=rejectValues=resolveContexts=Array(length);updateFunc=function(index,contexts,values){return function(){if(values!==resolveValues){failed++}deferred.notifyWith(contexts[index]=this,values[index]=s.call(arguments));if(!(--remaining)){deferred[(!failed?'resolve':'reject')+'With'](contexts,values)}}};for(i=0;i<length;i++){if((value=resolveValues[i])&&$.isFunction(value.promise)){value.promise().done(updateFunc(i,resolveContexts,resolveValues)).fail(updateFunc(i,rejectContexts,rejectValues))}else{deferred.notifyWith(this,value);--remaining}}if(!remaining){deferred.resolveWith(resolveContexts,resolveValues)}return deferred.promise()}};FileInput=function(element,options){var self=this;self.$element=$(element);self.$parent=self.$element.parent();if(!self._validate()){return}self.isPreviewable=$h.hasFileAPISupport();self.isIE9=$h.isIE(9);self.isIE10=$h.isIE(10);if(self.isPreviewable||self.isIE9){self._init(options);self._listen()}self.$element.removeClass('file-loading')};FileInput.prototype={constructor:FileInput,_cleanup:function(){var self=this;self.reader=null;self.clearFileStack();self.fileBatchCompleted=true;self.isError=false;self.isDuplicateError=false;self.isPersistentError=false;self.cancelling=false;self.paused=false;self.lastProgress=0;self._initAjax()},_isAborted:function(){var self=this;return self.cancelling||self.paused},_initAjax:function(){var self=this,tm=self.taskManager={pool:{},addPool:function(id){return(tm.pool[id]=new tm.TasksPool(id))},getPool:function(id){return tm.pool[id]},addTask:function(id,logic){return new tm.Task(id,logic)},TasksPool:function(id){var tp=this;tp.id=id;tp.cancelled=false;tp.cancelledDeferrer=$.Deferred();tp.tasks={};tp.addTask=function(id,logic){return(tp.tasks[id]=new tm.Task(id,logic))};tp.size=function(){return $h.getObjectSize(tp.tasks)};tp.run=function(maxThreads){var i=0,failed=false,task,tasksList=$h.getObjectKeys(tp.tasks).map(function(key){return tp.tasks[key]}),tasksDone=[],deferred=$.Deferred(),enqueue,callback;if(tp.cancelled){tp.cancelledDeferrer.resolve();return deferred.reject()}if(!maxThreads){var tasksDeferredList=$h.getObjectKeys(tp.tasks).map(function(key){return tp.tasks[key].deferred});$h.whenAll(tasksDeferredList).done(function(){var argv=$h.getArray(arguments);if(!tp.cancelled){deferred.resolve.apply(null,argv);tp.cancelledDeferrer.reject()}else{deferred.reject.apply(null,argv);tp.cancelledDeferrer.resolve()}}).fail(function(){var argv=$h.getArray(arguments);deferred.reject.apply(null,argv);if(!tp.cancelled){tp.cancelledDeferrer.reject()}else{tp.cancelledDeferrer.resolve()}});$.each(tp.tasks,function(id){task=tp.tasks[id];task.run()});return deferred}enqueue=function(task){$.when(task.deferred).fail(function(){failed=true;callback.apply(null,arguments)}).always(callback)};callback=function(){var argv=$h.getArray(arguments);deferred.notify(argv);tasksDone.push(argv);if(tp.cancelled){deferred.reject.apply(null,tasksDone);tp.cancelledDeferrer.resolve();return}if(tasksDone.length===tp.size()){if(failed){deferred.reject.apply(null,tasksDone)}else{deferred.resolve.apply(null,tasksDone)}}if(tasksList.length){task=tasksList.shift();enqueue(task);task.run()}};while(tasksList.length&&i++<maxThreads){task=tasksList.shift();enqueue(task);task.run()}return deferred};tp.cancel=function(){tp.cancelled=true;return tp.cancelledDeferrer}},Task:function(id,logic){var tk=this;tk.id=id;tk.deferred=$.Deferred();tk.logic=logic;tk.context=null;tk.run=function(){var argv=$h.getArray(arguments);argv.unshift(tk.deferred);logic.apply(tk.context,argv);return tk.deferred};tk.runWithContext=function(context){tk.context=context;return tk.run()}}};self.ajaxQueue=[];self.ajaxRequests=[];self.ajaxPool=null;self.ajaxAborted=false},_init:function(options,refreshMode){var self=this,f,$el=self.$element,$cont,t,tmp;self.options=options;self.zoomPlaceholder=$h.getZoomPlaceholder();self.canOrientImage=$h.canOrientImage($el);$.each(options,function(key,value){switch(key){case'minFileCount':case'maxFileCount':case'maxTotalFileCount':case'minFileSize':case'maxFileSize':case'maxFilePreviewSize':case'resizeQuality':case'resizeIfSizeMoreThan':case'progressUploadThreshold':case'initialPreviewCount':case'zoomModalHeight':case'minImageHeight':case'maxImageHeight':case'minImageWidth':case'maxImageWidth':case'bytesToKB':self[key]=$h.getNum(value);break;default:self[key]=value;break}});if(!self.bytesToKB||self.bytesToKB<=0){self.bytesToKB=1024}if(self.errorCloseButton===undefined){self.errorCloseButton=$h.closeButton('kv-error-close'+($h.isBs(5)?'  float-end':''))}if(self.maxTotalFileCount>0&&self.maxTotalFileCount<self.maxFileCount){self.maxTotalFileCount=self.maxFileCount}if(self.rtl){tmp=self.previewZoomButtonIcons.prev;self.previewZoomButtonIcons.prev=self.previewZoomButtonIcons.next;self.previewZoomButtonIcons.next=tmp}if(!isNaN(self.maxAjaxThreads)&&self.maxAjaxThreads<self.resumableUploadOptions.maxThreads){self.resumableUploadOptions.maxThreads=self.maxAjaxThreads}self._initFileManager();if(typeof self.autoOrientImage==='function'){self.autoOrientImage=self.autoOrientImage()}if(typeof self.autoOrientImageInitial==='function'){self.autoOrientImageInitial=self.autoOrientImageInitial()}if(!refreshMode){self._cleanup()}self.duplicateErrors=[];self.$form=$el.closest('form');self._initTemplateDefaults();self.uploadFileAttr=!$h.isEmpty($el.attr('name'))?$el.attr('name'):'file_data';t=self._getLayoutTemplate('progress');self.progressTemplate=t.replace('{class}',self.progressClass);self.progressInfoTemplate=t.replace('{class}',self.progressInfoClass);self.progressPauseTemplate=t.replace('{class}',self.progressPauseClass);self.progressCompleteTemplate=t.replace('{class}',self.progressCompleteClass);self.progressErrorTemplate=t.replace('{class}',self.progressErrorClass);self.isDisabled=$el.attr('disabled')||$el.attr('readonly');if(self.isDisabled){$el.attr('disabled',true)}self.isClickable=self.browseOnZoneClick&&self.showPreview&&(self.dropZoneEnabled||!$h.isEmpty(self.defaultPreviewContent));self.isAjaxUpload=$h.hasFileUploadSupport()&&!$h.isEmpty(self.uploadUrl);self.dropZoneEnabled=$h.hasDragDropSupport()&&self.dropZoneEnabled;if(!self.isAjaxUpload){self.dropZoneEnabled=self.dropZoneEnabled&&$h.canAssignFilesToInput()}self.slug=typeof options.slugCallback==='function'?options.slugCallback:self._slugDefault;self.mainTemplate=self.showCaption?self._getLayoutTemplate('main1'):self._getLayoutTemplate('main2');self.captionTemplate=self._getLayoutTemplate('caption');self.previewGenericTemplate=self._getPreviewTemplate('generic');if(!self.imageCanvas&&self.resizeImage&&(self.maxImageWidth||self.maxImageHeight)){self.imageCanvas=document.createElement('canvas');self.imageCanvasContext=self.imageCanvas.getContext('2d')}if($h.isEmpty($el.attr('id'))){$el.attr('id',$h.uniqId())}self.namespace='.fileinput_'+$el.attr('id').replace(/-/g,'_');if(self.$container===undefined){self.$container=self._createContainer()}else{self._refreshContainer()}$cont=self.$container;self.$dropZone=$cont.find('.file-drop-zone');self.$progress=$cont.find('.kv-upload-progress');self.$btnUpload=$cont.find('.fileinput-upload');self.$captionContainer=$h.getElement(options,'elCaptionContainer',$cont.find('.file-caption'));self.$caption=$h.getElement(options,'elCaptionText',$cont.find('.file-caption-name'));if(!$h.isEmpty(self.msgPlaceholder)){f=$el.attr('multiple')?self.filePlural:self.fileSingle;self.$caption.attr('placeholder',self.msgPlaceholder.replace('{files}',f))}self.$captionIcon=self.$captionContainer.find('.file-caption-icon');self.$previewContainer=$h.getElement(options,'elPreviewContainer',$cont.find('.file-preview'));self.$preview=$h.getElement(options,'elPreviewImage',$cont.find('.file-preview-thumbnails'));self.$previewStatus=$h.getElement(options,'elPreviewStatus',$cont.find('.file-preview-status'));self.$errorContainer=$h.getElement(options,'elErrorContainer',self.$previewContainer.find('.kv-fileinput-error'));self._validateDisabled();if(!$h.isEmpty(self.msgErrorClass)){$h.addCss(self.$errorContainer,self.msgErrorClass)}if(!refreshMode){self._resetErrors();self.$errorContainer.hide();self.previewInitId='thumb-'+$el.attr('id');self._initPreviewCache();self._initPreview(true);self._initPreviewActions();if(self.$parent.hasClass('file-loading')){self.$container.insertBefore(self.$parent);self.$parent.remove()}}else{if(!self._errorsExist()){self.$errorContainer.hide()}}self._setFileDropZoneTitle();if($el.attr('disabled')){self.disable()}self._initZoom();if(self.hideThumbnailContent){$h.addCss(self.$preview,'hide-content')}},_initFileManager:function(){var self=this;self.uploadStartTime=$h.now();self.fileManager={stack:{},filesProcessed:[],errors:[],loadedImages:{},totalImages:0,totalFiles:null,totalSize:null,uploadedSize:0,stats:{},bpsLog:[],bps:0,initStats:function(id){var data={started:$h.now()};if(id){self.fileManager.stats[id]=data}else{self.fileManager.stats=data}},getUploadStats:function(id,loaded,total){var fm=self.fileManager,started=id?fm.stats[id]&&fm.stats[id].started||$h.now():self.uploadStartTime,elapsed=($h.now()-started)/1000,bps=Math.ceil(elapsed?loaded/elapsed:0),pendingBytes=total-loaded,out,delay=fm.bpsLog.length?self.bitrateUpdateDelay:0;setTimeout(function(){var i,j=0,n=0,len,beg;fm.bpsLog.push(bps);fm.bpsLog.sort(function(a,b){return a-b});len=fm.bpsLog.length;beg=len>10?len-10:Math.ceil(len/2);for(i=len;i>beg;i--){n=parseFloat(fm.bpsLog[i]);j++}fm.bps=(j>0?n/j:0)*64},delay);out={fileId:id,started:started,elapsed:elapsed,loaded:loaded,total:total,bps:fm.bps,bitrate:self._getSize(fm.bps,false,self.bitRateUnits),pendingBytes:pendingBytes};if(id){fm.stats[id]=out}else{fm.stats=out}return out},exists:function(id){return $.inArray(id,self.fileManager.getIdList())!==-1},count:function(){return self.fileManager.getIdList().length},total:function(){var fm=self.fileManager;if(!fm.totalFiles){fm.totalFiles=fm.count()}return fm.totalFiles},getTotalSize:function(){var fm=self.fileManager;if(fm.totalSize){return fm.totalSize}fm.totalSize=0;$.each(self.getFileStack(),function(id,f){var size=parseFloat(f.size);fm.totalSize+=isNaN(size)?0:size});return fm.totalSize},add:function(file,id){if(!id){id=self.fileManager.getId(file)}if(!id){return}self.fileManager.stack[id]={file:file,name:$h.getFileName(file),relativePath:$h.getFileRelativePath(file),size:file.size,nameFmt:self._getFileName(file,''),sizeFmt:self._getSize(file.size)}},remove:function($thumb){var id=self._getThumbFileId($thumb);self.fileManager.removeFile(id)},removeFile:function(id){var fm=self.fileManager;if(!id){return}delete fm.stack[id];delete fm.loadedImages[id]},move:function(idFrom,idTo){var result={},stack=self.fileManager.stack;if(!idFrom&&!idTo||idFrom===idTo){return}$.each(stack,function(k,v){if(k!==idFrom){result[k]=v}if(k===idTo){result[idFrom]=stack[idFrom]}});self.fileManager.stack=result},list:function(){var files=[];$.each(self.getFileStack(),function(k,v){if(v&&v.file){files.push(v.file)}});return files},isPending:function(id){return $.inArray(id,self.fileManager.filesProcessed)===-1&&self.fileManager.exists(id)},isProcessed:function(){var filesProcessed=true,fm=self.fileManager;$.each(self.getFileStack(),function(id){if(fm.isPending(id)){filesProcessed=false}});return filesProcessed},clear:function(){var fm=self.fileManager;self.isDuplicateError=false;self.isPersistentError=false;fm.totalFiles=null;fm.totalSize=null;fm.uploadedSize=0;fm.stack={};fm.errors=[];fm.filesProcessed=[];fm.stats={};fm.bpsLog=[];fm.bps=0;fm.clearImages()},clearImages:function(){self.fileManager.loadedImages={};self.fileManager.totalImages=0},addImage:function(id,config){self.fileManager.loadedImages[id]=config},removeImage:function(id){delete self.fileManager.loadedImages[id]},getImageIdList:function(){return $h.getObjectKeys(self.fileManager.loadedImages)},getImageCount:function(){return self.fileManager.getImageIdList().length},getId:function(file){return self._getFileId(file)},getIndex:function(id){return self.fileManager.getIdList().indexOf(id)},getThumb:function(id){var $thumb=null;self._getThumbs().each(function(){var $t=$(this);if(self._getThumbFileId($t)===id){$thumb=$t}});return $thumb},getThumbIndex:function($thumb){var id=self._getThumbFileId($thumb);return self.fileManager.getIndex(id)},getIdList:function(){return $h.getObjectKeys(self.fileManager.stack)},getFile:function(id){return self.fileManager.stack[id]||null},getFileName:function(id,fmt){var file=self.fileManager.getFile(id);if(!file){return''}return fmt?(file.nameFmt||''):file.name||''},getFirstFile:function(){var ids=self.fileManager.getIdList(),id=ids&&ids.length?ids[0]:null;return self.fileManager.getFile(id)},setFile:function(id,file){if(self.fileManager.getFile(id)){self.fileManager.stack[id].file=file}else{self.fileManager.add(file,id)}},setProcessed:function(id){self.fileManager.filesProcessed.push(id)},getProgress:function(){var total=self.fileManager.total(),filesProcessed=self.fileManager.filesProcessed.length;if(!total){return 0}return Math.ceil(filesProcessed/total*100)},setProgress:function(id,pct){var f=self.fileManager.getFile(id);if(!isNaN(pct)&&f){f.progress=pct}}}},_setUploadData:function(fd,config){var self=this;$.each(config,function(key,value){var param=self.uploadParamNames[key]||key;if($h.isArray(value)){fd.append(param,value[0],value[1])}else{fd.append(param,value)}})},_initResumableUpload:function(){var self=this,opts=self.resumableUploadOptions,logs=$h.logMessages,rm,fm=self.fileManager;if(!self.enableResumableUpload){return}if(opts.fallback!==false&&typeof opts.fallback!=='function'){opts.fallback=function(s){s._log(logs.noResumableSupport);s.enableResumableUpload=false}}if(!$h.hasResumableUploadSupport()&&opts.fallback!==false){opts.fallback(self);return}if(!self.uploadUrl&&self.enableResumableUpload){self._log(logs.noUploadUrl);self.enableResumableUpload=false;return}opts.chunkSize=parseFloat(opts.chunkSize);if(opts.chunkSize<=0||isNaN(opts.chunkSize)){self._log(logs.invalidChunkSize,{chunkSize:opts.chunkSize});self.enableResumableUpload=false;return}rm=self.resumableManager={init:function(id,f,index){rm.logs=[];rm.stack=[];rm.error='';rm.id=id;rm.file=f.file;rm.fileName=f.name;rm.fileIndex=index;rm.completed=false;rm.lastProgress=0;if(self.showPreview){rm.$thumb=fm.getThumb(id)||null;rm.$progress=rm.$btnDelete=null;if(rm.$thumb&&rm.$thumb.length){rm.$progress=rm.$thumb.find('.file-thumb-progress');rm.$btnDelete=rm.$thumb.find('.kv-file-remove')}}rm.chunkSize=opts.chunkSize*self.bytesToKB;rm.chunkCount=rm.getTotalChunks()},setAjaxError:function(jqXHR,textStatus,errorThrown,isTest){if(jqXHR.responseJSON&&jqXHR.responseJSON.error){errorThrown=jqXHR.responseJSON.error.toString()}if(!isTest){rm.error=errorThrown}if(opts.showErrorLog){self._log(logs.ajaxError,{status:jqXHR.status,error:errorThrown,text:jqXHR.responseText||''})}},reset:function(){rm.stack=[];rm.chunksProcessed={}},setProcessed:function(status){var id=rm.id,msg,$thumb=rm.$thumb,$prog=rm.$progress,hasThumb=$thumb&&$thumb.length,params={id:hasThumb?$thumb.attr('id'):'',index:fm.getIndex(id),fileId:id},tokens,skipErrorsAndProceed=self.resumableUploadOptions.skipErrorsAndProceed;rm.completed=true;rm.lastProgress=0;if(hasThumb){$thumb.removeClass('file-uploading')}if(status==='success'){fm.uploadedSize+=rm.file.size;if(self.showPreview){self._setProgress(101,$prog);self._setThumbStatus($thumb,'Success');self._initUploadSuccess(rm.chunksProcessed[id].data,$thumb)}fm.removeFile(id);delete rm.chunksProcessed[id];self._raise('fileuploaded',[params.id,params.index,params.fileId]);if(fm.isProcessed()){self._setProgress(101)}}else{if(status!=='cancel'){if(self.showPreview){self._setThumbStatus($thumb,'Error');self._setPreviewError($thumb,true);self._setProgress(101,$prog,self.msgProgressError);self._setProgress(101,self.$progress,self.msgProgressError);self.cancelling=!skipErrorsAndProceed}if(!self.$errorContainer.find('li[data-file-id="'+params.fileId+'"]').length){tokens={file:rm.fileName,max:opts.maxRetries,error:rm.error};msg=self.msgResumableUploadRetriesExceeded.setTokens(tokens);$.extend(params,tokens);self._showFileError(msg,params,'filemaxretries');if(skipErrorsAndProceed){fm.removeFile(id);delete rm.chunksProcessed[id];if(fm.isProcessed()){self._setProgress(101)}}}}}if(fm.isProcessed()){rm.reset()}},check:function(){var status=true;$.each(rm.logs,function(index,value){if(!value){status=false;return false}})},processedResumables:function(){var logs=rm.logs,i,count=0;if(!logs||!logs.length){return 0}for(i=0;i<logs.length;i++){if(logs[i]===true){count++}}return count},getUploadedSize:function(){var size=rm.processedResumables()*rm.chunkSize;return size>rm.file.size?rm.file.size:size},getTotalChunks:function(){var chunkSize=parseFloat(rm.chunkSize);if(!isNaN(chunkSize)&&chunkSize>0){return Math.ceil(rm.file.size/chunkSize)}return 0},getProgress:function(){var chunksProcessed=rm.processedResumables(),total=rm.chunkCount;if(total===0){return 0}return Math.ceil(chunksProcessed/total*100)},checkAborted:function(intervalId){if(self._isAborted()){clearInterval(intervalId);self.unlock()}},upload:function(){var ids=fm.getIdList(),flag='new',intervalId;intervalId=setInterval(function(){var id;rm.checkAborted(intervalId);if(flag==='new'){self.lock();flag='processing';id=ids.shift();fm.initStats(id);if(fm.stack[id]){rm.init(id,fm.stack[id],fm.getIndex(id));rm.processUpload()}}if(!fm.isPending(id)&&rm.completed){flag='new'}if(fm.isProcessed()){var $initThumbs=self.$preview.find('.file-preview-initial');if($initThumbs.length){$h.addCss($initThumbs,$h.SORT_CSS);self._initSortable()}clearInterval(intervalId);self._clearFileInput();self.unlock();setTimeout(function(){var data=self.previewCache.data;if(data){self.initialPreview=data.content;self.initialPreviewConfig=data.config;self.initialPreviewThumbTags=data.tags}self._raise('filebatchuploadcomplete',[self.initialPreview,self.initialPreviewConfig,self.initialPreviewThumbTags,self._getExtraData()])},self.processDelay)}},self.processDelay)},uploadResumable:function(){var i,pool,tm=self.taskManager,total=rm.chunkCount;pool=tm.addPool(rm.id);for(i=0;i<total;i++){rm.logs[i]=!!(rm.chunksProcessed[rm.id]&&rm.chunksProcessed[rm.id][i]);if(!rm.logs[i]){rm.pushAjax(i,0)}}pool.run(opts.maxThreads).done(function(){rm.setProcessed('success')}).fail(function(){rm.setProcessed(pool.cancelled?'cancel':'error')})},processUpload:function(){var fd,f,id=rm.id,fnBefore,fnSuccess,fnError,fnComplete,outData;if(!opts.testUrl){rm.uploadResumable();return}fd=new FormData();f=fm.stack[id];self._setUploadData(fd,{fileId:id,fileName:f.fileName,fileSize:f.size,fileRelativePath:f.relativePath,chunkSize:rm.chunkSize,chunkCount:rm.chunkCount});fnBefore=function(jqXHR){outData=self._getOutData(fd,jqXHR);self._raise('filetestbeforesend',[id,fm,rm,outData])};fnSuccess=function(data,textStatus,jqXHR){outData=self._getOutData(fd,jqXHR,data);var pNames=self.uploadParamNames,chunksUploaded=pNames.chunksUploaded||'chunksUploaded',params=[id,fm,rm,outData];if(!data[chunksUploaded]||!$h.isArray(data[chunksUploaded])){self._raise('filetesterror',params)}else{if(!rm.chunksProcessed[id]){rm.chunksProcessed[id]={}}$.each(data[chunksUploaded],function(key,index){rm.logs[index]=true;rm.chunksProcessed[id][index]=true});rm.chunksProcessed[id].data=data;self._raise('filetestsuccess',params)}rm.uploadResumable()};fnError=function(jqXHR,textStatus,errorThrown){outData=self._getOutData(fd,jqXHR);self._raise('filetestajaxerror',[id,fm,rm,outData]);rm.setAjaxError(jqXHR,textStatus,errorThrown,true);rm.uploadResumable()};fnComplete=function(){self._raise('filetestcomplete',[id,fm,rm,self._getOutData(fd)])};self._ajaxSubmit(fnBefore,fnSuccess,fnComplete,fnError,fd,id,rm.fileIndex,opts.testUrl)},pushAjax:function(index,retry){var tm=self.taskManager,pool=tm.getPool(rm.id);pool.addTask(pool.size()+1,function(deferrer){var arr=rm.stack.shift(),index;index=arr[0];if(!rm.chunksProcessed[rm.id]||!rm.chunksProcessed[rm.id][index]){rm.sendAjax(index,arr[1],deferrer)}else{self._log(logs.chunkQueueError,{index:index})}});rm.stack.push([index,retry])},sendAjax:function(index,retry,deferrer){var f,chunkSize=rm.chunkSize,id=rm.id,file=rm.file,$thumb=rm.$thumb,msgs=$h.logMessages,$btnDelete=rm.$btnDelete,logError=function(msg,tokens){if(tokens){msg=msg.setTokens(tokens)}msg=msgs.resumableRequestError.setTokens({msg:msg});self._log(msg);deferrer.reject(msg)};if(rm.chunksProcessed[id]&&rm.chunksProcessed[id][index]){return}if(retry>opts.maxRetries){logError(msgs.resumableMaxRetriesReached,{n:opts.maxRetries});rm.setProcessed('error');return}var fd,outData,fnBefore,fnSuccess,fnError,fnComplete,slice=file.slice?'slice':(file.mozSlice?'mozSlice':(file.webkitSlice?'webkitSlice':'slice')),blob=file[slice](chunkSize*index,chunkSize*(index+1));fd=new FormData();f=fm.stack[id];self._setUploadData(fd,{chunkCount:rm.chunkCount,chunkIndex:index,chunkSize:chunkSize,chunkSizeStart:chunkSize*index,fileBlob:[blob,rm.fileName],fileId:id,fileName:rm.fileName,fileRelativePath:f.relativePath,fileSize:file.size,retryCount:retry});if(rm.$progress&&rm.$progress.length){rm.$progress.show()}fnBefore=function(jqXHR){outData=self._getOutData(fd,jqXHR);if(self.showPreview){if(!$thumb.hasClass('file-preview-success')){self._setThumbStatus($thumb,'Loading');$h.addCss($thumb,'file-uploading')}$btnDelete.attr('disabled',true)}self._raise('filechunkbeforesend',[id,index,retry,fm,rm,outData])};fnSuccess=function(data,textStatus,jqXHR){if(self._isAborted()){logError(msgs.resumableAborting);return}outData=self._getOutData(fd,jqXHR,data);var paramNames=self.uploadParamNames,chunkIndex=paramNames.chunkIndex||'chunkIndex',params=[id,index,retry,fm,rm,outData];if(data.error){if(opts.showErrorLog){self._log(logs.retryStatus,{retry:retry+1,filename:rm.fileName,chunk:index})}self._raise('filechunkerror',params);rm.pushAjax(index,retry+1);rm.error=data.error;logError(data.error)}else{rm.logs[data[chunkIndex]]=true;if(!rm.chunksProcessed[id]){rm.chunksProcessed[id]={}}rm.chunksProcessed[id][data[chunkIndex]]=true;rm.chunksProcessed[id].data=data;deferrer.resolve.call(null,data);self._raise('filechunksuccess',params);rm.check()}};fnError=function(jqXHR,textStatus,errorThrown){if(self._isAborted()){logError(msgs.resumableAborting);return}outData=self._getOutData(fd,jqXHR);rm.setAjaxError(jqXHR,textStatus,errorThrown);self._raise('filechunkajaxerror',[id,index,retry,fm,rm,outData]);rm.pushAjax(index,retry+1);logError(msgs.resumableRetryError,{n:retry-1})};fnComplete=function(){if(!self._isAborted()){self._raise('filechunkcomplete',[id,index,retry,fm,rm,self._getOutData(fd)])}};self._ajaxSubmit(fnBefore,fnSuccess,fnComplete,fnError,fd,id,rm.fileIndex)}};rm.reset()},_initTemplateDefaults:function(){var self=this,tMain1,tMain2,tPreview,tFileIcon,tClose,tCaption,tBtnDefault,tBtnLink,tBtnBrowse,tModalMain,tModal,tProgress,tSize,tFooter,tActions,tActionDelete,tActionUpload,tActionDownload,tActionZoom,tActionDrag,tIndicator,tTagBef,tTagBef1,tTagBef2,tTagAft,tGeneric,tHtml,tImage,tText,tOffice,tGdocs,tVideo,tAudio,tFlash,tObject,tPdf,tOther,tStyle,tZoomCache,vDefaultDim,tActionRotate,tStats,tModalLabel,tDescClose,renderObject=function(type,mime){return'<object class="kv-preview-data file-preview-'+type+'" title="{caption}" data="{data}" type="'+mime+'"'+tStyle+'>\n'+$h.DEFAULT_PREVIEW+'\n</object>\n'},defBtnCss1='btn btn-sm btn-kv '+$h.defaultButtonCss();tMain1='{preview}\n<div class="kv-upload-progress kv-hidden"></div><div class="clearfix"></div>\n<div class="file-caption {class}">\n  <div class="input-group {inputGroupClass}">\n      {caption}\n<span class="file-caption-icon"></span>\n'+($h.isBs(5)?'':'<div class="input-group-btn input-group-append">\n')+'      {remove}\n      {cancel}\n      {pause}\n      {upload}\n      {browse}\n'+($h.isBs(5)?'':'    </div>\n')+'  </div>';'</div>';tMain2='{preview}\n<div class="kv-upload-progress kv-hidden"></div>\n<div class="clearfix"></div>\n<span class="{class}">{remove}\n{cancel}\n{upload}\n{browse}\n</span>';tPreview='<div class="file-preview {class}">\n  {close}  <div class="{dropClass} clearfix">\n    <div class="file-preview-thumbnails clearfix">\n    </div>\n    <div class="file-preview-status text-center text-success"></div>\n    <div class="kv-fileinput-error"></div>\n  </div>\n</div>';tClose=$h.closeButton('fileinput-remove');tFileIcon='<i class="glyphicon glyphicon-file"></i>';tCaption='<input readonly class="file-caption-name form-control {class}">\n';tBtnDefault='<button type="{type}" title="{title}" class="{css}" {status} {tabIndexConfig}>{icon} {label}</button>';tBtnLink='<a href="{href}" title="{title}" class="{css}" {status} {tabIndexConfig}>{icon} {label}</a>';tBtnBrowse='<div class="{css}" {status} {tabIndexConfig}>{icon} {label}</div>';tModalLabel=$h.MODAL_ID+'Label';tModalMain='<div id="'+$h.MODAL_ID+'" class="file-zoom-dialog modal fade" aria-labelledby="'+tModalLabel+'" {tabIndexConfig}></div>';tModal='<div class="modal-dialog modal-lg{rtl}" role="document">\n  <div class="modal-content">\n    <div class="modal-header kv-zoom-header">\n      <h6 class="modal-title kv-zoom-title" id="'+tModalLabel+'"><span class="kv-zoom-caption"></span> <span class="kv-zoom-size"></span></h6>\n      <div class="kv-zoom-actions">{toggleheader}{fullscreen}{borderless}{close}</div>\n    </div>\n    <div class="floating-buttons"></div>\n    <div class="kv-zoom-body file-zoom-content {zoomFrameClass}"></div>\n{prev} {next}\n    <div class="kv-zoom-description"></div>\n  </div>\n</div>\n';tDescClose='<button type="button" class="kv-desc-hide" aria-label="Close">{closeIcon}</button>';tProgress='<div class="progress">\n    <div class="{class}" role="progressbar" aria-valuenow="{percent}" aria-valuemin="0" aria-valuemax="100" style="width:{percent}%;">\n        {status}\n     </div>\n</div>{stats}';tStats='<div class="text-primary file-upload-stats"><span class="pending-time">{pendingTime}</span> <span class="upload-speed">{uploadSpeed}</span></div>';tSize=' <samp>({sizeText})</samp>';tFooter='<div class="file-thumbnail-footer">\n    <div class="file-footer-caption" title="{caption}">\n        <div class="file-caption-info">{caption}</div>\n        <div class="file-size-info">{size}</div>\n    </div>\n    {progress}\n{indicator}\n{actions}\n</div>';tActions='<div class="file-actions">\n    <div class="file-footer-buttons">\n        {rotate} {download} {upload} {delete} {zoom} {other}    </div>\n</div>\n{drag}\n<div class="clearfix"></div>';tActionDelete='<button type="button" class="kv-file-remove {removeClass}" title="{removeTitle}" {dataUrl}{dataKey}>{removeIcon}</button>\n';tActionUpload='<button type="button" class="kv-file-upload {uploadClass}" title="{uploadTitle}">{uploadIcon}</button>';tActionRotate='<button type="button" class="kv-file-rotate {rotateClass}" title="{rotateTitle}">{rotateIcon}</button>';tActionDownload='<a class="kv-file-download {downloadClass}" title="{downloadTitle}" href="{downloadUrl}" download="{caption}" target="_blank">{downloadIcon}</a>';tActionZoom='<button type="button" class="kv-file-zoom {zoomClass}" title="{zoomTitle}">{zoomIcon}</button>';tActionDrag='<span class="file-drag-handle {dragClass}" title="{dragTitle}">{dragIcon}</span>';tIndicator='<div class="file-upload-indicator" title="{indicatorTitle}">{indicator}</div>';tTagBef='<div class="file-preview-frame {frameClass}" id="{previewId}" data-fileindex="{fileindex}" data-fileid="{fileid}" data-filename="{filename}" data-template="{template}" data-zoom="{zoomData}"';tTagBef1=tTagBef+'><div class="kv-file-content">\n';tTagBef2=tTagBef+' title="{caption}"><div class="kv-file-content">\n';tTagAft='</div>{footer}\n{zoomCache}</div>\n';tGeneric='{content}\n';tStyle=' {style}';tHtml=renderObject('html','text/html');tText=renderObject('text','text/plain;charset=UTF-8');tPdf=renderObject('pdf','application/pdf');tImage='<img src="{data}" class="file-preview-image kv-preview-data" title="{title}" alt="{alt}"'+tStyle+'>\n';tOffice='<iframe class="kv-preview-data file-preview-office" src="https://view.officeapps.live.com/op/embed.aspx?src={data}"'+tStyle+'></iframe>';tGdocs='<iframe class="kv-preview-data file-preview-gdocs" src="https://docs.google.com/gview?url={data}&embedded=true"'+tStyle+'></iframe>';tVideo='<video class="kv-preview-data file-preview-video" controls'+tStyle+'>\n<source src="{data}" type="{type}">\n'+$h.DEFAULT_PREVIEW+'\n</video>\n';tAudio='<!--suppress ALL --><audio class="kv-preview-data file-preview-audio" controls'+tStyle+'>\n<source src="{data}" type="{type}">\n'+$h.DEFAULT_PREVIEW+'\n</audio>\n';tFlash='<embed class="kv-preview-data file-preview-flash" src="{data}" type="application/x-shockwave-flash"'+tStyle+'>\n';tObject='<object class="kv-preview-data file-preview-object file-object {typeCss}" data="{data}" type="{type}"'+tStyle+'>\n<param name="movie" value="{caption}" />\n'+$h.OBJECT_PARAMS+' '+$h.DEFAULT_PREVIEW+'\n</object>\n';tOther='<div class="kv-preview-data file-preview-other-frame"'+tStyle+'>\n'+$h.DEFAULT_PREVIEW+'\n</div>\n';tZoomCache='<div class="kv-zoom-cache">{zoomContent}</div>';vDefaultDim={width:'100%',height:'100%','min-height':'480px'};if(self._isPdfRendered()){tPdf=self.pdfRendererTemplate.replace('{renderer}',self._encodeURI(self.pdfRendererUrl))}self.defaults={layoutTemplates:{main1:tMain1,main2:tMain2,preview:tPreview,close:tClose,fileIcon:tFileIcon,caption:tCaption,modalMain:tModalMain,modal:tModal,descriptionClose:tDescClose,progress:tProgress,stats:tStats,size:tSize,footer:tFooter,indicator:tIndicator,actions:tActions,actionDelete:tActionDelete,actionRotate:tActionRotate,actionUpload:tActionUpload,actionDownload:tActionDownload,actionZoom:tActionZoom,actionDrag:tActionDrag,btnDefault:tBtnDefault,btnLink:tBtnLink,btnBrowse:tBtnBrowse,zoomCache:tZoomCache},previewMarkupTags:{tagBefore1:tTagBef1,tagBefore2:tTagBef2,tagAfter:tTagAft},previewContentTemplates:{generic:tGeneric,html:tHtml,image:tImage,text:tText,office:tOffice,gdocs:tGdocs,video:tVideo,audio:tAudio,flash:tFlash,object:tObject,pdf:tPdf,other:tOther},allowedPreviewTypes:['image','html','text','video','audio','flash','pdf','object'],previewTemplates:{},previewSettings:{image:{width:'auto',height:'auto','max-width':'100%','max-height':'100%'},html:{width:'213px',height:'160px'},text:{width:'213px',height:'160px'},office:{width:'213px',height:'160px'},gdocs:{width:'213px',height:'160px'},video:{width:'213px',height:'160px'},audio:{width:'100%',height:'30px'},flash:{width:'213px',height:'160px'},object:{width:'213px',height:'160px'},pdf:{width:'100%',height:'160px','position':'relative'},other:{width:'213px',height:'160px'}},previewSettingsSmall:{image:{width:'auto',height:'auto','max-width':'100%','max-height':'100%'},html:{width:'100%',height:'160px'},text:{width:'100%',height:'160px'},office:{width:'100%',height:'160px'},gdocs:{width:'100%',height:'160px'},video:{width:'100%',height:'auto'},audio:{width:'100%',height:'30px'},flash:{width:'100%',height:'auto'},object:{width:'100%',height:'auto'},pdf:{width:'100%',height:'160px'},other:{width:'100%',height:'160px'}},previewZoomSettings:{image:{width:'auto',height:'auto','max-width':'100%','max-height':'100%'},html:vDefaultDim,text:vDefaultDim,office:{width:'100%',height:'100%','max-width':'100%','min-height':'480px'},gdocs:{width:'100%',height:'100%','max-width':'100%','min-height':'480px'},video:{width:'auto',height:'100%','max-width':'100%'},audio:{width:'100%',height:'30px'},flash:{width:'auto',height:'480px'},object:{width:'auto',height:'100%','max-width':'100%','min-height':'480px'},pdf:vDefaultDim,other:{width:'auto',height:'100%','min-height':'480px'}},mimeTypeAliases:{'video/quicktime':'video/mp4'},fileTypeSettings:{image:function(vType,vName){return($h.compare(vType,'image.*')&&!$h.compare(vType,/(tiff?|wmf)$/i)||$h.compare(vName,/\.(gif|png|jpe?g)$/i))},html:function(vType,vName){return $h.compare(vType,'text/html')||$h.compare(vName,/\.(htm|html)$/i)},office:function(vType,vName){return $h.compare(vType,/(word|excel|powerpoint|office)$/i)||$h.compare(vName,/\.(docx?|xlsx?|pptx?|pps|potx?)$/i)},gdocs:function(vType,vName){return $h.compare(vType,/(word|excel|powerpoint|office|iwork-pages|tiff?)$/i)||$h.compare(vName,/\.(docx?|xlsx?|pptx?|pps|potx?|rtf|ods|odt|pages|ai|dxf|ttf|tiff?|wmf|e?ps)$/i)},text:function(vType,vName){return $h.compare(vType,'text.*')||$h.compare(vName,/\.(xml|javascript)$/i)||$h.compare(vName,/\.(txt|md|nfo|ini|json|php|js|css)$/i)},video:function(vType,vName){return $h.compare(vType,'video.*')&&($h.compare(vType,/(ogg|mp4|mp?g|mov|webm|3gp)$/i)||$h.compare(vName,/\.(og?|mp4|webm|mp?g|mov|3gp)$/i))},audio:function(vType,vName){return $h.compare(vType,'audio.*')&&($h.compare(vName,/(ogg|mp3|mp?g|wav)$/i)||$h.compare(vName,/\.(og?|mp3|mp?g|wav)$/i))},flash:function(vType,vName){return $h.compare(vType,'application/x-shockwave-flash',true)||$h.compare(vName,/\.(swf)$/i)},pdf:function(vType,vName){return $h.compare(vType,'application/pdf',true)||$h.compare(vName,/\.(pdf)$/i)},object:function(){return true},other:function(){return true}},fileActionSettings:{showRemove:true,showUpload:true,showDownload:true,showZoom:true,showDrag:true,showRotate:false,removeIcon:'<i class="glyphicon glyphicon-trash"></i>',removeClass:defBtnCss1,removeErrorClass:'btn btn-sm btn-kv btn-danger',removeTitle:'Remove file',uploadIcon:'<i class="glyphicon glyphicon-upload"></i>',uploadClass:defBtnCss1,uploadTitle:'Upload file',uploadRetryIcon:'<i class="glyphicon glyphicon-repeat"></i>',uploadRetryTitle:'Retry upload',downloadIcon:'<i class="glyphicon glyphicon-download"></i>',downloadClass:defBtnCss1,downloadTitle:'Download file',rotateIcon:'<i class="glyphicon glyphicon-repeat"></i>',rotateClass:defBtnCss1,rotateTitle:'Rotate 90 deg. clockwise',zoomIcon:'<i class="glyphicon glyphicon-zoom-in"></i>',zoomClass:defBtnCss1,zoomTitle:'View Details',dragIcon:'<i class="glyphicon glyphicon-move"></i>',dragClass:'text-primary',dragTitle:'Move / Rearrange',dragSettings:{},indicatorNew:'<i class="glyphicon glyphicon-plus-sign text-warning"></i>',indicatorSuccess:'<i class="glyphicon glyphicon-ok-sign text-success"></i>',indicatorError:'<i class="glyphicon glyphicon-exclamation-sign text-danger"></i>',indicatorLoading:'<i class="glyphicon glyphicon-hourglass text-muted"></i>',indicatorPaused:'<i class="glyphicon glyphicon-pause text-primary"></i>',indicatorNewTitle:'Not uploaded yet',indicatorSuccessTitle:'Uploaded',indicatorErrorTitle:'Upload Error',indicatorLoadingTitle:'Uploading &hellip;',indicatorPausedTitle:'Upload Paused'}};$.each(self.defaults,function(key,setting){if(key==='allowedPreviewTypes'){if(self.allowedPreviewTypes===undefined){self.allowedPreviewTypes=setting}return}self[key]=$.extend(true,{},setting,self[key])});self._initPreviewTemplates()},_initPreviewTemplates:function(){var self=this,tags=self.previewMarkupTags,tagBef,tagAft=tags.tagAfter;$.each(self.previewContentTemplates,function(key,value){if($h.isEmpty(self.previewTemplates[key])){tagBef=tags.tagBefore2;if(key==='generic'||key==='image'){tagBef=tags.tagBefore1}if(self._isPdfRendered()&&key==='pdf'){tagBef=tagBef.replace('kv-file-content','kv-file-content kv-pdf-rendered')}self.previewTemplates[key]=tagBef+value+tagAft}})},_initPreviewCache:function(){var self=this;self.previewCache={data:{},init:function(){var content=self.initialPreview;if(content.length>0&&!$h.isArray(content)){content=content.split(self.initialPreviewDelimiter)}self.previewCache.data={content:content,config:self.initialPreviewConfig,tags:self.initialPreviewThumbTags}},count:function(skipNull){if(!self.previewCache.data||!self.previewCache.data.content){return 0}if(skipNull){var chk=self.previewCache.data.content.filter(function(n){return n!==null});return chk.length}return self.previewCache.data.content.length},get:function(i,isDisabled){var ind=$h.INIT_FLAG+i,data=self.previewCache.data,config=data.config[i],content=data.content[i],out,$tmp,cat,ftr,fname,ftype,frameClass,asData=$h.ifSet('previewAsData',config,self.initialPreviewAsData),a=config?{title:config.title||null,alt:config.alt||null}:{title:null,alt:null},parseTemplate=function(cat,dat,fname,ftype,ftr,ind,fclass,t){var fc=' file-preview-initial '+$h.SORT_CSS+(fclass?' '+fclass:''),id=self.previewInitId+'-'+ind,fileId=config&&config.fileId||id;return self._generatePreviewTemplate(cat,dat,fname,ftype,id,fileId,false,null,null,fc,ftr,ind,t,a,config&&config.zoomData||dat)};if(!content||!content.length){return''}isDisabled=isDisabled===undefined?true:isDisabled;cat=$h.ifSet('type',config,self.initialPreviewFileType||'generic');fname=$h.ifSet('filename',config,$h.ifSet('caption',config));ftype=$h.ifSet('filetype',config,cat);ftr=self.previewCache.footer(i,isDisabled,(config&&config.size||null));frameClass=$h.ifSet('frameClass',config);if(asData){out=parseTemplate(cat,content,fname,ftype,ftr,ind,frameClass)}else{out=parseTemplate('generic',content,fname,ftype,ftr,ind,frameClass,cat).setTokens({'content':data.content[i]})}if(data.tags.length&&data.tags[i]){out=$h.replaceTags(out,data.tags[i])}if(!$h.isEmpty(config)&&!$h.isEmpty(config.frameAttr)){$tmp=$h.createElement(out);$tmp.find('.file-preview-initial').attr(config.frameAttr);out=$tmp.html();$tmp.remove()}return out},clean:function(data){data.content=$h.cleanArray(data.content);data.config=$h.cleanArray(data.config);data.tags=$h.cleanArray(data.tags);self.previewCache.data=data},add:function(content,config,tags,append){var data=self.previewCache.data,index;if(!content||!content.length){return 0}index=content.length-1;if(!$h.isArray(content)){content=content.split(self.initialPreviewDelimiter)}if(append&&data.content){index=data.content.push(content[0])-1;data.config[index]=config;data.tags[index]=tags}else{data.content=content;data.config=config;data.tags=tags}self.previewCache.clean(data);return index},set:function(content,config,tags,append){var data=self.previewCache.data,i,chk;if(!content||!content.length){return}if(!$h.isArray(content)){content=content.split(self.initialPreviewDelimiter)}chk=content.filter(function(n){return n!==null});if(!chk.length){return}if(data.content===undefined){data.content=[]}if(data.config===undefined){data.config=[]}if(data.tags===undefined){data.tags=[]}if(append){for(i=0;i<content.length;i++){if(content[i]){data.content.push(content[i])}}for(i=0;i<config.length;i++){if(config[i]){data.config.push(config[i])}}for(i=0;i<tags.length;i++){if(tags[i]){data.tags.push(tags[i])}}}else{data.content=content;data.config=config;data.tags=tags}self.previewCache.clean(data)},unset:function(index){var chk=self.previewCache.count(),rev=self.reversePreviewOrder;if(!chk){return}if(chk===1){self.previewCache.data.content=[];self.previewCache.data.config=[];self.previewCache.data.tags=[];self.initialPreview=[];self.initialPreviewConfig=[];self.initialPreviewThumbTags=[];return}self.previewCache.data.content=$h.spliceArray(self.previewCache.data.content,index,rev);self.previewCache.data.config=$h.spliceArray(self.previewCache.data.config,index,rev);self.previewCache.data.tags=$h.spliceArray(self.previewCache.data.tags,index,rev);var data=$.extend(true,{},self.previewCache.data);self.previewCache.clean(data)},out:function(){var html='',caption,len=self.previewCache.count(),i,content;if(len===0){return{content:'',caption:''}}for(i=0;i<len;i++){content=self.previewCache.get(i);html=self.reversePreviewOrder?(content+html):(html+content)}caption=self._getMsgSelected(len);return{content:html,caption:caption}},footer:function(i,isDisabled,size){var data=self.previewCache.data||{};if($h.isEmpty(data.content)){return''}if($h.isEmpty(data.config)||$h.isEmpty(data.config[i])){data.config[i]={}}isDisabled=isDisabled===undefined?true:isDisabled;var config=data.config[i],caption=$h.ifSet('caption',config),a,width=$h.ifSet('width',config,'auto'),url=$h.ifSet('url',config,false),key=$h.ifSet('key',config,null),fileId=$h.ifSet('fileId',config,null),fs=self.fileActionSettings,initPreviewShowDel=self.initialPreviewShowDelete||false,downloadInitialUrl=!self.initialPreviewDownloadUrl?'':self.initialPreviewDownloadUrl+'?key='+key+(fileId?'&fileId='+fileId:''),dUrl=config.downloadUrl||downloadInitialUrl,dFil=config.filename||config.caption||'',initPreviewShowDwl=!!(dUrl),sDel=$h.ifSet('showRemove',config,initPreviewShowDel),sRot=$h.ifSet('showRotate',config,$h.ifSet('showRotate',fs,true)),sDwl=$h.ifSet('showDownload',config,$h.ifSet('showDownload',fs,initPreviewShowDwl)),sZm=$h.ifSet('showZoom',config,$h.ifSet('showZoom',fs,true)),sDrg=$h.ifSet('showDrag',config,$h.ifSet('showDrag',fs,true)),dis=(url===false)&&isDisabled;sDwl=sDwl&&config.downloadUrl!==false&&!!dUrl;a=self._renderFileActions(config,false,sDwl,sDel,sRot,sZm,sDrg,dis,url,key,true,dUrl,dFil);return self._getLayoutTemplate('footer').setTokens({'progress':self._renderThumbProgress(),'actions':a,'caption':caption,'size':self._getSize(size),'width':width,'indicator':''})}};self.previewCache.init()},_isPdfRendered:function(){var self=this,useLib=self.usePdfRenderer,flag=typeof useLib==='function'?useLib():!!useLib;return flag&&self.pdfRendererUrl},_handler:function($el,event,callback){var self=this,ns=self.namespace,ev=event.split(' ').join(ns+' ')+ns;if(!$el||!$el.length){return}$el.off(ev).on(ev,callback)},_encodeURI:function(vUrl){var self=this;return self.encodeUrl?encodeURI(vUrl):vUrl},_log:function(msg,tokens){var self=this,id=self.$element.attr('id');if(!self.showConsoleLogs){return}if(id){msg='"'+id+'": '+msg}msg='bootstrap-fileinput: '+msg;if(typeof tokens==='object'){msg=msg.setTokens(tokens)}if(window.console&&typeof window.console.log!=='undefined'){window.console.log(msg)}else{window.alert(msg)}},_validate:function(){var self=this,status=self.$element.attr('type')==='file';if(!status){self._log($h.logMessages.badInputType)}return status},_errorsExist:function(){var self=this,$err,$errList=self.$errorContainer.find('li');if($errList.length){return true}$err=$h.createElement(self.$errorContainer.html());$err.find('.kv-error-close').remove();$err.find('ul').remove();return!!$.trim($err.text()).length},_errorHandler:function(evt,caption){var self=this,err=evt.target.error,showError=function(msg){self._showError(msg.replace('{name}',caption))};if(err.code===err.NOT_FOUND_ERR){showError(self.msgFileNotFound)}else{if(err.code===err.SECURITY_ERR){showError(self.msgFileSecured)}else{if(err.code===err.NOT_READABLE_ERR){showError(self.msgFileNotReadable)}else{if(err.code===err.ABORT_ERR){showError(self.msgFilePreviewAborted)}else{showError(self.msgFilePreviewError)}}}}},_addError:function(msg){var self=this,$error=self.$errorContainer;if(msg&&$error.length){$h.setHtml($error,self.errorCloseButton+msg);self._handler($error.find('.kv-error-close'),'click',function(){setTimeout(function(){if(self.showPreview&&!self.getFrames().length){self.clear()}$error.fadeOut('slow')},self.processDelay)})}},_setValidationError:function(css){var self=this;css=(css?css+' ':'')+'has-error';self.$container.removeClass(css).addClass('has-error');$h.addCss(self.$caption,'is-invalid')},_resetErrors:function(fade){var self=this,$error=self.$errorContainer,history=self.resumableUploadOptions.retainErrorHistory;if(self.isPersistentError||(self.enableResumableUpload&&history&&!self.clearInput)){return}self.clearInput=false;self.isError=false;self.$container.removeClass('has-error');self.$caption.removeClass('is-invalid is-valid file-processing');$error.html('');if(fade){$error.fadeOut('slow')}else{$error.hide()}},_showFolderError:function(folders){var self=this,$error=self.$errorContainer,msg;if(!folders){return}if(!self.isAjaxUpload){self._clearFileInput()}msg=self.msgFoldersNotAllowed.replace('{n}',folders);self._addError(msg);self._setValidationError();$error.fadeIn(self.fadeDelay);self._raise('filefoldererror',[folders,msg])},showUserError:function(msg,params,retainErrorHistory){var self=this,fileName;if(!self.uploadInitiated){return}if(!params||!params.fileId){if(!retainErrorHistory){self.$errorContainer.html('')}}else{if(!retainErrorHistory){self.$errorContainer.find('[data-file-id="'+params.fileId+'"]').remove()}fileName=self.fileManager.getFileName(params.fileId);if(fileName){msg='<b>'+fileName+':</b> '+msg}}self._showFileError(msg,params,'fileusererror')},_showFileError:function(msg,params,event){var self=this,$error=self.$errorContainer,ev=event||'fileuploaderror',fId=params&&params.fileId||'',e=params&&params.id?'<li data-thumb-id="'+params.id+'" data-file-id="'+fId+'">'+msg+'</li>':'<li>'+msg+'</li>';if($error.find('ul').length===0){self._addError('<ul>'+e+'</ul>')}else{$error.find('ul').append(e)}$error.fadeIn(self.fadeDelay);self._raise(ev,[params,msg]);self._setValidationError('file-input-new');return true},_showError:function(msg,params,event){var self=this,$error=self.$errorContainer,ev=event||'fileerror';params=params||{};params.reader=self.reader;self._addError(msg);$error.fadeIn(self.fadeDelay);self._raise(ev,[params,msg]);if(!self.isAjaxUpload){self._clearFileInput()}self._setValidationError('file-input-new');self.$btnUpload.attr('disabled',true);return true},_noFilesError:function(params){var self=this,label=self.minFileCount>1?self.filePlural:self.fileSingle,msg=self.msgFilesTooLess.replace('{n}',self.minFileCount).replace('{files}',label),$error=self.$errorContainer;msg='<li>'+msg+'</li>';if($error.find('ul').length===0){self._addError('<ul>'+msg+'</ul>')}else{$error.find('ul').append(msg)}self.isError=true;self._updateFileDetails(0);$error.fadeIn(self.fadeDelay);self._raise('fileerror',[params,msg]);self._clearFileInput();self._setValidationError()},_parseError:function(operation,jqXHR,errorThrown,fileName){var self=this,errMsg=$.trim(errorThrown+''),textPre,errText,text;errText=jqXHR.responseJSON&&jqXHR.responseJSON.error?jqXHR.responseJSON.error.toString():'';text=errText?errText:jqXHR.responseText;if(self.cancelling&&self.msgUploadAborted){errMsg=self.msgUploadAborted}if(self.showAjaxErrorDetails&&text){if(errText){errMsg=$.trim(errText+'')}else{text=$.trim(text.replace(/\n\s*\n/g,'\n'));textPre=text.length?'<pre>'+text+'</pre>':'';errMsg+=errMsg?textPre:text}}if(!errMsg){errMsg=self.msgAjaxError.replace('{operation}',operation)}self.cancelling=false;return fileName?'<b>'+fileName+': </b>'+errMsg:errMsg},_parseFileType:function(type,name){var self=this,isValid,vType,cat,i,types=self.allowedPreviewTypes||[];if(type==='application/text-plain'){return'text'}for(i=0;i<types.length;i++){cat=types[i];isValid=self.fileTypeSettings[cat];vType=isValid(type,name)?cat:'';if(!$h.isEmpty(vType)){return vType}}return'other'},_getPreviewIcon:function(fname){var self=this,ext,out=null;if(fname&&fname.indexOf('.')>-1){ext=fname.split('.').pop();if(self.previewFileIconSettings){out=self.previewFileIconSettings[ext]||self.previewFileIconSettings[ext.toLowerCase()]||null}if(self.previewFileExtSettings){$.each(self.previewFileExtSettings,function(key,func){if(self.previewFileIconSettings[key]&&func(ext)){out=self.previewFileIconSettings[key];return}})}}return out||self.previewFileIcon},_parseFilePreviewIcon:function(content,fname){var self=this,icn=self._getPreviewIcon(fname),out=content;if(out.indexOf('{previewFileIcon}')>-1){out=out.setTokens({'previewFileIconClass':self.previewFileIconClass,'previewFileIcon':icn})}return out},_raise:function(event,params){var self=this,e=$.Event(event);if(params!==undefined){self.$element.trigger(e,params)}else{self.$element.trigger(e)}var out=e.result,isAborted=out===false;if(e.isDefaultPrevented()||isAborted){return false}if(e.type==='filebatchpreupload'&&(out||isAborted)){self.ajaxAborted=out;return false}switch(event){case'filebatchuploadcomplete':case'filebatchuploadsuccess':case'fileuploaded':case'fileclear':case'filecleared':case'filereset':case'fileerror':case'filefoldererror':case'filecustomerror':case'filesuccessremove':break;default:if(!self.ajaxAborted){self.ajaxAborted=out}break}return true},_listenFullScreen:function(isFullScreen){var self=this,$modal=self.$modal,$btnFull,$btnBord;if(!$modal||!$modal.length){return}$btnFull=$modal&&$modal.find('.btn-kv-fullscreen');$btnBord=$modal&&$modal.find('.btn-kv-borderless');if(!$btnFull.length||!$btnBord.length){return}$btnFull.removeClass('active').attr('aria-pressed','false');$btnBord.removeClass('active').attr('aria-pressed','false');if(isFullScreen){$btnFull.addClass('active').attr('aria-pressed','true')}else{$btnBord.addClass('active').attr('aria-pressed','true')}if($modal.hasClass('file-zoom-fullscreen')){self._maximizeZoomDialog()}else{if(isFullScreen){self._maximizeZoomDialog()}else{$btnBord.removeClass('active').attr('aria-pressed','false')}}},_listen:function(){var self=this,$el=self.$element,$form=self.$form,$cont=self.$container,fullScreenEv;self._handler($el,'click',function(e){self._initFileSelected();if($el.hasClass('file-no-browse')){if($el.data('zoneClicked')){$el.data('zoneClicked',false)}else{e.preventDefault()}}});self._handler($el,'change',$.proxy(self._change,self));self._handler(self.$caption,'paste',$.proxy(self.paste,self));if(self.showBrowse){self._handler(self.$btnFile,'click',$.proxy(self._browse,self));self._handler(self.$btnFile,'keypress',function(e){var keycode=e.keyCode||e.which;if(keycode===13){$el.trigger('click');self._browse(e)}})}self._handler($cont.find('.fileinput-remove:not([disabled])'),'click',$.proxy(self.clear,self));self._handler($cont.find('.fileinput-cancel'),'click',$.proxy(self.cancel,self));self._handler($cont.find('.fileinput-pause'),'click',$.proxy(self.pause,self));self._initDragDrop();self._handler($form,'reset',$.proxy(self.clear,self));if(!self.isAjaxUpload){self._handler($form,'submit',$.proxy(self._submitForm,self))}self._handler(self.$container.find('.fileinput-upload'),'click',$.proxy(self._uploadClick,self));self._handler($(window),'resize',function(){self._listenFullScreen(screen.width===window.innerWidth&&screen.height===window.innerHeight)});fullScreenEv='webkitfullscreenchange mozfullscreenchange fullscreenchange MSFullscreenChange';self._handler($(document),fullScreenEv,function(){self._listenFullScreen($h.checkFullScreen())});self.$caption.on('focus',function(){self.$captionContainer.focus()});self._autoFitContent();self._initClickable();self._refreshPreview()},_autoFitContent:function(){var width=window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth,self=this,config=width<400?(self.previewSettingsSmall||self.defaults.previewSettingsSmall):(self.previewSettings||self.defaults.previewSettings),sel;$.each(config,function(cat,settings){sel='.file-preview-frame .file-preview-'+cat;self.$preview.find(sel+'.kv-preview-data,'+sel+' .kv-preview-data').css(settings)})},_scanDroppedItems:function(item,files,path){path=path||'';var self=this,i,dirReader,readDir,errorHandler=function(e){self._log($h.logMessages.badDroppedFiles);self._log(e)};if(item.isFile){item.file(function(file){if(path){file.newPath=path+file.name}files.push(file)},errorHandler)}else{if(item.isDirectory){dirReader=item.createReader();readDir=function(){dirReader.readEntries(function(entries){if(entries&&entries.length>0){for(i=0;i<entries.length;i++){self._scanDroppedItems(entries[i],files,path+item.name+'/')}readDir()}return null},errorHandler)};readDir()}}},_initDragDrop:function(){var self=this,$zone=self.$dropZone;if(self.dropZoneEnabled&&self.showPreview){self._handler($zone,'dragenter dragover',$.proxy(self._zoneDragEnter,self));self._handler($zone,'dragleave',$.proxy(self._zoneDragLeave,self));self._handler($zone,'drop',$.proxy(self._zoneDrop,self));self._handler($(document),'dragenter dragover drop',self._zoneDragDropInit)}},_zoneDragDropInit:function(e){e.stopPropagation();e.preventDefault()},_zoneDragEnter:function(e){var self=this,dt=e.originalEvent.dataTransfer,hasFiles=$.inArray('Files',dt.types)>-1;self._zoneDragDropInit(e);if(self.isDisabled||!hasFiles){dt.effectAllowed='none';dt.dropEffect='none';return}dt.dropEffect='copy';if(self._raise('fileDragEnter',{'sourceEvent':e,'files':dt.types.Files})){$h.addCss(self.$dropZone,'file-highlighted')}},_zoneDragLeave:function(e){var self=this;self._zoneDragDropInit(e);if(self.isDisabled){return}if(self._raise('fileDragLeave',{'sourceEvent':e})){self.$dropZone.removeClass('file-highlighted')}},_dropFiles:function(e,files){var self=this,$el=self.$element;if(!self.isAjaxUpload){self.changeTriggered=true;$el.get(0).files=files;setTimeout(function(){self.changeTriggered=false;$el.trigger('change'+self.namespace)},self.processDelay)}else{self._change(e,files)}self.$dropZone.removeClass('file-highlighted')},_zoneDrop:function(e){var self=this,i,$el=self.$element,dt=e.originalEvent.dataTransfer,files=dt.files,items=dt.items,folders=$h.getDragDropFolders(items);e.preventDefault();if(self.isDisabled||$h.isEmpty(files)){return}if(!self._raise('fileDragDrop',{'sourceEvent':e,'files':files})){return}if(folders>0){if(!self.isAjaxUpload){self._showFolderError(folders);return}files=[];for(i=0;i<items.length;i++){var item=items[i].webkitGetAsEntry();if(item){self._scanDroppedItems(item,files)}}setTimeout(function(){self._dropFiles(e,files)},500)}else{self._dropFiles(e,files)}},_uploadClick:function(e){var self=this,$btn=self.$container.find('.fileinput-upload'),$form,isEnabled=!$btn.hasClass('disabled')&&$h.isEmpty($btn.attr('disabled'));if(e&&e.isDefaultPrevented()){return}if(!self.isAjaxUpload){if(isEnabled&&$btn.attr('type')!=='submit'){e.preventDefault();$form=$btn.closest('form');if($form.length){$form.trigger('submit')}}return}e.preventDefault();if(isEnabled){self.upload()}},_submitForm:function(){var self=this;return self._isFileSelectionValid()&&!self._abort({})},_clearPreview:function(){var self=this,$thumbs=self.showUploadedThumbs?self.getFrames(':not(.file-preview-success)'):self.getFrames();$thumbs.each(function(){var $thumb=$(this);$thumb.remove()});if(!self.getFrames().length||!self.showPreview){self._resetUpload()}self._validateDefaultPreview()},_initSortable:function(){var self=this,$el=self.$preview,settings,selector='.'+$h.SORT_CSS,$cont,$body=$('body'),$html=$('html'),rev=self.reversePreviewOrder,Sortable=window.Sortable,beginGrab,endGrab;if(!Sortable||$el.find(selector).length===0){return}$cont=$body.length?$body:($html.length?$html:self.$container);beginGrab=function(){$cont.addClass('file-grabbing')};endGrab=function(){$cont.removeClass('file-grabbing')};settings={handle:'.drag-handle-init',dataIdAttr:'data-fileid',animation:600,draggable:selector,scroll:false,forceFallback:true,onChoose:beginGrab,onStart:beginGrab,onUnchoose:endGrab,onEnd:endGrab,onSort:function(e){var oldIndex=e.oldIndex,newIndex=e.newIndex,i=0,len=self.initialPreviewConfig.length,exceedsLast=len>0&&newIndex>=len,$item=$(e.item),$first;if(exceedsLast){newIndex=len-1}self.initialPreview=$h.moveArray(self.initialPreview,oldIndex,newIndex,rev);self.initialPreviewConfig=$h.moveArray(self.initialPreviewConfig,oldIndex,newIndex,rev);self.previewCache.init();self.getFrames('.file-preview-initial').each(function(){$(this).attr('data-fileindex',$h.INIT_FLAG+i);i++});if(exceedsLast){$first=self.getFrames(':not(.file-preview-initial):first');if($first.length){$item.slideUp(function(){$item.insertBefore($first).slideDown()})}}self._raise('filesorted',{previewId:$item.attr('id'),'oldIndex':oldIndex,'newIndex':newIndex,stack:self.initialPreviewConfig})},};$.extend(true,settings,self.fileActionSettings.dragSettings);if(self.sortable){self.sortable.destroy()}self.sortable=Sortable.create($el[0],settings)},_setPreviewContent:function(content){var self=this;$h.setHtml(self.$preview,content);self._autoFitContent()},_initPreviewImageOrientations:function(){var self=this,i=0,canOrientImage=self.canOrientImage;if(!self.autoOrientImageInitial&&!canOrientImage){return}self.getFrames('.file-preview-initial').each(function(){var $thumb=$(this),$img,$zoomImg,id,config=self.initialPreviewConfig[i];if(config&&config.exif&&config.exif.Orientation){id=$thumb.attr('id');$img=$thumb.find('>.kv-file-content img');$zoomImg=self._getZoom(id,' >.kv-file-content img');if(canOrientImage){$img.css('image-orientation',(self.autoOrientImageInitial?'from-image':'none'))}else{self.setImageOrientation($img,$zoomImg,config.exif.Orientation,$thumb)}}i++})},_initPreview:function(isInit){var self=this,cap=self.initialCaption||'',out;if(!self.previewCache.count(true)){self._clearPreview();if(isInit){self._setCaption(cap)}else{self._initCaption()}return}out=self.previewCache.out();cap=isInit&&self.initialCaption?self.initialCaption:out.caption;self._setPreviewContent(out.content);self._setInitThumbAttr();self._setCaption(cap);self._initSortable();if(!$h.isEmpty(out.content)){self.$container.removeClass('file-input-new')}self._initPreviewImageOrientations()},_getZoomButton:function(type){var self=this,label=self.previewZoomButtonIcons[type],css=self.previewZoomButtonClasses[type],title=' title="'+(self.previewZoomButtonTitles[type]||'')+'" ',tag=$h.isBs(5)?'bs-':'',params=title+(type==='close'?' data-'+tag+'dismiss="modal" aria-hidden="true"':'');if(type==='fullscreen'||type==='borderless'||type==='toggleheader'){params+=' data-toggle="button" aria-pressed="false" autocomplete="off"'}return'<button type="button" class="'+css+' btn-kv-'+type+'"'+params+'>'+label+'</button>'},_getModalContent:function(){var self=this;return self._getLayoutTemplate('modal').setTokens({'rtl':self.rtl?' kv-rtl':'','zoomFrameClass':self.frameClass,'prev':self._getZoomButton('prev'),'next':self._getZoomButton('next'),'rotate':self._getZoomButton('rotate'),'toggleheader':self._getZoomButton('toggleheader'),'fullscreen':self._getZoomButton('fullscreen'),'borderless':self._getZoomButton('borderless'),'close':self._getZoomButton('close')})},_listenModalEvent:function(event){var self=this,$modal=self.$modal,getParams=function(e){return{sourceEvent:e,previewId:$modal.data('previewId'),modal:$modal}};$modal.on(event+'.bs.modal',function(e){if(e.namespace!=='bs.modal'){return}var $btnFull=$modal.find('.btn-fullscreen'),$btnBord=$modal.find('.btn-borderless');if($modal.data('fileinputPluginId')===self.$element.attr('id')){self._raise('filezoom'+event,getParams(e))}if(event==='shown'){self._handleRotation($modal,$modal.find('.file-zoom-detail'),$modal.data('angle'));$btnBord.removeClass('active').attr('aria-pressed','false');$btnFull.removeClass('active').attr('aria-pressed','false');if($modal.hasClass('file-zoom-fullscreen')){self._maximizeZoomDialog();if($h.checkFullScreen()){$btnFull.addClass('active').attr('aria-pressed','true')}else{$btnBord.addClass('active').attr('aria-pressed','true')}}}})},_initZoom:function(){var self=this,$dialog,modalMain=self._getLayoutTemplate('modalMain'),modalId='#'+$h.MODAL_ID;modalMain=self._setTabIndex('modal',modalMain);if(!self.showPreview){return}self.$modal=$(modalId);if(!self.$modal||!self.$modal.length){$dialog=$h.createElement($h.cspBuffer.stash(modalMain)).insertAfter(self.$container);self.$modal=$(modalId).insertBefore($dialog);$h.cspBuffer.apply(self.$modal);$dialog.remove()}$h.initModal(self.$modal);self.$modal.html($h.cspBuffer.stash(self._getModalContent()));$h.cspBuffer.apply(self.$modal);$.each($h.MODAL_EVENTS,function(key,event){self._listenModalEvent(event)})},_initZoomButtons:function(){var self=this,$modal=self.$modal,previewId=$modal.data('previewId')||'',$first,$last,thumbs=self.getFrames().toArray(),len=thumbs.length,$prev=$modal.find('.btn-kv-prev'),$next=$modal.find('.btn-kv-next'),$rotate=$modal.find('.btn-kv-rotate');if(thumbs.length<2){$prev.hide();$next.hide();return}else{$prev.show();$next.show()}if(!len){return}$first=$(thumbs[0]);$last=$(thumbs[len-1]);$prev.removeAttr('disabled');$next.removeAttr('disabled');if(self.reversePreviewOrder){[$prev,$next]=[$next,$prev]}if($first.length&&$first.attr('id')===previewId){$prev.attr('disabled',true)}if($last.length&&$last.attr('id')===previewId){$next.attr('disabled',true)}},_maximizeZoomDialog:function(){var self=this,$modal=self.$modal,$head=$modal.find('.modal-header:visible'),$foot=$modal.find('.modal-footer:visible'),$body=$modal.find('.kv-zoom-body'),h=$(window).height(),diff=0;$modal.addClass('file-zoom-fullscreen');if($head&&$head.length){h-=$head.outerHeight(true)}if($foot&&$foot.length){h-=$foot.outerHeight(true)}if($body&&$body.length){diff=$body.outerHeight(true)-$body.height();h-=diff}$modal.find('.kv-zoom-body').height(h)},_resizeZoomDialog:function(fullScreen){var self=this,$modal=self.$modal,$btnFull=$modal.find('.btn-kv-fullscreen'),$btnBord=$modal.find('.btn-kv-borderless');if($modal.hasClass('file-zoom-fullscreen')){$h.toggleFullScreen(false);if(!fullScreen){if(!$btnFull.hasClass('active')){$modal.removeClass('file-zoom-fullscreen');self.$modal.find('.kv-zoom-body').css('height',self.zoomModalHeight)}else{$btnFull.removeClass('active').attr('aria-pressed','false')}}else{if(!$btnFull.hasClass('active')){$modal.removeClass('file-zoom-fullscreen');self._resizeZoomDialog(true);if($btnBord.hasClass('active')){$btnBord.removeClass('active').attr('aria-pressed','false')}}}}else{if(!fullScreen){self._maximizeZoomDialog();return}$h.toggleFullScreen(true)}$modal.focus()},_setZoomContent:function($frame,navigate){var self=this,$content,tmplt,body,title,$body,$dataEl,config,previewId=$frame.attr('id'),$zoomPreview=self._getZoom(previewId),$modal=self.$modal,$tmp,desc,$desc,$btnFull=$modal.find('.btn-kv-fullscreen'),$btnBord=$modal.find('.btn-kv-borderless'),cap,size,$btnTogh=$modal.find('.btn-kv-toggleheader'),dir=navigate==='prev'?'Left':'Right',slideIn='slideIn'+dir,slideOut='slideOut'+dir,parsed,zoomData=$frame.data('zoom');if(zoomData){zoomData=decodeURIComponent(zoomData);parsed=$zoomPreview.html().replace(self.zoomPlaceholder,'').setTokens({zoomData:zoomData});$zoomPreview.html(parsed);$frame.data('zoom','');$zoomPreview.attr('data-zoom',zoomData)}tmplt=$zoomPreview.attr('data-template')||'generic';$content=$zoomPreview.find('.kv-file-content');body=$content.length?$content.html():'';cap=$frame.data('caption')||self.msgZoomModalHeading;size=$frame.data('size')||'';desc=$frame.data('description')||'';$modal.find('.kv-zoom-caption').attr('title',cap).html(cap);$modal.find('.kv-zoom-size').html(size);$desc=$modal.find('.kv-zoom-description').hide();if(desc){if(self.showDescriptionClose){desc=self._getLayoutTemplate('descriptionClose').setTokens({closeIcon:self.previewZoomButtonIcons.close})+'</button>'+desc}$desc.show().html(desc);if(self.showDescriptionClose){self._handler($modal.find('.kv-desc-hide'),'click',function(){$(this).parent().fadeOut('fast',function(){$modal.focus()})})}}$body=$modal.find('.kv-zoom-body');$modal.removeClass('kv-single-content');if(navigate){$tmp=$body.addClass('file-thumb-loading').clone().insertAfter($body);$h.setHtml($body,body).hide();$tmp.fadeOut('fast',function(){$body.fadeIn('fast',function(){$body.removeClass('file-thumb-loading')});$tmp.remove()})}else{$h.setHtml($body,body)}config=self.previewZoomSettings[tmplt];if(config){$dataEl=$body.find('.kv-preview-data');$h.addCss($dataEl,'file-zoom-detail');$.each(config,function(key,value){$dataEl.css(key,value);if(($dataEl.attr('width')&&key==='width')||($dataEl.attr('height')&&key==='height')){$dataEl.removeAttr(key)}})}$modal.data('previewId',previewId);self._handler($modal.find('.btn-kv-prev'),'click',function(){self._zoomSlideShow('prev',previewId)});self._handler($modal.find('.btn-kv-next'),'click',function(){self._zoomSlideShow('next',previewId)});self._handler($btnFull,'click',function(){self._resizeZoomDialog(true)});self._handler($btnBord,'click',function(){self._resizeZoomDialog(false)});self._handler($btnTogh,'click',function(){var $header=$modal.find('.modal-header'),$floatBar=$modal.find('.floating-buttons'),ht,$actions=$header.find('.kv-zoom-actions'),resize=function(height){var $body=self.$modal.find('.kv-zoom-body'),h=self.zoomModalHeight;if($modal.hasClass('file-zoom-fullscreen')){h=$body.outerHeight(true);if(!height){h=h-$header.outerHeight(true)}}$body.css('height',height?h+height:h)};if($header.is(':visible')){ht=$header.outerHeight(true);$header.slideUp('slow',function(){$actions.find('.btn').appendTo($floatBar);resize(ht)})}else{$floatBar.find('.btn').appendTo($actions);$header.slideDown('slow',function(){resize()})}$modal.focus()});self._handler($modal,'keydown',function(e){var key=e.which||e.keyCode,delay=self.processDelay+1,$prev=$(this).find('.btn-kv-prev'),$next=$(this).find('.btn-kv-next'),vId=$(this).data('previewId'),vPrevKey,vNextKey;[vPrevKey,vNextKey]=self.rtl?[39,37]:[37,39];$.each({prev:[$prev,vPrevKey],next:[$next,vNextKey]},function(direction,config){var $btn=config[0],vKey=config[1];if(key===vKey&&$btn.length){$modal.focus();if(!$btn.attr('disabled')){$btn.blur();setTimeout(function(){$btn.focus();self._zoomSlideShow(direction,vId);setTimeout(function(){if($btn.attr('disabled')){$modal.focus()}},delay)},delay)}}})})},_showModal:function($frame){var self=this,$modal=self.$modal,$content,css,angle;if(!$frame||!$frame.length){return}$h.initModal($modal);$h.setHtml($modal,self._getModalContent());self._setZoomContent($frame);$modal.removeClass('rotatable');$modal.data({backdrop:false,fileinputPluginId:self.$element.attr('id')});$modal.find('.kv-zoom-body').css('height',self.zoomModalHeight);$content=$frame.find('.kv-file-content > :first-child');if($content.length){css=$content.css('transform');if(css){$modal.find('.file-zoom-detail').css('transform',css)}}if($frame.hasClass('rotatable')){$modal.addClass('rotatable')}if($frame.data('angle')){$modal.data('angle',$frame.data('angle'))}angle=($frame.data('angle')||0);$modal.modal('show');self._initZoomButtons();self._initRotateZoom($frame,$content)},_zoomPreview:function($btn){var self=this,$frame;if(!$btn.length){throw'Cannot zoom to detailed preview!';}$frame=$btn.closest($h.FRAMES);self._showModal($frame)},_zoomSlideShow:function(dir,previewId){var self=this,$modal=self.$modal,$btn=$modal.find('.kv-zoom-actions .btn-kv-'+dir),$targFrame,i,$thumb,thumbsData=self.getFrames().toArray(),thumbs=[],len=thumbsData.length,out,angle,$content;if(self.reversePreviewOrder){dir=dir==='prev'?'next':'prev'}if($btn.attr('disabled')){return}for(i=0;i<len;i++){$thumb=$(thumbsData[i]);if($thumb&&$thumb.length&&$thumb.find('.kv-file-zoom:visible').length){thumbs.push(thumbsData[i])}}len=thumbs.length;for(i=0;i<len;i++){if($(thumbs[i]).attr('id')===previewId){out=dir==='prev'?i-1:i+1;break}}if(out<0||out>=len||!thumbs[out]){return}$targFrame=$(thumbs[out]);if($targFrame.length){self._setZoomContent($targFrame,dir)}self._initZoomButtons();if($targFrame.length&&$targFrame.hasClass('rotatable')){angle=$targFrame.data('angle')||0;$modal.addClass('rotatable').data('angle',angle);$content=$targFrame.find('.kv-file-content > :first-child');self._initRotateZoom($targFrame,$content)}else{$modal.removeClass('rotatable').removeData('angle')}self._raise('filezoom'+dir,{'previewId':previewId,modal:self.$modal})},_initZoomButton:function(){var self=this;self.$preview.find('.kv-file-zoom').each(function(){var $el=$(this);self._handler($el,'click',function(){self._zoomPreview($el)})})},_inputFileCount:function(){return this.$element[0].files.length},_refreshPreview:function(){var self=this,files;if((!self._inputFileCount()&&!self.isAjaxUpload)||!self.showPreview||!self.isPreviewable){return}if(self.isAjaxUpload){if(self.fileManager.count()>0){files=$.extend(true,[],self.getFileList());self.fileManager.clear();self._clearFileInput()}else{files=self.$element[0].files}}else{files=self.$element[0].files}if(files&&files.length){self.readFiles(files)}},_clearObjects:function($el){$el.find('video audio').each(function(){this.pause();$(this).remove()});$el.find('img object div').each(function(){$(this).remove()})},_clearFileInput:function(){var self=this,$el=self.$element,$srcFrm,$tmpFrm,$tmpEl;if(!self._inputFileCount()){return}$srcFrm=$el.closest('form');$tmpFrm=$(document.createElement('form'));$tmpEl=$(document.createElement('div'));$el.before($tmpEl);if($srcFrm.length){$srcFrm.after($tmpFrm)}else{$tmpEl.after($tmpFrm)}$tmpFrm.append($el).trigger('reset');$tmpEl.before($el).remove();$tmpFrm.remove()},_resetUpload:function(){var self=this;self.uploadInitiated=false;self.uploadStartTime=$h.now();self.uploadCache=[];self.$btnUpload.removeAttr('disabled');self._setProgress(0);self._hideProgress();self._resetErrors(false);self._initAjax();self.fileManager.clearImages();self._resetCanvas();if(self.overwriteInitial){self.initialPreview=[];self.initialPreviewConfig=[];self.initialPreviewThumbTags=[];self.previewCache.data={content:[],config:[],tags:[]}}},_resetCanvas:function(){var self=this;if(self.imageCanvas&&self.imageCanvasContext){self.imageCanvasContext.clearRect(0,0,self.imageCanvas.width,self.imageCanvas.height)}},_hasInitialPreview:function(){var self=this;return!self.overwriteInitial&&self.previewCache.count(true)},_resetPreview:function(){var self=this,out,cap,$div,hasSuc=self.showUploadedThumbs,hasErr=!self.removeFromPreviewOnError,includeProcessed=(hasSuc||hasErr)&&self.isDuplicateError;if(self.previewCache.count(true)){out=self.previewCache.out();if(includeProcessed){$div=$h.createElement('').insertAfter(self.$container);self.getFrames().each(function(){var $thumb=$(this);if((hasSuc&&$thumb.hasClass('file-preview-success'))||(hasErr&&$thumb.hasClass('file-preview-error'))){$div.append($thumb)}})}self._setPreviewContent(out.content);self._setInitThumbAttr();cap=self.initialCaption?self.initialCaption:out.caption;self._setCaption(cap);if(includeProcessed){$div.contents().appendTo(self.$preview);$div.remove()}}else{self._clearPreview();self._initCaption()}if(self.showPreview){self._initZoom();self._initSortable()}self.isDuplicateError=false},_clearDefaultPreview:function(){var self=this;self.$preview.find('.file-default-preview').remove()},_validateDefaultPreview:function(){var self=this;if(!self.showPreview||$h.isEmpty(self.defaultPreviewContent)){return}self._setPreviewContent('<div class="file-default-preview">'+self.defaultPreviewContent+'</div>');self.$container.removeClass('file-input-new');self._initClickable()},_resetPreviewThumbs:function(isAjax){var self=this,out;if(isAjax){self._clearPreview();self.clearFileStack();return}if(self._hasInitialPreview()){out=self.previewCache.out();self._setPreviewContent(out.content);self._setInitThumbAttr();self._setCaption(out.caption);self._initPreviewActions()}else{self._clearPreview()}},_getLayoutTemplate:function(t){var self=this,template=self.layoutTemplates[t];if($h.isEmpty(self.customLayoutTags)){return template}return $h.replaceTags(template,self.customLayoutTags)},_getPreviewTemplate:function(t){var self=this,templates=self.previewTemplates,template=templates[t]||templates.other;if($h.isEmpty(self.customPreviewTags)){return template}return $h.replaceTags(template,self.customPreviewTags)},_getOutData:function(formdata,jqXHR,responseData,filesData){var self=this;jqXHR=jqXHR||{};responseData=responseData||{};filesData=filesData||self.fileManager.list();return{formdata:formdata,files:filesData,filenames:self.filenames,filescount:self.getFilesCount(),extra:self._getExtraData(),response:responseData,reader:self.reader,jqXHR:jqXHR}},_getMsgSelected:function(n,processing){var self=this,strFiles=n===1?self.fileSingle:self.filePlural;return n>0?self.msgSelected.replace('{n}',n).replace('{files}',strFiles):(processing?self.msgProcessing:self.msgNoFilesSelected)},_getFrame:function(id,skipWarning){var self=this,$frame=$h.getFrameElement(self.$preview,id);if(self.showPreview&&!skipWarning&&!$frame.length){self._log($h.logMessages.invalidThumb,{id:id})}return $frame},_getZoom:function(id,selector){var self=this,$frame=$h.getZoomElement(self.$preview,id,selector);if(self.showPreview&&!$frame.length){self._log($h.logMessages.invalidThumb,{id:id})}return $frame},_getThumbs:function(css){css=css||'';return this.getFrames(':not(.file-preview-initial)'+css)},_getThumbId:function(fileId){var self=this;return self.previewInitId+'-'+fileId},_getExtraData:function(fileId,index){var self=this,data=self.uploadExtraData;if(typeof self.uploadExtraData==='function'){data=self.uploadExtraData(fileId,index)}return data},_initXhr:function(xhrobj,fileId){var self=this,fm=self.fileManager,func=function(event){var pct=0,total=event.total,loaded=event.loaded||event.position,stats=fm.getUploadStats(fileId,loaded,total);if(event.lengthComputable&&!self.enableResumableUpload){pct=$h.round(loaded/total*100)}if(fileId){self._setFileUploadStats(fileId,pct,stats)}else{self._setProgress(pct,null,null,self._getStats(stats))}self._raise('fileajaxprogress',[stats])};if(xhrobj.upload){if(self.progressDelay){func=$h.debounce(func,self.progressDelay)}xhrobj.upload.addEventListener('progress',func,false)}return xhrobj},_initAjaxSettings:function(){var self=this;self._ajaxSettings=$.extend(true,{},self.ajaxSettings);self._ajaxDeleteSettings=$.extend(true,{},self.ajaxDeleteSettings)},_mergeAjaxCallback:function(funcName,srcFunc,type){var self=this,settings=self._ajaxSettings,flag=self.mergeAjaxCallbacks,targFunc;if(type==='delete'){settings=self._ajaxDeleteSettings;flag=self.mergeAjaxDeleteCallbacks}targFunc=settings[funcName];if(flag&&typeof targFunc==='function'){if(flag==='before'){settings[funcName]=function(){targFunc.apply(this,arguments);srcFunc.apply(this,arguments)}}else{settings[funcName]=function(){srcFunc.apply(this,arguments);targFunc.apply(this,arguments)}}}else{settings[funcName]=srcFunc}},_ajaxSubmit:function(fnBefore,fnSuccess,fnComplete,fnError,formdata,fileId,index,vUrl){var self=this,settings,defaults,data,tm=self.taskManager;if(!self._raise('filepreajax',[formdata,fileId,index])){return}formdata.append('initialPreview',JSON.stringify(self.initialPreview));formdata.append('initialPreviewConfig',JSON.stringify(self.initialPreviewConfig));formdata.append('initialPreviewThumbTags',JSON.stringify(self.initialPreviewThumbTags));self._initAjaxSettings();self._mergeAjaxCallback('beforeSend',fnBefore);self._mergeAjaxCallback('success',fnSuccess);self._mergeAjaxCallback('complete',fnComplete);self._mergeAjaxCallback('error',fnError);vUrl=vUrl||self.uploadUrlThumb||self.uploadUrl;if(typeof vUrl==='function'){vUrl=vUrl()}data=self._getExtraData(fileId,index)||{};if(typeof data==='object'){$.each(data,function(key,value){formdata.append(key,value)})}defaults={xhr:function(){var xhrobj=$.ajaxSettings.xhr();return self._initXhr(xhrobj,fileId)},url:self._encodeURI(vUrl),type:'POST',dataType:'json',data:formdata,cache:false,processData:false,contentType:false};settings=$.extend(true,{},defaults,self._ajaxSettings);self.ajaxQueue.push(settings);tm.addTask(fileId+'-'+index,function(){var self=this.self,config,xhr;config=self.ajaxQueue.shift();xhr=$.ajax(config);self.ajaxRequests.push(xhr)}).runWithContext({self:self})},_mergeArray:function(prop,content){var self=this,arr1=$h.cleanArray(self[prop]),arr2=$h.cleanArray(content);self[prop]=arr1.concat(arr2)},_initUploadSuccess:function(out,$thumb,allFiles){var self=this,append,data,index,$div,content,config,tags,id,i;if(!self.showPreview||typeof out!=='object'||$.isEmptyObject(out)){self._resetCaption();return}if(out.initialPreview!==undefined&&out.initialPreview.length>0){self.hasInitData=true;content=out.initialPreview||[];config=out.initialPreviewConfig||[];tags=out.initialPreviewThumbTags||[];append=out.append===undefined||out.append;if(content.length>0&&!$h.isArray(content)){content=content.split(self.initialPreviewDelimiter)}if(content.length){self._mergeArray('initialPreview',content);self._mergeArray('initialPreviewConfig',config);self._mergeArray('initialPreviewThumbTags',tags)}if($thumb!==undefined){if(!allFiles){index=self.previewCache.add(content[0],config[0],tags[0],append);data=self.previewCache.get(index,false);$div=$h.createElement(data).hide().appendTo($thumb);$thumb.fadeOut('slow',function(){var $newThumb=$div.find('> .file-preview-frame');if($newThumb&&$newThumb.length){$newThumb.insertBefore($thumb).fadeIn('slow').css('display:inline-block')}self._initPreviewActions();self._clearFileInput();$thumb.remove();$div.remove();self._initSortable()})}else{id=$thumb.attr('id');i=self._getUploadCacheIndex(id);if(i!==null){self.uploadCache[i]={id:id,content:content[0],config:config[0]||[],tags:tags[0]||[],append:append}}}}else{self.previewCache.set(content,config,tags,append);self._initPreview();self._initPreviewActions()}}self._resetCaption()},_getUploadCacheIndex:function(id){var self=this,i,len=self.uploadCache.length,config;for(i=0;i<len;i++){config=self.uploadCache[i];if(config.id===id){return i}}return null},_initSuccessThumbs:function(){var self=this;if(!self.showPreview){return}setTimeout(function(){self._getThumbs($h.FRAMES+'.file-preview-success').each(function(){var $thumb=$(this),$remove=$thumb.find('.kv-file-remove');$remove.removeAttr('disabled');self._handler($remove,'click',function(){var id=$thumb.attr('id'),out=self._raise('filesuccessremove',[id,$thumb.attr('data-fileindex')]);$h.cleanMemory($thumb);if(out===false){return}self.$caption.attr('title','');$thumb.fadeOut('slow',function(){var fm=self.fileManager;$thumb.remove();if(!self.getFrames().length){self.reset()}})})})},self.processDelay)},_updateInitialPreview:function(){var self=this,u=self.uploadCache;if(self.showPreview){$.each(u,function(key,setting){self.previewCache.add(setting.content,setting.config,setting.tags,setting.append)});if(self.hasInitData){self._initPreview();self._initPreviewActions()}}},_getThumbFileId:function($thumb){var self=this;if(self.showPreview&&$thumb!==undefined){return $thumb.attr('data-fileid')}return null},_getThumbFile:function($thumb){var self=this,id=self._getThumbFileId($thumb);return id?self.fileManager.getFile(id):null},_uploadSingle:function(i,id,isBatch,deferrer){var self=this,fm=self.fileManager,count=fm.count(),formdata=new FormData(),outData,previewId=self._getThumbId(id),$thumb,chkComplete,$btnUpload,$btnDelete,hasPostData=count>0||!$.isEmptyObject(self.uploadExtraData),uploadFailed,$prog,fnBefore,errMsg,fnSuccess,fnComplete,fnError,updateUploadLog,op=self.ajaxOperations.uploadThumb,fileObj=fm.getFile(id),params={id:previewId,index:i,fileId:id},fileName=self.fileManager.getFileName(id,true),resolve=function(){if(deferrer&&deferrer.resolve){deferrer.resolve()}},reject=function(){if(deferrer&&deferrer.reject){deferrer.reject()}};if(self.enableResumableUpload){return}self.uploadInitiated=true;if(self.showPreview){$thumb=fm.getThumb(id);$prog=$thumb.find('.file-thumb-progress');$btnUpload=$thumb.find('.kv-file-upload');$btnDelete=$thumb.find('.kv-file-remove');$prog.show()}if(count===0||!hasPostData||(self.showPreview&&$btnUpload&&$btnUpload.hasClass('disabled'))||self._abort(params)){return}updateUploadLog=function(){if(!uploadFailed){fm.removeFile(id)}else{fm.errors.push(id)}fm.setProcessed(id);if(fm.isProcessed()){self.fileBatchCompleted=true;chkComplete()}};chkComplete=function(){var $initThumbs;if(!self.fileBatchCompleted){return}setTimeout(function(){var triggerReset=fm.count()===0,errCount=fm.errors.length;self._updateInitialPreview();self.unlock(triggerReset);if(triggerReset){self._clearFileInput()}$initThumbs=self.$preview.find('.file-preview-initial');if(self.uploadAsync&&$initThumbs.length){$h.addCss($initThumbs,$h.SORT_CSS);self._initSortable()}self._raise('filebatchuploadcomplete',[fm.stack,self._getExtraData()]);if(!self.retryErrorUploads||errCount===0){fm.clear()}self._setProgress(101);self.ajaxAborted=false;self.uploadInitiated=false},self.processDelay)};fnBefore=function(jqXHR){outData=self._getOutData(formdata,jqXHR);fm.initStats(id);self.fileBatchCompleted=false;if(!isBatch){self.ajaxAborted=false}if(self.showPreview){if(!$thumb.hasClass('file-preview-success')){self._setThumbStatus($thumb,'Loading');$h.addCss($thumb,'file-uploading')}$btnUpload.attr('disabled',true);$btnDelete.attr('disabled',true)}if(!isBatch){self.lock()}if(fm.errors.indexOf(id)!==-1){delete fm.errors[id]}self._raise('filepreupload',[outData,previewId,i,self._getThumbFileId($thumb)]);$.extend(true,params,outData);if(self._abort(params)){jqXHR.abort();if(!isBatch){self._setThumbStatus($thumb,'New');$thumb.removeClass('file-uploading');$btnUpload.removeAttr('disabled');$btnDelete.removeAttr('disabled')}self._setProgressCancelled()}};fnSuccess=function(data,textStatus,jqXHR){var pid=self.showPreview&&$thumb.attr('id')?$thumb.attr('id'):previewId;outData=self._getOutData(formdata,jqXHR,data);$.extend(true,params,outData);setTimeout(function(){if($h.isEmpty(data)||$h.isEmpty(data.error)){if(self.showPreview){self._setThumbStatus($thumb,'Success');$btnUpload.hide();self._initUploadSuccess(data,$thumb,isBatch);self._setProgress(101,$prog)}self._raise('fileuploaded',[outData,pid,i,self._getThumbFileId($thumb)]);if(!isBatch){self.fileManager.remove($thumb)}else{updateUploadLog();resolve()}}else{uploadFailed=true;errMsg=self._parseError(op,jqXHR,self.msgUploadError,self.fileManager.getFileName(id));self._showFileError(errMsg,params);self._setPreviewError($thumb,true);if(!self.retryErrorUploads){$btnUpload.hide()}if(isBatch){updateUploadLog();resolve()}self._setProgress(101,self._getFrame(pid).find('.file-thumb-progress'),self.msgUploadError)}},self.processDelay)};fnComplete=function(){if(self.showPreview){$btnUpload.removeAttr('disabled');$btnDelete.removeAttr('disabled');$thumb.removeClass('file-uploading')}if(!isBatch){self.unlock(false);self._clearFileInput()}else{chkComplete()}self._initSuccessThumbs()};fnError=function(jqXHR,textStatus,errorThrown){errMsg=self._parseError(op,jqXHR,errorThrown,self.fileManager.getFileName(id));uploadFailed=true;setTimeout(function(){var $prog;if(isBatch){updateUploadLog();reject()}self.fileManager.setProgress(id,100);self._setPreviewError($thumb,true);if(!self.retryErrorUploads){$btnUpload.hide()}$.extend(true,params,self._getOutData(formdata,jqXHR));self._setProgress(101,self.$progress,self.msgAjaxProgressError.replace('{operation}',op));$prog=self.showPreview&&$thumb?$thumb.find('.file-thumb-progress'):'';self._setProgress(101,$prog,self.msgUploadError);self._showFileError(errMsg,params)},self.processDelay)};self._setFileData(formdata,fileObj.file,fileName,id);self._setUploadData(formdata,{fileId:id});self._ajaxSubmit(fnBefore,fnSuccess,fnComplete,fnError,formdata,id,i)},_setFileData:function(formdata,file,fileName,fileId){var self=this,preProcess=self.preProcessUpload;if(preProcess&&typeof preProcess==='function'){formdata.append(self.uploadFileAttr,preProcess(fileId,file))}else{formdata.append(self.uploadFileAttr,file,fileName)}},_checkBatchPreupload:function(outData,jqXHR){var self=this,out=self._raise('filebatchpreupload',[outData]);if(out){return true}self._abort(outData);if(jqXHR){jqXHR.abort()}self._getThumbs().each(function(){var $thumb=$(this),$btnUpload=$thumb.find('.kv-file-upload'),$btnDelete=$thumb.find('.kv-file-remove');if($thumb.hasClass('file-preview-loading')){self._setThumbStatus($thumb,'New');$thumb.removeClass('file-uploading')}$btnUpload.removeAttr('disabled');$btnDelete.removeAttr('disabled')});self._setProgressCancelled();return false},_uploadBatch:function(){var self=this,fm=self.fileManager,total=fm.total(),params={},fnBefore,fnSuccess,fnError,fnComplete,hasPostData=total>0||!$.isEmptyObject(self.uploadExtraData),errMsg,setAllUploaded,formdata=new FormData(),op=self.ajaxOperations.uploadBatch;if(total===0||!hasPostData||self._abort(params)){return}setAllUploaded=function(){self.fileManager.clear();self._clearFileInput()};fnBefore=function(jqXHR){self.lock();fm.initStats();var outData=self._getOutData(formdata,jqXHR);self.ajaxAborted=false;if(self.showPreview){self._getThumbs().each(function(){var $thumb=$(this),$btnUpload=$thumb.find('.kv-file-upload'),$btnDelete=$thumb.find('.kv-file-remove');if(!$thumb.hasClass('file-preview-success')){self._setThumbStatus($thumb,'Loading');$h.addCss($thumb,'file-uploading')}$btnUpload.attr('disabled',true);$btnDelete.attr('disabled',true)})}self._checkBatchPreupload(outData,jqXHR)};fnSuccess=function(data,textStatus,jqXHR){var outData=self._getOutData(formdata,jqXHR,data),key=0,$thumbs=self._getThumbs(':not(.file-preview-success)'),keys=$h.isEmpty(data)||$h.isEmpty(data.errorkeys)?[]:data.errorkeys;if($h.isEmpty(data)||$h.isEmpty(data.error)){self._raise('filebatchuploadsuccess',[outData]);setAllUploaded();if(self.showPreview){$thumbs.each(function(){var $thumb=$(this);self._setThumbStatus($thumb,'Success');$thumb.removeClass('file-uploading');$thumb.find('.kv-file-upload').hide().removeAttr('disabled')});self._initUploadSuccess(data)}else{self.reset()}self._setProgress(101)}else{if(self.showPreview){$thumbs.each(function(){var $thumb=$(this);$thumb.removeClass('file-uploading');$thumb.find('.kv-file-upload').removeAttr('disabled');$thumb.find('.kv-file-remove').removeAttr('disabled');if(keys.length===0||$.inArray(key,keys)!==-1){self._setPreviewError($thumb,true);if(!self.retryErrorUploads){$thumb.find('.kv-file-upload').hide();self.fileManager.remove($thumb)}}else{$thumb.find('.kv-file-upload').hide();self._setThumbStatus($thumb,'Success');self.fileManager.remove($thumb)}if(!$thumb.hasClass('file-preview-error')||self.retryErrorUploads){key++}});self._initUploadSuccess(data)}errMsg=self._parseError(op,jqXHR,self.msgUploadError);self._showFileError(errMsg,outData,'filebatchuploaderror');self._setProgress(101,self.$progress,self.msgUploadError)}};fnComplete=function(){self.unlock();self._initSuccessThumbs();self._clearFileInput();self._raise('filebatchuploadcomplete',[self.fileManager.stack,self._getExtraData()])};fnError=function(jqXHR,textStatus,errorThrown){var outData=self._getOutData(formdata,jqXHR);errMsg=self._parseError(op,jqXHR,errorThrown);self._showFileError(errMsg,outData,'filebatchuploaderror');self.uploadFileCount=total-1;if(!self.showPreview){return}self._getThumbs().each(function(){var $thumb=$(this);$thumb.removeClass('file-uploading');if(self._getThumbFile($thumb)){self._setPreviewError($thumb)}});self._getThumbs().removeClass('file-uploading');self._getThumbs(' .kv-file-upload').removeAttr('disabled');self._getThumbs(' .kv-file-delete').removeAttr('disabled');self._setProgress(101,self.$progress,self.msgAjaxProgressError.replace('{operation}',op))};var ctr=0;$.each(self.fileManager.stack,function(key,data){if(!$h.isEmpty(data.file)){self._setFileData(formdata,data.file,(data.nameFmt||('untitled_'+ctr)),key)}ctr++});self._ajaxSubmit(fnBefore,fnSuccess,fnComplete,fnError,formdata)},_uploadExtraOnly:function(){var self=this,params={},fnBefore,fnSuccess,fnComplete,fnError,formdata=new FormData(),errMsg,op=self.ajaxOperations.uploadExtra;fnBefore=function(jqXHR){self.lock();var outData=self._getOutData(formdata,jqXHR);self._setProgress(50);params.data=outData;params.xhr=jqXHR;self._checkBatchPreupload(outData,jqXHR)};fnSuccess=function(data,textStatus,jqXHR){var outData=self._getOutData(formdata,jqXHR,data);if($h.isEmpty(data)||$h.isEmpty(data.error)){self._raise('filebatchuploadsuccess',[outData]);self._clearFileInput();self._initUploadSuccess(data);self._setProgress(101)}else{errMsg=self._parseError(op,jqXHR,self.msgUploadError);self._showFileError(errMsg,outData,'filebatchuploaderror')}};fnComplete=function(){self.unlock();self._clearFileInput();self._raise('filebatchuploadcomplete',[self.fileManager.stack,self._getExtraData()])};fnError=function(jqXHR,textStatus,errorThrown){var outData=self._getOutData(formdata,jqXHR);errMsg=self._parseError(op,jqXHR,errorThrown);params.data=outData;self._showFileError(errMsg,outData,'filebatchuploaderror');self._setProgress(101,self.$progress,self.msgAjaxProgressError.replace('{operation}',op))};self._ajaxSubmit(fnBefore,fnSuccess,fnComplete,fnError,formdata)},_deleteFileIndex:function($frame){var self=this,ind=$frame.attr('data-fileindex'),rev=self.reversePreviewOrder;if(ind.substring(0,5)===$h.INIT_FLAG){ind=parseInt(ind.replace($h.INIT_FLAG,''));self.initialPreview=$h.spliceArray(self.initialPreview,ind,rev);self.initialPreviewConfig=$h.spliceArray(self.initialPreviewConfig,ind,rev);self.initialPreviewThumbTags=$h.spliceArray(self.initialPreviewThumbTags,ind,rev);self.getFrames().each(function(){var $nFrame=$(this),nInd=$nFrame.attr('data-fileindex');if(nInd.substring(0,5)===$h.INIT_FLAG){nInd=parseInt(nInd.replace($h.INIT_FLAG,''));if(nInd>ind){nInd--;$nFrame.attr('data-fileindex',$h.INIT_FLAG+nInd)}}})}},_resetCaption:function(){var self=this;setTimeout(function(){var cap='',n,chk=self.previewCache.count(true),len=self.fileManager.count(),file,incomplete=':not(.file-preview-success):not(.file-preview-error)',cfg,hasThumb=self.showPreview&&self.getFrames(incomplete).length;if(len===0&&chk===0&&!hasThumb){self.reset()}else{n=chk+len;if(n>1){cap=self._getMsgSelected(n)}else{if(len===0){cfg=self.initialPreviewConfig[0];cap='';if(cfg){cap=cfg.caption||cfg.filename||''}if(!cap){cap=self._getMsgSelected(n)}}else{file=self.fileManager.getFirstFile();cap=file?file.nameFmt:'_'}}self._setCaption(cap)}},self.processDelay)},_handleRotation:function($el,$content,angle){var self=this,css,newCss,addCss='',scale=1,elContent=$content[0],quadrant,transform,h,w,wNew,$parent=$content.parent(),hParent,wParent,$body=$('body'),bodyExists=!!$body.length;if(bodyExists){$body.addClass('kv-overflow-hidden')}if(!$content.length||$el.hasClass('hide-rotate')){if(bodyExists){$body.removeClass('kv-overflow-hidden')}return}transform=$content.css('transform');if(transform){$content.css('transform','none')}if(transform){$content.css('transform',transform)}angle=angle||0;quadrant=angle%360;css='rotate('+angle+'deg)';newCss='rotate('+quadrant+'deg)';addCss='';if(quadrant===90||quadrant===270){w=elContent.naturalWidth||$content.outerWidth()||0;h=elContent.naturalHeight||$content.outerHeight()||0;scale=w>h&&w!=0?(h/w).toFixed(2):1;if($parent.length){hParent=$parent.height();wParent=$parent.width();wNew=Math.min(w,wParent);if(hParent>scale*wNew){scale=wNew>hParent&&wNew!=0?(hParent/wNew).toFixed(2):1}}if(scale!==1){addCss=' scale('+scale+')'}}$content.addClass('rotate-animate').css('transform',css+addCss);setTimeout(function(){$content.removeClass('rotate-animate').css('transform',newCss+addCss);if(bodyExists){$body.removeClass('kv-overflow-hidden')}$el.data('angle',quadrant)},self.fadeDelay)},_initRotateButton:function(){var self=this;self.getFrames('.rotatable .kv-file-rotate').each(function(){var $el=$(this),$frame=$el.closest($h.FRAMES),$content=$frame.find('.kv-file-content > :first-child');self._handler($el,'click',function(){var angle=($frame.data('angle')||0)+90;self._handleRotation($frame,$content,angle)})})},_initRotateZoom:function($frame,$content){var self=this,$modal=self.$modal,$rotate=$modal.find('.btn-kv-rotate'),angle=$frame.data('angle');$modal.data('angle',angle);if($rotate.length){$rotate.off('click');if($modal.hasClass('rotatable')){$rotate.on('click',function(){angle=($modal.data('angle')||0)+90;$modal.data('angle',angle);self._handleRotation($modal,$modal.find('.file-zoom-detail'),angle);self._handleRotation($frame,$content,angle);if($frame.hasClass('hide-rotate')){$frame.data('angle',angle)}})}}},_initFileActions:function(){var self=this;if(!self.showPreview){return}self._initZoomButton();self._initRotateButton();self.getFrames(' .kv-file-remove').each(function(){var $el=$(this),$frame=$el.closest($h.FRAMES),hasError,id=$frame.attr('id'),ind=$frame.attr('data-fileindex'),status,fm=self.fileManager;self._handler($el,'click',function(){status=self._raise('filepreremove',[id,ind]);if(status===false||!self._validateMinCount()){return false}hasError=$frame.hasClass('file-preview-error');$h.cleanMemory($frame);$frame.fadeOut('slow',function(){self.fileManager.remove($frame);self._clearObjects($frame);$frame.remove();if(id&&hasError){self.$errorContainer.find('li[data-thumb-id="'+id+'"]').fadeOut('fast',function(){$(this).remove();if(!self._errorsExist()){self._resetErrors()}})}self._clearFileInput();self._resetCaption();self._raise('fileremoved',[id,ind])})})});self.getFrames(' .kv-file-upload').each(function(){var $el=$(this);self._handler($el,'click',function(){var $frame=$el.closest($h.FRAMES),fileId=self._getThumbFileId($frame);self._hideProgress();if($frame.hasClass('file-preview-error')&&!self.retryErrorUploads){return}self._uploadSingle(self.fileManager.getIndex(fileId),fileId,false)})})},_initPreviewActions:function(){var self=this,$preview=self.$preview,deleteExtraData=self.deleteExtraData||{},btnRemove=$h.FRAMES+' .kv-file-remove',settings=self.fileActionSettings,origClass=settings.removeClass,errClass=settings.removeErrorClass,resetProgress=function(){var hasFiles=self.isAjaxUpload?self.previewCache.count(true):self._inputFileCount();if(!self.getFrames().length&&!hasFiles){self._setCaption('');self.reset();self.initialCaption=''}else{self._resetCaption()}};self._initZoomButton();self._initRotateButton();$preview.find(btnRemove).each(function(){var $el=$(this),vUrl=$el.data('url')||self.deleteUrl,vKey=$el.data('key'),errMsg,fnBefore,fnSuccess,fnError,op=self.ajaxOperations.deleteThumb;if($h.isEmpty(vUrl)||vKey===undefined){return}if(typeof vUrl==='function'){vUrl=vUrl()}var $frame=$el.closest($h.FRAMES),cache=self.previewCache.data,settings,params,config,fileName,extraData,index=$frame.attr('data-fileindex');index=parseInt(index.replace($h.INIT_FLAG,''));config=$h.isEmpty(cache.config)&&$h.isEmpty(cache.config[index])?null:cache.config[index];extraData=$h.isEmpty(config)||$h.isEmpty(config.extra)?deleteExtraData:config.extra;fileName=config&&(config.filename||config.caption)||'';if(typeof extraData==='function'){extraData=extraData()}params={id:$el.attr('id'),key:vKey,extra:extraData};fnBefore=function(jqXHR){self.ajaxAborted=false;self._raise('filepredelete',[vKey,jqXHR,extraData]);if(self._abort()){jqXHR.abort()}else{$el.removeClass(errClass);$h.addCss($frame,'file-uploading');$h.addCss($el,'disabled '+origClass)}};fnSuccess=function(data,textStatus,jqXHR){var n,cap;if(!$h.isEmpty(data)&&!$h.isEmpty(data.error)){params.jqXHR=jqXHR;params.response=data;errMsg=self._parseError(op,jqXHR,self.msgDeleteError,fileName);self._showFileError(errMsg,params,'filedeleteerror');$frame.removeClass('file-uploading');$el.removeClass('disabled '+origClass).addClass(errClass);resetProgress();return}$frame.removeClass('file-uploading').addClass('file-deleted');$frame.fadeOut('slow',function(){index=parseInt(($frame.attr('data-fileindex')).replace($h.INIT_FLAG,''));self.previewCache.unset(index);self._deleteFileIndex($frame);n=self.previewCache.count(true);cap=n>0?self._getMsgSelected(n):'';self._setCaption(cap);self._raise('filedeleted',[vKey,jqXHR,extraData]);self._clearObjects($frame);$frame.remove();resetProgress()})};fnError=function(jqXHR,textStatus,errorThrown){var errMsg=self._parseError(op,jqXHR,errorThrown,fileName);params.jqXHR=jqXHR;params.response={};self._showFileError(errMsg,params,'filedeleteerror');$frame.removeClass('file-uploading');$el.removeClass('disabled '+origClass).addClass(errClass);resetProgress()};self._initAjaxSettings();self._mergeAjaxCallback('beforeSend',fnBefore,'delete');self._mergeAjaxCallback('success',fnSuccess,'delete');self._mergeAjaxCallback('error',fnError,'delete');settings=$.extend(true,{},{url:self._encodeURI(vUrl),type:'POST',dataType:'json',data:$.extend(true,{},{key:vKey},extraData)},self._ajaxDeleteSettings);self._handler($el,'click',function(){if(!self._validateMinCount()){return false}self.ajaxAborted=false;self._raise('filebeforedelete',[vKey,extraData]);if(self.ajaxAborted instanceof Promise){self.ajaxAborted.then(function(result){if(!result){$.ajax(settings)}})}else{if(!self.ajaxAborted){$.ajax(settings)}}})})},_hideFileIcon:function(){var self=this;if(self.overwriteInitial){self.$captionContainer.removeClass('icon-visible')}},_showFileIcon:function(){var self=this;$h.addCss(self.$captionContainer,'icon-visible')},_getSize:function(bytes,skipTemplate,sizeUnits){var self=this,size=parseFloat(bytes),i=0,factor=self.bytesToKB,func=self.fileSizeGetter,out,sizeHuman=size,newSize;if(!$.isNumeric(bytes)||!$.isNumeric(size)){return''}if(typeof func==='function'){out=func(size)}else{if(!sizeUnits){sizeUnits=self.sizeUnits}if(size>0){while(sizeHuman>=factor){sizeHuman/=factor;++i}if(!sizeUnits[i]){sizeHuman=size;i=0}}newSize=sizeHuman.toFixed(2);if(newSize==sizeHuman){newSize=sizeHuman}out=newSize+' '+sizeUnits[i]}return skipTemplate?out:self._getLayoutTemplate('size').replace('{sizeText}',out)},_getFileType:function(ftype){var self=this;return self.mimeTypeAliases[ftype]||ftype},_generatePreviewTemplate:function(cat,data,fname,ftype,previewId,fileId,isError,size,fnameUpdated,frameClass,foot,ind,templ,attrs,zoomData){var self=this,caption=self.slug(fname),prevContent,zoomContent='',styleAttribs='',filename=fnameUpdated||fname,isIconic,ext=filename.split('.').pop().toLowerCase(),screenW=window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth,config,title=caption,alt=caption,typeCss='type-default',getContent,addFrameCss,footer=foot||self._renderFileFooter(cat,caption,size,'auto',isError),isRotatable,alwaysPreview=$.inArray(ext,self.alwaysPreviewFileExtensions)!==-1,forcePrevIcon=self.preferIconicPreview&&!alwaysPreview,forceZoomIcon=self.preferIconicZoomPreview&&!alwaysPreview,newCat=forcePrevIcon?'other':cat;config=screenW<400?(self.previewSettingsSmall[newCat]||self.defaults.previewSettingsSmall[newCat]):(self.previewSettings[newCat]||self.defaults.previewSettings[newCat]);if(config){$.each(config,function(key,val){styleAttribs+=key+':'+val+';'})}getContent=function(vCat,vData,zoom,frameCss,vZoomData){var id=zoom?'zoom-'+previewId:previewId,tmplt=self._getPreviewTemplate(vCat),css=(frameClass||'')+' '+frameCss,tokens;if(self.frameClass){css=self.frameClass+' '+css}if(zoom){css=css.replace(' '+$h.SORT_CSS,'')}tmplt=self._parseFilePreviewIcon(tmplt,fname);if(cat==='object'&&!ftype){$.each(self.defaults.fileTypeSettings,function(key,func){if(key==='object'||key==='other'){return}if(func(fname,ftype)){typeCss='type-'+key}})}if(!$h.isEmpty(attrs)){if(attrs.title!==undefined&&attrs.title!==null){title=attrs.title}if(attrs.alt!==undefined&&attrs.alt!==null){alt=title=attrs.alt}}tokens={'previewId':id,'caption':caption,'title':title,'alt':alt,'frameClass':css,'type':self._getFileType(ftype),'fileindex':ind,'fileid':fileId||'','filename':filename,'typeCss':typeCss,'footer':footer,'data':vData,'template':templ||cat,'style':styleAttribs?'style="'+styleAttribs+'"':'','zoomData':vZoomData?encodeURIComponent(vZoomData):''};if(zoom){tokens.zoomCache='';tokens.zoomData='{zoomData}'}return tmplt.setTokens(tokens)};ind=ind||previewId.slice(previewId.lastIndexOf('-')+1);isRotatable=self.fileActionSettings.showRotate&&$.inArray(ext,self.rotatableFileExtensions)!==-1;if(self.fileActionSettings.showZoom){addFrameCss='kv-zoom-thumb';if(isRotatable){addFrameCss+=' rotatable'+(forceZoomIcon?' hide-rotate':'')}zoomContent=getContent((forceZoomIcon?'other':cat),data,true,addFrameCss,zoomData)}zoomContent='\n'+self._getLayoutTemplate('zoomCache').replace('{zoomContent}',zoomContent);if(typeof self.sanitizeZoomCache==='function'){zoomContent=self.sanitizeZoomCache(zoomContent)}addFrameCss='kv-preview-thumb';if(isRotatable){isIconic=forcePrevIcon||self.hideThumbnailContent||!!self.previewFileIconSettings[ext];addFrameCss+=' rotatable'+(isIconic?' hide-rotate':'')}prevContent=getContent((forcePrevIcon?'other':cat),data,false,addFrameCss,zoomData);return prevContent.setTokens({zoomCache:zoomContent})},_addToPreview:function($preview,content){var self=this,$el;content=$h.cspBuffer.stash(content);$el=self.reversePreviewOrder?$preview.prepend(content):$preview.append(content);$h.cspBuffer.apply($preview);return $el},_previewDefault:function(file,isDisabled){var self=this,$preview=self.$preview;if(!self.showPreview){return}var fname=$h.getFileName(file),ftype=file?file.type:'',content,size=file.size||0,caption=self._getFileName(file,''),isError=isDisabled===true&&!self.isAjaxUpload,data=$h.createObjectURL(file),fileId=self.fileManager.getId(file),previewId=self._getThumbId(fileId);self._clearDefaultPreview();content=self._generatePreviewTemplate('other',data,fname,ftype,previewId,fileId,isError,size);self._addToPreview($preview,content);self._setThumbAttr(previewId,caption,size);if(isDisabled===true&&self.isAjaxUpload){self._setThumbStatus(self._getFrame(previewId),'Error')}},_previewFile:function(i,file,theFile,data,fileInfo){if(!this.showPreview){return}var self=this,fname=$h.getFileName(file),ftype=fileInfo.type,content,caption=fileInfo.name,cat=self._parseFileType(ftype,fname),$preview=self.$preview,fsize=file.size||0,iData=cat==='image'?theFile.target.result:data,fm=self.fileManager,fileId=fm.getId(file),previewId=self._getThumbId(fileId);content=self._generatePreviewTemplate(cat,iData,fname,ftype,previewId,fileId,false,fsize,fileInfo.filename);self._clearDefaultPreview();self._addToPreview($preview,content);var $thumb=self._getFrame(previewId);self._validateImageOrientation($thumb.find('img'),file,previewId,fileId,caption,ftype,fsize,iData);self._setThumbAttr(previewId,caption,fsize);self._initSortable()},_setThumbAttr:function(id,caption,size,description){var self=this,$frame=self._getFrame(id);if($frame.length){size=size&&size>0?self._getSize(size):'';$frame.data({'caption':caption,'size':size,'description':description||''})}},_setInitThumbAttr:function(){var self=this,data=self.previewCache.data,len=self.previewCache.count(true),config,caption,size,description,previewId;if(len===0){return}for(var i=0;i<len;i++){config=data.config[i];previewId=self.previewInitId+'-'+$h.INIT_FLAG+i;caption=$h.ifSet('caption',config,$h.ifSet('filename',config));size=$h.ifSet('size',config);description=$h.ifSet('description',config);self._setThumbAttr(previewId,caption,size,description)}},_slugDefault:function(text){return $h.isEmpty(text,true)?'':String(text).replace(/[\[\]\/\{}:;#%=\(\)\*\+\?\\\^\$\|<>&"']/g,'_')},_updateFileDetails:function(numFiles){var self=this,$el=self.$element,label,n,log,nFiles,file,name=($h.isIE(9)&&$h.findFileName($el.val()))||($el[0].files[0]&&$el[0].files[0].name);if(!name&&self.fileManager.count()>0){file=self.fileManager.getFirstFile();label=file.nameFmt}else{label=name?self.slug(name):'_'}n=self.isAjaxUpload?self.fileManager.count():numFiles;nFiles=self.previewCache.count(true)+n;log=n===1?label:self._getMsgSelected(nFiles,!self.isAjaxUpload&&!self.isError);if(self.isError){self.$previewContainer.removeClass('file-thumb-loading');self._initCapStatus();self.$previewStatus.html('');self.$captionContainer.removeClass('icon-visible')}else{self._showFileIcon()}self._setCaption(log,self.isError);self.$container.removeClass('file-input-new file-input-ajax-new');self._raise('fileselect',[numFiles,label]);if(self.previewCache.count(true)){self._initPreviewActions()}},_setThumbStatus:function($thumb,status){var self=this;if(!self.showPreview){return}var icon='indicator'+status,msg=icon+'Title',css='file-preview-'+status.toLowerCase(),$indicator=$thumb.find('.file-upload-indicator'),config=self.fileActionSettings;$thumb.removeClass('file-preview-success file-preview-error file-preview-paused file-preview-loading');if(status==='Success'){$thumb.find('.file-drag-handle').remove()}$h.setHtml($indicator,config[icon]);$indicator.attr('title',config[msg]);$thumb.addClass(css);if(status==='Error'&&!self.retryErrorUploads){$thumb.find('.kv-file-upload').attr('disabled',true)}},_setProgressCancelled:function(){var self=this;self._setProgress(101,self.$progress,self.msgCancelled)},_setProgress:function(p,$el,error,stats){var self=this;$el=$el||self.$progress;if(!$el.length){return}var pct=Math.min(p,100),out,pctLimit=self.progressUploadThreshold,t=p<=100?self.progressTemplate:self.progressCompleteTemplate,template=pct<100?self.progressTemplate:(error?(self.paused?self.progressPauseTemplate:self.progressErrorTemplate):t);if(p>=100){stats=''}if(!$h.isEmpty(template)){if(pctLimit&&pct>pctLimit&&p<=100){out=template.setTokens({'percent':pctLimit,'status':self.msgUploadThreshold})}else{out=template.setTokens({'percent':pct,'status':(p>100?self.msgUploadEnd:pct+'%')})}stats=stats||'';out=out.setTokens({stats:stats});$h.setHtml($el,out);if(error){$h.setHtml($el.find('[role="progressbar"]'),error)}}},_hasFiles:function(){var el=this.$element[0];return!!(el&&el.files&&el.files.length)},_setFileDropZoneTitle:function(){var self=this,$zone=self.$container.find('.file-drop-zone'),title=self.dropZoneTitle,strFiles;if(self.isClickable){strFiles=$h.isEmpty(self.$element.attr('multiple'))?self.fileSingle:self.filePlural;title+=self.dropZoneClickTitle.replace('{files}',strFiles)}$zone.find('.'+self.dropZoneTitleClass).remove();if(!self.showPreview||$zone.length===0||self.fileManager.count()>0||!self.dropZoneEnabled||self.previewCache.count()>0||(!self.isAjaxUpload&&self._hasFiles())){return}if($zone.find($h.FRAMES).length===0&&$h.isEmpty(self.defaultPreviewContent)){$zone.prepend('<div class="'+self.dropZoneTitleClass+'">'+title+'</div>')}self.$container.removeClass('file-input-new');$h.addCss(self.$container,'file-input-ajax-new')},_getStats:function(stats){var self=this,pendingTime,t;if(!self.showUploadStats||!stats||!stats.bitrate){return''}t=self._getLayoutTemplate('stats');pendingTime=(!stats.elapsed||!stats.bps)?self.msgCalculatingTime:self.msgPendingTime.setTokens({time:$h.getElapsed(Math.ceil(stats.pendingBytes/stats.bps))});return t.setTokens({uploadSpeed:stats.bitrate,pendingTime:pendingTime})},_setResumableProgress:function(pct,stats,$thumb){var self=this,rm=self.resumableManager,obj=$thumb?rm:self,$prog=$thumb?$thumb.find('.file-thumb-progress'):null;if(obj.lastProgress===0){obj.lastProgress=pct}if(pct<obj.lastProgress){pct=obj.lastProgress}self._setProgress(pct,$prog,null,self._getStats(stats));obj.lastProgress=pct},_toggleResumableProgress:function(template,message){var self=this,$progress=self.$progress;if($progress&&$progress.length){$h.setHtml($progress,template.setTokens({percent:101,status:message,stats:''}))}},_setFileUploadStats:function(id,pct,stats){var self=this,$prog=self.$progress;if(!self.showPreview&&(!$prog||!$prog.length)){return}var fm=self.fileManager,rm=self.resumableManager,$thumb=fm.getThumb(id),pctTot,totUpSize=0,totSize=fm.getTotalSize(),totStats=$.extend(true,{},stats);if(self.enableResumableUpload){var loaded=stats.loaded,currUplSize=rm.getUploadedSize(),currTotSize=rm.file.size,totLoaded;loaded+=currUplSize;totLoaded=fm.uploadedSize+loaded;pct=$h.round(100*loaded/currTotSize);stats.pendingBytes=currTotSize-currUplSize;self._setResumableProgress(pct,stats,$thumb);pctTot=Math.floor(100*totLoaded/totSize);totStats.pendingBytes=totSize-totLoaded;self._setResumableProgress(pctTot,totStats)}else{fm.setProgress(id,pct);$prog=$thumb&&$thumb.length?$thumb.find('.file-thumb-progress'):null;self._setProgress(pct,$prog,null,self._getStats(stats));$.each(fm.stats,function(id,cfg){totUpSize+=cfg.loaded});totStats.pendingBytes=totSize-totUpSize;pctTot=$h.round(totUpSize/totSize*100);self._setProgress(pctTot,null,null,self._getStats(totStats))}},_validateMinCount:function(){var self=this,len=self.isAjaxUpload?self.fileManager.count():self._inputFileCount();if(self.validateInitialCount&&self.minFileCount>0&&self._getFileCount(len-1)<self.minFileCount){self._noFilesError({});return false}return true},_getFileCount:function(fileCount,includeInitial){var self=this,addCount=0;if(includeInitial===undefined){includeInitial=self.validateInitialCount&&!self.overwriteInitial}if(includeInitial){addCount=self.previewCache.count(true);fileCount+=addCount}return fileCount},_getFileId:function(file){return $h.getFileId(file,this.generateFileId)},_getFileName:function(file,defaultValue){var self=this,fileName=$h.getFileName(file);return fileName?self.slug(fileName):defaultValue},_getFileNames:function(skipNull){var self=this;return self.filenames.filter(function(n){return(skipNull?n!==undefined:n!==undefined&&n!==null)})},_setPreviewError:function($thumb,keepFile){var self=this,removeFrame=self.removeFromPreviewOnError&&!self.retryErrorUploads;if(!keepFile||removeFrame){self.fileManager.remove($thumb)}if(!self.showPreview){return}if(removeFrame){$thumb.remove();return}else{self._setThumbStatus($thumb,'Error')}self._refreshUploadButton($thumb)},_refreshUploadButton:function($thumb){var self=this,$btn=$thumb.find('.kv-file-upload'),cfg=self.fileActionSettings,icon=cfg.uploadIcon,title=cfg.uploadTitle;if(!$btn.length){return}if(self.retryErrorUploads){icon=cfg.uploadRetryIcon;title=cfg.uploadRetryTitle}$btn.attr('title',title);$h.setHtml($btn,icon)},_isValidSize:function(size,type,$image,$thumb,filename,params){var self=this,msg,dim,$img,tag=size==='Small'?'min':'max',limit=self[tag+'Image'+type];if($h.isEmpty(limit)||!$image.length){return true}$img=$image[0];dim=(type==='Width')?$img.naturalWidth||$img.width:$img.naturalHeight||$img.height;if(size==='Small'?dim>=limit:dim<=limit){return true}msg=self['msgImage'+type+size]||'Image "{name}" has a size validation error (limit "{size}").';self._showFileError(msg.setTokens({'name':filename,'size':limit,'dimension':dim}),params);self._setPreviewError($thumb);self.fileManager.remove($thumb);self._clearFileInput();return false},_getExifObj:function(data){var self=this,exifObj,error=$h.logMessages.exifWarning;if(data.slice(0,23)!=='data:image/jpeg;base64,'&&data.slice(0,22)!=='data:image/jpg;base64,'){exifObj=null;return}try{exifObj=window.piexif?window.piexif.load(data):null}catch(err){exifObj=null;error=err&&err.message||''}if(!exifObj&&self.showExifErrorLog){self._log($h.logMessages.badExifParser,{details:error})}return exifObj},setImageOrientation:function($img,$zoomImg,value,$thumb){var self=this,invalidImg=!$img||!$img.length,invalidZoomImg=!$zoomImg||!$zoomImg.length,$mark,isHidden=false,$div,zoomOnly=invalidImg&&$thumb&&$thumb.attr('data-template')==='image',ev;if(invalidImg&&invalidZoomImg){return}ev='load.fileinputimageorient';if(zoomOnly){$img=$zoomImg;$zoomImg=null;$img.css(self.previewSettings.image);$div=$(document.createElement('div')).appendTo($thumb.find('.kv-file-content'));$mark=$(document.createElement('span')).insertBefore($img);$img.css('visibility','hidden').removeClass('file-zoom-detail').appendTo($div)}else{isHidden=!$img.is(':visible')}$img.off(ev).on(ev,function(){if(isHidden){self.$preview.removeClass('hide-content');$thumb.find('.kv-file-content').css('visibility','hidden')}var img=$img[0],zoomImg=$zoomImg&&$zoomImg.length?$zoomImg[0]:null,h=img.offsetHeight,w=img.offsetWidth,r=$h.getRotation(value);if(isHidden){$thumb.find('.kv-file-content').css('visibility','visible');self.$preview.addClass('hide-content')}$img.data('orientation',value);if(zoomImg){$zoomImg.data('orientation',value)}if(value<5){$h.setTransform(img,r);$h.setTransform(zoomImg,r);return}var offsetAngle=Math.atan(w/h),origFactor=Math.sqrt(Math.pow(h,2)+Math.pow(w,2)),scale=!origFactor?1:(h/Math.cos(Math.PI/2+offsetAngle))/origFactor,s=' scale('+Math.abs(scale)+')';$h.setTransform(img,r+s);$h.setTransform(zoomImg,r+s);if(zoomOnly){$img.css('visibility','visible').insertAfter($mark).addClass('file-zoom-detail');$mark.remove();$div.remove()}})},_validateImageOrientation:function($img,file,previewId,fileId,caption,ftype,fsize,iData){var self=this,exifObj=null,value,autoOrientImage=self.autoOrientImage,selector;exifObj=self._getExifObj(iData);if(self.canOrientImage){$img.css('image-orientation',(autoOrientImage?'from-image':'none'));self._validateImage(previewId,fileId,caption,ftype,fsize,iData,exifObj);return}selector=$h.getZoomSelector(previewId,' img');value=exifObj?exifObj['0th'][piexif.ImageIFD.Orientation]:null;if(!value){self._validateImage(previewId,fileId,caption,ftype,fsize,iData,exifObj);return}self.setImageOrientation($img,$(selector),value,self._getFrame(previewId));self._raise('fileimageoriented',{'$img':$img,'file':file});self._validateImage(previewId,fileId,caption,ftype,fsize,iData,exifObj)},_validateImage:function(previewId,fileId,fname,ftype,fsize,iData,exifObj){var self=this,$preview=self.$preview,params,w1,w2,$thumb=self._getFrame(previewId),i=$thumb.attr('data-fileindex'),$img=$thumb.find('img');fname=fname||'Untitled';$img.one('load',function(){if($img.data('validated')){return}$img.data('validated',true);w1=$thumb.width();w2=$preview.width();if(w1>w2){$img.css('width','100%')}params={ind:i,id:previewId,fileId:fileId};setTimeout(function(){var isValidWidth,isValidHeight;isValidWidth=self._isValidSize('Small','Width',$img,$thumb,fname,params);isValidHeight=self._isValidSize('Small','Height',$img,$thumb,fname,params);if(!self.resizeImage){isValidWidth=isValidWidth&&self._isValidSize('Large','Width',$img,$thumb,fname,params);isValidHeight=isValidHeight&&self._isValidSize('Large','Height',$img,$thumb,fname,params)}self._raise('fileimageloaded',[previewId]);$thumb.data('exif',exifObj);if(isValidWidth&&isValidHeight){self.fileManager.addImage(fileId,{ind:i,img:$img,thumb:$thumb,pid:previewId,typ:ftype,siz:fsize,validated:false,imgData:iData,exifObj:exifObj});self._validateAllImages()}},self.processDelay)}).one('error',function(){self._raise('fileimageloaderror',[previewId])})},_validateAllImages:function(){var self=this,counter={val:0},numImgs=self.fileManager.getImageCount(),fsize,minSize=self.resizeIfSizeMoreThan;if(numImgs!==self.fileManager.totalImages){return}self._raise('fileimagesloaded');if(!self.resizeImage){return}$.each(self.fileManager.loadedImages,function(id,config){if(!config.validated){fsize=config.siz;if(fsize&&fsize>minSize*self.bytesToKB){self._getResizedImage(id,config,counter,numImgs)}config.validated=true}})},_getResizedImage:function(id,config,counter,numImgs){var self=this,img=$(config.img)[0],width=img.naturalWidth,height=img.naturalHeight,blob,ratio=1,maxWidth=self.maxImageWidth||width,maxHeight=self.maxImageHeight||height,isValidImage=!!(width&&height),chkWidth,chkHeight,canvas=self.imageCanvas,dataURI,context=self.imageCanvasContext,type=config.typ,pid=config.pid,ind=config.ind,$thumb=config.thumb,throwError,msg,exifObj=config.exifObj,exifStr,file,params,evParams;throwError=function(msg,params,ev){if(self.isAjaxUpload){self._showFileError(msg,params,ev);}else{self._showError(msg,params,ev)}self._setPreviewError($thumb)};file=self.fileManager.getFile(id);params={id:pid,'index':ind,fileId:id};evParams=[id,pid,ind];if(!file||!isValidImage||(width<=maxWidth&&height<=maxHeight)){if(isValidImage&&file){self._raise('fileimageresized',evParams)}counter.val++;if(counter.val===numImgs){self._raise('fileimagesresized')}if(!isValidImage){throwError(self.msgImageResizeError,params,'fileimageresizeerror');return}}type=type||self.resizeDefaultImageType;chkWidth=width>maxWidth;chkHeight=height>maxHeight;if(self.resizePreference==='width'){ratio=chkWidth?maxWidth/width:(chkHeight?maxHeight/height:1)}else{ratio=chkHeight?maxHeight/height:(chkWidth?maxWidth/width:1)}self._resetCanvas();width*=ratio;height*=ratio;canvas.width=width;canvas.height=height;try{context.drawImage(img,0,0,width,height);dataURI=canvas.toDataURL(type,self.resizeQuality);if(exifObj){exifStr=window.piexif.dump(exifObj);dataURI=window.piexif.insert(exifStr,dataURI)}blob=$h.dataURI2Blob(dataURI);self.fileManager.setFile(id,blob);self._raise('fileimageresized',evParams);counter.val++;if(counter.val===numImgs){self._raise('fileimagesresized',[undefined,undefined])}if(!(blob instanceof Blob)){throwError(self.msgImageResizeError,params,'fileimageresizeerror');}}catch(err){counter.val++;if(counter.val===numImgs){self._raise('fileimagesresized',[undefined,undefined])}msg=self.msgImageResizeException.replace('{errors}',err.message);throwError(msg,params,'fileimageresizeexception');}},_showProgress:function(){var self=this;if(self.$progress&&self.$progress.length){self.$progress.show()}},_hideProgress:function(){var self=this;if(self.$progress&&self.$progress.length){self.$progress.hide()}},_initBrowse:function($container){var self=this,$el=self.$element;if(self.showBrowse){self.$btnFile=$container.find('.btn-file').append($el)}else{$el.appendTo($container).attr('tabindex',-1);$h.addCss($el,'file-no-browse')}},_initClickable:function(){var self=this,$zone,$tmpZone;if(!self.isClickable){return}$zone=self.$dropZone;if(!self.isAjaxUpload){$tmpZone=self.$preview.find('.file-default-preview');if($tmpZone.length){$zone=$tmpZone}}$h.addCss($zone,'clickable');$zone.attr('tabindex',-1);self._handler($zone,'click',function(e){var $tar=$(e.target);if(!self.$errorContainer.is(':visible')&&(!$tar.parents('.file-preview-thumbnails').length||$tar.parents('.file-default-preview').length)){self.$element.data('zoneClicked',true).trigger('click');$zone.blur()}})},_initCaption:function(){var self=this,cap=self.initialCaption||'';if(self.overwriteInitial||$h.isEmpty(cap)){self.$caption.val('');return false}self._setCaption(cap);return true},_setCaption:function(content,isError){var self=this,title,out,icon,n,cap,file;if(!self.$caption.length){return}self.$captionContainer.removeClass('icon-visible');if(isError){title=$('<div>'+self.msgValidationError+'</div>').text();n=self.fileManager.count();if(n){file=self.fileManager.getFirstFile();cap=n===1&&file?file.nameFmt:self._getMsgSelected(n)}else{cap=self._getMsgSelected(self.msgNo)}out=$h.isEmpty(content)?cap:content;icon='<span class="'+self.msgValidationErrorClass+'">'+self.msgValidationErrorIcon+'</span>'}else{if($h.isEmpty(content)){self.$caption.attr('title','');return}title=$('<div>'+content+'</div>').text();out=title;icon=self._getLayoutTemplate('fileIcon')}self.$captionContainer.addClass('icon-visible');self.$caption.attr('title',title).val(out);$h.setHtml(self.$captionIcon,icon)},_createContainer:function(){var self=this,attribs={'class':'file-input file-input-new'+(self.rtl?' kv-rtl':'')},$container=$h.createElement($h.cspBuffer.stash(self._renderMain()));$h.cspBuffer.apply($container);$container.insertBefore(self.$element).attr(attribs);self._initBrowse($container);if(self.theme){$container.addClass('theme-'+self.theme)}return $container},_refreshContainer:function(){var self=this,$container=self.$container,$el=self.$element;$el.insertAfter($container);$h.setHtml($container,self._renderMain());self._initBrowse($container);self._validateDisabled()},_validateDisabled:function(){var self=this;self.$caption.attr({readonly:self.isDisabled})},_setTabIndex:function(type,html){var self=this,index=self.tabIndexConfig[type];return html.setTokens({tabIndexConfig:index===undefined||index===null?'':'tabindex="'+index+'"'})},_renderMain:function(){var self=this,dropCss=self.dropZoneEnabled?' file-drop-zone':'file-drop-disabled',close=!self.showClose?'':self._getLayoutTemplate('close'),preview=!self.showPreview?'':self._getLayoutTemplate('preview').setTokens({'class':self.previewClass,'dropClass':dropCss}),css=self.isDisabled?self.captionClass+' file-caption-disabled':self.captionClass,caption=self.captionTemplate.setTokens({'class':css+' kv-fileinput-caption'});caption=self._setTabIndex('caption',caption);return self.mainTemplate.setTokens({'class':self.mainClass+(!self.showBrowse&&self.showCaption?' no-browse':''),'inputGroupClass':self.inputGroupClass,'preview':preview,'close':close,'caption':caption,'upload':self._renderButton('upload'),'remove':self._renderButton('remove'),'cancel':self._renderButton('cancel'),'pause':self._renderButton('pause'),'browse':self._renderButton('browse')})},_renderButton:function(type){var self=this,tmplt=self._getLayoutTemplate('btnDefault'),css=self[type+'Class'],title=self[type+'Title'],icon=self[type+'Icon'],label=self[type+'Label'],status=self.isDisabled?' disabled':'',btnType='button';switch(type){case'remove':if(!self.showRemove){return''}break;case'cancel':if(!self.showCancel){return''}css+=' kv-hidden';break;case'pause':if(!self.showPause){return''}css+=' kv-hidden';break;case'upload':if(!self.showUpload){return''}if(self.isAjaxUpload&&!self.isDisabled){tmplt=self._getLayoutTemplate('btnLink').replace('{href}',self.uploadUrl)}else{btnType='submit'}break;case'browse':if(!self.showBrowse){return''}tmplt=self._getLayoutTemplate('btnBrowse');break;default:return''}tmplt=self._setTabIndex(type,tmplt);css+=type==='browse'?' btn-file':' fileinput-'+type+' fileinput-'+type+'-button';if(!$h.isEmpty(label)){label=' <span class="'+self.buttonLabelClass+'">'+label+'</span>'}return tmplt.setTokens({'type':btnType,'css':css,'title':title,'status':status,'icon':icon,'label':label})},_renderThumbProgress:function(){var self=this;return'<div class="file-thumb-progress kv-hidden">'+self.progressInfoTemplate.setTokens({percent:101,status:self.msgUploadBegin,stats:''})+'</div>'},_renderFileFooter:function(cat,caption,size,width,isError){var self=this,config=self.fileActionSettings,rem=config.showRemove,drg=config.showDrag,upl=config.showUpload,rot=config.showRotate,zoom=config.showZoom,out,params,template=self._getLayoutTemplate('footer'),tInd=self._getLayoutTemplate('indicator'),ind=isError?config.indicatorError:config.indicatorNew,title=isError?config.indicatorErrorTitle:config.indicatorNewTitle,indicator=tInd.setTokens({'indicator':ind,'indicatorTitle':title});size=self._getSize(size);params={type:cat,caption:caption,size:size,width:width,progress:'',indicator:indicator};if(self.isAjaxUpload){params.progress=self._renderThumbProgress();params.actions=self._renderFileActions(params,upl,false,rem,rot,zoom,drg,false,false,false)}else{params.actions=self._renderFileActions(params,false,false,false,false,zoom,drg,false,false,false)}out=template.setTokens(params);out=$h.replaceTags(out,self.previewThumbTags);return out},_renderFileActions:function(cfg,showUpl,showDwn,showDel,showRot,showZoom,showDrag,disabled,url,key,isInit,dUrl,dFile){var self=this;if(!cfg.type&&isInit){cfg.type='image'}if(self.enableResumableUpload){showUpl=false}else{if(typeof showUpl==='function'){showUpl=showUpl(cfg)}}if(typeof showDwn==='function'){showDwn=showDwn(cfg)}if(typeof showDel==='function'){showDel=showDel(cfg)}if(typeof showZoom==='function'){showZoom=showZoom(cfg)}if(typeof showDrag==='function'){showDrag=showDrag(cfg)}if(typeof showRot==='function'){showRot=showRot(cfg)}if(!showUpl&&!showDwn&&!showDel&&!showRot&&!showZoom&&!showDrag){return''}var vUrl=url===false?'':' data-url="'+url+'"',btnZoom='',btnDrag='',btnRotate='',css,vKey=key===false?'':' data-key="'+key+'"',btnDelete='',btnUpload='',btnDownload='',template=self._getLayoutTemplate('actions'),config=self.fileActionSettings,otherButtons=self.otherActionButtons.setTokens({'dataKey':vKey,'key':key}),removeClass=disabled?config.removeClass+' disabled':config.removeClass;if(showDel){btnDelete=self._getLayoutTemplate('actionDelete').setTokens({'removeClass':removeClass,'removeIcon':config.removeIcon,'removeTitle':config.removeTitle,'dataUrl':vUrl,'dataKey':vKey,'key':key})}if(showRot){btnRotate=self._getLayoutTemplate('actionRotate').setTokens({'rotateClass':config.rotateClass,'rotateIcon':config.rotateIcon,'rotateTitle':config.rotateTitle})}if(showUpl){btnUpload=self._getLayoutTemplate('actionUpload').setTokens({'uploadClass':config.uploadClass,'uploadIcon':config.uploadIcon,'uploadTitle':config.uploadTitle})}if(showDwn){btnDownload=self._getLayoutTemplate('actionDownload').setTokens({'downloadClass':config.downloadClass,'downloadIcon':config.downloadIcon,'downloadTitle':config.downloadTitle,'downloadUrl':dUrl||self.initialPreviewDownloadUrl});btnDownload=btnDownload.setTokens({'filename':dFile,'key':key})}if(showZoom){btnZoom=self._getLayoutTemplate('actionZoom').setTokens({'zoomClass':config.zoomClass,'zoomIcon':config.zoomIcon,'zoomTitle':config.zoomTitle})}if(showDrag&&isInit){css='drag-handle-init '+config.dragClass;btnDrag=self._getLayoutTemplate('actionDrag').setTokens({'dragClass':css,'dragTitle':config.dragTitle,'dragIcon':config.dragIcon})}return template.setTokens({'delete':btnDelete,'upload':btnUpload,'download':btnDownload,'rotate':btnRotate,'zoom':btnZoom,'drag':btnDrag,'other':otherButtons})},_browse:function(e){var self=this;if(e&&e.isDefaultPrevented()||!self._raise('filebrowse')){return}if(self.isError&&!self.isAjaxUpload){self.clear()}if(self.focusCaptionOnBrowse){self.$captionContainer.focus()}},_change:function(e){var self=this;$(document.body).off('focusin.fileinput focusout.fileinput');if(self.changeTriggered){self._toggleLoading('hide');return}self._toggleLoading('show');var $el=self.$element,isDragDrop=arguments.length>1,isAjaxUpload=self.isAjaxUpload,tfiles,files=isDragDrop?arguments[1]:$el[0].files,ctr=self.fileManager.count(),total,initCount,len,isSingleUpl=$h.isEmpty($el.attr('multiple')),maxCount=!isAjaxUpload&&isSingleUpl?1:self.maxFileCount,maxTotCount=self.maxTotalFileCount,inclAll=maxTotCount>0&&maxTotCount>maxCount,flagSingle=(isSingleUpl&&ctr>0),throwError=function(mesg,file,previewId,index){var p1=$.extend(true,{},self._getOutData(null,{},{},files),{id:previewId,index:index}),p2={id:previewId,index:index,file:file,files:files};self.isPersistentError=true;self._toggleLoading('hide');return isAjaxUpload?self._showFileError(mesg,p1):self._showError(mesg,p2)},maxCountCheck=function(n,m,all){var msg=all?self.msgTotalFilesTooMany:self.msgFilesTooMany;msg=msg.replace('{m}',m).replace('{n}',n);self.isError=throwError(msg,null,null,null);self.$captionContainer.removeClass('icon-visible');self._setCaption('',true);self.$container.removeClass('file-input-new file-input-ajax-new')};self.reader=null;self._resetUpload();self._hideFileIcon();if(self.dropZoneEnabled){self.$container.find('.file-drop-zone .'+self.dropZoneTitleClass).remove()}if(!isAjaxUpload){if(e.target&&e.target.files===undefined){files=e.target.value?[{name:e.target.value.replace(/^.+\\/,'')}]:[]}else{files=e.target.files||{}}}tfiles=files;if($h.isEmpty(tfiles)||tfiles.length===0){if(!isAjaxUpload){self.clear()}self._raise('fileselectnone');return}self._resetErrors();len=tfiles.length;initCount=isAjaxUpload?(self.fileManager.count()+len):len;total=self._getFileCount(initCount,inclAll?false:undefined);if(maxCount>0&&total>maxCount){if(!self.autoReplace||len>maxCount){maxCountCheck((self.autoReplace&&len>maxCount?len:total),maxCount);return}if(total>maxCount){self._resetPreviewThumbs(isAjaxUpload)}}else{if(inclAll){total=self._getFileCount(initCount,true);if(maxTotCount>0&&total>maxTotCount){if(!self.autoReplace||len>maxCount){maxCountCheck((self.autoReplace&&len>maxTotCount?len:total),maxTotCount,true);return}if(total>maxCount){self._resetPreviewThumbs(isAjaxUpload)}}}if(!isAjaxUpload||flagSingle){self._resetPreviewThumbs(false);if(flagSingle){self.clearFileStack()}}else{if(isAjaxUpload&&ctr===0&&(!self.previewCache.count(true)||self.overwriteInitial)){self._resetPreviewThumbs(true)}}}if(self.autoReplace){self._getThumbs().each(function(){var $thumb=$(this);if($thumb.hasClass('file-preview-success')||$thumb.hasClass('file-preview-error')){$thumb.remove()}})}self.readFiles(tfiles);self._toggleLoading('hide')},_abort:function(params){var self=this,data;if(self.ajaxAborted&&typeof self.ajaxAborted==='object'&&self.ajaxAborted.message!==undefined){data=$.extend(true,{},self._getOutData(null),params);data.abortData=self.ajaxAborted.data||{};data.abortMessage=self.ajaxAborted.message;self._setProgress(101,self.$progress,self.msgCancelled);self._showFileError(self.ajaxAborted.message,data,'filecustomerror');self.cancel();self.unlock();return true}return!!self.ajaxAborted},_resetFileStack:function(){var self=this,i=0;self._getThumbs().each(function(){var $thumb=$(this),ind=$thumb.attr('data-fileindex'),pid=$thumb.attr('id');if(ind==='-1'||ind===-1){return}if(!self._getThumbFile($thumb)){$thumb.attr({'data-fileindex':i});i++}else{$thumb.attr({'data-fileindex':'-1'})}self._getZoom(pid).attr({'data-fileindex':$thumb.attr('data-fileindex')})})},_isFileSelectionValid:function(cnt){var self=this;cnt=cnt||0;if(self.required&&!self.getFilesCount()){self.$errorContainer.html('');self._showFileError(self.msgFileRequired);return false}if(self.minFileCount>0&&self._getFileCount(cnt)<self.minFileCount){self._noFilesError({});return false}return true},_canPreview:function(file){var self=this;if(!file||!self.showPreview||!self.$preview||!self.$preview.length){return false}var name=file.name||'',type=file.type||'',size=(file.size||0)/self.bytesToKB,cat=self._parseFileType(type,name),allowedTypes,allowedMimes,allowedExts,skipPreview,types=self.allowedPreviewTypes,mimes=self.allowedPreviewMimeTypes,exts=self.allowedPreviewExtensions||[],dTypes=self.disabledPreviewTypes,dMimes=self.disabledPreviewMimeTypes,dExts=self.disabledPreviewExtensions||[],maxSize=self.maxFilePreviewSize&&parseFloat(self.maxFilePreviewSize)||0,expAllExt=new RegExp('\\.('+exts.join('|')+')$','i'),expDisExt=new RegExp('\\.('+dExts.join('|')+')$','i');allowedTypes=!types||types.indexOf(cat)!==-1;allowedMimes=!mimes||mimes.indexOf(type)!==-1;allowedExts=!exts.length||$h.compare(name,expAllExt);skipPreview=(dTypes&&dTypes.indexOf(cat)!==-1)||(dMimes&&dMimes.indexOf(type)!==-1)||(dExts.length&&$h.compare(name,expDisExt))||(maxSize&&!isNaN(maxSize)&&size>maxSize);return!skipPreview&&(allowedTypes||allowedMimes||allowedExts)},addToStack:function(file,id){var self=this;self.stackIsUpdating=true;self.fileManager.add(file,id);self._refreshPreview();self.stackIsUpdating=false},clearFileStack:function(){var self=this;self.fileManager.clear();self._initResumableUpload();if(self.enableResumableUpload){if(self.showPause===null){self.showPause=true}if(self.showCancel===null){self.showCancel=false}}else{self.showPause=false;if(self.showCancel===null){self.showCancel=true}}return self.$element},getFileStack:function(){return this.fileManager.stack},getFileList:function(){return this.fileManager.list()},getFilesSize:function(){return this.fileManager.getTotalSize()},getFilesCount:function(includeInitial){var self=this,len=self.isAjaxUpload?self.fileManager.count():self._inputFileCount();if(includeInitial){len+=self.previewCache.count(true)}return self._getFileCount(len)},_initCapStatus:function(status){var self=this,$cap=self.$caption;$cap.removeClass('is-valid file-processing');if(!status){return}if(status==='processing'){$cap.addClass('file-processing')}else{$cap.addClass('is-valid')}},_toggleLoading:function(type){var self=this;self.$previewStatus.html(type==='hide'?'':self.msgProcessing);self.$container.removeClass('file-thumb-loading');self._initCapStatus(type==='hide'?'':'processing');if(type!=='hide'){if(self.dropZoneEnabled){self.$container.find('.file-drop-zone .'+self.dropZoneTitleClass).remove()}self.$container.addClass('file-thumb-loading')}},_initFileSelected:function(){var self=this,$el=self.$element,$body=$(document.body),ev='focusin.fileinput focusout.fileinput';if($body.length){$body.off(ev).on('focusout.fileinput',function(){self._toggleLoading('show')}).on('focusin.fileinput',function(){setTimeout(function(){if(!$el.val()){self._setFileDropZoneTitle()}$body.off(ev);self._toggleLoading('hide')},2500)})}else{self._toggleLoading('hide')}},readFiles:function(files){this.reader=new FileReader();var self=this,reader=self.reader,$container=self.$previewContainer,$status=self.$previewStatus,msgLoading=self.msgLoading,msgProgress=self.msgProgress,previewInitId=self.previewInitId,numFiles=files.length,settings=self.fileTypeSettings,readFile,fileTypes=self.allowedFileTypes,typLen=fileTypes?fileTypes.length:0,fileExt=self.allowedFileExtensions,strExt=$h.isEmpty(fileExt)?'':fileExt.join(', '),throwError=function(msg,file,previewId,index,fileId){var $thumb,p1=$.extend(true,{},self._getOutData(null,{},{},files),{id:previewId,index:index,fileId:fileId}),p2={id:previewId,index:index,fileId:fileId,file:file,files:files};self._previewDefault(file,true);$thumb=self._getFrame(previewId,true);self._toggleLoading('hide');if(self.isAjaxUpload){setTimeout(function(){readFile(index+1)},self.processDelay)}else{self.unlock();numFiles=0}if(self.removeFromPreviewOnError&&$thumb.length){$thumb.remove()}else{self._initFileActions();$thumb.find('.kv-file-upload').remove()}self.isPersistentError=true;self.isError=self.isAjaxUpload?self._showFileError(msg,p1):self._showError(msg,p2);self._updateFileDetails(numFiles)};self.fileManager.clearImages();$.each(files,function(key,file){var func=self.fileTypeSettings.image;if(func&&func(file.type)){self.fileManager.totalImages++}});readFile=function(i){var $error=self.$errorContainer,errors,fm=self.fileManager;if(i>=numFiles){self.unlock();if(self.duplicateErrors.length){errors='<li>'+self.duplicateErrors.join('</li><li>')+'</li>';if($error.find('ul').length===0){$h.setHtml($error,self.errorCloseButton+'<ul>'+errors+'</ul>')}else{$error.find('ul').append(errors)}$error.fadeIn(self.fadeDelay);self._handler($error.find('.kv-error-close'),'click',function(){$error.fadeOut(self.fadeDelay)});self.duplicateErrors=[]}if(self.isAjaxUpload){self._raise('filebatchselected',[fm.stack]);if(fm.count()===0&&!self.isError){self.reset()}}else{self._raise('filebatchselected',[files])}$container.removeClass('file-thumb-loading');self._initCapStatus('valid');$status.html('');return}self.lock(true);var file=files[i],id,previewId,fileProcessed,fSize=(file&&file.size||0),sizeHuman=self._getSize(fSize,true),j,msg,fnImage=settings.image,chk,typ,typ1,typ2,caption,fileSize=fSize/self.bytesToKB,fileExtExpr='',previewData,fileCount=0,strTypes='',fileId,canLoad,fileReaderAborted=false,func,knownTypes=0,isImage,processFileLoaded,initFileData;initFileData=function(dataSource){dataSource=dataSource||file;id=fileId=self._getFileId(file);previewId=previewInitId+'-'+id;previewData=$h.createObjectURL(dataSource);caption=self._getFileName(file,'')};processFileLoaded=function(){var isImageResized=!!fm.loadedImages[id],msg=msgProgress.setTokens({'index':i+1,'files':numFiles,'percent':50,'name':caption});setTimeout(function(){$status.html(msg);self._updateFileDetails(numFiles);if(self.getFilesCount(true)>0&&self.getFrames(':visible')){self.$dropZone.find('.'+self.dropZoneTitleClass).remove()}readFile(i+1)},self.processDelay);if(self._raise('fileloaded',[file,previewId,id,i,reader])&&self.isAjaxUpload){if(!isImageResized){fm.add(file)}}else{if(isImageResized){fm.removeFile(id)}}};if(!file){return}initFileData();if(typLen>0){for(j=0;j<typLen;j++){typ1=fileTypes[j];typ2=self.msgFileTypes[typ1]||typ1;strTypes+=j===0?typ2:', '+typ2}}if(caption===false){readFile(i+1);return}if(caption.length===0){msg=self.msgInvalidFileName.replace('{name}',$h.htmlEncode($h.getFileName(file),'[unknown]'));throwError(msg,file,previewId,i,fileId);return}if(!$h.isEmpty(fileExt)){fileExtExpr=new RegExp('\\.('+fileExt.join('|')+')$','i')}if(self.isAjaxUpload&&fm.exists(fileId)||self._getFrame(previewId,true).length){var p2={id:previewId,index:i,fileId:fileId,file:file,files:files};msg=self.msgDuplicateFile.setTokens({name:caption,size:sizeHuman});if(self.isAjaxUpload){if(!self.stackIsUpdating){self.duplicateErrors.push(msg);self.isDuplicateError=true;self._raise('fileduplicateerror',[file,fileId,caption,sizeHuman,previewId,i])}readFile(i+1);self._updateFileDetails(numFiles)}else{self._showError(msg,p2);self.unlock();numFiles=0;self._clearFileInput();self.reset();self._updateFileDetails(numFiles)}return}if(self.maxFileSize>0&&fileSize>self.maxFileSize){msg=self.msgSizeTooLarge.setTokens({'name':caption,'size':sizeHuman,'maxSize':self._getSize(self.maxFileSize*self.bytesToKB,true)});throwError(msg,file,previewId,i,fileId);return}if(self.minFileSize!==null&&fileSize<=$h.getNum(self.minFileSize)){msg=self.msgSizeTooSmall.setTokens({'name':caption,'size':sizeHuman,'minSize':self._getSize(self.minFileSize*self.bytesToKB,true)});throwError(msg,file,previewId,i,fileId);return}if(!$h.isEmpty(fileTypes)&&$h.isArray(fileTypes)){for(j=0;j<fileTypes.length;j+=1){typ=fileTypes[j];func=settings[typ];fileCount+=!func||(typeof func!=='function')?0:(func(file.type,$h.getFileName(file))?1:0)}if(fileCount===0){msg=self.msgInvalidFileType.setTokens({name:caption,types:strTypes});throwError(msg,file,previewId,i,fileId);return}}if(fileCount===0&&!$h.isEmpty(fileExt)&&$h.isArray(fileExt)&&!$h.isEmpty(fileExtExpr)){chk=$h.compare(caption,fileExtExpr);fileCount+=$h.isEmpty(chk)?0:chk.length;if(fileCount===0){msg=self.msgInvalidFileExtension.setTokens({name:caption,extensions:strExt});throwError(msg,file,previewId,i,fileId);return}}if(!self._canPreview(file)){canLoad=self._raise('filebeforeload',[file,i,reader]);if(self.isAjaxUpload&&canLoad){fm.add(file)}if(self.showPreview&&canLoad){$container.addClass('file-thumb-loading');self._initCapStatus('processing');self._previewDefault(file);self._initFileActions()}setTimeout(function(){if(canLoad){self._updateFileDetails(numFiles)}readFile(i+1);self._raise('fileloaded',[file,previewId,id,i])},10);return}isImage=fnImage(file.type,caption);$status.html(msgLoading.replace('{index}',i+1).replace('{files}',numFiles));$container.addClass('file-thumb-loading');self._initCapStatus('processing');reader.onerror=function(evt){self._errorHandler(evt,caption)};reader.onload=function(theFile){var hex,fileInfo,fileData,byte,bytes=[],contents,mime,processPreview=function(fType,ext){if($h.isEmpty(fType)){contents=$h.arrayBuffer2String(reader.result);fType=$h.isSvg(contents)?'image/svg+xml':$h.getMimeType(hex,contents,file.type)}fileInfo={'name':caption,'type':fType||''};if(ext&&typeof File!=="undefined"){try{var fName=fileInfo.filename=caption+'.'+ext;fileProcessed=new File([file],fName,{type:fileInfo.type});initFileData(fileProcessed)}catch(err){}}isImage=fnImage(fType,'');if(isImage){var newReader=new FileReader();newReader.onerror=function(theFileNew){self._errorHandler(theFileNew,caption)};newReader.onload=function(theFileNew){if(self.isAjaxUpload&&!self._raise('filebeforeload',[file,i,reader])){fileReaderAborted=true;self._resetCaption();reader.abort();$status.html('');$container.removeClass('file-thumb-loading');self._initCapStatus('valid');self.enable();return}self._previewFile(i,file,theFileNew,previewData,fileInfo);self._initFileActions();processFileLoaded()};newReader.readAsDataURL(file);return}if(self.isAjaxUpload&&!self._raise('filebeforeload',[file,i,reader])){fileReaderAborted=true;self._resetCaption();reader.abort();$status.html('');$container.removeClass('file-thumb-loading');self._initCapStatus('valid');self.enable();return}self._previewFile(i,file,theFile,previewData,fileInfo);self._initFileActions();processFileLoaded()};mime=file.type;fileInfo={'name':caption,'type':mime};$.each(settings,function(k,f){if(k!=='object'&&k!=='other'&&typeof f==='function'&&f(mime,caption)){knownTypes++}});if(typeof FileTypeParser!=="undefined"){fileData=new Uint8Array(theFile.target.result);new FileTypeParser().parse(fileData).then(function(result){processPreview(result&&result.mime||mime,result&&result.ext||'')})}else{if(knownTypes===0){fileData=new Uint8Array(theFile.target.result);for(j=0;j<fileData.length;j++){byte=fileData[j].toString(16);bytes.push(byte)}hex=bytes.join('').toLowerCase().substring(0,8);mime=$h.getMimeType(hex,'','')}processPreview(mime)}};reader.onprogress=function(data){if(data.lengthComputable){var fact=(data.loaded/data.total)*100,progress=Math.ceil(fact);msg=msgProgress.setTokens({'index':i+1,'files':numFiles,'percent':progress,'name':caption});setTimeout(function(){if(!fileReaderAborted){$status.html(msg)}},self.processDelay)}};reader.readAsArrayBuffer(file)};readFile(0);self._updateFileDetails(numFiles)},lock:function(selectMode){var self=this,$container=self.$container;self._resetErrors();self.disable();if(!selectMode&&self.showCancel){$container.find('.fileinput-cancel').show()}if(!selectMode&&self.showPause){$container.find('.fileinput-pause').show()}self._initCapStatus('processing');self._raise('filelock',[self.fileManager.stack,self._getExtraData()]);return self.$element},unlock:function(reset){var self=this,$container=self.$container;if(reset===undefined){reset=true}self.enable();$container.removeClass('is-locked');if(self.showCancel){$container.find('.fileinput-cancel').hide()}if(self.showPause){$container.find('.fileinput-pause').hide()}if(reset){self._resetFileStack()}self._initCapStatus();self._raise('fileunlock',[self.fileManager.stack,self._getExtraData()]);return self.$element},resume:function(){var self=this,fm=self.fileManager,flag=false,rm=self.resumableManager;fm.bpsLog=[];fm.bps=0;if(!self.enableResumableUpload){return self.$element}if(self.paused){self._toggleResumableProgress(self.progressPauseTemplate,self.msgUploadResume)}else{flag=true}self.paused=false;if(flag){self._toggleResumableProgress(self.progressInfoTemplate,self.msgUploadBegin)}setTimeout(function(){rm.upload()},self.processDelay);return self.$element},paste:function(e){var self=this,ev=e.originalEvent,files=ev.clipboardData&&ev.clipboardData.files||null;if(files){self._dropFiles(e,files)}return self.$element},pause:function(){var self=this,rm=self.resumableManager,xhr=self.ajaxRequests,len=xhr.length,i,pct=rm.getProgress(),actions=self.fileActionSettings,tm=self.taskManager,pool=tm.getPool(rm.id);if(!self.enableResumableUpload){return self.$element}else{if(pool){pool.cancel()}}self._raise('fileuploadpaused',[self.fileManager,rm]);if(len>0){for(i=0;i<len;i+=1){self.paused=true;xhr[i].abort()}}if(self.showPreview){self._getThumbs().each(function(){var $thumb=$(this),t=self._getLayoutTemplate('stats'),stats,$indicator=$thumb.find('.file-upload-indicator');$thumb.removeClass('file-uploading');if($indicator.attr('title')===actions.indicatorLoadingTitle){self._setThumbStatus($thumb,'Paused');stats=t.setTokens({pendingTime:self.msgPaused,uploadSpeed:''});self.paused=true;self._setProgress(pct,$thumb.find('.file-thumb-progress'),pct+'%',stats)}if(!self._getThumbFile($thumb)){$thumb.find('.kv-file-remove').removeClass('disabled').removeAttr('disabled')}})}self._setProgress(101,self.$progress,self.msgPaused);return self.$element},cancel:function(){var self=this,xhr=self.ajaxRequests,rm=self.resumableManager,tm=self.taskManager,pool=rm?tm.getPool(rm.id):undefined,len=xhr.length,i;if(self.enableResumableUpload&&pool){pool.cancel().done(function(){self._setProgressCancelled()});rm.reset();self._raise('fileuploadcancelled',[self.fileManager,rm])}else{if(self.ajaxPool){self.ajaxPool.cancel()}self._raise('fileuploadcancelled',[self.fileManager])}self._initAjax();if(len>0){for(i=0;i<len;i+=1){self.cancelling=true;xhr[i].abort()}}self._getThumbs().each(function(){var $thumb=$(this),$prog=$thumb.find('.file-thumb-progress');$thumb.removeClass('file-uploading');self._setProgress(0,$prog);$prog.hide();if(!self._getThumbFile($thumb)){$thumb.find('.kv-file-upload').removeClass('disabled').removeAttr('disabled');$thumb.find('.kv-file-remove').removeClass('disabled').removeAttr('disabled')}self.unlock()});setTimeout(function(){self._setProgressCancelled()},self.processDelay);return self.$element},clear:function(){var self=this,cap;if(!self._raise('fileclear')){return}self.clearInput=true;self.$btnUpload.removeAttr('disabled');self._getThumbs().find('video,audio,img').each(function(){$h.cleanMemory($(this))});self._clearFileInput();self._resetUpload();self.clearFileStack();self.isDuplicateError=false;self.isPersistentError=false;self._resetErrors(true);if(self._hasInitialPreview()){self._showFileIcon();self._resetPreview();self._initPreviewActions();self.$container.removeClass('file-input-new')}else{self._getThumbs().each(function(){self._clearObjects($(this))});if(self.isAjaxUpload){self.previewCache.data={}}self.$preview.html('');cap=(!self.overwriteInitial&&self.initialCaption.length>0)?self.initialCaption:'';self.$caption.attr('title','').val(cap);$h.addCss(self.$container,'file-input-new');self._validateDefaultPreview()}if(self.$container.find($h.FRAMES).length===0){if(!self._initCaption()){self.$captionContainer.removeClass('icon-visible')}}self._hideFileIcon();if(self.focusCaptionOnClear){self.$captionContainer.focus()}self._setFileDropZoneTitle();self._raise('filecleared');return self.$element},reset:function(){var self=this;if(!self._raise('filereset')){return}self.lastProgress=0;self._resetPreview();self.$container.find('.fileinput-filename').text('');$h.addCss(self.$container,'file-input-new');if(self.getFrames().length){self.$container.removeClass('file-input-new')}self.clearFileStack();self._setFileDropZoneTitle();return self.$element},disable:function(){var self=this,$container=self.$container;self.isDisabled=true;self._raise('filedisabled');self.$element.attr('disabled','disabled');$container.addClass('is-locked');$h.addCss($container.find('.btn-file'),'disabled');$container.find('.kv-fileinput-caption').addClass('file-caption-disabled');$container.find('.fileinput-remove, .fileinput-upload, .file-preview-frame button').attr('disabled',true);self._initDragDrop();return self.$element},enable:function(){var self=this,$container=self.$container;self.isDisabled=false;self._raise('fileenabled');self.$element.removeAttr('disabled');$container.removeClass('is-locked');$container.find('.kv-fileinput-caption').removeClass('file-caption-disabled');$container.find('.fileinput-remove, .fileinput-upload, .file-preview-frame button').removeAttr('disabled');$container.find('.btn-file').removeClass('disabled');self._initDragDrop();return self.$element},upload:function(){var self=this,fm=self.fileManager,totLen=fm.count(),i,outData,tm=self.taskManager,hasExtraData=!$.isEmptyObject(self._getExtraData());fm.bpsLog=[];fm.bps=0;if(!self.isAjaxUpload||self.isDisabled||!self._isFileSelectionValid(totLen)){return}self.lastProgress=0;self._resetUpload();if(totLen===0&&!hasExtraData){self._showFileError(self.msgUploadEmpty);return}self.cancelling=false;self.uploadInitiated=true;self._showProgress();self.lock();if(totLen===0&&hasExtraData){self._setProgress(2);self._uploadExtraOnly();return}if(self.enableResumableUpload){return self.resume()}if(self.uploadAsync||self.enableResumableUpload){outData=self._getOutData(null);if(!self._checkBatchPreupload(outData)){return}self.fileBatchCompleted=false;self.uploadCache=[];$.each(self.getFileStack(),function(id){var previewId=self._getThumbId(id);self.uploadCache.push({id:previewId,content:null,config:null,tags:null,append:true})});self.$preview.find('.file-preview-initial').removeClass($h.SORT_CSS);self._initSortable()}self._setProgress(2);self.hasInitData=false;if(self.uploadAsync){i=0;var pool=self.ajaxPool=tm.addPool($h.uniqId());$.each(self.getFileStack(),function(id){pool.addTask(id+i,function(deferrer){self._uploadSingle(i,id,true,deferrer)});i++});pool.run(self.maxAjaxThreads).done(function(){self._log('Async upload batch completed successfully.');self._raise('filebatchuploadsuccess',[fm.stack,self._getExtraData()])}).fail(function(){self._log('Async upload batch completed with errors.');self._raise('filebatchuploaderror',[fm.stack,self._getExtraData()])});return}self._uploadBatch();return self.$element},destroy:function(){var self=this,$form=self.$form,$cont=self.$container,$el=self.$element,ns=self.namespace;$(document).off(ns);$(window).off(ns);if($form&&$form.length){$form.off(ns)}if(self.isAjaxUpload){self._clearFileInput()}self._cleanup();self._initPreviewCache();$el.insertBefore($cont).off(ns).removeData();$cont.off().remove();return $el},refresh:function(options){var self=this,$el=self.$element;if(typeof options!=='object'||$h.isEmpty(options)){options=self.options}else{options=$.extend(true,{},self.options,options)}self._init(options,true);self._listen();return $el},zoom:function(frameId){var self=this,$frame=self._getFrame(frameId);self._showModal($frame)},getExif:function(frameId){var self=this,$frame=self._getFrame(frameId);return $frame&&$frame.data('exif')||null},getFrames:function(cssFilter){var self=this,$frames;cssFilter=cssFilter||'';$frames=self.$preview.find($h.FRAMES+cssFilter);if(self.reversePreviewOrder){$frames=$($frames.get().reverse())}return $frames},getPreview:function(){var self=this;return{content:self.initialPreview,config:self.initialPreviewConfig,tags:self.initialPreviewThumbTags}}};$.fn.fileinput=function(option){if(!$h.hasFileAPISupport()&&!$h.isIE(9)){return}var args=Array.apply(null,arguments),retvals=[];args.shift();this.each(function(){var self=$(this),data=self.data('fileinput'),options=typeof option==='object'&&option,theme=options.theme||self.data('theme'),l={},t={},lang=options.language||self.data('language')||$.fn.fileinput.defaults.language||'en',opt;if(!data){if(theme){t=$.fn.fileinputThemes[theme]||{}}if(lang!=='en'&&!$h.isEmpty($.fn.fileinputLocales[lang])){l=$.fn.fileinputLocales[lang]||{}}opt=$.extend(true,{},$.fn.fileinput.defaults,t,$.fn.fileinputLocales.en,l,options,self.data());data=new FileInput(this,opt);self.data('fileinput',data)}if(typeof option==='string'){retvals.push(data[option].apply(data,args))}});switch(retvals.length){case 0:return this;case 1:return retvals[0];default:return retvals}};var IFRAME_ATTRIBS='class="kv-preview-data file-preview-pdf" src="{renderer}?file={data}" {style}',defBtnCss1='btn btn-sm btn-kv '+$h.defaultButtonCss(),defBtnCss2='btn '+$h.defaultButtonCss();$.fn.fileinput.defaults={language:'zh',bytesToKB:1024,showCaption:true,showBrowse:true,showPreview:true,showRemove:true,showUpload:true,showUploadStats:true,showCancel:null,showPause:null,showClose:true,showUploadedThumbs:true,showConsoleLogs:false,browseOnZoneClick:false,autoReplace:false,showDescriptionClose:true,autoOrientImage:function(){var ua=window.navigator.userAgent,webkit=!!ua.match(/WebKit/i),iOS=!!ua.match(/iP(od|ad|hone)/i),iOSSafari=iOS&&webkit&&!ua.match(/CriOS/i);return!iOSSafari},autoOrientImageInitial:true,showExifErrorLog:false,required:false,rtl:false,hideThumbnailContent:false,encodeUrl:true,focusCaptionOnBrowse:true,focusCaptionOnClear:true,generateFileId:null,previewClass:'',captionClass:'',frameClass:'krajee-default',mainClass:'',inputGroupClass:'',mainTemplate:null,fileSizeGetter:null,initialCaption:'',initialPreview:[],initialPreviewDelimiter:'*$$*',initialPreviewAsData:false,initialPreviewFileType:'image',initialPreviewConfig:[],initialPreviewThumbTags:[],previewThumbTags:{},initialPreviewShowDelete:true,initialPreviewDownloadUrl:'',removeFromPreviewOnError:false,deleteUrl:'',deleteExtraData:{},overwriteInitial:true,sanitizeZoomCache:function(content){var $container=$h.createElement(content);$container.find('input,textarea,select,datalist,form,.file-thumbnail-footer').remove();return $container.html()},previewZoomButtonIcons:{prev:'<i class="glyphicon glyphicon-triangle-left"></i>',next:'<i class="glyphicon glyphicon-triangle-right"></i>',toggleheader:'<i class="glyphicon glyphicon-resize-vertical"></i>',fullscreen:'<i class="glyphicon glyphicon-fullscreen"></i>',borderless:'<i class="glyphicon glyphicon-resize-full"></i>',close:'<i class="glyphicon glyphicon-remove"></i>'},previewZoomButtonClasses:{prev:'btn btn-default btn-outline-secondary btn-navigate',next:'btn btn-default btn-outline-secondary btn-navigate',rotate:defBtnCss1,toggleheader:defBtnCss1,fullscreen:defBtnCss1,borderless:defBtnCss1,close:defBtnCss1},previewTemplates:{},previewContentTemplates:{},preferIconicPreview:false,preferIconicZoomPreview:false,alwaysPreviewFileExtensions:[],rotatableFileExtensions:['jpg','jpeg','png','gif'],allowedFileTypes:null,allowedFileExtensions:null,allowedPreviewTypes:undefined,allowedPreviewMimeTypes:null,allowedPreviewExtensions:null,disabledPreviewTypes:undefined,disabledPreviewExtensions:['msi','exe','com','zip','rar','app','vb','scr'],disabledPreviewMimeTypes:null,defaultPreviewContent:null,customLayoutTags:{},customPreviewTags:{},previewFileIcon:'<i class="bi-file-earmark-fill"></i>',previewFileIconClass:'file-other-icon',previewFileIconSettings:{},previewFileExtSettings:{},buttonLabelClass:'hidden-xs',browseIcon:'<i class="bi-folder2-open"></i> ',browseClass:'btn btn-primary',removeIcon:'<i class="bi-trash"></i>',removeClass:defBtnCss2,cancelIcon:'<i class="bi-slash-circle"></i>',cancelClass:defBtnCss2,pauseIcon:'<i class="bi-pause-fill"></i>',pauseClass:defBtnCss2,uploadIcon:'<i class="bi-upload"></i>',uploadClass:defBtnCss2,uploadUrl:null,uploadUrlThumb:null,uploadAsync:true,uploadParamNames:{chunkCount:'chunkCount',chunkIndex:'chunkIndex',chunkSize:'chunkSize',chunkSizeStart:'chunkSizeStart',chunksUploaded:'chunksUploaded',fileBlob:'fileBlob',fileId:'fileId',fileName:'fileName',fileRelativePath:'fileRelativePath',fileSize:'fileSize',retryCount:'retryCount'},maxAjaxThreads:5,fadeDelay:800,processDelay:100,bitrateUpdateDelay:500,queueDelay:10,progressDelay:0,enableResumableUpload:false,resumableUploadOptions:{fallback:null,testUrl:null,chunkSize:2048,maxThreads:4,maxRetries:3,showErrorLog:true,retainErrorHistory:false,skipErrorsAndProceed:false},uploadExtraData:{},zoomModalHeight:485,minImageWidth:null,minImageHeight:null,maxImageWidth:null,maxImageHeight:null,resizeImage:false,resizePreference:'width',resizeQuality:0.92,resizeDefaultImageType:'image/jpeg',resizeIfSizeMoreThan:0,minFileSize:-1,maxFileSize:0,maxFilePreviewSize:25600,minFileCount:0,maxFileCount:0,maxTotalFileCount:0,validateInitialCount:false,msgValidationErrorClass:'text-danger',msgValidationErrorIcon:'<i class="glyphicon glyphicon-exclamation-sign"></i> ',msgErrorClass:'file-error-message',progressThumbClass:'progress-bar progress-bar-striped active progress-bar-animated',progressClass:'progress-bar bg-success progress-bar-success progress-bar-striped active progress-bar-animated',progressInfoClass:'progress-bar bg-info progress-bar-info progress-bar-striped active progress-bar-animated',progressCompleteClass:'progress-bar bg-success progress-bar-success',progressPauseClass:'progress-bar bg-primary progress-bar-primary progress-bar-striped active progress-bar-animated',progressErrorClass:'progress-bar bg-danger progress-bar-danger',progressUploadThreshold:99,previewFileType:'image',elCaptionContainer:null,elCaptionText:null,elPreviewContainer:null,elPreviewImage:null,elPreviewStatus:null,elErrorContainer:null,errorCloseButton:undefined,slugCallback:null,dropZoneEnabled:true,dropZoneTitleClass:'file-drop-zone-title',fileActionSettings:{},otherActionButtons:'',textEncoding:'UTF-8',preProcessUpload:null,ajaxSettings:{},ajaxDeleteSettings:{},showAjaxErrorDetails:true,mergeAjaxCallbacks:false,mergeAjaxDeleteCallbacks:false,retryErrorUploads:true,reversePreviewOrder:false,usePdfRenderer:function(){var isIE11=!!window.MSInputMethodContext&&!!document.documentMode;return!!navigator.userAgent.match(/(iPod|iPhone|iPad|Android)/i)||isIE11},pdfRendererUrl:'',pdfRendererTemplate:'<iframe '+IFRAME_ATTRIBS+'></iframe>',tabIndexConfig:{browse:500,remove:500,upload:500,cancel:null,pause:null,modal:-1}};$.fn.fileinputLocales.en={sizeUnits:['B','KB','MB','GB','TB','PB','EB','ZB','YB'],bitRateUnits:['B/s','KB/s','MB/s','GB/s','TB/s','PB/s','EB/s','ZB/s','YB/s'],fileSingle:'file',filePlural:'files',browseLabel:'Browse &hellip;',removeLabel:'Remove',removeTitle:'Clear all unprocessed files',cancelLabel:'Cancel',cancelTitle:'Abort ongoing upload',pauseLabel:'Pause',pauseTitle:'Pause ongoing upload',uploadLabel:'Upload',uploadTitle:'Upload selected files',msgNo:'No',msgNoFilesSelected:'No files selected',msgCancelled:'Cancelled',msgPaused:'Paused',msgPlaceholder:'Select {files} ...',msgZoomModalHeading:'Detailed Preview',msgFileRequired:'You must select a file to upload.',msgSizeTooSmall:'File "{name}" (<b>{size}</b>) is too small and must be larger than <b>{minSize}</b>.',msgSizeTooLarge:'File "{name}" (<b>{size}</b>) exceeds maximum allowed upload size of <b>{maxSize}</b>.',msgFilesTooLess:'You must select at least <b>{n}</b> {files} to upload.',msgFilesTooMany:'Number of files selected for upload <b>({n})</b> exceeds maximum allowed limit of <b>{m}</b>.',msgTotalFilesTooMany:'You can upload a maximum of <b>{m}</b> files (<b>{n}</b> files detected).',msgFileNotFound:'File "{name}" not found!',msgFileSecured:'Security restrictions prevent reading the file "{name}".',msgFileNotReadable:'File "{name}" is not readable.',msgFilePreviewAborted:'File preview aborted for "{name}".',msgFilePreviewError:'An error occurred while reading the file "{name}".',msgInvalidFileName:'Invalid or unsupported characters in file name "{name}".',msgInvalidFileType:'Invalid type for file "{name}". Only "{types}" files are supported.',msgInvalidFileExtension:'Invalid extension for file "{name}". Only "{extensions}" files are supported.',msgFileTypes:{'image':'image','html':'HTML','text':'text','video':'video','audio':'audio','flash':'flash','pdf':'PDF','object':'object'},msgUploadAborted:'The file upload was aborted',msgUploadThreshold:'Processing &hellip;',msgUploadBegin:'Initializing &hellip;',msgUploadEnd:'Done',msgUploadResume:'Resuming upload &hellip;',msgUploadEmpty:'No valid data available for upload.',msgUploadError:'Upload Error',msgDeleteError:'Delete Error',msgProgressError:'Error',msgValidationError:'Validation Error',msgLoading:'Loading file {index} of {files} &hellip;',msgProgress:'Loading file {index} of {files} - {name} - {percent}% completed.',msgSelected:'{n} {files} selected',msgProcessing:'Processing ...',msgFoldersNotAllowed:'Drag & drop files only! {n} folder(s) dropped were skipped.',msgImageWidthSmall:'Width of image file "{name}" must be at least <b>{size} px</b> (detected <b>{dimension} px</b>).',msgImageHeightSmall:'Height of image file "{name}" must be at least <b>{size} px</b> (detected <b>{dimension} px</b>).',msgImageWidthLarge:'Width of image file "{name}" cannot exceed <b>{size} px</b> (detected <b>{dimension} px</b>).',msgImageHeightLarge:'Height of image file "{name}" cannot exceed <b>{size} px</b> (detected <b>{dimension} px</b>).',msgImageResizeError:'Could not get the image dimensions to resize.',msgImageResizeException:'Error while resizing the image.<pre>{errors}</pre>',msgAjaxError:'Something went wrong with the {operation} operation. Please try again later!',msgAjaxProgressError:'{operation} failed',msgDuplicateFile:'File "{name}" of same size "{size}" has already been selected earlier. Skipping duplicate selection.',msgResumableUploadRetriesExceeded:'Upload aborted beyond <b>{max}</b> retries for file <b>{file}</b>! Error Details: <pre>{error}</pre>',msgPendingTime:'{time} remaining',msgCalculatingTime:'calculating time remaining',ajaxOperations:{deleteThumb:'file delete',uploadThumb:'file upload',uploadBatch:'batch file upload',uploadExtra:'form data upload'},dropZoneTitle:'Drag & drop files here &hellip;',dropZoneClickTitle:'<br>(or click to select {files})',previewZoomButtonTitles:{prev:'View previous file',next:'View next file',rotate:'Rotate 90 deg. clockwise',toggleheader:'Toggle header',fullscreen:'Toggle full screen',borderless:'Toggle borderless mode',close:'Close detailed preview'}};$.fn.fileinputLocales.zh={sizeUnits:['B','KB','MB','GB','TB','PB','EB','ZB','YB'],bitRateUnits:['B/s','KB/s','MB/s','GB/s','TB/s','PB/s','EB/s','ZB/s','YB/s'],fileSingle:'文件',filePlural:'个文件',browseLabel:'选择 &hellip;',removeLabel:'移除',removeTitle:'清除选中文件',cancelLabel:'取消',cancelTitle:'取消进行中的上传',pauseLabel:'暂停',pauseTitle:'暂停上传',uploadLabel:'上传',uploadTitle:'上传选中文件',msgNo:'没有',msgNoFilesSelected:'未选择文件',msgPaused:'已暂停',msgCancelled:'取消',msgPlaceholder:'选择 {files} ...',msgZoomModalHeading:'详细预览',msgFileRequired:'必须选择一个文件上传.',msgSizeTooSmall:'文件 "{name}" (<b>{size}</b>) 必须大于限定大小 <b>{minSize}</b>.',msgSizeTooLarge:'文件 "{name}" (<b>{size}</b>) 超过了允许大小 <b>{maxSize}</b>.',msgFilesTooLess:'你必须选择最少 <b>{n}</b> {files} 来上传. ',msgFilesTooMany:'选择的上传文件个数 <b>({n})</b> 超出最大文件的限制个数 <b>{m}</b>.',msgTotalFilesTooMany:'你最多可以上传 <b>{m}</b> 个文件 (当前有<b>{n}</b> 个文件).',msgFileNotFound:'文件 "{name}" 未找到!',msgFileSecured:'安全限制,为了防止读取文件 "{name}".',msgFileNotReadable:'文件 "{name}" 不可读.',msgFilePreviewAborted:'取消 "{name}" 的预览.',msgFilePreviewError:'读取 "{name}" 时出现了一个错误.',msgInvalidFileName:'文件名 "{name}" 包含非法字符.',msgInvalidFileType:'不正确的类型 "{name}". 只支持 "{types}" 类型的文件.',msgInvalidFileExtension:'不正确的文件扩展名 "{name}". 只支持 "{extensions}" 的文件扩展名.',msgFileTypes:{'image':'image','html':'HTML','text':'text','video':'video','audio':'audio','flash':'flash','pdf':'PDF','object':'object'},msgUploadAborted:'该文件上传被中止',msgUploadThreshold:'处理中 &hellip;',msgUploadBegin:'正在初始化 &hellip;',msgUploadEnd:'完成',msgUploadResume:'继续上传 &hellip;',msgUploadEmpty:'无效的文件上传.',msgUploadError:'上传出错',msgDeleteError:'删除出错',msgProgressError:'上传出错',msgValidationError:'验证错误',msgLoading:'加载第 {index} 文件 共 {files} &hellip;',msgProgress:'加载第 {index} 文件 共 {files} - {name} - {percent}% 完成.',msgSelected:'{n} {files} 选中',msgProcessing:'处理中 ...',msgFoldersNotAllowed:'只支持拖拽文件! 跳过 {n} 拖拽的文件夹.',msgImageWidthSmall:'图像文件的"{name}"的宽度必须是至少{size}像素.',msgImageHeightSmall:'图像文件的"{name}"的高度必须至少为{size}像素.',msgImageWidthLarge:'图像文件"{name}"的宽度不能超过{size}像素.',msgImageHeightLarge:'图像文件"{name}"的高度不能超过{size}像素.',msgImageResizeError:'无法获取的图像尺寸调整。',msgImageResizeException:'调整图像大小时发生错误。<pre>{errors}</pre>',msgAjaxError:'{operation} 发生错误. 请重试!',msgAjaxProgressError:'{operation} 失败',msgDuplicateFile:'文件 "{name}",大小 "{size}" 已经被选中.忽略相同的文件.',msgResumableUploadRetriesExceeded:'文件 <b>{file}</b> 上传失败超过 <b>{max}</b> 次重试 ! 错误详情: <pre>{error}</pre>',msgPendingTime:'{time} 剩余',msgCalculatingTime:'计算剩余时间',ajaxOperations:{deleteThumb:'删除文件',uploadThumb:'上传文件',uploadBatch:'批量上传',uploadExtra:'表单数据上传'},dropZoneTitle:'拖拽文件到这里 &hellip;<br>支持多文件同时上传',dropZoneClickTitle:'<br>(或点击{files}按钮选择文件)',fileActionSettings:{removeTitle:'删除文件',uploadTitle:'上传文件',downloadTitle:'下载文件',uploadRetryTitle:'重试',rotateTitle:'顺时针旋转90度',zoomTitle:'查看详情',dragTitle:'移动 / 重置',indicatorNewTitle:'没有上传',indicatorSuccessTitle:'上传',indicatorErrorTitle:'上传错误',indicatorPausedTitle:'上传已暂停',indicatorLoadingTitle:'上传 &hellip;'},previewZoomButtonTitles:{prev:'预览上一个文件',next:'预览下一个文件',rotate:'顺时针旋转90度',toggleheader:'缩放',fullscreen:'全屏',borderless:'无边界模式',close:'关闭当前预览'}};$.fn.fileinput.Constructor=FileInput;$(document).ready(function(){var $input=$('input.file[type=file]');if($input.length){$input.fileinput()}})}));
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-fileinput/loading-sm.gif b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-fileinput/loading-sm.gif
new file mode 100644
index 0000000..44e3b7a
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-fileinput/loading-sm.gif
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-fileinput/loading.gif b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-fileinput/loading.gif
new file mode 100644
index 0000000..0ea146c
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-fileinput/loading.gif
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-select/bootstrap-select.css b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-select/bootstrap-select.css
new file mode 100644
index 0000000..34edabf
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-select/bootstrap-select.css
@@ -0,0 +1,459 @@
+/*!
+ * Bootstrap-select v1.13.18 (https://developer.snapappointments.com/bootstrap-select)
+ *
+ * Copyright 2012-2020 SnapAppointments, LLC
+ * Licensed under MIT (https://github.com/snapappointments/bootstrap-select/blob/master/LICENSE)
+ */
+
+@-webkit-keyframes bs-notify-fadeOut {
+  0% {
+    opacity: 0.9;
+  }
+  100% {
+    opacity: 0;
+  }
+}
+@-o-keyframes bs-notify-fadeOut {
+  0% {
+    opacity: 0.9;
+  }
+  100% {
+    opacity: 0;
+  }
+}
+@keyframes bs-notify-fadeOut {
+  0% {
+    opacity: 0.9;
+  }
+  100% {
+    opacity: 0;
+  }
+}
+select.bs-select-hidden,
+.bootstrap-select > select.bs-select-hidden,
+select.selectpicker {
+  display: none !important;
+}
+.bootstrap-select {
+  width: 220px \0;
+  /*IE9 and below*/
+  vertical-align: middle;
+}
+.bootstrap-select > .dropdown-toggle {
+  position: relative;
+  width: 100%;
+  text-align: right;
+  white-space: nowrap;
+  display: -webkit-inline-box;
+  display: -webkit-inline-flex;
+  display: -ms-inline-flexbox;
+  display: inline-flex;
+  -webkit-box-align: center;
+  -webkit-align-items: center;
+      -ms-flex-align: center;
+          align-items: center;
+  -webkit-box-pack: justify;
+  -webkit-justify-content: space-between;
+      -ms-flex-pack: justify;
+          justify-content: space-between;
+}
+.bootstrap-select > .dropdown-toggle:after {
+  margin-top: -1px;
+}
+.bootstrap-select > .dropdown-toggle.bs-placeholder,
+.bootstrap-select > .dropdown-toggle.bs-placeholder:hover,
+.bootstrap-select > .dropdown-toggle.bs-placeholder:focus,
+.bootstrap-select > .dropdown-toggle.bs-placeholder:active {
+  color: #999;
+}
+.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-primary,
+.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-secondary,
+.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-success,
+.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-danger,
+.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-info,
+.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-dark,
+.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-primary:hover,
+.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-secondary:hover,
+.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-success:hover,
+.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-danger:hover,
+.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-info:hover,
+.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-dark:hover,
+.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-primary:focus,
+.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-secondary:focus,
+.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-success:focus,
+.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-danger:focus,
+.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-info:focus,
+.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-dark:focus,
+.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-primary:active,
+.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-secondary:active,
+.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-success:active,
+.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-danger:active,
+.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-info:active,
+.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-dark:active {
+  color: rgba(255, 255, 255, 0.5);
+}
+.bootstrap-select > select {
+  position: absolute !important;
+  bottom: 0;
+  left: 50%;
+  display: block !important;
+  width: 0.5px !important;
+  height: 100% !important;
+  padding: 0 !important;
+  opacity: 0 !important;
+  border: none;
+  z-index: 0 !important;
+}
+.bootstrap-select > select.mobile-device {
+  top: 0;
+  left: 0;
+  display: block !important;
+  width: 100% !important;
+  z-index: 2 !important;
+}
+.has-error .bootstrap-select .dropdown-toggle,
+.error .bootstrap-select .dropdown-toggle,
+.bootstrap-select.is-invalid .dropdown-toggle,
+.was-validated .bootstrap-select select:invalid + .dropdown-toggle {
+  border-color: #b94a48;
+}
+.bootstrap-select.is-valid .dropdown-toggle,
+.was-validated .bootstrap-select select:valid + .dropdown-toggle {
+  border-color: #28a745;
+}
+.bootstrap-select.fit-width {
+  width: auto !important;
+}
+.bootstrap-select:not([class*="col-"]):not([class*="form-control"]):not(.input-group-btn) {
+  width: 220px;
+}
+.bootstrap-select > select.mobile-device:focus + .dropdown-toggle,
+.bootstrap-select .dropdown-toggle:focus {
+  outline: thin dotted #333333 !important;
+  outline: 5px auto -webkit-focus-ring-color !important;
+  outline-offset: -2px;
+}
+.bootstrap-select.form-control {
+  margin-bottom: 0;
+  padding: 0;
+  border: none;
+  height: auto;
+}
+:not(.input-group) > .bootstrap-select.form-control:not([class*="col-"]) {
+  width: 100%;
+}
+.bootstrap-select.form-control.input-group-btn {
+  float: none;
+  z-index: auto;
+}
+.form-inline .bootstrap-select,
+.form-inline .bootstrap-select.form-control:not([class*="col-"]) {
+  width: auto;
+}
+.bootstrap-select:not(.input-group-btn),
+.bootstrap-select[class*="col-"] {
+  float: none;
+  display: inline-block;
+  margin-left: 0;
+}
+.bootstrap-select.dropdown-menu-right,
+.bootstrap-select[class*="col-"].dropdown-menu-right,
+.row .bootstrap-select[class*="col-"].dropdown-menu-right {
+  float: right;
+}
+.form-inline .bootstrap-select,
+.form-horizontal .bootstrap-select,
+.form-group .bootstrap-select {
+  margin-bottom: 0;
+}
+.form-group-lg .bootstrap-select.form-control,
+.form-group-sm .bootstrap-select.form-control {
+  padding: 0;
+}
+.form-group-lg .bootstrap-select.form-control .dropdown-toggle,
+.form-group-sm .bootstrap-select.form-control .dropdown-toggle {
+  height: 100%;
+  font-size: inherit;
+  line-height: inherit;
+  border-radius: inherit;
+}
+.bootstrap-select.form-control-sm .dropdown-toggle,
+.bootstrap-select.form-control-lg .dropdown-toggle {
+  font-size: inherit;
+  line-height: inherit;
+  border-radius: inherit;
+}
+.bootstrap-select.form-control-sm .dropdown-toggle {
+  padding: 0.25rem 0.5rem;
+}
+.bootstrap-select.form-control-lg .dropdown-toggle {
+  padding: 0.5rem 1rem;
+}
+.form-inline .bootstrap-select .form-control {
+  width: 100%;
+}
+.bootstrap-select.disabled,
+.bootstrap-select > .disabled {
+  cursor: not-allowed;
+}
+.bootstrap-select.disabled:focus,
+.bootstrap-select > .disabled:focus {
+  outline: none !important;
+}
+.bootstrap-select.bs-container {
+  position: absolute;
+  top: 0;
+  left: 0;
+  height: 0 !important;
+  padding: 0 !important;
+}
+.bootstrap-select.bs-container .dropdown-menu {
+  z-index: 1060;
+}
+.bootstrap-select .dropdown-toggle .filter-option {
+  position: static;
+  top: 0;
+  left: 0;
+  float: left;
+  height: 100%;
+  width: 100%;
+  text-align: left;
+  overflow: hidden;
+  -webkit-box-flex: 0;
+  -webkit-flex: 0 1 auto;
+      -ms-flex: 0 1 auto;
+          flex: 0 1 auto;
+}
+.bs3.bootstrap-select .dropdown-toggle .filter-option {
+  padding-right: inherit;
+}
+.input-group .bs3-has-addon.bootstrap-select .dropdown-toggle .filter-option {
+  position: absolute;
+  padding-top: inherit;
+  padding-bottom: inherit;
+  padding-left: inherit;
+  float: none;
+}
+.input-group .bs3-has-addon.bootstrap-select .dropdown-toggle .filter-option .filter-option-inner {
+  padding-right: inherit;
+}
+.bootstrap-select .dropdown-toggle .filter-option-inner-inner {
+  overflow: hidden;
+}
+.bootstrap-select .dropdown-toggle .filter-expand {
+  width: 0 !important;
+  float: left;
+  opacity: 0 !important;
+  overflow: hidden;
+}
+.bootstrap-select .dropdown-toggle .caret {
+  position: absolute;
+  top: 50%;
+  right: 12px;
+  margin-top: -2px;
+  vertical-align: middle;
+}
+.input-group .bootstrap-select.form-control .dropdown-toggle {
+  border-radius: inherit;
+}
+.bootstrap-select[class*="col-"] .dropdown-toggle {
+  width: 100%;
+}
+.bootstrap-select .dropdown-menu {
+  min-width: 100%;
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+}
+.bootstrap-select .dropdown-menu > .inner:focus {
+  outline: none !important;
+}
+.bootstrap-select .dropdown-menu.inner {
+  position: static;
+  float: none;
+  border: 0;
+  padding: 0;
+  margin: 0;
+  border-radius: 0;
+  -webkit-box-shadow: none;
+          box-shadow: none;
+}
+.bootstrap-select .dropdown-menu li {
+  position: relative;
+}
+.bootstrap-select .dropdown-menu li.active small {
+  color: rgba(255, 255, 255, 0.5) !important;
+}
+.bootstrap-select .dropdown-menu li.disabled a {
+  cursor: not-allowed;
+}
+.bootstrap-select .dropdown-menu li a {
+  cursor: pointer;
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+}
+.bootstrap-select .dropdown-menu li a.opt {
+  position: relative;
+  padding-left: 2.25em;
+}
+.bootstrap-select .dropdown-menu li a span.check-mark {
+  display: none;
+}
+.bootstrap-select .dropdown-menu li a span.text {
+  display: inline-block;
+}
+.bootstrap-select .dropdown-menu li small {
+  padding-left: 0.5em;
+}
+.bootstrap-select .dropdown-menu .notify {
+  position: absolute;
+  bottom: 5px;
+  width: 96%;
+  margin: 0 2%;
+  min-height: 26px;
+  padding: 3px 5px;
+  background: #f5f5f5;
+  border: 1px solid #e3e3e3;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
+  pointer-events: none;
+  opacity: 0.9;
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+}
+.bootstrap-select .dropdown-menu .notify.fadeOut {
+  -webkit-animation: 300ms linear 750ms forwards bs-notify-fadeOut;
+       -o-animation: 300ms linear 750ms forwards bs-notify-fadeOut;
+          animation: 300ms linear 750ms forwards bs-notify-fadeOut;
+}
+.bootstrap-select .no-results {
+  padding: 3px;
+  background: #f5f5f5;
+  margin: 0 5px;
+  white-space: nowrap;
+}
+.bootstrap-select.fit-width .dropdown-toggle .filter-option {
+  position: static;
+  display: inline;
+  padding: 0;
+}
+.bootstrap-select.fit-width .dropdown-toggle .filter-option-inner,
+.bootstrap-select.fit-width .dropdown-toggle .filter-option-inner-inner {
+  display: inline;
+}
+.bootstrap-select.fit-width .dropdown-toggle .bs-caret:before {
+  content: '\00a0';
+}
+.bootstrap-select.fit-width .dropdown-toggle .caret {
+  position: static;
+  top: auto;
+  margin-top: -1px;
+}
+.bootstrap-select.show-tick .dropdown-menu .selected span.check-mark {
+  position: absolute;
+  display: inline-block;
+  right: 15px;
+  top: 5px;
+}
+.bootstrap-select.show-tick .dropdown-menu li a span.text {
+  margin-right: 34px;
+}
+.bootstrap-select .bs-ok-default:after {
+  content: '';
+  display: block;
+  width: 0.5em;
+  height: 1em;
+  border-style: solid;
+  border-width: 0 0.26em 0.26em 0;
+  -webkit-transform-style: preserve-3d;
+          transform-style: preserve-3d;
+  -webkit-transform: rotate(45deg);
+      -ms-transform: rotate(45deg);
+       -o-transform: rotate(45deg);
+          transform: rotate(45deg);
+}
+.bootstrap-select.show-menu-arrow.open > .dropdown-toggle,
+.bootstrap-select.show-menu-arrow.show > .dropdown-toggle {
+  z-index: 1061;
+}
+.bootstrap-select.show-menu-arrow .dropdown-toggle .filter-option:before {
+  content: '';
+  border-left: 7px solid transparent;
+  border-right: 7px solid transparent;
+  border-bottom: 7px solid rgba(204, 204, 204, 0.2);
+  position: absolute;
+  bottom: -4px;
+  left: 9px;
+  display: none;
+}
+.bootstrap-select.show-menu-arrow .dropdown-toggle .filter-option:after {
+  content: '';
+  border-left: 6px solid transparent;
+  border-right: 6px solid transparent;
+  border-bottom: 6px solid white;
+  position: absolute;
+  bottom: -4px;
+  left: 10px;
+  display: none;
+}
+.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle .filter-option:before {
+  bottom: auto;
+  top: -4px;
+  border-top: 7px solid rgba(204, 204, 204, 0.2);
+  border-bottom: 0;
+}
+.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle .filter-option:after {
+  bottom: auto;
+  top: -4px;
+  border-top: 6px solid white;
+  border-bottom: 0;
+}
+.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle .filter-option:before {
+  right: 12px;
+  left: auto;
+}
+.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle .filter-option:after {
+  right: 13px;
+  left: auto;
+}
+.bootstrap-select.show-menu-arrow.open > .dropdown-toggle .filter-option:before,
+.bootstrap-select.show-menu-arrow.show > .dropdown-toggle .filter-option:before,
+.bootstrap-select.show-menu-arrow.open > .dropdown-toggle .filter-option:after,
+.bootstrap-select.show-menu-arrow.show > .dropdown-toggle .filter-option:after {
+  display: block;
+}
+.bs-searchbox,
+.bs-actionsbox,
+.bs-donebutton {
+  padding: 4px 8px;
+}
+.bs-actionsbox {
+  width: 100%;
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+}
+.bs-actionsbox .btn-group button {
+  width: 50%;
+}
+.bs-donebutton {
+  float: left;
+  width: 100%;
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+}
+.bs-donebutton .btn-group button {
+  width: 100%;
+}
+.bs-searchbox + .bs-actionsbox {
+  padding: 0 8px 4px;
+}
+.bs-searchbox .form-control {
+  margin-bottom: 0;
+  width: 100%;
+  float: none;
+}
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-select/bootstrap-select.js b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-select/bootstrap-select.js
new file mode 100644
index 0000000..d25d751
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-select/bootstrap-select.js
@@ -0,0 +1,3247 @@
+/*!
+ * Bootstrap-select v1.13.18 (https://developer.snapappointments.com/bootstrap-select)
+ *
+ * Copyright 2012-2020 SnapAppointments, LLC
+ * Licensed under MIT (https://github.com/snapappointments/bootstrap-select/blob/master/LICENSE)
+ */
+
+(function (root, factory) {
+  if (root === undefined && window !== undefined) root = window;
+  if (typeof define === 'function' && define.amd) {
+    // AMD. Register as an anonymous module unless amdModuleId is set
+    define(["jquery"], function (a0) {
+      return (factory(a0));
+    });
+  } else if (typeof module === 'object' && module.exports) {
+    // Node. Does not work with strict CommonJS, but
+    // only CommonJS-like environments that support module.exports,
+    // like Node.
+    module.exports = factory(require("jquery"));
+  } else {
+    factory(root["jQuery"]);
+  }
+}(this, function (jQuery) {
+
+(function ($) {
+  'use strict';
+
+  var DISALLOWED_ATTRIBUTES = ['sanitize', 'whiteList', 'sanitizeFn'];
+
+  var uriAttrs = [
+    'background',
+    'cite',
+    'href',
+    'itemtype',
+    'longdesc',
+    'poster',
+    'src',
+    'xlink:href'
+  ];
+
+  var ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i;
+
+  var DefaultWhitelist = {
+    // Global attributes allowed on any supplied element below.
+    '*': ['class', 'dir', 'id', 'lang', 'role', 'tabindex', 'style', ARIA_ATTRIBUTE_PATTERN],
+    a: ['target', 'href', 'title', 'rel'],
+    area: [],
+    b: [],
+    br: [],
+    col: [],
+    code: [],
+    div: [],
+    em: [],
+    hr: [],
+    h1: [],
+    h2: [],
+    h3: [],
+    h4: [],
+    h5: [],
+    h6: [],
+    i: [],
+    img: ['src', 'alt', 'title', 'width', 'height'],
+    li: [],
+    ol: [],
+    p: [],
+    pre: [],
+    s: [],
+    small: [],
+    span: [],
+    sub: [],
+    sup: [],
+    strong: [],
+    u: [],
+    ul: []
+  }
+
+  /**
+   * A pattern that recognizes a commonly useful subset of URLs that are safe.
+   *
+   * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts
+   */
+  var SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^&:/?#]*(?:[/?#]|$))/gi;
+
+  /**
+   * A pattern that matches safe data URLs. Only matches image, video and audio types.
+   *
+   * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts
+   */
+  var DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[a-z0-9+/]+=*$/i;
+
+  function allowedAttribute (attr, allowedAttributeList) {
+    var attrName = attr.nodeName.toLowerCase()
+
+    if ($.inArray(attrName, allowedAttributeList) !== -1) {
+      if ($.inArray(attrName, uriAttrs) !== -1) {
+        return Boolean(attr.nodeValue.match(SAFE_URL_PATTERN) || attr.nodeValue.match(DATA_URL_PATTERN))
+      }
+
+      return true
+    }
+
+    var regExp = $(allowedAttributeList).filter(function (index, value) {
+      return value instanceof RegExp
+    })
+
+    // Check if a regular expression validates the attribute.
+    for (var i = 0, l = regExp.length; i < l; i++) {
+      if (attrName.match(regExp[i])) {
+        return true
+      }
+    }
+
+    return false
+  }
+
+  function sanitizeHtml (unsafeElements, whiteList, sanitizeFn) {
+    if (sanitizeFn && typeof sanitizeFn === 'function') {
+      return sanitizeFn(unsafeElements);
+    }
+
+    var whitelistKeys = Object.keys(whiteList);
+
+    for (var i = 0, len = unsafeElements.length; i < len; i++) {
+      var elements = unsafeElements[i].querySelectorAll('*');
+
+      for (var j = 0, len2 = elements.length; j < len2; j++) {
+        var el = elements[j];
+        var elName = el.nodeName.toLowerCase();
+
+        if (whitelistKeys.indexOf(elName) === -1) {
+          el.parentNode.removeChild(el);
+
+          continue;
+        }
+
+        var attributeList = [].slice.call(el.attributes);
+        var whitelistedAttributes = [].concat(whiteList['*'] || [], whiteList[elName] || []);
+
+        for (var k = 0, len3 = attributeList.length; k < len3; k++) {
+          var attr = attributeList[k];
+
+          if (!allowedAttribute(attr, whitelistedAttributes)) {
+            el.removeAttribute(attr.nodeName);
+          }
+        }
+      }
+    }
+  }
+
+  // Polyfill for browsers with no classList support
+  // Remove in v2
+  if (!('classList' in document.createElement('_'))) {
+    (function (view) {
+      if (!('Element' in view)) return;
+
+      var classListProp = 'classList',
+          protoProp = 'prototype',
+          elemCtrProto = view.Element[protoProp],
+          objCtr = Object,
+          classListGetter = function () {
+            var $elem = $(this);
+
+            return {
+              add: function (classes) {
+                classes = Array.prototype.slice.call(arguments).join(' ');
+                return $elem.addClass(classes);
+              },
+              remove: function (classes) {
+                classes = Array.prototype.slice.call(arguments).join(' ');
+                return $elem.removeClass(classes);
+              },
+              toggle: function (classes, force) {
+                return $elem.toggleClass(classes, force);
+              },
+              contains: function (classes) {
+                return $elem.hasClass(classes);
+              }
+            }
+          };
+
+      if (objCtr.defineProperty) {
+        var classListPropDesc = {
+          get: classListGetter,
+          enumerable: true,
+          configurable: true
+        };
+        try {
+          objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
+        } catch (ex) { // IE 8 doesn't support enumerable:true
+          // adding undefined to fight this issue https://github.com/eligrey/classList.js/issues/36
+          // modernie IE8-MSW7 machine has IE8 8.0.6001.18702 and is affected
+          if (ex.number === undefined || ex.number === -0x7FF5EC54) {
+            classListPropDesc.enumerable = false;
+            objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
+          }
+        }
+      } else if (objCtr[protoProp].__defineGetter__) {
+        elemCtrProto.__defineGetter__(classListProp, classListGetter);
+      }
+    }(window));
+  }
+
+  var testElement = document.createElement('_');
+
+  testElement.classList.add('c1', 'c2');
+
+  if (!testElement.classList.contains('c2')) {
+    var _add = DOMTokenList.prototype.add,
+        _remove = DOMTokenList.prototype.remove;
+
+    DOMTokenList.prototype.add = function () {
+      Array.prototype.forEach.call(arguments, _add.bind(this));
+    }
+
+    DOMTokenList.prototype.remove = function () {
+      Array.prototype.forEach.call(arguments, _remove.bind(this));
+    }
+  }
+
+  testElement.classList.toggle('c3', false);
+
+  // Polyfill for IE 10 and Firefox <24, where classList.toggle does not
+  // support the second argument.
+  if (testElement.classList.contains('c3')) {
+    var _toggle = DOMTokenList.prototype.toggle;
+
+    DOMTokenList.prototype.toggle = function (token, force) {
+      if (1 in arguments && !this.contains(token) === !force) {
+        return force;
+      } else {
+        return _toggle.call(this, token);
+      }
+    };
+  }
+
+  testElement = null;
+
+  // shallow array comparison
+  function isEqual (array1, array2) {
+    return array1.length === array2.length && array1.every(function (element, index) {
+      return element === array2[index];
+    });
+  };
+
+  // <editor-fold desc="Shims">
+  if (!String.prototype.startsWith) {
+    (function () {
+      'use strict'; // needed to support `apply`/`call` with `undefined`/`null`
+      var defineProperty = (function () {
+        // IE 8 only supports `Object.defineProperty` on DOM elements
+        try {
+          var object = {};
+          var $defineProperty = Object.defineProperty;
+          var result = $defineProperty(object, object, object) && $defineProperty;
+        } catch (error) {
+        }
+        return result;
+      }());
+      var toString = {}.toString;
+      var startsWith = function (search) {
+        if (this == null) {
+          throw new TypeError();
+        }
+        var string = String(this);
+        if (search && toString.call(search) == '[object RegExp]') {
+          throw new TypeError();
+        }
+        var stringLength = string.length;
+        var searchString = String(search);
+        var searchLength = searchString.length;
+        var position = arguments.length > 1 ? arguments[1] : undefined;
+        // `ToInteger`
+        var pos = position ? Number(position) : 0;
+        if (pos != pos) { // better `isNaN`
+          pos = 0;
+        }
+        var start = Math.min(Math.max(pos, 0), stringLength);
+        // Avoid the `indexOf` call if no match is possible
+        if (searchLength + start > stringLength) {
+          return false;
+        }
+        var index = -1;
+        while (++index < searchLength) {
+          if (string.charCodeAt(start + index) != searchString.charCodeAt(index)) {
+            return false;
+          }
+        }
+        return true;
+      };
+      if (defineProperty) {
+        defineProperty(String.prototype, 'startsWith', {
+          'value': startsWith,
+          'configurable': true,
+          'writable': true
+        });
+      } else {
+        String.prototype.startsWith = startsWith;
+      }
+    }());
+  }
+
+  if (!Object.keys) {
+    Object.keys = function (
+      o, // object
+      k, // key
+      r  // result array
+    ) {
+      // initialize object and result
+      r = [];
+      // iterate over object keys
+      for (k in o) {
+        // fill result array with non-prototypical keys
+        r.hasOwnProperty.call(o, k) && r.push(k);
+      }
+      // return result
+      return r;
+    };
+  }
+
+  if (HTMLSelectElement && !HTMLSelectElement.prototype.hasOwnProperty('selectedOptions')) {
+    Object.defineProperty(HTMLSelectElement.prototype, 'selectedOptions', {
+      get: function () {
+        return this.querySelectorAll(':checked');
+      }
+    });
+  }
+
+  function getSelectedOptions (select, ignoreDisabled) {
+    var selectedOptions = select.selectedOptions,
+        options = [],
+        opt;
+
+    if (ignoreDisabled) {
+      for (var i = 0, len = selectedOptions.length; i < len; i++) {
+        opt = selectedOptions[i];
+
+        if (!(opt.disabled || opt.parentNode.tagName === 'OPTGROUP' && opt.parentNode.disabled)) {
+          options.push(opt);
+        }
+      }
+
+      return options;
+    }
+
+    return selectedOptions;
+  }
+
+  // much faster than $.val()
+  function getSelectValues (select, selectedOptions) {
+    var value = [],
+        options = selectedOptions || select.selectedOptions,
+        opt;
+
+    for (var i = 0, len = options.length; i < len; i++) {
+      opt = options[i];
+
+      if (!(opt.disabled || opt.parentNode.tagName === 'OPTGROUP' && opt.parentNode.disabled)) {
+        value.push(opt.value);
+      }
+    }
+
+    if (!select.multiple) {
+      return !value.length ? null : value[0];
+    }
+
+    return value;
+  }
+
+  // set data-selected on select element if the value has been programmatically selected
+  // prior to initialization of bootstrap-select
+  // * consider removing or replacing an alternative method *
+  var valHooks = {
+    useDefault: false,
+    _set: $.valHooks.select.set
+  };
+
+  $.valHooks.select.set = function (elem, value) {
+    if (value && !valHooks.useDefault) $(elem).data('selected', true);
+
+    return valHooks._set.apply(this, arguments);
+  };
+
+  var changedArguments = null;
+
+  var EventIsSupported = (function () {
+    try {
+      new Event('change');
+      return true;
+    } catch (e) {
+      return false;
+    }
+  })();
+
+  $.fn.triggerNative = function (eventName) {
+    var el = this[0],
+        event;
+
+    if (el.dispatchEvent) { // for modern browsers & IE9+
+      if (EventIsSupported) {
+        // For modern browsers
+        event = new Event(eventName, {
+          bubbles: true
+        });
+      } else {
+        // For IE since it doesn't support Event constructor
+        event = document.createEvent('Event');
+        event.initEvent(eventName, true, false);
+      }
+
+      el.dispatchEvent(event);
+    } else if (el.fireEvent) { // for IE8
+      event = document.createEventObject();
+      event.eventType = eventName;
+      el.fireEvent('on' + eventName, event);
+    } else {
+      // fall back to jQuery.trigger
+      this.trigger(eventName);
+    }
+  };
+  // </editor-fold>
+
+  function stringSearch (li, searchString, method, normalize) {
+    var stringTypes = [
+          'display',
+          'subtext',
+          'tokens'
+        ],
+        searchSuccess = false;
+
+    for (var i = 0; i < stringTypes.length; i++) {
+      var stringType = stringTypes[i],
+          string = li[stringType];
+
+      if (string) {
+        string = string.toString();
+
+        // Strip HTML tags. This isn't perfect, but it's much faster than any other method
+        if (stringType === 'display') {
+          string = string.replace(/<[^>]+>/g, '');
+        }
+
+        if (normalize) string = normalizeToBase(string);
+        string = string.toUpperCase();
+
+        if (method === 'contains') {
+          searchSuccess = string.indexOf(searchString) >= 0;
+        } else {
+          searchSuccess = string.startsWith(searchString);
+        }
+
+        if (searchSuccess) break;
+      }
+    }
+
+    return searchSuccess;
+  }
+
+  function toInteger (value) {
+    return parseInt(value, 10) || 0;
+  }
+
+  // Borrowed from Lodash (_.deburr)
+  /** Used to map Latin Unicode letters to basic Latin letters. */
+  var deburredLetters = {
+    // Latin-1 Supplement block.
+    '\xc0': 'A',  '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A',
+    '\xe0': 'a',  '\xe1': 'a', '\xe2': 'a', '\xe3': 'a', '\xe4': 'a', '\xe5': 'a',
+    '\xc7': 'C',  '\xe7': 'c',
+    '\xd0': 'D',  '\xf0': 'd',
+    '\xc8': 'E',  '\xc9': 'E', '\xca': 'E', '\xcb': 'E',
+    '\xe8': 'e',  '\xe9': 'e', '\xea': 'e', '\xeb': 'e',
+    '\xcc': 'I',  '\xcd': 'I', '\xce': 'I', '\xcf': 'I',
+    '\xec': 'i',  '\xed': 'i', '\xee': 'i', '\xef': 'i',
+    '\xd1': 'N',  '\xf1': 'n',
+    '\xd2': 'O',  '\xd3': 'O', '\xd4': 'O', '\xd5': 'O', '\xd6': 'O', '\xd8': 'O',
+    '\xf2': 'o',  '\xf3': 'o', '\xf4': 'o', '\xf5': 'o', '\xf6': 'o', '\xf8': 'o',
+    '\xd9': 'U',  '\xda': 'U', '\xdb': 'U', '\xdc': 'U',
+    '\xf9': 'u',  '\xfa': 'u', '\xfb': 'u', '\xfc': 'u',
+    '\xdd': 'Y',  '\xfd': 'y', '\xff': 'y',
+    '\xc6': 'Ae', '\xe6': 'ae',
+    '\xde': 'Th', '\xfe': 'th',
+    '\xdf': 'ss',
+    // Latin Extended-A block.
+    '\u0100': 'A',  '\u0102': 'A', '\u0104': 'A',
+    '\u0101': 'a',  '\u0103': 'a', '\u0105': 'a',
+    '\u0106': 'C',  '\u0108': 'C', '\u010a': 'C', '\u010c': 'C',
+    '\u0107': 'c',  '\u0109': 'c', '\u010b': 'c', '\u010d': 'c',
+    '\u010e': 'D',  '\u0110': 'D', '\u010f': 'd', '\u0111': 'd',
+    '\u0112': 'E',  '\u0114': 'E', '\u0116': 'E', '\u0118': 'E', '\u011a': 'E',
+    '\u0113': 'e',  '\u0115': 'e', '\u0117': 'e', '\u0119': 'e', '\u011b': 'e',
+    '\u011c': 'G',  '\u011e': 'G', '\u0120': 'G', '\u0122': 'G',
+    '\u011d': 'g',  '\u011f': 'g', '\u0121': 'g', '\u0123': 'g',
+    '\u0124': 'H',  '\u0126': 'H', '\u0125': 'h', '\u0127': 'h',
+    '\u0128': 'I',  '\u012a': 'I', '\u012c': 'I', '\u012e': 'I', '\u0130': 'I',
+    '\u0129': 'i',  '\u012b': 'i', '\u012d': 'i', '\u012f': 'i', '\u0131': 'i',
+    '\u0134': 'J',  '\u0135': 'j',
+    '\u0136': 'K',  '\u0137': 'k', '\u0138': 'k',
+    '\u0139': 'L',  '\u013b': 'L', '\u013d': 'L', '\u013f': 'L', '\u0141': 'L',
+    '\u013a': 'l',  '\u013c': 'l', '\u013e': 'l', '\u0140': 'l', '\u0142': 'l',
+    '\u0143': 'N',  '\u0145': 'N', '\u0147': 'N', '\u014a': 'N',
+    '\u0144': 'n',  '\u0146': 'n', '\u0148': 'n', '\u014b': 'n',
+    '\u014c': 'O',  '\u014e': 'O', '\u0150': 'O',
+    '\u014d': 'o',  '\u014f': 'o', '\u0151': 'o',
+    '\u0154': 'R',  '\u0156': 'R', '\u0158': 'R',
+    '\u0155': 'r',  '\u0157': 'r', '\u0159': 'r',
+    '\u015a': 'S',  '\u015c': 'S', '\u015e': 'S', '\u0160': 'S',
+    '\u015b': 's',  '\u015d': 's', '\u015f': 's', '\u0161': 's',
+    '\u0162': 'T',  '\u0164': 'T', '\u0166': 'T',
+    '\u0163': 't',  '\u0165': 't', '\u0167': 't',
+    '\u0168': 'U',  '\u016a': 'U', '\u016c': 'U', '\u016e': 'U', '\u0170': 'U', '\u0172': 'U',
+    '\u0169': 'u',  '\u016b': 'u', '\u016d': 'u', '\u016f': 'u', '\u0171': 'u', '\u0173': 'u',
+    '\u0174': 'W',  '\u0175': 'w',
+    '\u0176': 'Y',  '\u0177': 'y', '\u0178': 'Y',
+    '\u0179': 'Z',  '\u017b': 'Z', '\u017d': 'Z',
+    '\u017a': 'z',  '\u017c': 'z', '\u017e': 'z',
+    '\u0132': 'IJ', '\u0133': 'ij',
+    '\u0152': 'Oe', '\u0153': 'oe',
+    '\u0149': "'n", '\u017f': 's'
+  };
+
+  /** Used to match Latin Unicode letters (excluding mathematical operators). */
+  var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g;
+
+  /** Used to compose unicode character classes. */
+  var rsComboMarksRange = '\\u0300-\\u036f',
+      reComboHalfMarksRange = '\\ufe20-\\ufe2f',
+      rsComboSymbolsRange = '\\u20d0-\\u20ff',
+      rsComboMarksExtendedRange = '\\u1ab0-\\u1aff',
+      rsComboMarksSupplementRange = '\\u1dc0-\\u1dff',
+      rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange + rsComboMarksExtendedRange + rsComboMarksSupplementRange;
+
+  /** Used to compose unicode capture groups. */
+  var rsCombo = '[' + rsComboRange + ']';
+
+  /**
+   * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and
+   * [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols).
+   */
+  var reComboMark = RegExp(rsCombo, 'g');
+
+  function deburrLetter (key) {
+    return deburredLetters[key];
+  };
+
+  function normalizeToBase (string) {
+    string = string.toString();
+    return string && string.replace(reLatin, deburrLetter).replace(reComboMark, '');
+  }
+
+  // List of HTML entities for escaping.
+  var escapeMap = {
+    '&': '&amp;',
+    '<': '&lt;',
+    '>': '&gt;',
+    '"': '&quot;',
+    "'": '&#x27;',
+    '`': '&#x60;'
+  };
+
+  // Functions for escaping and unescaping strings to/from HTML interpolation.
+  var createEscaper = function (map) {
+    var escaper = function (match) {
+      return map[match];
+    };
+    // Regexes for identifying a key that needs to be escaped.
+    var source = '(?:' + Object.keys(map).join('|') + ')';
+    var testRegexp = RegExp(source);
+    var replaceRegexp = RegExp(source, 'g');
+    return function (string) {
+      string = string == null ? '' : '' + string;
+      return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
+    };
+  };
+
+  var htmlEscape = createEscaper(escapeMap);
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var keyCodeMap = {
+    32: ' ',
+    48: '0',
+    49: '1',
+    50: '2',
+    51: '3',
+    52: '4',
+    53: '5',
+    54: '6',
+    55: '7',
+    56: '8',
+    57: '9',
+    59: ';',
+    65: 'A',
+    66: 'B',
+    67: 'C',
+    68: 'D',
+    69: 'E',
+    70: 'F',
+    71: 'G',
+    72: 'H',
+    73: 'I',
+    74: 'J',
+    75: 'K',
+    76: 'L',
+    77: 'M',
+    78: 'N',
+    79: 'O',
+    80: 'P',
+    81: 'Q',
+    82: 'R',
+    83: 'S',
+    84: 'T',
+    85: 'U',
+    86: 'V',
+    87: 'W',
+    88: 'X',
+    89: 'Y',
+    90: 'Z',
+    96: '0',
+    97: '1',
+    98: '2',
+    99: '3',
+    100: '4',
+    101: '5',
+    102: '6',
+    103: '7',
+    104: '8',
+    105: '9'
+  };
+
+  var keyCodes = {
+    ESCAPE: 27, // KeyboardEvent.which value for Escape (Esc) key
+    ENTER: 13, // KeyboardEvent.which value for Enter key
+    SPACE: 32, // KeyboardEvent.which value for space key
+    TAB: 9, // KeyboardEvent.which value for tab key
+    ARROW_UP: 38, // KeyboardEvent.which value for up arrow key
+    ARROW_DOWN: 40 // KeyboardEvent.which value for down arrow key
+  }
+
+  var version = {
+    success: false,
+    major: '3'
+  };
+
+  try {
+    version.full = ($.fn.dropdown.Constructor.VERSION || '').split(' ')[0].split('.');
+    version.major = version.full[0];
+    version.success = true;
+  } catch (err) {
+    // do nothing
+  }
+
+  var selectId = 0;
+
+  var EVENT_KEY = '.bs.select';
+
+  var classNames = {
+    DISABLED: 'disabled',
+    DIVIDER: 'divider',
+    SHOW: 'open',
+    DROPUP: 'dropup',
+    MENU: 'dropdown-menu',
+    MENURIGHT: 'dropdown-menu-right',
+    MENULEFT: 'dropdown-menu-left',
+    // to-do: replace with more advanced template/customization options
+    BUTTONCLASS: 'btn-default',
+    POPOVERHEADER: 'popover-title',
+    ICONBASE: 'glyphicon',
+    TICKICON: 'glyphicon-ok'
+  }
+
+  var Selector = {
+    MENU: '.' + classNames.MENU
+  }
+
+  var elementTemplates = {
+    div: document.createElement('div'),
+    span: document.createElement('span'),
+    i: document.createElement('i'),
+    subtext: document.createElement('small'),
+    a: document.createElement('a'),
+    li: document.createElement('li'),
+    whitespace: document.createTextNode('\u00A0'),
+    fragment: document.createDocumentFragment()
+  }
+
+  elementTemplates.noResults = elementTemplates.li.cloneNode(false);
+  elementTemplates.noResults.className = 'no-results';
+
+  elementTemplates.a.setAttribute('role', 'option');
+  elementTemplates.a.className = 'dropdown-item';
+
+  elementTemplates.subtext.className = 'text-muted';
+
+  elementTemplates.text = elementTemplates.span.cloneNode(false);
+  elementTemplates.text.className = 'text';
+
+  elementTemplates.checkMark = elementTemplates.span.cloneNode(false);
+
+  var REGEXP_ARROW = new RegExp(keyCodes.ARROW_UP + '|' + keyCodes.ARROW_DOWN);
+  var REGEXP_TAB_OR_ESCAPE = new RegExp('^' + keyCodes.TAB + '$|' + keyCodes.ESCAPE);
+
+  var generateOption = {
+    li: function (content, classes, optgroup) {
+      var li = elementTemplates.li.cloneNode(false);
+
+      if (content) {
+        if (content.nodeType === 1 || content.nodeType === 11) {
+          li.appendChild(content);
+        } else {
+          li.innerHTML = content;
+        }
+      }
+
+      if (typeof classes !== 'undefined' && classes !== '') li.className = classes;
+      if (typeof optgroup !== 'undefined' && optgroup !== null) li.classList.add('optgroup-' + optgroup);
+
+      return li;
+    },
+
+    a: function (text, classes, inline) {
+      var a = elementTemplates.a.cloneNode(true);
+
+      if (text) {
+        if (text.nodeType === 11) {
+          a.appendChild(text);
+        } else {
+          a.insertAdjacentHTML('beforeend', text);
+        }
+      }
+
+      if (typeof classes !== 'undefined' && classes !== '') a.classList.add.apply(a.classList, classes.split(/\s+/));
+      if (inline) a.setAttribute('style', inline);
+
+      return a;
+    },
+
+    text: function (options, useFragment) {
+      var textElement = elementTemplates.text.cloneNode(false),
+          subtextElement,
+          iconElement;
+
+      if (options.content) {
+        textElement.innerHTML = options.content;
+      } else {
+        textElement.textContent = options.text;
+
+        if (options.icon) {
+          var whitespace = elementTemplates.whitespace.cloneNode(false);
+
+          // need to use <i> for icons in the button to prevent a breaking change
+          // note: switch to span in next major release
+          iconElement = (useFragment === true ? elementTemplates.i : elementTemplates.span).cloneNode(false);
+          iconElement.className = this.options.iconBase + ' ' + options.icon;
+
+          elementTemplates.fragment.appendChild(iconElement);
+          elementTemplates.fragment.appendChild(whitespace);
+        }
+
+        if (options.subtext) {
+          subtextElement = elementTemplates.subtext.cloneNode(false);
+          subtextElement.textContent = options.subtext;
+          textElement.appendChild(subtextElement);
+        }
+      }
+
+      if (useFragment === true) {
+        while (textElement.childNodes.length > 0) {
+          elementTemplates.fragment.appendChild(textElement.childNodes[0]);
+        }
+      } else {
+        elementTemplates.fragment.appendChild(textElement);
+      }
+
+      return elementTemplates.fragment;
+    },
+
+    label: function (options) {
+      var textElement = elementTemplates.text.cloneNode(false),
+          subtextElement,
+          iconElement;
+
+      textElement.innerHTML = options.display;
+
+      if (options.icon) {
+        var whitespace = elementTemplates.whitespace.cloneNode(false);
+
+        iconElement = elementTemplates.span.cloneNode(false);
+        iconElement.className = this.options.iconBase + ' ' + options.icon;
+
+        elementTemplates.fragment.appendChild(iconElement);
+        elementTemplates.fragment.appendChild(whitespace);
+      }
+
+      if (options.subtext) {
+        subtextElement = elementTemplates.subtext.cloneNode(false);
+        subtextElement.textContent = options.subtext;
+        textElement.appendChild(subtextElement);
+      }
+
+      elementTemplates.fragment.appendChild(textElement);
+
+      return elementTemplates.fragment;
+    }
+  }
+
+  function showNoResults (searchMatch, searchValue) {
+    if (!searchMatch.length) {
+      elementTemplates.noResults.innerHTML = this.options.noneResultsText.replace('{0}', '"' + htmlEscape(searchValue) + '"');
+      this.$menuInner[0].firstChild.appendChild(elementTemplates.noResults);
+    }
+  }
+
+  var Selectpicker = function (element, options) {
+    var that = this;
+
+    // bootstrap-select has been initialized - revert valHooks.select.set back to its original function
+    if (!valHooks.useDefault) {
+      $.valHooks.select.set = valHooks._set;
+      valHooks.useDefault = true;
+    }
+
+    this.$element = $(element);
+    this.$newElement = null;
+    this.$button = null;
+    this.$menu = null;
+    this.options = options;
+    this.selectpicker = {
+      main: {},
+      search: {},
+      current: {}, // current changes if a search is in progress
+      view: {},
+      isSearching: false,
+      keydown: {
+        keyHistory: '',
+        resetKeyHistory: {
+          start: function () {
+            return setTimeout(function () {
+              that.selectpicker.keydown.keyHistory = '';
+            }, 800);
+          }
+        }
+      }
+    };
+
+    this.sizeInfo = {};
+
+    // If we have no title yet, try to pull it from the html title attribute (jQuery doesnt' pick it up as it's not a
+    // data-attribute)
+    if (this.options.title === null) {
+      this.options.title = this.$element.attr('title');
+    }
+
+    // Format window padding
+    var winPad = this.options.windowPadding;
+    if (typeof winPad === 'number') {
+      this.options.windowPadding = [winPad, winPad, winPad, winPad];
+    }
+
+    // Expose public methods
+    this.val = Selectpicker.prototype.val;
+    this.render = Selectpicker.prototype.render;
+    this.refresh = Selectpicker.prototype.refresh;
+    this.setStyle = Selectpicker.prototype.setStyle;
+    this.selectAll = Selectpicker.prototype.selectAll;
+    this.deselectAll = Selectpicker.prototype.deselectAll;
+    this.destroy = Selectpicker.prototype.destroy;
+    this.remove = Selectpicker.prototype.remove;
+    this.show = Selectpicker.prototype.show;
+    this.hide = Selectpicker.prototype.hide;
+
+    this.init();
+  };
+
+  Selectpicker.VERSION = '1.13.18';
+
+  // part of this is duplicated in i18n/defaults-en_US.js. Make sure to update both.
+  Selectpicker.DEFAULTS = {
+    noneSelectedText: 'Nothing selected',
+    noneResultsText: 'No results matched {0}',
+    countSelectedText: function (numSelected, numTotal) {
+      return (numSelected == 1) ? '{0} item selected' : '{0} items selected';
+    },
+    maxOptionsText: function (numAll, numGroup) {
+      return [
+        (numAll == 1) ? 'Limit reached ({n} item max)' : 'Limit reached ({n} items max)',
+        (numGroup == 1) ? 'Group limit reached ({n} item max)' : 'Group limit reached ({n} items max)'
+      ];
+    },
+    selectAllText: 'Select All',
+    deselectAllText: 'Deselect All',
+    doneButton: false,
+    doneButtonText: 'Close',
+    multipleSeparator: ', ',
+    styleBase: 'btn',
+    style: classNames.BUTTONCLASS,
+    size: 'auto',
+    title: null,
+    selectedTextFormat: 'values',
+    width: false,
+    container: false,
+    hideDisabled: false,
+    showSubtext: false,
+    showIcon: true,
+    showContent: true,
+    dropupAuto: true,
+    header: false,
+    liveSearch: false,
+    liveSearchPlaceholder: null,
+    liveSearchNormalize: false,
+    liveSearchStyle: 'contains',
+    actionsBox: false,
+    iconBase: classNames.ICONBASE,
+    tickIcon: classNames.TICKICON,
+    showTick: false,
+    template: {
+      caret: '<span class="caret"></span>'
+    },
+    maxOptions: false,
+    mobile: false,
+    selectOnTab: false,
+    dropdownAlignRight: false,
+    windowPadding: 0,
+    virtualScroll: 600,
+    display: false,
+    sanitize: true,
+    sanitizeFn: null,
+    whiteList: DefaultWhitelist
+  };
+
+  Selectpicker.prototype = {
+
+    constructor: Selectpicker,
+
+    init: function () {
+      var that = this,
+          id = this.$element.attr('id'),
+          element = this.$element[0],
+          form = element.form;
+
+      selectId++;
+      this.selectId = 'bs-select-' + selectId;
+
+      element.classList.add('bs-select-hidden');
+
+      this.multiple = this.$element.prop('multiple');
+      this.autofocus = this.$element.prop('autofocus');
+
+      if (element.classList.contains('show-tick')) {
+        this.options.showTick = true;
+      }
+
+      this.$newElement = this.createDropdown();
+      this.buildData();
+      this.$element
+        .after(this.$newElement)
+        .prependTo(this.$newElement);
+
+      // ensure select is associated with form element if it got unlinked after moving it inside newElement
+      if (form && element.form === null) {
+        if (!form.id) form.id = 'form-' + this.selectId;
+        element.setAttribute('form', form.id);
+      }
+
+      this.$button = this.$newElement.children('button');
+      this.$menu = this.$newElement.children(Selector.MENU);
+      this.$menuInner = this.$menu.children('.inner');
+      this.$searchbox = this.$menu.find('input');
+
+      element.classList.remove('bs-select-hidden');
+
+      if (this.options.dropdownAlignRight === true) this.$menu[0].classList.add(classNames.MENURIGHT);
+
+      if (typeof id !== 'undefined') {
+        this.$button.attr('data-id', id);
+      }
+
+      this.checkDisabled();
+      this.clickListener();
+
+      if (this.options.liveSearch) {
+        this.liveSearchListener();
+        this.focusedParent = this.$searchbox[0];
+      } else {
+        this.focusedParent = this.$menuInner[0];
+      }
+
+      this.setStyle();
+      this.render();
+      this.setWidth();
+      if (this.options.container) {
+        this.selectPosition();
+      } else {
+        this.$element.on('hide' + EVENT_KEY, function () {
+          if (that.isVirtual()) {
+            // empty menu on close
+            var menuInner = that.$menuInner[0],
+                emptyMenu = menuInner.firstChild.cloneNode(false);
+
+            // replace the existing UL with an empty one - this is faster than $.empty() or innerHTML = ''
+            menuInner.replaceChild(emptyMenu, menuInner.firstChild);
+            menuInner.scrollTop = 0;
+          }
+        });
+      }
+      this.$menu.data('this', this);
+      this.$newElement.data('this', this);
+      if (this.options.mobile) this.mobile();
+
+      this.$newElement.on({
+        'hide.bs.dropdown': function (e) {
+          that.$element.trigger('hide' + EVENT_KEY, e);
+        },
+        'hidden.bs.dropdown': function (e) {
+          that.$element.trigger('hidden' + EVENT_KEY, e);
+        },
+        'show.bs.dropdown': function (e) {
+          that.$element.trigger('show' + EVENT_KEY, e);
+        },
+        'shown.bs.dropdown': function (e) {
+          that.$element.trigger('shown' + EVENT_KEY, e);
+        }
+      });
+
+      if (element.hasAttribute('required')) {
+        this.$element.on('invalid' + EVENT_KEY, function () {
+          that.$button[0].classList.add('bs-invalid');
+
+          that.$element
+            .on('shown' + EVENT_KEY + '.invalid', function () {
+              that.$element
+                .val(that.$element.val()) // set the value to hide the validation message in Chrome when menu is opened
+                .off('shown' + EVENT_KEY + '.invalid');
+            })
+            .on('rendered' + EVENT_KEY, function () {
+              // if select is no longer invalid, remove the bs-invalid class
+              if (this.validity.valid) that.$button[0].classList.remove('bs-invalid');
+              that.$element.off('rendered' + EVENT_KEY);
+            });
+
+          that.$button.on('blur' + EVENT_KEY, function () {
+            that.$element.trigger('focus').trigger('blur');
+            that.$button.off('blur' + EVENT_KEY);
+          });
+        });
+      }
+
+      setTimeout(function () {
+        that.buildList();
+        that.$element.trigger('loaded' + EVENT_KEY);
+      });
+    },
+
+    createDropdown: function () {
+      // Options
+      // If we are multiple or showTick option is set, then add the show-tick class
+      var showTick = (this.multiple || this.options.showTick) ? ' show-tick' : '',
+          multiselectable = this.multiple ? ' aria-multiselectable="true"' : '',
+          inputGroup = '',
+          autofocus = this.autofocus ? ' autofocus' : '';
+
+      if (version.major < 4 && this.$element.parent().hasClass('input-group')) {
+        inputGroup = ' input-group-btn';
+      }
+
+      // Elements
+      var drop,
+          header = '',
+          searchbox = '',
+          actionsbox = '',
+          donebutton = '';
+
+      if (this.options.header) {
+        header =
+          '<div class="' + classNames.POPOVERHEADER + '">' +
+            '<button type="button" class="close" aria-hidden="true">&times;</button>' +
+              this.options.header +
+          '</div>';
+      }
+
+      if (this.options.liveSearch) {
+        searchbox =
+          '<div class="bs-searchbox">' +
+            '<input type="search" class="form-control" autocomplete="off"' +
+              (
+                this.options.liveSearchPlaceholder === null ? ''
+                :
+                ' placeholder="' + htmlEscape(this.options.liveSearchPlaceholder) + '"'
+              ) +
+              ' role="combobox" aria-label="Search" aria-controls="' + this.selectId + '" aria-autocomplete="list">' +
+          '</div>';
+      }
+
+      if (this.multiple && this.options.actionsBox) {
+        actionsbox =
+          '<div class="bs-actionsbox">' +
+            '<div class="btn-group btn-group-sm btn-block">' +
+              '<button type="button" class="actions-btn bs-select-all btn ' + classNames.BUTTONCLASS + '">' +
+                this.options.selectAllText +
+              '</button>' +
+              '<button type="button" class="actions-btn bs-deselect-all btn ' + classNames.BUTTONCLASS + '">' +
+                this.options.deselectAllText +
+              '</button>' +
+            '</div>' +
+          '</div>';
+      }
+
+      if (this.multiple && this.options.doneButton) {
+        donebutton =
+          '<div class="bs-donebutton">' +
+            '<div class="btn-group btn-block">' +
+              '<button type="button" class="btn btn-sm ' + classNames.BUTTONCLASS + '">' +
+                this.options.doneButtonText +
+              '</button>' +
+            '</div>' +
+          '</div>';
+      }
+
+      drop =
+        '<div class="dropdown bootstrap-select' + showTick + inputGroup + '">' +
+          '<button type="button" tabindex="-1" class="' + this.options.styleBase + ' dropdown-toggle" ' + (this.options.display === 'static' ? 'data-display="static"' : '') + 'data-toggle="dropdown"' + autofocus + ' role="combobox" aria-owns="' + this.selectId + '" aria-haspopup="listbox" aria-expanded="false">' +
+            '<div class="filter-option">' +
+              '<div class="filter-option-inner">' +
+                '<div class="filter-option-inner-inner"></div>' +
+              '</div> ' +
+            '</div>' +
+            (
+              version.major === '4' ? ''
+              :
+              '<span class="bs-caret">' +
+                this.options.template.caret +
+              '</span>'
+            ) +
+          '</button>' +
+          '<div class="' + classNames.MENU + ' ' + (version.major === '4' ? '' : classNames.SHOW) + '">' +
+            header +
+            searchbox +
+            actionsbox +
+            '<div class="inner ' + classNames.SHOW + '" role="listbox" id="' + this.selectId + '" tabindex="-1" ' + multiselectable + '>' +
+                '<ul class="' + classNames.MENU + ' inner ' + (version.major === '4' ? classNames.SHOW : '') + '" role="presentation">' +
+                '</ul>' +
+            '</div>' +
+            donebutton +
+          '</div>' +
+        '</div>';
+
+      return $(drop);
+    },
+
+    setPositionData: function () {
+      this.selectpicker.view.canHighlight = [];
+      this.selectpicker.view.size = 0;
+      this.selectpicker.view.firstHighlightIndex = false;
+
+      for (var i = 0; i < this.selectpicker.current.data.length; i++) {
+        var li = this.selectpicker.current.data[i],
+            canHighlight = true;
+
+        if (li.type === 'divider') {
+          canHighlight = false;
+          li.height = this.sizeInfo.dividerHeight;
+        } else if (li.type === 'optgroup-label') {
+          canHighlight = false;
+          li.height = this.sizeInfo.dropdownHeaderHeight;
+        } else {
+          li.height = this.sizeInfo.liHeight;
+        }
+
+        if (li.disabled) canHighlight = false;
+
+        this.selectpicker.view.canHighlight.push(canHighlight);
+
+        if (canHighlight) {
+          this.selectpicker.view.size++;
+          li.posinset = this.selectpicker.view.size;
+          if (this.selectpicker.view.firstHighlightIndex === false) this.selectpicker.view.firstHighlightIndex = i;
+        }
+
+        li.position = (i === 0 ? 0 : this.selectpicker.current.data[i - 1].position) + li.height;
+      }
+    },
+
+    isVirtual: function () {
+      return (this.options.virtualScroll !== false) && (this.selectpicker.main.elements.length >= this.options.virtualScroll) || this.options.virtualScroll === true;
+    },
+
+    createView: function (isSearching, setSize, refresh) {
+      var that = this,
+          scrollTop = 0,
+          active = [],
+          selected,
+          prevActive;
+
+      this.selectpicker.isSearching = isSearching;
+      this.selectpicker.current = isSearching ? this.selectpicker.search : this.selectpicker.main;
+
+      this.setPositionData();
+
+      if (setSize) {
+        if (refresh) {
+          scrollTop = this.$menuInner[0].scrollTop;
+        } else if (!that.multiple) {
+          var element = that.$element[0],
+              selectedIndex = (element.options[element.selectedIndex] || {}).liIndex;
+
+          if (typeof selectedIndex === 'number' && that.options.size !== false) {
+            var selectedData = that.selectpicker.main.data[selectedIndex],
+                position = selectedData && selectedData.position;
+
+            if (position) {
+              scrollTop = position - ((that.sizeInfo.menuInnerHeight + that.sizeInfo.liHeight) / 2);
+            }
+          }
+        }
+      }
+
+      scroll(scrollTop, true);
+
+      this.$menuInner.off('scroll.createView').on('scroll.createView', function (e, updateValue) {
+        if (!that.noScroll) scroll(this.scrollTop, updateValue);
+        that.noScroll = false;
+      });
+
+      function scroll (scrollTop, init) {
+        var size = that.selectpicker.current.elements.length,
+            chunks = [],
+            chunkSize,
+            chunkCount,
+            firstChunk,
+            lastChunk,
+            currentChunk,
+            prevPositions,
+            positionIsDifferent,
+            previousElements,
+            menuIsDifferent = true,
+            isVirtual = that.isVirtual();
+
+        that.selectpicker.view.scrollTop = scrollTop;
+
+        chunkSize = Math.ceil(that.sizeInfo.menuInnerHeight / that.sizeInfo.liHeight * 1.5); // number of options in a chunk
+        chunkCount = Math.round(size / chunkSize) || 1; // number of chunks
+
+        for (var i = 0; i < chunkCount; i++) {
+          var endOfChunk = (i + 1) * chunkSize;
+
+          if (i === chunkCount - 1) {
+            endOfChunk = size;
+          }
+
+          chunks[i] = [
+            (i) * chunkSize + (!i ? 0 : 1),
+            endOfChunk
+          ];
+
+          if (!size) break;
+
+          if (currentChunk === undefined && scrollTop - 1 <= that.selectpicker.current.data[endOfChunk - 1].position - that.sizeInfo.menuInnerHeight) {
+            currentChunk = i;
+          }
+        }
+
+        if (currentChunk === undefined) currentChunk = 0;
+
+        prevPositions = [that.selectpicker.view.position0, that.selectpicker.view.position1];
+
+        // always display previous, current, and next chunks
+        firstChunk = Math.max(0, currentChunk - 1);
+        lastChunk = Math.min(chunkCount - 1, currentChunk + 1);
+
+        that.selectpicker.view.position0 = isVirtual === false ? 0 : (Math.max(0, chunks[firstChunk][0]) || 0);
+        that.selectpicker.view.position1 = isVirtual === false ? size : (Math.min(size, chunks[lastChunk][1]) || 0);
+
+        positionIsDifferent = prevPositions[0] !== that.selectpicker.view.position0 || prevPositions[1] !== that.selectpicker.view.position1;
+
+        if (that.activeIndex !== undefined) {
+          prevActive = that.selectpicker.main.elements[that.prevActiveIndex];
+          active = that.selectpicker.main.elements[that.activeIndex];
+          selected = that.selectpicker.main.elements[that.selectedIndex];
+
+          if (init) {
+            if (that.activeIndex !== that.selectedIndex) {
+              that.defocusItem(active);
+            }
+            that.activeIndex = undefined;
+          }
+
+          if (that.activeIndex && that.activeIndex !== that.selectedIndex) {
+            that.defocusItem(selected);
+          }
+        }
+
+        if (that.prevActiveIndex !== undefined && that.prevActiveIndex !== that.activeIndex && that.prevActiveIndex !== that.selectedIndex) {
+          that.defocusItem(prevActive);
+        }
+
+        if (init || positionIsDifferent) {
+          previousElements = that.selectpicker.view.visibleElements ? that.selectpicker.view.visibleElements.slice() : [];
+
+          if (isVirtual === false) {
+            that.selectpicker.view.visibleElements = that.selectpicker.current.elements;
+          } else {
+            that.selectpicker.view.visibleElements = that.selectpicker.current.elements.slice(that.selectpicker.view.position0, that.selectpicker.view.position1);
+          }
+
+          that.setOptionStatus();
+
+          // if searching, check to make sure the list has actually been updated before updating DOM
+          // this prevents unnecessary repaints
+          if (isSearching || (isVirtual === false && init)) menuIsDifferent = !isEqual(previousElements, that.selectpicker.view.visibleElements);
+
+          // if virtual scroll is disabled and not searching,
+          // menu should never need to be updated more than once
+          if ((init || isVirtual === true) && menuIsDifferent) {
+            var menuInner = that.$menuInner[0],
+                menuFragment = document.createDocumentFragment(),
+                emptyMenu = menuInner.firstChild.cloneNode(false),
+                marginTop,
+                marginBottom,
+                elements = that.selectpicker.view.visibleElements,
+                toSanitize = [];
+
+            // replace the existing UL with an empty one - this is faster than $.empty()
+            menuInner.replaceChild(emptyMenu, menuInner.firstChild);
+
+            for (var i = 0, visibleElementsLen = elements.length; i < visibleElementsLen; i++) {
+              var element = elements[i],
+                  elText,
+                  elementData;
+
+              if (that.options.sanitize) {
+                elText = element.lastChild;
+
+                if (elText) {
+                  elementData = that.selectpicker.current.data[i + that.selectpicker.view.position0];
+
+                  if (elementData && elementData.content && !elementData.sanitized) {
+                    toSanitize.push(elText);
+                    elementData.sanitized = true;
+                  }
+                }
+              }
+
+              menuFragment.appendChild(element);
+            }
+
+            if (that.options.sanitize && toSanitize.length) {
+              sanitizeHtml(toSanitize, that.options.whiteList, that.options.sanitizeFn);
+            }
+
+            if (isVirtual === true) {
+              marginTop = (that.selectpicker.view.position0 === 0 ? 0 : that.selectpicker.current.data[that.selectpicker.view.position0 - 1].position);
+              marginBottom = (that.selectpicker.view.position1 > size - 1 ? 0 : that.selectpicker.current.data[size - 1].position - that.selectpicker.current.data[that.selectpicker.view.position1 - 1].position);
+
+              menuInner.firstChild.style.marginTop = marginTop + 'px';
+              menuInner.firstChild.style.marginBottom = marginBottom + 'px';
+            } else {
+              menuInner.firstChild.style.marginTop = 0;
+              menuInner.firstChild.style.marginBottom = 0;
+            }
+
+            menuInner.firstChild.appendChild(menuFragment);
+
+            // if an option is encountered that is wider than the current menu width, update the menu width accordingly
+            // switch to ResizeObserver with increased browser support
+            if (isVirtual === true && that.sizeInfo.hasScrollBar) {
+              var menuInnerInnerWidth = menuInner.firstChild.offsetWidth;
+
+              if (init && menuInnerInnerWidth < that.sizeInfo.menuInnerInnerWidth && that.sizeInfo.totalMenuWidth > that.sizeInfo.selectWidth) {
+                menuInner.firstChild.style.minWidth = that.sizeInfo.menuInnerInnerWidth + 'px';
+              } else if (menuInnerInnerWidth > that.sizeInfo.menuInnerInnerWidth) {
+                // set to 0 to get actual width of menu
+                that.$menu[0].style.minWidth = 0;
+
+                var actualMenuWidth = menuInner.firstChild.offsetWidth;
+
+                if (actualMenuWidth > that.sizeInfo.menuInnerInnerWidth) {
+                  that.sizeInfo.menuInnerInnerWidth = actualMenuWidth;
+                  menuInner.firstChild.style.minWidth = that.sizeInfo.menuInnerInnerWidth + 'px';
+                }
+
+                // reset to default CSS styling
+                that.$menu[0].style.minWidth = '';
+              }
+            }
+          }
+        }
+
+        that.prevActiveIndex = that.activeIndex;
+
+        if (!that.options.liveSearch) {
+          that.$menuInner.trigger('focus');
+        } else if (isSearching && init) {
+          var index = 0,
+              newActive;
+
+          if (!that.selectpicker.view.canHighlight[index]) {
+            index = 1 + that.selectpicker.view.canHighlight.slice(1).indexOf(true);
+          }
+
+          newActive = that.selectpicker.view.visibleElements[index];
+
+          that.defocusItem(that.selectpicker.view.currentActive);
+
+          that.activeIndex = (that.selectpicker.current.data[index] || {}).index;
+
+          that.focusItem(newActive);
+        }
+      }
+
+      $(window)
+        .off('resize' + EVENT_KEY + '.' + this.selectId + '.createView')
+        .on('resize' + EVENT_KEY + '.' + this.selectId + '.createView', function () {
+          var isActive = that.$newElement.hasClass(classNames.SHOW);
+
+          if (isActive) scroll(that.$menuInner[0].scrollTop);
+        });
+    },
+
+    focusItem: function (li, liData, noStyle) {
+      if (li) {
+        liData = liData || this.selectpicker.main.data[this.activeIndex];
+        var a = li.firstChild;
+
+        if (a) {
+          a.setAttribute('aria-setsize', this.selectpicker.view.size);
+          a.setAttribute('aria-posinset', liData.posinset);
+
+          if (noStyle !== true) {
+            this.focusedParent.setAttribute('aria-activedescendant', a.id);
+            li.classList.add('active');
+            a.classList.add('active');
+          }
+        }
+      }
+    },
+
+    defocusItem: function (li) {
+      if (li) {
+        li.classList.remove('active');
+        if (li.firstChild) li.firstChild.classList.remove('active');
+      }
+    },
+
+    setPlaceholder: function () {
+      var that = this,
+          updateIndex = false;
+
+      if (this.options.title && !this.multiple) {
+        if (!this.selectpicker.view.titleOption) this.selectpicker.view.titleOption = document.createElement('option');
+
+        // this option doesn't create a new <li> element, but does add a new option at the start,
+        // so startIndex should increase to prevent having to check every option for the bs-title-option class
+        updateIndex = true;
+
+        var element = this.$element[0],
+            selectTitleOption = false,
+            titleNotAppended = !this.selectpicker.view.titleOption.parentNode,
+            selectedIndex = element.selectedIndex,
+            selectedOption = element.options[selectedIndex],
+            navigation = window.performance && window.performance.getEntriesByType('navigation'),
+            // Safari doesn't support getEntriesByType('navigation') - fall back to performance.navigation
+            isNotBackForward = (navigation && navigation.length) ? navigation[0].type !== 'back_forward' : window.performance.navigation.type !== 2;
+
+        if (titleNotAppended) {
+          // Use native JS to prepend option (faster)
+          this.selectpicker.view.titleOption.className = 'bs-title-option';
+          this.selectpicker.view.titleOption.value = '';
+
+          // Check if selected or data-selected attribute is already set on an option. If not, select the titleOption option.
+          // the selected item may have been changed by user or programmatically before the bootstrap select plugin runs,
+          // if so, the select will have the data-selected attribute
+          selectTitleOption = !selectedOption || (selectedIndex === 0 && selectedOption.defaultSelected === false && this.$element.data('selected') === undefined);
+        }
+
+        if (titleNotAppended || this.selectpicker.view.titleOption.index !== 0) {
+          element.insertBefore(this.selectpicker.view.titleOption, element.firstChild);
+        }
+
+        // Set selected *after* appending to select,
+        // otherwise the option doesn't get selected in IE
+        // set using selectedIndex, as setting the selected attr to true here doesn't work in IE11
+        if (selectTitleOption && isNotBackForward) {
+          element.selectedIndex = 0;
+        } else if (document.readyState !== 'complete') {
+          // if navigation type is back_forward, there's a chance the select will have its value set by BFCache
+          // wait for that value to be set, then run render again
+          window.addEventListener('pageshow', function () {
+            if (that.selectpicker.view.displayedValue !== element.value) that.render();
+          });
+        }
+      }
+
+      return updateIndex;
+    },
+
+    buildData: function () {
+      var optionSelector = ':not([hidden]):not([data-hidden="true"])',
+          mainData = [],
+          optID = 0,
+          startIndex = this.setPlaceholder() ? 1 : 0; // append the titleOption if necessary and skip the first option in the loop
+
+      if (this.options.hideDisabled) optionSelector += ':not(:disabled)';
+
+      var selectOptions = this.$element[0].querySelectorAll('select > *' + optionSelector);
+
+      function addDivider (config) {
+        var previousData = mainData[mainData.length - 1];
+
+        // ensure optgroup doesn't create back-to-back dividers
+        if (
+          previousData &&
+          previousData.type === 'divider' &&
+          (previousData.optID || config.optID)
+        ) {
+          return;
+        }
+
+        config = config || {};
+        config.type = 'divider';
+
+        mainData.push(config);
+      }
+
+      function addOption (option, config) {
+        config = config || {};
+
+        config.divider = option.getAttribute('data-divider') === 'true';
+
+        if (config.divider) {
+          addDivider({
+            optID: config.optID
+          });
+        } else {
+          var liIndex = mainData.length,
+              cssText = option.style.cssText,
+              inlineStyle = cssText ? htmlEscape(cssText) : '',
+              optionClass = (option.className || '') + (config.optgroupClass || '');
+
+          if (config.optID) optionClass = 'opt ' + optionClass;
+
+          config.optionClass = optionClass.trim();
+          config.inlineStyle = inlineStyle;
+          config.text = option.textContent;
+
+          config.content = option.getAttribute('data-content');
+          config.tokens = option.getAttribute('data-tokens');
+          config.subtext = option.getAttribute('data-subtext');
+          config.icon = option.getAttribute('data-icon');
+
+          option.liIndex = liIndex;
+
+          config.display = config.content || config.text;
+          config.type = 'option';
+          config.index = liIndex;
+          config.option = option;
+          config.selected = !!option.selected;
+          config.disabled = config.disabled || !!option.disabled;
+
+          mainData.push(config);
+        }
+      }
+
+      function addOptgroup (index, selectOptions) {
+        var optgroup = selectOptions[index],
+            // skip placeholder option
+            previous = index - 1 < startIndex ? false : selectOptions[index - 1],
+            next = selectOptions[index + 1],
+            options = optgroup.querySelectorAll('option' + optionSelector);
+
+        if (!options.length) return;
+
+        var config = {
+              display: htmlEscape(optgroup.label),
+              subtext: optgroup.getAttribute('data-subtext'),
+              icon: optgroup.getAttribute('data-icon'),
+              type: 'optgroup-label',
+              optgroupClass: ' ' + (optgroup.className || '')
+            },
+            headerIndex,
+            lastIndex;
+
+        optID++;
+
+        if (previous) {
+          addDivider({ optID: optID });
+        }
+
+        config.optID = optID;
+
+        mainData.push(config);
+
+        for (var j = 0, len = options.length; j < len; j++) {
+          var option = options[j];
+
+          if (j === 0) {
+            headerIndex = mainData.length - 1;
+            lastIndex = headerIndex + len;
+          }
+
+          addOption(option, {
+            headerIndex: headerIndex,
+            lastIndex: lastIndex,
+            optID: config.optID,
+            optgroupClass: config.optgroupClass,
+            disabled: optgroup.disabled
+          });
+        }
+
+        if (next) {
+          addDivider({ optID: optID });
+        }
+      }
+
+      for (var len = selectOptions.length, i = startIndex; i < len; i++) {
+        var item = selectOptions[i];
+
+        if (item.tagName !== 'OPTGROUP') {
+          addOption(item, {});
+        } else {
+          addOptgroup(i, selectOptions);
+        }
+      }
+
+      this.selectpicker.main.data = this.selectpicker.current.data = mainData;
+    },
+
+    buildList: function () {
+      var that = this,
+          selectData = this.selectpicker.main.data,
+          mainElements = [],
+          widestOptionLength = 0;
+
+      if ((that.options.showTick || that.multiple) && !elementTemplates.checkMark.parentNode) {
+        elementTemplates.checkMark.className = this.options.iconBase + ' ' + that.options.tickIcon + ' check-mark';
+        elementTemplates.a.appendChild(elementTemplates.checkMark);
+      }
+
+      function buildElement (item) {
+        var liElement,
+            combinedLength = 0;
+
+        switch (item.type) {
+          case 'divider':
+            liElement = generateOption.li(
+              false,
+              classNames.DIVIDER,
+              (item.optID ? item.optID + 'div' : undefined)
+            );
+
+            break;
+
+          case 'option':
+            liElement = generateOption.li(
+              generateOption.a(
+                generateOption.text.call(that, item),
+                item.optionClass,
+                item.inlineStyle
+              ),
+              '',
+              item.optID
+            );
+
+            if (liElement.firstChild) {
+              liElement.firstChild.id = that.selectId + '-' + item.index;
+            }
+
+            break;
+
+          case 'optgroup-label':
+            liElement = generateOption.li(
+              generateOption.label.call(that, item),
+              'dropdown-header' + item.optgroupClass,
+              item.optID
+            );
+
+            break;
+        }
+
+        item.element = liElement;
+        mainElements.push(liElement);
+
+        // count the number of characters in the option - not perfect, but should work in most cases
+        if (item.display) combinedLength += item.display.length;
+        if (item.subtext) combinedLength += item.subtext.length;
+        // if there is an icon, ensure this option's width is checked
+        if (item.icon) combinedLength += 1;
+
+        if (combinedLength > widestOptionLength) {
+          widestOptionLength = combinedLength;
+
+          // guess which option is the widest
+          // use this when calculating menu width
+          // not perfect, but it's fast, and the width will be updating accordingly when scrolling
+          that.selectpicker.view.widestOption = mainElements[mainElements.length - 1];
+        }
+      }
+
+      for (var len = selectData.length, i = 0; i < len; i++) {
+        var item = selectData[i];
+
+        buildElement(item);
+      }
+
+      this.selectpicker.main.elements = this.selectpicker.current.elements = mainElements;
+    },
+
+    findLis: function () {
+      return this.$menuInner.find('.inner > li');
+    },
+
+    render: function () {
+      var that = this,
+          element = this.$element[0],
+          // ensure titleOption is appended and selected (if necessary) before getting selectedOptions
+          placeholderSelected = this.setPlaceholder() && element.selectedIndex === 0,
+          selectedOptions = getSelectedOptions(element, this.options.hideDisabled),
+          selectedCount = selectedOptions.length,
+          button = this.$button[0],
+          buttonInner = button.querySelector('.filter-option-inner-inner'),
+          multipleSeparator = document.createTextNode(this.options.multipleSeparator),
+          titleFragment = elementTemplates.fragment.cloneNode(false),
+          showCount,
+          countMax,
+          hasContent = false;
+
+      button.classList.toggle('bs-placeholder', that.multiple ? !selectedCount : !getSelectValues(element, selectedOptions));
+
+      if (!that.multiple && selectedOptions.length === 1) {
+        that.selectpicker.view.displayedValue = getSelectValues(element, selectedOptions);
+      }
+
+      if (this.options.selectedTextFormat === 'static') {
+        titleFragment = generateOption.text.call(this, { text: this.options.title }, true);
+      } else {
+        showCount = this.multiple && this.options.selectedTextFormat.indexOf('count') !== -1 && selectedCount > 1;
+
+        // determine if the number of selected options will be shown (showCount === true)
+        if (showCount) {
+          countMax = this.options.selectedTextFormat.split('>');
+          showCount = (countMax.length > 1 && selectedCount > countMax[1]) || (countMax.length === 1 && selectedCount >= 2);
+        }
+
+        // only loop through all selected options if the count won't be shown
+        if (showCount === false) {
+          if (!placeholderSelected) {
+            for (var selectedIndex = 0; selectedIndex < selectedCount; selectedIndex++) {
+              if (selectedIndex < 50) {
+                var option = selectedOptions[selectedIndex],
+                    thisData = this.selectpicker.main.data[option.liIndex],
+                    titleOptions = {};
+
+                if (this.multiple && selectedIndex > 0) {
+                  titleFragment.appendChild(multipleSeparator.cloneNode(false));
+                }
+
+                if (option.title) {
+                  titleOptions.text = option.title;
+                } else if (thisData) {
+                  if (thisData.content && that.options.showContent) {
+                    titleOptions.content = thisData.content.toString();
+                    hasContent = true;
+                  } else {
+                    if (that.options.showIcon) {
+                      titleOptions.icon = thisData.icon;
+                    }
+                    if (that.options.showSubtext && !that.multiple && thisData.subtext) titleOptions.subtext = ' ' + thisData.subtext;
+                    titleOptions.text = option.textContent.trim();
+                  }
+                }
+
+                titleFragment.appendChild(generateOption.text.call(this, titleOptions, true));
+              } else {
+                break;
+              }
+            }
+
+            // add ellipsis
+            if (selectedCount > 49) {
+              titleFragment.appendChild(document.createTextNode('...'));
+            }
+          }
+        } else {
+          var optionSelector = ':not([hidden]):not([data-hidden="true"]):not([data-divider="true"])';
+          if (this.options.hideDisabled) optionSelector += ':not(:disabled)';
+
+          // If this is a multiselect, and selectedTextFormat is count, then show 1 of 2 selected, etc.
+          var totalCount = this.$element[0].querySelectorAll('select > option' + optionSelector + ', optgroup' + optionSelector + ' option' + optionSelector).length,
+              tr8nText = (typeof this.options.countSelectedText === 'function') ? this.options.countSelectedText(selectedCount, totalCount) : this.options.countSelectedText;
+
+          titleFragment = generateOption.text.call(this, {
+            text: tr8nText.replace('{0}', selectedCount.toString()).replace('{1}', totalCount.toString())
+          }, true);
+        }
+      }
+
+      if (this.options.title == undefined) {
+        // use .attr to ensure undefined is returned if title attribute is not set
+        this.options.title = this.$element.attr('title');
+      }
+
+      // If the select doesn't have a title, then use the default, or if nothing is set at all, use noneSelectedText
+      if (!titleFragment.childNodes.length) {
+        titleFragment = generateOption.text.call(this, {
+          text: typeof this.options.title !== 'undefined' ? this.options.title : this.options.noneSelectedText
+        }, true);
+      }
+
+      // strip all HTML tags and trim the result, then unescape any escaped tags
+      button.title = titleFragment.textContent.replace(/<[^>]*>?/g, '').trim();
+
+      if (this.options.sanitize && hasContent) {
+        sanitizeHtml([titleFragment], that.options.whiteList, that.options.sanitizeFn);
+      }
+
+      buttonInner.innerHTML = '';
+      buttonInner.appendChild(titleFragment);
+
+      if (version.major < 4 && this.$newElement[0].classList.contains('bs3-has-addon')) {
+        var filterExpand = button.querySelector('.filter-expand'),
+            clone = buttonInner.cloneNode(true);
+
+        clone.className = 'filter-expand';
+
+        if (filterExpand) {
+          button.replaceChild(clone, filterExpand);
+        } else {
+          button.appendChild(clone);
+        }
+      }
+
+      this.$element.trigger('rendered' + EVENT_KEY);
+    },
+
+    /**
+     * @param [style]
+     * @param [status]
+     */
+    setStyle: function (newStyle, status) {
+      var button = this.$button[0],
+          newElement = this.$newElement[0],
+          style = this.options.style.trim(),
+          buttonClass;
+
+      if (this.$element.attr('class')) {
+        this.$newElement.addClass(this.$element.attr('class').replace(/selectpicker|mobile-device|bs-select-hidden|validate\[.*\]/gi, ''));
+      }
+
+      if (version.major < 4) {
+        newElement.classList.add('bs3');
+
+        if (newElement.parentNode.classList && newElement.parentNode.classList.contains('input-group') &&
+            (newElement.previousElementSibling || newElement.nextElementSibling) &&
+            (newElement.previousElementSibling || newElement.nextElementSibling).classList.contains('input-group-addon')
+        ) {
+          newElement.classList.add('bs3-has-addon');
+        }
+      }
+
+      if (newStyle) {
+        buttonClass = newStyle.trim();
+      } else {
+        buttonClass = style;
+      }
+
+      if (status == 'add') {
+        if (buttonClass) button.classList.add.apply(button.classList, buttonClass.split(' '));
+      } else if (status == 'remove') {
+        if (buttonClass) button.classList.remove.apply(button.classList, buttonClass.split(' '));
+      } else {
+        if (style) button.classList.remove.apply(button.classList, style.split(' '));
+        if (buttonClass) button.classList.add.apply(button.classList, buttonClass.split(' '));
+      }
+    },
+
+    liHeight: function (refresh) {
+      if (!refresh && (this.options.size === false || Object.keys(this.sizeInfo).length)) return;
+
+      var newElement = elementTemplates.div.cloneNode(false),
+          menu = elementTemplates.div.cloneNode(false),
+          menuInner = elementTemplates.div.cloneNode(false),
+          menuInnerInner = document.createElement('ul'),
+          divider = elementTemplates.li.cloneNode(false),
+          dropdownHeader = elementTemplates.li.cloneNode(false),
+          li,
+          a = elementTemplates.a.cloneNode(false),
+          text = elementTemplates.span.cloneNode(false),
+          header = this.options.header && this.$menu.find('.' + classNames.POPOVERHEADER).length > 0 ? this.$menu.find('.' + classNames.POPOVERHEADER)[0].cloneNode(true) : null,
+          search = this.options.liveSearch ? elementTemplates.div.cloneNode(false) : null,
+          actions = this.options.actionsBox && this.multiple && this.$menu.find('.bs-actionsbox').length > 0 ? this.$menu.find('.bs-actionsbox')[0].cloneNode(true) : null,
+          doneButton = this.options.doneButton && this.multiple && this.$menu.find('.bs-donebutton').length > 0 ? this.$menu.find('.bs-donebutton')[0].cloneNode(true) : null,
+          firstOption = this.$element.find('option')[0];
+
+      this.sizeInfo.selectWidth = this.$newElement[0].offsetWidth;
+
+      text.className = 'text';
+      a.className = 'dropdown-item ' + (firstOption ? firstOption.className : '');
+      newElement.className = this.$menu[0].parentNode.className + ' ' + classNames.SHOW;
+      newElement.style.width = 0; // ensure button width doesn't affect natural width of menu when calculating
+      if (this.options.width === 'auto') menu.style.minWidth = 0;
+      menu.className = classNames.MENU + ' ' + classNames.SHOW;
+      menuInner.className = 'inner ' + classNames.SHOW;
+      menuInnerInner.className = classNames.MENU + ' inner ' + (version.major === '4' ? classNames.SHOW : '');
+      divider.className = classNames.DIVIDER;
+      dropdownHeader.className = 'dropdown-header';
+
+      text.appendChild(document.createTextNode('\u200b'));
+
+      if (this.selectpicker.current.data.length) {
+        for (var i = 0; i < this.selectpicker.current.data.length; i++) {
+          var data = this.selectpicker.current.data[i];
+          if (data.type === 'option') {
+            li = data.element;
+            break;
+          }
+        }
+      } else {
+        li = elementTemplates.li.cloneNode(false);
+        a.appendChild(text);
+        li.appendChild(a);
+      }
+
+      dropdownHeader.appendChild(text.cloneNode(true));
+
+      if (this.selectpicker.view.widestOption) {
+        menuInnerInner.appendChild(this.selectpicker.view.widestOption.cloneNode(true));
+      }
+
+      menuInnerInner.appendChild(li);
+      menuInnerInner.appendChild(divider);
+      menuInnerInner.appendChild(dropdownHeader);
+      if (header) menu.appendChild(header);
+      if (search) {
+        var input = document.createElement('input');
+        search.className = 'bs-searchbox';
+        input.className = 'form-control';
+        search.appendChild(input);
+        menu.appendChild(search);
+      }
+      if (actions) menu.appendChild(actions);
+      menuInner.appendChild(menuInnerInner);
+      menu.appendChild(menuInner);
+      if (doneButton) menu.appendChild(doneButton);
+      newElement.appendChild(menu);
+
+      document.body.appendChild(newElement);
+
+      var liHeight = li.offsetHeight,
+          dropdownHeaderHeight = dropdownHeader ? dropdownHeader.offsetHeight : 0,
+          headerHeight = header ? header.offsetHeight : 0,
+          searchHeight = search ? search.offsetHeight : 0,
+          actionsHeight = actions ? actions.offsetHeight : 0,
+          doneButtonHeight = doneButton ? doneButton.offsetHeight : 0,
+          dividerHeight = $(divider).outerHeight(true),
+          // fall back to jQuery if getComputedStyle is not supported
+          menuStyle = window.getComputedStyle ? window.getComputedStyle(menu) : false,
+          menuWidth = menu.offsetWidth,
+          $menu = menuStyle ? null : $(menu),
+          menuPadding = {
+            vert: toInteger(menuStyle ? menuStyle.paddingTop : $menu.css('paddingTop')) +
+                  toInteger(menuStyle ? menuStyle.paddingBottom : $menu.css('paddingBottom')) +
+                  toInteger(menuStyle ? menuStyle.borderTopWidth : $menu.css('borderTopWidth')) +
+                  toInteger(menuStyle ? menuStyle.borderBottomWidth : $menu.css('borderBottomWidth')),
+            horiz: toInteger(menuStyle ? menuStyle.paddingLeft : $menu.css('paddingLeft')) +
+                  toInteger(menuStyle ? menuStyle.paddingRight : $menu.css('paddingRight')) +
+                  toInteger(menuStyle ? menuStyle.borderLeftWidth : $menu.css('borderLeftWidth')) +
+                  toInteger(menuStyle ? menuStyle.borderRightWidth : $menu.css('borderRightWidth'))
+          },
+          menuExtras = {
+            vert: menuPadding.vert +
+                  toInteger(menuStyle ? menuStyle.marginTop : $menu.css('marginTop')) +
+                  toInteger(menuStyle ? menuStyle.marginBottom : $menu.css('marginBottom')) + 2,
+            horiz: menuPadding.horiz +
+                  toInteger(menuStyle ? menuStyle.marginLeft : $menu.css('marginLeft')) +
+                  toInteger(menuStyle ? menuStyle.marginRight : $menu.css('marginRight')) + 2
+          },
+          scrollBarWidth;
+
+      menuInner.style.overflowY = 'scroll';
+
+      scrollBarWidth = menu.offsetWidth - menuWidth;
+
+      document.body.removeChild(newElement);
+
+      this.sizeInfo.liHeight = liHeight;
+      this.sizeInfo.dropdownHeaderHeight = dropdownHeaderHeight;
+      this.sizeInfo.headerHeight = headerHeight;
+      this.sizeInfo.searchHeight = searchHeight;
+      this.sizeInfo.actionsHeight = actionsHeight;
+      this.sizeInfo.doneButtonHeight = doneButtonHeight;
+      this.sizeInfo.dividerHeight = dividerHeight;
+      this.sizeInfo.menuPadding = menuPadding;
+      this.sizeInfo.menuExtras = menuExtras;
+      this.sizeInfo.menuWidth = menuWidth;
+      this.sizeInfo.menuInnerInnerWidth = menuWidth - menuPadding.horiz;
+      this.sizeInfo.totalMenuWidth = this.sizeInfo.menuWidth;
+      this.sizeInfo.scrollBarWidth = scrollBarWidth;
+      this.sizeInfo.selectHeight = this.$newElement[0].offsetHeight;
+
+      this.setPositionData();
+    },
+
+    getSelectPosition: function () {
+      var that = this,
+          $window = $(window),
+          pos = that.$newElement.offset(),
+          $container = $(that.options.container),
+          containerPos;
+
+      if (that.options.container && $container.length && !$container.is('body')) {
+        containerPos = $container.offset();
+        containerPos.top += parseInt($container.css('borderTopWidth'));
+        containerPos.left += parseInt($container.css('borderLeftWidth'));
+      } else {
+        containerPos = { top: 0, left: 0 };
+      }
+
+      var winPad = that.options.windowPadding;
+
+      this.sizeInfo.selectOffsetTop = pos.top - containerPos.top - $window.scrollTop();
+      this.sizeInfo.selectOffsetBot = $window.height() - this.sizeInfo.selectOffsetTop - this.sizeInfo.selectHeight - containerPos.top - winPad[2];
+      this.sizeInfo.selectOffsetLeft = pos.left - containerPos.left - $window.scrollLeft();
+      this.sizeInfo.selectOffsetRight = $window.width() - this.sizeInfo.selectOffsetLeft - this.sizeInfo.selectWidth - containerPos.left - winPad[1];
+      this.sizeInfo.selectOffsetTop -= winPad[0];
+      this.sizeInfo.selectOffsetLeft -= winPad[3];
+    },
+
+    setMenuSize: function (isAuto) {
+      this.getSelectPosition();
+
+      var selectWidth = this.sizeInfo.selectWidth,
+          liHeight = this.sizeInfo.liHeight,
+          headerHeight = this.sizeInfo.headerHeight,
+          searchHeight = this.sizeInfo.searchHeight,
+          actionsHeight = this.sizeInfo.actionsHeight,
+          doneButtonHeight = this.sizeInfo.doneButtonHeight,
+          divHeight = this.sizeInfo.dividerHeight,
+          menuPadding = this.sizeInfo.menuPadding,
+          menuInnerHeight,
+          menuHeight,
+          divLength = 0,
+          minHeight,
+          _minHeight,
+          maxHeight,
+          menuInnerMinHeight,
+          estimate,
+          isDropup;
+
+      if (this.options.dropupAuto) {
+        // Get the estimated height of the menu without scrollbars.
+        // This is useful for smaller menus, where there might be plenty of room
+        // below the button without setting dropup, but we can't know
+        // the exact height of the menu until createView is called later
+        estimate = liHeight * this.selectpicker.current.elements.length + menuPadding.vert;
+
+        isDropup = this.sizeInfo.selectOffsetTop - this.sizeInfo.selectOffsetBot > this.sizeInfo.menuExtras.vert && estimate + this.sizeInfo.menuExtras.vert + 50 > this.sizeInfo.selectOffsetBot;
+
+        // ensure dropup doesn't change while searching (so menu doesn't bounce back and forth)
+        if (this.selectpicker.isSearching === true) {
+          isDropup = this.selectpicker.dropup;
+        }
+
+        this.$newElement.toggleClass(classNames.DROPUP, isDropup);
+        this.selectpicker.dropup = isDropup;
+      }
+
+      if (this.options.size === 'auto') {
+        _minHeight = this.selectpicker.current.elements.length > 3 ? this.sizeInfo.liHeight * 3 + this.sizeInfo.menuExtras.vert - 2 : 0;
+        menuHeight = this.sizeInfo.selectOffsetBot - this.sizeInfo.menuExtras.vert;
+        minHeight = _minHeight + headerHeight + searchHeight + actionsHeight + doneButtonHeight;
+        menuInnerMinHeight = Math.max(_minHeight - menuPadding.vert, 0);
+
+        if (this.$newElement.hasClass(classNames.DROPUP)) {
+          menuHeight = this.sizeInfo.selectOffsetTop - this.sizeInfo.menuExtras.vert;
+        }
+
+        maxHeight = menuHeight;
+        menuInnerHeight = menuHeight - headerHeight - searchHeight - actionsHeight - doneButtonHeight - menuPadding.vert;
+      } else if (this.options.size && this.options.size != 'auto' && this.selectpicker.current.elements.length > this.options.size) {
+        for (var i = 0; i < this.options.size; i++) {
+          if (this.selectpicker.current.data[i].type === 'divider') divLength++;
+        }
+
+        menuHeight = liHeight * this.options.size + divLength * divHeight + menuPadding.vert;
+        menuInnerHeight = menuHeight - menuPadding.vert;
+        maxHeight = menuHeight + headerHeight + searchHeight + actionsHeight + doneButtonHeight;
+        minHeight = menuInnerMinHeight = '';
+      }
+
+      this.$menu.css({
+        'max-height': maxHeight + 'px',
+        'overflow': 'hidden',
+        'min-height': minHeight + 'px'
+      });
+
+      this.$menuInner.css({
+        'max-height': menuInnerHeight + 'px',
+        'overflow-y': 'auto',
+        'min-height': menuInnerMinHeight + 'px'
+      });
+
+      // ensure menuInnerHeight is always a positive number to prevent issues calculating chunkSize in createView
+      this.sizeInfo.menuInnerHeight = Math.max(menuInnerHeight, 1);
+
+      if (this.selectpicker.current.data.length && this.selectpicker.current.data[this.selectpicker.current.data.length - 1].position > this.sizeInfo.menuInnerHeight) {
+        this.sizeInfo.hasScrollBar = true;
+        this.sizeInfo.totalMenuWidth = this.sizeInfo.menuWidth + this.sizeInfo.scrollBarWidth;
+      }
+
+      if (this.options.dropdownAlignRight === 'auto') {
+        this.$menu.toggleClass(classNames.MENURIGHT, this.sizeInfo.selectOffsetLeft > this.sizeInfo.selectOffsetRight && this.sizeInfo.selectOffsetRight < (this.sizeInfo.totalMenuWidth - selectWidth));
+      }
+
+      if (this.dropdown && this.dropdown._popper) this.dropdown._popper.update();
+    },
+
+    setSize: function (refresh) {
+      this.liHeight(refresh);
+
+      if (this.options.header) this.$menu.css('padding-top', 0);
+
+      if (this.options.size !== false) {
+        var that = this,
+            $window = $(window);
+
+        this.setMenuSize();
+
+        if (this.options.liveSearch) {
+          this.$searchbox
+            .off('input.setMenuSize propertychange.setMenuSize')
+            .on('input.setMenuSize propertychange.setMenuSize', function () {
+              return that.setMenuSize();
+            });
+        }
+
+        if (this.options.size === 'auto') {
+          $window
+            .off('resize' + EVENT_KEY + '.' + this.selectId + '.setMenuSize' + ' scroll' + EVENT_KEY + '.' + this.selectId + '.setMenuSize')
+            .on('resize' + EVENT_KEY + '.' + this.selectId + '.setMenuSize' + ' scroll' + EVENT_KEY + '.' + this.selectId + '.setMenuSize', function () {
+              return that.setMenuSize();
+            });
+        } else if (this.options.size && this.options.size != 'auto' && this.selectpicker.current.elements.length > this.options.size) {
+          $window.off('resize' + EVENT_KEY + '.' + this.selectId + '.setMenuSize' + ' scroll' + EVENT_KEY + '.' + this.selectId + '.setMenuSize');
+        }
+      }
+
+      this.createView(false, true, refresh);
+    },
+
+    setWidth: function () {
+      var that = this;
+
+      if (this.options.width === 'auto') {
+        requestAnimationFrame(function () {
+          that.$menu.css('min-width', '0');
+
+          that.$element.on('loaded' + EVENT_KEY, function () {
+            that.liHeight();
+            that.setMenuSize();
+
+            // Get correct width if element is hidden
+            var $selectClone = that.$newElement.clone().appendTo('body'),
+                btnWidth = $selectClone.css('width', 'auto').children('button').outerWidth();
+
+            $selectClone.remove();
+
+            // Set width to whatever's larger, button title or longest option
+            that.sizeInfo.selectWidth = Math.max(that.sizeInfo.totalMenuWidth, btnWidth);
+            that.$newElement.css('width', that.sizeInfo.selectWidth + 'px');
+          });
+        });
+      } else if (this.options.width === 'fit') {
+        // Remove inline min-width so width can be changed from 'auto'
+        this.$menu.css('min-width', '');
+        this.$newElement.css('width', '').addClass('fit-width');
+      } else if (this.options.width) {
+        // Remove inline min-width so width can be changed from 'auto'
+        this.$menu.css('min-width', '');
+        this.$newElement.css('width', this.options.width);
+      } else {
+        // Remove inline min-width/width so width can be changed
+        this.$menu.css('min-width', '');
+        this.$newElement.css('width', '');
+      }
+      // Remove fit-width class if width is changed programmatically
+      if (this.$newElement.hasClass('fit-width') && this.options.width !== 'fit') {
+        this.$newElement[0].classList.remove('fit-width');
+      }
+    },
+
+    selectPosition: function () {
+      this.$bsContainer = $('<div class="bs-container" />');
+
+      var that = this,
+          $container = $(this.options.container),
+          pos,
+          containerPos,
+          actualHeight,
+          getPlacement = function ($element) {
+            var containerPosition = {},
+                // fall back to dropdown's default display setting if display is not manually set
+                display = that.options.display || (
+                  // Bootstrap 3 doesn't have $.fn.dropdown.Constructor.Default
+                  $.fn.dropdown.Constructor.Default ? $.fn.dropdown.Constructor.Default.display
+                  : false
+                );
+
+            that.$bsContainer.addClass($element.attr('class').replace(/form-control|fit-width/gi, '')).toggleClass(classNames.DROPUP, $element.hasClass(classNames.DROPUP));
+            pos = $element.offset();
+
+            if (!$container.is('body')) {
+              containerPos = $container.offset();
+              containerPos.top += parseInt($container.css('borderTopWidth')) - $container.scrollTop();
+              containerPos.left += parseInt($container.css('borderLeftWidth')) - $container.scrollLeft();
+            } else {
+              containerPos = { top: 0, left: 0 };
+            }
+
+            actualHeight = $element.hasClass(classNames.DROPUP) ? 0 : $element[0].offsetHeight;
+
+            // Bootstrap 4+ uses Popper for menu positioning
+            if (version.major < 4 || display === 'static') {
+              containerPosition.top = pos.top - containerPos.top + actualHeight;
+              containerPosition.left = pos.left - containerPos.left;
+            }
+
+            containerPosition.width = $element[0].offsetWidth;
+
+            that.$bsContainer.css(containerPosition);
+          };
+
+      this.$button.on('click.bs.dropdown.data-api', function () {
+        if (that.isDisabled()) {
+          return;
+        }
+
+        getPlacement(that.$newElement);
+
+        that.$bsContainer
+          .appendTo(that.options.container)
+          .toggleClass(classNames.SHOW, !that.$button.hasClass(classNames.SHOW))
+          .append(that.$menu);
+      });
+
+      $(window)
+        .off('resize' + EVENT_KEY + '.' + this.selectId + ' scroll' + EVENT_KEY + '.' + this.selectId)
+        .on('resize' + EVENT_KEY + '.' + this.selectId + ' scroll' + EVENT_KEY + '.' + this.selectId, function () {
+          var isActive = that.$newElement.hasClass(classNames.SHOW);
+
+          if (isActive) getPlacement(that.$newElement);
+        });
+
+      this.$element.on('hide' + EVENT_KEY, function () {
+        that.$menu.data('height', that.$menu.height());
+        that.$bsContainer.detach();
+      });
+    },
+
+    setOptionStatus: function (selectedOnly) {
+      var that = this;
+
+      that.noScroll = false;
+
+      if (that.selectpicker.view.visibleElements && that.selectpicker.view.visibleElements.length) {
+        for (var i = 0; i < that.selectpicker.view.visibleElements.length; i++) {
+          var liData = that.selectpicker.current.data[i + that.selectpicker.view.position0],
+              option = liData.option;
+
+          if (option) {
+            if (selectedOnly !== true) {
+              that.setDisabled(
+                liData.index,
+                liData.disabled
+              );
+            }
+
+            that.setSelected(
+              liData.index,
+              option.selected
+            );
+          }
+        }
+      }
+    },
+
+    /**
+     * @param {number} index - the index of the option that is being changed
+     * @param {boolean} selected - true if the option is being selected, false if being deselected
+     */
+    setSelected: function (index, selected) {
+      var li = this.selectpicker.main.elements[index],
+          liData = this.selectpicker.main.data[index],
+          activeIndexIsSet = this.activeIndex !== undefined,
+          thisIsActive = this.activeIndex === index,
+          prevActive,
+          a,
+          // if current option is already active
+          // OR
+          // if the current option is being selected, it's NOT multiple, and
+          // activeIndex is undefined:
+          //  - when the menu is first being opened, OR
+          //  - after a search has been performed, OR
+          //  - when retainActive is false when selecting a new option (i.e. index of the newly selected option is not the same as the current activeIndex)
+          keepActive = thisIsActive || (selected && !this.multiple && !activeIndexIsSet);
+
+      liData.selected = selected;
+
+      a = li.firstChild;
+
+      if (selected) {
+        this.selectedIndex = index;
+      }
+
+      li.classList.toggle('selected', selected);
+
+      if (keepActive) {
+        this.focusItem(li, liData);
+        this.selectpicker.view.currentActive = li;
+        this.activeIndex = index;
+      } else {
+        this.defocusItem(li);
+      }
+
+      if (a) {
+        a.classList.toggle('selected', selected);
+
+        if (selected) {
+          a.setAttribute('aria-selected', true);
+        } else {
+          if (this.multiple) {
+            a.setAttribute('aria-selected', false);
+          } else {
+            a.removeAttribute('aria-selected');
+          }
+        }
+      }
+
+      if (!keepActive && !activeIndexIsSet && selected && this.prevActiveIndex !== undefined) {
+        prevActive = this.selectpicker.main.elements[this.prevActiveIndex];
+
+        this.defocusItem(prevActive);
+      }
+    },
+
+    /**
+     * @param {number} index - the index of the option that is being disabled
+     * @param {boolean} disabled - true if the option is being disabled, false if being enabled
+     */
+    setDisabled: function (index, disabled) {
+      var li = this.selectpicker.main.elements[index],
+          a;
+
+      this.selectpicker.main.data[index].disabled = disabled;
+
+      a = li.firstChild;
+
+      li.classList.toggle(classNames.DISABLED, disabled);
+
+      if (a) {
+        if (version.major === '4') a.classList.toggle(classNames.DISABLED, disabled);
+
+        if (disabled) {
+          a.setAttribute('aria-disabled', disabled);
+          a.setAttribute('tabindex', -1);
+        } else {
+          a.removeAttribute('aria-disabled');
+          a.setAttribute('tabindex', 0);
+        }
+      }
+    },
+
+    isDisabled: function () {
+      return this.$element[0].disabled;
+    },
+
+    checkDisabled: function () {
+      if (this.isDisabled()) {
+        this.$newElement[0].classList.add(classNames.DISABLED);
+        this.$button.addClass(classNames.DISABLED).attr('aria-disabled', true);
+      } else {
+        if (this.$button[0].classList.contains(classNames.DISABLED)) {
+          this.$newElement[0].classList.remove(classNames.DISABLED);
+          this.$button.removeClass(classNames.DISABLED).attr('aria-disabled', false);
+        }
+      }
+    },
+
+    clickListener: function () {
+      var that = this,
+          $document = $(document);
+
+      $document.data('spaceSelect', false);
+
+      this.$button.on('keyup', function (e) {
+        if (/(32)/.test(e.keyCode.toString(10)) && $document.data('spaceSelect')) {
+          e.preventDefault();
+          $document.data('spaceSelect', false);
+        }
+      });
+
+      this.$newElement.on('show.bs.dropdown', function () {
+        if (version.major > 3 && !that.dropdown) {
+          that.dropdown = that.$button.data('bs.dropdown');
+          that.dropdown._menu = that.$menu[0];
+        }
+      });
+
+      this.$button.on('click.bs.dropdown.data-api', function () {
+        if (!that.$newElement.hasClass(classNames.SHOW)) {
+          that.setSize();
+        }
+      });
+
+      function setFocus () {
+        if (that.options.liveSearch) {
+          that.$searchbox.trigger('focus');
+        } else {
+          that.$menuInner.trigger('focus');
+        }
+      }
+
+      function checkPopperExists () {
+        if (that.dropdown && that.dropdown._popper && that.dropdown._popper.state.isCreated) {
+          setFocus();
+        } else {
+          requestAnimationFrame(checkPopperExists);
+        }
+      }
+
+      this.$element.on('shown' + EVENT_KEY, function () {
+        if (that.$menuInner[0].scrollTop !== that.selectpicker.view.scrollTop) {
+          that.$menuInner[0].scrollTop = that.selectpicker.view.scrollTop;
+        }
+
+        if (version.major > 3) {
+          requestAnimationFrame(checkPopperExists);
+        } else {
+          setFocus();
+        }
+      });
+
+      // ensure posinset and setsize are correct before selecting an option via a click
+      this.$menuInner.on('mouseenter', 'li a', function (e) {
+        var hoverLi = this.parentElement,
+            position0 = that.isVirtual() ? that.selectpicker.view.position0 : 0,
+            index = Array.prototype.indexOf.call(hoverLi.parentElement.children, hoverLi),
+            hoverData = that.selectpicker.current.data[index + position0];
+
+        that.focusItem(hoverLi, hoverData, true);
+      });
+
+      this.$menuInner.on('click', 'li a', function (e, retainActive) {
+        var $this = $(this),
+            element = that.$element[0],
+            position0 = that.isVirtual() ? that.selectpicker.view.position0 : 0,
+            clickedData = that.selectpicker.current.data[$this.parent().index() + position0],
+            clickedIndex = clickedData.index,
+            prevValue = getSelectValues(element),
+            prevIndex = element.selectedIndex,
+            prevOption = element.options[prevIndex],
+            triggerChange = true;
+
+        // Don't close on multi choice menu
+        if (that.multiple && that.options.maxOptions !== 1) {
+          e.stopPropagation();
+        }
+
+        e.preventDefault();
+
+        // Don't run if the select is disabled
+        if (!that.isDisabled() && !$this.parent().hasClass(classNames.DISABLED)) {
+          var option = clickedData.option,
+              $option = $(option),
+              state = option.selected,
+              $optgroup = $option.parent('optgroup'),
+              $optgroupOptions = $optgroup.find('option'),
+              maxOptions = that.options.maxOptions,
+              maxOptionsGrp = $optgroup.data('maxOptions') || false;
+
+          if (clickedIndex === that.activeIndex) retainActive = true;
+
+          if (!retainActive) {
+            that.prevActiveIndex = that.activeIndex;
+            that.activeIndex = undefined;
+          }
+
+          if (!that.multiple) { // Deselect all others if not multi select box
+            if (prevOption) prevOption.selected = false;
+            option.selected = true;
+            that.setSelected(clickedIndex, true);
+          } else { // Toggle the one we have chosen if we are multi select.
+            option.selected = !state;
+
+            that.setSelected(clickedIndex, !state);
+            that.focusedParent.focus();
+
+            if (maxOptions !== false || maxOptionsGrp !== false) {
+              var maxReached = maxOptions < getSelectedOptions(element).length,
+                  maxReachedGrp = maxOptionsGrp < $optgroup.find('option:selected').length;
+
+              if ((maxOptions && maxReached) || (maxOptionsGrp && maxReachedGrp)) {
+                if (maxOptions && maxOptions == 1) {
+                  element.selectedIndex = -1;
+                  option.selected = true;
+                  that.setOptionStatus(true);
+                } else if (maxOptionsGrp && maxOptionsGrp == 1) {
+                  for (var i = 0; i < $optgroupOptions.length; i++) {
+                    var _option = $optgroupOptions[i];
+                    _option.selected = false;
+                    that.setSelected(_option.liIndex, false);
+                  }
+
+                  option.selected = true;
+                  that.setSelected(clickedIndex, true);
+                } else {
+                  var maxOptionsText = typeof that.options.maxOptionsText === 'string' ? [that.options.maxOptionsText, that.options.maxOptionsText] : that.options.maxOptionsText,
+                      maxOptionsArr = typeof maxOptionsText === 'function' ? maxOptionsText(maxOptions, maxOptionsGrp) : maxOptionsText,
+                      maxTxt = maxOptionsArr[0].replace('{n}', maxOptions),
+                      maxTxtGrp = maxOptionsArr[1].replace('{n}', maxOptionsGrp),
+                      $notify = $('<div class="notify"></div>');
+                  // If {var} is set in array, replace it
+                  /** @deprecated */
+                  if (maxOptionsArr[2]) {
+                    maxTxt = maxTxt.replace('{var}', maxOptionsArr[2][maxOptions > 1 ? 0 : 1]);
+                    maxTxtGrp = maxTxtGrp.replace('{var}', maxOptionsArr[2][maxOptionsGrp > 1 ? 0 : 1]);
+                  }
+
+                  option.selected = false;
+
+                  that.$menu.append($notify);
+
+                  if (maxOptions && maxReached) {
+                    $notify.append($('<div>' + maxTxt + '</div>'));
+                    triggerChange = false;
+                    that.$element.trigger('maxReached' + EVENT_KEY);
+                  }
+
+                  if (maxOptionsGrp && maxReachedGrp) {
+                    $notify.append($('<div>' + maxTxtGrp + '</div>'));
+                    triggerChange = false;
+                    that.$element.trigger('maxReachedGrp' + EVENT_KEY);
+                  }
+
+                  setTimeout(function () {
+                    that.setSelected(clickedIndex, false);
+                  }, 10);
+
+                  $notify[0].classList.add('fadeOut');
+
+                  setTimeout(function () {
+                    $notify.remove();
+                  }, 1050);
+                }
+              }
+            }
+          }
+
+          if (!that.multiple || (that.multiple && that.options.maxOptions === 1)) {
+            that.$button.trigger('focus');
+          } else if (that.options.liveSearch) {
+            that.$searchbox.trigger('focus');
+          }
+
+          // Trigger select 'change'
+          if (triggerChange) {
+            if (that.multiple || prevIndex !== element.selectedIndex) {
+              // $option.prop('selected') is current option state (selected/unselected). prevValue is the value of the select prior to being changed.
+              changedArguments = [option.index, $option.prop('selected'), prevValue];
+              that.$element
+                .triggerNative('change');
+            }
+          }
+        }
+      });
+
+      this.$menu.on('click', 'li.' + classNames.DISABLED + ' a, .' + classNames.POPOVERHEADER + ', .' + classNames.POPOVERHEADER + ' :not(.close)', function (e) {
+        if (e.currentTarget == this) {
+          e.preventDefault();
+          e.stopPropagation();
+          if (that.options.liveSearch && !$(e.target).hasClass('close')) {
+            that.$searchbox.trigger('focus');
+          } else {
+            that.$button.trigger('focus');
+          }
+        }
+      });
+
+      this.$menuInner.on('click', '.divider, .dropdown-header', function (e) {
+        e.preventDefault();
+        e.stopPropagation();
+        if (that.options.liveSearch) {
+          that.$searchbox.trigger('focus');
+        } else {
+          that.$button.trigger('focus');
+        }
+      });
+
+      this.$menu.on('click', '.' + classNames.POPOVERHEADER + ' .close', function () {
+        that.$button.trigger('click');
+      });
+
+      this.$searchbox.on('click', function (e) {
+        e.stopPropagation();
+      });
+
+      this.$menu.on('click', '.actions-btn', function (e) {
+        if (that.options.liveSearch) {
+          that.$searchbox.trigger('focus');
+        } else {
+          that.$button.trigger('focus');
+        }
+
+        e.preventDefault();
+        e.stopPropagation();
+
+        if ($(this).hasClass('bs-select-all')) {
+          that.selectAll();
+        } else {
+          that.deselectAll();
+        }
+      });
+
+      this.$button
+        .on('focus' + EVENT_KEY, function (e) {
+          var tabindex = that.$element[0].getAttribute('tabindex');
+
+          // only change when button is actually focused
+          if (tabindex !== undefined && e.originalEvent && e.originalEvent.isTrusted) {
+            // apply select element's tabindex to ensure correct order is followed when tabbing to the next element
+            this.setAttribute('tabindex', tabindex);
+            // set element's tabindex to -1 to allow for reverse tabbing
+            that.$element[0].setAttribute('tabindex', -1);
+            that.selectpicker.view.tabindex = tabindex;
+          }
+        })
+        .on('blur' + EVENT_KEY, function (e) {
+          // revert everything to original tabindex
+          if (that.selectpicker.view.tabindex !== undefined && e.originalEvent && e.originalEvent.isTrusted) {
+            that.$element[0].setAttribute('tabindex', that.selectpicker.view.tabindex);
+            this.setAttribute('tabindex', -1);
+            that.selectpicker.view.tabindex = undefined;
+          }
+        });
+
+      this.$element
+        .on('change' + EVENT_KEY, function () {
+          that.render();
+          that.$element.trigger('changed' + EVENT_KEY, changedArguments);
+          changedArguments = null;
+        })
+        .on('focus' + EVENT_KEY, function () {
+          if (!that.options.mobile) that.$button[0].focus();
+        });
+    },
+
+    liveSearchListener: function () {
+      var that = this;
+
+      this.$button.on('click.bs.dropdown.data-api', function () {
+        if (!!that.$searchbox.val()) {
+          that.$searchbox.val('');
+          that.selectpicker.search.previousValue = undefined;
+        }
+      });
+
+      this.$searchbox.on('click.bs.dropdown.data-api focus.bs.dropdown.data-api touchend.bs.dropdown.data-api', function (e) {
+        e.stopPropagation();
+      });
+
+      this.$searchbox.on('input propertychange', function () {
+        var searchValue = that.$searchbox[0].value;
+
+        that.selectpicker.search.elements = [];
+        that.selectpicker.search.data = [];
+
+        if (searchValue) {
+          var i,
+              searchMatch = [],
+              q = searchValue.toUpperCase(),
+              cache = {},
+              cacheArr = [],
+              searchStyle = that._searchStyle(),
+              normalizeSearch = that.options.liveSearchNormalize;
+
+          if (normalizeSearch) q = normalizeToBase(q);
+
+          for (var i = 0; i < that.selectpicker.main.data.length; i++) {
+            var li = that.selectpicker.main.data[i];
+
+            if (!cache[i]) {
+              cache[i] = stringSearch(li, q, searchStyle, normalizeSearch);
+            }
+
+            if (cache[i] && li.headerIndex !== undefined && cacheArr.indexOf(li.headerIndex) === -1) {
+              if (li.headerIndex > 0) {
+                cache[li.headerIndex - 1] = true;
+                cacheArr.push(li.headerIndex - 1);
+              }
+
+              cache[li.headerIndex] = true;
+              cacheArr.push(li.headerIndex);
+
+              cache[li.lastIndex + 1] = true;
+            }
+
+            if (cache[i] && li.type !== 'optgroup-label') cacheArr.push(i);
+          }
+
+          for (var i = 0, cacheLen = cacheArr.length; i < cacheLen; i++) {
+            var index = cacheArr[i],
+                prevIndex = cacheArr[i - 1],
+                li = that.selectpicker.main.data[index],
+                liPrev = that.selectpicker.main.data[prevIndex];
+
+            if (li.type !== 'divider' || (li.type === 'divider' && liPrev && liPrev.type !== 'divider' && cacheLen - 1 !== i)) {
+              that.selectpicker.search.data.push(li);
+              searchMatch.push(that.selectpicker.main.elements[index]);
+            }
+          }
+
+          that.activeIndex = undefined;
+          that.noScroll = true;
+          that.$menuInner.scrollTop(0);
+          that.selectpicker.search.elements = searchMatch;
+          that.createView(true);
+          showNoResults.call(that, searchMatch, searchValue);
+        } else if (that.selectpicker.search.previousValue) { // for IE11 (#2402)
+          that.$menuInner.scrollTop(0);
+          that.createView(false);
+        }
+
+        that.selectpicker.search.previousValue =  searchValue;
+      });
+    },
+
+    _searchStyle: function () {
+      return this.options.liveSearchStyle || 'contains';
+    },
+
+    val: function (value) {
+      var element = this.$element[0];
+
+      if (typeof value !== 'undefined') {
+        var prevValue = getSelectValues(element);
+
+        changedArguments = [null, null, prevValue];
+
+        this.$element
+          .val(value)
+          .trigger('changed' + EVENT_KEY, changedArguments);
+
+        if (this.$newElement.hasClass(classNames.SHOW)) {
+          if (this.multiple) {
+            this.setOptionStatus(true);
+          } else {
+            var liSelectedIndex = (element.options[element.selectedIndex] || {}).liIndex;
+
+            if (typeof liSelectedIndex === 'number') {
+              this.setSelected(this.selectedIndex, false);
+              this.setSelected(liSelectedIndex, true);
+            }
+          }
+        }
+
+        this.render();
+
+        changedArguments = null;
+
+        return this.$element;
+      } else {
+        return this.$element.val();
+      }
+    },
+
+    changeAll: function (status) {
+      if (!this.multiple) return;
+      if (typeof status === 'undefined') status = true;
+
+      var element = this.$element[0],
+          previousSelected = 0,
+          currentSelected = 0,
+          prevValue = getSelectValues(element);
+
+      element.classList.add('bs-select-hidden');
+
+      for (var i = 0, data = this.selectpicker.current.data, len = data.length; i < len; i++) {
+        var liData = data[i],
+            option = liData.option;
+
+        if (option && !liData.disabled && liData.type !== 'divider') {
+          if (liData.selected) previousSelected++;
+          option.selected = status;
+          if (status === true) currentSelected++;
+        }
+      }
+
+      element.classList.remove('bs-select-hidden');
+
+      if (previousSelected === currentSelected) return;
+
+      this.setOptionStatus();
+
+      changedArguments = [null, null, prevValue];
+
+      this.$element
+        .triggerNative('change');
+    },
+
+    selectAll: function () {
+      return this.changeAll(true);
+    },
+
+    deselectAll: function () {
+      return this.changeAll(false);
+    },
+
+    toggle: function (e) {
+      e = e || window.event;
+
+      if (e) e.stopPropagation();
+
+      this.$button.trigger('click.bs.dropdown.data-api');
+    },
+
+    keydown: function (e) {
+      var $this = $(this),
+          isToggle = $this.hasClass('dropdown-toggle'),
+          $parent = isToggle ? $this.closest('.dropdown') : $this.closest(Selector.MENU),
+          that = $parent.data('this'),
+          $items = that.findLis(),
+          index,
+          isActive,
+          liActive,
+          activeLi,
+          offset,
+          updateScroll = false,
+          downOnTab = e.which === keyCodes.TAB && !isToggle && !that.options.selectOnTab,
+          isArrowKey = REGEXP_ARROW.test(e.which) || downOnTab,
+          scrollTop = that.$menuInner[0].scrollTop,
+          isVirtual = that.isVirtual(),
+          position0 = isVirtual === true ? that.selectpicker.view.position0 : 0;
+
+      // do nothing if a function key is pressed
+      if (e.which >= 112 && e.which <= 123) return;
+
+      isActive = that.$newElement.hasClass(classNames.SHOW);
+
+      if (
+        !isActive &&
+        (
+          isArrowKey ||
+          (e.which >= 48 && e.which <= 57) ||
+          (e.which >= 96 && e.which <= 105) ||
+          (e.which >= 65 && e.which <= 90)
+        )
+      ) {
+        that.$button.trigger('click.bs.dropdown.data-api');
+
+        if (that.options.liveSearch) {
+          that.$searchbox.trigger('focus');
+          return;
+        }
+      }
+
+      if (e.which === keyCodes.ESCAPE && isActive) {
+        e.preventDefault();
+        that.$button.trigger('click.bs.dropdown.data-api').trigger('focus');
+      }
+
+      if (isArrowKey) { // if up or down
+        if (!$items.length) return;
+
+        liActive = that.selectpicker.main.elements[that.activeIndex];
+        index = liActive ? Array.prototype.indexOf.call(liActive.parentElement.children, liActive) : -1;
+
+        if (index !== -1) {
+          that.defocusItem(liActive);
+        }
+
+        if (e.which === keyCodes.ARROW_UP) { // up
+          if (index !== -1) index--;
+          if (index + position0 < 0) index += $items.length;
+
+          if (!that.selectpicker.view.canHighlight[index + position0]) {
+            index = that.selectpicker.view.canHighlight.slice(0, index + position0).lastIndexOf(true) - position0;
+            if (index === -1) index = $items.length - 1;
+          }
+        } else if (e.which === keyCodes.ARROW_DOWN || downOnTab) { // down
+          index++;
+          if (index + position0 >= that.selectpicker.view.canHighlight.length) index = that.selectpicker.view.firstHighlightIndex;
+
+          if (!that.selectpicker.view.canHighlight[index + position0]) {
+            index = index + 1 + that.selectpicker.view.canHighlight.slice(index + position0 + 1).indexOf(true);
+          }
+        }
+
+        e.preventDefault();
+
+        var liActiveIndex = position0 + index;
+
+        if (e.which === keyCodes.ARROW_UP) { // up
+          // scroll to bottom and highlight last option
+          if (position0 === 0 && index === $items.length - 1) {
+            that.$menuInner[0].scrollTop = that.$menuInner[0].scrollHeight;
+
+            liActiveIndex = that.selectpicker.current.elements.length - 1;
+          } else {
+            activeLi = that.selectpicker.current.data[liActiveIndex];
+            offset = activeLi.position - activeLi.height;
+
+            updateScroll = offset < scrollTop;
+          }
+        } else if (e.which === keyCodes.ARROW_DOWN || downOnTab) { // down
+          // scroll to top and highlight first option
+          if (index === that.selectpicker.view.firstHighlightIndex) {
+            that.$menuInner[0].scrollTop = 0;
+
+            liActiveIndex = that.selectpicker.view.firstHighlightIndex;
+          } else {
+            activeLi = that.selectpicker.current.data[liActiveIndex];
+            offset = activeLi.position - that.sizeInfo.menuInnerHeight;
+
+            updateScroll = offset > scrollTop;
+          }
+        }
+
+        liActive = that.selectpicker.current.elements[liActiveIndex];
+
+        that.activeIndex = that.selectpicker.current.data[liActiveIndex].index;
+
+        that.focusItem(liActive);
+
+        that.selectpicker.view.currentActive = liActive;
+
+        if (updateScroll) that.$menuInner[0].scrollTop = offset;
+
+        if (that.options.liveSearch) {
+          that.$searchbox.trigger('focus');
+        } else {
+          $this.trigger('focus');
+        }
+      } else if (
+        (!$this.is('input') && !REGEXP_TAB_OR_ESCAPE.test(e.which)) ||
+        (e.which === keyCodes.SPACE && that.selectpicker.keydown.keyHistory)
+      ) {
+        var searchMatch,
+            matches = [],
+            keyHistory;
+
+        e.preventDefault();
+
+        that.selectpicker.keydown.keyHistory += keyCodeMap[e.which];
+
+        if (that.selectpicker.keydown.resetKeyHistory.cancel) clearTimeout(that.selectpicker.keydown.resetKeyHistory.cancel);
+        that.selectpicker.keydown.resetKeyHistory.cancel = that.selectpicker.keydown.resetKeyHistory.start();
+
+        keyHistory = that.selectpicker.keydown.keyHistory;
+
+        // if all letters are the same, set keyHistory to just the first character when searching
+        if (/^(.)\1+$/.test(keyHistory)) {
+          keyHistory = keyHistory.charAt(0);
+        }
+
+        // find matches
+        for (var i = 0; i < that.selectpicker.current.data.length; i++) {
+          var li = that.selectpicker.current.data[i],
+              hasMatch;
+
+          hasMatch = stringSearch(li, keyHistory, 'startsWith', true);
+
+          if (hasMatch && that.selectpicker.view.canHighlight[i]) {
+            matches.push(li.index);
+          }
+        }
+
+        if (matches.length) {
+          var matchIndex = 0;
+
+          $items.removeClass('active').find('a').removeClass('active');
+
+          // either only one key has been pressed or they are all the same key
+          if (keyHistory.length === 1) {
+            matchIndex = matches.indexOf(that.activeIndex);
+
+            if (matchIndex === -1 || matchIndex === matches.length - 1) {
+              matchIndex = 0;
+            } else {
+              matchIndex++;
+            }
+          }
+
+          searchMatch = matches[matchIndex];
+
+          activeLi = that.selectpicker.main.data[searchMatch];
+
+          if (scrollTop - activeLi.position > 0) {
+            offset = activeLi.position - activeLi.height;
+            updateScroll = true;
+          } else {
+            offset = activeLi.position - that.sizeInfo.menuInnerHeight;
+            // if the option is already visible at the current scroll position, just keep it the same
+            updateScroll = activeLi.position > scrollTop + that.sizeInfo.menuInnerHeight;
+          }
+
+          liActive = that.selectpicker.main.elements[searchMatch];
+
+          that.activeIndex = matches[matchIndex];
+
+          that.focusItem(liActive);
+
+          if (liActive) liActive.firstChild.focus();
+
+          if (updateScroll) that.$menuInner[0].scrollTop = offset;
+
+          $this.trigger('focus');
+        }
+      }
+
+      // Select focused option if "Enter", "Spacebar" or "Tab" (when selectOnTab is true) are pressed inside the menu.
+      if (
+        isActive &&
+        (
+          (e.which === keyCodes.SPACE && !that.selectpicker.keydown.keyHistory) ||
+          e.which === keyCodes.ENTER ||
+          (e.which === keyCodes.TAB && that.options.selectOnTab)
+        )
+      ) {
+        if (e.which !== keyCodes.SPACE) e.preventDefault();
+
+        if (!that.options.liveSearch || e.which !== keyCodes.SPACE) {
+          that.$menuInner.find('.active a').trigger('click', true); // retain active class
+          $this.trigger('focus');
+
+          if (!that.options.liveSearch) {
+            // Prevent screen from scrolling if the user hits the spacebar
+            e.preventDefault();
+            // Fixes spacebar selection of dropdown items in FF & IE
+            $(document).data('spaceSelect', true);
+          }
+        }
+      }
+    },
+
+    mobile: function () {
+      // ensure mobile is set to true if mobile function is called after init
+      this.options.mobile = true;
+      this.$element[0].classList.add('mobile-device');
+    },
+
+    refresh: function () {
+      // update options if data attributes have been changed
+      var config = $.extend({}, this.options, this.$element.data());
+      this.options = config;
+
+      this.checkDisabled();
+      this.buildData();
+      this.setStyle();
+      this.render();
+      this.buildList();
+      this.setWidth();
+
+      this.setSize(true);
+
+      this.$element.trigger('refreshed' + EVENT_KEY);
+    },
+
+    hide: function () {
+      this.$newElement.hide();
+    },
+
+    show: function () {
+      this.$newElement.show();
+    },
+
+    remove: function () {
+      this.$newElement.remove();
+      this.$element.remove();
+    },
+
+    destroy: function () {
+      this.$newElement.before(this.$element).remove();
+
+      if (this.$bsContainer) {
+        this.$bsContainer.remove();
+      } else {
+        this.$menu.remove();
+      }
+
+      if (this.selectpicker.view.titleOption && this.selectpicker.view.titleOption.parentNode) {
+        this.selectpicker.view.titleOption.parentNode.removeChild(this.selectpicker.view.titleOption);
+      }
+
+      this.$element
+        .off(EVENT_KEY)
+        .removeData('selectpicker')
+        .removeClass('bs-select-hidden selectpicker');
+
+      $(window).off(EVENT_KEY + '.' + this.selectId);
+    }
+  };
+
+  // SELECTPICKER PLUGIN DEFINITION
+  // ==============================
+  function Plugin (option) {
+    // get the args of the outer function..
+    var args = arguments;
+    // The arguments of the function are explicitly re-defined from the argument list, because the shift causes them
+    // to get lost/corrupted in android 2.3 and IE9 #715 #775
+    var _option = option;
+
+    [].shift.apply(args);
+
+    // if the version was not set successfully
+    if (!version.success) {
+      // try to retreive it again
+      try {
+        version.full = ($.fn.dropdown.Constructor.VERSION || '').split(' ')[0].split('.');
+      } catch (err) {
+        // fall back to use BootstrapVersion if set
+        if (Selectpicker.BootstrapVersion) {
+          version.full = Selectpicker.BootstrapVersion.split(' ')[0].split('.');
+        } else {
+          version.full = [version.major, '0', '0'];
+
+          console.warn(
+            'There was an issue retrieving Bootstrap\'s version. ' +
+            'Ensure Bootstrap is being loaded before bootstrap-select and there is no namespace collision. ' +
+            'If loading Bootstrap asynchronously, the version may need to be manually specified via $.fn.selectpicker.Constructor.BootstrapVersion.',
+            err
+          );
+        }
+      }
+
+      version.major = version.full[0];
+      version.success = true;
+    }
+
+    if (version.major === '4') {
+      // some defaults need to be changed if using Bootstrap 4
+      // check to see if they have already been manually changed before forcing them to update
+      var toUpdate = [];
+
+      if (Selectpicker.DEFAULTS.style === classNames.BUTTONCLASS) toUpdate.push({ name: 'style', className: 'BUTTONCLASS' });
+      if (Selectpicker.DEFAULTS.iconBase === classNames.ICONBASE) toUpdate.push({ name: 'iconBase', className: 'ICONBASE' });
+      if (Selectpicker.DEFAULTS.tickIcon === classNames.TICKICON) toUpdate.push({ name: 'tickIcon', className: 'TICKICON' });
+
+      classNames.DIVIDER = 'dropdown-divider';
+      classNames.SHOW = 'show';
+      classNames.BUTTONCLASS = 'btn-light';
+      classNames.POPOVERHEADER = 'popover-header';
+      classNames.ICONBASE = '';
+      classNames.TICKICON = 'bs-ok-default';
+
+      for (var i = 0; i < toUpdate.length; i++) {
+        var option = toUpdate[i];
+        Selectpicker.DEFAULTS[option.name] = classNames[option.className];
+      }
+    }
+
+    var value;
+    var chain = this.each(function () {
+      var $this = $(this);
+      if ($this.is('select')) {
+        var data = $this.data('selectpicker'),
+            options = typeof _option == 'object' && _option;
+
+        if (!data) {
+          var dataAttributes = $this.data();
+
+          for (var dataAttr in dataAttributes) {
+            if (Object.prototype.hasOwnProperty.call(dataAttributes, dataAttr) && $.inArray(dataAttr, DISALLOWED_ATTRIBUTES) !== -1) {
+              delete dataAttributes[dataAttr];
+            }
+          }
+
+          var config = $.extend({}, Selectpicker.DEFAULTS, $.fn.selectpicker.defaults || {}, dataAttributes, options);
+          config.template = $.extend({}, Selectpicker.DEFAULTS.template, ($.fn.selectpicker.defaults ? $.fn.selectpicker.defaults.template : {}), dataAttributes.template, options.template);
+          $this.data('selectpicker', (data = new Selectpicker(this, config)));
+        } else if (options) {
+          for (var i in options) {
+            if (Object.prototype.hasOwnProperty.call(options, i)) {
+              data.options[i] = options[i];
+            }
+          }
+        }
+
+        if (typeof _option == 'string') {
+          if (data[_option] instanceof Function) {
+            value = data[_option].apply(data, args);
+          } else {
+            value = data.options[_option];
+          }
+        }
+      }
+    });
+
+    if (typeof value !== 'undefined') {
+      // noinspection JSUnusedAssignment
+      return value;
+    } else {
+      return chain;
+    }
+  }
+
+  var old = $.fn.selectpicker;
+  $.fn.selectpicker = Plugin;
+  $.fn.selectpicker.Constructor = Selectpicker;
+
+  // SELECTPICKER NO CONFLICT
+  // ========================
+  $.fn.selectpicker.noConflict = function () {
+    $.fn.selectpicker = old;
+    return this;
+  };
+
+  // get Bootstrap's keydown event handler for either Bootstrap 4 or Bootstrap 3
+  function keydownHandler () {
+    if ($.fn.dropdown) {
+      // wait to define until function is called in case Bootstrap isn't loaded yet
+      var bootstrapKeydown = $.fn.dropdown.Constructor._dataApiKeydownHandler || $.fn.dropdown.Constructor.prototype.keydown;
+      return bootstrapKeydown.apply(this, arguments);
+    }
+  }
+
+  $(document)
+    .off('keydown.bs.dropdown.data-api')
+    .on('keydown.bs.dropdown.data-api', ':not(.bootstrap-select) > [data-toggle="dropdown"]', keydownHandler)
+    .on('keydown.bs.dropdown.data-api', ':not(.bootstrap-select) > .dropdown-menu', keydownHandler)
+    .on('keydown' + EVENT_KEY, '.bootstrap-select [data-toggle="dropdown"], .bootstrap-select [role="listbox"], .bootstrap-select .bs-searchbox input', Selectpicker.prototype.keydown)
+    .on('focusin.modal', '.bootstrap-select [data-toggle="dropdown"], .bootstrap-select [role="listbox"], .bootstrap-select .bs-searchbox input', function (e) {
+      e.stopPropagation();
+    });
+
+  // SELECTPICKER DATA-API
+  // =====================
+  $(window).on('load' + EVENT_KEY + '.data-api', function () {
+    $('.selectpicker').each(function () {
+      var $selectpicker = $(this);
+      Plugin.call($selectpicker, $selectpicker.data());
+    })
+  });
+})(jQuery);
+
+
+}));
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-select/bootstrap-select.min.css b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-select/bootstrap-select.min.css
new file mode 100644
index 0000000..8d0f049
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-select/bootstrap-select.min.css
@@ -0,0 +1,6 @@
+/*!
+ * Bootstrap-select v1.13.18 (https://developer.snapappointments.com/bootstrap-select)
+ *
+ * Copyright 2012-2020 SnapAppointments, LLC
+ * Licensed under MIT (https://github.com/snapappointments/bootstrap-select/blob/master/LICENSE)
+ */@-webkit-keyframes bs-notify-fadeOut{0%{opacity:.9}100%{opacity:0}}@-o-keyframes bs-notify-fadeOut{0%{opacity:.9}100%{opacity:0}}@keyframes bs-notify-fadeOut{0%{opacity:.9}100%{opacity:0}}.bootstrap-select>select.bs-select-hidden,select.bs-select-hidden,select.selectpicker{display:none!important}.bootstrap-select{width:220px\0;vertical-align:middle}.bootstrap-select>.dropdown-toggle{position:relative;width:100%;text-align:right;white-space:nowrap;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between}.bootstrap-select>.dropdown-toggle:after{margin-top:-1px}.bootstrap-select>.dropdown-toggle.bs-placeholder,.bootstrap-select>.dropdown-toggle.bs-placeholder:active,.bootstrap-select>.dropdown-toggle.bs-placeholder:focus,.bootstrap-select>.dropdown-toggle.bs-placeholder:hover{color:#999}.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-danger,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-danger:active,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-danger:focus,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-danger:hover,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-dark,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-dark:active,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-dark:focus,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-dark:hover,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-info,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-info:active,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-info:focus,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-info:hover,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-primary,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-primary:active,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-primary:focus,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-primary:hover,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-secondary,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-secondary:active,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-secondary:focus,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-secondary:hover,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-success,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-success:active,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-success:focus,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-success:hover{color:rgba(255,255,255,.5)}.bootstrap-select>select{position:absolute!important;bottom:0;left:50%;display:block!important;width:.5px!important;height:100%!important;padding:0!important;opacity:0!important;border:none;z-index:0!important}.bootstrap-select>select.mobile-device{top:0;left:0;display:block!important;width:100%!important;z-index:2!important}.bootstrap-select.is-invalid .dropdown-toggle,.error .bootstrap-select .dropdown-toggle,.has-error .bootstrap-select .dropdown-toggle,.was-validated .bootstrap-select select:invalid+.dropdown-toggle{border-color:#b94a48}.bootstrap-select.is-valid .dropdown-toggle,.was-validated .bootstrap-select select:valid+.dropdown-toggle{border-color:#28a745}.bootstrap-select.fit-width{width:auto!important}.bootstrap-select:not([class*=col-]):not([class*=form-control]):not(.input-group-btn){width:220px}.bootstrap-select .dropdown-toggle:focus,.bootstrap-select>select.mobile-device:focus+.dropdown-toggle{outline:thin dotted #333!important;outline:5px auto -webkit-focus-ring-color!important;outline-offset:-2px}.bootstrap-select.form-control{margin-bottom:0;padding:0;border:none;height:auto}:not(.input-group)>.bootstrap-select.form-control:not([class*=col-]){width:100%}.bootstrap-select.form-control.input-group-btn{float:none;z-index:auto}.form-inline .bootstrap-select,.form-inline .bootstrap-select.form-control:not([class*=col-]){width:auto}.bootstrap-select:not(.input-group-btn),.bootstrap-select[class*=col-]{float:none;display:inline-block;margin-left:0}.bootstrap-select.dropdown-menu-right,.bootstrap-select[class*=col-].dropdown-menu-right,.row .bootstrap-select[class*=col-].dropdown-menu-right{float:right}.form-group .bootstrap-select,.form-horizontal .bootstrap-select,.form-inline .bootstrap-select{margin-bottom:0}.form-group-lg .bootstrap-select.form-control,.form-group-sm .bootstrap-select.form-control{padding:0}.form-group-lg .bootstrap-select.form-control .dropdown-toggle,.form-group-sm .bootstrap-select.form-control .dropdown-toggle{height:100%;font-size:inherit;line-height:inherit;border-radius:inherit}.bootstrap-select.form-control-lg .dropdown-toggle,.bootstrap-select.form-control-sm .dropdown-toggle{font-size:inherit;line-height:inherit;border-radius:inherit}.bootstrap-select.form-control-sm .dropdown-toggle{padding:.25rem .5rem}.bootstrap-select.form-control-lg .dropdown-toggle{padding:.5rem 1rem}.form-inline .bootstrap-select .form-control{width:100%}.bootstrap-select.disabled,.bootstrap-select>.disabled{cursor:not-allowed}.bootstrap-select.disabled:focus,.bootstrap-select>.disabled:focus{outline:0!important}.bootstrap-select.bs-container{position:absolute;top:0;left:0;height:0!important;padding:0!important}.bootstrap-select.bs-container .dropdown-menu{z-index:1060}.bootstrap-select .dropdown-toggle .filter-option{position:static;top:0;left:0;float:left;height:100%;width:100%;text-align:left;overflow:hidden;-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.bs3.bootstrap-select .dropdown-toggle .filter-option{padding-right:inherit}.input-group .bs3-has-addon.bootstrap-select .dropdown-toggle .filter-option{position:absolute;padding-top:inherit;padding-bottom:inherit;padding-left:inherit;float:none}.input-group .bs3-has-addon.bootstrap-select .dropdown-toggle .filter-option .filter-option-inner{padding-right:inherit}.bootstrap-select .dropdown-toggle .filter-option-inner-inner{overflow:hidden}.bootstrap-select .dropdown-toggle .filter-expand{width:0!important;float:left;opacity:0!important;overflow:hidden}.bootstrap-select .dropdown-toggle .caret{position:absolute;top:50%;right:12px;margin-top:-2px;vertical-align:middle}.input-group .bootstrap-select.form-control .dropdown-toggle{border-radius:inherit}.bootstrap-select[class*=col-] .dropdown-toggle{width:100%}.bootstrap-select .dropdown-menu{min-width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bootstrap-select .dropdown-menu>.inner:focus{outline:0!important}.bootstrap-select .dropdown-menu.inner{position:static;float:none;border:0;padding:0;margin:0;border-radius:0;-webkit-box-shadow:none;box-shadow:none}.bootstrap-select .dropdown-menu li{position:relative}.bootstrap-select .dropdown-menu li.active small{color:rgba(255,255,255,.5)!important}.bootstrap-select .dropdown-menu li.disabled a{cursor:not-allowed}.bootstrap-select .dropdown-menu li a{cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.bootstrap-select .dropdown-menu li a.opt{position:relative;padding-left:2.25em}.bootstrap-select .dropdown-menu li a span.check-mark{display:none}.bootstrap-select .dropdown-menu li a span.text{display:inline-block}.bootstrap-select .dropdown-menu li small{padding-left:.5em}.bootstrap-select .dropdown-menu .notify{position:absolute;bottom:5px;width:96%;margin:0 2%;min-height:26px;padding:3px 5px;background:#f5f5f5;border:1px solid #e3e3e3;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05);pointer-events:none;opacity:.9;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bootstrap-select .dropdown-menu .notify.fadeOut{-webkit-animation:.3s linear 750ms forwards bs-notify-fadeOut;-o-animation:.3s linear 750ms forwards bs-notify-fadeOut;animation:.3s linear 750ms forwards bs-notify-fadeOut}.bootstrap-select .no-results{padding:3px;background:#f5f5f5;margin:0 5px;white-space:nowrap}.bootstrap-select.fit-width .dropdown-toggle .filter-option{position:static;display:inline;padding:0}.bootstrap-select.fit-width .dropdown-toggle .filter-option-inner,.bootstrap-select.fit-width .dropdown-toggle .filter-option-inner-inner{display:inline}.bootstrap-select.fit-width .dropdown-toggle .bs-caret:before{content:'\00a0'}.bootstrap-select.fit-width .dropdown-toggle .caret{position:static;top:auto;margin-top:-1px}.bootstrap-select.show-tick .dropdown-menu .selected span.check-mark{position:absolute;display:inline-block;right:15px;top:5px}.bootstrap-select.show-tick .dropdown-menu li a span.text{margin-right:34px}.bootstrap-select .bs-ok-default:after{content:'';display:block;width:.5em;height:1em;border-style:solid;border-width:0 .26em .26em 0;-webkit-transform-style:preserve-3d;transform-style:preserve-3d;-webkit-transform:rotate(45deg);-ms-transform:rotate(45deg);-o-transform:rotate(45deg);transform:rotate(45deg)}.bootstrap-select.show-menu-arrow.open>.dropdown-toggle,.bootstrap-select.show-menu-arrow.show>.dropdown-toggle{z-index:1061}.bootstrap-select.show-menu-arrow .dropdown-toggle .filter-option:before{content:'';border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid rgba(204,204,204,.2);position:absolute;bottom:-4px;left:9px;display:none}.bootstrap-select.show-menu-arrow .dropdown-toggle .filter-option:after{content:'';border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #fff;position:absolute;bottom:-4px;left:10px;display:none}.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle .filter-option:before{bottom:auto;top:-4px;border-top:7px solid rgba(204,204,204,.2);border-bottom:0}.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle .filter-option:after{bottom:auto;top:-4px;border-top:6px solid #fff;border-bottom:0}.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle .filter-option:before{right:12px;left:auto}.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle .filter-option:after{right:13px;left:auto}.bootstrap-select.show-menu-arrow.open>.dropdown-toggle .filter-option:after,.bootstrap-select.show-menu-arrow.open>.dropdown-toggle .filter-option:before,.bootstrap-select.show-menu-arrow.show>.dropdown-toggle .filter-option:after,.bootstrap-select.show-menu-arrow.show>.dropdown-toggle .filter-option:before{display:block}.bs-actionsbox,.bs-donebutton,.bs-searchbox{padding:4px 8px}.bs-actionsbox{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bs-actionsbox .btn-group button{width:50%}.bs-donebutton{float:left;width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bs-donebutton .btn-group button{width:100%}.bs-searchbox+.bs-actionsbox{padding:0 8px 4px}.bs-searchbox .form-control{margin-bottom:0;width:100%;float:none}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-select/bootstrap-select.min.js b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-select/bootstrap-select.min.js
new file mode 100644
index 0000000..46cf10e
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-select/bootstrap-select.min.js
@@ -0,0 +1,8 @@
+/*!
+ * Bootstrap-select v1.13.18 (https://developer.snapappointments.com/bootstrap-select)
+ *
+ * Copyright 2012-2020 SnapAppointments, LLC
+ * Licensed under MIT (https://github.com/snapappointments/bootstrap-select/blob/master/LICENSE)
+ */
+
+!function(e,t){void 0===e&&void 0!==window&&(e=window),"function"==typeof define&&define.amd?define(["jquery"],function(e){return t(e)}):"object"==typeof module&&module.exports?module.exports=t(require("jquery")):t(e.jQuery)}(this,function(e){!function(P){"use strict";var d=["sanitize","whiteList","sanitizeFn"],r=["background","cite","href","itemtype","longdesc","poster","src","xlink:href"],e={"*":["class","dir","id","lang","role","tabindex","style",/^aria-[\w-]*$/i],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],div:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},l=/^(?:(?:https?|mailto|ftp|tel|file):|[^&:/?#]*(?:[/?#]|$))/gi,a=/^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[a-z0-9+/]+=*$/i;function v(e,t){var i=e.nodeName.toLowerCase();if(-1!==P.inArray(i,t))return-1===P.inArray(i,r)||Boolean(e.nodeValue.match(l)||e.nodeValue.match(a));for(var s=P(t).filter(function(e,t){return t instanceof RegExp}),n=0,o=s.length;n<o;n++)if(i.match(s[n]))return!0;return!1}function W(e,t,i){if(i&&"function"==typeof i)return i(e);for(var s=Object.keys(t),n=0,o=e.length;n<o;n++)for(var r=e[n].querySelectorAll("*"),l=0,a=r.length;l<a;l++){var c=r[l],d=c.nodeName.toLowerCase();if(-1!==s.indexOf(d))for(var h=[].slice.call(c.attributes),p=[].concat(t["*"]||[],t[d]||[]),u=0,f=h.length;u<f;u++){var m=h[u];v(m,p)||c.removeAttribute(m.nodeName)}else c.parentNode.removeChild(c)}}"classList"in document.createElement("_")||function(e){if("Element"in e){var t="classList",i="prototype",s=e.Element[i],n=Object,o=function(){var i=P(this);return{add:function(e){return e=Array.prototype.slice.call(arguments).join(" "),i.addClass(e)},remove:function(e){return e=Array.prototype.slice.call(arguments).join(" "),i.removeClass(e)},toggle:function(e,t){return i.toggleClass(e,t)},contains:function(e){return i.hasClass(e)}}};if(n.defineProperty){var r={get:o,enumerable:!0,configurable:!0};try{n.defineProperty(s,t,r)}catch(e){void 0!==e.number&&-2146823252!==e.number||(r.enumerable=!1,n.defineProperty(s,t,r))}}else n[i].__defineGetter__&&s.__defineGetter__(t,o)}}(window);var t,c,i=document.createElement("_");if(i.classList.add("c1","c2"),!i.classList.contains("c2")){var s=DOMTokenList.prototype.add,n=DOMTokenList.prototype.remove;DOMTokenList.prototype.add=function(){Array.prototype.forEach.call(arguments,s.bind(this))},DOMTokenList.prototype.remove=function(){Array.prototype.forEach.call(arguments,n.bind(this))}}if(i.classList.toggle("c3",!1),i.classList.contains("c3")){var o=DOMTokenList.prototype.toggle;DOMTokenList.prototype.toggle=function(e,t){return 1 in arguments&&!this.contains(e)==!t?t:o.call(this,e)}}function h(e){if(null==this)throw new TypeError;var t=String(this);if(e&&"[object RegExp]"==c.call(e))throw new TypeError;var i=t.length,s=String(e),n=s.length,o=1<arguments.length?arguments[1]:void 0,r=o?Number(o):0;r!=r&&(r=0);var l=Math.min(Math.max(r,0),i);if(i<n+l)return!1;for(var a=-1;++a<n;)if(t.charCodeAt(l+a)!=s.charCodeAt(a))return!1;return!0}function O(e,t){var i,s=e.selectedOptions,n=[];if(t){for(var o=0,r=s.length;o<r;o++)(i=s[o]).disabled||"OPTGROUP"===i.parentNode.tagName&&i.parentNode.disabled||n.push(i);return n}return s}function z(e,t){for(var i,s=[],n=t||e.selectedOptions,o=0,r=n.length;o<r;o++)(i=n[o]).disabled||"OPTGROUP"===i.parentNode.tagName&&i.parentNode.disabled||s.push(i.value);return e.multiple?s:s.length?s[0]:null}i=null,String.prototype.startsWith||(t=function(){try{var e={},t=Object.defineProperty,i=t(e,e,e)&&t}catch(e){}return i}(),c={}.toString,t?t(String.prototype,"startsWith",{value:h,configurable:!0,writable:!0}):String.prototype.startsWith=h),Object.keys||(Object.keys=function(e,t,i){for(t in i=[],e)i.hasOwnProperty.call(e,t)&&i.push(t);return i}),HTMLSelectElement&&!HTMLSelectElement.prototype.hasOwnProperty("selectedOptions")&&Object.defineProperty(HTMLSelectElement.prototype,"selectedOptions",{get:function(){return this.querySelectorAll(":checked")}});var p={useDefault:!1,_set:P.valHooks.select.set};P.valHooks.select.set=function(e,t){return t&&!p.useDefault&&P(e).data("selected",!0),p._set.apply(this,arguments)};var T=null,u=function(){try{return new Event("change"),!0}catch(e){return!1}}();function k(e,t,i,s){for(var n=["display","subtext","tokens"],o=!1,r=0;r<n.length;r++){var l=n[r],a=e[l];if(a&&(a=a.toString(),"display"===l&&(a=a.replace(/<[^>]+>/g,"")),s&&(a=w(a)),a=a.toUpperCase(),o="contains"===i?0<=a.indexOf(t):a.startsWith(t)))break}return o}function N(e){return parseInt(e,10)||0}P.fn.triggerNative=function(e){var t,i=this[0];i.dispatchEvent?(u?t=new Event(e,{bubbles:!0}):(t=document.createEvent("Event")).initEvent(e,!0,!1),i.dispatchEvent(t)):i.fireEvent?((t=document.createEventObject()).eventType=e,i.fireEvent("on"+e,t)):this.trigger(e)};var f={"\xc0":"A","\xc1":"A","\xc2":"A","\xc3":"A","\xc4":"A","\xc5":"A","\xe0":"a","\xe1":"a","\xe2":"a","\xe3":"a","\xe4":"a","\xe5":"a","\xc7":"C","\xe7":"c","\xd0":"D","\xf0":"d","\xc8":"E","\xc9":"E","\xca":"E","\xcb":"E","\xe8":"e","\xe9":"e","\xea":"e","\xeb":"e","\xcc":"I","\xcd":"I","\xce":"I","\xcf":"I","\xec":"i","\xed":"i","\xee":"i","\xef":"i","\xd1":"N","\xf1":"n","\xd2":"O","\xd3":"O","\xd4":"O","\xd5":"O","\xd6":"O","\xd8":"O","\xf2":"o","\xf3":"o","\xf4":"o","\xf5":"o","\xf6":"o","\xf8":"o","\xd9":"U","\xda":"U","\xdb":"U","\xdc":"U","\xf9":"u","\xfa":"u","\xfb":"u","\xfc":"u","\xdd":"Y","\xfd":"y","\xff":"y","\xc6":"Ae","\xe6":"ae","\xde":"Th","\xfe":"th","\xdf":"ss","\u0100":"A","\u0102":"A","\u0104":"A","\u0101":"a","\u0103":"a","\u0105":"a","\u0106":"C","\u0108":"C","\u010a":"C","\u010c":"C","\u0107":"c","\u0109":"c","\u010b":"c","\u010d":"c","\u010e":"D","\u0110":"D","\u010f":"d","\u0111":"d","\u0112":"E","\u0114":"E","\u0116":"E","\u0118":"E","\u011a":"E","\u0113":"e","\u0115":"e","\u0117":"e","\u0119":"e","\u011b":"e","\u011c":"G","\u011e":"G","\u0120":"G","\u0122":"G","\u011d":"g","\u011f":"g","\u0121":"g","\u0123":"g","\u0124":"H","\u0126":"H","\u0125":"h","\u0127":"h","\u0128":"I","\u012a":"I","\u012c":"I","\u012e":"I","\u0130":"I","\u0129":"i","\u012b":"i","\u012d":"i","\u012f":"i","\u0131":"i","\u0134":"J","\u0135":"j","\u0136":"K","\u0137":"k","\u0138":"k","\u0139":"L","\u013b":"L","\u013d":"L","\u013f":"L","\u0141":"L","\u013a":"l","\u013c":"l","\u013e":"l","\u0140":"l","\u0142":"l","\u0143":"N","\u0145":"N","\u0147":"N","\u014a":"N","\u0144":"n","\u0146":"n","\u0148":"n","\u014b":"n","\u014c":"O","\u014e":"O","\u0150":"O","\u014d":"o","\u014f":"o","\u0151":"o","\u0154":"R","\u0156":"R","\u0158":"R","\u0155":"r","\u0157":"r","\u0159":"r","\u015a":"S","\u015c":"S","\u015e":"S","\u0160":"S","\u015b":"s","\u015d":"s","\u015f":"s","\u0161":"s","\u0162":"T","\u0164":"T","\u0166":"T","\u0163":"t","\u0165":"t","\u0167":"t","\u0168":"U","\u016a":"U","\u016c":"U","\u016e":"U","\u0170":"U","\u0172":"U","\u0169":"u","\u016b":"u","\u016d":"u","\u016f":"u","\u0171":"u","\u0173":"u","\u0174":"W","\u0175":"w","\u0176":"Y","\u0177":"y","\u0178":"Y","\u0179":"Z","\u017b":"Z","\u017d":"Z","\u017a":"z","\u017c":"z","\u017e":"z","\u0132":"IJ","\u0133":"ij","\u0152":"Oe","\u0153":"oe","\u0149":"'n","\u017f":"s"},m=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,g=RegExp("[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff\\u1ab0-\\u1aff\\u1dc0-\\u1dff]","g");function b(e){return f[e]}function w(e){return(e=e.toString())&&e.replace(m,b).replace(g,"")}var I,x,y,$,S=(I={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#x27;","`":"&#x60;"},x="(?:"+Object.keys(I).join("|")+")",y=RegExp(x),$=RegExp(x,"g"),function(e){return e=null==e?"":""+e,y.test(e)?e.replace($,E):e});function E(e){return I[e]}var C={32:" ",48:"0",49:"1",50:"2",51:"3",52:"4",53:"5",54:"6",55:"7",56:"8",57:"9",59:";",65:"A",66:"B",67:"C",68:"D",69:"E",70:"F",71:"G",72:"H",73:"I",74:"J",75:"K",76:"L",77:"M",78:"N",79:"O",80:"P",81:"Q",82:"R",83:"S",84:"T",85:"U",86:"V",87:"W",88:"X",89:"Y",90:"Z",96:"0",97:"1",98:"2",99:"3",100:"4",101:"5",102:"6",103:"7",104:"8",105:"9"},A=27,L=13,D=32,H=9,B=38,R=40,M={success:!1,major:"3"};try{M.full=(P.fn.dropdown.Constructor.VERSION||"").split(" ")[0].split("."),M.major=M.full[0],M.success=!0}catch(e){}var U=0,j=".bs.select",V={DISABLED:"disabled",DIVIDER:"divider",SHOW:"open",DROPUP:"dropup",MENU:"dropdown-menu",MENURIGHT:"dropdown-menu-right",MENULEFT:"dropdown-menu-left",BUTTONCLASS:"btn-default",POPOVERHEADER:"popover-title",ICONBASE:"glyphicon",TICKICON:"glyphicon-ok"},F={MENU:"."+V.MENU},_={div:document.createElement("div"),span:document.createElement("span"),i:document.createElement("i"),subtext:document.createElement("small"),a:document.createElement("a"),li:document.createElement("li"),whitespace:document.createTextNode("\xa0"),fragment:document.createDocumentFragment()};_.noResults=_.li.cloneNode(!1),_.noResults.className="no-results",_.a.setAttribute("role","option"),_.a.className="dropdown-item",_.subtext.className="text-muted",_.text=_.span.cloneNode(!1),_.text.className="text",_.checkMark=_.span.cloneNode(!1);var G=new RegExp(B+"|"+R),q=new RegExp("^"+H+"$|"+A),K={li:function(e,t,i){var s=_.li.cloneNode(!1);return e&&(1===e.nodeType||11===e.nodeType?s.appendChild(e):s.innerHTML=e),void 0!==t&&""!==t&&(s.className=t),null!=i&&s.classList.add("optgroup-"+i),s},a:function(e,t,i){var s=_.a.cloneNode(!0);return e&&(11===e.nodeType?s.appendChild(e):s.insertAdjacentHTML("beforeend",e)),void 0!==t&&""!==t&&s.classList.add.apply(s.classList,t.split(/\s+/)),i&&s.setAttribute("style",i),s},text:function(e,t){var i,s,n=_.text.cloneNode(!1);if(e.content)n.innerHTML=e.content;else{if(n.textContent=e.text,e.icon){var o=_.whitespace.cloneNode(!1);(s=(!0===t?_.i:_.span).cloneNode(!1)).className=this.options.iconBase+" "+e.icon,_.fragment.appendChild(s),_.fragment.appendChild(o)}e.subtext&&((i=_.subtext.cloneNode(!1)).textContent=e.subtext,n.appendChild(i))}if(!0===t)for(;0<n.childNodes.length;)_.fragment.appendChild(n.childNodes[0]);else _.fragment.appendChild(n);return _.fragment},label:function(e){var t,i,s=_.text.cloneNode(!1);if(s.innerHTML=e.display,e.icon){var n=_.whitespace.cloneNode(!1);(i=_.span.cloneNode(!1)).className=this.options.iconBase+" "+e.icon,_.fragment.appendChild(i),_.fragment.appendChild(n)}return e.subtext&&((t=_.subtext.cloneNode(!1)).textContent=e.subtext,s.appendChild(t)),_.fragment.appendChild(s),_.fragment}};var Y=function(e,t){var i=this;p.useDefault||(P.valHooks.select.set=p._set,p.useDefault=!0),this.$element=P(e),this.$newElement=null,this.$button=null,this.$menu=null,this.options=t,this.selectpicker={main:{},search:{},current:{},view:{},isSearching:!1,keydown:{keyHistory:"",resetKeyHistory:{start:function(){return setTimeout(function(){i.selectpicker.keydown.keyHistory=""},800)}}}},this.sizeInfo={},null===this.options.title&&(this.options.title=this.$element.attr("title"));var s=this.options.windowPadding;"number"==typeof s&&(this.options.windowPadding=[s,s,s,s]),this.val=Y.prototype.val,this.render=Y.prototype.render,this.refresh=Y.prototype.refresh,this.setStyle=Y.prototype.setStyle,this.selectAll=Y.prototype.selectAll,this.deselectAll=Y.prototype.deselectAll,this.destroy=Y.prototype.destroy,this.remove=Y.prototype.remove,this.show=Y.prototype.show,this.hide=Y.prototype.hide,this.init()};function Z(e){var l,a=arguments,c=e;if([].shift.apply(a),!M.success){try{M.full=(P.fn.dropdown.Constructor.VERSION||"").split(" ")[0].split(".")}catch(e){Y.BootstrapVersion?M.full=Y.BootstrapVersion.split(" ")[0].split("."):(M.full=[M.major,"0","0"],console.warn("There was an issue retrieving Bootstrap's version. Ensure Bootstrap is being loaded before bootstrap-select and there is no namespace collision. If loading Bootstrap asynchronously, the version may need to be manually specified via $.fn.selectpicker.Constructor.BootstrapVersion.",e))}M.major=M.full[0],M.success=!0}if("4"===M.major){var t=[];Y.DEFAULTS.style===V.BUTTONCLASS&&t.push({name:"style",className:"BUTTONCLASS"}),Y.DEFAULTS.iconBase===V.ICONBASE&&t.push({name:"iconBase",className:"ICONBASE"}),Y.DEFAULTS.tickIcon===V.TICKICON&&t.push({name:"tickIcon",className:"TICKICON"}),V.DIVIDER="dropdown-divider",V.SHOW="show",V.BUTTONCLASS="btn-light",V.POPOVERHEADER="popover-header",V.ICONBASE="",V.TICKICON="bs-ok-default";for(var i=0;i<t.length;i++){e=t[i];Y.DEFAULTS[e.name]=V[e.className]}}var s=this.each(function(){var e=P(this);if(e.is("select")){var t=e.data("selectpicker"),i="object"==typeof c&&c;if(t){if(i)for(var s in i)Object.prototype.hasOwnProperty.call(i,s)&&(t.options[s]=i[s])}else{var n=e.data();for(var o in n)Object.prototype.hasOwnProperty.call(n,o)&&-1!==P.inArray(o,d)&&delete n[o];var r=P.extend({},Y.DEFAULTS,P.fn.selectpicker.defaults||{},n,i);r.template=P.extend({},Y.DEFAULTS.template,P.fn.selectpicker.defaults?P.fn.selectpicker.defaults.template:{},n.template,i.template),e.data("selectpicker",t=new Y(this,r))}"string"==typeof c&&(l=t[c]instanceof Function?t[c].apply(t,a):t.options[c])}});return void 0!==l?l:s}Y.VERSION="1.13.18",Y.DEFAULTS={noneSelectedText:"Nothing selected",noneResultsText:"No results matched {0}",countSelectedText:function(e,t){return 1==e?"{0} item selected":"{0} items selected"},maxOptionsText:function(e,t){return[1==e?"Limit reached ({n} item max)":"Limit reached ({n} items max)",1==t?"Group limit reached ({n} item max)":"Group limit reached ({n} items max)"]},selectAllText:"Select All",deselectAllText:"Deselect All",doneButton:!1,doneButtonText:"Close",multipleSeparator:", ",styleBase:"btn",style:V.BUTTONCLASS,size:"auto",title:null,selectedTextFormat:"values",width:!1,container:!1,hideDisabled:!1,showSubtext:!1,showIcon:!0,showContent:!0,dropupAuto:!0,header:!1,liveSearch:!1,liveSearchPlaceholder:null,liveSearchNormalize:!1,liveSearchStyle:"contains",actionsBox:!1,iconBase:V.ICONBASE,tickIcon:V.TICKICON,showTick:!1,template:{caret:'<span class="caret"></span>'},maxOptions:!1,mobile:!1,selectOnTab:!1,dropdownAlignRight:!1,windowPadding:0,virtualScroll:600,display:!1,sanitize:!0,sanitizeFn:null,whiteList:e},Y.prototype={constructor:Y,init:function(){var i=this,e=this.$element.attr("id"),t=this.$element[0],s=t.form;U++,this.selectId="bs-select-"+U,t.classList.add("bs-select-hidden"),this.multiple=this.$element.prop("multiple"),this.autofocus=this.$element.prop("autofocus"),t.classList.contains("show-tick")&&(this.options.showTick=!0),this.$newElement=this.createDropdown(),this.buildData(),this.$element.after(this.$newElement).prependTo(this.$newElement),s&&null===t.form&&(s.id||(s.id="form-"+this.selectId),t.setAttribute("form",s.id)),this.$button=this.$newElement.children("button"),this.$menu=this.$newElement.children(F.MENU),this.$menuInner=this.$menu.children(".inner"),this.$searchbox=this.$menu.find("input"),t.classList.remove("bs-select-hidden"),!0===this.options.dropdownAlignRight&&this.$menu[0].classList.add(V.MENURIGHT),void 0!==e&&this.$button.attr("data-id",e),this.checkDisabled(),this.clickListener(),this.options.liveSearch?(this.liveSearchListener(),this.focusedParent=this.$searchbox[0]):this.focusedParent=this.$menuInner[0],this.setStyle(),this.render(),this.setWidth(),this.options.container?this.selectPosition():this.$element.on("hide"+j,function(){if(i.isVirtual()){var e=i.$menuInner[0],t=e.firstChild.cloneNode(!1);e.replaceChild(t,e.firstChild),e.scrollTop=0}}),this.$menu.data("this",this),this.$newElement.data("this",this),this.options.mobile&&this.mobile(),this.$newElement.on({"hide.bs.dropdown":function(e){i.$element.trigger("hide"+j,e)},"hidden.bs.dropdown":function(e){i.$element.trigger("hidden"+j,e)},"show.bs.dropdown":function(e){i.$element.trigger("show"+j,e)},"shown.bs.dropdown":function(e){i.$element.trigger("shown"+j,e)}}),t.hasAttribute("required")&&this.$element.on("invalid"+j,function(){i.$button[0].classList.add("bs-invalid"),i.$element.on("shown"+j+".invalid",function(){i.$element.val(i.$element.val()).off("shown"+j+".invalid")}).on("rendered"+j,function(){this.validity.valid&&i.$button[0].classList.remove("bs-invalid"),i.$element.off("rendered"+j)}),i.$button.on("blur"+j,function(){i.$element.trigger("focus").trigger("blur"),i.$button.off("blur"+j)})}),setTimeout(function(){i.buildList(),i.$element.trigger("loaded"+j)})},createDropdown:function(){var e=this.multiple||this.options.showTick?" show-tick":"",t=this.multiple?' aria-multiselectable="true"':"",i="",s=this.autofocus?" autofocus":"";M.major<4&&this.$element.parent().hasClass("input-group")&&(i=" input-group-btn");var n,o="",r="",l="",a="";return this.options.header&&(o='<div class="'+V.POPOVERHEADER+'"><button type="button" class="close" aria-hidden="true">&times;</button>'+this.options.header+"</div>"),this.options.liveSearch&&(r='<div class="bs-searchbox"><input type="search" class="form-control" autocomplete="off"'+(null===this.options.liveSearchPlaceholder?"":' placeholder="'+S(this.options.liveSearchPlaceholder)+'"')+' role="combobox" aria-label="Search" aria-controls="'+this.selectId+'" aria-autocomplete="list"></div>'),this.multiple&&this.options.actionsBox&&(l='<div class="bs-actionsbox"><div class="btn-group btn-group-sm btn-block"><button type="button" class="actions-btn bs-select-all btn '+V.BUTTONCLASS+'">'+this.options.selectAllText+'</button><button type="button" class="actions-btn bs-deselect-all btn '+V.BUTTONCLASS+'">'+this.options.deselectAllText+"</button></div></div>"),this.multiple&&this.options.doneButton&&(a='<div class="bs-donebutton"><div class="btn-group btn-block"><button type="button" class="btn btn-sm '+V.BUTTONCLASS+'">'+this.options.doneButtonText+"</button></div></div>"),n='<div class="dropdown bootstrap-select'+e+i+'"><button type="button" tabindex="-1" class="'+this.options.styleBase+' dropdown-toggle" '+("static"===this.options.display?'data-display="static"':"")+'data-toggle="dropdown"'+s+' role="combobox" aria-owns="'+this.selectId+'" aria-haspopup="listbox" aria-expanded="false"><div class="filter-option"><div class="filter-option-inner"><div class="filter-option-inner-inner"></div></div> </div>'+("4"===M.major?"":'<span class="bs-caret">'+this.options.template.caret+"</span>")+'</button><div class="'+V.MENU+" "+("4"===M.major?"":V.SHOW)+'">'+o+r+l+'<div class="inner '+V.SHOW+'" role="listbox" id="'+this.selectId+'" tabindex="-1" '+t+'><ul class="'+V.MENU+" inner "+("4"===M.major?V.SHOW:"")+'" role="presentation"></ul></div>'+a+"</div></div>",P(n)},setPositionData:function(){this.selectpicker.view.canHighlight=[],this.selectpicker.view.size=0,this.selectpicker.view.firstHighlightIndex=!1;for(var e=0;e<this.selectpicker.current.data.length;e++){var t=this.selectpicker.current.data[e],i=!0;"divider"===t.type?(i=!1,t.height=this.sizeInfo.dividerHeight):"optgroup-label"===t.type?(i=!1,t.height=this.sizeInfo.dropdownHeaderHeight):t.height=this.sizeInfo.liHeight,t.disabled&&(i=!1),this.selectpicker.view.canHighlight.push(i),i&&(this.selectpicker.view.size++,t.posinset=this.selectpicker.view.size,!1===this.selectpicker.view.firstHighlightIndex&&(this.selectpicker.view.firstHighlightIndex=e)),t.position=(0===e?0:this.selectpicker.current.data[e-1].position)+t.height}},isVirtual:function(){return!1!==this.options.virtualScroll&&this.selectpicker.main.elements.length>=this.options.virtualScroll||!0===this.options.virtualScroll},createView:function(N,e,t){var A,L,D=this,i=0,H=[];if(this.selectpicker.isSearching=N,this.selectpicker.current=N?this.selectpicker.search:this.selectpicker.main,this.setPositionData(),e)if(t)i=this.$menuInner[0].scrollTop;else if(!D.multiple){var s=D.$element[0],n=(s.options[s.selectedIndex]||{}).liIndex;if("number"==typeof n&&!1!==D.options.size){var o=D.selectpicker.main.data[n],r=o&&o.position;r&&(i=r-(D.sizeInfo.menuInnerHeight+D.sizeInfo.liHeight)/2)}}function l(e,t){var i,s,n,o,r,l,a,c,d=D.selectpicker.current.elements.length,h=[],p=!0,u=D.isVirtual();D.selectpicker.view.scrollTop=e,i=Math.ceil(D.sizeInfo.menuInnerHeight/D.sizeInfo.liHeight*1.5),s=Math.round(d/i)||1;for(var f=0;f<s;f++){var m=(f+1)*i;if(f===s-1&&(m=d),h[f]=[f*i+(f?1:0),m],!d)break;void 0===r&&e-1<=D.selectpicker.current.data[m-1].position-D.sizeInfo.menuInnerHeight&&(r=f)}if(void 0===r&&(r=0),l=[D.selectpicker.view.position0,D.selectpicker.view.position1],n=Math.max(0,r-1),o=Math.min(s-1,r+1),D.selectpicker.view.position0=!1===u?0:Math.max(0,h[n][0])||0,D.selectpicker.view.position1=!1===u?d:Math.min(d,h[o][1])||0,a=l[0]!==D.selectpicker.view.position0||l[1]!==D.selectpicker.view.position1,void 0!==D.activeIndex&&(L=D.selectpicker.main.elements[D.prevActiveIndex],H=D.selectpicker.main.elements[D.activeIndex],A=D.selectpicker.main.elements[D.selectedIndex],t&&(D.activeIndex!==D.selectedIndex&&D.defocusItem(H),D.activeIndex=void 0),D.activeIndex&&D.activeIndex!==D.selectedIndex&&D.defocusItem(A)),void 0!==D.prevActiveIndex&&D.prevActiveIndex!==D.activeIndex&&D.prevActiveIndex!==D.selectedIndex&&D.defocusItem(L),(t||a)&&(c=D.selectpicker.view.visibleElements?D.selectpicker.view.visibleElements.slice():[],D.selectpicker.view.visibleElements=!1===u?D.selectpicker.current.elements:D.selectpicker.current.elements.slice(D.selectpicker.view.position0,D.selectpicker.view.position1),D.setOptionStatus(),(N||!1===u&&t)&&(p=!function(e,i){return e.length===i.length&&e.every(function(e,t){return e===i[t]})}(c,D.selectpicker.view.visibleElements)),(t||!0===u)&&p)){var v,g,b=D.$menuInner[0],w=document.createDocumentFragment(),I=b.firstChild.cloneNode(!1),x=D.selectpicker.view.visibleElements,k=[];b.replaceChild(I,b.firstChild);f=0;for(var y=x.length;f<y;f++){var $,S,E=x[f];D.options.sanitize&&($=E.lastChild)&&(S=D.selectpicker.current.data[f+D.selectpicker.view.position0])&&S.content&&!S.sanitized&&(k.push($),S.sanitized=!0),w.appendChild(E)}if(D.options.sanitize&&k.length&&W(k,D.options.whiteList,D.options.sanitizeFn),!0===u?(v=0===D.selectpicker.view.position0?0:D.selectpicker.current.data[D.selectpicker.view.position0-1].position,g=D.selectpicker.view.position1>d-1?0:D.selectpicker.current.data[d-1].position-D.selectpicker.current.data[D.selectpicker.view.position1-1].position,b.firstChild.style.marginTop=v+"px",b.firstChild.style.marginBottom=g+"px"):(b.firstChild.style.marginTop=0,b.firstChild.style.marginBottom=0),b.firstChild.appendChild(w),!0===u&&D.sizeInfo.hasScrollBar){var C=b.firstChild.offsetWidth;if(t&&C<D.sizeInfo.menuInnerInnerWidth&&D.sizeInfo.totalMenuWidth>D.sizeInfo.selectWidth)b.firstChild.style.minWidth=D.sizeInfo.menuInnerInnerWidth+"px";else if(C>D.sizeInfo.menuInnerInnerWidth){D.$menu[0].style.minWidth=0;var O=b.firstChild.offsetWidth;O>D.sizeInfo.menuInnerInnerWidth&&(D.sizeInfo.menuInnerInnerWidth=O,b.firstChild.style.minWidth=D.sizeInfo.menuInnerInnerWidth+"px"),D.$menu[0].style.minWidth=""}}}if(D.prevActiveIndex=D.activeIndex,D.options.liveSearch){if(N&&t){var z,T=0;D.selectpicker.view.canHighlight[T]||(T=1+D.selectpicker.view.canHighlight.slice(1).indexOf(!0)),z=D.selectpicker.view.visibleElements[T],D.defocusItem(D.selectpicker.view.currentActive),D.activeIndex=(D.selectpicker.current.data[T]||{}).index,D.focusItem(z)}}else D.$menuInner.trigger("focus")}l(i,!0),this.$menuInner.off("scroll.createView").on("scroll.createView",function(e,t){D.noScroll||l(this.scrollTop,t),D.noScroll=!1}),P(window).off("resize"+j+"."+this.selectId+".createView").on("resize"+j+"."+this.selectId+".createView",function(){D.$newElement.hasClass(V.SHOW)&&l(D.$menuInner[0].scrollTop)})},focusItem:function(e,t,i){if(e){t=t||this.selectpicker.main.data[this.activeIndex];var s=e.firstChild;s&&(s.setAttribute("aria-setsize",this.selectpicker.view.size),s.setAttribute("aria-posinset",t.posinset),!0!==i&&(this.focusedParent.setAttribute("aria-activedescendant",s.id),e.classList.add("active"),s.classList.add("active")))}},defocusItem:function(e){e&&(e.classList.remove("active"),e.firstChild&&e.firstChild.classList.remove("active"))},setPlaceholder:function(){var e=this,t=!1;if(this.options.title&&!this.multiple){this.selectpicker.view.titleOption||(this.selectpicker.view.titleOption=document.createElement("option")),t=!0;var i=this.$element[0],s=!1,n=!this.selectpicker.view.titleOption.parentNode,o=i.selectedIndex,r=i.options[o],l=window.performance&&window.performance.getEntriesByType("navigation"),a=l&&l.length?"back_forward"!==l[0].type:2!==window.performance.navigation.type;n&&(this.selectpicker.view.titleOption.className="bs-title-option",this.selectpicker.view.titleOption.value="",s=!r||0===o&&!1===r.defaultSelected&&void 0===this.$element.data("selected")),!n&&0===this.selectpicker.view.titleOption.index||i.insertBefore(this.selectpicker.view.titleOption,i.firstChild),s&&a?i.selectedIndex=0:"complete"!==document.readyState&&window.addEventListener("pageshow",function(){e.selectpicker.view.displayedValue!==i.value&&e.render()})}return t},buildData:function(){var p=':not([hidden]):not([data-hidden="true"])',u=[],f=0,m=this.setPlaceholder()?1:0;this.options.hideDisabled&&(p+=":not(:disabled)");var e=this.$element[0].querySelectorAll("select > *"+p);function v(e){var t=u[u.length-1];t&&"divider"===t.type&&(t.optID||e.optID)||((e=e||{}).type="divider",u.push(e))}function g(e,t){if((t=t||{}).divider="true"===e.getAttribute("data-divider"),t.divider)v({optID:t.optID});else{var i=u.length,s=e.style.cssText,n=s?S(s):"",o=(e.className||"")+(t.optgroupClass||"");t.optID&&(o="opt "+o),t.optionClass=o.trim(),t.inlineStyle=n,t.text=e.textContent,t.content=e.getAttribute("data-content"),t.tokens=e.getAttribute("data-tokens"),t.subtext=e.getAttribute("data-subtext"),t.icon=e.getAttribute("data-icon"),e.liIndex=i,t.display=t.content||t.text,t.type="option",t.index=i,t.option=e,t.selected=!!e.selected,t.disabled=t.disabled||!!e.disabled,u.push(t)}}function t(e,t){var i=t[e],s=!(e-1<m)&&t[e-1],n=t[e+1],o=i.querySelectorAll("option"+p);if(o.length){var r,l,a={display:S(i.label),subtext:i.getAttribute("data-subtext"),icon:i.getAttribute("data-icon"),type:"optgroup-label",optgroupClass:" "+(i.className||"")};f++,s&&v({optID:f}),a.optID=f,u.push(a);for(var c=0,d=o.length;c<d;c++){var h=o[c];0===c&&(l=(r=u.length-1)+d),g(h,{headerIndex:r,lastIndex:l,optID:a.optID,optgroupClass:a.optgroupClass,disabled:i.disabled})}n&&v({optID:f})}}for(var i=e.length,s=m;s<i;s++){var n=e[s];"OPTGROUP"!==n.tagName?g(n,{}):t(s,e)}this.selectpicker.main.data=this.selectpicker.current.data=u},buildList:function(){var s=this,e=this.selectpicker.main.data,n=[],o=0;function t(e){var t,i=0;switch(e.type){case"divider":t=K.li(!1,V.DIVIDER,e.optID?e.optID+"div":void 0);break;case"option":(t=K.li(K.a(K.text.call(s,e),e.optionClass,e.inlineStyle),"",e.optID)).firstChild&&(t.firstChild.id=s.selectId+"-"+e.index);break;case"optgroup-label":t=K.li(K.label.call(s,e),"dropdown-header"+e.optgroupClass,e.optID)}e.element=t,n.push(t),e.display&&(i+=e.display.length),e.subtext&&(i+=e.subtext.length),e.icon&&(i+=1),o<i&&(o=i,s.selectpicker.view.widestOption=n[n.length-1])}!s.options.showTick&&!s.multiple||_.checkMark.parentNode||(_.checkMark.className=this.options.iconBase+" "+s.options.tickIcon+" check-mark",_.a.appendChild(_.checkMark));for(var i=e.length,r=0;r<i;r++){t(e[r])}this.selectpicker.main.elements=this.selectpicker.current.elements=n},findLis:function(){return this.$menuInner.find(".inner > li")},render:function(){var e,t=this,i=this.$element[0],s=this.setPlaceholder()&&0===i.selectedIndex,n=O(i,this.options.hideDisabled),o=n.length,r=this.$button[0],l=r.querySelector(".filter-option-inner-inner"),a=document.createTextNode(this.options.multipleSeparator),c=_.fragment.cloneNode(!1),d=!1;if(r.classList.toggle("bs-placeholder",t.multiple?!o:!z(i,n)),t.multiple||1!==n.length||(t.selectpicker.view.displayedValue=z(i,n)),"static"===this.options.selectedTextFormat)c=K.text.call(this,{text:this.options.title},!0);else if(!1===(this.multiple&&-1!==this.options.selectedTextFormat.indexOf("count")&&1<o&&(1<(e=this.options.selectedTextFormat.split(">")).length&&o>e[1]||1===e.length&&2<=o))){if(!s){for(var h=0;h<o&&h<50;h++){var p=n[h],u=this.selectpicker.main.data[p.liIndex],f={};this.multiple&&0<h&&c.appendChild(a.cloneNode(!1)),p.title?f.text=p.title:u&&(u.content&&t.options.showContent?(f.content=u.content.toString(),d=!0):(t.options.showIcon&&(f.icon=u.icon),t.options.showSubtext&&!t.multiple&&u.subtext&&(f.subtext=" "+u.subtext),f.text=p.textContent.trim())),c.appendChild(K.text.call(this,f,!0))}49<o&&c.appendChild(document.createTextNode("..."))}}else{var m=':not([hidden]):not([data-hidden="true"]):not([data-divider="true"])';this.options.hideDisabled&&(m+=":not(:disabled)");var v=this.$element[0].querySelectorAll("select > option"+m+", optgroup"+m+" option"+m).length,g="function"==typeof this.options.countSelectedText?this.options.countSelectedText(o,v):this.options.countSelectedText;c=K.text.call(this,{text:g.replace("{0}",o.toString()).replace("{1}",v.toString())},!0)}if(null==this.options.title&&(this.options.title=this.$element.attr("title")),c.childNodes.length||(c=K.text.call(this,{text:void 0!==this.options.title?this.options.title:this.options.noneSelectedText},!0)),r.title=c.textContent.replace(/<[^>]*>?/g,"").trim(),this.options.sanitize&&d&&W([c],t.options.whiteList,t.options.sanitizeFn),l.innerHTML="",l.appendChild(c),M.major<4&&this.$newElement[0].classList.contains("bs3-has-addon")){var b=r.querySelector(".filter-expand"),w=l.cloneNode(!0);w.className="filter-expand",b?r.replaceChild(w,b):r.appendChild(w)}this.$element.trigger("rendered"+j)},setStyle:function(e,t){var i,s=this.$button[0],n=this.$newElement[0],o=this.options.style.trim();this.$element.attr("class")&&this.$newElement.addClass(this.$element.attr("class").replace(/selectpicker|mobile-device|bs-select-hidden|validate\[.*\]/gi,"")),M.major<4&&(n.classList.add("bs3"),n.parentNode.classList&&n.parentNode.classList.contains("input-group")&&(n.previousElementSibling||n.nextElementSibling)&&(n.previousElementSibling||n.nextElementSibling).classList.contains("input-group-addon")&&n.classList.add("bs3-has-addon")),i=e?e.trim():o,"add"==t?i&&s.classList.add.apply(s.classList,i.split(" ")):"remove"==t?i&&s.classList.remove.apply(s.classList,i.split(" ")):(o&&s.classList.remove.apply(s.classList,o.split(" ")),i&&s.classList.add.apply(s.classList,i.split(" ")))},liHeight:function(e){if(e||!1!==this.options.size&&!Object.keys(this.sizeInfo).length){var t,i=_.div.cloneNode(!1),s=_.div.cloneNode(!1),n=_.div.cloneNode(!1),o=document.createElement("ul"),r=_.li.cloneNode(!1),l=_.li.cloneNode(!1),a=_.a.cloneNode(!1),c=_.span.cloneNode(!1),d=this.options.header&&0<this.$menu.find("."+V.POPOVERHEADER).length?this.$menu.find("."+V.POPOVERHEADER)[0].cloneNode(!0):null,h=this.options.liveSearch?_.div.cloneNode(!1):null,p=this.options.actionsBox&&this.multiple&&0<this.$menu.find(".bs-actionsbox").length?this.$menu.find(".bs-actionsbox")[0].cloneNode(!0):null,u=this.options.doneButton&&this.multiple&&0<this.$menu.find(".bs-donebutton").length?this.$menu.find(".bs-donebutton")[0].cloneNode(!0):null,f=this.$element.find("option")[0];if(this.sizeInfo.selectWidth=this.$newElement[0].offsetWidth,c.className="text",a.className="dropdown-item "+(f?f.className:""),i.className=this.$menu[0].parentNode.className+" "+V.SHOW,i.style.width=0,"auto"===this.options.width&&(s.style.minWidth=0),s.className=V.MENU+" "+V.SHOW,n.className="inner "+V.SHOW,o.className=V.MENU+" inner "+("4"===M.major?V.SHOW:""),r.className=V.DIVIDER,l.className="dropdown-header",c.appendChild(document.createTextNode("\u200b")),this.selectpicker.current.data.length)for(var m=0;m<this.selectpicker.current.data.length;m++){var v=this.selectpicker.current.data[m];if("option"===v.type){t=v.element;break}}else t=_.li.cloneNode(!1),a.appendChild(c),t.appendChild(a);if(l.appendChild(c.cloneNode(!0)),this.selectpicker.view.widestOption&&o.appendChild(this.selectpicker.view.widestOption.cloneNode(!0)),o.appendChild(t),o.appendChild(r),o.appendChild(l),d&&s.appendChild(d),h){var g=document.createElement("input");h.className="bs-searchbox",g.className="form-control",h.appendChild(g),s.appendChild(h)}p&&s.appendChild(p),n.appendChild(o),s.appendChild(n),u&&s.appendChild(u),i.appendChild(s),document.body.appendChild(i);var b,w=t.offsetHeight,I=l?l.offsetHeight:0,x=d?d.offsetHeight:0,k=h?h.offsetHeight:0,y=p?p.offsetHeight:0,$=u?u.offsetHeight:0,S=P(r).outerHeight(!0),E=!!window.getComputedStyle&&window.getComputedStyle(s),C=s.offsetWidth,O=E?null:P(s),z={vert:N(E?E.paddingTop:O.css("paddingTop"))+N(E?E.paddingBottom:O.css("paddingBottom"))+N(E?E.borderTopWidth:O.css("borderTopWidth"))+N(E?E.borderBottomWidth:O.css("borderBottomWidth")),horiz:N(E?E.paddingLeft:O.css("paddingLeft"))+N(E?E.paddingRight:O.css("paddingRight"))+N(E?E.borderLeftWidth:O.css("borderLeftWidth"))+N(E?E.borderRightWidth:O.css("borderRightWidth"))},T={vert:z.vert+N(E?E.marginTop:O.css("marginTop"))+N(E?E.marginBottom:O.css("marginBottom"))+2,horiz:z.horiz+N(E?E.marginLeft:O.css("marginLeft"))+N(E?E.marginRight:O.css("marginRight"))+2};n.style.overflowY="scroll",b=s.offsetWidth-C,document.body.removeChild(i),this.sizeInfo.liHeight=w,this.sizeInfo.dropdownHeaderHeight=I,this.sizeInfo.headerHeight=x,this.sizeInfo.searchHeight=k,this.sizeInfo.actionsHeight=y,this.sizeInfo.doneButtonHeight=$,this.sizeInfo.dividerHeight=S,this.sizeInfo.menuPadding=z,this.sizeInfo.menuExtras=T,this.sizeInfo.menuWidth=C,this.sizeInfo.menuInnerInnerWidth=C-z.horiz,this.sizeInfo.totalMenuWidth=this.sizeInfo.menuWidth,this.sizeInfo.scrollBarWidth=b,this.sizeInfo.selectHeight=this.$newElement[0].offsetHeight,this.setPositionData()}},getSelectPosition:function(){var e,t=P(window),i=this.$newElement.offset(),s=P(this.options.container);this.options.container&&s.length&&!s.is("body")?((e=s.offset()).top+=parseInt(s.css("borderTopWidth")),e.left+=parseInt(s.css("borderLeftWidth"))):e={top:0,left:0};var n=this.options.windowPadding;this.sizeInfo.selectOffsetTop=i.top-e.top-t.scrollTop(),this.sizeInfo.selectOffsetBot=t.height()-this.sizeInfo.selectOffsetTop-this.sizeInfo.selectHeight-e.top-n[2],this.sizeInfo.selectOffsetLeft=i.left-e.left-t.scrollLeft(),this.sizeInfo.selectOffsetRight=t.width()-this.sizeInfo.selectOffsetLeft-this.sizeInfo.selectWidth-e.left-n[1],this.sizeInfo.selectOffsetTop-=n[0],this.sizeInfo.selectOffsetLeft-=n[3]},setMenuSize:function(e){this.getSelectPosition();var t,i,s,n,o,r,l,a,c=this.sizeInfo.selectWidth,d=this.sizeInfo.liHeight,h=this.sizeInfo.headerHeight,p=this.sizeInfo.searchHeight,u=this.sizeInfo.actionsHeight,f=this.sizeInfo.doneButtonHeight,m=this.sizeInfo.dividerHeight,v=this.sizeInfo.menuPadding,g=0;if(this.options.dropupAuto&&(l=d*this.selectpicker.current.elements.length+v.vert,a=this.sizeInfo.selectOffsetTop-this.sizeInfo.selectOffsetBot>this.sizeInfo.menuExtras.vert&&l+this.sizeInfo.menuExtras.vert+50>this.sizeInfo.selectOffsetBot,!0===this.selectpicker.isSearching&&(a=this.selectpicker.dropup),this.$newElement.toggleClass(V.DROPUP,a),this.selectpicker.dropup=a),"auto"===this.options.size)n=3<this.selectpicker.current.elements.length?3*this.sizeInfo.liHeight+this.sizeInfo.menuExtras.vert-2:0,i=this.sizeInfo.selectOffsetBot-this.sizeInfo.menuExtras.vert,s=n+h+p+u+f,r=Math.max(n-v.vert,0),this.$newElement.hasClass(V.DROPUP)&&(i=this.sizeInfo.selectOffsetTop-this.sizeInfo.menuExtras.vert),t=(o=i)-h-p-u-f-v.vert;else if(this.options.size&&"auto"!=this.options.size&&this.selectpicker.current.elements.length>this.options.size){for(var b=0;b<this.options.size;b++)"divider"===this.selectpicker.current.data[b].type&&g++;t=(i=d*this.options.size+g*m+v.vert)-v.vert,o=i+h+p+u+f,s=r=""}this.$menu.css({"max-height":o+"px",overflow:"hidden","min-height":s+"px"}),this.$menuInner.css({"max-height":t+"px","overflow-y":"auto","min-height":r+"px"}),this.sizeInfo.menuInnerHeight=Math.max(t,1),this.selectpicker.current.data.length&&this.selectpicker.current.data[this.selectpicker.current.data.length-1].position>this.sizeInfo.menuInnerHeight&&(this.sizeInfo.hasScrollBar=!0,this.sizeInfo.totalMenuWidth=this.sizeInfo.menuWidth+this.sizeInfo.scrollBarWidth),"auto"===this.options.dropdownAlignRight&&this.$menu.toggleClass(V.MENURIGHT,this.sizeInfo.selectOffsetLeft>this.sizeInfo.selectOffsetRight&&this.sizeInfo.selectOffsetRight<this.sizeInfo.totalMenuWidth-c),this.dropdown&&this.dropdown._popper&&this.dropdown._popper.update()},setSize:function(e){if(this.liHeight(e),this.options.header&&this.$menu.css("padding-top",0),!1!==this.options.size){var t=this,i=P(window);this.setMenuSize(),this.options.liveSearch&&this.$searchbox.off("input.setMenuSize propertychange.setMenuSize").on("input.setMenuSize propertychange.setMenuSize",function(){return t.setMenuSize()}),"auto"===this.options.size?i.off("resize"+j+"."+this.selectId+".setMenuSize scroll"+j+"."+this.selectId+".setMenuSize").on("resize"+j+"."+this.selectId+".setMenuSize scroll"+j+"."+this.selectId+".setMenuSize",function(){return t.setMenuSize()}):this.options.size&&"auto"!=this.options.size&&this.selectpicker.current.elements.length>this.options.size&&i.off("resize"+j+"."+this.selectId+".setMenuSize scroll"+j+"."+this.selectId+".setMenuSize")}this.createView(!1,!0,e)},setWidth:function(){var i=this;"auto"===this.options.width?requestAnimationFrame(function(){i.$menu.css("min-width","0"),i.$element.on("loaded"+j,function(){i.liHeight(),i.setMenuSize();var e=i.$newElement.clone().appendTo("body"),t=e.css("width","auto").children("button").outerWidth();e.remove(),i.sizeInfo.selectWidth=Math.max(i.sizeInfo.totalMenuWidth,t),i.$newElement.css("width",i.sizeInfo.selectWidth+"px")})}):"fit"===this.options.width?(this.$menu.css("min-width",""),this.$newElement.css("width","").addClass("fit-width")):this.options.width?(this.$menu.css("min-width",""),this.$newElement.css("width",this.options.width)):(this.$menu.css("min-width",""),this.$newElement.css("width","")),this.$newElement.hasClass("fit-width")&&"fit"!==this.options.width&&this.$newElement[0].classList.remove("fit-width")},selectPosition:function(){this.$bsContainer=P('<div class="bs-container" />');function e(e){var t={},i=r.options.display||!!P.fn.dropdown.Constructor.Default&&P.fn.dropdown.Constructor.Default.display;r.$bsContainer.addClass(e.attr("class").replace(/form-control|fit-width/gi,"")).toggleClass(V.DROPUP,e.hasClass(V.DROPUP)),s=e.offset(),l.is("body")?n={top:0,left:0}:((n=l.offset()).top+=parseInt(l.css("borderTopWidth"))-l.scrollTop(),n.left+=parseInt(l.css("borderLeftWidth"))-l.scrollLeft()),o=e.hasClass(V.DROPUP)?0:e[0].offsetHeight,(M.major<4||"static"===i)&&(t.top=s.top-n.top+o,t.left=s.left-n.left),t.width=e[0].offsetWidth,r.$bsContainer.css(t)}var s,n,o,r=this,l=P(this.options.container);this.$button.on("click.bs.dropdown.data-api",function(){r.isDisabled()||(e(r.$newElement),r.$bsContainer.appendTo(r.options.container).toggleClass(V.SHOW,!r.$button.hasClass(V.SHOW)).append(r.$menu))}),P(window).off("resize"+j+"."+this.selectId+" scroll"+j+"."+this.selectId).on("resize"+j+"."+this.selectId+" scroll"+j+"."+this.selectId,function(){r.$newElement.hasClass(V.SHOW)&&e(r.$newElement)}),this.$element.on("hide"+j,function(){r.$menu.data("height",r.$menu.height()),r.$bsContainer.detach()})},setOptionStatus:function(e){var t=this;if(t.noScroll=!1,t.selectpicker.view.visibleElements&&t.selectpicker.view.visibleElements.length)for(var i=0;i<t.selectpicker.view.visibleElements.length;i++){var s=t.selectpicker.current.data[i+t.selectpicker.view.position0],n=s.option;n&&(!0!==e&&t.setDisabled(s.index,s.disabled),t.setSelected(s.index,n.selected))}},setSelected:function(e,t){var i,s,n=this.selectpicker.main.elements[e],o=this.selectpicker.main.data[e],r=void 0!==this.activeIndex,l=this.activeIndex===e||t&&!this.multiple&&!r;o.selected=t,s=n.firstChild,t&&(this.selectedIndex=e),n.classList.toggle("selected",t),l?(this.focusItem(n,o),this.selectpicker.view.currentActive=n,this.activeIndex=e):this.defocusItem(n),s&&(s.classList.toggle("selected",t),t?s.setAttribute("aria-selected",!0):this.multiple?s.setAttribute("aria-selected",!1):s.removeAttribute("aria-selected")),l||r||!t||void 0===this.prevActiveIndex||(i=this.selectpicker.main.elements[this.prevActiveIndex],this.defocusItem(i))},setDisabled:function(e,t){var i,s=this.selectpicker.main.elements[e];this.selectpicker.main.data[e].disabled=t,i=s.firstChild,s.classList.toggle(V.DISABLED,t),i&&("4"===M.major&&i.classList.toggle(V.DISABLED,t),t?(i.setAttribute("aria-disabled",t),i.setAttribute("tabindex",-1)):(i.removeAttribute("aria-disabled"),i.setAttribute("tabindex",0)))},isDisabled:function(){return this.$element[0].disabled},checkDisabled:function(){this.isDisabled()?(this.$newElement[0].classList.add(V.DISABLED),this.$button.addClass(V.DISABLED).attr("aria-disabled",!0)):this.$button[0].classList.contains(V.DISABLED)&&(this.$newElement[0].classList.remove(V.DISABLED),this.$button.removeClass(V.DISABLED).attr("aria-disabled",!1))},clickListener:function(){var C=this,t=P(document);function e(){C.options.liveSearch?C.$searchbox.trigger("focus"):C.$menuInner.trigger("focus")}function i(){C.dropdown&&C.dropdown._popper&&C.dropdown._popper.state.isCreated?e():requestAnimationFrame(i)}t.data("spaceSelect",!1),this.$button.on("keyup",function(e){/(32)/.test(e.keyCode.toString(10))&&t.data("spaceSelect")&&(e.preventDefault(),t.data("spaceSelect",!1))}),this.$newElement.on("show.bs.dropdown",function(){3<M.major&&!C.dropdown&&(C.dropdown=C.$button.data("bs.dropdown"),C.dropdown._menu=C.$menu[0])}),this.$button.on("click.bs.dropdown.data-api",function(){C.$newElement.hasClass(V.SHOW)||C.setSize()}),this.$element.on("shown"+j,function(){C.$menuInner[0].scrollTop!==C.selectpicker.view.scrollTop&&(C.$menuInner[0].scrollTop=C.selectpicker.view.scrollTop),3<M.major?requestAnimationFrame(i):e()}),this.$menuInner.on("mouseenter","li a",function(e){var t=this.parentElement,i=C.isVirtual()?C.selectpicker.view.position0:0,s=Array.prototype.indexOf.call(t.parentElement.children,t),n=C.selectpicker.current.data[s+i];C.focusItem(t,n,!0)}),this.$menuInner.on("click","li a",function(e,t){var i=P(this),s=C.$element[0],n=C.isVirtual()?C.selectpicker.view.position0:0,o=C.selectpicker.current.data[i.parent().index()+n],r=o.index,l=z(s),a=s.selectedIndex,c=s.options[a],d=!0;if(C.multiple&&1!==C.options.maxOptions&&e.stopPropagation(),e.preventDefault(),!C.isDisabled()&&!i.parent().hasClass(V.DISABLED)){var h=o.option,p=P(h),u=h.selected,f=p.parent("optgroup"),m=f.find("option"),v=C.options.maxOptions,g=f.data("maxOptions")||!1;if(r===C.activeIndex&&(t=!0),t||(C.prevActiveIndex=C.activeIndex,C.activeIndex=void 0),C.multiple){if(h.selected=!u,C.setSelected(r,!u),C.focusedParent.focus(),!1!==v||!1!==g){var b=v<O(s).length,w=g<f.find("option:selected").length;if(v&&b||g&&w)if(v&&1==v)s.selectedIndex=-1,h.selected=!0,C.setOptionStatus(!0);else if(g&&1==g){for(var I=0;I<m.length;I++){var x=m[I];x.selected=!1,C.setSelected(x.liIndex,!1)}h.selected=!0,C.setSelected(r,!0)}else{var k="string"==typeof C.options.maxOptionsText?[C.options.maxOptionsText,C.options.maxOptionsText]:C.options.maxOptionsText,y="function"==typeof k?k(v,g):k,$=y[0].replace("{n}",v),S=y[1].replace("{n}",g),E=P('<div class="notify"></div>');y[2]&&($=$.replace("{var}",y[2][1<v?0:1]),S=S.replace("{var}",y[2][1<g?0:1])),h.selected=!1,C.$menu.append(E),v&&b&&(E.append(P("<div>"+$+"</div>")),d=!1,C.$element.trigger("maxReached"+j)),g&&w&&(E.append(P("<div>"+S+"</div>")),d=!1,C.$element.trigger("maxReachedGrp"+j)),setTimeout(function(){C.setSelected(r,!1)},10),E[0].classList.add("fadeOut"),setTimeout(function(){E.remove()},1050)}}}else c&&(c.selected=!1),h.selected=!0,C.setSelected(r,!0);!C.multiple||C.multiple&&1===C.options.maxOptions?C.$button.trigger("focus"):C.options.liveSearch&&C.$searchbox.trigger("focus"),d&&(!C.multiple&&a===s.selectedIndex||(T=[h.index,p.prop("selected"),l],C.$element.triggerNative("change")))}}),this.$menu.on("click","li."+V.DISABLED+" a, ."+V.POPOVERHEADER+", ."+V.POPOVERHEADER+" :not(.close)",function(e){e.currentTarget==this&&(e.preventDefault(),e.stopPropagation(),C.options.liveSearch&&!P(e.target).hasClass("close")?C.$searchbox.trigger("focus"):C.$button.trigger("focus"))}),this.$menuInner.on("click",".divider, .dropdown-header",function(e){e.preventDefault(),e.stopPropagation(),C.options.liveSearch?C.$searchbox.trigger("focus"):C.$button.trigger("focus")}),this.$menu.on("click","."+V.POPOVERHEADER+" .close",function(){C.$button.trigger("click")}),this.$searchbox.on("click",function(e){e.stopPropagation()}),this.$menu.on("click",".actions-btn",function(e){C.options.liveSearch?C.$searchbox.trigger("focus"):C.$button.trigger("focus"),e.preventDefault(),e.stopPropagation(),P(this).hasClass("bs-select-all")?C.selectAll():C.deselectAll()}),this.$button.on("focus"+j,function(e){var t=C.$element[0].getAttribute("tabindex");void 0!==t&&e.originalEvent&&e.originalEvent.isTrusted&&(this.setAttribute("tabindex",t),C.$element[0].setAttribute("tabindex",-1),C.selectpicker.view.tabindex=t)}).on("blur"+j,function(e){void 0!==C.selectpicker.view.tabindex&&e.originalEvent&&e.originalEvent.isTrusted&&(C.$element[0].setAttribute("tabindex",C.selectpicker.view.tabindex),this.setAttribute("tabindex",-1),C.selectpicker.view.tabindex=void 0)}),this.$element.on("change"+j,function(){C.render(),C.$element.trigger("changed"+j,T),T=null}).on("focus"+j,function(){C.options.mobile||C.$button[0].focus()})},liveSearchListener:function(){var u=this;this.$button.on("click.bs.dropdown.data-api",function(){u.$searchbox.val()&&(u.$searchbox.val(""),u.selectpicker.search.previousValue=void 0)}),this.$searchbox.on("click.bs.dropdown.data-api focus.bs.dropdown.data-api touchend.bs.dropdown.data-api",function(e){e.stopPropagation()}),this.$searchbox.on("input propertychange",function(){var e=u.$searchbox[0].value;if(u.selectpicker.search.elements=[],u.selectpicker.search.data=[],e){var t=[],i=e.toUpperCase(),s={},n=[],o=u._searchStyle(),r=u.options.liveSearchNormalize;r&&(i=w(i));for(var l=0;l<u.selectpicker.main.data.length;l++){var a=u.selectpicker.main.data[l];s[l]||(s[l]=k(a,i,o,r)),s[l]&&void 0!==a.headerIndex&&-1===n.indexOf(a.headerIndex)&&(0<a.headerIndex&&(s[a.headerIndex-1]=!0,n.push(a.headerIndex-1)),s[a.headerIndex]=!0,n.push(a.headerIndex),s[a.lastIndex+1]=!0),s[l]&&"optgroup-label"!==a.type&&n.push(l)}l=0;for(var c=n.length;l<c;l++){var d=n[l],h=n[l-1],p=(a=u.selectpicker.main.data[d],u.selectpicker.main.data[h]);("divider"!==a.type||"divider"===a.type&&p&&"divider"!==p.type&&c-1!==l)&&(u.selectpicker.search.data.push(a),t.push(u.selectpicker.main.elements[d]))}u.activeIndex=void 0,u.noScroll=!0,u.$menuInner.scrollTop(0),u.selectpicker.search.elements=t,u.createView(!0),function(e,t){e.length||(_.noResults.innerHTML=this.options.noneResultsText.replace("{0}",'"'+S(t)+'"'),this.$menuInner[0].firstChild.appendChild(_.noResults))}.call(u,t,e)}else u.selectpicker.search.previousValue&&(u.$menuInner.scrollTop(0),u.createView(!1));u.selectpicker.search.previousValue=e})},_searchStyle:function(){return this.options.liveSearchStyle||"contains"},val:function(e){var t=this.$element[0];if(void 0===e)return this.$element.val();var i=z(t);if(T=[null,null,i],this.$element.val(e).trigger("changed"+j,T),this.$newElement.hasClass(V.SHOW))if(this.multiple)this.setOptionStatus(!0);else{var s=(t.options[t.selectedIndex]||{}).liIndex;"number"==typeof s&&(this.setSelected(this.selectedIndex,!1),this.setSelected(s,!0))}return this.render(),T=null,this.$element},changeAll:function(e){if(this.multiple){void 0===e&&(e=!0);var t=this.$element[0],i=0,s=0,n=z(t);t.classList.add("bs-select-hidden");for(var o=0,r=this.selectpicker.current.data,l=r.length;o<l;o++){var a=r[o],c=a.option;c&&!a.disabled&&"divider"!==a.type&&(a.selected&&i++,!0===(c.selected=e)&&s++)}t.classList.remove("bs-select-hidden"),i!==s&&(this.setOptionStatus(),T=[null,null,n],this.$element.triggerNative("change"))}},selectAll:function(){return this.changeAll(!0)},deselectAll:function(){return this.changeAll(!1)},toggle:function(e){(e=e||window.event)&&e.stopPropagation(),this.$button.trigger("click.bs.dropdown.data-api")},keydown:function(e){var t,i,s,n,o,r=P(this),l=r.hasClass("dropdown-toggle"),a=(l?r.closest(".dropdown"):r.closest(F.MENU)).data("this"),c=a.findLis(),d=!1,h=e.which===H&&!l&&!a.options.selectOnTab,p=G.test(e.which)||h,u=a.$menuInner[0].scrollTop,f=!0===a.isVirtual()?a.selectpicker.view.position0:0;if(!(112<=e.which&&e.which<=123))if(!(i=a.$newElement.hasClass(V.SHOW))&&(p||48<=e.which&&e.which<=57||96<=e.which&&e.which<=105||65<=e.which&&e.which<=90)&&(a.$button.trigger("click.bs.dropdown.data-api"),a.options.liveSearch))a.$searchbox.trigger("focus");else{if(e.which===A&&i&&(e.preventDefault(),a.$button.trigger("click.bs.dropdown.data-api").trigger("focus")),p){if(!c.length)return;-1!==(t=(s=a.selectpicker.main.elements[a.activeIndex])?Array.prototype.indexOf.call(s.parentElement.children,s):-1)&&a.defocusItem(s),e.which===B?(-1!==t&&t--,t+f<0&&(t+=c.length),a.selectpicker.view.canHighlight[t+f]||-1===(t=a.selectpicker.view.canHighlight.slice(0,t+f).lastIndexOf(!0)-f)&&(t=c.length-1)):e.which!==R&&!h||(++t+f>=a.selectpicker.view.canHighlight.length&&(t=a.selectpicker.view.firstHighlightIndex),a.selectpicker.view.canHighlight[t+f]||(t=t+1+a.selectpicker.view.canHighlight.slice(t+f+1).indexOf(!0))),e.preventDefault();var m=f+t;e.which===B?0===f&&t===c.length-1?(a.$menuInner[0].scrollTop=a.$menuInner[0].scrollHeight,m=a.selectpicker.current.elements.length-1):d=(o=(n=a.selectpicker.current.data[m]).position-n.height)<u:e.which!==R&&!h||(t===a.selectpicker.view.firstHighlightIndex?(a.$menuInner[0].scrollTop=0,m=a.selectpicker.view.firstHighlightIndex):d=u<(o=(n=a.selectpicker.current.data[m]).position-a.sizeInfo.menuInnerHeight)),s=a.selectpicker.current.elements[m],a.activeIndex=a.selectpicker.current.data[m].index,a.focusItem(s),a.selectpicker.view.currentActive=s,d&&(a.$menuInner[0].scrollTop=o),a.options.liveSearch?a.$searchbox.trigger("focus"):r.trigger("focus")}else if(!r.is("input")&&!q.test(e.which)||e.which===D&&a.selectpicker.keydown.keyHistory){var v,g,b=[];e.preventDefault(),a.selectpicker.keydown.keyHistory+=C[e.which],a.selectpicker.keydown.resetKeyHistory.cancel&&clearTimeout(a.selectpicker.keydown.resetKeyHistory.cancel),a.selectpicker.keydown.resetKeyHistory.cancel=a.selectpicker.keydown.resetKeyHistory.start(),g=a.selectpicker.keydown.keyHistory,/^(.)\1+$/.test(g)&&(g=g.charAt(0));for(var w=0;w<a.selectpicker.current.data.length;w++){var I=a.selectpicker.current.data[w];k(I,g,"startsWith",!0)&&a.selectpicker.view.canHighlight[w]&&b.push(I.index)}if(b.length){var x=0;c.removeClass("active").find("a").removeClass("active"),1===g.length&&(-1===(x=b.indexOf(a.activeIndex))||x===b.length-1?x=0:x++),v=b[x],d=0<u-(n=a.selectpicker.main.data[v]).position?(o=n.position-n.height,!0):(o=n.position-a.sizeInfo.menuInnerHeight,n.position>u+a.sizeInfo.menuInnerHeight),s=a.selectpicker.main.elements[v],a.activeIndex=b[x],a.focusItem(s),s&&s.firstChild.focus(),d&&(a.$menuInner[0].scrollTop=o),r.trigger("focus")}}i&&(e.which===D&&!a.selectpicker.keydown.keyHistory||e.which===L||e.which===H&&a.options.selectOnTab)&&(e.which!==D&&e.preventDefault(),a.options.liveSearch&&e.which===D||(a.$menuInner.find(".active a").trigger("click",!0),r.trigger("focus"),a.options.liveSearch||(e.preventDefault(),P(document).data("spaceSelect",!0))))}},mobile:function(){this.options.mobile=!0,this.$element[0].classList.add("mobile-device")},refresh:function(){var e=P.extend({},this.options,this.$element.data());this.options=e,this.checkDisabled(),this.buildData(),this.setStyle(),this.render(),this.buildList(),this.setWidth(),this.setSize(!0),this.$element.trigger("refreshed"+j)},hide:function(){this.$newElement.hide()},show:function(){this.$newElement.show()},remove:function(){this.$newElement.remove(),this.$element.remove()},destroy:function(){this.$newElement.before(this.$element).remove(),this.$bsContainer?this.$bsContainer.remove():this.$menu.remove(),this.selectpicker.view.titleOption&&this.selectpicker.view.titleOption.parentNode&&this.selectpicker.view.titleOption.parentNode.removeChild(this.selectpicker.view.titleOption),this.$element.off(j).removeData("selectpicker").removeClass("bs-select-hidden selectpicker"),P(window).off(j+"."+this.selectId)}};var J=P.fn.selectpicker;function Q(){if(P.fn.dropdown)return(P.fn.dropdown.Constructor._dataApiKeydownHandler||P.fn.dropdown.Constructor.prototype.keydown).apply(this,arguments)}P.fn.selectpicker=Z,P.fn.selectpicker.Constructor=Y,P.fn.selectpicker.noConflict=function(){return P.fn.selectpicker=J,this},P(document).off("keydown.bs.dropdown.data-api").on("keydown.bs.dropdown.data-api",':not(.bootstrap-select) > [data-toggle="dropdown"]',Q).on("keydown.bs.dropdown.data-api",":not(.bootstrap-select) > .dropdown-menu",Q).on("keydown"+j,'.bootstrap-select [data-toggle="dropdown"], .bootstrap-select [role="listbox"], .bootstrap-select .bs-searchbox input',Y.prototype.keydown).on("focusin.modal",'.bootstrap-select [data-toggle="dropdown"], .bootstrap-select [role="listbox"], .bootstrap-select .bs-searchbox input',function(e){e.stopPropagation()}),P(window).on("load"+j+".data-api",function(){P(".selectpicker").each(function(){var e=P(this);Z.call(e,e.data())})})}(e)});
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/bootstrap-table.min.css b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/bootstrap-table.min.css
new file mode 100644
index 0000000..7e150cf
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/bootstrap-table.min.css
@@ -0,0 +1,6 @@
+/**
+ * @author zhixin wen <wenzhixin2010@gmail.com>
+ * version: 1.19.1
+ * https://github.com/wenzhixin/bootstrap-table/
+ */
+.bootstrap-table .fixed-table-toolbar::after{content:"";display:block;clear:both}.bootstrap-table .fixed-table-toolbar .bs-bars,.bootstrap-table .fixed-table-toolbar .columns,.bootstrap-table .fixed-table-toolbar .search{position:relative;margin-top:10px;margin-bottom:10px}.bootstrap-table .fixed-table-toolbar .columns .btn-group>.btn-group{display:inline-block;margin-left:-1px!important}.bootstrap-table .fixed-table-toolbar .columns .btn-group>.btn-group>.btn{border-radius:0}.bootstrap-table .fixed-table-toolbar .columns .btn-group>.btn-group:first-child>.btn{border-top-left-radius:4px;border-bottom-left-radius:4px}.bootstrap-table .fixed-table-toolbar .columns .btn-group>.btn-group:last-child>.btn{border-top-right-radius:4px;border-bottom-right-radius:4px}.bootstrap-table .fixed-table-toolbar .columns .dropdown-menu{text-align:left;max-height:300px;overflow:auto;-ms-overflow-style:scrollbar;z-index:1001}.bootstrap-table .fixed-table-toolbar .columns label{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.428571429}.bootstrap-table .fixed-table-toolbar .columns-left{margin-right:5px}.bootstrap-table .fixed-table-toolbar .columns-right{margin-left:5px}.bootstrap-table .fixed-table-toolbar .pull-right .dropdown-menu{right:0;left:auto}.bootstrap-table .fixed-table-container{position:relative;clear:both}.bootstrap-table .fixed-table-container .table{width:100%;margin-bottom:0!important}.bootstrap-table .fixed-table-container .table td,.bootstrap-table .fixed-table-container .table th{vertical-align:middle;box-sizing:border-box}.bootstrap-table .fixed-table-container .table thead th{vertical-align:bottom;padding:0;margin:0}.bootstrap-table .fixed-table-container .table thead th:focus{outline:0 solid transparent}.bootstrap-table .fixed-table-container .table thead th.detail{width:30px}.bootstrap-table .fixed-table-container .table thead th .th-inner{padding:.75rem;vertical-align:bottom;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.bootstrap-table .fixed-table-container .table thead th .sortable{cursor:pointer;background-position:right;background-repeat:no-repeat;padding-right:30px!important}.bootstrap-table .fixed-table-container .table thead th .both{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAQAAADYWf5HAAAAkElEQVQoz7X QMQ5AQBCF4dWQSJxC5wwax1Cq1e7BAdxD5SL+Tq/QCM1oNiJidwox0355mXnG/DrEtIQ6azioNZQxI0ykPhTQIwhCR+BmBYtlK7kLJYwWCcJA9M4qdrZrd8pPjZWPtOqdRQy320YSV17OatFC4euts6z39GYMKRPCTKY9UnPQ6P+GtMRfGtPnBCiqhAeJPmkqAAAAAElFTkSuQmCC")}.bootstrap-table .fixed-table-container .table thead th .asc{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZ0lEQVQ4y2NgGLKgquEuFxBPAGI2ahhWCsS/gDibUoO0gPgxEP8H4ttArEyuQYxAPBdqEAxPBImTY5gjEL9DM+wTENuQahAvEO9DMwiGdwAxOymGJQLxTyD+jgWDxCMZRsEoGAVoAADeemwtPcZI2wAAAABJRU5ErkJggg==")}.bootstrap-table .fixed-table-container .table thead th .desc{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZUlEQVQ4y2NgGAWjYBSggaqGu5FA/BOIv2PBIPFEUgxjB+IdQPwfC94HxLykus4GiD+hGfQOiB3J8SojEE9EM2wuSJzcsFMG4ttQgx4DsRalkZENxL+AuJQaMcsGxBOAmGvopk8AVz1sLZgg0bsAAAAASUVORK5CYII= ")}.bootstrap-table .fixed-table-container .table tbody tr.selected td{background-color:rgba(0,0,0,.075)}.bootstrap-table .fixed-table-container .table tbody tr.no-records-found td{text-align:center}.bootstrap-table .fixed-table-container .table tbody tr .card-view{display:flex}.bootstrap-table .fixed-table-container .table tbody tr .card-view .card-view-title{font-weight:700;display:inline-block;min-width:30%;width:auto!important;text-align:left!important}.bootstrap-table .fixed-table-container .table tbody tr .card-view .card-view-value{width:100%!important}.bootstrap-table .fixed-table-container .table .bs-checkbox{text-align:center}.bootstrap-table .fixed-table-container .table .bs-checkbox label{margin-bottom:0}.bootstrap-table .fixed-table-container .table .bs-checkbox label input[type=checkbox],.bootstrap-table .fixed-table-container .table .bs-checkbox label input[type=radio]{margin:0 auto!important}.bootstrap-table .fixed-table-container .table.table-sm .th-inner{padding:.3rem}.bootstrap-table .fixed-table-container.fixed-height:not(.has-footer){border-bottom:1px solid #dee2e6}.bootstrap-table .fixed-table-container.fixed-height.has-card-view{border-top:1px solid #dee2e6;border-bottom:1px solid #dee2e6}.bootstrap-table .fixed-table-container.fixed-height .fixed-table-border{border-left:1px solid #dee2e6;border-right:1px solid #dee2e6}.bootstrap-table .fixed-table-container.fixed-height .table thead th{border-bottom:1px solid #dee2e6}.bootstrap-table .fixed-table-container.fixed-height .table-dark thead th{border-bottom:1px solid #32383e}.bootstrap-table .fixed-table-container .fixed-table-header{overflow:hidden}.bootstrap-table .fixed-table-container .fixed-table-body{overflow-x:auto;overflow-y:auto;height:100%}.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading{align-items:center;background:#fff;display:flex;justify-content:center;position:absolute;bottom:0;width:100%;max-width:100%;z-index:1000;transition:visibility 0s,opacity .15s ease-in-out;opacity:0;visibility:hidden}.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading.open{visibility:visible;opacity:1}.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap{align-items:baseline;display:flex;justify-content:center}.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap .loading-text{margin-right:6px}.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap .animation-wrap{align-items:center;display:flex;justify-content:center}.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap .animation-dot,.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap .animation-wrap::after,.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap .animation-wrap::before{content:"";animation-duration:1.5s;animation-iteration-count:infinite;animation-name:LOADING;background:#212529;border-radius:50%;display:block;height:5px;margin:0 4px;opacity:0;width:5px}.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap .animation-dot{animation-delay:.3s}.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap .animation-wrap::after{animation-delay:.6s}.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading.table-dark{background:#212529}.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading.table-dark .animation-dot,.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading.table-dark .animation-wrap::after,.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading.table-dark .animation-wrap::before{background:#fff}.bootstrap-table .fixed-table-container .fixed-table-footer{overflow:hidden}.bootstrap-table .fixed-table-pagination::after{content:"";display:block;clear:both}.bootstrap-table .fixed-table-pagination>.pagination,.bootstrap-table .fixed-table-pagination>.pagination-detail{margin-top:10px;margin-bottom:10px}.bootstrap-table .fixed-table-pagination>.pagination-detail .pagination-info{line-height:34px;margin-right:5px}.bootstrap-table .fixed-table-pagination>.pagination-detail .page-list{display:inline-block}.bootstrap-table .fixed-table-pagination>.pagination-detail .page-list .btn-group{position:relative;display:inline-block;vertical-align:middle}.bootstrap-table .fixed-table-pagination>.pagination-detail .page-list .btn-group .dropdown-menu{margin-bottom:0}.bootstrap-table .fixed-table-pagination>.pagination ul.pagination{margin:0}.bootstrap-table .fixed-table-pagination>.pagination ul.pagination li.page-intermediate a{color:#c8c8c8}.bootstrap-table .fixed-table-pagination>.pagination ul.pagination li.page-intermediate a::before{content:'\2B05'}.bootstrap-table .fixed-table-pagination>.pagination ul.pagination li.page-intermediate a::after{content:'\27A1'}.bootstrap-table .fixed-table-pagination>.pagination ul.pagination li.disabled a{pointer-events:none;cursor:default}.bootstrap-table.fullscreen{position:fixed;top:0;left:0;z-index:1050;width:100%!important;background:#fff;height:calc(100vh);overflow-y:scroll}.bootstrap-table.bootstrap4 .pagination-lg .page-link,.bootstrap-table.bootstrap5 .pagination-lg .page-link{padding:.5rem 1rem}.bootstrap-table.bootstrap5 .float-left{float:left}.bootstrap-table.bootstrap5 .float-right{float:right}div.fixed-table-scroll-inner{width:100%;height:200px}div.fixed-table-scroll-outer{top:0;left:0;visibility:hidden;width:200px;height:150px;overflow:hidden}@keyframes LOADING{0%{opacity:0}50%{opacity:1}to{opacity:0}}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/bootstrap-table.min.js b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/bootstrap-table.min.js
new file mode 100644
index 0000000..3aec87b
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/bootstrap-table.min.js
@@ -0,0 +1,6 @@
+/**
+ * @author zhixin wen
+ * version: 1.22.6
+ * https://github.com/wenzhixin/bootstrap-table/
+ */
+!function(t,e){"object"===typeof exports&&"undefined"!==typeof module?module.exports=e(require("jquery")):"function"===typeof define&&define.amd?define(["jquery"],e):(t="undefined"!==typeof globalThis?globalThis:t||self,t.BootstrapTable=e(t.jQuery))}(this,function(t){"use strict";function e(t,e){var r=null==t?null:"undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(null!=r){var a,i,n,o,s=[],l=!0,c=!1;try{if(n=(r=r.call(t)).next,0===e){if(Object(r)!==r)return;l=!1}else for(;!(l=(a=n.call(r)).done)&&(s.push(a.value),s.length!==e);l=!0);}catch(t){c=!0,i=t}finally{try{if(!l&&null!=r["return"]&&(o=r["return"](),Object(o)!==o))return}finally{if(c)throw i}}return s}}function r(t,e){if("object"!=typeof t||!t)return t;var r=t[Symbol.toPrimitive];if(void 0!==r){var a=r.call(t,e||"default");if("object"!=typeof a)return a;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===e?String:Number)(t)}function a(t){var e=r(t,"string");return"symbol"==typeof e?e:e+""}function i(t){"@babel/helpers - typeof";return i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},i(t)}function n(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function o(t,e){for(var r=0;r<e.length;r++){var i=e[r];i.enumerable=i.enumerable||false;i.configurable=true;if("value"in i)i.writable=true;Object.defineProperty(t,a(i.key),i)}}function s(t,e,r){if(e)o(t.prototype,e);if(r)o(t,r);Object.defineProperty(t,"prototype",{writable:false});return t}function l(t,r){return u(t)||e(t,r)||v(t,r)||g()}function c(t){return f(t)||h(t)||v(t)||p()}function f(t){if(Array.isArray(t))return d(t)}function u(t){if(Array.isArray(t))return t}function h(t){if("undefined"!==typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}function v(t,e){if(!t)return;if("string"===typeof t)return d(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);if("Object"===r&&t.constructor)r=t.constructor.name;if("Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return d(t,e)}function d(t,e){if(null==e||e>t.length)e=t.length;for(var r=0,a=new Array(e);r<e;r++)a[r]=t[r];return a}function p(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function g(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function b(t,e){var r="undefined"!==typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(!r){if(Array.isArray(t)||(r=v(t))||e&&t&&"number"===typeof t.length){if(r)t=r;var a=0;var i=function(){};return{s:i,n:function(){if(a>=t.length)return{done:true};return{done:false,value:t[a++]}},e:function(t){throw t},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var n=true,o=false,s;return{s:function(){r=r.call(t)},n:function(){var t=r.next();n=t.done;return t},e:function(t){o=true;s=t},f:function(){try{if(!n&&null!=r["return"])r["return"]()}finally{if(o)throw s}}}}var m="undefined"!==typeof globalThis?globalThis:"undefined"!==typeof window?window:"undefined"!==typeof global?global:"undefined"!==typeof self?self:{};var y=function(t){return t&&t.Math===Math&&t};var w=y("object"==typeof globalThis&&globalThis)||y("object"==typeof window&&window)||y("object"==typeof self&&self)||y("object"==typeof m&&m)||y("object"==typeof m&&m)||function(){return this}()||Function("return this")();var S={};var x=function(t){try{return!!t()}catch(e){return true}};var O=x;var k=!O(function(){return 7!==Object.defineProperty({},1,{get:function(){return 7}})[1]});var P=x;var C=!P(function(){var t=function(){}.bind();return"function"!=typeof t||t.hasOwnProperty("prototype")});var T=C;var I=Function.prototype.call;var A=T?I.bind(I):function(){return I.apply(I,arguments)};var $={};var R={}.propertyIsEnumerable;var E=Object.getOwnPropertyDescriptor;var j=E&&!R.call({1:2},1);$.f=j?function ky(t){var e=E(this,t);return!!e&&e.enumerable}:R;var _=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}};var N=C;var F=Function.prototype;var D=F.call;var V=N&&F.bind.bind(D,D);var B=N?V:function(t){return function(){return D.apply(t,arguments)}};var L=B;var H=L({}.toString);var M=L("".slice);var U=function(t){return M(H(t),8,-1)};var z=B;var q=x;var G=U;var W=Object;var K=z("".split);var Y=q(function(){return!W("z").propertyIsEnumerable(0)})?function(t){return"String"===G(t)?K(t,""):W(t)}:W;var J=function(t){return null===t||void 0===t};var X=J;var Q=TypeError;var Z=function(t){if(X(t))throw new Q("Can't call method on "+t);return t};var tt=Y;var et=Z;var rt=function(t){return tt(et(t))};var at="object"==typeof document&&document.all;var it="undefined"==typeof at&&void 0!==at?function(t){return"function"==typeof t||t===at}:function(t){return"function"==typeof t};var nt=it;var ot=function(t){return"object"==typeof t?null!==t:nt(t)};var st=w;var lt=it;var ct=function(t){return lt(t)?t:void 0};var ft=function(t,e){return arguments.length<2?ct(st[t]):st[t]&&st[t][e]};var ut=B;var ht=ut({}.isPrototypeOf);var vt="undefined"!=typeof navigator&&String(navigator.userAgent)||"";var dt=w;var pt=vt;var gt=dt.process;var bt=dt.Deno;var mt=gt&&gt.versions||bt&&bt.version;var yt=mt&&mt.v8;var wt,St;if(yt){wt=yt.split(".");St=wt[0]>0&&wt[0]<4?1:+(wt[0]+wt[1])}if(!St&&pt){wt=pt.match(/Edge\/(\d+)/);if(!wt||wt[1]>=74){wt=pt.match(/Chrome\/(\d+)/);if(wt)St=+wt[1]}}var xt=St;var Ot=xt;var kt=x;var Pt=w;var Ct=Pt.String;var Tt=!!Object.getOwnPropertySymbols&&!kt(function(){var t=Symbol("symbol detection");return!Ct(t)||!(Object(t)instanceof Symbol)||!Symbol.sham&&Ot&&Ot<41});var It=Tt;var At=It&&!Symbol.sham&&"symbol"==typeof Symbol.iterator;var $t=ft;var Rt=it;var Et=ht;var jt=At;var _t=Object;var Nt=jt?function(t){return"symbol"==typeof t}:function(t){var e=$t("Symbol");return Rt(e)&&Et(e.prototype,_t(t))};var Ft=String;var Dt=function(t){try{return Ft(t)}catch(e){return"Object"}};var Vt=it;var Bt=Dt;var Lt=TypeError;var Ht=function(t){if(Vt(t))return t;throw new Lt(Bt(t)+" is not a function")};var Mt=Ht;var Ut=J;var zt=function(t,e){var r=t[e];return Ut(r)?void 0:Mt(r)};var qt=A;var Gt=it;var Wt=ot;var Kt=TypeError;var Yt=function(t,e){var r,a;if("string"===e&&Gt(r=t.toString)&&!Wt(a=qt(r,t)))return a;if(Gt(r=t.valueOf)&&!Wt(a=qt(r,t)))return a;if("string"!==e&&Gt(r=t.toString)&&!Wt(a=qt(r,t)))return a;throw new Kt("Can't convert object to primitive value")};var Jt={exports:{}};var Xt=false;var Qt=w;var Zt=Object.defineProperty;var te=function(t,e){try{Zt(Qt,t,{value:e,configurable:true,writable:true})}catch(r){Qt[t]=e}return e};var ee=w;var re=te;var ae="__core-js_shared__";var ie=Jt.exports=ee[ae]||re(ae,{});(ie.versions||(ie.versions=[])).push({version:"3.36.1",mode:"global",copyright:"© 2014-2024 Denis Pushkarev (zloirock.ru)",license:"https://github.com/zloirock/core-js/blob/v3.36.1/LICENSE",source:"https://github.com/zloirock/core-js"});var ne=Jt.exports;var oe=ne;var se=function(t,e){return oe[t]||(oe[t]=e||{})};var le=Z;var ce=Object;var fe=function(t){return ce(le(t))};var ue=B;var he=fe;var ve=ue({}.hasOwnProperty);var de=Object.hasOwn||function Py(t,e){return ve(he(t),e)};var pe=B;var ge=0;var be=Math.random();var me=pe(1..toString);var ye=function(t){return"Symbol("+(void 0===t?"":t)+")_"+me(++ge+be,36)};var we=w;var Se=se;var xe=de;var Oe=ye;var ke=Tt;var Pe=At;var Ce=we.Symbol;var Te=Se("wks");var Ie=Pe?Ce["for"]||Ce:Ce&&Ce.withoutSetter||Oe;var Ae=function(t){if(!xe(Te,t))Te[t]=ke&&xe(Ce,t)?Ce[t]:Ie("Symbol."+t);return Te[t]};var $e=A;var Re=ot;var Ee=Nt;var je=zt;var _e=Yt;var Ne=Ae;var Fe=TypeError;var De=Ne("toPrimitive");var Ve=function(t,e){if(!Re(t)||Ee(t))return t;var r=je(t,De);var a;if(r){if(void 0===e)e="default";a=$e(r,t,e);if(!Re(a)||Ee(a))return a;throw new Fe("Can't convert object to primitive value")}if(void 0===e)e="number";return _e(t,e)};var Be=Ve;var Le=Nt;var He=function(t){var e=Be(t,"string");return Le(e)?e:e+""};var Me=w;var Ue=ot;var ze=Me.document;var qe=Ue(ze)&&Ue(ze.createElement);var Ge=function(t){return qe?ze.createElement(t):{}};var We=k;var Ke=x;var Ye=Ge;var Je=!We&&!Ke(function(){return 7!==Object.defineProperty(Ye("div"),"a",{get:function(){return 7}}).a});var Xe=k;var Qe=A;var Ze=$;var tr=_;var er=rt;var rr=He;var ar=de;var ir=Je;var nr=Object.getOwnPropertyDescriptor;S.f=Xe?nr:function Cy(t,e){t=er(t);e=rr(e);if(ir)try{return nr(t,e)}catch(r){}if(ar(t,e))return tr(!Qe(Ze.f,t,e),t[e])};var or={};var sr=k;var lr=x;var cr=sr&&lr(function(){return 42!==Object.defineProperty(function(){},"prototype",{value:42,writable:false}).prototype});var fr=ot;var ur=String;var hr=TypeError;var vr=function(t){if(fr(t))return t;throw new hr(ur(t)+" is not an object")};var dr=k;var pr=Je;var gr=cr;var br=vr;var mr=He;var yr=TypeError;var wr=Object.defineProperty;var Sr=Object.getOwnPropertyDescriptor;var xr="enumerable";var Or="configurable";var kr="writable";or.f=dr?gr?function Ty(t,e,r){br(t);e=mr(e);br(r);if("function"===typeof t&&"prototype"===e&&"value"in r&&kr in r&&!r[kr]){var a=Sr(t,e);if(a&&a[kr]){t[e]=r.value;r={configurable:Or in r?r[Or]:a[Or],enumerable:xr in r?r[xr]:a[xr],writable:false}}}return wr(t,e,r)}:wr:function Iy(t,e,r){br(t);e=mr(e);br(r);if(pr)try{return wr(t,e,r)}catch(a){}if("get"in r||"set"in r)throw new yr("Accessors not supported");if("value"in r)t[e]=r.value;return t};var Pr=k;var Cr=or;var Tr=_;var Ir=Pr?function(t,e,r){return Cr.f(t,e,Tr(1,r))}:function(t,e,r){t[e]=r;return t};var Ar={exports:{}};var $r=k;var Rr=de;var Er=Function.prototype;var jr=$r&&Object.getOwnPropertyDescriptor;var _r=Rr(Er,"name");var Nr=_r&&"something"===function Ay(){}.name;var Fr=_r&&(!$r||$r&&jr(Er,"name").configurable);var Dr={EXISTS:_r,PROPER:Nr,CONFIGURABLE:Fr};var Vr=B;var Br=it;var Lr=ne;var Hr=Vr(Function.toString);if(!Br(Lr.inspectSource))Lr.inspectSource=function(t){return Hr(t)};var Mr=Lr.inspectSource;var Ur=w;var zr=it;var qr=Ur.WeakMap;var Gr=zr(qr)&&/native code/.test(String(qr));var Wr=se;var Kr=ye;var Yr=Wr("keys");var Jr=function(t){return Yr[t]||(Yr[t]=Kr(t))};var Xr={};var Qr=Gr;var Zr=w;var ta=ot;var ea=Ir;var ra=de;var aa=ne;var ia=Jr;var na=Xr;var oa="Object already initialized";var sa=Zr.TypeError;var la=Zr.WeakMap;var ca,fa,ua;var ha=function(t){return ua(t)?fa(t):ca(t,{})};var va=function(t){return function(e){var r;if(!ta(e)||(r=fa(e)).type!==t)throw new sa("Incompatible receiver, "+t+" required");return r}};if(Qr||aa.state){var da=aa.state||(aa.state=new la);da.get=da.get;da.has=da.has;da.set=da.set;ca=function(t,e){if(da.has(t))throw new sa(oa);e.facade=t;da.set(t,e);return e};fa=function(t){return da.get(t)||{}};ua=function(t){return da.has(t)}}else{var pa=ia("state");na[pa]=true;ca=function(t,e){if(ra(t,pa))throw new sa(oa);e.facade=t;ea(t,pa,e);return e};fa=function(t){return ra(t,pa)?t[pa]:{}};ua=function(t){return ra(t,pa)}}var ga={set:ca,get:fa,has:ua,enforce:ha,getterFor:va};var ba=B;var ma=x;var ya=it;var wa=de;var Sa=k;var xa=Dr.CONFIGURABLE;var Oa=Mr;var ka=ga;var Pa=ka.enforce;var Ca=ka.get;var Ta=String;var Ia=Object.defineProperty;var Aa=ba("".slice);var $a=ba("".replace);var Ra=ba([].join);var Ea=Sa&&!ma(function(){return 8!==Ia(function(){},"length",{value:8}).length});var ja=String(String).split("String");var _a=Ar.exports=function(t,e,r){if("Symbol("===Aa(Ta(e),0,7))e="["+$a(Ta(e),/^Symbol\(([^)]*)\).*$/,"$1")+"]";if(r&&r.getter)e="get "+e;if(r&&r.setter)e="set "+e;if(!wa(t,"name")||xa&&t.name!==e)if(Sa)Ia(t,"name",{value:e,configurable:true});else t.name=e;if(Ea&&r&&wa(r,"arity")&&t.length!==r.arity)Ia(t,"length",{value:r.arity});try{if(r&&wa(r,"constructor")&&r.constructor){if(Sa)Ia(t,"prototype",{writable:false})}else if(t.prototype)t.prototype=void 0}catch(a){}var i=Pa(t);if(!wa(i,"source"))i.source=Ra(ja,"string"==typeof e?e:"");return t};Function.prototype.toString=_a(function $y(){return ya(this)&&Ca(this).source||Oa(this)},"toString");var Na=Ar.exports;var Fa=it;var Da=or;var Va=Na;var Ba=te;var La=function(t,e,r,a){if(!a)a={};var i=a.enumerable;var n=void 0!==a.name?a.name:e;if(Fa(r))Va(r,n,a);if(a.global)if(i)t[e]=r;else Ba(e,r);else{try{if(!a.unsafe)delete t[e];else if(t[e])i=true}catch(o){}if(i)t[e]=r;else Da.f(t,e,{value:r,enumerable:false,configurable:!a.nonConfigurable,writable:!a.nonWritable})}return t};var Ha={};var Ma=Math.ceil;var Ua=Math.floor;var za=Math.trunc||function Ry(t){var e=+t;return(e>0?Ua:Ma)(e)};var qa=za;var Ga=function(t){var e=+t;return e!==e||0===e?0:qa(e)};var Wa=Ga;var Ka=Math.max;var Ya=Math.min;var Ja=function(t,e){var r=Wa(t);return r<0?Ka(r+e,0):Ya(r,e)};var Xa=Ga;var Qa=Math.min;var Za=function(t){var e=Xa(t);return e>0?Qa(e,9007199254740991):0};var ti=Za;var ei=function(t){return ti(t.length)};var ri=rt;var ai=Ja;var ii=ei;var ni=function(t){return function(e,r,a){var i=ri(e);var n=ii(i);if(0===n)return!t&&-1;var o=ai(a,n);var s;if(t&&r!==r)while(n>o){s=i[o++];if(s!==s)return true}else for(;n>o;o++)if((t||o in i)&&i[o]===r)return t||o||0;return!t&&-1}};var oi={includes:ni(true),indexOf:ni(false)};var si=B;var li=de;var ci=rt;var fi=oi.indexOf;var ui=Xr;var hi=si([].push);var vi=function(t,e){var r=ci(t);var a=0;var i=[];var n;for(n in r)!li(ui,n)&&li(r,n)&&hi(i,n);while(e.length>a)if(li(r,n=e[a++]))~fi(i,n)||hi(i,n);return i};var di=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"];var pi=vi;var gi=di;var bi=gi.concat("length","prototype");Ha.f=Object.getOwnPropertyNames||function Ey(t){return pi(t,bi)};var mi={};mi.f=Object.getOwnPropertySymbols;var yi=ft;var wi=B;var Si=Ha;var xi=mi;var Oi=vr;var ki=wi([].concat);var Pi=yi("Reflect","ownKeys")||function jy(t){var e=Si.f(Oi(t));var r=xi.f;return r?ki(e,r(t)):e};var Ci=de;var Ti=Pi;var Ii=S;var Ai=or;var $i=function(t,e,r){var a=Ti(e);var i=Ai.f;var n=Ii.f;for(var o=0;o<a.length;o++){var s=a[o];if(!Ci(t,s)&&!(r&&Ci(r,s)))i(t,s,n(e,s))}};var Ri=x;var Ei=it;var ji=/#|\.prototype\./;var _i=function(t,e){var r=Fi[Ni(t)];return r===Vi?true:r===Di?false:Ei(e)?Ri(e):!!e};var Ni=_i.normalize=function(t){return String(t).replace(ji,".").toLowerCase()};var Fi=_i.data={};var Di=_i.NATIVE="N";var Vi=_i.POLYFILL="P";var Bi=_i;var Li=w;var Hi=S.f;var Mi=Ir;var Ui=La;var zi=te;var qi=$i;var Gi=Bi;var Wi=function(t,e){var r=t.target;var a=t.global;var i=t.stat;var n,o,s,l,c,f;if(a)o=Li;else if(i)o=Li[r]||zi(r,{});else o=Li[r]&&Li[r].prototype;if(o)for(s in e){c=e[s];if(t.dontCallGetSet){f=Hi(o,s);l=f&&f.value}else l=o[s];n=Gi(a?s:r+(i?".":"#")+s,t.forced);if(!n&&void 0!==l){if(typeof c==typeof l)continue;qi(c,l)}if(t.sham||l&&l.sham)Mi(c,"sham",true);Ui(o,s,c,t)}};var Ki=U;var Yi=Array.isArray||function _y(t){return"Array"===Ki(t)};var Ji=TypeError;var Xi=9007199254740991;var Qi=function(t){if(t>Xi)throw Ji("Maximum allowed index exceeded");return t};var Zi=k;var tn=or;var en=_;var rn=function(t,e,r){if(Zi)tn.f(t,e,en(0,r));else t[e]=r};var an=Ae;var nn=an("toStringTag");var on={};on[nn]="z";var sn="[object z]"===String(on);var ln=sn;var cn=it;var fn=U;var un=Ae;var hn=un("toStringTag");var vn=Object;var dn="Arguments"===fn(function(){return arguments}());var pn=function(t,e){try{return t[e]}catch(r){}};var gn=ln?fn:function(t){var e,r,a;return void 0===t?"Undefined":null===t?"Null":"string"==typeof(r=pn(e=vn(t),hn))?r:dn?fn(e):"Object"===(a=fn(e))&&cn(e.callee)?"Arguments":a};var bn=B;var mn=x;var yn=it;var wn=gn;var Sn=ft;var xn=Mr;var On=function(){};var kn=Sn("Reflect","construct");var Pn=/^\s*(?:class|function)\b/;var Cn=bn(Pn.exec);var Tn=!Pn.test(On);var In=function Ny(t){if(!yn(t))return false;try{kn(On,[],t);return true}catch(e){return false}};var An=function Fy(t){if(!yn(t))return false;switch(wn(t)){case"AsyncFunction":case"GeneratorFunction":case"AsyncGeneratorFunction":return false}try{return Tn||!!Cn(Pn,xn(t))}catch(e){return true}};An.sham=true;var $n=!kn||mn(function(){var t;return In(In.call)||!In(Object)||!In(function(){t=true})||t})?An:In;var Rn=Yi;var En=$n;var jn=ot;var _n=Ae;var Nn=_n("species");var Fn=Array;var Dn=function(t){var e;if(Rn(t)){e=t.constructor;if(En(e)&&(e===Fn||Rn(e.prototype)))e=void 0;else if(jn(e)){e=e[Nn];if(null===e)e=void 0}}return void 0===e?Fn:e};var Vn=Dn;var Bn=function(t,e){return new(Vn(t))(0===e?0:e)};var Ln=x;var Hn=Ae;var Mn=xt;var Un=Hn("species");var zn=function(t){return Mn>=51||!Ln(function(){var e=[];var r=e.constructor={};r[Un]=function(){return{foo:1}};return 1!==e[t](Boolean).foo})};var qn=Wi;var Gn=x;var Wn=Yi;var Kn=ot;var Yn=fe;var Jn=ei;var Xn=Qi;var Qn=rn;var Zn=Bn;var to=zn;var eo=Ae;var ro=xt;var ao=eo("isConcatSpreadable");var io=ro>=51||!Gn(function(){var t=[];t[ao]=false;return t.concat()[0]!==t});var no=function(t){if(!Kn(t))return false;var e=t[ao];return void 0!==e?!!e:Wn(t)};var oo=!io||!to("concat");qn({target:"Array",proto:true,arity:1,forced:oo},{concat:function Dy(t){var e=Yn(this);var r=Zn(e,0);var a=0;var i,n,o,s,l;for(i=-1,o=arguments.length;i<o;i++){l=i===-1?e:arguments[i];if(no(l)){s=Jn(l);Xn(a+s);for(n=0;n<s;n++,a++)if(n in l)Qn(r,a,l[n])}else{Xn(a+1);Qn(r,a++,l)}}r.length=a;return r}});var so=U;var lo=B;var co=function(t){if("Function"===so(t))return lo(t)};var fo=co;var uo=Ht;var ho=C;var vo=fo(fo.bind);var po=function(t,e){uo(t);return void 0===e?t:ho?vo(t,e):function(){return t.apply(e,arguments)}};var go=po;var bo=B;var mo=Y;var yo=fe;var wo=ei;var So=Bn;var xo=bo([].push);var Oo=function(t){var e=1===t;var r=2===t;var a=3===t;var i=4===t;var n=6===t;var o=7===t;var s=5===t||n;return function(l,c,f,u){var h=yo(l);var v=mo(h);var d=wo(v);var p=go(c,f);var g=0;var b=u||So;var m=e?b(l,d):r||o?b(l,0):void 0;var y,w;for(;d>g;g++)if(s||g in v){y=v[g];w=p(y,g,h);if(t)if(e)m[g]=w;else if(w)switch(t){case 3:return true;case 5:return y;case 6:return g;case 2:xo(m,y)}else switch(t){case 4:return false;case 7:xo(m,y)}}return n?-1:a||i?i:m}};var ko={forEach:Oo(0),map:Oo(1),filter:Oo(2),some:Oo(3),every:Oo(4),find:Oo(5),findIndex:Oo(6),filterReject:Oo(7)};var Po=Wi;var Co=ko.filter;var To=zn;var Io=To("filter");Po({target:"Array",proto:true,forced:!Io},{filter:function Vy(t){return Co(this,t,arguments.length>1?arguments[1]:void 0)}});var Ao={};var $o=vi;var Ro=di;var Eo=Object.keys||function By(t){return $o(t,Ro)};var jo=k;var _o=cr;var No=or;var Fo=vr;var Do=rt;var Vo=Eo;Ao.f=jo&&!_o?Object.defineProperties:function Ly(t,e){Fo(t);var r=Do(e);var a=Vo(e);var i=a.length;var n=0;var o;while(i>n)No.f(t,o=a[n++],r[o]);return t};var Bo=ft;var Lo=Bo("document","documentElement");var Ho=vr;var Mo=Ao;var Uo=di;var zo=Xr;var qo=Lo;var Go=Ge;var Wo=Jr;var Ko=">";var Yo="<";var Jo="prototype";var Xo="script";var Qo=Wo("IE_PROTO");var Zo=function(){};var ts=function(t){return Yo+Xo+Ko+t+Yo+"/"+Xo+Ko};var es=function(t){t.write(ts(""));t.close();var e=t.parentWindow.Object;t=null;return e};var rs=function(){var t=Go("iframe");var e="java"+Xo+":";var r;t.style.display="none";qo.appendChild(t);t.src=String(e);r=t.contentWindow.document;r.open();r.write(ts("document.F=Object"));r.close();return r.F};var as;var is=function(){try{as=new ActiveXObject("htmlfile")}catch(t){}is="undefined"!=typeof document?document.domain&&as?es(as):rs():es(as);var e=Uo.length;while(e--)delete is[Jo][Uo[e]];return is()};zo[Qo]=true;var ns=Object.create||function Hy(t,e){var r;if(null!==t){Zo[Jo]=Ho(t);r=new Zo;Zo[Jo]=null;r[Qo]=t}else r=is();return void 0===e?r:Mo.f(r,e)};var os=Ae;var ss=ns;var ls=or.f;var cs=os("unscopables");var fs=Array.prototype;if(void 0===fs[cs])ls(fs,cs,{configurable:true,value:ss(null)});var us=function(t){fs[cs][t]=true};var hs=Wi;var vs=ko.find;var ds=us;var ps="find";var gs=true;if(ps in[])Array(1)[ps](function(){gs=false});hs({target:"Array",proto:true,forced:gs},{find:function My(t){return vs(this,t,arguments.length>1?arguments[1]:void 0)}});ds(ps);var bs=Wi;var ms=ko.findIndex;var ys=us;var ws="findIndex";var Ss=true;if(ws in[])Array(1)[ws](function(){Ss=false});bs({target:"Array",proto:true,forced:Ss},{findIndex:function Uy(t){return ms(this,t,arguments.length>1?arguments[1]:void 0)}});ys(ws);var xs=Wi;var Os=oi.includes;var ks=x;var Ps=us;var Cs=ks(function(){return!Array(1).includes()});xs({target:"Array",proto:true,forced:Cs},{includes:function zy(t){return Os(this,t,arguments.length>1?arguments[1]:void 0)}});Ps("includes");var Ts=x;var Is=function(t,e){var r=[][t];return!!r&&Ts(function(){r.call(null,e||function(){return 1},1)})};var As=Wi;var $s=co;var Rs=oi.indexOf;var Es=Is;var js=$s([].indexOf);var _s=!!js&&1/js([1],1,-0)<0;var Ns=_s||!Es("indexOf");As({target:"Array",proto:true,forced:Ns},{indexOf:function qy(t){var e=arguments.length>1?arguments[1]:void 0;return _s?js(this,t,e)||0:Rs(this,t,e)}});var Fs={};var Ds=x;var Vs=!Ds(function(){function t(){}t.prototype.constructor=null;return Object.getPrototypeOf(new t)!==t.prototype});var Bs=de;var Ls=it;var Hs=fe;var Ms=Jr;var Us=Vs;var zs=Ms("IE_PROTO");var qs=Object;var Gs=qs.prototype;var Ws=Us?qs.getPrototypeOf:function(t){var e=Hs(t);if(Bs(e,zs))return e[zs];var r=e.constructor;if(Ls(r)&&e instanceof r)return r.prototype;return e instanceof qs?Gs:null};var Ks=x;var Ys=it;var Js=ot;var Xs=Ws;var Qs=La;var Zs=Ae;var tl=Zs("iterator");var el=false;var rl,al,il;if([].keys){il=[].keys();if(!("next"in il))el=true;else{al=Xs(Xs(il));if(al!==Object.prototype)rl=al}}var nl=!Js(rl)||Ks(function(){var t={};return rl[tl].call(t)!==t});if(nl)rl={};if(!Ys(rl[tl]))Qs(rl,tl,function(){return this});var ol={IteratorPrototype:rl,BUGGY_SAFARI_ITERATORS:el};var sl=or.f;var ll=de;var cl=Ae;var fl=cl("toStringTag");var ul=function(t,e,r){if(t&&!r)t=t.prototype;if(t&&!ll(t,fl))sl(t,fl,{configurable:true,value:e})};var hl=ol.IteratorPrototype;var vl=ns;var dl=_;var pl=ul;var gl=Fs;var bl=function(){return this};var ml=function(t,e,r,a){var i=e+" Iterator";t.prototype=vl(hl,{next:dl(+!a,r)});pl(t,i,false);gl[i]=bl;return t};var yl=B;var wl=Ht;var Sl=function(t,e,r){try{return yl(wl(Object.getOwnPropertyDescriptor(t,e)[r]))}catch(a){}};var xl=ot;var Ol=function(t){return xl(t)||null===t};var kl=Ol;var Pl=String;var Cl=TypeError;var Tl=function(t){if(kl(t))return t;throw new Cl("Can't set "+Pl(t)+" as a prototype")};var Il=Sl;var Al=ot;var $l=Z;var Rl=Tl;var El=Object.setPrototypeOf||("__proto__"in{}?function(){var t=false;var e={};var r;try{r=Il(Object.prototype,"__proto__","set");r(e,[]);t=e instanceof Array}catch(a){}return function i(e,a){$l(e);Rl(a);if(!Al(e))return e;if(t)r(e,a);else e.__proto__=a;return e}}():void 0);var jl=Wi;var _l=A;var Nl=Dr;var Fl=it;var Dl=ml;var Vl=Ws;var Bl=El;var Ll=ul;var Hl=Ir;var Ml=La;var Ul=Ae;var zl=Fs;var ql=ol;var Gl=Nl.PROPER;var Wl=Nl.CONFIGURABLE;var Kl=ql.IteratorPrototype;var Yl=ql.BUGGY_SAFARI_ITERATORS;var Jl=Ul("iterator");var Xl="keys";var Ql="values";var Zl="entries";var tc=function(){return this};var ec=function(t,e,r,a,i,n,o){Dl(r,e,a);var s=function(t){if(t===i&&h)return h;if(!Yl&&t&&t in f)return f[t];switch(t){case Xl:return function e(){return new r(this,t)};case Ql:return function a(){return new r(this,t)};case Zl:return function n(){return new r(this,t)}}return function(){return new r(this)}};var l=e+" Iterator";var c=false;var f=t.prototype;var u=f[Jl]||f["@@iterator"]||i&&f[i];var h=!Yl&&u||s(i);var v="Array"===e?f.entries||u:u;var d,p,g;if(v){d=Vl(v.call(new t));if(d!==Object.prototype&&d.next){if(Vl(d)!==Kl)if(Bl)Bl(d,Kl);else if(!Fl(d[Jl]))Ml(d,Jl,tc);Ll(d,l,true)}}if(Gl&&i===Ql&&u&&u.name!==Ql)if(Wl)Hl(f,"name",Ql);else{c=true;h=function b(){return _l(u,this)}}if(i){p={values:s(Ql),keys:n?h:s(Xl),entries:s(Zl)};if(o){for(g in p)if(Yl||c||!(g in f))Ml(f,g,p[g])}else jl({target:e,proto:true,forced:Yl||c},p)}if(f[Jl]!==h)Ml(f,Jl,h,{name:i});zl[e]=h;return p};var rc=function(t,e){return{value:t,done:e}};var ac=rt;var ic=us;var nc=Fs;var oc=ga;var sc=or.f;var lc=ec;var cc=rc;var fc=k;var uc="Array Iterator";var hc=oc.set;var vc=oc.getterFor(uc);var dc=lc(Array,"Array",function(t,e){hc(this,{type:uc,target:ac(t),index:0,kind:e})},function(){var t=vc(this);var e=t.target;var r=t.index++;if(!e||r>=e.length){t.target=void 0;return cc(void 0,true)}switch(t.kind){case"keys":return cc(r,false);case"values":return cc(e[r],false)}return cc([r,e[r]],false)},"values");var pc=nc.Arguments=nc.Array;ic("keys");ic("values");ic("entries");if(fc&&"values"!==pc.name)try{sc(pc,"name",{value:"values"})}catch(gc){}var bc=Wi;var mc=B;var yc=Y;var wc=rt;var Sc=Is;var xc=mc([].join);var Oc=yc!==Object;var kc=Oc||!Sc("join",",");bc({target:"Array",proto:true,forced:kc},{join:function Gy(t){return xc(wc(this),void 0===t?",":t)}});var Pc=Wi;var Cc=ko.map;var Tc=zn;var Ic=Tc("map");Pc({target:"Array",proto:true,forced:!Ic},{map:function Wy(t){return Cc(this,t,arguments.length>1?arguments[1]:void 0)}});var Ac=Wi;var $c=B;var Rc=Yi;var Ec=$c([].reverse);var jc=[1,2];Ac({target:"Array",proto:true,forced:String(jc)===String(jc.reverse())},{reverse:function Ky(){if(Rc(this))this.length=this.length;return Ec(this)}});var _c=B;var Nc=_c([].slice);var Fc=Wi;var Dc=Yi;var Vc=$n;var Bc=ot;var Lc=Ja;var Hc=ei;var Mc=rt;var Uc=rn;var zc=Ae;var qc=zn;var Gc=Nc;var Wc=qc("slice");var Kc=zc("species");var Yc=Array;var Jc=Math.max;Fc({target:"Array",proto:true,forced:!Wc},{slice:function Yy(t,e){var r=Mc(this);var a=Hc(r);var i=Lc(t,a);var n=Lc(void 0===e?a:e,a);var o,s,l;if(Dc(r)){o=r.constructor;if(Vc(o)&&(o===Yc||Dc(o.prototype)))o=void 0;else if(Bc(o)){o=o[Kc];if(null===o)o=void 0}if(o===Yc||void 0===o)return Gc(r,i,n)}s=new(void 0===o?Yc:o)(Jc(n-i,0));for(l=0;i<n;i++,l++)if(i in r)Uc(s,l,r[i]);s.length=l;return s}});var Xc=Dt;var Qc=TypeError;var Zc=function(t,e){if(!delete t[e])throw new Qc("Cannot delete property "+Xc(e)+" of "+Xc(t))};var tf=gn;var ef=String;var rf=function(t){if("Symbol"===tf(t))throw new TypeError("Cannot convert a Symbol value to a string");return ef(t)};var af=Nc;var nf=Math.floor;var of=function(t,e){var r=t.length;if(r<8){var a=1;var i,n;while(a<r){n=a;i=t[a];while(n&&e(t[n-1],i)>0)t[n]=t[--n];if(n!==a++)t[n]=i}}else{var o=nf(r/2);var s=of(af(t,0,o),e);var l=of(af(t,o),e);var c=s.length;var f=l.length;var u=0;var h=0;while(u<c||h<f)t[u+h]=u<c&&h<f?e(s[u],l[h])<=0?s[u++]:l[h++]:u<c?s[u++]:l[h++]}return t};var sf=of;var lf=vt;var cf=lf.match(/firefox\/(\d+)/i);var ff=!!cf&&+cf[1];var uf=vt;var hf=/MSIE|Trident/.test(uf);var vf=vt;var df=vf.match(/AppleWebKit\/(\d+)\./);var pf=!!df&&+df[1];var gf=Wi;var bf=B;var mf=Ht;var yf=fe;var wf=ei;var Sf=Zc;var xf=rf;var Of=x;var kf=sf;var Pf=Is;var Cf=ff;var Tf=hf;var If=xt;var Af=pf;var $f=[];var Rf=bf($f.sort);var Ef=bf($f.push);var jf=Of(function(){$f.sort(void 0)});var _f=Of(function(){$f.sort(null)});var Nf=Pf("sort");var Ff=!Of(function(){if(If)return If<70;if(Cf&&Cf>3)return;if(Tf)return true;if(Af)return Af<603;var t="";var e,r,a,i;for(e=65;e<76;e++){r=String.fromCharCode(e);switch(e){case 66:case 69:case 70:case 72:a=3;break;case 68:case 71:a=4;break;default:a=2}for(i=0;i<47;i++)$f.push({k:r+i,v:a})}$f.sort(function(t,e){return e.v-t.v});for(i=0;i<$f.length;i++){r=$f[i].k.charAt(0);if(t.charAt(t.length-1)!==r)t+=r}return"DGBEFHACIJK"!==t});var Df=jf||!_f||!Nf||!Ff;var Vf=function(t){return function(e,r){if(void 0===r)return-1;if(void 0===e)return 1;if(void 0!==t)return+t(e,r)||0;return xf(e)>xf(r)?1:-1}};gf({target:"Array",proto:true,forced:Df},{sort:function Jy(t){if(void 0!==t)mf(t);var e=yf(this);if(Ff)return void 0===t?Rf(e):Rf(e,t);var r=[];var a=wf(e);var i,n;for(n=0;n<a;n++)if(n in e)Ef(r,e[n]);kf(r,Vf(t));i=wf(r);n=0;while(n<i)e[n]=r[n++];while(n<a)Sf(e,n++);return e}});var Bf=k;var Lf=Yi;var Hf=TypeError;var Mf=Object.getOwnPropertyDescriptor;var Uf=Bf&&!function(){if(void 0!==this)return true;try{Object.defineProperty([],"length",{writable:false}).length=1}catch(t){return t instanceof TypeError}}();var zf=Uf?function(t,e){if(Lf(t)&&!Mf(t,"length").writable)throw new Hf("Cannot set read only .length");return t.length=e}:function(t,e){return t.length=e};var qf=Wi;var Gf=fe;var Wf=Ja;var Kf=Ga;var Yf=ei;var Jf=zf;var Xf=Qi;var Qf=Bn;var Zf=rn;var tu=Zc;var eu=zn;var ru=eu("splice");var au=Math.max;var iu=Math.min;qf({target:"Array",proto:true,forced:!ru},{splice:function Xy(t,e){var r=Gf(this);var a=Yf(r);var i=Wf(t,a);var n=arguments.length;var o,s,l,c,f,u;if(0===n)o=s=0;else if(1===n){o=0;s=a-i}else{o=n-2;s=iu(au(Kf(e),0),a-i)}Xf(a+o-s);l=Qf(r,s);for(c=0;c<s;c++){f=i+c;if(f in r)Zf(l,c,r[f])}l.length=s;if(o<s){for(c=i;c<a-s;c++){f=c+s;u=c+o;if(f in r)r[u]=r[f];else tu(r,u)}for(c=a;c>a-s+o;c--)tu(r,c-1)}else if(o>s)for(c=a-s;c>i;c--){f=c+s-1;u=c+o-1;if(f in r)r[u]=r[f];else tu(r,u)}for(c=0;c<o;c++)r[c+i]=arguments[c+2];Jf(r,a-s+o);return l}});var nu=Wi;var ou=x;var su=fe;var lu=Ve;var cu=ou(function(){return null!==new Date(NaN).toJSON()||1!==Date.prototype.toJSON.call({toISOString:function(){return 1}})});nu({target:"Date",proto:true,arity:1,forced:cu},{toJSON:function Qy(t){var e=su(this);var r=lu(e,"number");return"number"==typeof r&&!isFinite(r)?null:e.toISOString()}});var fu=w;var uu=fu;var hu=it;var vu=ot;var du=El;var pu=function(t,e,r){var a,i;if(du&&hu(a=e.constructor)&&a!==r&&vu(i=a.prototype)&&i!==r.prototype)du(t,i);return t};var gu=B;var bu=gu(1..valueOf);var mu="\t\n\v\f\r      "+"           \u2028\u2029\ufeff";var yu=B;var wu=Z;var Su=rf;var xu=mu;var Ou=yu("".replace);var ku=RegExp("^["+xu+"]+");var Pu=RegExp("(^|[^"+xu+"])["+xu+"]+$");var Cu=function(t){return function(e){var r=Su(wu(e));if(1&t)r=Ou(r,ku,"");if(2&t)r=Ou(r,Pu,"$1");return r}};var Tu={start:Cu(1),end:Cu(2),trim:Cu(3)};var Iu=Wi;var Au=Xt;var $u=k;var Ru=w;var Eu=uu;var ju=B;var _u=Bi;var Nu=de;var Fu=pu;var Du=ht;var Vu=Nt;var Bu=Ve;var Lu=x;var Hu=Ha.f;var Mu=S.f;var Uu=or.f;var zu=bu;var qu=Tu.trim;var Gu="Number";var Wu=Ru[Gu];Eu[Gu];var Ku=Wu.prototype;var Yu=Ru.TypeError;var Ju=ju("".slice);var Xu=ju("".charCodeAt);var Qu=function(t){var e=Bu(t,"number");return"bigint"==typeof e?e:Zu(e)};var Zu=function(t){var e=Bu(t,"number");var r,a,i,n,o,s,l,c;if(Vu(e))throw new Yu("Cannot convert a Symbol value to a number");if("string"==typeof e&&e.length>2){e=qu(e);r=Xu(e,0);if(43===r||45===r){a=Xu(e,2);if(88===a||120===a)return NaN}else if(48===r){switch(Xu(e,1)){case 66:case 98:i=2;n=49;break;case 79:case 111:i=8;n=55;break;default:return+e}o=Ju(e,2);s=o.length;for(l=0;l<s;l++){c=Xu(o,l);if(c<48||c>n)return NaN}return parseInt(o,i)}}return+e};var th=_u(Gu,!Wu(" 0o1")||!Wu("0b1")||Wu("+0x1"));var eh=function(t){return Du(Ku,t)&&Lu(function(){zu(t)})};var rh=function Zy(t){var e=arguments.length<1?0:Wu(Qu(t));return eh(this)?Fu(Object(e),this,rh):e};rh.prototype=Ku;if(th&&!Au)Ku.constructor=rh;Iu({global:true,constructor:true,wrap:true,forced:th},{Number:rh});var ah=function(t,e){for(var r=$u?Hu(e):("MAX_VALUE,MIN_VALUE,NaN,NEGATIVE_INFINITY,POSITIVE_INFINITY,"+"EPSILON,MAX_SAFE_INTEGER,MIN_SAFE_INTEGER,isFinite,isInteger,isNaN,isSafeInteger,parseFloat,parseInt,"+"fromString,range").split(","),a=0,i;r.length>a;a++)if(Nu(e,i=r[a])&&!Nu(t,i))Uu(t,i,Mu(e,i))};if(th||Au)ah(Eu[Gu],Wu);var ih=k;var nh=B;var oh=A;var sh=x;var lh=Eo;var ch=mi;var fh=$;var uh=fe;var hh=Y;var vh=Object.assign;var dh=Object.defineProperty;var ph=nh([].concat);var gh=!vh||sh(function(){if(ih&&1!==vh({b:1},vh(dh({},"a",{enumerable:true,get:function(){dh(this,"b",{value:3,enumerable:false})}}),{b:2})).b)return true;var t={};var e={};var r=Symbol("assign detection");var a="abcdefghijklmnopqrst";t[r]=7;a.split("").forEach(function(t){e[t]=t});return 7!==vh({},t)[r]||lh(vh({},e)).join("")!==a})?function tw(t,e){var r=uh(t);var a=arguments.length;var i=1;var n=ch.f;var o=fh.f;while(a>i){var s=hh(arguments[i++]);var l=n?ph(lh(s),n(s)):lh(s);var c=l.length;var f=0;var u;while(c>f){u=l[f++];if(!ih||oh(o,s,u))r[u]=s[u]}}return r}:vh;var bh=Wi;var mh=gh;bh({target:"Object",stat:true,arity:2,forced:Object.assign!==mh},{assign:mh});var yh=k;var wh=x;var Sh=B;var xh=Ws;var Oh=Eo;var kh=rt;var Ph=$.f;var Ch=Sh(Ph);var Th=Sh([].push);var Ih=yh&&wh(function(){var t=Object.create(null);t[2]=2;return!Ch(t,2)});var Ah=function(t){return function(e){var r=kh(e);var a=Oh(r);var i=Ih&&null===xh(r);var n=a.length;var o=0;var s=[];var l;while(n>o){l=a[o++];if(!yh||(i?l in r:Ch(r,l)))Th(s,t?[l,r[l]]:r[l])}return s}};var $h={entries:Ah(true),values:Ah(false)};var Rh=Wi;var Eh=$h.entries;Rh({target:"Object",stat:true},{entries:function ew(t){return Eh(t)}});var jh=Wi;var _h=fe;var Nh=Eo;var Fh=x;var Dh=Fh(function(){Nh(1)});jh({target:"Object",stat:true,forced:Dh},{keys:function rw(t){return Nh(_h(t))}});var Vh=sn;var Bh=gn;var Lh=Vh?{}.toString:function aw(){return"[object "+Bh(this)+"]"};var Hh=sn;var Mh=La;var Uh=Lh;if(!Hh)Mh(Object.prototype,"toString",Uh,{unsafe:true});var zh=w;var qh=x;var Gh=B;var Wh=rf;var Kh=Tu.trim;var Yh=mu;var Jh=Gh("".charAt);var Xh=zh.parseFloat;var Qh=zh.Symbol;var Zh=Qh&&Qh.iterator;var tv=1/Xh(Yh+"-0")!==-(1/0)||Zh&&!qh(function(){Xh(Object(Zh))});var ev=tv?function iw(t){var e=Kh(Wh(t));var r=Xh(e);return 0===r&&"-"===Jh(e,0)?-0:r}:Xh;var rv=Wi;var av=ev;rv({global:true,forced:parseFloat!==av},{parseFloat:av});var iv=w;var nv=x;var ov=B;var sv=rf;var lv=Tu.trim;var cv=mu;var fv=iv.parseInt;var uv=iv.Symbol;var hv=uv&&uv.iterator;var vv=/^[+-]?0x/i;var dv=ov(vv.exec);var pv=8!==fv(cv+"08")||22!==fv(cv+"0x16")||hv&&!nv(function(){fv(Object(hv))});var gv=pv?function nw(t,e){var r=lv(sv(t));return fv(r,e>>>0||(dv(vv,r)?16:10))}:fv;var bv=Wi;var mv=gv;bv({global:true,forced:parseInt!==mv},{parseInt:mv});var yv=ot;var wv=U;var Sv=Ae;var xv=Sv("match");var Ov=function(t){var e;return yv(t)&&(void 0!==(e=t[xv])?!!e:"RegExp"===wv(t))};var kv=vr;var Pv=function(){var t=kv(this);var e="";if(t.hasIndices)e+="d";if(t.global)e+="g";if(t.ignoreCase)e+="i";if(t.multiline)e+="m";if(t.dotAll)e+="s";if(t.unicode)e+="u";if(t.unicodeSets)e+="v";if(t.sticky)e+="y";return e};var Cv=A;var Tv=de;var Iv=ht;var Av=Pv;var $v=RegExp.prototype;var Rv=function(t){var e=t.flags;return void 0===e&&!("flags"in $v)&&!Tv(t,"flags")&&Iv($v,t)?Cv(Av,t):e};var Ev=x;var jv=w;var _v=jv.RegExp;var Nv=Ev(function(){var t=_v("a","y");t.lastIndex=2;return null!==t.exec("abcd")});var Fv=Nv||Ev(function(){return!_v("a","y").sticky});var Dv=Nv||Ev(function(){var t=_v("^r","gy");t.lastIndex=2;return null!==t.exec("str")});var Vv={BROKEN_CARET:Dv,MISSED_STICKY:Fv,UNSUPPORTED_Y:Nv};var Bv=or.f;var Lv=function(t,e,r){r in t||Bv(t,r,{configurable:true,get:function(){return e[r]},set:function(t){e[r]=t}})};var Hv=Na;var Mv=or;var Uv=function(t,e,r){if(r.get)Hv(r.get,e,{getter:true});if(r.set)Hv(r.set,e,{setter:true});return Mv.f(t,e,r)};var zv=ft;var qv=Uv;var Gv=Ae;var Wv=k;var Kv=Gv("species");var Yv=function(t){var e=zv(t);if(Wv&&e&&!e[Kv])qv(e,Kv,{configurable:true,get:function(){return this}})};var Jv=x;var Xv=w;var Qv=Xv.RegExp;var Zv=Jv(function(){var t=Qv(".","s");return!(t.dotAll&&t.test("\n")&&"s"===t.flags)});var td=x;var ed=w;var rd=ed.RegExp;var ad=td(function(){var t=rd("(?<a>b)","g");return"b"!==t.exec("b").groups.a||"bc"!=="b".replace(t,"$<a>c")});var id=k;var nd=w;var od=B;var sd=Bi;var ld=pu;var cd=Ir;var fd=ns;var ud=Ha.f;var hd=ht;var vd=Ov;var dd=rf;var pd=Rv;var gd=Vv;var bd=Lv;var md=La;var yd=x;var wd=de;var Sd=ga.enforce;var xd=Yv;var Od=Ae;var kd=Zv;var Pd=ad;var Cd=Od("match");var Td=nd.RegExp;var Id=Td.prototype;var Ad=nd.SyntaxError;var $d=od(Id.exec);var Rd=od("".charAt);var Ed=od("".replace);var jd=od("".indexOf);var _d=od("".slice);var Nd=/^\?<[^\s\d!#%&*+<=>@^][^\s!#%&*+<=>@^]*>/;var Fd=/a/g;var Dd=/a/g;var Vd=new Td(Fd)!==Fd;var Bd=gd.MISSED_STICKY;var Ld=gd.UNSUPPORTED_Y;var Hd=id&&(!Vd||Bd||kd||Pd||yd(function(){Dd[Cd]=false;return Td(Fd)!==Fd||Td(Dd)===Dd||"/a/i"!==String(Td(Fd,"i"))}));var Md=function(t){var e=t.length;var r=0;var a="";var i=false;var n;for(;r<=e;r++){n=Rd(t,r);if("\\"===n){a+=n+Rd(t,++r);continue}if(!i&&"."===n)a+="[\\s\\S]";else{if("["===n)i=true;else if("]"===n)i=false;a+=n}}return a};var Ud=function(t){var e=t.length;var r=0;var a="";var i=[];var n=fd(null);var o=false;var s=false;var l=0;var c="";var f;for(;r<=e;r++){f=Rd(t,r);if("\\"===f)f+=Rd(t,++r);else if("]"===f)o=false;else if(!o)switch(true){case"["===f:o=true;break;case"("===f:if($d(Nd,_d(t,r+1))){r+=2;s=true}a+=f;l++;continue;case">"===f&&s:if(""===c||wd(n,c))throw new Ad("Invalid capture group name");n[c]=true;i[i.length]=[c,l];s=false;c="";continue}if(s)c+=f;else a+=f}return[a,i]};if(sd("RegExp",Hd)){var zd=function ow(t,e){var r=hd(Id,this);var a=vd(t);var i=void 0===e;var n=[];var o=t;var s,l,c,f,u,h;if(!r&&a&&i&&t.constructor===zd)return t;if(a||hd(Id,t)){t=t.source;if(i)e=pd(o)}t=void 0===t?"":dd(t);e=void 0===e?"":dd(e);o=t;if(kd&&"dotAll"in Fd){l=!!e&&jd(e,"s")>-1;if(l)e=Ed(e,/s/g,"")}s=e;if(Bd&&"sticky"in Fd){c=!!e&&jd(e,"y")>-1;if(c&&Ld)e=Ed(e,/y/g,"")}if(Pd){f=Ud(t);t=f[0];n=f[1]}u=ld(Td(t,e),r?this:Id,zd);if(l||c||n.length){h=Sd(u);if(l){h.dotAll=true;h.raw=zd(Md(t),s)}if(c)h.sticky=true;if(n.length)h.groups=n}if(t!==o)try{cd(u,"source",""===o?"(?:)":o)}catch(v){}return u};for(var qd=ud(Td),Gd=0;qd.length>Gd;)bd(zd,Td,qd[Gd++]);Id.constructor=zd;zd.prototype=Id;md(nd,"RegExp",zd,{constructor:true})}xd("RegExp");var Wd=A;var Kd=B;var Yd=rf;var Jd=Pv;var Xd=Vv;var Qd=se;var Zd=ns;var tp=ga.get;var ep=Zv;var rp=ad;var ap=Qd("native-string-replace",String.prototype.replace);var ip=RegExp.prototype.exec;var np=ip;var op=Kd("".charAt);var sp=Kd("".indexOf);var lp=Kd("".replace);var cp=Kd("".slice);var fp=function(){var t=/a/;var e=/b*/g;Wd(ip,t,"a");Wd(ip,e,"a");return 0!==t.lastIndex||0!==e.lastIndex}();var up=Xd.BROKEN_CARET;var hp=void 0!==/()??/.exec("")[1];var vp=fp||hp||up||ep||rp;if(vp)np=function sw(t){var e=this;var r=tp(e);var a=Yd(t);var i=r.raw;var n,o,s,l,c,f,u;if(i){i.lastIndex=e.lastIndex;n=Wd(np,i,a);e.lastIndex=i.lastIndex;return n}var h=r.groups;var v=up&&e.sticky;var d=Wd(Jd,e);var p=e.source;var g=0;var b=a;if(v){d=lp(d,"y","");if(sp(d,"g")===-1)d+="g";b=cp(a,e.lastIndex);if(e.lastIndex>0&&(!e.multiline||e.multiline&&"\n"!==op(a,e.lastIndex-1))){p="(?: "+p+")";b=" "+b;g++}o=new RegExp("^(?:"+p+")",d)}if(hp)o=new RegExp("^"+p+"$(?!\\s)",d);if(fp)s=e.lastIndex;l=Wd(ip,v?o:e,b);if(v)if(l){l.input=cp(l.input,g);l[0]=cp(l[0],g);l.index=e.lastIndex;e.lastIndex+=l[0].length}else e.lastIndex=0;else if(fp&&l)e.lastIndex=e.global?l.index+l[0].length:s;if(hp&&l&&l.length>1)Wd(ap,l[0],o,function(){for(c=1;c<arguments.length-2;c++)if(void 0===arguments[c])l[c]=void 0});if(l&&h){l.groups=f=Zd(null);for(c=0;c<h.length;c++){u=h[c];f[u[0]]=l[u[1]]}}return l};var dp=np;var pp=Wi;var gp=dp;pp({target:"RegExp",proto:true,forced:/./.exec!==gp},{exec:gp});var bp=Dr.PROPER;var mp=La;var yp=vr;var wp=rf;var Sp=x;var xp=Rv;var Op="toString";var kp=RegExp.prototype;var Pp=kp[Op];var Cp=Sp(function(){return"/a/b"!==Pp.call({source:"a",flags:"b"})});var Tp=bp&&Pp.name!==Op;if(Cp||Tp)mp(kp,Op,function lw(){var t=yp(this);var e=wp(t.source);var r=wp(xp(t));return"/"+e+"/"+r},{unsafe:true});var Ip=Ov;var Ap=TypeError;var $p=function(t){if(Ip(t))throw new Ap("The method doesn't accept regular expressions");return t};var Rp=Ae;var Ep=Rp("match");var jp=function(t){var e=/./;try{"/./"[t](e)}catch(r){try{e[Ep]=false;return"/./"[t](e)}catch(a){}}return false};var _p=Wi;var Np=B;var Fp=$p;var Dp=Z;var Vp=rf;var Bp=jp;var Lp=Np("".indexOf);_p({target:"String",proto:true,forced:!Bp("includes")},{includes:function cw(t){return!!~Lp(Vp(Dp(this)),Vp(Fp(t)),arguments.length>1?arguments[1]:void 0)}});var Hp=C;var Mp=Function.prototype;var Up=Mp.apply;var zp=Mp.call;var qp="object"==typeof Reflect&&Reflect.apply||(Hp?zp.bind(Up):function(){return zp.apply(Up,arguments)});var Gp=A;var Wp=La;var Kp=dp;var Yp=x;var Jp=Ae;var Xp=Ir;var Qp=Jp("species");var Zp=RegExp.prototype;var tg=function(t,e,r,a){var i=Jp(t);var n=!Yp(function(){var e={};e[i]=function(){return 7};return 7!==""[t](e)});var o=n&&!Yp(function(){var e=false;var r=/a/;if("split"===t){r={};r.constructor={};r.constructor[Qp]=function(){return r};r.flags="";r[i]=/./[i]}r.exec=function(){e=true;return null};r[i]("");return!e});if(!n||!o||r){var s=/./[i];var l=e(i,""[t],function(t,e,r,a,i){var o=e.exec;if(o===Kp||o===Zp.exec){if(n&&!i)return{done:true,value:Gp(s,e,r,a)};return{done:true,value:Gp(t,r,e,a)}}return{done:false}});Wp(String.prototype,t,l[0]);Wp(Zp,i,l[1])}if(a)Xp(Zp[i],"sham",true)};var eg=B;var rg=Ga;var ag=rf;var ig=Z;var ng=eg("".charAt);var og=eg("".charCodeAt);var sg=eg("".slice);var lg=function(t){return function(e,r){var a=ag(ig(e));var i=rg(r);var n=a.length;var o,s;if(i<0||i>=n)return t?"":void 0;o=og(a,i);return o<55296||o>56319||i+1===n||(s=og(a,i+1))<56320||s>57343?t?ng(a,i):o:t?sg(a,i,i+2):(o-55296<<10)+(s-56320)+65536}};var cg={codeAt:lg(false),charAt:lg(true)};var fg=cg.charAt;var ug=function(t,e,r){return e+(r?fg(t,e).length:1)};var hg=B;var vg=fe;var dg=Math.floor;var pg=hg("".charAt);var gg=hg("".replace);var bg=hg("".slice);var mg=/\$([$&'`]|\d{1,2}|<[^>]*>)/g;var yg=/\$([$&'`]|\d{1,2})/g;var wg=function(t,e,r,a,i,n){var o=r+t.length;var s=a.length;var l=yg;if(void 0!==i){i=vg(i);l=mg}return gg(n,l,function(n,l){var c;switch(pg(l,0)){case"$":return"$";case"&":return t;case"`":return bg(e,0,r);case"'":return bg(e,o);case"<":c=i[bg(l,1,-1)];break;default:var f=+l;if(0===f)return n;if(f>s){var u=dg(f/10);if(0===u)return n;if(u<=s)return void 0===a[u-1]?pg(l,1):a[u-1]+pg(l,1);return n}c=a[f-1]}return void 0===c?"":c})};var Sg=A;var xg=vr;var Og=it;var kg=U;var Pg=dp;var Cg=TypeError;var Tg=function(t,e){var r=t.exec;if(Og(r)){var a=Sg(r,t,e);if(null!==a)xg(a);return a}if("RegExp"===kg(t))return Sg(Pg,t,e);throw new Cg("RegExp#exec called on incompatible receiver")};var Ig=qp;var Ag=A;var $g=B;var Rg=tg;var Eg=x;var jg=vr;var _g=it;var Ng=J;var Fg=Ga;var Dg=Za;var Vg=rf;var Bg=Z;var Lg=ug;var Hg=zt;var Mg=wg;var Ug=Tg;var zg=Ae;var qg=zg("replace");var Gg=Math.max;var Wg=Math.min;var Kg=$g([].concat);var Yg=$g([].push);var Jg=$g("".indexOf);var Xg=$g("".slice);var Qg=function(t){return void 0===t?t:String(t)};var Zg=function(){return"$0"==="a".replace(/./,"$0")}();var tb=function(){if(/./[qg])return""===/./[qg]("a","$0");return false}();var eb=!Eg(function(){var t=/./;t.exec=function(){var t=[];t.groups={a:"7"};return t};return"7"!=="".replace(t,"$<a>")});Rg("replace",function(t,e,r){var a=tb?"$":"$0";return[function i(t,r){var a=Bg(this);var i=Ng(t)?void 0:Hg(t,qg);return i?Ag(i,t,a,r):Ag(e,Vg(a),t,r)},function(t,i){var n=jg(this);var o=Vg(t);if("string"==typeof i&&Jg(i,a)===-1&&Jg(i,"$<")===-1){var s=r(e,n,o,i);if(s.done)return s.value}var l=_g(i);if(!l)i=Vg(i);var c=n.global;var f;if(c){f=n.unicode;n.lastIndex=0}var u=[];var h;while(true){h=Ug(n,o);if(null===h)break;Yg(u,h);if(!c)break;var v=Vg(h[0]);if(""===v)n.lastIndex=Lg(o,Dg(n.lastIndex),f)}var d="";var p=0;for(var g=0;g<u.length;g++){h=u[g];var b=Vg(h[0]);var m=Gg(Wg(Fg(h.index),o.length),0);var y=[];var w;for(var S=1;S<h.length;S++)Yg(y,Qg(h[S]));var x=h.groups;if(l){var O=Kg([b],y,m,o);if(void 0!==x)Yg(O,x);w=Vg(Ig(i,void 0,O))}else w=Mg(b,o,m,y,x,i);if(m>=p){d+=Xg(o,p,m)+w;p=m+b.length}}return d+Xg(o,p)}]},!eb||!Zg||tb);var rb=Object.is||function fw(t,e){return t===e?0!==t||1/t===1/e:t!==t&&e!==e};var ab=A;var ib=tg;var nb=vr;var ob=J;var sb=Z;var lb=rb;var cb=rf;var fb=zt;var ub=Tg;ib("search",function(t,e,r){return[function a(e){var r=sb(this);var a=ob(e)?void 0:fb(e,t);return a?ab(a,e,r):new RegExp(e)[t](cb(r))},function(t){var a=nb(this);var i=cb(t);var n=r(e,a,i);if(n.done)return n.value;var o=a.lastIndex;if(!lb(o,0))a.lastIndex=0;var s=ub(a,i);if(!lb(a.lastIndex,o))a.lastIndex=o;return null===s?-1:s.index}]});var hb=$n;var vb=Dt;var db=TypeError;var pb=function(t){if(hb(t))return t;throw new db(vb(t)+" is not a constructor")};var gb=vr;var bb=pb;var mb=J;var yb=Ae;var wb=yb("species");var Sb=function(t,e){var r=gb(t).constructor;var a;return void 0===r||mb(a=gb(r)[wb])?e:bb(a)};var xb=A;var Ob=B;var kb=tg;var Pb=vr;var Cb=J;var Tb=Z;var Ib=Sb;var Ab=ug;var $b=Za;var Rb=rf;var Eb=zt;var jb=Tg;var _b=Vv;var Nb=x;var Fb=_b.UNSUPPORTED_Y;var Db=4294967295;var Vb=Math.min;var Bb=Ob([].push);var Lb=Ob("".slice);var Hb=!Nb(function(){var t=/(?:)/;var e=t.exec;t.exec=function(){return e.apply(this,arguments)};var r="ab".split(t);return 2!==r.length||"a"!==r[0]||"b"!==r[1]});var Mb="c"==="abbc".split(/(b)*/)[1]||4!=="test".split(/(?:)/,-1).length||2!=="ab".split(/(?:ab)*/).length||4!==".".split(/(.?)(.?)/).length||".".split(/()()/).length>1||"".split(/.?/).length;kb("split",function(t,e,r){var a="0".split(void 0,0).length?function(t,r){return void 0===t&&0===r?[]:xb(e,this,t,r)}:e;return[function i(e,r){var i=Tb(this);var n=Cb(e)?void 0:Eb(e,t);return n?xb(n,e,i,r):xb(a,Rb(i),e,r)},function(t,i){var n=Pb(this);var o=Rb(t);if(!Mb){var s=r(a,n,o,i,a!==e);if(s.done)return s.value}var l=Ib(n,RegExp);var c=n.unicode;var f=(n.ignoreCase?"i":"")+(n.multiline?"m":"")+(n.unicode?"u":"")+(Fb?"g":"y");var u=new l(Fb?"^(?:"+n.source+")":n,f);var h=void 0===i?Db:i>>>0;if(0===h)return[];if(0===o.length)return null===jb(u,o)?[o]:[];var v=0;var d=0;var p=[];while(d<o.length){u.lastIndex=Fb?0:d;var g=jb(u,Fb?Lb(o,d):o);var b;if(null===g||(b=Vb($b(u.lastIndex+(Fb?d:0)),o.length))===v)d=Ab(o,d,c);else{Bb(p,Lb(o,v,d));if(p.length===h)return p;for(var m=1;m<=g.length-1;m++){Bb(p,g[m]);if(p.length===h)return p}d=v=b}}Bb(p,Lb(o,v));return p}]},Mb||!Hb,Fb);var Ub=Dr.PROPER;var zb=x;var qb=mu;var Gb="​…᠎";var Wb=function(t){return zb(function(){return!!qb[t]()||Gb[t]()!==Gb||Ub&&qb[t].name!==t})};var Kb=Wi;var Yb=Tu.trim;var Jb=Wb;Kb({target:"String",proto:true,forced:Jb("trim")},{trim:function uw(){return Yb(this)}});var Xb={CSSRuleList:0,CSSStyleDeclaration:0,CSSValueList:0,ClientRectList:0,DOMRectList:0,DOMStringList:0,DOMTokenList:1,DataTransferItemList:0,FileList:0,HTMLAllCollection:0,HTMLCollection:0,HTMLFormElement:0,HTMLSelectElement:0,MediaList:0,MimeTypeArray:0,NamedNodeMap:0,NodeList:1,PaintRequestList:0,Plugin:0,PluginArray:0,SVGLengthList:0,SVGNumberList:0,SVGPathSegList:0,SVGPointList:0,SVGStringList:0,SVGTransformList:0,SourceBufferList:0,StyleSheetList:0,TextTrackCueList:0,TextTrackList:0,TouchList:0};var Qb=Ge;var Zb=Qb("span").classList;var tm=Zb&&Zb.constructor&&Zb.constructor.prototype;var em=tm===Object.prototype?void 0:tm;var rm=ko.forEach;var am=Is;var im=am("forEach");var nm=!im?function hw(t){return rm(this,t,arguments.length>1?arguments[1]:void 0)}:[].forEach;var om=w;var sm=Xb;var lm=em;var cm=nm;var fm=Ir;var um=function(t){if(t&&t.forEach!==cm)try{fm(t,"forEach",cm)}catch(e){t.forEach=cm}};for(var hm in sm)if(sm[hm])um(om[hm]&&om[hm].prototype);um(lm);var vm=w;var dm=Xb;var pm=em;var gm=dc;var bm=Ir;var mm=ul;var ym=Ae;var wm=ym("iterator");var Sm=gm.values;var xm=function(t,e){if(t){if(t[wm]!==Sm)try{bm(t,wm,Sm)}catch(r){t[wm]=Sm}mm(t,e,true);if(dm[e])for(var a in gm)if(t[a]!==gm[a])try{bm(t,a,gm[a])}catch(r){t[a]=gm[a]}}};for(var Om in dm)xm(vm[Om]&&vm[Om].prototype,Om);xm(pm,"DOMTokenList");var km=Wi;var Pm=x;var Cm=fe;var Tm=Ws;var Im=Vs;var Am=Pm(function(){Tm(1)});km({target:"Object",stat:true,forced:Am,sham:!Im},{getPrototypeOf:function vw(t){return Tm(Cm(t))}});var $m=Wi;var Rm=co;var Em=S.f;var jm=Za;var _m=rf;var Nm=$p;var Fm=Z;var Dm=jp;var Vm=Rm("".slice);var Bm=Math.min;var Lm=Dm("endsWith");var Hm=!Lm&&!!function(){var t=Em(String.prototype,"endsWith");return t&&!t.writable}();$m({target:"String",proto:true,forced:!Hm&&!Lm},{endsWith:function dw(t){var e=_m(Fm(this));Nm(t);var r=arguments.length>1?arguments[1]:void 0;var a=e.length;var i=void 0===r?a:Bm(jm(r),a);var n=_m(t);return Vm(e,i-n.length,i)===n}});var Mm=A;var Um=tg;var zm=vr;var qm=J;var Gm=Za;var Wm=rf;var Km=Z;var Ym=zt;var Jm=ug;var Xm=Tg;Um("match",function(t,e,r){return[function a(e){var r=Km(this);var a=qm(e)?void 0:Ym(e,t);return a?Mm(a,e,r):new RegExp(e)[t](Wm(r))},function(t){var a=zm(this);var i=Wm(t);var n=r(e,a,i);if(n.done)return n.value;if(!a.global)return Xm(a,i);var o=a.unicode;a.lastIndex=0;var s=[];var l=0;var c;while(null!==(c=Xm(a,i))){var f=Wm(c[0]);s[l]=f;if(""===f)a.lastIndex=Jm(i,Gm(a.lastIndex),o);l++}return 0===l?null:s}]});var Qm=Wi;var Zm=co;var ty=S.f;var ey=Za;var ry=rf;var ay=$p;var iy=Z;var ny=jp;var oy=Zm("".slice);var sy=Math.min;var ly=ny("startsWith");var cy=!ly&&!!function(){var t=ty(String.prototype,"startsWith");return t&&!t.writable}();Qm({target:"String",proto:true,forced:!cy&&!ly},{startsWith:function pw(t){var e=ry(iy(this));ay(t);var r=ey(sy(arguments.length>1?arguments[1]:void 0,e.length));var a=ry(t);return oy(e,r,r+a.length)===a}});var fy={getBootstrapVersion:function gw(){var e=5;try{var r=t.fn.dropdown.Constructor.VERSION;if(void 0!==r)e=parseInt(r,10)}catch(a){}try{var i=bootstrap.Tooltip.VERSION;if(void 0!==i)e=parseInt(i,10)}catch(a){}return e},getIconsPrefix:function bw(t){return{bootstrap3:"glyphicon",bootstrap4:"fa",bootstrap5:"bi","bootstrap-table":"icon",bulma:"fa",foundation:"fa",materialize:"material-icons",semantic:"fa"}[t]||"fa"},getIcons:function mw(t){return{glyphicon:{paginationSwitchDown:"glyphicon-collapse-down icon-chevron-down",paginationSwitchUp:"glyphicon-collapse-up icon-chevron-up",refresh:"glyphicon-refresh icon-refresh",toggleOff:"glyphicon-list-alt icon-list-alt",toggleOn:"glyphicon-list-alt icon-list-alt",columns:"glyphicon-th icon-th",detailOpen:"glyphicon-plus icon-plus",detailClose:"glyphicon-minus icon-minus",fullscreen:"glyphicon-fullscreen",search:"glyphicon-search",clearSearch:"glyphicon-trash"},fa:{paginationSwitchDown:"fa-caret-square-down",paginationSwitchUp:"fa-caret-square-up",refresh:"fa-sync",toggleOff:"fa-toggle-off",toggleOn:"fa-toggle-on",columns:"fa-th-list",detailOpen:"fa-plus",detailClose:"fa-minus",fullscreen:"fa-arrows-alt",search:"fa-search",clearSearch:"fa-trash"},bi:{paginationSwitchDown:"bi-caret-down-square",paginationSwitchUp:"bi-caret-up-square",refresh:"bi-arrow-clockwise",toggleOff:"bi-toggle-off",toggleOn:"bi-toggle-on",columns:"bi-list-ul",detailOpen:"bi-plus",detailClose:"bi-dash",fullscreen:"bi-arrows-move",search:"bi-search",clearSearch:"bi-trash"},icon:{paginationSwitchDown:"icon-arrow-up-circle",paginationSwitchUp:"icon-arrow-down-circle",refresh:"icon-refresh-cw",toggleOff:"icon-toggle-right",toggleOn:"icon-toggle-right",columns:"icon-list",detailOpen:"icon-plus",detailClose:"icon-minus",fullscreen:"icon-maximize",search:"icon-search",clearSearch:"icon-trash-2"},"material-icons":{paginationSwitchDown:"grid_on",paginationSwitchUp:"grid_off",refresh:"refresh",toggleOff:"tablet",toggleOn:"tablet_android",columns:"view_list",detailOpen:"add",detailClose:"remove",fullscreen:"fullscreen",sort:"sort",search:"search",clearSearch:"delete"}}[t]||{}},getSearchInput:function yw(e){if("string"===typeof e.options.searchSelector)return t(e.options.searchSelector);return e.$toolbar.find(".search input")},extend:function ww(){var t=this;for(var e=arguments.length,r=new Array(e),a=0;a<e;a++)r[a]=arguments[a];var n=r[0]||{};var o=1;var s=false;var l;if("boolean"===typeof n){s=n;n=r[o]||{};o++}if("object"!==i(n)&&"function"!==typeof n)n={};for(;o<r.length;o++){var c=r[o];if("undefined"===typeof c||null===c)continue;for(var f in c){var u=c[f];if("__proto__"===f||n===u)continue;var h=Array.isArray(u);if(s&&u&&(this.isObject(u)||h)){var v=n[f];if(h&&Array.isArray(v))if(v.every(function(e){return!t.isObject(e)&&!Array.isArray(e)})){n[f]=u;continue}if(h&&!Array.isArray(v))l=[];else if(!h&&!this.isObject(v))l={};else l=v;n[f]=this.extend(s,l,u)}else if(void 0!==u)n[f]=u}}return n},sprintf:function Sw(t){for(var e=arguments.length,r=new Array(e>1?e-1:0),a=1;a<e;a++)r[a-1]=arguments[a];var i=true;var n=0;var o=t.replace(/%s/g,function(){var t=r[n++];if("undefined"===typeof t){i=false;return""}return t});return i?o:""},isObject:function xw(t){if("object"!==i(t)||null===t)return false;var e=t;while(null!==Object.getPrototypeOf(e))e=Object.getPrototypeOf(e);return Object.getPrototypeOf(t)===e},isEmptyObject:function Ow(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return 0===Object.entries(t).length&&t.constructor===Object},isNumeric:function kw(t){return!isNaN(parseFloat(t))&&isFinite(t)},getFieldTitle:function Pw(t,e){var r=b(t),a;try{for(r.s();!(a=r.n()).done;){var i=a.value;if(i.field===e)return i.title}}catch(n){r.e(n)}finally{r.f()}return""},setFieldIndex:function Cw(t){var e=0;var r=[];var a=b(t[0]),i;try{for(a.s();!(i=a.n()).done;){var n=i.value;e+=n.colspan||1}}catch(o){a.e(o)}finally{a.f()}for(var s=0;s<t.length;s++){r[s]=[];for(var l=0;l<e;l++)r[s][l]=false}for(var c=0;c<t.length;c++){var f=b(t[c]),u;try{for(f.s();!(u=f.n()).done;){var h=u.value;var v=h.rowspan||1;var d=h.colspan||1;var p=r[c].indexOf(false);h.colspanIndex=p;if(1===d){h.fieldIndex=p;if("undefined"===typeof h.field)h.field=p}else h.colspanGroup=h.colspan;for(var g=0;g<v;g++)for(var m=0;m<d;m++)r[c+g][p+m]=true}}catch(o){f.e(o)}finally{f.f()}}},normalizeAccent:function Tw(t){if("string"!==typeof t)return t;return t.normalize("NFD").replace(/[\u0300-\u036f]/g,"")},updateFieldGroup:function Iw(t,e){var r;var a=(r=[]).concat.apply(r,c(t));var i=b(t),n;try{for(i.s();!(n=i.n()).done;){var o=n.value;var s=b(o),l;try{for(s.s();!(l=s.n()).done;){var f=l.value;if(f.colspanGroup>1){var u=0;var h=function y(t){var e=a.filter(function(e){return e.fieldIndex===t});var r=e[e.length-1];if(e.length>1)for(var i=0;i<e.length-1;i++)e[i].visible=r.visible;if(r.visible)u++};for(var v=f.colspanIndex;v<f.colspanIndex+f.colspanGroup;v++)h(v);f.colspan=u;f.visible=u>0}}}catch(d){s.e(d)}finally{s.f()}}}catch(d){i.e(d)}finally{i.f()}if(t.length<2)return;var p=b(e),g;try{var m=function w(){var t=g.value;var e=a.filter(function(e){return e.fieldIndex===t.fieldIndex});if(e.length>1){var r=b(e),i;try{for(r.s();!(i=r.n()).done;){var n=i.value;n.visible=t.visible}}catch(o){r.e(o)}finally{r.f()}}};for(p.s();!(g=p.n()).done;)m()}catch(d){p.e(d)}finally{p.f()}},getScrollBarWidth:function Aw(){if(void 0===this.cachedWidth){var e=t("<div/>").addClass("fixed-table-scroll-inner");var r=t("<div/>").addClass("fixed-table-scroll-outer");r.append(e);t("body").append(r);var a=e[0].offsetWidth;r.css("overflow","scroll");var i=e[0].offsetWidth;if(a===i)i=r[0].clientWidth;r.remove();this.cachedWidth=a-i}return this.cachedWidth},calculateObjectValue:function $w(t,e,r,a){var n=e;if("string"===typeof e){var o=e.split(".");if(o.length>1){n=window;var s=b(o),l;try{for(s.s();!(l=s.n()).done;){var f=l.value;n=n[f]}}catch(u){s.e(u)}finally{s.f()}}else n=window[e]}if(null!==n&&"object"===i(n))return n;if("function"===typeof n)return n.apply(t,r||[]);if(!n&&"string"===typeof e&&r&&this.sprintf.apply(this,[e].concat(c(r))))return this.sprintf.apply(this,[e].concat(c(r)));return a},compareObjects:function Rw(t,e,r){var a=Object.keys(t);var i=Object.keys(e);if(r&&a.length!==i.length)return false;for(var n=0,o=a;n<o.length;n++){var s=o[n];if(i.includes(s)&&t[s]!==e[s])return false}return true},regexCompare:function Ew(t,e){try{var r=e.match(/^\/(.*?)\/([gim]*)$/);if(t.toString().search(r?new RegExp(r[1],r[2]):new RegExp(e,"gim"))!==-1)return true}catch(a){return false}return false},escapeApostrophe:function jw(t){return t.toString().replace(/'/g,"&#39;")},escapeHTML:function _w(t){if(!t)return t;return t.toString().replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")},unescapeHTML:function Nw(t){if("string"!==typeof t||!t)return t;return t.toString().replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"').replace(/&#39;/g,"'")},removeHTML:function Fw(t){if(!t)return t;return t.toString().replace(/(<([^>]+)>)/gi,"").replace(/&[#A-Za-z0-9]+;/gi,"").trim()},getRealDataAttr:function Dw(t){for(var e=0,r=Object.entries(t);e<r.length;e++){var a=l(r[e],2),i=a[0],n=a[1];var o=i.split(/(?=[A-Z])/).join("-").toLowerCase();if(o!==i){t[o]=n;delete t[i]}}return t},getItemField:function Vw(t,e,r){var a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:void 0;var i=t;if("undefined"!==typeof a)r=a;if("string"!==typeof e||t.hasOwnProperty(e))return r?this.escapeHTML(t[e]):t[e];var n=e.split(".");var o=b(n),s;try{for(o.s();!(s=o.n()).done;){var l=s.value;i=i&&i[l]}}catch(c){o.e(c)}finally{o.f()}return r?this.escapeHTML(i):i},isIEBrowser:function Bw(){return navigator.userAgent.includes("MSIE ")||/Trident.*rv:11\./.test(navigator.userAgent)},findIndex:function Lw(t,e){var r=b(t),a;try{for(r.s();!(a=r.n()).done;){var i=a.value;if(JSON.stringify(i)===JSON.stringify(e))return t.indexOf(i)}}catch(n){r.e(n)}finally{r.f()}return-1},trToData:function Hw(e,r){var a=this;var i=[];var n=[];r.each(function(r,o){var s=t(o);var l={};l._id=s.attr("id");l._class=s.attr("class");l._data=a.getRealDataAttr(s.data());l._style=s.attr("style");s.find(">td,>th").each(function(i,o){var s=t(o);var c=+s.attr("colspan")||1;var f=+s.attr("rowspan")||1;var u=i;for(;n[r]&&n[r][u];u++);for(var h=u;h<u+c;h++)for(var v=r;v<r+f;v++){if(!n[v])n[v]=[];n[v][h]=true}var d=e[u].field;l[d]=a.escapeApostrophe(s.html().trim());l["_".concat(d,"_id")]=s.attr("id");l["_".concat(d,"_class")]=s.attr("class");l["_".concat(d,"_rowspan")]=s.attr("rowspan");l["_".concat(d,"_colspan")]=s.attr("colspan");l["_".concat(d,"_title")]=s.attr("title");l["_".concat(d,"_data")]=a.getRealDataAttr(s.data());l["_".concat(d,"_style")]=s.attr("style")});i.push(l)});return i},sort:function Mw(t,e,r,a,i,n){if(void 0===t||null===t)t="";if(void 0===e||null===e)e="";if(a.sortStable&&t===e){t=i;e=n}if(this.isNumeric(t)&&this.isNumeric(e)){t=parseFloat(t);e=parseFloat(e);if(t<e)return r*-1;if(t>e)return r;return 0}if(a.sortEmptyLast){if(""===t)return 1;if(""===e)return-1}if(t===e)return 0;if("string"!==typeof t)t=t.toString();if(t.localeCompare(e)===-1)return r*-1;return r},getEventName:function Uw(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";e=e||"".concat(+new Date).concat(~~(1e6*Math.random()));return"".concat(t,"-").concat(e)},hasDetailViewIcon:function zw(t){return t.detailView&&t.detailViewIcon&&!t.cardView},getDetailViewIndexOffset:function qw(t){return this.hasDetailViewIcon(t)&&"right"!==t.detailViewAlign?1:0},checkAutoMergeCells:function Gw(t){var e=b(t),r;try{for(e.s();!(r=e.n()).done;){var a=r.value;for(var i=0,n=Object.keys(a);i<n.length;i++){var o=n[i];if(o.startsWith("_")&&(o.endsWith("_rowspan")||o.endsWith("_colspan")))return true}}}catch(s){e.e(s)}finally{e.f()}return false},deepCopy:function Ww(t){if(void 0===t)return t;return this.extend(true,Array.isArray(t)?[]:{},t)},debounce:function Kw(t,e,r){var a;return function i(){var i=this;var n=arguments;var o=function l(){a=null;if(!r)t.apply(i,n)};var s=r&&!a;clearTimeout(a);a=setTimeout(o,e);if(s)t.apply(i,n)}}};var uy="1.22.6";var hy=fy.getBootstrapVersion();var vy={3:{classes:{buttonsPrefix:"btn",buttons:"default",buttonsGroup:"btn-group",buttonsDropdown:"btn-group",pull:"pull",inputGroup:"input-group",inputPrefix:"input-",input:"form-control",select:"form-control",paginationDropdown:"btn-group dropdown",dropup:"dropup",dropdownActive:"active",paginationActive:"active",buttonActive:"active"},html:{toolbarDropdown:['<ul class="dropdown-menu" role="menu">',"</ul>"],toolbarDropdownItem:'<li class="dropdown-item-marker" role="menuitem"><label>%s</label></li>',toolbarDropdownSeparator:'<li class="divider"></li>',pageDropdown:['<ul class="dropdown-menu" role="menu">',"</ul>"],pageDropdownItem:'<li role="menuitem" class="%s"><a href="#">%s</a></li>',dropdownCaret:'<span class="caret"></span>',pagination:['<ul class="pagination%s">',"</ul>"],paginationItem:'<li class="page-item%s"><a class="page-link" aria-label="%s" href="javascript:void(0)">%s</a></li>',icon:'<i class="%s %s"></i>',inputGroup:'<div class="input-group">%s<span class="input-group-btn">%s</span></div>',searchInput:'<input class="%s%s" type="text" placeholder="%s">',searchButton:'<button class="%s" type="button" name="search" title="%s">%s %s</button>',searchClearButton:'<button class="%s" type="button" name="clearSearch" title="%s">%s %s</button>'}},4:{classes:{buttonsPrefix:"btn",buttons:"secondary",buttonsGroup:"btn-group",buttonsDropdown:"btn-group",pull:"float",inputGroup:"btn-group",inputPrefix:"form-control-",input:"form-control",select:"form-control",paginationDropdown:"btn-group dropdown",dropup:"dropup",dropdownActive:"active",paginationActive:"active",buttonActive:"active"},html:{toolbarDropdown:['<div class="dropdown-menu dropdown-menu-right">',"</div>"],toolbarDropdownItem:'<label class="dropdown-item dropdown-item-marker">%s</label>',pageDropdown:['<div class="dropdown-menu">',"</div>"],pageDropdownItem:'<a class="dropdown-item %s" href="#">%s</a>',toolbarDropdownSeparator:'<div class="dropdown-divider"></div>',dropdownCaret:'<span class="caret"></span>',pagination:['<ul class="pagination%s">',"</ul>"],paginationItem:'<li class="page-item%s"><a class="page-link" aria-label="%s" href="javascript:void(0)">%s</a></li>',icon:'<i class="%s %s"></i>',inputGroup:'<div class="input-group">%s<div class="input-group-append">%s</div></div>',searchInput:'<input class="%s%s" type="text" placeholder="%s">',searchButton:'<button class="%s" type="button" name="search" title="%s">%s %s</button>',searchClearButton:'<button class="%s" type="button" name="clearSearch" title="%s">%s %s</button>'}},5:{classes:{buttonsPrefix:"btn",buttons:"secondary",buttonsGroup:"btn-group",buttonsDropdown:"btn-group",pull:"float",inputGroup:"btn-group",inputPrefix:"form-control-",input:"form-control",select:"form-select",paginationDropdown:"btn-group dropdown",dropup:"dropup",dropdownActive:"active",paginationActive:"active",buttonActive:"active"},html:{dataToggle:"data-bs-toggle",toolbarDropdown:['<div class="dropdown-menu dropdown-menu-end">',"</div>"],toolbarDropdownItem:'<label class="dropdown-item dropdown-item-marker">%s</label>',pageDropdown:['<div class="dropdown-menu">',"</div>"],pageDropdownItem:'<a class="dropdown-item %s" href="#">%s</a>',toolbarDropdownSeparator:'<div class="dropdown-divider"></div>',dropdownCaret:'<span class="caret"></span>',pagination:['<ul class="pagination%s">',"</ul>"],paginationItem:'<li class="page-item%s"><a class="page-link" aria-label="%s" href="javascript:void(0)">%s</a></li>',icon:'<i class="%s %s"></i>',inputGroup:'<div class="input-group">%s%s</div>',searchInput:'<input class="%s%s" type="text" placeholder="%s">',searchButton:'<button class="%s" type="button" name="search" title="%s">%s %s</button>',searchClearButton:'<button class="%s" type="button" name="clearSearch" title="%s">%s %s</button>'}}}[hy];var dy={id:void 0,firstLoad:true,height:void 0,classes:"table table-bordered table-hover",buttons:{},theadClasses:"",striped:false,headerStyle:function Yw(t){return{}},rowStyle:function Jw(t,e){return{}},rowAttributes:function Xw(t,e){return{}},undefinedText:"-",locale:void 0,virtualScroll:false,virtualScrollItemHeight:void 0,sortable:true,sortClass:void 0,silentSort:true,sortEmptyLast:false,sortName:void 0,sortOrder:void 0,sortReset:false,sortStable:false,sortResetPage:false,rememberOrder:false,serverSort:true,customSort:void 0,columns:[[]],data:[],url:void 0,method:"get",cache:true,contentType:"application/json",dataType:"json",ajax:void 0,ajaxOptions:{},queryParams:function Qw(t){return t},queryParamsType:"limit",responseHandler:function Zw(t){return t},totalField:"total",totalNotFilteredField:"totalNotFiltered",dataField:"rows",footerField:"footer",pagination:false,paginationParts:["pageInfo","pageSize","pageList"],showExtendedPagination:false,paginationLoop:true,sidePagination:"client",totalRows:0,totalNotFiltered:0,pageNumber:1,pageSize:10,pageList:[10,25,50,100],paginationHAlign:"right",paginationVAlign:"bottom",paginationDetailHAlign:"left",paginationPreText:"&lsaquo;",paginationNextText:"&rsaquo;",paginationSuccessivelySize:5,paginationPagesBySide:1,paginationUseIntermediate:false,paginationLoadMore:false,search:false,searchable:false,searchHighlight:false,searchOnEnterKey:false,strictSearch:false,regexSearch:false,searchSelector:false,visibleSearch:false,showButtonIcons:true,showButtonText:false,showSearchButton:false,showSearchClearButton:false,trimOnSearch:true,searchAlign:"right",searchTimeOut:500,searchText:"",customSearch:void 0,showHeader:true,showFooter:false,footerStyle:function tS(t){return{}},searchAccentNeutralise:false,showColumns:false,showSearch:false,showPageGo:false,showColumnsToggleAll:false,showColumnsSearch:false,minimumCountColumns:1,showPaginationSwitch:false,showRefresh:false,showToggle:false,showFullscreen:false,smartDisplay:true,escape:false,escapeTitle:true,filterOptions:{filterAlgorithm:"and"},idField:void 0,selectItemName:"btSelectItem",clickToSelect:false,ignoreClickToSelectOn:function eS(t){var e=t.tagName;return["A","BUTTON"].includes(e)},singleSelect:false,checkboxHeader:true,maintainMetaData:false,multipleSelectRow:false,uniqueId:void 0,cardView:false,detailView:false,detailViewIcon:true,detailViewByClick:false,detailViewAlign:"left",detailFormatter:function rS(t,e){return""},detailFilter:function aS(t,e){return true},toolbar:void 0,toolbarAlign:"left",buttonsToolbar:void 0,buttonsAlign:"right",buttonsOrder:["search","paginationSwitch","refresh","toggle","fullscreen","columns"],buttonsPrefix:vy.classes.buttonsPrefix,buttonsClass:vy.classes.buttons,iconsPrefix:void 0,icons:{},iconSize:void 0,fixedScroll:false,loadingFontSize:"auto",loadingTemplate:function iS(t){return'<span class="loading-wrap">\n      <span class="loading-text">'.concat(t,'</span>\n      <span class="animation-wrap"><span class="animation-dot"></span></span>\n      </span>\n    ')},onAll:function nS(t,e){return false},onClickCell:function oS(t,e,r,a){return false},onDblClickCell:function sS(t,e,r,a){return false},onClickRow:function lS(t,e){return false},onDblClickRow:function cS(t,e){return false},onSort:function fS(t,e){return false},onCheck:function uS(t){return false},onUncheck:function hS(t){return false},onCheckAll:function vS(t){return false},onUncheckAll:function dS(t){return false},onCheckSome:function pS(t){return false},onUncheckSome:function gS(t){return false},onLoadSuccess:function bS(t){return false},onLoadError:function mS(t){return false},onColumnSwitch:function yS(t,e){return false},onColumnSwitchAll:function wS(t){return false},onPageChange:function SS(t,e){return false},onSearch:function xS(t){return false},onShowSearch:function OS(){return false},onToggle:function kS(t){return false},onPreBody:function PS(t){return false},onPostBody:function CS(){return false},onPostHeader:function TS(){return false},onPostFooter:function IS(){return false},onExpandRow:function AS(t,e,r){return false},onCollapseRow:function $S(t,e){return false},onRefreshOptions:function RS(t){return false},onRefresh:function ES(t){return false},onResetView:function jS(){return false},onScrollBody:function _S(){return false},onTogglePagination:function NS(t){return false},onVirtualScroll:function FS(t,e){return false}};var py={formatLoadingMessage:function DS(){return"Loading, please wait"},formatRecordsPerPage:function VS(t){return"".concat(t," rows per page")},formatShowingRows:function BS(t,e,r,a){if(void 0!==a&&a>0&&a>r)return"Showing ".concat(t," to ").concat(e," of ").concat(r," rows (filtered from ").concat(a," total rows)");return"Showing ".concat(t," to ").concat(e," of ").concat(r," rows")},formatSRPaginationPreText:function LS(){return"previous page"},formatSRPaginationPageText:function HS(t){return"to page ".concat(t)},formatSRPaginationNextText:function MS(){return"next page"},formatDetailPagination:function US(t){return"Showing ".concat(t," rows")},formatSearch:function zS(){return"Search"},formatShowSearch:function qS(){return"Show Search"},formatPageGo:function(){return"Go"},formatClearSearch:function GS(){return"Clear Search"},formatNoMatches:function WS(){return"No matching records found"},formatPaginationSwitch:function KS(){return"Hide/Show pagination"},formatPaginationSwitchDown:function YS(){return"Show pagination"},formatPaginationSwitchUp:function JS(){return"Hide pagination"},formatRefresh:function XS(){return"Refresh"},formatToggleOn:function QS(){return"Show card view"},formatToggleOff:function ZS(){return"Hide card view"},formatColumns:function tx(){return"Columns"},formatColumnsToggleAll:function ex(){return"Toggle all"},formatFullscreen:function rx(){return"Fullscreen"},formatAllRows:function ax(){return"All"}};var gy={field:void 0,title:void 0,titleTooltip:void 0,class:void 0,width:void 0,widthUnit:"px",rowspan:void 0,colspan:void 0,align:void 0,halign:void 0,falign:void 0,valign:void 0,cellStyle:void 0,radio:false,checkbox:false,checkboxEnabled:true,clickToSelect:true,showSelectTitle:false,sortable:false,sortName:void 0,order:"asc",sorter:void 0,visible:true,ignore:false,switchable:true,switchableLabel:void 0,cardVisible:true,searchable:true,formatter:void 0,footerFormatter:void 0,footerStyle:void 0,detailFormatter:void 0,searchFormatter:true,searchHighlightFormatter:false,escape:void 0,events:void 0};var by=["getOptions","refreshOptions","getData","getSelections","load","append","prepend","remove","removeAll","insertRow","updateRow","getRowByUniqueId","updateByUniqueId","removeByUniqueId","updateCell","updateCellByUniqueId","showRow","hideRow","getHiddenRows","showColumn","hideColumn","getVisibleColumns","getHiddenColumns","showAllColumns","hideAllColumns","mergeCells","checkAll","uncheckAll","checkInvert","check","uncheck","checkBy","uncheckBy","refresh","destroy","resetView","showLoading","hideLoading","togglePagination","toggleFullscreen","toggleView","resetSearch","filterBy","sortBy","scrollTo","getScrollPosition","selectPage","prevPage","nextPage","toggleDetailView","expandRow","collapseRow","expandRowByUniqueId","collapseRowByUniqueId","expandAllRows","collapseAllRows","updateColumnTitle","updateFormatText"];var my={"all.bs.table":"onAll","click-row.bs.table":"onClickRow","dbl-click-row.bs.table":"onDblClickRow","click-cell.bs.table":"onClickCell","dbl-click-cell.bs.table":"onDblClickCell","sort.bs.table":"onSort","check.bs.table":"onCheck","uncheck.bs.table":"onUncheck","check-all.bs.table":"onCheckAll","uncheck-all.bs.table":"onUncheckAll","check-some.bs.table":"onCheckSome","uncheck-some.bs.table":"onUncheckSome","load-success.bs.table":"onLoadSuccess","load-error.bs.table":"onLoadError","column-switch.bs.table":"onColumnSwitch","column-switch-all.bs.table":"onColumnSwitchAll","page-change.bs.table":"onPageChange","search.bs.table":"onSearch","toggle.bs.table":"onToggle","pre-body.bs.table":"onPreBody","post-body.bs.table":"onPostBody","post-header.bs.table":"onPostHeader","post-footer.bs.table":"onPostFooter","expand-row.bs.table":"onExpandRow","collapse-row.bs.table":"onCollapseRow","refresh-options.bs.table":"onRefreshOptions","reset-view.bs.table":"onResetView","refresh.bs.table":"onRefresh","scroll-body.bs.table":"onScrollBody","toggle-pagination.bs.table":"onTogglePagination","virtual-scroll.bs.table":"onVirtualScroll"};Object.assign(dy,py);var yy={VERSION:uy,THEME:"bootstrap".concat(hy),CONSTANTS:vy,DEFAULTS:dy,COLUMN_DEFAULTS:gy,METHODS:by,EVENTS:my,LOCALES:{en:py,"en-US":py}};var wy=50;var Sy=4;var xy=function(){function t(e){var r=this;n(this,t);this.rows=e.rows;this.scrollEl=e.scrollEl;this.contentEl=e.contentEl;this.callback=e.callback;this.itemHeight=e.itemHeight;this.cache={};this.scrollTop=this.scrollEl.scrollTop;this.initDOM(this.rows,e.fixedScroll);this.scrollEl.scrollTop=this.scrollTop;this.lastCluster=0;var a=function i(){if(r.lastCluster!==(r.lastCluster=r.getNum())){r.initDOM(r.rows);r.callback(r.startIndex,r.endIndex)}};this.scrollEl.addEventListener("scroll",a,false);this.destroy=function(){r.contentEl.innerHtml="";r.scrollEl.removeEventListener("scroll",a,false)}}return s(t,[{key:"initDOM",value:function e(t,r){if("undefined"===typeof this.clusterHeight){this.cache.scrollTop=this.scrollEl.scrollTop;this.cache.data=this.contentEl.innerHTML=t[0]+t[0]+t[0];this.getRowsHeight(t)}else if(0===this.blockHeight)this.getRowsHeight(t);var a=this.initData(t,this.getNum(r));var i=a.rows.join("");var n=this.checkChanges("data",i);var o=this.checkChanges("top",a.topOffset);var s=this.checkChanges("bottom",a.bottomOffset);var l=[];if(n&&o){if(a.topOffset)l.push(this.getExtra("top",a.topOffset));l.push(i);if(a.bottomOffset)l.push(this.getExtra("bottom",a.bottomOffset));this.startIndex=a.start;this.endIndex=a.end;this.contentEl.innerHTML=l.join("");if(r)this.contentEl.scrollTop=this.cache.scrollTop}else if(s)this.contentEl.lastChild.style.height="".concat(a.bottomOffset,"px")}},{key:"getRowsHeight",value:function r(){if("undefined"===typeof this.itemHeight||0===this.itemHeight){var t=this.contentEl.children;var e=t[Math.floor(t.length/2)];this.itemHeight=e.offsetHeight}this.blockHeight=this.itemHeight*wy;this.clusterRows=wy*Sy;this.clusterHeight=this.blockHeight*Sy}},{key:"getNum",value:function a(t){this.scrollTop=t?this.cache.scrollTop:this.scrollEl.scrollTop;return Math.floor(this.scrollTop/(this.clusterHeight-this.blockHeight))||0}},{key:"initData",value:function i(t,e){if(t.length<wy)return{topOffset:0,bottomOffset:0,rowsAbove:0,rows:t};var r=Math.max((this.clusterRows-wy)*e,0);var a=r+this.clusterRows;var i=Math.max(r*this.itemHeight,0);var n=Math.max((t.length-a)*this.itemHeight,0);var o=[];var s=r;if(i<1)s++;for(var l=r;l<a;l++)t[l]&&o.push(t[l]);return{start:r,end:a,topOffset:i,bottomOffset:n,rowsAbove:s,rows:o}}},{key:"checkChanges",value:function o(t,e){var r=e!==this.cache[t];this.cache[t]=e;return r}},{key:"getExtra",value:function l(t,e){var r=document.createElement("tr");r.className="virtual-scroll-".concat(t);if(e)r.style.height="".concat(e,"px");return r.outerHTML}}])}();var Oy=function(){function e(r,a){n(this,e);this.options=a;this.$el=t(r);this.$el_=this.$el.clone();this.timeoutId_=0;this.timeoutFooter_=0}return s(e,[{key:"init",value:function r(){this.initConstants();this.initLocale();this.initContainer();this.initTable();this.initHeader();this.initData();this.initHiddenRows();this.initToolbar();this.initPagination();this.initBody();this.initSearchText();this.initServer()}},{key:"initConstants",value:function a(){var e=this.options;this.constants=yy.CONSTANTS;this.constants.theme=t.fn.bootstrapTable.theme;this.constants.dataToggle=this.constants.html.dataToggle||"data-toggle";var r=fy.getIconsPrefix(t.fn.bootstrapTable.theme);if("string"===typeof e.icons)e.icons=fy.calculateObjectValue(null,e.icons);e.iconsPrefix=e.iconsPrefix||t.fn.bootstrapTable.defaults.iconsPrefix||r;e.icons=Object.assign(fy.getIcons(e.iconsPrefix),t.fn.bootstrapTable.defaults.icons,e.icons);var a=e.buttonsPrefix?"".concat(e.buttonsPrefix,"-"):"";this.constants.buttonsClass=[e.buttonsPrefix,a+e.buttonsClass,fy.sprintf("".concat(a,"%s"),e.iconSize)].join(" ").trim();this.buttons=fy.calculateObjectValue(this,e.buttons,[],{});if("object"!==i(this.buttons))this.buttons={}}},{key:"initLocale",value:function o(){if(this.options.locale){var r=t.fn.bootstrapTable.locales;var a=this.options.locale.split(/-|_/);a[0]=a[0].toLowerCase();if(a[1])a[1]=a[1].toUpperCase();var i={};if(r[this.options.locale])i=r[this.options.locale];else if(r[a.join("-")])i=r[a.join("-")];else if(r[a[0]])i=r[a[0]];this._defaultLocales=this._defaultLocales||{};for(var n=0,o=Object.entries(i);n<o.length;n++){var s=l(o[n],2),c=s[0],f=s[1];var u=this._defaultLocales.hasOwnProperty(c)?this._defaultLocales[c]:e.DEFAULTS[c];if(this.options[c]!==u)continue;this.options[c]=f;this._defaultLocales[c]=f}}}},{key:"initContainer",value:function f(){var e=["top","both"].includes(this.options.paginationVAlign)?'<div class="fixed-table-pagination clearfix"></div>':"";var r=["bottom","both"].includes(this.options.paginationVAlign)?'<div class="fixed-table-pagination"></div>':"";var a=fy.calculateObjectValue(this.options,this.options.loadingTemplate,[this.options.formatLoadingMessage()]);this.$container=t('\n      <div class="bootstrap-table '.concat(this.constants.theme,'">\n      <div class="fixed-table-toolbar"></div>\n      ').concat(e,'\n      <div class="fixed-table-container">\n      <div class="fixed-table-header"><table></table></div>\n      <div class="fixed-table-body">\n      <div class="fixed-table-loading">\n      ').concat(a,'\n      </div>\n      </div>\n      <div class="fixed-table-footer"></div>\n      </div>\n      ').concat(r,"\n      </div>\n    "));this.$container.insertAfter(this.$el);this.$tableContainer=this.$container.find(".fixed-table-container");this.$tableHeader=this.$container.find(".fixed-table-header");this.$tableBody=this.$container.find(".fixed-table-body");this.$tableLoading=this.$container.find(".fixed-table-loading");this.$tableFooter=this.$el.find("tfoot");if(this.options.buttonsToolbar)this.$toolbar=t("body").find(this.options.buttonsToolbar);else this.$toolbar=this.$container.find(".fixed-table-toolbar");this.$pagination=this.$container.find(".fixed-table-pagination");this.$tableBody.append(this.$el);this.$container.after('<div class="clearfix"></div>');this.$el.addClass(this.options.classes);this.$tableLoading.addClass(this.options.classes);if(this.options.striped)this.$el.addClass("table-striped");if(this.options.height){this.$tableContainer.addClass("fixed-height");if(this.options.showFooter)this.$tableContainer.addClass("has-footer");if(this.options.classes.split(" ").includes("table-bordered")){this.$tableBody.append('<div class="fixed-table-border"></div>');this.$tableBorder=this.$tableBody.find(".fixed-table-border");this.$tableLoading.addClass("fixed-table-border")}this.$tableFooter=this.$container.find(".fixed-table-footer")}}},{key:"initTable",value:function u(){var r=this;var a=[];this.$header=this.$el.find(">thead");if(!this.$header.length)this.$header=t('<thead class="'.concat(this.options.theadClasses,'"></thead>')).appendTo(this.$el);else if(this.options.theadClasses)this.$header.addClass(this.options.theadClasses);this._headerTrClasses=[];this._headerTrStyles=[];this.$header.find("tr").each(function(e,i){var n=t(i);var o=[];n.find("th").each(function(e,r){var a=t(r);if("undefined"!==typeof a.data("field"))a.data("field","".concat(a.data("field")));var i=Object.assign({},a.data());for(var n in i)if(t.fn.bootstrapTable.columnDefaults.hasOwnProperty(n))delete i[n];o.push(fy.extend({},{_data:fy.getRealDataAttr(i),title:a.html(),class:a.attr("class"),titleTooltip:a.attr("title"),rowspan:a.attr("rowspan")?+a.attr("rowspan"):void 0,colspan:a.attr("colspan")?+a.attr("colspan"):void 0},a.data()))});a.push(o);if(n.attr("class"))r._headerTrClasses.push(n.attr("class"));if(n.attr("style"))r._headerTrStyles.push(n.attr("style"))});if(!Array.isArray(this.options.columns[0]))this.options.columns=[this.options.columns];this.options.columns=fy.extend(true,[],a,this.options.columns);this.columns=[];this.fieldsColumnsIndex=[];fy.setFieldIndex(this.options.columns);this.options.columns.forEach(function(t,a){t.forEach(function(t,i){var n=fy.extend({},e.COLUMN_DEFAULTS,t,{passed:t});if("undefined"!==typeof n.fieldIndex){r.columns[n.fieldIndex]=n;r.fieldsColumnsIndex[n.field]=n.fieldIndex}r.options.columns[a][i]=n})});if(!this.options.data.length){var i=fy.trToData(this.columns,this.$el.find(">tbody>tr"));if(i.length){this.options.data=i;this.fromHtml=true}}if(!(this.options.pagination&&"server"!==this.options.sidePagination))this.footerData=fy.trToData(this.columns,this.$el.find(">tfoot>tr"));if(this.footerData)this.$el.find("tfoot").html("<tr></tr>");if(!this.options.showFooter||this.options.cardView)this.$tableFooter.hide();else this.$tableFooter.show()}},{key:"initHeader",value:function h(){var e=this;var r={};var a=[];this.header={fields:[],styles:[],classes:[],formatters:[],detailFormatters:[],events:[],sorters:[],sortNames:[],cellStyles:[],searchables:[]};fy.updateFieldGroup(this.options.columns,this.columns);this.options.columns.forEach(function(t,n){var o=[];o.push("<tr".concat(fy.sprintf(' class="%s"',e._headerTrClasses[n])," ").concat(fy.sprintf(' style="%s"',e._headerTrStyles[n]),">"));var s="";if(0===n&&fy.hasDetailViewIcon(e.options)){var c=e.options.columns.length>1?' rowspan="'.concat(e.options.columns.length,'"'):"";s='<th class="detail"'.concat(c,'>\n          <div class="fht-cell"></div>\n          </th>')}if(s&&"right"!==e.options.detailViewAlign)o.push(s);t.forEach(function(t,a){var s=fy.sprintf(' class="%s"',t["class"]);var c=t.widthUnit;var f=parseFloat(t.width);var u=t.halign?t.halign:t.align;var h=fy.sprintf("text-align: %s; ",u);var v=fy.sprintf("text-align: %s; ",t.align);var d=fy.sprintf("vertical-align: %s; ",t.valign);d+=fy.sprintf("width: %s; ",(t.checkbox||t.radio)&&!f?!t.showSelectTitle?"36px":void 0:f?f+c:void 0);if("undefined"===typeof t.fieldIndex&&!t.visible)return;var p=fy.calculateObjectValue(null,e.options.headerStyle,[t]);var g=[];var b=[];var m="";if(p&&p.css)for(var y=0,w=Object.entries(p.css);y<w.length;y++){var S=l(w[y],2),x=S[0],O=S[1];g.push("".concat(x,": ").concat(O))}if(p&&p.classes)m=fy.sprintf(' class="%s"',t["class"]?[t["class"],p.classes].join(" "):p.classes);if("undefined"!==typeof t.fieldIndex){e.header.fields[t.fieldIndex]=t.field;e.header.styles[t.fieldIndex]=v+d;e.header.classes[t.fieldIndex]=s;e.header.formatters[t.fieldIndex]=t.formatter;e.header.detailFormatters[t.fieldIndex]=t.detailFormatter;e.header.events[t.fieldIndex]=t.events;e.header.sorters[t.fieldIndex]=t.sorter;e.header.sortNames[t.fieldIndex]=t.sortName;e.header.cellStyles[t.fieldIndex]=t.cellStyle;e.header.searchables[t.fieldIndex]=t.searchable;if(!t.visible)return;if(e.options.cardView&&!t.cardVisible)return;r[t.field]=t}if(Object.keys(t._data||{}).length>0)for(var k=0,P=Object.entries(t._data);k<P.length;k++){var C=l(P[k],2),T=C[0],I=C[1];b.push("data-".concat(T,"='").concat("object"===i(I)?JSON.stringify(I):I,"'"))}o.push("<th".concat(fy.sprintf(' title="%s"',t.titleTooltip)),t.checkbox||t.radio?fy.sprintf(' class="bs-checkbox %s"',t["class"]||""):m||s,fy.sprintf(' style="%s"',h+d+g.join("; ")||void 0),fy.sprintf(' rowspan="%s"',t.rowspan),fy.sprintf(' colspan="%s"',t.colspan),fy.sprintf(' data-field="%s"',t.field),0===a&&n>0?" data-not-first-th":"",b.length>0?b.join(" "):"",">");o.push(fy.sprintf('<div class="th-inner %s">',e.options.sortable&&t.sortable?"sortable".concat("center"===u?" sortable-center":""," both"):""));var A=e.options.escape&&e.options.escapeTitle?fy.escapeHTML(t.title):t.title;var $=A;if(t.checkbox){A="";if(!e.options.singleSelect&&e.options.checkboxHeader)A='<label><input name="btSelectAll" type="checkbox" /><span></span></label>';e.header.stateField=t.field}if(t.radio){A="";e.header.stateField=t.field}if(!A&&t.showSelectTitle)A+=$;o.push(A);o.push("</div>");o.push('<div class="fht-cell"></div>');o.push("</div>");o.push("</th>")});if(s&&"right"===e.options.detailViewAlign)o.push(s);o.push("</tr>");if(o.length>3)a.push(o.join(""))});this.$header.html(a.join(""));this.$header.find("th[data-field]").each(function(e,a){t(a).data(r[t(a).data("field")])});this.$container.off("click",".th-inner").on("click",".th-inner",function(r){var a=t(r.currentTarget);if(e.options.detailView&&!a.parent().hasClass("bs-checkbox"))if(a.closest(".bootstrap-table")[0]!==e.$container[0])return false;if(e.options.sortable&&a.parent().data().sortable)e.onSort(r)});var n=fy.getEventName("resize.bootstrap-table",this.$el.attr("id"));t(window).off(n);if(!this.options.showHeader||this.options.cardView){this.$header.hide();this.$tableHeader.hide();this.$tableLoading.css("top",0)}else{this.$header.show();this.$tableHeader.show();this.$tableLoading.css("top",this.$header.outerHeight()+1);this.getCaret();t(window).on(n,function(){return e.resetView()})}this.$selectAll=this.$header.find('[name="btSelectAll"]');this.$selectAll.off("click").on("click",function(r){r.stopPropagation();var a=t(r.currentTarget).prop("checked");e[a?"checkAll":"uncheckAll"]();e.updateSelected()})}},{key:"initData",value:function v(t,e){if("append"===e)this.options.data=this.options.data.concat(t);else if("prepend"===e)this.options.data=[].concat(t).concat(this.options.data);else{t=t||fy.deepCopy(this.options.data);this.options.data=Array.isArray(t)?t:t[this.options.dataField]}this.data=c(this.options.data);if(this.options.sortReset)this.unsortedData=c(this.data);if("server"===this.options.sidePagination)return;this.initSort()}},{key:"initSort",value:function d(){var t=this;var e=this.options.sortName;var r="desc"===this.options.sortOrder?-1:1;var a=this.header.fields.indexOf(this.options.sortName);var i=0;if(a!==-1){if(this.options.sortStable)this.data.forEach(function(t,e){if(!t.hasOwnProperty("_position"))t._position=e});if(this.options.customSort)fy.calculateObjectValue(this.options,this.options.customSort,[this.options.sortName,this.options.sortOrder,this.data]);else this.data.sort(function(i,n){if(t.header.sortNames[a])e=t.header.sortNames[a];var o=fy.getItemField(i,e,t.options.escape);var s=fy.getItemField(n,e,t.options.escape);var l=fy.calculateObjectValue(t.header,t.header.sorters[a],[o,s,i,n]);if(void 0!==l){if(t.options.sortStable&&0===l)return r*(i._position-n._position);return r*l}return fy.sort(o,s,r,t.options,i._position,n._position)});if(void 0!==this.options.sortClass){clearTimeout(i);i=setTimeout(function(){t.$el.removeClass(t.options.sortClass);var e=t.$header.find('[data-field="'.concat(t.options.sortName,'"]')).index();t.$el.find("tr td:nth-child(".concat(e+1,")")).addClass(t.options.sortClass)},250)}}else if(this.options.sortReset)this.data=c(this.unsortedData)}},{key:"sortBy",value:function p(t){this.options.sortName=t.field;this.options.sortOrder=t.hasOwnProperty("sortOrder")?t.sortOrder:"asc";this._sort()}},{key:"onSort",value:function g(e){var r=e.type,a=e.currentTarget;var i="keypress"===r?t(a):t(a).parent();var n=this.$header.find("th").eq(i.index());this.$header.add(this.$header_).find("span.order").remove();if(this.options.sortName===i.data("field")){var o=this.options.sortOrder;var s=this.columns[this.fieldsColumnsIndex[i.data("field")]].sortOrder||this.columns[this.fieldsColumnsIndex[i.data("field")]].order;if(void 0===o)this.options.sortOrder="asc";else if("asc"===o)this.options.sortOrder=this.options.sortReset?"asc"===s?"desc":void 0:"desc";else if("desc"===this.options.sortOrder)this.options.sortOrder=this.options.sortReset?"desc"===s?"asc":void 0:"asc";if(void 0===this.options.sortOrder)this.options.sortName=void 0}else{this.options.sortName=i.data("field");if(this.options.rememberOrder)this.options.sortOrder="asc"===i.data("order")?"desc":"asc";else this.options.sortOrder=this.columns[this.fieldsColumnsIndex[i.data("field")]].sortOrder||this.columns[this.fieldsColumnsIndex[i.data("field")]].order}i.add(n).data("order",this.options.sortOrder);this.getCaret();this._sort()}},{key:"_sort",value:function m(){if("server"===this.options.sidePagination&&this.options.serverSort){this.options.pageNumber=1;this.trigger("sort",this.options.sortName,this.options.sortOrder);this.initServer(this.options.silentSort);return}if(this.options.pagination&&this.options.sortResetPage){this.options.pageNumber=1;this.initPagination()}this.trigger("sort",this.options.sortName,this.options.sortOrder);this.initSort();this.initBody()}},{key:"initToolbar",value:function y(){var e=this;var r=this.options;var a=[];var n=0;var o;var s=0;if(this.$toolbar.find(".bs-bars").children().length)t("body").append(t(r.toolbar));this.$toolbar.html("");if("string"===typeof r.toolbar||"object"===i(r.toolbar))t(fy.sprintf('<div class="bs-bars %s-%s"></div>',this.constants.classes.pull,r.toolbarAlign)).appendTo(this.$toolbar).append(t(r.toolbar));a=['<div class="'.concat(["columns","columns-".concat(r.buttonsAlign),this.constants.classes.buttonsGroup,"".concat(this.constants.classes.pull,"-").concat(r.buttonsAlign)].join(" "),'">')];if("string"===typeof r.buttonsOrder)r.buttonsOrder=r.buttonsOrder.replace(/\[|\]| |'/g,"").split(",");this.buttons=Object.assign(this.buttons,{search:{text:r.formatSearch(),icon:r.icons.search,render:false,event:this.toggleShowSearch,attributes:{"aria-label":r.formatShowSearch(),title:r.formatShowSearch()}},paginationSwitch:{text:r.pagination?r.formatPaginationSwitchUp():r.formatPaginationSwitchDown(),icon:r.pagination?r.icons.paginationSwitchDown:r.icons.paginationSwitchUp,render:false,event:this.togglePagination,attributes:{"aria-label":r.formatPaginationSwitch(),title:r.formatPaginationSwitch()}},refresh:{text:r.formatRefresh(),icon:r.icons.refresh,render:false,event:this.refresh,attributes:{"aria-label":r.formatRefresh(),title:r.formatRefresh()}},toggle:{text:r.formatToggleOn(),icon:r.icons.toggleOff,render:false,event:this.toggleView,attributes:{"aria-label":r.formatToggleOn(),title:r.formatToggleOn()}},fullscreen:{text:r.formatFullscreen(),icon:r.icons.fullscreen,render:false,event:this.toggleFullscreen,attributes:{"aria-label":r.formatFullscreen(),title:r.formatFullscreen()}},columns:{render:false,html:function z(){var z=[];z.push('<div class="keep-open '.concat(e.constants.classes.buttonsDropdown,'">\n            <button class="').concat(e.constants.buttonsClass,' dropdown-toggle" type="button" ').concat(e.constants.dataToggle,'="dropdown"\n            aria-label="').concat(r.formatColumns(),'" title="').concat(r.formatColumns(),'">\n            ').concat(r.showButtonIcons?fy.sprintf(e.constants.html.icon,r.iconsPrefix,r.icons.columns):"","\n            ").concat(r.showButtonText?r.formatColumns():"","\n            ").concat(e.constants.html.dropdownCaret,"\n            </button>\n            ").concat(e.constants.html.toolbarDropdown[0]));if(r.showColumnsSearch){z.push(fy.sprintf(e.constants.html.toolbarDropdownItem,fy.sprintf('<input type="text" class="%s" name="columnsSearch" placeholder="%s" autocomplete="off">',e.constants.classes.input,r.formatSearch())));z.push(e.constants.html.toolbarDropdownSeparator)}if(r.showColumnsToggleAll){var t=e.getVisibleColumns().length===e.columns.filter(function(t){return!e.isSelectionColumn(t)}).length;z.push(fy.sprintf(e.constants.html.toolbarDropdownItem,fy.sprintf('<input type="checkbox" class="toggle-all" %s> <span>%s</span>',t?'checked="checked"':"",r.formatColumnsToggleAll())));z.push(e.constants.html.toolbarDropdownSeparator)}var a=0;e.columns.forEach(function(t){if(t.visible)a++});e.columns.forEach(function(t,i){if(e.isSelectionColumn(t))return;if(r.cardView&&!t.cardVisible)return;if(t.ignore)return;var n=t.visible?' checked="checked"':"";var o=a<=r.minimumCountColumns&&n?' disabled="disabled"':"";if(t.switchable){z.push(fy.sprintf(e.constants.html.toolbarDropdownItem,fy.sprintf('<input type="checkbox" data-field="%s" value="%s"%s%s> <span>%s</span>',t.field,i,n,o,t.switchableLabel||t.title)));s++}});z.push(e.constants.html.toolbarDropdown[1],"</div>");return z.join("")}}});var c={};for(var f=0,u=Object.entries(this.buttons);f<u.length;f++){var h=l(u[f],2),v=h[0],d=h[1];var p=void 0;if(d.hasOwnProperty("html")){if("function"===typeof d.html)p=d.html();else if("string"===typeof d.html)p=d.html}else{var g=this.constants.buttonsClass;if(d.hasOwnProperty("attributes")&&d.attributes["class"])g+=" ".concat(d.attributes["class"]);p='<button class="'.concat(g,'" type="button" name="').concat(v,'"');if(d.hasOwnProperty("attributes"))for(var m=0,y=Object.entries(d.attributes);m<y.length;m++){var w=l(y[m],2),S=w[0],x=w[1];if("class"===S)continue;p+=" ".concat(S,'="').concat(x,'"')}p+=">";if(r.showButtonIcons&&d.hasOwnProperty("icon"))p+="".concat(fy.sprintf(this.constants.html.icon,r.iconsPrefix,d.icon)," ");if(r.showButtonText&&d.hasOwnProperty("text"))p+=d.text;p+="</button>"}c[v]=p;var O="show".concat(v.charAt(0).toUpperCase()).concat(v.substring(1));var k=r[O];if((!d.hasOwnProperty("render")||d.hasOwnProperty("render")&&d.render)&&(void 0===k||true===k))r[O]=true;if(!r.buttonsOrder.includes(v))r.buttonsOrder.push(v)}var P=b(r.buttonsOrder),C;try{for(P.s();!(C=P.n()).done;){var T=C.value;var I=r["show".concat(T.charAt(0).toUpperCase()).concat(T.substring(1))];if(I)a.push(c[T])}}catch(A){P.e(A)}finally{P.f()}a.push("</div>");if(this.showToolbar||a.length>2)this.$toolbar.append(a.join(""));if(r.showSearch)this.$toolbar.find('button[name="showSearch"]').off("click").on("click",function(){return e.toggleShowSearch()});var $=function q(){var t=l(E[R],2),r=t[0],a=t[1];if(a.hasOwnProperty("event")){if("function"===typeof a.event||"string"===typeof a.event){var i="string"===typeof a.event?window[a.event]:a.event;e.$toolbar.find('button[name="'.concat(r,'"]')).off("click").on("click",function(){return i.call(e)});return 1}var n=function c(){var t=l(s[o],2),a=t[0],i=t[1];var n="string"===typeof i?window[i]:i;e.$toolbar.find('button[name="'.concat(r,'"]')).off(a).on(a,function(){return n.call(e)})};for(var o=0,s=Object.entries(a.event);o<s.length;o++)n()}};for(var R=0,E=Object.entries(this.buttons);R<E.length;R++)if($())continue;if(r.showColumns){o=this.$toolbar.find(".keep-open");var j=o.find('input[type="checkbox"]:not(".toggle-all")');var _=o.find('input[type="checkbox"].toggle-all');if(s<=r.minimumCountColumns)o.find("input").prop("disabled",true);o.find("li, label").off("click").on("click",function(t){t.stopImmediatePropagation()});j.off("click").on("click",function(r){var a=r.currentTarget;var i=t(a);e._toggleColumn(i.val(),i.prop("checked"),false);e.trigger("column-switch",i.data("field"),i.prop("checked"));_.prop("checked",j.filter(":checked").length===e.columns.filter(function(t){return!e.isSelectionColumn(t)}).length)});_.off("click").on("click",function(r){var a=r.currentTarget;e._toggleAllColumns(t(a).prop("checked"));e.trigger("column-switch-all",t(a).prop("checked"))});if(r.showColumnsSearch){var N=o.find('[name="columnsSearch"]');var F=o.find(".dropdown-item-marker");N.on("keyup paste change",function(e){var r=e.currentTarget;var a=t(r);var i=a.val().toLowerCase();F.show();j.each(function(e,r){var a=t(r);var n=a.parents(".dropdown-item-marker");var o=n.text().toLowerCase();if(!o.includes(i))n.hide()})})}}var D=function G(t){var a=t.is("select")?"change":"keyup drop blur mouseup";t.off(a).on(a,function(t){if(r.searchOnEnterKey&&13!==t.keyCode)return;if([37,38,39,40].includes(t.keyCode))return;clearTimeout(n);n=setTimeout(function(){e.onSearch({currentTarget:t.currentTarget})},r.searchTimeOut)})};if((r.search||this.showSearchClearButton)&&"string"!==typeof r.searchSelector){a=[];var V=fy.sprintf(this.constants.html.searchButton,this.constants.buttonsClass,r.formatSearch(),r.showButtonIcons?fy.sprintf(this.constants.html.icon,r.iconsPrefix,r.icons.search):"",r.showButtonText?r.formatSearch():"");var B=fy.sprintf(this.constants.html.searchClearButton,this.constants.buttonsClass,r.formatClearSearch(),r.showButtonIcons?fy.sprintf(this.constants.html.icon,r.iconsPrefix,r.icons.clearSearch):"",r.showButtonText?r.formatClearSearch():"");var L='<input class="'.concat(this.constants.classes.input,"\n        ").concat(fy.sprintf(" %s%s",this.constants.classes.inputPrefix,r.iconSize),'\n        search-input" type="search" aria-label="').concat(r.formatSearch(),'" placeholder="').concat(r.formatSearch(),'" autocomplete="off">');var H=L;if(r.showSearchButton||r.showSearchClearButton){var M=(r.showSearchButton?V:"")+(r.showSearchClearButton?B:"");H=r.search?fy.sprintf(this.constants.html.inputGroup,L,M):M}a.push(fy.sprintf('\n        <div class="'.concat(this.constants.classes.pull,"-").concat(r.searchAlign," search ").concat(this.constants.classes.inputGroup,'">\n          %s\n        </div>\n      '),H));this.$toolbar.append(a.join(""));var U=fy.getSearchInput(this);if(r.showSearchButton){this.$toolbar.find(".search button[name=search]").off("click").on("click",function(){clearTimeout(n);n=setTimeout(function(){e.onSearch({currentTarget:U})},r.searchTimeOut)});if(r.searchOnEnterKey)D(U)}else D(U);if(r.showSearchClearButton)this.$toolbar.find(".search button[name=clearSearch]").click(function(){e.resetSearch()})}else if("string"===typeof r.searchSelector)D(fy.getSearchInput(this))}},{key:"onSearch",value:function w(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},r=e.currentTarget,a=e.firedByInitSearchText;var i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:true;if(void 0!==r&&t(r).length&&i){var n=t(r).val().trim();if(this.options.trimOnSearch&&t(r).val()!==n)t(r).val(n);if(this.searchText===n)return;var o=fy.getSearchInput(this);var s=r instanceof jQuery?r:t(r);if(s.is(o)||s.hasClass("search-input")){this.searchText=n;this.options.searchText=n}}if(!a)this.options.pageNumber=1;this.initSearch();if(a){if("client"===this.options.sidePagination)this.updatePagination()}else this.updatePagination();this.trigger("search",this.searchText)}},{key:"initSearch",value:function S(){var t=this;this.filterOptions=this.filterOptions||this.options.filterOptions;if("server"!==this.options.sidePagination){if(this.options.customSearch){this.data=fy.calculateObjectValue(this.options,this.options.customSearch,[this.options.data,this.searchText,this.filterColumns]);if(this.options.sortReset)this.unsortedData=c(this.data);this.initSort();return}var e=this.searchText&&(this.fromHtml?fy.escapeHTML(this.searchText):this.searchText);var r=e?e.toLowerCase():"";var a=fy.isEmptyObject(this.filterColumns)?null:this.filterColumns;if(this.options.searchAccentNeutralise)r=fy.normalizeAccent(r);if("function"===typeof this.filterOptions.filterAlgorithm)this.data=this.options.data.filter(function(e){return t.filterOptions.filterAlgorithm.apply(null,[e,a])});else if("string"===typeof this.filterOptions.filterAlgorithm)this.data=a?this.options.data.filter(function(e){var r=t.filterOptions.filterAlgorithm;if("and"===r){for(var i in a)if(Array.isArray(a[i])&&!a[i].includes(e[i])||!Array.isArray(a[i])&&e[i]!==a[i])return false}else if("or"===r){var n=false;for(var o in a)if(Array.isArray(a[o])&&a[o].includes(e[o])||!Array.isArray(a[o])&&e[o]===a[o])n=true;return n}return true}):c(this.options.data);var i=this.getVisibleFields();this.data=r?this.data.filter(function(a,n){for(var o=0;o<t.header.fields.length;o++){if(!t.header.searchables[o]||t.options.visibleSearch&&i.indexOf(t.header.fields[o])===-1)continue;var s=fy.isNumeric(t.header.fields[o])?parseInt(t.header.fields[o],10):t.header.fields[o];var l=t.columns[t.fieldsColumnsIndex[s]];var c=void 0;if("string"===typeof s&&!a.hasOwnProperty(s)){c=a;var f=s.split(".");for(var u=0;u<f.length;u++)if(null!==c[f[u]])c=c[f[u]];else{c=null;break}}else c=a[s];if(t.options.searchAccentNeutralise)c=fy.normalizeAccent(c);if(l&&l.searchFormatter)c=fy.calculateObjectValue(l,t.header.formatters[o],[c,a,n,l.field],c);if("string"===typeof c||"number"===typeof c){if(t.options.strictSearch&&"".concat(c).toLowerCase()===r||t.options.regexSearch&&fy.regexCompare(c,e))return true;var h=/(?:(<=|=>|=<|>=|>|<)(?:\s+)?(-?\d+)?|(-?\d+)?(\s+)?(<=|=>|=<|>=|>|<))/gm;var v=h.exec(t.searchText);var d=false;if(v){var p=v[1]||"".concat(v[5],"l");var g=v[2]||v[3];var b=parseInt(c,10);var m=parseInt(g,10);switch(p){case">":case"<l":d=b>m;break;case"<":case">l":d=b<m;break;case"<=":case"=<":case">=l":case"=>l":d=b<=m;break;case">=":case"=>":case"<=l":case"=<l":d=b>=m}}if(d||"".concat(c).toLowerCase().includes(r))return true}}return false}):this.data;if(this.options.sortReset)this.unsortedData=c(this.data);this.initSort()}}},{key:"initPagination",value:function x(){var e=this;var r=this.options;if(!r.pagination){this.$pagination.hide();return}this.$pagination.show();var a=[];var i=false;var n;var o;var s;var l;var c;var f;var u;var h=this.getData({includeHiddenRows:false});var v=r.pageList;if("string"===typeof v)v=v.replace(/\[|\]| /g,"").toLowerCase().split(",");v=v.map(function(t){if("string"===typeof t)return t.toLowerCase()===r.formatAllRows().toLowerCase()||["all","unlimited"].includes(t.toLowerCase())?r.formatAllRows():+t;return t});this.paginationParts=r.paginationParts;if("string"===typeof this.paginationParts)this.paginationParts=this.paginationParts.replace(/\[|\]| |'/g,"").split(",");if("server"!==r.sidePagination)r.totalRows=h.length;this.totalPages=0;if(r.totalRows){if(r.pageSize===r.formatAllRows()){r.pageSize=r.totalRows;i=true}this.totalPages=~~((r.totalRows-1)/r.pageSize)+1;r.totalPages=this.totalPages}if(this.totalPages>0&&r.pageNumber>this.totalPages)r.pageNumber=this.totalPages;this.pageFrom=(r.pageNumber-1)*r.pageSize+1;this.pageTo=r.pageNumber*r.pageSize;if(this.pageTo>r.totalRows)this.pageTo=r.totalRows;if(this.options.pagination&&"server"!==this.options.sidePagination)this.options.totalNotFiltered=this.options.data.length;if(!this.options.showExtendedPagination)this.options.totalNotFiltered=void 0;if(this.paginationParts.includes("pageInfo")||this.paginationParts.includes("pageInfoShort")||this.paginationParts.includes("pageSize"))a.push('<div class="'.concat(this.constants.classes.pull,"-").concat(r.paginationDetailHAlign,' pagination-detail">'));if(this.paginationParts.includes("pageInfo")||this.paginationParts.includes("pageInfoShort")){var d=this.options.totalRows+("client"===this.options.sidePagination&&this.options.paginationLoadMore&&!this._paginationLoaded?" +":"");var p=this.paginationParts.includes("pageInfoShort")?r.formatDetailPagination(d):r.formatShowingRows(this.pageFrom,this.pageTo,d,r.totalNotFiltered);a.push('<span class="pagination-info">\n      '.concat(p,"\n      </span>"))}if(this.paginationParts.includes("pageSize")){a.push('<div class="page-list">');var g=['<div class="'.concat(this.constants.classes.paginationDropdown,'">\n        <button class="').concat(this.constants.buttonsClass,' dropdown-toggle" type="button" ').concat(this.constants.dataToggle,'="dropdown">\n        <span class="page-size">\n        ').concat(i?r.formatAllRows():r.pageSize,"\n        </span>\n        ").concat(this.constants.html.dropdownCaret,"\n        </button>\n        ").concat(this.constants.html.pageDropdown[0])];v.forEach(function(t,a){if(!r.smartDisplay||0===a||v[a-1]<r.totalRows||t===r.formatAllRows()){var n;if(i)n=t===r.formatAllRows()?e.constants.classes.dropdownActive:"";else n=t===r.pageSize?e.constants.classes.dropdownActive:"";g.push(fy.sprintf(e.constants.html.pageDropdownItem,n,t))}});g.push("".concat(this.constants.html.pageDropdown[1],"</div>"));a.push(r.formatRecordsPerPage(g.join("")))}if(this.paginationParts.includes("pageInfo")||this.paginationParts.includes("pageInfoShort")||this.paginationParts.includes("pageSize"))a.push("</div></div>");if(this.paginationParts.includes("pageList")){a.push('<div class="'.concat(this.constants.classes.pull,"-").concat(r.paginationHAlign,' pagination">'),fy.sprintf(this.constants.html.pagination[0],fy.sprintf(" pagination-%s",r.iconSize)),fy.sprintf(this.constants.html.paginationItem," page-pre",r.formatSRPaginationPreText(),r.paginationPreText));if(this.totalPages<r.paginationSuccessivelySize){o=1;s=this.totalPages}else{o=r.pageNumber-r.paginationPagesBySide;s=o+2*r.paginationPagesBySide}if(r.pageNumber<r.paginationSuccessivelySize-1)s=r.paginationSuccessivelySize;if(r.paginationSuccessivelySize>this.totalPages-o)o=o-(r.paginationSuccessivelySize-(this.totalPages-o))+1;if(o<1)o=1;if(s>this.totalPages)s=this.totalPages;var b=Math.round(r.paginationPagesBySide/2);var m=function P(t){var a=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";return fy.sprintf(e.constants.html.paginationItem,a+(t===r.pageNumber?" ".concat(e.constants.classes.paginationActive):""),r.formatSRPaginationPageText(t),t)};if(o>1){var y=r.paginationPagesBySide;if(y>=o)y=o-1;for(n=1;n<=y;n++)a.push(m(n));if(o-1===y+1){n=o-1;a.push(m(n))}else if(o-1>y)if(o-2*r.paginationPagesBySide>r.paginationPagesBySide&&r.paginationUseIntermediate){n=Math.round((o-b)/2+b);a.push(m(n," page-intermediate"))}else a.push(fy.sprintf(this.constants.html.paginationItem," page-first-separator disabled","","..."))}for(n=o;n<=s;n++)a.push(m(n));if(this.totalPages>s){var w=this.totalPages-(r.paginationPagesBySide-1);if(s>=w)w=s+1;if(s+1===w-1){n=s+1;a.push(m(n))}else if(w>s+1)if(this.totalPages-s>2*r.paginationPagesBySide&&r.paginationUseIntermediate){n=Math.round((this.totalPages-b-s)/2+s);a.push(m(n," page-intermediate"))}else a.push(fy.sprintf(this.constants.html.paginationItem," page-last-separator disabled","","..."));for(n=w;n<=this.totalPages;n++)a.push(m(n))}a.push(fy.sprintf(this.constants.html.paginationItem," page-next",r.formatSRPaginationNextText(),r.paginationNextText));a.push(this.constants.html.pagination[1],"</div>")}this.$pagination.html(a.join(""));var S=["bottom","both"].includes(r.paginationVAlign)?" ".concat(this.constants.classes.dropup):"";this.$pagination.last().find(".page-list > div").addClass(S);if(!r.onlyInfoPagination){l=this.$pagination.find(".page-list a");c=this.$pagination.find(".page-pre");f=this.$pagination.find(".page-next");u=this.$pagination.find(".page-item").not(".page-next, .page-pre, .page-last-separator, .page-first-separator");if(this.totalPages<=1)this.$pagination.find("div.pagination").hide();if(r.smartDisplay)if(v.length<2||r.totalRows<=v[0])this.$pagination.find("div.page-list").hide();this.$pagination[this.getData().length?"show":"hide"]();if(!r.paginationLoop){if(1===r.pageNumber)c.addClass("disabled");if(r.pageNumber===this.totalPages)f.addClass("disabled")}if(i)r.pageSize=r.formatAllRows();l.off("click").on("click",function(t){return e.onPageListChange(t)});c.off("click").on("click",function(t){return e.onPagePre(t)});f.off("click").on("click",function(t){return e.onPageNext(t)});u.off("click").on("click",function(t){return e.onPageNumber(t)});if(this.options.showPageGo){var x=this,O=this.$pagination.find("ul.pagination"),k=O.find("li.pageGo");if(!k.length){k=t(['<li class="pageGo">',fy.sprintf('<input type="text" class="form-control" value="%s">',this.options.pageNumber),'<button class="btn'+fy.sprintf(" btn-%s",this.constants.buttonsClass)+fy.sprintf(" btn-%s",r.iconSize)+'" title="'+r.formatPageGo()+'" '+' type="button">'+r.formatPageGo(),"</button>","</li>"].join("")).appendTo(O);k.find("button").click(function(){var t=parseInt(k.find("input").val())||1;if(t<1||t>x.options.totalPages)t=1;x.selectPage(t)})}}}}},{key:"updatePagination",value:function O(e){if(e&&t(e.currentTarget).hasClass("disabled"))return;if(!this.options.maintainMetaData)this.resetRows();this.initPagination();this.trigger("page-change",this.options.pageNumber,this.options.pageSize);if("server"===this.options.sidePagination||"client"===this.options.sidePagination&&this.options.paginationLoadMore&&!this._paginationLoaded&&this.options.pageNumber===this.totalPages)this.initServer();else this.initBody()}},{key:"onPageListChange",value:function k(e){e.preventDefault();var r=t(e.currentTarget);r.parent().addClass(this.constants.classes.dropdownActive).siblings().removeClass(this.constants.classes.dropdownActive);this.options.pageSize=r.text().toUpperCase()===this.options.formatAllRows().toUpperCase()?this.options.formatAllRows():+r.text();this.$toolbar.find(".page-size").text(this.options.pageSize);this.updatePagination(e);return false}},{key:"onPagePre",value:function P(e){if(t(e.target).hasClass("disabled"))return;e.preventDefault();if(this.options.pageNumber-1===0)this.options.pageNumber=this.options.totalPages;else this.options.pageNumber--;this.updatePagination(e);return false}},{key:"onPageNext",value:function C(e){if(t(e.target).hasClass("disabled"))return;e.preventDefault();if(this.options.pageNumber+1>this.options.totalPages)this.options.pageNumber=1;else this.options.pageNumber++;this.updatePagination(e);return false}},{key:"onPageNumber",value:function T(e){e.preventDefault();if(this.options.pageNumber===+t(e.currentTarget).text())return;this.options.pageNumber=+t(e.currentTarget).text();this.updatePagination(e);return false}},{key:"initRow",value:function I(t,e,r,a){var n=this;var o=[];var s={};var c=[];var f="";var u={};var h=[];if(fy.findIndex(this.hiddenRows,t)>-1)return;s=fy.calculateObjectValue(this.options,this.options.rowStyle,[t,e],s);if(s&&s.css)for(var v=0,d=Object.entries(s.css);v<d.length;v++){var p=l(d[v],2),g=p[0],b=p[1];c.push("".concat(g,": ").concat(b))}u=fy.calculateObjectValue(this.options,this.options.rowAttributes,[t,e],u);if(u)for(var m=0,y=Object.entries(u);m<y.length;m++){var w=l(y[m],2),S=w[0],x=w[1];h.push("".concat(S,'="').concat(fy.escapeHTML(x),'"'))}if(t._data&&!fy.isEmptyObject(t._data))for(var O=0,k=Object.entries(t._data);O<k.length;O++){var P=l(k[O],2),C=P[0],T=P[1];if("index"===C)return;f+=" data-".concat(C,"='").concat("object"===i(T)?JSON.stringify(T):T,"'")}o.push("<tr",fy.sprintf(" %s",h.length?h.join(" "):void 0),fy.sprintf(' id="%s"',Array.isArray(t)?void 0:t._id),fy.sprintf(' class="%s"',s.classes||(Array.isArray(t)?void 0:t._class)),fy.sprintf(' style="%s"',Array.isArray(t)?void 0:t._style),' data-index="'.concat(e,'"'),fy.sprintf(' data-uniqueid="%s"',fy.getItemField(t,this.options.uniqueId,false)),fy.sprintf(' data-has-detail-view="%s"',this.options.detailView&&fy.calculateObjectValue(null,this.options.detailFilter,[e,t])?"true":void 0),fy.sprintf("%s",f),">");if(this.options.cardView)o.push('<td colspan="'.concat(this.header.fields.length,'"><div class="card-views">'));var I="";if(fy.hasDetailViewIcon(this.options)){I="<td>";if(fy.calculateObjectValue(null,this.options.detailFilter,[e,t]))I+='\n          <a class="detail-icon" href="#">\n          '.concat(fy.sprintf(this.constants.html.icon,this.options.iconsPrefix,this.options.icons.detailOpen),"\n          </a>\n        ");I+="</td>"}if(I&&"right"!==this.options.detailViewAlign)o.push(I);this.header.fields.forEach(function(r,a){var i=n.columns[a];var s="";var f=fy.getItemField(t,r,n.options.escape,i.escape);var u="";var h="";var v={};var d="";var p=n.header.classes[a];var g="";var b="";var m="";var y="";var w="";var S="";if((n.fromHtml||n.autoMergeCells)&&"undefined"===typeof f)if(!i.checkbox&&!i.radio)return;if(!i.visible)return;if(n.options.cardView&&!i.cardVisible)return;if(c.concat([n.header.styles[a]]).length)b+="".concat(c.concat([n.header.styles[a]]).join("; "));if(t["_".concat(r,"_style")])b+="".concat(t["_".concat(r,"_style")]);if(b)g=' style="'.concat(b,'"');if(t["_".concat(r,"_id")])d=fy.sprintf(' id="%s"',t["_".concat(r,"_id")]);if(t["_".concat(r,"_class")])p=fy.sprintf(' class="%s"',t["_".concat(r,"_class")]);if(t["_".concat(r,"_rowspan")])y=fy.sprintf(' rowspan="%s"',t["_".concat(r,"_rowspan")]);if(t["_".concat(r,"_colspan")])w=fy.sprintf(' colspan="%s"',t["_".concat(r,"_colspan")]);if(t["_".concat(r,"_title")])S=fy.sprintf(' title="%s"',t["_".concat(r,"_title")]);v=fy.calculateObjectValue(n.header,n.header.cellStyles[a],[f,t,e,r],v);if(v.classes)p=' class="'.concat(v.classes,'"');if(v.css){var x=[];for(var O=0,k=Object.entries(v.css);O<k.length;O++){var P=l(k[O],2),C=P[0],T=P[1];x.push("".concat(C,": ").concat(T))}g=' style="'.concat(x.concat(n.header.styles[a]).join("; "),'"')}u=fy.calculateObjectValue(i,n.header.formatters[a],[f,t,e,r],f);if(!(i.checkbox||i.radio))u="undefined"===typeof u||null===u?n.options.undefinedText:u;if(i.searchable&&n.searchText&&n.options.searchHighlight&&!(i.checkbox||i.radio)){var I="";var A=n.searchText.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");if(n.options.searchAccentNeutralise){var $=new RegExp("".concat(fy.normalizeAccent(A)),"gmi");var R=$.exec(fy.normalizeAccent(u));if(R)A=u.substring(R.index,R.index+A.length)}var E=new RegExp("(".concat(A,")"),"gim");var j="<mark>$1</mark>";var _=u&&/<(?=.*? .*?\/ ?>|br|hr|input|!--|wbr)[a-z]+.*?>|<([a-z]+).*?<\/\1>/i.test(u);if(_){var N=(new DOMParser).parseFromString(u.toString(),"text/html").documentElement.textContent;var F=N.replace(E,j);N=N.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");I=u.replace(new RegExp("(>\\s*)(".concat(N,")(\\s*)"),"gm"),"$1".concat(F,"$3"))}else I=u.toString().replace(E,j);u=fy.calculateObjectValue(i,i.searchHighlightFormatter,[u,n.searchText],I)}if(t["_".concat(r,"_data")]&&!fy.isEmptyObject(t["_".concat(r,"_data")]))for(var D=0,V=Object.entries(t["_".concat(r,"_data")]);D<V.length;D++){var B=l(V[D],2),L=B[0],H=B[1];if("index"===L)return;m+=" data-".concat(L,'="').concat(H,'"')}if(i.checkbox||i.radio){h=i.checkbox?"checkbox":h;h=i.radio?"radio":h;var M=i["class"]||"";var U=fy.isObject(u)&&u.hasOwnProperty("checked")?u.checked:(true===u||f)&&false!==u;var z=!i.checkboxEnabled||u&&u.disabled;s=[n.options.cardView?'<div class="card-view '.concat(M,'">'):'<td class="bs-checkbox '.concat(M,'"').concat(p).concat(g,">"),'<label>\n            <input\n            data-index="'.concat(e,'"\n            name="').concat(n.options.selectItemName,'"\n            type="').concat(h,'"\n            ').concat(fy.sprintf('value="%s"',t[n.options.idField]),"\n            ").concat(fy.sprintf('checked="%s"',U?"checked":void 0),"\n            ").concat(fy.sprintf('disabled="%s"',z?"disabled":void 0)," />\n            <span></span>\n            </label>"),n.header.formatters[a]&&"string"===typeof u?u:"",n.options.cardView?"</div>":"</td>"].join("");t[n.header.stateField]=true===u||!!f||u&&u.checked}else if(n.options.cardView){var q=n.options.showHeader?'<span class="card-view-title '.concat(v.classes||"",'"').concat(g,">").concat(fy.getFieldTitle(n.columns,r),"</span>"):"";s='<div class="card-view">'.concat(q,'<span class="card-view-value ').concat(v.classes||"",'"').concat(g,">").concat(u,"</span></div>");if(n.options.smartDisplay&&""===u)s='<div class="card-view"></div>'}else s="<td".concat(d).concat(p).concat(g).concat(m).concat(y).concat(w).concat(S,">").concat(u,"</td>");o.push(s)});if(I&&"right"===this.options.detailViewAlign)o.push(I);if(this.options.cardView)o.push("</div></td>");o.push("</tr>");return o.join("")}},{key:"initBody",value:function A(e,r){var a=this;var i=this.getData();this.trigger("pre-body",i);this.$body=this.$el.find(">tbody");if(!this.$body.length)this.$body=t("<tbody></tbody>").appendTo(this.$el);if(!this.options.pagination||"server"===this.options.sidePagination){this.pageFrom=1;this.pageTo=i.length}var n=[];var o=t(document.createDocumentFragment());var s=false;var l=[];this.autoMergeCells=fy.checkAutoMergeCells(i.slice(this.pageFrom-1,this.pageTo));for(var c=this.pageFrom-1;c<this.pageTo;c++){var f=i[c];var u=this.initRow(f,c,i,o);s=s||!!u;if(u&&"string"===typeof u){var h=this.options.uniqueId;if(h&&f.hasOwnProperty(h)){var v=f[h];var d=this.$body.find(fy.sprintf('> tr[data-uniqueid="%s"][data-has-detail-view]',v));var p=d.next();if(p.is("tr.detail-view")){l.push(c);if(!r||v!==r)u+=p[0].outerHTML}}if(!this.options.virtualScroll)o.append(u);else n.push(u)}}if(!s)this.$body.html('<tr class="no-records-found">'.concat(fy.sprintf('<td colspan="%s">%s</td>',this.getVisibleFields().length+fy.getDetailViewIndexOffset(this.options),this.options.formatNoMatches()),"</tr>"));else if(!this.options.virtualScroll)this.$body.html(o);else{if(this.virtualScroll)this.virtualScroll.destroy();this.virtualScroll=new xy({rows:n,fixedScroll:e,scrollEl:this.$tableBody[0],contentEl:this.$body[0],itemHeight:this.options.virtualScrollItemHeight,callback:function g(t,e){a.fitHeader();a.initBodyEvent();a.trigger("virtual-scroll",t,e)}})}l.forEach(function(t){a.expandRow(t)});if(!e)this.scrollTo(0);this.initBodyEvent();this.initFooter();this.resetView();this.updateSelected();if("server"!==this.options.sidePagination)this.options.totalRows=i.length;this.trigger("post-body",i)}},{key:"initBodyEvent",value:function $(){var e=this;this.$body.find("> tr[data-index] > td").off("click dblclick").on("click dblclick",function(r){var a=t(r.currentTarget);if(a.find(".detail-icon").length||a.index()-fy.getDetailViewIndexOffset(e.options)<0)return;var i=a.parent();var n=t(r.target).parents(".card-views").children();var o=t(r.target).parents(".card-view");var s=i.data("index");var l=e.data[s];var c=e.options.cardView?n.index(o):a[0].cellIndex;var f=e.getVisibleFields();var u=f[c-fy.getDetailViewIndexOffset(e.options)];var h=e.columns[e.fieldsColumnsIndex[u]];var v=fy.getItemField(l,u,e.options.escape,h.escape);e.trigger("click"===r.type?"click-cell":"dbl-click-cell",u,v,l,a);e.trigger("click"===r.type?"click-row":"dbl-click-row",l,i,u);if("click"===r.type&&e.options.clickToSelect&&h.clickToSelect&&!fy.calculateObjectValue(e.options,e.options.ignoreClickToSelectOn,[r.target])){var d=i.find(fy.sprintf('[name="%s"]',e.options.selectItemName));if(d.length)d[0].click()}if("click"===r.type&&e.options.detailViewByClick)e.toggleDetailView(s,e.header.detailFormatters[e.fieldsColumnsIndex[u]])}).off("mousedown").on("mousedown",function(t){e.multipleSelectRowCtrlKey=t.ctrlKey||t.metaKey;e.multipleSelectRowShiftKey=t.shiftKey});this.$body.find("> tr[data-index] > td > .detail-icon").off("click").on("click",function(r){r.preventDefault();e.toggleDetailView(t(r.currentTarget).parent().parent().data("index"));return false});this.$selectItem=this.$body.find(fy.sprintf('[name="%s"]',this.options.selectItemName));this.$selectItem.off("click").on("click",function(r){r.stopImmediatePropagation();var a=t(r.currentTarget);e._toggleCheck(a.prop("checked"),a.data("index"))});this.header.events.forEach(function(r,a){var i=r;if(!i)return;if("string"===typeof i)i=fy.calculateObjectValue(null,i);if(!i)throw new Error("Unknown event in the scope: ".concat(r));var n=e.header.fields[a];var o=e.getVisibleFields().indexOf(n);if(o===-1)return;o+=fy.getDetailViewIndexOffset(e.options);var s=function c(r){if(!i.hasOwnProperty(r))return 1;var a=i[r];e.$body.find(">tr:not(.no-records-found)").each(function(i,s){var l=t(s);var c=l.find(e.options.cardView?".card-views>.card-view":">td").eq(o);var f=r.indexOf(" ");var u=r.substring(0,f);var h=r.substring(f+1);c.find(h).off(u).on(u,function(t){var r=l.data("index");var i=e.data[r];var o=i[n];a.apply(e,[t,o,i,r])})})};for(var l in i)if(s(l))continue})}},{key:"initServer",value:function R(e,r,a){var i=this;var n={};var o=this.header.fields.indexOf(this.options.sortName);var s={searchText:this.searchText,sortName:this.options.sortName,sortOrder:this.options.sortOrder};if(this.header.sortNames[o])s.sortName=this.header.sortNames[o];if(this.options.pagination&&"server"===this.options.sidePagination){s.pageSize=this.options.pageSize===this.options.formatAllRows()?this.options.totalRows:this.options.pageSize;s.pageNumber=this.options.pageNumber}if(!this.options.firstLoad&&!firstLoadTable.includes(this.options.id)){firstLoadTable.push(this.options.id);return}if(!(a||this.options.url)&&!this.options.ajax)return;if("limit"===this.options.queryParamsType){s={search:s.searchText,sort:s.sortName,order:s.sortOrder};if(this.options.pagination&&"server"===this.options.sidePagination){s.offset=this.options.pageSize===this.options.formatAllRows()?0:this.options.pageSize*(this.options.pageNumber-1);s.limit=this.options.pageSize;if(0===s.limit||this.options.pageSize===this.options.formatAllRows())delete s.limit}}if(this.options.search&&"server"===this.options.sidePagination&&this.options.searchable&&this.columns.filter(function(t){return t.searchable}).length){s.searchable=[];var l=b(this.columns),c;try{for(l.s();!(c=l.n()).done;){var f=c.value;if(!f.checkbox&&f.searchable&&(this.options.visibleSearch&&f.visible||!this.options.visibleSearch))s.searchable.push(f.field)}}catch(u){l.e(u)}finally{l.f()}}if(!fy.isEmptyObject(this.filterColumnsPartial))s.filter=JSON.stringify(this.filterColumnsPartial,null);fy.extend(s,r||{});n=fy.calculateObjectValue(this.options,this.options.queryParams,[s],n);if(false===n)return;if(!e)this.showLoading();var h=fy.extend({},fy.calculateObjectValue(null,this.options.ajaxOptions),{type:this.options.method,url:a||this.options.url,data:"application/json"===this.options.contentType&&"post"===this.options.method?JSON.stringify(n):n,cache:this.options.cache,contentType:this.options.contentType,dataType:this.options.dataType,success:function v(t,r,a){var n=fy.calculateObjectValue(i.options,i.options.responseHandler,[t,a],t);if("client"===i.options.sidePagination&&i.options.paginationLoadMore)i._paginationLoaded=i.data.length===n.length;i.load(n);i.trigger("load-success",n,a&&a.status,a);if(!e)i.hideLoading();if("server"===i.options.sidePagination&&i.options.pageNumber>1&&n[i.options.totalField]>0&&!n[i.options.dataField].length)i.updatePagination()},error:function d(t){if(t&&0===t.status&&i._xhrAbort){i._xhrAbort=false;return}var r=[];if("server"===i.options.sidePagination){r={};r[i.options.totalField]=0;r[i.options.dataField]=[]}i.load(r);i.trigger("load-error",t&&t.status,t);if(!e)i.hideLoading()}});if(this.options.ajax)fy.calculateObjectValue(this,this.options.ajax,[h],null);else{if(this._xhr&&4!==this._xhr.readyState){this._xhrAbort=true;this._xhr.abort()}this._xhr=t.ajax(h)}return n}},{key:"initSearchText",value:function E(){if(this.options.search){this.searchText="";if(""!==this.options.searchText){var t=fy.getSearchInput(this);t.val(this.options.searchText);this.onSearch({currentTarget:t,firedByInitSearchText:true})}}}},{key:"getCaret",value:function j(){var e=this;this.$header.find("th").each(function(r,a){t(a).find(".sortable").removeClass("desc asc").addClass(t(a).data("field")===e.options.sortName?e.options.sortOrder:"both")})}},{key:"updateSelected",value:function _(){var e=this.$selectItem.filter(":enabled").length&&this.$selectItem.filter(":enabled").length===this.$selectItem.filter(":enabled").filter(":checked").length;this.$selectAll.add(this.$selectAll_).prop("checked",e);this.$selectItem.each(function(e,r){t(r).closest("tr")[t(r).prop("checked")?"addClass":"removeClass"]("selected")})}},{key:"updateRows",value:function N(){var e=this;this.$selectItem.each(function(r,a){e.data[t(a).data("index")][e.header.stateField]=t(a).prop("checked")})}},{key:"resetRows",value:function F(){var t=b(this.data),e;try{for(t.s();!(e=t.n()).done;){var r=e.value;this.$selectAll.prop("checked",false);this.$selectItem.prop("checked",false);if(this.header.stateField)r[this.header.stateField]=false}}catch(a){t.e(a)}finally{t.f()}this.initHiddenRows()}},{key:"trigger",value:function D(r){var a,i;var n="".concat(r,".bs.table");for(var o=arguments.length,s=new Array(o>1?o-1:0),l=1;l<o;l++)s[l-1]=arguments[l];(a=this.options)[e.EVENTS[n]].apply(a,[].concat(s,[this]));this.$el.trigger(t.Event(n,{sender:this}),s);(i=this.options).onAll.apply(i,[n].concat([].concat(s,[this])));this.$el.trigger(t.Event("all.bs.table",{sender:this}),[n,s])}},{key:"resetHeader",value:function V(){var t=this;clearTimeout(this.timeoutId_);this.timeoutId_=setTimeout(function(){return t.fitHeader()},this.$el.is(":hidden")?100:0)}},{key:"fitHeader",value:function B(){var e=this;if(this.$el.is(":hidden")){this.timeoutId_=setTimeout(function(){return e.fitHeader()},100);return}var r=this.$tableBody.get(0);var a=this.hasScrollBar&&r.scrollHeight>r.clientHeight+this.$header.outerHeight()?fy.getScrollBarWidth():0;this.$el.css("margin-top",-this.$header.outerHeight());var i=this.$tableHeader.find(":focus");if(i.length>0){var n=i.parents("th");if(n.length>0){var o=n.attr("data-field");if(void 0!==o){var s=this.$header.find("[data-field='".concat(o,"']"));if(s.length>0)s.find(":input").addClass("focus-temp")}}}this.$header_=this.$header.clone(true,true);this.$selectAll_=this.$header_.find('[name="btSelectAll"]');this.$tableHeader.css("margin-right",a).find("table").css("width",this.$el.outerWidth()).html("").attr("class",this.$el.attr("class")).append(this.$header_);this.$tableLoading.css("width",this.$el.outerWidth());var l=t(".focus-temp:visible:eq(0)");if(l.length>0){l.focus();this.$header.find(".focus-temp").removeClass("focus-temp")}this.$header.find("th[data-field]").each(function(r,a){e.$header_.find(fy.sprintf('th[data-field="%s"]',t(a).data("field"))).data(t(a).data())});var c=this.getVisibleFields();var f=this.$header_.find("th");var u=this.$body.find(">tr:not(.no-records-found,.virtual-scroll-top)").eq(0);while(u.length&&u.find('>td[colspan]:not([colspan="1"])').length)u=u.next();var h=u.find("> *").length;u.find("> *").each(function(r,a){var i=t(a);if(fy.hasDetailViewIcon(e.options))if(0===r&&"right"!==e.options.detailViewAlign||r===h-1&&"right"===e.options.detailViewAlign){var n=f.filter(".detail");var o=n.innerWidth()-n.find(".fht-cell").width();n.find(".fht-cell").width(i.innerWidth()-o);return}var s=r-fy.getDetailViewIndexOffset(e.options);var l=e.$header_.find(fy.sprintf('th[data-field="%s"]',c[s]));if(l.length>1)l=t(f[i[0].cellIndex]);var u=l.innerWidth()-l.find(".fht-cell").width();l.find(".fht-cell").width(i.innerWidth()-u)});this.horizontalScroll();this.trigger("post-header")}},{key:"initFooter",value:function L(){if(!this.options.showFooter||this.options.cardView)return;var t=this.getData();var e=[];var r="";if(fy.hasDetailViewIcon(this.options))r='<th class="detail"><div class="th-inner"></div><div class="fht-cell"></div></th>';if(r&&"right"!==this.options.detailViewAlign)e.push(r);var a=b(this.columns),i;try{for(a.s();!(i=a.n()).done;){var n=i.value;var o="";var s="";var c=[];var f={};var u=fy.sprintf(' class="%s"',n["class"]);if(!n.visible||this.footerData&&this.footerData.length>0&&!(n.field in this.footerData[0]))continue;if(this.options.cardView&&!n.cardVisible)return;o=fy.sprintf("text-align: %s; ",n.falign?n.falign:n.align);s=fy.sprintf("vertical-align: %s; ",n.valign);f=fy.calculateObjectValue(null,n.footerStyle||this.options.footerStyle,[n]);if(f&&f.css)for(var h=0,v=Object.entries(f.css);h<v.length;h++){var d=l(v[h],2),p=d[0],g=d[1];c.push("".concat(p,": ").concat(g))}if(f&&f.classes)u=fy.sprintf(' class="%s"',n["class"]?[n["class"],f.classes].join(" "):f.classes);e.push("<th",u,fy.sprintf(' style="%s"',o+s+c.concat().join("; ")||void 0));var m=0;if(this.footerData&&this.footerData.length>0)m=this.footerData[0]["_".concat(n.field,"_colspan")]||0;if(m)e.push(' colspan="'.concat(m,'" '));e.push(">");e.push('<div class="th-inner">');var y="";if(this.footerData&&this.footerData.length>0)y=this.footerData[0][n.field]||"";e.push(fy.calculateObjectValue(n,n.footerFormatter,[t,y],y));e.push("</div>");e.push('<div class="fht-cell"></div>');e.push("</div>");e.push("</th>")}}catch(w){a.e(w)}finally{a.f()}if(r&&"right"===this.options.detailViewAlign)e.push(r);if(!this.options.height&&!this.$tableFooter.length){this.$el.append("<tfoot><tr></tr></tfoot>");this.$tableFooter=this.$el.find("tfoot")}if(!this.$tableFooter.find("tr").length)this.$tableFooter.html("<table><thead><tr></tr></thead></table>");this.$tableFooter.find("tr").html(e.join(""));this.trigger("post-footer",this.$tableFooter)}},{key:"fitFooter",value:function H(){var e=this;if(this.$el.is(":hidden")){setTimeout(function(){return e.fitFooter()},100);return}var r=this.$tableBody.get(0);var a=this.hasScrollBar&&r.scrollHeight>r.clientHeight+this.$header.outerHeight()?fy.getScrollBarWidth():0;this.$tableFooter.css("margin-right",a).find("table").css("width",this.$el.outerWidth()).attr("class",this.$el.attr("class"));var i=this.$tableFooter.find("th");var n=this.$body.find(">tr:first-child:not(.no-records-found)");i.find(".fht-cell").width("auto");while(n.length&&n.find('>td[colspan]:not([colspan="1"])').length)n=n.next();var o=n.find("> *").length;n.find("> *").each(function(r,a){var n=t(a);if(fy.hasDetailViewIcon(e.options))if(0===r&&"left"===e.options.detailViewAlign||r===o-1&&"right"===e.options.detailViewAlign){var s=i.filter(".detail");var l=s.innerWidth()-s.find(".fht-cell").width();s.find(".fht-cell").width(n.innerWidth()-l);return}var c=i.eq(r);var f=c.innerWidth()-c.find(".fht-cell").width();c.find(".fht-cell").width(n.innerWidth()-f)});this.horizontalScroll()}},{key:"horizontalScroll",value:function M(){var t=this;this.$tableBody.off("scroll").on("scroll",function(){var e=t.$tableBody.scrollLeft();if(t.options.showHeader&&t.options.height)t.$tableHeader.scrollLeft(e);if(t.options.showFooter&&!t.options.cardView)t.$tableFooter.scrollLeft(e);t.trigger("scroll-body",t.$tableBody)})}},{key:"getVisibleFields",value:function U(){var t=[];var e=b(this.header.fields),r;try{for(e.s();!(r=e.n()).done;){var a=r.value;var i=this.columns[this.fieldsColumnsIndex[a]];if(!i||!i.visible||this.options.cardView&&!i.cardVisible)continue;t.push(a)}}catch(n){e.e(n)}finally{e.f()}return t}},{key:"initHiddenRows",value:function z(){this.hiddenRows=[]}},{key:"getOptions",value:function q(){var t=fy.extend({},this.options);delete t.data;return fy.extend(true,{},t)}},{key:"refreshOptions",value:function G(t){if(fy.compareObjects(this.options,t,true))return;this.options=fy.extend(this.options,t);this.trigger("refresh-options",this.options);this.destroy();this.init()}},{key:"getData",value:function W(t){var e=this;var r=this.options.data;if((this.searchText||this.options.customSearch||void 0!==this.options.sortName||this.enableCustomSort||!fy.isEmptyObject(this.filterColumns)||"function"===typeof this.options.filterOptions.filterAlgorithm||!fy.isEmptyObject(this.filterColumnsPartial))&&(!t||!t.unfiltered))r=this.data;if(t&&!t.includeHiddenRows){var a=this.getHiddenRows();r=r.filter(function(t){return fy.findIndex(a,t)===-1})}if(t&&t.useCurrentPage)r=r.slice(this.pageFrom-1,this.pageTo);if(t&&t.formatted)r.forEach(function(t){for(var r=0,a=Object.entries(t);r<a.length;r++){var i=l(a[r],2),n=i[0],o=i[1];var s=e.columns[e.fieldsColumnsIndex[n]];if(!s)return;t[n]=fy.calculateObjectValue(s,e.header.formatters[s.fieldIndex],[o,t,t.index,s.field],o)}});return r}},{key:"getSelections",value:function K(){var t=this;return(this.options.maintainMetaData?this.options.data:this.data).filter(function(e){return true===e[t.header.stateField]})}},{key:"load",value:function Y(t){var e=false;var r=t;if(this.options.pagination&&"server"===this.options.sidePagination){this.options.totalRows=r[this.options.totalField];this.options.totalNotFiltered=r[this.options.totalNotFilteredField];this.footerData=r[this.options.footerField]?[r[this.options.footerField]]:void 0}e=this.options.fixedScroll||r.fixedScroll;r=Array.isArray(r)?r:r[this.options.dataField];this.initData(r);this.initSearch();this.initPagination();this.initBody(e)}},{key:"append",value:function J(t){this.initData(t,"append");this.initSearch();this.initPagination();this.initSort();this.initBody(true)}},{key:"prepend",value:function X(t){this.initData(t,"prepend");this.initSearch();this.initPagination();this.initSort();this.initBody(true)}},{key:"remove",value:function Q(t){var e=0;for(var r=this.options.data.length-1;r>=0;r--){var a=this.options.data[r];var i=fy.getItemField(a,t.field,this.options.escape,a.escape);if(void 0===i&&"$index"!==t.field)continue;if(!a.hasOwnProperty(t.field)&&"$index"===t.field&&t.values.includes(r)||t.values.includes(i)){e++;this.options.data.splice(r,1)}}if(!e)return;if("server"===this.options.sidePagination){this.options.totalRows-=e;this.data=c(this.options.data)}this.initSearch();this.initPagination();this.initSort();this.initBody(true)}},{key:"removeAll",value:function Z(){if(this.options.data.length>0){this.options.data.splice(0,this.options.data.length);this.initSearch();this.initPagination();this.initBody(true)}}},{key:"insertRow",value:function tt(t){if(!t.hasOwnProperty("index")||!t.hasOwnProperty("row"))return;this.options.data.splice(t.index,0,t.row);this.initSearch();this.initPagination();this.initSort();this.initBody(true)}},{key:"updateRow",value:function et(t){var e=Array.isArray(t)?t:[t];var r=b(e),a;try{for(r.s();!(a=r.n()).done;){var i=a.value;if(!i.hasOwnProperty("index")||!i.hasOwnProperty("row"))continue;if(i.hasOwnProperty("replace")&&i.replace)this.options.data[i.index]=i.row;else fy.extend(this.options.data[i.index],i.row)}}catch(n){r.e(n)}finally{r.f()}this.initSearch();this.initPagination();this.initSort();this.initBody(true)}},{key:"getRowByUniqueId",value:function rt(t){var e=this.options.uniqueId;var r=this.options.data.length;var a=t;var i=null;var n;var o;for(n=r-1;n>=0;n--){o=this.options.data[n];var s=fy.getItemField(o,e,this.options.escape,o.escape);if(void 0===s)continue;if("string"===typeof s)a=t.toString();else if("number"===typeof s)if(Number(s)===s&&s%1===0)a=parseInt(t,10);else if(s===Number(s)&&0!==s)a=parseFloat(t);if(s===a){i=o;break}}return i}},{key:"updateByUniqueId",value:function at(t){var e=Array.isArray(t)?t:[t];var r=null;var a=b(e),i;try{for(a.s();!(i=a.n()).done;){var n=i.value;if(!n.hasOwnProperty("id")||!n.hasOwnProperty("row"))continue;var o=this.options.data.indexOf(this.getRowByUniqueId(n.id));if(o===-1)continue;if(n.hasOwnProperty("replace")&&n.replace)this.options.data[o]=n.row;else fy.extend(this.options.data[o],n.row);r=n.id}}catch(s){a.e(s)}finally{a.f()}this.initSearch();this.initPagination();this.initSort();this.initBody(true,r)}},{key:"removeByUniqueId",value:function it(t){var e=this.options.data.length;var r=this.getRowByUniqueId(t);if(r)this.options.data.splice(this.options.data.indexOf(r),1);if(e===this.options.data.length)return;if("server"===this.options.sidePagination){this.options.totalRows-=1;this.data=c(this.options.data)}this.initSearch();this.initPagination();this.initBody(true)}},{key:"_updateCellOnly",value:function nt(e,r){var a=this.initRow(this.options.data[r],r);var i=this.getVisibleFields().indexOf(e);if(i===-1)return;i+=fy.getDetailViewIndexOffset(this.options);this.$body.find(">tr[data-index=".concat(r,"]")).find(">td:eq(".concat(i,")")).replaceWith(t(a).find(">td:eq(".concat(i,")")));this.initBodyEvent();this.initFooter();this.resetView();this.updateSelected()}},{key:"updateCell",value:function ot(t){if(!t.hasOwnProperty("index")||!t.hasOwnProperty("field")||!t.hasOwnProperty("value"))return;this.options.data[t.index][t.field]=t.value;if(false===t.reinit){this._updateCellOnly(t.field,t.index);return}this.initSort();this.initBody(true)}},{key:"updateCellByUniqueId",value:function st(t){var e=this;var r=Array.isArray(t)?t:[t];r.forEach(function(t){var r=t.id,a=t.field,i=t.value;var n=e.options.data.indexOf(e.getRowByUniqueId(r));if(n===-1)return;e.options.data[n][a]=i});if(false===t.reinit){this._updateCellOnly(t.field,this.options.data.indexOf(this.getRowByUniqueId(t.id)));return}this.initSort();this.initBody(true)}},{key:"showRow",value:function lt(t){this._toggleRow(t,true)}},{key:"hideRow",value:function ct(t){this._toggleRow(t,false)}},{key:"_toggleRow",value:function ft(t,e){var r;if(t.hasOwnProperty("index"))r=this.getData()[t.index];else if(t.hasOwnProperty("uniqueId"))r=this.getRowByUniqueId(t.uniqueId);if(!r)return;var a=fy.findIndex(this.hiddenRows,r);if(!e&&a===-1)this.hiddenRows.push(r);else if(e&&a>-1)this.hiddenRows.splice(a,1);this.initBody(true);this.initPagination()}},{key:"getHiddenRows",value:function ut(t){if(t){this.initHiddenRows();this.initBody(true);this.initPagination();return}var e=this.getData();var r=[];var a=b(e),i;try{for(a.s();!(i=a.n()).done;){var n=i.value;if(this.hiddenRows.includes(n))r.push(n)}}catch(o){a.e(o)}finally{a.f()}this.hiddenRows=r;return r}},{key:"showColumn",value:function ht(t){var e=this;var r=Array.isArray(t)?t:[t];r.forEach(function(t){e._toggleColumn(e.fieldsColumnsIndex[t],true,true)})}},{key:"hideColumn",value:function vt(t){var e=this;var r=Array.isArray(t)?t:[t];r.forEach(function(t){e._toggleColumn(e.fieldsColumnsIndex[t],false,true)})}},{key:"_toggleColumn",value:function dt(t,e,r){if(t===-1||this.columns[t].visible===e)return;this.columns[t].visible=e;this.initHeader();this.initSearch();this.initPagination();this.initBody();if(this.options.showColumns){var a=this.$toolbar.find('.keep-open input:not(".toggle-all")').prop("disabled",false);if(r)a.filter(fy.sprintf('[value="%s"]',t)).prop("checked",e);if(a.filter(":checked").length<=this.options.minimumCountColumns)a.filter(":checked").prop("disabled",true)}}},{key:"getVisibleColumns",value:function pt(){var t=this;return this.columns.filter(function(e){return e.visible&&!t.isSelectionColumn(e)})}},{key:"getHiddenColumns",value:function gt(){return this.columns.filter(function(t){var e=t.visible;return!e})}},{key:"isSelectionColumn",value:function bt(t){return t.radio||t.checkbox}},{key:"showAllColumns",value:function mt(){this._toggleAllColumns(true)}},{key:"hideAllColumns",value:function yt(){this._toggleAllColumns(false)}},{key:"_toggleAllColumns",value:function wt(e){var r=this;var a=b(this.columns.slice().reverse()),i;try{for(a.s();!(i=a.n()).done;){var n=i.value;if(n.switchable){if(!e&&this.options.showColumns&&this.getVisibleColumns().filter(function(t){return t.switchable}).length===this.options.minimumCountColumns)continue;n.visible=e}}}catch(o){a.e(o)}finally{a.f()}this.initHeader();this.initSearch();this.initPagination();this.initBody();if(this.options.showColumns){var s=this.$toolbar.find('.keep-open input[type="checkbox"]:not(".toggle-all")').prop("disabled",false);if(e)s.prop("checked",e);else s.get().reverse().forEach(function(a){if(s.filter(":checked").length>r.options.minimumCountColumns)t(a).prop("checked",e)});if(s.filter(":checked").length<=this.options.minimumCountColumns)s.filter(":checked").prop("disabled",true)}}},{key:"mergeCells",value:function St(t){var e=t.index;var r=this.getVisibleFields().indexOf(t.field);var a=t.rowspan||1;var i=t.colspan||1;var n;var o;var s=this.$body.find(">tr[data-index]");r+=fy.getDetailViewIndexOffset(this.options);var l=s.eq(e).find(">td").eq(r);if(e<0||r<0||e>=this.data.length)return;for(n=e;n<e+a;n++)for(o=r;o<r+i;o++)s.eq(n).find(">td").eq(o).hide();l.attr("rowspan",a).attr("colspan",i).show()}},{key:"checkAll",value:function xt(){this._toggleCheckAll(true)}},{key:"uncheckAll",value:function Ot(){this._toggleCheckAll(false)}},{key:"_toggleCheckAll",value:function kt(t){var e=this.getSelections();this.$selectAll.add(this.$selectAll_).prop("checked",t);this.$selectItem.filter(":enabled").prop("checked",t);this.updateRows();this.updateSelected();var r=this.getSelections();if(t){this.trigger("check-all",r,e);return}this.trigger("uncheck-all",r,e)}},{key:"checkInvert",value:function Pt(){var e=this.$selectItem.filter(":enabled");var r=e.filter(":checked");e.each(function(e,r){t(r).prop("checked",!t(r).prop("checked"))});this.updateRows();this.updateSelected();this.trigger("uncheck-some",r);r=this.getSelections();this.trigger("check-some",r)}},{key:"check",value:function Ct(t){this._toggleCheck(true,t)}},{key:"uncheck",value:function Tt(t){this._toggleCheck(false,t)}},{key:"_toggleCheck",value:function It(t,e){var r=this.$selectItem.filter('[data-index="'.concat(e,'"]'));var a=this.data[e];if(r.is(":radio")||this.options.singleSelect||this.options.multipleSelectRow&&!this.multipleSelectRowCtrlKey&&!this.multipleSelectRowShiftKey){var i=b(this.options.data),n;try{for(i.s();!(n=i.n()).done;){var o=n.value;o[this.header.stateField]=false}}catch(s){i.e(s)}finally{i.f()}this.$selectItem.filter(":checked").not(r).prop("checked",false)}a[this.header.stateField]=t;if(this.options.multipleSelectRow){if(this.multipleSelectRowShiftKey&&this.multipleSelectRowLastSelectedIndex>=0){var c=this.multipleSelectRowLastSelectedIndex<e?[this.multipleSelectRowLastSelectedIndex,e]:[e,this.multipleSelectRowLastSelectedIndex],f=l(c,2),u=f[0],h=f[1];for(var v=u+1;v<h;v++){this.data[v][this.header.stateField]=true;this.$selectItem.filter('[data-index="'.concat(v,'"]')).prop("checked",true)}}this.multipleSelectRowCtrlKey=false;this.multipleSelectRowShiftKey=false;this.multipleSelectRowLastSelectedIndex=t?e:-1}r.prop("checked",t);this.updateSelected();this.trigger(t?"check":"uncheck",this.data[e],r)}},{key:"checkBy",value:function At(t){this._toggleCheckBy(true,t)}},{key:"uncheckBy",value:function $t(t){this._toggleCheckBy(false,t)}},{key:"_toggleCheckBy",value:function Rt(t,e){var r=this;if(!e.hasOwnProperty("field")||!e.hasOwnProperty("values"))return;var a=[];this.data.forEach(function(i,n){if(!i.hasOwnProperty(e.field))return false;if(e.values.includes(i[e.field])){var o=r.$selectItem.filter(":enabled").filter(fy.sprintf('[data-index="%s"]',n));var s=e.hasOwnProperty("onlyCurrentPage")?e.onlyCurrentPage:false;o=t?o.not(":checked"):o.filter(":checked");if(!o.length&&s)return;o.prop("checked",t);i[r.header.stateField]=t;a.push(i);r.trigger(t?"check":"uncheck",i,o)}});this.updateSelected();this.trigger(t?"check-some":"uncheck-some",a)}},{key:"refresh",value:function Et(t){if(t&&t.url)this.options.url=t.url;if(t&&t.pageNumber)this.options.pageNumber=t.pageNumber;if(t&&t.pageSize)this.options.pageSize=t.pageSize;table.rememberSelecteds={};table.rememberSelectedIds={};this.trigger("refresh",this.initServer(t&&t.silent,t&&t.query,t&&t.url))}},{key:"destroy",value:function jt(){this.$el.insertBefore(this.$container);t(this.options.toolbar).insertBefore(this.$el);this.$container.next().remove();this.$container.remove();this.$el.html(this.$el_.html()).css("margin-top","0").attr("class",this.$el_.attr("class")||"");var e=fy.getEventName("resize.bootstrap-table",this.$el.attr("id"));t(window).off(e)}},{key:"resetView",value:function _t(t){var e=0;if(t&&t.height)this.options.height=t.height;this.$tableContainer.toggleClass("has-card-view",this.options.cardView);if(this.options.height){var r=this.$tableBody.get(0);this.hasScrollBar=r.scrollWidth>r.clientWidth}if(!this.options.cardView&&this.options.showHeader&&this.options.height){this.$tableHeader.show();this.resetHeader();e+=this.$header.outerHeight(true)+1}else{this.$tableHeader.hide();this.trigger("post-header")}if(!this.options.cardView&&this.options.showFooter){this.$tableFooter.show();this.fitFooter();if(this.options.height)e+=this.$tableFooter.outerHeight(true)}if(this.$container.hasClass("fullscreen")){this.$tableContainer.css("height","");this.$tableContainer.css("width","")}else if(this.options.height){if(this.$tableBorder){this.$tableBorder.css("width","");this.$tableBorder.css("height","")}var a=this.$toolbar.outerHeight(true);var i=this.$pagination.outerHeight(true);var n=this.options.height-a-i;var o=this.$tableBody.find(">table");var s=o.outerHeight();this.$tableContainer.css("height","".concat(n,"px"));if(this.$tableBorder&&o.is(":visible")){var l=n-s-2;if(this.hasScrollBar)l-=fy.getScrollBarWidth();this.$tableBorder.css("width","".concat(o.outerWidth(),"px"));this.$tableBorder.css("height","".concat(l,"px"))}}if(this.options.cardView){this.$el.css("margin-top","0");this.$tableContainer.css("padding-bottom","0");this.$tableFooter.hide()}else{this.getCaret();this.$tableContainer.css("padding-bottom","".concat(e,"px"))}this.trigger("reset-view")}},{key:"showLoading",value:function Nt(){this.$tableLoading.toggleClass("open",true);var t=this.options.loadingFontSize;if("auto"===this.options.loadingFontSize){t=.04*this.$tableLoading.width();t=Math.max(12,t);t=Math.min(32,t);t="".concat(t,"px")}this.$tableLoading.find(".loading-text").css("font-size",t)}},{key:"hideLoading",value:function Ft(){this.$tableLoading.toggleClass("open",false)}},{key:"toggleShowSearch",value:function Dt(){this.$el.parents(".select-table").siblings().slideToggle()}},{key:"togglePagination",value:function Vt(){this.options.pagination=!this.options.pagination;var t=this.options.showButtonIcons?this.options.pagination?this.options.icons.paginationSwitchDown:this.options.icons.paginationSwitchUp:"";var e=this.options.showButtonText?this.options.pagination?this.options.formatPaginationSwitchUp():this.options.formatPaginationSwitchDown():"";this.$toolbar.find('button[name="paginationSwitch"]').html("".concat(fy.sprintf(this.constants.html.icon,this.options.iconsPrefix,t)," ").concat(e));this.updatePagination();this.trigger("toggle-pagination",this.options.pagination)}},{key:"toggleFullscreen",value:function Bt(){this.$el.closest(".bootstrap-table").toggleClass("fullscreen");this.resetView()}},{key:"toggleView",value:function Lt(){this.options.cardView=!this.options.cardView;this.initHeader();var t=this.options.showButtonIcons?this.options.cardView?this.options.icons.toggleOn:this.options.icons.toggleOff:"";var e=this.options.showButtonText?this.options.cardView?this.options.formatToggleOff():this.options.formatToggleOn():"";this.$toolbar.find('button[name="toggle"]').html("".concat(fy.sprintf(this.constants.html.icon,this.options.iconsPrefix,t)," ").concat(e)).attr("aria-label",e).attr("title",e);this.initBody();this.trigger("toggle",this.options.cardView)}},{key:"resetSearch",value:function Ht(t){var e=fy.getSearchInput(this);var r=t||"";e.val(r);this.searchText=r;this.onSearch({currentTarget:e},false)}},{key:"filterBy",value:function Mt(t,e){this.filterOptions=fy.isEmptyObject(e)?this.options.filterOptions:fy.extend(this.options.filterOptions,e);this.filterColumns=fy.isEmptyObject(t)?{}:t;this.options.pageNumber=1;this.initSearch();this.updatePagination()}},{key:"scrollTo",value:function Ut(e){var r={unit:"px",value:0};if("object"===i(e))r=Object.assign(r,e);else if("string"===typeof e&&"bottom"===e)r.value=this.$tableBody[0].scrollHeight;else if("string"===typeof e||"number"===typeof e)r.value=e;var Ut=r.value;if("rows"===r.unit){Ut=0;this.$body.find("> tr:lt(".concat(r.value,")")).each(function(e,r){Ut+=t(r).outerHeight(true)})}this.$tableBody.scrollTop(Ut)}},{key:"getScrollPosition",value:function zt(){return this.$tableBody.scrollTop()}},{key:"selectPage",value:function qt(t){if(t>0&&t<=this.options.totalPages){this.options.pageNumber=t;this.updatePagination()}}},{key:"prevPage",value:function Gt(){if(this.options.pageNumber>1){this.options.pageNumber--;this.updatePagination()}}},{key:"nextPage",value:function Wt(){if(this.options.pageNumber<this.options.totalPages){this.options.pageNumber++;this.updatePagination()}}},{key:"toggleDetailView",value:function Kt(t,e){var r=this.$body.find(fy.sprintf('> tr[data-index="%s"]',t));if(r.next().is("tr.detail-view"))this.collapseRow(t);else this.expandRow(t,e);this.resetView()}},{key:"expandRow",value:function Yt(t,e){var r=this.data[t];var a=this.$body.find(fy.sprintf('> tr[data-index="%s"][data-has-detail-view]',t));if(this.options.detailViewIcon)a.find("a.detail-icon").html(fy.sprintf(this.constants.html.icon,this.options.iconsPrefix,this.options.icons.detailClose));if(a.next().is("tr.detail-view"))return;a.after(fy.sprintf('<tr class="detail-view"><td colspan="%s"></td></tr>',a.children("td").length));var i=a.next().find("td");var n=e||this.options.detailFormatter;var o=fy.calculateObjectValue(this.options,n,[t,r,i],"");if(1===i.length)i.append(o);this.trigger("expand-row",t,r,i)}},{key:"expandRowByUniqueId",value:function Jt(t){var e=this.getRowByUniqueId(t);if(!e)return;this.expandRow(this.data.indexOf(e))}},{key:"collapseRow",value:function Xt(t){var e=this.data[t];var r=this.$body.find(fy.sprintf('> tr[data-index="%s"][data-has-detail-view]',t));if(!r.next().is("tr.detail-view"))return;if(this.options.detailViewIcon)r.find("a.detail-icon").html(fy.sprintf(this.constants.html.icon,this.options.iconsPrefix,this.options.icons.detailOpen));this.trigger("collapse-row",t,e,r.next());r.next().remove()}},{key:"collapseRowByUniqueId",value:function Qt(t){var e=this.getRowByUniqueId(t);if(!e)return;this.collapseRow(this.data.indexOf(e))}},{key:"expandAllRows",value:function Zt(){var e=this.$body.find("> tr[data-index][data-has-detail-view]");for(var r=0;r<e.length;r++)this.expandRow(t(e[r]).data("index"))}},{key:"collapseAllRows",value:function te(){var e=this.$body.find("> tr[data-index][data-has-detail-view]");for(var r=0;r<e.length;r++)this.collapseRow(t(e[r]).data("index"))}},{key:"updateColumnTitle",value:function ee(e){if(!e.hasOwnProperty("field")||!e.hasOwnProperty("title"))return;this.columns[this.fieldsColumnsIndex[e.field]].title=this.options.escape&&this.options.escapeTitle?fy.escapeHTML(e.title):e.title;if(this.columns[this.fieldsColumnsIndex[e.field]].visible){this.$header.find("th[data-field]").each(function(r,a){if(t(a).data("field")===e.field){t(t(a).find(".th-inner")[0]).html(e.title);return false}});this.resetView()}}},{key:"updateFormatText",value:function re(t,e){if(!/^format/.test(t)||!this.options[t])return;if("string"===typeof e)this.options[t]=function(){return e};else if("function"===typeof e)this.options[t]=e;this.initToolbar();this.initPagination();this.initBody()}}])}();Oy.VERSION=yy.VERSION;Oy.DEFAULTS=yy.DEFAULTS;Oy.LOCALES=yy.LOCALES;Oy.COLUMN_DEFAULTS=yy.COLUMN_DEFAULTS;Oy.METHODS=yy.METHODS;Oy.EVENTS=yy.EVENTS;t.BootstrapTable=Oy;t.fn.bootstrapTable=function(e){for(var r=arguments.length,a=new Array(r>1?r-1:0),n=1;n<r;n++)a[n-1]=arguments[n];var o;this.each(function(r,n){var s=t(n).data("bootstrap.table");if("string"===typeof e){var l;if(!yy.METHODS.includes(e))throw new Error("Unknown method: ".concat(e));if(!s)return;o=(l=s)[e].apply(l,a);if("destroy"===e)t(n).removeData("bootstrap.table");return}if(s){console.warn("You cannot initialize the table more than once!");return}var c=fy.extend(true,{},Oy.DEFAULTS,t(n).data(),"object"===i(e)&&e);s=new t.BootstrapTable(n,c);t(n).data("bootstrap.table",s);s.init()});return"undefined"===typeof o?this:o};t.fn.bootstrapTable.Constructor=Oy;t.fn.bootstrapTable.theme=yy.THEME;t.fn.bootstrapTable.VERSION=yy.VERSION;t.fn.bootstrapTable.defaults=Oy.DEFAULTS;t.fn.bootstrapTable.columnDefaults=Oy.COLUMN_DEFAULTS;t.fn.bootstrapTable.events=Oy.EVENTS;t.fn.bootstrapTable.locales=Oy.LOCALES;t.fn.bootstrapTable.methods=Oy.METHODS;t.fn.bootstrapTable.utils=fy;t(function(){t('[data-toggle="table"]').bootstrapTable()});return Oy});var TABLE_EVENTS="all.bs.table click-cell.bs.table dbl-click-cell.bs.table click-row.bs.table dbl-click-row.bs.table sort.bs.table check.bs.table uncheck.bs.table onUncheck check-all.bs.table uncheck-all.bs.table check-some.bs.table uncheck-some.bs.table load-success.bs.table load-error.bs.table column-switch.bs.table page-change.bs.table search.bs.table toggle.bs.table show-search.bs.table expand-row.bs.table collapse-row.bs.table refresh-options.bs.table reset-view.bs.table refresh.bs.table";var firstLoadTable=[];var union=function(t,e){if($.isPlainObject(e))addRememberRow(t,e);else if($.isArray(e))$.each(e,function(e,r){if($.isPlainObject(r))addRememberRow(t,r);else if($.inArray(r,t)==-1)t[t.length]=r});else if($.inArray(e,t)==-1)t[t.length]=e;return t};var difference=function(t,e){if($.isPlainObject(e))removeRememberRow(t,e);else if($.isArray(e))$.each(e,function(e,r){if($.isPlainObject(r))removeRememberRow(t,r);else{var a=$.inArray(r,t);if(a!=-1)t.splice(a,1)}});else{var r=$.inArray(e,t);if(r!=-1)t.splice(r,1)}return t};function getRememberRowIds(t,e){if($.isArray(t))props=$.map(t,function(t){return t[e]});else props=[t[e]];return props}function addRememberRow(t,e){var r=null==table.options.uniqueId?table.options.columns[1].field:table.options.uniqueId;var a=getRememberRowIds(t,r);if($.inArray(e[r],a)==-1)t[t.length]=e}function removeRememberRow(t,e){var r=null==table.options.uniqueId?table.options.columns[1].field:table.options.uniqueId;var a=getRememberRowIds(t,r);var i=$.inArray(e[r],a);if(i!=-1)t.splice(i,1)}var _={union:union,difference:difference};
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/auto-refresh/bootstrap-table-auto-refresh.js b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/auto-refresh/bootstrap-table-auto-refresh.js
new file mode 100644
index 0000000..12fc0fd
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/auto-refresh/bootstrap-table-auto-refresh.js
@@ -0,0 +1,95 @@
+/**
+ * @author: Alec Fenichel
+ * @webSite: https://fenichelar.com
+ * @update: zhixin wen <wenzhixin2010@gmail.com>
+ */
+
+var Utils = $.fn.bootstrapTable.utils
+
+$.extend($.fn.bootstrapTable.defaults, {
+  autoRefresh: false,
+  showAutoRefresh: true,
+  autoRefreshInterval: 60,
+  autoRefreshSilent: true,
+  autoRefreshStatus: true,
+  autoRefreshFunction: null
+})
+
+$.extend($.fn.bootstrapTable.defaults.icons, {
+  autoRefresh: {
+    bootstrap3: 'glyphicon-time icon-time',
+    bootstrap5: 'bi-clock',
+    materialize: 'access_time',
+    'bootstrap-table': 'icon-clock'
+  }[$.fn.bootstrapTable.theme] || 'fa-clock'
+})
+
+$.extend($.fn.bootstrapTable.locales, {
+  formatAutoRefresh () {
+    return 'Auto Refresh'
+  }
+})
+
+$.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales)
+
+$.BootstrapTable = class extends $.BootstrapTable {
+  init (...args) {
+    super.init(...args)
+
+    if (this.options.autoRefresh && this.options.autoRefreshStatus) {
+      this.setupRefreshInterval()
+    }
+  }
+
+  initToolbar (...args) {
+    if (this.options.autoRefresh) {
+      this.buttons = Object.assign(this.buttons, {
+        autoRefresh: {
+          html: `
+            <button class="auto-refresh ${this.constants.buttonsClass}
+              ${this.options.autoRefreshStatus ? ` ${this.constants.classes.buttonActive}` : ''}"
+              type="button" name="autoRefresh" title="${this.options.formatAutoRefresh()}">
+              ${this.options.showButtonIcons ? Utils.sprintf(this.constants.html.icon, this.options.iconsPrefix, this.options.icons.autoRefresh) : ''}
+              ${this.options.showButtonText ? this.options.formatAutoRefresh() : ''}
+            </button>
+           `,
+          event: this.toggleAutoRefresh
+        }
+      })
+    }
+
+    super.initToolbar(...args)
+  }
+
+  toggleAutoRefresh () {
+    if (this.options.autoRefresh) {
+      if (this.options.autoRefreshStatus) {
+        clearInterval(this.options.autoRefreshFunction)
+        this.$toolbar.find('>.columns .auto-refresh')
+          .removeClass(this.constants.classes.buttonActive)
+      } else {
+        this.setupRefreshInterval()
+        this.$toolbar.find('>.columns .auto-refresh')
+          .addClass(this.constants.classes.buttonActive)
+      }
+      this.options.autoRefreshStatus = !this.options.autoRefreshStatus
+    }
+  }
+
+  destroy () {
+    if (this.options.autoRefresh && this.options.autoRefreshStatus) {
+      clearInterval(this.options.autoRefreshFunction)
+    }
+
+    super.destroy()
+  }
+
+  setupRefreshInterval () {
+    this.options.autoRefreshFunction = setInterval(() => {
+      if (!this.options.autoRefresh || !this.options.autoRefreshStatus) {
+        return
+      }
+      this.refresh({ silent: this.options.autoRefreshSilent })
+    }, this.options.autoRefreshInterval * 1000)
+  }
+}
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/columns/bootstrap-table-fixed-columns.js b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/columns/bootstrap-table-fixed-columns.js
new file mode 100644
index 0000000..e35b89f
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/columns/bootstrap-table-fixed-columns.js
@@ -0,0 +1,5 @@
+/**
+ * @author zhixin wen <wenzhixin2010@gmail.com>
+ * @github: bootstrap-table/dist/extensions/fixed-columns/bootstrap-table-fixed-columns.min.js
+ */
+!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(require("jquery")):"function"==typeof define&&define.amd?define(["jquery"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).jQuery)}(this,(function(t){"use strict";function e(t){return t&&"object"==typeof t&&"default"in t?t:{default:t}}var n=e(t);function i(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function r(t,e){for(var n=0;n<e.length;n++){var i=e[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,i.key,i)}}function o(t){return o=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(t){return t.__proto__||Object.getPrototypeOf(t)},o(t)}function u(t,e){return u=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(t,e){return t.__proto__=e,t},u(t,e)}function f(t,e){if(e&&("object"==typeof e||"function"==typeof e))return e;if(void 0!==e)throw new TypeError("Derived constructors may only return object or undefined");return function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(t)}function a(t){var e=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var n,i=o(t);if(e){var r=o(this).constructor;n=Reflect.construct(i,arguments,r)}else n=i.apply(this,arguments);return f(this,n)}}function c(t,e){for(;!Object.prototype.hasOwnProperty.call(t,e)&&null!==(t=o(t)););return t}function s(){return s="undefined"!=typeof Reflect&&Reflect.get?Reflect.get.bind():function(t,e,n){var i=c(t,e);if(i){var r=Object.getOwnPropertyDescriptor(i,e);return r.get?r.get.call(arguments.length<3?t:n):r.value}},s.apply(this,arguments)}var l="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},d=function(t){return t&&t.Math==Math&&t},h=d("object"==typeof globalThis&&globalThis)||d("object"==typeof window&&window)||d("object"==typeof self&&self)||d("object"==typeof l&&l)||function(){return this}()||Function("return this")(),p={},y=function(t){try{return!!t()}catch(t){return!0}},b=!y((function(){return 7!=Object.defineProperty({},1,{get:function(){return 7}})[1]})),g=!y((function(){var t=function(){}.bind();return"function"!=typeof t||t.hasOwnProperty("prototype")})),v=g,m=Function.prototype.call,x=v?m.bind(m):function(){return m.apply(m,arguments)},$={},w={}.propertyIsEnumerable,C=Object.getOwnPropertyDescriptor,O=C&&!w.call({1:2},1);$.f=O?function(t){var e=C(this,t);return!!e&&e.enumerable}:w;var S,j,R=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}},B=g,T=Function.prototype,F=T.call,k=B&&T.bind.bind(F,F),P=function(t){return B?k(t):function(){return F.apply(t,arguments)}},E=P,A=E({}.toString),N=E("".slice),H=function(t){return N(A(t),8,-1)},D=H,I=P,L=function(t){if("Function"===D(t))return I(t)},M=y,_=H,W=Object,z=L("".split),X=M((function(){return!W("z").propertyIsEnumerable(0)}))?function(t){return"String"==_(t)?z(t,""):W(t)}:W,Y=function(t){return null==t},q=Y,G=TypeError,V=function(t){if(q(t))throw G("Can't call method on "+t);return t},U=X,K=V,Q=function(t){return U(K(t))},Z="object"==typeof document&&document.all,J={all:Z,IS_HTMLDDA:void 0===Z&&void 0!==Z},tt=J.all,et=J.IS_HTMLDDA?function(t){return"function"==typeof t||t===tt}:function(t){return"function"==typeof t},nt=et,it=J.all,rt=J.IS_HTMLDDA?function(t){return"object"==typeof t?null!==t:nt(t)||t===it}:function(t){return"object"==typeof t?null!==t:nt(t)},ot=h,ut=et,ft=function(t){return ut(t)?t:void 0},at=function(t,e){return arguments.length<2?ft(ot[t]):ot[t]&&ot[t][e]},ct=L({}.isPrototypeOf),st=h,lt=at("navigator","userAgent")||"",dt=st.process,ht=st.Deno,pt=dt&&dt.versions||ht&&ht.version,yt=pt&&pt.v8;yt&&(j=(S=yt.split("."))[0]>0&&S[0]<4?1:+(S[0]+S[1])),!j&&lt&&(!(S=lt.match(/Edge\/(\d+)/))||S[1]>=74)&&(S=lt.match(/Chrome\/(\d+)/))&&(j=+S[1]);var bt=j,gt=bt,vt=y,mt=!!Object.getOwnPropertySymbols&&!vt((function(){var t=Symbol();return!String(t)||!(Object(t)instanceof Symbol)||!Symbol.sham&&gt&&gt<41})),xt=mt&&!Symbol.sham&&"symbol"==typeof Symbol.iterator,$t=at,wt=et,Ct=ct,Ot=Object,St=xt?function(t){return"symbol"==typeof t}:function(t){var e=$t("Symbol");return wt(e)&&Ct(e.prototype,Ot(t))},jt=String,Rt=et,Bt=function(t){try{return jt(t)}catch(t){return"Object"}},Tt=TypeError,Ft=function(t){if(Rt(t))return t;throw Tt(Bt(t)+" is not a function")},kt=Ft,Pt=Y,Et=x,At=et,Nt=rt,Ht=TypeError,Dt={exports:{}},It=h,Lt=Object.defineProperty,Mt=function(t,e){try{Lt(It,t,{value:e,configurable:!0,writable:!0})}catch(n){It[t]=e}return e},_t=Mt,Wt="__core-js_shared__",zt=h[Wt]||_t(Wt,{}),Xt=zt;(Dt.exports=function(t,e){return Xt[t]||(Xt[t]=void 0!==e?e:{})})("versions",[]).push({version:"3.25.5",mode:"global",copyright:"© 2014-2022 Denis Pushkarev (zloirock.ru)",license:"https://github.com/zloirock/core-js/blob/v3.25.5/LICENSE",source:"https://github.com/zloirock/core-js"});var Yt=V,qt=Object,Gt=function(t){return qt(Yt(t))},Vt=Gt,Ut=L({}.hasOwnProperty),Kt=Object.hasOwn||function(t,e){return Ut(Vt(t),e)},Qt=L,Zt=0,Jt=Math.random(),te=Qt(1..toString),ee=function(t){return"Symbol("+(void 0===t?"":t)+")_"+te(++Zt+Jt,36)},ne=h,ie=Dt.exports,re=Kt,oe=ee,ue=mt,fe=xt,ae=ie("wks"),ce=ne.Symbol,se=ce&&ce.for,le=fe?ce:ce&&ce.withoutSetter||oe,de=function(t){if(!re(ae,t)||!ue&&"string"!=typeof ae[t]){var e="Symbol."+t;ue&&re(ce,t)?ae[t]=ce[t]:ae[t]=fe&&se?se(e):le(e)}return ae[t]},he=x,pe=rt,ye=St,be=function(t,e){var n=t[e];return Pt(n)?void 0:kt(n)},ge=function(t,e){var n,i;if("string"===e&&At(n=t.toString)&&!Nt(i=Et(n,t)))return i;if(At(n=t.valueOf)&&!Nt(i=Et(n,t)))return i;if("string"!==e&&At(n=t.toString)&&!Nt(i=Et(n,t)))return i;throw Ht("Can't convert object to primitive value")},ve=TypeError,me=de("toPrimitive"),xe=function(t,e){if(!pe(t)||ye(t))return t;var n,i=be(t,me);if(i){if(void 0===e&&(e="default"),n=he(i,t,e),!pe(n)||ye(n))return n;throw ve("Can't convert object to primitive value")}return void 0===e&&(e="number"),ge(t,e)},$e=St,we=function(t){var e=xe(t,"string");return $e(e)?e:e+""},Ce=rt,Oe=h.document,Se=Ce(Oe)&&Ce(Oe.createElement),je=function(t){return Se?Oe.createElement(t):{}},Re=je,Be=!b&&!y((function(){return 7!=Object.defineProperty(Re("div"),"a",{get:function(){return 7}}).a})),Te=b,Fe=x,ke=$,Pe=R,Ee=Q,Ae=we,Ne=Kt,He=Be,De=Object.getOwnPropertyDescriptor;p.f=Te?De:function(t,e){if(t=Ee(t),e=Ae(e),He)try{return De(t,e)}catch(t){}if(Ne(t,e))return Pe(!Fe(ke.f,t,e),t[e])};var Ie={},Le=b&&y((function(){return 42!=Object.defineProperty((function(){}),"prototype",{value:42,writable:!1}).prototype})),Me=rt,_e=String,We=TypeError,ze=function(t){if(Me(t))return t;throw We(_e(t)+" is not an object")},Xe=b,Ye=Be,qe=Le,Ge=ze,Ve=we,Ue=TypeError,Ke=Object.defineProperty,Qe=Object.getOwnPropertyDescriptor,Ze="enumerable",Je="configurable",tn="writable";Ie.f=Xe?qe?function(t,e,n){if(Ge(t),e=Ve(e),Ge(n),"function"==typeof t&&"prototype"===e&&"value"in n&&tn in n&&!n.writable){var i=Qe(t,e);i&&i.writable&&(t[e]=n.value,n={configurable:Je in n?n.configurable:i.configurable,enumerable:Ze in n?n.enumerable:i.enumerable,writable:!1})}return Ke(t,e,n)}:Ke:function(t,e,n){if(Ge(t),e=Ve(e),Ge(n),Ye)try{return Ke(t,e,n)}catch(t){}if("get"in n||"set"in n)throw Ue("Accessors not supported");return"value"in n&&(t[e]=n.value),t};var en=Ie,nn=R,rn=b?function(t,e,n){return en.f(t,e,nn(1,n))}:function(t,e,n){return t[e]=n,t},on={exports:{}},un=b,fn=Kt,an=Function.prototype,cn=un&&Object.getOwnPropertyDescriptor,sn=fn(an,"name"),ln={EXISTS:sn,PROPER:sn&&"something"===function(){}.name,CONFIGURABLE:sn&&(!un||un&&cn(an,"name").configurable)},dn=et,hn=zt,pn=L(Function.toString);dn(hn.inspectSource)||(hn.inspectSource=function(t){return pn(t)});var yn,bn,gn,vn=hn.inspectSource,mn=et,xn=h.WeakMap,$n=mn(xn)&&/native code/.test(String(xn)),wn=Dt.exports,Cn=ee,On=wn("keys"),Sn=function(t){return On[t]||(On[t]=Cn(t))},jn={},Rn=$n,Bn=h,Tn=rt,Fn=rn,kn=Kt,Pn=zt,En=Sn,An=jn,Nn="Object already initialized",Hn=Bn.TypeError,Dn=Bn.WeakMap;if(Rn||Pn.state){var In=Pn.state||(Pn.state=new Dn);In.get=In.get,In.has=In.has,In.set=In.set,yn=function(t,e){if(In.has(t))throw Hn(Nn);return e.facade=t,In.set(t,e),e},bn=function(t){return In.get(t)||{}},gn=function(t){return In.has(t)}}else{var Ln=En("state");An[Ln]=!0,yn=function(t,e){if(kn(t,Ln))throw Hn(Nn);return e.facade=t,Fn(t,Ln,e),e},bn=function(t){return kn(t,Ln)?t[Ln]:{}},gn=function(t){return kn(t,Ln)}}var Mn={set:yn,get:bn,has:gn,enforce:function(t){return gn(t)?bn(t):yn(t,{})},getterFor:function(t){return function(e){var n;if(!Tn(e)||(n=bn(e)).type!==t)throw Hn("Incompatible receiver, "+t+" required");return n}}},_n=y,Wn=et,zn=Kt,Xn=b,Yn=ln.CONFIGURABLE,qn=vn,Gn=Mn.enforce,Vn=Mn.get,Un=Object.defineProperty,Kn=Xn&&!_n((function(){return 8!==Un((function(){}),"length",{value:8}).length})),Qn=String(String).split("String"),Zn=on.exports=function(t,e,n){"Symbol("===String(e).slice(0,7)&&(e="["+String(e).replace(/^Symbol\(([^)]*)\)/,"$1")+"]"),n&&n.getter&&(e="get "+e),n&&n.setter&&(e="set "+e),(!zn(t,"name")||Yn&&t.name!==e)&&(Xn?Un(t,"name",{value:e,configurable:!0}):t.name=e),Kn&&n&&zn(n,"arity")&&t.length!==n.arity&&Un(t,"length",{value:n.arity});try{n&&zn(n,"constructor")&&n.constructor?Xn&&Un(t,"prototype",{writable:!1}):t.prototype&&(t.prototype=void 0)}catch(t){}var i=Gn(t);return zn(i,"source")||(i.source=Qn.join("string"==typeof e?e:"")),t};Function.prototype.toString=Zn((function(){return Wn(this)&&Vn(this).source||qn(this)}),"toString");var Jn=et,ti=Ie,ei=on.exports,ni=Mt,ii=function(t,e,n,i){i||(i={});var r=i.enumerable,o=void 0!==i.name?i.name:e;if(Jn(n)&&ei(n,o,i),i.global)r?t[e]=n:ni(e,n);else{try{i.unsafe?t[e]&&(r=!0):delete t[e]}catch(t){}r?t[e]=n:ti.f(t,e,{value:n,enumerable:!1,configurable:!i.nonConfigurable,writable:!i.nonWritable})}return t},ri={},oi=Math.ceil,ui=Math.floor,fi=Math.trunc||function(t){var e=+t;return(e>0?ui:oi)(e)},ai=function(t){var e=+t;return e!=e||0===e?0:fi(e)},ci=ai,si=Math.max,li=Math.min,di=ai,hi=Math.min,pi=function(t){return t>0?hi(di(t),9007199254740991):0},yi=function(t){return pi(t.length)},bi=Q,gi=function(t,e){var n=ci(t);return n<0?si(n+e,0):li(n,e)},vi=yi,mi=function(t){return function(e,n,i){var r,o=bi(e),u=vi(o),f=gi(i,u);if(t&&n!=n){for(;u>f;)if((r=o[f++])!=r)return!0}else for(;u>f;f++)if((t||f in o)&&o[f]===n)return t||f||0;return!t&&-1}},xi={includes:mi(!0),indexOf:mi(!1)},$i=Kt,wi=Q,Ci=xi.indexOf,Oi=jn,Si=L([].push),ji=function(t,e){var n,i=wi(t),r=0,o=[];for(n in i)!$i(Oi,n)&&$i(i,n)&&Si(o,n);for(;e.length>r;)$i(i,n=e[r++])&&(~Ci(o,n)||Si(o,n));return o},Ri=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"],Bi=ji,Ti=Ri.concat("length","prototype");ri.f=Object.getOwnPropertyNames||function(t){return Bi(t,Ti)};var Fi={};Fi.f=Object.getOwnPropertySymbols;var ki=at,Pi=ri,Ei=Fi,Ai=ze,Ni=L([].concat),Hi=ki("Reflect","ownKeys")||function(t){var e=Pi.f(Ai(t)),n=Ei.f;return n?Ni(e,n(t)):e},Di=Kt,Ii=Hi,Li=p,Mi=Ie,_i=y,Wi=et,zi=/#|\.prototype\./,Xi=function(t,e){var n=qi[Yi(t)];return n==Vi||n!=Gi&&(Wi(e)?_i(e):!!e)},Yi=Xi.normalize=function(t){return String(t).replace(zi,".").toLowerCase()},qi=Xi.data={},Gi=Xi.NATIVE="N",Vi=Xi.POLYFILL="P",Ui=Xi,Ki=h,Qi=p.f,Zi=rn,Ji=ii,tr=Mt,er=function(t,e,n){for(var i=Ii(e),r=Mi.f,o=Li.f,u=0;u<i.length;u++){var f=i[u];Di(t,f)||n&&Di(n,f)||r(t,f,o(e,f))}},nr=Ui,ir=function(t,e){var n,i,r,o,u,f=t.target,a=t.global,c=t.stat;if(n=a?Ki:c?Ki[f]||tr(f,{}):(Ki[f]||{}).prototype)for(i in e){if(o=e[i],r=t.dontCallGetSet?(u=Qi(n,i))&&u.value:n[i],!nr(a?i:f+(c?".":"#")+i,t.forced)&&void 0!==r){if(typeof o==typeof r)continue;er(o,r)}(t.sham||r&&r.sham)&&Zi(o,"sham",!0),Ji(n,i,o,t)}},rr=Ft,or=g,ur=L(L.bind),fr=H,ar=Array.isArray||function(t){return"Array"==fr(t)},cr={};cr[de("toStringTag")]="z";var sr="[object z]"===String(cr),lr=sr,dr=et,hr=H,pr=de("toStringTag"),yr=Object,br="Arguments"==hr(function(){return arguments}()),gr=lr?hr:function(t){var e,n,i;return void 0===t?"Undefined":null===t?"Null":"string"==typeof(n=function(t,e){try{return t[e]}catch(t){}}(e=yr(t),pr))?n:br?hr(e):"Object"==(i=hr(e))&&dr(e.callee)?"Arguments":i},vr=L,mr=y,xr=et,$r=gr,wr=vn,Cr=function(){},Or=[],Sr=at("Reflect","construct"),jr=/^\s*(?:class|function)\b/,Rr=vr(jr.exec),Br=!jr.exec(Cr),Tr=function(t){if(!xr(t))return!1;try{return Sr(Cr,Or,t),!0}catch(t){return!1}},Fr=function(t){if(!xr(t))return!1;switch($r(t)){case"AsyncFunction":case"GeneratorFunction":case"AsyncGeneratorFunction":return!1}try{return Br||!!Rr(jr,wr(t))}catch(t){return!0}};Fr.sham=!0;var kr=!Sr||mr((function(){var t;return Tr(Tr.call)||!Tr(Object)||!Tr((function(){t=!0}))||t}))?Fr:Tr,Pr=ar,Er=kr,Ar=rt,Nr=de("species"),Hr=Array,Dr=function(t){var e;return Pr(t)&&(e=t.constructor,(Er(e)&&(e===Hr||Pr(e.prototype))||Ar(e)&&null===(e=e[Nr]))&&(e=void 0)),void 0===e?Hr:e},Ir=function(t,e){return new(Dr(t))(0===e?0:e)},Lr=function(t,e){return rr(t),void 0===e?t:or?ur(t,e):function(){return t.apply(e,arguments)}},Mr=X,_r=Gt,Wr=yi,zr=Ir,Xr=L([].push),Yr=function(t){var e=1==t,n=2==t,i=3==t,r=4==t,o=6==t,u=7==t,f=5==t||o;return function(a,c,s,l){for(var d,h,p=_r(a),y=Mr(p),b=Lr(c,s),g=Wr(y),v=0,m=l||zr,x=e?m(a,g):n||u?m(a,0):void 0;g>v;v++)if((f||v in y)&&(h=b(d=y[v],v,p),t))if(e)x[v]=h;else if(h)switch(t){case 3:return!0;case 5:return d;case 6:return v;case 2:Xr(x,d)}else switch(t){case 4:return!1;case 7:Xr(x,d)}return o?-1:i||r?r:x}},qr={forEach:Yr(0),map:Yr(1),filter:Yr(2),some:Yr(3),every:Yr(4),find:Yr(5),findIndex:Yr(6),filterReject:Yr(7)},Gr={},Vr=ji,Ur=Ri,Kr=Object.keys||function(t){return Vr(t,Ur)},Qr=b,Zr=Le,Jr=Ie,to=ze,eo=Q,no=Kr;Gr.f=Qr&&!Zr?Object.defineProperties:function(t,e){to(t);for(var n,i=eo(e),r=no(e),o=r.length,u=0;o>u;)Jr.f(t,n=r[u++],i[n]);return t};var io,ro=at("document","documentElement"),oo=ze,uo=Gr,fo=Ri,ao=jn,co=ro,so=je,lo=Sn("IE_PROTO"),ho=function(){},po=function(t){return"<script>"+t+"</"+"script>"},yo=function(t){t.write(po("")),t.close();var e=t.parentWindow.Object;return t=null,e},bo=function(){try{io=new ActiveXObject("htmlfile")}catch(t){}var t,e;bo="undefined"!=typeof document?document.domain&&io?yo(io):((e=so("iframe")).style.display="none",co.appendChild(e),e.src=String("javascript:"),(t=e.contentWindow.document).open(),t.write(po("document.F=Object")),t.close(),t.F):yo(io);for(var n=fo.length;n--;)delete bo.prototype[fo[n]];return bo()};ao[lo]=!0;var go=de,vo=Object.create||function(t,e){var n;return null!==t?(ho.prototype=oo(t),n=new ho,ho.prototype=null,n[lo]=t):n=bo(),void 0===e?n:uo.f(n,e)},mo=Ie.f,xo=go("unscopables"),$o=Array.prototype;null==$o[xo]&&mo($o,xo,{configurable:!0,value:vo(null)});var wo=ir,Co=qr.find,Oo=function(t){$o[xo][t]=!0},So="find",jo=!0;So in[]&&Array(1).find((function(){jo=!1})),wo({target:"Array",proto:!0,forced:jo},{find:function(t){return Co(this,t,arguments.length>1?arguments[1]:void 0)}}),Oo(So);var Ro=gr,Bo=sr?{}.toString:function(){return"[object "+Ro(this)+"]"};sr||ii(Object.prototype,"toString",Bo,{unsafe:!0});var To=TypeError,Fo=we,ko=Ie,Po=R,Eo=y,Ao=bt,No=de("species"),Ho=ir,Do=y,Io=ar,Lo=rt,Mo=Gt,_o=yi,Wo=function(t){if(t>9007199254740991)throw To("Maximum allowed index exceeded");return t},zo=function(t,e,n){var i=Fo(e);i in t?ko.f(t,i,Po(0,n)):t[i]=n},Xo=Ir,Yo=function(t){return Ao>=51||!Eo((function(){var e=[];return(e.constructor={})[No]=function(){return{foo:1}},1!==e[t](Boolean).foo}))},qo=bt,Go=de("isConcatSpreadable"),Vo=qo>=51||!Do((function(){var t=[];return t[Go]=!1,t.concat()[0]!==t})),Uo=Yo("concat"),Ko=function(t){if(!Lo(t))return!1;var e=t[Go];return void 0!==e?!!e:Io(t)};Ho({target:"Array",proto:!0,arity:1,forced:!Vo||!Uo},{concat:function(t){var e,n,i,r,o,u=Mo(this),f=Xo(u,0),a=0;for(e=-1,i=arguments.length;e<i;e++)if(Ko(o=-1===e?u:arguments[e]))for(r=_o(o),Wo(a+r),n=0;n<r;n++,a++)n in o&&zo(f,a,o[n]);else Wo(a+1),zo(f,a++,o);return f.length=a,f}});var Qo=ir,Zo=ar,Jo=L([].reverse),tu=[1,2];Qo({target:"Array",proto:!0,forced:String(tu)===String(tu.reverse())},{reverse:function(){return Zo(this)&&(this.length=this.length),Jo(this)}});var eu=gr,nu=String,iu=function(t){if("Symbol"===eu(t))throw TypeError("Cannot convert a Symbol value to a string");return nu(t)},ru="\t\n\v\f\r                 \u2028\u2029\ufeff",ou=V,uu=iu,fu=L("".replace),au="[\t\n\v\f\r                 \u2028\u2029\ufeff]",cu=RegExp("^"+au+au+"*"),su=RegExp(au+au+"*$"),lu=function(t){return function(e){var n=uu(ou(e));return 1&t&&(n=fu(n,cu,"")),2&t&&(n=fu(n,su,"")),n}},du={start:lu(1),end:lu(2),trim:lu(3)},hu=h,pu=y,yu=L,bu=iu,gu=du.trim,vu=ru,mu=hu.parseInt,xu=hu.Symbol,$u=xu&&xu.iterator,wu=/^[+-]?0x/i,Cu=yu(wu.exec),Ou=8!==mu(vu+"08")||22!==mu(vu+"0x16")||$u&&!pu((function(){mu(Object($u))}))?function(t,e){var n=gu(bu(t));return mu(n,e>>>0||(Cu(wu,n)?16:10))}:mu;ir({global:!0,forced:parseInt!=Ou},{parseInt:Ou});var Su=y,ju=ir,Ru=xi.indexOf,Bu=function(t,e){var n=[][t];return!!n&&Su((function(){n.call(null,e||function(){return 1},1)}))},Tu=L([].indexOf),Fu=!!Tu&&1/Tu([1],1,-0)<0,ku=Bu("indexOf");ju({target:"Array",proto:!0,forced:Fu||!ku},{indexOf:function(t){var e=arguments.length>1?arguments[1]:void 0;return Fu?Tu(this,t,e)||0:Ru(this,t,e)}});var Pu=n.default.fn.bootstrapTable.utils;n.default.extend(n.default.fn.bootstrapTable.defaults,{fixedColumns:!1,fixedNumber:0,fixedRightNumber:0}),n.default.BootstrapTable=function(t){!function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),Object.defineProperty(t,"prototype",{writable:!1}),e&&u(t,e)}(d,t);var e,f,c,l=a(d);function d(){return i(this,d),l.apply(this,arguments)}return e=d,f=[{key:"fixedColumnsSupported",value:function(){return this.options.fixedColumns&&!this.options.detailView&&!this.options.cardView}},{key:"initContainer",value:function(){s(o(d.prototype),"initContainer",this).call(this),this.fixedColumnsSupported()&&(this.options.fixedNumber&&(this.$tableContainer.append('<div class="fixed-columns"></div>'),this.$fixedColumns=this.$tableContainer.find(".fixed-columns")),this.options.fixedRightNumber&&(this.$tableContainer.append('<div class="fixed-columns-right"></div>'),this.$fixedColumnsRight=this.$tableContainer.find(".fixed-columns-right")))}},{key:"initBody",value:function(){for(var t,e=arguments.length,n=new Array(e),i=0;i<e;i++)n[i]=arguments[i];(t=s(o(d.prototype),"initBody",this)).call.apply(t,[this].concat(n)),this.$fixedColumns&&this.$fixedColumns.length&&this.$fixedColumns.toggle(this.fixedColumnsSupported()),this.$fixedColumnsRight&&this.$fixedColumnsRight.length&&this.$fixedColumnsRight.toggle(this.fixedColumnsSupported()),this.fixedColumnsSupported()&&(this.options.showHeader&&this.options.height||(this.initFixedColumnsBody(),this.initFixedColumnsEvents()))}},{key:"trigger",value:function(){for(var t,e=arguments.length,n=new Array(e),i=0;i<e;i++)n[i]=arguments[i];(t=s(o(d.prototype),"trigger",this)).call.apply(t,[this].concat(n)),this.fixedColumnsSupported()&&("post-header"===n[0]?this.initFixedColumnsHeader():"scroll-body"===n[0]&&(this.needFixedColumns&&this.options.fixedNumber&&this.$fixedBody.scrollTop(this.$tableBody.scrollTop()),this.needFixedColumns&&this.options.fixedRightNumber&&this.$fixedBodyRight.scrollTop(this.$tableBody.scrollTop())))}},{key:"updateSelected",value:function(){var t=this;s(o(d.prototype),"updateSelected",this).call(this),this.fixedColumnsSupported()&&this.$tableBody.find("tr").each((function(e,i){var r=n.default(i),o=r.data("index"),u=r.attr("class"),f='[name="'.concat(t.options.selectItemName,'"]'),a=r.find(f);if(void 0!==o){var c=function(e,n){var i=n.find('tr[data-index="'.concat(o,'"]'));i.attr("class",u),a.length&&i.find(f).prop("checked",a.prop("checked")),t.$selectAll.length&&e.add(n).find('[name="btSelectAll"]').prop("checked",t.$selectAll.prop("checked"))};t.$fixedBody&&t.options.fixedNumber&&c(t.$fixedHeader,t.$fixedBody),t.$fixedBodyRight&&t.options.fixedRightNumber&&c(t.$fixedHeaderRight,t.$fixedBodyRight)}}))}},{key:"hideLoading",value:function(){s(o(d.prototype),"hideLoading",this).call(this),this.needFixedColumns&&this.options.fixedNumber&&this.$fixedColumns.find(".fixed-table-loading").hide(),this.needFixedColumns&&this.options.fixedRightNumber&&this.$fixedColumnsRight.find(".fixed-table-loading").hide()}},{key:"initFixedColumnsHeader",value:function(){var t=this;this.options.height?this.needFixedColumns=this.$tableHeader.outerWidth(!0)<this.$tableHeader.find("table").outerWidth(!0):this.needFixedColumns=this.$tableBody.outerWidth(!0)<this.$tableBody.find("table").outerWidth(!0);var e=function(e,n){return e.find(".fixed-table-header").remove(),e.append(t.$tableHeader.clone(!0)),e.css({width:t.getFixedColumnsWidth(n)}),e.find(".fixed-table-header")};this.needFixedColumns&&this.options.fixedNumber?(this.$fixedHeader=e(this.$fixedColumns),this.$fixedHeader.css("margin-right","")):this.$fixedColumns&&this.$fixedColumns.html("").css("width",""),this.needFixedColumns&&this.options.fixedRightNumber?(this.$fixedHeaderRight=e(this.$fixedColumnsRight,!0),this.$fixedHeaderRight.scrollLeft(this.$fixedHeaderRight.find("table").width())):this.$fixedColumnsRight&&this.$fixedColumnsRight.html("").css("width",""),this.initFixedColumnsBody(),this.initFixedColumnsEvents()}},{key:"initFixedColumnsBody",value:function(){var t=this,e=function(e,n){e.find(".fixed-table-body").remove(),e.append(t.$tableBody.clone(!0)),e.find(".fixed-table-body table").removeAttr("id");var i=e.find(".fixed-table-body"),r=t.$tableBody.get(0),o=r.scrollWidth>r.clientWidth?Pu.getScrollBarWidth():0,u=t.$tableContainer.outerHeight(!0)-o-1;return e.css({height:u}),i.css({height:u-n.height()}),i};this.needFixedColumns&&this.options.fixedNumber&&(this.$fixedBody=e(this.$fixedColumns,this.$fixedHeader)),this.needFixedColumns&&this.options.fixedRightNumber&&(this.$fixedBodyRight=e(this.$fixedColumnsRight,this.$fixedHeaderRight),this.$fixedBodyRight.scrollLeft(this.$fixedBodyRight.find("table").width()),this.$fixedBodyRight.css("overflow-y",this.options.height?"auto":"hidden"))}},{key:"getFixedColumnsWidth",value:function(t){var e=this.getVisibleFields(),n=0,i=this.options.fixedNumber,r=0;t&&(e=e.reverse(),i=this.options.fixedRightNumber,r=parseInt(this.$tableHeader.css("margin-right"),10));for(var o=0;o<i;o++)n+=this.$header.find('th[data-field="'.concat(e[o],'"]')).outerWidth(!0);return n+r+1}},{key:"initFixedColumnsEvents",value:function(){var t=this,e=function(e,i){var r='tr[data-index="'.concat(n.default(e.currentTarget).data("index"),'"]'),o=t.$tableBody.find(r);t.$fixedBody&&(o=o.add(t.$fixedBody.find(r))),t.$fixedBodyRight&&(o=o.add(t.$fixedBodyRight.find(r))),o.css("background-color",i?n.default(e.currentTarget).css("background-color"):"")};this.$tableBody.find("tr").hover((function(t){e(t,!0)}),(function(t){e(t,!1)}));var i="undefined"!=typeof navigator&&navigator.userAgent.toLowerCase().indexOf("firefox")>-1?"DOMMouseScroll":"mousewheel";this.needFixedColumns&&this.options.fixedNumber&&(this.$fixedBody.find("tr").hover((function(t){e(t,!0)}),(function(t){e(t,!1)})),this.$fixedBody[0].addEventListener(i,(function(e){!function(e,n){var i,r,o,u,f,a=(r=0,o=0,u=0,f=0,"detail"in(i=e)&&(o=i.detail),"wheelDelta"in i&&(o=-i.wheelDelta/120),"wheelDeltaY"in i&&(o=-i.wheelDeltaY/120),"wheelDeltaX"in i&&(r=-i.wheelDeltaX/120),"axis"in i&&i.axis===i.HORIZONTAL_AXIS&&(r=o,o=0),u=10*r,f=10*o,"deltaY"in i&&(f=i.deltaY),"deltaX"in i&&(u=i.deltaX),(u||f)&&i.deltaMode&&(1===i.deltaMode?(u*=40,f*=40):(u*=800,f*=800)),u&&!r&&(r=u<1?-1:1),f&&!o&&(o=f<1?-1:1),{spinX:r,spinY:o,pixelX:u,pixelY:f}),c=Math.ceil(a.pixelY),s=t.$tableBody.scrollTop()+c;(c<0&&s>0||c>0&&s<n.scrollHeight-n.clientHeight)&&e.preventDefault(),t.$tableBody.scrollTop(s),t.$fixedBody&&t.$fixedBody.scrollTop(s),t.$fixedBodyRight&&t.$fixedBodyRight.scrollTop(s)}(e,t.$fixedBody[0])}))),this.needFixedColumns&&this.options.fixedRightNumber&&(this.$fixedBodyRight.find("tr").hover((function(t){e(t,!0)}),(function(t){e(t,!1)})),this.$fixedBodyRight.off("scroll").on("scroll",(function(){var e=t.$fixedBodyRight.scrollTop();t.$tableBody.scrollTop(e),t.$fixedBody&&t.$fixedBody.scrollTop(e)}))),this.options.filterControl&&n.default(this.$fixedColumns).off("keyup change").on("keyup change",(function(e){var i=n.default(e.target),r=i.val(),o=i.parents("th").data("field"),u=t.$header.find('th[data-field="'.concat(o,'"]'));if(i.is("input"))u.find("input").val(r);else if(i.is("select")){var f=u.find("select");f.find("option[selected]").removeAttr("selected"),f.find('option[value="'.concat(r,'"]')).attr("selected",!0)}t.triggerSearch()}))}},{key:"renderStickyHeader",value:function(){if(this.options.stickyHeader&&(this.$stickyContainer=this.$container.find(".sticky-header-container"),s(o(d.prototype),"renderStickyHeader",this).call(this),this.needFixedColumns&&this.options.fixedNumber&&this.$fixedColumns.css("z-index",101).find(".sticky-header-container").css("right","").width(this.$fixedColumns.outerWidth()),this.needFixedColumns&&this.options.fixedRightNumber)){var t=this.$fixedColumnsRight.find(".sticky-header-container");this.$fixedColumnsRight.css("z-index",101),t.css("left","").scrollLeft(t.find(".table").outerWidth()).width(this.$fixedColumnsRight.outerWidth())}}},{key:"matchPositionX",value:function(){this.options.stickyHeader&&this.$stickyContainer.eq(0).scrollLeft(this.$tableBody.scrollLeft())}}],f&&r(e.prototype,f),c&&r(e,c),Object.defineProperty(e,"prototype",{writable:!1}),d}(n.default.BootstrapTable)}));
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/cookie/bootstrap-table-cookie.js b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/cookie/bootstrap-table-cookie.js
new file mode 100644
index 0000000..2d0c852
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/cookie/bootstrap-table-cookie.js
@@ -0,0 +1,606 @@
+/**
+ * @author: Dennis Hernández
+ * @update zhixin wen <wenzhixin2010@gmail.com>
+ */
+var Utils = $.fn.bootstrapTable.utils
+var UtilsCookie = {
+  cookieIds: {
+    sortOrder: 'bs.table.sortOrder',
+    sortName: 'bs.table.sortName',
+    sortPriority: 'bs.table.sortPriority',
+    pageNumber: 'bs.table.pageNumber',
+    pageList: 'bs.table.pageList',
+    hiddenColumns: 'bs.table.hiddenColumns',
+    cardView: 'bs.table.cardView',
+    customView: 'bs.table.customView',
+    searchText: 'bs.table.searchText',
+    reorderColumns: 'bs.table.reorderColumns',
+    filterControl: 'bs.table.filterControl',
+    filterBy: 'bs.table.filterBy'
+  },
+  getCurrentHeader (that) {
+    return that.options.height ? that.$tableHeader : that.$header
+  },
+  getCurrentSearchControls (that) {
+    return that.options.height ? 'table select, table input' : 'select, input'
+  },
+  isCookieSupportedByBrowser () {
+    return navigator.cookieEnabled
+  },
+  isCookieEnabled (that, cookieName) {
+    return that.options.cookiesEnabled.includes(cookieName)
+  },
+  setCookie (that, cookieName, cookieValue) {
+    if (
+      !that.options.cookie ||
+      !UtilsCookie.isCookieEnabled(that, cookieName)
+    ) {
+      return
+    }
+
+    return that._storage.setItem(`${that.options.cookieIdTable}.${cookieName}`, cookieValue)
+  },
+  getCookie (that, cookieName) {
+    if (
+      !cookieName ||
+      !UtilsCookie.isCookieEnabled(that, cookieName)
+    ) {
+      return null
+    }
+
+    return that._storage.getItem(`${that.options.cookieIdTable}.${cookieName}`)
+  },
+  deleteCookie (that, cookieName) {
+    return that._storage.removeItem(`${that.options.cookieIdTable}.${cookieName}`)
+  },
+  calculateExpiration (cookieExpire) {
+    const time = cookieExpire.replace(/[0-9]*/, '') // s,mi,h,d,m,y
+
+    cookieExpire = cookieExpire.replace(/[A-Za-z]{1,2}/, '') // number
+
+    switch (time.toLowerCase()) {
+      case 's':
+        cookieExpire = +cookieExpire
+        break
+      case 'mi':
+        cookieExpire *= 60
+        break
+      case 'h':
+        cookieExpire = cookieExpire * 60 * 60
+        break
+      case 'd':
+        cookieExpire = cookieExpire * 24 * 60 * 60
+        break
+      case 'm':
+        cookieExpire = cookieExpire * 30 * 24 * 60 * 60
+        break
+      case 'y':
+        cookieExpire = cookieExpire * 365 * 24 * 60 * 60
+        break
+      default:
+        cookieExpire = undefined
+        break
+    }
+    if (!cookieExpire) {
+      return ''
+    }
+    const d = new Date()
+
+    d.setTime(d.getTime() + cookieExpire * 1000)
+    return d.toGMTString()
+  },
+  initCookieFilters (that) {
+    setTimeout(() => {
+      const parsedCookieFilters = JSON.parse(
+        UtilsCookie.getCookie(that, UtilsCookie.cookieIds.filterControl))
+
+      if (!that._filterControlValuesLoaded && parsedCookieFilters) {
+        const cachedFilters = {}
+        const header = UtilsCookie.getCurrentHeader(that)
+        const searchControls = UtilsCookie.getCurrentSearchControls(that)
+
+        const applyCookieFilters = (element, filteredCookies) => {
+          filteredCookies.forEach(cookie => {
+            const value = element.value.toString()
+            const text = cookie.text
+
+            if (
+              text === '' ||
+              element.type === 'radio' &&
+              value !== text
+            ) {
+              return
+            }
+
+            if (
+              element.tagName === 'INPUT' &&
+              element.type === 'radio' &&
+              value === text
+            ) {
+              element.checked = true
+              cachedFilters[cookie.field] = text
+            } else if (element.tagName === 'INPUT') {
+              element.value = text
+              cachedFilters[cookie.field] = text
+            } else if (
+              element.tagName === 'SELECT' &&
+              that.options.filterControlContainer
+            ) {
+              element.value = text
+              cachedFilters[cookie.field] = text
+            } else if (text !== '' && element.tagName === 'SELECT') {
+              cachedFilters[cookie.field] = text
+              for (const currentElement of element) {
+                if (currentElement.value === text) {
+                  currentElement.selected = true
+                  return
+                }
+              }
+              const option = document.createElement('option')
+
+              option.value = text
+              option.text = text
+              element.add(option, element[1])
+              element.selectedIndex = 1
+            }
+          })
+        }
+
+        let filterContainer = header
+
+        if (that.options.filterControlContainer) {
+          filterContainer = $(`${that.options.filterControlContainer}`)
+        }
+
+        filterContainer.find(searchControls).each(function () {
+          const field = $(this).closest('[data-field]').data('field')
+          const filteredCookies = parsedCookieFilters.filter(cookie => cookie.field === field)
+
+          applyCookieFilters(this, filteredCookies)
+        })
+
+        that.initColumnSearch(cachedFilters)
+        that._filterControlValuesLoaded = true
+        that.initServer()
+      }
+    }, 250)
+  }
+}
+
+Object.assign($.fn.bootstrapTable.defaults, {
+  cookie: false,
+  cookieExpire: '2h',
+  cookiePath: null,
+  cookieDomain: null,
+  cookieSecure: null,
+  cookieSameSite: 'Lax',
+  cookieIdTable: '',
+  cookiesEnabled: [
+    'bs.table.sortOrder', 'bs.table.sortName', 'bs.table.sortPriority',
+    'bs.table.pageNumber', 'bs.table.pageList',
+    'bs.table.hiddenColumns', 'bs.table.searchText',
+    'bs.table.filterControl', 'bs.table.filterBy',
+    'bs.table.reorderColumns', 'bs.table.cardView', 'bs.table.customView'
+  ],
+  cookieStorage: 'cookieStorage', // localStorage, sessionStorage, customStorage
+  cookieCustomStorageGet: null,
+  cookieCustomStorageSet: null,
+  cookieCustomStorageDelete: null,
+  // internal variable
+  _filterControls: [],
+  _filterControlValuesLoaded: false,
+  _storage: {
+    setItem: undefined,
+    getItem: undefined,
+    removeItem: undefined
+  }
+})
+
+$.fn.bootstrapTable.methods.push('getCookies')
+$.fn.bootstrapTable.methods.push('deleteCookie')
+
+Object.assign($.fn.bootstrapTable.utils, {
+  setCookie: UtilsCookie.setCookie,
+  getCookie: UtilsCookie.getCookie
+})
+
+$.BootstrapTable = class extends $.BootstrapTable {
+  init () {
+    if (this.options.cookie) {
+      if (
+        this.options.cookieStorage === 'cookieStorage' &&
+        !UtilsCookie.isCookieSupportedByBrowser()
+      ) {
+        throw new Error('Cookies are not enabled in this browser.')
+      }
+
+      this.configureStorage()
+
+      // FilterBy logic
+      const filterByCookieValue = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.filterBy)
+
+      if (typeof filterByCookieValue === 'boolean' && !filterByCookieValue) {
+        throw new Error('The cookie value of filterBy must be a json!')
+      }
+
+      let filterByCookie = {}
+
+      try {
+        filterByCookie = JSON.parse(filterByCookieValue)
+      } catch (e) {
+        throw new Error('Could not parse the json of the filterBy cookie!')
+      }
+      this.filterColumns = filterByCookie ? filterByCookie : {}
+
+      // FilterControl logic
+      this._filterControls = []
+      this._filterControlValuesLoaded = false
+
+      this.options.cookiesEnabled = typeof this.options.cookiesEnabled === 'string' ?
+        this.options.cookiesEnabled.replace('[', '').replace(']', '')
+          .replace(/'/g, '').replace(/ /g, '').split(',') :
+        this.options.cookiesEnabled
+
+      if (this.options.filterControl) {
+        const that = this
+
+        this.$el.on('column-search.bs.table', (e, field, text) => {
+          let isNewField = true
+
+          for (let i = 0; i < that._filterControls.length; i++) {
+            if (that._filterControls[i].field === field) {
+              that._filterControls[i].text = text
+              isNewField = false
+              break
+            }
+          }
+          if (isNewField) {
+            that._filterControls.push({
+              field,
+              text
+            })
+          }
+
+          UtilsCookie.setCookie(that, UtilsCookie.cookieIds.filterControl, JSON.stringify(that._filterControls))
+        }).on('created-controls.bs.table', UtilsCookie.initCookieFilters(that))
+      }
+    }
+    super.init()
+  }
+
+  initServer (...args) {
+    if (
+      this.options.cookie &&
+      this.options.filterControl &&
+      !this._filterControlValuesLoaded
+    ) {
+      const cookie = JSON.parse(UtilsCookie.getCookie(this, UtilsCookie.cookieIds.filterControl))
+
+      if (cookie) {
+        return
+      }
+    }
+    super.initServer(...args)
+  }
+
+  initTable (...args) {
+    super.initTable(...args)
+    this.initCookie()
+  }
+
+  onSort (...args) {
+    super.onSort(...args)
+
+    if (!this.options.cookie) {
+      return
+    }
+
+    if (this.options.sortName === undefined || this.options.sortOrder === undefined) {
+      UtilsCookie.deleteCookie(this, UtilsCookie.cookieIds.sortName)
+      UtilsCookie.deleteCookie(this, UtilsCookie.cookieIds.sortOrder)
+    } else {
+      this.options.sortPriority = null
+      UtilsCookie.deleteCookie(this, UtilsCookie.cookieIds.sortPriority)
+
+      UtilsCookie.setCookie(this, UtilsCookie.cookieIds.sortOrder, this.options.sortOrder)
+      UtilsCookie.setCookie(this, UtilsCookie.cookieIds.sortName, this.options.sortName)
+    }
+  }
+
+  onMultipleSort (...args) {
+    super.onMultipleSort(...args)
+
+    if (!this.options.cookie) {
+      return
+    }
+
+    if (this.options.sortPriority === undefined) {
+      UtilsCookie.deleteCookie(this, UtilsCookie.cookieIds.sortPriority)
+    } else {
+      this.options.sortName = undefined
+      this.options.sortOrder = undefined
+      UtilsCookie.deleteCookie(this, UtilsCookie.cookieIds.sortName)
+      UtilsCookie.deleteCookie(this, UtilsCookie.cookieIds.sortOrder)
+
+      UtilsCookie.setCookie(this, UtilsCookie.cookieIds.sortPriority, JSON.stringify(this.options.sortPriority))
+    }
+  }
+
+  onPageNumber (...args) {
+    super.onPageNumber(...args)
+    if (!this.options.cookie) {
+      return
+    }
+    UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, this.options.pageNumber)
+  }
+
+  onPageListChange (...args) {
+    super.onPageListChange(...args)
+    if (!this.options.cookie) {
+      return
+    }
+    UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageList,
+      this.options.pageSize === this.options.formatAllRows() ? 'all' : this.options.pageSize)
+    UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, this.options.pageNumber)
+  }
+
+  onPagePre (...args) {
+    super.onPagePre(...args)
+    if (!this.options.cookie) {
+      return
+    }
+    UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, this.options.pageNumber)
+  }
+
+  onPageNext (...args) {
+    super.onPageNext(...args)
+    if (!this.options.cookie) {
+      return
+    }
+    UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, this.options.pageNumber)
+  }
+
+  _toggleColumn (...args) {
+    super._toggleColumn(...args)
+    if (!this.options.cookie) {
+      return
+    }
+    UtilsCookie.setCookie(this, UtilsCookie.cookieIds.hiddenColumns, JSON.stringify(this.getHiddenColumns().map(column => column.field)))
+  }
+
+  _toggleAllColumns (...args) {
+    super._toggleAllColumns(...args)
+    if (!this.options.cookie) {
+      return
+    }
+    UtilsCookie.setCookie(this, UtilsCookie.cookieIds.hiddenColumns, JSON.stringify(this.getHiddenColumns().map(column => column.field)))
+  }
+
+  toggleView () {
+    super.toggleView()
+    UtilsCookie.setCookie(this, UtilsCookie.cookieIds.cardView, this.options.cardView)
+  }
+
+  toggleCustomView () {
+    super.toggleCustomView()
+    UtilsCookie.setCookie(this, UtilsCookie.cookieIds.customView, this.customViewDefaultView)
+  }
+
+  selectPage (page) {
+    super.selectPage(page)
+    if (!this.options.cookie) {
+      return
+    }
+    UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, page)
+  }
+
+  onSearch (event) {
+    super.onSearch(event, arguments.length > 1 ? arguments[1] : true)
+    if (!this.options.cookie) {
+      return
+    }
+    if (this.options.search) {
+      UtilsCookie.setCookie(this, UtilsCookie.cookieIds.searchText, this.searchText)
+    }
+    UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, this.options.pageNumber)
+  }
+
+  initHeader (...args) {
+    if (this.options.reorderableColumns && this.options.cookie) {
+      this.columnsSortOrder = JSON.parse(UtilsCookie.getCookie(this, UtilsCookie.cookieIds.reorderColumns))
+    }
+    super.initHeader(...args)
+  }
+
+  persistReorderColumnsState (that) {
+    UtilsCookie.setCookie(that, UtilsCookie.cookieIds.reorderColumns, JSON.stringify(that.columnsSortOrder))
+  }
+
+  filterBy (...args) {
+    super.filterBy(...args)
+    if (!this.options.cookie) {
+      return
+    }
+    UtilsCookie.setCookie(this, UtilsCookie.cookieIds.filterBy, JSON.stringify(this.filterColumns))
+  }
+
+  initCookie () {
+    if (!this.options.cookie) {
+      return
+    }
+
+    if (this.options.cookieIdTable === '' || this.options.cookieExpire === '') {
+      console.error('Configuration error. Please review the cookieIdTable and the cookieExpire property. If the properties are correct, then this browser does not support cookies.')
+      this.options.cookie = false // Make sure that the cookie extension is disabled
+      return
+    }
+
+    const sortOrderCookie = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.sortOrder)
+    const sortOrderNameCookie = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.sortName)
+    let sortPriorityCookie = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.sortPriority)
+    const pageNumberCookie = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.pageNumber)
+    const pageListCookie = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.pageList)
+    const searchTextCookie = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.searchText)
+    const cardViewCookie = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.cardView)
+    const customViewCookie = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.customView)
+    const hiddenColumnsCookieValue = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.hiddenColumns)
+
+    let hiddenColumnsCookie = {}
+
+    try {
+      hiddenColumnsCookie = JSON.parse(hiddenColumnsCookieValue)
+    } catch (e) {
+      throw new Error('Could not parse the json of the hidden columns cookie!', hiddenColumnsCookieValue)
+    }
+
+    try {
+      sortPriorityCookie = JSON.parse(sortPriorityCookie)
+    } catch (e) {
+      throw new Error('Could not parse the json of the sortPriority cookie!', sortPriorityCookie)
+    }
+
+    if (!sortPriorityCookie) {
+      // sortOrder
+      this.options.sortOrder = sortOrderCookie ? sortOrderCookie : this.options.sortOrder
+      // sortName
+      this.options.sortName = sortOrderNameCookie ? sortOrderNameCookie : this.options.sortName
+    } else {
+      this.options.sortOrder = undefined
+      this.options.sortName = undefined
+    }
+
+    // sortPriority
+    this.options.sortPriority = sortPriorityCookie ? sortPriorityCookie : this.options.sortPriority
+
+    if (this.options.sortOrder || this.options.sortName) {
+      // sortPriority
+      this.options.sortPriority = null
+    }
+
+    // pageNumber
+    this.options.pageNumber = pageNumberCookie ? +pageNumberCookie : this.options.pageNumber
+    // pageSize
+    this.options.pageSize = pageListCookie ? pageListCookie === 'all' ?
+      this.options.formatAllRows() : +pageListCookie : this.options.pageSize
+    // searchText
+    if (UtilsCookie.isCookieEnabled(this, UtilsCookie.cookieIds.searchText) && this.options.searchText === '') {
+      this.options.searchText = searchTextCookie ? searchTextCookie : ''
+    }
+    // cardView
+    if (cardViewCookie !== null) {
+      this.options.cardView = cardViewCookie === 'true' ? cardViewCookie : false
+    }
+    this.customViewDefaultView = customViewCookie === 'true'
+
+    if (hiddenColumnsCookie) {
+      for (const column of this.columns) {
+        if (!column.switchable) {
+          continue
+        }
+
+        column.visible = this.isSelectionColumn(column) ||
+          !hiddenColumnsCookie.includes(column.field)
+      }
+    }
+  }
+
+  getCookies () {
+    const bootstrapTable = this
+    const cookies = {}
+
+    for (const [key, value] of Object.entries(UtilsCookie.cookieIds)) {
+      cookies[key] = UtilsCookie.getCookie(bootstrapTable, value)
+      if (key === 'columns' || key === 'hiddenColumns' || key === 'sortPriority') {
+        cookies[key] = JSON.parse(cookies[key])
+      }
+    }
+    return cookies
+  }
+
+  deleteCookie (cookieName) {
+    if (!cookieName) {
+      return
+    }
+
+    UtilsCookie.deleteCookie(this, UtilsCookie.cookieIds[cookieName])
+  }
+
+  configureStorage () {
+    const that = this
+
+    this._storage = {}
+    switch (this.options.cookieStorage) {
+      case 'cookieStorage':
+        this._storage.setItem = function (cookieName, cookieValue) {
+          document.cookie = [
+            cookieName, '=', encodeURIComponent(cookieValue),
+            `; expires=${UtilsCookie.calculateExpiration(that.options.cookieExpire)}`,
+            that.options.cookiePath ? `; path=${that.options.cookiePath}` : '',
+            that.options.cookieDomain ? `; domain=${that.options.cookieDomain}` : '',
+            that.options.cookieSecure ? '; secure' : '',
+            `;SameSite=${that.options.cookieSameSite}`
+          ].join('')
+        }
+        this._storage.getItem = function (cookieName) {
+          const value = `; ${document.cookie}`
+          const parts = value.split(`; ${cookieName}=`)
+
+          return parts.length === 2 ? decodeURIComponent(parts.pop().split(';').shift()) : null
+        }
+        this._storage.removeItem = function (cookieName) {
+          document.cookie = [
+            encodeURIComponent(cookieName), '=',
+            '; expires=Thu, 01 Jan 1970 00:00:00 GMT',
+            that.options.cookiePath ? `; path=${that.options.cookiePath}` : '',
+            that.options.cookieDomain ? `; domain=${that.options.cookieDomain}` : '',
+            `;SameSite=${that.options.cookieSameSite}`
+          ].join('')
+        }
+        break
+      case 'localStorage':
+        this._storage.setItem = function (cookieName, cookieValue) {
+          localStorage.setItem(cookieName, cookieValue)
+        }
+        this._storage.getItem = function (cookieName) {
+          return localStorage.getItem(cookieName)
+        }
+        this._storage.removeItem = function (cookieName) {
+          localStorage.removeItem(cookieName)
+        }
+        break
+      case 'sessionStorage':
+        this._storage.setItem = function (cookieName, cookieValue) {
+          sessionStorage.setItem(cookieName, cookieValue)
+        }
+        this._storage.getItem = function (cookieName) {
+          return sessionStorage.getItem(cookieName)
+        }
+        this._storage.removeItem = function (cookieName) {
+          sessionStorage.removeItem(cookieName)
+        }
+        break
+      case 'customStorage':
+        if (
+          !this.options.cookieCustomStorageSet ||
+          !this.options.cookieCustomStorageGet ||
+          !this.options.cookieCustomStorageDelete
+        ) {
+          throw new Error('The following options must be set while using the customStorage: cookieCustomStorageSet, cookieCustomStorageGet and cookieCustomStorageDelete')
+        }
+
+        this._storage.setItem = function (cookieName, cookieValue) {
+          Utils.calculateObjectValue(that.options, that.options.cookieCustomStorageSet, [cookieName, cookieValue], '')
+        }
+        this._storage.getItem = function (cookieName) {
+          return Utils.calculateObjectValue(that.options, that.options.cookieCustomStorageGet, [cookieName], '')
+        }
+        this._storage.removeItem = function (cookieName) {
+          Utils.calculateObjectValue(that.options, that.options.cookieCustomStorageDelete, [cookieName], '')
+        }
+
+        break
+      default:
+        throw new Error('Storage method not supported.')
+    }
+  }
+}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/custom-view/bootstrap-table-custom-view.js b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/custom-view/bootstrap-table-custom-view.js
new file mode 100644
index 0000000..d97de54
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/custom-view/bootstrap-table-custom-view.js
@@ -0,0 +1,135 @@
+/**
+ * @author: Dustin Utecht
+ * @github: https://github.com/UtechtDustin
+ */
+
+var Utils = $.fn.bootstrapTable.utils
+
+Object.assign($.fn.bootstrapTable.defaults, {
+  customView: false,
+  showCustomView: false,
+  customViewDefaultView: false
+})
+
+Object.assign($.fn.bootstrapTable.defaults.icons, {
+  customViewOn: {
+    bootstrap3: 'glyphicon glyphicon-list',
+    bootstrap5: 'bi-list',
+    bootstrap4: 'fa fa-list',
+    semantic: 'fa fa-list',
+    foundation: 'fa fa-list',
+    bulma: 'fa fa-list',
+    materialize: 'list'
+  }[$.fn.bootstrapTable.theme] || 'fa-list',
+  customViewOff: {
+    bootstrap3: 'glyphicon glyphicon-eye-open',
+    bootstrap5: 'bi-grid',
+    bootstrap4: 'fa fa-th',
+    semantic: 'fa fa-th',
+    foundation: 'fa fa-th',
+    bulma: 'fa fa-th',
+    materialize: 'grid_on'
+  }[$.fn.bootstrapTable.theme] || 'fa-th'
+})
+
+Object.assign($.fn.bootstrapTable.defaults, {
+  onCustomViewPostBody () {
+    return false
+  },
+  onCustomViewPreBody () {
+    return false
+  },
+  onToggleCustomView () {
+    return false
+  }
+})
+
+Object.assign($.fn.bootstrapTable.locales, {
+  formatToggleCustomViewOn () {
+    return 'Show custom view'
+  },
+  formatToggleCustomViewOff () {
+    return 'Hide custom view'
+  }
+})
+Object.assign($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales)
+
+$.fn.bootstrapTable.methods.push('toggleCustomView')
+
+Object.assign($.fn.bootstrapTable.events, {
+  'custom-view-post-body.bs.table': 'onCustomViewPostBody',
+  'custom-view-pre-body.bs.table': 'onCustomViewPreBody',
+  'toggle-custom-view.bs.table': 'onToggleCustomView'
+})
+
+$.BootstrapTable = class extends $.BootstrapTable {
+
+  init () {
+    this.customViewDefaultView = this.options.customViewDefaultView
+
+    super.init()
+  }
+
+  initToolbar (...args) {
+    if (this.options.customView && this.options.showCustomView) {
+      this.buttons = Object.assign(this.buttons, {
+        customView: {
+          text: this.options.customViewDefaultView ? this.options.formatToggleCustomViewOff() : this.options.formatToggleCustomViewOn(),
+          icon: this.options.customViewDefaultView ? this.options.icons.customViewOn : this.options.icons.customViewOff,
+          event: this.toggleCustomView,
+          attributes: {
+            'aria-label': this.options.customViewDefaultView ? this.options.formatToggleCustomViewOff() : this.options.formatToggleCustomViewOn(),
+            title: this.options.customViewDefaultView ? this.options.formatToggleCustomViewOff() : this.options.formatToggleCustomViewOn()
+          }
+        }
+      })
+    }
+
+    super.initToolbar(...args)
+  }
+
+  initBody () {
+    super.initBody()
+
+    if (!this.options.customView) {
+      return
+    }
+
+    const $table = this.$el
+    const $customViewContainer = this.$container.find('.fixed-table-custom-view')
+
+    $table.hide()
+    $customViewContainer.hide()
+    if (!this.options.customView || !this.customViewDefaultView) {
+      $table.show()
+      return
+    }
+
+    const data = this.getData().slice(this.pageFrom - 1, this.pageTo)
+    const value = Utils.calculateObjectValue(this, this.options.customView, [data], '')
+
+    this.trigger('custom-view-pre-body', data, value)
+    if ($customViewContainer.length === 1) {
+      $customViewContainer.show().html(value)
+    } else {
+      this.$tableBody.after(`<div class="fixed-table-custom-view">${value}</div>`)
+    }
+
+    this.trigger('custom-view-post-body', data, value)
+  }
+
+  toggleCustomView () {
+    this.customViewDefaultView = !this.customViewDefaultView
+
+    const icon = this.options.showButtonIcons ? this.customViewDefaultView ? this.options.icons.customViewOn : this.options.icons.customViewOff : ''
+    const text = this.options.showButtonText ? this.customViewDefaultView ? this.options.formatToggleCustomViewOff() : this.options.formatToggleCustomViewOn() : ''
+
+    this.$toolbar.find('button[name="customView"]')
+      .html(`${Utils.sprintf(this.constants.html.icon, this.options.iconsPrefix, icon)} ${text}`)
+      .attr('aria-label', text)
+      .attr('title', text)
+
+    this.initBody()
+    this.trigger('toggle-custom-view', this.customViewDefaultView)
+  }
+}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/editable/bootstrap-editable.css b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/editable/bootstrap-editable.css
new file mode 100644
index 0000000..1e159c6
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/editable/bootstrap-editable.css
@@ -0,0 +1,674 @@
+/*! X-editable - v1.5.3 
+* In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery
+* http://github.com/vitalets/x-editable
+* Copyright (c) 2019 Vitaliy Potapov; Licensed MIT */
+.editableform {
+    margin-bottom: 0; /* overwrites bootstrap margin */
+}
+
+.editableform .control-group {
+    margin-bottom: 0; /* overwrites bootstrap margin */
+    white-space: nowrap; /* prevent wrapping buttons on new line */
+    line-height: 20px; /* overwriting bootstrap line-height. See #133 */
+}
+
+/*
+    BS3 fix: stop css from breaking when the form is inside a popup and inside a form with the class .form-horizontal
+    See: https://github.com/vitalets/x-editable/issues/682
+*/
+.form-horizontal .editable-popup .editableform .form-group {
+    margin-left:0;
+    margin-right:0;
+}
+
+
+/* 
+  BS3 width:1005 for inputs breaks editable form in popup 
+  See: https://github.com/vitalets/x-editable/issues/393
+*/
+.editableform .form-control {
+    width: auto;
+}
+
+.editable-buttons {
+   display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */
+   vertical-align: top;
+   margin-left: 7px;
+   /* inline-block emulation for IE7*/
+   zoom: 1; 
+   *display: inline;
+}
+
+.editable-buttons.editable-buttons-bottom {
+   display: block; 
+   margin-top: 7px;
+   margin-left: 0;
+}
+
+.editable-input {
+    vertical-align: top; 
+    display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */
+    width: auto; /* bootstrap-responsive has width: 100% that breakes layout */
+    white-space: normal; /* reset white-space decalred in parent*/
+   /* display-inline emulation for IE7*/
+   zoom: 1; 
+   *display: inline;   
+}
+
+.editable-buttons .editable-cancel {
+   margin-left: 7px; 
+}
+
+/*for jquery-ui buttons need set height to look more pretty*/
+.editable-buttons button.ui-button-icon-only {
+   height: 24px; 
+   width: 30px;
+}
+
+.editableform-loading {
+    background: url('loading.gif') center center no-repeat;  
+    height: 25px;
+    width: auto; 
+    min-width: 25px; 
+}
+
+.editable-inline .editableform-loading {
+    background-position: left 5px;      
+}
+
+ .editable-error-block {
+    max-width: 300px;
+    margin: 5px 0 0 0;
+    width: auto;
+    white-space: normal;
+}
+
+/*add padding for jquery ui*/
+.editable-error-block.ui-state-error {
+    padding: 3px;  
+}  
+
+.editable-error {
+   color: red;  
+}
+
+/* ---- For specific types ---- */
+
+.editableform .editable-date {
+    padding: 0; 
+    margin: 0;
+    float: left;
+}
+
+/* move datepicker icon to center of add-on button. See https://github.com/vitalets/x-editable/issues/183 */
+.editable-inline .add-on .icon-th {
+   margin-top: 3px;
+   margin-left: 1px; 
+}
+
+
+/* checklist vertical alignment */
+.editable-checklist label input[type="checkbox"], 
+.editable-checklist label span {
+    vertical-align: middle;
+    margin: 0;
+}
+
+.editable-checklist label {
+    white-space: nowrap; 
+}
+
+/* set exact width of textarea to fit buttons toolbar */
+.editable-wysihtml5 {
+    width: 566px; 
+    height: 250px; 
+}
+
+/* clear button shown as link in date inputs */
+.editable-clear {
+   clear: both;
+   font-size: 0.9em;
+   text-decoration: none;
+   text-align: right;
+}
+
+/* IOS-style clear button for text inputs */
+.editable-clear-x {
+   background: url('clear.png') center center no-repeat;
+   display: block;
+   width: 13px;    
+   height: 13px;
+   position: absolute;
+   opacity: 0.6;
+   z-index: 100;
+   
+   top: 50%;
+   right: 6px;
+   margin-top: -6px;
+   
+}
+
+.editable-clear-x:hover {
+   opacity: 1;
+}
+
+.editable-pre-wrapped {
+   white-space: pre-wrap;
+}
+
+.editable-container.editable-popup {
+    max-width: none !important; /* without this rule poshytip/tooltip does not stretch */
+}  
+
+.editable-container.popover {
+    width: auto; /* without this rule popover does not stretch */
+}
+
+.editable-container.editable-inline {
+    display: inline-block; 
+    vertical-align: middle;
+    width: auto;
+    /* inline-block emulation for IE7*/
+    zoom: 1; 
+    *display: inline;    
+}
+
+.editable-container.ui-widget {
+   font-size: inherit;  /* jqueryui widget font 1.1em too big, overwrite it */
+   z-index: 9990; /* should be less than select2 dropdown z-index to close dropdown first when click */
+}
+.editable-click, 
+a.editable-click, 
+a.editable-click:hover {
+    text-decoration: none;
+    border-bottom: dashed 1px #0088cc;
+}
+
+.editable-click.editable-disabled, 
+a.editable-click.editable-disabled, 
+a.editable-click.editable-disabled:hover {
+   color: #585858;  
+   cursor: default;
+   border-bottom: none;
+}
+
+.editable-empty, .editable-empty:hover, .editable-empty:focus{
+  font-style: italic; 
+  color: #DD1144;  
+  /* border-bottom: none; */
+  text-decoration: none;
+}
+
+.editable-unsaved {
+  font-weight: bold; 
+}
+
+.editable-unsaved:after {
+/*    content: '*'*/
+}
+
+.editable-bg-transition {
+  -webkit-transition: background-color 1400ms ease-out;
+  -moz-transition: background-color 1400ms ease-out;
+  -o-transition: background-color 1400ms ease-out;
+  -ms-transition: background-color 1400ms ease-out;
+  transition: background-color 1400ms ease-out;  
+}
+
+/*see https://github.com/vitalets/x-editable/issues/139 */
+.form-horizontal .editable
+{ 
+    padding-top: 5px;
+    display:inline-block;
+}
+
+
+/*!
+ * Datepicker for Bootstrap
+ *
+ * Copyright 2012 Stefan Petre
+ * Improvements by Andrew Rowls
+ * Licensed under the Apache License v2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+.datepicker {
+  padding: 4px;
+  -webkit-border-radius: 4px;
+  -moz-border-radius: 4px;
+  border-radius: 4px;
+  direction: ltr;
+  /*.dow {
+		border-top: 1px solid #ddd !important;
+	}*/
+
+}
+.datepicker-inline {
+  width: 220px;
+}
+.datepicker.datepicker-rtl {
+  direction: rtl;
+}
+.datepicker.datepicker-rtl table tr td span {
+  float: right;
+}
+.datepicker-dropdown {
+  top: 0;
+  left: 0;
+}
+.datepicker-dropdown:before {
+  content: '';
+  display: inline-block;
+  border-left: 7px solid transparent;
+  border-right: 7px solid transparent;
+  border-bottom: 7px solid #ccc;
+  border-bottom-color: rgba(0, 0, 0, 0.2);
+  position: absolute;
+  top: -7px;
+  left: 6px;
+}
+.datepicker-dropdown:after {
+  content: '';
+  display: inline-block;
+  border-left: 6px solid transparent;
+  border-right: 6px solid transparent;
+  border-bottom: 6px solid #ffffff;
+  position: absolute;
+  top: -6px;
+  left: 7px;
+}
+.datepicker > div {
+  display: none;
+}
+.datepicker.days div.datepicker-days {
+  display: block;
+}
+.datepicker.months div.datepicker-months {
+  display: block;
+}
+.datepicker.years div.datepicker-years {
+  display: block;
+}
+.datepicker table {
+  margin: 0;
+}
+.datepicker td,
+.datepicker th {
+  text-align: center;
+  width: 20px;
+  height: 20px;
+  -webkit-border-radius: 4px;
+  -moz-border-radius: 4px;
+  border-radius: 4px;
+  border: none;
+}
+.table-striped .datepicker table tr td,
+.table-striped .datepicker table tr th {
+  background-color: transparent;
+}
+.datepicker table tr td.day:hover {
+  background: #eeeeee;
+  cursor: pointer;
+}
+.datepicker table tr td.old,
+.datepicker table tr td.new {
+  color: #999999;
+}
+.datepicker table tr td.disabled,
+.datepicker table tr td.disabled:hover {
+  background: none;
+  color: #999999;
+  cursor: default;
+}
+.datepicker table tr td.today,
+.datepicker table tr td.today:hover,
+.datepicker table tr td.today.disabled,
+.datepicker table tr td.today.disabled:hover {
+  background-color: #fde19a;
+  background-image: -moz-linear-gradient(top, #fdd49a, #fdf59a);
+  background-image: -ms-linear-gradient(top, #fdd49a, #fdf59a);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fdd49a), to(#fdf59a));
+  background-image: -webkit-linear-gradient(top, #fdd49a, #fdf59a);
+  background-image: -o-linear-gradient(top, #fdd49a, #fdf59a);
+  background-image: linear-gradient(top, #fdd49a, #fdf59a);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a', endColorstr='#fdf59a', GradientType=0);
+  border-color: #fdf59a #fdf59a #fbed50;
+  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+  color: #000;
+}
+.datepicker table tr td.today:hover,
+.datepicker table tr td.today:hover:hover,
+.datepicker table tr td.today.disabled:hover,
+.datepicker table tr td.today.disabled:hover:hover,
+.datepicker table tr td.today:active,
+.datepicker table tr td.today:hover:active,
+.datepicker table tr td.today.disabled:active,
+.datepicker table tr td.today.disabled:hover:active,
+.datepicker table tr td.today.active,
+.datepicker table tr td.today:hover.active,
+.datepicker table tr td.today.disabled.active,
+.datepicker table tr td.today.disabled:hover.active,
+.datepicker table tr td.today.disabled,
+.datepicker table tr td.today:hover.disabled,
+.datepicker table tr td.today.disabled.disabled,
+.datepicker table tr td.today.disabled:hover.disabled,
+.datepicker table tr td.today[disabled],
+.datepicker table tr td.today:hover[disabled],
+.datepicker table tr td.today.disabled[disabled],
+.datepicker table tr td.today.disabled:hover[disabled] {
+  background-color: #fdf59a;
+}
+.datepicker table tr td.today:active,
+.datepicker table tr td.today:hover:active,
+.datepicker table tr td.today.disabled:active,
+.datepicker table tr td.today.disabled:hover:active,
+.datepicker table tr td.today.active,
+.datepicker table tr td.today:hover.active,
+.datepicker table tr td.today.disabled.active,
+.datepicker table tr td.today.disabled:hover.active {
+  background-color: #fbf069 \9;
+}
+.datepicker table tr td.today:hover:hover {
+  color: #000;
+}
+.datepicker table tr td.today.active:hover {
+  color: #fff;
+}
+.datepicker table tr td.range,
+.datepicker table tr td.range:hover,
+.datepicker table tr td.range.disabled,
+.datepicker table tr td.range.disabled:hover {
+  background: #eeeeee;
+  -webkit-border-radius: 0;
+  -moz-border-radius: 0;
+  border-radius: 0;
+}
+.datepicker table tr td.range.today,
+.datepicker table tr td.range.today:hover,
+.datepicker table tr td.range.today.disabled,
+.datepicker table tr td.range.today.disabled:hover {
+  background-color: #f3d17a;
+  background-image: -moz-linear-gradient(top, #f3c17a, #f3e97a);
+  background-image: -ms-linear-gradient(top, #f3c17a, #f3e97a);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f3c17a), to(#f3e97a));
+  background-image: -webkit-linear-gradient(top, #f3c17a, #f3e97a);
+  background-image: -o-linear-gradient(top, #f3c17a, #f3e97a);
+  background-image: linear-gradient(top, #f3c17a, #f3e97a);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f3c17a', endColorstr='#f3e97a', GradientType=0);
+  border-color: #f3e97a #f3e97a #edde34;
+  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+  -webkit-border-radius: 0;
+  -moz-border-radius: 0;
+  border-radius: 0;
+}
+.datepicker table tr td.range.today:hover,
+.datepicker table tr td.range.today:hover:hover,
+.datepicker table tr td.range.today.disabled:hover,
+.datepicker table tr td.range.today.disabled:hover:hover,
+.datepicker table tr td.range.today:active,
+.datepicker table tr td.range.today:hover:active,
+.datepicker table tr td.range.today.disabled:active,
+.datepicker table tr td.range.today.disabled:hover:active,
+.datepicker table tr td.range.today.active,
+.datepicker table tr td.range.today:hover.active,
+.datepicker table tr td.range.today.disabled.active,
+.datepicker table tr td.range.today.disabled:hover.active,
+.datepicker table tr td.range.today.disabled,
+.datepicker table tr td.range.today:hover.disabled,
+.datepicker table tr td.range.today.disabled.disabled,
+.datepicker table tr td.range.today.disabled:hover.disabled,
+.datepicker table tr td.range.today[disabled],
+.datepicker table tr td.range.today:hover[disabled],
+.datepicker table tr td.range.today.disabled[disabled],
+.datepicker table tr td.range.today.disabled:hover[disabled] {
+  background-color: #f3e97a;
+}
+.datepicker table tr td.range.today:active,
+.datepicker table tr td.range.today:hover:active,
+.datepicker table tr td.range.today.disabled:active,
+.datepicker table tr td.range.today.disabled:hover:active,
+.datepicker table tr td.range.today.active,
+.datepicker table tr td.range.today:hover.active,
+.datepicker table tr td.range.today.disabled.active,
+.datepicker table tr td.range.today.disabled:hover.active {
+  background-color: #efe24b \9;
+}
+.datepicker table tr td.selected,
+.datepicker table tr td.selected:hover,
+.datepicker table tr td.selected.disabled,
+.datepicker table tr td.selected.disabled:hover {
+  background-color: #9e9e9e;
+  background-image: -moz-linear-gradient(top, #b3b3b3, #808080);
+  background-image: -ms-linear-gradient(top, #b3b3b3, #808080);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#b3b3b3), to(#808080));
+  background-image: -webkit-linear-gradient(top, #b3b3b3, #808080);
+  background-image: -o-linear-gradient(top, #b3b3b3, #808080);
+  background-image: linear-gradient(top, #b3b3b3, #808080);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#b3b3b3', endColorstr='#808080', GradientType=0);
+  border-color: #808080 #808080 #595959;
+  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+  color: #fff;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+}
+.datepicker table tr td.selected:hover,
+.datepicker table tr td.selected:hover:hover,
+.datepicker table tr td.selected.disabled:hover,
+.datepicker table tr td.selected.disabled:hover:hover,
+.datepicker table tr td.selected:active,
+.datepicker table tr td.selected:hover:active,
+.datepicker table tr td.selected.disabled:active,
+.datepicker table tr td.selected.disabled:hover:active,
+.datepicker table tr td.selected.active,
+.datepicker table tr td.selected:hover.active,
+.datepicker table tr td.selected.disabled.active,
+.datepicker table tr td.selected.disabled:hover.active,
+.datepicker table tr td.selected.disabled,
+.datepicker table tr td.selected:hover.disabled,
+.datepicker table tr td.selected.disabled.disabled,
+.datepicker table tr td.selected.disabled:hover.disabled,
+.datepicker table tr td.selected[disabled],
+.datepicker table tr td.selected:hover[disabled],
+.datepicker table tr td.selected.disabled[disabled],
+.datepicker table tr td.selected.disabled:hover[disabled] {
+  background-color: #808080;
+}
+.datepicker table tr td.selected:active,
+.datepicker table tr td.selected:hover:active,
+.datepicker table tr td.selected.disabled:active,
+.datepicker table tr td.selected.disabled:hover:active,
+.datepicker table tr td.selected.active,
+.datepicker table tr td.selected:hover.active,
+.datepicker table tr td.selected.disabled.active,
+.datepicker table tr td.selected.disabled:hover.active {
+  background-color: #666666 \9;
+}
+.datepicker table tr td.active,
+.datepicker table tr td.active:hover,
+.datepicker table tr td.active.disabled,
+.datepicker table tr td.active.disabled:hover {
+  background-color: #006dcc;
+  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
+  background-image: -ms-linear-gradient(top, #0088cc, #0044cc);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
+  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
+  background-image: -o-linear-gradient(top, #0088cc, #0044cc);
+  background-image: linear-gradient(top, #0088cc, #0044cc);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);
+  border-color: #0044cc #0044cc #002a80;
+  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+  color: #fff;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+}
+.datepicker table tr td.active:hover,
+.datepicker table tr td.active:hover:hover,
+.datepicker table tr td.active.disabled:hover,
+.datepicker table tr td.active.disabled:hover:hover,
+.datepicker table tr td.active:active,
+.datepicker table tr td.active:hover:active,
+.datepicker table tr td.active.disabled:active,
+.datepicker table tr td.active.disabled:hover:active,
+.datepicker table tr td.active.active,
+.datepicker table tr td.active:hover.active,
+.datepicker table tr td.active.disabled.active,
+.datepicker table tr td.active.disabled:hover.active,
+.datepicker table tr td.active.disabled,
+.datepicker table tr td.active:hover.disabled,
+.datepicker table tr td.active.disabled.disabled,
+.datepicker table tr td.active.disabled:hover.disabled,
+.datepicker table tr td.active[disabled],
+.datepicker table tr td.active:hover[disabled],
+.datepicker table tr td.active.disabled[disabled],
+.datepicker table tr td.active.disabled:hover[disabled] {
+  background-color: #0044cc;
+}
+.datepicker table tr td.active:active,
+.datepicker table tr td.active:hover:active,
+.datepicker table tr td.active.disabled:active,
+.datepicker table tr td.active.disabled:hover:active,
+.datepicker table tr td.active.active,
+.datepicker table tr td.active:hover.active,
+.datepicker table tr td.active.disabled.active,
+.datepicker table tr td.active.disabled:hover.active {
+  background-color: #003399 \9;
+}
+.datepicker table tr td span {
+  display: block;
+  width: 23%;
+  height: 54px;
+  line-height: 54px;
+  float: left;
+  margin: 1%;
+  cursor: pointer;
+  -webkit-border-radius: 4px;
+  -moz-border-radius: 4px;
+  border-radius: 4px;
+}
+.datepicker table tr td span:hover {
+  background: #eeeeee;
+}
+.datepicker table tr td span.disabled,
+.datepicker table tr td span.disabled:hover {
+  background: none;
+  color: #999999;
+  cursor: default;
+}
+.datepicker table tr td span.active,
+.datepicker table tr td span.active:hover,
+.datepicker table tr td span.active.disabled,
+.datepicker table tr td span.active.disabled:hover {
+  background-color: #006dcc;
+  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
+  background-image: -ms-linear-gradient(top, #0088cc, #0044cc);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
+  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
+  background-image: -o-linear-gradient(top, #0088cc, #0044cc);
+  background-image: linear-gradient(top, #0088cc, #0044cc);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);
+  border-color: #0044cc #0044cc #002a80;
+  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+  color: #fff;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+}
+.datepicker table tr td span.active:hover,
+.datepicker table tr td span.active:hover:hover,
+.datepicker table tr td span.active.disabled:hover,
+.datepicker table tr td span.active.disabled:hover:hover,
+.datepicker table tr td span.active:active,
+.datepicker table tr td span.active:hover:active,
+.datepicker table tr td span.active.disabled:active,
+.datepicker table tr td span.active.disabled:hover:active,
+.datepicker table tr td span.active.active,
+.datepicker table tr td span.active:hover.active,
+.datepicker table tr td span.active.disabled.active,
+.datepicker table tr td span.active.disabled:hover.active,
+.datepicker table tr td span.active.disabled,
+.datepicker table tr td span.active:hover.disabled,
+.datepicker table tr td span.active.disabled.disabled,
+.datepicker table tr td span.active.disabled:hover.disabled,
+.datepicker table tr td span.active[disabled],
+.datepicker table tr td span.active:hover[disabled],
+.datepicker table tr td span.active.disabled[disabled],
+.datepicker table tr td span.active.disabled:hover[disabled] {
+  background-color: #0044cc;
+}
+.datepicker table tr td span.active:active,
+.datepicker table tr td span.active:hover:active,
+.datepicker table tr td span.active.disabled:active,
+.datepicker table tr td span.active.disabled:hover:active,
+.datepicker table tr td span.active.active,
+.datepicker table tr td span.active:hover.active,
+.datepicker table tr td span.active.disabled.active,
+.datepicker table tr td span.active.disabled:hover.active {
+  background-color: #003399 \9;
+}
+.datepicker table tr td span.old,
+.datepicker table tr td span.new {
+  color: #999999;
+}
+.datepicker th.datepicker-switch {
+  width: 145px;
+}
+.datepicker thead tr:first-child th,
+.datepicker tfoot tr th {
+  cursor: pointer;
+}
+.datepicker thead tr:first-child th:hover,
+.datepicker tfoot tr th:hover {
+  background: #eeeeee;
+}
+.datepicker .cw {
+  font-size: 10px;
+  width: 12px;
+  padding: 0 2px 0 5px;
+  vertical-align: middle;
+}
+.datepicker thead tr:first-child th.cw {
+  cursor: default;
+  background-color: transparent;
+}
+.input-append.date .add-on i,
+.input-prepend.date .add-on i {
+  display: block;
+  cursor: pointer;
+  width: 16px;
+  height: 16px;
+}
+.input-daterange input {
+  text-align: center;
+}
+.input-daterange input:first-child {
+  -webkit-border-radius: 3px 0 0 3px;
+  -moz-border-radius: 3px 0 0 3px;
+  border-radius: 3px 0 0 3px;
+}
+.input-daterange input:last-child {
+  -webkit-border-radius: 0 3px 3px 0;
+  -moz-border-radius: 0 3px 3px 0;
+  border-radius: 0 3px 3px 0;
+}
+.input-daterange .add-on {
+  display: inline-block;
+  width: auto;
+  min-width: 16px;
+  height: 18px;
+  padding: 4px 5px;
+  font-weight: normal;
+  line-height: 18px;
+  text-align: center;
+  text-shadow: 0 1px 0 #ffffff;
+  vertical-align: middle;
+  background-color: #eeeeee;
+  border: 1px solid #ccc;
+  margin-left: -5px;
+  margin-right: -5px;
+}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/editable/bootstrap-editable.min.js b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/editable/bootstrap-editable.min.js
new file mode 100644
index 0000000..144fef8
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/editable/bootstrap-editable.min.js
@@ -0,0 +1,7 @@
+/*! X-editable - v1.5.3 
+* In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery
+* http://github.com/vitalets/x-editable
+* Copyright (c) 2019 Vitaliy Potapov; Licensed MIT */
+!function(a){"use strict";var b=function(b,c){this.options=a.extend({},a.fn.editableform.defaults,c),this.$div=a(b),this.options.scope||(this.options.scope=this)};b.prototype={constructor:b,initInput:function(){this.input=this.options.input,this.value=this.input.str2value(this.options.value),this.input.prerender()},initTemplate:function(){this.$form=a(a.fn.editableform.template)},initButtons:function(){var b=this.$form.find(".editable-buttons");b.append(a.fn.editableform.buttons),"bottom"===this.options.showbuttons&&b.addClass("editable-buttons-bottom")},render:function(){this.$loading=a(a.fn.editableform.loading),this.$div.empty().append(this.$loading),this.initTemplate(),this.options.showbuttons?this.initButtons():this.$form.find(".editable-buttons").remove(),this.showLoading(),this.isSaving=!1,this.$div.triggerHandler("rendering"),this.initInput(),this.$form.find("div.editable-input").append(this.input.$tpl),this.$div.append(this.$form),a.when(this.input.render()).then(a.proxy(function(){if(this.options.showbuttons||this.input.autosubmit(),this.$form.find(".editable-cancel").click(a.proxy(this.cancel,this)),this.input.error)this.error(this.input.error),this.$form.find(".editable-submit").attr("disabled",!0),this.input.$input.attr("disabled",!0),this.$form.submit(function(a){a.preventDefault()});else{this.error(!1),this.input.$input.removeAttr("disabled"),this.$form.find(".editable-submit").removeAttr("disabled");var b=null===this.value||void 0===this.value||""===this.value?this.options.defaultValue:this.value;this.input.value2input(b),this.$form.submit(a.proxy(this.submit,this))}this.$div.triggerHandler("rendered"),this.showForm(),this.input.postrender&&this.input.postrender()},this))},cancel:function(){this.$div.triggerHandler("cancel")},showLoading:function(){var a,b;this.$form?(a=this.$form.outerWidth(),b=this.$form.outerHeight(),a&&this.$loading.width(a),b&&this.$loading.height(b),this.$form.hide()):(a=this.$loading.parent().width(),a&&this.$loading.width(a)),this.$loading.show()},showForm:function(a){this.$loading.hide(),this.$form.show(),a!==!1&&this.input.activate(),this.$div.triggerHandler("show")},error:function(b){var c,d=this.$form.find(".control-group"),e=this.$form.find(".editable-error-block");if(b===!1)d.removeClass(a.fn.editableform.errorGroupClass),e.removeClass(a.fn.editableform.errorBlockClass).empty().hide();else{if(b){c=(""+b).split("\n");for(var f=0;f<c.length;f++)c[f]=a("<div>").text(c[f]).html();b=c.join("<br>")}d.addClass(a.fn.editableform.errorGroupClass),e.addClass(a.fn.editableform.errorBlockClass).html(b).show()}},submit:function(b){b.stopPropagation(),b.preventDefault();var c=this.input.input2value(),d=this.validate(c);if("object"===a.type(d)&&void 0!==d.newValue){if(c=d.newValue,this.input.value2input(c),"string"==typeof d.msg)return this.error(d.msg),void this.showForm()}else if(d)return this.error(d),void this.showForm();if(!this.options.savenochange&&this.input.value2str(c)===this.input.value2str(this.value))return void this.$div.triggerHandler("nochange");var e=this.input.value2submit(c);this.isSaving=!0,a.when(this.save(e)).done(a.proxy(function(a){this.isSaving=!1;var b="function"==typeof this.options.success?this.options.success.call(this.options.scope,a,c):null;return b===!1?(this.error(!1),void this.showForm(!1)):"string"==typeof b?(this.error(b),void this.showForm()):(b&&"object"==typeof b&&b.hasOwnProperty("newValue")&&(c=b.newValue),this.error(!1),this.value=c,void this.$div.triggerHandler("save",{newValue:c,submitValue:e,response:a}))},this)).fail(a.proxy(function(a){this.isSaving=!1;var b;b="function"==typeof this.options.error?this.options.error.call(this.options.scope,a,c):"string"==typeof a?a:a.responseText||a.statusText||"Unknown error!",this.error(b),this.showForm()},this))},save:function(b){this.options.pk=a.fn.editableutils.tryParseJson(this.options.pk,!0);var c,d="function"==typeof this.options.pk?this.options.pk.call(this.options.scope):this.options.pk,e=!!("function"==typeof this.options.url||this.options.url&&("always"===this.options.send||"auto"===this.options.send&&null!==d&&void 0!==d));return e?(this.showLoading(),c={name:this.options.name||"",value:b,pk:d},"function"==typeof this.options.params?c=this.options.params.call(this.options.scope,c):(this.options.params=a.fn.editableutils.tryParseJson(this.options.params,!0),a.extend(c,this.options.params)),"function"==typeof this.options.url?this.options.url.call(this.options.scope,c):a.ajax(a.extend({url:this.options.url,data:c,type:"POST"},this.options.ajaxOptions))):void 0},validate:function(a){return void 0===a&&(a=this.value),"function"==typeof this.options.validate?this.options.validate.call(this.options.scope,a):void 0},option:function(a,b){a in this.options&&(this.options[a]=b),"value"===a&&this.setValue(b)},setValue:function(a,b){b?this.value=this.input.str2value(a):this.value=a,this.$form&&this.$form.is(":visible")&&this.input.value2input(this.value)}},a.fn.editableform=function(c){var d=arguments;return this.each(function(){var e=a(this),f=e.data("editableform"),g="object"==typeof c&&c;f||e.data("editableform",f=new b(this,g)),"string"==typeof c&&f[c].apply(f,Array.prototype.slice.call(d,1))})},a.fn.editableform.Constructor=b,a.fn.editableform.defaults={type:"text",url:null,params:null,name:null,pk:null,value:null,defaultValue:null,send:"auto",validate:null,success:null,error:null,ajaxOptions:null,showbuttons:!0,scope:null,savenochange:!1},a.fn.editableform.template='<form class="form-inline editableform"><div class="control-group"><div><div class="editable-input"></div><div class="editable-buttons"></div></div><div class="editable-error-block"></div></div></form>',a.fn.editableform.loading='<div class="editableform-loading"></div>',a.fn.editableform.buttons='<button type="submit" class="editable-submit">ok</button><button type="button" class="editable-cancel">cancel</button>',a.fn.editableform.errorGroupClass=null,a.fn.editableform.errorBlockClass="editable-error",a.fn.editableform.engine="jquery"}(window.jQuery),function(a){"use strict";a.fn.editableutils={inherit:function(a,b){var c=function(){};c.prototype=b.prototype,a.prototype=new c,a.prototype.constructor=a,a.superclass=b.prototype},setCursorPosition:function(a,b){if(a.setSelectionRange&&/text|search|password|tel|url/i.test(a.type))try{a.setSelectionRange(b,b)}catch(c){}else if(a.createTextRange){var d=a.createTextRange();d.collapse(!0),d.moveEnd("character",b),d.moveStart("character",b),d.select()}},tryParseJson:function(a,b){if("string"==typeof a&&a.length&&a.match(/^[\{\[].*[\}\]]$/))if(b)try{a=new Function("return "+a)()}catch(c){}finally{return a}else a=new Function("return "+a)();return a},sliceObj:function(b,c,d){var e,f,g={};if(!a.isArray(c)||!c.length)return g;for(var h=0;h<c.length;h++)e=c[h],b.hasOwnProperty(e)&&(g[e]=b[e]),d!==!0&&(f=e.toLowerCase(),b.hasOwnProperty(f)&&(g[e]=b[f]));return g},getConfigData:function(b){var c={};return a.each(b[0].dataset,function(a,b){("object"!=typeof b||b&&"object"==typeof b&&(b.constructor===Object||b.constructor===Array))&&(c[a]=b)}),c},objectKeys:function(a){if(Object.keys)return Object.keys(a);if(a!==Object(a))throw new TypeError("Object.keys called on a non-object");var b,c=[];for(b in a)Object.prototype.hasOwnProperty.call(a,b)&&c.push(b);return c},escape:function(b){return a("<div>").text(b).html()},itemsByValue:function(b,c,d){if(!c||null===b)return[];if("function"!=typeof d){var e=d||"value";d=function(a){return a[e]}}var f=a.isArray(b),g=[],h=this;return a.each(c,function(c,e){if(e.children)g=g.concat(h.itemsByValue(b,e.children,d));else if(f)a.grep(b,function(a){return a==(e&&"object"==typeof e?d(e):e)}).length&&g.push(e);else{var i=e&&"object"==typeof e?d(e):e;b==i&&g.push(e)}}),g},createInput:function(b){var c,d,e,f=b.type;return"date"===f&&("inline"===b.mode?a.fn.editabletypes.datefield?f="datefield":a.fn.editabletypes.dateuifield&&(f="dateuifield"):a.fn.editabletypes.date?f="date":a.fn.editabletypes.dateui&&(f="dateui"),"date"!==f||a.fn.editabletypes.date||(f="combodate")),"datetime"===f&&"inline"===b.mode&&(f="datetimefield"),"wysihtml5"!==f||a.fn.editabletypes[f]||(f="textarea"),"function"==typeof a.fn.editabletypes[f]?(c=a.fn.editabletypes[f],d=this.sliceObj(b,this.objectKeys(c.defaults)),e=new c(d)):(a.error("Unknown type: "+f),!1)},supportsTransitions:function(){var a=document.body||document.documentElement,b=a.style,c="transition",d=["Moz","Webkit","Khtml","O","ms"];if("string"==typeof b[c])return!0;c=c.charAt(0).toUpperCase()+c.substr(1);for(var e=0;e<d.length;e++)if("string"==typeof b[d[e]+c])return!0;return!1}}}(window.jQuery),function(a){"use strict";var b=function(a,b){this.init(a,b)},c=function(a,b){this.init(a,b)};b.prototype={containerName:null,containerDataName:null,innerCss:null,containerClass:"editable-container editable-popup",defaults:{},init:function(c,d){this.$element=a(c),this.options=a.extend({},a.fn.editableContainer.defaults,d),this.splitOptions(),this.formOptions.scope=this.$element[0],this.initContainer(),this.delayedHide=!1,this.$element.on("destroyed",a.proxy(function(){this.destroy()},this)),a(document).data("editable-handlers-attached")||(a(document).on("keyup.editable",function(b){27===b.which&&a(".editable-open").editableContainer("hide","cancel")}),a(document).on("click.editable",function(c){var d,e=a(c.target),f=[".editable-container",".ui-datepicker-header",".datepicker",".modal-backdrop",".bootstrap-wysihtml5-insert-image-modal",".bootstrap-wysihtml5-insert-link-modal"];if(!a(".select2-drop-mask").is(":visible")&&a.contains(document.documentElement,c.target)&&!e.is(document)){for(d=0;d<f.length;d++)if(e.is(f[d])||e.parents(f[d]).length)return;b.prototype.closeOthers(c.target)}}),a(document).data("editable-handlers-attached",!0))},splitOptions:function(){if(this.containerOptions={},this.formOptions={},!a.fn[this.containerName])throw new Error(this.containerName+" not found. Have you included corresponding js file?");for(var b in this.options)b in this.defaults?this.containerOptions[b]=this.options[b]:this.formOptions[b]=this.options[b]},tip:function(){return this.container()?this.container().$tip:null},container:function(){var a;return this.containerDataName&&(a=this.$element.data(this.containerDataName))?a:a=this.$element.data(this.containerName)},call:function(){this.$element[this.containerName].apply(this.$element,arguments)},initContainer:function(){this.call(this.containerOptions)},renderForm:function(){this.$form.editableform(this.formOptions).on({save:a.proxy(this.save,this),nochange:a.proxy(function(){this.hide("nochange")},this),cancel:a.proxy(function(){this.hide("cancel")},this),show:a.proxy(function(){this.delayedHide?(this.hide(this.delayedHide.reason),this.delayedHide=!1):this.setPosition()},this),rendering:a.proxy(this.setPosition,this),resize:a.proxy(this.setPosition,this),rendered:a.proxy(function(){this.$element.triggerHandler("shown",a(this.options.scope).data("editable"))},this)}).editableform("render")},show:function(b){this.$element.addClass("editable-open"),b!==!1&&this.closeOthers(this.$element[0]),this.innerShow(),this.tip().addClass(this.containerClass),this.$form,this.$form=a("<div>"),this.tip().is(this.innerCss)?this.tip().append(this.$form):this.tip().find(this.innerCss).append(this.$form),this.renderForm()},hide:function(a){if(this.tip()&&this.tip().is(":visible")&&this.$element.hasClass("editable-open")){if(this.$form.data("editableform").isSaving)return void(this.delayedHide={reason:a});this.delayedHide=!1,this.$element.removeClass("editable-open"),this.innerHide(),this.$element.triggerHandler("hidden",a||"manual")}},innerShow:function(){},innerHide:function(){},toggle:function(a){this.container()&&this.tip()&&this.tip().is(":visible")?this.hide():this.show(a)},setPosition:function(){},save:function(a,b){this.$element.triggerHandler("save",b),this.hide("save")},option:function(a,b){this.options[a]=b,a in this.containerOptions?(this.containerOptions[a]=b,this.setContainerOption(a,b)):(this.formOptions[a]=b,this.$form&&this.$form.editableform("option",a,b))},setContainerOption:function(a,b){this.call("option",a,b)},destroy:function(){this.hide(),this.innerDestroy(),this.$element.off("destroyed"),this.$element.removeData("editableContainer")},innerDestroy:function(){},closeOthers:function(b){a(".editable-open").each(function(c,d){if(d!==b&&!a(d).find(b).length){var e=a(d),f=e.data("editableContainer");f&&("cancel"===f.options.onblur?e.data("editableContainer").hide("onblur"):"submit"===f.options.onblur&&e.data("editableContainer").tip().find("form").submit())}})},activate:function(){this.tip&&this.tip().is(":visible")&&this.$form&&this.$form.data("editableform").input.activate()}},a.fn.editableContainer=function(d){var e=arguments;return this.each(function(){var f=a(this),g="editableContainer",h=f.data(g),i="object"==typeof d&&d,j="inline"===i.mode?c:b;h||f.data(g,h=new j(this,i)),"string"==typeof d&&h[d].apply(h,Array.prototype.slice.call(e,1))})},a.fn.editableContainer.Popup=b,a.fn.editableContainer.Inline=c,a.fn.editableContainer.defaults={value:null,placement:"top",autohide:!0,onblur:"cancel",anim:!1,mode:"popup"},jQuery.event.special.destroyed={remove:function(a){a.handler&&a.handler()}}}(window.jQuery),function(a){"use strict";a.extend(a.fn.editableContainer.Inline.prototype,a.fn.editableContainer.Popup.prototype,{containerName:"editableform",innerCss:".editable-inline",containerClass:"editable-container editable-inline",initContainer:function(){this.$tip=a("<span></span>"),this.options.anim||(this.options.anim=0)},splitOptions:function(){this.containerOptions={},this.formOptions=this.options},tip:function(){return this.$tip},innerShow:function(){this.$element.hide(),this.tip().insertAfter(this.$element).show()},innerHide:function(){this.$tip.hide(this.options.anim,a.proxy(function(){this.$element.show(),this.innerDestroy()},this))},innerDestroy:function(){this.tip()&&this.tip().empty().remove()}})}(window.jQuery),function(a){"use strict";var b=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.editable.defaults,c,a.fn.editableutils.getConfigData(this.$element)),this.options.selector?this.initLive():this.init(),this.options.highlight&&!a.fn.editableutils.supportsTransitions()&&(this.options.highlight=!1)};b.prototype={constructor:b,init:function(){var b,c=!1;if(this.options.name=this.options.name||this.$element.attr("id"),this.options.scope=this.$element[0],this.input=a.fn.editableutils.createInput(this.options),this.input){switch(void 0===this.options.value||null===this.options.value?(this.value=this.input.html2value(a.trim(this.$element.html())),c=!0):(this.options.value=a.fn.editableutils.tryParseJson(this.options.value,!0),"string"==typeof this.options.value?this.value=this.input.str2value(this.options.value):this.value=this.options.value),this.$element.addClass("editable"),"textarea"===this.input.type&&this.$element.addClass("editable-pre-wrapped"),"manual"!==this.options.toggle?(this.$element.addClass("editable-click"),this.$element.on(this.options.toggle+".editable",a.proxy(function(a){if(this.options.disabled||a.preventDefault(),"mouseenter"===this.options.toggle)this.show();else{var b="click"!==this.options.toggle;this.toggle(b)}},this))):this.$element.attr("tabindex",-1),"function"==typeof this.options.display&&(this.options.autotext="always"),this.options.autotext){case"always":b=!0;break;case"auto":b=!a.trim(this.$element.text()).length&&null!==this.value&&void 0!==this.value&&!c;break;default:b=!1}a.when(b?this.render():!0).then(a.proxy(function(){this.options.disabled?this.disable():this.enable(),this.$element.triggerHandler("init",this)},this))}},initLive:function(){var b=this.options.selector;this.options.selector=!1,this.options.autotext="never",this.$element.on(this.options.toggle+".editable",b,a.proxy(function(c){var d=a(c.target).closest(b);d.data("editable")||(d.hasClass(this.options.emptyclass)&&d.empty(),d.editable(this.options).trigger(c))},this))},render:function(a){return this.options.display!==!1?this.input.value2htmlFinal?this.input.value2html(this.value,this.$element[0],this.options.display,a):"function"==typeof this.options.display?this.options.display.call(this.$element[0],this.value,a):this.input.value2html(this.value,this.$element[0]):void 0},enable:function(){this.options.disabled=!1,this.$element.removeClass("editable-disabled"),this.handleEmpty(this.isEmpty),"manual"!==this.options.toggle&&"-1"===this.$element.attr("tabindex")&&this.$element.removeAttr("tabindex")},disable:function(){this.options.disabled=!0,this.hide(),this.$element.addClass("editable-disabled"),this.handleEmpty(this.isEmpty),this.$element.attr("tabindex",-1)},toggleDisabled:function(){this.options.disabled?this.enable():this.disable()},option:function(b,c){return b&&"object"==typeof b?void a.each(b,a.proxy(function(b,c){this.option(a.trim(b),c)},this)):(this.options[b]=c,"disabled"===b?c?this.disable():this.enable():("value"===b&&this.setValue(c),this.container&&this.container.option(b,c),void(this.input.option&&this.input.option(b,c))))},handleEmpty:function(b){this.options.display!==!1&&(void 0!==b?this.isEmpty=b:"function"==typeof this.input.isEmpty?this.isEmpty=this.input.isEmpty(this.$element):this.isEmpty=""===a.trim(this.$element.html()),this.options.disabled?this.isEmpty&&(this.$element.empty(),this.options.emptyclass&&this.$element.removeClass(this.options.emptyclass)):this.isEmpty?(this.$element.html(this.options.emptytext),this.options.emptyclass&&this.$element.addClass(this.options.emptyclass)):this.options.emptyclass&&this.$element.removeClass(this.options.emptyclass))},show:function(b){if(!this.options.disabled){if(this.container){if(this.container.tip().is(":visible"))return}else{var c=a.extend({},this.options,{value:this.value,input:this.input});this.$element.editableContainer(c),this.$element.on("save.internal",a.proxy(this.save,this)),this.container=this.$element.data("editableContainer")}this.container.show(b)}},hide:function(){this.container&&this.container.hide()},toggle:function(a){this.container&&this.container.tip().is(":visible")?this.hide():this.show(a)},save:function(a,b){if(this.options.unsavedclass){var c=!1;c=c||"function"==typeof this.options.url,c=c||this.options.display===!1,c=c||void 0!==b.response,c=c||this.options.savenochange&&this.input.value2str(this.value)!==this.input.value2str(b.newValue),c?this.$element.removeClass(this.options.unsavedclass):this.$element.addClass(this.options.unsavedclass)}if(this.options.highlight){var d=this.$element,e=d.css("background-color");d.css("background-color",this.options.highlight),setTimeout(function(){"transparent"===e&&(e=""),d.css("background-color",e),d.addClass("editable-bg-transition"),setTimeout(function(){d.removeClass("editable-bg-transition")},1700)},10)}this.setValue(b.newValue,!1,b.response)},validate:function(){return"function"==typeof this.options.validate?this.options.validate.call(this,this.value):void 0},setValue:function(b,c,d){c?this.value=this.input.str2value(b):this.value=b,this.container&&this.container.option("value",this.value),a.when(this.render(d)).then(a.proxy(function(){this.handleEmpty()},this))},activate:function(){this.container&&this.container.activate()},destroy:function(){this.disable(),this.container&&this.container.destroy(),this.input.destroy(),"manual"!==this.options.toggle&&(this.$element.removeClass("editable-click"),this.$element.off(this.options.toggle+".editable")),this.$element.off("save.internal"),this.$element.removeClass("editable editable-open editable-disabled"),this.$element.removeData("editable")}},a.fn.editable=function(c){var d={},e=arguments,f="editable";switch(c){case"validate":return this.each(function(){var b,c=a(this),e=c.data(f);e&&(b=e.validate())&&(d[e.options.name]=b)}),d;case"getValue":return 2===arguments.length&&arguments[1]===!0?d=this.eq(0).data(f).value:this.each(function(){var b=a(this),c=b.data(f);c&&void 0!==c.value&&null!==c.value&&(d[c.options.name]=c.input.value2submit(c.value))}),d;case"submit":var g=arguments[1]||{},h=this,i=this.editable("validate");if(a.isEmptyObject(i)){var j={};if(1===h.length){var k=h.data("editable"),l={name:k.options.name||"",value:k.input.value2submit(k.value),pk:"function"==typeof k.options.pk?k.options.pk.call(k.options.scope):k.options.pk};"function"==typeof k.options.params?l=k.options.params.call(k.options.scope,l):(k.options.params=a.fn.editableutils.tryParseJson(k.options.params,!0),a.extend(l,k.options.params)),j={url:k.options.url,data:l,type:"POST"},g.success=g.success||k.options.success,g.error=g.error||k.options.error}else{var m=this.editable("getValue");j={url:g.url,data:m,type:"POST"}}j.success="function"==typeof g.success?function(a){g.success.call(h,a,g)}:a.noop,j.error="function"==typeof g.error?function(){g.error.apply(h,arguments)}:a.noop,g.ajaxOptions&&a.extend(j,g.ajaxOptions),g.data&&a.extend(j.data,g.data),a.ajax(j)}else"function"==typeof g.error&&g.error.call(h,i);return this}return this.each(function(){var d=a(this),g=d.data(f),h="object"==typeof c&&c;return h&&h.selector?void(g=new b(this,h)):(g||d.data(f,g=new b(this,h)),void("string"==typeof c&&g[c].apply(g,Array.prototype.slice.call(e,1))))})},a.fn.editable.defaults={type:"text",disabled:!1,toggle:"click",emptytext:"Empty",autotext:"auto",value:null,display:null,emptyclass:"editable-empty",unsavedclass:"editable-unsaved",selector:null,highlight:"#FFFF80"}}(window.jQuery),function(a){"use strict";a.fn.editabletypes={};var b=function(){};b.prototype={init:function(b,c,d){this.type=b,this.options=a.extend({},d,c)},prerender:function(){this.$tpl=a(this.options.tpl),this.$input=this.$tpl,this.$clear=null,this.error=null},render:function(){},value2html:function(b,c){a(c)[this.options.escape?"text":"html"](a.trim(b))},html2value:function(b){return a("<div>").html(b).text()},value2str:function(a){return String(a)},str2value:function(a){return a},value2submit:function(a){return a},value2input:function(a){this.$input.val(a)},input2value:function(){return this.$input.val()},activate:function(){this.$input.is(":visible")&&this.$input.focus()},clear:function(){this.$input.val(null)},escape:function(b){return a("<div>").text(b).html()},autosubmit:function(){},destroy:function(){},setClass:function(){this.options.inputclass&&this.$input.addClass(this.options.inputclass)},setAttr:function(a){void 0!==this.options[a]&&null!==this.options[a]&&this.$input.attr(a,this.options[a])},option:function(a,b){this.options[a]=b}},b.defaults={tpl:"",inputclass:null,escape:!0,scope:null,showbuttons:!0},a.extend(a.fn.editabletypes,{abstractinput:b})}(window.jQuery),function(a){"use strict";var b=function(a){};a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{render:function(){var b=a.Deferred();return this.error=null,this.onSourceReady(function(){this.renderList(),b.resolve()},function(){this.error=this.options.sourceError,b.resolve()}),b.promise()},html2value:function(a){return null},value2html:function(b,c,d,e){var f=a.Deferred(),g=function(){"function"==typeof d?d.call(c,b,this.sourceData,e):this.value2htmlFinal(b,c),f.resolve()};return null===b?g.call(this):this.onSourceReady(g,function(){f.resolve()}),f.promise()},onSourceReady:function(b,c){var d;if(a.isFunction(this.options.source)?(d=this.options.source.call(this.options.scope),this.sourceData=null):d=this.options.source,this.options.sourceCache&&a.isArray(this.sourceData))return void b.call(this);try{d=a.fn.editableutils.tryParseJson(d,!1)}catch(e){return void c.call(this)}if("string"==typeof d){if(this.options.sourceCache){var f,g=d;if(a(document).data(g)||a(document).data(g,{}),f=a(document).data(g),f.loading===!1&&f.sourceData)return this.sourceData=f.sourceData,this.doPrepend(),void b.call(this);if(f.loading===!0)return f.callbacks.push(a.proxy(function(){this.sourceData=f.sourceData,this.doPrepend(),b.call(this)},this)),void f.err_callbacks.push(a.proxy(c,this));f.loading=!0,f.callbacks=[],f.err_callbacks=[]}var h=a.extend({url:d,type:"get",cache:!1,dataType:"json",success:a.proxy(function(d){f&&(f.loading=!1),this.sourceData=this.makeArray(d),a.isArray(this.sourceData)?(f&&(f.sourceData=this.sourceData,a.each(f.callbacks,function(){this.call()})),this.doPrepend(),b.call(this)):(c.call(this),f&&a.each(f.err_callbacks,function(){this.call()}))},this),error:a.proxy(function(){c.call(this),f&&(f.loading=!1,a.each(f.err_callbacks,function(){this.call()}))},this)},this.options.sourceOptions);a.ajax(h)}else this.sourceData=this.makeArray(d),a.isArray(this.sourceData)?(this.doPrepend(),b.call(this)):c.call(this)},doPrepend:function(){null!==this.options.prepend&&void 0!==this.options.prepend&&(a.isArray(this.prependData)||(a.isFunction(this.options.prepend)&&(this.options.prepend=this.options.prepend.call(this.options.scope)),this.options.prepend=a.fn.editableutils.tryParseJson(this.options.prepend,!0),"string"==typeof this.options.prepend&&(this.options.prepend={"":this.options.prepend}),this.prependData=this.makeArray(this.options.prepend)),a.isArray(this.prependData)&&a.isArray(this.sourceData)&&(this.sourceData=this.prependData.concat(this.sourceData)))},renderList:function(){},value2htmlFinal:function(a,b){},makeArray:function(b){var c,d,e,f,g=[];if(!b||"string"==typeof b)return null;if(a.isArray(b)){f=function(a,b){return d={value:a,text:b},c++>=2?!1:void 0};for(var h=0;h<b.length;h++)e=b[h],"object"==typeof e?(c=0,a.each(e,f),1===c?g.push(d):c>1&&(e.children&&(e.children=this.makeArray(e.children)),g.push(e))):g.push({value:e,text:e})}else a.each(b,function(a,b){g.push({value:a,text:b})});return g},option:function(a,b){this.options[a]=b,"source"===a&&(this.sourceData=null),"prepend"===a&&(this.prependData=null)}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{source:null,prepend:!1,sourceError:"Error when loading list",sourceCache:!0,sourceOptions:null}),a.fn.editabletypes.list=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("text",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{render:function(){this.renderClear(),this.setClass(),this.setAttr("placeholder")},activate:function(){this.$input.is(":visible")&&(this.$input.focus(),this.$input.is("input,textarea")&&!this.$input.is('[type="checkbox"],[type="range"]')&&a.fn.editableutils.setCursorPosition(this.$input.get(0),this.$input.val().length),this.toggleClear&&this.toggleClear())},renderClear:function(){this.options.clear&&(this.$clear=a('<span class="editable-clear-x"></span>'),this.$input.after(this.$clear).css("padding-right",24).keyup(a.proxy(function(b){if(!~a.inArray(b.keyCode,[40,38,9,13,27])){clearTimeout(this.t);var c=this;this.t=setTimeout(function(){c.toggleClear(b)},100)}},this)).parent().css("position","relative"),this.$clear.click(a.proxy(this.clear,this)))},postrender:function(){},toggleClear:function(a){if(this.$clear){var b=this.$input.val().length,c=this.$clear.is(":visible");b&&!c&&this.$clear.show(),!b&&c&&this.$clear.hide()}},clear:function(){this.$clear.hide(),this.$input.val("").focus()}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{tpl:'<input type="text">',placeholder:null,clear:!0}),a.fn.editabletypes.text=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("textarea",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{render:function(){this.setClass(),this.setAttr("placeholder"),this.setAttr("rows"),this.$input.keydown(function(b){b.ctrlKey&&13===b.which&&a(this).closest("form").submit()})},activate:function(){a.fn.editabletypes.text.prototype.activate.call(this)}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{tpl:"<textarea></textarea>",inputclass:"input-large",placeholder:null,rows:7}),a.fn.editabletypes.textarea=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("select",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.list),a.extend(b.prototype,{renderList:function(){this.$input.empty();var b=this.options.escape,c=function(d,e){var f;if(a.isArray(e))for(var g=0;g<e.length;g++)if(f={},e[g].children)f.label=e[g].text,d.append(c(a("<optgroup>",f),e[g].children));else{f.value=e[g].value,e[g].disabled&&(f.disabled=!0);var h=a("<option>",f);h[b?"text":"html"](e[g].text),d.append(h)}return d};c(this.$input,this.sourceData),this.setClass(),this.$input.on("keydown.editable",function(b){13===b.which&&a(this).closest("form").submit()})},value2htmlFinal:function(b,c){var d="",e=a.fn.editableutils.itemsByValue(b,this.sourceData);e.length&&(d=e[0].text),a.fn.editabletypes.abstractinput.prototype.value2html.call(this,d,c)},autosubmit:function(){this.$input.off("keydown.editable").on("change.editable",function(){a(this).closest("form").submit()})}}),b.defaults=a.extend({},a.fn.editabletypes.list.defaults,{tpl:"<select></select>"}),a.fn.editabletypes.select=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("checklist",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.list),a.extend(b.prototype,{renderList:function(){var b;if(this.$tpl.empty(),a.isArray(this.sourceData)){for(var c=0;c<this.sourceData.length;c++){b=a("<label>").append(a("<input>",{type:"checkbox",value:this.sourceData[c].value}));var d=a("<span>");d[this.options.escape?"text":"html"](" "+this.sourceData[c].text),b.append(d),a("<div>").append(b).appendTo(this.$tpl)}this.$input=this.$tpl.find('input[type="checkbox"]'),this.setClass()}},value2str:function(b){return a.isArray(b)?b.sort().join(a.trim(this.options.separator)):""},str2value:function(b){var c,d=null;return"string"==typeof b&&b.length?(c=new RegExp("\\s*"+a.trim(this.options.separator)+"\\s*"),d=b.split(c)):d=a.isArray(b)?b:[b],d},value2input:function(b){this.$input.prop("checked",!1),a.isArray(b)&&b.length&&this.$input.each(function(c,d){var e=a(d);a.each(b,function(a,b){e.val()==b&&e.prop("checked",!0)})})},input2value:function(){var b=[];return this.$input.filter(":checked").each(function(c,d){b.push(a(d).val())}),b},value2htmlFinal:function(b,c){var d=[],e=a.fn.editableutils.itemsByValue(b,this.sourceData),f=this.options.escape;e.length?(a.each(e,function(b,c){var e=f?a.fn.editableutils.escape(c.text):c.text;d.push(e)}),a(c).html(d.join("<br>"))):a(c).empty()},activate:function(){this.$input.first().focus()},autosubmit:function(){this.$input.on("keydown",function(b){13===b.which&&a(this).closest("form").submit()})}}),b.defaults=a.extend({},a.fn.editabletypes.list.defaults,{tpl:'<div class="editable-checklist"></div>',inputclass:null,separator:","}),a.fn.editabletypes.checklist=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("password",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.text),a.extend(b.prototype,{value2html:function(b,c){b?a(c).text("[hidden]"):a(c).empty()},html2value:function(a){return null}}),b.defaults=a.extend({},a.fn.editabletypes.text.defaults,{tpl:'<input type="password">'}),a.fn.editabletypes.password=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("email",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.text),b.defaults=a.extend({},a.fn.editabletypes.text.defaults,{tpl:'<input type="email">'}),a.fn.editabletypes.email=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("url",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.text),b.defaults=a.extend({},a.fn.editabletypes.text.defaults,{tpl:'<input type="url">'}),a.fn.editabletypes.url=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("tel",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.text),b.defaults=a.extend({},a.fn.editabletypes.text.defaults,{tpl:'<input type="tel">'}),a.fn.editabletypes.tel=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("number",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.text),a.extend(b.prototype,{render:function(){
+b.superclass.render.call(this),this.setAttr("min"),this.setAttr("max"),this.setAttr("step")},postrender:function(){this.$clear&&this.$clear.css({right:24})}}),b.defaults=a.extend({},a.fn.editabletypes.text.defaults,{tpl:'<input type="number">',inputclass:"input-mini",min:null,max:null,step:null}),a.fn.editabletypes.number=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("range",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.number),a.extend(b.prototype,{render:function(){this.$input=this.$tpl.filter("input"),this.setClass(),this.setAttr("min"),this.setAttr("max"),this.setAttr("step"),this.$input.on("input",function(){a(this).siblings("output").text(a(this).val())})},activate:function(){this.$input.focus()}}),b.defaults=a.extend({},a.fn.editabletypes.number.defaults,{tpl:'<input type="range"><output style="width: 30px; display: inline-block"></output>',inputclass:"input-medium"}),a.fn.editabletypes.range=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("time",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{render:function(){this.setClass()}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{tpl:'<input type="time">'}),a.fn.editabletypes.time=b}(window.jQuery),function(a){"use strict";var b=function(c){if(this.init("select2",c,b.defaults),c.select2=c.select2||{},this.sourceData=null,c.placeholder&&(c.select2.placeholder=c.placeholder),!c.select2.tags&&c.source){var d=c.source;a.isFunction(c.source)&&(d=c.source.call(c.scope)),"string"==typeof d?(c.select2.ajax=c.select2.ajax||{},c.select2.ajax.data||(c.select2.ajax.data=function(a){return{query:a}}),c.select2.ajax.results||(c.select2.ajax.results=function(a){return{results:a}}),c.select2.ajax.url=d):(this.sourceData=this.convertSource(d),c.select2.data=this.sourceData)}if(this.options.select2=a.extend({},b.defaults.select2,c.select2),this.isMultiple=this.options.select2.tags||this.options.select2.multiple,this.isRemote="ajax"in this.options.select2,this.idFunc=this.options.select2.id,"function"!=typeof this.idFunc){var e=this.idFunc||"id";this.idFunc=function(a){return a[e]}}this.formatSelection=this.options.select2.formatSelection,"function"!=typeof this.formatSelection&&(this.formatSelection=function(a){return a.text})};a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{render:function(){this.setClass(),this.isRemote&&this.$input.on("select2-loaded",a.proxy(function(a){this.sourceData=a.items.results},this)),this.isMultiple&&this.$input.on("change",function(){a(this).closest("form").parent().triggerHandler("resize")})},value2html:function(c,d){var e,f="",g=this;this.options.select2.tags?e=c:this.sourceData&&(e=a.fn.editableutils.itemsByValue(c,this.sourceData,this.idFunc)),a.isArray(e)?(f=[],a.each(e,function(a,b){f.push(b&&"object"==typeof b?g.formatSelection(b):b)})):e&&(f=g.formatSelection(e)),f=a.isArray(f)?f.join(this.options.viewseparator):f,b.superclass.value2html.call(this,f,d)},html2value:function(a){return this.options.select2.tags?this.str2value(a,this.options.viewseparator):null},value2input:function(b){if(a.isArray(b)&&(b=b.join(this.getSeparator())),this.$input.data("select2")?this.$input.val(b).trigger("change",!0):(this.$input.val(b),this.$input.select2(this.options.select2)),this.isRemote&&!this.isMultiple&&!this.options.select2.initSelection){var c=this.options.select2.id,d=this.options.select2.formatSelection;if(!c&&!d){var e=a(this.options.scope);if(!e.data("editable").isEmpty){var f={id:b,text:e.text()};this.$input.select2("data",f)}}}},input2value:function(){return this.$input.select2("val")},str2value:function(b,c){if("string"!=typeof b||!this.isMultiple)return b;c=c||this.getSeparator();var d,e,f;if(null===b||b.length<1)return null;for(d=b.split(c),e=0,f=d.length;f>e;e+=1)d[e]=a.trim(d[e]);return d},autosubmit:function(){this.$input.on("change",function(b,c){c||a(this).closest("form").submit()})},getSeparator:function(){return this.options.select2.separator||a.fn.select2.defaults.separator},convertSource:function(b){if(a.isArray(b)&&b.length&&void 0!==b[0].value)for(var c=0;c<b.length;c++)void 0!==b[c].value&&(b[c].id=b[c].value,delete b[c].value);return b},destroy:function(){this.$input&&this.$input.data("select2")&&this.$input.select2("destroy")}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{tpl:'<input type="hidden">',select2:null,placeholder:null,source:null,viewseparator:", "}),a.fn.editabletypes.select2=b}(window.jQuery),function(a){var b=function(b,c){return this.$element=a(b),this.$element.is("input")?(this.options=a.extend({},a.fn.combodate.defaults,c,this.$element.data()),void this.init()):void a.error("Combodate should be applied to INPUT element")};b.prototype={constructor:b,init:function(){this.map={day:["D","date"],month:["M","month"],year:["Y","year"],hour:["[Hh]","hours"],minute:["m","minutes"],second:["s","seconds"],ampm:["[Aa]",""]},this.$widget=a('<span class="combodate"></span>').html(this.getTemplate()),this.initCombos(),this.datetime=null,this.$widget.on("change","select",a.proxy(function(b){this.$element.val(this.getValue()).change(),this.options.smartDays&&(a(b.target).is(".month")||a(b.target).is(".year"))&&this.fillCombo("day")},this)),this.$widget.find("select").css("width","auto"),this.$element.hide().after(this.$widget),this.setValue(this.$element.val()||this.options.value)},getTemplate:function(){var b=this.options.template,c=this.$element.prop("disabled"),d=this.options.customClass;return a.each(this.map,function(a,c){c=c[0];var d=new RegExp(c+"+"),e=c.length>1?c.substring(1,2):c;b=b.replace(d,"{"+e+"}")}),b=b.replace(/ /g,"&nbsp;"),a.each(this.map,function(a,e){e=e[0];var f=e.length>1?e.substring(1,2):e;b=b.replace("{"+f+"}",'<select class="'+a+" "+d+'"'+(c?' disabled="disabled"':"")+"></select>")}),b},initCombos:function(){for(var a in this.map){var b=this.$widget.find("."+a);this["$"+a]=b.length?b:null,this.fillCombo(a)}},fillCombo:function(a){var b=this["$"+a];if(b){var c="fill"+a.charAt(0).toUpperCase()+a.slice(1),d=this[c](),e=b.val();b.empty();for(var f=0;f<d.length;f++)b.append('<option value="'+d[f][0]+'">'+d[f][1]+"</option>");b.val(e)}},fillCommon:function(a){var b,c=[];if("name"===this.options.firstItem){b=moment.localeData?moment.localeData()._relativeTime:moment.relativeTime||moment.langData()._relativeTime;var d="function"==typeof b[a]?b[a](1,!0,a,!1):b[a];d=d.split(" ").reverse()[0],c.push(["",d])}else"empty"===this.options.firstItem&&c.push(["",""]);return c},fillDay:function(){var a,b,c=this.fillCommon("d"),d=-1!==this.options.template.indexOf("DD"),e=31;if(this.options.smartDays&&this.$month&&this.$year){var f=parseInt(this.$month.val(),10),g=parseInt(this.$year.val(),10);isNaN(f)||isNaN(g)||(e=moment([g,f]).daysInMonth())}for(b=1;e>=b;b++)a=d?this.leadZero(b):b,c.push([b,a]);return c},fillMonth:function(){var a,b,c=this.fillCommon("M"),d=-1!==this.options.template.indexOf("MMMMMM"),e=-1!==this.options.template.indexOf("MMMMM"),f=-1!==this.options.template.indexOf("MMMM"),g=-1!==this.options.template.indexOf("MMM"),h=-1!==this.options.template.indexOf("MM");for(b=0;11>=b;b++)a=d?moment().date(1).month(b).format("MM - MMMM"):e?moment().date(1).month(b).format("MM - MMM"):f?moment().date(1).month(b).format("MMMM"):g?moment().date(1).month(b).format("MMM"):h?this.leadZero(b+1):b+1,c.push([b,a]);return c},fillYear:function(){var a,b,c=[],d=-1!==this.options.template.indexOf("YYYY");for(b=this.options.maxYear;b>=this.options.minYear;b--)a=d?b:(b+"").substring(2),c[this.options.yearDescending?"push":"unshift"]([b,a]);return c=this.fillCommon("y").concat(c)},fillHour:function(){var a,b,c=this.fillCommon("h"),d=-1!==this.options.template.indexOf("h"),e=(-1!==this.options.template.indexOf("H"),-1!==this.options.template.toLowerCase().indexOf("hh")),f=d?1:0,g=d?12:23;for(b=f;g>=b;b++)a=e?this.leadZero(b):b,c.push([b,a]);return c},fillMinute:function(){var a,b,c=this.fillCommon("m"),d=-1!==this.options.template.indexOf("mm");for(b=0;59>=b;b+=this.options.minuteStep)a=d?this.leadZero(b):b,c.push([b,a]);return c},fillSecond:function(){var a,b,c=this.fillCommon("s"),d=-1!==this.options.template.indexOf("ss");for(b=0;59>=b;b+=this.options.secondStep)a=d?this.leadZero(b):b,c.push([b,a]);return c},fillAmpm:function(){var a=-1!==this.options.template.indexOf("a"),b=(-1!==this.options.template.indexOf("A"),[["am",a?"am":"AM"],["pm",a?"pm":"PM"]]);return b},getValue:function(b){var c,d={},e=this,f=!1;return a.each(this.map,function(a,b){if("ampm"!==a){if(e["$"+a])d[a]=parseInt(e["$"+a].val(),10);else{var c;c=e.datetime?e.datetime[b[1]]():"day"===a?1:0,d[a]=c}return isNaN(d[a])?(f=!0,!1):void 0}}),f?"":(this.$ampm&&(12===d.hour?d.hour="am"===this.$ampm.val()?0:12:d.hour="am"===this.$ampm.val()?d.hour:d.hour+12),c=moment([d.year,d.month,d.day,d.hour,d.minute,d.second]),this.highlight(c),b=void 0===b?this.options.format:b,null===b?c.isValid()?c:null:c.isValid()?c.format(b):"")},setValue:function(b){function c(b,c){var d={};return b.children("option").each(function(b,e){var f,g=a(e).attr("value");""!==g&&(f=Math.abs(g-c),("undefined"==typeof d.distance||f<d.distance)&&(d={value:g,distance:f}))}),d.value}if(b){var d="string"==typeof b?moment(b,this.options.format,!0):moment(b),e=this,f={};d.isValid()?(a.each(this.map,function(a,b){"ampm"!==a&&(f[a]=d[b[1]]())}),this.$ampm&&(f.hour>=12?(f.ampm="pm",f.hour>12&&(f.hour-=12)):(f.ampm="am",0===f.hour&&(f.hour=12))),a.each(f,function(a,b){e["$"+a]&&("minute"===a&&e.options.minuteStep>1&&e.options.roundTime&&(b=c(e["$"+a],b)),"second"===a&&e.options.secondStep>1&&e.options.roundTime&&(b=c(e["$"+a],b)),e["$"+a].val(b))}),this.options.smartDays&&this.fillCombo("day"),this.$element.val(d.format(this.options.format)).change(),this.datetime=d):this.datetime=null}},highlight:function(a){a.isValid()?this.options.errorClass?this.$widget.removeClass(this.options.errorClass):this.$widget.find("select").css("border-color",this.borderColor):this.options.errorClass?this.$widget.addClass(this.options.errorClass):(this.borderColor||(this.borderColor=this.$widget.find("select").css("border-color")),this.$widget.find("select").css("border-color","red"))},leadZero:function(a){return 9>=a?"0"+a:a},destroy:function(){this.$widget.remove(),this.$element.removeData("combodate").show()}},a.fn.combodate=function(c){var d,e=Array.apply(null,arguments);return e.shift(),"getValue"===c&&this.length&&(d=this.eq(0).data("combodate"))?d.getValue.apply(d,e):this.each(function(){var d=a(this),f=d.data("combodate"),g="object"==typeof c&&c;f||d.data("combodate",f=new b(this,g)),"string"==typeof c&&"function"==typeof f[c]&&f[c].apply(f,e)})},a.fn.combodate.defaults={format:"DD-MM-YYYY HH:mm",template:"D / MMM / YYYY   H : mm",value:null,minYear:1970,maxYear:(new Date).getFullYear(),yearDescending:!0,minuteStep:5,secondStep:1,firstItem:"empty",errorClass:null,customClass:"",roundTime:!0,smartDays:!1}}(window.jQuery),function(a){"use strict";var b=function(c){this.init("combodate",c,b.defaults),this.options.viewformat||(this.options.viewformat=this.options.format),c.combodate=a.fn.editableutils.tryParseJson(c.combodate,!0),this.options.combodate=a.extend({},b.defaults.combodate,c.combodate,{format:this.options.format,template:this.options.template})};a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{render:function(){this.$input.combodate(this.options.combodate),"bs3"===a.fn.editableform.engine&&this.$input.siblings().find("select").addClass("form-control"),this.options.inputclass&&this.$input.siblings().find("select").addClass(this.options.inputclass)},value2html:function(a,c){var d=a?a.format(this.options.viewformat):"";b.superclass.value2html.call(this,d,c)},html2value:function(a){return a?moment(a,this.options.viewformat):null},value2str:function(a){return a?a.format(this.options.format):""},str2value:function(a){return a?moment(a,this.options.format):null},value2submit:function(a){return this.value2str(a)},value2input:function(a){this.$input.combodate("setValue",a)},input2value:function(){return this.$input.combodate("getValue",null)},activate:function(){this.$input.siblings(".combodate").find("select").eq(0).focus()},autosubmit:function(){}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{tpl:'<input type="text">',inputclass:null,format:"YYYY-MM-DD",viewformat:null,template:"D / MMM / YYYY",combodate:null}),a.fn.editabletypes.combodate=b}(window.jQuery),function(a){"use strict";var b=a.fn.editableform.Constructor.prototype.initInput;a.extend(a.fn.editableform.Constructor.prototype,{initTemplate:function(){this.$form=a(a.fn.editableform.template),this.$form.find(".control-group").addClass("form-group"),this.$form.find(".editable-error-block").addClass("help-block")},initInput:function(){b.apply(this);var c=null===this.input.options.inputclass||this.input.options.inputclass===!1,d="input-sm",e="text,select,textarea,password,email,url,tel,number,range,time,typeaheadjs".split(",");~a.inArray(this.input.type,e)&&(this.input.$input.addClass("form-control"),c&&(this.input.options.inputclass=d,this.input.$input.addClass(d)));for(var f=this.$form.find(".editable-buttons"),g=c?[d]:this.input.options.inputclass.split(" "),h=0;h<g.length;h++)"input-lg"===g[h].toLowerCase()&&f.find("button").removeClass("btn-sm").addClass("btn-lg")}}),a.fn.editableform.buttons='<button type="submit" class="btn btn-primary btn-sm editable-submit"><i class="glyphicon glyphicon-ok"></i></button><button type="button" class="btn btn-default btn-sm editable-cancel"><i class="glyphicon glyphicon-remove"></i></button>',a.fn.editableform.errorGroupClass="has-error",a.fn.editableform.errorBlockClass=null,a.fn.editableform.engine="bs3"}(window.jQuery),function(a){"use strict";a.extend(a.fn.editableContainer.Popup.prototype,{containerName:"popover",containerDataName:"bs.popover",innerCss:".popover-content",defaults:a.fn.popover.Constructor.DEFAULTS,initContainer:function(){a.extend(this.containerOptions,{trigger:"manual",selector:!1,content:" ",template:this.defaults.template});var b;this.$element.data("template")&&(b=this.$element.data("template"),this.$element.removeData("template")),this.call(this.containerOptions),b&&this.$element.data("template",b)},innerShow:function(){this.call("show")},innerHide:function(){this.call("hide")},innerDestroy:function(){this.call("destroy")},setContainerOption:function(a,b){this.container().options[a]=b},setPosition:function(){(function(){var a=this.tip(),b="function"==typeof this.options.placement?this.options.placement.call(this,a[0],this.$element[0]):this.options.placement,c=/\s?auto?\s?/i,d=c.test(b);d&&(b=b.replace(c,"")||"top");var e=this.getPosition(),f=a[0].offsetWidth,g=a[0].offsetHeight;if(d){var h=this.$element.parent(),i=b,j=document.documentElement.scrollTop||document.body.scrollTop,k="body"==this.options.container?window.innerWidth:h.outerWidth(),l="body"==this.options.container?window.innerHeight:h.outerHeight(),m="body"==this.options.container?0:h.offset().left;b="bottom"==b&&e.top+e.height+g-j>l?"top":"top"==b&&e.top-j-g<0?"bottom":"right"==b&&e.right+f>k?"left":"left"==b&&e.left-f<m?"right":b,a.removeClass(i).addClass(b)}var n=this.getCalculatedOffset(b,e,f,g);this.applyPlacement(n,b)}).call(this.container())}})}(window.jQuery),function(a){function b(){return new Date(Date.UTC.apply(Date,arguments))}function c(b,c){var d,e=a(b).data(),f={},g=new RegExp("^"+c.toLowerCase()+"([A-Z])"),c=new RegExp("^"+c.toLowerCase());for(var h in e)c.test(h)&&(d=h.replace(g,function(a,b){return b.toLowerCase()}),f[d]=e[h]);return f}function d(b){var c={};if(k[b]||(b=b.split("-")[0],k[b])){var d=k[b];return a.each(j,function(a,b){b in d&&(c[b]=d[b])}),c}}var e=function(b,c){this._process_options(c),this.element=a(b),this.isInline=!1,this.isInput=this.element.is("input"),this.component=this.element.is(".date")?this.element.find(".add-on, .btn"):!1,this.hasInput=this.component&&this.element.find("input").length,this.component&&0===this.component.length&&(this.component=!1),this.picker=a(l.template),this._buildEvents(),this._attachEvents(),this.isInline?this.picker.addClass("datepicker-inline").appendTo(this.element):this.picker.addClass("datepicker-dropdown dropdown-menu"),this.o.rtl&&(this.picker.addClass("datepicker-rtl"),this.picker.find(".prev i, .next i").toggleClass("icon-arrow-left icon-arrow-right")),this.viewMode=this.o.startView,this.o.calendarWeeks&&this.picker.find("tfoot th.today").attr("colspan",function(a,b){return parseInt(b)+1}),this._allow_update=!1,this.setStartDate(this.o.startDate),this.setEndDate(this.o.endDate),this.setDaysOfWeekDisabled(this.o.daysOfWeekDisabled),this.fillDow(),this.fillMonths(),this._allow_update=!0,this.update(),this.showMode(),this.isInline&&this.show()};e.prototype={constructor:e,_process_options:function(b){this._o=a.extend({},this._o,b);var c=this.o=a.extend({},this._o),d=c.language;switch(k[d]||(d=d.split("-")[0],k[d]||(d=i.language)),c.language=d,c.startView){case 2:case"decade":c.startView=2;break;case 1:case"year":c.startView=1;break;default:c.startView=0}switch(c.minViewMode){case 1:case"months":c.minViewMode=1;break;case 2:case"years":c.minViewMode=2;break;default:c.minViewMode=0}c.startView=Math.max(c.startView,c.minViewMode),c.weekStart%=7,c.weekEnd=(c.weekStart+6)%7;var e=l.parseFormat(c.format);c.startDate!==-(1/0)&&(c.startDate=l.parseDate(c.startDate,e,c.language)),c.endDate!==1/0&&(c.endDate=l.parseDate(c.endDate,e,c.language)),c.daysOfWeekDisabled=c.daysOfWeekDisabled||[],a.isArray(c.daysOfWeekDisabled)||(c.daysOfWeekDisabled=c.daysOfWeekDisabled.split(/[,\s]*/)),c.daysOfWeekDisabled=a.map(c.daysOfWeekDisabled,function(a){return parseInt(a,10)})},_events:[],_secondaryEvents:[],_applyEvents:function(a){for(var b,c,d=0;d<a.length;d++)b=a[d][0],c=a[d][1],b.on(c)},_unapplyEvents:function(a){for(var b,c,d=0;d<a.length;d++)b=a[d][0],c=a[d][1],b.off(c)},_buildEvents:function(){this.isInput?this._events=[[this.element,{focus:a.proxy(this.show,this),keyup:a.proxy(this.update,this),keydown:a.proxy(this.keydown,this)}]]:this.component&&this.hasInput?this._events=[[this.element.find("input"),{focus:a.proxy(this.show,this),keyup:a.proxy(this.update,this),keydown:a.proxy(this.keydown,this)}],[this.component,{click:a.proxy(this.show,this)}]]:this.element.is("div")?this.isInline=!0:this._events=[[this.element,{click:a.proxy(this.show,this)}]],this._secondaryEvents=[[this.picker,{click:a.proxy(this.click,this)}],[a(window),{resize:a.proxy(this.place,this)}],[a(document),{mousedown:a.proxy(function(a){this.element.is(a.target)||this.element.find(a.target).size()||this.picker.is(a.target)||this.picker.find(a.target).size()||this.hide()},this)}]]},_attachEvents:function(){this._detachEvents(),this._applyEvents(this._events)},_detachEvents:function(){this._unapplyEvents(this._events)},_attachSecondaryEvents:function(){this._detachSecondaryEvents(),this._applyEvents(this._secondaryEvents)},_detachSecondaryEvents:function(){this._unapplyEvents(this._secondaryEvents)},_trigger:function(b,c){var d=c||this.date,e=new Date(d.getTime()+6e4*d.getTimezoneOffset());this.element.trigger({type:b,date:e,format:a.proxy(function(a){var b=a||this.o.format;return l.formatDate(d,b,this.o.language)},this)})},show:function(a){this.isInline||this.picker.appendTo("body"),this.picker.show(),this.height=this.component?this.component.outerHeight():this.element.outerHeight(),this.place(),this._attachSecondaryEvents(),a&&a.preventDefault(),this._trigger("show")},hide:function(a){this.isInline||this.picker.is(":visible")&&(this.picker.hide().detach(),this._detachSecondaryEvents(),this.viewMode=this.o.startView,this.showMode(),this.o.forceParse&&(this.isInput&&this.element.val()||this.hasInput&&this.element.find("input").val())&&this.setValue(),this._trigger("hide"))},remove:function(){this.hide(),this._detachEvents(),this._detachSecondaryEvents(),this.picker.remove(),delete this.element.data().datepicker,this.isInput||delete this.element.data().date},getDate:function(){var a=this.getUTCDate();return new Date(a.getTime()+6e4*a.getTimezoneOffset())},getUTCDate:function(){return this.date},setDate:function(a){this.setUTCDate(new Date(a.getTime()-6e4*a.getTimezoneOffset()))},setUTCDate:function(a){this.date=a,this.setValue()},setValue:function(){var a=this.getFormattedDate();this.isInput?this.element.val(a):this.component&&this.element.find("input").val(a)},getFormattedDate:function(a){return void 0===a&&(a=this.o.format),l.formatDate(this.date,a,this.o.language)},setStartDate:function(a){this._process_options({startDate:a}),this.update(),this.updateNavArrows()},setEndDate:function(a){this._process_options({endDate:a}),this.update(),this.updateNavArrows()},setDaysOfWeekDisabled:function(a){this._process_options({daysOfWeekDisabled:a}),this.update(),this.updateNavArrows()},place:function(){if(!this.isInline){var b=parseInt(this.element.parents().filter(function(){return"auto"!=a(this).css("z-index")}).first().css("z-index"))+10,c=this.component?this.component.parent().offset():this.element.offset(),d=this.component?this.component.outerHeight(!0):this.element.outerHeight(!0);this.picker.css({top:c.top+d,left:c.left,zIndex:b})}},_allow_update:!0,update:function(){if(this._allow_update){var a,b=!1;arguments&&arguments.length&&("string"==typeof arguments[0]||arguments[0]instanceof Date)?(a=arguments[0],b=!0):(a=this.isInput?this.element.val():this.element.data("date")||this.element.find("input").val(),delete this.element.data().date),this.date=l.parseDate(a,this.o.format,this.o.language),b&&this.setValue(),this.date<this.o.startDate?this.viewDate=new Date(this.o.startDate):this.date>this.o.endDate?this.viewDate=new Date(this.o.endDate):this.viewDate=new Date(this.date),this.fill()}},fillDow:function(){var a=this.o.weekStart,b="<tr>";if(this.o.calendarWeeks){var c='<th class="cw">&nbsp;</th>';b+=c,this.picker.find(".datepicker-days thead tr:first-child").prepend(c)}for(;a<this.o.weekStart+7;)b+='<th class="dow">'+k[this.o.language].daysMin[a++%7]+"</th>";b+="</tr>",this.picker.find(".datepicker-days thead").append(b)},fillMonths:function(){for(var a="",b=0;12>b;)a+='<span class="month">'+k[this.o.language].monthsShort[b++]+"</span>";this.picker.find(".datepicker-months td").html(a)},setRange:function(b){b&&b.length?this.range=a.map(b,function(a){return a.valueOf()}):delete this.range,this.fill()},getClassNames:function(b){var c=[],d=this.viewDate.getUTCFullYear(),e=this.viewDate.getUTCMonth(),f=this.date.valueOf(),g=new Date;return b.getUTCFullYear()<d||b.getUTCFullYear()==d&&b.getUTCMonth()<e?c.push("old"):(b.getUTCFullYear()>d||b.getUTCFullYear()==d&&b.getUTCMonth()>e)&&c.push("new"),this.o.todayHighlight&&b.getUTCFullYear()==g.getFullYear()&&b.getUTCMonth()==g.getMonth()&&b.getUTCDate()==g.getDate()&&c.push("today"),f&&b.valueOf()==f&&c.push("active"),(b.valueOf()<this.o.startDate||b.valueOf()>this.o.endDate||-1!==a.inArray(b.getUTCDay(),this.o.daysOfWeekDisabled))&&c.push("disabled"),this.range&&(b>this.range[0]&&b<this.range[this.range.length-1]&&c.push("range"),-1!=a.inArray(b.valueOf(),this.range)&&c.push("selected")),c},fill:function(){var c,d=new Date(this.viewDate),e=d.getUTCFullYear(),f=d.getUTCMonth(),g=this.o.startDate!==-(1/0)?this.o.startDate.getUTCFullYear():-(1/0),h=this.o.startDate!==-(1/0)?this.o.startDate.getUTCMonth():-(1/0),i=this.o.endDate!==1/0?this.o.endDate.getUTCFullYear():1/0,j=this.o.endDate!==1/0?this.o.endDate.getUTCMonth():1/0;this.date&&this.date.valueOf();this.picker.find(".datepicker-days thead th.datepicker-switch").text(k[this.o.language].months[f]+" "+e),this.picker.find("tfoot th.today").text(k[this.o.language].today).toggle(this.o.todayBtn!==!1),this.picker.find("tfoot th.clear").text(k[this.o.language].clear).toggle(this.o.clearBtn!==!1),this.updateNavArrows(),this.fillMonths();var m=b(e,f-1,28,0,0,0,0),n=l.getDaysInMonth(m.getUTCFullYear(),m.getUTCMonth());m.setUTCDate(n),m.setUTCDate(n-(m.getUTCDay()-this.o.weekStart+7)%7);var o=new Date(m);o.setUTCDate(o.getUTCDate()+42),o=o.valueOf();for(var p,q=[];m.valueOf()<o;){if(m.getUTCDay()==this.o.weekStart&&(q.push("<tr>"),this.o.calendarWeeks)){var r=new Date(+m+(this.o.weekStart-m.getUTCDay()-7)%7*864e5),s=new Date(+r+(11-r.getUTCDay())%7*864e5),t=new Date(+(t=b(s.getUTCFullYear(),0,1))+(11-t.getUTCDay())%7*864e5),u=(s-t)/864e5/7+1;q.push('<td class="cw">'+u+"</td>")}p=this.getClassNames(m),p.push("day");var v=this.o.beforeShowDay(m);void 0===v?v={}:"boolean"==typeof v?v={enabled:v}:"string"==typeof v&&(v={classes:v}),v.enabled===!1&&p.push("disabled"),v.classes&&(p=p.concat(v.classes.split(/\s+/))),v.tooltip&&(c=v.tooltip),p=a.unique(p),q.push('<td class="'+p.join(" ")+'"'+(c?' title="'+c+'"':"")+">"+m.getUTCDate()+"</td>"),m.getUTCDay()==this.o.weekEnd&&q.push("</tr>"),m.setUTCDate(m.getUTCDate()+1)}this.picker.find(".datepicker-days tbody").empty().append(q.join(""));var w=this.date&&this.date.getUTCFullYear(),x=this.picker.find(".datepicker-months").find("th:eq(1)").text(e).end().find("span").removeClass("active");w&&w==e&&x.eq(this.date.getUTCMonth()).addClass("active"),(g>e||e>i)&&x.addClass("disabled"),e==g&&x.slice(0,h).addClass("disabled"),e==i&&x.slice(j+1).addClass("disabled"),q="",e=10*parseInt(e/10,10);var y=this.picker.find(".datepicker-years").find("th:eq(1)").text(e+"-"+(e+9)).end().find("td");e-=1;for(var z=-1;11>z;z++)q+='<span class="year'+(-1==z?" old":10==z?" new":"")+(w==e?" active":"")+(g>e||e>i?" disabled":"")+'">'+e+"</span>",e+=1;y.html(q)},updateNavArrows:function(){if(this._allow_update){var a=new Date(this.viewDate),b=a.getUTCFullYear(),c=a.getUTCMonth();switch(this.viewMode){case 0:this.o.startDate!==-(1/0)&&b<=this.o.startDate.getUTCFullYear()&&c<=this.o.startDate.getUTCMonth()?this.picker.find(".prev").css({visibility:"hidden"}):this.picker.find(".prev").css({visibility:"visible"}),this.o.endDate!==1/0&&b>=this.o.endDate.getUTCFullYear()&&c>=this.o.endDate.getUTCMonth()?this.picker.find(".next").css({visibility:"hidden"}):this.picker.find(".next").css({visibility:"visible"});break;case 1:case 2:this.o.startDate!==-(1/0)&&b<=this.o.startDate.getUTCFullYear()?this.picker.find(".prev").css({visibility:"hidden"}):this.picker.find(".prev").css({visibility:"visible"}),this.o.endDate!==1/0&&b>=this.o.endDate.getUTCFullYear()?this.picker.find(".next").css({visibility:"hidden"}):this.picker.find(".next").css({visibility:"visible"})}}},click:function(c){c.preventDefault();var d=a(c.target).closest("span, td, th");if(1==d.length)switch(d[0].nodeName.toLowerCase()){case"th":switch(d[0].className){case"datepicker-switch":this.showMode(1);break;case"prev":case"next":var e=l.modes[this.viewMode].navStep*("prev"==d[0].className?-1:1);switch(this.viewMode){case 0:this.viewDate=this.moveMonth(this.viewDate,e);break;case 1:case 2:this.viewDate=this.moveYear(this.viewDate,e)}this.fill();break;case"today":var f=new Date;f=b(f.getFullYear(),f.getMonth(),f.getDate(),0,0,0),this.showMode(-2);var g="linked"==this.o.todayBtn?null:"view";this._setDate(f,g);break;case"clear":var h;this.isInput?h=this.element:this.component&&(h=this.element.find("input")),h&&h.val("").change(),this._trigger("changeDate"),this.update(),this.o.autoclose&&this.hide()}break;case"span":if(!d.is(".disabled")){if(this.viewDate.setUTCDate(1),d.is(".month")){var i=1,j=d.parent().find("span").index(d),k=this.viewDate.getUTCFullYear();this.viewDate.setUTCMonth(j),this._trigger("changeMonth",this.viewDate),1===this.o.minViewMode&&this._setDate(b(k,j,i,0,0,0,0))}else{var k=parseInt(d.text(),10)||0,i=1,j=0;this.viewDate.setUTCFullYear(k),this._trigger("changeYear",this.viewDate),2===this.o.minViewMode&&this._setDate(b(k,j,i,0,0,0,0))}this.showMode(-1),this.fill()}break;case"td":if(d.is(".day")&&!d.is(".disabled")){var i=parseInt(d.text(),10)||1,k=this.viewDate.getUTCFullYear(),j=this.viewDate.getUTCMonth();d.is(".old")?0===j?(j=11,k-=1):j-=1:d.is(".new")&&(11==j?(j=0,k+=1):j+=1),this._setDate(b(k,j,i,0,0,0,0))}}},_setDate:function(a,b){b&&"date"!=b||(this.date=new Date(a)),b&&"view"!=b||(this.viewDate=new Date(a)),this.fill(),this.setValue(),this._trigger("changeDate");var c;this.isInput?c=this.element:this.component&&(c=this.element.find("input")),c&&(c.change(),!this.o.autoclose||b&&"date"!=b||this.hide())},moveMonth:function(a,b){if(!b)return a;var c,d,e=new Date(a.valueOf()),f=e.getUTCDate(),g=e.getUTCMonth(),h=Math.abs(b);if(b=b>0?1:-1,1==h)d=-1==b?function(){return e.getUTCMonth()==g}:function(){return e.getUTCMonth()!=c},c=g+b,e.setUTCMonth(c),(0>c||c>11)&&(c=(c+12)%12);else{for(var i=0;h>i;i++)e=this.moveMonth(e,b);c=e.getUTCMonth(),e.setUTCDate(f),d=function(){return c!=e.getUTCMonth()}}for(;d();)e.setUTCDate(--f),e.setUTCMonth(c);return e},moveYear:function(a,b){return this.moveMonth(a,12*b)},dateWithinRange:function(a){return a>=this.o.startDate&&a<=this.o.endDate},keydown:function(a){if(this.picker.is(":not(:visible)"))return void(27==a.keyCode&&this.show());var b,c,d,e=!1;switch(a.keyCode){case 27:this.hide(),a.preventDefault();break;case 37:case 39:if(!this.o.keyboardNavigation)break;b=37==a.keyCode?-1:1,a.ctrlKey?(c=this.moveYear(this.date,b),d=this.moveYear(this.viewDate,b)):a.shiftKey?(c=this.moveMonth(this.date,b),d=this.moveMonth(this.viewDate,b)):(c=new Date(this.date),c.setUTCDate(this.date.getUTCDate()+b),d=new Date(this.viewDate),d.setUTCDate(this.viewDate.getUTCDate()+b)),this.dateWithinRange(c)&&(this.date=c,this.viewDate=d,this.setValue(),this.update(),a.preventDefault(),e=!0);break;case 38:case 40:if(!this.o.keyboardNavigation)break;b=38==a.keyCode?-1:1,a.ctrlKey?(c=this.moveYear(this.date,b),d=this.moveYear(this.viewDate,b)):a.shiftKey?(c=this.moveMonth(this.date,b),d=this.moveMonth(this.viewDate,b)):(c=new Date(this.date),c.setUTCDate(this.date.getUTCDate()+7*b),d=new Date(this.viewDate),d.setUTCDate(this.viewDate.getUTCDate()+7*b)),this.dateWithinRange(c)&&(this.date=c,this.viewDate=d,this.setValue(),this.update(),a.preventDefault(),e=!0);break;case 13:this.hide(),a.preventDefault();break;case 9:this.hide()}if(e){this._trigger("changeDate");var f;this.isInput?f=this.element:this.component&&(f=this.element.find("input")),f&&f.change()}},showMode:function(a){a&&(this.viewMode=Math.max(this.o.minViewMode,Math.min(2,this.viewMode+a))),this.picker.find(">div").hide().filter(".datepicker-"+l.modes[this.viewMode].clsName).css("display","block"),this.updateNavArrows()}};var f=function(b,c){this.element=a(b),this.inputs=a.map(c.inputs,function(a){return a.jquery?a[0]:a}),delete c.inputs,a(this.inputs).datepicker(c).bind("changeDate",a.proxy(this.dateUpdated,this)),this.pickers=a.map(this.inputs,function(b){return a(b).data("datepicker")}),this.updateDates()};f.prototype={updateDates:function(){this.dates=a.map(this.pickers,function(a){return a.date}),this.updateRanges()},updateRanges:function(){var b=a.map(this.dates,function(a){return a.valueOf()});a.each(this.pickers,function(a,c){c.setRange(b)})},dateUpdated:function(b){var c=a(b.target).data("datepicker"),d=c.getUTCDate(),e=a.inArray(b.target,this.inputs),f=this.inputs.length;if(-1!=e){if(d<this.dates[e])for(;e>=0&&d<this.dates[e];)this.pickers[e--].setUTCDate(d);else if(d>this.dates[e])for(;f>e&&d>this.dates[e];)this.pickers[e++].setUTCDate(d);this.updateDates()}},remove:function(){a.map(this.pickers,function(a){a.remove()}),delete this.element.data().datepicker}};var g=a.fn.datepicker,h=a.fn.datepicker=function(b){var g=Array.apply(null,arguments);g.shift();var h;return this.each(function(){var j=a(this),k=j.data("datepicker"),l="object"==typeof b&&b;if(!k){var m=c(this,"date"),n=a.extend({},i,m,l),o=d(n.language),p=a.extend({},i,o,m,l);if(j.is(".input-daterange")||p.inputs){var q={inputs:p.inputs||j.find("input").toArray()};j.data("datepicker",k=new f(this,a.extend(p,q)))}else j.data("datepicker",k=new e(this,p))}return"string"==typeof b&&"function"==typeof k[b]&&(h=k[b].apply(k,g),void 0!==h)?!1:void 0;
+}),void 0!==h?h:this},i=a.fn.datepicker.defaults={autoclose:!1,beforeShowDay:a.noop,calendarWeeks:!1,clearBtn:!1,daysOfWeekDisabled:[],endDate:1/0,forceParse:!0,format:"mm/dd/yyyy",keyboardNavigation:!0,language:"en",minViewMode:0,rtl:!1,startDate:-(1/0),startView:0,todayBtn:!1,todayHighlight:!1,weekStart:0},j=a.fn.datepicker.locale_opts=["format","rtl","weekStart"];a.fn.datepicker.Constructor=e;var k=a.fn.datepicker.dates={en:{days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat","Sun"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa","Su"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today",clear:"Clear"}},l={modes:[{clsName:"days",navFnc:"Month",navStep:1},{clsName:"months",navFnc:"FullYear",navStep:1},{clsName:"years",navFnc:"FullYear",navStep:10}],isLeapYear:function(a){return a%4===0&&a%100!==0||a%400===0},getDaysInMonth:function(a,b){return[31,l.isLeapYear(a)?29:28,31,30,31,30,31,31,30,31,30,31][b]},validParts:/dd?|DD?|mm?|MM?|yy(?:yy)?/g,nonpunctuation:/[^ -\/:-@\[\u3400-\u9fff-`{-~\t\n\r]+/g,parseFormat:function(a){var b=a.replace(this.validParts,"\x00").split("\x00"),c=a.match(this.validParts);if(!b||!b.length||!c||0===c.length)throw new Error("Invalid date format.");return{separators:b,parts:c}},parseDate:function(c,d,f){if(c instanceof Date)return c;if("string"==typeof d&&(d=l.parseFormat(d)),/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/.test(c)){var g,h,i=/([\-+]\d+)([dmwy])/,j=c.match(/([\-+]\d+)([dmwy])/g);c=new Date;for(var m=0;m<j.length;m++)switch(g=i.exec(j[m]),h=parseInt(g[1]),g[2]){case"d":c.setUTCDate(c.getUTCDate()+h);break;case"m":c=e.prototype.moveMonth.call(e.prototype,c,h);break;case"w":c.setUTCDate(c.getUTCDate()+7*h);break;case"y":c=e.prototype.moveYear.call(e.prototype,c,h)}return b(c.getUTCFullYear(),c.getUTCMonth(),c.getUTCDate(),0,0,0)}var n,o,g,j=c&&c.match(this.nonpunctuation)||[],c=new Date,p={},q=["yyyy","yy","M","MM","m","mm","d","dd"],r={yyyy:function(a,b){return a.setUTCFullYear(b)},yy:function(a,b){return a.setUTCFullYear(2e3+b)},m:function(a,b){for(b-=1;0>b;)b+=12;for(b%=12,a.setUTCMonth(b);a.getUTCMonth()!=b;)a.setUTCDate(a.getUTCDate()-1);return a},d:function(a,b){return a.setUTCDate(b)}};r.M=r.MM=r.mm=r.m,r.dd=r.d,c=b(c.getFullYear(),c.getMonth(),c.getDate(),0,0,0);var s=d.parts.slice();if(j.length!=s.length&&(s=a(s).filter(function(b,c){return-1!==a.inArray(c,q)}).toArray()),j.length==s.length){for(var m=0,t=s.length;t>m;m++){if(n=parseInt(j[m],10),g=s[m],isNaN(n))switch(g){case"MM":o=a(k[f].months).filter(function(){var a=this.slice(0,j[m].length),b=j[m].slice(0,a.length);return a==b}),n=a.inArray(o[0],k[f].months)+1;break;case"M":o=a(k[f].monthsShort).filter(function(){var a=this.slice(0,j[m].length),b=j[m].slice(0,a.length);return a==b}),n=a.inArray(o[0],k[f].monthsShort)+1}p[g]=n}for(var u,m=0;m<q.length;m++)u=q[m],u in p&&!isNaN(p[u])&&r[u](c,p[u])}return c},formatDate:function(b,c,d){"string"==typeof c&&(c=l.parseFormat(c));var e={d:b.getUTCDate(),D:k[d].daysShort[b.getUTCDay()],DD:k[d].days[b.getUTCDay()],m:b.getUTCMonth()+1,M:k[d].monthsShort[b.getUTCMonth()],MM:k[d].months[b.getUTCMonth()],yy:b.getUTCFullYear().toString().substring(2),yyyy:b.getUTCFullYear()};e.dd=(e.d<10?"0":"")+e.d,e.mm=(e.m<10?"0":"")+e.m;for(var b=[],f=a.extend([],c.separators),g=0,h=c.parts.length;h>=g;g++)f.length&&b.push(f.shift()),b.push(e[c.parts[g]]);return b.join("")},headTemplate:'<thead><tr><th class="prev"><i class="icon-arrow-left"/></th><th colspan="5" class="datepicker-switch"></th><th class="next"><i class="icon-arrow-right"/></th></tr></thead>',contTemplate:'<tbody><tr><td colspan="7"></td></tr></tbody>',footTemplate:'<tfoot><tr><th colspan="7" class="today"></th></tr><tr><th colspan="7" class="clear"></th></tr></tfoot>'};l.template='<div class="datepicker"><div class="datepicker-days"><table class=" table-condensed">'+l.headTemplate+"<tbody></tbody>"+l.footTemplate+'</table></div><div class="datepicker-months"><table class="table-condensed">'+l.headTemplate+l.contTemplate+l.footTemplate+'</table></div><div class="datepicker-years"><table class="table-condensed">'+l.headTemplate+l.contTemplate+l.footTemplate+"</table></div></div>",a.fn.datepicker.DPGlobal=l,a.fn.datepicker.noConflict=function(){return a.fn.datepicker=g,this},a(document).on("focus.datepicker.data-api click.datepicker.data-api",'[data-provide="datepicker"]',function(b){var c=a(this);c.data("datepicker")||(b.preventDefault(),h.call(c,"show"))}),a(function(){h.call(a('[data-provide="datepicker-inline"]'))})}(window.jQuery),function(a){"use strict";a.fn.bdatepicker=a.fn.datepicker.noConflict(),a.fn.datepicker||(a.fn.datepicker=a.fn.bdatepicker);var b=function(a){this.init("date",a,b.defaults),this.initPicker(a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{initPicker:function(b,c){this.options.viewformat||(this.options.viewformat=this.options.format),b.datepicker=a.fn.editableutils.tryParseJson(b.datepicker,!0),this.options.datepicker=a.extend({},c.datepicker,b.datepicker,{format:this.options.viewformat}),this.options.datepicker.language=this.options.datepicker.language||"en",this.dpg=a.fn.bdatepicker.DPGlobal,this.parsedFormat=this.dpg.parseFormat(this.options.format),this.parsedViewFormat=this.dpg.parseFormat(this.options.viewformat)},render:function(){this.$input.bdatepicker(this.options.datepicker),this.options.clear&&(this.$clear=a('<a href="#"></a>').html(this.options.clear).click(a.proxy(function(a){a.preventDefault(),a.stopPropagation(),this.clear()},this)),this.$tpl.parent().append(a('<div class="editable-clear">').append(this.$clear)))},value2html:function(a,c){var d=a?this.dpg.formatDate(a,this.parsedViewFormat,this.options.datepicker.language):"";b.superclass.value2html.call(this,d,c)},html2value:function(a){return this.parseDate(a,this.parsedViewFormat)},value2str:function(a){return a?this.dpg.formatDate(a,this.parsedFormat,this.options.datepicker.language):""},str2value:function(a){return this.parseDate(a,this.parsedFormat)},value2submit:function(a){return this.value2str(a)},value2input:function(a){this.$input.bdatepicker("update",a)},input2value:function(){return this.$input.data("datepicker").date},activate:function(){},clear:function(){this.$input.data("datepicker").date=null,this.$input.find(".active").removeClass("active"),this.options.showbuttons||this.$input.closest("form").submit()},autosubmit:function(){this.$input.on("mouseup",".day",function(b){if(!a(b.currentTarget).is(".old")&&!a(b.currentTarget).is(".new")){var c=a(this).closest("form");setTimeout(function(){c.submit()},200)}})},parseDate:function(a,b){var c,d=null;return a&&(d=this.dpg.parseDate(a,b,this.options.datepicker.language),"string"==typeof a&&(c=this.dpg.formatDate(d,b,this.options.datepicker.language),a!==c&&(d=null))),d}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{tpl:'<div class="editable-date well"></div>',inputclass:null,format:"yyyy-mm-dd",viewformat:null,datepicker:{weekStart:0,startView:0,minViewMode:0,autoclose:!1},clear:"&times; clear"}),a.fn.editabletypes.date=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("datefield",a,b.defaults),this.initPicker(a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.date),a.extend(b.prototype,{render:function(){this.$input=this.$tpl.find("input"),this.setClass(),this.setAttr("placeholder"),this.$input.bdatepicker(this.options.datepicker),this.$input.off("focus keydown"),this.$input.keyup(a.proxy(function(){this.$tpl.removeData("date"),this.$tpl.bdatepicker("update")},this))},value2input:function(a){this.$input.val(a?this.dpg.formatDate(a,this.parsedViewFormat,this.options.datepicker.language):""),this.$tpl.bdatepicker("update")},input2value:function(){return this.html2value(this.$input.val())},activate:function(){a.fn.editabletypes.text.prototype.activate.call(this)},autosubmit:function(){}}),b.defaults=a.extend({},a.fn.editabletypes.date.defaults,{tpl:'<div class="input-append date"><input type="text"/><span class="add-on"><i class="icon-th"></i></span></div>',inputclass:"input-small",datepicker:{weekStart:0,startView:0,minViewMode:0,autoclose:!0}}),a.fn.editabletypes.datefield=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("datetime",a,b.defaults),this.initPicker(a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{initPicker:function(b,c){this.options.viewformat||(this.options.viewformat=this.options.format),b.datetimepicker=a.fn.editableutils.tryParseJson(b.datetimepicker,!0),this.options.datetimepicker=a.extend({},c.datetimepicker,b.datetimepicker,{format:this.options.viewformat}),this.options.datetimepicker.language=this.options.datetimepicker.language||"en",this.dpg=a.fn.datetimepicker.DPGlobal,this.parsedFormat=this.dpg.parseFormat(this.options.format,this.options.formatType),this.parsedViewFormat=this.dpg.parseFormat(this.options.viewformat,this.options.formatType)},render:function(){this.$input.datetimepicker(this.options.datetimepicker),this.$input.on("changeMode",function(b){var c=a(this).closest("form").parent();setTimeout(function(){c.triggerHandler("resize")},0)}),this.options.clear&&(this.$clear=a('<a href="#"></a>').html(this.options.clear).click(a.proxy(function(a){a.preventDefault(),a.stopPropagation(),this.clear()},this)),this.$tpl.parent().append(a('<div class="editable-clear">').append(this.$clear)))},value2html:function(a,c){var d=a?this.dpg.formatDate(this.toUTC(a),this.parsedViewFormat,this.options.datetimepicker.language,this.options.formatType):"";return c?void b.superclass.value2html.call(this,d,c):d},html2value:function(a){var b=this.parseDate(a,this.parsedViewFormat);return b?this.fromUTC(b):null},value2str:function(a){return a?this.dpg.formatDate(this.toUTC(a),this.parsedFormat,this.options.datetimepicker.language,this.options.formatType):""},str2value:function(a){var b=this.parseDate(a,this.parsedFormat);return b?this.fromUTC(b):null},value2submit:function(a){return this.value2str(a)},value2input:function(a){a&&this.$input.data("datetimepicker").setDate(a)},input2value:function(){var a=this.$input.data("datetimepicker");return a.date?a.getDate():null},activate:function(){},clear:function(){this.$input.data("datetimepicker").date=null,this.$input.find(".active").removeClass("active"),this.options.showbuttons||this.$input.closest("form").submit()},autosubmit:function(){this.$input.on("mouseup",".minute",function(b){var c=a(this).closest("form");setTimeout(function(){c.submit()},200)})},toUTC:function(a){return a?new Date(a.valueOf()-6e4*a.getTimezoneOffset()):a},fromUTC:function(a){return a?new Date(a.valueOf()+6e4*a.getTimezoneOffset()):a},parseDate:function(a,b){var c,d=null;return a&&(d=this.dpg.parseDate(a,b,this.options.datetimepicker.language,this.options.formatType),"string"==typeof a&&(c=this.dpg.formatDate(d,b,this.options.datetimepicker.language,this.options.formatType),a!==c&&(d=null))),d}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{tpl:'<div class="editable-date well"></div>',inputclass:null,format:"yyyy-mm-dd hh:ii",formatType:"standard",viewformat:null,datetimepicker:{todayHighlight:!1,autoclose:!1},clear:"&times; clear"}),a.fn.editabletypes.datetime=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("datetimefield",a,b.defaults),this.initPicker(a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.datetime),a.extend(b.prototype,{render:function(){this.$input=this.$tpl.find("input"),this.setClass(),this.setAttr("placeholder"),this.$tpl.datetimepicker(this.options.datetimepicker),this.$input.off("focus keydown"),this.$input.keyup(a.proxy(function(){this.$tpl.removeData("date"),this.$tpl.datetimepicker("update")},this))},value2input:function(a){this.$input.val(this.value2html(a)),this.$tpl.datetimepicker("update")},input2value:function(){return this.html2value(this.$input.val())},activate:function(){a.fn.editabletypes.text.prototype.activate.call(this)},autosubmit:function(){}}),b.defaults=a.extend({},a.fn.editabletypes.datetime.defaults,{tpl:'<div class="input-append date"><input type="text"/><span class="add-on"><i class="icon-th"></i></span></div>',inputclass:"input-medium",datetimepicker:{todayHighlight:!1,autoclose:!0}}),a.fn.editabletypes.datetimefield=b}(window.jQuery);
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/editable/bootstrap-table-editable.js b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/editable/bootstrap-table-editable.js
new file mode 100644
index 0000000..8bd108f
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/editable/bootstrap-table-editable.js
@@ -0,0 +1,189 @@
+/* eslint-disable no-unused-vars */
+/**
+ * @author zhixin wen <wenzhixin2010@gmail.com>
+ * extensions: https://github.com/vitalets/x-editable
+ */
+
+var Utils = $.fn.bootstrapTable.utils
+
+$.extend($.fn.bootstrapTable.defaults, {
+  editable: true,
+  onEditableInit () {
+    return false
+  },
+  onEditableSave (field, row, rowIndex, oldValue, $el) {
+    return false
+  },
+  onEditableShown (field, row, $el, editable) {
+    return false
+  },
+  onEditableHidden (field, row, $el, reason) {
+    return false
+  }
+})
+
+$.extend($.fn.bootstrapTable.columnDefaults, {
+  alwaysUseFormatter: false
+})
+
+$.extend($.fn.bootstrapTable.events, {
+  'editable-init.bs.table': 'onEditableInit',
+  'editable-save.bs.table': 'onEditableSave',
+  'editable-shown.bs.table': 'onEditableShown',
+  'editable-hidden.bs.table': 'onEditableHidden'
+})
+
+$.BootstrapTable = class extends $.BootstrapTable {
+  initTable () {
+    super.initTable()
+
+    if (!this.options.editable) {
+      return
+    }
+
+    this.editedCells = []
+    $.each(this.columns, (i, column) => {
+      if (!column.editable) {
+        return
+      }
+
+      const editableOptions = {}
+      const editableDataMarkup = []
+      const editableDataPrefix = 'editable-'
+      const processDataOptions = (key, value) => {
+        // Replace camel case with dashes.
+        const dashKey = key.replace(/([A-Z])/g, $1 => `-${$1.toLowerCase()}`)
+
+        if (dashKey.indexOf(editableDataPrefix) === 0) {
+          editableOptions[dashKey.replace(editableDataPrefix, 'data-')] = value
+        }
+      }
+
+      $.each(this.options, processDataOptions)
+
+      column.formatter = column.formatter || (value => value)
+      column._formatter = column._formatter ? column._formatter : column.formatter
+      column.formatter = (value, row, index, field) => {
+        let result = Utils.calculateObjectValue(column, column._formatter, [value, row, index], value)
+
+        result = typeof result === 'undefined' || result === null ? this.options.undefinedText : result
+        if (this.options.uniqueId !== undefined && !column.alwaysUseFormatter) {
+          const uniqueId = Utils.getItemField(row, this.options.uniqueId, false)
+
+          if ($.inArray(column.field + uniqueId, this.editedCells) !== -1) {
+            result = value
+          }
+        }
+
+        $.each(column, processDataOptions)
+
+        $.each(editableOptions, (key, value) => {
+          editableDataMarkup.push(` ${key}="${value}"`)
+        })
+
+        let noEditFormatter = false
+        const editableOpts = Utils.calculateObjectValue(column,
+          column.editable, [index, row], {})
+
+        if (editableOpts.hasOwnProperty('noEditFormatter')) {
+          noEditFormatter = editableOpts.noEditFormatter(value, row, index, field)
+        }
+
+        if (noEditFormatter === false) {
+          return `<a href="javascript:void(0)"
+            data-name="${column.field}"
+            data-pk="${row[this.options.idField]}"
+            data-value="${result}"
+            ${editableDataMarkup.join('')}></a>`
+        }
+        return noEditFormatter
+      }
+    })
+  }
+
+  initBody (fixedScroll) {
+    super.initBody(fixedScroll)
+
+    if (!this.options.editable) {
+      return
+    }
+
+    $.each(this.columns, (i, column) => {
+      if (!column.editable) {
+        return
+      }
+
+      const data = this.getData({ escape: true })
+      const $field = this.$body.find(`a[data-name="${column.field}"]`)
+
+      $field.each((i, element) => {
+        const $element = $(element)
+        const $tr = $element.closest('tr')
+        const index = $tr.data('index')
+        const row = data[index]
+
+        const editableOpts = Utils.calculateObjectValue(column,
+          column.editable, [index, row, $element], {})
+
+        $element.editable(editableOpts)
+      })
+
+      $field.off('save').on('save', ({ currentTarget }, { submitValue }) => {
+        const $this = $(currentTarget)
+        const data = this.getData()
+        const rowIndex = $this.parents('tr[data-index]').data('index')
+        const row = data[rowIndex]
+        const oldValue = row[column.field]
+
+        if (this.options.uniqueId !== undefined && !column.alwaysUseFormatter) {
+          const uniqueId = Utils.getItemField(row, this.options.uniqueId, false)
+
+          if ($.inArray(column.field + uniqueId, this.editedCells) === -1) {
+            this.editedCells.push(column.field + uniqueId)
+          }
+        }
+
+        submitValue = Utils.escapeHTML(submitValue)
+        $this.data('value', submitValue)
+        row[column.field] = submitValue
+        this.trigger('editable-save', column.field, row, rowIndex, oldValue, $this)
+        this.initBody()
+      })
+
+      $field.off('shown').on('shown', ({ currentTarget }, editable) => {
+        const $this = $(currentTarget)
+        const data = this.getData()
+        const rowIndex = $this.parents('tr[data-index]').data('index')
+        const row = data[rowIndex]
+
+        this.trigger('editable-shown', column.field, row, $this, editable)
+      })
+
+      $field.off('hidden').on('hidden', ({ currentTarget }, reason) => {
+        const $this = $(currentTarget)
+        const data = this.getData()
+        const rowIndex = $this.parents('tr[data-index]').data('index')
+        const row = data[rowIndex]
+
+        this.trigger('editable-hidden', column.field, row, $this, reason)
+      })
+    })
+    this.trigger('editable-init')
+  }
+
+  getData (params) {
+    const data = super.getData(params)
+
+    if (params && params.escape) {
+      for (const row of data) {
+        for (const [key, value] of Object.entries(row)) {
+          if (typeof(value) !== "number") {
+              row[key] = Utils.unescapeHTML(value)
+          }
+        }
+      }
+    }
+
+    return data
+  }
+}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/editable/clear.png b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/editable/clear.png
new file mode 100644
index 0000000..a3d7124
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/editable/clear.png
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/editable/loading.gif b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/editable/loading.gif
new file mode 100644
index 0000000..5b33f7e
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/editable/loading.gif
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/export/bootstrap-table-export.js b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/export/bootstrap-table-export.js
new file mode 100644
index 0000000..8a732a0
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/export/bootstrap-table-export.js
@@ -0,0 +1,335 @@
+/**
+ * @author zhixin wen <wenzhixin2010@gmail.com>
+ * extensions: https://github.com/hhurz/tableExport.jquery.plugin
+ */
+
+var Utils = $.fn.bootstrapTable.utils
+
+const TYPE_NAME = {
+  json: 'JSON',
+  xml: 'XML',
+  png: 'PNG',
+  csv: 'CSV',
+  txt: 'TXT',
+  sql: 'SQL',
+  doc: 'MS-Word',
+  excel: 'MS-Excel',
+  xlsx: 'MS-Excel (OpenXML)',
+  powerpoint: 'MS-Powerpoint',
+  pdf: 'PDF'
+}
+
+Object.assign($.fn.bootstrapTable.defaults, {
+  showExport: false,
+  exportDataType: 'basic', // basic, all, selected
+  exportTypes: ['json', 'xml', 'csv', 'txt', 'sql', 'excel'],
+  exportOptions: {},
+  exportFooter: false
+})
+
+Object.assign($.fn.bootstrapTable.columnDefaults, {
+  forceExport: false,
+  forceHide: false
+})
+
+Object.assign($.fn.bootstrapTable.defaults.icons, {
+  export: {
+    bootstrap3: 'glyphicon-export icon-share',
+    bootstrap5: 'bi-download',
+    materialize: 'file_download',
+    'bootstrap-table': 'icon-download'
+  }[$.fn.bootstrapTable.theme] || 'fa-download'
+})
+
+Object.assign($.fn.bootstrapTable.locales, {
+  formatExport () {
+    return 'Export data'
+  }
+})
+Object.assign($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales)
+
+$.fn.bootstrapTable.methods.push('exportTable')
+
+Object.assign($.fn.bootstrapTable.defaults, {
+  // eslint-disable-next-line no-unused-vars
+  onExportSaved (exportedRows) {
+    return false
+  },
+  onExportStarted () {
+    return false
+  }
+})
+
+Object.assign($.fn.bootstrapTable.events, {
+  'export-saved.bs.table': 'onExportSaved',
+  'export-started.bs.table': 'onExportStarted'
+})
+
+$.BootstrapTable = class extends $.BootstrapTable {
+  initToolbar (...args) {
+    const o = this.options
+    let exportTypes = o.exportTypes
+
+    this.showToolbar = this.showToolbar || o.showExport
+
+    if (this.options.showExport) {
+
+      if (typeof exportTypes === 'string') {
+        const types = exportTypes.slice(1, -1).replace(/ /g, '').split(',')
+
+        exportTypes = types.map(t => t.slice(1, -1))
+      }
+
+      if (typeof o.exportOptions === 'string') {
+        o.exportOptions = Utils.calculateObjectValue(null, o.exportOptions)
+      }
+
+      this.$export = this.$toolbar.find('>.columns div.export')
+      if (this.$export.length) {
+        this.updateExportButton()
+        return
+      }
+
+      this.buttons = Object.assign(this.buttons, {
+        export: {
+          html:
+            () => {
+              if (exportTypes.length === 1) {
+                return `
+                  <div class="export ${this.constants.classes.buttonsDropdown}"
+                  data-type="${exportTypes[0]}">
+                  <button class="${this.constants.buttonsClass}"
+                  aria-label="${o.formatExport()}"
+                  type="button"
+                  title="${o.formatExport()}">
+                  ${o.showButtonIcons ? Utils.sprintf(this.constants.html.icon, o.iconsPrefix, o.icons.export) : ''}
+                  ${o.showButtonText ? o.formatExport() : ''}
+                  </button>
+                  </div>
+                `
+              }
+
+              const html = []
+
+              html.push(`
+                <div class="export ${this.constants.classes.buttonsDropdown}">
+                <button class="${this.constants.buttonsClass} dropdown-toggle"
+                aria-label="${o.formatExport()}"
+                ${this.constants.dataToggle}="dropdown"
+                type="button"
+                title="${o.formatExport()}">
+                ${o.showButtonIcons ? Utils.sprintf(this.constants.html.icon, o.iconsPrefix, o.icons.export) : ''}
+                ${o.showButtonText ? o.formatExport() : ''}
+                ${this.constants.html.dropdownCaret}
+                </button>
+                ${this.constants.html.toolbarDropdown[0]}
+              `)
+
+              for (const type of exportTypes) {
+                if (TYPE_NAME.hasOwnProperty(type)) {
+                  const $item = $(Utils.sprintf(this.constants.html.pageDropdownItem, '', TYPE_NAME[type]))
+
+                  $item.attr('data-type', type)
+                  html.push($item.prop('outerHTML'))
+                }
+              }
+
+              html.push(this.constants.html.toolbarDropdown[1], '</div>')
+              return html.join('')
+            }
+        }
+      })
+    }
+
+    super.initToolbar(...args)
+    this.$export = this.$toolbar.find('>.columns div.export')
+
+    if (!this.options.showExport) {
+      return
+    }
+
+    this.updateExportButton()
+    let $exportButtons = this.$export.find('[data-type]')
+
+    if (exportTypes.length === 1) {
+      $exportButtons = this.$export
+    }
+
+    $exportButtons.click(e => {
+      e.preventDefault()
+      this.trigger('export-started')
+      this.exportTable({
+        type: $(e.currentTarget).data('type')
+      })
+    })
+    this.handleToolbar()
+  }
+
+  handleToolbar () {
+    if (!this.$export) {
+      return
+    }
+
+    if (super.handleToolbar) {
+      super.handleToolbar()
+    }
+  }
+
+  exportTable (options) {
+    const o = this.options
+    const stateField = this.header.stateField
+    const isCardView = o.cardView
+
+    const doExport = callback => {
+      if (stateField) {
+        this.hideColumn(stateField)
+      }
+      if (isCardView) {
+        this.toggleView()
+      }
+
+      this.columns.forEach(row => {
+        if (row.forceHide) {
+          this.hideColumn(row.field)
+        }
+      })
+
+      const data = this.getData()
+
+      if (o.detailView && o.detailViewIcon) {
+        const detailViewIndex = o.detailViewAlign === 'left' ? 0 : this.getVisibleFields().length + Utils.getDetailViewIndexOffset(this.options)
+
+        o.exportOptions.ignoreColumn = [detailViewIndex].concat(o.exportOptions.ignoreColumn || [])
+      }
+
+      if (o.exportFooter && o.height) {
+        const $footerRow = this.$tableFooter.find('tr').first()
+        const footerData = {}
+        const footerHtml = []
+
+        $.each($footerRow.children(), (index, footerCell) => {
+          const footerCellHtml = $(footerCell).children('.th-inner').first().html()
+
+          footerData[this.columns[index].field] = footerCellHtml === '&nbsp;' ? null : footerCellHtml
+
+          // grab footer cell text into cell index-based array
+          footerHtml.push(footerCellHtml)
+        })
+
+        this.$body.append(this.$body.children().last()[0].outerHTML)
+        const $lastTableRow = this.$body.children().last()
+
+        $.each($lastTableRow.children(), (index, lastTableRowCell) => {
+          $(lastTableRowCell).html(footerHtml[index])
+        })
+      }
+
+      const hiddenColumns = this.getHiddenColumns()
+
+      hiddenColumns.forEach(row => {
+        if (row.forceExport) {
+          this.showColumn(row.field)
+        }
+      })
+
+      if (typeof o.exportOptions.fileName === 'function') {
+        options.fileName = o.exportOptions.fileName()
+      }
+
+      this.$el.tableExport(Utils.extend({
+        onAfterSaveToFile: () => {
+          if (o.exportFooter) {
+            this.load(data)
+          }
+
+          if (stateField) {
+            this.showColumn(stateField)
+          }
+          if (isCardView) {
+            this.toggleView()
+          }
+
+          hiddenColumns.forEach(row => {
+            if (row.forceExport) {
+              this.hideColumn(row.field)
+            }
+          })
+
+          this.columns.forEach(row => {
+            if (row.forceHide) {
+              this.showColumn(row.field)
+            }
+          })
+
+          if (callback) callback()
+        }
+      }, o.exportOptions, options))
+    }
+
+    if (o.exportDataType === 'all' && o.pagination) {
+      const eventName = o.sidePagination === 'server' ?
+        'post-body.bs.table' : 'page-change.bs.table'
+      const virtualScroll = this.options.virtualScroll
+
+      this.$el.one(eventName, () => {
+        setTimeout(() => {
+          const data = this.getData()
+
+          doExport(() => {
+            this.options.virtualScroll = virtualScroll
+            this.togglePagination()
+          })
+          this.trigger('export-saved', data)
+        }, 0)
+      })
+      this.options.virtualScroll = false
+      this.togglePagination()
+    } else if (o.exportDataType === 'selected') {
+      let data = this.getData()
+      let selectedData = this.getSelections()
+      const pagination = o.pagination
+
+      if (!selectedData.length) {
+        return
+      }
+
+      if (o.sidePagination === 'server') {
+        data = {
+          total: o.totalRows,
+          [this.options.dataField]: data
+        }
+        selectedData = {
+          total: selectedData.length,
+          [this.options.dataField]: selectedData
+        }
+      }
+
+      this.load(selectedData)
+      if (pagination) {
+        this.togglePagination()
+      }
+      doExport(() => {
+        if (pagination) {
+          this.togglePagination()
+        }
+        this.load(data)
+      })
+      this.trigger('export-saved', selectedData)
+    } else {
+      doExport()
+      this.trigger('export-saved', this.getData(true))
+    }
+  }
+
+  updateSelected () {
+    super.updateSelected()
+    this.updateExportButton()
+  }
+
+  updateExportButton () {
+    if (this.options.exportDataType === 'selected') {
+      this.$export.find('> button')
+        .prop('disabled', !this.getSelections().length)
+    }
+  }
+}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/export/tableExport.min.js b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/export/tableExport.min.js
new file mode 100644
index 0000000..ec046c3
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/export/tableExport.min.js
@@ -0,0 +1,92 @@
+/*
+ tableExport.jquery.plugin
+ Version 1.10.24
+ Copyright (c) 2015-2021 hhurz, https://github.com/hhurz/tableExport.jquery.plugin
+ Based on https://github.com/kayalshri/tableExport.jquery.plugin
+ Licensed under the MIT License
+*/
+var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.findInternal=function(d,k,y){d instanceof String&&(d=String(d));for(var C=d.length,v=0;v<C;v++){var R=d[v];if(k.call(y,R,v,d))return{i:v,v:R}}return{i:-1,v:void 0}};$jscomp.ASSUME_ES5=!1;$jscomp.ASSUME_NO_NATIVE_MAP=!1;$jscomp.ASSUME_NO_NATIVE_SET=!1;$jscomp.defineProperty=$jscomp.ASSUME_ES5||"function"==typeof Object.defineProperties?Object.defineProperty:function(d,k,y){d!=Array.prototype&&d!=Object.prototype&&(d[k]=y.value)};
+$jscomp.getGlobal=function(d){return"undefined"!=typeof window&&window===d?d:"undefined"!=typeof global&&null!=global?global:d};$jscomp.global=$jscomp.getGlobal(this);$jscomp.polyfill=function(d,k,y,C){if(k){y=$jscomp.global;d=d.split(".");for(C=0;C<d.length-1;C++){var v=d[C];v in y||(y[v]={});y=y[v]}d=d[d.length-1];C=y[d];k=k(C);k!=C&&null!=k&&$jscomp.defineProperty(y,d,{configurable:!0,writable:!0,value:k})}};
+$jscomp.polyfill("Array.prototype.find",function(d){return d?d:function(d,y){return $jscomp.findInternal(this,d,y).v}},"es6","es3");
+(function(d){d.fn.tableExport=function(k){function y(b){var c=[];v(b,"thead").each(function(){c.push.apply(c,v(d(this),a.theadSelector).toArray())});return c}function C(b){var c=[];v(b,"tbody").each(function(){c.push.apply(c,v(d(this),a.tbodySelector).toArray())});a.tfootSelector.length&&v(b,"tfoot").each(function(){c.push.apply(c,v(d(this),a.tfootSelector).toArray())});return c}function v(b,a){var c=b[0].tagName,q=b.parents(c).length;return b.find(a).filter(function(){return q===d(this).closest(c).parents(c).length})}
+function R(b){var a=[],e=0,q=0,f=0;d(b).find("thead").first().find("th").each(function(b,c){b=void 0!==d(c).attr("data-field");"undefined"!==typeof c.parentNode.rowIndex&&q!==c.parentNode.rowIndex&&(q=c.parentNode.rowIndex,e=f=0);var h=J(c);for(e+=h?h:1;f<e;)a[f]=b?d(c).attr("data-field"):f.toString(),f++});return a}function I(b){var a="undefined"!==typeof b[0].rowIndex,e=!1===a&&"undefined"!==typeof b[0].cellIndex,q=e||a?Ja(b):b.is(":visible"),f=b.attr("data-tableexport-display");e&&"none"!==f&&
+"always"!==f&&(b=d(b[0].parentNode),a="undefined"!==typeof b[0].rowIndex,f=b.attr("data-tableexport-display"));a&&"none"!==f&&"always"!==f&&(f=b.closest("table").attr("data-tableexport-display"));return"none"!==f&&(!0===q||"always"===f)}function Ja(b){var a=[];V&&(a=K.filter(function(){var a=!1;this.nodeType===b[0].nodeType&&("undefined"!==typeof this.rowIndex&&this.rowIndex===b[0].rowIndex?a=!0:"undefined"!==typeof this.cellIndex&&this.cellIndex===b[0].cellIndex&&"undefined"!==typeof this.parentNode.rowIndex&&
+"undefined"!==typeof b[0].parentNode.rowIndex&&this.parentNode.rowIndex===b[0].parentNode.rowIndex&&(a=!0));return a}));return!1===V||0===a.length}function ta(b,c,e){var q=!1;I(b)?0<a.ignoreColumn.length&&(-1!==d.inArray(e,a.ignoreColumn)||-1!==d.inArray(e-c,a.ignoreColumn)||S.length>e&&"undefined"!==typeof S[e]&&-1!==d.inArray(S[e],a.ignoreColumn))&&(q=!0):q=!0;return q}function E(b,c,e,q,f){if("function"===typeof f){var h=!1;"function"===typeof a.onIgnoreRow&&(h=a.onIgnoreRow(d(b),e));if(!1===h&&
+(0===a.ignoreRow.length||-1===d.inArray(e,a.ignoreRow)&&-1===d.inArray(e-q,a.ignoreRow))&&I(d(b))){b=v(d(b),c);var n=b.length,l=0,u=0;b.each(function(){var b=d(this),a=J(this),c=T(this),h;d.each(G,function(){if(e>this.s.r&&e<=this.e.r&&l>=this.s.c&&l<=this.e.c)for(h=0;h<=this.e.c-this.s.c;++h)n++,u++,f(null,e,l++)});if(c||a)a=a||1,G.push({s:{r:e,c:l},e:{r:e+(c||1)-1,c:l+a-1}});!1===ta(b,n,u++)&&f(this,e,l++);if(1<a)for(h=0;h<a-1;++h)u++,f(null,e,l++)});d.each(G,function(){if(e>=this.s.r&&e<=this.e.r&&
+l>=this.s.c&&l<=this.e.c)for(ea=0;ea<=this.e.c-this.s.c;++ea)f(null,e,l++)})}}}function ua(b,a,e,d){if("undefined"!==typeof d.images&&(e=d.images[e],"undefined"!==typeof e)){a=a.getBoundingClientRect();var c=b.width/b.height,h=a.width/a.height,q=b.width,l=b.height,u=19.049976/25.4,g=0;h<=c?(l=Math.min(b.height,a.height),q=a.width*l/a.height):h>c&&(q=Math.min(b.width,a.width),l=a.height*q/a.width);q*=u;l*=u;l<b.height&&(g=(b.height-l)/2);try{d.doc.addImage(e.src,b.textPos.x,b.y+g,q,l)}catch(Pa){}b.textPos.x+=
+q}}function va(b,c){if("string"===a.outputMode)return b.output();if("base64"===a.outputMode)return L(b.output());if("window"===a.outputMode)window.URL=window.URL||window.webkitURL,window.open(window.URL.createObjectURL(b.output("blob")));else try{var e=b.output("blob");saveAs(e,a.fileName+".pdf")}catch(q){ka(a.fileName+".pdf","data:application/pdf"+(c?"":";base64")+",",c?b.output("blob"):b.output())}}function wa(b,a,e){var c=0;"undefined"!==typeof e&&(c=e.colspan);if(0<=c){for(var f=b.width,d=b.textPos.x,
+n=a.table.columns.indexOf(a.column),l=1;l<c;l++)f+=a.table.columns[n+l].width;1<c&&("right"===b.styles.halign?d=b.textPos.x+f-b.width:"center"===b.styles.halign&&(d=b.textPos.x+(f-b.width)/2));b.width=f;b.textPos.x=d;"undefined"!==typeof e&&1<e.rowspan&&(b.height*=e.rowspan);if("middle"===b.styles.valign||"bottom"===b.styles.valign)e=("string"===typeof b.text?b.text.split(/\r\n|\r|\n/g):b.text).length||1,2<e&&(b.textPos.y-=(2-1.15)/2*a.row.styles.fontSize*(e-2)/3);return!0}return!1}function xa(b,
+a,e){"undefined"!==typeof b&&null!==b&&(b.hasAttribute("data-tableexport-canvas")?(a=(new Date).getTime(),d(b).attr("data-tableexport-canvas",a),e.images[a]={url:'[data-tableexport-canvas="'+a+'"]',src:null}):"undefined"!==a&&null!=a&&a.each(function(){if(d(this).is("img")){var a=ya(this.src);e.images[a]={url:this.src,src:this.src}}xa(b,d(this).children(),e)}))}function Ka(b,a){function c(b){if(b.url)if(b.src){var c=new Image;q=++f;c.crossOrigin="Anonymous";c.onerror=c.onload=function(){if(c.complete&&
+(0===c.src.indexOf("data:image/")&&(c.width=b.width||c.width||0,c.height=b.height||c.height||0),c.width+c.height)){var e=document.createElement("canvas"),d=e.getContext("2d");e.width=c.width;e.height=c.height;d.drawImage(c,0,0);b.src=e.toDataURL("image/png")}--f||a(q)};c.src=b.url}else{var e=d(b.url);e.length&&(q=++f,html2canvas(e[0]).then(function(c){b.src=c.toDataURL("image/png");--f||a(q)}))}}var q=0,f=0;if("undefined"!==typeof b.images)for(var h in b.images)b.images.hasOwnProperty(h)&&c(b.images[h]);
+(b=f)||(a(q),b=void 0);return b}function za(b,c,e){c.each(function(){if(d(this).is("div")){var c=fa(M(this,"background-color"),[255,255,255]),f=fa(M(this,"border-top-color"),[0,0,0]),h=ha(this,"border-top-width",a.jspdf.unit),n=this.getBoundingClientRect(),l=this.offsetLeft*e.wScaleFactor,u=this.offsetTop*e.hScaleFactor,g=n.width*e.wScaleFactor;n=n.height*e.hScaleFactor;e.doc.setDrawColor.apply(void 0,f);e.doc.setFillColor.apply(void 0,c);e.doc.setLineWidth(h);e.doc.rect(b.x+l,b.y+u,g,n,h?"FD":"F")}else d(this).is("img")&&
+(c=ya(this.src),ua(b,this,c,e));za(b,d(this).children(),e)})}function Aa(b,c,e){if("function"===typeof e.onAutotableText)e.onAutotableText(e.doc,b,c);else{var q=b.textPos.x,f=b.textPos.y,h={halign:b.styles.halign,valign:b.styles.valign};if(c.length){for(c=c[0];c.previousSibling;)c=c.previousSibling;for(var n=!1,l=!1;c;){var u=c.innerText||c.textContent||"",g=u.length&&" "===u[0]?" ":"",k=1<u.length&&" "===u[u.length-1]?" ":"";!0!==a.preserve.leadingWS&&(u=g+la(u));!0!==a.preserve.trailingWS&&(u=ma(u)+
+k);d(c).is("br")&&(q=b.textPos.x,f+=e.doc.internal.getFontSize());d(c).is("b")?n=!0:d(c).is("i")&&(l=!0);(n||l)&&e.doc.setFontType(n&&l?"bolditalic":n?"bold":"italic");if(g=e.doc.getStringUnitWidth(u)*e.doc.internal.getFontSize()){"linebreak"===b.styles.overflow&&q>b.textPos.x&&q+g>b.textPos.x+b.width&&(0<=".,!%*;:=-".indexOf(u.charAt(0))&&(k=u.charAt(0),g=e.doc.getStringUnitWidth(k)*e.doc.internal.getFontSize(),q+g<=b.textPos.x+b.width&&(e.doc.autoTableText(k,q,f,h),u=u.substring(1,u.length)),g=
+e.doc.getStringUnitWidth(u)*e.doc.internal.getFontSize()),q=b.textPos.x,f+=e.doc.internal.getFontSize());if("visible"!==b.styles.overflow)for(;u.length&&q+g>b.textPos.x+b.width;)u=u.substring(0,u.length-1),g=e.doc.getStringUnitWidth(u)*e.doc.internal.getFontSize();e.doc.autoTableText(u,q,f,h);q+=g}if(n||l)d(c).is("b")?n=!1:d(c).is("i")&&(l=!1),e.doc.setFontType(n||l?n?"bold":"italic":"normal");c=c.nextSibling}b.textPos.x=q;b.textPos.y=f}else e.doc.autoTableText(b.text,b.textPos.x,b.textPos.y,h)}}
+function W(b,a,e){return null==b?"":b.toString().replace(new RegExp(null==a?"":a.toString().replace(/([.*+?^=!:${}()|\[\]\/\\])/g,"\\$1"),"g"),e)}function la(b){return null==b?"":b.toString().replace(/^\s+/,"")}function ma(b){return null==b?"":b.toString().replace(/\s+$/,"")}function La(b){if(0===a.date.html.length)return!1;a.date.pattern.lastIndex=0;var c=a.date.pattern.exec(b);if(null==c)return!1;b=+c[a.date.match_y];if(0>b||8099<b)return!1;var e=1*c[a.date.match_m];c=1*c[a.date.match_d];if(!isFinite(c))return!1;
+var d=new Date(b,e-1,c,0,0,0);return d.getFullYear()===b&&d.getMonth()===e-1&&d.getDate()===c?new Date(Date.UTC(b,e-1,c,0,0,0)):!1}function na(b){b=b||"0";""!==a.numbers.html.thousandsSeparator&&(b=W(b,a.numbers.html.thousandsSeparator,""));"."!==a.numbers.html.decimalMark&&(b=W(b,a.numbers.html.decimalMark,"."));return"number"===typeof b||!1!==jQuery.isNumeric(b)?b:!1}function Ma(b){-1<b.indexOf("%")?(b=na(b.replace(/%/g,"")),!1!==b&&(b/=100)):b=!1;return b}function D(b,c,e,q){var f="",h="text";
+if(null!==b){var n=d(b);n.removeData("teUserDefText");if(n[0].hasAttribute("data-tableexport-canvas"))var l="";else if(n[0].hasAttribute("data-tableexport-value"))l=(l=n.attr("data-tableexport-value"))?l+"":"",n.data("teUserDefText",1);else if(l=n.html(),"function"===typeof a.onCellHtmlData)l=a.onCellHtmlData(n,c,e,l),n.data("teUserDefText",1);else if(""!==l){b=d.parseHTML(l);var g=0,k=0;l="";d.each(b,function(){if(d(this).is("input"))l+=n.find("input").eq(g++).val();else if(d(this).is("select"))l+=
+n.find("select option:selected").eq(k++).text();else if(d(this).is("br"))l+="<br>";else{if("undefined"===typeof d(this).html())l+=d(this).text();else if(void 0===jQuery().bootstrapTable||!1===d(this).hasClass("fht-cell")&&!1===d(this).hasClass("filterControl")&&0===n.parents(".detail-view").length)l+=d(this).html();if(d(this).is("a")){var b=n.find("a").attr("href")||"";f="function"===typeof a.onCellHtmlHyperlink?f+a.onCellHtmlHyperlink(n,c,e,b,l):"href"===a.htmlHyperlink?f+b:f+l;l=""}}})}if(l&&""!==
+l&&!0===a.htmlContent)f=d.trim(l);else if(l&&""!==l)if(""!==n.attr("data-tableexport-cellformat")){var m=l.replace(/\n/g,"\u2028").replace(/(<\s*br([^>]*)>)/gi,"\u2060"),p=d("<div/>").html(m).contents();b=!1;m="";d.each(p.text().split("\u2028"),function(b,c){0<b&&(m+=" ");!0!==a.preserve.leadingWS&&(c=la(c));m+=!0!==a.preserve.trailingWS?ma(c):c});d.each(m.split("\u2060"),function(b,c){0<b&&(f+="\n");!0!==a.preserve.leadingWS&&(c=la(c));!0!==a.preserve.trailingWS&&(c=ma(c));f+=c.replace(/\u00AD/g,
+"")});f=f.replace(/\u00A0/g," ");if("json"===a.type||"excel"===a.type&&"xmlss"===a.mso.fileFormat||!1===a.numbers.output)b=na(f),!1!==b&&(h="number",f=Number(b));else if(a.numbers.html.decimalMark!==a.numbers.output.decimalMark||a.numbers.html.thousandsSeparator!==a.numbers.output.thousandsSeparator)if(b=na(f),!1!==b){p=(""+b.substr(0>b?1:0)).split(".");1===p.length&&(p[1]="");var t=3<p[0].length?p[0].length%3:0;h="number";f=(0>b?"-":"")+(a.numbers.output.thousandsSeparator?(t?p[0].substr(0,t)+a.numbers.output.thousandsSeparator:
+"")+p[0].substr(t).replace(/(\d{3})(?=\d)/g,"$1"+a.numbers.output.thousandsSeparator):p[0])+(p[1].length?a.numbers.output.decimalMark+p[1]:"")}}else f=l;!0===a.escape&&(f=escape(f));"function"===typeof a.onCellData&&(f=a.onCellData(n,c,e,f,h),n.data("teUserDefText",1))}void 0!==q&&(q.type=h);return f}function Ba(b){return 0<b.length&&!0===a.preventInjection&&0<="=+-@".indexOf(b.charAt(0))?"'"+b:b}function Na(b,a,e){return a+"-"+e.toLowerCase()}function fa(b,a){(b=/^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/.exec(b))&&
+(a=[parseInt(b[1]),parseInt(b[2]),parseInt(b[3])]);return a}function Ca(b){var a=M(b,"text-align"),e=M(b,"font-weight"),d=M(b,"font-style"),f="";"start"===a&&(a="rtl"===M(b,"direction")?"right":"left");700<=e&&(f="bold");"italic"===d&&(f+=d);""===f&&(f="normal");a={style:{align:a,bcolor:fa(M(b,"background-color"),[255,255,255]),color:fa(M(b,"color"),[0,0,0]),fstyle:f},colspan:J(b),rowspan:T(b)};null!==b&&(b=b.getBoundingClientRect(),a.rect={width:b.width,height:b.height});return a}function J(b){var a=
+d(b).attr("data-tableexport-colspan");"undefined"===typeof a&&d(b).is("[colspan]")&&(a=d(b).attr("colspan"));return parseInt(a)||0}function T(b){var a=d(b).attr("data-tableexport-rowspan");"undefined"===typeof a&&d(b).is("[rowspan]")&&(a=d(b).attr("rowspan"));return parseInt(a)||0}function M(a,c){try{return window.getComputedStyle?(c=c.replace(/([a-z])([A-Z])/,Na),window.getComputedStyle(a,null).getPropertyValue(c)):a.currentStyle?a.currentStyle[c]:a.style[c]}catch(e){}return""}function ha(a,c,e){c=
+M(a,c).match(/\d+/);if(null!==c){c=c[0];a=a.parentElement;var b=document.createElement("div");b.style.overflow="hidden";b.style.visibility="hidden";a.appendChild(b);b.style.width=100+e;e=100/b.offsetWidth;a.removeChild(b);return c*e}return 0}function Oa(a){for(var b=new ArrayBuffer(a.length),e=new Uint8Array(b),d=0;d!==a.length;++d)e[d]=a.charCodeAt(d)&255;return b}function oa(a){var b=a.c,e="";for(++b;b;b=Math.floor((b-1)/26))e=String.fromCharCode((b-1)%26+65)+e;return e+(""+(a.r+1))}function pa(a,
+c){if("undefined"===typeof c||"number"===typeof c)return pa(a.s,a.e);"string"!==typeof a&&(a=oa(a));"string"!==typeof c&&(c=oa(c));return a===c?a:a+":"+c}function Da(a,c){var b=Number(a);if(isFinite(b))return b;var d=1;""!==c.thousandsSeparator&&(a=a.replace(new RegExp("([\\d])"+c.thousandsSeparator+"([\\d])","g"),"$1$2"));"."!==c.decimalMark&&(a=a.replace(new RegExp("([\\d])"+c.decimalMark+"([\\d])","g"),"$1.$2"));a=a.replace(/[$]/g,"").replace(/[%]/g,function(){d*=100;return""});if(isFinite(b=Number(a)))return b/
+d;a=a.replace(/[(](.*)[)]/,function(a,b){d=-d;return b});return isFinite(b=Number(a))?b/d:b}function ya(a){var b=0,d;if(0===a.length)return b;var q=0;for(d=a.length;q<d;q++){var f=a.charCodeAt(q);b=(b<<5)-b+f;b|=0}return b}function N(b,c,d,q,f,h){var e=!0;"function"===typeof a.onBeforeSaveToFile&&(e=a.onBeforeSaveToFile(b,c,d,q,f),"boolean"!==typeof e&&(e=!0));if(e)try{if(Ea=new Blob([b],{type:d+";charset="+q}),saveAs(Ea,c,!1===h),"function"===typeof a.onAfterSaveToFile)a.onAfterSaveToFile(b,c)}catch(l){ka(c,
+"data:"+d+(q.length?";charset="+q:"")+(f.length?";"+f:"")+",",h?"\ufeff"+b:b)}}function ka(b,c,d){var e=window.navigator.userAgent;if(!1!==b&&window.navigator.msSaveOrOpenBlob)window.navigator.msSaveOrOpenBlob(new Blob([d]),b);else if(!1!==b&&(0<e.indexOf("MSIE ")||e.match(/Trident.*rv\:11\./))){if(c=document.createElement("iframe")){document.body.appendChild(c);c.setAttribute("style","display:none");c.contentDocument.open("txt/plain","replace");c.contentDocument.write(d);c.contentDocument.close();
+c.contentWindow.focus();switch(b.substr(b.lastIndexOf(".")+1)){case "doc":case "json":case "png":case "pdf":case "xls":case "xlsx":b+=".txt"}c.contentDocument.execCommand("SaveAs",!0,b);document.body.removeChild(c)}}else{var f=document.createElement("a");if(f){var h=null;f.style.display="none";!1!==b?f.download=b:f.target="_blank";"object"===typeof d?(window.URL=window.URL||window.webkitURL,e=[],e.push(d),h=window.URL.createObjectURL(new Blob(e,{type:c})),f.href=h):0<=c.toLowerCase().indexOf("base64,")?
+f.href=c+L(d):f.href=c+encodeURIComponent(d);document.body.appendChild(f);if(document.createEvent)null===ia&&(ia=document.createEvent("MouseEvents")),ia.initEvent("click",!0,!1),f.dispatchEvent(ia);else if(document.createEventObject)f.fireEvent("onclick");else if("function"===typeof f.onclick)f.onclick();setTimeout(function(){h&&window.URL.revokeObjectURL(h);document.body.removeChild(f);if("function"===typeof a.onAfterSaveToFile)a.onAfterSaveToFile(d,b)},100)}}}function L(a){var b,d="",q=0;if("string"===
+typeof a){a=a.replace(/\x0d\x0a/g,"\n");var f="";for(b=0;b<a.length;b++){var h=a.charCodeAt(b);128>h?f+=String.fromCharCode(h):(127<h&&2048>h?f+=String.fromCharCode(h>>6|192):(f+=String.fromCharCode(h>>12|224),f+=String.fromCharCode(h>>6&63|128)),f+=String.fromCharCode(h&63|128))}a=f}for(;q<a.length;){var n=a.charCodeAt(q++);f=a.charCodeAt(q++);b=a.charCodeAt(q++);h=n>>2;n=(n&3)<<4|f>>4;var l=(f&15)<<2|b>>6;var g=b&63;isNaN(f)?l=g=64:isNaN(b)&&(g=64);d=d+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(h)+
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(n)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(l)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(g)}return d}var a={csvEnclosure:'"',csvSeparator:",",csvUseBOM:!0,date:{html:"dd/mm/yyyy"},displayTableName:!1,escape:!1,exportHiddenCells:!1,fileName:"tableExport",htmlContent:!1,htmlHyperlink:"content",ignoreColumn:[],ignoreRow:[],jsonScope:"all",jspdf:{orientation:"p",
+unit:"pt",format:"a4",margins:{left:20,right:10,top:10,bottom:10},onDocCreated:null,autotable:{styles:{cellPadding:2,rowHeight:12,fontSize:8,fillColor:255,textColor:50,fontStyle:"normal",overflow:"ellipsize",halign:"inherit",valign:"middle"},headerStyles:{fillColor:[52,73,94],textColor:255,fontStyle:"bold",halign:"inherit",valign:"middle"},alternateRowStyles:{fillColor:245},tableExport:{doc:null,onAfterAutotable:null,onBeforeAutotable:null,onAutotableText:null,onTable:null,outputImages:!0}}},mso:{fileFormat:"xlshtml",
+onMsoNumberFormat:null,pageFormat:"a4",pageOrientation:"portrait",rtl:!1,styles:[],worksheetName:"",xslx:{formatId:{date:14,numbers:2}}},numbers:{html:{decimalMark:".",thousandsSeparator:","},output:{decimalMark:".",thousandsSeparator:","}},onAfterSaveToFile:null,onBeforeSaveToFile:null,onCellData:null,onCellHtmlData:null,onCellHtmlHyperlink:null,onIgnoreRow:null,onTableExportBegin:null,onTableExportEnd:null,outputMode:"file",pdfmake:{enabled:!1,docDefinition:{pageSize:"A4",pageOrientation:"portrait",
+styles:{header:{background:"#34495E",color:"#FFFFFF",bold:!0,alignment:"center",fillColor:"#34495E"},alternateRow:{fillColor:"#f5f5f5"}},defaultStyle:{color:"#000000",fontSize:8,font:"Roboto"}},fonts:{}},preserve:{leadingWS:!1,trailingWS:!1},preventInjection:!0,sql:{tableEnclosure:"`",columnEnclosure:"`"},tbodySelector:"tr",tfootSelector:"tr",theadSelector:"tr",tableName:"Table",type:"csv"},O={a0:[2383.94,3370.39],a1:[1683.78,2383.94],a2:[1190.55,1683.78],a3:[841.89,1190.55],a4:[595.28,841.89],a5:[419.53,
+595.28],a6:[297.64,419.53],a7:[209.76,297.64],a8:[147.4,209.76],a9:[104.88,147.4],a10:[73.7,104.88],b0:[2834.65,4008.19],b1:[2004.09,2834.65],b2:[1417.32,2004.09],b3:[1000.63,1417.32],b4:[708.66,1000.63],b5:[498.9,708.66],b6:[354.33,498.9],b7:[249.45,354.33],b8:[175.75,249.45],b9:[124.72,175.75],b10:[87.87,124.72],c0:[2599.37,3676.54],c1:[1836.85,2599.37],c2:[1298.27,1836.85],c3:[918.43,1298.27],c4:[649.13,918.43],c5:[459.21,649.13],c6:[323.15,459.21],c7:[229.61,323.15],c8:[161.57,229.61],c9:[113.39,
+161.57],c10:[79.37,113.39],dl:[311.81,623.62],letter:[612,792],"government-letter":[576,756],legal:[612,1008],"junior-legal":[576,360],ledger:[1224,792],tabloid:[792,1224],"credit-card":[153,243]},B=this,ia=null,r=[],w=[],p=0,t="",S=[],G=[],Ea,K=[],V=!1;d.extend(!0,a,k);"xlsx"===a.type&&(a.mso.fileFormat=a.type,a.type="excel");"undefined"!==typeof a.excelFileFormat&&"undefined"===a.mso.fileFormat&&(a.mso.fileFormat=a.excelFileFormat);"undefined"!==typeof a.excelPageFormat&&"undefined"===a.mso.pageFormat&&
+(a.mso.pageFormat=a.excelPageFormat);"undefined"!==typeof a.excelPageOrientation&&"undefined"===a.mso.pageOrientation&&(a.mso.pageOrientation=a.excelPageOrientation);"undefined"!==typeof a.excelRTL&&"undefined"===a.mso.rtl&&(a.mso.rtl=a.excelRTL);"undefined"!==typeof a.excelstyles&&"undefined"===a.mso.styles&&(a.mso.styles=a.excelstyles);"undefined"!==typeof a.onMsoNumberFormat&&"undefined"===a.mso.onMsoNumberFormat&&(a.mso.onMsoNumberFormat=a.onMsoNumberFormat);"undefined"!==typeof a.worksheetName&&
+"undefined"===a.mso.worksheetName&&(a.mso.worksheetName=a.worksheetName);a.mso.pageOrientation="l"===a.mso.pageOrientation.substr(0,1)?"landscape":"portrait";a.date.html=a.date.html||"";if(a.date.html.length){k=[];k.dd="(3[01]|[12][0-9]|0?[1-9])";k.mm="(1[012]|0?[1-9])";k.yyyy="((?:1[6-9]|2[0-2])\\d{2})";k.yy="(\\d{2})";var z=a.date.html.match(/[^a-zA-Z0-9]/)[0];z=a.date.html.toLowerCase().split(z);a.date.regex="^\\s*";a.date.regex+=k[z[0]];a.date.regex+="(.)";a.date.regex+=k[z[1]];a.date.regex+=
+"\\2";a.date.regex+=k[z[2]];a.date.regex+="\\s*$";a.date.pattern=new RegExp(a.date.regex,"g");k=z.indexOf("dd")+1;a.date.match_d=k+(1<k?1:0);k=z.indexOf("mm")+1;a.date.match_m=k+(1<k?1:0);k=(0<=z.indexOf("yyyy")?z.indexOf("yyyy"):z.indexOf("yy"))+1;a.date.match_y=k+(1<k?1:0)}S=R(B);if("function"===typeof a.onTableExportBegin)a.onTableExportBegin();if("csv"===a.type||"tsv"===a.type||"txt"===a.type){var P="",Z=0;G=[];p=0;var qa=function(b,c,e){b.each(function(){t="";E(this,c,p,e+b.length,function(b,
+c,d){var e=t,f="";if(null!==b)if(b=D(b,c,d),c=null===b||""===b?"":b.toString(),"tsv"===a.type)b instanceof Date&&b.toLocaleString(),f=W(c,"\t"," ");else if(b instanceof Date)f=a.csvEnclosure+b.toLocaleString()+a.csvEnclosure;else if(f=Ba(c),f=W(f,a.csvEnclosure,a.csvEnclosure+a.csvEnclosure),0<=f.indexOf(a.csvSeparator)||/[\r\n ]/g.test(f))f=a.csvEnclosure+f+a.csvEnclosure;t=e+(f+("tsv"===a.type?"\t":a.csvSeparator))});t=d.trim(t).substring(0,t.length-1);0<t.length&&(0<P.length&&(P+="\n"),P+=t);p++});
+return b.length};Z+=qa(d(B).find("thead").first().find(a.theadSelector),"th,td",Z);v(d(B),"tbody").each(function(){Z+=qa(v(d(this),a.tbodySelector),"td,th",Z)});a.tfootSelector.length&&qa(d(B).find("tfoot").first().find(a.tfootSelector),"td,th",Z);P+="\n";if("string"===a.outputMode)return P;if("base64"===a.outputMode)return L(P);if("window"===a.outputMode){ka(!1,"data:text/"+("csv"===a.type?"csv":"plain")+";charset=utf-8,",P);return}N(P,a.fileName+"."+a.type,"text/"+("csv"===a.type?"csv":"plain"),
+"utf-8","","csv"===a.type&&a.csvUseBOM)}else if("sql"===a.type){p=0;G=[];var A="INSERT INTO "+a.sql.tableEnclosure+a.tableName+a.sql.tableEnclosure+" (";r=y(d(B));d(r).each(function(){E(this,"th,td",p,r.length,function(b,c,d){b=D(b,c,d)||"";-1<b.indexOf(a.sql.columnEnclosure)&&(b=W(b.toString(),a.sql.columnEnclosure,a.sql.columnEnclosure+a.sql.columnEnclosure));A+=a.sql.columnEnclosure+b+a.sql.columnEnclosure+","});p++;A=d.trim(A).substring(0,A.length-1)});A+=") VALUES ";w=C(d(B));d(w).each(function(){t=
+"";E(this,"td,th",p,r.length+w.length,function(a,c,d){a=D(a,c,d)||"";-1<a.indexOf("'")&&(a=W(a.toString(),"'","''"));t+="'"+a+"',"});3<t.length&&(A+="("+t,A=d.trim(A).substring(0,A.length-1),A+="),");p++});A=d.trim(A).substring(0,A.length-1);A+=";";if("string"===a.outputMode)return A;if("base64"===a.outputMode)return L(A);N(A,a.fileName+".sql","application/sql","utf-8","",!1)}else if("json"===a.type){var X=[];G=[];r=y(d(B));d(r).each(function(){var a=[];E(this,"th,td",p,r.length,function(b,d,g){a.push(D(b,
+d,g))});X.push(a)});var ra=[];w=C(d(B));d(w).each(function(){var a={},c=0;E(this,"td,th",p,r.length+w.length,function(b,d,f){X.length?a[X[X.length-1][c]]=D(b,d,f):a[c]=D(b,d,f);c++});!1===d.isEmptyObject(a)&&ra.push(a);p++});k="head"===a.jsonScope?JSON.stringify(X):"data"===a.jsonScope?JSON.stringify(ra):JSON.stringify({header:X,data:ra});if("string"===a.outputMode)return k;if("base64"===a.outputMode)return L(k);N(k,a.fileName+".json","application/json","utf-8","base64",!1)}else if("xml"===a.type){p=
+0;G=[];var Q='<?xml version="1.0" encoding="utf-8"?>';Q+="<tabledata><fields>";r=y(d(B));d(r).each(function(){E(this,"th,td",p,r.length,function(a,d,e){Q+="<field>"+D(a,d,e)+"</field>"});p++});Q+="</fields><data>";var Fa=1;w=C(d(B));d(w).each(function(){var a=1;t="";E(this,"td,th",p,r.length+w.length,function(b,d,g){t+="<column-"+a+">"+D(b,d,g)+"</column-"+a+">";a++});0<t.length&&"<column-1></column-1>"!==t&&(Q+='<row id="'+Fa+'">'+t+"</row>",Fa++);p++});Q+="</data></tabledata>";if("string"===a.outputMode)return Q;
+if("base64"===a.outputMode)return L(Q);N(Q,a.fileName+".xml","application/xml","utf-8","base64",!1)}else if("excel"===a.type&&"xmlss"===a.mso.fileFormat){var sa=[],F=[];d(B).filter(function(){return I(d(this))}).each(function(){function b(a,b,c){var f=[];d(a).each(function(){var b=0,e=0;t="";E(this,"td,th",p,c+a.length,function(a,c,h){if(null!==a){var l="";c=D(a,c,h);h="String";if(!1!==jQuery.isNumeric(c))h="Number";else{var n=Ma(c);!1!==n&&(c=n,h="Number",l+=' ss:StyleID="pct1"')}"Number"!==h&&(c=
+c.replace(/\n/g,"<br>"));n=J(a);a=T(a);d.each(f,function(){if(p>=this.s.r&&p<=this.e.r&&e>=this.s.c&&e<=this.e.c)for(var a=0;a<=this.e.c-this.s.c;++a)e++,b++});if(a||n)a=a||1,n=n||1,f.push({s:{r:p,c:e},e:{r:p+a-1,c:e+n-1}});1<n&&(l+=' ss:MergeAcross="'+(n-1)+'"',e+=n-1);1<a&&(l+=' ss:MergeDown="'+(a-1)+'" ss:StyleID="rsp1"');0<b&&(l+=' ss:Index="'+(e+1)+'"',b=0);t+="<Cell"+l+'><Data ss:Type="'+h+'">'+d("<div />").text(c).html()+"</Data></Cell>\r";e++}});0<t.length&&(H+='<Row ss:AutoFitHeight="0">\r'+
+t+"</Row>\r");p++});return a.length}var c=d(this),e="";"string"===typeof a.mso.worksheetName&&a.mso.worksheetName.length?e=a.mso.worksheetName+" "+(F.length+1):"undefined"!==typeof a.mso.worksheetName[F.length]&&(e=a.mso.worksheetName[F.length]);e.length||(e=c.find("caption").text()||"");e.length||(e="Table "+(F.length+1));e=d.trim(e.replace(/[\\\/[\]*:?'"]/g,"").substring(0,31));F.push(d("<div />").text(e).html());!1===a.exportHiddenCells&&(K=c.find("tr, th, td").filter(":hidden"),V=0<K.length);
+p=0;S=R(this);H="<Table>\r";e=b(y(c),"th,td",0);b(C(c),"td,th",e);H+="</Table>\r";sa.push(H)});k={};z={};for(var m,aa,Y=0,ea=F.length;Y<ea;Y++)m=F[Y],aa=k[m],aa=k[m]=null==aa?1:aa+1,2===aa&&(F[z[m]]=F[z[m]].substring(0,29)+"-1"),1<k[m]?F[Y]=F[Y].substring(0,29)+"-"+k[m]:z[m]=Y;k='<?xml version="1.0" encoding="UTF-8"?>\r<?mso-application progid="Excel.Sheet"?>\r<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"\r xmlns:o="urn:schemas-microsoft-com:office:office"\r xmlns:x="urn:schemas-microsoft-com:office:excel"\r xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"\r xmlns:html="http://www.w3.org/TR/REC-html40">\r<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">\r  <Created>'+
+(new Date).toISOString()+'</Created>\r</DocumentProperties>\r<OfficeDocumentSettings xmlns="urn:schemas-microsoft-com:office:office">\r  <AllowPNG/>\r</OfficeDocumentSettings>\r<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">\r  <WindowHeight>9000</WindowHeight>\r  <WindowWidth>13860</WindowWidth>\r  <WindowTopX>0</WindowTopX>\r  <WindowTopY>0</WindowTopY>\r  <ProtectStructure>False</ProtectStructure>\r  <ProtectWindows>False</ProtectWindows>\r</ExcelWorkbook>\r<Styles>\r  <Style ss:ID="Default" ss:Name="Normal">\r    <Alignment ss:Vertical="Bottom"/>\r    <Borders/>\r    <Font/>\r    <Interior/>\r    <NumberFormat/>\r    <Protection/>\r  </Style>\r  <Style ss:ID="rsp1">\r    <Alignment ss:Vertical="Center"/>\r  </Style>\r  <Style ss:ID="pct1">\r    <NumberFormat ss:Format="Percent"/>\r  </Style>\r</Styles>\r';
+for(z=0;z<sa.length;z++)k+='<Worksheet ss:Name="'+F[z]+'" ss:RightToLeft="'+(a.mso.rtl?"1":"0")+'">\r'+sa[z],k=a.mso.rtl?k+'<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">\r<DisplayRightToLeft/>\r</WorksheetOptions>\r':k+'<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel"/>\r',k+="</Worksheet>\r";k+="</Workbook>\r";if("string"===a.outputMode)return k;if("base64"===a.outputMode)return L(k);N(k,a.fileName+".xml","application/xml","utf-8","base64",!1)}else if("excel"===
+a.type&&"xlsx"===a.mso.fileFormat){var ba=[],Ga=XLSX.utils.book_new();d(B).filter(function(){return I(d(this))}).each(function(){for(var b=d(this),c={},e=this.getElementsByTagName("tr"),g={s:{r:0,c:0},e:{r:0,c:0}},f=[],h,n=[],l=0,u=0,k,m,p,t,r,w=XLSX.SSF.get_table();l<e.length&&1E7>u;++l)if(k=e[l],m=!1,"function"===typeof a.onIgnoreRow&&(m=a.onIgnoreRow(d(k),l)),!0!==m&&(0===a.ignoreRow.length||-1===d.inArray(l,a.ignoreRow)&&-1===d.inArray(l-e.length,a.ignoreRow))&&!1!==I(d(k))){var y=k.children,
+B=0;for(k=0;k<y.length;++k)r=y[k],t=+J(r)||1,B+=t;var z=0;for(k=m=0;k<y.length;++k)if(r=y[k],t=+J(r)||1,h=k+z,!ta(d(r),B,h+(h<m?m-h:0))){z+=t-1;for(h=0;h<f.length;++h){var v=f[h];v.s.c==m&&v.s.r<=u&&u<=v.e.r&&(m=v.e.c+1,h=-1)}(0<(p=+T(r))||1<t)&&f.push({s:{r:u,c:m},e:{r:u+(p||1)-1,c:m+t-1}});var C={type:""};h=D(r,l,k+z,C);v={t:"s",v:h};var A="";if(""!==(d(r).attr("data-tableexport-cellformat")||"")){var x=parseInt(d(r).attr("data-tableexport-xlsxformatid")||0);0===x&&"function"===typeof a.mso.xslx.formatId.numbers&&
+(x=a.mso.xslx.formatId.numbers(d(r),l,k+z));0===x&&"function"===typeof a.mso.xslx.formatId.date&&(x=a.mso.xslx.formatId.date(d(r),l,k+z));if(49===x||"@"===x)A="s";else if("number"===C.type||0<x&&14>x||36<x&&41>x||48===x)A="n";else if("date"===C.type||13<x&&37>x||44<x&&48>x||56===x)A="d"}else A="s";if(null!=h)if(0===h.length)v.t="z";else if(0!==h.trim().length)if("s"===A)d(r).find("a").length&&(h="href"!==a.htmlHyperlink?h:"",v={f:'=HYPERLINK("'+d(r).find("a").attr("href")+(h.length?'","'+h:"")+'")'});
+else if("function"===C.type)v={f:h};else if("TRUE"===h)v={t:"b",v:!0};else if("FALSE"===h)v={t:"b",v:!1};else if("n"===A||isFinite(Da(h,a.numbers.output))){if(r=Da(h,a.numbers.output),0===x&&"function"!==typeof a.mso.xslx.formatId.numbers&&(x=a.mso.xslx.formatId.numbers),isFinite(r)||isFinite(h))v={t:"n",v:isFinite(r)?r:h,z:"string"===typeof x?x:x in w?w[x]:"0.00"}}else if(!1!==(r=La(h))||"d"===A)0===x&&"function"!==typeof a.mso.xslx.formatId.date&&(x=a.mso.xslx.formatId.date),v={t:"d",v:!1!==r?r:
+h,z:"string"===typeof x?x:x in w?w[x]:"m/d/yy"};c[oa({c:m,r:u})]=v;g.e.c<m&&(g.e.c=m);m+=t}++u}f.length&&(c["!merges"]=f);n.length&&(c["!rows"]=n);g.e.r=u-1;c["!ref"]=pa(g);1E7<=u&&(c["!fullref"]=pa((g.e.r=e.length-l+u-1,g)));e="";"string"===typeof a.mso.worksheetName&&a.mso.worksheetName.length?e=a.mso.worksheetName+" "+(ba.length+1):"undefined"!==typeof a.mso.worksheetName[ba.length]&&(e=a.mso.worksheetName[ba.length]);e.length||(e=b.find("caption").text()||"");e.length||(e="Table "+(ba.length+
+1));e=d.trim(e.replace(/[\\\/[\]*:?'"]/g,"").substring(0,31));ba.push(e);XLSX.utils.book_append_sheet(Ga,c,e)});k=XLSX.write(Ga,{type:"binary",bookType:a.mso.fileFormat,bookSST:!1});N(Oa(k),a.fileName+"."+a.mso.fileFormat,"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet","UTF-8","",!1)}else if("excel"===a.type||"xls"===a.type||"word"===a.type||"doc"===a.type){k="excel"===a.type||"xls"===a.type?"excel":"word";z="excel"===k?"xls":"doc";m='xmlns:x="urn:schemas-microsoft-com:office:'+
+k+'"';var H="",ca="";d(B).filter(function(){return I(d(this))}).each(function(){var b=d(this);""===ca&&(ca=a.mso.worksheetName||b.find("caption").text()||"Table",ca=d.trim(ca.replace(/[\\\/[\]*:?'"]/g,"").substring(0,31)));!1===a.exportHiddenCells&&(K=b.find("tr, th, td").filter(":hidden"),V=0<K.length);p=0;G=[];S=R(this);H+="<table><thead>";r=y(b);d(r).each(function(){var b=d(this);t="";E(this,"th,td",p,r.length,function(d,c,f){if(null!==d){var e="";t+="<th";if(a.mso.styles.length){var n=document.defaultView.getComputedStyle(d,
+null),l=document.defaultView.getComputedStyle(b[0],null),g;for(g in a.mso.styles){var k=n[a.mso.styles[g]];""===k&&(k=l[a.mso.styles[g]]);""!==k&&"0px none rgb(0, 0, 0)"!==k&&"rgba(0, 0, 0, 0)"!==k&&(e+=""===e?'style="':";",e+=a.mso.styles[g]+":"+k)}}""!==e&&(t+=" "+e+'"');e=J(d);0<e&&(t+=' colspan="'+e+'"');e=T(d);0<e&&(t+=' rowspan="'+e+'"');t+=">"+D(d,c,f)+"</th>"}});0<t.length&&(H+="<tr>"+t+"</tr>");p++});H+="</thead><tbody>";w=C(b);d(w).each(function(){var b=d(this);t="";E(this,"td,th",p,r.length+
+w.length,function(c,g,f){if(null!==c){var e=D(c,g,f),n="",l=d(c).attr("data-tableexport-msonumberformat");"undefined"===typeof l&&"function"===typeof a.mso.onMsoNumberFormat&&(l=a.mso.onMsoNumberFormat(c,g,f));"undefined"!==typeof l&&""!==l&&(n="style=\"mso-number-format:'"+l+"'");if(a.mso.styles.length){g=document.defaultView.getComputedStyle(c,null);f=document.defaultView.getComputedStyle(b[0],null);for(var k in a.mso.styles)l=g[a.mso.styles[k]],""===l&&(l=f[a.mso.styles[k]]),""!==l&&"0px none rgb(0, 0, 0)"!==
+l&&"rgba(0, 0, 0, 0)"!==l&&(n+=""===n?'style="':";",n+=a.mso.styles[k]+":"+l)}t+="<td";""!==n&&(t+=" "+n+'"');n=J(c);0<n&&(t+=' colspan="'+n+'"');c=T(c);0<c&&(t+=' rowspan="'+c+'"');"string"===typeof e&&""!==e&&(e=Ba(e),e=e.replace(/\n/g,"<br>"));t+=">"+e+"</td>"}});0<t.length&&(H+="<tr>"+t+"</tr>");p++});a.displayTableName&&(H+="<tr><td></td></tr><tr><td></td></tr><tr><td>"+D(d("<p>"+a.tableName+"</p>"))+"</td></tr>");H+="</tbody></table>"});m='<html xmlns:o="urn:schemas-microsoft-com:office:office" '+
+m+' xmlns="http://www.w3.org/TR/REC-html40">'+('<meta http-equiv="content-type" content="application/vnd.ms-'+k+'; charset=UTF-8">')+"<head>";"excel"===k&&(m+="\x3c!--[if gte mso 9]>",m+="<xml>",m+="<x:ExcelWorkbook>",m+="<x:ExcelWorksheets>",m+="<x:ExcelWorksheet>",m+="<x:Name>",m+=ca,m+="</x:Name>",m+="<x:WorksheetOptions>",m+="<x:DisplayGridlines/>",a.mso.rtl&&(m+="<x:DisplayRightToLeft/>"),m+="</x:WorksheetOptions>",m+="</x:ExcelWorksheet>",m+="</x:ExcelWorksheets>",m+="</x:ExcelWorkbook>",m+=
+"</xml>",m+="<![endif]--\x3e");m+="<style>";m+="@page { size:"+a.mso.pageOrientation+"; mso-page-orientation:"+a.mso.pageOrientation+"; }";m+="@page Section1 {size:"+O[a.mso.pageFormat][0]+"pt "+O[a.mso.pageFormat][1]+"pt";m+="; margin:1.0in 1.25in 1.0in 1.25in;mso-header-margin:.5in;mso-footer-margin:.5in;mso-paper-source:0;}";m+="div.Section1 {page:Section1;}";m+="@page Section2 {size:"+O[a.mso.pageFormat][1]+"pt "+O[a.mso.pageFormat][0]+"pt";m+=";mso-page-orientation:"+a.mso.pageOrientation+";margin:1.25in 1.0in 1.25in 1.0in;mso-header-margin:.5in;mso-footer-margin:.5in;mso-paper-source:0;}";
+m+="div.Section2 {page:Section2;}";m+="br {mso-data-placement:same-cell;}";m+="</style>";m+="</head>";m+="<body>";m+='<div class="Section'+("landscape"===a.mso.pageOrientation?"2":"1")+'">';m+=H;m+="</div>";m+="</body>";m+="</html>";if("string"===a.outputMode)return m;if("base64"===a.outputMode)return L(m);N(m,a.fileName+"."+z,"application/vnd.ms-"+k,"","base64",!1)}else if("png"===a.type)html2canvas(d(B)[0]).then(function(b){b=b.toDataURL();for(var c=atob(b.substring(22)),d=new ArrayBuffer(c.length),
+g=new Uint8Array(d),f=0;f<c.length;f++)g[f]=c.charCodeAt(f);if("string"===a.outputMode)return c;if("base64"===a.outputMode)return L(b);"window"===a.outputMode?window.open(b):N(d,a.fileName+".png","image/png","","",!1)});else if("pdf"===a.type)if(!0===a.pdfmake.enabled){var U={content:[]};d.extend(!0,U,a.pdfmake.docDefinition);G=[];d(B).filter(function(){return I(d(this))}).each(function(){var b=d(this),c=[],e=[];p=0;var g=function(a,b,c){var f=0;d(a).each(function(){var a=[];E(this,b,p,c,function(c,
+d,f){if("undefined"!==typeof c&&null!==c){var e=J(c),h=T(c);c={text:D(c,d,f)||" "};if(1<e||1<h)c.colSpan=e||1,c.rowSpan=h||1}else c={text:" "};0<=b.indexOf("th")&&(c.style="header");a.push(c)});for(var d=a.length;d<c;d++)a.push("");a.length&&e.push(a);f<a.length&&(f=a.length);p++});return f};r=y(b);for(var f=g(r,"th,td",r.length),h=c.length;h<f;h++)c.push("*");w=C(b);f=g(w,"td",r.length+w.length);for(h=c.length;h<f;h++)c.push("*");U.content.push({table:{headerRows:r.length?r.length:null,widths:c,
+body:e},layout:{layout:"noBorders",hLineStyle:function(a,b){return 0},vLineWidth:function(a,b){return 0},hLineColor:function(b,c){return b<c.table.headerRows?a.pdfmake.docDefinition.styles.header.background:a.pdfmake.docDefinition.styles.alternateRow.fillColor},vLineColor:function(b,c){return b<c.table.headerRows?a.pdfmake.docDefinition.styles.header.background:a.pdfmake.docDefinition.styles.alternateRow.fillColor},fillColor:function(b,c,d){return 0===b%2?a.pdfmake.docDefinition.styles.alternateRow.fillColor:
+null}},pageBreak:U.content.length?"before":void 0})});"undefined"!==typeof pdfMake&&"undefined"!==typeof pdfMake.createPdf&&(pdfMake.fonts={Roboto:{normal:"Roboto-Regular.ttf",bold:"Roboto-Medium.ttf",italics:"Roboto-Italic.ttf",bolditalics:"Roboto-MediumItalic.ttf"}},pdfMake.vfs.hasOwnProperty("Mirza-Regular.ttf")?(U.defaultStyle.font="Mirza",d.extend(!0,pdfMake.fonts,{Mirza:{normal:"Mirza-Regular.ttf",bold:"Mirza-Bold.ttf",italics:"Mirza-Medium.ttf",bolditalics:"Mirza-SemiBold.ttf"}})):pdfMake.vfs.hasOwnProperty("gbsn00lp.ttf")?
+(U.defaultStyle.font="gbsn00lp",d.extend(!0,pdfMake.fonts,{gbsn00lp:{normal:"gbsn00lp.ttf",bold:"gbsn00lp.ttf",italics:"gbsn00lp.ttf",bolditalics:"gbsn00lp.ttf"}})):pdfMake.vfs.hasOwnProperty("ZCOOLXiaoWei-Regular.ttf")&&(U.defaultStyle.font="ZCOOLXiaoWei",d.extend(!0,pdfMake.fonts,{ZCOOLXiaoWei:{normal:"ZCOOLXiaoWei-Regular.ttf",bold:"ZCOOLXiaoWei-Regular.ttf",italics:"ZCOOLXiaoWei-Regular.ttf",bolditalics:"ZCOOLXiaoWei-Regular.ttf"}})),d.extend(!0,pdfMake.fonts,a.pdfmake.fonts),pdfMake.createPdf(U).getBuffer(function(b){N(b,
+a.fileName+".pdf","application/pdf","","",!1)}))}else if(!1===a.jspdf.autotable){k={dim:{w:ha(d(B).first().get(0),"width","mm"),h:ha(d(B).first().get(0),"height","mm")},pagesplit:!1};var Ha=new jsPDF(a.jspdf.orientation,a.jspdf.unit,a.jspdf.format);Ha.addHTML(d(B).first(),a.jspdf.margins.left,a.jspdf.margins.top,k,function(){va(Ha,!1)})}else{var g=a.jspdf.autotable.tableExport;if("string"===typeof a.jspdf.format&&"bestfit"===a.jspdf.format.toLowerCase()){var ja="",da="",Ia=0;d(B).each(function(){if(I(d(this))){var a=
+ha(d(this).get(0),"width","pt");if(a>Ia){a>O.a0[0]&&(ja="a0",da="l");for(var c in O)O.hasOwnProperty(c)&&O[c][1]>a&&(ja=c,da="l",O[c][0]>a&&(da="p"));Ia=a}}});a.jspdf.format=""===ja?"a4":ja;a.jspdf.orientation=""===da?"w":da}if(null==g.doc&&(g.doc=new jsPDF(a.jspdf.orientation,a.jspdf.unit,a.jspdf.format),g.wScaleFactor=1,g.hScaleFactor=1,"function"===typeof a.jspdf.onDocCreated))a.jspdf.onDocCreated(g.doc);!0===g.outputImages&&(g.images={});"undefined"!==typeof g.images&&(d(B).filter(function(){return I(d(this))}).each(function(){var b=
+0;G=[];!1===a.exportHiddenCells&&(K=d(this).find("tr, th, td").filter(":hidden"),V=0<K.length);r=y(d(this));w=C(d(this));d(w).each(function(){E(this,"td,th",r.length+b,r.length+w.length,function(a){xa(a,d(a).children(),g)});b++})}),r=[],w=[]);Ka(g,function(){d(B).filter(function(){return I(d(this))}).each(function(){var b;p=0;G=[];!1===a.exportHiddenCells&&(K=d(this).find("tr, th, td").filter(":hidden"),V=0<K.length);S=R(this);g.columns=[];g.rows=[];g.teCells={};if("function"===typeof g.onTable&&
+!1===g.onTable(d(this),a))return!0;a.jspdf.autotable.tableExport=null;var c=d.extend(!0,{},a.jspdf.autotable);a.jspdf.autotable.tableExport=g;c.margin={};d.extend(!0,c.margin,a.jspdf.margins);c.tableExport=g;"function"!==typeof c.beforePageContent&&(c.beforePageContent=function(a){if(1===a.pageCount){var b=a.table.rows.concat(a.table.headerRow);d.each(b,function(){0<this.height&&(this.height+=(2-1.15)/2*this.styles.fontSize,a.table.height+=(2-1.15)/2*this.styles.fontSize)})}});"function"!==typeof c.createdHeaderCell&&
+(c.createdHeaderCell=function(a,b){a.styles=d.extend({},b.row.styles);if("undefined"!==typeof g.columns[b.column.dataKey]){var e=g.columns[b.column.dataKey];if("undefined"!==typeof e.rect){a.contentWidth=e.rect.width;if("undefined"===typeof g.heightRatio||0===g.heightRatio){var f=b.row.raw[b.column.dataKey].rowspan?b.row.raw[b.column.dataKey].rect.height/b.row.raw[b.column.dataKey].rowspan:b.row.raw[b.column.dataKey].rect.height;g.heightRatio=a.styles.rowHeight/f}f=b.row.raw[b.column.dataKey].rect.height*
+g.heightRatio;f>a.styles.rowHeight&&(a.styles.rowHeight=f)}a.styles.halign="inherit"===c.headerStyles.halign?"center":c.headerStyles.halign;a.styles.valign=c.headerStyles.valign;"undefined"!==typeof e.style&&!0!==e.style.hidden&&("inherit"===c.headerStyles.halign&&(a.styles.halign=e.style.align),"inherit"===c.styles.fillColor&&(a.styles.fillColor=e.style.bcolor),"inherit"===c.styles.textColor&&(a.styles.textColor=e.style.color),"inherit"===c.styles.fontStyle&&(a.styles.fontStyle=e.style.fstyle))}});
+"function"!==typeof c.createdCell&&(c.createdCell=function(a,b){b=g.teCells[b.row.index+":"+b.column.dataKey];a.styles.halign="inherit"===c.styles.halign?"center":c.styles.halign;a.styles.valign=c.styles.valign;"undefined"!==typeof b&&"undefined"!==typeof b.style&&!0!==b.style.hidden&&("inherit"===c.styles.halign&&(a.styles.halign=b.style.align),"inherit"===c.styles.fillColor&&(a.styles.fillColor=b.style.bcolor),"inherit"===c.styles.textColor&&(a.styles.textColor=b.style.color),"inherit"===c.styles.fontStyle&&
+(a.styles.fontStyle=b.style.fstyle))});"function"!==typeof c.drawHeaderCell&&(c.drawHeaderCell=function(a,b){var c=g.columns[b.column.dataKey];return(!0!==c.style.hasOwnProperty("hidden")||!0!==c.style.hidden)&&0<=c.rowIndex?wa(a,b,c):!1});"function"!==typeof c.drawCell&&(c.drawCell=function(a,b){var c=g.teCells[b.row.index+":"+b.column.dataKey];if(!0!==("undefined"!==typeof c&&c.isCanvas))wa(a,b,c)&&(g.doc.rect(a.x,a.y,a.width,a.height,a.styles.fillStyle),"undefined"===typeof c||"undefined"!==typeof c.hasUserDefText&&
+!0===c.hasUserDefText||"undefined"===typeof c.elements||!c.elements.length?Aa(a,{},g):(b=a.height/c.rect.height,b>g.hScaleFactor&&(g.hScaleFactor=b),g.wScaleFactor=a.width/c.rect.width,b=a.textPos.y,za(a,c.elements,g),a.textPos.y=b,Aa(a,c.elements,g)));else{c=c.elements[0];var e=d(c).attr("data-tableexport-canvas"),f=c.getBoundingClientRect();a.width=f.width*g.wScaleFactor;a.height=f.height*g.hScaleFactor;b.row.height=a.height;ua(a,c,e,g)}return!1});g.headerrows=[];r=y(d(this));d(r).each(function(){b=
+0;g.headerrows[p]=[];E(this,"th,td",p,r.length,function(a,c,d){var e=Ca(a);e.title=D(a,c,d);e.key=b++;e.rowIndex=p;g.headerrows[p].push(e)});p++});if(0<p)for(var e=p-1;0<=e;)d.each(g.headerrows[e],function(){var a=this;0<e&&null===this.rect&&(a=g.headerrows[e-1][this.key]);null!==a&&0<=a.rowIndex&&(!0!==a.style.hasOwnProperty("hidden")||!0!==a.style.hidden)&&g.columns.push(a)}),e=0<g.columns.length?-1:e-1;var k=0;w=[];w=C(d(this));d(w).each(function(){var a=[];b=0;E(this,"td,th",p,r.length+w.length,
+function(c,e,f){if("undefined"===typeof g.columns[b]){var h={title:"",key:b,style:{hidden:!0}};g.columns.push(h)}a.push(D(c,e,f));"undefined"!==typeof c&&null!==c?(h=Ca(c),h.isCanvas=c.hasAttribute("data-tableexport-canvas"),h.elements=h.isCanvas?d(c):d(c).children(),"undefined"!==typeof d(c).data("teUserDefText")&&(h.hasUserDefText=!0)):(h=d.extend(!0,{},g.teCells[k+":"+(b-1)]),h.colspan=-1);g.teCells[k+":"+b++]=h});a.length&&(g.rows.push(a),k++);p++});if("function"===typeof g.onBeforeAutotable)g.onBeforeAutotable(d(this),
+g.columns,g.rows,c);g.doc.autoTable(g.columns,g.rows,c);if("function"===typeof g.onAfterAutotable)g.onAfterAutotable(d(this),c);a.jspdf.autotable.startY=g.doc.autoTableEndPosY()+c.margin.top});va(g.doc,"undefined"!==typeof g.images&&!1===jQuery.isEmptyObject(g.images));"undefined"!==typeof g.headerrows&&(g.headerrows.length=0);"undefined"!==typeof g.columns&&(g.columns.length=0);"undefined"!==typeof g.rows&&(g.rows.length=0);delete g.doc;g.doc=null})}if("function"===typeof a.onTableExportEnd)a.onTableExportEnd();
+return this}})(jQuery);
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/mobile/bootstrap-table-mobile.js b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/mobile/bootstrap-table-mobile.js
new file mode 100644
index 0000000..c93fe91
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/mobile/bootstrap-table-mobile.js
@@ -0,0 +1,123 @@
+/**
+ * @author: Dennis Hernández
+ * @update zhixin wen <wenzhixin2010@gmail.com>
+ */
+
+const debounce = (func, wait) => {
+  let timeout = 0
+
+  return (...args) => {
+    const later = () => {
+      timeout = 0
+      func(...args)
+    }
+
+    clearTimeout(timeout)
+    timeout = setTimeout(later, wait)
+  }
+}
+
+Object.assign($.fn.bootstrapTable.defaults, {
+  mobileResponsive: false,
+  minWidth: 562,
+  minHeight: undefined,
+  heightThreshold: 100, // just slightly larger than mobile chrome's auto-hiding toolbar
+  checkOnInit: true,
+  columnsHidden: []
+})
+
+$.BootstrapTable = class extends $.BootstrapTable {
+  init (...args) {
+    super.init(...args)
+
+    if (!this.options.mobileResponsive || !this.options.minWidth) {
+      return
+    }
+
+    if (this.options.minWidth < 100 && this.options.resizable) {
+      console.warn('The minWidth when the resizable extension is active should be greater or equal than 100')
+      this.options.minWidth = 100
+    }
+
+    let old = {
+      width: $(window).width(),
+      height: $(window).height()
+    }
+
+    $(window).on('resize orientationchange', debounce(() => {
+      // reset view if height has only changed by at least the threshold.
+      const width = $(window).width()
+      const height = $(window).height()
+      const $activeElement = $(document.activeElement)
+
+      if ($activeElement.length && ['INPUT', 'SELECT', 'TEXTAREA'].includes($activeElement.prop('nodeName'))) {
+        return
+      }
+
+      if (
+        Math.abs(old.height - height) > this.options.heightThreshold ||
+        old.width !== width
+      ) {
+        this.changeView(width, height)
+        old = {
+          width,
+          height
+        }
+      }
+    }, 200))
+
+    if (this.options.checkOnInit) {
+      const width = $(window).width()
+      const height = $(window).height()
+
+      this.changeView(width, height)
+      old = {
+        width,
+        height
+      }
+    }
+  }
+
+  conditionCardView () {
+    this.changeTableView(false)
+    this.showHideColumns(false)
+  }
+
+  conditionFullView () {
+    this.changeTableView(true)
+    this.showHideColumns(true)
+  }
+
+  changeTableView (cardViewState) {
+    this.options.cardView = cardViewState
+    this.toggleView()
+  }
+
+  showHideColumns (checked) {
+    if (this.options.columnsHidden.length > 0) {
+      this.columns.forEach(column => {
+        if (this.options.columnsHidden.includes(column.field)) {
+          if (column.visible !== checked) {
+            this._toggleColumn(this.fieldsColumnsIndex[column.field], checked, true)
+          }
+        }
+      })
+    }
+  }
+
+  changeView (width, height) {
+    if (this.options.minHeight) {
+      if (width <= this.options.minWidth && height <= this.options.minHeight) {
+        this.conditionCardView()
+      } else if (width > this.options.minWidth && height > this.options.minHeight) {
+        this.conditionFullView()
+      }
+    } else if (width <= this.options.minWidth) {
+      this.conditionCardView()
+    } else if (width > this.options.minWidth) {
+      this.conditionFullView()
+    }
+
+    this.resetView()
+  }
+}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/print/bootstrap-table-print.js b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/print/bootstrap-table-print.js
new file mode 100644
index 0000000..b758ce3
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/print/bootstrap-table-print.js
@@ -0,0 +1,312 @@
+/**
+ * @update zhixin wen <wenzhixin2010@gmail.com>
+ */
+
+var Utils = $.fn.bootstrapTable.utils
+
+function printPageBuilderDefault (table, styles) {
+  return `
+    <html>
+    <head>
+    ${styles}
+    <style type="text/css" media="print">
+    @page {
+      size: auto;
+      margin: 25px 0 25px 0;
+    }
+    </style>
+    <style type="text/css" media="all">
+    table {
+      border-collapse: collapse;
+      font-size: 12px;
+    }
+    table, th, td {
+      border: 1px solid grey;
+    }
+    th, td {
+      text-align: center;
+      vertical-align: middle;
+    }
+    p {
+      font-weight: bold;
+      margin-left:20px;
+    }
+    table {
+      width: 94%;
+      margin-left: 3%;
+      margin-right: 3%;
+    }
+    div.bs-table-print {
+      text-align: center;
+    }
+    </style>
+    </head>
+    <title>Print Table</title>
+    <body>
+    <p>Printed on: ${new Date} </p>
+    <div class="bs-table-print">${table}</div>
+    </body>
+    </html>
+  `
+}
+
+Object.assign($.fn.bootstrapTable.locales, {
+  formatPrint () {
+    return 'Print'
+  }
+})
+Object.assign($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales)
+
+Object.assign($.fn.bootstrapTable.defaults, {
+  showPrint: false,
+  printAsFilteredAndSortedOnUI: true,
+  printSortColumn: undefined,
+  printSortOrder: 'asc',
+  printStyles: [],
+  printPageBuilder (table, styles) {
+    return printPageBuilderDefault(table, styles)
+  }
+})
+
+Object.assign($.fn.bootstrapTable.columnDefaults, {
+  printFilter: undefined,
+  printIgnore: false,
+  printFormatter: undefined
+})
+
+Object.assign($.fn.bootstrapTable.defaults.icons, {
+  print: {
+    bootstrap3: 'glyphicon-print icon-share',
+    bootstrap5: 'bi-printer',
+    'bootstrap-table': 'icon-printer'
+  }[$.fn.bootstrapTable.theme] || 'fa-print'
+})
+
+$.BootstrapTable = class extends $.BootstrapTable {
+  init (...args) {
+    super.init(...args)
+
+    if (!this.options.showPrint) {
+      return
+    }
+
+    this.mergedCells = []
+  }
+
+  initToolbar (...args) {
+    this.showToolbar = this.showToolbar || this.options.showPrint
+
+    if (this.options.showPrint) {
+      this.buttons = Object.assign(this.buttons, {
+        print: {
+          text: this.options.formatPrint(),
+          icon: this.options.icons.print,
+          event: () => {
+            this.doPrint(this.options.printAsFilteredAndSortedOnUI ? this.getData() : this.options.data.slice(0))
+          },
+          attributes: {
+            'aria-label': this.options.formatPrint(),
+            title: this.options.formatPrint()
+          }
+        }
+      })
+    }
+
+    super.initToolbar(...args)
+  }
+
+  mergeCells (options) {
+    super.mergeCells(options)
+
+    if (!this.options.showPrint) {
+      return
+    }
+
+    let col = this.getVisibleFields().indexOf(options.field)
+
+    if (Utils.hasDetailViewIcon(this.options)) {
+      col += 1
+    }
+
+    this.mergedCells.push({
+      row: options.index,
+      col,
+      rowspan: options.rowspan || 1,
+      colspan: options.colspan || 1
+    })
+  }
+
+  doPrint (data) {
+    const canPrint = column => {
+      return !column.printIgnore && column.visible
+    }
+
+    const formatValue = (row, i, column) => {
+      const value_ = Utils.getItemField(row, column.field, this.options.escape, column.escape)
+      const value = Utils.calculateObjectValue(column,
+        column.printFormatter || column.formatter,
+        [value_, row, i], value_)
+
+      return typeof value === 'undefined' || value === null ?
+        this.options.undefinedText : value
+    }
+
+    const buildTable = (data, columnsArray) => {
+      const dir = this.$el.attr('dir') || 'ltr'
+      const html = [`<table dir="${dir}"><thead>`]
+
+      for (const columns of columnsArray) {
+        html.push('<tr>')
+        for (let h = 0; h < columns.length; h++) {
+          if (canPrint(columns[h])) {
+            html.push(
+              `<th
+              ${Utils.sprintf(' rowspan="%s"', columns[h].rowspan)}
+              ${Utils.sprintf(' colspan="%s"', columns[h].colspan)}
+              >${columns[h].title}</th>`)
+          }
+        }
+        html.push('</tr>')
+      }
+
+      html.push('</thead><tbody>')
+
+      const notRender = []
+
+      if (this.mergedCells) {
+        for (let mc = 0; mc < this.mergedCells.length; mc++) {
+          const currentMergedCell = this.mergedCells[mc]
+
+          for (let rs = 0; rs < currentMergedCell.rowspan; rs++) {
+            const row = currentMergedCell.row + rs
+
+            for (let cs = 0; cs < currentMergedCell.colspan; cs++) {
+              const col = currentMergedCell.col + cs
+
+              notRender.push(`${row},${col}`)
+            }
+          }
+        }
+      }
+
+      for (let i = 0; i < data.length; i++) {
+        html.push('<tr>')
+
+        const columns = columnsArray.flat(1)
+
+        columns.sort((c1, c2) => {
+          return c1.colspanIndex - c2.colspanIndex
+        })
+
+        for (let j = 0; j < columns.length; j++) {
+          if (columns[j].colspanGroup > 0) continue
+
+          let rowspan = 0
+          let colspan = 0
+
+          if (this.mergedCells) {
+            for (let mc = 0; mc < this.mergedCells.length; mc++) {
+              const currentMergedCell = this.mergedCells[mc]
+
+              if (currentMergedCell.col === j && currentMergedCell.row === i) {
+                rowspan = currentMergedCell.rowspan
+                colspan = currentMergedCell.colspan
+              }
+            }
+          }
+
+          if (
+            canPrint(columns[j]) &&
+            (
+              !notRender.includes(`${i},${j}`) ||
+              rowspan > 0 && colspan > 0
+            )
+          ) {
+            if (rowspan > 0 && colspan > 0) {
+              html.push(`<td ${Utils.sprintf(' rowspan="%s"', rowspan)} ${Utils.sprintf(' colspan="%s"', colspan)}>`, formatValue(data[i], i, columns[j]), '</td>')
+            } else {
+              html.push('<td>', formatValue(data[i], i, columns[j]), '</td>')
+            }
+          }
+        }
+
+        html.push('</tr>')
+      }
+
+      html.push('</tbody>')
+      if (this.options.showFooter) {
+        html.push('<footer><tr>')
+
+        for (const columns of columnsArray) {
+          for (let h = 0; h < columns.length; h++) {
+            if (canPrint(columns)) {
+              const footerData = Utils.trToData(columns, this.$el.find('>tfoot>tr'))
+              const footerValue = Utils.calculateObjectValue(columns[h], columns[h].footerFormatter, [data], footerData[0] && footerData[0][columns[h].field] || '')
+
+              html.push(`<th>${footerValue}</th>`)
+            }
+          }
+        }
+
+        html.push('</tr></footer>')
+      }
+      html.push('</table>')
+      return html.join('')
+    }
+
+    const sortRows = (data, colName, sortOrder) => {
+      if (!colName) {
+        return data
+      }
+      let reverse = sortOrder !== 'asc'
+
+      reverse = -(+reverse || -1)
+      return data.sort((a, b) => reverse * a[colName].localeCompare(b[colName]))
+    }
+
+    const filterRow = (row, filters) => {
+      for (let index = 0; index < filters.length; ++index) {
+        if (row[filters[index].colName] !== filters[index].value) {
+          return false
+        }
+      }
+      return true
+    }
+
+    const filterRows = (data, filters) => data.filter(row => filterRow(row, filters))
+    const getColumnFilters = columns => !columns || !columns[0] ? [] : columns[0].filter(col => col.printFilter).map(col => ({
+      colName: col.field,
+      value: col.printFilter
+    }))
+
+    data = filterRows(data, getColumnFilters(this.options.columns))
+    data = sortRows(data, this.options.printSortColumn, this.options.printSortOrder)
+    const table = buildTable(data, this.options.columns)
+    const newWin = window.open('')
+    const printStyles = typeof this.options.printStyles === 'string' ?
+      this.options.printStyles.replace(/\[|\]| /g, '').toLowerCase().split(',') :
+      this.options.printStyles
+    const styles = printStyles.map(it =>
+      `<link rel="stylesheet" href="${it}" />`).join('')
+
+    const calculatedPrintPage = Utils.calculateObjectValue(this, this.options.printPageBuilder,
+      [table, styles], printPageBuilderDefault(table, styles))
+    const startPrint = () => {
+      newWin.focus()
+      newWin.print()
+      newWin.close()
+    }
+
+    newWin.document.write(calculatedPrintPage)
+    newWin.document.close()
+
+    if (printStyles.length) {
+      const links = document.getElementsByTagName('link')
+      const lastLink = links[links.length - 1]
+
+      lastLink.onload = startPrint
+    } else {
+      startPrint()
+    }
+  }
+}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/reorder-columns/bootstrap-table-reorder-columns.js b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/reorder-columns/bootstrap-table-reorder-columns.js
new file mode 100644
index 0000000..6c893be
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/reorder-columns/bootstrap-table-reorder-columns.js
@@ -0,0 +1,212 @@
+/**
+ * @author: Dennis Hernández
+ * @update: https://github.com/wenzhixin
+ * @version: v1.2.0
+ */
+
+$.akottr.dragtable.prototype._restoreState = function (persistObj) {
+  let i = 0
+
+  for (const [field, value] of Object.entries(persistObj)) {
+    const $th = this.originalTable.el.find(`th[data-field="${field}"]`)
+
+    if (!$th.length) {
+      i++
+      continue
+    }
+
+    this.originalTable.startIndex = $th.prevAll().length + 1
+    this.originalTable.endIndex = parseInt(value, 10) + 1 - i
+    this._bubbleCols()
+  }
+}
+
+// From MDN site, https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
+const filterFn = () => {
+  if (!Array.prototype.filter) {
+    Array.prototype.filter = function (fun/* , thisArg*/) {
+      if (this === undefined || this === null) {
+        throw new TypeError()
+      }
+
+      const t = Object(this)
+      const len = t.length >>> 0
+
+      if (typeof fun !== 'function') {
+        throw new TypeError()
+      }
+
+      const res = []
+      const thisArg = arguments.length >= 2 ? arguments[1] : undefined
+
+      for (let i = 0; i < len; i++) {
+        if (i in t) {
+          const val = t[i]
+
+          // NOTE: Technically this should Object.defineProperty at
+          //       the next index, as push can be affected by
+          //       properties on Object.prototype and Array.prototype.
+          //       But this method's new, and collisions should be
+          //       rare, so use the more-compatible alternative.
+          if (fun.call(thisArg, val, i, t)) {
+            res.push(val)
+          }
+        }
+      }
+
+      return res
+    }
+  }
+}
+
+Object.assign($.fn.bootstrapTable.defaults, {
+  reorderableColumns: false,
+  maxMovingRows: 10,
+  // eslint-disable-next-line no-unused-vars
+  onReorderColumn (headerFields) {
+    return false
+  },
+  dragaccept: null
+})
+
+Object.assign($.fn.bootstrapTable.events, {
+  'reorder-column.bs.table': 'onReorderColumn'
+})
+
+$.fn.bootstrapTable.methods.push('orderColumns')
+
+$.BootstrapTable = class extends $.BootstrapTable {
+  initHeader (...args) {
+    super.initHeader(...args)
+
+    if (!this.options.reorderableColumns) {
+      return
+    }
+
+    this.makeColumnsReorderable()
+  }
+
+  _toggleColumn (...args) {
+    super._toggleColumn(...args)
+
+    if (!this.options.reorderableColumns) {
+      return
+    }
+
+    this.makeColumnsReorderable()
+  }
+
+  toggleView (...args) {
+    super.toggleView(...args)
+
+    if (!this.options.reorderableColumns) {
+      return
+    }
+
+    if (this.options.cardView) {
+      return
+    }
+
+    this.makeColumnsReorderable()
+  }
+
+  resetView (...args) {
+    super.resetView(...args)
+
+    if (!this.options.reorderableColumns) {
+      return
+    }
+
+    this.makeColumnsReorderable()
+  }
+
+  makeColumnsReorderable (order = null) {
+    try {
+      $(this.$el).dragtable('destroy')
+    } catch (e) {
+      // do nothing
+    }
+    $(this.$el).dragtable({
+      maxMovingRows: this.options.maxMovingRows,
+      dragaccept: this.options.dragaccept,
+      clickDelay: 200,
+      dragHandle: '.th-inner',
+      restoreState: order ? order : this.columnsSortOrder,
+      beforeStop: table => {
+        const sortOrder = {}
+
+        table.el.find('th').each((i, el) => {
+          sortOrder[$(el).data('field')] = i
+        })
+
+        this.columnsSortOrder = sortOrder
+        if (this.options.cookie) {
+          this.persistReorderColumnsState(this)
+        }
+
+        const ths = []
+        const formatters = []
+        const columns = []
+        let columnsHidden = []
+        let columnIndex = -1
+        const optionsColumns = []
+
+        this.$header.find('th:not(.detail)').each((i, el) => {
+          ths.push($(el).data('field'))
+          formatters.push($(el).data('formatter'))
+        })
+
+        // Exist columns not shown
+        if (ths.length < this.columns.length) {
+          columnsHidden = this.columns.filter(column => !column.visible)
+          for (let i = 0; i < columnsHidden.length; i++) {
+            ths.push(columnsHidden[i].field)
+            formatters.push(columnsHidden[i].formatter)
+          }
+        }
+
+        for (let i = 0; i < ths.length; i++) {
+          columnIndex = this.fieldsColumnsIndex[ths[i]]
+          if (columnIndex !== -1) {
+            this.fieldsColumnsIndex[ths[i]] = i
+            this.columns[columnIndex].fieldIndex = i
+            columns.push(this.columns[columnIndex])
+          }
+        }
+
+        this.columns = columns
+
+        filterFn() // Support <IE9
+        $.each(this.columns, (i, column) => {
+          let found = false
+          const field = column.field
+
+          this.options.columns[0].filter(item => {
+            if (!found && item['field'] === field) {
+              optionsColumns.push(item)
+              found = true
+              return false
+            }
+            return true
+          })
+        })
+
+        this.options.columns[0] = optionsColumns
+
+        this.header.fields = ths
+        this.header.formatters = formatters
+        this.initHeader()
+        this.initToolbar()
+        this.initSearchText()
+        this.initBody()
+        this.resetView()
+        this.trigger('reorder-column', ths)
+      }
+    })
+  }
+
+  orderColumns (order) {
+    this.columnsSortOrder = order
+    this.makeColumnsReorderable()
+  }
+}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/reorder-columns/jquery.dragtable.js b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/reorder-columns/jquery.dragtable.js
new file mode 100644
index 0000000..01c18f1
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/reorder-columns/jquery.dragtable.js
@@ -0,0 +1,22 @@
+/**
+ * Minified by jsDelivr using Terser v5.3.5.
+ * Original file: /gh/akottr/dragtable@master/jquery.dragtable.js
+ *
+ * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
+ */
+/*!
+ * dragtable
+ *
+ * @Version 2.0.15
+ *
+ * Copyright (c) 2010-2013, Andres akottr@gmail.com
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * Inspired by the the dragtable from Dan Vanderkam (danvk.org/dragtable/)
+ * Thanks to the jquery and jqueryui comitters
+ *
+ * Any comment, bug report, feature-request is welcome
+ * Feel free to contact me.
+ */
+!function(e){e.widget("akottr.dragtable",{options:{revert:!1,dragHandle:".table-handle",maxMovingRows:40,excludeFooter:!1,onlyHeaderThreshold:100,dragaccept:null,persistState:null,restoreState:null,exact:!0,clickDelay:10,containment:null,cursor:"move",cursorAt:!1,distance:0,tolerance:"pointer",axis:"x",beforeStart:e.noop,beforeMoving:e.noop,beforeReorganize:e.noop,beforeStop:e.noop},originalTable:{el:null,selectedHandle:null,sortOrder:null,startIndex:0,endIndex:0},sortableTable:{el:e(),selectedHandle:e(),movingRow:e()},persistState:function(){var t=this;this.originalTable.el.find("th").each((function(e){""!==this.id&&(t.originalTable.sortOrder[this.id]=e)})),e.ajax({url:this.options.persistState,data:this.originalTable.sortOrder})},_restoreState:function(t){for(var i in t)this.originalTable.startIndex=e("#"+i).closest("th").prevAll().length+1,this.originalTable.endIndex=parseInt(t[i],10)+1,this._bubbleCols()},_bubbleCols:function(){var e,t,i,o,a=this.originalTable.startIndex,l=this.originalTable.endIndex,s=this.originalTable.el.children();if(this.options.excludeFooter&&(s=s.not("tfoot")),a<l)for(e=a;e<l;e++)for(i=s.find("> tr > td:nth-child("+e+")").add(s.find("> tr > th:nth-child("+e+")")),o=s.find("> tr > td:nth-child("+(e+1)+")").add(s.find("> tr > th:nth-child("+(e+1)+")")),t=0;t<i.length;t++)n(i[t],o[t]);else for(e=a;e>l;e--)for(i=s.find("> tr > td:nth-child("+e+")").add(s.find("> tr > th:nth-child("+e+")")),o=s.find("> tr > td:nth-child("+(e-1)+")").add(s.find("> tr > th:nth-child("+(e-1)+")")),t=0;t<i.length;t++)n(i[t],o[t])},_rearrangeTableBackroundProcessing:function(){var n=this;return function(){n._bubbleCols(),n.options.beforeStop(n.originalTable),n.sortableTable.el.remove(),function(){e("#__dragtable_disable_text_selection__").remove(),t?e(document.body).attr("onselectstart",t):e(document.body).removeAttr("onselectstart");i?e(document.body).attr("unselectable",i):e(document.body).removeAttr("unselectable")}(),null!==n.options.persistState&&(e.isFunction(n.options.persistState)?n.options.persistState(n.originalTable):n.persistState())}},_rearrangeTable:function(){var e=this;return function(){e.originalTable.selectedHandle.removeClass("dragtable-handle-selected"),e.sortableTable.el.sortable("disable"),e.sortableTable.el.addClass("dragtable-disabled"),e.options.beforeReorganize(e.originalTable,e.sortableTable),e.originalTable.endIndex=e.sortableTable.movingRow.prevAll().length+1,setTimeout(e._rearrangeTableBackroundProcessing(),50)}},_generateSortable:function(t){!t.cancelBubble&&(t.cancelBubble=!0);for(var i=this,n=this.originalTable.el[0].attributes,o="",a=0;a<n.length;a++)n[a].nodeValue&&"id"!=n[a].nodeName&&"width"!=n[a].nodeName&&(o+=n[a].nodeName+'="'+n[a].nodeValue+'" ');var l=[],s=[];this.originalTable.el.find("tr").slice(0,this.options.maxMovingRows).each((function(t,i){for(var n=this.attributes,o="",a=0;a<n.length;a++)n[a].nodeValue&&"id"!=n[a].nodeName&&(o+=" "+n[a].nodeName+'="'+n[a].nodeValue+'"');l.push(o),s.push(e(this).height())}));var r=[],d=0,h=i.originalTable.el.children();if(this.options.excludeFooter&&(h=h.not("tfoot")),h.find("> tr > th").each((function(t,i){var n=e(this).is(":visible")?e(this).outerWidth():0;r.push(n),d+=n})),i.options.exact){var c=d-i.originalTable.el.outerWidth();r[0]-=c}var b='<ul class="dragtable-sortable" style="position:absolute; width:'+(d+=2)+'px;">';h.find("> tr > th").each((function(t,n){var a=e(this).is(":visible")?e(this).outerWidth():0;b+='<li style="width:'+a+'px;">',b+="<table "+o+">";var r=h.find("> tr > th:nth-child("+(t+1)+")");i.options.maxMovingRows>1&&(r=r.add(h.find("> tr > td:nth-child("+(t+1)+")").slice(0,i.options.maxMovingRows-1))),r.each((function(t){var i=e(this).clone().wrap("<div></div>").parent().html();0===i.toLowerCase().indexOf("<th")&&(b+="<thead>"),b+="<tr "+l[t]+'" style="height:'+s[t]+'px;">',b+=i,0===i.toLowerCase().indexOf("<th")&&(b+="</thead>"),b+="</tr>"})),b+="</table>",b+="</li>"})),b+="</ul>",this.sortableTable.el=this.originalTable.el.before(b).prev(),this.sortableTable.el.find("> li > table").each((function(t,i){e(this).css("width",r[t]+"px")})),this.sortableTable.selectedHandle=this.sortableTable.el.find("th .dragtable-handle-selected");var u,g=this.options.dragaccept?"li:has("+this.options.dragaccept+")":"li";this.sortableTable.el.sortable({items:g,stop:this._rearrangeTable(),revert:this.options.revert,tolerance:this.options.tolerance,containment:this.options.containment,cursor:this.options.cursor,cursorAt:this.options.cursorAt,distance:this.options.distance,axis:this.options.axis}),this.originalTable.startIndex=e(t.target).closest("th").prevAll().length+1,this.options.beforeMoving(this.originalTable,this.sortableTable),this.sortableTable.movingRow=this.sortableTable.el.find("> li:nth-child("+this.originalTable.startIndex+")"),u=e('<style id="__dragtable_disable_text_selection__" type="text/css">body { -ms-user-select:none;-moz-user-select:-moz-none;-khtml-user-select:none;-webkit-user-select:none;user-select:none; }</style>'),e(document.head).append(u),e(document.body).attr("onselectstart","return false;").attr("unselectable","on"),window.getSelection?window.getSelection().removeAllRanges():document.selection.empty(),this.sortableTable.movingRow.trigger(e.extend(e.Event(t.type),{which:1,clientX:t.clientX,clientY:t.clientY,pageX:t.pageX,pageY:t.pageY,screenX:t.screenX,screenY:t.screenY}));var p=this.sortableTable.el.find(".ui-sortable-placeholder");!p.height()<=0&&p.css("height",this.sortableTable.el.find(".ui-sortable-helper").height()),p.html('<div class="outer" style="height:100%;"><div class="inner" style="height:100%;"></div></div>')},bindTo:{},_create:function(){this.originalTable={el:this.element,selectedHandle:e(),sortOrder:{},startIndex:0,endIndex:0},this.bindTo=this.originalTable.el.find("th"),this.options.dragaccept&&(this.bindTo=this.bindTo.filter(this.options.dragaccept)),this.bindTo.find(this.options.dragHandle).length>0&&(this.bindTo=this.bindTo.find(this.options.dragHandle)),null!==this.options.restoreState&&(e.isFunction(this.options.restoreState)?this.options.restoreState(this.originalTable):this._restoreState(this.options.restoreState));var t=this;this.bindTo.mousedown((function(i){1===i.which&&!1!==t.options.beforeStart(t.originalTable)&&(clearTimeout(this.downTimer),this.downTimer=setTimeout((function(){t.originalTable.selectedHandle=e(this),t.originalTable.selectedHandle.addClass("dragtable-handle-selected"),t._generateSortable(i)}),t.options.clickDelay))})).mouseup((function(e){clearTimeout(this.downTimer)}))},redraw:function(){this.destroy(),this._create()},destroy:function(){this.bindTo.unbind("mousedown"),e.Widget.prototype.destroy.apply(this,arguments)}});var t=e(document.body).attr("onselectstart"),i=e(document.body).attr("unselectable");function n(e,t){var i=e.parentNode,n=e.nextSibling===t?e:e.nextSibling;t.parentNode.insertBefore(e,t),i.insertBefore(t,n)}}(jQuery);
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/reorder-rows/bootstrap-table-reorder-rows.js b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/reorder-rows/bootstrap-table-reorder-rows.js
new file mode 100644
index 0000000..ff8a65e
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/reorder-rows/bootstrap-table-reorder-rows.js
@@ -0,0 +1,145 @@
+/**
+ * @author: Dennis Hernández
+ * @update zhixin wen <wenzhixin2010@gmail.com>
+ */
+
+const rowAttr = (row, index) => ({
+  id: `customId_${index}`
+})
+
+Object.assign($.fn.bootstrapTable.defaults, {
+  reorderableRows: false,
+  onDragStyle: null,
+  onDropStyle: null,
+  onDragClass: 'reorder-rows-on-drag-class',
+  dragHandle: '>tbody>tr>td:not(.bs-checkbox)',
+  useRowAttrFunc: false,
+  // eslint-disable-next-line no-unused-vars
+  onReorderRowsDrag (row) {
+    return false
+  },
+  // eslint-disable-next-line no-unused-vars
+  onReorderRowsDrop (row) {
+    return false
+  },
+  // eslint-disable-next-line no-unused-vars
+  onReorderRow (newData) {
+    return false
+  },
+  onDragStop () {},
+  onAllowDrop () {
+    return true
+  }
+})
+
+Object.assign($.fn.bootstrapTable.events, {
+  'reorder-row.bs.table': 'onReorderRow'
+})
+
+$.BootstrapTable = class extends $.BootstrapTable {
+  init (...args) {
+    if (!this.options.reorderableRows) {
+      super.init(...args)
+      return
+    }
+
+    if (this.options.useRowAttrFunc) {
+      this.options.rowAttributes = rowAttr
+    }
+
+    const onPostBody = this.options.onPostBody
+
+    this.options.onPostBody = () => {
+      setTimeout(() => {
+        this.makeRowsReorderable()
+        onPostBody.call(this.options, this.options.data)
+      }, 1)
+    }
+
+    super.init(...args)
+  }
+
+  makeRowsReorderable () {
+    this.$el.tableDnD({
+      onDragStyle: this.options.onDragStyle,
+      onDropStyle: this.options.onDropStyle,
+      onDragClass: this.options.onDragClass,
+      onAllowDrop: (hoveredRow, draggedRow) => this.onAllowDrop(hoveredRow, draggedRow),
+      onDragStop: (table, draggedRow) => this.onDragStop(table, draggedRow),
+      onDragStart: (table, droppedRow) => this.onDropStart(table, droppedRow),
+      onDrop: (table, droppedRow) => this.onDrop(table, droppedRow),
+      dragHandle: this.options.dragHandle
+    })
+  }
+
+  onDropStart (table, draggingTd) {
+    this.$draggingTd = $(draggingTd).css('cursor', 'move')
+    this.draggingIndex = $(this.$draggingTd.parent()).data('index')
+    // Call the user defined function
+    this.options.onReorderRowsDrag(this.data[this.draggingIndex])
+  }
+
+  onDragStop (table, draggedRow) {
+    const rowIndexDraggedRow = $(draggedRow).data('index')
+    const draggedRowItem = this.data[rowIndexDraggedRow]
+
+    this.options.onDragStop(table, draggedRowItem, draggedRow)
+  }
+
+  onAllowDrop (hoveredRow, draggedRow) {
+    const rowIndexDraggedRow = $(draggedRow).data('index')
+    const rowIndexHoveredRow = $(hoveredRow).data('index')
+    const draggedRowItem = this.data[rowIndexDraggedRow]
+    const hoveredRowItem = this.data[rowIndexHoveredRow]
+
+    return this.options.onAllowDrop(hoveredRowItem, draggedRowItem, hoveredRow, draggedRow)
+  }
+
+  onDrop (table) {
+    this.$draggingTd.css('cursor', '')
+    const pageNum = this.options.pageNumber
+    const pageSize = this.options.pageSize
+    const newData = []
+
+    for (let i = 0; i < table.tBodies[0].rows.length; i++) {
+      const $tr = $(table.tBodies[0].rows[i])
+
+      newData.push(this.data[$tr.data('index')])
+      $tr.data('index', i)
+    }
+
+    const draggingRow = this.data[this.draggingIndex]
+    const droppedIndex = newData.indexOf(this.data[this.draggingIndex])
+    const droppedRow = this.data[droppedIndex]
+    const index = (pageNum - 1) * pageSize + this.options.data.indexOf(this.data[droppedIndex])
+
+    this.options.data.splice(this.options.data.indexOf(draggingRow), 1)
+    this.options.data.splice(index, 0, draggingRow)
+
+    this.initSearch()
+
+    if (this.options.sidePagination === 'server') {
+      this.data = [...this.options.data]
+    }
+
+    // Call the user defined function
+    this.options.onReorderRowsDrop(droppedRow)
+
+    // Call the event reorder-row
+    this.trigger('reorder-row', newData, draggingRow, droppedRow)
+  }
+
+  initSearch () {
+    this.ignoreInitSort = true
+    super.initSearch()
+  }
+
+  initSort () {
+    if (this.ignoreInitSort) {
+      this.ignoreInitSort = false
+      return
+    }
+
+    super.initSort()
+  }
+}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/reorder-rows/jquery.tablednd.js b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/reorder-rows/jquery.tablednd.js
new file mode 100644
index 0000000..08f9a12
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/reorder-rows/jquery.tablednd.js
@@ -0,0 +1,603 @@
+/**
+ * TableDnD plug-in for JQuery, allows you to drag and drop table rows
+ * You can set up various options to control how the system will work
+ * Copyright (c) Denis Howlett <denish@isocra.com>
+ * License: MIT.
+ * See https://github.com/isocra/TableDnD
+ */
+!function ($, window, document, undefined) {
+
+var startEvent = 'touchstart mousedown',
+    moveEvent  = 'touchmove mousemove',
+    endEvent   = 'touchend mouseup';
+
+$(document).ready(function () {
+    function parseStyle(css) {
+        var objMap = {},
+            parts = css.match(/([^;:]+)/g) || [];
+        while (parts.length)
+            objMap[parts.shift()] = parts.shift().trim();
+
+        return objMap;
+    }
+    $('table').each(function () {
+        if ($(this).data('table') === 'dnd') {
+
+            $(this).tableDnD({
+                onDragStyle: $(this).data('ondragstyle') && parseStyle($(this).data('ondragstyle')) || null,
+                onDropStyle: $(this).data('ondropstyle') && parseStyle($(this).data('ondropstyle')) || null,
+                onDragClass: $(this).data('ondragclass') === undefined && "tDnD_whileDrag" || $(this).data('ondragclass'),
+                onDrop: $(this).data('ondrop') && new Function('table', 'row', $(this).data('ondrop')), // 'return eval("'+$(this).data('ondrop')+'");') || null,
+                onDragStart: $(this).data('ondragstart') && new Function('table', 'row' ,$(this).data('ondragstart')), // 'return eval("'+$(this).data('ondragstart')+'");') || null,
+                onDragStop: $(this).data('ondragstop') && new Function('table', 'row' ,$(this).data('ondragstop')),
+                scrollAmount: $(this).data('scrollamount') || 5,
+                sensitivity: $(this).data('sensitivity') || 10,
+                hierarchyLevel: $(this).data('hierarchylevel') || 0,
+                indentArtifact: $(this).data('indentartifact') || '<div class="indent">&nbsp;</div>',
+                autoWidthAdjust: $(this).data('autowidthadjust') || true,
+                autoCleanRelations: $(this).data('autocleanrelations') || true,
+                jsonPretifySeparator: $(this).data('jsonpretifyseparator') || '\t',
+                serializeRegexp: $(this).data('serializeregexp') && new RegExp($(this).data('serializeregexp')) || /[^\-]*$/,
+                serializeParamName: $(this).data('serializeparamname') || false,
+                dragHandle: $(this).data('draghandle') || null
+            });
+        }
+
+
+    });
+});
+
+jQuery.tableDnD = {
+    /** Keep hold of the current table being dragged */
+    currentTable: null,
+    /** Keep hold of the current drag object if any */
+    dragObject: null,
+    /** The current mouse offset */
+    mouseOffset: null,
+    /** Remember the old value of X and Y so that we don't do too much processing */
+    oldX: 0,
+    oldY: 0,
+
+    /** Actually build the structure */
+    build: function(options) {
+        // Set up the defaults if any
+
+        this.each(function() {
+            // This is bound to each matching table, set up the defaults and override with user options
+            this.tableDnDConfig = $.extend({
+                onDragStyle: null,
+                onDropStyle: null,
+                // Add in the default class for whileDragging
+                onDragClass: "tDnD_whileDrag",
+                onDrop: null,
+                onDragStart: null,
+                onDragStop: null,
+                scrollAmount: 5,
+                /** Sensitivity setting will throttle the trigger rate for movement detection */
+                sensitivity: 10,
+                /** Hierarchy level to support parent child. 0 switches this functionality off */
+                hierarchyLevel: 0,
+                /** The html artifact to prepend the first cell with as indentation */
+                indentArtifact: '<div class="indent">&nbsp;</div>',
+                /** Automatically adjust width of first cell */
+                autoWidthAdjust: true,
+                /** Automatic clean-up to ensure relationship integrity */
+                autoCleanRelations: true,
+                /** Specify a number (4) as number of spaces or any indent string for JSON.stringify */
+                jsonPretifySeparator: '\t',
+                /** The regular expression to use to trim row IDs */
+                serializeRegexp: /[^\-]*$/,
+                /** If you want to specify another parameter name instead of the table ID */
+                serializeParamName: false,
+                /** If you give the name of a class here, then only Cells with this class will be draggable */
+                dragHandle: null
+            }, options || {});
+
+            // Now make the rows draggable
+            $.tableDnD.makeDraggable(this);
+            // Prepare hierarchy support
+            this.tableDnDConfig.hierarchyLevel
+                && $.tableDnD.makeIndented(this);
+        });
+
+        // Don't break the chain
+        return this;
+    },
+    makeIndented: function (table) {
+        var config = table.tableDnDConfig,
+            rows = table.rows,
+            firstCell = $(rows).first().find('td:first')[0],
+            indentLevel = 0,
+            cellWidth = 0,
+            longestCell,
+            tableStyle;
+
+        if ($(table).hasClass('indtd'))
+            return null;
+
+        tableStyle = $(table).addClass('indtd').attr('style');
+        $(table).css({whiteSpace: "nowrap"});
+
+        for (var w = 0; w < rows.length; w++) {
+            if (cellWidth < $(rows[w]).find('td:first').text().length) {
+                cellWidth = $(rows[w]).find('td:first').text().length;
+                longestCell = w;
+            }
+        }
+        $(firstCell).css({width: 'auto'});
+        for (w = 0; w < config.hierarchyLevel; w++)
+            $(rows[longestCell]).find('td:first').prepend(config.indentArtifact);
+        firstCell && $(firstCell).css({width: firstCell.offsetWidth});
+        tableStyle && $(table).css(tableStyle);
+
+        for (w = 0; w < config.hierarchyLevel; w++)
+            $(rows[longestCell]).find('td:first').children(':first').remove();
+
+        config.hierarchyLevel
+            && $(rows).each(function () {
+                indentLevel = $(this).data('level') || 0;
+                indentLevel <= config.hierarchyLevel
+                    && $(this).data('level', indentLevel)
+                    || $(this).data('level', 0);
+                for (var i = 0; i < $(this).data('level'); i++)
+                    $(this).find('td:first').prepend(config.indentArtifact);
+            });
+
+        return this;
+    },
+    /** This function makes all the rows on the table draggable apart from those marked as "NoDrag" */
+    makeDraggable: function(table) {
+        var config = table.tableDnDConfig;
+
+        config.dragHandle
+            // We only need to add the event to the specified cells
+            && $(config.dragHandle, table).each(function() {
+                if (! $(this).hasClass("nodrag")) {
+                    // The cell is bound to "this"
+                    $(this).bind(startEvent, function(e) {
+                        if (e.target.tagName === "TD" && event.target.className !== "nodrag") {
+                    	    $.tableDnD.initialiseDrag($(this).parents('tr')[0], table, this, e, config);
+                            return false;
+                	    }
+                        return true;
+                    });
+                }
+            })
+            // For backwards compatibility, we add the event to the whole row
+            // get all the rows as a wrapped set
+            || $(table.rows).each(function() {
+                // Iterate through each row, the row is bound to "this"
+                if (! $(this).hasClass("nodrag")) {
+                    $(this).bind(startEvent, function(e) {
+                        if (e.target.tagName === "TD" && event.target.className !== "nodrag") {
+                            $.tableDnD.initialiseDrag(this, table, this, e, config);
+                            return false;
+                        }
+                    }).css("cursor", "move"); // Store the tableDnD object
+                } else {
+                    $(this).css("cursor", ""); // Remove the cursor if we don't have the nodrag class
+                }
+            });
+    },
+    currentOrder: function() {
+        var rows = this.currentTable.rows;
+        return $.map(rows, function (val) {
+            return ($(val).data('level') + val.id).replace(/\s/g, '');
+        }).join('');
+    },
+    initialiseDrag: function(dragObject, table, target, e, config) {
+        this.dragObject    = dragObject;
+        this.currentTable  = table;
+        this.mouseOffset   = this.getMouseOffset(target, e);
+        this.originalOrder = this.currentOrder();
+
+        // Now we need to capture the mouse up and mouse move event
+        // We can use bind so that we don't interfere with other event handlers
+        $(document)
+            .bind(moveEvent, this.mousemove)
+            .bind(endEvent, this.mouseup);
+
+        // Call the onDragStart method if there is one
+        config.onDragStart
+            && config.onDragStart(table, target);
+    },
+    updateTables: function() {
+        this.each(function() {
+            // this is now bound to each matching table
+            if (this.tableDnDConfig)
+                $.tableDnD.makeDraggable(this);
+        });
+    },
+    /** Get the mouse coordinates from the event (allowing for browser differences) */
+    mouseCoords: function(e) {
+        if (e.originalEvent.changedTouches)
+            return {
+                x: e.originalEvent.changedTouches[0].clientX,
+                y: e.originalEvent.changedTouches[0].clientY
+            };
+
+        if(e.pageX || e.pageY)
+            return {
+                x: e.pageX,
+                y: e.pageY
+            };
+
+        return {
+            x: e.clientX + document.body.scrollLeft - document.body.clientLeft,
+            y: e.clientY + document.body.scrollTop  - document.body.clientTop
+        };
+    },
+    /** Given a target element and a mouse eent, get the mouse offset from that element.
+     To do this we need the element's position and the mouse position */
+    getMouseOffset: function(target, e) {
+        var mousePos,
+            docPos;
+
+        e = e || window.event;
+
+        docPos    = this.getPosition(target);
+        mousePos  = this.mouseCoords(e);
+
+        return {
+            x: mousePos.x - docPos.x,
+            y: mousePos.y - docPos.y
+        };
+    },
+    /** Get the position of an element by going up the DOM tree and adding up all the offsets */
+    getPosition: function(element) {
+        var left = 0,
+            top  = 0;
+
+        // Safari fix -- thanks to Luis Chato for this!
+        // Safari 2 doesn't correctly grab the offsetTop of a table row
+        // this is detailed here:
+        // http://jacob.peargrove.com/blog/2006/technical/table-row-offsettop-bug-in-safari/
+        // the solution is likewise noted there, grab the offset of a table cell in the row - the firstChild.
+        // note that firefox will return a text node as a first child, so designing a more thorough
+        // solution may need to take that into account, for now this seems to work in firefox, safari, ie
+        if (element.offsetHeight === 0)
+            element = element.firstChild; // a table cell
+
+        while (element.offsetParent) {
+            left   += element.offsetLeft;
+            top    += element.offsetTop;
+            element = element.offsetParent;
+        }
+
+        left += element.offsetLeft;
+        top  += element.offsetTop;
+
+        return {
+            x: left,
+            y: top
+        };
+    },
+    autoScroll: function (mousePos) {
+      var config       = this.currentTable.tableDnDConfig,
+          yOffset      = window.pageYOffset,
+          windowHeight = window.innerHeight
+            ? window.innerHeight
+            : document.documentElement.clientHeight
+            ? document.documentElement.clientHeight
+            : document.body.clientHeight;
+
+        // Windows version
+        // yOffset=document.body.scrollTop;
+        if (document.all)
+            if (typeof document.compatMode !== 'undefined'
+                && document.compatMode !== 'BackCompat')
+                yOffset = document.documentElement.scrollTop;
+            else if (typeof document.body !== 'undefined')
+                yOffset = document.body.scrollTop;
+
+        mousePos.y - yOffset < config.scrollAmount
+            && window.scrollBy(0, - config.scrollAmount)
+        || windowHeight - (mousePos.y - yOffset) < config.scrollAmount
+            && window.scrollBy(0, config.scrollAmount);
+
+    },
+    moveVerticle: function (moving, currentRow) {
+
+        if (0 !== moving.vertical
+            // If we're over a row then move the dragged row to there so that the user sees the
+            // effect dynamically
+            && currentRow
+            && this.dragObject !== currentRow
+            && this.dragObject.parentNode === currentRow.parentNode)
+            0 > moving.vertical
+                && this.dragObject.parentNode.insertBefore(this.dragObject, currentRow.nextSibling)
+            || 0 < moving.vertical
+                && this.dragObject.parentNode.insertBefore(this.dragObject, currentRow);
+
+    },
+    moveHorizontal: function (moving, currentRow) {
+        var config       = this.currentTable.tableDnDConfig,
+            currentLevel;
+
+        if (!config.hierarchyLevel
+            || 0 === moving.horizontal
+            // We only care if moving left or right on the current row
+            || !currentRow
+            || this.dragObject !== currentRow)
+                return null;
+
+            currentLevel = $(currentRow).data('level');
+
+            0 < moving.horizontal
+                && currentLevel > 0
+                && $(currentRow).find('td:first').children(':first').remove()
+                && $(currentRow).data('level', --currentLevel);
+
+            0 > moving.horizontal
+                && currentLevel < config.hierarchyLevel
+                && $(currentRow).prev().data('level') >= currentLevel
+                && $(currentRow).children(':first').prepend(config.indentArtifact)
+                && $(currentRow).data('level', ++currentLevel);
+
+    },
+    mousemove: function(e) {
+        var dragObj      = $($.tableDnD.dragObject),
+            config       = $.tableDnD.currentTable.tableDnDConfig,
+            currentRow,
+            mousePos,
+            moving,
+            x,
+            y;
+
+        e && e.preventDefault();
+
+        if (!$.tableDnD.dragObject)
+            return false;
+
+        // prevent touch device screen scrolling
+        e.type === 'touchmove'
+            && event.preventDefault(); // TODO verify this is event and not really e
+
+        // update the style to show we're dragging
+        config.onDragClass
+            && dragObj.addClass(config.onDragClass)
+            || dragObj.css(config.onDragStyle);
+
+        mousePos = $.tableDnD.mouseCoords(e);
+        x = mousePos.x - $.tableDnD.mouseOffset.x;
+        y = mousePos.y - $.tableDnD.mouseOffset.y;
+
+        // auto scroll the window
+        $.tableDnD.autoScroll(mousePos);
+
+        currentRow = $.tableDnD.findDropTargetRow(dragObj, y);
+        moving = $.tableDnD.findDragDirection(x, y);
+
+        $.tableDnD.moveVerticle(moving, currentRow);
+        $.tableDnD.moveHorizontal(moving, currentRow);
+
+        return false;
+    },
+    findDragDirection: function (x,y) {
+        var sensitivity = this.currentTable.tableDnDConfig.sensitivity,
+            oldX        = this.oldX,
+            oldY        = this.oldY,
+            xMin        = oldX - sensitivity,
+            xMax        = oldX + sensitivity,
+            yMin        = oldY - sensitivity,
+            yMax        = oldY + sensitivity,
+            moving      = {
+                horizontal: x >= xMin && x <= xMax ? 0 : x > oldX ? -1 : 1,
+                vertical  : y >= yMin && y <= yMax ? 0 : y > oldY ? -1 : 1
+            };
+
+        // update the old value
+        if (moving.horizontal !== 0)
+            this.oldX    = x;
+        if (moving.vertical   !== 0)
+            this.oldY    = y;
+
+        return moving;
+    },
+    /** We're only worried about the y position really, because we can only move rows up and down */
+    findDropTargetRow: function(draggedRow, y) {
+        var rowHeight = 0,
+            rows      = this.currentTable.rows,
+            config    = this.currentTable.tableDnDConfig,
+            rowY      = 0,
+            row       = null;
+
+        for (var i = 0; i < rows.length; i++) {
+            row       = rows[i];
+            rowY      = this.getPosition(row).y;
+            rowHeight = parseInt(row.offsetHeight) / 2;
+            if (row.offsetHeight === 0) {
+                rowY      = this.getPosition(row.firstChild).y;
+                rowHeight = parseInt(row.firstChild.offsetHeight) / 2;
+            }
+            // Because we always have to insert before, we need to offset the height a bit
+            if (y > (rowY - rowHeight) && y < (rowY + rowHeight))
+                // that's the row we're over
+                // If it's the same as the current row, ignore it
+                if (draggedRow.is(row)
+                    || (config.onAllowDrop
+                    && !config.onAllowDrop(draggedRow, row))
+                    // If a row has nodrop class, then don't allow dropping (inspired by John Tarr and Famic)
+                    || $(row).hasClass("nodrop"))
+                        return null;
+                else
+                    return row;
+        }
+        return null;
+    },
+    processMouseup: function() {
+        if (!this.currentTable || !this.dragObject)
+            return null;
+
+        var config      = this.currentTable.tableDnDConfig,
+            droppedRow  = this.dragObject,
+            parentLevel = 0,
+            myLevel     = 0;
+
+        // Unbind the event handlers
+        $(document)
+            .unbind(moveEvent, this.mousemove)
+            .unbind(endEvent,  this.mouseup);
+
+        config.hierarchyLevel
+            && config.autoCleanRelations
+            && $(this.currentTable.rows).first().find('td:first').children().each(function () {
+                myLevel = $(this).parents('tr:first').data('level');
+                myLevel
+                    && $(this).parents('tr:first').data('level', --myLevel)
+                    && $(this).remove();
+            })
+            && config.hierarchyLevel > 1
+            && $(this.currentTable.rows).each(function () {
+                myLevel = $(this).data('level');
+                if (myLevel > 1) {
+                    parentLevel = $(this).prev().data('level');
+                    while (myLevel > parentLevel + 1) {
+                        $(this).find('td:first').children(':first').remove();
+                        $(this).data('level', --myLevel);
+                    }
+                }
+            });
+
+        // If we have a dragObject, then we need to release it,
+        // The row will already have been moved to the right place so we just reset stuff
+        config.onDragClass
+            && $(droppedRow).removeClass(config.onDragClass)
+            || $(droppedRow).css(config.onDropStyle);
+
+        this.dragObject = null;
+        // Call the onDrop method if there is one
+        config.onDrop
+            && this.originalOrder !== this.currentOrder()
+            && $(droppedRow).hide().fadeIn('fast')
+            && config.onDrop(this.currentTable, droppedRow);
+
+        // Call the onDragStop method if there is one
+        config.onDragStop
+            && config.onDragStop(this.currentTable, droppedRow);
+
+        this.currentTable = null; // let go of the table too
+    },
+    mouseup: function(e) {
+        e && e.preventDefault();
+        $.tableDnD.processMouseup();
+        return false;
+    },
+    jsonize: function(pretify) {
+        var table = this.currentTable;
+        if (pretify)
+            return JSON.stringify(
+                this.tableData(table),
+                null,
+                table.tableDnDConfig.jsonPretifySeparator
+            );
+        return JSON.stringify(this.tableData(table));
+    },
+    serialize: function() {
+        return $.param(this.tableData(this.currentTable));
+    },
+    serializeTable: function(table) {
+        var result = "";
+        var paramName = table.tableDnDConfig.serializeParamName || table.id;
+        var rows = table.rows;
+        for (var i=0; i<rows.length; i++) {
+            if (result.length > 0) result += "&";
+            var rowId = rows[i].id;
+            if (rowId && table.tableDnDConfig && table.tableDnDConfig.serializeRegexp) {
+                rowId = rowId.match(table.tableDnDConfig.serializeRegexp)[0];
+                result += paramName + '[]=' + rowId;
+            }
+        }
+        return result;
+    },
+    serializeTables: function() {
+        var result = [];
+        $('table').each(function() {
+            this.id && result.push($.param($.tableDnD.tableData(this)));
+        });
+        return result.join('&');
+    },
+    tableData: function (table) {
+        var config = table.tableDnDConfig,
+            previousIDs  = [],
+            currentLevel = 0,
+            indentLevel  = 0,
+            rowID        = null,
+            data         = {},
+            getSerializeRegexp,
+            paramName,
+            currentID,
+            rows;
+
+        if (!table)
+            table = this.currentTable;
+        if (!table || !table.rows || !table.rows.length)
+            return {error: { code: 500, message: "Not a valid table."}};
+        if (!table.id && !config.serializeParamName)
+            return {error: { code: 500, message: "No serializable unique id provided."}};
+        
+        rows      = config.autoCleanRelations
+                        && table.rows
+                        || $.makeArray(table.rows);
+        paramName = config.serializeParamName || table.id;
+        currentID = paramName;
+
+        getSerializeRegexp = function (rowId) {
+            if (rowId && config && config.serializeRegexp)
+                return rowId.match(config.serializeRegexp)[0];
+            return rowId;
+        };
+
+        data[currentID] = [];
+        !config.autoCleanRelations
+            && $(rows[0]).data('level')
+            && rows.unshift({id: 'undefined'});
+
+
+
+        for (var i=0; i < rows.length; i++) {
+            if (config.hierarchyLevel) {
+                indentLevel = $(rows[i]).data('level') || 0;
+                if (indentLevel === 0) {
+                    currentID   = paramName;
+                    previousIDs = [];
+                }
+                else if (indentLevel > currentLevel) {
+                    previousIDs.push([currentID, currentLevel]);
+                    currentID = getSerializeRegexp(rows[i-1].id);
+                }
+                else if (indentLevel < currentLevel) {
+                    for (var h = 0; h < previousIDs.length; h++) {
+                        if (previousIDs[h][1] === indentLevel)
+                            currentID         = previousIDs[h][0];
+                        if (previousIDs[h][1] >= currentLevel)
+                            previousIDs[h][1] = 0;
+                    }
+                }
+                currentLevel = indentLevel;
+
+                if (!$.isArray(data[currentID]))
+                    data[currentID] = [];
+                rowID = getSerializeRegexp(rows[i].id);
+                rowID && data[currentID].push(rowID);
+            }
+            else {
+                rowID = getSerializeRegexp(rows[i].id);
+                rowID && data[currentID].push(rowID);
+            }
+        }
+        return data;
+    }
+};
+
+jQuery.fn.extend(
+    {
+        tableDnD             : $.tableDnD.build,
+        tableDnDUpdate       : $.tableDnD.updateTables,
+        tableDnDSerialize    : $.proxy($.tableDnD.serialize, $.tableDnD),
+        tableDnDSerializeAll : $.tableDnD.serializeTables,
+        tableDnDData         : $.proxy($.tableDnD.tableData, $.tableDnD)
+    }
+);
+
+}(jQuery, window, window.document);
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/resizable/bootstrap-table-resizable.js b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/resizable/bootstrap-table-resizable.js
new file mode 100644
index 0000000..7d2c2ba
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/resizable/bootstrap-table-resizable.js
@@ -0,0 +1,68 @@
+/**
+ * @author: Dennis Hernández
+ * @version: v2.0.0
+ */
+
+const isInit = that => that.$el.data('resizableColumns') !== undefined
+
+const initResizable = that => {
+  if (
+    that.options.resizable &&
+    !that.options.cardView &&
+    !isInit(that) &&
+    that.$el.is(':visible')
+  ) {
+    that.$el.resizableColumns({
+      store: window.store
+    })
+  }
+}
+
+const destroy = that => {
+  if (isInit(that)) {
+    that.$el.data('resizableColumns').destroy()
+  }
+}
+
+const reInitResizable = that => {
+  destroy(that)
+  initResizable(that)
+}
+
+Object.assign($.fn.bootstrapTable.defaults, {
+  resizable: false
+})
+
+$.BootstrapTable = class extends $.BootstrapTable {
+
+  initBody (...args) {
+    super.initBody(...args)
+
+    this.$el.off('column-switch.bs.table page-change.bs.table')
+      .on('column-switch.bs.table page-change.bs.table', () => {
+        reInitResizable(this)
+      })
+
+    reInitResizable(this)
+  }
+
+  toggleView (...args) {
+    super.toggleView(...args)
+
+    if (this.options.resizable && this.options.cardView) {
+      // Destroy the plugin
+      destroy(this)
+    }
+  }
+
+  resetView (...args) {
+    super.resetView(...args)
+
+    if (this.options.resizable) {
+      // because in fitHeader function, we use setTimeout(func, 100);
+      setTimeout(() => {
+        initResizable(this)
+      }, 100)
+    }
+  }
+}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/resizable/jquery.resizableColumns.min.js b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/resizable/jquery.resizableColumns.min.js
new file mode 100644
index 0000000..d5129fe
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/resizable/jquery.resizableColumns.min.js
@@ -0,0 +1,8 @@
+/**
+ * jquery-resizable-columns - Resizable table columns for jQuery
+ * @date Sat May 16 2015 19:03:57 GMT+0100 (BST)
+ * @version v0.1.0
+ * @link http://dobtco.github.io/jquery-resizable-columns/
+ * @license MIT
+ */
+!function t(e,i,n){function s(a,o){if(!i[a]){if(!e[a]){var h="function"==typeof require&&require;if(!o&&h)return h(a,!0);if(r)return r(a,!0);var l=new Error("Cannot find module '"+a+"'");throw l.code="MODULE_NOT_FOUND",l}var d=i[a]={exports:{}};e[a][0].call(d.exports,function(t){var i=e[a][1][t];return s(i?i:t)},d,d.exports,t,e,i,n)}return i[a].exports}for(var r="function"==typeof require&&require,a=0;a<n.length;a++)s(n[a]);return s}({1:[function(t,e,i){"use strict";function n(t){return t&&t.__esModule?t:{"default":t}}var s=t("./class"),r=n(s),a=t("./constants");$.fn.resizableColumns=function(t){for(var e=arguments.length,i=Array(e>1?e-1:0),n=1;e>n;n++)i[n-1]=arguments[n];return this.each(function(){var e=$(this),n=e.data(a.DATA_API);if(n){if("string"==typeof t)return n[t].apply(n,i)}else n=new r["default"](e,t),e.data(a.DATA_API,n)})},$.resizableColumns=r["default"]},{"./class":2,"./constants":3}],2:[function(t,e,i){"use strict";function n(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(i,"__esModule",{value:!0});var s=function(){function t(t,e){for(var i=0;i<e.length;i++){var n=e[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,i,n){return i&&t(e.prototype,i),n&&t(e,n),e}}(),r=t("./constants"),a=function(){function t(e,i){n(this,t),this.ns=".rc"+this.count++,this.options=$.extend({},t.defaults,i),this.$window=$(window),this.$ownerDocument=$(e[0].ownerDocument),this.$table=e,this.refreshHeaders(),this.restoreColumnWidths(),this.syncHandleWidths(),this.bindEvents(this.$window,"resize",this.syncHandleWidths.bind(this)),this.options.start&&this.bindEvents(this.$table,r.EVENT_RESIZE_START,this.options.start),this.options.resize&&this.bindEvents(this.$table,r.EVENT_RESIZE,this.options.resize),this.options.stop&&this.bindEvents(this.$table,r.EVENT_RESIZE_STOP,this.options.stop)}return s(t,[{key:"refreshHeaders",value:function(){var t=this.options.selector;"function"==typeof t&&(t=t.call(this,this.$table)),this.$tableHeaders=this.$table.find(t),this.assignPercentageWidths(),this.createHandles()}},{key:"createHandles",value:function(){var t=this,e=this.$handleContainer;null!=e&&e.remove(),this.$handleContainer=$("<div class='"+r.CLASS_HANDLE_CONTAINER+"' />"),this.$table.before(this.$handleContainer),this.$tableHeaders.each(function(e,i){var n=t.$tableHeaders.eq(e),s=t.$tableHeaders.eq(e+1);if(0!==s.length&&!n.is(r.SELECTOR_UNRESIZABLE)&&!s.is(r.SELECTOR_UNRESIZABLE)){$("<div class='"+r.CLASS_HANDLE+"' />").data(r.DATA_TH,$(i)).appendTo(t.$handleContainer)}}),this.bindEvents(this.$handleContainer,["mousedown","touchstart"],"."+r.CLASS_HANDLE,this.onPointerDown.bind(this))}},{key:"assignPercentageWidths",value:function(){var t=this;this.$tableHeaders.each(function(e,i){var n=$(i);t.setWidth(n[0],n.outerWidth()/t.$table.width()*100)})}},{key:"syncHandleWidths",value:function(){var t=this,e=this.$handleContainer;e.width(this.$table.width()),e.find("."+r.CLASS_HANDLE).each(function(e,i){var n=$(i),s=t.options.resizeFromBody?t.$table.height():t.$table.find("thead").height(),a=n.data(r.DATA_TH).outerWidth()+(n.data(r.DATA_TH).offset().left-t.$handleContainer.offset().left);n.css({left:a,height:s})})}},{key:"saveColumnWidths",value:function(){var t=this;this.$tableHeaders.each(function(e,i){var n=$(i);t.options.store&&!n.is(r.SELECTOR_UNRESIZABLE)&&t.options.store.set(t.generateColumnId(n),t.parseWidth(i))})}},{key:"restoreColumnWidths",value:function(){var t=this;this.$tableHeaders.each(function(e,i){var n=$(i);if(t.options.store&&!n.is(r.SELECTOR_UNRESIZABLE)){var s=t.options.store.get(t.generateColumnId(n));null!=s&&t.setWidth(i,s)}})}},{key:"onPointerDown",value:function(t){if(1===t.which){this.operation&&this.onPointerUp(t);var e=$(t.currentTarget);if(!e.is(r.SELECTOR_UNRESIZABLE)){var i=e.index(),n=this.$tableHeaders.eq(i).not(r.SELECTOR_UNRESIZABLE),s=this.$tableHeaders.eq(i+1).not(r.SELECTOR_UNRESIZABLE),a=this.parseWidth(n[0]),o=this.parseWidth(s[0]);this.operation={$leftColumn:n,$rightColumn:s,$currentGrip:e,startX:this.getPointerX(t),widths:{left:a,right:o},newWidths:{left:a,right:o}},this.bindEvents(this.$ownerDocument,["mousemove","touchmove"],this.onPointerMove.bind(this)),this.bindEvents(this.$ownerDocument,["mouseup","touchend"],this.onPointerUp.bind(this)),this.$handleContainer.add(this.$table).addClass(r.CLASS_TABLE_RESIZING),n.add(s).add(e).addClass(r.CLASS_COLUMN_RESIZING),this.triggerEvent(r.EVENT_RESIZE_START,[n,s,a,o],t),t.preventDefault()}}}},{key:"onPointerMove",value:function(t){var e=this.operation;if(this.operation){var i=(this.getPointerX(t)-e.startX)/this.$table.width()*100;if(0!==i){var n=e.$leftColumn[0],s=e.$rightColumn[0],a=void 0,o=void 0;return i>0?(a=this.constrainWidth(e.widths.left+(e.widths.right-e.newWidths.right)),o=this.constrainWidth(e.widths.right-i)):0>i&&(a=this.constrainWidth(e.widths.left+i),o=this.constrainWidth(e.widths.right+(e.widths.left-e.newWidths.left))),n&&this.setWidth(n,a),s&&this.setWidth(s,o),e.newWidths.left=a,e.newWidths.right=o,this.triggerEvent(r.EVENT_RESIZE,[e.$leftColumn,e.$rightColumn,a,o],t)}}}},{key:"onPointerUp",value:function(t){var e=this.operation;if(this.operation)return this.unbindEvents(this.$ownerDocument,["mouseup","touchend","mousemove","touchmove"]),this.$handleContainer.add(this.$table).removeClass(r.CLASS_TABLE_RESIZING),e.$leftColumn.add(e.$rightColumn).add(e.$currentGrip).removeClass(r.CLASS_COLUMN_RESIZING),this.syncHandleWidths(),this.saveColumnWidths(),this.operation=null,this.triggerEvent(r.EVENT_RESIZE_STOP,[e.$leftColumn,e.$rightColumn,e.newWidths.left,e.newWidths.right],t)}},{key:"destroy",value:function(){var t=this.$table,e=this.$handleContainer.find("."+r.CLASS_HANDLE);return this.unbindEvents(this.$window.add(this.$ownerDocument).add(this.$table).add(e)),e.removeData(r.DATA_TH),t.removeData(r.DATA_API),this.$handleContainer.remove(),this.$handleContainer=null,this.$tableHeaders=null,this.$table=null,t}},{key:"bindEvents",value:function(t,e,i,n){"string"==typeof e?e+=this.ns:e=e.join(this.ns+" ")+this.ns,arguments.length>3?t.on(e,i,n):t.on(e,i)}},{key:"unbindEvents",value:function(t,e){"string"==typeof e?e+=this.ns:e=null!=e?e.join(this.ns+" ")+this.ns:this.ns,t.off(e)}},{key:"triggerEvent",value:function(t,e,i){var n=$.Event(t);return n.originalEvent&&(n.originalEvent=$.extend({},i)),this.$table.trigger(n,[this].concat(e||[]))}},{key:"generateColumnId",value:function(t){return this.$table.data(r.DATA_COLUMNS_ID)+"-"+t.data(r.DATA_COLUMN_ID)}},{key:"parseWidth",value:function(t){return t?parseFloat(t.style.width.replace("%","")):0}},{key:"setWidth",value:function(t,e){e=e.toFixed(2),e=e>0?e:0,t.style.width=e+"%"}},{key:"constrainWidth",value:function(t){return void 0!=this.options.minWidth&&(t=Math.max(this.options.minWidth,t)),void 0!=this.options.maxWidth&&(t=Math.min(this.options.maxWidth,t)),t}},{key:"getPointerX",value:function(t){return 0===t.type.indexOf("touch")?(t.originalEvent.touches[0]||t.originalEvent.changedTouches[0]).pageX:t.pageX}}]),t}();i["default"]=a,a.defaults={selector:function(t){return t.find("thead").length?r.SELECTOR_TH:r.SELECTOR_TD},store:window.store,syncHandlers:!0,resizeFromBody:!0,maxWidth:null,minWidth:.01},a.count=0,e.exports=i["default"]},{"./constants":3}],3:[function(t,e,i){"use strict";Object.defineProperty(i,"__esModule",{value:!0});var n="resizableColumns";i.DATA_API=n;var s="resizable-columns-id";i.DATA_COLUMNS_ID=s;var r="resizable-column-id";i.DATA_COLUMN_ID=r;var a="th";i.DATA_TH=a;var o="rc-table-resizing";i.CLASS_TABLE_RESIZING=o;var h="rc-column-resizing";i.CLASS_COLUMN_RESIZING=h;var l="rc-handle";i.CLASS_HANDLE=l;var d="rc-handle-container";i.CLASS_HANDLE_CONTAINER=d;var u="column:resize:start";i.EVENT_RESIZE_START=u;var c="column:resize";i.EVENT_RESIZE=c;var f="column:resize:stop";i.EVENT_RESIZE_STOP=f;var E="tr:first > th:visible";i.SELECTOR_TH=E;var v="tr:first > td:visible";i.SELECTOR_TD=v;var $="[data-noresize]";i.SELECTOR_UNRESIZABLE=$},{}],4:[function(t,e,i){"use strict";function n(t){return t&&t.__esModule?t:{"default":t}}Object.defineProperty(i,"__esModule",{value:!0});{var s=t("./class"),r=n(s),a=t("./adapter");n(a)}i["default"]=r["default"],e.exports=i["default"]},{"./adapter":1,"./class":2}]},{},[4]);
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/tree/bootstrap-table-tree.js b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/tree/bootstrap-table-tree.js
new file mode 100644
index 0000000..a35e4c8
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/tree/bootstrap-table-tree.js
@@ -0,0 +1,1087 @@
+/**
+ * 基于bootstrapTreeTable/bootstrap-table-treegrid修改
+ * Copyright (c) 2019 ruoyi
+ */
+(function($) {
+    "use strict";
+
+    $.fn.bootstrapTreeTable = function(options, param) {
+        var target = $(this).data('bootstrap.tree.table');
+        target = target ? target : $(this);
+        // 如果是调用方法
+        if (typeof options == 'string') {
+            return $.fn.bootstrapTreeTable.methods[options](target, param);
+        }
+        // 如果是初始化组件
+        options = $.extend({}, $.fn.bootstrapTreeTable.defaults, options || {});
+        target.hasSelectItem = false;    // 是否有radio或checkbox
+        target.data_list = null;         // 用于缓存格式化后的数据-按父分组
+        target.data_obj = null;          // 用于缓存格式化后的数据-按id存对象
+        target.hiddenColumns = [];       // 用于存放被隐藏列的field
+        target.lastAjaxParams;           // 用户最后一次请求的参数
+        target.isFixWidth=false;         // 是否有固定宽度
+        target.totalRows = 0;            // 记录总数
+        target.totalPages = 0;           // 总页数
+        // 初始化
+        var init = function() {
+            // 初始化容器
+            initContainer();
+            // 初始化工具栏
+            initToolbar();
+            // 初始化表头
+            initHeader();
+            // 初始化表体
+            initBody();
+            // 初始化数据服务
+            initServer();
+            // 动态设置表头宽度
+            autoTheadWidth(true);
+            // 缓存target对象
+            target.data('bootstrap.tree.table', target);
+        }
+        // 初始化容器
+        var initContainer = function() {
+            // 在外层包装一下div,样式用的bootstrap-table的
+            var $main_div = $("<div class='bootstrap-tree-table'></div>");
+            var $treetable = $("<div class='treetable-table'></div>");
+            target.before($main_div);
+            $main_div.append($treetable);
+            $treetable.append(target);
+            target.addClass("table");
+            if (options.striped) {
+                target.addClass('table-striped');
+            }
+            if (options.bordered) {
+                target.addClass('table-bordered');
+            }
+            if (options.hover) {
+                target.addClass('table-hover');
+            }
+            if (options.condensed) {
+                target.addClass('table-condensed');
+            }
+            target.html("");
+        }
+        // 初始化工具栏
+        var initToolbar = function() {
+            var $toolbar = $("<div class='treetable-bars'></div>");
+            if (options.toolbar) {
+                $(options.toolbar).addClass('tool-left');
+                $toolbar.append($(options.toolbar));
+            }
+            var $rightToolbar = $('<div class="btn-group tool-right">');
+            $toolbar.append($rightToolbar);
+            target.parent().before($toolbar);
+            // ruoyi 是否显示检索信息
+            if (options.showSearch) {
+                var $searchBtn = $('<button class="btn btn-default btn-outline" type="button" aria-label="search" title="搜索"><i class="glyphicon glyphicon-search"></i></button>');
+                $rightToolbar.append($searchBtn);
+                registerSearchBtnClickEvent($searchBtn);
+            }
+            // 是否显示刷新按钮
+            if (options.showRefresh) {
+                var $refreshBtn = $('<button class="btn btn-default btn-outline" type="button" aria-label="refresh" title="刷新"><i class="glyphicon glyphicon-repeat"></i></button>');
+                $rightToolbar.append($refreshBtn);
+                registerRefreshBtnClickEvent($refreshBtn);
+            }
+            // 是否显示列选项
+            if (options.showColumns) {
+                var $columns_div = $('<div class="btn-group pull-right" title="列"><button type="button" aria-label="columns" class="btn btn-default btn-outline dropdown-toggle" data-toggle="dropdown" aria-expanded="false"><i class="glyphicon glyphicon-list"></i> <span class="caret"></span></button></div>');
+                var $columns_ul = $('<ul class="dropdown-menu columns" role="menu"></ul>');
+                $.each(options.columns, function(i, column) {
+                    if (column.field != 'selectItem') {
+                        var _li = null;
+                        if(typeof column.visible == "undefined"||column.visible==true){
+                            _li = $('<li role="menuitem"><label><input type="checkbox" checked="checked" data-field="'+column.field+'" value="'+column.field+'" > '+column.title+'</label></li>');
+                        }else{
+                            _li = $('<li role="menuitem"><label><input type="checkbox" data-field="'+column.field+'" value="'+column.field+'" > '+column.title+'</label></li>');
+                            target.hiddenColumns.push(column.field);
+                        }
+                        $columns_ul.append(_li);
+                    }
+                });
+                $columns_div.append($columns_ul);
+                $rightToolbar.append($columns_div);
+                // 注册列选项事件
+                registerColumnClickEvent();
+            }else{
+                $.each(options.columns, function(i, column) {
+                    if (column.field != 'selectItem') {
+                        if(!(typeof column.visible == "undefined"||column.visible==true)){
+                            target.hiddenColumns.push(column.field);
+                        }
+                    }
+                });
+            }
+        }
+        // 初始化隐藏列
+        var initHiddenColumns = function(){
+            $.each(target.hiddenColumns, function(i, field) {
+                target.find("."+field+"_cls").hide();
+            });
+        }
+        // 初始化表头
+        var initHeader = function() {
+            var $thr = $('<tr></tr>');
+            $.each(options.columns, function(i, column) {
+                var $th = null;
+                // 判断有没有选择列
+                if (i == 0 && column.field == 'selectItem') {
+                    target.hasSelectItem = true;
+                    $th = $('<th style="width:36px"></th>');
+                } else {
+                    $th = $('<th style="' + ((column.width) ? ('width:' + column.width + ((column.widthUnit) ? column.widthUnit : 'px')) : '') + '" class="' + column.field + '_cls"></th>');
+                    if (column.align) {
+                        $th.css("text-align", column.align);
+                    }
+                }
+                if((!target.isFixWidth)&& column.width){
+                    target.isFixWidth = column.width.indexOf("px")>-1?true:false;
+                }
+                $th.html(column.title);
+                $thr.append($th);
+            });
+            var $thead = $('<thead class="treetable-thead"></thead>');
+            $thead.append($thr);
+            target.append($thead);
+        }
+        // 初始化表体
+        var initBody = function() {
+            var $tbody = $('<tbody class="treetable-tbody"></tbody>');
+            target.append($tbody);
+            // 默认高度
+            if (options.height) {
+                $tbody.css("height", options.height);
+            }
+            if (options.pagination) {
+                var $pagination = $('<div class="fixed-table-pagination"></div>');
+                target.append($pagination);
+            }
+        }
+        // 初始化数据服务
+        var initServer = function(parms) {
+            if (options.pagination) {
+                if(parms == undefined || parms == null) {
+                    parms = {};
+                }
+                parms[options.parentCode] = options.rootIdValue;
+            }
+            // 加载数据前先清空
+            target.data_list = {};
+            target.data_obj = {};
+            // 设置请求分页参数
+            if (options.pagination) {
+                var params = {};
+                params.offset = options.pageSize * (options.pageNumber - 1);
+                params.limit = options.pageSize;
+                var curParams = { pageSize: params.limit, pageNum: params.offset / params.limit + 1 };
+                parms = $.extend(curParams, parms);
+            }
+            var $tbody = target.find("tbody");
+            // 添加加载loading
+            var $loading = '<tr><td colspan="' + options.columns.length + '"><div style="display: block;text-align: center;">正在努力地加载数据中,请稍候……</div></td></tr>'
+            $tbody.html($loading);
+            if (options.url) {
+                $.ajax({
+                    type: options.type,
+                    url: options.url,
+                    data: $.extend(parms, options.ajaxParams),
+                    dataType: "json",
+                    success: function(data, textStatus, jqXHR) {
+                    	data = calculateObjectValue(options, options.responseHandler, [data], data);
+                        renderTable(data);
+                        calculateObjectValue(options, options.onLoadSuccess, [data], data);
+                    },
+                    error: function(xhr, textStatus) {
+                        var _errorMsg = '<tr><td colspan="' + options.columns.length + '"><div style="display: block;text-align: center;">' + xhr.responseText + '</div></td></tr>'
+                        $tbody.html(_errorMsg);
+                    }
+                });
+            } else {
+                renderTable(options.data);
+            }
+        }
+        // 加载完数据后渲染表格
+        var renderTable = function(data) {
+            var list, totalPage = 0, currPage = 0;
+            if (options.pagination) {
+            	list = data.rows;  // 数据
+                currPage = options.pageNumber; // 当前页
+                totalPage = ~~((data.total - 1) / options.pageSize) + 1 // 总页数
+                target.totalPages  = totalPage;
+                target.totalRows = data.total; // 总记录数
+            } else {
+            	list = data;
+            }
+            data = list;
+            var $tbody = target.find("tbody");
+            // 先清空
+            $tbody.html("");
+            if (!data || data.length <= 0) {
+                var _empty = '<tr><td colspan="' + options.columns.length + '"><div style="display: block;text-align: center;">没有找到匹配的记录</div></td></tr>'
+                $tbody.html(_empty);
+                options.pageNumber = 1;
+                initPagination(0, 0);
+                return;
+            }
+            // 缓存并格式化数据
+            formatData(data);
+            // 获取所有根节点
+            var rootNode = target.data_list["_root_"];
+            // 开始绘制
+            if (rootNode) {
+                $.each(rootNode, function(i, item) {
+                    var _child_row_id = "row_id_" + i
+                    recursionNode(item, 1, _child_row_id, "row_root", item[options.code]);
+                });
+            }
+            // 下边的操作主要是为了查询时让一些没有根节点的节点显示
+            $.each(data, function(i, item) {
+                if (!item.isShow) {
+                    var tr = renderRow(item, false, 1, "", "", options.pagination, item[options.code]);
+                    $tbody.append(tr);
+                }
+            });
+            registerExpanderEvent();
+            registerRowClickEvent();
+            initHiddenColumns();
+            // 动态设置表头宽度
+            autoTheadWidth();
+            if (options.pagination) {
+                initPagination(totalPage, currPage);
+            }
+            // 移动端适配
+            var treetableTable = $(target).parent('.treetable-table');
+            var availableHeight = treetableTable.outerWidth();
+            if($.common.isMobile() || availableHeight < 769){
+                var tableStyle = "width: " + availableHeight + "px;overflow: auto;position: relative;";
+                treetableTable.attr('style', tableStyle);
+                var w = 0;
+                $.each(options.columns, function(i, column) {
+                    if (i == 0 && column.field == 'selectItem') {
+                        w += 36;
+                    } else {
+                        w += 200;
+                    }
+                });
+                $(target).attr('style','width:' + w +'px');
+            }
+        }
+        // 初始化分页
+        var initPagination = function (totalPage,currPage) {
+            var $pagination = target.find(".fixed-table-pagination");
+            $pagination.empty();
+            var html = [];
+            var pageFrom = (options.pageNumber - 1) * options.pageSize + 1;
+            var pageTo = options.pageNumber * options.pageSize;
+            if (pageTo > target.totalRows) {
+                pageTo = target.totalRows;
+            }
+            if (pageFrom > pageTo) {
+                pageFrom = pageTo;
+            }
+            html.push('<div class="pull-left pagination-detail">');
+            html.push('<span class="pagination-info">' + formatShowingRows(pageFrom, pageTo, target.totalRows) + '</span>');
+            var pageList = false;
+            $.each(options.pageList, function (i, page) {
+                if(target.totalRows > page){
+                    pageList = true;
+                }
+            })
+            if(pageList){
+                var _page_list = [];
+                _page_list.push('<span class="page-list">');
+                _page_list.push('<span class="btn-group dropup">');
+                _page_list.push('<button type="button" class="btn btn-default btn-outline dropdown-toggle" data-toggle="dropdown">');
+                _page_list.push('<span class="page-size">' + options.pageSize + '</span>');
+                _page_list.push('<span class="caret"></span>');
+                _page_list.push('</button>');
+                _page_list.push('<ul class="dropdown-menu" role="menu">');
+                $.each(options.pageList, function (i, page) {
+                    if(page == options.pageSize){
+                        _page_list.push('<li class="active"><a href="javascript:void(0)">' + page + '</a></li>');
+                    }
+                    else if(page >= target.totalRows && i === 1){
+                        _page_list.push('<li><a href="javascript:void(0)">' + page + '</a></li>');
+                    }
+                    else if(page <= target.totalRows){
+                        _page_list.push('<li><a href="javascript:void(0)">' + page + '</a></li>');
+                    }
+                })
+                _page_list.push('</ul>');
+                _page_list.push('</span>');
+                html.push(formatRecordsPerPage(_page_list.join('')))
+                html.push('</span>');
+            }
+            html.push('</div>');
+
+            if(totalPage > 1){
+                html.push('<div class="pull-right pagination">');
+                html.push('<ul class="pagination pagination-outline">');
+                html.push('<li class="page-pre"><a href="javascript:void(0)">' + options.paginationPreText + '</a></li>');
+                var from, to;
+                if (totalPage < 5) {
+                    from = 1;
+                    to = totalPage;
+                } else {
+                    from = currPage - 2;
+                    to = from + 4;
+                    if (from < 1) {
+                        from = 1;
+                        to = 5;
+                    }
+                    if (to > totalPage) {
+                        to = totalPage;
+                        from = to - 4;
+                    }
+                }
+
+                if (totalPage >= 6) {
+                    if (currPage >= 3) {
+                        html.push('<li class="page-first' + (1 == currPage ? ' active' : '') + '">', '<a href="javascript:void(0)">', 1, '</a>', '</li>');
+                        from++;
+                    }
+                    if (currPage >= 4) {
+                        if (currPage == 4 || totalPage == 6 || totalPage == 7) {
+                            from--;
+                        } else {
+                            html.push('<li class="page-first-separator disabled">', '<a href="javascript:void(0)">...</a>', '</li>');
+                        }
+                        to--;
+                    }
+                }
+
+                if (totalPage >= 7) {
+                    if (currPage >= (totalPage - 2)) {
+                        from--;
+                    }
+                }
+                if (totalPage == 6) {
+                    if (currPage >= (totalPage - 2)) {
+                        to++;
+                    }
+                } else if (totalPage >= 7) {
+                    if (totalPage == 7 || currPage >= (totalPage - 3)) {
+                        to++;
+                    }
+                }
+
+                for (var i = from; i <= to; i++) {
+                    html.push('<li class="page-number' + (i == currPage ? ' active' : '') + '">', '<a href="javascript:void(0)">', i, '</a>', '</li>');
+                }
+
+                if (totalPage >= 8) {
+                    if (currPage <= (totalPage - 4)) {
+                        html.push('<li class="page-last-separator disabled">', '<a href="javascript:void(0)">...</a>', '</li>');
+                    }
+                }
+
+                if (totalPage >= 6) {
+                    if (currPage <= (totalPage - 3)) {
+                        html.push('<li class="page-last' + (totalPage === currPage ? ' active' : '') + '">', '<a href="javascript:void(0)">', totalPage, '</a>', '</li>');
+                    }
+                }
+
+                html.push('<li class="page-next"><a href="javascript:void(0)">' + options.paginationNextText + '</a></li>');
+                html.push('</ul></div>');
+            }
+
+            $pagination.append(html.join(''));
+
+            var $pageList = $pagination.find('.page-list a');
+            var $pre = $pagination.find('.page-pre');
+            var $next = $pagination.find('.page-next');
+            var $number = $pagination.find('.page-number');
+            var $first = $pagination.find('.page-first');
+            var $last = $pagination.find('.page-last');
+            $pre.off('click').on('click', $.proxy(onPagePre, this));
+            $pageList.off('click').on('click', $.proxy(onPageListChange, this));
+            $number.off('click').on('click', $.proxy(onPageNumber, this));
+            $first.off('click').on('click', $.proxy(onPageFirst, this));
+            $last.off('click').on('click', $.proxy(onPageLast, this));
+            $next.off('click').on('click', $.proxy(onPageNext, this));
+        }
+        var onPageListChange = function(event){
+            var $this = $(event.currentTarget);
+            $this.parent().addClass('active').siblings().removeClass('active');
+            var $pagination = target.find(".fixed-table-pagination");
+            options.pageSize = $this.text().toUpperCase() === target.totalRows ? target.totalRows : + $this.text();
+            
+            if(target.totalRows < options.pageSize * options.pageNumber){
+                options.pageNumber = 1;
+            }
+            $pagination.find('.page-size').text(options.pageSize);
+            initServer();
+        }
+        var onPagePre = function(event){
+            if ((options.pageNumber - 1) === 0) {
+                options.pageNumber = target.totalPages;
+            } else {
+                options.pageNumber--;
+            }
+            initServer();
+        }
+        var onPageNumber = function(event){
+            if (options.pageNumber == $(event.currentTarget).text()) {
+                return;
+            }
+            options.pageNumber = $(event.currentTarget).text();
+            initServer();
+        }
+        var onPageFirst = function(event){
+            options.pageNumber = 1;
+            initServer();
+        }
+        var onPageLast = function (event) {
+            options.pageNumber = target.totalPages;
+            initServer();
+        }
+        var onPageNext = function(event){
+            if ((options.pageNumber + 1) > target.totalPages) {
+                options.pageNumber = 1;
+            } else {
+                options.pageNumber++;
+            }
+            initServer();
+        }
+        // 动态设置表头宽度
+        var autoTheadWidth = function(initFlag) {
+            if(options.height>0){
+                var $thead = target.find("thead");
+                var $tbody = target.find("tbody");
+                var borderWidth = parseInt(target.css("border-left-width")) + parseInt(target.css("border-right-width"))
+                
+                $thead.css("width", $tbody.children(":first").width());
+                if(initFlag){
+                    var resizeWaiter = false;
+                    $(window).resize(function() {
+                        if(!resizeWaiter){
+                            resizeWaiter = true;
+                            setTimeout(function(){
+                                if(!target.isFixWidth){
+                                    $tbody.css("width", target.parent().width()-borderWidth);
+                                }
+                                $thead.css("width", $tbody.children(":first").width());
+                                resizeWaiter = false;
+                            }, 300);
+                        }
+                    });
+                }
+            }
+        
+        }
+        // 缓存并格式化数据
+        var formatData = function(data) {
+            var _root = options.rootIdValue ? options.rootIdValue : null;
+            // 父节点属性列表
+            var parentCodes = [];
+            var rootFlag = false;
+            $.each(data, function(index, item) {
+            	if($.inArray(item[options.parentCode], parentCodes) == -1){
+            		parentCodes.push(item[options.parentCode]);
+                }
+            });
+            $.each(data, function(index, item) {
+                // 添加一个默认属性,用来判断当前节点有没有被显示
+                item.isShow = false;
+                // 是否分页
+                if (options.pagination) {
+                    if (item.isTreeLeaf == undefined || item.isTreeLeaf == null) {
+                        item.isTreeLeaf = false;
+                    } else {
+                        item.isTreeLeaf = (item["isTreeLeaf"] == 1 ? true: false) || ((item["isTreeLeaf"] == 'true' || item["isTreeLeaf"] == true) ? true: false);
+                    }
+                }
+                // 顶级节点校验判断,兼容0,'0','',null
+                var _defaultRootFlag = item[options.parentCode] == '0' ||
+                item[options.parentCode] == 0 ||
+                item[options.parentCode] == null ||
+                item[options.parentCode] == '' ||
+                $.inArray(item[options.code], parentCodes) > 0 && !rootFlag;
+                if (!item[options.parentCode] || (_root ? (item[options.parentCode] == options.rootIdValue) : _defaultRootFlag)) {
+                	rootFlag = true;
+                	if (!target.data_list["_root_"]) {
+                        target.data_list["_root_"] = [];
+                    }
+                    if (!target.data_obj["id_" + item[options.code]]) {
+                        target.data_list["_root_"].push(item);
+                    }
+                } else {
+                    if (!target.data_list["_n_" + item[options.parentCode]]) {
+                        target.data_list["_n_" + item[options.parentCode]] = [];
+                    }
+                    if (!target.data_obj["id_" + item[options.code]]) {
+                        target.data_list["_n_" + item[options.parentCode]].push(item);
+                    }
+                }
+                target.data_obj["id_" + item[options.code]] = item;
+            });
+        }
+        // 递归获取子节点并且设置子节点
+        var recursionNode = function(parentNode, lv, row_id, p_id, k) {
+            var $tbody = target.find("tbody");
+            var _ls = target.data_list["_n_" + parentNode[options.code]];
+            var $tr = renderRow(parentNode, _ls ? true : false, lv, row_id, p_id, options.pagination, k);
+            $tbody.append($tr);
+            if (_ls) {
+                $.each(_ls, function(i, item) {
+                    var _child_row_id = row_id + "_" + i
+                    recursionNode(item, (lv + 1), _child_row_id, row_id, item[options.code])
+                });
+            }
+        };
+        // 绘制行
+        var renderRow = function(item, isP, lv, row_id, p_id, _pagination, k) {
+            // 标记已显示
+            item.isShow = true;
+            item.row_id = row_id;
+            item.p_id = p_id;
+            item.lv = lv;
+            var $tr = $('<tr id="' + row_id + '" data-id="' + k + '"pid="' + p_id + '"></tr>');
+            var _icon = options.expanderCollapsedClass;
+            if (options.expandAll) {
+                $tr.css("display", "table");
+                _icon = options.expanderExpandedClass;
+            } else if (lv == 1) {
+                $tr.css("display", "table");
+                _icon = (options.expandFirst) ? options.expanderExpandedClass : options.expanderCollapsedClass;
+            } else if (lv == 2) {
+                if (options.expandFirst) {
+                    $tr.css("display", "table");
+                } else {
+                    $tr.css("display", "none");
+                }
+                _icon = options.expanderCollapsedClass;
+            } else if (_pagination) {
+                if (item.isTreeLeaf) {
+                    _icon = options.expanderCollapsedClass;
+                }
+            } else {
+                $tr.css("display", "none");
+                _icon = options.expanderCollapsedClass;
+            }
+            $.each(options.columns, function(index, column) {
+                // 判断有没有选择列
+                if (column.field == 'selectItem') {
+                    target.hasSelectItem = true;
+                    var $td = $('<td style="text-align:center;width:36px"></td>');
+                    if (column.radio) {
+                        var _ipt = $('<input name="select_item" type="radio" value="' + item[options.code] + '"></input>');
+                        $td.append(_ipt);
+                    }
+                    if (column.checkbox) {
+                        var _ipt = $('<input name="select_item" type="checkbox" value="' + item[options.code] + '"></input>');
+                        $td.append(_ipt);
+                    }
+                    $tr.append($td);
+                } else {
+                    var $td = $('<td name="' + column.field + '" class="' + column.field + '_cls"></td>');
+                    if(column.width){
+                        $td.css("width",column.width + (column.widthUnit ? column.widthUnit : 'px'));
+                    }
+                    if(column.align){
+                        $td.css("text-align",column.align);
+                    }
+                    if(options.expandColumn == index){
+                        $td.css("text-align","left");
+                    }
+                    if(column.valign){
+                        $td.css("vertical-align",column.valign);
+                    }
+                    if(options.showTitle){
+                        $td.addClass("ellipsis");
+                    }
+                    // 增加formatter渲染
+                    if (column.formatter) {
+                        $td.html(column.formatter.call(this, getItemField(item, column.field), item, index));
+                    } else {
+                        if(options.showTitle){
+                            // 只在字段没有formatter时才添加title属性
+                            $td.attr("title",item[column.field]);
+                        }
+                        $td.text(getItemField(item, column.field));
+                    }
+                    if (options.expandColumn == index) {
+                    	if (_pagination) {
+                    	    if (item["isTreeLeaf"]) {
+                    	        $td.prepend('<span class="treetable-expander ' + _icon + '"></span>');
+                    	    } else {
+                    	        $td.prepend('<span class="treetable-expander"></span>')
+                    	    }
+                    	} else {
+	                        if (!isP) {
+	                            $td.prepend('<span class="treetable-expander"></span>')
+	                        } else {
+	                            $td.prepend('<span class="treetable-expander ' + _icon + '"></span>');
+	                        }
+                    	}
+                    	for (var int = 0; int < (lv - options.expandColumn); int++) {
+                            $td.prepend('<span class="treetable-indent"></span>')
+                        }
+                    }
+                    $tr.append($td);
+                }
+            });
+            return $tr;
+        }
+        // 检索信息按钮点击事件
+        var registerSearchBtnClickEvent = function(btn) {
+            $(btn).off('click').on('click', function () {
+                $(".search-collapse").slideToggle();
+            });
+        }
+        // 注册刷新按钮点击事件
+        var registerRefreshBtnClickEvent = function(btn) {
+            $(btn).off('click').on('click', function () {
+                target.refresh();
+            });
+        }
+        // 注册列选项事件
+        var registerColumnClickEvent = function() {
+            $(".bootstrap-tree-table .treetable-bars .columns label input").off('click').on('click', function () {
+                var $this = $(this);
+                if($this.prop('checked')){
+                    target.showColumn($(this).val());
+                }else{
+                    target.hideColumn($(this).val());
+                }
+            });
+        }
+        // 注册行点击选中事件
+        var registerRowClickEvent = function() {
+            target.find("tbody").find("tr").unbind();
+            target.find("tbody").find("tr").click(function() {
+                if (target.hasSelectItem) {
+                    var _ipt = $(this).find("input[name='select_item']");
+                    if (_ipt.attr("type") == "radio") {
+                        _ipt.prop('checked', true);
+                        target.find("tbody").find("tr").removeClass("treetable-selected");
+                        $(this).addClass("treetable-selected");
+                    } else if (_ipt.attr("type") == "checkbox") {
+                    	if (_ipt.prop('checked')) {
+                    		_ipt.prop('checked', true);
+                    		target.find("tbody").find("tr").removeClass("treetable-selected");
+                    		$(this).addClass("treetable-selected");
+                    	} else {
+                    		_ipt.prop('checked', false);
+                    		target.find("tbody").find("tr").removeClass("treetable-selected");
+                    	}
+                    } else {
+                        if (_ipt.prop('checked')) {
+                            _ipt.prop('checked', false);
+                            $(this).removeClass("treetable-selected");
+                        } else {
+                            _ipt.prop('checked', true);
+                            $(this).addClass("treetable-selected");
+                        }
+                    }
+                    var _rowData = target.data_obj["id_" + $(this).data('id')];
+                    calculateObjectValue(options, options.onClickRow, [_rowData], _rowData);
+                }
+            });
+        }
+        // 注册小图标点击事件--展开缩起
+        var registerExpanderEvent = function() {
+            target.find("tbody").find("tr").find(".treetable-expander").unbind();
+            target.find("tbody").find("tr").find(".treetable-expander").click(function() {
+                var _isExpanded = $(this).hasClass(options.expanderExpandedClass);
+                var _isCollapsed = $(this).hasClass(options.expanderCollapsedClass);
+                if (_isExpanded || _isCollapsed) {
+                    var tr = $(this).parent().parent();
+                    var row_id = tr.attr("id");
+                    var row_pid = tr.attr("pid");
+                    var _id = tr.attr("data-id");
+                    var _ls = target.find("tbody").find("tr[id^='" + row_id + "_']");
+                    if (!options.pagination) {
+	                    if (_isExpanded) {
+	                        $(this).removeClass(options.expanderExpandedClass);
+	                        $(this).addClass(options.expanderCollapsedClass);
+	                        if (_ls && _ls.length > 0) {
+	                            $.each(_ls, function(index, item) {
+	                                $(item).css("display", "none");
+	                            });
+	                        }
+	                    } else {
+	                        $(this).removeClass(options.expanderCollapsedClass);
+	                        $(this).addClass(options.expanderExpandedClass);
+	                        if (_ls && _ls.length > 0) {
+	                            $.each(_ls, function(index, item) {
+	                                var _p_icon = $("#" + $(item).attr("pid")).children().eq(options.expandColumn).find(".treetable-expander");
+	                                var _p_display = $("#" + $(item).attr("pid")).css('display');
+	                                if (_p_icon.hasClass(options.expanderExpandedClass) && _p_display == 'table') {
+	                                    $(item).css("display", "table");
+	                                }
+	                            });
+	                        }
+	                    }
+                    } else {
+                        var _ls = target.find("tbody").find("tr[id^='" + row_id + "_']");
+                        if (_ls && _ls.length > 0) {
+                            if (_isExpanded) {
+                                if (row_pid == "row_root") {
+                                    $('table tr[id^="' + row_id + '_"]').css("display", "none");
+                                    $('table tr[id^="' + row_id + '_"]').each(function(i,n) {
+                                        var _isExpanded = $(n).find(".treetable-expander").hasClass(options.expanderExpandedClass);
+                                        if (_isExpanded) {
+                                            $(n).find(".treetable-expander").trigger("click");
+                                        }
+                                    })
+                                } else {
+                                    $.each(_ls, function(index, item) {
+                                        $(item).css("display", "none");
+                                        var _isExpanded = $(item).find(".treetable-expander").hasClass(options.expanderExpandedClass);
+                                        if (_isExpanded) {
+                                            $(item).find(".treetable-expander").trigger("click");
+                                        }
+                                     });
+                            	}
+                            } else {
+                                if (row_pid == "row_root") {
+                                    $('table tr[pid="' + row_id + '"]').css("display", "table");
+                                } else {
+	                                $.each(_ls, function(index, item) {
+	                                    var _p_icon = $("#" + $(item).attr("pid")).children().eq(options.expandColumn).find(".treetable-expander");
+                                        var _isExpanded = _p_icon.hasClass(options.expanderExpandedClass);
+                                        var _isCollapsed = _p_icon.hasClass(options.expanderCollapsedClass);
+	                                    if (row_id == $(item).attr("pid")) {
+		                                    $(item).css("display", "table");
+	                                    }
+	                                });
+                                }
+                            }
+                        } else {
+                            if (options.pagination) {
+                                var parms = {};
+                                parms[options.parentCode] = _id;
+                                if (options.dataUrl) {
+                                    $.ajax({
+                                        type: options.type,
+                                        url: options.dataUrl,
+                                        data: parms,
+                                        dataType: "json",
+                                        success: function(data, textStatus, jqXHR) {
+                                            $("#" + row_id + "_load").remove();
+                                            var list = data;
+                                            data = list;
+                                            target.appendData(data)
+                                        },
+                                        error: function(xhr, textStatus) {
+                                            var _errorMsg = '<tr><td colspan="' + options.columns.length + '"><div style="display: block;text-align: center;">' + xhr.responseText + '</div></td></tr>'
+                                            $("#" + row_id).after(_errorMsg);
+                                        }
+                                    });
+                                }
+                            }
+                        }
+                        if (_isExpanded) {
+                            $(this).removeClass(options.expanderExpandedClass);
+                            $(this).addClass(options.expanderCollapsedClass);
+                        } else {
+                            $(this).removeClass(options.expanderCollapsedClass);
+                            $(this).addClass(options.expanderExpandedClass);
+                        }
+                    }
+                }
+            });
+        }
+        // 刷新数据
+        target.refresh = function(parms) {
+            if(parms){
+                target.lastAjaxParams=parms;
+            }
+            initServer(target.lastAjaxParams);
+        }
+        // 添加数据刷新表格
+        target.appendData = function(data) {
+            data.reverse()
+            // 下边的操作主要是为了查询时让一些没有根节点的节点显示
+            $.each(data, function(i, item) {
+                if (options.pagination) {
+                    item.__nodes = (item["nodes"] == 1 ? true: false) || ((item["nodes"] == 'true' || item["nodes"] == true) ? true: false);
+                }
+                var _data = target.data_obj["id_" + item[options.code]];
+                var _p_data = target.data_obj["id_" + item[options.parentCode]];
+                var _c_list = target.data_list["_n_" + item[options.parentCode]];
+                var row_id = ""; //行id
+                var p_id = ""; //父行id
+                var _lv = 1; //如果没有父就是1默认显示
+                var tr; //要添加行的对象
+                if (_data && _data.row_id && _data.row_id != "") {
+                    row_id = _data.row_id; // 如果已经存在了,就直接引用原来的
+                }
+                if (_p_data) {
+                    p_id = _p_data.row_id;
+                    if (row_id == "") {
+                        var _tmp = 0
+                        if (_c_list && _c_list.length > 0) {
+                            _tmp = _c_list.length;
+                        }
+                        row_id = _p_data.row_id + "_" + _tmp;
+                    }
+                    _lv = _p_data.lv + 1; //如果有父
+                    // 绘制行
+                    tr = renderRow(item, true, _lv, row_id, p_id, options.pagination, item[options.code]);
+
+                    var _p_icon = $("#" + _p_data.row_id).children().eq(options.expandColumn).find(".treetable-expander");
+                    var _isExpanded = _p_icon.hasClass(options.expanderExpandedClass);
+                    var _isCollapsed = _p_icon.hasClass(options.expanderCollapsedClass);
+                    // 父节点有没有展开收缩按钮
+                    if (_isExpanded || _isCollapsed) {
+                        // 父节点展开状态显示新加行
+                        if (_isExpanded) {
+                            tr.css("display", "table");
+                        }
+                    } else {
+                        // 父节点没有展开收缩按钮则添加
+                        _p_icon.addClass(options.expanderCollapsedClass);
+                    }
+
+                    if (_data) {
+                        $("#" + _data.row_id).before(tr);
+                        $("#" + _data.row_id).remove();
+                    } else {
+                        // 计算父的同级下一行
+                        var _tmp_ls = _p_data.row_id.split("_");
+                        var _p_next = _p_data.row_id.substring(0, _p_data.row_id.length - (_tmp_ls[_tmp_ls.length - 1] + "").length) + (parseInt(_tmp_ls[_tmp_ls.length - 1]) + 1);
+                        $("#" + _p_data.row_id).after(tr);
+                    }
+                } else {
+                    tr = renderRow(item, false, _lv, row_id, p_id, options.pagination, item[options.code]);
+                    if (_data) {
+                        $("#" + _data.row_id).before(tr);
+                        $("#" + _data.row_id).remove();
+                    } else {
+                        // 画上
+                        var tbody = target.find("tbody");
+                        tbody.append(tr);
+                    }
+                }
+                item.isShow = true;
+                // 缓存并格式化数据
+                formatData([item]);
+            });
+            registerExpanderEvent();
+            registerRowClickEvent();
+            initHiddenColumns();
+        }
+
+        // 展开/折叠指定的行
+        target.toggleRow=function(id) {
+            var _rowData = target.data_obj["id_" + id];
+            var $row_expander = $("#"+_rowData.row_id).find(".treetable-expander");
+            $row_expander.trigger("click");
+        }
+        // 展开指定的行
+        target.expandRow=function(id) {
+            var _rowData = target.data_obj["id_" + id];
+            var $row_expander = $("#"+_rowData.row_id).find(".treetable-expander");
+            var _isCollapsed = $row_expander.hasClass(target.options.expanderCollapsedClass);
+            if (_isCollapsed) {
+                $row_expander.trigger("click");
+            }
+        }
+        // 折叠 指定的行
+        target.collapseRow=function(id) {
+            var _rowData = target.data_obj["id_" + id];
+            var $row_expander = $("#"+_rowData.row_id).find(".treetable-expander");
+            var _isExpanded = $row_expander.hasClass(target.options.expanderExpandedClass);
+            if (_isExpanded) {
+                $row_expander.trigger("click");
+            }
+        }
+        // 展开所有的行
+        target.expandAll=function() {
+            target.find("tbody").find("tr").find(".treetable-expander").each(function(i,n){
+                var _isCollapsed = $(n).hasClass(options.expanderCollapsedClass);
+                if (_isCollapsed) {
+                    $(n).trigger("click");
+                }
+            })
+        }
+        // 折叠所有的行
+        target.collapseAll=function() {
+            target.find("tbody").find("tr").find(".treetable-expander").each(function(i,n){
+                var _isExpanded = $(n).hasClass(options.expanderExpandedClass);
+                if (_isExpanded) {
+                    $(n).trigger("click");
+                }
+            })
+        }
+        // 显示指定列
+        target.showColumn=function(field,flag) {
+            var _index = $.inArray(field, target.hiddenColumns);
+            if (_index > -1) {
+                target.hiddenColumns.splice(_index, 1);
+            }
+            target.find("."+field+"_cls").show();
+            //是否更新列选项状态
+            if(flag&&options.showColumns){
+                var $input = $(".bootstrap-tree-table .treetable-bars .columns label").find("input[value='"+field+"']")
+                $input.prop("checked", 'checked');
+            }
+        }
+        // 隐藏指定列
+        target.hideColumn=function(field,flag) {
+            target.hiddenColumns.push(field);
+            target.find("."+field+"_cls").hide();
+            //是否更新列选项状态
+            if(flag&&options.showColumns){
+                var $input = $(".bootstrap-tree-table .treetable-bars .columns label").find("input[value='"+field+"']")
+                $input.prop("checked", '');
+            }
+        }
+        // ruoyi 解析数据,支持多层级访问
+        var getItemField = function (item, field) {
+            var value = item;
+
+            if (typeof field !== 'string' || item.hasOwnProperty(field)) {
+                return item[field];
+            }
+            var props = field.split('.');
+            for (var p in props) {
+                value = value && value[props[p]];
+            }
+            return value;
+        };
+        // ruoyi 发起对目标(target)函数的调用
+        var calculateObjectValue = function (self, name, args, defaultValue) {
+            var func = name;
+
+            if (typeof name === 'string') {
+                var names = name.split('.');
+
+                if (names.length > 1) {
+                    func = window;
+                    $.each(names, function (i, f) {
+                        func = func[f];
+                    });
+                } else {
+                    func = window[name];
+                }
+            }
+            if (typeof func === 'object') {
+                return func;
+            }
+            if (typeof func === 'function') {
+                return func.apply(self, args);
+            }
+            if (!func && typeof name === 'string' && sprintf.apply(this, [name].concat(args))) {
+                return sprintf.apply(this, [name].concat(args));
+            }
+            return defaultValue;
+        };
+        var  formatRecordsPerPage =  function (pageNumber) {
+            return '每页显示 ' + pageNumber + ' 条记录';
+        };
+        var formatShowingRows = function (pageFrom, pageTo, totalRows) {
+        	return '显示第 ' + pageFrom + ' 到第 ' + pageTo + ' 条记录,总共 ' + totalRows + ' 条记录。';
+        };
+        // 初始化
+        init();
+        return target;
+    };
+
+    // 组件方法封装........
+    $.fn.bootstrapTreeTable.methods = {
+        // 为了兼容bootstrap-table的写法,统一返回数组,这里返回了表格显示列的数据
+        getSelections: function(target, data) {
+            // 所有被选中的记录input
+            var _ipt = target.find("tbody").find("tr").find("input[name='select_item']:checked");
+            var chk_value = [];
+            // 如果是radio
+            if (_ipt.attr("type") == "radio") {
+                var _data = target.data_obj["id_" + _ipt.val()];
+                chk_value.push(_data);
+            } else {
+                _ipt.each(function(_i, _item) {
+                    var _data = target.data_obj["id_" + $(_item).val()];
+                    chk_value.push(_data);
+                });
+            }
+            return chk_value;
+        },
+        // 刷新记录
+        refresh: function(target, parms) {
+            if (parms) {
+                target.refresh(parms);
+            } else {
+                target.refresh();
+            }
+        },
+        // 添加数据到表格
+        appendData: function(target, data) {
+            if (data) {
+                target.appendData(data);
+            }
+        },
+        // 展开/折叠指定的行
+        toggleRow: function(target, id) {
+            target.toggleRow(id);
+        },
+        // 展开指定的行
+        expandRow: function(target, id) {
+            target.expandRow(id);
+        },
+        // 折叠 指定的行
+        collapseRow: function(target, id) {
+            target.collapseRow(id);
+        },
+        // 展开所有的行
+        expandAll: function(target) {
+            target.expandAll();
+        },
+        // 折叠所有的行
+        collapseAll: function(target) {
+            target.collapseAll();
+        },
+        // 显示指定列
+        showColumn: function(target,field) {
+            target.showColumn(field,true);
+        },
+        // 隐藏指定列
+        hideColumn: function(target,field) {
+            target.hideColumn(field,true);
+        }
+        // 组件的其他方法也可以进行类似封装........
+    };
+
+    $.fn.bootstrapTreeTable.defaults = {
+        code: 'code',              // 选取记录返回的值,用于设置父子关系
+        parentCode: 'parentCode',  // 用于设置父子关系
+        rootIdValue: 0,            // 设置根节点id值----可指定根节点,默认为null,"",0,"0"
+        data: null,                // 构造table的数据集合
+        type: "GET",               // 请求数据的ajax类型
+        url: null,                 // 请求数据的ajax的url
+        ajaxParams: {},            // 请求数据的ajax的data属性
+        expandColumn: 1,           // 在哪一列上面显示展开按钮
+        expandAll: false,          // 是否全部展开
+        expandFirst: true,         // 是否默认第一级展开--expandAll为false时生效
+        striped: false,            // 是否各行渐变色
+        bordered: false,           // 是否显示边框
+        hover: true,               // 是否鼠标悬停
+        condensed: false,          // 是否紧缩表格
+        columns: [],               // 列
+        toolbar: null,             // 顶部工具条
+        height: 0,                 // 表格高度
+        pagination: false,         // 是否显示分页
+        dataUrl: null,             // 加载子节点异步请求数据url
+        pageNumber: 1,             // 当前页条数
+        pageSize: 10,              // 每页的记录行数
+        onClickRow: null,          // 单击某行事件
+        pageList: [10, 25, 50],    // 可供选择的每页的行数
+        showTitle: true,           // 是否采用title属性显示字段内容(被formatter格式化的字段不会显示)
+        showSearch: true,          // 是否显示检索信息
+        showColumns: true,         // 是否显示内容列下拉框
+        showRefresh: true,         // 是否显示刷新按钮
+        paginationPreText: '&lsaquo;',
+        paginationNextText: '&rsaquo;',
+        expanderExpandedClass: 'glyphicon glyphicon-chevron-down',   // 展开的按钮的图标
+        expanderCollapsedClass: 'glyphicon glyphicon-chevron-right', // 缩起的按钮的图标
+        responseHandler: function(res) {
+            return false;
+        },
+        onLoadSuccess: function(res) {
+            return false;
+        }
+    };
+})(jQuery);
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/tree/bootstrap-table-tree.min.js b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/tree/bootstrap-table-tree.min.js
new file mode 100644
index 0000000..2a76d75
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/tree/bootstrap-table-tree.min.js
@@ -0,0 +1,5 @@
+/**
+ * 基于bootstrapTreeTable/bootstrap-table-treegrid修改
+ * Copyright (c) 2019 ruoyi
+ */
+!function(e){e.fn.bootstrapTreeTable=function(a,t){var n=e(this).data("bootstrap.tree.table");if(n=n?n:e(this),"string"==typeof a){return e.fn.bootstrapTreeTable.methods[a](n,t)}a=e.extend({},e.fn.bootstrapTreeTable.defaults,a||{}),n.hasSelectItem=!1,n.data_list=null,n.data_obj=null,n.hiddenColumns=[],n.lastAjaxParams,n.isFixWidth=!1,n.totalRows=0,n.totalPages=0;var i=function(){s(),l(),o(),r(),p(),C(!0),n.data("bootstrap.tree.table",n)},s=function(){var t=e("<div class='bootstrap-tree-table'></div>"),i=e("<div class='treetable-table'></div>");n.before(t),t.append(i),i.append(n),n.addClass("table"),a.striped&&n.addClass("table-striped"),a.bordered&&n.addClass("table-bordered"),a.hover&&n.addClass("table-hover"),a.condensed&&n.addClass("table-condensed"),n.html("")},l=function(){var t=e("<div class='treetable-bars'></div>");a.toolbar&&(e(a.toolbar).addClass("tool-left"),t.append(e(a.toolbar)));var i=e('<div class="btn-group tool-right">');if(t.append(i),n.parent().before(t),a.showSearch){var s=e('<button class="btn btn-default btn-outline" type="button" aria-label="search" title="搜索"><i class="glyphicon glyphicon-search"></i></button>');i.append(s),y(s)}if(a.showRefresh){var l=e('<button class="btn btn-default btn-outline" type="button" aria-label="refresh" title="刷新"><i class="glyphicon glyphicon-repeat"></i></button>');i.append(l),k(l)}if(a.showColumns){var d=e('<div class="btn-group pull-right" title="列"><button type="button" aria-label="columns" class="btn btn-default btn-outline dropdown-toggle" data-toggle="dropdown" aria-expanded="false"><i class="glyphicon glyphicon-list"></i> <span class="caret"></span></button></div>'),o=e('<ul class="dropdown-menu columns" role="menu"></ul>');e.each(a.columns,function(a,t){if("selectItem"!=t.field){var i=null;void 0===t.visible||1==t.visible?i=e('<li role="menuitem"><label><input type="checkbox" checked="checked" data-field="'+t.field+'" value="'+t.field+'" > '+t.title+"</label></li>"):(i=e('<li role="menuitem"><label><input type="checkbox" data-field="'+t.field+'" value="'+t.field+'" > '+t.title+"</label></li>"),n.hiddenColumns.push(t.field)),o.append(i)}}),d.append(o),i.append(d),j()}else{e.each(a.columns,function(e,a){"selectItem"!=a.field&&void 0!==a.visible&&1!=a.visible&&n.hiddenColumns.push(a.field)})}},d=function(){e.each(n.hiddenColumns,function(e,a){n.find("."+a+"_cls").hide()})},o=function(){var t=e("<tr></tr>");e.each(a.columns,function(a,i){var s=null;0==a&&"selectItem"==i.field?(n.hasSelectItem=!0,s=e('<th style="width:36px"></th>')):(s=e('<th style="'+(i.width?"width:"+i.width+(i.widthUnit?i.widthUnit:"px"):"")+'" class="'+i.field+'_cls"></th>'),i.align&&s.css("text-align",i.align)),!n.isFixWidth&&i.width&&(n.isFixWidth=i.width.indexOf("px")>-1?!0:!1),s.html(i.title),t.append(s)});var i=e('<thead class="treetable-thead"></thead>');i.append(t),n.append(i)},r=function(){var t=e('<tbody class="treetable-tbody"></tbody>');if(n.append(t),a.height&&t.css("height",a.height),a.pagination){var i=e('<div class="fixed-table-pagination"></div>');n.append(i)}},p=function(t){if(a.pagination&&((void 0==t||null==t)&&(t={}),t[a.parentCode]=a.rootIdValue),n.data_list={},n.data_obj={},a.pagination){var i={};i.offset=a.pageSize*(a.pageNumber-1),i.limit=a.pageSize;var s={pageSize:i.limit,pageNum:i.offset/i.limit+1};t=e.extend(s,t)}var l=n.find("tbody"),d='<tr><td colspan="'+a.columns.length+'"><div style="display: block;text-align: center;">正在努力地加载数据中,请稍候……</div></td></tr>';l.html(d),a.url?e.ajax({type:a.type,url:a.url,data:e.extend(t,a.ajaxParams),dataType:"json",success:function(e,t,n){e=N(a,a.responseHandler,[e],e),c(e),N(a,a.onLoadSuccess,[e],e)},error:function(e,t){var n='<tr><td colspan="'+a.columns.length+'"><div style="display: block;text-align: center;">'+e.responseText+"</div></td></tr>";l.html(n)}}):c(a.data)},c=function(t){var i,s=0,l=0;a.pagination?(i=t.rows,l=a.pageNumber,s=~~((t.total-1)/a.pageSize)+1,n.totalPages=s,n.totalRows=t.total):i=t,t=i;var o=n.find("tbody");if(o.html(""),!t||t.length<=0){var r='<tr><td colspan="'+a.columns.length+'"><div style="display: block;text-align: center;">没有找到匹配的记录</div></td></tr>';return o.html(r),a.pageNumber=1,void u(0,0)}m(t);var p=n.data_list._root_;p&&e.each(p,function(e,t){var n="row_id_"+e;w(t,1,n,"row_root",t[a.code])}),e.each(t,function(e,t){if(!t.isShow){var n=_(t,!1,1,"","",a.pagination,t[a.code]);o.append(n)}}),S(),T(),d(),C(),a.pagination&&u(s,l);var c=e(n).parent(".treetable-table"),f=c.outerWidth();if(e.common.isMobile()||769>f){var h="width: "+f+"px;overflow: auto;position: relative;";c.attr("style",h);var b=0;e.each(a.columns,function(e,a){b+=0==e&&"selectItem"==a.field?36:200}),e(n).attr("style","width:"+b+"px")}},u=function(t,i){var s=n.find(".fixed-table-pagination");s.empty();var l=[],d=(a.pageNumber-1)*a.pageSize+1,o=a.pageNumber*a.pageSize;o>n.totalRows&&(o=n.totalRows),d>o&&(d=o),l.push('<div class="pull-left pagination-detail">'),l.push('<span class="pagination-info">'+E(d,o,n.totalRows)+"</span>");var r=!1;if(e.each(a.pageList,function(e,a){n.totalRows>a&&(r=!0)}),r){var p=[];p.push('<span class="page-list">'),p.push('<span class="btn-group dropup">'),p.push('<button type="button" class="btn btn-default btn-outline dropdown-toggle" data-toggle="dropdown">'),p.push('<span class="page-size">'+a.pageSize+"</span>"),p.push('<span class="caret"></span>'),p.push("</button>"),p.push('<ul class="dropdown-menu" role="menu">'),e.each(a.pageList,function(e,t){t==a.pageSize?p.push('<li class="active"><a href="javascript:void(0)">'+t+"</a></li>"):t>=n.totalRows&&1===e?p.push('<li><a href="javascript:void(0)">'+t+"</a></li>"):t<=n.totalRows&&p.push('<li><a href="javascript:void(0)">'+t+"</a></li>")}),p.push("</ul>"),p.push("</span>"),l.push(I(p.join(""))),l.push("</span>")}if(l.push("</div>"),t>1){l.push('<div class="pull-right pagination">'),l.push('<ul class="pagination pagination-outline">'),l.push('<li class="page-pre"><a href="javascript:void(0)">'+a.paginationPreText+"</a></li>");var c,u;5>t?(c=1,u=t):(c=i-2,u=c+4,1>c&&(c=1,u=5),u>t&&(u=t,c=u-4)),t>=6&&(i>=3&&(l.push('<li class="page-first'+(1==i?" active":"")+'">','<a href="javascript:void(0)">',1,"</a>","</li>"),c++),i>=4&&(4==i||6==t||7==t?c--:l.push('<li class="page-first-separator disabled">','<a href="javascript:void(0)">...</a>',"</li>"),u--)),t>=7&&i>=t-2&&c--,6==t?i>=t-2&&u++:t>=7&&(7==t||i>=t-3)&&u++;for(var C=c;u>=C;C++){l.push('<li class="page-number'+(C==i?" active":"")+'">','<a href="javascript:void(0)">',C,"</a>","</li>")}t>=8&&t-4>=i&&l.push('<li class="page-last-separator disabled">','<a href="javascript:void(0)">...</a>',"</li>"),t>=6&&t-3>=i&&l.push('<li class="page-last'+(t===i?" active":"")+'">','<a href="javascript:void(0)">',t,"</a>","</li>"),l.push('<li class="page-next"><a href="javascript:void(0)">'+a.paginationNextText+"</a></li>"),l.push("</ul></div>")}s.append(l.join(""));var m=s.find(".page-list a"),w=s.find(".page-pre"),_=s.find(".page-next"),y=s.find(".page-number"),k=s.find(".page-first"),j=s.find(".page-last");w.off("click").on("click",e.proxy(h,this)),m.off("click").on("click",e.proxy(f,this)),y.off("click").on("click",e.proxy(b,this)),k.off("click").on("click",e.proxy(v,this)),j.off("click").on("click",e.proxy(g,this)),_.off("click").on("click",e.proxy(x,this))},f=function(t){var i=e(t.currentTarget);i.parent().addClass("active").siblings().removeClass("active");var s=n.find(".fixed-table-pagination");a.pageSize=i.text().toUpperCase()===n.totalRows?n.totalRows:+i.text(),n.totalRows<a.pageSize*a.pageNumber&&(a.pageNumber=1),s.find(".page-size").text(a.pageSize),p()},h=function(e){a.pageNumber-1===0?a.pageNumber=n.totalPages:a.pageNumber--,p()},b=function(t){a.pageNumber!=e(t.currentTarget).text()&&(a.pageNumber=e(t.currentTarget).text(),p())},v=function(e){a.pageNumber=1,p()},g=function(e){a.pageNumber=n.totalPages,p()},x=function(e){a.pageNumber+1>n.totalPages?a.pageNumber=1:a.pageNumber++,p()},C=function(t){if(a.height>0){var i=n.find("thead"),s=n.find("tbody"),l=parseInt(n.css("border-left-width"))+parseInt(n.css("border-right-width"));if(i.css("width",s.children(":first").width()),t){var d=!1;e(window).resize(function(){d||(d=!0,setTimeout(function(){n.isFixWidth||s.css("width",n.parent().width()-l),i.css("width",s.children(":first").width()),d=!1},300))})}}},m=function(t){var i=a.rootIdValue?a.rootIdValue:null,s=[],l=!1;e.each(t,function(t,n){-1==e.inArray(n[a.parentCode],s)&&s.push(n[a.parentCode])}),e.each(t,function(t,d){d.isShow=!1,a.pagination&&(void 0==d.isTreeLeaf||null==d.isTreeLeaf?d.isTreeLeaf=!1:d.isTreeLeaf=!((1==d.isTreeLeaf?0:1)&&("true"==d.isTreeLeaf||1==d.isTreeLeaf?0:1)));var o="0"==d[a.parentCode]||0==d[a.parentCode]||null==d[a.parentCode]||""==d[a.parentCode]||e.inArray(d[a.code],s)>0&&!l;!d[a.parentCode]||(i?d[a.parentCode]==a.rootIdValue:o)?(l=!0,n.data_list._root_||(n.data_list._root_=[]),n.data_obj["id_"+d[a.code]]||n.data_list._root_.push(d)):(n.data_list["_n_"+d[a.parentCode]]||(n.data_list["_n_"+d[a.parentCode]]=[]),n.data_obj["id_"+d[a.code]]||n.data_list["_n_"+d[a.parentCode]].push(d)),n.data_obj["id_"+d[a.code]]=d})},w=function(t,i,s,l,d){var o=n.find("tbody"),r=n.data_list["_n_"+t[a.code]],p=_(t,r?!0:!1,i,s,l,a.pagination,d);o.append(p),r&&e.each(r,function(e,t){var n=s+"_"+e;w(t,i+1,n,s,t[a.code])})},_=function(t,i,s,l,d,o,r){t.isShow=!0,t.row_id=l,t.p_id=d,t.lv=s;var p=e('<tr id="'+l+'" data-id="'+r+'"pid="'+d+'"></tr>'),c=a.expanderCollapsedClass;return a.expandAll?(p.css("display","table"),c=a.expanderExpandedClass):1==s?(p.css("display","table"),c=a.expandFirst?a.expanderExpandedClass:a.expanderCollapsedClass):2==s?(a.expandFirst?p.css("display","table"):p.css("display","none"),c=a.expanderCollapsedClass):o?t.isTreeLeaf&&(c=a.expanderCollapsedClass):(p.css("display","none"),c=a.expanderCollapsedClass),e.each(a.columns,function(l,d){if("selectItem"==d.field){n.hasSelectItem=!0;var r=e('<td style="text-align:center;width:36px"></td>');if(d.radio){var u=e('<input name="select_item" type="radio" value="'+t[a.code]+'"></input>');r.append(u)}if(d.checkbox){var u=e('<input name="select_item" type="checkbox" value="'+t[a.code]+'"></input>');r.append(u)}p.append(r)}else{var r=e('<td name="'+d.field+'" class="'+d.field+'_cls"></td>');if(d.width&&r.css("width",d.width+(d.widthUnit?d.widthUnit:"px")),d.align&&r.css("text-align",d.align),a.expandColumn==l&&r.css("text-align","left"),d.valign&&r.css("vertical-align",d.valign),a.showTitle&&r.addClass("ellipsis"),d.formatter?r.html(d.formatter.call(this,R(t,d.field),t,l)):(a.showTitle&&r.attr("title",t[d.field]),r.text(R(t,d.field))),a.expandColumn==l){o?t.isTreeLeaf?r.prepend('<span class="treetable-expander '+c+'"></span>'):r.prepend('<span class="treetable-expander"></span>'):i?r.prepend('<span class="treetable-expander '+c+'"></span>'):r.prepend('<span class="treetable-expander"></span>');for(var f=0;f<s-a.expandColumn;f++){r.prepend('<span class="treetable-indent"></span>')}}p.append(r)}}),p},y=function(a){e(a).off("click").on("click",function(){e(".search-collapse").slideToggle()})},k=function(a){e(a).off("click").on("click",function(){n.refresh()})},j=function(){e(".bootstrap-tree-table .treetable-bars .columns label input").off("click").on("click",function(){var a=e(this);a.prop("checked")?n.showColumn(e(this).val()):n.hideColumn(e(this).val())})},T=function(){n.find("tbody").find("tr").unbind(),n.find("tbody").find("tr").click(function(){if(n.hasSelectItem){var t=e(this).find("input[name='select_item']");"radio"==t.attr("type")?(t.prop("checked",!0),n.find("tbody").find("tr").removeClass("treetable-selected"),e(this).addClass("treetable-selected")):"checkbox"==t.attr("type")?t.prop("checked")?(t.prop("checked",!0),n.find("tbody").find("tr").removeClass("treetable-selected"),e(this).addClass("treetable-selected")):(t.prop("checked",!1),n.find("tbody").find("tr").removeClass("treetable-selected")):t.prop("checked")?(t.prop("checked",!1),e(this).removeClass("treetable-selected")):(t.prop("checked",!0),e(this).addClass("treetable-selected"));var i=n.data_obj["id_"+e(this).data("id")];N(a,a.onClickRow,[i],i)}})},S=function(){n.find("tbody").find("tr").find(".treetable-expander").unbind(),n.find("tbody").find("tr").find(".treetable-expander").click(function(){var t=e(this).hasClass(a.expanderExpandedClass),i=e(this).hasClass(a.expanderCollapsedClass);if(t||i){var s=e(this).parent().parent(),l=s.attr("id"),d=s.attr("pid"),o=s.attr("data-id"),r=n.find("tbody").find("tr[id^='"+l+"_']");if(a.pagination){var r=n.find("tbody").find("tr[id^='"+l+"_']");if(r&&r.length>0){t?"row_root"==d?(e('table tr[id^="'+l+'_"]').css("display","none"),e('table tr[id^="'+l+'_"]').each(function(t,n){var i=e(n).find(".treetable-expander").hasClass(a.expanderExpandedClass);i&&e(n).find(".treetable-expander").trigger("click")})):e.each(r,function(t,n){e(n).css("display","none");var i=e(n).find(".treetable-expander").hasClass(a.expanderExpandedClass);i&&e(n).find(".treetable-expander").trigger("click")}):"row_root"==d?e('table tr[pid="'+l+'"]').css("display","table"):e.each(r,function(t,n){var i=e("#"+e(n).attr("pid")).children().eq(a.expandColumn).find(".treetable-expander");i.hasClass(a.expanderExpandedClass),i.hasClass(a.expanderCollapsedClass);l==e(n).attr("pid")&&e(n).css("display","table")})}else{if(a.pagination){var p={};p[a.parentCode]=o,a.dataUrl&&e.ajax({type:a.type,url:a.dataUrl,data:p,dataType:"json",success:function(a,t,i){e("#"+l+"_load").remove();var s=a;a=s,n.appendData(a)},error:function(t,n){var i='<tr><td colspan="'+a.columns.length+'"><div style="display: block;text-align: center;">'+t.responseText+"</div></td></tr>";e("#"+l).after(i)}})}}t?(e(this).removeClass(a.expanderExpandedClass),e(this).addClass(a.expanderCollapsedClass)):(e(this).removeClass(a.expanderCollapsedClass),e(this).addClass(a.expanderExpandedClass))}else{t?(e(this).removeClass(a.expanderExpandedClass),e(this).addClass(a.expanderCollapsedClass),r&&r.length>0&&e.each(r,function(a,t){e(t).css("display","none")})):(e(this).removeClass(a.expanderCollapsedClass),e(this).addClass(a.expanderExpandedClass),r&&r.length>0&&e.each(r,function(t,n){var i=e("#"+e(n).attr("pid")).children().eq(a.expandColumn).find(".treetable-expander"),s=e("#"+e(n).attr("pid")).css("display");i.hasClass(a.expanderExpandedClass)&&"table"==s&&e(n).css("display","table")}))}}})};n.refresh=function(e){e&&(n.lastAjaxParams=e),p(n.lastAjaxParams)},n.appendData=function(t){t.reverse(),e.each(t,function(t,i){a.pagination&&(i.__nodes=!((1==i.nodes?0:1)&&("true"==i.nodes||1==i.nodes?0:1)));var s,l=n.data_obj["id_"+i[a.code]],d=n.data_obj["id_"+i[a.parentCode]],o=n.data_list["_n_"+i[a.parentCode]],r="",p="",c=1;if(l&&l.row_id&&""!=l.row_id&&(r=l.row_id),d){if(p=d.row_id,""==r){var u=0;o&&o.length>0&&(u=o.length),r=d.row_id+"_"+u}c=d.lv+1,s=_(i,!0,c,r,p,a.pagination,i[a.code]);var f=e("#"+d.row_id).children().eq(a.expandColumn).find(".treetable-expander"),h=f.hasClass(a.expanderExpandedClass),b=f.hasClass(a.expanderCollapsedClass);if(h||b?h&&s.css("display","table"):f.addClass(a.expanderCollapsedClass),l){e("#"+l.row_id).before(s),e("#"+l.row_id).remove()}else{var v=d.row_id.split("_");d.row_id.substring(0,d.row_id.length-(v[v.length-1]+"").length)+(parseInt(v[v.length-1])+1);e("#"+d.row_id).after(s)}}else{if(s=_(i,!1,c,r,p,a.pagination,i[a.code]),l){e("#"+l.row_id).before(s),e("#"+l.row_id).remove()}else{var g=n.find("tbody");g.append(s)}}i.isShow=!0,m([i])}),S(),T(),d()},n.toggleRow=function(a){var t=n.data_obj["id_"+a],i=e("#"+t.row_id).find(".treetable-expander");i.trigger("click")},n.expandRow=function(a){var t=n.data_obj["id_"+a],i=e("#"+t.row_id).find(".treetable-expander"),s=i.hasClass(n.options.expanderCollapsedClass);s&&i.trigger("click")},n.collapseRow=function(a){var t=n.data_obj["id_"+a],i=e("#"+t.row_id).find(".treetable-expander"),s=i.hasClass(n.options.expanderExpandedClass);s&&i.trigger("click")},n.expandAll=function(){n.find("tbody").find("tr").find(".treetable-expander").each(function(t,n){var i=e(n).hasClass(a.expanderCollapsedClass);i&&e(n).trigger("click")})},n.collapseAll=function(){n.find("tbody").find("tr").find(".treetable-expander").each(function(t,n){var i=e(n).hasClass(a.expanderExpandedClass);i&&e(n).trigger("click")})},n.showColumn=function(t,i){var s=e.inArray(t,n.hiddenColumns);if(s>-1&&n.hiddenColumns.splice(s,1),n.find("."+t+"_cls").show(),i&&a.showColumns){var l=e(".bootstrap-tree-table .treetable-bars .columns label").find("input[value='"+t+"']");l.prop("checked","checked")}},n.hideColumn=function(t,i){if(n.hiddenColumns.push(t),n.find("."+t+"_cls").hide(),i&&a.showColumns){var s=e(".bootstrap-tree-table .treetable-bars .columns label").find("input[value='"+t+"']");s.prop("checked","")}};var R=function(e,a){var t=e;if("string"!=typeof a||e.hasOwnProperty(a)){return e[a]}var n=a.split(".");for(var i in n){t=t&&t[n[i]]}return t},N=function(a,t,n,i){var s=t;if("string"==typeof t){var l=t.split(".");l.length>1?(s=window,e.each(l,function(e,a){s=s[a]})):s=window[t]}return"object"==typeof s?s:"function"==typeof s?s.apply(a,n):!s&&"string"==typeof t&&sprintf.apply(this,[t].concat(n))?sprintf.apply(this,[t].concat(n)):i},I=function(e){return"每页显示 "+e+" 条记录"},E=function(e,a,t){return"显示第 "+e+" 到第 "+a+" 条记录,总共 "+t+" 条记录。"};return i(),n},e.fn.bootstrapTreeTable.methods={getSelections:function(a,t){var n=a.find("tbody").find("tr").find("input[name='select_item']:checked"),i=[];if("radio"==n.attr("type")){var s=a.data_obj["id_"+n.val()];i.push(s)}else{n.each(function(t,n){var s=a.data_obj["id_"+e(n).val()];i.push(s)})}return i},refresh:function(e,a){a?e.refresh(a):e.refresh()},appendData:function(e,a){a&&e.appendData(a)},toggleRow:function(e,a){e.toggleRow(a)},expandRow:function(e,a){e.expandRow(a)},collapseRow:function(e,a){e.collapseRow(a)},expandAll:function(e){e.expandAll()},collapseAll:function(e){e.collapseAll()},showColumn:function(e,a){e.showColumn(a,!0)},hideColumn:function(e,a){e.hideColumn(a,!0)}},e.fn.bootstrapTreeTable.defaults={code:"code",parentCode:"parentCode",rootIdValue:0,data:null,type:"GET",url:null,ajaxParams:{},expandColumn:1,expandAll:!1,expandFirst:!0,striped:!1,bordered:!1,hover:!0,condensed:!1,columns:[],toolbar:null,height:0,pagination:!1,dataUrl:null,pageNumber:1,pageSize:10,onClickRow:null,pageList:[10,25,50],showTitle:!0,showSearch:!0,showColumns:!0,showRefresh:!0,paginationPreText:"&lsaquo;",paginationNextText:"&rsaquo;",expanderExpandedClass:"glyphicon glyphicon-chevron-down",expanderCollapsedClass:"glyphicon glyphicon-chevron-right",responseHandler:function(e){return !1},onLoadSuccess:function(e){return !1}}}(jQuery);
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/locale/bootstrap-table-zh-CN.js b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/locale/bootstrap-table-zh-CN.js
new file mode 100644
index 0000000..7f10d2e
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/locale/bootstrap-table-zh-CN.js
@@ -0,0 +1,109 @@
+/**
+ * Bootstrap Table Chinese translation
+ * Author: Zhixin Wen<wenzhixin2010@gmail.com>
+ */
+$.fn.bootstrapTable.locales['zh-CN'] = {
+  formatShowSearch: function formatShowSearch() {
+    return '隐藏/显示搜索';
+  },
+  formatPageGo: function formatPageGo() {
+    return '跳转';
+  },
+  formatCopyRows: function formatCopyRows() {
+    return '复制行';
+  },
+  formatPrint: function formatPrint() {
+    return '打印';
+  },
+  formatLoadingMessage: function formatLoadingMessage() {
+    return '正在努力地加载数据中,请稍候';
+  },
+  formatRecordsPerPage: function formatRecordsPerPage(pageNumber) {
+    return "每页显示 ".concat(pageNumber, " 条记录");
+  },
+  formatShowingRows: function formatShowingRows(pageFrom, pageTo, totalRows, totalNotFiltered) {
+    if (totalNotFiltered !== undefined && totalNotFiltered > 0 && totalNotFiltered > totalRows) {
+      return "显示第 ".concat(pageFrom, " 到第 ").concat(pageTo, " 条记录,总共 ").concat(totalRows, " 条记录(从 ").concat(totalNotFiltered, " 总记录中过滤)");
+    }
+    return "显示第 ".concat(pageFrom, " 到第 ").concat(pageTo, " 条记录,总共 ").concat(totalRows, " 条记录");
+  },
+  formatSRPaginationPreText: function formatSRPaginationPreText() {
+    return '上一页';
+  },
+  formatSRPaginationPageText: function formatSRPaginationPageText(page) {
+    return "第".concat(page, "页");
+  },
+  formatSRPaginationNextText: function formatSRPaginationNextText() {
+    return '下一页';
+  },
+  formatDetailPagination: function formatDetailPagination(totalRows) {
+    return "总共 ".concat(totalRows, " 条记录");
+  },
+  formatClearSearch: function formatClearSearch() {
+    return '清空过滤';
+  },
+  formatSearch: function formatSearch() {
+    return '搜索';
+  },
+  formatNoMatches: function formatNoMatches() {
+    return '没有找到匹配的记录';
+  },
+  formatPaginationSwitch: function formatPaginationSwitch() {
+    return '隐藏/显示分页';
+  },
+  formatPaginationSwitchDown: function formatPaginationSwitchDown() {
+    return '显示分页';
+  },
+  formatPaginationSwitchUp: function formatPaginationSwitchUp() {
+    return '隐藏分页';
+  },
+  formatRefresh: function formatRefresh() {
+    return '刷新';
+  },
+  formatToggle: function formatToggle() {
+    return '切换';
+  },
+  formatToggleOn: function formatToggleOn() {
+    return '显示卡片视图';
+  },
+  formatToggleOff: function formatToggleOff() {
+    return '隐藏卡片视图';
+  },
+  formatColumns: function formatColumns() {
+    return '列';
+  },
+  formatColumnsToggleAll: function formatColumnsToggleAll() {
+    return '切换所有';
+  },
+  formatFullscreen: function formatFullscreen() {
+    return '全屏';
+  },
+  formatAllRows: function formatAllRows() {
+    return '所有';
+  },
+  formatAutoRefresh: function formatAutoRefresh() {
+    return '自动刷新';
+  },
+  formatExport: function formatExport() {
+    return '导出数据';
+  },
+  formatJumpTo: function formatJumpTo() {
+    return '跳转';
+  },
+  formatAdvancedSearch: function formatAdvancedSearch() {
+    return '高级搜索';
+  },
+  formatAdvancedCloseButton: function formatAdvancedCloseButton() {
+    return '关闭';
+  },
+  formatFilterControlSwitch: function formatFilterControlSwitch() {
+    return '隐藏/显示过滤控制';
+  },
+  formatFilterControlSwitchHide: function formatFilterControlSwitchHide() {
+    return '隐藏过滤控制';
+  },
+  formatFilterControlSwitchShow: function formatFilterControlSwitchShow() {
+    return '显示过滤控制';
+  }
+};
+$.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales['zh-CN']);
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/locale/bootstrap-table-zh-CN.min.js b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/locale/bootstrap-table-zh-CN.min.js
new file mode 100644
index 0000000..76a1da2
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/locale/bootstrap-table-zh-CN.min.js
@@ -0,0 +1 @@
+$.fn.bootstrapTable.locales["zh-CN"]={formatShowSearch:function formatShowSearch(){return"隐藏/显示搜索"},formatPageGo:function formatPageGo(){return"跳转"},formatCopyRows:function formatCopyRows(){return"复制行"},formatPrint:function formatPrint(){return"打印"},formatLoadingMessage:function formatLoadingMessage(){return"正在努力地加载数据中,请稍候"},formatRecordsPerPage:function formatRecordsPerPage(pageNumber){return"每页显示 ".concat(pageNumber," 条记录")},formatShowingRows:function formatShowingRows(pageFrom,pageTo,totalRows,totalNotFiltered){if(totalNotFiltered!==undefined&&totalNotFiltered>0&&totalNotFiltered>totalRows){return"显示第 ".concat(pageFrom," 到第 ").concat(pageTo," 条记录,总共 ").concat(totalRows," 条记录(从 ").concat(totalNotFiltered," 总记录中过滤)")}return"显示第 ".concat(pageFrom," 到第 ").concat(pageTo," 条记录,总共 ").concat(totalRows," 条记录")},formatSRPaginationPreText:function formatSRPaginationPreText(){return"上一页"},formatSRPaginationPageText:function formatSRPaginationPageText(page){return"第".concat(page,"页")},formatSRPaginationNextText:function formatSRPaginationNextText(){return"下一页"},formatDetailPagination:function formatDetailPagination(totalRows){return"总共 ".concat(totalRows," 条记录")},formatClearSearch:function formatClearSearch(){return"清空过滤"},formatSearch:function formatSearch(){return"搜索"},formatNoMatches:function formatNoMatches(){return"没有找到匹配的记录"},formatPaginationSwitch:function formatPaginationSwitch(){return"隐藏/显示分页"},formatPaginationSwitchDown:function formatPaginationSwitchDown(){return"显示分页"},formatPaginationSwitchUp:function formatPaginationSwitchUp(){return"隐藏分页"},formatRefresh:function formatRefresh(){return"刷新"},formatToggle:function formatToggle(){return"切换"},formatToggleOn:function formatToggleOn(){return"显示卡片视图"},formatToggleOff:function formatToggleOff(){return"隐藏卡片视图"},formatColumns:function formatColumns(){return"列"},formatColumnsToggleAll:function formatColumnsToggleAll(){return"切换所有"},formatFullscreen:function formatFullscreen(){return"全屏"},formatAllRows:function formatAllRows(){return"所有"},formatAutoRefresh:function formatAutoRefresh(){return"自动刷新"},formatExport:function formatExport(){return"导出数据"},formatJumpTo:function formatJumpTo(){return"跳转"},formatAdvancedSearch:function formatAdvancedSearch(){return"高级搜索"},formatAdvancedCloseButton:function formatAdvancedCloseButton(){return"关闭"},formatFilterControlSwitch:function formatFilterControlSwitch(){return"隐藏/显示过滤控制"},formatFilterControlSwitchHide:function formatFilterControlSwitchHide(){return"隐藏过滤控制"},formatFilterControlSwitchShow:function formatFilterControlSwitchShow(){return"显示过滤控制"}};$.extend($.fn.bootstrapTable.defaults,$.fn.bootstrapTable.locales["zh-CN"]);
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/cropper/cropper.css b/ruoyi-admin/src/main/resources/static/ajax/libs/cropper/cropper.css
new file mode 100644
index 0000000..506909e
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/cropper/cropper.css
@@ -0,0 +1,304 @@
+/*!
+ * Cropper.js v1.5.12
+ * https://fengyuanchen.github.io/cropperjs
+ *
+ * Copyright 2015-present Chen Fengyuan
+ * Released under the MIT license
+ *
+ * Date: 2021-06-12T08:00:11.623Z
+ */
+
+.cropper-container {
+  direction: ltr;
+  font-size: 0;
+  line-height: 0;
+  position: relative;
+  -ms-touch-action: none;
+  touch-action: none;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+}
+
+.cropper-container img {
+  display: block;
+  height: 100%;
+  image-orientation: 0deg;
+  max-height: none !important;
+  max-width: none !important;
+  min-height: 0 !important;
+  min-width: 0 !important;
+  width: 100%;
+}
+
+.cropper-wrap-box,
+.cropper-canvas,
+.cropper-drag-box,
+.cropper-crop-box,
+.cropper-modal {
+  bottom: 0;
+  left: 0;
+  position: absolute;
+  right: 0;
+  top: 0;
+}
+
+.cropper-wrap-box,
+.cropper-canvas {
+  overflow: hidden;
+}
+
+.cropper-drag-box {
+  background-color: #fff;
+  opacity: 0;
+}
+
+.cropper-modal {
+  background-color: #000;
+  opacity: 0.5;
+}
+
+.cropper-view-box {
+  display: block;
+  height: 100%;
+  outline: 1px solid #39f;
+  outline-color: rgba(51, 153, 255, 0.75);
+  overflow: hidden;
+  width: 100%;
+}
+
+.cropper-dashed {
+  border: 0 dashed #eee;
+  display: block;
+  opacity: 0.5;
+  position: absolute;
+}
+
+.cropper-dashed.dashed-h {
+  border-bottom-width: 1px;
+  border-top-width: 1px;
+  height: calc(100% / 3);
+  left: 0;
+  top: calc(100% / 3);
+  width: 100%;
+}
+
+.cropper-dashed.dashed-v {
+  border-left-width: 1px;
+  border-right-width: 1px;
+  height: 100%;
+  left: calc(100% / 3);
+  top: 0;
+  width: calc(100% / 3);
+}
+
+.cropper-center {
+  display: block;
+  height: 0;
+  left: 50%;
+  opacity: 0.75;
+  position: absolute;
+  top: 50%;
+  width: 0;
+}
+
+.cropper-center::before,
+.cropper-center::after {
+  background-color: #eee;
+  content: ' ';
+  display: block;
+  position: absolute;
+}
+
+.cropper-center::before {
+  height: 1px;
+  left: -3px;
+  top: 0;
+  width: 7px;
+}
+
+.cropper-center::after {
+  height: 7px;
+  left: 0;
+  top: -3px;
+  width: 1px;
+}
+
+.cropper-face,
+.cropper-line,
+.cropper-point {
+  display: block;
+  height: 100%;
+  opacity: 0.1;
+  position: absolute;
+  width: 100%;
+}
+
+.cropper-face {
+  background-color: #fff;
+  left: 0;
+  top: 0;
+}
+
+.cropper-line {
+  background-color: #39f;
+}
+
+.cropper-line.line-e {
+  cursor: ew-resize;
+  right: -3px;
+  top: 0;
+  width: 5px;
+}
+
+.cropper-line.line-n {
+  cursor: ns-resize;
+  height: 5px;
+  left: 0;
+  top: -3px;
+}
+
+.cropper-line.line-w {
+  cursor: ew-resize;
+  left: -3px;
+  top: 0;
+  width: 5px;
+}
+
+.cropper-line.line-s {
+  bottom: -3px;
+  cursor: ns-resize;
+  height: 5px;
+  left: 0;
+}
+
+.cropper-point {
+  background-color: #39f;
+  height: 5px;
+  opacity: 0.75;
+  width: 5px;
+}
+
+.cropper-point.point-e {
+  cursor: ew-resize;
+  margin-top: -3px;
+  right: -3px;
+  top: 50%;
+}
+
+.cropper-point.point-n {
+  cursor: ns-resize;
+  left: 50%;
+  margin-left: -3px;
+  top: -3px;
+}
+
+.cropper-point.point-w {
+  cursor: ew-resize;
+  left: -3px;
+  margin-top: -3px;
+  top: 50%;
+}
+
+.cropper-point.point-s {
+  bottom: -3px;
+  cursor: s-resize;
+  left: 50%;
+  margin-left: -3px;
+}
+
+.cropper-point.point-ne {
+  cursor: nesw-resize;
+  right: -3px;
+  top: -3px;
+}
+
+.cropper-point.point-nw {
+  cursor: nwse-resize;
+  left: -3px;
+  top: -3px;
+}
+
+.cropper-point.point-sw {
+  bottom: -3px;
+  cursor: nesw-resize;
+  left: -3px;
+}
+
+.cropper-point.point-se {
+  bottom: -3px;
+  cursor: nwse-resize;
+  height: 20px;
+  opacity: 1;
+  right: -3px;
+  width: 20px;
+}
+
+@media (min-width: 768px) {
+  .cropper-point.point-se {
+    height: 15px;
+    width: 15px;
+  }
+}
+
+@media (min-width: 992px) {
+  .cropper-point.point-se {
+    height: 10px;
+    width: 10px;
+  }
+}
+
+@media (min-width: 1200px) {
+  .cropper-point.point-se {
+    height: 5px;
+    opacity: 0.75;
+    width: 5px;
+  }
+}
+
+.cropper-point.point-se::before {
+  background-color: #39f;
+  bottom: -50%;
+  content: ' ';
+  display: block;
+  height: 200%;
+  opacity: 0;
+  position: absolute;
+  right: -50%;
+  width: 200%;
+}
+
+.cropper-invisible {
+  opacity: 0;
+}
+
+.cropper-bg {
+  background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC');
+}
+
+.cropper-hide {
+  display: block;
+  height: 0;
+  position: absolute;
+  width: 0;
+}
+
+.cropper-hidden {
+  display: none !important;
+}
+
+.cropper-move {
+  cursor: move;
+}
+
+.cropper-crop {
+  cursor: crosshair;
+}
+
+.cropper-disabled .cropper-drag-box,
+.cropper-disabled .cropper-face,
+.cropper-disabled .cropper-line,
+.cropper-disabled .cropper-point {
+  cursor: not-allowed;
+}
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/cropper/cropper.js b/ruoyi-admin/src/main/resources/static/ajax/libs/cropper/cropper.js
new file mode 100644
index 0000000..07b6545
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/cropper/cropper.js
@@ -0,0 +1,3631 @@
+/*!
+ * Cropper.js v1.5.12
+ * https://fengyuanchen.github.io/cropperjs
+ *
+ * Copyright 2015-present Chen Fengyuan
+ * Released under the MIT license
+ *
+ * Date: 2021-06-12T08:00:17.411Z
+ */
+
+(function (global, factory) {
+  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+  typeof define === 'function' && define.amd ? define(factory) :
+  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Cropper = factory());
+}(this, (function () { 'use strict';
+
+  function ownKeys(object, enumerableOnly) {
+    var keys = Object.keys(object);
+
+    if (Object.getOwnPropertySymbols) {
+      var symbols = Object.getOwnPropertySymbols(object);
+
+      if (enumerableOnly) {
+        symbols = symbols.filter(function (sym) {
+          return Object.getOwnPropertyDescriptor(object, sym).enumerable;
+        });
+      }
+
+      keys.push.apply(keys, symbols);
+    }
+
+    return keys;
+  }
+
+  function _objectSpread2(target) {
+    for (var i = 1; i < arguments.length; i++) {
+      var source = arguments[i] != null ? arguments[i] : {};
+
+      if (i % 2) {
+        ownKeys(Object(source), true).forEach(function (key) {
+          _defineProperty(target, key, source[key]);
+        });
+      } else if (Object.getOwnPropertyDescriptors) {
+        Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
+      } else {
+        ownKeys(Object(source)).forEach(function (key) {
+          Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
+        });
+      }
+    }
+
+    return target;
+  }
+
+  function _typeof(obj) {
+    "@babel/helpers - typeof";
+
+    if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
+      _typeof = function (obj) {
+        return typeof obj;
+      };
+    } else {
+      _typeof = function (obj) {
+        return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
+      };
+    }
+
+    return _typeof(obj);
+  }
+
+  function _classCallCheck(instance, Constructor) {
+    if (!(instance instanceof Constructor)) {
+      throw new TypeError("Cannot call a class as a function");
+    }
+  }
+
+  function _defineProperties(target, props) {
+    for (var i = 0; i < props.length; i++) {
+      var descriptor = props[i];
+      descriptor.enumerable = descriptor.enumerable || false;
+      descriptor.configurable = true;
+      if ("value" in descriptor) descriptor.writable = true;
+      Object.defineProperty(target, descriptor.key, descriptor);
+    }
+  }
+
+  function _createClass(Constructor, protoProps, staticProps) {
+    if (protoProps) _defineProperties(Constructor.prototype, protoProps);
+    if (staticProps) _defineProperties(Constructor, staticProps);
+    return Constructor;
+  }
+
+  function _defineProperty(obj, key, value) {
+    if (key in obj) {
+      Object.defineProperty(obj, key, {
+        value: value,
+        enumerable: true,
+        configurable: true,
+        writable: true
+      });
+    } else {
+      obj[key] = value;
+    }
+
+    return obj;
+  }
+
+  function _toConsumableArray(arr) {
+    return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
+  }
+
+  function _arrayWithoutHoles(arr) {
+    if (Array.isArray(arr)) return _arrayLikeToArray(arr);
+  }
+
+  function _iterableToArray(iter) {
+    if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
+  }
+
+  function _unsupportedIterableToArray(o, minLen) {
+    if (!o) return;
+    if (typeof o === "string") return _arrayLikeToArray(o, minLen);
+    var n = Object.prototype.toString.call(o).slice(8, -1);
+    if (n === "Object" && o.constructor) n = o.constructor.name;
+    if (n === "Map" || n === "Set") return Array.from(o);
+    if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
+  }
+
+  function _arrayLikeToArray(arr, len) {
+    if (len == null || len > arr.length) len = arr.length;
+
+    for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
+
+    return arr2;
+  }
+
+  function _nonIterableSpread() {
+    throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
+  }
+
+  var IS_BROWSER = typeof window !== 'undefined' && typeof window.document !== 'undefined';
+  var WINDOW = IS_BROWSER ? window : {};
+  var IS_TOUCH_DEVICE = IS_BROWSER && WINDOW.document.documentElement ? 'ontouchstart' in WINDOW.document.documentElement : false;
+  var HAS_POINTER_EVENT = IS_BROWSER ? 'PointerEvent' in WINDOW : false;
+  var NAMESPACE = 'cropper'; // Actions
+
+  var ACTION_ALL = 'all';
+  var ACTION_CROP = 'crop';
+  var ACTION_MOVE = 'move';
+  var ACTION_ZOOM = 'zoom';
+  var ACTION_EAST = 'e';
+  var ACTION_WEST = 'w';
+  var ACTION_SOUTH = 's';
+  var ACTION_NORTH = 'n';
+  var ACTION_NORTH_EAST = 'ne';
+  var ACTION_NORTH_WEST = 'nw';
+  var ACTION_SOUTH_EAST = 'se';
+  var ACTION_SOUTH_WEST = 'sw'; // Classes
+
+  var CLASS_CROP = "".concat(NAMESPACE, "-crop");
+  var CLASS_DISABLED = "".concat(NAMESPACE, "-disabled");
+  var CLASS_HIDDEN = "".concat(NAMESPACE, "-hidden");
+  var CLASS_HIDE = "".concat(NAMESPACE, "-hide");
+  var CLASS_INVISIBLE = "".concat(NAMESPACE, "-invisible");
+  var CLASS_MODAL = "".concat(NAMESPACE, "-modal");
+  var CLASS_MOVE = "".concat(NAMESPACE, "-move"); // Data keys
+
+  var DATA_ACTION = "".concat(NAMESPACE, "Action");
+  var DATA_PREVIEW = "".concat(NAMESPACE, "Preview"); // Drag modes
+
+  var DRAG_MODE_CROP = 'crop';
+  var DRAG_MODE_MOVE = 'move';
+  var DRAG_MODE_NONE = 'none'; // Events
+
+  var EVENT_CROP = 'crop';
+  var EVENT_CROP_END = 'cropend';
+  var EVENT_CROP_MOVE = 'cropmove';
+  var EVENT_CROP_START = 'cropstart';
+  var EVENT_DBLCLICK = 'dblclick';
+  var EVENT_TOUCH_START = IS_TOUCH_DEVICE ? 'touchstart' : 'mousedown';
+  var EVENT_TOUCH_MOVE = IS_TOUCH_DEVICE ? 'touchmove' : 'mousemove';
+  var EVENT_TOUCH_END = IS_TOUCH_DEVICE ? 'touchend touchcancel' : 'mouseup';
+  var EVENT_POINTER_DOWN = HAS_POINTER_EVENT ? 'pointerdown' : EVENT_TOUCH_START;
+  var EVENT_POINTER_MOVE = HAS_POINTER_EVENT ? 'pointermove' : EVENT_TOUCH_MOVE;
+  var EVENT_POINTER_UP = HAS_POINTER_EVENT ? 'pointerup pointercancel' : EVENT_TOUCH_END;
+  var EVENT_READY = 'ready';
+  var EVENT_RESIZE = 'resize';
+  var EVENT_WHEEL = 'wheel';
+  var EVENT_ZOOM = 'zoom'; // Mime types
+
+  var MIME_TYPE_JPEG = 'image/jpeg'; // RegExps
+
+  var REGEXP_ACTIONS = /^e|w|s|n|se|sw|ne|nw|all|crop|move|zoom$/;
+  var REGEXP_DATA_URL = /^data:/;
+  var REGEXP_DATA_URL_JPEG = /^data:image\/jpeg;base64,/;
+  var REGEXP_TAG_NAME = /^img|canvas$/i; // Misc
+  // Inspired by the default width and height of a canvas element.
+
+  var MIN_CONTAINER_WIDTH = 200;
+  var MIN_CONTAINER_HEIGHT = 100;
+
+  var DEFAULTS = {
+    // Define the view mode of the cropper
+    viewMode: 0,
+    // 0, 1, 2, 3
+    // Define the dragging mode of the cropper
+    dragMode: DRAG_MODE_CROP,
+    // 'crop', 'move' or 'none'
+    // Define the initial aspect ratio of the crop box
+    initialAspectRatio: NaN,
+    // Define the aspect ratio of the crop box
+    aspectRatio: NaN,
+    // An object with the previous cropping result data
+    data: null,
+    // A selector for adding extra containers to preview
+    preview: '',
+    // Re-render the cropper when resize the window
+    responsive: true,
+    // Restore the cropped area after resize the window
+    restore: true,
+    // Check if the current image is a cross-origin image
+    checkCrossOrigin: true,
+    // Check the current image's Exif Orientation information
+    checkOrientation: true,
+    // Show the black modal
+    modal: true,
+    // Show the dashed lines for guiding
+    guides: true,
+    // Show the center indicator for guiding
+    center: true,
+    // Show the white modal to highlight the crop box
+    highlight: true,
+    // Show the grid background
+    background: true,
+    // Enable to crop the image automatically when initialize
+    autoCrop: true,
+    // Define the percentage of automatic cropping area when initializes
+    autoCropArea: 0.8,
+    // Enable to move the image
+    movable: true,
+    // Enable to rotate the image
+    rotatable: true,
+    // Enable to scale the image
+    scalable: true,
+    // Enable to zoom the image
+    zoomable: true,
+    // Enable to zoom the image by dragging touch
+    zoomOnTouch: true,
+    // Enable to zoom the image by wheeling mouse
+    zoomOnWheel: true,
+    // Define zoom ratio when zoom the image by wheeling mouse
+    wheelZoomRatio: 0.1,
+    // Enable to move the crop box
+    cropBoxMovable: true,
+    // Enable to resize the crop box
+    cropBoxResizable: true,
+    // Toggle drag mode between "crop" and "move" when click twice on the cropper
+    toggleDragModeOnDblclick: true,
+    // Size limitation
+    minCanvasWidth: 0,
+    minCanvasHeight: 0,
+    minCropBoxWidth: 0,
+    minCropBoxHeight: 0,
+    minContainerWidth: MIN_CONTAINER_WIDTH,
+    minContainerHeight: MIN_CONTAINER_HEIGHT,
+    // Shortcuts of events
+    ready: null,
+    cropstart: null,
+    cropmove: null,
+    cropend: null,
+    crop: null,
+    zoom: null
+  };
+
+  var TEMPLATE = '<div class="cropper-container" touch-action="none">' + '<div class="cropper-wrap-box">' + '<div class="cropper-canvas"></div>' + '</div>' + '<div class="cropper-drag-box"></div>' + '<div class="cropper-crop-box">' + '<span class="cropper-view-box"></span>' + '<span class="cropper-dashed dashed-h"></span>' + '<span class="cropper-dashed dashed-v"></span>' + '<span class="cropper-center"></span>' + '<span class="cropper-face"></span>' + '<span class="cropper-line line-e" data-cropper-action="e"></span>' + '<span class="cropper-line line-n" data-cropper-action="n"></span>' + '<span class="cropper-line line-w" data-cropper-action="w"></span>' + '<span class="cropper-line line-s" data-cropper-action="s"></span>' + '<span class="cropper-point point-e" data-cropper-action="e"></span>' + '<span class="cropper-point point-n" data-cropper-action="n"></span>' + '<span class="cropper-point point-w" data-cropper-action="w"></span>' + '<span class="cropper-point point-s" data-cropper-action="s"></span>' + '<span class="cropper-point point-ne" data-cropper-action="ne"></span>' + '<span class="cropper-point point-nw" data-cropper-action="nw"></span>' + '<span class="cropper-point point-sw" data-cropper-action="sw"></span>' + '<span class="cropper-point point-se" data-cropper-action="se"></span>' + '</div>' + '</div>';
+
+  /**
+   * Check if the given value is not a number.
+   */
+
+  var isNaN = Number.isNaN || WINDOW.isNaN;
+  /**
+   * Check if the given value is a number.
+   * @param {*} value - The value to check.
+   * @returns {boolean} Returns `true` if the given value is a number, else `false`.
+   */
+
+  function isNumber(value) {
+    return typeof value === 'number' && !isNaN(value);
+  }
+  /**
+   * Check if the given value is a positive number.
+   * @param {*} value - The value to check.
+   * @returns {boolean} Returns `true` if the given value is a positive number, else `false`.
+   */
+
+  var isPositiveNumber = function isPositiveNumber(value) {
+    return value > 0 && value < Infinity;
+  };
+  /**
+   * Check if the given value is undefined.
+   * @param {*} value - The value to check.
+   * @returns {boolean} Returns `true` if the given value is undefined, else `false`.
+   */
+
+  function isUndefined(value) {
+    return typeof value === 'undefined';
+  }
+  /**
+   * Check if the given value is an object.
+   * @param {*} value - The value to check.
+   * @returns {boolean} Returns `true` if the given value is an object, else `false`.
+   */
+
+  function isObject(value) {
+    return _typeof(value) === 'object' && value !== null;
+  }
+  var hasOwnProperty = Object.prototype.hasOwnProperty;
+  /**
+   * Check if the given value is a plain object.
+   * @param {*} value - The value to check.
+   * @returns {boolean} Returns `true` if the given value is a plain object, else `false`.
+   */
+
+  function isPlainObject(value) {
+    if (!isObject(value)) {
+      return false;
+    }
+
+    try {
+      var _constructor = value.constructor;
+      var prototype = _constructor.prototype;
+      return _constructor && prototype && hasOwnProperty.call(prototype, 'isPrototypeOf');
+    } catch (error) {
+      return false;
+    }
+  }
+  /**
+   * Check if the given value is a function.
+   * @param {*} value - The value to check.
+   * @returns {boolean} Returns `true` if the given value is a function, else `false`.
+   */
+
+  function isFunction(value) {
+    return typeof value === 'function';
+  }
+  var slice = Array.prototype.slice;
+  /**
+   * Convert array-like or iterable object to an array.
+   * @param {*} value - The value to convert.
+   * @returns {Array} Returns a new array.
+   */
+
+  function toArray(value) {
+    return Array.from ? Array.from(value) : slice.call(value);
+  }
+  /**
+   * Iterate the given data.
+   * @param {*} data - The data to iterate.
+   * @param {Function} callback - The process function for each element.
+   * @returns {*} The original data.
+   */
+
+  function forEach(data, callback) {
+    if (data && isFunction(callback)) {
+      if (Array.isArray(data) || isNumber(data.length)
+      /* array-like */
+      ) {
+          toArray(data).forEach(function (value, key) {
+            callback.call(data, value, key, data);
+          });
+        } else if (isObject(data)) {
+        Object.keys(data).forEach(function (key) {
+          callback.call(data, data[key], key, data);
+        });
+      }
+    }
+
+    return data;
+  }
+  /**
+   * Extend the given object.
+   * @param {*} target - The target object to extend.
+   * @param {*} args - The rest objects for merging to the target object.
+   * @returns {Object} The extended object.
+   */
+
+  var assign = Object.assign || function assign(target) {
+    for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
+      args[_key - 1] = arguments[_key];
+    }
+
+    if (isObject(target) && args.length > 0) {
+      args.forEach(function (arg) {
+        if (isObject(arg)) {
+          Object.keys(arg).forEach(function (key) {
+            target[key] = arg[key];
+          });
+        }
+      });
+    }
+
+    return target;
+  };
+  var REGEXP_DECIMALS = /\.\d*(?:0|9){12}\d*$/;
+  /**
+   * Normalize decimal number.
+   * Check out {@link https://0.30000000000000004.com/}
+   * @param {number} value - The value to normalize.
+   * @param {number} [times=100000000000] - The times for normalizing.
+   * @returns {number} Returns the normalized number.
+   */
+
+  function normalizeDecimalNumber(value) {
+    var times = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 100000000000;
+    return REGEXP_DECIMALS.test(value) ? Math.round(value * times) / times : value;
+  }
+  var REGEXP_SUFFIX = /^width|height|left|top|marginLeft|marginTop$/;
+  /**
+   * Apply styles to the given element.
+   * @param {Element} element - The target element.
+   * @param {Object} styles - The styles for applying.
+   */
+
+  function setStyle(element, styles) {
+    var style = element.style;
+    forEach(styles, function (value, property) {
+      if (REGEXP_SUFFIX.test(property) && isNumber(value)) {
+        value = "".concat(value, "px");
+      }
+
+      style[property] = value;
+    });
+  }
+  /**
+   * Check if the given element has a special class.
+   * @param {Element} element - The element to check.
+   * @param {string} value - The class to search.
+   * @returns {boolean} Returns `true` if the special class was found.
+   */
+
+  function hasClass(element, value) {
+    return element.classList ? element.classList.contains(value) : element.className.indexOf(value) > -1;
+  }
+  /**
+   * Add classes to the given element.
+   * @param {Element} element - The target element.
+   * @param {string} value - The classes to be added.
+   */
+
+  function addClass(element, value) {
+    if (!value) {
+      return;
+    }
+
+    if (isNumber(element.length)) {
+      forEach(element, function (elem) {
+        addClass(elem, value);
+      });
+      return;
+    }
+
+    if (element.classList) {
+      element.classList.add(value);
+      return;
+    }
+
+    var className = element.className.trim();
+
+    if (!className) {
+      element.className = value;
+    } else if (className.indexOf(value) < 0) {
+      element.className = "".concat(className, " ").concat(value);
+    }
+  }
+  /**
+   * Remove classes from the given element.
+   * @param {Element} element - The target element.
+   * @param {string} value - The classes to be removed.
+   */
+
+  function removeClass(element, value) {
+    if (!value) {
+      return;
+    }
+
+    if (isNumber(element.length)) {
+      forEach(element, function (elem) {
+        removeClass(elem, value);
+      });
+      return;
+    }
+
+    if (element.classList) {
+      element.classList.remove(value);
+      return;
+    }
+
+    if (element.className.indexOf(value) >= 0) {
+      element.className = element.className.replace(value, '');
+    }
+  }
+  /**
+   * Add or remove classes from the given element.
+   * @param {Element} element - The target element.
+   * @param {string} value - The classes to be toggled.
+   * @param {boolean} added - Add only.
+   */
+
+  function toggleClass(element, value, added) {
+    if (!value) {
+      return;
+    }
+
+    if (isNumber(element.length)) {
+      forEach(element, function (elem) {
+        toggleClass(elem, value, added);
+      });
+      return;
+    } // IE10-11 doesn't support the second parameter of `classList.toggle`
+
+
+    if (added) {
+      addClass(element, value);
+    } else {
+      removeClass(element, value);
+    }
+  }
+  var REGEXP_CAMEL_CASE = /([a-z\d])([A-Z])/g;
+  /**
+   * Transform the given string from camelCase to kebab-case
+   * @param {string} value - The value to transform.
+   * @returns {string} The transformed value.
+   */
+
+  function toParamCase(value) {
+    return value.replace(REGEXP_CAMEL_CASE, '$1-$2').toLowerCase();
+  }
+  /**
+   * Get data from the given element.
+   * @param {Element} element - The target element.
+   * @param {string} name - The data key to get.
+   * @returns {string} The data value.
+   */
+
+  function getData(element, name) {
+    if (isObject(element[name])) {
+      return element[name];
+    }
+
+    if (element.dataset) {
+      return element.dataset[name];
+    }
+
+    return element.getAttribute("data-".concat(toParamCase(name)));
+  }
+  /**
+   * Set data to the given element.
+   * @param {Element} element - The target element.
+   * @param {string} name - The data key to set.
+   * @param {string} data - The data value.
+   */
+
+  function setData(element, name, data) {
+    if (isObject(data)) {
+      element[name] = data;
+    } else if (element.dataset) {
+      element.dataset[name] = data;
+    } else {
+      element.setAttribute("data-".concat(toParamCase(name)), data);
+    }
+  }
+  /**
+   * Remove data from the given element.
+   * @param {Element} element - The target element.
+   * @param {string} name - The data key to remove.
+   */
+
+  function removeData(element, name) {
+    if (isObject(element[name])) {
+      try {
+        delete element[name];
+      } catch (error) {
+        element[name] = undefined;
+      }
+    } else if (element.dataset) {
+      // #128 Safari not allows to delete dataset property
+      try {
+        delete element.dataset[name];
+      } catch (error) {
+        element.dataset[name] = undefined;
+      }
+    } else {
+      element.removeAttribute("data-".concat(toParamCase(name)));
+    }
+  }
+  var REGEXP_SPACES = /\s\s*/;
+
+  var onceSupported = function () {
+    var supported = false;
+
+    if (IS_BROWSER) {
+      var once = false;
+
+      var listener = function listener() {};
+
+      var options = Object.defineProperty({}, 'once', {
+        get: function get() {
+          supported = true;
+          return once;
+        },
+
+        /**
+         * This setter can fix a `TypeError` in strict mode
+         * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Getter_only}
+         * @param {boolean} value - The value to set
+         */
+        set: function set(value) {
+          once = value;
+        }
+      });
+      WINDOW.addEventListener('test', listener, options);
+      WINDOW.removeEventListener('test', listener, options);
+    }
+
+    return supported;
+  }();
+  /**
+   * Remove event listener from the target element.
+   * @param {Element} element - The event target.
+   * @param {string} type - The event type(s).
+   * @param {Function} listener - The event listener.
+   * @param {Object} options - The event options.
+   */
+
+
+  function removeListener(element, type, listener) {
+    var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
+    var handler = listener;
+    type.trim().split(REGEXP_SPACES).forEach(function (event) {
+      if (!onceSupported) {
+        var listeners = element.listeners;
+
+        if (listeners && listeners[event] && listeners[event][listener]) {
+          handler = listeners[event][listener];
+          delete listeners[event][listener];
+
+          if (Object.keys(listeners[event]).length === 0) {
+            delete listeners[event];
+          }
+
+          if (Object.keys(listeners).length === 0) {
+            delete element.listeners;
+          }
+        }
+      }
+
+      element.removeEventListener(event, handler, options);
+    });
+  }
+  /**
+   * Add event listener to the target element.
+   * @param {Element} element - The event target.
+   * @param {string} type - The event type(s).
+   * @param {Function} listener - The event listener.
+   * @param {Object} options - The event options.
+   */
+
+  function addListener(element, type, listener) {
+    var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
+    var _handler = listener;
+    type.trim().split(REGEXP_SPACES).forEach(function (event) {
+      if (options.once && !onceSupported) {
+        var _element$listeners = element.listeners,
+            listeners = _element$listeners === void 0 ? {} : _element$listeners;
+
+        _handler = function handler() {
+          delete listeners[event][listener];
+          element.removeEventListener(event, _handler, options);
+
+          for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
+            args[_key2] = arguments[_key2];
+          }
+
+          listener.apply(element, args);
+        };
+
+        if (!listeners[event]) {
+          listeners[event] = {};
+        }
+
+        if (listeners[event][listener]) {
+          element.removeEventListener(event, listeners[event][listener], options);
+        }
+
+        listeners[event][listener] = _handler;
+        element.listeners = listeners;
+      }
+
+      element.addEventListener(event, _handler, options);
+    });
+  }
+  /**
+   * Dispatch event on the target element.
+   * @param {Element} element - The event target.
+   * @param {string} type - The event type(s).
+   * @param {Object} data - The additional event data.
+   * @returns {boolean} Indicate if the event is default prevented or not.
+   */
+
+  function dispatchEvent(element, type, data) {
+    var event; // Event and CustomEvent on IE9-11 are global objects, not constructors
+
+    if (isFunction(Event) && isFunction(CustomEvent)) {
+      event = new CustomEvent(type, {
+        detail: data,
+        bubbles: true,
+        cancelable: true
+      });
+    } else {
+      event = document.createEvent('CustomEvent');
+      event.initCustomEvent(type, true, true, data);
+    }
+
+    return element.dispatchEvent(event);
+  }
+  /**
+   * Get the offset base on the document.
+   * @param {Element} element - The target element.
+   * @returns {Object} The offset data.
+   */
+
+  function getOffset(element) {
+    var box = element.getBoundingClientRect();
+    return {
+      left: box.left + (window.pageXOffset - document.documentElement.clientLeft),
+      top: box.top + (window.pageYOffset - document.documentElement.clientTop)
+    };
+  }
+  var location = WINDOW.location;
+  var REGEXP_ORIGINS = /^(\w+:)\/\/([^:/?#]*):?(\d*)/i;
+  /**
+   * Check if the given URL is a cross origin URL.
+   * @param {string} url - The target URL.
+   * @returns {boolean} Returns `true` if the given URL is a cross origin URL, else `false`.
+   */
+
+  function isCrossOriginURL(url) {
+    var parts = url.match(REGEXP_ORIGINS);
+    return parts !== null && (parts[1] !== location.protocol || parts[2] !== location.hostname || parts[3] !== location.port);
+  }
+  /**
+   * Add timestamp to the given URL.
+   * @param {string} url - The target URL.
+   * @returns {string} The result URL.
+   */
+
+  function addTimestamp(url) {
+    var timestamp = "timestamp=".concat(new Date().getTime());
+    return url + (url.indexOf('?') === -1 ? '?' : '&') + timestamp;
+  }
+  /**
+   * Get transforms base on the given object.
+   * @param {Object} obj - The target object.
+   * @returns {string} A string contains transform values.
+   */
+
+  function getTransforms(_ref) {
+    var rotate = _ref.rotate,
+        scaleX = _ref.scaleX,
+        scaleY = _ref.scaleY,
+        translateX = _ref.translateX,
+        translateY = _ref.translateY;
+    var values = [];
+
+    if (isNumber(translateX) && translateX !== 0) {
+      values.push("translateX(".concat(translateX, "px)"));
+    }
+
+    if (isNumber(translateY) && translateY !== 0) {
+      values.push("translateY(".concat(translateY, "px)"));
+    } // Rotate should come first before scale to match orientation transform
+
+
+    if (isNumber(rotate) && rotate !== 0) {
+      values.push("rotate(".concat(rotate, "deg)"));
+    }
+
+    if (isNumber(scaleX) && scaleX !== 1) {
+      values.push("scaleX(".concat(scaleX, ")"));
+    }
+
+    if (isNumber(scaleY) && scaleY !== 1) {
+      values.push("scaleY(".concat(scaleY, ")"));
+    }
+
+    var transform = values.length ? values.join(' ') : 'none';
+    return {
+      WebkitTransform: transform,
+      msTransform: transform,
+      transform: transform
+    };
+  }
+  /**
+   * Get the max ratio of a group of pointers.
+   * @param {string} pointers - The target pointers.
+   * @returns {number} The result ratio.
+   */
+
+  function getMaxZoomRatio(pointers) {
+    var pointers2 = _objectSpread2({}, pointers);
+
+    var maxRatio = 0;
+    forEach(pointers, function (pointer, pointerId) {
+      delete pointers2[pointerId];
+      forEach(pointers2, function (pointer2) {
+        var x1 = Math.abs(pointer.startX - pointer2.startX);
+        var y1 = Math.abs(pointer.startY - pointer2.startY);
+        var x2 = Math.abs(pointer.endX - pointer2.endX);
+        var y2 = Math.abs(pointer.endY - pointer2.endY);
+        var z1 = Math.sqrt(x1 * x1 + y1 * y1);
+        var z2 = Math.sqrt(x2 * x2 + y2 * y2);
+        var ratio = (z2 - z1) / z1;
+
+        if (Math.abs(ratio) > Math.abs(maxRatio)) {
+          maxRatio = ratio;
+        }
+      });
+    });
+    return maxRatio;
+  }
+  /**
+   * Get a pointer from an event object.
+   * @param {Object} event - The target event object.
+   * @param {boolean} endOnly - Indicates if only returns the end point coordinate or not.
+   * @returns {Object} The result pointer contains start and/or end point coordinates.
+   */
+
+  function getPointer(_ref2, endOnly) {
+    var pageX = _ref2.pageX,
+        pageY = _ref2.pageY;
+    var end = {
+      endX: pageX,
+      endY: pageY
+    };
+    return endOnly ? end : _objectSpread2({
+      startX: pageX,
+      startY: pageY
+    }, end);
+  }
+  /**
+   * Get the center point coordinate of a group of pointers.
+   * @param {Object} pointers - The target pointers.
+   * @returns {Object} The center point coordinate.
+   */
+
+  function getPointersCenter(pointers) {
+    var pageX = 0;
+    var pageY = 0;
+    var count = 0;
+    forEach(pointers, function (_ref3) {
+      var startX = _ref3.startX,
+          startY = _ref3.startY;
+      pageX += startX;
+      pageY += startY;
+      count += 1;
+    });
+    pageX /= count;
+    pageY /= count;
+    return {
+      pageX: pageX,
+      pageY: pageY
+    };
+  }
+  /**
+   * Get the max sizes in a rectangle under the given aspect ratio.
+   * @param {Object} data - The original sizes.
+   * @param {string} [type='contain'] - The adjust type.
+   * @returns {Object} The result sizes.
+   */
+
+  function getAdjustedSizes(_ref4) // or 'cover'
+  {
+    var aspectRatio = _ref4.aspectRatio,
+        height = _ref4.height,
+        width = _ref4.width;
+    var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'contain';
+    var isValidWidth = isPositiveNumber(width);
+    var isValidHeight = isPositiveNumber(height);
+
+    if (isValidWidth && isValidHeight) {
+      var adjustedWidth = height * aspectRatio;
+
+      if (type === 'contain' && adjustedWidth > width || type === 'cover' && adjustedWidth < width) {
+        height = width / aspectRatio;
+      } else {
+        width = height * aspectRatio;
+      }
+    } else if (isValidWidth) {
+      height = width / aspectRatio;
+    } else if (isValidHeight) {
+      width = height * aspectRatio;
+    }
+
+    return {
+      width: width,
+      height: height
+    };
+  }
+  /**
+   * Get the new sizes of a rectangle after rotated.
+   * @param {Object} data - The original sizes.
+   * @returns {Object} The result sizes.
+   */
+
+  function getRotatedSizes(_ref5) {
+    var width = _ref5.width,
+        height = _ref5.height,
+        degree = _ref5.degree;
+    degree = Math.abs(degree) % 180;
+
+    if (degree === 90) {
+      return {
+        width: height,
+        height: width
+      };
+    }
+
+    var arc = degree % 90 * Math.PI / 180;
+    var sinArc = Math.sin(arc);
+    var cosArc = Math.cos(arc);
+    var newWidth = width * cosArc + height * sinArc;
+    var newHeight = width * sinArc + height * cosArc;
+    return degree > 90 ? {
+      width: newHeight,
+      height: newWidth
+    } : {
+      width: newWidth,
+      height: newHeight
+    };
+  }
+  /**
+   * Get a canvas which drew the given image.
+   * @param {HTMLImageElement} image - The image for drawing.
+   * @param {Object} imageData - The image data.
+   * @param {Object} canvasData - The canvas data.
+   * @param {Object} options - The options.
+   * @returns {HTMLCanvasElement} The result canvas.
+   */
+
+  function getSourceCanvas(image, _ref6, _ref7, _ref8) {
+    var imageAspectRatio = _ref6.aspectRatio,
+        imageNaturalWidth = _ref6.naturalWidth,
+        imageNaturalHeight = _ref6.naturalHeight,
+        _ref6$rotate = _ref6.rotate,
+        rotate = _ref6$rotate === void 0 ? 0 : _ref6$rotate,
+        _ref6$scaleX = _ref6.scaleX,
+        scaleX = _ref6$scaleX === void 0 ? 1 : _ref6$scaleX,
+        _ref6$scaleY = _ref6.scaleY,
+        scaleY = _ref6$scaleY === void 0 ? 1 : _ref6$scaleY;
+    var aspectRatio = _ref7.aspectRatio,
+        naturalWidth = _ref7.naturalWidth,
+        naturalHeight = _ref7.naturalHeight;
+    var _ref8$fillColor = _ref8.fillColor,
+        fillColor = _ref8$fillColor === void 0 ? 'transparent' : _ref8$fillColor,
+        _ref8$imageSmoothingE = _ref8.imageSmoothingEnabled,
+        imageSmoothingEnabled = _ref8$imageSmoothingE === void 0 ? true : _ref8$imageSmoothingE,
+        _ref8$imageSmoothingQ = _ref8.imageSmoothingQuality,
+        imageSmoothingQuality = _ref8$imageSmoothingQ === void 0 ? 'low' : _ref8$imageSmoothingQ,
+        _ref8$maxWidth = _ref8.maxWidth,
+        maxWidth = _ref8$maxWidth === void 0 ? Infinity : _ref8$maxWidth,
+        _ref8$maxHeight = _ref8.maxHeight,
+        maxHeight = _ref8$maxHeight === void 0 ? Infinity : _ref8$maxHeight,
+        _ref8$minWidth = _ref8.minWidth,
+        minWidth = _ref8$minWidth === void 0 ? 0 : _ref8$minWidth,
+        _ref8$minHeight = _ref8.minHeight,
+        minHeight = _ref8$minHeight === void 0 ? 0 : _ref8$minHeight;
+    var canvas = document.createElement('canvas');
+    var context = canvas.getContext('2d');
+    var maxSizes = getAdjustedSizes({
+      aspectRatio: aspectRatio,
+      width: maxWidth,
+      height: maxHeight
+    });
+    var minSizes = getAdjustedSizes({
+      aspectRatio: aspectRatio,
+      width: minWidth,
+      height: minHeight
+    }, 'cover');
+    var width = Math.min(maxSizes.width, Math.max(minSizes.width, naturalWidth));
+    var height = Math.min(maxSizes.height, Math.max(minSizes.height, naturalHeight)); // Note: should always use image's natural sizes for drawing as
+    // imageData.naturalWidth === canvasData.naturalHeight when rotate % 180 === 90
+
+    var destMaxSizes = getAdjustedSizes({
+      aspectRatio: imageAspectRatio,
+      width: maxWidth,
+      height: maxHeight
+    });
+    var destMinSizes = getAdjustedSizes({
+      aspectRatio: imageAspectRatio,
+      width: minWidth,
+      height: minHeight
+    }, 'cover');
+    var destWidth = Math.min(destMaxSizes.width, Math.max(destMinSizes.width, imageNaturalWidth));
+    var destHeight = Math.min(destMaxSizes.height, Math.max(destMinSizes.height, imageNaturalHeight));
+    var params = [-destWidth / 2, -destHeight / 2, destWidth, destHeight];
+    canvas.width = normalizeDecimalNumber(width);
+    canvas.height = normalizeDecimalNumber(height);
+    context.fillStyle = fillColor;
+    context.fillRect(0, 0, width, height);
+    context.save();
+    context.translate(width / 2, height / 2);
+    context.rotate(rotate * Math.PI / 180);
+    context.scale(scaleX, scaleY);
+    context.imageSmoothingEnabled = imageSmoothingEnabled;
+    context.imageSmoothingQuality = imageSmoothingQuality;
+    context.drawImage.apply(context, [image].concat(_toConsumableArray(params.map(function (param) {
+      return Math.floor(normalizeDecimalNumber(param));
+    }))));
+    context.restore();
+    return canvas;
+  }
+  var fromCharCode = String.fromCharCode;
+  /**
+   * Get string from char code in data view.
+   * @param {DataView} dataView - The data view for read.
+   * @param {number} start - The start index.
+   * @param {number} length - The read length.
+   * @returns {string} The read result.
+   */
+
+  function getStringFromCharCode(dataView, start, length) {
+    var str = '';
+    length += start;
+
+    for (var i = start; i < length; i += 1) {
+      str += fromCharCode(dataView.getUint8(i));
+    }
+
+    return str;
+  }
+  var REGEXP_DATA_URL_HEAD = /^data:.*,/;
+  /**
+   * Transform Data URL to array buffer.
+   * @param {string} dataURL - The Data URL to transform.
+   * @returns {ArrayBuffer} The result array buffer.
+   */
+
+  function dataURLToArrayBuffer(dataURL) {
+    var base64 = dataURL.replace(REGEXP_DATA_URL_HEAD, '');
+    var binary = atob(base64);
+    var arrayBuffer = new ArrayBuffer(binary.length);
+    var uint8 = new Uint8Array(arrayBuffer);
+    forEach(uint8, function (value, i) {
+      uint8[i] = binary.charCodeAt(i);
+    });
+    return arrayBuffer;
+  }
+  /**
+   * Transform array buffer to Data URL.
+   * @param {ArrayBuffer} arrayBuffer - The array buffer to transform.
+   * @param {string} mimeType - The mime type of the Data URL.
+   * @returns {string} The result Data URL.
+   */
+
+  function arrayBufferToDataURL(arrayBuffer, mimeType) {
+    var chunks = []; // Chunk Typed Array for better performance (#435)
+
+    var chunkSize = 8192;
+    var uint8 = new Uint8Array(arrayBuffer);
+
+    while (uint8.length > 0) {
+      // XXX: Babel's `toConsumableArray` helper will throw error in IE or Safari 9
+      // eslint-disable-next-line prefer-spread
+      chunks.push(fromCharCode.apply(null, toArray(uint8.subarray(0, chunkSize))));
+      uint8 = uint8.subarray(chunkSize);
+    }
+
+    return "data:".concat(mimeType, ";base64,").concat(btoa(chunks.join('')));
+  }
+  /**
+   * Get orientation value from given array buffer.
+   * @param {ArrayBuffer} arrayBuffer - The array buffer to read.
+   * @returns {number} The read orientation value.
+   */
+
+  function resetAndGetOrientation(arrayBuffer) {
+    var dataView = new DataView(arrayBuffer);
+    var orientation; // Ignores range error when the image does not have correct Exif information
+
+    try {
+      var littleEndian;
+      var app1Start;
+      var ifdStart; // Only handle JPEG image (start by 0xFFD8)
+
+      if (dataView.getUint8(0) === 0xFF && dataView.getUint8(1) === 0xD8) {
+        var length = dataView.byteLength;
+        var offset = 2;
+
+        while (offset + 1 < length) {
+          if (dataView.getUint8(offset) === 0xFF && dataView.getUint8(offset + 1) === 0xE1) {
+            app1Start = offset;
+            break;
+          }
+
+          offset += 1;
+        }
+      }
+
+      if (app1Start) {
+        var exifIDCode = app1Start + 4;
+        var tiffOffset = app1Start + 10;
+
+        if (getStringFromCharCode(dataView, exifIDCode, 4) === 'Exif') {
+          var endianness = dataView.getUint16(tiffOffset);
+          littleEndian = endianness === 0x4949;
+
+          if (littleEndian || endianness === 0x4D4D
+          /* bigEndian */
+          ) {
+              if (dataView.getUint16(tiffOffset + 2, littleEndian) === 0x002A) {
+                var firstIFDOffset = dataView.getUint32(tiffOffset + 4, littleEndian);
+
+                if (firstIFDOffset >= 0x00000008) {
+                  ifdStart = tiffOffset + firstIFDOffset;
+                }
+              }
+            }
+        }
+      }
+
+      if (ifdStart) {
+        var _length = dataView.getUint16(ifdStart, littleEndian);
+
+        var _offset;
+
+        var i;
+
+        for (i = 0; i < _length; i += 1) {
+          _offset = ifdStart + i * 12 + 2;
+
+          if (dataView.getUint16(_offset, littleEndian) === 0x0112
+          /* Orientation */
+          ) {
+              // 8 is the offset of the current tag's value
+              _offset += 8; // Get the original orientation value
+
+              orientation = dataView.getUint16(_offset, littleEndian); // Override the orientation with its default value
+
+              dataView.setUint16(_offset, 1, littleEndian);
+              break;
+            }
+        }
+      }
+    } catch (error) {
+      orientation = 1;
+    }
+
+    return orientation;
+  }
+  /**
+   * Parse Exif Orientation value.
+   * @param {number} orientation - The orientation to parse.
+   * @returns {Object} The parsed result.
+   */
+
+  function parseOrientation(orientation) {
+    var rotate = 0;
+    var scaleX = 1;
+    var scaleY = 1;
+
+    switch (orientation) {
+      // Flip horizontal
+      case 2:
+        scaleX = -1;
+        break;
+      // Rotate left 180°
+
+      case 3:
+        rotate = -180;
+        break;
+      // Flip vertical
+
+      case 4:
+        scaleY = -1;
+        break;
+      // Flip vertical and rotate right 90°
+
+      case 5:
+        rotate = 90;
+        scaleY = -1;
+        break;
+      // Rotate right 90°
+
+      case 6:
+        rotate = 90;
+        break;
+      // Flip horizontal and rotate right 90°
+
+      case 7:
+        rotate = 90;
+        scaleX = -1;
+        break;
+      // Rotate left 90°
+
+      case 8:
+        rotate = -90;
+        break;
+    }
+
+    return {
+      rotate: rotate,
+      scaleX: scaleX,
+      scaleY: scaleY
+    };
+  }
+
+  var render = {
+    render: function render() {
+      this.initContainer();
+      this.initCanvas();
+      this.initCropBox();
+      this.renderCanvas();
+
+      if (this.cropped) {
+        this.renderCropBox();
+      }
+    },
+    initContainer: function initContainer() {
+      var element = this.element,
+          options = this.options,
+          container = this.container,
+          cropper = this.cropper;
+      var minWidth = Number(options.minContainerWidth);
+      var minHeight = Number(options.minContainerHeight);
+      addClass(cropper, CLASS_HIDDEN);
+      removeClass(element, CLASS_HIDDEN);
+      var containerData = {
+        width: Math.max(container.offsetWidth, minWidth >= 0 ? minWidth : MIN_CONTAINER_WIDTH),
+        height: Math.max(container.offsetHeight, minHeight >= 0 ? minHeight : MIN_CONTAINER_HEIGHT)
+      };
+      this.containerData = containerData;
+      setStyle(cropper, {
+        width: containerData.width,
+        height: containerData.height
+      });
+      addClass(element, CLASS_HIDDEN);
+      removeClass(cropper, CLASS_HIDDEN);
+    },
+    // Canvas (image wrapper)
+    initCanvas: function initCanvas() {
+      var containerData = this.containerData,
+          imageData = this.imageData;
+      var viewMode = this.options.viewMode;
+      var rotated = Math.abs(imageData.rotate) % 180 === 90;
+      var naturalWidth = rotated ? imageData.naturalHeight : imageData.naturalWidth;
+      var naturalHeight = rotated ? imageData.naturalWidth : imageData.naturalHeight;
+      var aspectRatio = naturalWidth / naturalHeight;
+      var canvasWidth = containerData.width;
+      var canvasHeight = containerData.height;
+
+      if (containerData.height * aspectRatio > containerData.width) {
+        if (viewMode === 3) {
+          canvasWidth = containerData.height * aspectRatio;
+        } else {
+          canvasHeight = containerData.width / aspectRatio;
+        }
+      } else if (viewMode === 3) {
+        canvasHeight = containerData.width / aspectRatio;
+      } else {
+        canvasWidth = containerData.height * aspectRatio;
+      }
+
+      var canvasData = {
+        aspectRatio: aspectRatio,
+        naturalWidth: naturalWidth,
+        naturalHeight: naturalHeight,
+        width: canvasWidth,
+        height: canvasHeight
+      };
+      this.canvasData = canvasData;
+      this.limited = viewMode === 1 || viewMode === 2;
+      this.limitCanvas(true, true);
+      canvasData.width = Math.min(Math.max(canvasData.width, canvasData.minWidth), canvasData.maxWidth);
+      canvasData.height = Math.min(Math.max(canvasData.height, canvasData.minHeight), canvasData.maxHeight);
+      canvasData.left = (containerData.width - canvasData.width) / 2;
+      canvasData.top = (containerData.height - canvasData.height) / 2;
+      canvasData.oldLeft = canvasData.left;
+      canvasData.oldTop = canvasData.top;
+      this.initialCanvasData = assign({}, canvasData);
+    },
+    limitCanvas: function limitCanvas(sizeLimited, positionLimited) {
+      var options = this.options,
+          containerData = this.containerData,
+          canvasData = this.canvasData,
+          cropBoxData = this.cropBoxData;
+      var viewMode = options.viewMode;
+      var aspectRatio = canvasData.aspectRatio;
+      var cropped = this.cropped && cropBoxData;
+
+      if (sizeLimited) {
+        var minCanvasWidth = Number(options.minCanvasWidth) || 0;
+        var minCanvasHeight = Number(options.minCanvasHeight) || 0;
+
+        if (viewMode > 1) {
+          minCanvasWidth = Math.max(minCanvasWidth, containerData.width);
+          minCanvasHeight = Math.max(minCanvasHeight, containerData.height);
+
+          if (viewMode === 3) {
+            if (minCanvasHeight * aspectRatio > minCanvasWidth) {
+              minCanvasWidth = minCanvasHeight * aspectRatio;
+            } else {
+              minCanvasHeight = minCanvasWidth / aspectRatio;
+            }
+          }
+        } else if (viewMode > 0) {
+          if (minCanvasWidth) {
+            minCanvasWidth = Math.max(minCanvasWidth, cropped ? cropBoxData.width : 0);
+          } else if (minCanvasHeight) {
+            minCanvasHeight = Math.max(minCanvasHeight, cropped ? cropBoxData.height : 0);
+          } else if (cropped) {
+            minCanvasWidth = cropBoxData.width;
+            minCanvasHeight = cropBoxData.height;
+
+            if (minCanvasHeight * aspectRatio > minCanvasWidth) {
+              minCanvasWidth = minCanvasHeight * aspectRatio;
+            } else {
+              minCanvasHeight = minCanvasWidth / aspectRatio;
+            }
+          }
+        }
+
+        var _getAdjustedSizes = getAdjustedSizes({
+          aspectRatio: aspectRatio,
+          width: minCanvasWidth,
+          height: minCanvasHeight
+        });
+
+        minCanvasWidth = _getAdjustedSizes.width;
+        minCanvasHeight = _getAdjustedSizes.height;
+        canvasData.minWidth = minCanvasWidth;
+        canvasData.minHeight = minCanvasHeight;
+        canvasData.maxWidth = Infinity;
+        canvasData.maxHeight = Infinity;
+      }
+
+      if (positionLimited) {
+        if (viewMode > (cropped ? 0 : 1)) {
+          var newCanvasLeft = containerData.width - canvasData.width;
+          var newCanvasTop = containerData.height - canvasData.height;
+          canvasData.minLeft = Math.min(0, newCanvasLeft);
+          canvasData.minTop = Math.min(0, newCanvasTop);
+          canvasData.maxLeft = Math.max(0, newCanvasLeft);
+          canvasData.maxTop = Math.max(0, newCanvasTop);
+
+          if (cropped && this.limited) {
+            canvasData.minLeft = Math.min(cropBoxData.left, cropBoxData.left + (cropBoxData.width - canvasData.width));
+            canvasData.minTop = Math.min(cropBoxData.top, cropBoxData.top + (cropBoxData.height - canvasData.height));
+            canvasData.maxLeft = cropBoxData.left;
+            canvasData.maxTop = cropBoxData.top;
+
+            if (viewMode === 2) {
+              if (canvasData.width >= containerData.width) {
+                canvasData.minLeft = Math.min(0, newCanvasLeft);
+                canvasData.maxLeft = Math.max(0, newCanvasLeft);
+              }
+
+              if (canvasData.height >= containerData.height) {
+                canvasData.minTop = Math.min(0, newCanvasTop);
+                canvasData.maxTop = Math.max(0, newCanvasTop);
+              }
+            }
+          }
+        } else {
+          canvasData.minLeft = -canvasData.width;
+          canvasData.minTop = -canvasData.height;
+          canvasData.maxLeft = containerData.width;
+          canvasData.maxTop = containerData.height;
+        }
+      }
+    },
+    renderCanvas: function renderCanvas(changed, transformed) {
+      var canvasData = this.canvasData,
+          imageData = this.imageData;
+
+      if (transformed) {
+        var _getRotatedSizes = getRotatedSizes({
+          width: imageData.naturalWidth * Math.abs(imageData.scaleX || 1),
+          height: imageData.naturalHeight * Math.abs(imageData.scaleY || 1),
+          degree: imageData.rotate || 0
+        }),
+            naturalWidth = _getRotatedSizes.width,
+            naturalHeight = _getRotatedSizes.height;
+
+        var width = canvasData.width * (naturalWidth / canvasData.naturalWidth);
+        var height = canvasData.height * (naturalHeight / canvasData.naturalHeight);
+        canvasData.left -= (width - canvasData.width) / 2;
+        canvasData.top -= (height - canvasData.height) / 2;
+        canvasData.width = width;
+        canvasData.height = height;
+        canvasData.aspectRatio = naturalWidth / naturalHeight;
+        canvasData.naturalWidth = naturalWidth;
+        canvasData.naturalHeight = naturalHeight;
+        this.limitCanvas(true, false);
+      }
+
+      if (canvasData.width > canvasData.maxWidth || canvasData.width < canvasData.minWidth) {
+        canvasData.left = canvasData.oldLeft;
+      }
+
+      if (canvasData.height > canvasData.maxHeight || canvasData.height < canvasData.minHeight) {
+        canvasData.top = canvasData.oldTop;
+      }
+
+      canvasData.width = Math.min(Math.max(canvasData.width, canvasData.minWidth), canvasData.maxWidth);
+      canvasData.height = Math.min(Math.max(canvasData.height, canvasData.minHeight), canvasData.maxHeight);
+      this.limitCanvas(false, true);
+      canvasData.left = Math.min(Math.max(canvasData.left, canvasData.minLeft), canvasData.maxLeft);
+      canvasData.top = Math.min(Math.max(canvasData.top, canvasData.minTop), canvasData.maxTop);
+      canvasData.oldLeft = canvasData.left;
+      canvasData.oldTop = canvasData.top;
+      setStyle(this.canvas, assign({
+        width: canvasData.width,
+        height: canvasData.height
+      }, getTransforms({
+        translateX: canvasData.left,
+        translateY: canvasData.top
+      })));
+      this.renderImage(changed);
+
+      if (this.cropped && this.limited) {
+        this.limitCropBox(true, true);
+      }
+    },
+    renderImage: function renderImage(changed) {
+      var canvasData = this.canvasData,
+          imageData = this.imageData;
+      var width = imageData.naturalWidth * (canvasData.width / canvasData.naturalWidth);
+      var height = imageData.naturalHeight * (canvasData.height / canvasData.naturalHeight);
+      assign(imageData, {
+        width: width,
+        height: height,
+        left: (canvasData.width - width) / 2,
+        top: (canvasData.height - height) / 2
+      });
+      setStyle(this.image, assign({
+        width: imageData.width,
+        height: imageData.height
+      }, getTransforms(assign({
+        translateX: imageData.left,
+        translateY: imageData.top
+      }, imageData))));
+
+      if (changed) {
+        this.output();
+      }
+    },
+    initCropBox: function initCropBox() {
+      var options = this.options,
+          canvasData = this.canvasData;
+      var aspectRatio = options.aspectRatio || options.initialAspectRatio;
+      var autoCropArea = Number(options.autoCropArea) || 0.8;
+      var cropBoxData = {
+        width: canvasData.width,
+        height: canvasData.height
+      };
+
+      if (aspectRatio) {
+        if (canvasData.height * aspectRatio > canvasData.width) {
+          cropBoxData.height = cropBoxData.width / aspectRatio;
+        } else {
+          cropBoxData.width = cropBoxData.height * aspectRatio;
+        }
+      }
+
+      this.cropBoxData = cropBoxData;
+      this.limitCropBox(true, true); // Initialize auto crop area
+
+      cropBoxData.width = Math.min(Math.max(cropBoxData.width, cropBoxData.minWidth), cropBoxData.maxWidth);
+      cropBoxData.height = Math.min(Math.max(cropBoxData.height, cropBoxData.minHeight), cropBoxData.maxHeight); // The width/height of auto crop area must large than "minWidth/Height"
+
+      cropBoxData.width = Math.max(cropBoxData.minWidth, cropBoxData.width * autoCropArea);
+      cropBoxData.height = Math.max(cropBoxData.minHeight, cropBoxData.height * autoCropArea);
+      cropBoxData.left = canvasData.left + (canvasData.width - cropBoxData.width) / 2;
+      cropBoxData.top = canvasData.top + (canvasData.height - cropBoxData.height) / 2;
+      cropBoxData.oldLeft = cropBoxData.left;
+      cropBoxData.oldTop = cropBoxData.top;
+      this.initialCropBoxData = assign({}, cropBoxData);
+    },
+    limitCropBox: function limitCropBox(sizeLimited, positionLimited) {
+      var options = this.options,
+          containerData = this.containerData,
+          canvasData = this.canvasData,
+          cropBoxData = this.cropBoxData,
+          limited = this.limited;
+      var aspectRatio = options.aspectRatio;
+
+      if (sizeLimited) {
+        var minCropBoxWidth = Number(options.minCropBoxWidth) || 0;
+        var minCropBoxHeight = Number(options.minCropBoxHeight) || 0;
+        var maxCropBoxWidth = limited ? Math.min(containerData.width, canvasData.width, canvasData.width + canvasData.left, containerData.width - canvasData.left) : containerData.width;
+        var maxCropBoxHeight = limited ? Math.min(containerData.height, canvasData.height, canvasData.height + canvasData.top, containerData.height - canvasData.top) : containerData.height; // The min/maxCropBoxWidth/Height must be less than container's width/height
+
+        minCropBoxWidth = Math.min(minCropBoxWidth, containerData.width);
+        minCropBoxHeight = Math.min(minCropBoxHeight, containerData.height);
+
+        if (aspectRatio) {
+          if (minCropBoxWidth && minCropBoxHeight) {
+            if (minCropBoxHeight * aspectRatio > minCropBoxWidth) {
+              minCropBoxHeight = minCropBoxWidth / aspectRatio;
+            } else {
+              minCropBoxWidth = minCropBoxHeight * aspectRatio;
+            }
+          } else if (minCropBoxWidth) {
+            minCropBoxHeight = minCropBoxWidth / aspectRatio;
+          } else if (minCropBoxHeight) {
+            minCropBoxWidth = minCropBoxHeight * aspectRatio;
+          }
+
+          if (maxCropBoxHeight * aspectRatio > maxCropBoxWidth) {
+            maxCropBoxHeight = maxCropBoxWidth / aspectRatio;
+          } else {
+            maxCropBoxWidth = maxCropBoxHeight * aspectRatio;
+          }
+        } // The minWidth/Height must be less than maxWidth/Height
+
+
+        cropBoxData.minWidth = Math.min(minCropBoxWidth, maxCropBoxWidth);
+        cropBoxData.minHeight = Math.min(minCropBoxHeight, maxCropBoxHeight);
+        cropBoxData.maxWidth = maxCropBoxWidth;
+        cropBoxData.maxHeight = maxCropBoxHeight;
+      }
+
+      if (positionLimited) {
+        if (limited) {
+          cropBoxData.minLeft = Math.max(0, canvasData.left);
+          cropBoxData.minTop = Math.max(0, canvasData.top);
+          cropBoxData.maxLeft = Math.min(containerData.width, canvasData.left + canvasData.width) - cropBoxData.width;
+          cropBoxData.maxTop = Math.min(containerData.height, canvasData.top + canvasData.height) - cropBoxData.height;
+        } else {
+          cropBoxData.minLeft = 0;
+          cropBoxData.minTop = 0;
+          cropBoxData.maxLeft = containerData.width - cropBoxData.width;
+          cropBoxData.maxTop = containerData.height - cropBoxData.height;
+        }
+      }
+    },
+    renderCropBox: function renderCropBox() {
+      var options = this.options,
+          containerData = this.containerData,
+          cropBoxData = this.cropBoxData;
+
+      if (cropBoxData.width > cropBoxData.maxWidth || cropBoxData.width < cropBoxData.minWidth) {
+        cropBoxData.left = cropBoxData.oldLeft;
+      }
+
+      if (cropBoxData.height > cropBoxData.maxHeight || cropBoxData.height < cropBoxData.minHeight) {
+        cropBoxData.top = cropBoxData.oldTop;
+      }
+
+      cropBoxData.width = Math.min(Math.max(cropBoxData.width, cropBoxData.minWidth), cropBoxData.maxWidth);
+      cropBoxData.height = Math.min(Math.max(cropBoxData.height, cropBoxData.minHeight), cropBoxData.maxHeight);
+      this.limitCropBox(false, true);
+      cropBoxData.left = Math.min(Math.max(cropBoxData.left, cropBoxData.minLeft), cropBoxData.maxLeft);
+      cropBoxData.top = Math.min(Math.max(cropBoxData.top, cropBoxData.minTop), cropBoxData.maxTop);
+      cropBoxData.oldLeft = cropBoxData.left;
+      cropBoxData.oldTop = cropBoxData.top;
+
+      if (options.movable && options.cropBoxMovable) {
+        // Turn to move the canvas when the crop box is equal to the container
+        setData(this.face, DATA_ACTION, cropBoxData.width >= containerData.width && cropBoxData.height >= containerData.height ? ACTION_MOVE : ACTION_ALL);
+      }
+
+      setStyle(this.cropBox, assign({
+        width: cropBoxData.width,
+        height: cropBoxData.height
+      }, getTransforms({
+        translateX: cropBoxData.left,
+        translateY: cropBoxData.top
+      })));
+
+      if (this.cropped && this.limited) {
+        this.limitCanvas(true, true);
+      }
+
+      if (!this.disabled) {
+        this.output();
+      }
+    },
+    output: function output() {
+      this.preview();
+      dispatchEvent(this.element, EVENT_CROP, this.getData());
+    }
+  };
+
+  var preview = {
+    initPreview: function initPreview() {
+      var element = this.element,
+          crossOrigin = this.crossOrigin;
+      var preview = this.options.preview;
+      var url = crossOrigin ? this.crossOriginUrl : this.url;
+      var alt = element.alt || 'The image to preview';
+      var image = document.createElement('img');
+
+      if (crossOrigin) {
+        image.crossOrigin = crossOrigin;
+      }
+
+      image.src = url;
+      image.alt = alt;
+      this.viewBox.appendChild(image);
+      this.viewBoxImage = image;
+
+      if (!preview) {
+        return;
+      }
+
+      var previews = preview;
+
+      if (typeof preview === 'string') {
+        previews = element.ownerDocument.querySelectorAll(preview);
+      } else if (preview.querySelector) {
+        previews = [preview];
+      }
+
+      this.previews = previews;
+      forEach(previews, function (el) {
+        var img = document.createElement('img'); // Save the original size for recover
+
+        setData(el, DATA_PREVIEW, {
+          width: el.offsetWidth,
+          height: el.offsetHeight,
+          html: el.innerHTML
+        });
+
+        if (crossOrigin) {
+          img.crossOrigin = crossOrigin;
+        }
+
+        img.src = url;
+        img.alt = alt;
+        /**
+         * Override img element styles
+         * Add `display:block` to avoid margin top issue
+         * Add `height:auto` to override `height` attribute on IE8
+         * (Occur only when margin-top <= -height)
+         */
+
+        img.style.cssText = 'display:block;' + 'width:100%;' + 'height:auto;' + 'min-width:0!important;' + 'min-height:0!important;' + 'max-width:none!important;' + 'max-height:none!important;' + 'image-orientation:0deg!important;"';
+        el.innerHTML = '';
+        el.appendChild(img);
+      });
+    },
+    resetPreview: function resetPreview() {
+      forEach(this.previews, function (element) {
+        var data = getData(element, DATA_PREVIEW);
+        setStyle(element, {
+          width: data.width,
+          height: data.height
+        });
+        element.innerHTML = data.html;
+        removeData(element, DATA_PREVIEW);
+      });
+    },
+    preview: function preview() {
+      var imageData = this.imageData,
+          canvasData = this.canvasData,
+          cropBoxData = this.cropBoxData;
+      var cropBoxWidth = cropBoxData.width,
+          cropBoxHeight = cropBoxData.height;
+      var width = imageData.width,
+          height = imageData.height;
+      var left = cropBoxData.left - canvasData.left - imageData.left;
+      var top = cropBoxData.top - canvasData.top - imageData.top;
+
+      if (!this.cropped || this.disabled) {
+        return;
+      }
+
+      setStyle(this.viewBoxImage, assign({
+        width: width,
+        height: height
+      }, getTransforms(assign({
+        translateX: -left,
+        translateY: -top
+      }, imageData))));
+      forEach(this.previews, function (element) {
+        var data = getData(element, DATA_PREVIEW);
+        var originalWidth = data.width;
+        var originalHeight = data.height;
+        var newWidth = originalWidth;
+        var newHeight = originalHeight;
+        var ratio = 1;
+
+        if (cropBoxWidth) {
+          ratio = originalWidth / cropBoxWidth;
+          newHeight = cropBoxHeight * ratio;
+        }
+
+        if (cropBoxHeight && newHeight > originalHeight) {
+          ratio = originalHeight / cropBoxHeight;
+          newWidth = cropBoxWidth * ratio;
+          newHeight = originalHeight;
+        }
+
+        setStyle(element, {
+          width: newWidth,
+          height: newHeight
+        });
+        setStyle(element.getElementsByTagName('img')[0], assign({
+          width: width * ratio,
+          height: height * ratio
+        }, getTransforms(assign({
+          translateX: -left * ratio,
+          translateY: -top * ratio
+        }, imageData))));
+      });
+    }
+  };
+
+  var events = {
+    bind: function bind() {
+      var element = this.element,
+          options = this.options,
+          cropper = this.cropper;
+
+      if (isFunction(options.cropstart)) {
+        addListener(element, EVENT_CROP_START, options.cropstart);
+      }
+
+      if (isFunction(options.cropmove)) {
+        addListener(element, EVENT_CROP_MOVE, options.cropmove);
+      }
+
+      if (isFunction(options.cropend)) {
+        addListener(element, EVENT_CROP_END, options.cropend);
+      }
+
+      if (isFunction(options.crop)) {
+        addListener(element, EVENT_CROP, options.crop);
+      }
+
+      if (isFunction(options.zoom)) {
+        addListener(element, EVENT_ZOOM, options.zoom);
+      }
+
+      addListener(cropper, EVENT_POINTER_DOWN, this.onCropStart = this.cropStart.bind(this));
+
+      if (options.zoomable && options.zoomOnWheel) {
+        addListener(cropper, EVENT_WHEEL, this.onWheel = this.wheel.bind(this), {
+          passive: false,
+          capture: true
+        });
+      }
+
+      if (options.toggleDragModeOnDblclick) {
+        addListener(cropper, EVENT_DBLCLICK, this.onDblclick = this.dblclick.bind(this));
+      }
+
+      addListener(element.ownerDocument, EVENT_POINTER_MOVE, this.onCropMove = this.cropMove.bind(this));
+      addListener(element.ownerDocument, EVENT_POINTER_UP, this.onCropEnd = this.cropEnd.bind(this));
+
+      if (options.responsive) {
+        addListener(window, EVENT_RESIZE, this.onResize = this.resize.bind(this));
+      }
+    },
+    unbind: function unbind() {
+      var element = this.element,
+          options = this.options,
+          cropper = this.cropper;
+
+      if (isFunction(options.cropstart)) {
+        removeListener(element, EVENT_CROP_START, options.cropstart);
+      }
+
+      if (isFunction(options.cropmove)) {
+        removeListener(element, EVENT_CROP_MOVE, options.cropmove);
+      }
+
+      if (isFunction(options.cropend)) {
+        removeListener(element, EVENT_CROP_END, options.cropend);
+      }
+
+      if (isFunction(options.crop)) {
+        removeListener(element, EVENT_CROP, options.crop);
+      }
+
+      if (isFunction(options.zoom)) {
+        removeListener(element, EVENT_ZOOM, options.zoom);
+      }
+
+      removeListener(cropper, EVENT_POINTER_DOWN, this.onCropStart);
+
+      if (options.zoomable && options.zoomOnWheel) {
+        removeListener(cropper, EVENT_WHEEL, this.onWheel, {
+          passive: false,
+          capture: true
+        });
+      }
+
+      if (options.toggleDragModeOnDblclick) {
+        removeListener(cropper, EVENT_DBLCLICK, this.onDblclick);
+      }
+
+      removeListener(element.ownerDocument, EVENT_POINTER_MOVE, this.onCropMove);
+      removeListener(element.ownerDocument, EVENT_POINTER_UP, this.onCropEnd);
+
+      if (options.responsive) {
+        removeListener(window, EVENT_RESIZE, this.onResize);
+      }
+    }
+  };
+
+  var handlers = {
+    resize: function resize() {
+      if (this.disabled) {
+        return;
+      }
+
+      var options = this.options,
+          container = this.container,
+          containerData = this.containerData;
+      var ratioX = container.offsetWidth / containerData.width;
+      var ratioY = container.offsetHeight / containerData.height;
+      var ratio = Math.abs(ratioX - 1) > Math.abs(ratioY - 1) ? ratioX : ratioY; // Resize when width changed or height changed
+
+      if (ratio !== 1) {
+        var canvasData;
+        var cropBoxData;
+
+        if (options.restore) {
+          canvasData = this.getCanvasData();
+          cropBoxData = this.getCropBoxData();
+        }
+
+        this.render();
+
+        if (options.restore) {
+          this.setCanvasData(forEach(canvasData, function (n, i) {
+            canvasData[i] = n * ratio;
+          }));
+          this.setCropBoxData(forEach(cropBoxData, function (n, i) {
+            cropBoxData[i] = n * ratio;
+          }));
+        }
+      }
+    },
+    dblclick: function dblclick() {
+      if (this.disabled || this.options.dragMode === DRAG_MODE_NONE) {
+        return;
+      }
+
+      this.setDragMode(hasClass(this.dragBox, CLASS_CROP) ? DRAG_MODE_MOVE : DRAG_MODE_CROP);
+    },
+    wheel: function wheel(event) {
+      var _this = this;
+
+      var ratio = Number(this.options.wheelZoomRatio) || 0.1;
+      var delta = 1;
+
+      if (this.disabled) {
+        return;
+      }
+
+      event.preventDefault(); // Limit wheel speed to prevent zoom too fast (#21)
+
+      if (this.wheeling) {
+        return;
+      }
+
+      this.wheeling = true;
+      setTimeout(function () {
+        _this.wheeling = false;
+      }, 50);
+
+      if (event.deltaY) {
+        delta = event.deltaY > 0 ? 1 : -1;
+      } else if (event.wheelDelta) {
+        delta = -event.wheelDelta / 120;
+      } else if (event.detail) {
+        delta = event.detail > 0 ? 1 : -1;
+      }
+
+      this.zoom(-delta * ratio, event);
+    },
+    cropStart: function cropStart(event) {
+      var buttons = event.buttons,
+          button = event.button;
+
+      if (this.disabled // Handle mouse event and pointer event and ignore touch event
+      || (event.type === 'mousedown' || event.type === 'pointerdown' && event.pointerType === 'mouse') && ( // No primary button (Usually the left button)
+      isNumber(buttons) && buttons !== 1 || isNumber(button) && button !== 0 // Open context menu
+      || event.ctrlKey)) {
+        return;
+      }
+
+      var options = this.options,
+          pointers = this.pointers;
+      var action;
+
+      if (event.changedTouches) {
+        // Handle touch event
+        forEach(event.changedTouches, function (touch) {
+          pointers[touch.identifier] = getPointer(touch);
+        });
+      } else {
+        // Handle mouse event and pointer event
+        pointers[event.pointerId || 0] = getPointer(event);
+      }
+
+      if (Object.keys(pointers).length > 1 && options.zoomable && options.zoomOnTouch) {
+        action = ACTION_ZOOM;
+      } else {
+        action = getData(event.target, DATA_ACTION);
+      }
+
+      if (!REGEXP_ACTIONS.test(action)) {
+        return;
+      }
+
+      if (dispatchEvent(this.element, EVENT_CROP_START, {
+        originalEvent: event,
+        action: action
+      }) === false) {
+        return;
+      } // This line is required for preventing page zooming in iOS browsers
+
+
+      event.preventDefault();
+      this.action = action;
+      this.cropping = false;
+
+      if (action === ACTION_CROP) {
+        this.cropping = true;
+        addClass(this.dragBox, CLASS_MODAL);
+      }
+    },
+    cropMove: function cropMove(event) {
+      var action = this.action;
+
+      if (this.disabled || !action) {
+        return;
+      }
+
+      var pointers = this.pointers;
+      event.preventDefault();
+
+      if (dispatchEvent(this.element, EVENT_CROP_MOVE, {
+        originalEvent: event,
+        action: action
+      }) === false) {
+        return;
+      }
+
+      if (event.changedTouches) {
+        forEach(event.changedTouches, function (touch) {
+          // The first parameter should not be undefined (#432)
+          assign(pointers[touch.identifier] || {}, getPointer(touch, true));
+        });
+      } else {
+        assign(pointers[event.pointerId || 0] || {}, getPointer(event, true));
+      }
+
+      this.change(event);
+    },
+    cropEnd: function cropEnd(event) {
+      if (this.disabled) {
+        return;
+      }
+
+      var action = this.action,
+          pointers = this.pointers;
+
+      if (event.changedTouches) {
+        forEach(event.changedTouches, function (touch) {
+          delete pointers[touch.identifier];
+        });
+      } else {
+        delete pointers[event.pointerId || 0];
+      }
+
+      if (!action) {
+        return;
+      }
+
+      event.preventDefault();
+
+      if (!Object.keys(pointers).length) {
+        this.action = '';
+      }
+
+      if (this.cropping) {
+        this.cropping = false;
+        toggleClass(this.dragBox, CLASS_MODAL, this.cropped && this.options.modal);
+      }
+
+      dispatchEvent(this.element, EVENT_CROP_END, {
+        originalEvent: event,
+        action: action
+      });
+    }
+  };
+
+  var change = {
+    change: function change(event) {
+      var options = this.options,
+          canvasData = this.canvasData,
+          containerData = this.containerData,
+          cropBoxData = this.cropBoxData,
+          pointers = this.pointers;
+      var action = this.action;
+      var aspectRatio = options.aspectRatio;
+      var left = cropBoxData.left,
+          top = cropBoxData.top,
+          width = cropBoxData.width,
+          height = cropBoxData.height;
+      var right = left + width;
+      var bottom = top + height;
+      var minLeft = 0;
+      var minTop = 0;
+      var maxWidth = containerData.width;
+      var maxHeight = containerData.height;
+      var renderable = true;
+      var offset; // Locking aspect ratio in "free mode" by holding shift key
+
+      if (!aspectRatio && event.shiftKey) {
+        aspectRatio = width && height ? width / height : 1;
+      }
+
+      if (this.limited) {
+        minLeft = cropBoxData.minLeft;
+        minTop = cropBoxData.minTop;
+        maxWidth = minLeft + Math.min(containerData.width, canvasData.width, canvasData.left + canvasData.width);
+        maxHeight = minTop + Math.min(containerData.height, canvasData.height, canvasData.top + canvasData.height);
+      }
+
+      var pointer = pointers[Object.keys(pointers)[0]];
+      var range = {
+        x: pointer.endX - pointer.startX,
+        y: pointer.endY - pointer.startY
+      };
+
+      var check = function check(side) {
+        switch (side) {
+          case ACTION_EAST:
+            if (right + range.x > maxWidth) {
+              range.x = maxWidth - right;
+            }
+
+            break;
+
+          case ACTION_WEST:
+            if (left + range.x < minLeft) {
+              range.x = minLeft - left;
+            }
+
+            break;
+
+          case ACTION_NORTH:
+            if (top + range.y < minTop) {
+              range.y = minTop - top;
+            }
+
+            break;
+
+          case ACTION_SOUTH:
+            if (bottom + range.y > maxHeight) {
+              range.y = maxHeight - bottom;
+            }
+
+            break;
+        }
+      };
+
+      switch (action) {
+        // Move crop box
+        case ACTION_ALL:
+          left += range.x;
+          top += range.y;
+          break;
+        // Resize crop box
+
+        case ACTION_EAST:
+          if (range.x >= 0 && (right >= maxWidth || aspectRatio && (top <= minTop || bottom >= maxHeight))) {
+            renderable = false;
+            break;
+          }
+
+          check(ACTION_EAST);
+          width += range.x;
+
+          if (width < 0) {
+            action = ACTION_WEST;
+            width = -width;
+            left -= width;
+          }
+
+          if (aspectRatio) {
+            height = width / aspectRatio;
+            top += (cropBoxData.height - height) / 2;
+          }
+
+          break;
+
+        case ACTION_NORTH:
+          if (range.y <= 0 && (top <= minTop || aspectRatio && (left <= minLeft || right >= maxWidth))) {
+            renderable = false;
+            break;
+          }
+
+          check(ACTION_NORTH);
+          height -= range.y;
+          top += range.y;
+
+          if (height < 0) {
+            action = ACTION_SOUTH;
+            height = -height;
+            top -= height;
+          }
+
+          if (aspectRatio) {
+            width = height * aspectRatio;
+            left += (cropBoxData.width - width) / 2;
+          }
+
+          break;
+
+        case ACTION_WEST:
+          if (range.x <= 0 && (left <= minLeft || aspectRatio && (top <= minTop || bottom >= maxHeight))) {
+            renderable = false;
+            break;
+          }
+
+          check(ACTION_WEST);
+          width -= range.x;
+          left += range.x;
+
+          if (width < 0) {
+            action = ACTION_EAST;
+            width = -width;
+            left -= width;
+          }
+
+          if (aspectRatio) {
+            height = width / aspectRatio;
+            top += (cropBoxData.height - height) / 2;
+          }
+
+          break;
+
+        case ACTION_SOUTH:
+          if (range.y >= 0 && (bottom >= maxHeight || aspectRatio && (left <= minLeft || right >= maxWidth))) {
+            renderable = false;
+            break;
+          }
+
+          check(ACTION_SOUTH);
+          height += range.y;
+
+          if (height < 0) {
+            action = ACTION_NORTH;
+            height = -height;
+            top -= height;
+          }
+
+          if (aspectRatio) {
+            width = height * aspectRatio;
+            left += (cropBoxData.width - width) / 2;
+          }
+
+          break;
+
+        case ACTION_NORTH_EAST:
+          if (aspectRatio) {
+            if (range.y <= 0 && (top <= minTop || right >= maxWidth)) {
+              renderable = false;
+              break;
+            }
+
+            check(ACTION_NORTH);
+            height -= range.y;
+            top += range.y;
+            width = height * aspectRatio;
+          } else {
+            check(ACTION_NORTH);
+            check(ACTION_EAST);
+
+            if (range.x >= 0) {
+              if (right < maxWidth) {
+                width += range.x;
+              } else if (range.y <= 0 && top <= minTop) {
+                renderable = false;
+              }
+            } else {
+              width += range.x;
+            }
+
+            if (range.y <= 0) {
+              if (top > minTop) {
+                height -= range.y;
+                top += range.y;
+              }
+            } else {
+              height -= range.y;
+              top += range.y;
+            }
+          }
+
+          if (width < 0 && height < 0) {
+            action = ACTION_SOUTH_WEST;
+            height = -height;
+            width = -width;
+            top -= height;
+            left -= width;
+          } else if (width < 0) {
+            action = ACTION_NORTH_WEST;
+            width = -width;
+            left -= width;
+          } else if (height < 0) {
+            action = ACTION_SOUTH_EAST;
+            height = -height;
+            top -= height;
+          }
+
+          break;
+
+        case ACTION_NORTH_WEST:
+          if (aspectRatio) {
+            if (range.y <= 0 && (top <= minTop || left <= minLeft)) {
+              renderable = false;
+              break;
+            }
+
+            check(ACTION_NORTH);
+            height -= range.y;
+            top += range.y;
+            width = height * aspectRatio;
+            left += cropBoxData.width - width;
+          } else {
+            check(ACTION_NORTH);
+            check(ACTION_WEST);
+
+            if (range.x <= 0) {
+              if (left > minLeft) {
+                width -= range.x;
+                left += range.x;
+              } else if (range.y <= 0 && top <= minTop) {
+                renderable = false;
+              }
+            } else {
+              width -= range.x;
+              left += range.x;
+            }
+
+            if (range.y <= 0) {
+              if (top > minTop) {
+                height -= range.y;
+                top += range.y;
+              }
+            } else {
+              height -= range.y;
+              top += range.y;
+            }
+          }
+
+          if (width < 0 && height < 0) {
+            action = ACTION_SOUTH_EAST;
+            height = -height;
+            width = -width;
+            top -= height;
+            left -= width;
+          } else if (width < 0) {
+            action = ACTION_NORTH_EAST;
+            width = -width;
+            left -= width;
+          } else if (height < 0) {
+            action = ACTION_SOUTH_WEST;
+            height = -height;
+            top -= height;
+          }
+
+          break;
+
+        case ACTION_SOUTH_WEST:
+          if (aspectRatio) {
+            if (range.x <= 0 && (left <= minLeft || bottom >= maxHeight)) {
+              renderable = false;
+              break;
+            }
+
+            check(ACTION_WEST);
+            width -= range.x;
+            left += range.x;
+            height = width / aspectRatio;
+          } else {
+            check(ACTION_SOUTH);
+            check(ACTION_WEST);
+
+            if (range.x <= 0) {
+              if (left > minLeft) {
+                width -= range.x;
+                left += range.x;
+              } else if (range.y >= 0 && bottom >= maxHeight) {
+                renderable = false;
+              }
+            } else {
+              width -= range.x;
+              left += range.x;
+            }
+
+            if (range.y >= 0) {
+              if (bottom < maxHeight) {
+                height += range.y;
+              }
+            } else {
+              height += range.y;
+            }
+          }
+
+          if (width < 0 && height < 0) {
+            action = ACTION_NORTH_EAST;
+            height = -height;
+            width = -width;
+            top -= height;
+            left -= width;
+          } else if (width < 0) {
+            action = ACTION_SOUTH_EAST;
+            width = -width;
+            left -= width;
+          } else if (height < 0) {
+            action = ACTION_NORTH_WEST;
+            height = -height;
+            top -= height;
+          }
+
+          break;
+
+        case ACTION_SOUTH_EAST:
+          if (aspectRatio) {
+            if (range.x >= 0 && (right >= maxWidth || bottom >= maxHeight)) {
+              renderable = false;
+              break;
+            }
+
+            check(ACTION_EAST);
+            width += range.x;
+            height = width / aspectRatio;
+          } else {
+            check(ACTION_SOUTH);
+            check(ACTION_EAST);
+
+            if (range.x >= 0) {
+              if (right < maxWidth) {
+                width += range.x;
+              } else if (range.y >= 0 && bottom >= maxHeight) {
+                renderable = false;
+              }
+            } else {
+              width += range.x;
+            }
+
+            if (range.y >= 0) {
+              if (bottom < maxHeight) {
+                height += range.y;
+              }
+            } else {
+              height += range.y;
+            }
+          }
+
+          if (width < 0 && height < 0) {
+            action = ACTION_NORTH_WEST;
+            height = -height;
+            width = -width;
+            top -= height;
+            left -= width;
+          } else if (width < 0) {
+            action = ACTION_SOUTH_WEST;
+            width = -width;
+            left -= width;
+          } else if (height < 0) {
+            action = ACTION_NORTH_EAST;
+            height = -height;
+            top -= height;
+          }
+
+          break;
+        // Move canvas
+
+        case ACTION_MOVE:
+          this.move(range.x, range.y);
+          renderable = false;
+          break;
+        // Zoom canvas
+
+        case ACTION_ZOOM:
+          this.zoom(getMaxZoomRatio(pointers), event);
+          renderable = false;
+          break;
+        // Create crop box
+
+        case ACTION_CROP:
+          if (!range.x || !range.y) {
+            renderable = false;
+            break;
+          }
+
+          offset = getOffset(this.cropper);
+          left = pointer.startX - offset.left;
+          top = pointer.startY - offset.top;
+          width = cropBoxData.minWidth;
+          height = cropBoxData.minHeight;
+
+          if (range.x > 0) {
+            action = range.y > 0 ? ACTION_SOUTH_EAST : ACTION_NORTH_EAST;
+          } else if (range.x < 0) {
+            left -= width;
+            action = range.y > 0 ? ACTION_SOUTH_WEST : ACTION_NORTH_WEST;
+          }
+
+          if (range.y < 0) {
+            top -= height;
+          } // Show the crop box if is hidden
+
+
+          if (!this.cropped) {
+            removeClass(this.cropBox, CLASS_HIDDEN);
+            this.cropped = true;
+
+            if (this.limited) {
+              this.limitCropBox(true, true);
+            }
+          }
+
+          break;
+      }
+
+      if (renderable) {
+        cropBoxData.width = width;
+        cropBoxData.height = height;
+        cropBoxData.left = left;
+        cropBoxData.top = top;
+        this.action = action;
+        this.renderCropBox();
+      } // Override
+
+
+      forEach(pointers, function (p) {
+        p.startX = p.endX;
+        p.startY = p.endY;
+      });
+    }
+  };
+
+  var methods = {
+    // Show the crop box manually
+    crop: function crop() {
+      if (this.ready && !this.cropped && !this.disabled) {
+        this.cropped = true;
+        this.limitCropBox(true, true);
+
+        if (this.options.modal) {
+          addClass(this.dragBox, CLASS_MODAL);
+        }
+
+        removeClass(this.cropBox, CLASS_HIDDEN);
+        this.setCropBoxData(this.initialCropBoxData);
+      }
+
+      return this;
+    },
+    // Reset the image and crop box to their initial states
+    reset: function reset() {
+      if (this.ready && !this.disabled) {
+        this.imageData = assign({}, this.initialImageData);
+        this.canvasData = assign({}, this.initialCanvasData);
+        this.cropBoxData = assign({}, this.initialCropBoxData);
+        this.renderCanvas();
+
+        if (this.cropped) {
+          this.renderCropBox();
+        }
+      }
+
+      return this;
+    },
+    // Clear the crop box
+    clear: function clear() {
+      if (this.cropped && !this.disabled) {
+        assign(this.cropBoxData, {
+          left: 0,
+          top: 0,
+          width: 0,
+          height: 0
+        });
+        this.cropped = false;
+        this.renderCropBox();
+        this.limitCanvas(true, true); // Render canvas after crop box rendered
+
+        this.renderCanvas();
+        removeClass(this.dragBox, CLASS_MODAL);
+        addClass(this.cropBox, CLASS_HIDDEN);
+      }
+
+      return this;
+    },
+
+    /**
+     * Replace the image's src and rebuild the cropper
+     * @param {string} url - The new URL.
+     * @param {boolean} [hasSameSize] - Indicate if the new image has the same size as the old one.
+     * @returns {Cropper} this
+     */
+    replace: function replace(url) {
+      var hasSameSize = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
+
+      if (!this.disabled && url) {
+        if (this.isImg) {
+          this.element.src = url;
+        }
+
+        if (hasSameSize) {
+          this.url = url;
+          this.image.src = url;
+
+          if (this.ready) {
+            this.viewBoxImage.src = url;
+            forEach(this.previews, function (element) {
+              element.getElementsByTagName('img')[0].src = url;
+            });
+          }
+        } else {
+          if (this.isImg) {
+            this.replaced = true;
+          }
+
+          this.options.data = null;
+          this.uncreate();
+          this.load(url);
+        }
+      }
+
+      return this;
+    },
+    // Enable (unfreeze) the cropper
+    enable: function enable() {
+      if (this.ready && this.disabled) {
+        this.disabled = false;
+        removeClass(this.cropper, CLASS_DISABLED);
+      }
+
+      return this;
+    },
+    // Disable (freeze) the cropper
+    disable: function disable() {
+      if (this.ready && !this.disabled) {
+        this.disabled = true;
+        addClass(this.cropper, CLASS_DISABLED);
+      }
+
+      return this;
+    },
+
+    /**
+     * Destroy the cropper and remove the instance from the image
+     * @returns {Cropper} this
+     */
+    destroy: function destroy() {
+      var element = this.element;
+
+      if (!element[NAMESPACE]) {
+        return this;
+      }
+
+      element[NAMESPACE] = undefined;
+
+      if (this.isImg && this.replaced) {
+        element.src = this.originalUrl;
+      }
+
+      this.uncreate();
+      return this;
+    },
+
+    /**
+     * Move the canvas with relative offsets
+     * @param {number} offsetX - The relative offset distance on the x-axis.
+     * @param {number} [offsetY=offsetX] - The relative offset distance on the y-axis.
+     * @returns {Cropper} this
+     */
+    move: function move(offsetX) {
+      var offsetY = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : offsetX;
+      var _this$canvasData = this.canvasData,
+          left = _this$canvasData.left,
+          top = _this$canvasData.top;
+      return this.moveTo(isUndefined(offsetX) ? offsetX : left + Number(offsetX), isUndefined(offsetY) ? offsetY : top + Number(offsetY));
+    },
+
+    /**
+     * Move the canvas to an absolute point
+     * @param {number} x - The x-axis coordinate.
+     * @param {number} [y=x] - The y-axis coordinate.
+     * @returns {Cropper} this
+     */
+    moveTo: function moveTo(x) {
+      var y = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : x;
+      var canvasData = this.canvasData;
+      var changed = false;
+      x = Number(x);
+      y = Number(y);
+
+      if (this.ready && !this.disabled && this.options.movable) {
+        if (isNumber(x)) {
+          canvasData.left = x;
+          changed = true;
+        }
+
+        if (isNumber(y)) {
+          canvasData.top = y;
+          changed = true;
+        }
+
+        if (changed) {
+          this.renderCanvas(true);
+        }
+      }
+
+      return this;
+    },
+
+    /**
+     * Zoom the canvas with a relative ratio
+     * @param {number} ratio - The target ratio.
+     * @param {Event} _originalEvent - The original event if any.
+     * @returns {Cropper} this
+     */
+    zoom: function zoom(ratio, _originalEvent) {
+      var canvasData = this.canvasData;
+      ratio = Number(ratio);
+
+      if (ratio < 0) {
+        ratio = 1 / (1 - ratio);
+      } else {
+        ratio = 1 + ratio;
+      }
+
+      return this.zoomTo(canvasData.width * ratio / canvasData.naturalWidth, null, _originalEvent);
+    },
+
+    /**
+     * Zoom the canvas to an absolute ratio
+     * @param {number} ratio - The target ratio.
+     * @param {Object} pivot - The zoom pivot point coordinate.
+     * @param {Event} _originalEvent - The original event if any.
+     * @returns {Cropper} this
+     */
+    zoomTo: function zoomTo(ratio, pivot, _originalEvent) {
+      var options = this.options,
+          canvasData = this.canvasData;
+      var width = canvasData.width,
+          height = canvasData.height,
+          naturalWidth = canvasData.naturalWidth,
+          naturalHeight = canvasData.naturalHeight;
+      ratio = Number(ratio);
+
+      if (ratio >= 0 && this.ready && !this.disabled && options.zoomable) {
+        var newWidth = naturalWidth * ratio;
+        var newHeight = naturalHeight * ratio;
+
+        if (dispatchEvent(this.element, EVENT_ZOOM, {
+          ratio: ratio,
+          oldRatio: width / naturalWidth,
+          originalEvent: _originalEvent
+        }) === false) {
+          return this;
+        }
+
+        if (_originalEvent) {
+          var pointers = this.pointers;
+          var offset = getOffset(this.cropper);
+          var center = pointers && Object.keys(pointers).length ? getPointersCenter(pointers) : {
+            pageX: _originalEvent.pageX,
+            pageY: _originalEvent.pageY
+          }; // Zoom from the triggering point of the event
+
+          canvasData.left -= (newWidth - width) * ((center.pageX - offset.left - canvasData.left) / width);
+          canvasData.top -= (newHeight - height) * ((center.pageY - offset.top - canvasData.top) / height);
+        } else if (isPlainObject(pivot) && isNumber(pivot.x) && isNumber(pivot.y)) {
+          canvasData.left -= (newWidth - width) * ((pivot.x - canvasData.left) / width);
+          canvasData.top -= (newHeight - height) * ((pivot.y - canvasData.top) / height);
+        } else {
+          // Zoom from the center of the canvas
+          canvasData.left -= (newWidth - width) / 2;
+          canvasData.top -= (newHeight - height) / 2;
+        }
+
+        canvasData.width = newWidth;
+        canvasData.height = newHeight;
+        this.renderCanvas(true);
+      }
+
+      return this;
+    },
+
+    /**
+     * Rotate the canvas with a relative degree
+     * @param {number} degree - The rotate degree.
+     * @returns {Cropper} this
+     */
+    rotate: function rotate(degree) {
+      return this.rotateTo((this.imageData.rotate || 0) + Number(degree));
+    },
+
+    /**
+     * Rotate the canvas to an absolute degree
+     * @param {number} degree - The rotate degree.
+     * @returns {Cropper} this
+     */
+    rotateTo: function rotateTo(degree) {
+      degree = Number(degree);
+
+      if (isNumber(degree) && this.ready && !this.disabled && this.options.rotatable) {
+        this.imageData.rotate = degree % 360;
+        this.renderCanvas(true, true);
+      }
+
+      return this;
+    },
+
+    /**
+     * Scale the image on the x-axis.
+     * @param {number} scaleX - The scale ratio on the x-axis.
+     * @returns {Cropper} this
+     */
+    scaleX: function scaleX(_scaleX) {
+      var scaleY = this.imageData.scaleY;
+      return this.scale(_scaleX, isNumber(scaleY) ? scaleY : 1);
+    },
+
+    /**
+     * Scale the image on the y-axis.
+     * @param {number} scaleY - The scale ratio on the y-axis.
+     * @returns {Cropper} this
+     */
+    scaleY: function scaleY(_scaleY) {
+      var scaleX = this.imageData.scaleX;
+      return this.scale(isNumber(scaleX) ? scaleX : 1, _scaleY);
+    },
+
+    /**
+     * Scale the image
+     * @param {number} scaleX - The scale ratio on the x-axis.
+     * @param {number} [scaleY=scaleX] - The scale ratio on the y-axis.
+     * @returns {Cropper} this
+     */
+    scale: function scale(scaleX) {
+      var scaleY = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : scaleX;
+      var imageData = this.imageData;
+      var transformed = false;
+      scaleX = Number(scaleX);
+      scaleY = Number(scaleY);
+
+      if (this.ready && !this.disabled && this.options.scalable) {
+        if (isNumber(scaleX)) {
+          imageData.scaleX = scaleX;
+          transformed = true;
+        }
+
+        if (isNumber(scaleY)) {
+          imageData.scaleY = scaleY;
+          transformed = true;
+        }
+
+        if (transformed) {
+          this.renderCanvas(true, true);
+        }
+      }
+
+      return this;
+    },
+
+    /**
+     * Get the cropped area position and size data (base on the original image)
+     * @param {boolean} [rounded=false] - Indicate if round the data values or not.
+     * @returns {Object} The result cropped data.
+     */
+    getData: function getData() {
+      var rounded = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
+      var options = this.options,
+          imageData = this.imageData,
+          canvasData = this.canvasData,
+          cropBoxData = this.cropBoxData;
+      var data;
+
+      if (this.ready && this.cropped) {
+        data = {
+          x: cropBoxData.left - canvasData.left,
+          y: cropBoxData.top - canvasData.top,
+          width: cropBoxData.width,
+          height: cropBoxData.height
+        };
+        var ratio = imageData.width / imageData.naturalWidth;
+        forEach(data, function (n, i) {
+          data[i] = n / ratio;
+        });
+
+        if (rounded) {
+          // In case rounding off leads to extra 1px in right or bottom border
+          // we should round the top-left corner and the dimension (#343).
+          var bottom = Math.round(data.y + data.height);
+          var right = Math.round(data.x + data.width);
+          data.x = Math.round(data.x);
+          data.y = Math.round(data.y);
+          data.width = right - data.x;
+          data.height = bottom - data.y;
+        }
+      } else {
+        data = {
+          x: 0,
+          y: 0,
+          width: 0,
+          height: 0
+        };
+      }
+
+      if (options.rotatable) {
+        data.rotate = imageData.rotate || 0;
+      }
+
+      if (options.scalable) {
+        data.scaleX = imageData.scaleX || 1;
+        data.scaleY = imageData.scaleY || 1;
+      }
+
+      return data;
+    },
+
+    /**
+     * Set the cropped area position and size with new data
+     * @param {Object} data - The new data.
+     * @returns {Cropper} this
+     */
+    setData: function setData(data) {
+      var options = this.options,
+          imageData = this.imageData,
+          canvasData = this.canvasData;
+      var cropBoxData = {};
+
+      if (this.ready && !this.disabled && isPlainObject(data)) {
+        var transformed = false;
+
+        if (options.rotatable) {
+          if (isNumber(data.rotate) && data.rotate !== imageData.rotate) {
+            imageData.rotate = data.rotate;
+            transformed = true;
+          }
+        }
+
+        if (options.scalable) {
+          if (isNumber(data.scaleX) && data.scaleX !== imageData.scaleX) {
+            imageData.scaleX = data.scaleX;
+            transformed = true;
+          }
+
+          if (isNumber(data.scaleY) && data.scaleY !== imageData.scaleY) {
+            imageData.scaleY = data.scaleY;
+            transformed = true;
+          }
+        }
+
+        if (transformed) {
+          this.renderCanvas(true, true);
+        }
+
+        var ratio = imageData.width / imageData.naturalWidth;
+
+        if (isNumber(data.x)) {
+          cropBoxData.left = data.x * ratio + canvasData.left;
+        }
+
+        if (isNumber(data.y)) {
+          cropBoxData.top = data.y * ratio + canvasData.top;
+        }
+
+        if (isNumber(data.width)) {
+          cropBoxData.width = data.width * ratio;
+        }
+
+        if (isNumber(data.height)) {
+          cropBoxData.height = data.height * ratio;
+        }
+
+        this.setCropBoxData(cropBoxData);
+      }
+
+      return this;
+    },
+
+    /**
+     * Get the container size data.
+     * @returns {Object} The result container data.
+     */
+    getContainerData: function getContainerData() {
+      return this.ready ? assign({}, this.containerData) : {};
+    },
+
+    /**
+     * Get the image position and size data.
+     * @returns {Object} The result image data.
+     */
+    getImageData: function getImageData() {
+      return this.sized ? assign({}, this.imageData) : {};
+    },
+
+    /**
+     * Get the canvas position and size data.
+     * @returns {Object} The result canvas data.
+     */
+    getCanvasData: function getCanvasData() {
+      var canvasData = this.canvasData;
+      var data = {};
+
+      if (this.ready) {
+        forEach(['left', 'top', 'width', 'height', 'naturalWidth', 'naturalHeight'], function (n) {
+          data[n] = canvasData[n];
+        });
+      }
+
+      return data;
+    },
+
+    /**
+     * Set the canvas position and size with new data.
+     * @param {Object} data - The new canvas data.
+     * @returns {Cropper} this
+     */
+    setCanvasData: function setCanvasData(data) {
+      var canvasData = this.canvasData;
+      var aspectRatio = canvasData.aspectRatio;
+
+      if (this.ready && !this.disabled && isPlainObject(data)) {
+        if (isNumber(data.left)) {
+          canvasData.left = data.left;
+        }
+
+        if (isNumber(data.top)) {
+          canvasData.top = data.top;
+        }
+
+        if (isNumber(data.width)) {
+          canvasData.width = data.width;
+          canvasData.height = data.width / aspectRatio;
+        } else if (isNumber(data.height)) {
+          canvasData.height = data.height;
+          canvasData.width = data.height * aspectRatio;
+        }
+
+        this.renderCanvas(true);
+      }
+
+      return this;
+    },
+
+    /**
+     * Get the crop box position and size data.
+     * @returns {Object} The result crop box data.
+     */
+    getCropBoxData: function getCropBoxData() {
+      var cropBoxData = this.cropBoxData;
+      var data;
+
+      if (this.ready && this.cropped) {
+        data = {
+          left: cropBoxData.left,
+          top: cropBoxData.top,
+          width: cropBoxData.width,
+          height: cropBoxData.height
+        };
+      }
+
+      return data || {};
+    },
+
+    /**
+     * Set the crop box position and size with new data.
+     * @param {Object} data - The new crop box data.
+     * @returns {Cropper} this
+     */
+    setCropBoxData: function setCropBoxData(data) {
+      var cropBoxData = this.cropBoxData;
+      var aspectRatio = this.options.aspectRatio;
+      var widthChanged;
+      var heightChanged;
+
+      if (this.ready && this.cropped && !this.disabled && isPlainObject(data)) {
+        if (isNumber(data.left)) {
+          cropBoxData.left = data.left;
+        }
+
+        if (isNumber(data.top)) {
+          cropBoxData.top = data.top;
+        }
+
+        if (isNumber(data.width) && data.width !== cropBoxData.width) {
+          widthChanged = true;
+          cropBoxData.width = data.width;
+        }
+
+        if (isNumber(data.height) && data.height !== cropBoxData.height) {
+          heightChanged = true;
+          cropBoxData.height = data.height;
+        }
+
+        if (aspectRatio) {
+          if (widthChanged) {
+            cropBoxData.height = cropBoxData.width / aspectRatio;
+          } else if (heightChanged) {
+            cropBoxData.width = cropBoxData.height * aspectRatio;
+          }
+        }
+
+        this.renderCropBox();
+      }
+
+      return this;
+    },
+
+    /**
+     * Get a canvas drawn the cropped image.
+     * @param {Object} [options={}] - The config options.
+     * @returns {HTMLCanvasElement} - The result canvas.
+     */
+    getCroppedCanvas: function getCroppedCanvas() {
+      var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
+
+      if (!this.ready || !window.HTMLCanvasElement) {
+        return null;
+      }
+
+      var canvasData = this.canvasData;
+      var source = getSourceCanvas(this.image, this.imageData, canvasData, options); // Returns the source canvas if it is not cropped.
+
+      if (!this.cropped) {
+        return source;
+      }
+
+      var _this$getData = this.getData(),
+          initialX = _this$getData.x,
+          initialY = _this$getData.y,
+          initialWidth = _this$getData.width,
+          initialHeight = _this$getData.height;
+
+      var ratio = source.width / Math.floor(canvasData.naturalWidth);
+
+      if (ratio !== 1) {
+        initialX *= ratio;
+        initialY *= ratio;
+        initialWidth *= ratio;
+        initialHeight *= ratio;
+      }
+
+      var aspectRatio = initialWidth / initialHeight;
+      var maxSizes = getAdjustedSizes({
+        aspectRatio: aspectRatio,
+        width: options.maxWidth || Infinity,
+        height: options.maxHeight || Infinity
+      });
+      var minSizes = getAdjustedSizes({
+        aspectRatio: aspectRatio,
+        width: options.minWidth || 0,
+        height: options.minHeight || 0
+      }, 'cover');
+
+      var _getAdjustedSizes = getAdjustedSizes({
+        aspectRatio: aspectRatio,
+        width: options.width || (ratio !== 1 ? source.width : initialWidth),
+        height: options.height || (ratio !== 1 ? source.height : initialHeight)
+      }),
+          width = _getAdjustedSizes.width,
+          height = _getAdjustedSizes.height;
+
+      width = Math.min(maxSizes.width, Math.max(minSizes.width, width));
+      height = Math.min(maxSizes.height, Math.max(minSizes.height, height));
+      var canvas = document.createElement('canvas');
+      var context = canvas.getContext('2d');
+      canvas.width = normalizeDecimalNumber(width);
+      canvas.height = normalizeDecimalNumber(height);
+      context.fillStyle = options.fillColor || 'transparent';
+      context.fillRect(0, 0, width, height);
+      var _options$imageSmoothi = options.imageSmoothingEnabled,
+          imageSmoothingEnabled = _options$imageSmoothi === void 0 ? true : _options$imageSmoothi,
+          imageSmoothingQuality = options.imageSmoothingQuality;
+      context.imageSmoothingEnabled = imageSmoothingEnabled;
+
+      if (imageSmoothingQuality) {
+        context.imageSmoothingQuality = imageSmoothingQuality;
+      } // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D.drawImage
+
+
+      var sourceWidth = source.width;
+      var sourceHeight = source.height; // Source canvas parameters
+
+      var srcX = initialX;
+      var srcY = initialY;
+      var srcWidth;
+      var srcHeight; // Destination canvas parameters
+
+      var dstX;
+      var dstY;
+      var dstWidth;
+      var dstHeight;
+
+      if (srcX <= -initialWidth || srcX > sourceWidth) {
+        srcX = 0;
+        srcWidth = 0;
+        dstX = 0;
+        dstWidth = 0;
+      } else if (srcX <= 0) {
+        dstX = -srcX;
+        srcX = 0;
+        srcWidth = Math.min(sourceWidth, initialWidth + srcX);
+        dstWidth = srcWidth;
+      } else if (srcX <= sourceWidth) {
+        dstX = 0;
+        srcWidth = Math.min(initialWidth, sourceWidth - srcX);
+        dstWidth = srcWidth;
+      }
+
+      if (srcWidth <= 0 || srcY <= -initialHeight || srcY > sourceHeight) {
+        srcY = 0;
+        srcHeight = 0;
+        dstY = 0;
+        dstHeight = 0;
+      } else if (srcY <= 0) {
+        dstY = -srcY;
+        srcY = 0;
+        srcHeight = Math.min(sourceHeight, initialHeight + srcY);
+        dstHeight = srcHeight;
+      } else if (srcY <= sourceHeight) {
+        dstY = 0;
+        srcHeight = Math.min(initialHeight, sourceHeight - srcY);
+        dstHeight = srcHeight;
+      }
+
+      var params = [srcX, srcY, srcWidth, srcHeight]; // Avoid "IndexSizeError"
+
+      if (dstWidth > 0 && dstHeight > 0) {
+        var scale = width / initialWidth;
+        params.push(dstX * scale, dstY * scale, dstWidth * scale, dstHeight * scale);
+      } // All the numerical parameters should be integer for `drawImage`
+      // https://github.com/fengyuanchen/cropper/issues/476
+
+
+      context.drawImage.apply(context, [source].concat(_toConsumableArray(params.map(function (param) {
+        return Math.floor(normalizeDecimalNumber(param));
+      }))));
+      return canvas;
+    },
+
+    /**
+     * Change the aspect ratio of the crop box.
+     * @param {number} aspectRatio - The new aspect ratio.
+     * @returns {Cropper} this
+     */
+    setAspectRatio: function setAspectRatio(aspectRatio) {
+      var options = this.options;
+
+      if (!this.disabled && !isUndefined(aspectRatio)) {
+        // 0 -> NaN
+        options.aspectRatio = Math.max(0, aspectRatio) || NaN;
+
+        if (this.ready) {
+          this.initCropBox();
+
+          if (this.cropped) {
+            this.renderCropBox();
+          }
+        }
+      }
+
+      return this;
+    },
+
+    /**
+     * Change the drag mode.
+     * @param {string} mode - The new drag mode.
+     * @returns {Cropper} this
+     */
+    setDragMode: function setDragMode(mode) {
+      var options = this.options,
+          dragBox = this.dragBox,
+          face = this.face;
+
+      if (this.ready && !this.disabled) {
+        var croppable = mode === DRAG_MODE_CROP;
+        var movable = options.movable && mode === DRAG_MODE_MOVE;
+        mode = croppable || movable ? mode : DRAG_MODE_NONE;
+        options.dragMode = mode;
+        setData(dragBox, DATA_ACTION, mode);
+        toggleClass(dragBox, CLASS_CROP, croppable);
+        toggleClass(dragBox, CLASS_MOVE, movable);
+
+        if (!options.cropBoxMovable) {
+          // Sync drag mode to crop box when it is not movable
+          setData(face, DATA_ACTION, mode);
+          toggleClass(face, CLASS_CROP, croppable);
+          toggleClass(face, CLASS_MOVE, movable);
+        }
+      }
+
+      return this;
+    }
+  };
+
+  var AnotherCropper = WINDOW.Cropper;
+
+  var Cropper = /*#__PURE__*/function () {
+    /**
+     * Create a new Cropper.
+     * @param {Element} element - The target element for cropping.
+     * @param {Object} [options={}] - The configuration options.
+     */
+    function Cropper(element) {
+      var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
+
+      _classCallCheck(this, Cropper);
+
+      if (!element || !REGEXP_TAG_NAME.test(element.tagName)) {
+        throw new Error('The first argument is required and must be an <img> or <canvas> element.');
+      }
+
+      this.element = element;
+      this.options = assign({}, DEFAULTS, isPlainObject(options) && options);
+      this.cropped = false;
+      this.disabled = false;
+      this.pointers = {};
+      this.ready = false;
+      this.reloading = false;
+      this.replaced = false;
+      this.sized = false;
+      this.sizing = false;
+      this.init();
+    }
+
+    _createClass(Cropper, [{
+      key: "init",
+      value: function init() {
+        var element = this.element;
+        var tagName = element.tagName.toLowerCase();
+        var url;
+
+        if (element[NAMESPACE]) {
+          return;
+        }
+
+        element[NAMESPACE] = this;
+
+        if (tagName === 'img') {
+          this.isImg = true; // e.g.: "img/picture.jpg"
+
+          url = element.getAttribute('src') || '';
+          this.originalUrl = url; // Stop when it's a blank image
+
+          if (!url) {
+            return;
+          } // e.g.: "https://example.com/img/picture.jpg"
+
+
+          url = element.src;
+        } else if (tagName === 'canvas' && window.HTMLCanvasElement) {
+          url = element.toDataURL();
+        }
+
+        this.load(url);
+      }
+    }, {
+      key: "load",
+      value: function load(url) {
+        var _this = this;
+
+        if (!url) {
+          return;
+        }
+
+        this.url = url;
+        this.imageData = {};
+        var element = this.element,
+            options = this.options;
+
+        if (!options.rotatable && !options.scalable) {
+          options.checkOrientation = false;
+        } // Only IE10+ supports Typed Arrays
+
+
+        if (!options.checkOrientation || !window.ArrayBuffer) {
+          this.clone();
+          return;
+        } // Detect the mime type of the image directly if it is a Data URL
+
+
+        if (REGEXP_DATA_URL.test(url)) {
+          // Read ArrayBuffer from Data URL of JPEG images directly for better performance
+          if (REGEXP_DATA_URL_JPEG.test(url)) {
+            this.read(dataURLToArrayBuffer(url));
+          } else {
+            // Only a JPEG image may contains Exif Orientation information,
+            // the rest types of Data URLs are not necessary to check orientation at all.
+            this.clone();
+          }
+
+          return;
+        } // 1. Detect the mime type of the image by a XMLHttpRequest.
+        // 2. Load the image as ArrayBuffer for reading orientation if its a JPEG image.
+
+
+        var xhr = new XMLHttpRequest();
+        var clone = this.clone.bind(this);
+        this.reloading = true;
+        this.xhr = xhr; // 1. Cross origin requests are only supported for protocol schemes:
+        // http, https, data, chrome, chrome-extension.
+        // 2. Access to XMLHttpRequest from a Data URL will be blocked by CORS policy
+        // in some browsers as IE11 and Safari.
+
+        xhr.onabort = clone;
+        xhr.onerror = clone;
+        xhr.ontimeout = clone;
+
+        xhr.onprogress = function () {
+          // Abort the request directly if it not a JPEG image for better performance
+          if (xhr.getResponseHeader('content-type') !== MIME_TYPE_JPEG) {
+            xhr.abort();
+          }
+        };
+
+        xhr.onload = function () {
+          _this.read(xhr.response);
+        };
+
+        xhr.onloadend = function () {
+          _this.reloading = false;
+          _this.xhr = null;
+        }; // Bust cache when there is a "crossOrigin" property to avoid browser cache error
+
+
+        if (options.checkCrossOrigin && isCrossOriginURL(url) && element.crossOrigin) {
+          url = addTimestamp(url);
+        } // The third parameter is required for avoiding side-effect (#682)
+
+
+        xhr.open('GET', url, true);
+        xhr.responseType = 'arraybuffer';
+        xhr.withCredentials = element.crossOrigin === 'use-credentials';
+        xhr.send();
+      }
+    }, {
+      key: "read",
+      value: function read(arrayBuffer) {
+        var options = this.options,
+            imageData = this.imageData; // Reset the orientation value to its default value 1
+        // as some iOS browsers will render image with its orientation
+
+        var orientation = resetAndGetOrientation(arrayBuffer);
+        var rotate = 0;
+        var scaleX = 1;
+        var scaleY = 1;
+
+        if (orientation > 1) {
+          // Generate a new URL which has the default orientation value
+          this.url = arrayBufferToDataURL(arrayBuffer, MIME_TYPE_JPEG);
+
+          var _parseOrientation = parseOrientation(orientation);
+
+          rotate = _parseOrientation.rotate;
+          scaleX = _parseOrientation.scaleX;
+          scaleY = _parseOrientation.scaleY;
+        }
+
+        if (options.rotatable) {
+          imageData.rotate = rotate;
+        }
+
+        if (options.scalable) {
+          imageData.scaleX = scaleX;
+          imageData.scaleY = scaleY;
+        }
+
+        this.clone();
+      }
+    }, {
+      key: "clone",
+      value: function clone() {
+        var element = this.element,
+            url = this.url;
+        var crossOrigin = element.crossOrigin;
+        var crossOriginUrl = url;
+
+        if (this.options.checkCrossOrigin && isCrossOriginURL(url)) {
+          if (!crossOrigin) {
+            crossOrigin = 'anonymous';
+          } // Bust cache when there is not a "crossOrigin" property (#519)
+
+
+          crossOriginUrl = addTimestamp(url);
+        }
+
+        this.crossOrigin = crossOrigin;
+        this.crossOriginUrl = crossOriginUrl;
+        var image = document.createElement('img');
+
+        if (crossOrigin) {
+          image.crossOrigin = crossOrigin;
+        }
+
+        image.src = crossOriginUrl || url;
+        image.alt = element.alt || 'The image to crop';
+        this.image = image;
+        image.onload = this.start.bind(this);
+        image.onerror = this.stop.bind(this);
+        addClass(image, CLASS_HIDE);
+        element.parentNode.insertBefore(image, element.nextSibling);
+      }
+    }, {
+      key: "start",
+      value: function start() {
+        var _this2 = this;
+
+        var image = this.image;
+        image.onload = null;
+        image.onerror = null;
+        this.sizing = true; // Match all browsers that use WebKit as the layout engine in iOS devices,
+        // such as Safari for iOS, Chrome for iOS, and in-app browsers.
+
+        var isIOSWebKit = WINDOW.navigator && /(?:iPad|iPhone|iPod).*?AppleWebKit/i.test(WINDOW.navigator.userAgent);
+
+        var done = function done(naturalWidth, naturalHeight) {
+          assign(_this2.imageData, {
+            naturalWidth: naturalWidth,
+            naturalHeight: naturalHeight,
+            aspectRatio: naturalWidth / naturalHeight
+          });
+          _this2.initialImageData = assign({}, _this2.imageData);
+          _this2.sizing = false;
+          _this2.sized = true;
+
+          _this2.build();
+        }; // Most modern browsers (excepts iOS WebKit)
+
+
+        if (image.naturalWidth && !isIOSWebKit) {
+          done(image.naturalWidth, image.naturalHeight);
+          return;
+        }
+
+        var sizingImage = document.createElement('img');
+        var body = document.body || document.documentElement;
+        this.sizingImage = sizingImage;
+
+        sizingImage.onload = function () {
+          done(sizingImage.width, sizingImage.height);
+
+          if (!isIOSWebKit) {
+            body.removeChild(sizingImage);
+          }
+        };
+
+        sizingImage.src = image.src; // iOS WebKit will convert the image automatically
+        // with its orientation once append it into DOM (#279)
+
+        if (!isIOSWebKit) {
+          sizingImage.style.cssText = 'left:0;' + 'max-height:none!important;' + 'max-width:none!important;' + 'min-height:0!important;' + 'min-width:0!important;' + 'opacity:0;' + 'position:absolute;' + 'top:0;' + 'z-index:-1;';
+          body.appendChild(sizingImage);
+        }
+      }
+    }, {
+      key: "stop",
+      value: function stop() {
+        var image = this.image;
+        image.onload = null;
+        image.onerror = null;
+        image.parentNode.removeChild(image);
+        this.image = null;
+      }
+    }, {
+      key: "build",
+      value: function build() {
+        if (!this.sized || this.ready) {
+          return;
+        }
+
+        var element = this.element,
+            options = this.options,
+            image = this.image; // Create cropper elements
+
+        var container = element.parentNode;
+        var template = document.createElement('div');
+        template.innerHTML = TEMPLATE;
+        var cropper = template.querySelector(".".concat(NAMESPACE, "-container"));
+        var canvas = cropper.querySelector(".".concat(NAMESPACE, "-canvas"));
+        var dragBox = cropper.querySelector(".".concat(NAMESPACE, "-drag-box"));
+        var cropBox = cropper.querySelector(".".concat(NAMESPACE, "-crop-box"));
+        var face = cropBox.querySelector(".".concat(NAMESPACE, "-face"));
+        this.container = container;
+        this.cropper = cropper;
+        this.canvas = canvas;
+        this.dragBox = dragBox;
+        this.cropBox = cropBox;
+        this.viewBox = cropper.querySelector(".".concat(NAMESPACE, "-view-box"));
+        this.face = face;
+        canvas.appendChild(image); // Hide the original image
+
+        addClass(element, CLASS_HIDDEN); // Inserts the cropper after to the current image
+
+        container.insertBefore(cropper, element.nextSibling); // Show the image if is hidden
+
+        if (!this.isImg) {
+          removeClass(image, CLASS_HIDE);
+        }
+
+        this.initPreview();
+        this.bind();
+        options.initialAspectRatio = Math.max(0, options.initialAspectRatio) || NaN;
+        options.aspectRatio = Math.max(0, options.aspectRatio) || NaN;
+        options.viewMode = Math.max(0, Math.min(3, Math.round(options.viewMode))) || 0;
+        addClass(cropBox, CLASS_HIDDEN);
+
+        if (!options.guides) {
+          addClass(cropBox.getElementsByClassName("".concat(NAMESPACE, "-dashed")), CLASS_HIDDEN);
+        }
+
+        if (!options.center) {
+          addClass(cropBox.getElementsByClassName("".concat(NAMESPACE, "-center")), CLASS_HIDDEN);
+        }
+
+        if (options.background) {
+          addClass(cropper, "".concat(NAMESPACE, "-bg"));
+        }
+
+        if (!options.highlight) {
+          addClass(face, CLASS_INVISIBLE);
+        }
+
+        if (options.cropBoxMovable) {
+          addClass(face, CLASS_MOVE);
+          setData(face, DATA_ACTION, ACTION_ALL);
+        }
+
+        if (!options.cropBoxResizable) {
+          addClass(cropBox.getElementsByClassName("".concat(NAMESPACE, "-line")), CLASS_HIDDEN);
+          addClass(cropBox.getElementsByClassName("".concat(NAMESPACE, "-point")), CLASS_HIDDEN);
+        }
+
+        this.render();
+        this.ready = true;
+        this.setDragMode(options.dragMode);
+
+        if (options.autoCrop) {
+          this.crop();
+        }
+
+        this.setData(options.data);
+
+        if (isFunction(options.ready)) {
+          addListener(element, EVENT_READY, options.ready, {
+            once: true
+          });
+        }
+
+        dispatchEvent(element, EVENT_READY);
+      }
+    }, {
+      key: "unbuild",
+      value: function unbuild() {
+        if (!this.ready) {
+          return;
+        }
+
+        this.ready = false;
+        this.unbind();
+        this.resetPreview();
+        this.cropper.parentNode.removeChild(this.cropper);
+        removeClass(this.element, CLASS_HIDDEN);
+      }
+    }, {
+      key: "uncreate",
+      value: function uncreate() {
+        if (this.ready) {
+          this.unbuild();
+          this.ready = false;
+          this.cropped = false;
+        } else if (this.sizing) {
+          this.sizingImage.onload = null;
+          this.sizing = false;
+          this.sized = false;
+        } else if (this.reloading) {
+          this.xhr.onabort = null;
+          this.xhr.abort();
+        } else if (this.image) {
+          this.stop();
+        }
+      }
+      /**
+       * Get the no conflict cropper class.
+       * @returns {Cropper} The cropper class.
+       */
+
+    }], [{
+      key: "noConflict",
+      value: function noConflict() {
+        window.Cropper = AnotherCropper;
+        return Cropper;
+      }
+      /**
+       * Change the default options.
+       * @param {Object} options - The new default options.
+       */
+
+    }, {
+      key: "setDefaults",
+      value: function setDefaults(options) {
+        assign(DEFAULTS, isPlainObject(options) && options);
+      }
+    }]);
+
+    return Cropper;
+  }();
+
+  assign(Cropper.prototype, render, preview, events, handlers, change, methods);
+
+  return Cropper;
+
+})));
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/cropper/cropper.min.css b/ruoyi-admin/src/main/resources/static/ajax/libs/cropper/cropper.min.css
new file mode 100644
index 0000000..9b23714
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/cropper/cropper.min.css
@@ -0,0 +1,9 @@
+/*!
+ * Cropper.js v1.5.12
+ * https://fengyuanchen.github.io/cropperjs
+ *
+ * Copyright 2015-present Chen Fengyuan
+ * Released under the MIT license
+ *
+ * Date: 2021-06-12T08:00:11.623Z
+ */.cropper-container{direction:ltr;font-size:0;line-height:0;position:relative;-ms-touch-action:none;touch-action:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.cropper-container img{image-orientation:0deg;display:block;height:100%;max-height:none!important;max-width:none!important;min-height:0!important;min-width:0!important;width:100%}.cropper-canvas,.cropper-crop-box,.cropper-drag-box,.cropper-modal,.cropper-wrap-box{bottom:0;left:0;position:absolute;right:0;top:0}.cropper-canvas,.cropper-wrap-box{overflow:hidden}.cropper-drag-box{background-color:#fff;opacity:0}.cropper-modal{background-color:#000;opacity:.5}.cropper-view-box{display:block;height:100%;outline:1px solid #39f;outline-color:rgba(51,153,255,.75);overflow:hidden;width:100%}.cropper-dashed{border:0 dashed #eee;display:block;opacity:.5;position:absolute}.cropper-dashed.dashed-h{border-bottom-width:1px;border-top-width:1px;height:33.33333%;left:0;top:33.33333%;width:100%}.cropper-dashed.dashed-v{border-left-width:1px;border-right-width:1px;height:100%;left:33.33333%;top:0;width:33.33333%}.cropper-center{display:block;height:0;left:50%;opacity:.75;position:absolute;top:50%;width:0}.cropper-center:after,.cropper-center:before{background-color:#eee;content:" ";display:block;position:absolute}.cropper-center:before{height:1px;left:-3px;top:0;width:7px}.cropper-center:after{height:7px;left:0;top:-3px;width:1px}.cropper-face,.cropper-line,.cropper-point{display:block;height:100%;opacity:.1;position:absolute;width:100%}.cropper-face{background-color:#fff;left:0;top:0}.cropper-line{background-color:#39f}.cropper-line.line-e{cursor:ew-resize;right:-3px;top:0;width:5px}.cropper-line.line-n{cursor:ns-resize;height:5px;left:0;top:-3px}.cropper-line.line-w{cursor:ew-resize;left:-3px;top:0;width:5px}.cropper-line.line-s{bottom:-3px;cursor:ns-resize;height:5px;left:0}.cropper-point{background-color:#39f;height:5px;opacity:.75;width:5px}.cropper-point.point-e{cursor:ew-resize;margin-top:-3px;right:-3px;top:50%}.cropper-point.point-n{cursor:ns-resize;left:50%;margin-left:-3px;top:-3px}.cropper-point.point-w{cursor:ew-resize;left:-3px;margin-top:-3px;top:50%}.cropper-point.point-s{bottom:-3px;cursor:s-resize;left:50%;margin-left:-3px}.cropper-point.point-ne{cursor:nesw-resize;right:-3px;top:-3px}.cropper-point.point-nw{cursor:nwse-resize;left:-3px;top:-3px}.cropper-point.point-sw{bottom:-3px;cursor:nesw-resize;left:-3px}.cropper-point.point-se{bottom:-3px;cursor:nwse-resize;height:20px;opacity:1;right:-3px;width:20px}@media (min-width:768px){.cropper-point.point-se{height:15px;width:15px}}@media (min-width:992px){.cropper-point.point-se{height:10px;width:10px}}@media (min-width:1200px){.cropper-point.point-se{height:5px;opacity:.75;width:5px}}.cropper-point.point-se:before{background-color:#39f;bottom:-50%;content:" ";display:block;height:200%;opacity:0;position:absolute;right:-50%;width:200%}.cropper-invisible{opacity:0}.cropper-bg{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC")}.cropper-hide{display:block;height:0;position:absolute;width:0}.cropper-hidden{display:none!important}.cropper-move{cursor:move}.cropper-crop{cursor:crosshair}.cropper-disabled .cropper-drag-box,.cropper-disabled .cropper-face,.cropper-disabled .cropper-line,.cropper-disabled .cropper-point{cursor:not-allowed}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/cropper/cropper.min.js b/ruoyi-admin/src/main/resources/static/ajax/libs/cropper/cropper.min.js
new file mode 100644
index 0000000..365ce8b
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/cropper/cropper.min.js
@@ -0,0 +1,10 @@
+/*!
+ * Cropper.js v1.5.12
+ * https://fengyuanchen.github.io/cropperjs
+ *
+ * Copyright 2015-present Chen Fengyuan
+ * Released under the MIT license
+ *
+ * Date: 2021-06-12T08:00:17.411Z
+ */
+!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).Cropper=e()}(this,function(){"use strict";function e(e,t){var i,a=Object.keys(e);return Object.getOwnPropertySymbols&&(i=Object.getOwnPropertySymbols(e),t&&(i=i.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),a.push.apply(a,i)),a}function B(a){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?e(Object(n),!0).forEach(function(t){var e,i;e=a,t=n[i=t],i in e?Object.defineProperty(e,i,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[i]=t}):Object.getOwnPropertyDescriptors?Object.defineProperties(a,Object.getOwnPropertyDescriptors(n)):e(Object(n)).forEach(function(t){Object.defineProperty(a,t,Object.getOwnPropertyDescriptor(n,t))})}return a}function i(t){return(i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function n(t,e){for(var i=0;i<e.length;i++){var a=e[i];a.enumerable=a.enumerable||!1,a.configurable=!0,"value"in a&&(a.writable=!0),Object.defineProperty(t,a.key,a)}}function T(t){return function(t){if(Array.isArray(t))return a(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||function(t,e){if(t){if("string"==typeof t)return a(t,e);var i=Object.prototype.toString.call(t).slice(8,-1);return"Map"===(i="Object"===i&&t.constructor?t.constructor.name:i)||"Set"===i?Array.from(t):"Arguments"===i||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(i)?a(t,e):void 0}}(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function a(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,a=new Array(e);i<e;i++)a[i]=t[i];return a}var t="undefined"!=typeof window&&void 0!==window.document,h=t?window:{},o=!(!t||!h.document.documentElement)&&"ontouchstart"in h.document.documentElement,r=t&&"PointerEvent"in h,c="cropper",k="all",O="crop",E="move",W="zoom",H="e",N="w",L="s",z="n",Y="ne",X="nw",R="se",S="sw",s="".concat(c,"-crop"),d="".concat(c,"-disabled"),A="".concat(c,"-hidden"),l="".concat(c,"-hide"),p="".concat(c,"-invisible"),m="".concat(c,"-modal"),u="".concat(c,"-move"),g="".concat(c,"Action"),f="".concat(c,"Preview"),v="crop",w="move",b="none",y="crop",x="cropend",M="cropmove",C="cropstart",D="dblclick",j=r?"pointerdown":o?"touchstart":"mousedown",I=r?"pointermove":o?"touchmove":"mousemove",P=r?"pointerup pointercancel":o?"touchend touchcancel":"mouseup",U="zoom",q="image/jpeg",$=/^e|w|s|n|se|sw|ne|nw|all|crop|move|zoom$/,Q=/^data:/,K=/^data:image\/jpeg;base64,/,Z=/^img|canvas$/i,G={viewMode:0,dragMode:v,initialAspectRatio:NaN,aspectRatio:NaN,data:null,preview:"",responsive:!0,restore:!0,checkCrossOrigin:!0,checkOrientation:!0,modal:!0,guides:!0,center:!0,highlight:!0,background:!0,autoCrop:!0,autoCropArea:.8,movable:!0,rotatable:!0,scalable:!0,zoomable:!0,zoomOnTouch:!0,zoomOnWheel:!0,wheelZoomRatio:.1,cropBoxMovable:!0,cropBoxResizable:!0,toggleDragModeOnDblclick:!0,minCanvasWidth:0,minCanvasHeight:0,minCropBoxWidth:0,minCropBoxHeight:0,minContainerWidth:200,minContainerHeight:100,ready:null,cropstart:null,cropmove:null,cropend:null,crop:null,zoom:null},V=Number.isNaN||h.isNaN;function F(t){return"number"==typeof t&&!V(t)}var J=function(t){return 0<t&&t<1/0};function _(t){return void 0===t}function tt(t){return"object"===i(t)&&null!==t}var et=Object.prototype.hasOwnProperty;function it(t){if(!tt(t))return!1;try{var e=t.constructor,i=e.prototype;return e&&i&&et.call(i,"isPrototypeOf")}catch(t){return!1}}function at(t){return"function"==typeof t}var nt=Array.prototype.slice;function ot(t){return Array.from?Array.from(t):nt.call(t)}function ht(i,a){return i&&at(a)&&(Array.isArray(i)||F(i.length)?ot(i).forEach(function(t,e){a.call(i,t,e,i)}):tt(i)&&Object.keys(i).forEach(function(t){a.call(i,i[t],t,i)})),i}var rt=Object.assign||function(i){for(var t=arguments.length,e=new Array(1<t?t-1:0),a=1;a<t;a++)e[a-1]=arguments[a];return tt(i)&&0<e.length&&e.forEach(function(e){tt(e)&&Object.keys(e).forEach(function(t){i[t]=e[t]})}),i},st=/\.\d*(?:0|9){12}\d*$/;function ct(t,e){e=1<arguments.length&&void 0!==e?e:1e11;return st.test(t)?Math.round(t*e)/e:t}var dt=/^width|height|left|top|marginLeft|marginTop$/;function lt(t,e){var i=t.style;ht(e,function(t,e){dt.test(e)&&F(t)&&(t="".concat(t,"px")),i[e]=t})}function pt(t,e){var i;e&&(F(t.length)?ht(t,function(t){pt(t,e)}):t.classList?t.classList.add(e):(i=t.className.trim())?i.indexOf(e)<0&&(t.className="".concat(i," ").concat(e)):t.className=e)}function mt(t,e){e&&(F(t.length)?ht(t,function(t){mt(t,e)}):t.classList?t.classList.remove(e):0<=t.className.indexOf(e)&&(t.className=t.className.replace(e,"")))}function ut(t,e,i){e&&(F(t.length)?ht(t,function(t){ut(t,e,i)}):(i?pt:mt)(t,e))}var gt=/([a-z\d])([A-Z])/g;function ft(t){return t.replace(gt,"$1-$2").toLowerCase()}function vt(t,e){return tt(t[e])?t[e]:t.dataset?t.dataset[e]:t.getAttribute("data-".concat(ft(e)))}function wt(t,e,i){tt(i)?t[e]=i:t.dataset?t.dataset[e]=i:t.setAttribute("data-".concat(ft(e)),i)}var bt,yt,xt=/\s\s*/,Mt=(yt=!1,t&&(bt=!1,At=function(){},It=Object.defineProperty({},"once",{get:function(){return yt=!0,bt},set:function(t){bt=t}}),h.addEventListener("test",At,It),h.removeEventListener("test",At,It)),yt);function Ct(i,t,a,e){var n=3<arguments.length&&void 0!==e?e:{},o=a;t.trim().split(xt).forEach(function(t){var e;Mt||(e=i.listeners)&&e[t]&&e[t][a]&&(o=e[t][a],delete e[t][a],0===Object.keys(e[t]).length&&delete e[t],0===Object.keys(e).length&&delete i.listeners),i.removeEventListener(t,o,n)})}function Dt(o,t,h,e){var r=3<arguments.length&&void 0!==e?e:{},s=h;t.trim().split(xt).forEach(function(a){var t,n;r.once&&!Mt&&(t=o.listeners,s=function(){delete n[a][h],o.removeEventListener(a,s,r);for(var t=arguments.length,e=new Array(t),i=0;i<t;i++)e[i]=arguments[i];h.apply(o,e)},(n=void 0===t?{}:t)[a]||(n[a]={}),n[a][h]&&o.removeEventListener(a,n[a][h],r),n[a][h]=s,o.listeners=n),o.addEventListener(a,s,r)})}function Bt(t,e,i){var a;return at(Event)&&at(CustomEvent)?a=new CustomEvent(e,{detail:i,bubbles:!0,cancelable:!0}):(a=document.createEvent("CustomEvent")).initCustomEvent(e,!0,!0,i),t.dispatchEvent(a)}function kt(t){t=t.getBoundingClientRect();return{left:t.left+(window.pageXOffset-document.documentElement.clientLeft),top:t.top+(window.pageYOffset-document.documentElement.clientTop)}}var Ot=h.location,Tt=/^(\w+:)\/\/([^:/?#]*):?(\d*)/i;function Et(t){t=t.match(Tt);return null!==t&&(t[1]!==Ot.protocol||t[2]!==Ot.hostname||t[3]!==Ot.port)}function Wt(t){var e="timestamp=".concat((new Date).getTime());return t+(-1===t.indexOf("?")?"?":"&")+e}function Ht(t){var e=t.rotate,i=t.scaleX,a=t.scaleY,n=t.translateX,o=t.translateY,t=[];F(n)&&0!==n&&t.push("translateX(".concat(n,"px)")),F(o)&&0!==o&&t.push("translateY(".concat(o,"px)")),F(e)&&0!==e&&t.push("rotate(".concat(e,"deg)")),F(i)&&1!==i&&t.push("scaleX(".concat(i,")")),F(a)&&1!==a&&t.push("scaleY(".concat(a,")"));t=t.length?t.join(" "):"none";return{WebkitTransform:t,msTransform:t,transform:t}}function Nt(t,e){var i=t.pageX,a=t.pageY,t={endX:i,endY:a};return e?t:B({startX:i,startY:a},t)}function Lt(t,e){var i=t.aspectRatio,a=t.height,n=t.width,o=1<arguments.length&&void 0!==e?e:"contain",h=J(n),t=J(a);return h&&t?(e=a*i,"contain"===o&&n<e||"cover"===o&&e<n?a=n/i:n=a*i):h?a=n/i:t&&(n=a*i),{width:n,height:a}}var zt=String.fromCharCode;var Yt=/^data:.*,/;function Xt(t){var e,i,a,n,o,h,r,s=new DataView(t);try{if(255===s.getUint8(0)&&216===s.getUint8(1))for(var c=s.byteLength,d=2;d+1<c;){if(255===s.getUint8(d)&&225===s.getUint8(d+1)){i=d;break}d+=1}if(i&&(n=i+10,"Exif"===function(t,e,i){var a="";i+=e;for(var n=e;n<i;n+=1)a+=zt(t.getUint8(n));return a}(s,i+4,4)&&(!(r=18761===(o=s.getUint16(n)))&&19789!==o||42!==s.getUint16(n+2,r)||8<=(h=s.getUint32(n+4,r))&&(a=n+h))),a)for(var l,p=s.getUint16(a,r),m=0;m<p;m+=1)if(l=a+12*m+2,274===s.getUint16(l,r)){l+=8,e=s.getUint16(l,r),s.setUint16(l,1,r);break}}catch(t){e=1}return e}var Rt={render:function(){this.initContainer(),this.initCanvas(),this.initCropBox(),this.renderCanvas(),this.cropped&&this.renderCropBox()},initContainer:function(){var t=this.element,e=this.options,i=this.container,a=this.cropper,n=Number(e.minContainerWidth),e=Number(e.minContainerHeight);pt(a,A),mt(t,A);e={width:Math.max(i.offsetWidth,0<=n?n:200),height:Math.max(i.offsetHeight,0<=e?e:100)};lt(a,{width:(this.containerData=e).width,height:e.height}),pt(t,A),mt(a,A)},initCanvas:function(){var t=this.containerData,e=this.imageData,i=this.options.viewMode,a=Math.abs(e.rotate)%180==90,n=a?e.naturalHeight:e.naturalWidth,o=a?e.naturalWidth:e.naturalHeight,h=n/o,a=t.width,e=t.height;t.height*h>t.width?3===i?a=t.height*h:e=t.width/h:3===i?e=t.width/h:a=t.height*h;e={aspectRatio:h,naturalWidth:n,naturalHeight:o,width:a,height:e};this.canvasData=e,this.limited=1===i||2===i,this.limitCanvas(!0,!0),e.width=Math.min(Math.max(e.width,e.minWidth),e.maxWidth),e.height=Math.min(Math.max(e.height,e.minHeight),e.maxHeight),e.left=(t.width-e.width)/2,e.top=(t.height-e.height)/2,e.oldLeft=e.left,e.oldTop=e.top,this.initialCanvasData=rt({},e)},limitCanvas:function(t,e){var i,a=this.options,n=this.containerData,o=this.canvasData,h=this.cropBoxData,r=a.viewMode,s=o.aspectRatio,c=this.cropped&&h;t&&(t=Number(a.minCanvasWidth)||0,i=Number(a.minCanvasHeight)||0,1<r?(t=Math.max(t,n.width),i=Math.max(i,n.height),3===r&&(t<i*s?t=i*s:i=t/s)):0<r&&(t?t=Math.max(t,c?h.width:0):i?i=Math.max(i,c?h.height:0):c&&((t=h.width)<(i=h.height)*s?t=i*s:i=t/s)),t=(s=Lt({aspectRatio:s,width:t,height:i})).width,i=s.height,o.minWidth=t,o.minHeight=i,o.maxWidth=1/0,o.maxHeight=1/0),e&&((c?0:1)<r?(i=n.width-o.width,e=n.height-o.height,o.minLeft=Math.min(0,i),o.minTop=Math.min(0,e),o.maxLeft=Math.max(0,i),o.maxTop=Math.max(0,e),c&&this.limited&&(o.minLeft=Math.min(h.left,h.left+(h.width-o.width)),o.minTop=Math.min(h.top,h.top+(h.height-o.height)),o.maxLeft=h.left,o.maxTop=h.top,2===r&&(o.width>=n.width&&(o.minLeft=Math.min(0,i),o.maxLeft=Math.max(0,i)),o.height>=n.height&&(o.minTop=Math.min(0,e),o.maxTop=Math.max(0,e))))):(o.minLeft=-o.width,o.minTop=-o.height,o.maxLeft=n.width,o.maxTop=n.height))},renderCanvas:function(t,e){var i,a,n=this.canvasData,o=this.imageData;e&&(i=(a=function(t){var e=t.width,i=t.height,a=t.degree;if(90==(a=Math.abs(a)%180))return{width:i,height:e};var n=a%90*Math.PI/180,o=Math.sin(n),t=Math.cos(n),n=e*t+i*o,t=e*o+i*t;return 90<a?{width:t,height:n}:{width:n,height:t}}({width:o.naturalWidth*Math.abs(o.scaleX||1),height:o.naturalHeight*Math.abs(o.scaleY||1),degree:o.rotate||0})).width,e=a.height,o=n.width*(i/n.naturalWidth),a=n.height*(e/n.naturalHeight),n.left-=(o-n.width)/2,n.top-=(a-n.height)/2,n.width=o,n.height=a,n.aspectRatio=i/e,n.naturalWidth=i,n.naturalHeight=e,this.limitCanvas(!0,!1)),(n.width>n.maxWidth||n.width<n.minWidth)&&(n.left=n.oldLeft),(n.height>n.maxHeight||n.height<n.minHeight)&&(n.top=n.oldTop),n.width=Math.min(Math.max(n.width,n.minWidth),n.maxWidth),n.height=Math.min(Math.max(n.height,n.minHeight),n.maxHeight),this.limitCanvas(!1,!0),n.left=Math.min(Math.max(n.left,n.minLeft),n.maxLeft),n.top=Math.min(Math.max(n.top,n.minTop),n.maxTop),n.oldLeft=n.left,n.oldTop=n.top,lt(this.canvas,rt({width:n.width,height:n.height},Ht({translateX:n.left,translateY:n.top}))),this.renderImage(t),this.cropped&&this.limited&&this.limitCropBox(!0,!0)},renderImage:function(t){var e=this.canvasData,i=this.imageData,a=i.naturalWidth*(e.width/e.naturalWidth),n=i.naturalHeight*(e.height/e.naturalHeight);rt(i,{width:a,height:n,left:(e.width-a)/2,top:(e.height-n)/2}),lt(this.image,rt({width:i.width,height:i.height},Ht(rt({translateX:i.left,translateY:i.top},i)))),t&&this.output()},initCropBox:function(){var t=this.options,e=this.canvasData,i=t.aspectRatio||t.initialAspectRatio,a=Number(t.autoCropArea)||.8,t={width:e.width,height:e.height};i&&(e.height*i>e.width?t.height=t.width/i:t.width=t.height*i),this.cropBoxData=t,this.limitCropBox(!0,!0),t.width=Math.min(Math.max(t.width,t.minWidth),t.maxWidth),t.height=Math.min(Math.max(t.height,t.minHeight),t.maxHeight),t.width=Math.max(t.minWidth,t.width*a),t.height=Math.max(t.minHeight,t.height*a),t.left=e.left+(e.width-t.width)/2,t.top=e.top+(e.height-t.height)/2,t.oldLeft=t.left,t.oldTop=t.top,this.initialCropBoxData=rt({},t)},limitCropBox:function(t,e){var i,a,n=this.options,o=this.containerData,h=this.canvasData,r=this.cropBoxData,s=this.limited,c=n.aspectRatio;t&&(i=Number(n.minCropBoxWidth)||0,a=Number(n.minCropBoxHeight)||0,t=s?Math.min(o.width,h.width,h.width+h.left,o.width-h.left):o.width,n=s?Math.min(o.height,h.height,h.height+h.top,o.height-h.top):o.height,i=Math.min(i,o.width),a=Math.min(a,o.height),c&&(i&&a?i<a*c?a=i/c:i=a*c:i?a=i/c:a&&(i=a*c),t<n*c?n=t/c:t=n*c),r.minWidth=Math.min(i,t),r.minHeight=Math.min(a,n),r.maxWidth=t,r.maxHeight=n),e&&(s?(r.minLeft=Math.max(0,h.left),r.minTop=Math.max(0,h.top),r.maxLeft=Math.min(o.width,h.left+h.width)-r.width,r.maxTop=Math.min(o.height,h.top+h.height)-r.height):(r.minLeft=0,r.minTop=0,r.maxLeft=o.width-r.width,r.maxTop=o.height-r.height))},renderCropBox:function(){var t=this.options,e=this.containerData,i=this.cropBoxData;(i.width>i.maxWidth||i.width<i.minWidth)&&(i.left=i.oldLeft),(i.height>i.maxHeight||i.height<i.minHeight)&&(i.top=i.oldTop),i.width=Math.min(Math.max(i.width,i.minWidth),i.maxWidth),i.height=Math.min(Math.max(i.height,i.minHeight),i.maxHeight),this.limitCropBox(!1,!0),i.left=Math.min(Math.max(i.left,i.minLeft),i.maxLeft),i.top=Math.min(Math.max(i.top,i.minTop),i.maxTop),i.oldLeft=i.left,i.oldTop=i.top,t.movable&&t.cropBoxMovable&&wt(this.face,g,i.width>=e.width&&i.height>=e.height?E:k),lt(this.cropBox,rt({width:i.width,height:i.height},Ht({translateX:i.left,translateY:i.top}))),this.cropped&&this.limited&&this.limitCanvas(!0,!0),this.disabled||this.output()},output:function(){this.preview(),Bt(this.element,y,this.getData())}},St={initPreview:function(){var t=this.element,i=this.crossOrigin,e=this.options.preview,a=i?this.crossOriginUrl:this.url,n=t.alt||"The image to preview",o=document.createElement("img");i&&(o.crossOrigin=i),o.src=a,o.alt=n,this.viewBox.appendChild(o),this.viewBoxImage=o,e&&("string"==typeof(o=e)?o=t.ownerDocument.querySelectorAll(e):e.querySelector&&(o=[e]),ht(this.previews=o,function(t){var e=document.createElement("img");wt(t,f,{width:t.offsetWidth,height:t.offsetHeight,html:t.innerHTML}),i&&(e.crossOrigin=i),e.src=a,e.alt=n,e.style.cssText='display:block;width:100%;height:auto;min-width:0!important;min-height:0!important;max-width:none!important;max-height:none!important;image-orientation:0deg!important;"',t.innerHTML="",t.appendChild(e)}))},resetPreview:function(){ht(this.previews,function(t){var e=vt(t,f);lt(t,{width:e.width,height:e.height}),t.innerHTML=e.html,function(e,i){if(tt(e[i]))try{delete e[i]}catch(t){e[i]=void 0}else if(e.dataset)try{delete e.dataset[i]}catch(t){e.dataset[i]=void 0}else e.removeAttribute("data-".concat(ft(i)))}(t,f)})},preview:function(){var h=this.imageData,t=this.canvasData,e=this.cropBoxData,r=e.width,s=e.height,c=h.width,d=h.height,l=e.left-t.left-h.left,p=e.top-t.top-h.top;this.cropped&&!this.disabled&&(lt(this.viewBoxImage,rt({width:c,height:d},Ht(rt({translateX:-l,translateY:-p},h)))),ht(this.previews,function(t){var e=vt(t,f),i=e.width,a=e.height,n=i,o=a,e=1;r&&(o=s*(e=i/r)),s&&a<o&&(n=r*(e=a/s),o=a),lt(t,{width:n,height:o}),lt(t.getElementsByTagName("img")[0],rt({width:c*e,height:d*e},Ht(rt({translateX:-l*e,translateY:-p*e},h))))}))}},r={bind:function(){var t=this.element,e=this.options,i=this.cropper;at(e.cropstart)&&Dt(t,C,e.cropstart),at(e.cropmove)&&Dt(t,M,e.cropmove),at(e.cropend)&&Dt(t,x,e.cropend),at(e.crop)&&Dt(t,y,e.crop),at(e.zoom)&&Dt(t,U,e.zoom),Dt(i,j,this.onCropStart=this.cropStart.bind(this)),e.zoomable&&e.zoomOnWheel&&Dt(i,"wheel",this.onWheel=this.wheel.bind(this),{passive:!1,capture:!0}),e.toggleDragModeOnDblclick&&Dt(i,D,this.onDblclick=this.dblclick.bind(this)),Dt(t.ownerDocument,I,this.onCropMove=this.cropMove.bind(this)),Dt(t.ownerDocument,P,this.onCropEnd=this.cropEnd.bind(this)),e.responsive&&Dt(window,"resize",this.onResize=this.resize.bind(this))},unbind:function(){var t=this.element,e=this.options,i=this.cropper;at(e.cropstart)&&Ct(t,C,e.cropstart),at(e.cropmove)&&Ct(t,M,e.cropmove),at(e.cropend)&&Ct(t,x,e.cropend),at(e.crop)&&Ct(t,y,e.crop),at(e.zoom)&&Ct(t,U,e.zoom),Ct(i,j,this.onCropStart),e.zoomable&&e.zoomOnWheel&&Ct(i,"wheel",this.onWheel,{passive:!1,capture:!0}),e.toggleDragModeOnDblclick&&Ct(i,D,this.onDblclick),Ct(t.ownerDocument,I,this.onCropMove),Ct(t.ownerDocument,P,this.onCropEnd),e.responsive&&Ct(window,"resize",this.onResize)}},o={resize:function(){var t,e,i,a,n,o,h;this.disabled||(t=this.options,e=this.container,a=this.containerData,i=e.offsetWidth/a.width,a=e.offsetHeight/a.height,1!=(n=Math.abs(i-1)>Math.abs(a-1)?i:a)&&(t.restore&&(o=this.getCanvasData(),h=this.getCropBoxData()),this.render(),t.restore&&(this.setCanvasData(ht(o,function(t,e){o[e]=t*n})),this.setCropBoxData(ht(h,function(t,e){h[e]=t*n})))))},dblclick:function(){var t,e;this.disabled||this.options.dragMode===b||this.setDragMode((t=this.dragBox,e=s,(t.classList?t.classList.contains(e):-1<t.className.indexOf(e))?w:v))},wheel:function(t){var e=this,i=Number(this.options.wheelZoomRatio)||.1,a=1;this.disabled||(t.preventDefault(),this.wheeling||(this.wheeling=!0,setTimeout(function(){e.wheeling=!1},50),t.deltaY?a=0<t.deltaY?1:-1:t.wheelDelta?a=-t.wheelDelta/120:t.detail&&(a=0<t.detail?1:-1),this.zoom(-a*i,t)))},cropStart:function(t){var e,i=t.buttons,a=t.button;this.disabled||("mousedown"===t.type||"pointerdown"===t.type&&"mouse"===t.pointerType)&&(F(i)&&1!==i||F(a)&&0!==a||t.ctrlKey)||(a=this.options,e=this.pointers,t.changedTouches?ht(t.changedTouches,function(t){e[t.identifier]=Nt(t)}):e[t.pointerId||0]=Nt(t),a=1<Object.keys(e).length&&a.zoomable&&a.zoomOnTouch?W:vt(t.target,g),$.test(a)&&!1!==Bt(this.element,C,{originalEvent:t,action:a})&&(t.preventDefault(),this.action=a,this.cropping=!1,a===O&&(this.cropping=!0,pt(this.dragBox,m))))},cropMove:function(t){var e,i=this.action;!this.disabled&&i&&(e=this.pointers,t.preventDefault(),!1!==Bt(this.element,M,{originalEvent:t,action:i})&&(t.changedTouches?ht(t.changedTouches,function(t){rt(e[t.identifier]||{},Nt(t,!0))}):rt(e[t.pointerId||0]||{},Nt(t,!0)),this.change(t)))},cropEnd:function(t){var e,i;this.disabled||(e=this.action,i=this.pointers,t.changedTouches?ht(t.changedTouches,function(t){delete i[t.identifier]}):delete i[t.pointerId||0],e&&(t.preventDefault(),Object.keys(i).length||(this.action=""),this.cropping&&(this.cropping=!1,ut(this.dragBox,m,this.cropped&&this.options.modal)),Bt(this.element,x,{originalEvent:t,action:e})))}},t={change:function(t){var e=this.options,i=this.canvasData,a=this.containerData,n=this.cropBoxData,o=this.pointers,h=this.action,r=e.aspectRatio,s=n.left,c=n.top,d=n.width,l=n.height,p=s+d,m=c+l,u=0,g=0,f=a.width,v=a.height,w=!0;!r&&t.shiftKey&&(r=d&&l?d/l:1),this.limited&&(u=n.minLeft,g=n.minTop,f=u+Math.min(a.width,i.width,i.left+i.width),v=g+Math.min(a.height,i.height,i.top+i.height));function b(t){switch(t){case H:p+D.x>f&&(D.x=f-p);break;case N:s+D.x<u&&(D.x=u-s);break;case z:c+D.y<g&&(D.y=g-c);break;case L:m+D.y>v&&(D.y=v-m)}}var y,x,M,C=o[Object.keys(o)[0]],D={x:C.endX-C.startX,y:C.endY-C.startY};switch(h){case k:s+=D.x,c+=D.y;break;case H:if(0<=D.x&&(f<=p||r&&(c<=g||v<=m))){w=!1;break}b(H),(d+=D.x)<0&&(h=N,s-=d=-d),r&&(c+=(n.height-(l=d/r))/2);break;case z:if(D.y<=0&&(c<=g||r&&(s<=u||f<=p))){w=!1;break}b(z),l-=D.y,c+=D.y,l<0&&(h=L,c-=l=-l),r&&(s+=(n.width-(d=l*r))/2);break;case N:if(D.x<=0&&(s<=u||r&&(c<=g||v<=m))){w=!1;break}b(N),d-=D.x,s+=D.x,d<0&&(h=H,s-=d=-d),r&&(c+=(n.height-(l=d/r))/2);break;case L:if(0<=D.y&&(v<=m||r&&(s<=u||f<=p))){w=!1;break}b(L),(l+=D.y)<0&&(h=z,c-=l=-l),r&&(s+=(n.width-(d=l*r))/2);break;case Y:if(r){if(D.y<=0&&(c<=g||f<=p)){w=!1;break}b(z),l-=D.y,c+=D.y,d=l*r}else b(z),b(H),!(0<=D.x)||p<f?d+=D.x:D.y<=0&&c<=g&&(w=!1),D.y<=0&&!(g<c)||(l-=D.y,c+=D.y);d<0&&l<0?(h=S,c-=l=-l,s-=d=-d):d<0?(h=X,s-=d=-d):l<0&&(h=R,c-=l=-l);break;case X:if(r){if(D.y<=0&&(c<=g||s<=u)){w=!1;break}b(z),l-=D.y,c+=D.y,s+=n.width-(d=l*r)}else b(z),b(N),!(D.x<=0)||u<s?(d-=D.x,s+=D.x):D.y<=0&&c<=g&&(w=!1),D.y<=0&&!(g<c)||(l-=D.y,c+=D.y);d<0&&l<0?(h=R,c-=l=-l,s-=d=-d):d<0?(h=Y,s-=d=-d):l<0&&(h=S,c-=l=-l);break;case S:if(r){if(D.x<=0&&(s<=u||v<=m)){w=!1;break}b(N),d-=D.x,s+=D.x,l=d/r}else b(L),b(N),!(D.x<=0)||u<s?(d-=D.x,s+=D.x):0<=D.y&&v<=m&&(w=!1),0<=D.y&&!(m<v)||(l+=D.y);d<0&&l<0?(h=Y,c-=l=-l,s-=d=-d):d<0?(h=R,s-=d=-d):l<0&&(h=X,c-=l=-l);break;case R:if(r){if(0<=D.x&&(f<=p||v<=m)){w=!1;break}b(H),l=(d+=D.x)/r}else b(L),b(H),!(0<=D.x)||p<f?d+=D.x:0<=D.y&&v<=m&&(w=!1),0<=D.y&&!(m<v)||(l+=D.y);d<0&&l<0?(h=X,c-=l=-l,s-=d=-d):d<0?(h=S,s-=d=-d):l<0&&(h=Y,c-=l=-l);break;case E:this.move(D.x,D.y),w=!1;break;case W:this.zoom((x=B({},y=o),M=0,ht(y,function(n,t){delete x[t],ht(x,function(t){var e=Math.abs(n.startX-t.startX),i=Math.abs(n.startY-t.startY),a=Math.abs(n.endX-t.endX),t=Math.abs(n.endY-t.endY),i=Math.sqrt(e*e+i*i),i=(Math.sqrt(a*a+t*t)-i)/i;Math.abs(i)>Math.abs(M)&&(M=i)})}),M),t),w=!1;break;case O:if(!D.x||!D.y){w=!1;break}y=kt(this.cropper),s=C.startX-y.left,c=C.startY-y.top,d=n.minWidth,l=n.minHeight,0<D.x?h=0<D.y?R:Y:D.x<0&&(s-=d,h=0<D.y?S:X),D.y<0&&(c-=l),this.cropped||(mt(this.cropBox,A),this.cropped=!0,this.limited&&this.limitCropBox(!0,!0))}w&&(n.width=d,n.height=l,n.left=s,n.top=c,this.action=h,this.renderCropBox()),ht(o,function(t){t.startX=t.endX,t.startY=t.endY})}},At={crop:function(){return!this.ready||this.cropped||this.disabled||(this.cropped=!0,this.limitCropBox(!0,!0),this.options.modal&&pt(this.dragBox,m),mt(this.cropBox,A),this.setCropBoxData(this.initialCropBoxData)),this},reset:function(){return this.ready&&!this.disabled&&(this.imageData=rt({},this.initialImageData),this.canvasData=rt({},this.initialCanvasData),this.cropBoxData=rt({},this.initialCropBoxData),this.renderCanvas(),this.cropped&&this.renderCropBox()),this},clear:function(){return this.cropped&&!this.disabled&&(rt(this.cropBoxData,{left:0,top:0,width:0,height:0}),this.cropped=!1,this.renderCropBox(),this.limitCanvas(!0,!0),this.renderCanvas(),mt(this.dragBox,m),pt(this.cropBox,A)),this},replace:function(e){var t=1<arguments.length&&void 0!==arguments[1]&&arguments[1];return!this.disabled&&e&&(this.isImg&&(this.element.src=e),t?(this.url=e,this.image.src=e,this.ready&&(this.viewBoxImage.src=e,ht(this.previews,function(t){t.getElementsByTagName("img")[0].src=e}))):(this.isImg&&(this.replaced=!0),this.options.data=null,this.uncreate(),this.load(e))),this},enable:function(){return this.ready&&this.disabled&&(this.disabled=!1,mt(this.cropper,d)),this},disable:function(){return this.ready&&!this.disabled&&(this.disabled=!0,pt(this.cropper,d)),this},destroy:function(){var t=this.element;return t[c]&&(t[c]=void 0,this.isImg&&this.replaced&&(t.src=this.originalUrl),this.uncreate()),this},move:function(t){var e=1<arguments.length&&void 0!==arguments[1]?arguments[1]:t,i=this.canvasData,a=i.left,i=i.top;return this.moveTo(_(t)?t:a+Number(t),_(e)?e:i+Number(e))},moveTo:function(t){var e=1<arguments.length&&void 0!==arguments[1]?arguments[1]:t,i=this.canvasData,a=!1;return t=Number(t),e=Number(e),this.ready&&!this.disabled&&this.options.movable&&(F(t)&&(i.left=t,a=!0),F(e)&&(i.top=e,a=!0),a&&this.renderCanvas(!0)),this},zoom:function(t,e){var i=this.canvasData;return t=Number(t),this.zoomTo(i.width*(t=t<0?1/(1-t):1+t)/i.naturalWidth,null,e)},zoomTo:function(t,e,i){var a,n,o,h=this.options,r=this.canvasData,s=r.width,c=r.height,d=r.naturalWidth,l=r.naturalHeight;if(0<=(t=Number(t))&&this.ready&&!this.disabled&&h.zoomable){h=d*t,l=l*t;if(!1===Bt(this.element,U,{ratio:t,oldRatio:s/d,originalEvent:i}))return this;i?(t=this.pointers,d=kt(this.cropper),i=t&&Object.keys(t).length?(o=n=a=0,ht(t,function(t){var e=t.startX,t=t.startY;a+=e,n+=t,o+=1}),{pageX:a/=o,pageY:n/=o}):{pageX:i.pageX,pageY:i.pageY},r.left-=(h-s)*((i.pageX-d.left-r.left)/s),r.top-=(l-c)*((i.pageY-d.top-r.top)/c)):it(e)&&F(e.x)&&F(e.y)?(r.left-=(h-s)*((e.x-r.left)/s),r.top-=(l-c)*((e.y-r.top)/c)):(r.left-=(h-s)/2,r.top-=(l-c)/2),r.width=h,r.height=l,this.renderCanvas(!0)}return this},rotate:function(t){return this.rotateTo((this.imageData.rotate||0)+Number(t))},rotateTo:function(t){return F(t=Number(t))&&this.ready&&!this.disabled&&this.options.rotatable&&(this.imageData.rotate=t%360,this.renderCanvas(!0,!0)),this},scaleX:function(t){var e=this.imageData.scaleY;return this.scale(t,F(e)?e:1)},scaleY:function(t){var e=this.imageData.scaleX;return this.scale(F(e)?e:1,t)},scale:function(t){var e=1<arguments.length&&void 0!==arguments[1]?arguments[1]:t,i=this.imageData,a=!1;return t=Number(t),e=Number(e),this.ready&&!this.disabled&&this.options.scalable&&(F(t)&&(i.scaleX=t,a=!0),F(e)&&(i.scaleY=e,a=!0),a&&this.renderCanvas(!0,!0)),this},getData:function(){var i,a,t=0<arguments.length&&void 0!==arguments[0]&&arguments[0],e=this.options,n=this.imageData,o=this.canvasData,h=this.cropBoxData;return this.ready&&this.cropped?(i={x:h.left-o.left,y:h.top-o.top,width:h.width,height:h.height},a=n.width/n.naturalWidth,ht(i,function(t,e){i[e]=t/a}),t&&(h=Math.round(i.y+i.height),t=Math.round(i.x+i.width),i.x=Math.round(i.x),i.y=Math.round(i.y),i.width=t-i.x,i.height=h-i.y)):i={x:0,y:0,width:0,height:0},e.rotatable&&(i.rotate=n.rotate||0),e.scalable&&(i.scaleX=n.scaleX||1,i.scaleY=n.scaleY||1),i},setData:function(t){var e,i=this.options,a=this.imageData,n=this.canvasData,o={};return this.ready&&!this.disabled&&it(t)&&(e=!1,i.rotatable&&F(t.rotate)&&t.rotate!==a.rotate&&(a.rotate=t.rotate,e=!0),i.scalable&&(F(t.scaleX)&&t.scaleX!==a.scaleX&&(a.scaleX=t.scaleX,e=!0),F(t.scaleY)&&t.scaleY!==a.scaleY&&(a.scaleY=t.scaleY,e=!0)),e&&this.renderCanvas(!0,!0),a=a.width/a.naturalWidth,F(t.x)&&(o.left=t.x*a+n.left),F(t.y)&&(o.top=t.y*a+n.top),F(t.width)&&(o.width=t.width*a),F(t.height)&&(o.height=t.height*a),this.setCropBoxData(o)),this},getContainerData:function(){return this.ready?rt({},this.containerData):{}},getImageData:function(){return this.sized?rt({},this.imageData):{}},getCanvasData:function(){var e=this.canvasData,i={};return this.ready&&ht(["left","top","width","height","naturalWidth","naturalHeight"],function(t){i[t]=e[t]}),i},setCanvasData:function(t){var e=this.canvasData,i=e.aspectRatio;return this.ready&&!this.disabled&&it(t)&&(F(t.left)&&(e.left=t.left),F(t.top)&&(e.top=t.top),F(t.width)?(e.width=t.width,e.height=t.width/i):F(t.height)&&(e.height=t.height,e.width=t.height*i),this.renderCanvas(!0)),this},getCropBoxData:function(){var t,e=this.cropBoxData;return(t=this.ready&&this.cropped?{left:e.left,top:e.top,width:e.width,height:e.height}:t)||{}},setCropBoxData:function(t){var e,i,a=this.cropBoxData,n=this.options.aspectRatio;return this.ready&&this.cropped&&!this.disabled&&it(t)&&(F(t.left)&&(a.left=t.left),F(t.top)&&(a.top=t.top),F(t.width)&&t.width!==a.width&&(e=!0,a.width=t.width),F(t.height)&&t.height!==a.height&&(i=!0,a.height=t.height),n&&(e?a.height=a.width/n:i&&(a.width=a.height*n)),this.renderCropBox()),this},getCroppedCanvas:function(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:{};if(!this.ready||!window.HTMLCanvasElement)return null;var e,i,a,n,o,h,r,s,c,d,l,p,m,u=this.canvasData,h=(w=this.image,e=this.imageData,i=u,y=t,a=e.aspectRatio,n=e.naturalWidth,b=e.naturalHeight,o=void 0===(m=e.rotate)?0:m,h=void 0===(v=e.scaleX)?1:v,g=void 0===(l=e.scaleY)?1:l,r=i.aspectRatio,s=i.naturalWidth,c=i.naturalHeight,d=void 0===(p=y.fillColor)?"transparent":p,x=y.imageSmoothingEnabled,f=void 0===x||x,v=void 0===(m=y.imageSmoothingQuality)?"low":m,l=void 0===(e=y.maxWidth)?1/0:e,p=void 0===(i=y.maxHeight)?1/0:i,m=void 0===(x=y.minWidth)?0:x,i=void 0===(e=y.minHeight)?0:e,y=(x=document.createElement("canvas")).getContext("2d"),e=Lt({aspectRatio:r,width:l,height:p}),r=Lt({aspectRatio:r,width:m,height:i},"cover"),s=Math.min(e.width,Math.max(r.width,s)),c=Math.min(e.height,Math.max(r.height,c)),p=Lt({aspectRatio:a,width:l,height:p}),i=Lt({aspectRatio:a,width:m,height:i},"cover"),n=Math.min(p.width,Math.max(i.width,n)),b=Math.min(p.height,Math.max(i.height,b)),b=[-n/2,-b/2,n,b],x.width=ct(s),x.height=ct(c),y.fillStyle=d,y.fillRect(0,0,s,c),y.save(),y.translate(s/2,c/2),y.rotate(o*Math.PI/180),y.scale(h,g),y.imageSmoothingEnabled=f,y.imageSmoothingQuality=v,y.drawImage.apply(y,[w].concat(T(b.map(function(t){return Math.floor(ct(t))})))),y.restore(),x);if(!this.cropped)return h;var g=this.getData(),f=g.x,v=g.y,w=g.width,b=g.height,y=h.width/Math.floor(u.naturalWidth);1!=y&&(f*=y,v*=y,w*=y,b*=y);var x=w/b,g=Lt({aspectRatio:x,width:t.maxWidth||1/0,height:t.maxHeight||1/0}),u=Lt({aspectRatio:x,width:t.minWidth||0,height:t.minHeight||0},"cover"),x=Lt({aspectRatio:x,width:t.width||(1!=y?h.width:w),height:t.height||(1!=y?h.height:b)}),y=x.width,x=x.height,y=Math.min(g.width,Math.max(u.width,y)),x=Math.min(g.height,Math.max(u.height,x)),g=document.createElement("canvas"),u=g.getContext("2d");g.width=ct(y),g.height=ct(x),u.fillStyle=t.fillColor||"transparent",u.fillRect(0,0,y,x);x=t.imageSmoothingEnabled,t=t.imageSmoothingQuality;u.imageSmoothingEnabled=void 0===x||x,t&&(u.imageSmoothingQuality=t);var M,C,D,B,k,x=h.width,t=h.height,f=f,v=v;f<=-w||x<f?B=C=M=f=0:f<=0?(C=-f,f=0,B=M=Math.min(x,w+f)):f<=x&&(C=0,B=M=Math.min(w,x-f)),M<=0||v<=-b||t<v?k=D=O=v=0:v<=0?(D=-v,v=0,k=O=Math.min(t,b+v)):v<=t&&(D=0,k=O=Math.min(b,t-v));var O=[f,v,M,O];return 0<B&&0<k&&O.push(C*(w=y/w),D*w,B*w,k*w),u.drawImage.apply(u,[h].concat(T(O.map(function(t){return Math.floor(ct(t))})))),g},setAspectRatio:function(t){var e=this.options;return this.disabled||_(t)||(e.aspectRatio=Math.max(0,t)||NaN,this.ready&&(this.initCropBox(),this.cropped&&this.renderCropBox())),this},setDragMode:function(t){var e,i,a=this.options,n=this.dragBox,o=this.face;return this.ready&&!this.disabled&&(i=a.movable&&t===w,a.dragMode=t=(e=t===v)||i?t:b,wt(n,g,t),ut(n,s,e),ut(n,u,i),a.cropBoxMovable||(wt(o,g,t),ut(o,s,e),ut(o,u,i))),this}},jt=h.Cropper,It=function(){function i(t){var e=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{};if(!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,i),!t||!Z.test(t.tagName))throw new Error("The first argument is required and must be an <img> or <canvas> element.");this.element=t,this.options=rt({},G,it(e)&&e),this.cropped=!1,this.disabled=!1,this.pointers={},this.ready=!1,this.reloading=!1,this.replaced=!1,this.sized=!1,this.sizing=!1,this.init()}var t,e,a;return t=i,a=[{key:"noConflict",value:function(){return window.Cropper=jt,i}},{key:"setDefaults",value:function(t){rt(G,it(t)&&t)}}],(e=[{key:"init",value:function(){var t,e=this.element,i=e.tagName.toLowerCase();if(!e[c]){if(e[c]=this,"img"===i){if(this.isImg=!0,t=e.getAttribute("src")||"",!(this.originalUrl=t))return;t=e.src}else"canvas"===i&&window.HTMLCanvasElement&&(t=e.toDataURL());this.load(t)}}},{key:"load",value:function(t){var e,i,a,n,o,h,r=this;t&&(this.url=t,this.imageData={},e=this.element,(i=this.options).rotatable||i.scalable||(i.checkOrientation=!1),i.checkOrientation&&window.ArrayBuffer?Q.test(t)?K.test(t)?this.read((h=(h=t).replace(Yt,""),a=atob(h),h=new ArrayBuffer(a.length),ht(n=new Uint8Array(h),function(t,e){n[e]=a.charCodeAt(e)}),h)):this.clone():(o=new XMLHttpRequest,h=this.clone.bind(this),this.reloading=!0,(this.xhr=o).onabort=h,o.onerror=h,o.ontimeout=h,o.onprogress=function(){o.getResponseHeader("content-type")!==q&&o.abort()},o.onload=function(){r.read(o.response)},o.onloadend=function(){r.reloading=!1,r.xhr=null},i.checkCrossOrigin&&Et(t)&&e.crossOrigin&&(t=Wt(t)),o.open("GET",t,!0),o.responseType="arraybuffer",o.withCredentials="use-credentials"===e.crossOrigin,o.send()):this.clone())}},{key:"read",value:function(t){var e=this.options,i=this.imageData,a=Xt(t),n=0,o=1,h=1;1<a&&(this.url=function(t,e){for(var i=[],a=new Uint8Array(t);0<a.length;)i.push(zt.apply(null,ot(a.subarray(0,8192)))),a=a.subarray(8192);return"data:".concat(e,";base64,").concat(btoa(i.join("")))}(t,q),n=(a=function(t){var e=0,i=1,a=1;switch(t){case 2:i=-1;break;case 3:e=-180;break;case 4:a=-1;break;case 5:e=90,a=-1;break;case 6:e=90;break;case 7:e=90,i=-1;break;case 8:e=-90}return{rotate:e,scaleX:i,scaleY:a}}(a)).rotate,o=a.scaleX,h=a.scaleY),e.rotatable&&(i.rotate=n),e.scalable&&(i.scaleX=o,i.scaleY=h),this.clone()}},{key:"clone",value:function(){var t=this.element,e=this.url,i=t.crossOrigin,a=e;this.options.checkCrossOrigin&&Et(e)&&(i=i||"anonymous",a=Wt(e)),this.crossOrigin=i,this.crossOriginUrl=a;var n=document.createElement("img");i&&(n.crossOrigin=i),n.src=a||e,n.alt=t.alt||"The image to crop",(this.image=n).onload=this.start.bind(this),n.onerror=this.stop.bind(this),pt(n,l),t.parentNode.insertBefore(n,t.nextSibling)}},{key:"start",value:function(){var i=this,t=this.image;t.onload=null,t.onerror=null,this.sizing=!0;function e(t,e){rt(i.imageData,{naturalWidth:t,naturalHeight:e,aspectRatio:t/e}),i.initialImageData=rt({},i.imageData),i.sizing=!1,i.sized=!0,i.build()}var a,n,o=h.navigator&&/(?:iPad|iPhone|iPod).*?AppleWebKit/i.test(h.navigator.userAgent);!t.naturalWidth||o?(a=document.createElement("img"),n=document.body||document.documentElement,(this.sizingImage=a).onload=function(){e(a.width,a.height),o||n.removeChild(a)},a.src=t.src,o||(a.style.cssText="left:0;max-height:none!important;max-width:none!important;min-height:0!important;min-width:0!important;opacity:0;position:absolute;top:0;z-index:-1;",n.appendChild(a))):e(t.naturalWidth,t.naturalHeight)}},{key:"stop",value:function(){var t=this.image;t.onload=null,t.onerror=null,t.parentNode.removeChild(t),this.image=null}},{key:"build",value:function(){var t,e,i,a,n,o,h,r,s;this.sized&&!this.ready&&(t=this.element,e=this.options,i=this.image,a=t.parentNode,(s=document.createElement("div")).innerHTML='<div class="cropper-container" touch-action="none"><div class="cropper-wrap-box"><div class="cropper-canvas"></div></div><div class="cropper-drag-box"></div><div class="cropper-crop-box"><span class="cropper-view-box"></span><span class="cropper-dashed dashed-h"></span><span class="cropper-dashed dashed-v"></span><span class="cropper-center"></span><span class="cropper-face"></span><span class="cropper-line line-e" data-cropper-action="e"></span><span class="cropper-line line-n" data-cropper-action="n"></span><span class="cropper-line line-w" data-cropper-action="w"></span><span class="cropper-line line-s" data-cropper-action="s"></span><span class="cropper-point point-e" data-cropper-action="e"></span><span class="cropper-point point-n" data-cropper-action="n"></span><span class="cropper-point point-w" data-cropper-action="w"></span><span class="cropper-point point-s" data-cropper-action="s"></span><span class="cropper-point point-ne" data-cropper-action="ne"></span><span class="cropper-point point-nw" data-cropper-action="nw"></span><span class="cropper-point point-sw" data-cropper-action="sw"></span><span class="cropper-point point-se" data-cropper-action="se"></span></div></div>',o=(n=s.querySelector(".".concat(c,"-container"))).querySelector(".".concat(c,"-canvas")),h=n.querySelector(".".concat(c,"-drag-box")),s=(r=n.querySelector(".".concat(c,"-crop-box"))).querySelector(".".concat(c,"-face")),this.container=a,this.cropper=n,this.canvas=o,this.dragBox=h,this.cropBox=r,this.viewBox=n.querySelector(".".concat(c,"-view-box")),this.face=s,o.appendChild(i),pt(t,A),a.insertBefore(n,t.nextSibling),this.isImg||mt(i,l),this.initPreview(),this.bind(),e.initialAspectRatio=Math.max(0,e.initialAspectRatio)||NaN,e.aspectRatio=Math.max(0,e.aspectRatio)||NaN,e.viewMode=Math.max(0,Math.min(3,Math.round(e.viewMode)))||0,pt(r,A),e.guides||pt(r.getElementsByClassName("".concat(c,"-dashed")),A),e.center||pt(r.getElementsByClassName("".concat(c,"-center")),A),e.background&&pt(n,"".concat(c,"-bg")),e.highlight||pt(s,p),e.cropBoxMovable&&(pt(s,u),wt(s,g,k)),e.cropBoxResizable||(pt(r.getElementsByClassName("".concat(c,"-line")),A),pt(r.getElementsByClassName("".concat(c,"-point")),A)),this.render(),this.ready=!0,this.setDragMode(e.dragMode),e.autoCrop&&this.crop(),this.setData(e.data),at(e.ready)&&Dt(t,"ready",e.ready,{once:!0}),Bt(t,"ready"))}},{key:"unbuild",value:function(){this.ready&&(this.ready=!1,this.unbind(),this.resetPreview(),this.cropper.parentNode.removeChild(this.cropper),mt(this.element,A))}},{key:"uncreate",value:function(){this.ready?(this.unbuild(),this.ready=!1,this.cropped=!1):this.sizing?(this.sizingImage.onload=null,this.sizing=!1,this.sized=!1):this.reloading?(this.xhr.onabort=null,this.xhr.abort()):this.image&&this.stop()}}])&&n(t.prototype,e),a&&n(t,a),i}();return rt(It.prototype,Rt,St,r,o,t,At),It});
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/cxselect/jquery.cxselect.js b/ruoyi-admin/src/main/resources/static/ajax/libs/cxselect/jquery.cxselect.js
new file mode 100644
index 0000000..05e26af
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/cxselect/jquery.cxselect.js
@@ -0,0 +1,406 @@
+/*!
+ * jQuery cxSelect
+ * @name jquery.cxselect.js
+ * @version 1.4.2
+ * @date 2017-09-26
+ * @author ciaoca
+ * @email ciaoca@gmail.com
+ * @site https://github.com/ciaoca/cxSelect
+ * @license Released under the MIT license
+ */
+(function(factory) {
+  if (typeof define === 'function' && define.amd) {
+    define(['jquery'], factory);
+  } else {
+    factory(window.jQuery || window.Zepto || window.$);
+  };
+}(function($) {
+  var cxSelect = function() {
+    var self = this;
+    var dom, settings, callback;
+
+    // 分配参数
+    for (var i = 0, l = arguments.length; i < l; i++) {
+      if (cxSelect.isJquery(arguments[i]) || cxSelect.isZepto(arguments[i])) {
+        dom = arguments[i];
+      } else if (cxSelect.isElement(arguments[i])) {
+        dom = $(arguments[i]);
+      } else if (typeof arguments[i] === 'function') {
+        callback = arguments[i];
+      } else if (typeof arguments[i] === 'object') {
+        settings = arguments[i];
+      };
+    };
+
+    var api = new cxSelect.init(dom, settings);
+
+    if (typeof callback === 'function') {
+      callback(api);
+    };
+
+    return api;
+  };
+
+  cxSelect.isElement = function(o){
+    if (o && (typeof HTMLElement === 'function' || typeof HTMLElement === 'object') && o instanceof HTMLElement) {
+      return true;
+    } else {
+      return (o && o.nodeType && o.nodeType === 1) ? true : false;
+    };
+  };
+
+  cxSelect.isJquery = function(o){
+    return (o && o.length && (typeof jQuery === 'function' || typeof jQuery === 'object') && o instanceof jQuery) ? true : false;
+  };
+
+  cxSelect.isZepto = function(o){
+    return (o && o.length && (typeof Zepto === 'function' || typeof Zepto === 'object') && Zepto.zepto.isZ(o)) ? true : false;
+  };
+
+  cxSelect.getIndex = function(n, required) {
+    return required ? n : n - 1;
+  };
+
+  cxSelect.getData = function(data, space) {
+    if (typeof space === 'string' && space.length) {
+      space = space.split('.');
+      for (var i = 0, l = space.length; i < l; i++) {
+        data = data[space[i]];
+      };
+    };
+    return data;
+  };
+
+  cxSelect.init = function(dom, settings) {
+    var self = this;
+
+    if (!cxSelect.isJquery(dom) && !cxSelect.isZepto(dom)) {return};
+
+    var theSelect = {
+      dom: {
+        box: dom
+      }
+    };
+
+    self.attach = cxSelect.attach.bind(theSelect);
+    self.detach = cxSelect.detach.bind(theSelect);
+    self.setOptions = cxSelect.setOptions.bind(theSelect);
+    self.clear = cxSelect.clear.bind(theSelect);
+
+    theSelect.changeEvent = function() {
+      cxSelect.selectChange.call(theSelect, this.className);
+    };
+
+    theSelect.settings = $.extend({}, $.cxSelect.defaults, settings, {
+      url: theSelect.dom.box.data('url'),
+      emptyStyle: theSelect.dom.box.data('emptyStyle'),
+      required: theSelect.dom.box.data('required'),
+      firstTitle: theSelect.dom.box.data('firstTitle'),
+      firstValue: theSelect.dom.box.data('firstValue'),
+      jsonSpace: theSelect.dom.box.data('jsonSpace'),
+      jsonName: theSelect.dom.box.data('jsonName'),
+      jsonValue: theSelect.dom.box.data('jsonValue'),
+      jsonSub: theSelect.dom.box.data('jsonSub')
+    });
+
+    var _dataSelects = theSelect.dom.box.data('selects');
+
+    if (typeof _dataSelects === 'string' && _dataSelects.length) {
+      theSelect.settings.selects = _dataSelects.split(',');
+    };
+
+    self.setOptions();
+    self.attach();
+
+    // 使用独立接口获取数据
+    if (!theSelect.settings.url && !theSelect.settings.data) {
+      cxSelect.start.apply(theSelect);
+
+    // 设置自定义数据
+    } else if ($.isArray(theSelect.settings.data)) {
+      cxSelect.start.call(theSelect, theSelect.settings.data);
+
+    // 设置 URL,通过 Ajax 获取数据
+    } else if (typeof theSelect.settings.url === 'string' && theSelect.settings.url.length) {
+      $.getJSON(theSelect.settings.url, function(json) {
+        cxSelect.start.call(theSelect, json);
+      });
+    };
+  };
+
+  // 设置参数
+  cxSelect.setOptions = function(opts) {
+    var self = this;
+
+    if (opts) {
+      $.extend(self.settings, opts);
+    };
+
+    // 初次或重设选择器组
+    if (!$.isArray(self.selectArray) || !self.selectArray.length || (opts && opts.selects)) {
+      self.selectArray = [];
+
+      if ($.isArray(self.settings.selects) && self.settings.selects.length) {
+        var _tempSelect;
+
+        for (var i = 0, l = self.settings.selects.length; i < l; i++) {
+          _tempSelect = self.dom.box.find('select.' + self.settings.selects[i]);
+
+          if (!_tempSelect || !_tempSelect.length) {break};
+
+          self.selectArray.push(_tempSelect);
+        };
+      };
+    };
+
+    if (opts) {
+      if (!$.isArray(opts.data) && typeof opts.url === 'string' && opts.url.length) {
+        $.getJSON(self.settings.url, function(json) {
+          cxSelect.start.call(self, json);
+        });
+
+      } else {
+        cxSelect.start.call(self, opts.data);
+      };
+    };
+  };
+
+  // 绑定
+  cxSelect.attach = function() {
+    var self = this;
+
+    if (!self.attachStatus) {
+      self.dom.box.on('change', 'select', self.changeEvent);
+    };
+
+    if (typeof self.attachStatus === 'boolean') {
+      cxSelect.start.call(self);
+    };
+
+    self.attachStatus = true;
+  };
+
+  // 移除绑定
+  cxSelect.detach = function() {
+    var self = this;
+    self.dom.box.off('change', 'select', self.changeEvent);
+    self.attachStatus = false;
+  };
+
+  // 清空选项
+  cxSelect.clear = function(index) {
+    var self = this;
+    var _style = {
+      display: '',
+      visibility: ''
+    };
+
+    index = isNaN(index) ? 0 : index;
+
+    // 清空后面的 select
+    for (var i = index, l = self.selectArray.length; i < l; i++) {
+      self.selectArray[i].empty().prop('disabled', true);
+
+      if (self.settings.emptyStyle === 'none') {
+        _style.display = 'none';
+      } else if (self.settings.emptyStyle === 'hidden') {
+        _style.visibility = 'hidden';
+      };
+
+      self.selectArray[i].css(_style);
+    };
+  };
+
+  cxSelect.start = function(data) {
+    var self = this;
+
+    if ($.isArray(data)) {
+      self.settings.data = cxSelect.getData(data, self.settings.jsonSpace);
+    };
+
+    if (!self.selectArray.length) {return};
+
+    // 保存默认值
+    for (var i = 0, l = self.selectArray.length; i < l; i++) {
+      if (typeof self.selectArray[i].attr('data-value') !== 'string' && self.selectArray[i][0].options.length) {
+        self.selectArray[i].attr('data-value', self.selectArray[i].val());
+      };
+    };
+
+    if (self.settings.data || (typeof self.selectArray[0].data('url') === 'string' && self.selectArray[0].data('url').length)) {
+      cxSelect.getOptionData.call(self, 0);
+    } else if (self.selectArray[0][0].options.length && typeof self.selectArray[0].attr('data-value') === 'string' && self.selectArray[0].attr('data-value').length) {
+      self.selectArray[0].val(self.selectArray[0].attr('data-value'));
+      cxSelect.getOptionData.call(self, 1);
+    } else {
+      self.selectArray[0].prop('disabled', false).css({
+        'display': '',
+        'visibility': ''
+      });
+    };
+  };
+
+  // 获取选项数据
+  cxSelect.getOptionData = function(index) {
+    var self = this;
+
+    if (typeof index !== 'number' || isNaN(index) || index < 0 || index >= self.selectArray.length) {return};
+
+    var _indexPrev = index - 1;
+    var _select = self.selectArray[index];
+    var _selectData;
+    var _valueIndex;
+    var _dataUrl = _select.data('url');
+    var _jsonSpace = typeof _select.data('jsonSpace') === 'undefined' ? self.settings.jsonSpace : _select.data('jsonSpace');
+    var _query = {};
+    var _queryName;
+    var _selectName;
+    var _selectValue;
+
+    cxSelect.clear.call(self, index);
+
+    // 使用独立接口
+    if (typeof _dataUrl === 'string' && _dataUrl.length) {
+      if (index > 0) {
+        for (var i = 0, j = 1; i < index; i++, j++) {
+          _queryName = self.selectArray[j].data('queryName');
+          _selectName = self.selectArray[i].attr('name');
+          _selectValue = self.selectArray[i].val();
+
+          if (typeof _queryName === 'string' && _queryName.length) {
+            _query[_queryName] = _selectValue;
+          } else if (typeof _selectName === 'string' && _selectName.length) {
+            _query[_selectName] = _selectValue;
+          };
+        };
+      };
+
+      $.getJSON(_dataUrl, _query, function(json) {
+        _selectData = cxSelect.getData(json, _jsonSpace);
+
+        cxSelect.buildOption.call(self, index, _selectData);
+      });
+
+    // 使用整合数据
+    } else if (self.settings.data && typeof self.settings.data === 'object') {
+      _selectData = self.settings.data;
+
+      for (var i = 0; i < index; i++) {
+        _valueIndex = cxSelect.getIndex(self.selectArray[i][0].selectedIndex, typeof self.selectArray[i].data('required') === 'boolean' ? self.selectArray[i].data('required') : self.settings.required);
+
+        if (typeof _selectData[_valueIndex] === 'object' && $.isArray(_selectData[_valueIndex][self.settings.jsonSub]) && _selectData[_valueIndex][self.settings.jsonSub].length) {
+          _selectData = _selectData[_valueIndex][self.settings.jsonSub];
+        } else {
+          _selectData = null;
+          break;
+        };
+      };
+
+      cxSelect.buildOption.call(self, index, _selectData);
+    };
+  };
+
+  // 构建选项列表
+  cxSelect.buildOption = function(index, data) {
+    var self = this;
+
+    var _select = self.selectArray[index];
+    var _required = typeof _select.data('required') === 'boolean' ? _select.data('required') : self.settings.required;
+    var _firstTitle = typeof _select.data('firstTitle') === 'undefined' ? self.settings.firstTitle : _select.data('firstTitle');
+    var _firstValue = typeof _select.data('firstValue') === 'undefined' ? self.settings.firstValue : _select.data('firstValue');
+    var _jsonName = typeof _select.data('jsonName') === 'undefined' ? self.settings.jsonName : _select.data('jsonName');
+    var _jsonValue = typeof _select.data('jsonValue') === 'undefined' ? self.settings.jsonValue : _select.data('jsonValue');
+
+    if (!$.isArray(data)) {return};
+
+    var _html = !_required ? '<option value="' + String(_firstValue) + '">' + String(_firstTitle) + '</option>' : '';
+
+    // 区分标题、值的数据
+    if (typeof _jsonName === 'string' && _jsonName.length) {
+      // 无值字段时使用标题作为值
+      if (typeof _jsonValue !== 'string' || !_jsonValue.length) {
+        _jsonValue = _jsonName;
+      };
+
+      for (var i = 0, l = data.length; i < l; i++) {
+        _html += '<option value="' + String(data[i][_jsonValue]) + '">' + String(data[i][_jsonName]) + '</option>';
+      };
+
+    // 数组即为值的数据
+    } else {
+      for (var i = 0, l = data.length; i < l; i++) {
+        _html += '<option value="' + String(data[i]) + '">' + String(data[i]) + '</option>';
+      };
+    };
+
+    _select.html(_html).prop('disabled', false).css({
+      'display': '',
+      'visibility': ''
+    });
+
+    // 初次加载设置默认值
+    if (typeof _select.attr('data-value') === 'string') {
+      _select.val(String(_select.attr('data-value'))).removeAttr('data-value');
+
+      if (_select[0].selectedIndex < 0) {
+        _select[0].options[0].selected = true;
+      };
+    };
+
+    if (_required || _select[0].selectedIndex > 0) {
+      _select.trigger('change');
+    };
+
+  };
+
+  // 改变选择时的处理
+  cxSelect.selectChange = function(name) {
+    var self = this;
+
+    if (typeof name !== 'string' || !name.length) {return};
+
+    var index;
+
+    name = name.replace(/\s+/g, ',');
+    name = ',' + name + ',';
+
+    // 获取当前 select 位置
+    for (var i = 0, l = self.selectArray.length; i < l; i++) {
+      if (name.indexOf(',' + self.settings.selects[i] + ',') > -1) {
+        index = i;
+        break;
+      };
+    };
+
+    if (typeof index === 'number' && index > -1) {
+      index += 1;
+      cxSelect.getOptionData.call(self, index);
+    };
+  };
+
+  $.cxSelect = function() {
+    return cxSelect.apply(this, arguments);
+  };
+
+  // 默认值
+  $.cxSelect.defaults = {
+    selects: [],            // 下拉选框组
+    url: null,              // 列表数据文件路径(URL)或数组数据
+    data: null,             // 自定义数据
+    emptyStyle: null,       // 无数据状态显示方式
+    required: false,        // 是否为必选
+    firstTitle: '请选择',    // 第一个选项的标题
+    firstValue: '',         // 第一个选项的值
+    jsonSpace: '',          // 数据命名空间
+    jsonName: 'n',          // 数据标题字段名称
+    jsonValue: '',          // 数据值字段名称
+    jsonSub: 's'            // 子集数据字段名称
+  };
+
+  $.fn.cxSelect = function(settings, callback) {
+    this.each(function(i) {
+      $.cxSelect(this, settings, callback);
+    });
+    return this;
+  };
+}));
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/cxselect/jquery.cxselect.min.js b/ruoyi-admin/src/main/resources/static/ajax/libs/cxselect/jquery.cxselect.min.js
new file mode 100644
index 0000000..85433a1
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/cxselect/jquery.cxselect.min.js
@@ -0,0 +1,11 @@
+/*!
+ * jQuery cxSelect
+ * @name jquery.cxselect.js
+ * @version 1.4.2
+ * @date 2017-09-26
+ * @author ciaoca
+ * @email ciaoca@gmail.com
+ * @site https://github.com/ciaoca/cxSelect
+ * @license Released under the MIT license
+ */
+!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):a(window.jQuery||window.Zepto||window.$)}(function(a){var b=function(){var d,e,f,g,h,i;for(g=0,h=arguments.length;h>g;g++)b.isJquery(arguments[g])||b.isZepto(arguments[g])?d=arguments[g]:b.isElement(arguments[g])?d=a(arguments[g]):"function"==typeof arguments[g]?f=arguments[g]:"object"==typeof arguments[g]&&(e=arguments[g]);return i=new b.init(d,e),"function"==typeof f&&f(i),i};b.isElement=function(a){return a&&("function"==typeof HTMLElement||"object"==typeof HTMLElement)&&a instanceof HTMLElement?!0:a&&a.nodeType&&1===a.nodeType?!0:!1},b.isJquery=function(a){return a&&a.length&&("function"==typeof jQuery||"object"==typeof jQuery)&&a instanceof jQuery?!0:!1},b.isZepto=function(a){return a&&a.length&&("function"==typeof Zepto||"object"==typeof Zepto)&&Zepto.zepto.isZ(a)?!0:!1},b.getIndex=function(a,b){return b?a:a-1},b.getData=function(a,b){if("string"==typeof b&&b.length){b=b.split(".");for(var c=0,d=b.length;d>c;c++)a=a[b[c]]}return a},b.init=function(c,d){var f,g,e=this;(b.isJquery(c)||b.isZepto(c))&&(f={dom:{box:c}},e.attach=b.attach.bind(f),e.detach=b.detach.bind(f),e.setOptions=b.setOptions.bind(f),e.clear=b.clear.bind(f),f.changeEvent=function(){b.selectChange.call(f,this.className)},f.settings=a.extend({},a.cxSelect.defaults,d,{url:f.dom.box.data("url"),emptyStyle:f.dom.box.data("emptyStyle"),required:f.dom.box.data("required"),firstTitle:f.dom.box.data("firstTitle"),firstValue:f.dom.box.data("firstValue"),jsonSpace:f.dom.box.data("jsonSpace"),jsonName:f.dom.box.data("jsonName"),jsonValue:f.dom.box.data("jsonValue"),jsonSub:f.dom.box.data("jsonSub")}),g=f.dom.box.data("selects"),"string"==typeof g&&g.length&&(f.settings.selects=g.split(",")),e.setOptions(),e.attach(),f.settings.url||f.settings.data?a.isArray(f.settings.data)?b.start.call(f,f.settings.data):"string"==typeof f.settings.url&&f.settings.url.length&&a.getJSON(f.settings.url,function(a){b.start.call(f,a)}):b.start.apply(f))},b.setOptions=function(c){var e,f,g,d=this;if(c&&a.extend(d.settings,c),(!a.isArray(d.selectArray)||!d.selectArray.length||c&&c.selects)&&(d.selectArray=[],a.isArray(d.settings.selects)&&d.settings.selects.length))for(f=0,g=d.settings.selects.length;g>f&&(e=d.dom.box.find("select."+d.settings.selects[f]),e&&e.length);f++)d.selectArray.push(e);c&&(!a.isArray(c.data)&&"string"==typeof c.url&&c.url.length?a.getJSON(d.settings.url,function(a){b.start.call(d,a)}):b.start.call(d,c.data))},b.attach=function(){var a=this;a.attachStatus||a.dom.box.on("change","select",a.changeEvent),"boolean"==typeof a.attachStatus&&b.start.call(a),a.attachStatus=!0},b.detach=function(){var a=this;a.dom.box.off("change","select",a.changeEvent),a.attachStatus=!1},b.clear=function(a){var d,e,b=this,c={display:"",visibility:""};for(a=isNaN(a)?0:a,d=a,e=b.selectArray.length;e>d;d++)b.selectArray[d].empty().prop("disabled",!0),"none"===b.settings.emptyStyle?c.display="none":"hidden"===b.settings.emptyStyle&&(c.visibility="hidden"),b.selectArray[d].css(c)},b.start=function(c){var e,f,d=this;if(a.isArray(c)&&(d.settings.data=b.getData(c,d.settings.jsonSpace)),d.selectArray.length){for(e=0,f=d.selectArray.length;f>e;e++)"string"!=typeof d.selectArray[e].attr("data-value")&&d.selectArray[e][0].options.length&&d.selectArray[e].attr("data-value",d.selectArray[e].val());d.settings.data||"string"==typeof d.selectArray[0].data("url")&&d.selectArray[0].data("url").length?b.getOptionData.call(d,0):d.selectArray[0][0].options.length&&"string"==typeof d.selectArray[0].attr("data-value")&&d.selectArray[0].attr("data-value").length?(d.selectArray[0].val(d.selectArray[0].attr("data-value")),b.getOptionData.call(d,1)):d.selectArray[0].prop("disabled",!1).css({display:"",visibility:""})}},b.getOptionData=function(c){var f,g,h,i,j,k,l,m,n,o,p,d=this;if(!("number"!=typeof c||isNaN(c)||0>c||c>=d.selectArray.length))if(f=d.selectArray[c],i=f.data("url"),j="undefined"==typeof f.data("jsonSpace")?d.settings.jsonSpace:f.data("jsonSpace"),k={},b.clear.call(d,c),"string"==typeof i&&i.length){if(c>0)for(o=0,p=1;c>o;o++,p++)l=d.selectArray[p].data("queryName"),m=d.selectArray[o].attr("name"),n=d.selectArray[o].val(),"string"==typeof l&&l.length?k[l]=n:"string"==typeof m&&m.length&&(k[m]=n);a.getJSON(i,k,function(a){g=b.getData(a,j),b.buildOption.call(d,c,g)})}else if(d.settings.data&&"object"==typeof d.settings.data){for(g=d.settings.data,o=0;c>o;o++){if(h=b.getIndex(d.selectArray[o][0].selectedIndex,"boolean"==typeof d.selectArray[o].data("required")?d.selectArray[o].data("required"):d.settings.required),"object"!=typeof g[h]||!a.isArray(g[h][d.settings.jsonSub])||!g[h][d.settings.jsonSub].length){g=null;break}g=g[h][d.settings.jsonSub]}b.buildOption.call(d,c,g)}},b.buildOption=function(b,c){var k,l,m,d=this,e=d.selectArray[b],f="boolean"==typeof e.data("required")?e.data("required"):d.settings.required,g="undefined"==typeof e.data("firstTitle")?d.settings.firstTitle:e.data("firstTitle"),h="undefined"==typeof e.data("firstValue")?d.settings.firstValue:e.data("firstValue"),i="undefined"==typeof e.data("jsonName")?d.settings.jsonName:e.data("jsonName"),j="undefined"==typeof e.data("jsonValue")?d.settings.jsonValue:e.data("jsonValue");if(a.isArray(c)){if(k=f?"":'<option value="'+String(h)+'">'+String(g)+"</option>","string"==typeof i&&i.length)for("string"==typeof j&&j.length||(j=i),l=0,m=c.length;m>l;l++)k+='<option value="'+String(c[l][j])+'">'+String(c[l][i])+"</option>";else for(l=0,m=c.length;m>l;l++)k+='<option value="'+String(c[l])+'">'+String(c[l])+"</option>";e.html(k).prop("disabled",!1).css({display:"",visibility:""}),"string"==typeof e.attr("data-value")&&(e.val(String(e.attr("data-value"))).removeAttr("data-value"),e[0].selectedIndex<0&&(e[0].options[0].selected=!0)),(f||e[0].selectedIndex>0)&&e.trigger("change")}},b.selectChange=function(a){var d,e,f,c=this;if("string"==typeof a&&a.length){for(a=a.replace(/\s+/g,","),a=","+a+",",e=0,f=c.selectArray.length;f>e;e++)if(a.indexOf(","+c.settings.selects[e]+",")>-1){d=e;break}"number"==typeof d&&d>-1&&(d+=1,b.getOptionData.call(c,d))}},a.cxSelect=function(){return b.apply(this,arguments)},a.cxSelect.defaults={selects:[],url:null,data:null,emptyStyle:null,required:!1,firstTitle:"请选择",firstValue:"",jsonSpace:"",jsonName:"n",jsonValue:"",jsonSub:"s"},a.fn.cxSelect=function(b,c){return this.each(function(){a.cxSelect(this,b,c)}),this}});
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/datapicker/bootstrap-datetimepicker.css b/ruoyi-admin/src/main/resources/static/ajax/libs/datapicker/bootstrap-datetimepicker.css
new file mode 100644
index 0000000..537c6a4
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/datapicker/bootstrap-datetimepicker.css
@@ -0,0 +1,418 @@
+/*!
+ * Datetimepicker for Bootstrap
+ *
+ * Copyright 2012 Stefan Petre
+ * Improvements by Andrew Rowls
+ * Licensed under the Apache License v2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+.datetimepicker {
+	padding: 4px;
+	margin-top: 1px;
+	-webkit-border-radius: 4px;
+	-moz-border-radius: 4px;
+	border-radius: 4px;
+	direction: ltr;
+}
+
+.datetimepicker-inline {
+	width: 220px;
+}
+
+.datetimepicker.datetimepicker-rtl {
+	direction: rtl;
+}
+
+.datetimepicker.datetimepicker-rtl table tr td span {
+	float: right;
+}
+
+.datetimepicker-dropdown, .datetimepicker-dropdown-left {
+	top: 0;
+	left: 0;
+}
+
+[class*=" datetimepicker-dropdown"]:before {
+	content: '';
+	display: inline-block;
+	border-left: 7px solid transparent;
+	border-right: 7px solid transparent;
+	border-bottom: 7px solid #cccccc;
+	border-bottom-color: rgba(0, 0, 0, 0.2);
+	position: absolute;
+}
+
+[class*=" datetimepicker-dropdown"]:after {
+	content: '';
+	display: inline-block;
+	border-left: 6px solid transparent;
+	border-right: 6px solid transparent;
+	border-bottom: 6px solid #ffffff;
+	position: absolute;
+}
+
+[class*=" datetimepicker-dropdown-top"]:before {
+	content: '';
+	display: inline-block;
+	border-left: 7px solid transparent;
+	border-right: 7px solid transparent;
+	border-top: 7px solid #cccccc;
+	border-top-color: rgba(0, 0, 0, 0.2);
+	border-bottom: 0;
+}
+
+[class*=" datetimepicker-dropdown-top"]:after {
+	content: '';
+	display: inline-block;
+	border-left: 6px solid transparent;
+	border-right: 6px solid transparent;
+	border-top: 6px solid #ffffff;
+	border-bottom: 0;
+}
+
+.datetimepicker-dropdown-bottom-left:before {
+	top: -7px;
+	right: 6px;
+}
+
+.datetimepicker-dropdown-bottom-left:after {
+	top: -6px;
+	right: 7px;
+}
+
+.datetimepicker-dropdown-bottom-right:before {
+	top: -7px;
+	left: 6px;
+}
+
+.datetimepicker-dropdown-bottom-right:after {
+	top: -6px;
+	left: 7px;
+}
+
+.datetimepicker-dropdown-top-left:before {
+	bottom: -7px;
+	right: 6px;
+}
+
+.datetimepicker-dropdown-top-left:after {
+	bottom: -6px;
+	right: 7px;
+}
+
+.datetimepicker-dropdown-top-right:before {
+	bottom: -7px;
+	left: 6px;
+}
+
+.datetimepicker-dropdown-top-right:after {
+	bottom: -6px;
+	left: 7px;
+}
+
+.datetimepicker > div {
+	display: none;
+}
+
+.datetimepicker.minutes div.datetimepicker-minutes {
+	display: block;
+}
+
+.datetimepicker.hours div.datetimepicker-hours {
+	display: block;
+}
+
+.datetimepicker.days div.datetimepicker-days {
+	display: block;
+}
+
+.datetimepicker.months div.datetimepicker-months {
+	display: block;
+}
+
+.datetimepicker.years div.datetimepicker-years {
+	display: block;
+}
+
+.datetimepicker table {
+	margin: 0;
+}
+
+.datetimepicker  td,
+.datetimepicker th {
+	text-align: center;
+	width: 20px;
+	height: 20px;
+	-webkit-border-radius: 4px;
+	-moz-border-radius: 4px;
+	border-radius: 4px;
+	border: none;
+}
+
+.table-striped .datetimepicker table tr td,
+.table-striped .datetimepicker table tr th {
+	background-color: transparent;
+}
+
+.datetimepicker table tr td.minute:hover {
+	background: #eeeeee;
+	cursor: pointer;
+}
+
+.datetimepicker table tr td.hour:hover {
+	background: #eeeeee;
+	cursor: pointer;
+}
+
+.datetimepicker table tr td.day:hover {
+	background: #eeeeee;
+	cursor: pointer;
+}
+
+.datetimepicker table tr td.old,
+.datetimepicker table tr td.new {
+	color: #999999;
+}
+
+.datetimepicker table tr td.disabled,
+.datetimepicker table tr td.disabled:hover {
+	background: none;
+	color: #999999;
+	cursor: default;
+}
+
+.datetimepicker table tr td.today,
+.datetimepicker table tr td.today:hover,
+.datetimepicker table tr td.today.disabled,
+.datetimepicker table tr td.today.disabled:hover {
+	background-color: #fde19a;
+	background-image: -moz-linear-gradient(top, #fdd49a, #fdf59a);
+	background-image: -ms-linear-gradient(top, #fdd49a, #fdf59a);
+	background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fdd49a), to(#fdf59a));
+	background-image: -webkit-linear-gradient(top, #fdd49a, #fdf59a);
+	background-image: -o-linear-gradient(top, #fdd49a, #fdf59a);
+	background-image: linear-gradient(to bottom, #fdd49a, #fdf59a);
+	background-repeat: repeat-x;
+	filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a', endColorstr='#fdf59a', GradientType=0);
+	border-color: #fdf59a #fdf59a #fbed50;
+	border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+	filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.datetimepicker table tr td.today:hover,
+.datetimepicker table tr td.today:hover:hover,
+.datetimepicker table tr td.today.disabled:hover,
+.datetimepicker table tr td.today.disabled:hover:hover,
+.datetimepicker table tr td.today:active,
+.datetimepicker table tr td.today:hover:active,
+.datetimepicker table tr td.today.disabled:active,
+.datetimepicker table tr td.today.disabled:hover:active,
+.datetimepicker table tr td.today.active,
+.datetimepicker table tr td.today:hover.active,
+.datetimepicker table tr td.today.disabled.active,
+.datetimepicker table tr td.today.disabled:hover.active,
+.datetimepicker table tr td.today.disabled,
+.datetimepicker table tr td.today:hover.disabled,
+.datetimepicker table tr td.today.disabled.disabled,
+.datetimepicker table tr td.today.disabled:hover.disabled,
+.datetimepicker table tr td.today[disabled],
+.datetimepicker table tr td.today:hover[disabled],
+.datetimepicker table tr td.today.disabled[disabled],
+.datetimepicker table tr td.today.disabled:hover[disabled] {
+	background-color: #fdf59a;
+}
+
+.datetimepicker table tr td.today:active,
+.datetimepicker table tr td.today:hover:active,
+.datetimepicker table tr td.today.disabled:active,
+.datetimepicker table tr td.today.disabled:hover:active,
+.datetimepicker table tr td.today.active,
+.datetimepicker table tr td.today:hover.active,
+.datetimepicker table tr td.today.disabled.active,
+.datetimepicker table tr td.today.disabled:hover.active {
+	background-color: #fbf069;
+}
+
+.datetimepicker table tr td.active,
+.datetimepicker table tr td.active:hover,
+.datetimepicker table tr td.active.disabled,
+.datetimepicker table tr td.active.disabled:hover {
+	background-color: #006dcc;
+	background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
+	background-image: -ms-linear-gradient(top, #0088cc, #0044cc);
+	background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
+	background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
+	background-image: -o-linear-gradient(top, #0088cc, #0044cc);
+	background-image: linear-gradient(to bottom, #0088cc, #0044cc);
+	background-repeat: repeat-x;
+	filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);
+	border-color: #0044cc #0044cc #002a80;
+	border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+	filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+	color: #ffffff;
+	text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+}
+
+.datetimepicker table tr td.active:hover,
+.datetimepicker table tr td.active:hover:hover,
+.datetimepicker table tr td.active.disabled:hover,
+.datetimepicker table tr td.active.disabled:hover:hover,
+.datetimepicker table tr td.active:active,
+.datetimepicker table tr td.active:hover:active,
+.datetimepicker table tr td.active.disabled:active,
+.datetimepicker table tr td.active.disabled:hover:active,
+.datetimepicker table tr td.active.active,
+.datetimepicker table tr td.active:hover.active,
+.datetimepicker table tr td.active.disabled.active,
+.datetimepicker table tr td.active.disabled:hover.active,
+.datetimepicker table tr td.active.disabled,
+.datetimepicker table tr td.active:hover.disabled,
+.datetimepicker table tr td.active.disabled.disabled,
+.datetimepicker table tr td.active.disabled:hover.disabled,
+.datetimepicker table tr td.active[disabled],
+.datetimepicker table tr td.active:hover[disabled],
+.datetimepicker table tr td.active.disabled[disabled],
+.datetimepicker table tr td.active.disabled:hover[disabled] {
+	background-color: #0044cc;
+}
+
+.datetimepicker table tr td.active:active,
+.datetimepicker table tr td.active:hover:active,
+.datetimepicker table tr td.active.disabled:active,
+.datetimepicker table tr td.active.disabled:hover:active,
+.datetimepicker table tr td.active.active,
+.datetimepicker table tr td.active:hover.active,
+.datetimepicker table tr td.active.disabled.active,
+.datetimepicker table tr td.active.disabled:hover.active {
+	background-color: #003399;
+}
+
+.datetimepicker table tr td span {
+	display: block;
+	width: 23%;
+	height: 54px;
+	line-height: 54px;
+	float: left;
+	margin: 1%;
+	cursor: pointer;
+	-webkit-border-radius: 4px;
+	-moz-border-radius: 4px;
+	border-radius: 4px;
+}
+
+.datetimepicker .datetimepicker-hours span {
+	height: 26px;
+	line-height: 26px;
+}
+
+.datetimepicker .datetimepicker-hours table tr td span.hour_am,
+.datetimepicker .datetimepicker-hours table tr td span.hour_pm {
+	width: 14.6%;
+}
+
+.datetimepicker .datetimepicker-hours fieldset legend,
+.datetimepicker .datetimepicker-minutes fieldset legend {
+	margin-bottom: inherit;
+	line-height: 30px;
+}
+
+.datetimepicker .datetimepicker-minutes span {
+	height: 26px;
+	line-height: 26px;
+}
+
+.datetimepicker table tr td span:hover {
+	background: #eeeeee;
+}
+
+.datetimepicker table tr td span.disabled,
+.datetimepicker table tr td span.disabled:hover {
+	background: none;
+	color: #999999;
+	cursor: default;
+}
+
+.datetimepicker table tr td span.active,
+.datetimepicker table tr td span.active:hover,
+.datetimepicker table tr td span.active.disabled,
+.datetimepicker table tr td span.active.disabled:hover {
+	background-color: #006dcc;
+	background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
+	background-image: -ms-linear-gradient(top, #0088cc, #0044cc);
+	background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
+	background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
+	background-image: -o-linear-gradient(top, #0088cc, #0044cc);
+	background-image: linear-gradient(to bottom, #0088cc, #0044cc);
+	background-repeat: repeat-x;
+	filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);
+	border-color: #0044cc #0044cc #002a80;
+	border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+	filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+	color: #ffffff;
+	text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+}
+
+.datetimepicker table tr td span.active:hover,
+.datetimepicker table tr td span.active:hover:hover,
+.datetimepicker table tr td span.active.disabled:hover,
+.datetimepicker table tr td span.active.disabled:hover:hover,
+.datetimepicker table tr td span.active:active,
+.datetimepicker table tr td span.active:hover:active,
+.datetimepicker table tr td span.active.disabled:active,
+.datetimepicker table tr td span.active.disabled:hover:active,
+.datetimepicker table tr td span.active.active,
+.datetimepicker table tr td span.active:hover.active,
+.datetimepicker table tr td span.active.disabled.active,
+.datetimepicker table tr td span.active.disabled:hover.active,
+.datetimepicker table tr td span.active.disabled,
+.datetimepicker table tr td span.active:hover.disabled,
+.datetimepicker table tr td span.active.disabled.disabled,
+.datetimepicker table tr td span.active.disabled:hover.disabled,
+.datetimepicker table tr td span.active[disabled],
+.datetimepicker table tr td span.active:hover[disabled],
+.datetimepicker table tr td span.active.disabled[disabled],
+.datetimepicker table tr td span.active.disabled:hover[disabled] {
+	background-color: #0044cc;
+}
+
+.datetimepicker table tr td span.active:active,
+.datetimepicker table tr td span.active:hover:active,
+.datetimepicker table tr td span.active.disabled:active,
+.datetimepicker table tr td span.active.disabled:hover:active,
+.datetimepicker table tr td span.active.active,
+.datetimepicker table tr td span.active:hover.active,
+.datetimepicker table tr td span.active.disabled.active,
+.datetimepicker table tr td span.active.disabled:hover.active {
+	background-color: #003399;
+}
+
+.datetimepicker table tr td span.old {
+	color: #999999;
+}
+
+.datetimepicker th.switch {
+	width: 145px;
+}
+
+.datetimepicker th span.glyphicon {
+	pointer-events: none;
+}
+
+.datetimepicker thead tr:first-child th,
+.datetimepicker tfoot th {
+	cursor: pointer;
+}
+
+.datetimepicker thead tr:first-child th:hover,
+.datetimepicker tfoot th:hover {
+	background: #eeeeee;
+}
+
+.input-append.date .add-on i,
+.input-prepend.date .add-on i,
+.input-group.date .input-group-addon span {
+	cursor: pointer;
+	width: 14px;
+	height: 14px;
+}
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/datapicker/bootstrap-datetimepicker.js b/ruoyi-admin/src/main/resources/static/ajax/libs/datapicker/bootstrap-datetimepicker.js
new file mode 100644
index 0000000..3361d4b
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/datapicker/bootstrap-datetimepicker.js
@@ -0,0 +1,1978 @@
+/* =========================================================
+ * bootstrap-datetimepicker.js
+ * =========================================================
+ * Copyright 2012 Stefan Petre
+ *
+ * Improvements by Andrew Rowls
+ * Improvements by Sébastien Malot
+ * Improvements by Yun Lai
+ * Improvements by Kenneth Henderick
+ * Improvements by CuGBabyBeaR
+ * Improvements by Christian Vaas <auspex@auspex.eu>
+ *
+ * Project URL : http://www.malot.fr/bootstrap-datetimepicker
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================= */
+
+(function(factory){
+    if (typeof define === 'function' && define.amd)
+      define(['jquery'], factory);
+    else if (typeof exports === 'object')
+      factory(require('jquery'));
+    else
+      factory(jQuery);
+
+}(function($, undefined){
+
+  // Add ECMA262-5 Array methods if not supported natively (IE8)
+  if (!('indexOf' in Array.prototype)) {
+    Array.prototype.indexOf = function (find, i) {
+      if (i === undefined) i = 0;
+      if (i < 0) i += this.length;
+      if (i < 0) i = 0;
+      for (var n = this.length; i < n; i++) {
+        if (i in this && this[i] === find) {
+          return i;
+        }
+      }
+      return -1;
+    }
+  }
+
+  // Add timezone abbreviation support for ie6+, Chrome, Firefox
+  function timeZoneAbbreviation() {
+    var abbreviation, date, formattedStr, i, len, matchedStrings, ref, str;
+    date = (new Date()).toString();
+    formattedStr = ((ref = date.split('(')[1]) != null ? ref.slice(0, -1) : 0) || date.split(' ');
+    if (formattedStr instanceof Array) {
+      matchedStrings = [];
+      for (var i = 0, len = formattedStr.length; i < len; i++) {
+        str = formattedStr[i];
+        if ((abbreviation = (ref = str.match(/\b[A-Z]+\b/)) !== null) ? ref[0] : 0) {
+          matchedStrings.push(abbreviation);
+        }
+      }
+      formattedStr = matchedStrings.pop();
+    }
+    return formattedStr;
+  }
+
+  function UTCDate() {
+    return new Date(Date.UTC.apply(Date, arguments));
+  }
+
+  // Picker object
+  var Datetimepicker = function (element, options) {
+    var that = this;
+
+    this.element = $(element);
+
+    // add container for single page application
+    // when page switch the datetimepicker div will be removed also.
+    this.container = options.container || 'body';
+
+    this.language = options.language || this.element.data('date-language') || 'zh-cn';
+    this.language = this.language in dates ? this.language : this.language.split('-')[0]; // fr-CA fallback to fr
+    this.language = this.language in dates ? this.language : 'en';
+    this.isRTL = dates[this.language].rtl || false;
+    this.formatType = options.formatType || this.element.data('format-type') || 'standard';
+    this.format = DPGlobal.parseFormat(options.format || this.element.data('date-format') || dates[this.language].format || DPGlobal.getDefaultFormat(this.formatType, 'input'), this.formatType);
+    this.isInline = false;
+    this.isVisible = false;
+    this.isInput = this.element.is('input');
+    this.fontAwesome = options.fontAwesome || this.element.data('font-awesome') || false;
+
+    this.bootcssVer = options.bootcssVer || (this.isInput ? (this.element.is('.form-control') ? 3 : 2) : ( this.bootcssVer = this.element.is('.input-group') ? 3 : 2 ));
+
+    this.component = this.element.is('.date') ? ( this.bootcssVer === 3 ? this.element.find('.input-group-addon .glyphicon-th, .input-group-addon .glyphicon-time, .input-group-addon .glyphicon-remove, .input-group-addon .glyphicon-calendar, .input-group-addon .fa-calendar, .input-group-addon .fa-clock-o').parent() : this.element.find('.add-on .icon-th, .add-on .icon-time, .add-on .icon-calendar, .add-on .fa-calendar, .add-on .fa-clock-o').parent()) : false;
+    this.componentReset = this.element.is('.date') ? ( this.bootcssVer === 3 ? this.element.find('.input-group-addon .glyphicon-remove, .input-group-addon .fa-times').parent():this.element.find('.add-on .icon-remove, .add-on .fa-times').parent()) : false;
+    this.hasInput = this.component && this.element.find('input').length;
+    if (this.component && this.component.length === 0) {
+      this.component = false;
+    }
+    this.linkField = options.linkField || this.element.data('link-field') || false;
+    this.linkFormat = DPGlobal.parseFormat(options.linkFormat || this.element.data('link-format') || DPGlobal.getDefaultFormat(this.formatType, 'link'), this.formatType);
+    this.minuteStep = options.minuteStep || this.element.data('minute-step') || 5;
+    this.pickerPosition = options.pickerPosition || this.element.data('picker-position') || 'bottom-right';
+    this.showMeridian = options.showMeridian || this.element.data('show-meridian') || false;
+    this.initialDate = options.initialDate || new Date();
+    this.zIndex = options.zIndex || this.element.data('z-index') || undefined;
+    this.title = typeof options.title === 'undefined' ? false : options.title;
+    this.timezone = options.timezone || timeZoneAbbreviation();
+
+    this.icons = {
+      leftArrow: this.fontAwesome ? 'fa-arrow-left' : (this.bootcssVer === 3 ? 'glyphicon-arrow-left' : 'icon-arrow-left'),
+      rightArrow: this.fontAwesome ? 'fa-arrow-right' : (this.bootcssVer === 3 ? 'glyphicon-arrow-right' : 'icon-arrow-right')
+    }
+    this.icontype = this.fontAwesome ? 'fa' : 'glyphicon';
+
+    this._attachEvents();
+
+    this.clickedOutside = function (e) {
+        // Clicked outside the datetimepicker, hide it
+        if ($(e.target).closest('.datetimepicker').length === 0) {
+            that.hide();
+        }
+    }
+
+    this.formatViewType = 'datetime';
+    if ('formatViewType' in options) {
+      this.formatViewType = options.formatViewType;
+    } else if ('formatViewType' in this.element.data()) {
+      this.formatViewType = this.element.data('formatViewType');
+    }
+
+    this.minView = 0;
+    if ('minView' in options) {
+      this.minView = options.minView;
+    } else if ('minView' in this.element.data()) {
+      this.minView = this.element.data('min-view');
+    }
+    this.minView = DPGlobal.convertViewMode(this.minView);
+
+    this.maxView = DPGlobal.modes.length - 1;
+    if ('maxView' in options) {
+      this.maxView = options.maxView;
+    } else if ('maxView' in this.element.data()) {
+      this.maxView = this.element.data('max-view');
+    }
+    this.maxView = DPGlobal.convertViewMode(this.maxView);
+
+    this.wheelViewModeNavigation = false;
+    if ('wheelViewModeNavigation' in options) {
+      this.wheelViewModeNavigation = options.wheelViewModeNavigation;
+    } else if ('wheelViewModeNavigation' in this.element.data()) {
+      this.wheelViewModeNavigation = this.element.data('view-mode-wheel-navigation');
+    }
+
+    this.wheelViewModeNavigationInverseDirection = false;
+
+    if ('wheelViewModeNavigationInverseDirection' in options) {
+      this.wheelViewModeNavigationInverseDirection = options.wheelViewModeNavigationInverseDirection;
+    } else if ('wheelViewModeNavigationInverseDirection' in this.element.data()) {
+      this.wheelViewModeNavigationInverseDirection = this.element.data('view-mode-wheel-navigation-inverse-dir');
+    }
+
+    this.wheelViewModeNavigationDelay = 100;
+    if ('wheelViewModeNavigationDelay' in options) {
+      this.wheelViewModeNavigationDelay = options.wheelViewModeNavigationDelay;
+    } else if ('wheelViewModeNavigationDelay' in this.element.data()) {
+      this.wheelViewModeNavigationDelay = this.element.data('view-mode-wheel-navigation-delay');
+    }
+
+    this.startViewMode = 2;
+    if ('startView' in options) {
+      this.startViewMode = options.startView;
+    } else if ('startView' in this.element.data()) {
+      this.startViewMode = this.element.data('start-view');
+    }
+    this.startViewMode = DPGlobal.convertViewMode(this.startViewMode);
+    this.viewMode = this.startViewMode;
+
+    this.viewSelect = this.minView;
+    if ('viewSelect' in options) {
+      this.viewSelect = options.viewSelect;
+    } else if ('viewSelect' in this.element.data()) {
+      this.viewSelect = this.element.data('view-select');
+    }
+    this.viewSelect = DPGlobal.convertViewMode(this.viewSelect);
+
+    this.forceParse = true;
+    if ('forceParse' in options) {
+      this.forceParse = options.forceParse;
+    } else if ('dateForceParse' in this.element.data()) {
+      this.forceParse = this.element.data('date-force-parse');
+    }
+    var template = this.bootcssVer === 3 ? DPGlobal.templateV3 : DPGlobal.template;
+    while (template.indexOf('{iconType}') !== -1) {
+      template = template.replace('{iconType}', this.icontype);
+    }
+    while (template.indexOf('{leftArrow}') !== -1) {
+      template = template.replace('{leftArrow}', this.icons.leftArrow);
+    }
+    while (template.indexOf('{rightArrow}') !== -1) {
+      template = template.replace('{rightArrow}', this.icons.rightArrow);
+    }
+    this.picker = $(template)
+      .appendTo(this.isInline ? this.element : this.container) // 'body')
+      .on({
+        click:     $.proxy(this.click, this),
+        mousedown: $.proxy(this.mousedown, this)
+      });
+
+    if (this.wheelViewModeNavigation) {
+      if ($.fn.mousewheel) {
+        this.picker.on({mousewheel: $.proxy(this.mousewheel, this)});
+      } else {
+        console.log('Mouse Wheel event is not supported. Please include the jQuery Mouse Wheel plugin before enabling this option');
+      }
+    }
+
+    if (this.isInline) {
+      this.picker.addClass('datetimepicker-inline');
+    } else {
+      this.picker.addClass('datetimepicker-dropdown-' + this.pickerPosition + ' dropdown-menu');
+    }
+    if (this.isRTL) {
+      this.picker.addClass('datetimepicker-rtl');
+      var selector = this.bootcssVer === 3 ? '.prev span, .next span' : '.prev i, .next i';
+      this.picker.find(selector).toggleClass(this.icons.leftArrow + ' ' + this.icons.rightArrow);
+    }
+
+    $(document).on('mousedown touchend', this.clickedOutside);
+
+    this.autoclose = false;
+    if ('autoclose' in options) {
+      this.autoclose = options.autoclose;
+    } else if ('dateAutoclose' in this.element.data()) {
+      this.autoclose = this.element.data('date-autoclose');
+    }
+
+    this.keyboardNavigation = true;
+    if ('keyboardNavigation' in options) {
+      this.keyboardNavigation = options.keyboardNavigation;
+    } else if ('dateKeyboardNavigation' in this.element.data()) {
+      this.keyboardNavigation = this.element.data('date-keyboard-navigation');
+    }
+
+    this.todayBtn = (options.todayBtn || this.element.data('date-today-btn') || false);
+    this.clearBtn = (options.clearBtn || this.element.data('date-clear-btn') || false);
+    this.todayHighlight = (options.todayHighlight || this.element.data('date-today-highlight') || false);
+
+    this.weekStart = 0;
+    if (typeof options.weekStart !== 'undefined') {
+      this.weekStart = options.weekStart;
+    } else if (typeof this.element.data('date-weekstart') !== 'undefined') {
+      this.weekStart = this.element.data('date-weekstart');
+    } else if (typeof dates[this.language].weekStart !== 'undefined') {
+      this.weekStart = dates[this.language].weekStart;
+    }
+    this.weekStart = this.weekStart % 7;
+    this.weekEnd = ((this.weekStart + 6) % 7);
+    this.onRenderDay = function (date) {
+      var render = (options.onRenderDay || function () { return []; })(date);
+      if (typeof render === 'string') {
+        render = [render];
+      }
+      var res = ['day'];
+      return res.concat((render ? render : []));
+    };
+    this.onRenderHour = function (date) {
+      var render = (options.onRenderHour || function () { return []; })(date);
+      var res = ['hour'];
+      if (typeof render === 'string') {
+        render = [render];
+      }
+      return res.concat((render ? render : []));
+    };
+    this.onRenderMinute = function (date) {
+      var render = (options.onRenderMinute || function () { return []; })(date);
+      var res = ['minute'];
+      if (typeof render === 'string') {
+        render = [render];
+      }
+      if (date < this.startDate || date > this.endDate) {
+        res.push('disabled');
+      } else if (Math.floor(this.date.getUTCMinutes() / this.minuteStep) === Math.floor(date.getUTCMinutes() / this.minuteStep)) {
+        res.push('active');
+      }
+      return res.concat((render ? render : []));
+    };
+    this.onRenderYear = function (date) {
+      var render = (options.onRenderYear || function () { return []; })(date);
+      var res = ['year'];
+      if (typeof render === 'string') {
+        render = [render];
+      }
+      if (this.date.getUTCFullYear() === date.getUTCFullYear()) {
+        res.push('active');
+      }
+      var currentYear = date.getUTCFullYear();
+      var endYear = this.endDate.getUTCFullYear();
+      if (date < this.startDate || currentYear > endYear) {
+        res.push('disabled');
+      }
+      return res.concat((render ? render : []));
+    }
+    this.onRenderMonth = function (date) {
+      var render = (options.onRenderMonth || function () { return []; })(date);
+      var res = ['month'];
+      if (typeof render === 'string') {
+        render = [render];
+      }
+      return res.concat((render ? render : []));
+    }
+    this.startDate = new Date(-8639968443048000);
+    this.endDate = new Date(8639968443048000);
+    this.datesDisabled = [];
+    this.daysOfWeekDisabled = [];
+    this.setStartDate(options.startDate || this.element.data('date-startdate'));
+    this.setEndDate(options.endDate || this.element.data('date-enddate'));
+    this.setDatesDisabled(options.datesDisabled || this.element.data('date-dates-disabled'));
+    this.setDaysOfWeekDisabled(options.daysOfWeekDisabled || this.element.data('date-days-of-week-disabled'));
+    this.setMinutesDisabled(options.minutesDisabled || this.element.data('date-minute-disabled'));
+    this.setHoursDisabled(options.hoursDisabled || this.element.data('date-hour-disabled'));
+    this.fillDow();
+    this.fillMonths();
+    this.update();
+    this.showMode();
+
+    if (this.isInline) {
+      this.show();
+    }
+  };
+
+  Datetimepicker.prototype = {
+    constructor: Datetimepicker,
+
+    _events:       [],
+    _attachEvents: function () {
+      this._detachEvents();
+      if (this.isInput) { // single input
+        this._events = [
+          [this.element, {
+            focus:   $.proxy(this.show, this),
+            keyup:   $.proxy(this.update, this),
+            keydown: $.proxy(this.keydown, this)
+          }]
+        ];
+      }
+      else if (this.component && this.hasInput) { // component: input + button
+        this._events = [
+          // For components that are not readonly, allow keyboard nav
+          [this.element.find('input'), {
+            focus:   $.proxy(this.show, this),
+            keyup:   $.proxy(this.update, this),
+            keydown: $.proxy(this.keydown, this)
+          }],
+          [this.component, {
+            click: $.proxy(this.show, this)
+          }]
+        ];
+        if (this.componentReset) {
+          this._events.push([
+            this.componentReset,
+            {click: $.proxy(this.reset, this)}
+          ]);
+        }
+      }
+      else if (this.element.is('div')) {  // inline datetimepicker
+        this.isInline = true;
+      }
+      else {
+        this._events = [
+          [this.element, {
+            click: $.proxy(this.show, this)
+          }]
+        ];
+      }
+      for (var i = 0, el, ev; i < this._events.length; i++) {
+        el = this._events[i][0];
+        ev = this._events[i][1];
+        el.on(ev);
+      }
+    },
+
+    _detachEvents: function () {
+      for (var i = 0, el, ev; i < this._events.length; i++) {
+        el = this._events[i][0];
+        ev = this._events[i][1];
+        el.off(ev);
+      }
+      this._events = [];
+    },
+
+    show: function (e) {
+      this.picker.show();
+      this.height = this.component ? this.component.outerHeight() : this.element.outerHeight();
+      if (this.forceParse) {
+        this.update();
+      }
+      this.place();
+      $(window).on('resize', $.proxy(this.place, this));
+      if (e) {
+        e.stopPropagation();
+        e.preventDefault();
+      }
+      this.isVisible = true;
+      this.element.trigger({
+        type: 'show',
+        date: this.date
+      });
+    },
+
+    hide: function () {
+      if (!this.isVisible) return;
+      if (this.isInline) return;
+      this.picker.hide();
+      $(window).off('resize', this.place);
+      this.viewMode = this.startViewMode;
+      this.showMode();
+      if (!this.isInput) {
+        $(document).off('mousedown', this.hide);
+      }
+
+      if (
+        this.forceParse &&
+          (
+            this.isInput && this.element.val() ||
+              this.hasInput && this.element.find('input').val()
+            )
+        )
+        this.setValue();
+      this.isVisible = false;
+      this.element.trigger({
+        type: 'hide',
+        date: this.date
+      });
+    },
+
+    remove: function () {
+      this._detachEvents();
+      $(document).off('mousedown', this.clickedOutside);
+      this.picker.remove();
+      delete this.picker;
+      delete this.element.data().datetimepicker;
+    },
+
+    getDate: function () {
+      var d = this.getUTCDate();
+      if (d === null) {
+        return null;
+      }
+      return new Date(d.getTime() + (d.getTimezoneOffset() * 60000));
+    },
+
+    getUTCDate: function () {
+      return this.date;
+    },
+
+    getInitialDate: function () {
+      return this.initialDate
+    },
+
+    setInitialDate: function (initialDate) {
+      this.initialDate = initialDate;
+    },
+
+    setDate: function (d) {
+      this.setUTCDate(new Date(d.getTime() - (d.getTimezoneOffset() * 60000)));
+    },
+
+    setUTCDate: function (d) {
+      if (d >= this.startDate && d <= this.endDate) {
+        this.date = d;
+        this.setValue();
+        this.viewDate = this.date;
+        this.fill();
+      } else {
+        this.element.trigger({
+          type:      'outOfRange',
+          date:      d,
+          startDate: this.startDate,
+          endDate:   this.endDate
+        });
+      }
+    },
+
+    setFormat: function (format) {
+      this.format = DPGlobal.parseFormat(format, this.formatType);
+      var element;
+      if (this.isInput) {
+        element = this.element;
+      } else if (this.component) {
+        element = this.element.find('input');
+      }
+      if (element && element.val()) {
+        this.setValue();
+      }
+    },
+
+    setValue: function () {
+      var formatted = this.getFormattedDate();
+      if (!this.isInput) {
+        if (this.component) {
+          this.element.find('input').val(formatted);
+        }
+        this.element.data('date', formatted);
+      } else {
+        this.element.val(formatted);
+      }
+      if (this.linkField) {
+        $('#' + this.linkField).val(this.getFormattedDate(this.linkFormat));
+      }
+    },
+
+    getFormattedDate: function (format) {
+      format = format || this.format;
+      return DPGlobal.formatDate(this.date, format, this.language, this.formatType, this.timezone);
+    },
+
+    setStartDate: function (startDate) {
+      this.startDate = startDate || this.startDate;
+      if (this.startDate.valueOf() !== 8639968443048000) {
+        this.startDate = DPGlobal.parseDate(this.startDate, this.format, this.language, this.formatType, this.timezone);
+      }
+      this.update();
+      this.updateNavArrows();
+    },
+
+    setEndDate: function (endDate) {
+      this.endDate = endDate || this.endDate;
+      if (this.endDate.valueOf() !== 8639968443048000) {
+        this.endDate = DPGlobal.parseDate(this.endDate, this.format, this.language, this.formatType, this.timezone);
+      }
+      this.update();
+      this.updateNavArrows();
+    },
+
+    setDatesDisabled: function (datesDisabled) {
+      this.datesDisabled = datesDisabled || [];
+      if (!$.isArray(this.datesDisabled)) {
+        this.datesDisabled = this.datesDisabled.split(/,\s*/);
+      }
+      var mThis = this;
+      this.datesDisabled = $.map(this.datesDisabled, function (d) {
+        return DPGlobal.parseDate(d, mThis.format, mThis.language, mThis.formatType, mThis.timezone).toDateString();
+      });
+      this.update();
+      this.updateNavArrows();
+    },
+
+    setTitle: function (selector, value) {
+      return this.picker.find(selector)
+        .find('th:eq(1)')
+        .text(this.title === false ? value : this.title);
+    },
+
+    setDaysOfWeekDisabled: function (daysOfWeekDisabled) {
+      this.daysOfWeekDisabled = daysOfWeekDisabled || [];
+      if (!$.isArray(this.daysOfWeekDisabled)) {
+        this.daysOfWeekDisabled = this.daysOfWeekDisabled.split(/,\s*/);
+      }
+      this.daysOfWeekDisabled = $.map(this.daysOfWeekDisabled, function (d) {
+        return parseInt(d, 10);
+      });
+      this.update();
+      this.updateNavArrows();
+    },
+
+    setMinutesDisabled: function (minutesDisabled) {
+      this.minutesDisabled = minutesDisabled || [];
+      if (!$.isArray(this.minutesDisabled)) {
+        this.minutesDisabled = this.minutesDisabled.split(/,\s*/);
+      }
+      this.minutesDisabled = $.map(this.minutesDisabled, function (d) {
+        return parseInt(d, 10);
+      });
+      this.update();
+      this.updateNavArrows();
+    },
+
+    setHoursDisabled: function (hoursDisabled) {
+      this.hoursDisabled = hoursDisabled || [];
+      if (!$.isArray(this.hoursDisabled)) {
+        this.hoursDisabled = this.hoursDisabled.split(/,\s*/);
+      }
+      this.hoursDisabled = $.map(this.hoursDisabled, function (d) {
+        return parseInt(d, 10);
+      });
+      this.update();
+      this.updateNavArrows();
+    },
+
+    place: function () {
+      if (this.isInline) return;
+
+      if (!this.zIndex) {
+        var index_highest = 0;
+        $('div').each(function () {
+          var index_current = parseInt($(this).css('zIndex'), 10);
+          if (index_current > index_highest) {
+            index_highest = index_current;
+          }
+        });
+        this.zIndex = index_highest + 10;
+      }
+
+      var offset, top, left, containerOffset;
+      if (this.container instanceof $) {
+        containerOffset = this.container.offset();
+      } else {
+        containerOffset = $(this.container).offset();
+      }
+
+      if (this.component) {
+        offset = this.component.offset();
+        left = offset.left;
+        if (this.pickerPosition === 'bottom-left' || this.pickerPosition === 'top-left') {
+          left += this.component.outerWidth() - this.picker.outerWidth();
+        }
+      } else {
+        offset = this.element.offset();
+        left = offset.left;
+        if (this.pickerPosition === 'bottom-left' || this.pickerPosition === 'top-left') {
+          left += this.element.outerWidth() - this.picker.outerWidth();
+        }
+      }
+
+      var bodyWidth = document.body.clientWidth || window.innerWidth;
+      if (left + 220 > bodyWidth) {
+        left = bodyWidth - 220;
+      }
+
+      if (this.pickerPosition === 'top-left' || this.pickerPosition === 'top-right') {
+        top = offset.top - this.picker.outerHeight();
+      } else {
+        top = offset.top + this.height;
+      }
+
+      top = top - containerOffset.top;
+      left = left - containerOffset.left;
+
+      this.picker.css({
+        top:    top,
+        left:   left,
+        zIndex: this.zIndex
+      });
+    },
+
+    hour_minute: "^([0-9]|0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]",
+
+    update: function () {
+      var date, fromArgs = false;
+      if (arguments && arguments.length && (typeof arguments[0] === 'string' || arguments[0] instanceof Date)) {
+        date = arguments[0];
+        fromArgs = true;
+      } else {
+        date = (this.isInput ? this.element.val() : this.element.find('input').val()) || this.element.data('date') || this.initialDate;
+        if (typeof date === 'string') {
+          date = date.replace(/^\s+|\s+$/g,'');
+        }
+      }
+
+      if (!date) {
+        date = new Date();
+        fromArgs = false;
+      }
+
+      if (typeof date === "string") {
+        if (new RegExp(this.hour_minute).test(date) || new RegExp(this.hour_minute + ":[0-5][0-9]").test(date)) {
+          date = this.getDate()
+        }
+      }
+
+      this.date = DPGlobal.parseDate(date, this.format, this.language, this.formatType, this.timezone);
+
+      if (fromArgs) this.setValue();
+
+      if (this.date < this.startDate) {
+        this.viewDate = new Date(this.startDate);
+      } else if (this.date > this.endDate) {
+        this.viewDate = new Date(this.endDate);
+      } else {
+        this.viewDate = new Date(this.date);
+      }
+      this.fill();
+    },
+
+    fillDow: function () {
+      var dowCnt = this.weekStart,
+        html = '<tr>';
+      while (dowCnt < this.weekStart + 7) {
+        html += '<th class="dow">' + dates[this.language].daysMin[(dowCnt++) % 7] + '</th>';
+      }
+      html += '</tr>';
+      this.picker.find('.datetimepicker-days thead').append(html);
+    },
+
+    fillMonths: function () {
+      var html = '';
+      var d = new Date(this.viewDate);
+      for (var i = 0; i < 12; i++) {
+        d.setUTCMonth(i);
+        var classes = this.onRenderMonth(d);
+        html += '<span class="' + classes.join(' ') + '">' + dates[this.language].monthsShort[i] + '</span>';
+      }
+      this.picker.find('.datetimepicker-months td').html(html);
+    },
+
+    fill: function () {
+      if (!this.date || !this.viewDate) {
+        return;
+      }
+      var d = new Date(this.viewDate),
+        year = d.getUTCFullYear(),
+        month = d.getUTCMonth(),
+        dayMonth = d.getUTCDate(),
+        hours = d.getUTCHours(),
+        startYear = this.startDate.getUTCFullYear(),
+        startMonth = this.startDate.getUTCMonth(),
+        endYear = this.endDate.getUTCFullYear(),
+        endMonth = this.endDate.getUTCMonth() + 1,
+        currentDate = (new UTCDate(this.date.getUTCFullYear(), this.date.getUTCMonth(), this.date.getUTCDate())).valueOf(),
+        today = new Date();
+      this.setTitle('.datetimepicker-days', dates[this.language].months[month] + ' ' + year)
+      if (this.formatViewType === 'time') {
+        var formatted = this.getFormattedDate();
+        this.setTitle('.datetimepicker-hours', formatted);
+        this.setTitle('.datetimepicker-minutes', formatted);
+      } else {
+        this.setTitle('.datetimepicker-hours', dayMonth + ' ' + dates[this.language].months[month] + ' ' + year);
+        this.setTitle('.datetimepicker-minutes', dayMonth + ' ' + dates[this.language].months[month] + ' ' + year);
+      }
+      this.picker.find('tfoot th.today')
+        .text(dates[this.language].today || dates['en'].today)
+        .toggle(this.todayBtn !== false);
+      this.picker.find('tfoot th.clear')
+        .text(dates[this.language].clear || dates['en'].clear)
+        .toggle(this.clearBtn !== false);
+      this.updateNavArrows();
+      this.fillMonths();
+      var prevMonth = UTCDate(year, month - 1, 28, 0, 0, 0, 0),
+        day = DPGlobal.getDaysInMonth(prevMonth.getUTCFullYear(), prevMonth.getUTCMonth());
+      prevMonth.setUTCDate(day);
+      prevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.weekStart + 7) % 7);
+      var nextMonth = new Date(prevMonth);
+      nextMonth.setUTCDate(nextMonth.getUTCDate() + 42);
+      nextMonth = nextMonth.valueOf();
+      var html = [];
+      var classes;
+      while (prevMonth.valueOf() < nextMonth) {
+        if (prevMonth.getUTCDay() === this.weekStart) {
+          html.push('<tr>');
+        }
+        classes = this.onRenderDay(prevMonth);
+        if (prevMonth.getUTCFullYear() < year || (prevMonth.getUTCFullYear() === year && prevMonth.getUTCMonth() < month)) {
+          classes.push('old');
+        } else if (prevMonth.getUTCFullYear() > year || (prevMonth.getUTCFullYear() === year && prevMonth.getUTCMonth() > month)) {
+          classes.push('new');
+        }
+        // Compare internal UTC date with local today, not UTC today
+        if (this.todayHighlight &&
+          prevMonth.getUTCFullYear() === today.getFullYear() &&
+          prevMonth.getUTCMonth() === today.getMonth() &&
+          prevMonth.getUTCDate() === today.getDate()) {
+          classes.push('today');
+        }
+        if (prevMonth.valueOf() === currentDate) {
+          classes.push('active');
+        }
+        if ((prevMonth.valueOf() + 86400000) <= this.startDate || prevMonth.valueOf() > this.endDate ||
+          $.inArray(prevMonth.getUTCDay(), this.daysOfWeekDisabled) !== -1 ||
+          $.inArray(prevMonth.toDateString(), this.datesDisabled) !== -1) {
+          classes.push('disabled');
+        }
+        html.push('<td class="' + classes.join(' ') + '">' + prevMonth.getUTCDate() + '</td>');
+        if (prevMonth.getUTCDay() === this.weekEnd) {
+          html.push('</tr>');
+        }
+        prevMonth.setUTCDate(prevMonth.getUTCDate() + 1);
+      }
+      this.picker.find('.datetimepicker-days tbody').empty().append(html.join(''));
+
+      html = [];
+      var txt = '', meridian = '', meridianOld = '';
+      var hoursDisabled = this.hoursDisabled || [];
+      d = new Date(this.viewDate)
+      for (var i = 0; i < 24; i++) {
+        d.setUTCHours(i);
+        classes = this.onRenderHour(d);
+        if (hoursDisabled.indexOf(i) !== -1) {
+          classes.push('disabled');
+        }
+        var actual = UTCDate(year, month, dayMonth, i);
+        // We want the previous hour for the startDate
+        if ((actual.valueOf() + 3600000) <= this.startDate || actual.valueOf() > this.endDate) {
+          classes.push('disabled');
+        } else if (hours === i) {
+          classes.push('active');
+        }
+        if (this.showMeridian && dates[this.language].meridiem.length === 2) {
+          meridian = (i < 12 ? dates[this.language].meridiem[0] : dates[this.language].meridiem[1]);
+          if (meridian !== meridianOld) {
+            if (meridianOld !== '') {
+              html.push('</fieldset>');
+            }
+            html.push('<fieldset class="hour"><legend>' + meridian.toUpperCase() + '</legend>');
+          }
+          meridianOld = meridian;
+          txt = (i % 12 ? i % 12 : 12);
+          if (i < 12) {
+            classes.push('hour_am');
+          } else {
+            classes.push('hour_pm');
+          }
+          html.push('<span class="' + classes.join(' ') + '">' + txt + '</span>');
+          if (i === 23) {
+            html.push('</fieldset>');
+          }
+        } else {
+          txt = i + ':00';
+          html.push('<span class="' + classes.join(' ') + '">' + txt + '</span>');
+        }
+      }
+      this.picker.find('.datetimepicker-hours td').html(html.join(''));
+
+      html = [];
+      txt = '';
+      meridian = '';
+      meridianOld = '';
+      var minutesDisabled = this.minutesDisabled || [];
+      d = new Date(this.viewDate);
+      for (var i = 0; i < 60; i += this.minuteStep) {
+        if (minutesDisabled.indexOf(i) !== -1) continue;
+        d.setUTCMinutes(i);
+        d.setUTCSeconds(0);
+        classes = this.onRenderMinute(d);
+        if (this.showMeridian && dates[this.language].meridiem.length === 2) {
+          meridian = (hours < 12 ? dates[this.language].meridiem[0] : dates[this.language].meridiem[1]);
+          if (meridian !== meridianOld) {
+            if (meridianOld !== '') {
+              html.push('</fieldset>');
+            }
+            html.push('<fieldset class="minute"><legend>' + meridian.toUpperCase() + '</legend>');
+          }
+          meridianOld = meridian;
+          txt = (hours % 12 ? hours % 12 : 12);
+          html.push('<span class="' + classes.join(' ') + '">' + txt + ':' + (i < 10 ? '0' + i : i) + '</span>');
+          if (i === 59) {
+            html.push('</fieldset>');
+          }
+        } else {
+          txt = i + ':00';
+          html.push('<span class="' + classes.join(' ') + '">' + hours + ':' + (i < 10 ? '0' + i : i) + '</span>');
+        }
+      }
+      this.picker.find('.datetimepicker-minutes td').html(html.join(''));
+
+      var currentYear = this.date.getUTCFullYear();
+      var months = this.setTitle('.datetimepicker-months', year)
+        .end()
+        .find('.month').removeClass('active');
+      if (currentYear === year) {
+        // getUTCMonths() returns 0 based, and we need to select the next one
+        // To cater bootstrap 2 we don't need to select the next one
+        months.eq(this.date.getUTCMonth()).addClass('active');
+      }
+      if (year < startYear || year > endYear) {
+        months.addClass('disabled');
+      }
+      if (year === startYear) {
+        months.slice(0, startMonth).addClass('disabled');
+      }
+      if (year === endYear) {
+        months.slice(endMonth).addClass('disabled');
+      }
+
+      html = '';
+      year = parseInt(year / 10, 10) * 10;
+      var yearCont = this.setTitle('.datetimepicker-years', year + '-' + (year + 9))
+        .end()
+        .find('td');
+      year -= 1;
+      d = new Date(this.viewDate);
+      for (var i = -1; i < 11; i++) {
+        d.setUTCFullYear(year);
+        classes = this.onRenderYear(d);
+        if (i === -1 || i === 10) {
+          classes.push(old);
+        }
+        html += '<span class="' + classes.join(' ') + '">' + year + '</span>';
+        year += 1;
+      }
+      yearCont.html(html);
+      this.place();
+    },
+
+    updateNavArrows: function () {
+      var d = new Date(this.viewDate),
+        year = d.getUTCFullYear(),
+        month = d.getUTCMonth(),
+        day = d.getUTCDate(),
+        hour = d.getUTCHours();
+      switch (this.viewMode) {
+        case 0:
+          if (year <= this.startDate.getUTCFullYear()
+            && month <= this.startDate.getUTCMonth()
+            && day <= this.startDate.getUTCDate()
+            && hour <= this.startDate.getUTCHours()) {
+            this.picker.find('.prev').css({visibility: 'hidden'});
+          } else {
+            this.picker.find('.prev').css({visibility: 'visible'});
+          }
+          if (year >= this.endDate.getUTCFullYear()
+            && month >= this.endDate.getUTCMonth()
+            && day >= this.endDate.getUTCDate()
+            && hour >= this.endDate.getUTCHours()) {
+            this.picker.find('.next').css({visibility: 'hidden'});
+          } else {
+            this.picker.find('.next').css({visibility: 'visible'});
+          }
+          break;
+        case 1:
+          if (year <= this.startDate.getUTCFullYear()
+            && month <= this.startDate.getUTCMonth()
+            && day <= this.startDate.getUTCDate()) {
+            this.picker.find('.prev').css({visibility: 'hidden'});
+          } else {
+            this.picker.find('.prev').css({visibility: 'visible'});
+          }
+          if (year >= this.endDate.getUTCFullYear()
+            && month >= this.endDate.getUTCMonth()
+            && day >= this.endDate.getUTCDate()) {
+            this.picker.find('.next').css({visibility: 'hidden'});
+          } else {
+            this.picker.find('.next').css({visibility: 'visible'});
+          }
+          break;
+        case 2:
+          if (year <= this.startDate.getUTCFullYear()
+            && month <= this.startDate.getUTCMonth()) {
+            this.picker.find('.prev').css({visibility: 'hidden'});
+          } else {
+            this.picker.find('.prev').css({visibility: 'visible'});
+          }
+          if (year >= this.endDate.getUTCFullYear()
+            && month >= this.endDate.getUTCMonth()) {
+            this.picker.find('.next').css({visibility: 'hidden'});
+          } else {
+            this.picker.find('.next').css({visibility: 'visible'});
+          }
+          break;
+        case 3:
+        case 4:
+          if (year <= this.startDate.getUTCFullYear()) {
+            this.picker.find('.prev').css({visibility: 'hidden'});
+          } else {
+            this.picker.find('.prev').css({visibility: 'visible'});
+          }
+          if (year >= this.endDate.getUTCFullYear()) {
+            this.picker.find('.next').css({visibility: 'hidden'});
+          } else {
+            this.picker.find('.next').css({visibility: 'visible'});
+          }
+          break;
+      }
+    },
+
+    mousewheel: function (e) {
+
+      e.preventDefault();
+      e.stopPropagation();
+
+      if (this.wheelPause) {
+        return;
+      }
+
+      this.wheelPause = true;
+
+      var originalEvent = e.originalEvent;
+
+      var delta = originalEvent.wheelDelta;
+
+      var mode = delta > 0 ? 1 : (delta === 0) ? 0 : -1;
+
+      if (this.wheelViewModeNavigationInverseDirection) {
+        mode = -mode;
+      }
+
+      this.showMode(mode);
+
+      setTimeout($.proxy(function () {
+
+        this.wheelPause = false
+
+      }, this), this.wheelViewModeNavigationDelay);
+
+    },
+
+    click: function (e) {
+      e.stopPropagation();
+      e.preventDefault();
+      var target = $(e.target).closest('span, td, th, legend');
+      if (target.is('.' + this.icontype)) {
+        target = $(target).parent().closest('span, td, th, legend');
+      }
+      if (target.length === 1) {
+        if (target.is('.disabled')) {
+          this.element.trigger({
+            type:      'outOfRange',
+            date:      this.viewDate,
+            startDate: this.startDate,
+            endDate:   this.endDate
+          });
+          return;
+        }
+        switch (target[0].nodeName.toLowerCase()) {
+          case 'th':
+            switch (target[0].className) {
+              case 'switch':
+                this.showMode(1);
+                break;
+              case 'prev':
+              case 'next':
+                var dir = DPGlobal.modes[this.viewMode].navStep * (target[0].className === 'prev' ? -1 : 1);
+                switch (this.viewMode) {
+                  case 0:
+                    this.viewDate = this.moveHour(this.viewDate, dir);
+                    break;
+                  case 1:
+                    this.viewDate = this.moveDate(this.viewDate, dir);
+                    break;
+                  case 2:
+                    this.viewDate = this.moveMonth(this.viewDate, dir);
+                    break;
+                  case 3:
+                  case 4:
+                    this.viewDate = this.moveYear(this.viewDate, dir);
+                    break;
+                }
+                this.fill();
+                this.element.trigger({
+                  type:      target[0].className + ':' + this.convertViewModeText(this.viewMode),
+                  date:      this.viewDate,
+                  startDate: this.startDate,
+                  endDate:   this.endDate
+                });
+                break;
+              case 'clear':
+                this.reset();
+                if (this.autoclose) {
+                  this.hide();
+                }
+                break;
+              case 'today':
+                var date = new Date();
+                date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), 0);
+
+                // Respect startDate and endDate.
+                if (date < this.startDate) date = this.startDate;
+                else if (date > this.endDate) date = this.endDate;
+
+                this.viewMode = this.startViewMode;
+                this.showMode(0);
+                this._setDate(date);
+                this.fill();
+                if (this.autoclose) {
+                  this.hide();
+                }
+                break;
+            }
+            break;
+          case 'span':
+            if (!target.is('.disabled')) {
+              var year = this.viewDate.getUTCFullYear(),
+                month = this.viewDate.getUTCMonth(),
+                day = this.viewDate.getUTCDate(),
+                hours = this.viewDate.getUTCHours(),
+                minutes = this.viewDate.getUTCMinutes(),
+                seconds = this.viewDate.getUTCSeconds();
+
+              if (target.is('.month')) {
+                this.viewDate.setUTCDate(1);
+                month = target.parent().find('span').index(target);
+                day = this.viewDate.getUTCDate();
+                this.viewDate.setUTCMonth(month);
+                this.element.trigger({
+                  type: 'changeMonth',
+                  date: this.viewDate
+                });
+                if (this.viewSelect >= 3) {
+                  this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0));
+                }
+              } else if (target.is('.year')) {
+                this.viewDate.setUTCDate(1);
+                year = parseInt(target.text(), 10) || 0;
+                this.viewDate.setUTCFullYear(year);
+                this.element.trigger({
+                  type: 'changeYear',
+                  date: this.viewDate
+                });
+                if (this.viewSelect >= 4) {
+                  this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0));
+                }
+              } else if (target.is('.hour')) {
+                hours = parseInt(target.text(), 10) || 0;
+                if (target.hasClass('hour_am') || target.hasClass('hour_pm')) {
+                  if (hours === 12 && target.hasClass('hour_am')) {
+                    hours = 0;
+                  } else if (hours !== 12 && target.hasClass('hour_pm')) {
+                    hours += 12;
+                  }
+                }
+                this.viewDate.setUTCHours(hours);
+                this.element.trigger({
+                  type: 'changeHour',
+                  date: this.viewDate
+                });
+                if (this.viewSelect >= 1) {
+                  this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0));
+                }
+              } else if (target.is('.minute')) {
+                minutes = parseInt(target.text().substr(target.text().indexOf(':') + 1), 10) || 0;
+                this.viewDate.setUTCMinutes(minutes);
+                this.element.trigger({
+                  type: 'changeMinute',
+                  date: this.viewDate
+                });
+                if (this.viewSelect >= 0) {
+                  this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0));
+                }
+              }
+              if (this.viewMode !== 0) {
+                var oldViewMode = this.viewMode;
+                this.showMode(-1);
+                this.fill();
+                if (oldViewMode === this.viewMode && this.autoclose) {
+                  this.hide();
+                }
+              } else {
+                this.fill();
+                if (this.autoclose) {
+                  this.hide();
+                }
+              }
+            }
+            break;
+          case 'td':
+            if (target.is('.day') && !target.is('.disabled')) {
+              var day = parseInt(target.text(), 10) || 1;
+              var year = this.viewDate.getUTCFullYear(),
+                month = this.viewDate.getUTCMonth(),
+                hours = this.viewDate.getUTCHours(),
+                minutes = this.viewDate.getUTCMinutes(),
+                seconds = this.viewDate.getUTCSeconds();
+              if (target.is('.old')) {
+                if (month === 0) {
+                  month = 11;
+                  year -= 1;
+                } else {
+                  month -= 1;
+                }
+              } else if (target.is('.new')) {
+                if (month === 11) {
+                  month = 0;
+                  year += 1;
+                } else {
+                  month += 1;
+                }
+              }
+              this.viewDate.setUTCFullYear(year);
+              this.viewDate.setUTCMonth(month, day);
+              this.element.trigger({
+                type: 'changeDay',
+                date: this.viewDate
+              });
+              if (this.viewSelect >= 2) {
+                this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0));
+              }
+            }
+            var oldViewMode = this.viewMode;
+            this.showMode(-1);
+            this.fill();
+            if (oldViewMode === this.viewMode && this.autoclose) {
+              this.hide();
+            }
+            break;
+        }
+      }
+    },
+
+    _setDate: function (date, which) {
+      if (!which || which === 'date')
+        this.date = date;
+      if (!which || which === 'view')
+        this.viewDate = date;
+      this.fill();
+      this.setValue();
+      var element;
+      if (this.isInput) {
+        element = this.element;
+      } else if (this.component) {
+        element = this.element.find('input');
+      }
+      if (element) {
+        element.change();
+      }
+      this.element.trigger({
+        type: 'changeDate',
+        date: this.getDate()
+      });
+      if(date === null)
+        this.date = this.viewDate;
+    },
+
+    moveMinute: function (date, dir) {
+      if (!dir) return date;
+      var new_date = new Date(date.valueOf());
+      //dir = dir > 0 ? 1 : -1;
+      new_date.setUTCMinutes(new_date.getUTCMinutes() + (dir * this.minuteStep));
+      return new_date;
+    },
+
+    moveHour: function (date, dir) {
+      if (!dir) return date;
+      var new_date = new Date(date.valueOf());
+      //dir = dir > 0 ? 1 : -1;
+      new_date.setUTCHours(new_date.getUTCHours() + dir);
+      return new_date;
+    },
+
+    moveDate: function (date, dir) {
+      if (!dir) return date;
+      var new_date = new Date(date.valueOf());
+      //dir = dir > 0 ? 1 : -1;
+      new_date.setUTCDate(new_date.getUTCDate() + dir);
+      return new_date;
+    },
+
+    moveMonth: function (date, dir) {
+      if (!dir) return date;
+      var new_date = new Date(date.valueOf()),
+        day = new_date.getUTCDate(),
+        month = new_date.getUTCMonth(),
+        mag = Math.abs(dir),
+        new_month, test;
+      dir = dir > 0 ? 1 : -1;
+      if (mag === 1) {
+        test = dir === -1
+          // If going back one month, make sure month is not current month
+          // (eg, Mar 31 -> Feb 31 === Feb 28, not Mar 02)
+          ? function () {
+          return new_date.getUTCMonth() === month;
+        }
+          // If going forward one month, make sure month is as expected
+          // (eg, Jan 31 -> Feb 31 === Feb 28, not Mar 02)
+          : function () {
+          return new_date.getUTCMonth() !== new_month;
+        };
+        new_month = month + dir;
+        new_date.setUTCMonth(new_month);
+        // Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11
+        if (new_month < 0 || new_month > 11)
+          new_month = (new_month + 12) % 12;
+      } else {
+        // For magnitudes >1, move one month at a time...
+        for (var i = 0; i < mag; i++)
+          // ...which might decrease the day (eg, Jan 31 to Feb 28, etc)...
+          new_date = this.moveMonth(new_date, dir);
+        // ...then reset the day, keeping it in the new month
+        new_month = new_date.getUTCMonth();
+        new_date.setUTCDate(day);
+        test = function () {
+          return new_month !== new_date.getUTCMonth();
+        };
+      }
+      // Common date-resetting loop -- if date is beyond end of month, make it
+      // end of month
+      while (test()) {
+        new_date.setUTCDate(--day);
+        new_date.setUTCMonth(new_month);
+      }
+      return new_date;
+    },
+
+    moveYear: function (date, dir) {
+      return this.moveMonth(date, dir * 12);
+    },
+
+    dateWithinRange: function (date) {
+      return date >= this.startDate && date <= this.endDate;
+    },
+
+    keydown: function (e) {
+      if (this.picker.is(':not(:visible)')) {
+        if (e.keyCode === 27) // allow escape to hide and re-show picker
+          this.show();
+        return;
+      }
+      var dateChanged = false,
+        dir, newDate, newViewDate;
+      switch (e.keyCode) {
+        case 27: // escape
+          this.hide();
+          e.preventDefault();
+          break;
+        case 37: // left
+        case 39: // right
+          if (!this.keyboardNavigation) break;
+          dir = e.keyCode === 37 ? -1 : 1;
+          var viewMode = this.viewMode;
+          if (e.ctrlKey) {
+            viewMode += 2;
+          } else if (e.shiftKey) {
+            viewMode += 1;
+          }
+          if (viewMode === 4) {
+            newDate = this.moveYear(this.date, dir);
+            newViewDate = this.moveYear(this.viewDate, dir);
+          } else if (viewMode === 3) {
+            newDate = this.moveMonth(this.date, dir);
+            newViewDate = this.moveMonth(this.viewDate, dir);
+          } else if (viewMode === 2) {
+            newDate = this.moveDate(this.date, dir);
+            newViewDate = this.moveDate(this.viewDate, dir);
+          } else if (viewMode === 1) {
+            newDate = this.moveHour(this.date, dir);
+            newViewDate = this.moveHour(this.viewDate, dir);
+          } else if (viewMode === 0) {
+            newDate = this.moveMinute(this.date, dir);
+            newViewDate = this.moveMinute(this.viewDate, dir);
+          }
+          if (this.dateWithinRange(newDate)) {
+            this.date = newDate;
+            this.viewDate = newViewDate;
+            this.setValue();
+            this.update();
+            e.preventDefault();
+            dateChanged = true;
+          }
+          break;
+        case 38: // up
+        case 40: // down
+          if (!this.keyboardNavigation) break;
+          dir = e.keyCode === 38 ? -1 : 1;
+          viewMode = this.viewMode;
+          if (e.ctrlKey) {
+            viewMode += 2;
+          } else if (e.shiftKey) {
+            viewMode += 1;
+          }
+          if (viewMode === 4) {
+            newDate = this.moveYear(this.date, dir);
+            newViewDate = this.moveYear(this.viewDate, dir);
+          } else if (viewMode === 3) {
+            newDate = this.moveMonth(this.date, dir);
+            newViewDate = this.moveMonth(this.viewDate, dir);
+          } else if (viewMode === 2) {
+            newDate = this.moveDate(this.date, dir * 7);
+            newViewDate = this.moveDate(this.viewDate, dir * 7);
+          } else if (viewMode === 1) {
+            if (this.showMeridian) {
+              newDate = this.moveHour(this.date, dir * 6);
+              newViewDate = this.moveHour(this.viewDate, dir * 6);
+            } else {
+              newDate = this.moveHour(this.date, dir * 4);
+              newViewDate = this.moveHour(this.viewDate, dir * 4);
+            }
+          } else if (viewMode === 0) {
+            newDate = this.moveMinute(this.date, dir * 4);
+            newViewDate = this.moveMinute(this.viewDate, dir * 4);
+          }
+          if (this.dateWithinRange(newDate)) {
+            this.date = newDate;
+            this.viewDate = newViewDate;
+            this.setValue();
+            this.update();
+            e.preventDefault();
+            dateChanged = true;
+          }
+          break;
+        case 13: // enter
+          if (this.viewMode !== 0) {
+            var oldViewMode = this.viewMode;
+            this.showMode(-1);
+            this.fill();
+            if (oldViewMode === this.viewMode && this.autoclose) {
+              this.hide();
+            }
+          } else {
+            this.fill();
+            if (this.autoclose) {
+              this.hide();
+            }
+          }
+          e.preventDefault();
+          break;
+        case 9: // tab
+          this.hide();
+          break;
+      }
+      if (dateChanged) {
+        var element;
+        if (this.isInput) {
+          element = this.element;
+        } else if (this.component) {
+          element = this.element.find('input');
+        }
+        if (element) {
+          element.change();
+        }
+        this.element.trigger({
+          type: 'changeDate',
+          date: this.getDate()
+        });
+      }
+    },
+
+    showMode: function (dir) {
+      if (dir) {
+        var newViewMode = Math.max(0, Math.min(DPGlobal.modes.length - 1, this.viewMode + dir));
+        if (newViewMode >= this.minView && newViewMode <= this.maxView) {
+          this.element.trigger({
+            type:        'changeMode',
+            date:        this.viewDate,
+            oldViewMode: this.viewMode,
+            newViewMode: newViewMode
+          });
+
+          this.viewMode = newViewMode;
+        }
+      }
+      /*
+       vitalets: fixing bug of very special conditions:
+       jquery 1.7.1 + webkit + show inline datetimepicker in bootstrap popover.
+       Method show() does not set display css correctly and datetimepicker is not shown.
+       Changed to .css('display', 'block') solve the problem.
+       See https://github.com/vitalets/x-editable/issues/37
+
+       In jquery 1.7.2+ everything works fine.
+       */
+      //this.picker.find('>div').hide().filter('.datetimepicker-'+DPGlobal.modes[this.viewMode].clsName).show();
+      this.picker.find('>div').hide().filter('.datetimepicker-' + DPGlobal.modes[this.viewMode].clsName).css('display', 'block');
+      this.updateNavArrows();
+    },
+
+    reset: function () {
+      this._setDate(null, 'date');
+    },
+
+    convertViewModeText:  function (viewMode) {
+      switch (viewMode) {
+        case 4:
+          return 'decade';
+        case 3:
+          return 'year';
+        case 2:
+          return 'month';
+        case 1:
+          return 'day';
+        case 0:
+          return 'hour';
+      }
+    }
+  };
+
+  var old = $.fn.datetimepicker;
+  $.fn.datetimepicker = function (option) {
+    var args = Array.apply(null, arguments);
+    args.shift();
+    var internal_return;
+    this.each(function () {
+      var $this = $(this),
+        data = $this.data('datetimepicker'),
+        options = typeof option === 'object' && option;
+      if (!data) {
+        $this.data('datetimepicker', (data = new Datetimepicker(this, $.extend({}, $.fn.datetimepicker.defaults, options))));
+      }
+      if (typeof option === 'string' && typeof data[option] === 'function') {
+        internal_return = data[option].apply(data, args);
+        if (internal_return !== undefined) {
+          return false;
+        }
+      }
+    });
+    if (internal_return !== undefined)
+      return internal_return;
+    else
+      return this;
+  };
+
+  $.fn.datetimepicker.defaults = {
+  };
+  $.fn.datetimepicker.Constructor = Datetimepicker;
+  var dates = $.fn.datetimepicker.dates = {
+  'zh-cn': {
+      days:        ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"],
+      daysShort:   ["周日", "周一", "周二", "周三", "周四", "周五", "周六", "周日"],
+      daysMin:     ["日", "一", "二", "三", "四", "五", "六", "日"],
+      months:      ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
+      monthsShort: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
+      meridiem:    ["上午", "下午"],
+      suffix:      ["st", "nd", "rd", "th"],
+      today:       "今天",
+      clear:       "清除"
+    },
+    en: {
+      days:        ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'],
+      daysShort:   ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
+      daysMin:     ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su'],
+      months:      ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
+      monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
+      meridiem:    ['am', 'pm'],
+      suffix:      ['st', 'nd', 'rd', 'th'],
+      today:       'Today',
+      clear:       'Clear'
+    }
+  };
+
+  var DPGlobal = {
+    modes:            [
+      {
+        clsName: 'minutes',
+        navFnc:  'Hours',
+        navStep: 1
+      },
+      {
+        clsName: 'hours',
+        navFnc:  'Date',
+        navStep: 1
+      },
+      {
+        clsName: 'days',
+        navFnc:  'Month',
+        navStep: 1
+      },
+      {
+        clsName: 'months',
+        navFnc:  'FullYear',
+        navStep: 1
+      },
+      {
+        clsName: 'years',
+        navFnc:  'FullYear',
+        navStep: 10
+      }
+    ],
+    isLeapYear:       function (year) {
+      return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0))
+    },
+    getDaysInMonth:   function (year, month) {
+      return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]
+    },
+    getDefaultFormat: function (type, field) {
+      if (type === 'standard') {
+        if (field === 'input')
+          return 'yyyy-mm-dd hh:ii';
+        else
+          return 'yyyy-mm-dd hh:ii:ss';
+      } else if (type === 'php') {
+        if (field === 'input')
+          return 'Y-m-d H:i';
+        else
+          return 'Y-m-d H:i:s';
+      } else {
+        throw new Error('Invalid format type.');
+      }
+    },
+    validParts: function (type) {
+      if (type === 'standard') {
+        return /t|hh?|HH?|p|P|z|Z|ii?|ss?|dd?|DD?|mm?|MM?|yy(?:yy)?/g;
+      } else if (type === 'php') {
+        return /[dDjlNwzFmMnStyYaABgGhHis]/g;
+      } else {
+        throw new Error('Invalid format type.');
+      }
+    },
+    nonpunctuation: /[^ -\/:-@\[-`{-~\t\n\rTZ]+/g,
+    parseFormat: function (format, type) {
+      // IE treats \0 as a string end in inputs (truncating the value),
+      // so it's a bad format delimiter, anyway
+      var separators = format.replace(this.validParts(type), '\0').split('\0'),
+        parts = format.match(this.validParts(type));
+      if (!separators || !separators.length || !parts || parts.length === 0) {
+        throw new Error('Invalid date format.');
+      }
+      return {separators: separators, parts: parts};
+    },
+    parseDate: function (date, format, language, type, timezone) {
+      if (date instanceof Date) {
+        var dateUTC = new Date(date.valueOf() - date.getTimezoneOffset() * 60000);
+        dateUTC.setMilliseconds(0);
+        return dateUTC;
+      }
+      if (/^\d{4}\-\d{1,2}\-\d{1,2}$/.test(date)) {
+        format = this.parseFormat('yyyy-mm-dd', type);
+      }
+      if (/^\d{4}\-\d{1,2}\-\d{1,2}[T ]\d{1,2}\:\d{1,2}$/.test(date)) {
+        format = this.parseFormat('yyyy-mm-dd hh:ii', type);
+      }
+      if (/^\d{4}\-\d{1,2}\-\d{1,2}[T ]\d{1,2}\:\d{1,2}\:\d{1,2}[Z]{0,1}$/.test(date)) {
+        format = this.parseFormat('yyyy-mm-dd hh:ii:ss', type);
+      }
+      if (/^[-+]\d+[dmwy]([\s,]+[-+]\d+[dmwy])*$/.test(date)) {
+        var part_re = /([-+]\d+)([dmwy])/,
+          parts = date.match(/([-+]\d+)([dmwy])/g),
+          part, dir;
+        date = new Date();
+        for (var i = 0; i < parts.length; i++) {
+          part = part_re.exec(parts[i]);
+          dir = parseInt(part[1]);
+          switch (part[2]) {
+            case 'd':
+              date.setUTCDate(date.getUTCDate() + dir);
+              break;
+            case 'm':
+              date = Datetimepicker.prototype.moveMonth.call(Datetimepicker.prototype, date, dir);
+              break;
+            case 'w':
+              date.setUTCDate(date.getUTCDate() + dir * 7);
+              break;
+            case 'y':
+              date = Datetimepicker.prototype.moveYear.call(Datetimepicker.prototype, date, dir);
+              break;
+          }
+        }
+        return UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds(), 0);
+      }
+      var parts = date && date.toString().match(this.nonpunctuation) || [],
+        date = new Date(0, 0, 0, 0, 0, 0, 0),
+        parsed = {},
+        setters_order = ['hh', 'h', 'ii', 'i', 'ss', 's', 'yyyy', 'yy', 'M', 'MM', 'm', 'mm', 'D', 'DD', 'd', 'dd', 'H', 'HH', 'p', 'P', 'z', 'Z'],
+        setters_map = {
+          hh:   function (d, v) {
+            return d.setUTCHours(v);
+          },
+          h:    function (d, v) {
+            return d.setUTCHours(v);
+          },
+          HH:   function (d, v) {
+            return d.setUTCHours(v === 12 ? 0 : v);
+          },
+          H:    function (d, v) {
+            return d.setUTCHours(v === 12 ? 0 : v);
+          },
+          ii:   function (d, v) {
+            return d.setUTCMinutes(v);
+          },
+          i:    function (d, v) {
+            return d.setUTCMinutes(v);
+          },
+          ss:   function (d, v) {
+            return d.setUTCSeconds(v);
+          },
+          s:    function (d, v) {
+            return d.setUTCSeconds(v);
+          },
+          yyyy: function (d, v) {
+            return d.setUTCFullYear(v);
+          },
+          yy:   function (d, v) {
+            return d.setUTCFullYear(2000 + v);
+          },
+          m:    function (d, v) {
+            v -= 1;
+            while (v < 0) v += 12;
+            v %= 12;
+            d.setUTCMonth(v);
+            while (d.getUTCMonth() !== v)
+              if (isNaN(d.getUTCMonth()))
+                return d;
+              else
+                d.setUTCDate(d.getUTCDate() - 1);
+            return d;
+          },
+          d:    function (d, v) {
+            return d.setUTCDate(v);
+          },
+          p:    function (d, v) {
+            return d.setUTCHours(v === 1 ? d.getUTCHours() + 12 : d.getUTCHours());
+          },
+          z:    function () {
+            return timezone
+          }
+        },
+        val, filtered, part;
+      setters_map['M'] = setters_map['MM'] = setters_map['mm'] = setters_map['m'];
+      setters_map['dd'] = setters_map['d'];
+      setters_map['P'] = setters_map['p'];
+      setters_map['Z'] = setters_map['z'];
+      date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds());
+      if (parts.length === format.parts.length) {
+        for (var i = 0, cnt = format.parts.length; i < cnt; i++) {
+          val = parseInt(parts[i], 10);
+          part = format.parts[i];
+          if (isNaN(val)) {
+            switch (part) {
+              case 'MM':
+                filtered = $(dates[language].months).filter(function () {
+                  var m = this.slice(0, parts[i].length),
+                    p = parts[i].slice(0, m.length);
+                  return m === p;
+                });
+                val = $.inArray(filtered[0], dates[language].months) + 1;
+                break;
+              case 'M':
+                filtered = $(dates[language].monthsShort).filter(function () {
+                  var m = this.slice(0, parts[i].length),
+                    p = parts[i].slice(0, m.length);
+                  return m.toLowerCase() === p.toLowerCase();
+                });
+                val = $.inArray(filtered[0], dates[language].monthsShort) + 1;
+                break;
+              case 'p':
+              case 'P':
+                val = $.inArray(parts[i].toLowerCase(), dates[language].meridiem);
+                break;
+              case 'z':
+              case 'Z':
+                timezone;
+                break;
+
+            }
+          }
+          parsed[part] = val;
+        }
+        for (var i = 0, s; i < setters_order.length; i++) {
+          s = setters_order[i];
+          if (s in parsed && !isNaN(parsed[s]))
+            setters_map[s](date, parsed[s])
+        }
+      }
+      return date;
+    },
+    formatDate:       function (date, format, language, type, timezone) {
+      if (date === null) {
+        return '';
+      }
+      var val;
+      if (type === 'standard') {
+        val = {
+          t:    date.getTime(),
+          // year
+          yy:   date.getUTCFullYear().toString().substring(2),
+          yyyy: date.getUTCFullYear(),
+          // month
+          m:    date.getUTCMonth() + 1,
+          M:    dates[language].monthsShort[date.getUTCMonth()],
+          MM:   dates[language].months[date.getUTCMonth()],
+          // day
+          d:    date.getUTCDate(),
+          D:    dates[language].daysShort[date.getUTCDay()],
+          DD:   dates[language].days[date.getUTCDay()],
+          p:    (dates[language].meridiem.length === 2 ? dates[language].meridiem[date.getUTCHours() < 12 ? 0 : 1] : ''),
+          // hour
+          h:    date.getUTCHours(),
+          // minute
+          i:    date.getUTCMinutes(),
+          // second
+          s:    date.getUTCSeconds(),
+          // timezone
+          z:    timezone
+        };
+
+        if (dates[language].meridiem.length === 2) {
+          val.H = (val.h % 12 === 0 ? 12 : val.h % 12);
+        }
+        else {
+          val.H = val.h;
+        }
+        val.HH = (val.H < 10 ? '0' : '') + val.H;
+        val.P = val.p.toUpperCase();
+        val.Z = val.z;
+        val.hh = (val.h < 10 ? '0' : '') + val.h;
+        val.ii = (val.i < 10 ? '0' : '') + val.i;
+        val.ss = (val.s < 10 ? '0' : '') + val.s;
+        val.dd = (val.d < 10 ? '0' : '') + val.d;
+        val.mm = (val.m < 10 ? '0' : '') + val.m;
+      } else if (type === 'php') {
+        // php format
+        val = {
+          // year
+          y: date.getUTCFullYear().toString().substring(2),
+          Y: date.getUTCFullYear(),
+          // month
+          F: dates[language].months[date.getUTCMonth()],
+          M: dates[language].monthsShort[date.getUTCMonth()],
+          n: date.getUTCMonth() + 1,
+          t: DPGlobal.getDaysInMonth(date.getUTCFullYear(), date.getUTCMonth()),
+          // day
+          j: date.getUTCDate(),
+          l: dates[language].days[date.getUTCDay()],
+          D: dates[language].daysShort[date.getUTCDay()],
+          w: date.getUTCDay(), // 0 -> 6
+          N: (date.getUTCDay() === 0 ? 7 : date.getUTCDay()),       // 1 -> 7
+          S: (date.getUTCDate() % 10 <= dates[language].suffix.length ? dates[language].suffix[date.getUTCDate() % 10 - 1] : ''),
+          // hour
+          a: (dates[language].meridiem.length === 2 ? dates[language].meridiem[date.getUTCHours() < 12 ? 0 : 1] : ''),
+          g: (date.getUTCHours() % 12 === 0 ? 12 : date.getUTCHours() % 12),
+          G: date.getUTCHours(),
+          // minute
+          i: date.getUTCMinutes(),
+          // second
+          s: date.getUTCSeconds()
+        };
+        val.m = (val.n < 10 ? '0' : '') + val.n;
+        val.d = (val.j < 10 ? '0' : '') + val.j;
+        val.A = val.a.toString().toUpperCase();
+        val.h = (val.g < 10 ? '0' : '') + val.g;
+        val.H = (val.G < 10 ? '0' : '') + val.G;
+        val.i = (val.i < 10 ? '0' : '') + val.i;
+        val.s = (val.s < 10 ? '0' : '') + val.s;
+      } else {
+        throw new Error('Invalid format type.');
+      }
+      var date = [],
+        seps = $.extend([], format.separators);
+      for (var i = 0, cnt = format.parts.length; i < cnt; i++) {
+        if (seps.length) {
+          date.push(seps.shift());
+        }
+        date.push(val[format.parts[i]]);
+      }
+      if (seps.length) {
+        date.push(seps.shift());
+      }
+      return date.join('');
+    },
+    convertViewMode:  function (viewMode) {
+      switch (viewMode) {
+        case 4:
+        case 'decade':
+          viewMode = 4;
+          break;
+        case 3:
+        case 'year':
+          viewMode = 3;
+          break;
+        case 2:
+        case 'month':
+          viewMode = 2;
+          break;
+        case 1:
+        case 'day':
+          viewMode = 1;
+          break;
+        case 0:
+        case 'hour':
+          viewMode = 0;
+          break;
+      }
+
+      return viewMode;
+    },
+    headTemplate: '<thead>' +
+                '<tr>' +
+                '<th class="prev"><i class="{iconType} {leftArrow}"/></th>' +
+                '<th colspan="5" class="switch"></th>' +
+                '<th class="next"><i class="{iconType} {rightArrow}"/></th>' +
+                '</tr>' +
+      '</thead>',
+    headTemplateV3: '<thead>' +
+                '<tr>' +
+                '<th class="prev"><span class="{iconType} {leftArrow}"></span> </th>' +
+                '<th colspan="5" class="switch"></th>' +
+                '<th class="next"><span class="{iconType} {rightArrow}"></span> </th>' +
+                '</tr>' +
+      '</thead>',
+    contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>',
+    footTemplate: '<tfoot>' + 
+                    '<tr><th colspan="7" class="today"></th></tr>' +
+                    '<tr><th colspan="7" class="clear"></th></tr>' +
+                  '</tfoot>'
+  };
+  DPGlobal.template = '<div class="datetimepicker">' +
+    '<div class="datetimepicker-minutes">' +
+    '<table class=" table-condensed">' +
+    DPGlobal.headTemplate +
+    DPGlobal.contTemplate +
+    DPGlobal.footTemplate +
+    '</table>' +
+    '</div>' +
+    '<div class="datetimepicker-hours">' +
+    '<table class=" table-condensed">' +
+    DPGlobal.headTemplate +
+    DPGlobal.contTemplate +
+    DPGlobal.footTemplate +
+    '</table>' +
+    '</div>' +
+    '<div class="datetimepicker-days">' +
+    '<table class=" table-condensed">' +
+    DPGlobal.headTemplate +
+    '<tbody></tbody>' +
+    DPGlobal.footTemplate +
+    '</table>' +
+    '</div>' +
+    '<div class="datetimepicker-months">' +
+    '<table class="table-condensed">' +
+    DPGlobal.headTemplate +
+    DPGlobal.contTemplate +
+    DPGlobal.footTemplate +
+    '</table>' +
+    '</div>' +
+    '<div class="datetimepicker-years">' +
+    '<table class="table-condensed">' +
+    DPGlobal.headTemplate +
+    DPGlobal.contTemplate +
+    DPGlobal.footTemplate +
+    '</table>' +
+    '</div>' +
+    '</div>';
+  DPGlobal.templateV3 = '<div class="datetimepicker">' +
+    '<div class="datetimepicker-minutes">' +
+    '<table class=" table-condensed">' +
+    DPGlobal.headTemplateV3 +
+    DPGlobal.contTemplate +
+    DPGlobal.footTemplate +
+    '</table>' +
+    '</div>' +
+    '<div class="datetimepicker-hours">' +
+    '<table class=" table-condensed">' +
+    DPGlobal.headTemplateV3 +
+    DPGlobal.contTemplate +
+    DPGlobal.footTemplate +
+    '</table>' +
+    '</div>' +
+    '<div class="datetimepicker-days">' +
+    '<table class=" table-condensed">' +
+    DPGlobal.headTemplateV3 +
+    '<tbody></tbody>' +
+    DPGlobal.footTemplate +
+    '</table>' +
+    '</div>' +
+    '<div class="datetimepicker-months">' +
+    '<table class="table-condensed">' +
+    DPGlobal.headTemplateV3 +
+    DPGlobal.contTemplate +
+    DPGlobal.footTemplate +
+    '</table>' +
+    '</div>' +
+    '<div class="datetimepicker-years">' +
+    '<table class="table-condensed">' +
+    DPGlobal.headTemplateV3 +
+    DPGlobal.contTemplate +
+    DPGlobal.footTemplate +
+    '</table>' +
+    '</div>' +
+    '</div>';
+  $.fn.datetimepicker.DPGlobal = DPGlobal;
+
+  /* DATETIMEPICKER NO CONFLICT
+   * =================== */
+
+  $.fn.datetimepicker.noConflict = function () {
+    $.fn.datetimepicker = old;
+    return this;
+  };
+
+  /* DATETIMEPICKER DATA-API
+   * ================== */
+
+  $(document).on(
+    'focus.datetimepicker.data-api click.datetimepicker.data-api',
+    '[data-provide="datetimepicker"]',
+    function (e) {
+      var $this = $(this);
+      if ($this.data('datetimepicker')) return;
+      e.preventDefault();
+      // component click requires us to explicitly show it
+      $this.datetimepicker('show');
+    }
+  );
+  $(function () {
+    $('[data-provide="datetimepicker-inline"]').datetimepicker();
+  });
+
+}));
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/datapicker/bootstrap-datetimepicker.min.css b/ruoyi-admin/src/main/resources/static/ajax/libs/datapicker/bootstrap-datetimepicker.min.css
new file mode 100644
index 0000000..78485fe
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/datapicker/bootstrap-datetimepicker.min.css
@@ -0,0 +1,9 @@
+/*!
+ * Datetimepicker for Bootstrap
+ *
+ * Copyright 2012 Stefan Petre
+ * Improvements by Andrew Rowls
+ * Licensed under the Apache License v2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */.datetimepicker{padding:4px;margin-top:1px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;direction:ltr}.datetimepicker-inline{width:220px}.datetimepicker.datetimepicker-rtl{direction:rtl}.datetimepicker.datetimepicker-rtl table tr td span{float:right}.datetimepicker-dropdown,.datetimepicker-dropdown-left{top:0;left:0}[class*=" datetimepicker-dropdown"]:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-bottom-color:rgba(0,0,0,0.2);position:absolute}[class*=" datetimepicker-dropdown"]:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #fff;position:absolute}[class*=" datetimepicker-dropdown-top"]:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-top:7px solid #ccc;border-top-color:rgba(0,0,0,0.2);border-bottom:0}[class*=" datetimepicker-dropdown-top"]:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-top:6px solid #fff;border-bottom:0}.datetimepicker-dropdown-bottom-left:before{top:-7px;right:6px}.datetimepicker-dropdown-bottom-left:after{top:-6px;right:7px}.datetimepicker-dropdown-bottom-right:before{top:-7px;left:6px}.datetimepicker-dropdown-bottom-right:after{top:-6px;left:7px}.datetimepicker-dropdown-top-left:before{bottom:-7px;right:6px}.datetimepicker-dropdown-top-left:after{bottom:-6px;right:7px}.datetimepicker-dropdown-top-right:before{bottom:-7px;left:6px}.datetimepicker-dropdown-top-right:after{bottom:-6px;left:7px}.datetimepicker>div{display:none}.datetimepicker.minutes div.datetimepicker-minutes{display:block}.datetimepicker.hours div.datetimepicker-hours{display:block}.datetimepicker.days div.datetimepicker-days{display:block}.datetimepicker.months div.datetimepicker-months{display:block}.datetimepicker.years div.datetimepicker-years{display:block}.datetimepicker table{margin:0}.datetimepicker td,.datetimepicker th{text-align:center;width:20px;height:20px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;border:0}.table-striped .datetimepicker table tr td,.table-striped .datetimepicker table tr th{background-color:transparent}.datetimepicker table tr td.minute:hover{background:#eee;cursor:pointer}.datetimepicker table tr td.hour:hover{background:#eee;cursor:pointer}.datetimepicker table tr td.day:hover{background:#eee;cursor:pointer}.datetimepicker table tr td.old,.datetimepicker table tr td.new{color:#999}.datetimepicker table tr td.disabled,.datetimepicker table tr td.disabled:hover{background:0;color:#999;cursor:default}.datetimepicker table tr td.today,.datetimepicker table tr td.today:hover,.datetimepicker table tr td.today.disabled,.datetimepicker table tr td.today.disabled:hover{background-color:#fde19a;background-image:-moz-linear-gradient(top,#fdd49a,#fdf59a);background-image:-ms-linear-gradient(top,#fdd49a,#fdf59a);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fdd49a),to(#fdf59a));background-image:-webkit-linear-gradient(top,#fdd49a,#fdf59a);background-image:-o-linear-gradient(top,#fdd49a,#fdf59a);background-image:linear-gradient(to bottom,#fdd49a,#fdf59a);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a',endColorstr='#fdf59a',GradientType=0);border-color:#fdf59a #fdf59a #fbed50;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.datetimepicker table tr td.today:hover,.datetimepicker table tr td.today:hover:hover,.datetimepicker table tr td.today.disabled:hover,.datetimepicker table tr td.today.disabled:hover:hover,.datetimepicker table tr td.today:active,.datetimepicker table tr td.today:hover:active,.datetimepicker table tr td.today.disabled:active,.datetimepicker table tr td.today.disabled:hover:active,.datetimepicker table tr td.today.active,.datetimepicker table tr td.today:hover.active,.datetimepicker table tr td.today.disabled.active,.datetimepicker table tr td.today.disabled:hover.active,.datetimepicker table tr td.today.disabled,.datetimepicker table tr td.today:hover.disabled,.datetimepicker table tr td.today.disabled.disabled,.datetimepicker table tr td.today.disabled:hover.disabled,.datetimepicker table tr td.today[disabled],.datetimepicker table tr td.today:hover[disabled],.datetimepicker table tr td.today.disabled[disabled],.datetimepicker table tr td.today.disabled:hover[disabled]{background-color:#fdf59a}.datetimepicker table tr td.today:active,.datetimepicker table tr td.today:hover:active,.datetimepicker table tr td.today.disabled:active,.datetimepicker table tr td.today.disabled:hover:active,.datetimepicker table tr td.today.active,.datetimepicker table tr td.today:hover.active,.datetimepicker table tr td.today.disabled.active,.datetimepicker table tr td.today.disabled:hover.active{background-color:#fbf069}.datetimepicker table tr td.active,.datetimepicker table tr td.active:hover,.datetimepicker table tr td.active.disabled,.datetimepicker table tr td.active.disabled:hover{background-color:#006dcc;background-image:-moz-linear-gradient(top,#08c,#04c);background-image:-ms-linear-gradient(top,#08c,#04c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(top,#08c,#04c);background-image:-o-linear-gradient(top,#08c,#04c);background-image:linear-gradient(to bottom,#08c,#04c);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc',endColorstr='#0044cc',GradientType=0);border-color:#04c #04c #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.datetimepicker table tr td.active:hover,.datetimepicker table tr td.active:hover:hover,.datetimepicker table tr td.active.disabled:hover,.datetimepicker table tr td.active.disabled:hover:hover,.datetimepicker table tr td.active:active,.datetimepicker table tr td.active:hover:active,.datetimepicker table tr td.active.disabled:active,.datetimepicker table tr td.active.disabled:hover:active,.datetimepicker table tr td.active.active,.datetimepicker table tr td.active:hover.active,.datetimepicker table tr td.active.disabled.active,.datetimepicker table tr td.active.disabled:hover.active,.datetimepicker table tr td.active.disabled,.datetimepicker table tr td.active:hover.disabled,.datetimepicker table tr td.active.disabled.disabled,.datetimepicker table tr td.active.disabled:hover.disabled,.datetimepicker table tr td.active[disabled],.datetimepicker table tr td.active:hover[disabled],.datetimepicker table tr td.active.disabled[disabled],.datetimepicker table tr td.active.disabled:hover[disabled]{background-color:#04c}.datetimepicker table tr td.active:active,.datetimepicker table tr td.active:hover:active,.datetimepicker table tr td.active.disabled:active,.datetimepicker table tr td.active.disabled:hover:active,.datetimepicker table tr td.active.active,.datetimepicker table tr td.active:hover.active,.datetimepicker table tr td.active.disabled.active,.datetimepicker table tr td.active.disabled:hover.active{background-color:#039}.datetimepicker table tr td span{display:block;width:23%;height:54px;line-height:54px;float:left;margin:1%;cursor:pointer;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.datetimepicker .datetimepicker-hours span{height:26px;line-height:26px}.datetimepicker .datetimepicker-hours table tr td span.hour_am,.datetimepicker .datetimepicker-hours table tr td span.hour_pm{width:14.6%}.datetimepicker .datetimepicker-hours fieldset legend,.datetimepicker .datetimepicker-minutes fieldset legend{margin-bottom:inherit;line-height:30px}.datetimepicker .datetimepicker-minutes span{height:26px;line-height:26px}.datetimepicker table tr td span:hover{background:#eee}.datetimepicker table tr td span.disabled,.datetimepicker table tr td span.disabled:hover{background:0;color:#999;cursor:default}.datetimepicker table tr td span.active,.datetimepicker table tr td span.active:hover,.datetimepicker table tr td span.active.disabled,.datetimepicker table tr td span.active.disabled:hover{background-color:#006dcc;background-image:-moz-linear-gradient(top,#08c,#04c);background-image:-ms-linear-gradient(top,#08c,#04c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(top,#08c,#04c);background-image:-o-linear-gradient(top,#08c,#04c);background-image:linear-gradient(to bottom,#08c,#04c);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc',endColorstr='#0044cc',GradientType=0);border-color:#04c #04c #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.datetimepicker table tr td span.active:hover,.datetimepicker table tr td span.active:hover:hover,.datetimepicker table tr td span.active.disabled:hover,.datetimepicker table tr td span.active.disabled:hover:hover,.datetimepicker table tr td span.active:active,.datetimepicker table tr td span.active:hover:active,.datetimepicker table tr td span.active.disabled:active,.datetimepicker table tr td span.active.disabled:hover:active,.datetimepicker table tr td span.active.active,.datetimepicker table tr td span.active:hover.active,.datetimepicker table tr td span.active.disabled.active,.datetimepicker table tr td span.active.disabled:hover.active,.datetimepicker table tr td span.active.disabled,.datetimepicker table tr td span.active:hover.disabled,.datetimepicker table tr td span.active.disabled.disabled,.datetimepicker table tr td span.active.disabled:hover.disabled,.datetimepicker table tr td span.active[disabled],.datetimepicker table tr td span.active:hover[disabled],.datetimepicker table tr td span.active.disabled[disabled],.datetimepicker table tr td span.active.disabled:hover[disabled]{background-color:#04c}.datetimepicker table tr td span.active:active,.datetimepicker table tr td span.active:hover:active,.datetimepicker table tr td span.active.disabled:active,.datetimepicker table tr td span.active.disabled:hover:active,.datetimepicker table tr td span.active.active,.datetimepicker table tr td span.active:hover.active,.datetimepicker table tr td span.active.disabled.active,.datetimepicker table tr td span.active.disabled:hover.active{background-color:#039}.datetimepicker table tr td span.old{color:#999}.datetimepicker th.switch{width:145px}.datetimepicker th span.glyphicon{pointer-events:none}.datetimepicker thead tr:first-child th,.datetimepicker tfoot th{cursor:pointer}.datetimepicker thead tr:first-child th:hover,.datetimepicker tfoot th:hover{background:#eee}.input-append.date .add-on i,.input-prepend.date .add-on i,.input-group.date .input-group-addon span{cursor:pointer;width:14px;height:14px}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/datapicker/bootstrap-datetimepicker.min.js b/ruoyi-admin/src/main/resources/static/ajax/libs/datapicker/bootstrap-datetimepicker.min.js
new file mode 100644
index 0000000..7756ee5
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/datapicker/bootstrap-datetimepicker.min.js
@@ -0,0 +1 @@
+(function(factory){if(typeof define==="function"&&define.amd){define(["jquery"],factory)}else{if(typeof exports==="object"){factory(require("jquery"))}else{factory(jQuery)}}}(function($,undefined){if(!("indexOf" in Array.prototype)){Array.prototype.indexOf=function(find,i){if(i===undefined){i=0}if(i<0){i+=this.length}if(i<0){i=0}for(var n=this.length;i<n;i++){if(i in this&&this[i]===find){return i}}return -1}}function timeZoneAbbreviation(){var abbreviation,date,formattedStr,i,len,matchedStrings,ref,str;date=(new Date()).toString();formattedStr=((ref=date.split("(")[1])!=null?ref.slice(0,-1):0)||date.split(" ");if(formattedStr instanceof Array){matchedStrings=[];for(var i=0,len=formattedStr.length;i<len;i++){str=formattedStr[i];if((abbreviation=(ref=str.match(/\b[A-Z]+\b/))!==null)?ref[0]:0){matchedStrings.push(abbreviation)}}formattedStr=matchedStrings.pop()}return formattedStr}function UTCDate(){return new Date(Date.UTC.apply(Date,arguments))}var Datetimepicker=function(element,options){var that=this;this.element=$(element);this.container=options.container||"body";this.language=options.language||this.element.data("date-language")||"zh-cn";this.language=this.language in dates?this.language:this.language.split("-")[0];this.language=this.language in dates?this.language:"en";this.isRTL=dates[this.language].rtl||false;this.formatType=options.formatType||this.element.data("format-type")||"standard";this.format=DPGlobal.parseFormat(options.format||this.element.data("date-format")||dates[this.language].format||DPGlobal.getDefaultFormat(this.formatType,"input"),this.formatType);this.isInline=false;this.isVisible=false;this.isInput=this.element.is("input");this.fontAwesome=options.fontAwesome||this.element.data("font-awesome")||false;this.bootcssVer=options.bootcssVer||(this.isInput?(this.element.is(".form-control")?3:2):(this.bootcssVer=this.element.is(".input-group")?3:2));this.component=this.element.is(".date")?(this.bootcssVer===3?this.element.find(".input-group-addon .glyphicon-th, .input-group-addon .glyphicon-time, .input-group-addon .glyphicon-remove, .input-group-addon .glyphicon-calendar, .input-group-addon .fa-calendar, .input-group-addon .fa-clock-o").parent():this.element.find(".add-on .icon-th, .add-on .icon-time, .add-on .icon-calendar, .add-on .fa-calendar, .add-on .fa-clock-o").parent()):false;this.componentReset=this.element.is(".date")?(this.bootcssVer===3?this.element.find(".input-group-addon .glyphicon-remove, .input-group-addon .fa-times").parent():this.element.find(".add-on .icon-remove, .add-on .fa-times").parent()):false;this.hasInput=this.component&&this.element.find("input").length;if(this.component&&this.component.length===0){this.component=false}this.linkField=options.linkField||this.element.data("link-field")||false;this.linkFormat=DPGlobal.parseFormat(options.linkFormat||this.element.data("link-format")||DPGlobal.getDefaultFormat(this.formatType,"link"),this.formatType);this.minuteStep=options.minuteStep||this.element.data("minute-step")||5;this.pickerPosition=options.pickerPosition||this.element.data("picker-position")||"bottom-right";this.showMeridian=options.showMeridian||this.element.data("show-meridian")||false;this.initialDate=options.initialDate||new Date();this.zIndex=options.zIndex||this.element.data("z-index")||undefined;this.title=typeof options.title==="undefined"?false:options.title;this.timezone=options.timezone||timeZoneAbbreviation();this.icons={leftArrow:this.fontAwesome?"fa-arrow-left":(this.bootcssVer===3?"glyphicon-arrow-left":"icon-arrow-left"),rightArrow:this.fontAwesome?"fa-arrow-right":(this.bootcssVer===3?"glyphicon-arrow-right":"icon-arrow-right")};this.icontype=this.fontAwesome?"fa":"glyphicon";this._attachEvents();this.clickedOutside=function(e){if($(e.target).closest(".datetimepicker").length===0){that.hide()}};this.formatViewType="datetime";if("formatViewType" in options){this.formatViewType=options.formatViewType}else{if("formatViewType" in this.element.data()){this.formatViewType=this.element.data("formatViewType")}}this.minView=0;if("minView" in options){this.minView=options.minView}else{if("minView" in this.element.data()){this.minView=this.element.data("min-view")}}this.minView=DPGlobal.convertViewMode(this.minView);this.maxView=DPGlobal.modes.length-1;if("maxView" in options){this.maxView=options.maxView}else{if("maxView" in this.element.data()){this.maxView=this.element.data("max-view")}}this.maxView=DPGlobal.convertViewMode(this.maxView);this.wheelViewModeNavigation=false;if("wheelViewModeNavigation" in options){this.wheelViewModeNavigation=options.wheelViewModeNavigation}else{if("wheelViewModeNavigation" in this.element.data()){this.wheelViewModeNavigation=this.element.data("view-mode-wheel-navigation")}}this.wheelViewModeNavigationInverseDirection=false;if("wheelViewModeNavigationInverseDirection" in options){this.wheelViewModeNavigationInverseDirection=options.wheelViewModeNavigationInverseDirection}else{if("wheelViewModeNavigationInverseDirection" in this.element.data()){this.wheelViewModeNavigationInverseDirection=this.element.data("view-mode-wheel-navigation-inverse-dir")}}this.wheelViewModeNavigationDelay=100;if("wheelViewModeNavigationDelay" in options){this.wheelViewModeNavigationDelay=options.wheelViewModeNavigationDelay}else{if("wheelViewModeNavigationDelay" in this.element.data()){this.wheelViewModeNavigationDelay=this.element.data("view-mode-wheel-navigation-delay")}}this.startViewMode=2;if("startView" in options){this.startViewMode=options.startView}else{if("startView" in this.element.data()){this.startViewMode=this.element.data("start-view")}}this.startViewMode=DPGlobal.convertViewMode(this.startViewMode);this.viewMode=this.startViewMode;this.viewSelect=this.minView;if("viewSelect" in options){this.viewSelect=options.viewSelect}else{if("viewSelect" in this.element.data()){this.viewSelect=this.element.data("view-select")}}this.viewSelect=DPGlobal.convertViewMode(this.viewSelect);this.forceParse=true;if("forceParse" in options){this.forceParse=options.forceParse}else{if("dateForceParse" in this.element.data()){this.forceParse=this.element.data("date-force-parse")}}var template=this.bootcssVer===3?DPGlobal.templateV3:DPGlobal.template;while(template.indexOf("{iconType}")!==-1){template=template.replace("{iconType}",this.icontype)}while(template.indexOf("{leftArrow}")!==-1){template=template.replace("{leftArrow}",this.icons.leftArrow)}while(template.indexOf("{rightArrow}")!==-1){template=template.replace("{rightArrow}",this.icons.rightArrow)}this.picker=$(template).appendTo(this.isInline?this.element:this.container).on({click:$.proxy(this.click,this),mousedown:$.proxy(this.mousedown,this)});if(this.wheelViewModeNavigation){if($.fn.mousewheel){this.picker.on({mousewheel:$.proxy(this.mousewheel,this)})}else{console.log("Mouse Wheel event is not supported. Please include the jQuery Mouse Wheel plugin before enabling this option")}}if(this.isInline){this.picker.addClass("datetimepicker-inline")}else{this.picker.addClass("datetimepicker-dropdown-"+this.pickerPosition+" dropdown-menu")}if(this.isRTL){this.picker.addClass("datetimepicker-rtl");var selector=this.bootcssVer===3?".prev span, .next span":".prev i, .next i";this.picker.find(selector).toggleClass(this.icons.leftArrow+" "+this.icons.rightArrow)}$(document).on("mousedown touchend",this.clickedOutside);this.autoclose=false;if("autoclose" in options){this.autoclose=options.autoclose}else{if("dateAutoclose" in this.element.data()){this.autoclose=this.element.data("date-autoclose")}}this.keyboardNavigation=true;if("keyboardNavigation" in options){this.keyboardNavigation=options.keyboardNavigation}else{if("dateKeyboardNavigation" in this.element.data()){this.keyboardNavigation=this.element.data("date-keyboard-navigation")}}this.todayBtn=(options.todayBtn||this.element.data("date-today-btn")||false);this.clearBtn=(options.clearBtn||this.element.data("date-clear-btn")||false);this.todayHighlight=(options.todayHighlight||this.element.data("date-today-highlight")||false);this.weekStart=0;if(typeof options.weekStart!=="undefined"){this.weekStart=options.weekStart}else{if(typeof this.element.data("date-weekstart")!=="undefined"){this.weekStart=this.element.data("date-weekstart")}else{if(typeof dates[this.language].weekStart!=="undefined"){this.weekStart=dates[this.language].weekStart}}}this.weekStart=this.weekStart%7;this.weekEnd=((this.weekStart+6)%7);this.onRenderDay=function(date){var render=(options.onRenderDay||function(){return[]})(date);if(typeof render==="string"){render=[render]}var res=["day"];return res.concat((render?render:[]))};this.onRenderHour=function(date){var render=(options.onRenderHour||function(){return[]})(date);var res=["hour"];if(typeof render==="string"){render=[render]}return res.concat((render?render:[]))};this.onRenderMinute=function(date){var render=(options.onRenderMinute||function(){return[]})(date);var res=["minute"];if(typeof render==="string"){render=[render]}if(date<this.startDate||date>this.endDate){res.push("disabled")}else{if(Math.floor(this.date.getUTCMinutes()/this.minuteStep)===Math.floor(date.getUTCMinutes()/this.minuteStep)){res.push("active")}}return res.concat((render?render:[]))};this.onRenderYear=function(date){var render=(options.onRenderYear||function(){return[]})(date);var res=["year"];if(typeof render==="string"){render=[render]}if(this.date.getUTCFullYear()===date.getUTCFullYear()){res.push("active")}var currentYear=date.getUTCFullYear();var endYear=this.endDate.getUTCFullYear();if(date<this.startDate||currentYear>endYear){res.push("disabled")}return res.concat((render?render:[]))};this.onRenderMonth=function(date){var render=(options.onRenderMonth||function(){return[]})(date);var res=["month"];if(typeof render==="string"){render=[render]}return res.concat((render?render:[]))};this.startDate=new Date(-8639968443048000);this.endDate=new Date(8639968443048000);this.datesDisabled=[];this.daysOfWeekDisabled=[];this.setStartDate(options.startDate||this.element.data("date-startdate"));this.setEndDate(options.endDate||this.element.data("date-enddate"));this.setDatesDisabled(options.datesDisabled||this.element.data("date-dates-disabled"));this.setDaysOfWeekDisabled(options.daysOfWeekDisabled||this.element.data("date-days-of-week-disabled"));this.setMinutesDisabled(options.minutesDisabled||this.element.data("date-minute-disabled"));this.setHoursDisabled(options.hoursDisabled||this.element.data("date-hour-disabled"));this.fillDow();this.fillMonths();this.update();this.showMode();if(this.isInline){this.show()}};Datetimepicker.prototype={constructor:Datetimepicker,_events:[],_attachEvents:function(){this._detachEvents();if(this.isInput){this._events=[[this.element,{focus:$.proxy(this.show,this),keyup:$.proxy(this.update,this),keydown:$.proxy(this.keydown,this)}]]}else{if(this.component&&this.hasInput){this._events=[[this.element.find("input"),{focus:$.proxy(this.show,this),keyup:$.proxy(this.update,this),keydown:$.proxy(this.keydown,this)}],[this.component,{click:$.proxy(this.show,this)}]];if(this.componentReset){this._events.push([this.componentReset,{click:$.proxy(this.reset,this)}])}}else{if(this.element.is("div")){this.isInline=true}else{this._events=[[this.element,{click:$.proxy(this.show,this)}]]}}}for(var i=0,el,ev;i<this._events.length;i++){el=this._events[i][0];ev=this._events[i][1];el.on(ev)}},_detachEvents:function(){for(var i=0,el,ev;i<this._events.length;i++){el=this._events[i][0];ev=this._events[i][1];el.off(ev)}this._events=[]},show:function(e){this.picker.show();this.height=this.component?this.component.outerHeight():this.element.outerHeight();if(this.forceParse){this.update()}this.place();$(window).on("resize",$.proxy(this.place,this));if(e){e.stopPropagation();e.preventDefault()}this.isVisible=true;this.element.trigger({type:"show",date:this.date})},hide:function(){if(!this.isVisible){return}if(this.isInline){return}this.picker.hide();$(window).off("resize",this.place);this.viewMode=this.startViewMode;this.showMode();if(!this.isInput){$(document).off("mousedown",this.hide)}if(this.forceParse&&(this.isInput&&this.element.val()||this.hasInput&&this.element.find("input").val())){this.setValue()}this.isVisible=false;this.element.trigger({type:"hide",date:this.date})},remove:function(){this._detachEvents();$(document).off("mousedown",this.clickedOutside);this.picker.remove();delete this.picker;delete this.element.data().datetimepicker},getDate:function(){var d=this.getUTCDate();if(d===null){return null}return new Date(d.getTime()+(d.getTimezoneOffset()*60000))},getUTCDate:function(){return this.date},getInitialDate:function(){return this.initialDate},setInitialDate:function(initialDate){this.initialDate=initialDate},setDate:function(d){this.setUTCDate(new Date(d.getTime()-(d.getTimezoneOffset()*60000)))},setUTCDate:function(d){if(d>=this.startDate&&d<=this.endDate){this.date=d;this.setValue();this.viewDate=this.date;this.fill()}else{this.element.trigger({type:"outOfRange",date:d,startDate:this.startDate,endDate:this.endDate})}},setFormat:function(format){this.format=DPGlobal.parseFormat(format,this.formatType);var element;if(this.isInput){element=this.element}else{if(this.component){element=this.element.find("input")}}if(element&&element.val()){this.setValue()}},setValue:function(){var formatted=this.getFormattedDate();if(!this.isInput){if(this.component){this.element.find("input").val(formatted)}this.element.data("date",formatted)}else{this.element.val(formatted)}if(this.linkField){$("#"+this.linkField).val(this.getFormattedDate(this.linkFormat))}},getFormattedDate:function(format){format=format||this.format;return DPGlobal.formatDate(this.date,format,this.language,this.formatType,this.timezone)},setStartDate:function(startDate){this.startDate=startDate||this.startDate;if(this.startDate.valueOf()!==8639968443048000){this.startDate=DPGlobal.parseDate(this.startDate,this.format,this.language,this.formatType,this.timezone)}this.update();this.updateNavArrows()},setEndDate:function(endDate){this.endDate=endDate||this.endDate;if(this.endDate.valueOf()!==8639968443048000){this.endDate=DPGlobal.parseDate(this.endDate,this.format,this.language,this.formatType,this.timezone)}this.update();this.updateNavArrows()},setDatesDisabled:function(datesDisabled){this.datesDisabled=datesDisabled||[];if(!$.isArray(this.datesDisabled)){this.datesDisabled=this.datesDisabled.split(/,\s*/)}var mThis=this;this.datesDisabled=$.map(this.datesDisabled,function(d){return DPGlobal.parseDate(d,mThis.format,mThis.language,mThis.formatType,mThis.timezone).toDateString()});this.update();this.updateNavArrows()},setTitle:function(selector,value){return this.picker.find(selector).find("th:eq(1)").text(this.title===false?value:this.title)},setDaysOfWeekDisabled:function(daysOfWeekDisabled){this.daysOfWeekDisabled=daysOfWeekDisabled||[];if(!$.isArray(this.daysOfWeekDisabled)){this.daysOfWeekDisabled=this.daysOfWeekDisabled.split(/,\s*/)}this.daysOfWeekDisabled=$.map(this.daysOfWeekDisabled,function(d){return parseInt(d,10)});this.update();this.updateNavArrows()},setMinutesDisabled:function(minutesDisabled){this.minutesDisabled=minutesDisabled||[];if(!$.isArray(this.minutesDisabled)){this.minutesDisabled=this.minutesDisabled.split(/,\s*/)}this.minutesDisabled=$.map(this.minutesDisabled,function(d){return parseInt(d,10)});this.update();this.updateNavArrows()},setHoursDisabled:function(hoursDisabled){this.hoursDisabled=hoursDisabled||[];if(!$.isArray(this.hoursDisabled)){this.hoursDisabled=this.hoursDisabled.split(/,\s*/)}this.hoursDisabled=$.map(this.hoursDisabled,function(d){return parseInt(d,10)});this.update();this.updateNavArrows()},place:function(){if(this.isInline){return}if(!this.zIndex){var index_highest=0;$("div").each(function(){var index_current=parseInt($(this).css("zIndex"),10);if(index_current>index_highest){index_highest=index_current}});this.zIndex=index_highest+10}var offset,top,left,containerOffset;if(this.container instanceof $){containerOffset=this.container.offset()}else{containerOffset=$(this.container).offset()}if(this.component){offset=this.component.offset();left=offset.left;if(this.pickerPosition==="bottom-left"||this.pickerPosition==="top-left"){left+=this.component.outerWidth()-this.picker.outerWidth()}}else{offset=this.element.offset();left=offset.left;if(this.pickerPosition==="bottom-left"||this.pickerPosition==="top-left"){left+=this.element.outerWidth()-this.picker.outerWidth()}}var bodyWidth=document.body.clientWidth||window.innerWidth;if(left+220>bodyWidth){left=bodyWidth-220}if(this.pickerPosition==="top-left"||this.pickerPosition==="top-right"){top=offset.top-this.picker.outerHeight()}else{top=offset.top+this.height}top=top-containerOffset.top;left=left-containerOffset.left;this.picker.css({top:top,left:left,zIndex:this.zIndex})},hour_minute:"^([0-9]|0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]",update:function(){var date,fromArgs=false;if(arguments&&arguments.length&&(typeof arguments[0]==="string"||arguments[0] instanceof Date)){date=arguments[0];fromArgs=true}else{date=(this.isInput?this.element.val():this.element.find("input").val())||this.element.data("date")||this.initialDate;if(typeof date==="string"){date=date.replace(/^\s+|\s+$/g,"")}}if(!date){date=new Date();fromArgs=false}if(typeof date==="string"){if(new RegExp(this.hour_minute).test(date)||new RegExp(this.hour_minute+":[0-5][0-9]").test(date)){date=this.getDate()}}this.date=DPGlobal.parseDate(date,this.format,this.language,this.formatType,this.timezone);if(fromArgs){this.setValue()}if(this.date<this.startDate){this.viewDate=new Date(this.startDate)}else{if(this.date>this.endDate){this.viewDate=new Date(this.endDate)}else{this.viewDate=new Date(this.date)}}this.fill()},fillDow:function(){var dowCnt=this.weekStart,html="<tr>";while(dowCnt<this.weekStart+7){html+='<th class="dow">'+dates[this.language].daysMin[(dowCnt++)%7]+"</th>"}html+="</tr>";this.picker.find(".datetimepicker-days thead").append(html)},fillMonths:function(){var html="";var d=new Date(this.viewDate);for(var i=0;i<12;i++){d.setUTCMonth(i);var classes=this.onRenderMonth(d);html+='<span class="'+classes.join(" ")+'">'+dates[this.language].monthsShort[i]+"</span>"}this.picker.find(".datetimepicker-months td").html(html)},fill:function(){if(!this.date||!this.viewDate){return}var d=new Date(this.viewDate),year=d.getUTCFullYear(),month=d.getUTCMonth(),dayMonth=d.getUTCDate(),hours=d.getUTCHours(),startYear=this.startDate.getUTCFullYear(),startMonth=this.startDate.getUTCMonth(),endYear=this.endDate.getUTCFullYear(),endMonth=this.endDate.getUTCMonth()+1,currentDate=(new UTCDate(this.date.getUTCFullYear(),this.date.getUTCMonth(),this.date.getUTCDate())).valueOf(),today=new Date();this.setTitle(".datetimepicker-days",dates[this.language].months[month]+" "+year);if(this.formatViewType==="time"){var formatted=this.getFormattedDate();this.setTitle(".datetimepicker-hours",formatted);this.setTitle(".datetimepicker-minutes",formatted)}else{this.setTitle(".datetimepicker-hours",dayMonth+" "+dates[this.language].months[month]+" "+year);this.setTitle(".datetimepicker-minutes",dayMonth+" "+dates[this.language].months[month]+" "+year)}this.picker.find("tfoot th.today").text(dates[this.language].today||dates["en"].today).toggle(this.todayBtn!==false);this.picker.find("tfoot th.clear").text(dates[this.language].clear||dates["en"].clear).toggle(this.clearBtn!==false);this.updateNavArrows();this.fillMonths();var prevMonth=UTCDate(year,month-1,28,0,0,0,0),day=DPGlobal.getDaysInMonth(prevMonth.getUTCFullYear(),prevMonth.getUTCMonth());prevMonth.setUTCDate(day);prevMonth.setUTCDate(day-(prevMonth.getUTCDay()-this.weekStart+7)%7);var nextMonth=new Date(prevMonth);nextMonth.setUTCDate(nextMonth.getUTCDate()+42);nextMonth=nextMonth.valueOf();var html=[];var classes;while(prevMonth.valueOf()<nextMonth){if(prevMonth.getUTCDay()===this.weekStart){html.push("<tr>")}classes=this.onRenderDay(prevMonth);if(prevMonth.getUTCFullYear()<year||(prevMonth.getUTCFullYear()===year&&prevMonth.getUTCMonth()<month)){classes.push("old")}else{if(prevMonth.getUTCFullYear()>year||(prevMonth.getUTCFullYear()===year&&prevMonth.getUTCMonth()>month)){classes.push("new")}}if(this.todayHighlight&&prevMonth.getUTCFullYear()===today.getFullYear()&&prevMonth.getUTCMonth()===today.getMonth()&&prevMonth.getUTCDate()===today.getDate()){classes.push("today")}if(prevMonth.valueOf()===currentDate){classes.push("active")}if((prevMonth.valueOf()+86400000)<=this.startDate||prevMonth.valueOf()>this.endDate||$.inArray(prevMonth.getUTCDay(),this.daysOfWeekDisabled)!==-1||$.inArray(prevMonth.toDateString(),this.datesDisabled)!==-1){classes.push("disabled")}html.push('<td class="'+classes.join(" ")+'">'+prevMonth.getUTCDate()+"</td>");if(prevMonth.getUTCDay()===this.weekEnd){html.push("</tr>")}prevMonth.setUTCDate(prevMonth.getUTCDate()+1)}this.picker.find(".datetimepicker-days tbody").empty().append(html.join(""));html=[];var txt="",meridian="",meridianOld="";var hoursDisabled=this.hoursDisabled||[];d=new Date(this.viewDate);for(var i=0;i<24;i++){d.setUTCHours(i);classes=this.onRenderHour(d);if(hoursDisabled.indexOf(i)!==-1){classes.push("disabled")}var actual=UTCDate(year,month,dayMonth,i);if((actual.valueOf()+3600000)<=this.startDate||actual.valueOf()>this.endDate){classes.push("disabled")}else{if(hours===i){classes.push("active")}}if(this.showMeridian&&dates[this.language].meridiem.length===2){meridian=(i<12?dates[this.language].meridiem[0]:dates[this.language].meridiem[1]);if(meridian!==meridianOld){if(meridianOld!==""){html.push("</fieldset>")}html.push('<fieldset class="hour"><legend>'+meridian.toUpperCase()+"</legend>")}meridianOld=meridian;txt=(i%12?i%12:12);if(i<12){classes.push("hour_am")}else{classes.push("hour_pm")}html.push('<span class="'+classes.join(" ")+'">'+txt+"</span>");if(i===23){html.push("</fieldset>")}}else{txt=i+":00";html.push('<span class="'+classes.join(" ")+'">'+txt+"</span>")}}this.picker.find(".datetimepicker-hours td").html(html.join(""));html=[];txt="";meridian="";meridianOld="";var minutesDisabled=this.minutesDisabled||[];d=new Date(this.viewDate);for(var i=0;i<60;i+=this.minuteStep){if(minutesDisabled.indexOf(i)!==-1){continue}d.setUTCMinutes(i);d.setUTCSeconds(0);classes=this.onRenderMinute(d);if(this.showMeridian&&dates[this.language].meridiem.length===2){meridian=(hours<12?dates[this.language].meridiem[0]:dates[this.language].meridiem[1]);if(meridian!==meridianOld){if(meridianOld!==""){html.push("</fieldset>")}html.push('<fieldset class="minute"><legend>'+meridian.toUpperCase()+"</legend>")}meridianOld=meridian;txt=(hours%12?hours%12:12);html.push('<span class="'+classes.join(" ")+'">'+txt+":"+(i<10?"0"+i:i)+"</span>");if(i===59){html.push("</fieldset>")}}else{txt=i+":00";html.push('<span class="'+classes.join(" ")+'">'+hours+":"+(i<10?"0"+i:i)+"</span>")}}this.picker.find(".datetimepicker-minutes td").html(html.join(""));var currentYear=this.date.getUTCFullYear();var months=this.setTitle(".datetimepicker-months",year).end().find(".month").removeClass("active");if(currentYear===year){months.eq(this.date.getUTCMonth()).addClass("active")}if(year<startYear||year>endYear){months.addClass("disabled")}if(year===startYear){months.slice(0,startMonth).addClass("disabled")}if(year===endYear){months.slice(endMonth).addClass("disabled")}html="";year=parseInt(year/10,10)*10;var yearCont=this.setTitle(".datetimepicker-years",year+"-"+(year+9)).end().find("td");year-=1;d=new Date(this.viewDate);for(var i=-1;i<11;i++){d.setUTCFullYear(year);classes=this.onRenderYear(d);if(i===-1||i===10){classes.push(old)}html+='<span class="'+classes.join(" ")+'">'+year+"</span>";year+=1}yearCont.html(html);this.place()},updateNavArrows:function(){var d=new Date(this.viewDate),year=d.getUTCFullYear(),month=d.getUTCMonth(),day=d.getUTCDate(),hour=d.getUTCHours();switch(this.viewMode){case 0:if(year<=this.startDate.getUTCFullYear()&&month<=this.startDate.getUTCMonth()&&day<=this.startDate.getUTCDate()&&hour<=this.startDate.getUTCHours()){this.picker.find(".prev").css({visibility:"hidden"})}else{this.picker.find(".prev").css({visibility:"visible"})}if(year>=this.endDate.getUTCFullYear()&&month>=this.endDate.getUTCMonth()&&day>=this.endDate.getUTCDate()&&hour>=this.endDate.getUTCHours()){this.picker.find(".next").css({visibility:"hidden"})}else{this.picker.find(".next").css({visibility:"visible"})}break;case 1:if(year<=this.startDate.getUTCFullYear()&&month<=this.startDate.getUTCMonth()&&day<=this.startDate.getUTCDate()){this.picker.find(".prev").css({visibility:"hidden"})}else{this.picker.find(".prev").css({visibility:"visible"})}if(year>=this.endDate.getUTCFullYear()&&month>=this.endDate.getUTCMonth()&&day>=this.endDate.getUTCDate()){this.picker.find(".next").css({visibility:"hidden"})}else{this.picker.find(".next").css({visibility:"visible"})}break;case 2:if(year<=this.startDate.getUTCFullYear()&&month<=this.startDate.getUTCMonth()){this.picker.find(".prev").css({visibility:"hidden"})}else{this.picker.find(".prev").css({visibility:"visible"})}if(year>=this.endDate.getUTCFullYear()&&month>=this.endDate.getUTCMonth()){this.picker.find(".next").css({visibility:"hidden"})}else{this.picker.find(".next").css({visibility:"visible"})}break;case 3:case 4:if(year<=this.startDate.getUTCFullYear()){this.picker.find(".prev").css({visibility:"hidden"})}else{this.picker.find(".prev").css({visibility:"visible"})}if(year>=this.endDate.getUTCFullYear()){this.picker.find(".next").css({visibility:"hidden"})}else{this.picker.find(".next").css({visibility:"visible"})}break}},mousewheel:function(e){e.preventDefault();e.stopPropagation();if(this.wheelPause){return}this.wheelPause=true;var originalEvent=e.originalEvent;var delta=originalEvent.wheelDelta;var mode=delta>0?1:(delta===0)?0:-1;if(this.wheelViewModeNavigationInverseDirection){mode=-mode}this.showMode(mode);setTimeout($.proxy(function(){this.wheelPause=false},this),this.wheelViewModeNavigationDelay)},click:function(e){e.stopPropagation();e.preventDefault();var target=$(e.target).closest("span, td, th, legend");if(target.is("."+this.icontype)){target=$(target).parent().closest("span, td, th, legend")}if(target.length===1){if(target.is(".disabled")){this.element.trigger({type:"outOfRange",date:this.viewDate,startDate:this.startDate,endDate:this.endDate});return}switch(target[0].nodeName.toLowerCase()){case"th":switch(target[0].className){case"switch":this.showMode(1);break;case"prev":case"next":var dir=DPGlobal.modes[this.viewMode].navStep*(target[0].className==="prev"?-1:1);switch(this.viewMode){case 0:this.viewDate=this.moveHour(this.viewDate,dir);break;case 1:this.viewDate=this.moveDate(this.viewDate,dir);break;case 2:this.viewDate=this.moveMonth(this.viewDate,dir);break;case 3:case 4:this.viewDate=this.moveYear(this.viewDate,dir);break}this.fill();this.element.trigger({type:target[0].className+":"+this.convertViewModeText(this.viewMode),date:this.viewDate,startDate:this.startDate,endDate:this.endDate});break;case"clear":this.reset();if(this.autoclose){this.hide()}break;case"today":var date=new Date();date=UTCDate(date.getFullYear(),date.getMonth(),date.getDate(),date.getHours(),date.getMinutes(),date.getSeconds(),0);if(date<this.startDate){date=this.startDate}else{if(date>this.endDate){date=this.endDate}}this.viewMode=this.startViewMode;this.showMode(0);this._setDate(date);this.fill();if(this.autoclose){this.hide()}break}break;case"span":if(!target.is(".disabled")){var year=this.viewDate.getUTCFullYear(),month=this.viewDate.getUTCMonth(),day=this.viewDate.getUTCDate(),hours=this.viewDate.getUTCHours(),minutes=this.viewDate.getUTCMinutes(),seconds=this.viewDate.getUTCSeconds();if(target.is(".month")){this.viewDate.setUTCDate(1);month=target.parent().find("span").index(target);day=this.viewDate.getUTCDate();this.viewDate.setUTCMonth(month);this.element.trigger({type:"changeMonth",date:this.viewDate});if(this.viewSelect>=3){this._setDate(UTCDate(year,month,day,hours,minutes,seconds,0))}}else{if(target.is(".year")){this.viewDate.setUTCDate(1);year=parseInt(target.text(),10)||0;this.viewDate.setUTCFullYear(year);this.element.trigger({type:"changeYear",date:this.viewDate});if(this.viewSelect>=4){this._setDate(UTCDate(year,month,day,hours,minutes,seconds,0))}}else{if(target.is(".hour")){hours=parseInt(target.text(),10)||0;if(target.hasClass("hour_am")||target.hasClass("hour_pm")){if(hours===12&&target.hasClass("hour_am")){hours=0}else{if(hours!==12&&target.hasClass("hour_pm")){hours+=12}}}this.viewDate.setUTCHours(hours);this.element.trigger({type:"changeHour",date:this.viewDate});if(this.viewSelect>=1){this._setDate(UTCDate(year,month,day,hours,minutes,seconds,0))}}else{if(target.is(".minute")){minutes=parseInt(target.text().substr(target.text().indexOf(":")+1),10)||0;this.viewDate.setUTCMinutes(minutes);this.element.trigger({type:"changeMinute",date:this.viewDate});if(this.viewSelect>=0){this._setDate(UTCDate(year,month,day,hours,minutes,seconds,0))}}}}}if(this.viewMode!==0){var oldViewMode=this.viewMode;this.showMode(-1);this.fill();if(oldViewMode===this.viewMode&&this.autoclose){this.hide()}}else{this.fill();if(this.autoclose){this.hide()}}}break;case"td":if(target.is(".day")&&!target.is(".disabled")){var day=parseInt(target.text(),10)||1;var year=this.viewDate.getUTCFullYear(),month=this.viewDate.getUTCMonth(),hours=this.viewDate.getUTCHours(),minutes=this.viewDate.getUTCMinutes(),seconds=this.viewDate.getUTCSeconds();if(target.is(".old")){if(month===0){month=11;year-=1}else{month-=1}}else{if(target.is(".new")){if(month===11){month=0;year+=1}else{month+=1}}}this.viewDate.setUTCFullYear(year);this.viewDate.setUTCMonth(month,day);this.element.trigger({type:"changeDay",date:this.viewDate});if(this.viewSelect>=2){this._setDate(UTCDate(year,month,day,hours,minutes,seconds,0))}}var oldViewMode=this.viewMode;this.showMode(-1);this.fill();if(oldViewMode===this.viewMode&&this.autoclose){this.hide()}break}}},_setDate:function(date,which){if(!which||which==="date"){this.date=date}if(!which||which==="view"){this.viewDate=date}this.fill();this.setValue();var element;if(this.isInput){element=this.element}else{if(this.component){element=this.element.find("input")}}if(element){element.change()}this.element.trigger({type:"changeDate",date:this.getDate()});if(date===null){this.date=this.viewDate}},moveMinute:function(date,dir){if(!dir){return date}var new_date=new Date(date.valueOf());new_date.setUTCMinutes(new_date.getUTCMinutes()+(dir*this.minuteStep));return new_date},moveHour:function(date,dir){if(!dir){return date}var new_date=new Date(date.valueOf());new_date.setUTCHours(new_date.getUTCHours()+dir);return new_date},moveDate:function(date,dir){if(!dir){return date}var new_date=new Date(date.valueOf());new_date.setUTCDate(new_date.getUTCDate()+dir);return new_date},moveMonth:function(date,dir){if(!dir){return date}var new_date=new Date(date.valueOf()),day=new_date.getUTCDate(),month=new_date.getUTCMonth(),mag=Math.abs(dir),new_month,test;dir=dir>0?1:-1;if(mag===1){test=dir===-1?function(){return new_date.getUTCMonth()===month}:function(){return new_date.getUTCMonth()!==new_month};new_month=month+dir;new_date.setUTCMonth(new_month);if(new_month<0||new_month>11){new_month=(new_month+12)%12}}else{for(var i=0;i<mag;i++){new_date=this.moveMonth(new_date,dir)}new_month=new_date.getUTCMonth();new_date.setUTCDate(day);test=function(){return new_month!==new_date.getUTCMonth()}}while(test()){new_date.setUTCDate(--day);new_date.setUTCMonth(new_month)}return new_date},moveYear:function(date,dir){return this.moveMonth(date,dir*12)},dateWithinRange:function(date){return date>=this.startDate&&date<=this.endDate},keydown:function(e){if(this.picker.is(":not(:visible)")){if(e.keyCode===27){this.show()}return}var dateChanged=false,dir,newDate,newViewDate;switch(e.keyCode){case 27:this.hide();e.preventDefault();break;case 37:case 39:if(!this.keyboardNavigation){break}dir=e.keyCode===37?-1:1;var viewMode=this.viewMode;if(e.ctrlKey){viewMode+=2}else{if(e.shiftKey){viewMode+=1}}if(viewMode===4){newDate=this.moveYear(this.date,dir);newViewDate=this.moveYear(this.viewDate,dir)}else{if(viewMode===3){newDate=this.moveMonth(this.date,dir);newViewDate=this.moveMonth(this.viewDate,dir)}else{if(viewMode===2){newDate=this.moveDate(this.date,dir);newViewDate=this.moveDate(this.viewDate,dir)}else{if(viewMode===1){newDate=this.moveHour(this.date,dir);newViewDate=this.moveHour(this.viewDate,dir)}else{if(viewMode===0){newDate=this.moveMinute(this.date,dir);newViewDate=this.moveMinute(this.viewDate,dir)}}}}}if(this.dateWithinRange(newDate)){this.date=newDate;this.viewDate=newViewDate;this.setValue();this.update();e.preventDefault();dateChanged=true}break;case 38:case 40:if(!this.keyboardNavigation){break}dir=e.keyCode===38?-1:1;viewMode=this.viewMode;if(e.ctrlKey){viewMode+=2}else{if(e.shiftKey){viewMode+=1}}if(viewMode===4){newDate=this.moveYear(this.date,dir);newViewDate=this.moveYear(this.viewDate,dir)}else{if(viewMode===3){newDate=this.moveMonth(this.date,dir);newViewDate=this.moveMonth(this.viewDate,dir)}else{if(viewMode===2){newDate=this.moveDate(this.date,dir*7);newViewDate=this.moveDate(this.viewDate,dir*7)}else{if(viewMode===1){if(this.showMeridian){newDate=this.moveHour(this.date,dir*6);newViewDate=this.moveHour(this.viewDate,dir*6)}else{newDate=this.moveHour(this.date,dir*4);newViewDate=this.moveHour(this.viewDate,dir*4)}}else{if(viewMode===0){newDate=this.moveMinute(this.date,dir*4);newViewDate=this.moveMinute(this.viewDate,dir*4)}}}}}if(this.dateWithinRange(newDate)){this.date=newDate;this.viewDate=newViewDate;this.setValue();this.update();e.preventDefault();dateChanged=true}break;case 13:if(this.viewMode!==0){var oldViewMode=this.viewMode;this.showMode(-1);this.fill();if(oldViewMode===this.viewMode&&this.autoclose){this.hide()}}else{this.fill();if(this.autoclose){this.hide()}}e.preventDefault();break;case 9:this.hide();break}if(dateChanged){var element;if(this.isInput){element=this.element}else{if(this.component){element=this.element.find("input")}}if(element){element.change()}this.element.trigger({type:"changeDate",date:this.getDate()})}},showMode:function(dir){if(dir){var newViewMode=Math.max(0,Math.min(DPGlobal.modes.length-1,this.viewMode+dir));if(newViewMode>=this.minView&&newViewMode<=this.maxView){this.element.trigger({type:"changeMode",date:this.viewDate,oldViewMode:this.viewMode,newViewMode:newViewMode});this.viewMode=newViewMode}}this.picker.find(">div").hide().filter(".datetimepicker-"+DPGlobal.modes[this.viewMode].clsName).css("display","block");this.updateNavArrows()},reset:function(){this._setDate(null,"date")},convertViewModeText:function(viewMode){switch(viewMode){case 4:return"decade";case 3:return"year";case 2:return"month";case 1:return"day";case 0:return"hour"}}};var old=$.fn.datetimepicker;$.fn.datetimepicker=function(option){var args=Array.apply(null,arguments);args.shift();var internal_return;this.each(function(){var $this=$(this),data=$this.data("datetimepicker"),options=typeof option==="object"&&option;if(!data){$this.data("datetimepicker",(data=new Datetimepicker(this,$.extend({},$.fn.datetimepicker.defaults,options))))}if(typeof option==="string"&&typeof data[option]==="function"){internal_return=data[option].apply(data,args);if(internal_return!==undefined){return false}}});if(internal_return!==undefined){return internal_return}else{return this}};$.fn.datetimepicker.defaults={};$.fn.datetimepicker.Constructor=Datetimepicker;var dates=$.fn.datetimepicker.dates={"zh-cn":{days:["星期日","星期一","星期二","星期三","星期四","星期五","星期六","星期日"],daysShort:["周日","周一","周二","周三","周四","周五","周六","周日"],daysMin:["日","一","二","三","四","五","六","日"],months:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],monthsShort:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],meridiem:["上午","下午"],suffix:["st","nd","rd","th"],today:"今天",clear:"清除"},en:{days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat","Sun"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa","Su"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],meridiem:["am","pm"],suffix:["st","nd","rd","th"],today:"Today",clear:"Clear"}};var DPGlobal={modes:[{clsName:"minutes",navFnc:"Hours",navStep:1},{clsName:"hours",navFnc:"Date",navStep:1},{clsName:"days",navFnc:"Month",navStep:1},{clsName:"months",navFnc:"FullYear",navStep:1},{clsName:"years",navFnc:"FullYear",navStep:10}],isLeapYear:function(year){return(((year%4===0)&&(year%100!==0))||(year%400===0))},getDaysInMonth:function(year,month){return[31,(DPGlobal.isLeapYear(year)?29:28),31,30,31,30,31,31,30,31,30,31][month]},getDefaultFormat:function(type,field){if(type==="standard"){if(field==="input"){return"yyyy-mm-dd hh:ii"}else{return"yyyy-mm-dd hh:ii:ss"}}else{if(type==="php"){if(field==="input"){return"Y-m-d H:i"}else{return"Y-m-d H:i:s"}}else{throw new Error("Invalid format type.")}}},validParts:function(type){if(type==="standard"){return/t|hh?|HH?|p|P|z|Z|ii?|ss?|dd?|DD?|mm?|MM?|yy(?:yy)?/g}else{if(type==="php"){return/[dDjlNwzFmMnStyYaABgGhHis]/g}else{throw new Error("Invalid format type.")}}},nonpunctuation:/[^ -\/:-@\[-`{-~\t\n\rTZ]+/g,parseFormat:function(format,type){var separators=format.replace(this.validParts(type),"\0").split("\0"),parts=format.match(this.validParts(type));if(!separators||!separators.length||!parts||parts.length===0){throw new Error("Invalid date format.")}return{separators:separators,parts:parts}},parseDate:function(date,format,language,type,timezone){if(date instanceof Date){var dateUTC=new Date(date.valueOf()-date.getTimezoneOffset()*60000);dateUTC.setMilliseconds(0);return dateUTC}if(/^\d{4}\-\d{1,2}\-\d{1,2}$/.test(date)){format=this.parseFormat("yyyy-mm-dd",type)}if(/^\d{4}\-\d{1,2}\-\d{1,2}[T ]\d{1,2}\:\d{1,2}$/.test(date)){format=this.parseFormat("yyyy-mm-dd hh:ii",type)}if(/^\d{4}\-\d{1,2}\-\d{1,2}[T ]\d{1,2}\:\d{1,2}\:\d{1,2}[Z]{0,1}$/.test(date)){format=this.parseFormat("yyyy-mm-dd hh:ii:ss",type)}if(/^[-+]\d+[dmwy]([\s,]+[-+]\d+[dmwy])*$/.test(date)){var part_re=/([-+]\d+)([dmwy])/,parts=date.match(/([-+]\d+)([dmwy])/g),part,dir;date=new Date();for(var i=0;i<parts.length;i++){part=part_re.exec(parts[i]);dir=parseInt(part[1]);switch(part[2]){case"d":date.setUTCDate(date.getUTCDate()+dir);break;case"m":date=Datetimepicker.prototype.moveMonth.call(Datetimepicker.prototype,date,dir);break;case"w":date.setUTCDate(date.getUTCDate()+dir*7);break;case"y":date=Datetimepicker.prototype.moveYear.call(Datetimepicker.prototype,date,dir);break}}return UTCDate(date.getUTCFullYear(),date.getUTCMonth(),date.getUTCDate(),date.getUTCHours(),date.getUTCMinutes(),date.getUTCSeconds(),0)}var parts=date&&date.toString().match(this.nonpunctuation)||[],date=new Date(0,0,0,0,0,0,0),parsed={},setters_order=["hh","h","ii","i","ss","s","yyyy","yy","M","MM","m","mm","D","DD","d","dd","H","HH","p","P","z","Z"],setters_map={hh:function(d,v){return d.setUTCHours(v)},h:function(d,v){return d.setUTCHours(v)},HH:function(d,v){return d.setUTCHours(v===12?0:v)},H:function(d,v){return d.setUTCHours(v===12?0:v)},ii:function(d,v){return d.setUTCMinutes(v)},i:function(d,v){return d.setUTCMinutes(v)},ss:function(d,v){return d.setUTCSeconds(v)},s:function(d,v){return d.setUTCSeconds(v)},yyyy:function(d,v){return d.setUTCFullYear(v)},yy:function(d,v){return d.setUTCFullYear(2000+v)},m:function(d,v){v-=1;while(v<0){v+=12}v%=12;d.setUTCMonth(v);while(d.getUTCMonth()!==v){if(isNaN(d.getUTCMonth())){return d}else{d.setUTCDate(d.getUTCDate()-1)}}return d},d:function(d,v){return d.setUTCDate(v)},p:function(d,v){return d.setUTCHours(v===1?d.getUTCHours()+12:d.getUTCHours())},z:function(){return timezone}},val,filtered,part;setters_map["M"]=setters_map["MM"]=setters_map["mm"]=setters_map["m"];setters_map["dd"]=setters_map["d"];setters_map["P"]=setters_map["p"];setters_map["Z"]=setters_map["z"];date=UTCDate(date.getFullYear(),date.getMonth(),date.getDate(),date.getHours(),date.getMinutes(),date.getSeconds());if(parts.length===format.parts.length){for(var i=0,cnt=format.parts.length;i<cnt;i++){val=parseInt(parts[i],10);part=format.parts[i];if(isNaN(val)){switch(part){case"MM":filtered=$(dates[language].months).filter(function(){var m=this.slice(0,parts[i].length),p=parts[i].slice(0,m.length);return m===p});val=$.inArray(filtered[0],dates[language].months)+1;break;case"M":filtered=$(dates[language].monthsShort).filter(function(){var m=this.slice(0,parts[i].length),p=parts[i].slice(0,m.length);return m.toLowerCase()===p.toLowerCase()});val=$.inArray(filtered[0],dates[language].monthsShort)+1;break;case"p":case"P":val=$.inArray(parts[i].toLowerCase(),dates[language].meridiem);break;case"z":case"Z":timezone;break}}parsed[part]=val}for(var i=0,s;i<setters_order.length;i++){s=setters_order[i];if(s in parsed&&!isNaN(parsed[s])){setters_map[s](date,parsed[s])}}}return date},formatDate:function(date,format,language,type,timezone){if(date===null){return""}var val;if(type==="standard"){val={t:date.getTime(),yy:date.getUTCFullYear().toString().substring(2),yyyy:date.getUTCFullYear(),m:date.getUTCMonth()+1,M:dates[language].monthsShort[date.getUTCMonth()],MM:dates[language].months[date.getUTCMonth()],d:date.getUTCDate(),D:dates[language].daysShort[date.getUTCDay()],DD:dates[language].days[date.getUTCDay()],p:(dates[language].meridiem.length===2?dates[language].meridiem[date.getUTCHours()<12?0:1]:""),h:date.getUTCHours(),i:date.getUTCMinutes(),s:date.getUTCSeconds(),z:timezone};if(dates[language].meridiem.length===2){val.H=(val.h%12===0?12:val.h%12)}else{val.H=val.h}val.HH=(val.H<10?"0":"")+val.H;val.P=val.p.toUpperCase();val.Z=val.z;val.hh=(val.h<10?"0":"")+val.h;val.ii=(val.i<10?"0":"")+val.i;val.ss=(val.s<10?"0":"")+val.s;val.dd=(val.d<10?"0":"")+val.d;val.mm=(val.m<10?"0":"")+val.m}else{if(type==="php"){val={y:date.getUTCFullYear().toString().substring(2),Y:date.getUTCFullYear(),F:dates[language].months[date.getUTCMonth()],M:dates[language].monthsShort[date.getUTCMonth()],n:date.getUTCMonth()+1,t:DPGlobal.getDaysInMonth(date.getUTCFullYear(),date.getUTCMonth()),j:date.getUTCDate(),l:dates[language].days[date.getUTCDay()],D:dates[language].daysShort[date.getUTCDay()],w:date.getUTCDay(),N:(date.getUTCDay()===0?7:date.getUTCDay()),S:(date.getUTCDate()%10<=dates[language].suffix.length?dates[language].suffix[date.getUTCDate()%10-1]:""),a:(dates[language].meridiem.length===2?dates[language].meridiem[date.getUTCHours()<12?0:1]:""),g:(date.getUTCHours()%12===0?12:date.getUTCHours()%12),G:date.getUTCHours(),i:date.getUTCMinutes(),s:date.getUTCSeconds()};val.m=(val.n<10?"0":"")+val.n;val.d=(val.j<10?"0":"")+val.j;val.A=val.a.toString().toUpperCase();val.h=(val.g<10?"0":"")+val.g;val.H=(val.G<10?"0":"")+val.G;val.i=(val.i<10?"0":"")+val.i;val.s=(val.s<10?"0":"")+val.s}else{throw new Error("Invalid format type.")}}var date=[],seps=$.extend([],format.separators);for(var i=0,cnt=format.parts.length;i<cnt;i++){if(seps.length){date.push(seps.shift())}date.push(val[format.parts[i]])}if(seps.length){date.push(seps.shift())}return date.join("")},convertViewMode:function(viewMode){switch(viewMode){case 4:case"decade":viewMode=4;break;case 3:case"year":viewMode=3;break;case 2:case"month":viewMode=2;break;case 1:case"day":viewMode=1;break;case 0:case"hour":viewMode=0;break}return viewMode},headTemplate:"<thead>"+"<tr>"+'<th class="prev"><i class="{iconType} {leftArrow}"/></th>'+'<th colspan="5" class="switch"></th>'+'<th class="next"><i class="{iconType} {rightArrow}"/></th>'+"</tr>"+"</thead>",headTemplateV3:"<thead>"+"<tr>"+'<th class="prev"><span class="{iconType} {leftArrow}"></span> </th>'+'<th colspan="5" class="switch"></th>'+'<th class="next"><span class="{iconType} {rightArrow}"></span> </th>'+"</tr>"+"</thead>",contTemplate:'<tbody><tr><td colspan="7"></td></tr></tbody>',footTemplate:"<tfoot>"+'<tr><th colspan="7" class="today"></th></tr>'+'<tr><th colspan="7" class="clear"></th></tr>'+"</tfoot>"};DPGlobal.template='<div class="datetimepicker">'+'<div class="datetimepicker-minutes">'+'<table class=" table-condensed">'+DPGlobal.headTemplate+DPGlobal.contTemplate+DPGlobal.footTemplate+"</table>"+"</div>"+'<div class="datetimepicker-hours">'+'<table class=" table-condensed">'+DPGlobal.headTemplate+DPGlobal.contTemplate+DPGlobal.footTemplate+"</table>"+"</div>"+'<div class="datetimepicker-days">'+'<table class=" table-condensed">'+DPGlobal.headTemplate+"<tbody></tbody>"+DPGlobal.footTemplate+"</table>"+"</div>"+'<div class="datetimepicker-months">'+'<table class="table-condensed">'+DPGlobal.headTemplate+DPGlobal.contTemplate+DPGlobal.footTemplate+"</table>"+"</div>"+'<div class="datetimepicker-years">'+'<table class="table-condensed">'+DPGlobal.headTemplate+DPGlobal.contTemplate+DPGlobal.footTemplate+"</table>"+"</div>"+"</div>";DPGlobal.templateV3='<div class="datetimepicker">'+'<div class="datetimepicker-minutes">'+'<table class=" table-condensed">'+DPGlobal.headTemplateV3+DPGlobal.contTemplate+DPGlobal.footTemplate+"</table>"+"</div>"+'<div class="datetimepicker-hours">'+'<table class=" table-condensed">'+DPGlobal.headTemplateV3+DPGlobal.contTemplate+DPGlobal.footTemplate+"</table>"+"</div>"+'<div class="datetimepicker-days">'+'<table class=" table-condensed">'+DPGlobal.headTemplateV3+"<tbody></tbody>"+DPGlobal.footTemplate+"</table>"+"</div>"+'<div class="datetimepicker-months">'+'<table class="table-condensed">'+DPGlobal.headTemplateV3+DPGlobal.contTemplate+DPGlobal.footTemplate+"</table>"+"</div>"+'<div class="datetimepicker-years">'+'<table class="table-condensed">'+DPGlobal.headTemplateV3+DPGlobal.contTemplate+DPGlobal.footTemplate+"</table>"+"</div>"+"</div>";$.fn.datetimepicker.DPGlobal=DPGlobal;$.fn.datetimepicker.noConflict=function(){$.fn.datetimepicker=old;return this};$(document).on("focus.datetimepicker.data-api click.datetimepicker.data-api",'[data-provide="datetimepicker"]',function(e){var $this=$(this);if($this.data("datetimepicker")){return}e.preventDefault();$this.datetimepicker("show")});$(function(){$('[data-provide="datetimepicker-inline"]').datetimepicker()})}));
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/duallistbox/bootstrap-duallistbox.css b/ruoyi-admin/src/main/resources/static/ajax/libs/duallistbox/bootstrap-duallistbox.css
new file mode 100644
index 0000000..e35978b
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/duallistbox/bootstrap-duallistbox.css
@@ -0,0 +1,86 @@
+/*
+ *  Bootstrap Duallistbox - v3.0.9
+ *  A responsive dual listbox widget optimized for Twitter Bootstrap. It works on all modern browsers and on touch devices.
+ *  https://www.virtuosoft.eu/code/bootstrap-duallistbox/
+ *
+ *  Made by István Ujj-Mészáros
+ *  Under Apache License v2.0 License
+ */
+.bootstrap-duallistbox-container .buttons {
+  width: 100%;
+  margin-bottom: -1px;
+}
+
+.bootstrap-duallistbox-container label {
+  display: block;
+}
+
+.bootstrap-duallistbox-container .info {
+  display: inline-block;
+  margin-bottom: 5px;
+  font-size: 11px;
+}
+
+.bootstrap-duallistbox-container .clear1,
+.bootstrap-duallistbox-container .clear2 {
+  display: none;
+  font-size: 10px;
+}
+
+.bootstrap-duallistbox-container .box1.filtered .clear1,
+.bootstrap-duallistbox-container .box2.filtered .clear2 {
+  display: inline-block;
+}
+
+.bootstrap-duallistbox-container .move,
+.bootstrap-duallistbox-container .remove {
+  width: 60%;
+}
+
+.bootstrap-duallistbox-container .btn-group .btn {
+  border-bottom-left-radius: 0;
+  border-bottom-right-radius: 0;
+}
+.bootstrap-duallistbox-container select {
+  border-top-left-radius: 0;
+  border-top-right-radius: 0;
+}
+
+.bootstrap-duallistbox-container .moveall,
+.bootstrap-duallistbox-container .removeall {
+  width: 40%;
+}
+
+.bootstrap-duallistbox-container.bs2compatible .btn-group > .btn + .btn {
+  margin-left: 0;
+}
+
+.bootstrap-duallistbox-container select {
+  width: 100%;
+  height: 300px;
+  padding: 0;
+}
+
+.bootstrap-duallistbox-container .filter {
+  display: inline-block;
+  width: 100%;
+  height: 31px;
+  margin: 0 0 5px 0;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+
+.bootstrap-duallistbox-container .filter.placeholder {
+  color: #aaa;
+}
+
+.bootstrap-duallistbox-container.moveonselect .move,
+.bootstrap-duallistbox-container.moveonselect .remove {
+  display:none;
+}
+
+.bootstrap-duallistbox-container.moveonselect .moveall,
+.bootstrap-duallistbox-container.moveonselect .removeall {
+  width: 100%;
+}
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/duallistbox/bootstrap-duallistbox.js b/ruoyi-admin/src/main/resources/static/ajax/libs/duallistbox/bootstrap-duallistbox.js
new file mode 100644
index 0000000..6dc6e7b
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/duallistbox/bootstrap-duallistbox.js
@@ -0,0 +1,844 @@
+/*
+ *  Bootstrap Duallistbox - v3.0.9
+ *  A responsive dual listbox widget optimized for Twitter Bootstrap. It works on all modern browsers and on touch devices.
+ *  https://www.virtuosoft.eu/code/bootstrap-duallistbox/
+ *
+ *  Made by István Ujj-Mészáros
+ *  Under Apache License v2.0 License
+ */
+;(function ($, window, document, undefined) {
+  // Create the defaults once
+  var pluginName = 'bootstrapDualListbox',
+    defaults = {
+      bootstrap2Compatible: false,
+      filterTextClear: 'show all',
+      filterPlaceHolder: 'Filter',
+      moveSelectedLabel: 'Move selected',
+      moveAllLabel: 'Move all',
+      removeSelectedLabel: 'Remove selected',
+      removeAllLabel: 'Remove all',
+      moveOnSelect: true,                                                                 // true/false (forced true on androids, see the comment later)
+      moveOnDoubleClick: true,                                                            // true/false (forced false on androids, cause moveOnSelect is forced to true)
+      preserveSelectionOnMove: false,                                                     // 'all' / 'moved' / false
+      selectedListLabel: false,                                                           // 'string', false
+      nonSelectedListLabel: false,                                                        // 'string', false
+      helperSelectNamePostfix: '_helper',                                                 // 'string_of_postfix' / false
+      selectorMinimalHeight: 100,
+      showFilterInputs: true,                                                             // whether to show filter inputs
+      nonSelectedFilter: '',                                                              // string, filter the non selected options
+      selectedFilter: '',                                                                 // string, filter the selected options
+      infoText: 'Showing all {0}',                                                        // text when all options are visible / false for no info text
+      infoTextFiltered: '<span class="label label-warning">Filtered</span> {0} from {1}', // when not all of the options are visible due to the filter
+      infoTextEmpty: 'Empty list',                                                        // when there are no options present in the list
+      filterOnValues: false,                                                              // filter by selector's values, boolean
+      sortByInputOrder: false,
+      eventMoveOverride: false,                                                           // boolean, allows user to unbind default event behaviour and run their own instead
+      eventMoveAllOverride: false,                                                        // boolean, allows user to unbind default event behaviour and run their own instead
+      eventRemoveOverride: false,                                                         // boolean, allows user to unbind default event behaviour and run their own instead
+      eventRemoveAllOverride: false                                                       // boolean, allows user to unbind default event behaviour and run their own instead
+    },
+    // Selections are invisible on android if the containing select is styled with CSS
+    // http://code.google.com/p/android/issues/detail?id=16922
+    isBuggyAndroid = /android/i.test(navigator.userAgent.toLowerCase());
+
+  // The actual plugin constructor
+  function BootstrapDualListbox(element, options) {
+    this.element = $(element);
+    // jQuery has an extend method which merges the contents of two or
+    // more objects, storing the result in the first object. The first object
+    // is generally empty as we don't want to alter the default options for
+    // future instances of the plugin
+    this.settings = $.extend({}, defaults, options);
+    this._defaults = defaults;
+    this._name = pluginName;
+    this.init();
+  }
+
+  function triggerChangeEvent(dualListbox) {
+    dualListbox.element.trigger('change');
+  }
+
+  function updateSelectionStates(dualListbox) {
+    dualListbox.element.find('option').each(function(index, item) {
+      var $item = $(item);
+      if (typeof($item.data('original-index')) === 'undefined') {
+        $item.data('original-index', dualListbox.elementCount++);
+      }
+      if (typeof($item.data('_selected')) === 'undefined') {
+        $item.data('_selected', false);
+      }
+    });
+  }
+
+  function changeSelectionState(dualListbox, original_index, selected) {
+    dualListbox.element.find('option').each(function(index, item) {
+      var $item = $(item);
+      if ($item.data('original-index') === original_index) {
+        $item.prop('selected', selected);
+        if(selected){
+          $item.attr('data-sortindex', dualListbox.sortIndex);
+          dualListbox.sortIndex++;
+        } else {
+          $item.removeAttr('data-sortindex');
+        }
+      }
+    });
+  }
+
+  function formatString(s, args) {
+    return s.replace(/\{(\d+)\}/g, function(match, number) {
+      return typeof args[number] !== 'undefined' ? args[number] : match;
+    });
+  }
+
+  function refreshInfo(dualListbox) {
+    if (!dualListbox.settings.infoText) {
+      return;
+    }
+
+    var visible1 = dualListbox.elements.select1.find('option').length,
+      visible2 = dualListbox.elements.select2.find('option').length,
+      all1 = dualListbox.element.find('option').length - dualListbox.selectedElements,
+      all2 = dualListbox.selectedElements,
+      content = '';
+
+    if (all1 === 0) {
+      content = dualListbox.settings.infoTextEmpty;
+    } else if (visible1 === all1) {
+      content = formatString(dualListbox.settings.infoText, [visible1, all1]);
+    } else {
+      content = formatString(dualListbox.settings.infoTextFiltered, [visible1, all1]);
+    }
+
+    dualListbox.elements.info1.html(content);
+    dualListbox.elements.box1.toggleClass('filtered', !(visible1 === all1 || all1 === 0));
+
+    if (all2 === 0) {
+      content = dualListbox.settings.infoTextEmpty;
+    } else if (visible2 === all2) {
+      content = formatString(dualListbox.settings.infoText, [visible2, all2]);
+    } else {
+      content = formatString(dualListbox.settings.infoTextFiltered, [visible2, all2]);
+    }
+
+    dualListbox.elements.info2.html(content);
+    dualListbox.elements.box2.toggleClass('filtered', !(visible2 === all2 || all2 === 0));
+  }
+
+  function refreshSelects(dualListbox) {
+    dualListbox.selectedElements = 0;
+
+    dualListbox.elements.select1.empty();
+    dualListbox.elements.select2.empty();
+
+    dualListbox.element.find('option').each(function(index, item) {
+      var $item = $(item);
+      if ($item.prop('selected')) {
+        dualListbox.selectedElements++;
+        dualListbox.elements.select2.append($item.clone(true).prop('selected', $item.data('_selected')));
+      } else {
+        dualListbox.elements.select1.append($item.clone(true).prop('selected', $item.data('_selected')));
+      }
+    });
+
+    if (dualListbox.settings.showFilterInputs) {
+      filter(dualListbox, 1);
+      filter(dualListbox, 2);
+    }
+    refreshInfo(dualListbox);
+  }
+
+  function filter(dualListbox, selectIndex) {
+    if (!dualListbox.settings.showFilterInputs) {
+      return;
+    }
+
+    saveSelections(dualListbox, selectIndex);
+
+    dualListbox.elements['select'+selectIndex].empty().scrollTop(0);
+    var regex = new RegExp($.trim(dualListbox.elements['filterInput'+selectIndex].val()), 'gi'),
+      allOptions = dualListbox.element.find('option'),
+      options = dualListbox.element;
+
+    if (selectIndex === 1) {
+      options = allOptions.not(':selected');
+    } else  {
+      options = options.find('option:selected');
+    }
+
+    options.each(function(index, item) {
+      var $item = $(item),
+        isFiltered = true;
+      if (item.text.match(regex) || (dualListbox.settings.filterOnValues && $item.attr('value').match(regex) ) ) {
+        isFiltered = false;
+        dualListbox.elements['select'+selectIndex].append($item.clone(true).prop('selected', $item.data('_selected')));
+      }
+      allOptions.eq($item.data('original-index')).data('filtered'+selectIndex, isFiltered);
+    });
+
+    refreshInfo(dualListbox);
+  }
+
+  function saveSelections(dualListbox, selectIndex) {
+    var options = dualListbox.element.find('option');
+    dualListbox.elements['select'+selectIndex].find('option').each(function(index, item) {
+      var $item = $(item);
+      options.eq($item.data('original-index')).data('_selected', $item.prop('selected'));
+    });
+  }
+
+  function sortOptionsByInputOrder(select){
+    var selectopt = select.children('option');
+
+    selectopt.sort(function(a,b){
+      var an = parseInt(a.getAttribute('data-sortindex')),
+          bn = parseInt(b.getAttribute('data-sortindex'));
+
+          if(an > bn) {
+             return 1;
+          }
+          if(an < bn) {
+            return -1;
+          }
+          return 0;
+    });
+
+    selectopt.detach().appendTo(select);
+  }
+
+  function sortOptions(select, dualListbox) {
+    select.find('option').sort(function(a, b) {
+      return ($(a).data('original-index') > $(b).data('original-index')) ? 1 : -1;
+    }).appendTo(select);
+
+    // workaround for chromium bug: https://bugs.chromium.org/p/chromium/issues/detail?id=1072475
+    refreshSelects(dualListbox);
+  }
+
+  function clearSelections(dualListbox) {
+    dualListbox.elements.select1.find('option').each(function() {
+      dualListbox.element.find('option').data('_selected', false);
+    });
+  }
+
+  function move(dualListbox) {
+    if (dualListbox.settings.preserveSelectionOnMove === 'all' && !dualListbox.settings.moveOnSelect) {
+      saveSelections(dualListbox, 1);
+      saveSelections(dualListbox, 2);
+    } else if (dualListbox.settings.preserveSelectionOnMove === 'moved' && !dualListbox.settings.moveOnSelect) {
+      saveSelections(dualListbox, 1);
+    }
+
+    dualListbox.elements.select1.find('option:selected').each(function(index, item) {
+      var $item = $(item);
+      if (!$item.data('filtered1')) {
+        changeSelectionState(dualListbox, $item.data('original-index'), true);
+      }
+    });
+
+    refreshSelects(dualListbox);
+    triggerChangeEvent(dualListbox);
+    if(dualListbox.settings.sortByInputOrder){
+        sortOptionsByInputOrder(dualListbox.elements.select2);
+    } else {
+        sortOptions(dualListbox.elements.select2, dualListbox);
+    }
+  }
+
+  function remove(dualListbox) {
+    if (dualListbox.settings.preserveSelectionOnMove === 'all' && !dualListbox.settings.moveOnSelect) {
+      saveSelections(dualListbox, 1);
+      saveSelections(dualListbox, 2);
+    } else if (dualListbox.settings.preserveSelectionOnMove === 'moved' && !dualListbox.settings.moveOnSelect) {
+      saveSelections(dualListbox, 2);
+    }
+
+    dualListbox.elements.select2.find('option:selected').each(function(index, item) {
+      var $item = $(item);
+      if (!$item.data('filtered2')) {
+        changeSelectionState(dualListbox, $item.data('original-index'), false);
+      }
+    });
+
+    refreshSelects(dualListbox);
+    triggerChangeEvent(dualListbox);
+    sortOptions(dualListbox.elements.select1, dualListbox);
+    if(dualListbox.settings.sortByInputOrder){
+        sortOptionsByInputOrder(dualListbox.elements.select2);
+    }
+  }
+
+  function moveAll(dualListbox) {
+    if (dualListbox.settings.preserveSelectionOnMove === 'all' && !dualListbox.settings.moveOnSelect) {
+      saveSelections(dualListbox, 1);
+      saveSelections(dualListbox, 2);
+    } else if (dualListbox.settings.preserveSelectionOnMove === 'moved' && !dualListbox.settings.moveOnSelect) {
+      saveSelections(dualListbox, 1);
+    }
+
+    dualListbox.element.find('option').each(function(index, item) {
+      var $item = $(item);
+      if (!$item.data('filtered1')) {
+        $item.prop('selected', true);
+        $item.attr('data-sortindex', dualListbox.sortIndex);
+        dualListbox.sortIndex++;
+      }
+    });
+
+    refreshSelects(dualListbox);
+    triggerChangeEvent(dualListbox);
+  }
+
+  function removeAll(dualListbox) {
+    if (dualListbox.settings.preserveSelectionOnMove === 'all' && !dualListbox.settings.moveOnSelect) {
+      saveSelections(dualListbox, 1);
+      saveSelections(dualListbox, 2);
+    } else if (dualListbox.settings.preserveSelectionOnMove === 'moved' && !dualListbox.settings.moveOnSelect) {
+      saveSelections(dualListbox, 2);
+    }
+
+    dualListbox.element.find('option').each(function(index, item) {
+      var $item = $(item);
+      if (!$item.data('filtered2')) {
+        $item.prop('selected', false);
+        $item.removeAttr('data-sortindex');
+      }
+    });
+
+    refreshSelects(dualListbox);
+    triggerChangeEvent(dualListbox);
+  }
+
+  function bindEvents(dualListbox) {
+    dualListbox.elements.form.submit(function(e) {
+      if (dualListbox.elements.filterInput1.is(':focus')) {
+        e.preventDefault();
+        dualListbox.elements.filterInput1.focusout();
+      } else if (dualListbox.elements.filterInput2.is(':focus')) {
+        e.preventDefault();
+        dualListbox.elements.filterInput2.focusout();
+      }
+    });
+
+    dualListbox.element.on('bootstrapDualListbox.refresh', function(e, mustClearSelections){
+      dualListbox.refresh(mustClearSelections);
+    });
+
+    dualListbox.elements.filterClear1.on('click', function() {
+      dualListbox.setNonSelectedFilter('', true);
+    });
+
+    dualListbox.elements.filterClear2.on('click', function() {
+      dualListbox.setSelectedFilter('', true);
+    });
+
+    if (dualListbox.settings.eventMoveOverride === false) {
+      dualListbox.elements.moveButton.on('click', function() {
+        move(dualListbox);
+      });
+    }
+
+    if (dualListbox.settings.eventMoveAllOverride === false) {
+      dualListbox.elements.moveAllButton.on('click', function() {
+        moveAll(dualListbox);
+      });
+    }
+
+    if (dualListbox.settings.eventRemoveOverride === false) {
+      dualListbox.elements.removeButton.on('click', function() {
+        remove(dualListbox);
+      });
+    }
+
+    if (dualListbox.settings.eventRemoveAllOverride === false) {
+      dualListbox.elements.removeAllButton.on('click', function() {
+        removeAll(dualListbox);
+      });
+    }
+
+    dualListbox.elements.filterInput1.on('change keyup', function() {
+      filter(dualListbox, 1);
+    });
+
+    dualListbox.elements.filterInput2.on('change keyup', function() {
+      filter(dualListbox, 2);
+    });
+  }
+
+  BootstrapDualListbox.prototype = {
+    init: function () {
+      // Add the custom HTML template
+      this.container = $('' +
+        '<div class="bootstrap-duallistbox-container">' +
+        ' <div class="box1">' +
+        '   <label></label>' +
+        '   <span class="info-container">' +
+        '     <span class="info"></span>' +
+        '     <button type="button" class="btn clear1 pull-right"></button>' +
+        '   </span>' +
+        '   <input class="filter" type="text">' +
+        '   <div class="btn-group buttons">' +
+        '     <button type="button" class="btn moveall">' +
+        '       <i></i>' +
+        '       <i></i>' +
+        '     </button>' +
+        '     <button type="button" class="btn move">' +
+        '       <i></i>' +
+        '     </button>' +
+        '   </div>' +
+        '   <select multiple="multiple"></select>' +
+        ' </div>' +
+        ' <div class="box2">' +
+        '   <label></label>' +
+        '   <span class="info-container">' +
+        '     <span class="info"></span>' +
+        '     <button type="button" class="btn clear2 pull-right"></button>' +
+        '   </span>' +
+        '   <input class="filter" type="text">' +
+        '   <div class="btn-group buttons">' +
+        '     <button type="button" class="btn remove">' +
+        '       <i></i>' +
+        '     </button>' +
+        '     <button type="button" class="btn removeall">' +
+        '       <i></i>' +
+        '       <i></i>' +
+        '     </button>' +
+        '   </div>' +
+        '   <select multiple="multiple"></select>' +
+        ' </div>' +
+        '</div>')
+        .insertBefore(this.element);
+
+      // Cache the inner elements
+      this.elements = {
+        originalSelect: this.element,
+        box1: $('.box1', this.container),
+        box2: $('.box2', this.container),
+        filterInput1: $('.box1 .filter', this.container),
+        filterInput2: $('.box2 .filter', this.container),
+        filterClear1: $('.box1 .clear1', this.container),
+        filterClear2: $('.box2 .clear2', this.container),
+        label1: $('.box1 > label', this.container),
+        label2: $('.box2 > label', this.container),
+        info1: $('.box1 .info', this.container),
+        info2: $('.box2 .info', this.container),
+        select1: $('.box1 select', this.container),
+        select2: $('.box2 select', this.container),
+        moveButton: $('.box1 .move', this.container),
+        removeButton: $('.box2 .remove', this.container),
+        moveAllButton: $('.box1 .moveall', this.container),
+        removeAllButton: $('.box2 .removeall', this.container),
+        form: $($('.box1 .filter', this.container)[0].form)
+      };
+
+      // Set select IDs
+      this.originalSelectName = this.element.attr('name') || '';
+      var select1Id = 'bootstrap-duallistbox-nonselected-list_' + this.originalSelectName,
+        select2Id = 'bootstrap-duallistbox-selected-list_' + this.originalSelectName;
+      this.elements.select1.attr('id', select1Id);
+      this.elements.select2.attr('id', select2Id);
+      this.elements.label1.attr('for', select1Id);
+      this.elements.label2.attr('for', select2Id);
+
+      // Apply all settings
+      this.selectedElements = 0;
+      this.sortIndex = 0;
+      this.elementCount = 0;
+      this.setBootstrap2Compatible(this.settings.bootstrap2Compatible);
+      this.setFilterTextClear(this.settings.filterTextClear);
+      this.setFilterPlaceHolder(this.settings.filterPlaceHolder);
+      this.setMoveSelectedLabel(this.settings.moveSelectedLabel);
+      this.setMoveAllLabel(this.settings.moveAllLabel);
+      this.setRemoveSelectedLabel(this.settings.removeSelectedLabel);
+      this.setRemoveAllLabel(this.settings.removeAllLabel);
+      this.setMoveOnSelect(this.settings.moveOnSelect);
+      this.setMoveOnDoubleClick(this.settings.moveOnDoubleClick);
+      this.setPreserveSelectionOnMove(this.settings.preserveSelectionOnMove);
+      this.setSelectedListLabel(this.settings.selectedListLabel);
+      this.setNonSelectedListLabel(this.settings.nonSelectedListLabel);
+      this.setHelperSelectNamePostfix(this.settings.helperSelectNamePostfix);
+      this.setSelectOrMinimalHeight(this.settings.selectorMinimalHeight);
+
+      updateSelectionStates(this);
+
+      this.setShowFilterInputs(this.settings.showFilterInputs);
+      this.setNonSelectedFilter(this.settings.nonSelectedFilter);
+      this.setSelectedFilter(this.settings.selectedFilter);
+      this.setInfoText(this.settings.infoText);
+      this.setInfoTextFiltered(this.settings.infoTextFiltered);
+      this.setInfoTextEmpty(this.settings.infoTextEmpty);
+      this.setFilterOnValues(this.settings.filterOnValues);
+      this.setSortByInputOrder(this.settings.sortByInputOrder);
+      this.setEventMoveOverride(this.settings.eventMoveOverride);
+      this.setEventMoveAllOverride(this.settings.eventMoveAllOverride);
+      this.setEventRemoveOverride(this.settings.eventRemoveOverride);
+      this.setEventRemoveAllOverride(this.settings.eventRemoveAllOverride);
+
+      // Hide the original select
+      this.element.hide();
+
+      bindEvents(this);
+      refreshSelects(this);
+
+      return this.element;
+    },
+    setBootstrap2Compatible: function(value, refresh) {
+      this.settings.bootstrap2Compatible = value;
+      if (value) {
+        this.container.removeClass('row').addClass('row-fluid bs2compatible');
+        this.container.find('.box1, .box2').removeClass('col-md-6').addClass('span6');
+        this.container.find('.clear1, .clear2').removeClass('btn-default btn-xs').addClass('btn-mini');
+        this.container.find('input, select').removeClass('form-control');
+        this.container.find('.btn').removeClass('btn-default');
+        this.container.find('.moveall > i, .move > i').removeClass('glyphicon glyphicon-arrow-right').addClass('icon-arrow-right');
+        this.container.find('.removeall > i, .remove > i').removeClass('glyphicon glyphicon-arrow-left').addClass('icon-arrow-left');
+      } else {
+        this.container.removeClass('row-fluid bs2compatible').addClass('row');
+        this.container.find('.box1, .box2').removeClass('span6').addClass('col-md-6');
+        this.container.find('.clear1, .clear2').removeClass('btn-mini').addClass('btn-default btn-xs');
+        this.container.find('input, select').addClass('form-control');
+        this.container.find('.btn').addClass('btn-default');
+        this.container.find('.moveall > i, .move > i').removeClass('icon-arrow-right').addClass('glyphicon glyphicon-arrow-right');
+        this.container.find('.removeall > i, .remove > i').removeClass('icon-arrow-left').addClass('glyphicon glyphicon-arrow-left');
+      }
+      if (refresh) {
+        refreshSelects(this);
+      }
+      return this.element;
+    },
+    setFilterTextClear: function(value, refresh) {
+      this.settings.filterTextClear = value;
+      this.elements.filterClear1.html(value);
+      this.elements.filterClear2.html(value);
+      if (refresh) {
+        refreshSelects(this);
+      }
+      return this.element;
+    },
+    setFilterPlaceHolder: function(value, refresh) {
+      this.settings.filterPlaceHolder = value;
+      this.elements.filterInput1.attr('placeholder', value);
+      this.elements.filterInput2.attr('placeholder', value);
+      if (refresh) {
+        refreshSelects(this);
+      }
+      return this.element;
+    },
+    setMoveSelectedLabel: function(value, refresh) {
+      this.settings.moveSelectedLabel = value;
+      this.elements.moveButton.attr('title', value);
+      if (refresh) {
+        refreshSelects(this);
+      }
+      return this.element;
+    },
+    setMoveAllLabel: function(value, refresh) {
+      this.settings.moveAllLabel = value;
+      this.elements.moveAllButton.attr('title', value);
+      if (refresh) {
+        refreshSelects(this);
+      }
+      return this.element;
+    },
+    setRemoveSelectedLabel: function(value, refresh) {
+      this.settings.removeSelectedLabel = value;
+      this.elements.removeButton.attr('title', value);
+      if (refresh) {
+        refreshSelects(this);
+      }
+      return this.element;
+    },
+    setRemoveAllLabel: function(value, refresh) {
+      this.settings.removeAllLabel = value;
+      this.elements.removeAllButton.attr('title', value);
+      if (refresh) {
+        refreshSelects(this);
+      }
+      return this.element;
+    },
+    setMoveOnSelect: function(value, refresh) {
+      if (isBuggyAndroid) {
+        value = true;
+      }
+      this.settings.moveOnSelect = value;
+      if (this.settings.moveOnSelect) {
+        this.container.addClass('moveonselect');
+        var self = this;
+        this.elements.select1.on('change', function() {
+          move(self);
+        });
+        this.elements.select2.on('change', function() {
+          remove(self);
+        });
+      } else {
+        this.container.removeClass('moveonselect');
+        this.elements.select1.off('change');
+        this.elements.select2.off('change');
+      }
+      if (refresh) {
+        refreshSelects(this);
+      }
+      return this.element;
+    },
+    setMoveOnDoubleClick: function(value, refresh) {
+      if (isBuggyAndroid) {
+        value = false;
+      }
+      this.settings.moveOnDoubleClick = value;
+      if (this.settings.moveOnDoubleClick) {
+        this.container.addClass('moveondoubleclick');
+        var self = this;
+        this.elements.select1.on('dblclick', function() {
+          move(self);
+        });
+        this.elements.select2.on('dblclick', function() {
+          remove(self);
+        });
+      } else {
+        this.container.removeClass('moveondoubleclick');
+        this.elements.select1.off('dblclick');
+        this.elements.select2.off('dblclick');
+      }
+      if (refresh) {
+        refreshSelects(this);
+      }
+      return this.element;
+    },
+    setPreserveSelectionOnMove: function(value, refresh) {
+      // We are forcing to move on select and disabling preserveSelectionOnMove on Android
+      if (isBuggyAndroid) {
+        value = false;
+      }
+      this.settings.preserveSelectionOnMove = value;
+      if (refresh) {
+        refreshSelects(this);
+      }
+      return this.element;
+    },
+    setSelectedListLabel: function(value, refresh) {
+      this.settings.selectedListLabel = value;
+      if (value) {
+        this.elements.label2.show().html(value);
+      } else {
+        this.elements.label2.hide().html(value);
+      }
+      if (refresh) {
+        refreshSelects(this);
+      }
+      return this.element;
+    },
+    setNonSelectedListLabel: function(value, refresh) {
+      this.settings.nonSelectedListLabel = value;
+      if (value) {
+        this.elements.label1.show().html(value);
+      } else {
+        this.elements.label1.hide().html(value);
+      }
+      if (refresh) {
+        refreshSelects(this);
+      }
+      return this.element;
+    },
+    setHelperSelectNamePostfix: function(value, refresh) {
+      this.settings.helperSelectNamePostfix = value;
+      if (value) {
+        this.elements.select1.attr('name', this.originalSelectName + value + '1');
+        this.elements.select2.attr('name', this.originalSelectName + value + '2');
+      } else {
+        this.elements.select1.removeAttr('name');
+        this.elements.select2.removeAttr('name');
+      }
+      if (refresh) {
+        refreshSelects(this);
+      }
+      return this.element;
+    },
+    setSelectOrMinimalHeight: function(value, refresh) {
+      this.settings.selectorMinimalHeight = value;
+      var height = this.element.height();
+      if (this.element.height() < value) {
+        height = value;
+      }
+      this.elements.select1.height(height);
+      this.elements.select2.height(height);
+      if (refresh) {
+        refreshSelects(this);
+      }
+      return this.element;
+    },
+    setShowFilterInputs: function(value, refresh) {
+      if (!value) {
+        this.setNonSelectedFilter('');
+        this.setSelectedFilter('');
+        refreshSelects(this);
+        this.elements.filterInput1.hide();
+        this.elements.filterInput2.hide();
+      } else {
+        this.elements.filterInput1.show();
+        this.elements.filterInput2.show();
+      }
+      this.settings.showFilterInputs = value;
+      if (refresh) {
+        refreshSelects(this);
+      }
+      return this.element;
+    },
+    setNonSelectedFilter: function(value, refresh) {
+      if (this.settings.showFilterInputs) {
+        this.settings.nonSelectedFilter = value;
+        this.elements.filterInput1.val(value);
+        if (refresh) {
+          refreshSelects(this);
+        }
+        return this.element;
+      }
+    },
+    setSelectedFilter: function(value, refresh) {
+      if (this.settings.showFilterInputs) {
+        this.settings.selectedFilter = value;
+        this.elements.filterInput2.val(value);
+        if (refresh) {
+          refreshSelects(this);
+        }
+        return this.element;
+      }
+    },
+    setInfoText: function(value, refresh) {
+      this.settings.infoText = value;
+      if (value) {
+        this.elements.info1.show();
+        this.elements.info2.show();
+      } else {
+        this.elements.info1.hide();
+        this.elements.info2.hide();
+      }
+      if (refresh) {
+        refreshSelects(this);
+      }
+      return this.element;
+    },
+    setInfoTextFiltered: function(value, refresh) {
+      this.settings.infoTextFiltered = value;
+      if (refresh) {
+        refreshSelects(this);
+      }
+      return this.element;
+    },
+    setInfoTextEmpty: function(value, refresh) {
+      this.settings.infoTextEmpty = value;
+      if (refresh) {
+        refreshSelects(this);
+      }
+      return this.element;
+    },
+    setFilterOnValues: function(value, refresh) {
+      this.settings.filterOnValues = value;
+      if (refresh) {
+        refreshSelects(this);
+      }
+      return this.element;
+    },
+    setSortByInputOrder: function(value, refresh){
+        this.settings.sortByInputOrder = value;
+        if (refresh) {
+          refreshSelects(this);
+        }
+        return this.element;
+    },
+    setEventMoveOverride: function(value, refresh) {
+        this.settings.eventMoveOverride = value;
+        if (refresh) {
+          refreshSelects(this);
+        }
+        return this.element;
+    },
+    setEventMoveAllOverride: function(value, refresh) {
+        this.settings.eventMoveAllOverride = value;
+        if (refresh) {
+          refreshSelects(this);
+        }
+        return this.element;
+    },
+    setEventRemoveOverride: function(value, refresh) {
+        this.settings.eventRemoveOverride = value;
+        if (refresh) {
+          refreshSelects(this);
+        }
+        return this.element;
+    },
+    setEventRemoveAllOverride: function(value, refresh) {
+        this.settings.eventRemoveAllOverride = value;
+        if (refresh) {
+          refreshSelects(this);
+        }
+        return this.element;
+    },
+    getContainer: function() {
+      return this.container;
+    },
+    refresh: function(mustClearSelections) {
+      updateSelectionStates(this);
+
+      if (!mustClearSelections) {
+        saveSelections(this, 1);
+        saveSelections(this, 2);
+      } else {
+        clearSelections(this);
+      }
+
+      refreshSelects(this);
+    },
+    destroy: function() {
+      this.container.remove();
+      this.element.show();
+      $.data(this, 'plugin_' + pluginName, null);
+      return this.element;
+    }
+  };
+
+  // A really lightweight plugin wrapper around the constructor,
+  // preventing against multiple instantiations
+  $.fn[ pluginName ] = function (options) {
+    var args = arguments;
+
+    // Is the first parameter an object (options), or was omitted, instantiate a new instance of the plugin.
+    if (options === undefined || typeof options === 'object') {
+      return this.each(function () {
+        // If this is not a select
+        if (!$(this).is('select')) {
+          $(this).find('select').each(function(index, item) {
+            // For each nested select, instantiate the Dual List Box
+            $(item).bootstrapDualListbox(options);
+          });
+        } else if (!$.data(this, 'plugin_' + pluginName)) {
+          // Only allow the plugin to be instantiated once so we check that the element has no plugin instantiation yet
+
+          // if it has no instance, create a new one, pass options to our plugin constructor,
+          // and store the plugin instance in the elements jQuery data object.
+          $.data(this, 'plugin_' + pluginName, new BootstrapDualListbox(this, options));
+        }
+      });
+      // If the first parameter is a string and it doesn't start with an underscore or "contains" the `init`-function,
+      // treat this as a call to a public method.
+    } else if (typeof options === 'string' && options[0] !== '_' && options !== 'init') {
+
+      // Cache the method call to make it possible to return a value
+      var returns;
+
+      this.each(function () {
+        var instance = $.data(this, 'plugin_' + pluginName);
+        // Tests that there's already a plugin-instance and checks that the requested public method exists
+        if (instance instanceof BootstrapDualListbox && typeof instance[options] === 'function') {
+          // Call the method of our plugin instance, and pass it the supplied arguments.
+          returns = instance[options].apply(instance, Array.prototype.slice.call(args, 1));
+        }
+      });
+
+      // If the earlier cached method gives a value back return the value,
+      // otherwise return this to preserve chainability.
+      return returns !== undefined ? returns : this;
+    }
+
+  };
+
+})(jQuery, window, document);
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/duallistbox/bootstrap-duallistbox.min.css b/ruoyi-admin/src/main/resources/static/ajax/libs/duallistbox/bootstrap-duallistbox.min.css
new file mode 100644
index 0000000..750ac17
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/duallistbox/bootstrap-duallistbox.min.css
@@ -0,0 +1,9 @@
+/*
+ *  Bootstrap Duallistbox - v3.0.9
+ *  A responsive dual listbox widget optimized for Twitter Bootstrap. It works on all modern browsers and on touch devices.
+ *  https://www.virtuosoft.eu/code/bootstrap-duallistbox/
+ *
+ *  Made by István Ujj-Mészáros
+ *  Under Apache License v2.0 License
+ */
+.bootstrap-duallistbox-container .buttons{width:100%;margin-bottom:-1px}.bootstrap-duallistbox-container label{display:block}.bootstrap-duallistbox-container .info{display:inline-block;margin-bottom:5px;font-size:11px}.bootstrap-duallistbox-container .clear1,.bootstrap-duallistbox-container .clear2{display:none;font-size:10px}.bootstrap-duallistbox-container .box1.filtered .clear1,.bootstrap-duallistbox-container .box2.filtered .clear2{display:inline-block}.bootstrap-duallistbox-container .move,.bootstrap-duallistbox-container .remove{width:60%}.bootstrap-duallistbox-container .btn-group .btn{border-bottom-left-radius:0;border-bottom-right-radius:0}.bootstrap-duallistbox-container select{border-top-left-radius:0;border-top-right-radius:0}.bootstrap-duallistbox-container .moveall,.bootstrap-duallistbox-container .removeall{width:40%}.bootstrap-duallistbox-container.bs2compatible .btn-group>.btn+.btn{margin-left:0}.bootstrap-duallistbox-container select{width:100%;height:300px;padding:0}.bootstrap-duallistbox-container .filter{display:inline-block;width:100%;height:31px;margin:0 0 5px 0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bootstrap-duallistbox-container .filter.placeholder{color:#aaa}.bootstrap-duallistbox-container.moveonselect .move,.bootstrap-duallistbox-container.moveonselect .remove{display:none}.bootstrap-duallistbox-container.moveonselect .moveall,.bootstrap-duallistbox-container.moveonselect .removeall{width:100%}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/duallistbox/bootstrap-duallistbox.min.js b/ruoyi-admin/src/main/resources/static/ajax/libs/duallistbox/bootstrap-duallistbox.min.js
new file mode 100644
index 0000000..bfc9e77
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/duallistbox/bootstrap-duallistbox.min.js
@@ -0,0 +1,10 @@
+/*
+ *  Bootstrap Duallistbox - v3.0.9
+ *  A responsive dual listbox widget optimized for Twitter Bootstrap. It works on all modern browsers and on touch devices.
+ *  https://www.virtuosoft.eu/code/bootstrap-duallistbox/
+ *
+ *  Made by István Ujj-Mészáros
+ *  Under Apache License v2.0 License
+ */
+
+!function(a,e){var s="bootstrapDualListbox",n={bootstrap2Compatible:!1,filterTextClear:"show all",filterPlaceHolder:"Filter",moveSelectedLabel:"Move selected",moveAllLabel:"Move all",removeSelectedLabel:"Remove selected",removeAllLabel:"Remove all",moveOnSelect:!0,moveOnDoubleClick:!0,preserveSelectionOnMove:!1,selectedListLabel:!1,nonSelectedListLabel:!1,helperSelectNamePostfix:"_helper",selectorMinimalHeight:100,showFilterInputs:!0,nonSelectedFilter:"",selectedFilter:"",infoText:"Showing all {0}",infoTextFiltered:'<span class="label label-warning">Filtered</span> {0} from {1}',infoTextEmpty:"Empty list",filterOnValues:!1,sortByInputOrder:!1,eventMoveOverride:!1,eventMoveAllOverride:!1,eventRemoveOverride:!1,eventRemoveAllOverride:!1},i=/android/i.test(navigator.userAgent.toLowerCase());function l(e,t){this.element=a(e),this.settings=a.extend({},n,t),this._defaults=n,this._name=s,this.init()}function t(e){e.element.trigger("change")}function o(i){i.element.find("option").each(function(e,t){var n=a(t);void 0===n.data("original-index")&&n.data("original-index",i.elementCount++),void 0===n.data("_selected")&&n.data("_selected",!1)})}function r(i,s,l){i.element.find("option").each(function(e,t){var n=a(t);n.data("original-index")===s&&(n.prop("selected",l),l?(n.attr("data-sortindex",i.sortIndex),i.sortIndex++):n.removeAttr("data-sortindex"))})}function c(e,n){return e.replace(/\{(\d+)\}/g,function(e,t){return void 0!==n[t]?n[t]:e})}function h(e){if(e.settings.infoText){var t=e.elements.select1.find("option").length,n=e.elements.select2.find("option").length,i=e.element.find("option").length-e.selectedElements,s=e.selectedElements,l="";l=0==i?e.settings.infoTextEmpty:c(t===i?e.settings.infoText:e.settings.infoTextFiltered,[t,i]),e.elements.info1.html(l),e.elements.box1.toggleClass("filtered",!(t===i||0==i)),l=0===s?e.settings.infoTextEmpty:c(n===s?e.settings.infoText:e.settings.infoTextFiltered,[n,s]),e.elements.info2.html(l),e.elements.box2.toggleClass("filtered",!(n===s||0===s))}}function m(i){i.selectedElements=0,i.elements.select1.empty(),i.elements.select2.empty(),i.element.find("option").each(function(e,t){var n=a(t);n.prop("selected")?(i.selectedElements++,i.elements.select2.append(n.clone(!0).prop("selected",n.data("_selected")))):i.elements.select1.append(n.clone(!0).prop("selected",n.data("_selected")))}),i.settings.showFilterInputs&&(d(i,1),d(i,2)),h(i)}function d(s,l){if(s.settings.showFilterInputs){v(s,l),s.elements["select"+l].empty().scrollTop(0);var o=new RegExp(a.trim(s.elements["filterInput"+l].val()),"gi"),r=s.element.find("option"),e=s.element;(e=1===l?r.not(":selected"):e.find("option:selected")).each(function(e,t){var n=a(t),i=!0;(t.text.match(o)||s.settings.filterOnValues&&n.attr("value").match(o))&&(i=!1,s.elements["select"+l].append(n.clone(!0).prop("selected",n.data("_selected")))),r.eq(n.data("original-index")).data("filtered"+l,i)}),h(s)}}function v(e,t){var i=e.element.find("option");e.elements["select"+t].find("option").each(function(e,t){var n=a(t);i.eq(n.data("original-index")).data("_selected",n.prop("selected"))})}function f(e){var t=e.children("option");t.sort(function(e,t){var n=parseInt(e.getAttribute("data-sortindex")),i=parseInt(t.getAttribute("data-sortindex"));return i<n?1:n<i?-1:0}),t.detach().appendTo(e)}function u(e,t){e.find("option").sort(function(e,t){return a(e).data("original-index")>a(t).data("original-index")?1:-1}).appendTo(e),m(t)}function p(i){"all"!==i.settings.preserveSelectionOnMove||i.settings.moveOnSelect?"moved"!==i.settings.preserveSelectionOnMove||i.settings.moveOnSelect||v(i,1):(v(i,1),v(i,2)),i.elements.select1.find("option:selected").each(function(e,t){var n=a(t);n.data("filtered1")||r(i,n.data("original-index"),!0)}),m(i),t(i),i.settings.sortByInputOrder?f(i.elements.select2):u(i.elements.select2,i)}function g(i){"all"!==i.settings.preserveSelectionOnMove||i.settings.moveOnSelect?"moved"!==i.settings.preserveSelectionOnMove||i.settings.moveOnSelect||v(i,2):(v(i,1),v(i,2)),i.elements.select2.find("option:selected").each(function(e,t){var n=a(t);n.data("filtered2")||r(i,n.data("original-index"),!1)}),m(i),t(i),u(i.elements.select1,i),i.settings.sortByInputOrder&&f(i.elements.select2)}function b(n){n.elements.form.submit(function(e){n.elements.filterInput1.is(":focus")?(e.preventDefault(),n.elements.filterInput1.focusout()):n.elements.filterInput2.is(":focus")&&(e.preventDefault(),n.elements.filterInput2.focusout())}),n.element.on("bootstrapDualListbox.refresh",function(e,t){n.refresh(t)}),n.elements.filterClear1.on("click",function(){n.setNonSelectedFilter("",!0)}),n.elements.filterClear2.on("click",function(){n.setSelectedFilter("",!0)}),!1===n.settings.eventMoveOverride&&n.elements.moveButton.on("click",function(){p(n)}),!1===n.settings.eventMoveAllOverride&&n.elements.moveAllButton.on("click",function(){var i;"all"!==(i=n).settings.preserveSelectionOnMove||i.settings.moveOnSelect?"moved"!==i.settings.preserveSelectionOnMove||i.settings.moveOnSelect||v(i,1):(v(i,1),v(i,2)),i.element.find("option").each(function(e,t){var n=a(t);n.data("filtered1")||(n.prop("selected",!0),n.attr("data-sortindex",i.sortIndex),i.sortIndex++)}),m(i),t(i)}),!1===n.settings.eventRemoveOverride&&n.elements.removeButton.on("click",function(){g(n)}),!1===n.settings.eventRemoveAllOverride&&n.elements.removeAllButton.on("click",function(){var e;"all"!==(e=n).settings.preserveSelectionOnMove||e.settings.moveOnSelect?"moved"!==e.settings.preserveSelectionOnMove||e.settings.moveOnSelect||v(e,2):(v(e,1),v(e,2)),e.element.find("option").each(function(e,t){var n=a(t);n.data("filtered2")||(n.prop("selected",!1),n.removeAttr("data-sortindex"))}),m(e),t(e)}),n.elements.filterInput1.on("change keyup",function(){d(n,1)}),n.elements.filterInput2.on("change keyup",function(){d(n,2)})}l.prototype={init:function(){this.container=a('<div class="bootstrap-duallistbox-container"> <div class="box1">   <label></label>   <span class="info-container">     <span class="info"></span>     <button type="button" class="btn clear1 pull-right"></button>   </span>   <input class="filter" type="text">   <div class="btn-group buttons">     <button type="button" class="btn moveall">       <i></i>       <i></i>     </button>     <button type="button" class="btn move">       <i></i>     </button>   </div>   <select multiple="multiple"></select> </div> <div class="box2">   <label></label>   <span class="info-container">     <span class="info"></span>     <button type="button" class="btn clear2 pull-right"></button>   </span>   <input class="filter" type="text">   <div class="btn-group buttons">     <button type="button" class="btn remove">       <i></i>     </button>     <button type="button" class="btn removeall">       <i></i>       <i></i>     </button>   </div>   <select multiple="multiple"></select> </div></div>').insertBefore(this.element),this.elements={originalSelect:this.element,box1:a(".box1",this.container),box2:a(".box2",this.container),filterInput1:a(".box1 .filter",this.container),filterInput2:a(".box2 .filter",this.container),filterClear1:a(".box1 .clear1",this.container),filterClear2:a(".box2 .clear2",this.container),label1:a(".box1 > label",this.container),label2:a(".box2 > label",this.container),info1:a(".box1 .info",this.container),info2:a(".box2 .info",this.container),select1:a(".box1 select",this.container),select2:a(".box2 select",this.container),moveButton:a(".box1 .move",this.container),removeButton:a(".box2 .remove",this.container),moveAllButton:a(".box1 .moveall",this.container),removeAllButton:a(".box2 .removeall",this.container),form:a(a(".box1 .filter",this.container)[0].form)},this.originalSelectName=this.element.attr("name")||"";var e="bootstrap-duallistbox-nonselected-list_"+this.originalSelectName,t="bootstrap-duallistbox-selected-list_"+this.originalSelectName;return this.elements.select1.attr("id",e),this.elements.select2.attr("id",t),this.elements.label1.attr("for",e),this.elements.label2.attr("for",t),this.selectedElements=0,this.sortIndex=0,this.elementCount=0,this.setBootstrap2Compatible(this.settings.bootstrap2Compatible),this.setFilterTextClear(this.settings.filterTextClear),this.setFilterPlaceHolder(this.settings.filterPlaceHolder),this.setMoveSelectedLabel(this.settings.moveSelectedLabel),this.setMoveAllLabel(this.settings.moveAllLabel),this.setRemoveSelectedLabel(this.settings.removeSelectedLabel),this.setRemoveAllLabel(this.settings.removeAllLabel),this.setMoveOnSelect(this.settings.moveOnSelect),this.setMoveOnDoubleClick(this.settings.moveOnDoubleClick),this.setPreserveSelectionOnMove(this.settings.preserveSelectionOnMove),this.setSelectedListLabel(this.settings.selectedListLabel),this.setNonSelectedListLabel(this.settings.nonSelectedListLabel),this.setHelperSelectNamePostfix(this.settings.helperSelectNamePostfix),this.setSelectOrMinimalHeight(this.settings.selectorMinimalHeight),o(this),this.setShowFilterInputs(this.settings.showFilterInputs),this.setNonSelectedFilter(this.settings.nonSelectedFilter),this.setSelectedFilter(this.settings.selectedFilter),this.setInfoText(this.settings.infoText),this.setInfoTextFiltered(this.settings.infoTextFiltered),this.setInfoTextEmpty(this.settings.infoTextEmpty),this.setFilterOnValues(this.settings.filterOnValues),this.setSortByInputOrder(this.settings.sortByInputOrder),this.setEventMoveOverride(this.settings.eventMoveOverride),this.setEventMoveAllOverride(this.settings.eventMoveAllOverride),this.setEventRemoveOverride(this.settings.eventRemoveOverride),this.setEventRemoveAllOverride(this.settings.eventRemoveAllOverride),this.element.hide(),b(this),m(this),this.element},setBootstrap2Compatible:function(e,t){return(this.settings.bootstrap2Compatible=e)?(this.container.removeClass("row").addClass("row-fluid bs2compatible"),this.container.find(".box1, .box2").removeClass("col-md-6").addClass("span6"),this.container.find(".clear1, .clear2").removeClass("btn-default btn-xs").addClass("btn-mini"),this.container.find("input, select").removeClass("form-control"),this.container.find(".btn").removeClass("btn-default"),this.container.find(".moveall > i, .move > i").removeClass("glyphicon glyphicon-arrow-right").addClass("icon-arrow-right"),this.container.find(".removeall > i, .remove > i").removeClass("glyphicon glyphicon-arrow-left").addClass("icon-arrow-left")):(this.container.removeClass("row-fluid bs2compatible").addClass("row"),this.container.find(".box1, .box2").removeClass("span6").addClass("col-md-6"),this.container.find(".clear1, .clear2").removeClass("btn-mini").addClass("btn-default btn-xs"),this.container.find("input, select").addClass("form-control"),this.container.find(".btn").addClass("btn-default"),this.container.find(".moveall > i, .move > i").removeClass("icon-arrow-right").addClass("glyphicon glyphicon-arrow-right"),this.container.find(".removeall > i, .remove > i").removeClass("icon-arrow-left").addClass("glyphicon glyphicon-arrow-left")),t&&m(this),this.element},setFilterTextClear:function(e,t){return this.settings.filterTextClear=e,this.elements.filterClear1.html(e),this.elements.filterClear2.html(e),t&&m(this),this.element},setFilterPlaceHolder:function(e,t){return this.settings.filterPlaceHolder=e,this.elements.filterInput1.attr("placeholder",e),this.elements.filterInput2.attr("placeholder",e),t&&m(this),this.element},setMoveSelectedLabel:function(e,t){return this.settings.moveSelectedLabel=e,this.elements.moveButton.attr("title",e),t&&m(this),this.element},setMoveAllLabel:function(e,t){return this.settings.moveAllLabel=e,this.elements.moveAllButton.attr("title",e),t&&m(this),this.element},setRemoveSelectedLabel:function(e,t){return this.settings.removeSelectedLabel=e,this.elements.removeButton.attr("title",e),t&&m(this),this.element},setRemoveAllLabel:function(e,t){return this.settings.removeAllLabel=e,this.elements.removeAllButton.attr("title",e),t&&m(this),this.element},setMoveOnSelect:function(e,t){if(i&&(e=!0),this.settings.moveOnSelect=e,this.settings.moveOnSelect){this.container.addClass("moveonselect");var n=this;this.elements.select1.on("change",function(){p(n)}),this.elements.select2.on("change",function(){g(n)})}else this.container.removeClass("moveonselect"),this.elements.select1.off("change"),this.elements.select2.off("change");return t&&m(this),this.element},setMoveOnDoubleClick:function(e,t){if(i&&(e=!1),this.settings.moveOnDoubleClick=e,this.settings.moveOnDoubleClick){this.container.addClass("moveondoubleclick");var n=this;this.elements.select1.on("dblclick",function(){p(n)}),this.elements.select2.on("dblclick",function(){g(n)})}else this.container.removeClass("moveondoubleclick"),this.elements.select1.off("dblclick"),this.elements.select2.off("dblclick");return t&&m(this),this.element},setPreserveSelectionOnMove:function(e,t){return i&&(e=!1),this.settings.preserveSelectionOnMove=e,t&&m(this),this.element},setSelectedListLabel:function(e,t){return(this.settings.selectedListLabel=e)?this.elements.label2.show().html(e):this.elements.label2.hide().html(e),t&&m(this),this.element},setNonSelectedListLabel:function(e,t){return(this.settings.nonSelectedListLabel=e)?this.elements.label1.show().html(e):this.elements.label1.hide().html(e),t&&m(this),this.element},setHelperSelectNamePostfix:function(e,t){return(this.settings.helperSelectNamePostfix=e)?(this.elements.select1.attr("name",this.originalSelectName+e+"1"),this.elements.select2.attr("name",this.originalSelectName+e+"2")):(this.elements.select1.removeAttr("name"),this.elements.select2.removeAttr("name")),t&&m(this),this.element},setSelectOrMinimalHeight:function(e,t){this.settings.selectorMinimalHeight=e;var n=this.element.height();return this.element.height()<e&&(n=e),this.elements.select1.height(n),this.elements.select2.height(n),t&&m(this),this.element},setShowFilterInputs:function(e,t){return e?(this.elements.filterInput1.show(),this.elements.filterInput2.show()):(this.setNonSelectedFilter(""),this.setSelectedFilter(""),m(this),this.elements.filterInput1.hide(),this.elements.filterInput2.hide()),this.settings.showFilterInputs=e,t&&m(this),this.element},setNonSelectedFilter:function(e,t){if(this.settings.showFilterInputs)return this.settings.nonSelectedFilter=e,this.elements.filterInput1.val(e),t&&m(this),this.element},setSelectedFilter:function(e,t){if(this.settings.showFilterInputs)return this.settings.selectedFilter=e,this.elements.filterInput2.val(e),t&&m(this),this.element},setInfoText:function(e,t){return(this.settings.infoText=e)?(this.elements.info1.show(),this.elements.info2.show()):(this.elements.info1.hide(),this.elements.info2.hide()),t&&m(this),this.element},setInfoTextFiltered:function(e,t){return this.settings.infoTextFiltered=e,t&&m(this),this.element},setInfoTextEmpty:function(e,t){return this.settings.infoTextEmpty=e,t&&m(this),this.element},setFilterOnValues:function(e,t){return this.settings.filterOnValues=e,t&&m(this),this.element},setSortByInputOrder:function(e,t){return this.settings.sortByInputOrder=e,t&&m(this),this.element},setEventMoveOverride:function(e,t){return this.settings.eventMoveOverride=e,t&&m(this),this.element},setEventMoveAllOverride:function(e,t){return this.settings.eventMoveAllOverride=e,t&&m(this),this.element},setEventRemoveOverride:function(e,t){return this.settings.eventRemoveOverride=e,t&&m(this),this.element},setEventRemoveAllOverride:function(e,t){return this.settings.eventRemoveAllOverride=e,t&&m(this),this.element},getContainer:function(){return this.container},refresh:function(e){var t;o(this),e?(t=this).elements.select1.find("option").each(function(){t.element.find("option").data("_selected",!1)}):(v(this,1),v(this,2)),m(this)},destroy:function(){return this.container.remove(),this.element.show(),a.data(this,"plugin_"+s,null),this.element}},a.fn[s]=function(n){var t,i=arguments;return n===e||"object"==typeof n?this.each(function(){a(this).is("select")?a.data(this,"plugin_"+s)||a.data(this,"plugin_"+s,new l(this,n)):a(this).find("select").each(function(e,t){a(t).bootstrapDualListbox(n)})}):"string"==typeof n&&"_"!==n[0]&&"init"!==n?(this.each(function(){var e=a.data(this,"plugin_"+s);e instanceof l&&"function"==typeof e[n]&&(t=e[n].apply(e,Array.prototype.slice.call(i,1)))}),t!==e?t:this):void 0}}(jQuery,(window,void document));
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/flot/curvedLines.js b/ruoyi-admin/src/main/resources/static/ajax/libs/flot/curvedLines.js
new file mode 100644
index 0000000..12c1ad6
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/flot/curvedLines.js
@@ -0,0 +1,315 @@
+/* The MIT License
+
+ Copyright (c) 2011 by Michael Zinsmaier and nergal.dev
+ Copyright (c) 2012 by Thomas Ritou
+
+ 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.
+ */
+
+/*
+
+ ____________________________________________________
+
+ what it is:
+ ____________________________________________________
+
+ curvedLines is a plugin for flot, that tries to display lines in a smoother way.
+ The plugin is based on nergal.dev's work https://code.google.com/p/flot/issues/detail?id=226
+ and further extended with a mode that forces the min/max points of the curves to be on the
+ points. Both modes are achieved through adding of more data points
+ => 1) with large data sets you may get trouble
+ => 2) if you want to display the points too, you have to plot them as 2nd data series over the lines
+
+ && 3) consecutive x data points are not allowed to have the same value
+
+ This is version 0.5 of curvedLines so it will probably not work in every case. However
+ the basic form of use descirbed next works (:
+
+ Feel free to further improve the code
+
+ ____________________________________________________
+
+ how to use it:
+ ____________________________________________________
+
+ var d1 = [[5,5],[7,3],[9,12]];
+
+ var options = { series: { curvedLines: {  active: true }}};
+
+ $.plot($("#placeholder"), [{data = d1, lines: { show: true}, curvedLines: {apply: true}}], options);
+
+ _____________________________________________________
+
+ options:
+ _____________________________________________________
+
+ active:           bool true => plugin can be used
+ apply:            bool true => series will be drawn as curved line
+ fit:              bool true => forces the max,mins of the curve to be on the datapoints
+ curvePointFactor  int  defines how many "virtual" points are used per "real" data point to
+ emulate the curvedLines (points total = real points * curvePointFactor)
+ fitPointDist:     int  defines the x axis distance of the additional two points that are used
+ to enforce the min max condition.
+
+ + line options (since v0.5 curved lines use flots line implementation for drawing
+ => line options like fill, show ... are supported out of the box)
+
+ */
+
+/*
+ *  v0.1   initial commit
+ *  v0.15  negative values should work now (outcommented a negative -> 0 hook hope it does no harm)
+ *  v0.2   added fill option (thanks to monemihir) and multi axis support (thanks to soewono effendi)
+ *  v0.3   improved saddle handling and added basic handling of Dates
+ *  v0.4   rewritten fill option (thomas ritou) mostly from original flot code (now fill between points rather than to graph bottom), corrected fill Opacity bug
+ *  v0.5   rewritten instead of implementing a own draw function CurvedLines is now based on the processDatapoints flot hook (credits go to thomas ritou).
+ * 		   This change breakes existing code however CurvedLines are now just many tiny straight lines to flot and therefore all flot lines options (like gradient fill,
+ * 	       shadow) are now supported out of the box
+ *  v0.6   flot 0.8 compatibility and some bug fixes
+ */
+
+(function($) {
+
+    var options = {
+        series : {
+            curvedLines : {
+                active : false,
+                apply: false,
+                fit : false,
+                curvePointFactor : 20,
+                fitPointDist : undefined
+            }
+        }
+    };
+
+    function init(plot) {
+
+        plot.hooks.processOptions.push(processOptions);
+
+        //if the plugin is active register processDatapoints method
+        function processOptions(plot, options) {
+            if (options.series.curvedLines.active) {
+                plot.hooks.processDatapoints.unshift(processDatapoints);
+            }
+        }
+
+        //only if the plugin is active
+        function processDatapoints(plot, series, datapoints) {
+            var nrPoints = datapoints.points.length / datapoints.pointsize;
+            var EPSILON = 0.5; //pretty large epsilon but save
+
+            if (series.curvedLines.apply == true && series.originSeries === undefined && nrPoints > (1 + EPSILON)) {
+                if (series.lines.fill) {
+
+                    var pointsTop = calculateCurvePoints(datapoints, series.curvedLines, 1)
+                        ,pointsBottom = calculateCurvePoints(datapoints, series.curvedLines, 2); //flot makes sure for us that we've got a second y point if fill is true !
+
+                    //Merge top and bottom curve
+                    datapoints.pointsize = 3;
+                    datapoints.points = [];
+                    var j = 0;
+                    var k = 0;
+                    var i = 0;
+                    var ps = 2;
+                    while (i < pointsTop.length || j < pointsBottom.length) {
+                        if (pointsTop[i] == pointsBottom[j]) {
+                            datapoints.points[k] = pointsTop[i];
+                            datapoints.points[k + 1] = pointsTop[i + 1];
+                            datapoints.points[k + 2] = pointsBottom[j + 1];
+                            j += ps;
+                            i += ps;
+
+                        } else if (pointsTop[i] < pointsBottom[j]) {
+                            datapoints.points[k] = pointsTop[i];
+                            datapoints.points[k + 1] = pointsTop[i + 1];
+                            datapoints.points[k + 2] = k > 0 ? datapoints.points[k-1] : null;
+                            i += ps;
+                        } else {
+                            datapoints.points[k] = pointsBottom[j];
+                            datapoints.points[k + 1] = k > 1 ? datapoints.points[k-2] : null;
+                            datapoints.points[k + 2] = pointsBottom[j + 1];
+                            j += ps;
+                        }
+                        k += 3;
+                    }
+                } else if (series.lines.lineWidth > 0) {
+                    datapoints.points = calculateCurvePoints(datapoints, series.curvedLines, 1);
+                    datapoints.pointsize = 2;
+                }
+            }
+        }
+
+        //no real idea whats going on here code mainly from https://code.google.com/p/flot/issues/detail?id=226
+        //if fit option is selected additional datapoints get inserted before the curve calculations in nergal.dev s code.
+        function calculateCurvePoints(datapoints, curvedLinesOptions, yPos) {
+
+            var points = datapoints.points, ps = datapoints.pointsize;
+            var num = curvedLinesOptions.curvePointFactor * (points.length / ps);
+
+            var xdata = new Array;
+            var ydata = new Array;
+
+            var curX = -1;
+            var curY = -1;
+            var j = 0;
+
+            if (curvedLinesOptions.fit) {
+                //insert a point before and after the "real" data point to force the line
+                //to have a max,min at the data point.
+
+                var fpDist;
+                if(typeof curvedLinesOptions.fitPointDist == 'undefined') {
+                    //estimate it
+                    var minX = points[0];
+                    var maxX = points[points.length-ps];
+                    fpDist = (maxX - minX) / (500 * 100); //x range / (estimated pixel length of placeholder * factor)
+                } else {
+                    //use user defined value
+                    fpDist = curvedLinesOptions.fitPointDist;
+                }
+
+                for (var i = 0; i < points.length; i += ps) {
+
+                    var frontX;
+                    var backX;
+                    curX = i;
+                    curY = i + yPos;
+
+                    //add point X s
+                    frontX = points[curX] - fpDist;
+                    backX = points[curX] + fpDist;
+
+                    var factor = 2;
+                    while (frontX == points[curX] || backX == points[curX]) {
+                        //inside the ulp
+                        frontX = points[curX] - (fpDist * factor);
+                        backX = points[curX] + (fpDist * factor);
+                        factor++;
+                    }
+
+                    //add curve points
+                    xdata[j] = frontX;
+                    ydata[j] = points[curY];
+                    j++;
+
+                    xdata[j] = points[curX];
+                    ydata[j] = points[curY];
+                    j++;
+
+                    xdata[j] = backX;
+                    ydata[j] = points[curY];
+                    j++;
+                }
+            } else {
+                //just use the datapoints
+                for (var i = 0; i < points.length; i += ps) {
+                    curX = i;
+                    curY = i + yPos;
+
+                    xdata[j] = points[curX];
+                    ydata[j] = points[curY];
+                    j++;
+                }
+            }
+
+            var n = xdata.length;
+
+            var y2 = new Array();
+            var delta = new Array();
+            y2[0] = 0;
+            y2[n - 1] = 0;
+            delta[0] = 0;
+
+            for (var i = 1; i < n - 1; ++i) {
+                var d = (xdata[i + 1] - xdata[i - 1]);
+                if (d == 0) {
+                    //point before current point and after current point need some space in between
+                    return [];
+                }
+
+                var s = (xdata[i] - xdata[i - 1]) / d;
+                var p = s * y2[i - 1] + 2;
+                y2[i] = (s - 1) / p;
+                delta[i] = (ydata[i + 1] - ydata[i]) / (xdata[i + 1] - xdata[i]) - (ydata[i] - ydata[i - 1]) / (xdata[i] - xdata[i - 1]);
+                delta[i] = (6 * delta[i] / (xdata[i + 1] - xdata[i - 1]) - s * delta[i - 1]) / p;
+            }
+
+            for (var j = n - 2; j >= 0; --j) {
+                y2[j] = y2[j] * y2[j + 1] + delta[j];
+            }
+
+            //   xmax  - xmin  / #points
+            var step = (xdata[n - 1] - xdata[0]) / (num - 1);
+
+            var xnew = new Array;
+            var ynew = new Array;
+            var result = new Array;
+
+            xnew[0] = xdata[0];
+            ynew[0] = ydata[0];
+
+            result.push(xnew[0]);
+            result.push(ynew[0]);
+
+            for ( j = 1; j < num; ++j) {
+                //new x point (sampling point for the created curve)
+                xnew[j] = xnew[0] + j * step;
+
+                var max = n - 1;
+                var min = 0;
+
+                while (max - min > 1) {
+                    var k = Math.round((max + min) / 2);
+                    if (xdata[k] > xnew[j]) {
+                        max = k;
+                    } else {
+                        min = k;
+                    }
+                }
+
+                //found point one to the left and one to the right of generated new point
+                var h = (xdata[max] - xdata[min]);
+
+                if (h == 0) {
+                    //similar to above two points from original x data need some space between them
+                    return [];
+                }
+
+                var a = (xdata[max] - xnew[j]) / h;
+                var b = (xnew[j] - xdata[min]) / h;
+
+                ynew[j] = a * ydata[min] + b * ydata[max] + ((a * a * a - a) * y2[min] + (b * b * b - b) * y2[max]) * (h * h) / 6;
+
+                result.push(xnew[j]);
+                result.push(ynew[j]);
+            }
+
+            return result;
+        }
+
+    }//end init
+
+    $.plot.plugins.push({
+        init : init,
+        options : options,
+        name : 'curvedLines',
+        version : '0.5'
+    });
+
+})(jQuery);
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/flot/jquery.flot.js b/ruoyi-admin/src/main/resources/static/ajax/libs/flot/jquery.flot.js
new file mode 100644
index 0000000..e02ba64
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/flot/jquery.flot.js
@@ -0,0 +1,2599 @@
+/*! Javascript plotting library for jQuery, v. 0.7.
+ *
+ * Released under the MIT license by IOLA, December 2007.
+ *
+ */
+
+// first an inline dependency, jquery.colorhelpers.js, we inline it here
+// for convenience
+
+/* Plugin for jQuery for working with colors.
+ *
+ * Version 1.1.
+ *
+ * Inspiration from jQuery color animation plugin by John Resig.
+ *
+ * Released under the MIT license by Ole Laursen, October 2009.
+ *
+ * Examples:
+ *
+ *   $.color.parse("#fff").scale('rgb', 0.25).add('a', -0.5).toString()
+ *   var c = $.color.extract($("#mydiv"), 'background-color');
+ *   console.log(c.r, c.g, c.b, c.a);
+ *   $.color.make(100, 50, 25, 0.4).toString() // returns "rgba(100,50,25,0.4)"
+ *
+ * Note that .scale() and .add() return the same modified object
+ * instead of making a new one.
+ *
+ * V. 1.1: Fix error handling so e.g. parsing an empty string does
+ * produce a color rather than just crashing.
+ */
+(function(B){B.color={};B.color.make=function(F,E,C,D){var G={};G.r=F||0;G.g=E||0;G.b=C||0;G.a=D!=null?D:1;G.add=function(J,I){for(var H=0;H<J.length;++H){G[J.charAt(H)]+=I}return G.normalize()};G.scale=function(J,I){for(var H=0;H<J.length;++H){G[J.charAt(H)]*=I}return G.normalize()};G.toString=function(){if(G.a>=1){return"rgb("+[G.r,G.g,G.b].join(",")+")"}else{return"rgba("+[G.r,G.g,G.b,G.a].join(",")+")"}};G.normalize=function(){function H(J,K,I){return K<J?J:(K>I?I:K)}G.r=H(0,parseInt(G.r),255);G.g=H(0,parseInt(G.g),255);G.b=H(0,parseInt(G.b),255);G.a=H(0,G.a,1);return G};G.clone=function(){return B.color.make(G.r,G.b,G.g,G.a)};return G.normalize()};B.color.extract=function(D,C){var E;do{E=D.css(C).toLowerCase();if(E!=""&&E!="transparent"){break}D=D.parent()}while(!B.nodeName(D.get(0),"body"));if(E=="rgba(0, 0, 0, 0)"){E="transparent"}return B.color.parse(E)};B.color.parse=function(F){var E,C=B.color.make;if(E=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(F)){return C(parseInt(E[1],10),parseInt(E[2],10),parseInt(E[3],10))}if(E=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(F)){return C(parseInt(E[1],10),parseInt(E[2],10),parseInt(E[3],10),parseFloat(E[4]))}if(E=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(F)){return C(parseFloat(E[1])*2.55,parseFloat(E[2])*2.55,parseFloat(E[3])*2.55)}if(E=/rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(F)){return C(parseFloat(E[1])*2.55,parseFloat(E[2])*2.55,parseFloat(E[3])*2.55,parseFloat(E[4]))}if(E=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(F)){return C(parseInt(E[1],16),parseInt(E[2],16),parseInt(E[3],16))}if(E=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(F)){return C(parseInt(E[1]+E[1],16),parseInt(E[2]+E[2],16),parseInt(E[3]+E[3],16))}var D=B.trim(F).toLowerCase();if(D=="transparent"){return C(255,255,255,0)}else{E=A[D]||[0,0,0];return C(E[0],E[1],E[2])}};var A={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]}})(jQuery);
+
+// the actual Flot code
+(function($) {
+    function Plot(placeholder, data_, options_, plugins) {
+        // data is on the form:
+        //   [ series1, series2 ... ]
+        // where series is either just the data as [ [x1, y1], [x2, y2], ... ]
+        // or { data: [ [x1, y1], [x2, y2], ... ], label: "some label", ... }
+
+        var series = [],
+            options = {
+                // the color theme used for graphs
+                colors: ["#edc240", "#afd8f8", "#cb4b4b", "#4da74d", "#9440ed"],
+                legend: {
+                    show: true,
+                    noColumns: 1, // number of colums in legend table
+                    labelFormatter: null, // fn: string -> string
+                    labelBoxBorderColor: "#ccc", // border color for the little label boxes
+                    container: null, // container (as jQuery object) to put legend in, null means default on top of graph
+                    position: "ne", // position of default legend container within plot
+                    margin: 5, // distance from grid edge to default legend container within plot
+                    backgroundColor: null, // null means auto-detect
+                    backgroundOpacity: 0.85 // set to 0 to avoid background
+                },
+                xaxis: {
+                    show: null, // null = auto-detect, true = always, false = never
+                    position: "bottom", // or "top"
+                    mode: null, // null or "time"
+                    color: null, // base color, labels, ticks
+                    tickColor: null, // possibly different color of ticks, e.g. "rgba(0,0,0,0.15)"
+                    transform: null, // null or f: number -> number to transform axis
+                    inverseTransform: null, // if transform is set, this should be the inverse function
+                    min: null, // min. value to show, null means set automatically
+                    max: null, // max. value to show, null means set automatically
+                    autoscaleMargin: null, // margin in % to add if auto-setting min/max
+                    ticks: null, // either [1, 3] or [[1, "a"], 3] or (fn: axis info -> ticks) or app. number of ticks for auto-ticks
+                    tickFormatter: null, // fn: number -> string
+                    labelWidth: null, // size of tick labels in pixels
+                    labelHeight: null,
+                    reserveSpace: null, // whether to reserve space even if axis isn't shown
+                    tickLength: null, // size in pixels of ticks, or "full" for whole line
+                    alignTicksWithAxis: null, // axis number or null for no sync
+
+                    // mode specific options
+                    tickDecimals: null, // no. of decimals, null means auto
+                    tickSize: null, // number or [number, "unit"]
+                    minTickSize: null, // number or [number, "unit"]
+                    monthNames: null, // list of names of months
+                    timeformat: null, // format string to use
+                    twelveHourClock: false // 12 or 24 time in time mode
+                },
+                yaxis: {
+                    autoscaleMargin: 0.02,
+                    position: "left" // or "right"
+                },
+                xaxes: [],
+                yaxes: [],
+                series: {
+                    points: {
+                        show: false,
+                        radius: 3,
+                        lineWidth: 2, // in pixels
+                        fill: true,
+                        fillColor: "#ffffff",
+                        symbol: "circle" // or callback
+                    },
+                    lines: {
+                        // we don't put in show: false so we can see
+                        // whether lines were actively disabled
+                        lineWidth: 2, // in pixels
+                        fill: false,
+                        fillColor: null,
+                        steps: false
+                    },
+                    bars: {
+                        show: false,
+                        lineWidth: 2, // in pixels
+                        barWidth: 1, // in units of the x axis
+                        fill: true,
+                        fillColor: null,
+                        align: "left", // or "center"
+                        horizontal: false
+                    },
+                    shadowSize: 3
+                },
+                grid: {
+                    show: true,
+                    aboveData: false,
+                    color: "#545454", // primary color used for outline and labels
+                    backgroundColor: null, // null for transparent, else color
+                    borderColor: null, // set if different from the grid color
+                    tickColor: null, // color for the ticks, e.g. "rgba(0,0,0,0.15)"
+                    labelMargin: 5, // in pixels
+                    axisMargin: 8, // in pixels
+                    borderWidth: 2, // in pixels
+                    minBorderMargin: null, // in pixels, null means taken from points radius
+                    markings: null, // array of ranges or fn: axes -> array of ranges
+                    markingsColor: "#f4f4f4",
+                    markingsLineWidth: 2,
+                    // interactive stuff
+                    clickable: false,
+                    hoverable: false,
+                    autoHighlight: true, // highlight in case mouse is near
+                    mouseActiveRadius: 10 // how far the mouse can be away to activate an item
+                },
+                hooks: {}
+            },
+        canvas = null,      // the canvas for the plot itself
+        overlay = null,     // canvas for interactive stuff on top of plot
+        eventHolder = null, // jQuery object that events should be bound to
+        ctx = null, octx = null,
+        xaxes = [], yaxes = [],
+        plotOffset = { left: 0, right: 0, top: 0, bottom: 0},
+        canvasWidth = 0, canvasHeight = 0,
+        plotWidth = 0, plotHeight = 0,
+        hooks = {
+            processOptions: [],
+            processRawData: [],
+            processDatapoints: [],
+            drawSeries: [],
+            draw: [],
+            bindEvents: [],
+            drawOverlay: [],
+            shutdown: []
+        },
+        plot = this;
+
+        // public functions
+        plot.setData = setData;
+        plot.setupGrid = setupGrid;
+        plot.draw = draw;
+        plot.getPlaceholder = function() { return placeholder; };
+        plot.getCanvas = function() { return canvas; };
+        plot.getPlotOffset = function() { return plotOffset; };
+        plot.width = function () { return plotWidth; };
+        plot.height = function () { return plotHeight; };
+        plot.offset = function () {
+            var o = eventHolder.offset();
+            o.left += plotOffset.left;
+            o.top += plotOffset.top;
+            return o;
+        };
+        plot.getData = function () { return series; };
+        plot.getAxes = function () {
+            var res = {}, i;
+            $.each(xaxes.concat(yaxes), function (_, axis) {
+                if (axis)
+                    res[axis.direction + (axis.n != 1 ? axis.n : "") + "axis"] = axis;
+            });
+            return res;
+        };
+        plot.getXAxes = function () { return xaxes; };
+        plot.getYAxes = function () { return yaxes; };
+        plot.c2p = canvasToAxisCoords;
+        plot.p2c = axisToCanvasCoords;
+        plot.getOptions = function () { return options; };
+        plot.highlight = highlight;
+        plot.unhighlight = unhighlight;
+        plot.triggerRedrawOverlay = triggerRedrawOverlay;
+        plot.pointOffset = function(point) {
+            return {
+                left: parseInt(xaxes[axisNumber(point, "x") - 1].p2c(+point.x) + plotOffset.left),
+                top: parseInt(yaxes[axisNumber(point, "y") - 1].p2c(+point.y) + plotOffset.top)
+            };
+        };
+        plot.shutdown = shutdown;
+        plot.resize = function () {
+            getCanvasDimensions();
+            resizeCanvas(canvas);
+            resizeCanvas(overlay);
+        };
+
+        // public attributes
+        plot.hooks = hooks;
+
+        // initialize
+        initPlugins(plot);
+        parseOptions(options_);
+        setupCanvases();
+        setData(data_);
+        setupGrid();
+        draw();
+        bindEvents();
+
+
+        function executeHooks(hook, args) {
+            args = [plot].concat(args);
+            for (var i = 0; i < hook.length; ++i)
+                hook[i].apply(this, args);
+        }
+
+        function initPlugins() {
+            for (var i = 0; i < plugins.length; ++i) {
+                var p = plugins[i];
+                p.init(plot);
+                if (p.options)
+                    $.extend(true, options, p.options);
+            }
+        }
+
+        function parseOptions(opts) {
+            var i;
+
+            $.extend(true, options, opts);
+
+            if (options.xaxis.color == null)
+                options.xaxis.color = options.grid.color;
+            if (options.yaxis.color == null)
+                options.yaxis.color = options.grid.color;
+
+            if (options.xaxis.tickColor == null) // backwards-compatibility
+                options.xaxis.tickColor = options.grid.tickColor;
+            if (options.yaxis.tickColor == null) // backwards-compatibility
+                options.yaxis.tickColor = options.grid.tickColor;
+
+            if (options.grid.borderColor == null)
+                options.grid.borderColor = options.grid.color;
+            if (options.grid.tickColor == null)
+                options.grid.tickColor = $.color.parse(options.grid.color).scale('a', 0.22).toString();
+
+            // fill in defaults in axes, copy at least always the
+            // first as the rest of the code assumes it'll be there
+            for (i = 0; i < Math.max(1, options.xaxes.length); ++i)
+                options.xaxes[i] = $.extend(true, {}, options.xaxis, options.xaxes[i]);
+            for (i = 0; i < Math.max(1, options.yaxes.length); ++i)
+                options.yaxes[i] = $.extend(true, {}, options.yaxis, options.yaxes[i]);
+
+            // backwards compatibility, to be removed in future
+            if (options.xaxis.noTicks && options.xaxis.ticks == null)
+                options.xaxis.ticks = options.xaxis.noTicks;
+            if (options.yaxis.noTicks && options.yaxis.ticks == null)
+                options.yaxis.ticks = options.yaxis.noTicks;
+            if (options.x2axis) {
+                options.xaxes[1] = $.extend(true, {}, options.xaxis, options.x2axis);
+                options.xaxes[1].position = "top";
+            }
+            if (options.y2axis) {
+                options.yaxes[1] = $.extend(true, {}, options.yaxis, options.y2axis);
+                options.yaxes[1].position = "right";
+            }
+            if (options.grid.coloredAreas)
+                options.grid.markings = options.grid.coloredAreas;
+            if (options.grid.coloredAreasColor)
+                options.grid.markingsColor = options.grid.coloredAreasColor;
+            if (options.lines)
+                $.extend(true, options.series.lines, options.lines);
+            if (options.points)
+                $.extend(true, options.series.points, options.points);
+            if (options.bars)
+                $.extend(true, options.series.bars, options.bars);
+            if (options.shadowSize != null)
+                options.series.shadowSize = options.shadowSize;
+
+            // save options on axes for future reference
+            for (i = 0; i < options.xaxes.length; ++i)
+                getOrCreateAxis(xaxes, i + 1).options = options.xaxes[i];
+            for (i = 0; i < options.yaxes.length; ++i)
+                getOrCreateAxis(yaxes, i + 1).options = options.yaxes[i];
+
+            // add hooks from options
+            for (var n in hooks)
+                if (options.hooks[n] && options.hooks[n].length)
+                    hooks[n] = hooks[n].concat(options.hooks[n]);
+
+            executeHooks(hooks.processOptions, [options]);
+        }
+
+        function setData(d) {
+            series = parseData(d);
+            fillInSeriesOptions();
+            processData();
+        }
+
+        function parseData(d) {
+            var res = [];
+            for (var i = 0; i < d.length; ++i) {
+                var s = $.extend(true, {}, options.series);
+
+                if (d[i].data != null) {
+                    s.data = d[i].data; // move the data instead of deep-copy
+                    delete d[i].data;
+
+                    $.extend(true, s, d[i]);
+
+                    d[i].data = s.data;
+                }
+                else
+                    s.data = d[i];
+                res.push(s);
+            }
+
+            return res;
+        }
+
+        function axisNumber(obj, coord) {
+            var a = obj[coord + "axis"];
+            if (typeof a == "object") // if we got a real axis, extract number
+                a = a.n;
+            if (typeof a != "number")
+                a = 1; // default to first axis
+            return a;
+        }
+
+        function allAxes() {
+            // return flat array without annoying null entries
+            return $.grep(xaxes.concat(yaxes), function (a) { return a; });
+        }
+
+        function canvasToAxisCoords(pos) {
+            // return an object with x/y corresponding to all used axes
+            var res = {}, i, axis;
+            for (i = 0; i < xaxes.length; ++i) {
+                axis = xaxes[i];
+                if (axis && axis.used)
+                    res["x" + axis.n] = axis.c2p(pos.left);
+            }
+
+            for (i = 0; i < yaxes.length; ++i) {
+                axis = yaxes[i];
+                if (axis && axis.used)
+                    res["y" + axis.n] = axis.c2p(pos.top);
+            }
+
+            if (res.x1 !== undefined)
+                res.x = res.x1;
+            if (res.y1 !== undefined)
+                res.y = res.y1;
+
+            return res;
+        }
+
+        function axisToCanvasCoords(pos) {
+            // get canvas coords from the first pair of x/y found in pos
+            var res = {}, i, axis, key;
+
+            for (i = 0; i < xaxes.length; ++i) {
+                axis = xaxes[i];
+                if (axis && axis.used) {
+                    key = "x" + axis.n;
+                    if (pos[key] == null && axis.n == 1)
+                        key = "x";
+
+                    if (pos[key] != null) {
+                        res.left = axis.p2c(pos[key]);
+                        break;
+                    }
+                }
+            }
+
+            for (i = 0; i < yaxes.length; ++i) {
+                axis = yaxes[i];
+                if (axis && axis.used) {
+                    key = "y" + axis.n;
+                    if (pos[key] == null && axis.n == 1)
+                        key = "y";
+
+                    if (pos[key] != null) {
+                        res.top = axis.p2c(pos[key]);
+                        break;
+                    }
+                }
+            }
+
+            return res;
+        }
+
+        function getOrCreateAxis(axes, number) {
+            if (!axes[number - 1])
+                axes[number - 1] = {
+                    n: number, // save the number for future reference
+                    direction: axes == xaxes ? "x" : "y",
+                    options: $.extend(true, {}, axes == xaxes ? options.xaxis : options.yaxis)
+                };
+
+            return axes[number - 1];
+        }
+
+        function fillInSeriesOptions() {
+            var i;
+
+            // collect what we already got of colors
+            var neededColors = series.length,
+                usedColors = [],
+                assignedColors = [];
+            for (i = 0; i < series.length; ++i) {
+                var sc = series[i].color;
+                if (sc != null) {
+                    --neededColors;
+                    if (typeof sc == "number")
+                        assignedColors.push(sc);
+                    else
+                        usedColors.push($.color.parse(series[i].color));
+                }
+            }
+
+            // we might need to generate more colors if higher indices
+            // are assigned
+            for (i = 0; i < assignedColors.length; ++i) {
+                neededColors = Math.max(neededColors, assignedColors[i] + 1);
+            }
+
+            // produce colors as needed
+            var colors = [], variation = 0;
+            i = 0;
+            while (colors.length < neededColors) {
+                var c;
+                if (options.colors.length == i) // check degenerate case
+                    c = $.color.make(100, 100, 100);
+                else
+                    c = $.color.parse(options.colors[i]);
+
+                // vary color if needed
+                var sign = variation % 2 == 1 ? -1 : 1;
+                c.scale('rgb', 1 + sign * Math.ceil(variation / 2) * 0.2)
+
+                // FIXME: if we're getting to close to something else,
+                // we should probably skip this one
+                colors.push(c);
+
+                ++i;
+                if (i >= options.colors.length) {
+                    i = 0;
+                    ++variation;
+                }
+            }
+
+            // fill in the options
+            var colori = 0, s;
+            for (i = 0; i < series.length; ++i) {
+                s = series[i];
+
+                // assign colors
+                if (s.color == null) {
+                    s.color = colors[colori].toString();
+                    ++colori;
+                }
+                else if (typeof s.color == "number")
+                    s.color = colors[s.color].toString();
+
+                // turn on lines automatically in case nothing is set
+                if (s.lines.show == null) {
+                    var v, show = true;
+                    for (v in s)
+                        if (s[v] && s[v].show) {
+                            show = false;
+                            break;
+                        }
+                    if (show)
+                        s.lines.show = true;
+                }
+
+                // setup axes
+                s.xaxis = getOrCreateAxis(xaxes, axisNumber(s, "x"));
+                s.yaxis = getOrCreateAxis(yaxes, axisNumber(s, "y"));
+            }
+        }
+
+        function processData() {
+            var topSentry = Number.POSITIVE_INFINITY,
+                bottomSentry = Number.NEGATIVE_INFINITY,
+                fakeInfinity = Number.MAX_VALUE,
+                i, j, k, m, length,
+                s, points, ps, x, y, axis, val, f, p;
+
+            function updateAxis(axis, min, max) {
+                if (min < axis.datamin && min != -fakeInfinity)
+                    axis.datamin = min;
+                if (max > axis.datamax && max != fakeInfinity)
+                    axis.datamax = max;
+            }
+
+            $.each(allAxes(), function (_, axis) {
+                // init axis
+                axis.datamin = topSentry;
+                axis.datamax = bottomSentry;
+                axis.used = false;
+            });
+
+            for (i = 0; i < series.length; ++i) {
+                s = series[i];
+                s.datapoints = { points: [] };
+
+                executeHooks(hooks.processRawData, [ s, s.data, s.datapoints ]);
+            }
+
+            // first pass: clean and copy data
+            for (i = 0; i < series.length; ++i) {
+                s = series[i];
+
+                var data = s.data, format = s.datapoints.format;
+
+                if (!format) {
+                    format = [];
+                    // find out how to copy
+                    format.push({ x: true, number: true, required: true });
+                    format.push({ y: true, number: true, required: true });
+
+                    if (s.bars.show || (s.lines.show && s.lines.fill)) {
+                        format.push({ y: true, number: true, required: false, defaultValue: 0 });
+                        if (s.bars.horizontal) {
+                            delete format[format.length - 1].y;
+                            format[format.length - 1].x = true;
+                        }
+                    }
+
+                    s.datapoints.format = format;
+                }
+
+                if (s.datapoints.pointsize != null)
+                    continue; // already filled in
+
+                s.datapoints.pointsize = format.length;
+
+                ps = s.datapoints.pointsize;
+                points = s.datapoints.points;
+
+                insertSteps = s.lines.show && s.lines.steps;
+                s.xaxis.used = s.yaxis.used = true;
+
+                for (j = k = 0; j < data.length; ++j, k += ps) {
+                    p = data[j];
+
+                    var nullify = p == null;
+                    if (!nullify) {
+                        for (m = 0; m < ps; ++m) {
+                            val = p[m];
+                            f = format[m];
+
+                            if (f) {
+                                if (f.number && val != null) {
+                                    val = +val; // convert to number
+                                    if (isNaN(val))
+                                        val = null;
+                                    else if (val == Infinity)
+                                        val = fakeInfinity;
+                                    else if (val == -Infinity)
+                                        val = -fakeInfinity;
+                                }
+
+                                if (val == null) {
+                                    if (f.required)
+                                        nullify = true;
+
+                                    if (f.defaultValue != null)
+                                        val = f.defaultValue;
+                                }
+                            }
+
+                            points[k + m] = val;
+                        }
+                    }
+
+                    if (nullify) {
+                        for (m = 0; m < ps; ++m) {
+                            val = points[k + m];
+                            if (val != null) {
+                                f = format[m];
+                                // extract min/max info
+                                if (f.x)
+                                    updateAxis(s.xaxis, val, val);
+                                if (f.y)
+                                    updateAxis(s.yaxis, val, val);
+                            }
+                            points[k + m] = null;
+                        }
+                    }
+                    else {
+                        // a little bit of line specific stuff that
+                        // perhaps shouldn't be here, but lacking
+                        // better means...
+                        if (insertSteps && k > 0
+                            && points[k - ps] != null
+                            && points[k - ps] != points[k]
+                            && points[k - ps + 1] != points[k + 1]) {
+                            // copy the point to make room for a middle point
+                            for (m = 0; m < ps; ++m)
+                                points[k + ps + m] = points[k + m];
+
+                            // middle point has same y
+                            points[k + 1] = points[k - ps + 1];
+
+                            // we've added a point, better reflect that
+                            k += ps;
+                        }
+                    }
+                }
+            }
+
+            // give the hooks a chance to run
+            for (i = 0; i < series.length; ++i) {
+                s = series[i];
+
+                executeHooks(hooks.processDatapoints, [ s, s.datapoints]);
+            }
+
+            // second pass: find datamax/datamin for auto-scaling
+            for (i = 0; i < series.length; ++i) {
+                s = series[i];
+                points = s.datapoints.points,
+                ps = s.datapoints.pointsize;
+
+                var xmin = topSentry, ymin = topSentry,
+                    xmax = bottomSentry, ymax = bottomSentry;
+
+                for (j = 0; j < points.length; j += ps) {
+                    if (points[j] == null)
+                        continue;
+
+                    for (m = 0; m < ps; ++m) {
+                        val = points[j + m];
+                        f = format[m];
+                        if (!f || val == fakeInfinity || val == -fakeInfinity)
+                            continue;
+
+                        if (f.x) {
+                            if (val < xmin)
+                                xmin = val;
+                            if (val > xmax)
+                                xmax = val;
+                        }
+                        if (f.y) {
+                            if (val < ymin)
+                                ymin = val;
+                            if (val > ymax)
+                                ymax = val;
+                        }
+                    }
+                }
+
+                if (s.bars.show) {
+                    // make sure we got room for the bar on the dancing floor
+                    var delta = s.bars.align == "left" ? 0 : -s.bars.barWidth/2;
+                    if (s.bars.horizontal) {
+                        ymin += delta;
+                        ymax += delta + s.bars.barWidth;
+                    }
+                    else {
+                        xmin += delta;
+                        xmax += delta + s.bars.barWidth;
+                    }
+                }
+
+                updateAxis(s.xaxis, xmin, xmax);
+                updateAxis(s.yaxis, ymin, ymax);
+            }
+
+            $.each(allAxes(), function (_, axis) {
+                if (axis.datamin == topSentry)
+                    axis.datamin = null;
+                if (axis.datamax == bottomSentry)
+                    axis.datamax = null;
+            });
+        }
+
+        function makeCanvas(skipPositioning, cls) {
+            var c = document.createElement('canvas');
+            c.className = cls;
+            c.width = canvasWidth;
+            c.height = canvasHeight;
+
+            if (!skipPositioning)
+                $(c).css({ position: 'absolute', left: 0, top: 0 });
+
+            $(c).appendTo(placeholder);
+
+            if (!c.getContext) // excanvas hack
+                c = window.G_vmlCanvasManager.initElement(c);
+
+            // used for resetting in case we get replotted
+            c.getContext("2d").save();
+
+            return c;
+        }
+
+        function getCanvasDimensions() {
+            canvasWidth = placeholder.width();
+            canvasHeight = placeholder.height();
+
+            if (canvasWidth <= 0 || canvasHeight <= 0)
+                throw "Invalid dimensions for plot, width = " + canvasWidth + ", height = " + canvasHeight;
+        }
+
+        function resizeCanvas(c) {
+            // resizing should reset the state (excanvas seems to be
+            // buggy though)
+            if (c.width != canvasWidth)
+                c.width = canvasWidth;
+
+            if (c.height != canvasHeight)
+                c.height = canvasHeight;
+
+            // so try to get back to the initial state (even if it's
+            // gone now, this should be safe according to the spec)
+            var cctx = c.getContext("2d");
+            cctx.restore();
+
+            // and save again
+            cctx.save();
+        }
+
+        function setupCanvases() {
+            var reused,
+                existingCanvas = placeholder.children("canvas.base"),
+                existingOverlay = placeholder.children("canvas.overlay");
+
+            if (existingCanvas.length == 0 || existingOverlay == 0) {
+                // init everything
+
+                placeholder.html(""); // make sure placeholder is clear
+
+                placeholder.css({ padding: 0 }); // padding messes up the positioning
+
+                if (placeholder.css("position") == 'static')
+                    placeholder.css("position", "relative"); // for positioning labels and overlay
+
+                getCanvasDimensions();
+
+                canvas = makeCanvas(true, "base");
+                overlay = makeCanvas(false, "overlay"); // overlay canvas for interactive features
+
+                reused = false;
+            }
+            else {
+                // reuse existing elements
+
+                canvas = existingCanvas.get(0);
+                overlay = existingOverlay.get(0);
+
+                reused = true;
+            }
+
+            ctx = canvas.getContext("2d");
+            octx = overlay.getContext("2d");
+
+            // we include the canvas in the event holder too, because IE 7
+            // sometimes has trouble with the stacking order
+            eventHolder = $([overlay, canvas]);
+
+            if (reused) {
+                // run shutdown in the old plot object
+                placeholder.data("plot").shutdown();
+
+                // reset reused canvases
+                plot.resize();
+
+                // make sure overlay pixels are cleared (canvas is cleared when we redraw)
+                octx.clearRect(0, 0, canvasWidth, canvasHeight);
+
+                // then whack any remaining obvious garbage left
+                eventHolder.unbind();
+                placeholder.children().not([canvas, overlay]).remove();
+            }
+
+            // save in case we get replotted
+            placeholder.data("plot", plot);
+        }
+
+        function bindEvents() {
+            // bind events
+            if (options.grid.hoverable) {
+                eventHolder.mousemove(onMouseMove);
+                eventHolder.mouseleave(onMouseLeave);
+            }
+
+            if (options.grid.clickable)
+                eventHolder.click(onClick);
+
+            executeHooks(hooks.bindEvents, [eventHolder]);
+        }
+
+        function shutdown() {
+            if (redrawTimeout)
+                clearTimeout(redrawTimeout);
+
+            eventHolder.unbind("mousemove", onMouseMove);
+            eventHolder.unbind("mouseleave", onMouseLeave);
+            eventHolder.unbind("click", onClick);
+
+            executeHooks(hooks.shutdown, [eventHolder]);
+        }
+
+        function setTransformationHelpers(axis) {
+            // set helper functions on the axis, assumes plot area
+            // has been computed already
+
+            function identity(x) { return x; }
+
+            var s, m, t = axis.options.transform || identity,
+                it = axis.options.inverseTransform;
+
+            // precompute how much the axis is scaling a point
+            // in canvas space
+            if (axis.direction == "x") {
+                s = axis.scale = plotWidth / Math.abs(t(axis.max) - t(axis.min));
+                m = Math.min(t(axis.max), t(axis.min));
+            }
+            else {
+                s = axis.scale = plotHeight / Math.abs(t(axis.max) - t(axis.min));
+                s = -s;
+                m = Math.max(t(axis.max), t(axis.min));
+            }
+
+            // data point to canvas coordinate
+            if (t == identity) // slight optimization
+                axis.p2c = function (p) { return (p - m) * s; };
+            else
+                axis.p2c = function (p) { return (t(p) - m) * s; };
+            // canvas coordinate to data point
+            if (!it)
+                axis.c2p = function (c) { return m + c / s; };
+            else
+                axis.c2p = function (c) { return it(m + c / s); };
+        }
+
+        function measureTickLabels(axis) {
+            var opts = axis.options, i, ticks = axis.ticks || [], labels = [],
+                l, w = opts.labelWidth, h = opts.labelHeight, dummyDiv;
+
+            function makeDummyDiv(labels, width) {
+                return $('<div style="position:absolute;top:-10000px;' + width + 'font-size:smaller">' +
+                         '<div class="' + axis.direction + 'Axis ' + axis.direction + axis.n + 'Axis">'
+                         + labels.join("") + '</div></div>')
+                    .appendTo(placeholder);
+            }
+
+            if (axis.direction == "x") {
+                // to avoid measuring the widths of the labels (it's slow), we
+                // construct fixed-size boxes and put the labels inside
+                // them, we don't need the exact figures and the
+                // fixed-size box content is easy to center
+                if (w == null)
+                    w = Math.floor(canvasWidth / (ticks.length > 0 ? ticks.length : 1));
+
+                // measure x label heights
+                if (h == null) {
+                    labels = [];
+                    for (i = 0; i < ticks.length; ++i) {
+                        l = ticks[i].label;
+                        if (l)
+                            labels.push('<div class="tickLabel" style="float:left;width:' + w + 'px">' + l + '</div>');
+                    }
+
+                    if (labels.length > 0) {
+                        // stick them all in the same div and measure
+                        // collective height
+                        labels.push('<div style="clear:left"></div>');
+                        dummyDiv = makeDummyDiv(labels, "width:10000px;");
+                        h = dummyDiv.height();
+                        dummyDiv.remove();
+                    }
+                }
+            }
+            else if (w == null || h == null) {
+                // calculate y label dimensions
+                for (i = 0; i < ticks.length; ++i) {
+                    l = ticks[i].label;
+                    if (l)
+                        labels.push('<div class="tickLabel">' + l + '</div>');
+                }
+
+                if (labels.length > 0) {
+                    dummyDiv = makeDummyDiv(labels, "");
+                    if (w == null)
+                        w = dummyDiv.children().width();
+                    if (h == null)
+                        h = dummyDiv.find("div.tickLabel").height();
+                    dummyDiv.remove();
+                }
+            }
+
+            if (w == null)
+                w = 0;
+            if (h == null)
+                h = 0;
+
+            axis.labelWidth = w;
+            axis.labelHeight = h;
+        }
+
+        function allocateAxisBoxFirstPhase(axis) {
+            // find the bounding box of the axis by looking at label
+            // widths/heights and ticks, make room by diminishing the
+            // plotOffset
+
+            var lw = axis.labelWidth,
+                lh = axis.labelHeight,
+                pos = axis.options.position,
+                tickLength = axis.options.tickLength,
+                axismargin = options.grid.axisMargin,
+                padding = options.grid.labelMargin,
+                all = axis.direction == "x" ? xaxes : yaxes,
+                index;
+
+            // determine axis margin
+            var samePosition = $.grep(all, function (a) {
+                return a && a.options.position == pos && a.reserveSpace;
+            });
+            if ($.inArray(axis, samePosition) == samePosition.length - 1)
+                axismargin = 0; // outermost
+
+            // determine tick length - if we're innermost, we can use "full"
+            if (tickLength == null)
+                tickLength = "full";
+
+            var sameDirection = $.grep(all, function (a) {
+                return a && a.reserveSpace;
+            });
+
+            var innermost = $.inArray(axis, sameDirection) == 0;
+            if (!innermost && tickLength == "full")
+                tickLength = 5;
+
+            if (!isNaN(+tickLength))
+                padding += +tickLength;
+
+            // compute box
+            if (axis.direction == "x") {
+                lh += padding;
+
+                if (pos == "bottom") {
+                    plotOffset.bottom += lh + axismargin;
+                    axis.box = { top: canvasHeight - plotOffset.bottom, height: lh };
+                }
+                else {
+                    axis.box = { top: plotOffset.top + axismargin, height: lh };
+                    plotOffset.top += lh + axismargin;
+                }
+            }
+            else {
+                lw += padding;
+
+                if (pos == "left") {
+                    axis.box = { left: plotOffset.left + axismargin, width: lw };
+                    plotOffset.left += lw + axismargin;
+                }
+                else {
+                    plotOffset.right += lw + axismargin;
+                    axis.box = { left: canvasWidth - plotOffset.right, width: lw };
+                }
+            }
+
+             // save for future reference
+            axis.position = pos;
+            axis.tickLength = tickLength;
+            axis.box.padding = padding;
+            axis.innermost = innermost;
+        }
+
+        function allocateAxisBoxSecondPhase(axis) {
+            // set remaining bounding box coordinates
+            if (axis.direction == "x") {
+                axis.box.left = plotOffset.left;
+                axis.box.width = plotWidth;
+            }
+            else {
+                axis.box.top = plotOffset.top;
+                axis.box.height = plotHeight;
+            }
+        }
+
+        function setupGrid() {
+            var i, axes = allAxes();
+
+            // first calculate the plot and axis box dimensions
+
+            $.each(axes, function (_, axis) {
+                axis.show = axis.options.show;
+                if (axis.show == null)
+                    axis.show = axis.used; // by default an axis is visible if it's got data
+
+                axis.reserveSpace = axis.show || axis.options.reserveSpace;
+
+                setRange(axis);
+            });
+
+            allocatedAxes = $.grep(axes, function (axis) { return axis.reserveSpace; });
+
+            plotOffset.left = plotOffset.right = plotOffset.top = plotOffset.bottom = 0;
+            if (options.grid.show) {
+                $.each(allocatedAxes, function (_, axis) {
+                    // make the ticks
+                    setupTickGeneration(axis);
+                    setTicks(axis);
+                    snapRangeToTicks(axis, axis.ticks);
+
+                    // find labelWidth/Height for axis
+                    measureTickLabels(axis);
+                });
+
+                // with all dimensions in house, we can compute the
+                // axis boxes, start from the outside (reverse order)
+                for (i = allocatedAxes.length - 1; i >= 0; --i)
+                    allocateAxisBoxFirstPhase(allocatedAxes[i]);
+
+                // make sure we've got enough space for things that
+                // might stick out
+                var minMargin = options.grid.minBorderMargin;
+                if (minMargin == null) {
+                    minMargin = 0;
+                    for (i = 0; i < series.length; ++i)
+                        minMargin = Math.max(minMargin, series[i].points.radius + series[i].points.lineWidth/2);
+                }
+
+                for (var a in plotOffset) {
+                    plotOffset[a] += options.grid.borderWidth;
+                    plotOffset[a] = Math.max(minMargin, plotOffset[a]);
+                }
+            }
+
+            plotWidth = canvasWidth - plotOffset.left - plotOffset.right;
+            plotHeight = canvasHeight - plotOffset.bottom - plotOffset.top;
+
+            // now we got the proper plotWidth/Height, we can compute the scaling
+            $.each(axes, function (_, axis) {
+                setTransformationHelpers(axis);
+            });
+
+            if (options.grid.show) {
+                $.each(allocatedAxes, function (_, axis) {
+                    allocateAxisBoxSecondPhase(axis);
+                });
+
+                insertAxisLabels();
+            }
+
+            insertLegend();
+        }
+
+        function setRange(axis) {
+            var opts = axis.options,
+                min = +(opts.min != null ? opts.min : axis.datamin),
+                max = +(opts.max != null ? opts.max : axis.datamax),
+                delta = max - min;
+
+            if (delta == 0.0) {
+                // degenerate case
+                var widen = max == 0 ? 1 : 0.01;
+
+                if (opts.min == null)
+                    min -= widen;
+                // always widen max if we couldn't widen min to ensure we
+                // don't fall into min == max which doesn't work
+                if (opts.max == null || opts.min != null)
+                    max += widen;
+            }
+            else {
+                // consider autoscaling
+                var margin = opts.autoscaleMargin;
+                if (margin != null) {
+                    if (opts.min == null) {
+                        min -= delta * margin;
+                        // make sure we don't go below zero if all values
+                        // are positive
+                        if (min < 0 && axis.datamin != null && axis.datamin >= 0)
+                            min = 0;
+                    }
+                    if (opts.max == null) {
+                        max += delta * margin;
+                        if (max > 0 && axis.datamax != null && axis.datamax <= 0)
+                            max = 0;
+                    }
+                }
+            }
+            axis.min = min;
+            axis.max = max;
+        }
+
+        function setupTickGeneration(axis) {
+            var opts = axis.options;
+
+            // estimate number of ticks
+            var noTicks;
+            if (typeof opts.ticks == "number" && opts.ticks > 0)
+                noTicks = opts.ticks;
+            else
+                // heuristic based on the model a*sqrt(x) fitted to
+                // some data points that seemed reasonable
+                noTicks = 0.3 * Math.sqrt(axis.direction == "x" ? canvasWidth : canvasHeight);
+
+            var delta = (axis.max - axis.min) / noTicks,
+                size, generator, unit, formatter, i, magn, norm;
+
+            if (opts.mode == "time") {
+                // pretty handling of time
+
+                // map of app. size of time units in milliseconds
+                var timeUnitSize = {
+                    "second": 1000,
+                    "minute": 60 * 1000,
+                    "hour": 60 * 60 * 1000,
+                    "day": 24 * 60 * 60 * 1000,
+                    "month": 30 * 24 * 60 * 60 * 1000,
+                    "year": 365.2425 * 24 * 60 * 60 * 1000
+                };
+
+
+                // the allowed tick sizes, after 1 year we use
+                // an integer algorithm
+                var spec = [
+                    [1, "second"], [2, "second"], [5, "second"], [10, "second"],
+                    [30, "second"],
+                    [1, "minute"], [2, "minute"], [5, "minute"], [10, "minute"],
+                    [30, "minute"],
+                    [1, "hour"], [2, "hour"], [4, "hour"],
+                    [8, "hour"], [12, "hour"],
+                    [1, "day"], [2, "day"], [3, "day"],
+                    [0.25, "month"], [0.5, "month"], [1, "month"],
+                    [2, "month"], [3, "month"], [6, "month"],
+                    [1, "year"]
+                ];
+
+                var minSize = 0;
+                if (opts.minTickSize != null) {
+                    if (typeof opts.tickSize == "number")
+                        minSize = opts.tickSize;
+                    else
+                        minSize = opts.minTickSize[0] * timeUnitSize[opts.minTickSize[1]];
+                }
+
+                for (var i = 0; i < spec.length - 1; ++i)
+                    if (delta < (spec[i][0] * timeUnitSize[spec[i][1]]
+                                 + spec[i + 1][0] * timeUnitSize[spec[i + 1][1]]) / 2
+                       && spec[i][0] * timeUnitSize[spec[i][1]] >= minSize)
+                        break;
+                size = spec[i][0];
+                unit = spec[i][1];
+
+                // special-case the possibility of several years
+                if (unit == "year") {
+                    magn = Math.pow(10, Math.floor(Math.log(delta / timeUnitSize.year) / Math.LN10));
+                    norm = (delta / timeUnitSize.year) / magn;
+                    if (norm < 1.5)
+                        size = 1;
+                    else if (norm < 3)
+                        size = 2;
+                    else if (norm < 7.5)
+                        size = 5;
+                    else
+                        size = 10;
+
+                    size *= magn;
+                }
+
+                axis.tickSize = opts.tickSize || [size, unit];
+
+                generator = function(axis) {
+                    var ticks = [],
+                        tickSize = axis.tickSize[0], unit = axis.tickSize[1],
+                        d = new Date(axis.min);
+
+                    var step = tickSize * timeUnitSize[unit];
+
+                    if (unit == "second")
+                        d.setUTCSeconds(floorInBase(d.getUTCSeconds(), tickSize));
+                    if (unit == "minute")
+                        d.setUTCMinutes(floorInBase(d.getUTCMinutes(), tickSize));
+                    if (unit == "hour")
+                        d.setUTCHours(floorInBase(d.getUTCHours(), tickSize));
+                    if (unit == "month")
+                        d.setUTCMonth(floorInBase(d.getUTCMonth(), tickSize));
+                    if (unit == "year")
+                        d.setUTCFullYear(floorInBase(d.getUTCFullYear(), tickSize));
+
+                    // reset smaller components
+                    d.setUTCMilliseconds(0);
+                    if (step >= timeUnitSize.minute)
+                        d.setUTCSeconds(0);
+                    if (step >= timeUnitSize.hour)
+                        d.setUTCMinutes(0);
+                    if (step >= timeUnitSize.day)
+                        d.setUTCHours(0);
+                    if (step >= timeUnitSize.day * 4)
+                        d.setUTCDate(1);
+                    if (step >= timeUnitSize.year)
+                        d.setUTCMonth(0);
+
+
+                    var carry = 0, v = Number.NaN, prev;
+                    do {
+                        prev = v;
+                        v = d.getTime();
+                        ticks.push(v);
+                        if (unit == "month") {
+                            if (tickSize < 1) {
+                                // a bit complicated - we'll divide the month
+                                // up but we need to take care of fractions
+                                // so we don't end up in the middle of a day
+                                d.setUTCDate(1);
+                                var start = d.getTime();
+                                d.setUTCMonth(d.getUTCMonth() + 1);
+                                var end = d.getTime();
+                                d.setTime(v + carry * timeUnitSize.hour + (end - start) * tickSize);
+                                carry = d.getUTCHours();
+                                d.setUTCHours(0);
+                            }
+                            else
+                                d.setUTCMonth(d.getUTCMonth() + tickSize);
+                        }
+                        else if (unit == "year") {
+                            d.setUTCFullYear(d.getUTCFullYear() + tickSize);
+                        }
+                        else
+                            d.setTime(v + step);
+                    } while (v < axis.max && v != prev);
+
+                    return ticks;
+                };
+
+                formatter = function (v, axis) {
+                    var d = new Date(v);
+
+                    // first check global format
+                    if (opts.timeformat != null)
+                        return $.plot.formatDate(d, opts.timeformat, opts.monthNames);
+
+                    var t = axis.tickSize[0] * timeUnitSize[axis.tickSize[1]];
+                    var span = axis.max - axis.min;
+                    var suffix = (opts.twelveHourClock) ? " %p" : "";
+
+                    if (t < timeUnitSize.minute)
+                        fmt = "%h:%M:%S" + suffix;
+                    else if (t < timeUnitSize.day) {
+                        if (span < 2 * timeUnitSize.day)
+                            fmt = "%h:%M" + suffix;
+                        else
+                            fmt = "%b %d %h:%M" + suffix;
+                    }
+                    else if (t < timeUnitSize.month)
+                        fmt = "%b %d";
+                    else if (t < timeUnitSize.year) {
+                        if (span < timeUnitSize.year)
+                            fmt = "%b";
+                        else
+                            fmt = "%b %y";
+                    }
+                    else
+                        fmt = "%y";
+
+                    return $.plot.formatDate(d, fmt, opts.monthNames);
+                };
+            }
+            else {
+                // pretty rounding of base-10 numbers
+                var maxDec = opts.tickDecimals;
+                var dec = -Math.floor(Math.log(delta) / Math.LN10);
+                if (maxDec != null && dec > maxDec)
+                    dec = maxDec;
+
+                magn = Math.pow(10, -dec);
+                norm = delta / magn; // norm is between 1.0 and 10.0
+
+                if (norm < 1.5)
+                    size = 1;
+                else if (norm < 3) {
+                    size = 2;
+                    // special case for 2.5, requires an extra decimal
+                    if (norm > 2.25 && (maxDec == null || dec + 1 <= maxDec)) {
+                        size = 2.5;
+                        ++dec;
+                    }
+                }
+                else if (norm < 7.5)
+                    size = 5;
+                else
+                    size = 10;
+
+                size *= magn;
+
+                if (opts.minTickSize != null && size < opts.minTickSize)
+                    size = opts.minTickSize;
+
+                axis.tickDecimals = Math.max(0, maxDec != null ? maxDec : dec);
+                axis.tickSize = opts.tickSize || size;
+
+                generator = function (axis) {
+                    var ticks = [];
+
+                    // spew out all possible ticks
+                    var start = floorInBase(axis.min, axis.tickSize),
+                        i = 0, v = Number.NaN, prev;
+                    do {
+                        prev = v;
+                        v = start + i * axis.tickSize;
+                        ticks.push(v);
+                        ++i;
+                    } while (v < axis.max && v != prev);
+                    return ticks;
+                };
+
+                formatter = function (v, axis) {
+                    return v.toFixed(axis.tickDecimals);
+                };
+            }
+
+            if (opts.alignTicksWithAxis != null) {
+                var otherAxis = (axis.direction == "x" ? xaxes : yaxes)[opts.alignTicksWithAxis - 1];
+                if (otherAxis && otherAxis.used && otherAxis != axis) {
+                    // consider snapping min/max to outermost nice ticks
+                    var niceTicks = generator(axis);
+                    if (niceTicks.length > 0) {
+                        if (opts.min == null)
+                            axis.min = Math.min(axis.min, niceTicks[0]);
+                        if (opts.max == null && niceTicks.length > 1)
+                            axis.max = Math.max(axis.max, niceTicks[niceTicks.length - 1]);
+                    }
+
+                    generator = function (axis) {
+                        // copy ticks, scaled to this axis
+                        var ticks = [], v, i;
+                        for (i = 0; i < otherAxis.ticks.length; ++i) {
+                            v = (otherAxis.ticks[i].v - otherAxis.min) / (otherAxis.max - otherAxis.min);
+                            v = axis.min + v * (axis.max - axis.min);
+                            ticks.push(v);
+                        }
+                        return ticks;
+                    };
+
+                    // we might need an extra decimal since forced
+                    // ticks don't necessarily fit naturally
+                    if (axis.mode != "time" && opts.tickDecimals == null) {
+                        var extraDec = Math.max(0, -Math.floor(Math.log(delta) / Math.LN10) + 1),
+                            ts = generator(axis);
+
+                        // only proceed if the tick interval rounded
+                        // with an extra decimal doesn't give us a
+                        // zero at end
+                        if (!(ts.length > 1 && /\..*0$/.test((ts[1] - ts[0]).toFixed(extraDec))))
+                            axis.tickDecimals = extraDec;
+                    }
+                }
+            }
+
+            axis.tickGenerator = generator;
+            if ($.isFunction(opts.tickFormatter))
+                axis.tickFormatter = function (v, axis) { return "" + opts.tickFormatter(v, axis); };
+            else
+                axis.tickFormatter = formatter;
+        }
+
+        function setTicks(axis) {
+            var oticks = axis.options.ticks, ticks = [];
+            if (oticks == null || (typeof oticks == "number" && oticks > 0))
+                ticks = axis.tickGenerator(axis);
+            else if (oticks) {
+                if ($.isFunction(oticks))
+                    // generate the ticks
+                    ticks = oticks({ min: axis.min, max: axis.max });
+                else
+                    ticks = oticks;
+            }
+
+            // clean up/labelify the supplied ticks, copy them over
+            var i, v;
+            axis.ticks = [];
+            for (i = 0; i < ticks.length; ++i) {
+                var label = null;
+                var t = ticks[i];
+                if (typeof t == "object") {
+                    v = +t[0];
+                    if (t.length > 1)
+                        label = t[1];
+                }
+                else
+                    v = +t;
+                if (label == null)
+                    label = axis.tickFormatter(v, axis);
+                if (!isNaN(v))
+                    axis.ticks.push({ v: v, label: label });
+            }
+        }
+
+        function snapRangeToTicks(axis, ticks) {
+            if (axis.options.autoscaleMargin && ticks.length > 0) {
+                // snap to ticks
+                if (axis.options.min == null)
+                    axis.min = Math.min(axis.min, ticks[0].v);
+                if (axis.options.max == null && ticks.length > 1)
+                    axis.max = Math.max(axis.max, ticks[ticks.length - 1].v);
+            }
+        }
+
+        function draw() {
+            ctx.clearRect(0, 0, canvasWidth, canvasHeight);
+
+            var grid = options.grid;
+
+            // draw background, if any
+            if (grid.show && grid.backgroundColor)
+                drawBackground();
+
+            if (grid.show && !grid.aboveData)
+                drawGrid();
+
+            for (var i = 0; i < series.length; ++i) {
+                executeHooks(hooks.drawSeries, [ctx, series[i]]);
+                drawSeries(series[i]);
+            }
+
+            executeHooks(hooks.draw, [ctx]);
+
+            if (grid.show && grid.aboveData)
+                drawGrid();
+        }
+
+        function extractRange(ranges, coord) {
+            var axis, from, to, key, axes = allAxes();
+
+            for (i = 0; i < axes.length; ++i) {
+                axis = axes[i];
+                if (axis.direction == coord) {
+                    key = coord + axis.n + "axis";
+                    if (!ranges[key] && axis.n == 1)
+                        key = coord + "axis"; // support x1axis as xaxis
+                    if (ranges[key]) {
+                        from = ranges[key].from;
+                        to = ranges[key].to;
+                        break;
+                    }
+                }
+            }
+
+            // backwards-compat stuff - to be removed in future
+            if (!ranges[key]) {
+                axis = coord == "x" ? xaxes[0] : yaxes[0];
+                from = ranges[coord + "1"];
+                to = ranges[coord + "2"];
+            }
+
+            // auto-reverse as an added bonus
+            if (from != null && to != null && from > to) {
+                var tmp = from;
+                from = to;
+                to = tmp;
+            }
+
+            return { from: from, to: to, axis: axis };
+        }
+
+        function drawBackground() {
+            ctx.save();
+            ctx.translate(plotOffset.left, plotOffset.top);
+
+            ctx.fillStyle = getColorOrGradient(options.grid.backgroundColor, plotHeight, 0, "rgba(255, 255, 255, 0)");
+            ctx.fillRect(0, 0, plotWidth, plotHeight);
+            ctx.restore();
+        }
+
+        function drawGrid() {
+            var i;
+
+            ctx.save();
+            ctx.translate(plotOffset.left, plotOffset.top);
+
+            // draw markings
+            var markings = options.grid.markings;
+            if (markings) {
+                if ($.isFunction(markings)) {
+                    var axes = plot.getAxes();
+                    // xmin etc. is backwards compatibility, to be
+                    // removed in the future
+                    axes.xmin = axes.xaxis.min;
+                    axes.xmax = axes.xaxis.max;
+                    axes.ymin = axes.yaxis.min;
+                    axes.ymax = axes.yaxis.max;
+
+                    markings = markings(axes);
+                }
+
+                for (i = 0; i < markings.length; ++i) {
+                    var m = markings[i],
+                        xrange = extractRange(m, "x"),
+                        yrange = extractRange(m, "y");
+
+                    // fill in missing
+                    if (xrange.from == null)
+                        xrange.from = xrange.axis.min;
+                    if (xrange.to == null)
+                        xrange.to = xrange.axis.max;
+                    if (yrange.from == null)
+                        yrange.from = yrange.axis.min;
+                    if (yrange.to == null)
+                        yrange.to = yrange.axis.max;
+
+                    // clip
+                    if (xrange.to < xrange.axis.min || xrange.from > xrange.axis.max ||
+                        yrange.to < yrange.axis.min || yrange.from > yrange.axis.max)
+                        continue;
+
+                    xrange.from = Math.max(xrange.from, xrange.axis.min);
+                    xrange.to = Math.min(xrange.to, xrange.axis.max);
+                    yrange.from = Math.max(yrange.from, yrange.axis.min);
+                    yrange.to = Math.min(yrange.to, yrange.axis.max);
+
+                    if (xrange.from == xrange.to && yrange.from == yrange.to)
+                        continue;
+
+                    // then draw
+                    xrange.from = xrange.axis.p2c(xrange.from);
+                    xrange.to = xrange.axis.p2c(xrange.to);
+                    yrange.from = yrange.axis.p2c(yrange.from);
+                    yrange.to = yrange.axis.p2c(yrange.to);
+
+                    if (xrange.from == xrange.to || yrange.from == yrange.to) {
+                        // draw line
+                        ctx.beginPath();
+                        ctx.strokeStyle = m.color || options.grid.markingsColor;
+                        ctx.lineWidth = m.lineWidth || options.grid.markingsLineWidth;
+                        ctx.moveTo(xrange.from, yrange.from);
+                        ctx.lineTo(xrange.to, yrange.to);
+                        ctx.stroke();
+                    }
+                    else {
+                        // fill area
+                        ctx.fillStyle = m.color || options.grid.markingsColor;
+                        ctx.fillRect(xrange.from, yrange.to,
+                                     xrange.to - xrange.from,
+                                     yrange.from - yrange.to);
+                    }
+                }
+            }
+
+            // draw the ticks
+            var axes = allAxes(), bw = options.grid.borderWidth;
+
+            for (var j = 0; j < axes.length; ++j) {
+                var axis = axes[j], box = axis.box,
+                    t = axis.tickLength, x, y, xoff, yoff;
+                if (!axis.show || axis.ticks.length == 0)
+                    continue
+
+                ctx.strokeStyle = axis.options.tickColor || $.color.parse(axis.options.color).scale('a', 0.22).toString();
+                ctx.lineWidth = 1;
+
+                // find the edges
+                if (axis.direction == "x") {
+                    x = 0;
+                    if (t == "full")
+                        y = (axis.position == "top" ? 0 : plotHeight);
+                    else
+                        y = box.top - plotOffset.top + (axis.position == "top" ? box.height : 0);
+                }
+                else {
+                    y = 0;
+                    if (t == "full")
+                        x = (axis.position == "left" ? 0 : plotWidth);
+                    else
+                        x = box.left - plotOffset.left + (axis.position == "left" ? box.width : 0);
+                }
+
+                // draw tick bar
+                if (!axis.innermost) {
+                    ctx.beginPath();
+                    xoff = yoff = 0;
+                    if (axis.direction == "x")
+                        xoff = plotWidth;
+                    else
+                        yoff = plotHeight;
+
+                    if (ctx.lineWidth == 1) {
+                        x = Math.floor(x) + 0.5;
+                        y = Math.floor(y) + 0.5;
+                    }
+
+                    ctx.moveTo(x, y);
+                    ctx.lineTo(x + xoff, y + yoff);
+                    ctx.stroke();
+                }
+
+                // draw ticks
+                ctx.beginPath();
+                for (i = 0; i < axis.ticks.length; ++i) {
+                    var v = axis.ticks[i].v;
+
+                    xoff = yoff = 0;
+
+                    if (v < axis.min || v > axis.max
+                        // skip those lying on the axes if we got a border
+                        || (t == "full" && bw > 0
+                            && (v == axis.min || v == axis.max)))
+                        continue;
+
+                    if (axis.direction == "x") {
+                        x = axis.p2c(v);
+                        yoff = t == "full" ? -plotHeight : t;
+
+                        if (axis.position == "top")
+                            yoff = -yoff;
+                    }
+                    else {
+                        y = axis.p2c(v);
+                        xoff = t == "full" ? -plotWidth : t;
+
+                        if (axis.position == "left")
+                            xoff = -xoff;
+                    }
+
+                    if (ctx.lineWidth == 1) {
+                        if (axis.direction == "x")
+                            x = Math.floor(x) + 0.5;
+                        else
+                            y = Math.floor(y) + 0.5;
+                    }
+
+                    ctx.moveTo(x, y);
+                    ctx.lineTo(x + xoff, y + yoff);
+                }
+
+                ctx.stroke();
+            }
+
+
+            // draw border
+            if (bw) {
+                ctx.lineWidth = bw;
+                ctx.strokeStyle = options.grid.borderColor;
+                ctx.strokeRect(-bw/2, -bw/2, plotWidth + bw, plotHeight + bw);
+            }
+
+            ctx.restore();
+        }
+
+        function insertAxisLabels() {
+            placeholder.find(".tickLabels").remove();
+
+            var html = ['<div class="tickLabels" style="font-size:smaller">'];
+
+            var axes = allAxes();
+            for (var j = 0; j < axes.length; ++j) {
+                var axis = axes[j], box = axis.box;
+                if (!axis.show)
+                    continue;
+                //debug: html.push('<div style="position:absolute;opacity:0.10;background-color:red;left:' + box.left + 'px;top:' + box.top + 'px;width:' + box.width +  'px;height:' + box.height + 'px"></div>')
+                html.push('<div class="' + axis.direction + 'Axis ' + axis.direction + axis.n + 'Axis" style="color:' + axis.options.color + '">');
+                for (var i = 0; i < axis.ticks.length; ++i) {
+                    var tick = axis.ticks[i];
+                    if (!tick.label || tick.v < axis.min || tick.v > axis.max)
+                        continue;
+
+                    var pos = {}, align;
+
+                    if (axis.direction == "x") {
+                        align = "center";
+                        pos.left = Math.round(plotOffset.left + axis.p2c(tick.v) - axis.labelWidth/2);
+                        if (axis.position == "bottom")
+                            pos.top = box.top + box.padding;
+                        else
+                            pos.bottom = canvasHeight - (box.top + box.height - box.padding);
+                    }
+                    else {
+                        pos.top = Math.round(plotOffset.top + axis.p2c(tick.v) - axis.labelHeight/2);
+                        if (axis.position == "left") {
+                            pos.right = canvasWidth - (box.left + box.width - box.padding)
+                            align = "right";
+                        }
+                        else {
+                            pos.left = box.left + box.padding;
+                            align = "left";
+                        }
+                    }
+
+                    pos.width = axis.labelWidth;
+
+                    var style = ["position:absolute", "text-align:" + align ];
+                    for (var a in pos)
+                        style.push(a + ":" + pos[a] + "px")
+
+                    html.push('<div class="tickLabel" style="' + style.join(';') + '">' + tick.label + '</div>');
+                }
+                html.push('</div>');
+            }
+
+            html.push('</div>');
+
+            placeholder.append(html.join(""));
+        }
+
+        function drawSeries(series) {
+            if (series.lines.show)
+                drawSeriesLines(series);
+            if (series.bars.show)
+                drawSeriesBars(series);
+            if (series.points.show)
+                drawSeriesPoints(series);
+        }
+
+        function drawSeriesLines(series) {
+            function plotLine(datapoints, xoffset, yoffset, axisx, axisy) {
+                var points = datapoints.points,
+                    ps = datapoints.pointsize,
+                    prevx = null, prevy = null;
+
+                ctx.beginPath();
+                for (var i = ps; i < points.length; i += ps) {
+                    var x1 = points[i - ps], y1 = points[i - ps + 1],
+                        x2 = points[i], y2 = points[i + 1];
+
+                    if (x1 == null || x2 == null)
+                        continue;
+
+                    // clip with ymin
+                    if (y1 <= y2 && y1 < axisy.min) {
+                        if (y2 < axisy.min)
+                            continue;   // line segment is outside
+                        // compute new intersection point
+                        x1 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
+                        y1 = axisy.min;
+                    }
+                    else if (y2 <= y1 && y2 < axisy.min) {
+                        if (y1 < axisy.min)
+                            continue;
+                        x2 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
+                        y2 = axisy.min;
+                    }
+
+                    // clip with ymax
+                    if (y1 >= y2 && y1 > axisy.max) {
+                        if (y2 > axisy.max)
+                            continue;
+                        x1 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
+                        y1 = axisy.max;
+                    }
+                    else if (y2 >= y1 && y2 > axisy.max) {
+                        if (y1 > axisy.max)
+                            continue;
+                        x2 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
+                        y2 = axisy.max;
+                    }
+
+                    // clip with xmin
+                    if (x1 <= x2 && x1 < axisx.min) {
+                        if (x2 < axisx.min)
+                            continue;
+                        y1 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
+                        x1 = axisx.min;
+                    }
+                    else if (x2 <= x1 && x2 < axisx.min) {
+                        if (x1 < axisx.min)
+                            continue;
+                        y2 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
+                        x2 = axisx.min;
+                    }
+
+                    // clip with xmax
+                    if (x1 >= x2 && x1 > axisx.max) {
+                        if (x2 > axisx.max)
+                            continue;
+                        y1 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
+                        x1 = axisx.max;
+                    }
+                    else if (x2 >= x1 && x2 > axisx.max) {
+                        if (x1 > axisx.max)
+                            continue;
+                        y2 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
+                        x2 = axisx.max;
+                    }
+
+                    if (x1 != prevx || y1 != prevy)
+                        ctx.moveTo(axisx.p2c(x1) + xoffset, axisy.p2c(y1) + yoffset);
+
+                    prevx = x2;
+                    prevy = y2;
+                    ctx.lineTo(axisx.p2c(x2) + xoffset, axisy.p2c(y2) + yoffset);
+                }
+                ctx.stroke();
+            }
+
+            function plotLineArea(datapoints, axisx, axisy) {
+                var points = datapoints.points,
+                    ps = datapoints.pointsize,
+                    bottom = Math.min(Math.max(0, axisy.min), axisy.max),
+                    i = 0, top, areaOpen = false,
+                    ypos = 1, segmentStart = 0, segmentEnd = 0;
+
+                // we process each segment in two turns, first forward
+                // direction to sketch out top, then once we hit the
+                // end we go backwards to sketch the bottom
+                while (true) {
+                    if (ps > 0 && i > points.length + ps)
+                        break;
+
+                    i += ps; // ps is negative if going backwards
+
+                    var x1 = points[i - ps],
+                        y1 = points[i - ps + ypos],
+                        x2 = points[i], y2 = points[i + ypos];
+
+                    if (areaOpen) {
+                        if (ps > 0 && x1 != null && x2 == null) {
+                            // at turning point
+                            segmentEnd = i;
+                            ps = -ps;
+                            ypos = 2;
+                            continue;
+                        }
+
+                        if (ps < 0 && i == segmentStart + ps) {
+                            // done with the reverse sweep
+                            ctx.fill();
+                            areaOpen = false;
+                            ps = -ps;
+                            ypos = 1;
+                            i = segmentStart = segmentEnd + ps;
+                            continue;
+                        }
+                    }
+
+                    if (x1 == null || x2 == null)
+                        continue;
+
+                    // clip x values
+
+                    // clip with xmin
+                    if (x1 <= x2 && x1 < axisx.min) {
+                        if (x2 < axisx.min)
+                            continue;
+                        y1 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
+                        x1 = axisx.min;
+                    }
+                    else if (x2 <= x1 && x2 < axisx.min) {
+                        if (x1 < axisx.min)
+                            continue;
+                        y2 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
+                        x2 = axisx.min;
+                    }
+
+                    // clip with xmax
+                    if (x1 >= x2 && x1 > axisx.max) {
+                        if (x2 > axisx.max)
+                            continue;
+                        y1 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
+                        x1 = axisx.max;
+                    }
+                    else if (x2 >= x1 && x2 > axisx.max) {
+                        if (x1 > axisx.max)
+                            continue;
+                        y2 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
+                        x2 = axisx.max;
+                    }
+
+                    if (!areaOpen) {
+                        // open area
+                        ctx.beginPath();
+                        ctx.moveTo(axisx.p2c(x1), axisy.p2c(bottom));
+                        areaOpen = true;
+                    }
+
+                    // now first check the case where both is outside
+                    if (y1 >= axisy.max && y2 >= axisy.max) {
+                        ctx.lineTo(axisx.p2c(x1), axisy.p2c(axisy.max));
+                        ctx.lineTo(axisx.p2c(x2), axisy.p2c(axisy.max));
+                        continue;
+                    }
+                    else if (y1 <= axisy.min && y2 <= axisy.min) {
+                        ctx.lineTo(axisx.p2c(x1), axisy.p2c(axisy.min));
+                        ctx.lineTo(axisx.p2c(x2), axisy.p2c(axisy.min));
+                        continue;
+                    }
+
+                    // else it's a bit more complicated, there might
+                    // be a flat maxed out rectangle first, then a
+                    // triangular cutout or reverse; to find these
+                    // keep track of the current x values
+                    var x1old = x1, x2old = x2;
+
+                    // clip the y values, without shortcutting, we
+                    // go through all cases in turn
+
+                    // clip with ymin
+                    if (y1 <= y2 && y1 < axisy.min && y2 >= axisy.min) {
+                        x1 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
+                        y1 = axisy.min;
+                    }
+                    else if (y2 <= y1 && y2 < axisy.min && y1 >= axisy.min) {
+                        x2 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
+                        y2 = axisy.min;
+                    }
+
+                    // clip with ymax
+                    if (y1 >= y2 && y1 > axisy.max && y2 <= axisy.max) {
+                        x1 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
+                        y1 = axisy.max;
+                    }
+                    else if (y2 >= y1 && y2 > axisy.max && y1 <= axisy.max) {
+                        x2 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
+                        y2 = axisy.max;
+                    }
+
+                    // if the x value was changed we got a rectangle
+                    // to fill
+                    if (x1 != x1old) {
+                        ctx.lineTo(axisx.p2c(x1old), axisy.p2c(y1));
+                        // it goes to (x1, y1), but we fill that below
+                    }
+
+                    // fill triangular section, this sometimes result
+                    // in redundant points if (x1, y1) hasn't changed
+                    // from previous line to, but we just ignore that
+                    ctx.lineTo(axisx.p2c(x1), axisy.p2c(y1));
+                    ctx.lineTo(axisx.p2c(x2), axisy.p2c(y2));
+
+                    // fill the other rectangle if it's there
+                    if (x2 != x2old) {
+                        ctx.lineTo(axisx.p2c(x2), axisy.p2c(y2));
+                        ctx.lineTo(axisx.p2c(x2old), axisy.p2c(y2));
+                    }
+                }
+            }
+
+            ctx.save();
+            ctx.translate(plotOffset.left, plotOffset.top);
+            ctx.lineJoin = "round";
+
+            var lw = series.lines.lineWidth,
+                sw = series.shadowSize;
+            // FIXME: consider another form of shadow when filling is turned on
+            if (lw > 0 && sw > 0) {
+                // draw shadow as a thick and thin line with transparency
+                ctx.lineWidth = sw;
+                ctx.strokeStyle = "rgba(0,0,0,0.1)";
+                // position shadow at angle from the mid of line
+                var angle = Math.PI/18;
+                plotLine(series.datapoints, Math.sin(angle) * (lw/2 + sw/2), Math.cos(angle) * (lw/2 + sw/2), series.xaxis, series.yaxis);
+                ctx.lineWidth = sw/2;
+                plotLine(series.datapoints, Math.sin(angle) * (lw/2 + sw/4), Math.cos(angle) * (lw/2 + sw/4), series.xaxis, series.yaxis);
+            }
+
+            ctx.lineWidth = lw;
+            ctx.strokeStyle = series.color;
+            var fillStyle = getFillStyle(series.lines, series.color, 0, plotHeight);
+            if (fillStyle) {
+                ctx.fillStyle = fillStyle;
+                plotLineArea(series.datapoints, series.xaxis, series.yaxis);
+            }
+
+            if (lw > 0)
+                plotLine(series.datapoints, 0, 0, series.xaxis, series.yaxis);
+            ctx.restore();
+        }
+
+        function drawSeriesPoints(series) {
+            function plotPoints(datapoints, radius, fillStyle, offset, shadow, axisx, axisy, symbol) {
+                var points = datapoints.points, ps = datapoints.pointsize;
+
+                for (var i = 0; i < points.length; i += ps) {
+                    var x = points[i], y = points[i + 1];
+                    if (x == null || x < axisx.min || x > axisx.max || y < axisy.min || y > axisy.max)
+                        continue;
+
+                    ctx.beginPath();
+                    x = axisx.p2c(x);
+                    y = axisy.p2c(y) + offset;
+                    if (symbol == "circle")
+                        ctx.arc(x, y, radius, 0, shadow ? Math.PI : Math.PI * 2, false);
+                    else
+                        symbol(ctx, x, y, radius, shadow);
+                    ctx.closePath();
+
+                    if (fillStyle) {
+                        ctx.fillStyle = fillStyle;
+                        ctx.fill();
+                    }
+                    ctx.stroke();
+                }
+            }
+
+            ctx.save();
+            ctx.translate(plotOffset.left, plotOffset.top);
+
+            var lw = series.points.lineWidth,
+                sw = series.shadowSize,
+                radius = series.points.radius,
+                symbol = series.points.symbol;
+            if (lw > 0 && sw > 0) {
+                // draw shadow in two steps
+                var w = sw / 2;
+                ctx.lineWidth = w;
+                ctx.strokeStyle = "rgba(0,0,0,0.1)";
+                plotPoints(series.datapoints, radius, null, w + w/2, true,
+                           series.xaxis, series.yaxis, symbol);
+
+                ctx.strokeStyle = "rgba(0,0,0,0.2)";
+                plotPoints(series.datapoints, radius, null, w/2, true,
+                           series.xaxis, series.yaxis, symbol);
+            }
+
+            ctx.lineWidth = lw;
+            ctx.strokeStyle = series.color;
+            plotPoints(series.datapoints, radius,
+                       getFillStyle(series.points, series.color), 0, false,
+                       series.xaxis, series.yaxis, symbol);
+            ctx.restore();
+        }
+
+        function drawBar(x, y, b, barLeft, barRight, offset, fillStyleCallback, axisx, axisy, c, horizontal, lineWidth) {
+            var left, right, bottom, top,
+                drawLeft, drawRight, drawTop, drawBottom,
+                tmp;
+
+            // in horizontal mode, we start the bar from the left
+            // instead of from the bottom so it appears to be
+            // horizontal rather than vertical
+            if (horizontal) {
+                drawBottom = drawRight = drawTop = true;
+                drawLeft = false;
+                left = b;
+                right = x;
+                top = y + barLeft;
+                bottom = y + barRight;
+
+                // account for negative bars
+                if (right < left) {
+                    tmp = right;
+                    right = left;
+                    left = tmp;
+                    drawLeft = true;
+                    drawRight = false;
+                }
+            }
+            else {
+                drawLeft = drawRight = drawTop = true;
+                drawBottom = false;
+                left = x + barLeft;
+                right = x + barRight;
+                bottom = b;
+                top = y;
+
+                // account for negative bars
+                if (top < bottom) {
+                    tmp = top;
+                    top = bottom;
+                    bottom = tmp;
+                    drawBottom = true;
+                    drawTop = false;
+                }
+            }
+
+            // clip
+            if (right < axisx.min || left > axisx.max ||
+                top < axisy.min || bottom > axisy.max)
+                return;
+
+            if (left < axisx.min) {
+                left = axisx.min;
+                drawLeft = false;
+            }
+
+            if (right > axisx.max) {
+                right = axisx.max;
+                drawRight = false;
+            }
+
+            if (bottom < axisy.min) {
+                bottom = axisy.min;
+                drawBottom = false;
+            }
+
+            if (top > axisy.max) {
+                top = axisy.max;
+                drawTop = false;
+            }
+
+            left = axisx.p2c(left);
+            bottom = axisy.p2c(bottom);
+            right = axisx.p2c(right);
+            top = axisy.p2c(top);
+
+            // fill the bar
+            if (fillStyleCallback) {
+                c.beginPath();
+                c.moveTo(left, bottom);
+                c.lineTo(left, top);
+                c.lineTo(right, top);
+                c.lineTo(right, bottom);
+                c.fillStyle = fillStyleCallback(bottom, top);
+                c.fill();
+            }
+
+            // draw outline
+            if (lineWidth > 0 && (drawLeft || drawRight || drawTop || drawBottom)) {
+                c.beginPath();
+
+                // FIXME: inline moveTo is buggy with excanvas
+                c.moveTo(left, bottom + offset);
+                if (drawLeft)
+                    c.lineTo(left, top + offset);
+                else
+                    c.moveTo(left, top + offset);
+                if (drawTop)
+                    c.lineTo(right, top + offset);
+                else
+                    c.moveTo(right, top + offset);
+                if (drawRight)
+                    c.lineTo(right, bottom + offset);
+                else
+                    c.moveTo(right, bottom + offset);
+                if (drawBottom)
+                    c.lineTo(left, bottom + offset);
+                else
+                    c.moveTo(left, bottom + offset);
+                c.stroke();
+            }
+        }
+
+        function drawSeriesBars(series) {
+            function plotBars(datapoints, barLeft, barRight, offset, fillStyleCallback, axisx, axisy) {
+                var points = datapoints.points, ps = datapoints.pointsize;
+
+                for (var i = 0; i < points.length; i += ps) {
+                    if (points[i] == null)
+                        continue;
+                    drawBar(points[i], points[i + 1], points[i + 2], barLeft, barRight, offset, fillStyleCallback, axisx, axisy, ctx, series.bars.horizontal, series.bars.lineWidth);
+                }
+            }
+
+            ctx.save();
+            ctx.translate(plotOffset.left, plotOffset.top);
+
+            // FIXME: figure out a way to add shadows (for instance along the right edge)
+            ctx.lineWidth = series.bars.lineWidth;
+            ctx.strokeStyle = series.color;
+            var barLeft = series.bars.align == "left" ? 0 : -series.bars.barWidth/2;
+            var fillStyleCallback = series.bars.fill ? function (bottom, top) { return getFillStyle(series.bars, series.color, bottom, top); } : null;
+            plotBars(series.datapoints, barLeft, barLeft + series.bars.barWidth, 0, fillStyleCallback, series.xaxis, series.yaxis);
+            ctx.restore();
+        }
+
+        function getFillStyle(filloptions, seriesColor, bottom, top) {
+            var fill = filloptions.fill;
+            if (!fill)
+                return null;
+
+            if (filloptions.fillColor)
+                return getColorOrGradient(filloptions.fillColor, bottom, top, seriesColor);
+
+            var c = $.color.parse(seriesColor);
+            c.a = typeof fill == "number" ? fill : 0.4;
+            c.normalize();
+            return c.toString();
+        }
+
+        function insertLegend() {
+            placeholder.find(".legend").remove();
+
+            if (!options.legend.show)
+                return;
+
+            var fragments = [], rowStarted = false,
+                lf = options.legend.labelFormatter, s, label;
+            for (var i = 0; i < series.length; ++i) {
+                s = series[i];
+                label = s.label;
+                if (!label)
+                    continue;
+
+                if (i % options.legend.noColumns == 0) {
+                    if (rowStarted)
+                        fragments.push('</tr>');
+                    fragments.push('<tr>');
+                    rowStarted = true;
+                }
+
+                if (lf)
+                    label = lf(label, s);
+
+                fragments.push(
+                    '<td class="legendColorBox"><div style="border:1px solid ' + options.legend.labelBoxBorderColor + ';padding:1px"><div style="width:4px;height:0;border:5px solid ' + s.color + ';overflow:hidden"></div></div></td>' +
+                    '<td class="legendLabel">' + label + '</td>');
+            }
+            if (rowStarted)
+                fragments.push('</tr>');
+
+            if (fragments.length == 0)
+                return;
+
+            var table = '<table style="font-size:smaller;color:' + options.grid.color + '">' + fragments.join("") + '</table>';
+            if (options.legend.container != null)
+                $(options.legend.container).html(table);
+            else {
+                var pos = "",
+                    p = options.legend.position,
+                    m = options.legend.margin;
+                if (m[0] == null)
+                    m = [m, m];
+                if (p.charAt(0) == "n")
+                    pos += 'top:' + (m[1] + plotOffset.top) + 'px;';
+                else if (p.charAt(0) == "s")
+                    pos += 'bottom:' + (m[1] + plotOffset.bottom) + 'px;';
+                if (p.charAt(1) == "e")
+                    pos += 'right:' + (m[0] + plotOffset.right) + 'px;';
+                else if (p.charAt(1) == "w")
+                    pos += 'left:' + (m[0] + plotOffset.left) + 'px;';
+                var legend = $('<div class="legend">' + table.replace('style="', 'style="position:absolute;' + pos +';') + '</div>').appendTo(placeholder);
+                if (options.legend.backgroundOpacity != 0.0) {
+                    // put in the transparent background
+                    // separately to avoid blended labels and
+                    // label boxes
+                    var c = options.legend.backgroundColor;
+                    if (c == null) {
+                        c = options.grid.backgroundColor;
+                        if (c && typeof c == "string")
+                            c = $.color.parse(c);
+                        else
+                            c = $.color.extract(legend, 'background-color');
+                        c.a = 1;
+                        c = c.toString();
+                    }
+                    var div = legend.children();
+                    $('<div style="position:absolute;width:' + div.width() + 'px;height:' + div.height() + 'px;' + pos +'background-color:' + c + ';"> </div>').prependTo(legend).css('opacity', options.legend.backgroundOpacity);
+                }
+            }
+        }
+
+
+        // interactive features
+
+        var highlights = [],
+            redrawTimeout = null;
+
+        // returns the data item the mouse is over, or null if none is found
+        function findNearbyItem(mouseX, mouseY, seriesFilter) {
+            var maxDistance = options.grid.mouseActiveRadius,
+                smallestDistance = maxDistance * maxDistance + 1,
+                item = null, foundPoint = false, i, j;
+
+            for (i = series.length - 1; i >= 0; --i) {
+                if (!seriesFilter(series[i]))
+                    continue;
+
+                var s = series[i],
+                    axisx = s.xaxis,
+                    axisy = s.yaxis,
+                    points = s.datapoints.points,
+                    ps = s.datapoints.pointsize,
+                    mx = axisx.c2p(mouseX), // precompute some stuff to make the loop faster
+                    my = axisy.c2p(mouseY),
+                    maxx = maxDistance / axisx.scale,
+                    maxy = maxDistance / axisy.scale;
+
+                // with inverse transforms, we can't use the maxx/maxy
+                // optimization, sadly
+                if (axisx.options.inverseTransform)
+                    maxx = Number.MAX_VALUE;
+                if (axisy.options.inverseTransform)
+                    maxy = Number.MAX_VALUE;
+
+                if (s.lines.show || s.points.show) {
+                    for (j = 0; j < points.length; j += ps) {
+                        var x = points[j], y = points[j + 1];
+                        if (x == null)
+                            continue;
+
+                        // For points and lines, the cursor must be within a
+                        // certain distance to the data point
+                        if (x - mx > maxx || x - mx < -maxx ||
+                            y - my > maxy || y - my < -maxy)
+                            continue;
+
+                        // We have to calculate distances in pixels, not in
+                        // data units, because the scales of the axes may be different
+                        var dx = Math.abs(axisx.p2c(x) - mouseX),
+                            dy = Math.abs(axisy.p2c(y) - mouseY),
+                            dist = dx * dx + dy * dy; // we save the sqrt
+
+                        // use <= to ensure last point takes precedence
+                        // (last generally means on top of)
+                        if (dist < smallestDistance) {
+                            smallestDistance = dist;
+                            item = [i, j / ps];
+                        }
+                    }
+                }
+
+                if (s.bars.show && !item) { // no other point can be nearby
+                    var barLeft = s.bars.align == "left" ? 0 : -s.bars.barWidth/2,
+                        barRight = barLeft + s.bars.barWidth;
+
+                    for (j = 0; j < points.length; j += ps) {
+                        var x = points[j], y = points[j + 1], b = points[j + 2];
+                        if (x == null)
+                            continue;
+
+                        // for a bar graph, the cursor must be inside the bar
+                        if (series[i].bars.horizontal ?
+                            (mx <= Math.max(b, x) && mx >= Math.min(b, x) &&
+                             my >= y + barLeft && my <= y + barRight) :
+                            (mx >= x + barLeft && mx <= x + barRight &&
+                             my >= Math.min(b, y) && my <= Math.max(b, y)))
+                                item = [i, j / ps];
+                    }
+                }
+            }
+
+            if (item) {
+                i = item[0];
+                j = item[1];
+                ps = series[i].datapoints.pointsize;
+
+                return { datapoint: series[i].datapoints.points.slice(j * ps, (j + 1) * ps),
+                         dataIndex: j,
+                         series: series[i],
+                         seriesIndex: i };
+            }
+
+            return null;
+        }
+
+        function onMouseMove(e) {
+            if (options.grid.hoverable)
+                triggerClickHoverEvent("plothover", e,
+                                       function (s) { return s["hoverable"] != false; });
+        }
+
+        function onMouseLeave(e) {
+            if (options.grid.hoverable)
+                triggerClickHoverEvent("plothover", e,
+                                       function (s) { return false; });
+        }
+
+        function onClick(e) {
+            triggerClickHoverEvent("plotclick", e,
+                                   function (s) { return s["clickable"] != false; });
+        }
+
+        // trigger click or hover event (they send the same parameters
+        // so we share their code)
+        function triggerClickHoverEvent(eventname, event, seriesFilter) {
+            var offset = eventHolder.offset(),
+                canvasX = event.pageX - offset.left - plotOffset.left,
+                canvasY = event.pageY - offset.top - plotOffset.top,
+            pos = canvasToAxisCoords({ left: canvasX, top: canvasY });
+
+            pos.pageX = event.pageX;
+            pos.pageY = event.pageY;
+
+            var item = findNearbyItem(canvasX, canvasY, seriesFilter);
+
+            if (item) {
+                // fill in mouse pos for any listeners out there
+                item.pageX = parseInt(item.series.xaxis.p2c(item.datapoint[0]) + offset.left + plotOffset.left);
+                item.pageY = parseInt(item.series.yaxis.p2c(item.datapoint[1]) + offset.top + plotOffset.top);
+            }
+
+            if (options.grid.autoHighlight) {
+                // clear auto-highlights
+                for (var i = 0; i < highlights.length; ++i) {
+                    var h = highlights[i];
+                    if (h.auto == eventname &&
+                        !(item && h.series == item.series &&
+                          h.point[0] == item.datapoint[0] &&
+                          h.point[1] == item.datapoint[1]))
+                        unhighlight(h.series, h.point);
+                }
+
+                if (item)
+                    highlight(item.series, item.datapoint, eventname);
+            }
+
+            placeholder.trigger(eventname, [ pos, item ]);
+        }
+
+        function triggerRedrawOverlay() {
+            if (!redrawTimeout)
+                redrawTimeout = setTimeout(drawOverlay, 30);
+        }
+
+        function drawOverlay() {
+            redrawTimeout = null;
+
+            // draw highlights
+            octx.save();
+            octx.clearRect(0, 0, canvasWidth, canvasHeight);
+            octx.translate(plotOffset.left, plotOffset.top);
+
+            var i, hi;
+            for (i = 0; i < highlights.length; ++i) {
+                hi = highlights[i];
+
+                if (hi.series.bars.show)
+                    drawBarHighlight(hi.series, hi.point);
+                else
+                    drawPointHighlight(hi.series, hi.point);
+            }
+            octx.restore();
+
+            executeHooks(hooks.drawOverlay, [octx]);
+        }
+
+        function highlight(s, point, auto) {
+            if (typeof s == "number")
+                s = series[s];
+
+            if (typeof point == "number") {
+                var ps = s.datapoints.pointsize;
+                point = s.datapoints.points.slice(ps * point, ps * (point + 1));
+            }
+
+            var i = indexOfHighlight(s, point);
+            if (i == -1) {
+                highlights.push({ series: s, point: point, auto: auto });
+
+                triggerRedrawOverlay();
+            }
+            else if (!auto)
+                highlights[i].auto = false;
+        }
+
+        function unhighlight(s, point) {
+            if (s == null && point == null) {
+                highlights = [];
+                triggerRedrawOverlay();
+            }
+
+            if (typeof s == "number")
+                s = series[s];
+
+            if (typeof point == "number")
+                point = s.data[point];
+
+            var i = indexOfHighlight(s, point);
+            if (i != -1) {
+                highlights.splice(i, 1);
+
+                triggerRedrawOverlay();
+            }
+        }
+
+        function indexOfHighlight(s, p) {
+            for (var i = 0; i < highlights.length; ++i) {
+                var h = highlights[i];
+                if (h.series == s && h.point[0] == p[0]
+                    && h.point[1] == p[1])
+                    return i;
+            }
+            return -1;
+        }
+
+        function drawPointHighlight(series, point) {
+            var x = point[0], y = point[1],
+                axisx = series.xaxis, axisy = series.yaxis;
+
+            if (x < axisx.min || x > axisx.max || y < axisy.min || y > axisy.max)
+                return;
+
+            var pointRadius = series.points.radius + series.points.lineWidth / 2;
+            octx.lineWidth = pointRadius;
+            octx.strokeStyle = $.color.parse(series.color).scale('a', 0.5).toString();
+            var radius = 1.5 * pointRadius,
+                x = axisx.p2c(x),
+                y = axisy.p2c(y);
+
+            octx.beginPath();
+            if (series.points.symbol == "circle")
+                octx.arc(x, y, radius, 0, 2 * Math.PI, false);
+            else
+                series.points.symbol(octx, x, y, radius, false);
+            octx.closePath();
+            octx.stroke();
+        }
+
+        function drawBarHighlight(series, point) {
+            octx.lineWidth = series.bars.lineWidth;
+            octx.strokeStyle = $.color.parse(series.color).scale('a', 0.5).toString();
+            var fillStyle = $.color.parse(series.color).scale('a', 0.5).toString();
+            var barLeft = series.bars.align == "left" ? 0 : -series.bars.barWidth/2;
+            drawBar(point[0], point[1], point[2] || 0, barLeft, barLeft + series.bars.barWidth,
+                    0, function () { return fillStyle; }, series.xaxis, series.yaxis, octx, series.bars.horizontal, series.bars.lineWidth);
+        }
+
+        function getColorOrGradient(spec, bottom, top, defaultColor) {
+            if (typeof spec == "string")
+                return spec;
+            else {
+                // assume this is a gradient spec; IE currently only
+                // supports a simple vertical gradient properly, so that's
+                // what we support too
+                var gradient = ctx.createLinearGradient(0, top, 0, bottom);
+
+                for (var i = 0, l = spec.colors.length; i < l; ++i) {
+                    var c = spec.colors[i];
+                    if (typeof c != "string") {
+                        var co = $.color.parse(defaultColor);
+                        if (c.brightness != null)
+                            co = co.scale('rgb', c.brightness)
+                        if (c.opacity != null)
+                            co.a *= c.opacity;
+                        c = co.toString();
+                    }
+                    gradient.addColorStop(i / (l - 1), c);
+                }
+
+                return gradient;
+            }
+        }
+    }
+
+    $.plot = function(placeholder, data, options) {
+        //var t0 = new Date();
+        var plot = new Plot($(placeholder), data, options, $.plot.plugins);
+        //(window.console ? console.log : alert)("time used (msecs): " + ((new Date()).getTime() - t0.getTime()));
+        return plot;
+    };
+
+    $.plot.version = "0.7";
+
+    $.plot.plugins = [];
+
+    // returns a string with the date d formatted according to fmt
+    $.plot.formatDate = function(d, fmt, monthNames) {
+        var leftPad = function(n) {
+            n = "" + n;
+            return n.length == 1 ? "0" + n : n;
+        };
+
+        var r = [];
+        var escape = false, padNext = false;
+        var hours = d.getUTCHours();
+        var isAM = hours < 12;
+        if (monthNames == null)
+            monthNames = ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"];
+
+        if (fmt.search(/%p|%P/) != -1) {
+            if (hours > 12) {
+                hours = hours - 12;
+            } else if (hours == 0) {
+                hours = 12;
+            }
+        }
+        for (var i = 0; i < fmt.length; ++i) {
+            var c = fmt.charAt(i);
+
+            if (escape) {
+                switch (c) {
+                case 'h': c = "" + hours; break;
+                case 'H': c = leftPad(hours); break;
+                case 'M': c = leftPad(d.getUTCMinutes()); break;
+                case 'S': c = leftPad(d.getUTCSeconds()); break;
+                case 'd': c = "" + d.getUTCDate(); break;
+                case 'm': c = "" + (d.getUTCMonth() + 1); break;
+                case 'y': c = "" + d.getUTCFullYear(); break;
+                case 'b': c = "" + monthNames[d.getUTCMonth()]; break;
+                case 'p': c = (isAM) ? ("" + "am") : ("" + "pm"); break;
+                case 'P': c = (isAM) ? ("" + "AM") : ("" + "PM"); break;
+                case '0': c = ""; padNext = true; break;
+                }
+                if (c && padNext) {
+                    c = leftPad(c);
+                    padNext = false;
+                }
+                r.push(c);
+                if (!padNext)
+                    escape = false;
+            }
+            else {
+                if (c == "%")
+                    escape = true;
+                else
+                    r.push(c);
+            }
+        }
+        return r.join("");
+    };
+
+    // round to nearby lower multiple of base
+    function floorInBase(n, base) {
+        return base * Math.floor(n / base);
+    }
+
+})(jQuery);
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/flot/jquery.flot.pie.js b/ruoyi-admin/src/main/resources/static/ajax/libs/flot/jquery.flot.pie.js
new file mode 100644
index 0000000..d7b603d
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/flot/jquery.flot.pie.js
@@ -0,0 +1,750 @@
+/*
+Flot plugin for rendering pie charts. The plugin assumes the data is
+coming is as a single data value for each series, and each of those
+values is a positive value or zero (negative numbers don't make
+any sense and will cause strange effects). The data values do
+NOT need to be passed in as percentage values because it
+internally calculates the total and percentages.
+
+* Created by Brian Medendorp, June 2009
+* Updated November 2009 with contributions from: btburnett3, Anthony Aragues and Xavi Ivars
+
+* Changes:
+	2009-10-22: lineJoin set to round
+	2009-10-23: IE full circle fix, donut
+	2009-11-11: Added basic hover from btburnett3 - does not work in IE, and center is off in Chrome and Opera
+	2009-11-17: Added IE hover capability submitted by Anthony Aragues
+	2009-11-18: Added bug fix submitted by Xavi Ivars (issues with arrays when other JS libraries are included as well)
+
+
+Available options are:
+series: {
+	pie: {
+		show: true/false
+		radius: 0-1 for percentage of fullsize, or a specified pixel length, or 'auto'
+		innerRadius: 0-1 for percentage of fullsize or a specified pixel length, for creating a donut effect
+		startAngle: 0-2 factor of PI used for starting angle (in radians) i.e 3/2 starts at the top, 0 and 2 have the same result
+		tilt: 0-1 for percentage to tilt the pie, where 1 is no tilt, and 0 is completely flat (nothing will show)
+		offset: {
+			top: integer value to move the pie up or down
+			left: integer value to move the pie left or right, or 'auto'
+		},
+		stroke: {
+			color: any hexidecimal color value (other formats may or may not work, so best to stick with something like '#FFF')
+			width: integer pixel width of the stroke
+		},
+		label: {
+			show: true/false, or 'auto'
+			formatter:  a user-defined function that modifies the text/style of the label text
+			radius: 0-1 for percentage of fullsize, or a specified pixel length
+			background: {
+				color: any hexidecimal color value (other formats may or may not work, so best to stick with something like '#000')
+				opacity: 0-1
+			},
+			threshold: 0-1 for the percentage value at which to hide labels (if they're too small)
+		},
+		combine: {
+			threshold: 0-1 for the percentage value at which to combine slices (if they're too small)
+			color: any hexidecimal color value (other formats may or may not work, so best to stick with something like '#CCC'), if null, the plugin will automatically use the color of the first slice to be combined
+			label: any text value of what the combined slice should be labeled
+		}
+		highlight: {
+			opacity: 0-1
+		}
+	}
+}
+
+More detail and specific examples can be found in the included HTML file.
+
+*/
+
+(function ($)
+{
+	function init(plot) // this is the "body" of the plugin
+	{
+		var canvas = null;
+		var target = null;
+		var maxRadius = null;
+		var centerLeft = null;
+		var centerTop = null;
+		var total = 0;
+		var redraw = true;
+		var redrawAttempts = 10;
+		var shrink = 0.95;
+		var legendWidth = 0;
+		var processed = false;
+		var raw = false;
+
+		// interactive variables
+		var highlights = [];
+
+		// add hook to determine if pie plugin in enabled, and then perform necessary operations
+		plot.hooks.processOptions.push(checkPieEnabled);
+		plot.hooks.bindEvents.push(bindEvents);
+
+		// check to see if the pie plugin is enabled
+		function checkPieEnabled(plot, options)
+		{
+			if (options.series.pie.show)
+			{
+				//disable grid
+				options.grid.show = false;
+
+				// set labels.show
+				if (options.series.pie.label.show=='auto')
+					if (options.legend.show)
+						options.series.pie.label.show = false;
+					else
+						options.series.pie.label.show = true;
+
+				// set radius
+				if (options.series.pie.radius=='auto')
+					if (options.series.pie.label.show)
+						options.series.pie.radius = 3/4;
+					else
+						options.series.pie.radius = 1;
+
+				// ensure sane tilt
+				if (options.series.pie.tilt>1)
+					options.series.pie.tilt=1;
+				if (options.series.pie.tilt<0)
+					options.series.pie.tilt=0;
+
+				// add processData hook to do transformations on the data
+				plot.hooks.processDatapoints.push(processDatapoints);
+				plot.hooks.drawOverlay.push(drawOverlay);
+
+				// add draw hook
+				plot.hooks.draw.push(draw);
+			}
+		}
+
+		// bind hoverable events
+		function bindEvents(plot, eventHolder)
+		{
+			var options = plot.getOptions();
+
+			if (options.series.pie.show && options.grid.hoverable)
+				eventHolder.unbind('mousemove').mousemove(onMouseMove);
+
+			if (options.series.pie.show && options.grid.clickable)
+				eventHolder.unbind('click').click(onClick);
+		}
+
+
+		// debugging function that prints out an object
+		function alertObject(obj)
+		{
+			var msg = '';
+			function traverse(obj, depth)
+			{
+				if (!depth)
+					depth = 0;
+				for (var i = 0; i < obj.length; ++i)
+				{
+					for (var j=0; j<depth; j++)
+						msg += '\t';
+
+					if( typeof obj[i] == "object")
+					{	// its an object
+						msg += ''+i+':\n';
+						traverse(obj[i], depth+1);
+					}
+					else
+					{	// its a value
+						msg += ''+i+': '+obj[i]+'\n';
+					}
+				}
+			}
+			traverse(obj);
+			alert(msg);
+		}
+
+		function calcTotal(data)
+		{
+			for (var i = 0; i < data.length; ++i)
+			{
+				var item = parseFloat(data[i].data[0][1]);
+				if (item)
+					total += item;
+			}
+		}
+
+		function processDatapoints(plot, series, data, datapoints)
+		{
+			if (!processed)
+			{
+				processed = true;
+
+				canvas = plot.getCanvas();
+				target = $(canvas).parent();
+				options = plot.getOptions();
+
+				plot.setData(combine(plot.getData()));
+			}
+		}
+
+		function setupPie()
+		{
+			legendWidth = target.children().filter('.legend').children().width();
+
+			// calculate maximum radius and center point
+			maxRadius =  Math.min(canvas.width,(canvas.height/options.series.pie.tilt))/2;
+			centerTop = (canvas.height/2)+options.series.pie.offset.top;
+			centerLeft = (canvas.width/2);
+
+			if (options.series.pie.offset.left=='auto')
+				if (options.legend.position.match('w'))
+					centerLeft += legendWidth/2;
+				else
+					centerLeft -= legendWidth/2;
+			else
+				centerLeft += options.series.pie.offset.left;
+
+			if (centerLeft<maxRadius)
+				centerLeft = maxRadius;
+			else if (centerLeft>canvas.width-maxRadius)
+				centerLeft = canvas.width-maxRadius;
+		}
+
+		function fixData(data)
+		{
+			for (var i = 0; i < data.length; ++i)
+			{
+				if (typeof(data[i].data)=='number')
+					data[i].data = [[1,data[i].data]];
+				else if (typeof(data[i].data)=='undefined' || typeof(data[i].data[0])=='undefined')
+				{
+					if (typeof(data[i].data)!='undefined' && typeof(data[i].data.label)!='undefined')
+						data[i].label = data[i].data.label; // fix weirdness coming from flot
+					data[i].data = [[1,0]];
+
+				}
+			}
+			return data;
+		}
+
+		function combine(data)
+		{
+			data = fixData(data);
+			calcTotal(data);
+			var combined = 0;
+			var numCombined = 0;
+			var color = options.series.pie.combine.color;
+
+			var newdata = [];
+			for (var i = 0; i < data.length; ++i)
+			{
+				// make sure its a number
+				data[i].data[0][1] = parseFloat(data[i].data[0][1]);
+				if (!data[i].data[0][1])
+					data[i].data[0][1] = 0;
+
+				if (data[i].data[0][1]/total<=options.series.pie.combine.threshold)
+				{
+					combined += data[i].data[0][1];
+					numCombined++;
+					if (!color)
+						color = data[i].color;
+				}
+				else
+				{
+					newdata.push({
+						data: [[1,data[i].data[0][1]]],
+						color: data[i].color,
+						label: data[i].label,
+						angle: (data[i].data[0][1]*(Math.PI*2))/total,
+						percent: (data[i].data[0][1]/total*100)
+					});
+				}
+			}
+			if (numCombined>0)
+				newdata.push({
+					data: [[1,combined]],
+					color: color,
+					label: options.series.pie.combine.label,
+					angle: (combined*(Math.PI*2))/total,
+					percent: (combined/total*100)
+				});
+			return newdata;
+		}
+
+		function draw(plot, newCtx)
+		{
+			if (!target) return; // if no series were passed
+			ctx = newCtx;
+
+			setupPie();
+			var slices = plot.getData();
+
+			var attempts = 0;
+			while (redraw && attempts<redrawAttempts)
+			{
+				redraw = false;
+				if (attempts>0)
+					maxRadius *= shrink;
+				attempts += 1;
+				clear();
+				if (options.series.pie.tilt<=0.8)
+					drawShadow();
+				drawPie();
+			}
+			if (attempts >= redrawAttempts) {
+				clear();
+				target.prepend('<div class="error">Could not draw pie with labels contained inside canvas</div>');
+			}
+
+			if ( plot.setSeries && plot.insertLegend )
+			{
+				plot.setSeries(slices);
+				plot.insertLegend();
+			}
+
+			// we're actually done at this point, just defining internal functions at this point
+
+			function clear()
+			{
+				ctx.clearRect(0,0,canvas.width,canvas.height);
+				target.children().filter('.pieLabel, .pieLabelBackground').remove();
+			}
+
+			function drawShadow()
+			{
+				var shadowLeft = 5;
+				var shadowTop = 15;
+				var edge = 10;
+				var alpha = 0.02;
+
+				// set radius
+				if (options.series.pie.radius>1)
+					var radius = options.series.pie.radius;
+				else
+					var radius = maxRadius * options.series.pie.radius;
+
+				if (radius>=(canvas.width/2)-shadowLeft || radius*options.series.pie.tilt>=(canvas.height/2)-shadowTop || radius<=edge)
+					return;	// shadow would be outside canvas, so don't draw it
+
+				ctx.save();
+				ctx.translate(shadowLeft,shadowTop);
+				ctx.globalAlpha = alpha;
+				ctx.fillStyle = '#000';
+
+				// center and rotate to starting position
+				ctx.translate(centerLeft,centerTop);
+				ctx.scale(1, options.series.pie.tilt);
+
+				//radius -= edge;
+				for (var i=1; i<=edge; i++)
+				{
+					ctx.beginPath();
+					ctx.arc(0,0,radius,0,Math.PI*2,false);
+					ctx.fill();
+					radius -= i;
+				}
+
+				ctx.restore();
+			}
+
+			function drawPie()
+			{
+				startAngle = Math.PI*options.series.pie.startAngle;
+
+				// set radius
+				if (options.series.pie.radius>1)
+					var radius = options.series.pie.radius;
+				else
+					var radius = maxRadius * options.series.pie.radius;
+
+				// center and rotate to starting position
+				ctx.save();
+				ctx.translate(centerLeft,centerTop);
+				ctx.scale(1, options.series.pie.tilt);
+				//ctx.rotate(startAngle); // start at top; -- This doesn't work properly in Opera
+
+				// draw slices
+				ctx.save();
+				var currentAngle = startAngle;
+				for (var i = 0; i < slices.length; ++i)
+				{
+					slices[i].startAngle = currentAngle;
+					drawSlice(slices[i].angle, slices[i].color, true);
+				}
+				ctx.restore();
+
+				// draw slice outlines
+				ctx.save();
+				ctx.lineWidth = options.series.pie.stroke.width;
+				currentAngle = startAngle;
+				for (var i = 0; i < slices.length; ++i)
+					drawSlice(slices[i].angle, options.series.pie.stroke.color, false);
+				ctx.restore();
+
+				// draw donut hole
+				drawDonutHole(ctx);
+
+				// draw labels
+				if (options.series.pie.label.show)
+					drawLabels();
+
+				// restore to original state
+				ctx.restore();
+
+				function drawSlice(angle, color, fill)
+				{
+					if (angle<=0)
+						return;
+
+					if (fill)
+						ctx.fillStyle = color;
+					else
+					{
+						ctx.strokeStyle = color;
+						ctx.lineJoin = 'round';
+					}
+
+					ctx.beginPath();
+					if (Math.abs(angle - Math.PI*2) > 0.000000001)
+						ctx.moveTo(0,0); // Center of the pie
+					else if ($.browser.msie)
+						angle -= 0.0001;
+					//ctx.arc(0,0,radius,0,angle,false); // This doesn't work properly in Opera
+					ctx.arc(0,0,radius,currentAngle,currentAngle+angle,false);
+					ctx.closePath();
+					//ctx.rotate(angle); // This doesn't work properly in Opera
+					currentAngle += angle;
+
+					if (fill)
+						ctx.fill();
+					else
+						ctx.stroke();
+				}
+
+				function drawLabels()
+				{
+					var currentAngle = startAngle;
+
+					// set radius
+					if (options.series.pie.label.radius>1)
+						var radius = options.series.pie.label.radius;
+					else
+						var radius = maxRadius * options.series.pie.label.radius;
+
+					for (var i = 0; i < slices.length; ++i)
+					{
+						if (slices[i].percent >= options.series.pie.label.threshold*100)
+							drawLabel(slices[i], currentAngle, i);
+						currentAngle += slices[i].angle;
+					}
+
+					function drawLabel(slice, startAngle, index)
+					{
+						if (slice.data[0][1]==0)
+							return;
+
+						// format label text
+						var lf = options.legend.labelFormatter, text, plf = options.series.pie.label.formatter;
+						if (lf)
+							text = lf(slice.label, slice);
+						else
+							text = slice.label;
+						if (plf)
+							text = plf(text, slice);
+
+						var halfAngle = ((startAngle+slice.angle) + startAngle)/2;
+						var x = centerLeft + Math.round(Math.cos(halfAngle) * radius);
+						var y = centerTop + Math.round(Math.sin(halfAngle) * radius) * options.series.pie.tilt;
+
+						var html = '<span class="pieLabel" id="pieLabel'+index+'" style="position:absolute;top:' + y + 'px;left:' + x + 'px;">' + text + "</span>";
+						target.append(html);
+						var label = target.children('#pieLabel'+index);
+						var labelTop = (y - label.height()/2);
+						var labelLeft = (x - label.width()/2);
+						label.css('top', labelTop);
+						label.css('left', labelLeft);
+
+						// check to make sure that the label is not outside the canvas
+						if (0-labelTop>0 || 0-labelLeft>0 || canvas.height-(labelTop+label.height())<0 || canvas.width-(labelLeft+label.width())<0)
+							redraw = true;
+
+						if (options.series.pie.label.background.opacity != 0) {
+							// put in the transparent background separately to avoid blended labels and label boxes
+							var c = options.series.pie.label.background.color;
+							if (c == null) {
+								c = slice.color;
+							}
+							var pos = 'top:'+labelTop+'px;left:'+labelLeft+'px;';
+							$('<div class="pieLabelBackground" style="position:absolute;width:' + label.width() + 'px;height:' + label.height() + 'px;' + pos +'background-color:' + c + ';"> </div>').insertBefore(label).css('opacity', options.series.pie.label.background.opacity);
+						}
+					} // end individual label function
+				} // end drawLabels function
+			} // end drawPie function
+		} // end draw function
+
+		// Placed here because it needs to be accessed from multiple locations
+		function drawDonutHole(layer)
+		{
+			// draw donut hole
+			if(options.series.pie.innerRadius > 0)
+			{
+				// subtract the center
+				layer.save();
+				innerRadius = options.series.pie.innerRadius > 1 ? options.series.pie.innerRadius : maxRadius * options.series.pie.innerRadius;
+				layer.globalCompositeOperation = 'destination-out'; // this does not work with excanvas, but it will fall back to using the stroke color
+				layer.beginPath();
+				layer.fillStyle = options.series.pie.stroke.color;
+				layer.arc(0,0,innerRadius,0,Math.PI*2,false);
+				layer.fill();
+				layer.closePath();
+				layer.restore();
+
+				// add inner stroke
+				layer.save();
+				layer.beginPath();
+				layer.strokeStyle = options.series.pie.stroke.color;
+				layer.arc(0,0,innerRadius,0,Math.PI*2,false);
+				layer.stroke();
+				layer.closePath();
+				layer.restore();
+				// TODO: add extra shadow inside hole (with a mask) if the pie is tilted.
+			}
+		}
+
+		//-- Additional Interactive related functions --
+
+		function isPointInPoly(poly, pt)
+		{
+			for(var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i)
+				((poly[i][1] <= pt[1] && pt[1] < poly[j][1]) || (poly[j][1] <= pt[1] && pt[1]< poly[i][1]))
+				&& (pt[0] < (poly[j][0] - poly[i][0]) * (pt[1] - poly[i][1]) / (poly[j][1] - poly[i][1]) + poly[i][0])
+				&& (c = !c);
+			return c;
+		}
+
+		function findNearbySlice(mouseX, mouseY)
+		{
+			var slices = plot.getData(),
+				options = plot.getOptions(),
+				radius = options.series.pie.radius > 1 ? options.series.pie.radius : maxRadius * options.series.pie.radius;
+
+			for (var i = 0; i < slices.length; ++i)
+			{
+				var s = slices[i];
+
+				if(s.pie.show)
+				{
+					ctx.save();
+					ctx.beginPath();
+					ctx.moveTo(0,0); // Center of the pie
+					//ctx.scale(1, options.series.pie.tilt);	// this actually seems to break everything when here.
+					ctx.arc(0,0,radius,s.startAngle,s.startAngle+s.angle,false);
+					ctx.closePath();
+					x = mouseX-centerLeft;
+					y = mouseY-centerTop;
+					if(ctx.isPointInPath)
+					{
+						if (ctx.isPointInPath(mouseX-centerLeft, mouseY-centerTop))
+						{
+							//alert('found slice!');
+							ctx.restore();
+							return {datapoint: [s.percent, s.data], dataIndex: 0, series: s, seriesIndex: i};
+						}
+					}
+					else
+					{
+						// excanvas for IE doesn;t support isPointInPath, this is a workaround.
+						p1X = (radius * Math.cos(s.startAngle));
+						p1Y = (radius * Math.sin(s.startAngle));
+						p2X = (radius * Math.cos(s.startAngle+(s.angle/4)));
+						p2Y = (radius * Math.sin(s.startAngle+(s.angle/4)));
+						p3X = (radius * Math.cos(s.startAngle+(s.angle/2)));
+						p3Y = (radius * Math.sin(s.startAngle+(s.angle/2)));
+						p4X = (radius * Math.cos(s.startAngle+(s.angle/1.5)));
+						p4Y = (radius * Math.sin(s.startAngle+(s.angle/1.5)));
+						p5X = (radius * Math.cos(s.startAngle+s.angle));
+						p5Y = (radius * Math.sin(s.startAngle+s.angle));
+						arrPoly = [[0,0],[p1X,p1Y],[p2X,p2Y],[p3X,p3Y],[p4X,p4Y],[p5X,p5Y]];
+						arrPoint = [x,y];
+						// TODO: perhaps do some mathmatical trickery here with the Y-coordinate to compensate for pie tilt?
+						if(isPointInPoly(arrPoly, arrPoint))
+						{
+							ctx.restore();
+							return {datapoint: [s.percent, s.data], dataIndex: 0, series: s, seriesIndex: i};
+						}
+					}
+					ctx.restore();
+				}
+			}
+
+			return null;
+		}
+
+		function onMouseMove(e)
+		{
+			triggerClickHoverEvent('plothover', e);
+		}
+
+        function onClick(e)
+		{
+			triggerClickHoverEvent('plotclick', e);
+        }
+
+		// trigger click or hover event (they send the same parameters so we share their code)
+		function triggerClickHoverEvent(eventname, e)
+		{
+			var offset = plot.offset(),
+				canvasX = parseInt(e.pageX - offset.left),
+				canvasY =  parseInt(e.pageY - offset.top),
+				item = findNearbySlice(canvasX, canvasY);
+
+			if (options.grid.autoHighlight)
+			{
+				// clear auto-highlights
+				for (var i = 0; i < highlights.length; ++i)
+				{
+					var h = highlights[i];
+					if (h.auto == eventname && !(item && h.series == item.series))
+						unhighlight(h.series);
+				}
+			}
+
+			// highlight the slice
+			if (item)
+			    highlight(item.series, eventname);
+
+			// trigger any hover bind events
+			var pos = { pageX: e.pageX, pageY: e.pageY };
+			target.trigger(eventname, [ pos, item ]);
+		}
+
+		function highlight(s, auto)
+		{
+			if (typeof s == "number")
+				s = series[s];
+
+			var i = indexOfHighlight(s);
+			if (i == -1)
+			{
+				highlights.push({ series: s, auto: auto });
+				plot.triggerRedrawOverlay();
+			}
+			else if (!auto)
+				highlights[i].auto = false;
+		}
+
+		function unhighlight(s)
+		{
+			if (s == null)
+			{
+				highlights = [];
+				plot.triggerRedrawOverlay();
+			}
+
+			if (typeof s == "number")
+				s = series[s];
+
+			var i = indexOfHighlight(s);
+			if (i != -1)
+			{
+				highlights.splice(i, 1);
+				plot.triggerRedrawOverlay();
+			}
+		}
+
+		function indexOfHighlight(s)
+		{
+			for (var i = 0; i < highlights.length; ++i)
+			{
+				var h = highlights[i];
+				if (h.series == s)
+					return i;
+			}
+			return -1;
+		}
+
+		function drawOverlay(plot, octx)
+		{
+			//alert(options.series.pie.radius);
+			var options = plot.getOptions();
+			//alert(options.series.pie.radius);
+
+			var radius = options.series.pie.radius > 1 ? options.series.pie.radius : maxRadius * options.series.pie.radius;
+
+			octx.save();
+			octx.translate(centerLeft, centerTop);
+			octx.scale(1, options.series.pie.tilt);
+
+			for (i = 0; i < highlights.length; ++i)
+				drawHighlight(highlights[i].series);
+
+			drawDonutHole(octx);
+
+			octx.restore();
+
+			function drawHighlight(series)
+			{
+				if (series.angle < 0) return;
+
+				//octx.fillStyle = parseColor(options.series.pie.highlight.color).scale(null, null, null, options.series.pie.highlight.opacity).toString();
+				octx.fillStyle = "rgba(255, 255, 255, "+options.series.pie.highlight.opacity+")"; // this is temporary until we have access to parseColor
+
+				octx.beginPath();
+				if (Math.abs(series.angle - Math.PI*2) > 0.000000001)
+					octx.moveTo(0,0); // Center of the pie
+				octx.arc(0,0,radius,series.startAngle,series.startAngle+series.angle,false);
+				octx.closePath();
+				octx.fill();
+			}
+
+		}
+
+	} // end init (plugin body)
+
+	// define pie specific options and their default values
+	var options = {
+		series: {
+			pie: {
+				show: false,
+				radius: 'auto',	// actual radius of the visible pie (based on full calculated radius if <=1, or hard pixel value)
+				innerRadius:0, /* for donut */
+				startAngle: 3/2,
+				tilt: 1,
+				offset: {
+					top: 0,
+					left: 'auto'
+				},
+				stroke: {
+					color: '#FFF',
+					width: 1
+				},
+				label: {
+					show: 'auto',
+					formatter: function(label, slice){
+						return '<div style="font-size:x-small;text-align:center;padding:2px;color:'+slice.color+';">'+label+'<br/>'+Math.round(slice.percent)+'%</div>';
+					},	// formatter function
+					radius: 1,	// radius at which to place the labels (based on full calculated radius if <=1, or hard pixel value)
+					background: {
+						color: null,
+						opacity: 0
+					},
+					threshold: 0	// percentage at which to hide the label (i.e. the slice is too narrow)
+				},
+				combine: {
+					threshold: -1,	// percentage at which to combine little slices into one larger slice
+					color: null,	// color to give the new slice (auto-generated if null)
+					label: 'Other'	// label to give the new slice
+				},
+				highlight: {
+					//color: '#FFF',		// will add this functionality once parseColor is available
+					opacity: 0.5
+				}
+			}
+		}
+	};
+
+	$.plot.plugins.push({
+		init: init,
+		options: options,
+		name: "pie",
+		version: "1.0"
+	});
+})(jQuery);
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/flot/jquery.flot.resize.js b/ruoyi-admin/src/main/resources/static/ajax/libs/flot/jquery.flot.resize.js
new file mode 100644
index 0000000..3276243
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/flot/jquery.flot.resize.js
@@ -0,0 +1,60 @@
+/* Flot plugin for automatically redrawing plots as the placeholder resizes.
+
+Copyright (c) 2007-2013 IOLA and Ole Laursen.
+Licensed under the MIT license.
+
+It works by listening for changes on the placeholder div (through the jQuery
+resize event plugin) - if the size changes, it will redraw the plot.
+
+There are no options. If you need to disable the plugin for some plots, you
+can just fix the size of their placeholders.
+
+*/
+
+/* Inline dependency:
+ * jQuery resize event - v1.1 - 3/14/2010
+ * http://benalman.com/projects/jquery-resize-plugin/
+ *
+ * Copyright (c) 2010 "Cowboy" Ben Alman
+ * Dual licensed under the MIT and GPL licenses.
+ * http://benalman.com/about/license/
+ */
+
+(function($,h,c){var a=$([]),e=$.resize=$.extend($.resize,{}),i,k="setTimeout",j="resize",d=j+"-special-event",b="delay",f="throttleWindow";e[b]=250;e[f]=true;$.event.special[j]={setup:function(){if(!e[f]&&this[k]){return false}var l=$(this);a=a.add(l);$.data(this,d,{w:l.width(),h:l.height()});if(a.length===1){g()}},teardown:function(){if(!e[f]&&this[k]){return false}var l=$(this);a=a.not(l);l.removeData(d);if(!a.length){clearTimeout(i)}},add:function(l){if(!e[f]&&this[k]){return false}var n;function m(s,o,p){var q=$(this),r=$.data(this,d);r.w=o!==c?o:q.width();r.h=p!==c?p:q.height();n.apply(this,arguments)}if($.isFunction(l)){n=l;return m}else{n=l.handler;l.handler=m}}};function g(){i=h[k](function(){a.each(function(){var n=$(this),m=n.width(),l=n.height(),o=$.data(this,d);if(m!==o.w||l!==o.h){n.trigger(j,[o.w=m,o.h=l])}});g()},e[b])}})(jQuery,this);
+
+(function ($) {
+    var options = { }; // no options
+
+    function init(plot) {
+        function onResize() {
+            var placeholder = plot.getPlaceholder();
+
+            // somebody might have hidden us and we can't plot
+            // when we don't have the dimensions
+            if (placeholder.width() == 0 || placeholder.height() == 0)
+                return;
+
+            plot.resize();
+            plot.setupGrid();
+            plot.draw();
+        }
+
+        function bindEvents(plot, eventHolder) {
+            plot.getPlaceholder().resize(onResize);
+        }
+
+        function shutdown(plot, eventHolder) {
+            plot.getPlaceholder().unbind("resize", onResize);
+        }
+
+        plot.hooks.bindEvents.push(bindEvents);
+        plot.hooks.shutdown.push(shutdown);
+    }
+
+    $.plot.plugins.push({
+        init: init,
+        options: options,
+        name: 'resize',
+        version: '1.0'
+    });
+})(jQuery);
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/flot/jquery.flot.spline.js b/ruoyi-admin/src/main/resources/static/ajax/libs/flot/jquery.flot.spline.js
new file mode 100644
index 0000000..bc16f48
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/flot/jquery.flot.spline.js
@@ -0,0 +1,212 @@
+/**
+ * Flot plugin that provides spline interpolation for line graphs
+ * author: Alex Bardas < alex.bardas@gmail.com >
+ * modified by: Avi Kohn https://github.com/AMKohn
+ * based on the spline interpolation described at:
+ *		 http://scaledinnovation.com/analytics/splines/aboutSplines.html
+ *
+ * Example usage: (add in plot options series object)
+ *		for linespline:
+ *			series: {
+ *				...
+ *				lines: {
+ *					show: false
+ *				},
+ *				splines: {
+ *					show: true,
+ *					tension: x, (float between 0 and 1, defaults to 0.5),
+ *					lineWidth: y (number, defaults to 2),
+ *					fill: z (float between 0 .. 1 or false, as in flot documentation)
+ *				},
+ *				...
+ *			}
+ *		areaspline:
+ *			series: {
+ *				...
+ *				lines: {
+ *					show: true,
+ *					lineWidth: 0, (line drawing will not execute)
+ *					fill: x, (float between 0 .. 1, as in flot documentation)
+ *					...
+ *				},
+ *				splines: {
+ *					show: true,
+ *					tension: 0.5 (float between 0 and 1)
+ *				},
+ *				...
+ *			}
+ *
+ */
+
+(function($) {
+    'use strict'
+
+    /**
+     * @param {Number} x0, y0, x1, y1: coordinates of the end (knot) points of the segment
+     * @param {Number} x2, y2: the next knot (not connected, but needed to calculate p2)
+     * @param {Number} tension: control how far the control points spread
+     * @return {Array}: p1 -> control point, from x1 back toward x0
+     * 					p2 -> the next control point, returned to become the next segment's p1
+     *
+     * @api private
+     */
+    function getControlPoints(x0, y0, x1, y1, x2, y2, tension) {
+
+        var pow = Math.pow,
+            sqrt = Math.sqrt,
+            d01, d12, fa, fb, p1x, p1y, p2x, p2y;
+
+        //  Scaling factors: distances from this knot to the previous and following knots.
+        d01 = sqrt(pow(x1 - x0, 2) + pow(y1 - y0, 2));
+        d12 = sqrt(pow(x2 - x1, 2) + pow(y2 - y1, 2));
+
+        fa = tension * d01 / (d01 + d12);
+        fb = tension - fa;
+
+        p1x = x1 + fa * (x0 - x2);
+        p1y = y1 + fa * (y0 - y2);
+
+        p2x = x1 - fb * (x0 - x2);
+        p2y = y1 - fb * (y0 - y2);
+
+        return [p1x, p1y, p2x, p2y];
+    }
+
+    var line = [];
+
+    function drawLine(points, ctx, height, fill, seriesColor) {
+        var c = $.color.parse(seriesColor);
+
+        c.a = typeof fill == "number" ? fill : .3;
+        c.normalize();
+        c = c.toString();
+
+        ctx.beginPath();
+        ctx.moveTo(points[0][0], points[0][1]);
+
+        var plength = points.length;
+
+        for (var i = 0; i < plength; i++) {
+            ctx[points[i][3]].apply(ctx, points[i][2]);
+        }
+
+        ctx.stroke();
+
+        ctx.lineWidth = 0;
+        ctx.lineTo(points[plength - 1][0], height);
+        ctx.lineTo(points[0][0], height);
+
+        ctx.closePath();
+
+        if (fill !== false) {
+            ctx.fillStyle = c;
+            ctx.fill();
+        }
+    }
+
+    /**
+     * @param {Object} ctx: canvas context
+     * @param {String} type: accepted strings: 'bezier' or 'quadratic' (defaults to quadratic)
+     * @param {Array} points: 2 points for which to draw the interpolation
+     * @param {Array} cpoints: control points for those segment points
+     *
+     * @api private
+     */
+    function queue(ctx, type, points, cpoints) {
+        if (type === void 0 || (type !== 'bezier' && type !== 'quadratic')) {
+            type = 'quadratic';
+        }
+        type = type + 'CurveTo';
+
+        if (line.length == 0) line.push([points[0], points[1], cpoints.concat(points.slice(2)), type]);
+        else if (type == "quadraticCurveTo" && points.length == 2) {
+            cpoints = cpoints.slice(0, 2).concat(points);
+
+            line.push([points[0], points[1], cpoints, type]);
+        }
+        else line.push([points[2], points[3], cpoints.concat(points.slice(2)), type]);
+    }
+
+    /**
+     * @param {Object} plot
+     * @param {Object} ctx: canvas context
+     * @param {Object} series
+     *
+     * @api private
+     */
+
+    function drawSpline(plot, ctx, series) {
+        // Not interested if spline is not requested
+        if (series.splines.show !== true) {
+            return;
+        }
+
+        var cp = [],
+        // array of control points
+            tension = series.splines.tension || 0.5,
+            idx, x, y, points = series.datapoints.points,
+            ps = series.datapoints.pointsize,
+            plotOffset = plot.getPlotOffset(),
+            len = points.length,
+            pts = [];
+
+        line = [];
+
+        // Cannot display a linespline/areaspline if there are less than 3 points
+        if (len / ps < 4) {
+            $.extend(series.lines, series.splines);
+            return;
+        }
+
+        for (idx = 0; idx < len; idx += ps) {
+            x = points[idx];
+            y = points[idx + 1];
+            if (x == null || x < series.xaxis.min || x > series.xaxis.max || y < series.yaxis.min || y > series.yaxis.max) {
+                continue;
+            }
+
+            pts.push(series.xaxis.p2c(x) + plotOffset.left, series.yaxis.p2c(y) + plotOffset.top);
+        }
+
+        len = pts.length;
+
+        // Draw an open curve, not connected at the ends
+        for (idx = 0; idx < len - 2; idx += 2) {
+            cp = cp.concat(getControlPoints.apply(this, pts.slice(idx, idx + 6).concat([tension])));
+        }
+
+        ctx.save();
+        ctx.strokeStyle = series.color;
+        ctx.lineWidth = series.splines.lineWidth;
+
+        queue(ctx, 'quadratic', pts.slice(0, 4), cp.slice(0, 2));
+
+        for (idx = 2; idx < len - 3; idx += 2) {
+            queue(ctx, 'bezier', pts.slice(idx, idx + 4), cp.slice(2 * idx - 2, 2 * idx + 2));
+        }
+
+        queue(ctx, 'quadratic', pts.slice(len - 2, len), [cp[2 * len - 10], cp[2 * len - 9], pts[len - 4], pts[len - 3]]);
+
+        drawLine(line, ctx, plot.height() + 10, series.splines.fill, series.color);
+
+        ctx.restore();
+    }
+
+    $.plot.plugins.push({
+        init: function(plot) {
+            plot.hooks.drawSeries.push(drawSpline);
+        },
+        options: {
+            series: {
+                splines: {
+                    show: false,
+                    lineWidth: 2,
+                    tension: 0.5,
+                    fill: false
+                }
+            }
+        },
+        name: 'spline',
+        version: '0.8.2'
+    });
+})(jQuery);
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/flot/jquery.flot.symbol.js b/ruoyi-admin/src/main/resources/static/ajax/libs/flot/jquery.flot.symbol.js
new file mode 100644
index 0000000..f2464ec
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/flot/jquery.flot.symbol.js
@@ -0,0 +1,71 @@
+/* Flot plugin that adds some extra symbols for plotting points.
+
+ Copyright (c) 2007-2014 IOLA and Ole Laursen.
+ Licensed under the MIT license.
+
+ The symbols are accessed as strings through the standard symbol options:
+
+ series: {
+ points: {
+ symbol: "square" // or "diamond", "triangle", "cross"
+ }
+ }
+
+ */
+
+(function ($) {
+    function processRawData(plot, series, datapoints) {
+        // we normalize the area of each symbol so it is approximately the
+        // same as a circle of the given radius
+
+        var handlers = {
+            square: function (ctx, x, y, radius, shadow) {
+                // pi * r^2 = (2s)^2  =>  s = r * sqrt(pi)/2
+                var size = radius * Math.sqrt(Math.PI) / 2;
+                ctx.rect(x - size, y - size, size + size, size + size);
+            },
+            diamond: function (ctx, x, y, radius, shadow) {
+                // pi * r^2 = 2s^2  =>  s = r * sqrt(pi/2)
+                var size = radius * Math.sqrt(Math.PI / 2);
+                ctx.moveTo(x - size, y);
+                ctx.lineTo(x, y - size);
+                ctx.lineTo(x + size, y);
+                ctx.lineTo(x, y + size);
+                ctx.lineTo(x - size, y);
+            },
+            triangle: function (ctx, x, y, radius, shadow) {
+                // pi * r^2 = 1/2 * s^2 * sin (pi / 3)  =>  s = r * sqrt(2 * pi / sin(pi / 3))
+                var size = radius * Math.sqrt(2 * Math.PI / Math.sin(Math.PI / 3));
+                var height = size * Math.sin(Math.PI / 3);
+                ctx.moveTo(x - size/2, y + height/2);
+                ctx.lineTo(x + size/2, y + height/2);
+                if (!shadow) {
+                    ctx.lineTo(x, y - height/2);
+                    ctx.lineTo(x - size/2, y + height/2);
+                }
+            },
+            cross: function (ctx, x, y, radius, shadow) {
+                // pi * r^2 = (2s)^2  =>  s = r * sqrt(pi)/2
+                var size = radius * Math.sqrt(Math.PI) / 2;
+                ctx.moveTo(x - size, y - size);
+                ctx.lineTo(x + size, y + size);
+                ctx.moveTo(x - size, y + size);
+                ctx.lineTo(x + size, y - size);
+            }
+        };
+
+        var s = series.points.symbol;
+        if (handlers[s])
+            series.points.symbol = handlers[s];
+    }
+
+    function init(plot) {
+        plot.hooks.processDatapoints.push(processRawData);
+    }
+
+    $.plot.plugins.push({
+        init: init,
+        name: 'symbols',
+        version: '1.0'
+    });
+})(jQuery);
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/flot/jquery.flot.tooltip.min.js b/ruoyi-admin/src/main/resources/static/ajax/libs/flot/jquery.flot.tooltip.min.js
new file mode 100644
index 0000000..57d9667
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/flot/jquery.flot.tooltip.min.js
@@ -0,0 +1,12 @@
+/*
+ * jquery.flot.tooltip
+ *
+ * description: easy-to-use tooltips for Flot charts
+ * version: 0.6.2
+ * author: Krzysztof Urbas @krzysu [myviews.pl]
+ * website: https://github.com/krzysu/flot.tooltip
+ *
+ * build on 2013-09-30
+ * released under MIT License, 2012
+*/
+(function(t){var o={tooltip:!1,tooltipOpts:{content:"%s | X: %x | Y: %y",xDateFormat:null,yDateFormat:null,shifts:{x:10,y:20},defaultTheme:!0,onHover:function(){}}},i=function(t){this.tipPosition={x:0,y:0},this.init(t)};i.prototype.init=function(o){function i(t){var o={};o.x=t.pageX,o.y=t.pageY,s.updateTooltipPosition(o)}function e(t,o,i){var e=s.getDomElement();if(i){var n;n=s.stringFormat(s.tooltipOptions.content,i),e.html(n),s.updateTooltipPosition({x:o.pageX,y:o.pageY}),e.css({left:s.tipPosition.x+s.tooltipOptions.shifts.x,top:s.tipPosition.y+s.tooltipOptions.shifts.y}).show(),"function"==typeof s.tooltipOptions.onHover&&s.tooltipOptions.onHover(i,e)}else e.hide().html("")}var s=this;o.hooks.bindEvents.push(function(o,n){s.plotOptions=o.getOptions(),s.plotOptions.tooltip!==!1&&void 0!==s.plotOptions.tooltip&&(s.tooltipOptions=s.plotOptions.tooltipOpts,s.getDomElement(),t(o.getPlaceholder()).bind("plothover",e),t(n).bind("mousemove",i))}),o.hooks.shutdown.push(function(o,s){t(o.getPlaceholder()).unbind("plothover",e),t(s).unbind("mousemove",i)})},i.prototype.getDomElement=function(){var o;return t("#flotTip").length>0?o=t("#flotTip"):(o=t("<div />").attr("id","flotTip"),o.appendTo("body").hide().css({position:"absolute"}),this.tooltipOptions.defaultTheme&&o.css({background:"#fff","z-index":"100",padding:"0.4em 0.6em","border-radius":"0.5em","font-size":"0.8em",border:"1px solid #111",display:"none","white-space":"nowrap"})),o},i.prototype.updateTooltipPosition=function(o){var i=t("#flotTip").outerWidth()+this.tooltipOptions.shifts.x,e=t("#flotTip").outerHeight()+this.tooltipOptions.shifts.y;o.x-t(window).scrollLeft()>t(window).innerWidth()-i&&(o.x-=i),o.y-t(window).scrollTop()>t(window).innerHeight()-e&&(o.y-=e),this.tipPosition.x=o.x,this.tipPosition.y=o.y},i.prototype.stringFormat=function(t,o){var i=/%p\.{0,1}(\d{0,})/,e=/%s/,s=/%x\.{0,1}(?:\d{0,})/,n=/%y\.{0,1}(?:\d{0,})/;return"function"==typeof t&&(t=t(o.series.label,o.series.data[o.dataIndex][0],o.series.data[o.dataIndex][1],o)),o.series.percent!==void 0&&(t=this.adjustValPrecision(i,t,o.series.percent)),o.series.label!==void 0&&(t=t.replace(e,o.series.label)),this.isTimeMode("xaxis",o)&&this.isXDateFormat(o)&&(t=t.replace(s,this.timestampToDate(o.series.data[o.dataIndex][0],this.tooltipOptions.xDateFormat))),this.isTimeMode("yaxis",o)&&this.isYDateFormat(o)&&(t=t.replace(n,this.timestampToDate(o.series.data[o.dataIndex][1],this.tooltipOptions.yDateFormat))),"number"==typeof o.series.data[o.dataIndex][0]&&(t=this.adjustValPrecision(s,t,o.series.data[o.dataIndex][0])),"number"==typeof o.series.data[o.dataIndex][1]&&(t=this.adjustValPrecision(n,t,o.series.data[o.dataIndex][1])),o.series.xaxis.tickFormatter!==void 0&&(t=t.replace(s,o.series.xaxis.tickFormatter(o.series.data[o.dataIndex][0],o.series.xaxis))),o.series.yaxis.tickFormatter!==void 0&&(t=t.replace(n,o.series.yaxis.tickFormatter(o.series.data[o.dataIndex][1],o.series.yaxis))),t},i.prototype.isTimeMode=function(t,o){return o.series[t].options.mode!==void 0&&"time"===o.series[t].options.mode},i.prototype.isXDateFormat=function(){return this.tooltipOptions.xDateFormat!==void 0&&null!==this.tooltipOptions.xDateFormat},i.prototype.isYDateFormat=function(){return this.tooltipOptions.yDateFormat!==void 0&&null!==this.tooltipOptions.yDateFormat},i.prototype.timestampToDate=function(o,i){var e=new Date(o);return t.plot.formatDate(e,i)},i.prototype.adjustValPrecision=function(t,o,i){var e,s=o.match(t);return null!==s&&""!==RegExp.$1&&(e=RegExp.$1,i=i.toFixed(e),o=o.replace(t,i)),o};var e=function(t){new i(t)};t.plot.plugins.push({init:e,options:o,name:"tooltip",version:"0.6.1"})})(jQuery);
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/fullscreen/jquery.fullscreen.js b/ruoyi-admin/src/main/resources/static/ajax/libs/fullscreen/jquery.fullscreen.js
new file mode 100644
index 0000000..aeac349
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/fullscreen/jquery.fullscreen.js
@@ -0,0 +1,182 @@
+/**
+ * 基于jQuery FullScreen修改
+ * 新增支持IE全屏显示
+ * Copyright (c) 2019 ruoyi
+ */
+(function(jQuery) {
+    
+    /**
+     * Sets or gets the fullscreen state.
+     * 
+     * @param {boolean=} state
+     *            True to enable fullscreen mode, false to disable it. If not
+     *            specified then the current fullscreen state is returned.
+     * @return {boolean|Element|jQuery|null}
+     *            When querying the fullscreen state then the current fullscreen
+     *            element (or true if browser doesn't support it) is returned
+     *            when browser is currently in full screen mode. False is returned
+     *            if browser is not in full screen mode. Null is returned if 
+     *            browser doesn't support fullscreen mode at all. When setting 
+     *            the fullscreen state then the current jQuery selection is 
+     *            returned for chaining.
+     * @this {jQuery}
+     */
+    function fullScreen(state)
+    {
+        var e, func, doc;
+        
+        // Do nothing when nothing was selected
+        if (!this.length) return this;
+        
+        // We only use the first selected element because it doesn't make sense
+        // to fullscreen multiple elements.
+        e = (/** @type {Element} */ this[0]);
+        
+        // Find the real element and the document (Depends on whether the
+        // document itself or a HTML element was selected)
+        if (e.ownerDocument)
+        {
+            doc = e.ownerDocument;
+        }
+        else
+        {
+            doc = e;
+            e = doc.documentElement;
+        }
+        
+        // When no state was specified then return the current state.
+        if (state == null)
+        {
+            // When fullscreen mode is not supported then return null
+            if (!((/** @type {?Function} */ doc["exitFullscreen"])
+                || (/** @type {?Function} */ doc["webkitExitFullscreen"])
+                || (/** @type {?Function} */ doc["webkitCancelFullScreen"])
+                || (/** @type {?Function} */ doc["msExitFullscreen"])
+                || (/** @type {?Function} */ doc["mozCancelFullScreen"])))
+            {
+                return null;
+            }
+            
+            // Check fullscreen state
+            state = !!doc["fullscreenElement"]
+                || !!doc["msFullscreenElement"]
+                || !!doc["webkitIsFullScreen"]
+                || !!doc["mozFullScreen"];
+            if (!state) return state;
+            
+            // Return current fullscreen element or "true" if browser doesn't
+            // support this
+            return (/** @type {?Element} */ doc["fullscreenElement"])
+                || (/** @type {?Element} */ doc["webkitFullscreenElement"])
+                || (/** @type {?Element} */ doc["webkitCurrentFullScreenElement"])
+                || (/** @type {?Element} */ doc["msFullscreenElement"])
+                || (/** @type {?Element} */ doc["mozFullScreenElement"])
+                || state;
+        }
+        
+        // When state was specified then enter or exit fullscreen mode.
+        if (state)
+        {
+            // Enter fullscreen
+            func = (/** @type {?Function} */ e["requestFullscreen"])
+                || (/** @type {?Function} */ e["webkitRequestFullscreen"])
+                || (/** @type {?Function} */ e["webkitRequestFullScreen"])
+                || (/** @type {?Function} */ e["msRequestFullscreen"])
+                || (/** @type {?Function} */ e["mozRequestFullScreen"]);
+            if (func) 
+            {
+                func.call(e);
+            }
+            return this;
+        }
+        else
+        {
+            // Exit fullscreen
+            func = (/** @type {?Function} */ doc["exitFullscreen"])
+                || (/** @type {?Function} */ doc["webkitExitFullscreen"])
+                || (/** @type {?Function} */ doc["webkitCancelFullScreen"])
+                || (/** @type {?Function} */ doc["msExitFullscreen"])
+                || (/** @type {?Function} */ doc["mozCancelFullScreen"]);
+            if (func) func.call(doc);
+            return this;
+        }
+    }
+    
+    /**
+     * Toggles the fullscreen mode.
+     * 
+     * @return {!jQuery}
+     *            The jQuery selection for chaining.
+     * @this {jQuery}
+     */
+    function toggleFullScreen()
+    {
+        return (/** @type {!jQuery} */ fullScreen.call(this, 
+            !fullScreen.call(this)));
+    }
+    
+    /**
+     * Handles the browser-specific fullscreenchange event and triggers
+     * a jquery event for it.
+     *
+     * @param {?Event} event
+     *            The fullscreenchange event.
+     */
+    function fullScreenChangeHandler(event)
+    {
+        jQuery(document).trigger(new jQuery.Event("fullscreenchange"));
+    }
+    
+    /**
+     * Handles the browser-specific fullscreenerror event and triggers
+     * a jquery event for it.
+     *
+     * @param {?Event} event
+     *            The fullscreenerror event.
+     */
+    function fullScreenErrorHandler(event)
+    {
+        jQuery(document).trigger(new jQuery.Event("fullscreenerror"));
+    }
+    
+    /**
+     * Installs the fullscreenchange event handler.
+     */
+    function installFullScreenHandlers()
+    {
+        var e, change, error;
+        
+        // Determine event name
+        e = document;
+        if (e["webkitCancelFullScreen"])
+        {
+            change = "webkitfullscreenchange";
+            error = "webkitfullscreenerror";
+        }
+        else if (e["msExitFullscreen"])
+        {
+            change = "MSFullscreenChange";
+            error = "MSFullscreenError";
+        }
+        else if (e["mozCancelFullScreen"])
+        {
+            change = "mozfullscreenchange";
+            error = "mozfullscreenerror";
+        }
+        else 
+        {
+            change = "fullscreenchange";
+            error = "fullscreenerror";
+        }
+    
+        // Install the event handlers
+        jQuery(document).bind(change, fullScreenChangeHandler);
+        jQuery(document).bind(error, fullScreenErrorHandler);
+    }
+    
+    jQuery.fn["fullScreen"] = fullScreen;
+    jQuery.fn["toggleFullScreen"] = toggleFullScreen;
+    installFullScreenHandlers();
+    
+    })(jQuery);
+    
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/highlight/default.min.css b/ruoyi-admin/src/main/resources/static/ajax/libs/highlight/default.min.css
new file mode 100644
index 0000000..18240c8
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/highlight/default.min.css
@@ -0,0 +1,79 @@
+/**
+ * GitHub Gist Theme
+ * Author : Anthony Attard - https://github.com/AnthonyAttard
+ * Author : Louis Barranqueiro - https://github.com/LouisBarranqueiro
+ */
+
+.hljs {
+  display: block;
+  background: white;
+  padding: 0.5em;
+  color: #333333;
+  overflow-x: auto;
+}
+
+.hljs-comment,
+.hljs-meta {
+  color: #969896;
+}
+
+.hljs-variable,
+.hljs-template-variable,
+.hljs-strong,
+.hljs-emphasis,
+.hljs-quote {
+  color: #df5000;
+}
+
+.hljs-keyword,
+.hljs-selector-tag,
+.hljs-type {
+  color: #d73a49;
+}
+
+.hljs-literal,
+.hljs-symbol,
+.hljs-bullet,
+.hljs-attribute {
+  color: #0086b3;
+}
+
+.hljs-section,
+.hljs-name {
+  color: #63a35c;
+}
+
+.hljs-tag {
+  color: #333333;
+}
+
+.hljs-title,
+.hljs-attr,
+.hljs-selector-id,
+.hljs-selector-class,
+.hljs-selector-attr,
+.hljs-selector-pseudo {
+  color: #6f42c1;
+}
+
+.hljs-addition {
+  color: #55a532;
+  background-color: #eaffea;
+}
+
+.hljs-deletion {
+  color: #bd2c00;
+  background-color: #ffecec;
+}
+
+.hljs-link {
+  text-decoration: underline;
+}
+
+.hljs-number {
+  color: #005cc5;
+}
+
+.hljs-string {
+  color: #032f62;
+}
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/highlight/highlight.min.js b/ruoyi-admin/src/main/resources/static/ajax/libs/highlight/highlight.min.js
new file mode 100644
index 0000000..43562cb
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/highlight/highlight.min.js
@@ -0,0 +1,1102 @@
+/*
+  Highlight.js 10.3.2 (31e1fc40)
+  License: BSD-3-Clause
+  Copyright (c) 2006-2020, Ivan Sagalaev
+*/
+var hljs=function(){"use strict";function e(n){Object.freeze(n)
+;var t="function"==typeof n
+;return Object.getOwnPropertyNames(n).forEach((function(r){
+!Object.hasOwnProperty.call(n,r)||null===n[r]||"object"!=typeof n[r]&&"function"!=typeof n[r]||t&&("caller"===r||"callee"===r||"arguments"===r)||Object.isFrozen(n[r])||e(n[r])
+})),n}class n{constructor(e){void 0===e.data&&(e.data={}),this.data=e.data}
+ignoreMatch(){this.ignore=!0}}function t(e){
+return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#x27;")
+}function r(e,...n){var t={};for(const n in e)t[n]=e[n]
+;return n.forEach((function(e){for(const n in e)t[n]=e[n]})),t}function a(e){
+return e.nodeName.toLowerCase()}var i=Object.freeze({__proto__:null,
+escapeHTML:t,inherit:r,nodeStream:function(e){var n=[];return function e(t,r){
+for(var i=t.firstChild;i;i=i.nextSibling)3===i.nodeType?r+=i.nodeValue.length:1===i.nodeType&&(n.push({
+event:"start",offset:r,node:i}),r=e(i,r),a(i).match(/br|hr|img|input/)||n.push({
+event:"stop",offset:r,node:i}));return r}(e,0),n},mergeStreams:function(e,n,r){
+var i=0,s="",o=[];function l(){
+return e.length&&n.length?e[0].offset!==n[0].offset?e[0].offset<n[0].offset?e:n:"start"===n[0].event?e:n:e.length?e:n
+}function c(e){s+="<"+a(e)+[].map.call(e.attributes,(function(e){
+return" "+e.nodeName+'="'+t(e.value)+'"'})).join("")+">"}function u(e){
+s+="</"+a(e)+">"}function g(e){("start"===e.event?c:u)(e.node)}
+for(;e.length||n.length;){var d=l()
+;if(s+=t(r.substring(i,d[0].offset)),i=d[0].offset,d===e){o.reverse().forEach(u)
+;do{g(d.splice(0,1)[0]),d=l()}while(d===e&&d.length&&d[0].offset===i)
+;o.reverse().forEach(c)
+}else"start"===d[0].event?o.push(d[0].node):o.pop(),g(d.splice(0,1)[0])}
+return s+t(r.substr(i))}});const s=e=>!!e.kind;class o{constructor(e,n){
+this.buffer="",this.classPrefix=n.classPrefix,e.walk(this)}addText(e){
+this.buffer+=t(e)}openNode(e){if(!s(e))return;let n=e.kind
+;e.sublanguage||(n=`${this.classPrefix}${n}`),this.span(n)}closeNode(e){
+s(e)&&(this.buffer+="</span>")}value(){return this.buffer}span(e){
+this.buffer+=`<span class="${e}">`}}class l{constructor(){this.rootNode={
+children:[]},this.stack=[this.rootNode]}get top(){
+return this.stack[this.stack.length-1]}get root(){return this.rootNode}add(e){
+this.top.children.push(e)}openNode(e){const n={kind:e,children:[]}
+;this.add(n),this.stack.push(n)}closeNode(){
+if(this.stack.length>1)return this.stack.pop()}closeAllNodes(){
+for(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)}
+walk(e){return this.constructor._walk(e,this.rootNode)}static _walk(e,n){
+return"string"==typeof n?e.addText(n):n.children&&(e.openNode(n),
+n.children.forEach((n=>this._walk(e,n))),e.closeNode(n)),e}static _collapse(e){
+"string"!=typeof e&&e.children&&(e.children.every((e=>"string"==typeof e))?e.children=[e.children.join("")]:e.children.forEach((e=>{
+l._collapse(e)})))}}class c extends l{constructor(e){super(),this.options=e}
+addKeyword(e,n){""!==e&&(this.openNode(n),this.addText(e),this.closeNode())}
+addText(e){""!==e&&this.add(e)}addSublanguage(e,n){const t=e.root
+;t.kind=n,t.sublanguage=!0,this.add(t)}toHTML(){
+return new o(this,this.options).value()}finalize(){return!0}}function u(e){
+return e?"string"==typeof e?e:e.source:null}
+const g="[a-zA-Z]\\w*",d="[a-zA-Z_]\\w*",h="\\b\\d+(\\.\\d+)?",f="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",p="\\b(0b[01]+)",m={
+begin:"\\\\[\\s\\S]",relevance:0},b={className:"string",begin:"'",end:"'",
+illegal:"\\n",contains:[m]},v={className:"string",begin:'"',end:'"',
+illegal:"\\n",contains:[m]},x={
+begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/
+},E=function(e,n,t={}){var a=r({className:"comment",begin:e,end:n,contains:[]
+},t);return a.contains.push(x),a.contains.push({className:"doctag",
+begin:"(?:TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):",relevance:0}),a
+},_=E("//","$"),w=E("/\\*","\\*/"),N=E("#","$");var y=Object.freeze({
+__proto__:null,IDENT_RE:g,UNDERSCORE_IDENT_RE:d,NUMBER_RE:h,C_NUMBER_RE:f,
+BINARY_NUMBER_RE:p,
+RE_STARTERS_RE:"!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",
+SHEBANG:(e={})=>{const n=/^#![ ]*\//;return e.binary&&(e.begin=function(...e){
+return e.map((e=>u(e))).join("")}(n,/.*\b/,e.binary,/\b.*/)),r({
+className:"meta",begin:n,end:/$/,relevance:0,"on:begin":(e,n)=>{
+0!==e.index&&n.ignoreMatch()}},e)},BACKSLASH_ESCAPE:m,APOS_STRING_MODE:b,
+QUOTE_STRING_MODE:v,PHRASAL_WORDS_MODE:x,COMMENT:E,C_LINE_COMMENT_MODE:_,
+C_BLOCK_COMMENT_MODE:w,HASH_COMMENT_MODE:N,NUMBER_MODE:{className:"number",
+begin:h,relevance:0},C_NUMBER_MODE:{className:"number",begin:f,relevance:0},
+BINARY_NUMBER_MODE:{className:"number",begin:p,relevance:0},CSS_NUMBER_MODE:{
+className:"number",
+begin:h+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",
+relevance:0},REGEXP_MODE:{begin:/(?=\/[^/\n]*\/)/,contains:[{className:"regexp",
+begin:/\//,end:/\/[gimuy]*/,illegal:/\n/,contains:[m,{begin:/\[/,end:/\]/,
+relevance:0,contains:[m]}]}]},TITLE_MODE:{className:"title",begin:g,relevance:0
+},UNDERSCORE_TITLE_MODE:{className:"title",begin:d,relevance:0},METHOD_GUARD:{
+begin:"\\.\\s*[a-zA-Z_]\\w*",relevance:0},END_SAME_AS_BEGIN:function(e){
+return Object.assign(e,{"on:begin":(e,n)=>{n.data._beginMatch=e[1]},
+"on:end":(e,n)=>{n.data._beginMatch!==e[1]&&n.ignoreMatch()}})}
+}),R="of and for in not or if then".split(" ");function k(e){function n(n,t){
+return RegExp(u(n),"m"+(e.case_insensitive?"i":"")+(t?"g":""))}class t{
+constructor(){
+this.matchIndexes={},this.regexes=[],this.matchAt=1,this.position=0}
+addRule(e,n){
+n.position=this.position++,this.matchIndexes[this.matchAt]=n,this.regexes.push([n,e]),
+this.matchAt+=function(e){return RegExp(e.toString()+"|").exec("").length-1
+}(e)+1}compile(){0===this.regexes.length&&(this.exec=()=>null)
+;const e=this.regexes.map((e=>e[1]));this.matcherRe=n(function(e,n="|"){
+for(var t=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./,r=0,a="",i=0;i<e.length;i++){
+var s=r+=1,o=u(e[i]);for(i>0&&(a+=n),a+="(";o.length>0;){var l=t.exec(o)
+;if(null==l){a+=o;break}
+a+=o.substring(0,l.index),o=o.substring(l.index+l[0].length),
+"\\"===l[0][0]&&l[1]?a+="\\"+(Number(l[1])+s):(a+=l[0],"("===l[0]&&r++)}a+=")"}
+return a}(e),!0),this.lastIndex=0}exec(e){
+this.matcherRe.lastIndex=this.lastIndex;const n=this.matcherRe.exec(e)
+;if(!n)return null
+;const t=n.findIndex(((e,n)=>n>0&&void 0!==e)),r=this.matchIndexes[t]
+;return n.splice(0,t),Object.assign(n,r)}}class a{constructor(){
+this.rules=[],this.multiRegexes=[],
+this.count=0,this.lastIndex=0,this.regexIndex=0}getMatcher(e){
+if(this.multiRegexes[e])return this.multiRegexes[e];const n=new t
+;return this.rules.slice(e).forEach((([e,t])=>n.addRule(e,t))),
+n.compile(),this.multiRegexes[e]=n,n}resumingScanAtSamePosition(){
+return 0!==this.regexIndex}considerAll(){this.regexIndex=0}addRule(e,n){
+this.rules.push([e,n]),"begin"===n.type&&this.count++}exec(e){
+const n=this.getMatcher(this.regexIndex);n.lastIndex=this.lastIndex
+;let t=n.exec(e)
+;if(this.resumingScanAtSamePosition())if(t&&t.index===this.lastIndex);else{
+const n=this.getMatcher(0);n.lastIndex=this.lastIndex+1,t=n.exec(e)}
+return t&&(this.regexIndex+=t.position+1,
+this.regexIndex===this.count&&this.considerAll()),t}}function i(e,n){
+const t=e.input[e.index-1],r=e.input[e.index+e[0].length]
+;"."!==t&&"."!==r||n.ignoreMatch()}
+if(e.contains&&e.contains.includes("self"))throw Error("ERR: contains `self` is not supported at the top-level of a language.  See documentation.")
+;return function t(s,o){const l=s;if(s.compiled)return l
+;s.compiled=!0,s.__beforeBegin=null,s.keywords=s.keywords||s.beginKeywords
+;let c=null
+;if("object"==typeof s.keywords&&(c=s.keywords.$pattern,delete s.keywords.$pattern),
+s.keywords&&(s.keywords=function(e,n){var t={}
+;return"string"==typeof e?r("keyword",e):Object.keys(e).forEach((function(n){
+r(n,e[n])})),t;function r(e,r){
+n&&(r=r.toLowerCase()),r.split(" ").forEach((function(n){var r=n.split("|")
+;t[r[0]]=[e,O(r[0],r[1])]}))}
+}(s.keywords,e.case_insensitive)),s.lexemes&&c)throw Error("ERR: Prefer `keywords.$pattern` to `mode.lexemes`, BOTH are not allowed. (see mode reference) ")
+;return l.keywordPatternRe=n(s.lexemes||c||/\w+/,!0),
+o&&(s.beginKeywords&&(s.begin="\\b("+s.beginKeywords.split(" ").join("|")+")(?=\\b|\\s)",
+s.__beforeBegin=i),
+s.begin||(s.begin=/\B|\b/),l.beginRe=n(s.begin),s.endSameAsBegin&&(s.end=s.begin),
+s.end||s.endsWithParent||(s.end=/\B|\b/),
+s.end&&(l.endRe=n(s.end)),l.terminator_end=u(s.end)||"",
+s.endsWithParent&&o.terminator_end&&(l.terminator_end+=(s.end?"|":"")+o.terminator_end)),
+s.illegal&&(l.illegalRe=n(s.illegal)),
+void 0===s.relevance&&(s.relevance=1),s.contains||(s.contains=[]),
+s.contains=[].concat(...s.contains.map((function(e){return function(e){
+return e.variants&&!e.cached_variants&&(e.cached_variants=e.variants.map((function(n){
+return r(e,{variants:null},n)}))),e.cached_variants?e.cached_variants:M(e)?r(e,{
+starts:e.starts?r(e.starts):null}):Object.isFrozen(e)?r(e):e}("self"===e?s:e)
+}))),s.contains.forEach((function(e){t(e,l)
+})),s.starts&&t(s.starts,o),l.matcher=function(e){const n=new a
+;return e.contains.forEach((e=>n.addRule(e.begin,{rule:e,type:"begin"
+}))),e.terminator_end&&n.addRule(e.terminator_end,{type:"end"
+}),e.illegal&&n.addRule(e.illegal,{type:"illegal"}),n}(l),l}(e)}function M(e){
+return!!e&&(e.endsWithParent||M(e.starts))}function O(e,n){
+return n?Number(n):function(e){return R.includes(e.toLowerCase())}(e)?0:1}
+const L={props:["language","code","autodetect"],data:function(){return{
+detectedLanguage:"",unknownLanguage:!1}},computed:{className(){
+return this.unknownLanguage?"":"hljs "+this.detectedLanguage},highlighted(){
+if(!this.autoDetect&&!hljs.getLanguage(this.language))return console.warn(`The language "${this.language}" you specified could not be found.`),
+this.unknownLanguage=!0,t(this.code);let e
+;return this.autoDetect?(e=hljs.highlightAuto(this.code),
+this.detectedLanguage=e.language):(e=hljs.highlight(this.language,this.code,this.ignoreIllegals),
+this.detectectLanguage=this.language),e.value},autoDetect(){
+return!(this.language&&(e=this.autodetect,!e&&""!==e));var e},
+ignoreIllegals:()=>!0},render(e){return e("pre",{},[e("code",{
+class:this.className,domProps:{innerHTML:this.highlighted}})])}},j={install(e){
+e.component("highlightjs",L)}
+},I=t,T=r,{nodeStream:S,mergeStreams:A}=i,B=Symbol("nomatch")
+;return function(t){
+var r=[],a=Object.create(null),i=Object.create(null),s=[],o=!0,l=/(^(<[^>]+>|\t|)+|\n)/gm,u="Could not find the language '{}', did you forget to load/include a language module?"
+;const g={disableAutodetect:!0,name:"Plain text",contains:[]};var d={
+noHighlightRe:/^(no-?highlight)$/i,
+languageDetectRe:/\blang(?:uage)?-([\w-]+)\b/i,classPrefix:"hljs-",
+tabReplace:null,useBR:!1,languages:null,__emitter:c};function h(e){
+return d.noHighlightRe.test(e)}function f(e,n,t,r){var a={code:n,language:e}
+;N("before:highlight",a);var i=a.result?a.result:p(a.language,a.code,t,r)
+;return i.code=a.code,N("after:highlight",i),i}function p(e,t,r,i){var s=t
+;function l(e,n){var t=_.case_insensitive?n[0].toLowerCase():n[0]
+;return Object.prototype.hasOwnProperty.call(e.keywords,t)&&e.keywords[t]}
+function c(){null!=y.subLanguage?function(){if(""!==O){var e=null
+;if("string"==typeof y.subLanguage){
+if(!a[y.subLanguage])return void M.addText(O)
+;e=p(y.subLanguage,O,!0,R[y.subLanguage]),R[y.subLanguage]=e.top
+}else e=m(O,y.subLanguage.length?y.subLanguage:null)
+;y.relevance>0&&(L+=e.relevance),M.addSublanguage(e.emitter,e.language)}
+}():function(){if(!y.keywords)return void M.addText(O);let e=0
+;y.keywordPatternRe.lastIndex=0;let n=y.keywordPatternRe.exec(O),t="";for(;n;){
+t+=O.substring(e,n.index);const r=l(y,n);if(r){const[e,a]=r
+;M.addText(t),t="",L+=a,M.addKeyword(n[0],e)}else t+=n[0]
+;e=y.keywordPatternRe.lastIndex,n=y.keywordPatternRe.exec(O)}
+t+=O.substr(e),M.addText(t)}(),O=""}function g(e){
+return e.className&&M.openNode(e.className),y=Object.create(e,{parent:{value:y}
+})}function h(e,t,r){let a=function(e,n){var t=e&&e.exec(n)
+;return t&&0===t.index}(e.endRe,r);if(a){if(e["on:end"]){const r=new n(e)
+;e["on:end"](t,r),r.ignore&&(a=!1)}if(a){for(;e.endsParent&&e.parent;)e=e.parent
+;return e}}if(e.endsWithParent)return h(e.parent,t,r)}function f(e){
+return 0===y.matcher.regexIndex?(O+=e[0],1):(S=!0,0)}function b(e){
+var n=e[0],t=s.substr(e.index),r=h(y,e,t);if(!r)return B;var a=y
+;a.skip?O+=n:(a.returnEnd||a.excludeEnd||(O+=n),c(),a.excludeEnd&&(O=n));do{
+y.className&&M.closeNode(),y.skip||y.subLanguage||(L+=y.relevance),y=y.parent
+}while(y!==r.parent)
+;return r.starts&&(r.endSameAsBegin&&(r.starts.endRe=r.endRe),
+g(r.starts)),a.returnEnd?0:n.length}var v={};function x(t,a){var i=a&&a[0]
+;if(O+=t,null==i)return c(),0
+;if("begin"===v.type&&"end"===a.type&&v.index===a.index&&""===i){
+if(O+=s.slice(a.index,a.index+1),!o){const n=Error("0 width match regex")
+;throw n.languageName=e,n.badRule=v.rule,n}return 1}
+if(v=a,"begin"===a.type)return function(e){var t=e[0],r=e.rule
+;const a=new n(r),i=[r.__beforeBegin,r["on:begin"]]
+;for(const n of i)if(n&&(n(e,a),a.ignore))return f(t)
+;return r&&r.endSameAsBegin&&(r.endRe=RegExp(t.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&"),"m")),
+r.skip?O+=t:(r.excludeBegin&&(O+=t),
+c(),r.returnBegin||r.excludeBegin||(O=t)),g(r),r.returnBegin?0:t.length}(a)
+;if("illegal"===a.type&&!r){
+const e=Error('Illegal lexeme "'+i+'" for mode "'+(y.className||"<unnamed>")+'"')
+;throw e.mode=y,e}if("end"===a.type){var l=b(a);if(l!==B)return l}
+if("illegal"===a.type&&""===i)return 1
+;if(T>1e5&&T>3*a.index)throw Error("potential infinite loop, way more iterations than matches")
+;return O+=i,i.length}var _=E(e)
+;if(!_)throw console.error(u.replace("{}",e)),Error('Unknown language: "'+e+'"')
+;var w=k(_),N="",y=i||w,R={},M=new d.__emitter(d);!function(){
+for(var e=[],n=y;n!==_;n=n.parent)n.className&&e.unshift(n.className)
+;e.forEach((e=>M.openNode(e)))}();var O="",L=0,j=0,T=0,S=!1;try{
+for(y.matcher.considerAll();;){
+T++,S?S=!1:y.matcher.considerAll(),y.matcher.lastIndex=j
+;const e=y.matcher.exec(s);if(!e)break;const n=x(s.substring(j,e.index),e)
+;j=e.index+n}return x(s.substr(j)),M.closeAllNodes(),M.finalize(),N=M.toHTML(),{
+relevance:L,value:N,language:e,illegal:!1,emitter:M,top:y}}catch(n){
+if(n.message&&n.message.includes("Illegal"))return{illegal:!0,illegalBy:{
+msg:n.message,context:s.slice(j-100,j+100),mode:n.mode},sofar:N,relevance:0,
+value:I(s),emitter:M};if(o)return{illegal:!1,relevance:0,value:I(s),emitter:M,
+language:e,top:y,errorRaised:n};throw n}}function m(e,n){
+n=n||d.languages||Object.keys(a);var t=function(e){const n={relevance:0,
+emitter:new d.__emitter(d),value:I(e),illegal:!1,top:g}
+;return n.emitter.addText(e),n}(e),r=t
+;return n.filter(E).filter(w).forEach((function(n){var a=p(n,e,!1);a.language=n,
+a.relevance>r.relevance&&(r=a),a.relevance>t.relevance&&(r=t,t=a)
+})),r.language&&(t.second_best=r),t}function b(e){
+return d.tabReplace||d.useBR?e.replace(l,(e=>"\n"===e?d.useBR?"<br>":e:d.tabReplace?e.replace(/\t/g,d.tabReplace):e)):e
+}function v(e){let n=null;const t=function(e){var n=e.className+" "
+;n+=e.parentNode?e.parentNode.className:"";const t=d.languageDetectRe.exec(n)
+;if(t){var r=E(t[1])
+;return r||(console.warn(u.replace("{}",t[1])),console.warn("Falling back to no-highlight mode for this block.",e)),
+r?t[1]:"no-highlight"}return n.split(/\s+/).find((e=>h(e)||E(e)))}(e)
+;if(h(t))return;N("before:highlightBlock",{block:e,language:t
+}),d.useBR?(n=document.createElement("div"),
+n.innerHTML=e.innerHTML.replace(/\n/g,"").replace(/<br[ /]*>/g,"\n")):n=e
+;const r=n.textContent,a=t?f(t,r,!0):m(r),s=S(n);if(s.length){
+const e=document.createElement("div");e.innerHTML=a.value,a.value=A(s,S(e),r)}
+a.value=b(a.value),N("after:highlightBlock",{block:e,result:a
+}),e.innerHTML=a.value,e.className=function(e,n,t){var r=n?i[n]:t,a=[e.trim()]
+;return e.match(/\bhljs\b/)||a.push("hljs"),
+e.includes(r)||a.push(r),a.join(" ").trim()
+}(e.className,t,a.language),e.result={language:a.language,re:a.relevance,
+relavance:a.relevance},a.second_best&&(e.second_best={
+language:a.second_best.language,re:a.second_best.relevance,
+relavance:a.second_best.relevance})}const x=()=>{if(!x.called){x.called=!0
+;var e=document.querySelectorAll("pre code");r.forEach.call(e,v)}}
+;function E(e){return e=(e||"").toLowerCase(),a[e]||a[i[e]]}
+function _(e,{languageName:n}){"string"==typeof e&&(e=[e]),e.forEach((e=>{i[e]=n
+}))}function w(e){var n=E(e);return n&&!n.disableAutodetect}function N(e,n){
+var t=e;s.forEach((function(e){e[t]&&e[t](n)}))}Object.assign(t,{highlight:f,
+highlightAuto:m,fixMarkup:function(e){
+return console.warn("fixMarkup is deprecated and will be removed entirely in v11.0"),
+console.warn("Please see https://github.com/highlightjs/highlight.js/issues/2534"),
+b(e)},highlightBlock:v,configure:function(e){
+e.useBR&&(console.warn("'useBR' option is deprecated and will be removed entirely in v11.0"),
+console.warn("Please see https://github.com/highlightjs/highlight.js/issues/2559")),
+d=T(d,e)},initHighlighting:x,initHighlightingOnLoad:function(){
+window.addEventListener("DOMContentLoaded",x,!1)},
+registerLanguage:function(e,n){var r=null;try{r=n(t)}catch(n){
+if(console.error("Language definition for '{}' could not be registered.".replace("{}",e)),
+!o)throw n;console.error(n),r=g}
+r.name||(r.name=e),a[e]=r,r.rawDefinition=n.bind(null,t),
+r.aliases&&_(r.aliases,{languageName:e})},listLanguages:function(){
+return Object.keys(a)},getLanguage:E,registerAliases:_,
+requireLanguage:function(e){var n=E(e);if(n)return n
+;throw Error("The '{}' language is required, but not loaded.".replace("{}",e))},
+autoDetection:w,inherit:T,addPlugin:function(e){s.push(e)},vuePlugin:j
+}),t.debugMode=function(){o=!1},t.safeMode=function(){o=!0
+},t.versionString="10.3.2";for(const n in y)"object"==typeof y[n]&&e(y[n])
+;return Object.assign(t,y),t}({})}()
+;"object"==typeof exports&&"undefined"!=typeof module&&(module.exports=hljs);
+hljs.registerLanguage("apache",function(){"use strict";return function(e){
+var n={className:"number",
+begin:"\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}(:\\d{1,5})?"};return{
+name:"Apache config",aliases:["apacheconf"],case_insensitive:!0,
+contains:[e.HASH_COMMENT_MODE,{className:"section",begin:"</?",end:">",
+contains:[n,{className:"number",begin:":\\d{1,5}"
+},e.inherit(e.QUOTE_STRING_MODE,{relevance:0})]},{className:"attribute",
+begin:/\w+/,relevance:0,keywords:{
+nomarkup:"order deny allow setenv rewriterule rewriteengine rewritecond documentroot sethandler errordocument loadmodule options header listen serverroot servername"
+},starts:{end:/$/,relevance:0,keywords:{literal:"on off all deny allow"},
+contains:[{className:"meta",begin:"\\s\\[",end:"\\]$"},{className:"variable",
+begin:"[\\$%]\\{",end:"\\}",contains:["self",{className:"number",
+begin:"[\\$%]\\d+"}]},n,{className:"number",begin:"\\d+"},e.QUOTE_STRING_MODE]}
+}],illegal:/\S/}}}());
+hljs.registerLanguage("bash",function(){"use strict";return function(e){
+const s={};Object.assign(s,{className:"variable",variants:[{
+begin:/\$[\w\d#@][\w\d_]*/},{begin:/\$\{/,end:/\}/,contains:["self",{begin:/:-/,
+contains:[s]}]}]});const n={className:"subst",begin:/\$\(/,end:/\)/,
+contains:[e.BACKSLASH_ESCAPE]},t={begin:/<<-?\s*(?=\w+)/,starts:{
+contains:[e.END_SAME_AS_BEGIN({begin:/(\w+)/,end:/(\w+)/,className:"string"})]}
+},a={className:"string",begin:/"/,end:/"/,contains:[e.BACKSLASH_ESCAPE,s,n]}
+;n.contains.push(a);const i={begin:/\$\(\(/,end:/\)\)/,contains:[{
+begin:/\d+#[0-9a-f]+/,className:"number"},e.NUMBER_MODE,s]},c=e.SHEBANG({
+binary:"(fish|bash|zsh|sh|csh|ksh|tcsh|dash|scsh)",relevance:10}),o={
+className:"function",begin:/\w[\w\d_]*\s*\(\s*\)\s*\{/,returnBegin:!0,
+contains:[e.inherit(e.TITLE_MODE,{begin:/\w[\w\d_]*/})],relevance:0};return{
+name:"Bash",aliases:["sh","zsh"],keywords:{$pattern:/\b[a-z._-]+\b/,
+keyword:"if then else elif fi for while in do done case esac function",
+literal:"true false",
+built_in:"break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp"
+},contains:[c,e.SHEBANG(),o,i,e.HASH_COMMENT_MODE,t,a,{className:"",begin:/\\"/
+},{className:"string",begin:/'/,end:/'/},s]}}}());
+hljs.registerLanguage("c-like",function(){"use strict";return function(e){
+function t(e){return"(?:"+e+")?"}var n=e.COMMENT("//","$",{contains:[{
+begin:/\\\n/}]
+}),r="[a-zA-Z_]\\w*::",a="(decltype\\(auto\\)|"+t(r)+"[a-zA-Z_]\\w*"+t("<.*?>")+")",i={
+className:"keyword",begin:"\\b[a-z\\d_]*_t\\b"},s={className:"string",
+variants:[{begin:'(u8?|U|L)?"',end:'"',illegal:"\\n",
+contains:[e.BACKSLASH_ESCAPE]},{
+begin:"(u8?|U|L)?'(\\\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4,8}|[0-7]{3}|\\S)|.)",
+end:"'",illegal:"."},e.END_SAME_AS_BEGIN({
+begin:/(?:u8?|U|L)?R"([^()\\ ]{0,16})\(/,end:/\)([^()\\ ]{0,16})"/})]},o={
+className:"number",variants:[{begin:"\\b(0b[01']+)"},{
+begin:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)(u|U|l|L|ul|UL|f|F|b|B)"},{
+begin:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)"
+}],relevance:0},c={className:"meta",begin:/#\s*[a-z]+\b/,end:/$/,keywords:{
+"meta-keyword":"if else elif endif define undef warning error line pragma _Pragma ifdef ifndef include"
+},contains:[{begin:/\\\n/,relevance:0},e.inherit(s,{className:"meta-string"}),{
+className:"meta-string",begin:/<.*?>/,end:/$/,illegal:"\\n"
+},n,e.C_BLOCK_COMMENT_MODE]},l={className:"title",begin:t(r)+e.IDENT_RE,
+relevance:0},d=t(r)+e.IDENT_RE+"\\s*\\(",u={
+keyword:"int float while private char char8_t char16_t char32_t catch import module export virtual operator sizeof dynamic_cast|10 typedef const_cast|10 const for static_cast|10 union namespace unsigned long volatile static protected bool template mutable if public friend do goto auto void enum else break extern using asm case typeid wchar_t short reinterpret_cast|10 default double register explicit signed typename try this switch continue inline delete alignas alignof constexpr consteval constinit decltype concept co_await co_return co_yield requires noexcept static_assert thread_local restrict final override atomic_bool atomic_char atomic_schar atomic_uchar atomic_short atomic_ushort atomic_int atomic_uint atomic_long atomic_ulong atomic_llong atomic_ullong new throw return and and_eq bitand bitor compl not not_eq or or_eq xor xor_eq",
+built_in:"std string wstring cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set pair bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap priority_queue make_pair array shared_ptr abort terminate abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf future isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc realloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf endl initializer_list unique_ptr _Bool complex _Complex imaginary _Imaginary",
+literal:"true false nullptr NULL"},m=[c,i,n,e.C_BLOCK_COMMENT_MODE,o,s],p={
+variants:[{begin:/=/,end:/;/},{begin:/\(/,end:/\)/},{
+beginKeywords:"new throw return else",end:/;/}],keywords:u,contains:m.concat([{
+begin:/\(/,end:/\)/,keywords:u,contains:m.concat(["self"]),relevance:0}]),
+relevance:0},_={className:"function",begin:"("+a+"[\\*&\\s]+)+"+d,
+returnBegin:!0,end:/[{;=]/,excludeEnd:!0,keywords:u,illegal:/[^\w\s\*&:<>]/,
+contains:[{begin:"decltype\\(auto\\)",keywords:u,relevance:0},{begin:d,
+returnBegin:!0,contains:[l],relevance:0},{className:"params",begin:/\(/,
+end:/\)/,keywords:u,relevance:0,contains:[n,e.C_BLOCK_COMMENT_MODE,s,o,i,{
+begin:/\(/,end:/\)/,keywords:u,relevance:0,
+contains:["self",n,e.C_BLOCK_COMMENT_MODE,s,o,i]}]
+},i,n,e.C_BLOCK_COMMENT_MODE,c]};return{
+aliases:["c","cc","h","c++","h++","hpp","hh","hxx","cxx"],keywords:u,
+disableAutodetect:!0,illegal:"</",contains:[].concat(p,_,m,[c,{
+begin:"\\b(deque|list|queue|priority_queue|pair|stack|vector|map|set|bitset|multiset|multimap|unordered_map|unordered_set|unordered_multiset|unordered_multimap|array)\\s*<",
+end:">",keywords:u,contains:["self",i]},{begin:e.IDENT_RE+"::",keywords:u},{
+className:"class",beginKeywords:"enum class struct union",end:/[{;:<>=]/,
+contains:[{beginKeywords:"final class struct"},e.TITLE_MODE]}]),exports:{
+preprocessor:c,strings:s,keywords:u}}}}());
+hljs.registerLanguage("c",function(){"use strict";return function(e){
+var n=e.requireLanguage("c-like").rawDefinition()
+;return n.name="C",n.aliases=["c","h"],n}}());
+hljs.registerLanguage("coffeescript",function(){"use strict"
+;const e=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","switch","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends"],n=["true","false","null","undefined","NaN","Infinity"],a=[].concat(["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],["arguments","this","super","console","window","document","localStorage","module","global"],["Intl","DataView","Number","Math","Date","String","RegExp","Object","Function","Boolean","Error","Symbol","Set","Map","WeakSet","WeakMap","Proxy","Reflect","JSON","Promise","Float64Array","Int16Array","Int32Array","Int8Array","Uint16Array","Uint32Array","Float32Array","Array","Uint8Array","Uint8ClampedArray","ArrayBuffer"],["EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"])
+;return function(r){var t,i={
+keyword:e.concat(["then","unless","until","loop","by","when","and","or","is","isnt","not"]).filter((t=["var","const","let","function","static"],
+e=>!t.includes(e))).join(" "),
+literal:n.concat(["yes","no","on","off"]).join(" "),
+built_in:a.concat(["npm","print"]).join(" ")},s="[A-Za-z$_][0-9A-Za-z$_]*",o={
+className:"subst",begin:/#\{/,end:/}/,keywords:i
+},c=[r.BINARY_NUMBER_MODE,r.inherit(r.C_NUMBER_MODE,{starts:{end:"(\\s*/)?",
+relevance:0}}),{className:"string",variants:[{begin:/'''/,end:/'''/,
+contains:[r.BACKSLASH_ESCAPE]},{begin:/'/,end:/'/,contains:[r.BACKSLASH_ESCAPE]
+},{begin:/"""/,end:/"""/,contains:[r.BACKSLASH_ESCAPE,o]},{begin:/"/,end:/"/,
+contains:[r.BACKSLASH_ESCAPE,o]}]},{className:"regexp",variants:[{begin:"///",
+end:"///",contains:[o,r.HASH_COMMENT_MODE]},{begin:"//[gim]{0,3}(?=\\W)",
+relevance:0},{begin:/\/(?![ *]).*?(?![\\]).\/[gim]{0,3}(?=\W)/}]},{begin:"@"+s
+},{subLanguage:"javascript",excludeBegin:!0,excludeEnd:!0,variants:[{
+begin:"```",end:"```"},{begin:"`",end:"`"}]}];o.contains=c
+;var l=r.inherit(r.TITLE_MODE,{begin:s}),d="(\\(.*\\))?\\s*\\B[-=]>",g={
+className:"params",begin:"\\([^\\(]",returnBegin:!0,contains:[{begin:/\(/,
+end:/\)/,keywords:i,contains:["self"].concat(c)}]};return{name:"CoffeeScript",
+aliases:["coffee","cson","iced"],keywords:i,illegal:/\/\*/,
+contains:c.concat([r.COMMENT("###","###"),r.HASH_COMMENT_MODE,{
+className:"function",begin:"^\\s*"+s+"\\s*=\\s*"+d,end:"[-=]>",returnBegin:!0,
+contains:[l,g]},{begin:/[:\(,=]\s*/,relevance:0,contains:[{className:"function",
+begin:d,end:"[-=]>",returnBegin:!0,contains:[g]}]},{className:"class",
+beginKeywords:"class",end:"$",illegal:/[:="\[\]]/,contains:[{
+beginKeywords:"extends",endsWithParent:!0,illegal:/[:="\[\]]/,contains:[l]},l]
+},{begin:s+":",end:":",returnBegin:!0,returnEnd:!0,relevance:0}])}}}());
+hljs.registerLanguage("cpp",function(){"use strict";return function(e){
+var i=e.requireLanguage("c-like").rawDefinition();return i.disableAutodetect=!1,
+i.name="C++",i.aliases=["cc","c++","h++","hpp","hh","hxx","cxx"],i}}());
+hljs.registerLanguage("csharp",function(){"use strict";return function(e){
+var n={
+keyword:["abstract","as","base","break","case","class","const","continue","do","else","event","explicit","extern","finally","fixed","for","foreach","goto","if","implicit","in","interface","internal","is","lock","namespace","new","operator","out","override","params","private","protected","public","readonly","record","ref","return","sealed","sizeof","stackalloc","static","struct","switch","this","throw","try","typeof","unchecked","unsafe","using","virtual","void","volatile","while"].concat(["add","alias","and","ascending","async","await","by","descending","equals","from","get","global","group","init","into","join","let","nameof","not","notnull","on","or","orderby","partial","remove","select","set","unmanaged","value","var","when","where","with","yield"]).join(" "),
+built_in:"bool byte char decimal delegate double dynamic enum float int long nint nuint object sbyte short string ulong unit ushort",
+literal:"default false null true"},i=e.inherit(e.TITLE_MODE,{
+begin:"[a-zA-Z](\\.?\\w)*"}),a={className:"number",variants:[{
+begin:"\\b(0b[01']+)"},{
+begin:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)(u|U|l|L|ul|UL|f|F|b|B)"},{
+begin:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)"
+}],relevance:0},s={className:"string",begin:'@"',end:'"',contains:[{begin:'""'}]
+},t=e.inherit(s,{illegal:/\n/}),r={className:"subst",begin:"{",end:"}",
+keywords:n},l=e.inherit(r,{illegal:/\n/}),c={className:"string",begin:/\$"/,
+end:'"',illegal:/\n/,contains:[{begin:"{{"},{begin:"}}"},e.BACKSLASH_ESCAPE,l]
+},o={className:"string",begin:/\$@"/,end:'"',contains:[{begin:"{{"},{begin:"}}"
+},{begin:'""'},r]},d=e.inherit(o,{illegal:/\n/,contains:[{begin:"{{"},{
+begin:"}}"},{begin:'""'},l]})
+;r.contains=[o,c,s,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,a,e.C_BLOCK_COMMENT_MODE],
+l.contains=[d,c,t,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,a,e.inherit(e.C_BLOCK_COMMENT_MODE,{
+illegal:/\n/})];var g={variants:[o,c,s,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]
+},E={begin:"<",end:">",contains:[{beginKeywords:"in out"},i]
+},_=e.IDENT_RE+"(<"+e.IDENT_RE+"(\\s*,\\s*"+e.IDENT_RE+")*>)?(\\[\\])?",b={
+begin:"@"+e.IDENT_RE,relevance:0};return{name:"C#",aliases:["cs","c#"],
+keywords:n,illegal:/::/,contains:[e.COMMENT("///","$",{returnBegin:!0,
+contains:[{className:"doctag",variants:[{begin:"///",relevance:0},{
+begin:"\x3c!--|--\x3e"},{begin:"</?",end:">"}]}]
+}),e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{className:"meta",begin:"#",
+end:"$",keywords:{
+"meta-keyword":"if else elif endif define undef warning error line region endregion pragma checksum"
+}},g,a,{beginKeywords:"class interface",end:/[{;=]/,illegal:/[^\s:,]/,
+contains:[{beginKeywords:"where class"
+},i,E,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{beginKeywords:"namespace",
+end:/[{;=]/,illegal:/[^\s:]/,
+contains:[i,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{
+beginKeywords:"record",end:/[{;=]/,illegal:/[^\s:]/,
+contains:[i,E,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{className:"meta",
+begin:"^\\s*\\[",excludeBegin:!0,end:"\\]",excludeEnd:!0,contains:[{
+className:"meta-string",begin:/"/,end:/"/}]},{
+beginKeywords:"new return throw await else",relevance:0},{className:"function",
+begin:"("+_+"\\s+)+"+e.IDENT_RE+"\\s*(\\<.+\\>)?\\s*\\(",returnBegin:!0,
+end:/\s*[{;=]/,excludeEnd:!0,keywords:n,contains:[{
+beginKeywords:"public private protected static internal protected abstract async extern override unsafe virtual new sealed partial"
+},{begin:e.IDENT_RE+"\\s*(\\<.+\\>)?\\s*\\(",returnBegin:!0,
+contains:[e.TITLE_MODE,E],relevance:0},{className:"params",begin:/\(/,end:/\)/,
+excludeBegin:!0,excludeEnd:!0,keywords:n,relevance:0,
+contains:[g,a,e.C_BLOCK_COMMENT_MODE]
+},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},b]}}}());
+hljs.registerLanguage("css",function(){"use strict";return function(e){var n={
+begin:/(?:[A-Z\_\.\-]+|--[a-zA-Z0-9_-]+)\s*:/,returnBegin:!0,end:";",
+endsWithParent:!0,contains:[{className:"attribute",begin:/\S/,end:":",
+excludeEnd:!0,starts:{endsWithParent:!0,excludeEnd:!0,contains:[{
+begin:/[\w-]+\(/,returnBegin:!0,contains:[{className:"built_in",begin:/[\w-]+/
+},{begin:/\(/,end:/\)/,
+contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.CSS_NUMBER_MODE]}]
+},e.CSS_NUMBER_MODE,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,e.C_BLOCK_COMMENT_MODE,{
+className:"number",begin:"#[0-9A-Fa-f]+"},{className:"meta",begin:"!important"}]
+}}]};return{name:"CSS",case_insensitive:!0,illegal:/[=\/|'\$]/,
+contains:[e.C_BLOCK_COMMENT_MODE,{className:"selector-id",
+begin:/#[A-Za-z0-9_-]+/},{className:"selector-class",begin:/\.[A-Za-z0-9_-]+/},{
+className:"selector-attr",begin:/\[/,end:/\]/,illegal:"$",
+contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]},{className:"selector-pseudo",
+begin:/:(:)?[a-zA-Z0-9\_\-\+\(\)"'.]+/},{begin:"@(page|font-face)",
+lexemes:"@[a-z-]+",keywords:"@page @font-face"},{begin:"@",end:"[{;]",
+illegal:/:/,returnBegin:!0,contains:[{className:"keyword",
+begin:/@\-?\w[\w]*(\-\w+)*/},{begin:/\s/,endsWithParent:!0,excludeEnd:!0,
+relevance:0,keywords:"and or not only",contains:[{begin:/[a-z-]+:/,
+className:"attribute"},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.CSS_NUMBER_MODE]
+}]},{className:"selector-tag",begin:"[a-zA-Z-][a-zA-Z0-9_-]*",relevance:0},{
+begin:"{",end:"}",illegal:/\S/,contains:[e.C_BLOCK_COMMENT_MODE,n]}]}}}());
+hljs.registerLanguage("diff",function(){"use strict";return function(e){return{
+name:"Diff",aliases:["patch"],contains:[{className:"meta",relevance:10,
+variants:[{begin:/^@@ +\-\d+,\d+ +\+\d+,\d+ +@@$/},{
+begin:/^\*\*\* +\d+,\d+ +\*\*\*\*$/},{begin:/^\-\-\- +\d+,\d+ +\-\-\-\-$/}]},{
+className:"comment",variants:[{begin:/Index: /,end:/$/},{begin:/={3,}/,end:/$/
+},{begin:/^\-{3}/,end:/$/},{begin:/^\*{3} /,end:/$/},{begin:/^\+{3}/,end:/$/},{
+begin:/^\*{15}$/}]},{className:"addition",begin:"^\\+",end:"$"},{
+className:"deletion",begin:"^\\-",end:"$"},{className:"addition",begin:"^\\!",
+end:"$"}]}}}());
+hljs.registerLanguage("go",function(){"use strict";return function(e){var n={
+keyword:"break default func interface select case map struct chan else goto package switch const fallthrough if range type continue for import return var go defer bool byte complex64 complex128 float32 float64 int8 int16 int32 int64 string uint8 uint16 uint32 uint64 int uint uintptr rune",
+literal:"true false iota nil",
+built_in:"append cap close complex copy imag len make new panic print println real recover delete"
+};return{name:"Go",aliases:["golang"],keywords:n,illegal:"</",
+contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{className:"string",
+variants:[e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,{begin:"`",end:"`"}]},{
+className:"number",variants:[{begin:e.C_NUMBER_RE+"[i]",relevance:1
+},e.C_NUMBER_MODE]},{begin:/:=/},{className:"function",beginKeywords:"func",
+end:"\\s*(\\{|$)",excludeEnd:!0,contains:[e.TITLE_MODE,{className:"params",
+begin:/\(/,end:/\)/,keywords:n,illegal:/["']/}]}]}}}());
+hljs.registerLanguage("http",function(){"use strict";return function(e){
+var n="HTTP/[0-9\\.]+";return{name:"HTTP",aliases:["https"],illegal:"\\S",
+contains:[{begin:"^"+n,end:"$",contains:[{className:"number",
+begin:"\\b\\d{3}\\b"}]},{begin:"^[A-Z]+ (.*?) "+n+"$",returnBegin:!0,end:"$",
+contains:[{className:"string",begin:" ",end:" ",excludeBegin:!0,excludeEnd:!0},{
+begin:n},{className:"keyword",begin:"[A-Z]+"}]},{className:"attribute",
+begin:"^\\w",end:": ",excludeEnd:!0,illegal:"\\n|\\s|=",starts:{end:"$",
+relevance:0}},{begin:"\\n\\n",starts:{subLanguage:[],endsWithParent:!0}}]}}}());
+hljs.registerLanguage("ini",function(){"use strict";function e(e){
+return e?"string"==typeof e?e:e.source:null}function n(...n){
+return n.map((n=>e(n))).join("")}return function(a){var s={className:"number",
+relevance:0,variants:[{begin:/([\+\-]+)?[\d]+_[\d_]+/},{begin:a.NUMBER_RE}]
+},i=a.COMMENT();i.variants=[{begin:/;/,end:/$/},{begin:/#/,end:/$/}];var t={
+className:"variable",variants:[{begin:/\$[\w\d"][\w\d_]*/},{begin:/\$\{(.*?)}/}]
+},r={className:"literal",begin:/\bon|off|true|false|yes|no\b/},l={
+className:"string",contains:[a.BACKSLASH_ESCAPE],variants:[{begin:"'''",
+end:"'''",relevance:10},{begin:'"""',end:'"""',relevance:10},{begin:'"',end:'"'
+},{begin:"'",end:"'"}]},c={begin:/\[/,end:/\]/,contains:[i,r,t,l,s,"self"],
+relevance:0
+},g="("+[/[A-Za-z0-9_-]+/,/"(\\"|[^"])*"/,/'[^']*'/].map((n=>e(n))).join("|")+")"
+;return{name:"TOML, also INI",aliases:["toml"],case_insensitive:!0,illegal:/\S/,
+contains:[i,{className:"section",begin:/\[+/,end:/\]+/},{
+begin:n(g,"(\\s*\\.\\s*",g,")*",n("(?=",/\s*=\s*[^#\s]/,")")),className:"attr",
+starts:{end:/$/,contains:[i,c,r,t,l,s]}}]}}}());
+hljs.registerLanguage("java",function(){"use strict";function e(e){
+return e?"string"==typeof e?e:e.source:null}function n(e){return a("(",e,")?")}
+function a(...n){return n.map((n=>e(n))).join("")}function s(...n){
+return"("+n.map((n=>e(n))).join("|")+")"}return function(e){
+var r="false synchronized int abstract float private char boolean var static null if const for true while long strictfp finally protected import native final void enum else break transient catch instanceof byte super volatile case assert short package default double public try this switch continue throws protected public private module requires exports do",i={
+className:"meta",begin:"@[\xc0-\u02b8a-zA-Z_$][\xc0-\u02b8a-zA-Z_$0-9]*",
+contains:[{begin:/\(/,end:/\)/,contains:["self"]}]
+},t=e=>a("[",e,"]+([",e,"_]*[",e,"]+)?"),c={className:"number",variants:[{
+begin:`\\b(0[bB]${t("01")})[lL]?`},{begin:`\\b(0${t("0-7")})[dDfFlL]?`},{
+begin:a(/\b0[xX]/,s(a(t("a-fA-F0-9"),/\./,t("a-fA-F0-9")),a(t("a-fA-F0-9"),/\.?/),a(/\./,t("a-fA-F0-9"))),/([pP][+-]?(\d+))?/,/[fFdDlL]?/)
+},{begin:a(/\b/,s(a(/\d*\./,t("\\d")),t("\\d")),/[eE][+-]?[\d]+[dDfF]?/)},{
+begin:a(/\b/,t(/\d/),n(/\.?/),n(t(/\d/)),/[dDfFlL]?/)}],relevance:0};return{
+name:"Java",aliases:["jsp"],keywords:r,illegal:/<\/|#/,
+contains:[e.COMMENT("/\\*\\*","\\*/",{relevance:0,contains:[{begin:/\w+@/,
+relevance:0},{className:"doctag",begin:"@[A-Za-z]+"}]
+}),e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,{
+className:"class",beginKeywords:"class interface enum",end:/[{;=]/,
+excludeEnd:!0,keywords:"class interface enum",illegal:/[:"\[\]]/,contains:[{
+beginKeywords:"extends implements"},e.UNDERSCORE_TITLE_MODE]},{
+beginKeywords:"new throw return else",relevance:0},{className:"class",
+begin:"record\\s+"+e.UNDERSCORE_IDENT_RE+"\\s*\\(",returnBegin:!0,excludeEnd:!0,
+end:/[{;=]/,keywords:r,contains:[{beginKeywords:"record"},{
+begin:e.UNDERSCORE_IDENT_RE+"\\s*\\(",returnBegin:!0,relevance:0,
+contains:[e.UNDERSCORE_TITLE_MODE]},{className:"params",begin:/\(/,end:/\)/,
+keywords:r,relevance:0,contains:[e.C_BLOCK_COMMENT_MODE]
+},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{className:"function",
+begin:"([\xc0-\u02b8a-zA-Z_$][\xc0-\u02b8a-zA-Z_$0-9]*(<[\xc0-\u02b8a-zA-Z_$][\xc0-\u02b8a-zA-Z_$0-9]*(\\s*,\\s*[\xc0-\u02b8a-zA-Z_$][\xc0-\u02b8a-zA-Z_$0-9]*)*>)?\\s+)+"+e.UNDERSCORE_IDENT_RE+"\\s*\\(",
+returnBegin:!0,end:/[{;=]/,excludeEnd:!0,keywords:r,contains:[{
+begin:e.UNDERSCORE_IDENT_RE+"\\s*\\(",returnBegin:!0,relevance:0,
+contains:[e.UNDERSCORE_TITLE_MODE]},{className:"params",begin:/\(/,end:/\)/,
+keywords:r,relevance:0,
+contains:[i,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.C_NUMBER_MODE,e.C_BLOCK_COMMENT_MODE]
+},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},c,i]}}}());
+hljs.registerLanguage("javascript",function(){"use strict"
+;const e="[A-Za-z$_][0-9A-Za-z$_]*",n=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","switch","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends"],a=["true","false","null","undefined","NaN","Infinity"],s=[].concat(["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],["arguments","this","super","console","window","document","localStorage","module","global"],["Intl","DataView","Number","Math","Date","String","RegExp","Object","Function","Boolean","Error","Symbol","Set","Map","WeakSet","WeakMap","Proxy","Reflect","JSON","Promise","Float64Array","Int16Array","Int32Array","Int8Array","Uint16Array","Uint32Array","Float32Array","Array","Uint8Array","Uint8ClampedArray","ArrayBuffer"],["EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"])
+;function r(e){return i("(?=",e,")")}function t(e){return i("(",e,")?")}
+function i(...e){return e.map((e=>{
+return(n=e)?"string"==typeof n?n:n.source:null;var n})).join("")}
+return function(c){const o=e,l={begin:/<[A-Za-z0-9\\._:-]+/,
+end:/\/[A-Za-z0-9\\._:-]+>|\/>/,isTrulyOpeningTag:(e,n)=>{
+const a=e[0].length+e.index,s=e.input[a];"<"!==s?">"===s&&(((e,{after:n})=>{
+const a=e[0].replace("<","</");return-1!==e.input.indexOf(a,n)})(e,{after:a
+})||n.ignoreMatch()):n.ignoreMatch()}},g={$pattern:e,keyword:n.join(" "),
+literal:a.join(" "),built_in:s.join(" ")
+},d=(e,n)=>`\\b0[${e}][${n}]([${n}_]*[${n}])?n?`,b=/[1-9]([0-9_]*\d)?/,E=/\d([0-9_]*\d)?/,u=i(/[eE][+-]?/,E),_={
+className:"number",variants:[{begin:d("bB","01")},{begin:d("oO","0-7")},{
+begin:d("xX","0-9a-fA-F")},{begin:i(/\b/,b,"n")},{begin:i(/(\b0)?\./,E,t(u))},{
+begin:i(/\b/,b,t(i(/\./,t(E))),t(u))},{begin:/\b0[\.n]?/}],relevance:0},m={
+className:"subst",begin:"\\$\\{",end:"\\}",keywords:g,contains:[]},N={
+begin:"html`",end:"",starts:{end:"`",returnEnd:!1,
+contains:[c.BACKSLASH_ESCAPE,m],subLanguage:"xml"}},y={begin:"css`",end:"",
+starts:{end:"`",returnEnd:!1,contains:[c.BACKSLASH_ESCAPE,m],subLanguage:"css"}
+},f={className:"string",begin:"`",end:"`",contains:[c.BACKSLASH_ESCAPE,m]},A={
+className:"comment",variants:[c.COMMENT("/\\*\\*","\\*/",{relevance:0,
+contains:[{className:"doctag",begin:"@[A-Za-z]+",contains:[{className:"type",
+begin:"\\{",end:"\\}",relevance:0},{className:"variable",
+begin:o+"(?=\\s*(-)|$)",endsParent:!0,relevance:0},{begin:/(?=[^\n])\s/,
+relevance:0}]}]}),c.C_BLOCK_COMMENT_MODE,c.C_LINE_COMMENT_MODE]
+},p=[c.APOS_STRING_MODE,c.QUOTE_STRING_MODE,N,y,f,_,c.REGEXP_MODE]
+;m.contains=p.concat({begin:/{/,end:/}/,keywords:g,contains:["self"].concat(p)})
+;const O=[].concat(A,m.contains),T=O.concat([{begin:/\(/,end:/\)/,keywords:g,
+contains:["self"].concat(O)}]),R={className:"params",begin:/\(/,end:/\)/,
+excludeBegin:!0,excludeEnd:!0,keywords:g,contains:T};return{name:"Javascript",
+aliases:["js","jsx","mjs","cjs"],keywords:g,exports:{PARAMS_CONTAINS:T},
+illegal:/#(?![$_A-z])/,contains:[c.SHEBANG({label:"shebang",binary:"node",
+relevance:5}),{label:"use_strict",className:"meta",relevance:10,
+begin:/^\s*['"]use (strict|asm)['"]/
+},c.APOS_STRING_MODE,c.QUOTE_STRING_MODE,N,y,f,A,_,{
+begin:i(/[{,\n]\s*/,r(i(/(\/\/.*$)*/,/(\/\*(.|\n)*\*\/)*/,/\s*/,o+"\\s*:"))),
+relevance:0,contains:[{className:"attr",begin:o+r("\\s*:"),relevance:0}]},{
+begin:"("+c.RE_STARTERS_RE+"|\\b(case|return|throw)\\b)\\s*",
+keywords:"return throw case",contains:[A,c.REGEXP_MODE,{className:"function",
+begin:"(\\([^()]*(\\([^()]*(\\([^()]*\\))*[^()]*\\))*[^()]*\\)|"+c.UNDERSCORE_IDENT_RE+")\\s*=>",
+returnBegin:!0,end:"\\s*=>",contains:[{className:"params",variants:[{
+begin:c.UNDERSCORE_IDENT_RE},{className:null,begin:/\(\s*\)/,skip:!0},{
+begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:g,contains:T}]}]},{
+begin:/,/,relevance:0},{className:"",begin:/\s/,end:/\s*/,skip:!0},{variants:[{
+begin:"<>",end:"</>"},{begin:l.begin,"on:begin":l.isTrulyOpeningTag,end:l.end}],
+subLanguage:"xml",contains:[{begin:l.begin,end:l.end,skip:!0,contains:["self"]}]
+}],relevance:0},{className:"function",beginKeywords:"function",end:/[{;]/,
+excludeEnd:!0,keywords:g,contains:["self",c.inherit(c.TITLE_MODE,{begin:o}),R],
+illegal:/%/},{className:"function",
+begin:c.UNDERSCORE_IDENT_RE+"\\([^()]*(\\([^()]*(\\([^()]*\\))*[^()]*\\))*[^()]*\\)\\s*{",
+returnBegin:!0,contains:[R,c.inherit(c.TITLE_MODE,{begin:o})]},{variants:[{
+begin:"\\."+o},{begin:"\\$"+o}],relevance:0},{className:"class",
+beginKeywords:"class",end:/[{;=]/,excludeEnd:!0,illegal:/[:"\[\]]/,contains:[{
+beginKeywords:"extends"},c.UNDERSCORE_TITLE_MODE]},{begin:/\b(?=constructor)/,
+end:/[\{;]/,excludeEnd:!0,contains:[c.inherit(c.TITLE_MODE,{begin:o}),"self",R]
+},{begin:"(get|set)\\s+(?="+o+"\\()",end:/{/,keywords:"get set",
+contains:[c.inherit(c.TITLE_MODE,{begin:o}),{begin:/\(\)/},R]},{begin:/\$[(.]/}]
+}}}());
+hljs.registerLanguage("json",function(){"use strict";return function(n){var e={
+literal:"true false null"
+},i=[n.C_LINE_COMMENT_MODE,n.C_BLOCK_COMMENT_MODE],t=[n.QUOTE_STRING_MODE,n.C_NUMBER_MODE],a={
+end:",",endsWithParent:!0,excludeEnd:!0,contains:t,keywords:e},l={begin:"{",
+end:"}",contains:[{className:"attr",begin:/"/,end:/"/,
+contains:[n.BACKSLASH_ESCAPE],illegal:"\\n"},n.inherit(a,{begin:/:/
+})].concat(i),illegal:"\\S"},s={begin:"\\[",end:"\\]",contains:[n.inherit(a)],
+illegal:"\\S"};return t.push(l,s),i.forEach((function(n){t.push(n)})),{
+name:"JSON",contains:t,keywords:e,illegal:"\\S"}}}());
+hljs.registerLanguage("kotlin",function(){"use strict";return function(e){
+var n={
+keyword:"abstract as val var vararg get set class object open private protected public noinline crossinline dynamic final enum if else do while for when throw try catch finally import package is in fun override companion reified inline lateinit init interface annotation data sealed internal infix operator out by constructor super tailrec where const inner suspend typealias external expect actual",
+built_in:"Byte Short Char Int Long Boolean Float Double Void Unit Nothing",
+literal:"true false null"},a={className:"symbol",begin:e.UNDERSCORE_IDENT_RE+"@"
+},i={className:"subst",begin:"\\${",end:"}",contains:[e.C_NUMBER_MODE]},s={
+className:"variable",begin:"\\$"+e.UNDERSCORE_IDENT_RE},t={className:"string",
+variants:[{begin:'"""',end:'"""(?=[^"])',contains:[s,i]},{begin:"'",end:"'",
+illegal:/\n/,contains:[e.BACKSLASH_ESCAPE]},{begin:'"',end:'"',illegal:/\n/,
+contains:[e.BACKSLASH_ESCAPE,s,i]}]};i.contains.push(t);var r={className:"meta",
+begin:"@(?:file|property|field|get|set|receiver|param|setparam|delegate)\\s*:(?:\\s*"+e.UNDERSCORE_IDENT_RE+")?"
+},l={className:"meta",begin:"@"+e.UNDERSCORE_IDENT_RE,contains:[{begin:/\(/,
+end:/\)/,contains:[e.inherit(t,{className:"meta-string"})]}]
+},c=e.COMMENT("/\\*","\\*/",{contains:[e.C_BLOCK_COMMENT_MODE]}),o={variants:[{
+className:"type",begin:e.UNDERSCORE_IDENT_RE},{begin:/\(/,end:/\)/,contains:[]}]
+},d=o;return d.variants[1].contains=[o],o.variants[1].contains=[d],{
+name:"Kotlin",aliases:["kt"],keywords:n,contains:[e.COMMENT("/\\*\\*","\\*/",{
+relevance:0,contains:[{className:"doctag",begin:"@[A-Za-z]+"}]
+}),e.C_LINE_COMMENT_MODE,c,{className:"keyword",
+begin:/\b(break|continue|return|this)\b/,starts:{contains:[{className:"symbol",
+begin:/@\w+/}]}},a,r,l,{className:"function",beginKeywords:"fun",end:"[(]|$",
+returnBegin:!0,excludeEnd:!0,keywords:n,
+illegal:/fun\s+(<.*>)?[^\s\(]+(\s+[^\s\(]+)\s*=/,relevance:5,contains:[{
+begin:e.UNDERSCORE_IDENT_RE+"\\s*\\(",returnBegin:!0,relevance:0,
+contains:[e.UNDERSCORE_TITLE_MODE]},{className:"type",begin:/</,end:/>/,
+keywords:"reified",relevance:0},{className:"params",begin:/\(/,end:/\)/,
+endsParent:!0,keywords:n,relevance:0,contains:[{begin:/:/,end:/[=,\/]/,
+endsWithParent:!0,contains:[o,e.C_LINE_COMMENT_MODE,c],relevance:0
+},e.C_LINE_COMMENT_MODE,c,r,l,t,e.C_NUMBER_MODE]},c]},{className:"class",
+beginKeywords:"class interface trait",end:/[:\{(]|$/,excludeEnd:!0,
+illegal:"extends implements",contains:[{
+beginKeywords:"public protected internal private constructor"
+},e.UNDERSCORE_TITLE_MODE,{className:"type",begin:/</,end:/>/,excludeBegin:!0,
+excludeEnd:!0,relevance:0},{className:"type",begin:/[,:]\s*/,end:/[<\(,]|$/,
+excludeBegin:!0,returnEnd:!0},r,l]},t,{className:"meta",begin:"^#!/usr/bin/env",
+end:"$",illegal:"\n"},{className:"number",
+begin:"\\b(0[bB]([01]+[01_]+[01]+|[01]+)|0[xX]([a-fA-F0-9]+[a-fA-F0-9_]+[a-fA-F0-9]+|[a-fA-F0-9]+)|(([\\d]+[\\d_]+[\\d]+|[\\d]+)(\\.([\\d]+[\\d_]+[\\d]+|[\\d]+))?|\\.([\\d]+[\\d_]+[\\d]+|[\\d]+))([eE][-+]?\\d+)?)[lLfF]?",
+relevance:0}]}}}());
+hljs.registerLanguage("less",function(){"use strict";return function(e){
+var n="([\\w-]+|@{[\\w-]+})",a=[],s=[],t=function(e){return{className:"string",
+begin:"~?"+e+".*?"+e}},r=function(e,n,a){return{className:e,begin:n,relevance:a}
+},i={begin:"\\(",end:"\\)",contains:s,relevance:0}
+;s.push(e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,t("'"),t('"'),e.CSS_NUMBER_MODE,{
+begin:"(url|data-uri)\\(",starts:{className:"string",end:"[\\)\\n]",
+excludeEnd:!0}
+},r("number","#[0-9A-Fa-f]+\\b"),i,r("variable","@@?[\\w-]+",10),r("variable","@{[\\w-]+}"),r("built_in","~?`[^`]*?`"),{
+className:"attribute",begin:"[\\w-]+\\s*:",end:":",returnBegin:!0,excludeEnd:!0
+},{className:"meta",begin:"!important"});var c=s.concat({begin:"{",end:"}",
+contains:a}),l={beginKeywords:"when",endsWithParent:!0,contains:[{
+beginKeywords:"and not"}].concat(s)},o={begin:n+"\\s*:",returnBegin:!0,
+end:"[;}]",relevance:0,contains:[{className:"attribute",begin:n,end:":",
+excludeEnd:!0,starts:{endsWithParent:!0,illegal:"[<=$]",relevance:0,contains:s}
+}]},g={className:"keyword",
+begin:"@(import|media|charset|font-face|(-[a-z]+-)?keyframes|supports|document|namespace|page|viewport|host)\\b",
+starts:{end:"[;{}]",returnEnd:!0,contains:s,relevance:0}},d={
+className:"variable",variants:[{begin:"@[\\w-]+\\s*:",relevance:15},{
+begin:"@[\\w-]+"}],starts:{end:"[;}]",returnEnd:!0,contains:c}},b={variants:[{
+begin:"[\\.#:&\\[>]",end:"[;{}]"},{begin:n,end:"{"}],returnBegin:!0,
+returnEnd:!0,illegal:"[<='$\"]",relevance:0,
+contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,l,r("keyword","all\\b"),r("variable","@{[\\w-]+}"),r("selector-tag",n+"%?",0),r("selector-id","#"+n),r("selector-class","\\."+n,0),r("selector-tag","&",0),{
+className:"selector-attr",begin:"\\[",end:"\\]"},{className:"selector-pseudo",
+begin:/:(:)?[a-zA-Z0-9\_\-\+\(\)"'.]+/},{begin:"\\(",end:"\\)",contains:c},{
+begin:"!important"}]}
+;return a.push(e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,g,d,o,b),{
+name:"Less",case_insensitive:!0,illegal:"[=>'/<($\"]",contains:a}}}());
+hljs.registerLanguage("lua",function(){"use strict";return function(e){
+var t="\\[=*\\[",a="\\]=*\\]",n={begin:t,end:a,contains:["self"]
+},o=[e.COMMENT("--(?!\\[=*\\[)","$"),e.COMMENT("--\\[=*\\[",a,{contains:[n],
+relevance:10})];return{name:"Lua",keywords:{$pattern:e.UNDERSCORE_IDENT_RE,
+literal:"true false nil",
+keyword:"and break do else elseif end for goto if in local not or repeat return then until while",
+built_in:"_G _ENV _VERSION __index __newindex __mode __call __metatable __tostring __len __gc __add __sub __mul __div __mod __pow __concat __unm __eq __lt __le assert collectgarbage dofile error getfenv getmetatable ipairs load loadfile loadstring module next pairs pcall print rawequal rawget rawset require select setfenv setmetatable tonumber tostring type unpack xpcall arg self coroutine resume yield status wrap create running debug getupvalue debug sethook getmetatable gethook setmetatable setlocal traceback setfenv getinfo setupvalue getlocal getregistry getfenv io lines write close flush open output type read stderr stdin input stdout popen tmpfile math log max acos huge ldexp pi cos tanh pow deg tan cosh sinh random randomseed frexp ceil floor rad abs sqrt modf asin min mod fmod log10 atan2 exp sin atan os exit setlocale date getenv difftime remove time clock tmpname rename execute package preload loadlib loaded loaders cpath config path seeall string sub upper len gfind rep find match char dump gmatch reverse byte format gsub lower table setn insert getn foreachi maxn foreach concat sort remove"
+},contains:o.concat([{className:"function",beginKeywords:"function",end:"\\)",
+contains:[e.inherit(e.TITLE_MODE,{
+begin:"([_a-zA-Z]\\w*\\.)*([_a-zA-Z]\\w*:)?[_a-zA-Z]\\w*"}),{className:"params",
+begin:"\\(",endsWithParent:!0,contains:o}].concat(o)
+},e.C_NUMBER_MODE,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,{className:"string",
+begin:t,end:a,contains:[n],relevance:5}])}}}());
+hljs.registerLanguage("makefile",function(){"use strict";return function(e){
+var i={className:"variable",variants:[{
+begin:"\\$\\("+e.UNDERSCORE_IDENT_RE+"\\)",contains:[e.BACKSLASH_ESCAPE]},{
+begin:/\$[@%<?\^\+\*]/}]},n={className:"string",begin:/"/,end:/"/,
+contains:[e.BACKSLASH_ESCAPE,i]},a={className:"variable",begin:/\$\([\w-]+\s/,
+end:/\)/,keywords:{
+built_in:"subst patsubst strip findstring filter filter-out sort word wordlist firstword lastword dir notdir suffix basename addsuffix addprefix join wildcard realpath abspath error warning shell origin flavor foreach if or and call eval file value"
+},contains:[i]},r={begin:"^"+e.UNDERSCORE_IDENT_RE+"\\s*(?=[:+?]?=)"},s={
+className:"section",begin:/^[^\s]+:/,end:/$/,contains:[i]};return{
+name:"Makefile",aliases:["mk","mak"],keywords:{$pattern:/[\w-]+/,
+keyword:"define endef undefine ifdef ifndef ifeq ifneq else endif include -include sinclude override export unexport private vpath"
+},contains:[e.HASH_COMMENT_MODE,i,n,a,r,{className:"meta",begin:/^\.PHONY:/,
+end:/$/,keywords:{$pattern:/[\.\w]+/,"meta-keyword":".PHONY"}},s]}}}());
+hljs.registerLanguage("xml",function(){"use strict";return function(e){var n={
+className:"symbol",begin:"&[a-z]+;|&#[0-9]+;|&#x[a-f0-9]+;"},a={begin:"\\s",
+contains:[{className:"meta-keyword",begin:"#?[a-z_][a-z1-9_-]+",illegal:"\\n"}]
+},s=e.inherit(a,{begin:"\\(",end:"\\)"}),t=e.inherit(e.APOS_STRING_MODE,{
+className:"meta-string"}),i=e.inherit(e.QUOTE_STRING_MODE,{
+className:"meta-string"}),c={endsWithParent:!0,illegal:/</,relevance:0,
+contains:[{className:"attr",begin:"[A-Za-z0-9\\._:-]+",relevance:0},{
+begin:/=\s*/,relevance:0,contains:[{className:"string",endsParent:!0,variants:[{
+begin:/"/,end:/"/,contains:[n]},{begin:/'/,end:/'/,contains:[n]},{
+begin:/[^\s"'=<>`]+/}]}]}]};return{name:"HTML, XML",
+aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist","wsf","svg"],
+case_insensitive:!0,contains:[{className:"meta",begin:"<![a-z]",end:">",
+relevance:10,contains:[a,i,t,s,{begin:"\\[",end:"\\]",contains:[{
+className:"meta",begin:"<![a-z]",end:">",contains:[a,s,i,t]}]}]
+},e.COMMENT("\x3c!--","--\x3e",{relevance:10}),{begin:"<\\!\\[CDATA\\[",
+end:"\\]\\]>",relevance:10},n,{className:"meta",begin:/<\?xml/,end:/\?>/,
+relevance:10},{className:"tag",begin:"<style(?=\\s|>)",end:">",keywords:{
+name:"style"},contains:[c],starts:{end:"</style>",returnEnd:!0,
+subLanguage:["css","xml"]}},{className:"tag",begin:"<script(?=\\s|>)",end:">",
+keywords:{name:"script"},contains:[c],starts:{end:"<\/script>",returnEnd:!0,
+subLanguage:["javascript","handlebars","xml"]}},{className:"tag",begin:"</?",
+end:"/?>",contains:[{className:"name",begin:/[^\/><\s]+/,relevance:0},c]}]}}
+}());
+hljs.registerLanguage("markdown",function(){"use strict";return function(n){
+const e={begin:"<",end:">",subLanguage:"xml",relevance:0},a={
+begin:"\\[.+?\\][\\(\\[].*?[\\)\\]]",returnBegin:!0,contains:[{
+className:"string",begin:"\\[",end:"\\]",excludeBegin:!0,returnEnd:!0,
+relevance:0},{className:"link",begin:"\\]\\(",end:"\\)",excludeBegin:!0,
+excludeEnd:!0},{className:"symbol",begin:"\\]\\[",end:"\\]",excludeBegin:!0,
+excludeEnd:!0}],relevance:10},i={className:"strong",contains:[],variants:[{
+begin:/_{2}/,end:/_{2}/},{begin:/\*{2}/,end:/\*{2}/}]},s={className:"emphasis",
+contains:[],variants:[{begin:/\*(?!\*)/,end:/\*/},{begin:/_(?!_)/,end:/_/,
+relevance:0}]};i.contains.push(s),s.contains.push(i);var c=[e,a]
+;return i.contains=i.contains.concat(c),s.contains=s.contains.concat(c),{
+name:"Markdown",aliases:["md","mkdown","mkd"],contains:[{className:"section",
+variants:[{begin:"^#{1,6}",end:"$",contains:c=c.concat(i,s)},{
+begin:"(?=^.+?\\n[=-]{2,}$)",contains:[{begin:"^[=-]*$"},{begin:"^",end:"\\n",
+contains:c}]}]},e,{className:"bullet",begin:"^[ \t]*([*+-]|(\\d+\\.))(?=\\s+)",
+end:"\\s+",excludeEnd:!0},i,s,{className:"quote",begin:"^>\\s+",contains:c,
+end:"$"},{className:"code",variants:[{begin:"(`{3,})(.|\\n)*?\\1`*[ ]*"},{
+begin:"(~{3,})(.|\\n)*?\\1~*[ ]*"},{begin:"```",end:"```+[ ]*$"},{begin:"~~~",
+end:"~~~+[ ]*$"},{begin:"`.+?`"},{begin:"(?=^( {4}|\\t))",contains:[{
+begin:"^( {4}|\\t)",end:"(\\n)$"}],relevance:0}]},{begin:"^[-\\*]{3,}",end:"$"
+},a,{begin:/^\[[^\n]+\]:/,returnBegin:!0,contains:[{className:"symbol",
+begin:/\[/,end:/\]/,excludeBegin:!0,excludeEnd:!0},{className:"link",
+begin:/:\s*/,end:/$/,excludeBegin:!0}]}]}}}());
+hljs.registerLanguage("nginx",function(){"use strict";return function(e){var n={
+className:"variable",variants:[{begin:/\$\d+/},{begin:/\$\{/,end:/}/},{
+begin:"[\\$\\@]"+e.UNDERSCORE_IDENT_RE}]},a={endsWithParent:!0,keywords:{
+$pattern:"[a-z/_]+",
+literal:"on off yes no true false none blocked debug info notice warn error crit select break last permanent redirect kqueue rtsig epoll poll /dev/poll"
+},relevance:0,illegal:"=>",contains:[e.HASH_COMMENT_MODE,{className:"string",
+contains:[e.BACKSLASH_ESCAPE,n],variants:[{begin:/"/,end:/"/},{begin:/'/,end:/'/
+}]},{begin:"([a-z]+):/",end:"\\s",endsWithParent:!0,excludeEnd:!0,contains:[n]
+},{className:"regexp",contains:[e.BACKSLASH_ESCAPE,n],variants:[{begin:"\\s\\^",
+end:"\\s|{|;",returnEnd:!0},{begin:"~\\*?\\s+",end:"\\s|{|;",returnEnd:!0},{
+begin:"\\*(\\.[a-z\\-]+)+"},{begin:"([a-z\\-]+\\.)+\\*"}]},{className:"number",
+begin:"\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}(:\\d{1,5})?\\b"},{
+className:"number",begin:"\\b\\d+[kKmMgGdshdwy]*\\b",relevance:0},n]};return{
+name:"Nginx config",aliases:["nginxconf"],contains:[e.HASH_COMMENT_MODE,{
+begin:e.UNDERSCORE_IDENT_RE+"\\s+{",returnBegin:!0,end:"{",contains:[{
+className:"section",begin:e.UNDERSCORE_IDENT_RE}],relevance:0},{
+begin:e.UNDERSCORE_IDENT_RE+"\\s",end:";|{",returnBegin:!0,contains:[{
+className:"attribute",begin:e.UNDERSCORE_IDENT_RE,starts:a}],relevance:0}],
+illegal:"[^\\s\\}]"}}}());
+hljs.registerLanguage("objectivec",function(){"use strict";return function(e){
+var n=/[a-zA-Z@][a-zA-Z0-9_]*/,_={$pattern:n,
+keyword:"@interface @class @protocol @implementation"};return{
+name:"Objective-C",aliases:["mm","objc","obj-c","obj-c++","objective-c++"],
+keywords:{$pattern:n,
+keyword:"int float while char export sizeof typedef const struct for union unsigned long volatile static bool mutable if do return goto void enum else break extern asm case short default double register explicit signed typename this switch continue wchar_t inline readonly assign readwrite self @synchronized id typeof nonatomic super unichar IBOutlet IBAction strong weak copy in out inout bycopy byref oneway __strong __weak __block __autoreleasing @private @protected @public @try @property @end @throw @catch @finally @autoreleasepool @synthesize @dynamic @selector @optional @required @encode @package @import @defs @compatibility_alias __bridge __bridge_transfer __bridge_retained __bridge_retain __covariant __contravariant __kindof _Nonnull _Nullable _Null_unspecified __FUNCTION__ __PRETTY_FUNCTION__ __attribute__ getter setter retain unsafe_unretained nonnull nullable null_unspecified null_resettable class instancetype NS_DESIGNATED_INITIALIZER NS_UNAVAILABLE NS_REQUIRES_SUPER NS_RETURNS_INNER_POINTER NS_INLINE NS_AVAILABLE NS_DEPRECATED NS_ENUM NS_OPTIONS NS_SWIFT_UNAVAILABLE NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_END NS_REFINED_FOR_SWIFT NS_SWIFT_NAME NS_SWIFT_NOTHROW NS_DURING NS_HANDLER NS_ENDHANDLER NS_VALUERETURN NS_VOIDRETURN",
+literal:"false true FALSE TRUE nil YES NO NULL",
+built_in:"BOOL dispatch_once_t dispatch_queue_t dispatch_sync dispatch_async dispatch_once"
+},illegal:"</",contains:[{className:"built_in",
+begin:"\\b(AV|CA|CF|CG|CI|CL|CM|CN|CT|MK|MP|MTK|MTL|NS|SCN|SK|UI|WK|XC)\\w+"
+},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,e.C_NUMBER_MODE,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,{
+className:"string",variants:[{begin:'@"',end:'"',illegal:"\\n",
+contains:[e.BACKSLASH_ESCAPE]}]},{className:"meta",begin:/#\s*[a-z]+\b/,end:/$/,
+keywords:{
+"meta-keyword":"if else elif endif define undef warning error line pragma ifdef ifndef include"
+},contains:[{begin:/\\\n/,relevance:0},e.inherit(e.QUOTE_STRING_MODE,{
+className:"meta-string"}),{className:"meta-string",begin:/<.*?>/,end:/$/,
+illegal:"\\n"},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{
+className:"class",begin:"("+_.keyword.split(" ").join("|")+")\\b",end:"({|$)",
+excludeEnd:!0,keywords:_,contains:[e.UNDERSCORE_TITLE_MODE]},{
+begin:"\\."+e.UNDERSCORE_IDENT_RE,relevance:0}]}}}());
+hljs.registerLanguage("perl",function(){"use strict";return function(e){var n={
+$pattern:/[\w.]+/,
+keyword:"getpwent getservent quotemeta msgrcv scalar kill dbmclose undef lc ma syswrite tr send umask sysopen shmwrite vec qx utime local oct semctl localtime readpipe do return format read sprintf dbmopen pop getpgrp not getpwnam rewinddir qq fileno qw endprotoent wait sethostent bless s|0 opendir continue each sleep endgrent shutdown dump chomp connect getsockname die socketpair close flock exists index shmget sub for endpwent redo lstat msgctl setpgrp abs exit select print ref gethostbyaddr unshift fcntl syscall goto getnetbyaddr join gmtime symlink semget splice x|0 getpeername recv log setsockopt cos last reverse gethostbyname getgrnam study formline endhostent times chop length gethostent getnetent pack getprotoent getservbyname rand mkdir pos chmod y|0 substr endnetent printf next open msgsnd readdir use unlink getsockopt getpriority rindex wantarray hex system getservbyport endservent int chr untie rmdir prototype tell listen fork shmread ucfirst setprotoent else sysseek link getgrgid shmctl waitpid unpack getnetbyname reset chdir grep split require caller lcfirst until warn while values shift telldir getpwuid my getprotobynumber delete and sort uc defined srand accept package seekdir getprotobyname semop our rename seek if q|0 chroot sysread setpwent no crypt getc chown sqrt write setnetent setpriority foreach tie sin msgget map stat getlogin unless elsif truncate exec keys glob tied closedir ioctl socket readlink eval xor readline binmode setservent eof ord bind alarm pipe atan2 getgrent exp time push setgrent gt lt or ne m|0 break given say state when"
+},t={className:"subst",begin:"[$@]\\{",end:"\\}",keywords:n},s={begin:"->{",
+end:"}"},r={variants:[{begin:/\$\d/},{
+begin:/[\$%@](\^\w\b|#\w+(::\w+)*|{\w+}|\w+(::\w*)*)/},{begin:/[\$%@][^\s\w{]/,
+relevance:0}]
+},i=[e.BACKSLASH_ESCAPE,t,r],a=[r,e.HASH_COMMENT_MODE,e.COMMENT("^\\=\\w","\\=cut",{
+endsWithParent:!0}),s,{className:"string",contains:i,variants:[{
+begin:"q[qwxr]?\\s*\\(",end:"\\)",relevance:5},{begin:"q[qwxr]?\\s*\\[",
+end:"\\]",relevance:5},{begin:"q[qwxr]?\\s*\\{",end:"\\}",relevance:5},{
+begin:"q[qwxr]?\\s*\\|",end:"\\|",relevance:5},{begin:"q[qwxr]?\\s*\\<",
+end:"\\>",relevance:5},{begin:"qw\\s+q",end:"q",relevance:5},{begin:"'",end:"'",
+contains:[e.BACKSLASH_ESCAPE]},{begin:'"',end:'"'},{begin:"`",end:"`",
+contains:[e.BACKSLASH_ESCAPE]},{begin:"{\\w+}",contains:[],relevance:0},{
+begin:"-?\\w+\\s*\\=\\>",contains:[],relevance:0}]},{className:"number",
+begin:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",
+relevance:0},{
+begin:"(\\/\\/|"+e.RE_STARTERS_RE+"|\\b(split|return|print|reverse|grep)\\b)\\s*",
+keywords:"split return print reverse grep",relevance:0,
+contains:[e.HASH_COMMENT_MODE,{className:"regexp",
+begin:"(s|tr|y)/(\\\\.|[^/])*/(\\\\.|[^/])*/[a-z]*",relevance:10},{
+className:"regexp",begin:"(m|qr)?/",end:"/[a-z]*",contains:[e.BACKSLASH_ESCAPE],
+relevance:0}]},{className:"function",beginKeywords:"sub",
+end:"(\\s*\\(.*?\\))?[;{]",excludeEnd:!0,relevance:5,contains:[e.TITLE_MODE]},{
+begin:"-\\w\\b",relevance:0},{begin:"^__DATA__$",end:"^__END__$",
+subLanguage:"mojolicious",contains:[{begin:"^@@.*",end:"$",className:"comment"}]
+}];return t.contains=a,s.contains=a,{name:"Perl",aliases:["pl","pm"],keywords:n,
+contains:a}}}());
+hljs.registerLanguage("php",function(){"use strict";return function(e){var r={
+begin:"\\$+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*"},t={className:"meta",
+variants:[{begin:/<\?php/,relevance:10},{begin:/<\?[=]?/},{begin:/\?>/}]},a={
+className:"subst",variants:[{begin:/\$\w+/},{begin:/\{\$/,end:/\}/}]
+},n=e.inherit(e.APOS_STRING_MODE,{illegal:null
+}),i=e.inherit(e.QUOTE_STRING_MODE,{illegal:null,
+contains:e.QUOTE_STRING_MODE.contains.concat(a)}),o=e.END_SAME_AS_BEGIN({
+begin:/<<<[ \t]*(\w+)\n/,end:/[ \t]*(\w+)\b/,
+contains:e.QUOTE_STRING_MODE.contains.concat(a)}),l={className:"string",
+contains:[e.BACKSLASH_ESCAPE,t],variants:[e.inherit(n,{begin:"b'",end:"'"
+}),e.inherit(i,{begin:'b"',end:'"'}),i,n,o]},s={
+variants:[e.BINARY_NUMBER_MODE,e.C_NUMBER_MODE]},c={
+keyword:"__CLASS__ __DIR__ __FILE__ __FUNCTION__ __LINE__ __METHOD__ __NAMESPACE__ __TRAIT__ die echo exit include include_once print require require_once array abstract and as binary bool boolean break callable case catch class clone const continue declare default do double else elseif empty enddeclare endfor endforeach endif endswitch endwhile eval extends final finally float for foreach from global goto if implements instanceof insteadof int integer interface isset iterable list match new object or private protected public real return string switch throw trait try unset use var void while xor yield",
+literal:"false null true",
+built_in:"Error|0 AppendIterator ArgumentCountError ArithmeticError ArrayIterator ArrayObject AssertionError BadFunctionCallException BadMethodCallException CachingIterator CallbackFilterIterator CompileError Countable DirectoryIterator DivisionByZeroError DomainException EmptyIterator ErrorException Exception FilesystemIterator FilterIterator GlobIterator InfiniteIterator InvalidArgumentException IteratorIterator LengthException LimitIterator LogicException MultipleIterator NoRewindIterator OutOfBoundsException OutOfRangeException OuterIterator OverflowException ParentIterator ParseError RangeException RecursiveArrayIterator RecursiveCachingIterator RecursiveCallbackFilterIterator RecursiveDirectoryIterator RecursiveFilterIterator RecursiveIterator RecursiveIteratorIterator RecursiveRegexIterator RecursiveTreeIterator RegexIterator RuntimeException SeekableIterator SplDoublyLinkedList SplFileInfo SplFileObject SplFixedArray SplHeap SplMaxHeap SplMinHeap SplObjectStorage SplObserver SplObserver SplPriorityQueue SplQueue SplStack SplSubject SplSubject SplTempFileObject TypeError UnderflowException UnexpectedValueException ArrayAccess Closure Generator Iterator IteratorAggregate Serializable Throwable Traversable WeakReference Directory __PHP_Incomplete_Class parent php_user_filter self static stdClass"
+};return{aliases:["php","php3","php4","php5","php6","php7","php8"],
+case_insensitive:!0,keywords:c,
+contains:[e.HASH_COMMENT_MODE,e.COMMENT("//","$",{contains:[t]
+}),e.COMMENT("/\\*","\\*/",{contains:[{className:"doctag",begin:"@[A-Za-z]+"}]
+}),e.COMMENT("__halt_compiler.+?;",!1,{endsWithParent:!0,
+keywords:"__halt_compiler"}),t,{className:"keyword",begin:/\$this\b/},r,{
+begin:/(::|->)+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/},{className:"function",
+beginKeywords:"fn function",end:/[;{]/,excludeEnd:!0,illegal:"[$%\\[]",
+contains:[e.UNDERSCORE_TITLE_MODE,{className:"params",begin:"\\(",end:"\\)",
+excludeBegin:!0,excludeEnd:!0,keywords:c,
+contains:["self",r,e.C_BLOCK_COMMENT_MODE,l,s]}]},{className:"class",
+beginKeywords:"class interface",end:"{",excludeEnd:!0,illegal:/[:\(\$"]/,
+contains:[{beginKeywords:"extends implements"},e.UNDERSCORE_TITLE_MODE]},{
+beginKeywords:"namespace",end:";",illegal:/[\.']/,
+contains:[e.UNDERSCORE_TITLE_MODE]},{beginKeywords:"use",end:";",
+contains:[e.UNDERSCORE_TITLE_MODE]},{begin:"=>"},l,s]}}}());
+hljs.registerLanguage("php-template",function(){"use strict";return function(n){
+return{name:"PHP template",subLanguage:"xml",contains:[{begin:/<\?(php|=)?/,
+end:/\?>/,subLanguage:"php",contains:[{begin:"/\\*",end:"\\*/",skip:!0},{
+begin:'b"',end:'"',skip:!0},{begin:"b'",end:"'",skip:!0
+},n.inherit(n.APOS_STRING_MODE,{illegal:null,className:null,contains:null,
+skip:!0}),n.inherit(n.QUOTE_STRING_MODE,{illegal:null,className:null,
+contains:null,skip:!0})]}]}}}());
+hljs.registerLanguage("plaintext",function(){"use strict";return function(t){
+return{name:"Plain text",aliases:["text","txt"],disableAutodetect:!0}}}());
+hljs.registerLanguage("properties",function(){"use strict";return function(e){
+var n="[ \\t\\f]*",t="("+n+"[:=]"+n+"|[ \\t\\f]+)",a="([^\\\\\\W:= \\t\\f\\n]|\\\\.)+",s="([^\\\\:= \\t\\f\\n]|\\\\.)+",r={
+end:t,relevance:0,starts:{className:"string",end:/$/,relevance:0,contains:[{
+begin:"\\\\\\n"}]}};return{name:".properties",case_insensitive:!0,illegal:/\S/,
+contains:[e.COMMENT("^\\s*[!#]","$"),{begin:a+t,returnBegin:!0,contains:[{
+className:"attr",begin:a,endsParent:!0,relevance:0}],starts:r},{begin:s+t,
+returnBegin:!0,relevance:0,contains:[{className:"meta",begin:s,endsParent:!0,
+relevance:0}],starts:r},{className:"attr",relevance:0,begin:s+n+"$"}]}}}());
+hljs.registerLanguage("python",function(){"use strict";return function(e){
+const n={
+keyword:"and as assert async await break class continue def del elif else except finally for  from global if import in is lambda nonlocal|10 not or pass raise return try while with yield",
+built_in:"__import__ abs all any ascii bin bool breakpoint bytearray bytes callable chr classmethod compile complex delattr dict dir divmod enumerate eval exec filter float format frozenset getattr globals hasattr hash help hex id input int isinstance issubclass iter len list locals map max memoryview min next object oct open ord pow print property range repr reversed round set setattr slice sorted staticmethod str sum super tuple type vars zip",
+literal:"__debug__ Ellipsis False None NotImplemented True"},a={
+className:"meta",begin:/^(>>>|\.\.\.) /},s={className:"subst",begin:/\{/,
+end:/\}/,keywords:n,illegal:/#/},i={begin:/\{\{/,relevance:0},r={
+className:"string",contains:[e.BACKSLASH_ESCAPE],variants:[{
+begin:/([uU]|[bB]|[rR]|[bB][rR]|[rR][bB])?'''/,end:/'''/,
+contains:[e.BACKSLASH_ESCAPE,a],relevance:10},{
+begin:/([uU]|[bB]|[rR]|[bB][rR]|[rR][bB])?"""/,end:/"""/,
+contains:[e.BACKSLASH_ESCAPE,a],relevance:10},{
+begin:/([fF][rR]|[rR][fF]|[fF])'''/,end:/'''/,
+contains:[e.BACKSLASH_ESCAPE,a,i,s]},{begin:/([fF][rR]|[rR][fF]|[fF])"""/,
+end:/"""/,contains:[e.BACKSLASH_ESCAPE,a,i,s]},{begin:/([uU]|[rR])'/,end:/'/,
+relevance:10},{begin:/([uU]|[rR])"/,end:/"/,relevance:10},{
+begin:/([bB]|[bB][rR]|[rR][bB])'/,end:/'/},{begin:/([bB]|[bB][rR]|[rR][bB])"/,
+end:/"/},{begin:/([fF][rR]|[rR][fF]|[fF])'/,end:/'/,
+contains:[e.BACKSLASH_ESCAPE,i,s]},{begin:/([fF][rR]|[rR][fF]|[fF])"/,end:/"/,
+contains:[e.BACKSLASH_ESCAPE,i,s]},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]},t={
+className:"number",relevance:0,variants:[{begin:e.BINARY_NUMBER_RE+"[lLjJ]?"},{
+begin:"\\b(0o[0-7]+)[lLjJ]?"},{begin:e.C_NUMBER_RE+"[lLjJ]?"}]},l={
+className:"params",variants:[{begin:/\(\s*\)/,skip:!0,className:null},{
+begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:n,
+contains:["self",a,t,r,e.HASH_COMMENT_MODE]}]};return s.contains=[r,t,a],{
+name:"Python",aliases:["py","gyp","ipython"],keywords:n,
+illegal:/(<\/|->|\?)|=>/,contains:[a,t,{beginKeywords:"if",relevance:0
+},r,e.HASH_COMMENT_MODE,{variants:[{className:"function",beginKeywords:"def"},{
+className:"class",beginKeywords:"class"}],end:/:/,illegal:/[${=;\n,]/,
+contains:[e.UNDERSCORE_TITLE_MODE,l,{begin:/->/,endsWithParent:!0,
+keywords:"None"}]},{className:"meta",begin:/^[\t ]*@/,end:/$/},{
+begin:/\b(print|exec)\(/}]}}}());
+hljs.registerLanguage("python-repl",function(){"use strict";return function(n){
+return{aliases:["pycon"],contains:[{className:"meta",starts:{end:/ |$/,starts:{
+end:"$",subLanguage:"python"}},variants:[{begin:/^>>>(?=[ ]|$)/},{
+begin:/^\.\.\.(?=[ ]|$)/}]}]}}}());
+hljs.registerLanguage("ruby",function(){"use strict";return function(e){
+var n="[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?",a={
+keyword:"and then defined module in return redo if BEGIN retry end for self when next until do begin unless END rescue else break undef not super class case require yield alias while ensure elsif or include attr_reader attr_writer attr_accessor",
+literal:"true false nil"},s={className:"doctag",begin:"@[A-Za-z]+"},i={
+begin:"#<",end:">"},r=[e.COMMENT("#","$",{contains:[s]
+}),e.COMMENT("^\\=begin","^\\=end",{contains:[s],relevance:10
+}),e.COMMENT("^__END__","\\n$")],c={className:"subst",begin:"#\\{",end:"}",
+keywords:a},t={className:"string",contains:[e.BACKSLASH_ESCAPE,c],variants:[{
+begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/`/,end:/`/},{
+begin:"%[qQwWx]?\\(",end:"\\)"},{begin:"%[qQwWx]?\\[",end:"\\]"},{
+begin:"%[qQwWx]?{",end:"}"},{begin:"%[qQwWx]?<",end:">"},{begin:"%[qQwWx]?/",
+end:"/"},{begin:"%[qQwWx]?%",end:"%"},{begin:"%[qQwWx]?-",end:"-"},{
+begin:"%[qQwWx]?\\|",end:"\\|"},{
+begin:/\B\?(\\\d{1,3}|\\x[A-Fa-f0-9]{1,2}|\\u[A-Fa-f0-9]{4}|\\?\S)\b/},{
+begin:/<<[-~]?'?(\w+)(?:.|\n)*?\n\s*\1\b/,returnBegin:!0,contains:[{
+begin:/<<[-~]?'?/},e.END_SAME_AS_BEGIN({begin:/(\w+)/,end:/(\w+)/,
+contains:[e.BACKSLASH_ESCAPE,c]})]}]},b={className:"params",begin:"\\(",
+end:"\\)",endsParent:!0,keywords:a},d=[t,i,{className:"class",
+beginKeywords:"class module",end:"$|;",illegal:/=/,
+contains:[e.inherit(e.TITLE_MODE,{begin:"[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?"}),{
+begin:"<\\s*",contains:[{begin:"("+e.IDENT_RE+"::)?"+e.IDENT_RE}]}].concat(r)},{
+className:"function",beginKeywords:"def",end:"$|;",
+contains:[e.inherit(e.TITLE_MODE,{begin:n}),b].concat(r)},{begin:e.IDENT_RE+"::"
+},{className:"symbol",begin:e.UNDERSCORE_IDENT_RE+"(\\!|\\?)?:",relevance:0},{
+className:"symbol",begin:":(?!\\s)",contains:[t,{begin:n}],relevance:0},{
+className:"number",
+begin:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",
+relevance:0},{begin:"(\\$\\W)|((\\$|\\@\\@?)(\\w+))"},{className:"params",
+begin:/\|/,end:/\|/,keywords:a},{begin:"("+e.RE_STARTERS_RE+"|unless)\\s*",
+keywords:"unless",contains:[i,{className:"regexp",
+contains:[e.BACKSLASH_ESCAPE,c],illegal:/\n/,variants:[{begin:"/",end:"/[a-z]*"
+},{begin:"%r{",end:"}[a-z]*"},{begin:"%r\\(",end:"\\)[a-z]*"},{begin:"%r!",
+end:"![a-z]*"},{begin:"%r\\[",end:"\\][a-z]*"}]}].concat(r),relevance:0
+}].concat(r);c.contains=d,b.contains=d;var g=[{begin:/^\s*=>/,starts:{end:"$",
+contains:d}},{className:"meta",
+begin:"^([>?]>|[\\w#]+\\(\\w+\\):\\d+:\\d+>|(\\w+-)?\\d+\\.\\d+\\.\\d(p\\d+)?[^>]+>)",
+starts:{end:"$",contains:d}}];return{name:"Ruby",
+aliases:["rb","gemspec","podspec","thor","irb"],keywords:a,illegal:/\/\*/,
+contains:r.concat(g).concat(d)}}}());
+hljs.registerLanguage("rust",function(){"use strict";return function(e){
+var n="([ui](8|16|32|64|128|size)|f(32|64))?",t="drop i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize f32 f64 str char bool Box Option Result String Vec Copy Send Sized Sync Drop Fn FnMut FnOnce ToOwned Clone Debug PartialEq PartialOrd Eq Ord AsRef AsMut Into From Default Iterator Extend IntoIterator DoubleEndedIterator ExactSizeIterator SliceConcatExt ToString assert! assert_eq! bitflags! bytes! cfg! col! concat! concat_idents! debug_assert! debug_assert_eq! env! panic! file! format! format_args! include_bin! include_str! line! local_data_key! module_path! option_env! print! println! select! stringify! try! unimplemented! unreachable! vec! write! writeln! macro_rules! assert_ne! debug_assert_ne!"
+;return{name:"Rust",aliases:["rs"],keywords:{$pattern:e.IDENT_RE+"!?",
+keyword:"abstract as async await become box break const continue crate do dyn else enum extern false final fn for if impl in let loop macro match mod move mut override priv pub ref return self Self static struct super trait true try type typeof unsafe unsized use virtual where while yield",
+literal:"true false Some None Ok Err",built_in:t},illegal:"</",
+contains:[e.C_LINE_COMMENT_MODE,e.COMMENT("/\\*","\\*/",{contains:["self"]
+}),e.inherit(e.QUOTE_STRING_MODE,{begin:/b?"/,illegal:null}),{
+className:"string",variants:[{begin:/r(#*)"(.|\n)*?"\1(?!#)/},{
+begin:/b?'\\?(x\w{2}|u\w{4}|U\w{8}|.)'/}]},{className:"symbol",
+begin:/'[a-zA-Z_][a-zA-Z0-9_]*/},{className:"number",variants:[{
+begin:"\\b0b([01_]+)"+n},{begin:"\\b0o([0-7_]+)"+n},{
+begin:"\\b0x([A-Fa-f0-9_]+)"+n},{
+begin:"\\b(\\d[\\d_]*(\\.[0-9_]+)?([eE][+-]?[0-9_]+)?)"+n}],relevance:0},{
+className:"function",beginKeywords:"fn",end:"(\\(|<)",excludeEnd:!0,
+contains:[e.UNDERSCORE_TITLE_MODE]},{className:"meta",begin:"#\\!?\\[",
+end:"\\]",contains:[{className:"meta-string",begin:/"/,end:/"/}]},{
+className:"class",beginKeywords:"type",end:";",
+contains:[e.inherit(e.UNDERSCORE_TITLE_MODE,{endsParent:!0})],illegal:"\\S"},{
+className:"class",beginKeywords:"trait enum struct union",end:"{",
+contains:[e.inherit(e.UNDERSCORE_TITLE_MODE,{endsParent:!0})],illegal:"[\\w\\d]"
+},{begin:e.IDENT_RE+"::",keywords:{built_in:t}},{begin:"->"}]}}}());
+hljs.registerLanguage("scss",function(){"use strict";return function(e){
+var t="@[a-z-]+",i={className:"variable",begin:"(\\$[a-zA-Z-][a-zA-Z0-9_-]*)\\b"
+},r={className:"number",begin:"#[0-9A-Fa-f]+"}
+;return e.CSS_NUMBER_MODE,e.QUOTE_STRING_MODE,
+e.APOS_STRING_MODE,e.C_BLOCK_COMMENT_MODE,{name:"SCSS",case_insensitive:!0,
+illegal:"[=/|']",contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{
+className:"selector-id",begin:"\\#[A-Za-z0-9_-]+",relevance:0},{
+className:"selector-class",begin:"\\.[A-Za-z0-9_-]+",relevance:0},{
+className:"selector-attr",begin:"\\[",end:"\\]",illegal:"$"},{
+className:"selector-tag",
+begin:"\\b(a|abbr|acronym|address|area|article|aside|audio|b|base|big|blockquote|body|br|button|canvas|caption|cite|code|col|colgroup|command|datalist|dd|del|details|dfn|div|dl|dt|em|embed|fieldset|figcaption|figure|footer|form|frame|frameset|(h[1-6])|head|header|hgroup|hr|html|i|iframe|img|input|ins|kbd|keygen|label|legend|li|link|map|mark|meta|meter|nav|noframes|noscript|object|ol|optgroup|option|output|p|param|pre|progress|q|rp|rt|ruby|samp|script|section|select|small|span|strike|strong|style|sub|sup|table|tbody|td|textarea|tfoot|th|thead|time|title|tr|tt|ul|var|video)\\b",
+relevance:0},{className:"selector-pseudo",
+begin:":(visited|valid|root|right|required|read-write|read-only|out-range|optional|only-of-type|only-child|nth-of-type|nth-last-of-type|nth-last-child|nth-child|not|link|left|last-of-type|last-child|lang|invalid|indeterminate|in-range|hover|focus|first-of-type|first-line|first-letter|first-child|first|enabled|empty|disabled|default|checked|before|after|active)"
+},{className:"selector-pseudo",
+begin:"::(after|before|choices|first-letter|first-line|repeat-index|repeat-item|selection|value)"
+},i,{className:"attribute",
+begin:"\\b(src|z-index|word-wrap|word-spacing|word-break|width|widows|white-space|visibility|vertical-align|unicode-bidi|transition-timing-function|transition-property|transition-duration|transition-delay|transition|transform-style|transform-origin|transform|top|text-underline-position|text-transform|text-shadow|text-rendering|text-overflow|text-indent|text-decoration-style|text-decoration-line|text-decoration-color|text-decoration|text-align-last|text-align|tab-size|table-layout|right|resize|quotes|position|pointer-events|perspective-origin|perspective|page-break-inside|page-break-before|page-break-after|padding-top|padding-right|padding-left|padding-bottom|padding|overflow-y|overflow-x|overflow-wrap|overflow|outline-width|outline-style|outline-offset|outline-color|outline|orphans|order|opacity|object-position|object-fit|normal|none|nav-up|nav-right|nav-left|nav-index|nav-down|min-width|min-height|max-width|max-height|mask|marks|margin-top|margin-right|margin-left|margin-bottom|margin|list-style-type|list-style-position|list-style-image|list-style|line-height|letter-spacing|left|justify-content|initial|inherit|ime-mode|image-orientation|image-resolution|image-rendering|icon|hyphens|height|font-weight|font-variant-ligatures|font-variant|font-style|font-stretch|font-size-adjust|font-size|font-language-override|font-kerning|font-feature-settings|font-family|font|float|flex-wrap|flex-shrink|flex-grow|flex-flow|flex-direction|flex-basis|flex|filter|empty-cells|display|direction|cursor|counter-reset|counter-increment|content|column-width|column-span|column-rule-width|column-rule-style|column-rule-color|column-rule|column-gap|column-fill|column-count|columns|color|clip-path|clip|clear|caption-side|break-inside|break-before|break-after|box-sizing|box-shadow|box-decoration-break|bottom|border-width|border-top-width|border-top-style|border-top-right-radius|border-top-left-radius|border-top-color|border-top|border-style|border-spacing|border-right-width|border-right-style|border-right-color|border-right|border-radius|border-left-width|border-left-style|border-left-color|border-left|border-image-width|border-image-source|border-image-slice|border-image-repeat|border-image-outset|border-image|border-color|border-collapse|border-bottom-width|border-bottom-style|border-bottom-right-radius|border-bottom-left-radius|border-bottom-color|border-bottom|border|background-size|background-repeat|background-position|background-origin|background-image|background-color|background-clip|background-attachment|background-blend-mode|background|backface-visibility|auto|animation-timing-function|animation-play-state|animation-name|animation-iteration-count|animation-fill-mode|animation-duration|animation-direction|animation-delay|animation|align-self|align-items|align-content)\\b",
+illegal:"[^\\s]"},{
+begin:"\\b(whitespace|wait|w-resize|visible|vertical-text|vertical-ideographic|uppercase|upper-roman|upper-alpha|underline|transparent|top|thin|thick|text|text-top|text-bottom|tb-rl|table-header-group|table-footer-group|sw-resize|super|strict|static|square|solid|small-caps|separate|se-resize|scroll|s-resize|rtl|row-resize|ridge|right|repeat|repeat-y|repeat-x|relative|progress|pointer|overline|outside|outset|oblique|nowrap|not-allowed|normal|none|nw-resize|no-repeat|no-drop|newspaper|ne-resize|n-resize|move|middle|medium|ltr|lr-tb|lowercase|lower-roman|lower-alpha|loose|list-item|line|line-through|line-edge|lighter|left|keep-all|justify|italic|inter-word|inter-ideograph|inside|inset|inline|inline-block|inherit|inactive|ideograph-space|ideograph-parenthesis|ideograph-numeric|ideograph-alpha|horizontal|hidden|help|hand|groove|fixed|ellipsis|e-resize|double|dotted|distribute|distribute-space|distribute-letter|distribute-all-lines|disc|disabled|default|decimal|dashed|crosshair|collapse|col-resize|circle|char|center|capitalize|break-word|break-all|bottom|both|bolder|bold|block|bidi-override|below|baseline|auto|always|all-scroll|absolute|table|table-cell)\\b"
+},{begin:":",end:";",
+contains:[i,r,e.CSS_NUMBER_MODE,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,{
+className:"meta",begin:"!important"}]},{begin:"@(page|font-face)",lexemes:t,
+keywords:"@page @font-face"},{begin:"@",end:"[{;]",returnBegin:!0,
+keywords:"and or not only",contains:[{begin:t,className:"keyword"
+},i,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,r,e.CSS_NUMBER_MODE]}]}}}());
+hljs.registerLanguage("shell",function(){"use strict";return function(s){return{
+name:"Shell Session",aliases:["console"],contains:[{className:"meta",
+begin:"^\\s{0,3}[/\\w\\d\\[\\]()@-]*[>%$#]",starts:{end:"$",subLanguage:"bash"}
+}]}}}());
+hljs.registerLanguage("sql",function(){"use strict";return function(e){
+var t=e.COMMENT("--","$");return{name:"SQL",case_insensitive:!0,
+illegal:/[<>{}*]/,contains:[{
+beginKeywords:"begin end start commit rollback savepoint lock alter create drop rename call delete do handler insert load replace select truncate update set show pragma grant merge describe use explain help declare prepare execute deallocate release unlock purge reset change stop analyze cache flush optimize repair kill install uninstall checksum restore check backup revoke comment values with",
+end:/;/,endsWithParent:!0,keywords:{$pattern:/[\w\.]+/,
+keyword:"as abort abs absolute acc acce accep accept access accessed accessible account acos action activate add addtime admin administer advanced advise aes_decrypt aes_encrypt after agent aggregate ali alia alias all allocate allow alter always analyze ancillary and anti any anydata anydataset anyschema anytype apply archive archived archivelog are as asc ascii asin assembly assertion associate asynchronous at atan atn2 attr attri attrib attribu attribut attribute attributes audit authenticated authentication authid authors auto autoallocate autodblink autoextend automatic availability avg backup badfile basicfile before begin beginning benchmark between bfile bfile_base big bigfile bin binary_double binary_float binlog bit_and bit_count bit_length bit_or bit_xor bitmap blob_base block blocksize body both bound bucket buffer_cache buffer_pool build bulk by byte byteordermark bytes cache caching call calling cancel capacity cascade cascaded case cast catalog category ceil ceiling chain change changed char_base char_length character_length characters characterset charindex charset charsetform charsetid check checksum checksum_agg child choose chr chunk class cleanup clear client clob clob_base clone close cluster_id cluster_probability cluster_set clustering coalesce coercibility col collate collation collect colu colum column column_value columns columns_updated comment commit compact compatibility compiled complete composite_limit compound compress compute concat concat_ws concurrent confirm conn connec connect connect_by_iscycle connect_by_isleaf connect_by_root connect_time connection consider consistent constant constraint constraints constructor container content contents context contributors controlfile conv convert convert_tz corr corr_k corr_s corresponding corruption cos cost count count_big counted covar_pop covar_samp cpu_per_call cpu_per_session crc32 create creation critical cross cube cume_dist curdate current current_date current_time current_timestamp current_user cursor curtime customdatum cycle data database databases datafile datafiles datalength date_add date_cache date_format date_sub dateadd datediff datefromparts datename datepart datetime2fromparts day day_to_second dayname dayofmonth dayofweek dayofyear days db_role_change dbtimezone ddl deallocate declare decode decompose decrement decrypt deduplicate def defa defau defaul default defaults deferred defi defin define degrees delayed delegate delete delete_all delimited demand dense_rank depth dequeue des_decrypt des_encrypt des_key_file desc descr descri describ describe descriptor deterministic diagnostics difference dimension direct_load directory disable disable_all disallow disassociate discardfile disconnect diskgroup distinct distinctrow distribute distributed div do document domain dotnet double downgrade drop dumpfile duplicate duration each edition editionable editions element ellipsis else elsif elt empty enable enable_all enclosed encode encoding encrypt end end-exec endian enforced engine engines enqueue enterprise entityescaping eomonth error errors escaped evalname evaluate event eventdata events except exception exceptions exchange exclude excluding execu execut execute exempt exists exit exp expire explain explode export export_set extended extent external external_1 external_2 externally extract failed failed_login_attempts failover failure far fast feature_set feature_value fetch field fields file file_name_convert filesystem_like_logging final finish first first_value fixed flash_cache flashback floor flush following follows for forall force foreign form forma format found found_rows freelist freelists freepools fresh from from_base64 from_days ftp full function general generated get get_format get_lock getdate getutcdate global global_name globally go goto grant grants greatest group group_concat group_id grouping grouping_id groups gtid_subtract guarantee guard handler hash hashkeys having hea head headi headin heading heap help hex hierarchy high high_priority hosts hour hours http id ident_current ident_incr ident_seed identified identity idle_time if ifnull ignore iif ilike ilm immediate import in include including increment index indexes indexing indextype indicator indices inet6_aton inet6_ntoa inet_aton inet_ntoa infile initial initialized initially initrans inmemory inner innodb input insert install instance instantiable instr interface interleaved intersect into invalidate invisible is is_free_lock is_ipv4 is_ipv4_compat is_not is_not_null is_used_lock isdate isnull isolation iterate java join json json_exists keep keep_duplicates key keys kill language large last last_day last_insert_id last_value lateral lax lcase lead leading least leaves left len lenght length less level levels library like like2 like4 likec limit lines link list listagg little ln load load_file lob lobs local localtime localtimestamp locate locator lock locked log log10 log2 logfile logfiles logging logical logical_reads_per_call logoff logon logs long loop low low_priority lower lpad lrtrim ltrim main make_set makedate maketime managed management manual map mapping mask master master_pos_wait match matched materialized max maxextents maximize maxinstances maxlen maxlogfiles maxloghistory maxlogmembers maxsize maxtrans md5 measures median medium member memcompress memory merge microsecond mid migration min minextents minimum mining minus minute minutes minvalue missing mod mode model modification modify module monitoring month months mount move movement multiset mutex name name_const names nan national native natural nav nchar nclob nested never new newline next nextval no no_write_to_binlog noarchivelog noaudit nobadfile nocheck nocompress nocopy nocycle nodelay nodiscardfile noentityescaping noguarantee nokeep nologfile nomapping nomaxvalue nominimize nominvalue nomonitoring none noneditionable nonschema noorder nopr nopro noprom nopromp noprompt norely noresetlogs noreverse normal norowdependencies noschemacheck noswitch not nothing notice notnull notrim novalidate now nowait nth_value nullif nulls num numb numbe nvarchar nvarchar2 object ocicoll ocidate ocidatetime ociduration ociinterval ociloblocator ocinumber ociref ocirefcursor ocirowid ocistring ocitype oct octet_length of off offline offset oid oidindex old on online only opaque open operations operator optimal optimize option optionally or oracle oracle_date oradata ord ordaudio orddicom orddoc order ordimage ordinality ordvideo organization orlany orlvary out outer outfile outline output over overflow overriding package pad parallel parallel_enable parameters parent parse partial partition partitions pascal passing password password_grace_time password_lock_time password_reuse_max password_reuse_time password_verify_function patch path patindex pctincrease pctthreshold pctused pctversion percent percent_rank percentile_cont percentile_disc performance period period_add period_diff permanent physical pi pipe pipelined pivot pluggable plugin policy position post_transaction pow power pragma prebuilt precedes preceding precision prediction prediction_cost prediction_details prediction_probability prediction_set prepare present preserve prior priority private private_sga privileges procedural procedure procedure_analyze processlist profiles project prompt protection public publishingservername purge quarter query quick quiesce quota quotename radians raise rand range rank raw read reads readsize rebuild record records recover recovery recursive recycle redo reduced ref reference referenced references referencing refresh regexp_like register regr_avgx regr_avgy regr_count regr_intercept regr_r2 regr_slope regr_sxx regr_sxy reject rekey relational relative relaylog release release_lock relies_on relocate rely rem remainder rename repair repeat replace replicate replication required reset resetlogs resize resource respect restore restricted result result_cache resumable resume retention return returning returns reuse reverse revoke right rlike role roles rollback rolling rollup round row row_count rowdependencies rowid rownum rows rtrim rules safe salt sample save savepoint sb1 sb2 sb4 scan schema schemacheck scn scope scroll sdo_georaster sdo_topo_geometry search sec_to_time second seconds section securefile security seed segment select self semi sequence sequential serializable server servererror session session_user sessions_per_user set sets settings sha sha1 sha2 share shared shared_pool short show shrink shutdown si_averagecolor si_colorhistogram si_featurelist si_positionalcolor si_stillimage si_texture siblings sid sign sin size size_t sizes skip slave sleep smalldatetimefromparts smallfile snapshot some soname sort soundex source space sparse spfile split sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_small_result sql_variant_property sqlcode sqldata sqlerror sqlname sqlstate sqrt square standalone standby start starting startup statement static statistics stats_binomial_test stats_crosstab stats_ks_test stats_mode stats_mw_test stats_one_way_anova stats_t_test_ stats_t_test_indep stats_t_test_one stats_t_test_paired stats_wsr_test status std stddev stddev_pop stddev_samp stdev stop storage store stored str str_to_date straight_join strcmp strict string struct stuff style subdate subpartition subpartitions substitutable substr substring subtime subtring_index subtype success sum suspend switch switchoffset switchover sync synchronous synonym sys sys_xmlagg sysasm sysaux sysdate sysdatetimeoffset sysdba sysoper system system_user sysutcdatetime table tables tablespace tablesample tan tdo template temporary terminated tertiary_weights test than then thread through tier ties time time_format time_zone timediff timefromparts timeout timestamp timestampadd timestampdiff timezone_abbr timezone_minute timezone_region to to_base64 to_date to_days to_seconds todatetimeoffset trace tracking transaction transactional translate translation treat trigger trigger_nestlevel triggers trim truncate try_cast try_convert try_parse type ub1 ub2 ub4 ucase unarchived unbounded uncompress under undo unhex unicode uniform uninstall union unique unix_timestamp unknown unlimited unlock unnest unpivot unrecoverable unsafe unsigned until untrusted unusable unused update updated upgrade upped upper upsert url urowid usable usage use use_stored_outlines user user_data user_resources users using utc_date utc_timestamp uuid uuid_short validate validate_password_strength validation valist value values var var_samp varcharc vari varia variab variabl variable variables variance varp varraw varrawc varray verify version versions view virtual visible void wait wallet warning warnings week weekday weekofyear wellformed when whene whenev wheneve whenever where while whitespace window with within without work wrapped xdb xml xmlagg xmlattributes xmlcast xmlcolattval xmlelement xmlexists xmlforest xmlindex xmlnamespaces xmlpi xmlquery xmlroot xmlschema xmlserialize xmltable xmltype xor year year_to_month years yearweek",
+literal:"true false null unknown",
+built_in:"array bigint binary bit blob bool boolean char character date dec decimal float int int8 integer interval number numeric real record serial serial8 smallint text time timestamp tinyint varchar varchar2 varying void"
+},contains:[{className:"string",begin:"'",end:"'",contains:[{begin:"''"}]},{
+className:"string",begin:'"',end:'"',contains:[{begin:'""'}]},{
+className:"string",begin:"`",end:"`"
+},e.C_NUMBER_MODE,e.C_BLOCK_COMMENT_MODE,t,e.HASH_COMMENT_MODE]
+},e.C_BLOCK_COMMENT_MODE,t,e.HASH_COMMENT_MODE]}}}());
+hljs.registerLanguage("swift",function(){"use strict";return function(e){var i={
+keyword:"#available #colorLiteral #column #else #elseif #endif #file #fileLiteral #function #if #imageLiteral #line #selector #sourceLocation _ __COLUMN__ __FILE__ __FUNCTION__ __LINE__ Any as as! as? associatedtype associativity break case catch class continue convenience default defer deinit didSet do dynamic dynamicType else enum extension fallthrough false fileprivate final for func get guard if import in indirect infix init inout internal is lazy left let mutating nil none nonmutating open operator optional override postfix precedence prefix private protocol Protocol public repeat required rethrows return right self Self set static struct subscript super switch throw throws true try try! try? Type typealias unowned var weak where while willSet",
+literal:"true false nil",
+built_in:"abs advance alignof alignofValue anyGenerator assert assertionFailure bridgeFromObjectiveC bridgeFromObjectiveCUnconditional bridgeToObjectiveC bridgeToObjectiveCUnconditional c compactMap contains count countElements countLeadingZeros debugPrint debugPrintln distance dropFirst dropLast dump encodeBitsAsWords enumerate equal fatalError filter find getBridgedObjectiveCType getVaList indices insertionSort isBridgedToObjectiveC isBridgedVerbatimToObjectiveC isUniquelyReferenced isUniquelyReferencedNonObjC join lazy lexicographicalCompare map max maxElement min minElement numericCast overlaps partition posix precondition preconditionFailure print println quickSort readLine reduce reflect reinterpretCast reverse roundUpToAlignment sizeof sizeofValue sort split startsWith stride strideof strideofValue swap toString transcode underestimateCount unsafeAddressOf unsafeBitCast unsafeDowncast unsafeUnwrap unsafeReflect withExtendedLifetime withObjectAtPlusZero withUnsafePointer withUnsafePointerToObject withUnsafeMutablePointer withUnsafeMutablePointers withUnsafePointer withUnsafePointers withVaList zip"
+},n=e.COMMENT("/\\*","\\*/",{contains:["self"]}),t={className:"subst",
+begin:/\\\(/,end:"\\)",keywords:i,contains:[]},a={className:"string",
+contains:[e.BACKSLASH_ESCAPE,t],variants:[{begin:/"""/,end:/"""/},{begin:/"/,
+end:/"/}]},r={className:"number",
+begin:"\\b([\\d_]+(\\.[\\deE_]+)?|0x[a-fA-F0-9_]+(\\.[a-fA-F0-9p_]+)?|0b[01_]+|0o[0-7_]+)\\b",
+relevance:0};return t.contains=[r],{name:"Swift",keywords:i,
+contains:[a,e.C_LINE_COMMENT_MODE,n,{className:"type",
+begin:"\\b[A-Z][\\w\xc0-\u02b8']*[!?]"},{className:"type",
+begin:"\\b[A-Z][\\w\xc0-\u02b8']*",relevance:0},r,{className:"function",
+beginKeywords:"func",end:"{",excludeEnd:!0,contains:[e.inherit(e.TITLE_MODE,{
+begin:/[A-Za-z$_][0-9A-Za-z$_]*/}),{begin:/</,end:/>/},{className:"params",
+begin:/\(/,end:/\)/,endsParent:!0,keywords:i,
+contains:["self",r,a,e.C_BLOCK_COMMENT_MODE,{begin:":"}],illegal:/["']/}],
+illegal:/\[|%/},{className:"class",
+beginKeywords:"struct protocol class extension enum",keywords:i,end:"\\{",
+excludeEnd:!0,contains:[e.inherit(e.TITLE_MODE,{
+begin:/[A-Za-z$_][\u00C0-\u02B80-9A-Za-z$_]*/})]},{className:"meta",
+begin:"(@discardableResult|@warn_unused_result|@exported|@lazy|@noescape|@NSCopying|@NSManaged|@objc|@objcMembers|@convention|@required|@noreturn|@IBAction|@IBDesignable|@IBInspectable|@IBOutlet|@infix|@prefix|@postfix|@autoclosure|@testable|@available|@nonobjc|@NSApplicationMain|@UIApplicationMain|@dynamicMemberLookup|@propertyWrapper)\\b"
+},{beginKeywords:"import",end:/$/,contains:[e.C_LINE_COMMENT_MODE,n]}]}}}());
+hljs.registerLanguage("typescript",function(){"use strict"
+;const e="[A-Za-z$_][0-9A-Za-z$_]*",n=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","switch","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends"],a=["true","false","null","undefined","NaN","Infinity"],s=[].concat(["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],["arguments","this","super","console","window","document","localStorage","module","global"],["Intl","DataView","Number","Math","Date","String","RegExp","Object","Function","Boolean","Error","Symbol","Set","Map","WeakSet","WeakMap","Proxy","Reflect","JSON","Promise","Float64Array","Int16Array","Int32Array","Int8Array","Uint16Array","Uint32Array","Float32Array","Array","Uint8Array","Uint8ClampedArray","ArrayBuffer"],["EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"])
+;function t(e){return r("(?=",e,")")}function i(e){return r("(",e,")?")}
+function r(...e){return e.map((e=>{
+return(n=e)?"string"==typeof n?n:n.source:null;var n})).join("")}
+return function(c){const o={$pattern:e,
+keyword:n.concat(["type","namespace","typedef","interface","public","private","protected","implements","declare","abstract","readonly"]).join(" "),
+literal:a.join(" "),
+built_in:s.concat(["any","void","number","boolean","string","object","never","enum"]).join(" ")
+},l={className:"meta",begin:"@[A-Za-z$_][0-9A-Za-z$_]*"},d=(e,n,a)=>{
+const s=e.contains.findIndex((e=>e.label===n))
+;if(-1===s)throw Error("can not find mode to replace");e.contains.splice(s,1,a)
+},g=function(c){const o=e,l={begin:/<[A-Za-z0-9\\._:-]+/,
+end:/\/[A-Za-z0-9\\._:-]+>|\/>/,isTrulyOpeningTag:(e,n)=>{
+const a=e[0].length+e.index,s=e.input[a];"<"!==s?">"===s&&(((e,{after:n})=>{
+const a=e[0].replace("<","</");return-1!==e.input.indexOf(a,n)})(e,{after:a
+})||n.ignoreMatch()):n.ignoreMatch()}},d={$pattern:e,keyword:n.join(" "),
+literal:a.join(" "),built_in:s.join(" ")
+},g=(e,n)=>`\\b0[${e}][${n}]([${n}_]*[${n}])?n?`,b=/[1-9]([0-9_]*\d)?/,u=/\d([0-9_]*\d)?/,E=r(/[eE][+-]?/,u),m={
+className:"number",variants:[{begin:g("bB","01")},{begin:g("oO","0-7")},{
+begin:g("xX","0-9a-fA-F")},{begin:r(/\b/,b,"n")},{begin:r(/(\b0)?\./,u,i(E))},{
+begin:r(/\b/,b,i(r(/\./,i(u))),i(E))},{begin:/\b0[\.n]?/}],relevance:0},y={
+className:"subst",begin:"\\$\\{",end:"\\}",keywords:d,contains:[]},p={
+begin:"html`",end:"",starts:{end:"`",returnEnd:!1,
+contains:[c.BACKSLASH_ESCAPE,y],subLanguage:"xml"}},_={begin:"css`",end:"",
+starts:{end:"`",returnEnd:!1,contains:[c.BACKSLASH_ESCAPE,y],subLanguage:"css"}
+},N={className:"string",begin:"`",end:"`",contains:[c.BACKSLASH_ESCAPE,y]},f={
+className:"comment",variants:[c.COMMENT("/\\*\\*","\\*/",{relevance:0,
+contains:[{className:"doctag",begin:"@[A-Za-z]+",contains:[{className:"type",
+begin:"\\{",end:"\\}",relevance:0},{className:"variable",
+begin:o+"(?=\\s*(-)|$)",endsParent:!0,relevance:0},{begin:/(?=[^\n])\s/,
+relevance:0}]}]}),c.C_BLOCK_COMMENT_MODE,c.C_LINE_COMMENT_MODE]
+},A=[c.APOS_STRING_MODE,c.QUOTE_STRING_MODE,p,_,N,m,c.REGEXP_MODE]
+;y.contains=A.concat({begin:/{/,end:/}/,keywords:d,contains:["self"].concat(A)})
+;const O=[].concat(f,y.contains),S=O.concat([{begin:/\(/,end:/\)/,keywords:d,
+contains:["self"].concat(O)}]),T={className:"params",begin:/\(/,end:/\)/,
+excludeBegin:!0,excludeEnd:!0,keywords:d,contains:S};return{name:"Javascript",
+aliases:["js","jsx","mjs","cjs"],keywords:d,exports:{PARAMS_CONTAINS:S},
+illegal:/#(?![$_A-z])/,contains:[c.SHEBANG({label:"shebang",binary:"node",
+relevance:5}),{label:"use_strict",className:"meta",relevance:10,
+begin:/^\s*['"]use (strict|asm)['"]/
+},c.APOS_STRING_MODE,c.QUOTE_STRING_MODE,p,_,N,f,m,{
+begin:r(/[{,\n]\s*/,t(r(/(\/\/.*$)*/,/(\/\*(.|\n)*\*\/)*/,/\s*/,o+"\\s*:"))),
+relevance:0,contains:[{className:"attr",begin:o+t("\\s*:"),relevance:0}]},{
+begin:"("+c.RE_STARTERS_RE+"|\\b(case|return|throw)\\b)\\s*",
+keywords:"return throw case",contains:[f,c.REGEXP_MODE,{className:"function",
+begin:"(\\([^()]*(\\([^()]*(\\([^()]*\\))*[^()]*\\))*[^()]*\\)|"+c.UNDERSCORE_IDENT_RE+")\\s*=>",
+returnBegin:!0,end:"\\s*=>",contains:[{className:"params",variants:[{
+begin:c.UNDERSCORE_IDENT_RE},{className:null,begin:/\(\s*\)/,skip:!0},{
+begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:d,contains:S}]}]},{
+begin:/,/,relevance:0},{className:"",begin:/\s/,end:/\s*/,skip:!0},{variants:[{
+begin:"<>",end:"</>"},{begin:l.begin,"on:begin":l.isTrulyOpeningTag,end:l.end}],
+subLanguage:"xml",contains:[{begin:l.begin,end:l.end,skip:!0,contains:["self"]}]
+}],relevance:0},{className:"function",beginKeywords:"function",end:/[{;]/,
+excludeEnd:!0,keywords:d,contains:["self",c.inherit(c.TITLE_MODE,{begin:o}),T],
+illegal:/%/},{className:"function",
+begin:c.UNDERSCORE_IDENT_RE+"\\([^()]*(\\([^()]*(\\([^()]*\\))*[^()]*\\))*[^()]*\\)\\s*{",
+returnBegin:!0,contains:[T,c.inherit(c.TITLE_MODE,{begin:o})]},{variants:[{
+begin:"\\."+o},{begin:"\\$"+o}],relevance:0},{className:"class",
+beginKeywords:"class",end:/[{;=]/,excludeEnd:!0,illegal:/[:"\[\]]/,contains:[{
+beginKeywords:"extends"},c.UNDERSCORE_TITLE_MODE]},{begin:/\b(?=constructor)/,
+end:/[\{;]/,excludeEnd:!0,contains:[c.inherit(c.TITLE_MODE,{begin:o}),"self",T]
+},{begin:"(get|set)\\s+(?="+o+"\\()",end:/{/,keywords:"get set",
+contains:[c.inherit(c.TITLE_MODE,{begin:o}),{begin:/\(\)/},T]},{begin:/\$[(.]/}]
+}}(c)
+;return Object.assign(g.keywords,o),g.exports.PARAMS_CONTAINS.push(l),g.contains=g.contains.concat([l,{
+beginKeywords:"namespace",end:/\{/,excludeEnd:!0},{beginKeywords:"interface",
+end:/\{/,excludeEnd:!0,keywords:"interface extends"
+}]),d(g,"shebang",c.SHEBANG()),d(g,"use_strict",{className:"meta",relevance:10,
+begin:/^\s*['"]use strict['"]/
+}),g.contains.find((e=>"function"===e.className)).relevance=0,Object.assign(g,{
+name:"TypeScript",aliases:["ts"]}),g}}());
+hljs.registerLanguage("yaml",function(){"use strict";return function(e){
+var n="true false yes no null",a="[\\w#;/?:@&=+$,.~*\\'()[\\]]+",s={
+className:"string",relevance:0,variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/
+},{begin:/\S+/}],contains:[e.BACKSLASH_ESCAPE,{className:"template-variable",
+variants:[{begin:"{{",end:"}}"},{begin:"%{",end:"}"}]}]},i=e.inherit(s,{
+variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/[^\s,{}[\]]+/}]}),l={
+end:",",endsWithParent:!0,excludeEnd:!0,contains:[],keywords:n,relevance:0},t={
+begin:"{",end:"}",contains:[l],illegal:"\\n",relevance:0},g={begin:"\\[",
+end:"\\]",contains:[l],illegal:"\\n",relevance:0},b=[{className:"attr",
+variants:[{begin:"\\w[\\w :\\/.-]*:(?=[ \t]|$)"},{
+begin:'"\\w[\\w :\\/.-]*":(?=[ \t]|$)'},{begin:"'\\w[\\w :\\/.-]*':(?=[ \t]|$)"
+}]},{className:"meta",begin:"^---s*$",relevance:10},{className:"string",
+begin:"[\\|>]([0-9]?[+-])?[ ]*\\n( *)[\\S ]+\\n(\\2[\\S ]+\\n?)*"},{
+begin:"<%[%=-]?",end:"[%-]?%>",subLanguage:"ruby",excludeBegin:!0,excludeEnd:!0,
+relevance:0},{className:"type",begin:"!\\w+!"+a},{className:"type",
+begin:"!<"+a+">"},{className:"type",begin:"!"+a},{className:"type",begin:"!!"+a
+},{className:"meta",begin:"&"+e.UNDERSCORE_IDENT_RE+"$"},{className:"meta",
+begin:"\\*"+e.UNDERSCORE_IDENT_RE+"$"},{className:"bullet",begin:"\\-(?=[ ]|$)",
+relevance:0},e.HASH_COMMENT_MODE,{beginKeywords:n,keywords:{literal:n}},{
+className:"number",
+begin:"\\b[0-9]{4}(-[0-9][0-9]){0,2}([Tt \\t][0-9][0-9]?(:[0-9][0-9]){2})?(\\.[0-9]*)?([ \\t])*(Z|[-+][0-9][0-9]?(:[0-9][0-9])?)?\\b"
+},{className:"number",begin:e.C_NUMBER_RE+"\\b"},t,g,s],c=[...b];return c.pop(),
+c.push(i),l.contains=c,{name:"YAML",case_insensitive:!0,aliases:["yml","YAML"],
+contains:b}}}());
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/iCheck/custom.css b/ruoyi-admin/src/main/resources/static/ajax/libs/iCheck/custom.css
new file mode 100644
index 0000000..efeea1c
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/iCheck/custom.css
@@ -0,0 +1,72 @@
+/* iCheck plugin Square skin, green
+----------------------------------- */
+.icheckbox_square-green,
+.iradio_square-green {
+    display: inline-block;
+    *display: inline;
+    vertical-align: middle;
+    margin: 0;
+    padding: 0;
+    width: 22px;
+    height: 22px;
+    background: url(green.png) no-repeat;
+    border: none;
+    cursor: pointer;
+}
+
+.icheckbox_square-green-login{
+    display: inline-block;
+    *display: inline;
+    vertical-align: middle;
+    margin: 0;
+    padding: 0;
+    width: 22px;
+    height: 22px;
+    background: url(green-login.png) no-repeat;
+    border: none;
+    cursor: pointer;
+}
+
+.icheckbox_square-green,.icheckbox_square-green-login {
+    background-position: 0 0;
+}
+.icheckbox_square-green.hover,.icheckbox_square-green-login.hover {
+    background-position: -24px 0;
+}
+.icheckbox_square-green.checked,.icheckbox_square-green-login.checked {
+    background-position: -48px 0;
+}
+.icheckbox_square-green.disabled,.icheckbox_square-green.disabled-login {
+    background-position: -72px 0;
+    cursor: default;
+}
+.icheckbox_square-green.checked.disabled,.icheckbox_square-green-login.checked.disabled {
+    background-position: -96px 0;
+}
+
+.iradio_square-green {
+    background-position: -120px 0;
+}
+.iradio_square-green.hover {
+    background-position: -144px 0;
+}
+.iradio_square-green.checked {
+    background-position: -168px 0;
+}
+.iradio_square-green.disabled {
+    background-position: -192px 0;
+    cursor: default;
+}
+.iradio_square-green.checked.disabled {
+    background-position: -216px 0;
+}
+
+/* HiDPI support */
+@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {
+    .icheckbox_square-green,.icheckbox_square-green-login,
+    .iradio_square-green {
+        background-image: url(green%402x.png);
+        -webkit-background-size: 240px 24px;
+        background-size: 240px 24px;
+    }
+}
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/iCheck/green-login.png b/ruoyi-admin/src/main/resources/static/ajax/libs/iCheck/green-login.png
new file mode 100644
index 0000000..3487235
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/iCheck/green-login.png
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/iCheck/green.png b/ruoyi-admin/src/main/resources/static/ajax/libs/iCheck/green.png
new file mode 100644
index 0000000..cf62300
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/iCheck/green.png
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/iCheck/green@2x.png b/ruoyi-admin/src/main/resources/static/ajax/libs/iCheck/green@2x.png
new file mode 100644
index 0000000..3bda5be
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/iCheck/green@2x.png
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/iCheck/icheck.min.js b/ruoyi-admin/src/main/resources/static/ajax/libs/iCheck/icheck.min.js
new file mode 100644
index 0000000..29ce0f4
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/iCheck/icheck.min.js
@@ -0,0 +1,11 @@
+/*! iCheck v1.0.3 by Damir Sultanov, https://github.com/dargullin/icheck, MIT Licensed */
+(function(k){function E(a,b,e){var c=a[0],f=/er/.test(e)?"indeterminate":/bl/.test(e)?"disabled":"checked",d="update"==e?{checked:c.checked,disabled:c.disabled,indeterminate:"true"==a.attr("indeterminate")||"false"==a.attr("determinate")}:c[f];if(/^(ch|di|in)/.test(e)&&!d)B(a,f);else if(/^(un|en|de)/.test(e)&&d)v(a,f);else if("update"==e)for(var l in d)d[l]?B(a,l,!0):v(a,l,!0);else b&&"toggle"!=e||(b||a.trigger("ifClicked"),d?"radio"!==c.type&&v(a,f):B(a,f))}function B(a,b,e){var c=a[0],f=a.parent(),
+  d="checked"==b,l="indeterminate"==b,t="disabled"==b,u=l?"determinate":d?"unchecked":"enabled",x=q(a,u+C(c.type)),y=q(a,b+C(c.type));if(!0!==c[b]){if(!e&&"checked"==b&&"radio"==c.type&&c.name){var z=a.closest("form"),r='input[name="'+c.name+'"]';r=z.length?z.find(r):k(r);r.each(function(){this!==c&&k(this).data("iCheck")&&v(k(this),b)})}l?(c[b]=!0,c.checked&&v(a,"checked","force")):(e||(c[b]=!0),d&&c.indeterminate&&v(a,"indeterminate",!1));I(a,d,b,e)}c.disabled&&q(a,"cursor",!0)&&f.find(".iCheck-helper").css("cursor",
+  "default");f.addClass(y||q(a,b)||"");f.attr("role")&&!l&&f.attr("aria-"+(t?"disabled":"checked"),"true");f.removeClass(x||q(a,u)||"")}function v(a,b,e){var c=a[0],f=a.parent(),d="checked"==b,l="indeterminate"==b,t="disabled"==b,u=l?"determinate":d?"unchecked":"enabled",x=q(a,u+C(c.type)),y=q(a,b+C(c.type));if(!1!==c[b]){if(l||!e||"force"==e)c[b]=!1;I(a,d,u,e)}!c.disabled&&q(a,"cursor",!0)&&f.find(".iCheck-helper").css("cursor","pointer");f.removeClass(y||q(a,b)||"");f.attr("role")&&!l&&f.attr("aria-"+
+  (t?"disabled":"checked"),"false");f.addClass(x||q(a,u)||"")}function J(a,b){a.data("iCheck")&&(a.parent().html(a.attr("style",a.data("iCheck").s||"")),b&&a.trigger(b),a.off(".i").unwrap(),k('label[for="'+a[0].id+'"]').add(a.closest("label")).off(".i"))}function q(a,b,e){if(a.data("iCheck"))return a.data("iCheck").o[b+(e?"":"Class")]}function C(a){return a.charAt(0).toUpperCase()+a.slice(1)}function I(a,b,e,c){c||(b&&a.trigger("ifToggled"),a.trigger("change").trigger("ifChanged").trigger("if"+C(e)))}
+  var G=/ip(hone|od|ad)|android|blackberry|windows phone|opera mini|silk/i.test(navigator.userAgent)||"MacIntel"===navigator.platform&&1<navigator.maxTouchPoints;k.fn.iCheck=function(a,b){var e='input[type="checkbox"], input[type="radio"]',c=k(),f=function(g){g.each(function(){var m=k(this);c=m.is(e)?c.add(m):c.add(m.find(e))})};if(/^(check|uncheck|toggle|indeterminate|determinate|disable|enable|update|destroy)$/i.test(a))return a=a.toLowerCase(),f(this),c.each(function(){var g=k(this);"destroy"==a?
+  J(g,"ifDestroyed"):E(g,!0,a);k.isFunction(b)&&b()});if("object"!=typeof a&&a)return this;var d=k.extend({checkedClass:"checked",disabledClass:"disabled",indeterminateClass:"indeterminate",labelHover:!0},a),l=d.handle,t=d.hoverClass||"hover",u=d.focusClass||"focus",x=d.activeClass||"active",y=!!d.labelHover,z=d.labelHoverClass||"hover",r=(""+d.increaseArea).replace("%","")|0;if("checkbox"==l||"radio"==l)e='input[type="'+l+'"]';-50>r&&(r=-50);f(this);return c.each(function(){var g=k(this);J(g);var m=
+  this,H=m.id,F=-r+"%",w=100+2*r+"%";w={position:"absolute",top:F,left:F,display:"block",width:w,height:w,margin:0,padding:0,background:"#fff",border:0,opacity:0};F=G?{position:"absolute",visibility:"hidden"}:r?w:{position:"absolute",opacity:0};var M="checkbox"==m.type?d.checkboxClass||"icheckbox":d.radioClass||"iradio",D=k('label[for="'+H+'"]').add(g.closest("label")),K=!!d.aria,L="iCheck-"+Math.random().toString(36).substr(2,6),h='<div class="'+M+'" '+(K?'role="'+m.type+'" ':"");K&&D.each(function(){h+=
+  'aria-labelledby="';this.id?h+=this.id:(this.id=L,h+=L);h+='"'});h=g.wrap(h+"/>").trigger("ifCreated").parent().append(d.insert);w=k('<ins class="iCheck-helper"/>').css(w).appendTo(h);g.data("iCheck",{o:d,s:g.attr("style")}).css(F);d.inheritClass&&h.addClass(m.className||"");d.inheritID&&H&&h.attr("id","iCheck-"+H);"static"==h.css("position")&&h.css("position","relative");E(g,!0,"update");if(D.length)D.on("click.i mouseover.i mouseout.i touchbegin.i touchend.i",function(p){var n=p.type,A=k(this);
+  if(!m.disabled){if("click"==n){if(k(p.target).is("a"))return;E(g,!1,!0)}else y&&(/ut|nd/.test(n)?(h.removeClass(t),A.removeClass(z)):(h.addClass(t),A.addClass(z)));if(G)p.stopPropagation();else return!1}});g.on("click.i focus.i blur.i keyup.i keydown.i keypress.i",function(p){var n=p.type;p=p.keyCode;if("click"==n)return!1;if("keydown"==n&&32==p)return"radio"==m.type&&m.checked||(m.checked?v(g,"checked"):B(g,"checked")),!1;if("keyup"==n&&"radio"==m.type)!m.checked&&B(g,"checked");else if(/us|ur/.test(n))h["blur"==
+  n?"removeClass":"addClass"](u)});w.on("click mousedown mouseup mouseover mouseout touchbegin.i touchend.i",function(p){var n=p.type,A=/wn|up/.test(n)?x:t;if(!m.disabled){if("click"==n)E(g,!1,!0);else if(/wn|er|in/.test(n)?h.addClass(A):h.removeClass(A+" "+x),D.length&&y&&A==t)D[/ut|nd/.test(n)?"removeClass":"addClass"](z);if(G)p.stopPropagation();else return!1}})})}})(window.jQuery||window.Zepto);
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jasny/jasny-bootstrap.css b/ruoyi-admin/src/main/resources/static/ajax/libs/jasny/jasny-bootstrap.css
new file mode 100644
index 0000000..09c1bf0
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jasny/jasny-bootstrap.css
@@ -0,0 +1,620 @@
+/*!
+ * Jasny Bootstrap v3.1.3 (http://jasny.github.io/bootstrap)
+ * Copyright 2012-2014 Arnold Daniels
+ * Licensed under Apache-2.0 (https://github.com/jasny/bootstrap/blob/master/LICENSE)
+ */
+
+.container-smooth {
+  max-width: 1170px;
+}
+@media (min-width: 1px) {
+  .container-smooth {
+    width: auto;
+  }
+}
+.btn-labeled {
+  padding-top: 0;
+  padding-bottom: 0;
+}
+.btn-label {
+  position: relative;
+  left: -12px;
+  display: inline-block;
+  padding: 6px 12px;
+  background: transparent;
+  background: rgba(0, 0, 0, .15);
+  border-radius: 3px 0 0 3px;
+}
+.btn-label.btn-label-right {
+  right: -12px;
+  left: auto;
+  border-radius: 0 3px 3px 0;
+}
+.btn-lg .btn-label {
+  left: -16px;
+  padding: 10px 16px;
+  border-radius: 5px 0 0 5px;
+}
+.btn-lg .btn-label.btn-label-right {
+  right: -16px;
+  left: auto;
+  border-radius: 0 5px 5px 0;
+}
+.btn-sm .btn-label {
+  left: -10px;
+  padding: 5px 10px;
+  border-radius: 2px 0 0 2px;
+}
+.btn-sm .btn-label.btn-label-right {
+  right: -10px;
+  left: auto;
+  border-radius: 0 2px 2px 0;
+}
+.btn-xs .btn-label {
+  left: -5px;
+  padding: 1px 5px;
+  border-radius: 2px 0 0 2px;
+}
+.btn-xs .btn-label.btn-label-right {
+  right: -5px;
+  left: auto;
+  border-radius: 0 2px 2px 0;
+}
+.nav-tabs-bottom {
+  border-top: 1px solid #ddd;
+  border-bottom: 0;
+}
+.nav-tabs-bottom > li {
+  margin-top: -1px;
+  margin-bottom: 0;
+}
+.nav-tabs-bottom > li > a {
+  border-radius: 0 0 4px 4px;
+}
+.nav-tabs-bottom > li > a:hover,
+.nav-tabs-bottom > li > a:focus,
+.nav-tabs-bottom > li.active > a,
+.nav-tabs-bottom > li.active > a:hover,
+.nav-tabs-bottom > li.active > a:focus {
+  border: 1px solid #ddd;
+  border-top-color: transparent;
+}
+.nav-tabs-left {
+  border-right: 1px solid #ddd;
+  border-bottom: 0;
+}
+.nav-tabs-left > li {
+  float: none;
+  margin-right: -1px;
+  margin-bottom: 0;
+}
+.nav-tabs-left > li > a {
+  margin-right: 0;
+  margin-bottom: 2px;
+  border-radius: 4px 0 0 4px;
+}
+.nav-tabs-left > li > a:hover,
+.nav-tabs-left > li > a:focus,
+.nav-tabs-left > li.active > a,
+.nav-tabs-left > li.active > a:hover,
+.nav-tabs-left > li.active > a:focus {
+  border: 1px solid #ddd;
+  border-right-color: transparent;
+}
+.row > .nav-tabs-left {
+  position: relative;
+  z-index: 1;
+  padding-right: 0;
+  padding-left: 15px;
+  margin-right: -1px;
+}
+.row > .nav-tabs-left + .tab-content {
+  border-left: 1px solid #ddd;
+}
+.nav-tabs-right {
+  border-bottom: 0;
+  border-left: 1px solid #ddd;
+}
+.nav-tabs-right > li {
+  float: none;
+  margin-bottom: 0;
+  margin-left: -1px;
+}
+.nav-tabs-right > li > a {
+  margin-bottom: 2px;
+  margin-left: 0;
+  border-radius: 0 4px 4px 0;
+}
+.nav-tabs-right > li > a:hover,
+.nav-tabs-right > li > a:focus,
+.nav-tabs-right > li.active > a,
+.nav-tabs-right > li.active > a:hover,
+.nav-tabs-right > li.active > a:focus {
+  border: 1px solid #ddd;
+  border-left-color: transparent;
+}
+.row > .nav-tabs-right {
+  padding-right: 15px;
+  padding-left: 0;
+}
+.navmenu,
+.navbar-offcanvas {
+  width: 300px;
+  height: auto;
+  border-style: solid;
+  border-width: 1px;
+  border-radius: 4px;
+}
+.navmenu-fixed-left,
+.navmenu-fixed-right,
+.navbar-offcanvas {
+  position: fixed;
+  top: 0;
+  bottom: 0;
+  z-index: 1030;
+  overflow-y: auto;
+  border-radius: 0;
+}
+.navmenu-fixed-left,
+.navbar-offcanvas.navmenu-fixed-left {
+  right: auto;
+  left: 0;
+  border-width: 0 1px 0 0;
+}
+.navmenu-fixed-right,
+.navbar-offcanvas {
+  right: 0;
+  left: auto;
+  border-width: 0 0 0 1px;
+}
+.navmenu-nav {
+  margin-bottom: 10px;
+}
+.navmenu-nav.dropdown-menu {
+  position: static;
+  float: none;
+  padding-top: 0;
+  margin: 0;
+  border: none;
+  border-radius: 0;
+  -webkit-box-shadow: none;
+          box-shadow: none;
+}
+.navbar-offcanvas .navbar-nav {
+  margin: 0;
+}
+@media (min-width: 768px) {
+  .navbar-offcanvas {
+    width: auto;
+    border-top: 0;
+    box-shadow: none;
+  }
+  .navbar-offcanvas.offcanvas {
+    position: static;
+    display: block !important;
+    height: auto !important;
+    padding-bottom: 0;
+    overflow: visible !important;
+  }
+  .navbar-offcanvas .navbar-nav.navbar-left:first-child {
+    margin-left: -15px;
+  }
+  .navbar-offcanvas .navbar-nav.navbar-right:last-child {
+    margin-right: -15px;
+  }
+  .navbar-offcanvas .navmenu-brand {
+    display: none;
+  }
+}
+.navmenu-brand {
+  display: block;
+  padding: 10px 15px;
+  margin: 10px 0;
+  font-size: 18px;
+  line-height: 20px;
+}
+.navmenu-brand:hover,
+.navmenu-brand:focus {
+  text-decoration: none;
+}
+.navmenu-default,
+.navbar-default .navbar-offcanvas {
+  background-color: #f8f8f8;
+  border-color: #e7e7e7;
+}
+.navmenu-default .navmenu-brand,
+.navbar-default .navbar-offcanvas .navmenu-brand {
+  color: #777;
+}
+.navmenu-default .navmenu-brand:hover,
+.navbar-default .navbar-offcanvas .navmenu-brand:hover,
+.navmenu-default .navmenu-brand:focus,
+.navbar-default .navbar-offcanvas .navmenu-brand:focus {
+  color: #5e5e5e;
+  background-color: transparent;
+}
+.navmenu-default .navmenu-text,
+.navbar-default .navbar-offcanvas .navmenu-text {
+  color: #777;
+}
+.navmenu-default .navmenu-nav > .dropdown > a:hover .caret,
+.navbar-default .navbar-offcanvas .navmenu-nav > .dropdown > a:hover .caret,
+.navmenu-default .navmenu-nav > .dropdown > a:focus .caret,
+.navbar-default .navbar-offcanvas .navmenu-nav > .dropdown > a:focus .caret {
+  border-top-color: #333;
+  border-bottom-color: #333;
+}
+.navmenu-default .navmenu-nav > .open > a,
+.navbar-default .navbar-offcanvas .navmenu-nav > .open > a,
+.navmenu-default .navmenu-nav > .open > a:hover,
+.navbar-default .navbar-offcanvas .navmenu-nav > .open > a:hover,
+.navmenu-default .navmenu-nav > .open > a:focus,
+.navbar-default .navbar-offcanvas .navmenu-nav > .open > a:focus {
+  color: #555;
+  background-color: #e7e7e7;
+}
+.navmenu-default .navmenu-nav > .open > a .caret,
+.navbar-default .navbar-offcanvas .navmenu-nav > .open > a .caret,
+.navmenu-default .navmenu-nav > .open > a:hover .caret,
+.navbar-default .navbar-offcanvas .navmenu-nav > .open > a:hover .caret,
+.navmenu-default .navmenu-nav > .open > a:focus .caret,
+.navbar-default .navbar-offcanvas .navmenu-nav > .open > a:focus .caret {
+  border-top-color: #555;
+  border-bottom-color: #555;
+}
+.navmenu-default .navmenu-nav > .dropdown > a .caret,
+.navbar-default .navbar-offcanvas .navmenu-nav > .dropdown > a .caret {
+  border-top-color: #777;
+  border-bottom-color: #777;
+}
+.navmenu-default .navmenu-nav.dropdown-menu,
+.navbar-default .navbar-offcanvas .navmenu-nav.dropdown-menu {
+  background-color: #e7e7e7;
+}
+.navmenu-default .navmenu-nav.dropdown-menu > .divider,
+.navbar-default .navbar-offcanvas .navmenu-nav.dropdown-menu > .divider {
+  background-color: #f8f8f8;
+}
+.navmenu-default .navmenu-nav.dropdown-menu > .active > a,
+.navbar-default .navbar-offcanvas .navmenu-nav.dropdown-menu > .active > a,
+.navmenu-default .navmenu-nav.dropdown-menu > .active > a:hover,
+.navbar-default .navbar-offcanvas .navmenu-nav.dropdown-menu > .active > a:hover,
+.navmenu-default .navmenu-nav.dropdown-menu > .active > a:focus,
+.navbar-default .navbar-offcanvas .navmenu-nav.dropdown-menu > .active > a:focus {
+  background-color: #d7d7d7;
+}
+.navmenu-default .navmenu-nav > li > a,
+.navbar-default .navbar-offcanvas .navmenu-nav > li > a {
+  color: #777;
+}
+.navmenu-default .navmenu-nav > li > a:hover,
+.navbar-default .navbar-offcanvas .navmenu-nav > li > a:hover,
+.navmenu-default .navmenu-nav > li > a:focus,
+.navbar-default .navbar-offcanvas .navmenu-nav > li > a:focus {
+  color: #333;
+  background-color: transparent;
+}
+.navmenu-default .navmenu-nav > .active > a,
+.navbar-default .navbar-offcanvas .navmenu-nav > .active > a,
+.navmenu-default .navmenu-nav > .active > a:hover,
+.navbar-default .navbar-offcanvas .navmenu-nav > .active > a:hover,
+.navmenu-default .navmenu-nav > .active > a:focus,
+.navbar-default .navbar-offcanvas .navmenu-nav > .active > a:focus {
+  color: #555;
+  background-color: #e7e7e7;
+}
+.navmenu-default .navmenu-nav > .disabled > a,
+.navbar-default .navbar-offcanvas .navmenu-nav > .disabled > a,
+.navmenu-default .navmenu-nav > .disabled > a:hover,
+.navbar-default .navbar-offcanvas .navmenu-nav > .disabled > a:hover,
+.navmenu-default .navmenu-nav > .disabled > a:focus,
+.navbar-default .navbar-offcanvas .navmenu-nav > .disabled > a:focus {
+  color: #ccc;
+  background-color: transparent;
+}
+.navmenu-inverse,
+.navbar-inverse .navbar-offcanvas {
+  background-color: #222;
+  border-color: #080808;
+}
+.navmenu-inverse .navmenu-brand,
+.navbar-inverse .navbar-offcanvas .navmenu-brand {
+  color: #999;
+}
+.navmenu-inverse .navmenu-brand:hover,
+.navbar-inverse .navbar-offcanvas .navmenu-brand:hover,
+.navmenu-inverse .navmenu-brand:focus,
+.navbar-inverse .navbar-offcanvas .navmenu-brand:focus {
+  color: #fff;
+  background-color: transparent;
+}
+.navmenu-inverse .navmenu-text,
+.navbar-inverse .navbar-offcanvas .navmenu-text {
+  color: #999;
+}
+.navmenu-inverse .navmenu-nav > .dropdown > a:hover .caret,
+.navbar-inverse .navbar-offcanvas .navmenu-nav > .dropdown > a:hover .caret,
+.navmenu-inverse .navmenu-nav > .dropdown > a:focus .caret,
+.navbar-inverse .navbar-offcanvas .navmenu-nav > .dropdown > a:focus .caret {
+  border-top-color: #fff;
+  border-bottom-color: #fff;
+}
+.navmenu-inverse .navmenu-nav > .open > a,
+.navbar-inverse .navbar-offcanvas .navmenu-nav > .open > a,
+.navmenu-inverse .navmenu-nav > .open > a:hover,
+.navbar-inverse .navbar-offcanvas .navmenu-nav > .open > a:hover,
+.navmenu-inverse .navmenu-nav > .open > a:focus,
+.navbar-inverse .navbar-offcanvas .navmenu-nav > .open > a:focus {
+  color: #fff;
+  background-color: #080808;
+}
+.navmenu-inverse .navmenu-nav > .open > a .caret,
+.navbar-inverse .navbar-offcanvas .navmenu-nav > .open > a .caret,
+.navmenu-inverse .navmenu-nav > .open > a:hover .caret,
+.navbar-inverse .navbar-offcanvas .navmenu-nav > .open > a:hover .caret,
+.navmenu-inverse .navmenu-nav > .open > a:focus .caret,
+.navbar-inverse .navbar-offcanvas .navmenu-nav > .open > a:focus .caret {
+  border-top-color: #fff;
+  border-bottom-color: #fff;
+}
+.navmenu-inverse .navmenu-nav > .dropdown > a .caret,
+.navbar-inverse .navbar-offcanvas .navmenu-nav > .dropdown > a .caret {
+  border-top-color: #999;
+  border-bottom-color: #999;
+}
+.navmenu-inverse .navmenu-nav.dropdown-menu,
+.navbar-inverse .navbar-offcanvas .navmenu-nav.dropdown-menu {
+  background-color: #080808;
+}
+.navmenu-inverse .navmenu-nav.dropdown-menu > .divider,
+.navbar-inverse .navbar-offcanvas .navmenu-nav.dropdown-menu > .divider {
+  background-color: #222;
+}
+.navmenu-inverse .navmenu-nav.dropdown-menu > .active > a,
+.navbar-inverse .navbar-offcanvas .navmenu-nav.dropdown-menu > .active > a,
+.navmenu-inverse .navmenu-nav.dropdown-menu > .active > a:hover,
+.navbar-inverse .navbar-offcanvas .navmenu-nav.dropdown-menu > .active > a:hover,
+.navmenu-inverse .navmenu-nav.dropdown-menu > .active > a:focus,
+.navbar-inverse .navbar-offcanvas .navmenu-nav.dropdown-menu > .active > a:focus {
+  background-color: #000;
+}
+.navmenu-inverse .navmenu-nav > li > a,
+.navbar-inverse .navbar-offcanvas .navmenu-nav > li > a {
+  color: #999;
+}
+.navmenu-inverse .navmenu-nav > li > a:hover,
+.navbar-inverse .navbar-offcanvas .navmenu-nav > li > a:hover,
+.navmenu-inverse .navmenu-nav > li > a:focus,
+.navbar-inverse .navbar-offcanvas .navmenu-nav > li > a:focus {
+  color: #fff;
+  background-color: transparent;
+}
+.navmenu-inverse .navmenu-nav > .active > a,
+.navbar-inverse .navbar-offcanvas .navmenu-nav > .active > a,
+.navmenu-inverse .navmenu-nav > .active > a:hover,
+.navbar-inverse .navbar-offcanvas .navmenu-nav > .active > a:hover,
+.navmenu-inverse .navmenu-nav > .active > a:focus,
+.navbar-inverse .navbar-offcanvas .navmenu-nav > .active > a:focus {
+  color: #fff;
+  background-color: #080808;
+}
+.navmenu-inverse .navmenu-nav > .disabled > a,
+.navbar-inverse .navbar-offcanvas .navmenu-nav > .disabled > a,
+.navmenu-inverse .navmenu-nav > .disabled > a:hover,
+.navbar-inverse .navbar-offcanvas .navmenu-nav > .disabled > a:hover,
+.navmenu-inverse .navmenu-nav > .disabled > a:focus,
+.navbar-inverse .navbar-offcanvas .navmenu-nav > .disabled > a:focus {
+  color: #444;
+  background-color: transparent;
+}
+.alert-fixed-top,
+.alert-fixed-bottom {
+  position: fixed;
+  left: 0;
+  z-index: 1035;
+  width: 100%;
+  margin: 0;
+  border-radius: 0;
+}
+@media (min-width: 992px) {
+  .alert-fixed-top,
+  .alert-fixed-bottom {
+    left: 50%;
+    width: 992px;
+    margin-left: -496px;
+  }
+}
+.alert-fixed-top {
+  top: 0;
+  border-width: 0 0 1px 0;
+}
+@media (min-width: 992px) {
+  .alert-fixed-top {
+    border-width: 0 1px 1px 1px;
+    border-bottom-right-radius: 4px;
+    border-bottom-left-radius: 4px;
+  }
+}
+.alert-fixed-bottom {
+  bottom: 0;
+  border-width: 1px 0 0 0;
+}
+@media (min-width: 992px) {
+  .alert-fixed-bottom {
+    border-width: 1px 1px 0 1px;
+    border-top-left-radius: 4px;
+    border-top-right-radius: 4px;
+  }
+}
+.offcanvas {
+  display: none;
+}
+.offcanvas.in {
+  display: block;
+}
+@media (max-width: 767px) {
+  .offcanvas-xs {
+    display: none;
+  }
+  .offcanvas-xs.in {
+    display: block;
+  }
+}
+@media (max-width: 991px) {
+  .offcanvas-sm {
+    display: none;
+  }
+  .offcanvas-sm.in {
+    display: block;
+  }
+}
+@media (max-width: 1199px) {
+  .offcanvas-md {
+    display: none;
+  }
+  .offcanvas-md.in {
+    display: block;
+  }
+}
+.offcanvas-lg {
+  display: none;
+}
+.offcanvas-lg.in {
+  display: block;
+}
+.canvas-sliding {
+  -webkit-transition: top .35s, left .35s, bottom .35s, right .35s;
+          transition: top .35s, left .35s, bottom .35s, right .35s;
+}
+.offcanvas-clone {
+  position: absolute !important;
+  top: auto !important;
+  right: 0 !important;
+  bottom: 0 !important;
+  left: auto !important;
+  width: 0 !important;
+  height: 0 !important;
+  padding: 0 !important;
+  margin: 0 !important;
+  overflow: hidden !important;
+  border: none !important;
+  opacity: 0 !important;
+}
+.table.rowlink td:not(.rowlink-skip),
+.table .rowlink td:not(.rowlink-skip) {
+  cursor: pointer;
+}
+.table.rowlink td:not(.rowlink-skip) a,
+.table .rowlink td:not(.rowlink-skip) a {
+  font: inherit;
+  color: inherit;
+  text-decoration: inherit;
+}
+.table-hover.rowlink tr:hover td,
+.table-hover .rowlink tr:hover td {
+  background-color: #cfcfcf;
+}
+.btn-file {
+  position: relative;
+  overflow: hidden;
+  vertical-align: middle;
+}
+.btn-file > input {
+  position: absolute;
+  top: 0;
+  right: 0;
+  width: 100%;
+  height: 100%;
+  margin: 0;
+  font-size: 23px;
+  cursor: pointer;
+  filter: alpha(opacity=0);
+  opacity: 0;
+
+  direction: ltr;
+}
+.fileinput {
+  display: inline-block;
+  margin-bottom: 9px;
+}
+.fileinput .form-control {
+  display: inline-block;
+  padding-top: 7px;
+  padding-bottom: 5px;
+  margin-bottom: 0;
+  vertical-align: middle;
+  cursor: text;
+}
+.fileinput .thumbnail {
+  display: inline-block;
+  margin-bottom: 5px;
+  overflow: hidden;
+  text-align: center;
+  vertical-align: middle;
+}
+.fileinput .thumbnail > img {
+  max-height: 100%;
+}
+.fileinput .btn {
+  vertical-align: middle;
+}
+.fileinput-exists .fileinput-new,
+.fileinput-new .fileinput-exists {
+  display: none;
+}
+.fileinput-inline .fileinput-controls {
+  display: inline;
+}
+.fileinput-filename {
+  display: inline-block;
+  overflow: hidden;
+  vertical-align: middle;
+}
+.form-control .fileinput-filename {
+  vertical-align: bottom;
+}
+.fileinput.input-group {
+  display: table;
+}
+.fileinput.input-group > * {
+  position: relative;
+  z-index: 2;
+}
+.fileinput.input-group > .btn-file {
+  z-index: 1;
+}
+.fileinput-new.input-group .btn-file,
+.fileinput-new .input-group .btn-file {
+  border-radius: 0 4px 4px 0;
+}
+.fileinput-new.input-group .btn-file.btn-xs,
+.fileinput-new .input-group .btn-file.btn-xs,
+.fileinput-new.input-group .btn-file.btn-sm,
+.fileinput-new .input-group .btn-file.btn-sm {
+  border-radius: 0 3px 3px 0;
+}
+.fileinput-new.input-group .btn-file.btn-lg,
+.fileinput-new .input-group .btn-file.btn-lg {
+  border-radius: 0 6px 6px 0;
+}
+.form-group.has-warning .fileinput .fileinput-preview {
+  color: #8a6d3b;
+}
+.form-group.has-warning .fileinput .thumbnail {
+  border-color: #faebcc;
+}
+.form-group.has-error .fileinput .fileinput-preview {
+  color: #a94442;
+}
+.form-group.has-error .fileinput .thumbnail {
+  border-color: #ebccd1;
+}
+.form-group.has-success .fileinput .fileinput-preview {
+  color: #3c763d;
+}
+.form-group.has-success .fileinput .thumbnail {
+  border-color: #d6e9c6;
+}
+.input-group-addon:not(:first-child) {
+  border-left: 0;
+}
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jasny/jasny-bootstrap.js b/ruoyi-admin/src/main/resources/static/ajax/libs/jasny/jasny-bootstrap.js
new file mode 100644
index 0000000..870ad9f
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jasny/jasny-bootstrap.js
@@ -0,0 +1,324 @@
+/*!
+ * Jasny Bootstrap v4.0.0 (http://jasny.github.io/bootstrap)
+ * Copyright 2012-2014 Arnold Daniels
+ * Licensed under Apache-2.0 (https://github.com/jasny/bootstrap/blob/master/LICENSE)
+ */
+
++function ($) { "use strict";
+
+  var isIE = window.navigator.appName == 'Microsoft Internet Explorer'
+
+  // FILEUPLOAD PUBLIC CLASS DEFINITION
+  // =================================
+
+  var Fileinput = function (element, options) {
+    this.$element = $(element)
+
+    this.options = $.extend({}, Fileinput.DEFAULTS, options)
+    this.$input = this.$element.find(':file')
+    if (this.$input.length === 0) return
+
+    this.name = this.$input.attr('name') || options.name
+
+    this.$hidden = this.$element.find('input[type=hidden][name="' + this.name + '"]')
+    if (this.$hidden.length === 0) {
+      this.$hidden = $('<input type="hidden">').insertBefore(this.$input)
+    }
+
+    this.$preview = this.$element.find('.fileinput-preview')
+    var height = this.$preview.css('height')
+    if (this.$preview.css('display') !== 'inline' && height !== '0px' && height !== 'none') {
+      this.$preview.css('line-height', height)
+    }
+
+    this.original = {
+      exists: this.$element.hasClass('fileinput-exists'),
+      preview: this.$preview.html(),
+      hiddenVal: this.$hidden.val()
+    }
+
+    this.listen()
+    this.reset()
+  }
+
+  Fileinput.DEFAULTS = {
+    clearName: true
+  }
+
+  Fileinput.prototype.listen = function() {
+    this.$input.on('change.bs.fileinput', $.proxy(this.change, this))
+    $(this.$input[0].form).on('reset.bs.fileinput', $.proxy(this.reset, this))
+
+    this.$element.find('[data-trigger="fileinput"]').on('click.bs.fileinput', $.proxy(this.trigger, this))
+    this.$element.find('[data-dismiss="fileinput"]').on('click.bs.fileinput', $.proxy(this.clear, this))
+  },
+
+  Fileinput.prototype.verifySizes = function(files) {
+    if (typeof this.options.maxSize === 'undefined') return true
+
+    var max = parseFloat(this.options.maxSize)
+    if (max !== this.options.maxSize) return true
+
+    for (var i = 0; i < files.length; i++) {
+      var size = typeof files[i].size !== 'undefined' ? files[i].size : null
+      if (size === null) continue
+
+      size = size / 1000 / 1000 /* convert from bytes to MB */
+      if (size > max) return false
+    }
+
+    return true
+  }
+
+  Fileinput.prototype.change = function(e) {
+    var files = e.target.files === undefined ? (e.target && e.target.value ? [{ name: e.target.value.replace(/^.+\\/, '')}] : []) : e.target.files
+
+    e.stopPropagation()
+
+    if (files.length === 0) {
+      this.clear()
+      this.$element.trigger('clear.bs.fileinput')
+      return
+    }
+
+    if (!this.verifySizes(files)) {
+      this.$element.trigger('max_size.bs.fileinput')
+
+      this.clear()
+      this.$element.trigger('clear.bs.fileinput')
+      return
+    }
+
+    this.$hidden.val('')
+    this.$hidden.attr('name', '')
+    this.$input.attr('name', this.name)
+
+    var file = files[0]
+
+    if (this.$preview.length > 0 && (typeof file.type !== "undefined" ? file.type.match(/^image\/(gif|png|jpeg|svg\+xml)$/) : file.name.match(/\.(gif|png|jpe?g|svg)$/i)) && typeof FileReader !== "undefined") {
+      var Fileinput = this
+      var reader = new FileReader()
+      var preview = this.$preview
+      var element = this.$element
+
+      reader.onload = function(re) {
+        var $img = $('<img>')
+        $img[0].src = re.target.result
+        files[0].result = re.target.result
+
+        element.find('.fileinput-filename').text(file.name)
+
+        // if parent has max-height, using `(max-)height: 100%` on child doesn't take padding and border into account
+        if (preview.css('max-height') != 'none') {
+          var mh = parseInt(preview.css('max-height'), 10) || 0
+          var pt = parseInt(preview.css('padding-top'), 10) || 0
+          var pb = parseInt(preview.css('padding-bottom'), 10) || 0
+          var bt = parseInt(preview.css('border-top'), 10) || 0
+          var bb = parseInt(preview.css('border-bottom'), 10) || 0
+
+          $img.css('max-height', mh - pt - pb - bt - bb)
+        }
+
+        preview.html($img)
+        if (Fileinput.options.exif) {
+          //Fix image tranformation if this is possible
+          Fileinput.setImageTransform($img, file);
+        }
+        element.addClass('fileinput-exists').removeClass('fileinput-new')
+
+        element.trigger('change.bs.fileinput', files)
+      }
+
+      reader.readAsDataURL(file)
+    } else {
+      var text = file.name
+      var $nameView = this.$element.find('.fileinput-filename')
+
+      if (files.length > 1) {
+        text = $.map(files, function(file) {
+          return file.name;
+        }).join(', ')
+      }
+
+      $nameView.text(text)
+      this.$preview.text(file.name)
+      this.$element.addClass('fileinput-exists').removeClass('fileinput-new')
+      this.$element.trigger('change.bs.fileinput')
+    }
+  },
+
+  Fileinput.prototype.setImageTransform = function($img, file) {
+      var Fileinput = this;
+      var reader = new FileReader();
+      reader.onload = function(me) {
+        var transform = false;
+        var view = new DataView(reader.result);
+        var exif = Fileinput.getImageExif(view);
+        if (exif) {
+            Fileinput.resetOrientation($img, exif);
+        }
+      }
+
+      reader.readAsArrayBuffer(file);
+  }
+
+  Fileinput.prototype.getImageExif = function(view) {
+    if (view.getUint16(0, false) != 0xFFD8) {
+      return -2;
+    }
+    var length = view.byteLength, offset = 2;
+    while (offset < length) {
+      var marker = view.getUint16(offset, false);
+          offset += 2;
+      if (marker == 0xFFE1) {
+        if (view.getUint32(offset += 2, false) != 0x45786966) {
+          return -1;
+        }
+        var little = view.getUint16(offset += 6, false) == 0x4949;
+            offset += view.getUint32(offset + 4, little);
+        var tags = view.getUint16(offset, little);
+            offset += 2;
+        for (var i = 0; i < tags; i++)   {
+          if (view.getUint16(offset + (i * 12), little) == 0x0112) {
+            return view.getUint16(offset + (i * 12) + 8, little);
+          }
+        }
+      }
+      else if ((marker & 0xFF00) != 0xFF00){
+         break;
+      } else {
+        offset += view.getUint16(offset, false);
+      }
+    }
+
+    return -1;
+  }
+
+  Fileinput.prototype.resetOrientation = function($img, transform) {
+  var img = new Image();
+
+  img.onload = function() {
+    var width = img.width,
+        height = img.height,
+        canvas = document.createElement('canvas'),
+        ctx = canvas.getContext("2d");
+
+    // set proper canvas dimensions before transform & export
+    if ([5,6,7,8].indexOf(transform) > -1) {
+      canvas.width = height;
+      canvas.height = width;
+    } else {
+      canvas.width = width;
+      canvas.height = height;
+    }
+
+    // transform context before drawing image
+    switch (transform) {
+      case 2: ctx.transform(-1, 0, 0, 1, width, 0); break;
+      case 3: ctx.transform(-1, 0, 0, -1, width, height ); break;
+      case 4: ctx.transform(1, 0, 0, -1, 0, height ); break;
+      case 5: ctx.transform(0, 1, 1, 0, 0, 0); break;
+      case 6: ctx.transform(0, 1, -1, 0, height , 0); break;
+      case 7: ctx.transform(0, -1, -1, 0, height , width); break;
+      case 8: ctx.transform(0, -1, 1, 0, 0, width); break;
+      default: ctx.transform(1, 0, 0, 1, 0, 0);
+    }
+
+    // draw image
+    ctx.drawImage(img, 0, 0);
+
+    // export base64
+    $img.attr('src', canvas.toDataURL());
+  };
+
+  img.src = $img.attr('src');
+};
+
+  Fileinput.prototype.clear = function(e) {
+    if (e) e.preventDefault()
+
+    this.$hidden.val('')
+    this.$hidden.attr('name', this.name)
+    if (this.options.clearName) this.$input.attr('name', '')
+
+    //ie8+ doesn't support changing the value of input with type=file so clone instead
+    if (isIE) {
+      var inputClone = this.$input.clone(true);
+      this.$input.after(inputClone);
+      this.$input.remove();
+      this.$input = inputClone;
+    } else {
+      this.$input.val('')
+    }
+
+    this.$preview.html('')
+    this.$element.find('.fileinput-filename').text('')
+    this.$element.addClass('fileinput-new').removeClass('fileinput-exists')
+
+    if (e !== undefined) {
+      this.$input.trigger('change')
+      this.$element.trigger('clear.bs.fileinput')
+    }
+  },
+
+  Fileinput.prototype.reset = function() {
+    this.clear()
+
+    this.$hidden.val(this.original.hiddenVal)
+    this.$preview.html(this.original.preview)
+    this.$element.find('.fileinput-filename').text('')
+
+    if (this.original.exists) this.$element.addClass('fileinput-exists').removeClass('fileinput-new')
+     else this.$element.addClass('fileinput-new').removeClass('fileinput-exists')
+
+    this.$element.trigger('reseted.bs.fileinput')
+  },
+
+  Fileinput.prototype.trigger = function(e) {
+    this.$input.trigger('click')
+    e.preventDefault()
+  }
+
+
+  // FILEUPLOAD PLUGIN DEFINITION
+  // ===========================
+
+  var old = $.fn.fileinput
+
+  $.fn.fileinput = function (options) {
+    return this.each(function () {
+      var $this = $(this),
+          data = $this.data('bs.fileinput')
+      if (!data) $this.data('bs.fileinput', (data = new Fileinput(this, options)))
+      if (typeof options == 'string') data[options]()
+    })
+  }
+
+  $.fn.fileinput.Constructor = Fileinput
+
+
+  // FILEINPUT NO CONFLICT
+  // ====================
+
+  $.fn.fileinput.noConflict = function () {
+    $.fn.fileinput = old
+    return this
+  }
+
+
+  // FILEUPLOAD DATA-API
+  // ==================
+
+  $(document).on('click.fileinput.data-api', '[data-provides="fileinput"]', function (e) {
+    var $this = $(this)
+    if ($this.data('bs.fileinput')) return
+    $this.fileinput($this.data())
+
+    var $target = $(e.target).closest('[data-dismiss="fileinput"],[data-trigger="fileinput"]');
+    if ($target.length > 0) {
+      e.preventDefault()
+      $target.trigger('click.bs.fileinput')
+    }
+  })
+
+}(window.jQuery);
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jasny/jasny-bootstrap.min.css b/ruoyi-admin/src/main/resources/static/ajax/libs/jasny/jasny-bootstrap.min.css
new file mode 100644
index 0000000..312eada
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jasny/jasny-bootstrap.min.css
@@ -0,0 +1,7 @@
+/*!
+ * Jasny Bootstrap v3.1.3 (http://jasny.github.io/bootstrap)
+ * Copyright 2012-2014 Arnold Daniels
+ * Licensed under Apache-2.0 (https://github.com/jasny/bootstrap/blob/master/LICENSE)
+ */
+
+.container-smooth{max-width:1170px}@media (min-width:1px){.container-smooth{width:auto}}.btn-labeled{padding-top:0;padding-bottom:0}.btn-label{position:relative;background:0 0;background:rgba(0,0,0,.15);display:inline-block;padding:6px 12px;left:-12px;border-radius:3px 0 0 3px}.btn-label.btn-label-right{left:auto;right:-12px;border-radius:0 3px 3px 0}.btn-lg .btn-label{padding:10px 16px;left:-16px;border-radius:5px 0 0 5px}.btn-lg .btn-label.btn-label-right{left:auto;right:-16px;border-radius:0 5px 5px 0}.btn-sm .btn-label{padding:5px 10px;left:-10px;border-radius:2px 0 0 2px}.btn-sm .btn-label.btn-label-right{left:auto;right:-10px;border-radius:0 2px 2px 0}.btn-xs .btn-label{padding:1px 5px;left:-5px;border-radius:2px 0 0 2px}.btn-xs .btn-label.btn-label-right{left:auto;right:-5px;border-radius:0 2px 2px 0}.nav-tabs-bottom{border-bottom:0;border-top:1px solid #ddd}.nav-tabs-bottom>li{margin-bottom:0;margin-top:-1px}.nav-tabs-bottom>li>a{border-radius:0 0 4px 4px}.nav-tabs-bottom>li>a:hover,.nav-tabs-bottom>li>a:focus,.nav-tabs-bottom>li.active>a,.nav-tabs-bottom>li.active>a:hover,.nav-tabs-bottom>li.active>a:focus{border:1px solid #ddd;border-top-color:transparent}.nav-tabs-left{border-bottom:0;border-right:1px solid #ddd}.nav-tabs-left>li{margin-bottom:0;margin-right:-1px;float:none}.nav-tabs-left>li>a{border-radius:4px 0 0 4px;margin-right:0;margin-bottom:2px}.nav-tabs-left>li>a:hover,.nav-tabs-left>li>a:focus,.nav-tabs-left>li.active>a,.nav-tabs-left>li.active>a:hover,.nav-tabs-left>li.active>a:focus{border:1px solid #ddd;border-right-color:transparent}.row>.nav-tabs-left{padding-right:0;padding-left:15px;margin-right:-1px;position:relative;z-index:1}.row>.nav-tabs-left+.tab-content{border-left:1px solid #ddd}.nav-tabs-right{border-bottom:0;border-left:1px solid #ddd}.nav-tabs-right>li{margin-bottom:0;margin-left:-1px;float:none}.nav-tabs-right>li>a{border-radius:0 4px 4px 0;margin-left:0;margin-bottom:2px}.nav-tabs-right>li>a:hover,.nav-tabs-right>li>a:focus,.nav-tabs-right>li.active>a,.nav-tabs-right>li.active>a:hover,.nav-tabs-right>li.active>a:focus{border:1px solid #ddd;border-left-color:transparent}.row>.nav-tabs-right{padding-left:0;padding-right:15px}.navmenu,.navbar-offcanvas{width:300px;height:auto;border-width:1px;border-style:solid;border-radius:4px}.navmenu-fixed-left,.navmenu-fixed-right,.navbar-offcanvas{position:fixed;z-index:1030;top:0;bottom:0;overflow-y:auto;border-radius:0}.navmenu-fixed-left,.navbar-offcanvas.navmenu-fixed-left{left:0;right:auto;border-width:0 1px 0 0}.navmenu-fixed-right,.navbar-offcanvas{left:auto;right:0;border-width:0 0 0 1px}.navmenu-nav{margin-bottom:10px}.navmenu-nav.dropdown-menu{position:static;margin:0;padding-top:0;float:none;border:none;-webkit-box-shadow:none;box-shadow:none;border-radius:0}.navbar-offcanvas .navbar-nav{margin:0}@media (min-width:768px){.navbar-offcanvas{width:auto;border-top:0;box-shadow:none}.navbar-offcanvas.offcanvas{position:static;display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-offcanvas .navbar-nav.navbar-left:first-child{margin-left:-15px}.navbar-offcanvas .navbar-nav.navbar-right:last-child{margin-right:-15px}.navbar-offcanvas .navmenu-brand{display:none}}.navmenu-brand{display:block;font-size:18px;line-height:20px;padding:10px 15px;margin:10px 0}.navmenu-brand:hover,.navmenu-brand:focus{text-decoration:none}.navmenu-default,.navbar-default .navbar-offcanvas{background-color:#f8f8f8;border-color:#e7e7e7}.navmenu-default .navmenu-brand,.navbar-default .navbar-offcanvas .navmenu-brand{color:#777}.navmenu-default .navmenu-brand:hover,.navbar-default .navbar-offcanvas .navmenu-brand:hover,.navmenu-default .navmenu-brand:focus,.navbar-default .navbar-offcanvas .navmenu-brand:focus{color:#5e5e5e;background-color:transparent}.navmenu-default .navmenu-text,.navbar-default .navbar-offcanvas .navmenu-text{color:#777}.navmenu-default .navmenu-nav>.dropdown>a:hover .caret,.navbar-default .navbar-offcanvas .navmenu-nav>.dropdown>a:hover .caret,.navmenu-default .navmenu-nav>.dropdown>a:focus .caret,.navbar-default .navbar-offcanvas .navmenu-nav>.dropdown>a:focus .caret{border-top-color:#333;border-bottom-color:#333}.navmenu-default .navmenu-nav>.open>a,.navbar-default .navbar-offcanvas .navmenu-nav>.open>a,.navmenu-default .navmenu-nav>.open>a:hover,.navbar-default .navbar-offcanvas .navmenu-nav>.open>a:hover,.navmenu-default .navmenu-nav>.open>a:focus,.navbar-default .navbar-offcanvas .navmenu-nav>.open>a:focus{background-color:#e7e7e7;color:#555}.navmenu-default .navmenu-nav>.open>a .caret,.navbar-default .navbar-offcanvas .navmenu-nav>.open>a .caret,.navmenu-default .navmenu-nav>.open>a:hover .caret,.navbar-default .navbar-offcanvas .navmenu-nav>.open>a:hover .caret,.navmenu-default .navmenu-nav>.open>a:focus .caret,.navbar-default .navbar-offcanvas .navmenu-nav>.open>a:focus .caret{border-top-color:#555;border-bottom-color:#555}.navmenu-default .navmenu-nav>.dropdown>a .caret,.navbar-default .navbar-offcanvas .navmenu-nav>.dropdown>a .caret{border-top-color:#777;border-bottom-color:#777}.navmenu-default .navmenu-nav.dropdown-menu,.navbar-default .navbar-offcanvas .navmenu-nav.dropdown-menu{background-color:#e7e7e7}.navmenu-default .navmenu-nav.dropdown-menu>.divider,.navbar-default .navbar-offcanvas .navmenu-nav.dropdown-menu>.divider{background-color:#f8f8f8}.navmenu-default .navmenu-nav.dropdown-menu>.active>a,.navbar-default .navbar-offcanvas .navmenu-nav.dropdown-menu>.active>a,.navmenu-default .navmenu-nav.dropdown-menu>.active>a:hover,.navbar-default .navbar-offcanvas .navmenu-nav.dropdown-menu>.active>a:hover,.navmenu-default .navmenu-nav.dropdown-menu>.active>a:focus,.navbar-default .navbar-offcanvas .navmenu-nav.dropdown-menu>.active>a:focus{background-color:#d7d7d7}.navmenu-default .navmenu-nav>li>a,.navbar-default .navbar-offcanvas .navmenu-nav>li>a{color:#777}.navmenu-default .navmenu-nav>li>a:hover,.navbar-default .navbar-offcanvas .navmenu-nav>li>a:hover,.navmenu-default .navmenu-nav>li>a:focus,.navbar-default .navbar-offcanvas .navmenu-nav>li>a:focus{color:#333;background-color:transparent}.navmenu-default .navmenu-nav>.active>a,.navbar-default .navbar-offcanvas .navmenu-nav>.active>a,.navmenu-default .navmenu-nav>.active>a:hover,.navbar-default .navbar-offcanvas .navmenu-nav>.active>a:hover,.navmenu-default .navmenu-nav>.active>a:focus,.navbar-default .navbar-offcanvas .navmenu-nav>.active>a:focus{color:#555;background-color:#e7e7e7}.navmenu-default .navmenu-nav>.disabled>a,.navbar-default .navbar-offcanvas .navmenu-nav>.disabled>a,.navmenu-default .navmenu-nav>.disabled>a:hover,.navbar-default .navbar-offcanvas .navmenu-nav>.disabled>a:hover,.navmenu-default .navmenu-nav>.disabled>a:focus,.navbar-default .navbar-offcanvas .navmenu-nav>.disabled>a:focus{color:#ccc;background-color:transparent}.navmenu-inverse,.navbar-inverse .navbar-offcanvas{background-color:#222;border-color:#080808}.navmenu-inverse .navmenu-brand,.navbar-inverse .navbar-offcanvas .navmenu-brand{color:#999}.navmenu-inverse .navmenu-brand:hover,.navbar-inverse .navbar-offcanvas .navmenu-brand:hover,.navmenu-inverse .navmenu-brand:focus,.navbar-inverse .navbar-offcanvas .navmenu-brand:focus{color:#fff;background-color:transparent}.navmenu-inverse .navmenu-text,.navbar-inverse .navbar-offcanvas .navmenu-text{color:#999}.navmenu-inverse .navmenu-nav>.dropdown>a:hover .caret,.navbar-inverse .navbar-offcanvas .navmenu-nav>.dropdown>a:hover .caret,.navmenu-inverse .navmenu-nav>.dropdown>a:focus .caret,.navbar-inverse .navbar-offcanvas .navmenu-nav>.dropdown>a:focus .caret{border-top-color:#fff;border-bottom-color:#fff}.navmenu-inverse .navmenu-nav>.open>a,.navbar-inverse .navbar-offcanvas .navmenu-nav>.open>a,.navmenu-inverse .navmenu-nav>.open>a:hover,.navbar-inverse .navbar-offcanvas .navmenu-nav>.open>a:hover,.navmenu-inverse .navmenu-nav>.open>a:focus,.navbar-inverse .navbar-offcanvas .navmenu-nav>.open>a:focus{background-color:#080808;color:#fff}.navmenu-inverse .navmenu-nav>.open>a .caret,.navbar-inverse .navbar-offcanvas .navmenu-nav>.open>a .caret,.navmenu-inverse .navmenu-nav>.open>a:hover .caret,.navbar-inverse .navbar-offcanvas .navmenu-nav>.open>a:hover .caret,.navmenu-inverse .navmenu-nav>.open>a:focus .caret,.navbar-inverse .navbar-offcanvas .navmenu-nav>.open>a:focus .caret{border-top-color:#fff;border-bottom-color:#fff}.navmenu-inverse .navmenu-nav>.dropdown>a .caret,.navbar-inverse .navbar-offcanvas .navmenu-nav>.dropdown>a .caret{border-top-color:#999;border-bottom-color:#999}.navmenu-inverse .navmenu-nav.dropdown-menu,.navbar-inverse .navbar-offcanvas .navmenu-nav.dropdown-menu{background-color:#080808}.navmenu-inverse .navmenu-nav.dropdown-menu>.divider,.navbar-inverse .navbar-offcanvas .navmenu-nav.dropdown-menu>.divider{background-color:#222}.navmenu-inverse .navmenu-nav.dropdown-menu>.active>a,.navbar-inverse .navbar-offcanvas .navmenu-nav.dropdown-menu>.active>a,.navmenu-inverse .navmenu-nav.dropdown-menu>.active>a:hover,.navbar-inverse .navbar-offcanvas .navmenu-nav.dropdown-menu>.active>a:hover,.navmenu-inverse .navmenu-nav.dropdown-menu>.active>a:focus,.navbar-inverse .navbar-offcanvas .navmenu-nav.dropdown-menu>.active>a:focus{background-color:#000}.navmenu-inverse .navmenu-nav>li>a,.navbar-inverse .navbar-offcanvas .navmenu-nav>li>a{color:#999}.navmenu-inverse .navmenu-nav>li>a:hover,.navbar-inverse .navbar-offcanvas .navmenu-nav>li>a:hover,.navmenu-inverse .navmenu-nav>li>a:focus,.navbar-inverse .navbar-offcanvas .navmenu-nav>li>a:focus{color:#fff;background-color:transparent}.navmenu-inverse .navmenu-nav>.active>a,.navbar-inverse .navbar-offcanvas .navmenu-nav>.active>a,.navmenu-inverse .navmenu-nav>.active>a:hover,.navbar-inverse .navbar-offcanvas .navmenu-nav>.active>a:hover,.navmenu-inverse .navmenu-nav>.active>a:focus,.navbar-inverse .navbar-offcanvas .navmenu-nav>.active>a:focus{color:#fff;background-color:#080808}.navmenu-inverse .navmenu-nav>.disabled>a,.navbar-inverse .navbar-offcanvas .navmenu-nav>.disabled>a,.navmenu-inverse .navmenu-nav>.disabled>a:hover,.navbar-inverse .navbar-offcanvas .navmenu-nav>.disabled>a:hover,.navmenu-inverse .navmenu-nav>.disabled>a:focus,.navbar-inverse .navbar-offcanvas .navmenu-nav>.disabled>a:focus{color:#444;background-color:transparent}.alert-fixed-top,.alert-fixed-bottom{position:fixed;width:100%;z-index:1035;border-radius:0;margin:0;left:0}@media (min-width:992px){.alert-fixed-top,.alert-fixed-bottom{width:992px;left:50%;margin-left:-496px}}.alert-fixed-top{top:0;border-width:0 0 1px}@media (min-width:992px){.alert-fixed-top{border-bottom-right-radius:4px;border-bottom-left-radius:4px;border-width:0 1px 1px}}.alert-fixed-bottom{bottom:0;border-width:1px 0 0}@media (min-width:992px){.alert-fixed-bottom{border-top-right-radius:4px;border-top-left-radius:4px;border-width:1px 1px 0}}.offcanvas{display:none}.offcanvas.in{display:block}@media (max-width:767px){.offcanvas-xs{display:none}.offcanvas-xs.in{display:block}}@media (max-width:991px){.offcanvas-sm{display:none}.offcanvas-sm.in{display:block}}@media (max-width:1199px){.offcanvas-md{display:none}.offcanvas-md.in{display:block}}.offcanvas-lg{display:none}.offcanvas-lg.in{display:block}.canvas-sliding{-webkit-transition:top .35s,left .35s,bottom .35s,right .35s;transition:top .35s,left .35s,bottom .35s,right .35s}.offcanvas-clone{height:0!important;width:0!important;overflow:hidden!important;border:none!important;margin:0!important;padding:0!important;position:absolute!important;top:auto!important;left:auto!important;bottom:0!important;right:0!important;opacity:0!important}.table.rowlink td:not(.rowlink-skip),.table .rowlink td:not(.rowlink-skip){cursor:pointer}.table.rowlink td:not(.rowlink-skip) a,.table .rowlink td:not(.rowlink-skip) a{color:inherit;font:inherit;text-decoration:inherit}.table-hover.rowlink tr:hover td,.table-hover .rowlink tr:hover td{background-color:#cfcfcf}.btn-file{overflow:hidden;position:relative;vertical-align:middle}.btn-file>input{position:absolute;top:0;right:0;margin:0;opacity:0;filter:alpha(opacity=0);font-size:23px;height:100%;width:100%;direction:ltr;cursor:pointer}.fileinput{margin-bottom:9px;display:inline-block}.fileinput .form-control{padding-top:7px;padding-bottom:5px;display:inline-block;margin-bottom:0;vertical-align:middle;cursor:text}.fileinput .thumbnail{overflow:hidden;display:inline-block;margin-bottom:5px;vertical-align:middle;text-align:center}.fileinput .thumbnail>img{max-height:100%}.fileinput .btn{vertical-align:middle}.fileinput-exists .fileinput-new,.fileinput-new .fileinput-exists{display:none}.fileinput-inline .fileinput-controls{display:inline}.fileinput-filename{vertical-align:middle;display:inline-block;overflow:hidden}.form-control .fileinput-filename{vertical-align:bottom}.fileinput.input-group{display:table}.fileinput.input-group>*{position:relative;z-index:2}.fileinput.input-group>.btn-file{z-index:1}.fileinput-new.input-group .btn-file,.fileinput-new .input-group .btn-file{border-radius:0 4px 4px 0}.fileinput-new.input-group .btn-file.btn-xs,.fileinput-new .input-group .btn-file.btn-xs,.fileinput-new.input-group .btn-file.btn-sm,.fileinput-new .input-group .btn-file.btn-sm{border-radius:0 3px 3px 0}.fileinput-new.input-group .btn-file.btn-lg,.fileinput-new .input-group .btn-file.btn-lg{border-radius:0 6px 6px 0}.form-group.has-warning .fileinput .fileinput-preview{color:#8a6d3b}.form-group.has-warning .fileinput .thumbnail{border-color:#faebcc}.form-group.has-error .fileinput .fileinput-preview{color:#a94442}.form-group.has-error .fileinput .thumbnail{border-color:#ebccd1}.form-group.has-success .fileinput .fileinput-preview{color:#3c763d}.form-group.has-success .fileinput .thumbnail{border-color:#d6e9c6}.input-group-addon:not(:first-child){border-left:0}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jasny/jasny-bootstrap.min.js b/ruoyi-admin/src/main/resources/static/ajax/libs/jasny/jasny-bootstrap.min.js
new file mode 100644
index 0000000..e0f7b8f
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jasny/jasny-bootstrap.min.js
@@ -0,0 +1,6 @@
+/*!
+ * Jasny Bootstrap v4.0.0 (http://jasny.github.io/bootstrap)
+ * Copyright 2012-2014 Arnold Daniels
+ * Licensed under Apache-2.0 (https://github.com/jasny/bootstrap/blob/master/LICENSE)
+ */
++function($){var isIE=window.navigator.appName=="Microsoft Internet Explorer";var Fileinput=function(element,options){this.$element=$(element);this.options=$.extend({},Fileinput.DEFAULTS,options);this.$input=this.$element.find(":file");if(this.$input.length===0){return}this.name=this.$input.attr("name")||options.name;this.$hidden=this.$element.find('input[type=hidden][name="'+this.name+'"]');if(this.$hidden.length===0){this.$hidden=$('<input type="hidden">').insertBefore(this.$input)}this.$preview=this.$element.find(".fileinput-preview");var height=this.$preview.css("height");if(this.$preview.css("display")!=="inline"&&height!=="0px"&&height!=="none"){this.$preview.css("line-height",height)}this.original={exists:this.$element.hasClass("fileinput-exists"),preview:this.$preview.html(),hiddenVal:this.$hidden.val()};this.listen();this.reset()};Fileinput.DEFAULTS={clearName:true};Fileinput.prototype.listen=function(){this.$input.on("change.bs.fileinput",$.proxy(this.change,this));$(this.$input[0].form).on("reset.bs.fileinput",$.proxy(this.reset,this));this.$element.find('[data-trigger="fileinput"]').on("click.bs.fileinput",$.proxy(this.trigger,this));this.$element.find('[data-dismiss="fileinput"]').on("click.bs.fileinput",$.proxy(this.clear,this))},Fileinput.prototype.verifySizes=function(files){if(typeof this.options.maxSize==="undefined"){return true}var max=parseFloat(this.options.maxSize);if(max!==this.options.maxSize){return true}for(var i=0;i<files.length;i++){var size=typeof files[i].size!=="undefined"?files[i].size:null;if(size===null){continue}size=size/1000/1000;if(size>max){return false}}return true};Fileinput.prototype.change=function(e){var files=e.target.files===undefined?(e.target&&e.target.value?[{name:e.target.value.replace(/^.+\\/,"")}]:[]):e.target.files;e.stopPropagation();if(files.length===0){this.clear();this.$element.trigger("clear.bs.fileinput");return}if(!this.verifySizes(files)){this.$element.trigger("max_size.bs.fileinput");this.clear();this.$element.trigger("clear.bs.fileinput");return}this.$hidden.val("");this.$hidden.attr("name","");this.$input.attr("name",this.name);var file=files[0];if(this.$preview.length>0&&(typeof file.type!=="undefined"?file.type.match(/^image\/(gif|png|jpeg|svg\+xml)$/):file.name.match(/\.(gif|png|jpe?g|svg)$/i))&&typeof FileReader!=="undefined"){var Fileinput=this;var reader=new FileReader();var preview=this.$preview;var element=this.$element;reader.onload=function(re){var $img=$("<img>");$img[0].src=re.target.result;files[0].result=re.target.result;element.find(".fileinput-filename").text(file.name);if(preview.css("max-height")!="none"){var mh=parseInt(preview.css("max-height"),10)||0;var pt=parseInt(preview.css("padding-top"),10)||0;var pb=parseInt(preview.css("padding-bottom"),10)||0;var bt=parseInt(preview.css("border-top"),10)||0;var bb=parseInt(preview.css("border-bottom"),10)||0;$img.css("max-height",mh-pt-pb-bt-bb)}preview.html($img);if(Fileinput.options.exif){Fileinput.setImageTransform($img,file)}element.addClass("fileinput-exists").removeClass("fileinput-new");element.trigger("change.bs.fileinput",files)};reader.readAsDataURL(file)}else{var text=file.name;var $nameView=this.$element.find(".fileinput-filename");if(files.length>1){text=$.map(files,function(file){return file.name}).join(", ")}$nameView.text(text);this.$preview.text(file.name);this.$element.addClass("fileinput-exists").removeClass("fileinput-new");this.$element.trigger("change.bs.fileinput")}},Fileinput.prototype.setImageTransform=function($img,file){var Fileinput=this;var reader=new FileReader();reader.onload=function(me){var transform=false;var view=new DataView(reader.result);var exif=Fileinput.getImageExif(view);if(exif){Fileinput.resetOrientation($img,exif)}};reader.readAsArrayBuffer(file)};Fileinput.prototype.getImageExif=function(view){if(view.getUint16(0,false)!=65496){return -2}var length=view.byteLength,offset=2;while(offset<length){var marker=view.getUint16(offset,false);offset+=2;if(marker==65505){if(view.getUint32(offset+=2,false)!=1165519206){return -1}var little=view.getUint16(offset+=6,false)==18761;offset+=view.getUint32(offset+4,little);var tags=view.getUint16(offset,little);offset+=2;for(var i=0;i<tags;i++){if(view.getUint16(offset+(i*12),little)==274){return view.getUint16(offset+(i*12)+8,little)}}}else{if((marker&65280)!=65280){break}else{offset+=view.getUint16(offset,false)}}}return -1};Fileinput.prototype.resetOrientation=function($img,transform){var img=new Image();img.onload=function(){var width=img.width,height=img.height,canvas=document.createElement("canvas"),ctx=canvas.getContext("2d");if([5,6,7,8].indexOf(transform)>-1){canvas.width=height;canvas.height=width}else{canvas.width=width;canvas.height=height}switch(transform){case 2:ctx.transform(-1,0,0,1,width,0);break;case 3:ctx.transform(-1,0,0,-1,width,height);break;case 4:ctx.transform(1,0,0,-1,0,height);break;case 5:ctx.transform(0,1,1,0,0,0);break;case 6:ctx.transform(0,1,-1,0,height,0);break;case 7:ctx.transform(0,-1,-1,0,height,width);break;case 8:ctx.transform(0,-1,1,0,0,width);break;default:ctx.transform(1,0,0,1,0,0)}ctx.drawImage(img,0,0);$img.attr("src",canvas.toDataURL())};img.src=$img.attr("src")};Fileinput.prototype.clear=function(e){if(e){e.preventDefault()}this.$hidden.val("");this.$hidden.attr("name",this.name);if(this.options.clearName){this.$input.attr("name","")}if(isIE){var inputClone=this.$input.clone(true);this.$input.after(inputClone);this.$input.remove();this.$input=inputClone}else{this.$input.val("")}this.$preview.html("");this.$element.find(".fileinput-filename").text("");this.$element.addClass("fileinput-new").removeClass("fileinput-exists");if(e!==undefined){this.$input.trigger("change");this.$element.trigger("clear.bs.fileinput")}},Fileinput.prototype.reset=function(){this.clear();this.$hidden.val(this.original.hiddenVal);this.$preview.html(this.original.preview);this.$element.find(".fileinput-filename").text("");if(this.original.exists){this.$element.addClass("fileinput-exists").removeClass("fileinput-new")}else{this.$element.addClass("fileinput-new").removeClass("fileinput-exists")}this.$element.trigger("reseted.bs.fileinput")},Fileinput.prototype.trigger=function(e){this.$input.trigger("click");e.preventDefault()};var old=$.fn.fileinput;$.fn.fileinput=function(options){return this.each(function(){var $this=$(this),data=$this.data("bs.fileinput");if(!data){$this.data("bs.fileinput",(data=new Fileinput(this,options)))}if(typeof options=="string"){data[options]()}})};$.fn.fileinput.Constructor=Fileinput;$.fn.fileinput.noConflict=function(){$.fn.fileinput=old;return this};$(document).on("click.fileinput.data-api",'[data-provides="fileinput"]',function(e){var $this=$(this);if($this.data("bs.fileinput")){return}$this.fileinput($this.data());var $target=$(e.target).closest('[data-dismiss="fileinput"],[data-trigger="fileinput"]');if($target.length>0){e.preventDefault();$target.trigger("click.bs.fileinput")}})}(window.jQuery);
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-layout/jquery.layout-latest.css b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-layout/jquery.layout-latest.css
new file mode 100644
index 0000000..987ccc7
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-layout/jquery.layout-latest.css
@@ -0,0 +1 @@
+.ui-draggable-handle{-ms-touch-action:none;touch-action:none}.ui-layout-pane{overflow:auto}.ui-layout-content{padding:10px;position:relative;overflow:auto;width:100%;border:0}.layout-child-container,.layout-content-container{padding:0;overflow:hidden}.layout-child-container{border:0}.layout-scroll{overflow:auto}.layout-hide{display:none}.ui-layout-resizer{background:#fafafa;border:1px solid #eee;border-width:0}.ui-layout-resizer-open-hover,.ui-layout-resizer-dragging{background:#fafafa}.ui-layout-resizer-dragging{border:1px solid #eee}.ui-layout-resizer-north-dragging,.ui-layout-resizer-south-dragging{border-width:1px 0}.ui-layout-resizer-west-dragging,.ui-layout-resizer-east-dragging{border-width:0 1px}.ui-layout-resizer-dragging-limit{background:#e1a4a4}.ui-layout-resizer-closed-hover{background:#ebd5aa}.ui-layout-resizer-north-sliding-hover{border-bottom-width:1px}.ui-layout-resizer-south-sliding-hover{border-top-width:1px}.ui-layout-resizer-west-sliding-hover{border-right-width:1px}.ui-layout-resizer-east-sliding-hover{border-left-width:1px}.ui-layout-toggler{border:1px solid #eee;background-color:#eee}.ui-layout-resizer-hover .ui-layout-toggler{opacity:1.00;filter:alpha(opacity=100)}.ui-layout-toggler-hover,.ui-layout-resizer-hover .ui-layout-toggler-hover{background-color:#FC6;opacity:1.00;filter:alpha(opacity=100)}.ui-layout-toggler-north,.ui-layout-toggler-south{border-width:0 1px}.ui-layout-toggler-west,.ui-layout-toggler-east{border-width:1px 0}.ui-layout-resizer-sliding .ui-layout-toggler{display:none}.ui-layout-toggler .ui-content{color:#666;font-size:12px;font-weight:bold;line-height:8px;width:100%;padding-bottom:.35ex}.ui-layout-toggler .ui-content .fa{line-height:8px}.ui-layout-toggler-north-closed .fa:before,.ui-layout-toggler-south-open .fa:before{content:"\f0d7"}.ui-layout-toggler-south-closed .fa:before,.ui-layout-toggler-north-open .fa:before{content:"\f0d8"}.ui-layout-toggler-west-closed .fa:before,.ui-layout-toggler-east-open .fa:before{content:"\f0da"}.ui-layout-toggler-east-closed .fa:before,.ui-layout-toggler-west-open .fa:before{content:"\f0d9"}.ui-layout-mask{border:none!important;padding:0!important;margin:0!important;overflow:hidden!important;position:absolute!important;opacity:0!important;filter:Alpha(Opacity="0")!important}.ui-layout-mask-inside-pane{top:0!important;left:0!important;width:100%!important;height:100%!important}@media print{html{height:auto!important;overflow:visible!important}body.ui-layout-container{position:static!important;top:auto!important;bottom:auto!important;left:auto!important;right:auto!important;_width:auto!important;_height:auto!important}.ui-layout-resizer,.ui-layout-toggler{display:none!important}.ui-layout-pane{border:none!important;background:transparent!important;position:relative!important;top:auto!important;bottom:auto!important;left:auto!important;right:auto!important;width:auto!important;height:auto!important;overflow:visible!important}}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-layout/jquery.layout-latest.js b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-layout/jquery.layout-latest.js
new file mode 100644
index 0000000..a9f335d
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-layout/jquery.layout-latest.js
@@ -0,0 +1,2 @@
+(function($){var min=Math.min,max=Math.max,round=Math.floor,isStr=function(v){return $.type(v)==="string"},runPluginCallbacks=function(Instance,a_fn){if($.isArray(a_fn)){for(var i=0,c=a_fn.length;i<c;i++){var fn=a_fn[i];try{if(isStr(fn)){fn=eval(fn)}if($.isFunction(fn)){g(fn)(Instance)}}catch(ex){}}}function g(f){return f}};$.layout={version:"1.4.4",revision:1.0404,browser:{},effects:{slide:{all:{duration:"fast"},north:{direction:"up"},south:{direction:"down"},east:{direction:"right"},west:{direction:"left"}},drop:{all:{duration:"slow"},north:{direction:"up"},south:{direction:"down"},east:{direction:"right"},west:{direction:"left"}},scale:{all:{duration:"fast"}},blind:{},clip:{},explode:{},fade:{},fold:{},puff:{},size:{all:{easing:"swing"}}},config:{optionRootKeys:"effects,panes,north,south,west,east,center".split(","),allPanes:"north,south,west,east,center".split(","),borderPanes:"north,south,west,east".split(","),oppositeEdge:{north:"south",south:"north",east:"west",west:"east"},offscreenCSS:{left:"-99999px",right:"auto"},offscreenReset:"offscreenReset",hidden:{visibility:"hidden"},visible:{visibility:"visible"},resizers:{cssReq:{position:"absolute",padding:0,margin:0,fontSize:"1px",textAlign:"left",overflow:"hidden"},cssDemo:{background:"#DDD",border:"none"}},togglers:{cssReq:{position:"absolute",display:"block",padding:0,margin:0,overflow:"hidden",textAlign:"center",fontSize:"1px",cursor:"pointer",zIndex:1},cssDemo:{background:"#AAA"}},content:{cssReq:{position:"relative"},cssDemo:{overflow:"auto",padding:"10px"},cssDemoPane:{overflow:"hidden",padding:0}},panes:{cssReq:{position:"absolute",margin:0},cssDemo:{padding:"10px",background:"#FFF",border:"1px solid #BBB",overflow:"auto"}},north:{side:"top",sizeType:"Height",dir:"horz",cssReq:{top:0,bottom:"auto",left:0,right:0,width:"auto"}},south:{side:"bottom",sizeType:"Height",dir:"horz",cssReq:{top:"auto",bottom:0,left:0,right:0,width:"auto"}},east:{side:"right",sizeType:"Width",dir:"vert",cssReq:{left:"auto",right:0,top:"auto",bottom:"auto",height:"auto"}},west:{side:"left",sizeType:"Width",dir:"vert",cssReq:{left:0,right:"auto",top:"auto",bottom:"auto",height:"auto"}},center:{dir:"center",cssReq:{left:"auto",right:"auto",top:"auto",bottom:"auto",height:"auto",width:"auto"}}},callbacks:{},getParentPaneElem:function(el){var $el=$(el),layout=$el.data("layout")||$el.data("parentLayout");if(layout){var $cont=layout.container;if($cont.data("layoutPane")){return $cont}var $pane=$cont.closest("."+$.layout.defaults.panes.paneClass);if($pane.data("layoutPane")){return $pane}}return null},getParentPaneInstance:function(el){var $pane=$.layout.getParentPaneElem(el);return $pane?$pane.data("layoutPane"):null},getParentLayoutInstance:function(el){var $pane=$.layout.getParentPaneElem(el);return $pane?$pane.data("parentLayout"):null},getEventObject:function(evt){return typeof evt==="object"&&evt.stopPropagation?evt:null},parsePaneName:function(evt_or_pane){var evt=$.layout.getEventObject(evt_or_pane),pane=evt_or_pane;if(evt){evt.stopPropagation();pane=$(this).data("layoutEdge")}if(pane&&!/^(west|east|north|south|center)$/.test(pane)){$.layout.msg('LAYOUT ERROR - Invalid pane-name: "'+pane+'"');pane="error"}return pane},plugins:{draggable:!!$.fn.draggable,effects:{core:!!$.effects,slide:$.effects&&($.effects.slide||($.effects.effect&&$.effects.effect.slide))}},onCreate:[],onLoad:[],onReady:[],onDestroy:[],onUnload:[],afterOpen:[],afterClose:[],scrollbarWidth:function(){return window.scrollbarWidth||$.layout.getScrollbarSize("width")},scrollbarHeight:function(){return window.scrollbarHeight||$.layout.getScrollbarSize("height")},getScrollbarSize:function(dim){var $c=$('<div style="position: absolute; top: -10000px; left: -10000px; width: 100px; height: 100px; border: 0; overflow: scroll;"></div>').appendTo("body"),d={width:$c.outerWidth-$c[0].clientWidth,height:100-$c[0].clientHeight};$c.remove();window.scrollbarWidth=d.width;window.scrollbarHeight=d.height;return dim.match(/^(width|height)$/)?d[dim]:d},disableTextSelection:function(){var $d=$(document),s="textSelectionDisabled",x="textSelectionInitialized";if($.fn.disableSelection){if(!$d.data(x)){$d.on("mouseup",$.layout.enableTextSelection).data(x,true)}if(!$d.data(s)){$d.disableSelection().data(s,true)}}},enableTextSelection:function(){var $d=$(document),s="textSelectionDisabled";if($.fn.enableSelection&&$d.data(s)){$d.enableSelection().data(s,false)}},showInvisibly:function($E,force){if($E&&$E.length&&(force||$E.css("display")==="none")){var s=$E[0].style,CSS={display:s.display||"",visibility:s.visibility||""};$E.css({display:"block",visibility:"hidden"});return CSS}return{}},getElementDimensions:function($E,inset){var d={css:{},inset:{}},x=d.css,i={bottom:0},N=$.layout.cssNum,R=Math.round,off=$E.offset(),b,p,ei;d.offsetLeft=off.left;d.offsetTop=off.top;if(!inset){inset={}}$.each("Left,Right,Top,Bottom".split(","),function(idx,e){b=x["border"+e]=$.layout.borderWidth($E,e);p=x["padding"+e]=$.layout.cssNum($E,"padding"+e);ei=e.toLowerCase();d.inset[ei]=inset[ei]>=0?inset[ei]:p;i[ei]=d.inset[ei]+b});x.width=R($E.width());x.height=R($E.height());x.top=N($E,"top",true);x.bottom=N($E,"bottom",true);x.left=N($E,"left",true);x.right=N($E,"right",true);d.outerWidth=R($E.outerWidth());d.outerHeight=R($E.outerHeight());d.innerWidth=max(0,d.outerWidth-i.left-i.right);d.innerHeight=max(0,d.outerHeight-i.top-i.bottom);d.layoutWidth=R($E.innerWidth());d.layoutHeight=R($E.innerHeight());return d},getElementStyles:function($E,list){var CSS={},style=$E[0].style,props=list.split(","),sides="Top,Bottom,Left,Right".split(","),attrs="Color,Style,Width".split(","),p,s,a,i,j,k;for(i=0;i<props.length;i++){p=props[i];if(p.match(/(border|padding|margin)$/)){for(j=0;j<4;j++){s=sides[j];if(p==="border"){for(k=0;k<3;k++){a=attrs[k];CSS[p+s+a]=style[p+s+a]}}else{CSS[p+s]=style[p+s]}}}else{CSS[p]=style[p]}}return CSS},cssWidth:function($E,outerWidth){if(outerWidth<=0){return 0}var lb=$.layout.browser,bs=!lb.boxModel?"border-box":lb.boxSizing?$E.css("boxSizing"):"content-box",b=$.layout.borderWidth,n=$.layout.cssNum,W=outerWidth;if(bs!=="border-box"){W-=(b($E,"Left")+b($E,"Right"))}if(bs==="content-box"){W-=(n($E,"paddingLeft")+n($E,"paddingRight"))}return max(0,W)},cssHeight:function($E,outerHeight){if(outerHeight<=0){return 0}var lb=$.layout.browser,bs=!lb.boxModel?"border-box":lb.boxSizing?$E.css("boxSizing"):"content-box",b=$.layout.borderWidth,n=$.layout.cssNum,H=outerHeight;if(bs!=="border-box"){H-=(b($E,"Top")+b($E,"Bottom"))}if(bs==="content-box"){H-=(n($E,"paddingTop")+n($E,"paddingBottom"))}return max(0,H)},cssNum:function($E,prop,allowAuto){if(!$E.jquery){$E=$($E)}var CSS=$.layout.showInvisibly($E),p=$.css($E[0],prop,true),v=allowAuto&&p=="auto"?p:Math.round(parseFloat(p)||0);$E.css(CSS);return v},borderWidth:function(el,side){if(el.jquery){el=el[0]}var b="border"+side.substr(0,1).toUpperCase()+side.substr(1);return $.css(el,b+"Style",true)==="none"?0:Math.round(parseFloat($.css(el,b+"Width",true))||0)},isMouseOverElem:function(evt,el){var $E=$(el||this),d=$E.offset(),T=d.top,L=d.left,R=L+$E.outerWidth(),B=T+$E.outerHeight(),x=evt.pageX,y=evt.pageY;return($.layout.browser.msie&&x<0&&y<0)||((x>=L&&x<=R)&&(y>=T&&y<=B))},msg:function(info,popup,debugTitle,debugOpts){if($.isPlainObject(info)&&window.debugData){if(typeof popup==="string"){debugOpts=debugTitle;debugTitle=popup}else{if(typeof debugTitle==="object"){debugOpts=debugTitle;debugTitle=null}}var t=debugTitle||"log( <object> )",o=$.extend({sort:false,returnHTML:false,display:false},debugOpts);if(popup===true||o.display){debugData(info,t,o)}else{if(window.console){console.log(debugData(info,t,o))}}}else{if(popup){alert(info)}else{if(window.console){console.log(info)}else{var id="#layoutLogger",$l=$(id);if(!$l.length){$l=createLog()}$l.children("ul").append('<li style="padding: 4px 10px; margin: 0; border-top: 1px solid #CCC;">'+info.replace(/\</g,"&lt;").replace(/\>/g,"&gt;")+"</li>")}}}function createLog(){var pos=$.support.fixedPosition?"fixed":"absolute",$e=$('<div id="layoutLogger" style="position: '+pos+'; top: 5px; z-index: 999999; max-width: 25%; overflow: hidden; border: 1px solid #000; border-radius: 5px; background: #FBFBFB; box-shadow: 0 2px 10px rgba(0,0,0,0.3);">'+'<div style="font-size: 13px; font-weight: bold; padding: 5px 10px; background: #F6F6F6; border-radius: 5px 5px 0 0; cursor: move;">'+'<span style="float: right; padding-left: 7px; cursor: pointer;" title="Remove Console" onclick="$(this).closest(\'#layoutLogger\').remove()">X</span>Layout console.log</div>'+'<ul style="font-size: 13px; font-weight: none; list-style: none; margin: 0; padding: 0 0 2px;"></ul>'+"</div>").appendTo("body");$e.css("left",$(window).width()-$e.outerWidth()-5);if($.ui.draggable){$e.draggable({handle:":first-child"})}return $e}}};(function(){var u=navigator.userAgent.toLowerCase(),m=/(chrome)[ \/]([\w.]+)/.exec(u)||/(webkit)[ \/]([\w.]+)/.exec(u)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(u)||/(msie) ([\w.]+)/.exec(u)||u.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(u)||[],b=m[1]||"",v=m[2]||0,ie=b==="msie",cm=document.compatMode,$s=$.support,bs=$s.boxSizing!==undefined?$s.boxSizing:$s.boxSizingReliable,bm=!ie||!cm||cm==="CSS1Compat"||$s.boxModel||false,lb=$.layout.browser={version:v,safari:b==="webkit",webkit:b==="chrome",msie:ie,isIE6:ie&&v==6,boxModel:bm,boxSizing:!!(typeof bs==="function"?bs():bs)};if(b){lb[b]=true}if(!bm&&!cm){$(function(){lb.boxModel=$s.boxModel})}})();$.layout.defaults={name:"",containerClass:"ui-layout-container",inset:null,scrollToBookmarkOnLoad:true,resizeWithWindow:true,resizeWithWindowDelay:50,resizeWithWindowMaxDelay:0,maskPanesEarly:false,onresizeall_start:null,onresizeall_end:null,onload_start:null,onload_end:null,onunload_start:null,onunload_end:null,initPanes:true,showErrorMessages:true,showDebugMessages:false,zIndex:null,zIndexes:{pane_normal:0,content_mask:1,resizer_normal:2,pane_sliding:100,pane_animate:1000,resizer_drag:10000},errors:{pane:"pane",selector:"selector",addButtonError:"Error Adding Button\nInvalid ",containerMissing:"UI Layout Initialization Error\nThe specified layout-container does not exist.",centerPaneMissing:"UI Layout Initialization Error\nThe center-pane element does not exist.\nThe center-pane is a required element.",noContainerHeight:"UI Layout Initialization Warning\nThe layout-container \"CONTAINER\" has no height.\nTherefore the layout is 0-height and hence 'invisible'!",callbackError:"UI Layout Callback Error\nThe EVENT callback is not a valid function."},panes:{applyDemoStyles:false,closable:true,resizable:true,slidable:true,initClosed:false,initHidden:false,contentSelector:".ui-layout-content",contentIgnoreSelector:".ui-layout-ignore",findNestedContent:true,paneClass:"ui-layout-pane",resizerClass:"ui-layout-resizer",togglerClass:"ui-layout-toggler",buttonClass:"ui-layout-button",minSize:0,maxSize:0,spacing_open:8,spacing_closed:8,togglerLength_open:50,togglerLength_closed:50,togglerAlign_open:"center",togglerAlign_closed:"center",togglerContent_open:'<i class="fa"></i>',togglerContent_closed:'<i class="fa"></i>',resizerDblClickToggle:true,autoResize:true,autoReopen:true,resizerDragOpacity:1,maskContents:false,maskObjects:false,maskZindex:null,resizingGrid:false,livePaneResizing:false,liveContentResizing:false,liveResizingTolerance:1,sliderCursor:"pointer",slideTrigger_open:"mouseenter",slideTrigger_close:"mouseleave",slideDelay_open:100,slideDelay_close:500,hideTogglerOnSlide:false,preventQuickSlideClose:$.layout.browser.webkit,preventPrematureSlideClose:false,tips:{Open:"展开",Close:"折叠",Resize:"调整大小/双击折叠",Slide:"鼠标停留自动展开",Pin:"Pin",Unpin:"Un-Pin",noRoomToOpen:"Not enough room to show this panel.",minSizeWarning:"Panel has reached its minimum size",maxSizeWarning:"Panel has reached its maximum size"},showOverflowOnHover:false,enableCursorHotkey:true,customHotkeyModifier:"SHIFT",fxName:"slide",fxSpeed:null,fxSettings:{},fxOpacityFix:true,animatePaneSizing:false,children:null,containerSelector:"",initChildren:true,destroyChildren:true,resizeChildren:true,triggerEventsOnLoad:false,triggerEventsDuringLiveResize:true,onshow_start:null,onshow_end:null,onhide_start:null,onhide_end:null,onopen_start:null,onopen_end:null,onclose_start:null,onclose_end:null,onresize_start:null,onresize_end:null,onsizecontent_start:null,onsizecontent_end:null,onswap_start:null,onswap_end:null,ondrag_start:null,ondrag_end:null},north:{paneSelector:".ui-layout-north",size:"auto",resizerCursor:"n-resize",customHotkey:""},south:{paneSelector:".ui-layout-south",size:"auto",resizerCursor:"s-resize",customHotkey:""},east:{paneSelector:".ui-layout-east",size:200,resizerCursor:"e-resize",customHotkey:""},west:{paneSelector:".ui-layout-west",size:200,resizerCursor:"w-resize",customHotkey:""},center:{paneSelector:".ui-layout-center",minWidth:0,minHeight:0}};$.layout.optionsMap={layout:("name,instanceKey,stateManagement,effects,inset,zIndexes,errors,"+"zIndex,scrollToBookmarkOnLoad,showErrorMessages,maskPanesEarly,"+"outset,resizeWithWindow,resizeWithWindowDelay,resizeWithWindowMaxDelay,"+"onresizeall,onresizeall_start,onresizeall_end,onload,onload_start,onload_end,onunload,onunload_start,onunload_end").split(","),center:("paneClass,contentSelector,contentIgnoreSelector,findNestedContent,applyDemoStyles,triggerEventsOnLoad,"+"showOverflowOnHover,maskContents,maskObjects,liveContentResizing,"+"containerSelector,children,initChildren,resizeChildren,destroyChildren,"+"onresize,onresize_start,onresize_end,onsizecontent,onsizecontent_start,onsizecontent_end").split(","),noDefault:("paneSelector,resizerCursor,customHotkey").split(",")};$.layout.transformData=function(hash,addKeys){var json=addKeys?{panes:{},center:{}}:{},branch,optKey,keys,key,val,i,c;if(typeof hash!=="object"){return json}for(optKey in hash){branch=json;val=hash[optKey];keys=optKey.split("__");c=keys.length-1;for(i=0;i<=c;i++){key=keys[i];if(i===c){if($.isPlainObject(val)){branch[key]=$.layout.transformData(val)}else{branch[key]=val}}else{if(!branch[key]){branch[key]={}}branch=branch[key]}}}return json};$.layout.backwardCompatibility={map:{applyDefaultStyles:"applyDemoStyles",childOptions:"children",initChildLayout:"initChildren",destroyChildLayout:"destroyChildren",resizeChildLayout:"resizeChildren",resizeNestedLayout:"resizeChildren",resizeWhileDragging:"livePaneResizing",resizeContentWhileDragging:"liveContentResizing",triggerEventsWhileDragging:"triggerEventsDuringLiveResize",maskIframesOnResize:"maskContents",useStateCookie:"stateManagement.enabled","cookie.autoLoad":"stateManagement.autoLoad","cookie.autoSave":"stateManagement.autoSave","cookie.keys":"stateManagement.stateKeys","cookie.name":"stateManagement.cookie.name","cookie.domain":"stateManagement.cookie.domain","cookie.path":"stateManagement.cookie.path","cookie.expires":"stateManagement.cookie.expires","cookie.secure":"stateManagement.cookie.secure",noRoomToOpenTip:"tips.noRoomToOpen",togglerTip_open:"tips.Close",togglerTip_closed:"tips.Open",resizerTip:"tips.Resize",sliderTip:"tips.Slide"},renameOptions:function(opts){var map=$.layout.backwardCompatibility.map,oldData,newData,value;for(var itemPath in map){oldData=getBranch(itemPath);value=oldData.branch[oldData.key];if(value!==undefined){newData=getBranch(map[itemPath],true);newData.branch[newData.key]=value;delete oldData.branch[oldData.key]}}function getBranch(path,create){var a=path.split("."),c=a.length-1,D={branch:opts,key:a[c]},i=0,k,undef;for(;i<c;i++){k=a[i];if(D.branch[k]==undefined){if(create){D.branch=D.branch[k]={}}else{D.branch={}}}else{D.branch=D.branch[k]}}return D}},renameAllOptions:function(opts){var ren=$.layout.backwardCompatibility.renameOptions;ren(opts);if(opts.defaults){if(typeof opts.panes!=="object"){opts.panes={}}$.extend(true,opts.panes,opts.defaults);delete opts.defaults}if(opts.panes){ren(opts.panes)}$.each($.layout.config.allPanes,function(i,pane){if(opts[pane]){ren(opts[pane])}});return opts}};$.fn.layout=function(opts){var browser=$.layout.browser,_c=$.layout.config,cssW=$.layout.cssWidth,cssH=$.layout.cssHeight,elDims=$.layout.getElementDimensions,styles=$.layout.getElementStyles,evtObj=$.layout.getEventObject,evtPane=$.layout.parsePaneName,options=$.extend(true,{},$.layout.defaults),effects=options.effects=$.extend(true,{},$.layout.effects),state={id:"layout"+$.now(),initialized:false,paneResizing:false,panesSliding:{},container:{innerWidth:0,innerHeight:0,outerWidth:0,outerHeight:0,layoutWidth:0,layoutHeight:0},north:{childIdx:0},south:{childIdx:0},east:{childIdx:0},west:{childIdx:0},center:{childIdx:0}},children={north:null,south:null,east:null,west:null,center:null},timer={data:{},set:function(s,fn,ms){timer.clear(s);timer.data[s]=setTimeout(fn,ms)},clear:function(s){var t=timer.data;if(t[s]){clearTimeout(t[s]);delete t[s]}}},_log=function(msg,popup,debug){var o=options;if((o.showErrorMessages&&!debug)||(debug&&o.showDebugMessages)){$.layout.msg(o.name+" / "+msg,(popup!==false))}return false},_runCallbacks=function(evtName,pane,skipBoundEvents){var hasPane=pane&&isStr(pane),s=hasPane?state[pane]:state,o=hasPane?options[pane]:options,lName=options.name,lng=evtName+(evtName.match(/_/)?"":"_end"),shrt=lng.match(/_end$/)?lng.substr(0,lng.length-4):"",fn=o[lng]||o[shrt],retVal="NC",args=[],$P=hasPane?$Ps[pane]:0;if(hasPane&&!$P){return retVal}if(!hasPane&&$.type(pane)==="boolean"){skipBoundEvents=pane;pane=""}if(fn){try{if(isStr(fn)){if(fn.match(/,/)){args=fn.split(","),fn=eval(args[0])}else{fn=eval(fn)}}if($.isFunction(fn)){if(args.length){retVal=g(fn)(args[1])}else{if(hasPane){retVal=g(fn)(pane,$Ps[pane],s,o,lName)}else{retVal=g(fn)(Instance,s,o,lName)}}}}catch(ex){_log(options.errors.callbackError.replace(/EVENT/,$.trim((pane||"")+" "+lng)),false);if($.type(ex)==="string"&&string.length){_log("Exception:  "+ex,false)}}}if(!skipBoundEvents&&retVal!==false){if(hasPane){o=options[pane];s=state[pane];$P.triggerHandler("layoutpane"+lng,[pane,$P,s,o,lName]);if(shrt){$P.triggerHandler("layoutpane"+shrt,[pane,$P,s,o,lName])}}else{$N.triggerHandler("layout"+lng,[Instance,s,o,lName]);if(shrt){$N.triggerHandler("layout"+shrt,[Instance,s,o,lName])}}}if(hasPane&&evtName==="onresize_end"){resizeChildren(pane+"",true)}return retVal;function g(f){return f}},_fixIframe=function(pane){if(browser.mozilla){return}var $P=$Ps[pane];if(state[pane].tagName==="IFRAME"){$P.css(_c.hidden).css(_c.visible)}else{$P.find("IFRAME").css(_c.hidden).css(_c.visible)}},cssSize=function(pane,outerSize){var fn=_c[pane].dir=="horz"?cssH:cssW;return fn($Ps[pane],outerSize)},cssMinDims=function(pane){var $P=$Ps[pane],dir=_c[pane].dir,d={minWidth:1001-cssW($P,1000),minHeight:1001-cssH($P,1000)};if(dir==="horz"){d.minSize=d.minHeight}if(dir==="vert"){d.minSize=d.minWidth}return d},setOuterWidth=function(el,outerWidth,autoHide){var $E=el,w;if(isStr(el)){$E=$Ps[el]}else{if(!el.jquery){$E=$(el)}}w=cssW($E,outerWidth);$E.css({width:w});if(w>0){if(autoHide&&$E.data("autoHidden")&&$E.innerHeight()>0){$E.show().data("autoHidden",false);if(!browser.mozilla){$E.css(_c.hidden).css(_c.visible)}}}else{if(autoHide&&!$E.data("autoHidden")){$E.hide().data("autoHidden",true)}}},setOuterHeight=function(el,outerHeight,autoHide){var $E=el,h;if(isStr(el)){$E=$Ps[el]}else{if(!el.jquery){$E=$(el)}}h=cssH($E,outerHeight);$E.css({height:h,visibility:"visible"});if(h>0&&$E.innerWidth()>0){if(autoHide&&$E.data("autoHidden")){$E.show().data("autoHidden",false);if(!browser.mozilla){$E.css(_c.hidden).css(_c.visible)}}}else{if(autoHide&&!$E.data("autoHidden")){$E.hide().data("autoHidden",true)}}},_parseSize=function(pane,size,dir){if(!dir){dir=_c[pane].dir}if(isStr(size)&&size.match(/%/)){size=(size==="100%")?-1:parseInt(size,10)/100}if(size===0){return 0}else{if(size>=1){return parseInt(size,10)}}var o=options,avail=0;if(dir=="horz"){avail=sC.innerHeight-($Ps.north?o.north.spacing_open:0)-($Ps.south?o.south.spacing_open:0)}else{if(dir=="vert"){avail=sC.innerWidth-($Ps.west?o.west.spacing_open:0)-($Ps.east?o.east.spacing_open:0)}}if(size===-1){return avail}else{if(size>0){return round(avail*size)}else{if(pane=="center"){return 0}else{var dim=(dir==="horz"?"height":"width"),$P=$Ps[pane],$C=dim==="height"?$Cs[pane]:false,vis=$.layout.showInvisibly($P),szP=$P.css(dim),szC=$C?$C.css(dim):0;$P.css(dim,"auto");if($C){$C.css(dim,"auto")}size=(dim==="height")?$P.outerHeight():$P.outerWidth();$P.css(dim,szP).css(vis);if($C){$C.css(dim,szC)}return size}}}},getPaneSize=function(pane,inclSpace){var $P=$Ps[pane],o=options[pane],s=state[pane],oSp=(inclSpace?o.spacing_open:0),cSp=(inclSpace?o.spacing_closed:0);if(!$P||s.isHidden){return 0}else{if(s.isClosed||(s.isSliding&&inclSpace)){return cSp}else{if(_c[pane].dir==="horz"){return $P.outerHeight()+oSp}else{return $P.outerWidth()+oSp}}}},setSizeLimits=function(pane,slide){if(!isInitialized()){return}var o=options[pane],s=state[pane],c=_c[pane],dir=c.dir,type=c.sizeType.toLowerCase(),isSliding=(slide!=undefined?slide:s.isSliding),$P=$Ps[pane],paneSpacing=o.spacing_open,altPane=_c.oppositeEdge[pane],altS=state[altPane],$altP=$Ps[altPane],altPaneSize=(!$altP||altS.isVisible===false||altS.isSliding?0:(dir=="horz"?$altP.outerHeight():$altP.outerWidth())),altPaneSpacing=((!$altP||altS.isHidden?0:options[altPane][altS.isClosed!==false?"spacing_closed":"spacing_open"])||0),containerSize=(dir=="horz"?sC.innerHeight:sC.innerWidth),minCenterDims=cssMinDims("center"),minCenterSize=dir=="horz"?max(options.center.minHeight,minCenterDims.minHeight):max(options.center.minWidth,minCenterDims.minWidth),limitSize=(containerSize-paneSpacing-(isSliding?0:(_parseSize("center",minCenterSize,dir)+altPaneSize+altPaneSpacing))),minSize=s.minSize=max(_parseSize(pane,o.minSize),cssMinDims(pane).minSize),maxSize=s.maxSize=min((o.maxSize?_parseSize(pane,o.maxSize):100000),limitSize),r=s.resizerPosition={},top=sC.inset.top,left=sC.inset.left,W=sC.innerWidth,H=sC.innerHeight,rW=o.spacing_open;switch(pane){case"north":r.min=top+minSize;r.max=top+maxSize;break;case"west":r.min=left+minSize;r.max=left+maxSize;break;case"south":r.min=top+H-maxSize-rW;r.max=top+H-minSize-rW;break;case"east":r.min=left+W-maxSize-rW;r.max=left+W-minSize-rW;break}},calcNewCenterPaneDims=function(){var d={top:getPaneSize("north",true),bottom:getPaneSize("south",true),left:getPaneSize("west",true),right:getPaneSize("east",true),width:0,height:0};d.width=sC.innerWidth-d.left-d.right;d.height=sC.innerHeight-d.bottom-d.top;d.top+=sC.inset.top;d.bottom+=sC.inset.bottom;d.left+=sC.inset.left;d.right+=sC.inset.right;return d},getHoverClasses=function(el,allStates){var $El=$(el),type=$El.data("layoutRole"),pane=$El.data("layoutEdge"),o=options[pane],root=o[type+"Class"],_pane="-"+pane,_open="-open",_closed="-closed",_slide="-sliding",_hover="-hover ",_state=$El.hasClass(root+_closed)?_closed:_open,_alt=_state===_closed?_open:_closed,classes=(root+_hover)+(root+_pane+_hover)+(root+_state+_hover)+(root+_pane+_state+_hover);if(allStates){classes+=(root+_alt+_hover)+(root+_pane+_alt+_hover)}if(type=="resizer"&&$El.hasClass(root+_slide)){classes+=(root+_slide+_hover)+(root+_pane+_slide+_hover)}return $.trim(classes)},addHover=function(evt,el){var $E=$(el||this);if(evt&&$E.data("layoutRole")==="toggler"){evt.stopPropagation()}$E.addClass(getHoverClasses($E))},removeHover=function(evt,el){var $E=$(el||this);$E.removeClass(getHoverClasses($E,true))},onResizerEnter=function(evt){var pane=$(this).data("layoutEdge"),s=state[pane],$d=$(document);if(s.isResizing||state.paneResizing){return}if(options.maskPanesEarly){showMasks(pane,{resizing:true})}},onResizerLeave=function(evt,el){var e=el||this,pane=$(e).data("layoutEdge"),name=pane+"ResizerLeave",$d=$(document);timer.clear(pane+"_openSlider");timer.clear(name);if(!el){timer.set(name,function(){onResizerLeave(evt,e)},200)}else{if(options.maskPanesEarly&&!state.paneResizing){hideMasks()}}},_create=function(){initOptions();var o=options,s=state;s.creatingLayout=true;runPluginCallbacks(Instance,$.layout.onCreate);if(false===_runCallbacks("onload_start")){return"cancel"}_initContainer();initHotkeys();$(window).bind("unload."+sID,unload);runPluginCallbacks(Instance,$.layout.onLoad);if(o.initPanes){_initLayoutElements()}delete s.creatingLayout;return state.initialized},isInitialized=function(){if(state.initialized||state.creatingLayout){return true}else{return _initLayoutElements()}},_initLayoutElements=function(retry){var o=options;if(!$N.is(":visible")){if(!retry&&browser.webkit&&$N[0].tagName==="BODY"){setTimeout(function(){_initLayoutElements(true)},50)}return false}if(!getPane("center").length){return _log(o.errors.centerPaneMissing)}state.creatingLayout=true;$.extend(sC,elDims($N,o.inset));initPanes();if(o.scrollToBookmarkOnLoad){var l=self.location;if(l.hash){l.replace(l.hash)}}if(Instance.hasParentLayout){o.resizeWithWindow=false}else{if(o.resizeWithWindow){$(window).bind("resize."+sID,windowResize)}}delete state.creatingLayout;state.initialized=true;runPluginCallbacks(Instance,$.layout.onReady);_runCallbacks("onload_end");return true},createChildren=function(evt_or_pane,opts){var pane=evtPane.call(this,evt_or_pane),$P=$Ps[pane];if(!$P){return}var $C=$Cs[pane],s=state[pane],o=options[pane],sm=options.stateManagement||{},cos=opts?(o.children=opts):o.children;if($.isPlainObject(cos)){cos=[cos]}else{if(!cos||!$.isArray(cos)){return}}$.each(cos,function(idx,co){if(!$.isPlainObject(co)){return}var $containers=co.containerSelector?$P.find(co.containerSelector):($C||$P);$containers.each(function(){var $cont=$(this),child=$cont.data("layout");if(!child){setInstanceKey({container:$cont,options:co},s);if(sm.includeChildren&&state.stateData[pane]){var paneChildren=state.stateData[pane].children||{},childState=paneChildren[co.instanceKey],co_sm=co.stateManagement||(co.stateManagement={autoLoad:true});if(co_sm.autoLoad===true&&childState){co_sm.autoSave=false;co_sm.includeChildren=true;co_sm.autoLoad=$.extend(true,{},childState)}}child=$cont.layout(co);if(child){refreshChildren(pane,child)}}})})},setInstanceKey=function(child,parentPaneState){var $c=child.container,o=child.options,sm=o.stateManagement,key=o.instanceKey||$c.data("layoutInstanceKey");if(!key){key=(sm&&sm.cookie?sm.cookie.name:"")||o.name}if(!key){key="layout"+(++parentPaneState.childIdx)}else{key=key.replace(/[^\w-]/gi,"_").replace(/_{2,}/g,"_")}o.instanceKey=key;$c.data("layoutInstanceKey",key);return key},refreshChildren=function(pane,newChild){var $P=$Ps[pane],pC=children[pane],s=state[pane],o;if($.isPlainObject(pC)){$.each(pC,function(key,child){if(child.destroyed){delete pC[key]}});if($.isEmptyObject(pC)){pC=children[pane]=null}}if(!newChild&&!pC){newChild=$P.data("layout")}if(newChild){newChild.hasParentLayout=true;o=newChild.options;setInstanceKey(newChild,s);if(!pC){pC=children[pane]={}}pC[o.instanceKey]=newChild.container.data("layout")}Instance[pane].children=children[pane];if(!newChild){createChildren(pane)}},windowResize=function(){var o=options,delay=Number(o.resizeWithWindowDelay);if(delay<10){delay=100}timer.clear("winResize");timer.set("winResize",function(){timer.clear("winResize");timer.clear("winResizeRepeater");var dims=elDims($N,o.inset);if(dims.innerWidth!==sC.innerWidth||dims.innerHeight!==sC.innerHeight){resizeAll()}},delay);if(!timer.data["winResizeRepeater"]){setWindowResizeRepeater()}},setWindowResizeRepeater=function(){var delay=Number(options.resizeWithWindowMaxDelay);if(delay>0){timer.set("winResizeRepeater",function(){setWindowResizeRepeater();resizeAll()},delay)}},unload=function(){var o=options;_runCallbacks("onunload_start");runPluginCallbacks(Instance,$.layout.onUnload);_runCallbacks("onunload_end")},_initContainer=function(){var N=$N[0],$H=$("html"),tag=sC.tagName=N.tagName,id=sC.id=N.id,cls=sC.className=N.className,o=options,name=o.name,props="position,margin,padding,border",css="layoutCSS",CSS={},hid="hidden",parent=$N.data("parentLayout"),pane=$N.data("layoutEdge"),isChild=parent&&pane,num=$.layout.cssNum,$parent,n;if($N.selector!==undefined){alert($N.selector);sC.selector=$N.selector.split(".slice")[0]}sC.ref=(o.name?o.name+" layout / ":"")+tag+(id?"#"+id:cls?".["+cls+"]":"");sC.isBody=(tag==="BODY");if(!isChild&&!sC.isBody){$parent=$N.closest("."+$.layout.defaults.panes.paneClass);parent=$parent.data("parentLayout");pane=$parent.data("layoutEdge");isChild=parent&&pane}$N.data({layout:Instance,layoutContainer:sID}).addClass(o.containerClass);var layoutMethods={destroy:"",initPanes:"",resizeAll:"resizeAll",resize:"resizeAll"};for(name in layoutMethods){$N.bind("layout"+name.toLowerCase()+"."+sID,Instance[layoutMethods[name]||name])}if(isChild){Instance.hasParentLayout=true;parent.refreshChildren(pane,Instance)}if(!$N.data(css)){if(sC.isBody){$N.data(css,$.extend(styles($N,props),{height:$N.css("height"),overflow:$N.css("overflow"),overflowX:$N.css("overflowX"),overflowY:$N.css("overflowY")}));$H.data(css,$.extend(styles($H,"padding"),{height:"auto",overflow:$H.css("overflow"),overflowX:$H.css("overflowX"),overflowY:$H.css("overflowY")}))}else{$N.data(css,styles($N,props+",top,bottom,left,right,width,height,overflow,overflowX,overflowY"))}}try{CSS={overflow:hid,overflowX:hid,overflowY:hid};$N.css(CSS);if(o.inset&&!$.isPlainObject(o.inset)){n=parseInt(o.inset,10)||0;o.inset={top:n,bottom:n,left:n,right:n}}if(sC.isBody){if(!o.outset){o.outset={top:num($H,"paddingTop"),bottom:num($H,"paddingBottom"),left:num($H,"paddingLeft"),right:num($H,"paddingRight")}}else{if(!$.isPlainObject(o.outset)){n=parseInt(o.outset,10)||0;o.outset={top:n,bottom:n,left:n,right:n}}}$H.css(CSS).css({height:"100%",border:"none",padding:0,margin:0});if(browser.isIE6){$N.css({width:"100%",height:"100%",border:"none",padding:0,margin:0,position:"relative"});if(!o.inset){o.inset=elDims($N).inset}}else{$N.css({width:"auto",height:"auto",margin:0,position:"absolute"});$N.css(o.outset)}$.extend(sC,elDims($N,o.inset))}else{var p=$N.css("position");if(!p||!p.match(/(fixed|absolute|relative)/)){$N.css("position","relative")}if($N.is(":visible")){$.extend(sC,elDims($N,o.inset));if(sC.innerHeight<1){_log(o.errors.noContainerHeight.replace(/CONTAINER/,sC.ref))}}}if(num($N,"minWidth")){$N.parent().css("overflowX","auto")}if(num($N,"minHeight")){$N.parent().css("overflowY","auto")}}catch(ex){}},initHotkeys=function(panes){panes=panes?panes.split(","):_c.borderPanes;$.each(panes,function(i,pane){var o=options[pane];if(o.enableCursorHotkey||o.customHotkey){$(document).bind("keydown."+sID,keyDown);return false}})},initOptions=function(){var data,d,pane,key,val,i,c,o;opts=$.layout.transformData(opts,true);opts=$.layout.backwardCompatibility.renameAllOptions(opts);if(!$.isEmptyObject(opts.panes)){data=$.layout.optionsMap.noDefault;for(i=0,c=data.length;i<c;i++){key=data[i];delete opts.panes[key]}data=$.layout.optionsMap.layout;for(i=0,c=data.length;i<c;i++){key=data[i];delete opts.panes[key]}}data=$.layout.optionsMap.layout;var rootKeys=$.layout.config.optionRootKeys;for(key in opts){val=opts[key];if($.inArray(key,rootKeys)<0&&$.inArray(key,data)<0){if(!opts.panes[key]){opts.panes[key]=$.isPlainObject(val)?$.extend(true,{},val):val}delete opts[key]}}$.extend(true,options,opts);$.each(_c.allPanes,function(i,pane){_c[pane]=$.extend(true,{},_c.panes,_c[pane]);d=options.panes;o=options[pane];if(pane==="center"){data=$.layout.optionsMap.center;for(i=0,c=data.length;i<c;i++){key=data[i];if(!opts.center[key]&&(opts.panes[key]||!o[key])){o[key]=d[key]}}}else{o=options[pane]=$.extend(true,{},d,o);createFxOptions(pane);if(!o.resizerClass){o.resizerClass="ui-layout-resizer"}if(!o.togglerClass){o.togglerClass="ui-layout-toggler"}}if(!o.paneClass){o.paneClass="ui-layout-pane"}});var zo=opts.zIndex,z=options.zIndexes;if(zo>0){z.pane_normal=zo;z.content_mask=max(zo+1,z.content_mask);z.resizer_normal=max(zo+2,z.resizer_normal)}delete options.panes;function createFxOptions(pane){var o=options[pane],d=options.panes;if(!o.fxSettings){o.fxSettings={}}if(!d.fxSettings){d.fxSettings={}}$.each(["_open","_close","_size"],function(i,n){var sName="fxName"+n,sSpeed="fxSpeed"+n,sSettings="fxSettings"+n,fxName=o[sName]=o[sName]||d[sName]||o.fxName||d.fxName||"none",fxExists=$.effects&&($.effects[fxName]||($.effects.effect&&$.effects.effect[fxName]));if(fxName==="none"||!options.effects[fxName]||!fxExists){fxName=o[sName]="none"}var fx=options.effects[fxName]||{},fx_all=fx.all||null,fx_pane=fx[pane]||null;o[sSpeed]=o[sSpeed]||d[sSpeed]||o.fxSpeed||d.fxSpeed||null;o[sSettings]=$.extend(true,{},fx_all,fx_pane,d.fxSettings,o.fxSettings,d[sSettings],o[sSettings])});delete o.fxName;delete o.fxSpeed;delete o.fxSettings}},getPane=function(pane){var sel=options[pane].paneSelector;if(sel.substr(0,1)==="#"){return $N.find(sel).eq(0)}else{var $P=$N.children(sel).eq(0);return $P.length?$P:$N.children("form:first").children(sel).eq(0)}},initPanes=function(evt){evtPane(evt);$.each(_c.allPanes,function(idx,pane){addPane(pane,true)});initHandles();$.each(_c.borderPanes,function(i,pane){if($Ps[pane]&&state[pane].isVisible){setSizeLimits(pane);makePaneFit(pane)}});sizeMidPanes("center");$.each(_c.allPanes,function(idx,pane){afterInitPane(pane)})},addPane=function(pane,force){if(!force&&!isInitialized()){return}var o=options[pane],s=state[pane],c=_c[pane],dir=c.dir,fx=s.fx,spacing=o.spacing_open||0,isCenter=(pane==="center"),CSS={},$P=$Ps[pane],size,minSize,maxSize,child;if($P){removePane(pane,false,true,false)}else{$Cs[pane]=false}$P=$Ps[pane]=getPane(pane);if(!$P.length){$Ps[pane]=false;return}if(!$P.data("layoutCSS")){var props="position,top,left,bottom,right,width,height,overflow,zIndex,display,backgroundColor,padding,margin,border";$P.data("layoutCSS",styles($P,props))}Instance[pane]={name:pane,pane:$Ps[pane],content:$Cs[pane],options:options[pane],state:state[pane],children:children[pane]};$P.data({parentLayout:Instance,layoutPane:Instance[pane],layoutEdge:pane,layoutRole:"pane"}).css(c.cssReq).css("zIndex",options.zIndexes.pane_normal).css(o.applyDemoStyles?c.cssDemo:{}).addClass(o.paneClass+" "+o.paneClass+"-"+pane).bind("mouseenter."+sID,addHover).bind("mouseleave."+sID,removeHover);var paneMethods={hide:"",show:"",toggle:"",close:"",open:"",slideOpen:"",slideClose:"",slideToggle:"",size:"sizePane",sizePane:"sizePane",sizeContent:"",sizeHandles:"",enableClosable:"",disableClosable:"",enableSlideable:"",disableSlideable:"",enableResizable:"",disableResizable:"",swapPanes:"swapPanes",swap:"swapPanes",move:"swapPanes",removePane:"removePane",remove:"removePane",createChildren:"",resizeChildren:"",resizeAll:"resizeAll",resizeLayout:"resizeAll"},name;for(name in paneMethods){$P.bind("layoutpane"+name.toLowerCase()+"."+sID,Instance[paneMethods[name]||name])}initContent(pane,false);if(!isCenter){size=s.size=_parseSize(pane,o.size);minSize=_parseSize(pane,o.minSize)||1;maxSize=_parseSize(pane,o.maxSize)||100000;if(size>0){size=max(min(size,maxSize),minSize)}s.autoResize=o.autoResize;s.isClosed=false;s.isSliding=false;s.isResizing=false;s.isHidden=false;if(!s.pins){s.pins=[]}}s.tagName=$P[0].tagName;s.edge=pane;s.noRoom=false;s.isVisible=true;setPanePosition(pane);if(dir==="horz"){CSS.height=cssH($P,size)}else{if(dir==="vert"){CSS.width=cssW($P,size)}}$P.css(CSS);if(dir!="horz"){sizeMidPanes(pane,true)}if(state.initialized){initHandles(pane);initHotkeys(pane)}if(o.initClosed&&o.closable&&!o.initHidden){close(pane,true,true)}else{if(o.initHidden||o.initClosed){hide(pane)}else{if(!s.noRoom){$P.css("display","block")}}}$P.css("visibility","visible");if(o.showOverflowOnHover){$P.hover(allowOverflow,resetOverflow)}if(state.initialized){afterInitPane(pane)}},afterInitPane=function(pane){var $P=$Ps[pane],s=state[pane],o=options[pane];if(!$P){return}if($P.data("layout")){refreshChildren(pane,$P.data("layout"))}if(s.isVisible){if(state.initialized){resizeAll()}else{sizeContent(pane)}if(o.triggerEventsOnLoad){_runCallbacks("onresize_end",pane)}else{resizeChildren(pane,true)}}if(o.initChildren&&o.children){createChildren(pane)}},setPanePosition=function(panes){panes=panes?panes.split(","):_c.borderPanes;$.each(panes,function(i,pane){var $P=$Ps[pane],$R=$Rs[pane],o=options[pane],s=state[pane],side=_c[pane].side,CSS={};if(!$P){return}switch(pane){case"north":CSS.top=sC.inset.top;CSS.left=sC.inset.left;CSS.right=sC.inset.right;break;case"south":CSS.bottom=sC.inset.bottom;CSS.left=sC.inset.left;CSS.right=sC.inset.right;break;case"west":CSS.left=sC.inset.left;break;case"east":CSS.right=sC.inset.right;break;case"center":}$P.css(CSS);if($R&&s.isClosed){$R.css(side,sC.inset[side])}else{if($R&&!s.isHidden){$R.css(side,sC.inset[side]+getPaneSize(pane))}}})},initHandles=function(panes){panes=panes?panes.split(","):_c.borderPanes;$.each(panes,function(i,pane){var $P=$Ps[pane];$Rs[pane]=false;$Ts[pane]=false;if(!$P){return}var o=options[pane],s=state[pane],c=_c[pane],paneId=o.paneSelector.substr(0,1)==="#"?o.paneSelector.substr(1):"",rClass=o.resizerClass,tClass=o.togglerClass,spacing=(s.isVisible?o.spacing_open:o.spacing_closed),_pane="-"+pane,_state=(s.isVisible?"-open":"-closed"),I=Instance[pane],$R=I.resizer=$Rs[pane]=$("<div></div>"),$T=I.toggler=(o.closable?$Ts[pane]=$("<div></div>"):false);if(!s.isVisible&&o.slidable){$R.attr("title",o.tips.Slide).css("cursor",o.sliderCursor)}$R.attr("id",paneId?paneId+"-resizer":"").data({parentLayout:Instance,layoutPane:Instance[pane],layoutEdge:pane,layoutRole:"resizer"}).css(_c.resizers.cssReq).css("zIndex",options.zIndexes.resizer_normal).css(o.applyDemoStyles?_c.resizers.cssDemo:{}).addClass(rClass+" "+rClass+_pane).hover(addHover,removeHover).hover(onResizerEnter,onResizerLeave).mousedown($.layout.disableTextSelection).mouseup($.layout.enableTextSelection).appendTo($N);if($.fn.disableSelection){$R.disableSelection()}if(o.resizerDblClickToggle){$R.bind("dblclick."+sID,toggle)}if($T){$T.attr("id",paneId?paneId+"-toggler":"").data({parentLayout:Instance,layoutPane:Instance[pane],layoutEdge:pane,layoutRole:"toggler"}).css(_c.togglers.cssReq).css(o.applyDemoStyles?_c.togglers.cssDemo:{}).addClass(tClass+" "+tClass+_pane).hover(addHover,removeHover).bind("mouseenter",onResizerEnter).appendTo($R);if(o.togglerContent_open){$("<span>"+o.togglerContent_open+"</span>").data({layoutEdge:pane,layoutRole:"togglerContent"}).data("layoutRole","togglerContent").data("layoutEdge",pane).addClass("ui-content content-open").css("display","none").appendTo($T)}if(o.togglerContent_closed){$("<span>"+o.togglerContent_closed+"</span>").data({layoutEdge:pane,layoutRole:"togglerContent"}).addClass("ui-content content-closed").css("display","none").appendTo($T)}enableClosable(pane)}initResizable(pane);if(s.isVisible){setAsOpen(pane)}else{setAsClosed(pane);bindStartSlidingEvents(pane,true)}});sizeHandles()},initContent=function(pane,resize){if(!isInitialized()){return}var o=options[pane],sel=o.contentSelector,I=Instance[pane],$P=$Ps[pane],$C;if(sel){$C=I.content=$Cs[pane]=(o.findNestedContent)?$P.find(sel).eq(0):$P.children(sel).eq(0)}if($C&&$C.length){$C.data("layoutRole","content");if(!$C.data("layoutCSS")){$C.data("layoutCSS",styles($C,"height"))}$C.css(_c.content.cssReq);if(o.applyDemoStyles){$C.css(_c.content.cssDemo);$P.css(_c.content.cssDemoPane)}if($P.css("overflowX").match(/(scroll|auto)/)){$P.css("overflow","hidden")}state[pane].content={};if(resize!==false){sizeContent(pane)}}else{I.content=$Cs[pane]=false}},initResizable=function(panes){var draggingAvailable=$.layout.plugins.draggable,side;panes=panes?panes.split(","):_c.borderPanes;$.each(panes,function(idx,pane){var o=options[pane];if(!draggingAvailable||!$Ps[pane]||!o.resizable){o.resizable=false;return true}var s=state[pane],z=options.zIndexes,c=_c[pane],side=c.dir=="horz"?"top":"left",$P=$Ps[pane],$R=$Rs[pane],base=o.resizerClass,lastPos=0,r,live,resizerClass=base+"-drag",resizerPaneClass=base+"-"+pane+"-drag",helperClass=base+"-dragging",helperPaneClass=base+"-"+pane+"-dragging",helperLimitClass=base+"-dragging-limit",helperPaneLimitClass=base+"-"+pane+"-dragging-limit",helperClassesSet=false;if(!s.isClosed){$R.attr("title",o.tips.Resize).css("cursor",o.resizerCursor)}$R.draggable({containment:$N[0],axis:(c.dir=="horz"?"y":"x"),delay:0,distance:1,grid:o.resizingGrid,helper:"clone",opacity:o.resizerDragOpacity,addClasses:false,zIndex:z.resizer_drag,iframeFix:true,start:function(e,ui){o=options[pane];s=state[pane];live=o.livePaneResizing;if(false===_runCallbacks("ondrag_start",pane)){return false}s.isResizing=true;state.paneResizing=pane;timer.clear(pane+"_closeSlider");setSizeLimits(pane);r=s.resizerPosition;lastPos=ui.position[side];$R.addClass(resizerClass+" "+resizerPaneClass);helperClassesSet=false;showMasks(pane,{resizing:true})},drag:function(e,ui){if(!helperClassesSet){ui.helper.addClass(helperClass+" "+helperPaneClass).css({right:"auto",bottom:"auto"}).children().css("visibility","hidden");helperClassesSet=true;if(s.isSliding){$Ps[pane].css("zIndex",z.pane_sliding)}}var limit=0;if(ui.position[side]<r.min){ui.position[side]=r.min;limit=-1}else{if(ui.position[side]>r.max){ui.position[side]=r.max;limit=1}}if(limit){ui.helper.addClass(helperLimitClass+" "+helperPaneLimitClass);window.defaultStatus=(limit>0&&pane.match(/(north|west)/))||(limit<0&&pane.match(/(south|east)/))?o.tips.maxSizeWarning:o.tips.minSizeWarning}else{ui.helper.removeClass(helperLimitClass+" "+helperPaneLimitClass);window.defaultStatus=""}if(live&&Math.abs(ui.position[side]-lastPos)>=o.liveResizingTolerance){lastPos=ui.position[side];resizePanes(e,ui,pane)}},stop:function(e,ui){$("body").enableSelection();window.defaultStatus="";$R.removeClass(resizerClass+" "+resizerPaneClass);s.isResizing=false;state.paneResizing=false;resizePanes(e,ui,pane,true)}})});var resizePanes=function(evt,ui,pane,resizingDone){var dragPos=ui.position,c=_c[pane],o=options[pane],s=state[pane],resizerPos;switch(pane){case"north":resizerPos=dragPos.top;break;case"west":resizerPos=dragPos.left;break;case"south":resizerPos=sC.layoutHeight-dragPos.top-o.spacing_open;break;case"east":resizerPos=sC.layoutWidth-dragPos.left-o.spacing_open;break}var newSize=resizerPos-sC.inset[c.side];if(!resizingDone){if(Math.abs(newSize-s.size)<o.liveResizingTolerance){return}manualSizePane(pane,newSize,false,true);sizeMasks()}else{if(false!==_runCallbacks("ondrag_end",pane)){manualSizePane(pane,newSize,false,true)}hideMasks(true);if(s.isSliding){showMasks(pane,{resizing:true})}}}},sizeMask=function(){var $M=$(this),pane=$M.data("layoutMask"),s=state[pane];if(s.tagName=="IFRAME"&&s.isVisible){$M.css({top:s.offsetTop,left:s.offsetLeft,width:s.outerWidth,height:s.outerHeight})}},sizeMasks=function(){$Ms.each(sizeMask)},showMasks=function(pane,args){var c=_c[pane],panes=["center"],z=options.zIndexes,a=$.extend({objectsOnly:false,animation:false,resizing:true,sliding:state[pane].isSliding},args),o,s;if(a.resizing){panes.push(pane)}if(a.sliding){panes.push(_c.oppositeEdge[pane])}if(c.dir==="horz"){panes.push("west");panes.push("east")}$.each(panes,function(i,p){s=state[p];o=options[p];if(s.isVisible&&(o.maskObjects||(!a.objectsOnly&&o.maskContents))){getMasks(p).each(function(){sizeMask.call(this);this.style.zIndex=s.isSliding?z.pane_sliding+1:z.pane_normal+1;this.style.display="block"})}})},hideMasks=function(force){if(force||!state.paneResizing){$Ms.hide()}else{if(!force&&!$.isEmptyObject(state.panesSliding)){var i=$Ms.length-1,p,$M;for(;i>=0;i--){$M=$Ms.eq(i);p=$M.data("layoutMask");if(!options[p].maskObjects){$M.hide()}}}}},getMasks=function(pane){var $Masks=$([]),$M,i=0,c=$Ms.length;for(;i<c;i++){$M=$Ms.eq(i);if($M.data("layoutMask")===pane){$Masks=$Masks.add($M)}}if($Masks.length){return $Masks}else{return createMasks(pane)}},createMasks=function(pane){var $P=$Ps[pane],s=state[pane],o=options[pane],z=options.zIndexes,isIframe,el,$M,css,i;if(!o.maskContents&&!o.maskObjects){return $([])}for(i=0;i<(o.maskObjects?2:1);i++){isIframe=o.maskObjects&&i==0;el=document.createElement(isIframe?"iframe":"div");$M=$(el).data("layoutMask",pane);el.className="ui-layout-mask ui-layout-mask-"+pane;css=el.style;css.background="#FFF";css.position="absolute";css.display="block";if(isIframe){el.src="about:blank";el.frameborder=0;css.border=0;css.opacity=0;css.filter="Alpha(Opacity='0')"}else{css.opacity=0.001;css.filter="Alpha(Opacity='1')"}if(s.tagName=="IFRAME"){css.zIndex=z.pane_normal+1;$N.append(el)}else{$M.addClass("ui-layout-mask-inside-pane");css.zIndex=o.maskZindex||z.content_mask;css.top=0;css.left=0;css.width="100%";css.height="100%";$P.append(el)}$Ms=$Ms.add(el)}return $Ms},destroy=function(evt_or_destroyChildren,destroyChildren){$(window).unbind("."+sID);$(document).unbind("."+sID);if(typeof evt_or_destroyChildren==="object"){evtPane(evt_or_destroyChildren)}else{destroyChildren=evt_or_destroyChildren}$N.clearQueue().removeData("layout").removeData("layoutContainer").removeClass(options.containerClass).unbind("."+sID);$Ms.remove();$.each(_c.allPanes,function(i,pane){removePane(pane,false,true,destroyChildren)});var css="layoutCSS";if($N.data(css)&&!$N.data("layoutRole")){$N.css($N.data(css)).removeData(css)}if(sC.tagName==="BODY"&&($N=$("html")).data(css)){$N.css($N.data(css)).removeData(css)}runPluginCallbacks(Instance,$.layout.onDestroy);unload();for(var n in Instance){if(!n.match(/^(container|options)$/)){delete Instance[n]}}Instance.destroyed=true;return Instance},removePane=function(evt_or_pane,remove,skipResize,destroyChild){if(!isInitialized()){return}var pane=evtPane.call(this,evt_or_pane),$P=$Ps[pane],$C=$Cs[pane],$R=$Rs[pane],$T=$Ts[pane];if($P&&$.isEmptyObject($P.data())){$P=false}if($C&&$.isEmptyObject($C.data())){$C=false}if($R&&$.isEmptyObject($R.data())){$R=false}if($T&&$.isEmptyObject($T.data())){$T=false}if($P){$P.stop(true,true)}var o=options[pane],s=state[pane],d="layout",css="layoutCSS",pC=children[pane],hasChildren=$.isPlainObject(pC)&&!$.isEmptyObject(pC),destroy=destroyChild!==undefined?destroyChild:o.destroyChildren;if(hasChildren&&destroy){$.each(pC,function(key,child){if(!child.destroyed){child.destroy(true)}if(child.destroyed){delete pC[key]}});if($.isEmptyObject(pC)){pC=children[pane]=null;hasChildren=false}}if($P&&remove&&!hasChildren){$P.remove()}else{if($P&&$P[0]){var root=o.paneClass,pRoot=root+"-"+pane,_open="-open",_sliding="-sliding",_closed="-closed",classes=[root,root+_open,root+_closed,root+_sliding,pRoot,pRoot+_open,pRoot+_closed,pRoot+_sliding];$.merge(classes,getHoverClasses($P,true));$P.removeClass(classes.join(" ")).removeData("parentLayout").removeData("layoutPane").removeData("layoutRole").removeData("layoutEdge").removeData("autoHidden").unbind("."+sID);if(hasChildren&&$C){$C.width($C.width());$.each(pC,function(key,child){child.resizeAll()})}else{if($C){$C.css($C.data(css)).removeData(css).removeData("layoutRole")}}if(!$P.data(d)){$P.css($P.data(css)).removeData(css)}}}if($T){$T.remove()}if($R){$R.remove()}Instance[pane]=$Ps[pane]=$Cs[pane]=$Rs[pane]=$Ts[pane]=false;s={removed:true};if(!skipResize){resizeAll()}},_hidePane=function(pane){var $P=$Ps[pane],o=options[pane],s=$P[0].style;if(o.useOffscreenClose){if(!$P.data(_c.offscreenReset)){$P.data(_c.offscreenReset,{left:s.left,right:s.right})}$P.css(_c.offscreenCSS)}else{$P.hide().removeData(_c.offscreenReset)}},_showPane=function(pane){var $P=$Ps[pane],o=options[pane],off=_c.offscreenCSS,old=$P.data(_c.offscreenReset),s=$P[0].style;$P.show().removeData(_c.offscreenReset);if(o.useOffscreenClose&&old){if(s.left==off.left){s.left=old.left}if(s.right==off.right){s.right=old.right}}},hide=function(evt_or_pane,noAnimation){if(!isInitialized()){return}var pane=evtPane.call(this,evt_or_pane),o=options[pane],s=state[pane],$P=$Ps[pane],$R=$Rs[pane];if(pane==="center"||!$P||s.isHidden){return}if(state.initialized&&false===_runCallbacks("onhide_start",pane)){return}s.isSliding=false;delete state.panesSliding[pane];if($R){$R.hide()}if(!state.initialized||s.isClosed){s.isClosed=true;s.isHidden=true;s.isVisible=false;if(!state.initialized){_hidePane(pane)}sizeMidPanes(_c[pane].dir==="horz"?"":"center");if(state.initialized||o.triggerEventsOnLoad){_runCallbacks("onhide_end",pane)}}else{s.isHiding=true;close(pane,false,noAnimation)}},show=function(evt_or_pane,openPane,noAnimation,noAlert){if(!isInitialized()){return}var pane=evtPane.call(this,evt_or_pane),o=options[pane],s=state[pane],$P=$Ps[pane],$R=$Rs[pane];if(pane==="center"||!$P||!s.isHidden){return}if(false===_runCallbacks("onshow_start",pane)){return}s.isShowing=true;s.isSliding=false;delete state.panesSliding[pane];if(openPane===false){close(pane,true)}else{open(pane,false,noAnimation,noAlert)}},toggle=function(evt_or_pane,slide){if(!isInitialized()){return}var evt=evtObj(evt_or_pane),pane=evtPane.call(this,evt_or_pane),s=state[pane];if(evt){evt.stopImmediatePropagation()}if(s.isHidden){show(pane)}else{if(s.isClosed){open(pane,!!slide)}else{close(pane)}}},_closePane=function(pane,setHandles){var $P=$Ps[pane],s=state[pane];_hidePane(pane);s.isClosed=true;s.isVisible=false;if(setHandles){setAsClosed(pane)}},close=function(evt_or_pane,force,noAnimation,skipCallback){var pane=evtPane.call(this,evt_or_pane);if(pane==="center"){return}if(!state.initialized&&$Ps[pane]){_closePane(pane,true);return}if(!isInitialized()){return}var $P=$Ps[pane],$R=$Rs[pane],$T=$Ts[pane],o=options[pane],s=state[pane],c=_c[pane],doFX,isShowing,isHiding,wasSliding;$N.queue(function(queueNext){if(!$P||(!o.closable&&!s.isShowing&&!s.isHiding)||(!force&&s.isClosed&&!s.isShowing)){return queueNext()}var abort=!s.isShowing&&false===_runCallbacks("onclose_start",pane);isShowing=s.isShowing;isHiding=s.isHiding;wasSliding=s.isSliding;delete s.isShowing;delete s.isHiding;if(abort){return queueNext()}doFX=!noAnimation&&!s.isClosed&&(o.fxName_close!="none");s.isMoving=true;s.isClosed=true;s.isVisible=false;if(isHiding){s.isHidden=true}else{if(isShowing){s.isHidden=false}}if(s.isSliding){bindStopSlidingEvents(pane,false)}else{sizeMidPanes(_c[pane].dir==="horz"?"":"center",false)}setAsClosed(pane);if(doFX){lockPaneForFX(pane,true);$P.hide(o.fxName_close,o.fxSettings_close,o.fxSpeed_close,function(){lockPaneForFX(pane,false);if(s.isClosed){close_2()}queueNext()
+})}else{_hidePane(pane);close_2();queueNext()}});function close_2(){s.isMoving=false;bindStartSlidingEvents(pane,true);var altPane=_c.oppositeEdge[pane];if(state[altPane].noRoom){setSizeLimits(altPane);makePaneFit(altPane)}if(!skipCallback&&(state.initialized||o.triggerEventsOnLoad)){if(!isShowing){_runCallbacks("onclose_end",pane)}if(isShowing){_runCallbacks("onshow_end",pane)}if(isHiding){_runCallbacks("onhide_end",pane)}}}},setAsClosed=function(pane){if(!$Rs[pane]){return}var $P=$Ps[pane],$R=$Rs[pane],$T=$Ts[pane],o=options[pane],s=state[pane],side=_c[pane].side,rClass=o.resizerClass,tClass=o.togglerClass,_pane="-"+pane,_open="-open",_sliding="-sliding",_closed="-closed";$R.css(side,sC.inset[side]).removeClass(rClass+_open+" "+rClass+_pane+_open).removeClass(rClass+_sliding+" "+rClass+_pane+_sliding).addClass(rClass+_closed+" "+rClass+_pane+_closed);if(s.isHidden){$R.hide()}if(o.resizable&&$.layout.plugins.draggable){$R.draggable("disable").removeClass("ui-state-disabled").css("cursor","default").attr("title","")}if($T){$T.removeClass(tClass+_open+" "+tClass+_pane+_open).addClass(tClass+_closed+" "+tClass+_pane+_closed).attr("title",o.tips.Open);$T.children(".content-open").hide();$T.children(".content-closed").css("display","block")}syncPinBtns(pane,false);if(state.initialized){sizeHandles()}},open=function(evt_or_pane,slide,noAnimation,noAlert){if(!isInitialized()){return}var pane=evtPane.call(this,evt_or_pane),$P=$Ps[pane],$R=$Rs[pane],$T=$Ts[pane],o=options[pane],s=state[pane],c=_c[pane],doFX,isShowing;if(pane==="center"){return}$N.queue(function(queueNext){if(!$P||(!o.resizable&&!o.closable&&!s.isShowing)||(s.isVisible&&!s.isSliding)){return queueNext()}if(s.isHidden&&!s.isShowing){queueNext();show(pane,true);return}if(s.autoResize&&s.size!=o.size){sizePane(pane,o.size,true,true,true)}else{setSizeLimits(pane,slide)}var cbReturn=_runCallbacks("onopen_start",pane);if(cbReturn==="abort"){return queueNext()}if(cbReturn!=="NC"){setSizeLimits(pane,slide)}if(s.minSize>s.maxSize){syncPinBtns(pane,false);if(!noAlert&&o.tips.noRoomToOpen){alert(o.tips.noRoomToOpen)}return queueNext()}if(slide){bindStopSlidingEvents(pane,true)}else{if(s.isSliding){bindStopSlidingEvents(pane,false)}else{if(o.slidable){bindStartSlidingEvents(pane,false)}}}s.noRoom=false;makePaneFit(pane);isShowing=s.isShowing;delete s.isShowing;doFX=!noAnimation&&s.isClosed&&(o.fxName_open!="none");s.isMoving=true;s.isVisible=true;s.isClosed=false;if(isShowing){s.isHidden=false}if(doFX){lockPaneForFX(pane,true);$P.show(o.fxName_open,o.fxSettings_open,o.fxSpeed_open,function(){lockPaneForFX(pane,false);if(s.isVisible){open_2()}queueNext()})}else{_showPane(pane);open_2();queueNext()}});function open_2(){s.isMoving=false;_fixIframe(pane);if(!s.isSliding){sizeMidPanes(_c[pane].dir=="vert"?"center":"",false)}setAsOpen(pane)}},setAsOpen=function(pane,skipCallback){var $P=$Ps[pane],$R=$Rs[pane],$T=$Ts[pane],o=options[pane],s=state[pane],side=_c[pane].side,rClass=o.resizerClass,tClass=o.togglerClass,_pane="-"+pane,_open="-open",_closed="-closed",_sliding="-sliding";$R.css(side,sC.inset[side]+getPaneSize(pane)).removeClass(rClass+_closed+" "+rClass+_pane+_closed).addClass(rClass+_open+" "+rClass+_pane+_open);if(s.isSliding){$R.addClass(rClass+_sliding+" "+rClass+_pane+_sliding)}else{$R.removeClass(rClass+_sliding+" "+rClass+_pane+_sliding)}removeHover(0,$R);if(o.resizable&&$.layout.plugins.draggable){$R.draggable("enable").css("cursor",o.resizerCursor).attr("title",o.tips.Resize)}else{if(!s.isSliding){$R.css("cursor","default")}}if($T){$T.removeClass(tClass+_closed+" "+tClass+_pane+_closed).addClass(tClass+_open+" "+tClass+_pane+_open).attr("title",o.tips.Close);removeHover(0,$T);$T.children(".content-closed").hide();$T.children(".content-open").css("display","block")}syncPinBtns(pane,!s.isSliding);$.extend(s,elDims($P));if(state.initialized){sizeHandles();sizeContent(pane,true)}if(!skipCallback&&(state.initialized||o.triggerEventsOnLoad)&&$P.is(":visible")){_runCallbacks("onopen_end",pane);if(s.isShowing){_runCallbacks("onshow_end",pane)}if(state.initialized){_runCallbacks("onresize_end",pane)}}},slideOpen=function(evt_or_pane){if(!isInitialized()){return}var evt=evtObj(evt_or_pane),pane=evtPane.call(this,evt_or_pane),s=state[pane],delay=options[pane].slideDelay_open;if(pane==="center"){return}if(evt){evt.stopImmediatePropagation()}if(s.isClosed&&evt&&evt.type==="mouseenter"&&delay>0){timer.set(pane+"_openSlider",open_NOW,delay)}else{open_NOW()}function open_NOW(){if(!s.isClosed){bindStopSlidingEvents(pane,true)}else{if(!s.isMoving){open(pane,true)}}}},slideClose=function(evt_or_pane){if(!isInitialized()){return}var evt=evtObj(evt_or_pane),pane=evtPane.call(this,evt_or_pane),o=options[pane],s=state[pane],delay=s.isMoving?1000:300;if(pane==="center"){return}if(s.isClosed||s.isResizing){return}else{if(o.slideTrigger_close==="click"){close_NOW()}else{if(o.preventQuickSlideClose&&s.isMoving){return}else{if(o.preventPrematureSlideClose&&evt&&$.layout.isMouseOverElem(evt,$Ps[pane])){return}else{if(evt){timer.set(pane+"_closeSlider",close_NOW,max(o.slideDelay_close,delay))}else{close_NOW()}}}}}function close_NOW(){if(s.isClosed){bindStopSlidingEvents(pane,false)}else{if(!s.isMoving){close(pane)}}}},slideToggle=function(evt_or_pane){var pane=evtPane.call(this,evt_or_pane);toggle(pane,true)},lockPaneForFX=function(pane,doLock){var $P=$Ps[pane],s=state[pane],o=options[pane],z=options.zIndexes;if(doLock){showMasks(pane,{animation:true,objectsOnly:true});$P.css({zIndex:z.pane_animate});if(pane=="south"){$P.css({top:sC.inset.top+sC.innerHeight-$P.outerHeight()})}else{if(pane=="east"){$P.css({left:sC.inset.left+sC.innerWidth-$P.outerWidth()})}}}else{hideMasks();$P.css({zIndex:(s.isSliding?z.pane_sliding:z.pane_normal)});if(pane=="south"){$P.css({top:"auto"})}else{if(pane=="east"&&!$P.css("left").match(/\-99999/)){$P.css({left:"auto"})}}if(browser.msie&&o.fxOpacityFix&&o.fxName_open!="slide"&&$P.css("filter")&&$P.css("opacity")==1){$P[0].style.removeAttribute("filter")}}},bindStartSlidingEvents=function(pane,enable){var o=options[pane],$P=$Ps[pane],$R=$Rs[pane],evtName=o.slideTrigger_open.toLowerCase();if(!$R||(enable&&!o.slidable)){return}if(evtName.match(/mouseover/)){evtName=o.slideTrigger_open="mouseenter"}else{if(!evtName.match(/(click|dblclick|mouseenter)/)){evtName=o.slideTrigger_open="click"}}if(o.resizerDblClickToggle&&evtName.match(/click/)){$R[enable?"unbind":"bind"]("dblclick."+sID,toggle)}$R[enable?"bind":"unbind"](evtName+"."+sID,slideOpen).css("cursor",enable?o.sliderCursor:"default").attr("title",enable?o.tips.Slide:"")},bindStopSlidingEvents=function(pane,enable){var o=options[pane],s=state[pane],c=_c[pane],z=options.zIndexes,evtName=o.slideTrigger_close.toLowerCase(),action=(enable?"bind":"unbind"),$P=$Ps[pane],$R=$Rs[pane];timer.clear(pane+"_closeSlider");if(enable){s.isSliding=true;state.panesSliding[pane]=true;bindStartSlidingEvents(pane,false)}else{s.isSliding=false;delete state.panesSliding[pane]}$P.css("zIndex",enable?z.pane_sliding:z.pane_normal);$R.css("zIndex",enable?z.pane_sliding+2:z.resizer_normal);if(!evtName.match(/(click|mouseleave)/)){evtName=o.slideTrigger_close="mouseleave"}$R[action](evtName,slideClose);if(evtName==="mouseleave"){$P[action]("mouseleave."+sID,slideClose);$R[action]("mouseenter."+sID,cancelMouseOut);$P[action]("mouseenter."+sID,cancelMouseOut)}if(!enable){timer.clear(pane+"_closeSlider")}else{if(evtName==="click"&&!o.resizable){$R.css("cursor",enable?o.sliderCursor:"default");$R.attr("title",enable?o.tips.Close:"")}}function cancelMouseOut(evt){timer.clear(pane+"_closeSlider");evt.stopPropagation()}},makePaneFit=function(pane,isOpening,skipCallback,force){var o=options[pane],s=state[pane],c=_c[pane],$P=$Ps[pane],$R=$Rs[pane],isSidePane=c.dir==="vert",hasRoom=false;if(pane==="center"||(isSidePane&&s.noVerticalRoom)){hasRoom=(s.maxHeight>=0);if(hasRoom&&s.noRoom){_showPane(pane);if($R){$R.show()}s.isVisible=true;s.noRoom=false;if(isSidePane){s.noVerticalRoom=false}_fixIframe(pane)}else{if(!hasRoom&&!s.noRoom){_hidePane(pane);if($R){$R.hide()}s.isVisible=false;s.noRoom=true}}}if(pane==="center"){}else{if(s.minSize<=s.maxSize){hasRoom=true;if(s.size>s.maxSize){sizePane(pane,s.maxSize,skipCallback,true,force)}else{if(s.size<s.minSize){sizePane(pane,s.minSize,skipCallback,true,force)}else{if($R&&s.isVisible&&$P.is(":visible")){var pos=s.size+sC.inset[c.side];if($.layout.cssNum($R,c.side)!=pos){$R.css(c.side,pos)}}}}if(s.noRoom){if(s.wasOpen&&o.closable){if(o.autoReopen){open(pane,false,true,true)}else{s.noRoom=false}}else{show(pane,s.wasOpen,true,true)}}}else{if(!s.noRoom){s.noRoom=true;s.wasOpen=!s.isClosed&&!s.isSliding;if(s.isClosed){}else{if(o.closable){close(pane,true,true)}else{hide(pane,true)}}}}}},manualSizePane=function(evt_or_pane,size,skipCallback,noAnimation,force){if(!isInitialized()){return}var pane=evtPane.call(this,evt_or_pane),o=options[pane],s=state[pane],forceResize=force||(o.livePaneResizing&&!s.isResizing);if(pane==="center"){return}s.autoResize=false;sizePane(pane,size,skipCallback,noAnimation,forceResize)},sizePane=function(evt_or_pane,size,skipCallback,noAnimation,force){if(!isInitialized()){return}var pane=evtPane.call(this,evt_or_pane),o=options[pane],s=state[pane],$P=$Ps[pane],$R=$Rs[pane],side=_c[pane].side,dimName=_c[pane].sizeType.toLowerCase(),skipResizeWhileDragging=s.isResizing&&!o.triggerEventsDuringLiveResize,doFX=noAnimation!==true&&o.animatePaneSizing,oldSize,newSize;if(pane==="center"){return}$N.queue(function(queueNext){setSizeLimits(pane);oldSize=s.size;size=_parseSize(pane,size);size=max(size,_parseSize(pane,o.minSize));size=min(size,s.maxSize);if(size<s.minSize){queueNext();makePaneFit(pane,false,skipCallback);return}if(!force&&size===oldSize){return queueNext()}s.newSize=size;if(!skipCallback&&state.initialized&&s.isVisible){_runCallbacks("onresize_start",pane)}newSize=cssSize(pane,size);if(doFX&&$P.is(":visible")){var fx=$.layout.effects.size[pane]||$.layout.effects.size.all,easing=o.fxSettings_size.easing||fx.easing,z=options.zIndexes,props={};props[dimName]=newSize+"px";s.isMoving=true;$P.css({zIndex:z.pane_animate}).show().animate(props,o.fxSpeed_size,easing,function(){$P.css({zIndex:(s.isSliding?z.pane_sliding:z.pane_normal)});s.isMoving=false;delete s.newSize;sizePane_2();queueNext()})}else{$P.css(dimName,newSize);delete s.newSize;if($P.is(":visible")){sizePane_2()}else{s.size=size}queueNext()}});function sizePane_2(){var actual=dimName==="width"?$P.outerWidth():$P.outerHeight(),tries=[{pane:pane,count:1,target:size,actual:actual,correct:(size===actual),attempt:size,cssSize:newSize}],lastTry=tries[0],thisTry={},msg="Inaccurate size after resizing the "+pane+"-pane.";while(!lastTry.correct){thisTry={pane:pane,count:lastTry.count+1,target:size};if(lastTry.actual>size){thisTry.attempt=max(0,lastTry.attempt-(lastTry.actual-size))}else{thisTry.attempt=max(0,lastTry.attempt+(size-lastTry.actual))}thisTry.cssSize=cssSize(pane,thisTry.attempt);$P.css(dimName,thisTry.cssSize);thisTry.actual=dimName=="width"?$P.outerWidth():$P.outerHeight();thisTry.correct=(size===thisTry.actual);if(tries.length===1){_log(msg,false,true);_log(lastTry,false,true)}_log(thisTry,false,true);if(tries.length>3){break}tries.push(thisTry);lastTry=tries[tries.length-1]}s.size=size;$.extend(s,elDims($P));if(s.isVisible&&$P.is(":visible")){if($R){$R.css(side,size+sC.inset[side])}sizeContent(pane)}if(!skipCallback&&!skipResizeWhileDragging&&state.initialized&&s.isVisible){_runCallbacks("onresize_end",pane)}if(!skipCallback){if(!s.isSliding){sizeMidPanes(_c[pane].dir=="horz"?"":"center",skipResizeWhileDragging,force)}sizeHandles()}var altPane=_c.oppositeEdge[pane];if(size<oldSize&&state[altPane].noRoom){setSizeLimits(altPane);makePaneFit(altPane,false,skipCallback)}if(tries.length>1){_log(msg+"\nSee the Error Console for details.",true,true)}}},sizeMidPanes=function(panes,skipCallback,force){panes=(panes?panes:"east,west,center").split(",");$.each(panes,function(i,pane){if(!$Ps[pane]){return}var o=options[pane],s=state[pane],$P=$Ps[pane],$R=$Rs[pane],isCenter=(pane=="center"),hasRoom=true,CSS={},visCSS=$.layout.showInvisibly($P),newCenter=calcNewCenterPaneDims();$.extend(s,elDims($P));if(pane==="center"){if(!force&&s.isVisible&&newCenter.width===s.outerWidth&&newCenter.height===s.outerHeight){$P.css(visCSS);return true}$.extend(s,cssMinDims(pane),{maxWidth:newCenter.width,maxHeight:newCenter.height});CSS=newCenter;s.newWidth=CSS.width;s.newHeight=CSS.height;CSS.width=cssW($P,CSS.width);CSS.height=cssH($P,CSS.height);hasRoom=CSS.width>=0&&CSS.height>=0;if(!state.initialized&&o.minWidth>newCenter.width){var reqPx=o.minWidth-s.outerWidth,minE=options.east.minSize||0,minW=options.west.minSize||0,sizeE=state.east.size,sizeW=state.west.size,newE=sizeE,newW=sizeW;if(reqPx>0&&state.east.isVisible&&sizeE>minE){newE=max(sizeE-minE,sizeE-reqPx);reqPx-=sizeE-newE}if(reqPx>0&&state.west.isVisible&&sizeW>minW){newW=max(sizeW-minW,sizeW-reqPx);reqPx-=sizeW-newW}if(reqPx===0){if(sizeE&&sizeE!=minE){sizePane("east",newE,true,true,force)}if(sizeW&&sizeW!=minW){sizePane("west",newW,true,true,force)}sizeMidPanes("center",skipCallback,force);$P.css(visCSS);return}}}else{if(s.isVisible&&!s.noVerticalRoom){$.extend(s,elDims($P),cssMinDims(pane))}if(!force&&!s.noVerticalRoom&&newCenter.height===s.outerHeight){$P.css(visCSS);return true}CSS.top=newCenter.top;CSS.bottom=newCenter.bottom;s.newSize=newCenter.height;CSS.height=cssH($P,newCenter.height);s.maxHeight=CSS.height;hasRoom=(s.maxHeight>=0);if(!hasRoom){s.noVerticalRoom=true}}if(hasRoom){if(!skipCallback&&state.initialized){_runCallbacks("onresize_start",pane)}$P.css(CSS);if(pane!=="center"){sizeHandles(pane)}if(s.noRoom&&!s.isClosed&&!s.isHidden){makePaneFit(pane)}if(s.isVisible){$.extend(s,elDims($P));if(state.initialized){sizeContent(pane)}}}else{if(!s.noRoom&&s.isVisible){makePaneFit(pane)}}$P.css(visCSS);delete s.newSize;delete s.newWidth;delete s.newHeight;if(!s.isVisible){return true}if(pane==="center"){var fix=browser.isIE6||!browser.boxModel;if($Ps.north&&(fix||state.north.tagName=="IFRAME")){$Ps.north.css("width",cssW($Ps.north,sC.innerWidth))}if($Ps.south&&(fix||state.south.tagName=="IFRAME")){$Ps.south.css("width",cssW($Ps.south,sC.innerWidth))}}if(!skipCallback&&state.initialized){_runCallbacks("onresize_end",pane)}})},resizeAll=function(evt_or_refresh){var oldW=sC.innerWidth,oldH=sC.innerHeight;evtPane(evt_or_refresh);if(!$N.is(":visible")){return}if(!state.initialized){_initLayoutElements();return}if(evt_or_refresh===true&&$.isPlainObject(options.outset)){$N.css(options.outset)}$.extend(sC,elDims($N,options.inset));if(!sC.outerHeight){return}if(evt_or_refresh===true){setPanePosition()}if(false===_runCallbacks("onresizeall_start")){return false}var shrunkH=(sC.innerHeight<oldH),shrunkW=(sC.innerWidth<oldW),$P,o,s;$.each(["south","north","east","west"],function(i,pane){if(!$Ps[pane]){return}o=options[pane];s=state[pane];if(s.autoResize&&s.size!=o.size){sizePane(pane,o.size,true,true,true)}else{setSizeLimits(pane);makePaneFit(pane,false,true,true)}});sizeMidPanes("",true,true);sizeHandles();$.each(_c.allPanes,function(i,pane){$P=$Ps[pane];if(!$P){return}if(state[pane].isVisible){_runCallbacks("onresize_end",pane)}});_runCallbacks("onresizeall_end")},resizeChildren=function(evt_or_pane,skipRefresh){var pane=evtPane.call(this,evt_or_pane);if(!options[pane].resizeChildren){return}if(!skipRefresh){refreshChildren(pane)}var pC=children[pane];if($.isPlainObject(pC)){$.each(pC,function(key,child){if(!child.destroyed){child.resizeAll()}})}},sizeContent=function(evt_or_panes,remeasure){if(!isInitialized()){return}var panes=evtPane.call(this,evt_or_panes);panes=panes?panes.split(","):_c.allPanes;$.each(panes,function(idx,pane){var $P=$Ps[pane],$C=$Cs[pane],o=options[pane],s=state[pane],m=s.content;if(!$P||!$C||!$P.is(":visible")){return true}if(!$C.length){initContent(pane,false);if(!$C){return}}if(false===_runCallbacks("onsizecontent_start",pane)){return}if((!s.isMoving&&!s.isResizing)||o.liveContentResizing||remeasure||m.top==undefined){_measure();if(m.hiddenFooters>0&&$P.css("overflow")==="hidden"){$P.css("overflow","visible");_measure();$P.css("overflow","hidden")}}var newH=s.innerHeight-(m.spaceAbove-s.css.paddingTop)-(m.spaceBelow-s.css.paddingBottom);if(!$C.is(":visible")||m.height!=newH){setOuterHeight($C,newH,true);m.height=newH}if(state.initialized){_runCallbacks("onsizecontent_end",pane)}function _below($E){return max(s.css.paddingBottom,(parseInt($E.css("marginBottom"),10)||0))}function _measure(){var ignore=options[pane].contentIgnoreSelector,$Fs=$C.nextAll().not(".ui-layout-mask").not(ignore||":lt(0)"),$Fs_vis=$Fs.filter(":visible"),$F=$Fs_vis.filter(":last");m={top:$C[0].offsetTop,height:$C.outerHeight(),numFooters:$Fs.length,hiddenFooters:$Fs.length-$Fs_vis.length,spaceBelow:0};m.spaceAbove=m.top;m.bottom=m.top+m.height;if($F.length){m.spaceBelow=($F[0].offsetTop+$F.outerHeight())-m.bottom+_below($F)}else{m.spaceBelow=_below($C)}}})},sizeHandles=function(evt_or_panes){var panes=evtPane.call(this,evt_or_panes);panes=panes?panes.split(","):_c.borderPanes;$.each(panes,function(i,pane){var o=options[pane],s=state[pane],$P=$Ps[pane],$R=$Rs[pane],$T=$Ts[pane],$TC;if(!$P||!$R){return}var dir=_c[pane].dir,_state=(s.isClosed?"_closed":"_open"),spacing=o["spacing"+_state],togAlign=o["togglerAlign"+_state],togLen=o["togglerLength"+_state],paneLen,left,offset,CSS={};if(spacing===0){$R.hide();return}else{if(!s.noRoom&&!s.isHidden){$R.show()}}if(dir==="horz"){paneLen=sC.innerWidth;s.resizerLength=paneLen;left=$.layout.cssNum($P,"left");$R.css({width:cssW($R,paneLen),height:cssH($R,spacing),left:left>-9999?left:sC.inset.left})}else{paneLen=$P.outerHeight();s.resizerLength=paneLen;$R.css({height:cssH($R,paneLen),width:cssW($R,spacing),top:sC.inset.top+getPaneSize("north",true)})}removeHover(o,$R);if($T){if(togLen===0||(s.isSliding&&o.hideTogglerOnSlide)){$T.hide();return}else{$T.show()}if(!(togLen>0)||togLen==="100%"||togLen>paneLen){togLen=paneLen;offset=0}else{if(isStr(togAlign)){switch(togAlign){case"top":case"left":offset=0;break;case"bottom":case"right":offset=paneLen-togLen;break;case"middle":case"center":default:offset=round((paneLen-togLen)/2)}}else{var x=parseInt(togAlign,10);if(togAlign>=0){offset=x}else{offset=paneLen-togLen+x}}}if(dir==="horz"){var width=cssW($T,togLen);$T.css({width:width,height:cssH($T,spacing),left:offset,top:0})}else{var height=cssH($T,togLen);$T.css({height:height,width:cssW($T,spacing),top:offset,left:0});$T.children(".ui-content").each(function(){$TC=$(this);$TC.css("marginTop",round((height-$TC.outerHeight())/2))})}removeHover(0,$T)}if(!state.initialized&&(o.initHidden||s.isHidden)){$R.hide();if($T){$T.hide()}}})},enableClosable=function(evt_or_pane){if(!isInitialized()){return}var pane=evtPane.call(this,evt_or_pane),$T=$Ts[pane],o=options[pane];if(!$T){return}o.closable=true;$T.bind("click."+sID,function(evt){evt.stopPropagation();toggle(pane)}).css("visibility","visible").css("cursor","pointer").attr("title",state[pane].isClosed?o.tips.Open:o.tips.Close).show()},disableClosable=function(evt_or_pane,hide){if(!isInitialized()){return}var pane=evtPane.call(this,evt_or_pane),$T=$Ts[pane];if(!$T){return}options[pane].closable=false;if(state[pane].isClosed){open(pane,false,true)}$T.unbind("."+sID).css("visibility",hide?"hidden":"visible").css("cursor","default").attr("title","")},enableSlidable=function(evt_or_pane){if(!isInitialized()){return}var pane=evtPane.call(this,evt_or_pane),$R=$Rs[pane];if(!$R||!$R.data("draggable")){return}options[pane].slidable=true;if(state[pane].isClosed){bindStartSlidingEvents(pane,true)}},disableSlidable=function(evt_or_pane){if(!isInitialized()){return}var pane=evtPane.call(this,evt_or_pane),$R=$Rs[pane];if(!$R){return}options[pane].slidable=false;if(state[pane].isSliding){close(pane,false,true)}else{bindStartSlidingEvents(pane,false);$R.css("cursor","default").attr("title","");removeHover(null,$R[0])}},enableResizable=function(evt_or_pane){if(!isInitialized()){return}var pane=evtPane.call(this,evt_or_pane),$R=$Rs[pane],o=options[pane];if(!$R||!$R.data("draggable")){return}o.resizable=true;$R.draggable("enable");if(!state[pane].isClosed){$R.css("cursor",o.resizerCursor).attr("title",o.tips.Resize)}},disableResizable=function(evt_or_pane){if(!isInitialized()){return}var pane=evtPane.call(this,evt_or_pane),$R=$Rs[pane];if(!$R||!$R.data("draggable")){return}options[pane].resizable=false;$R.draggable("disable").css("cursor","default").attr("title","");removeHover(null,$R[0])},swapPanes=function(evt_or_pane1,pane2){if(!isInitialized()){return}var pane1=evtPane.call(this,evt_or_pane1);state[pane1].edge=pane2;state[pane2].edge=pane1;if(false===_runCallbacks("onswap_start",pane1)||false===_runCallbacks("onswap_start",pane2)){state[pane1].edge=pane1;state[pane2].edge=pane2;return}var oPane1=copy(pane1),oPane2=copy(pane2),sizes={};sizes[pane1]=oPane1?oPane1.state.size:0;sizes[pane2]=oPane2?oPane2.state.size:0;$Ps[pane1]=false;$Ps[pane2]=false;state[pane1]={};state[pane2]={};if($Ts[pane1]){$Ts[pane1].remove()}if($Ts[pane2]){$Ts[pane2].remove()}if($Rs[pane1]){$Rs[pane1].remove()}if($Rs[pane2]){$Rs[pane2].remove()}$Rs[pane1]=$Rs[pane2]=$Ts[pane1]=$Ts[pane2]=false;move(oPane1,pane2);move(oPane2,pane1);oPane1=oPane2=sizes=null;if($Ps[pane1]){$Ps[pane1].css(_c.visible)}if($Ps[pane2]){$Ps[pane2].css(_c.visible)}resizeAll();_runCallbacks("onswap_end",pane1);_runCallbacks("onswap_end",pane2);return;function copy(n){var $P=$Ps[n],$C=$Cs[n];return !$P?false:{pane:n,P:$P?$P[0]:false,C:$C?$C[0]:false,state:$.extend(true,{},state[n]),options:$.extend(true,{},options[n])}}function move(oPane,pane){if(!oPane){return}var P=oPane.P,C=oPane.C,oldPane=oPane.pane,c=_c[pane],s=$.extend(true,{},state[pane]),o=options[pane],fx={resizerCursor:o.resizerCursor},re,size,pos;$.each("fxName,fxSpeed,fxSettings".split(","),function(i,k){fx[k+"_open"]=o[k+"_open"];fx[k+"_close"]=o[k+"_close"];fx[k+"_size"]=o[k+"_size"]});$Ps[pane]=$(P).data({layoutPane:Instance[pane],layoutEdge:pane}).css(_c.hidden).css(c.cssReq);$Cs[pane]=C?$(C):false;options[pane]=$.extend(true,{},oPane.options,fx);state[pane]=$.extend(true,{},oPane.state);re=new RegExp(o.paneClass+"-"+oldPane,"g");P.className=P.className.replace(re,o.paneClass+"-"+pane);initHandles(pane);if(c.dir!=_c[oldPane].dir){size=sizes[pane]||0;setSizeLimits(pane);size=max(size,state[pane].minSize);manualSizePane(pane,size,true,true)}else{$Rs[pane].css(c.side,sC.inset[c.side]+(state[pane].isVisible?getPaneSize(pane):0))}if(oPane.state.isVisible&&!s.isVisible){setAsOpen(pane,true)}else{setAsClosed(pane);bindStartSlidingEvents(pane,true)}oPane=null}},syncPinBtns=function(pane,doPin){if($.layout.plugins.buttons){$.each(state[pane].pins,function(i,selector){$.layout.buttons.setPinState(Instance,$(selector),pane,doPin)})}};function keyDown(evt){if(!evt){return true}var code=evt.keyCode;if(code<33){return true}var PANE={38:"north",40:"south",37:"west",39:"east"},ALT=evt.altKey,SHIFT=evt.shiftKey,CTRL=evt.ctrlKey,CURSOR=(CTRL&&code>=37&&code<=40),o,k,m,pane;if(CURSOR&&options[PANE[code]].enableCursorHotkey){pane=PANE[code]}else{if(CTRL||SHIFT){$.each(_c.borderPanes,function(i,p){o=options[p];k=o.customHotkey;m=o.customHotkeyModifier;if((SHIFT&&m=="SHIFT")||(CTRL&&m=="CTRL")||(CTRL&&SHIFT)){if(k&&code===(isNaN(k)||k<=9?k.toUpperCase().charCodeAt(0):k)){pane=p;return false}}})}}if(!pane||!$Ps[pane]||!options[pane].closable||state[pane].isHidden){return true}toggle(pane);evt.stopPropagation();evt.returnValue=false;return false}function allowOverflow(el){if(!isInitialized()){return}if(this&&this.tagName){el=this}var $P;if(isStr(el)){$P=$Ps[el]}else{if($(el).data("layoutRole")){$P=$(el)}else{$(el).parents().each(function(){if($(this).data("layoutRole")){$P=$(this);return false}})}}if(!$P||!$P.length){return}var pane=$P.data("layoutEdge"),s=state[pane];if(s.cssSaved){resetOverflow(pane)}if(s.isSliding||s.isResizing||s.isClosed){s.cssSaved=false;return}var newCSS={zIndex:(options.zIndexes.resizer_normal+1)},curCSS={},of=$P.css("overflow"),ofX=$P.css("overflowX"),ofY=$P.css("overflowY");if(of!="visible"){curCSS.overflow=of;newCSS.overflow="visible"}if(ofX&&!ofX.match(/(visible|auto)/)){curCSS.overflowX=ofX;newCSS.overflowX="visible"}if(ofY&&!ofY.match(/(visible|auto)/)){curCSS.overflowY=ofX;newCSS.overflowY="visible"}s.cssSaved=curCSS;$P.css(newCSS);$.each(_c.allPanes,function(i,p){if(p!=pane){resetOverflow(p)}})}function resetOverflow(el){if(!isInitialized()){return}if(this&&this.tagName){el=this}var $P;if(isStr(el)){$P=$Ps[el]}else{if($(el).data("layoutRole")){$P=$(el)}else{$(el).parents().each(function(){if($(this).data("layoutRole")){$P=$(this);return false}})}}if(!$P||!$P.length){return}var pane=$P.data("layoutEdge"),s=state[pane],CSS=s.cssSaved||{};if(!s.isSliding&&!s.isResizing){$P.css("zIndex",options.zIndexes.pane_normal)}$P.css(CSS);s.cssSaved=false}var $N=$(this).eq(0);if(!$N.length){return _log(options.errors.containerMissing)}if($N.data("layoutContainer")&&$N.data("layout")){return $N.data("layout")}var $Ps={},$Cs={},$Rs={},$Ts={},$Ms=$([]),sC=state.container,sID=state.id;var Instance={options:options,state:state,container:$N,panes:$Ps,contents:$Cs,resizers:$Rs,togglers:$Ts,hide:hide,show:show,toggle:toggle,open:open,close:close,slideOpen:slideOpen,slideClose:slideClose,slideToggle:slideToggle,setSizeLimits:setSizeLimits,_sizePane:sizePane,sizePane:manualSizePane,sizeContent:sizeContent,swapPanes:swapPanes,showMasks:showMasks,hideMasks:hideMasks,initContent:initContent,addPane:addPane,removePane:removePane,createChildren:createChildren,refreshChildren:refreshChildren,enableClosable:enableClosable,disableClosable:disableClosable,enableSlidable:enableSlidable,disableSlidable:disableSlidable,enableResizable:enableResizable,disableResizable:disableResizable,allowOverflow:allowOverflow,resetOverflow:resetOverflow,destroy:destroy,initPanes:isInitialized,resizeAll:resizeAll,runCallbacks:_runCallbacks,hasParentLayout:false,children:children,north:false,south:false,west:false,east:false,center:false};if(_create()==="cancel"){return null}else{return Instance}}})(jQuery);(function($){if(!$.layout){return}if(!$.ui){$.ui={}}$.ui.cookie={acceptsCookies:!!navigator.cookieEnabled,read:function(name){var c=document.cookie,cs=c?c.split(";"):[],pair,data,i;for(i=0;pair=cs[i];i++){data=$.trim(pair).split("=");if(data[0]==name){return decodeURIComponent(data[1])}}return null},write:function(name,val,cookieOpts){var params="",date="",clear=false,o=cookieOpts||{},x=o.expires||null,t=$.type(x);if(t==="date"){date=x}else{if(t==="string"&&x>0){x=parseInt(x,10);t="number"}}if(t==="number"){date=new Date();if(x>0){date.setDate(date.getDate()+x)}else{date.setFullYear(1970);clear=true}}if(date){params+=";expires="+date.toUTCString()}if(o.path){params+=";path="+o.path}if(o.domain){params+=";domain="+o.domain}if(o.secure){params+=";secure"}document.cookie=name+"="+(clear?"":encodeURIComponent(val))+params},clear:function(name){$.ui.cookie.write(name,"",{expires:-1})}};if(!$.cookie){$.cookie=function(k,v,o){var C=$.ui.cookie;if(v===null){C.clear(k)}else{if(v===undefined){return C.read(k)}else{C.write(k,v,o)}}}}$.layout.plugins.stateManagement=true;$.layout.defaults.stateManagement={enabled:false,autoSave:true,autoLoad:true,animateLoad:true,includeChildren:true,stateKeys:"north.size,south.size,east.size,west.size,"+"north.isClosed,south.isClosed,east.isClosed,west.isClosed,"+"north.isHidden,south.isHidden,east.isHidden,west.isHidden",cookie:{name:"",domain:"",path:"",expires:"",secure:false}};$.layout.optionsMap.layout.push("stateManagement");$.layout.config.optionRootKeys.push("stateManagement");$.layout.state={saveCookie:function(inst,keys,cookieOpts){var o=inst.options,sm=o.stateManagement,oC=$.extend(true,{},sm.cookie,cookieOpts||null),data=inst.state.stateData=inst.readState(keys||sm.stateKeys);$.ui.cookie.write(oC.name||o.name||"Layout",$.layout.state.encodeJSON(data),oC);return $.extend(true,{},data)},deleteCookie:function(inst){var o=inst.options;$.ui.cookie.clear(o.stateManagement.cookie.name||o.name||"Layout")},readCookie:function(inst){var o=inst.options;var c=$.ui.cookie.read(o.stateManagement.cookie.name||o.name||"Layout");return c?$.layout.state.decodeJSON(c):{}},loadCookie:function(inst){var c=$.layout.state.readCookie(inst);if(c&&!$.isEmptyObject(c)){inst.state.stateData=$.extend(true,{},c);inst.loadState(c)}return c},loadState:function(inst,data,opts){if(!$.isPlainObject(data)||$.isEmptyObject(data)){return}data=inst.state.stateData=$.layout.transformData(data);var smo=inst.options.stateManagement;opts=$.extend({animateLoad:false,includeChildren:smo.includeChildren},opts);if(!inst.state.initialized){var o=$.extend(true,{},data);$.each($.layout.config.allPanes,function(idx,pane){if(o[pane]){delete o[pane].children}});$.extend(true,inst.options,o)}else{var noAnimate=!opts.animateLoad,o,c,h,state,open;$.each($.layout.config.borderPanes,function(idx,pane){o=data[pane];if(!$.isPlainObject(o)){return}s=o.size;c=o.initClosed;h=o.initHidden;ar=o.autoResize;state=inst.state[pane];open=state.isVisible;if(ar){state.autoResize=ar}if(!open){inst._sizePane(pane,s,false,false,false)}if(h===true){inst.hide(pane,noAnimate)}else{if(c===true){inst.close(pane,false,noAnimate)}else{if(c===false){inst.open(pane,false,noAnimate)}else{if(h===false){inst.show(pane,false,noAnimate)}}}}if(open){inst._sizePane(pane,s,false,false,noAnimate)}});if(opts.includeChildren){var paneStateChildren,childState;$.each(inst.children,function(pane,paneChildren){paneStateChildren=data[pane]?data[pane].children:0;if(paneStateChildren&&paneChildren){$.each(paneChildren,function(stateKey,child){childState=paneStateChildren[stateKey];if(child&&childState){child.loadState(childState)}})}})}}},readState:function(inst,opts){if($.type(opts)==="string"){opts={keys:opts}}if(!opts){opts={}}var sm=inst.options.stateManagement,ic=opts.includeChildren,recurse=ic!==undefined?ic:sm.includeChildren,keys=opts.stateKeys||sm.stateKeys,alt={isClosed:"initClosed",isHidden:"initHidden"},state=inst.state,panes=$.layout.config.allPanes,data={},pair,pane,key,val,ps,pC,child,array,count,branch;if($.isArray(keys)){keys=keys.join(",")}keys=keys.replace(/__/g,".").split(",");for(var i=0,n=keys.length;i<n;i++){pair=keys[i].split(".");pane=pair[0];key=pair[1];if($.inArray(pane,panes)<0){continue}val=state[pane][key];if(val==undefined){continue}if(key=="isClosed"&&state[pane]["isSliding"]){val=true}(data[pane]||(data[pane]={}))[alt[key]?alt[key]:key]=val}if(recurse){$.each(panes,function(idx,pane){pC=inst.children[pane];ps=state.stateData[pane];if($.isPlainObject(pC)&&!$.isEmptyObject(pC)){branch=data[pane]||(data[pane]={});if(!branch.children){branch.children={}}$.each(pC,function(key,child){if(child.state.initialized){branch.children[key]=$.layout.state.readState(child)}else{if(ps&&ps.children&&ps.children[key]){branch.children[key]=$.extend(true,{},ps.children[key])}}})}})}return data},encodeJSON:function(json){var local=window.JSON||{};return(local.stringify||stringify)(json);function stringify(h){var D=[],i=0,k,v,t,a=$.isArray(h);for(k in h){v=h[k];t=typeof v;if(t=="string"){v='"'+v+'"'}else{if(t=="object"){v=parse(v)}}D[i++]=(!a?'"'+k+'":':"")+v}return(a?"[":"{")+D.join(",")+(a?"]":"}")}},decodeJSON:function(str){try{return $.parseJSON?$.parseJSON(str):window["eval"]("("+str+")")||{}}catch(e){return{}}},_create:function(inst){var s=$.layout.state,o=inst.options,sm=o.stateManagement;$.extend(inst,{readCookie:function(){return s.readCookie(inst)},deleteCookie:function(){s.deleteCookie(inst)},saveCookie:function(keys,cookieOpts){return s.saveCookie(inst,keys,cookieOpts)},loadCookie:function(){return s.loadCookie(inst)},loadState:function(stateData,opts){s.loadState(inst,stateData,opts)},readState:function(keys){return s.readState(inst,keys)},encodeJSON:s.encodeJSON,decodeJSON:s.decodeJSON});inst.state.stateData={};if(!sm.autoLoad){return}if($.isPlainObject(sm.autoLoad)){if(!$.isEmptyObject(sm.autoLoad)){inst.loadState(sm.autoLoad)}}else{if(sm.enabled){if($.isFunction(sm.autoLoad)){var d={};try{d=sm.autoLoad(inst,inst.state,inst.options,inst.options.name||"")}catch(e){}if(d&&$.isPlainObject(d)&&!$.isEmptyObject(d)){inst.loadState(d)}}else{inst.loadCookie()}}}},_unload:function(inst){var sm=inst.options.stateManagement;if(sm.enabled&&sm.autoSave){if($.isFunction(sm.autoSave)){try{sm.autoSave(inst,inst.state,inst.options,inst.options.name||"")}catch(e){}}else{inst.saveCookie()}}}};$.layout.onCreate.push($.layout.state._create);$.layout.onUnload.push($.layout.state._unload)})(jQuery);(function($){if(!$.layout){return}$.layout.plugins.buttons=true;$.layout.defaults.autoBindCustomButtons=false;$.layout.optionsMap.layout.push("autoBindCustomButtons");$.layout.buttons={config:{borderPanes:"north,south,west,east"},init:function(inst){var pre="ui-layout-button-",layout=inst.options.name||"",name;$.each("toggle,open,close,pin,toggle-slide,open-slide".split(","),function(i,action){$.each($.layout.buttons.config.borderPanes.split(","),function(ii,pane){$("."+pre+action+"-"+pane).each(function(){name=$(this).data("layoutName")||$(this).attr("layoutName");if(name==undefined||name===layout){inst.bindButton(this,action,pane)}})})})},get:function(inst,selector,pane,action){var $E=$(selector),o=inst.options;if($E.length&&$.layout.buttons.config.borderPanes.indexOf(pane)>=0){var btn=o[pane].buttonClass+"-"+action;$E.addClass(btn+" "+btn+"-"+pane).data("layoutName",o.name)}return $E},bind:function(inst,sel,action,pane){var _=$.layout.buttons;switch(action.toLowerCase()){case"toggle":_.addToggle(inst,sel,pane);break;case"open":_.addOpen(inst,sel,pane);break;case"close":_.addClose(inst,sel,pane);break;case"pin":_.addPin(inst,sel,pane);break;case"toggle-slide":_.addToggle(inst,sel,pane,true);break;case"open-slide":_.addOpen(inst,sel,pane,true);break}return inst},addToggle:function(inst,selector,pane,slide){$.layout.buttons.get(inst,selector,pane,"toggle").click(function(evt){inst.toggle(pane,!!slide);evt.stopPropagation()});return inst},addOpen:function(inst,selector,pane,slide){$.layout.buttons.get(inst,selector,pane,"open").attr("title",inst.options[pane].tips.Open).click(function(evt){inst.open(pane,!!slide);evt.stopPropagation()});return inst},addClose:function(inst,selector,pane){$.layout.buttons.get(inst,selector,pane,"close").attr("title",inst.options[pane].tips.Close).click(function(evt){inst.close(pane);evt.stopPropagation()});return inst},addPin:function(inst,selector,pane){var $E=$.layout.buttons.get(inst,selector,pane,"pin");if($E.length){var s=inst.state[pane];$E.click(function(evt){$.layout.buttons.setPinState(inst,$(this),pane,(s.isSliding||s.isClosed));if(s.isSliding||s.isClosed){inst.open(pane)}else{inst.close(pane)}evt.stopPropagation()});$.layout.buttons.setPinState(inst,$E,pane,(!s.isClosed&&!s.isSliding));s.pins.push(selector)}return inst},setPinState:function(inst,$Pin,pane,doPin){var updown=$Pin.attr("pin");if(updown&&doPin===(updown=="down")){return}var po=inst.options[pane],lang=po.tips,pin=po.buttonClass+"-pin",side=pin+"-"+pane,UP=pin+"-up "+side+"-up",DN=pin+"-down "+side+"-down";$Pin.attr("pin",doPin?"down":"up").attr("title",doPin?lang.Unpin:lang.Pin).removeClass(doPin?UP:DN).addClass(doPin?DN:UP)},syncPinBtns:function(inst,pane,doPin){$.each(state[pane].pins,function(i,selector){$.layout.buttons.setPinState(inst,$(selector),pane,doPin)})},_load:function(inst){$.extend(inst,{bindButton:function(selector,action,pane){return $.layout.buttons.bind(inst,selector,action,pane)},addToggleBtn:function(selector,pane,slide){return $.layout.buttons.addToggle(inst,selector,pane,slide)},addOpenBtn:function(selector,pane,slide){return $.layout.buttons.addOpen(inst,selector,pane,slide)},addCloseBtn:function(selector,pane){return $.layout.buttons.addClose(inst,selector,pane)},addPinBtn:function(selector,pane){return $.layout.buttons.addPin(inst,selector,pane)}});for(var i=0;i<4;i++){var pane=$.layout.buttons.config.borderPanes[i];inst.state[pane].pins=[]}if(inst.options.autoBindCustomButtons){$.layout.buttons.init(inst)}},_unload:function(inst){}};$.layout.onLoad.push($.layout.buttons._load)})(jQuery);(function($){$.layout.plugins.browserZoom=true;$.layout.defaults.browserZoomCheckInterval=1000;$.layout.optionsMap.layout.push("browserZoomCheckInterval");$.layout.browserZoom={_init:function(inst){if($.layout.browserZoom.ratio()!==false){$.layout.browserZoom._setTimer(inst)}},_setTimer:function(inst){if(inst.destroyed){return}var o=inst.options,s=inst.state,ms=inst.hasParentLayout?5000:Math.max(o.browserZoomCheckInterval,100);setTimeout(function(){if(inst.destroyed||!o.resizeWithWindow){return}var d=$.layout.browserZoom.ratio();if(d!==s.browserZoom){s.browserZoom=d;inst.resizeAll()}$.layout.browserZoom._setTimer(inst)},ms)},ratio:function(){var w=window,s=screen,d=document,dE=d.documentElement||d.body,b=$.layout.browser,v=b.version,r,sW,cW;if(!b.msie||v>8){return false}if(s.deviceXDPI&&s.systemXDPI){return calc(s.deviceXDPI,s.systemXDPI)}if(b.webkit&&(r=d.body.getBoundingClientRect)){return calc((r.left-r.right),d.body.offsetWidth)}if(b.webkit&&(sW=w.outerWidth)){return calc(sW,w.innerWidth)}if((sW=s.width)&&(cW=dE.clientWidth)){return calc(sW,cW)}return false;function calc(x,y){return(parseInt(x,10)/parseInt(y,10)*100).toFixed()}}};$.layout.onReady.push($.layout.browserZoom._init)})(jQuery);(function($){if($.effects){$.layout.defaults.panes.useOffscreenClose=false;if($.layout.plugins){$.layout.plugins.effects.slideOffscreen=true}$.layout.effects.slideOffscreen=$.extend(true,{},$.layout.effects.slide);$.effects.slideOffscreen=function(o){return this.queue(function(){var fx=$.effects,opt=o.options,$el=$(this),pane=$el.data("layoutEdge"),state=$el.data("parentLayout").state,dist=state[pane].size,s=this.style,props=["top","bottom","left","right"],mode=fx.setMode($el,opt.mode||"show"),show=(mode=="show"),dir=opt.direction||"left",ref=(dir=="up"||dir=="down")?"top":"left",pos=(dir=="up"||dir=="left"),offscrn=$.layout.config.offscreenCSS||{},keyLR=$.layout.config.offscreenReset,keyTB="offscreenResetTop",animation={};animation[ref]=(show?(pos?"+=":"-="):(pos?"-=":"+="))+dist;if(show){$el.data(keyTB,{top:s.top,bottom:s.bottom});if(pos){$el.css(ref,isNaN(dist)?"-"+dist:-dist)}else{if(dir==="right"){$el.css({left:state.container.layoutWidth,right:"auto"})}else{$el.css({top:state.container.layoutHeight,bottom:"auto"})}}if(ref==="top"){$el.css($el.data(keyLR)||{})}}else{$el.data(keyTB,{top:s.top,bottom:s.bottom});$el.data(keyLR,{left:s.left,right:s.right})}$el.show().animate(animation,{queue:false,duration:o.duration,easing:opt.easing,complete:function(){if($el.data(keyTB)){$el.css($el.data(keyTB)).removeData(keyTB)}if(show){$el.css($el.data(keyLR)||{}).removeData(keyLR)}else{$el.css(offscrn)}if(o.callback){o.callback.apply(this,arguments)}$el.dequeue()}})})}}})(jQuery);
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/diy/1_close.png b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/diy/1_close.png
new file mode 100644
index 0000000..68ccb3c
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/diy/1_close.png
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/diy/1_open.png b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/diy/1_open.png
new file mode 100644
index 0000000..d6ff36d
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/diy/1_open.png
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/diy/2.png b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/diy/2.png
new file mode 100644
index 0000000..9eff506
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/diy/2.png
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/diy/3.png b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/diy/3.png
new file mode 100644
index 0000000..d7ba6d0
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/diy/3.png
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/diy/4.png b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/diy/4.png
new file mode 100644
index 0000000..753e2bf
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/diy/4.png
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/diy/5.png b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/diy/5.png
new file mode 100644
index 0000000..0c5eccd
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/diy/5.png
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/diy/6.png b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/diy/6.png
new file mode 100644
index 0000000..070b835
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/diy/6.png
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/diy/7.png b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/diy/7.png
new file mode 100644
index 0000000..532b037
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/diy/7.png
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/diy/8.png b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/diy/8.png
new file mode 100644
index 0000000..a8f3a86
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/diy/8.png
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/diy/9.png b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/diy/9.png
new file mode 100644
index 0000000..4db73cd
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/diy/9.png
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/line_conn.gif b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/line_conn.gif
new file mode 100644
index 0000000..d561d36
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/line_conn.gif
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/loading.gif b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/loading.gif
new file mode 100644
index 0000000..e8c2892
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/loading.gif
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/zTreeStandard.gif b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/zTreeStandard.gif
new file mode 100644
index 0000000..50c94fd
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/zTreeStandard.gif
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/zTreeStandard.png b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/zTreeStandard.png
new file mode 100644
index 0000000..ffda01e
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/img/zTreeStandard.png
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/zTreeStyle.css b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/zTreeStyle.css
new file mode 100644
index 0000000..8a9115a
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/default/zTreeStyle.css
@@ -0,0 +1,102 @@
+/*-------------------------------------
+zTree Style
+
+version:	3.4
+author:		Hunter.z
+email:		hunter.z@263.net
+website:	http://code.google.com/p/jquerytree/
+
+-------------------------------------*/
+
+.ztree * {padding:0; margin:0; font-size:12px;}
+.ztree {margin:0; padding:2px; color:#333}
+.ztree li{padding:0; margin:0; list-style:none; line-height:18px; text-align:left; white-space:nowrap; outline:0}
+.ztree li ul{ margin:0; padding:0 0 0 18px}
+.ztree li ul.line{ background:url(./img/line_conn.gif) 0 0 repeat-y;}
+
+.ztree li a {padding:1px 3px 0 0; margin:0; cursor:pointer; /* height:17px; */ color:#333; background-color: transparent;
+	text-decoration:none; vertical-align:top; display: inline-block}
+.ztree li a:hover {text-decoration:underline}
+/*.ztree li a.curSelectedNode {padding-top:0px; background-color:#FFE6B0; color:black; height:16px; border:1px #FFB951 solid; opacity:0.8;}*/
+.ztree li a.curSelectedNode {padding-top:0px; background-color:#F6F6F6; color:#0663A2; border:1px #DDDDDD solid; opacity:0.8;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}
+/*.ztree li a.curSelectedNode {padding-top:0px; color:#0663a2; font-weight:bold; height:16px; opacity:0.8;}*/
+.ztree li a.curSelectedNode_Edit {padding-top:0px; background-color:#FFE6B0; color:black; height:16px; border:1px #FFB951 solid; opacity:0.8;}
+.ztree li a.tmpTargetNode_inner {padding-top:0px; background-color:#316AC5; color:white; height:16px; border:1px #316AC5 solid;
+	opacity:0.8; filter:alpha(opacity=80)}
+.ztree li a.tmpTargetNode_prev {}
+.ztree li a.tmpTargetNode_next {}
+.ztree li a input.rename {height:14px; width:80px; padding:0; margin:0;
+	font-size:12px; border:1px #7EC4CC solid; *border:0px}
+.ztree li span {line-height:16px; margin-right:2px}
+.ztree li span.button {line-height:0; margin:0; width:16px; height:16px; display: inline-block; vertical-align:middle;
+	border:0 none; cursor: pointer;outline:none;
+	background-color:transparent; background-repeat:no-repeat; background-attachment: scroll;
+	background-image:url("./img/zTreeStandard.png"); *background-image:url("./img/zTreeStandard.gif")}
+
+/* IE7 fix */
+.ztree li span.button.level0 {*margin-left:-15px;}
+
+.ztree li span.button.chk {width:13px; height:13px; margin:0 3px 0 0; cursor: auto}
+.ztree li span.button.chk.checkbox_false_full {background-position:0 0}
+.ztree li span.button.chk.checkbox_false_full_focus {background-position:0 -14px}
+.ztree li span.button.chk.checkbox_false_part {background-position:0 -28px}
+.ztree li span.button.chk.checkbox_false_part_focus {background-position:0 -42px}
+.ztree li span.button.chk.checkbox_false_disable {background-position:0 -56px}
+.ztree li span.button.chk.checkbox_true_full {background-position:-14px 0}
+.ztree li span.button.chk.checkbox_true_full_focus {background-position:-14px -14px}
+.ztree li span.button.chk.checkbox_true_part {background-position:-14px -28px}
+.ztree li span.button.chk.checkbox_true_part_focus {background-position:-14px -42px}
+.ztree li span.button.chk.checkbox_true_disable {background-position:-14px -56px}
+.ztree li span.button.chk.radio_false_full {background-position:-28px 0}
+.ztree li span.button.chk.radio_false_full_focus {background-position:-28px -14px}
+.ztree li span.button.chk.radio_false_part {background-position:-28px -28px}
+.ztree li span.button.chk.radio_false_part_focus {background-position:-28px -42px}
+.ztree li span.button.chk.radio_false_disable {background-position:-28px -56px}
+.ztree li span.button.chk.radio_true_full {background-position:-42px 0}
+.ztree li span.button.chk.radio_true_full_focus {background-position:-42px -14px}
+.ztree li span.button.chk.radio_true_part {background-position:-42px -28px}
+.ztree li span.button.chk.radio_true_part_focus {background-position:-42px -42px}
+.ztree li span.button.chk.radio_true_disable {background-position:-42px -56px}
+
+.ztree li span.button.switch {width:18px; height:18px}
+.ztree li span.button.root_open{background-position:-92px -54px}
+.ztree li span.button.root_close{background-position:-74px -54px}
+.ztree li span.button.roots_open{background-position:-92px 0}
+.ztree li span.button.roots_close{background-position:-74px 0}
+.ztree li span.button.center_open{background-position:-92px -18px}
+.ztree li span.button.center_close{background-position:-74px -18px}
+.ztree li span.button.bottom_open{background-position:-92px -36px}
+.ztree li span.button.bottom_close{background-position:-74px -36px}
+.ztree li span.button.noline_open{background-position:-92px -72px}
+.ztree li span.button.noline_close{background-position:-74px -72px}
+.ztree li span.button.root_docu{ background:none;}
+.ztree li span.button.roots_docu{background-position:-56px 0}
+.ztree li span.button.center_docu{background-position:-56px -18px}
+.ztree li span.button.bottom_docu{background-position:-56px -36px}
+.ztree li span.button.noline_docu{ background:none;}
+
+.ztree li span.button.ico_open{margin-right:2px; background-position:-110px -16px; vertical-align:top; *vertical-align:middle}
+.ztree li span.button.ico_close{margin-right:2px; background-position:-110px 0; vertical-align:top; *vertical-align:middle}
+.ztree li span.button.ico_docu{margin-right:2px; background-position:-110px -32px; /* vertical-align:top; * */vertical-align:middle}
+.ztree li span.button.edit {margin-right:2px; background-position:-110px -48px; vertical-align:top; *vertical-align:middle}
+.ztree li span.button.remove {margin-right:2px; background-position:-110px -64px; vertical-align:top; *vertical-align:middle}
+
+.ztree li span.button.ico_loading{margin-right:2px; background:url(./img/loading.gif) no-repeat scroll 0 0 transparent; vertical-align:top; *vertical-align:middle}
+
+ul.tmpTargetzTree {background-color:#FFE6B0; opacity:0.8; filter:alpha(opacity=80)}
+
+span.tmpzTreeMove_arrow {width:16px; height:16px; display: inline-block; padding:0; margin:2px 0 0 1px; border:0 none; position:absolute;
+	background-color:transparent; background-repeat:no-repeat; background-attachment: scroll;
+	background-position:-110px -80px; background-image:url("./img/zTreeStandard.png"); *background-image:url("./img/zTreeStandard.gif")}
+
+ul.ztree.zTreeDragUL {margin:0; padding:0; position:absolute; width:auto; height:auto;overflow:hidden; background-color:#cfcfcf; border:1px #00B83F dotted; opacity:0.8; filter:alpha(opacity=80)}
+.zTreeMask {z-index:10000; background-color:#cfcfcf; opacity:0.0; filter:alpha(opacity=0); position:absolute}
+
+/* level style*/
+/*.ztree li span.button.level0 {
+	display:none;
+}
+.ztree li ul.level0 {
+	padding:0;
+	background:none;
+}*/
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/metro/img/line_conn.gif b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/metro/img/line_conn.gif
new file mode 100644
index 0000000..d561d36
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/metro/img/line_conn.gif
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/metro/img/line_conn.png b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/metro/img/line_conn.png
new file mode 100644
index 0000000..b211da2
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/metro/img/line_conn.png
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/metro/img/loading.gif b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/metro/img/loading.gif
new file mode 100644
index 0000000..e8c2892
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/metro/img/loading.gif
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/metro/img/metro.gif b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/metro/img/metro.gif
new file mode 100644
index 0000000..7f7df77
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/metro/img/metro.gif
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/metro/img/metro.png b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/metro/img/metro.png
new file mode 100644
index 0000000..ca8ff0e
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/metro/img/metro.png
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/metro/zTreeStyle.css b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/metro/zTreeStyle.css
new file mode 100644
index 0000000..bddc102
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/metro/zTreeStyle.css
@@ -0,0 +1,107 @@
+/*-------------------------------------
+zTree Style
+
+version:    3.4
+author:     Hunter.z
+email:      hunter.z@263.net
+website:    http://code.google.com/p/jquerytree/
+
+-------------------------------------*/
+
+.ztree * {padding:0; margin:0; font-size:12px; font-family: Verdana, Arial, Helvetica, AppleGothic, sans-serif}
+.ztree {margin:0; padding:5px; color:#333}
+.ztree li{padding:0; margin:0; list-style:none; line-height:21px; text-align:left; white-space:nowrap; outline:0}
+.ztree li ul{ margin:0; padding:0 0 0 18px}
+.ztree li ul.line{ background:url(./img/line_conn.png) 0 0 repeat-y;}
+
+.ztree li a {padding-right:3px; margin:0; cursor:pointer; height:21px; color:#333; background-color: transparent; text-decoration:none; display: inline-block}
+.ztree li a:hover {text-decoration:underline}
+.ztree li a.curSelectedNode {padding-top:0px; background-color:#e5e5e5; color:black; height:22px; -webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}
+.ztree li a.curSelectedNode_Edit {padding-top:0px; background-color:#e5e5e5; color:black; height:22px; border:1px #666 solid; -webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}
+.ztree li a.tmpTargetNode_inner {padding-top:0px; background-color:#aaa; color:white; height:21px; border:1px #666 solid;
+    opacity:0.8; filter:alpha(opacity=80)}
+.ztree li a.tmpTargetNode_prev {}
+.ztree li a.tmpTargetNode_next {}
+.ztree li a input.rename {height:14px; width:80px; padding:0; margin:0;
+    font-size:12px; border:1px #7EC4CC solid; *border:0px}
+.ztree li span {line-height:21px; margin-right:2px}
+.ztree li span.button {line-height:0; margin:0; width:21px; height:21px; display: inline-block; vertical-align:middle;
+    border:0 none; cursor: pointer;outline:none;
+    background-color:transparent; background-repeat:no-repeat; background-attachment: scroll;
+    background-image:url("./img/metro.png"); *background-image:url("./img/metro.gif")}
+
+.ztree li span.button.chk {width:13px; height:13px; margin:0 2px; cursor: auto}
+.ztree li span.button.chk.checkbox_false_full {background-position: -5px -5px;}
+.ztree li span.button.chk.checkbox_false_full_focus {background-position: -5px -26px;}
+.ztree li span.button.chk.checkbox_false_part {background-position: -5px -48px;}
+.ztree li span.button.chk.checkbox_false_part_focus {background-position: -5px -68px;}
+.ztree li span.button.chk.checkbox_false_disable {background-position: -5px -89px;}
+.ztree li span.button.chk.checkbox_true_full {background-position: -26px -5px;}
+.ztree li span.button.chk.checkbox_true_full_focus {background-position: -26px -26px;}
+.ztree li span.button.chk.checkbox_true_part {background-position: -26px -48px;}
+.ztree li span.button.chk.checkbox_true_part_focus {background-position: -26px -68px;}
+.ztree li span.button.chk.checkbox_true_disable {background-position: -26px -89px;}
+.ztree li span.button.chk.radio_false_full {background-position: -47px -5px;}
+.ztree li span.button.chk.radio_false_full_focus {background-position: -47px -26px;}
+.ztree li span.button.chk.radio_false_part {background-position: -47px -47px;}
+.ztree li span.button.chk.radio_false_part_focus {background-position: -47px -68px;}
+.ztree li span.button.chk.radio_false_disable {background-position: -47px -89px;}
+.ztree li span.button.chk.radio_true_full {background-position: -68px -5px;}
+.ztree li span.button.chk.radio_true_full_focus {background-position: -68px -26px;}
+.ztree li span.button.chk.radio_true_part {background-position: -68px -47px;}
+.ztree li span.button.chk.radio_true_part_focus {background-position: -68px -68px;}
+.ztree li span.button.chk.radio_true_disable {background-position: -68px -89px;}
+
+.ztree li span.button.switch {width:21px; height:21px}
+.ztree li span.button.root_open{background-position:-105px -85px}
+.ztree li span.button.root_close{background-position:-126px -85px}
+.ztree li span.button.roots_open{background-position: -105px 0;}
+.ztree li span.button.roots_close{background-position: -126px 0;}
+.ztree li span.button.center_open{background-position: -105px -21px;}
+.ztree li span.button.center_close{background-position: -126px -21px;}
+.ztree li span.button.bottom_open{background-position: -105px -42px;}
+.ztree li span.button.bottom_close{background-position: -126px -42px;}
+.ztree li span.button.noline_open{background-position: -126px -84px;}
+.ztree li span.button.noline_close{background-position: -105px -84px;}
+.ztree li span.button.root_docu{ background:none;}
+.ztree li span.button.roots_docu{background-position: -84px 0;}
+.ztree li span.button.center_docu{background-position: -84px -21px;}
+.ztree li span.button.bottom_docu{background-position: -84px -42px;}
+.ztree li span.button.noline_docu{ background:none;}
+
+.ztree li span.button.ico_open{margin-right:2px; background-position: -147px -21px; vertical-align:top; *vertical-align:middle}
+.ztree li span.button.ico_close{margin-right:2px; margin-right:2px; background-position: -147px 0; vertical-align:top; *vertical-align:middle}
+.ztree li span.button.ico_docu{margin-right:2px; background-position: -147px -42px; vertical-align:top; *vertical-align:middle}
+.ztree li span.button.edit {margin-left:2px; margin-right: -1px; background-position: -189px -21px; vertical-align:top; *vertical-align:middle}
+.ztree li span.button.edit:hover {
+  background-position: -168px -21px;
+}
+.ztree li span.button.remove {margin-left:2px; margin-right: -1px; background-position: -189px -42px; vertical-align:top; *vertical-align:middle}
+.ztree li span.button.remove:hover {
+  background-position: -168px -42px;
+}
+.ztree li span.button.add {margin-left:2px; margin-right: -1px; background-position: -189px 0; vertical-align:top; *vertical-align:middle}
+.ztree li span.button.add:hover {
+  background-position: -168px 0;
+}
+.ztree li span.button.ico_loading{margin-right:2px; background:url(./img/loading.gif) no-repeat scroll 0 0 transparent; vertical-align:top; *vertical-align:middle}
+
+ul.tmpTargetzTree {background-color:#FFE6B0; opacity:0.8; filter:alpha(opacity=80)}
+
+span.tmpzTreeMove_arrow {width:16px; height:21px; display: inline-block; padding:0; margin:2px 0 0 1px; border:0 none; position:absolute;
+    background-color:transparent; background-repeat:no-repeat; background-attachment: scroll;
+    background-position:-168px -84px; background-image:url("./img/metro.png"); *background-image:url("./img/metro.gif")}
+
+ul.ztree.zTreeDragUL {margin:0; padding:0; position:absolute; width:auto; height:auto;overflow:hidden; background-color:#cfcfcf; border:1px #00B83F dotted; opacity:0.8; filter:alpha(opacity=80)}
+.zTreeMask {z-index:10000; background-color:#cfcfcf; opacity:0.0; filter:alpha(opacity=0); position:absolute}
+
+/* 树搜索相关 */
+.treeSearchInput {padding:13px 0 0 20px;}
+.treeSearchInput label {padding:5px 0 3px 0;font-size:13px;font-weight:normal;vertical-align:middle;}
+.treeSearchInput input {width:145px;vertical-align:middle;line-height:24px;height:26px;border:1px solid #bbb;padding:0 4px;}
+.treeSearchInput button {border:1px solid #bbb;vertical-align:middle;height:26px;height:26px\9;font-size:13px;background:#efefef;padding:0 8px;}
+.treeShowHideButton {position:absolute;right:8px;top:2px;font-size:12px;color:#333;z-index:3;}
+.treeShowHideButton label {cursor:pointer;}
+.treeExpandCollapse {float:right;margin:6px 5px;padding:5px;font-size:12px;color:#333;position:relative;z-index:2;background:#fff;}
+.treeExpandCollapse a {text-decoration:none;color:#333}
+.treeselect.ztree {padding:10px 20px;}
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/simple/img/left_menu.gif b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/simple/img/left_menu.gif
new file mode 100644
index 0000000..c252f0f
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/simple/img/left_menu.gif
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/simple/img/left_menu.png b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/simple/img/left_menu.png
new file mode 100644
index 0000000..36e8acf
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/simple/img/left_menu.png
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/simple/img/line_conn.gif b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/simple/img/line_conn.gif
new file mode 100644
index 0000000..d561d36
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/simple/img/line_conn.gif
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/simple/img/loading.gif b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/simple/img/loading.gif
new file mode 100644
index 0000000..e8c2892
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/simple/img/loading.gif
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/simple/img/zTreeStandard.gif b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/simple/img/zTreeStandard.gif
new file mode 100644
index 0000000..50c94fd
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/simple/img/zTreeStandard.gif
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/simple/img/zTreeStandard.png b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/simple/img/zTreeStandard.png
new file mode 100644
index 0000000..ffda01e
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/simple/img/zTreeStandard.png
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/simple/zTreeStyle.css b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/simple/zTreeStyle.css
new file mode 100644
index 0000000..5bdcd76
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/css/simple/zTreeStyle.css
@@ -0,0 +1,118 @@
+/*-------------------------------------
+zTree Style
+
+version:    3.4
+author:     Hunter.z
+email:      hunter.z@263.net
+website:    http://code.google.com/p/jquerytree/
+
+-------------------------------------*/
+
+.ztree * {padding:0; margin:0; font-size:12px; font-family: Verdana, Arial, Helvetica, AppleGothic, sans-serif}
+.ztree {margin:0; padding:5px; color:#333}
+.ztree li{padding:0; margin:0; list-style:none; line-height:21px; text-align:left; white-space:nowrap; outline:0}
+.ztree li ul{ margin:0; padding:0 0 0 18px}
+.ztree li ul.line{ background:url(./img/line_conn.png) 0 0 repeat-y;}
+
+.ztree li a {padding-right:3px; margin:0; cursor:pointer; height:21px; color:#333; background-color: transparent; text-decoration:none; display: inline-block}
+.ztree li a:hover {text-decoration:underline}
+.ztree li a.curSelectedNode {padding-top:0px; background-color:#e5e5e5; color:black; height:21px; opacity:0.8;}
+.ztree li a.curSelectedNode_Edit {padding-top:0px; background-color:#e5e5e5; color:black; height:21px; border:1px #666 solid; opacity:0.8;}
+.ztree li a.tmpTargetNode_inner {padding-top:0px; background-color:#aaa; color:white; height:21px; border:1px #666 solid;
+    opacity:0.8; filter:alpha(opacity=80)}
+.ztree li a.tmpTargetNode_prev {}
+.ztree li a.tmpTargetNode_next {}
+.ztree li a input.rename {height:14px; width:80px; padding:0; margin:0;
+    font-size:12px; border:1px #7EC4CC solid; *border:0px}
+.ztree li span {line-height:21px; margin-right:2px}
+.ztree li span.button {line-height:0; margin:0; width:21px; height:21px; display: inline-block; vertical-align:middle;
+    border:0 none; cursor: pointer;outline:none;
+    background-color:transparent; background-repeat:no-repeat; background-attachment: scroll;
+    background-image:url("./img/metro.png"); *background-image:url("./img/metro.gif")}
+
+.ztree li span.button.chk {width:13px; height:13px; margin:0 2px; cursor: auto}
+.ztree li span.button.chk.checkbox_false_full {background-position: -5px -5px;}
+.ztree li span.button.chk.checkbox_false_full_focus {background-position: -5px -26px;}
+.ztree li span.button.chk.checkbox_false_part {background-position: -5px -48px;}
+.ztree li span.button.chk.checkbox_false_part_focus {background-position: -5px -68px;}
+.ztree li span.button.chk.checkbox_false_disable {background-position: -5px -89px;}
+.ztree li span.button.chk.checkbox_true_full {background-position: -26px -5px;}
+.ztree li span.button.chk.checkbox_true_full_focus {background-position: -26px -26px;}
+.ztree li span.button.chk.checkbox_true_part {background-position: -26px -48px;}
+.ztree li span.button.chk.checkbox_true_part_focus {background-position: -26px -68px;}
+.ztree li span.button.chk.checkbox_true_disable {background-position: -26px -89px;}
+.ztree li span.button.chk.radio_false_full {background-position: -47px -5px;}
+.ztree li span.button.chk.radio_false_full_focus {background-position: -47px -26px;}
+.ztree li span.button.chk.radio_false_part {background-position: -47px -47px;}
+.ztree li span.button.chk.radio_false_part_focus {background-position: -47px -68px;}
+.ztree li span.button.chk.radio_false_disable {background-position: -47px -89px;}
+.ztree li span.button.chk.radio_true_full {background-position: -68px -5px;}
+.ztree li span.button.chk.radio_true_full_focus {background-position: -68px -26px;}
+.ztree li span.button.chk.radio_true_part {background-position: -68px -47px;}
+.ztree li span.button.chk.radio_true_part_focus {background-position: -68px -68px;}
+.ztree li span.button.chk.radio_true_disable {background-position: -68px -89px;}
+
+.ztree li span.button.switch {width:21px; height:21px}
+.ztree li span.button.root_open{background-position:-92px -54px}
+.ztree li span.button.root_close{background-position:-74px -54px}
+.ztree li span.button.roots_open{background-position: -105px 0;}
+.ztree li span.button.roots_close{background-position: -126px 0;}
+.ztree li span.button.center_open{background-position: -105px -21px;}
+.ztree li span.button.center_close{background-position: -126px -21px;}
+.ztree li span.button.bottom_open{background-position: -105px -42px;}
+.ztree li span.button.bottom_close{background-position: -126px -42px;}
+.ztree li span.button.noline_open{background-position: -126px -84px;}
+.ztree li span.button.noline_close{background-position: -105px -84px;}
+.ztree li span.button.root_docu{ background:none;}
+.ztree li span.button.roots_docu{background-position: -84px 0;}
+.ztree li span.button.center_docu{background-position: -84px -21px;}
+.ztree li span.button.bottom_docu{background-position: -84px -42px;}
+.ztree li span.button.noline_docu{ background:none;}
+
+.ztree li span.button.ico_open{margin-right:2px; background-position: -147px -21px; vertical-align:top; *vertical-align:middle}
+.ztree li span.button.ico_close{margin-right:2px; margin-right:2px; background-position: -147px 0; vertical-align:top; *vertical-align:middle}
+.ztree li span.button.ico_docu{margin-right:2px; background-position: -147px -42px; vertical-align:top; *vertical-align:middle}
+.ztree li span.button.edit {margin-left:2px; margin-right: -1px; background-position: -189px -21px; vertical-align:top; *vertical-align:middle}
+.ztree li span.button.edit:hover {
+  background-position: -168px -21px;
+}
+.ztree li span.button.remove {margin-left:2px; margin-right: -1px; background-position: -189px -42px; vertical-align:top; *vertical-align:middle}
+.ztree li span.button.remove:hover {
+  background-position: -168px -42px;
+}
+.ztree li span.button.add {margin-left:2px; margin-right: -1px; background-position: -189px 0; vertical-align:top; *vertical-align:middle}
+.ztree li span.button.add:hover {
+  background-position: -168px 0;
+}
+.ztree li span.button.ico_loading{margin-right:2px; background:url(./img/loading.gif) no-repeat scroll 0 0 transparent; vertical-align:top; *vertical-align:middle}
+
+ul.tmpTargetzTree {background-color:#FFE6B0; opacity:0.8; filter:alpha(opacity=80)}
+
+span.tmpzTreeMove_arrow {width:16px; height:21px; display: inline-block; padding:0; margin:2px 0 0 1px; border:0 none; position:absolute;
+    background-color:transparent; background-repeat:no-repeat; background-attachment: scroll;
+    background-position:-168px -84px; background-image:url("./img/metro.png"); *background-image:url("./img/metro.gif")}
+
+ul.ztree.zTreeDragUL {margin:0; padding:0; position:absolute; width:auto; height:auto;overflow:hidden; background-color:#cfcfcf; border:1px #00B83F dotted; opacity:0.8; filter:alpha(opacity=80)}
+.zTreeMask {z-index:10000; background-color:#cfcfcf; opacity:0.0; filter:alpha(opacity=0); position:absolute}
+
+/* simple */
+
+.ztree * {font-size:14px;font-family:"Microsoft Yahei",Verdana,Simsun,"Segoe UI Web Light","Segoe UI Light","Segoe UI Web Regular","Segoe UI","Segoe UI Symbol","Helvetica Neue",Arial;}
+.ztree li ul{ margin:0; padding:0}
+.ztree li {line-height:28px;}
+.ztree li a {width:100%;height:28px;padding-top: 0px;}
+.ztree li a:hover {text-decoration:none; background-color: #E7E7E7;}
+.ztree11 li a span.button.switch {visibility:hidden}
+.ztree11.showIcon li a span.button.switch {visibility:visible}
+.ztree li a.curSelectedNode {background-color:#D4D4D4;border:0;height:28px;}
+.ztree li span {line-height:26px;margin-right:0px;}
+.ztree li span.button {margin-top: -7px;}
+.ztree li span.button.switch {width:16px;height: 16px;}
+.ztree li a.level0 span {font-size:15px;font-weight:bold;}
+.ztree li span.button {background-image:url("img/left_menu.png"); *background-image:url("./left_menu.gif")}
+.ztree li span.button.switch.level0 {width: 20px; height:20px}
+.ztree li span.button.switch.level1 {width: 20px; height:20px}
+.ztree li span.button.noline_open {background-position: 0 0;}
+.ztree li span.button.noline_close {background-position: -18px 0;}
+.ztree li span.button.noline_open.level0 {background-position: 0 -17px;}
+.ztree li span.button.noline_close.level0 {background-position: -18px -17px;}
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/js/jquery.ztree.all-3.5.js b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/js/jquery.ztree.all-3.5.js
new file mode 100644
index 0000000..d71caf8
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/js/jquery.ztree.all-3.5.js
@@ -0,0 +1,3820 @@
+
+/*
+ * JQuery zTree core 3.5.12
+ * http://zTree.me/
+ *
+ * Copyright (c) 2010 Hunter.z
+ *
+ * Licensed same as jquery - MIT License
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ * email: hunter.z@263.net
+ * Date: 2013-03-11
+ */
+(function($){
+	var settings = {}, roots = {}, caches = {},
+	//default consts of core
+	_consts = {
+		className: {
+			BUTTON: "button",
+			LEVEL: "level",
+			ICO_LOADING: "ico_loading",
+			SWITCH: "switch"
+		},
+		event: {
+			NODECREATED: "ztree_nodeCreated",
+			CLICK: "ztree_click",
+			EXPAND: "ztree_expand",
+			COLLAPSE: "ztree_collapse",
+			ASYNC_SUCCESS: "ztree_async_success",
+			ASYNC_ERROR: "ztree_async_error"
+		},
+		id: {
+			A: "_a",
+			ICON: "_ico",
+			SPAN: "_span",
+			SWITCH: "_switch",
+			UL: "_ul"
+		},
+		line: {
+			ROOT: "root",
+			ROOTS: "roots",
+			CENTER: "center",
+			BOTTOM: "bottom",
+			NOLINE: "noline",
+			LINE: "line"
+		},
+		folder: {
+			OPEN: "open",
+			CLOSE: "close",
+			DOCU: "docu"
+		},
+		node: {
+			CURSELECTED: "curSelectedNode"
+		}
+	},
+	//default setting of core
+	_setting = {
+		treeId: "",
+		treeObj: null,
+		view: {
+			addDiyDom: null,
+			autoCancelSelected: true,
+			dblClickExpand: true,
+			expandSpeed: "fast",
+			fontCss: {},
+			nameIsHTML: false,
+			selectedMulti: true,
+			showIcon: true,
+			showLine: true,
+			showTitle: true
+		},
+		data: {
+			key: {
+				children: "children",
+				name: "name",
+				title: "",
+				url: "url"
+			},
+			simpleData: {
+				enable: false,
+				idKey: "id",
+				pIdKey: "pId",
+				rootPId: null
+			},
+			keep: {
+				parent: false,
+				leaf: false
+			}
+		},
+		async: {
+			enable: false,
+			contentType: "application/x-www-form-urlencoded",
+			type: "post",
+			dataType: "text",
+			url: "",
+			autoParam: [],
+			otherParam: [],
+			dataFilter: null
+		},
+		callback: {
+			beforeAsync:null,
+			beforeClick:null,
+			beforeDblClick:null,
+			beforeRightClick:null,
+			beforeMouseDown:null,
+			beforeMouseUp:null,
+			beforeExpand:null,
+			beforeCollapse:null,
+			beforeRemove:null,
+
+			onAsyncError:null,
+			onAsyncSuccess:null,
+			onNodeCreated:null,
+			onClick:null,
+			onDblClick:null,
+			onRightClick:null,
+			onMouseDown:null,
+			onMouseUp:null,
+			onExpand:null,
+			onCollapse:null,
+			onRemove:null
+		}
+	},
+	//default root of core
+	//zTree use root to save full data
+	_initRoot = function (setting) {
+		var r = data.getRoot(setting);
+		if (!r) {
+			r = {};
+			data.setRoot(setting, r);
+		}
+		r[setting.data.key.children] = [];
+		r.expandTriggerFlag = false;
+		r.curSelectedList = [];
+		r.noSelection = true;
+		r.createdNodes = [];
+		r.zId = 0;
+		r._ver = (new Date()).getTime();
+	},
+	//default cache of core
+	_initCache = function(setting) {
+		var c = data.getCache(setting);
+		if (!c) {
+			c = {};
+			data.setCache(setting, c);
+		}
+		c.nodes = [];
+		c.doms = [];
+	},
+	//default bindEvent of core
+	_bindEvent = function(setting) {
+		var o = setting.treeObj,
+		c = consts.event;
+		o.bind(c.NODECREATED, function (event, treeId, node) {
+			tools.apply(setting.callback.onNodeCreated, [event, treeId, node]);
+		});
+
+		o.bind(c.CLICK, function (event, srcEvent, treeId, node, clickFlag) {
+			tools.apply(setting.callback.onClick, [srcEvent, treeId, node, clickFlag]);
+		});
+
+		o.bind(c.EXPAND, function (event, treeId, node) {
+			tools.apply(setting.callback.onExpand, [event, treeId, node]);
+		});
+
+		o.bind(c.COLLAPSE, function (event, treeId, node) {
+			tools.apply(setting.callback.onCollapse, [event, treeId, node]);
+		});
+
+		o.bind(c.ASYNC_SUCCESS, function (event, treeId, node, msg) {
+			tools.apply(setting.callback.onAsyncSuccess, [event, treeId, node, msg]);
+		});
+
+		o.bind(c.ASYNC_ERROR, function (event, treeId, node, XMLHttpRequest, textStatus, errorThrown) {
+			tools.apply(setting.callback.onAsyncError, [event, treeId, node, XMLHttpRequest, textStatus, errorThrown]);
+		});
+	},
+	_unbindEvent = function(setting) {
+		var o = setting.treeObj,
+		c = consts.event;
+		o.unbind(c.NODECREATED)
+		.unbind(c.CLICK)
+		.unbind(c.EXPAND)
+		.unbind(c.COLLAPSE)
+		.unbind(c.ASYNC_SUCCESS)
+		.unbind(c.ASYNC_ERROR);
+	},	
+	//default event proxy of core
+	_eventProxy = function(event) {
+		var target = event.target,
+		setting = data.getSetting(event.data.treeId),
+		tId = "", node = null,
+		nodeEventType = "", treeEventType = "",
+		nodeEventCallback = null, treeEventCallback = null,
+		tmp = null;
+
+		if (tools.eqs(event.type, "mousedown")) {
+			treeEventType = "mousedown";
+		} else if (tools.eqs(event.type, "mouseup")) {
+			treeEventType = "mouseup";
+		} else if (tools.eqs(event.type, "contextmenu")) {
+			treeEventType = "contextmenu";
+		} else if (tools.eqs(event.type, "click")) {
+			if (tools.eqs(target.tagName, "span") && target.getAttribute("treeNode"+ consts.id.SWITCH) !== null) {
+				tId = ($(target).parent("li").get(0) || $(target).parentsUntil("li").parent().get(0)).id;
+				nodeEventType = "switchNode";
+			} else {
+				tmp = tools.getMDom(setting, target, [{tagName:"a", attrName:"treeNode"+consts.id.A}]);
+				if (tmp) {
+					tId = ($(tmp).parent("li").get(0) || $(tmp).parentsUntil("li").parent().get(0)).id;
+					nodeEventType = "clickNode";
+				}
+			}
+		} else if (tools.eqs(event.type, "dblclick")) {
+			treeEventType = "dblclick";
+			tmp = tools.getMDom(setting, target, [{tagName:"a", attrName:"treeNode"+consts.id.A}]);
+			if (tmp) {
+				tId = ($(tmp).parent("li").get(0) || $(tmp).parentsUntil("li").parent().get(0)).id;
+				nodeEventType = "switchNode";
+			}
+		}
+		if (treeEventType.length > 0 && tId.length == 0) {
+			tmp = tools.getMDom(setting, target, [{tagName:"a", attrName:"treeNode"+consts.id.A}]);
+			if (tmp) {tId = ($(tmp).parent("li").get(0) || $(tmp).parentsUntil("li").parent().get(0)).id;}
+		}
+		// event to node
+		if (tId.length>0) {
+			node = data.getNodeCache(setting, tId);
+			switch (nodeEventType) {
+				case "switchNode" :
+					if (!node.isParent) {
+						nodeEventType = "";
+					} else if (tools.eqs(event.type, "click") 
+						|| (tools.eqs(event.type, "dblclick") && tools.apply(setting.view.dblClickExpand, [setting.treeId, node], setting.view.dblClickExpand))) {
+						nodeEventCallback = handler.onSwitchNode;
+					} else {
+						nodeEventType = "";
+					}
+					break;
+				case "clickNode" :
+					nodeEventCallback = handler.onClickNode;
+					break;
+			}
+		}
+		// event to zTree
+		switch (treeEventType) {
+			case "mousedown" :
+				treeEventCallback = handler.onZTreeMousedown;
+				break;
+			case "mouseup" :
+				treeEventCallback = handler.onZTreeMouseup;
+				break;
+			case "dblclick" :
+				treeEventCallback = handler.onZTreeDblclick;
+				break;
+			case "contextmenu" :
+				treeEventCallback = handler.onZTreeContextmenu;
+				break;
+		}
+		var proxyResult = {
+			stop: false,
+			node: node,
+			nodeEventType: nodeEventType,
+			nodeEventCallback: nodeEventCallback,
+			treeEventType: treeEventType,
+			treeEventCallback: treeEventCallback
+		};
+		return proxyResult
+	},
+	//default init node of core
+	_initNode = function(setting, level, n, parentNode, isFirstNode, isLastNode, openFlag) {
+		if (!n) return;
+		var r = data.getRoot(setting),
+		childKey = setting.data.key.children;
+		n.level = level;
+		n.tId = setting.treeId + "_" + (++r.zId);
+		n.parentTId = parentNode ? parentNode.tId : null;
+		if (n[childKey] && n[childKey].length > 0) {
+			if (typeof n.open == "string") n.open = tools.eqs(n.open, "true");
+			n.open = !!n.open;
+			n.isParent = true;
+			n.zAsync = true;
+		} else {
+			n.open = false;
+			if (typeof n.isParent == "string") n.isParent = tools.eqs(n.isParent, "true");
+			n.isParent = !!n.isParent;
+			n.zAsync = !n.isParent;
+		}
+		n.isFirstNode = isFirstNode;
+		n.isLastNode = isLastNode;
+		n.getParentNode = function() {return data.getNodeCache(setting, n.parentTId);};
+		n.getPreNode = function() {return data.getPreNode(setting, n);};
+		n.getNextNode = function() {return data.getNextNode(setting, n);};
+		n.isAjaxing = false;
+		data.fixPIdKeyValue(setting, n);
+	},
+	_init = {
+		bind: [_bindEvent],
+		unbind: [_unbindEvent],
+		caches: [_initCache],
+		nodes: [_initNode],
+		proxys: [_eventProxy],
+		roots: [_initRoot],
+		beforeA: [],
+		afterA: [],
+		innerBeforeA: [],
+		innerAfterA: [],
+		zTreeTools: []
+	},
+	//method of operate data
+	data = {
+		addNodeCache: function(setting, node) {
+			data.getCache(setting).nodes[data.getNodeCacheId(node.tId)] = node;
+		},
+		getNodeCacheId: function(tId) {
+			return tId.substring(tId.lastIndexOf("_")+1);
+		},
+		addAfterA: function(afterA) {
+			_init.afterA.push(afterA);
+		},
+		addBeforeA: function(beforeA) {
+			_init.beforeA.push(beforeA);
+		},
+		addInnerAfterA: function(innerAfterA) {
+			_init.innerAfterA.push(innerAfterA);
+		},
+		addInnerBeforeA: function(innerBeforeA) {
+			_init.innerBeforeA.push(innerBeforeA);
+		},
+		addInitBind: function(bindEvent) {
+			_init.bind.push(bindEvent);
+		},
+		addInitUnBind: function(unbindEvent) {
+			_init.unbind.push(unbindEvent);
+		},
+		addInitCache: function(initCache) {
+			_init.caches.push(initCache);
+		},
+		addInitNode: function(initNode) {
+			_init.nodes.push(initNode);
+		},
+		addInitProxy: function(initProxy) {
+			_init.proxys.push(initProxy);
+		},
+		addInitRoot: function(initRoot) {
+			_init.roots.push(initRoot);
+		},
+		addNodesData: function(setting, parentNode, nodes) {
+			var childKey = setting.data.key.children;
+			if (!parentNode[childKey]) parentNode[childKey] = [];
+			if (parentNode[childKey].length > 0) {
+				parentNode[childKey][parentNode[childKey].length - 1].isLastNode = false;
+				view.setNodeLineIcos(setting, parentNode[childKey][parentNode[childKey].length - 1]);
+			}
+			parentNode.isParent = true;
+			parentNode[childKey] = parentNode[childKey].concat(nodes);
+		},
+		addSelectedNode: function(setting, node) {
+			var root = data.getRoot(setting);
+			if (!data.isSelectedNode(setting, node)) {
+				root.curSelectedList.push(node);
+			}
+		},
+		addCreatedNode: function(setting, node) {
+			if (!!setting.callback.onNodeCreated || !!setting.view.addDiyDom) {
+				var root = data.getRoot(setting);
+				root.createdNodes.push(node);
+			}
+		},
+		addZTreeTools: function(zTreeTools) {
+			_init.zTreeTools.push(zTreeTools);
+		},
+		exSetting: function(s) {
+			$.extend(true, _setting, s);
+		},
+		fixPIdKeyValue: function(setting, node) {
+			if (setting.data.simpleData.enable) {
+				node[setting.data.simpleData.pIdKey] = node.parentTId ? node.getParentNode()[setting.data.simpleData.idKey] : setting.data.simpleData.rootPId;
+			}
+		},
+		getAfterA: function(setting, node, array) {
+			for (var i=0, j=_init.afterA.length; i<j; i++) {
+				_init.afterA[i].apply(this, arguments);
+			}
+		},
+		getBeforeA: function(setting, node, array) {
+			for (var i=0, j=_init.beforeA.length; i<j; i++) {
+				_init.beforeA[i].apply(this, arguments);
+			}
+		},
+		getInnerAfterA: function(setting, node, array) {
+			for (var i=0, j=_init.innerAfterA.length; i<j; i++) {
+				_init.innerAfterA[i].apply(this, arguments);
+			}
+		},
+		getInnerBeforeA: function(setting, node, array) {
+			for (var i=0, j=_init.innerBeforeA.length; i<j; i++) {
+				_init.innerBeforeA[i].apply(this, arguments);
+			}
+		},
+		getCache: function(setting) {
+			return caches[setting.treeId];
+		},
+		getNextNode: function(setting, node) {
+			if (!node) return null;
+			var childKey = setting.data.key.children,
+			p = node.parentTId ? node.getParentNode() : data.getRoot(setting);
+			for (var i=0, l=p[childKey].length-1; i<=l; i++) {
+				if (p[childKey][i] === node) {
+					return (i==l ? null : p[childKey][i+1]);
+				}
+			}
+			return null;
+		},
+		getNodeByParam: function(setting, nodes, key, value) {
+			if (!nodes || !key) return null;
+			var childKey = setting.data.key.children;
+			for (var i = 0, l = nodes.length; i < l; i++) {
+				if (nodes[i][key] == value) {
+					return nodes[i];
+				}
+				var tmp = data.getNodeByParam(setting, nodes[i][childKey], key, value);
+				if (tmp) return tmp;
+			}
+			return null;
+		},
+		getNodeCache: function(setting, tId) {
+			if (!tId) return null;
+			var n = caches[setting.treeId].nodes[data.getNodeCacheId(tId)];
+			return n ? n : null;
+		},
+		getNodeName: function(setting, node) {
+			var nameKey = setting.data.key.name;
+			return "" + node[nameKey];
+		},
+		getNodeTitle: function(setting, node) {
+			var t = setting.data.key.title === "" ? setting.data.key.name : setting.data.key.title;
+			return "" + node[t];
+		},
+		getNodes: function(setting) {
+			return data.getRoot(setting)[setting.data.key.children];
+		},
+		getNodesByParam: function(setting, nodes, key, value) {
+			if (!nodes || !key) return [];
+			var childKey = setting.data.key.children,
+			result = [];
+			for (var i = 0, l = nodes.length; i < l; i++) {
+				if (nodes[i][key] == value) {
+					result.push(nodes[i]);
+				}
+				result = result.concat(data.getNodesByParam(setting, nodes[i][childKey], key, value));
+			}
+			return result;
+		},
+		getNodesByParamFuzzy: function(setting, nodes, key, value) {
+			if (!nodes || !key) return [];
+			var childKey = setting.data.key.children,
+			result = [];
+			value = value.toLowerCase();
+			for (var i = 0, l = nodes.length; i < l; i++) {
+				if (typeof nodes[i][key] == "string" && nodes[i][key].toLowerCase().indexOf(value)>-1) {
+					result.push(nodes[i]);
+				}
+				result = result.concat(data.getNodesByParamFuzzy(setting, nodes[i][childKey], key, value));
+			}
+			return result;
+		},
+		getNodesByFilter: function(setting, nodes, filter, isSingle, invokeParam) {
+			if (!nodes) return (isSingle ? null : []);
+			var childKey = setting.data.key.children,
+			result = isSingle ? null : [];
+			for (var i = 0, l = nodes.length; i < l; i++) {
+				if (tools.apply(filter, [nodes[i], invokeParam], false)) {
+					if (isSingle) {return nodes[i];}
+					result.push(nodes[i]);
+				}
+				var tmpResult = data.getNodesByFilter(setting, nodes[i][childKey], filter, isSingle, invokeParam);
+				if (isSingle && !!tmpResult) {return tmpResult;}
+				result = isSingle ? tmpResult : result.concat(tmpResult);
+			}
+			return result;
+		},
+		getPreNode: function(setting, node) {
+			if (!node) return null;
+			var childKey = setting.data.key.children,
+			p = node.parentTId ? node.getParentNode() : data.getRoot(setting);
+			for (var i=0, l=p[childKey].length; i<l; i++) {
+				if (p[childKey][i] === node) {
+					return (i==0 ? null : p[childKey][i-1]);
+				}
+			}
+			return null;
+		},
+		getRoot: function(setting) {
+			return setting ? roots[setting.treeId] : null;
+		},
+		getSetting: function(treeId) {
+			return settings[treeId];
+		},
+		getSettings: function() {
+			return settings;
+		},
+		getZTreeTools: function(treeId) {
+			var r = this.getRoot(this.getSetting(treeId));
+			return r ? r.treeTools : null;
+		},
+		initCache: function(setting) {
+			for (var i=0, j=_init.caches.length; i<j; i++) {
+				_init.caches[i].apply(this, arguments);
+			}
+		},
+		initNode: function(setting, level, node, parentNode, preNode, nextNode) {
+			for (var i=0, j=_init.nodes.length; i<j; i++) {
+				_init.nodes[i].apply(this, arguments);
+			}
+		},
+		initRoot: function(setting) {
+			for (var i=0, j=_init.roots.length; i<j; i++) {
+				_init.roots[i].apply(this, arguments);
+			}
+		},
+		isSelectedNode: function(setting, node) {
+			var root = data.getRoot(setting);
+			for (var i=0, j=root.curSelectedList.length; i<j; i++) {
+				if(node === root.curSelectedList[i]) return true;
+			}
+			return false;
+		},
+		removeNodeCache: function(setting, node) {
+			var childKey = setting.data.key.children;
+			if (node[childKey]) {
+				for (var i=0, l=node[childKey].length; i<l; i++) {
+					arguments.callee(setting, node[childKey][i]);
+				}
+			}
+			data.getCache(setting).nodes[data.getNodeCacheId(node.tId)] = null;
+		},
+		removeSelectedNode: function(setting, node) {
+			var root = data.getRoot(setting);
+			for (var i=0, j=root.curSelectedList.length; i<j; i++) {
+				if(node === root.curSelectedList[i] || !data.getNodeCache(setting, root.curSelectedList[i].tId)) {
+					root.curSelectedList.splice(i, 1);
+					i--;j--;
+				}
+			}
+		},
+		setCache: function(setting, cache) {
+			caches[setting.treeId] = cache;
+		},
+		setRoot: function(setting, root) {
+			roots[setting.treeId] = root;
+		},
+		setZTreeTools: function(setting, zTreeTools) {
+			for (var i=0, j=_init.zTreeTools.length; i<j; i++) {
+				_init.zTreeTools[i].apply(this, arguments);
+			}
+		},
+		transformToArrayFormat: function (setting, nodes) {
+			if (!nodes) return [];
+			var childKey = setting.data.key.children,
+			r = [];
+			if (tools.isArray(nodes)) {
+				for (var i=0, l=nodes.length; i<l; i++) {
+					r.push(nodes[i]);
+					if (nodes[i][childKey])
+						r = r.concat(data.transformToArrayFormat(setting, nodes[i][childKey]));
+				}
+			} else {
+				r.push(nodes);
+				if (nodes[childKey])
+					r = r.concat(data.transformToArrayFormat(setting, nodes[childKey]));
+			}
+			return r;
+		},
+		transformTozTreeFormat: function(setting, sNodes) {
+			var i,l,
+			key = setting.data.simpleData.idKey,
+			parentKey = setting.data.simpleData.pIdKey,
+			childKey = setting.data.key.children;
+			if (!key || key=="" || !sNodes) return [];
+
+			if (tools.isArray(sNodes)) {
+				var r = [];
+				var tmpMap = [];
+				for (i=0, l=sNodes.length; i<l; i++) {
+					tmpMap[sNodes[i][key]] = sNodes[i];
+				}
+				for (i=0, l=sNodes.length; i<l; i++) {
+					if (tmpMap[sNodes[i][parentKey]] && sNodes[i][key] != sNodes[i][parentKey]) {
+						if (!tmpMap[sNodes[i][parentKey]][childKey])
+							tmpMap[sNodes[i][parentKey]][childKey] = [];
+						tmpMap[sNodes[i][parentKey]][childKey].push(sNodes[i]);
+					} else {
+						r.push(sNodes[i]);
+					}
+				}
+				return r;
+			}else {
+				return [sNodes];
+			}
+		}
+	},
+	//method of event proxy
+	event = {
+		bindEvent: function(setting) {
+			for (var i=0, j=_init.bind.length; i<j; i++) {
+				_init.bind[i].apply(this, arguments);
+			}
+		},
+		unbindEvent: function(setting) {
+			for (var i=0, j=_init.unbind.length; i<j; i++) {
+				_init.unbind[i].apply(this, arguments);
+			}
+		},
+		bindTree: function(setting) {
+			var eventParam = {
+				treeId: setting.treeId
+			},
+			o = setting.treeObj;
+			// for can't select text
+			o.bind('selectstart', function(e){
+					var n = e.originalEvent.srcElement.nodeName.toLowerCase();
+					return (n === "input" || n === "textarea" );
+			}).css({
+				"-moz-user-select":"-moz-none"
+			});
+			o.bind('click', eventParam, event.proxy);
+			o.bind('dblclick', eventParam, event.proxy);
+			o.bind('mouseover', eventParam, event.proxy);
+			o.bind('mouseout', eventParam, event.proxy);
+			o.bind('mousedown', eventParam, event.proxy);
+			o.bind('mouseup', eventParam, event.proxy);
+			o.bind('contextmenu', eventParam, event.proxy);
+		},
+		unbindTree: function(setting) {
+			var o = setting.treeObj;
+			o.unbind('click', event.proxy)
+			.unbind('dblclick', event.proxy)
+			.unbind('mouseover', event.proxy)
+			.unbind('mouseout', event.proxy)
+			.unbind('mousedown', event.proxy)
+			.unbind('mouseup', event.proxy)
+			.unbind('contextmenu', event.proxy);
+		},
+		doProxy: function(e) {
+			var results = [];
+			for (var i=0, j=_init.proxys.length; i<j; i++) {
+				var proxyResult = _init.proxys[i].apply(this, arguments);
+				results.push(proxyResult);
+				if (proxyResult.stop) {
+					break;
+				}
+			}
+			return results;
+		},
+		proxy: function(e) {
+			var setting = data.getSetting(e.data.treeId);
+			if (!tools.uCanDo(setting, e)) return true;
+			var results = event.doProxy(e),
+			r = true, x = false;
+			for (var i=0, l=results.length; i<l; i++) {
+				var proxyResult = results[i];
+				if (proxyResult.nodeEventCallback) {
+					x = true;
+					r = proxyResult.nodeEventCallback.apply(proxyResult, [e, proxyResult.node]) && r;
+				}
+				if (proxyResult.treeEventCallback) {
+					x = true;
+					r = proxyResult.treeEventCallback.apply(proxyResult, [e, proxyResult.node]) && r;
+				}
+			}
+			return r;
+		}
+	},
+	//method of event handler
+	handler = {
+		onSwitchNode: function (event, node) {
+			var setting = data.getSetting(event.data.treeId);
+			if (node.open) {
+				if (tools.apply(setting.callback.beforeCollapse, [setting.treeId, node], true) == false) return true;
+				data.getRoot(setting).expandTriggerFlag = true;
+				view.switchNode(setting, node);
+			} else {
+				if (tools.apply(setting.callback.beforeExpand, [setting.treeId, node], true) == false) return true;
+				data.getRoot(setting).expandTriggerFlag = true;
+				view.switchNode(setting, node);
+			}
+			return true;
+		},
+		onClickNode: function (event, node) {
+			var setting = data.getSetting(event.data.treeId),
+			clickFlag = ( (setting.view.autoCancelSelected && event.ctrlKey) && data.isSelectedNode(setting, node)) ? 0 : (setting.view.autoCancelSelected && event.ctrlKey && setting.view.selectedMulti) ? 2 : 1;
+			if (tools.apply(setting.callback.beforeClick, [setting.treeId, node, clickFlag], true) == false) return true;
+			if (clickFlag === 0) {
+				view.cancelPreSelectedNode(setting, node);
+			} else {
+				view.selectNode(setting, node, clickFlag === 2);
+			}
+			setting.treeObj.trigger(consts.event.CLICK, [event, setting.treeId, node, clickFlag]);
+			return true;
+		},
+		onZTreeMousedown: function(event, node) {
+			var setting = data.getSetting(event.data.treeId);
+			if (tools.apply(setting.callback.beforeMouseDown, [setting.treeId, node], true)) {
+				tools.apply(setting.callback.onMouseDown, [event, setting.treeId, node]);
+			}
+			return true;
+		},
+		onZTreeMouseup: function(event, node) {
+			var setting = data.getSetting(event.data.treeId);
+			if (tools.apply(setting.callback.beforeMouseUp, [setting.treeId, node], true)) {
+				tools.apply(setting.callback.onMouseUp, [event, setting.treeId, node]);
+			}
+			return true;
+		},
+		onZTreeDblclick: function(event, node) {
+			var setting = data.getSetting(event.data.treeId);
+			if (tools.apply(setting.callback.beforeDblClick, [setting.treeId, node], true)) {
+				tools.apply(setting.callback.onDblClick, [event, setting.treeId, node]);
+			}
+			return true;
+		},
+		onZTreeContextmenu: function(event, node) {
+			var setting = data.getSetting(event.data.treeId);
+			if (tools.apply(setting.callback.beforeRightClick, [setting.treeId, node], true)) {
+				tools.apply(setting.callback.onRightClick, [event, setting.treeId, node]);
+			}
+			return (typeof setting.callback.onRightClick) != "function";
+		}
+	},
+	//method of tools for zTree
+	tools = {
+		apply: function(fun, param, defaultValue) {
+			if ((typeof fun) == "function") {
+				return fun.apply(zt, param?param:[]);
+			}
+			return defaultValue;
+		},
+		canAsync: function(setting, node) {
+			var childKey = setting.data.key.children;
+			return (setting.async.enable && node && node.isParent && !(node.zAsync || (node[childKey] && node[childKey].length > 0)));
+		},
+		clone: function (obj){
+			if (obj === null) return null;
+			var o = obj.constructor === Array ? [] : {};
+			for(var i in obj){
+				o[i] = (obj[i] instanceof Date) ? new Date(obj[i].getTime()) : (typeof obj[i] === "object" ? arguments.callee(obj[i]) : obj[i]);
+			}
+			return o;
+		},
+		eqs: function(str1, str2) {
+			return str1.toLowerCase() === str2.toLowerCase();
+		},
+		isArray: function(arr) {
+			return Object.prototype.toString.apply(arr) === "[object Array]";
+		},
+		getMDom: function (setting, curDom, targetExpr) {
+			if (!curDom) return null;
+			while (curDom && curDom.id !== setting.treeId) {
+				for (var i=0, l=targetExpr.length; curDom.tagName && i<l; i++) {
+					if (tools.eqs(curDom.tagName, targetExpr[i].tagName) && curDom.getAttribute(targetExpr[i].attrName) !== null) {
+						return curDom;
+					}
+				}
+				curDom = curDom.parentNode;
+			}
+			return null;
+		},
+		uCanDo: function(setting, e) {
+			return true;
+		}
+	},
+	//method of operate ztree dom
+	view = {
+		addNodes: function(setting, parentNode, newNodes, isSilent) {
+			if (setting.data.keep.leaf && parentNode && !parentNode.isParent) {
+				return;
+			}
+			if (!tools.isArray(newNodes)) {
+				newNodes = [newNodes];
+			}
+			if (setting.data.simpleData.enable) {
+				newNodes = data.transformTozTreeFormat(setting, newNodes);
+			}
+			if (parentNode) {
+				var target_switchObj = $("#" + parentNode.tId + consts.id.SWITCH),
+				target_icoObj = $("#" + parentNode.tId + consts.id.ICON),
+				target_ulObj = $("#" + parentNode.tId + consts.id.UL);
+
+				if (!parentNode.open) {
+					view.replaceSwitchClass(parentNode, target_switchObj, consts.folder.CLOSE);
+					view.replaceIcoClass(parentNode, target_icoObj, consts.folder.CLOSE);
+					parentNode.open = false;
+					target_ulObj.css({
+						"display": "none"
+					});
+				}
+
+				data.addNodesData(setting, parentNode, newNodes);
+				view.createNodes(setting, parentNode.level + 1, newNodes, parentNode);
+				if (!isSilent) {
+					view.expandCollapseParentNode(setting, parentNode, true);
+				}
+			} else {
+				data.addNodesData(setting, data.getRoot(setting), newNodes);
+				view.createNodes(setting, 0, newNodes, null);
+			}
+		},
+		appendNodes: function(setting, level, nodes, parentNode, initFlag, openFlag) {
+			if (!nodes) return [];
+			var html = [],
+			childKey = setting.data.key.children;
+			for (var i = 0, l = nodes.length; i < l; i++) {
+				var node = nodes[i];
+				if (initFlag) {
+					var tmpPNode = (parentNode) ? parentNode: data.getRoot(setting),
+					tmpPChild = tmpPNode[childKey],
+					isFirstNode = ((tmpPChild.length == nodes.length) && (i == 0)),
+					isLastNode = (i == (nodes.length - 1));
+					data.initNode(setting, level, node, parentNode, isFirstNode, isLastNode, openFlag);
+					data.addNodeCache(setting, node);
+				}
+
+				var childHtml = [];
+				if (node[childKey] && node[childKey].length > 0) {
+					//make child html first, because checkType
+					childHtml = view.appendNodes(setting, level + 1, node[childKey], node, initFlag, openFlag && node.open);
+				}
+				if (openFlag) {
+					
+					view.makeDOMNodeMainBefore(html, setting, node);
+					view.makeDOMNodeLine(html, setting, node);
+					data.getBeforeA(setting, node, html);
+					view.makeDOMNodeNameBefore(html, setting, node);
+					data.getInnerBeforeA(setting, node, html);
+					view.makeDOMNodeIcon(html, setting, node);
+					data.getInnerAfterA(setting, node, html);
+					view.makeDOMNodeNameAfter(html, setting, node);
+					data.getAfterA(setting, node, html);
+					if (node.isParent && node.open) {
+						view.makeUlHtml(setting, node, html, childHtml.join(''));
+					}
+					view.makeDOMNodeMainAfter(html, setting, node);
+					data.addCreatedNode(setting, node);
+				}
+			}
+			return html;
+		},
+		appendParentULDom: function(setting, node) {
+			var html = [],
+			nObj = $("#" + node.tId),
+			ulObj = $("#" + node.tId + consts.id.UL),
+			childKey = setting.data.key.children,
+			childHtml = view.appendNodes(setting, node.level+1, node[childKey], node, false, true);
+			view.makeUlHtml(setting, node, html, childHtml.join(''));
+			if (!nObj.get(0) && !!node.parentTId) {
+				view.appendParentULDom(setting, node.getParentNode());
+				nObj = $("#" + node.tId);
+			}
+			if (ulObj.get(0)) {
+				ulObj.remove();
+			}
+			nObj.append(html.join(''));
+		},
+		asyncNode: function(setting, node, isSilent, callback) {
+			var i, l;
+			if (node && !node.isParent) {
+				tools.apply(callback);
+				return false;
+			} else if (node && node.isAjaxing) {
+				return false;
+			} else if (tools.apply(setting.callback.beforeAsync, [setting.treeId, node], true) == false) {
+				tools.apply(callback);
+				return false;
+			}
+			if (node) {
+				node.isAjaxing = true;
+				var icoObj = $("#" + node.tId + consts.id.ICON);
+				icoObj.attr({"style":"", "class":consts.className.BUTTON + " " + consts.className.ICO_LOADING});
+			}
+
+			var tmpParam = {};
+			for (i = 0, l = setting.async.autoParam.length; node && i < l; i++) {
+				var pKey = setting.async.autoParam[i].split("="), spKey = pKey;
+				if (pKey.length>1) {
+					spKey = pKey[1];
+					pKey = pKey[0];
+				}
+				tmpParam[spKey] = node[pKey];
+			}
+			if (tools.isArray(setting.async.otherParam)) {
+				for (i = 0, l = setting.async.otherParam.length; i < l; i += 2) {
+					tmpParam[setting.async.otherParam[i]] = setting.async.otherParam[i + 1];
+				}
+			} else {
+				for (var p in setting.async.otherParam) {
+					tmpParam[p] = setting.async.otherParam[p];
+				}
+			}
+
+			var _tmpV = data.getRoot(setting)._ver;
+			$.ajax({
+				contentType: setting.async.contentType,
+				type: setting.async.type,
+				url: tools.apply(setting.async.url, [setting.treeId, node], setting.async.url),
+				data: tmpParam,
+				dataType: setting.async.dataType,
+				success: function(msg) {
+					if (_tmpV != data.getRoot(setting)._ver) {
+						return;
+					}
+					var newNodes = [];
+					try {
+						if (!msg || msg.length == 0) {
+							newNodes = [];
+						} else if (typeof msg == "string") {
+							newNodes = eval("(" + msg + ")");
+						} else {
+							newNodes = msg;
+						}
+					} catch(err) {
+						newNodes = msg;
+					}
+
+					if (node) {
+						node.isAjaxing = null;
+						node.zAsync = true;
+					}
+					view.setNodeLineIcos(setting, node);
+					if (newNodes && newNodes !== "") {
+						newNodes = tools.apply(setting.async.dataFilter, [setting.treeId, node, newNodes], newNodes);
+						view.addNodes(setting, node, !!newNodes ? tools.clone(newNodes) : [], !!isSilent);
+					} else {
+						view.addNodes(setting, node, [], !!isSilent);
+					}
+					setting.treeObj.trigger(consts.event.ASYNC_SUCCESS, [setting.treeId, node, msg]);
+					tools.apply(callback);
+				},
+				error: function(XMLHttpRequest, textStatus, errorThrown) {
+					if (_tmpV != data.getRoot(setting)._ver) {
+						return;
+					}
+					if (node) node.isAjaxing = null;
+					view.setNodeLineIcos(setting, node);
+					setting.treeObj.trigger(consts.event.ASYNC_ERROR, [setting.treeId, node, XMLHttpRequest, textStatus, errorThrown]);
+				}
+			});
+			return true;
+		},
+		cancelPreSelectedNode: function (setting, node) {
+			var list = data.getRoot(setting).curSelectedList;
+			for (var i=0, j=list.length-1; j>=i; j--) {
+				if (!node || node === list[j]) {
+					$("#" + list[j].tId + consts.id.A).removeClass(consts.node.CURSELECTED);
+					if (node) {
+						data.removeSelectedNode(setting, node);
+						break;
+					}
+				}
+			}
+			if (!node) data.getRoot(setting).curSelectedList = [];
+		},
+		createNodeCallback: function(setting) {
+			if (!!setting.callback.onNodeCreated || !!setting.view.addDiyDom) {
+				var root = data.getRoot(setting);
+				while (root.createdNodes.length>0) {
+					var node = root.createdNodes.shift();
+					tools.apply(setting.view.addDiyDom, [setting.treeId, node]);
+					if (!!setting.callback.onNodeCreated) {
+						setting.treeObj.trigger(consts.event.NODECREATED, [setting.treeId, node]);
+					}
+				}
+			}
+		},
+		createNodes: function(setting, level, nodes, parentNode) {
+			if (!nodes || nodes.length == 0) return;
+			var root = data.getRoot(setting),
+			childKey = setting.data.key.children,
+			openFlag = !parentNode || parentNode.open || !!$("#" + parentNode[childKey][0].tId).get(0);
+			root.createdNodes = [];
+			var zTreeHtml = view.appendNodes(setting, level, nodes, parentNode, true, openFlag);
+			if (!parentNode) {
+				setting.treeObj.append(zTreeHtml.join(''));
+			} else {
+				var ulObj = $("#" + parentNode.tId + consts.id.UL);
+				if (ulObj.get(0)) {
+					ulObj.append(zTreeHtml.join(''));
+				}
+			}
+			view.createNodeCallback(setting);
+		},
+		destroy: function(setting) {
+			if (!setting) return;
+			data.initCache(setting);
+			data.initRoot(setting);
+			event.unbindTree(setting);
+			event.unbindEvent(setting);
+			setting.treeObj.empty();
+		},
+		expandCollapseNode: function(setting, node, expandFlag, animateFlag, callback) {
+			var root = data.getRoot(setting),
+			childKey = setting.data.key.children;
+			if (!node) {
+				tools.apply(callback, []);
+				return;
+			}
+			if (root.expandTriggerFlag) {
+				var _callback = callback;
+				callback = function(){
+					if (_callback) _callback();
+					if (node.open) {
+						setting.treeObj.trigger(consts.event.EXPAND, [setting.treeId, node]);
+					} else {
+						setting.treeObj.trigger(consts.event.COLLAPSE, [setting.treeId, node]);
+					}
+				};
+				root.expandTriggerFlag = false;
+			}
+			if (!node.open && node.isParent && ((!$("#" + node.tId + consts.id.UL).get(0)) || (node[childKey] && node[childKey].length>0 && !$("#" + node[childKey][0].tId).get(0)))) {
+				view.appendParentULDom(setting, node);
+				view.createNodeCallback(setting);
+			}
+			if (node.open == expandFlag) {
+				tools.apply(callback, []);
+				return;
+			}
+			var ulObj = $("#" + node.tId + consts.id.UL),
+			switchObj = $("#" + node.tId + consts.id.SWITCH),
+			icoObj = $("#" + node.tId + consts.id.ICON);
+
+			if (node.isParent) {
+				node.open = !node.open;
+				if (node.iconOpen && node.iconClose) {
+					icoObj.attr("style", view.makeNodeIcoStyle(setting, node));
+				}
+
+				if (node.open) {
+					view.replaceSwitchClass(node, switchObj, consts.folder.OPEN);
+					view.replaceIcoClass(node, icoObj, consts.folder.OPEN);
+					if (animateFlag == false || setting.view.expandSpeed == "") {
+						ulObj.show();
+						tools.apply(callback, []);
+					} else {
+						if (node[childKey] && node[childKey].length > 0) {
+							ulObj.slideDown(setting.view.expandSpeed, callback);
+						} else {
+							ulObj.show();
+							tools.apply(callback, []);
+						}
+					}
+				} else {
+					view.replaceSwitchClass(node, switchObj, consts.folder.CLOSE);
+					view.replaceIcoClass(node, icoObj, consts.folder.CLOSE);
+					if (animateFlag == false || setting.view.expandSpeed == "" || !(node[childKey] && node[childKey].length > 0)) {
+						ulObj.hide();
+						tools.apply(callback, []);
+					} else {
+						ulObj.slideUp(setting.view.expandSpeed, callback);
+					}
+				}
+			} else {
+				tools.apply(callback, []);
+			}
+		},
+		expandCollapseParentNode: function(setting, node, expandFlag, animateFlag, callback) {
+			if (!node) return;
+			if (!node.parentTId) {
+				view.expandCollapseNode(setting, node, expandFlag, animateFlag, callback);
+				return;
+			} else {
+				view.expandCollapseNode(setting, node, expandFlag, animateFlag);
+			}
+			if (node.parentTId) {
+				view.expandCollapseParentNode(setting, node.getParentNode(), expandFlag, animateFlag, callback);
+			}
+		},
+		expandCollapseSonNode: function(setting, node, expandFlag, animateFlag, callback) {
+			var root = data.getRoot(setting),
+			childKey = setting.data.key.children,
+			treeNodes = (node) ? node[childKey]: root[childKey],
+			selfAnimateSign = (node) ? false : animateFlag,
+			expandTriggerFlag = data.getRoot(setting).expandTriggerFlag;
+			data.getRoot(setting).expandTriggerFlag = false;
+			if (treeNodes) {
+				for (var i = 0, l = treeNodes.length; i < l; i++) {
+					if (treeNodes[i]) view.expandCollapseSonNode(setting, treeNodes[i], expandFlag, selfAnimateSign);
+				}
+			}
+			data.getRoot(setting).expandTriggerFlag = expandTriggerFlag;
+			view.expandCollapseNode(setting, node, expandFlag, animateFlag, callback );
+		},
+		makeDOMNodeIcon: function(html, setting, node) {
+			var nameStr = data.getNodeName(setting, node),
+			name = setting.view.nameIsHTML ? nameStr : nameStr.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
+			html.push("<span id='", node.tId, consts.id.ICON,
+				"' title='' treeNode", consts.id.ICON," class='", view.makeNodeIcoClass(setting, node),
+				"' style='", view.makeNodeIcoStyle(setting, node), "'></span><span id='", node.tId, consts.id.SPAN,
+				"'>",name,"</span>");
+		},
+		makeDOMNodeLine: function(html, setting, node) {
+			html.push("<span id='", node.tId, consts.id.SWITCH,	"' title='' class='", view.makeNodeLineClass(setting, node), "' treeNode", consts.id.SWITCH,"></span>");
+		},
+		makeDOMNodeMainAfter: function(html, setting, node) {
+			html.push("</li>");
+		},
+		makeDOMNodeMainBefore: function(html, setting, node) {
+			html.push("<li id='", node.tId, "' class='", consts.className.LEVEL, node.level,"' tabindex='0' hidefocus='true' treenode>");
+		},
+		makeDOMNodeNameAfter: function(html, setting, node) {
+			html.push("</a>");
+		},
+		makeDOMNodeNameBefore: function(html, setting, node) {
+			var title = data.getNodeTitle(setting, node),
+			url = view.makeNodeUrl(setting, node),
+			fontcss = view.makeNodeFontCss(setting, node),
+			fontStyle = [];
+			for (var f in fontcss) {
+				fontStyle.push(f, ":", fontcss[f], ";");
+			}
+			html.push("<a id='", node.tId, consts.id.A, "' class='", consts.className.LEVEL, node.level,"' treeNode", consts.id.A," onclick=\"", (node.click || ''),
+				"\" ", ((url != null && url.length > 0) ? "href='" + url + "'" : ""), " target='",view.makeNodeTarget(node),"' style='", fontStyle.join(''),
+				"'");
+			if (tools.apply(setting.view.showTitle, [setting.treeId, node], setting.view.showTitle) && title) {html.push("title='", title.replace(/'/g,"&#39;").replace(/</g,'&lt;').replace(/>/g,'&gt;'),"'");}
+			html.push(">");
+		},
+		makeNodeFontCss: function(setting, node) {
+			var fontCss = tools.apply(setting.view.fontCss, [setting.treeId, node], setting.view.fontCss);
+			return (fontCss && ((typeof fontCss) != "function")) ? fontCss : {};
+		},
+		makeNodeIcoClass: function(setting, node) {
+			var icoCss = ["ico"];
+			if (!node.isAjaxing) {
+				icoCss[0] = (node.iconSkin ? node.iconSkin + "_" : "") + icoCss[0];
+				if (node.isParent) {
+					icoCss.push(node.open ? consts.folder.OPEN : consts.folder.CLOSE);
+				} else {
+					icoCss.push(consts.folder.DOCU);
+				}
+			}
+			return consts.className.BUTTON + " " + icoCss.join('_');
+		},
+		makeNodeIcoStyle: function(setting, node) {
+			var icoStyle = [];
+			if (!node.isAjaxing) {
+				var icon = (node.isParent && node.iconOpen && node.iconClose) ? (node.open ? node.iconOpen : node.iconClose) : node.icon;
+				if (icon) icoStyle.push("background:url(", icon, ") 0 0 no-repeat;");
+				if (setting.view.showIcon == false || !tools.apply(setting.view.showIcon, [setting.treeId, node], true)) {
+					icoStyle.push("width:0px;height:0px;");
+				}
+			}
+			return icoStyle.join('');
+		},
+		makeNodeLineClass: function(setting, node) {
+			var lineClass = [];
+			if (setting.view.showLine) {
+				if (node.level == 0 && node.isFirstNode && node.isLastNode) {
+					lineClass.push(consts.line.ROOT);
+				} else if (node.level == 0 && node.isFirstNode) {
+					lineClass.push(consts.line.ROOTS);
+				} else if (node.isLastNode) {
+					lineClass.push(consts.line.BOTTOM);
+				} else {
+					lineClass.push(consts.line.CENTER);
+				}
+			} else {
+				lineClass.push(consts.line.NOLINE);
+			}
+			if (node.isParent) {
+				lineClass.push(node.open ? consts.folder.OPEN : consts.folder.CLOSE);
+			} else {
+				lineClass.push(consts.folder.DOCU);
+			}
+			return view.makeNodeLineClassEx(node) + lineClass.join('_');
+		},
+		makeNodeLineClassEx: function(node) {
+			return consts.className.BUTTON + " " + consts.className.LEVEL + node.level + " " + consts.className.SWITCH + " ";
+		},
+		makeNodeTarget: function(node) {
+			return (node.target || "_blank");
+		},
+		makeNodeUrl: function(setting, node) {
+			var urlKey = setting.data.key.url;
+			return node[urlKey] ? node[urlKey] : null;
+		},
+		makeUlHtml: function(setting, node, html, content) {
+			html.push("<ul id='", node.tId, consts.id.UL, "' class='", consts.className.LEVEL, node.level, " ", view.makeUlLineClass(setting, node), "' style='display:", (node.open ? "block": "none"),"'>");
+			html.push(content);
+			html.push("</ul>");
+		},
+		makeUlLineClass: function(setting, node) {
+			return ((setting.view.showLine && !node.isLastNode) ? consts.line.LINE : "");
+		},
+		removeChildNodes: function(setting, node) {
+			if (!node) return;
+			var childKey = setting.data.key.children,
+			nodes = node[childKey];
+			if (!nodes) return;
+
+			for (var i = 0, l = nodes.length; i < l; i++) {
+				data.removeNodeCache(setting, nodes[i]);
+			}
+			data.removeSelectedNode(setting);
+			delete node[childKey];
+
+			if (!setting.data.keep.parent) {
+				node.isParent = false;
+				node.open = false;
+				var tmp_switchObj = $("#" + node.tId + consts.id.SWITCH),
+				tmp_icoObj = $("#" + node.tId + consts.id.ICON);
+				view.replaceSwitchClass(node, tmp_switchObj, consts.folder.DOCU);
+				view.replaceIcoClass(node, tmp_icoObj, consts.folder.DOCU);
+				$("#" + node.tId + consts.id.UL).remove();
+			} else {
+				$("#" + node.tId + consts.id.UL).empty();
+			}
+		},
+		setFirstNode: function(setting, parentNode) {
+			var childKey = setting.data.key.children, childLength = parentNode[childKey].length;
+			if ( childLength > 0) {
+				parentNode[childKey][0].isFirstNode = true;
+			}
+		},
+		setLastNode: function(setting, parentNode) {
+			var childKey = setting.data.key.children, childLength = parentNode[childKey].length;
+			if ( childLength > 0) {
+				parentNode[childKey][childLength - 1].isLastNode = true;
+			}
+		},
+		removeNode: function(setting, node) {
+			var root = data.getRoot(setting),
+			childKey = setting.data.key.children,
+			parentNode = (node.parentTId) ? node.getParentNode() : root;
+
+			node.isFirstNode = false;
+			node.isLastNode = false;
+			node.getPreNode = function() {return null;};
+			node.getNextNode = function() {return null;};
+
+			if (!data.getNodeCache(setting, node.tId)) {
+				return;
+			}
+                        
+			$("#" + node.tId).remove();
+			data.removeNodeCache(setting, node);
+			data.removeSelectedNode(setting, node);
+
+			for (var i = 0, l = parentNode[childKey].length; i < l; i++) {
+				if (parentNode[childKey][i].tId == node.tId) {
+					parentNode[childKey].splice(i, 1);
+					break;
+				}
+			}
+			view.setFirstNode(setting, parentNode);
+			view.setLastNode(setting, parentNode);
+                                                
+			var tmp_ulObj,tmp_switchObj,tmp_icoObj,
+			childLength = parentNode[childKey].length;
+
+			//repair nodes old parent
+			if (!setting.data.keep.parent && childLength == 0) {
+				//old parentNode has no child nodes
+				parentNode.isParent = false;
+				parentNode.open = false;
+				tmp_ulObj = $("#" + parentNode.tId + consts.id.UL);
+				tmp_switchObj = $("#" + parentNode.tId + consts.id.SWITCH);
+				tmp_icoObj = $("#" + parentNode.tId + consts.id.ICON);
+				view.replaceSwitchClass(parentNode, tmp_switchObj, consts.folder.DOCU);
+				view.replaceIcoClass(parentNode, tmp_icoObj, consts.folder.DOCU);
+				tmp_ulObj.css("display", "none");
+
+			} else if (setting.view.showLine && childLength > 0) {
+				//old parentNode has child nodes
+				var newLast = parentNode[childKey][childLength - 1];
+				tmp_ulObj = $("#" + newLast.tId + consts.id.UL);
+				tmp_switchObj = $("#" + newLast.tId + consts.id.SWITCH);
+				tmp_icoObj = $("#" + newLast.tId + consts.id.ICON);
+				if (parentNode == root) {
+					if (parentNode[childKey].length == 1) {
+						//node was root, and ztree has only one root after move node
+						view.replaceSwitchClass(newLast, tmp_switchObj, consts.line.ROOT);
+					} else {
+						var tmp_first_switchObj = $("#" + parentNode[childKey][0].tId + consts.id.SWITCH);
+						view.replaceSwitchClass(parentNode[childKey][0], tmp_first_switchObj, consts.line.ROOTS);
+						view.replaceSwitchClass(newLast, tmp_switchObj, consts.line.BOTTOM);
+					}
+				} else {
+					view.replaceSwitchClass(newLast, tmp_switchObj, consts.line.BOTTOM);
+				}
+				tmp_ulObj.removeClass(consts.line.LINE);
+			}
+		},
+		replaceIcoClass: function(node, obj, newName) {
+			if (!obj || node.isAjaxing) return;
+			var tmpName = obj.attr("class");
+			if (tmpName == undefined) return;
+			var tmpList = tmpName.split("_");
+			switch (newName) {
+				case consts.folder.OPEN:
+				case consts.folder.CLOSE:
+				case consts.folder.DOCU:
+					tmpList[tmpList.length-1] = newName;
+					break;
+			}
+			obj.attr("class", tmpList.join("_"));
+		},
+		replaceSwitchClass: function(node, obj, newName) {
+			if (!obj) return;
+			var tmpName = obj.attr("class");
+			if (tmpName == undefined) return;
+			var tmpList = tmpName.split("_");
+			switch (newName) {
+				case consts.line.ROOT:
+				case consts.line.ROOTS:
+				case consts.line.CENTER:
+				case consts.line.BOTTOM:
+				case consts.line.NOLINE:
+					tmpList[0] = view.makeNodeLineClassEx(node) + newName;
+					break;
+				case consts.folder.OPEN:
+				case consts.folder.CLOSE:
+				case consts.folder.DOCU:
+					tmpList[1] = newName;
+					break;
+			}
+			obj.attr("class", tmpList.join("_"));
+			if (newName !== consts.folder.DOCU) {
+				obj.removeAttr("disabled");
+			} else {
+				obj.attr("disabled", "disabled");
+			}
+		},
+		selectNode: function(setting, node, addFlag) {
+			if (!addFlag) {
+				view.cancelPreSelectedNode(setting);
+			}
+			$("#" + node.tId + consts.id.A).addClass(consts.node.CURSELECTED);
+			data.addSelectedNode(setting, node);
+		},
+		setNodeFontCss: function(setting, treeNode) {
+			var aObj = $("#" + treeNode.tId + consts.id.A),
+			fontCss = view.makeNodeFontCss(setting, treeNode);
+			if (fontCss) {
+				aObj.css(fontCss);
+			}
+		},
+		setNodeLineIcos: function(setting, node) {
+			if (!node) return;
+			var switchObj = $("#" + node.tId + consts.id.SWITCH),
+			ulObj = $("#" + node.tId + consts.id.UL),
+			icoObj = $("#" + node.tId + consts.id.ICON),
+			ulLine = view.makeUlLineClass(setting, node);
+			if (ulLine.length==0) {
+				ulObj.removeClass(consts.line.LINE);
+			} else {
+				ulObj.addClass(ulLine);
+			}
+			switchObj.attr("class", view.makeNodeLineClass(setting, node));
+			if (node.isParent) {
+				switchObj.removeAttr("disabled");
+			} else {
+				switchObj.attr("disabled", "disabled");
+			}
+			icoObj.removeAttr("style");
+			icoObj.attr("style", view.makeNodeIcoStyle(setting, node));
+			icoObj.attr("class", view.makeNodeIcoClass(setting, node));
+		},
+		setNodeName: function(setting, node) {
+			var title = data.getNodeTitle(setting, node),
+			nObj = $("#" + node.tId + consts.id.SPAN);
+			nObj.empty();
+			if (setting.view.nameIsHTML) {
+				nObj.html(data.getNodeName(setting, node));
+			} else {
+				nObj.text(data.getNodeName(setting, node));
+			}
+			if (tools.apply(setting.view.showTitle, [setting.treeId, node], setting.view.showTitle)) {
+				var aObj = $("#" + node.tId + consts.id.A);
+				aObj.attr("title", !title ? "" : title);
+			}
+		},
+		setNodeTarget: function(node) {
+			var aObj = $("#" + node.tId + consts.id.A);
+			aObj.attr("target", view.makeNodeTarget(node));
+		},
+		setNodeUrl: function(setting, node) {
+			var aObj = $("#" + node.tId + consts.id.A),
+			url = view.makeNodeUrl(setting, node);
+			if (url == null || url.length == 0) {
+				aObj.removeAttr("href");
+			} else {
+				aObj.attr("href", url);
+			}
+		},
+		switchNode: function(setting, node) {
+			if (node.open || !tools.canAsync(setting, node)) {
+				view.expandCollapseNode(setting, node, !node.open);
+			} else if (setting.async.enable) {
+				if (!view.asyncNode(setting, node)) {
+					view.expandCollapseNode(setting, node, !node.open);
+					return;
+				}
+			} else if (node) {
+				view.expandCollapseNode(setting, node, !node.open);
+			}
+		}
+	};
+	// zTree defind
+	$.fn.zTree = {
+		consts : _consts,
+		_z : {
+			tools: tools,
+			view: view,
+			event: event,
+			data: data
+		},
+		getZTreeObj: function(treeId) {
+			var o = data.getZTreeTools(treeId);
+			return o ? o : null;
+		},
+		destroy: function(treeId) {
+			if (!!treeId && treeId.length > 0) {
+				view.destroy(data.getSetting(treeId));
+			} else {
+				for(var s in settings) {
+					view.destroy(settings[s]);
+				}
+			}
+		},
+		init: function(obj, zSetting, zNodes) {
+			var setting = tools.clone(_setting);
+			$.extend(true, setting, zSetting);
+			setting.treeId = obj.attr("id");
+			setting.treeObj = obj;
+			setting.treeObj.empty();
+			settings[setting.treeId] = setting;
+			//For some older browser,(e.g., ie6)
+			if(typeof document.body.style.maxHeight === "undefined") {
+				setting.view.expandSpeed = "";
+			}
+			data.initRoot(setting);
+			var root = data.getRoot(setting),
+			childKey = setting.data.key.children;
+			zNodes = zNodes ? tools.clone(tools.isArray(zNodes)? zNodes : [zNodes]) : [];
+			if (setting.data.simpleData.enable) {
+				root[childKey] = data.transformTozTreeFormat(setting, zNodes);
+			} else {
+				root[childKey] = zNodes;
+			}
+
+			data.initCache(setting);
+			event.unbindTree(setting);
+			event.bindTree(setting);
+			event.unbindEvent(setting);
+			event.bindEvent(setting);
+			
+			var zTreeTools = {
+				setting : setting,
+				addNodes : function(parentNode, newNodes, isSilent) {
+					if (!newNodes) return null;
+					if (!parentNode) parentNode = null;
+					if (parentNode && !parentNode.isParent && setting.data.keep.leaf) return null;
+					var xNewNodes = tools.clone(tools.isArray(newNodes)? newNodes: [newNodes]);
+					function addCallback() {
+						view.addNodes(setting, parentNode, xNewNodes, (isSilent==true));
+					}
+
+					if (tools.canAsync(setting, parentNode)) {
+						view.asyncNode(setting, parentNode, isSilent, addCallback);
+					} else {
+						addCallback();
+					}
+					return xNewNodes;
+				},
+				cancelSelectedNode : function(node) {
+					view.cancelPreSelectedNode(this.setting, node);
+				},
+				destroy : function() {
+					view.destroy(this.setting);
+				},
+				expandAll : function(expandFlag) {
+					expandFlag = !!expandFlag;
+					view.expandCollapseSonNode(this.setting, null, expandFlag, true);
+					return expandFlag;
+				},
+				expandNode : function(node, expandFlag, sonSign, focus, callbackFlag) {
+					if (!node || !node.isParent) return null;
+					if (expandFlag !== true && expandFlag !== false) {
+						expandFlag = !node.open;
+					}
+					callbackFlag = !!callbackFlag;
+
+					if (callbackFlag && expandFlag && (tools.apply(setting.callback.beforeExpand, [setting.treeId, node], true) == false)) {
+						return null;
+					} else if (callbackFlag && !expandFlag && (tools.apply(setting.callback.beforeCollapse, [setting.treeId, node], true) == false)) {
+						return null;
+					}
+					if (expandFlag && node.parentTId) {
+						view.expandCollapseParentNode(this.setting, node.getParentNode(), expandFlag, false);
+					}
+					if (expandFlag === node.open && !sonSign) {
+						return null;
+					}
+					
+					data.getRoot(setting).expandTriggerFlag = callbackFlag;
+					if (sonSign) {
+						view.expandCollapseSonNode(this.setting, node, expandFlag, true, function() {
+							if (focus !== false) {try{$("#" + node.tId).focus().blur();}catch(e){}}
+						});
+					} else {
+						node.open = !expandFlag;
+						view.switchNode(this.setting, node);
+						if (focus !== false) {try{$("#" + node.tId).focus().blur();}catch(e){}}
+					}
+					return expandFlag;
+				},
+				getNodes : function() {
+					return data.getNodes(this.setting);
+				},
+				getNodeByParam : function(key, value, parentNode) {
+					if (!key) return null;
+					return data.getNodeByParam(this.setting, parentNode?parentNode[this.setting.data.key.children]:data.getNodes(this.setting), key, value);
+				},
+				getNodeByTId : function(tId) {
+					return data.getNodeCache(this.setting, tId);
+				},
+				getNodesByParam : function(key, value, parentNode) {
+					if (!key) return null;
+					return data.getNodesByParam(this.setting, parentNode?parentNode[this.setting.data.key.children]:data.getNodes(this.setting), key, value);
+				},
+				getNodesByParamFuzzy : function(key, value, parentNode) {
+					if (!key) return null;
+					return data.getNodesByParamFuzzy(this.setting, parentNode?parentNode[this.setting.data.key.children]:data.getNodes(this.setting), key, value);
+				},
+				getNodesByFilter: function(filter, isSingle, parentNode, invokeParam) {
+					isSingle = !!isSingle;
+					if (!filter || (typeof filter != "function")) return (isSingle ? null : []);
+					return data.getNodesByFilter(this.setting, parentNode?parentNode[this.setting.data.key.children]:data.getNodes(this.setting), filter, isSingle, invokeParam);
+				},
+				getNodeIndex : function(node) {
+					if (!node) return null;
+					var childKey = setting.data.key.children,
+					parentNode = (node.parentTId) ? node.getParentNode() : data.getRoot(this.setting);
+					for (var i=0, l = parentNode[childKey].length; i < l; i++) {
+						if (parentNode[childKey][i] == node) return i;
+					}
+					return -1;
+				},
+				getSelectedNodes : function() {
+					var r = [], list = data.getRoot(this.setting).curSelectedList;
+					for (var i=0, l=list.length; i<l; i++) {
+						r.push(list[i]);
+					}
+					return r;
+				},
+				isSelectedNode : function(node) {
+					return data.isSelectedNode(this.setting, node);
+				},
+				reAsyncChildNodes : function(parentNode, reloadType, isSilent) {
+					if (!this.setting.async.enable) return;
+					var isRoot = !parentNode;
+					if (isRoot) {
+						parentNode = data.getRoot(this.setting);
+					}
+					if (reloadType=="refresh") {
+						var childKey = this.setting.data.key.children;
+						for (var i = 0, l = parentNode[childKey] ? parentNode[childKey].length : 0; i < l; i++) {
+							data.removeNodeCache(setting, parentNode[childKey][i]);
+						}
+						data.removeSelectedNode(setting);
+						parentNode[childKey] = [];
+						if (isRoot) {
+							this.setting.treeObj.empty();
+						} else {
+							var ulObj = $("#" + parentNode.tId + consts.id.UL);
+							ulObj.empty();
+						}
+					}
+					view.asyncNode(this.setting, isRoot? null:parentNode, !!isSilent);
+				},
+				refresh : function() {
+					this.setting.treeObj.empty();
+					var root = data.getRoot(this.setting),
+					nodes = root[this.setting.data.key.children]
+					data.initRoot(this.setting);
+					root[this.setting.data.key.children] = nodes
+					data.initCache(this.setting);
+					view.createNodes(this.setting, 0, root[this.setting.data.key.children]);
+				},
+				removeChildNodes : function(node) {
+					if (!node) return null;
+					var childKey = setting.data.key.children,
+					nodes = node[childKey];
+					view.removeChildNodes(setting, node);
+					return nodes ? nodes : null;
+				},
+				removeNode : function(node, callbackFlag) {
+					if (!node) return;
+					callbackFlag = !!callbackFlag;
+					if (callbackFlag && tools.apply(setting.callback.beforeRemove, [setting.treeId, node], true) == false) return;
+					view.removeNode(setting, node);
+					if (callbackFlag) {
+						this.setting.treeObj.trigger(consts.event.REMOVE, [setting.treeId, node]);
+					}
+				},
+				selectNode : function(node, addFlag) {
+					if (!node) return;
+					if (tools.uCanDo(this.setting)) {
+						addFlag = setting.view.selectedMulti && addFlag;
+						if (node.parentTId) {
+							view.expandCollapseParentNode(this.setting, node.getParentNode(), true, false, function() {
+								try{$("#" + node.tId).focus().blur();}catch(e){}
+							});
+						} else {
+							try{$("#" + node.tId).focus().blur();}catch(e){}
+						}
+						view.selectNode(this.setting, node, addFlag);
+					}
+				},
+				transformTozTreeNodes : function(simpleNodes) {
+					return data.transformTozTreeFormat(this.setting, simpleNodes);
+				},
+				transformToArray : function(nodes) {
+					return data.transformToArrayFormat(this.setting, nodes);
+				},
+				updateNode : function(node, checkTypeFlag) {
+					if (!node) return;
+					var nObj = $("#" + node.tId);
+					if (nObj.get(0) && tools.uCanDo(this.setting)) {
+						view.setNodeName(this.setting, node);
+						view.setNodeTarget(node);
+						view.setNodeUrl(this.setting, node);
+						view.setNodeLineIcos(this.setting, node);
+						view.setNodeFontCss(this.setting, node);
+					}
+				}
+			}
+			root.treeTools = zTreeTools;
+			data.setZTreeTools(setting, zTreeTools);
+
+			if (root[childKey] && root[childKey].length > 0) {
+				view.createNodes(setting, 0, root[childKey]);
+			} else if (setting.async.enable && setting.async.url && setting.async.url !== '') {
+				view.asyncNode(setting);
+			}
+			return zTreeTools;
+		}
+	};
+
+	var zt = $.fn.zTree,
+	consts = zt.consts;
+})(jQuery);
+/*
+ * JQuery zTree excheck 3.5.12
+ * http://zTree.me/
+ *
+ * Copyright (c) 2010 Hunter.z
+ *
+ * Licensed same as jquery - MIT License
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ * email: hunter.z@263.net
+ * Date: 2013-03-11
+ */
+(function($){
+	//default consts of excheck
+	var _consts = {
+		event: {
+			CHECK: "ztree_check"
+		},
+		id: {
+			CHECK: "_check"
+		},
+		checkbox: {
+			STYLE: "checkbox",
+			DEFAULT: "chk",
+			DISABLED: "disable",
+			FALSE: "false",
+			TRUE: "true",
+			FULL: "full",
+			PART: "part",
+			FOCUS: "focus"
+		},
+		radio: {
+			STYLE: "radio",
+			TYPE_ALL: "all",
+			TYPE_LEVEL: "level"
+		}
+	},
+	//default setting of excheck
+	_setting = {
+		check: {
+			enable: false,
+			autoCheckTrigger: false,
+			chkStyle: _consts.checkbox.STYLE,
+			nocheckInherit: false,
+			chkDisabledInherit: false,
+			radioType: _consts.radio.TYPE_LEVEL,
+			chkboxType: {
+				"Y": "ps",
+				"N": "ps"
+			}
+		},
+		data: {
+			key: {
+				checked: "checked"
+			}
+		},
+		callback: {
+			beforeCheck:null,
+			onCheck:null
+		}
+	},
+	//default root of excheck
+	_initRoot = function (setting) {
+		var r = data.getRoot(setting);
+		r.radioCheckedList = [];
+	},
+	//default cache of excheck
+	_initCache = function(treeId) {},
+	//default bind event of excheck
+	_bindEvent = function(setting) {
+		var o = setting.treeObj,
+		c = consts.event;
+		o.bind(c.CHECK, function (event, srcEvent, treeId, node) {
+			tools.apply(setting.callback.onCheck, [!!srcEvent?srcEvent : event, treeId, node]);
+		});
+	},
+	_unbindEvent = function(setting) {
+		var o = setting.treeObj,
+		c = consts.event;
+		o.unbind(c.CHECK);
+	},
+	//default event proxy of excheck
+	_eventProxy = function(e) {
+		var target = e.target,
+		setting = data.getSetting(e.data.treeId),
+		tId = "", node = null,
+		nodeEventType = "", treeEventType = "",
+		nodeEventCallback = null, treeEventCallback = null;
+
+		if (tools.eqs(e.type, "mouseover")) {
+			if (setting.check.enable && tools.eqs(target.tagName, "span") && target.getAttribute("treeNode"+ consts.id.CHECK) !== null) {
+				tId = target.parentNode.id;
+				nodeEventType = "mouseoverCheck";
+			}
+		} else if (tools.eqs(e.type, "mouseout")) {
+			if (setting.check.enable && tools.eqs(target.tagName, "span") && target.getAttribute("treeNode"+ consts.id.CHECK) !== null) {
+				tId = target.parentNode.id;
+				nodeEventType = "mouseoutCheck";
+			}
+		} else if (tools.eqs(e.type, "click")) {
+			if (setting.check.enable && tools.eqs(target.tagName, "span") && target.getAttribute("treeNode"+ consts.id.CHECK) !== null) {
+				tId = target.parentNode.id;
+				nodeEventType = "checkNode";
+			}
+		}
+		if (tId.length>0) {
+			node = data.getNodeCache(setting, tId);
+			switch (nodeEventType) {
+				case "checkNode" :
+					nodeEventCallback = _handler.onCheckNode;
+					break;
+				case "mouseoverCheck" :
+					nodeEventCallback = _handler.onMouseoverCheck;
+					break;
+				case "mouseoutCheck" :
+					nodeEventCallback = _handler.onMouseoutCheck;
+					break;
+			}
+		}
+		var proxyResult = {
+			stop: false,
+			node: node,
+			nodeEventType: nodeEventType,
+			nodeEventCallback: nodeEventCallback,
+			treeEventType: treeEventType,
+			treeEventCallback: treeEventCallback
+		};
+		return proxyResult
+	},
+	//default init node of excheck
+	_initNode = function(setting, level, n, parentNode, isFirstNode, isLastNode, openFlag) {
+		if (!n) return;
+		var checkedKey = setting.data.key.checked;
+		if (typeof n[checkedKey] == "string") n[checkedKey] = tools.eqs(n[checkedKey], "true");
+		n[checkedKey] = !!n[checkedKey];
+		n.checkedOld = n[checkedKey];
+		if (typeof n.nocheck == "string") n.nocheck = tools.eqs(n.nocheck, "true");
+		n.nocheck = !!n.nocheck || (setting.check.nocheckInherit && parentNode && !!parentNode.nocheck);
+		if (typeof n.chkDisabled == "string") n.chkDisabled = tools.eqs(n.chkDisabled, "true");
+		n.chkDisabled = !!n.chkDisabled || (setting.check.chkDisabledInherit && parentNode && !!parentNode.chkDisabled);
+		if (typeof n.halfCheck == "string") n.halfCheck = tools.eqs(n.halfCheck, "true");
+		n.halfCheck = !!n.halfCheck;
+		n.check_Child_State = -1;
+		n.check_Focus = false;
+		n.getCheckStatus = function() {return data.getCheckStatus(setting, n);};
+	},
+	//add dom for check
+	_beforeA = function(setting, node, html) {
+		var checkedKey = setting.data.key.checked;
+		if (setting.check.enable) {
+			data.makeChkFlag(setting, node);
+			if (setting.check.chkStyle == consts.radio.STYLE && setting.check.radioType == consts.radio.TYPE_ALL && node[checkedKey] ) {
+				var r = data.getRoot(setting);
+				r.radioCheckedList.push(node);
+			}
+			html.push("<span ID='", node.tId, consts.id.CHECK, "' class='", view.makeChkClass(setting, node), "' treeNode", consts.id.CHECK, (node.nocheck === true?" style='display:none;'":""),"></span>");
+		}
+	},
+	//update zTreeObj, add method of check
+	_zTreeTools = function(setting, zTreeTools) {
+		zTreeTools.checkNode = function(node, checked, checkTypeFlag, callbackFlag) {
+			var checkedKey = this.setting.data.key.checked;
+			if (node.chkDisabled === true) return;
+			if (checked !== true && checked !== false) {
+				checked = !node[checkedKey];
+			}
+			callbackFlag = !!callbackFlag;
+			
+			if (node[checkedKey] === checked && !checkTypeFlag) {
+				return;
+			} else if (callbackFlag && tools.apply(this.setting.callback.beforeCheck, [this.setting.treeId, node], true) == false) {
+				return;
+			}
+			if (tools.uCanDo(this.setting) && this.setting.check.enable && node.nocheck !== true) {
+				node[checkedKey] = checked;
+				var checkObj = $("#" + node.tId + consts.id.CHECK);
+				if (checkTypeFlag || this.setting.check.chkStyle === consts.radio.STYLE) view.checkNodeRelation(this.setting, node);
+				view.setChkClass(this.setting, checkObj, node);
+				view.repairParentChkClassWithSelf(this.setting, node);
+				if (callbackFlag) {
+					setting.treeObj.trigger(consts.event.CHECK, [null, setting.treeId, node]);
+				}
+			}
+		}
+
+		zTreeTools.checkAllNodes = function(checked) {
+			view.repairAllChk(this.setting, !!checked);
+		}
+
+		zTreeTools.getCheckedNodes = function(checked) {
+			var childKey = this.setting.data.key.children;
+			checked = (checked !== false);
+			return data.getTreeCheckedNodes(this.setting, data.getRoot(setting)[childKey], checked);
+		}
+
+		zTreeTools.getChangeCheckedNodes = function() {
+			var childKey = this.setting.data.key.children;
+			return data.getTreeChangeCheckedNodes(this.setting, data.getRoot(setting)[childKey]);
+		}
+
+		zTreeTools.setChkDisabled = function(node, disabled, inheritParent, inheritChildren) {
+			disabled = !!disabled;
+			inheritParent = !!inheritParent;
+			inheritChildren = !!inheritChildren;
+			view.repairSonChkDisabled(this.setting, node, disabled, inheritChildren);
+			view.repairParentChkDisabled(this.setting, node.getParentNode(), disabled, inheritParent);
+		}
+
+		var _updateNode = zTreeTools.updateNode;
+		zTreeTools.updateNode = function(node, checkTypeFlag) {
+			if (_updateNode) _updateNode.apply(zTreeTools, arguments);
+			if (!node || !this.setting.check.enable) return;
+			var nObj = $("#" + node.tId);
+			if (nObj.get(0) && tools.uCanDo(this.setting)) {
+				var checkObj = $("#" + node.tId + consts.id.CHECK);
+				if (checkTypeFlag == true || this.setting.check.chkStyle === consts.radio.STYLE) view.checkNodeRelation(this.setting, node);
+				view.setChkClass(this.setting, checkObj, node);
+				view.repairParentChkClassWithSelf(this.setting, node);
+			}
+		}
+	},
+	//method of operate data
+	_data = {
+		getRadioCheckedList: function(setting) {
+			var checkedList = data.getRoot(setting).radioCheckedList;
+			for (var i=0, j=checkedList.length; i<j; i++) {
+				if(!data.getNodeCache(setting, checkedList[i].tId)) {
+					checkedList.splice(i, 1);
+					i--; j--;
+				}
+			}
+			return checkedList;
+		},
+		getCheckStatus: function(setting, node) {
+			if (!setting.check.enable || node.nocheck || node.chkDisabled) return null;
+			var checkedKey = setting.data.key.checked,
+			r = {
+				checked: node[checkedKey],
+				half: node.halfCheck ? node.halfCheck : (setting.check.chkStyle == consts.radio.STYLE ? (node.check_Child_State === 2) : (node[checkedKey] ? (node.check_Child_State > -1 && node.check_Child_State < 2) : (node.check_Child_State > 0)))
+			};
+			return r;
+		},
+		getTreeCheckedNodes: function(setting, nodes, checked, results) {
+			if (!nodes) return [];
+			var childKey = setting.data.key.children,
+			checkedKey = setting.data.key.checked,
+			onlyOne = (checked && setting.check.chkStyle == consts.radio.STYLE && setting.check.radioType == consts.radio.TYPE_ALL);
+			results = !results ? [] : results;
+			for (var i = 0, l = nodes.length; i < l; i++) {
+				if (nodes[i].nocheck !== true && nodes[i].chkDisabled !== true && nodes[i][checkedKey] == checked) {
+					results.push(nodes[i]);
+					if(onlyOne) {
+						break;
+					}
+				}
+				data.getTreeCheckedNodes(setting, nodes[i][childKey], checked, results);
+				if(onlyOne && results.length > 0) {
+					break;
+				}
+			}
+			return results;
+		},
+		getTreeChangeCheckedNodes: function(setting, nodes, results) {
+			if (!nodes) return [];
+			var childKey = setting.data.key.children,
+			checkedKey = setting.data.key.checked;
+			results = !results ? [] : results;
+			for (var i = 0, l = nodes.length; i < l; i++) {
+				if (nodes[i].nocheck !== true && nodes[i].chkDisabled !== true && nodes[i][checkedKey] != nodes[i].checkedOld) {
+					results.push(nodes[i]);
+				}
+				data.getTreeChangeCheckedNodes(setting, nodes[i][childKey], results);
+			}
+			return results;
+		},
+		makeChkFlag: function(setting, node) {
+			if (!node) return;
+			var childKey = setting.data.key.children,
+			checkedKey = setting.data.key.checked,
+			chkFlag = -1;
+			if (node[childKey]) {
+				for (var i = 0, l = node[childKey].length; i < l; i++) {
+					var cNode = node[childKey][i];
+					var tmp = -1;
+					if (setting.check.chkStyle == consts.radio.STYLE) {
+						if (cNode.nocheck === true || cNode.chkDisabled === true) {
+							tmp = cNode.check_Child_State;
+						} else if (cNode.halfCheck === true) {
+							tmp = 2;
+						} else if (cNode[checkedKey]) {
+							tmp = 2;
+						} else {
+							tmp = cNode.check_Child_State > 0 ? 2:0;
+						}
+						if (tmp == 2) {
+							chkFlag = 2; break;
+						} else if (tmp == 0){
+							chkFlag = 0;
+						}
+					} else if (setting.check.chkStyle == consts.checkbox.STYLE) {
+						if (cNode.nocheck === true || cNode.chkDisabled === true) {
+							tmp = cNode.check_Child_State;
+						} else if (cNode.halfCheck === true) {
+							tmp = 1;
+						} else if (cNode[checkedKey] ) {
+							tmp = (cNode.check_Child_State === -1 || cNode.check_Child_State === 2) ? 2 : 1;
+						} else {
+							tmp = (cNode.check_Child_State > 0) ? 1 : 0;
+						}
+						if (tmp === 1) {
+							chkFlag = 1; break;
+						} else if (tmp === 2 && chkFlag > -1 && i > 0 && tmp !== chkFlag) {
+							chkFlag = 1; break;
+						} else if (chkFlag === 2 && tmp > -1 && tmp < 2) {
+							chkFlag = 1; break;
+						} else if (tmp > -1) {
+							chkFlag = tmp;
+						}
+					}
+				}
+			}
+			node.check_Child_State = chkFlag;
+		}
+	},
+	//method of event proxy
+	_event = {
+
+	},
+	//method of event handler
+	_handler = {
+		onCheckNode: function (event, node) {
+			if (node.chkDisabled === true) return false;
+			var setting = data.getSetting(event.data.treeId),
+			checkedKey = setting.data.key.checked;
+			if (tools.apply(setting.callback.beforeCheck, [setting.treeId, node], true) == false) return true;
+			node[checkedKey] = !node[checkedKey];
+			view.checkNodeRelation(setting, node);
+			var checkObj = $("#" + node.tId + consts.id.CHECK);
+			view.setChkClass(setting, checkObj, node);
+			view.repairParentChkClassWithSelf(setting, node);
+			setting.treeObj.trigger(consts.event.CHECK, [event, setting.treeId, node]);
+			return true;
+		},
+		onMouseoverCheck: function(event, node) {
+			if (node.chkDisabled === true) return false;
+			var setting = data.getSetting(event.data.treeId),
+			checkObj = $("#" + node.tId + consts.id.CHECK);
+			node.check_Focus = true;
+			view.setChkClass(setting, checkObj, node);
+			return true;
+		},
+		onMouseoutCheck: function(event, node) {
+			if (node.chkDisabled === true) return false;
+			var setting = data.getSetting(event.data.treeId),
+			checkObj = $("#" + node.tId + consts.id.CHECK);
+			node.check_Focus = false;
+			view.setChkClass(setting, checkObj, node);
+			return true;
+		}
+	},
+	//method of tools for zTree
+	_tools = {
+
+	},
+	//method of operate ztree dom
+	_view = {
+		checkNodeRelation: function(setting, node) {
+			var pNode, i, l,
+			childKey = setting.data.key.children,
+			checkedKey = setting.data.key.checked,
+			r = consts.radio;
+			if (setting.check.chkStyle == r.STYLE) {
+				var checkedList = data.getRadioCheckedList(setting);
+				if (node[checkedKey]) {
+					if (setting.check.radioType == r.TYPE_ALL) {
+						for (i = checkedList.length-1; i >= 0; i--) {
+							pNode = checkedList[i];
+							pNode[checkedKey] = false;
+							checkedList.splice(i, 1);
+
+							view.setChkClass(setting, $("#" + pNode.tId + consts.id.CHECK), pNode);
+							if (pNode.parentTId != node.parentTId) {
+								view.repairParentChkClassWithSelf(setting, pNode);
+							}
+						}
+						checkedList.push(node);
+					} else {
+						var parentNode = (node.parentTId) ? node.getParentNode() : data.getRoot(setting);
+						for (i = 0, l = parentNode[childKey].length; i < l; i++) {
+							pNode = parentNode[childKey][i];
+							if (pNode[checkedKey] && pNode != node) {
+								pNode[checkedKey] = false;
+								view.setChkClass(setting, $("#" + pNode.tId + consts.id.CHECK), pNode);
+							}
+						}
+					}
+				} else if (setting.check.radioType == r.TYPE_ALL) {
+					for (i = 0, l = checkedList.length; i < l; i++) {
+						if (node == checkedList[i]) {
+							checkedList.splice(i, 1);
+							break;
+						}
+					}
+				}
+
+			} else {
+				if (node[checkedKey] && (!node[childKey] || node[childKey].length==0 || setting.check.chkboxType.Y.indexOf("s") > -1)) {
+					view.setSonNodeCheckBox(setting, node, true);
+				}
+				if (!node[checkedKey] && (!node[childKey] || node[childKey].length==0 || setting.check.chkboxType.N.indexOf("s") > -1)) {
+					view.setSonNodeCheckBox(setting, node, false);
+				}
+				if (node[checkedKey] && setting.check.chkboxType.Y.indexOf("p") > -1) {
+					view.setParentNodeCheckBox(setting, node, true);
+				}
+				if (!node[checkedKey] && setting.check.chkboxType.N.indexOf("p") > -1) {
+					view.setParentNodeCheckBox(setting, node, false);
+				}
+			}
+		},
+		makeChkClass: function(setting, node) {
+			var checkedKey = setting.data.key.checked,
+			c = consts.checkbox, r = consts.radio,
+			fullStyle = "";
+			if (node.chkDisabled === true) {
+				fullStyle = c.DISABLED;
+			} else if (node.halfCheck) {
+				fullStyle = c.PART;
+			} else if (setting.check.chkStyle == r.STYLE) {
+				fullStyle = (node.check_Child_State < 1)? c.FULL:c.PART;
+			} else {
+				fullStyle = node[checkedKey] ? ((node.check_Child_State === 2 || node.check_Child_State === -1) ? c.FULL:c.PART) : ((node.check_Child_State < 1)? c.FULL:c.PART);
+			}
+			var chkName = setting.check.chkStyle + "_" + (node[checkedKey] ? c.TRUE : c.FALSE) + "_" + fullStyle;
+			chkName = (node.check_Focus && node.chkDisabled !== true) ? chkName + "_" + c.FOCUS : chkName;
+			return consts.className.BUTTON + " " + c.DEFAULT + " " + chkName;
+		},
+		repairAllChk: function(setting, checked) {
+			if (setting.check.enable && setting.check.chkStyle === consts.checkbox.STYLE) {
+				var checkedKey = setting.data.key.checked,
+				childKey = setting.data.key.children,
+				root = data.getRoot(setting);
+				for (var i = 0, l = root[childKey].length; i<l ; i++) {
+					var node = root[childKey][i];
+					if (node.nocheck !== true && node.chkDisabled !== true) {
+						node[checkedKey] = checked;
+					}
+					view.setSonNodeCheckBox(setting, node, checked);
+				}
+			}
+		},
+		repairChkClass: function(setting, node) {
+			if (!node) return;
+			data.makeChkFlag(setting, node);
+			if (node.nocheck !== true) {
+				var checkObj = $("#" + node.tId + consts.id.CHECK);
+				view.setChkClass(setting, checkObj, node);
+			}
+		},
+		repairParentChkClass: function(setting, node) {
+			if (!node || !node.parentTId) return;
+			var pNode = node.getParentNode();
+			view.repairChkClass(setting, pNode);
+			view.repairParentChkClass(setting, pNode);
+		},
+		repairParentChkClassWithSelf: function(setting, node) {
+			if (!node) return;
+			var childKey = setting.data.key.children;
+			if (node[childKey] && node[childKey].length > 0) {
+				view.repairParentChkClass(setting, node[childKey][0]);
+			} else {
+				view.repairParentChkClass(setting, node);
+			}
+		},
+		repairSonChkDisabled: function(setting, node, chkDisabled, inherit) {
+			if (!node) return;
+			var childKey = setting.data.key.children;
+			if (node.chkDisabled != chkDisabled) {
+				node.chkDisabled = chkDisabled;
+			}
+			view.repairChkClass(setting, node);
+			if (node[childKey] && inherit) {
+				for (var i = 0, l = node[childKey].length; i < l; i++) {
+					var sNode = node[childKey][i];
+					view.repairSonChkDisabled(setting, sNode, chkDisabled, inherit);
+				}
+			}
+		},
+		repairParentChkDisabled: function(setting, node, chkDisabled, inherit) {
+			if (!node) return;
+			if (node.chkDisabled != chkDisabled && inherit) {
+				node.chkDisabled = chkDisabled;
+			}
+			view.repairChkClass(setting, node);
+			view.repairParentChkDisabled(setting, node.getParentNode(), chkDisabled, inherit);
+		},
+		setChkClass: function(setting, obj, node) {
+			if (!obj) return;
+			if (node.nocheck === true) {
+				obj.hide();
+			} else {
+				obj.show();
+			}
+			obj.removeClass();
+			obj.addClass(view.makeChkClass(setting, node));
+		},
+		setParentNodeCheckBox: function(setting, node, value, srcNode) {
+			var childKey = setting.data.key.children,
+			checkedKey = setting.data.key.checked,
+			checkObj = $("#" + node.tId + consts.id.CHECK);
+			if (!srcNode) srcNode = node;
+			data.makeChkFlag(setting, node);
+			if (node.nocheck !== true && node.chkDisabled !== true) {
+				node[checkedKey] = value;
+				view.setChkClass(setting, checkObj, node);
+				if (setting.check.autoCheckTrigger && node != srcNode) {
+					setting.treeObj.trigger(consts.event.CHECK, [null, setting.treeId, node]);
+				}
+			}
+			if (node.parentTId) {
+				var pSign = true;
+				if (!value) {
+					var pNodes = node.getParentNode()[childKey];
+					for (var i = 0, l = pNodes.length; i < l; i++) {
+						if ((pNodes[i].nocheck !== true && pNodes[i].chkDisabled !== true && pNodes[i][checkedKey])
+						|| ((pNodes[i].nocheck === true || pNodes[i].chkDisabled === true) && pNodes[i].check_Child_State > 0)) {
+							pSign = false;
+							break;
+						}
+					}
+				}
+				if (pSign) {
+					view.setParentNodeCheckBox(setting, node.getParentNode(), value, srcNode);
+				}
+			}
+		},
+		setSonNodeCheckBox: function(setting, node, value, srcNode) {
+			if (!node) return;
+			var childKey = setting.data.key.children,
+			checkedKey = setting.data.key.checked,
+			checkObj = $("#" + node.tId + consts.id.CHECK);
+			if (!srcNode) srcNode = node;
+
+			var hasDisable = false;
+			if (node[childKey]) {
+				for (var i = 0, l = node[childKey].length; i < l && node.chkDisabled !== true; i++) {
+					var sNode = node[childKey][i];
+					view.setSonNodeCheckBox(setting, sNode, value, srcNode);
+					if (sNode.chkDisabled === true) hasDisable = true;
+				}
+			}
+			
+			if (node != data.getRoot(setting) && node.chkDisabled !== true) {
+				if (hasDisable && node.nocheck !== true) {
+					data.makeChkFlag(setting, node);
+				}
+				if (node.nocheck !== true && node.chkDisabled !== true) {
+					node[checkedKey] = value;
+					if (!hasDisable) node.check_Child_State = (node[childKey] && node[childKey].length > 0) ? (value ? 2 : 0) : -1;
+				} else {
+					node.check_Child_State = -1;
+				}
+				view.setChkClass(setting, checkObj, node);
+				if (setting.check.autoCheckTrigger && node != srcNode && node.nocheck !== true && node.chkDisabled !== true) {
+					setting.treeObj.trigger(consts.event.CHECK, [null, setting.treeId, node]);
+				}
+			}
+
+		}
+	},
+
+	_z = {
+		tools: _tools,
+		view: _view,
+		event: _event,
+		data: _data
+	};
+	$.extend(true, $.fn.zTree.consts, _consts);
+	$.extend(true, $.fn.zTree._z, _z);
+
+	var zt = $.fn.zTree,
+	tools = zt._z.tools,
+	consts = zt.consts,
+	view = zt._z.view,
+	data = zt._z.data,
+	event = zt._z.event;
+
+	data.exSetting(_setting);
+	data.addInitBind(_bindEvent);
+	data.addInitUnBind(_unbindEvent);
+	data.addInitCache(_initCache);
+	data.addInitNode(_initNode);
+	data.addInitProxy(_eventProxy);
+	data.addInitRoot(_initRoot);
+	data.addBeforeA(_beforeA);
+	data.addZTreeTools(_zTreeTools);
+
+	var _createNodes = view.createNodes;
+	view.createNodes = function(setting, level, nodes, parentNode) {
+		if (_createNodes) _createNodes.apply(view, arguments);
+		if (!nodes) return;
+		view.repairParentChkClassWithSelf(setting, parentNode);
+	}
+	var _removeNode = view.removeNode;
+	view.removeNode = function(setting, node) {
+		var parentNode = node.getParentNode();
+		if (_removeNode) _removeNode.apply(view, arguments);
+		if (!node || !parentNode) return;
+		view.repairChkClass(setting, parentNode);
+		view.repairParentChkClass(setting, parentNode);
+	}
+
+	var _appendNodes = view.appendNodes;
+	view.appendNodes = function(setting, level, nodes, parentNode, initFlag, openFlag) {
+		var html = "";
+		if (_appendNodes) {
+			html = _appendNodes.apply(view, arguments);
+		}
+		if (parentNode) {
+			data.makeChkFlag(setting, parentNode);
+		}
+		return html;
+	}
+})(jQuery);
+/*
+ * JQuery zTree exedit 3.5.12
+ * http://zTree.me/
+ *
+ * Copyright (c) 2010 Hunter.z
+ *
+ * Licensed same as jquery - MIT License
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ * email: hunter.z@263.net
+ * Date: 2013-03-11
+ */
+(function($){
+	//default consts of exedit
+	var _consts = {
+		event: {
+			DRAG: "ztree_drag",
+			DROP: "ztree_drop",
+			REMOVE: "ztree_remove",
+			RENAME: "ztree_rename"
+		},
+		id: {
+			EDIT: "_edit",
+			INPUT: "_input",
+			REMOVE: "_remove"
+		},
+		move: {
+			TYPE_INNER: "inner",
+			TYPE_PREV: "prev",
+			TYPE_NEXT: "next"
+		},
+		node: {
+			CURSELECTED_EDIT: "curSelectedNode_Edit",
+			TMPTARGET_TREE: "tmpTargetzTree",
+			TMPTARGET_NODE: "tmpTargetNode"
+		}
+	},
+	//default setting of exedit
+	_setting = {
+		edit: {
+			enable: false,
+			editNameSelectAll: false,
+			showRemoveBtn: true,
+			showRenameBtn: true,
+			removeTitle: "remove",
+			renameTitle: "rename",
+			drag: {
+				autoExpandTrigger: false,
+				isCopy: true,
+				isMove: true,
+				prev: true,
+				next: true,
+				inner: true,
+				minMoveSize: 5,
+				borderMax: 10,
+				borderMin: -5,
+				maxShowNodeNum: 5,
+				autoOpenTime: 500
+			}
+		},
+		view: {
+			addHoverDom: null,
+			removeHoverDom: null
+		},
+		callback: {
+			beforeDrag:null,
+			beforeDragOpen:null,
+			beforeDrop:null,
+			beforeEditName:null,
+			beforeRename:null,
+			onDrag:null,
+			onDrop:null,
+			onRename:null
+		}
+	},
+	//default root of exedit
+	_initRoot = function (setting) {
+		var r = data.getRoot(setting);
+		r.curEditNode = null;
+		r.curEditInput = null;
+		r.curHoverNode = null;
+		r.dragFlag = 0;
+		r.dragNodeShowBefore = [];
+		r.dragMaskList = new Array();
+		r.showHoverDom = true;
+	},
+	//default cache of exedit
+	_initCache = function(treeId) {},
+	//default bind event of exedit
+	_bindEvent = function(setting) {
+		var o = setting.treeObj;
+		var c = consts.event;
+		o.bind(c.RENAME, function (event, treeId, treeNode) {
+			tools.apply(setting.callback.onRename, [event, treeId, treeNode]);
+		});
+
+		o.bind(c.REMOVE, function (event, treeId, treeNode) {
+			tools.apply(setting.callback.onRemove, [event, treeId, treeNode]);
+		});
+
+		o.bind(c.DRAG, function (event, srcEvent, treeId, treeNodes) {
+			tools.apply(setting.callback.onDrag, [srcEvent, treeId, treeNodes]);
+		});
+
+		o.bind(c.DROP, function (event, srcEvent, treeId, treeNodes, targetNode, moveType, isCopy) {
+			tools.apply(setting.callback.onDrop, [srcEvent, treeId, treeNodes, targetNode, moveType, isCopy]);
+		});
+	},
+	_unbindEvent = function(setting) {
+		var o = setting.treeObj;
+		var c = consts.event;
+		o.unbind(c.RENAME);
+		o.unbind(c.REMOVE);
+		o.unbind(c.DRAG);
+		o.unbind(c.DROP);
+	},
+	//default event proxy of exedit
+	_eventProxy = function(e) {
+		var target = e.target,
+		setting = data.getSetting(e.data.treeId),
+		relatedTarget = e.relatedTarget,
+		tId = "", node = null,
+		nodeEventType = "", treeEventType = "",
+		nodeEventCallback = null, treeEventCallback = null,
+		tmp = null;
+
+		if (tools.eqs(e.type, "mouseover")) {
+			tmp = tools.getMDom(setting, target, [{tagName:"a", attrName:"treeNode"+consts.id.A}]);
+			if (tmp) {
+				tId = tmp.parentNode.id;
+				nodeEventType = "hoverOverNode";
+			}
+		} else if (tools.eqs(e.type, "mouseout")) {
+			tmp = tools.getMDom(setting, relatedTarget, [{tagName:"a", attrName:"treeNode"+consts.id.A}]);
+			if (!tmp) {
+				tId = "remove";
+				nodeEventType = "hoverOutNode";
+			}
+		} else if (tools.eqs(e.type, "mousedown")) {
+			tmp = tools.getMDom(setting, target, [{tagName:"a", attrName:"treeNode"+consts.id.A}]);
+			if (tmp) {
+				tId = tmp.parentNode.id;
+				nodeEventType = "mousedownNode";
+			}
+		}
+		if (tId.length>0) {
+			node = data.getNodeCache(setting, tId);
+			switch (nodeEventType) {
+				case "mousedownNode" :
+					nodeEventCallback = _handler.onMousedownNode;
+					break;
+				case "hoverOverNode" :
+					nodeEventCallback = _handler.onHoverOverNode;
+					break;
+				case "hoverOutNode" :
+					nodeEventCallback = _handler.onHoverOutNode;
+					break;
+			}
+		}
+		var proxyResult = {
+			stop: false,
+			node: node,
+			nodeEventType: nodeEventType,
+			nodeEventCallback: nodeEventCallback,
+			treeEventType: treeEventType,
+			treeEventCallback: treeEventCallback
+		};
+		return proxyResult
+	},
+	//default init node of exedit
+	_initNode = function(setting, level, n, parentNode, isFirstNode, isLastNode, openFlag) {
+		if (!n) return;
+		n.isHover = false;
+		n.editNameFlag = false;
+	},
+	//update zTreeObj, add method of edit
+	_zTreeTools = function(setting, zTreeTools) {
+		zTreeTools.cancelEditName = function(newName) {
+			var root = data.getRoot(setting),
+			nameKey = setting.data.key.name,
+			node = root.curEditNode;
+			if (!root.curEditNode) return;
+			view.cancelCurEditNode(setting, newName?newName:node[nameKey]);
+		}
+		zTreeTools.copyNode = function(targetNode, node, moveType, isSilent) {
+			if (!node) return null;
+			if (targetNode && !targetNode.isParent && setting.data.keep.leaf && moveType === consts.move.TYPE_INNER) return null;
+			var newNode = tools.clone(node);
+			if (!targetNode) {
+				targetNode = null;
+				moveType = consts.move.TYPE_INNER;
+			}
+			if (moveType == consts.move.TYPE_INNER) {
+				function copyCallback() {
+					view.addNodes(setting, targetNode, [newNode], isSilent);
+				}
+
+				if (tools.canAsync(setting, targetNode)) {
+					view.asyncNode(setting, targetNode, isSilent, copyCallback);
+				} else {
+					copyCallback();
+				}
+			} else {
+				view.addNodes(setting, targetNode.parentNode, [newNode], isSilent);
+				view.moveNode(setting, targetNode, newNode, moveType, false, isSilent);
+			}
+			return newNode;
+		}
+		zTreeTools.editName = function(node) {
+			if (!node || !node.tId || node !== data.getNodeCache(setting, node.tId)) return;
+			if (node.parentTId) view.expandCollapseParentNode(setting, node.getParentNode(), true);
+			view.editNode(setting, node)
+		}
+		zTreeTools.moveNode = function(targetNode, node, moveType, isSilent) {
+			if (!node) return node;
+			if (targetNode && !targetNode.isParent && setting.data.keep.leaf && moveType === consts.move.TYPE_INNER) {
+				return null;
+			} else if (targetNode && ((node.parentTId == targetNode.tId && moveType == consts.move.TYPE_INNER) || $("#" + node.tId).find("#" + targetNode.tId).length > 0)) {
+				return null;
+			} else if (!targetNode) {
+				targetNode = null;
+			}
+			function moveCallback() {
+				view.moveNode(setting, targetNode, node, moveType, false, isSilent);
+			}
+			if (tools.canAsync(setting, targetNode) && moveType === consts.move.TYPE_INNER) {
+				view.asyncNode(setting, targetNode, isSilent, moveCallback);
+			} else {
+				moveCallback();
+			}
+			return node;
+		}
+		zTreeTools.setEditable = function(editable) {
+			setting.edit.enable = editable;
+			return this.refresh();
+		}
+	},
+	//method of operate data
+	_data = {
+		setSonNodeLevel: function(setting, parentNode, node) {
+			if (!node) return;
+			var childKey = setting.data.key.children;
+			node.level = (parentNode)? parentNode.level + 1 : 0;
+			if (!node[childKey]) return;
+			for (var i = 0, l = node[childKey].length; i < l; i++) {
+				if (node[childKey][i]) data.setSonNodeLevel(setting, node, node[childKey][i]);
+			}
+		}
+	},
+	//method of event proxy
+	_event = {
+
+	},
+	//method of event handler
+	_handler = {
+		onHoverOverNode: function(event, node) {
+			var setting = data.getSetting(event.data.treeId),
+			root = data.getRoot(setting);
+			if (root.curHoverNode != node) {
+				_handler.onHoverOutNode(event);
+			}
+			root.curHoverNode = node;
+			view.addHoverDom(setting, node);
+		},
+		onHoverOutNode: function(event, node) {
+			var setting = data.getSetting(event.data.treeId),
+			root = data.getRoot(setting);
+			if (root.curHoverNode && !data.isSelectedNode(setting, root.curHoverNode)) {
+				view.removeTreeDom(setting, root.curHoverNode);
+				root.curHoverNode = null;
+			}
+		},
+		onMousedownNode: function(eventMouseDown, _node) {
+			var i,l,
+			setting = data.getSetting(eventMouseDown.data.treeId),
+			root = data.getRoot(setting);
+			//right click can't drag & drop
+			if (eventMouseDown.button == 2 || !setting.edit.enable || (!setting.edit.drag.isCopy && !setting.edit.drag.isMove)) return true;
+
+			//input of edit node name can't drag & drop
+			var target = eventMouseDown.target,
+			_nodes = data.getRoot(setting).curSelectedList,
+			nodes = [];
+			if (!data.isSelectedNode(setting, _node)) {
+				nodes = [_node];
+			} else {
+				for (i=0, l=_nodes.length; i<l; i++) {
+					if (_nodes[i].editNameFlag && tools.eqs(target.tagName, "input") && target.getAttribute("treeNode"+consts.id.INPUT) !== null) {
+						return true;
+					}
+					nodes.push(_nodes[i]);
+					if (nodes[0].parentTId !== _nodes[i].parentTId) {
+						nodes = [_node];
+						break;
+					}
+				}
+			}
+
+			view.editNodeBlur = true;
+			view.cancelCurEditNode(setting, null, true);
+			
+
+			var doc = $(document), curNode, tmpArrow, tmpTarget,
+			isOtherTree = false,
+			targetSetting = setting,
+			preNode, nextNode,
+			preTmpTargetNodeId = null,
+			preTmpMoveType = null,
+			tmpTargetNodeId = null,
+			moveType = consts.move.TYPE_INNER,
+			mouseDownX = eventMouseDown.clientX,
+			mouseDownY = eventMouseDown.clientY,
+			startTime = (new Date()).getTime();
+
+			if (tools.uCanDo(setting)) {
+				doc.bind("mousemove", _docMouseMove);
+			}
+			function _docMouseMove(event) {
+				//avoid start drag after click node
+				if (root.dragFlag == 0 && Math.abs(mouseDownX - event.clientX) < setting.edit.drag.minMoveSize
+					&& Math.abs(mouseDownY - event.clientY) < setting.edit.drag.minMoveSize) {
+					return true;
+				}
+				var i, l, tmpNode, tmpDom, tmpNodes,
+				childKey = setting.data.key.children;
+				$("body").css("cursor", "pointer");
+
+				if (root.dragFlag == 0) {
+					if (tools.apply(setting.callback.beforeDrag, [setting.treeId, nodes], true) == false) {
+						_docMouseUp(event);
+						return true;
+					}
+
+					for (i=0, l=nodes.length; i<l; i++) {
+						if (i==0) {
+							root.dragNodeShowBefore = [];
+						}
+						tmpNode = nodes[i];
+						if (tmpNode.isParent && tmpNode.open) {
+							view.expandCollapseNode(setting, tmpNode, !tmpNode.open);
+							root.dragNodeShowBefore[tmpNode.tId] = true;
+						} else {
+							root.dragNodeShowBefore[tmpNode.tId] = false;
+						}
+					}
+
+					root.dragFlag = 1;
+					root.showHoverDom = false;
+					tools.showIfameMask(setting, true);
+
+					//sort
+					var isOrder = true, lastIndex = -1;
+					if (nodes.length>1) {
+						var pNodes = nodes[0].parentTId ? nodes[0].getParentNode()[childKey] : data.getNodes(setting);
+						tmpNodes = [];
+						for (i=0, l=pNodes.length; i<l; i++) {
+							if (root.dragNodeShowBefore[pNodes[i].tId] !== undefined) {
+								if (isOrder && lastIndex > -1 && (lastIndex+1) !== i) {
+									isOrder = false;
+								}
+								tmpNodes.push(pNodes[i]);
+								lastIndex = i;
+							}
+							if (nodes.length === tmpNodes.length) {
+								nodes = tmpNodes;
+								break;
+							}
+						}
+					}
+					if (isOrder) {
+						preNode = nodes[0].getPreNode();
+						nextNode = nodes[nodes.length-1].getNextNode();
+					}
+
+					//set node in selected
+					curNode = $("<ul class='zTreeDragUL'></ul>");
+					for (i=0, l=nodes.length; i<l; i++) {
+						tmpNode = nodes[i];
+						tmpNode.editNameFlag = false;
+						view.selectNode(setting, tmpNode, i>0);
+						view.removeTreeDom(setting, tmpNode);
+
+						tmpDom = $("<li id='"+ tmpNode.tId +"_tmp'></li>");
+						tmpDom.append($("#" + tmpNode.tId + consts.id.A).clone());
+						tmpDom.css("padding", "0");
+						tmpDom.children("#" + tmpNode.tId + consts.id.A).removeClass(consts.node.CURSELECTED);
+						curNode.append(tmpDom);
+						if (i == setting.edit.drag.maxShowNodeNum-1) {
+							tmpDom = $("<li id='"+ tmpNode.tId +"_moretmp'><a>  ...  </a></li>");
+							curNode.append(tmpDom);
+							break;
+						}
+					}
+					curNode.attr("id", nodes[0].tId + consts.id.UL + "_tmp");
+					curNode.addClass(setting.treeObj.attr("class"));
+					curNode.appendTo("body");
+
+					tmpArrow = $("<span class='tmpzTreeMove_arrow'></span>");
+					tmpArrow.attr("id", "zTreeMove_arrow_tmp");
+					tmpArrow.appendTo("body");
+
+					setting.treeObj.trigger(consts.event.DRAG, [event, setting.treeId, nodes]);
+				}
+
+				if (root.dragFlag == 1) {
+					if (tmpTarget && tmpArrow.attr("id") == event.target.id && tmpTargetNodeId && (event.clientX + doc.scrollLeft()+2) > ($("#" + tmpTargetNodeId + consts.id.A, tmpTarget).offset().left)) {
+						var xT = $("#" + tmpTargetNodeId + consts.id.A, tmpTarget);
+						event.target = (xT.length > 0) ? xT.get(0) : event.target;
+					} else if (tmpTarget) {
+						tmpTarget.removeClass(consts.node.TMPTARGET_TREE);
+						if (tmpTargetNodeId) $("#" + tmpTargetNodeId + consts.id.A, tmpTarget).removeClass(consts.node.TMPTARGET_NODE + "_" + consts.move.TYPE_PREV)
+							.removeClass(consts.node.TMPTARGET_NODE + "_" + _consts.move.TYPE_NEXT).removeClass(consts.node.TMPTARGET_NODE + "_" + _consts.move.TYPE_INNER);
+					}
+					tmpTarget = null;
+					tmpTargetNodeId = null;
+
+					//judge drag & drop in multi ztree
+					isOtherTree = false;
+					targetSetting = setting;
+					var settings = data.getSettings();
+					for (var s in settings) {
+						if (settings[s].treeId && settings[s].edit.enable && settings[s].treeId != setting.treeId
+							&& (event.target.id == settings[s].treeId || $(event.target).parents("#" + settings[s].treeId).length>0)) {
+							isOtherTree = true;
+							targetSetting = settings[s];
+						}
+					}
+
+					var docScrollTop = doc.scrollTop(),
+					docScrollLeft = doc.scrollLeft(),
+					treeOffset = targetSetting.treeObj.offset(),
+					scrollHeight = targetSetting.treeObj.get(0).scrollHeight,
+					scrollWidth = targetSetting.treeObj.get(0).scrollWidth,
+					dTop = (event.clientY + docScrollTop - treeOffset.top),
+					dBottom = (targetSetting.treeObj.height() + treeOffset.top - event.clientY - docScrollTop),
+					dLeft = (event.clientX + docScrollLeft - treeOffset.left),
+					dRight = (targetSetting.treeObj.width() + treeOffset.left - event.clientX - docScrollLeft),
+					isTop = (dTop < setting.edit.drag.borderMax && dTop > setting.edit.drag.borderMin),
+					isBottom = (dBottom < setting.edit.drag.borderMax && dBottom > setting.edit.drag.borderMin),
+					isLeft = (dLeft < setting.edit.drag.borderMax && dLeft > setting.edit.drag.borderMin),
+					isRight = (dRight < setting.edit.drag.borderMax && dRight > setting.edit.drag.borderMin),
+					isTreeInner = dTop > setting.edit.drag.borderMin && dBottom > setting.edit.drag.borderMin && dLeft > setting.edit.drag.borderMin && dRight > setting.edit.drag.borderMin,
+					isTreeTop = (isTop && targetSetting.treeObj.scrollTop() <= 0),
+					isTreeBottom = (isBottom && (targetSetting.treeObj.scrollTop() + targetSetting.treeObj.height()+10) >= scrollHeight),
+					isTreeLeft = (isLeft && targetSetting.treeObj.scrollLeft() <= 0),
+					isTreeRight = (isRight && (targetSetting.treeObj.scrollLeft() + targetSetting.treeObj.width()+10) >= scrollWidth);
+
+					if (event.target.id && targetSetting.treeObj.find("#" + event.target.id).length > 0) {
+						//get node <li> dom
+						var targetObj = event.target;
+						while (targetObj && targetObj.tagName && !tools.eqs(targetObj.tagName, "li") && targetObj.id != targetSetting.treeId) {
+							targetObj = targetObj.parentNode;
+						}
+
+						var canMove = true;
+						//don't move to self or children of self
+						for (i=0, l=nodes.length; i<l; i++) {
+							tmpNode = nodes[i];
+							if (targetObj.id === tmpNode.tId) {
+								canMove = false;
+								break;
+							} else if ($("#" + tmpNode.tId).find("#" + targetObj.id).length > 0) {
+								canMove = false;
+								break;
+							}
+						}
+						if (canMove) {
+							if (event.target.id &&
+								(event.target.id == (targetObj.id + consts.id.A) || $(event.target).parents("#" + targetObj.id + consts.id.A).length > 0)) {
+								tmpTarget = $(targetObj);
+								tmpTargetNodeId = targetObj.id;
+							}
+						}
+					}
+
+					//the mouse must be in zTree
+					tmpNode = nodes[0];
+					if (isTreeInner && (event.target.id == targetSetting.treeId || $(event.target).parents("#" + targetSetting.treeId).length>0)) {
+						//judge mouse move in root of ztree
+						if (!tmpTarget && (event.target.id == targetSetting.treeId || isTreeTop || isTreeBottom || isTreeLeft || isTreeRight) && (isOtherTree || (!isOtherTree && tmpNode.parentTId))) {
+							tmpTarget = targetSetting.treeObj;
+						}
+						//auto scroll top
+						if (isTop) {
+							targetSetting.treeObj.scrollTop(targetSetting.treeObj.scrollTop()-10);
+						} else if (isBottom)  {
+							targetSetting.treeObj.scrollTop(targetSetting.treeObj.scrollTop()+10);
+						}
+						if (isLeft) {
+							targetSetting.treeObj.scrollLeft(targetSetting.treeObj.scrollLeft()-10);
+						} else if (isRight) {
+							targetSetting.treeObj.scrollLeft(targetSetting.treeObj.scrollLeft()+10);
+						}
+						//auto scroll left
+						if (tmpTarget && tmpTarget != targetSetting.treeObj && tmpTarget.offset().left < targetSetting.treeObj.offset().left) {
+							targetSetting.treeObj.scrollLeft(targetSetting.treeObj.scrollLeft()+ tmpTarget.offset().left - targetSetting.treeObj.offset().left);
+						}
+					}
+
+					curNode.css({
+						"top": (event.clientY + docScrollTop + 3) + "px",
+						"left": (event.clientX + docScrollLeft + 3) + "px"
+					});
+
+					var dX = 0;
+					var dY = 0;
+					if (tmpTarget && tmpTarget.attr("id")!=targetSetting.treeId) {
+						var tmpTargetNode = tmpTargetNodeId == null ? null: data.getNodeCache(targetSetting, tmpTargetNodeId),
+						isCopy = (event.ctrlKey && setting.edit.drag.isMove && setting.edit.drag.isCopy) || (!setting.edit.drag.isMove && setting.edit.drag.isCopy),
+						isPrev = !!(preNode && tmpTargetNodeId === preNode.tId),
+						isNext = !!(nextNode && tmpTargetNodeId === nextNode.tId),
+						isInner = (tmpNode.parentTId && tmpNode.parentTId == tmpTargetNodeId),
+						canPrev = (isCopy || !isNext) && tools.apply(targetSetting.edit.drag.prev, [targetSetting.treeId, nodes, tmpTargetNode], !!targetSetting.edit.drag.prev),
+						canNext = (isCopy || !isPrev) && tools.apply(targetSetting.edit.drag.next, [targetSetting.treeId, nodes, tmpTargetNode], !!targetSetting.edit.drag.next),
+						canInner = (isCopy || !isInner) && !(targetSetting.data.keep.leaf && !tmpTargetNode.isParent) && tools.apply(targetSetting.edit.drag.inner, [targetSetting.treeId, nodes, tmpTargetNode], !!targetSetting.edit.drag.inner);
+						if (!canPrev && !canNext && !canInner) {
+							tmpTarget = null;
+							tmpTargetNodeId = "";
+							moveType = consts.move.TYPE_INNER;
+							tmpArrow.css({
+								"display":"none"
+							});
+							if (window.zTreeMoveTimer) {
+								clearTimeout(window.zTreeMoveTimer);
+								window.zTreeMoveTargetNodeTId = null
+							}
+						} else {
+							var tmpTargetA = $("#" + tmpTargetNodeId + consts.id.A, tmpTarget),
+							tmpNextA = tmpTargetNode.isLastNode ? null : $("#" + tmpTargetNode.getNextNode().tId + consts.id.A, tmpTarget.next()),
+							tmpTop = tmpTargetA.offset().top,
+							tmpLeft = tmpTargetA.offset().left,
+							prevPercent = canPrev ? (canInner ? 0.25 : (canNext ? 0.5 : 1) ) : -1,
+							nextPercent = canNext ? (canInner ? 0.75 : (canPrev ? 0.5 : 0) ) : -1,
+							dY_percent = (event.clientY + docScrollTop - tmpTop)/tmpTargetA.height();
+							if ((prevPercent==1 ||dY_percent<=prevPercent && dY_percent>=-.2) && canPrev) {
+								dX = 1 - tmpArrow.width();
+								dY = tmpTop - tmpArrow.height()/2;
+								moveType = consts.move.TYPE_PREV;
+							} else if ((nextPercent==0 || dY_percent>=nextPercent && dY_percent<=1.2) && canNext) {
+								dX = 1 - tmpArrow.width();
+								dY = (tmpNextA == null || (tmpTargetNode.isParent && tmpTargetNode.open)) ? (tmpTop + tmpTargetA.height() - tmpArrow.height()/2) : (tmpNextA.offset().top - tmpArrow.height()/2);
+								moveType = consts.move.TYPE_NEXT;
+							}else {
+								dX = 5 - tmpArrow.width();
+								dY = tmpTop;
+								moveType = consts.move.TYPE_INNER;
+							}
+							tmpArrow.css({
+								"display":"block",
+								"top": dY + "px",
+								"left": (tmpLeft + dX) + "px"
+							});
+							tmpTargetA.addClass(consts.node.TMPTARGET_NODE + "_" + moveType);
+
+							if (preTmpTargetNodeId != tmpTargetNodeId || preTmpMoveType != moveType) {
+								startTime = (new Date()).getTime();
+							}
+							if (tmpTargetNode && tmpTargetNode.isParent && moveType == consts.move.TYPE_INNER) {
+								var startTimer = true;
+								if (window.zTreeMoveTimer && window.zTreeMoveTargetNodeTId !== tmpTargetNode.tId) {
+									clearTimeout(window.zTreeMoveTimer);
+									window.zTreeMoveTargetNodeTId = null;
+								} else if (window.zTreeMoveTimer && window.zTreeMoveTargetNodeTId === tmpTargetNode.tId) {
+									startTimer = false;
+								}
+								if (startTimer) {
+									window.zTreeMoveTimer = setTimeout(function() {
+										if (moveType != consts.move.TYPE_INNER) return;
+										if (tmpTargetNode && tmpTargetNode.isParent && !tmpTargetNode.open && (new Date()).getTime() - startTime > targetSetting.edit.drag.autoOpenTime
+											&& tools.apply(targetSetting.callback.beforeDragOpen, [targetSetting.treeId, tmpTargetNode], true)) {
+											view.switchNode(targetSetting, tmpTargetNode);
+											if (targetSetting.edit.drag.autoExpandTrigger) {
+												targetSetting.treeObj.trigger(consts.event.EXPAND, [targetSetting.treeId, tmpTargetNode]);
+											}
+										}
+									}, targetSetting.edit.drag.autoOpenTime+50);
+									window.zTreeMoveTargetNodeTId = tmpTargetNode.tId;
+								}
+							}
+						}
+					} else {
+						moveType = consts.move.TYPE_INNER;
+						if (tmpTarget && tools.apply(targetSetting.edit.drag.inner, [targetSetting.treeId, nodes, null], !!targetSetting.edit.drag.inner)) {
+							tmpTarget.addClass(consts.node.TMPTARGET_TREE);
+						} else {
+							tmpTarget = null;
+						}
+						tmpArrow.css({
+							"display":"none"
+						});
+						if (window.zTreeMoveTimer) {
+							clearTimeout(window.zTreeMoveTimer);
+							window.zTreeMoveTargetNodeTId = null;
+						}
+					}
+					preTmpTargetNodeId = tmpTargetNodeId;
+					preTmpMoveType = moveType;
+				}
+				return false;
+			}
+
+			doc.bind("mouseup", _docMouseUp);
+			function _docMouseUp(event) {
+				if (window.zTreeMoveTimer) {
+					clearTimeout(window.zTreeMoveTimer);
+					window.zTreeMoveTargetNodeTId = null;
+				}
+				preTmpTargetNodeId = null;
+				preTmpMoveType = null;
+				doc.unbind("mousemove", _docMouseMove);
+				doc.unbind("mouseup", _docMouseUp);
+				doc.unbind("selectstart", _docSelect);
+				$("body").css("cursor", "auto");
+				if (tmpTarget) {
+					tmpTarget.removeClass(consts.node.TMPTARGET_TREE);
+					if (tmpTargetNodeId) $("#" + tmpTargetNodeId + consts.id.A, tmpTarget).removeClass(consts.node.TMPTARGET_NODE + "_" + consts.move.TYPE_PREV)
+							.removeClass(consts.node.TMPTARGET_NODE + "_" + _consts.move.TYPE_NEXT).removeClass(consts.node.TMPTARGET_NODE + "_" + _consts.move.TYPE_INNER);
+				}
+				tools.showIfameMask(setting, false);
+
+				root.showHoverDom = true;
+				if (root.dragFlag == 0) return;
+				root.dragFlag = 0;
+
+				var i, l, tmpNode;
+				for (i=0, l=nodes.length; i<l; i++) {
+					tmpNode = nodes[i];
+					if (tmpNode.isParent && root.dragNodeShowBefore[tmpNode.tId] && !tmpNode.open) {
+						view.expandCollapseNode(setting, tmpNode, !tmpNode.open);
+						delete root.dragNodeShowBefore[tmpNode.tId];
+					}
+				}
+
+				if (curNode) curNode.remove();
+				if (tmpArrow) tmpArrow.remove();
+
+				var isCopy = (event.ctrlKey && setting.edit.drag.isMove && setting.edit.drag.isCopy) || (!setting.edit.drag.isMove && setting.edit.drag.isCopy);
+				if (!isCopy && tmpTarget && tmpTargetNodeId && nodes[0].parentTId && tmpTargetNodeId==nodes[0].parentTId && moveType == consts.move.TYPE_INNER) {
+					tmpTarget = null;
+				}
+				if (tmpTarget) {
+					var dragTargetNode = tmpTargetNodeId == null ? null: data.getNodeCache(targetSetting, tmpTargetNodeId);
+					if (tools.apply(setting.callback.beforeDrop, [targetSetting.treeId, nodes, dragTargetNode, moveType, isCopy], true) == false) return;
+					var newNodes = isCopy ? tools.clone(nodes) : nodes;
+					
+					function dropCallback() {
+						if (isOtherTree) {							
+							if (!isCopy) {
+								for(var i=0, l=nodes.length; i<l; i++) {
+									view.removeNode(setting, nodes[i]);
+								}
+							}
+							if (moveType == consts.move.TYPE_INNER) {
+								view.addNodes(targetSetting, dragTargetNode, newNodes);
+							} else {
+								view.addNodes(targetSetting, dragTargetNode.getParentNode(), newNodes);
+								if (moveType == consts.move.TYPE_PREV) {
+									for (i=0, l=newNodes.length; i<l; i++) {
+										view.moveNode(targetSetting, dragTargetNode, newNodes[i], moveType, false);
+									}
+								} else {
+									for (i=-1, l=newNodes.length-1; i<l; l--) {
+										view.moveNode(targetSetting, dragTargetNode, newNodes[l], moveType, false);
+									}
+								}
+							}
+						} else {
+							if (isCopy && moveType == consts.move.TYPE_INNER) {
+								view.addNodes(targetSetting, dragTargetNode, newNodes);
+							} else {
+								if (isCopy) {
+									view.addNodes(targetSetting, dragTargetNode.getParentNode(), newNodes);
+								}
+								if (moveType != consts.move.TYPE_NEXT) {
+									for (i=0, l=newNodes.length; i<l; i++) {
+										view.moveNode(targetSetting, dragTargetNode, newNodes[i], moveType, false);
+									}
+								} else {
+									for (i=-1, l=newNodes.length-1; i<l; l--) {
+										view.moveNode(targetSetting, dragTargetNode, newNodes[l], moveType, false);
+									}
+								}
+							}
+						}
+						for (i=0, l=newNodes.length; i<l; i++) {
+							view.selectNode(targetSetting, newNodes[i], i>0);
+						}
+						$("#" + newNodes[0].tId).focus().blur();
+
+						setting.treeObj.trigger(consts.event.DROP, [event, targetSetting.treeId, newNodes, dragTargetNode, moveType, isCopy]);
+					}
+
+					if (moveType == consts.move.TYPE_INNER && tools.canAsync(targetSetting, dragTargetNode)) {
+						view.asyncNode(targetSetting, dragTargetNode, false, dropCallback);
+					} else {
+						dropCallback();
+					}
+
+				} else {
+					for (i=0, l=nodes.length; i<l; i++) {
+						view.selectNode(targetSetting, nodes[i], i>0);
+					}
+					setting.treeObj.trigger(consts.event.DROP, [event, setting.treeId, nodes, null, null, null]);
+				}
+			}
+
+			doc.bind("selectstart", _docSelect);
+			function _docSelect() {
+				return false;
+			}
+
+			//Avoid FireFox's Bug
+			//If zTree Div CSS set 'overflow', so drag node outside of zTree, and event.target is error.
+			if(eventMouseDown.preventDefault) {
+				eventMouseDown.preventDefault();
+			}
+			return true;
+		}
+	},
+	//method of tools for zTree
+	_tools = {
+		getAbs: function (obj) {
+			var oRect = obj.getBoundingClientRect();
+			return [oRect.left,oRect.top]
+		},
+		inputFocus: function(inputObj) {
+			if (inputObj.get(0)) {
+				inputObj.focus();
+				tools.setCursorPosition(inputObj.get(0), inputObj.val().length);
+			}
+		},
+		inputSelect: function(inputObj) {
+			if (inputObj.get(0)) {
+				inputObj.focus();
+				inputObj.select();
+			}
+		},
+		setCursorPosition: function(obj, pos){
+			if(obj.setSelectionRange) {
+				obj.focus();
+				obj.setSelectionRange(pos,pos);
+			} else if (obj.createTextRange) {
+				var range = obj.createTextRange();
+				range.collapse(true);
+				range.moveEnd('character', pos);
+				range.moveStart('character', pos);
+				range.select();
+			}
+		},
+		showIfameMask: function(setting, showSign) {
+			var root = data.getRoot(setting);
+			//clear full mask
+			while (root.dragMaskList.length > 0) {
+				root.dragMaskList[0].remove();
+				root.dragMaskList.shift();
+			}
+			if (showSign) {
+				//show mask
+				var iframeList = $("iframe");
+				for (var i = 0, l = iframeList.length; i < l; i++) {
+					var obj = iframeList.get(i),
+					r = tools.getAbs(obj),
+					dragMask = $("<div id='zTreeMask_" + i + "' class='zTreeMask' style='top:" + r[1] + "px; left:" + r[0] + "px; width:" + obj.offsetWidth + "px; height:" + obj.offsetHeight + "px;'></div>");
+					dragMask.appendTo("body");
+					root.dragMaskList.push(dragMask);
+				}
+			}
+		}
+	},
+	//method of operate ztree dom
+	_view = {
+		addEditBtn: function(setting, node) {
+			if (node.editNameFlag || $("#" + node.tId + consts.id.EDIT).length > 0) {
+				return;
+			}
+			if (!tools.apply(setting.edit.showRenameBtn, [setting.treeId, node], setting.edit.showRenameBtn)) {
+				return;
+			}
+			var aObj = $("#" + node.tId + consts.id.A),
+			editStr = "<span class='" + consts.className.BUTTON + " edit' id='" + node.tId + consts.id.EDIT + "' title='"+tools.apply(setting.edit.renameTitle, [setting.treeId, node], setting.edit.renameTitle)+"' treeNode"+consts.id.EDIT+" style='display:none;'></span>";
+			aObj.append(editStr);
+
+			$("#" + node.tId + consts.id.EDIT).bind('click',
+				function() {
+					if (!tools.uCanDo(setting) || tools.apply(setting.callback.beforeEditName, [setting.treeId, node], true) == false) return false;
+					view.editNode(setting, node);
+					return false;
+				}
+				).show();
+		},
+		addRemoveBtn: function(setting, node) {
+			if (node.editNameFlag || $("#" + node.tId + consts.id.REMOVE).length > 0) {
+				return;
+			}
+			if (!tools.apply(setting.edit.showRemoveBtn, [setting.treeId, node], setting.edit.showRemoveBtn)) {
+				return;
+			}
+			var aObj = $("#" + node.tId + consts.id.A),
+			removeStr = "<span class='" + consts.className.BUTTON + " remove' id='" + node.tId + consts.id.REMOVE + "' title='"+tools.apply(setting.edit.removeTitle, [setting.treeId, node], setting.edit.removeTitle)+"' treeNode"+consts.id.REMOVE+" style='display:none;'></span>";
+			aObj.append(removeStr);
+
+			$("#" + node.tId + consts.id.REMOVE).bind('click',
+				function() {
+					if (!tools.uCanDo(setting) || tools.apply(setting.callback.beforeRemove, [setting.treeId, node], true) == false) return false;
+					view.removeNode(setting, node);
+					setting.treeObj.trigger(consts.event.REMOVE, [setting.treeId, node]);
+					return false;
+				}
+				).bind('mousedown',
+				function(eventMouseDown) {
+					return true;
+				}
+				).show();
+		},
+		addHoverDom: function(setting, node) {
+			if (data.getRoot(setting).showHoverDom) {
+				node.isHover = true;
+				if (setting.edit.enable) {
+					view.addEditBtn(setting, node);
+					view.addRemoveBtn(setting, node);
+				}
+				tools.apply(setting.view.addHoverDom, [setting.treeId, node]);
+			}
+		},
+		cancelCurEditNode: function (setting, forceName) {
+			var root = data.getRoot(setting),
+			nameKey = setting.data.key.name,
+			node = root.curEditNode;
+			
+			if (node) {
+				var inputObj = root.curEditInput;
+				var newName = forceName ? forceName:inputObj.val();
+				if (!forceName && tools.apply(setting.callback.beforeRename, [setting.treeId, node, newName], true) === false) {
+					return false;
+				} else {
+					node[nameKey] = newName ? newName:inputObj.val();
+					if (!forceName) {
+						setting.treeObj.trigger(consts.event.RENAME, [setting.treeId, node]);
+					}
+				}
+				var aObj = $("#" + node.tId + consts.id.A);
+				aObj.removeClass(consts.node.CURSELECTED_EDIT);
+				inputObj.unbind();
+				view.setNodeName(setting, node);
+				node.editNameFlag = false;
+				root.curEditNode = null;
+				root.curEditInput = null;
+				view.selectNode(setting, node, false);
+			}
+			root.noSelection = true;
+			return true;
+		},
+		editNode: function(setting, node) {
+			var root = data.getRoot(setting);
+			view.editNodeBlur = false;
+			if (data.isSelectedNode(setting, node) && root.curEditNode == node && node.editNameFlag) {
+				setTimeout(function() {tools.inputFocus(root.curEditInput);}, 0);
+				return;
+			}
+			var nameKey = setting.data.key.name;
+			node.editNameFlag = true;
+			view.removeTreeDom(setting, node);
+			view.cancelCurEditNode(setting);
+			view.selectNode(setting, node, false);
+			$("#" + node.tId + consts.id.SPAN).html("<input type=text class='rename' id='" + node.tId + consts.id.INPUT + "' treeNode" + consts.id.INPUT + " >");
+			var inputObj = $("#" + node.tId + consts.id.INPUT);
+			inputObj.attr("value", node[nameKey]);
+			if (setting.edit.editNameSelectAll) {
+				tools.inputSelect(inputObj);
+			} else {
+				tools.inputFocus(inputObj);
+			}
+
+			inputObj.bind('blur', function(event) {
+				if (!view.editNodeBlur) {
+					view.cancelCurEditNode(setting);
+				}
+			}).bind('keydown', function(event) {
+				if (event.keyCode=="13") {
+					view.editNodeBlur = true;
+					view.cancelCurEditNode(setting, null, true);
+				} else if (event.keyCode=="27") {
+					view.cancelCurEditNode(setting, node[nameKey]);
+				}
+			}).bind('click', function(event) {
+				return false;
+			}).bind('dblclick', function(event) {
+				return false;
+			});
+
+			$("#" + node.tId + consts.id.A).addClass(consts.node.CURSELECTED_EDIT);
+			root.curEditInput = inputObj;
+			root.noSelection = false;
+			root.curEditNode = node;
+		},
+		moveNode: function(setting, targetNode, node, moveType, animateFlag, isSilent) {
+			var root = data.getRoot(setting),
+			childKey = setting.data.key.children;
+			if (targetNode == node) return;
+			if (setting.data.keep.leaf && targetNode && !targetNode.isParent && moveType == consts.move.TYPE_INNER) return;
+			var oldParentNode = (node.parentTId ? node.getParentNode(): root),
+			targetNodeIsRoot = (targetNode === null || targetNode == root);
+			if (targetNodeIsRoot && targetNode === null) targetNode = root;
+			if (targetNodeIsRoot) moveType = consts.move.TYPE_INNER;
+			var targetParentNode = (targetNode.parentTId ? targetNode.getParentNode() : root);
+
+			if (moveType != consts.move.TYPE_PREV && moveType != consts.move.TYPE_NEXT) {
+				moveType = consts.move.TYPE_INNER;
+			}
+			
+			if (moveType == consts.move.TYPE_INNER) {
+				if (targetNodeIsRoot) {
+					//parentTId of root node is null
+					node.parentTId = null;
+				} else {
+					if (!targetNode.isParent) {
+						targetNode.isParent = true;
+						targetNode.open = !!targetNode.open;
+						view.setNodeLineIcos(setting, targetNode);
+					}
+					node.parentTId = targetNode.tId;
+				}
+			}
+
+			//move node Dom
+			var targetObj, target_ulObj;
+			if (targetNodeIsRoot) {
+				targetObj = setting.treeObj;
+				target_ulObj = targetObj;
+			} else {
+				if (!isSilent && moveType == consts.move.TYPE_INNER) {
+					view.expandCollapseNode(setting, targetNode, true, false);
+				} else if (!isSilent) {
+					view.expandCollapseNode(setting, targetNode.getParentNode(), true, false);
+				}
+				targetObj = $("#" + targetNode.tId);
+				target_ulObj = $("#" + targetNode.tId + consts.id.UL);
+				if (!!targetObj.get(0) && !target_ulObj.get(0)) {
+					var ulstr = [];
+					view.makeUlHtml(setting, targetNode, ulstr, '');
+					targetObj.append(ulstr.join(''));
+				}
+				target_ulObj = $("#" + targetNode.tId + consts.id.UL);
+			}
+			var nodeDom = $("#" + node.tId);
+			if (!nodeDom.get(0)) {
+				nodeDom = view.appendNodes(setting, node.level, [node], null, false, true).join('');
+			} else if (!targetObj.get(0)) {
+				nodeDom.remove();
+			}
+			if (target_ulObj.get(0) && moveType == consts.move.TYPE_INNER) {
+				target_ulObj.append(nodeDom);
+			} else if (targetObj.get(0) && moveType == consts.move.TYPE_PREV) {
+				targetObj.before(nodeDom);
+			} else if (targetObj.get(0) && moveType == consts.move.TYPE_NEXT) {
+				targetObj.after(nodeDom);
+			}
+
+			//repair the data after move
+			var i,l,
+			tmpSrcIndex = -1,
+			tmpTargetIndex = 0,
+			oldNeighbor = null,
+			newNeighbor = null,
+			oldLevel = node.level;
+			if (node.isFirstNode) {
+				tmpSrcIndex = 0;
+				if (oldParentNode[childKey].length > 1 ) {
+					oldNeighbor = oldParentNode[childKey][1];
+					oldNeighbor.isFirstNode = true;
+				}
+			} else if (node.isLastNode) {
+				tmpSrcIndex = oldParentNode[childKey].length -1;
+				oldNeighbor = oldParentNode[childKey][tmpSrcIndex - 1];
+				oldNeighbor.isLastNode = true;
+			} else {
+				for (i = 0, l = oldParentNode[childKey].length; i < l; i++) {
+					if (oldParentNode[childKey][i].tId == node.tId) {
+						tmpSrcIndex = i;
+						break;
+					}
+				}
+			}
+			if (tmpSrcIndex >= 0) {
+				oldParentNode[childKey].splice(tmpSrcIndex, 1);
+			}
+			if (moveType != consts.move.TYPE_INNER) {
+				for (i = 0, l = targetParentNode[childKey].length; i < l; i++) {
+					if (targetParentNode[childKey][i].tId == targetNode.tId) tmpTargetIndex = i;
+				}
+			}
+			if (moveType == consts.move.TYPE_INNER) {
+				if (!targetNode[childKey]) targetNode[childKey] = new Array();
+				if (targetNode[childKey].length > 0) {
+					newNeighbor = targetNode[childKey][targetNode[childKey].length - 1];
+					newNeighbor.isLastNode = false;
+				}
+				targetNode[childKey].splice(targetNode[childKey].length, 0, node);
+				node.isLastNode = true;
+				node.isFirstNode = (targetNode[childKey].length == 1);
+			} else if (targetNode.isFirstNode && moveType == consts.move.TYPE_PREV) {
+				targetParentNode[childKey].splice(tmpTargetIndex, 0, node);
+				newNeighbor = targetNode;
+				newNeighbor.isFirstNode = false;
+				node.parentTId = targetNode.parentTId;
+				node.isFirstNode = true;
+				node.isLastNode = false;
+
+			} else if (targetNode.isLastNode && moveType == consts.move.TYPE_NEXT) {
+				targetParentNode[childKey].splice(tmpTargetIndex + 1, 0, node);
+				newNeighbor = targetNode;
+				newNeighbor.isLastNode = false;
+				node.parentTId = targetNode.parentTId;
+				node.isFirstNode = false;
+				node.isLastNode = true;
+
+			} else {
+				if (moveType == consts.move.TYPE_PREV) {
+					targetParentNode[childKey].splice(tmpTargetIndex, 0, node);
+				} else {
+					targetParentNode[childKey].splice(tmpTargetIndex + 1, 0, node);
+				}
+				node.parentTId = targetNode.parentTId;
+				node.isFirstNode = false;
+				node.isLastNode = false;
+			}
+			data.fixPIdKeyValue(setting, node);
+			data.setSonNodeLevel(setting, node.getParentNode(), node);
+
+			//repair node what been moved
+			view.setNodeLineIcos(setting, node);
+			view.repairNodeLevelClass(setting, node, oldLevel)
+
+			//repair node's old parentNode dom
+			if (!setting.data.keep.parent && oldParentNode[childKey].length < 1) {
+				//old parentNode has no child nodes
+				oldParentNode.isParent = false;
+				oldParentNode.open = false;
+				var tmp_ulObj = $("#" + oldParentNode.tId + consts.id.UL),
+				tmp_switchObj = $("#" + oldParentNode.tId + consts.id.SWITCH),
+				tmp_icoObj = $("#" + oldParentNode.tId + consts.id.ICON);
+				view.replaceSwitchClass(oldParentNode, tmp_switchObj, consts.folder.DOCU);
+				view.replaceIcoClass(oldParentNode, tmp_icoObj, consts.folder.DOCU);
+				tmp_ulObj.css("display", "none");
+
+			} else if (oldNeighbor) {
+				//old neigbor node
+				view.setNodeLineIcos(setting, oldNeighbor);
+			}
+
+			//new neigbor node
+			if (newNeighbor) {
+				view.setNodeLineIcos(setting, newNeighbor);
+			}
+
+			//repair checkbox / radio
+			if (!!setting.check && setting.check.enable && view.repairChkClass) {
+				view.repairChkClass(setting, oldParentNode);
+				view.repairParentChkClassWithSelf(setting, oldParentNode);
+				if (oldParentNode != node.parent)
+					view.repairParentChkClassWithSelf(setting, node);
+			}
+
+			//expand parents after move
+			if (!isSilent) {
+				view.expandCollapseParentNode(setting, node.getParentNode(), true, animateFlag);
+			}
+		},
+		removeEditBtn: function(node) {
+			$("#" + node.tId + consts.id.EDIT).unbind().remove();
+		},
+		removeRemoveBtn: function(node) {
+			$("#" + node.tId + consts.id.REMOVE).unbind().remove();
+		},
+		removeTreeDom: function(setting, node) {
+			node.isHover = false;
+			view.removeEditBtn(node);
+			view.removeRemoveBtn(node);
+			tools.apply(setting.view.removeHoverDom, [setting.treeId, node]);
+		},
+		repairNodeLevelClass: function(setting, node, oldLevel) {
+			if (oldLevel === node.level) return;
+			var liObj = $("#" + node.tId),
+			aObj = $("#" + node.tId + consts.id.A),
+			ulObj = $("#" + node.tId + consts.id.UL),
+			oldClass = consts.className.LEVEL + oldLevel,
+			newClass = consts.className.LEVEL + node.level;
+			liObj.removeClass(oldClass);
+			liObj.addClass(newClass);
+			aObj.removeClass(oldClass);
+			aObj.addClass(newClass);
+			ulObj.removeClass(oldClass);
+			ulObj.addClass(newClass);
+		}
+	},
+
+	_z = {
+		tools: _tools,
+		view: _view,
+		event: _event,
+		data: _data
+	};
+	$.extend(true, $.fn.zTree.consts, _consts);
+	$.extend(true, $.fn.zTree._z, _z);
+
+	var zt = $.fn.zTree,
+	tools = zt._z.tools,
+	consts = zt.consts,
+	view = zt._z.view,
+	data = zt._z.data,
+	event = zt._z.event;
+
+	data.exSetting(_setting);
+	data.addInitBind(_bindEvent);
+	data.addInitUnBind(_unbindEvent);
+	data.addInitCache(_initCache);
+	data.addInitNode(_initNode);
+	data.addInitProxy(_eventProxy);
+	data.addInitRoot(_initRoot);
+	data.addZTreeTools(_zTreeTools);
+
+	var _cancelPreSelectedNode = view.cancelPreSelectedNode;
+	view.cancelPreSelectedNode = function (setting, node) {
+		var list = data.getRoot(setting).curSelectedList;
+		for (var i=0, j=list.length; i<j; i++) {
+			if (!node || node === list[i]) {
+				view.removeTreeDom(setting, list[i]);
+				if (node) break;
+			}
+		}
+		if (_cancelPreSelectedNode) _cancelPreSelectedNode.apply(view, arguments);
+	}
+
+	var _createNodes = view.createNodes;
+	view.createNodes = function(setting, level, nodes, parentNode) {
+		if (_createNodes) {
+			_createNodes.apply(view, arguments);
+		}
+		if (!nodes) return;
+		if (view.repairParentChkClassWithSelf) {
+			view.repairParentChkClassWithSelf(setting, parentNode);
+		}
+	}
+
+	var _makeNodeUrl = view.makeNodeUrl;
+	view.makeNodeUrl = function(setting, node) {
+		return setting.edit.enable ? null : (_makeNodeUrl.apply(view, arguments));
+	}
+
+	var _removeNode = view.removeNode;
+	view.removeNode = function(setting, node) {
+		var root = data.getRoot(setting);
+		if (root.curEditNode === node) root.curEditNode = null;
+		if (_removeNode) {
+			_removeNode.apply(view, arguments);
+		}
+	}
+
+	var _selectNode = view.selectNode;
+	view.selectNode = function(setting, node, addFlag) {
+		var root = data.getRoot(setting);
+		if (data.isSelectedNode(setting, node) && root.curEditNode == node && node.editNameFlag) {
+			return false;
+		}
+		if (_selectNode) _selectNode.apply(view, arguments);
+		view.addHoverDom(setting, node);
+		return true;
+	}
+
+	var _uCanDo = tools.uCanDo;
+	tools.uCanDo = function(setting, e) {
+		var root = data.getRoot(setting);
+		if (e && (tools.eqs(e.type, "mouseover") || tools.eqs(e.type, "mouseout") || tools.eqs(e.type, "mousedown") || tools.eqs(e.type, "mouseup"))) {
+			return true;
+		}
+		return (!root.curEditNode) && (_uCanDo ? _uCanDo.apply(view, arguments) : true);
+	}
+})(jQuery);
+
+/*
+ * JQuery zTree exHideNodes 3.5.12
+ * http://zTree.me/
+ *
+ * Copyright (c) 2010 Hunter.z
+ *
+ * Licensed same as jquery - MIT License
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ * email: hunter.z@263.net
+ * Date: 2013-03-11
+ */
+(function($){
+	//default init node of exLib
+	var _initNode = function(setting, level, n, parentNode, isFirstNode, isLastNode, openFlag) {
+		if (typeof n.isHidden == "string") n.isHidden = tools.eqs(n.isHidden, "true");
+		n.isHidden = !!n.isHidden;
+		data.initHideForExCheck(setting, n);
+	},
+	//add dom for check
+	_beforeA = function(setting, node, html) {},
+	//update zTreeObj, add method of exLib
+	_zTreeTools = function(setting, zTreeTools) {
+		zTreeTools.showNodes = function(nodes, options) {
+			view.showNodes(setting, nodes, options);
+		}
+		zTreeTools.showNode = function(node, options) {
+			if (!node) {
+				return;
+			}
+			view.showNodes(setting, [node], options);
+		}
+		zTreeTools.hideNodes = function(nodes, options) {
+			view.hideNodes(setting, nodes, options);
+		}
+		zTreeTools.hideNode = function(node, options) {
+			if (!node) {
+				return;
+			}
+			view.hideNodes(setting, [node], options);
+		}
+
+		var _checkNode = zTreeTools.checkNode;
+		if (_checkNode) {
+			zTreeTools.checkNode = function(node, checked, checkTypeFlag, callbackFlag) {
+				if (!!node && !!node.isHidden) {
+					return;
+				}
+				_checkNode.apply(zTreeTools, arguments);
+			}
+		}
+	},
+	//method of operate data
+	_data = {
+		initHideForExCheck: function(setting, n) {
+			if (n.isHidden && setting.check && setting.check.enable) {
+				if(typeof n._nocheck == "undefined") {
+					n._nocheck = !!n.nocheck
+					n.nocheck = true;
+				}
+				n.check_Child_State = -1;
+				if (view.repairParentChkClassWithSelf) {
+					view.repairParentChkClassWithSelf(setting, n);
+				}
+			}
+		},
+		initShowForExCheck: function(setting, n) {
+			if (!n.isHidden && setting.check && setting.check.enable) {
+				if(typeof n._nocheck != "undefined") {
+					n.nocheck = n._nocheck;
+					delete n._nocheck;
+				}
+				if (view.setChkClass) {
+					var checkObj = $("#" + n.tId + consts.id.CHECK);
+					view.setChkClass(setting, checkObj, n);
+				}
+				if (view.repairParentChkClassWithSelf) {
+					view.repairParentChkClassWithSelf(setting, n);
+				}
+			}
+		}
+	},
+	//method of operate ztree dom
+	_view = {
+		clearOldFirstNode: function(setting, node) {
+			var n = node.getNextNode();
+			while(!!n){
+				if (n.isFirstNode) {
+					n.isFirstNode = false;
+					view.setNodeLineIcos(setting, n);
+					break;
+				}
+				if (n.isLastNode) {
+					break;
+				}
+				n = n.getNextNode();
+			}
+		},
+		clearOldLastNode: function(setting, node) {
+			var n = node.getPreNode();
+			while(!!n){
+				if (n.isLastNode) {
+					n.isLastNode = false;
+					view.setNodeLineIcos(setting, n);
+					break;
+				}
+				if (n.isFirstNode) {
+					break;
+				}
+				n = n.getPreNode();
+			}
+		},
+		makeDOMNodeMainBefore: function(html, setting, node) {
+			html.push("<li ", (node.isHidden ? "style='display:none;' " : ""), "id='", node.tId, "' class='", consts.className.LEVEL, node.level,"' tabindex='0' hidefocus='true' treenode>");
+		},
+		showNode: function(setting, node, options) {
+			node.isHidden = false;
+			data.initShowForExCheck(setting, node);
+			$("#" + node.tId).show();
+		},
+		showNodes: function(setting, nodes, options) {
+			if (!nodes || nodes.length == 0) {
+				return;
+			}
+			var pList = {}, i, j;
+			for (i=0, j=nodes.length; i<j; i++) {
+				var n = nodes[i];
+				if (!pList[n.parentTId]) {
+					var pn = n.getParentNode();
+					pList[n.parentTId] = (pn === null) ? data.getRoot(setting) : n.getParentNode();
+				}
+				view.showNode(setting, n, options);
+			}
+			for (var tId in pList) {
+				var children = pList[tId][setting.data.key.children];
+				view.setFirstNodeForShow(setting, children);
+				view.setLastNodeForShow(setting, children);
+			}
+		},
+		hideNode: function(setting, node, options) {
+			node.isHidden = true;
+			node.isFirstNode = false;
+			node.isLastNode = false;
+			data.initHideForExCheck(setting, node);
+			view.cancelPreSelectedNode(setting, node);
+			$("#" + node.tId).hide();
+		},
+		hideNodes: function(setting, nodes, options) {
+			if (!nodes || nodes.length == 0) {
+				return;
+			}
+			var pList = {}, i, j;
+			for (i=0, j=nodes.length; i<j; i++) {
+				var n = nodes[i];
+				if ((n.isFirstNode || n.isLastNode) && !pList[n.parentTId]) {
+					var pn = n.getParentNode();
+					pList[n.parentTId] = (pn === null) ? data.getRoot(setting) : n.getParentNode();
+				}
+				view.hideNode(setting, n, options);
+			}
+			for (var tId in pList) {
+				var children = pList[tId][setting.data.key.children];
+				view.setFirstNodeForHide(setting, children);
+				view.setLastNodeForHide(setting, children);
+			}
+		},
+		setFirstNode: function(setting, parentNode) {
+			var childKey = setting.data.key.children, childLength = parentNode[childKey].length;
+			if (childLength > 0 && !parentNode[childKey][0].isHidden) {
+				parentNode[childKey][0].isFirstNode = true;
+			} else if (childLength > 0) {
+				view.setFirstNodeForHide(setting, parentNode[childKey]);
+			}
+		},
+		setLastNode: function(setting, parentNode) {
+			var childKey = setting.data.key.children, childLength = parentNode[childKey].length;
+			if (childLength > 0 && !parentNode[childKey][0].isHidden) {
+				parentNode[childKey][childLength - 1].isLastNode = true;
+			} else if (childLength > 0) {
+				view.setLastNodeForHide(setting, parentNode[childKey]);
+			}
+		},
+		setFirstNodeForHide: function(setting, nodes) {
+			var n,i,j;
+			for (i=0, j=nodes.length; i<j; i++) {
+				n = nodes[i];
+				if (n.isFirstNode) {
+					break;
+				}
+				if (!n.isHidden && !n.isFirstNode) {
+					n.isFirstNode = true;
+					view.setNodeLineIcos(setting, n);
+					break;
+				} else {
+					n = null;
+				}
+			}
+			return n;
+		},
+		setFirstNodeForShow: function(setting, nodes) {
+			var n,i,j, first, old;
+			for(i=0, j=nodes.length; i<j; i++) {
+				n = nodes[i];
+				if (!first && !n.isHidden && n.isFirstNode) {
+					first = n;
+					break;
+				} else if (!first && !n.isHidden && !n.isFirstNode) {
+					n.isFirstNode = true;
+					first = n;
+					view.setNodeLineIcos(setting, n);
+				} else if (first && n.isFirstNode) {
+					n.isFirstNode = false;
+					old = n;
+					view.setNodeLineIcos(setting, n);
+					break;
+				} else {
+					n = null;
+				}
+			}
+			return {"new":first, "old":old};
+		},
+		setLastNodeForHide: function(setting, nodes) {
+			var n,i;
+			for (i=nodes.length-1; i>=0; i--) {
+				n = nodes[i];
+				if (n.isLastNode) {
+					break;
+				}
+				if (!n.isHidden && !n.isLastNode) {
+					n.isLastNode = true;
+					view.setNodeLineIcos(setting, n);
+					break;
+				} else {
+					n = null;
+				}
+			}
+			return n;
+		},
+		setLastNodeForShow: function(setting, nodes) {
+			var n,i,j, last, old;
+			for (i=nodes.length-1; i>=0; i--) {
+				n = nodes[i];
+				if (!last && !n.isHidden && n.isLastNode) {
+					last = n;
+					break;
+				} else if (!last && !n.isHidden && !n.isLastNode) {
+					n.isLastNode = true;
+					last = n;
+					view.setNodeLineIcos(setting, n);
+				} else if (last && n.isLastNode) {
+					n.isLastNode = false;
+					old = n;
+					view.setNodeLineIcos(setting, n);
+					break;
+				} else {
+					n = null;
+				}
+			}
+			return {"new":last, "old":old};
+		}
+	},
+
+	_z = {
+		view: _view,
+		data: _data
+	};
+	$.extend(true, $.fn.zTree._z, _z);
+
+	var zt = $.fn.zTree,
+	tools = zt._z.tools,
+	consts = zt.consts,
+	view = zt._z.view,
+	data = zt._z.data,
+	event = zt._z.event;
+
+	data.addInitNode(_initNode);
+	data.addBeforeA(_beforeA);
+	data.addZTreeTools(_zTreeTools);
+
+//	Override method in core
+	var _dInitNode = data.initNode;
+	data.tmpHideParent = -1;
+	data.initNode = function(setting, level, node, parentNode, isFirstNode, isLastNode, openFlag) {
+		if (data.tmpHideParent !== parentNode) {
+			data.tmpHideParent = parentNode;
+			var tmpPNode = (parentNode) ? parentNode: data.getRoot(setting),
+			children = tmpPNode[setting.data.key.children];
+			data.tmpHideFirstNode = view.setFirstNodeForHide(setting, children);
+			data.tmpHideLastNode = view.setLastNodeForHide(setting, children);
+			view.setNodeLineIcos(setting, data.tmpHideFirstNode);
+			view.setNodeLineIcos(setting, data.tmpHideLastNode);
+		}
+		isFirstNode = (data.tmpHideFirstNode === node);
+		isLastNode = (data.tmpHideLastNode === node);
+		if (_dInitNode) _dInitNode.apply(data, arguments);
+		if (isLastNode) {
+			view.clearOldLastNode(setting, node);
+		}
+	}
+
+	var _makeChkFlag = data.makeChkFlag;
+	if (!!_makeChkFlag) {
+		data.makeChkFlag = function(setting, node) {
+			if (!!node && !!node.isHidden) {
+				return;
+			}
+			_makeChkFlag.apply(data, arguments);
+		}
+	}
+
+	var _getTreeCheckedNodes = data.getTreeCheckedNodes;
+	if (!!_getTreeCheckedNodes) {
+		data.getTreeCheckedNodes = function(setting, nodes, checked, results) {
+			if (!!nodes && nodes.length > 0) {
+				var p = nodes[0].getParentNode();
+				if (!!p && !!p.isHidden) {
+					return [];
+				}
+			}
+			return _getTreeCheckedNodes.apply(data, arguments);
+		}
+	}
+
+	var _getTreeChangeCheckedNodes = data.getTreeChangeCheckedNodes;
+	if (!!_getTreeChangeCheckedNodes) {
+		data.getTreeChangeCheckedNodes = function(setting, nodes, results) {
+			if (!!nodes && nodes.length > 0) {
+				var p = nodes[0].getParentNode();
+				if (!!p && !!p.isHidden) {
+					return [];
+				}
+			}
+			return _getTreeChangeCheckedNodes.apply(data, arguments);
+		}
+	}
+
+	var _expandCollapseSonNode = view.expandCollapseSonNode;
+	if (!!_expandCollapseSonNode) {
+		view.expandCollapseSonNode = function(setting, node, expandFlag, animateFlag, callback) {
+			if (!!node && !!node.isHidden) {
+				return;
+			}
+			_expandCollapseSonNode.apply(view, arguments);
+		}
+	}
+
+	var _setSonNodeCheckBox = view.setSonNodeCheckBox;
+	if (!!_setSonNodeCheckBox) {
+		view.setSonNodeCheckBox = function(setting, node, value, srcNode) {
+			if (!!node && !!node.isHidden) {
+				return;
+			}
+			_setSonNodeCheckBox.apply(view, arguments);
+		}
+	}
+
+	var _repairParentChkClassWithSelf = view.repairParentChkClassWithSelf;
+	if (!!_repairParentChkClassWithSelf) {
+		view.repairParentChkClassWithSelf = function(setting, node) {
+			if (!!node && !!node.isHidden) {
+				return;
+			}
+			_repairParentChkClassWithSelf.apply(view, arguments);
+		}
+	}
+})(jQuery);
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/js/jquery.ztree.core-3.5.js b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/js/jquery.ztree.core-3.5.js
new file mode 100644
index 0000000..d8bc64f
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/js/jquery.ztree.core-3.5.js
@@ -0,0 +1,1650 @@
+/*
+ * JQuery zTree core 3.5.12
+ * http://zTree.me/
+ *
+ * Copyright (c) 2010 Hunter.z
+ *
+ * Licensed same as jquery - MIT License
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ * email: hunter.z@263.net
+ * Date: 2013-03-11
+ */
+(function($){
+	var settings = {}, roots = {}, caches = {},
+	//default consts of core
+	_consts = {
+		className: {
+			BUTTON: "button",
+			LEVEL: "level",
+			ICO_LOADING: "ico_loading",
+			SWITCH: "switch"
+		},
+		event: {
+			NODECREATED: "ztree_nodeCreated",
+			CLICK: "ztree_click",
+			EXPAND: "ztree_expand",
+			COLLAPSE: "ztree_collapse",
+			ASYNC_SUCCESS: "ztree_async_success",
+			ASYNC_ERROR: "ztree_async_error"
+		},
+		id: {
+			A: "_a",
+			ICON: "_ico",
+			SPAN: "_span",
+			SWITCH: "_switch",
+			UL: "_ul"
+		},
+		line: {
+			ROOT: "root",
+			ROOTS: "roots",
+			CENTER: "center",
+			BOTTOM: "bottom",
+			NOLINE: "noline",
+			LINE: "line"
+		},
+		folder: {
+			OPEN: "open",
+			CLOSE: "close",
+			DOCU: "docu"
+		},
+		node: {
+			CURSELECTED: "curSelectedNode"
+		}
+	},
+	//default setting of core
+	_setting = {
+		treeId: "",
+		treeObj: null,
+		view: {
+			addDiyDom: null,
+			autoCancelSelected: true,
+			dblClickExpand: true,
+			expandSpeed: "fast",
+			fontCss: {},
+			nameIsHTML: false,
+			selectedMulti: true,
+			showIcon: true,
+			showLine: true,
+			showTitle: true
+		},
+		data: {
+			key: {
+				children: "children",
+				name: "name",
+				title: "",
+				url: "url"
+			},
+			simpleData: {
+				enable: false,
+				idKey: "id",
+				pIdKey: "pId",
+				rootPId: null
+			},
+			keep: {
+				parent: false,
+				leaf: false
+			}
+		},
+		async: {
+			enable: false,
+			contentType: "application/x-www-form-urlencoded",
+			type: "post",
+			dataType: "text",
+			url: "",
+			autoParam: [],
+			otherParam: [],
+			dataFilter: null
+		},
+		callback: {
+			beforeAsync:null,
+			beforeClick:null,
+			beforeDblClick:null,
+			beforeRightClick:null,
+			beforeMouseDown:null,
+			beforeMouseUp:null,
+			beforeExpand:null,
+			beforeCollapse:null,
+			beforeRemove:null,
+
+			onAsyncError:null,
+			onAsyncSuccess:null,
+			onNodeCreated:null,
+			onClick:null,
+			onDblClick:null,
+			onRightClick:null,
+			onMouseDown:null,
+			onMouseUp:null,
+			onExpand:null,
+			onCollapse:null,
+			onRemove:null
+		}
+	},
+	//default root of core
+	//zTree use root to save full data
+	_initRoot = function (setting) {
+		var r = data.getRoot(setting);
+		if (!r) {
+			r = {};
+			data.setRoot(setting, r);
+		}
+		r[setting.data.key.children] = [];
+		r.expandTriggerFlag = false;
+		r.curSelectedList = [];
+		r.noSelection = true;
+		r.createdNodes = [];
+		r.zId = 0;
+		r._ver = (new Date()).getTime();
+	},
+	//default cache of core
+	_initCache = function(setting) {
+		var c = data.getCache(setting);
+		if (!c) {
+			c = {};
+			data.setCache(setting, c);
+		}
+		c.nodes = [];
+		c.doms = [];
+	},
+	//default bindEvent of core
+	_bindEvent = function(setting) {
+		var o = setting.treeObj,
+		c = consts.event;
+		o.bind(c.NODECREATED, function (event, treeId, node) {
+			tools.apply(setting.callback.onNodeCreated, [event, treeId, node]);
+		});
+
+		o.bind(c.CLICK, function (event, srcEvent, treeId, node, clickFlag) {
+			tools.apply(setting.callback.onClick, [srcEvent, treeId, node, clickFlag]);
+		});
+
+		o.bind(c.EXPAND, function (event, treeId, node) {
+			tools.apply(setting.callback.onExpand, [event, treeId, node]);
+		});
+
+		o.bind(c.COLLAPSE, function (event, treeId, node) {
+			tools.apply(setting.callback.onCollapse, [event, treeId, node]);
+		});
+
+		o.bind(c.ASYNC_SUCCESS, function (event, treeId, node, msg) {
+			tools.apply(setting.callback.onAsyncSuccess, [event, treeId, node, msg]);
+		});
+
+		o.bind(c.ASYNC_ERROR, function (event, treeId, node, XMLHttpRequest, textStatus, errorThrown) {
+			tools.apply(setting.callback.onAsyncError, [event, treeId, node, XMLHttpRequest, textStatus, errorThrown]);
+		});
+	},
+	_unbindEvent = function(setting) {
+		var o = setting.treeObj,
+		c = consts.event;
+		o.unbind(c.NODECREATED)
+		.unbind(c.CLICK)
+		.unbind(c.EXPAND)
+		.unbind(c.COLLAPSE)
+		.unbind(c.ASYNC_SUCCESS)
+		.unbind(c.ASYNC_ERROR);
+	},	
+	//default event proxy of core
+	_eventProxy = function(event) {
+		var target = event.target,
+		setting = data.getSetting(event.data.treeId),
+		tId = "", node = null,
+		nodeEventType = "", treeEventType = "",
+		nodeEventCallback = null, treeEventCallback = null,
+		tmp = null;
+
+		if (tools.eqs(event.type, "mousedown")) {
+			treeEventType = "mousedown";
+		} else if (tools.eqs(event.type, "mouseup")) {
+			treeEventType = "mouseup";
+		} else if (tools.eqs(event.type, "contextmenu")) {
+			treeEventType = "contextmenu";
+		} else if (tools.eqs(event.type, "click")) {
+			if (tools.eqs(target.tagName, "span") && target.getAttribute("treeNode"+ consts.id.SWITCH) !== null) {
+				tId = ($(target).parent("li").get(0) || $(target).parentsUntil("li").parent().get(0)).id;
+				nodeEventType = "switchNode";
+			} else {
+				tmp = tools.getMDom(setting, target, [{tagName:"a", attrName:"treeNode"+consts.id.A}]);
+				if (tmp) {
+					tId = ($(tmp).parent("li").get(0) || $(tmp).parentsUntil("li").parent().get(0)).id;
+					nodeEventType = "clickNode";
+				}
+			}
+		} else if (tools.eqs(event.type, "dblclick")) {
+			treeEventType = "dblclick";
+			tmp = tools.getMDom(setting, target, [{tagName:"a", attrName:"treeNode"+consts.id.A}]);
+			if (tmp) {
+				tId = ($(tmp).parent("li").get(0) || $(tmp).parentsUntil("li").parent().get(0)).id;
+				nodeEventType = "switchNode";
+			}
+		}
+		if (treeEventType.length > 0 && tId.length == 0) {
+			tmp = tools.getMDom(setting, target, [{tagName:"a", attrName:"treeNode"+consts.id.A}]);
+			if (tmp) {tId = ($(tmp).parent("li").get(0) || $(tmp).parentsUntil("li").parent().get(0)).id;}
+		}
+		// event to node
+		if (tId.length>0) {
+			node = data.getNodeCache(setting, tId);
+			switch (nodeEventType) {
+				case "switchNode" :
+					if (!node.isParent) {
+						nodeEventType = "";
+					} else if (tools.eqs(event.type, "click") 
+						|| (tools.eqs(event.type, "dblclick") && tools.apply(setting.view.dblClickExpand, [setting.treeId, node], setting.view.dblClickExpand))) {
+						nodeEventCallback = handler.onSwitchNode;
+					} else {
+						nodeEventType = "";
+					}
+					break;
+				case "clickNode" :
+					nodeEventCallback = handler.onClickNode;
+					break;
+			}
+		}
+		// event to zTree
+		switch (treeEventType) {
+			case "mousedown" :
+				treeEventCallback = handler.onZTreeMousedown;
+				break;
+			case "mouseup" :
+				treeEventCallback = handler.onZTreeMouseup;
+				break;
+			case "dblclick" :
+				treeEventCallback = handler.onZTreeDblclick;
+				break;
+			case "contextmenu" :
+				treeEventCallback = handler.onZTreeContextmenu;
+				break;
+		}
+		var proxyResult = {
+			stop: false,
+			node: node,
+			nodeEventType: nodeEventType,
+			nodeEventCallback: nodeEventCallback,
+			treeEventType: treeEventType,
+			treeEventCallback: treeEventCallback
+		};
+		return proxyResult
+	},
+	//default init node of core
+	_initNode = function(setting, level, n, parentNode, isFirstNode, isLastNode, openFlag) {
+		if (!n) return;
+		var r = data.getRoot(setting),
+		childKey = setting.data.key.children;
+		n.level = level;
+		n.tId = setting.treeId + "_" + (++r.zId);
+		n.parentTId = parentNode ? parentNode.tId : null;
+		if (n[childKey] && n[childKey].length > 0) {
+			if (typeof n.open == "string") n.open = tools.eqs(n.open, "true");
+			n.open = !!n.open;
+			n.isParent = true;
+			n.zAsync = true;
+		} else {
+			n.open = false;
+			if (typeof n.isParent == "string") n.isParent = tools.eqs(n.isParent, "true");
+			n.isParent = !!n.isParent;
+			n.zAsync = !n.isParent;
+		}
+		n.isFirstNode = isFirstNode;
+		n.isLastNode = isLastNode;
+		n.getParentNode = function() {return data.getNodeCache(setting, n.parentTId);};
+		n.getPreNode = function() {return data.getPreNode(setting, n);};
+		n.getNextNode = function() {return data.getNextNode(setting, n);};
+		n.isAjaxing = false;
+		data.fixPIdKeyValue(setting, n);
+	},
+	_init = {
+		bind: [_bindEvent],
+		unbind: [_unbindEvent],
+		caches: [_initCache],
+		nodes: [_initNode],
+		proxys: [_eventProxy],
+		roots: [_initRoot],
+		beforeA: [],
+		afterA: [],
+		innerBeforeA: [],
+		innerAfterA: [],
+		zTreeTools: []
+	},
+	//method of operate data
+	data = {
+		addNodeCache: function(setting, node) {
+			data.getCache(setting).nodes[data.getNodeCacheId(node.tId)] = node;
+		},
+		getNodeCacheId: function(tId) {
+			return tId.substring(tId.lastIndexOf("_")+1);
+		},
+		addAfterA: function(afterA) {
+			_init.afterA.push(afterA);
+		},
+		addBeforeA: function(beforeA) {
+			_init.beforeA.push(beforeA);
+		},
+		addInnerAfterA: function(innerAfterA) {
+			_init.innerAfterA.push(innerAfterA);
+		},
+		addInnerBeforeA: function(innerBeforeA) {
+			_init.innerBeforeA.push(innerBeforeA);
+		},
+		addInitBind: function(bindEvent) {
+			_init.bind.push(bindEvent);
+		},
+		addInitUnBind: function(unbindEvent) {
+			_init.unbind.push(unbindEvent);
+		},
+		addInitCache: function(initCache) {
+			_init.caches.push(initCache);
+		},
+		addInitNode: function(initNode) {
+			_init.nodes.push(initNode);
+		},
+		addInitProxy: function(initProxy) {
+			_init.proxys.push(initProxy);
+		},
+		addInitRoot: function(initRoot) {
+			_init.roots.push(initRoot);
+		},
+		addNodesData: function(setting, parentNode, nodes) {
+			var childKey = setting.data.key.children;
+			if (!parentNode[childKey]) parentNode[childKey] = [];
+			if (parentNode[childKey].length > 0) {
+				parentNode[childKey][parentNode[childKey].length - 1].isLastNode = false;
+				view.setNodeLineIcos(setting, parentNode[childKey][parentNode[childKey].length - 1]);
+			}
+			parentNode.isParent = true;
+			parentNode[childKey] = parentNode[childKey].concat(nodes);
+		},
+		addSelectedNode: function(setting, node) {
+			var root = data.getRoot(setting);
+			if (!data.isSelectedNode(setting, node)) {
+				root.curSelectedList.push(node);
+			}
+		},
+		addCreatedNode: function(setting, node) {
+			if (!!setting.callback.onNodeCreated || !!setting.view.addDiyDom) {
+				var root = data.getRoot(setting);
+				root.createdNodes.push(node);
+			}
+		},
+		addZTreeTools: function(zTreeTools) {
+			_init.zTreeTools.push(zTreeTools);
+		},
+		exSetting: function(s) {
+			$.extend(true, _setting, s);
+		},
+		fixPIdKeyValue: function(setting, node) {
+			if (setting.data.simpleData.enable) {
+				node[setting.data.simpleData.pIdKey] = node.parentTId ? node.getParentNode()[setting.data.simpleData.idKey] : setting.data.simpleData.rootPId;
+			}
+		},
+		getAfterA: function(setting, node, array) {
+			for (var i=0, j=_init.afterA.length; i<j; i++) {
+				_init.afterA[i].apply(this, arguments);
+			}
+		},
+		getBeforeA: function(setting, node, array) {
+			for (var i=0, j=_init.beforeA.length; i<j; i++) {
+				_init.beforeA[i].apply(this, arguments);
+			}
+		},
+		getInnerAfterA: function(setting, node, array) {
+			for (var i=0, j=_init.innerAfterA.length; i<j; i++) {
+				_init.innerAfterA[i].apply(this, arguments);
+			}
+		},
+		getInnerBeforeA: function(setting, node, array) {
+			for (var i=0, j=_init.innerBeforeA.length; i<j; i++) {
+				_init.innerBeforeA[i].apply(this, arguments);
+			}
+		},
+		getCache: function(setting) {
+			return caches[setting.treeId];
+		},
+		getNextNode: function(setting, node) {
+			if (!node) return null;
+			var childKey = setting.data.key.children,
+			p = node.parentTId ? node.getParentNode() : data.getRoot(setting);
+			for (var i=0, l=p[childKey].length-1; i<=l; i++) {
+				if (p[childKey][i] === node) {
+					return (i==l ? null : p[childKey][i+1]);
+				}
+			}
+			return null;
+		},
+		getNodeByParam: function(setting, nodes, key, value) {
+			if (!nodes || !key) return null;
+			var childKey = setting.data.key.children;
+			for (var i = 0, l = nodes.length; i < l; i++) {
+				if (nodes[i][key] == value) {
+					return nodes[i];
+				}
+				var tmp = data.getNodeByParam(setting, nodes[i][childKey], key, value);
+				if (tmp) return tmp;
+			}
+			return null;
+		},
+		getNodeCache: function(setting, tId) {
+			if (!tId) return null;
+			var n = caches[setting.treeId].nodes[data.getNodeCacheId(tId)];
+			return n ? n : null;
+		},
+		getNodeName: function(setting, node) {
+			var nameKey = setting.data.key.name;
+			return "" + node[nameKey];
+		},
+		getNodeTitle: function(setting, node) {
+			var t = setting.data.key.title === "" ? setting.data.key.name : setting.data.key.title;
+			return "" + node[t];
+		},
+		getNodes: function(setting) {
+			return data.getRoot(setting)[setting.data.key.children];
+		},
+		getNodesByParam: function(setting, nodes, key, value) {
+			if (!nodes || !key) return [];
+			var childKey = setting.data.key.children,
+			result = [];
+			for (var i = 0, l = nodes.length; i < l; i++) {
+				if (nodes[i][key] == value) {
+					result.push(nodes[i]);
+				}
+				result = result.concat(data.getNodesByParam(setting, nodes[i][childKey], key, value));
+			}
+			return result;
+		},
+		getNodesByParamFuzzy: function(setting, nodes, key, value) {
+			if (!nodes || !key) return [];
+			var childKey = setting.data.key.children,
+			result = [];
+			value = value.toLowerCase();
+			for (var i = 0, l = nodes.length; i < l; i++) {
+				if (typeof nodes[i][key] == "string" && nodes[i][key].toLowerCase().indexOf(value)>-1) {
+					result.push(nodes[i]);
+				}
+				result = result.concat(data.getNodesByParamFuzzy(setting, nodes[i][childKey], key, value));
+			}
+			return result;
+		},
+		getNodesByFilter: function(setting, nodes, filter, isSingle, invokeParam) {
+			if (!nodes) return (isSingle ? null : []);
+			var childKey = setting.data.key.children,
+			result = isSingle ? null : [];
+			for (var i = 0, l = nodes.length; i < l; i++) {
+				if (tools.apply(filter, [nodes[i], invokeParam], false)) {
+					if (isSingle) {return nodes[i];}
+					result.push(nodes[i]);
+				}
+				var tmpResult = data.getNodesByFilter(setting, nodes[i][childKey], filter, isSingle, invokeParam);
+				if (isSingle && !!tmpResult) {return tmpResult;}
+				result = isSingle ? tmpResult : result.concat(tmpResult);
+			}
+			return result;
+		},
+		getPreNode: function(setting, node) {
+			if (!node) return null;
+			var childKey = setting.data.key.children,
+			p = node.parentTId ? node.getParentNode() : data.getRoot(setting);
+			for (var i=0, l=p[childKey].length; i<l; i++) {
+				if (p[childKey][i] === node) {
+					return (i==0 ? null : p[childKey][i-1]);
+				}
+			}
+			return null;
+		},
+		getRoot: function(setting) {
+			return setting ? roots[setting.treeId] : null;
+		},
+		getSetting: function(treeId) {
+			return settings[treeId];
+		},
+		getSettings: function() {
+			return settings;
+		},
+		getZTreeTools: function(treeId) {
+			var r = this.getRoot(this.getSetting(treeId));
+			return r ? r.treeTools : null;
+		},
+		initCache: function(setting) {
+			for (var i=0, j=_init.caches.length; i<j; i++) {
+				_init.caches[i].apply(this, arguments);
+			}
+		},
+		initNode: function(setting, level, node, parentNode, preNode, nextNode) {
+			for (var i=0, j=_init.nodes.length; i<j; i++) {
+				_init.nodes[i].apply(this, arguments);
+			}
+		},
+		initRoot: function(setting) {
+			for (var i=0, j=_init.roots.length; i<j; i++) {
+				_init.roots[i].apply(this, arguments);
+			}
+		},
+		isSelectedNode: function(setting, node) {
+			var root = data.getRoot(setting);
+			for (var i=0, j=root.curSelectedList.length; i<j; i++) {
+				if(node === root.curSelectedList[i]) return true;
+			}
+			return false;
+		},
+		removeNodeCache: function(setting, node) {
+			var childKey = setting.data.key.children;
+			if (node[childKey]) {
+				for (var i=0, l=node[childKey].length; i<l; i++) {
+					arguments.callee(setting, node[childKey][i]);
+				}
+			}
+			data.getCache(setting).nodes[data.getNodeCacheId(node.tId)] = null;
+		},
+		removeSelectedNode: function(setting, node) {
+			var root = data.getRoot(setting);
+			for (var i=0, j=root.curSelectedList.length; i<j; i++) {
+				if(node === root.curSelectedList[i] || !data.getNodeCache(setting, root.curSelectedList[i].tId)) {
+					root.curSelectedList.splice(i, 1);
+					i--;j--;
+				}
+			}
+		},
+		setCache: function(setting, cache) {
+			caches[setting.treeId] = cache;
+		},
+		setRoot: function(setting, root) {
+			roots[setting.treeId] = root;
+		},
+		setZTreeTools: function(setting, zTreeTools) {
+			for (var i=0, j=_init.zTreeTools.length; i<j; i++) {
+				_init.zTreeTools[i].apply(this, arguments);
+			}
+		},
+		transformToArrayFormat: function (setting, nodes) {
+			if (!nodes) return [];
+			var childKey = setting.data.key.children,
+			r = [];
+			if (tools.isArray(nodes)) {
+				for (var i=0, l=nodes.length; i<l; i++) {
+					r.push(nodes[i]);
+					if (nodes[i][childKey])
+						r = r.concat(data.transformToArrayFormat(setting, nodes[i][childKey]));
+				}
+			} else {
+				r.push(nodes);
+				if (nodes[childKey])
+					r = r.concat(data.transformToArrayFormat(setting, nodes[childKey]));
+			}
+			return r;
+		},
+		transformTozTreeFormat: function(setting, sNodes) {
+			var i,l,
+			key = setting.data.simpleData.idKey,
+			parentKey = setting.data.simpleData.pIdKey,
+			childKey = setting.data.key.children;
+			if (!key || key=="" || !sNodes) return [];
+
+			if (tools.isArray(sNodes)) {
+				var r = [];
+				var tmpMap = [];
+				for (i=0, l=sNodes.length; i<l; i++) {
+					tmpMap[sNodes[i][key]] = sNodes[i];
+				}
+				for (i=0, l=sNodes.length; i<l; i++) {
+					if (tmpMap[sNodes[i][parentKey]] && sNodes[i][key] != sNodes[i][parentKey]) {
+						if (!tmpMap[sNodes[i][parentKey]][childKey])
+							tmpMap[sNodes[i][parentKey]][childKey] = [];
+						tmpMap[sNodes[i][parentKey]][childKey].push(sNodes[i]);
+					} else {
+						r.push(sNodes[i]);
+					}
+				}
+				return r;
+			}else {
+				return [sNodes];
+			}
+		}
+	},
+	//method of event proxy
+	event = {
+		bindEvent: function(setting) {
+			for (var i=0, j=_init.bind.length; i<j; i++) {
+				_init.bind[i].apply(this, arguments);
+			}
+		},
+		unbindEvent: function(setting) {
+			for (var i=0, j=_init.unbind.length; i<j; i++) {
+				_init.unbind[i].apply(this, arguments);
+			}
+		},
+		bindTree: function(setting) {
+			var eventParam = {
+				treeId: setting.treeId
+			},
+			o = setting.treeObj;
+			// for can't select text
+			o.bind('selectstart', function(e){
+					var n = e.originalEvent.srcElement.nodeName.toLowerCase();
+					return (n === "input" || n === "textarea" );
+			}).css({
+				"-moz-user-select":"-moz-none"
+			});
+			o.bind('click', eventParam, event.proxy);
+			o.bind('dblclick', eventParam, event.proxy);
+			o.bind('mouseover', eventParam, event.proxy);
+			o.bind('mouseout', eventParam, event.proxy);
+			o.bind('mousedown', eventParam, event.proxy);
+			o.bind('mouseup', eventParam, event.proxy);
+			o.bind('contextmenu', eventParam, event.proxy);
+		},
+		unbindTree: function(setting) {
+			var o = setting.treeObj;
+			o.unbind('click', event.proxy)
+			.unbind('dblclick', event.proxy)
+			.unbind('mouseover', event.proxy)
+			.unbind('mouseout', event.proxy)
+			.unbind('mousedown', event.proxy)
+			.unbind('mouseup', event.proxy)
+			.unbind('contextmenu', event.proxy);
+		},
+		doProxy: function(e) {
+			var results = [];
+			for (var i=0, j=_init.proxys.length; i<j; i++) {
+				var proxyResult = _init.proxys[i].apply(this, arguments);
+				results.push(proxyResult);
+				if (proxyResult.stop) {
+					break;
+				}
+			}
+			return results;
+		},
+		proxy: function(e) {
+			var setting = data.getSetting(e.data.treeId);
+			if (!tools.uCanDo(setting, e)) return true;
+			var results = event.doProxy(e),
+			r = true, x = false;
+			for (var i=0, l=results.length; i<l; i++) {
+				var proxyResult = results[i];
+				if (proxyResult.nodeEventCallback) {
+					x = true;
+					r = proxyResult.nodeEventCallback.apply(proxyResult, [e, proxyResult.node]) && r;
+				}
+				if (proxyResult.treeEventCallback) {
+					x = true;
+					r = proxyResult.treeEventCallback.apply(proxyResult, [e, proxyResult.node]) && r;
+				}
+			}
+			return r;
+		}
+	},
+	//method of event handler
+	handler = {
+		onSwitchNode: function (event, node) {
+			var setting = data.getSetting(event.data.treeId);
+			if (node.open) {
+				if (tools.apply(setting.callback.beforeCollapse, [setting.treeId, node], true) == false) return true;
+				data.getRoot(setting).expandTriggerFlag = true;
+				view.switchNode(setting, node);
+			} else {
+				if (tools.apply(setting.callback.beforeExpand, [setting.treeId, node], true) == false) return true;
+				data.getRoot(setting).expandTriggerFlag = true;
+				view.switchNode(setting, node);
+			}
+			return true;
+		},
+		onClickNode: function (event, node) {
+			var setting = data.getSetting(event.data.treeId),
+			clickFlag = ( (setting.view.autoCancelSelected && event.ctrlKey) && data.isSelectedNode(setting, node)) ? 0 : (setting.view.autoCancelSelected && event.ctrlKey && setting.view.selectedMulti) ? 2 : 1;
+			if (tools.apply(setting.callback.beforeClick, [setting.treeId, node, clickFlag], true) == false) return true;
+			if (clickFlag === 0) {
+				view.cancelPreSelectedNode(setting, node);
+			} else {
+				view.selectNode(setting, node, clickFlag === 2);
+			}
+			setting.treeObj.trigger(consts.event.CLICK, [event, setting.treeId, node, clickFlag]);
+			return true;
+		},
+		onZTreeMousedown: function(event, node) {
+			var setting = data.getSetting(event.data.treeId);
+			if (tools.apply(setting.callback.beforeMouseDown, [setting.treeId, node], true)) {
+				tools.apply(setting.callback.onMouseDown, [event, setting.treeId, node]);
+			}
+			return true;
+		},
+		onZTreeMouseup: function(event, node) {
+			var setting = data.getSetting(event.data.treeId);
+			if (tools.apply(setting.callback.beforeMouseUp, [setting.treeId, node], true)) {
+				tools.apply(setting.callback.onMouseUp, [event, setting.treeId, node]);
+			}
+			return true;
+		},
+		onZTreeDblclick: function(event, node) {
+			var setting = data.getSetting(event.data.treeId);
+			if (tools.apply(setting.callback.beforeDblClick, [setting.treeId, node], true)) {
+				tools.apply(setting.callback.onDblClick, [event, setting.treeId, node]);
+			}
+			return true;
+		},
+		onZTreeContextmenu: function(event, node) {
+			var setting = data.getSetting(event.data.treeId);
+			if (tools.apply(setting.callback.beforeRightClick, [setting.treeId, node], true)) {
+				tools.apply(setting.callback.onRightClick, [event, setting.treeId, node]);
+			}
+			return (typeof setting.callback.onRightClick) != "function";
+		}
+	},
+	//method of tools for zTree
+	tools = {
+		apply: function(fun, param, defaultValue) {
+			if ((typeof fun) == "function") {
+				return fun.apply(zt, param?param:[]);
+			}
+			return defaultValue;
+		},
+		canAsync: function(setting, node) {
+			var childKey = setting.data.key.children;
+			return (setting.async.enable && node && node.isParent && !(node.zAsync || (node[childKey] && node[childKey].length > 0)));
+		},
+		clone: function (obj){
+			if (obj === null) return null;
+			var o = obj.constructor === Array ? [] : {};
+			for(var i in obj){
+				o[i] = (obj[i] instanceof Date) ? new Date(obj[i].getTime()) : (typeof obj[i] === "object" ? arguments.callee(obj[i]) : obj[i]);
+			}
+			return o;
+		},
+		eqs: function(str1, str2) {
+			return str1.toLowerCase() === str2.toLowerCase();
+		},
+		isArray: function(arr) {
+			return Object.prototype.toString.apply(arr) === "[object Array]";
+		},
+		getMDom: function (setting, curDom, targetExpr) {
+			if (!curDom) return null;
+			while (curDom && curDom.id !== setting.treeId) {
+				for (var i=0, l=targetExpr.length; curDom.tagName && i<l; i++) {
+					if (tools.eqs(curDom.tagName, targetExpr[i].tagName) && curDom.getAttribute(targetExpr[i].attrName) !== null) {
+						return curDom;
+					}
+				}
+				curDom = curDom.parentNode;
+			}
+			return null;
+		},
+		uCanDo: function(setting, e) {
+			return true;
+		}
+	},
+	//method of operate ztree dom
+	view = {
+		addNodes: function(setting, parentNode, newNodes, isSilent) {
+			if (setting.data.keep.leaf && parentNode && !parentNode.isParent) {
+				return;
+			}
+			if (!tools.isArray(newNodes)) {
+				newNodes = [newNodes];
+			}
+			if (setting.data.simpleData.enable) {
+				newNodes = data.transformTozTreeFormat(setting, newNodes);
+			}
+			if (parentNode) {
+				var target_switchObj = $("#" + parentNode.tId + consts.id.SWITCH),
+				target_icoObj = $("#" + parentNode.tId + consts.id.ICON),
+				target_ulObj = $("#" + parentNode.tId + consts.id.UL);
+
+				if (!parentNode.open) {
+					view.replaceSwitchClass(parentNode, target_switchObj, consts.folder.CLOSE);
+					view.replaceIcoClass(parentNode, target_icoObj, consts.folder.CLOSE);
+					parentNode.open = false;
+					target_ulObj.css({
+						"display": "none"
+					});
+				}
+
+				data.addNodesData(setting, parentNode, newNodes);
+				view.createNodes(setting, parentNode.level + 1, newNodes, parentNode);
+				if (!isSilent) {
+					view.expandCollapseParentNode(setting, parentNode, true);
+				}
+			} else {
+				data.addNodesData(setting, data.getRoot(setting), newNodes);
+				view.createNodes(setting, 0, newNodes, null);
+			}
+		},
+		appendNodes: function(setting, level, nodes, parentNode, initFlag, openFlag) {
+			if (!nodes) return [];
+			var html = [],
+			childKey = setting.data.key.children;
+			for (var i = 0, l = nodes.length; i < l; i++) {
+				var node = nodes[i];
+				if (initFlag) {
+					var tmpPNode = (parentNode) ? parentNode: data.getRoot(setting),
+					tmpPChild = tmpPNode[childKey],
+					isFirstNode = ((tmpPChild.length == nodes.length) && (i == 0)),
+					isLastNode = (i == (nodes.length - 1));
+					data.initNode(setting, level, node, parentNode, isFirstNode, isLastNode, openFlag);
+					data.addNodeCache(setting, node);
+				}
+
+				var childHtml = [];
+				if (node[childKey] && node[childKey].length > 0) {
+					//make child html first, because checkType
+					childHtml = view.appendNodes(setting, level + 1, node[childKey], node, initFlag, openFlag && node.open);
+				}
+				if (openFlag) {
+					
+					view.makeDOMNodeMainBefore(html, setting, node);
+					view.makeDOMNodeLine(html, setting, node);
+					data.getBeforeA(setting, node, html);
+					view.makeDOMNodeNameBefore(html, setting, node);
+					data.getInnerBeforeA(setting, node, html);
+					view.makeDOMNodeIcon(html, setting, node);
+					data.getInnerAfterA(setting, node, html);
+					view.makeDOMNodeNameAfter(html, setting, node);
+					data.getAfterA(setting, node, html);
+					if (node.isParent && node.open) {
+						view.makeUlHtml(setting, node, html, childHtml.join(''));
+					}
+					view.makeDOMNodeMainAfter(html, setting, node);
+					data.addCreatedNode(setting, node);
+				}
+			}
+			return html;
+		},
+		appendParentULDom: function(setting, node) {
+			var html = [],
+			nObj = $("#" + node.tId),
+			ulObj = $("#" + node.tId + consts.id.UL),
+			childKey = setting.data.key.children,
+			childHtml = view.appendNodes(setting, node.level+1, node[childKey], node, false, true);
+			view.makeUlHtml(setting, node, html, childHtml.join(''));
+			if (!nObj.get(0) && !!node.parentTId) {
+				view.appendParentULDom(setting, node.getParentNode());
+				nObj = $("#" + node.tId);
+			}
+			if (ulObj.get(0)) {
+				ulObj.remove();
+			}
+			nObj.append(html.join(''));
+		},
+		asyncNode: function(setting, node, isSilent, callback) {
+			var i, l;
+			if (node && !node.isParent) {
+				tools.apply(callback);
+				return false;
+			} else if (node && node.isAjaxing) {
+				return false;
+			} else if (tools.apply(setting.callback.beforeAsync, [setting.treeId, node], true) == false) {
+				tools.apply(callback);
+				return false;
+			}
+			if (node) {
+				node.isAjaxing = true;
+				var icoObj = $("#" + node.tId + consts.id.ICON);
+				icoObj.attr({"style":"", "class":consts.className.BUTTON + " " + consts.className.ICO_LOADING});
+			}
+
+			var tmpParam = {};
+			for (i = 0, l = setting.async.autoParam.length; node && i < l; i++) {
+				var pKey = setting.async.autoParam[i].split("="), spKey = pKey;
+				if (pKey.length>1) {
+					spKey = pKey[1];
+					pKey = pKey[0];
+				}
+				tmpParam[spKey] = node[pKey];
+			}
+			if (tools.isArray(setting.async.otherParam)) {
+				for (i = 0, l = setting.async.otherParam.length; i < l; i += 2) {
+					tmpParam[setting.async.otherParam[i]] = setting.async.otherParam[i + 1];
+				}
+			} else {
+				for (var p in setting.async.otherParam) {
+					tmpParam[p] = setting.async.otherParam[p];
+				}
+			}
+
+			var _tmpV = data.getRoot(setting)._ver;
+			$.ajax({
+				contentType: setting.async.contentType,
+				type: setting.async.type,
+				url: tools.apply(setting.async.url, [setting.treeId, node], setting.async.url),
+				data: tmpParam,
+				dataType: setting.async.dataType,
+				success: function(msg) {
+					if (_tmpV != data.getRoot(setting)._ver) {
+						return;
+					}
+					var newNodes = [];
+					try {
+						if (!msg || msg.length == 0) {
+							newNodes = [];
+						} else if (typeof msg == "string") {
+							newNodes = eval("(" + msg + ")");
+						} else {
+							newNodes = msg;
+						}
+					} catch(err) {
+						newNodes = msg;
+					}
+
+					if (node) {
+						node.isAjaxing = null;
+						node.zAsync = true;
+					}
+					view.setNodeLineIcos(setting, node);
+					if (newNodes && newNodes !== "") {
+						newNodes = tools.apply(setting.async.dataFilter, [setting.treeId, node, newNodes], newNodes);
+						view.addNodes(setting, node, !!newNodes ? tools.clone(newNodes) : [], !!isSilent);
+					} else {
+						view.addNodes(setting, node, [], !!isSilent);
+					}
+					setting.treeObj.trigger(consts.event.ASYNC_SUCCESS, [setting.treeId, node, msg]);
+					tools.apply(callback);
+				},
+				error: function(XMLHttpRequest, textStatus, errorThrown) {
+					if (_tmpV != data.getRoot(setting)._ver) {
+						return;
+					}
+					if (node) node.isAjaxing = null;
+					view.setNodeLineIcos(setting, node);
+					setting.treeObj.trigger(consts.event.ASYNC_ERROR, [setting.treeId, node, XMLHttpRequest, textStatus, errorThrown]);
+				}
+			});
+			return true;
+		},
+		cancelPreSelectedNode: function (setting, node) {
+			var list = data.getRoot(setting).curSelectedList;
+			for (var i=0, j=list.length-1; j>=i; j--) {
+				if (!node || node === list[j]) {
+					$("#" + list[j].tId + consts.id.A).removeClass(consts.node.CURSELECTED);
+					if (node) {
+						data.removeSelectedNode(setting, node);
+						break;
+					}
+				}
+			}
+			if (!node) data.getRoot(setting).curSelectedList = [];
+		},
+		createNodeCallback: function(setting) {
+			if (!!setting.callback.onNodeCreated || !!setting.view.addDiyDom) {
+				var root = data.getRoot(setting);
+				while (root.createdNodes.length>0) {
+					var node = root.createdNodes.shift();
+					tools.apply(setting.view.addDiyDom, [setting.treeId, node]);
+					if (!!setting.callback.onNodeCreated) {
+						setting.treeObj.trigger(consts.event.NODECREATED, [setting.treeId, node]);
+					}
+				}
+			}
+		},
+		createNodes: function(setting, level, nodes, parentNode) {
+			if (!nodes || nodes.length == 0) return;
+			var root = data.getRoot(setting),
+			childKey = setting.data.key.children,
+			openFlag = !parentNode || parentNode.open || !!$("#" + parentNode[childKey][0].tId).get(0);
+			root.createdNodes = [];
+			var zTreeHtml = view.appendNodes(setting, level, nodes, parentNode, true, openFlag);
+			if (!parentNode) {
+				setting.treeObj.append(zTreeHtml.join(''));
+			} else {
+				var ulObj = $("#" + parentNode.tId + consts.id.UL);
+				if (ulObj.get(0)) {
+					ulObj.append(zTreeHtml.join(''));
+				}
+			}
+			view.createNodeCallback(setting);
+		},
+		destroy: function(setting) {
+			if (!setting) return;
+			data.initCache(setting);
+			data.initRoot(setting);
+			event.unbindTree(setting);
+			event.unbindEvent(setting);
+			setting.treeObj.empty();
+		},
+		expandCollapseNode: function(setting, node, expandFlag, animateFlag, callback) {
+			var root = data.getRoot(setting),
+			childKey = setting.data.key.children;
+			if (!node) {
+				tools.apply(callback, []);
+				return;
+			}
+			if (root.expandTriggerFlag) {
+				var _callback = callback;
+				callback = function(){
+					if (_callback) _callback();
+					if (node.open) {
+						setting.treeObj.trigger(consts.event.EXPAND, [setting.treeId, node]);
+					} else {
+						setting.treeObj.trigger(consts.event.COLLAPSE, [setting.treeId, node]);
+					}
+				};
+				root.expandTriggerFlag = false;
+			}
+			if (!node.open && node.isParent && ((!$("#" + node.tId + consts.id.UL).get(0)) || (node[childKey] && node[childKey].length>0 && !$("#" + node[childKey][0].tId).get(0)))) {
+				view.appendParentULDom(setting, node);
+				view.createNodeCallback(setting);
+			}
+			if (node.open == expandFlag) {
+				tools.apply(callback, []);
+				return;
+			}
+			var ulObj = $("#" + node.tId + consts.id.UL),
+			switchObj = $("#" + node.tId + consts.id.SWITCH),
+			icoObj = $("#" + node.tId + consts.id.ICON);
+
+			if (node.isParent) {
+				node.open = !node.open;
+				if (node.iconOpen && node.iconClose) {
+					icoObj.attr("style", view.makeNodeIcoStyle(setting, node));
+				}
+
+				if (node.open) {
+					view.replaceSwitchClass(node, switchObj, consts.folder.OPEN);
+					view.replaceIcoClass(node, icoObj, consts.folder.OPEN);
+					if (animateFlag == false || setting.view.expandSpeed == "") {
+						ulObj.show();
+						tools.apply(callback, []);
+					} else {
+						if (node[childKey] && node[childKey].length > 0) {
+							ulObj.slideDown(setting.view.expandSpeed, callback);
+						} else {
+							ulObj.show();
+							tools.apply(callback, []);
+						}
+					}
+				} else {
+					view.replaceSwitchClass(node, switchObj, consts.folder.CLOSE);
+					view.replaceIcoClass(node, icoObj, consts.folder.CLOSE);
+					if (animateFlag == false || setting.view.expandSpeed == "" || !(node[childKey] && node[childKey].length > 0)) {
+						ulObj.hide();
+						tools.apply(callback, []);
+					} else {
+						ulObj.slideUp(setting.view.expandSpeed, callback);
+					}
+				}
+			} else {
+				tools.apply(callback, []);
+			}
+		},
+		expandCollapseParentNode: function(setting, node, expandFlag, animateFlag, callback) {
+			if (!node) return;
+			if (!node.parentTId) {
+				view.expandCollapseNode(setting, node, expandFlag, animateFlag, callback);
+				return;
+			} else {
+				view.expandCollapseNode(setting, node, expandFlag, animateFlag);
+			}
+			if (node.parentTId) {
+				view.expandCollapseParentNode(setting, node.getParentNode(), expandFlag, animateFlag, callback);
+			}
+		},
+		expandCollapseSonNode: function(setting, node, expandFlag, animateFlag, callback) {
+			var root = data.getRoot(setting),
+			childKey = setting.data.key.children,
+			treeNodes = (node) ? node[childKey]: root[childKey],
+			selfAnimateSign = (node) ? false : animateFlag,
+			expandTriggerFlag = data.getRoot(setting).expandTriggerFlag;
+			data.getRoot(setting).expandTriggerFlag = false;
+			if (treeNodes) {
+				for (var i = 0, l = treeNodes.length; i < l; i++) {
+					if (treeNodes[i]) view.expandCollapseSonNode(setting, treeNodes[i], expandFlag, selfAnimateSign);
+				}
+			}
+			data.getRoot(setting).expandTriggerFlag = expandTriggerFlag;
+			view.expandCollapseNode(setting, node, expandFlag, animateFlag, callback );
+		},
+		makeDOMNodeIcon: function(html, setting, node) {
+			var nameStr = data.getNodeName(setting, node),
+			name = setting.view.nameIsHTML ? nameStr : nameStr.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
+			html.push("<span id='", node.tId, consts.id.ICON,
+				"' title='' treeNode", consts.id.ICON," class='", view.makeNodeIcoClass(setting, node),
+				"' style='", view.makeNodeIcoStyle(setting, node), "'></span><span id='", node.tId, consts.id.SPAN,
+				"'>",name,"</span>");
+		},
+		makeDOMNodeLine: function(html, setting, node) {
+			html.push("<span id='", node.tId, consts.id.SWITCH,	"' title='' class='", view.makeNodeLineClass(setting, node), "' treeNode", consts.id.SWITCH,"></span>");
+		},
+		makeDOMNodeMainAfter: function(html, setting, node) {
+			html.push("</li>");
+		},
+		makeDOMNodeMainBefore: function(html, setting, node) {
+			html.push("<li id='", node.tId, "' class='", consts.className.LEVEL, node.level,"' tabindex='0' hidefocus='true' treenode>");
+		},
+		makeDOMNodeNameAfter: function(html, setting, node) {
+			html.push("</a>");
+		},
+		makeDOMNodeNameBefore: function(html, setting, node) {
+			var title = data.getNodeTitle(setting, node),
+			url = view.makeNodeUrl(setting, node),
+			fontcss = view.makeNodeFontCss(setting, node),
+			fontStyle = [];
+			for (var f in fontcss) {
+				fontStyle.push(f, ":", fontcss[f], ";");
+			}
+			html.push("<a id='", node.tId, consts.id.A, "' class='", consts.className.LEVEL, node.level,"' treeNode", consts.id.A," onclick=\"", (node.click || ''),
+				"\" ", ((url != null && url.length > 0) ? "href='" + url + "'" : ""), " target='",view.makeNodeTarget(node),"' style='", fontStyle.join(''),
+				"'");
+			if (tools.apply(setting.view.showTitle, [setting.treeId, node], setting.view.showTitle) && title) {html.push("title='", title.replace(/'/g,"&#39;").replace(/</g,'&lt;').replace(/>/g,'&gt;'),"'");}
+			html.push(">");
+		},
+		makeNodeFontCss: function(setting, node) {
+			var fontCss = tools.apply(setting.view.fontCss, [setting.treeId, node], setting.view.fontCss);
+			return (fontCss && ((typeof fontCss) != "function")) ? fontCss : {};
+		},
+		makeNodeIcoClass: function(setting, node) {
+			var icoCss = ["ico"];
+			if (!node.isAjaxing) {
+				icoCss[0] = (node.iconSkin ? node.iconSkin + "_" : "") + icoCss[0];
+				if (node.isParent) {
+					icoCss.push(node.open ? consts.folder.OPEN : consts.folder.CLOSE);
+				} else {
+					icoCss.push(consts.folder.DOCU);
+				}
+			}
+			return consts.className.BUTTON + " " + icoCss.join('_');
+		},
+		makeNodeIcoStyle: function(setting, node) {
+			var icoStyle = [];
+			if (!node.isAjaxing) {
+				var icon = (node.isParent && node.iconOpen && node.iconClose) ? (node.open ? node.iconOpen : node.iconClose) : node.icon;
+				if (icon) icoStyle.push("background:url(", icon, ") 0 0 no-repeat;");
+				if (setting.view.showIcon == false || !tools.apply(setting.view.showIcon, [setting.treeId, node], true)) {
+					icoStyle.push("width:0px;height:0px;");
+				}
+			}
+			return icoStyle.join('');
+		},
+		makeNodeLineClass: function(setting, node) {
+			var lineClass = [];
+			if (setting.view.showLine) {
+				if (node.level == 0 && node.isFirstNode && node.isLastNode) {
+					lineClass.push(consts.line.ROOT);
+				} else if (node.level == 0 && node.isFirstNode) {
+					lineClass.push(consts.line.ROOTS);
+				} else if (node.isLastNode) {
+					lineClass.push(consts.line.BOTTOM);
+				} else {
+					lineClass.push(consts.line.CENTER);
+				}
+			} else {
+				lineClass.push(consts.line.NOLINE);
+			}
+			if (node.isParent) {
+				lineClass.push(node.open ? consts.folder.OPEN : consts.folder.CLOSE);
+			} else {
+				lineClass.push(consts.folder.DOCU);
+			}
+			return view.makeNodeLineClassEx(node) + lineClass.join('_');
+		},
+		makeNodeLineClassEx: function(node) {
+			return consts.className.BUTTON + " " + consts.className.LEVEL + node.level + " " + consts.className.SWITCH + " ";
+		},
+		makeNodeTarget: function(node) {
+			return (node.target || "_blank");
+		},
+		makeNodeUrl: function(setting, node) {
+			var urlKey = setting.data.key.url;
+			return node[urlKey] ? node[urlKey] : null;
+		},
+		makeUlHtml: function(setting, node, html, content) {
+			html.push("<ul id='", node.tId, consts.id.UL, "' class='", consts.className.LEVEL, node.level, " ", view.makeUlLineClass(setting, node), "' style='display:", (node.open ? "block": "none"),"'>");
+			html.push(content);
+			html.push("</ul>");
+		},
+		makeUlLineClass: function(setting, node) {
+			return ((setting.view.showLine && !node.isLastNode) ? consts.line.LINE : "");
+		},
+		removeChildNodes: function(setting, node) {
+			if (!node) return;
+			var childKey = setting.data.key.children,
+			nodes = node[childKey];
+			if (!nodes) return;
+
+			for (var i = 0, l = nodes.length; i < l; i++) {
+				data.removeNodeCache(setting, nodes[i]);
+			}
+			data.removeSelectedNode(setting);
+			delete node[childKey];
+
+			if (!setting.data.keep.parent) {
+				node.isParent = false;
+				node.open = false;
+				var tmp_switchObj = $("#" + node.tId + consts.id.SWITCH),
+				tmp_icoObj = $("#" + node.tId + consts.id.ICON);
+				view.replaceSwitchClass(node, tmp_switchObj, consts.folder.DOCU);
+				view.replaceIcoClass(node, tmp_icoObj, consts.folder.DOCU);
+				$("#" + node.tId + consts.id.UL).remove();
+			} else {
+				$("#" + node.tId + consts.id.UL).empty();
+			}
+		},
+		setFirstNode: function(setting, parentNode) {
+			var childKey = setting.data.key.children, childLength = parentNode[childKey].length;
+			if ( childLength > 0) {
+				parentNode[childKey][0].isFirstNode = true;
+			}
+		},
+		setLastNode: function(setting, parentNode) {
+			var childKey = setting.data.key.children, childLength = parentNode[childKey].length;
+			if ( childLength > 0) {
+				parentNode[childKey][childLength - 1].isLastNode = true;
+			}
+		},
+		removeNode: function(setting, node) {
+			var root = data.getRoot(setting),
+			childKey = setting.data.key.children,
+			parentNode = (node.parentTId) ? node.getParentNode() : root;
+
+			node.isFirstNode = false;
+			node.isLastNode = false;
+			node.getPreNode = function() {return null;};
+			node.getNextNode = function() {return null;};
+
+			if (!data.getNodeCache(setting, node.tId)) {
+				return;
+			}
+                        
+			$("#" + node.tId).remove();
+			data.removeNodeCache(setting, node);
+			data.removeSelectedNode(setting, node);
+
+			for (var i = 0, l = parentNode[childKey].length; i < l; i++) {
+				if (parentNode[childKey][i].tId == node.tId) {
+					parentNode[childKey].splice(i, 1);
+					break;
+				}
+			}
+			view.setFirstNode(setting, parentNode);
+			view.setLastNode(setting, parentNode);
+                                                
+			var tmp_ulObj,tmp_switchObj,tmp_icoObj,
+			childLength = parentNode[childKey].length;
+
+			//repair nodes old parent
+			if (!setting.data.keep.parent && childLength == 0) {
+				//old parentNode has no child nodes
+				parentNode.isParent = false;
+				parentNode.open = false;
+				tmp_ulObj = $("#" + parentNode.tId + consts.id.UL);
+				tmp_switchObj = $("#" + parentNode.tId + consts.id.SWITCH);
+				tmp_icoObj = $("#" + parentNode.tId + consts.id.ICON);
+				view.replaceSwitchClass(parentNode, tmp_switchObj, consts.folder.DOCU);
+				view.replaceIcoClass(parentNode, tmp_icoObj, consts.folder.DOCU);
+				tmp_ulObj.css("display", "none");
+
+			} else if (setting.view.showLine && childLength > 0) {
+				//old parentNode has child nodes
+				var newLast = parentNode[childKey][childLength - 1];
+				tmp_ulObj = $("#" + newLast.tId + consts.id.UL);
+				tmp_switchObj = $("#" + newLast.tId + consts.id.SWITCH);
+				tmp_icoObj = $("#" + newLast.tId + consts.id.ICON);
+				if (parentNode == root) {
+					if (parentNode[childKey].length == 1) {
+						//node was root, and ztree has only one root after move node
+						view.replaceSwitchClass(newLast, tmp_switchObj, consts.line.ROOT);
+					} else {
+						var tmp_first_switchObj = $("#" + parentNode[childKey][0].tId + consts.id.SWITCH);
+						view.replaceSwitchClass(parentNode[childKey][0], tmp_first_switchObj, consts.line.ROOTS);
+						view.replaceSwitchClass(newLast, tmp_switchObj, consts.line.BOTTOM);
+					}
+				} else {
+					view.replaceSwitchClass(newLast, tmp_switchObj, consts.line.BOTTOM);
+				}
+				tmp_ulObj.removeClass(consts.line.LINE);
+			}
+		},
+		replaceIcoClass: function(node, obj, newName) {
+			if (!obj || node.isAjaxing) return;
+			var tmpName = obj.attr("class");
+			if (tmpName == undefined) return;
+			var tmpList = tmpName.split("_");
+			switch (newName) {
+				case consts.folder.OPEN:
+				case consts.folder.CLOSE:
+				case consts.folder.DOCU:
+					tmpList[tmpList.length-1] = newName;
+					break;
+			}
+			obj.attr("class", tmpList.join("_"));
+		},
+		replaceSwitchClass: function(node, obj, newName) {
+			if (!obj) return;
+			var tmpName = obj.attr("class");
+			if (tmpName == undefined) return;
+			var tmpList = tmpName.split("_");
+			switch (newName) {
+				case consts.line.ROOT:
+				case consts.line.ROOTS:
+				case consts.line.CENTER:
+				case consts.line.BOTTOM:
+				case consts.line.NOLINE:
+					tmpList[0] = view.makeNodeLineClassEx(node) + newName;
+					break;
+				case consts.folder.OPEN:
+				case consts.folder.CLOSE:
+				case consts.folder.DOCU:
+					tmpList[1] = newName;
+					break;
+			}
+			obj.attr("class", tmpList.join("_"));
+			if (newName !== consts.folder.DOCU) {
+				obj.removeAttr("disabled");
+			} else {
+				obj.attr("disabled", "disabled");
+			}
+		},
+		selectNode: function(setting, node, addFlag) {
+			if (!addFlag) {
+				view.cancelPreSelectedNode(setting);
+			}
+			$("#" + node.tId + consts.id.A).addClass(consts.node.CURSELECTED);
+			data.addSelectedNode(setting, node);
+		},
+		setNodeFontCss: function(setting, treeNode) {
+			var aObj = $("#" + treeNode.tId + consts.id.A),
+			fontCss = view.makeNodeFontCss(setting, treeNode);
+			if (fontCss) {
+				aObj.css(fontCss);
+			}
+		},
+		setNodeLineIcos: function(setting, node) {
+			if (!node) return;
+			var switchObj = $("#" + node.tId + consts.id.SWITCH),
+			ulObj = $("#" + node.tId + consts.id.UL),
+			icoObj = $("#" + node.tId + consts.id.ICON),
+			ulLine = view.makeUlLineClass(setting, node);
+			if (ulLine.length==0) {
+				ulObj.removeClass(consts.line.LINE);
+			} else {
+				ulObj.addClass(ulLine);
+			}
+			switchObj.attr("class", view.makeNodeLineClass(setting, node));
+			if (node.isParent) {
+				switchObj.removeAttr("disabled");
+			} else {
+				switchObj.attr("disabled", "disabled");
+			}
+			icoObj.removeAttr("style");
+			icoObj.attr("style", view.makeNodeIcoStyle(setting, node));
+			icoObj.attr("class", view.makeNodeIcoClass(setting, node));
+		},
+		setNodeName: function(setting, node) {
+			var title = data.getNodeTitle(setting, node),
+			nObj = $("#" + node.tId + consts.id.SPAN);
+			nObj.empty();
+			if (setting.view.nameIsHTML) {
+				nObj.html(data.getNodeName(setting, node));
+			} else {
+				nObj.text(data.getNodeName(setting, node));
+			}
+			if (tools.apply(setting.view.showTitle, [setting.treeId, node], setting.view.showTitle)) {
+				var aObj = $("#" + node.tId + consts.id.A);
+				aObj.attr("title", !title ? "" : title);
+			}
+		},
+		setNodeTarget: function(node) {
+			var aObj = $("#" + node.tId + consts.id.A);
+			aObj.attr("target", view.makeNodeTarget(node));
+		},
+		setNodeUrl: function(setting, node) {
+			var aObj = $("#" + node.tId + consts.id.A),
+			url = view.makeNodeUrl(setting, node);
+			if (url == null || url.length == 0) {
+				aObj.removeAttr("href");
+			} else {
+				aObj.attr("href", url);
+			}
+		},
+		switchNode: function(setting, node) {
+			if (node.open || !tools.canAsync(setting, node)) {
+				view.expandCollapseNode(setting, node, !node.open);
+			} else if (setting.async.enable) {
+				if (!view.asyncNode(setting, node)) {
+					view.expandCollapseNode(setting, node, !node.open);
+					return;
+				}
+			} else if (node) {
+				view.expandCollapseNode(setting, node, !node.open);
+			}
+		}
+	};
+	// zTree defind
+	$.fn.zTree = {
+		consts : _consts,
+		_z : {
+			tools: tools,
+			view: view,
+			event: event,
+			data: data
+		},
+		getZTreeObj: function(treeId) {
+			var o = data.getZTreeTools(treeId);
+			return o ? o : null;
+		},
+		destroy: function(treeId) {
+			if (!!treeId && treeId.length > 0) {
+				view.destroy(data.getSetting(treeId));
+			} else {
+				for(var s in settings) {
+					view.destroy(settings[s]);
+				}
+			}
+		},
+		init: function(obj, zSetting, zNodes) {
+			var setting = tools.clone(_setting);
+			$.extend(true, setting, zSetting);
+			setting.treeId = obj.attr("id");
+			setting.treeObj = obj;
+			setting.treeObj.empty();
+			settings[setting.treeId] = setting;
+			//For some older browser,(e.g., ie6)
+			if(typeof document.body.style.maxHeight === "undefined") {
+				setting.view.expandSpeed = "";
+			}
+			data.initRoot(setting);
+			var root = data.getRoot(setting),
+			childKey = setting.data.key.children;
+			zNodes = zNodes ? tools.clone(tools.isArray(zNodes)? zNodes : [zNodes]) : [];
+			if (setting.data.simpleData.enable) {
+				root[childKey] = data.transformTozTreeFormat(setting, zNodes);
+			} else {
+				root[childKey] = zNodes;
+			}
+
+			data.initCache(setting);
+			event.unbindTree(setting);
+			event.bindTree(setting);
+			event.unbindEvent(setting);
+			event.bindEvent(setting);
+			
+			var zTreeTools = {
+				setting : setting,
+				addNodes : function(parentNode, newNodes, isSilent) {
+					if (!newNodes) return null;
+					if (!parentNode) parentNode = null;
+					if (parentNode && !parentNode.isParent && setting.data.keep.leaf) return null;
+					var xNewNodes = tools.clone(tools.isArray(newNodes)? newNodes: [newNodes]);
+					function addCallback() {
+						view.addNodes(setting, parentNode, xNewNodes, (isSilent==true));
+					}
+
+					if (tools.canAsync(setting, parentNode)) {
+						view.asyncNode(setting, parentNode, isSilent, addCallback);
+					} else {
+						addCallback();
+					}
+					return xNewNodes;
+				},
+				cancelSelectedNode : function(node) {
+					view.cancelPreSelectedNode(this.setting, node);
+				},
+				destroy : function() {
+					view.destroy(this.setting);
+				},
+				expandAll : function(expandFlag) {
+					expandFlag = !!expandFlag;
+					view.expandCollapseSonNode(this.setting, null, expandFlag, true);
+					return expandFlag;
+				},
+				expandNode : function(node, expandFlag, sonSign, focus, callbackFlag) {
+					if (!node || !node.isParent) return null;
+					if (expandFlag !== true && expandFlag !== false) {
+						expandFlag = !node.open;
+					}
+					callbackFlag = !!callbackFlag;
+
+					if (callbackFlag && expandFlag && (tools.apply(setting.callback.beforeExpand, [setting.treeId, node], true) == false)) {
+						return null;
+					} else if (callbackFlag && !expandFlag && (tools.apply(setting.callback.beforeCollapse, [setting.treeId, node], true) == false)) {
+						return null;
+					}
+					if (expandFlag && node.parentTId) {
+						view.expandCollapseParentNode(this.setting, node.getParentNode(), expandFlag, false);
+					}
+					if (expandFlag === node.open && !sonSign) {
+						return null;
+					}
+					
+					data.getRoot(setting).expandTriggerFlag = callbackFlag;
+					if (sonSign) {
+						view.expandCollapseSonNode(this.setting, node, expandFlag, true, function() {
+							if (focus !== false) {try{$("#" + node.tId).focus().blur();}catch(e){}}
+						});
+					} else {
+						node.open = !expandFlag;
+						view.switchNode(this.setting, node);
+						if (focus !== false) {try{$("#" + node.tId).focus().blur();}catch(e){}}
+					}
+					return expandFlag;
+				},
+				getNodes : function() {
+					return data.getNodes(this.setting);
+				},
+				getNodeByParam : function(key, value, parentNode) {
+					if (!key) return null;
+					return data.getNodeByParam(this.setting, parentNode?parentNode[this.setting.data.key.children]:data.getNodes(this.setting), key, value);
+				},
+				getNodeByTId : function(tId) {
+					return data.getNodeCache(this.setting, tId);
+				},
+				getNodesByParam : function(key, value, parentNode) {
+					if (!key) return null;
+					return data.getNodesByParam(this.setting, parentNode?parentNode[this.setting.data.key.children]:data.getNodes(this.setting), key, value);
+				},
+				getNodesByParamFuzzy : function(key, value, parentNode) {
+					if (!key) return null;
+					return data.getNodesByParamFuzzy(this.setting, parentNode?parentNode[this.setting.data.key.children]:data.getNodes(this.setting), key, value);
+				},
+				getNodesByFilter: function(filter, isSingle, parentNode, invokeParam) {
+					isSingle = !!isSingle;
+					if (!filter || (typeof filter != "function")) return (isSingle ? null : []);
+					return data.getNodesByFilter(this.setting, parentNode?parentNode[this.setting.data.key.children]:data.getNodes(this.setting), filter, isSingle, invokeParam);
+				},
+				getNodeIndex : function(node) {
+					if (!node) return null;
+					var childKey = setting.data.key.children,
+					parentNode = (node.parentTId) ? node.getParentNode() : data.getRoot(this.setting);
+					for (var i=0, l = parentNode[childKey].length; i < l; i++) {
+						if (parentNode[childKey][i] == node) return i;
+					}
+					return -1;
+				},
+				getSelectedNodes : function() {
+					var r = [], list = data.getRoot(this.setting).curSelectedList;
+					for (var i=0, l=list.length; i<l; i++) {
+						r.push(list[i]);
+					}
+					return r;
+				},
+				isSelectedNode : function(node) {
+					return data.isSelectedNode(this.setting, node);
+				},
+				reAsyncChildNodes : function(parentNode, reloadType, isSilent) {
+					if (!this.setting.async.enable) return;
+					var isRoot = !parentNode;
+					if (isRoot) {
+						parentNode = data.getRoot(this.setting);
+					}
+					if (reloadType=="refresh") {
+						var childKey = this.setting.data.key.children;
+						for (var i = 0, l = parentNode[childKey] ? parentNode[childKey].length : 0; i < l; i++) {
+							data.removeNodeCache(setting, parentNode[childKey][i]);
+						}
+						data.removeSelectedNode(setting);
+						parentNode[childKey] = [];
+						if (isRoot) {
+							this.setting.treeObj.empty();
+						} else {
+							var ulObj = $("#" + parentNode.tId + consts.id.UL);
+							ulObj.empty();
+						}
+					}
+					view.asyncNode(this.setting, isRoot? null:parentNode, !!isSilent);
+				},
+				refresh : function() {
+					this.setting.treeObj.empty();
+					var root = data.getRoot(this.setting),
+					nodes = root[this.setting.data.key.children]
+					data.initRoot(this.setting);
+					root[this.setting.data.key.children] = nodes
+					data.initCache(this.setting);
+					view.createNodes(this.setting, 0, root[this.setting.data.key.children]);
+				},
+				removeChildNodes : function(node) {
+					if (!node) return null;
+					var childKey = setting.data.key.children,
+					nodes = node[childKey];
+					view.removeChildNodes(setting, node);
+					return nodes ? nodes : null;
+				},
+				removeNode : function(node, callbackFlag) {
+					if (!node) return;
+					callbackFlag = !!callbackFlag;
+					if (callbackFlag && tools.apply(setting.callback.beforeRemove, [setting.treeId, node], true) == false) return;
+					view.removeNode(setting, node);
+					if (callbackFlag) {
+						this.setting.treeObj.trigger(consts.event.REMOVE, [setting.treeId, node]);
+					}
+				},
+				selectNode : function(node, addFlag) {
+					if (!node) return;
+					if (tools.uCanDo(this.setting)) {
+						addFlag = setting.view.selectedMulti && addFlag;
+						if (node.parentTId) {
+							view.expandCollapseParentNode(this.setting, node.getParentNode(), true, false, function() {
+								try{$("#" + node.tId).focus().blur();}catch(e){}
+							});
+						} else {
+							try{$("#" + node.tId).focus().blur();}catch(e){}
+						}
+						view.selectNode(this.setting, node, addFlag);
+					}
+				},
+				transformTozTreeNodes : function(simpleNodes) {
+					return data.transformTozTreeFormat(this.setting, simpleNodes);
+				},
+				transformToArray : function(nodes) {
+					return data.transformToArrayFormat(this.setting, nodes);
+				},
+				updateNode : function(node, checkTypeFlag) {
+					if (!node) return;
+					var nObj = $("#" + node.tId);
+					if (nObj.get(0) && tools.uCanDo(this.setting)) {
+						view.setNodeName(this.setting, node);
+						view.setNodeTarget(node);
+						view.setNodeUrl(this.setting, node);
+						view.setNodeLineIcos(this.setting, node);
+						view.setNodeFontCss(this.setting, node);
+					}
+				}
+			}
+			root.treeTools = zTreeTools;
+			data.setZTreeTools(setting, zTreeTools);
+
+			if (root[childKey] && root[childKey].length > 0) {
+				view.createNodes(setting, 0, root[childKey]);
+			} else if (setting.async.enable && setting.async.url && setting.async.url !== '') {
+				view.asyncNode(setting);
+			}
+			return zTreeTools;
+		}
+	};
+
+	var zt = $.fn.zTree,
+	consts = zt.consts;
+})(jQuery);
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/js/jquery.ztree.excheck-3.5.js b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/js/jquery.ztree.excheck-3.5.js
new file mode 100644
index 0000000..2605bad
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/js/jquery.ztree.excheck-3.5.js
@@ -0,0 +1,624 @@
+/*
+ * JQuery zTree excheck 3.5.12
+ * http://zTree.me/
+ *
+ * Copyright (c) 2010 Hunter.z
+ *
+ * Licensed same as jquery - MIT License
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ * email: hunter.z@263.net
+ * Date: 2013-03-11
+ */
+(function($){
+	//default consts of excheck
+	var _consts = {
+		event: {
+			CHECK: "ztree_check"
+		},
+		id: {
+			CHECK: "_check"
+		},
+		checkbox: {
+			STYLE: "checkbox",
+			DEFAULT: "chk",
+			DISABLED: "disable",
+			FALSE: "false",
+			TRUE: "true",
+			FULL: "full",
+			PART: "part",
+			FOCUS: "focus"
+		},
+		radio: {
+			STYLE: "radio",
+			TYPE_ALL: "all",
+			TYPE_LEVEL: "level"
+		}
+	},
+	//default setting of excheck
+	_setting = {
+		check: {
+			enable: false,
+			autoCheckTrigger: false,
+			chkStyle: _consts.checkbox.STYLE,
+			nocheckInherit: false,
+			chkDisabledInherit: false,
+			radioType: _consts.radio.TYPE_LEVEL,
+			chkboxType: {
+				"Y": "ps",
+				"N": "ps"
+			}
+		},
+		data: {
+			key: {
+				checked: "checked"
+			}
+		},
+		callback: {
+			beforeCheck:null,
+			onCheck:null
+		}
+	},
+	//default root of excheck
+	_initRoot = function (setting) {
+		var r = data.getRoot(setting);
+		r.radioCheckedList = [];
+	},
+	//default cache of excheck
+	_initCache = function(treeId) {},
+	//default bind event of excheck
+	_bindEvent = function(setting) {
+		var o = setting.treeObj,
+		c = consts.event;
+		o.bind(c.CHECK, function (event, srcEvent, treeId, node) {
+			tools.apply(setting.callback.onCheck, [!!srcEvent?srcEvent : event, treeId, node]);
+		});
+	},
+	_unbindEvent = function(setting) {
+		var o = setting.treeObj,
+		c = consts.event;
+		o.unbind(c.CHECK);
+	},
+	//default event proxy of excheck
+	_eventProxy = function(e) {
+		var target = e.target,
+		setting = data.getSetting(e.data.treeId),
+		tId = "", node = null,
+		nodeEventType = "", treeEventType = "",
+		nodeEventCallback = null, treeEventCallback = null;
+
+		if (tools.eqs(e.type, "mouseover")) {
+			if (setting.check.enable && tools.eqs(target.tagName, "span") && target.getAttribute("treeNode"+ consts.id.CHECK) !== null) {
+				tId = target.parentNode.id;
+				nodeEventType = "mouseoverCheck";
+			}
+		} else if (tools.eqs(e.type, "mouseout")) {
+			if (setting.check.enable && tools.eqs(target.tagName, "span") && target.getAttribute("treeNode"+ consts.id.CHECK) !== null) {
+				tId = target.parentNode.id;
+				nodeEventType = "mouseoutCheck";
+			}
+		} else if (tools.eqs(e.type, "click")) {
+			if (setting.check.enable && tools.eqs(target.tagName, "span") && target.getAttribute("treeNode"+ consts.id.CHECK) !== null) {
+				tId = target.parentNode.id;
+				nodeEventType = "checkNode";
+			}
+		}
+		if (tId.length>0) {
+			node = data.getNodeCache(setting, tId);
+			switch (nodeEventType) {
+				case "checkNode" :
+					nodeEventCallback = _handler.onCheckNode;
+					break;
+				case "mouseoverCheck" :
+					nodeEventCallback = _handler.onMouseoverCheck;
+					break;
+				case "mouseoutCheck" :
+					nodeEventCallback = _handler.onMouseoutCheck;
+					break;
+			}
+		}
+		var proxyResult = {
+			stop: false,
+			node: node,
+			nodeEventType: nodeEventType,
+			nodeEventCallback: nodeEventCallback,
+			treeEventType: treeEventType,
+			treeEventCallback: treeEventCallback
+		};
+		return proxyResult
+	},
+	//default init node of excheck
+	_initNode = function(setting, level, n, parentNode, isFirstNode, isLastNode, openFlag) {
+		if (!n) return;
+		var checkedKey = setting.data.key.checked;
+		if (typeof n[checkedKey] == "string") n[checkedKey] = tools.eqs(n[checkedKey], "true");
+		n[checkedKey] = !!n[checkedKey];
+		n.checkedOld = n[checkedKey];
+		if (typeof n.nocheck == "string") n.nocheck = tools.eqs(n.nocheck, "true");
+		n.nocheck = !!n.nocheck || (setting.check.nocheckInherit && parentNode && !!parentNode.nocheck);
+		if (typeof n.chkDisabled == "string") n.chkDisabled = tools.eqs(n.chkDisabled, "true");
+		n.chkDisabled = !!n.chkDisabled || (setting.check.chkDisabledInherit && parentNode && !!parentNode.chkDisabled);
+		if (typeof n.halfCheck == "string") n.halfCheck = tools.eqs(n.halfCheck, "true");
+		n.halfCheck = !!n.halfCheck;
+		n.check_Child_State = -1;
+		n.check_Focus = false;
+		n.getCheckStatus = function() {return data.getCheckStatus(setting, n);};
+	},
+	//add dom for check
+	_beforeA = function(setting, node, html) {
+		var checkedKey = setting.data.key.checked;
+		if (setting.check.enable) {
+			data.makeChkFlag(setting, node);
+			if (setting.check.chkStyle == consts.radio.STYLE && setting.check.radioType == consts.radio.TYPE_ALL && node[checkedKey] ) {
+				var r = data.getRoot(setting);
+				r.radioCheckedList.push(node);
+			}
+			html.push("<span ID='", node.tId, consts.id.CHECK, "' class='", view.makeChkClass(setting, node), "' treeNode", consts.id.CHECK, (node.nocheck === true?" style='display:none;'":""),"></span>");
+		}
+	},
+	//update zTreeObj, add method of check
+	_zTreeTools = function(setting, zTreeTools) {
+		zTreeTools.checkNode = function(node, checked, checkTypeFlag, callbackFlag) {
+			var checkedKey = this.setting.data.key.checked;
+			if (node.chkDisabled === true) return;
+			if (checked !== true && checked !== false) {
+				checked = !node[checkedKey];
+			}
+			callbackFlag = !!callbackFlag;
+			
+			if (node[checkedKey] === checked && !checkTypeFlag) {
+				return;
+			} else if (callbackFlag && tools.apply(this.setting.callback.beforeCheck, [this.setting.treeId, node], true) == false) {
+				return;
+			}
+			if (tools.uCanDo(this.setting) && this.setting.check.enable && node.nocheck !== true) {
+				node[checkedKey] = checked;
+				var checkObj = $("#" + node.tId + consts.id.CHECK);
+				if (checkTypeFlag || this.setting.check.chkStyle === consts.radio.STYLE) view.checkNodeRelation(this.setting, node);
+				view.setChkClass(this.setting, checkObj, node);
+				view.repairParentChkClassWithSelf(this.setting, node);
+				if (callbackFlag) {
+					setting.treeObj.trigger(consts.event.CHECK, [null, setting.treeId, node]);
+				}
+			}
+		}
+
+		zTreeTools.checkAllNodes = function(checked) {
+			view.repairAllChk(this.setting, !!checked);
+		}
+
+		zTreeTools.getCheckedNodes = function(checked) {
+			var childKey = this.setting.data.key.children;
+			checked = (checked !== false);
+			return data.getTreeCheckedNodes(this.setting, data.getRoot(setting)[childKey], checked);
+		}
+
+		zTreeTools.getChangeCheckedNodes = function() {
+			var childKey = this.setting.data.key.children;
+			return data.getTreeChangeCheckedNodes(this.setting, data.getRoot(setting)[childKey]);
+		}
+
+		zTreeTools.setChkDisabled = function(node, disabled, inheritParent, inheritChildren) {
+			disabled = !!disabled;
+			inheritParent = !!inheritParent;
+			inheritChildren = !!inheritChildren;
+			view.repairSonChkDisabled(this.setting, node, disabled, inheritChildren);
+			view.repairParentChkDisabled(this.setting, node.getParentNode(), disabled, inheritParent);
+		}
+
+		var _updateNode = zTreeTools.updateNode;
+		zTreeTools.updateNode = function(node, checkTypeFlag) {
+			if (_updateNode) _updateNode.apply(zTreeTools, arguments);
+			if (!node || !this.setting.check.enable) return;
+			var nObj = $("#" + node.tId);
+			if (nObj.get(0) && tools.uCanDo(this.setting)) {
+				var checkObj = $("#" + node.tId + consts.id.CHECK);
+				if (checkTypeFlag == true || this.setting.check.chkStyle === consts.radio.STYLE) view.checkNodeRelation(this.setting, node);
+				view.setChkClass(this.setting, checkObj, node);
+				view.repairParentChkClassWithSelf(this.setting, node);
+			}
+		}
+	},
+	//method of operate data
+	_data = {
+		getRadioCheckedList: function(setting) {
+			var checkedList = data.getRoot(setting).radioCheckedList;
+			for (var i=0, j=checkedList.length; i<j; i++) {
+				if(!data.getNodeCache(setting, checkedList[i].tId)) {
+					checkedList.splice(i, 1);
+					i--; j--;
+				}
+			}
+			return checkedList;
+		},
+		getCheckStatus: function(setting, node) {
+			if (!setting.check.enable || node.nocheck || node.chkDisabled) return null;
+			var checkedKey = setting.data.key.checked,
+			r = {
+				checked: node[checkedKey],
+				half: node.halfCheck ? node.halfCheck : (setting.check.chkStyle == consts.radio.STYLE ? (node.check_Child_State === 2) : (node[checkedKey] ? (node.check_Child_State > -1 && node.check_Child_State < 2) : (node.check_Child_State > 0)))
+			};
+			return r;
+		},
+		getTreeCheckedNodes: function(setting, nodes, checked, results) {
+			if (!nodes) return [];
+			var childKey = setting.data.key.children,
+			checkedKey = setting.data.key.checked,
+			onlyOne = (checked && setting.check.chkStyle == consts.radio.STYLE && setting.check.radioType == consts.radio.TYPE_ALL);
+			results = !results ? [] : results;
+			for (var i = 0, l = nodes.length; i < l; i++) {
+				if (nodes[i].nocheck !== true && nodes[i].chkDisabled !== true && nodes[i][checkedKey] == checked) {
+					results.push(nodes[i]);
+					if(onlyOne) {
+						break;
+					}
+				}
+				data.getTreeCheckedNodes(setting, nodes[i][childKey], checked, results);
+				if(onlyOne && results.length > 0) {
+					break;
+				}
+			}
+			return results;
+		},
+		getTreeChangeCheckedNodes: function(setting, nodes, results) {
+			if (!nodes) return [];
+			var childKey = setting.data.key.children,
+			checkedKey = setting.data.key.checked;
+			results = !results ? [] : results;
+			for (var i = 0, l = nodes.length; i < l; i++) {
+				if (nodes[i].nocheck !== true && nodes[i].chkDisabled !== true && nodes[i][checkedKey] != nodes[i].checkedOld) {
+					results.push(nodes[i]);
+				}
+				data.getTreeChangeCheckedNodes(setting, nodes[i][childKey], results);
+			}
+			return results;
+		},
+		makeChkFlag: function(setting, node) {
+			if (!node) return;
+			var childKey = setting.data.key.children,
+			checkedKey = setting.data.key.checked,
+			chkFlag = -1;
+			if (node[childKey]) {
+				for (var i = 0, l = node[childKey].length; i < l; i++) {
+					var cNode = node[childKey][i];
+					var tmp = -1;
+					if (setting.check.chkStyle == consts.radio.STYLE) {
+						if (cNode.nocheck === true || cNode.chkDisabled === true) {
+							tmp = cNode.check_Child_State;
+						} else if (cNode.halfCheck === true) {
+							tmp = 2;
+						} else if (cNode[checkedKey]) {
+							tmp = 2;
+						} else {
+							tmp = cNode.check_Child_State > 0 ? 2:0;
+						}
+						if (tmp == 2) {
+							chkFlag = 2; break;
+						} else if (tmp == 0){
+							chkFlag = 0;
+						}
+					} else if (setting.check.chkStyle == consts.checkbox.STYLE) {
+						if (cNode.nocheck === true || cNode.chkDisabled === true) {
+							tmp = cNode.check_Child_State;
+						} else if (cNode.halfCheck === true) {
+							tmp = 1;
+						} else if (cNode[checkedKey] ) {
+							tmp = (cNode.check_Child_State === -1 || cNode.check_Child_State === 2) ? 2 : 1;
+						} else {
+							tmp = (cNode.check_Child_State > 0) ? 1 : 0;
+						}
+						if (tmp === 1) {
+							chkFlag = 1; break;
+						} else if (tmp === 2 && chkFlag > -1 && i > 0 && tmp !== chkFlag) {
+							chkFlag = 1; break;
+						} else if (chkFlag === 2 && tmp > -1 && tmp < 2) {
+							chkFlag = 1; break;
+						} else if (tmp > -1) {
+							chkFlag = tmp;
+						}
+					}
+				}
+			}
+			node.check_Child_State = chkFlag;
+		}
+	},
+	//method of event proxy
+	_event = {
+
+	},
+	//method of event handler
+	_handler = {
+		onCheckNode: function (event, node) {
+			if (node.chkDisabled === true) return false;
+			var setting = data.getSetting(event.data.treeId),
+			checkedKey = setting.data.key.checked;
+			if (tools.apply(setting.callback.beforeCheck, [setting.treeId, node], true) == false) return true;
+			node[checkedKey] = !node[checkedKey];
+			view.checkNodeRelation(setting, node);
+			var checkObj = $("#" + node.tId + consts.id.CHECK);
+			view.setChkClass(setting, checkObj, node);
+			view.repairParentChkClassWithSelf(setting, node);
+			setting.treeObj.trigger(consts.event.CHECK, [event, setting.treeId, node]);
+			return true;
+		},
+		onMouseoverCheck: function(event, node) {
+			if (node.chkDisabled === true) return false;
+			var setting = data.getSetting(event.data.treeId),
+			checkObj = $("#" + node.tId + consts.id.CHECK);
+			node.check_Focus = true;
+			view.setChkClass(setting, checkObj, node);
+			return true;
+		},
+		onMouseoutCheck: function(event, node) {
+			if (node.chkDisabled === true) return false;
+			var setting = data.getSetting(event.data.treeId),
+			checkObj = $("#" + node.tId + consts.id.CHECK);
+			node.check_Focus = false;
+			view.setChkClass(setting, checkObj, node);
+			return true;
+		}
+	},
+	//method of tools for zTree
+	_tools = {
+
+	},
+	//method of operate ztree dom
+	_view = {
+		checkNodeRelation: function(setting, node) {
+			var pNode, i, l,
+			childKey = setting.data.key.children,
+			checkedKey = setting.data.key.checked,
+			r = consts.radio;
+			if (setting.check.chkStyle == r.STYLE) {
+				var checkedList = data.getRadioCheckedList(setting);
+				if (node[checkedKey]) {
+					if (setting.check.radioType == r.TYPE_ALL) {
+						for (i = checkedList.length-1; i >= 0; i--) {
+							pNode = checkedList[i];
+							pNode[checkedKey] = false;
+							checkedList.splice(i, 1);
+
+							view.setChkClass(setting, $("#" + pNode.tId + consts.id.CHECK), pNode);
+							if (pNode.parentTId != node.parentTId) {
+								view.repairParentChkClassWithSelf(setting, pNode);
+							}
+						}
+						checkedList.push(node);
+					} else {
+						var parentNode = (node.parentTId) ? node.getParentNode() : data.getRoot(setting);
+						for (i = 0, l = parentNode[childKey].length; i < l; i++) {
+							pNode = parentNode[childKey][i];
+							if (pNode[checkedKey] && pNode != node) {
+								pNode[checkedKey] = false;
+								view.setChkClass(setting, $("#" + pNode.tId + consts.id.CHECK), pNode);
+							}
+						}
+					}
+				} else if (setting.check.radioType == r.TYPE_ALL) {
+					for (i = 0, l = checkedList.length; i < l; i++) {
+						if (node == checkedList[i]) {
+							checkedList.splice(i, 1);
+							break;
+						}
+					}
+				}
+
+			} else {
+				if (node[checkedKey] && (!node[childKey] || node[childKey].length==0 || setting.check.chkboxType.Y.indexOf("s") > -1)) {
+					view.setSonNodeCheckBox(setting, node, true);
+				}
+				if (!node[checkedKey] && (!node[childKey] || node[childKey].length==0 || setting.check.chkboxType.N.indexOf("s") > -1)) {
+					view.setSonNodeCheckBox(setting, node, false);
+				}
+				if (node[checkedKey] && setting.check.chkboxType.Y.indexOf("p") > -1) {
+					view.setParentNodeCheckBox(setting, node, true);
+				}
+				if (!node[checkedKey] && setting.check.chkboxType.N.indexOf("p") > -1) {
+					view.setParentNodeCheckBox(setting, node, false);
+				}
+			}
+		},
+		makeChkClass: function(setting, node) {
+			var checkedKey = setting.data.key.checked,
+			c = consts.checkbox, r = consts.radio,
+			fullStyle = "";
+			if (node.chkDisabled === true) {
+				fullStyle = c.DISABLED;
+			} else if (node.halfCheck) {
+				fullStyle = c.PART;
+			} else if (setting.check.chkStyle == r.STYLE) {
+				fullStyle = (node.check_Child_State < 1)? c.FULL:c.PART;
+			} else {
+				fullStyle = node[checkedKey] ? ((node.check_Child_State === 2 || node.check_Child_State === -1) ? c.FULL:c.PART) : ((node.check_Child_State < 1)? c.FULL:c.PART);
+			}
+			var chkName = setting.check.chkStyle + "_" + (node[checkedKey] ? c.TRUE : c.FALSE) + "_" + fullStyle;
+			chkName = (node.check_Focus && node.chkDisabled !== true) ? chkName + "_" + c.FOCUS : chkName;
+			return consts.className.BUTTON + " " + c.DEFAULT + " " + chkName;
+		},
+		repairAllChk: function(setting, checked) {
+			if (setting.check.enable && setting.check.chkStyle === consts.checkbox.STYLE) {
+				var checkedKey = setting.data.key.checked,
+				childKey = setting.data.key.children,
+				root = data.getRoot(setting);
+				for (var i = 0, l = root[childKey].length; i<l ; i++) {
+					var node = root[childKey][i];
+					if (node.nocheck !== true && node.chkDisabled !== true) {
+						node[checkedKey] = checked;
+					}
+					view.setSonNodeCheckBox(setting, node, checked);
+				}
+			}
+		},
+		repairChkClass: function(setting, node) {
+			if (!node) return;
+			data.makeChkFlag(setting, node);
+			if (node.nocheck !== true) {
+				var checkObj = $("#" + node.tId + consts.id.CHECK);
+				view.setChkClass(setting, checkObj, node);
+			}
+		},
+		repairParentChkClass: function(setting, node) {
+			if (!node || !node.parentTId) return;
+			var pNode = node.getParentNode();
+			view.repairChkClass(setting, pNode);
+			view.repairParentChkClass(setting, pNode);
+		},
+		repairParentChkClassWithSelf: function(setting, node) {
+			if (!node) return;
+			var childKey = setting.data.key.children;
+			if (node[childKey] && node[childKey].length > 0) {
+				view.repairParentChkClass(setting, node[childKey][0]);
+			} else {
+				view.repairParentChkClass(setting, node);
+			}
+		},
+		repairSonChkDisabled: function(setting, node, chkDisabled, inherit) {
+			if (!node) return;
+			var childKey = setting.data.key.children;
+			if (node.chkDisabled != chkDisabled) {
+				node.chkDisabled = chkDisabled;
+			}
+			view.repairChkClass(setting, node);
+			if (node[childKey] && inherit) {
+				for (var i = 0, l = node[childKey].length; i < l; i++) {
+					var sNode = node[childKey][i];
+					view.repairSonChkDisabled(setting, sNode, chkDisabled, inherit);
+				}
+			}
+		},
+		repairParentChkDisabled: function(setting, node, chkDisabled, inherit) {
+			if (!node) return;
+			if (node.chkDisabled != chkDisabled && inherit) {
+				node.chkDisabled = chkDisabled;
+			}
+			view.repairChkClass(setting, node);
+			view.repairParentChkDisabled(setting, node.getParentNode(), chkDisabled, inherit);
+		},
+		setChkClass: function(setting, obj, node) {
+			if (!obj) return;
+			if (node.nocheck === true) {
+				obj.hide();
+			} else {
+				obj.show();
+			}
+			obj.removeClass();
+			obj.addClass(view.makeChkClass(setting, node));
+		},
+		setParentNodeCheckBox: function(setting, node, value, srcNode) {
+			var childKey = setting.data.key.children,
+			checkedKey = setting.data.key.checked,
+			checkObj = $("#" + node.tId + consts.id.CHECK);
+			if (!srcNode) srcNode = node;
+			data.makeChkFlag(setting, node);
+			if (node.nocheck !== true && node.chkDisabled !== true) {
+				node[checkedKey] = value;
+				view.setChkClass(setting, checkObj, node);
+				if (setting.check.autoCheckTrigger && node != srcNode) {
+					setting.treeObj.trigger(consts.event.CHECK, [null, setting.treeId, node]);
+				}
+			}
+			if (node.parentTId) {
+				var pSign = true;
+				if (!value) {
+					var pNodes = node.getParentNode()[childKey];
+					for (var i = 0, l = pNodes.length; i < l; i++) {
+						if ((pNodes[i].nocheck !== true && pNodes[i].chkDisabled !== true && pNodes[i][checkedKey])
+						|| ((pNodes[i].nocheck === true || pNodes[i].chkDisabled === true) && pNodes[i].check_Child_State > 0)) {
+							pSign = false;
+							break;
+						}
+					}
+				}
+				if (pSign) {
+					view.setParentNodeCheckBox(setting, node.getParentNode(), value, srcNode);
+				}
+			}
+		},
+		setSonNodeCheckBox: function(setting, node, value, srcNode) {
+			if (!node) return;
+			var childKey = setting.data.key.children,
+			checkedKey = setting.data.key.checked,
+			checkObj = $("#" + node.tId + consts.id.CHECK);
+			if (!srcNode) srcNode = node;
+
+			var hasDisable = false;
+			if (node[childKey]) {
+				for (var i = 0, l = node[childKey].length; i < l && node.chkDisabled !== true; i++) {
+					var sNode = node[childKey][i];
+					view.setSonNodeCheckBox(setting, sNode, value, srcNode);
+					if (sNode.chkDisabled === true) hasDisable = true;
+				}
+			}
+			
+			if (node != data.getRoot(setting) && node.chkDisabled !== true) {
+				if (hasDisable && node.nocheck !== true) {
+					data.makeChkFlag(setting, node);
+				}
+				if (node.nocheck !== true && node.chkDisabled !== true) {
+					node[checkedKey] = value;
+					if (!hasDisable) node.check_Child_State = (node[childKey] && node[childKey].length > 0) ? (value ? 2 : 0) : -1;
+				} else {
+					node.check_Child_State = -1;
+				}
+				view.setChkClass(setting, checkObj, node);
+				if (setting.check.autoCheckTrigger && node != srcNode && node.nocheck !== true && node.chkDisabled !== true) {
+					setting.treeObj.trigger(consts.event.CHECK, [null, setting.treeId, node]);
+				}
+			}
+
+		}
+	},
+
+	_z = {
+		tools: _tools,
+		view: _view,
+		event: _event,
+		data: _data
+	};
+	$.extend(true, $.fn.zTree.consts, _consts);
+	$.extend(true, $.fn.zTree._z, _z);
+
+	var zt = $.fn.zTree,
+	tools = zt._z.tools,
+	consts = zt.consts,
+	view = zt._z.view,
+	data = zt._z.data,
+	event = zt._z.event;
+
+	data.exSetting(_setting);
+	data.addInitBind(_bindEvent);
+	data.addInitUnBind(_unbindEvent);
+	data.addInitCache(_initCache);
+	data.addInitNode(_initNode);
+	data.addInitProxy(_eventProxy);
+	data.addInitRoot(_initRoot);
+	data.addBeforeA(_beforeA);
+	data.addZTreeTools(_zTreeTools);
+
+	var _createNodes = view.createNodes;
+	view.createNodes = function(setting, level, nodes, parentNode) {
+		if (_createNodes) _createNodes.apply(view, arguments);
+		if (!nodes) return;
+		view.repairParentChkClassWithSelf(setting, parentNode);
+	}
+	var _removeNode = view.removeNode;
+	view.removeNode = function(setting, node) {
+		var parentNode = node.getParentNode();
+		if (_removeNode) _removeNode.apply(view, arguments);
+		if (!node || !parentNode) return;
+		view.repairChkClass(setting, parentNode);
+		view.repairParentChkClass(setting, parentNode);
+	}
+
+	var _appendNodes = view.appendNodes;
+	view.appendNodes = function(setting, level, nodes, parentNode, initFlag, openFlag) {
+		var html = "";
+		if (_appendNodes) {
+			html = _appendNodes.apply(view, arguments);
+		}
+		if (parentNode) {
+			data.makeChkFlag(setting, parentNode);
+		}
+		return html;
+	}
+})(jQuery);
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/js/jquery.ztree.exedit-3.5.js b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/js/jquery.ztree.exedit-3.5.js
new file mode 100644
index 0000000..c6ec3fc
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/js/jquery.ztree.exedit-3.5.js
@@ -0,0 +1,1178 @@
+/*
+ * JQuery zTree exedit 3.5.12
+ * http://zTree.me/
+ *
+ * Copyright (c) 2010 Hunter.z
+ *
+ * Licensed same as jquery - MIT License
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ * email: hunter.z@263.net
+ * Date: 2013-03-11
+ */
+(function($){
+	//default consts of exedit
+	var _consts = {
+		event: {
+			DRAG: "ztree_drag",
+			DROP: "ztree_drop",
+			REMOVE: "ztree_remove",
+			RENAME: "ztree_rename"
+		},
+		id: {
+			EDIT: "_edit",
+			INPUT: "_input",
+			REMOVE: "_remove"
+		},
+		move: {
+			TYPE_INNER: "inner",
+			TYPE_PREV: "prev",
+			TYPE_NEXT: "next"
+		},
+		node: {
+			CURSELECTED_EDIT: "curSelectedNode_Edit",
+			TMPTARGET_TREE: "tmpTargetzTree",
+			TMPTARGET_NODE: "tmpTargetNode"
+		}
+	},
+	//default setting of exedit
+	_setting = {
+		edit: {
+			enable: false,
+			editNameSelectAll: false,
+			showRemoveBtn: true,
+			showRenameBtn: true,
+			removeTitle: "remove",
+			renameTitle: "rename",
+			drag: {
+				autoExpandTrigger: false,
+				isCopy: true,
+				isMove: true,
+				prev: true,
+				next: true,
+				inner: true,
+				minMoveSize: 5,
+				borderMax: 10,
+				borderMin: -5,
+				maxShowNodeNum: 5,
+				autoOpenTime: 500
+			}
+		},
+		view: {
+			addHoverDom: null,
+			removeHoverDom: null
+		},
+		callback: {
+			beforeDrag:null,
+			beforeDragOpen:null,
+			beforeDrop:null,
+			beforeEditName:null,
+			beforeRename:null,
+			onDrag:null,
+			onDrop:null,
+			onRename:null
+		}
+	},
+	//default root of exedit
+	_initRoot = function (setting) {
+		var r = data.getRoot(setting);
+		r.curEditNode = null;
+		r.curEditInput = null;
+		r.curHoverNode = null;
+		r.dragFlag = 0;
+		r.dragNodeShowBefore = [];
+		r.dragMaskList = new Array();
+		r.showHoverDom = true;
+	},
+	//default cache of exedit
+	_initCache = function(treeId) {},
+	//default bind event of exedit
+	_bindEvent = function(setting) {
+		var o = setting.treeObj;
+		var c = consts.event;
+		o.bind(c.RENAME, function (event, treeId, treeNode) {
+			tools.apply(setting.callback.onRename, [event, treeId, treeNode]);
+		});
+
+		o.bind(c.REMOVE, function (event, treeId, treeNode) {
+			tools.apply(setting.callback.onRemove, [event, treeId, treeNode]);
+		});
+
+		o.bind(c.DRAG, function (event, srcEvent, treeId, treeNodes) {
+			tools.apply(setting.callback.onDrag, [srcEvent, treeId, treeNodes]);
+		});
+
+		o.bind(c.DROP, function (event, srcEvent, treeId, treeNodes, targetNode, moveType, isCopy) {
+			tools.apply(setting.callback.onDrop, [srcEvent, treeId, treeNodes, targetNode, moveType, isCopy]);
+		});
+	},
+	_unbindEvent = function(setting) {
+		var o = setting.treeObj;
+		var c = consts.event;
+		o.unbind(c.RENAME);
+		o.unbind(c.REMOVE);
+		o.unbind(c.DRAG);
+		o.unbind(c.DROP);
+	},
+	//default event proxy of exedit
+	_eventProxy = function(e) {
+		var target = e.target,
+		setting = data.getSetting(e.data.treeId),
+		relatedTarget = e.relatedTarget,
+		tId = "", node = null,
+		nodeEventType = "", treeEventType = "",
+		nodeEventCallback = null, treeEventCallback = null,
+		tmp = null;
+
+		if (tools.eqs(e.type, "mouseover")) {
+			tmp = tools.getMDom(setting, target, [{tagName:"a", attrName:"treeNode"+consts.id.A}]);
+			if (tmp) {
+				tId = tmp.parentNode.id;
+				nodeEventType = "hoverOverNode";
+			}
+		} else if (tools.eqs(e.type, "mouseout")) {
+			tmp = tools.getMDom(setting, relatedTarget, [{tagName:"a", attrName:"treeNode"+consts.id.A}]);
+			if (!tmp) {
+				tId = "remove";
+				nodeEventType = "hoverOutNode";
+			}
+		} else if (tools.eqs(e.type, "mousedown")) {
+			tmp = tools.getMDom(setting, target, [{tagName:"a", attrName:"treeNode"+consts.id.A}]);
+			if (tmp) {
+				tId = tmp.parentNode.id;
+				nodeEventType = "mousedownNode";
+			}
+		}
+		if (tId.length>0) {
+			node = data.getNodeCache(setting, tId);
+			switch (nodeEventType) {
+				case "mousedownNode" :
+					nodeEventCallback = _handler.onMousedownNode;
+					break;
+				case "hoverOverNode" :
+					nodeEventCallback = _handler.onHoverOverNode;
+					break;
+				case "hoverOutNode" :
+					nodeEventCallback = _handler.onHoverOutNode;
+					break;
+			}
+		}
+		var proxyResult = {
+			stop: false,
+			node: node,
+			nodeEventType: nodeEventType,
+			nodeEventCallback: nodeEventCallback,
+			treeEventType: treeEventType,
+			treeEventCallback: treeEventCallback
+		};
+		return proxyResult
+	},
+	//default init node of exedit
+	_initNode = function(setting, level, n, parentNode, isFirstNode, isLastNode, openFlag) {
+		if (!n) return;
+		n.isHover = false;
+		n.editNameFlag = false;
+	},
+	//update zTreeObj, add method of edit
+	_zTreeTools = function(setting, zTreeTools) {
+		zTreeTools.cancelEditName = function(newName) {
+			var root = data.getRoot(setting),
+			nameKey = setting.data.key.name,
+			node = root.curEditNode;
+			if (!root.curEditNode) return;
+			view.cancelCurEditNode(setting, newName?newName:node[nameKey]);
+		}
+		zTreeTools.copyNode = function(targetNode, node, moveType, isSilent) {
+			if (!node) return null;
+			if (targetNode && !targetNode.isParent && setting.data.keep.leaf && moveType === consts.move.TYPE_INNER) return null;
+			var newNode = tools.clone(node);
+			if (!targetNode) {
+				targetNode = null;
+				moveType = consts.move.TYPE_INNER;
+			}
+			if (moveType == consts.move.TYPE_INNER) {
+				function copyCallback() {
+					view.addNodes(setting, targetNode, [newNode], isSilent);
+				}
+
+				if (tools.canAsync(setting, targetNode)) {
+					view.asyncNode(setting, targetNode, isSilent, copyCallback);
+				} else {
+					copyCallback();
+				}
+			} else {
+				view.addNodes(setting, targetNode.parentNode, [newNode], isSilent);
+				view.moveNode(setting, targetNode, newNode, moveType, false, isSilent);
+			}
+			return newNode;
+		}
+		zTreeTools.editName = function(node) {
+			if (!node || !node.tId || node !== data.getNodeCache(setting, node.tId)) return;
+			if (node.parentTId) view.expandCollapseParentNode(setting, node.getParentNode(), true);
+			view.editNode(setting, node)
+		}
+		zTreeTools.moveNode = function(targetNode, node, moveType, isSilent) {
+			if (!node) return node;
+			if (targetNode && !targetNode.isParent && setting.data.keep.leaf && moveType === consts.move.TYPE_INNER) {
+				return null;
+			} else if (targetNode && ((node.parentTId == targetNode.tId && moveType == consts.move.TYPE_INNER) || $("#" + node.tId).find("#" + targetNode.tId).length > 0)) {
+				return null;
+			} else if (!targetNode) {
+				targetNode = null;
+			}
+			function moveCallback() {
+				view.moveNode(setting, targetNode, node, moveType, false, isSilent);
+			}
+			if (tools.canAsync(setting, targetNode) && moveType === consts.move.TYPE_INNER) {
+				view.asyncNode(setting, targetNode, isSilent, moveCallback);
+			} else {
+				moveCallback();
+			}
+			return node;
+		}
+		zTreeTools.setEditable = function(editable) {
+			setting.edit.enable = editable;
+			return this.refresh();
+		}
+	},
+	//method of operate data
+	_data = {
+		setSonNodeLevel: function(setting, parentNode, node) {
+			if (!node) return;
+			var childKey = setting.data.key.children;
+			node.level = (parentNode)? parentNode.level + 1 : 0;
+			if (!node[childKey]) return;
+			for (var i = 0, l = node[childKey].length; i < l; i++) {
+				if (node[childKey][i]) data.setSonNodeLevel(setting, node, node[childKey][i]);
+			}
+		}
+	},
+	//method of event proxy
+	_event = {
+
+	},
+	//method of event handler
+	_handler = {
+		onHoverOverNode: function(event, node) {
+			var setting = data.getSetting(event.data.treeId),
+			root = data.getRoot(setting);
+			if (root.curHoverNode != node) {
+				_handler.onHoverOutNode(event);
+			}
+			root.curHoverNode = node;
+			view.addHoverDom(setting, node);
+		},
+		onHoverOutNode: function(event, node) {
+			var setting = data.getSetting(event.data.treeId),
+			root = data.getRoot(setting);
+			if (root.curHoverNode && !data.isSelectedNode(setting, root.curHoverNode)) {
+				view.removeTreeDom(setting, root.curHoverNode);
+				root.curHoverNode = null;
+			}
+		},
+		onMousedownNode: function(eventMouseDown, _node) {
+			var i,l,
+			setting = data.getSetting(eventMouseDown.data.treeId),
+			root = data.getRoot(setting);
+			//right click can't drag & drop
+			if (eventMouseDown.button == 2 || !setting.edit.enable || (!setting.edit.drag.isCopy && !setting.edit.drag.isMove)) return true;
+
+			//input of edit node name can't drag & drop
+			var target = eventMouseDown.target,
+			_nodes = data.getRoot(setting).curSelectedList,
+			nodes = [];
+			if (!data.isSelectedNode(setting, _node)) {
+				nodes = [_node];
+			} else {
+				for (i=0, l=_nodes.length; i<l; i++) {
+					if (_nodes[i].editNameFlag && tools.eqs(target.tagName, "input") && target.getAttribute("treeNode"+consts.id.INPUT) !== null) {
+						return true;
+					}
+					nodes.push(_nodes[i]);
+					if (nodes[0].parentTId !== _nodes[i].parentTId) {
+						nodes = [_node];
+						break;
+					}
+				}
+			}
+
+			view.editNodeBlur = true;
+			view.cancelCurEditNode(setting, null, true);
+			
+
+			var doc = $(document), curNode, tmpArrow, tmpTarget,
+			isOtherTree = false,
+			targetSetting = setting,
+			preNode, nextNode,
+			preTmpTargetNodeId = null,
+			preTmpMoveType = null,
+			tmpTargetNodeId = null,
+			moveType = consts.move.TYPE_INNER,
+			mouseDownX = eventMouseDown.clientX,
+			mouseDownY = eventMouseDown.clientY,
+			startTime = (new Date()).getTime();
+
+			if (tools.uCanDo(setting)) {
+				doc.bind("mousemove", _docMouseMove);
+			}
+			function _docMouseMove(event) {
+				//avoid start drag after click node
+				if (root.dragFlag == 0 && Math.abs(mouseDownX - event.clientX) < setting.edit.drag.minMoveSize
+					&& Math.abs(mouseDownY - event.clientY) < setting.edit.drag.minMoveSize) {
+					return true;
+				}
+				var i, l, tmpNode, tmpDom, tmpNodes,
+				childKey = setting.data.key.children;
+				$("body").css("cursor", "pointer");
+
+				if (root.dragFlag == 0) {
+					if (tools.apply(setting.callback.beforeDrag, [setting.treeId, nodes], true) == false) {
+						_docMouseUp(event);
+						return true;
+					}
+
+					for (i=0, l=nodes.length; i<l; i++) {
+						if (i==0) {
+							root.dragNodeShowBefore = [];
+						}
+						tmpNode = nodes[i];
+						if (tmpNode.isParent && tmpNode.open) {
+							view.expandCollapseNode(setting, tmpNode, !tmpNode.open);
+							root.dragNodeShowBefore[tmpNode.tId] = true;
+						} else {
+							root.dragNodeShowBefore[tmpNode.tId] = false;
+						}
+					}
+
+					root.dragFlag = 1;
+					root.showHoverDom = false;
+					tools.showIfameMask(setting, true);
+
+					//sort
+					var isOrder = true, lastIndex = -1;
+					if (nodes.length>1) {
+						var pNodes = nodes[0].parentTId ? nodes[0].getParentNode()[childKey] : data.getNodes(setting);
+						tmpNodes = [];
+						for (i=0, l=pNodes.length; i<l; i++) {
+							if (root.dragNodeShowBefore[pNodes[i].tId] !== undefined) {
+								if (isOrder && lastIndex > -1 && (lastIndex+1) !== i) {
+									isOrder = false;
+								}
+								tmpNodes.push(pNodes[i]);
+								lastIndex = i;
+							}
+							if (nodes.length === tmpNodes.length) {
+								nodes = tmpNodes;
+								break;
+							}
+						}
+					}
+					if (isOrder) {
+						preNode = nodes[0].getPreNode();
+						nextNode = nodes[nodes.length-1].getNextNode();
+					}
+
+					//set node in selected
+					curNode = $("<ul class='zTreeDragUL'></ul>");
+					for (i=0, l=nodes.length; i<l; i++) {
+						tmpNode = nodes[i];
+						tmpNode.editNameFlag = false;
+						view.selectNode(setting, tmpNode, i>0);
+						view.removeTreeDom(setting, tmpNode);
+
+						tmpDom = $("<li id='"+ tmpNode.tId +"_tmp'></li>");
+						tmpDom.append($("#" + tmpNode.tId + consts.id.A).clone());
+						tmpDom.css("padding", "0");
+						tmpDom.children("#" + tmpNode.tId + consts.id.A).removeClass(consts.node.CURSELECTED);
+						curNode.append(tmpDom);
+						if (i == setting.edit.drag.maxShowNodeNum-1) {
+							tmpDom = $("<li id='"+ tmpNode.tId +"_moretmp'><a>  ...  </a></li>");
+							curNode.append(tmpDom);
+							break;
+						}
+					}
+					curNode.attr("id", nodes[0].tId + consts.id.UL + "_tmp");
+					curNode.addClass(setting.treeObj.attr("class"));
+					curNode.appendTo("body");
+
+					tmpArrow = $("<span class='tmpzTreeMove_arrow'></span>");
+					tmpArrow.attr("id", "zTreeMove_arrow_tmp");
+					tmpArrow.appendTo("body");
+
+					setting.treeObj.trigger(consts.event.DRAG, [event, setting.treeId, nodes]);
+				}
+
+				if (root.dragFlag == 1) {
+					if (tmpTarget && tmpArrow.attr("id") == event.target.id && tmpTargetNodeId && (event.clientX + doc.scrollLeft()+2) > ($("#" + tmpTargetNodeId + consts.id.A, tmpTarget).offset().left)) {
+						var xT = $("#" + tmpTargetNodeId + consts.id.A, tmpTarget);
+						event.target = (xT.length > 0) ? xT.get(0) : event.target;
+					} else if (tmpTarget) {
+						tmpTarget.removeClass(consts.node.TMPTARGET_TREE);
+						if (tmpTargetNodeId) $("#" + tmpTargetNodeId + consts.id.A, tmpTarget).removeClass(consts.node.TMPTARGET_NODE + "_" + consts.move.TYPE_PREV)
+							.removeClass(consts.node.TMPTARGET_NODE + "_" + _consts.move.TYPE_NEXT).removeClass(consts.node.TMPTARGET_NODE + "_" + _consts.move.TYPE_INNER);
+					}
+					tmpTarget = null;
+					tmpTargetNodeId = null;
+
+					//judge drag & drop in multi ztree
+					isOtherTree = false;
+					targetSetting = setting;
+					var settings = data.getSettings();
+					for (var s in settings) {
+						if (settings[s].treeId && settings[s].edit.enable && settings[s].treeId != setting.treeId
+							&& (event.target.id == settings[s].treeId || $(event.target).parents("#" + settings[s].treeId).length>0)) {
+							isOtherTree = true;
+							targetSetting = settings[s];
+						}
+					}
+
+					var docScrollTop = doc.scrollTop(),
+					docScrollLeft = doc.scrollLeft(),
+					treeOffset = targetSetting.treeObj.offset(),
+					scrollHeight = targetSetting.treeObj.get(0).scrollHeight,
+					scrollWidth = targetSetting.treeObj.get(0).scrollWidth,
+					dTop = (event.clientY + docScrollTop - treeOffset.top),
+					dBottom = (targetSetting.treeObj.height() + treeOffset.top - event.clientY - docScrollTop),
+					dLeft = (event.clientX + docScrollLeft - treeOffset.left),
+					dRight = (targetSetting.treeObj.width() + treeOffset.left - event.clientX - docScrollLeft),
+					isTop = (dTop < setting.edit.drag.borderMax && dTop > setting.edit.drag.borderMin),
+					isBottom = (dBottom < setting.edit.drag.borderMax && dBottom > setting.edit.drag.borderMin),
+					isLeft = (dLeft < setting.edit.drag.borderMax && dLeft > setting.edit.drag.borderMin),
+					isRight = (dRight < setting.edit.drag.borderMax && dRight > setting.edit.drag.borderMin),
+					isTreeInner = dTop > setting.edit.drag.borderMin && dBottom > setting.edit.drag.borderMin && dLeft > setting.edit.drag.borderMin && dRight > setting.edit.drag.borderMin,
+					isTreeTop = (isTop && targetSetting.treeObj.scrollTop() <= 0),
+					isTreeBottom = (isBottom && (targetSetting.treeObj.scrollTop() + targetSetting.treeObj.height()+10) >= scrollHeight),
+					isTreeLeft = (isLeft && targetSetting.treeObj.scrollLeft() <= 0),
+					isTreeRight = (isRight && (targetSetting.treeObj.scrollLeft() + targetSetting.treeObj.width()+10) >= scrollWidth);
+
+					if (event.target.id && targetSetting.treeObj.find("#" + event.target.id).length > 0) {
+						//get node <li> dom
+						var targetObj = event.target;
+						while (targetObj && targetObj.tagName && !tools.eqs(targetObj.tagName, "li") && targetObj.id != targetSetting.treeId) {
+							targetObj = targetObj.parentNode;
+						}
+
+						var canMove = true;
+						//don't move to self or children of self
+						for (i=0, l=nodes.length; i<l; i++) {
+							tmpNode = nodes[i];
+							if (targetObj.id === tmpNode.tId) {
+								canMove = false;
+								break;
+							} else if ($("#" + tmpNode.tId).find("#" + targetObj.id).length > 0) {
+								canMove = false;
+								break;
+							}
+						}
+						if (canMove) {
+							if (event.target.id &&
+								(event.target.id == (targetObj.id + consts.id.A) || $(event.target).parents("#" + targetObj.id + consts.id.A).length > 0)) {
+								tmpTarget = $(targetObj);
+								tmpTargetNodeId = targetObj.id;
+							}
+						}
+					}
+
+					//the mouse must be in zTree
+					tmpNode = nodes[0];
+					if (isTreeInner && (event.target.id == targetSetting.treeId || $(event.target).parents("#" + targetSetting.treeId).length>0)) {
+						//judge mouse move in root of ztree
+						if (!tmpTarget && (event.target.id == targetSetting.treeId || isTreeTop || isTreeBottom || isTreeLeft || isTreeRight) && (isOtherTree || (!isOtherTree && tmpNode.parentTId))) {
+							tmpTarget = targetSetting.treeObj;
+						}
+						//auto scroll top
+						if (isTop) {
+							targetSetting.treeObj.scrollTop(targetSetting.treeObj.scrollTop()-10);
+						} else if (isBottom)  {
+							targetSetting.treeObj.scrollTop(targetSetting.treeObj.scrollTop()+10);
+						}
+						if (isLeft) {
+							targetSetting.treeObj.scrollLeft(targetSetting.treeObj.scrollLeft()-10);
+						} else if (isRight) {
+							targetSetting.treeObj.scrollLeft(targetSetting.treeObj.scrollLeft()+10);
+						}
+						//auto scroll left
+						if (tmpTarget && tmpTarget != targetSetting.treeObj && tmpTarget.offset().left < targetSetting.treeObj.offset().left) {
+							targetSetting.treeObj.scrollLeft(targetSetting.treeObj.scrollLeft()+ tmpTarget.offset().left - targetSetting.treeObj.offset().left);
+						}
+					}
+
+					curNode.css({
+						"top": (event.clientY + docScrollTop + 3) + "px",
+						"left": (event.clientX + docScrollLeft + 3) + "px"
+					});
+
+					var dX = 0;
+					var dY = 0;
+					if (tmpTarget && tmpTarget.attr("id")!=targetSetting.treeId) {
+						var tmpTargetNode = tmpTargetNodeId == null ? null: data.getNodeCache(targetSetting, tmpTargetNodeId),
+						isCopy = (event.ctrlKey && setting.edit.drag.isMove && setting.edit.drag.isCopy) || (!setting.edit.drag.isMove && setting.edit.drag.isCopy),
+						isPrev = !!(preNode && tmpTargetNodeId === preNode.tId),
+						isNext = !!(nextNode && tmpTargetNodeId === nextNode.tId),
+						isInner = (tmpNode.parentTId && tmpNode.parentTId == tmpTargetNodeId),
+						canPrev = (isCopy || !isNext) && tools.apply(targetSetting.edit.drag.prev, [targetSetting.treeId, nodes, tmpTargetNode], !!targetSetting.edit.drag.prev),
+						canNext = (isCopy || !isPrev) && tools.apply(targetSetting.edit.drag.next, [targetSetting.treeId, nodes, tmpTargetNode], !!targetSetting.edit.drag.next),
+						canInner = (isCopy || !isInner) && !(targetSetting.data.keep.leaf && !tmpTargetNode.isParent) && tools.apply(targetSetting.edit.drag.inner, [targetSetting.treeId, nodes, tmpTargetNode], !!targetSetting.edit.drag.inner);
+						if (!canPrev && !canNext && !canInner) {
+							tmpTarget = null;
+							tmpTargetNodeId = "";
+							moveType = consts.move.TYPE_INNER;
+							tmpArrow.css({
+								"display":"none"
+							});
+							if (window.zTreeMoveTimer) {
+								clearTimeout(window.zTreeMoveTimer);
+								window.zTreeMoveTargetNodeTId = null
+							}
+						} else {
+							var tmpTargetA = $("#" + tmpTargetNodeId + consts.id.A, tmpTarget),
+							tmpNextA = tmpTargetNode.isLastNode ? null : $("#" + tmpTargetNode.getNextNode().tId + consts.id.A, tmpTarget.next()),
+							tmpTop = tmpTargetA.offset().top,
+							tmpLeft = tmpTargetA.offset().left,
+							prevPercent = canPrev ? (canInner ? 0.25 : (canNext ? 0.5 : 1) ) : -1,
+							nextPercent = canNext ? (canInner ? 0.75 : (canPrev ? 0.5 : 0) ) : -1,
+							dY_percent = (event.clientY + docScrollTop - tmpTop)/tmpTargetA.height();
+							if ((prevPercent==1 ||dY_percent<=prevPercent && dY_percent>=-.2) && canPrev) {
+								dX = 1 - tmpArrow.width();
+								dY = tmpTop - tmpArrow.height()/2;
+								moveType = consts.move.TYPE_PREV;
+							} else if ((nextPercent==0 || dY_percent>=nextPercent && dY_percent<=1.2) && canNext) {
+								dX = 1 - tmpArrow.width();
+								dY = (tmpNextA == null || (tmpTargetNode.isParent && tmpTargetNode.open)) ? (tmpTop + tmpTargetA.height() - tmpArrow.height()/2) : (tmpNextA.offset().top - tmpArrow.height()/2);
+								moveType = consts.move.TYPE_NEXT;
+							}else {
+								dX = 5 - tmpArrow.width();
+								dY = tmpTop;
+								moveType = consts.move.TYPE_INNER;
+							}
+							tmpArrow.css({
+								"display":"block",
+								"top": dY + "px",
+								"left": (tmpLeft + dX) + "px"
+							});
+							tmpTargetA.addClass(consts.node.TMPTARGET_NODE + "_" + moveType);
+
+							if (preTmpTargetNodeId != tmpTargetNodeId || preTmpMoveType != moveType) {
+								startTime = (new Date()).getTime();
+							}
+							if (tmpTargetNode && tmpTargetNode.isParent && moveType == consts.move.TYPE_INNER) {
+								var startTimer = true;
+								if (window.zTreeMoveTimer && window.zTreeMoveTargetNodeTId !== tmpTargetNode.tId) {
+									clearTimeout(window.zTreeMoveTimer);
+									window.zTreeMoveTargetNodeTId = null;
+								} else if (window.zTreeMoveTimer && window.zTreeMoveTargetNodeTId === tmpTargetNode.tId) {
+									startTimer = false;
+								}
+								if (startTimer) {
+									window.zTreeMoveTimer = setTimeout(function() {
+										if (moveType != consts.move.TYPE_INNER) return;
+										if (tmpTargetNode && tmpTargetNode.isParent && !tmpTargetNode.open && (new Date()).getTime() - startTime > targetSetting.edit.drag.autoOpenTime
+											&& tools.apply(targetSetting.callback.beforeDragOpen, [targetSetting.treeId, tmpTargetNode], true)) {
+											view.switchNode(targetSetting, tmpTargetNode);
+											if (targetSetting.edit.drag.autoExpandTrigger) {
+												targetSetting.treeObj.trigger(consts.event.EXPAND, [targetSetting.treeId, tmpTargetNode]);
+											}
+										}
+									}, targetSetting.edit.drag.autoOpenTime+50);
+									window.zTreeMoveTargetNodeTId = tmpTargetNode.tId;
+								}
+							}
+						}
+					} else {
+						moveType = consts.move.TYPE_INNER;
+						if (tmpTarget && tools.apply(targetSetting.edit.drag.inner, [targetSetting.treeId, nodes, null], !!targetSetting.edit.drag.inner)) {
+							tmpTarget.addClass(consts.node.TMPTARGET_TREE);
+						} else {
+							tmpTarget = null;
+						}
+						tmpArrow.css({
+							"display":"none"
+						});
+						if (window.zTreeMoveTimer) {
+							clearTimeout(window.zTreeMoveTimer);
+							window.zTreeMoveTargetNodeTId = null;
+						}
+					}
+					preTmpTargetNodeId = tmpTargetNodeId;
+					preTmpMoveType = moveType;
+				}
+				return false;
+			}
+
+			doc.bind("mouseup", _docMouseUp);
+			function _docMouseUp(event) {
+				if (window.zTreeMoveTimer) {
+					clearTimeout(window.zTreeMoveTimer);
+					window.zTreeMoveTargetNodeTId = null;
+				}
+				preTmpTargetNodeId = null;
+				preTmpMoveType = null;
+				doc.unbind("mousemove", _docMouseMove);
+				doc.unbind("mouseup", _docMouseUp);
+				doc.unbind("selectstart", _docSelect);
+				$("body").css("cursor", "auto");
+				if (tmpTarget) {
+					tmpTarget.removeClass(consts.node.TMPTARGET_TREE);
+					if (tmpTargetNodeId) $("#" + tmpTargetNodeId + consts.id.A, tmpTarget).removeClass(consts.node.TMPTARGET_NODE + "_" + consts.move.TYPE_PREV)
+							.removeClass(consts.node.TMPTARGET_NODE + "_" + _consts.move.TYPE_NEXT).removeClass(consts.node.TMPTARGET_NODE + "_" + _consts.move.TYPE_INNER);
+				}
+				tools.showIfameMask(setting, false);
+
+				root.showHoverDom = true;
+				if (root.dragFlag == 0) return;
+				root.dragFlag = 0;
+
+				var i, l, tmpNode;
+				for (i=0, l=nodes.length; i<l; i++) {
+					tmpNode = nodes[i];
+					if (tmpNode.isParent && root.dragNodeShowBefore[tmpNode.tId] && !tmpNode.open) {
+						view.expandCollapseNode(setting, tmpNode, !tmpNode.open);
+						delete root.dragNodeShowBefore[tmpNode.tId];
+					}
+				}
+
+				if (curNode) curNode.remove();
+				if (tmpArrow) tmpArrow.remove();
+
+				var isCopy = (event.ctrlKey && setting.edit.drag.isMove && setting.edit.drag.isCopy) || (!setting.edit.drag.isMove && setting.edit.drag.isCopy);
+				if (!isCopy && tmpTarget && tmpTargetNodeId && nodes[0].parentTId && tmpTargetNodeId==nodes[0].parentTId && moveType == consts.move.TYPE_INNER) {
+					tmpTarget = null;
+				}
+				if (tmpTarget) {
+					var dragTargetNode = tmpTargetNodeId == null ? null: data.getNodeCache(targetSetting, tmpTargetNodeId);
+					if (tools.apply(setting.callback.beforeDrop, [targetSetting.treeId, nodes, dragTargetNode, moveType, isCopy], true) == false) return;
+					var newNodes = isCopy ? tools.clone(nodes) : nodes;
+					
+					function dropCallback() {
+						if (isOtherTree) {							
+							if (!isCopy) {
+								for(var i=0, l=nodes.length; i<l; i++) {
+									view.removeNode(setting, nodes[i]);
+								}
+							}
+							if (moveType == consts.move.TYPE_INNER) {
+								view.addNodes(targetSetting, dragTargetNode, newNodes);
+							} else {
+								view.addNodes(targetSetting, dragTargetNode.getParentNode(), newNodes);
+								if (moveType == consts.move.TYPE_PREV) {
+									for (i=0, l=newNodes.length; i<l; i++) {
+										view.moveNode(targetSetting, dragTargetNode, newNodes[i], moveType, false);
+									}
+								} else {
+									for (i=-1, l=newNodes.length-1; i<l; l--) {
+										view.moveNode(targetSetting, dragTargetNode, newNodes[l], moveType, false);
+									}
+								}
+							}
+						} else {
+							if (isCopy && moveType == consts.move.TYPE_INNER) {
+								view.addNodes(targetSetting, dragTargetNode, newNodes);
+							} else {
+								if (isCopy) {
+									view.addNodes(targetSetting, dragTargetNode.getParentNode(), newNodes);
+								}
+								if (moveType != consts.move.TYPE_NEXT) {
+									for (i=0, l=newNodes.length; i<l; i++) {
+										view.moveNode(targetSetting, dragTargetNode, newNodes[i], moveType, false);
+									}
+								} else {
+									for (i=-1, l=newNodes.length-1; i<l; l--) {
+										view.moveNode(targetSetting, dragTargetNode, newNodes[l], moveType, false);
+									}
+								}
+							}
+						}
+						for (i=0, l=newNodes.length; i<l; i++) {
+							view.selectNode(targetSetting, newNodes[i], i>0);
+						}
+						$("#" + newNodes[0].tId).focus().blur();
+
+						setting.treeObj.trigger(consts.event.DROP, [event, targetSetting.treeId, newNodes, dragTargetNode, moveType, isCopy]);
+					}
+
+					if (moveType == consts.move.TYPE_INNER && tools.canAsync(targetSetting, dragTargetNode)) {
+						view.asyncNode(targetSetting, dragTargetNode, false, dropCallback);
+					} else {
+						dropCallback();
+					}
+
+				} else {
+					for (i=0, l=nodes.length; i<l; i++) {
+						view.selectNode(targetSetting, nodes[i], i>0);
+					}
+					setting.treeObj.trigger(consts.event.DROP, [event, setting.treeId, nodes, null, null, null]);
+				}
+			}
+
+			doc.bind("selectstart", _docSelect);
+			function _docSelect() {
+				return false;
+			}
+
+			//Avoid FireFox's Bug
+			//If zTree Div CSS set 'overflow', so drag node outside of zTree, and event.target is error.
+			if(eventMouseDown.preventDefault) {
+				eventMouseDown.preventDefault();
+			}
+			return true;
+		}
+	},
+	//method of tools for zTree
+	_tools = {
+		getAbs: function (obj) {
+			var oRect = obj.getBoundingClientRect();
+			return [oRect.left,oRect.top]
+		},
+		inputFocus: function(inputObj) {
+			if (inputObj.get(0)) {
+				inputObj.focus();
+				tools.setCursorPosition(inputObj.get(0), inputObj.val().length);
+			}
+		},
+		inputSelect: function(inputObj) {
+			if (inputObj.get(0)) {
+				inputObj.focus();
+				inputObj.select();
+			}
+		},
+		setCursorPosition: function(obj, pos){
+			if(obj.setSelectionRange) {
+				obj.focus();
+				obj.setSelectionRange(pos,pos);
+			} else if (obj.createTextRange) {
+				var range = obj.createTextRange();
+				range.collapse(true);
+				range.moveEnd('character', pos);
+				range.moveStart('character', pos);
+				range.select();
+			}
+		},
+		showIfameMask: function(setting, showSign) {
+			var root = data.getRoot(setting);
+			//clear full mask
+			while (root.dragMaskList.length > 0) {
+				root.dragMaskList[0].remove();
+				root.dragMaskList.shift();
+			}
+			if (showSign) {
+				//show mask
+				var iframeList = $("iframe");
+				for (var i = 0, l = iframeList.length; i < l; i++) {
+					var obj = iframeList.get(i),
+					r = tools.getAbs(obj),
+					dragMask = $("<div id='zTreeMask_" + i + "' class='zTreeMask' style='top:" + r[1] + "px; left:" + r[0] + "px; width:" + obj.offsetWidth + "px; height:" + obj.offsetHeight + "px;'></div>");
+					dragMask.appendTo("body");
+					root.dragMaskList.push(dragMask);
+				}
+			}
+		}
+	},
+	//method of operate ztree dom
+	_view = {
+		addEditBtn: function(setting, node) {
+			if (node.editNameFlag || $("#" + node.tId + consts.id.EDIT).length > 0) {
+				return;
+			}
+			if (!tools.apply(setting.edit.showRenameBtn, [setting.treeId, node], setting.edit.showRenameBtn)) {
+				return;
+			}
+			var aObj = $("#" + node.tId + consts.id.A),
+			editStr = "<span class='" + consts.className.BUTTON + " edit' id='" + node.tId + consts.id.EDIT + "' title='"+tools.apply(setting.edit.renameTitle, [setting.treeId, node], setting.edit.renameTitle)+"' treeNode"+consts.id.EDIT+" style='display:none;'></span>";
+			aObj.append(editStr);
+
+			$("#" + node.tId + consts.id.EDIT).bind('click',
+				function() {
+					if (!tools.uCanDo(setting) || tools.apply(setting.callback.beforeEditName, [setting.treeId, node], true) == false) return false;
+					view.editNode(setting, node);
+					return false;
+				}
+				).show();
+		},
+		addRemoveBtn: function(setting, node) {
+			if (node.editNameFlag || $("#" + node.tId + consts.id.REMOVE).length > 0) {
+				return;
+			}
+			if (!tools.apply(setting.edit.showRemoveBtn, [setting.treeId, node], setting.edit.showRemoveBtn)) {
+				return;
+			}
+			var aObj = $("#" + node.tId + consts.id.A),
+			removeStr = "<span class='" + consts.className.BUTTON + " remove' id='" + node.tId + consts.id.REMOVE + "' title='"+tools.apply(setting.edit.removeTitle, [setting.treeId, node], setting.edit.removeTitle)+"' treeNode"+consts.id.REMOVE+" style='display:none;'></span>";
+			aObj.append(removeStr);
+
+			$("#" + node.tId + consts.id.REMOVE).bind('click',
+				function() {
+					if (!tools.uCanDo(setting) || tools.apply(setting.callback.beforeRemove, [setting.treeId, node], true) == false) return false;
+					view.removeNode(setting, node);
+					setting.treeObj.trigger(consts.event.REMOVE, [setting.treeId, node]);
+					return false;
+				}
+				).bind('mousedown',
+				function(eventMouseDown) {
+					return true;
+				}
+				).show();
+		},
+		addHoverDom: function(setting, node) {
+			if (data.getRoot(setting).showHoverDom) {
+				node.isHover = true;
+				if (setting.edit.enable) {
+					view.addEditBtn(setting, node);
+					view.addRemoveBtn(setting, node);
+				}
+				tools.apply(setting.view.addHoverDom, [setting.treeId, node]);
+			}
+		},
+		cancelCurEditNode: function (setting, forceName) {
+			var root = data.getRoot(setting),
+			nameKey = setting.data.key.name,
+			node = root.curEditNode;
+			
+			if (node) {
+				var inputObj = root.curEditInput;
+				var newName = forceName ? forceName:inputObj.val();
+				if (!forceName && tools.apply(setting.callback.beforeRename, [setting.treeId, node, newName], true) === false) {
+					return false;
+				} else {
+					node[nameKey] = newName ? newName:inputObj.val();
+					if (!forceName) {
+						setting.treeObj.trigger(consts.event.RENAME, [setting.treeId, node]);
+					}
+				}
+				var aObj = $("#" + node.tId + consts.id.A);
+				aObj.removeClass(consts.node.CURSELECTED_EDIT);
+				inputObj.unbind();
+				view.setNodeName(setting, node);
+				node.editNameFlag = false;
+				root.curEditNode = null;
+				root.curEditInput = null;
+				view.selectNode(setting, node, false);
+			}
+			root.noSelection = true;
+			return true;
+		},
+		editNode: function(setting, node) {
+			var root = data.getRoot(setting);
+			view.editNodeBlur = false;
+			if (data.isSelectedNode(setting, node) && root.curEditNode == node && node.editNameFlag) {
+				setTimeout(function() {tools.inputFocus(root.curEditInput);}, 0);
+				return;
+			}
+			var nameKey = setting.data.key.name;
+			node.editNameFlag = true;
+			view.removeTreeDom(setting, node);
+			view.cancelCurEditNode(setting);
+			view.selectNode(setting, node, false);
+			$("#" + node.tId + consts.id.SPAN).html("<input type=text class='rename' id='" + node.tId + consts.id.INPUT + "' treeNode" + consts.id.INPUT + " >");
+			var inputObj = $("#" + node.tId + consts.id.INPUT);
+			inputObj.attr("value", node[nameKey]);
+			if (setting.edit.editNameSelectAll) {
+				tools.inputSelect(inputObj);
+			} else {
+				tools.inputFocus(inputObj);
+			}
+
+			inputObj.bind('blur', function(event) {
+				if (!view.editNodeBlur) {
+					view.cancelCurEditNode(setting);
+				}
+			}).bind('keydown', function(event) {
+				if (event.keyCode=="13") {
+					view.editNodeBlur = true;
+					view.cancelCurEditNode(setting, null, true);
+				} else if (event.keyCode=="27") {
+					view.cancelCurEditNode(setting, node[nameKey]);
+				}
+			}).bind('click', function(event) {
+				return false;
+			}).bind('dblclick', function(event) {
+				return false;
+			});
+
+			$("#" + node.tId + consts.id.A).addClass(consts.node.CURSELECTED_EDIT);
+			root.curEditInput = inputObj;
+			root.noSelection = false;
+			root.curEditNode = node;
+		},
+		moveNode: function(setting, targetNode, node, moveType, animateFlag, isSilent) {
+			var root = data.getRoot(setting),
+			childKey = setting.data.key.children;
+			if (targetNode == node) return;
+			if (setting.data.keep.leaf && targetNode && !targetNode.isParent && moveType == consts.move.TYPE_INNER) return;
+			var oldParentNode = (node.parentTId ? node.getParentNode(): root),
+			targetNodeIsRoot = (targetNode === null || targetNode == root);
+			if (targetNodeIsRoot && targetNode === null) targetNode = root;
+			if (targetNodeIsRoot) moveType = consts.move.TYPE_INNER;
+			var targetParentNode = (targetNode.parentTId ? targetNode.getParentNode() : root);
+
+			if (moveType != consts.move.TYPE_PREV && moveType != consts.move.TYPE_NEXT) {
+				moveType = consts.move.TYPE_INNER;
+			}
+			
+			if (moveType == consts.move.TYPE_INNER) {
+				if (targetNodeIsRoot) {
+					//parentTId of root node is null
+					node.parentTId = null;
+				} else {
+					if (!targetNode.isParent) {
+						targetNode.isParent = true;
+						targetNode.open = !!targetNode.open;
+						view.setNodeLineIcos(setting, targetNode);
+					}
+					node.parentTId = targetNode.tId;
+				}
+			}
+
+			//move node Dom
+			var targetObj, target_ulObj;
+			if (targetNodeIsRoot) {
+				targetObj = setting.treeObj;
+				target_ulObj = targetObj;
+			} else {
+				if (!isSilent && moveType == consts.move.TYPE_INNER) {
+					view.expandCollapseNode(setting, targetNode, true, false);
+				} else if (!isSilent) {
+					view.expandCollapseNode(setting, targetNode.getParentNode(), true, false);
+				}
+				targetObj = $("#" + targetNode.tId);
+				target_ulObj = $("#" + targetNode.tId + consts.id.UL);
+				if (!!targetObj.get(0) && !target_ulObj.get(0)) {
+					var ulstr = [];
+					view.makeUlHtml(setting, targetNode, ulstr, '');
+					targetObj.append(ulstr.join(''));
+				}
+				target_ulObj = $("#" + targetNode.tId + consts.id.UL);
+			}
+			var nodeDom = $("#" + node.tId);
+			if (!nodeDom.get(0)) {
+				nodeDom = view.appendNodes(setting, node.level, [node], null, false, true).join('');
+			} else if (!targetObj.get(0)) {
+				nodeDom.remove();
+			}
+			if (target_ulObj.get(0) && moveType == consts.move.TYPE_INNER) {
+				target_ulObj.append(nodeDom);
+			} else if (targetObj.get(0) && moveType == consts.move.TYPE_PREV) {
+				targetObj.before(nodeDom);
+			} else if (targetObj.get(0) && moveType == consts.move.TYPE_NEXT) {
+				targetObj.after(nodeDom);
+			}
+
+			//repair the data after move
+			var i,l,
+			tmpSrcIndex = -1,
+			tmpTargetIndex = 0,
+			oldNeighbor = null,
+			newNeighbor = null,
+			oldLevel = node.level;
+			if (node.isFirstNode) {
+				tmpSrcIndex = 0;
+				if (oldParentNode[childKey].length > 1 ) {
+					oldNeighbor = oldParentNode[childKey][1];
+					oldNeighbor.isFirstNode = true;
+				}
+			} else if (node.isLastNode) {
+				tmpSrcIndex = oldParentNode[childKey].length -1;
+				oldNeighbor = oldParentNode[childKey][tmpSrcIndex - 1];
+				oldNeighbor.isLastNode = true;
+			} else {
+				for (i = 0, l = oldParentNode[childKey].length; i < l; i++) {
+					if (oldParentNode[childKey][i].tId == node.tId) {
+						tmpSrcIndex = i;
+						break;
+					}
+				}
+			}
+			if (tmpSrcIndex >= 0) {
+				oldParentNode[childKey].splice(tmpSrcIndex, 1);
+			}
+			if (moveType != consts.move.TYPE_INNER) {
+				for (i = 0, l = targetParentNode[childKey].length; i < l; i++) {
+					if (targetParentNode[childKey][i].tId == targetNode.tId) tmpTargetIndex = i;
+				}
+			}
+			if (moveType == consts.move.TYPE_INNER) {
+				if (!targetNode[childKey]) targetNode[childKey] = new Array();
+				if (targetNode[childKey].length > 0) {
+					newNeighbor = targetNode[childKey][targetNode[childKey].length - 1];
+					newNeighbor.isLastNode = false;
+				}
+				targetNode[childKey].splice(targetNode[childKey].length, 0, node);
+				node.isLastNode = true;
+				node.isFirstNode = (targetNode[childKey].length == 1);
+			} else if (targetNode.isFirstNode && moveType == consts.move.TYPE_PREV) {
+				targetParentNode[childKey].splice(tmpTargetIndex, 0, node);
+				newNeighbor = targetNode;
+				newNeighbor.isFirstNode = false;
+				node.parentTId = targetNode.parentTId;
+				node.isFirstNode = true;
+				node.isLastNode = false;
+
+			} else if (targetNode.isLastNode && moveType == consts.move.TYPE_NEXT) {
+				targetParentNode[childKey].splice(tmpTargetIndex + 1, 0, node);
+				newNeighbor = targetNode;
+				newNeighbor.isLastNode = false;
+				node.parentTId = targetNode.parentTId;
+				node.isFirstNode = false;
+				node.isLastNode = true;
+
+			} else {
+				if (moveType == consts.move.TYPE_PREV) {
+					targetParentNode[childKey].splice(tmpTargetIndex, 0, node);
+				} else {
+					targetParentNode[childKey].splice(tmpTargetIndex + 1, 0, node);
+				}
+				node.parentTId = targetNode.parentTId;
+				node.isFirstNode = false;
+				node.isLastNode = false;
+			}
+			data.fixPIdKeyValue(setting, node);
+			data.setSonNodeLevel(setting, node.getParentNode(), node);
+
+			//repair node what been moved
+			view.setNodeLineIcos(setting, node);
+			view.repairNodeLevelClass(setting, node, oldLevel)
+
+			//repair node's old parentNode dom
+			if (!setting.data.keep.parent && oldParentNode[childKey].length < 1) {
+				//old parentNode has no child nodes
+				oldParentNode.isParent = false;
+				oldParentNode.open = false;
+				var tmp_ulObj = $("#" + oldParentNode.tId + consts.id.UL),
+				tmp_switchObj = $("#" + oldParentNode.tId + consts.id.SWITCH),
+				tmp_icoObj = $("#" + oldParentNode.tId + consts.id.ICON);
+				view.replaceSwitchClass(oldParentNode, tmp_switchObj, consts.folder.DOCU);
+				view.replaceIcoClass(oldParentNode, tmp_icoObj, consts.folder.DOCU);
+				tmp_ulObj.css("display", "none");
+
+			} else if (oldNeighbor) {
+				//old neigbor node
+				view.setNodeLineIcos(setting, oldNeighbor);
+			}
+
+			//new neigbor node
+			if (newNeighbor) {
+				view.setNodeLineIcos(setting, newNeighbor);
+			}
+
+			//repair checkbox / radio
+			if (!!setting.check && setting.check.enable && view.repairChkClass) {
+				view.repairChkClass(setting, oldParentNode);
+				view.repairParentChkClassWithSelf(setting, oldParentNode);
+				if (oldParentNode != node.parent)
+					view.repairParentChkClassWithSelf(setting, node);
+			}
+
+			//expand parents after move
+			if (!isSilent) {
+				view.expandCollapseParentNode(setting, node.getParentNode(), true, animateFlag);
+			}
+		},
+		removeEditBtn: function(node) {
+			$("#" + node.tId + consts.id.EDIT).unbind().remove();
+		},
+		removeRemoveBtn: function(node) {
+			$("#" + node.tId + consts.id.REMOVE).unbind().remove();
+		},
+		removeTreeDom: function(setting, node) {
+			node.isHover = false;
+			view.removeEditBtn(node);
+			view.removeRemoveBtn(node);
+			tools.apply(setting.view.removeHoverDom, [setting.treeId, node]);
+		},
+		repairNodeLevelClass: function(setting, node, oldLevel) {
+			if (oldLevel === node.level) return;
+			var liObj = $("#" + node.tId),
+			aObj = $("#" + node.tId + consts.id.A),
+			ulObj = $("#" + node.tId + consts.id.UL),
+			oldClass = consts.className.LEVEL + oldLevel,
+			newClass = consts.className.LEVEL + node.level;
+			liObj.removeClass(oldClass);
+			liObj.addClass(newClass);
+			aObj.removeClass(oldClass);
+			aObj.addClass(newClass);
+			ulObj.removeClass(oldClass);
+			ulObj.addClass(newClass);
+		}
+	},
+
+	_z = {
+		tools: _tools,
+		view: _view,
+		event: _event,
+		data: _data
+	};
+	$.extend(true, $.fn.zTree.consts, _consts);
+	$.extend(true, $.fn.zTree._z, _z);
+
+	var zt = $.fn.zTree,
+	tools = zt._z.tools,
+	consts = zt.consts,
+	view = zt._z.view,
+	data = zt._z.data,
+	event = zt._z.event;
+
+	data.exSetting(_setting);
+	data.addInitBind(_bindEvent);
+	data.addInitUnBind(_unbindEvent);
+	data.addInitCache(_initCache);
+	data.addInitNode(_initNode);
+	data.addInitProxy(_eventProxy);
+	data.addInitRoot(_initRoot);
+	data.addZTreeTools(_zTreeTools);
+
+	var _cancelPreSelectedNode = view.cancelPreSelectedNode;
+	view.cancelPreSelectedNode = function (setting, node) {
+		var list = data.getRoot(setting).curSelectedList;
+		for (var i=0, j=list.length; i<j; i++) {
+			if (!node || node === list[i]) {
+				view.removeTreeDom(setting, list[i]);
+				if (node) break;
+			}
+		}
+		if (_cancelPreSelectedNode) _cancelPreSelectedNode.apply(view, arguments);
+	}
+
+	var _createNodes = view.createNodes;
+	view.createNodes = function(setting, level, nodes, parentNode) {
+		if (_createNodes) {
+			_createNodes.apply(view, arguments);
+		}
+		if (!nodes) return;
+		if (view.repairParentChkClassWithSelf) {
+			view.repairParentChkClassWithSelf(setting, parentNode);
+		}
+	}
+
+	var _makeNodeUrl = view.makeNodeUrl;
+	view.makeNodeUrl = function(setting, node) {
+		return setting.edit.enable ? null : (_makeNodeUrl.apply(view, arguments));
+	}
+
+	var _removeNode = view.removeNode;
+	view.removeNode = function(setting, node) {
+		var root = data.getRoot(setting);
+		if (root.curEditNode === node) root.curEditNode = null;
+		if (_removeNode) {
+			_removeNode.apply(view, arguments);
+		}
+	}
+
+	var _selectNode = view.selectNode;
+	view.selectNode = function(setting, node, addFlag) {
+		var root = data.getRoot(setting);
+		if (data.isSelectedNode(setting, node) && root.curEditNode == node && node.editNameFlag) {
+			return false;
+		}
+		if (_selectNode) _selectNode.apply(view, arguments);
+		view.addHoverDom(setting, node);
+		return true;
+	}
+
+	var _uCanDo = tools.uCanDo;
+	tools.uCanDo = function(setting, e) {
+		var root = data.getRoot(setting);
+		if (e && (tools.eqs(e.type, "mouseover") || tools.eqs(e.type, "mouseout") || tools.eqs(e.type, "mousedown") || tools.eqs(e.type, "mouseup"))) {
+			return true;
+		}
+		return (!root.curEditNode) && (_uCanDo ? _uCanDo.apply(view, arguments) : true);
+	}
+})(jQuery);
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/js/jquery.ztree.exhide-3.5.js b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/js/jquery.ztree.exhide-3.5.js
new file mode 100644
index 0000000..98c2d97
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/js/jquery.ztree.exhide-3.5.js
@@ -0,0 +1,366 @@
+/*
+ * JQuery zTree exHideNodes 3.5.12
+ * http://zTree.me/
+ *
+ * Copyright (c) 2010 Hunter.z
+ *
+ * Licensed same as jquery - MIT License
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ * email: hunter.z@263.net
+ * Date: 2013-03-11
+ */
+(function($){
+	//default init node of exLib
+	var _initNode = function(setting, level, n, parentNode, isFirstNode, isLastNode, openFlag) {
+		if (typeof n.isHidden == "string") n.isHidden = tools.eqs(n.isHidden, "true");
+		n.isHidden = !!n.isHidden;
+		data.initHideForExCheck(setting, n);
+	},
+	//add dom for check
+	_beforeA = function(setting, node, html) {},
+	//update zTreeObj, add method of exLib
+	_zTreeTools = function(setting, zTreeTools) {
+		zTreeTools.showNodes = function(nodes, options) {
+			view.showNodes(setting, nodes, options);
+		}
+		zTreeTools.showNode = function(node, options) {
+			if (!node) {
+				return;
+			}
+			view.showNodes(setting, [node], options);
+		}
+		zTreeTools.hideNodes = function(nodes, options) {
+			view.hideNodes(setting, nodes, options);
+		}
+		zTreeTools.hideNode = function(node, options) {
+			if (!node) {
+				return;
+			}
+			view.hideNodes(setting, [node], options);
+		}
+
+		var _checkNode = zTreeTools.checkNode;
+		if (_checkNode) {
+			zTreeTools.checkNode = function(node, checked, checkTypeFlag, callbackFlag) {
+				if (!!node && !!node.isHidden) {
+					return;
+				}
+				_checkNode.apply(zTreeTools, arguments);
+			}
+		}
+	},
+	//method of operate data
+	_data = {
+		initHideForExCheck: function(setting, n) {
+			if (n.isHidden && setting.check && setting.check.enable) {
+				if(typeof n._nocheck == "undefined") {
+					n._nocheck = !!n.nocheck
+					n.nocheck = true;
+				}
+				n.check_Child_State = -1;
+				if (view.repairParentChkClassWithSelf) {
+					view.repairParentChkClassWithSelf(setting, n);
+				}
+			}
+		},
+		initShowForExCheck: function(setting, n) {
+			if (!n.isHidden && setting.check && setting.check.enable) {
+				if(typeof n._nocheck != "undefined") {
+					n.nocheck = n._nocheck;
+					delete n._nocheck;
+				}
+				if (view.setChkClass) {
+					var checkObj = $("#" + n.tId + consts.id.CHECK);
+					view.setChkClass(setting, checkObj, n);
+				}
+				if (view.repairParentChkClassWithSelf) {
+					view.repairParentChkClassWithSelf(setting, n);
+				}
+			}
+		}
+	},
+	//method of operate ztree dom
+	_view = {
+		clearOldFirstNode: function(setting, node) {
+			var n = node.getNextNode();
+			while(!!n){
+				if (n.isFirstNode) {
+					n.isFirstNode = false;
+					view.setNodeLineIcos(setting, n);
+					break;
+				}
+				if (n.isLastNode) {
+					break;
+				}
+				n = n.getNextNode();
+			}
+		},
+		clearOldLastNode: function(setting, node) {
+			var n = node.getPreNode();
+			while(!!n){
+				if (n.isLastNode) {
+					n.isLastNode = false;
+					view.setNodeLineIcos(setting, n);
+					break;
+				}
+				if (n.isFirstNode) {
+					break;
+				}
+				n = n.getPreNode();
+			}
+		},
+		makeDOMNodeMainBefore: function(html, setting, node) {
+			html.push("<li ", (node.isHidden ? "style='display:none;' " : ""), "id='", node.tId, "' class='", consts.className.LEVEL, node.level,"' tabindex='0' hidefocus='true' treenode>");
+		},
+		showNode: function(setting, node, options) {
+			node.isHidden = false;
+			data.initShowForExCheck(setting, node);
+			$("#" + node.tId).show();
+		},
+		showNodes: function(setting, nodes, options) {
+			if (!nodes || nodes.length == 0) {
+				return;
+			}
+			var pList = {}, i, j;
+			for (i=0, j=nodes.length; i<j; i++) {
+				var n = nodes[i];
+				if (!pList[n.parentTId]) {
+					var pn = n.getParentNode();
+					pList[n.parentTId] = (pn === null) ? data.getRoot(setting) : n.getParentNode();
+				}
+				view.showNode(setting, n, options);
+			}
+			for (var tId in pList) {
+				var children = pList[tId][setting.data.key.children];
+				view.setFirstNodeForShow(setting, children);
+				view.setLastNodeForShow(setting, children);
+			}
+		},
+		hideNode: function(setting, node, options) {
+			node.isHidden = true;
+			node.isFirstNode = false;
+			node.isLastNode = false;
+			data.initHideForExCheck(setting, node);
+			view.cancelPreSelectedNode(setting, node);
+			$("#" + node.tId).hide();
+		},
+		hideNodes: function(setting, nodes, options) {
+			if (!nodes || nodes.length == 0) {
+				return;
+			}
+			var pList = {}, i, j;
+			for (i=0, j=nodes.length; i<j; i++) {
+				var n = nodes[i];
+				if ((n.isFirstNode || n.isLastNode) && !pList[n.parentTId]) {
+					var pn = n.getParentNode();
+					pList[n.parentTId] = (pn === null) ? data.getRoot(setting) : n.getParentNode();
+				}
+				view.hideNode(setting, n, options);
+			}
+			for (var tId in pList) {
+				var children = pList[tId][setting.data.key.children];
+				view.setFirstNodeForHide(setting, children);
+				view.setLastNodeForHide(setting, children);
+			}
+		},
+		setFirstNode: function(setting, parentNode) {
+			var childKey = setting.data.key.children, childLength = parentNode[childKey].length;
+			if (childLength > 0 && !parentNode[childKey][0].isHidden) {
+				parentNode[childKey][0].isFirstNode = true;
+			} else if (childLength > 0) {
+				view.setFirstNodeForHide(setting, parentNode[childKey]);
+			}
+		},
+		setLastNode: function(setting, parentNode) {
+			var childKey = setting.data.key.children, childLength = parentNode[childKey].length;
+			if (childLength > 0 && !parentNode[childKey][0].isHidden) {
+				parentNode[childKey][childLength - 1].isLastNode = true;
+			} else if (childLength > 0) {
+				view.setLastNodeForHide(setting, parentNode[childKey]);
+			}
+		},
+		setFirstNodeForHide: function(setting, nodes) {
+			var n,i,j;
+			for (i=0, j=nodes.length; i<j; i++) {
+				n = nodes[i];
+				if (n.isFirstNode) {
+					break;
+				}
+				if (!n.isHidden && !n.isFirstNode) {
+					n.isFirstNode = true;
+					view.setNodeLineIcos(setting, n);
+					break;
+				} else {
+					n = null;
+				}
+			}
+			return n;
+		},
+		setFirstNodeForShow: function(setting, nodes) {
+			var n,i,j, first, old;
+			for(i=0, j=nodes.length; i<j; i++) {
+				n = nodes[i];
+				if (!first && !n.isHidden && n.isFirstNode) {
+					first = n;
+					break;
+				} else if (!first && !n.isHidden && !n.isFirstNode) {
+					n.isFirstNode = true;
+					first = n;
+					view.setNodeLineIcos(setting, n);
+				} else if (first && n.isFirstNode) {
+					n.isFirstNode = false;
+					old = n;
+					view.setNodeLineIcos(setting, n);
+					break;
+				} else {
+					n = null;
+				}
+			}
+			return {"new":first, "old":old};
+		},
+		setLastNodeForHide: function(setting, nodes) {
+			var n,i;
+			for (i=nodes.length-1; i>=0; i--) {
+				n = nodes[i];
+				if (n.isLastNode) {
+					break;
+				}
+				if (!n.isHidden && !n.isLastNode) {
+					n.isLastNode = true;
+					view.setNodeLineIcos(setting, n);
+					break;
+				} else {
+					n = null;
+				}
+			}
+			return n;
+		},
+		setLastNodeForShow: function(setting, nodes) {
+			var n,i,j, last, old;
+			for (i=nodes.length-1; i>=0; i--) {
+				n = nodes[i];
+				if (!last && !n.isHidden && n.isLastNode) {
+					last = n;
+					break;
+				} else if (!last && !n.isHidden && !n.isLastNode) {
+					n.isLastNode = true;
+					last = n;
+					view.setNodeLineIcos(setting, n);
+				} else if (last && n.isLastNode) {
+					n.isLastNode = false;
+					old = n;
+					view.setNodeLineIcos(setting, n);
+					break;
+				} else {
+					n = null;
+				}
+			}
+			return {"new":last, "old":old};
+		}
+	},
+
+	_z = {
+		view: _view,
+		data: _data
+	};
+	$.extend(true, $.fn.zTree._z, _z);
+
+	var zt = $.fn.zTree,
+	tools = zt._z.tools,
+	consts = zt.consts,
+	view = zt._z.view,
+	data = zt._z.data,
+	event = zt._z.event;
+
+	data.addInitNode(_initNode);
+	data.addBeforeA(_beforeA);
+	data.addZTreeTools(_zTreeTools);
+
+//	Override method in core
+	var _dInitNode = data.initNode;
+	data.tmpHideParent = -1;
+	data.initNode = function(setting, level, node, parentNode, isFirstNode, isLastNode, openFlag) {
+		if (data.tmpHideParent !== parentNode) {
+			data.tmpHideParent = parentNode;
+			var tmpPNode = (parentNode) ? parentNode: data.getRoot(setting),
+			children = tmpPNode[setting.data.key.children];
+			data.tmpHideFirstNode = view.setFirstNodeForHide(setting, children);
+			data.tmpHideLastNode = view.setLastNodeForHide(setting, children);
+			view.setNodeLineIcos(setting, data.tmpHideFirstNode);
+			view.setNodeLineIcos(setting, data.tmpHideLastNode);
+		}
+		isFirstNode = (data.tmpHideFirstNode === node);
+		isLastNode = (data.tmpHideLastNode === node);
+		if (_dInitNode) _dInitNode.apply(data, arguments);
+		if (isLastNode) {
+			view.clearOldLastNode(setting, node);
+		}
+	}
+
+	var _makeChkFlag = data.makeChkFlag;
+	if (!!_makeChkFlag) {
+		data.makeChkFlag = function(setting, node) {
+			if (!!node && !!node.isHidden) {
+				return;
+			}
+			_makeChkFlag.apply(data, arguments);
+		}
+	}
+
+	var _getTreeCheckedNodes = data.getTreeCheckedNodes;
+	if (!!_getTreeCheckedNodes) {
+		data.getTreeCheckedNodes = function(setting, nodes, checked, results) {
+			if (!!nodes && nodes.length > 0) {
+				var p = nodes[0].getParentNode();
+				if (!!p && !!p.isHidden) {
+					return [];
+				}
+			}
+			return _getTreeCheckedNodes.apply(data, arguments);
+		}
+	}
+
+	var _getTreeChangeCheckedNodes = data.getTreeChangeCheckedNodes;
+	if (!!_getTreeChangeCheckedNodes) {
+		data.getTreeChangeCheckedNodes = function(setting, nodes, results) {
+			if (!!nodes && nodes.length > 0) {
+				var p = nodes[0].getParentNode();
+				if (!!p && !!p.isHidden) {
+					return [];
+				}
+			}
+			return _getTreeChangeCheckedNodes.apply(data, arguments);
+		}
+	}
+
+	var _expandCollapseSonNode = view.expandCollapseSonNode;
+	if (!!_expandCollapseSonNode) {
+		view.expandCollapseSonNode = function(setting, node, expandFlag, animateFlag, callback) {
+			if (!!node && !!node.isHidden) {
+				return;
+			}
+			_expandCollapseSonNode.apply(view, arguments);
+		}
+	}
+
+	var _setSonNodeCheckBox = view.setSonNodeCheckBox;
+	if (!!_setSonNodeCheckBox) {
+		view.setSonNodeCheckBox = function(setting, node, value, srcNode) {
+			if (!!node && !!node.isHidden) {
+				return;
+			}
+			_setSonNodeCheckBox.apply(view, arguments);
+		}
+	}
+
+	var _repairParentChkClassWithSelf = view.repairParentChkClassWithSelf;
+	if (!!_repairParentChkClassWithSelf) {
+		view.repairParentChkClassWithSelf = function(setting, node) {
+			if (!!node && !!node.isHidden) {
+				return;
+			}
+			_repairParentChkClassWithSelf.apply(view, arguments);
+		}
+	}
+})(jQuery);
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/log v3.x.txt b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/log v3.x.txt
new file mode 100644
index 0000000..371542c
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-ztree/3.5/log v3.x.txt
@@ -0,0 +1,170 @@
+=ZTree v3.x (JQuery Tree插件) 更新日志=
+
+<font color="red">为了更好的优化及扩展zTree, 因此决定升级为v3.x,并且对之前的v2.x不兼容,会有很多结构上的修改,对此深感无奈与抱歉,请大家谅解。</font>
+<font color="red">
+
+具体修改内容可参考:
+
+   * [http://www.ztree.me/v3/api.php zTree v3.0 API 文档]
+
+   * [http://www.ztree.me/v3/demo.php#_101 zTree v3.0 Demo 演示]
+
+   * [http://www.ztree.me/v3/faq.php#_101 zTree v3.0 常见问题]
+
+</font>
+
+<font color=#041594>
+*2013.03.11* v3.5.12
+   * 【修改】由于 jquery 1.9 中移除 event.srcElement 导致的 js 报错的bug。
+   * 【修改】在异步加载模式下,使用 moveNode 方法,且 moveType != "inner" 时,也会导致 targetNode 自动加载子节点的 bug
+   * 【修改】对已经显示的节点(nochecked=true)使用 showNodes 或 showNode 方法后,导致勾选框出现的bug。
+   * 【修改】对已经隐藏的节点(nochecked=false)使用 hideNodes 或 hideNode 方法后,导致勾选框消失的bug。
+   * 【修改】getNodesByParamFuzzy 支持 大小写模糊。
+   * 【修改】className 结构,提取 _consts.className.BUTTON / LEVEL / ICO_LOADING / SWITCH,便于快速修改 css 冲突。
+     例如:与 WordPress 产生冲突后,直接修改 core 中的 "button" 和 "level" 即可。  Issue: https://github.com/zTree/zTree_v3/issues/2
+
+*2013.01.28* v3.5.02
+   * 【增加】setting.check.chkDisabledInherit 属性,用于设置 chkDisabled 在初始化时子节点是否可以继承父节点的 chkDisabled 属性
+   * 【删除】内部 noSel 方法,使用 selectstart事件 和 "-moz-user-select"样式 处理禁止 节点文字被选择的功能
+   * 【修改】不兼容 jQuery 1.9 的bug
+   * 【修改】onDrop 的触发规则,保证异步加载模式下,可以在延迟加载结束后触发,避免 onDrop 中被拖拽的节点是已经更新后的数据。
+   * 【修改】setChkDisabled 方法,增加 inheritParent, inheritChildren 参数设置是否让父子节点继承 disabled
+   * 【修改】异步加载时 拼接参数的方法,由 string 修改为 json 对象
+   * 【修正】1-2-3 3级节点时,如果 2级节点 全部设置为 nocheck 或 chkDisabled后,勾选3级节点时,1级节点的半勾选状态错误的 bug
+   * 【修改】Demo: checkbox_nocheck.html & checkbox_chkDisabled.html;
+   * 【修改】Demo: edit_super.html,增加 showRenameBtn & showRemoveBtn 的演示
+   * 【修改】Demo: asyncForAll, 将 post 修改为 get;为了避免由于 IE10 的 bug 造成的客户端 以及 服务端崩溃
+      IE10 ajax Post 无法提交参数的bug (http://bugs.jquery.com/ticket/12790)
+
+*2012.12.21* v3.5.01
+   * 【优化】clone 方法
+   * 【修正】对于初始化无 children 属性的父节点进行 reAsyncChildNodes 操作时出错的 bug
+   * 【修正】beforeRename 回调中使用 cancelEditName 方法后,再 return false 导致无法重新进行编辑的 bug
+   * 【修正】exedit 扩展包让 setting.data.key.url 失效的 bug
+   * 【修正】setting.check.autoCheckTrigger 设置为 true 时,onCheck 回调缺少 event 参数的 bug
+   * 【修正】singlepath.html Demo 中的 bug
+
+*2012.11.20* v3.5
+   * 【优化】原先的 clone 方法 (特别感谢:愚人码头)
+   * 【修改】隐藏父节点后,使用 expandAll 方法导致 父节点展开的 bug
+   * 【修改】使用 jQuery v1.7 以上时,设置 zTree 容器 ul 隐藏(visibility: hidden;)后, 调用 selectNode 导致 IE 浏览器报错 Can't move focus 的 bug
+   * 【修改】正在异步加载时,执行 destory 或 init 方法后,异步加载的节点影响新树的 bug
+   * 【修改】方法 reAsyncChildNodes 在 refresh 的时候未清空内部 cache 导致内存泄露 的 bug
+   * 【修改】批量节点拖拽到其他父节点内(inner)时,导致顺序反转 的 bug
+   * 【修改】对于 使用 html格式的 节点无法触发 双击事件 的 bug
+   * 【修改】onCheck 回调中的 event ,保证与触发事件中的 event 一致
+   * 【修改】异步加载时,在 onNodeCreated 中执行 selectNode 后,导致节点折叠的 bug
+   * 【修改】API 中 dataFilter 的参数名称 childNodes ->  responseData
+   * 【修改】API 中 iconSkin 的 举例内容
+   * 【修改】API 中 chkDisabled 的说明
+   * 【修改】Demo 中 index.html 内的 loadReady 重复绑定问题
+
+*2012.09.03* v3.4
+   * 【增加】 Demo —— OutLook 样式的左侧菜单
+   * 【增加】清空 zTree 的方法 $.fn.zTree.destory(treeId) & zTree.destory()
+
+   * 【修改】core核心文件内 _eventProxy 方法中获取 tId 的方法,提高 DOM 的灵活性
+   * 【修改】初始化时 多层父节点的 checkbox 半选状态计算错误的 bug
+   * 【修改】同时选中父、子节点后,利用 getSelectedNodes 获取选中节点并利用 removeNode 删除时报错的 bug
+   * 【修改】treeNode.chkDisabled / nocheck 属性,支持字符串格式的 "false"/"true"
+   * 【修改】异步加载模式下无法利用 server 返回 xml 并且 在 dataFilter 中继续处理的 bug
+   * 【修改】title 只允许设置为 string 类型值的问题。 修正后允许设置为 number 类型的值
+   * 【修改】zId 计数规则 & Cache 保存,减少 IE9 的 bug 造成的内存泄漏
+   * 【修改】API 页面搜索功能导致 IE 崩溃的 bug
+
+*2012.07.16* v3.3
+   * 【增加】扩展库 exhide -- 节点隐藏功能
+
+   * 【修改】getNodesByFilter 方法,添加 invokeParam 自定义参数
+   * 【修改】拖拽中测试代码未删除,导致出现黄颜色的 iframe 遮罩层的 bug
+   * 【修改】延迟加载方法 对于使用 expandAll 进行全部展开时,导致 onNodeCreated 回调 和 addDiyDom 方法触发过早的 bug
+   * 【修改】使用 moveNode 移动尚未生成 DOM 的节点时,视图会出现异常的 bug
+   * 【修改】删除节点后,相关节点的 isFirstNode 属性未重置的 bug
+   * 【修改】getPreNode(),getNextNode() 方法在对于特殊情况时计算错误的 bug
+   * 【修改】设置 title 之后,如果重新将 title 内容设置为空后,会导致无法更新 title 的 bug
+   * 【修改】针对 setting.check.chkStyle=="radio" && setting.check.radioType=="all" 的情况时,getTreeCheckedNodes方法优化,找到一个结果就 break
+   * 【修改】zTreeObj.getCheckedNodes(false) 在 radioType = "all" 时计算错误的 bug
+   * 【修改】完善 API 中 beforeDrop / onDrop 的关于 treeId 的说明
+
+*2012.05.13* v3.2
+   * 【增加】setting.data.key.url 允许修改 treeNode.url 属性
+   * 【增加】getNodesByFilter(filter, isSingle) 方法
+   * 【增加】"与其他 DOM 拖拽互动" 的 Demo (http://www.ztree.me/v3/demo.php#_511)
+   * 【增加】"异步加载模式下全部展开" 的 Demo (http://www.ztree.me/v3/demo.php#_512)
+
+   * 【修改】代码结构,将 addNodes、removeNode、removeChildNodes 方法 和 beforeRemove、onRemove 回调 转移到 core 内
+   * 【修改】IE7的环境下无子节点的父节点反复展开出现多余空行的 bug
+   * 【修改】异步加载时,如果出现网络异常等,会导致 图标显示错误的 bug
+   * 【修改】dataFilter中 return null 导致异常 的 bug
+   * 【修改】removeChildNodes 方法清空子节点后,无法正常添加节点的 bug
+   * 【修改】moveNode 后节点中的自定义元素的事件丢失的 bug
+   * 【修改】moveNode 方法中设置 isSilent = true 时,如果移动到已展开的 父节点后,出现异常的 bug
+   * 【修改】onClick/onDrag/onDrop 回调中 event 不是原始 event 的 bug
+   * 【修改】onDrop 回调中 当拖拽无效时,无法获得 treeNodes 的 bug
+   * 【修改】onDrop 无法判断拖拽是 移动还是复制的问题
+   * 【修改】未开启异步加载模式时,拖拽节点到子节点为空的父节点内时 出现异常 的 bug
+   * 【修改】拖拽过程中,反复在 父节点图标上划动时,会出现停顿的 bug
+            (需要css 结构—— button -> span.button)
+
+   * 【修改】拖拽操作时箭头 与 targetNode 背景之间的细节现实问题,便于用户拖拽时更容易区分 prev、next 和 inner 操作
+   * 【修改】拖拽操作时IE6/7 下 在 节点<a> 右侧 10px 内会导致 targetNode = root 的 bug
+   * 【修改】编辑模式下 默认的编辑按钮、删除按钮点击后,如果相应的 before 回调 return false 时会触发 onClick 回调的 bug
+
+*2012.02.14* v3.1
+   * 【增加】ajax 的参数 setting.async.contentType ,让提交参数适用于 json 数据提交 (主要适用于 .Net 的开发)。
+   * 【增加】setting.edit.editNameSelectAll, 用于设定编辑节点名称时初次显示 input 后 text 内容为全选
+   * 【修改】异步加载 规则,不再仅仅依靠父节点的子节点数来判定,增加内部属性 zAsync,保证默认状态下父节点及时无子节点也只能异步加载一次,除非使用 reAsyncChildNodes 方法强行控制异步加载。
+   * 【修改】放大浏览器后导致 界面出现多余连接线的bug (需要更新:icon 图标和 css )
+   * 【修改】在编辑状态,如果节点名超过编辑框宽度,左右键在框内不起作用的bug(IE 6 7 8 出现)
+      CSS 中 filter:alpha(opacity=80) 造成的,应该是 ie 的 bug,需要更新 css 文件
+   * 【修改】title 设置后,如果属性不存在,则默认为 title 为空,便于数据容错和用户灵活使用
+   * 【修改】editName 方法如果针对尚未展开的 父节点,会导致该父节点自动展开的 bug
+   * 【修改】title 中存在标签时导致 title 显示异常的bug(例如:蓝色字22%"'`<input/>`)
+
+*2012.01.10* v3.0
+   * 【增加】setting.check.autoCheckTrigger 默认值 false,可以设置联动选中时是否触发事件回调函数
+   * 【增加】setting.callback.beforeEditName 回调函数,以保证用户可以捕获点击编辑按钮的事件
+   * 【增加】treeNode.chkDisabled 属性,显示 checkbox 但是用户无法修改 checkbox 状态,并且该 checkbox 会影响父节点的 checkbox 的半选状态
+   * 【增加】setting.check.nocheckInherit 属性,用户设置子节点继承 nocheck 属性,用于批量初始化节点,不适用于已经显示的节点
+   * 【增加】setting.edit.drag.autoExpandTrigger 默认值 false,可以设置自动展开、折叠操作时是否触发事件回调函数
+   * 【增加】setting.view.nameIsHTML 默认值 false,允许用户对 name 设置 DOM 对象
+   * 【增加】treeNode.click 属性的说明文档
+   * 【增加】treeObj.setChkDisabled 方法用于设置 checkbox / radio disabled 状态
+   * 【增加】treeNode.halfCheck 属性,用于强制设定节点的半选状态
+
+   * 【修改】异步加载 & 编辑功能 共存时,拖拽节点 或 增加节点 导致 ie 上报错的 bug (apply 方法引起)
+   * 【修改】zTreeStyle 样式冲突
+   * 【修改】setting.data.key.title 默认值设置为 "",初始化时自动赋值为 setting.data.key.name 这样可避免希望 title 与 name 一致的用户反复设置参数
+   * 【修改】点击叶子节点的连接线会触发 expand 事件的 bug
+   * 【修改】IE 下 点击叶子节点连线会出现虚线框的 bug
+   * 【修改】updateNode 导致 checkbox 半选状态错误的 bug
+   * 【修改】checkNode 方法实现 toggle 操作, 取消 expandAll 方法的 toggle 操作
+   * 【修改】zTree 内鼠标移动会抢页面上 input 内的焦点的 bug
+   * 【修改】beforeRename / onRename 的触发方式——即使名称内容未改变也会触发,便于用户配合 beforeEditName 捕获编辑状态的结束,赋予用户更多调整规则的权利
+   * 【修改】与 easyUI 共存时无法拖拽的bug
+   * 【修改】beforeRename 在 Firefox 下如果利用 alert,会触发两次的 bug
+   * 【修改】checkNode/expandNode/removeNode 方法,默认不触发回调函数,恢复 v2.6 的默认状态,同时增加 callbackFlag 参数,设置为 true 时,可以触发回调函数
+   * 【修改】IE9下“根据参数查找节点”的Demo 报错:行14 重新声明常量属性(Demo 自身的问题,定义了history变量)
+   * 【修改】初始化 zTree 时 onNodeCreated 事件回调函数中无法 用 getZTreeObj 获取 zTree 对象的 bug
+   * 【修改】setting.edit.drag.prev / next / inner 参数,增加被拖拽的节点集合
+   * 【修改】异步加载模式下,otherParam 使用Array数组会出错的 bug。例如: ["id", "1", "name", "test"]
+   * 【修改】FireFox 下多棵树拖拽异常的 bug
+   * 【修改】exedit 中调用 excheck库的方法时没有进行容错处理,导致如果只加入 exedit 而没有 excheck的时候,会出现 js 错误
+   * 【修改】显示 checkbox 的 zTree 在编辑模式下,移动节点不会更新父节点半选状态的 bug
+   * 【修改】treeNode.childs --> children; treeObject.removeChilds --> removeChildNodes; setting.data.key.childs --> children(英文不好惹的祸!抱歉了!)
+   * 【修改】onRemove 回调中得到的 treeNode 还可以查找 preNode、nextNode 的bug。 修正后,getPreNode 和 getNextNode 都返回 null; 为了便于查找父节点,getParentNode 仍保留
+   * 【修改】简单数据模式下,如果 id 与 pId 的值相同会导致该节点无法正常加载的 bug
+   * 【修改】移动或删除中间节点会导致最后一个节点连接线图标变小的 bug
+
+*2011.09.05* v3.0 beta
+   * 【修改】zTree 的 js 代码架构全面修改,并且拆分
+   * 【修改】zTree 的 css 样式全面修改,对浏览器可以更好地兼容,同时解决了以前1个像素差的问题
+   * 【优化】采用延迟加载技术,一次性加载大数据量的节点性能飞速提升
+   * 【增加】支持多节点同时选中、拖拽
+   * 【增加】checkNode、checkAllNodes 等多种方法
+   * 【增加】IE6 自动取消动画展开、折叠的功能
+   * 【修正】异步加载 & 编辑模式 能够更完美的共存
+   * 【修正】setting 配置更加合理,并且增加了若干项配置参数
+   * 【修正】treeNode 节点数据的属性更加合理,并且增加了一些方法
+   * 【修正】拖拽操作更加灵活方便,更容易制定自己的规则
+   * 【修正】其他若干修改,详细对比请参考 url:[http://www.ztree.me/v3/faq.php#_101 zTree v3.0 常见问题]
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jsonview/jquery.jsonview.css b/ruoyi-admin/src/main/resources/static/ajax/libs/jsonview/jquery.jsonview.css
new file mode 100644
index 0000000..e3cb8c5
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jsonview/jquery.jsonview.css
@@ -0,0 +1,50 @@
+@charset "UTF-8";
+.jsonview {
+  font-family: monospace;
+  font-size: 1.1em;
+  white-space: pre-wrap; }
+  .jsonview .prop {
+    font-weight: bold; }
+  .jsonview .null {
+    color: red; }
+  .jsonview .bool {
+    color: blue; }
+  .jsonview .num {
+    color: blue; }
+  .jsonview .string {
+    color: green;
+    white-space: pre-wrap; }
+    .jsonview .string.multiline {
+      display: inline-block;
+      vertical-align: text-top; }
+  .jsonview .collapser {
+    position: absolute;
+    left: -1em;
+    cursor: pointer; }
+  .jsonview .collapsible {
+    transition: height 1.2s;
+    transition: width 1.2s; }
+  .jsonview .collapsible.collapsed {
+    height: .8em;
+    width: 1em;
+    display: inline-block;
+    overflow: hidden;
+    margin: 0; }
+  .jsonview .collapsible.collapsed:before {
+    content: "…";
+    width: 1em;
+    margin-left: .2em; }
+  .jsonview .collapser.collapsed {
+    transform: rotate(0deg); }
+  .jsonview .q {
+    display: inline-block;
+    width: 0px;
+    color: transparent; }
+  .jsonview li {
+    position: relative; }
+  .jsonview ul {
+    list-style: none;
+    margin: 0 0 0 2em;
+    padding: 0; }
+  .jsonview h1 {
+    font-size: 1.2em; }
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jsonview/jquery.jsonview.js b/ruoyi-admin/src/main/resources/static/ajax/libs/jsonview/jquery.jsonview.js
new file mode 100644
index 0000000..18738b4
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jsonview/jquery.jsonview.js
@@ -0,0 +1,250 @@
+(function(jQuery) {
+  var $, Collapser, JSONFormatter, JSONView;
+  JSONFormatter = (function() {
+    function JSONFormatter(options) {
+      if (options == null) {
+        options = {};
+      }
+      this.options = options;
+    }
+
+    JSONFormatter.prototype.htmlEncode = function(html) {
+      if (html !== null) {
+        return html.toString().replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
+      } else {
+        return '';
+      }
+    };
+
+    JSONFormatter.prototype.jsString = function(s) {
+      s = JSON.stringify(s).slice(1, -1);
+      return this.htmlEncode(s);
+    };
+
+    JSONFormatter.prototype.decorateWithSpan = function(value, className) {
+      return "<span class=\"" + className + "\">" + (this.htmlEncode(value)) + "</span>";
+    };
+
+    JSONFormatter.prototype.valueToHTML = function(value, level) {
+      var valueType;
+      if (level == null) {
+        level = 0;
+      }
+      valueType = Object.prototype.toString.call(value).match(/\s(.+)]/)[1].toLowerCase();
+      return this["" + valueType + "ToHTML"].call(this, value, level);
+    };
+
+    JSONFormatter.prototype.nullToHTML = function(value) {
+      return this.decorateWithSpan('null', 'null');
+    };
+
+    JSONFormatter.prototype.numberToHTML = function(value) {
+      return this.decorateWithSpan(value, 'num');
+    };
+
+    JSONFormatter.prototype.stringToHTML = function(value) {
+      var multilineClass, newLinePattern;
+      if (/^(http|https|file):\/\/[^\s]+$/i.test(value)) {
+        return "<a href=\"" + (this.htmlEncode(value)) + "\"><span class=\"q\">\"</span>" + (this.jsString(value)) + "<span class=\"q\">\"</span></a>";
+      } else {
+        multilineClass = '';
+        value = this.jsString(value);
+        if (this.options.nl2br) {
+          newLinePattern = /([^>\\r\\n]?)(\\r\\n|\\n\\r|\\r|\\n)/g;
+          if (newLinePattern.test(value)) {
+            multilineClass = ' multiline';
+            value = (value + '').replace(newLinePattern, '$1' + '<br />');
+          }
+        }
+        return "<span class=\"string" + multilineClass + "\">\"" + value + "\"</span>";
+      }
+    };
+
+    JSONFormatter.prototype.booleanToHTML = function(value) {
+      return this.decorateWithSpan(value, 'bool');
+    };
+
+    JSONFormatter.prototype.arrayToHTML = function(array, level) {
+      var collapsible, hasContents, index, numProps, output, value, _i, _len;
+      if (level == null) {
+        level = 0;
+      }
+      hasContents = false;
+      output = '';
+      numProps = array.length;
+      for (index = _i = 0, _len = array.length; _i < _len; index = ++_i) {
+        value = array[index];
+        hasContents = true;
+        output += '<li>' + this.valueToHTML(value, level + 1);
+        if (numProps > 1) {
+          output += ',';
+        }
+        output += '</li>';
+        numProps--;
+      }
+      if (hasContents) {
+        collapsible = level === 0 ? '' : ' collapsible';
+        return "[<ul class=\"array level" + level + collapsible + "\">" + output + "</ul>]";
+      } else {
+        return '[ ]';
+      }
+    };
+
+    JSONFormatter.prototype.objectToHTML = function(object, level) {
+      var collapsible, hasContents, numProps, output, prop, value;
+      if (level == null) {
+        level = 0;
+      }
+      hasContents = false;
+      output = '';
+      numProps = 0;
+      for (prop in object) {
+        numProps++;
+      }
+      for (prop in object) {
+        value = object[prop];
+        hasContents = true;
+        output += "<li><span class=\"prop\"><span class=\"q\">\"</span>" + (this.jsString(prop)) + "<span class=\"q\">\"</span></span>: " + (this.valueToHTML(value, level + 1));
+        if (numProps > 1) {
+          output += ',';
+        }
+        output += '</li>';
+        numProps--;
+      }
+      if (hasContents) {
+        collapsible = level === 0 ? '' : ' collapsible';
+        return "{<ul class=\"obj level" + level + collapsible + "\">" + output + "</ul>}";
+      } else {
+        return '{ }';
+      }
+    };
+
+    JSONFormatter.prototype.jsonToHTML = function(json) {
+      return "<div class=\"jsonview\">" + (this.valueToHTML(json)) + "</div>";
+    };
+
+    return JSONFormatter;
+
+  })();
+  (typeof module !== "undefined" && module !== null) && (module.exports = JSONFormatter);
+  Collapser = {
+    bindEvent: function(item, collapsed) {
+      var collapser;
+      collapser = document.createElement('div');
+      collapser.className = 'collapser';
+      collapser.innerHTML = collapsed ? '+' : '-';
+      collapser.addEventListener('click', (function(_this) {
+        return function(event) {
+          return _this.toggle(event.target);
+        };
+      })(this));
+      item.insertBefore(collapser, item.firstChild);
+      if (collapsed) {
+        return this.collapse(collapser);
+      }
+    },
+    expand: function(collapser) {
+      var ellipsis, target;
+      target = this.collapseTarget(collapser);
+      ellipsis = target.parentNode.getElementsByClassName('ellipsis')[0];
+      target.parentNode.removeChild(ellipsis);
+      target.style.display = '';
+      return collapser.innerHTML = '-';
+    },
+    collapse: function(collapser) {
+      var ellipsis, target;
+      target = this.collapseTarget(collapser);
+      target.style.display = 'none';
+      ellipsis = document.createElement('span');
+      ellipsis.className = 'ellipsis';
+      ellipsis.innerHTML = ' &hellip; ';
+      target.parentNode.insertBefore(ellipsis, target);
+      return collapser.innerHTML = '+';
+    },
+    toggle: function(collapser) {
+      var target;
+      target = this.collapseTarget(collapser);
+      if (target.style.display === 'none') {
+        return this.expand(collapser);
+      } else {
+        return this.collapse(collapser);
+      }
+    },
+    collapseTarget: function(collapser) {
+      var target, targets;
+      targets = collapser.parentNode.getElementsByClassName('collapsible');
+      if (!targets.length) {
+        return;
+      }
+      return target = targets[0];
+    }
+  };
+  $ = jQuery;
+  JSONView = {
+    collapse: function(el) {
+      if (el.innerHTML === '-') {
+        return Collapser.collapse(el);
+      }
+    },
+    expand: function(el) {
+      if (el.innerHTML === '+') {
+        return Collapser.expand(el);
+      }
+    },
+    toggle: function(el) {
+      return Collapser.toggle(el);
+    }
+  };
+  return $.fn.JSONView = function() {
+    var args, defaultOptions, formatter, json, method, options, outputDoc;
+    args = arguments;
+    if (JSONView[args[0]] != null) {
+      method = args[0];
+      return this.each(function() {
+        var $this, level;
+        $this = $(this);
+        if (args[1] != null) {
+          level = args[1];
+          return $this.find(".jsonview .collapsible.level" + level).siblings('.collapser').each(function() {
+            return JSONView[method](this);
+          });
+        } else {
+          return $this.find('.jsonview > ul > li > .collapsible').siblings('.collapser').each(function() {
+            return JSONView[method](this);
+          });
+        }
+      });
+    } else {
+      json = args[0];
+      options = args[1] || {};
+      defaultOptions = {
+        collapsed: false,
+        nl2br: false
+      };
+      options = $.extend(defaultOptions, options);
+      formatter = new JSONFormatter({
+        nl2br: options.nl2br
+      });
+      if (Object.prototype.toString.call(json) === '[object String]') {
+        json = JSON.parse(json);
+      }
+      outputDoc = formatter.jsonToHTML(json);
+      return this.each(function() {
+        var $this, item, items, _i, _len, _results;
+        $this = $(this);
+        $this.html(outputDoc);
+        items = $this[0].getElementsByClassName('collapsible');
+        _results = [];
+        for (_i = 0, _len = items.length; _i < _len; _i++) {
+          item = items[_i];
+          if (item.parentNode.nodeName === 'LI') {
+            _results.push(Collapser.bindEvent(item.parentNode, options.collapsed));
+          } else {
+            _results.push(void 0);
+          }
+        }
+        return _results;
+      });
+    }
+  };
+})(jQuery);
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/layer/css/layer.css b/ruoyi-admin/src/main/resources/static/ajax/libs/layer/css/layer.css
new file mode 100644
index 0000000..0803bbe
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/layer/css/layer.css
@@ -0,0 +1,286 @@
+html #layuicss-layer{display: none; position: absolute; width: 1989px;}
+
+/* common */
+.layui-layer-shade, .layui-layer{position:fixed; _position:absolute; pointer-events: auto;}
+.layui-layer-shade{top:0; left:0; width:100%; height:100%; _height:expression(document.body.offsetHeight+"px");}
+.layui-layer{-webkit-overflow-scrolling: touch;}
+.layui-layer{top:150px; left: 0; margin:0; padding:0; background-color:#fff; -webkit-background-clip: content; border-radius: 2px; box-shadow: 1px 1px 50px rgba(0,0,0,.3);}
+.layui-layer-close{position:absolute;}
+.layui-layer-content{position:relative;}
+.layui-layer-border{border: 1px solid #B2B2B2; border: 1px solid rgba(0,0,0,.1); box-shadow: 1px 1px 5px rgba(0,0,0,.2);}
+.layui-layer-setwin span,
+.layui-layer-btn a{display: inline-block; vertical-align: middle; *display: inline; *zoom:1; }
+
+.layui-layer-move{display: none; position: fixed; *position: absolute; left: 0px; top: 0px; width: 100%; height: 100%; cursor: move; opacity: 0; filter:alpha(opacity=0); background-color: #fff; z-index: 2147483647;}
+.layui-layer-resize{position: absolute; width: 15px; height: 15px; right: 0; bottom: 0; cursor: se-resize;}
+
+/* 动画 */
+.layer-anim{-webkit-animation-fill-mode: both; animation-fill-mode: both; -webkit-animation-duration:.3s; animation-duration:.3s;}
+
+@-webkit-keyframes layer-bounceIn { /* 默认 */
+	0% {opacity: 0; -webkit-transform: scale(.5); transform: scale(.5)}
+	100% {opacity: 1; -webkit-transform: scale(1); transform: scale(1)}
+}
+@keyframes layer-bounceIn {
+	0% {opacity: 0; -webkit-transform: scale(.5); -ms-transform: scale(.5); transform: scale(.5)}
+	100% {opacity: 1; -webkit-transform: scale(1); -ms-transform: scale(1); transform: scale(1)}
+}
+.layer-anim-00{-webkit-animation-name: layer-bounceIn;animation-name: layer-bounceIn}
+
+@-webkit-keyframes layer-zoomInDown{0%{opacity:0;-webkit-transform:scale(.1) translateY(-2000px);transform:scale(.1) translateY(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateY(60px);transform:scale(.475) translateY(60px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}@keyframes layer-zoomInDown{0%{opacity:0;-webkit-transform:scale(.1) translateY(-2000px);-ms-transform:scale(.1) translateY(-2000px);transform:scale(.1) translateY(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateY(60px);-ms-transform:scale(.475) translateY(60px);transform:scale(.475) translateY(60px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}.layer-anim-01{-webkit-animation-name:layer-zoomInDown;animation-name:layer-zoomInDown}
+
+@-webkit-keyframes layer-fadeInUpBig{0%{opacity:0;-webkit-transform:translateY(2000px);transform:translateY(2000px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes layer-fadeInUpBig{0%{opacity:0;-webkit-transform:translateY(2000px);-ms-transform:translateY(2000px);transform:translateY(2000px)}100%{opacity:1;-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}.layer-anim-02{-webkit-animation-name:layer-fadeInUpBig;animation-name:layer-fadeInUpBig}
+
+@-webkit-keyframes layer-zoomInLeft{0%{opacity:0;-webkit-transform:scale(.1) translateX(-2000px);transform:scale(.1) translateX(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateX(48px);transform:scale(.475) translateX(48px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}@keyframes layer-zoomInLeft{0%{opacity:0;-webkit-transform:scale(.1) translateX(-2000px);-ms-transform:scale(.1) translateX(-2000px);transform:scale(.1) translateX(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateX(48px);-ms-transform:scale(.475) translateX(48px);transform:scale(.475) translateX(48px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}.layer-anim-03{-webkit-animation-name:layer-zoomInLeft;animation-name:layer-zoomInLeft}
+
+@-webkit-keyframes layer-rollIn{0%{opacity:0;-webkit-transform:translateX(-100%) rotate(-120deg);transform:translateX(-100%) rotate(-120deg)}100%{opacity:1;-webkit-transform:translateX(0px) rotate(0deg);transform:translateX(0px) rotate(0deg)}}@keyframes layer-rollIn{0%{opacity:0;-webkit-transform:translateX(-100%) rotate(-120deg);-ms-transform:translateX(-100%) rotate(-120deg);transform:translateX(-100%) rotate(-120deg)}100%{opacity:1;-webkit-transform:translateX(0px) rotate(0deg);-ms-transform:translateX(0px) rotate(0deg);transform:translateX(0px) rotate(0deg)}}.layer-anim-04{-webkit-animation-name:layer-rollIn;animation-name:layer-rollIn}
+
+@keyframes layer-fadeIn{0%{opacity:0}100%{opacity:1}}.layer-anim-05{-webkit-animation-name:layer-fadeIn;animation-name:layer-fadeIn}
+
+@-webkit-keyframes layer-shake{0%,100%{-webkit-transform:translateX(0);transform:translateX(0)}10%,30%,50%,70%,90%{-webkit-transform:translateX(-10px);transform:translateX(-10px)}20%,40%,60%,80%{-webkit-transform:translateX(10px);transform:translateX(10px)}}@keyframes layer-shake{0%,100%{-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}10%,30%,50%,70%,90%{-webkit-transform:translateX(-10px);-ms-transform:translateX(-10px);transform:translateX(-10px)}20%,40%,60%,80%{-webkit-transform:translateX(10px);-ms-transform:translateX(10px);transform:translateX(10px)}}.layer-anim-06{-webkit-animation-name:layer-shake;animation-name:layer-shake}@-webkit-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}
+
+/* 从上往下 */
+@keyframes layer-slide-down {
+  from {
+    transform: translate3d(0,-100%,0);
+  } to {
+    transform: translate3d(0,0,0);
+  }
+}
+@keyframes layer-slide-down-out {
+  from {
+    transform: translate3d(0,0,0);
+  } to {
+    transform: translate3d(0,-100%,0);
+  }
+}
+.layer-anim-slide-down{animation-name: layer-slide-down}
+.layer-anim-slide-down-out{animation-name: layer-slide-down-out}
+
+/* 从右往左 */
+@keyframes layer-slide-left {
+  from {
+    transform: translate3d(100%,0,0);
+  } to {
+    transform: translate3d(0,0,0);
+  }
+}
+@keyframes layer-slide-left-out {
+  from {
+    transform: translate3d(0,0,0);
+  } to {
+    transform: translate3d(100%,0,0);
+  }
+}
+.layer-anim-slide-left{animation-name: layer-slide-left}
+.layer-anim-slide-left-out{animation-name: layer-slide-left-out}
+
+/* 从下往上 */
+@keyframes layer-slide-up {
+  from {
+    transform: translate3d(0,100%,0);
+  } to {
+    transform: translate3d(0,0,0);
+  }
+}
+@keyframes layer-slide-up-out {
+  from {
+    transform: translate3d(0,0,0);
+  } to {
+    transform: translate3d(0,100%,0);
+  }
+}
+.layer-anim-slide-up{animation-name: layer-slide-up}
+.layer-anim-slide-up-out{animation-name: layer-slide-up-out}
+
+/* 从左往右 */
+@keyframes layer-slide-right {
+  from {
+    transform: translate3d(-100%,0,0);
+  } to {
+    transform: translate3d(0,0,0);
+  }
+}
+@keyframes layer-slide-right-out {
+  from {
+    transform: translate3d(0,0,0);
+  } to {
+    transform: translate3d(-100%,0,0);
+  }
+}
+.layer-anim-slide-right{animation-name: layer-slide-right;}
+.layer-anim-slide-right-out{animation-name: layer-slide-right-out;}
+
+
+
+/* 标题栏 */
+.layui-layer-title{padding: 0 81px 0 16px; height: 50px; line-height: 50px; border-bottom:1px solid #F0F0F0; font-size: 14px; color:#333; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; border-radius: 2px 2px 0 0;}
+.layui-layer-setwin{position:absolute; right: 15px; *right:0; top: 16px; font-size:0; line-height: initial;}
+.layui-layer-setwin span{position:relative; width: 16px; height: 16px; line-height: 18px; margin-left: 10px; text-align: center; font-size: 16px; cursor: pointer; color: #000; _overflow: hidden; box-sizing: border-box;}
+.layui-layer-setwin .layui-layer-min:before{content: ''; position: absolute; width: 12px; border-bottom: 1px solid #2E2D3C; left: 50%; top: 50%; margin: -0.5px 0 0 -6px; cursor: pointer; _overflow:hidden;}
+.layui-layer-setwin .layui-layer-min:hover:before{background-color: #2D93CA}
+.layui-layer-setwin .layui-layer-max:hover:before,
+.layui-layer-setwin .layui-layer-max:hover:after{border-color: #2D93CA;}
+.layui-layer-setwin .layui-layer-min:hover:before{background-color: #2D93CA}
+.layui-layer-setwin .layui-layer-maxmin:before,
+.layui-layer-setwin .layui-layer-maxmin:after{width: 7px; height: 7px; margin: -3px 0 0 -3px; background-color: #fff;}
+.layui-layer-setwin .layui-layer-maxmin:after{z-index: 0; margin: -5px 0 0 -1px;}
+.layui-layer-setwin .layui-layer-close{cursor: pointer;}
+.layui-layer-setwin .layui-layer-close:hover{opacity:0.7;}
+.layui-layer-setwin .layui-layer-close2{position:absolute; right: -28px; top: -28px; color: #fff; background-color: #787878; padding: 3px; width: 16px; height: 20px; font-size: 16px; font-weight: bolder; border-radius: 50%; margin-left: 0; *right:-18px; _display:none;}
+.layui-layer-setwin .layui-layer-close2:hover{opacity: unset; background-color: #3888f6;}
+
+/* 按钮栏 */
+.layui-layer-btn{text-align: right; padding: 0 15px 12px; pointer-events: auto; user-select: none; -webkit-user-select: none;}
+.layui-layer-btn a{height: 30px; line-height: 30px; margin: 5px 5px 0; padding: 0 16px; border: 1px solid #dedede; background-color: #fff; color: #333; border-radius: 2px; font-weight: 400; cursor: pointer; text-decoration: none; box-sizing: border-box;}
+.layui-layer-btn a:hover{opacity: 0.9; text-decoration: none;}
+.layui-layer-btn a:active{opacity: 0.8;}
+.layui-layer-btn .layui-layer-btn0{border-color: transparent; background-color: #1E9FFF; color:#fff;}
+.layui-layer-btn-l{text-align: left;}
+.layui-layer-btn-c{text-align: center;}
+
+/* 定制化 */
+.layui-layer-dialog{min-width: 240px;}
+.layui-layer-dialog .layui-layer-content{position: relative; padding: 16px; line-height: 24px; word-break: break-all; overflow:hidden; font-size:14px; overflow-x: hidden; overflow-y:auto;}
+.layui-layer-dialog .layui-layer-content .layui-layer-face{position: absolute; top: 18px; left: 16px; color: #959595; font-size: 32px; _left: -40px;}
+.layui-layer-dialog .layui-layer-content .layui-icon-tips{color: #F39B12;}
+.layui-layer-dialog .layui-layer-content .layui-icon-success{color: #16b777;}
+.layui-layer-dialog .layui-layer-content .layui-icon-error{top: 19px; color: #FF5722;}
+.layui-layer-dialog .layui-layer-content .layui-icon-question{color: #FFB800;}
+.layui-layer-dialog .layui-layer-content .layui-icon-lock{color: #787878;}
+.layui-layer-dialog .layui-layer-content .layui-icon-face-cry{color: #FF5722;}
+.layui-layer-dialog .layui-layer-content .layui-icon-face-smile{color: #16b777;}
+
+.layui-layer-rim{border:6px solid #8D8D8D; border:6px solid rgba(0,0,0,.3); border-radius:5px; box-shadow: none;}
+.layui-layer-msg{min-width:180px; border:1px solid #D3D4D3; box-shadow: none;}
+.layui-layer-hui{min-width:100px;  background-color: #000; filter:alpha(opacity=60); background-color: rgba(0,0,0,0.6); color: #fff; border:none;}
+.layui-layer-hui .layui-layer-close{color: #fff;}
+.layui-layer-hui .layui-layer-content{padding: 11px 24px; text-align: center;}
+.layui-layer-dialog .layui-layer-padding{padding: 18px 24px 18px 58px; text-align: left;}
+.layui-layer-page .layui-layer-content{position:relative; overflow:auto;}
+.layui-layer-page .layui-layer-btn,.layui-layer-iframe .layui-layer-btn{padding-top:10px;}
+.layui-layer-nobg{background:none;}
+.layui-layer-iframe iframe{display: block; width: 100%;}
+
+.layui-layer-loading{border-radius:100%; background:none;  box-shadow:none;  border:none;}
+.layui-layer-loading .layui-layer-content{width: 76px; height: 38px; line-height: 38px; text-align: center;}
+.layui-layer-loading-icon{font-size: 38px; color: #959595;}
+.layui-layer-loading2{text-align: center;}
+.layui-layer-loading-2{position: relative; height: 38px;}
+.layui-layer-loading-2:before,
+.layui-layer-loading-2:after{content: ''; position: absolute; left: 50%; top: 50%; width: 38px; height: 38px; margin: -19px 0 0 -19px; border-radius: 50%; border: 3px solid #d2d2d2; box-sizing: border-box;}
+.layui-layer-loading-2:after{border-color: transparent; border-left-color: #1E9FFF;}
+
+
+.layui-layer-tips{background: none; box-shadow:none; border:none;}
+.layui-layer-tips .layui-layer-content{position: relative; line-height: 22px; min-width: 12px; padding: 8px 15px; font-size: 12px; _float:left; border-radius: 2px; box-shadow: 1px 1px 3px rgba(0,0,0,.2); background-color: #000; color: #fff;}
+.layui-layer-tips .layui-layer-close{right:-2px; top:-1px;}
+.layui-layer-tips i.layui-layer-TipsG{ position:absolute;  width:0; height:0; border-width:8px; border-color:transparent; border-style:dashed; *overflow:hidden;}
+.layui-layer-tips i.layui-layer-TipsT, .layui-layer-tips i.layui-layer-TipsB{left:5px; border-right-style:solid; border-right-color: #000;}
+.layui-layer-tips i.layui-layer-TipsT{bottom:-8px;}
+.layui-layer-tips i.layui-layer-TipsB{top:-8px;}
+.layui-layer-tips i.layui-layer-TipsR, .layui-layer-tips i.layui-layer-TipsL{top: 5px; border-bottom-style:solid; border-bottom-color: #000;}
+.layui-layer-tips i.layui-layer-TipsR{left:-8px;}
+.layui-layer-tips i.layui-layer-TipsL{right:-8px;}
+
+/* 内置 skin */
+.layui-layer-lan .layui-layer-title{background:#4476A7; color:#fff; border: none;}
+.layui-layer-lan .layui-layer-btn{padding: 5px 10px 10px; border-top:1px solid #E9E7E7}
+.layui-layer-lan .layui-layer-btn a{background: #fff; border-color: #E9E7E7; color: #333;}
+.layui-layer-lan .layui-layer-btn .layui-layer-btn1{background:#C9C5C5;}
+.layui-layer-molv .layui-layer-title{background: #009f95; color:#fff; border: none;}
+.layui-layer-molv .layui-layer-btn a{background: #009f95; border-color: #009f95;}
+.layui-layer-molv .layui-layer-btn .layui-layer-btn1{background:#92B8B1;}
+.layui-layer-lan .layui-layer-setwin .layui-icon,
+.layui-layer-molv .layui-layer-setwin .layui-icon{color: #fff;}
+
+/* Windows 10 风格主题  */
+.layui-layer-win10{border: 1px solid #aaa; box-shadow: 1px 1px 6px rgba(0,0,0,.3); border-radius: none;}
+.layui-layer-win10 .layui-layer-title{height: 32px; line-height: 32px; padding-left: 8px; border-bottom: none; font-size: 12px;}
+.layui-layer-win10 .layui-layer-setwin{right: 0; top: 0;}
+.layui-layer-win10 .layui-layer-setwin span{margin-left: 0; width: 32px; height: 32px; padding: 8px;}
+.layui-layer-win10.layui-layer-page .layui-layer-setwin span{width: 38px;}
+.layui-layer-win10 .layui-layer-setwin span:hover{background-color: #E5E5E5;}
+.layui-layer-win10 .layui-layer-setwin span.layui-icon-close:hover{background-color: #E81123; color: #fff;}
+.layui-layer-win10.layui-layer-dialog .layui-layer-content{padding: 8px 16px 32px; color: #0033BC;}
+.layui-layer-win10.layui-layer-dialog .layui-layer-padding{padding-top: 18px; padding-left: 58px;}
+.layui-layer-win10 .layui-layer-btn{padding: 5px 5px 10px; border-top:1px solid #DFDFDF; background-color: #F0F0F0;}
+.layui-layer-win10 .layui-layer-btn a{height: 20px; line-height: 18px; background-color: #E1E1E1; border-color: #ADADAD; color: #000; font-size: 12px; transition: all .3s;}
+.layui-layer-win10 .layui-layer-btn a:hover{border-color: #2A8EDD; background-color: #E5F1FB;}
+.layui-layer-win10 .layui-layer-btn .layui-layer-btn0{border-color: #0078D7;}
+
+
+/**
+ 
+ @Name: layer拓展样式
+ 
+ */
+
+/* prompt模式 */
+.layui-layer-prompt .layui-layer-input{display: block; width: 260px; height: 36px; margin: 0 auto; line-height: 30px; padding-left: 10px; border: 1px solid #e6e6e6; color: #333;}
+.layui-layer-prompt textarea.layui-layer-input{width: 300px; height: 100px; line-height: 20px; padding: 6px 10px;}
+.layui-layer-prompt .layui-layer-content{padding: 16px;}
+.layui-layer-prompt .layui-layer-btn{padding-top: 0;}
+
+/* tab模式 */
+.layui-layer-tab{box-shadow:1px 1px 50px rgba(0,0,0,.4);}
+.layui-layer-tab .layui-layer-title{padding-left:0; overflow: visible;}
+.layui-layer-tab .layui-layer-title span{position:relative; display: inline-block; vertical-align: top; border-left: 1px solid transparent; border-right: 1px solid transparent; min-width:80px; max-width: 300px; padding:0 16px; text-align:center; cursor:default; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; cursor: pointer;}
+.layui-layer-tab .layui-layer-title span.layui-this{height: 51px; border-left-color: #eee; border-right-color: #eee; background-color: #fff; z-index: 10;}
+.layui-layer-tab .layui-layer-title span:first-child{border-left-color: transparent;}
+.layui-layer-tabmain{line-height:24px; clear: both;}
+.layui-layer-tabmain .layui-layer-tabli{display:none;}
+.layui-layer-tabmain .layui-layer-tabli.layui-this{display: block;}
+
+/* photos */
+.layui-layer-photos{background: none; box-shadow: none;}
+.layui-layer-photos .layui-layer-content{overflow: visible; text-align: center;}
+.layui-layer-photos .layer-layer-photos-main img{position: relative; width:100%; display: inline-block; *display:inline; *zoom:1; vertical-align:top;}
+.layui-layer-photos-prev,
+.layui-layer-photos-next{position: fixed; top: 50%; width: 52px; height: 52px; line-height: 52px; margin-top: -26px; cursor: pointer; font-size: 52px; color: #717171;}
+.layui-layer-photos-prev{left: 32px;}
+.layui-layer-photos-next{right: 32px;}
+.layui-layer-photos-prev:hover,
+.layui-layer-photos-next:hover{color: #959595;}
+
+.layui-layer-photos-toolbar{position: fixed; left: 0; right: 0; bottom: 0; width: 100%; height: 52px; line-height: 52px; background-color: #000\9; filter: Alpha(opacity=60); background-color: rgba(0,0,0,.32); color: #fff; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; font-size:0;}
+.layui-layer-photos-toolbar > *{display:inline-block; vertical-align: top; padding: 0 16px; font-size: 12px; color: #fff; *display:inline; *zoom: 1;}
+.layui-layer-photos-toolbar *{font-size: 12px;}
+.layui-layer-photos-header{top: 0; bottom: auto;}
+.layui-layer-photos-header > span{cursor: pointer;}
+.layui-layer-photos-header > span:hover{background-color: rgba(51,51,51,.32);}
+.layui-layer-photos-header .layui-icon{font-size: 18px;}
+.layui-layer-photos-footer > h3{max-width: 65%; text-overflow: ellipsis; overflow: hidden; white-space: nowrap;}
+.layui-layer-photos-footer a:hover{text-decoration: underline;}
+.layui-layer-photos-footer em{font-style: normal;}
+
+
+/* 关闭动画 */
+@-webkit-keyframes layer-bounceOut {
+  100% {opacity: 0; -webkit-transform: scale(.7); transform: scale(.7)}
+  30% {-webkit-transform: scale(1.05); transform: scale(1.05)}
+  0% {-webkit-transform: scale(1); transform: scale(1);}
+}
+@keyframes layer-bounceOut {
+  100% {opacity: 0; -webkit-transform: scale(.7); -ms-transform: scale(.7); transform: scale(.7);}
+  30% {-webkit-transform: scale(1.05); -ms-transform: scale(1.05); transform: scale(1.05);}
+  0% {-webkit-transform: scale(1); -ms-transform: scale(1);transform: scale(1);}
+}
+.layer-anim-close{-webkit-animation-name: layer-bounceOut; animation-name: layer-bounceOut; -webkit-animation-fill-mode: both; animation-fill-mode: both; -webkit-animation-duration:.2s; animation-duration:.2s;}
+
+@media screen and (max-width: 1100px) {
+  .layui-layer-iframe{overflow-y: auto; -webkit-overflow-scrolling: touch;}
+}
+
+/* 其他样式 */
+.layui-layer-lan[type=dialog] {min-width: 280px}
+.layui-layer-lan .layui-layer-title {background: #4476a7; color: #fff; border: 0}
+.layui-layer-lan .layui-layer-btn {padding: 5px 10px 10px; text-align: right; border-top: 1px solid #e9e7e7}
+.layui-layer-lan .layui-layer-btn a {background: #fff; border-color: #e9e7e7; color: #333}
+.layui-layer-lan .layui-layer-btn .layui-layer-btn1 {background: #c9c5c5}
+.layui-layer-gray[type=dialog] {min-width: 280px}
+.layui-layer-gray .layui-layer-title {background: #f8f8f8; color: #333; border: 0}
+.layui-layer-gray .layui-layer-btn {padding: 5px 10px 10px; text-align: right; border-top: 1px solid #e9e7e7}
+.layui-layer-gray .layui-layer-btn a {background: #fff; border-color: #e9e7e7; color: #333}
+.layui-layer-gray .layui-layer-btn .layui-layer-btn1 {background: #c9c5c5}
+.layui-layer-tab .layui-layer-content {width: 100%}
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/layer/layer.min.js b/ruoyi-admin/src/main/resources/static/ajax/libs/layer/layer.min.js
new file mode 100644
index 0000000..594ebf7
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/layer/layer.min.js
@@ -0,0 +1,2 @@
+/*! layer-v3.7.0 Web 通用弹出层组件 MIT License */
+!function(window,undefined){var isLayui=window.layui&&layui.define;var $;var win;var ready={getPath:function(){var jsPath=document.currentScript?document.currentScript.src:function(){var js=document.scripts;var last=js.length-1;var src;for(var i=last;i>0;i--){if(js[i].readyState==="interactive"){src=js[i].src;break}}return src||js[last].src}();var GLOBAL=window.LAYUI_GLOBAL||{};return GLOBAL.layer_dir||jsPath.substring(0,jsPath.lastIndexOf("/")+1)}(),config:{removeFocus:true},end:{},events:{resize:{}},minStackIndex:0,minStackArr:[],btn:["&#x786E;&#x5B9A;","&#x53D6;&#x6D88;"],type:["dialog","page","iframe","loading","tips"],getStyle:function(node,name){var style=node.currentStyle?node.currentStyle:window.getComputedStyle(node,null);return style[style.getPropertyValue?"getPropertyValue":"getAttribute"](name)},link:function(href,fn,cssname){if(!layer.path){return}var head=document.getElementsByTagName("head")[0];var link=document.createElement("link");if(typeof fn==="string"){cssname=fn}var app=(cssname||href).replace(/\.|\//g,"");var id="layuicss-"+app;var STATUS_NAME="creating";var timeout=0;link.rel="stylesheet";link.href=layer.path+href;link.id=id;if(!document.getElementById(id)){head.appendChild(link)}if(typeof fn!=="function"){return}(function poll(status){var delay=100;var getLinkElem=document.getElementById(id);if(++timeout>10*1000/delay){return window.console&&console.error(app+".css: Invalid")}if(parseInt(ready.getStyle(getLinkElem,"width"))===1989){if(status===STATUS_NAME){getLinkElem.removeAttribute("lay-status")}getLinkElem.getAttribute("lay-status")===STATUS_NAME?setTimeout(poll,delay):fn()}else{getLinkElem.setAttribute("lay-status",STATUS_NAME);setTimeout(function(){poll(STATUS_NAME)},delay)}}())}};var layer={v:"3.7.0",ie:function(){var agent=navigator.userAgent.toLowerCase();return(!!window.ActiveXObject||"ActiveXObject" in window)?((agent.match(/msie\s(\d+)/)||[])[1]||"11"):false}(),index:(window.layer&&window.layer.v)?100000:0,path:ready.getPath,config:function(options,fn){options=options||{};layer.cache=ready.config=$.extend({},ready.config,options);layer.path=ready.config.path||layer.path;typeof options.extend==="string"&&(options.extend=[options.extend]);if(ready.config.path){layer.ready()}if(!options.extend){return this}ready.link("theme/"+options.extend);return this},ready:function(callback){var cssname="layer";var ver="";var path=(isLayui?"modules/":"css/")+"layer.css?v="+layer.v+ver;isLayui?(layui["layui.all"]?(typeof callback==="function"&&callback()):layui.addcss(path,callback,cssname)):ready.link(path,callback,cssname);return this},alert:function(content,options,yes){var type=typeof options==="function";if(type){yes=options}return layer.open($.extend({content:content,yes:yes},type?{}:options))},confirm:function(content,options,yes,cancel){var type=typeof options==="function";if(type){cancel=yes;yes=options}return layer.open($.extend({content:content,btn:ready.btn,yes:yes,btn2:cancel},type?{}:options))},msg:function(content,options,end){var type=typeof options==="function",rskin=ready.config.skin;var skin=(rskin?rskin+" "+rskin+"-msg":"")||"layui-layer-msg";var anim=doms.anim.length-1;if(type){end=options}return layer.open($.extend({content:content,time:3000,shade:false,skin:skin,title:false,closeBtn:false,btn:false,resize:false,end:end,removeFocus:false},(type&&!ready.config.skin)?{skin:skin+" layui-layer-hui",anim:anim}:function(){options=options||{};if(options.icon===-1||options.icon===undefined&&!ready.config.skin){options.skin=skin+" "+(options.skin||"layui-layer-hui")}return options}()))},load:function(icon,options){return layer.open($.extend({type:3,icon:icon||0,resize:false,shade:0.01,removeFocus:false},options))},tips:function(content,follow,options){return layer.open($.extend({type:4,content:[content,follow],closeBtn:false,time:3000,shade:false,resize:false,fixed:false,maxWidth:260,removeFocus:false},options))}};var Class=function(setings){var that=this,creat=function(){that.creat()};that.index=++layer.index;that.config.maxWidth=$(win).width()-15*2;that.config=$.extend({},that.config,ready.config,setings);document.body?creat():setTimeout(function(){creat()},30)};Class.pt=Class.prototype;var doms=["layui-layer",".layui-layer-title",".layui-layer-main",".layui-layer-dialog","layui-layer-iframe","layui-layer-content","layui-layer-btn","layui-layer-close"];doms.anim={0:"layer-anim-00",1:"layer-anim-01",2:"layer-anim-02",3:"layer-anim-03",4:"layer-anim-04",5:"layer-anim-05",6:"layer-anim-06",slideDown:"layer-anim-slide-down",slideLeft:"layer-anim-slide-left",slideUp:"layer-anim-slide-up",slideRight:"layer-anim-slide-right"};doms.SHADE="layui-layer-shade";doms.MOVE="layui-layer-move";Class.pt.config={type:0,shade:0.3,fixed:true,move:doms[1],title:"&#x4FE1;&#x606F;",offset:"auto",area:"auto",closeBtn:1,icon:-1,time:0,zIndex:19891014,maxWidth:360,anim:0,isOutAnim:true,minStack:true,moveType:1,resize:true,scrollbar:true,tips:2};Class.pt.vessel=function(conType,callback){var that=this,times=that.index,config=that.config;var zIndex=config.zIndex+times,titype=typeof config.title==="object";var ismax=config.maxmin&&(config.type===1||config.type===2);var titleHTML=(config.title?'<div class="layui-layer-title" style="'+(titype?config.title[1]:"")+'">'+(titype?config.title[0]:config.title)+"</div>":"");config.zIndex=zIndex;callback([config.shade?('<div class="'+doms.SHADE+'" id="'+doms.SHADE+times+'" times="'+times+'" style="'+("z-index:"+(zIndex-1)+"; ")+'"></div>'):"",'<div class="'+doms[0]+(" layui-layer-"+ready.type[config.type])+(((config.type==0||config.type==2)&&!config.shade)?" layui-layer-border":"")+" "+(config.skin||"")+'" id="'+doms[0]+times+'" type="'+ready.type[config.type]+'" times="'+times+'" showtime="'+config.time+'" conType="'+(conType?"object":"string")+'" style="z-index: '+zIndex+"; width:"+config.area[0]+";height:"+config.area[1]+";position:"+(config.fixed?"fixed;":"absolute;")+'">'+(conType&&config.type!=2?"":titleHTML)+"<div"+(config.id?' id="'+config.id+'"':"")+' class="layui-layer-content'+((config.type==0&&config.icon!==-1)?" layui-layer-padding":"")+(config.type==3?" layui-layer-loading"+config.icon:"")+'">'+function(){var face=["layui-icon-tips","layui-icon-success","layui-icon-error","layui-icon-question","layui-icon-lock","layui-icon-face-cry","layui-icon-face-smile"];var additFaceClass;var animClass="layui-anim layui-anim-rotate layui-anim-loop";if(config.type==0&&config.icon!==-1){if(config.icon==16){additFaceClass="layui-icon layui-icon-loading "+animClass}return'<i class="layui-layer-face layui-icon '+(additFaceClass||face[config.icon]||face[0])+'"></i>'}if(config.type==3){var type=["layui-icon-loading","layui-icon-loading-1"];if(config.icon==2){return'<div class="layui-layer-loading-2 '+animClass+'"></div>'}return'<i class="layui-layer-loading-icon layui-icon '+(type[config.icon]||type[0])+" "+animClass+'"></i>'}return""}()+(config.type==1&&conType?"":(config.content||""))+"</div>"+'<div class="layui-layer-setwin">'+function(){var arr=[];if(ismax){arr.push('<span class="layui-layer-min"></span>');arr.push('<span class="layui-layer-max"></span>')}if(config.closeBtn){arr.push('<span class="layui-icon layui-icon-close '+[doms[7],doms[7]+(config.title?config.closeBtn:(config.type==4?"1":"2"))].join(" ")+'"></span>')}return arr.join("")}()+"</div>"+(config.btn?function(){var button="";typeof config.btn==="string"&&(config.btn=[config.btn]);for(var i=0,len=config.btn.length;i<len;i++){button+='<a class="'+doms[6]+""+i+'">'+config.btn[i]+"</a>"}return'<div class="'+function(){var className=[doms[6]];if(config.btnAlign){className.push(doms[6]+"-"+config.btnAlign)}return className.join(" ")}()+'">'+button+"</div>"}():"")+(config.resize?'<span class="layui-layer-resize"></span>':"")+"</div>"],titleHTML,$('<div class="'+doms.MOVE+'" id="'+doms.MOVE+'"></div>'));return that};Class.pt.creat=function(){var that=this;var config=that.config;var times=that.index,nodeIndex;var content=config.content;var conType=typeof content==="object";var body=$("body");if(config.id&&$("."+doms[0]).find("#"+config.id)[0]){return(function(){var layero=$("#"+config.id).closest("."+doms[0]);var index=layero.attr("times");var options=layero.data("config");var elemShade=$("#"+doms.SHADE+index);var maxminStatus=layero.data("maxminStatus")||{};if(maxminStatus==="min"){layer.restore(index)}else{if(options.hideOnClose){elemShade.show();layero.show()}}})()}if(config.removeFocus){document.activeElement.blur()}if(typeof config.area==="string"){config.area=config.area==="auto"?["",""]:[config.area,""]}if(config.shift){config.anim=config.shift}if(layer.ie==6){config.fixed=false}switch(config.type){case 0:config.btn=("btn" in config)?config.btn:ready.btn[0];layer.closeAll("dialog");break;case 2:var content=config.content=conType?config.content:[config.content||"","auto"];config.content='<iframe scrolling="'+(config.content[1]||"auto")+'" allowtransparency="true" id="'+doms[4]+""+times+'" name="'+doms[4]+""+times+'" onload="this.className=\'\';" class="layui-layer-load" frameborder="0" src="'+config.content[0]+'"></iframe>';break;case 3:delete config.title;delete config.closeBtn;config.icon===-1&&(config.icon===0);layer.closeAll("loading");break;case 4:conType||(config.content=[config.content,"body"]);config.follow=config.content[1];config.content=config.content[0]+'<i class="layui-layer-TipsG"></i>';delete config.title;config.tips=typeof config.tips==="object"?config.tips:[config.tips,true];config.tipsMore||layer.closeAll("tips");break}that.vessel(conType,function(html,titleHTML,moveElem){body.append(html[0]);conType?function(){(config.type==2||config.type==4)?function(){$("body").append(html[1])}():function(){if(!content.parents("."+doms[0])[0]){content.data("display",content.css("display")).show().addClass("layui-layer-wrap").wrap(html[1]);$("#"+doms[0]+times).find("."+doms[5]).before(titleHTML)}}()}():body.append(html[1]);$("#"+doms.MOVE)[0]||body.append(ready.moveElem=moveElem);that.layero=$("#"+doms[0]+times);that.shadeo=$("#"+doms.SHADE+times);config.scrollbar||ready.setScrollbar(times)}).auto(times);that.shadeo.css({"background-color":config.shade[1]||"#000","opacity":config.shade[0]||config.shade});config.type==2&&layer.ie==6&&that.layero.find("iframe").attr("src",content[0]);config.type==4?that.tips():function(){that.offset();parseInt(ready.getStyle(document.getElementById(doms.MOVE),"z-index"))||function(){that.layero.css("visibility","hidden");layer.ready(function(){that.offset();that.layero.css("visibility","visible")})}()}();if(config.fixed){if(!ready.events.resize[that.index]){ready.events.resize[that.index]=function(){that.resize()};win.on("resize",ready.events.resize[that.index])}}config.time<=0||setTimeout(function(){layer.close(that.index)},config.time);that.move().callback();if(doms.anim[config.anim]){var animClass="layer-anim "+doms.anim[config.anim];that.layero.addClass(animClass).one("webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend",function(){$(this).removeClass(animClass)})}that.layero.data("config",config)};Class.pt.resize=function(){var that=this;var config=that.config;that.offset();(/^\d+%$/.test(config.area[0])||/^\d+%$/.test(config.area[1]))&&that.auto(that.index);config.type==4&&that.tips()};Class.pt.auto=function(index){var that=this,config=that.config,layero=$("#"+doms[0]+index);if(config.area[0]===""&&config.maxWidth>0){if(layer.ie&&layer.ie<8&&config.btn){layero.width(layero.innerWidth())}layero.outerWidth()>config.maxWidth&&layero.width(config.maxWidth)}var area=[layero.innerWidth(),layero.innerHeight()];var titHeight=layero.find(doms[1]).outerHeight()||0;var btnHeight=layero.find("."+doms[6]).outerHeight()||0;var setHeight=function(elem){elem=layero.find(elem);elem.height(area[1]-titHeight-btnHeight-2*(parseFloat(elem.css("padding-top"))|0))};switch(config.type){case 2:setHeight("iframe");break;default:if(config.area[1]===""){if(config.maxHeight>0&&layero.outerHeight()>config.maxHeight){area[1]=config.maxHeight;setHeight("."+doms[5])}else{if(config.fixed&&area[1]>=win.height()){area[1]=win.height();setHeight("."+doms[5])}}}else{setHeight("."+doms[5])}break}return that};Class.pt.offset=function(){var that=this,config=that.config,layero=that.layero;var area=[layero.outerWidth(),layero.outerHeight()];var type=typeof config.offset==="object";that.offsetTop=(win.height()-area[1])/2;that.offsetLeft=(win.width()-area[0])/2;if(type){that.offsetTop=config.offset[0];that.offsetLeft=config.offset[1]||that.offsetLeft}else{if(config.offset!=="auto"){if(config.offset==="t"){that.offsetTop=0}else{if(config.offset==="r"){that.offsetLeft=win.width()-area[0]}else{if(config.offset==="b"){that.offsetTop=win.height()-area[1]}else{if(config.offset==="l"){that.offsetLeft=0}else{if(config.offset==="lt"){that.offsetTop=0;that.offsetLeft=0}else{if(config.offset==="lb"){that.offsetTop=win.height()-area[1];that.offsetLeft=0}else{if(config.offset==="rt"){that.offsetTop=0;that.offsetLeft=win.width()-area[0]}else{if(config.offset==="rb"){that.offsetTop=win.height()-area[1];that.offsetLeft=win.width()-area[0]}else{that.offsetTop=config.offset}}}}}}}}}}if(!config.fixed){that.offsetTop=/%$/.test(that.offsetTop)?win.height()*parseFloat(that.offsetTop)/100:parseFloat(that.offsetTop);that.offsetLeft=/%$/.test(that.offsetLeft)?win.width()*parseFloat(that.offsetLeft)/100:parseFloat(that.offsetLeft);that.offsetTop+=win.scrollTop();that.offsetLeft+=win.scrollLeft()}if(layero.data("maxminStatus")==="min"){that.offsetTop=win.height()-(layero.find(doms[1]).outerHeight()||0);that.offsetLeft=layero.css("left")}layero.css({top:that.offsetTop,left:that.offsetLeft})};Class.pt.tips=function(){var that=this,config=that.config,layero=that.layero;var layArea=[layero.outerWidth(),layero.outerHeight()],follow=$(config.follow);if(!follow[0]){follow=$("body")}var goal={width:follow.outerWidth(),height:follow.outerHeight(),top:follow.offset().top,left:follow.offset().left},tipsG=layero.find(".layui-layer-TipsG");var guide=config.tips[0];config.tips[1]||tipsG.remove();goal.autoLeft=function(){if(goal.left+layArea[0]-win.width()>0){goal.tipLeft=goal.left+goal.width-layArea[0];tipsG.css({right:12,left:"auto"})}else{goal.tipLeft=goal.left}};goal.where=[function(){goal.autoLeft();goal.tipTop=goal.top-layArea[1]-10;tipsG.removeClass("layui-layer-TipsB").addClass("layui-layer-TipsT").css("border-right-color",config.tips[1])},function(){goal.tipLeft=goal.left+goal.width+10;goal.tipTop=goal.top;tipsG.removeClass("layui-layer-TipsL").addClass("layui-layer-TipsR").css("border-bottom-color",config.tips[1])},function(){goal.autoLeft();goal.tipTop=goal.top+goal.height+10;tipsG.removeClass("layui-layer-TipsT").addClass("layui-layer-TipsB").css("border-right-color",config.tips[1])},function(){goal.tipLeft=goal.left-layArea[0]-10;goal.tipTop=goal.top;tipsG.removeClass("layui-layer-TipsR").addClass("layui-layer-TipsL").css("border-bottom-color",config.tips[1])}];goal.where[guide-1]();if(guide===1){goal.top-(win.scrollTop()+layArea[1]+8*2)<0&&goal.where[2]()}else{if(guide===2){win.width()-(goal.left+goal.width+layArea[0]+8*2)>0||goal.where[3]()}else{if(guide===3){(goal.top-win.scrollTop()+goal.height+layArea[1]+8*2)-win.height()>0&&goal.where[0]()}else{if(guide===4){layArea[0]+8*2-goal.left>0&&goal.where[1]()}}}}layero.find("."+doms[5]).css({"background-color":config.tips[1],"padding-right":(config.closeBtn?"30px":"")});layero.css({left:goal.tipLeft-(config.fixed?win.scrollLeft():0),top:goal.tipTop-(config.fixed?win.scrollTop():0)})};Class.pt.move=function(){var that=this;var config=that.config;var _DOC=$(document);var layero=that.layero;var DATA_NAME=["LAY_MOVE_DICT","LAY_RESIZE_DICT"];var moveElem=layero.find(config.move);var resizeElem=layero.find(".layui-layer-resize");if(config.move){moveElem.css("cursor","move")}moveElem.on("mousedown",function(e){if(e.button){return}var othis=$(this);var dict={};if(config.move){dict.layero=layero;dict.config=config;dict.offset=[e.clientX-parseFloat(layero.css("left")),e.clientY-parseFloat(layero.css("top"))];othis.data(DATA_NAME[0],dict);ready.eventMoveElem=othis;ready.moveElem.css("cursor","move").show()}e.preventDefault()});resizeElem.on("mousedown",function(e){var othis=$(this);var dict={};if(config.resize){dict.layero=layero;dict.config=config;dict.offset=[e.clientX,e.clientY];dict.index=that.index;dict.area=[layero.outerWidth(),layero.outerHeight()];othis.data(DATA_NAME[1],dict);ready.eventResizeElem=othis;ready.moveElem.css("cursor","se-resize").show()}e.preventDefault()});if(ready.docEvent){return that}_DOC.on("mousemove",function(e){if(ready.eventMoveElem){var dict=ready.eventMoveElem.data(DATA_NAME[0])||{},layero=dict.layero,config=dict.config;var X=e.clientX-dict.offset[0];var Y=e.clientY-dict.offset[1];var fixed=layero.css("position")==="fixed";e.preventDefault();dict.stX=fixed?0:win.scrollLeft();dict.stY=fixed?0:win.scrollTop();if(!config.moveOut){var setRig=win.width()-layero.outerWidth()+dict.stX;var setBot=win.height()-layero.outerHeight()+dict.stY;X<dict.stX&&(X=dict.stX);X>setRig&&(X=setRig);Y<dict.stY&&(Y=dict.stY);Y>setBot&&(Y=setBot)}layero.css({left:X,top:Y})}if(ready.eventResizeElem){var dict=ready.eventResizeElem.data(DATA_NAME[1])||{};var config=dict.config;var X=e.clientX-dict.offset[0];var Y=e.clientY-dict.offset[1];e.preventDefault();layer.style(dict.index,{width:dict.area[0]+X,height:dict.area[1]+Y});config.resizing&&config.resizing(dict.layero)}}).on("mouseup",function(e){if(ready.eventMoveElem){var dict=ready.eventMoveElem.data(DATA_NAME[0])||{};var config=dict.config;ready.eventMoveElem.removeData(DATA_NAME[0]);delete ready.eventMoveElem;ready.moveElem.hide();config.moveEnd&&config.moveEnd(dict.layero)}if(ready.eventResizeElem){ready.eventResizeElem.removeData(DATA_NAME[1]);delete ready.eventResizeElem;ready.moveElem.hide()}});ready.docEvent=true;return that};Class.pt.callback=function(){var that=this,layero=that.layero,config=that.config;that.openLayer();if(config.success){if(config.type==2){layero.find("iframe").on("load",function(){config.success(layero,that.index,that)})}else{config.success(layero,that.index,that)}}layer.ie==6&&that.IE6(layero);layero.find("."+doms[6]).children("a").on("click",function(){var index=$(this).index();if(index===0){if(config.yes){config.yes(that.index,layero,that)}else{if(config["btn1"]){config["btn1"](that.index,layero,that)}else{layer.close(that.index)}}}else{var close=config["btn"+(index+1)]&&config["btn"+(index+1)](that.index,layero,that);close===false||layer.close(that.index)}});function cancel(){var close=config.cancel&&config.cancel(that.index,layero,that);close===false||layer.close(that.index)}layero.find("."+doms[7]).on("click",cancel);if(config.shadeClose){that.shadeo.on("click",function(){layer.close(that.index)})}layero.find(".layui-layer-min").on("click",function(){var min=config.min&&config.min(layero,that.index,that);min===false||layer.min(that.index,config)});layero.find(".layui-layer-max").on("click",function(){if($(this).hasClass("layui-layer-maxmin")){layer.restore(that.index);config.restore&&config.restore(layero,that.index,that)}else{layer.full(that.index,config);setTimeout(function(){config.full&&config.full(layero,that.index,that)},100)}});config.end&&(ready.end[that.index]=config.end)};ready.reselect=function(){$.each($("select"),function(index,value){var sthis=$(this);if(!sthis.parents("."+doms[0])[0]){(sthis.attr("layer")==1&&$("."+doms[0]).length<1)&&sthis.removeAttr("layer").show()}sthis=null})};Class.pt.IE6=function(layero){$("select").each(function(index,value){var sthis=$(this);if(!sthis.parents("."+doms[0])[0]){sthis.css("display")==="none"||sthis.attr({"layer":"1"}).hide()}sthis=null})};Class.pt.openLayer=function(){var that=this;layer.zIndex=that.config.zIndex;layer.setTop=function(layero){var setZindex=function(){layer.zIndex++;layero.css("z-index",layer.zIndex+1)};layer.zIndex=parseInt(layero[0].style.zIndex);layero.on("mousedown",setZindex);return layer.zIndex}};ready.record=function(layero){if(!layero[0]){return window.console&&console.error("index error")}var area=[layero[0].style.width||layero.width(),layero[0].style.height||layero.height(),layero.position().top,layero.position().left+parseFloat(layero.css("margin-left"))];layero.find(".layui-layer-max").addClass("layui-layer-maxmin");layero.attr({area:area})};ready.setScrollbar=function(index){doms.html.css("overflow","hidden").attr("layer-full",index)};ready.restScrollbar=function(index){if(doms.html.attr("layer-full")==index){doms.html[0].style[doms.html[0].style.removeProperty?"removeProperty":"removeAttribute"]("overflow");doms.html.removeAttr("layer-full")}};window.layer=layer;layer.getChildFrame=function(selector,index){index=index||$("."+doms[4]).attr("times");return $("#"+doms[0]+index).find("iframe").contents().find(selector)};layer.getFrameIndex=function(name){return $("#"+name).parents("."+doms[4]).attr("times")};layer.iframeAuto=function(index){if(!index){return}var heg=layer.getChildFrame("html",index).outerHeight();var layero=$("#"+doms[0]+index);var titHeight=layero.find(doms[1]).outerHeight()||0;var btnHeight=layero.find("."+doms[6]).outerHeight()||0;layero.css({height:heg+titHeight+btnHeight});layero.find("iframe").css({height:heg})};layer.iframeSrc=function(index,url){$("#"+doms[0]+index).find("iframe").attr("src",url)};layer.style=function(index,options,limit){var layero=$("#"+doms[0]+index);var contElem=layero.find(".layui-layer-content");var type=layero.attr("type");var titHeight=layero.find(doms[1]).outerHeight()||0;var btnHeight=layero.find("."+doms[6]).outerHeight()||0;var minLeft=layero.attr("minLeft");if(type===ready.type[3]||type===ready.type[4]){return}if(!limit){if(parseFloat(options.width)<=260){options.width=260}if(parseFloat(options.height)-titHeight-btnHeight<=64){options.height=64+titHeight+btnHeight}}layero.css(options);btnHeight=layero.find("."+doms[6]).outerHeight()||0;if(type===ready.type[2]){layero.find("iframe").css({height:(typeof options.height==="number"?options.height:layero.height())-titHeight-btnHeight})}else{contElem.css({height:(typeof options.height==="number"?options.height:layero.height())-titHeight-btnHeight-parseFloat(contElem.css("padding-top"))-parseFloat(contElem.css("padding-bottom"))})}};layer.min=function(index,options){var layero=$("#"+doms[0]+index);var maxminStatus=layero.data("maxminStatus");if(maxminStatus==="min"){return}if(maxminStatus==="max"){layer.restore(index)}layero.data("maxminStatus","min");options=options||layero.data("config")||{};var shadeo=$("#"+doms.SHADE+index);var elemMin=layero.find(".layui-layer-min");var titHeight=layero.find(doms[1]).outerHeight()||0;var minLeft=layero.attr("minLeft");var hasMinLeft=typeof minLeft==="string";var left=hasMinLeft?minLeft:(181*ready.minStackIndex)+"px";var position=layero.css("position");var minWidth=180;var settings={width:minWidth,height:titHeight,position:"fixed",overflow:"hidden"};ready.record(layero);if(ready.minStackArr.length>0){left=ready.minStackArr[0];ready.minStackArr.shift()}if(parseFloat(left)+minWidth>win.width()){left=win.width()-minWidth-function(){ready.minStackArr.edgeIndex=ready.minStackArr.edgeIndex||0;return ready.minStackArr.edgeIndex+=3}();if(left<0){left=0}}if(options.minStack){settings.left=left;settings.top=win.height()-titHeight;hasMinLeft||ready.minStackIndex++;layero.attr("minLeft",left)}layero.attr("position",position);layer.style(index,settings,true);elemMin.hide();layero.attr("type")==="page"&&layero.find(doms[4]).hide();ready.restScrollbar(index);shadeo.hide()};layer.restore=function(index){var layero=$("#"+doms[0]+index);var shadeo=$("#"+doms.SHADE+index);var area=layero.attr("area").split(",");var type=layero.attr("type");var options=layero.data("config")||{};layero.removeData("maxminStatus");layer.style(index,{width:area[0],height:area[1],top:parseFloat(area[2]),left:parseFloat(area[3]),position:layero.attr("position"),overflow:"visible"},true);layero.find(".layui-layer-max").removeClass("layui-layer-maxmin");layero.find(".layui-layer-min").show();type==="page"&&layero.find(doms[4]).show();options.scrollbar?ready.restScrollbar(index):ready.setScrollbar(index);shadeo.show()};layer.full=function(index){var layero=$("#"+doms[0]+index);var maxminStatus=layero.data("maxminStatus");if(maxminStatus==="max"){return}if(maxminStatus==="min"){layer.restore(index)}layero.data("maxminStatus","max");ready.record(layero);if(!doms.html.attr("layer-full")){ready.setScrollbar(index)}setTimeout(function(){var isfix=layero.css("position")==="fixed";layer.style(index,{top:isfix?0:win.scrollTop(),left:isfix?0:win.scrollLeft(),width:"100%",height:"100%"},true);layero.find(".layui-layer-min").hide()},100)};layer.title=function(name,index){var title=$("#"+doms[0]+(index||layer.index)).find(doms[1]);title.html(name)};layer.close=function(index,callback){var layero=function(){var closest=$("."+doms[0]).children("#"+index).closest("."+doms[0]);return closest[0]?(index=closest.attr("times"),closest):$("#"+doms[0]+index)}();var type=layero.attr("type");var options=layero.data("config")||{};var hideOnClose=options.id&&options.hideOnClose;if(!layero[0]){return}var closeAnim=({slideDown:"layer-anim-slide-down-out",slideLeft:"layer-anim-slide-left-out",slideUp:"layer-anim-slide-up-out",slideRight:"layer-anim-slide-right-out"})[options.anim]||"layer-anim-close";var remove=function(){var WRAP="layui-layer-wrap";if(hideOnClose){layero.removeClass("layer-anim "+closeAnim);return layero.hide()}if(type===ready.type[1]&&layero.attr("conType")==="object"){layero.children(":not(."+doms[5]+")").remove();var wrap=layero.find("."+WRAP);for(var i=0;i<2;i++){wrap.unwrap()}wrap.css("display",wrap.data("display")).removeClass(WRAP)}else{if(type===ready.type[2]){try{var iframe=$("#"+doms[4]+index)[0];iframe.contentWindow.document.write("");iframe.contentWindow.close();layero.find("."+doms[5])[0].removeChild(iframe)}catch(e){}}layero[0].innerHTML="";layero.remove()}typeof ready.end[index]==="function"&&ready.end[index]();delete ready.end[index];typeof callback==="function"&&callback();if(ready.events.resize[index]){win.off("resize",ready.events.resize[index]);delete ready.events.resize[index]}};var removeShade=(function fn(){$("#"+doms.SHADE+index)[hideOnClose?"hide":"remove"]()})();if(options.isOutAnim){layero.addClass("layer-anim "+closeAnim)}layer.ie==6&&ready.reselect();ready.restScrollbar(index);if(typeof layero.attr("minLeft")==="string"){ready.minStackIndex--;ready.minStackArr.push(layero.attr("minLeft"))}if((layer.ie&&layer.ie<10)||!options.isOutAnim){remove()}else{setTimeout(function(){remove()},200)}};layer.closeAll=function(type,callback){if(typeof type==="function"){callback=type;type=null}var domsElem=$("."+doms[0]);$.each(domsElem,function(_index){var othis=$(this);var is=type?(othis.attr("type")===type):1;is&&layer.close(othis.attr("times"),_index===domsElem.length-1?callback:null);is=null});if(domsElem.length===0){typeof callback==="function"&&callback()}};layer.closeLast=function(type){type=type||"page";layer.close($(".layui-layer-"+type+":last").attr("times"))};var cache=layer.cache||{};var skin=function(type){return(cache.skin?(" "+cache.skin+" "+cache.skin+"-"+type):"")};layer.prompt=function(options,yes){var style="",placeholder="";options=options||{};if(typeof options==="function"){yes=options}if(options.area){var area=options.area;style='style="width: '+area[0]+"; height: "+area[1]+';"';delete options.area}if(options.placeholder){placeholder=' placeholder="'+options.placeholder+'"'}var prompt,content=options.formType==2?'<textarea class="layui-layer-input"'+style+placeholder+"></textarea>":function(){return'<input type="'+(options.formType==1?"password":"text")+'" class="layui-layer-input"'+placeholder+">"}();var success=options.success;delete options.success;return layer.open($.extend({type:1,btn:["&#x786E;&#x5B9A;","&#x53D6;&#x6D88;"],content:content,skin:"layui-layer-prompt"+skin("prompt"),maxWidth:win.width(),success:function(layero){prompt=layero.find(".layui-layer-input");prompt.val(options.value||"").focus();typeof success==="function"&&success(layero)},resize:false,yes:function(index){var value=prompt.val();if(value.length>(options.maxlength||500)){layer.tips("&#x6700;&#x591A;&#x8F93;&#x5165;"+(options.maxlength||500)+"&#x4E2A;&#x5B57;&#x6570;",prompt,{tips:1})}else{yes&&yes(value,index,prompt)}}},options))};layer.tab=function(options){options=options||{};var tab=options.tab||{};var THIS="layui-this";var success=options.success;delete options.success;return layer.open($.extend({type:1,skin:"layui-layer-tab"+skin("tab"),resize:false,title:function(){var len=tab.length,ii=1,str="";if(len>0){str='<span class="'+THIS+'">'+tab[0].title+"</span>";for(;ii<len;ii++){str+="<span>"+tab[ii].title+"</span>"}}return str}(),content:'<ul class="layui-layer-tabmain">'+function(){var len=tab.length,ii=1,str="";if(len>0){str='<li class="layui-layer-tabli '+THIS+'">'+(tab[0].content||"no content")+"</li>";for(;ii<len;ii++){str+='<li class="layui-layer-tabli">'+(tab[ii].content||"no  content")+"</li>"}}return str}()+"</ul>",success:function(layero){var btn=layero.find(".layui-layer-title").children();var main=layero.find(".layui-layer-tabmain").children();btn.on("mousedown",function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=true;var othis=$(this),index=othis.index();othis.addClass(THIS).siblings().removeClass(THIS);main.eq(index).show().siblings().hide();typeof options.change==="function"&&options.change(index)});typeof success==="function"&&success(layero)}},options))};layer.photos=function(options,loop,key){var dict={};options=$.extend(true,{toolbar:true,footer:true},options);if(!options.photos){return}var isObject=!(typeof options.photos==="string"||options.photos instanceof $);var photos=isObject?options.photos:{};var data=photos.data||[];var start=photos.start||0;var success=options.success;dict.imgIndex=(start|0)+1;options.img=options.img||"img";delete options.success;if(!isObject){var parent=$(options.photos),pushData=function(){data=[];parent.find(options.img).each(function(index){var othis=$(this);othis.attr("layer-index",index);data.push({alt:othis.attr("alt"),pid:othis.attr("layer-pid"),src:othis.attr("lay-src")||othis.attr("layer-src")||othis.attr("src"),thumb:othis.attr("src")})})};pushData();if(data.length===0){return}loop||parent.on("click",options.img,function(){pushData();var othis=$(this),index=othis.attr("layer-index");layer.photos($.extend(options,{photos:{start:index,data:data,tab:options.tab},full:options.full}),true)});if(!loop){return}}else{if(data.length===0){return layer.msg("&#x6CA1;&#x6709;&#x56FE;&#x7247;")}}dict.imgprev=function(key){dict.imgIndex--;if(dict.imgIndex<1){dict.imgIndex=data.length}dict.tabimg(key)};dict.imgnext=function(key,errorMsg){dict.imgIndex++;if(dict.imgIndex>data.length){dict.imgIndex=1;if(errorMsg){return}}dict.tabimg(key)};dict.keyup=function(event){if(!dict.end){var code=event.keyCode;event.preventDefault();if(code===37){dict.imgprev(true)}else{if(code===39){dict.imgnext(true)}else{if(code===27){layer.close(dict.index)}}}}};dict.tabimg=function(key){if(data.length<=1){return}photos.start=dict.imgIndex-1;layer.close(dict.index);return layer.photos(options,true,key)};dict.isNumber=function(n){return typeof n==="number"&&!isNaN(n)};dict.image={};dict.getTransform=function(opts){var transforms=[];var rotate=opts.rotate;var scaleX=opts.scaleX;var scale=opts.scale;if(dict.isNumber(rotate)&&rotate!==0){transforms.push("rotate("+rotate+"deg)")}if(dict.isNumber(scaleX)&&scaleX!==1){transforms.push("scaleX("+scaleX+")")}if(dict.isNumber(scale)){transforms.push("scale("+scale+")")}return transforms.length?transforms.join(" "):"none"};dict.event=function(layero,index,that){dict.main.find(".layui-layer-photos-prev").on("click",function(event){event.preventDefault();dict.imgprev(true)});dict.main.find(".layui-layer-photos-next").on("click",function(event){event.preventDefault();dict.imgnext(true)});$(document).on("keyup",dict.keyup);layero.off("click").on("click","*[toolbar-event]",function(){var othis=$(this);var event=othis.attr("toolbar-event");switch(event){case"rotate":dict.image.rotate=((dict.image.rotate||0)+Number(othis.attr("data-option")))%360;dict.imgElem.css({transform:dict.getTransform(dict.image)});break;case"scalex":dict.image.scaleX=dict.image.scaleX===-1?1:-1;dict.imgElem.css({transform:dict.getTransform(dict.image)});break;case"zoom":var ratio=Number(othis.attr("data-option"));dict.image.scale=(dict.image.scale||1)+ratio;if(ratio<0&&dict.image.scale<0-ratio){dict.image.scale=0-ratio}dict.imgElem.css({transform:dict.getTransform(dict.image)});break;case"reset":dict.image.scaleX=1;dict.image.scale=1;dict.image.rotate=0;dict.imgElem.css({transform:"none"});break;case"close":layer.close(index);break}that.offset();that.auto(index)});dict.main.on("mousewheel DOMMouseScroll",function(e){var delta=e.originalEvent.wheelDelta||-e.originalEvent.detail;var zoomElem=dict.main.find('[toolbar-event="zoom"]');if(delta>0){zoomElem.eq(0).trigger("click")}else{zoomElem.eq(1).trigger("click")}})};function loadImage(url,callback,error){var img=new Image();img.src=url;if(img.complete){return callback(img)}img.onload=function(){img.onload=null;callback(img)};img.onerror=function(e){img.onerror=null;error(e)}}dict.loadi=layer.load(1,{shade:"shade" in options?false:0.9,scrollbar:false});loadImage(data[start].src,function(img){layer.close(dict.loadi);var alt=data[start].alt||"";if(key){options.anim=-1}dict.index=layer.open($.extend({type:1,id:"layui-layer-photos",area:function(){var imgarea=[img.width,img.height];var winarea=[$(window).width()-100,$(window).height()-100];if(!options.full&&(imgarea[0]>winarea[0]||imgarea[1]>winarea[1])){var wh=[imgarea[0]/winarea[0],imgarea[1]/winarea[1]];if(wh[0]>wh[1]){imgarea[0]=imgarea[0]/wh[0];imgarea[1]=imgarea[1]/wh[0]}else{if(wh[0]<wh[1]){imgarea[0]=imgarea[0]/wh[1];imgarea[1]=imgarea[1]/wh[1]}}}return[imgarea[0]+"px",imgarea[1]+"px"]}(),title:false,shade:0.9,shadeClose:true,closeBtn:false,move:".layer-layer-photos-main img",moveType:1,scrollbar:false,moveOut:true,anim:5,isOutAnim:false,skin:"layui-layer-photos"+skin("photos"),content:'<div class="layer-layer-photos-main">'+'<img src="'+data[start].src+'" alt="'+alt+'" layer-pid="'+(data[start].pid||"")+'">'+function(){var arr=['<div class="layui-layer-photos-pointer">'];if(data.length>1){arr.push(['<div class="layer-layer-photos-page">','<span class="layui-icon layui-icon-left layui-layer-photos-prev"></span>','<span class="layui-icon layui-icon-right layui-layer-photos-next"></span>',"</div>"].join(""))}if(options.toolbar){arr.push(['<div class="layui-layer-photos-toolbar layui-layer-photos-header">','<span toolbar-event="rotate" data-option="90" title="旋转"><i class="layui-icon layui-icon-refresh"></i></span>','<span toolbar-event="scalex" title="变换"><i class="layui-icon layui-icon-slider"></i></span>','<span toolbar-event="zoom" data-option="0.1" title="放大"><i class="layui-icon layui-icon-add-circle"></i></span>','<span toolbar-event="zoom" data-option="-0.1" title="缩小"><i class="layui-icon layui-icon-reduce-circle"></i></span>','<span toolbar-event="reset" title="还原"><i class="layui-icon layui-icon-refresh-1"></i></span>','<span toolbar-event="close" title="关闭"><i class="layui-icon layui-icon-close"></i></span>',"</div>"].join(""))}if(options.footer){arr.push(['<div class="layui-layer-photos-toolbar layui-layer-photos-footer">',"<div>"+alt+"</div>","<em>"+dict.imgIndex+" / "+data.length+"</em>",'<a href="'+data[start].src+'" target="_blank">查看原图</a>',"</div>"].join(""))}arr.push("</div>");return arr.join("")}()+"</div>",success:function(layero,index,that){dict.main=layero.find(".layer-layer-photos-main");dict.footer=layero.find(".layui-layer-photos-footer");dict.imgElem=dict.main.children("img");dict.event(layero,index,that);options.tab&&options.tab(data[start],layero);typeof success==="function"&&success(layero)},end:function(){dict.end=true;$(document).off("keyup",dict.keyup)}},options))},function(){layer.close(dict.loadi);layer.msg("&#x5F53;&#x524D;&#x56FE;&#x7247;&#x5730;&#x5740;&#x5F02;&#x5E38;<br>&#x662F;&#x5426;&#x7EE7;&#x7EED;&#x67E5;&#x770B;&#x4E0B;&#x4E00;&#x5F20;&#xFF1F;",{time:30000,btn:["&#x4E0B;&#x4E00;&#x5F20;","&#x4E0D;&#x770B;&#x4E86;"],yes:function(){data.length>1&&dict.imgnext(true,true)}})})};ready.run=function(_$){$=_$;win=$(window);var agent=navigator.userAgent.toLowerCase();var isMobile=/android|iphone|ipod|ipad|ios/.test(agent);var _win=$(window);if(isMobile){$.each({Height:"height",Width:"width"},function(propSuffix,funcName){var propName="inner"+propSuffix;win[funcName]=function(){return propName in window?window[propName]:_win[funcName]()}})}doms.html=$("html");layer.open=function(deliver){var o=new Class(deliver);return o.index}};window.layui&&layui.define?(layer.ready(),layui.define("jquery",function(exports){layer.path=layui.cache.dir;ready.run(layui.$);window.layer=layer;exports("layer",layer)})):((typeof define==="function"&&define.amd)?define(["jquery"],function(){ready.run(window.jQuery);return layer}):function(){layer.ready();ready.run(window.jQuery);layer.config({extend:"moon/style.css",skin:"layer-ext-moon"})}())}(window);
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/layer/theme/moon/default.png b/ruoyi-admin/src/main/resources/static/ajax/libs/layer/theme/moon/default.png
new file mode 100644
index 0000000..77dfaf3
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/layer/theme/moon/default.png
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/layer/theme/moon/style.css b/ruoyi-admin/src/main/resources/static/ajax/libs/layer/theme/moon/style.css
new file mode 100644
index 0000000..d3a3a56
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/layer/theme/moon/style.css
@@ -0,0 +1,169 @@
+/**
+ * layer皮肤
+ * Copyright (c) 2019 ruoyi
+ */
+html #layui_layer_skinmoonstylecss {
+	display: none;
+	position: absolute;
+	width: 1989px;
+}
+
+body .layer-ext-moon[type="dialog"] {
+	min-width: 320px;
+}
+body .layer-ext-moon-msg[type="dialog"]{min-width:200px;}
+body .layer-ext-moon .layui-layer-title {
+	background: #F8F8F8;
+	color: #333;
+	font-size: 14px;
+	height: 42px;
+	line-height: 42px;
+    border: none;
+}
+
+body .layer-ext-moon .layui-layer-content .layui-layer-face {
+	height: 32px;
+	width: 32px;
+	top:18.5px;
+}
+body .layer-ext-moon .layui-icon-tips {
+	background: url(default.png) no-repeat -96px 0;
+}
+body .layer-ext-moon .layui-icon-success {
+	background: url(default.png) no-repeat -224px 0;
+}
+body .layer-ext-moon .layui-icon-error {
+	background: url(default.png) no-repeat -192px 0;
+}
+body .layer-ext-moon .layui-icon-question {
+	background: url(default.png) no-repeat -160px 0;
+}
+body .layer-ext-moon .layui-icon-lock {
+	background: url(default.png) no-repeat -320px 0;
+}
+body .layer-ext-moon .layui-icon-face-cry {
+	background: url(default.png) no-repeat -288px 0;
+}
+body .layer-ext-moon .layui-icon-face-smile {
+	background: url(default.png) -256px 0;
+}
+body .layer-ext-moon .layui-layer-download {
+	background: url(default.png) no-repeat -128px 0;
+}
+body .layer-ext-moon .layui-layer-setwin {
+	top: 15px;
+	right: 15px;
+}
+body .layer-ext-moon .layui-layer-setwin a {
+	width: 16px;
+	height: 16px;
+}
+body .layer-ext-moon .layui-layer-setwin .layui-layer-min cite:hover {
+	background-color: #56abe4;
+}
+body .layer-ext-moon .layui-layer-setwin .layui-layer-max {
+	background: url(default.png) no-repeat -80px 0;
+}
+body .layer-ext-moon .layui-layer-setwin .layui-layer-max:hover {
+	background: url(default.png) no-repeat -64px 0;
+}
+body .layer-ext-moon .layui-layer-setwin .layui-layer-maxmin {
+	background: url(default.png) no-repeat -32px 0;
+}
+body .layer-ext-moon .layui-layer-setwin .layui-layer-maxmin:hover {
+	background: url(default.png) no-repeat -16px 0;
+}
+body .layer-ext-moon .layui-layer-setwin .layui-layer-close1,body .layer-ext-moon .layui-layer-setwin .layui-layer-close2, body .layui-layer-tab .layui-layer-setwin .layui-layer-close1,body .layui-layer-tab .layui-layer-setwin .layui-layer-close2 {
+	background: url(default.png) 0 0;
+}
+body .layer-ext-moon .layui-layer-setwin .layui-layer-close1:hover,body .layer-ext-moon .layui-layer-setwin .layui-layer-close2:hover, body .layui-layer-tab .layui-layer-setwin .layui-layer-close1:hover,body .layui-layer-tab .layui-layer-setwin .layui-layer-close2:hover {
+	background: url(default.png) -48px 0;
+}
+body .layer-ext-moon .layui-layer-padding{padding-top: 24px;}
+body .layer-ext-moon .layui-layer-btn {
+    text-align: right;
+    padding: 10px 15px 12px;
+	background: #f0f4f7;
+	border-top: 1px #c7c7c7 solid;
+}
+body .layer-ext-moon .layui-layer-btn a {
+	font-size: 12px;
+	font-weight: normal;
+	margin: 0 3px;
+	margin-right: 7px;
+	margin-left: 7px;
+	padding: 0 15px;
+	color: #fff;
+	border: 1px solid #0064b6;
+	background: #0071ce;
+	border-radius: 3px;
+	display: inline-block;
+	height: 30px;
+	line-height: 30px;
+	text-align: center;
+	vertical-align: middle;
+	background-repeat: no-repeat;
+	text-decoration: none;
+	outline: none;
+	-moz-box-sizing: content-box;
+	-webkit-box-sizing: content-box;
+	box-sizing: content-box;
+}
+body .layer-ext-moon .layui-layer-btn .layui-layer-btn0 {
+	background: #0071ce;
+}
+body .layer-ext-moon .layui-layer-btn .layui-layer-btn1 {
+	background: #fff;
+	color: #404a58;
+	border: 1px solid #c0c4cd;
+	border-radius: 3px;
+}
+body .layer-ext-moon .layui-layer-btn .layui-layer-btn2 {
+	background: #f60;
+	color: #fff;
+	border: 1px solid #f60;
+	border-radius: 3px;
+}
+body .layer-ext-moon .layui-layer-btn .layui-layer-btn3 {
+	background: #f00;
+	color: #fff;
+	border: 1px solid #f00;
+	border-radius: 3px;
+}
+
+body .layer-ext-moon .layui-layer-title span.layui-layer-tabnow{
+	height:47px;
+}
+
+/** 图标字体 **/
+@font-face {
+  font-family: 'layui-icon';
+  src: url('../../../../../fonts/iconfont.woff?v=282') format('woff');
+}
+
+.layui-icon{
+  font-family:"layui-icon" !important;
+  font-style: normal;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+/* font-class */
+.layui-icon-left:before{content:"\e603"}
+.layui-icon-right:before{content:"\e602"}
+.layui-icon-refresh:before{content:"\e669"}
+.layui-icon-slider:before{content:"\e714"}
+.layui-icon-add-circle:before{content:"\e61f"}
+.layui-icon-reduce-circle:before{content:"\e616"}
+.layui-icon-refresh-1:before{content:"\e666"}
+.layui-icon-loading:before{content:"\e63d"}
+.layui-icon-loading-1:before{content:"\e63e"}
+
+/** 循环旋转动画 **/
+.layui-anim{-webkit-animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-duration: 0.3s; animation-fill-mode: both;}
+.layui-anim.layui-icon{display: inline-block;}
+.layui-anim-loop{-webkit-animation-iteration-count: infinite; animation-iteration-count: infinite;}
+.layui-trans,
+.layui-trans a{transition: all .2s; -webkit-transition: all .2s;}
+@-webkit-keyframes layui-rotate{from {-webkit-transform: rotate(0deg);} to {-webkit-transform: rotate(360deg);}}
+@keyframes layui-rotate{from {transform: rotate(0deg);} to {transform: rotate(360deg);}}
+.layui-anim-rotate{-webkit-animation-name: layui-rotate; animation-name: layui-rotate; -webkit-animation-duration: 1s; animation-duration: 1s;  -webkit-animation-timing-function: linear; animation-timing-function: linear;}
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/layui/css/modules/laydate.css b/ruoyi-admin/src/main/resources/static/ajax/libs/layui/css/modules/laydate.css
new file mode 100644
index 0000000..1c32772
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/layui/css/modules/laydate.css
@@ -0,0 +1,2 @@
+/*! laydate-v5.5.0 日期与时间组件 */
+@font-face{font-family: 'laydate-icon';src: url('../../../../../fonts/iconfont.woff?v=282') format('woff');}.laydate-icon{font-family:"laydate-icon"!important;font-size:16px;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}html #layuicss-laydate{display:none;position:absolute;width:1989px}.layui-laydate *{margin:0;padding:0}.layui-laydate,.layui-laydate *{box-sizing:border-box}.layui-laydate{position:absolute;z-index:66666666;margin:5px 0;border-radius:2px;font-size:14px;-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both}.layui-laydate-main{width:272px}.layui-laydate-header *,.layui-laydate-content td,.layui-laydate-list li{transition-duration:.3s;-webkit-transition-duration:.3s}@keyframes laydate-downbit{0%{opacity:.3;transform:translate3d(0,-5px,0)}100%{opacity:1;transform:translate3d(0,0,0)}}.layui-laydate{animation-name:laydate-downbit}.layui-laydate-static{position:relative;z-index:0;display:inline-block;margin:0;-webkit-animation:none;animation:none}.laydate-ym-show .laydate-prev-m,.laydate-ym-show .laydate-next-m{display:none!important}.laydate-ym-show .laydate-prev-y,.laydate-ym-show .laydate-next-y{display:inline-block!important}.laydate-ym-show .laydate-set-ym span[lay-type="month"]{display:none!important}.laydate-time-show .layui-laydate-header .layui-icon,.laydate-time-show .laydate-set-ym span[lay-type="year"],.laydate-time-show .laydate-set-ym span[lay-type="month"]{display:none!important}.layui-laydate-header{position:relative;line-height:30px;padding:10px 70px 5px}.layui-laydate-header *{display:inline-block;vertical-align:bottom}.layui-laydate-header i{position:absolute;top:10px;padding:0 5px;color:#999;font-size:18px;cursor:pointer}.layui-laydate-header i.laydate-prev-y{left:15px}.layui-laydate-header i.laydate-prev-m{left:45px}.layui-laydate-header i.laydate-next-y{right:15px}.layui-laydate-header i.laydate-next-m{right:45px}.laydate-set-ym{width:100%;text-align:center;box-sizing:border-box;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.laydate-set-ym span{padding:0 10px;cursor:pointer}.laydate-time-text{cursor:default!important}.layui-laydate-content{position:relative;padding:10px;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.layui-laydate-content table{border-collapse:collapse;border-spacing:0}.layui-laydate-content th,.layui-laydate-content td{width:36px;height:30px;padding:5px;text-align:center}.layui-laydate-content th{font-weight:400}.layui-laydate-content td{position:relative;cursor:pointer}.laydate-day-mark{position:absolute;left:0;top:0;width:100%;line-height:30px;font-size:12px;overflow:hidden}.laydate-day-mark::after{position:absolute;content:'';right:2px;top:2px;width:5px;height:5px;border-radius:50%}.laydate-day-holidays:before{position:absolute;left:0;top:0;font-size:12px;transform:scale(.7)}.laydate-day-holidays:before{content:'\4F11';color:#ff5722}.laydate-day-holidays[type="work"]:before{content:'\73ED';color:inherit}.layui-laydate .layui-this .laydate-day-holidays:before{color:#fff}.layui-laydate-footer{position:relative;height:46px;line-height:26px;padding:10px}.layui-laydate-footer span{display:inline-block;vertical-align:top;height:26px;line-height:24px;padding:0 10px;border:1px solid #c9c9c9;border-radius:2px;background-color:#fff;font-size:12px;cursor:pointer;white-space:nowrap;transition:all .3s}.layui-laydate-footer span:hover{color:#5fb878}.layui-laydate-footer span.layui-laydate-preview{cursor:default;border-color:transparent!important}.layui-laydate-footer span.layui-laydate-preview:hover{color:#666}.layui-laydate-footer span:first-child.layui-laydate-preview{padding-left:0}.laydate-footer-btns{position:absolute;right:10px;top:10px}.laydate-footer-btns span{margin:0 0 0 -1px}.layui-laydate-list{position:absolute;left:0;top:0;width:100%;height:100%;padding:10px;box-sizing:border-box;background-color:#fff}.layui-laydate-list>li{position:relative;display:inline-block;width:33.3%;height:36px;line-height:36px;margin:3px 0;vertical-align:middle;text-align:center;cursor:pointer}.laydate-month-list>li{width:25%;margin:17px 0}.laydate-time-list>li{height:100%;margin:0;line-height:normal;cursor:default}.laydate-time-list p{position:relative;top:-4px;line-height:29px}.laydate-time-list ol{height:181px;overflow:hidden}.laydate-time-list>li:hover ol{overflow-y:auto}.laydate-time-list ol li{width:130%;padding-left:33px;height:30px;line-height:30px;text-align:left;cursor:pointer}.layui-laydate-hint{position:absolute;top:115px;left:50%;width:250px;margin-left:-125px;line-height:20px;padding:15px;text-align:center;font-size:12px;color:#ff5722}.layui-laydate-range{width:546px}.layui-laydate-range .layui-laydate-main{display:inline-block;vertical-align:middle}.layui-laydate-range .laydate-main-list-1 .layui-laydate-header,.layui-laydate-range .laydate-main-list-1 .layui-laydate-content{border-left:1px solid #e2e2e2}.layui-laydate,.layui-laydate-hint{border:1px solid #d2d2d2;box-shadow:0 2px 4px rgba(0,0,0,.12);background-color:#fff;color:#666}.layui-laydate-header{border-bottom:1px solid #e2e2e2}.layui-laydate-header i:hover,.layui-laydate-header span:hover{color:#5fb878}.layui-laydate-content{border-top:none 0;border-bottom:none 0}.layui-laydate-content th{color:#333}.layui-laydate-content td{color:#666}.layui-laydate-content td.laydate-selected{background-color:#b5fff8}.laydate-selected:hover{background-color:#00f7de!important}.layui-laydate-content td:hover,.layui-laydate-list li:hover{background-color:#eee;color:#333}.laydate-time-list li ol{margin:0;padding:0;border:1px solid #e2e2e2;border-left-width:0}.laydate-time-list li:first-child ol{border-left-width:1px}.laydate-time-list>li:hover{background:0}.layui-laydate-content .laydate-day-prev,.layui-laydate-content .laydate-day-next{color:#d2d2d2}.laydate-selected.laydate-day-prev,.laydate-selected.laydate-day-next{background-color:#f8f8f8!important}.layui-laydate-footer{border-top:1px solid #e2e2e2}.layui-laydate-hint{color:#ff5722}.laydate-day-mark::after{background-color:#5fb878}.layui-laydate-content td.layui-this .laydate-day-mark::after{display:none}.layui-laydate-footer span[lay-type="date"]{color:#5fb878}.layui-laydate .layui-this{background-color:#009688!important;color:#fff!important}.layui-laydate .laydate-disabled,.layui-laydate .laydate-disabled:hover{background:none!important;color:#d2d2d2!important;cursor:not-allowed!important;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.laydate-theme-molv{border:0}.laydate-theme-molv.layui-laydate-range{width:548px}.laydate-theme-molv .layui-laydate-main{width:274px}.laydate-theme-molv .layui-laydate-header{border:0;background-color:#009688}.laydate-theme-molv .layui-laydate-header i,.laydate-theme-molv .layui-laydate-header span{color:#f6f6f6}.laydate-theme-molv .layui-laydate-header i:hover,.laydate-theme-molv .layui-laydate-header span:hover{color:#fff}.laydate-theme-molv .layui-laydate-content{border:1px solid #e2e2e2;border-top:0;border-bottom:0}.laydate-theme-molv .laydate-main-list-1 .layui-laydate-content{border-left:none}.laydate-theme-molv .layui-laydate-footer{border:1px solid #e2e2e2}.laydate-theme-grid .layui-laydate-content td,.laydate-theme-grid .layui-laydate-content thead,.laydate-theme-grid .laydate-year-list>li,.laydate-theme-grid .laydate-month-list>li{border:1px solid #e2e2e2}.laydate-theme-grid .laydate-selected,.laydate-theme-grid .laydate-selected:hover{background-color:#f2f2f2!important;color:#009688!important}.laydate-theme-grid .laydate-selected.laydate-day-prev,.laydate-theme-grid .laydate-selected.laydate-day-next{color:#d2d2d2!important}.laydate-theme-grid .laydate-year-list,.laydate-theme-grid .laydate-month-list{margin:1px 0 0 1px}.laydate-theme-grid .laydate-year-list>li,.laydate-theme-grid .laydate-month-list>li{margin:0 -1px -1px 0}.laydate-theme-grid .laydate-year-list>li{height:43px;line-height:43px}.laydate-theme-grid .laydate-month-list>li{height:71px;line-height:71px}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/layui/layui.min.js b/ruoyi-admin/src/main/resources/static/ajax/libs/layui/layui.min.js
new file mode 100644
index 0000000..618aad8
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/layui/layui.min.js
@@ -0,0 +1,2 @@
+/** layui-v2.8.18 MIT License By https://www.layui.com */
+!function(win){var doc=win.document;var config={modules:{},status:{},timeout:10,event:{}};var Layui=function(){this.v="2.8.18"};var GLOBAL=win.LAYUI_GLOBAL||{};var getPath=function(){var jsPath=doc.currentScript?doc.currentScript.src:function(){var js=doc.scripts;var last=js.length-1;var src;for(var i=last;i>0;i--){if(js[i].readyState==="interactive"){src=js[i].src;break}}return src||js[last].src}();return config.dir=GLOBAL.dir||jsPath.substring(0,jsPath.lastIndexOf("/")+1)}();var error=function(msg,type){type=type||"log";win.console&&console[type]&&console[type]("layui error hint: "+msg)};var isOpera=typeof opera!=="undefined"&&opera.toString()==="[object Opera]";var modules=config.builtin={lay:"lay",layer:"layer",laydate:"laydate",laypage:"laypage",laytpl:"laytpl",form:"form",upload:"upload",dropdown:"dropdown",transfer:"transfer",tree:"tree",table:"table",treeTable:"treeTable",element:"element",rate:"rate",colorpicker:"colorpicker",slider:"slider",carousel:"carousel",flow:"flow",util:"util",code:"code",jquery:"jquery",all:"all","layui.all":"layui.all"};Layui.prototype.cache=config;Layui.prototype.define=function(deps,factory){var that=this;var type=typeof deps==="function";var callback=function(){var setApp=function(app,exports){layui[app]=exports;config.status[app]=true};typeof factory==="function"&&factory(function(app,exports){setApp(app,exports);config.callback[app]=function(){factory(setApp)}});return this};type&&(factory=deps,deps=[]);that.use(deps,callback,null,"define");return that};Layui.prototype.use=function(apps,callback,exports,from){var that=this;var dir=config.dir=config.dir?config.dir:getPath;var head=doc.getElementsByTagName("head")[0];apps=function(){if(typeof apps==="string"){return[apps]}else{if(typeof apps==="function"){callback=apps;return["all"]}}return apps}();if(win.jQuery&&jQuery.fn.on){that.each(apps,function(index,item){if(item==="jquery"){apps.splice(index,1)}});layui.jquery=layui.$=jQuery}var item=apps[0];var timeout=0;exports=exports||[];config.host=config.host||(dir.match(/\/\/([\s\S]+?)\//)||["//"+location.host+"/"])[0];function onScriptLoad(e,url){var readyRegExp=navigator.platform==="PLaySTATION 3"?/^complete$/:/^(complete|loaded)$/;if(e.type==="load"||(readyRegExp.test((e.currentTarget||e.srcElement).readyState))){config.modules[item]=url;head.removeChild(node);(function poll(){if(++timeout>config.timeout*1000/4){return error(item+" is not a valid module","error")}config.status[item]?onCallback():setTimeout(poll,4)}())}}function onCallback(){exports.push(layui[item]);apps.length>1?that.use(apps.slice(1),callback,exports,from):(typeof callback==="function"&&function(){if(layui.jquery&&typeof layui.jquery==="function"&&from!=="define"){return layui.jquery(function(){callback.apply(layui,exports)})}callback.apply(layui,exports)}())}if(apps.length===0||(layui["layui.all"]&&modules[item])){return onCallback(),that}var url=(modules[item]?(dir+"modules/"):(/^\{\/\}/.test(that.modules[item])?"":(config.base||"")))+(that.modules[item]||item)+".js";url=url.replace(/^\{\/\}/,"");if(!config.modules[item]&&layui[item]){config.modules[item]=url}if(!config.modules[item]){var node=doc.createElement("script");node.async=true;node.charset="utf-8";node.src=url+function(){var version=config.version===true?(config.v||(new Date()).getTime()):(config.version||"");return version?("?v="+version):""}();head.appendChild(node);if(node.attachEvent&&!(node.attachEvent.toString&&node.attachEvent.toString().indexOf("[native code")<0)&&!isOpera){node.attachEvent("onreadystatechange",function(e){onScriptLoad(e,url)})}else{node.addEventListener("load",function(e){onScriptLoad(e,url)},false)}config.modules[item]=url}else{(function poll(){if(++timeout>config.timeout*1000/4){return error(item+" is not a valid module","error")}(typeof config.modules[item]==="string"&&config.status[item])?onCallback():setTimeout(poll,4)}())}return that};Layui.prototype.disuse=function(apps){var that=this;apps=that.isArray(apps)?apps:[apps];that.each(apps,function(index,item){if(!config.status[item]){}delete that[item];delete modules[item];delete that.modules[item];delete config.status[item];delete config.modules[item]});return that};Layui.prototype.getStyle=function(node,name){var style=node.currentStyle?node.currentStyle:win.getComputedStyle(node,null);return style[style.getPropertyValue?"getPropertyValue":"getAttribute"](name)};Layui.prototype.link=function(href,fn,cssname){var that=this;var head=doc.getElementsByTagName("head")[0];var link=doc.createElement("link");if(typeof fn==="string"){cssname=fn}var app=(cssname||href).replace(/\.|\//g,"");var id="layuicss-"+app;var STAUTS_NAME="creating";var timeout=0;link.href=href+(config.debug?"?v="+new Date().getTime():"");link.rel="stylesheet";link.id=id;link.media="all";if(!doc.getElementById(id)){head.appendChild(link)}if(typeof fn!=="function"){return that}(function poll(status){var delay=100;var getLinkElem=doc.getElementById(id);if(++timeout>config.timeout*1000/delay){return error(href+" timeout")}if(parseInt(that.getStyle(getLinkElem,"width"))===1989){if(status===STAUTS_NAME){getLinkElem.removeAttribute("lay-status")}getLinkElem.getAttribute("lay-status")===STAUTS_NAME?setTimeout(poll,delay):fn()}else{getLinkElem.setAttribute("lay-status",STAUTS_NAME);setTimeout(function(){poll(STAUTS_NAME)},delay)}}());return that};Layui.prototype.addcss=function(firename,fn,cssname){return layui.link(config.dir+"css/"+firename,fn,cssname)};config.callback={};Layui.prototype.factory=function(modName){if(layui[modName]){return typeof config.callback[modName]==="function"?config.callback[modName]:null}};Layui.prototype.img=function(url,callback,error){var img=new Image();img.src=url;if(img.complete){return callback(img)}img.onload=function(){img.onload=null;typeof callback==="function"&&callback(img)};img.onerror=function(e){img.onerror=null;typeof error==="function"&&error(e)}};Layui.prototype.config=function(options){options=options||{};for(var key in options){config[key]=options[key]}return this};Layui.prototype.modules=function(){var clone={};for(var o in modules){clone[o]=modules[o]}return clone}();Layui.prototype.extend=function(options){var that=this;options=options||{};for(var o in options){if(that[o]||that.modules[o]){error(o+" Module already exists","error")}else{that.modules[o]=options[o]}}return that};Layui.prototype.router=Layui.prototype.hash=function(hash){var that=this;var hash=hash||location.hash;var data={path:[],search:{},hash:(hash.match(/[^#](#.*$)/)||[])[1]||""};if(!/^#\//.test(hash)){return data}hash=hash.replace(/^#\//,"");data.href="/"+hash;hash=hash.replace(/([^#])(#.*$)/,"$1").split("/")||[];that.each(hash,function(index,item){/^\w+=/.test(item)?function(){item=item.split("=");data.search[item[0]]=item[1]}():data.path.push(item)});return data};Layui.prototype.url=function(href){var that=this;var data={pathname:function(){var pathname=href?function(){var str=(href.match(/\.[^.]+?\/.+/)||[])[0]||"";return str.replace(/^[^\/]+/,"").replace(/\?.+/,"")}():location.pathname;return pathname.replace(/^\//,"").split("/")}(),search:function(){var obj={};var search=(href?function(){var str=(href.match(/\?.+/)||[])[0]||"";return str.replace(/\#.+/,"")}():location.search).replace(/^\?+/,"").split("&");that.each(search,function(index,item){var _index=item.indexOf("="),key=function(){if(_index<0){return item.substr(0,item.length)}else{if(_index===0){return false}else{return item.substr(0,_index)}}}();if(key){obj[key]=_index>0?item.substr(_index+1):null}});return obj}(),hash:that.router(function(){return href?((href.match(/#.+/)||[])[0]||"/"):location.hash}())};return data};Layui.prototype.data=function(table,settings,storage){table=table||"layui";storage=storage||localStorage;if(!win.JSON||!win.JSON.parse){return}if(settings===null){return delete storage[table]}settings=typeof settings==="object"?settings:{key:settings};try{var data=JSON.parse(storage[table])}catch(e){var data={}}if("value" in settings){data[settings.key]=settings.value}if(settings.remove){delete data[settings.key]}storage[table]=JSON.stringify(data);return settings.key?data[settings.key]:data};Layui.prototype.sessionData=function(table,settings){return this.data(table,settings,sessionStorage)};Layui.prototype.device=function(key){var agent=navigator.userAgent.toLowerCase();var getVersion=function(label){var exp=new RegExp(label+"/([^\\s\\_\\-]+)");label=(agent.match(exp)||[])[1];return label||false};var result={os:function(){if(/windows/.test(agent)){return"windows"}else{if(/linux/.test(agent)){return"linux"}else{if(/iphone|ipod|ipad|ios/.test(agent)){return"ios"}else{if(/mac/.test(agent)){return"mac"}}}}}(),ie:function(){return(!!win.ActiveXObject||"ActiveXObject" in win)?((agent.match(/msie\s(\d+)/)||[])[1]||"11"):false}(),weixin:getVersion("micromessenger")};if(key&&!result[key]){result[key]=getVersion(key)}result.android=/android/.test(agent);result.ios=result.os==="ios";result.mobile=(result.android||result.ios);return result};Layui.prototype.hint=function(){return{error:error}};Layui.prototype._typeof=Layui.prototype.type=function(operand){if(operand===null){return String(operand)}return(typeof operand==="object"||typeof operand==="function")?function(){var type=Object.prototype.toString.call(operand).match(/\s(.+)\]$/)||[];var classType="Function|Array|Date|RegExp|Object|Error|Symbol";type=type[1]||"Object";return new RegExp("\\b("+classType+")\\b").test(type)?type.toLowerCase():"object"}():typeof operand};Layui.prototype._isArray=Layui.prototype.isArray=function(obj){var that=this;var len;var type=that.type(obj);if(!obj||(typeof obj!=="object")||obj===win){return false}len="length" in obj&&obj.length;return type==="array"||len===0||(typeof len==="number"&&len>0&&(len-1) in obj)};Layui.prototype.each=function(obj,fn){var key;var that=this;var callFn=function(key,obj){return fn.call(obj[key],key,obj[key])};if(typeof fn!=="function"){return that}obj=obj||[];if(that.isArray(obj)){for(key=0;key<obj.length;key++){if(callFn(key,obj)){break}}}else{for(key in obj){if(callFn(key,obj)){break}}}return that};Layui.prototype.sort=function(arr,key,desc,notClone){var that=this;var clone=notClone?(arr||[]):JSON.parse(JSON.stringify(arr||[]));if(that.type(arr)==="object"&&!key){return clone}else{if(typeof arr!=="object"){return[clone]}}clone.sort(function(o1,o2){var v1=o1[key];var v2=o2[key];if(!isNaN(o1)&&!isNaN(o2)){return o1-o2}if(!isNaN(o1)&&isNaN(o2)){if(key&&typeof o2==="object"){v1=o1}else{return -1}}else{if(isNaN(o1)&&!isNaN(o2)){if(key&&typeof o1==="object"){v2=o2}else{return 1}}}var isNum=[!isNaN(v1),!isNaN(v2)];if(isNum[0]&&isNum[1]){if(v1&&(!v2&&v2!==0)){return 1}else{if((!v1&&v1!==0)&&v2){return -1}else{return v1-v2}}}if(!isNum[0]&&!isNum[1]){if(v1>v2){return 1}else{if(v1<v2){return -1}else{return 0}}}if(isNum[0]||!isNum[1]){return -1}else{if(!isNum[0]||isNum[1]){return 1}}});desc&&clone.reverse();return clone};Layui.prototype.stope=function(thisEvent){thisEvent=thisEvent||win.event;try{thisEvent.stopPropagation()}catch(e){thisEvent.cancelBubble=true}};var EV_REMOVE="LAYUI-EVENT-REMOVE";Layui.prototype.onevent=function(modName,events,callback){if(typeof modName!=="string"||typeof callback!=="function"){return this}return Layui.event(modName,events,null,callback)};Layui.prototype.event=Layui.event=function(modName,events,params,fn){var that=this;var result=null;var filter=(events||"").match(/\((.*)\)$/)||[];var eventName=(modName+"."+events).replace(filter[0],"");var filterName=filter[1]||"";var callback=function(_,item){var res=item&&item.call(that,params);res===false&&result===null&&(result=false)};if(params===EV_REMOVE){delete (that.cache.event[eventName]||{})[filterName];return that}if(fn){config.event[eventName]=config.event[eventName]||{};if(filterName){config.event[eventName][filterName]=[fn]}else{config.event[eventName][filterName]=config.event[eventName][filterName]||[];config.event[eventName][filterName].push(fn)}return this}layui.each(config.event[eventName],function(key,item){if(filterName==="{*}"){layui.each(item,callback);return}key===""&&layui.each(item,callback);(filterName&&key===filterName)&&layui.each(item,callback)});return result};Layui.prototype.on=function(events,modName,callback){var that=this;return that.onevent.call(that,modName,events,callback)};Layui.prototype.off=function(events,modName){var that=this;return that.event.call(that,modName,events,EV_REMOVE)};Layui.prototype.debounce=function(func,wait){var timeout;return function(){var context=this;var args=arguments;clearTimeout(timeout);timeout=setTimeout(function(){func.apply(context,args)},wait)}};Layui.prototype.throttle=function(func,wait){var cooldown=false;return function(){var context=this;var args=arguments;if(!cooldown){func.apply(context,args);cooldown=true;setTimeout(function(){cooldown=false},wait)}}};win.layui=new Layui()}(window);
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/layui/modules/laydate.js b/ruoyi-admin/src/main/resources/static/ajax/libs/layui/modules/laydate.js
new file mode 100644
index 0000000..e177d02
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/layui/modules/laydate.js
@@ -0,0 +1,2 @@
+/*! laydate-v5.5.0 日期与时间组件 */
+!function(window){var MOD_NAME="lay";var document=window.document;var lay=function(selector){return new Class(selector)};var Class=function(selector){var that=this;var elem=typeof selector==="object"?function(){return layui.isArray(selector)?selector:[selector]}():(this.selector=selector,document.querySelectorAll(selector||null));lay.each(elem,function(index,item){that.push(elem[index])})};Array.prototype.indexOf=Array.prototype.indexOf||function(searchElement,fromIndex){var rst=-1;fromIndex=fromIndex||0;layui.each(this,function(index,val){if(searchElement===val&&index>=fromIndex){rst=index;return !0}});return rst};Class.fn=Class.prototype=[];Class.fn.constructor=Class;lay.extend=function(){var ai=1;var length;var args=arguments;var clone=function(target,obj){target=target||(layui.type(obj)==="array"?[]:{});for(var i in obj){target[i]=(obj[i]&&obj[i].constructor===Object)?clone(target[i],obj[i]):obj[i]}return target};args[0]=typeof args[0]==="object"?args[0]:{};length=args.length;for(;ai<length;ai++){if(typeof args[ai]==="object"){clone(args[0],args[ai])}}return args[0]};lay.ie=function(){var agent=navigator.userAgent.toLowerCase();return(!!window.ActiveXObject||"ActiveXObject" in window)?((agent.match(/msie\s(\d+)/)||[])[1]||"11"):false}();lay.layui=layui||{};lay.getPath=layui.cache.dir;lay.stope=layui.stope;lay.each=function(){layui.each.apply(layui,arguments);return this};lay.digit=function(num,length){if(!(typeof num==="string"||typeof num==="number")){return""}var str="";num=String(num);length=length||2;for(var i=num.length;i<length;i++){str+="0"}return num<Math.pow(10,length)?str+num:num};lay.elem=function(elemName,attr){var elem=document.createElement(elemName);lay.each(attr||{},function(key,value){elem.setAttribute(key,value)});return elem};lay.hasScrollbar=function(){return document.body.scrollHeight>(window.innerHeight||document.documentElement.clientHeight)};lay.getStyleRules=function(style,callback){if(!style){return}var sheet=style.sheet||style.styleSheet||{};var rules=sheet.cssRules||sheet.rules;if(typeof callback==="function"){layui.each(rules,function(i,item){if(callback(item,i)){return true}})}return rules};lay.style=function(options){options=options||{};var style=lay.elem("style");var styleText=options.text||"";var target=options.target;if(!styleText){return}if("styleSheet" in style){style.setAttribute("type","text/css");style.styleSheet.cssText=styleText}else{style.innerHTML=styleText}style.id="LAY-STYLE-"+(options.id||function(index){lay.style.index++;return"DF-"+index}(lay.style.index||0));if(target){var styleElem=lay(target).find("#"+style.id);styleElem[0]&&styleElem.remove();lay(target).append(style)}return style};lay.position=function(target,elem,opts){if(!elem){return}opts=opts||{};if(target===document||target===lay("body")[0]){opts.clickType="right"}var rect=opts.clickType==="right"?function(){var e=opts.e||window.event||{};return{left:e.clientX,top:e.clientY,right:e.clientX,bottom:e.clientY}}():target.getBoundingClientRect();var elemWidth=elem.offsetWidth;var elemHeight=elem.offsetHeight;var scrollArea=function(type){type=type?"scrollLeft":"scrollTop";return document.body[type]|document.documentElement[type]};var winArea=function(type){return document.documentElement[type?"clientWidth":"clientHeight"]};var margin="margin" in opts?opts.margin:5;var left=rect.left;var top=rect.bottom;if(opts.align==="center"){left=left-(elemWidth-target.offsetWidth)/2}else{if(opts.align==="right"){left=left-elemWidth+target.offsetWidth}}if(left+elemWidth+margin>winArea("width")){left=winArea("width")-elemWidth-margin}if(left<margin){left=margin}if(rect.bottom+elemHeight+margin>winArea()){if(rect.top>elemHeight+margin&&rect.top<=winArea()){top=rect.top-elemHeight-margin*2}else{if(!opts.allowBottomOut){top=winArea()-elemHeight-margin*2;if(top<0){top=0}}}}var position=opts.position;if(position){elem.style.position=position}elem.style.left=left+(position==="fixed"?0:scrollArea(1))+"px";elem.style.top=top+(position==="fixed"?0:scrollArea())+"px";if(!lay.hasScrollbar()){var rect1=elem.getBoundingClientRect();if(!opts.SYSTEM_RELOAD&&(rect1.bottom+margin)>winArea()){opts.SYSTEM_RELOAD=true;setTimeout(function(){lay.position(target,elem,opts)},50)}}};lay.options=function(elem,opts){opts=typeof opts==="object"?opts:{attr:opts};if(elem===document){return{}}var othis=lay(elem);var attrName=opts.attr||"lay-options";var attrValue=othis.attr(attrName);try{return new Function("return "+(attrValue||"{}"))()}catch(ev){layui.hint().error(opts.errorText||[attrName+'="'+attrValue+'"',"\n parseerror: "+ev].join("\n"),"error");return{}}};lay.isTopElem=function(elem){var topElems=[document,lay("body")[0]],matched=false;lay.each(topElems,function(index,item){if(item===elem){return matched=true}});return matched};lay.clipboard={writeText:function(options){var text=String(options.text);try{navigator.clipboard.writeText(text).then(options.done)["catch"](options.error)}catch(e){var elem=document.createElement("textarea");elem.value=text;elem.style.position="fixed";elem.style.opacity="0";elem.style.top="0px";elem.style.left="0px";document.body.appendChild(elem);elem.select();try{document.execCommand("copy");typeof options.done==="function"&&options.done()}catch(err){typeof options.error==="function"&&options.error(err)}finally{elem.remove?elem.remove():document.body.removeChild(elem)}}}};Class.addStr=function(str,new_str){str=str.replace(/\s+/," ");new_str=new_str.replace(/\s+/," ").split(" ");lay.each(new_str,function(ii,item){if(!new RegExp("\\b"+item+"\\b").test(str)){str=str+" "+item}});return str.replace(/^\s|\s$/,"")};Class.removeStr=function(str,new_str){str=str.replace(/\s+/," ");new_str=new_str.replace(/\s+/," ").split(" ");lay.each(new_str,function(ii,item){var exp=new RegExp("\\b"+item+"\\b");if(exp.test(str)){str=str.replace(exp,"")}});return str.replace(/\s+/," ").replace(/^\s|\s$/,"")};Class.fn.find=function(selector){var that=this;var elem=[];var isObject=typeof selector==="object";this.each(function(i,item){var children=isObject&&item.contains(selector)?selector:item.querySelectorAll(selector||null);lay.each(children,function(index,child){elem.push(child)})});return lay(elem)};Class.fn.each=function(fn){return lay.each.call(this,this,fn)};Class.fn.addClass=function(className,type){return this.each(function(index,item){item.className=Class[type?"removeStr":"addStr"](item.className,className)})};Class.fn.removeClass=function(className){return this.addClass(className,true)};Class.fn.hasClass=function(className){var has=false;this.each(function(index,item){if(new RegExp("\\b"+className+"\\b").test(item.className)){has=true}});return has};Class.fn.css=function(key,value){var that=this;var parseValue=function(v){return isNaN(v)?v:(v+"px")};return(typeof key==="string"&&value===undefined)?function(){if(that.length>0){return that[0].style[key]}}():that.each(function(index,item){typeof key==="object"?lay.each(key,function(thisKey,thisValue){item.style[thisKey]=parseValue(thisValue)}):item.style[key]=parseValue(value)})};Class.fn.width=function(value){var that=this;return value===undefined?function(){if(that.length>0){return that[0].offsetWidth}}():that.each(function(index,item){that.css("width",value)})};Class.fn.height=function(value){var that=this;return value===undefined?function(){if(that.length>0){return that[0].offsetHeight}}():that.each(function(index,item){that.css("height",value)})};Class.fn.attr=function(key,value){var that=this;return value===undefined?function(){if(that.length>0){return that[0].getAttribute(key)}}():that.each(function(index,item){item.setAttribute(key,value)})};Class.fn.removeAttr=function(key){return this.each(function(index,item){item.removeAttribute(key)})};Class.fn.html=function(html){var that=this;return html===undefined?function(){if(that.length>0){return that[0].innerHTML}}():this.each(function(index,item){item.innerHTML=html})};Class.fn.val=function(value){var that=this;return value===undefined?function(){if(that.length>0){return that[0].value}}():this.each(function(index,item){item.value=value})};Class.fn.append=function(elem){return this.each(function(index,item){typeof elem==="object"?item.appendChild(elem):item.innerHTML=item.innerHTML+elem})};Class.fn.remove=function(elem){return this.each(function(index,item){elem?item.removeChild(elem):item.parentNode.removeChild(item)})};Class.fn.on=function(eventName,fn){return this.each(function(index,item){item.attachEvent?item.attachEvent("on"+eventName,function(e){e.target=e.srcElement;fn.call(item,e)}):item.addEventListener(eventName,fn,false)})};Class.fn.off=function(eventName,fn){return this.each(function(index,item){item.detachEvent?item.detachEvent("on"+eventName,fn):item.removeEventListener(eventName,fn,false)})};window.lay=lay;if(window.layui&&layui.define){layui.define(function(exports){exports(MOD_NAME,lay)})}}(window,window.document);!function(window,document){var isLayui=window.layui&&layui.define,ready={getPath:(window.lay&&lay.getPath)?lay.getPath:"",link:function(href,fn,cssname){if(!laydate.path){return}if(window.lay&&lay.layui){lay.layui.link(laydate.path+href,fn,cssname)}}};var GLOBAL=window.LAYUI_GLOBAL||{};var MOD_NAME="laydate";var MOD_ID="layui-"+MOD_NAME+"-id";var laydate={v:"5.5.0",config:{weekStart:0,},index:(window.laydate&&window.laydate.v)?100000:0,path:GLOBAL.laydate_dir||ready.getPath,set:function(options){var that=this;that.config=lay.extend({},that.config,options);return that},ready:function(callback){var cssname="laydate";var ver="";var path=(isLayui?"modules/":"")+"laydate.css?v="+laydate.v+ver;isLayui?(layui["layui.all"]?(typeof callback==="function"&&callback()):layui.addcss(path,callback,cssname)):ready.link(path,callback,cssname);return this}};var thisModule=function(){var that=this;var options=that.config;var id=options.id;thisModule.that[id]=that;return that.inst={hint:function(content){that.hint.call(that,content)},reload:function(options){that.reload.call(that,options)},config:that.config}};var MOD_NAME="laydate";var ELEM=".layui-laydate";var THIS="layui-this";var SHOW="layui-show";var HIDE="layui-hide";var DISABLED="laydate-disabled";var LIMIT_YEAR=[100,200000];var ELEM_STATIC="layui-laydate-static";var ELEM_LIST="layui-laydate-list";var ELEM_SELECTED="laydate-selected";var ELEM_HINT="layui-laydate-hint";var ELEM_DAY_NOW="laydate-day-now";var ELEM_PREV="laydate-day-prev";var ELEM_NEXT="laydate-day-next";var ELEM_FOOTER="layui-laydate-footer";var ELEM_SHORTCUT="layui-laydate-shortcut";var ELEM_NOW=".laydate-btns-now";var ELEM_CONFIRM=".laydate-btns-confirm";var ELEM_TIME_TEXT="laydate-time-text";var ELEM_TIME_BTN="laydate-btns-time";var ELEM_PREVIEW="layui-laydate-preview";var ELEM_MAIN="layui-laydate-main";var ELEM_SHADE="layui-laydate-shade";var Class=function(options){var that=this;that.index=++laydate.index;that.config=lay.extend({},that.config,laydate.config,options);var elem=lay(options.elem||that.config.elem);if(elem.length>1){lay.each(elem,function(){laydate.render(lay.extend({},that.config,{elem:this}))});return that}options=lay.extend(that.config,lay.options(elem[0]));if(elem[0]&&elem.attr(MOD_ID)){var newThat=thisModule.getThis(elem.attr(MOD_ID));if(!newThat){return}return newThat.reload(options)}options.id="id" in options?options.id:(elem.attr("id")||that.index);options.index=that.index;laydate.ready(function(){that.init()})};var dateType="yyyy|y|MM|M|dd|d|HH|H|mm|m|ss|s";thisModule.formatArr=function(format){return(format||"").match(new RegExp(dateType+"|.","g"))||[]};Class.isLeapYear=function(year){return(year%4===0&&year%100!==0)||year%400===0};Class.prototype.config={type:"date",range:false,format:"yyyy-MM-dd",value:null,isInitValue:true,min:"1900-1-1",max:"2099-12-31",trigger:"click",show:false,showBottom:true,isPreview:true,btns:["clear","now","confirm"],lang:"cn",theme:"default",position:null,calendar:false,mark:{},holidays:null,zIndex:null,done:null,change:null,autoConfirm:true,shade:0};Class.prototype.lang=function(){var that=this,options=that.config,text={cn:{weeks:["日","一","二","三","四","五","六"],time:["时","分","秒"],timeTips:"选择时间",startTime:"开始时间",endTime:"结束时间",dateTips:"返回日期",month:["一","二","三","四","五","六","七","八","九","十","十一","十二"],tools:{confirm:"确定",clear:"清空",now:"现在"},timeout:"结束时间不能早于开始时间<br>请重新选择",invalidDate:"不在有效日期或时间范围内",formatError:["日期格式不合法<br>必须遵循下述格式:<br>","<br>已为你重置"],preview:"当前选中的结果"},en:{weeks:["Su","Mo","Tu","We","Th","Fr","Sa"],time:["Hours","Minutes","Seconds"],timeTips:"Select Time",startTime:"Start Time",endTime:"End Time",dateTips:"Select Date",month:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],tools:{confirm:"Confirm",clear:"Clear",now:"Now"},timeout:"End time cannot be less than start Time<br>Please re-select",invalidDate:"Invalid date",formatError:["The date format error<br>Must be followed:<br>","<br>It has been reset"],preview:"The selected result"}};return text[options.lang]||text["cn"]};Class.prototype.reload=function(options){var that=this;that.config=lay.extend({},that.config,options);that.init()};Class.prototype.init=function(){var that=this,options=that.config,isStatic=options.position==="static",format={year:"yyyy",month:"yyyy-MM",date:"yyyy-MM-dd",time:"HH:mm:ss",datetime:"yyyy-MM-dd HH:mm:ss"};options.elem=lay(options.elem);options.eventElem=lay(options.eventElem);if(!options.elem[0]){return}layui.type(options.theme)!=="array"&&(options.theme=[options.theme]);if(options.fullPanel){if(options.type!=="datetime"||options.range){delete options.fullPanel}}that.rangeStr=options.range?(typeof options.range==="string"?options.range:"-"):"";that.rangeLinked=!!(options.range&&options.rangeLinked&&(options.type==="date"||options.type==="datetime"));that.autoCalendarModel=function(){var state=that.rangeLinked;that.rangeLinked=(options.range&&(options.type==="date"||options.type==="datetime"))&&((!that.startDate||!that.endDate)||(that.startDate&&that.endDate&&that.startDate.year===that.endDate.year&&that.startDate.month===that.endDate.month));lay(that.elem)[that.rangeLinked?"addClass":"removeClass"]("layui-laydate-linkage");return that.rangeLinked!=state};that.autoCalendarModel.auto=that.rangeLinked&&options.rangeLinked==="auto";if(layui.type(options.range)==="array"){that.rangeElem=[lay(options.range[0]),lay(options.range[1])]}if(!format[options.type]){window.console&&console.error&&console.error("laydate type error:'"+options.type+"' is not supported");options.type="date"}if(options.format===format.date){options.format=format[options.type]||format.date}that.format=thisModule.formatArr(options.format);if(options.weekStart){if(!/^[0-6]$/.test(options.weekStart)){var lang=that.lang();options.weekStart=lang.weeks.indexOf(options.weekStart);if(options.weekStart===-1){options.weekStart=0}}}that.EXP_IF="";that.EXP_SPLIT="";lay.each(that.format,function(i,item){var EXP=new RegExp(dateType).test(item)?"\\d{"+function(){if(new RegExp(dateType).test(that.format[i===0?i+1:i-1]||"")){if(/^yyyy|y$/.test(item)){return 4}return item.length}if(/^yyyy$/.test(item)){return"1,4"}if(/^y$/.test(item)){return"1,308"}return"1,2"}()+"}":"\\"+item;that.EXP_IF=that.EXP_IF+EXP;that.EXP_SPLIT=that.EXP_SPLIT+"("+EXP+")"});that.EXP_IF_ONE=new RegExp("^"+that.EXP_IF+"$");that.EXP_IF=new RegExp("^"+(options.range?that.EXP_IF+"\\s\\"+that.rangeStr+"\\s"+that.EXP_IF:that.EXP_IF)+"$");that.EXP_SPLIT=new RegExp("^"+that.EXP_SPLIT+"$","");if(!that.isInput(options.elem[0])){if(options.trigger==="focus"){options.trigger="click"}}options.elem.attr("lay-key",that.index);options.eventElem.attr("lay-key",that.index);options.elem.attr(MOD_ID,options.id);options.mark=lay.extend({},(options.calendar&&options.lang==="cn")?{"0-1-1":"元旦","0-2-14":"情人","0-3-8":"妇女","0-3-12":"植树","0-4-1":"愚人","0-5-1":"劳动","0-5-4":"青年","0-6-1":"儿童","0-9-10":"教师","0-10-1":"国庆","0-12-25":"圣诞"}:{},options.mark);lay.each(["min","max"],function(i,item){var ymd=[];var hms=[];if(typeof options[item]==="number"){var day=options[item],tDate=new Date(),time=that.newDate({year:tDate.getFullYear(),month:tDate.getMonth(),date:tDate.getDate(),hours:i?23:0,minutes:i?59:0,seconds:i?59:0}).getTime(),STAMP=86400000,thisDate=new Date(day?(day<STAMP?time+day*STAMP:day):time);ymd=[thisDate.getFullYear(),thisDate.getMonth()+1,thisDate.getDate()];hms=[thisDate.getHours(),thisDate.getMinutes(),thisDate.getSeconds()]}else{if(typeof options[item]==="string"){ymd=(options[item].match(/\d+-\d+-\d+/)||[""])[0].split("-");hms=(options[item].match(/\d+:\d+:\d+/)||[""])[0].split(":")}else{if(typeof options[item]==="object"){return options[item]}}}options[item]={year:ymd[0]|0||new Date().getFullYear(),month:ymd[1]?(ymd[1]|0)-1:new Date().getMonth(),date:ymd[2]|0||new Date().getDate(),hours:hms[0]|0,minutes:hms[1]|0,seconds:hms[2]|0}});that.elemID="layui-laydate"+options.elem.attr("lay-key");if(options.show||isStatic){that.render()}isStatic||that.events();if(options.value&&options.isInitValue){if(layui.type(options.value)==="date"){that.setValue(that.parse(0,that.systemDate(options.value)))}else{that.setValue(options.value)}}};Class.prototype.render=function(){var that=this,options=that.config,lang=that.lang(),isStatic=options.position==="static",elem=that.elem=lay.elem("div",{id:that.elemID,"class":["layui-laydate",options.range?" layui-laydate-range":"",that.rangeLinked?" layui-laydate-linkage":"",isStatic?(" "+ELEM_STATIC):"",options.fullPanel?" laydate-theme-fullpanel":"",(function(){var themeStr="";lay.each(options.theme,function(index,theme){if(theme!=="default"&&!/^#/.test(theme)){themeStr+=" laydate-theme-"+theme}});return themeStr})()].join("")}),elemMain=that.elemMain=[],elemHeader=that.elemHeader=[],elemCont=that.elemCont=[],elemTable=that.table=[],divFooter=that.footer=lay.elem("div",{"class":ELEM_FOOTER}),divShortcut=that.shortcut=lay.elem("ul",{"class":ELEM_SHORTCUT});if(options.zIndex){elem.style.zIndex=options.zIndex}lay.each(new Array(2),function(i){if(!options.range&&i>0){return true}var divHeader=lay.elem("div",{"class":"layui-laydate-header"}),headerChild=[function(){var elem=lay.elem("i",{"class":"layui-icon laydate-icon laydate-prev-y"});elem.innerHTML="&#xe65a;";return elem}(),function(){var elem=lay.elem("i",{"class":"layui-icon laydate-icon laydate-prev-m"});elem.innerHTML="&#xe603;";return elem}(),function(){var elem=lay.elem("div",{"class":"laydate-set-ym"}),spanY=lay.elem("span"),spanM=lay.elem("span");elem.appendChild(spanY);elem.appendChild(spanM);return elem}(),function(){var elem=lay.elem("i",{"class":"layui-icon laydate-icon laydate-next-m"});elem.innerHTML="&#xe602;";return elem}(),function(){var elem=lay.elem("i",{"class":"layui-icon laydate-icon laydate-next-y"});elem.innerHTML="&#xe65b;";return elem}()],divContent=lay.elem("div",{"class":"layui-laydate-content"}),table=lay.elem("table"),thead=lay.elem("thead"),theadTr=lay.elem("tr");lay.each(headerChild,function(i,item){divHeader.appendChild(item)});thead.appendChild(theadTr);lay.each(new Array(6),function(i){var tr=table.insertRow(0);lay.each(new Array(7),function(j){if(i===0){var th=lay.elem("th");th.innerHTML=lang.weeks[(j+options.weekStart)%7];theadTr.appendChild(th)}tr.insertCell(j)})});table.insertBefore(thead,table.children[0]);divContent.appendChild(table);elemMain[i]=lay.elem("div",{"class":ELEM_MAIN+" laydate-main-list-"+i});elemMain[i].appendChild(divHeader);elemMain[i].appendChild(divContent);elemHeader.push(headerChild);elemCont.push(divContent);elemTable.push(table)});lay(divFooter).html(function(){var html=[],btns=[];if(options.type==="datetime"){html.push('<span lay-type="datetime" class="'+ELEM_TIME_BTN+'">'+lang.timeTips+"</span>")}if(!(!options.range&&options.type==="datetime")||options.fullPanel){html.push('<span class="'+ELEM_PREVIEW+'" title="'+lang.preview+'"></span>')}lay.each(options.btns,function(i,item){var title=lang.tools[item]||"btn";if(options.range&&item==="now"){return}if(isStatic&&item==="clear"){title=options.lang==="cn"?"重置":"Reset"}btns.push('<span lay-type="'+item+'" class="laydate-btns-'+item+'">'+title+"</span>")});html.push('<div class="laydate-footer-btns">'+btns.join("")+"</div>");return html.join("")}());if(options.shortcuts){elem.appendChild(divShortcut);lay(divShortcut).html(function(){var shortcutBtns=[];lay.each(options.shortcuts,function(i,item){shortcutBtns.push('<li data-index="'+i+'">'+item.text+"</li>")});return shortcutBtns.join("")}()).find("li").on("click",function(event){var btnSetting=options.shortcuts[this.dataset["index"]]||{};var value=(typeof btnSetting.value==="function"?btnSetting.value():btnSetting.value)||[];if(!layui.isArray(value)){value=[value]}var type=options.type;lay.each(value,function(i,item){var dateTime=[options.dateTime,that.endDate][i];if(type==="time"&&layui.type(item)!=="date"){if(that.EXP_IF.test(item)){item=(item.match(that.EXP_SPLIT)||[]).slice(1);lay.extend(dateTime,{hours:item[0]|0,minutes:item[2]|0,seconds:item[4]|0})}}else{lay.extend(dateTime,that.systemDate(layui.type(item)==="date"?item:new Date(item)))}if(type==="time"||type==="datetime"){that[["startTime","endTime"][i]]={hours:dateTime.hours,minutes:dateTime.minutes,seconds:dateTime.seconds,}}if(i===0){that.startDate=lay.extend({},dateTime)}else{that.endState=true}if(type==="year"||type==="month"||type==="time"){that.listYM[i]=[dateTime.year,dateTime.month+1]}else{if(i){that.autoCalendarModel.auto&&that.autoCalendarModel()}}});that.checkDate("limit").calendar(null,null,"init");var timeBtn=lay(that.footer).find("."+ELEM_TIME_BTN).removeClass(DISABLED);timeBtn&&timeBtn.attr("lay-type")==="date"&&timeBtn[0].click();that.done(null,"change");lay(this).addClass(THIS);if(options.position!=="static"){that.setValue(that.parse()).done().remove()}})}lay.each(elemMain,function(i,main){elem.appendChild(main)});options.showBottom&&elem.appendChild(divFooter);var style=lay.elem("style");var styleText=[];var colorTheme;var isPrimaryColor=true;lay.each(options.theme,function(index,theme){if(isPrimaryColor&&/^#/.test(theme)){colorTheme=true;isPrimaryColor=false;styleText.push(["#{{id}} .layui-laydate-header{background-color:{{theme}};}","#{{id}} li.layui-this,#{{id}} td.layui-this>div{background-color:{{theme}} !important;}",options.theme.indexOf("circle")!==-1?"":"#{{id}} .layui-this{background-color:{{theme}} !important;}","#{{id}} .laydate-day-now{color:{{theme}} !important;}","#{{id}} .laydate-day-now:after{border-color:{{theme}} !important;}"].join("").replace(/{{id}}/g,that.elemID).replace(/{{theme}}/g,theme));return}if(!isPrimaryColor&&/^#/.test(theme)){styleText.push(["#{{id}} .laydate-selected>div{background-color:{{theme}} !important;}","#{{id}} .laydate-selected:hover>div{background-color:{{theme}} !important;}"].join("").replace(/{{id}}/g,that.elemID).replace(/{{theme}}/g,theme))}});if(options.shortcuts&&options.range){styleText.push("#{{id}}.layui-laydate-range{width: 628px;}".replace(/{{id}}/g,that.elemID))}if(styleText.length){styleText=styleText.join("");if("styleSheet" in style){style.setAttribute("type","text/css");style.styleSheet.cssText=styleText}else{style.innerHTML=styleText}colorTheme&&lay(elem).addClass("laydate-theme-molv");elem.appendChild(style)}that.remove(Class.thisElemDate);laydate.thisId=options.id;isStatic?options.elem.append(elem):(document.body.appendChild(elem),that.position());var shade=options.shade?('<div class="'+ELEM_SHADE+'" style="'+("z-index:"+(parseInt(layui.getStyle(elem,"z-index"))-1)+"; background-color: "+(options.shade[1]||"#000")+"; opacity: "+(options.shade[0]||options.shade))+'"></div>'):"";elem.insertAdjacentHTML("beforebegin",shade);that.checkDate().calendar(null,0,"init");that.changeEvent();Class.thisElemDate=that.elemID;that.renderAdditional();typeof options.ready==="function"&&options.ready(lay.extend({},options.dateTime,{month:options.dateTime.month+1}));that.preview()};Class.prototype.remove=function(prev){var that=this,options=that.config,elem=lay("#"+(prev||that.elemID));if(!elem[0]){return that}if(!elem.hasClass(ELEM_STATIC)){that.checkDate(function(){elem.remove();delete that.startDate;delete that.endDate;delete that.endState;delete that.startTime;delete that.endTime;delete laydate.thisId;typeof options.close==="function"&&options.close(that)})}lay("."+ELEM_SHADE).remove();return that};Class.prototype.position=function(){var that=this,options=that.config;lay.position(options.elem[0],that.elem,{position:options.position});return that};Class.prototype.hint=function(opts){var that=this;var options=that.config;var div=lay.elem("div",{"class":ELEM_HINT});if(!that.elem){return}if(typeof opts==="object"){opts=opts||{}}else{opts={content:opts}}div.innerHTML=opts.content||"";lay(that.elem).find("."+ELEM_HINT).remove();that.elem.appendChild(div);clearTimeout(that.hinTimer);that.hinTimer=setTimeout(function(){lay(that.elem).find("."+ELEM_HINT).remove()},"ms" in opts?opts.ms:3000)};Class.prototype.getAsYM=function(Y,M,type){type?M--:M++;if(M<0){M=11;Y--}if(M>11){M=0;Y++}return[Y,M]};Class.prototype.systemDate=function(newDate){var thisDate=newDate||new Date();return{year:thisDate.getFullYear(),month:thisDate.getMonth(),date:thisDate.getDate(),hours:newDate?newDate.getHours():0,minutes:newDate?newDate.getMinutes():0,seconds:newDate?newDate.getSeconds():0}};Class.prototype.checkDate=function(fn){var that=this,thisDate=new Date(),options=that.config,lang=that.lang(),dateTime=options.dateTime=options.dateTime||that.systemDate(),thisMaxDate,error,elem=options.elem[0],valType=that.isInput(elem)?"val":"html",value=function(){if(that.rangeElem){var vals=[that.rangeElem[0].val(),that.rangeElem[1].val()];if(vals[0]&&vals[1]){return vals.join(" "+that.rangeStr+" ")}}return that.isInput(elem)?elem.value:(options.position==="static"?"":lay(elem).attr("lay-date"))}(),checkValid=function(dateTime){if(!dateTime){return}if(dateTime.year>LIMIT_YEAR[1]){dateTime.year=LIMIT_YEAR[1],error=true}if(dateTime.month>11){dateTime.month=11,error=true}if(dateTime.seconds>59){dateTime.seconds=0,dateTime.minutes++,error=true}if(dateTime.minutes>59){dateTime.minutes=0,dateTime.hours++,error=true}if(dateTime.hours>23){dateTime.hours=0,error=true}thisMaxDate=laydate.getEndDate(dateTime.month+1,dateTime.year);if(dateTime.date>thisMaxDate){dateTime.date=thisMaxDate,error=true}},initDate=function(dateTime,value,index){var startEnd=["startTime","endTime"];value=(value.match(that.EXP_SPLIT)||[]).slice(1);index=index||0;if(options.range){that[startEnd[index]]=that[startEnd[index]]||{}}lay.each(that.format,function(i,item){var thisv=parseFloat(value[i]);if(value[i].length<item.length){error=true}if(/yyyy|y/.test(item)){if(thisv<LIMIT_YEAR[0]){thisv=LIMIT_YEAR[0],error=true}dateTime.year=thisv}else{if(/MM|M/.test(item)){if(thisv<1){thisv=1,error=true}dateTime.month=thisv-1}else{if(/dd|d/.test(item)){if(thisv<1){thisv=1,error=true}dateTime.date=thisv}else{if(/HH|H/.test(item)){if(thisv<0){thisv=0,error=true}if(thisv>23){thisv=23,error=true}dateTime.hours=thisv;options.range&&(that[startEnd[index]].hours=thisv)}else{if(/mm|m/.test(item)){if(thisv<0){thisv=0,error=true}if(thisv>59){thisv=59,error=true}dateTime.minutes=thisv;options.range&&(that[startEnd[index]].minutes=thisv)}else{if(/ss|s/.test(item)){if(thisv<0){thisv=0,error=true}if(thisv>59){thisv=59,error=true}dateTime.seconds=thisv;options.range&&(that[startEnd[index]].seconds=thisv)}}}}}}});checkValid(dateTime)};if(fn==="limit"){if(options.range){checkValid(that.rangeLinked?that.startDate:dateTime);that.endDate&&checkValid(that.endDate)}else{checkValid(dateTime)}return that}value=value||options.value;if(typeof value==="string"){value=value.replace(/\s+/g," ").replace(/^\s|\s$/g,"")}var getEndDate=function(){if(options.range){that.endDate=that.endDate||lay.extend({},options.dateTime,function(){var obj={},dateTime=options.dateTime,EYM=that.getAsYM(dateTime.year,dateTime.month);if(options.type==="year"){obj.year=dateTime.year+1}else{if(options.type!=="time"){obj.year=EYM[0];obj.month=EYM[1]}}if(options.type==="datetime"||options.type==="time"){obj.hours=23;obj.minutes=obj.seconds=59}return obj}())}};getEndDate();if(typeof value==="string"&&value){if(that.EXP_IF.test(value)){if(options.range){value=value.split(" "+that.rangeStr+" ");lay.each([options.dateTime,that.endDate],function(i,item){initDate(item,value[i],i)})}else{initDate(dateTime,value)}}else{that.hint(lang.formatError[0]+(options.range?(options.format+" "+that.rangeStr+" "+options.format):options.format)+lang.formatError[1]);error=true}}else{if(value&&layui.type(value)==="date"){options.dateTime=that.systemDate(value)}else{options.dateTime=that.systemDate();delete that.startTime;delete that.endDate;getEndDate();delete that.endTime}}(function(){if(that.rangeElem){var vals=[that.rangeElem[0].val(),that.rangeElem[1].val()],arrDate=[options.dateTime,that.endDate];lay.each(vals,function(_i,_v){if(that.EXP_IF_ONE.test(_v)){initDate(arrDate[_i],_v,_i)}})}})();checkValid(dateTime);if(options.range){checkValid(that.endDate)}if(error&&value){that.setValue(options.range?(that.endDate?that.parse():""):that.parse())}var minMaxError;if(that.getDateTime(dateTime)>that.getDateTime(options.max)){dateTime=options.dateTime=lay.extend({},options.max);minMaxError=true}else{if(that.getDateTime(dateTime)<that.getDateTime(options.min)){dateTime=options.dateTime=lay.extend({},options.min);minMaxError=true}}if(options.range){if(that.getDateTime(that.endDate)<that.getDateTime(options.min)||that.getDateTime(that.endDate)>that.getDateTime(options.max)){that.endDate=lay.extend({},options.max);minMaxError=true}that.startTime={hours:options.dateTime.hours,minutes:options.dateTime.minutes,seconds:options.dateTime.seconds,};that.endTime={hours:that.endDate.hours,minutes:that.endDate.minutes,seconds:that.endDate.seconds,};if(options.type==="month"){options.dateTime.date=1;that.endDate.date=1}}if(minMaxError&&value){that.setValue(that.parse());that.hint("value "+lang.invalidDate+lang.formatError[1])}that.startDate=that.startDate||value&&lay.extend({},options.dateTime);that.autoCalendarModel.auto&&that.autoCalendarModel();that.endState=!options.range||!that.rangeLinked||!!(that.startDate&&that.endDate);fn&&fn();return that};Class.prototype.mark=function(td,YMD){var that=this,mark,options=that.config;lay.each(options.mark,function(key,title){var keys=key.split("-");if((keys[0]==YMD[0]||keys[0]==0)&&(keys[1]==YMD[1]||keys[1]==0)&&keys[2]==YMD[2]){mark=title||YMD[2]}});mark&&td.find("div").html('<span class="laydate-day-mark">'+mark+"</span>");return that};Class.prototype.holidays=function(td,YMD){var that=this;var options=that.config;var type=["","work"];if(layui.type(options.holidays)!=="array"){return that}lay.each(options.holidays,function(idx,item){lay.each(item,function(i,dayStr){if(dayStr===td.attr("lay-ymd")){td.find("div").html('<span class="laydate-day-holidays"'+(type[idx]?('type="'+type[idx]+'"'):"")+">"+YMD[2]+"</span>")}})});return that};Class.prototype.limit=function(opts){opts=opts||{};var that=this;var options=that.config;var timestamp={};var dateTime=opts.index>(opts.time?0:41)?that.endDate:options.dateTime;var isOut;lay.each({now:lay.extend({},dateTime,opts.date||{}),min:options.min,max:options.max},function(key,item){timestamp[key]=that.newDate(lay.extend({year:item.year,month:opts.type==="year"?0:item.month,date:(opts.type==="year"||opts.type==="month")?1:item.date},function(){var hms={};lay.each(opts.time,function(i,keys){hms[keys]=item[keys]});return hms}())).getTime()});isOut=timestamp.now<timestamp.min||timestamp.now>timestamp.max;opts.elem&&opts.elem[isOut?"addClass":"removeClass"](DISABLED);return isOut};Class.prototype.thisDateTime=function(index){var that=this,options=that.config;return index?that.endDate:options.dateTime};Class.prototype.calendar=function(value,index,type){index=index?1:0;var that=this,options=that.config,dateTime=value||that.thisDateTime(index),thisDate=new Date(),startWeek,prevMaxDate,thisMaxDate,lang=that.lang(),isAlone=options.type!=="date"&&options.type!=="datetime",tds=lay(that.table[index]).find("td"),elemYM=lay(that.elemHeader[index][2]).find("span");if(dateTime.year<LIMIT_YEAR[0]){dateTime.year=LIMIT_YEAR[0],that.hint(lang.invalidDate)}if(dateTime.year>LIMIT_YEAR[1]){dateTime.year=LIMIT_YEAR[1],that.hint(lang.invalidDate)}if(!that.firstDate){that.firstDate=lay.extend({},dateTime)}thisDate.setFullYear(dateTime.year,dateTime.month,1);startWeek=(thisDate.getDay()+(7-options.weekStart))%7;prevMaxDate=laydate.getEndDate(dateTime.month||12,dateTime.year);thisMaxDate=laydate.getEndDate(dateTime.month+1,dateTime.year);lay.each(tds,function(index_,item){var YMD=[dateTime.year,dateTime.month],st;item=lay(item);item.removeAttr("class");if(index_<startWeek){st=prevMaxDate-startWeek+index_;item.addClass("laydate-day-prev");YMD=that.getAsYM(dateTime.year,dateTime.month,"sub")}else{if(index_>=startWeek&&index_<thisMaxDate+startWeek){st=index_-startWeek;if(!that.rangeLinked){st+1===dateTime.date&&item.addClass(THIS)}}else{st=index_-thisMaxDate-startWeek;item.addClass("laydate-day-next");YMD=that.getAsYM(dateTime.year,dateTime.month)}}YMD[1]++;YMD[2]=st+1;item.attr("lay-ymd",YMD.join("-")).html("<div>"+YMD[2]+"</div>");that.mark(item,YMD).holidays(item,YMD).limit({elem:item,date:{year:YMD[0],month:YMD[1]-1,date:YMD[2]},index:index_})});lay(elemYM[0]).attr("lay-ym",dateTime.year+"-"+(dateTime.month+1));lay(elemYM[1]).attr("lay-ym",dateTime.year+"-"+(dateTime.month+1));if(options.lang==="cn"){lay(elemYM[0]).attr("lay-type","year").html(dateTime.year+" 年");lay(elemYM[1]).attr("lay-type","month").html((dateTime.month+1)+" 月")}else{lay(elemYM[0]).attr("lay-type","month").html(lang.month[dateTime.month]);lay(elemYM[1]).attr("lay-type","year").html(dateTime.year)}if(isAlone){if(options.range){if(value||type!=="init"){that.listYM=[[(that.startDate||options.dateTime).year,(that.startDate||options.dateTime).month+1],[that.endDate.year,that.endDate.month+1]];that.list(options.type,0).list(options.type,1);options.type==="time"?that.setBtnStatus("时间",lay.extend({},that.systemDate(),that.startTime),lay.extend({},that.systemDate(),that.endTime)):that.setBtnStatus(true)}}else{that.listYM=[[dateTime.year,dateTime.month+1]];that.list(options.type,0)}}if(options.range&&type==="init"){if(that.rangeLinked){var EYM=that.getAsYM(dateTime.year,dateTime.month,index?"sub":null);that.calendar(lay.extend({},dateTime,{year:EYM[0],month:EYM[1]}),1-index)}else{that.calendar(null,1-index)}}if(!options.range){var timeParams=["hours","minutes","seconds"];that.limit({elem:lay(that.footer).find(ELEM_NOW),date:that.systemDate(/^(datetime|time)$/.test(options.type)?new Date():null),index:0,time:timeParams});that.limit({elem:lay(that.footer).find(ELEM_CONFIRM),index:0,time:timeParams})}that.setBtnStatus();lay(that.shortcut).find("li."+THIS).removeClass(THIS);if(options.range&&!isAlone&&type!=="init"){that.stampRange()}return that};Class.prototype.list=function(type,index){var that=this,options=that.config,dateTime=that.rangeLinked?options.dateTime:[options.dateTime,that.endDate][index],lang=that.lang(),isAlone=options.range&&options.type!=="date"&&options.type!=="datetime",ul=lay.elem("ul",{"class":ELEM_LIST+" "+({year:"laydate-year-list",month:"laydate-month-list",time:"laydate-time-list"})[type]}),elemHeader=that.elemHeader[index],elemYM=lay(elemHeader[2]).find("span"),elemCont=that.elemCont[index||0],haveList=lay(elemCont).find("."+ELEM_LIST)[0],isCN=options.lang==="cn",text=isCN?"年":"",listYM=that.listYM[index]||{},hms=["hours","minutes","seconds"],startEnd=["startTime","endTime"][index];if(listYM[0]<1){listYM[0]=1}if(type==="year"){var yearNum,startY=yearNum=listYM[0]-7;if(startY<1){startY=yearNum=1}lay.each(new Array(15),function(i){var li=lay.elem("li",{"lay-ym":yearNum}),ymd={year:yearNum,month:0,date:1};yearNum==listYM[0]&&lay(li).addClass(THIS);li.innerHTML=yearNum+text;ul.appendChild(li);that.limit({elem:lay(li),date:ymd,index:index,type:type});yearNum++});lay(elemYM[isCN?0:1]).attr("lay-ym",(yearNum-8)+"-"+listYM[1]).html((startY+text)+" - "+(yearNum-1+text))}else{if(type==="month"){lay.each(new Array(12),function(i){var li=lay.elem("li",{"lay-ym":i}),ymd={year:listYM[0],month:i,date:1};i+1==listYM[1]&&lay(li).addClass(THIS);li.innerHTML=lang.month[i]+(isCN?"月":"");ul.appendChild(li);that.limit({elem:lay(li),date:ymd,index:index,type:type})});lay(elemYM[isCN?0:1]).attr("lay-ym",listYM[0]+"-"+listYM[1]).html(listYM[0]+text)}else{if(type==="time"){var setTimeStatus=function(){lay(ul).find("ol").each(function(i,ol){lay(ol).find("li").each(function(ii,li){that.limit({elem:lay(li),date:[{hours:ii},{hours:that[startEnd].hours,minutes:ii},{hours:that[startEnd].hours,minutes:that[startEnd].minutes,seconds:ii}][i],index:index,time:[["hours"],["hours","minutes"],["hours","minutes","seconds"]][i]})})});if(!options.range){that.limit({elem:lay(that.footer).find(ELEM_CONFIRM),date:that[startEnd],inedx:0,time:["hours","minutes","seconds"]})}};if(options.range){if(!that[startEnd]){that[startEnd]=startEnd==="startTime"?dateTime:that.endDate}}else{that[startEnd]=dateTime}lay.each([24,60,60],function(i,item){var li=lay.elem("li"),childUL=["<p>"+lang.time[i]+"</p><ol>"];lay.each(new Array(item),function(ii){childUL.push("<li"+(that[startEnd][hms[i]]===ii?' class="'+THIS+'"':"")+">"+lay.digit(ii,2)+"</li>")});li.innerHTML=childUL.join("")+"</ol>";ul.appendChild(li)});setTimeStatus()}}}if(haveList){elemCont.removeChild(haveList)}elemCont.appendChild(ul);if(type==="year"||type==="month"){lay(that.elemMain[index]).addClass("laydate-ym-show");lay(ul).find("li").on("click",function(){var ym=lay(this).attr("lay-ym")|0;if(lay(this).hasClass(DISABLED)){return}if(that.rangeLinked){lay.extend(dateTime,{year:type==="year"?ym:listYM[0],month:type==="year"?listYM[1]-1:ym})}else{dateTime[type]=ym}var isYearOrMonth=options.type==="year"||options.type==="month";if(isYearOrMonth){lay(ul).find("."+THIS).removeClass(THIS);lay(this).addClass(THIS);if(options.type==="month"&&type==="year"){that.listYM[index][0]=ym;isAlone&&((index?that.endDate:dateTime).year=ym);that.list("month",index)}}else{that.checkDate("limit").calendar(dateTime,index,"init");that.closeList()}that.setBtnStatus();if(!options.range&&options.autoConfirm){if((options.type==="month"&&type==="month")||(options.type==="year"&&type==="year")){that.setValue(that.parse()).done().remove()}}(that.autoCalendarModel.auto&&!that.rangeLinked)?that.choose(lay(elemCont).find("td.layui-this"),index):(that.endState&&that.done(null,"change"));lay(that.footer).find("."+ELEM_TIME_BTN).removeClass(DISABLED)})}else{var span=lay.elem("span",{"class":ELEM_TIME_TEXT}),scroll=function(){lay(ul).find("ol").each(function(i){var ol=this,li=lay(ol).find("li");ol.scrollTop=30*(that[startEnd][hms[i]]-2);if(ol.scrollTop<=0){li.each(function(ii,item){if(!lay(this).hasClass(DISABLED)){ol.scrollTop=30*(ii-2);return true}})}})},haveSpan=lay(elemHeader[2]).find("."+ELEM_TIME_TEXT);scroll();span.innerHTML=options.range?[lang.startTime,lang.endTime][index]:lang.timeTips;lay(that.elemMain[index]).addClass("laydate-time-show");if(haveSpan[0]){haveSpan.remove()}elemHeader[2].appendChild(span);lay(ul).find("ol").each(function(i){var ol=this;lay(ol).find("li").on("click",function(){var value=this.innerHTML|0;if(lay(this).hasClass(DISABLED)){return}if(options.range){that[startEnd][hms[i]]=value}else{dateTime[hms[i]]=value}lay(ol).find("."+THIS).removeClass(THIS);lay(this).addClass(THIS);setTimeStatus();scroll();(that.endDate||options.type==="time"||(options.type==="datetime"&&options.fullPanel))&&that.done(null,"change");that.setBtnStatus()})})}return that};Class.prototype.listYM=[];Class.prototype.closeList=function(){var that=this,options=that.config;lay.each(that.elemCont,function(index,item){lay(this).find("."+ELEM_LIST).remove();lay(that.elemMain[index]).removeClass("laydate-ym-show laydate-time-show")});lay(that.elem).find("."+ELEM_TIME_TEXT).remove()};Class.prototype.setBtnStatus=function(tips,start,end){var that=this,options=that.config,lang=that.lang(),isOut,elemBtn=lay(that.footer).find(ELEM_CONFIRM);if(options.range&&options.type!=="time"){start=start||(that.rangeLinked?that.startDate:options.dateTime);end=end||that.endDate;isOut=!that.endState||that.newDate(start).getTime()>that.newDate(end).getTime();(that.limit({date:start})||that.limit({date:end}))?elemBtn.addClass(DISABLED):elemBtn[isOut?"addClass":"removeClass"](DISABLED);if(tips&&isOut){that.hint(typeof tips==="string"?lang.timeout.replace(/日期/g,tips):lang.timeout)}}};Class.prototype.parse=function(state,date){var that=this;var options=that.config;var startDate=(that.rangeLinked?that.startDate:options.dateTime);var dateTime=date||(state=="end"?lay.extend({},that.endDate,that.endTime):(options.range?lay.extend({},startDate||options.dateTime,that.startTime):options.dateTime));var format=laydate.parse(dateTime,that.format,1);if(options.range&&state===undefined){return format+" "+that.rangeStr+" "+that.parse("end")}return format};Class.prototype.newDate=function(dateTime){dateTime=dateTime||{};return new Date(dateTime.year||1,dateTime.month||0,dateTime.date||1,dateTime.hours||0,dateTime.minutes||0,dateTime.seconds||0)};Class.prototype.getDateTime=function(obj){return this.newDate(obj).getTime()};Class.prototype.setValue=function(value){var that=this,options=that.config,elem=options.elem[0];if(options.position==="static"){return that}value=value||"";if(that.isInput(elem)){lay(elem).val(value)}else{var rangeElem=that.rangeElem;if(rangeElem){if(layui.type(value)!=="array"){value=value.split(" "+that.rangeStr+" ")}rangeElem[0].val(value[0]||"");rangeElem[1].val(value[1]||"")}else{if(lay(elem).find("*").length===0){lay(elem).html(value)}lay(elem).attr("lay-date",value)}}return that};Class.prototype.preview=function(){var that=this,options=that.config;if(!options.isPreview){return}var elemPreview=lay(that.elem).find("."+ELEM_PREVIEW),value=options.range?((that.rangeLinked?that.endState:that.endDate)?that.parse():""):that.parse();elemPreview.html(value);var oldValue=elemPreview.html();oldValue&&(elemPreview.css({"color":"#16b777"}),setTimeout(function(){elemPreview.css({"color":"#777"})},300))};Class.prototype.renderAdditional=function(){var that=this;var options=that.config;if(options.fullPanel){that.list("time",0)}};Class.prototype.stampRange=function(){var that=this,options=that.config,startTime=that.rangeLinked?that.startDate:options.dateTime,endTime,tds=lay(that.elem).find("td");if(options.range&&!that.endState){lay(that.footer).find(ELEM_CONFIRM).addClass(DISABLED)}startTime=startTime&&that.newDate({year:startTime.year,month:startTime.month,date:startTime.date}).getTime();endTime=that.endState&&that.endDate&&that.newDate({year:that.endDate.year,month:that.endDate.month,date:that.endDate.date}).getTime();lay.each(tds,function(i,item){var ymd=lay(item).attr("lay-ymd").split("-");var thisTime=that.newDate({year:ymd[0],month:ymd[1]-1,date:ymd[2]}).getTime();if(options.rangeLinked&&!that.startDate){if(thisTime===that.newDate(that.systemDate()).getTime()){lay(item).addClass(lay(item).hasClass(ELEM_PREV)||lay(item).hasClass(ELEM_NEXT)?"":ELEM_DAY_NOW)}}lay(item).removeClass(ELEM_SELECTED+" "+THIS);if(thisTime===startTime||thisTime===endTime){(that.rangeLinked||(!that.rangeLinked&&(i<42?thisTime===startTime:thisTime===endTime)))&&lay(item).addClass(lay(item).hasClass(ELEM_PREV)||lay(item).hasClass(ELEM_NEXT)?ELEM_SELECTED:THIS)}if(thisTime>startTime&&thisTime<endTime){lay(item).addClass(ELEM_SELECTED)}})};Class.prototype.done=function(param,type){var that=this;var options=that.config;var start=lay.extend({},lay.extend(that.rangeLinked?that.startDate:options.dateTime,that.startTime));var end=lay.extend({},lay.extend(that.endDate,that.endTime));lay.each([start,end],function(i,item){if(!("month" in item)){return}lay.extend(item,{month:item.month+1})});that.preview();param=param||[that.parse(),start,end];type==="change"&&that.renderAdditional();typeof options[type||"done"]==="function"&&options[type||"done"].apply(options,param);return that};Class.prototype.choose=function(td,index){if(td.hasClass(DISABLED)){return}var that=this,options=that.config,panelIndex=index;if(that.rangeLinked){if(that.endState||!that.startDate){index=0;that.endState=false;that.endDate={}}else{index=1;that.endState=true}}var dateTime=that.thisDateTime(index),tds=lay(that.elem).find("td"),YMD=td.attr("lay-ymd").split("-");YMD={year:YMD[0]|0,month:(YMD[1]|0)-1,date:YMD[2]|0};lay.extend(dateTime,YMD);if(options.range){lay.each(["startTime","endTime"],function(i,item){that[item]=that[item]||{hours:i?23:0,minutes:i?59:0,seconds:i?59:0};if(index===i){if(that.getDateTime(lay.extend({},dateTime,that[item]))<that.getDateTime(options.min)){that[item]={hours:options.min.hours,minutes:options.min.minutes,seconds:options.min.seconds};lay.extend(dateTime,that[item])}else{if(that.getDateTime(lay.extend({},dateTime,that[item]))>that.getDateTime(options.max)){that[item]={hours:options.max.hours,minutes:options.max.minutes,seconds:options.max.seconds};lay.extend(dateTime,that[item])}}}});if(!index){that.startDate=lay.extend({},dateTime)}if(that.endState&&!that.limit({date:that.thisDateTime(1-index)})){var isChange;if(that.endState&&that.autoCalendarModel.auto){isChange=that.autoCalendarModel()}if((isChange||that.rangeLinked&&that.endState)&&that.newDate(that.startDate)>that.newDate(that.endDate)){var isSameDate=that.startDate.year===that.endDate.year&&that.startDate.month===that.endDate.month&&that.startDate.date===that.endDate.date;var startDate=that.startDate;that.startDate=lay.extend({},that.endDate,isSameDate?{}:that.startTime);options.dateTime=lay.extend({},that.startDate);that.endDate=lay.extend({},startDate,isSameDate?{}:that.endTime);isSameDate&&(startDate=that.startTime,that.startTime=that.endTime,that.endTime=startDate)}isChange&&(options.dateTime=lay.extend({},that.startDate))}if(that.rangeLinked){var dateTimeTemp=lay.extend({},dateTime);if(panelIndex&&!index&&!isChange){var YM=that.getAsYM(dateTime.year,dateTime.month,"sub");lay.extend(options.dateTime,{year:YM[0],month:YM[1]})}that.calendar(dateTimeTemp,panelIndex,isChange?"init":null)}else{that.calendar(null,index,isChange?"init":null)}that.endState&&that.done(null,"change")}else{if(options.position==="static"){that.calendar().done().done(null,"change")}else{if(options.type==="date"){options.autoConfirm?that.setValue(that.parse()).done().remove():that.calendar().done(null,"change")}else{if(options.type==="datetime"){that.calendar().done(null,"change")}}}}};Class.prototype.tool=function(btn,type){var that=this,options=that.config,lang=that.lang(),dateTime=options.dateTime,isStatic=options.position==="static",active={datetime:function(){if(lay(btn).hasClass(DISABLED)){return}that.list("time",0);options.range&&that.list("time",1);lay(btn).attr("lay-type","date").html(that.lang().dateTips)},date:function(){that.closeList();lay(btn).attr("lay-type","datetime").html(that.lang().timeTips)},clear:function(){isStatic&&(lay.extend(dateTime,that.firstDate),that.calendar());options.range&&(delete options.dateTime,delete that.endDate,delete that.startTime,delete that.endTime);that.setValue("");that.done(null,"onClear").done(["",{},{}]).remove()},now:function(){var thisDate=new Date();if(lay(btn).hasClass(DISABLED)){return that.hint(lang.tools.now+", "+lang.invalidDate)}lay.extend(dateTime,that.systemDate(),{hours:thisDate.getHours(),minutes:thisDate.getMinutes(),seconds:thisDate.getSeconds()});that.setValue(that.parse());isStatic&&that.calendar();that.done(null,"onNow").done().remove()},confirm:function(){if(options.range){if(lay(btn).hasClass(DISABLED)){return that.hint(options.type==="time"?lang.timeout.replace(/日期/g,"时间"):lang.timeout)}}else{if(lay(btn).hasClass(DISABLED)){return that.hint(lang.invalidDate)}}that.setValue(that.parse());that.done(null,"onConfirm").done().remove()}};active[type]&&active[type]()};Class.prototype.change=function(index){var that=this,options=that.config,dateTime=that.thisDateTime(index),isAlone=options.range&&(options.type==="year"||options.type==="month"),elemCont=that.elemCont[index||0],listYM=that.listYM[index],addSubYear=function(type){var isYear=lay(elemCont).find(".laydate-year-list")[0],isMonth=lay(elemCont).find(".laydate-month-list")[0];if(isYear){listYM[0]=type?listYM[0]-15:listYM[0]+15;that.list("year",index)}if(isMonth){type?listYM[0]--:listYM[0]++;that.list("month",index)}if(isYear||isMonth){lay.extend(dateTime,{year:listYM[0]});if(isAlone){dateTime.year=listYM[0]}options.range||that.done(null,"change");options.range||that.limit({elem:lay(that.footer).find(ELEM_CONFIRM),date:{year:listYM[0]}})}that.setBtnStatus();return isYear||isMonth};return{prevYear:function(){if(addSubYear("sub")){return}if(that.rangeLinked){options.dateTime.year--;that.checkDate("limit").calendar(null,null,"init")}else{dateTime.year--;that.checkDate("limit").calendar(null,index);that.autoCalendarModel.auto?that.choose(lay(elemCont).find("td.layui-this"),index):that.done(null,"change")}},prevMonth:function(){if(that.rangeLinked){dateTime=options.dateTime}var YM=that.getAsYM(dateTime.year,dateTime.month,"sub");lay.extend(dateTime,{year:YM[0],month:YM[1]});that.checkDate("limit").calendar(null,null,"init");if(!that.rangeLinked){that.autoCalendarModel.auto?that.choose(lay(elemCont).find("td.layui-this"),index):that.done(null,"change")}},nextMonth:function(){if(that.rangeLinked){dateTime=options.dateTime}var YM=that.getAsYM(dateTime.year,dateTime.month);lay.extend(dateTime,{year:YM[0],month:YM[1]});that.checkDate("limit").calendar(null,null,"init");if(!that.rangeLinked){that.autoCalendarModel.auto?that.choose(lay(elemCont).find("td.layui-this"),index):that.done(null,"change")}},nextYear:function(){if(addSubYear()){return}if(that.rangeLinked){options.dateTime.year++;that.checkDate("limit").calendar(null,0,"init")}else{dateTime.year++;that.checkDate("limit").calendar(null,index);that.autoCalendarModel.auto?that.choose(lay(elemCont).find("td.layui-this"),index):that.done(null,"change")}}}};Class.prototype.changeEvent=function(){var that=this,options=that.config;lay(that.elem).on("click",function(e){lay.stope(e)}).on("mousedown",function(e){lay.stope(e)});lay.each(that.elemHeader,function(i,header){lay(header[0]).on("click",function(e){that.change(i).prevYear()});lay(header[1]).on("click",function(e){that.change(i).prevMonth()});lay(header[2]).find("span").on("click",function(e){var othis=lay(this),layYM=othis.attr("lay-ym"),layType=othis.attr("lay-type");if(!layYM){return}layYM=layYM.split("-");that.listYM[i]=[layYM[0]|0,layYM[1]|0];that.list(layType,i);lay(that.footer).find("."+ELEM_TIME_BTN).addClass(DISABLED)});lay(header[3]).on("click",function(e){that.change(i).nextMonth()});lay(header[4]).on("click",function(e){that.change(i).nextYear()})});lay.each(that.table,function(i,table){var tds=lay(table).find("td");tds.on("click",function(){that.choose(lay(this),i)})});lay(that.footer).find("span").on("click",function(){var type=lay(this).attr("lay-type");that.tool(this,type)})};Class.prototype.isInput=function(elem){return/input|textarea/.test(elem.tagName.toLocaleLowerCase())||/INPUT|TEXTAREA/.test(elem.tagName)};Class.prototype.events=function(){var that=this;var options=that.config;if(!options.elem[0]||options.elem[0].eventHandler){return}var showEvent=function(){if(laydate.thisId===options.id){return}that.render()};options.elem.on(options.trigger,showEvent);options.elem[0].eventHandler=true;options.eventElem.on(options.trigger,showEvent);that.unbind=function(){that.remove();options.elem.off(options.trigger,showEvent);options.elem.removeAttr("lay-key");options.elem.removeAttr(MOD_ID);options.elem[0].eventHandler=false;options.eventElem.off(options.trigger,showEvent);options.eventElem.removeAttr("lay-key");delete thisModule.that[options.id]}};thisModule.that={};thisModule.getThis=function(id){var that=thisModule.that[id];if(!that&&isLayui){layui.hint().error(id?(MOD_NAME+" instance with ID '"+id+"' not found"):"ID argument required")}return that};ready.run=function(lay){lay(document).on("mousedown",function(e){if(!laydate.thisId){return}var that=thisModule.getThis(laydate.thisId);if(!that){return}var options=that.config;if(e.target===options.elem[0]||e.target===options.eventElem[0]||e.target===lay(options.closeStop)[0]||(options.elem[0]&&options.elem[0].contains(e.target))){return}that.remove()}).on("keydown",function(e){if(!laydate.thisId){return}var that=thisModule.getThis(laydate.thisId);if(!that){return}if(that.config.position==="static"){return}if(e.keyCode===13){if(lay("#"+that.elemID)[0]&&that.elemID===Class.thisElemDate){e.preventDefault();lay(that.footer).find(ELEM_CONFIRM)[0].click()}}});lay(window).on("resize",function(){if(!laydate.thisId){return}var that=thisModule.getThis(laydate.thisId);if(!that){return}if(!that.elem||!lay(ELEM)[0]){return false}that.position()})};laydate.render=function(options){var inst=new Class(options);return thisModule.call(inst)};laydate.reload=function(id,options){var that=thisModule.getThis(id);if(!that){return}return that.reload(options)};laydate.getInst=function(id){var that=thisModule.getThis(id);if(that){return that.inst}};laydate.hint=function(id,opts){var that=thisModule.getThis(id);if(!that){return}return that.hint(opts)};laydate.unbind=function(id){var that=thisModule.getThis(id);if(!that){return}return that.unbind()};laydate.close=function(id){var that=thisModule.getThis(id||laydate.thisId);if(!that){return}return that.remove()};laydate.parse=function(dateTime,format,one){dateTime=dateTime||{};if(typeof format==="string"){format=thisModule.formatArr(format)}format=(format||[]).concat();lay.each(format,function(i,item){if(/yyyy|y/.test(item)){format[i]=lay.digit(dateTime.year,item.length)}else{if(/MM|M/.test(item)){format[i]=lay.digit(dateTime.month+(one||0),item.length)}else{if(/dd|d/.test(item)){format[i]=lay.digit(dateTime.date,item.length)}else{if(/HH|H/.test(item)){format[i]=lay.digit(dateTime.hours,item.length)}else{if(/mm|m/.test(item)){format[i]=lay.digit(dateTime.minutes,item.length)}else{if(/ss|s/.test(item)){format[i]=lay.digit(dateTime.seconds,item.length)}}}}}}});return format.join("")};laydate.getEndDate=function(month,year){var thisDate=new Date();thisDate.setFullYear(year||thisDate.getFullYear(),month||(thisDate.getMonth()+1),1);return new Date(thisDate.getTime()-1000*60*60*24).getDate()};isLayui?(laydate.ready(),layui.define("lay",function(exports){laydate.path=layui.cache.dir;ready.run(lay);exports(MOD_NAME,laydate)})):((typeof define==="function"&&define.amd)?define(function(){ready.run(lay);return laydate}):function(){laydate.ready();ready.run(window.lay);window.laydate=laydate}())}(window,window.document);
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/report/echarts/echarts-all.min.js b/ruoyi-admin/src/main/resources/static/ajax/libs/report/echarts/echarts-all.min.js
new file mode 100644
index 0000000..b736651
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/report/echarts/echarts-all.min.js
@@ -0,0 +1,52 @@
+
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied.  See the License for the
+* specific language governing permissions and limitations
+* under the License.
+* version 4.2.1
+*/
+
+
+!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e(t.echarts={})}(this,function(t){"use strict";function e(t,e){"createCanvas"===t&&(nw=null),ew[t]=e}function i(t){if(null==t||"object"!=typeof t)return t;var e=t,n=Y_.call(t);if("[object Array]"===n){if(!O(t)){e=[];for(var o=0,a=t.length;o<a;o++)e[o]=i(t[o])}}else if(j_[n]){if(!O(t)){var r=t.constructor;if(t.constructor.from)e=r.from(t);else{e=new r(t.length);for(var o=0,a=t.length;o<a;o++)e[o]=i(t[o])}}}else if(!X_[n]&&!O(t)&&!M(t)){e={};for(var s in t)t.hasOwnProperty(s)&&(e[s]=i(t[s]))}return e}function n(t,e,o){if(!w(e)||!w(t))return o?i(e):t;for(var a in e)if(e.hasOwnProperty(a)){var r=t[a],s=e[a];!w(s)||!w(r)||y(s)||y(r)||M(s)||M(r)||b(s)||b(r)||O(s)||O(r)?!o&&a in t||(t[a]=i(e[a],!0)):n(r,s,o)}return t}function o(t,e){for(var i=t[0],o=1,a=t.length;o<a;o++)i=n(i,t[o],e);return i}function a(t,e){for(var i in e)e.hasOwnProperty(i)&&(t[i]=e[i]);return t}function r(t,e,i){for(var n in e)e.hasOwnProperty(n)&&(i?null!=e[n]:null==t[n])&&(t[n]=e[n]);return t}function s(){return nw||(nw=iw().getContext("2d")),nw}function l(t,e){if(t){if(t.indexOf)return t.indexOf(e);for(var i=0,n=t.length;i<n;i++)if(t[i]===e)return i}return-1}function u(t,e){function i(){}var n=t.prototype;i.prototype=e.prototype,t.prototype=new i;for(var o in n)t.prototype[o]=n[o];t.prototype.constructor=t,t.superClass=e}function h(t,e,i){r(t="prototype"in t?t.prototype:t,e="prototype"in e?e.prototype:e,i)}function c(t){if(t)return"string"!=typeof t&&"number"==typeof t.length}function d(t,e,i){if(t&&e)if(t.forEach&&t.forEach===K_)t.forEach(e,i);else if(t.length===+t.length)for(var n=0,o=t.length;n<o;n++)e.call(i,t[n],n,t);else for(var a in t)t.hasOwnProperty(a)&&e.call(i,t[a],a,t)}function f(t,e,i){if(t&&e){if(t.map&&t.map===Q_)return t.map(e,i);for(var n=[],o=0,a=t.length;o<a;o++)n.push(e.call(i,t[o],o,t));return n}}function p(t,e,i,n){if(t&&e){if(t.reduce&&t.reduce===tw)return t.reduce(e,i,n);for(var o=0,a=t.length;o<a;o++)i=e.call(n,i,t[o],o,t);return i}}function g(t,e,i){if(t&&e){if(t.filter&&t.filter===$_)return t.filter(e,i);for(var n=[],o=0,a=t.length;o<a;o++)e.call(i,t[o],o,t)&&n.push(t[o]);return n}}function m(t,e){var i=J_.call(arguments,2);return function(){return t.apply(e,i.concat(J_.call(arguments)))}}function v(t){var e=J_.call(arguments,1);return function(){return t.apply(this,e.concat(J_.call(arguments)))}}function y(t){return"[object Array]"===Y_.call(t)}function x(t){return"function"==typeof t}function _(t){return"[object String]"===Y_.call(t)}function w(t){var e=typeof t;return"function"===e||!!t&&"object"===e}function b(t){return!!X_[Y_.call(t)]}function S(t){return!!j_[Y_.call(t)]}function M(t){return"object"==typeof t&&"number"==typeof t.nodeType&&"object"==typeof t.ownerDocument}function I(t){return t!==t}function T(t){for(var e=0,i=arguments.length;e<i;e++)if(null!=arguments[e])return arguments[e]}function A(t,e){return null!=t?t:e}function D(t,e,i){return null!=t?t:null!=e?e:i}function C(){return Function.call.apply(J_,arguments)}function L(t){if("number"==typeof t)return[t,t,t,t];var e=t.length;return 2===e?[t[0],t[1],t[0],t[1]]:3===e?[t[0],t[1],t[2],t[1]]:t}function k(t,e){if(!t)throw new Error(e)}function P(t){return null==t?null:"function"==typeof t.trim?t.trim():t.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"")}function N(t){t[ow]=!0}function O(t){return t[ow]}function E(t){function e(t,e){i?n.set(t,e):n.set(e,t)}var i=y(t);this.data={};var n=this;t instanceof E?t.each(e):t&&d(t,e)}function R(t){return new E(t)}function z(t,e){for(var i=new t.constructor(t.length+e.length),n=0;n<t.length;n++)i[n]=t[n];var o=t.length;for(n=0;n<e.length;n++)i[n+o]=e[n];return i}function B(){}function V(t,e){var i=new rw(2);return null==t&&(t=0),null==e&&(e=0),i[0]=t,i[1]=e,i}function G(t,e){return t[0]=e[0],t[1]=e[1],t}function F(t){var e=new rw(2);return e[0]=t[0],e[1]=t[1],e}function W(t,e,i){return t[0]=e,t[1]=i,t}function H(t,e,i){return t[0]=e[0]+i[0],t[1]=e[1]+i[1],t}function Z(t,e,i,n){return t[0]=e[0]+i[0]*n,t[1]=e[1]+i[1]*n,t}function U(t,e,i){return t[0]=e[0]-i[0],t[1]=e[1]-i[1],t}function X(t){return Math.sqrt(j(t))}function j(t){return t[0]*t[0]+t[1]*t[1]}function Y(t,e,i){return t[0]=e[0]*i,t[1]=e[1]*i,t}function q(t,e){var i=X(e);return 0===i?(t[0]=0,t[1]=0):(t[0]=e[0]/i,t[1]=e[1]/i),t}function K(t,e){return Math.sqrt((t[0]-e[0])*(t[0]-e[0])+(t[1]-e[1])*(t[1]-e[1]))}function $(t,e){return(t[0]-e[0])*(t[0]-e[0])+(t[1]-e[1])*(t[1]-e[1])}function J(t,e,i,n){return t[0]=e[0]+n*(i[0]-e[0]),t[1]=e[1]+n*(i[1]-e[1]),t}function Q(t,e,i){var n=e[0],o=e[1];return t[0]=i[0]*n+i[2]*o+i[4],t[1]=i[1]*n+i[3]*o+i[5],t}function tt(t,e,i){return t[0]=Math.min(e[0],i[0]),t[1]=Math.min(e[1],i[1]),t}function et(t,e,i){return t[0]=Math.max(e[0],i[0]),t[1]=Math.max(e[1],i[1]),t}function it(){this.on("mousedown",this._dragStart,this),this.on("mousemove",this._drag,this),this.on("mouseup",this._dragEnd,this),this.on("globalout",this._dragEnd,this)}function nt(t,e){return{target:t,topTarget:e&&e.topTarget}}function ot(t,e){var i=t._$eventProcessor;return null!=e&&i&&i.normalizeQuery&&(e=i.normalizeQuery(e)),e}function at(t,e,i,n,o,a){var r=t._$handlers;if("function"==typeof i&&(o=n,n=i,i=null),!n||!e)return t;i=ot(t,i),r[e]||(r[e]=[]);for(var s=0;s<r[e].length;s++)if(r[e][s].h===n)return t;var l={h:n,one:a,query:i,ctx:o||t,callAtLast:n.zrEventfulCallAtLast},u=r[e].length-1,h=r[e][u];return h&&h.callAtLast?r[e].splice(u,0,l):r[e].push(l),t}function rt(t){return t.getBoundingClientRect?t.getBoundingClientRect():{left:0,top:0}}function st(t,e,i,n){return i=i||{},n||!U_.canvasSupported?lt(t,e,i):U_.browser.firefox&&null!=e.layerX&&e.layerX!==e.offsetX?(i.zrX=e.layerX,i.zrY=e.layerY):null!=e.offsetX?(i.zrX=e.offsetX,i.zrY=e.offsetY):lt(t,e,i),i}function lt(t,e,i){var n=rt(t);i.zrX=e.clientX-n.left,i.zrY=e.clientY-n.top}function ut(t,e,i){if(null!=(e=e||window.event).zrX)return e;var n=e.type;if(n&&n.indexOf("touch")>=0){var o="touchend"!==n?e.targetTouches[0]:e.changedTouches[0];o&&st(t,o,e,i)}else st(t,e,e,i),e.zrDelta=e.wheelDelta?e.wheelDelta/120:-(e.detail||0)/3;var a=e.button;return null==e.which&&void 0!==a&&gw.test(e.type)&&(e.which=1&a?1:2&a?3:4&a?2:0),e}function ht(t,e,i){pw?t.addEventListener(e,i):t.attachEvent("on"+e,i)}function ct(t,e,i){pw?t.removeEventListener(e,i):t.detachEvent("on"+e,i)}function dt(t){return 2===t.which||3===t.which}function ft(t){var e=t[1][0]-t[0][0],i=t[1][1]-t[0][1];return Math.sqrt(e*e+i*i)}function pt(t){return[(t[0][0]+t[1][0])/2,(t[0][1]+t[1][1])/2]}function gt(t,e,i){return{type:t,event:i,target:e.target,topTarget:e.topTarget,cancelBubble:!1,offsetX:i.zrX,offsetY:i.zrY,gestureEvent:i.gestureEvent,pinchX:i.pinchX,pinchY:i.pinchY,pinchScale:i.pinchScale,wheelDelta:i.zrDelta,zrByTouch:i.zrByTouch,which:i.which,stop:mt}}function mt(t){mw(this.event)}function vt(){}function yt(t,e,i){if(t[t.rectHover?"rectContain":"contain"](e,i)){for(var n,o=t;o;){if(o.clipPath&&!o.clipPath.contain(e,i))return!1;o.silent&&(n=!0),o=o.parent}return!n||xw}return!1}function xt(){var t=new bw(6);return _t(t),t}function _t(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t[4]=0,t[5]=0,t}function wt(t,e){return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[3],t[4]=e[4],t[5]=e[5],t}function bt(t,e,i){var n=e[0]*i[0]+e[2]*i[1],o=e[1]*i[0]+e[3]*i[1],a=e[0]*i[2]+e[2]*i[3],r=e[1]*i[2]+e[3]*i[3],s=e[0]*i[4]+e[2]*i[5]+e[4],l=e[1]*i[4]+e[3]*i[5]+e[5];return t[0]=n,t[1]=o,t[2]=a,t[3]=r,t[4]=s,t[5]=l,t}function St(t,e,i){return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[3],t[4]=e[4]+i[0],t[5]=e[5]+i[1],t}function Mt(t,e,i){var n=e[0],o=e[2],a=e[4],r=e[1],s=e[3],l=e[5],u=Math.sin(i),h=Math.cos(i);return t[0]=n*h+r*u,t[1]=-n*u+r*h,t[2]=o*h+s*u,t[3]=-o*u+h*s,t[4]=h*a+u*l,t[5]=h*l-u*a,t}function It(t,e,i){var n=i[0],o=i[1];return t[0]=e[0]*n,t[1]=e[1]*o,t[2]=e[2]*n,t[3]=e[3]*o,t[4]=e[4]*n,t[5]=e[5]*o,t}function Tt(t,e){var i=e[0],n=e[2],o=e[4],a=e[1],r=e[3],s=e[5],l=i*r-a*n;return l?(l=1/l,t[0]=r*l,t[1]=-a*l,t[2]=-n*l,t[3]=i*l,t[4]=(n*s-r*o)*l,t[5]=(a*o-i*s)*l,t):null}function At(t){var e=xt();return wt(e,t),e}function Dt(t){return t>Iw||t<-Iw}function Ct(t){this._target=t.target,this._life=t.life||1e3,this._delay=t.delay||0,this._initialized=!1,this.loop=null!=t.loop&&t.loop,this.gap=t.gap||0,this.easing=t.easing||"Linear",this.onframe=t.onframe,this.ondestroy=t.ondestroy,this.onrestart=t.onrestart,this._pausedTime=0,this._paused=!1}function Lt(t){return(t=Math.round(t))<0?0:t>255?255:t}function kt(t){return(t=Math.round(t))<0?0:t>360?360:t}function Pt(t){return t<0?0:t>1?1:t}function Nt(t){return Lt(t.length&&"%"===t.charAt(t.length-1)?parseFloat(t)/100*255:parseInt(t,10))}function Ot(t){return Pt(t.length&&"%"===t.charAt(t.length-1)?parseFloat(t)/100:parseFloat(t))}function Et(t,e,i){return i<0?i+=1:i>1&&(i-=1),6*i<1?t+(e-t)*i*6:2*i<1?e:3*i<2?t+(e-t)*(2/3-i)*6:t}function Rt(t,e,i){return t+(e-t)*i}function zt(t,e,i,n,o){return t[0]=e,t[1]=i,t[2]=n,t[3]=o,t}function Bt(t,e){return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[3],t}function Vt(t,e){Vw&&Bt(Vw,e),Vw=Bw.put(t,Vw||e.slice())}function Gt(t,e){if(t){e=e||[];var i=Bw.get(t);if(i)return Bt(e,i);var n=(t+="").replace(/ /g,"").toLowerCase();if(n in zw)return Bt(e,zw[n]),Vt(t,e),e;if("#"!==n.charAt(0)){var o=n.indexOf("("),a=n.indexOf(")");if(-1!==o&&a+1===n.length){var r=n.substr(0,o),s=n.substr(o+1,a-(o+1)).split(","),l=1;switch(r){case"rgba":if(4!==s.length)return void zt(e,0,0,0,1);l=Ot(s.pop());case"rgb":return 3!==s.length?void zt(e,0,0,0,1):(zt(e,Nt(s[0]),Nt(s[1]),Nt(s[2]),l),Vt(t,e),e);case"hsla":return 4!==s.length?void zt(e,0,0,0,1):(s[3]=Ot(s[3]),Ft(s,e),Vt(t,e),e);case"hsl":return 3!==s.length?void zt(e,0,0,0,1):(Ft(s,e),Vt(t,e),e);default:return}}zt(e,0,0,0,1)}else{if(4===n.length)return(u=parseInt(n.substr(1),16))>=0&&u<=4095?(zt(e,(3840&u)>>4|(3840&u)>>8,240&u|(240&u)>>4,15&u|(15&u)<<4,1),Vt(t,e),e):void zt(e,0,0,0,1);if(7===n.length){var u=parseInt(n.substr(1),16);return u>=0&&u<=16777215?(zt(e,(16711680&u)>>16,(65280&u)>>8,255&u,1),Vt(t,e),e):void zt(e,0,0,0,1)}}}}function Ft(t,e){var i=(parseFloat(t[0])%360+360)%360/360,n=Ot(t[1]),o=Ot(t[2]),a=o<=.5?o*(n+1):o+n-o*n,r=2*o-a;return e=e||[],zt(e,Lt(255*Et(r,a,i+1/3)),Lt(255*Et(r,a,i)),Lt(255*Et(r,a,i-1/3)),1),4===t.length&&(e[3]=t[3]),e}function Wt(t){if(t){var e,i,n=t[0]/255,o=t[1]/255,a=t[2]/255,r=Math.min(n,o,a),s=Math.max(n,o,a),l=s-r,u=(s+r)/2;if(0===l)e=0,i=0;else{i=u<.5?l/(s+r):l/(2-s-r);var h=((s-n)/6+l/2)/l,c=((s-o)/6+l/2)/l,d=((s-a)/6+l/2)/l;n===s?e=d-c:o===s?e=1/3+h-d:a===s&&(e=2/3+c-h),e<0&&(e+=1),e>1&&(e-=1)}var f=[360*e,i,u];return null!=t[3]&&f.push(t[3]),f}}function Ht(t,e){var i=Gt(t);if(i){for(var n=0;n<3;n++)i[n]=e<0?i[n]*(1-e)|0:(255-i[n])*e+i[n]|0,i[n]>255?i[n]=255:t[n]<0&&(i[n]=0);return qt(i,4===i.length?"rgba":"rgb")}}function Zt(t){var e=Gt(t);if(e)return((1<<24)+(e[0]<<16)+(e[1]<<8)+ +e[2]).toString(16).slice(1)}function Ut(t,e,i){if(e&&e.length&&t>=0&&t<=1){i=i||[];var n=t*(e.length-1),o=Math.floor(n),a=Math.ceil(n),r=e[o],s=e[a],l=n-o;return i[0]=Lt(Rt(r[0],s[0],l)),i[1]=Lt(Rt(r[1],s[1],l)),i[2]=Lt(Rt(r[2],s[2],l)),i[3]=Pt(Rt(r[3],s[3],l)),i}}function Xt(t,e,i){if(e&&e.length&&t>=0&&t<=1){var n=t*(e.length-1),o=Math.floor(n),a=Math.ceil(n),r=Gt(e[o]),s=Gt(e[a]),l=n-o,u=qt([Lt(Rt(r[0],s[0],l)),Lt(Rt(r[1],s[1],l)),Lt(Rt(r[2],s[2],l)),Pt(Rt(r[3],s[3],l))],"rgba");return i?{color:u,leftIndex:o,rightIndex:a,value:n}:u}}function jt(t,e,i,n){if(t=Gt(t))return t=Wt(t),null!=e&&(t[0]=kt(e)),null!=i&&(t[1]=Ot(i)),null!=n&&(t[2]=Ot(n)),qt(Ft(t),"rgba")}function Yt(t,e){if((t=Gt(t))&&null!=e)return t[3]=Pt(e),qt(t,"rgba")}function qt(t,e){if(t&&t.length){var i=t[0]+","+t[1]+","+t[2];return"rgba"!==e&&"hsva"!==e&&"hsla"!==e||(i+=","+t[3]),e+"("+i+")"}}function Kt(t,e){return t[e]}function $t(t,e,i){t[e]=i}function Jt(t,e,i){return(e-t)*i+t}function Qt(t,e,i){return i>.5?e:t}function te(t,e,i,n,o){var a=t.length;if(1===o)for(s=0;s<a;s++)n[s]=Jt(t[s],e[s],i);else for(var r=a&&t[0].length,s=0;s<a;s++)for(var l=0;l<r;l++)n[s][l]=Jt(t[s][l],e[s][l],i)}function ee(t,e,i){var n=t.length,o=e.length;if(n!==o)if(n>o)t.length=o;else for(r=n;r<o;r++)t.push(1===i?e[r]:Hw.call(e[r]));for(var a=t[0]&&t[0].length,r=0;r<t.length;r++)if(1===i)isNaN(t[r])&&(t[r]=e[r]);else for(var s=0;s<a;s++)isNaN(t[r][s])&&(t[r][s]=e[r][s])}function ie(t,e,i){if(t===e)return!0;var n=t.length;if(n!==e.length)return!1;if(1===i){for(a=0;a<n;a++)if(t[a]!==e[a])return!1}else for(var o=t[0].length,a=0;a<n;a++)for(var r=0;r<o;r++)if(t[a][r]!==e[a][r])return!1;return!0}function ne(t,e,i,n,o,a,r,s,l){var u=t.length;if(1===l)for(c=0;c<u;c++)s[c]=oe(t[c],e[c],i[c],n[c],o,a,r);else for(var h=t[0].length,c=0;c<u;c++)for(var d=0;d<h;d++)s[c][d]=oe(t[c][d],e[c][d],i[c][d],n[c][d],o,a,r)}function oe(t,e,i,n,o,a,r){var s=.5*(i-t),l=.5*(n-e);return(2*(e-i)+s+l)*r+(-3*(e-i)-2*s-l)*a+s*o+e}function ae(t){if(c(t)){var e=t.length;if(c(t[0])){for(var i=[],n=0;n<e;n++)i.push(Hw.call(t[n]));return i}return Hw.call(t)}return t}function re(t){return t[0]=Math.floor(t[0]),t[1]=Math.floor(t[1]),t[2]=Math.floor(t[2]),"rgba("+t.join(",")+")"}function se(t){var e=t[t.length-1].value;return c(e&&e[0])?2:1}function le(t,e,i,n,o,a){var r=t._getter,s=t._setter,l="spline"===e,u=n.length;if(u){var h,d=c(n[0].value),f=!1,p=!1,g=d?se(n):0;n.sort(function(t,e){return t.time-e.time}),h=n[u-1].time;for(var m=[],v=[],y=n[0].value,x=!0,_=0;_<u;_++){m.push(n[_].time/h);var w=n[_].value;if(d&&ie(w,y,g)||!d&&w===y||(x=!1),y=w,"string"==typeof w){var b=Gt(w);b?(w=b,f=!0):p=!0}v.push(w)}if(a||!x){for(var S=v[u-1],_=0;_<u-1;_++)d?ee(v[_],S,g):!isNaN(v[_])||isNaN(S)||p||f||(v[_]=S);d&&ee(r(t._target,o),S,g);var M,I,T,A,D,C,L=0,k=0;if(f)var P=[0,0,0,0];var N=new Ct({target:t._target,life:h,loop:t._loop,delay:t._delay,onframe:function(t,e){var i;if(e<0)i=0;else if(e<k){for(i=M=Math.min(L+1,u-1);i>=0&&!(m[i]<=e);i--);i=Math.min(i,u-2)}else{for(i=L;i<u&&!(m[i]>e);i++);i=Math.min(i-1,u-2)}L=i,k=e;var n=m[i+1]-m[i];if(0!==n)if(I=(e-m[i])/n,l)if(A=v[i],T=v[0===i?i:i-1],D=v[i>u-2?u-1:i+1],C=v[i>u-3?u-1:i+2],d)ne(T,A,D,C,I,I*I,I*I*I,r(t,o),g);else{if(f)a=ne(T,A,D,C,I,I*I,I*I*I,P,1),a=re(P);else{if(p)return Qt(A,D,I);a=oe(T,A,D,C,I,I*I,I*I*I)}s(t,o,a)}else if(d)te(v[i],v[i+1],I,r(t,o),g);else{var a;if(f)te(v[i],v[i+1],I,P,1),a=re(P);else{if(p)return Qt(v[i],v[i+1],I);a=Jt(v[i],v[i+1],I)}s(t,o,a)}},ondestroy:i});return e&&"spline"!==e&&(N.easing=e),N}}}function ue(t,e,i,n,o,a,r,s){_(n)?(a=o,o=n,n=0):x(o)?(a=o,o="linear",n=0):x(n)?(a=n,n=0):x(i)?(a=i,i=500):i||(i=500),t.stopAnimation(),he(t,"",t,e,i,n,s);var l=t.animators.slice(),u=l.length;u||a&&a();for(var h=0;h<l.length;h++)l[h].done(function(){--u||a&&a()}).start(o,r)}function he(t,e,i,n,o,a,r){var s={},l=0;for(var u in n)n.hasOwnProperty(u)&&(null!=i[u]?w(n[u])&&!c(n[u])?he(t,e?e+"."+u:u,i[u],n[u],o,a,r):(r?(s[u]=i[u],ce(t,e,u,n[u])):s[u]=n[u],l++):null==n[u]||r||ce(t,e,u,n[u]));l>0&&t.animate(e,!1).when(null==o?500:o,s).delay(a||0)}function ce(t,e,i,n){if(e){var o={};o[e]={},o[e][i]=n,t.attr(o)}else t.attr(i,n)}function de(t,e,i,n){i<0&&(t+=i,i=-i),n<0&&(e+=n,n=-n),this.x=t,this.y=e,this.width=i,this.height=n}function fe(t){for(var e=0;t>=eb;)e|=1&t,t>>=1;return t+e}function pe(t,e,i,n){var o=e+1;if(o===i)return 1;if(n(t[o++],t[e])<0){for(;o<i&&n(t[o],t[o-1])<0;)o++;ge(t,e,o)}else for(;o<i&&n(t[o],t[o-1])>=0;)o++;return o-e}function ge(t,e,i){for(i--;e<i;){var n=t[e];t[e++]=t[i],t[i--]=n}}function me(t,e,i,n,o){for(n===e&&n++;n<i;n++){for(var a,r=t[n],s=e,l=n;s<l;)o(r,t[a=s+l>>>1])<0?l=a:s=a+1;var u=n-s;switch(u){case 3:t[s+3]=t[s+2];case 2:t[s+2]=t[s+1];case 1:t[s+1]=t[s];break;default:for(;u>0;)t[s+u]=t[s+u-1],u--}t[s]=r}}function ve(t,e,i,n,o,a){var r=0,s=0,l=1;if(a(t,e[i+o])>0){for(s=n-o;l<s&&a(t,e[i+o+l])>0;)r=l,(l=1+(l<<1))<=0&&(l=s);l>s&&(l=s),r+=o,l+=o}else{for(s=o+1;l<s&&a(t,e[i+o-l])<=0;)r=l,(l=1+(l<<1))<=0&&(l=s);l>s&&(l=s);var u=r;r=o-l,l=o-u}for(r++;r<l;){var h=r+(l-r>>>1);a(t,e[i+h])>0?r=h+1:l=h}return l}function ye(t,e,i,n,o,a){var r=0,s=0,l=1;if(a(t,e[i+o])<0){for(s=o+1;l<s&&a(t,e[i+o-l])<0;)r=l,(l=1+(l<<1))<=0&&(l=s);l>s&&(l=s);var u=r;r=o-l,l=o-u}else{for(s=n-o;l<s&&a(t,e[i+o+l])>=0;)r=l,(l=1+(l<<1))<=0&&(l=s);l>s&&(l=s),r+=o,l+=o}for(r++;r<l;){var h=r+(l-r>>>1);a(t,e[i+h])<0?l=h:r=h+1}return l}function xe(t,e){function i(i){var s=a[i],u=r[i],h=a[i+1],c=r[i+1];r[i]=u+c,i===l-3&&(a[i+1]=a[i+2],r[i+1]=r[i+2]),l--;var d=ye(t[h],t,s,u,0,e);s+=d,0!==(u-=d)&&0!==(c=ve(t[s+u-1],t,h,c,c-1,e))&&(u<=c?n(s,u,h,c):o(s,u,h,c))}function n(i,n,o,a){var r=0;for(r=0;r<n;r++)u[r]=t[i+r];var l=0,h=o,c=i;if(t[c++]=t[h++],0!=--a)if(1!==n){for(var d,f,p,g=s;;){d=0,f=0,p=!1;do{if(e(t[h],u[l])<0){if(t[c++]=t[h++],f++,d=0,0==--a){p=!0;break}}else if(t[c++]=u[l++],d++,f=0,1==--n){p=!0;break}}while((d|f)<g);if(p)break;do{if(0!==(d=ye(t[h],u,l,n,0,e))){for(r=0;r<d;r++)t[c+r]=u[l+r];if(c+=d,l+=d,(n-=d)<=1){p=!0;break}}if(t[c++]=t[h++],0==--a){p=!0;break}if(0!==(f=ve(u[l],t,h,a,0,e))){for(r=0;r<f;r++)t[c+r]=t[h+r];if(c+=f,h+=f,0===(a-=f)){p=!0;break}}if(t[c++]=u[l++],1==--n){p=!0;break}g--}while(d>=ib||f>=ib);if(p)break;g<0&&(g=0),g+=2}if((s=g)<1&&(s=1),1===n){for(r=0;r<a;r++)t[c+r]=t[h+r];t[c+a]=u[l]}else{if(0===n)throw new Error;for(r=0;r<n;r++)t[c+r]=u[l+r]}}else{for(r=0;r<a;r++)t[c+r]=t[h+r];t[c+a]=u[l]}else for(r=0;r<n;r++)t[c+r]=u[l+r]}function o(i,n,o,a){var r=0;for(r=0;r<a;r++)u[r]=t[o+r];var l=i+n-1,h=a-1,c=o+a-1,d=0,f=0;if(t[c--]=t[l--],0!=--n)if(1!==a){for(var p=s;;){var g=0,m=0,v=!1;do{if(e(u[h],t[l])<0){if(t[c--]=t[l--],g++,m=0,0==--n){v=!0;break}}else if(t[c--]=u[h--],m++,g=0,1==--a){v=!0;break}}while((g|m)<p);if(v)break;do{if(0!=(g=n-ye(u[h],t,i,n,n-1,e))){for(n-=g,f=(c-=g)+1,d=(l-=g)+1,r=g-1;r>=0;r--)t[f+r]=t[d+r];if(0===n){v=!0;break}}if(t[c--]=u[h--],1==--a){v=!0;break}if(0!=(m=a-ve(t[l],u,0,a,a-1,e))){for(a-=m,f=(c-=m)+1,d=(h-=m)+1,r=0;r<m;r++)t[f+r]=u[d+r];if(a<=1){v=!0;break}}if(t[c--]=t[l--],0==--n){v=!0;break}p--}while(g>=ib||m>=ib);if(v)break;p<0&&(p=0),p+=2}if((s=p)<1&&(s=1),1===a){for(f=(c-=n)+1,d=(l-=n)+1,r=n-1;r>=0;r--)t[f+r]=t[d+r];t[c]=u[h]}else{if(0===a)throw new Error;for(d=c-(a-1),r=0;r<a;r++)t[d+r]=u[r]}}else{for(f=(c-=n)+1,d=(l-=n)+1,r=n-1;r>=0;r--)t[f+r]=t[d+r];t[c]=u[h]}else for(d=c-(a-1),r=0;r<a;r++)t[d+r]=u[r]}var a,r,s=ib,l=0,u=[];a=[],r=[],this.mergeRuns=function(){for(;l>1;){var t=l-2;if(t>=1&&r[t-1]<=r[t]+r[t+1]||t>=2&&r[t-2]<=r[t]+r[t-1])r[t-1]<r[t+1]&&t--;else if(r[t]>r[t+1])break;i(t)}},this.forceMergeRuns=function(){for(;l>1;){var t=l-2;t>0&&r[t-1]<r[t+1]&&t--,i(t)}},this.pushRun=function(t,e){a[l]=t,r[l]=e,l+=1}}function _e(t,e,i,n){i||(i=0),n||(n=t.length);var o=n-i;if(!(o<2)){var a=0;if(o<eb)return a=pe(t,i,n,e),void me(t,i,n,i+a,e);var r=new xe(t,e),s=fe(o);do{if((a=pe(t,i,n,e))<s){var l=o;l>s&&(l=s),me(t,i,i+l,i+a,e),a=l}r.pushRun(i,a),r.mergeRuns(),o-=a,i+=a}while(0!==o);r.forceMergeRuns()}}function we(t,e){return t.zlevel===e.zlevel?t.z===e.z?t.z2-e.z2:t.z-e.z:t.zlevel-e.zlevel}function be(t,e,i){var n=null==e.x?0:e.x,o=null==e.x2?1:e.x2,a=null==e.y?0:e.y,r=null==e.y2?0:e.y2;return e.global||(n=n*i.width+i.x,o=o*i.width+i.x,a=a*i.height+i.y,r=r*i.height+i.y),n=isNaN(n)?0:n,o=isNaN(o)?1:o,a=isNaN(a)?0:a,r=isNaN(r)?0:r,t.createLinearGradient(n,a,o,r)}function Se(t,e,i){var n=i.width,o=i.height,a=Math.min(n,o),r=null==e.x?.5:e.x,s=null==e.y?.5:e.y,l=null==e.r?.5:e.r;return e.global||(r=r*n+i.x,s=s*o+i.y,l*=a),t.createRadialGradient(r,s,0,r,s,l)}function Me(){return!1}function Ie(t,e,i){var n=iw(),o=e.getWidth(),a=e.getHeight(),r=n.style;return r&&(r.position="absolute",r.left=0,r.top=0,r.width=o+"px",r.height=a+"px",n.setAttribute("data-zr-dom-id",t)),n.width=o*i,n.height=a*i,n}function Te(t){if("string"==typeof t){var e=mb.get(t);return e&&e.image}return t}function Ae(t,e,i,n,o){if(t){if("string"==typeof t){if(e&&e.__zrImageSrc===t||!i)return e;var a=mb.get(t),r={hostEl:i,cb:n,cbPayload:o};return a?!Ce(e=a.image)&&a.pending.push(r):((e=new Image).onload=e.onerror=De,mb.put(t,e.__cachedImgObj={image:e,pending:[r]}),e.src=e.__zrImageSrc=t),e}return t}return e}function De(){var t=this.__cachedImgObj;this.onload=this.onerror=this.__cachedImgObj=null;for(var e=0;e<t.pending.length;e++){var i=t.pending[e],n=i.cb;n&&n(this,i.cbPayload),i.hostEl.dirty()}t.pending.length=0}function Ce(t){return t&&t.width&&t.height}function Le(t,e){var i=t+":"+(e=e||wb);if(vb[i])return vb[i];for(var n=(t+"").split("\n"),o=0,a=0,r=n.length;a<r;a++)o=Math.max(We(n[a],e).width,o);return yb>xb&&(yb=0,vb={}),yb++,vb[i]=o,o}function ke(t,e,i,n,o,a,r,s){return r?Ne(t,e,i,n,o,a,r,s):Pe(t,e,i,n,o,a,s)}function Pe(t,e,i,n,o,a,r){var s=He(t,e,o,a,r),l=Le(t,e);o&&(l+=o[1]+o[3]);var u=s.outerHeight,h=new de(Oe(0,l,i),Ee(0,u,n),l,u);return h.lineHeight=s.lineHeight,h}function Ne(t,e,i,n,o,a,r,s){var l=Ze(t,{rich:r,truncate:s,font:e,textAlign:i,textPadding:o,textLineHeight:a}),u=l.outerWidth,h=l.outerHeight;return new de(Oe(0,u,i),Ee(0,h,n),u,h)}function Oe(t,e,i){return"right"===i?t-=e:"center"===i&&(t-=e/2),t}function Ee(t,e,i){return"middle"===i?t-=e/2:"bottom"===i&&(t-=e),t}function Re(t,e,i){var n=e.x,o=e.y,a=e.height,r=e.width,s=a/2,l="left",u="top";switch(t){case"left":n-=i,o+=s,l="right",u="middle";break;case"right":n+=i+r,o+=s,u="middle";break;case"top":n+=r/2,o-=i,l="center",u="bottom";break;case"bottom":n+=r/2,o+=a+i,l="center";break;case"inside":n+=r/2,o+=s,l="center",u="middle";break;case"insideLeft":n+=i,o+=s,u="middle";break;case"insideRight":n+=r-i,o+=s,l="right",u="middle";break;case"insideTop":n+=r/2,o+=i,l="center";break;case"insideBottom":n+=r/2,o+=a-i,l="center",u="bottom";break;case"insideTopLeft":n+=i,o+=i;break;case"insideTopRight":n+=r-i,o+=i,l="right";break;case"insideBottomLeft":n+=i,o+=a-i,u="bottom";break;case"insideBottomRight":n+=r-i,o+=a-i,l="right",u="bottom"}return{x:n,y:o,textAlign:l,textVerticalAlign:u}}function ze(t,e,i,n,o){if(!e)return"";var a=(t+"").split("\n");o=Be(e,i,n,o);for(var r=0,s=a.length;r<s;r++)a[r]=Ve(a[r],o);return a.join("\n")}function Be(t,e,i,n){(n=a({},n)).font=e;var i=A(i,"...");n.maxIterations=A(n.maxIterations,2);var o=n.minChar=A(n.minChar,0);n.cnCharWidth=Le("国",e);var r=n.ascCharWidth=Le("a",e);n.placeholder=A(n.placeholder,"");for(var s=t=Math.max(0,t-1),l=0;l<o&&s>=r;l++)s-=r;var u=Le(i,e);return u>s&&(i="",u=0),s=t-u,n.ellipsis=i,n.ellipsisWidth=u,n.contentWidth=s,n.containerWidth=t,n}function Ve(t,e){var i=e.containerWidth,n=e.font,o=e.contentWidth;if(!i)return"";var a=Le(t,n);if(a<=i)return t;for(var r=0;;r++){if(a<=o||r>=e.maxIterations){t+=e.ellipsis;break}var s=0===r?Ge(t,o,e.ascCharWidth,e.cnCharWidth):a>0?Math.floor(t.length*o/a):0;a=Le(t=t.substr(0,s),n)}return""===t&&(t=e.placeholder),t}function Ge(t,e,i,n){for(var o=0,a=0,r=t.length;a<r&&o<e;a++){var s=t.charCodeAt(a);o+=0<=s&&s<=127?i:n}return a}function Fe(t){return Le("国",t)}function We(t,e){return bb.measureText(t,e)}function He(t,e,i,n,o){null!=t&&(t+="");var a=A(n,Fe(e)),r=t?t.split("\n"):[],s=r.length*a,l=s;if(i&&(l+=i[0]+i[2]),t&&o){var u=o.outerHeight,h=o.outerWidth;if(null!=u&&l>u)t="",r=[];else if(null!=h)for(var c=Be(h-(i?i[1]+i[3]:0),e,o.ellipsis,{minChar:o.minChar,placeholder:o.placeholder}),d=0,f=r.length;d<f;d++)r[d]=Ve(r[d],c)}return{lines:r,height:s,outerHeight:l,lineHeight:a}}function Ze(t,e){var i={lines:[],width:0,height:0};if(null!=t&&(t+=""),!t)return i;for(var n,o=_b.lastIndex=0;null!=(n=_b.exec(t));){var a=n.index;a>o&&Ue(i,t.substring(o,a)),Ue(i,n[2],n[1]),o=_b.lastIndex}o<t.length&&Ue(i,t.substring(o,t.length));var r=i.lines,s=0,l=0,u=[],h=e.textPadding,c=e.truncate,d=c&&c.outerWidth,f=c&&c.outerHeight;h&&(null!=d&&(d-=h[1]+h[3]),null!=f&&(f-=h[0]+h[2]));for(L=0;L<r.length;L++){for(var p=r[L],g=0,m=0,v=0;v<p.tokens.length;v++){var y=(k=p.tokens[v]).styleName&&e.rich[k.styleName]||{},x=k.textPadding=y.textPadding,_=k.font=y.font||e.font,w=k.textHeight=A(y.textHeight,Fe(_));if(x&&(w+=x[0]+x[2]),k.height=w,k.lineHeight=D(y.textLineHeight,e.textLineHeight,w),k.textAlign=y&&y.textAlign||e.textAlign,k.textVerticalAlign=y&&y.textVerticalAlign||"middle",null!=f&&s+k.lineHeight>f)return{lines:[],width:0,height:0};k.textWidth=Le(k.text,_);var b=y.textWidth,S=null==b||"auto"===b;if("string"==typeof b&&"%"===b.charAt(b.length-1))k.percentWidth=b,u.push(k),b=0;else{if(S){b=k.textWidth;var M=y.textBackgroundColor,I=M&&M.image;I&&Ce(I=Te(I))&&(b=Math.max(b,I.width*w/I.height))}var T=x?x[1]+x[3]:0;b+=T;var C=null!=d?d-m:null;null!=C&&C<b&&(!S||C<T?(k.text="",k.textWidth=b=0):(k.text=ze(k.text,C-T,_,c.ellipsis,{minChar:c.minChar}),k.textWidth=Le(k.text,_),b=k.textWidth+T))}m+=k.width=b,y&&(g=Math.max(g,k.lineHeight))}p.width=m,p.lineHeight=g,s+=g,l=Math.max(l,m)}i.outerWidth=i.width=A(e.textWidth,l),i.outerHeight=i.height=A(e.textHeight,s),h&&(i.outerWidth+=h[1]+h[3],i.outerHeight+=h[0]+h[2]);for(var L=0;L<u.length;L++){var k=u[L],P=k.percentWidth;k.width=parseInt(P,10)/100*l}return i}function Ue(t,e,i){for(var n=""===e,o=e.split("\n"),a=t.lines,r=0;r<o.length;r++){var s=o[r],l={styleName:i,text:s,isLineHolder:!s&&!n};if(r)a.push({tokens:[l]});else{var u=(a[a.length-1]||(a[0]={tokens:[]})).tokens,h=u.length;1===h&&u[0].isLineHolder?u[0]=l:(s||!h||n)&&u.push(l)}}}function Xe(t){var e=(t.fontSize||t.fontFamily)&&[t.fontStyle,t.fontWeight,(t.fontSize||12)+"px",t.fontFamily||"sans-serif"].join(" ");return e&&P(e)||t.textFont||t.font}function je(t,e){var i,n,o,a,r=e.x,s=e.y,l=e.width,u=e.height,h=e.r;l<0&&(r+=l,l=-l),u<0&&(s+=u,u=-u),"number"==typeof h?i=n=o=a=h:h instanceof Array?1===h.length?i=n=o=a=h[0]:2===h.length?(i=o=h[0],n=a=h[1]):3===h.length?(i=h[0],n=a=h[1],o=h[2]):(i=h[0],n=h[1],o=h[2],a=h[3]):i=n=o=a=0;var c;i+n>l&&(i*=l/(c=i+n),n*=l/c),o+a>l&&(o*=l/(c=o+a),a*=l/c),n+o>u&&(n*=u/(c=n+o),o*=u/c),i+a>u&&(i*=u/(c=i+a),a*=u/c),t.moveTo(r+i,s),t.lineTo(r+l-n,s),0!==n&&t.arc(r+l-n,s+n,n,-Math.PI/2,0),t.lineTo(r+l,s+u-o),0!==o&&t.arc(r+l-o,s+u-o,o,0,Math.PI/2),t.lineTo(r+a,s+u),0!==a&&t.arc(r+a,s+u-a,a,Math.PI/2,Math.PI),t.lineTo(r,s+i),0!==i&&t.arc(r+i,s+i,i,Math.PI,1.5*Math.PI)}function Ye(t){return qe(t),d(t.rich,qe),t}function qe(t){if(t){t.font=Xe(t);var e=t.textAlign;"middle"===e&&(e="center"),t.textAlign=null==e||Mb[e]?e:"left";var i=t.textVerticalAlign||t.textBaseline;"center"===i&&(i="middle"),t.textVerticalAlign=null==i||Ib[i]?i:"top",t.textPadding&&(t.textPadding=L(t.textPadding))}}function Ke(t,e,i,n,o,a){n.rich?Je(t,e,i,n,o,a):$e(t,e,i,n,o,a)}function $e(t,e,i,n,o,a){var r,s=ii(n),l=!1,u=e.__attrCachedBy===rb.PLAIN_TEXT;a!==sb?(a&&(r=a.style,l=!s&&u&&r),e.__attrCachedBy=s?rb.NONE:rb.PLAIN_TEXT):u&&(e.__attrCachedBy=rb.NONE);var h=n.font||Sb;l&&h===(r.font||Sb)||(e.font=h);var c=t.__computedFont;t.__styleFont!==h&&(t.__styleFont=h,c=t.__computedFont=e.font);var d=n.textPadding,f=n.textLineHeight,p=t.__textCotentBlock;p&&!t.__dirtyText||(p=t.__textCotentBlock=He(i,c,d,f,n.truncate));var g=p.outerHeight,m=p.lines,v=p.lineHeight,y=ai(g,n,o),x=y.baseX,_=y.baseY,w=y.textAlign||"left",b=y.textVerticalAlign;ti(e,n,o,x,_);var S=Ee(_,g,b),M=x,I=S;if(s||d){var T=Le(i,c);d&&(T+=d[1]+d[3]);var A=Oe(x,T,w);s&&ni(t,e,n,A,S,T,g),d&&(M=hi(x,w,d),I+=d[0])}e.textAlign=w,e.textBaseline="middle",e.globalAlpha=n.opacity||1;for(B=0;B<Tb.length;B++){var D=Tb[B],C=D[0],L=D[1],k=n[C];l&&k===r[C]||(e[L]=ab(e,L,k||D[2]))}I+=v/2;var P=n.textStrokeWidth,N=l?r.textStrokeWidth:null,O=!l||P!==N,E=!l||O||n.textStroke!==r.textStroke,R=si(n.textStroke,P),z=li(n.textFill);if(R&&(O&&(e.lineWidth=P),E&&(e.strokeStyle=R)),z&&(l&&n.textFill===r.textFill||(e.fillStyle=z)),1===m.length)R&&e.strokeText(m[0],M,I),z&&e.fillText(m[0],M,I);else for(var B=0;B<m.length;B++)R&&e.strokeText(m[B],M,I),z&&e.fillText(m[B],M,I),I+=v}function Je(t,e,i,n,o,a){a!==sb&&(e.__attrCachedBy=rb.NONE);var r=t.__textCotentBlock;r&&!t.__dirtyText||(r=t.__textCotentBlock=Ze(i,n)),Qe(t,e,r,n,o)}function Qe(t,e,i,n,o){var a=i.width,r=i.outerWidth,s=i.outerHeight,l=n.textPadding,u=ai(s,n,o),h=u.baseX,c=u.baseY,d=u.textAlign,f=u.textVerticalAlign;ti(e,n,o,h,c);var p=Oe(h,r,d),g=Ee(c,s,f),m=p,v=g;l&&(m+=l[3],v+=l[0]);var y=m+a;ii(n)&&ni(t,e,n,p,g,r,s);for(var x=0;x<i.lines.length;x++){for(var _,w=i.lines[x],b=w.tokens,S=b.length,M=w.lineHeight,I=w.width,T=0,A=m,D=y,C=S-1;T<S&&(!(_=b[T]).textAlign||"left"===_.textAlign);)ei(t,e,_,n,M,v,A,"left"),I-=_.width,A+=_.width,T++;for(;C>=0&&"right"===(_=b[C]).textAlign;)ei(t,e,_,n,M,v,D,"right"),I-=_.width,D-=_.width,C--;for(A+=(a-(A-m)-(y-D)-I)/2;T<=C;)ei(t,e,_=b[T],n,M,v,A+_.width/2,"center"),A+=_.width,T++;v+=M}}function ti(t,e,i,n,o){if(i&&e.textRotation){var a=e.textOrigin;"center"===a?(n=i.width/2+i.x,o=i.height/2+i.y):a&&(n=a[0]+i.x,o=a[1]+i.y),t.translate(n,o),t.rotate(-e.textRotation),t.translate(-n,-o)}}function ei(t,e,i,n,o,a,r,s){var l=n.rich[i.styleName]||{};l.text=i.text;var u=i.textVerticalAlign,h=a+o/2;"top"===u?h=a+i.height/2:"bottom"===u&&(h=a+o-i.height/2),!i.isLineHolder&&ii(l)&&ni(t,e,l,"right"===s?r-i.width:"center"===s?r-i.width/2:r,h-i.height/2,i.width,i.height);var c=i.textPadding;c&&(r=hi(r,s,c),h-=i.height/2-c[2]-i.textHeight/2),ri(e,"shadowBlur",D(l.textShadowBlur,n.textShadowBlur,0)),ri(e,"shadowColor",l.textShadowColor||n.textShadowColor||"transparent"),ri(e,"shadowOffsetX",D(l.textShadowOffsetX,n.textShadowOffsetX,0)),ri(e,"shadowOffsetY",D(l.textShadowOffsetY,n.textShadowOffsetY,0)),ri(e,"textAlign",s),ri(e,"textBaseline","middle"),ri(e,"font",i.font||Sb);var d=si(l.textStroke||n.textStroke,p),f=li(l.textFill||n.textFill),p=A(l.textStrokeWidth,n.textStrokeWidth);d&&(ri(e,"lineWidth",p),ri(e,"strokeStyle",d),e.strokeText(i.text,r,h)),f&&(ri(e,"fillStyle",f),e.fillText(i.text,r,h))}function ii(t){return!!(t.textBackgroundColor||t.textBorderWidth&&t.textBorderColor)}function ni(t,e,i,n,o,a,r){var s=i.textBackgroundColor,l=i.textBorderWidth,u=i.textBorderColor,h=_(s);if(ri(e,"shadowBlur",i.textBoxShadowBlur||0),ri(e,"shadowColor",i.textBoxShadowColor||"transparent"),ri(e,"shadowOffsetX",i.textBoxShadowOffsetX||0),ri(e,"shadowOffsetY",i.textBoxShadowOffsetY||0),h||l&&u){e.beginPath();var c=i.textBorderRadius;c?je(e,{x:n,y:o,width:a,height:r,r:c}):e.rect(n,o,a,r),e.closePath()}if(h)if(ri(e,"fillStyle",s),null!=i.fillOpacity){f=e.globalAlpha;e.globalAlpha=i.fillOpacity*i.opacity,e.fill(),e.globalAlpha=f}else e.fill();else if(w(s)){var d=s.image;(d=Ae(d,null,t,oi,s))&&Ce(d)&&e.drawImage(d,n,o,a,r)}if(l&&u)if(ri(e,"lineWidth",l),ri(e,"strokeStyle",u),null!=i.strokeOpacity){var f=e.globalAlpha;e.globalAlpha=i.strokeOpacity*i.opacity,e.stroke(),e.globalAlpha=f}else e.stroke()}function oi(t,e){e.image=t}function ai(t,e,i){var n=e.x||0,o=e.y||0,a=e.textAlign,r=e.textVerticalAlign;if(i){var s=e.textPosition;if(s instanceof Array)n=i.x+ui(s[0],i.width),o=i.y+ui(s[1],i.height);else{var l=Re(s,i,e.textDistance);n=l.x,o=l.y,a=a||l.textAlign,r=r||l.textVerticalAlign}var u=e.textOffset;u&&(n+=u[0],o+=u[1])}return{baseX:n,baseY:o,textAlign:a,textVerticalAlign:r}}function ri(t,e,i){return t[e]=ab(t,e,i),t[e]}function si(t,e){return null==t||e<=0||"transparent"===t||"none"===t?null:t.image||t.colorStops?"#000":t}function li(t){return null==t||"none"===t?null:t.image||t.colorStops?"#000":t}function ui(t,e){return"string"==typeof t?t.lastIndexOf("%")>=0?parseFloat(t)/100*e:parseFloat(t):t}function hi(t,e,i){return"right"===e?t-i[1]:"center"===e?t+i[3]/2-i[1]/2:t+i[3]}function ci(t,e){return null!=t&&(t||e.textBackgroundColor||e.textBorderWidth&&e.textBorderColor||e.textPadding)}function di(t){t=t||{},Kw.call(this,t);for(var e in t)t.hasOwnProperty(e)&&"style"!==e&&(this[e]=t[e]);this.style=new ub(t.style,this),this._rect=null,this.__clipPaths=[]}function fi(t){di.call(this,t)}function pi(t){return parseInt(t,10)}function gi(t){return!!t&&(!!t.__builtin__||"function"==typeof t.resize&&"function"==typeof t.refresh)}function mi(t,e,i){return Cb.copy(t.getBoundingRect()),t.transform&&Cb.applyTransform(t.transform),Lb.width=e,Lb.height=i,!Cb.intersect(Lb)}function vi(t,e){if(t===e)return!1;if(!t||!e||t.length!==e.length)return!0;for(var i=0;i<t.length;i++)if(t[i]!==e[i])return!0}function yi(t,e){for(var i=0;i<t.length;i++){var n=t[i];n.setTransform(e),e.beginPath(),n.buildPath(e,n.shape),e.clip(),n.restoreTransform(e)}}function xi(t,e){var i=document.createElement("div");return i.style.cssText=["position:relative","overflow:hidden","width:"+t+"px","height:"+e+"px","padding:0","margin:0","border-width:0"].join(";")+";",i}function _i(t){return"mousewheel"===t&&U_.browser.firefox?"DOMMouseScroll":t}function wi(t){t._touching=!0,clearTimeout(t._touchTimer),t._touchTimer=setTimeout(function(){t._touching=!1},700)}function bi(t){var e=t.pointerType;return"pen"===e||"touch"===e}function Si(t){function e(t,e){return function(){if(!e._touching)return t.apply(e,arguments)}}d(Ob,function(e){t._handlers[e]=m(zb[e],t)}),d(Rb,function(e){t._handlers[e]=m(zb[e],t)}),d(Nb,function(i){t._handlers[i]=e(zb[i],t)})}function Mi(t){function e(e,i){d(e,function(e){ht(t,_i(e),i._handlers[e])},i)}fw.call(this),this.dom=t,this._touching=!1,this._touchTimer,this._handlers={},Si(this),U_.pointerEventsSupported?e(Rb,this):(U_.touchEventsSupported&&e(Ob,this),e(Nb,this))}function Ii(t,e){var i=new Wb(H_(),t,e);return Fb[i.id]=i,i}function Ti(t,e){Gb[t]=e}function Ai(t){delete Fb[t]}function Di(t){return t instanceof Array?t:null==t?[]:[t]}function Ci(t,e,i){if(t){t[e]=t[e]||{},t.emphasis=t.emphasis||{},t.emphasis[e]=t.emphasis[e]||{};for(var n=0,o=i.length;n<o;n++){var a=i[n];!t.emphasis[e].hasOwnProperty(a)&&t[e].hasOwnProperty(a)&&(t.emphasis[e][a]=t[e][a])}}}function Li(t){return!Ub(t)||Xb(t)||t instanceof Date?t:t.value}function ki(t){return Ub(t)&&!(t instanceof Array)}function Pi(t,e){e=(e||[]).slice();var i=f(t||[],function(t,e){return{exist:t}});return Zb(e,function(t,n){if(Ub(t)){for(o=0;o<i.length;o++)if(!i[o].option&&null!=t.id&&i[o].exist.id===t.id+"")return i[o].option=t,void(e[n]=null);for(var o=0;o<i.length;o++){var a=i[o].exist;if(!(i[o].option||null!=a.id&&null!=t.id||null==t.name||Ei(t)||Ei(a)||a.name!==t.name+""))return i[o].option=t,void(e[n]=null)}}}),Zb(e,function(t,e){if(Ub(t)){for(var n=0;n<i.length;n++){var o=i[n].exist;if(!i[n].option&&!Ei(o)&&null==t.id){i[n].option=t;break}}n>=i.length&&i.push({option:t})}}),i}function Ni(t){var e=R();Zb(t,function(t,i){var n=t.exist;n&&e.set(n.id,t)}),Zb(t,function(t,i){var n=t.option;k(!n||null==n.id||!e.get(n.id)||e.get(n.id)===t,"id duplicates: "+(n&&n.id)),n&&null!=n.id&&e.set(n.id,t),!t.keyInfo&&(t.keyInfo={})}),Zb(t,function(t,i){var n=t.exist,o=t.option,a=t.keyInfo;if(Ub(o)){if(a.name=null!=o.name?o.name+"":n?n.name:jb+i,n)a.id=n.id;else if(null!=o.id)a.id=o.id+"";else{var r=0;do{a.id="\0"+a.name+"\0"+r++}while(e.get(a.id))}e.set(a.id,t)}})}function Oi(t){var e=t.name;return!(!e||!e.indexOf(jb))}function Ei(t){return Ub(t)&&t.id&&0===(t.id+"").indexOf("\0_ec_\0")}function Ri(t,e){function i(t,e,i){for(var n=0,o=t.length;n<o;n++)for(var a=t[n].seriesId,r=Di(t[n].dataIndex),s=i&&i[a],l=0,u=r.length;l<u;l++){var h=r[l];s&&s[h]?s[h]=null:(e[a]||(e[a]={}))[h]=1}}function n(t,e){var i=[];for(var o in t)if(t.hasOwnProperty(o)&&null!=t[o])if(e)i.push(+o);else{var a=n(t[o],!0);a.length&&i.push({seriesId:o,dataIndex:a})}return i}var o={},a={};return i(t||[],o),i(e||[],a,o),[n(o),n(a)]}function zi(t,e){return null!=e.dataIndexInside?e.dataIndexInside:null!=e.dataIndex?y(e.dataIndex)?f(e.dataIndex,function(e){return t.indexOfRawIndex(e)}):t.indexOfRawIndex(e.dataIndex):null!=e.name?y(e.name)?f(e.name,function(e){return t.indexOfName(e)}):t.indexOfName(e.name):void 0}function Bi(){var t="__\0ec_inner_"+qb+++"_"+Math.random().toFixed(5);return function(e){return e[t]||(e[t]={})}}function Vi(t,e,i){if(_(e)){var n={};n[e+"Index"]=0,e=n}var o=i&&i.defaultMainType;!o||Gi(e,o+"Index")||Gi(e,o+"Id")||Gi(e,o+"Name")||(e[o+"Index"]=0);var a={};return Zb(e,function(n,o){var n=e[o];if("dataIndex"!==o&&"dataIndexInside"!==o){var r=o.match(/^(\w+)(Index|Id|Name)$/)||[],s=r[1],u=(r[2]||"").toLowerCase();if(!(!s||!u||null==n||"index"===u&&"none"===n||i&&i.includeMainTypes&&l(i.includeMainTypes,s)<0)){var h={mainType:s};"index"===u&&"all"===n||(h[u]=n);var c=t.queryComponents(h);a[s+"Models"]=c,a[s+"Model"]=c[0]}}else a[o]=n}),a}function Gi(t,e){return t&&t.hasOwnProperty(e)}function Fi(t,e,i){t.setAttribute?t.setAttribute(e,i):t[e]=i}function Wi(t,e){return t.getAttribute?t.getAttribute(e):t[e]}function Hi(t){return"auto"===t?U_.domSupported?"html":"richText":t||"html"}function Zi(t,e){var i=R(),n=[];return d(t,function(t){var o=e(t);(i.get(o)||(n.push(o),i.set(o,[]))).push(t)}),{keys:n,buckets:i}}function Ui(t){var e={main:"",sub:""};return t&&(t=t.split(Kb),e.main=t[0]||"",e.sub=t[1]||""),e}function Xi(t){k(/^[a-zA-Z0-9_]+([.][a-zA-Z0-9_]+)?$/.test(t),'componentType "'+t+'" illegal')}function ji(t,e){t.$constructor=t,t.extend=function(t){var e=this,i=function(){t.$constructor?t.$constructor.apply(this,arguments):e.apply(this,arguments)};return a(i.prototype,t),i.extend=this.extend,i.superCall=qi,i.superApply=Ki,u(i,this),i.superClass=e,i}}function Yi(t){var e=["__\0is_clz",Jb++,Math.random().toFixed(3)].join("_");t.prototype[e]=!0,t.isInstance=function(t){return!(!t||!t[e])}}function qi(t,e){var i=C(arguments,2);return this.superClass.prototype[e].apply(t,i)}function Ki(t,e,i){return this.superClass.prototype[e].apply(t,i)}function $i(t,e){function i(t){var e=n[t.main];return e&&e[$b]||((e=n[t.main]={})[$b]=!0),e}e=e||{};var n={};if(t.registerClass=function(t,e){return e&&(Xi(e),(e=Ui(e)).sub?e.sub!==$b&&(i(e)[e.sub]=t):n[e.main]=t),t},t.getClass=function(t,e,i){var o=n[t];if(o&&o[$b]&&(o=e?o[e]:null),i&&!o)throw new Error(e?"Component "+t+"."+(e||"")+" not exists. Load it first.":t+".type should be specified.");return o},t.getClassesByMainType=function(t){t=Ui(t);var e=[],i=n[t.main];return i&&i[$b]?d(i,function(t,i){i!==$b&&e.push(t)}):e.push(i),e},t.hasClass=function(t){return t=Ui(t),!!n[t.main]},t.getAllClassMainTypes=function(){var t=[];return d(n,function(e,i){t.push(i)}),t},t.hasSubTypes=function(t){t=Ui(t);var e=n[t.main];return e&&e[$b]},t.parseClassType=Ui,e.registerWhenExtend){var o=t.extend;o&&(t.extend=function(e){var i=o.call(this,e);return t.registerClass(i,e.type)})}return t}function Ji(t){return t>-rS&&t<rS}function Qi(t){return t>rS||t<-rS}function tn(t,e,i,n,o){var a=1-o;return a*a*(a*t+3*o*e)+o*o*(o*n+3*a*i)}function en(t,e,i,n,o){var a=1-o;return 3*(((e-t)*a+2*(i-e)*o)*a+(n-i)*o*o)}function nn(t,e,i,n,o,a){var r=n+3*(e-i)-t,s=3*(i-2*e+t),l=3*(e-t),u=t-o,h=s*s-3*r*l,c=s*l-9*r*u,d=l*l-3*s*u,f=0;if(Ji(h)&&Ji(c))Ji(s)?a[0]=0:(M=-l/s)>=0&&M<=1&&(a[f++]=M);else{var p=c*c-4*h*d;if(Ji(p)){var g=c/h,m=-g/2;(M=-s/r+g)>=0&&M<=1&&(a[f++]=M),m>=0&&m<=1&&(a[f++]=m)}else if(p>0){var v=aS(p),y=h*s+1.5*r*(-c+v),x=h*s+1.5*r*(-c-v);(M=(-s-((y=y<0?-oS(-y,uS):oS(y,uS))+(x=x<0?-oS(-x,uS):oS(x,uS))))/(3*r))>=0&&M<=1&&(a[f++]=M)}else{var _=(2*h*s-3*r*c)/(2*aS(h*h*h)),w=Math.acos(_)/3,b=aS(h),S=Math.cos(w),M=(-s-2*b*S)/(3*r),m=(-s+b*(S+lS*Math.sin(w)))/(3*r),I=(-s+b*(S-lS*Math.sin(w)))/(3*r);M>=0&&M<=1&&(a[f++]=M),m>=0&&m<=1&&(a[f++]=m),I>=0&&I<=1&&(a[f++]=I)}}return f}function on(t,e,i,n,o){var a=6*i-12*e+6*t,r=9*e+3*n-3*t-9*i,s=3*e-3*t,l=0;if(Ji(r))Qi(a)&&(c=-s/a)>=0&&c<=1&&(o[l++]=c);else{var u=a*a-4*r*s;if(Ji(u))o[0]=-a/(2*r);else if(u>0){var h=aS(u),c=(-a+h)/(2*r),d=(-a-h)/(2*r);c>=0&&c<=1&&(o[l++]=c),d>=0&&d<=1&&(o[l++]=d)}}return l}function an(t,e,i,n,o,a){var r=(e-t)*o+t,s=(i-e)*o+e,l=(n-i)*o+i,u=(s-r)*o+r,h=(l-s)*o+s,c=(h-u)*o+u;a[0]=t,a[1]=r,a[2]=u,a[3]=c,a[4]=c,a[5]=h,a[6]=l,a[7]=n}function rn(t,e,i,n,o,a,r,s,l,u,h){var c,d,f,p,g,m=.005,v=1/0;hS[0]=l,hS[1]=u;for(var y=0;y<1;y+=.05)cS[0]=tn(t,i,o,r,y),cS[1]=tn(e,n,a,s,y),(p=hw(hS,cS))<v&&(c=y,v=p);v=1/0;for(var x=0;x<32&&!(m<sS);x++)d=c-m,f=c+m,cS[0]=tn(t,i,o,r,d),cS[1]=tn(e,n,a,s,d),p=hw(cS,hS),d>=0&&p<v?(c=d,v=p):(dS[0]=tn(t,i,o,r,f),dS[1]=tn(e,n,a,s,f),g=hw(dS,hS),f<=1&&g<v?(c=f,v=g):m*=.5);return h&&(h[0]=tn(t,i,o,r,c),h[1]=tn(e,n,a,s,c)),aS(v)}function sn(t,e,i,n){var o=1-n;return o*(o*t+2*n*e)+n*n*i}function ln(t,e,i,n){return 2*((1-n)*(e-t)+n*(i-e))}function un(t,e,i,n,o){var a=t-2*e+i,r=2*(e-t),s=t-n,l=0;if(Ji(a))Qi(r)&&(c=-s/r)>=0&&c<=1&&(o[l++]=c);else{var u=r*r-4*a*s;if(Ji(u))(c=-r/(2*a))>=0&&c<=1&&(o[l++]=c);else if(u>0){var h=aS(u),c=(-r+h)/(2*a),d=(-r-h)/(2*a);c>=0&&c<=1&&(o[l++]=c),d>=0&&d<=1&&(o[l++]=d)}}return l}function hn(t,e,i){var n=t+i-2*e;return 0===n?.5:(t-e)/n}function cn(t,e,i,n,o){var a=(e-t)*n+t,r=(i-e)*n+e,s=(r-a)*n+a;o[0]=t,o[1]=a,o[2]=s,o[3]=s,o[4]=r,o[5]=i}function dn(t,e,i,n,o,a,r,s,l){var u,h=.005,c=1/0;hS[0]=r,hS[1]=s;for(var d=0;d<1;d+=.05)cS[0]=sn(t,i,o,d),cS[1]=sn(e,n,a,d),(m=hw(hS,cS))<c&&(u=d,c=m);c=1/0;for(var f=0;f<32&&!(h<sS);f++){var p=u-h,g=u+h;cS[0]=sn(t,i,o,p),cS[1]=sn(e,n,a,p);var m=hw(cS,hS);if(p>=0&&m<c)u=p,c=m;else{dS[0]=sn(t,i,o,g),dS[1]=sn(e,n,a,g);var v=hw(dS,hS);g<=1&&v<c?(u=g,c=v):h*=.5}}return l&&(l[0]=sn(t,i,o,u),l[1]=sn(e,n,a,u)),aS(c)}function fn(t,e,i){if(0!==t.length){var n,o=t[0],a=o[0],r=o[0],s=o[1],l=o[1];for(n=1;n<t.length;n++)o=t[n],a=fS(a,o[0]),r=pS(r,o[0]),s=fS(s,o[1]),l=pS(l,o[1]);e[0]=a,e[1]=s,i[0]=r,i[1]=l}}function pn(t,e,i,n,o,a){o[0]=fS(t,i),o[1]=fS(e,n),a[0]=pS(t,i),a[1]=pS(e,n)}function gn(t,e,i,n,o,a,r,s,l,u){var h,c=on,d=tn,f=c(t,i,o,r,wS);for(l[0]=1/0,l[1]=1/0,u[0]=-1/0,u[1]=-1/0,h=0;h<f;h++){var p=d(t,i,o,r,wS[h]);l[0]=fS(p,l[0]),u[0]=pS(p,u[0])}for(f=c(e,n,a,s,bS),h=0;h<f;h++){var g=d(e,n,a,s,bS[h]);l[1]=fS(g,l[1]),u[1]=pS(g,u[1])}l[0]=fS(t,l[0]),u[0]=pS(t,u[0]),l[0]=fS(r,l[0]),u[0]=pS(r,u[0]),l[1]=fS(e,l[1]),u[1]=pS(e,u[1]),l[1]=fS(s,l[1]),u[1]=pS(s,u[1])}function mn(t,e,i,n,o,a,r,s){var l=hn,u=sn,h=pS(fS(l(t,i,o),1),0),c=pS(fS(l(e,n,a),1),0),d=u(t,i,o,h),f=u(e,n,a,c);r[0]=fS(t,o,d),r[1]=fS(e,a,f),s[0]=pS(t,o,d),s[1]=pS(e,a,f)}function vn(t,e,i,n,o,a,r,s,l){var u=tt,h=et,c=Math.abs(o-a);if(c%vS<1e-4&&c>1e-4)return s[0]=t-i,s[1]=e-n,l[0]=t+i,void(l[1]=e+n);if(yS[0]=mS(o)*i+t,yS[1]=gS(o)*n+e,xS[0]=mS(a)*i+t,xS[1]=gS(a)*n+e,u(s,yS,xS),h(l,yS,xS),(o%=vS)<0&&(o+=vS),(a%=vS)<0&&(a+=vS),o>a&&!r?a+=vS:o<a&&r&&(o+=vS),r){var d=a;a=o,o=d}for(var f=0;f<a;f+=Math.PI/2)f>o&&(_S[0]=mS(f)*i+t,_S[1]=gS(f)*n+e,u(s,_S,s),h(l,_S,l))}function yn(t,e,i,n,o,a,r){if(0===o)return!1;var s=o,l=0,u=t;if(r>e+s&&r>n+s||r<e-s&&r<n-s||a>t+s&&a>i+s||a<t-s&&a<i-s)return!1;if(t===i)return Math.abs(a-t)<=s/2;var h=(l=(e-n)/(t-i))*a-r+(u=(t*n-i*e)/(t-i));return h*h/(l*l+1)<=s/2*s/2}function xn(t,e,i,n,o,a,r,s,l,u,h){if(0===l)return!1;var c=l;return!(h>e+c&&h>n+c&&h>a+c&&h>s+c||h<e-c&&h<n-c&&h<a-c&&h<s-c||u>t+c&&u>i+c&&u>o+c&&u>r+c||u<t-c&&u<i-c&&u<o-c&&u<r-c)&&rn(t,e,i,n,o,a,r,s,u,h,null)<=c/2}function _n(t,e,i,n,o,a,r,s,l){if(0===r)return!1;var u=r;return!(l>e+u&&l>n+u&&l>a+u||l<e-u&&l<n-u&&l<a-u||s>t+u&&s>i+u&&s>o+u||s<t-u&&s<i-u&&s<o-u)&&dn(t,e,i,n,o,a,s,l,null)<=u/2}function wn(t){return(t%=RS)<0&&(t+=RS),t}function bn(t,e,i,n,o,a,r,s,l){if(0===r)return!1;var u=r;s-=t,l-=e;var h=Math.sqrt(s*s+l*l);if(h-u>i||h+u<i)return!1;if(Math.abs(n-o)%zS<1e-4)return!0;if(a){var c=n;n=wn(o),o=wn(c)}else n=wn(n),o=wn(o);n>o&&(o+=zS);var d=Math.atan2(l,s);return d<0&&(d+=zS),d>=n&&d<=o||d+zS>=n&&d+zS<=o}function Sn(t,e,i,n,o,a){if(a>e&&a>n||a<e&&a<n)return 0;if(n===e)return 0;var r=n<e?1:-1,s=(a-e)/(n-e);1!==s&&0!==s||(r=n<e?.5:-.5);var l=s*(i-t)+t;return l===o?1/0:l>o?r:0}function Mn(t,e){return Math.abs(t-e)<GS}function In(){var t=WS[0];WS[0]=WS[1],WS[1]=t}function Tn(t,e,i,n,o,a,r,s,l,u){if(u>e&&u>n&&u>a&&u>s||u<e&&u<n&&u<a&&u<s)return 0;var h=nn(e,n,a,s,u,FS);if(0===h)return 0;for(var c,d,f=0,p=-1,g=0;g<h;g++){var m=FS[g],v=0===m||1===m?.5:1;tn(t,i,o,r,m)<l||(p<0&&(p=on(e,n,a,s,WS),WS[1]<WS[0]&&p>1&&In(),c=tn(e,n,a,s,WS[0]),p>1&&(d=tn(e,n,a,s,WS[1]))),2===p?m<WS[0]?f+=c<e?v:-v:m<WS[1]?f+=d<c?v:-v:f+=s<d?v:-v:m<WS[0]?f+=c<e?v:-v:f+=s<c?v:-v)}return f}function An(t,e,i,n,o,a,r,s){if(s>e&&s>n&&s>a||s<e&&s<n&&s<a)return 0;var l=un(e,n,a,s,FS);if(0===l)return 0;var u=hn(e,n,a);if(u>=0&&u<=1){for(var h=0,c=sn(e,n,a,u),d=0;d<l;d++){f=0===FS[d]||1===FS[d]?.5:1;(p=sn(t,i,o,FS[d]))<r||(FS[d]<u?h+=c<e?f:-f:h+=a<c?f:-f)}return h}var f=0===FS[0]||1===FS[0]?.5:1,p=sn(t,i,o,FS[0]);return p<r?0:a<e?f:-f}function Dn(t,e,i,n,o,a,r,s){if((s-=e)>i||s<-i)return 0;u=Math.sqrt(i*i-s*s);FS[0]=-u,FS[1]=u;var l=Math.abs(n-o);if(l<1e-4)return 0;if(l%VS<1e-4){n=0,o=VS;p=a?1:-1;return r>=FS[0]+t&&r<=FS[1]+t?p:0}if(a){var u=n;n=wn(o),o=wn(u)}else n=wn(n),o=wn(o);n>o&&(o+=VS);for(var h=0,c=0;c<2;c++){var d=FS[c];if(d+t>r){var f=Math.atan2(s,d),p=a?1:-1;f<0&&(f=VS+f),(f>=n&&f<=o||f+VS>=n&&f+VS<=o)&&(f>Math.PI/2&&f<1.5*Math.PI&&(p=-p),h+=p)}}return h}function Cn(t,e,i,n,o){for(var a=0,r=0,s=0,l=0,u=0,h=0;h<t.length;){var c=t[h++];switch(c===BS.M&&h>1&&(i||(a+=Sn(r,s,l,u,n,o))),1===h&&(l=r=t[h],u=s=t[h+1]),c){case BS.M:r=l=t[h++],s=u=t[h++];break;case BS.L:if(i){if(yn(r,s,t[h],t[h+1],e,n,o))return!0}else a+=Sn(r,s,t[h],t[h+1],n,o)||0;r=t[h++],s=t[h++];break;case BS.C:if(i){if(xn(r,s,t[h++],t[h++],t[h++],t[h++],t[h],t[h+1],e,n,o))return!0}else a+=Tn(r,s,t[h++],t[h++],t[h++],t[h++],t[h],t[h+1],n,o)||0;r=t[h++],s=t[h++];break;case BS.Q:if(i){if(_n(r,s,t[h++],t[h++],t[h],t[h+1],e,n,o))return!0}else a+=An(r,s,t[h++],t[h++],t[h],t[h+1],n,o)||0;r=t[h++],s=t[h++];break;case BS.A:var d=t[h++],f=t[h++],p=t[h++],g=t[h++],m=t[h++],v=t[h++];h+=1;var y=1-t[h++],x=Math.cos(m)*p+d,_=Math.sin(m)*g+f;h>1?a+=Sn(r,s,x,_,n,o):(l=x,u=_);var w=(n-d)*g/p+d;if(i){if(bn(d,f,g,m,m+v,y,e,w,o))return!0}else a+=Dn(d,f,g,m,m+v,y,w,o);r=Math.cos(m+v)*p+d,s=Math.sin(m+v)*g+f;break;case BS.R:l=r=t[h++],u=s=t[h++];var x=l+t[h++],_=u+t[h++];if(i){if(yn(l,u,x,u,e,n,o)||yn(x,u,x,_,e,n,o)||yn(x,_,l,_,e,n,o)||yn(l,_,l,u,e,n,o))return!0}else a+=Sn(x,u,x,_,n,o),a+=Sn(l,_,l,u,n,o);break;case BS.Z:if(i){if(yn(r,s,l,u,e,n,o))return!0}else a+=Sn(r,s,l,u,n,o);r=l,s=u}}return i||Mn(s,u)||(a+=Sn(r,s,l,u,n,o)||0),0!==a}function Ln(t,e,i){return Cn(t,0,!1,e,i)}function kn(t,e,i,n){return Cn(t,e,!0,i,n)}function Pn(t){di.call(this,t),this.path=null}function Nn(t,e,i,n,o,a,r,s,l,u,h){var c=l*(tM/180),d=QS(c)*(t-i)/2+JS(c)*(e-n)/2,f=-1*JS(c)*(t-i)/2+QS(c)*(e-n)/2,p=d*d/(r*r)+f*f/(s*s);p>1&&(r*=$S(p),s*=$S(p));var g=(o===a?-1:1)*$S((r*r*(s*s)-r*r*(f*f)-s*s*(d*d))/(r*r*(f*f)+s*s*(d*d)))||0,m=g*r*f/s,v=g*-s*d/r,y=(t+i)/2+QS(c)*m-JS(c)*v,x=(e+n)/2+JS(c)*m+QS(c)*v,_=nM([1,0],[(d-m)/r,(f-v)/s]),w=[(d-m)/r,(f-v)/s],b=[(-1*d-m)/r,(-1*f-v)/s],S=nM(w,b);iM(w,b)<=-1&&(S=tM),iM(w,b)>=1&&(S=0),0===a&&S>0&&(S-=2*tM),1===a&&S<0&&(S+=2*tM),h.addData(u,y,x,r,s,_,S,c,a)}function On(t){if(!t)return new ES;for(var e,i=0,n=0,o=i,a=n,r=new ES,s=ES.CMD,l=t.match(oM),u=0;u<l.length;u++){for(var h,c=l[u],d=c.charAt(0),f=c.match(aM)||[],p=f.length,g=0;g<p;g++)f[g]=parseFloat(f[g]);for(var m=0;m<p;){var v,y,x,_,w,b,S,M=i,I=n;switch(d){case"l":i+=f[m++],n+=f[m++],h=s.L,r.addData(h,i,n);break;case"L":i=f[m++],n=f[m++],h=s.L,r.addData(h,i,n);break;case"m":i+=f[m++],n+=f[m++],h=s.M,r.addData(h,i,n),o=i,a=n,d="l";break;case"M":i=f[m++],n=f[m++],h=s.M,r.addData(h,i,n),o=i,a=n,d="L";break;case"h":i+=f[m++],h=s.L,r.addData(h,i,n);break;case"H":i=f[m++],h=s.L,r.addData(h,i,n);break;case"v":n+=f[m++],h=s.L,r.addData(h,i,n);break;case"V":n=f[m++],h=s.L,r.addData(h,i,n);break;case"C":h=s.C,r.addData(h,f[m++],f[m++],f[m++],f[m++],f[m++],f[m++]),i=f[m-2],n=f[m-1];break;case"c":h=s.C,r.addData(h,f[m++]+i,f[m++]+n,f[m++]+i,f[m++]+n,f[m++]+i,f[m++]+n),i+=f[m-2],n+=f[m-1];break;case"S":v=i,y=n;var T=r.len(),A=r.data;e===s.C&&(v+=i-A[T-4],y+=n-A[T-3]),h=s.C,M=f[m++],I=f[m++],i=f[m++],n=f[m++],r.addData(h,v,y,M,I,i,n);break;case"s":v=i,y=n;var T=r.len(),A=r.data;e===s.C&&(v+=i-A[T-4],y+=n-A[T-3]),h=s.C,M=i+f[m++],I=n+f[m++],i+=f[m++],n+=f[m++],r.addData(h,v,y,M,I,i,n);break;case"Q":M=f[m++],I=f[m++],i=f[m++],n=f[m++],h=s.Q,r.addData(h,M,I,i,n);break;case"q":M=f[m++]+i,I=f[m++]+n,i+=f[m++],n+=f[m++],h=s.Q,r.addData(h,M,I,i,n);break;case"T":v=i,y=n;var T=r.len(),A=r.data;e===s.Q&&(v+=i-A[T-4],y+=n-A[T-3]),i=f[m++],n=f[m++],h=s.Q,r.addData(h,v,y,i,n);break;case"t":v=i,y=n;var T=r.len(),A=r.data;e===s.Q&&(v+=i-A[T-4],y+=n-A[T-3]),i+=f[m++],n+=f[m++],h=s.Q,r.addData(h,v,y,i,n);break;case"A":x=f[m++],_=f[m++],w=f[m++],b=f[m++],S=f[m++],Nn(M=i,I=n,i=f[m++],n=f[m++],b,S,x,_,w,h=s.A,r);break;case"a":x=f[m++],_=f[m++],w=f[m++],b=f[m++],S=f[m++],Nn(M=i,I=n,i+=f[m++],n+=f[m++],b,S,x,_,w,h=s.A,r)}}"z"!==d&&"Z"!==d||(h=s.Z,r.addData(h),i=o,n=a),e=h}return r.toStatic(),r}function En(t,e){var i=On(t);return e=e||{},e.buildPath=function(t){if(t.setData)t.setData(i.data),(e=t.getContext())&&t.rebuildPath(e);else{var e=t;i.rebuildPath(e)}},e.applyTransform=function(t){KS(i,t),this.dirty(!0)},e}function Rn(t,e){return new Pn(En(t,e))}function zn(t,e){return Pn.extend(En(t,e))}function Bn(t,e,i,n,o,a,r){var s=.5*(i-t),l=.5*(n-e);return(2*(e-i)+s+l)*r+(-3*(e-i)-2*s-l)*a+s*o+e}function Vn(t,e,i){var n=e.points,o=e.smooth;if(n&&n.length>=2){if(o&&"spline"!==o){var a=fM(n,o,i,e.smoothConstraint);t.moveTo(n[0][0],n[0][1]);for(var r=n.length,s=0;s<(i?r:r-1);s++){var l=a[2*s],u=a[2*s+1],h=n[(s+1)%r];t.bezierCurveTo(l[0],l[1],u[0],u[1],h[0],h[1])}}else{"spline"===o&&(n=dM(n,i)),t.moveTo(n[0][0],n[0][1]);for(var s=1,c=n.length;s<c;s++)t.lineTo(n[s][0],n[s][1])}i&&t.closePath()}}function Gn(t,e,i){var n=i&&i.lineWidth;if(e&&n){var o=e.x1,a=e.x2,r=e.y1,s=e.y2;mM(2*o)===mM(2*a)?t.x1=t.x2=Wn(o,n,!0):(t.x1=o,t.x2=a),mM(2*r)===mM(2*s)?t.y1=t.y2=Wn(r,n,!0):(t.y1=r,t.y2=s)}}function Fn(t,e,i){var n=i&&i.lineWidth;if(e&&n){var o=e.x,a=e.y,r=e.width,s=e.height;t.x=Wn(o,n,!0),t.y=Wn(a,n,!0),t.width=Math.max(Wn(o+r,n,!1)-t.x,0===r?0:1),t.height=Math.max(Wn(a+s,n,!1)-t.y,0===s?0:1)}}function Wn(t,e,i){var n=mM(2*t);return(n+mM(e))%2==0?n/2:(n+(i?1:-1))/2}function Hn(t,e,i){var n=t.cpx2,o=t.cpy2;return null===n||null===o?[(i?en:tn)(t.x1,t.cpx1,t.cpx2,t.x2,e),(i?en:tn)(t.y1,t.cpy1,t.cpy2,t.y2,e)]:[(i?ln:sn)(t.x1,t.cpx1,t.x2,e),(i?ln:sn)(t.y1,t.cpy1,t.y2,e)]}function Zn(t){di.call(this,t),this._displayables=[],this._temporaryDisplayables=[],this._cursor=0,this.notClear=!0}function Un(t){return Pn.extend(t)}function Xn(t,e,i,n){var o=Rn(t,e);return i&&("center"===n&&(i=Yn(i,o.getBoundingRect())),qn(o,i)),o}function jn(t,e,i){var n=new fi({style:{image:t,x:e.x,y:e.y,width:e.width,height:e.height},onload:function(t){if("center"===i){var o={width:t.width,height:t.height};n.setStyle(Yn(e,o))}}});return n}function Yn(t,e){var i,n=e.width/e.height,o=t.height*n;return i=o<=t.width?t.height:(o=t.width)/n,{x:t.x+t.width/2-o/2,y:t.y+t.height/2-i/2,width:o,height:i}}function qn(t,e){if(t.applyTransform){var i=t.getBoundingRect().calculateTransform(e);t.applyTransform(i)}}function Kn(t){var e=t.shape,i=t.style.lineWidth;return CM(2*e.x1)===CM(2*e.x2)&&(e.x1=e.x2=Jn(e.x1,i,!0)),CM(2*e.y1)===CM(2*e.y2)&&(e.y1=e.y2=Jn(e.y1,i,!0)),t}function $n(t){var e=t.shape,i=t.style.lineWidth,n=e.x,o=e.y,a=e.width,r=e.height;return e.x=Jn(e.x,i,!0),e.y=Jn(e.y,i,!0),e.width=Math.max(Jn(n+a,i,!1)-e.x,0===a?0:1),e.height=Math.max(Jn(o+r,i,!1)-e.y,0===r?0:1),t}function Jn(t,e,i){var n=CM(2*t);return(n+CM(e))%2==0?n/2:(n+(i?1:-1))/2}function Qn(t){return null!=t&&"none"!==t}function to(t){if("string"!=typeof t)return t;var e=EM.get(t);return e||(e=Ht(t,-.1),RM<1e4&&(EM.set(t,e),RM++)),e}function eo(t){if(t.__hoverStlDirty){t.__hoverStlDirty=!1;var e=t.__hoverStl;if(e){var i=t.__cachedNormalStl={};t.__cachedNormalZ2=t.z2;var n=t.style;for(var o in e)null!=e[o]&&(i[o]=n[o]);i.fill=n.fill,i.stroke=n.stroke}else t.__cachedNormalStl=t.__cachedNormalZ2=null}}function io(t){var e=t.__hoverStl;if(e&&!t.__highlighted){var i=t.useHoverLayer;t.__highlighted=i?"layer":"plain";var n=t.__zr;if(n||!i){var o=t,a=t.style;i&&(a=(o=n.addHover(t)).style),bo(a),i||eo(o),a.extendFrom(e),no(a,e,"fill"),no(a,e,"stroke"),wo(a),i||(t.dirty(!1),t.z2+=NM)}}}function no(t,e,i){!Qn(e[i])&&Qn(t[i])&&(t[i]=to(t[i]))}function oo(t){var e=t.__highlighted;if(e)if(t.__highlighted=!1,"layer"===e)t.__zr&&t.__zr.removeHover(t);else if(e){var i=t.style,n=t.__cachedNormalStl;n&&(bo(i),t.setStyle(n),wo(i));var o=t.__cachedNormalZ2;null!=o&&t.z2-o===NM&&(t.z2=o)}}function ao(t,e){t.isGroup?t.traverse(function(t){!t.isGroup&&e(t)}):e(t)}function ro(t,e){e=t.__hoverStl=!1!==e&&(e||{}),t.__hoverStlDirty=!0,t.__highlighted&&(t.__cachedNormalStl=null,oo(t),io(t))}function so(t){return t&&t.__isEmphasisEntered}function lo(t){this.__hoverSilentOnTouch&&t.zrByTouch||!this.__isEmphasisEntered&&ao(this,io)}function uo(t){this.__hoverSilentOnTouch&&t.zrByTouch||!this.__isEmphasisEntered&&ao(this,oo)}function ho(){this.__isEmphasisEntered=!0,ao(this,io)}function co(){this.__isEmphasisEntered=!1,ao(this,oo)}function fo(t,e,i){t.isGroup?t.traverse(function(t){!t.isGroup&&ro(t,t.hoverStyle||e)}):ro(t,t.hoverStyle||e),po(t,i)}function po(t,e){var i=!1===e;if(t.__hoverSilentOnTouch=null!=e&&e.hoverSilentOnTouch,!i||t.__hoverStyleTrigger){var n=i?"off":"on";t[n]("mouseover",lo)[n]("mouseout",uo),t[n]("emphasis",ho)[n]("normal",co),t.__hoverStyleTrigger=!i}}function go(t,e,i,n,o,a,r){var s,l=(o=o||PM).labelFetcher,u=o.labelDataIndex,h=o.labelDimIndex,c=i.getShallow("show"),d=n.getShallow("show");(c||d)&&(l&&(s=l.getFormattedLabel(u,"normal",null,h)),null==s&&(s=x(o.defaultText)?o.defaultText(u,o):o.defaultText));var f=c?s:null,p=d?A(l?l.getFormattedLabel(u,"emphasis",null,h):null,s):null;null==f&&null==p||(mo(t,i,a,o),mo(e,n,r,o,!0)),t.text=f,e.text=p}function mo(t,e,i,n,o){return vo(t,e,n,o),i&&a(t,i),t}function vo(t,e,i,n){if((i=i||PM).isRectText){var o=e.getShallow("position")||(n?null:"inside");"outside"===o&&(o="top"),t.textPosition=o,t.textOffset=e.getShallow("offset");var a=e.getShallow("rotate");null!=a&&(a*=Math.PI/180),t.textRotation=a,t.textDistance=A(e.getShallow("distance"),n?null:5)}var r,s=e.ecModel,l=s&&s.option.textStyle,u=yo(e);if(u){r={};for(var h in u)if(u.hasOwnProperty(h)){var c=e.getModel(["rich",h]);xo(r[h]={},c,l,i,n)}}return t.rich=r,xo(t,e,l,i,n,!0),i.forceRich&&!i.textStyle&&(i.textStyle={}),t}function yo(t){for(var e;t&&t!==t.ecModel;){var i=(t.option||PM).rich;if(i){e=e||{};for(var n in i)i.hasOwnProperty(n)&&(e[n]=1)}t=t.parentModel}return e}function xo(t,e,i,n,o,a){i=!o&&i||PM,t.textFill=_o(e.getShallow("color"),n)||i.color,t.textStroke=_o(e.getShallow("textBorderColor"),n)||i.textBorderColor,t.textStrokeWidth=A(e.getShallow("textBorderWidth"),i.textBorderWidth),t.insideRawTextPosition=t.textPosition,o||(a&&(t.insideRollbackOpt=n,wo(t)),null==t.textFill&&(t.textFill=n.autoColor)),t.fontStyle=e.getShallow("fontStyle")||i.fontStyle,t.fontWeight=e.getShallow("fontWeight")||i.fontWeight,t.fontSize=e.getShallow("fontSize")||i.fontSize,t.fontFamily=e.getShallow("fontFamily")||i.fontFamily,t.textAlign=e.getShallow("align"),t.textVerticalAlign=e.getShallow("verticalAlign")||e.getShallow("baseline"),t.textLineHeight=e.getShallow("lineHeight"),t.textWidth=e.getShallow("width"),t.textHeight=e.getShallow("height"),t.textTag=e.getShallow("tag"),a&&n.disableBox||(t.textBackgroundColor=_o(e.getShallow("backgroundColor"),n),t.textPadding=e.getShallow("padding"),t.textBorderColor=_o(e.getShallow("borderColor"),n),t.textBorderWidth=e.getShallow("borderWidth"),t.textBorderRadius=e.getShallow("borderRadius"),t.textBoxShadowColor=e.getShallow("shadowColor"),t.textBoxShadowBlur=e.getShallow("shadowBlur"),t.textBoxShadowOffsetX=e.getShallow("shadowOffsetX"),t.textBoxShadowOffsetY=e.getShallow("shadowOffsetY")),t.textShadowColor=e.getShallow("textShadowColor")||i.textShadowColor,t.textShadowBlur=e.getShallow("textShadowBlur")||i.textShadowBlur,t.textShadowOffsetX=e.getShallow("textShadowOffsetX")||i.textShadowOffsetX,t.textShadowOffsetY=e.getShallow("textShadowOffsetY")||i.textShadowOffsetY}function _o(t,e){return"auto"!==t?t:e&&e.autoColor?e.autoColor:null}function wo(t){var e=t.insideRollbackOpt;if(e&&null==t.textFill){var i,n=e.useInsideStyle,o=t.insideRawTextPosition,a=e.autoColor;!1!==n&&(!0===n||e.isRectText&&o&&"string"==typeof o&&o.indexOf("inside")>=0)?(i={textFill:null,textStroke:t.textStroke,textStrokeWidth:t.textStrokeWidth},t.textFill="#fff",null==t.textStroke&&(t.textStroke=a,null==t.textStrokeWidth&&(t.textStrokeWidth=2))):null!=a&&(i={textFill:null},t.textFill=a),i&&(t.insideRollback=i)}}function bo(t){var e=t.insideRollback;e&&(t.textFill=e.textFill,t.textStroke=e.textStroke,t.textStrokeWidth=e.textStrokeWidth,t.insideRollback=null)}function So(t,e){var i=e||e.getModel("textStyle");return P([t.fontStyle||i&&i.getShallow("fontStyle")||"",t.fontWeight||i&&i.getShallow("fontWeight")||"",(t.fontSize||i&&i.getShallow("fontSize")||12)+"px",t.fontFamily||i&&i.getShallow("fontFamily")||"sans-serif"].join(" "))}function Mo(t,e,i,n,o,a){if("function"==typeof o&&(a=o,o=null),n&&n.isAnimationEnabled()){var r=t?"Update":"",s=n.getShallow("animationDuration"+r),l=n.getShallow("animationEasing"+r),u=n.getShallow("animationDelay"+r);"function"==typeof u&&(u=u(o,n.getAnimationDelayParams?n.getAnimationDelayParams(e,o):null)),"function"==typeof s&&(s=s(o)),s>0?e.animateTo(i,s,u||0,l,a,!!a):(e.stopAnimation(),e.attr(i),a&&a())}else e.stopAnimation(),e.attr(i),a&&a()}function Io(t,e,i,n,o){Mo(!0,t,e,i,n,o)}function To(t,e,i,n,o){Mo(!1,t,e,i,n,o)}function Ao(t,e){for(var i=_t([]);t&&t!==e;)bt(i,t.getLocalTransform(),i),t=t.parent;return i}function Do(t,e,i){return e&&!c(e)&&(e=Tw.getLocalTransform(e)),i&&(e=Tt([],e)),Q([],t,e)}function Co(t,e,i){var n=0===e[4]||0===e[5]||0===e[0]?1:Math.abs(2*e[4]/e[0]),o=0===e[4]||0===e[5]||0===e[2]?1:Math.abs(2*e[4]/e[2]),a=["left"===t?-n:"right"===t?n:0,"top"===t?-o:"bottom"===t?o:0];return a=Do(a,e,i),Math.abs(a[0])>Math.abs(a[1])?a[0]>0?"right":"left":a[1]>0?"bottom":"top"}function Lo(t,e,i,n){function o(t){var e={position:F(t.position),rotation:t.rotation};return t.shape&&(e.shape=a({},t.shape)),e}if(t&&e){var r=function(t){var e={};return t.traverse(function(t){!t.isGroup&&t.anid&&(e[t.anid]=t)}),e}(t);e.traverse(function(t){if(!t.isGroup&&t.anid){var e=r[t.anid];if(e){var n=o(t);t.attr(o(e)),Io(t,n,i,t.dataIndex)}}})}}function ko(t,e){return f(t,function(t){var i=t[0];i=LM(i,e.x),i=kM(i,e.x+e.width);var n=t[1];return n=LM(n,e.y),n=kM(n,e.y+e.height),[i,n]})}function Po(t,e,i){var n=(e=a({rectHover:!0},e)).style={strokeNoScale:!0};if(i=i||{x:-1,y:-1,width:2,height:2},t)return 0===t.indexOf("image://")?(n.image=t.slice(8),r(n,i),new fi(e)):Xn(t.replace("path://",""),e,i,"center")}function No(t,e,i){this.parentModel=e,this.ecModel=i,this.option=t}function Oo(t,e,i){for(var n=0;n<e.length&&(!e[n]||null!=(t=t&&"object"==typeof t?t[e[n]]:null));n++);return null==t&&i&&(t=i.get(e)),t}function Eo(t,e){var i=HM(t).getParent;return i?i.call(t,e):t.parentModel}function Ro(t){return[t||"",ZM++,Math.random().toFixed(5)].join("_")}function zo(t){return t.replace(/^\s+/,"").replace(/\s+$/,"")}function Bo(t,e,i,n){var o=e[1]-e[0],a=i[1]-i[0];if(0===o)return 0===a?i[0]:(i[0]+i[1])/2;if(n)if(o>0){if(t<=e[0])return i[0];if(t>=e[1])return i[1]}else{if(t>=e[0])return i[0];if(t<=e[1])return i[1]}else{if(t===e[0])return i[0];if(t===e[1])return i[1]}return(t-e[0])/o*a+i[0]}function Vo(t,e){switch(t){case"center":case"middle":t="50%";break;case"left":case"top":t="0%";break;case"right":case"bottom":t="100%"}return"string"==typeof t?zo(t).match(/%$/)?parseFloat(t)/100*e:parseFloat(t):null==t?NaN:+t}function Go(t,e,i){return null==e&&(e=10),e=Math.min(Math.max(0,e),20),t=(+t).toFixed(e),i?t:+t}function Fo(t){return t.sort(function(t,e){return t-e}),t}function Wo(t){if(t=+t,isNaN(t))return 0;for(var e=1,i=0;Math.round(t*e)/e!==t;)e*=10,i++;return i}function Ho(t){var e=t.toString(),i=e.indexOf("e");if(i>0){var n=+e.slice(i+1);return n<0?-n:0}var o=e.indexOf(".");return o<0?0:e.length-1-o}function Zo(t,e){var i=Math.log,n=Math.LN10,o=Math.floor(i(t[1]-t[0])/n),a=Math.round(i(Math.abs(e[1]-e[0]))/n),r=Math.min(Math.max(-o+a,0),20);return isFinite(r)?r:20}function Uo(t,e,i){if(!t[e])return 0;var n=p(t,function(t,e){return t+(isNaN(e)?0:e)},0);if(0===n)return 0;for(var o=Math.pow(10,i),a=f(t,function(t){return(isNaN(t)?0:t)/n*o*100}),r=100*o,s=f(a,function(t){return Math.floor(t)}),l=p(s,function(t,e){return t+e},0),u=f(a,function(t,e){return t-s[e]});l<r;){for(var h=Number.NEGATIVE_INFINITY,c=null,d=0,g=u.length;d<g;++d)u[d]>h&&(h=u[d],c=d);++s[c],u[c]=0,++l}return s[e]/o}function Xo(t){var e=2*Math.PI;return(t%e+e)%e}function jo(t){return t>-UM&&t<UM}function Yo(t){if(t instanceof Date)return t;if("string"==typeof t){var e=jM.exec(t);if(!e)return new Date(NaN);if(e[8]){var i=+e[4]||0;return"Z"!==e[8].toUpperCase()&&(i-=e[8].slice(0,3)),new Date(Date.UTC(+e[1],+(e[2]||1)-1,+e[3]||1,i,+(e[5]||0),+e[6]||0,+e[7]||0))}return new Date(+e[1],+(e[2]||1)-1,+e[3]||1,+e[4]||0,+(e[5]||0),+e[6]||0,+e[7]||0)}return null==t?new Date(NaN):new Date(Math.round(t))}function qo(t){return Math.pow(10,Ko(t))}function Ko(t){return Math.floor(Math.log(t)/Math.LN10)}function $o(t,e){var i,n=Ko(t),o=Math.pow(10,n),a=t/o;return i=e?a<1.5?1:a<2.5?2:a<4?3:a<7?5:10:a<1?1:a<2?2:a<3?3:a<5?5:10,t=i*o,n>=-20?+t.toFixed(n<0?-n:0):t}function Jo(t){function e(t,i,n){return t.interval[n]<i.interval[n]||t.interval[n]===i.interval[n]&&(t.close[n]-i.close[n]==(n?-1:1)||!n&&e(t,i,1))}t.sort(function(t,i){return e(t,i,0)?-1:1});for(var i=-1/0,n=1,o=0;o<t.length;){for(var a=t[o].interval,r=t[o].close,s=0;s<2;s++)a[s]<=i&&(a[s]=i,r[s]=s?1:1-n),i=a[s],n=r[s];a[0]===a[1]&&r[0]*r[1]!=1?t.splice(o,1):o++}return t}function Qo(t){return t-parseFloat(t)>=0}function ta(t){return isNaN(t)?"-":(t=(t+"").split("."))[0].replace(/(\d{1,3})(?=(?:\d{3})+(?!\d))/g,"$1,")+(t.length>1?"."+t[1]:"")}function ea(t,e){return t=(t||"").toLowerCase().replace(/-(.)/g,function(t,e){return e.toUpperCase()}),e&&t&&(t=t.charAt(0).toUpperCase()+t.slice(1)),t}function ia(t){return null==t?"":(t+"").replace(KM,function(t,e){return $M[e]})}function na(t,e,i){y(e)||(e=[e]);var n=e.length;if(!n)return"";for(var o=e[0].$vars||[],a=0;a<o.length;a++){var r=JM[a];t=t.replace(QM(r),QM(r,0))}for(var s=0;s<n;s++)for(var l=0;l<o.length;l++){var u=e[s][o[l]];t=t.replace(QM(JM[l],s),i?ia(u):u)}return t}function oa(t,e,i){return d(e,function(e,n){t=t.replace("{"+n+"}",i?ia(e):e)}),t}function aa(t,e){var i=(t=_(t)?{color:t,extraCssText:e}:t||{}).color,n=t.type,e=t.extraCssText,o=t.renderMode||"html",a=t.markerId||"X";return i?"html"===o?"subItem"===n?'<span style="display:inline-block;vertical-align:middle;margin-right:8px;margin-left:3px;border-radius:4px;width:4px;height:4px;background-color:'+ia(i)+";"+(e||"")+'"></span>':'<span style="display:inline-block;margin-right:5px;border-radius:10px;width:10px;height:10px;background-color:'+ia(i)+";"+(e||"")+'"></span>':{renderMode:o,content:"{marker"+a+"|}  ",style:{color:i}}:""}function ra(t,e){return t+="","0000".substr(0,e-t.length)+t}function sa(t,e,i){"week"!==t&&"month"!==t&&"quarter"!==t&&"half-year"!==t&&"year"!==t||(t="MM-dd\nyyyy");var n=Yo(e),o=i?"UTC":"",a=n["get"+o+"FullYear"](),r=n["get"+o+"Month"]()+1,s=n["get"+o+"Date"](),l=n["get"+o+"Hours"](),u=n["get"+o+"Minutes"](),h=n["get"+o+"Seconds"](),c=n["get"+o+"Milliseconds"]();return t=t.replace("MM",ra(r,2)).replace("M",r).replace("yyyy",a).replace("yy",a%100).replace("dd",ra(s,2)).replace("d",s).replace("hh",ra(l,2)).replace("h",l).replace("mm",ra(u,2)).replace("m",u).replace("ss",ra(h,2)).replace("s",h).replace("SSS",ra(c,3))}function la(t){return t?t.charAt(0).toUpperCase()+t.substr(1):t}function ua(t,e,i,n,o){var a=0,r=0;null==n&&(n=1/0),null==o&&(o=1/0);var s=0;e.eachChild(function(l,u){var h,c,d=l.position,f=l.getBoundingRect(),p=e.childAt(u+1),g=p&&p.getBoundingRect();if("horizontal"===t){var m=f.width+(g?-g.x+f.x:0);(h=a+m)>n||l.newline?(a=0,h=m,r+=s+i,s=f.height):s=Math.max(s,f.height)}else{var v=f.height+(g?-g.y+f.y:0);(c=r+v)>o||l.newline?(a+=s+i,r=0,c=v,s=f.width):s=Math.max(s,f.width)}l.newline||(d[0]=a,d[1]=r,"horizontal"===t?a=h+i:r=c+i)})}function ha(t,e,i){var n=e.width,o=e.height,a=Vo(t.x,n),r=Vo(t.y,o),s=Vo(t.x2,n),l=Vo(t.y2,o);return(isNaN(a)||isNaN(parseFloat(t.x)))&&(a=0),(isNaN(s)||isNaN(parseFloat(t.x2)))&&(s=n),(isNaN(r)||isNaN(parseFloat(t.y)))&&(r=0),(isNaN(l)||isNaN(parseFloat(t.y2)))&&(l=o),i=qM(i||0),{width:Math.max(s-a-i[1]-i[3],0),height:Math.max(l-r-i[0]-i[2],0)}}function ca(t,e,i){i=qM(i||0);var n=e.width,o=e.height,a=Vo(t.left,n),r=Vo(t.top,o),s=Vo(t.right,n),l=Vo(t.bottom,o),u=Vo(t.width,n),h=Vo(t.height,o),c=i[2]+i[0],d=i[1]+i[3],f=t.aspect;switch(isNaN(u)&&(u=n-s-d-a),isNaN(h)&&(h=o-l-c-r),null!=f&&(isNaN(u)&&isNaN(h)&&(f>n/o?u=.8*n:h=.8*o),isNaN(u)&&(u=f*h),isNaN(h)&&(h=u/f)),isNaN(a)&&(a=n-s-u-d),isNaN(r)&&(r=o-l-h-c),t.left||t.right){case"center":a=n/2-u/2-i[3];break;case"right":a=n-u-d}switch(t.top||t.bottom){case"middle":case"center":r=o/2-h/2-i[0];break;case"bottom":r=o-h-c}a=a||0,r=r||0,isNaN(u)&&(u=n-d-a-(s||0)),isNaN(h)&&(h=o-c-r-(l||0));var p=new de(a+i[3],r+i[0],u,h);return p.margin=i,p}function da(t,e,i,n,o){var a=!o||!o.hv||o.hv[0],s=!o||!o.hv||o.hv[1],l=o&&o.boundingMode||"all";if(a||s){var u;if("raw"===l)u="group"===t.type?new de(0,0,+e.width||0,+e.height||0):t.getBoundingRect();else if(u=t.getBoundingRect(),t.needLocalTransform()){var h=t.getLocalTransform();(u=u.clone()).applyTransform(h)}e=ca(r({width:u.width,height:u.height},e),i,n);var c=t.position,d=a?e.x-u.x:0,f=s?e.y-u.y:0;t.attr("position","raw"===l?[d,f]:[c[0]+d,c[1]+f])}}function fa(t,e){return null!=t[oI[e][0]]||null!=t[oI[e][1]]&&null!=t[oI[e][2]]}function pa(t,e,i){function n(i,n){var r={},l=0,u={},h=0;if(iI(i,function(e){u[e]=t[e]}),iI(i,function(t){o(e,t)&&(r[t]=u[t]=e[t]),a(r,t)&&l++,a(u,t)&&h++}),s[n])return a(e,i[1])?u[i[2]]=null:a(e,i[2])&&(u[i[1]]=null),u;if(2!==h&&l){if(l>=2)return r;for(var c=0;c<i.length;c++){var d=i[c];if(!o(r,d)&&o(t,d)){r[d]=t[d];break}}return r}return u}function o(t,e){return t.hasOwnProperty(e)}function a(t,e){return null!=t[e]&&"auto"!==t[e]}function r(t,e,i){iI(t,function(t){e[t]=i[t]})}!w(i)&&(i={});var s=i.ignoreSize;!y(s)&&(s=[s,s]);var l=n(oI[0],0),u=n(oI[1],1);r(oI[0],t,l),r(oI[1],t,u)}function ga(t){return ma({},t)}function ma(t,e){return e&&t&&iI(nI,function(i){e.hasOwnProperty(i)&&(t[i]=e[i])}),t}function va(t,e){for(var i=t.length,n=0;n<i;n++)if(t[n].length>e)return t[n];return t[i-1]}function ya(t){var e=t.get("coordinateSystem"),i={coordSysName:e,coordSysDims:[],axisMap:R(),categoryAxisMap:R()},n=fI[e];if(n)return n(t,i,i.axisMap,i.categoryAxisMap),i}function xa(t){return"category"===t.get("type")}function _a(t){this.fromDataset=t.fromDataset,this.data=t.data||(t.sourceFormat===vI?{}:[]),this.sourceFormat=t.sourceFormat||yI,this.seriesLayoutBy=t.seriesLayoutBy||_I,this.dimensionsDefine=t.dimensionsDefine,this.encodeDefine=t.encodeDefine&&R(t.encodeDefine),this.startIndex=t.startIndex||0,this.dimensionsDetectCount=t.dimensionsDetectCount}function wa(t){var e=t.option.source,i=yI;if(S(e))i=xI;else if(y(e)){0===e.length&&(i=gI);for(var n=0,o=e.length;n<o;n++){var a=e[n];if(null!=a){if(y(a)){i=gI;break}if(w(a)){i=mI;break}}}}else if(w(e)){for(var r in e)if(e.hasOwnProperty(r)&&c(e[r])){i=vI;break}}else if(null!=e)throw new Error("Invalid data");bI(t).sourceFormat=i}function ba(t){return bI(t).source}function Sa(t){bI(t).datasetMap=R()}function Ma(t){var e=t.option,i=e.data,n=S(i)?xI:pI,o=!1,a=e.seriesLayoutBy,r=e.sourceHeader,s=e.dimensions,l=La(t);if(l){var u=l.option;i=u.source,n=bI(l).sourceFormat,o=!0,a=a||u.seriesLayoutBy,null==r&&(r=u.sourceHeader),s=s||u.dimensions}var h=Ia(i,n,a,r,s),c=e.encode;!c&&l&&(c=Ca(t,l,i,n,a,h)),bI(t).source=new _a({data:i,fromDataset:o,seriesLayoutBy:a,sourceFormat:n,dimensionsDefine:h.dimensionsDefine,startIndex:h.startIndex,dimensionsDetectCount:h.dimensionsDetectCount,encodeDefine:c})}function Ia(t,e,i,n,o){if(!t)return{dimensionsDefine:Ta(o)};var a,r,s;if(e===gI)"auto"===n||null==n?Aa(function(t){null!=t&&"-"!==t&&(_(t)?null==r&&(r=1):r=0)},i,t,10):r=n?1:0,o||1!==r||(o=[],Aa(function(t,e){o[e]=null!=t?t:""},i,t)),a=o?o.length:i===wI?t.length:t[0]?t[0].length:null;else if(e===mI)o||(o=Da(t),s=!0);else if(e===vI)o||(o=[],s=!0,d(t,function(t,e){o.push(e)}));else if(e===pI){var l=Li(t[0]);a=y(l)&&l.length||1}var u;return s&&d(o,function(t,e){"name"===(w(t)?t.name:t)&&(u=e)}),{startIndex:r,dimensionsDefine:Ta(o),dimensionsDetectCount:a,potentialNameDimIndex:u}}function Ta(t){if(t){var e=R();return f(t,function(t,i){if(null==(t=a({},w(t)?t:{name:t})).name)return t;t.name+="",null==t.displayName&&(t.displayName=t.name);var n=e.get(t.name);return n?t.name+="-"+n.count++:e.set(t.name,{count:1}),t})}}function Aa(t,e,i,n){if(null==n&&(n=1/0),e===wI)for(a=0;a<i.length&&a<n;a++)t(i[a]?i[a][0]:null,a);else for(var o=i[0]||[],a=0;a<o.length&&a<n;a++)t(o[a],a)}function Da(t){for(var e,i=0;i<t.length&&!(e=t[i++]););if(e){var n=[];return d(e,function(t,e){n.push(e)}),n}}function Ca(t,e,i,n,o,a){var r=ya(t),s={},l=[],u=[],h=t.subType,c=R(["pie","map","funnel"]),f=R(["line","bar","pictorialBar","scatter","effectScatter","candlestick","boxplot"]);if(r&&null!=f.get(h)){var p=t.ecModel,g=bI(p).datasetMap,m=e.uid+"_"+o,v=g.get(m)||g.set(m,{categoryWayDim:1,valueWayDim:0});d(r.coordSysDims,function(t){if(null==r.firstCategoryDimIndex){e=v.valueWayDim++;s[t]=e,u.push(e)}else if(r.categoryAxisMap.get(t))s[t]=0,l.push(0);else{var e=v.categoryWayDim++;s[t]=e,u.push(e)}})}else if(null!=c.get(h)){for(var y,x=0;x<5&&null==y;x++)Pa(i,n,o,a.dimensionsDefine,a.startIndex,x)||(y=x);if(null!=y){s.value=y;var _=a.potentialNameDimIndex||Math.max(y-1,0);u.push(_),l.push(_)}}return l.length&&(s.itemName=l),u.length&&(s.seriesName=u),s}function La(t){var e=t.option;if(!e.data)return t.ecModel.getComponent("dataset",e.datasetIndex||0)}function ka(t,e){return Pa(t.data,t.sourceFormat,t.seriesLayoutBy,t.dimensionsDefine,t.startIndex,e)}function Pa(t,e,i,n,o,a){function r(t){return(null==t||!isFinite(t)||""===t)&&(!(!_(t)||"-"===t)||void 0)}var s;if(S(t))return!1;var l;if(n&&(l=w(l=n[a])?l.name:l),e===gI)if(i===wI){for(var u=t[a],h=0;h<(u||[]).length&&h<5;h++)if(null!=(s=r(u[o+h])))return s}else for(h=0;h<t.length&&h<5;h++){var c=t[o+h];if(c&&null!=(s=r(c[a])))return s}else if(e===mI){if(!l)return;for(h=0;h<t.length&&h<5;h++)if((d=t[h])&&null!=(s=r(d[l])))return s}else if(e===vI){if(!l)return;if(!(u=t[l])||S(u))return!1;for(h=0;h<u.length&&h<5;h++)if(null!=(s=r(u[h])))return s}else if(e===pI)for(h=0;h<t.length&&h<5;h++){var d=t[h],f=Li(d);if(!y(f))return!1;if(null!=(s=r(f[a])))return s}return!1}function Na(t,e){if(e){var i=e.seiresIndex,n=e.seriesId,o=e.seriesName;return null!=i&&t.componentIndex!==i||null!=n&&t.id!==n||null!=o&&t.name!==o}}function Oa(t,e){var o=t.color&&!t.colorLayer;d(e,function(e,a){"colorLayer"===a&&o||lI.hasClass(a)||("object"==typeof e?t[a]=t[a]?n(t[a],e,!1):i(e):null==t[a]&&(t[a]=e))})}function Ea(t){t=t,this.option={},this.option[SI]=1,this._componentsMap=R({series:[]}),this._seriesIndices,this._seriesIndicesMap,Oa(t,this._theme.option),n(t,hI,!1),this.mergeOption(t)}function Ra(t,e){y(e)||(e=e?[e]:[]);var i={};return d(e,function(e){i[e]=(t.get(e)||[]).slice()}),i}function za(t,e,i){return e.type?e.type:i?i.subType:lI.determineSubType(t,e)}function Ba(t,e){t._seriesIndicesMap=R(t._seriesIndices=f(e,function(t){return t.componentIndex})||[])}function Va(t,e){return e.hasOwnProperty("subType")?g(t,function(t){return t.subType===e.subType}):t}function Ga(t){d(II,function(e){this[e]=m(t[e],t)},this)}function Fa(){this._coordinateSystems=[]}function Wa(t){this._api=t,this._timelineOptions=[],this._mediaList=[],this._mediaDefault,this._currentMediaIndices=[],this._optionBackup,this._newBaseOption}function Ha(t,e,i){var n,o,a=[],r=[],s=t.timeline;if(t.baseOption&&(o=t.baseOption),(s||t.options)&&(o=o||{},a=(t.options||[]).slice()),t.media){o=o||{};var l=t.media;AI(l,function(t){t&&t.option&&(t.query?r.push(t):n||(n=t))})}return o||(o=t),o.timeline||(o.timeline=s),AI([o].concat(a).concat(f(r,function(t){return t.option})),function(t){AI(e,function(e){e(t,i)})}),{baseOption:o,timelineOptions:a,mediaDefault:n,mediaList:r}}function Za(t,e,i){var n={width:e,height:i,aspectratio:e/i},o=!0;return d(t,function(t,e){var i=e.match(kI);if(i&&i[1]&&i[2]){var a=i[1],r=i[2].toLowerCase();Ua(n[r],t,a)||(o=!1)}}),o}function Ua(t,e,i){return"min"===i?t>=e:"max"===i?t<=e:t===e}function Xa(t,e){return t.join(",")===e.join(",")}function ja(t,e){AI(e=e||{},function(e,i){if(null!=e){var n=t[i];if(lI.hasClass(i)){e=Di(e);var o=Pi(n=Di(n),e);t[i]=CI(o,function(t){return t.option&&t.exist?LI(t.exist,t.option,!0):t.exist||t.option})}else t[i]=LI(n,e,!0)}})}function Ya(t){var e=t&&t.itemStyle;if(e)for(var i=0,o=OI.length;i<o;i++){var a=OI[i],r=e.normal,s=e.emphasis;r&&r[a]&&(t[a]=t[a]||{},t[a].normal?n(t[a].normal,r[a]):t[a].normal=r[a],r[a]=null),s&&s[a]&&(t[a]=t[a]||{},t[a].emphasis?n(t[a].emphasis,s[a]):t[a].emphasis=s[a],s[a]=null)}}function qa(t,e,i){if(t&&t[e]&&(t[e].normal||t[e].emphasis)){var n=t[e].normal,o=t[e].emphasis;n&&(i?(t[e].normal=t[e].emphasis=null,r(t[e],n)):t[e]=n),o&&(t.emphasis=t.emphasis||{},t.emphasis[e]=o)}}function Ka(t){qa(t,"itemStyle"),qa(t,"lineStyle"),qa(t,"areaStyle"),qa(t,"label"),qa(t,"labelLine"),qa(t,"upperLabel"),qa(t,"edgeLabel")}function $a(t,e){var i=NI(t)&&t[e],n=NI(i)&&i.textStyle;if(n)for(var o=0,a=Yb.length;o<a;o++){var e=Yb[o];n.hasOwnProperty(e)&&(i[e]=n[e])}}function Ja(t){t&&(Ka(t),$a(t,"label"),t.emphasis&&$a(t.emphasis,"label"))}function Qa(t){if(NI(t)){Ya(t),Ka(t),$a(t,"label"),$a(t,"upperLabel"),$a(t,"edgeLabel"),t.emphasis&&($a(t.emphasis,"label"),$a(t.emphasis,"upperLabel"),$a(t.emphasis,"edgeLabel"));var e=t.markPoint;e&&(Ya(e),Ja(e));var i=t.markLine;i&&(Ya(i),Ja(i));var n=t.markArea;n&&Ja(n);var o=t.data;if("graph"===t.type){o=o||t.nodes;var a=t.links||t.edges;if(a&&!S(a))for(s=0;s<a.length;s++)Ja(a[s]);d(t.categories,function(t){Ka(t)})}if(o&&!S(o))for(s=0;s<o.length;s++)Ja(o[s]);if((e=t.markPoint)&&e.data)for(var r=e.data,s=0;s<r.length;s++)Ja(r[s]);if((i=t.markLine)&&i.data)for(var l=i.data,s=0;s<l.length;s++)y(l[s])?(Ja(l[s][0]),Ja(l[s][1])):Ja(l[s]);"gauge"===t.type?($a(t,"axisLabel"),$a(t,"title"),$a(t,"detail")):"treemap"===t.type?(qa(t.breadcrumb,"itemStyle"),d(t.levels,function(t){Ka(t)})):"tree"===t.type&&Ka(t.leaves)}}function tr(t){return y(t)?t:t?[t]:[]}function er(t){return(y(t)?t[0]:t)||{}}function ir(t,e){e=e.split(",");for(var i=t,n=0;n<e.length&&null!=(i=i&&i[e[n]]);n++);return i}function nr(t,e,i,n){e=e.split(",");for(var o,a=t,r=0;r<e.length-1;r++)null==a[o=e[r]]&&(a[o]={}),a=a[o];(n||null==a[e[r]])&&(a[e[r]]=i)}function or(t){d(RI,function(e){e[0]in t&&!(e[1]in t)&&(t[e[1]]=t[e[0]])})}function ar(t){d(t,function(e,i){var n=[],o=[NaN,NaN],a=[e.stackResultDimension,e.stackedOverDimension],r=e.data,s=e.isStackedByIndex,l=r.map(a,function(a,l,u){var h=r.get(e.stackedDimension,u);if(isNaN(h))return o;var c,d;s?d=r.getRawIndex(u):c=r.get(e.stackedByDimension,u);for(var f=NaN,p=i-1;p>=0;p--){var g=t[p];if(s||(d=g.data.rawIndexOf(g.stackedByDimension,c)),d>=0){var m=g.data.getByRawIndex(g.stackResultDimension,d);if(h>=0&&m>0||h<=0&&m<0){h+=m,f=m;break}}}return n[0]=h,n[1]=f,n});r.hostModel.setData(l),e.data=l})}function rr(t,e){_a.isInstance(t)||(t=_a.seriesDataToSource(t)),this._source=t;var i=this._data=t.data,n=t.sourceFormat;n===xI&&(this._offset=0,this._dimSize=e,this._data=i),a(this,GI[n===gI?n+"_"+t.seriesLayoutBy:n])}function sr(){return this._data.length}function lr(t){return this._data[t]}function ur(t){for(var e=0;e<t.length;e++)this._data.push(t[e])}function hr(t,e,i,n){return null!=i?t[i]:t}function cr(t,e,i,n){return dr(t[n],this._dimensionInfos[e])}function dr(t,e){var i=e&&e.type;if("ordinal"===i){var n=e&&e.ordinalMeta;return n?n.parseAndCollect(t):t}return"time"===i&&"number"!=typeof t&&null!=t&&"-"!==t&&(t=+Yo(t)),null==t||""===t?NaN:+t}function fr(t,e,i){if(t){var n=t.getRawDataItem(e);if(null!=n){var o,a,r=t.getProvider().getSource().sourceFormat,s=t.getDimensionInfo(i);return s&&(o=s.name,a=s.index),FI[r](n,e,a,o)}}}function pr(t,e,i){if(t){var n=t.getProvider().getSource().sourceFormat;if(n===pI||n===mI){var o=t.getRawDataItem(e);return n!==pI||w(o)||(o=null),o?o[i]:void 0}}}function gr(t){return new mr(t)}function mr(t){t=t||{},this._reset=t.reset,this._plan=t.plan,this._count=t.count,this._onDirty=t.onDirty,this._dirty=!0,this.context}function vr(t,e,i,n,o,a){XI.reset(i,n,o,a),t._callingProgress=e,t._callingProgress({start:i,end:n,count:n-i,next:XI.next},t.context)}function yr(t,e){t._dueIndex=t._outputDueEnd=t._dueEnd=0,t._settedOutputEnd=null;var i,n;!e&&t._reset&&((i=t._reset(t.context))&&i.progress&&(n=i.forceFirstProgress,i=i.progress),y(i)&&!i.length&&(i=null)),t._progress=i,t._modBy=t._modDataCount=null;var o=t._downstream;return o&&o.dirty(),n}function xr(t){var e=t.name;Oi(t)||(t.name=_r(t)||e)}function _r(t){var e=t.getRawData(),i=[];return d(e.mapDimension("seriesName",!0),function(t){var n=e.getDimensionInfo(t);n.displayName&&i.push(n.displayName)}),i.join(" ")}function wr(t){return t.model.getRawData().count()}function br(t){var e=t.model;return e.setData(e.getRawData().cloneShallow()),Sr}function Sr(t,e){t.end>e.outputData.count()&&e.model.getRawData().cloneShallow(e.outputData)}function Mr(t,e){d(t.CHANGABLE_METHODS,function(i){t.wrapMethod(i,v(Ir,e))})}function Ir(t){var e=Tr(t);e&&e.setOutputEnd(this.count())}function Tr(t){var e=(t.ecModel||{}).scheduler,i=e&&e.getPipeline(t.uid);if(i){var n=i.currentTask;if(n){var o=n.agentStubMap;o&&(n=o.get(t.uid))}return n}}function Ar(){this.group=new tb,this.uid=Ro("viewChart"),this.renderTask=gr({plan:Lr,reset:kr}),this.renderTask.context={view:this}}function Dr(t,e){if(t&&(t.trigger(e),"group"===t.type))for(var i=0;i<t.childCount();i++)Dr(t.childAt(i),e)}function Cr(t,e,i){var n=zi(t,e);null!=n?d(Di(n),function(e){Dr(t.getItemGraphicEl(e),i)}):t.eachItemGraphicEl(function(t){Dr(t,i)})}function Lr(t){return QI(t.model)}function kr(t){var e=t.model,i=t.ecModel,n=t.api,o=t.payload,a=e.pipelineContext.progressiveRender,r=t.view,s=o&&JI(o).updateMethod,l=a?"incrementalPrepareRender":s&&r[s]?s:"render";return"render"!==l&&r[l](e,i,n,o),eT[l]}function Pr(t,e,i){function n(){h=(new Date).getTime(),c=null,t.apply(r,s||[])}var o,a,r,s,l,u=0,h=0,c=null;e=e||0;var d=function(){o=(new Date).getTime(),r=this,s=arguments;var t=l||e,d=l||i;l=null,a=o-(d?u:h)-t,clearTimeout(c),d?c=setTimeout(n,t):a>=0?n():c=setTimeout(n,-a),u=o};return d.clear=function(){c&&(clearTimeout(c),c=null)},d.debounceNextCall=function(t){l=t},d}function Nr(t,e,i,n){var o=t[e];if(o){var a=o[iT]||o,r=o[oT];if(o[nT]!==i||r!==n){if(null==i||!n)return t[e]=a;(o=t[e]=Pr(a,i,"debounce"===n))[iT]=a,o[oT]=n,o[nT]=i}return o}}function Or(t,e){var i=t[e];i&&i[iT]&&(t[e]=i[iT])}function Er(t,e,i,n){this.ecInstance=t,this.api=e,this.unfinished;var i=this._dataProcessorHandlers=i.slice(),n=this._visualHandlers=n.slice();this._allHandlers=i.concat(n),this._stageTaskMap=R()}function Rr(t,e,i,n,o){function a(t,e){return t.setDirty&&(!t.dirtyMap||t.dirtyMap.get(e.__pipeline.id))}o=o||{};var r;d(e,function(e,s){if(!o.visualType||o.visualType===e.visualType){var l=t._stageTaskMap.get(e.uid),u=l.seriesTaskMap,h=l.overallTask;if(h){var c,d=h.agentStubMap;d.each(function(t){a(o,t)&&(t.dirty(),c=!0)}),c&&h.dirty(),hT(h,n);var f=t.getPerformArgs(h,o.block);d.each(function(t){t.perform(f)}),r|=h.perform(f)}else u&&u.each(function(s,l){a(o,s)&&s.dirty();var u=t.getPerformArgs(s,o.block);u.skip=!e.performRawSeries&&i.isSeriesFiltered(s.context.model),hT(s,n),r|=s.perform(u)})}}),t.unfinished|=r}function zr(t,e,i,n,o){function a(i){var a=i.uid,s=r.get(a)||r.set(a,gr({plan:Hr,reset:Zr,count:Xr}));s.context={model:i,ecModel:n,api:o,useClearVisual:e.isVisual&&!e.isLayout,plan:e.plan,reset:e.reset,scheduler:t},jr(t,i,s)}var r=i.seriesTaskMap||(i.seriesTaskMap=R()),s=e.seriesType,l=e.getTargetSeries;e.createOnAllSeries?n.eachRawSeries(a):s?n.eachRawSeriesByType(s,a):l&&l(n,o).each(a);var u=t._pipelineMap;r.each(function(t,e){u.get(e)||(t.dispose(),r.removeKey(e))})}function Br(t,e,i,n,o){function a(e){var i=e.uid,n=s.get(i);n||(n=s.set(i,gr({reset:Gr,onDirty:Wr})),r.dirty()),n.context={model:e,overallProgress:h,modifyOutputEnd:c},n.agent=r,n.__block=h,jr(t,e,n)}var r=i.overallTask=i.overallTask||gr({reset:Vr});r.context={ecModel:n,api:o,overallReset:e.overallReset,scheduler:t};var s=r.agentStubMap=r.agentStubMap||R(),l=e.seriesType,u=e.getTargetSeries,h=!0,c=e.modifyOutputEnd;l?n.eachRawSeriesByType(l,a):u?u(n,o).each(a):(h=!1,d(n.getSeries(),a));var f=t._pipelineMap;s.each(function(t,e){f.get(e)||(t.dispose(),r.dirty(),s.removeKey(e))})}function Vr(t){t.overallReset(t.ecModel,t.api,t.payload)}function Gr(t,e){return t.overallProgress&&Fr}function Fr(){this.agent.dirty(),this.getDownstream().dirty()}function Wr(){this.agent&&this.agent.dirty()}function Hr(t){return t.plan&&t.plan(t.model,t.ecModel,t.api,t.payload)}function Zr(t){t.useClearVisual&&t.data.clearAllVisual();var e=t.resetDefines=Di(t.reset(t.model,t.ecModel,t.api,t.payload));return e.length>1?f(e,function(t,e){return Ur(e)}):cT}function Ur(t){return function(e,i){var n=i.data,o=i.resetDefines[t];if(o&&o.dataEach)for(var a=e.start;a<e.end;a++)o.dataEach(n,a);else o&&o.progress&&o.progress(e,n)}}function Xr(t){return t.data.count()}function jr(t,e,i){var n=e.uid,o=t._pipelineMap.get(n);!o.head&&(o.head=i),o.tail&&o.tail.pipe(i),o.tail=i,i.__idxInPipeline=o.count++,i.__pipeline=o}function Yr(t){dT=null;try{t(fT,pT)}catch(t){}return dT}function qr(t,e){for(var i in e.prototype)t[i]=B}function Kr(t){for(_(t)&&(t=(new DOMParser).parseFromString(t,"text/xml")),9===t.nodeType&&(t=t.firstChild);"svg"!==t.nodeName.toLowerCase()||1!==t.nodeType;)t=t.nextSibling;return t}function $r(){this._defs={},this._root=null,this._isDefine=!1,this._isText=!1}function Jr(t,e){for(var i=t.firstChild;i;){if(1===i.nodeType){var n=i.getAttribute("offset");n=n.indexOf("%")>0?parseInt(n,10)/100:n?parseFloat(n):0;var o=i.getAttribute("stop-color")||"#000000";e.addColorStop(n,o)}i=i.nextSibling}}function Qr(t,e){t&&t.__inheritedStyle&&(e.__inheritedStyle||(e.__inheritedStyle={}),r(e.__inheritedStyle,t.__inheritedStyle))}function ts(t){for(var e=P(t).split(_T),i=[],n=0;n<e.length;n+=2){var o=parseFloat(e[n]),a=parseFloat(e[n+1]);i.push([o,a])}return i}function es(t,e,i,n){var o=e.__inheritedStyle||{},r="text"===e.type;if(1===t.nodeType&&(ns(t,e),a(o,os(t)),!n))for(var s in ST)if(ST.hasOwnProperty(s)){var l=t.getAttribute(s);null!=l&&(o[ST[s]]=l)}var u=r?"textFill":"fill",h=r?"textStroke":"stroke";e.style=e.style||new ub;var c=e.style;null!=o.fill&&c.set(u,is(o.fill,i)),null!=o.stroke&&c.set(h,is(o.stroke,i)),d(["lineWidth","opacity","fillOpacity","strokeOpacity","miterLimit","fontSize"],function(t){var e="lineWidth"===t&&r?"textStrokeWidth":t;null!=o[t]&&c.set(e,parseFloat(o[t]))}),o.textBaseline&&"auto"!==o.textBaseline||(o.textBaseline="alphabetic"),"alphabetic"===o.textBaseline&&(o.textBaseline="bottom"),"start"===o.textAlign&&(o.textAlign="left"),"end"===o.textAlign&&(o.textAlign="right"),d(["lineDashOffset","lineCap","lineJoin","fontWeight","fontFamily","fontStyle","textAlign","textBaseline"],function(t){null!=o[t]&&c.set(t,o[t])}),o.lineDash&&(e.style.lineDash=P(o.lineDash).split(_T)),c[h]&&"none"!==c[h]&&(e[h]=!0),e.__inheritedStyle=o}function is(t,e){var i=e&&t&&t.match(MT);return i?e[P(i[1])]:t}function ns(t,e){var i=t.getAttribute("transform");if(i){var n=null,o=[];(i=i.replace(/,/g," ")).replace(IT,function(t,e,i){o.push(e,i)});for(var a=o.length-1;a>0;a-=2){var r=o[a],s=o[a-1];switch(n=n||xt(),s){case"translate":r=P(r).split(_T),St(n,n,[parseFloat(r[0]),parseFloat(r[1]||0)]);break;case"scale":r=P(r).split(_T),It(n,n,[parseFloat(r[0]),parseFloat(r[1]||r[0])]);break;case"rotate":r=P(r).split(_T),Mt(n,n,parseFloat(r[0]));break;case"skew":r=P(r).split(_T),console.warn("Skew transform is not supported yet");break;case"matrix":r=P(r).split(_T);n[0]=parseFloat(r[0]),n[1]=parseFloat(r[1]),n[2]=parseFloat(r[2]),n[3]=parseFloat(r[3]),n[4]=parseFloat(r[4]),n[5]=parseFloat(r[5])}}e.setLocalTransform(n)}}function os(t){var e=t.getAttribute("style"),i={};if(!e)return i;var n={};TT.lastIndex=0;for(var o;null!=(o=TT.exec(e));)n[o[1]]=o[2];for(var a in ST)ST.hasOwnProperty(a)&&null!=n[a]&&(i[ST[a]]=n[a]);return i}function as(t,e,i){var n=e/t.width,o=i/t.height,a=Math.min(n,o);return{scale:[a,a],position:[-(t.x+t.width/2)*a+e/2,-(t.y+t.height/2)*a+i/2]}}function rs(t,e){return(new $r).parse(t,e)}function ss(t){return function(e,i,n){e=e&&e.toLowerCase(),fw.prototype[t].call(this,e,i,n)}}function ls(){fw.call(this)}function us(t,e,n){function o(t,e){return t.__prio-e.__prio}n=n||{},"string"==typeof e&&(e=JT[e]),this.id,this.group,this._dom=t;var a=this._zr=Ii(t,{renderer:n.renderer||"canvas",devicePixelRatio:n.devicePixelRatio,width:n.width,height:n.height});this._throttledZrFlush=Pr(m(a.flush,a),17),(e=i(e))&&BI(e,!0),this._theme=e,this._chartsViews=[],this._chartsMap={},this._componentsViews=[],this._componentsMap={},this._coordSysMgr=new Fa;var r=this._api=As(this);_e($T,o),_e(YT,o),this._scheduler=new Er(this,r,YT,$T),fw.call(this,this._ecEventProcessor=new Ds),this._messageCenter=new ls,this._initEvents(),this.resize=m(this.resize,this),this._pendingActions=[],a.animation.on("frame",this._onframe,this),vs(a,this),N(this)}function hs(t,e,i){var n,o=this._model,a=this._coordSysMgr.getCoordinateSystems();e=Vi(o,e);for(var r=0;r<a.length;r++){var s=a[r];if(s[t]&&null!=(n=s[t](o,e,i)))return n}}function cs(t){var e=t._model,i=t._scheduler;i.restorePipelines(e),i.prepareStageTasks(),ys(t,"component",e,i),ys(t,"chart",e,i),i.plan()}function ds(t,e,i,n,o){function a(n){n&&n.__alive&&n[e]&&n[e](n.__model,r,t._api,i)}var r=t._model;if(n){var s={};s[n+"Id"]=i[n+"Id"],s[n+"Index"]=i[n+"Index"],s[n+"Name"]=i[n+"Name"];var l={mainType:n,query:s};o&&(l.subType=o);var u=i.excludeSeriesId;null!=u&&(u=R(Di(u))),r&&r.eachComponent(l,function(e){u&&null!=u.get(e.id)||a(t["series"===n?"_chartsMap":"_componentsMap"][e.__viewId])},t)}else kT(t._componentsViews.concat(t._chartsViews),a)}function fs(t,e){var i=t._chartsMap,n=t._scheduler;e.eachSeries(function(t){n.updateStreamModes(t,i[t.__viewId])})}function ps(t,e){var i=t.type,n=t.escapeConnect,o=XT[i],s=o.actionInfo,l=(s.update||"update").split(":"),u=l.pop();l=null!=l[0]&&OT(l[0]),this[GT]=!0;var h=[t],c=!1;t.batch&&(c=!0,h=f(t.batch,function(e){return e=r(a({},e),t),e.batch=null,e}));var d,p=[],g="highlight"===i||"downplay"===i;kT(h,function(t){d=o.action(t,this._model,this._api),(d=d||a({},t)).type=s.event||d.type,p.push(d),g?ds(this,u,t,"series"):l&&ds(this,u,t,l.main,l.sub)},this),"none"===u||g||l||(this[FT]?(cs(this),ZT.update.call(this,t),this[FT]=!1):ZT[u].call(this,t)),d=c?{type:s.event||i,escapeConnect:n,batch:p}:p[0],this[GT]=!1,!e&&this._messageCenter.trigger(d.type,d)}function gs(t){for(var e=this._pendingActions;e.length;){var i=e.shift();ps.call(this,i,t)}}function ms(t){!t&&this.trigger("updated")}function vs(t,e){t.on("rendered",function(){e.trigger("rendered"),!t.animation.isFinished()||e[FT]||e._scheduler.unfinished||e._pendingActions.length||e.trigger("finished")})}function ys(t,e,i,n){function o(t){var e="_ec_"+t.id+"_"+t.type,o=s[e];if(!o){var h=OT(t.type);(o=new(a?qI.getClass(h.main,h.sub):Ar.getClass(h.sub))).init(i,u),s[e]=o,r.push(o),l.add(o.group)}t.__viewId=o.__id=e,o.__alive=!0,o.__model=t,o.group.__ecComponentInfo={mainType:t.mainType,index:t.componentIndex},!a&&n.prepareView(o,t,i,u)}for(var a="component"===e,r=a?t._componentsViews:t._chartsViews,s=a?t._componentsMap:t._chartsMap,l=t._zr,u=t._api,h=0;h<r.length;h++)r[h].__alive=!1;a?i.eachComponent(function(t,e){"series"!==t&&o(e)}):i.eachSeries(o);for(h=0;h<r.length;){var c=r[h];c.__alive?h++:(!a&&c.renderTask.dispose(),l.remove(c.group),c.dispose(i,u),r.splice(h,1),delete s[c.__id],c.__id=c.group.__ecComponentInfo=null)}}function xs(t){t.clearColorPalette(),t.eachSeries(function(t){t.clearColorPalette()})}function _s(t,e,i,n){ws(t,e,i,n),kT(t._chartsViews,function(t){t.__alive=!1}),bs(t,e,i,n),kT(t._chartsViews,function(t){t.__alive||t.remove(e,i)})}function ws(t,e,i,n,o){kT(o||t._componentsViews,function(t){var o=t.__model;t.render(o,e,i,n),Ts(o,t)})}function bs(t,e,i,n,o){var a,r=t._scheduler;e.eachSeries(function(e){var i=t._chartsMap[e.__viewId];i.__alive=!0;var s=i.renderTask;r.updatePayload(s,n),o&&o.get(e.uid)&&s.dirty(),a|=s.perform(r.getPerformArgs(s)),i.group.silent=!!e.get("silent"),Ts(e,i),Is(e,i)}),r.unfinished|=a,Ms(t._zr,e),sT(t._zr.dom,e)}function Ss(t,e){kT(KT,function(i){i(t,e)})}function Ms(t,e){var i=t.storage,n=0;i.traverse(function(t){t.isGroup||n++}),n>e.get("hoverLayerThreshold")&&!U_.node&&i.traverse(function(t){t.isGroup||(t.useHoverLayer=!0)})}function Is(t,e){var i=t.get("blendMode")||null;e.group.traverse(function(t){t.isGroup||t.style.blend!==i&&t.setStyle("blend",i),t.eachPendingDisplayable&&t.eachPendingDisplayable(function(t){t.setStyle("blend",i)})})}function Ts(t,e){var i=t.get("z"),n=t.get("zlevel");e.group.traverse(function(t){"group"!==t.type&&(null!=i&&(t.z=i),null!=n&&(t.zlevel=n))})}function As(t){var e=t._coordSysMgr;return a(new Ga(t),{getCoordinateSystems:m(e.getCoordinateSystems,e),getComponentByElement:function(e){for(;e;){var i=e.__ecComponentInfo;if(null!=i)return t._model.getComponent(i.mainType,i.index);e=e.parent}}})}function Ds(){this.eventInfo}function Cs(t){function e(t,e){for(var n=0;n<t.length;n++)t[n][i]=e}var i="__connectUpdateStatus";kT(jT,function(n,o){t._messageCenter.on(o,function(n){if(eA[t.group]&&0!==t[i]){if(n&&n.escapeConnect)return;var o=t.makeActionFromEvent(n),a=[];kT(tA,function(e){e!==t&&e.group===t.group&&a.push(e)}),e(a,0),kT(a,function(t){1!==t[i]&&t.dispatchAction(o)}),e(a,2)}})})}function Ls(t){eA[t]=!1}function ks(t){return tA[Wi(t,oA)]}function Ps(t,e){JT[t]=e}function Ns(t){qT.push(t)}function Os(t,e){Vs(YT,t,e,RT)}function Es(t,e,i){"function"==typeof e&&(i=e,e="");var n=NT(t)?t.type:[t,t={event:e}][0];t.event=(t.event||n).toLowerCase(),e=t.event,LT(WT.test(n)&&WT.test(e)),XT[n]||(XT[n]={action:i,actionInfo:t}),jT[e]=n}function Rs(t,e){Fa.register(t,e)}function zs(t,e){Vs($T,t,e,zT,"layout")}function Bs(t,e){Vs($T,t,e,BT,"visual")}function Vs(t,e,i,n,o){(PT(e)||NT(e))&&(i=e,e=n);var a=Er.wrapStageHandler(i,o);return a.__prio=e,a.__raw=i,t.push(a),a}function Gs(t,e){QT[t]=e}function Fs(t){return lI.extend(t)}function Ws(t){return qI.extend(t)}function Hs(t){return YI.extend(t)}function Zs(t){return Ar.extend(t)}function Us(t){return t}function Xs(t,e,i,n,o){this._old=t,this._new=e,this._oldKeyGetter=i||Us,this._newKeyGetter=n||Us,this.context=o}function js(t,e,i,n,o){for(var a=0;a<t.length;a++){var r="_ec_"+o[n](t[a],a),s=e[r];null==s?(i.push(r),e[r]=a):(s.length||(e[r]=s=[s]),s.push(a))}}function Ys(t){var e={},i=e.encode={},n=R(),o=[],a=[];d(t.dimensions,function(e){var r=t.getDimensionInfo(e),s=r.coordDim;if(s){var l=i[s];i.hasOwnProperty(s)||(l=i[s]=[]),l[r.coordDimIndex]=e,r.isExtraCoord||(n.set(s,1),Ks(r.type)&&(o[0]=e)),r.defaultTooltip&&a.push(e)}sA.each(function(t,e){var n=i[e];i.hasOwnProperty(e)||(n=i[e]=[]);var o=r.otherDims[e];null!=o&&!1!==o&&(n[o]=r.name)})});var r=[],s={};n.each(function(t,e){var n=i[e];s[e]=n[0],r=r.concat(n)}),e.dataDimsOnCoord=r,e.encodeFirstDimNotExtra=s;var l=i.label;l&&l.length&&(o=l.slice());var u=i.tooltip;return u&&u.length?a=u.slice():a.length||(a=o.slice()),i.defaultedLabel=o,i.defaultedTooltip=a,e}function qs(t){return"category"===t?"ordinal":"time"===t?"time":"float"}function Ks(t){return!("ordinal"===t||"time"===t)}function $s(t){return t._rawCount>65535?dA:pA}function Js(t){var e=t.constructor;return e===Array?t.slice():new e(t)}function Qs(t,e){d(gA.concat(e.__wrappedMethods||[]),function(i){e.hasOwnProperty(i)&&(t[i]=e[i])}),t.__wrappedMethods=e.__wrappedMethods,d(mA,function(n){t[n]=i(e[n])}),t._calculationInfo=a(e._calculationInfo)}function tl(t,e,i,n,o){var a=cA[e.type],r=n-1,s=e.name,l=t[s][r];if(l&&l.length<i){for(var u=new a(Math.min(o-r*i,i)),h=0;h<l.length;h++)u[h]=l[h];t[s][r]=u}for(var c=n*i;c<o;c+=i)t[s].push(new a(Math.min(o-c,i)))}function el(t){var e=t._invertedIndicesMap;d(e,function(i,n){var o=t._dimensionInfos[n].ordinalMeta;if(o){i=e[n]=new fA(o.categories.length);for(a=0;a<i.length;a++)i[a]=uA;for(var a=0;a<t._count;a++)i[t.get(n,a)]=a}})}function il(t,e,i){var n;if(null!=e){var o=t._chunkSize,a=Math.floor(i/o),r=i%o,s=t.dimensions[e],l=t._storage[s][a];if(l){n=l[r];var u=t._dimensionInfos[s].ordinalMeta;u&&u.categories.length&&(n=u.categories[n])}}return n}function nl(t){return t}function ol(t){return t<this._count&&t>=0?this._indices[t]:-1}function al(t,e){var i=t._idList[e];return null==i&&(i=il(t,t._idDimIdx,e)),null==i&&(i=hA+e),i}function rl(t){return y(t)||(t=[t]),t}function sl(t,e){var i=t.dimensions,n=new vA(f(i,t.getDimensionInfo,t),t.hostModel);Qs(n,t);for(var o=n._storage={},a=t._storage,r=0;r<i.length;r++){var s=i[r];a[s]&&(l(e,s)>=0?(o[s]=ll(a[s]),n._rawExtent[s]=ul(),n._extent[s]=null):o[s]=a[s])}return n}function ll(t){for(var e=new Array(t.length),i=0;i<t.length;i++)e[i]=Js(t[i]);return e}function ul(){return[1/0,-1/0]}function hl(t,e,n){function o(t,e,i){null!=sA.get(e)?t.otherDims[e]=i:(t.coordDim=e,t.coordDimIndex=i,h.set(e,!0))}_a.isInstance(e)||(e=_a.seriesDataToSource(e)),n=n||{},t=(t||[]).slice();for(var s=(n.dimsDef||[]).slice(),l=R(n.encodeDef),u=R(),h=R(),c=[],f=cl(e,t,s,n.dimCount),p=0;p<f;p++){var g=s[p]=a({},w(s[p])?s[p]:{name:s[p]}),m=g.name,v=c[p]={otherDims:{}};null!=m&&null==u.get(m)&&(v.name=v.displayName=m,u.set(m,p)),null!=g.type&&(v.type=g.type),null!=g.displayName&&(v.displayName=g.displayName)}l.each(function(t,e){if(1===(t=Di(t).slice()).length&&t[0]<0)l.set(e,!1);else{var i=l.set(e,[]);d(t,function(t,n){_(t)&&(t=u.get(t)),null!=t&&t<f&&(i[n]=t,o(c[t],e,n))})}});var y=0;d(t,function(t,e){var n,t,a,s;if(_(t))n=t,t={};else{n=t.name;var u=t.ordinalMeta;t.ordinalMeta=null,(t=i(t)).ordinalMeta=u,a=t.dimsDef,s=t.otherDims,t.name=t.coordDim=t.coordDimIndex=t.dimsDef=t.otherDims=null}var h=l.get(n);if(!1!==h){if(!(h=Di(h)).length)for(var f=0;f<(a&&a.length||1);f++){for(;y<c.length&&null!=c[y].coordDim;)y++;y<c.length&&h.push(y++)}d(h,function(e,i){var l=c[e];if(o(r(l,t),n,i),null==l.name&&a){var u=a[i];!w(u)&&(u={name:u}),l.name=l.displayName=u.name,l.defaultTooltip=u.defaultTooltip}s&&r(l.otherDims,s)})}});var x=n.generateCoord,b=n.generateCoordCount,S=null!=b;b=x?b||1:0;for(var M=x||"value",I=0;I<f;I++)null==(v=c[I]=c[I]||{}).coordDim&&(v.coordDim=dl(M,h,S),v.coordDimIndex=0,(!x||b<=0)&&(v.isExtraCoord=!0),b--),null==v.name&&(v.name=dl(v.coordDim,u)),null==v.type&&ka(e,I,v.name)&&(v.type="ordinal");return c}function cl(t,e,i,n){var o=Math.max(t.dimensionsDetectCount||1,e.length,i.length,n||0);return d(e,function(t){var e=t.dimsDef;e&&(o=Math.max(o,e.length))}),o}function dl(t,e,i){if(i||null!=e.get(t)){for(var n=0;null!=e.get(t+n);)n++;t+=n}return e.set(t,!0),t}function fl(t,e,i){var n,o,a,r,s=(i=i||{}).byIndex,l=i.stackedCoordDimension,u=!(!t||!t.get("stack"));if(d(e,function(t,i){_(t)&&(e[i]=t={name:t}),u&&!t.isExtraCoord&&(s||n||!t.ordinalMeta||(n=t),o||"ordinal"===t.type||"time"===t.type||l&&l!==t.coordDim||(o=t))}),!o||s||n||(s=!0),o){a="__\0ecstackresult",r="__\0ecstackedover",n&&(n.createInvertedIndices=!0);var h=o.coordDim,c=o.type,f=0;d(e,function(t){t.coordDim===h&&f++}),e.push({name:a,coordDim:h,coordDimIndex:f,type:c,isExtraCoord:!0,isCalculationCoord:!0}),f++,e.push({name:r,coordDim:r,coordDimIndex:f,type:c,isExtraCoord:!0,isCalculationCoord:!0})}return{stackedDimension:o&&o.name,stackedByDimension:n&&n.name,isStackedByIndex:s,stackedOverDimension:r,stackResultDimension:a}}function pl(t,e){return!!e&&e===t.getCalculationInfo("stackedDimension")}function gl(t,e){return pl(t,e)?t.getCalculationInfo("stackResultDimension"):e}function ml(t,e,i){i=i||{},_a.isInstance(t)||(t=_a.seriesDataToSource(t));var n,o=e.get("coordinateSystem"),a=Fa.get(o),r=ya(e);r&&(n=f(r.coordSysDims,function(t){var e={name:t},i=r.axisMap.get(t);if(i){var n=i.get("type");e.type=qs(n)}return e})),n||(n=a&&(a.getDimensionsInfo?a.getDimensionsInfo():a.dimensions.slice())||["x","y"]);var s,l,u=_A(t,{coordDimensions:n,generateCoord:i.generateCoord});r&&d(u,function(t,e){var i=t.coordDim,n=r.categoryAxisMap.get(i);n&&(null==s&&(s=e),t.ordinalMeta=n.getOrdinalMeta()),null!=t.otherDims.itemName&&(l=!0)}),l||null==s||(u[s].otherDims.itemName=0);var h=fl(e,u),c=new vA(u,e);c.setCalculationInfo(h);var p=null!=s&&vl(t)?function(t,e,i,n){return n===s?i:this.defaultDimValueGetter(t,e,i,n)}:null;return c.hasItemOption=!1,c.initData(t,null,p),c}function vl(t){if(t.sourceFormat===pI){var e=yl(t.data||[]);return null!=e&&!y(Li(e))}}function yl(t){for(var e=0;e<t.length&&null==t[e];)e++;return t[e]}function xl(t){this._setting=t||{},this._extent=[1/0,-1/0],this._interval=0,this.init&&this.init.apply(this,arguments)}function _l(t){this.categories=t.categories||[],this._needCollect=t.needCollect,this._deduplication=t.deduplication,this._map}function wl(t){return t._map||(t._map=R(t.categories))}function bl(t){return w(t)&&null!=t.value?t.value:t+""}function Sl(t,e,i,n){var o={},a=t[1]-t[0],r=o.interval=$o(a/e,!0);null!=i&&r<i&&(r=o.interval=i),null!=n&&r>n&&(r=o.interval=n);var s=o.intervalPrecision=Ml(r);return Tl(o.niceTickExtent=[MA(Math.ceil(t[0]/r)*r,s),MA(Math.floor(t[1]/r)*r,s)],t),o}function Ml(t){return Ho(t)+2}function Il(t,e,i){t[e]=Math.max(Math.min(t[e],i[1]),i[0])}function Tl(t,e){!isFinite(t[0])&&(t[0]=e[0]),!isFinite(t[1])&&(t[1]=e[1]),Il(t,0,e),Il(t,1,e),t[0]>t[1]&&(t[0]=t[1])}function Al(t,e,i,n){var o=[];if(!t)return o;e[0]<i[0]&&o.push(e[0]);for(var a=i[0];a<=i[1]&&(o.push(a),(a=MA(a+t,n))!==o[o.length-1]);)if(o.length>1e4)return[];return e[1]>(o.length?o[o.length-1]:i[1])&&o.push(e[1]),o}function Dl(t){return t.get("stack")||AA+t.seriesIndex}function Cl(t){return t.dim+t.index}function Ll(t){var e=[],i=t.axis;if("category"===i.type){for(var n=i.getBandWidth(),o=0;o<t.count;o++)e.push(r({bandWidth:n,axisKey:"axis0",stackId:AA+o},t));for(var a=Nl(e),s=[],o=0;o<t.count;o++){var l=a.axis0[AA+o];l.offsetCenter=l.offset+l.width/2,s.push(l)}return s}}function kl(t,e){var i=[];return e.eachSeriesByType(t,function(t){Rl(t)&&!zl(t)&&i.push(t)}),i}function Pl(t){var e=[];return d(t,function(t){var i=t.getData(),n=t.coordinateSystem.getBaseAxis(),o=n.getExtent(),a="category"===n.type?n.getBandWidth():Math.abs(o[1]-o[0])/i.count(),r=Vo(t.get("barWidth"),a),s=Vo(t.get("barMaxWidth"),a),l=t.get("barGap"),u=t.get("barCategoryGap");e.push({bandWidth:a,barWidth:r,barMaxWidth:s,barGap:l,barCategoryGap:u,axisKey:Cl(n),stackId:Dl(t)})}),Nl(e)}function Nl(t){var e={};d(t,function(t,i){var n=t.axisKey,o=t.bandWidth,a=e[n]||{bandWidth:o,remainedWidth:o,autoWidthCount:0,categoryGap:"20%",gap:"30%",stacks:{}},r=a.stacks;e[n]=a;var s=t.stackId;r[s]||a.autoWidthCount++,r[s]=r[s]||{width:0,maxWidth:0};var l=t.barWidth;l&&!r[s].width&&(r[s].width=l,l=Math.min(a.remainedWidth,l),a.remainedWidth-=l);var u=t.barMaxWidth;u&&(r[s].maxWidth=u);var h=t.barGap;null!=h&&(a.gap=h);var c=t.barCategoryGap;null!=c&&(a.categoryGap=c)});var i={};return d(e,function(t,e){i[e]={};var n=t.stacks,o=t.bandWidth,a=Vo(t.categoryGap,o),r=Vo(t.gap,1),s=t.remainedWidth,l=t.autoWidthCount,u=(s-a)/(l+(l-1)*r);u=Math.max(u,0),d(n,function(t,e){var i=t.maxWidth;i&&i<u&&(i=Math.min(i,s),t.width&&(i=Math.min(i,t.width)),s-=i,t.width=i,l--)}),u=(s-a)/(l+(l-1)*r),u=Math.max(u,0);var h,c=0;d(n,function(t,e){t.width||(t.width=u),h=t,c+=t.width*(1+r)}),h&&(c-=h.width*r);var f=-c/2;d(n,function(t,n){i[e][n]=i[e][n]||{offset:f,width:t.width},f+=t.width*(1+r)})}),i}function Ol(t,e,i){if(t&&e){var n=t[Cl(e)];return null!=n&&null!=i&&(n=n[Dl(i)]),n}}function El(t,e){var i=kl(t,e),n=Pl(i),o={};d(i,function(t){var e=t.getData(),i=t.coordinateSystem,a=i.getBaseAxis(),r=Dl(t),s=n[Cl(a)][r],l=s.offset,u=s.width,h=i.getOtherAxis(a),c=t.get("barMinHeight")||0;o[r]=o[r]||[],e.setLayout({offset:l,size:u});for(var d=e.mapDimension(h.dim),f=e.mapDimension(a.dim),p=pl(e,d),g=h.isHorizontal(),m=Bl(a,h,p),v=0,y=e.count();v<y;v++){var x=e.get(d,v),_=e.get(f,v);if(!isNaN(x)){var w=x>=0?"p":"n",b=m;p&&(o[r][_]||(o[r][_]={p:m,n:m}),b=o[r][_][w]);var S,M,I,T;if(g)S=b,M=(A=i.dataToPoint([x,_]))[1]+l,I=A[0]-m,T=u,Math.abs(I)<c&&(I=(I<0?-1:1)*c),p&&(o[r][_][w]+=I);else{var A=i.dataToPoint([_,x]);S=A[0]+l,M=b,I=u,T=A[1]-m,Math.abs(T)<c&&(T=(T<=0?-1:1)*c),p&&(o[r][_][w]+=T)}e.setItemLayout(v,{x:S,y:M,width:I,height:T})}}},this)}function Rl(t){return t.coordinateSystem&&"cartesian2d"===t.coordinateSystem.type}function zl(t){return t.pipelineContext&&t.pipelineContext.large}function Bl(t,e,i){var n,o,a=e.getGlobalExtent();a[0]>a[1]?(n=a[1],o=a[0]):(n=a[0],o=a[1]);var r=e.toGlobalCoord(e.dataToCoord(0));return r<n&&(r=n),r>o&&(r=o),r}function Vl(t,e){return VA(t,BA(e))}function Gl(t,e){var i,n,o,a=t.type,r=e.getMin(),s=e.getMax(),l=null!=r,u=null!=s,h=t.getExtent();"ordinal"===a?i=e.getCategories().length:(y(n=e.get("boundaryGap"))||(n=[n||0,n||0]),"boolean"==typeof n[0]&&(n=[0,0]),n[0]=Vo(n[0],1),n[1]=Vo(n[1],1),o=h[1]-h[0]||Math.abs(h[0])),null==r&&(r="ordinal"===a?i?0:NaN:h[0]-n[0]*o),null==s&&(s="ordinal"===a?i?i-1:NaN:h[1]+n[1]*o),"dataMin"===r?r=h[0]:"function"==typeof r&&(r=r({min:h[0],max:h[1]})),"dataMax"===s?s=h[1]:"function"==typeof s&&(s=s({min:h[0],max:h[1]})),(null==r||!isFinite(r))&&(r=NaN),(null==s||!isFinite(s))&&(s=NaN),t.setBlank(I(r)||I(s)||"ordinal"===a&&!t.getOrdinalMeta().categories.length),e.getNeedCrossZero()&&(r>0&&s>0&&!l&&(r=0),r<0&&s<0&&!u&&(s=0));var c=e.ecModel;if(c&&"time"===a){var f,p=kl("bar",c);if(d(p,function(t){f|=t.getBaseAxis()===e.axis}),f){var g=Pl(p),m=Fl(r,s,e,g);r=m.min,s=m.max}}return[r,s]}function Fl(t,e,i,n){var o=i.axis.getExtent(),a=o[1]-o[0],r=Ol(n,i.axis);if(void 0===r)return{min:t,max:e};var s=1/0;d(r,function(t){s=Math.min(t.offset,s)});var l=-1/0;d(r,function(t){l=Math.max(t.offset+t.width,l)}),s=Math.abs(s),l=Math.abs(l);var u=s+l,h=e-t,c=h/(1-(s+l)/a)-h;return e+=c*(l/u),t-=c*(s/u),{min:t,max:e}}function Wl(t,e){var i=Gl(t,e),n=null!=e.getMin(),o=null!=e.getMax(),a=e.get("splitNumber");"log"===t.type&&(t.base=e.get("logBase"));var r=t.type;t.setExtent(i[0],i[1]),t.niceExtent({splitNumber:a,fixMin:n,fixMax:o,minInterval:"interval"===r||"time"===r?e.get("minInterval"):null,maxInterval:"interval"===r||"time"===r?e.get("maxInterval"):null});var s=e.get("interval");null!=s&&t.setInterval&&t.setInterval(s)}function Hl(t,e){if(e=e||t.get("type"))switch(e){case"category":return new SA(t.getOrdinalMeta?t.getOrdinalMeta():t.getCategories(),[1/0,-1/0]);case"value":return new TA;default:return(xl.getClass(e)||TA).create(t)}}function Zl(t){var e=t.scale.getExtent(),i=e[0],n=e[1];return!(i>0&&n>0||i<0&&n<0)}function Ul(t){var e=t.getLabelModel().get("formatter"),i="category"===t.type?t.scale.getExtent()[0]:null;return"string"==typeof e?e=function(e){return function(i){return i=t.scale.getLabel(i),e.replace("{value}",null!=i?i:"")}}(e):"function"==typeof e?function(n,o){return null!=i&&(o=n-i),e(Xl(t,n),o)}:function(e){return t.scale.getLabel(e)}}function Xl(t,e){return"category"===t.type?t.scale.getLabel(e):e}function jl(t){var e=t.model,i=t.scale;if(e.get("axisLabel.show")&&!i.isBlank()){var n,o,a="category"===t.type,r=i.getExtent();o=a?i.count():(n=i.getTicks()).length;var s,l=t.getLabelModel(),u=Ul(t),h=1;o>40&&(h=Math.ceil(o/40));for(var c=0;c<o;c+=h){var d=u(n?n[c]:r[0]+c),f=Yl(l.getTextRect(d),l.get("rotate")||0);s?s.union(f):s=f}return s}}function Yl(t,e){var i=e*Math.PI/180,n=t.plain(),o=n.width,a=n.height,r=o*Math.cos(i)+a*Math.sin(i),s=o*Math.sin(i)+a*Math.cos(i);return new de(n.x,n.y,r,s)}function ql(t){var e=t.get("interval");return null==e?"auto":e}function Kl(t){return"category"===t.type&&0===ql(t.getLabelModel())}function $l(t,e){if("image"!==this.type){var i=this.style,n=this.shape;n&&"line"===n.symbolType?i.stroke=t:this.__isEmptyBrush?(i.stroke=t,i.fill=e||"#fff"):(i.fill&&(i.fill=t),i.stroke&&(i.stroke=t)),this.dirty(!1)}}function Jl(t,e,i,n,o,a,r){var s=0===t.indexOf("empty");s&&(t=t.substr(5,1).toLowerCase()+t.substr(6));var l;return l=0===t.indexOf("image://")?jn(t.slice(8),new de(e,i,n,o),r?"center":"cover"):0===t.indexOf("path://")?Xn(t.slice(7),{},new de(e,i,n,o),r?"center":"cover"):new JA({shape:{symbolType:t,x:e,y:i,width:n,height:o}}),l.__isEmptyBrush=s,l.setColor=$l,l.setColor(a),l}function Ql(t,e){return Math.abs(t-e)<eD}function tu(t,e,i){var n=0,o=t[0];if(!o)return!1;for(var a=1;a<t.length;a++){var r=t[a];n+=Sn(o[0],o[1],r[0],r[1],e,i),o=r}var s=t[0];return Ql(o[0],s[0])&&Ql(o[1],s[1])||(n+=Sn(o[0],o[1],s[0],s[1],e,i)),0!==n}function eu(t,e,i){if(this.name=t,this.geometries=e,i)i=[i[0],i[1]];else{var n=this.getBoundingRect();i=[n.x+n.width/2,n.y+n.height/2]}this.center=i}function iu(t){if(!t.UTF8Encoding)return t;var e=t.UTF8Scale;null==e&&(e=1024);for(var i=t.features,n=0;n<i.length;n++)for(var o=i[n].geometry,a=o.coordinates,r=o.encodeOffsets,s=0;s<a.length;s++){var l=a[s];if("Polygon"===o.type)a[s]=nu(l,r[s],e);else if("MultiPolygon"===o.type)for(var u=0;u<l.length;u++){var h=l[u];l[u]=nu(h,r[s][u],e)}}return t.UTF8Encoding=!1,t}function nu(t,e,i){for(var n=[],o=e[0],a=e[1],r=0;r<t.length;r+=2){var s=t.charCodeAt(r)-64,l=t.charCodeAt(r+1)-64;s=s>>1^-(1&s),l=l>>1^-(1&l),o=s+=o,a=l+=a,n.push([s/i,l/i])}return n}function ou(t){return"category"===t.type?ru(t):uu(t)}function au(t,e){return"category"===t.type?lu(t,e):{ticks:t.scale.getTicks()}}function ru(t){var e=t.getLabelModel(),i=su(t,e);return!e.get("show")||t.scale.isBlank()?{labels:[],labelCategoryInterval:i.labelCategoryInterval}:i}function su(t,e){var i=hu(t,"labels"),n=ql(e),o=cu(i,n);if(o)return o;var a,r;return a=x(n)?vu(t,n):mu(t,r="auto"===n?fu(t):n),du(i,n,{labels:a,labelCategoryInterval:r})}function lu(t,e){var i=hu(t,"ticks"),n=ql(e),o=cu(i,n);if(o)return o;var a,r;if(e.get("show")&&!t.scale.isBlank()||(a=[]),x(n))a=vu(t,n,!0);else if("auto"===n){var s=su(t,t.getLabelModel());r=s.labelCategoryInterval,a=f(s.labels,function(t){return t.tickValue})}else a=mu(t,r=n,!0);return du(i,n,{ticks:a,tickCategoryInterval:r})}function uu(t){var e=t.scale.getTicks(),i=Ul(t);return{labels:f(e,function(e,n){return{formattedLabel:i(e,n),rawLabel:t.scale.getLabel(e),tickValue:e}})}}function hu(t,e){return nD(t)[e]||(nD(t)[e]=[])}function cu(t,e){for(var i=0;i<t.length;i++)if(t[i].key===e)return t[i].value}function du(t,e,i){return t.push({key:e,value:i}),i}function fu(t){var e=nD(t).autoInterval;return null!=e?e:nD(t).autoInterval=t.calculateCategoryInterval()}function pu(t){var e=gu(t),i=Ul(t),n=(e.axisRotate-e.labelRotate)/180*Math.PI,o=t.scale,a=o.getExtent(),r=o.count();if(a[1]-a[0]<1)return 0;var s=1;r>40&&(s=Math.max(1,Math.floor(r/40)));for(var l=a[0],u=t.dataToCoord(l+1)-t.dataToCoord(l),h=Math.abs(u*Math.cos(n)),c=Math.abs(u*Math.sin(n)),d=0,f=0;l<=a[1];l+=s){var p=0,g=0,m=ke(i(l),e.font,"center","top");p=1.3*m.width,g=1.3*m.height,d=Math.max(d,p,7),f=Math.max(f,g,7)}var v=d/h,y=f/c;isNaN(v)&&(v=1/0),isNaN(y)&&(y=1/0);var x=Math.max(0,Math.floor(Math.min(v,y))),_=nD(t.model),w=_.lastAutoInterval,b=_.lastTickCount;return null!=w&&null!=b&&Math.abs(w-x)<=1&&Math.abs(b-r)<=1&&w>x?x=w:(_.lastTickCount=r,_.lastAutoInterval=x),x}function gu(t){var e=t.getLabelModel();return{axisRotate:t.getRotate?t.getRotate():t.isHorizontal&&!t.isHorizontal()?90:0,labelRotate:e.get("rotate")||0,font:e.getFont()}}function mu(t,e,i){function n(t){l.push(i?t:{formattedLabel:o(t),rawLabel:a.getLabel(t),tickValue:t})}var o=Ul(t),a=t.scale,r=a.getExtent(),s=t.getLabelModel(),l=[],u=Math.max((e||0)+1,1),h=r[0],c=a.count();0!==h&&u>1&&c/u>2&&(h=Math.round(Math.ceil(h/u)*u));var d=Kl(t),f=s.get("showMinLabel")||d,p=s.get("showMaxLabel")||d;f&&h!==r[0]&&n(r[0]);for(var g=h;g<=r[1];g+=u)n(g);return p&&g!==r[1]&&n(r[1]),l}function vu(t,e,i){var n=t.scale,o=Ul(t),a=[];return d(n.getTicks(),function(t){var r=n.getLabel(t);e(t,r)&&a.push(i?t:{formattedLabel:o(t),rawLabel:r,tickValue:t})}),a}function yu(t,e){var i=(t[1]-t[0])/e/2;t[0]+=i,t[1]-=i}function xu(t,e,i,n,o){function a(t,e){return h?t>e:t<e}var r=e.length;if(t.onBand&&!n&&r){var s,l=t.getExtent();if(1===r)e[0].coord=l[0],s=e[1]={coord:l[0]};else{var u=e[1].coord-e[0].coord;d(e,function(t){t.coord-=u/2;var e=e||0;e%2>0&&(t.coord-=u/(2*(e+1)))}),s={coord:e[r-1].coord+u},e.push(s)}var h=l[0]>l[1];a(e[0].coord,l[0])&&(o?e[0].coord=l[0]:e.shift()),o&&a(l[0],e[0].coord)&&e.unshift({coord:l[0]}),a(l[1],s.coord)&&(o?s.coord=l[1]:e.pop()),o&&a(s.coord,l[1])&&e.push({coord:l[1]})}}function _u(t,e){var i=t.mapDimension("defaultedLabel",!0),n=i.length;if(1===n)return fr(t,e,i[0]);if(n){for(var o=[],a=0;a<i.length;a++){var r=fr(t,e,i[a]);o.push(r)}return o.join(" ")}}function wu(t,e,i){tb.call(this),this.updateData(t,e,i)}function bu(t){return[t[0]/2,t[1]/2]}function Su(t,e){this.parent.drift(t,e)}function Mu(){!so(this)&&Tu.call(this)}function Iu(){!so(this)&&Au.call(this)}function Tu(){if(!this.incremental&&!this.useHoverLayer){var t=this.__symbolOriginalScale,e=t[1]/t[0];this.animateTo({scale:[Math.max(1.1*t[0],t[0]+3),Math.max(1.1*t[1],t[1]+3*e)]},400,"elasticOut")}}function Au(){this.incremental||this.useHoverLayer||this.animateTo({scale:this.__symbolOriginalScale},400,"elasticOut")}function Du(t){this.group=new tb,this._symbolCtor=t||wu}function Cu(t,e,i,n){return e&&!isNaN(e[0])&&!isNaN(e[1])&&!(n.isIgnore&&n.isIgnore(i))&&!(n.clipShape&&!n.clipShape.contain(e[0],e[1]))&&"none"!==t.getItemVisual(i,"symbol")}function Lu(t){return null==t||w(t)||(t={isIgnore:t}),t||{}}function ku(t){var e=t.hostModel;return{itemStyle:e.getModel("itemStyle").getItemStyle(["color"]),hoverItemStyle:e.getModel("emphasis.itemStyle").getItemStyle(),symbolRotate:e.get("symbolRotate"),symbolOffset:e.get("symbolOffset"),hoverAnimation:e.get("hoverAnimation"),labelModel:e.getModel("label"),hoverLabelModel:e.getModel("emphasis.label"),cursorStyle:e.get("cursor")}}function Pu(t,e,i){var n,o=t.getBaseAxis(),a=t.getOtherAxis(o),r=Nu(a,i),s=o.dim,l=a.dim,u=e.mapDimension(l),h=e.mapDimension(s),c="x"===l||"radius"===l?1:0,d=f(t.dimensions,function(t){return e.mapDimension(t)}),p=e.getCalculationInfo("stackResultDimension");return(n|=pl(e,d[0]))&&(d[0]=p),(n|=pl(e,d[1]))&&(d[1]=p),{dataDimsForPoint:d,valueStart:r,valueAxisDim:l,baseAxisDim:s,stacked:!!n,valueDim:u,baseDim:h,baseDataOffset:c,stackedOverDimension:e.getCalculationInfo("stackedOverDimension")}}function Nu(t,e){var i=0,n=t.scale.getExtent();return"start"===e?i=n[0]:"end"===e?i=n[1]:n[0]>0?i=n[0]:n[1]<0&&(i=n[1]),i}function Ou(t,e,i,n){var o=NaN;t.stacked&&(o=i.get(i.getCalculationInfo("stackedOverDimension"),n)),isNaN(o)&&(o=t.valueStart);var a=t.baseDataOffset,r=[];return r[a]=i.get(t.baseDim,n),r[1-a]=o,e.dataToPoint(r)}function Eu(t,e){var i=[];return e.diff(t).add(function(t){i.push({cmd:"+",idx:t})}).update(function(t,e){i.push({cmd:"=",idx:e,idx1:t})}).remove(function(t){i.push({cmd:"-",idx:t})}).execute(),i}function Ru(t){return isNaN(t[0])||isNaN(t[1])}function zu(t,e,i,n,o,a,r,s,l,u,h){return"none"!==u&&u?Bu.apply(this,arguments):Vu.apply(this,arguments)}function Bu(t,e,i,n,o,a,r,s,l,u,h){for(var c=0,d=i,f=0;f<n;f++){var p=e[d];if(d>=o||d<0)break;if(Ru(p)){if(h){d+=a;continue}break}if(d===i)t[a>0?"moveTo":"lineTo"](p[0],p[1]);else if(l>0){var g=e[c],m="y"===u?1:0,v=(p[m]-g[m])*l;_D(bD,g),bD[m]=g[m]+v,_D(SD,p),SD[m]=p[m]-v,t.bezierCurveTo(bD[0],bD[1],SD[0],SD[1],p[0],p[1])}else t.lineTo(p[0],p[1]);c=d,d+=a}return f}function Vu(t,e,i,n,o,a,r,s,l,u,h){for(var c=0,d=i,f=0;f<n;f++){var p=e[d];if(d>=o||d<0)break;if(Ru(p)){if(h){d+=a;continue}break}if(d===i)t[a>0?"moveTo":"lineTo"](p[0],p[1]),_D(bD,p);else if(l>0){var g=d+a,m=e[g];if(h)for(;m&&Ru(e[g]);)m=e[g+=a];var v=.5,y=e[c];if(!(m=e[g])||Ru(m))_D(SD,p);else{Ru(m)&&!h&&(m=p),U(wD,m,y);var x,_;if("x"===u||"y"===u){var w="x"===u?0:1;x=Math.abs(p[w]-y[w]),_=Math.abs(p[w]-m[w])}else x=uw(p,y),_=uw(p,m);xD(SD,p,wD,-l*(1-(v=_/(_+x))))}vD(bD,bD,s),yD(bD,bD,r),vD(SD,SD,s),yD(SD,SD,r),t.bezierCurveTo(bD[0],bD[1],SD[0],SD[1],p[0],p[1]),xD(bD,p,wD,l*v)}else t.lineTo(p[0],p[1]);c=d,d+=a}return f}function Gu(t,e){var i=[1/0,1/0],n=[-1/0,-1/0];if(e)for(var o=0;o<t.length;o++){var a=t[o];a[0]<i[0]&&(i[0]=a[0]),a[1]<i[1]&&(i[1]=a[1]),a[0]>n[0]&&(n[0]=a[0]),a[1]>n[1]&&(n[1]=a[1])}return{min:e?i:n,max:e?n:i}}function Fu(t,e){if(t.length===e.length){for(var i=0;i<t.length;i++){var n=t[i],o=e[i];if(n[0]!==o[0]||n[1]!==o[1])return}return!0}}function Wu(t){return"number"==typeof t?t:t?.5:0}function Hu(t){var e=t.getGlobalExtent();if(t.onBand){var i=t.getBandWidth()/2-1,n=e[1]>e[0]?1:-1;e[0]+=n*i,e[1]-=n*i}return e}function Zu(t,e,i){if(!i.valueDim)return[];for(var n=[],o=0,a=e.count();o<a;o++)n.push(Ou(i,t,e,o));return n}function Uu(t,e,i,n){var o=Hu(t.getAxis("x")),a=Hu(t.getAxis("y")),r=t.getBaseAxis().isHorizontal(),s=Math.min(o[0],o[1]),l=Math.min(a[0],a[1]),u=Math.max(o[0],o[1])-s,h=Math.max(a[0],a[1])-l;if(i)s-=.5,u+=.5,l-=.5,h+=.5;else{var c=n.get("lineStyle.width")||2,d=n.get("clipOverflow")?c/2:Math.max(u,h);r?(l-=d,h+=2*d):(s-=d,u+=2*d)}var f=new yM({shape:{x:s,y:l,width:u,height:h}});return e&&(f.shape[r?"width":"height"]=0,To(f,{shape:{width:u,height:h}},n)),f}function Xu(t,e,i,n){var o=t.getAngleAxis(),a=t.getRadiusAxis().getExtent().slice();a[0]>a[1]&&a.reverse();var r=o.getExtent(),s=Math.PI/180;i&&(a[0]-=.5,a[1]+=.5);var l=new hM({shape:{cx:Go(t.cx,1),cy:Go(t.cy,1),r0:Go(a[0],1),r:Go(a[1],1),startAngle:-r[0]*s,endAngle:-r[1]*s,clockwise:o.inverse}});return e&&(l.shape.endAngle=-r[0]*s,To(l,{shape:{endAngle:-r[1]*s}},n)),l}function ju(t,e,i,n){return"polar"===t.type?Xu(t,e,i,n):Uu(t,e,i,n)}function Yu(t,e,i){for(var n=e.getBaseAxis(),o="x"===n.dim||"radius"===n.dim?0:1,a=[],r=0;r<t.length-1;r++){var s=t[r+1],l=t[r];a.push(l);var u=[];switch(i){case"end":u[o]=s[o],u[1-o]=l[1-o],a.push(u);break;case"middle":var h=(l[o]+s[o])/2,c=[];u[o]=c[o]=h,u[1-o]=l[1-o],c[1-o]=s[1-o],a.push(u),a.push(c);break;default:u[o]=l[o],u[1-o]=s[1-o],a.push(u)}}return t[r]&&a.push(t[r]),a}function qu(t,e){var i=t.getVisual("visualMeta");if(i&&i.length&&t.count()&&"cartesian2d"===e.type){for(var n,o,a=i.length-1;a>=0;a--){var r=i[a].dimension,s=t.dimensions[r],l=t.getDimensionInfo(s);if("x"===(n=l&&l.coordDim)||"y"===n){o=i[a];break}}if(o){var u=e.getAxis(n),h=f(o.stops,function(t){return{coord:u.toGlobalCoord(u.dataToCoord(t.value)),color:t.color}}),c=h.length,p=o.outerColors.slice();c&&h[0].coord>h[c-1].coord&&(h.reverse(),p.reverse());var g=h[0].coord-10,m=h[c-1].coord+10,v=m-g;if(v<.001)return"transparent";d(h,function(t){t.offset=(t.coord-g)/v}),h.push({offset:c?h[c-1].offset:.5,color:p[1]||"transparent"}),h.unshift({offset:c?h[0].offset:.5,color:p[0]||"transparent"});var y=new TM(0,0,0,0,h,!0);return y[n]=g,y[n+"2"]=m,y}}}function Ku(t,e,i){var n=t.get("showAllSymbol"),o="auto"===n;if(!n||o){var a=i.getAxesByScale("ordinal")[0];if(a&&(!o||!$u(a,e))){var r=e.mapDimension(a.dim),s={};return d(a.getViewLabels(),function(t){s[t.tickValue]=1}),function(t){return!s.hasOwnProperty(e.get(r,t))}}}}function $u(t,e){var i=t.getExtent(),n=Math.abs(i[1]-i[0])/t.scale.count();isNaN(n)&&(n=0);for(var o=e.count(),a=Math.max(1,Math.round(o/5)),r=0;r<o;r+=a)if(1.5*wu.getSymbolSize(e,r)[t.isHorizontal()?1:0]>n)return!1;return!0}function Ju(t){return this._axes[t]}function Qu(t){LD.call(this,t)}function th(t,e){return e.type||(e.data?"category":"value")}function eh(t,e,i){return t.getCoordSysModel()===e}function ih(t,e,i){this._coordsMap={},this._coordsList=[],this._axesMap={},this._axesList=[],this._initCartesian(t,e,i),this.model=t}function nh(t,e,i,n){function o(t){return t.dim+"_"+t.index}i.getAxesOnZeroOf=function(){return a?[a]:[]};var a,r=t[e],s=i.model,l=s.get("axisLine.onZero"),u=s.get("axisLine.onZeroAxisIndex");if(l){if(null!=u)oh(r[u])&&(a=r[u]);else for(var h in r)if(r.hasOwnProperty(h)&&oh(r[h])&&!n[o(r[h])]){a=r[h];break}a&&(n[o(a)]=!0)}}function oh(t){return t&&"category"!==t.type&&"time"!==t.type&&Zl(t)}function ah(t,e){var i=t.getExtent(),n=i[0]+i[1];t.toGlobalCoord="x"===t.dim?function(t){return t+e}:function(t){return n-t+e},t.toLocalCoord="x"===t.dim?function(t){return t-e}:function(t){return n-t+e}}function rh(t,e){return f(VD,function(e){return t.getReferringComponents(e)[0]})}function sh(t){return"cartesian2d"===t.get("coordinateSystem")}function lh(t){var e={componentType:t.mainType,componentIndex:t.componentIndex};return e[t.mainType+"Index"]=t.componentIndex,e}function uh(t,e,i,n){var o,a,r=Xo(i-t.rotation),s=n[0]>n[1],l="start"===e&&!s||"start"!==e&&s;return jo(r-GD/2)?(a=l?"bottom":"top",o="center"):jo(r-1.5*GD)?(a=l?"top":"bottom",o="center"):(a="middle",o=r<1.5*GD&&r>GD/2?l?"left":"right":l?"right":"left"),{rotation:r,textAlign:o,textVerticalAlign:a}}function hh(t){var e=t.get("tooltip");return t.get("silent")||!(t.get("triggerEvent")||e&&e.show)}function ch(t,e,i){if(!Kl(t.axis)){var n=t.get("axisLabel.showMinLabel"),o=t.get("axisLabel.showMaxLabel");e=e||[],i=i||[];var a=e[0],r=e[1],s=e[e.length-1],l=e[e.length-2],u=i[0],h=i[1],c=i[i.length-1],d=i[i.length-2];!1===n?(dh(a),dh(u)):fh(a,r)&&(n?(dh(r),dh(h)):(dh(a),dh(u))),!1===o?(dh(s),dh(c)):fh(l,s)&&(o?(dh(l),dh(d)):(dh(s),dh(c)))}}function dh(t){t&&(t.ignore=!0)}function fh(t,e,i){var n=t&&t.getBoundingRect().clone(),o=e&&e.getBoundingRect().clone();if(n&&o){var a=_t([]);return Mt(a,a,-t.rotation),n.applyTransform(bt([],a,t.getLocalTransform())),o.applyTransform(bt([],a,e.getLocalTransform())),n.intersect(o)}}function ph(t){return"middle"===t||"center"===t}function gh(t,e,i){var n=e.axis;if(e.get("axisTick.show")&&!n.scale.isBlank()){for(var o=e.getModel("axisTick"),a=o.getModel("lineStyle"),s=o.get("length"),l=n.getTicksCoords(),u=[],h=[],c=t._transform,d=[],f=0;f<l.length;f++){var p=l[f].coord;u[0]=p,u[1]=0,h[0]=p,h[1]=i.tickDirection*s,c&&(Q(u,u,c),Q(h,h,c));var g=new _M(Kn({anid:"tick_"+l[f].tickValue,shape:{x1:u[0],y1:u[1],x2:h[0],y2:h[1]},style:r(a.getLineStyle(),{stroke:e.get("axisLine.lineStyle.color")}),z2:2,silent:!0}));t.group.add(g),d.push(g)}return d}}function mh(t,e,i){var n=e.axis;if(T(i.axisLabelShow,e.get("axisLabel.show"))&&!n.scale.isBlank()){var o=e.getModel("axisLabel"),a=o.get("margin"),r=n.getViewLabels(),s=(T(i.labelRotate,o.get("rotate"))||0)*GD/180,l=HD(i.rotation,s,i.labelDirection),u=e.getCategories(!0),h=[],c=hh(e),f=e.get("triggerEvent");return d(r,function(r,s){var d=r.tickValue,p=r.formattedLabel,g=r.rawLabel,m=o;u&&u[d]&&u[d].textStyle&&(m=new No(u[d].textStyle,o,e.ecModel));var v=m.getTextColor()||e.get("axisLine.lineStyle.color"),y=[n.dataToCoord(d),i.labelOffset+i.labelDirection*a],x=new rM({anid:"label_"+d,position:y,rotation:l.rotation,silent:c,z2:10});mo(x.style,m,{text:p,textAlign:m.getShallow("align",!0)||l.textAlign,textVerticalAlign:m.getShallow("verticalAlign",!0)||m.getShallow("baseline",!0)||l.textVerticalAlign,textFill:"function"==typeof v?v("category"===n.type?g:"value"===n.type?d+"":d,s):v}),f&&(x.eventData=lh(e),x.eventData.targetType="axisLabel",x.eventData.value=g),t._dumbGroup.add(x),x.updateTransform(),h.push(x),t.group.add(x),x.decomposeTransform()}),h}}function vh(t,e){var i={axesInfo:{},seriesInvolved:!1,coordSysAxesInfo:{},coordSysMap:{}};return yh(i,t,e),i.seriesInvolved&&_h(i,t),i}function yh(t,e,i){var n=e.getComponent("tooltip"),o=e.getComponent("axisPointer"),a=o.get("link",!0)||[],r=[];ZD(i.getCoordinateSystems(),function(i){function s(n,s,l){var c=l.model.getModel("axisPointer",o),d=c.get("show");if(d&&("auto"!==d||n||Th(c))){null==s&&(s=c.get("triggerTooltip"));var f=(c=n?xh(l,h,o,e,n,s):c).get("snap"),p=Ah(l.model),g=s||f||"category"===l.type,m=t.axesInfo[p]={key:p,axis:l,coordSys:i,axisPointerModel:c,triggerTooltip:s,involveSeries:g,snap:f,useHandle:Th(c),seriesModels:[]};u[p]=m,t.seriesInvolved|=g;var v=wh(a,l);if(null!=v){var y=r[v]||(r[v]={axesInfo:{}});y.axesInfo[p]=m,y.mapper=a[v].mapper,m.linkGroup=y}}}if(i.axisPointerEnabled){var l=Ah(i.model),u=t.coordSysAxesInfo[l]={};t.coordSysMap[l]=i;var h=i.model.getModel("tooltip",n);if(ZD(i.getAxes(),UD(s,!1,null)),i.getTooltipAxes&&n&&h.get("show")){var c="axis"===h.get("trigger"),d="cross"===h.get("axisPointer.type"),f=i.getTooltipAxes(h.get("axisPointer.axis"));(c||d)&&ZD(f.baseAxes,UD(s,!d||"cross",c)),d&&ZD(f.otherAxes,UD(s,"cross",!1))}}})}function xh(t,e,n,o,a,s){var l=e.getModel("axisPointer"),u={};ZD(["type","snap","lineStyle","shadowStyle","label","animation","animationDurationUpdate","animationEasingUpdate","z"],function(t){u[t]=i(l.get(t))}),u.snap="category"!==t.type&&!!s,"cross"===l.get("type")&&(u.type="line");var h=u.label||(u.label={});if(null==h.show&&(h.show=!1),"cross"===a){var c=l.get("label.show");if(h.show=null==c||c,!s){var d=u.lineStyle=l.get("crossStyle");d&&r(h,d.textStyle)}}return t.model.getModel("axisPointer",new No(u,n,o))}function _h(t,e){e.eachSeries(function(e){var i=e.coordinateSystem,n=e.get("tooltip.trigger",!0),o=e.get("tooltip.show",!0);i&&"none"!==n&&!1!==n&&"item"!==n&&!1!==o&&!1!==e.get("axisPointer.show",!0)&&ZD(t.coordSysAxesInfo[Ah(i.model)],function(t){var n=t.axis;i.getAxis(n.dim)===n&&(t.seriesModels.push(e),null==t.seriesDataCount&&(t.seriesDataCount=0),t.seriesDataCount+=e.getData().count())})},this)}function wh(t,e){for(var i=e.model,n=e.dim,o=0;o<t.length;o++){var a=t[o]||{};if(bh(a[n+"AxisId"],i.id)||bh(a[n+"AxisIndex"],i.componentIndex)||bh(a[n+"AxisName"],i.name))return o}}function bh(t,e){return"all"===t||y(t)&&l(t,e)>=0||t===e}function Sh(t){var e=Mh(t);if(e){var i=e.axisPointerModel,n=e.axis.scale,o=i.option,a=i.get("status"),r=i.get("value");null!=r&&(r=n.parse(r));var s=Th(i);null==a&&(o.status=s?"show":"hide");var l=n.getExtent().slice();l[0]>l[1]&&l.reverse(),(null==r||r>l[1])&&(r=l[1]),r<l[0]&&(r=l[0]),o.value=r,s&&(o.status=e.axis.scale.isBlank()?"hide":"show")}}function Mh(t){var e=(t.ecModel.getComponent("axisPointer")||{}).coordSysAxesInfo;return e&&e.axesInfo[Ah(t)]}function Ih(t){var e=Mh(t);return e&&e.axisPointerModel}function Th(t){return!!t.get("handle.show")}function Ah(t){return t.type+"||"+t.id}function Dh(t,e,i,n,o,a){var r=XD.getAxisPointerClass(t.axisPointerClass);if(r){var s=Ih(e);s?(t._axisPointer||(t._axisPointer=new r)).render(e,s,n,a):Ch(t,n)}}function Ch(t,e,i){var n=t._axisPointer;n&&n.dispose(e,i),t._axisPointer=null}function Lh(t,e,i){i=i||{};var n=t.coordinateSystem,o=e.axis,a={},r=o.getAxesOnZeroOf()[0],s=o.position,l=r?"onZero":s,u=o.dim,h=n.getRect(),c=[h.x,h.x+h.width,h.y,h.y+h.height],d={left:0,right:1,top:0,bottom:1,onZero:2},f=e.get("offset")||0,p="x"===u?[c[2]-f,c[3]+f]:[c[0]-f,c[1]+f];if(r){var g=r.toGlobalCoord(r.dataToCoord(0));p[d.onZero]=Math.max(Math.min(g,p[1]),p[0])}a.position=["y"===u?p[d[l]]:c[0],"x"===u?p[d[l]]:c[3]],a.rotation=Math.PI/2*("x"===u?0:1);var m={top:-1,bottom:1,left:-1,right:1};a.labelDirection=a.tickDirection=a.nameDirection=m[s],a.labelOffset=r?p[d[s]]-p[d.onZero]:0,e.get("axisTick.inside")&&(a.tickDirection=-a.tickDirection),T(i.labelInside,e.get("axisLabel.inside"))&&(a.labelDirection=-a.labelDirection);var v=e.get("axisLabel.rotate");return a.labelRotate="top"===l?-v:v,a.z2=1,a}function kh(t,e,i,n,o,a,r){go(t,e,i.getModel("label"),i.getModel("emphasis.label"),{labelFetcher:o,labelDataIndex:a,defaultText:_u(o.getData(),a),isRectText:!0,autoColor:n}),Ph(t),Ph(e)}function Ph(t,e){"outside"===t.textPosition&&(t.textPosition=e)}function Nh(t,e,i){i.style.text=null,Io(i,{shape:{width:0}},e,t,function(){i.parent&&i.parent.remove(i)})}function Oh(t,e,i){i.style.text=null,Io(i,{shape:{r:i.shape.r0}},e,t,function(){i.parent&&i.parent.remove(i)})}function Eh(t,e,i,n,o,a,s,l){var u=e.getItemVisual(i,"color"),h=e.getItemVisual(i,"opacity"),c=n.getModel("itemStyle"),d=n.getModel("emphasis.itemStyle").getBarItemStyle();l||t.setShape("r",c.get("barBorderRadius")||0),t.useStyle(r({fill:u,opacity:h},c.getBarItemStyle()));var f=n.getShallow("cursor");f&&t.attr("cursor",f);var p=s?o.height>0?"bottom":"top":o.width>0?"left":"right";l||kh(t.style,d,n,u,a,i,p),fo(t,d)}function Rh(t,e){var i=t.get(tC)||0;return Math.min(i,Math.abs(e.width),Math.abs(e.height))}function zh(t,e,i){var n=t.getData(),o=[],a=n.getLayout("valueAxisHorizontal")?1:0;o[1-a]=n.getLayout("valueAxisStart");var r=new nC({shape:{points:n.getLayout("largePoints")},incremental:!!i,__startPoint:o,__valueIdx:a});e.add(r),Bh(r,t,n)}function Bh(t,e,i){var n=i.getVisual("borderColor")||i.getVisual("color"),o=e.getModel("itemStyle").getItemStyle(["color","borderColor"]);t.useStyle(o),t.style.fill=null,t.style.stroke=n,t.style.lineWidth=i.getLayout("barWidth")}function Vh(t,e,i,n){var o=e.getData(),a=this.dataIndex,r=o.getName(a),s=e.get("selectedOffset");n.dispatchAction({type:"pieToggleSelect",from:t,name:r,seriesId:e.id}),o.each(function(t){Gh(o.getItemGraphicEl(t),o.getItemLayout(t),e.isSelected(o.getName(t)),s,i)})}function Gh(t,e,i,n,o){var a=(e.startAngle+e.endAngle)/2,r=Math.cos(a),s=Math.sin(a),l=i?n:0,u=[r*l,s*l];o?t.animate().when(200,{position:u}).start("bounceOut"):t.attr("position",u)}function Fh(t,e){function i(){a.ignore=a.hoverIgnore,r.ignore=r.hoverIgnore}function n(){a.ignore=a.normalIgnore,r.ignore=r.normalIgnore}tb.call(this);var o=new hM({z2:2}),a=new gM,r=new rM;this.add(o),this.add(a),this.add(r),this.updateData(t,e,!0),this.on("emphasis",i).on("normal",n).on("mouseover",i).on("mouseout",n)}function Wh(t,e,i,n,o,a,r){function s(e,i){for(var n=e;n>=0&&(t[n].y-=i,!(n>0&&t[n].y>t[n-1].y+t[n-1].height));n--);}function l(t,e,i,n,o,a){for(var r=e?Number.MAX_VALUE:0,s=0,l=t.length;s<l;s++){var u=Math.abs(t[s].y-n),h=t[s].len,c=t[s].len2,d=u<o+h?Math.sqrt((o+h+c)*(o+h+c)-u*u):Math.abs(t[s].x-i);e&&d>=r&&(d=r-10),!e&&d<=r&&(d=r+10),t[s].x=i+d*a,r=d}}t.sort(function(t,e){return t.y-e.y});for(var u,h=0,c=t.length,d=[],f=[],p=0;p<c;p++)(u=t[p].y-h)<0&&function(e,i,n,o){for(var a=e;a<i;a++)if(t[a].y+=n,a>e&&a+1<i&&t[a+1].y>t[a].y+t[a].height)return void s(a,n/2);s(i-1,n/2)}(p,c,-u),h=t[p].y+t[p].height;r-h<0&&s(c-1,h-r);for(p=0;p<c;p++)t[p].y>=i?f.push(t[p]):d.push(t[p]);l(d,!1,e,i,n,o),l(f,!0,e,i,n,o)}function Hh(t,e,i,n,o,a){for(var r=[],s=[],l=0;l<t.length;l++)Zh(t[l])||(t[l].x<e?r.push(t[l]):s.push(t[l]));Wh(s,e,i,n,1,o,a),Wh(r,e,i,n,-1,o,a);for(l=0;l<t.length;l++)if(!Zh(t[l])){var u=t[l].linePoints;if(u){var h=u[1][0]-u[2][0];t[l].x<e?u[2][0]=t[l].x+3:u[2][0]=t[l].x-3,u[1][1]=u[2][1]=t[l].y,u[1][0]=u[2][0]+h}}}function Zh(t){return"center"===t.position}function Uh(){this.group=new tb}function Xh(t,e,i){aD.call(this,t,e,i),this.type="value",this.angle=0,this.name="",this.model}function jh(t,e,i){this._model=t,this.dimensions=[],this._indicatorAxes=f(t.getIndicatorModels(),function(t,e){var i="indicator_"+e,n=new Xh(i,new TA);return n.name=t.get("name"),n.model=t,t.axis=n,this.dimensions.push(i),n},this),this.resize(t,i),this.cx,this.cy,this.r,this.r0,this.startAngle}function Yh(t,e){return r({show:e},t)}function qh(t){return y(t)||(t=[+t,+t]),t}function Kh(t){for(var e,i=0;i<t.length;i++){var n=t[i].getBoundingRect();(e=e||n.clone()).union(n)}return e}function $h(t,e){var i,n,o=t.svgXML;try{k(null!=(n=(i=o&&rs(o,{ignoreViewBox:!0,ignoreRootClip:!0})||{}).root))}catch(t){throw new Error("Invalid svg format\n"+t.message)}var a=i.width,r=i.height,s=i.viewBoxRect;if(e||(e=null==a||null==r?n.getBoundingRect():new de(0,0,0,0),null!=a&&(e.width=a),null!=r&&(e.height=r)),s){var l=as(s,e.width,e.height),u=n;(n=new tb).add(u),u.scale=l.scale,u.position=l.position}return n.setClipPath(new yM({shape:e.plain()})),{root:n,boundingRect:e}}function Jh(t){return function(e,i){var n=[];return d(Qh(e),function(o){var a=NC[o.type][t];a&&n.push(a(e,o,i))}),n}}function Qh(t){return DT.retrieveMap(t)||[]}function tc(t,e,i){nc(t)[e]=i}function ec(t,e,i){var n=nc(t);n[e]===i&&(n[e]=null)}function ic(t,e){return!!nc(t)[e]}function nc(t){return t[EC]||(t[EC]={})}function oc(t){this.pointerChecker,this._zr=t,this._opt={};var e=m,n=e(ac,this),o=e(rc,this),a=e(sc,this),s=e(lc,this),l=e(uc,this);fw.call(this),this.setPointerChecker=function(t){this.pointerChecker=t},this.enable=function(e,u){this.disable(),this._opt=r(i(u)||{},{zoomOnMouseWheel:!0,moveOnMouseMove:!0,moveOnMouseWheel:!1,preventDefaultMouseMove:!0}),null==e&&(e=!0),!0!==e&&"move"!==e&&"pan"!==e||(t.on("mousedown",n),t.on("mousemove",o),t.on("mouseup",a)),!0!==e&&"scale"!==e&&"zoom"!==e||(t.on("mousewheel",s),t.on("pinch",l))},this.disable=function(){t.off("mousedown",n),t.off("mousemove",o),t.off("mouseup",a),t.off("mousewheel",s),t.off("pinch",l)},this.dispose=this.disable,this.isDragging=function(){return this._dragging},this.isPinching=function(){return this._pinching}}function ac(t){if(!(dt(t)||t.target&&t.target.draggable)){var e=t.offsetX,i=t.offsetY;this.pointerChecker&&this.pointerChecker(t,e,i)&&(this._x=e,this._y=i,this._dragging=!0)}}function rc(t){if(this._dragging&&dc("moveOnMouseMove",t,this._opt)&&"pinch"!==t.gestureEvent&&!ic(this._zr,"globalPan")){var e=t.offsetX,i=t.offsetY,n=this._x,o=this._y,a=e-n,r=i-o;this._x=e,this._y=i,this._opt.preventDefaultMouseMove&&mw(t.event),cc(this,"pan","moveOnMouseMove",t,{dx:a,dy:r,oldX:n,oldY:o,newX:e,newY:i})}}function sc(t){dt(t)||(this._dragging=!1)}function lc(t){var e=dc("zoomOnMouseWheel",t,this._opt),i=dc("moveOnMouseWheel",t,this._opt),n=t.wheelDelta,o=Math.abs(n),a=t.offsetX,r=t.offsetY;if(0!==n&&(e||i)){if(e){var s=o>3?1.4:o>1?1.2:1.1;hc(this,"zoom","zoomOnMouseWheel",t,{scale:n>0?s:1/s,originX:a,originY:r})}if(i){var l=Math.abs(n);hc(this,"scrollMove","moveOnMouseWheel",t,{scrollDelta:(n>0?1:-1)*(l>3?.4:l>1?.15:.05),originX:a,originY:r})}}}function uc(t){ic(this._zr,"globalPan")||hc(this,"zoom",null,t,{scale:t.pinchScale>1?1.1:1/1.1,originX:t.pinchX,originY:t.pinchY})}function hc(t,e,i,n,o){t.pointerChecker&&t.pointerChecker(n,o.originX,o.originY)&&(mw(n.event),cc(t,e,i,n,o))}function cc(t,e,i,n,o){o.isAvailableBehavior=m(dc,null,i,n),t.trigger(e,o)}function dc(t,e,i){var n=i[t];return!t||n&&(!_(n)||e.event[n+"Key"])}function fc(t,e,i){var n=t.target,o=n.position;o[0]+=e,o[1]+=i,n.dirty()}function pc(t,e,i,n){var o=t.target,a=t.zoomLimit,r=o.position,s=o.scale,l=t.zoom=t.zoom||1;if(l*=e,a){var u=a.min||0,h=a.max||1/0;l=Math.max(Math.min(h,l),u)}var c=l/t.zoom;t.zoom=l,r[0]-=(i-r[0])*(c-1),r[1]-=(n-r[1])*(c-1),s[0]*=c,s[1]*=c,o.dirty()}function gc(t,e,i){var n=e.getComponentByElement(t.topTarget),o=n&&n.coordinateSystem;return n&&n!==i&&!RC[n.mainType]&&o&&o.model!==i}function mc(t,e){var i=t.getItemStyle(),n=t.get("areaColor");return null!=n&&(i.fill=n),i}function vc(t,e,i,n,o){i.off("click"),i.off("mousedown"),e.get("selectedMode")&&(i.on("mousedown",function(){t._mouseDownFlag=!0}),i.on("click",function(a){if(t._mouseDownFlag){t._mouseDownFlag=!1;for(var r=a.target;!r.__regions;)r=r.parent;if(r){var s={type:("geo"===e.mainType?"geo":"map")+"ToggleSelect",batch:f(r.__regions,function(t){return{name:t.name,from:o.uid}})};s[e.mainType+"Id"]=e.id,n.dispatchAction(s),yc(e,i)}}}))}function yc(t,e){e.eachChild(function(e){d(e.__regions,function(i){e.trigger(t.isSelected(i.name)?"emphasis":"normal")})})}function xc(t,e){var i=new tb;this.uid=Ro("ec_map_draw"),this._controller=new oc(t.getZr()),this._controllerHost={target:e?i:null},this.group=i,this._updateGroup=e,this._mouseDownFlag,this._mapName,this._initialized,i.add(this._regionsGroup=new tb),i.add(this._backgroundGroup=new tb)}function _c(t){var e=this[zC];e&&e.recordVersion===this[BC]&&wc(e,t)}function wc(t,e){var i=t.circle,n=t.labelModel,o=t.hoverLabelModel,a=t.emphasisText,r=t.normalText;e?(i.style.extendFrom(mo({},o,{text:o.get("show")?a:null},{isRectText:!0,useInsideStyle:!1},!0)),i.__mapOriginalZ2=i.z2,i.z2+=NM):(mo(i.style,n,{text:n.get("show")?r:null,textPosition:n.getShallow("position")||"bottom"},{isRectText:!0,useInsideStyle:!1}),i.dirty(!1),null!=i.__mapOriginalZ2&&(i.z2=i.__mapOriginalZ2,i.__mapOriginalZ2=null))}function bc(t,e,i){var n=t.getZoom(),o=t.getCenter(),a=e.zoom,r=t.dataToPoint(o);if(null!=e.dx&&null!=e.dy){r[0]-=e.dx,r[1]-=e.dy;o=t.pointToData(r);t.setCenter(o)}if(null!=a){if(i){var s=i.min||0,l=i.max||1/0;a=Math.max(Math.min(n*a,l),s)/n}t.scale[0]*=a,t.scale[1]*=a;var u=t.position,h=(e.originX-u[0])*(a-1),c=(e.originY-u[1])*(a-1);u[0]-=h,u[1]-=c,t.updateTransform();o=t.pointToData(r);t.setCenter(o),t.setZoom(a*n)}return{center:t.getCenter(),zoom:t.getZoom()}}function Sc(){Tw.call(this)}function Mc(t){this.name=t,this.zoomLimit,Tw.call(this),this._roamTransformable=new Sc,this._rawTransformable=new Sc,this._center,this._zoom}function Ic(t,e,i,n){var o=i.seriesModel,a=o?o.coordinateSystem:null;return a===this?a[t](n):null}function Tc(t,e,i,n){Mc.call(this,t),this.map=e;var o=OC.load(e,i);this._nameCoordMap=o.nameCoordMap,this._regionsMap=o.regionsMap,this._invertLongitute=null==n||n,this.regions=o.regions,this._rect=o.boundingRect}function Ac(t,e,i,n){var o=i.geoModel,a=i.seriesModel,r=o?o.coordinateSystem:a?a.coordinateSystem||(a.getReferringComponents("geo")[0]||{}).coordinateSystem:null;return r===this?r[t](n):null}function Dc(t,e){var i=t.get("boundingCoords");if(null!=i){var n=i[0],o=i[1];isNaN(n[0])||isNaN(n[1])||isNaN(o[0])||isNaN(o[1])||this.setBoundingRect(n[0],n[1],o[0]-n[0],o[1]-n[1])}var a,r=this.getBoundingRect(),s=t.get("layoutCenter"),l=t.get("layoutSize"),u=e.getWidth(),h=e.getHeight(),c=r.width/r.height*this.aspectScale,d=!1;s&&l&&(s=[Vo(s[0],u),Vo(s[1],h)],l=Vo(l,Math.min(u,h)),isNaN(s[0])||isNaN(s[1])||isNaN(l)||(d=!0));if(d){var f={};c>1?(f.width=l,f.height=l/c):(f.height=l,f.width=l*c),f.y=s[1]-f.height/2,f.x=s[0]-f.width/2}else(a=t.getBoxLayoutParams()).aspect=c,f=ca(a,{width:u,height:h});this.setViewRect(f.x,f.y,f.width,f.height),this.setCenter(t.get("center")),this.setZoom(t.get("zoom"))}function Cc(t,e){d(e.get("geoCoord"),function(e,i){t.addGeoCoord(i,e)})}function Lc(t,e){var i={};return d(t,function(t){t.each(t.mapDimension("value"),function(e,n){var o="ec-"+t.getName(n);i[o]=i[o]||[],isNaN(e)||i[o].push(e)})}),t[0].map(t[0].mapDimension("value"),function(n,o){for(var a="ec-"+t[0].getName(o),r=0,s=1/0,l=-1/0,u=i[a].length,h=0;h<u;h++)s=Math.min(s,i[a][h]),l=Math.max(l,i[a][h]),r+=i[a][h];var c;return c="min"===e?s:"max"===e?l:"average"===e?r/u:r,0===u?NaN:c})}function kc(t){var e=t.mainData,i=t.datas;i||(i={main:e},t.datasAttr={main:"data"}),t.datas=t.mainData=null,zc(e,i,t),FC(i,function(i){FC(e.TRANSFERABLE_METHODS,function(e){i.wrapMethod(e,v(Pc,t))})}),e.wrapMethod("cloneShallow",v(Oc,t)),FC(e.CHANGABLE_METHODS,function(i){e.wrapMethod(i,v(Nc,t))}),k(i[e.dataType]===e)}function Pc(t,e){if(Rc(this)){var i=a({},this[WC]);i[this.dataType]=e,zc(e,i,t)}else Bc(e,this.dataType,this[HC],t);return e}function Nc(t,e){return t.struct&&t.struct.update(this),e}function Oc(t,e){return FC(e[WC],function(i,n){i!==e&&Bc(i.cloneShallow(),n,e,t)}),e}function Ec(t){var e=this[HC];return null==t||null==e?e:e[WC][t]}function Rc(t){return t[HC]===t}function zc(t,e,i){t[WC]={},FC(e,function(e,n){Bc(e,n,t,i)})}function Bc(t,e,i,n){i[WC][e]=t,t[HC]=i,t.dataType=e,n.struct&&(t[n.structAttr]=n.struct,n.struct[n.datasAttr[e]]=t),t.getLinkedData=Ec}function Vc(t,e,i){this.root,this.data,this._nodes=[],this.hostModel=t,this.levelModels=f(e||[],function(e){return new No(e,t,t.ecModel)}),this.leavesModel=new No(i||{},t,t.ecModel)}function Gc(t,e){var i=e.children;t.parentNode!==e&&(i.push(t),t.parentNode=e)}function Fc(t){t.hierNode={defaultAncestor:null,ancestor:t,prelim:0,modifier:0,change:0,shift:0,i:0,thread:null};for(var e,i,n=[t];e=n.pop();)if(i=e.children,e.isExpand&&i.length)for(var o=i.length-1;o>=0;o--){var a=i[o];a.hierNode={defaultAncestor:null,ancestor:a,prelim:0,modifier:0,change:0,shift:0,i:o,thread:null},n.push(a)}}function Wc(t,e){var i=t.isExpand?t.children:[],n=t.parentNode.children,o=t.hierNode.i?n[t.hierNode.i-1]:null;if(i.length){jc(t);var a=(i[0].hierNode.prelim+i[i.length-1].hierNode.prelim)/2;o?(t.hierNode.prelim=o.hierNode.prelim+e(t,o),t.hierNode.modifier=t.hierNode.prelim-a):t.hierNode.prelim=a}else o&&(t.hierNode.prelim=o.hierNode.prelim+e(t,o));t.parentNode.hierNode.defaultAncestor=Yc(t,o,t.parentNode.hierNode.defaultAncestor||n[0],e)}function Hc(t){var e=t.hierNode.prelim+t.parentNode.hierNode.modifier;t.setLayout({x:e},!0),t.hierNode.modifier+=t.parentNode.hierNode.modifier}function Zc(t){return arguments.length?t:Qc}function Uc(t,e){var i={};return t-=Math.PI/2,i.x=e*Math.cos(t),i.y=e*Math.sin(t),i}function Xc(t,e){return ca(t.getBoxLayoutParams(),{width:e.getWidth(),height:e.getHeight()})}function jc(t){for(var e=t.children,i=e.length,n=0,o=0;--i>=0;){var a=e[i];a.hierNode.prelim+=n,a.hierNode.modifier+=n,o+=a.hierNode.change,n+=a.hierNode.shift+o}}function Yc(t,e,i,n){if(e){for(var o=t,a=t,r=a.parentNode.children[0],s=e,l=o.hierNode.modifier,u=a.hierNode.modifier,h=r.hierNode.modifier,c=s.hierNode.modifier;s=qc(s),a=Kc(a),s&&a;){o=qc(o),r=Kc(r),o.hierNode.ancestor=t;var d=s.hierNode.prelim+c-a.hierNode.prelim-u+n(s,a);d>0&&(Jc($c(s,t,i),t,d),u+=d,l+=d),c+=s.hierNode.modifier,u+=a.hierNode.modifier,l+=o.hierNode.modifier,h+=r.hierNode.modifier}s&&!qc(o)&&(o.hierNode.thread=s,o.hierNode.modifier+=c-l),a&&!Kc(r)&&(r.hierNode.thread=a,r.hierNode.modifier+=u-h,i=t)}return i}function qc(t){var e=t.children;return e.length&&t.isExpand?e[e.length-1]:t.hierNode.thread}function Kc(t){var e=t.children;return e.length&&t.isExpand?e[0]:t.hierNode.thread}function $c(t,e,i){return t.hierNode.ancestor.parentNode===e.parentNode?t.hierNode.ancestor:i}function Jc(t,e,i){var n=i/(e.hierNode.i-t.hierNode.i);e.hierNode.change-=n,e.hierNode.shift+=i,e.hierNode.modifier+=i,e.hierNode.prelim+=i,t.hierNode.change+=n}function Qc(t,e){return t.parentNode===e.parentNode?1:2}function td(t,e){var i=t.getItemLayout(e);return i&&!isNaN(i.x)&&!isNaN(i.y)&&"none"!==t.getItemVisual(e,"symbol")}function ed(t,e,i){return i.itemModel=e,i.itemStyle=e.getModel("itemStyle").getItemStyle(),i.hoverItemStyle=e.getModel("emphasis.itemStyle").getItemStyle(),i.lineStyle=e.getModel("lineStyle").getLineStyle(),i.labelModel=e.getModel("label"),i.hoverLabelModel=e.getModel("emphasis.label"),!1===t.isExpand&&0!==t.children.length?i.symbolInnerColor=i.itemStyle.fill:i.symbolInnerColor="#fff",i}function id(t,e,i,n,o,a){var s=!i,l=t.tree.getNodeByDataIndex(e),a=ed(l,l.getModel(),a),u=t.tree.root,h=l.parentNode===u?l:l.parentNode||l,c=t.getItemGraphicEl(h.dataIndex),d=h.getLayout(),f=c?{x:c.position[0],y:c.position[1],rawX:c.__radialOldRawX,rawY:c.__radialOldRawY}:d,p=l.getLayout();s?(i=new wu(t,e,a)).attr("position",[f.x,f.y]):i.updateData(t,e,a),i.__radialOldRawX=i.__radialRawX,i.__radialOldRawY=i.__radialRawY,i.__radialRawX=p.rawX,i.__radialRawY=p.rawY,n.add(i),t.setItemGraphicEl(e,i),Io(i,{position:[p.x,p.y]},o);var g=i.getSymbolPath();if("radial"===a.layout){var m,v,y=u.children[0],x=y.getLayout(),_=y.children.length;if(p.x===x.x&&!0===l.isExpand){var w={};w.x=(y.children[0].getLayout().x+y.children[_-1].getLayout().x)/2,w.y=(y.children[0].getLayout().y+y.children[_-1].getLayout().y)/2,(m=Math.atan2(w.y-x.y,w.x-x.x))<0&&(m=2*Math.PI+m),(v=w.x<x.x)&&(m-=Math.PI)}else(m=Math.atan2(p.y-x.y,p.x-x.x))<0&&(m=2*Math.PI+m),0===l.children.length||0!==l.children.length&&!1===l.isExpand?(v=p.x<x.x)&&(m-=Math.PI):(v=p.x>x.x)||(m-=Math.PI);var b=v?"left":"right";g.setStyle({textPosition:b,textRotation:-m,textOrigin:"center",verticalAlign:"middle"})}if(l.parentNode&&l.parentNode!==u){var S=i.__edge;S||(S=i.__edge=new bM({shape:od(a,f,f),style:r({opacity:0,strokeNoScale:!0},a.lineStyle)})),Io(S,{shape:od(a,d,p),style:{opacity:1}},o),n.add(S)}}function nd(t,e,i,n,o,a){for(var r,s=t.tree.getNodeByDataIndex(e),l=t.tree.root,a=ed(s,s.getModel(),a),u=s.parentNode===l?s:s.parentNode||s;null==(r=u.getLayout());)u=u.parentNode===l?u:u.parentNode||u;Io(i,{position:[r.x+1,r.y+1]},o,function(){n.remove(i),t.setItemGraphicEl(e,null)}),i.fadeOut(null,{keepLabel:!0});var h=i.__edge;h&&Io(h,{shape:od(a,r,r),style:{opacity:0}},o,function(){n.remove(h)})}function od(t,e,i){var n,o,a,r,s,l,u,h,c=t.orient;if("radial"===t.layout){s=e.rawX,u=e.rawY,l=i.rawX,h=i.rawY;var d=Uc(s,u),f=Uc(s,u+(h-u)*t.curvature),p=Uc(l,h+(u-h)*t.curvature),g=Uc(l,h);return{x1:d.x,y1:d.y,x2:g.x,y2:g.y,cpx1:f.x,cpy1:f.y,cpx2:p.x,cpy2:p.y}}return s=e.x,u=e.y,l=i.x,h=i.y,"LR"!==c&&"RL"!==c||(n=s+(l-s)*t.curvature,o=u,a=l+(s-l)*t.curvature,r=h),"TB"!==c&&"BT"!==c||(n=s,o=u+(h-u)*t.curvature,a=l,r=h+(u-h)*t.curvature),{x1:s,y1:u,x2:l,y2:h,cpx1:n,cpy1:o,cpx2:a,cpy2:r}}function ad(t,e,i){for(var n,o=[t],a=[];n=o.pop();)if(a.push(n),n.isExpand){var r=n.children;if(r.length)for(var s=0;s<r.length;s++)o.push(r[s])}for(;n=a.pop();)e(n,i)}function rd(t,e){for(var i,n=[t];i=n.pop();)if(e(i),i.isExpand){var o=i.children;if(o.length)for(var a=o.length-1;a>=0;a--)n.push(o[a])}}function sd(t,e){var i=Xc(t,e);t.layoutInfo=i;var n=t.get("layout"),o=0,a=0,r=null;"radial"===n?(o=2*Math.PI,a=Math.min(i.height,i.width)/2,r=Zc(function(t,e){return(t.parentNode===e.parentNode?1:2)/t.depth})):(o=i.width,a=i.height,r=Zc());var s=t.getData().tree.root,l=s.children[0];if(l){Fc(s),ad(l,Wc,r),s.hierNode.modifier=-l.hierNode.prelim,rd(l,Hc);var u=l,h=l,c=l;rd(l,function(t){var e=t.getLayout().x;e<u.getLayout().x&&(u=t),e>h.getLayout().x&&(h=t),t.depth>c.depth&&(c=t)});var d=u===h?1:r(u,h)/2,f=d-u.getLayout().x,p=0,g=0,m=0,v=0;if("radial"===n)p=o/(h.getLayout().x+d+f),g=a/(c.depth-1||1),rd(l,function(t){m=(t.getLayout().x+f)*p,v=(t.depth-1)*g;var e=Uc(m,v);t.setLayout({x:e.x,y:e.y,rawX:m,rawY:v},!0)});else{var y=t.getOrient();"RL"===y||"LR"===y?(g=a/(h.getLayout().x+d+f),p=o/(c.depth-1||1),rd(l,function(t){v=(t.getLayout().x+f)*g,m="LR"===y?(t.depth-1)*p:o-(t.depth-1)*p,t.setLayout({x:m,y:v},!0)})):"TB"!==y&&"BT"!==y||(p=o/(h.getLayout().x+d+f),g=a/(c.depth-1||1),rd(l,function(t){m=(t.getLayout().x+f)*p,v="TB"===y?(t.depth-1)*g:a-(t.depth-1)*g,t.setLayout({x:m,y:v},!0)}))}}}function ld(t,e,i){if(t&&l(e,t.type)>=0){var n=i.getData().tree.root,o=t.targetNode;if("string"==typeof o&&(o=n.getNodeById(o)),o&&n.contains(o))return{node:o};var a=t.targetNodeId;if(null!=a&&(o=n.getNodeById(a)))return{node:o}}}function ud(t){for(var e=[];t;)(t=t.parentNode)&&e.push(t);return e.reverse()}function hd(t,e){return l(ud(t),e)>=0}function cd(t,e){for(var i=[];t;){var n=t.dataIndex;i.push({name:t.name,dataIndex:n,value:e.getRawValue(n)}),t=t.parentNode}return i.reverse(),i}function dd(t){var e=0;d(t.children,function(t){dd(t);var i=t.value;y(i)&&(i=i[0]),e+=i});var i=t.value;y(i)&&(i=i[0]),(null==i||isNaN(i))&&(i=e),i<0&&(i=0),y(t.value)?t.value[0]=i:t.value=i}function fd(t,e){var i=e.get("color");if(i){var n;return d(t=t||[],function(t){var e=new No(t),i=e.get("color");(e.get("itemStyle.color")||i&&"none"!==i)&&(n=!0)}),n||((t[0]||(t[0]={})).color=i.slice()),t}}function pd(t){this.group=new tb,t.add(this.group)}function gd(t,e,i,n,o,a){var r=[[o?t:t-UC,e],[t+i,e],[t+i,e+n],[o?t:t-UC,e+n]];return!a&&r.splice(2,0,[t+i+UC,e+n/2]),!o&&r.push([t,e+n/2]),r}function md(t,e,i){t.eventData={componentType:"series",componentSubType:"treemap",componentIndex:e.componentIndex,seriesIndex:e.componentIndex,seriesName:e.name,seriesType:"treemap",selfType:"breadcrumb",nodeData:{dataIndex:i&&i.dataIndex,name:i&&i.name},treePathInfo:i&&cd(i,e)}}function vd(){var t,e=[],i={};return{add:function(t,n,o,a,r){return _(a)&&(r=a,a=0),!i[t.id]&&(i[t.id]=1,e.push({el:t,target:n,time:o,delay:a,easing:r}),!0)},done:function(e){return t=e,this},start:function(){for(var n=e.length,o=0,a=e.length;o<a;o++){var r=e[o];r.el.animateTo(r.target,r.time,r.delay,r.easing,function(){--n||(e.length=0,i={},t&&t())})}return this}}}function yd(t,e,n,o,r,s,l,u,h,c){function d(t,e){w?!t.invisible&&s.push(t):(e(),t.__tmWillVisible||(t.invisible=!1))}function f(e,n,o,a,r,s){var u=l.getModel(),h=T(t.getFormattedLabel(l.dataIndex,"normal",null,null,s?"upperLabel":"label"),u.get("name"));if(!s&&v.isLeafRoot){var c=t.get("drillDownIcon",!0);h=c?c+" "+h:h}var d=u.getModel(s?JC:KC),f=u.getModel(s?QC:$C),p=d.getShallow("show");go(e,n,d,f,{defaultText:p?h:null,autoColor:o,isRectText:!0}),s&&(e.textRect=i(s)),e.truncate=p&&d.get("ellipsis")?{outerWidth:a,outerHeight:r,minChar:2}:null}function p(t,i,o,a){var s=null!=S&&n[t][S],l=r[t];return s?(n[t][S]=null,g(l,s,t)):w||((s=new i({z:xd(o,a)})).__tmDepth=o,s.__tmStorageName=t,m(l,s,t)),e[t][b]=s}function g(t,e,i){(t[b]={}).old="nodeGroup"===i?e.position.slice():a({},e.shape)}function m(t,e,i){var n=t[b]={},a=l.parentNode;if(a&&(!o||"drillDown"===o.direction)){var s=0,u=0,h=r.background[a.getRawIndex()];!o&&h&&h.old&&(s=h.old.width,u=h.old.height),n.old="nodeGroup"===i?[0,u]:{x:s,y:u,width:0,height:0}}n.fadein="nodeGroup"!==i}if(l){var v=l.getLayout();if(v&&v.isInView){var y=v.width,x=v.height,_=v.borderWidth,w=v.invisible,b=l.getRawIndex(),S=u&&u.getRawIndex(),M=l.viewChildren,I=v.upperHeight,A=M&&M.length,D=l.getModel("itemStyle"),C=l.getModel("emphasis.itemStyle"),L=p("nodeGroup",jC);if(L){if(h.add(L),L.attr("position",[v.x||0,v.y||0]),L.__tmNodeWidth=y,L.__tmNodeHeight=x,v.isAboveViewRoot)return L;var k=p("background",YC,c,eL);if(k&&function(e,i,n){i.dataIndex=l.dataIndex,i.seriesIndex=t.seriesIndex,i.setShape({x:0,y:0,width:y,height:x});var o=l.getVisual("borderColor",!0),a=C.get("borderColor");d(i,function(){var t=oL(D);t.fill=o;var e=nL(C);if(e.fill=a,n){var r=y-2*_;f(t,e,o,r,I,{x:_,y:0,width:r,height:I})}else t.text=e.text=null;i.setStyle(t),fo(i,e)}),e.add(i)}(L,k,A&&v.upperHeight),!A){var P=p("content",YC,c,iL);P&&function(e,i){i.dataIndex=l.dataIndex,i.seriesIndex=t.seriesIndex;var n=Math.max(y-2*_,0),o=Math.max(x-2*_,0);i.culling=!0,i.setShape({x:_,y:_,width:n,height:o});var a=l.getVisual("color",!0);d(i,function(){var t=oL(D);t.fill=a;var e=nL(C);f(t,e,a,n,o),i.setStyle(t),fo(i,e)}),e.add(i)}(L,P)}return L}}}}function xd(t,e){var i=t*tL+e;return(i-1)/i}function _d(t){var e=t.pieceList;t.hasSpecialVisual=!1,d(e,function(e,i){e.originIndex=i,null!=e.visual&&(t.hasSpecialVisual=!0)})}function wd(t){var e=t.categories,i=t.visual,n=t.categoryMap={};if(sL(e,function(t,e){n[t]=e}),!y(i)){var o=[];w(i)?sL(i,function(t,e){var i=n[e];o[null!=i?i:uL]=t}):o[uL]=i,i=Ld(t,o)}for(var a=e.length-1;a>=0;a--)null==i[a]&&(delete n[e[a]],e.pop())}function bd(t,e){var i=t.visual,n=[];w(i)?sL(i,function(t){n.push(t)}):null!=i&&n.push(i);var o={color:1,symbol:1};e||1!==n.length||o.hasOwnProperty(t.type)||(n[1]=n[0]),Ld(t,n)}function Sd(t){return{applyVisual:function(e,i,n){e=this.mapValueToVisual(e),n("color",t(i("color"),e))},_doMap:Dd([0,1])}}function Md(t){var e=this.option.visual;return e[Math.round(Bo(t,[0,1],[0,e.length-1],!0))]||{}}function Id(t){return function(e,i,n){n(t,this.mapValueToVisual(e))}}function Td(t){var e=this.option.visual;return e[this.option.loop&&t!==uL?t%e.length:t]}function Ad(){return this.option.visual[0]}function Dd(t){return{linear:function(e){return Bo(e,t,this.option.visual,!0)},category:Td,piecewise:function(e,i){var n=Cd.call(this,i);return null==n&&(n=Bo(e,t,this.option.visual,!0)),n},fixed:Ad}}function Cd(t){var e=this.option,i=e.pieceList;if(e.hasSpecialVisual){var n=i[hL.findPieceIndex(t,i)];if(n&&n.visual)return n.visual[this.type]}}function Ld(t,e){return t.visual=e,"color"===t.type&&(t.parsedVisual=f(e,function(t){return Gt(t)})),e}function kd(t,e,i){return t?e<=i:e<i}function Pd(t,e,i,n,o,a){var r=t.getModel(),s=t.getLayout();if(s&&!s.invisible&&s.isInView){var l,u=t.getModel(pL),h=Nd(u,e,i[t.depth],n),c=u.get("borderColor"),f=u.get("borderColorSaturation");null!=f&&(c=Ed(f,l=Od(h))),t.setVisual("borderColor",c);var p=t.viewChildren;if(p&&p.length){var g=zd(t,r,s,u,h,p);d(p,function(t,e){(t.depth>=o.length||t===o[t.depth])&&Pd(t,Vd(r,h,t,e,g,a),i,n,o,a)})}else l=Od(h),t.setVisual("color",l)}}function Nd(t,e,i,n){var o=a({},e);return d(["color","colorAlpha","colorSaturation"],function(a){var r=t.get(a,!0);null==r&&i&&(r=i[a]),null==r&&(r=e[a]),null==r&&(r=n.get(a)),null!=r&&(o[a]=r)}),o}function Od(t){var e=Rd(t,"color");if(e){var i=Rd(t,"colorAlpha"),n=Rd(t,"colorSaturation");return n&&(e=jt(e,null,null,n)),i&&(e=Yt(e,i)),e}}function Ed(t,e){return null!=e?jt(e,null,null,t):null}function Rd(t,e){var i=t[e];if(null!=i&&"none"!==i)return i}function zd(t,e,i,n,o,a){if(a&&a.length){var r=Bd(e,"color")||null!=o.color&&"none"!==o.color&&(Bd(e,"colorAlpha")||Bd(e,"colorSaturation"));if(r){var s=e.get("visualMin"),l=e.get("visualMax"),u=i.dataExtent.slice();null!=s&&s<u[0]&&(u[0]=s),null!=l&&l>u[1]&&(u[1]=l);var h=e.get("colorMappingBy"),c={type:r.name,dataExtent:u,visual:r.range};"color"!==c.type||"index"!==h&&"id"!==h?c.mappingMethod="linear":(c.mappingMethod="category",c.loop=!0);var d=new hL(c);return d.__drColorMappingBy=h,d}}}function Bd(t,e){var i=t.get(e);return fL(i)&&i.length?{name:e,range:i}:null}function Vd(t,e,i,n,o,r){var s=a({},e);if(o){var l=o.type,u="color"===l&&o.__drColorMappingBy,h="index"===u?n:"id"===u?r.mapIdToIndex(i.getId()):i.getValue(t.get("visualDimension"));s[l]=o.mapValueToVisual(h)}return s}function Gd(t,e,i,n){var o,a;if(!t.isRemoved()){var r=t.getLayout();o=r.width,a=r.height;var s=(f=t.getModel()).get(_L),l=f.get(wL)/2,u=Kd(f),h=Math.max(s,u),c=s-l,d=h-l,f=t.getModel();t.setLayout({borderWidth:s,upperHeight:h,upperLabelHeight:u},!0);var p=(o=mL(o-2*c,0))*(a=mL(a-c-d,0)),g=Fd(t,f,p,e,i,n);if(g.length){var m={x:c,y:d,width:o,height:a},v=vL(o,a),y=1/0,x=[];x.area=0;for(var _=0,w=g.length;_<w;){var b=g[_];x.push(b),x.area+=b.getLayout().area;var S=Ud(x,v,e.squareRatio);S<=y?(_++,y=S):(x.area-=x.pop().getLayout().area,Xd(x,v,m,l,!1),v=vL(m.width,m.height),x.length=x.area=0,y=1/0)}if(x.length&&Xd(x,v,m,l,!0),!i){var M=f.get("childrenVisibleMin");null!=M&&p<M&&(i=!0)}for(var _=0,w=g.length;_<w;_++)Gd(g[_],e,i,n+1)}}}function Fd(t,e,i,n,o,a){var r=t.children||[],s=n.sort;"asc"!==s&&"desc"!==s&&(s=null);var l=null!=n.leafDepth&&n.leafDepth<=a;if(o&&!l)return t.viewChildren=[];Hd(r=g(r,function(t){return!t.isRemoved()}),s);var u=Zd(e,r,s);if(0===u.sum)return t.viewChildren=[];if(u.sum=Wd(e,i,u.sum,s,r),0===u.sum)return t.viewChildren=[];for(var h=0,c=r.length;h<c;h++){var d=r[h].getValue()/u.sum*i;r[h].setLayout({area:d})}return l&&(r.length&&t.setLayout({isLeafRoot:!0},!0),r.length=0),t.viewChildren=r,t.setLayout({dataExtent:u.dataExtent},!0),r}function Wd(t,e,i,n,o){if(!n)return i;for(var a=t.get("visibleMin"),r=o.length,s=r,l=r-1;l>=0;l--){var u=o["asc"===n?r-l-1:l].getValue();u/i*e<a&&(s=l,i-=u)}return"asc"===n?o.splice(0,r-s):o.splice(s,r-s),i}function Hd(t,e){return e&&t.sort(function(t,i){var n="asc"===e?t.getValue()-i.getValue():i.getValue()-t.getValue();return 0===n?"asc"===e?t.dataIndex-i.dataIndex:i.dataIndex-t.dataIndex:n}),t}function Zd(t,e,i){for(var n=0,o=0,a=e.length;o<a;o++)n+=e[o].getValue();var r=t.get("visualDimension");if(e&&e.length)if("value"===r&&i)s=[e[e.length-1].getValue(),e[0].getValue()],"asc"===i&&s.reverse();else{var s=[1/0,-1/0];xL(e,function(t){var e=t.getValue(r);e<s[0]&&(s[0]=e),e>s[1]&&(s[1]=e)})}else s=[NaN,NaN];return{sum:n,dataExtent:s}}function Ud(t,e,i){for(var n,o=0,a=1/0,r=0,s=t.length;r<s;r++)(n=t[r].getLayout().area)&&(n<a&&(a=n),n>o&&(o=n));var l=t.area*t.area,u=e*e*i;return l?mL(u*o/l,l/(u*a)):1/0}function Xd(t,e,i,n,o){var a=e===i.width?0:1,r=1-a,s=["x","y"],l=["width","height"],u=i[s[a]],h=e?t.area/e:0;(o||h>i[l[r]])&&(h=i[l[r]]);for(var c=0,d=t.length;c<d;c++){var f=t[c],p={},g=h?f.getLayout().area/h:0,m=p[l[r]]=mL(h-2*n,0),v=i[s[a]]+i[l[a]]-u,y=c===d-1||v<g?v:g,x=p[l[a]]=mL(y-2*n,0);p[s[r]]=i[s[r]]+vL(n,m/2),p[s[a]]=u+vL(n,x/2),u+=y,f.setLayout(p,!0)}i[s[r]]+=h,i[l[r]]-=h}function jd(t,e,i,n,o){var a=(e||{}).node,r=[n,o];if(!a||a===i)return r;for(var s,l=n*o,u=l*t.option.zoomToNodeRatio;s=a.parentNode;){for(var h=0,c=s.children,d=0,f=c.length;d<f;d++)h+=c[d].getValue();var p=a.getValue();if(0===p)return r;u*=h/p;var g=s.getModel(),m=g.get(_L);(u+=4*m*m+(3*m+Math.max(m,Kd(g)))*Math.pow(u,.5))>XM&&(u=XM),a=s}u<l&&(u=l);var v=Math.pow(u/l,.5);return[n*v,o*v]}function Yd(t,e,i){if(e)return{x:e.x,y:e.y};var n={x:0,y:0};if(!i)return n;var o=i.node,a=o.getLayout();if(!a)return n;for(var r=[a.width/2,a.height/2],s=o;s;){var l=s.getLayout();r[0]+=l.x,r[1]+=l.y,s=s.parentNode}return{x:t.width/2-r[0],y:t.height/2-r[1]}}function qd(t,e,i,n,o){var a=t.getLayout(),r=i[o],s=r&&r===t;if(!(r&&!s||o===i.length&&t!==n)){t.setLayout({isInView:!0,invisible:!s&&!e.intersect(a),isAboveViewRoot:s},!0);var l=new de(e.x-a.x,e.y-a.y,e.width,e.height);xL(t.viewChildren||[],function(t){qd(t,l,i,n,o+1)})}}function Kd(t){return t.get(bL)?t.get(SL):0}function $d(t){return"_EC_"+t}function Jd(t,e){this.id=null==t?"":t,this.inEdges=[],this.outEdges=[],this.edges=[],this.hostGraph,this.dataIndex=null==e?-1:e}function Qd(t,e,i){this.node1=t,this.node2=e,this.dataIndex=null==i?-1:i}function tf(t){return isNaN(+t.cpx1)||isNaN(+t.cpy1)}function ef(t){return"_"+t+"Type"}function nf(t,e,i){var n=e.getItemVisual(i,"color"),o=e.getItemVisual(i,t),a=e.getItemVisual(i,t+"Size");if(o&&"none"!==o){y(a)||(a=[a,a]);var r=Jl(o,-a[0]/2,-a[1]/2,a[0],a[1],n);return r.name=t,r}}function of(t){var e=new PL({name:"line"});return af(e.shape,t),e}function af(t,e){var i=e[0],n=e[1],o=e[2];t.x1=i[0],t.y1=i[1],t.x2=n[0],t.y2=n[1],t.percent=1,o?(t.cpx1=o[0],t.cpy1=o[1]):(t.cpx1=NaN,t.cpy1=NaN)}function rf(t,e,i){tb.call(this),this._createLine(t,e,i)}function sf(t){this._ctor=t||rf,this.group=new tb}function lf(t,e,i,n){if(df(e.getItemLayout(i))){var o=new t._ctor(e,i,n);e.setItemGraphicEl(i,o),t.group.add(o)}}function uf(t,e,i,n,o,a){var r=e.getItemGraphicEl(n);df(i.getItemLayout(o))?(r?r.updateData(i,o,a):r=new t._ctor(i,o,a),i.setItemGraphicEl(o,r),t.group.add(r)):t.group.remove(r)}function hf(t){var e=t.hostModel;return{lineStyle:e.getModel("lineStyle").getLineStyle(),hoverLineStyle:e.getModel("emphasis.lineStyle").getLineStyle(),labelModel:e.getModel("label"),hoverLabelModel:e.getModel("emphasis.label")}}function cf(t){return isNaN(t[0])||isNaN(t[1])}function df(t){return!cf(t[0])&&!cf(t[1])}function ff(t,e,i){for(var n,o=t[0],a=t[1],r=t[2],s=1/0,l=i*i,u=.1,h=.1;h<=.9;h+=.1)RL[0]=VL(o[0],a[0],r[0],h),RL[1]=VL(o[1],a[1],r[1],h),(f=FL(GL(RL,e)-l))<s&&(s=f,n=h);for(var c=0;c<32;c++){var d=n+u;zL[0]=VL(o[0],a[0],r[0],n),zL[1]=VL(o[1],a[1],r[1],n),BL[0]=VL(o[0],a[0],r[0],d),BL[1]=VL(o[1],a[1],r[1],d);var f=GL(zL,e)-l;if(FL(f)<.01)break;var p=GL(BL,e)-l;u/=2,f<0?p>=0?n+=u:n-=u:p>=0?n-=u:n+=u}return n}function pf(t,e){return t.getVisual("opacity")||t.getModel().get(e)}function gf(t,e,i){var n=t.getGraphicEl(),o=pf(t,e);null!=i&&(null==o&&(o=1),o*=i),n.downplay&&n.downplay(),n.traverse(function(t){if("group"!==t.type){var e=t.lineLabelOriginalOpacity;null!=e&&null==i||(e=o),t.setStyle("opacity",e)}})}function mf(t,e){var i=pf(t,e),n=t.getGraphicEl();n.highlight&&n.highlight(),n.traverse(function(t){"group"!==t.type&&t.setStyle("opacity",i)})}function vf(t){return t instanceof Array||(t=[t,t]),t}function yf(t){var e=t.coordinateSystem;if(!e||"view"===e.type){var i=t.getGraph();i.eachNode(function(t){var e=t.getModel();t.setLayout([+e.get("x"),+e.get("y")])}),xf(i)}}function xf(t){t.eachEdge(function(t){var e=t.getModel().get("lineStyle.curveness")||0,i=F(t.node1.getLayout()),n=F(t.node2.getLayout()),o=[i,n];+e&&o.push([(i[0]+n[0])/2-(i[1]-n[1])*e,(i[1]+n[1])/2-(n[0]-i[0])*e]),t.setLayout(o)})}function _f(t){var e=t.coordinateSystem;if(!e||"view"===e.type){var i=e.getBoundingRect(),n=t.getData(),o=n.graph,a=0,r=n.getSum("value"),s=2*Math.PI/(r||n.count()),l=i.width/2+i.x,u=i.height/2+i.y,h=Math.min(i.width,i.height)/2;o.eachNode(function(t){var e=t.getValue("value");a+=s*(r?e:1)/2,t.setLayout([h*Math.cos(a)+l,h*Math.sin(a)+u]),a+=s*(r?e:1)/2}),n.setLayout({cx:l,cy:u}),o.eachEdge(function(t){var e,i=t.getModel().get("lineStyle.curveness")||0,n=F(t.node1.getLayout()),o=F(t.node2.getLayout()),a=(n[0]+o[0])/2,r=(n[1]+o[1])/2;+i&&(e=[l*(i*=3)+a*(1-i),u*i+r*(1-i)]),t.setLayout([n,o,e])})}}function wf(t,e,i){for(var n=i.rect,o=n.width,a=n.height,r=[n.x+o/2,n.y+a/2],s=null==i.gravity?.1:i.gravity,l=0;l<t.length;l++){var u=t[l];u.p||(u.p=V(o*(Math.random()-.5)+r[0],a*(Math.random()-.5)+r[1])),u.pp=F(u.p),u.edges=null}var h=.6;return{warmUp:function(){h=.5},setFixed:function(e){t[e].fixed=!0},setUnfixed:function(e){t[e].fixed=!1},step:function(i){for(var n=[],o=t.length,a=0;a<e.length;a++){var l=e[a],u=l.n1;U(n,(p=l.n2).p,u.p);var c=X(n)-l.d,d=p.w/(u.w+p.w);isNaN(d)&&(d=0),q(n,n),!u.fixed&&XL(u.p,u.p,n,d*c*h),!p.fixed&&XL(p.p,p.p,n,-(1-d)*c*h)}for(a=0;a<o;a++)(v=t[a]).fixed||(U(n,r,v.p),XL(v.p,v.p,n,s*h));for(a=0;a<o;a++)for(var u=t[a],f=a+1;f<o;f++){var p=t[f];U(n,p.p,u.p),0===(c=X(n))&&(W(n,Math.random()-.5,Math.random()-.5),c=1);var g=(u.rep+p.rep)/c/c;!u.fixed&&XL(u.pp,u.pp,n,g),!p.fixed&&XL(p.pp,p.pp,n,-g)}for(var m=[],a=0;a<o;a++){var v=t[a];v.fixed||(U(m,v.p,v.pp),XL(v.p,v.p,m,h),G(v.pp,v.p))}h*=.992,i&&i(t,e,h<.01)}}}function bf(t,e,i){var n=t.getBoxLayoutParams();return n.aspect=i,ca(n,{width:e.getWidth(),height:e.getHeight()})}function Sf(t,e){var i=t.get("center"),n=e.getWidth(),o=e.getHeight(),a=Math.min(n,o);return{cx:Vo(i[0],e.getWidth()),cy:Vo(i[1],e.getHeight()),r:Vo(t.get("radius"),a/2)}}function Mf(t,e){return e&&("string"==typeof e?t=e.replace("{value}",null!=t?t:""):"function"==typeof e&&(t=e(t))),t}function If(t,e){function i(){a.ignore=a.hoverIgnore,r.ignore=r.hoverIgnore}function n(){a.ignore=a.normalIgnore,r.ignore=r.normalIgnore}tb.call(this);var o=new pM,a=new gM,r=new rM;this.add(o),this.add(a),this.add(r),this.updateData(t,e,!0),this.on("emphasis",i).on("normal",n).on("mouseover",i).on("mouseout",n)}function Tf(t,e){return ca(t.getBoxLayoutParams(),{width:e.getWidth(),height:e.getHeight()})}function Af(t,e){for(var i=t.mapDimension("value"),n=t.mapArray(i,function(t){return t}),o=[],a="ascending"===e,r=0,s=t.count();r<s;r++)o[r]=r;return"function"==typeof e?o.sort(e):"none"!==e&&o.sort(function(t,e){return a?n[t]-n[e]:n[e]-n[t]}),o}function Df(t){t.each(function(e){var i,n,o,a,r=t.getItemModel(e),s=r.getModel("label").get("position"),l=r.getModel("labelLine"),u=t.getItemLayout(e),h=u.points,c="inner"===s||"inside"===s||"center"===s;if(c)i="center",a=[[n=(h[0][0]+h[1][0]+h[2][0]+h[3][0])/4,o=(h[0][1]+h[1][1]+h[2][1]+h[3][1])/4],[n,o]];else{var d,f,p,g=l.get("length");"left"===s?(d=(h[3][0]+h[0][0])/2,f=(h[3][1]+h[0][1])/2,n=(p=d-g)-5,i="right"):(d=(h[1][0]+h[2][0])/2,f=(h[1][1]+h[2][1])/2,n=(p=d+g)+5,i="left");var m=f;a=[[d,f],[p,m]],o=m}u.label={linePoints:a,x:n,y:o,verticalAlign:"middle",textAlign:i,inside:c}})}function Cf(t){if(!t.parallel){var e=!1;d(t.series,function(t){t&&"parallel"===t.type&&(e=!0)}),e&&(t.parallel=[{}])}}function Lf(t){d(Di(t.parallelAxis),function(e){if(w(e)){var i=e.parallelIndex||0,o=Di(t.parallel)[i];o&&o.parallelAxisDefault&&n(e,o.parallelAxisDefault,!1)}})}function kf(t,e){var i=t[e]-t[1-e];return{span:Math.abs(i),sign:i>0?-1:i<0?1:e?-1:1}}function Pf(t,e){return Math.min(e[1],Math.max(e[0],t))}function Nf(t,e,i){this._axesMap=R(),this._axesLayout={},this.dimensions=t.dimensions,this._rect,this._model=t,this._init(t,e,i)}function Of(t,e){return ek(ik(t,e[0]),e[1])}function Ef(t,e){var i=e.layoutLength/(e.axisCount-1);return{position:i*t,axisNameAvailableWidth:i,axisLabelShow:!0}}function Rf(t,e){var i,n,o=e.layoutLength,a=e.axisExpandWidth,r=e.axisCount,s=e.axisCollapseWidth,l=e.winInnerIndices,u=s,h=!1;return t<l[0]?(i=t*s,n=s):t<=l[1]?(i=e.axisExpandWindow0Pos+t*a-e.axisExpandWindow[0],u=a,h=!0):(i=o-(r-1-t)*s,n=s),{position:i,axisNameAvailableWidth:u,axisLabelShow:h,nameTruncateMaxWidth:n}}function zf(t){fw.call(this),this._zr=t,this.group=new tb,this._brushType,this._brushOption,this._panels,this._track=[],this._dragging,this._covers=[],this._creatingCover,this._creatingPanel,this._enableGlobalPan,this._uid="brushController_"+bk++,this._handlers={},hk(Sk,function(t,e){this._handlers[e]=m(t,this)},this)}function Bf(t,e){var o=t._zr;t._enableGlobalPan||tc(o,yk,t._uid),hk(t._handlers,function(t,e){o.on(e,t)}),t._brushType=e.brushType,t._brushOption=n(i(wk),e,!0)}function Vf(t){var e=t._zr;ec(e,yk,t._uid),hk(t._handlers,function(t,i){e.off(i,t)}),t._brushType=t._brushOption=null}function Gf(t,e){var i=Mk[e.brushType].createCover(t,e);return i.__brushOption=e,Hf(i,e),t.group.add(i),i}function Ff(t,e){var i=Uf(e);return i.endCreating&&(i.endCreating(t,e),Hf(e,e.__brushOption)),e}function Wf(t,e){var i=e.__brushOption;Uf(e).updateCoverShape(t,e,i.range,i)}function Hf(t,e){var i=e.z;null==i&&(i=gk),t.traverse(function(t){t.z=i,t.z2=i})}function Zf(t,e){Uf(e).updateCommon(t,e),Wf(t,e)}function Uf(t){return Mk[t.__brushOption.brushType]}function Xf(t,e,i){var n=t._panels;if(!n)return!0;var o,a=t._transform;return hk(n,function(t){t.isTargetByCursor(e,i,a)&&(o=t)}),o}function jf(t,e){var i=t._panels;if(!i)return!0;var n=e.__brushOption.panelId;return null==n||i[n]}function Yf(t){var e=t._covers,i=e.length;return hk(e,function(e){t.group.remove(e)},t),e.length=0,!!i}function qf(t,e){var n=ck(t._covers,function(t){var e=t.__brushOption,n=i(e.range);return{brushType:e.brushType,panelId:e.panelId,range:n}});t.trigger("brush",n,{isEnd:!!e.isEnd,removeOnClick:!!e.removeOnClick})}function Kf(t){var e=t._track;if(!e.length)return!1;var i=e[e.length-1],n=e[0],o=i[0]-n[0],a=i[1]-n[1];return pk(o*o+a*a,.5)>mk}function $f(t){var e=t.length-1;return e<0&&(e=0),[t[0],t[e]]}function Jf(t,e,i,n){var o=new tb;return o.add(new yM({name:"main",style:ip(i),silent:!0,draggable:!0,cursor:"move",drift:uk(t,e,o,"nswe"),ondragend:uk(qf,e,{isEnd:!0})})),hk(n,function(i){o.add(new yM({name:i,style:{opacity:0},draggable:!0,silent:!0,invisible:!0,drift:uk(t,e,o,i),ondragend:uk(qf,e,{isEnd:!0})}))}),o}function Qf(t,e,i,n){var o=n.brushStyle.lineWidth||0,a=fk(o,vk),r=i[0][0],s=i[1][0],l=r-o/2,u=s-o/2,h=i[0][1],c=i[1][1],d=h-a+o/2,f=c-a+o/2,p=h-r,g=c-s,m=p+o,v=g+o;ep(t,e,"main",r,s,p,g),n.transformable&&(ep(t,e,"w",l,u,a,v),ep(t,e,"e",d,u,a,v),ep(t,e,"n",l,u,m,a),ep(t,e,"s",l,f,m,a),ep(t,e,"nw",l,u,a,a),ep(t,e,"ne",d,u,a,a),ep(t,e,"sw",l,f,a,a),ep(t,e,"se",d,f,a,a))}function tp(t,e){var i=e.__brushOption,n=i.transformable,o=e.childAt(0);o.useStyle(ip(i)),o.attr({silent:!n,cursor:n?"move":"default"}),hk(["w","e","n","s","se","sw","ne","nw"],function(i){var o=e.childOfName(i),a=ap(t,i);o&&o.attr({silent:!n,invisible:!n,cursor:n?_k[a]+"-resize":null})})}function ep(t,e,i,n,o,a,r){var s=e.childOfName(i);s&&s.setShape(hp(up(t,e,[[n,o],[n+a,o+r]])))}function ip(t){return r({strokeNoScale:!0},t.brushStyle)}function np(t,e,i,n){var o=[dk(t,i),dk(e,n)],a=[fk(t,i),fk(e,n)];return[[o[0],a[0]],[o[1],a[1]]]}function op(t){return Ao(t.group)}function ap(t,e){if(e.length>1)return("e"===(n=[ap(t,(e=e.split(""))[0]),ap(t,e[1])])[0]||"w"===n[0])&&n.reverse(),n.join("");var i={left:"w",right:"e",top:"n",bottom:"s"},n=Co({w:"left",e:"right",n:"top",s:"bottom"}[e],op(t));return i[n]}function rp(t,e,i,n,o,a,r,s){var l=n.__brushOption,u=t(l.range),h=lp(i,a,r);hk(o.split(""),function(t){var e=xk[t];u[e[0]][e[1]]+=h[e[0]]}),l.range=e(np(u[0][0],u[1][0],u[0][1],u[1][1])),Zf(i,n),qf(i,{isEnd:!1})}function sp(t,e,i,n,o){var a=e.__brushOption.range,r=lp(t,i,n);hk(a,function(t){t[0]+=r[0],t[1]+=r[1]}),Zf(t,e),qf(t,{isEnd:!1})}function lp(t,e,i){var n=t.group,o=n.transformCoordToLocal(e,i),a=n.transformCoordToLocal(0,0);return[o[0]-a[0],o[1]-a[1]]}function up(t,e,n){var o=jf(t,e);return o&&!0!==o?o.clipPath(n,t._transform):i(n)}function hp(t){var e=dk(t[0][0],t[1][0]),i=dk(t[0][1],t[1][1]);return{x:e,y:i,width:fk(t[0][0],t[1][0])-e,height:fk(t[0][1],t[1][1])-i}}function cp(t,e,i){if(t._brushType){var n=t._zr,o=t._covers,a=Xf(t,e,i);if(!t._dragging)for(var r=0;r<o.length;r++){var s=o[r].__brushOption;if(a&&(!0===a||s.panelId===a.panelId)&&Mk[s.brushType].contain(o[r],i[0],i[1]))return}a&&n.setCursorStyle("crosshair")}}function dp(t){var e=t.event;e.preventDefault&&e.preventDefault()}function fp(t,e,i){return t.childOfName("main").contain(e,i)}function pp(t,e,n,o){var a,r=t._creatingCover,s=t._creatingPanel,l=t._brushOption;if(t._track.push(n.slice()),Kf(t)||r){if(s&&!r){"single"===l.brushMode&&Yf(t);var u=i(l);u.brushType=gp(u.brushType,s),u.panelId=!0===s?null:s.panelId,r=t._creatingCover=Gf(t,u),t._covers.push(r)}if(r){var h=Mk[gp(t._brushType,s)];r.__brushOption.range=h.getCreatingRange(up(t,r,t._track)),o&&(Ff(t,r),h.updateCommon(t,r)),Wf(t,r),a={isEnd:o}}}else o&&"single"===l.brushMode&&l.removeOnClick&&Xf(t,e,n)&&Yf(t)&&(a={isEnd:o,removeOnClick:!0});return a}function gp(t,e){return"auto"===t?e.defaultBrushType:t}function mp(t){if(this._dragging){dp(t);var e=pp(this,t,this.group.transformCoordToLocal(t.offsetX,t.offsetY),!0);this._dragging=!1,this._track=[],this._creatingCover=null,e&&qf(this,e)}}function vp(t){return{createCover:function(e,i){return Jf(uk(rp,function(e){var i=[e,[0,100]];return t&&i.reverse(),i},function(e){return e[t]}),e,i,[["w","e"],["n","s"]][t])},getCreatingRange:function(e){var i=$f(e);return[dk(i[0][t],i[1][t]),fk(i[0][t],i[1][t])]},updateCoverShape:function(e,i,n,o){var a,r=jf(e,i);if(!0!==r&&r.getLinearBrushOtherExtent)a=r.getLinearBrushOtherExtent(t,e._transform);else{var s=e._zr;a=[0,[s.getWidth(),s.getHeight()][1-t]]}var l=[n,a];t&&l.reverse(),Qf(e,i,l,o)},updateCommon:tp,contain:fp}}function yp(t){return t=wp(t),function(e,i){return ko(e,t)}}function xp(t,e){return t=wp(t),function(i){var n=null!=e?e:i,o=n?t.width:t.height,a=n?t.x:t.y;return[a,a+(o||0)]}}function _p(t,e,i){return t=wp(t),function(n,o,a){return t.contain(o[0],o[1])&&!gc(n,e,i)}}function wp(t){return de.create(t)}function bp(t,e,i){return i&&"axisAreaSelect"===i.type&&e.findComponents({mainType:"parallelAxis",query:i})[0]===t}function Sp(t){var e=t.axis;return f(t.activeIntervals,function(t){return{brushType:"lineX",panelId:"pl",range:[e.dataToCoord(t[0],!0),e.dataToCoord(t[1],!0)]}})}function Mp(t,e){return e.getComponent("parallel",t.get("parallelIndex"))}function Ip(t,e){var i=t._model;return i.get("axisExpandable")&&i.get("axisExpandTriggerOn")===e}function Tp(t,e){if(!t.encodeDefine){var i=e.ecModel.getComponent("parallel",e.get("parallelIndex"));if(i){var n=t.encodeDefine=R();d(i.dimensions,function(t){var e=Ap(t);n.set(t,e)})}}}function Ap(t){return+t.replace("dim","")}function Dp(t,e,i){var n=t.model,o=t.getRect(),a=new yM({shape:{x:o.x,y:o.y,width:o.width,height:o.height}}),r="horizontal"===n.get("layout")?"width":"height";return a.setShape(r,0),To(a,{shape:{width:o.width,height:o.height}},e,i),a}function Cp(t,e,i,n){for(var o=[],a=0;a<i.length;a++){var r=i[a],s=t.get(t.mapDimension(r),e);Np(s,n.getAxis(r).type)||o.push(n.dataToPoint(s,r))}return o}function Lp(t,e,i,n,o){var a=Cp(t,i,n,o),r=new gM({shape:{points:a},silent:!0,z2:10});return e.add(r),t.setItemGraphicEl(i,r),r}function kp(t){var e=t.get("smooth",!0);return!0===e&&(e=Dk),{lineStyle:t.getModel("lineStyle").getLineStyle(),smooth:null!=e?e:Dk}}function Pp(t,e,i,n){var o=n.lineStyle;e.hasItemOption&&(o=e.getItemModel(i).getModel("lineStyle").getLineStyle()),t.useStyle(o);var a=t.style;a.fill=null,a.stroke=e.getItemVisual(i,"color"),a.opacity=e.getItemVisual(i,"opacity"),n.smooth&&(t.shape.smooth=n.smooth)}function Np(t,e){return"category"===e?null==t:null==t||isNaN(t)}function Op(t,e){return t.getVisual("opacity")||t.getModel().get(e)}function Ep(t,e,i){var n=t.getGraphicEl(),o=Op(t,e);null!=i&&(null==o&&(o=1),o*=i),n.downplay&&n.downplay(),n.traverse(function(t){"group"!==t.type&&t.setStyle("opacity",o)})}function Rp(t,e){var i=Op(t,e),n=t.getGraphicEl();n.highlight&&n.highlight(),n.traverse(function(t){"group"!==t.type&&t.setStyle("opacity",i)})}function zp(t,e,i){var n=new yM({shape:{x:t.x-10,y:t.y-10,width:0,height:t.height+20}});return To(n,{shape:{width:t.width+20,height:t.height+20}},e,i),n}function Bp(t,e){return ca(t.getBoxLayoutParams(),{width:e.getWidth(),height:e.getHeight()})}function Vp(t,e,i,n,o,a,r,s){Fp(t,e,i,o,a,s),Zp(t,e,a,o,n,r,s),eg(t,s)}function Gp(t){d(t,function(t){var e=Qp(t.outEdges,Jp),i=Qp(t.inEdges,Jp),n=Math.max(e,i);t.setLayout({value:n},!0)})}function Fp(t,e,i,n,o,a){for(var r=[],s=[],l=[],u=[],h=0,c=0;c<e.length;c++)r[c]=1;for(c=0;c<t.length;c++)s[c]=t[c].inEdges.length,0===s[c]&&l.push(t[c]);for(;l.length;){for(var d=0;d<l.length;d++){var f=l[d];"vertical"===a?(f.setLayout({y:h},!0),f.setLayout({dy:i},!0)):(f.setLayout({x:h},!0),f.setLayout({dx:i},!0));for(var p=0;p<f.outEdges.length;p++){var g=f.outEdges[p];r[e.indexOf(g)]=0;var m=g.node2;0==--s[t.indexOf(m)]&&u.push(m)}}++h,l=u,u=[]}for(c=0;c<r.length;c++);Wp(t,h,a),Hp(t,"vertical"===a?(o-i)/(h-1):(n-i)/(h-1),a)}function Wp(t,e,i){d(t,function(t){t.outEdges.length||("vertical"===i?t.setLayout({y:e-1},!0):t.setLayout({x:e-1},!0))})}function Hp(t,e,i){d(t,function(t){if("vertical"===i){var n=t.getLayout().y*e;t.setLayout({y:n},!0)}else{var o=t.getLayout().x*e;t.setLayout({x:o},!0)}})}function Zp(t,e,i,n,o,a,r){var s=Up(t,r);Xp(t,s,e,i,n,o,r),jp(s,o,i,n,r);for(var l=1;a>0;a--)Yp(s,l*=.99,r),jp(s,o,i,n,r),tg(s,l,r),jp(s,o,i,n,r)}function Up(t,e){var i=[],n="vertical"===e?"y":"x",o=Zi(t,function(t){return t.getLayout()[n]});return o.keys.sort(function(t,e){return t-e}),d(o.keys,function(t){i.push(o.buckets.get(t))}),i}function Xp(t,e,i,n,o,a,r){var s=[];d(e,function(t){var e=t.length,i=0,l=0;d(t,function(t){i+=t.getLayout().value}),l="vertical"===r?(o-(e-1)*a)/i:(n-(e-1)*a)/i,s.push(l)}),s.sort(function(t,e){return t-e});var l=s[0];d(e,function(t){d(t,function(t,e){var i=t.getLayout().value*l;"vertical"===r?(t.setLayout({x:e},!0),t.setLayout({dx:i},!0)):(t.setLayout({y:e},!0),t.setLayout({dy:i},!0))})}),d(i,function(t){var e=+t.getValue()*l;t.setLayout({dy:e},!0)})}function jp(t,e,i,n,o){d(t,function(t){var a,r,s,l=0,u=t.length;if("vertical"===o){var h;for(t.sort(function(t,e){return t.getLayout().x-e.getLayout().x}),s=0;s<u;s++)(r=l-(a=t[s]).getLayout().x)>0&&(h=a.getLayout().x+r,a.setLayout({x:h},!0)),l=a.getLayout().x+a.getLayout().dx+e;if((r=l-e-n)>0)for(h=a.getLayout().x-r,a.setLayout({x:h},!0),l=h,s=u-2;s>=0;--s)(r=(a=t[s]).getLayout().x+a.getLayout().dx+e-l)>0&&(h=a.getLayout().x-r,a.setLayout({x:h},!0)),l=a.getLayout().x}else{var c;for(t.sort(function(t,e){return t.getLayout().y-e.getLayout().y}),s=0;s<u;s++)(r=l-(a=t[s]).getLayout().y)>0&&(c=a.getLayout().y+r,a.setLayout({y:c},!0)),l=a.getLayout().y+a.getLayout().dy+e;if((r=l-e-i)>0)for(c=a.getLayout().y-r,a.setLayout({y:c},!0),l=c,s=u-2;s>=0;--s)(r=(a=t[s]).getLayout().y+a.getLayout().dy+e-l)>0&&(c=a.getLayout().y-r,a.setLayout({y:c},!0)),l=a.getLayout().y}})}function Yp(t,e,i){d(t.slice().reverse(),function(t){d(t,function(t){if(t.outEdges.length){var n=Qp(t.outEdges,qp,i)/Qp(t.outEdges,Jp,i);if("vertical"===i){var o=t.getLayout().x+(n-$p(t,i))*e;t.setLayout({x:o},!0)}else{var a=t.getLayout().y+(n-$p(t,i))*e;t.setLayout({y:a},!0)}}})})}function qp(t,e){return $p(t.node2,e)*t.getValue()}function Kp(t,e){return $p(t.node1,e)*t.getValue()}function $p(t,e){return"vertical"===e?t.getLayout().x+t.getLayout().dx/2:t.getLayout().y+t.getLayout().dy/2}function Jp(t){return t.getValue()}function Qp(t,e,i){for(var n=0,o=t.length,a=-1;++a<o;){var r=+e.call(t,t[a],i);isNaN(r)||(n+=r)}return n}function tg(t,e,i){d(t,function(t){d(t,function(t){if(t.inEdges.length){var n=Qp(t.inEdges,Kp,i)/Qp(t.inEdges,Jp,i);if("vertical"===i){var o=t.getLayout().x+(n-$p(t,i))*e;t.setLayout({x:o},!0)}else{var a=t.getLayout().y+(n-$p(t,i))*e;t.setLayout({y:a},!0)}}})})}function eg(t,e){d(t,function(t){"vertical"===e?(t.outEdges.sort(function(t,e){return t.node2.getLayout().x-e.node2.getLayout().x}),t.inEdges.sort(function(t,e){return t.node1.getLayout().x-e.node1.getLayout().x})):(t.outEdges.sort(function(t,e){return t.node2.getLayout().y-e.node2.getLayout().y}),t.inEdges.sort(function(t,e){return t.node1.getLayout().y-e.node1.getLayout().y}))}),d(t,function(t){var e=0,i=0;d(t.outEdges,function(t){t.setLayout({sy:e},!0),e+=t.getLayout().dy}),d(t.inEdges,function(t){t.setLayout({ty:i},!0),i+=t.getLayout().dy})})}function ig(t,e,i,n,o){var a=t.ends,r=new zk({shape:{points:o?og(a,n,t):a}});return ng(t,r,e,i,o),r}function ng(t,e,i,n,o){var a=i.hostModel;(0,zM[o?"initProps":"updateProps"])(e,{shape:{points:t.ends}},a,n);var r=i.getItemModel(n),s=r.getModel(Ek),l=i.getItemVisual(n,"color"),u=s.getItemStyle(["borderColor"]);u.stroke=l,u.strokeNoScale=!0,e.useStyle(u),e.z2=100,fo(e,r.getModel(Rk).getItemStyle())}function og(t,e,i){return f(t,function(t){return t=t.slice(),t[e]=i.initBaseline,t})}function ag(t){var e=[],i=[];return t.eachSeriesByType("boxplot",function(t){var n=t.getBaseAxis(),o=l(i,n);o<0&&(o=i.length,i[o]=n,e[o]={axis:n,seriesModels:[]}),e[o].seriesModels.push(t)}),e}function rg(t){var e,i,n=t.axis,o=t.seriesModels,a=o.length,r=t.boxWidthList=[],s=t.boxOffsetList=[],l=[];if("category"===n.type)i=n.getBandWidth();else{var u=0;Vk(o,function(t){u=Math.max(u,t.getData().count())}),e=n.getExtent(),Math.abs(e[1]-e[0])}Vk(o,function(t){var e=t.get("boxWidth");y(e)||(e=[e,e]),l.push([Vo(e[0],i)||0,Vo(e[1],i)||0])});var h=.8*i-2,c=h/a*.3,d=(h-c*(a-1))/a,f=d/2-h/2;Vk(o,function(t,e){s.push(f),f+=c+d,r.push(Math.min(Math.max(d,l[e][0]),l[e][1]))})}function sg(t,e,i){function n(t,i,n){var o=s.get(i,n),a=[];a[u]=t,a[h]=o;var l;return isNaN(t)||isNaN(o)?l=[NaN,NaN]:(l=r.dataToPoint(a))[u]+=e,l}function o(t,e,i){var n=e.slice(),o=e.slice();n[u]+=l,o[u]-=l,i?t.push(n,o):t.push(o,n)}function a(t,e){var i=e.slice(),n=e.slice();i[u]-=l,n[u]+=l,t.push(i,n)}var r=t.coordinateSystem,s=t.getData(),l=i/2,u="horizontal"===t.get("layout")?0:1,h=1-u,c=["x","y"],d=s.mapDimension(c[u]),f=s.mapDimension(c[h],!0);if(!(null==d||f.length<5))for(var p=0;p<s.count();p++){var g=s.get(d,p),m=n(g,f[2],p),v=n(g,f[0],p),y=n(g,f[1],p),x=n(g,f[3],p),_=n(g,f[4],p),w=[];o(w,y,0),o(w,x,1),w.push(v,y,_,x),a(w,v),a(w,_),a(w,m),s.setItemLayout(p,{initBaseline:m[h],ends:w})}}function lg(t,e,i){var n=t.ends;return new Hk({shape:{points:i?hg(n,t):n},z2:100})}function ug(t,e,i,n){var o=e.getItemModel(i),a=o.getModel(Gk),r=e.getItemVisual(i,"color"),s=e.getItemVisual(i,"borderColor")||r,l=a.getItemStyle(Wk);t.useStyle(l),t.style.strokeNoScale=!0,t.style.fill=r,t.style.stroke=s,t.__simpleBox=n,fo(t,o.getModel(Fk).getItemStyle())}function hg(t,e){return f(t,function(t){return t=t.slice(),t[1]=e.initBaseline,t})}function cg(t,e,i){var n=t.getData(),o=n.getLayout("largePoints"),a=new Zk({shape:{points:o},__sign:1});e.add(a);var r=new Zk({shape:{points:o},__sign:-1});e.add(r),dg(1,a,t,n),dg(-1,r,t,n),i&&(a.incremental=!0,r.incremental=!0)}function dg(t,e,i,n){var o=t>0?"P":"N",a=n.getVisual("borderColor"+o)||n.getVisual("color"+o),r=i.getModel(Gk).getItemStyle(Wk);e.useStyle(r),e.style.fill=null,e.style.stroke=a}function fg(t,e,i,n,o){return i>n?-1:i<n?1:e>0?t.get(o,e-1)<=n?1:-1:1}function pg(t,e){var i,n=t.getBaseAxis(),o="category"===n.type?n.getBandWidth():(i=n.getExtent(),Math.abs(i[1]-i[0])/e.count()),a=Vo(A(t.get("barMaxWidth"),o),o),r=Vo(A(t.get("barMinWidth"),1),o),s=t.get("barWidth");return null!=s?Vo(s,o):Math.max(Math.min(o/2,a),r)}function gg(t){return y(t)||(t=[+t,+t]),t}function mg(t,e){t.eachChild(function(t){t.attr({z:e.z,zlevel:e.zlevel,style:{stroke:"stroke"===e.brushType?e.color:null,fill:"fill"===e.brushType?e.color:null}})})}function vg(t,e){tb.call(this);var i=new wu(t,e),n=new tb;this.add(i),this.add(n),n.beforeUpdate=function(){this.attr(i.getScale())},this.updateData(t,e)}function yg(t){var e=t.data;e&&e[0]&&e[0][0]&&e[0][0].coord&&(t.data=f(e,function(t){var e={coords:[t[0].coord,t[1].coord]};return t[0].name&&(e.fromName=t[0].name),t[1].name&&(e.toName=t[1].name),o([e,t[0],t[1]])}))}function xg(t,e,i){tb.call(this),this.add(this.createLine(t,e,i)),this._updateEffectSymbol(t,e)}function _g(t,e,i){tb.call(this),this._createPolyline(t,e,i)}function wg(t,e,i){xg.call(this,t,e,i),this._lastFrame=0,this._lastFramePercent=0}function bg(){this.group=new tb}function Sg(t){return t instanceof Array||(t=[t,t]),t}function Mg(){var t=iw();this.canvas=t,this.blurSize=30,this.pointSize=20,this.maxOpacity=1,this.minOpacity=0,this._gradientPixels={}}function Ig(t,e,i){var n=t[1]-t[0],o=(e=f(e,function(e){return{interval:[(e.interval[0]-t[0])/n,(e.interval[1]-t[0])/n]}})).length,a=0;return function(t){for(n=a;n<o;n++)if((r=e[n].interval)[0]<=t&&t<=r[1]){a=n;break}if(n===o)for(var n=a-1;n>=0;n--){var r=e[n].interval;if(r[0]<=t&&t<=r[1]){a=n;break}}return n>=0&&n<o&&i[n]}}function Tg(t,e){var i=t[1]-t[0];return e=[(e[0]-t[0])/i,(e[1]-t[0])/i],function(t){return t>=e[0]&&t<=e[1]}}function Ag(t){var e=t.dimensions;return"lng"===e[0]&&"lat"===e[1]}function Dg(t,e,i,n){var o=t.getItemLayout(e),a=i.get("symbolRepeat"),r=i.get("symbolClip"),s=i.get("symbolPosition")||"start",l=(i.get("symbolRotate")||0)*Math.PI/180||0,u=i.get("symbolPatternSize")||2,h=i.isAnimationEnabled(),c={dataIndex:e,layout:o,itemModel:i,symbolType:t.getItemVisual(e,"symbol")||"circle",color:t.getItemVisual(e,"color"),symbolClip:r,symbolRepeat:a,symbolRepeatDirection:i.get("symbolRepeatDirection"),symbolPatternSize:u,rotation:l,animationModel:h?i:null,hoverAnimation:h&&i.get("hoverAnimation"),z2:i.getShallow("z",!0)||0};Cg(i,a,o,n,c),kg(t,e,o,a,r,c.boundingLength,c.pxSign,u,n,c),Pg(i,c.symbolScale,l,n,c);var d=c.symbolSize,f=i.get("symbolOffset");return y(f)&&(f=[Vo(f[0],d[0]),Vo(f[1],d[1])]),Ng(i,d,o,a,r,f,s,c.valueLineWidth,c.boundingLength,c.repeatCutLength,n,c),c}function Cg(t,e,i,n,o){var a,r=n.valueDim,s=t.get("symbolBoundingData"),l=n.coordSys.getOtherAxis(n.coordSys.getBaseAxis()),u=l.toGlobalCoord(l.dataToCoord(0)),h=1-+(i[r.wh]<=0);if(y(s)){var c=[Lg(l,s[0])-u,Lg(l,s[1])-u];c[1]<c[0]&&c.reverse(),a=c[h]}else a=null!=s?Lg(l,s)-u:e?n.coordSysExtent[r.index][h]-u:i[r.wh];o.boundingLength=a,e&&(o.repeatCutLength=i[r.wh]),o.pxSign=a>0?1:a<0?-1:0}function Lg(t,e){return t.toGlobalCoord(t.dataToCoord(t.scale.parse(e)))}function kg(t,e,i,n,o,a,r,s,l,u){var h=l.valueDim,c=l.categoryDim,d=Math.abs(i[c.wh]),f=t.getItemVisual(e,"symbolSize");y(f)?f=f.slice():(null==f&&(f="100%"),f=[f,f]),f[c.index]=Vo(f[c.index],d),f[h.index]=Vo(f[h.index],n?d:Math.abs(a)),u.symbolSize=f,(u.symbolScale=[f[0]/s,f[1]/s])[h.index]*=(l.isHorizontal?-1:1)*r}function Pg(t,e,i,n,o){var a=t.get(cP)||0;a&&(fP.attr({scale:e.slice(),rotation:i}),fP.updateTransform(),a/=fP.getLineScale(),a*=e[n.valueDim.index]),o.valueLineWidth=a}function Ng(t,e,i,n,o,r,s,l,u,h,c,d){var f=c.categoryDim,p=c.valueDim,g=d.pxSign,m=Math.max(e[p.index]+l,0),v=m;if(n){var y=Math.abs(u),x=T(t.get("symbolMargin"),"15%")+"",_=!1;x.lastIndexOf("!")===x.length-1&&(_=!0,x=x.slice(0,x.length-1)),x=Vo(x,e[p.index]);var w=Math.max(m+2*x,0),b=_?0:2*x,S=Qo(n),M=S?n:Kg((y+b)/w);w=m+2*(x=(y-M*m)/2/(_?M:M-1)),b=_?0:2*x,S||"fixed"===n||(M=h?Kg((Math.abs(h)+b)/w):0),v=M*w-b,d.repeatTimes=M,d.symbolMargin=x}var I=g*(v/2),A=d.pathPosition=[];A[f.index]=i[f.wh]/2,A[p.index]="start"===s?I:"end"===s?u-I:u/2,r&&(A[0]+=r[0],A[1]+=r[1]);var D=d.bundlePosition=[];D[f.index]=i[f.xy],D[p.index]=i[p.xy];var C=d.barRectShape=a({},i);C[p.wh]=g*Math.max(Math.abs(i[p.wh]),Math.abs(A[p.index]+I)),C[f.wh]=i[f.wh];var L=d.clipShape={};L[f.xy]=-i[f.xy],L[f.wh]=c.ecSize[f.wh],L[p.xy]=0,L[p.wh]=i[p.wh]}function Og(t){var e=t.symbolPatternSize,i=Jl(t.symbolType,-e/2,-e/2,e,e,t.color);return i.attr({culling:!0}),"image"!==i.type&&i.setStyle({strokeNoScale:!0}),i}function Eg(t,e,i,n){function o(t){var e=l.slice(),n=i.pxSign,o=t;return("start"===i.symbolRepeatDirection?n>0:n<0)&&(o=h-1-t),e[u.index]=d*(o-h/2+.5)+l[u.index],{position:e,scale:i.symbolScale.slice(),rotation:i.rotation}}var a=t.__pictorialBundle,r=i.symbolSize,s=i.valueLineWidth,l=i.pathPosition,u=e.valueDim,h=i.repeatTimes||0,c=0,d=r[e.valueDim.index]+s+2*i.symbolMargin;for(jg(t,function(t){t.__pictorialAnimationIndex=c,t.__pictorialRepeatTimes=h,c<h?Yg(t,null,o(c),i,n):Yg(t,null,{scale:[0,0]},i,n,function(){a.remove(t)}),Wg(t,i),c++});c<h;c++){var f=Og(i);f.__pictorialAnimationIndex=c,f.__pictorialRepeatTimes=h,a.add(f);var p=o(c);Yg(f,{position:p.position,scale:[0,0]},{scale:p.scale,rotation:p.rotation},i,n),f.on("mouseover",function(){jg(t,function(t){t.trigger("emphasis")})}).on("mouseout",function(){jg(t,function(t){t.trigger("normal")})}),Wg(f,i)}}function Rg(t,e,i,n){var o=t.__pictorialBundle,a=t.__pictorialMainPath;a?Yg(a,null,{position:i.pathPosition.slice(),scale:i.symbolScale.slice(),rotation:i.rotation},i,n):(a=t.__pictorialMainPath=Og(i),o.add(a),Yg(a,{position:i.pathPosition.slice(),scale:[0,0],rotation:i.rotation},{scale:i.symbolScale.slice()},i,n),a.on("mouseover",function(){this.trigger("emphasis")}).on("mouseout",function(){this.trigger("normal")})),Wg(a,i)}function zg(t,e,i){var n=a({},e.barRectShape),o=t.__pictorialBarRect;o?Yg(o,null,{shape:n},e,i):(o=t.__pictorialBarRect=new yM({z2:2,shape:n,silent:!0,style:{stroke:"transparent",fill:"transparent",lineWidth:0}}),t.add(o))}function Bg(t,e,i,n){if(i.symbolClip){var o=t.__pictorialClipPath,r=a({},i.clipShape),s=e.valueDim,l=i.animationModel,u=i.dataIndex;if(o)Io(o,{shape:r},l,u);else{r[s.wh]=0,o=new yM({shape:r}),t.__pictorialBundle.setClipPath(o),t.__pictorialClipPath=o;var h={};h[s.wh]=i.clipShape[s.wh],zM[n?"updateProps":"initProps"](o,{shape:h},l,u)}}}function Vg(t,e){var i=t.getItemModel(e);return i.getAnimationDelayParams=Gg,i.isAnimationEnabled=Fg,i}function Gg(t){return{index:t.__pictorialAnimationIndex,count:t.__pictorialRepeatTimes}}function Fg(){return this.parentModel.isAnimationEnabled()&&!!this.getShallow("animation")}function Wg(t,e){t.off("emphasis").off("normal");var i=e.symbolScale.slice();e.hoverAnimation&&t.on("emphasis",function(){this.animateTo({scale:[1.1*i[0],1.1*i[1]]},400,"elasticOut")}).on("normal",function(){this.animateTo({scale:i.slice()},400,"elasticOut")})}function Hg(t,e,i,n){var o=new tb,a=new tb;return o.add(a),o.__pictorialBundle=a,a.attr("position",i.bundlePosition.slice()),i.symbolRepeat?Eg(o,e,i):Rg(o,e,i),zg(o,i,n),Bg(o,e,i,n),o.__pictorialShapeStr=Xg(t,i),o.__pictorialSymbolMeta=i,o}function Zg(t,e,i){var n=i.animationModel,o=i.dataIndex;Io(t.__pictorialBundle,{position:i.bundlePosition.slice()},n,o),i.symbolRepeat?Eg(t,e,i,!0):Rg(t,e,i,!0),zg(t,i,!0),Bg(t,e,i,!0)}function Ug(t,e,i,n){var o=n.__pictorialBarRect;o&&(o.style.text=null);var a=[];jg(n,function(t){a.push(t)}),n.__pictorialMainPath&&a.push(n.__pictorialMainPath),n.__pictorialClipPath&&(i=null),d(a,function(t){Io(t,{scale:[0,0]},i,e,function(){n.parent&&n.parent.remove(n)})}),t.setItemGraphicEl(e,null)}function Xg(t,e){return[t.getItemVisual(e.dataIndex,"symbol")||"none",!!e.symbolRepeat,!!e.symbolClip].join(":")}function jg(t,e,i){d(t.__pictorialBundle.children(),function(n){n!==t.__pictorialBarRect&&e.call(i,n)})}function Yg(t,e,i,n,o,a){e&&t.attr(e),n.symbolClip&&!o?i&&t.attr(i):i&&zM[o?"updateProps":"initProps"](t,i,n.animationModel,n.dataIndex,a)}function qg(t,e,i){var n=i.color,o=i.dataIndex,a=i.itemModel,s=a.getModel("itemStyle").getItemStyle(["color"]),l=a.getModel("emphasis.itemStyle").getItemStyle(),u=a.getShallow("cursor");jg(t,function(t){t.setColor(n),t.setStyle(r({fill:n,opacity:i.opacity},s)),fo(t,l),u&&(t.cursor=u),t.z2=i.z2});var h={},c=e.valueDim.posDesc[+(i.boundingLength>0)],d=t.__pictorialBarRect;kh(d.style,h,a,n,e.seriesModel,o,c),fo(d,h)}function Kg(t){var e=Math.round(t);return Math.abs(t-e)<1e-4?e:Math.ceil(t)}function $g(t,e,i){this.dimension="single",this.dimensions=["single"],this._axis=null,this._rect,this._init(t,e,i),this.model=t}function Jg(t,e){e=e||{};var i=t.coordinateSystem,n=t.axis,o={},a=n.position,r=n.orient,s=i.getRect(),l=[s.x,s.x+s.width,s.y,s.y+s.height],u={horizontal:{top:l[2],bottom:l[3]},vertical:{left:l[0],right:l[1]}};o.position=["vertical"===r?u.vertical[a]:l[0],"horizontal"===r?u.horizontal[a]:l[3]];var h={horizontal:0,vertical:1};o.rotation=Math.PI/2*h[r];var c={top:-1,bottom:1,right:1,left:-1};o.labelDirection=o.tickDirection=o.nameDirection=c[a],t.get("axisTick.inside")&&(o.tickDirection=-o.tickDirection),T(e.labelInside,t.get("axisLabel.inside"))&&(o.labelDirection=-o.labelDirection);var d=e.rotate;return null==d&&(d=t.get("axisLabel.rotate")),o.labelRotation="top"===a?-d:d,o.z2=1,o}function Qg(t,e,i,n,o){var r=t.axis;if(!r.scale.isBlank()&&r.containData(e))if(t.involveSeries){var s=tm(e,t),l=s.payloadBatch,u=s.snapToValue;l[0]&&null==o.seriesIndex&&a(o,l[0]),!n&&t.snap&&r.containData(u)&&null!=u&&(e=u),i.showPointer(t,e,l,o),i.showTooltip(t,s,u)}else i.showPointer(t,e)}function tm(t,e){var i=e.axis,n=i.dim,o=t,a=[],r=Number.MAX_VALUE,s=-1;return _P(e.seriesModels,function(e,l){var u,h,c=e.getData().mapDimension(n,!0);if(e.getAxisTooltipData){var d=e.getAxisTooltipData(c,t,i);h=d.dataIndices,u=d.nestestValue}else{if(!(h=e.getData().indicesOfNearest(c[0],t,"category"===i.type?.5:null)).length)return;u=e.getData().get(c[0],h[0])}if(null!=u&&isFinite(u)){var f=t-u,p=Math.abs(f);p<=r&&((p<r||f>=0&&s<0)&&(r=p,s=f,o=u,a.length=0),_P(h,function(t){a.push({seriesIndex:e.seriesIndex,dataIndexInside:t,dataIndex:e.getData().getRawIndex(t)})}))}}),{payloadBatch:a,snapToValue:o}}function em(t,e,i,n){t[e.key]={value:i,payloadBatch:n}}function im(t,e,i,n){var o=i.payloadBatch,a=e.axis,r=a.model,s=e.axisPointerModel;if(e.triggerTooltip&&o.length){var l=e.coordSys.model,u=Ah(l),h=t.map[u];h||(h=t.map[u]={coordSysId:l.id,coordSysIndex:l.componentIndex,coordSysType:l.type,coordSysMainType:l.mainType,dataByAxis:[]},t.list.push(h)),h.dataByAxis.push({axisDim:a.dim,axisIndex:r.componentIndex,axisType:r.type,axisId:r.id,value:n,valueLabelOpt:{precision:s.get("label.precision"),formatter:s.get("label.formatter")},seriesDataIndices:o.slice()})}}function nm(t,e,i){var n=i.axesInfo=[];_P(e,function(e,i){var o=e.axisPointerModel.option,a=t[i];a?(!e.useHandle&&(o.status="show"),o.value=a.value,o.seriesDataIndices=(a.payloadBatch||[]).slice()):!e.useHandle&&(o.status="hide"),"show"===o.status&&n.push({axisDim:e.axis.dim,axisIndex:e.axis.model.componentIndex,value:o.value})})}function om(t,e,i,n){if(!lm(e)&&t.list.length){var o=((t.list[0].dataByAxis[0]||{}).seriesDataIndices||[])[0]||{};n({type:"showTip",escapeConnect:!0,x:e[0],y:e[1],tooltipOption:i.tooltipOption,position:i.position,dataIndexInside:o.dataIndexInside,dataIndex:o.dataIndex,seriesIndex:o.seriesIndex,dataByCoordSys:t.list})}else n({type:"hideTip"})}function am(t,e,i){var n=i.getZr(),o=bP(n).axisPointerLastHighlights||{},a=bP(n).axisPointerLastHighlights={};_P(t,function(t,e){var i=t.axisPointerModel.option;"show"===i.status&&_P(i.seriesDataIndices,function(t){var e=t.seriesIndex+" | "+t.dataIndex;a[e]=t})});var r=[],s=[];d(o,function(t,e){!a[e]&&s.push(t)}),d(a,function(t,e){!o[e]&&r.push(t)}),s.length&&i.dispatchAction({type:"downplay",escapeConnect:!0,batch:s}),r.length&&i.dispatchAction({type:"highlight",escapeConnect:!0,batch:r})}function rm(t,e){for(var i=0;i<(t||[]).length;i++){var n=t[i];if(e.axis.dim===n.axisDim&&e.axis.model.componentIndex===n.axisIndex)return n}}function sm(t){var e=t.axis.model,i={},n=i.axisDim=t.axis.dim;return i.axisIndex=i[n+"AxisIndex"]=e.componentIndex,i.axisName=i[n+"AxisName"]=e.name,i.axisId=i[n+"AxisId"]=e.id,i}function lm(t){return!t||null==t[0]||isNaN(t[0])||null==t[1]||isNaN(t[1])}function um(t,e,i){if(!U_.node){var n=e.getZr();SP(n).records||(SP(n).records={}),hm(n,e),(SP(n).records[t]||(SP(n).records[t]={})).handler=i}}function hm(t,e){function i(i,n){t.on(i,function(i){var o=pm(e);MP(SP(t).records,function(t){t&&n(t,i,o.dispatchAction)}),cm(o.pendings,e)})}SP(t).initialized||(SP(t).initialized=!0,i("click",v(fm,"click")),i("mousemove",v(fm,"mousemove")),i("globalout",dm))}function cm(t,e){var i,n=t.showTip.length,o=t.hideTip.length;n?i=t.showTip[n-1]:o&&(i=t.hideTip[o-1]),i&&(i.dispatchAction=null,e.dispatchAction(i))}function dm(t,e,i){t.handler("leave",null,i)}function fm(t,e,i,n){e.handler(t,i,n)}function pm(t){var e={showTip:[],hideTip:[]},i=function(n){var o=e[n.type];o?o.push(n):(n.dispatchAction=i,t.dispatchAction(n))};return{dispatchAction:i,pendings:e}}function gm(t,e){if(!U_.node){var i=e.getZr();(SP(i).records||{})[t]&&(SP(i).records[t]=null)}}function mm(){}function vm(t,e,i,n){ym(TP(i).lastProp,n)||(TP(i).lastProp=n,e?Io(i,n,t):(i.stopAnimation(),i.attr(n)))}function ym(t,e){if(w(t)&&w(e)){var i=!0;return d(e,function(e,n){i=i&&ym(t[n],e)}),!!i}return t===e}function xm(t,e){t[e.get("label.show")?"show":"hide"]()}function _m(t){return{position:t.position.slice(),rotation:t.rotation||0}}function wm(t,e,i){var n=e.get("z"),o=e.get("zlevel");t&&t.traverse(function(t){"group"!==t.type&&(null!=n&&(t.z=n),null!=o&&(t.zlevel=o),t.silent=i)})}function bm(t){var e,i=t.get("type"),n=t.getModel(i+"Style");return"line"===i?(e=n.getLineStyle()).fill=null:"shadow"===i&&((e=n.getAreaStyle()).stroke=null),e}function Sm(t,e,i,n,o){var a=Im(i.get("value"),e.axis,e.ecModel,i.get("seriesDataIndices"),{precision:i.get("label.precision"),formatter:i.get("label.formatter")}),r=i.getModel("label"),s=qM(r.get("padding")||0),l=r.getFont(),u=ke(a,l),h=o.position,c=u.width+s[1]+s[3],d=u.height+s[0]+s[2],f=o.align;"right"===f&&(h[0]-=c),"center"===f&&(h[0]-=c/2);var p=o.verticalAlign;"bottom"===p&&(h[1]-=d),"middle"===p&&(h[1]-=d/2),Mm(h,c,d,n);var g=r.get("backgroundColor");g&&"auto"!==g||(g=e.get("axisLine.lineStyle.color")),t.label={shape:{x:0,y:0,width:c,height:d,r:r.get("borderRadius")},position:h.slice(),style:{text:a,textFont:l,textFill:r.getTextColor(),textPosition:"inside",fill:g,stroke:r.get("borderColor")||"transparent",lineWidth:r.get("borderWidth")||0,shadowBlur:r.get("shadowBlur"),shadowColor:r.get("shadowColor"),shadowOffsetX:r.get("shadowOffsetX"),shadowOffsetY:r.get("shadowOffsetY")},z2:10}}function Mm(t,e,i,n){var o=n.getWidth(),a=n.getHeight();t[0]=Math.min(t[0]+e,o)-e,t[1]=Math.min(t[1]+i,a)-i,t[0]=Math.max(t[0],0),t[1]=Math.max(t[1],0)}function Im(t,e,i,n,o){t=e.scale.parse(t);var a=e.scale.getLabel(t,{precision:o.precision}),r=o.formatter;if(r){var s={value:Xl(e,t),seriesData:[]};d(n,function(t){var e=i.getSeriesByIndex(t.seriesIndex),n=t.dataIndexInside,o=e&&e.getDataParams(n);o&&s.seriesData.push(o)}),_(r)?a=r.replace("{value}",a):x(r)&&(a=r(s))}return a}function Tm(t,e,i){var n=xt();return Mt(n,n,i.rotation),St(n,n,i.position),Do([t.dataToCoord(e),(i.labelOffset||0)+(i.labelDirection||1)*(i.labelMargin||0)],n)}function Am(t,e,i,n,o,a){var r=FD.innerTextLayout(i.rotation,0,i.labelDirection);i.labelMargin=o.get("label.margin"),Sm(e,n,o,a,{position:Tm(n.axis,t,i),align:r.textAlign,verticalAlign:r.textVerticalAlign})}function Dm(t,e,i){return i=i||0,{x1:t[i],y1:t[1-i],x2:e[i],y2:e[1-i]}}function Cm(t,e,i){return i=i||0,{x:t[i],y:t[1-i],width:e[i],height:e[1-i]}}function Lm(t,e,i,n,o,a){return{cx:t,cy:e,r0:i,r:n,startAngle:o,endAngle:a,clockwise:!0}}function km(t,e){var i={};return i[e.dim+"AxisIndex"]=e.index,t.getCartesian(i)}function Pm(t){return"x"===t.dim?0:1}function Nm(t){return t.isHorizontal()?0:1}function Om(t,e){var i=t.getRect();return[i[kP[e]],i[kP[e]]+i[PP[e]]]}function Em(t,e,i){var n=new yM({shape:{x:t.x-10,y:t.y-10,width:0,height:t.height+20}});return To(n,{shape:{width:t.width+20,height:t.height+20}},e,i),n}function Rm(t,e,i){if(t.count())for(var n,o=e.coordinateSystem,a=e.getLayerSeries(),r=t.mapDimension("single"),s=t.mapDimension("value"),l=f(a,function(e){return f(e.indices,function(e){var i=o.dataToPoint(t.get(r,e));return i[1]=t.get(s,e),i})}),u=zm(l),h=u.y0,c=i/u.max,d=a.length,p=a[0].indices.length,g=0;g<p;++g){n=h[g]*c,t.setItemLayout(a[0].indices[g],{layerIndex:0,x:l[0][g][0],y0:n,y:l[0][g][1]*c});for(var m=1;m<d;++m)n+=l[m-1][g][1]*c,t.setItemLayout(a[m].indices[g],{layerIndex:m,x:l[m][g][0],y0:n,y:l[m][g][1]*c})}}function zm(t){for(var e=t.length,i=t[0].length,n=[],o=[],a=0,r={},s=0;s<i;++s){for(var l=0,u=0;l<e;++l)u+=t[l][s][1];u>a&&(a=u),n.push(u)}for(var h=0;h<i;++h)o[h]=(a-n[h])/2;a=0;for(var c=0;c<i;++c){var d=n[c]+o[c];d>a&&(a=d)}return r.y0=o,r.max=a,r}function Bm(t){var e=0;d(t.children,function(t){Bm(t);var i=t.value;y(i)&&(i=i[0]),e+=i});var i=t.value;y(i)&&(i=i[0]),(null==i||isNaN(i))&&(i=e),i<0&&(i=0),y(t.value)?t.value[0]=i:t.value=i}function Vm(t,e,i){function n(){r.ignore=r.hoverIgnore}function o(){r.ignore=r.normalIgnore}tb.call(this);var a=new hM({z2:zP});a.seriesIndex=e.seriesIndex;var r=new rM({z2:BP,silent:t.getModel("label").get("silent")});this.add(a),this.add(r),this.updateData(!0,t,"normal",e,i),this.on("emphasis",n).on("normal",o).on("mouseover",n).on("mouseout",o)}function Gm(t,e,i){var n=t.getVisual("color"),o=t.getVisual("visualMeta");o&&0!==o.length||(n=null);var a=t.getModel("itemStyle").get("color");if(a)return a;if(n)return n;if(0===t.depth)return i.option.color[0];var r=i.option.color.length;return a=i.option.color[Fm(t)%r]}function Fm(t){for(var e=t;e.depth>1;)e=e.parentNode;return l(t.getAncestors()[0].children,e)}function Wm(t,e,i){return i!==RP.NONE&&(i===RP.SELF?t===e:i===RP.ANCESTOR?t===e||t.isAncestorOf(e):t===e||t.isDescendantOf(e))}function Hm(t,e,i){e.getData().setItemVisual(t.dataIndex,"color",i)}function Zm(t,e){var i=t.children||[];t.children=Um(i,e),i.length&&d(t.children,function(t){Zm(t,e)})}function Um(t,e){if("function"==typeof e)return t.sort(e);var i="asc"===e;return t.sort(function(t,e){var n=(t.getValue()-e.getValue())*(i?1:-1);return 0===n?(t.dataIndex-e.dataIndex)*(i?-1:1):n})}function Xm(t,e){return e=e||[0,0],f(["x","y"],function(i,n){var o=this.getAxis(i),a=e[n],r=t[n]/2;return"category"===o.type?o.getBandWidth():Math.abs(o.dataToCoord(a-r)-o.dataToCoord(a+r))},this)}function jm(t,e){return e=e||[0,0],f([0,1],function(i){var n=e[i],o=t[i]/2,a=[],r=[];return a[i]=n-o,r[i]=n+o,a[1-i]=r[1-i]=e[1-i],Math.abs(this.dataToPoint(a)[i]-this.dataToPoint(r)[i])},this)}function Ym(t,e){var i=this.getAxis(),n=e instanceof Array?e[0]:e,o=(t instanceof Array?t[0]:t)/2;return"category"===i.type?i.getBandWidth():Math.abs(i.dataToCoord(n-o)-i.dataToCoord(n+o))}function qm(t,e){return f(["Radius","Angle"],function(i,n){var o=this["get"+i+"Axis"](),a=e[n],r=t[n]/2,s="dataTo"+i,l="category"===o.type?o.getBandWidth():Math.abs(o[s](a-r)-o[s](a+r));return"Angle"===i&&(l=l*Math.PI/180),l},this)}function Km(t){var e,i=t.type;if("path"===i){var n=t.shape,o=null!=n.width&&null!=n.height?{x:n.x||0,y:n.y||0,width:n.width,height:n.height}:null,a=lv(n);(e=Xn(a,null,o,n.layout||"center")).__customPathData=a}else"image"===i?(e=new fi({})).__customImagePath=t.style.image:"text"===i?(e=new rM({})).__customText=t.style.text:e=new(0,zM[i.charAt(0).toUpperCase()+i.slice(1)]);return e.__customGraphicType=i,e.name=t.name,e}function $m(t,e,n,o,a,r,s){var l={},u=n.style||{};if(n.shape&&(l.shape=i(n.shape)),n.position&&(l.position=n.position.slice()),n.scale&&(l.scale=n.scale.slice()),n.origin&&(l.origin=n.origin.slice()),n.rotation&&(l.rotation=n.rotation),"image"===t.type&&n.style){h=l.style={};d(["x","y","width","height"],function(e){Jm(e,h,u,t.style,r)})}if("text"===t.type&&n.style){var h=l.style={};d(["x","y"],function(e){Jm(e,h,u,t.style,r)}),!u.hasOwnProperty("textFill")&&u.fill&&(u.textFill=u.fill),!u.hasOwnProperty("textStroke")&&u.stroke&&(u.textStroke=u.stroke)}if("group"!==t.type&&(t.useStyle(u),r)){t.style.opacity=0;var c=u.opacity;null==c&&(c=1),To(t,{style:{opacity:c}},o,e)}r?t.attr(l):Io(t,l,o,e),n.hasOwnProperty("z2")&&t.attr("z2",n.z2||0),n.hasOwnProperty("silent")&&t.attr("silent",n.silent),n.hasOwnProperty("invisible")&&t.attr("invisible",n.invisible),n.hasOwnProperty("ignore")&&t.attr("ignore",n.ignore),n.hasOwnProperty("info")&&t.attr("info",n.info);var f=n.styleEmphasis,p=!1===f;t.__cusHasEmphStl&&null==f||!t.__cusHasEmphStl&&p||(ro(t,f),t.__cusHasEmphStl=!p),s&&po(t,!p)}function Jm(t,e,i,n,o){null==i[t]||o||(e[t]=i[t],i[t]=n[t])}function Qm(t,e,i,n){function o(t){null==t&&(t=h),v&&(c=e.getItemModel(t),d=c.getModel(UP),f=c.getModel(XP),p=e.getItemVisual(t,"color"),v=!1)}var s=t.get("renderItem"),l=t.coordinateSystem,u={};l&&(u=l.prepareCustoms?l.prepareCustoms():YP[l.type](l));var h,c,d,f,p,g=r({getWidth:n.getWidth,getHeight:n.getHeight,getZr:n.getZr,getDevicePixelRatio:n.getDevicePixelRatio,value:function(t,i){return null==i&&(i=h),e.get(e.getDimension(t||0),i)},style:function(i,n){null==n&&(n=h),o(n);var r=c.getModel(HP).getItemStyle();null!=p&&(r.fill=p);var s=e.getItemVisual(n,"opacity");return null!=s&&(r.opacity=s),mo(r,d,null,{autoColor:p,isRectText:!0}),r.text=d.getShallow("show")?A(t.getFormattedLabel(n,"normal"),_u(e,n)):null,i&&a(r,i),r},styleEmphasis:function(i,n){null==n&&(n=h),o(n);var r=c.getModel(ZP).getItemStyle();return mo(r,f,null,{isRectText:!0},!0),r.text=f.getShallow("show")?D(t.getFormattedLabel(n,"emphasis"),t.getFormattedLabel(n,"normal"),_u(e,n)):null,i&&a(r,i),r},visual:function(t,i){return null==i&&(i=h),e.getItemVisual(i,t)},barLayout:function(t){if(l.getBaseAxis)return Ll(r({axis:l.getBaseAxis()},t),n)},currentSeriesIndices:function(){return i.getCurrentSeriesIndices()},font:function(t){return So(t,i)}},u.api||{}),m={context:{},seriesId:t.id,seriesName:t.name,seriesIndex:t.seriesIndex,coordSys:u.coordSys,dataInsideLength:e.count(),encode:tv(t.getData())},v=!0;return function(t,i){return h=t,v=!0,s&&s(r({dataIndexInside:t,dataIndex:e.getRawIndex(t),actionType:i?i.type:null},m),g)}}function tv(t){var e={};return d(t.dimensions,function(i,n){var o=t.getDimensionInfo(i);if(!o.isExtraCoord){var a=o.coordDim;(e[a]=e[a]||[])[o.coordDimIndex]=n}}),e}function ev(t,e,i,n,o,a){return(t=iv(t,e,i,n,o,a,!0))&&a.setItemGraphicEl(e,t),t}function iv(t,e,i,n,o,a,r){var s=!i,l=(i=i||{}).type,u=i.shape,h=i.style;if(t&&(s||null!=l&&l!==t.__customGraphicType||"path"===l&&uv(u)&&lv(u)!==t.__customPathData||"image"===l&&hv(h,"image")&&h.image!==t.__customImagePath||"text"===l&&hv(u,"text")&&h.text!==t.__customText)&&(o.remove(t),t=null),!s){var c=!t;return!t&&(t=Km(i)),$m(t,e,i,n,a,c,r),"group"===l&&nv(t,e,i,n,a),o.add(t),t}}function nv(t,e,i,n,o){var a=i.children,r=a?a.length:0,s=i.$mergeChildren,l="byName"===s||i.diffChildrenByName,u=!1===s;if(r||l||u)if(l)ov({oldChildren:t.children()||[],newChildren:a||[],dataIndex:e,animatableModel:n,group:t,data:o});else{u&&t.removeAll();for(var h=0;h<r;h++)a[h]&&iv(t.childAt(h),e,a[h],n,t,o)}}function ov(t){new Xs(t.oldChildren,t.newChildren,av,av,t).add(rv).update(rv).remove(sv).execute()}function av(t,e){var i=t&&t.name;return null!=i?i:jP+e}function rv(t,e){var i=this.context,n=null!=t?i.newChildren[t]:null;iv(null!=e?i.oldChildren[e]:null,i.dataIndex,n,i.animatableModel,i.group,i.data)}function sv(t){var e=this.context,i=e.oldChildren[t];i&&e.group.remove(i)}function lv(t){return t&&(t.pathData||t.d)}function uv(t){return t&&(t.hasOwnProperty("pathData")||t.hasOwnProperty("d"))}function hv(t,e){return t&&t.hasOwnProperty(e)}function cv(t,e,i,n){var o=i.type,a=new(0,zM[o.charAt(0).toUpperCase()+o.slice(1)])(i);e.add(a),n.set(t,a),a.__ecGraphicId=t}function dv(t,e){var i=t&&t.parent;i&&("group"===t.type&&t.traverse(function(t){dv(t,e)}),e.removeKey(t.__ecGraphicId),i.remove(t))}function fv(t){return t=a({},t),d(["id","parentId","$action","hv","bounding"].concat(nI),function(e){delete t[e]}),t}function pv(t,e){var i;return d(e,function(e){null!=t[e]&&"auto"!==t[e]&&(i=!0)}),i}function gv(t,e){var i=t.exist;if(e.id=t.keyInfo.id,!e.type&&i&&(e.type=i.type),null==e.parentId){var n=e.parentOption;n?e.parentId=n.id:i&&(e.parentId=i.parentId)}e.parentOption=null}function mv(t,e,i){var o=a({},i),r=t[e],s=i.$action||"merge";"merge"===s?r?(n(r,o,!0),pa(r,o,{ignoreSize:!0}),ma(i,r)):t[e]=o:"replace"===s?t[e]=o:"remove"===s&&r&&(t[e]=null)}function vv(t,e){t&&(t.hv=e.hv=[pv(e,["left","right"]),pv(e,["top","bottom"])],"group"===t.type&&(null==t.width&&(t.width=e.width=0),null==t.height&&(t.height=e.height=0)))}function yv(t,e,i){var n=t.eventData;t.silent||t.ignore||n||(n=t.eventData={componentType:"graphic",componentIndex:e.componentIndex,name:t.name}),n&&(n.info=t.info)}function xv(t,e,i){var n,o={},a="toggleSelected"===t;return i.eachComponent("legend",function(i){a&&null!=n?i[n?"select":"unSelect"](e.name):(i[t](e.name),n=i.isSelected(e.name)),d(i.getData(),function(t){var e=t.get("name");if("\n"!==e&&""!==e){var n=i.isSelected(e);o.hasOwnProperty(e)?o[e]=o[e]&&n:o[e]=n}})}),{name:e.name,selected:o}}function _v(t,e,i){var n=e.getBoxLayoutParams(),o=e.get("padding"),a={width:i.getWidth(),height:i.getHeight()},r=ca(n,a,o);aI(e.get("orient"),t,e.get("itemGap"),r.width,r.height),da(t,n,a,o)}function wv(t,e){var i=qM(e.get("padding")),n=e.getItemStyle(["color","opacity"]);return n.fill=e.get("backgroundColor"),t=new yM({shape:{x:t.x-i[3],y:t.y-i[0],width:t.width+i[1]+i[3],height:t.height+i[0]+i[2],r:e.get("borderRadius")},style:n,silent:!0,z2:-1})}function bv(t,e){e.dispatchAction({type:"legendToggleSelect",name:t})}function Sv(t,e,i,n){var o=i.getZr().storage.getDisplayList()[0];o&&o.useHoverLayer||i.dispatchAction({type:"highlight",seriesName:t,name:e,excludeSeriesId:n})}function Mv(t,e,i,n){var o=i.getZr().storage.getDisplayList()[0];o&&o.useHoverLayer||i.dispatchAction({type:"downplay",seriesName:t,name:e,excludeSeriesId:n})}function Iv(t,e,i){var n=[1,1];n[t.getOrient().index]=0,pa(e,i,{type:"box",ignoreSize:n})}function Tv(t){var e="left "+t+"s cubic-bezier(0.23, 1, 0.32, 1),top "+t+"s cubic-bezier(0.23, 1, 0.32, 1)";return f(lN,function(t){return t+"transition:"+e}).join(";")}function Av(t){var e=[],i=t.get("fontSize"),n=t.getTextColor();return n&&e.push("color:"+n),e.push("font:"+t.getFont()),i&&e.push("line-height:"+Math.round(3*i/2)+"px"),rN(["decoration","align"],function(i){var n=t.get(i);n&&e.push("text-"+i+":"+n)}),e.join(";")}function Dv(t){var e=[],i=t.get("transitionDuration"),n=t.get("backgroundColor"),o=t.getModel("textStyle"),a=t.get("padding");return i&&e.push(Tv(i)),n&&(U_.canvasSupported?e.push("background-Color:"+n):(e.push("background-Color:#"+Zt(n)),e.push("filter:alpha(opacity=70)"))),rN(["width","color","radius"],function(i){var n="border-"+i,o=sN(n),a=t.get(o);null!=a&&e.push(n+":"+a+("color"===i?"":"px"))}),e.push(Av(o)),null!=a&&e.push("padding:"+qM(a).join("px ")+"px"),e.join(";")+";"}function Cv(t,e){if(U_.wxa)return null;var i=document.createElement("div"),n=this._zr=e.getZr();this.el=i,this._x=e.getWidth()/2,this._y=e.getHeight()/2,t.appendChild(i),this._container=t,this._show=!1,this._hideTimeout;var o=this;i.onmouseenter=function(){o._enterable&&(clearTimeout(o._hideTimeout),o._show=!0),o._inContent=!0},i.onmousemove=function(e){if(e=e||window.event,!o._enterable){var i=n.handler;ut(t,e,!0),i.dispatch("mousemove",e)}},i.onmouseleave=function(){o._enterable&&o._show&&o.hideLater(o._hideDelay),o._inContent=!1}}function Lv(t){this._zr=t.getZr(),this._show=!1,this._hideTimeout}function kv(t){for(var e=t.pop();t.length;){var i=t.pop();i&&(No.isInstance(i)&&(i=i.get("tooltip",!0)),"string"==typeof i&&(i={formatter:i}),e=new No(i,e,e.ecModel))}return e}function Pv(t,e){return t.dispatchAction||m(e.dispatchAction,e)}function Nv(t,e,i,n,o,a,r){var s=i.getOuterSize(),l=s.width,u=s.height;return null!=a&&(t+l+a>n?t-=l+a:t+=a),null!=r&&(e+u+r>o?e-=u+r:e+=r),[t,e]}function Ov(t,e,i,n,o){var a=i.getOuterSize(),r=a.width,s=a.height;return t=Math.min(t+r,n)-r,e=Math.min(e+s,o)-s,t=Math.max(t,0),e=Math.max(e,0),[t,e]}function Ev(t,e,i){var n=i[0],o=i[1],a=0,r=0,s=e.width,l=e.height;switch(t){case"inside":a=e.x+s/2-n/2,r=e.y+l/2-o/2;break;case"top":a=e.x+s/2-n/2,r=e.y-o-5;break;case"bottom":a=e.x+s/2-n/2,r=e.y+l+5;break;case"left":a=e.x-n-5,r=e.y+l/2-o/2;break;case"right":a=e.x+s+5,r=e.y+l/2-o/2}return[a,r]}function Rv(t){return"center"===t||"middle"===t}function zv(t){return t.get("stack")||"__ec_stack_"+t.seriesIndex}function Bv(t){return t.dim}function Vv(t,e){var i={};d(t,function(t,e){var n=t.getData(),o=t.coordinateSystem.getBaseAxis(),a=o.getExtent(),r="category"===o.type?o.getBandWidth():Math.abs(a[1]-a[0])/n.count(),s=i[Bv(o)]||{bandWidth:r,remainedWidth:r,autoWidthCount:0,categoryGap:"20%",gap:"30%",stacks:{}},l=s.stacks;i[Bv(o)]=s;var u=zv(t);l[u]||s.autoWidthCount++,l[u]=l[u]||{width:0,maxWidth:0};var h=Vo(t.get("barWidth"),r),c=Vo(t.get("barMaxWidth"),r),d=t.get("barGap"),f=t.get("barCategoryGap");h&&!l[u].width&&(h=Math.min(s.remainedWidth,h),l[u].width=h,s.remainedWidth-=h),c&&(l[u].maxWidth=c),null!=d&&(s.gap=d),null!=f&&(s.categoryGap=f)});var n={};return d(i,function(t,e){n[e]={};var i=t.stacks,o=t.bandWidth,a=Vo(t.categoryGap,o),r=Vo(t.gap,1),s=t.remainedWidth,l=t.autoWidthCount,u=(s-a)/(l+(l-1)*r);u=Math.max(u,0),d(i,function(t,e){var i=t.maxWidth;i&&i<u&&(i=Math.min(i,s),t.width&&(i=Math.min(i,t.width)),s-=i,t.width=i,l--)}),u=(s-a)/(l+(l-1)*r),u=Math.max(u,0);var h,c=0;d(i,function(t,e){t.width||(t.width=u),h=t,c+=t.width*(1+r)}),h&&(c-=h.width*r);var f=-c/2;d(i,function(t,i){n[e][i]=n[e][i]||{offset:f,width:t.width},f+=t.width*(1+r)})}),n}function Gv(t,e){aD.call(this,"radius",t,e),this.type="category"}function Fv(t,e){e=e||[0,360],aD.call(this,"angle",t,e),this.type="category"}function Wv(t,e){return e.type||(e.data?"category":"value")}function Hv(t,e,i){var n=e.get("center"),o=i.getWidth(),a=i.getHeight();t.cx=Vo(n[0],o),t.cy=Vo(n[1],a);var r=t.getRadiusAxis(),s=Math.min(o,a)/2,l=Vo(e.get("radius"),s);r.inverse?r.setExtent(l,0):r.setExtent(0,l)}function Zv(t,e){var i=this,n=i.getAngleAxis(),o=i.getRadiusAxis();if(n.scale.setExtent(1/0,-1/0),o.scale.setExtent(1/0,-1/0),t.eachSeries(function(t){if(t.coordinateSystem===i){var e=t.getData();d(e.mapDimension("radius",!0),function(t){o.scale.unionExtentFromData(e,gl(e,t))}),d(e.mapDimension("angle",!0),function(t){n.scale.unionExtentFromData(e,gl(e,t))})}}),Wl(n.scale,n.model),Wl(o.scale,o.model),"category"===n.type&&!n.onBand){var a=n.getExtent(),r=360/n.scale.count();n.inverse?a[1]+=r:a[1]-=r,n.setExtent(a[0],a[1])}}function Uv(t,e){if(t.type=e.get("type"),t.scale=Hl(e),t.onBand=e.get("boundaryGap")&&"category"===t.type,t.inverse=e.get("inverse"),"angleAxis"===e.mainType){t.inverse^=e.get("clockwise");var i=e.get("startAngle");t.setExtent(i,i+(t.inverse?-360:360))}e.axis=t,t.model=e}function Xv(t,e,i){e[1]>e[0]&&(e=e.slice().reverse());var n=t.coordToPoint([e[0],i]),o=t.coordToPoint([e[1],i]);return{x1:n[0],y1:n[1],x2:o[0],y2:o[1]}}function jv(t){return t.getRadiusAxis().inverse?0:1}function Yv(t){var e=t[0],i=t[t.length-1];e&&i&&Math.abs(Math.abs(e.coord-i.coord)-360)<1e-4&&t.pop()}function qv(t,e,i){return{position:[t.cx,t.cy],rotation:i/180*Math.PI,labelDirection:-1,tickDirection:-1,nameDirection:1,labelRotate:e.getModel("axisLabel").get("rotate"),z2:1}}function Kv(t,e,i,n,o){var a=e.axis,r=a.dataToCoord(t),s=n.getAngleAxis().getExtent()[0];s=s/180*Math.PI;var l,u,h,c=n.getRadiusAxis().getExtent();if("radius"===a.dim){var d=xt();Mt(d,d,s),St(d,d,[n.cx,n.cy]),l=Do([r,-o],d);var f=e.getModel("axisLabel").get("rotate")||0,p=FD.innerTextLayout(s,f*Math.PI/180,-1);u=p.textAlign,h=p.textVerticalAlign}else{var g=c[1];l=n.coordToPoint([g+o,r]);var m=n.cx,v=n.cy;u=Math.abs(l[0]-m)/g<.3?"center":l[0]>m?"left":"right",h=Math.abs(l[1]-v)/g<.3?"middle":l[1]>v?"top":"bottom"}return{position:l,align:u,verticalAlign:h}}function $v(t,e){e.update="updateView",Es(e,function(e,i){var n={};return i.eachComponent({mainType:"geo",query:e},function(i){i[t](e.name),d(i.coordinateSystem.regions,function(t){n[t.name]=i.isSelected(t.name)||!1})}),{selected:n,name:e.name}})}function Jv(t){var e={};d(t,function(t){e[t]=1}),t.length=0,d(e,function(e,i){t.push(i)})}function Qv(t){if(t)for(var e in t)if(t.hasOwnProperty(e))return!0}function ty(t,e,n){function o(){var t=function(){};return t.prototype.__hidden=t.prototype,new t}var a={};return MN(e,function(e){var r=a[e]=o();MN(t[e],function(t,o){if(hL.isValidType(o)){var a={type:o,visual:t};n&&n(a,e),r[o]=new hL(a),"opacity"===o&&((a=i(a)).type="colorAlpha",r.__hidden.__alphaForOpacity=new hL(a))}})}),a}function ey(t,e,n){var o;d(n,function(t){e.hasOwnProperty(t)&&Qv(e[t])&&(o=!0)}),o&&d(n,function(n){e.hasOwnProperty(n)&&Qv(e[n])?t[n]=i(e[n]):delete t[n]})}function iy(t,e,i,n,o,a){function r(t){return i.getItemVisual(h,t)}function s(t,e){i.setItemVisual(h,t,e)}function l(t,l){h=null==a?t:l;var c=i.getRawDataItem(h);if(!c||!1!==c.visualMap)for(var d=n.call(o,t),f=e[d],p=u[d],g=0,m=p.length;g<m;g++){var v=p[g];f[v]&&f[v].applyVisual(t,r,s)}}var u={};d(t,function(t){var i=hL.prepareVisualTypes(e[t]);u[t]=i});var h;null==a?i.each(l):i.each([a],l)}function ny(t,e,i,n){var o={};return d(t,function(t){var i=hL.prepareVisualTypes(e[t]);o[t]=i}),{progress:function(t,a){null!=n&&(n=a.getDimension(n));for(var r;null!=(r=t.next());){var s=a.getRawDataItem(r);if(!s||!1!==s.visualMap)for(var l=null!=n?a.get(n,r,!0):r,u=i(l),h=e[u],c=o[u],d=0,f=c.length;d<f;d++){var p=c[d];h[p]&&h[p].applyVisual(l,function(t){return a.getItemVisual(r,t)},function(t,e){a.setItemVisual(r,t,e)})}}}}}function oy(t){var e=["x","y"],i=["width","height"];return{point:function(e,i,n){if(e){var o=n.range;return ay(e[t],o)}},rect:function(n,o,a){if(n){var r=a.range,s=[n[e[t]],n[e[t]]+n[i[t]]];return s[1]<s[0]&&s.reverse(),ay(s[0],r)||ay(s[1],r)||ay(r[0],s)||ay(r[1],s)}}}}function ay(t,e){return e[0]<=t&&t<=e[1]}function ry(t,e,i,n,o){for(var a=0,r=o[o.length-1];a<o.length;a++){var s=o[a];if(sy(t,e,i,n,s[0],s[1],r[0],r[1]))return!0;r=s}}function sy(t,e,i,n,o,a,r,s){var l=uy(i-t,o-r,n-e,a-s);if(ly(l))return!1;var u=uy(o-t,o-r,a-e,a-s)/l;if(u<0||u>1)return!1;var h=uy(i-t,o-t,n-e,a-e)/l;return!(h<0||h>1)}function ly(t){return t<=1e-6&&t>=-1e-6}function uy(t,e,i,n){return t*n-e*i}function hy(t,e,i){var n=this._targetInfoList=[],o={},a=dy(e,t);TN(PN,function(t,e){(!i||!i.include||AN(i.include,e)>=0)&&t(a,n,o)})}function cy(t){return t[0]>t[1]&&t.reverse(),t}function dy(t,e){return Vi(t,e,{includeMainTypes:LN})}function fy(t,e,i,n){var o=i.getAxis(["x","y"][t]),a=cy(f([0,1],function(t){return e?o.coordToData(o.toLocalCoord(n[t])):o.toGlobalCoord(o.dataToCoord(n[t]))})),r=[];return r[t]=a,r[1-t]=[NaN,NaN],{values:a,xyMinMax:r}}function py(t,e,i,n){return[e[0]-n[t]*i[0],e[1]-n[t]*i[1]]}function gy(t,e){var i=my(t),n=my(e),o=[i[0]/n[0],i[1]/n[1]];return isNaN(o[0])&&(o[0]=1),isNaN(o[1])&&(o[1]=1),o}function my(t){return t?[t[0][1]-t[0][0],t[1][1]-t[1][0]]:[NaN,NaN]}function vy(t,e,i,n,o){if(o){var a=t.getZr();a[VN]||(a[BN]||(a[BN]=yy),Nr(a,BN,i,e)(t,n))}}function yy(t,e){if(!t.isDisposed()){var i=t.getZr();i[VN]=!0,t.dispatchAction({type:"brushSelect",batch:e}),i[VN]=!1}}function xy(t,e,i,n){for(var o=0,a=e.length;o<a;o++){var r=e[o];if(t[r.brushType](n,i,r.selectors,r))return!0}}function _y(t){var e=t.brushSelector;if(_(e)){var i=[];return d(IN,function(t,n){i[n]=function(i,n,o,a){var r=n.getItemLayout(i);return t[e](r,o,a)}}),i}if(x(e)){var n={};return d(IN,function(t,i){n[i]=e}),n}return e}function wy(t,e){var i=t.option.seriesIndex;return null!=i&&"all"!==i&&(y(i)?l(i,e)<0:e!==i)}function by(t){var e=t.selectors={};return d(IN[t.brushType],function(i,n){e[n]=function(n){return i(n,e,t)}}),t}function Sy(t){return new de(t[0][0],t[1][0],t[0][1]-t[0][0],t[1][1]-t[1][0])}function My(t,e){return n({brushType:t.brushType,brushMode:t.brushMode,transformable:t.transformable,brushStyle:new No(t.brushStyle).getItemStyle(),removeOnClick:t.removeOnClick,z:t.z},e,!0)}function Iy(t,e,i,n){(!n||n.$from!==t.id)&&this._brushController.setPanels(t.brushTargetManager.makePanelOpts(i)).enableBrush(t.brushOption).updateCovers(t.areas.slice())}function Ty(t,e){HN[t]=e}function Ay(t){return HN[t]}function Dy(t,e,i){this.model=t,this.ecModel=e,this.api=i,this._brushType,this._brushMode}function Cy(t,e,i){this._model=t}function Ly(t,e,i,n){var o=i.calendarModel,a=i.seriesModel,r=o?o.coordinateSystem:a?a.coordinateSystem:null;return r===this?r[t](n):null}function ky(t,e){var i=t.cellSize;y(i)?1===i.length&&(i[1]=i[0]):i=t.cellSize=[i,i];var n=f([0,1],function(t){return fa(e,t)&&(i[t]="auto"),null!=i[t]&&"auto"!==i[t]});pa(t,e,{type:"box",ignoreSize:n})}function Py(t){return l(qN,t)>=0}function Ny(t,e,i){function n(t,e){return l(e.nodes,t)>=0}function o(t,n){var o=!1;return e(function(e){d(i(t,e)||[],function(t){n.records[e.name][t]&&(o=!0)})}),o}function a(t,n){n.nodes.push(t),e(function(e){d(i(t,e)||[],function(t){n.records[e.name][t]=!0})})}return function(i){var r={nodes:[],records:{}};if(e(function(t){r.records[t.name]={}}),!i)return r;a(i,r);var s;do{s=!1,t(function(t){!n(t,r)&&o(t,r)&&(a(t,r),s=!0)})}while(s);return r}}function Oy(t,e,i){var n=[1/0,-1/0];return $N(i,function(t){var i=t.getData();i&&$N(i.mapDimension(e,!0),function(t){var e=i.getApproximateExtent(t);e[0]<n[0]&&(n[0]=e[0]),e[1]>n[1]&&(n[1]=e[1])})}),n[1]<n[0]&&(n=[NaN,NaN]),Ey(t,n),n}function Ey(t,e){var i=t.getAxisModel(),n=i.getMin(!0),o="category"===i.get("type"),a=o&&i.getCategories().length;null!=n&&"dataMin"!==n&&"function"!=typeof n?e[0]=n:o&&(e[0]=a>0?0:NaN);var r=i.getMax(!0);return null!=r&&"dataMax"!==r&&"function"!=typeof r?e[1]=r:o&&(e[1]=a>0?a-1:NaN),i.get("scale",!0)||(e[0]>0&&(e[0]=0),e[1]<0&&(e[1]=0)),e}function Ry(t,e){var i=t.getAxisModel(),n=t._percentWindow,o=t._valueWindow;if(n){var a=Zo(o,[0,500]);a=Math.min(a,20);var r=e||0===n[0]&&100===n[1];i.setRange(r?null:+o[0].toFixed(a),r?null:+o[1].toFixed(a))}}function zy(t){var e=t._minMaxSpan={},i=t._dataZoomModel;$N(["min","max"],function(n){e[n+"Span"]=i.get(n+"Span");var o=i.get(n+"ValueSpan");if(null!=o&&(e[n+"ValueSpan"]=o,null!=(o=t.getAxisModel().axis.scale.parse(o)))){var a=t._dataExtent;e[n+"Span"]=Bo(a[0]+o,a,[0,100],!0)}})}function By(t){var e={};return tO(["start","end","startValue","endValue","throttle"],function(i){t.hasOwnProperty(i)&&(e[i]=t[i])}),e}function Vy(t,e){var i=t._rangePropMode,n=t.get("rangeMode");tO([["start","startValue"],["end","endValue"]],function(t,o){var a=null!=e[t[0]],r=null!=e[t[1]];a&&!r?i[o]="percent":!a&&r?i[o]="value":n?i[o]=n[o]:a&&(i[o]="percent")})}function Gy(t){return{x:"y",y:"x",radius:"angle",angle:"radius"}[t]}function Fy(t){return"vertical"===t?"ns-resize":"ew-resize"}function Wy(t,e){var i=Uy(t),n=e.dataZoomId,o=e.coordId;d(i,function(t,i){var a=t.dataZoomInfos;a[n]&&l(e.allCoordIds,o)<0&&(delete a[n],t.count--)}),jy(i);var a=i[o];a||((a=i[o]={coordId:o,dataZoomInfos:{},count:0}).controller=Xy(t,a),a.dispatchAction=v(Yy,t)),!a.dataZoomInfos[n]&&a.count++,a.dataZoomInfos[n]=e;var r=qy(a.dataZoomInfos);a.controller.enable(r.controlType,r.opt),a.controller.setPointerChecker(e.containsPoint),Nr(a,"dispatchAction",e.dataZoomModel.get("throttle",!0),"fixRate")}function Hy(t,e){var i=Uy(t);d(i,function(t){t.controller.dispose();var i=t.dataZoomInfos;i[e]&&(delete i[e],t.count--)}),jy(i)}function Zy(t){return t.type+"\0_"+t.id}function Uy(t){var e=t.getZr();return e[fO]||(e[fO]={})}function Xy(t,e){var i=new oc(t.getZr());return d(["pan","zoom","scrollMove"],function(t){i.on(t,function(i){var n=[];d(e.dataZoomInfos,function(o){if(i.isAvailableBehavior(o.dataZoomModel.option)){var a=(o.getRange||{})[t],r=a&&a(e.controller,i);!o.dataZoomModel.get("disabled",!0)&&r&&n.push({dataZoomId:o.dataZoomId,start:r[0],end:r[1]})}}),n.length&&e.dispatchAction(n)})}),i}function jy(t){d(t,function(e,i){e.count||(e.controller.dispose(),delete t[i])})}function Yy(t,e){t.dispatchAction({type:"dataZoom",batch:e})}function qy(t){var e,i={type_true:2,type_move:1,type_false:0,type_undefined:-1},n=!0;return d(t,function(t){var o=t.dataZoomModel,a=!o.get("disabled",!0)&&(!o.get("zoomLock",!0)||"move");i["type_"+a]>i["type_"+e]&&(e=a),n&=o.get("preventDefaultMouseMove",!0)}),{controlType:e,opt:{zoomOnMouseWheel:!0,moveOnMouseMove:!0,moveOnMouseWheel:!0,preventDefaultMouseMove:!!n}}}function Ky(t){return function(e,i,n,o){var a=this._range,r=a.slice(),s=e.axisModels[0];if(s){var l=t(r,s,e,i,n,o);return QL(l,r,[0,100],"all"),this._range=r,a[0]!==r[0]||a[1]!==r[1]?r:void 0}}}function $y(t,e){return t&&t.hasOwnProperty&&t.hasOwnProperty(e)}function Jy(t,e,i,n){for(var o=e.targetVisuals[n],a=hL.prepareVisualTypes(o),r={color:t.getData().getVisual("color")},s=0,l=a.length;s<l;s++){var u=a[s],h=o["opacity"===u?"__alphaForOpacity":u];h&&h.applyVisual(i,function(t){return r[t]},function(t,e){r[t]=e})}return r.color}function Qy(t,e,i){if(i[0]===i[1])return i.slice();for(var n=(i[1]-i[0])/200,o=i[0],a=[],r=0;r<=200&&o<i[1];r++)a.push(o),o+=n;return a.push(i[1]),a}function tx(t,e,i){var n=t.option,o=n.align;if(null!=o&&"auto"!==o)return o;for(var a={width:e.getWidth(),height:e.getHeight()},r="horizontal"===n.orient?1:0,s=[["left","right","width"],["top","bottom","height"]],l=s[r],u=[0,null,10],h={},c=0;c<3;c++)h[s[1-r][c]]=u[c],h[l[c]]=2===c?i[0]:n[l[c]];var d=[["x","width",3],["y","height",0]][r],f=ca(h,a,n.padding);return l[(f.margin[d[2]]||0)+f[d[0]]+.5*f[d[1]]<.5*a[d[1]]?0:1]}function ex(t){return d(t||[],function(e){null!=t.dataIndex&&(t.dataIndexInside=t.dataIndex,t.dataIndex=null)}),t}function ix(t,e,i,n){return new pM({shape:{points:t},draggable:!!i,cursor:e,drift:i,onmousemove:function(t){mw(t.event)},ondragend:n})}function nx(t,e){return 0===t?[[0,0],[e,0],[e,-e]]:[[0,0],[e,0],[e,e]]}function ox(t,e,i,n){return t?[[0,-RO(e,zO(i,0))],[VO,0],[0,RO(e,zO(n-i,0))]]:[[0,0],[5,-5],[5,5]]}function ax(t,e,i){var n=BO/2,o=t.get("hoverLinkDataSize");return o&&(n=OO(o,e,i,!0)/2),n}function rx(t){var e=t.get("hoverLinkOnHandle");return!!(null==e?t.get("realtime"):e)}function sx(t){return"vertical"===t?"ns-resize":"ew-resize"}function lx(t,e){var i=t.inverse;("vertical"===t.orient?!i:i)&&e.reverse()}function ux(t){Ci(t,"label",["show"])}function hx(t){return!(isNaN(parseFloat(t.x))&&isNaN(parseFloat(t.y)))}function cx(t){return!isNaN(parseFloat(t.x))&&!isNaN(parseFloat(t.y))}function dx(t,e,i,n,o,a){var r=[],s=pl(e,n)?e.getCalculationInfo("stackResultDimension"):n,l=yx(e,s,t),u=e.indicesOfNearest(s,l)[0];r[o]=e.get(i,u),r[a]=e.get(n,u);var h=Wo(e.get(n,u));return(h=Math.min(h,20))>=0&&(r[a]=+r[a].toFixed(h)),r}function fx(t,e){var n=t.getData(),o=t.coordinateSystem;if(e&&!cx(e)&&!y(e.coord)&&o){var a=o.dimensions,r=px(e,n,o,t);if((e=i(e)).type&&YO[e.type]&&r.baseAxis&&r.valueAxis){var s=XO(a,r.baseAxis.dim),l=XO(a,r.valueAxis.dim);e.coord=YO[e.type](n,r.baseDataDim,r.valueDataDim,s,l),e.value=e.coord[l]}else{for(var u=[null!=e.xAxis?e.xAxis:e.radiusAxis,null!=e.yAxis?e.yAxis:e.angleAxis],h=0;h<2;h++)YO[u[h]]&&(u[h]=yx(n,n.mapDimension(a[h]),u[h]));e.coord=u}}return e}function px(t,e,i,n){var o={};return null!=t.valueIndex||null!=t.valueDim?(o.valueDataDim=null!=t.valueIndex?e.getDimension(t.valueIndex):t.valueDim,o.valueAxis=i.getAxis(gx(n,o.valueDataDim)),o.baseAxis=i.getOtherAxis(o.valueAxis),o.baseDataDim=e.mapDimension(o.baseAxis.dim)):(o.baseAxis=n.getBaseAxis(),o.valueAxis=i.getOtherAxis(o.baseAxis),o.baseDataDim=e.mapDimension(o.baseAxis.dim),o.valueDataDim=e.mapDimension(o.valueAxis.dim)),o}function gx(t,e){var i=t.getData(),n=i.dimensions;e=i.getDimension(e);for(var o=0;o<n.length;o++){var a=i.getDimensionInfo(n[o]);if(a.name===e)return a.coordDim}}function mx(t,e){return!(t&&t.containData&&e.coord&&!hx(e))||t.containData(e.coord)}function vx(t,e,i,n){return n<2?t.coord&&t.coord[n]:t.value}function yx(t,e,i){if("average"===i){var n=0,o=0;return t.each(e,function(t,e){isNaN(t)||(n+=t,o++)}),n/o}return"median"===i?t.getMedian(e):t.getDataExtent(e,!0)["max"===i?1:0]}function xx(t,e,i){var n=e.coordinateSystem;t.each(function(o){var a,r=t.getItemModel(o),s=Vo(r.get("x"),i.getWidth()),l=Vo(r.get("y"),i.getHeight());if(isNaN(s)||isNaN(l)){if(e.getMarkerPosition)a=e.getMarkerPosition(t.getValues(t.dimensions,o));else if(n){var u=t.get(n.dimensions[0],o),h=t.get(n.dimensions[1],o);a=n.dataToPoint([u,h])}}else a=[s,l];isNaN(s)||(a[0]=s),isNaN(l)||(a[1]=l),t.setItemLayout(o,a)})}function _x(t,e,i){var n;n=t?f(t&&t.dimensions,function(t){return r({name:t},e.getData().getDimensionInfo(e.getData().mapDimension(t))||{})}):[{name:"value",type:"float"}];var o=new vA(n,i),a=f(i.get("data"),v(fx,e));return t&&(a=g(a,v(mx,t))),o.initData(a,null,t?vx:function(t){return t.value}),o}function bx(t){return!isNaN(t)&&!isFinite(t)}function Sx(t,e,i,n){var o=1-t,a=n.dimensions[t];return bx(e[o])&&bx(i[o])&&e[t]===i[t]&&n.getAxis(a).containData(e[t])}function Mx(t,e){if("cartesian2d"===t.type){var i=e[0].coord,n=e[1].coord;if(i&&n&&(Sx(1,i,n,t)||Sx(0,i,n,t)))return!0}return mx(t,e[0])&&mx(t,e[1])}function Ix(t,e,i,n,o){var a,r=n.coordinateSystem,s=t.getItemModel(e),l=Vo(s.get("x"),o.getWidth()),u=Vo(s.get("y"),o.getHeight());if(isNaN(l)||isNaN(u)){if(n.getMarkerPosition)a=n.getMarkerPosition(t.getValues(t.dimensions,e));else{var h=r.dimensions,c=t.get(h[0],e),d=t.get(h[1],e);a=r.dataToPoint([c,d])}if("cartesian2d"===r.type){var f=r.getAxis("x"),p=r.getAxis("y"),h=r.dimensions;bx(t.get(h[0],e))?a[0]=f.toGlobalCoord(f.getExtent()[i?0:1]):bx(t.get(h[1],e))&&(a[1]=p.toGlobalCoord(p.getExtent()[i?0:1]))}isNaN(l)||(a[0]=l),isNaN(u)||(a[1]=u)}else a=[l,u];t.setItemLayout(e,a)}function Tx(t,e,i){var n;n=t?f(t&&t.dimensions,function(t){return r({name:t},e.getData().getDimensionInfo(e.getData().mapDimension(t))||{})}):[{name:"value",type:"float"}];var o=new vA(n,i),a=new vA(n,i),s=new vA([],i),l=f(i.get("data"),v(KO,e,t,i));t&&(l=g(l,v(Mx,t)));var u=t?vx:function(t){return t.value};return o.initData(f(l,function(t){return t[0]}),null,u),a.initData(f(l,function(t){return t[1]}),null,u),s.initData(f(l,function(t){return t[2]})),s.hasItemOption=!0,{from:o,to:a,line:s}}function Ax(t){return!isNaN(t)&&!isFinite(t)}function Dx(t,e,i,n){var o=1-t;return Ax(e[o])&&Ax(i[o])}function Cx(t,e){var i=e.coord[0],n=e.coord[1];return!("cartesian2d"!==t.type||!i||!n||!Dx(1,i,n,t)&&!Dx(0,i,n,t))||(mx(t,{coord:i,x:e.x0,y:e.y0})||mx(t,{coord:n,x:e.x1,y:e.y1}))}function Lx(t,e,i,n,o){var a,r=n.coordinateSystem,s=t.getItemModel(e),l=Vo(s.get(i[0]),o.getWidth()),u=Vo(s.get(i[1]),o.getHeight());if(isNaN(l)||isNaN(u)){if(n.getMarkerPosition)a=n.getMarkerPosition(t.getValues(i,e));else{var h=[f=t.get(i[0],e),p=t.get(i[1],e)];r.clampData&&r.clampData(h,h),a=r.dataToPoint(h,!0)}if("cartesian2d"===r.type){var c=r.getAxis("x"),d=r.getAxis("y"),f=t.get(i[0],e),p=t.get(i[1],e);Ax(f)?a[0]=c.toGlobalCoord(c.getExtent()["x0"===i[0]?0:1]):Ax(p)&&(a[1]=d.toGlobalCoord(d.getExtent()["y0"===i[1]?0:1]))}isNaN(l)||(a[0]=l),isNaN(u)||(a[1]=u)}else a=[l,u];return a}function kx(t,e,i){var n,o,a=["x0","y0","x1","y1"];t?(n=f(t&&t.dimensions,function(t){var i=e.getData();return r({name:t},i.getDimensionInfo(i.mapDimension(t))||{})}),o=new vA(f(a,function(t,e){return{name:t,type:n[e%2].type}}),i)):o=new vA(n=[{name:"value",type:"float"}],i);var s=f(i.get("data"),v($O,e,t,i));t&&(s=g(s,v(Cx,t)));var l=t?function(t,e,i,n){return t.coord[Math.floor(n/2)][n%2]}:function(t){return t.value};return o.initData(s,null,l),o.hasItemOption=!0,o}function Px(t){var e=t.type,i={number:"value",time:"time"};if(i[e]&&(t.axisType=i[e],delete t.type),Nx(t),Ox(t,"controlPosition")){var n=t.controlStyle||(t.controlStyle={});Ox(n,"position")||(n.position=t.controlPosition),"none"!==n.position||Ox(n,"show")||(n.show=!1,delete n.position),delete t.controlPosition}d(t.data||[],function(t){w(t)&&!y(t)&&(!Ox(t,"value")&&Ox(t,"name")&&(t.value=t.name),Nx(t))})}function Nx(t){var e=t.itemStyle||(t.itemStyle={}),i=e.emphasis||(e.emphasis={}),n=t.label||t.label||{},o=n.normal||(n.normal={}),a={normal:1,emphasis:1};d(n,function(t,e){a[e]||Ox(o,e)||(o[e]=t)}),i.label&&!Ox(n,"emphasis")&&(n.emphasis=i.label,delete i.label)}function Ox(t,e){return t.hasOwnProperty(e)}function Ex(t,e){return ca(t.getBoxLayoutParams(),{width:e.getWidth(),height:e.getHeight()},t.get("padding"))}function Rx(t,e,n,o){return Xn(t.get(e).replace(/^path:\/\//,""),i(o||{}),new de(n[0],n[1],n[2],n[3]),"center")}function zx(t,e,i,o,a,r){var s=e.get("color");a?(a.setColor(s),i.add(a),r&&r.onUpdate(a)):((a=Jl(t.get("symbol"),-1,-1,2,2,s)).setStyle("strokeNoScale",!0),i.add(a),r&&r.onCreate(a));var l=e.getItemStyle(["color","symbol","symbolSize"]);a.setStyle(l),o=n({rectHover:!0,z2:100},o,!0);var u=t.get("symbolSize");(u=u instanceof Array?u.slice():[+u,+u])[0]/=2,u[1]/=2,o.scale=u;var h=t.get("symbolOffset");if(h){var c=o.position=o.position||[0,0];c[0]+=Vo(h[0],u[0]),c[1]+=Vo(h[1],u[1])}var d=t.get("symbolRotate");return o.rotation=(d||0)*Math.PI/180||0,a.attr(o),a.updateTransform(),a}function Bx(t,e,i,n,o){if(!t.dragging){var a=n.getModel("checkpointStyle"),r=i.dataToCoord(n.getData().get(["value"],e));o||!a.get("animation",!0)?t.attr({position:[r,0]}):(t.stopAnimation(!0),t.animateTo({position:[r,0]},a.get("animationDuration",!0),a.get("animationEasing",!0)))}}function Vx(t){return 0===t.indexOf("my")}function Gx(t){this.model=t}function Fx(t){this.model=t}function Wx(t){var e={},i=[],n=[];return t.eachRawSeries(function(t){var o=t.coordinateSystem;if(!o||"cartesian2d"!==o.type&&"polar"!==o.type)i.push(t);else{var a=o.getBaseAxis();if("category"===a.type){var r=a.dim+"_"+a.index;e[r]||(e[r]={categoryAxis:a,valueAxis:o.getOtherAxis(a),series:[]},n.push({axisDim:a.dim,axisIndex:a.index})),e[r].series.push(t)}else i.push(t)}}),{seriesGroupByCategoryAxis:e,other:i,meta:n}}function Hx(t){var e=[];return d(t,function(t,i){var n=t.categoryAxis,o=t.valueAxis.dim,a=[" "].concat(f(t.series,function(t){return t.name})),r=[n.model.getCategories()];d(t.series,function(t){r.push(t.getRawData().mapArray(o,function(t){return t}))});for(var s=[a.join(fE)],l=0;l<r[0].length;l++){for(var u=[],h=0;h<r.length;h++)u.push(r[h][l]);s.push(u.join(fE))}e.push(s.join("\n"))}),e.join("\n\n"+dE+"\n\n")}function Zx(t){return f(t,function(t){var e=t.getRawData(),i=[t.name],n=[];return e.each(e.dimensions,function(){for(var t=arguments.length,o=arguments[t-1],a=e.getName(o),r=0;r<t-1;r++)n[r]=arguments[r];i.push((a?a+fE:"")+n.join(fE))}),i.join("\n")}).join("\n\n"+dE+"\n\n")}function Ux(t){var e=Wx(t);return{value:g([Hx(e.seriesGroupByCategoryAxis),Zx(e.other)],function(t){return t.replace(/[\n\t\s]/g,"")}).join("\n\n"+dE+"\n\n"),meta:e.meta}}function Xx(t){return t.replace(/^\s\s*/,"").replace(/\s\s*$/,"")}function jx(t){if(t.slice(0,t.indexOf("\n")).indexOf(fE)>=0)return!0}function Yx(t){for(var e=t.split(/\n+/g),i=[],n=f(Xx(e.shift()).split(pE),function(t){return{name:t,data:[]}}),o=0;o<e.length;o++){var a=Xx(e[o]).split(pE);i.push(a.shift());for(var r=0;r<a.length;r++)n[r]&&(n[r].data[o]=a[r])}return{series:n,categories:i}}function qx(t){for(var e=t.split(/\n+/g),i=Xx(e.shift()),n=[],o=0;o<e.length;o++){var a,r=Xx(e[o]).split(pE),s="",l=!1;isNaN(r[0])?(l=!0,s=r[0],r=r.slice(1),n[o]={name:s,value:[]},a=n[o].value):a=n[o]=[];for(var u=0;u<r.length;u++)a.push(+r[u]);1===a.length&&(l?n[o].value=a[0]:n[o]=a[0])}return{name:i,data:n}}function Kx(t,e){var i={series:[]};return d(t.split(new RegExp("\n*"+dE+"\n*","g")),function(t,n){if(jx(t)){var o=Yx(t),a=e[n],r=a.axisDim+"Axis";a&&(i[r]=i[r]||[],i[r][a.axisIndex]={data:o.categories},i.series=i.series.concat(o.series))}else{o=qx(t);i.series.push(o)}}),i}function $x(t){this._dom=null,this.model=t}function Jx(t,e){return f(t,function(t,i){var n=e&&e[i];return w(n)&&!y(n)?(w(t)&&!y(t)&&(t=t.value),r({value:t},n)):t})}function Qx(t,e){var i=n_(t);gE(e,function(e,n){for(var o=i.length-1;o>=0&&!i[o][n];o--);if(o<0){var a=t.queryComponents({mainType:"dataZoom",subType:"select",id:n})[0];if(a){var r=a.getPercentRange();i[0][n]={dataZoomId:n,start:r[0],end:r[1]}}}}),i.push(e)}function t_(t){var e=n_(t),i=e[e.length-1];e.length>1&&e.pop();var n={};return gE(i,function(t,i){for(var o=e.length-1;o>=0;o--)if(t=e[o][i]){n[i]=t;break}}),n}function e_(t){t[mE]=null}function i_(t){return n_(t).length}function n_(t){var e=t[mE];return e||(e=t[mE]=[{}]),e}function o_(t,e,i){(this._brushController=new zf(i.getZr())).on("brush",m(this._onBrush,this)).mount(),this._isZoomActive}function a_(t){var e={};return d(["xAxisIndex","yAxisIndex"],function(i){e[i]=t[i],null==e[i]&&(e[i]="all"),(!1===e[i]||"none"===e[i])&&(e[i]=[])}),e}function r_(t,e){t.setIconStatus("back",i_(e)>1?"emphasis":"normal")}function s_(t,e,i,n,o){var a=i._isZoomActive;n&&"takeGlobalCursor"===n.type&&(a="dataZoomSelect"===n.key&&n.dataZoomSelectActive),i._isZoomActive=a,t.setIconStatus("zoom",a?"emphasis":"normal");var r=new hy(a_(t.option),e,{include:["grid"]});i._brushController.setPanels(r.makePanelOpts(o,function(t){return t.xAxisDeclared&&!t.yAxisDeclared?"lineX":!t.xAxisDeclared&&t.yAxisDeclared?"lineY":"rect"})).enableBrush(!!a&&{brushType:"auto",brushStyle:{lineWidth:0,fill:"rgba(0,0,0,0.2)"}})}function l_(t){this.model=t}function u_(t){return SE(t)}function h_(){if(!TE&&AE){TE=!0;var t=AE.styleSheets;t.length<31?AE.createStyleSheet().addRule(".zrvml","behavior:url(#default#VML)"):t[0].addRule(".zrvml","behavior:url(#default#VML)")}}function c_(t){return parseInt(t,10)}function d_(t,e){h_(),this.root=t,this.storage=e;var i=document.createElement("div"),n=document.createElement("div");i.style.cssText="display:inline-block;overflow:hidden;position:relative;width:300px;height:150px;",n.style.cssText="position:absolute;left:0;top:0;",t.appendChild(i),this._vmlRoot=n,this._vmlViewport=i,this.resize();var o=e.delFromStorage,a=e.addToStorage;e.delFromStorage=function(t){o.call(e,t),t&&t.onRemove&&t.onRemove(n)},e.addToStorage=function(t){t.onAdd&&t.onAdd(n),a.call(e,t)},this._firstPaint=!0}function f_(t){return function(){Yw('In IE8.0 VML mode painter not support method "'+t+'"')}}function p_(t){return document.createElementNS(sR,t)}function g_(t){return cR(1e4*t)/1e4}function m_(t){return t<vR&&t>-vR}function v_(t,e){var i=e?t.textFill:t.fill;return null!=i&&i!==hR}function y_(t,e){var i=e?t.textStroke:t.stroke;return null!=i&&i!==hR}function x_(t,e){e&&__(t,"transform","matrix("+uR.call(e,",")+")")}function __(t,e,i){(!i||"linear"!==i.type&&"radial"!==i.type)&&t.setAttribute(e,i)}function w_(t,e,i){t.setAttributeNS("http://www.w3.org/1999/xlink",e,i)}function b_(t,e,i,n){if(v_(e,i)){var o=i?e.textFill:e.fill;o="transparent"===o?hR:o,"none"!==t.getAttribute("clip-path")&&o===hR&&(o="rgba(0, 0, 0, 0.002)"),__(t,"fill",o),__(t,"fill-opacity",null!=e.fillOpacity?e.fillOpacity*e.opacity:e.opacity)}else __(t,"fill",hR);if(y_(e,i)){var a=i?e.textStroke:e.stroke;__(t,"stroke",a="transparent"===a?hR:a),__(t,"stroke-width",(i?e.textStrokeWidth:e.lineWidth)/(!i&&e.strokeNoScale?n.getLineScale():1)),__(t,"paint-order",i?"stroke":"fill"),__(t,"stroke-opacity",null!=e.strokeOpacity?e.strokeOpacity:e.opacity),e.lineDash?(__(t,"stroke-dasharray",e.lineDash.join(",")),__(t,"stroke-dashoffset",cR(e.lineDashOffset||0))):__(t,"stroke-dasharray",""),e.lineCap&&__(t,"stroke-linecap",e.lineCap),e.lineJoin&&__(t,"stroke-linejoin",e.lineJoin),e.miterLimit&&__(t,"stroke-miterlimit",e.miterLimit)}else __(t,"stroke",hR)}function S_(t){for(var e=[],i=t.data,n=t.len(),o=0;o<n;){var a="",r=0;switch(i[o++]){case lR.M:a="M",r=2;break;case lR.L:a="L",r=2;break;case lR.Q:a="Q",r=4;break;case lR.C:a="C",r=6;break;case lR.A:var s=i[o++],l=i[o++],u=i[o++],h=i[o++],c=i[o++],d=i[o++],f=i[o++],p=i[o++],g=Math.abs(d),m=m_(g-gR)&&!m_(g),v=!1;v=g>=gR||!m_(g)&&(d>-pR&&d<0||d>pR)==!!p;var y=g_(s+u*fR(c)),x=g_(l+h*dR(c));m&&(d=p?gR-1e-4:1e-4-gR,v=!0,9===o&&e.push("M",y,x));var _=g_(s+u*fR(c+d)),w=g_(l+h*dR(c+d));e.push("A",g_(u),g_(h),cR(f*mR),+v,+p,_,w);break;case lR.Z:a="Z";break;case lR.R:var _=g_(i[o++]),w=g_(i[o++]),b=g_(i[o++]),S=g_(i[o++]);e.push("M",_,w,"L",_+b,w,"L",_+b,w+S,"L",_,w+S,"L",_,w)}a&&e.push(a);for(var M=0;M<r;M++)e.push(g_(i[o++]))}return e.join(" ")}function M_(t){return"middle"===t?"middle":"bottom"===t?"after-edge":"hanging"}function I_(){}function T_(t,e,i,n){for(var o=0,a=e.length,r=0,s=0;o<a;o++){var l=e[o];if(l.removed){for(var u=[],h=s;h<s+l.count;h++)u.push(h);l.indices=u,s+=l.count}else{for(var u=[],h=r;h<r+l.count;h++)u.push(h);l.indices=u,r+=l.count,l.added||(s+=l.count)}}return e}function A_(t){return{newPos:t.newPos,components:t.components.slice(0)}}function D_(t,e,i,n,o){this._zrId=t,this._svgRoot=e,this._tagNames="string"==typeof i?[i]:i,this._markLabel=n,this._domName=o||"_dom",this.nextId=0}function C_(t,e){D_.call(this,t,e,["linearGradient","radialGradient"],"__gradient_in_use__")}function L_(t,e){D_.call(this,t,e,"clipPath","__clippath_in_use__")}function k_(t,e){D_.call(this,t,e,["filter"],"__filter_in_use__","_shadowDom")}function P_(t){return t&&(t.shadowBlur||t.shadowOffsetX||t.shadowOffsetY||t.textShadowBlur||t.textShadowOffsetX||t.textShadowOffsetY)}function N_(t){return parseInt(t,10)}function O_(t){return t instanceof Pn?yR:t instanceof fi?xR:t instanceof rM?_R:yR}function E_(t,e){return e&&t&&e.parentNode!==t}function R_(t,e,i){if(E_(t,e)&&i){var n=i.nextSibling;n?t.insertBefore(e,n):t.appendChild(e)}}function z_(t,e){if(E_(t,e)){var i=t.firstChild;i?t.insertBefore(e,i):t.appendChild(e)}}function B_(t,e){e&&t&&e.parentNode===t&&t.removeChild(e)}function V_(t){return t.__textSvgEl}function G_(t){return t.__svgEl}function F_(t){return function(){Yw('In SVG mode painter not support method "'+t+'"')}}var W_=2311,H_=function(){return W_++},Z_={},U_=Z_="object"==typeof wx&&"function"==typeof wx.getSystemInfoSync?{browser:{},os:{},node:!1,wxa:!0,canvasSupported:!0,svgSupported:!1,touchEventsSupported:!0,domSupported:!1}:"undefined"==typeof document&&"undefined"!=typeof self?{browser:{},os:{},node:!1,worker:!0,canvasSupported:!0,domSupported:!1}:"undefined"==typeof navigator?{browser:{},os:{},node:!0,worker:!1,canvasSupported:!0,svgSupported:!0,domSupported:!1}:function(t){var e={},i={},n=t.match(/Firefox\/([\d.]+)/),o=t.match(/MSIE\s([\d.]+)/)||t.match(/Trident\/.+?rv:(([\d.]+))/),a=t.match(/Edge\/([\d.]+)/),r=/micromessenger/i.test(t);return n&&(i.firefox=!0,i.version=n[1]),o&&(i.ie=!0,i.version=o[1]),a&&(i.edge=!0,i.version=a[1]),r&&(i.weChat=!0),{browser:i,os:e,node:!1,canvasSupported:!!document.createElement("canvas").getContext,svgSupported:"undefined"!=typeof SVGRect,touchEventsSupported:"ontouchstart"in window&&!i.ie&&!i.edge,pointerEventsSupported:"onpointerdown"in window&&(i.edge||i.ie&&i.version>=11),domSupported:"undefined"!=typeof document}}(navigator.userAgent),X_={"[object Function]":1,"[object RegExp]":1,"[object Date]":1,"[object Error]":1,"[object CanvasGradient]":1,"[object CanvasPattern]":1,"[object Image]":1,"[object Canvas]":1},j_={"[object Int8Array]":1,"[object Uint8Array]":1,"[object Uint8ClampedArray]":1,"[object Int16Array]":1,"[object Uint16Array]":1,"[object Int32Array]":1,"[object Uint32Array]":1,"[object Float32Array]":1,"[object Float64Array]":1},Y_=Object.prototype.toString,q_=Array.prototype,K_=q_.forEach,$_=q_.filter,J_=q_.slice,Q_=q_.map,tw=q_.reduce,ew={},iw=function(){return ew.createCanvas()};ew.createCanvas=function(){return document.createElement("canvas")};var nw,ow="__ec_primitive__";E.prototype={constructor:E,get:function(t){return this.data.hasOwnProperty(t)?this.data[t]:null},set:function(t,e){return this.data[t]=e},each:function(t,e){void 0!==e&&(t=m(t,e));for(var i in this.data)this.data.hasOwnProperty(i)&&t(this.data[i],i)},removeKey:function(t){delete this.data[t]}};var aw=(Object.freeze||Object)({$override:e,clone:i,merge:n,mergeAll:o,extend:a,defaults:r,createCanvas:iw,getContext:s,indexOf:l,inherits:u,mixin:h,isArrayLike:c,each:d,map:f,reduce:p,filter:g,find:function(t,e,i){if(t&&e)for(var n=0,o=t.length;n<o;n++)if(e.call(i,t[n],n,t))return t[n]},bind:m,curry:v,isArray:y,isFunction:x,isString:_,isObject:w,isBuiltInObject:b,isTypedArray:S,isDom:M,eqNaN:I,retrieve:T,retrieve2:A,retrieve3:D,slice:C,normalizeCssArray:L,assert:k,trim:P,setAsPrimitive:N,isPrimitive:O,createHashMap:R,concatArray:z,noop:B}),rw="undefined"==typeof Float32Array?Array:Float32Array,sw=X,lw=j,uw=K,hw=$,cw=(Object.freeze||Object)({create:V,copy:G,clone:F,set:W,add:H,scaleAndAdd:Z,sub:U,len:X,length:sw,lenSquare:j,lengthSquare:lw,mul:function(t,e,i){return t[0]=e[0]*i[0],t[1]=e[1]*i[1],t},div:function(t,e,i){return t[0]=e[0]/i[0],t[1]=e[1]/i[1],t},dot:function(t,e){return t[0]*e[0]+t[1]*e[1]},scale:Y,normalize:q,distance:K,dist:uw,distanceSquare:$,distSquare:hw,negate:function(t,e){return t[0]=-e[0],t[1]=-e[1],t},lerp:J,applyTransform:Q,min:tt,max:et});it.prototype={constructor:it,_dragStart:function(t){var e=t.target;e&&e.draggable&&(this._draggingTarget=e,e.dragging=!0,this._x=t.offsetX,this._y=t.offsetY,this.dispatchToElement(nt(e,t),"dragstart",t.event))},_drag:function(t){var e=this._draggingTarget;if(e){var i=t.offsetX,n=t.offsetY,o=i-this._x,a=n-this._y;this._x=i,this._y=n,e.drift(o,a,t),this.dispatchToElement(nt(e,t),"drag",t.event);var r=this.findHover(i,n,e).target,s=this._dropTarget;this._dropTarget=r,e!==r&&(s&&r!==s&&this.dispatchToElement(nt(s,t),"dragleave",t.event),r&&r!==s&&this.dispatchToElement(nt(r,t),"dragenter",t.event))}},_dragEnd:function(t){var e=this._draggingTarget;e&&(e.dragging=!1),this.dispatchToElement(nt(e,t),"dragend",t.event),this._dropTarget&&this.dispatchToElement(nt(this._dropTarget,t),"drop",t.event),this._draggingTarget=null,this._dropTarget=null}};var dw=Array.prototype.slice,fw=function(t){this._$handlers={},this._$eventProcessor=t};fw.prototype={constructor:fw,one:function(t,e,i,n){return at(this,t,e,i,n,!0)},on:function(t,e,i,n){return at(this,t,e,i,n,!1)},isSilent:function(t){var e=this._$handlers;return!e[t]||!e[t].length},off:function(t,e){var i=this._$handlers;if(!t)return this._$handlers={},this;if(e){if(i[t]){for(var n=[],o=0,a=i[t].length;o<a;o++)i[t][o].h!==e&&n.push(i[t][o]);i[t]=n}i[t]&&0===i[t].length&&delete i[t]}else delete i[t];return this},trigger:function(t){var e=this._$handlers[t],i=this._$eventProcessor;if(e){var n=arguments,o=n.length;o>3&&(n=dw.call(n,1));for(var a=e.length,r=0;r<a;){var s=e[r];if(i&&i.filter&&null!=s.query&&!i.filter(t,s.query))r++;else{switch(o){case 1:s.h.call(s.ctx);break;case 2:s.h.call(s.ctx,n[1]);break;case 3:s.h.call(s.ctx,n[1],n[2]);break;default:s.h.apply(s.ctx,n)}s.one?(e.splice(r,1),a--):r++}}}return i&&i.afterTrigger&&i.afterTrigger(t),this},triggerWithContext:function(t){var e=this._$handlers[t],i=this._$eventProcessor;if(e){var n=arguments,o=n.length;o>4&&(n=dw.call(n,1,n.length-1));for(var a=n[n.length-1],r=e.length,s=0;s<r;){var l=e[s];if(i&&i.filter&&null!=l.query&&!i.filter(t,l.query))s++;else{switch(o){case 1:l.h.call(a);break;case 2:l.h.call(a,n[1]);break;case 3:l.h.call(a,n[1],n[2]);break;default:l.h.apply(a,n)}l.one?(e.splice(s,1),r--):s++}}}return i&&i.afterTrigger&&i.afterTrigger(t),this}};var pw="undefined"!=typeof window&&!!window.addEventListener,gw=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,mw=pw?function(t){t.preventDefault(),t.stopPropagation(),t.cancelBubble=!0}:function(t){t.returnValue=!1,t.cancelBubble=!0},vw=function(){this._track=[]};vw.prototype={constructor:vw,recognize:function(t,e,i){return this._doTrack(t,e,i),this._recognize(t)},clear:function(){return this._track.length=0,this},_doTrack:function(t,e,i){var n=t.touches;if(n){for(var o={points:[],touches:[],target:e,event:t},a=0,r=n.length;a<r;a++){var s=n[a],l=st(i,s,{});o.points.push([l.zrX,l.zrY]),o.touches.push(s)}this._track.push(o)}},_recognize:function(t){for(var e in yw)if(yw.hasOwnProperty(e)){var i=yw[e](this._track,t);if(i)return i}}};var yw={pinch:function(t,e){var i=t.length;if(i){var n=(t[i-1]||{}).points,o=(t[i-2]||{}).points||n;if(o&&o.length>1&&n&&n.length>1){var a=ft(n)/ft(o);!isFinite(a)&&(a=1),e.pinchScale=a;var r=pt(n);return e.pinchX=r[0],e.pinchY=r[1],{type:"pinch",target:t[0].target,event:e}}}}},xw="silent";vt.prototype.dispose=function(){};var _w=["click","dblclick","mousewheel","mouseout","mouseup","mousedown","mousemove","contextmenu"],ww=function(t,e,i,n){fw.call(this),this.storage=t,this.painter=e,this.painterRoot=n,i=i||new vt,this.proxy=null,this._hovered={},this._lastTouchMoment,this._lastX,this._lastY,this._gestureMgr,it.call(this),this.setHandlerProxy(i)};ww.prototype={constructor:ww,setHandlerProxy:function(t){this.proxy&&this.proxy.dispose(),t&&(d(_w,function(e){t.on&&t.on(e,this[e],this)},this),t.handler=this),this.proxy=t},mousemove:function(t){var e=t.zrX,i=t.zrY,n=this._hovered,o=n.target;o&&!o.__zr&&(o=(n=this.findHover(n.x,n.y)).target);var a=this._hovered=this.findHover(e,i),r=a.target,s=this.proxy;s.setCursor&&s.setCursor(r?r.cursor:"default"),o&&r!==o&&this.dispatchToElement(n,"mouseout",t),this.dispatchToElement(a,"mousemove",t),r&&r!==o&&this.dispatchToElement(a,"mouseover",t)},mouseout:function(t){this.dispatchToElement(this._hovered,"mouseout",t);var e,i=t.toElement||t.relatedTarget;do{i=i&&i.parentNode}while(i&&9!==i.nodeType&&!(e=i===this.painterRoot));!e&&this.trigger("globalout",{event:t})},resize:function(t){this._hovered={}},dispatch:function(t,e){var i=this[t];i&&i.call(this,e)},dispose:function(){this.proxy.dispose(),this.storage=this.proxy=this.painter=null},setCursorStyle:function(t){var e=this.proxy;e.setCursor&&e.setCursor(t)},dispatchToElement:function(t,e,i){var n=(t=t||{}).target;if(!n||!n.silent){for(var o="on"+e,a=gt(e,t,i);n&&(n[o]&&(a.cancelBubble=n[o].call(n,a)),n.trigger(e,a),n=n.parent,!a.cancelBubble););a.cancelBubble||(this.trigger(e,a),this.painter&&this.painter.eachOtherLayer(function(t){"function"==typeof t[o]&&t[o].call(t,a),t.trigger&&t.trigger(e,a)}))}},findHover:function(t,e,i){for(var n=this.storage.getDisplayList(),o={x:t,y:e},a=n.length-1;a>=0;a--){var r;if(n[a]!==i&&!n[a].ignore&&(r=yt(n[a],t,e))&&(!o.topTarget&&(o.topTarget=n[a]),r!==xw)){o.target=n[a];break}}return o},processGesture:function(t,e){this._gestureMgr||(this._gestureMgr=new vw);var i=this._gestureMgr;"start"===e&&i.clear();var n=i.recognize(t,this.findHover(t.zrX,t.zrY,null).target,this.proxy.dom);if("end"===e&&i.clear(),n){var o=n.type;t.gestureEvent=o,this.dispatchToElement({target:n.target},o,n.event)}}},d(["click","mousedown","mouseup","mousewheel","dblclick","contextmenu"],function(t){ww.prototype[t]=function(e){var i=this.findHover(e.zrX,e.zrY),n=i.target;if("mousedown"===t)this._downEl=n,this._downPoint=[e.zrX,e.zrY],this._upEl=n;else if("mouseup"===t)this._upEl=n;else if("click"===t){if(this._downEl!==this._upEl||!this._downPoint||uw(this._downPoint,[e.zrX,e.zrY])>4)return;this._downPoint=null}this.dispatchToElement(i,t,e)}}),h(ww,fw),h(ww,it);var bw="undefined"==typeof Float32Array?Array:Float32Array,Sw=(Object.freeze||Object)({create:xt,identity:_t,copy:wt,mul:bt,translate:St,rotate:Mt,scale:It,invert:Tt,clone:At}),Mw=_t,Iw=5e-5,Tw=function(t){(t=t||{}).position||(this.position=[0,0]),null==t.rotation&&(this.rotation=0),t.scale||(this.scale=[1,1]),this.origin=this.origin||null},Aw=Tw.prototype;Aw.transform=null,Aw.needLocalTransform=function(){return Dt(this.rotation)||Dt(this.position[0])||Dt(this.position[1])||Dt(this.scale[0]-1)||Dt(this.scale[1]-1)};var Dw=[];Aw.updateTransform=function(){var t=this.parent,e=t&&t.transform,i=this.needLocalTransform(),n=this.transform;if(i||e){n=n||xt(),i?this.getLocalTransform(n):Mw(n),e&&(i?bt(n,t.transform,n):wt(n,t.transform)),this.transform=n;var o=this.globalScaleRatio;if(null!=o&&1!==o){this.getGlobalScale(Dw);var a=Dw[0]<0?-1:1,r=Dw[1]<0?-1:1,s=((Dw[0]-a)*o+a)/Dw[0]||0,l=((Dw[1]-r)*o+r)/Dw[1]||0;n[0]*=s,n[1]*=s,n[2]*=l,n[3]*=l}this.invTransform=this.invTransform||xt(),Tt(this.invTransform,n)}else n&&Mw(n)},Aw.getLocalTransform=function(t){return Tw.getLocalTransform(this,t)},Aw.setTransform=function(t){var e=this.transform,i=t.dpr||1;e?t.setTransform(i*e[0],i*e[1],i*e[2],i*e[3],i*e[4],i*e[5]):t.setTransform(i,0,0,i,0,0)},Aw.restoreTransform=function(t){var e=t.dpr||1;t.setTransform(e,0,0,e,0,0)};var Cw=[],Lw=xt();Aw.setLocalTransform=function(t){if(t){var e=t[0]*t[0]+t[1]*t[1],i=t[2]*t[2]+t[3]*t[3],n=this.position,o=this.scale;Dt(e-1)&&(e=Math.sqrt(e)),Dt(i-1)&&(i=Math.sqrt(i)),t[0]<0&&(e=-e),t[3]<0&&(i=-i),n[0]=t[4],n[1]=t[5],o[0]=e,o[1]=i,this.rotation=Math.atan2(-t[1]/i,t[0]/e)}},Aw.decomposeTransform=function(){if(this.transform){var t=this.parent,e=this.transform;t&&t.transform&&(bt(Cw,t.invTransform,e),e=Cw);var i=this.origin;i&&(i[0]||i[1])&&(Lw[4]=i[0],Lw[5]=i[1],bt(Cw,e,Lw),Cw[4]-=i[0],Cw[5]-=i[1],e=Cw),this.setLocalTransform(e)}},Aw.getGlobalScale=function(t){var e=this.transform;return t=t||[],e?(t[0]=Math.sqrt(e[0]*e[0]+e[1]*e[1]),t[1]=Math.sqrt(e[2]*e[2]+e[3]*e[3]),e[0]<0&&(t[0]=-t[0]),e[3]<0&&(t[1]=-t[1]),t):(t[0]=1,t[1]=1,t)},Aw.transformCoordToLocal=function(t,e){var i=[t,e],n=this.invTransform;return n&&Q(i,i,n),i},Aw.transformCoordToGlobal=function(t,e){var i=[t,e],n=this.transform;return n&&Q(i,i,n),i},Tw.getLocalTransform=function(t,e){Mw(e=e||[]);var i=t.origin,n=t.scale||[1,1],o=t.rotation||0,a=t.position||[0,0];return i&&(e[4]-=i[0],e[5]-=i[1]),It(e,e,n),o&&Mt(e,e,o),i&&(e[4]+=i[0],e[5]+=i[1]),e[4]+=a[0],e[5]+=a[1],e};var kw={linear:function(t){return t},quadraticIn:function(t){return t*t},quadraticOut:function(t){return t*(2-t)},quadraticInOut:function(t){return(t*=2)<1?.5*t*t:-.5*(--t*(t-2)-1)},cubicIn:function(t){return t*t*t},cubicOut:function(t){return--t*t*t+1},cubicInOut:function(t){return(t*=2)<1?.5*t*t*t:.5*((t-=2)*t*t+2)},quarticIn:function(t){return t*t*t*t},quarticOut:function(t){return 1- --t*t*t*t},quarticInOut:function(t){return(t*=2)<1?.5*t*t*t*t:-.5*((t-=2)*t*t*t-2)},quinticIn:function(t){return t*t*t*t*t},quinticOut:function(t){return--t*t*t*t*t+1},quinticInOut:function(t){return(t*=2)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2)},sinusoidalIn:function(t){return 1-Math.cos(t*Math.PI/2)},sinusoidalOut:function(t){return Math.sin(t*Math.PI/2)},sinusoidalInOut:function(t){return.5*(1-Math.cos(Math.PI*t))},exponentialIn:function(t){return 0===t?0:Math.pow(1024,t-1)},exponentialOut:function(t){return 1===t?1:1-Math.pow(2,-10*t)},exponentialInOut:function(t){return 0===t?0:1===t?1:(t*=2)<1?.5*Math.pow(1024,t-1):.5*(2-Math.pow(2,-10*(t-1)))},circularIn:function(t){return 1-Math.sqrt(1-t*t)},circularOut:function(t){return Math.sqrt(1- --t*t)},circularInOut:function(t){return(t*=2)<1?-.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},elasticIn:function(t){var e,i=.1;return 0===t?0:1===t?1:(!i||i<1?(i=1,e=.1):e=.4*Math.asin(1/i)/(2*Math.PI),-i*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/.4))},elasticOut:function(t){var e,i=.1;return 0===t?0:1===t?1:(!i||i<1?(i=1,e=.1):e=.4*Math.asin(1/i)/(2*Math.PI),i*Math.pow(2,-10*t)*Math.sin((t-e)*(2*Math.PI)/.4)+1)},elasticInOut:function(t){var e,i=.1;return 0===t?0:1===t?1:(!i||i<1?(i=1,e=.1):e=.4*Math.asin(1/i)/(2*Math.PI),(t*=2)<1?i*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/.4)*-.5:i*Math.pow(2,-10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/.4)*.5+1)},backIn:function(t){var e=1.70158;return t*t*((e+1)*t-e)},backOut:function(t){var e=1.70158;return--t*t*((e+1)*t+e)+1},backInOut:function(t){var e=2.5949095;return(t*=2)<1?t*t*((e+1)*t-e)*.5:.5*((t-=2)*t*((e+1)*t+e)+2)},bounceIn:function(t){return 1-kw.bounceOut(1-t)},bounceOut:function(t){return t<1/2.75?7.5625*t*t:t<2/2.75?7.5625*(t-=1.5/2.75)*t+.75:t<2.5/2.75?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375},bounceInOut:function(t){return t<.5?.5*kw.bounceIn(2*t):.5*kw.bounceOut(2*t-1)+.5}};Ct.prototype={constructor:Ct,step:function(t,e){if(this._initialized||(this._startTime=t+this._delay,this._initialized=!0),this._paused)this._pausedTime+=e;else{var i=(t-this._startTime-this._pausedTime)/this._life;if(!(i<0)){i=Math.min(i,1);var n=this.easing,o="string"==typeof n?kw[n]:n,a="function"==typeof o?o(i):i;return this.fire("frame",a),1===i?this.loop?(this.restart(t),"restart"):(this._needsRemove=!0,"destroy"):null}}},restart:function(t){var e=(t-this._startTime-this._pausedTime)%this._life;this._startTime=t-e+this.gap,this._pausedTime=0,this._needsRemove=!1},fire:function(t,e){this[t="on"+t]&&this[t](this._target,e)},pause:function(){this._paused=!0},resume:function(){this._paused=!1}};var Pw=function(){this.head=null,this.tail=null,this._len=0},Nw=Pw.prototype;Nw.insert=function(t){var e=new Ow(t);return this.insertEntry(e),e},Nw.insertEntry=function(t){this.head?(this.tail.next=t,t.prev=this.tail,t.next=null,this.tail=t):this.head=this.tail=t,this._len++},Nw.remove=function(t){var e=t.prev,i=t.next;e?e.next=i:this.head=i,i?i.prev=e:this.tail=e,t.next=t.prev=null,this._len--},Nw.len=function(){return this._len},Nw.clear=function(){this.head=this.tail=null,this._len=0};var Ow=function(t){this.value=t,this.next,this.prev},Ew=function(t){this._list=new Pw,this._map={},this._maxSize=t||10,this._lastRemovedEntry=null},Rw=Ew.prototype;Rw.put=function(t,e){var i=this._list,n=this._map,o=null;if(null==n[t]){var a=i.len(),r=this._lastRemovedEntry;if(a>=this._maxSize&&a>0){var s=i.head;i.remove(s),delete n[s.key],o=s.value,this._lastRemovedEntry=s}r?r.value=e:r=new Ow(e),r.key=t,i.insertEntry(r),n[t]=r}return o},Rw.get=function(t){var e=this._map[t],i=this._list;if(null!=e)return e!==i.tail&&(i.remove(e),i.insertEntry(e)),e.value},Rw.clear=function(){this._list.clear(),this._map={}};var zw={transparent:[0,0,0,0],aliceblue:[240,248,255,1],antiquewhite:[250,235,215,1],aqua:[0,255,255,1],aquamarine:[127,255,212,1],azure:[240,255,255,1],beige:[245,245,220,1],bisque:[255,228,196,1],black:[0,0,0,1],blanchedalmond:[255,235,205,1],blue:[0,0,255,1],blueviolet:[138,43,226,1],brown:[165,42,42,1],burlywood:[222,184,135,1],cadetblue:[95,158,160,1],chartreuse:[127,255,0,1],chocolate:[210,105,30,1],coral:[255,127,80,1],cornflowerblue:[100,149,237,1],cornsilk:[255,248,220,1],crimson:[220,20,60,1],cyan:[0,255,255,1],darkblue:[0,0,139,1],darkcyan:[0,139,139,1],darkgoldenrod:[184,134,11,1],darkgray:[169,169,169,1],darkgreen:[0,100,0,1],darkgrey:[169,169,169,1],darkkhaki:[189,183,107,1],darkmagenta:[139,0,139,1],darkolivegreen:[85,107,47,1],darkorange:[255,140,0,1],darkorchid:[153,50,204,1],darkred:[139,0,0,1],darksalmon:[233,150,122,1],darkseagreen:[143,188,143,1],darkslateblue:[72,61,139,1],darkslategray:[47,79,79,1],darkslategrey:[47,79,79,1],darkturquoise:[0,206,209,1],darkviolet:[148,0,211,1],deeppink:[255,20,147,1],deepskyblue:[0,191,255,1],dimgray:[105,105,105,1],dimgrey:[105,105,105,1],dodgerblue:[30,144,255,1],firebrick:[178,34,34,1],floralwhite:[255,250,240,1],forestgreen:[34,139,34,1],fuchsia:[255,0,255,1],gainsboro:[220,220,220,1],ghostwhite:[248,248,255,1],gold:[255,215,0,1],goldenrod:[218,165,32,1],gray:[128,128,128,1],green:[0,128,0,1],greenyellow:[173,255,47,1],grey:[128,128,128,1],honeydew:[240,255,240,1],hotpink:[255,105,180,1],indianred:[205,92,92,1],indigo:[75,0,130,1],ivory:[255,255,240,1],khaki:[240,230,140,1],lavender:[230,230,250,1],lavenderblush:[255,240,245,1],lawngreen:[124,252,0,1],lemonchiffon:[255,250,205,1],lightblue:[173,216,230,1],lightcoral:[240,128,128,1],lightcyan:[224,255,255,1],lightgoldenrodyellow:[250,250,210,1],lightgray:[211,211,211,1],lightgreen:[144,238,144,1],lightgrey:[211,211,211,1],lightpink:[255,182,193,1],lightsalmon:[255,160,122,1],lightseagreen:[32,178,170,1],lightskyblue:[135,206,250,1],lightslategray:[119,136,153,1],lightslategrey:[119,136,153,1],lightsteelblue:[176,196,222,1],lightyellow:[255,255,224,1],lime:[0,255,0,1],limegreen:[50,205,50,1],linen:[250,240,230,1],magenta:[255,0,255,1],maroon:[128,0,0,1],mediumaquamarine:[102,205,170,1],mediumblue:[0,0,205,1],mediumorchid:[186,85,211,1],mediumpurple:[147,112,219,1],mediumseagreen:[60,179,113,1],mediumslateblue:[123,104,238,1],mediumspringgreen:[0,250,154,1],mediumturquoise:[72,209,204,1],mediumvioletred:[199,21,133,1],midnightblue:[25,25,112,1],mintcream:[245,255,250,1],mistyrose:[255,228,225,1],moccasin:[255,228,181,1],navajowhite:[255,222,173,1],navy:[0,0,128,1],oldlace:[253,245,230,1],olive:[128,128,0,1],olivedrab:[107,142,35,1],orange:[255,165,0,1],orangered:[255,69,0,1],orchid:[218,112,214,1],palegoldenrod:[238,232,170,1],palegreen:[152,251,152,1],paleturquoise:[175,238,238,1],palevioletred:[219,112,147,1],papayawhip:[255,239,213,1],peachpuff:[255,218,185,1],peru:[205,133,63,1],pink:[255,192,203,1],plum:[221,160,221,1],powderblue:[176,224,230,1],purple:[128,0,128,1],red:[255,0,0,1],rosybrown:[188,143,143,1],royalblue:[65,105,225,1],saddlebrown:[139,69,19,1],salmon:[250,128,114,1],sandybrown:[244,164,96,1],seagreen:[46,139,87,1],seashell:[255,245,238,1],sienna:[160,82,45,1],silver:[192,192,192,1],skyblue:[135,206,235,1],slateblue:[106,90,205,1],slategray:[112,128,144,1],slategrey:[112,128,144,1],snow:[255,250,250,1],springgreen:[0,255,127,1],steelblue:[70,130,180,1],tan:[210,180,140,1],teal:[0,128,128,1],thistle:[216,191,216,1],tomato:[255,99,71,1],turquoise:[64,224,208,1],violet:[238,130,238,1],wheat:[245,222,179,1],white:[255,255,255,1],whitesmoke:[245,245,245,1],yellow:[255,255,0,1],yellowgreen:[154,205,50,1]},Bw=new Ew(20),Vw=null,Gw=Ut,Fw=Xt,Ww=(Object.freeze||Object)({parse:Gt,lift:Ht,toHex:Zt,fastLerp:Ut,fastMapToColor:Gw,lerp:Xt,mapToColor:Fw,modifyHSL:jt,modifyAlpha:Yt,stringify:qt}),Hw=Array.prototype.slice,Zw=function(t,e,i,n){this._tracks={},this._target=t,this._loop=e||!1,this._getter=i||Kt,this._setter=n||$t,this._clipCount=0,this._delay=0,this._doneList=[],this._onframeList=[],this._clipList=[]};Zw.prototype={when:function(t,e){var i=this._tracks;for(var n in e)if(e.hasOwnProperty(n)){if(!i[n]){i[n]=[];var o=this._getter(this._target,n);if(null==o)continue;0!==t&&i[n].push({time:0,value:ae(o)})}i[n].push({time:t,value:e[n]})}return this},during:function(t){return this._onframeList.push(t),this},pause:function(){for(var t=0;t<this._clipList.length;t++)this._clipList[t].pause();this._paused=!0},resume:function(){for(var t=0;t<this._clipList.length;t++)this._clipList[t].resume();this._paused=!1},isPaused:function(){return!!this._paused},_doneCallback:function(){this._tracks={},this._clipList.length=0;for(var t=this._doneList,e=t.length,i=0;i<e;i++)t[i].call(this)},start:function(t,e){var i,n=this,o=0;for(var a in this._tracks)if(this._tracks.hasOwnProperty(a)){var r=le(this,t,function(){--o||n._doneCallback()},this._tracks[a],a,e);r&&(this._clipList.push(r),o++,this.animation&&this.animation.addClip(r),i=r)}if(i){var s=i.onframe;i.onframe=function(t,e){s(t,e);for(var i=0;i<n._onframeList.length;i++)n._onframeList[i](t,e)}}return o||this._doneCallback(),this},stop:function(t){for(var e=this._clipList,i=this.animation,n=0;n<e.length;n++){var o=e[n];t&&o.onframe(this._target,1),i&&i.removeClip(o)}e.length=0},delay:function(t){return this._delay=t,this},done:function(t){return t&&this._doneList.push(t),this},getClips:function(){return this._clipList}};var Uw=1;"undefined"!=typeof window&&(Uw=Math.max(window.devicePixelRatio||1,1));var Xw=Uw,jw=function(){},Yw=jw,qw=function(){this.animators=[]};qw.prototype={constructor:qw,animate:function(t,e){var i,n=!1,o=this,a=this.__zr;if(t){var r=t.split("."),s=o;n="shape"===r[0];for(var u=0,h=r.length;u<h;u++)s&&(s=s[r[u]]);s&&(i=s)}else i=o;if(i){var c=o.animators,d=new Zw(i,e);return d.during(function(t){o.dirty(n)}).done(function(){c.splice(l(c,d),1)}),c.push(d),a&&a.animation.addAnimator(d),d}Yw('Property "'+t+'" is not existed in element '+o.id)},stopAnimation:function(t){for(var e=this.animators,i=e.length,n=0;n<i;n++)e[n].stop(t);return e.length=0,this},animateTo:function(t,e,i,n,o,a){ue(this,t,e,i,n,o,a)},animateFrom:function(t,e,i,n,o,a){ue(this,t,e,i,n,o,a,!0)}};var Kw=function(t){Tw.call(this,t),fw.call(this,t),qw.call(this,t),this.id=t.id||H_()};Kw.prototype={type:"element",name:"",__zr:null,ignore:!1,clipPath:null,isGroup:!1,drift:function(t,e){switch(this.draggable){case"horizontal":e=0;break;case"vertical":t=0}var i=this.transform;i||(i=this.transform=[1,0,0,1,0,0]),i[4]+=t,i[5]+=e,this.decomposeTransform(),this.dirty(!1)},beforeUpdate:function(){},afterUpdate:function(){},update:function(){this.updateTransform()},traverse:function(t,e){},attrKV:function(t,e){if("position"===t||"scale"===t||"origin"===t){if(e){var i=this[t];i||(i=this[t]=[]),i[0]=e[0],i[1]=e[1]}}else this[t]=e},hide:function(){this.ignore=!0,this.__zr&&this.__zr.refresh()},show:function(){this.ignore=!1,this.__zr&&this.__zr.refresh()},attr:function(t,e){if("string"==typeof t)this.attrKV(t,e);else if(w(t))for(var i in t)t.hasOwnProperty(i)&&this.attrKV(i,t[i]);return this.dirty(!1),this},setClipPath:function(t){var e=this.__zr;e&&t.addSelfToZr(e),this.clipPath&&this.clipPath!==t&&this.removeClipPath(),this.clipPath=t,t.__zr=e,t.__clipTarget=this,this.dirty(!1)},removeClipPath:function(){var t=this.clipPath;t&&(t.__zr&&t.removeSelfFromZr(t.__zr),t.__zr=null,t.__clipTarget=null,this.clipPath=null,this.dirty(!1))},addSelfToZr:function(t){this.__zr=t;var e=this.animators;if(e)for(var i=0;i<e.length;i++)t.animation.addAnimator(e[i]);this.clipPath&&this.clipPath.addSelfToZr(t)},removeSelfFromZr:function(t){this.__zr=null;var e=this.animators;if(e)for(var i=0;i<e.length;i++)t.animation.removeAnimator(e[i]);this.clipPath&&this.clipPath.removeSelfFromZr(t)}},h(Kw,qw),h(Kw,Tw),h(Kw,fw);var $w=Q,Jw=Math.min,Qw=Math.max;de.prototype={constructor:de,union:function(t){var e=Jw(t.x,this.x),i=Jw(t.y,this.y);this.width=Qw(t.x+t.width,this.x+this.width)-e,this.height=Qw(t.y+t.height,this.y+this.height)-i,this.x=e,this.y=i},applyTransform:function(){var t=[],e=[],i=[],n=[];return function(o){if(o){t[0]=i[0]=this.x,t[1]=n[1]=this.y,e[0]=n[0]=this.x+this.width,e[1]=i[1]=this.y+this.height,$w(t,t,o),$w(e,e,o),$w(i,i,o),$w(n,n,o),this.x=Jw(t[0],e[0],i[0],n[0]),this.y=Jw(t[1],e[1],i[1],n[1]);var a=Qw(t[0],e[0],i[0],n[0]),r=Qw(t[1],e[1],i[1],n[1]);this.width=a-this.x,this.height=r-this.y}}}(),calculateTransform:function(t){var e=this,i=t.width/e.width,n=t.height/e.height,o=xt();return St(o,o,[-e.x,-e.y]),It(o,o,[i,n]),St(o,o,[t.x,t.y]),o},intersect:function(t){if(!t)return!1;t instanceof de||(t=de.create(t));var e=this,i=e.x,n=e.x+e.width,o=e.y,a=e.y+e.height,r=t.x,s=t.x+t.width,l=t.y,u=t.y+t.height;return!(n<r||s<i||a<l||u<o)},contain:function(t,e){var i=this;return t>=i.x&&t<=i.x+i.width&&e>=i.y&&e<=i.y+i.height},clone:function(){return new de(this.x,this.y,this.width,this.height)},copy:function(t){this.x=t.x,this.y=t.y,this.width=t.width,this.height=t.height},plain:function(){return{x:this.x,y:this.y,width:this.width,height:this.height}}},de.create=function(t){return new de(t.x,t.y,t.width,t.height)};var tb=function(t){t=t||{},Kw.call(this,t);for(var e in t)t.hasOwnProperty(e)&&(this[e]=t[e]);this._children=[],this.__storage=null,this.__dirty=!0};tb.prototype={constructor:tb,isGroup:!0,type:"group",silent:!1,children:function(){return this._children.slice()},childAt:function(t){return this._children[t]},childOfName:function(t){for(var e=this._children,i=0;i<e.length;i++)if(e[i].name===t)return e[i]},childCount:function(){return this._children.length},add:function(t){return t&&t!==this&&t.parent!==this&&(this._children.push(t),this._doAdd(t)),this},addBefore:function(t,e){if(t&&t!==this&&t.parent!==this&&e&&e.parent===this){var i=this._children,n=i.indexOf(e);n>=0&&(i.splice(n,0,t),this._doAdd(t))}return this},_doAdd:function(t){t.parent&&t.parent.remove(t),t.parent=this;var e=this.__storage,i=this.__zr;e&&e!==t.__storage&&(e.addToStorage(t),t instanceof tb&&t.addChildrenToStorage(e)),i&&i.refresh()},remove:function(t){var e=this.__zr,i=this.__storage,n=this._children,o=l(n,t);return o<0?this:(n.splice(o,1),t.parent=null,i&&(i.delFromStorage(t),t instanceof tb&&t.delChildrenFromStorage(i)),e&&e.refresh(),this)},removeAll:function(){var t,e,i=this._children,n=this.__storage;for(e=0;e<i.length;e++)t=i[e],n&&(n.delFromStorage(t),t instanceof tb&&t.delChildrenFromStorage(n)),t.parent=null;return i.length=0,this},eachChild:function(t,e){for(var i=this._children,n=0;n<i.length;n++){var o=i[n];t.call(e,o,n)}return this},traverse:function(t,e){for(var i=0;i<this._children.length;i++){var n=this._children[i];t.call(e,n),"group"===n.type&&n.traverse(t,e)}return this},addChildrenToStorage:function(t){for(var e=0;e<this._children.length;e++){var i=this._children[e];t.addToStorage(i),i instanceof tb&&i.addChildrenToStorage(t)}},delChildrenFromStorage:function(t){for(var e=0;e<this._children.length;e++){var i=this._children[e];t.delFromStorage(i),i instanceof tb&&i.delChildrenFromStorage(t)}},dirty:function(){return this.__dirty=!0,this.__zr&&this.__zr.refresh(),this},getBoundingRect:function(t){for(var e=null,i=new de(0,0,0,0),n=t||this._children,o=[],a=0;a<n.length;a++){var r=n[a];if(!r.ignore&&!r.invisible){var s=r.getBoundingRect(),l=r.getLocalTransform(o);l?(i.copy(s),i.applyTransform(l),(e=e||i.clone()).union(i)):(e=e||s.clone()).union(s)}}return e||i}},u(tb,Kw);var eb=32,ib=7,nb=function(){this._roots=[],this._displayList=[],this._displayListLen=0};nb.prototype={constructor:nb,traverse:function(t,e){for(var i=0;i<this._roots.length;i++)this._roots[i].traverse(t,e)},getDisplayList:function(t,e){return e=e||!1,t&&this.updateDisplayList(e),this._displayList},updateDisplayList:function(t){this._displayListLen=0;for(var e=this._roots,i=this._displayList,n=0,o=e.length;n<o;n++)this._updateAndAddDisplayable(e[n],null,t);i.length=this._displayListLen,U_.canvasSupported&&_e(i,we)},_updateAndAddDisplayable:function(t,e,i){if(!t.ignore||i){t.beforeUpdate(),t.__dirty&&t.update(),t.afterUpdate();var n=t.clipPath;if(n){e=e?e.slice():[];for(var o=n,a=t;o;)o.parent=a,o.updateTransform(),e.push(o),a=o,o=o.clipPath}if(t.isGroup){for(var r=t._children,s=0;s<r.length;s++){var l=r[s];t.__dirty&&(l.__dirty=!0),this._updateAndAddDisplayable(l,e,i)}t.__dirty=!1}else t.__clipPaths=e,this._displayList[this._displayListLen++]=t}},addRoot:function(t){t.__storage!==this&&(t instanceof tb&&t.addChildrenToStorage(this),this.addToStorage(t),this._roots.push(t))},delRoot:function(t){if(null==t){for(i=0;i<this._roots.length;i++){var e=this._roots[i];e instanceof tb&&e.delChildrenFromStorage(this)}return this._roots=[],this._displayList=[],void(this._displayListLen=0)}if(t instanceof Array)for(var i=0,n=t.length;i<n;i++)this.delRoot(t[i]);else{var o=l(this._roots,t);o>=0&&(this.delFromStorage(t),this._roots.splice(o,1),t instanceof tb&&t.delChildrenFromStorage(this))}},addToStorage:function(t){return t&&(t.__storage=this,t.dirty(!1)),this},delFromStorage:function(t){return t&&(t.__storage=null),this},dispose:function(){this._renderList=this._roots=null},displayableSortFunc:we};var ob={shadowBlur:1,shadowOffsetX:1,shadowOffsetY:1,textShadowBlur:1,textShadowOffsetX:1,textShadowOffsetY:1,textBoxShadowBlur:1,textBoxShadowOffsetX:1,textBoxShadowOffsetY:1},ab=function(t,e,i){return ob.hasOwnProperty(e)?i*=t.dpr:i},rb={NONE:0,STYLE_BIND:1,PLAIN_TEXT:2},sb=9,lb=[["shadowBlur",0],["shadowOffsetX",0],["shadowOffsetY",0],["shadowColor","#000"],["lineCap","butt"],["lineJoin","miter"],["miterLimit",10]],ub=function(t){this.extendFrom(t,!1)};ub.prototype={constructor:ub,fill:"#000",stroke:null,opacity:1,fillOpacity:null,strokeOpacity:null,lineDash:null,lineDashOffset:0,shadowBlur:0,shadowOffsetX:0,shadowOffsetY:0,lineWidth:1,strokeNoScale:!1,text:null,font:null,textFont:null,fontStyle:null,fontWeight:null,fontSize:null,fontFamily:null,textTag:null,textFill:"#000",textStroke:null,textWidth:null,textHeight:null,textStrokeWidth:0,textLineHeight:null,textPosition:"inside",textRect:null,textOffset:null,textAlign:null,textVerticalAlign:null,textDistance:5,textShadowColor:"transparent",textShadowBlur:0,textShadowOffsetX:0,textShadowOffsetY:0,textBoxShadowColor:"transparent",textBoxShadowBlur:0,textBoxShadowOffsetX:0,textBoxShadowOffsetY:0,transformText:!1,textRotation:0,textOrigin:null,textBackgroundColor:null,textBorderColor:null,textBorderWidth:0,textBorderRadius:0,textPadding:null,rich:null,truncate:null,blend:null,bind:function(t,e,i){var n=this,o=i&&i.style,a=!o||t.__attrCachedBy!==rb.STYLE_BIND;t.__attrCachedBy=rb.STYLE_BIND;for(var r=0;r<lb.length;r++){var s=lb[r],l=s[0];(a||n[l]!==o[l])&&(t[l]=ab(t,l,n[l]||s[1]))}if((a||n.fill!==o.fill)&&(t.fillStyle=n.fill),(a||n.stroke!==o.stroke)&&(t.strokeStyle=n.stroke),(a||n.opacity!==o.opacity)&&(t.globalAlpha=null==n.opacity?1:n.opacity),(a||n.blend!==o.blend)&&(t.globalCompositeOperation=n.blend||"source-over"),this.hasStroke()){var u=n.lineWidth;t.lineWidth=u/(this.strokeNoScale&&e&&e.getLineScale?e.getLineScale():1)}},hasFill:function(){var t=this.fill;return null!=t&&"none"!==t},hasStroke:function(){var t=this.stroke;return null!=t&&"none"!==t&&this.lineWidth>0},extendFrom:function(t,e){if(t)for(var i in t)!t.hasOwnProperty(i)||!0!==e&&(!1===e?this.hasOwnProperty(i):null==t[i])||(this[i]=t[i])},set:function(t,e){"string"==typeof t?this[t]=e:this.extendFrom(t,!0)},clone:function(){var t=new this.constructor;return t.extendFrom(this,!0),t},getGradient:function(t,e,i){for(var n=("radial"===e.type?Se:be)(t,e,i),o=e.colorStops,a=0;a<o.length;a++)n.addColorStop(o[a].offset,o[a].color);return n}};for(var hb=ub.prototype,cb=0;cb<lb.length;cb++){var db=lb[cb];db[0]in hb||(hb[db[0]]=db[1])}ub.getGradient=hb.getGradient;var fb=function(t,e){this.image=t,this.repeat=e,this.type="pattern"};fb.prototype.getCanvasPattern=function(t){return t.createPattern(this.image,this.repeat||"repeat")};var pb=function(t,e,i){var n;i=i||Xw,"string"==typeof t?n=Ie(t,e,i):w(t)&&(t=(n=t).id),this.id=t,this.dom=n;var o=n.style;o&&(n.onselectstart=Me,o["-webkit-user-select"]="none",o["user-select"]="none",o["-webkit-touch-callout"]="none",o["-webkit-tap-highlight-color"]="rgba(0,0,0,0)",o.padding=0,o.margin=0,o["border-width"]=0),this.domBack=null,this.ctxBack=null,this.painter=e,this.config=null,this.clearColor=0,this.motionBlur=!1,this.lastFrameAlpha=.7,this.dpr=i};pb.prototype={constructor:pb,__dirty:!0,__used:!1,__drawIndex:0,__startIndex:0,__endIndex:0,incremental:!1,getElementCount:function(){return this.__endIndex-this.__startIndex},initContext:function(){this.ctx=this.dom.getContext("2d"),this.ctx.dpr=this.dpr},createBackBuffer:function(){var t=this.dpr;this.domBack=Ie("back-"+this.id,this.painter,t),this.ctxBack=this.domBack.getContext("2d"),1!==t&&this.ctxBack.scale(t,t)},resize:function(t,e){var i=this.dpr,n=this.dom,o=n.style,a=this.domBack;o&&(o.width=t+"px",o.height=e+"px"),n.width=t*i,n.height=e*i,a&&(a.width=t*i,a.height=e*i,1!==i&&this.ctxBack.scale(i,i))},clear:function(t,e){var i=this.dom,n=this.ctx,o=i.width,a=i.height,e=e||this.clearColor,r=this.motionBlur&&!t,s=this.lastFrameAlpha,l=this.dpr;if(r&&(this.domBack||this.createBackBuffer(),this.ctxBack.globalCompositeOperation="copy",this.ctxBack.drawImage(i,0,0,o/l,a/l)),n.clearRect(0,0,o,a),e&&"transparent"!==e){var u;e.colorStops?(u=e.__canvasGradient||ub.getGradient(n,e,{x:0,y:0,width:o,height:a}),e.__canvasGradient=u):e.image&&(u=fb.prototype.getCanvasPattern.call(e,n)),n.save(),n.fillStyle=u||e,n.fillRect(0,0,o,a),n.restore()}if(r){var h=this.domBack;n.save(),n.globalAlpha=s,n.drawImage(h,0,0,o,a),n.restore()}}};var gb="undefined"!=typeof window&&(window.requestAnimationFrame&&window.requestAnimationFrame.bind(window)||window.msRequestAnimationFrame&&window.msRequestAnimationFrame.bind(window)||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame)||function(t){setTimeout(t,16)},mb=new Ew(50),vb={},yb=0,xb=5e3,_b=/\{([a-zA-Z0-9_]+)\|([^}]*)\}/g,wb="12px sans-serif",bb={};bb.measureText=function(t,e){var i=s();return i.font=e||wb,i.measureText(t)};var Sb=wb,Mb={left:1,right:1,center:1},Ib={top:1,bottom:1,middle:1},Tb=[["textShadowBlur","shadowBlur",0],["textShadowOffsetX","shadowOffsetX",0],["textShadowOffsetY","shadowOffsetY",0],["textShadowColor","shadowColor","transparent"]],Ab=new de,Db=function(){};Db.prototype={constructor:Db,drawRectText:function(t,e){var i=this.style;e=i.textRect||e,this.__dirty&&Ye(i);var n=i.text;if(null!=n&&(n+=""),ci(n,i)){t.save();var o=this.transform;i.transformText?this.setTransform(t):o&&(Ab.copy(e),Ab.applyTransform(o),e=Ab),Ke(this,t,n,i,e,sb),t.restore()}}},di.prototype={constructor:di,type:"displayable",__dirty:!0,invisible:!1,z:0,z2:0,zlevel:0,draggable:!1,dragging:!1,silent:!1,culling:!1,cursor:"pointer",rectHover:!1,progressive:!1,incremental:!1,globalScaleRatio:1,beforeBrush:function(t){},afterBrush:function(t){},brush:function(t,e){},getBoundingRect:function(){},contain:function(t,e){return this.rectContain(t,e)},traverse:function(t,e){t.call(e,this)},rectContain:function(t,e){var i=this.transformCoordToLocal(t,e);return this.getBoundingRect().contain(i[0],i[1])},dirty:function(){this.__dirty=this.__dirtyText=!0,this._rect=null,this.__zr&&this.__zr.refresh()},animateStyle:function(t){return this.animate("style",t)},attrKV:function(t,e){"style"!==t?Kw.prototype.attrKV.call(this,t,e):this.style.set(e)},setStyle:function(t,e){return this.style.set(t,e),this.dirty(!1),this},useStyle:function(t){return this.style=new ub(t,this),this.dirty(!1),this}},u(di,Kw),h(di,Db),fi.prototype={constructor:fi,type:"image",brush:function(t,e){var i=this.style,n=i.image;i.bind(t,this,e);var o=this._image=Ae(n,this._image,this,this.onload);if(o&&Ce(o)){var a=i.x||0,r=i.y||0,s=i.width,l=i.height,u=o.width/o.height;if(null==s&&null!=l?s=l*u:null==l&&null!=s?l=s/u:null==s&&null==l&&(s=o.width,l=o.height),this.setTransform(t),i.sWidth&&i.sHeight){var h=i.sx||0,c=i.sy||0;t.drawImage(o,h,c,i.sWidth,i.sHeight,a,r,s,l)}else if(i.sx&&i.sy){var d=s-(h=i.sx),f=l-(c=i.sy);t.drawImage(o,h,c,d,f,a,r,s,l)}else t.drawImage(o,a,r,s,l);null!=i.text&&(this.restoreTransform(t),this.drawRectText(t,this.getBoundingRect()))}},getBoundingRect:function(){var t=this.style;return this._rect||(this._rect=new de(t.x||0,t.y||0,t.width||0,t.height||0)),this._rect}},u(fi,di);var Cb=new de(0,0,0,0),Lb=new de(0,0,0,0),kb=function(t,e,i){this.type="canvas";var n=!t.nodeName||"CANVAS"===t.nodeName.toUpperCase();this._opts=i=a({},i||{}),this.dpr=i.devicePixelRatio||Xw,this._singleCanvas=n,this.root=t;var o=t.style;o&&(o["-webkit-tap-highlight-color"]="transparent",o["-webkit-user-select"]=o["user-select"]=o["-webkit-touch-callout"]="none",t.innerHTML=""),this.storage=e;var r=this._zlevelList=[],s=this._layers={};if(this._layerConfig={},this._needsManuallyCompositing=!1,n){var l=t.width,u=t.height;null!=i.width&&(l=i.width),null!=i.height&&(u=i.height),this.dpr=i.devicePixelRatio||1,t.width=l*this.dpr,t.height=u*this.dpr,this._width=l,this._height=u;var h=new pb(t,this,this.dpr);h.__builtin__=!0,h.initContext(),s[314159]=h,h.zlevel=314159,r.push(314159),this._domRoot=t}else{this._width=this._getSize(0),this._height=this._getSize(1);var c=this._domRoot=xi(this._width,this._height);t.appendChild(c)}this._hoverlayer=null,this._hoverElements=[]};kb.prototype={constructor:kb,getType:function(){return"canvas"},isSingleCanvas:function(){return this._singleCanvas},getViewportRoot:function(){return this._domRoot},getViewportRootOffset:function(){var t=this.getViewportRoot();if(t)return{offsetLeft:t.offsetLeft||0,offsetTop:t.offsetTop||0}},refresh:function(t){var e=this.storage.getDisplayList(!0),i=this._zlevelList;this._redrawId=Math.random(),this._paintList(e,t,this._redrawId);for(var n=0;n<i.length;n++){var o=i[n],a=this._layers[o];if(!a.__builtin__&&a.refresh){var r=0===n?this._backgroundColor:null;a.refresh(r)}}return this.refreshHover(),this},addHover:function(t,e){if(!t.__hoverMir){var i=new t.constructor({style:t.style,shape:t.shape,z:t.z,z2:t.z2,silent:t.silent});return i.__from=t,t.__hoverMir=i,e&&i.setStyle(e),this._hoverElements.push(i),i}},removeHover:function(t){var e=t.__hoverMir,i=this._hoverElements,n=l(i,e);n>=0&&i.splice(n,1),t.__hoverMir=null},clearHover:function(t){for(var e=this._hoverElements,i=0;i<e.length;i++){var n=e[i].__from;n&&(n.__hoverMir=null)}e.length=0},refreshHover:function(){var t=this._hoverElements,e=t.length,i=this._hoverlayer;if(i&&i.clear(),e){_e(t,this.storage.displayableSortFunc),i||(i=this._hoverlayer=this.getLayer(1e5));var n={};i.ctx.save();for(var o=0;o<e;){var a=t[o],r=a.__from;r&&r.__zr?(o++,r.invisible||(a.transform=r.transform,a.invTransform=r.invTransform,a.__clipPaths=r.__clipPaths,this._doPaintEl(a,i,!0,n))):(t.splice(o,1),r.__hoverMir=null,e--)}i.ctx.restore()}},getHoverLayer:function(){return this.getLayer(1e5)},_paintList:function(t,e,i){if(this._redrawId===i){e=e||!1,this._updateLayerStatus(t);var n=this._doPaintList(t,e);if(this._needsManuallyCompositing&&this._compositeManually(),!n){var o=this;gb(function(){o._paintList(t,e,i)})}}},_compositeManually:function(){var t=this.getLayer(314159).ctx,e=this._domRoot.width,i=this._domRoot.height;t.clearRect(0,0,e,i),this.eachBuiltinLayer(function(n){n.virtual&&t.drawImage(n.dom,0,0,e,i)})},_doPaintList:function(t,e){for(var i=[],n=0;n<this._zlevelList.length;n++){var o=this._zlevelList[n];(s=this._layers[o]).__builtin__&&s!==this._hoverlayer&&(s.__dirty||e)&&i.push(s)}for(var a=!0,r=0;r<i.length;r++){var s=i[r],l=s.ctx,u={};l.save();var h=e?s.__startIndex:s.__drawIndex,c=!e&&s.incremental&&Date.now,f=c&&Date.now(),p=s.zlevel===this._zlevelList[0]?this._backgroundColor:null;if(s.__startIndex===s.__endIndex)s.clear(!1,p);else if(h===s.__startIndex){var g=t[h];g.incremental&&g.notClear&&!e||s.clear(!1,p)}-1===h&&(console.error("For some unknown reason. drawIndex is -1"),h=s.__startIndex);for(var m=h;m<s.__endIndex;m++){var v=t[m];if(this._doPaintEl(v,s,e,u),v.__dirty=v.__dirtyText=!1,c&&Date.now()-f>15)break}s.__drawIndex=m,s.__drawIndex<s.__endIndex&&(a=!1),u.prevElClipPaths&&l.restore(),l.restore()}return U_.wxa&&d(this._layers,function(t){t&&t.ctx&&t.ctx.draw&&t.ctx.draw()}),a},_doPaintEl:function(t,e,i,n){var o=e.ctx,a=t.transform;if((e.__dirty||i)&&!t.invisible&&0!==t.style.opacity&&(!a||a[0]||a[3])&&(!t.culling||!mi(t,this._width,this._height))){var r=t.__clipPaths;n.prevElClipPaths&&!vi(r,n.prevElClipPaths)||(n.prevElClipPaths&&(e.ctx.restore(),n.prevElClipPaths=null,n.prevEl=null),r&&(o.save(),yi(r,o),n.prevElClipPaths=r)),t.beforeBrush&&t.beforeBrush(o),t.brush(o,n.prevEl||null),n.prevEl=t,t.afterBrush&&t.afterBrush(o)}},getLayer:function(t,e){this._singleCanvas&&!this._needsManuallyCompositing&&(t=314159);var i=this._layers[t];return i||((i=new pb("zr_"+t,this,this.dpr)).zlevel=t,i.__builtin__=!0,this._layerConfig[t]&&n(i,this._layerConfig[t],!0),e&&(i.virtual=e),this.insertLayer(t,i),i.initContext()),i},insertLayer:function(t,e){var i=this._layers,n=this._zlevelList,o=n.length,a=null,r=-1,s=this._domRoot;if(i[t])Yw("ZLevel "+t+" has been used already");else if(gi(e)){if(o>0&&t>n[0]){for(r=0;r<o-1&&!(n[r]<t&&n[r+1]>t);r++);a=i[n[r]]}if(n.splice(r+1,0,t),i[t]=e,!e.virtual)if(a){var l=a.dom;l.nextSibling?s.insertBefore(e.dom,l.nextSibling):s.appendChild(e.dom)}else s.firstChild?s.insertBefore(e.dom,s.firstChild):s.appendChild(e.dom)}else Yw("Layer of zlevel "+t+" is not valid")},eachLayer:function(t,e){var i,n,o=this._zlevelList;for(n=0;n<o.length;n++)i=o[n],t.call(e,this._layers[i],i)},eachBuiltinLayer:function(t,e){var i,n,o,a=this._zlevelList;for(o=0;o<a.length;o++)n=a[o],(i=this._layers[n]).__builtin__&&t.call(e,i,n)},eachOtherLayer:function(t,e){var i,n,o,a=this._zlevelList;for(o=0;o<a.length;o++)n=a[o],(i=this._layers[n]).__builtin__||t.call(e,i,n)},getLayers:function(){return this._layers},_updateLayerStatus:function(t){function e(t){i&&(i.__endIndex!==t&&(i.__dirty=!0),i.__endIndex=t)}if(this.eachBuiltinLayer(function(t,e){t.__dirty=t.__used=!1}),this._singleCanvas)for(o=1;o<t.length;o++)if((r=t[o]).zlevel!==t[o-1].zlevel||r.incremental){this._needsManuallyCompositing=!0;break}for(var i=null,n=0,o=0;o<t.length;o++){var a,r=t[o],s=r.zlevel;r.incremental?((a=this.getLayer(s+.001,this._needsManuallyCompositing)).incremental=!0,n=1):a=this.getLayer(s+(n>0?.01:0),this._needsManuallyCompositing),a.__builtin__||Yw("ZLevel "+s+" has been used by unkown layer "+a.id),a!==i&&(a.__used=!0,a.__startIndex!==o&&(a.__dirty=!0),a.__startIndex=o,a.incremental?a.__drawIndex=-1:a.__drawIndex=o,e(o),i=a),r.__dirty&&(a.__dirty=!0,a.incremental&&a.__drawIndex<0&&(a.__drawIndex=o))}e(o),this.eachBuiltinLayer(function(t,e){!t.__used&&t.getElementCount()>0&&(t.__dirty=!0,t.__startIndex=t.__endIndex=t.__drawIndex=0),t.__dirty&&t.__drawIndex<0&&(t.__drawIndex=t.__startIndex)})},clear:function(){return this.eachBuiltinLayer(this._clearLayer),this},_clearLayer:function(t){t.clear()},setBackgroundColor:function(t){this._backgroundColor=t},configLayer:function(t,e){if(e){var i=this._layerConfig;i[t]?n(i[t],e,!0):i[t]=e;for(var o=0;o<this._zlevelList.length;o++){var a=this._zlevelList[o];a!==t&&a!==t+.01||n(this._layers[a],i[t],!0)}}},delLayer:function(t){var e=this._layers,i=this._zlevelList,n=e[t];n&&(n.dom.parentNode.removeChild(n.dom),delete e[t],i.splice(l(i,t),1))},resize:function(t,e){if(this._domRoot.style){var i=this._domRoot;i.style.display="none";var n=this._opts;if(null!=t&&(n.width=t),null!=e&&(n.height=e),t=this._getSize(0),e=this._getSize(1),i.style.display="",this._width!==t||e!==this._height){i.style.width=t+"px",i.style.height=e+"px";for(var o in this._layers)this._layers.hasOwnProperty(o)&&this._layers[o].resize(t,e);d(this._progressiveLayers,function(i){i.resize(t,e)}),this.refresh(!0)}this._width=t,this._height=e}else{if(null==t||null==e)return;this._width=t,this._height=e,this.getLayer(314159).resize(t,e)}return this},clearLayer:function(t){var e=this._layers[t];e&&e.clear()},dispose:function(){this.root.innerHTML="",this.root=this.storage=this._domRoot=this._layers=null},getRenderedCanvas:function(t){if(t=t||{},this._singleCanvas&&!this._compositeManually)return this._layers[314159].dom;var e=new pb("image",this,t.pixelRatio||this.dpr);if(e.initContext(),e.clear(!1,t.backgroundColor||this._backgroundColor),t.pixelRatio<=this.dpr){this.refresh();var i=e.dom.width,n=e.dom.height,o=e.ctx;this.eachLayer(function(t){t.__builtin__?o.drawImage(t.dom,0,0,i,n):t.renderToCanvas&&(e.ctx.save(),t.renderToCanvas(e.ctx),e.ctx.restore())})}else for(var a={},r=this.storage.getDisplayList(!0),s=0;s<r.length;s++){var l=r[s];this._doPaintEl(l,e,!0,a)}return e.dom},getWidth:function(){return this._width},getHeight:function(){return this._height},_getSize:function(t){var e=this._opts,i=["width","height"][t],n=["clientWidth","clientHeight"][t],o=["paddingLeft","paddingTop"][t],a=["paddingRight","paddingBottom"][t];if(null!=e[i]&&"auto"!==e[i])return parseFloat(e[i]);var r=this.root,s=document.defaultView.getComputedStyle(r);return(r[n]||pi(s[i])||pi(r.style[i]))-(pi(s[o])||0)-(pi(s[a])||0)|0},pathToImage:function(t,e){e=e||this.dpr;var i=document.createElement("canvas"),n=i.getContext("2d"),o=t.getBoundingRect(),a=t.style,r=a.shadowBlur*e,s=a.shadowOffsetX*e,l=a.shadowOffsetY*e,u=a.hasStroke()?a.lineWidth:0,h=Math.max(u/2,-s+r),c=Math.max(u/2,s+r),d=Math.max(u/2,-l+r),f=Math.max(u/2,l+r),p=o.width+h+c,g=o.height+d+f;i.width=p*e,i.height=g*e,n.scale(e,e),n.clearRect(0,0,p,g),n.dpr=e;var m={position:t.position,rotation:t.rotation,scale:t.scale};t.position=[h-o.x,d-o.y],t.rotation=0,t.scale=[1,1],t.updateTransform(),t&&t.brush(n);var v=new fi({style:{x:0,y:0,image:i}});return null!=m.position&&(v.position=t.position=m.position),null!=m.rotation&&(v.rotation=t.rotation=m.rotation),null!=m.scale&&(v.scale=t.scale=m.scale),v}};var Pb=function(t){t=t||{},this.stage=t.stage||{},this.onframe=t.onframe||function(){},this._clips=[],this._running=!1,this._time,this._pausedTime,this._pauseStart,this._paused=!1,fw.call(this)};Pb.prototype={constructor:Pb,addClip:function(t){this._clips.push(t)},addAnimator:function(t){t.animation=this;for(var e=t.getClips(),i=0;i<e.length;i++)this.addClip(e[i])},removeClip:function(t){var e=l(this._clips,t);e>=0&&this._clips.splice(e,1)},removeAnimator:function(t){for(var e=t.getClips(),i=0;i<e.length;i++)this.removeClip(e[i]);t.animation=null},_update:function(){for(var t=(new Date).getTime()-this._pausedTime,e=t-this._time,i=this._clips,n=i.length,o=[],a=[],r=0;r<n;r++){var s=i[r],l=s.step(t,e);l&&(o.push(l),a.push(s))}for(r=0;r<n;)i[r]._needsRemove?(i[r]=i[n-1],i.pop(),n--):r++;n=o.length;for(r=0;r<n;r++)a[r].fire(o[r]);this._time=t,this.onframe(e),this.trigger("frame",e),this.stage.update&&this.stage.update()},_startLoop:function(){function t(){e._running&&(gb(t),!e._paused&&e._update())}var e=this;this._running=!0,gb(t)},start:function(){this._time=(new Date).getTime(),this._pausedTime=0,this._startLoop()},stop:function(){this._running=!1},pause:function(){this._paused||(this._pauseStart=(new Date).getTime(),this._paused=!0)},resume:function(){this._paused&&(this._pausedTime+=(new Date).getTime()-this._pauseStart,this._paused=!1)},clear:function(){this._clips=[]},isFinished:function(){return!this._clips.length},animate:function(t,e){var i=new Zw(t,(e=e||{}).loop,e.getter,e.setter);return this.addAnimator(i),i}},h(Pb,fw);var Nb=["click","dblclick","mousewheel","mouseout","mouseup","mousedown","mousemove","contextmenu"],Ob=["touchstart","touchend","touchmove"],Eb={pointerdown:1,pointerup:1,pointermove:1,pointerout:1},Rb=f(Nb,function(t){var e=t.replace("mouse","pointer");return Eb[e]?e:t}),zb={mousemove:function(t){t=ut(this.dom,t),this.trigger("mousemove",t)},mouseout:function(t){var e=(t=ut(this.dom,t)).toElement||t.relatedTarget;if(e!==this.dom)for(;e&&9!==e.nodeType;){if(e===this.dom)return;e=e.parentNode}this.trigger("mouseout",t)},touchstart:function(t){(t=ut(this.dom,t)).zrByTouch=!0,this._lastTouchMoment=new Date,this.handler.processGesture(this,t,"start"),zb.mousemove.call(this,t),zb.mousedown.call(this,t),wi(this)},touchmove:function(t){(t=ut(this.dom,t)).zrByTouch=!0,this.handler.processGesture(this,t,"change"),zb.mousemove.call(this,t),wi(this)},touchend:function(t){(t=ut(this.dom,t)).zrByTouch=!0,this.handler.processGesture(this,t,"end"),zb.mouseup.call(this,t),+new Date-this._lastTouchMoment<300&&zb.click.call(this,t),wi(this)},pointerdown:function(t){zb.mousedown.call(this,t)},pointermove:function(t){bi(t)||zb.mousemove.call(this,t)},pointerup:function(t){zb.mouseup.call(this,t)},pointerout:function(t){bi(t)||zb.mouseout.call(this,t)}};d(["click","mousedown","mouseup","mousewheel","dblclick","contextmenu"],function(t){zb[t]=function(e){e=ut(this.dom,e),this.trigger(t,e)}});var Bb=Mi.prototype;Bb.dispose=function(){for(var t=Nb.concat(Ob),e=0;e<t.length;e++){var i=t[e];ct(this.dom,_i(i),this._handlers[i])}},Bb.setCursor=function(t){this.dom.style&&(this.dom.style.cursor=t||"default")},h(Mi,fw);var Vb=!U_.canvasSupported,Gb={canvas:kb},Fb={},Wb=function(t,e,i){i=i||{},this.dom=e,this.id=t;var n=this,o=new nb,a=i.renderer;if(Vb){if(!Gb.vml)throw new Error("You need to require 'zrender/vml/vml' to support IE8");a="vml"}else a&&Gb[a]||(a="canvas");var r=new Gb[a](e,o,i,t);this.storage=o,this.painter=r;var s=U_.node||U_.worker?null:new Mi(r.getViewportRoot());this.handler=new ww(o,r,s,r.root),this.animation=new Pb({stage:{update:m(this.flush,this)}}),this.animation.start(),this._needsRefresh;var l=o.delFromStorage,u=o.addToStorage;o.delFromStorage=function(t){l.call(o,t),t&&t.removeSelfFromZr(n)},o.addToStorage=function(t){u.call(o,t),t.addSelfToZr(n)}};Wb.prototype={constructor:Wb,getId:function(){return this.id},add:function(t){this.storage.addRoot(t),this._needsRefresh=!0},remove:function(t){this.storage.delRoot(t),this._needsRefresh=!0},configLayer:function(t,e){this.painter.configLayer&&this.painter.configLayer(t,e),this._needsRefresh=!0},setBackgroundColor:function(t){this.painter.setBackgroundColor&&this.painter.setBackgroundColor(t),this._needsRefresh=!0},refreshImmediately:function(){this._needsRefresh=!1,this.painter.refresh(),this._needsRefresh=!1},refresh:function(){this._needsRefresh=!0},flush:function(){var t;this._needsRefresh&&(t=!0,this.refreshImmediately()),this._needsRefreshHover&&(t=!0,this.refreshHoverImmediately()),t&&this.trigger("rendered")},addHover:function(t,e){if(this.painter.addHover){var i=this.painter.addHover(t,e);return this.refreshHover(),i}},removeHover:function(t){this.painter.removeHover&&(this.painter.removeHover(t),this.refreshHover())},clearHover:function(){this.painter.clearHover&&(this.painter.clearHover(),this.refreshHover())},refreshHover:function(){this._needsRefreshHover=!0},refreshHoverImmediately:function(){this._needsRefreshHover=!1,this.painter.refreshHover&&this.painter.refreshHover()},resize:function(t){t=t||{},this.painter.resize(t.width,t.height),this.handler.resize()},clearAnimation:function(){this.animation.clear()},getWidth:function(){return this.painter.getWidth()},getHeight:function(){return this.painter.getHeight()},pathToImage:function(t,e){return this.painter.pathToImage(t,e)},setCursorStyle:function(t){this.handler.setCursorStyle(t)},findHover:function(t,e){return this.handler.findHover(t,e)},on:function(t,e,i){this.handler.on(t,e,i)},off:function(t,e){this.handler.off(t,e)},trigger:function(t,e){this.handler.trigger(t,e)},clear:function(){this.storage.delRoot(),this.painter.clear()},dispose:function(){this.animation.stop(),this.clear(),this.storage.dispose(),this.painter.dispose(),this.handler.dispose(),this.animation=this.storage=this.painter=this.handler=null,Ai(this.id)}};var Hb=(Object.freeze||Object)({version:"4.0.7",init:Ii,dispose:function(t){if(t)t.dispose();else{for(var e in Fb)Fb.hasOwnProperty(e)&&Fb[e].dispose();Fb={}}return this},getInstance:function(t){return Fb[t]},registerPainter:Ti}),Zb=d,Ub=w,Xb=y,jb="series\0",Yb=["fontStyle","fontWeight","fontSize","fontFamily","rich","tag","color","textBorderColor","textBorderWidth","width","height","lineHeight","align","verticalAlign","baseline","shadowColor","shadowBlur","shadowOffsetX","shadowOffsetY","textShadowColor","textShadowBlur","textShadowOffsetX","textShadowOffsetY","backgroundColor","borderColor","borderWidth","borderRadius","padding"],qb=0,Kb=".",$b="___EC__COMPONENT__CONTAINER___",Jb=0,Qb=function(t){for(var e=0;e<t.length;e++)t[e][1]||(t[e][1]=t[e][0]);return function(e,i,n){for(var o={},a=0;a<t.length;a++){var r=t[a][1];if(!(i&&l(i,r)>=0||n&&l(n,r)<0)){var s=e.getShallow(r);null!=s&&(o[t[a][0]]=s)}}return o}},tS=Qb([["lineWidth","width"],["stroke","color"],["opacity"],["shadowBlur"],["shadowOffsetX"],["shadowOffsetY"],["shadowColor"]]),eS={getLineStyle:function(t){var e=tS(this,t),i=this.getLineDash(e.lineWidth);return i&&(e.lineDash=i),e},getLineDash:function(t){null==t&&(t=1);var e=this.get("type"),i=Math.max(t,2),n=4*t;return"solid"===e||null==e?null:"dashed"===e?[n,n]:[i,i]}},iS=Qb([["fill","color"],["shadowBlur"],["shadowOffsetX"],["shadowOffsetY"],["opacity"],["shadowColor"]]),nS={getAreaStyle:function(t,e){return iS(this,t,e)}},oS=Math.pow,aS=Math.sqrt,rS=1e-8,sS=1e-4,lS=aS(3),uS=1/3,hS=V(),cS=V(),dS=V(),fS=Math.min,pS=Math.max,gS=Math.sin,mS=Math.cos,vS=2*Math.PI,yS=V(),xS=V(),_S=V(),wS=[],bS=[],SS={M:1,L:2,C:3,Q:4,A:5,Z:6,R:7},MS=[],IS=[],TS=[],AS=[],DS=Math.min,CS=Math.max,LS=Math.cos,kS=Math.sin,PS=Math.sqrt,NS=Math.abs,OS="undefined"!=typeof Float32Array,ES=function(t){this._saveData=!t,this._saveData&&(this.data=[]),this._ctx=null};ES.prototype={constructor:ES,_xi:0,_yi:0,_x0:0,_y0:0,_ux:0,_uy:0,_len:0,_lineDash:null,_dashOffset:0,_dashIdx:0,_dashSum:0,setScale:function(t,e){this._ux=NS(1/Xw/t)||0,this._uy=NS(1/Xw/e)||0},getContext:function(){return this._ctx},beginPath:function(t){return this._ctx=t,t&&t.beginPath(),t&&(this.dpr=t.dpr),this._saveData&&(this._len=0),this._lineDash&&(this._lineDash=null,this._dashOffset=0),this},moveTo:function(t,e){return this.addData(SS.M,t,e),this._ctx&&this._ctx.moveTo(t,e),this._x0=t,this._y0=e,this._xi=t,this._yi=e,this},lineTo:function(t,e){var i=NS(t-this._xi)>this._ux||NS(e-this._yi)>this._uy||this._len<5;return this.addData(SS.L,t,e),this._ctx&&i&&(this._needsDash()?this._dashedLineTo(t,e):this._ctx.lineTo(t,e)),i&&(this._xi=t,this._yi=e),this},bezierCurveTo:function(t,e,i,n,o,a){return this.addData(SS.C,t,e,i,n,o,a),this._ctx&&(this._needsDash()?this._dashedBezierTo(t,e,i,n,o,a):this._ctx.bezierCurveTo(t,e,i,n,o,a)),this._xi=o,this._yi=a,this},quadraticCurveTo:function(t,e,i,n){return this.addData(SS.Q,t,e,i,n),this._ctx&&(this._needsDash()?this._dashedQuadraticTo(t,e,i,n):this._ctx.quadraticCurveTo(t,e,i,n)),this._xi=i,this._yi=n,this},arc:function(t,e,i,n,o,a){return this.addData(SS.A,t,e,i,i,n,o-n,0,a?0:1),this._ctx&&this._ctx.arc(t,e,i,n,o,a),this._xi=LS(o)*i+t,this._yi=kS(o)*i+e,this},arcTo:function(t,e,i,n,o){return this._ctx&&this._ctx.arcTo(t,e,i,n,o),this},rect:function(t,e,i,n){return this._ctx&&this._ctx.rect(t,e,i,n),this.addData(SS.R,t,e,i,n),this},closePath:function(){this.addData(SS.Z);var t=this._ctx,e=this._x0,i=this._y0;return t&&(this._needsDash()&&this._dashedLineTo(e,i),t.closePath()),this._xi=e,this._yi=i,this},fill:function(t){t&&t.fill(),this.toStatic()},stroke:function(t){t&&t.stroke(),this.toStatic()},setLineDash:function(t){if(t instanceof Array){this._lineDash=t,this._dashIdx=0;for(var e=0,i=0;i<t.length;i++)e+=t[i];this._dashSum=e}return this},setLineDashOffset:function(t){return this._dashOffset=t,this},len:function(){return this._len},setData:function(t){var e=t.length;this.data&&this.data.length===e||!OS||(this.data=new Float32Array(e));for(var i=0;i<e;i++)this.data[i]=t[i];this._len=e},appendPath:function(t){t instanceof Array||(t=[t]);for(var e=t.length,i=0,n=this._len,o=0;o<e;o++)i+=t[o].len();OS&&this.data instanceof Float32Array&&(this.data=new Float32Array(n+i));for(o=0;o<e;o++)for(var a=t[o].data,r=0;r<a.length;r++)this.data[n++]=a[r];this._len=n},addData:function(t){if(this._saveData){var e=this.data;this._len+arguments.length>e.length&&(this._expandData(),e=this.data);for(var i=0;i<arguments.length;i++)e[this._len++]=arguments[i];this._prevCmd=t}},_expandData:function(){if(!(this.data instanceof Array)){for(var t=[],e=0;e<this._len;e++)t[e]=this.data[e];this.data=t}},_needsDash:function(){return this._lineDash},_dashedLineTo:function(t,e){var i,n,o=this._dashSum,a=this._dashOffset,r=this._lineDash,s=this._ctx,l=this._xi,u=this._yi,h=t-l,c=e-u,d=PS(h*h+c*c),f=l,p=u,g=r.length;for(h/=d,c/=d,a<0&&(a=o+a),f-=(a%=o)*h,p-=a*c;h>0&&f<=t||h<0&&f>=t||0===h&&(c>0&&p<=e||c<0&&p>=e);)f+=h*(i=r[n=this._dashIdx]),p+=c*i,this._dashIdx=(n+1)%g,h>0&&f<l||h<0&&f>l||c>0&&p<u||c<0&&p>u||s[n%2?"moveTo":"lineTo"](h>=0?DS(f,t):CS(f,t),c>=0?DS(p,e):CS(p,e));h=f-t,c=p-e,this._dashOffset=-PS(h*h+c*c)},_dashedBezierTo:function(t,e,i,n,o,a){var r,s,l,u,h,c=this._dashSum,d=this._dashOffset,f=this._lineDash,p=this._ctx,g=this._xi,m=this._yi,v=tn,y=0,x=this._dashIdx,_=f.length,w=0;for(d<0&&(d=c+d),d%=c,r=0;r<1;r+=.1)s=v(g,t,i,o,r+.1)-v(g,t,i,o,r),l=v(m,e,n,a,r+.1)-v(m,e,n,a,r),y+=PS(s*s+l*l);for(;x<_&&!((w+=f[x])>d);x++);for(r=(w-d)/y;r<=1;)u=v(g,t,i,o,r),h=v(m,e,n,a,r),x%2?p.moveTo(u,h):p.lineTo(u,h),r+=f[x]/y,x=(x+1)%_;x%2!=0&&p.lineTo(o,a),s=o-u,l=a-h,this._dashOffset=-PS(s*s+l*l)},_dashedQuadraticTo:function(t,e,i,n){var o=i,a=n;i=(i+2*t)/3,n=(n+2*e)/3,t=(this._xi+2*t)/3,e=(this._yi+2*e)/3,this._dashedBezierTo(t,e,i,n,o,a)},toStatic:function(){var t=this.data;t instanceof Array&&(t.length=this._len,OS&&(this.data=new Float32Array(t)))},getBoundingRect:function(){MS[0]=MS[1]=TS[0]=TS[1]=Number.MAX_VALUE,IS[0]=IS[1]=AS[0]=AS[1]=-Number.MAX_VALUE;for(var t=this.data,e=0,i=0,n=0,o=0,a=0;a<t.length;){var r=t[a++];switch(1===a&&(n=e=t[a],o=i=t[a+1]),r){case SS.M:e=n=t[a++],i=o=t[a++],TS[0]=n,TS[1]=o,AS[0]=n,AS[1]=o;break;case SS.L:pn(e,i,t[a],t[a+1],TS,AS),e=t[a++],i=t[a++];break;case SS.C:gn(e,i,t[a++],t[a++],t[a++],t[a++],t[a],t[a+1],TS,AS),e=t[a++],i=t[a++];break;case SS.Q:mn(e,i,t[a++],t[a++],t[a],t[a+1],TS,AS),e=t[a++],i=t[a++];break;case SS.A:var s=t[a++],l=t[a++],u=t[a++],h=t[a++],c=t[a++],d=t[a++]+c;a+=1;var f=1-t[a++];1===a&&(n=LS(c)*u+s,o=kS(c)*h+l),vn(s,l,u,h,c,d,f,TS,AS),e=LS(d)*u+s,i=kS(d)*h+l;break;case SS.R:pn(n=e=t[a++],o=i=t[a++],n+t[a++],o+t[a++],TS,AS);break;case SS.Z:e=n,i=o}tt(MS,MS,TS),et(IS,IS,AS)}return 0===a&&(MS[0]=MS[1]=IS[0]=IS[1]=0),new de(MS[0],MS[1],IS[0]-MS[0],IS[1]-MS[1])},rebuildPath:function(t){for(var e,i,n,o,a,r,s=this.data,l=this._ux,u=this._uy,h=this._len,c=0;c<h;){var d=s[c++];switch(1===c&&(e=n=s[c],i=o=s[c+1]),d){case SS.M:e=n=s[c++],i=o=s[c++],t.moveTo(n,o);break;case SS.L:a=s[c++],r=s[c++],(NS(a-n)>l||NS(r-o)>u||c===h-1)&&(t.lineTo(a,r),n=a,o=r);break;case SS.C:t.bezierCurveTo(s[c++],s[c++],s[c++],s[c++],s[c++],s[c++]),n=s[c-2],o=s[c-1];break;case SS.Q:t.quadraticCurveTo(s[c++],s[c++],s[c++],s[c++]),n=s[c-2],o=s[c-1];break;case SS.A:var f=s[c++],p=s[c++],g=s[c++],m=s[c++],v=s[c++],y=s[c++],x=s[c++],_=s[c++],w=g>m?g:m,b=g>m?1:g/m,S=g>m?m/g:1,M=v+y;Math.abs(g-m)>.001?(t.translate(f,p),t.rotate(x),t.scale(b,S),t.arc(0,0,w,v,M,1-_),t.scale(1/b,1/S),t.rotate(-x),t.translate(-f,-p)):t.arc(f,p,w,v,M,1-_),1===c&&(e=LS(v)*g+f,i=kS(v)*m+p),n=LS(M)*g+f,o=kS(M)*m+p;break;case SS.R:e=n=s[c],i=o=s[c+1],t.rect(s[c++],s[c++],s[c++],s[c++]);break;case SS.Z:t.closePath(),n=e,o=i}}}},ES.CMD=SS;var RS=2*Math.PI,zS=2*Math.PI,BS=ES.CMD,VS=2*Math.PI,GS=1e-4,FS=[-1,-1,-1],WS=[-1,-1],HS=fb.prototype.getCanvasPattern,ZS=Math.abs,US=new ES(!0);Pn.prototype={constructor:Pn,type:"path",__dirtyPath:!0,strokeContainThreshold:5,subPixelOptimize:!1,brush:function(t,e){var i=this.style,n=this.path||US,o=i.hasStroke(),a=i.hasFill(),r=i.fill,s=i.stroke,l=a&&!!r.colorStops,u=o&&!!s.colorStops,h=a&&!!r.image,c=o&&!!s.image;if(i.bind(t,this,e),this.setTransform(t),this.__dirty){var d;l&&(d=d||this.getBoundingRect(),this._fillGradient=i.getGradient(t,r,d)),u&&(d=d||this.getBoundingRect(),this._strokeGradient=i.getGradient(t,s,d))}l?t.fillStyle=this._fillGradient:h&&(t.fillStyle=HS.call(r,t)),u?t.strokeStyle=this._strokeGradient:c&&(t.strokeStyle=HS.call(s,t));var f=i.lineDash,p=i.lineDashOffset,g=!!t.setLineDash,m=this.getGlobalScale();if(n.setScale(m[0],m[1]),this.__dirtyPath||f&&!g&&o?(n.beginPath(t),f&&!g&&(n.setLineDash(f),n.setLineDashOffset(p)),this.buildPath(n,this.shape,!1),this.path&&(this.__dirtyPath=!1)):(t.beginPath(),this.path.rebuildPath(t)),a)if(null!=i.fillOpacity){v=t.globalAlpha;t.globalAlpha=i.fillOpacity*i.opacity,n.fill(t),t.globalAlpha=v}else n.fill(t);if(f&&g&&(t.setLineDash(f),t.lineDashOffset=p),o)if(null!=i.strokeOpacity){var v=t.globalAlpha;t.globalAlpha=i.strokeOpacity*i.opacity,n.stroke(t),t.globalAlpha=v}else n.stroke(t);f&&g&&t.setLineDash([]),null!=i.text&&(this.restoreTransform(t),this.drawRectText(t,this.getBoundingRect()))},buildPath:function(t,e,i){},createPathProxy:function(){this.path=new ES},getBoundingRect:function(){var t=this._rect,e=this.style,i=!t;if(i){var n=this.path;n||(n=this.path=new ES),this.__dirtyPath&&(n.beginPath(),this.buildPath(n,this.shape,!1)),t=n.getBoundingRect()}if(this._rect=t,e.hasStroke()){var o=this._rectWithStroke||(this._rectWithStroke=t.clone());if(this.__dirty||i){o.copy(t);var a=e.lineWidth,r=e.strokeNoScale?this.getLineScale():1;e.hasFill()||(a=Math.max(a,this.strokeContainThreshold||4)),r>1e-10&&(o.width+=a/r,o.height+=a/r,o.x-=a/r/2,o.y-=a/r/2)}return o}return t},contain:function(t,e){var i=this.transformCoordToLocal(t,e),n=this.getBoundingRect(),o=this.style;if(t=i[0],e=i[1],n.contain(t,e)){var a=this.path.data;if(o.hasStroke()){var r=o.lineWidth,s=o.strokeNoScale?this.getLineScale():1;if(s>1e-10&&(o.hasFill()||(r=Math.max(r,this.strokeContainThreshold)),kn(a,r/s,t,e)))return!0}if(o.hasFill())return Ln(a,t,e)}return!1},dirty:function(t){null==t&&(t=!0),t&&(this.__dirtyPath=t,this._rect=null),this.__dirty=this.__dirtyText=!0,this.__zr&&this.__zr.refresh(),this.__clipTarget&&this.__clipTarget.dirty()},animateShape:function(t){return this.animate("shape",t)},attrKV:function(t,e){"shape"===t?(this.setShape(e),this.__dirtyPath=!0,this._rect=null):di.prototype.attrKV.call(this,t,e)},setShape:function(t,e){var i=this.shape;if(i){if(w(t))for(var n in t)t.hasOwnProperty(n)&&(i[n]=t[n]);else i[t]=e;this.dirty(!0)}return this},getLineScale:function(){var t=this.transform;return t&&ZS(t[0]-1)>1e-10&&ZS(t[3]-1)>1e-10?Math.sqrt(ZS(t[0]*t[3]-t[2]*t[1])):1}},Pn.extend=function(t){var e=function(e){Pn.call(this,e),t.style&&this.style.extendFrom(t.style,!1);var i=t.shape;if(i){this.shape=this.shape||{};var n=this.shape;for(var o in i)!n.hasOwnProperty(o)&&i.hasOwnProperty(o)&&(n[o]=i[o])}t.init&&t.init.call(this,e)};u(e,Pn);for(var i in t)"style"!==i&&"shape"!==i&&(e.prototype[i]=t[i]);return e},u(Pn,di);var XS=ES.CMD,jS=[[],[],[]],YS=Math.sqrt,qS=Math.atan2,KS=function(t,e){var i,n,o,a,r,s,l=t.data,u=XS.M,h=XS.C,c=XS.L,d=XS.R,f=XS.A,p=XS.Q;for(o=0,a=0;o<l.length;){switch(i=l[o++],a=o,n=0,i){case u:case c:n=1;break;case h:n=3;break;case p:n=2;break;case f:var g=e[4],m=e[5],v=YS(e[0]*e[0]+e[1]*e[1]),y=YS(e[2]*e[2]+e[3]*e[3]),x=qS(-e[1]/y,e[0]/v);l[o]*=v,l[o++]+=g,l[o]*=y,l[o++]+=m,l[o++]*=v,l[o++]*=y,l[o++]+=x,l[o++]+=x,a=o+=2;break;case d:s[0]=l[o++],s[1]=l[o++],Q(s,s,e),l[a++]=s[0],l[a++]=s[1],s[0]+=l[o++],s[1]+=l[o++],Q(s,s,e),l[a++]=s[0],l[a++]=s[1]}for(r=0;r<n;r++)(s=jS[r])[0]=l[o++],s[1]=l[o++],Q(s,s,e),l[a++]=s[0],l[a++]=s[1]}},$S=Math.sqrt,JS=Math.sin,QS=Math.cos,tM=Math.PI,eM=function(t){return Math.sqrt(t[0]*t[0]+t[1]*t[1])},iM=function(t,e){return(t[0]*e[0]+t[1]*e[1])/(eM(t)*eM(e))},nM=function(t,e){return(t[0]*e[1]<t[1]*e[0]?-1:1)*Math.acos(iM(t,e))},oM=/([mlvhzcqtsa])([^mlvhzcqtsa]*)/gi,aM=/-?([0-9]*\.)?[0-9]+([eE]-?[0-9]+)?/g,rM=function(t){di.call(this,t)};rM.prototype={constructor:rM,type:"text",brush:function(t,e){var i=this.style;this.__dirty&&Ye(i),i.fill=i.stroke=i.shadowBlur=i.shadowColor=i.shadowOffsetX=i.shadowOffsetY=null;var n=i.text;null!=n&&(n+=""),ci(n,i)?(this.setTransform(t),Ke(this,t,n,i,null,e),this.restoreTransform(t)):t.__attrCachedBy=rb.NONE},getBoundingRect:function(){var t=this.style;if(this.__dirty&&Ye(t),!this._rect){var e=t.text;null!=e?e+="":e="";var i=ke(t.text+"",t.font,t.textAlign,t.textVerticalAlign,t.textPadding,t.textLineHeight,t.rich);if(i.x+=t.x||0,i.y+=t.y||0,si(t.textStroke,t.textStrokeWidth)){var n=t.textStrokeWidth;i.x-=n/2,i.y-=n/2,i.width+=n,i.height+=n}this._rect=i}return this._rect}},u(rM,di);var sM=Pn.extend({type:"circle",shape:{cx:0,cy:0,r:0},buildPath:function(t,e,i){i&&t.moveTo(e.cx+e.r,e.cy),t.arc(e.cx,e.cy,e.r,0,2*Math.PI,!0)}}),lM=[["shadowBlur",0],["shadowColor","#000"],["shadowOffsetX",0],["shadowOffsetY",0]],uM=function(t){return U_.browser.ie&&U_.browser.version>=11?function(){var e,i=this.__clipPaths,n=this.style;if(i)for(var o=0;o<i.length;o++){var a=i[o],r=a&&a.shape,s=a&&a.type;if(r&&("sector"===s&&r.startAngle===r.endAngle||"rect"===s&&(!r.width||!r.height))){for(l=0;l<lM.length;l++)lM[l][2]=n[lM[l][0]],n[lM[l][0]]=lM[l][1];e=!0;break}}if(t.apply(this,arguments),e)for(var l=0;l<lM.length;l++)n[lM[l][0]]=lM[l][2]}:t},hM=Pn.extend({type:"sector",shape:{cx:0,cy:0,r0:0,r:0,startAngle:0,endAngle:2*Math.PI,clockwise:!0},brush:uM(Pn.prototype.brush),buildPath:function(t,e){var i=e.cx,n=e.cy,o=Math.max(e.r0||0,0),a=Math.max(e.r,0),r=e.startAngle,s=e.endAngle,l=e.clockwise,u=Math.cos(r),h=Math.sin(r);t.moveTo(u*o+i,h*o+n),t.lineTo(u*a+i,h*a+n),t.arc(i,n,a,r,s,!l),t.lineTo(Math.cos(s)*o+i,Math.sin(s)*o+n),0!==o&&t.arc(i,n,o,s,r,l),t.closePath()}}),cM=Pn.extend({type:"ring",shape:{cx:0,cy:0,r:0,r0:0},buildPath:function(t,e){var i=e.cx,n=e.cy,o=2*Math.PI;t.moveTo(i+e.r,n),t.arc(i,n,e.r,0,o,!1),t.moveTo(i+e.r0,n),t.arc(i,n,e.r0,0,o,!0)}}),dM=function(t,e){for(var i=t.length,n=[],o=0,a=1;a<i;a++)o+=K(t[a-1],t[a]);var r=o/2;r=r<i?i:r;for(a=0;a<r;a++){var s,l,u,h=a/(r-1)*(e?i:i-1),c=Math.floor(h),d=h-c,f=t[c%i];e?(s=t[(c-1+i)%i],l=t[(c+1)%i],u=t[(c+2)%i]):(s=t[0===c?c:c-1],l=t[c>i-2?i-1:c+1],u=t[c>i-3?i-1:c+2]);var p=d*d,g=d*p;n.push([Bn(s[0],f[0],l[0],u[0],d,p,g),Bn(s[1],f[1],l[1],u[1],d,p,g)])}return n},fM=function(t,e,i,n){var o,a,r,s,l=[],u=[],h=[],c=[];if(n){r=[1/0,1/0],s=[-1/0,-1/0];for(var d=0,f=t.length;d<f;d++)tt(r,r,t[d]),et(s,s,t[d]);tt(r,r,n[0]),et(s,s,n[1])}for(var d=0,f=t.length;d<f;d++){var p=t[d];if(i)o=t[d?d-1:f-1],a=t[(d+1)%f];else{if(0===d||d===f-1){l.push(F(t[d]));continue}o=t[d-1],a=t[d+1]}U(u,a,o),Y(u,u,e);var g=K(p,o),m=K(p,a),v=g+m;0!==v&&(g/=v,m/=v),Y(h,u,-g),Y(c,u,m);var y=H([],p,h),x=H([],p,c);n&&(et(y,y,r),tt(y,y,s),et(x,x,r),tt(x,x,s)),l.push(y),l.push(x)}return i&&l.push(l.shift()),l},pM=Pn.extend({type:"polygon",shape:{points:null,smooth:!1,smoothConstraint:null},buildPath:function(t,e){Vn(t,e,!0)}}),gM=Pn.extend({type:"polyline",shape:{points:null,smooth:!1,smoothConstraint:null},style:{stroke:"#000",fill:null},buildPath:function(t,e){Vn(t,e,!1)}}),mM=Math.round,vM={},yM=Pn.extend({type:"rect",shape:{r:0,x:0,y:0,width:0,height:0},buildPath:function(t,e){var i,n,o,a;this.subPixelOptimize?(Fn(vM,e,this.style),i=vM.x,n=vM.y,o=vM.width,a=vM.height,vM.r=e.r,e=vM):(i=e.x,n=e.y,o=e.width,a=e.height),e.r?je(t,e):t.rect(i,n,o,a),t.closePath()}}),xM={},_M=Pn.extend({type:"line",shape:{x1:0,y1:0,x2:0,y2:0,percent:1},style:{stroke:"#000",fill:null},buildPath:function(t,e){var i,n,o,a;this.subPixelOptimize?(Gn(xM,e,this.style),i=xM.x1,n=xM.y1,o=xM.x2,a=xM.y2):(i=e.x1,n=e.y1,o=e.x2,a=e.y2);var r=e.percent;0!==r&&(t.moveTo(i,n),r<1&&(o=i*(1-r)+o*r,a=n*(1-r)+a*r),t.lineTo(o,a))},pointAt:function(t){var e=this.shape;return[e.x1*(1-t)+e.x2*t,e.y1*(1-t)+e.y2*t]}}),wM=[],bM=Pn.extend({type:"bezier-curve",shape:{x1:0,y1:0,x2:0,y2:0,cpx1:0,cpy1:0,percent:1},style:{stroke:"#000",fill:null},buildPath:function(t,e){var i=e.x1,n=e.y1,o=e.x2,a=e.y2,r=e.cpx1,s=e.cpy1,l=e.cpx2,u=e.cpy2,h=e.percent;0!==h&&(t.moveTo(i,n),null==l||null==u?(h<1&&(cn(i,r,o,h,wM),r=wM[1],o=wM[2],cn(n,s,a,h,wM),s=wM[1],a=wM[2]),t.quadraticCurveTo(r,s,o,a)):(h<1&&(an(i,r,l,o,h,wM),r=wM[1],l=wM[2],o=wM[3],an(n,s,u,a,h,wM),s=wM[1],u=wM[2],a=wM[3]),t.bezierCurveTo(r,s,l,u,o,a)))},pointAt:function(t){return Hn(this.shape,t,!1)},tangentAt:function(t){var e=Hn(this.shape,t,!0);return q(e,e)}}),SM=Pn.extend({type:"arc",shape:{cx:0,cy:0,r:0,startAngle:0,endAngle:2*Math.PI,clockwise:!0},style:{stroke:"#000",fill:null},buildPath:function(t,e){var i=e.cx,n=e.cy,o=Math.max(e.r,0),a=e.startAngle,r=e.endAngle,s=e.clockwise,l=Math.cos(a),u=Math.sin(a);t.moveTo(l*o+i,u*o+n),t.arc(i,n,o,a,r,!s)}}),MM=Pn.extend({type:"compound",shape:{paths:null},_updatePathDirty:function(){for(var t=this.__dirtyPath,e=this.shape.paths,i=0;i<e.length;i++)t=t||e[i].__dirtyPath;this.__dirtyPath=t,this.__dirty=this.__dirty||t},beforeBrush:function(){this._updatePathDirty();for(var t=this.shape.paths||[],e=this.getGlobalScale(),i=0;i<t.length;i++)t[i].path||t[i].createPathProxy(),t[i].path.setScale(e[0],e[1])},buildPath:function(t,e){for(var i=e.paths||[],n=0;n<i.length;n++)i[n].buildPath(t,i[n].shape,!0)},afterBrush:function(){for(var t=this.shape.paths||[],e=0;e<t.length;e++)t[e].__dirtyPath=!1},getBoundingRect:function(){return this._updatePathDirty(),Pn.prototype.getBoundingRect.call(this)}}),IM=function(t){this.colorStops=t||[]};IM.prototype={constructor:IM,addColorStop:function(t,e){this.colorStops.push({offset:t,color:e})}};var TM=function(t,e,i,n,o,a){this.x=null==t?0:t,this.y=null==e?0:e,this.x2=null==i?1:i,this.y2=null==n?0:n,this.type="linear",this.global=a||!1,IM.call(this,o)};TM.prototype={constructor:TM},u(TM,IM);var AM=function(t,e,i,n,o){this.x=null==t?.5:t,this.y=null==e?.5:e,this.r=null==i?.5:i,this.type="radial",this.global=o||!1,IM.call(this,n)};AM.prototype={constructor:AM},u(AM,IM),Zn.prototype.incremental=!0,Zn.prototype.clearDisplaybles=function(){this._displayables=[],this._temporaryDisplayables=[],this._cursor=0,this.dirty(),this.notClear=!1},Zn.prototype.addDisplayable=function(t,e){e?this._temporaryDisplayables.push(t):this._displayables.push(t),this.dirty()},Zn.prototype.addDisplayables=function(t,e){e=e||!1;for(var i=0;i<t.length;i++)this.addDisplayable(t[i],e)},Zn.prototype.eachPendingDisplayable=function(t){for(e=this._cursor;e<this._displayables.length;e++)t&&t(this._displayables[e]);for(var e=0;e<this._temporaryDisplayables.length;e++)t&&t(this._temporaryDisplayables[e])},Zn.prototype.update=function(){this.updateTransform();for(t=this._cursor;t<this._displayables.length;t++)(e=this._displayables[t]).parent=this,e.update(),e.parent=null;for(var t=0;t<this._temporaryDisplayables.length;t++){var e=this._temporaryDisplayables[t];e.parent=this,e.update(),e.parent=null}},Zn.prototype.brush=function(t,e){for(i=this._cursor;i<this._displayables.length;i++)(n=this._displayables[i]).beforeBrush&&n.beforeBrush(t),n.brush(t,i===this._cursor?null:this._displayables[i-1]),n.afterBrush&&n.afterBrush(t);this._cursor=i;for(var i=0;i<this._temporaryDisplayables.length;i++){var n=this._temporaryDisplayables[i];n.beforeBrush&&n.beforeBrush(t),n.brush(t,0===i?null:this._temporaryDisplayables[i-1]),n.afterBrush&&n.afterBrush(t)}this._temporaryDisplayables=[],this.notClear=!0};var DM=[];Zn.prototype.getBoundingRect=function(){if(!this._rect){for(var t=new de(1/0,1/0,-1/0,-1/0),e=0;e<this._displayables.length;e++){var i=this._displayables[e],n=i.getBoundingRect().clone();i.needLocalTransform()&&n.applyTransform(i.getLocalTransform(DM)),t.union(n)}this._rect=t}return this._rect},Zn.prototype.contain=function(t,e){var i=this.transformCoordToLocal(t,e);if(this.getBoundingRect().contain(i[0],i[1]))for(var n=0;n<this._displayables.length;n++)if(this._displayables[n].contain(t,e))return!0;return!1},u(Zn,di);var CM=Math.round,LM=Math.max,kM=Math.min,PM={},NM=1,OM=function(t,e){for(var i=[],n=t.length,o=0;o<n;o++){var a=t[o];a.path||a.createPathProxy(),a.__dirtyPath&&a.buildPath(a.path,a.shape,!0),i.push(a.path)}var r=new Pn(e);return r.createPathProxy(),r.buildPath=function(t){t.appendPath(i);var e=t.getContext();e&&t.rebuildPath(e)},r},EM=R(),RM=0,zM=(Object.freeze||Object)({Z2_EMPHASIS_LIFT:NM,extendShape:Un,extendPath:function(t,e){return zn(t,e)},makePath:Xn,makeImage:jn,mergePath:OM,resizePath:qn,subPixelOptimizeLine:Kn,subPixelOptimizeRect:$n,subPixelOptimize:Jn,setElementHoverStyle:ro,isInEmphasis:so,setHoverStyle:fo,setAsHoverStyleTrigger:po,setLabelStyle:go,setTextStyle:mo,setText:function(t,e,i){var n,o={isRectText:!0};!1===i?n=!0:o.autoColor=i,vo(t,e,o,n)},getFont:So,updateProps:Io,initProps:To,getTransform:Ao,applyTransform:Do,transformDirection:Co,groupTransition:Lo,clipPointsByRect:ko,clipRectByRect:function(t,e){var i=LM(t.x,e.x),n=kM(t.x+t.width,e.x+e.width),o=LM(t.y,e.y),a=kM(t.y+t.height,e.y+e.height);if(n>=i&&a>=o)return{x:i,y:o,width:n-i,height:a-o}},createIcon:Po,Group:tb,Image:fi,Text:rM,Circle:sM,Sector:hM,Ring:cM,Polygon:pM,Polyline:gM,Rect:yM,Line:_M,BezierCurve:bM,Arc:SM,IncrementalDisplayable:Zn,CompoundPath:MM,LinearGradient:TM,RadialGradient:AM,BoundingRect:de}),BM=["textStyle","color"],VM={getTextColor:function(t){var e=this.ecModel;return this.getShallow("color")||(!t&&e?e.get(BM):null)},getFont:function(){return So({fontStyle:this.getShallow("fontStyle"),fontWeight:this.getShallow("fontWeight"),fontSize:this.getShallow("fontSize"),fontFamily:this.getShallow("fontFamily")},this.ecModel)},getTextRect:function(t){return ke(t,this.getFont(),this.getShallow("align"),this.getShallow("verticalAlign")||this.getShallow("baseline"),this.getShallow("padding"),this.getShallow("lineHeight"),this.getShallow("rich"),this.getShallow("truncateText"))}},GM=Qb([["fill","color"],["stroke","borderColor"],["lineWidth","borderWidth"],["opacity"],["shadowBlur"],["shadowOffsetX"],["shadowOffsetY"],["shadowColor"],["textPosition"],["textAlign"]]),FM={getItemStyle:function(t,e){var i=GM(this,t,e),n=this.getBorderLineDash();return n&&(i.lineDash=n),i},getBorderLineDash:function(){var t=this.get("borderType");return"solid"===t||null==t?null:"dashed"===t?[5,5]:[1,1]}},WM=h,HM=Bi();No.prototype={constructor:No,init:null,mergeOption:function(t){n(this.option,t,!0)},get:function(t,e){return null==t?this.option:Oo(this.option,this.parsePath(t),!e&&Eo(this,t))},getShallow:function(t,e){var i=this.option,n=null==i?i:i[t],o=!e&&Eo(this,t);return null==n&&o&&(n=o.getShallow(t)),n},getModel:function(t,e){var i,n=null==t?this.option:Oo(this.option,t=this.parsePath(t));return e=e||(i=Eo(this,t))&&i.getModel(t),new No(n,e,this.ecModel)},isEmpty:function(){return null==this.option},restoreData:function(){},clone:function(){return new(0,this.constructor)(i(this.option))},setReadOnly:function(t){},parsePath:function(t){return"string"==typeof t&&(t=t.split(".")),t},customizeGetParent:function(t){HM(this).getParent=t},isAnimationEnabled:function(){if(!U_.node){if(null!=this.option.animation)return!!this.option.animation;if(this.parentModel)return this.parentModel.isAnimationEnabled()}}},ji(No),Yi(No),WM(No,eS),WM(No,nS),WM(No,VM),WM(No,FM);var ZM=0,UM=1e-4,XM=9007199254740991,jM=/^(?:(\d{4})(?:[-\/](\d{1,2})(?:[-\/](\d{1,2})(?:[T ](\d{1,2})(?::(\d\d)(?::(\d\d)(?:[.,](\d+))?)?)?(Z|[\+\-]\d\d:?\d\d)?)?)?)?)?$/,YM=(Object.freeze||Object)({linearMap:Bo,parsePercent:Vo,round:Go,asc:Fo,getPrecision:Wo,getPrecisionSafe:Ho,getPixelPrecision:Zo,getPercentWithPrecision:Uo,MAX_SAFE_INTEGER:XM,remRadian:Xo,isRadianAroundZero:jo,parseDate:Yo,quantity:qo,nice:$o,quantile:function(t,e){var i=(t.length-1)*e+1,n=Math.floor(i),o=+t[n-1],a=i-n;return a?o+a*(t[n]-o):o},reformIntervals:Jo,isNumeric:Qo}),qM=L,KM=/([&<>"'])/g,$M={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"},JM=["a","b","c","d","e","f","g"],QM=function(t,e){return"{"+t+(null==e?"":e)+"}"},tI=ze,eI=(Object.freeze||Object)({addCommas:ta,toCamelCase:ea,normalizeCssArray:qM,encodeHTML:ia,formatTpl:na,formatTplSimple:oa,getTooltipMarker:aa,formatTime:sa,capitalFirst:la,truncateText:tI,getTextBoundingRect:function(t){return ke(t.text,t.font,t.textAlign,t.textVerticalAlign,t.textPadding,t.textLineHeight,t.rich,t.truncate)},getTextRect:function(t,e,i,n,o,a,r,s){return ke(t,e,i,n,o,s,a,r)}}),iI=d,nI=["left","right","top","bottom","width","height"],oI=[["width","left","right"],["height","top","bottom"]],aI=ua,rI=(v(ua,"vertical"),v(ua,"horizontal"),{getBoxLayoutParams:function(){return{left:this.get("left"),top:this.get("top"),right:this.get("right"),bottom:this.get("bottom"),width:this.get("width"),height:this.get("height")}}}),sI=Bi(),lI=No.extend({type:"component",id:"",name:"",mainType:"",subType:"",componentIndex:0,defaultOption:null,ecModel:null,dependentModels:[],uid:null,layoutMode:null,$constructor:function(t,e,i,n){No.call(this,t,e,i,n),this.uid=Ro("ec_cpt_model")},init:function(t,e,i,n){this.mergeDefaultAndTheme(t,i)},mergeDefaultAndTheme:function(t,e){var i=this.layoutMode,o=i?ga(t):{};n(t,e.getTheme().get(this.mainType)),n(t,this.getDefaultOption()),i&&pa(t,o,i)},mergeOption:function(t,e){n(this.option,t,!0);var i=this.layoutMode;i&&pa(this.option,t,i)},optionUpdated:function(t,e){},getDefaultOption:function(){var t=sI(this);if(!t.defaultOption){for(var e=[],i=this.constructor;i;){var o=i.prototype.defaultOption;o&&e.push(o),i=i.superClass}for(var a={},r=e.length-1;r>=0;r--)a=n(a,e[r],!0);t.defaultOption=a}return t.defaultOption},getReferringComponents:function(t){return this.ecModel.queryComponents({mainType:t,index:this.get(t+"Index",!0),id:this.get(t+"Id",!0)})}});$i(lI,{registerWhenExtend:!0}),function(t){var e={};t.registerSubTypeDefaulter=function(t,i){t=Ui(t),e[t.main]=i},t.determineSubType=function(i,n){var o=n.type;if(!o){var a=Ui(i).main;t.hasSubTypes(i)&&e[a]&&(o=e[a](n))}return o}}(lI),function(t,e){function i(t){var i={},a=[];return d(t,function(r){var s=n(i,r),u=o(s.originalDeps=e(r),t);s.entryCount=u.length,0===s.entryCount&&a.push(r),d(u,function(t){l(s.predecessor,t)<0&&s.predecessor.push(t);var e=n(i,t);l(e.successor,t)<0&&e.successor.push(r)})}),{graph:i,noEntryList:a}}function n(t,e){return t[e]||(t[e]={predecessor:[],successor:[]}),t[e]}function o(t,e){var i=[];return d(t,function(t){l(e,t)>=0&&i.push(t)}),i}t.topologicalTravel=function(t,e,n,o){function a(t){s[t].entryCount--,0===s[t].entryCount&&l.push(t)}if(t.length){var r=i(e),s=r.graph,l=r.noEntryList,u={};for(d(t,function(t){u[t]=!0});l.length;){var h=l.pop(),c=s[h],f=!!u[h];f&&(n.call(o,h,c.originalDeps.slice()),delete u[h]),d(c.successor,f?function(t){u[t]=!0,a(t)}:a)}d(u,function(){throw new Error("Circle dependency may exists")})}}}(lI,function(t){var e=[];return d(lI.getClassesByMainType(t),function(t){e=e.concat(t.prototype.dependencies||[])}),e=f(e,function(t){return Ui(t).main}),"dataset"!==t&&l(e,"dataset")<=0&&e.unshift("dataset"),e}),h(lI,rI);var uI="";"undefined"!=typeof navigator&&(uI=navigator.platform||"");var hI={color:["#c23531","#2f4554","#61a0a8","#d48265","#91c7ae","#749f83","#ca8622","#bda29a","#6e7074","#546570","#c4ccd3"],gradientColor:["#f6efa6","#d88273","#bf444c"],textStyle:{fontFamily:uI.match(/^Win/)?"Microsoft YaHei":"sans-serif",fontSize:12,fontStyle:"normal",fontWeight:"normal"},blendMode:null,animation:"auto",animationDuration:1e3,animationDurationUpdate:300,animationEasing:"exponentialOut",animationEasingUpdate:"cubicOut",animationThreshold:2e3,progressiveThreshold:3e3,progressive:400,hoverLayerThreshold:3e3,useUTC:!1},cI=Bi(),dI={clearColorPalette:function(){cI(this).colorIdx=0,cI(this).colorNameMap={}},getColorFromPalette:function(t,e,i){var n=cI(e=e||this),o=n.colorIdx||0,a=n.colorNameMap=n.colorNameMap||{};if(a.hasOwnProperty(t))return a[t];var r=Di(this.get("color",!0)),s=this.get("colorLayer",!0),l=null!=i&&s?va(s,i):r;if((l=l||r)&&l.length){var u=l[o];return t&&(a[t]=u),n.colorIdx=(o+1)%l.length,u}}},fI={cartesian2d:function(t,e,i,n){var o=t.getReferringComponents("xAxis")[0],a=t.getReferringComponents("yAxis")[0];e.coordSysDims=["x","y"],i.set("x",o),i.set("y",a),xa(o)&&(n.set("x",o),e.firstCategoryDimIndex=0),xa(a)&&(n.set("y",a),e.firstCategoryDimIndex=1)},singleAxis:function(t,e,i,n){var o=t.getReferringComponents("singleAxis")[0];e.coordSysDims=["single"],i.set("single",o),xa(o)&&(n.set("single",o),e.firstCategoryDimIndex=0)},polar:function(t,e,i,n){var o=t.getReferringComponents("polar")[0],a=o.findAxisModel("radiusAxis"),r=o.findAxisModel("angleAxis");e.coordSysDims=["radius","angle"],i.set("radius",a),i.set("angle",r),xa(a)&&(n.set("radius",a),e.firstCategoryDimIndex=0),xa(r)&&(n.set("angle",r),e.firstCategoryDimIndex=1)},geo:function(t,e,i,n){e.coordSysDims=["lng","lat"]},parallel:function(t,e,i,n){var o=t.ecModel,a=o.getComponent("parallel",t.get("parallelIndex")),r=e.coordSysDims=a.dimensions.slice();d(a.parallelAxisIndex,function(t,a){var s=o.getComponent("parallelAxis",t),l=r[a];i.set(l,s),xa(s)&&null==e.firstCategoryDimIndex&&(n.set(l,s),e.firstCategoryDimIndex=a)})}},pI="original",gI="arrayRows",mI="objectRows",vI="keyedColumns",yI="unknown",xI="typedArray",_I="column",wI="row";_a.seriesDataToSource=function(t){return new _a({data:t,sourceFormat:S(t)?xI:pI,fromDataset:!1})},Yi(_a);var bI=Bi(),SI="\0_ec_inner",MI=No.extend({init:function(t,e,i,n){i=i||{},this.option=null,this._theme=new No(i),this._optionManager=n},setOption:function(t,e){k(!(SI in t),"please use chart.getOption()"),this._optionManager.setOption(t,e),this.resetOption(null)},resetOption:function(t){var e=!1,i=this._optionManager;if(!t||"recreate"===t){var n=i.mountOption("recreate"===t);this.option&&"recreate"!==t?(this.restoreData(),this.mergeOption(n)):Ea.call(this,n),e=!0}if("timeline"!==t&&"media"!==t||this.restoreData(),!t||"recreate"===t||"timeline"===t){var o=i.getTimelineOption(this);o&&(this.mergeOption(o),e=!0)}if(!t||"recreate"===t||"media"===t){var a=i.getMediaOption(this,this._api);a.length&&d(a,function(t){this.mergeOption(t,e=!0)},this)}return e},mergeOption:function(t){var e=this.option,o=this._componentsMap,r=[];Sa(this),d(t,function(t,o){null!=t&&(lI.hasClass(o)?o&&r.push(o):e[o]=null==e[o]?i(t):n(e[o],t,!0))}),lI.topologicalTravel(r,lI.getAllClassMainTypes(),function(i,n){var r=Di(t[i]),s=Pi(o.get(i),r);Ni(s),d(s,function(t,e){var n=t.option;w(n)&&(t.keyInfo.mainType=i,t.keyInfo.subType=za(i,n,t.exist))});var l=Ra(o,n);e[i]=[],o.set(i,[]),d(s,function(t,n){var r=t.exist,s=t.option;if(k(w(s)||r,"Empty component definition"),s){var u=lI.getClass(i,t.keyInfo.subType,!0);if(r&&r instanceof u)r.name=t.keyInfo.name,r.mergeOption(s,this),r.optionUpdated(s,!1);else{var h=a({dependentModels:l,componentIndex:n},t.keyInfo);a(r=new u(s,this,this,h),h),r.init(s,this,this,h),r.optionUpdated(null,!0)}}else r.mergeOption({},this),r.optionUpdated({},!1);o.get(i)[n]=r,e[i][n]=r.option},this),"series"===i&&Ba(this,o.get("series"))},this),this._seriesIndicesMap=R(this._seriesIndices=this._seriesIndices||[])},getOption:function(){var t=i(this.option);return d(t,function(e,i){if(lI.hasClass(i)){for(var n=(e=Di(e)).length-1;n>=0;n--)Ei(e[n])&&e.splice(n,1);t[i]=e}}),delete t[SI],t},getTheme:function(){return this._theme},getComponent:function(t,e){var i=this._componentsMap.get(t);if(i)return i[e||0]},queryComponents:function(t){var e=t.mainType;if(!e)return[];var i=t.index,n=t.id,o=t.name,a=this._componentsMap.get(e);if(!a||!a.length)return[];var r;if(null!=i)y(i)||(i=[i]),r=g(f(i,function(t){return a[t]}),function(t){return!!t});else if(null!=n){var s=y(n);r=g(a,function(t){return s&&l(n,t.id)>=0||!s&&t.id===n})}else if(null!=o){var u=y(o);r=g(a,function(t){return u&&l(o,t.name)>=0||!u&&t.name===o})}else r=a.slice();return Va(r,t)},findComponents:function(t){var e=t.query,i=t.mainType,n=function(t){var e=i+"Index",n=i+"Id",o=i+"Name";return!t||null==t[e]&&null==t[n]&&null==t[o]?null:{mainType:i,index:t[e],id:t[n],name:t[o]}}(e);return function(e){return t.filter?g(e,t.filter):e}(Va(n?this.queryComponents(n):this._componentsMap.get(i),t))},eachComponent:function(t,e,i){var n=this._componentsMap;"function"==typeof t?(i=e,e=t,n.each(function(t,n){d(t,function(t,o){e.call(i,n,t,o)})})):_(t)?d(n.get(t),e,i):w(t)&&d(this.findComponents(t),e,i)},getSeriesByName:function(t){return g(this._componentsMap.get("series"),function(e){return e.name===t})},getSeriesByIndex:function(t){return this._componentsMap.get("series")[t]},getSeriesByType:function(t){return g(this._componentsMap.get("series"),function(e){return e.subType===t})},getSeries:function(){return this._componentsMap.get("series").slice()},getSeriesCount:function(){return this._componentsMap.get("series").length},eachSeries:function(t,e){d(this._seriesIndices,function(i){var n=this._componentsMap.get("series")[i];t.call(e,n,i)},this)},eachRawSeries:function(t,e){d(this._componentsMap.get("series"),t,e)},eachSeriesByType:function(t,e,i){d(this._seriesIndices,function(n){var o=this._componentsMap.get("series")[n];o.subType===t&&e.call(i,o,n)},this)},eachRawSeriesByType:function(t,e,i){return d(this.getSeriesByType(t),e,i)},isSeriesFiltered:function(t){return null==this._seriesIndicesMap.get(t.componentIndex)},getCurrentSeriesIndices:function(){return(this._seriesIndices||[]).slice()},filterSeries:function(t,e){Ba(this,g(this._componentsMap.get("series"),t,e))},restoreData:function(t){var e=this._componentsMap;Ba(this,e.get("series"));var i=[];e.each(function(t,e){i.push(e)}),lI.topologicalTravel(i,lI.getAllClassMainTypes(),function(i,n){d(e.get(i),function(e){("series"!==i||!Na(e,t))&&e.restoreData()})})}});h(MI,dI);var II=["getDom","getZr","getWidth","getHeight","getDevicePixelRatio","dispatchAction","isDisposed","on","off","getDataURL","getConnectedDataURL","getModel","getOption","getViewOfComponentModel","getViewOfSeriesModel"],TI={};Fa.prototype={constructor:Fa,create:function(t,e){var i=[];d(TI,function(n,o){var a=n.create(t,e);i=i.concat(a||[])}),this._coordinateSystems=i},update:function(t,e){d(this._coordinateSystems,function(i){i.update&&i.update(t,e)})},getCoordinateSystems:function(){return this._coordinateSystems.slice()}},Fa.register=function(t,e){TI[t]=e},Fa.get=function(t){return TI[t]};var AI=d,DI=i,CI=f,LI=n,kI=/^(min|max)?(.+)$/;Wa.prototype={constructor:Wa,setOption:function(t,e){t&&d(Di(t.series),function(t){t&&t.data&&S(t.data)&&N(t.data)}),t=DI(t,!0);var i=this._optionBackup,n=Ha.call(this,t,e,!i);this._newBaseOption=n.baseOption,i?(ja(i.baseOption,n.baseOption),n.timelineOptions.length&&(i.timelineOptions=n.timelineOptions),n.mediaList.length&&(i.mediaList=n.mediaList),n.mediaDefault&&(i.mediaDefault=n.mediaDefault)):this._optionBackup=n},mountOption:function(t){var e=this._optionBackup;return this._timelineOptions=CI(e.timelineOptions,DI),this._mediaList=CI(e.mediaList,DI),this._mediaDefault=DI(e.mediaDefault),this._currentMediaIndices=[],DI(t?e.baseOption:this._newBaseOption)},getTimelineOption:function(t){var e,i=this._timelineOptions;if(i.length){var n=t.getComponent("timeline");n&&(e=DI(i[n.getCurrentIndex()],!0))}return e},getMediaOption:function(t){var e=this._api.getWidth(),i=this._api.getHeight(),n=this._mediaList,o=this._mediaDefault,a=[],r=[];if(!n.length&&!o)return r;for(var s=0,l=n.length;s<l;s++)Za(n[s].query,e,i)&&a.push(s);return!a.length&&o&&(a=[-1]),a.length&&!Xa(a,this._currentMediaIndices)&&(r=CI(a,function(t){return DI(-1===t?o.option:n[t].option)})),this._currentMediaIndices=a,r}};var PI=d,NI=w,OI=["areaStyle","lineStyle","nodeStyle","linkStyle","chordStyle","label","labelLine"],EI=function(t,e){PI(tr(t.series),function(t){NI(t)&&Qa(t)});var i=["xAxis","yAxis","radiusAxis","angleAxis","singleAxis","parallelAxis","radar"];e&&i.push("valueAxis","categoryAxis","logAxis","timeAxis"),PI(i,function(e){PI(tr(t[e]),function(t){t&&($a(t,"axisLabel"),$a(t.axisPointer,"label"))})}),PI(tr(t.parallel),function(t){var e=t&&t.parallelAxisDefault;$a(e,"axisLabel"),$a(e&&e.axisPointer,"label")}),PI(tr(t.calendar),function(t){qa(t,"itemStyle"),$a(t,"dayLabel"),$a(t,"monthLabel"),$a(t,"yearLabel")}),PI(tr(t.radar),function(t){$a(t,"name")}),PI(tr(t.geo),function(t){NI(t)&&(Ja(t),PI(tr(t.regions),function(t){Ja(t)}))}),PI(tr(t.timeline),function(t){Ja(t),qa(t,"label"),qa(t,"itemStyle"),qa(t,"controlStyle",!0);var e=t.data;y(e)&&d(e,function(t){w(t)&&(qa(t,"label"),qa(t,"itemStyle"))})}),PI(tr(t.toolbox),function(t){qa(t,"iconStyle"),PI(t.feature,function(t){qa(t,"iconStyle")})}),$a(er(t.axisPointer),"label"),$a(er(t.tooltip).axisPointer,"label")},RI=[["x","left"],["y","top"],["x2","right"],["y2","bottom"]],zI=["grid","geo","parallel","legend","toolbox","title","visualMap","dataZoom","timeline"],BI=function(t,e){EI(t,e),t.series=Di(t.series),d(t.series,function(t){if(w(t)){var e=t.type;if("pie"!==e&&"gauge"!==e||null!=t.clockWise&&(t.clockwise=t.clockWise),"gauge"===e){var i=ir(t,"pointer.color");null!=i&&nr(t,"itemStyle.normal.color",i)}or(t)}}),t.dataRange&&(t.visualMap=t.dataRange),d(zI,function(e){var i=t[e];i&&(y(i)||(i=[i]),d(i,function(t){or(t)}))})},VI=rr.prototype;VI.pure=!1,VI.persistent=!0,VI.getSource=function(){return this._source};var GI={arrayRows_column:{pure:!0,count:function(){return Math.max(0,this._data.length-this._source.startIndex)},getItem:function(t){return this._data[t+this._source.startIndex]},appendData:ur},arrayRows_row:{pure:!0,count:function(){var t=this._data[0];return t?Math.max(0,t.length-this._source.startIndex):0},getItem:function(t){t+=this._source.startIndex;for(var e=[],i=this._data,n=0;n<i.length;n++){var o=i[n];e.push(o?o[t]:null)}return e},appendData:function(){throw new Error('Do not support appendData when set seriesLayoutBy: "row".')}},objectRows:{pure:!0,count:sr,getItem:lr,appendData:ur},keyedColumns:{pure:!0,count:function(){var t=this._source.dimensionsDefine[0].name,e=this._data[t];return e?e.length:0},getItem:function(t){for(var e=[],i=this._source.dimensionsDefine,n=0;n<i.length;n++){var o=this._data[i[n].name];e.push(o?o[t]:null)}return e},appendData:function(t){var e=this._data;d(t,function(t,i){for(var n=e[i]||(e[i]=[]),o=0;o<(t||[]).length;o++)n.push(t[o])})}},original:{count:sr,getItem:lr,appendData:ur},typedArray:{persistent:!1,pure:!0,count:function(){return this._data?this._data.length/this._dimSize:0},getItem:function(t,e){t-=this._offset,e=e||[];for(var i=this._dimSize*t,n=0;n<this._dimSize;n++)e[n]=this._data[i+n];return e},appendData:function(t){this._data=t},clean:function(){this._offset+=this.count(),this._data=null}}},FI={arrayRows:hr,objectRows:function(t,e,i,n){return null!=i?t[n]:t},keyedColumns:hr,original:function(t,e,i,n){var o=Li(t);return null!=i&&o instanceof Array?o[i]:o},typedArray:hr},WI={arrayRows:cr,objectRows:function(t,e,i,n){return dr(t[e],this._dimensionInfos[e])},keyedColumns:cr,original:function(t,e,i,n){var o=t&&(null==t.value?t:t.value);return!this._rawData.pure&&ki(t)&&(this.hasItemOption=!0),dr(o instanceof Array?o[n]:o,this._dimensionInfos[e])},typedArray:function(t,e,i,n){return t[n]}},HI=/\{@(.+?)\}/g,ZI={getDataParams:function(t,e){var i=this.getData(e),n=this.getRawValue(t,e),o=i.getRawIndex(t),a=i.getName(t),r=i.getRawDataItem(t),s=i.getItemVisual(t,"color"),l=this.ecModel.getComponent("tooltip"),u=Hi(l&&l.get("renderMode")),h=this.mainType,c="series"===h;return{componentType:h,componentSubType:this.subType,componentIndex:this.componentIndex,seriesType:c?this.subType:null,seriesIndex:this.seriesIndex,seriesId:c?this.id:null,seriesName:c?this.name:null,name:a,dataIndex:o,data:r,dataType:e,value:n,color:s,marker:aa({color:s,renderMode:u}),$vars:["seriesName","name","value"]}},getFormattedLabel:function(t,e,i,n,o){e=e||"normal";var a=this.getData(i),r=a.getItemModel(t),s=this.getDataParams(t,i);null!=n&&s.value instanceof Array&&(s.value=s.value[n]);var l=r.get("normal"===e?[o||"label","formatter"]:[e,o||"label","formatter"]);return"function"==typeof l?(s.status=e,l(s)):"string"==typeof l?na(l,s).replace(HI,function(e,i){var n=i.length;return"["===i.charAt(0)&&"]"===i.charAt(n-1)&&(i=+i.slice(1,n-1)),fr(a,t,i)}):void 0},getRawValue:function(t,e){return fr(this.getData(e),t)},formatTooltip:function(){}},UI=mr.prototype;UI.perform=function(t){function e(t){return!(t>=1)&&(t=1),t}var i=this._upstream,n=t&&t.skip;if(this._dirty&&i){var o=this.context;o.data=o.outputData=i.context.outputData}this.__pipeline&&(this.__pipeline.currentTask=this);var a;this._plan&&!n&&(a=this._plan(this.context));var r=e(this._modBy),s=this._modDataCount||0,l=e(t&&t.modBy),u=t&&t.modDataCount||0;r===l&&s===u||(a="reset");var h;(this._dirty||"reset"===a)&&(this._dirty=!1,h=yr(this,n)),this._modBy=l,this._modDataCount=u;var c=t&&t.step;if(this._dueEnd=i?i._outputDueEnd:this._count?this._count(this.context):1/0,this._progress){var d=this._dueIndex,f=Math.min(null!=c?this._dueIndex+c:1/0,this._dueEnd);if(!n&&(h||d<f)){var p=this._progress;if(y(p))for(var g=0;g<p.length;g++)vr(this,p[g],d,f,l,u);else vr(this,p,d,f,l,u)}this._dueIndex=f;var m=null!=this._settedOutputEnd?this._settedOutputEnd:f;this._outputDueEnd=m}else this._dueIndex=this._outputDueEnd=null!=this._settedOutputEnd?this._settedOutputEnd:this._dueEnd;return this.unfinished()};var XI=function(){function t(){return n<i?n++:null}function e(){var t=n%r*o+Math.ceil(n/r),e=n>=i?null:t<a?t:n;return n++,e}var i,n,o,a,r,s={reset:function(l,u,h,c){n=l,i=u,o=h,a=c,r=Math.ceil(a/o),s.next=o>1&&a>0?e:t}};return s}();UI.dirty=function(){this._dirty=!0,this._onDirty&&this._onDirty(this.context)},UI.unfinished=function(){return this._progress&&this._dueIndex<this._dueEnd},UI.pipe=function(t){(this._downstream!==t||this._dirty)&&(this._downstream=t,t._upstream=this,t.dirty())},UI.dispose=function(){this._disposed||(this._upstream&&(this._upstream._downstream=null),this._downstream&&(this._downstream._upstream=null),this._dirty=!1,this._disposed=!0)},UI.getUpstream=function(){return this._upstream},UI.getDownstream=function(){return this._downstream},UI.setOutputEnd=function(t){this._outputDueEnd=this._settedOutputEnd=t};var jI=Bi(),YI=lI.extend({type:"series.__base__",seriesIndex:0,coordinateSystem:null,defaultOption:null,legendDataProvider:null,visualColorAccessPath:"itemStyle.color",layoutMode:null,init:function(t,e,i,n){this.seriesIndex=this.componentIndex,this.dataTask=gr({count:wr,reset:br}),this.dataTask.context={model:this},this.mergeDefaultAndTheme(t,i),Ma(this);var o=this.getInitialData(t,i);Mr(o,this),this.dataTask.context.data=o,jI(this).dataBeforeProcessed=o,xr(this)},mergeDefaultAndTheme:function(t,e){var i=this.layoutMode,o=i?ga(t):{},a=this.subType;lI.hasClass(a)&&(a+="Series"),n(t,e.getTheme().get(this.subType)),n(t,this.getDefaultOption()),Ci(t,"label",["show"]),this.fillDataTextStyle(t.data),i&&pa(t,o,i)},mergeOption:function(t,e){t=n(this.option,t,!0),this.fillDataTextStyle(t.data);var i=this.layoutMode;i&&pa(this.option,t,i),Ma(this);var o=this.getInitialData(t,e);Mr(o,this),this.dataTask.dirty(),this.dataTask.context.data=o,jI(this).dataBeforeProcessed=o,xr(this)},fillDataTextStyle:function(t){if(t&&!S(t))for(var e=["show"],i=0;i<t.length;i++)t[i]&&t[i].label&&Ci(t[i],"label",e)},getInitialData:function(){},appendData:function(t){this.getRawData().appendData(t.data)},getData:function(t){var e=Tr(this);if(e){var i=e.context.data;return null==t?i:i.getLinkedData(t)}return jI(this).data},setData:function(t){var e=Tr(this);if(e){var i=e.context;i.data!==t&&e.modifyOutputEnd&&e.setOutputEnd(t.count()),i.outputData=t,e!==this.dataTask&&(i.data=t)}jI(this).data=t},getSource:function(){return ba(this)},getRawData:function(){return jI(this).dataBeforeProcessed},getBaseAxis:function(){var t=this.coordinateSystem;return t&&t.getBaseAxis&&t.getBaseAxis()},formatTooltip:function(t,e,i,n){function o(t){return{renderMode:n,content:ia(ta(t)),style:l}}var a=this,r="html"===(n=n||"html")?"<br/>":"\n",s="richText"===n,l={},u=0,h=this.getData(),c=h.mapDimension("defaultedTooltip",!0),f=c.length,g=this.getRawValue(t),m=y(g),v=h.getItemVisual(t,"color");w(v)&&v.colorStops&&(v=(v.colorStops[0]||{}).color),v=v||"transparent";var x=(f>1||m&&!f?function(i){function o(t,i){var o=h.getDimensionInfo(i);if(o&&!1!==o.otherDims.tooltip){var c=o.type,d="sub"+a.seriesIndex+"at"+u,p=aa({color:v,type:"subItem",renderMode:n,markerId:d}),g="string"==typeof p?p:p.content,m=(r?g+ia(o.displayName||"-")+": ":"")+ia("ordinal"===c?t+"":"time"===c?e?"":sa("yyyy/MM/dd hh:mm:ss",t):ta(t));m&&f.push(m),s&&(l[d]=v,++u)}}var r=p(i,function(t,e,i){var n=h.getDimensionInfo(i);return t|=n&&!1!==n.tooltip&&null!=n.displayName},0),f=[];c.length?d(c,function(e){o(fr(h,t,e),e)}):d(i,o);var g=r?s?"\n":"<br/>":"",m=g+f.join(g||", ");return{renderMode:n,content:m,style:l}}(g):o(f?fr(h,t,c[0]):m?g[0]:g)).content,_=a.seriesIndex+"at"+u,b=aa({color:v,type:"item",renderMode:n,markerId:_});l[_]=v,++u;var S=h.getName(t),M=this.name;Oi(this)||(M=""),M=M?ia(M)+(e?": ":r):"";var I="string"==typeof b?b:b.content;return{html:e?I+M+x:M+I+(S?ia(S)+": "+x:x),markers:l}},isAnimationEnabled:function(){if(U_.node)return!1;var t=this.getShallow("animation");return t&&this.getData().count()>this.getShallow("animationThreshold")&&(t=!1),t},restoreData:function(){this.dataTask.dirty()},getColorFromPalette:function(t,e,i){var n=this.ecModel,o=dI.getColorFromPalette.call(this,t,e,i);return o||(o=n.getColorFromPalette(t,e,i)),o},coordDimToDataDim:function(t){return this.getRawData().mapDimension(t,!0)},getProgressive:function(){return this.get("progressive")},getProgressiveThreshold:function(){return this.get("progressiveThreshold")},getAxisTooltipData:null,getTooltipPosition:null,pipeTask:null,preventIncremental:null,pipelineContext:null});h(YI,ZI),h(YI,dI);var qI=function(){this.group=new tb,this.uid=Ro("viewComponent")};qI.prototype={constructor:qI,init:function(t,e){},render:function(t,e,i,n){},dispose:function(){},filterForExposedEvent:null};var KI=qI.prototype;KI.updateView=KI.updateLayout=KI.updateVisual=function(t,e,i,n){},ji(qI),$i(qI,{registerWhenExtend:!0});var $I=function(){var t=Bi();return function(e){var i=t(e),n=e.pipelineContext,o=i.large,a=i.progressiveRender,r=i.large=n.large,s=i.progressiveRender=n.progressiveRender;return!!(o^r||a^s)&&"reset"}},JI=Bi(),QI=$I();Ar.prototype={type:"chart",init:function(t,e){},render:function(t,e,i,n){},highlight:function(t,e,i,n){Cr(t.getData(),n,"emphasis")},downplay:function(t,e,i,n){Cr(t.getData(),n,"normal")},remove:function(t,e){this.group.removeAll()},dispose:function(){},incrementalPrepareRender:null,incrementalRender:null,updateTransform:null,filterForExposedEvent:null};var tT=Ar.prototype;tT.updateView=tT.updateLayout=tT.updateVisual=function(t,e,i,n){this.render(t,e,i,n)},ji(Ar),$i(Ar,{registerWhenExtend:!0}),Ar.markUpdateMethod=function(t,e){JI(t).updateMethod=e};var eT={incrementalPrepareRender:{progress:function(t,e){e.view.incrementalRender(t,e.model,e.ecModel,e.api,e.payload)}},render:{forceFirstProgress:!0,progress:function(t,e){e.view.render(e.model,e.ecModel,e.api,e.payload)}}},iT="\0__throttleOriginMethod",nT="\0__throttleRate",oT="\0__throttleType",aT={createOnAllSeries:!0,performRawSeries:!0,reset:function(t,e){var i=t.getData(),n=(t.visualColorAccessPath||"itemStyle.color").split("."),o=t.get(n)||t.getColorFromPalette(t.name,null,e.getSeriesCount());if(i.setVisual("color",o),!e.isSeriesFiltered(t)){"function"!=typeof o||o instanceof IM||i.each(function(e){i.setItemVisual(e,"color",o(t.getDataParams(e)))});return{dataEach:i.hasItemOption?function(t,e){var i=t.getItemModel(e).get(n,!0);null!=i&&t.setItemVisual(e,"color",i)}:null}}}},rT={toolbox:{brush:{title:{rect:"矩形选择",polygon:"圈选",lineX:"横向选择",lineY:"纵向选择",keep:"保持选择",clear:"清除选择"}},dataView:{title:"数据视图",lang:["数据视图","关闭","刷新"]},dataZoom:{title:{zoom:"区域缩放",back:"区域缩放还原"}},magicType:{title:{line:"切换为折线图",bar:"切换为柱状图",stack:"切换为堆叠",tiled:"切换为平铺"}},restore:{title:"还原"},saveAsImage:{title:"保存为图片",lang:["右键另存为图片"]}},series:{typeNames:{pie:"饼图",bar:"柱状图",line:"折线图",scatter:"散点图",effectScatter:"涟漪散点图",radar:"雷达图",tree:"树图",treemap:"矩形树图",boxplot:"箱型图",candlestick:"K线图",k:"K线图",heatmap:"热力图",map:"地图",parallel:"平行坐标图",lines:"线图",graph:"关系图",sankey:"桑基图",funnel:"漏斗图",gauge:"仪表盘图",pictorialBar:"象形柱图",themeRiver:"主题河流图",sunburst:"旭日图"}},aria:{general:{withTitle:"这是一个关于“{title}”的图表。",withoutTitle:"这是一个图表,"},series:{single:{prefix:"",withName:"图表类型是{seriesType},表示{seriesName}。",withoutName:"图表类型是{seriesType}。"},multiple:{prefix:"它由{seriesCount}个图表系列组成。",withName:"第{seriesId}个系列是一个表示{seriesName}的{seriesType},",withoutName:"第{seriesId}个系列是一个{seriesType},",separator:{middle:";",end:"。"}}},data:{allData:"其数据是——",partialData:"其中,前{displayCnt}项是——",withName:"{name}的数据是{value}",withoutName:"{value}",separator:{middle:",",end:""}}}},sT=function(t,e){function i(t,e){if("string"!=typeof t)return t;var i=t;return d(e,function(t,e){i=i.replace(new RegExp("\\{\\s*"+e+"\\s*\\}","g"),t)}),i}function n(t){var e=a.get(t);if(null==e){for(var i=t.split("."),n=rT.aria,o=0;o<i.length;++o)n=n[i[o]];return n}return e}function o(t){return rT.series.typeNames[t]||"自定义图"}var a=e.getModel("aria");if(a.get("show"))if(a.get("description"))t.setAttribute("aria-label",a.get("description"));else{var r=0;e.eachSeries(function(t,e){++r},this);var s,l=a.get("data.maxCount")||10,u=a.get("series.maxCount")||10,h=Math.min(r,u);if(!(r<1)){var c=function(){var t=e.getModel("title").option;return t&&t.length&&(t=t[0]),t&&t.text}();s=c?i(n("general.withTitle"),{title:c}):n("general.withoutTitle");var f=[];s+=i(n(r>1?"series.multiple.prefix":"series.single.prefix"),{seriesCount:r}),e.eachSeries(function(t,e){if(e<h){var a,s=t.get("name"),u="series."+(r>1?"multiple":"single")+".";a=i(a=n(s?u+"withName":u+"withoutName"),{seriesId:t.seriesIndex,seriesName:t.get("name"),seriesType:o(t.subType)});var c=t.getData();window.data=c,c.count()>l?a+=i(n("data.partialData"),{displayCnt:l}):a+=n("data.allData");for(var d=[],p=0;p<c.count();p++)if(p<l){var g=c.getName(p),m=fr(c,p);d.push(i(n(g?"data.withName":"data.withoutName"),{name:g,value:m}))}a+=d.join(n("data.separator.middle"))+n("data.separator.end"),f.push(a)}}),s+=f.join(n("series.multiple.separator.middle"))+n("series.multiple.separator.end"),t.setAttribute("aria-label",s)}}},lT=Math.PI,uT=Er.prototype;uT.restoreData=function(t,e){t.restoreData(e),this._stageTaskMap.each(function(t){var e=t.overallTask;e&&e.dirty()})},uT.getPerformArgs=function(t,e){if(t.__pipeline){var i=this._pipelineMap.get(t.__pipeline.id),n=i.context,o=!e&&i.progressiveEnabled&&(!n||n.progressiveRender)&&t.__idxInPipeline>i.blockIndex?i.step:null,a=n&&n.modDataCount;return{step:o,modBy:null!=a?Math.ceil(a/o):null,modDataCount:a}}},uT.getPipeline=function(t){return this._pipelineMap.get(t)},uT.updateStreamModes=function(t,e){var i=this._pipelineMap.get(t.uid),n=t.getData().count(),o=i.progressiveEnabled&&e.incrementalPrepareRender&&n>=i.threshold,a=t.get("large")&&n>=t.get("largeThreshold"),r="mod"===t.get("progressiveChunkMode")?n:null;t.pipelineContext=i.context={progressiveRender:o,modDataCount:r,large:a}},uT.restorePipelines=function(t){var e=this,i=e._pipelineMap=R();t.eachSeries(function(t){var n=t.getProgressive(),o=t.uid;i.set(o,{id:o,head:null,tail:null,threshold:t.getProgressiveThreshold(),progressiveEnabled:n&&!(t.preventIncremental&&t.preventIncremental()),blockIndex:-1,step:Math.round(n||700),count:0}),jr(e,t,t.dataTask)})},uT.prepareStageTasks=function(){var t=this._stageTaskMap,e=this.ecInstance.getModel(),i=this.api;d(this._allHandlers,function(n){var o=t.get(n.uid)||t.set(n.uid,[]);n.reset&&zr(this,n,o,e,i),n.overallReset&&Br(this,n,o,e,i)},this)},uT.prepareView=function(t,e,i,n){var o=t.renderTask,a=o.context;a.model=e,a.ecModel=i,a.api=n,o.__block=!t.incrementalPrepareRender,jr(this,e,o)},uT.performDataProcessorTasks=function(t,e){Rr(this,this._dataProcessorHandlers,t,e,{block:!0})},uT.performVisualTasks=function(t,e,i){Rr(this,this._visualHandlers,t,e,i)},uT.performSeriesTasks=function(t){var e;t.eachSeries(function(t){e|=t.dataTask.perform()}),this.unfinished|=e},uT.plan=function(){this._pipelineMap.each(function(t){var e=t.tail;do{if(e.__block){t.blockIndex=e.__idxInPipeline;break}e=e.getUpstream()}while(e)})};var hT=uT.updatePayload=function(t,e){"remain"!==e&&(t.context.payload=e)},cT=Ur(0);Er.wrapStageHandler=function(t,e){return x(t)&&(t={overallReset:t,seriesType:Yr(t)}),t.uid=Ro("stageHandler"),e&&(t.visualType=e),t};var dT,fT={},pT={};qr(fT,MI),qr(pT,Ga),fT.eachSeriesByType=fT.eachRawSeriesByType=function(t){dT=t},fT.eachComponent=function(t){"series"===t.mainType&&t.subType&&(dT=t.subType)};var gT=["#37A2DA","#32C5E9","#67E0E3","#9FE6B8","#FFDB5C","#ff9f7f","#fb7293","#E062AE","#E690D1","#e7bcf3","#9d96f5","#8378EA","#96BFFF"],mT={color:gT,colorLayer:[["#37A2DA","#ffd85c","#fd7b5f"],["#37A2DA","#67E0E3","#FFDB5C","#ff9f7f","#E062AE","#9d96f5"],["#37A2DA","#32C5E9","#9FE6B8","#FFDB5C","#ff9f7f","#fb7293","#e7bcf3","#8378EA","#96BFFF"],gT]},vT=["#dd6b66","#759aa0","#e69d87","#8dc1a9","#ea7e53","#eedd78","#73a373","#73b9bc","#7289ab","#91ca8c","#f49f42"],yT={color:vT,backgroundColor:"#333",tooltip:{axisPointer:{lineStyle:{color:"#eee"},crossStyle:{color:"#eee"}}},legend:{textStyle:{color:"#eee"}},textStyle:{color:"#eee"},title:{textStyle:{color:"#eee"}},toolbox:{iconStyle:{normal:{borderColor:"#eee"}}},dataZoom:{textStyle:{color:"#eee"}},visualMap:{textStyle:{color:"#eee"}},timeline:{lineStyle:{color:"#eee"},itemStyle:{normal:{color:vT[1]}},label:{normal:{textStyle:{color:"#eee"}}},controlStyle:{normal:{color:"#eee",borderColor:"#eee"}}},timeAxis:{axisLine:{lineStyle:{color:"#eee"}},axisTick:{lineStyle:{color:"#eee"}},axisLabel:{textStyle:{color:"#eee"}},splitLine:{lineStyle:{type:"dashed",color:"#aaa"}},splitArea:{areaStyle:{color:"#eee"}}},logAxis:{axisLine:{lineStyle:{color:"#eee"}},axisTick:{lineStyle:{color:"#eee"}},axisLabel:{textStyle:{color:"#eee"}},splitLine:{lineStyle:{type:"dashed",color:"#aaa"}},splitArea:{areaStyle:{color:"#eee"}}},valueAxis:{axisLine:{lineStyle:{color:"#eee"}},axisTick:{lineStyle:{color:"#eee"}},axisLabel:{textStyle:{color:"#eee"}},splitLine:{lineStyle:{type:"dashed",color:"#aaa"}},splitArea:{areaStyle:{color:"#eee"}}},categoryAxis:{axisLine:{lineStyle:{color:"#eee"}},axisTick:{lineStyle:{color:"#eee"}},axisLabel:{textStyle:{color:"#eee"}},splitLine:{lineStyle:{type:"dashed",color:"#aaa"}},splitArea:{areaStyle:{color:"#eee"}}},line:{symbol:"circle"},graph:{color:vT},gauge:{title:{textStyle:{color:"#eee"}}},candlestick:{itemStyle:{normal:{color:"#FD1050",color0:"#0CF49B",borderColor:"#FD1050",borderColor0:"#0CF49B"}}}};yT.categoryAxis.splitLine.show=!1,lI.extend({type:"dataset",defaultOption:{seriesLayoutBy:_I,sourceHeader:null,dimensions:null,source:null},optionUpdated:function(){wa(this)}}),qI.extend({type:"dataset"});var xT=Pn.extend({type:"ellipse",shape:{cx:0,cy:0,rx:0,ry:0},buildPath:function(t,e){var i=.5522848,n=e.cx,o=e.cy,a=e.rx,r=e.ry,s=a*i,l=r*i;t.moveTo(n-a,o),t.bezierCurveTo(n-a,o-l,n-s,o-r,n,o-r),t.bezierCurveTo(n+s,o-r,n+a,o-l,n+a,o),t.bezierCurveTo(n+a,o+l,n+s,o+r,n,o+r),t.bezierCurveTo(n-s,o+r,n-a,o+l,n-a,o),t.closePath()}}),_T=/[\s,]+/;$r.prototype.parse=function(t,e){e=e||{};var i=Kr(t);if(!i)throw new Error("Illegal svg");var n=new tb;this._root=n;var o=i.getAttribute("viewBox")||"",a=parseFloat(i.getAttribute("width")||e.width),r=parseFloat(i.getAttribute("height")||e.height);isNaN(a)&&(a=null),isNaN(r)&&(r=null),es(i,n,null,!0);for(var s=i.firstChild;s;)this._parseNode(s,n),s=s.nextSibling;var l,u;if(o){var h=P(o).split(_T);h.length>=4&&(l={x:parseFloat(h[0]||0),y:parseFloat(h[1]||0),width:parseFloat(h[2]),height:parseFloat(h[3])})}if(l&&null!=a&&null!=r&&(u=as(l,a,r),!e.ignoreViewBox)){var c=n;(n=new tb).add(c),c.scale=u.scale.slice(),c.position=u.position.slice()}return e.ignoreRootClip||null==a||null==r||n.setClipPath(new yM({shape:{x:0,y:0,width:a,height:r}})),{root:n,width:a,height:r,viewBoxRect:l,viewBoxTransform:u}},$r.prototype._parseNode=function(t,e){var i=t.nodeName.toLowerCase();"defs"===i?this._isDefine=!0:"text"===i&&(this._isText=!0);var n;if(this._isDefine){if(r=bT[i]){var o=r.call(this,t),a=t.getAttribute("id");a&&(this._defs[a]=o)}}else{var r=wT[i];r&&(n=r.call(this,t,e),e.add(n))}for(var s=t.firstChild;s;)1===s.nodeType&&this._parseNode(s,n),3===s.nodeType&&this._isText&&this._parseText(s,n),s=s.nextSibling;"defs"===i?this._isDefine=!1:"text"===i&&(this._isText=!1)},$r.prototype._parseText=function(t,e){if(1===t.nodeType){var i=t.getAttribute("dx")||0,n=t.getAttribute("dy")||0;this._textX+=parseFloat(i),this._textY+=parseFloat(n)}var o=new rM({style:{text:t.textContent,transformText:!0},position:[this._textX||0,this._textY||0]});Qr(e,o),es(t,o,this._defs);var a=o.style.fontSize;a&&a<9&&(o.style.fontSize=9,o.scale=o.scale||[1,1],o.scale[0]*=a/9,o.scale[1]*=a/9);var r=o.getBoundingRect();return this._textX+=r.width,e.add(o),o};var wT={g:function(t,e){var i=new tb;return Qr(e,i),es(t,i,this._defs),i},rect:function(t,e){var i=new yM;return Qr(e,i),es(t,i,this._defs),i.setShape({x:parseFloat(t.getAttribute("x")||0),y:parseFloat(t.getAttribute("y")||0),width:parseFloat(t.getAttribute("width")||0),height:parseFloat(t.getAttribute("height")||0)}),i},circle:function(t,e){var i=new sM;return Qr(e,i),es(t,i,this._defs),i.setShape({cx:parseFloat(t.getAttribute("cx")||0),cy:parseFloat(t.getAttribute("cy")||0),r:parseFloat(t.getAttribute("r")||0)}),i},line:function(t,e){var i=new _M;return Qr(e,i),es(t,i,this._defs),i.setShape({x1:parseFloat(t.getAttribute("x1")||0),y1:parseFloat(t.getAttribute("y1")||0),x2:parseFloat(t.getAttribute("x2")||0),y2:parseFloat(t.getAttribute("y2")||0)}),i},ellipse:function(t,e){var i=new xT;return Qr(e,i),es(t,i,this._defs),i.setShape({cx:parseFloat(t.getAttribute("cx")||0),cy:parseFloat(t.getAttribute("cy")||0),rx:parseFloat(t.getAttribute("rx")||0),ry:parseFloat(t.getAttribute("ry")||0)}),i},polygon:function(t,e){var i=t.getAttribute("points");i&&(i=ts(i));var n=new pM({shape:{points:i||[]}});return Qr(e,n),es(t,n,this._defs),n},polyline:function(t,e){var i=new Pn;Qr(e,i),es(t,i,this._defs);var n=t.getAttribute("points");return n&&(n=ts(n)),new gM({shape:{points:n||[]}})},image:function(t,e){var i=new fi;return Qr(e,i),es(t,i,this._defs),i.setStyle({image:t.getAttribute("xlink:href"),x:t.getAttribute("x"),y:t.getAttribute("y"),width:t.getAttribute("width"),height:t.getAttribute("height")}),i},text:function(t,e){var i=t.getAttribute("x")||0,n=t.getAttribute("y")||0,o=t.getAttribute("dx")||0,a=t.getAttribute("dy")||0;this._textX=parseFloat(i)+parseFloat(o),this._textY=parseFloat(n)+parseFloat(a);var r=new tb;return Qr(e,r),es(t,r,this._defs),r},tspan:function(t,e){var i=t.getAttribute("x"),n=t.getAttribute("y");null!=i&&(this._textX=parseFloat(i)),null!=n&&(this._textY=parseFloat(n));var o=t.getAttribute("dx")||0,a=t.getAttribute("dy")||0,r=new tb;return Qr(e,r),es(t,r,this._defs),this._textX+=o,this._textY+=a,r},path:function(t,e){var i=Rn(t.getAttribute("d")||"");return Qr(e,i),es(t,i,this._defs),i}},bT={lineargradient:function(t){var e=parseInt(t.getAttribute("x1")||0,10),i=parseInt(t.getAttribute("y1")||0,10),n=parseInt(t.getAttribute("x2")||10,10),o=parseInt(t.getAttribute("y2")||0,10),a=new TM(e,i,n,o);return Jr(t,a),a},radialgradient:function(t){}},ST={fill:"fill",stroke:"stroke","stroke-width":"lineWidth",opacity:"opacity","fill-opacity":"fillOpacity","stroke-opacity":"strokeOpacity","stroke-dasharray":"lineDash","stroke-dashoffset":"lineDashOffset","stroke-linecap":"lineCap","stroke-linejoin":"lineJoin","stroke-miterlimit":"miterLimit","font-family":"fontFamily","font-size":"fontSize","font-style":"fontStyle","font-weight":"fontWeight","text-align":"textAlign","alignment-baseline":"textBaseline"},MT=/url\(\s*#(.*?)\)/,IT=/(translate|scale|rotate|skewX|skewY|matrix)\(([\-\s0-9\.e,]*)\)/g,TT=/([^\s:;]+)\s*:\s*([^:;]+)/g,AT=R(),DT={registerMap:function(t,e,i){var n;return y(e)?n=e:e.svg?n=[{type:"svg",source:e.svg,specialAreas:e.specialAreas}]:(e.geoJson&&!e.features&&(i=e.specialAreas,e=e.geoJson),n=[{type:"geoJSON",source:e,specialAreas:i}]),d(n,function(t){var e=t.type;"geoJson"===e&&(e=t.type="geoJSON"),(0,CT[e])(t)}),AT.set(t,n)},retrieveMap:function(t){return AT.get(t)}},CT={geoJSON:function(t){var e=t.source;t.geoJSON=_(e)?"undefined"!=typeof JSON&&JSON.parse?JSON.parse(e):new Function("return ("+e+");")():e},svg:function(t){t.svgXML=Kr(t.source)}},LT=k,kT=d,PT=x,NT=w,OT=lI.parseClassType,ET={zrender:"4.0.6"},RT=1e3,zT=1e3,BT=3e3,VT={PROCESSOR:{FILTER:RT,STATISTIC:5e3},VISUAL:{LAYOUT:zT,GLOBAL:2e3,CHART:BT,COMPONENT:4e3,BRUSH:5e3}},GT="__flagInMainProcess",FT="__optionUpdated",WT=/^[a-zA-Z0-9_]+$/;ls.prototype.on=ss("on"),ls.prototype.off=ss("off"),ls.prototype.one=ss("one"),h(ls,fw);var HT=us.prototype;HT._onframe=function(){if(!this._disposed){var t=this._scheduler;if(this[FT]){var e=this[FT].silent;this[GT]=!0,cs(this),ZT.update.call(this),this[GT]=!1,this[FT]=!1,gs.call(this,e),ms.call(this,e)}else if(t.unfinished){var i=1,n=this._model;this._api;t.unfinished=!1;do{var o=+new Date;t.performSeriesTasks(n),t.performDataProcessorTasks(n),fs(this,n),t.performVisualTasks(n),bs(this,this._model,0,"remain"),i-=+new Date-o}while(i>0&&t.unfinished);t.unfinished||this._zr.flush()}}},HT.getDom=function(){return this._dom},HT.getZr=function(){return this._zr},HT.setOption=function(t,e,i){var n;if(NT(e)&&(i=e.lazyUpdate,n=e.silent,e=e.notMerge),this[GT]=!0,!this._model||e){var o=new Wa(this._api),a=this._theme,r=this._model=new MI(null,null,a,o);r.scheduler=this._scheduler,r.init(null,null,a,o)}this._model.setOption(t,qT),i?(this[FT]={silent:n},this[GT]=!1):(cs(this),ZT.update.call(this),this._zr.flush(),this[FT]=!1,this[GT]=!1,gs.call(this,n),ms.call(this,n))},HT.setTheme=function(){console.error("ECharts#setTheme() is DEPRECATED in ECharts 3.0")},HT.getModel=function(){return this._model},HT.getOption=function(){return this._model&&this._model.getOption()},HT.getWidth=function(){return this._zr.getWidth()},HT.getHeight=function(){return this._zr.getHeight()},HT.getDevicePixelRatio=function(){return this._zr.painter.dpr||window.devicePixelRatio||1},HT.getRenderedCanvas=function(t){if(U_.canvasSupported)return(t=t||{}).pixelRatio=t.pixelRatio||1,t.backgroundColor=t.backgroundColor||this._model.get("backgroundColor"),this._zr.painter.getRenderedCanvas(t)},HT.getSvgDataUrl=function(){if(U_.svgSupported){var t=this._zr;return d(t.storage.getDisplayList(),function(t){t.stopAnimation(!0)}),t.painter.pathToDataUrl()}},HT.getDataURL=function(t){var e=(t=t||{}).excludeComponents,i=this._model,n=[],o=this;kT(e,function(t){i.eachComponent({mainType:t},function(t){var e=o._componentsMap[t.__viewId];e.group.ignore||(n.push(e),e.group.ignore=!0)})});var a="svg"===this._zr.painter.getType()?this.getSvgDataUrl():this.getRenderedCanvas(t).toDataURL("image/"+(t&&t.type||"png"));return kT(n,function(t){t.group.ignore=!1}),a},HT.getConnectedDataURL=function(t){if(U_.canvasSupported){var e=this.group,n=Math.min,o=Math.max;if(eA[e]){var a=1/0,r=1/0,s=-1/0,l=-1/0,u=[],h=t&&t.pixelRatio||1;d(tA,function(h,c){if(h.group===e){var d=h.getRenderedCanvas(i(t)),f=h.getDom().getBoundingClientRect();a=n(f.left,a),r=n(f.top,r),s=o(f.right,s),l=o(f.bottom,l),u.push({dom:d,left:f.left,top:f.top})}});var c=(s*=h)-(a*=h),f=(l*=h)-(r*=h),p=iw();p.width=c,p.height=f;var g=Ii(p);return kT(u,function(t){var e=new fi({style:{x:t.left*h-a,y:t.top*h-r,image:t.dom}});g.add(e)}),g.refreshImmediately(),p.toDataURL("image/"+(t&&t.type||"png"))}return this.getDataURL(t)}},HT.convertToPixel=v(hs,"convertToPixel"),HT.convertFromPixel=v(hs,"convertFromPixel"),HT.containPixel=function(t,e){var i;return t=Vi(this._model,t),d(t,function(t,n){n.indexOf("Models")>=0&&d(t,function(t){var o=t.coordinateSystem;if(o&&o.containPoint)i|=!!o.containPoint(e);else if("seriesModels"===n){var a=this._chartsMap[t.__viewId];a&&a.containPoint&&(i|=a.containPoint(e,t))}},this)},this),!!i},HT.getVisual=function(t,e){var i=(t=Vi(this._model,t,{defaultMainType:"series"})).seriesModel.getData(),n=t.hasOwnProperty("dataIndexInside")?t.dataIndexInside:t.hasOwnProperty("dataIndex")?i.indexOfRawIndex(t.dataIndex):null;return null!=n?i.getItemVisual(n,e):i.getVisual(e)},HT.getViewOfComponentModel=function(t){return this._componentsMap[t.__viewId]},HT.getViewOfSeriesModel=function(t){return this._chartsMap[t.__viewId]};var ZT={prepareAndUpdate:function(t){cs(this),ZT.update.call(this,t)},update:function(t){var e=this._model,i=this._api,n=this._zr,o=this._coordSysMgr,a=this._scheduler;if(e){a.restoreData(e,t),a.performSeriesTasks(e),o.create(e,i),a.performDataProcessorTasks(e,t),fs(this,e),o.update(e,i),xs(e),a.performVisualTasks(e,t),_s(this,e,i,t);var r=e.get("backgroundColor")||"transparent";if(U_.canvasSupported)n.setBackgroundColor(r);else{var s=Gt(r);r=qt(s,"rgb"),0===s[3]&&(r="transparent")}Ss(e,i)}},updateTransform:function(t){var e=this._model,i=this,n=this._api;if(e){var o=[];e.eachComponent(function(a,r){var s=i.getViewOfComponentModel(r);if(s&&s.__alive)if(s.updateTransform){var l=s.updateTransform(r,e,n,t);l&&l.update&&o.push(s)}else o.push(s)});var a=R();e.eachSeries(function(o){var r=i._chartsMap[o.__viewId];if(r.updateTransform){var s=r.updateTransform(o,e,n,t);s&&s.update&&a.set(o.uid,1)}else a.set(o.uid,1)}),xs(e),this._scheduler.performVisualTasks(e,t,{setDirty:!0,dirtyMap:a}),bs(i,e,0,t,a),Ss(e,this._api)}},updateView:function(t){var e=this._model;e&&(Ar.markUpdateMethod(t,"updateView"),xs(e),this._scheduler.performVisualTasks(e,t,{setDirty:!0}),_s(this,this._model,this._api,t),Ss(e,this._api))},updateVisual:function(t){ZT.update.call(this,t)},updateLayout:function(t){ZT.update.call(this,t)}};HT.resize=function(t){this._zr.resize(t);var e=this._model;if(this._loadingFX&&this._loadingFX.resize(),e){var i=e.resetOption("media"),n=t&&t.silent;this[GT]=!0,i&&cs(this),ZT.update.call(this),this[GT]=!1,gs.call(this,n),ms.call(this,n)}},HT.showLoading=function(t,e){if(NT(t)&&(e=t,t=""),t=t||"default",this.hideLoading(),QT[t]){var i=QT[t](this._api,e),n=this._zr;this._loadingFX=i,n.add(i)}},HT.hideLoading=function(){this._loadingFX&&this._zr.remove(this._loadingFX),this._loadingFX=null},HT.makeActionFromEvent=function(t){var e=a({},t);return e.type=jT[t.type],e},HT.dispatchAction=function(t,e){NT(e)||(e={silent:!!e}),XT[t.type]&&this._model&&(this[GT]?this._pendingActions.push(t):(ps.call(this,t,e.silent),e.flush?this._zr.flush(!0):!1!==e.flush&&U_.browser.weChat&&this._throttledZrFlush(),gs.call(this,e.silent),ms.call(this,e.silent)))},HT.appendData=function(t){var e=t.seriesIndex;this.getModel().getSeriesByIndex(e).appendData(t),this._scheduler.unfinished=!0},HT.on=ss("on"),HT.off=ss("off"),HT.one=ss("one");var UT=["click","dblclick","mouseover","mouseout","mousemove","mousedown","mouseup","globalout","contextmenu"];HT._initEvents=function(){kT(UT,function(t){var e=function(e){var i,n=this.getModel(),o=e.target;if("globalout"===t)i={};else if(o&&null!=o.dataIndex){var r=o.dataModel||n.getSeriesByIndex(o.seriesIndex);i=r&&r.getDataParams(o.dataIndex,o.dataType,o)||{}}else o&&o.eventData&&(i=a({},o.eventData));if(i){var s=i.componentType,l=i.componentIndex;"markLine"!==s&&"markPoint"!==s&&"markArea"!==s||(s="series",l=i.seriesIndex);var u=s&&null!=l&&n.getComponent(s,l),h=u&&this["series"===u.mainType?"_chartsMap":"_componentsMap"][u.__viewId];i.event=e,i.type=t,this._ecEventProcessor.eventInfo={targetEl:o,packedEvent:i,model:u,view:h},this.trigger(t,i)}};e.zrEventfulCallAtLast=!0,this._zr.on(t,e,this)},this),kT(jT,function(t,e){this._messageCenter.on(e,function(t){this.trigger(e,t)},this)},this)},HT.isDisposed=function(){return this._disposed},HT.clear=function(){this.setOption({series:[]},!0)},HT.dispose=function(){if(!this._disposed){this._disposed=!0,Fi(this.getDom(),oA,"");var t=this._api,e=this._model;kT(this._componentsViews,function(i){i.dispose(e,t)}),kT(this._chartsViews,function(i){i.dispose(e,t)}),this._zr.dispose(),delete tA[this.id]}},h(us,fw),Ds.prototype={constructor:Ds,normalizeQuery:function(t){var e={},i={},n={};if(_(t)){var o=OT(t);e.mainType=o.main||null,e.subType=o.sub||null}else{var a=["Index","Name","Id"],r={name:1,dataIndex:1,dataType:1};d(t,function(t,o){for(var s=!1,l=0;l<a.length;l++){var u=a[l],h=o.lastIndexOf(u);if(h>0&&h===o.length-u.length){var c=o.slice(0,h);"data"!==c&&(e.mainType=c,e[u.toLowerCase()]=t,s=!0)}}r.hasOwnProperty(o)&&(i[o]=t,s=!0),s||(n[o]=t)})}return{cptQuery:e,dataQuery:i,otherQuery:n}},filter:function(t,e,i){function n(t,e,i,n){return null==t[i]||e[n||i]===t[i]}var o=this.eventInfo;if(!o)return!0;var a=o.targetEl,r=o.packedEvent,s=o.model,l=o.view;if(!s||!l)return!0;var u=e.cptQuery,h=e.dataQuery;return n(u,s,"mainType")&&n(u,s,"subType")&&n(u,s,"index","componentIndex")&&n(u,s,"name")&&n(u,s,"id")&&n(h,r,"name")&&n(h,r,"dataIndex")&&n(h,r,"dataType")&&(!l.filterForExposedEvent||l.filterForExposedEvent(t,e.otherQuery,a,r))},afterTrigger:function(){this.eventInfo=null}};var XT={},jT={},YT=[],qT=[],KT=[],$T=[],JT={},QT={},tA={},eA={},iA=new Date-0,nA=new Date-0,oA="_echarts_instance_",aA=Ls;Bs(2e3,aT),Ns(BI),Os(5e3,function(t){var e=R();t.eachSeries(function(t){var i=t.get("stack");if(i){var n=e.get(i)||e.set(i,[]),o=t.getData(),a={stackResultDimension:o.getCalculationInfo("stackResultDimension"),stackedOverDimension:o.getCalculationInfo("stackedOverDimension"),stackedDimension:o.getCalculationInfo("stackedDimension"),stackedByDimension:o.getCalculationInfo("stackedByDimension"),isStackedByIndex:o.getCalculationInfo("isStackedByIndex"),data:o,seriesModel:t};if(!a.stackedDimension||!a.isStackedByIndex&&!a.stackedByDimension)return;n.length&&o.setCalculationInfo("stackedOnSeries",n[n.length-1].seriesModel),n.push(a)}}),e.each(ar)}),Gs("default",function(t,e){r(e=e||{},{text:"loading",color:"#c23531",textColor:"#000",maskColor:"rgba(255, 255, 255, 0.8)",zlevel:0});var i=new yM({style:{fill:e.maskColor},zlevel:e.zlevel,z:1e4}),n=new SM({shape:{startAngle:-lT/2,endAngle:-lT/2+.1,r:10},style:{stroke:e.color,lineCap:"round",lineWidth:5},zlevel:e.zlevel,z:10001}),o=new yM({style:{fill:"none",text:e.text,textPosition:"right",textDistance:10,textFill:e.textColor},zlevel:e.zlevel,z:10001});n.animateShape(!0).when(1e3,{endAngle:3*lT/2}).start("circularInOut"),n.animateShape(!0).when(1e3,{startAngle:3*lT/2}).delay(300).start("circularInOut");var a=new tb;return a.add(n),a.add(o),a.add(i),a.resize=function(){var e=t.getWidth()/2,a=t.getHeight()/2;n.setShape({cx:e,cy:a});var r=n.shape.r;o.setShape({x:e-r,y:a-r,width:2*r,height:2*r}),i.setShape({x:0,y:0,width:t.getWidth(),height:t.getHeight()})},a.resize(),a}),Es({type:"highlight",event:"highlight",update:"highlight"},B),Es({type:"downplay",event:"downplay",update:"downplay"},B),Ps("light",mT),Ps("dark",yT);var rA={};Xs.prototype={constructor:Xs,add:function(t){return this._add=t,this},update:function(t){return this._update=t,this},remove:function(t){return this._remove=t,this},execute:function(){var t=this._old,e=this._new,i={},n=[],o=[];for(js(t,{},n,"_oldKeyGetter",this),js(e,i,o,"_newKeyGetter",this),a=0;a<t.length;a++)null!=(s=i[r=n[a]])?((u=s.length)?(1===u&&(i[r]=null),s=s.unshift()):i[r]=null,this._update&&this._update(s,a)):this._remove&&this._remove(a);for(var a=0;a<o.length;a++){var r=o[a];if(i.hasOwnProperty(r)){var s=i[r];if(null==s)continue;if(s.length)for(var l=0,u=s.length;l<u;l++)this._add&&this._add(s[l]);else this._add&&this._add(s)}}}};var sA=R(["tooltip","label","itemName","itemId","seriesName"]),lA=w,uA=-1,hA="e\0\0",cA={float:"undefined"==typeof Float64Array?Array:Float64Array,int:"undefined"==typeof Int32Array?Array:Int32Array,ordinal:Array,number:Array,time:Array},dA="undefined"==typeof Uint32Array?Array:Uint32Array,fA="undefined"==typeof Int32Array?Array:Int32Array,pA="undefined"==typeof Uint16Array?Array:Uint16Array,gA=["hasItemOption","_nameList","_idList","_invertedIndicesMap","_rawData","_chunkSize","_chunkCount","_dimValueGetter","_count","_rawCount","_nameDimIdx","_idDimIdx"],mA=["_extent","_approximateExtent","_rawExtent"],vA=function(t,e){t=t||["x","y"];for(var i={},n=[],o={},a=0;a<t.length;a++){var r=t[a];_(r)&&(r={name:r});var s=r.name;r.type=r.type||"float",r.coordDim||(r.coordDim=s,r.coordDimIndex=0),r.otherDims=r.otherDims||{},n.push(s),i[s]=r,r.index=a,r.createInvertedIndices&&(o[s]=[])}this.dimensions=n,this._dimensionInfos=i,this.hostModel=e,this.dataType,this._indices=null,this._count=0,this._rawCount=0,this._storage={},this._nameList=[],this._idList=[],this._optionModels=[],this._visual={},this._layout={},this._itemVisuals=[],this.hasItemVisual={},this._itemLayouts=[],this._graphicEls=[],this._chunkSize=1e5,this._chunkCount=0,this._rawData,this._rawExtent={},this._extent={},this._approximateExtent={},this._dimensionsSummary=Ys(this),this._invertedIndicesMap=o,this._calculationInfo={}},yA=vA.prototype;yA.type="list",yA.hasItemOption=!0,yA.getDimension=function(t){return isNaN(t)||(t=this.dimensions[t]||t),t},yA.getDimensionInfo=function(t){return this._dimensionInfos[this.getDimension(t)]},yA.getDimensionsOnCoord=function(){return this._dimensionsSummary.dataDimsOnCoord.slice()},yA.mapDimension=function(t,e){var i=this._dimensionsSummary;if(null==e)return i.encodeFirstDimNotExtra[t];var n=i.encode[t];return!0===e?(n||[]).slice():n&&n[e]},yA.initData=function(t,e,i){(_a.isInstance(t)||c(t))&&(t=new rr(t,this.dimensions.length)),this._rawData=t,this._storage={},this._indices=null,this._nameList=e||[],this._idList=[],this._nameRepeatCount={},i||(this.hasItemOption=!1),this.defaultDimValueGetter=WI[this._rawData.getSource().sourceFormat],this._dimValueGetter=i=i||this.defaultDimValueGetter,this._dimValueGetterArrayRows=WI.arrayRows,this._rawExtent={},this._initDataFromProvider(0,t.count()),t.pure&&(this.hasItemOption=!1)},yA.getProvider=function(){return this._rawData},yA.appendData=function(t){var e=this._rawData,i=this.count();e.appendData(t);var n=e.count();e.persistent||(n+=i),this._initDataFromProvider(i,n)},yA.appendValues=function(t,e){for(var i=this._chunkSize,n=this._storage,o=this.dimensions,a=o.length,r=this._rawExtent,s=this.count(),l=s+Math.max(t.length,e?e.length:0),u=this._chunkCount,h=0;h<a;h++)r[v=o[h]]||(r[v]=[1/0,-1/0]),n[v]||(n[v]=[]),tl(n,this._dimensionInfos[v],i,u,l),this._chunkCount=n[v].length;for(var c=new Array(a),d=s;d<l;d++){for(var f=d-s,p=Math.floor(d/i),g=d%i,m=0;m<a;m++){var v=o[m],y=this._dimValueGetterArrayRows(t[f]||c,v,f,m);n[v][p][g]=y;var x=r[v];y<x[0]&&(x[0]=y),y>x[1]&&(x[1]=y)}e&&(this._nameList[d]=e[f])}this._rawCount=this._count=l,this._extent={},el(this)},yA._initDataFromProvider=function(t,e){if(!(t>=e)){for(var i,n=this._chunkSize,o=this._rawData,a=this._storage,r=this.dimensions,s=r.length,l=this._dimensionInfos,u=this._nameList,h=this._idList,c=this._rawExtent,d=this._nameRepeatCount={},f=this._chunkCount,p=0;p<s;p++){c[w=r[p]]||(c[w]=[1/0,-1/0]);var g=l[w];0===g.otherDims.itemName&&(i=this._nameDimIdx=p),0===g.otherDims.itemId&&(this._idDimIdx=p),a[w]||(a[w]=[]),tl(a,g,n,f,e),this._chunkCount=a[w].length}for(var m=new Array(s),v=t;v<e;v++){m=o.getItem(v,m);for(var y=Math.floor(v/n),x=v%n,_=0;_<s;_++){var w=r[_],b=a[w][y],S=this._dimValueGetter(m,w,v,_);b[x]=S;var M=c[w];S<M[0]&&(M[0]=S),S>M[1]&&(M[1]=S)}if(!o.pure){var I=u[v];if(m&&null==I)if(null!=m.name)u[v]=I=m.name;else if(null!=i){var T=r[i],A=a[T][y];if(A){I=A[x];var D=l[T].ordinalMeta;D&&D.categories.length&&(I=D.categories[I])}}var C=null==m?null:m.id;null==C&&null!=I&&(d[I]=d[I]||0,C=I,d[I]>0&&(C+="__ec__"+d[I]),d[I]++),null!=C&&(h[v]=C)}}!o.persistent&&o.clean&&o.clean(),this._rawCount=this._count=e,this._extent={},el(this)}},yA.count=function(){return this._count},yA.getIndices=function(){var t=this._indices;if(t){var e=t.constructor,i=this._count;if(e===Array){n=new e(i);for(o=0;o<i;o++)n[o]=t[o]}else n=new e(t.buffer,0,i)}else for(var n=new(e=$s(this))(this.count()),o=0;o<n.length;o++)n[o]=o;return n},yA.get=function(t,e){if(!(e>=0&&e<this._count))return NaN;var i=this._storage;if(!i[t])return NaN;e=this.getRawIndex(e);var n=Math.floor(e/this._chunkSize),o=e%this._chunkSize;return i[t][n][o]},yA.getByRawIndex=function(t,e){if(!(e>=0&&e<this._rawCount))return NaN;var i=this._storage[t];if(!i)return NaN;var n=Math.floor(e/this._chunkSize),o=e%this._chunkSize;return i[n][o]},yA._getFast=function(t,e){var i=Math.floor(e/this._chunkSize),n=e%this._chunkSize;return this._storage[t][i][n]},yA.getValues=function(t,e){var i=[];y(t)||(e=t,t=this.dimensions);for(var n=0,o=t.length;n<o;n++)i.push(this.get(t[n],e));return i},yA.hasValue=function(t){for(var e=this._dimensionsSummary.dataDimsOnCoord,i=this._dimensionInfos,n=0,o=e.length;n<o;n++)if("ordinal"!==i[e[n]].type&&isNaN(this.get(e[n],t)))return!1;return!0},yA.getDataExtent=function(t){t=this.getDimension(t);var e=[1/0,-1/0];if(!this._storage[t])return e;var i,n=this.count();if(!this._indices)return this._rawExtent[t].slice();if(i=this._extent[t])return i.slice();for(var o=(i=e)[0],a=i[1],r=0;r<n;r++){var s=this._getFast(t,this.getRawIndex(r));s<o&&(o=s),s>a&&(a=s)}return i=[o,a],this._extent[t]=i,i},yA.getApproximateExtent=function(t){return t=this.getDimension(t),this._approximateExtent[t]||this.getDataExtent(t)},yA.setApproximateExtent=function(t,e){e=this.getDimension(e),this._approximateExtent[e]=t.slice()},yA.getCalculationInfo=function(t){return this._calculationInfo[t]},yA.setCalculationInfo=function(t,e){lA(t)?a(this._calculationInfo,t):this._calculationInfo[t]=e},yA.getSum=function(t){var e=0;if(this._storage[t])for(var i=0,n=this.count();i<n;i++){var o=this.get(t,i);isNaN(o)||(e+=o)}return e},yA.getMedian=function(t){var e=[];this.each(t,function(t,i){isNaN(t)||e.push(t)});var i=[].concat(e).sort(function(t,e){return t-e}),n=this.count();return 0===n?0:n%2==1?i[(n-1)/2]:(i[n/2]+i[n/2-1])/2},yA.rawIndexOf=function(t,e){var i=(t&&this._invertedIndicesMap[t])[e];return null==i||isNaN(i)?uA:i},yA.indexOfName=function(t){for(var e=0,i=this.count();e<i;e++)if(this.getName(e)===t)return e;return-1},yA.indexOfRawIndex=function(t){if(!this._indices)return t;if(t>=this._rawCount||t<0)return-1;var e=this._indices,i=e[t];if(null!=i&&i<this._count&&i===t)return t;for(var n=0,o=this._count-1;n<=o;){var a=(n+o)/2|0;if(e[a]<t)n=a+1;else{if(!(e[a]>t))return a;o=a-1}}return-1},yA.indicesOfNearest=function(t,e,i){var n=[];if(!this._storage[t])return n;null==i&&(i=1/0);for(var o=Number.MAX_VALUE,a=-1,r=0,s=this.count();r<s;r++){var l=e-this.get(t,r),u=Math.abs(l);l<=i&&u<=o&&((u<o||l>=0&&a<0)&&(o=u,a=l,n.length=0),n.push(r))}return n},yA.getRawIndex=nl,yA.getRawDataItem=function(t){if(this._rawData.persistent)return this._rawData.getItem(this.getRawIndex(t));for(var e=[],i=0;i<this.dimensions.length;i++){var n=this.dimensions[i];e.push(this.get(n,t))}return e},yA.getName=function(t){var e=this.getRawIndex(t);return this._nameList[e]||il(this,this._nameDimIdx,e)||""},yA.getId=function(t){return al(this,this.getRawIndex(t))},yA.each=function(t,e,i,n){if(this._count){"function"==typeof t&&(n=i,i=e,e=t,t=[]),i=i||n||this;for(var o=(t=f(rl(t),this.getDimension,this)).length,a=0;a<this.count();a++)switch(o){case 0:e.call(i,a);break;case 1:e.call(i,this.get(t[0],a),a);break;case 2:e.call(i,this.get(t[0],a),this.get(t[1],a),a);break;default:for(var r=0,s=[];r<o;r++)s[r]=this.get(t[r],a);s[r]=a,e.apply(i,s)}}},yA.filterSelf=function(t,e,i,n){if(this._count){"function"==typeof t&&(n=i,i=e,e=t,t=[]),i=i||n||this,t=f(rl(t),this.getDimension,this);for(var o=this.count(),a=new($s(this))(o),r=[],s=t.length,l=0,u=t[0],h=0;h<o;h++){var c,d=this.getRawIndex(h);if(0===s)c=e.call(i,h);else if(1===s){var p=this._getFast(u,d);c=e.call(i,p,h)}else{for(var g=0;g<s;g++)r[g]=this._getFast(u,d);r[g]=h,c=e.apply(i,r)}c&&(a[l++]=d)}return l<o&&(this._indices=a),this._count=l,this._extent={},this.getRawIndex=this._indices?ol:nl,this}},yA.selectRange=function(t){if(this._count){var e=[];for(var i in t)t.hasOwnProperty(i)&&e.push(i);var n=e.length;if(n){var o=this.count(),a=new($s(this))(o),r=0,s=e[0],l=t[s][0],u=t[s][1],h=!1;if(!this._indices){var c=0;if(1===n){for(var d=this._storage[e[0]],f=0;f<this._chunkCount;f++)for(var p=d[f],g=Math.min(this._count-f*this._chunkSize,this._chunkSize),m=0;m<g;m++)((w=p[m])>=l&&w<=u||isNaN(w))&&(a[r++]=c),c++;h=!0}else if(2===n){for(var d=this._storage[s],v=this._storage[e[1]],y=t[e[1]][0],x=t[e[1]][1],f=0;f<this._chunkCount;f++)for(var p=d[f],_=v[f],g=Math.min(this._count-f*this._chunkSize,this._chunkSize),m=0;m<g;m++){var w=p[m],b=_[m];(w>=l&&w<=u||isNaN(w))&&(b>=y&&b<=x||isNaN(b))&&(a[r++]=c),c++}h=!0}}if(!h)if(1===n)for(m=0;m<o;m++){M=this.getRawIndex(m);((w=this._getFast(s,M))>=l&&w<=u||isNaN(w))&&(a[r++]=M)}else for(m=0;m<o;m++){for(var S=!0,M=this.getRawIndex(m),f=0;f<n;f++){var I=e[f];((w=this._getFast(i,M))<t[I][0]||w>t[I][1])&&(S=!1)}S&&(a[r++]=this.getRawIndex(m))}return r<o&&(this._indices=a),this._count=r,this._extent={},this.getRawIndex=this._indices?ol:nl,this}}},yA.mapArray=function(t,e,i,n){"function"==typeof t&&(n=i,i=e,e=t,t=[]),i=i||n||this;var o=[];return this.each(t,function(){o.push(e&&e.apply(this,arguments))},i),o},yA.map=function(t,e,i,n){i=i||n||this;var o=sl(this,t=f(rl(t),this.getDimension,this));o._indices=this._indices,o.getRawIndex=o._indices?ol:nl;for(var a=o._storage,r=[],s=this._chunkSize,l=t.length,u=this.count(),h=[],c=o._rawExtent,d=0;d<u;d++){for(var p=0;p<l;p++)h[p]=this.get(t[p],d);h[l]=d;var g=e&&e.apply(i,h);if(null!=g){"object"!=typeof g&&(r[0]=g,g=r);for(var m=this.getRawIndex(d),v=Math.floor(m/s),y=m%s,x=0;x<g.length;x++){var _=t[x],w=g[x],b=c[_],S=a[_];S&&(S[v][y]=w),w<b[0]&&(b[0]=w),w>b[1]&&(b[1]=w)}}}return o},yA.downSample=function(t,e,i,n){for(var o=sl(this,[t]),a=o._storage,r=[],s=Math.floor(1/e),l=a[t],u=this.count(),h=this._chunkSize,c=o._rawExtent[t],d=new($s(this))(u),f=0,p=0;p<u;p+=s){s>u-p&&(s=u-p,r.length=s);for(var g=0;g<s;g++){var m=this.getRawIndex(p+g),v=Math.floor(m/h),y=m%h;r[g]=l[v][y]}var x=i(r),_=this.getRawIndex(Math.min(p+n(r,x)||0,u-1)),w=_%h;l[Math.floor(_/h)][w]=x,x<c[0]&&(c[0]=x),x>c[1]&&(c[1]=x),d[f++]=_}return o._count=f,o._indices=d,o.getRawIndex=ol,o},yA.getItemModel=function(t){var e=this.hostModel;return new No(this.getRawDataItem(t),e,e&&e.ecModel)},yA.diff=function(t){var e=this;return new Xs(t?t.getIndices():[],this.getIndices(),function(e){return al(t,e)},function(t){return al(e,t)})},yA.getVisual=function(t){var e=this._visual;return e&&e[t]},yA.setVisual=function(t,e){if(lA(t))for(var i in t)t.hasOwnProperty(i)&&this.setVisual(i,t[i]);else this._visual=this._visual||{},this._visual[t]=e},yA.setLayout=function(t,e){if(lA(t))for(var i in t)t.hasOwnProperty(i)&&this.setLayout(i,t[i]);else this._layout[t]=e},yA.getLayout=function(t){return this._layout[t]},yA.getItemLayout=function(t){return this._itemLayouts[t]},yA.setItemLayout=function(t,e,i){this._itemLayouts[t]=i?a(this._itemLayouts[t]||{},e):e},yA.clearItemLayouts=function(){this._itemLayouts.length=0},yA.getItemVisual=function(t,e,i){var n=this._itemVisuals[t],o=n&&n[e];return null!=o||i?o:this.getVisual(e)},yA.setItemVisual=function(t,e,i){var n=this._itemVisuals[t]||{},o=this.hasItemVisual;if(this._itemVisuals[t]=n,lA(e))for(var a in e)e.hasOwnProperty(a)&&(n[a]=e[a],o[a]=!0);else n[e]=i,o[e]=!0},yA.clearAllVisual=function(){this._visual={},this._itemVisuals=[],this.hasItemVisual={}};var xA=function(t){t.seriesIndex=this.seriesIndex,t.dataIndex=this.dataIndex,t.dataType=this.dataType};yA.setItemGraphicEl=function(t,e){var i=this.hostModel;e&&(e.dataIndex=t,e.dataType=this.dataType,e.seriesIndex=i&&i.seriesIndex,"group"===e.type&&e.traverse(xA,e)),this._graphicEls[t]=e},yA.getItemGraphicEl=function(t){return this._graphicEls[t]},yA.eachItemGraphicEl=function(t,e){d(this._graphicEls,function(i,n){i&&t&&t.call(e,i,n)})},yA.cloneShallow=function(t){if(!t){var e=f(this.dimensions,this.getDimensionInfo,this);t=new vA(e,this.hostModel)}if(t._storage=this._storage,Qs(t,this),this._indices){var i=this._indices.constructor;t._indices=new i(this._indices)}else t._indices=null;return t.getRawIndex=t._indices?ol:nl,t},yA.wrapMethod=function(t,e){var i=this[t];"function"==typeof i&&(this.__wrappedMethods=this.__wrappedMethods||[],this.__wrappedMethods.push(t),this[t]=function(){var t=i.apply(this,arguments);return e.apply(this,[t].concat(C(arguments)))})},yA.TRANSFERABLE_METHODS=["cloneShallow","downSample","map"],yA.CHANGABLE_METHODS=["filterSelf","selectRange"];var _A=function(t,e){return e=e||{},hl(e.coordDimensions||[],t,{dimsDef:e.dimensionsDefine||t.dimensionsDefine,encodeDef:e.encodeDefine||t.encodeDefine,dimCount:e.dimensionsCount,generateCoord:e.generateCoord,generateCoordCount:e.generateCoordCount})};xl.prototype.parse=function(t){return t},xl.prototype.getSetting=function(t){return this._setting[t]},xl.prototype.contain=function(t){var e=this._extent;return t>=e[0]&&t<=e[1]},xl.prototype.normalize=function(t){var e=this._extent;return e[1]===e[0]?.5:(t-e[0])/(e[1]-e[0])},xl.prototype.scale=function(t){var e=this._extent;return t*(e[1]-e[0])+e[0]},xl.prototype.unionExtent=function(t){var e=this._extent;t[0]<e[0]&&(e[0]=t[0]),t[1]>e[1]&&(e[1]=t[1])},xl.prototype.unionExtentFromData=function(t,e){this.unionExtent(t.getApproximateExtent(e))},xl.prototype.getExtent=function(){return this._extent.slice()},xl.prototype.setExtent=function(t,e){var i=this._extent;isNaN(t)||(i[0]=t),isNaN(e)||(i[1]=e)},xl.prototype.isBlank=function(){return this._isBlank},xl.prototype.setBlank=function(t){this._isBlank=t},xl.prototype.getLabel=null,ji(xl),$i(xl,{registerWhenExtend:!0}),_l.createByAxisModel=function(t){var e=t.option,i=e.data,n=i&&f(i,bl);return new _l({categories:n,needCollect:!n,deduplication:!1!==e.dedplication})};var wA=_l.prototype;wA.getOrdinal=function(t){return wl(this).get(t)},wA.parseAndCollect=function(t){var e,i=this._needCollect;if("string"!=typeof t&&!i)return t;if(i&&!this._deduplication)return e=this.categories.length,this.categories[e]=t,e;var n=wl(this);return null==(e=n.get(t))&&(i?(e=this.categories.length,this.categories[e]=t,n.set(t,e)):e=NaN),e};var bA=xl.prototype,SA=xl.extend({type:"ordinal",init:function(t,e){t&&!y(t)||(t=new _l({categories:t})),this._ordinalMeta=t,this._extent=e||[0,t.categories.length-1]},parse:function(t){return"string"==typeof t?this._ordinalMeta.getOrdinal(t):Math.round(t)},contain:function(t){return t=this.parse(t),bA.contain.call(this,t)&&null!=this._ordinalMeta.categories[t]},normalize:function(t){return bA.normalize.call(this,this.parse(t))},scale:function(t){return Math.round(bA.scale.call(this,t))},getTicks:function(){for(var t=[],e=this._extent,i=e[0];i<=e[1];)t.push(i),i++;return t},getLabel:function(t){if(!this.isBlank())return this._ordinalMeta.categories[t]},count:function(){return this._extent[1]-this._extent[0]+1},unionExtentFromData:function(t,e){this.unionExtent(t.getApproximateExtent(e))},getOrdinalMeta:function(){return this._ordinalMeta},niceTicks:B,niceExtent:B});SA.create=function(){return new SA};var MA=Go,IA=Go,TA=xl.extend({type:"interval",_interval:0,_intervalPrecision:2,setExtent:function(t,e){var i=this._extent;isNaN(t)||(i[0]=parseFloat(t)),isNaN(e)||(i[1]=parseFloat(e))},unionExtent:function(t){var e=this._extent;t[0]<e[0]&&(e[0]=t[0]),t[1]>e[1]&&(e[1]=t[1]),TA.prototype.setExtent.call(this,e[0],e[1])},getInterval:function(){return this._interval},setInterval:function(t){this._interval=t,this._niceExtent=this._extent.slice(),this._intervalPrecision=Ml(t)},getTicks:function(){return Al(this._interval,this._extent,this._niceExtent,this._intervalPrecision)},getLabel:function(t,e){if(null==t)return"";var i=e&&e.precision;return null==i?i=Ho(t)||0:"auto"===i&&(i=this._intervalPrecision),t=IA(t,i,!0),ta(t)},niceTicks:function(t,e,i){t=t||5;var n=this._extent,o=n[1]-n[0];if(isFinite(o)){o<0&&(o=-o,n.reverse());var a=Sl(n,t,e,i);this._intervalPrecision=a.intervalPrecision,this._interval=a.interval,this._niceExtent=a.niceTickExtent}},niceExtent:function(t){var e=this._extent;if(e[0]===e[1])if(0!==e[0]){var i=e[0];t.fixMax?e[0]-=i/2:(e[1]+=i/2,e[0]-=i/2)}else e[1]=1;var n=e[1]-e[0];isFinite(n)||(e[0]=0,e[1]=1),this.niceTicks(t.splitNumber,t.minInterval,t.maxInterval);var o=this._interval;t.fixMin||(e[0]=IA(Math.floor(e[0]/o)*o)),t.fixMax||(e[1]=IA(Math.ceil(e[1]/o)*o))}});TA.create=function(){return new TA};var AA="__ec_stack_",DA="undefined"!=typeof Float32Array?Float32Array:Array,CA={seriesType:"bar",plan:$I(),reset:function(t){if(Rl(t)&&zl(t)){var e=t.getData(),i=t.coordinateSystem,n=i.getBaseAxis(),o=i.getOtherAxis(n),a=e.mapDimension(o.dim),r=e.mapDimension(n.dim),s=o.isHorizontal(),l=s?0:1,u=Ol(Pl([t]),n,t).width;return u>.5||(u=.5),{progress:function(t,e){for(var n,h=new DA(2*t.count),c=[],d=[],f=0;null!=(n=t.next());)d[l]=e.get(a,n),d[1-l]=e.get(r,n),c=i.dataToPoint(d,null,c),h[f++]=c[0],h[f++]=c[1];e.setLayout({largePoints:h,barWidth:u,valueAxisStart:Bl(0,o),valueAxisHorizontal:s})}}}}},LA=TA.prototype,kA=Math.ceil,PA=Math.floor,NA=function(t,e,i,n){for(;i<n;){var o=i+n>>>1;t[o][1]<e?i=o+1:n=o}return i},OA=TA.extend({type:"time",getLabel:function(t){var e=this._stepLvl,i=new Date(t);return sa(e[0],i,this.getSetting("useUTC"))},niceExtent:function(t){var e=this._extent;if(e[0]===e[1]&&(e[0]-=864e5,e[1]+=864e5),e[1]===-1/0&&e[0]===1/0){var i=new Date;e[1]=+new Date(i.getFullYear(),i.getMonth(),i.getDate()),e[0]=e[1]-864e5}this.niceTicks(t.splitNumber,t.minInterval,t.maxInterval);var n=this._interval;t.fixMin||(e[0]=Go(PA(e[0]/n)*n)),t.fixMax||(e[1]=Go(kA(e[1]/n)*n))},niceTicks:function(t,e,i){t=t||10;var n=this._extent,o=n[1]-n[0],a=o/t;null!=e&&a<e&&(a=e),null!=i&&a>i&&(a=i);var r=EA.length,s=NA(EA,a,0,r),l=EA[Math.min(s,r-1)],u=l[1];"year"===l[0]&&(u*=$o(o/u/t,!0));var h=this.getSetting("useUTC")?0:60*new Date(+n[0]||+n[1]).getTimezoneOffset()*1e3,c=[Math.round(kA((n[0]-h)/u)*u+h),Math.round(PA((n[1]-h)/u)*u+h)];Tl(c,n),this._stepLvl=l,this._interval=u,this._niceExtent=c},parse:function(t){return+Yo(t)}});d(["contain","normalize"],function(t){OA.prototype[t]=function(e){return LA[t].call(this,this.parse(e))}});var EA=[["hh:mm:ss",1e3],["hh:mm:ss",5e3],["hh:mm:ss",1e4],["hh:mm:ss",15e3],["hh:mm:ss",3e4],["hh:mm\nMM-dd",6e4],["hh:mm\nMM-dd",3e5],["hh:mm\nMM-dd",6e5],["hh:mm\nMM-dd",9e5],["hh:mm\nMM-dd",18e5],["hh:mm\nMM-dd",36e5],["hh:mm\nMM-dd",72e5],["hh:mm\nMM-dd",216e5],["hh:mm\nMM-dd",432e5],["MM-dd\nyyyy",864e5],["MM-dd\nyyyy",1728e5],["MM-dd\nyyyy",2592e5],["MM-dd\nyyyy",3456e5],["MM-dd\nyyyy",432e6],["MM-dd\nyyyy",5184e5],["week",6048e5],["MM-dd\nyyyy",864e6],["week",12096e5],["week",18144e5],["month",26784e5],["week",36288e5],["month",53568e5],["week",6048e6],["quarter",8208e6],["month",107136e5],["month",13392e6],["half-year",16416e6],["month",214272e5],["month",26784e6],["year",32832e6]];OA.create=function(t){return new OA({useUTC:t.ecModel.get("useUTC")})};var RA=xl.prototype,zA=TA.prototype,BA=Ho,VA=Go,GA=Math.floor,FA=Math.ceil,WA=Math.pow,HA=Math.log,ZA=xl.extend({type:"log",base:10,$constructor:function(){xl.apply(this,arguments),this._originalScale=new TA},getTicks:function(){var t=this._originalScale,e=this._extent,i=t.getExtent();return f(zA.getTicks.call(this),function(n){var o=Go(WA(this.base,n));return o=n===e[0]&&t.__fixMin?Vl(o,i[0]):o,o=n===e[1]&&t.__fixMax?Vl(o,i[1]):o},this)},getLabel:zA.getLabel,scale:function(t){return t=RA.scale.call(this,t),WA(this.base,t)},setExtent:function(t,e){var i=this.base;t=HA(t)/HA(i),e=HA(e)/HA(i),zA.setExtent.call(this,t,e)},getExtent:function(){var t=this.base,e=RA.getExtent.call(this);e[0]=WA(t,e[0]),e[1]=WA(t,e[1]);var i=this._originalScale,n=i.getExtent();return i.__fixMin&&(e[0]=Vl(e[0],n[0])),i.__fixMax&&(e[1]=Vl(e[1],n[1])),e},unionExtent:function(t){this._originalScale.unionExtent(t);var e=this.base;t[0]=HA(t[0])/HA(e),t[1]=HA(t[1])/HA(e),RA.unionExtent.call(this,t)},unionExtentFromData:function(t,e){this.unionExtent(t.getApproximateExtent(e))},niceTicks:function(t){t=t||10;var e=this._extent,i=e[1]-e[0];if(!(i===1/0||i<=0)){var n=qo(i);for(t/i*n<=.5&&(n*=10);!isNaN(n)&&Math.abs(n)<1&&Math.abs(n)>0;)n*=10;var o=[Go(FA(e[0]/n)*n),Go(GA(e[1]/n)*n)];this._interval=n,this._niceExtent=o}},niceExtent:function(t){zA.niceExtent.call(this,t);var e=this._originalScale;e.__fixMin=t.fixMin,e.__fixMax=t.fixMax}});d(["contain","normalize"],function(t){ZA.prototype[t]=function(e){return e=HA(e)/HA(this.base),RA[t].call(this,e)}}),ZA.create=function(){return new ZA};var UA={getMin:function(t){var e=this.option,i=t||null==e.rangeStart?e.min:e.rangeStart;return this.axis&&null!=i&&"dataMin"!==i&&"function"!=typeof i&&!I(i)&&(i=this.axis.scale.parse(i)),i},getMax:function(t){var e=this.option,i=t||null==e.rangeEnd?e.max:e.rangeEnd;return this.axis&&null!=i&&"dataMax"!==i&&"function"!=typeof i&&!I(i)&&(i=this.axis.scale.parse(i)),i},getNeedCrossZero:function(){var t=this.option;return null==t.rangeStart&&null==t.rangeEnd&&!t.scale},getCoordSysModel:B,setRange:function(t,e){this.option.rangeStart=t,this.option.rangeEnd=e},resetRange:function(){this.option.rangeStart=this.option.rangeEnd=null}},XA=Un({type:"triangle",shape:{cx:0,cy:0,width:0,height:0},buildPath:function(t,e){var i=e.cx,n=e.cy,o=e.width/2,a=e.height/2;t.moveTo(i,n-a),t.lineTo(i+o,n+a),t.lineTo(i-o,n+a),t.closePath()}}),jA=Un({type:"diamond",shape:{cx:0,cy:0,width:0,height:0},buildPath:function(t,e){var i=e.cx,n=e.cy,o=e.width/2,a=e.height/2;t.moveTo(i,n-a),t.lineTo(i+o,n),t.lineTo(i,n+a),t.lineTo(i-o,n),t.closePath()}}),YA=Un({type:"pin",shape:{x:0,y:0,width:0,height:0},buildPath:function(t,e){var i=e.x,n=e.y,o=e.width/5*3,a=Math.max(o,e.height),r=o/2,s=r*r/(a-r),l=n-a+r+s,u=Math.asin(s/r),h=Math.cos(u)*r,c=Math.sin(u),d=Math.cos(u),f=.6*r,p=.7*r;t.moveTo(i-h,l+s),t.arc(i,l,r,Math.PI-u,2*Math.PI+u),t.bezierCurveTo(i+h-c*f,l+s+d*f,i,n-p,i,n),t.bezierCurveTo(i,n-p,i-h+c*f,l+s+d*f,i-h,l+s),t.closePath()}}),qA=Un({type:"arrow",shape:{x:0,y:0,width:0,height:0},buildPath:function(t,e){var i=e.height,n=e.width,o=e.x,a=e.y,r=n/3*2;t.moveTo(o,a),t.lineTo(o+r,a+i),t.lineTo(o,a+i/4*3),t.lineTo(o-r,a+i),t.lineTo(o,a),t.closePath()}}),KA={line:function(t,e,i,n,o){o.x1=t,o.y1=e+n/2,o.x2=t+i,o.y2=e+n/2},rect:function(t,e,i,n,o){o.x=t,o.y=e,o.width=i,o.height=n},roundRect:function(t,e,i,n,o){o.x=t,o.y=e,o.width=i,o.height=n,o.r=Math.min(i,n)/4},square:function(t,e,i,n,o){var a=Math.min(i,n);o.x=t,o.y=e,o.width=a,o.height=a},circle:function(t,e,i,n,o){o.cx=t+i/2,o.cy=e+n/2,o.r=Math.min(i,n)/2},diamond:function(t,e,i,n,o){o.cx=t+i/2,o.cy=e+n/2,o.width=i,o.height=n},pin:function(t,e,i,n,o){o.x=t+i/2,o.y=e+n/2,o.width=i,o.height=n},arrow:function(t,e,i,n,o){o.x=t+i/2,o.y=e+n/2,o.width=i,o.height=n},triangle:function(t,e,i,n,o){o.cx=t+i/2,o.cy=e+n/2,o.width=i,o.height=n}},$A={};d({line:_M,rect:yM,roundRect:yM,square:yM,circle:sM,diamond:jA,pin:YA,arrow:qA,triangle:XA},function(t,e){$A[e]=new t});var JA=Un({type:"symbol",shape:{symbolType:"",x:0,y:0,width:0,height:0},beforeBrush:function(){var t=this.style;"pin"===this.shape.symbolType&&"inside"===t.textPosition&&(t.textPosition=["50%","40%"],t.textAlign="center",t.textVerticalAlign="middle")},buildPath:function(t,e,i){var n=e.symbolType,o=$A[n];"none"!==e.symbolType&&(o||(o=$A[n="rect"]),KA[n](e.x,e.y,e.width,e.height,o.shape),o.buildPath(t,o.shape,i))}}),QA={isDimensionStacked:pl,enableDataStack:fl,getStackedDimension:gl},tD=(Object.freeze||Object)({createList:function(t){return ml(t.getSource(),t)},getLayoutRect:ca,dataStack:QA,createScale:function(t,e){var i=e;No.isInstance(e)||h(i=new No(e),UA);var n=Hl(i);return n.setExtent(t[0],t[1]),Wl(n,i),n},mixinAxisModelCommonMethods:function(t){h(t,UA)},completeDimensions:hl,createDimensions:_A,createSymbol:Jl}),eD=1e-8;eu.prototype={constructor:eu,properties:null,getBoundingRect:function(){var t=this._rect;if(t)return t;for(var e=Number.MAX_VALUE,i=[e,e],n=[-e,-e],o=[],a=[],r=this.geometries,s=0;s<r.length;s++)"polygon"===r[s].type&&(fn(r[s].exterior,o,a),tt(i,i,o),et(n,n,a));return 0===s&&(i[0]=i[1]=n[0]=n[1]=0),this._rect=new de(i[0],i[1],n[0]-i[0],n[1]-i[1])},contain:function(t){var e=this.getBoundingRect(),i=this.geometries;if(!e.contain(t[0],t[1]))return!1;t:for(var n=0,o=i.length;n<o;n++)if("polygon"===i[n].type){var a=i[n].exterior,r=i[n].interiors;if(tu(a,t[0],t[1])){for(var s=0;s<(r?r.length:0);s++)if(tu(r[s]))continue t;return!0}}return!1},transformTo:function(t,e,i,n){var o=this.getBoundingRect(),a=o.width/o.height;i?n||(n=i/a):i=a*n;for(var r=new de(t,e,i,n),s=o.calculateTransform(r),l=this.geometries,u=0;u<l.length;u++)if("polygon"===l[u].type){for(var h=l[u].exterior,c=l[u].interiors,d=0;d<h.length;d++)Q(h[d],h[d],s);for(var f=0;f<(c?c.length:0);f++)for(d=0;d<c[f].length;d++)Q(c[f][d],c[f][d],s)}(o=this._rect).copy(r),this.center=[o.x+o.width/2,o.y+o.height/2]},cloneShallow:function(t){null==t&&(t=this.name);var e=new eu(t,this.geometries,this.center);return e._rect=this._rect,e.transformTo=null,e}};var iD=function(t){return iu(t),f(g(t.features,function(t){return t.geometry&&t.properties&&t.geometry.coordinates.length>0}),function(t){var e=t.properties,i=t.geometry,n=i.coordinates,o=[];"Polygon"===i.type&&o.push({type:"polygon",exterior:n[0],interiors:n.slice(1)}),"MultiPolygon"===i.type&&d(n,function(t){t[0]&&o.push({type:"polygon",exterior:t[0],interiors:t.slice(1)})});var a=new eu(e.name,o,e.cp);return a.properties=e,a})},nD=Bi(),oD=[0,1],aD=function(t,e,i){this.dim=t,this.scale=e,this._extent=i||[0,0],this.inverse=!1,this.onBand=!1};aD.prototype={constructor:aD,contain:function(t){var e=this._extent,i=Math.min(e[0],e[1]),n=Math.max(e[0],e[1]);return t>=i&&t<=n},containData:function(t){return this.contain(this.dataToCoord(t))},getExtent:function(){return this._extent.slice()},getPixelPrecision:function(t){return Zo(t||this.scale.getExtent(),this._extent)},setExtent:function(t,e){var i=this._extent;i[0]=t,i[1]=e},dataToCoord:function(t,e){var i=this._extent,n=this.scale;return t=n.normalize(t),this.onBand&&"ordinal"===n.type&&yu(i=i.slice(),n.count()),Bo(t,oD,i,e)},coordToData:function(t,e){var i=this._extent,n=this.scale;this.onBand&&"ordinal"===n.type&&yu(i=i.slice(),n.count());var o=Bo(t,i,oD,e);return this.scale.scale(o)},pointToData:function(t,e){},getTicksCoords:function(t){var e=(t=t||{}).tickModel||this.getTickModel(),i=au(this,e),n=f(i.ticks,function(t){return{coord:this.dataToCoord(t),tickValue:t}},this),o=e.get("alignWithLabel");return xu(this,n,i.tickCategoryInterval,o,t.clamp),n},getViewLabels:function(){return ou(this).labels},getLabelModel:function(){return this.model.getModel("axisLabel")},getTickModel:function(){return this.model.getModel("axisTick")},getBandWidth:function(){var t=this._extent,e=this.scale.getExtent(),i=e[1]-e[0]+(this.onBand?1:0);0===i&&(i=1);var n=Math.abs(t[1]-t[0]);return Math.abs(n)/i},isHorizontal:null,getRotate:null,calculateCategoryInterval:function(){return pu(this)}};var rD=iD,sD={};d(["map","each","filter","indexOf","inherits","reduce","filter","bind","curry","isArray","isString","isObject","isFunction","extend","defaults","clone","merge"],function(t){sD[t]=aw[t]});var lD={};d(["extendShape","extendPath","makePath","makeImage","mergePath","resizePath","createIcon","setHoverStyle","setLabelStyle","setTextStyle","setText","getFont","updateProps","initProps","getTransform","clipPointsByRect","clipRectByRect","Group","Image","Text","Circle","Sector","Ring","Polygon","Polyline","Rect","Line","BezierCurve","Arc","IncrementalDisplayable","CompoundPath","LinearGradient","RadialGradient","BoundingRect"],function(t){lD[t]=zM[t]}),YI.extend({type:"series.line",dependencies:["grid","polar"],getInitialData:function(t,e){return ml(this.getSource(),this)},defaultOption:{zlevel:0,z:2,coordinateSystem:"cartesian2d",legendHoverLink:!0,hoverAnimation:!0,clipOverflow:!0,label:{position:"top"},lineStyle:{width:2,type:"solid"},step:!1,smooth:!1,smoothMonotone:null,symbol:"emptyCircle",symbolSize:4,symbolRotate:null,showSymbol:!0,showAllSymbol:"auto",connectNulls:!1,sampling:"none",animationEasing:"linear",progressive:0,hoverLayerThreshold:1/0}});var uD=wu.prototype,hD=wu.getSymbolSize=function(t,e){var i=t.getItemVisual(e,"symbolSize");return i instanceof Array?i.slice():[+i,+i]};uD._createSymbol=function(t,e,i,n,o){this.removeAll();var a=Jl(t,-1,-1,2,2,e.getItemVisual(i,"color"),o);a.attr({z2:100,culling:!0,scale:bu(n)}),a.drift=Su,this._symbolType=t,this.add(a)},uD.stopSymbolAnimation=function(t){this.childAt(0).stopAnimation(t)},uD.getSymbolPath=function(){return this.childAt(0)},uD.getScale=function(){return this.childAt(0).scale},uD.highlight=function(){this.childAt(0).trigger("emphasis")},uD.downplay=function(){this.childAt(0).trigger("normal")},uD.setZ=function(t,e){var i=this.childAt(0);i.zlevel=t,i.z=e},uD.setDraggable=function(t){var e=this.childAt(0);e.draggable=t,e.cursor=t?"move":"pointer"},uD.updateData=function(t,e,i){this.silent=!1;var n=t.getItemVisual(e,"symbol")||"circle",o=t.hostModel,a=hD(t,e),r=n!==this._symbolType;if(r){var s=t.getItemVisual(e,"symbolKeepAspect");this._createSymbol(n,t,e,a,s)}else(l=this.childAt(0)).silent=!1,Io(l,{scale:bu(a)},o,e);if(this._updateCommon(t,e,a,i),r){var l=this.childAt(0),u=i&&i.fadeIn,h={scale:l.scale.slice()};u&&(h.style={opacity:l.style.opacity}),l.scale=[0,0],u&&(l.style.opacity=0),To(l,h,o,e)}this._seriesModel=o};var cD=["itemStyle"],dD=["emphasis","itemStyle"],fD=["label"],pD=["emphasis","label"];uD._updateCommon=function(t,e,i,n){var o=this.childAt(0),r=t.hostModel,s=t.getItemVisual(e,"color");"image"!==o.type&&o.useStyle({strokeNoScale:!0});var l=n&&n.itemStyle,u=n&&n.hoverItemStyle,h=n&&n.symbolRotate,c=n&&n.symbolOffset,d=n&&n.labelModel,f=n&&n.hoverLabelModel,p=n&&n.hoverAnimation,g=n&&n.cursorStyle;if(!n||t.hasItemOption){var m=n&&n.itemModel?n.itemModel:t.getItemModel(e);l=m.getModel(cD).getItemStyle(["color"]),u=m.getModel(dD).getItemStyle(),h=m.getShallow("symbolRotate"),c=m.getShallow("symbolOffset"),d=m.getModel(fD),f=m.getModel(pD),p=m.getShallow("hoverAnimation"),g=m.getShallow("cursor")}else u=a({},u);var v=o.style;o.attr("rotation",(h||0)*Math.PI/180||0),c&&o.attr("position",[Vo(c[0],i[0]),Vo(c[1],i[1])]),g&&o.attr("cursor",g),o.setColor(s,n&&n.symbolInnerColor),o.setStyle(l);var y=t.getItemVisual(e,"opacity");null!=y&&(v.opacity=y);var x=t.getItemVisual(e,"liftZ"),_=o.__z2Origin;null!=x?null==_&&(o.__z2Origin=o.z2,o.z2+=x):null!=_&&(o.z2=_,o.__z2Origin=null);var w=n&&n.useNameLabel;go(v,u,d,f,{labelFetcher:r,labelDataIndex:e,defaultText:function(e,i){return w?t.getName(e):_u(t,e)},isRectText:!0,autoColor:s}),o.off("mouseover").off("mouseout").off("emphasis").off("normal"),o.hoverStyle=u,fo(o),o.__symbolOriginalScale=bu(i),p&&r.isAnimationEnabled()&&o.on("mouseover",Mu).on("mouseout",Iu).on("emphasis",Tu).on("normal",Au)},uD.fadeOut=function(t,e){var i=this.childAt(0);this.silent=i.silent=!0,!(e&&e.keepLabel)&&(i.style.text=null),Io(i,{style:{opacity:0},scale:[0,0]},this._seriesModel,this.dataIndex,t)},u(wu,tb);var gD=Du.prototype;gD.updateData=function(t,e){e=Lu(e);var i=this.group,n=t.hostModel,o=this._data,a=this._symbolCtor,r=ku(t);o||i.removeAll(),t.diff(o).add(function(n){var o=t.getItemLayout(n);if(Cu(t,o,n,e)){var s=new a(t,n,r);s.attr("position",o),t.setItemGraphicEl(n,s),i.add(s)}}).update(function(s,l){var u=o.getItemGraphicEl(l),h=t.getItemLayout(s);Cu(t,h,s,e)?(u?(u.updateData(t,s,r),Io(u,{position:h},n)):(u=new a(t,s)).attr("position",h),i.add(u),t.setItemGraphicEl(s,u)):i.remove(u)}).remove(function(t){var e=o.getItemGraphicEl(t);e&&e.fadeOut(function(){i.remove(e)})}).execute(),this._data=t},gD.isPersistent=function(){return!0},gD.updateLayout=function(){var t=this._data;t&&t.eachItemGraphicEl(function(e,i){var n=t.getItemLayout(i);e.attr("position",n)})},gD.incrementalPrepareUpdate=function(t){this._seriesScope=ku(t),this._data=null,this.group.removeAll()},gD.incrementalUpdate=function(t,e,i){i=Lu(i);for(var n=t.start;n<t.end;n++){var o=e.getItemLayout(n);if(Cu(e,o,n,i)){var a=new this._symbolCtor(e,n,this._seriesScope);a.traverse(function(t){t.isGroup||(t.incremental=t.useHoverLayer=!0)}),a.attr("position",o),this.group.add(a),e.setItemGraphicEl(n,a)}}},gD.remove=function(t){var e=this.group,i=this._data;i&&t?i.eachItemGraphicEl(function(t){t.fadeOut(function(){e.remove(t)})}):e.removeAll()};var mD=function(t,e,i,n,o,a,r,s){for(var l=Eu(t,e),u=[],h=[],c=[],d=[],f=[],p=[],g=[],m=Pu(o,e,r),v=Pu(a,t,s),y=0;y<l.length;y++){var x=l[y],_=!0;switch(x.cmd){case"=":var w=t.getItemLayout(x.idx),b=e.getItemLayout(x.idx1);(isNaN(w[0])||isNaN(w[1]))&&(w=b.slice()),u.push(w),h.push(b),c.push(i[x.idx]),d.push(n[x.idx1]),g.push(e.getRawIndex(x.idx1));break;case"+":S=x.idx;u.push(o.dataToPoint([e.get(m.dataDimsForPoint[0],S),e.get(m.dataDimsForPoint[1],S)])),h.push(e.getItemLayout(S).slice()),c.push(Ou(m,o,e,S)),d.push(n[S]),g.push(e.getRawIndex(S));break;case"-":var S=x.idx,M=t.getRawIndex(S);M!==S?(u.push(t.getItemLayout(S)),h.push(a.dataToPoint([t.get(v.dataDimsForPoint[0],S),t.get(v.dataDimsForPoint[1],S)])),c.push(i[S]),d.push(Ou(v,a,t,S)),g.push(M)):_=!1}_&&(f.push(x),p.push(p.length))}p.sort(function(t,e){return g[t]-g[e]});for(var I=[],T=[],A=[],D=[],C=[],y=0;y<p.length;y++){S=p[y];I[y]=u[S],T[y]=h[S],A[y]=c[S],D[y]=d[S],C[y]=f[S]}return{current:I,next:T,stackedOnCurrent:A,stackedOnNext:D,status:C}},vD=tt,yD=et,xD=Z,_D=G,wD=[],bD=[],SD=[],MD=Pn.extend({type:"ec-polyline",shape:{points:[],smooth:0,smoothConstraint:!0,smoothMonotone:null,connectNulls:!1},style:{fill:null,stroke:"#000"},brush:uM(Pn.prototype.brush),buildPath:function(t,e){var i=e.points,n=0,o=i.length,a=Gu(i,e.smoothConstraint);if(e.connectNulls){for(;o>0&&Ru(i[o-1]);o--);for(;n<o&&Ru(i[n]);n++);}for(;n<o;)n+=zu(t,i,n,o,o,1,a.min,a.max,e.smooth,e.smoothMonotone,e.connectNulls)+1}}),ID=Pn.extend({type:"ec-polygon",shape:{points:[],stackedOnPoints:[],smooth:0,stackedOnSmooth:0,smoothConstraint:!0,smoothMonotone:null,connectNulls:!1},brush:uM(Pn.prototype.brush),buildPath:function(t,e){var i=e.points,n=e.stackedOnPoints,o=0,a=i.length,r=e.smoothMonotone,s=Gu(i,e.smoothConstraint),l=Gu(n,e.smoothConstraint);if(e.connectNulls){for(;a>0&&Ru(i[a-1]);a--);for(;o<a&&Ru(i[o]);o++);}for(;o<a;){var u=zu(t,i,o,a,a,1,s.min,s.max,e.smooth,r,e.connectNulls);zu(t,n,o+u-1,u,a,-1,l.min,l.max,e.stackedOnSmooth,r,e.connectNulls),o+=u+1,t.closePath()}}});Ar.extend({type:"line",init:function(){var t=new tb,e=new Du;this.group.add(e.group),this._symbolDraw=e,this._lineGroup=t},render:function(t,e,i){var n=t.coordinateSystem,o=this.group,a=t.getData(),s=t.getModel("lineStyle"),l=t.getModel("areaStyle"),u=a.mapArray(a.getItemLayout),h="polar"===n.type,c=this._coordSys,d=this._symbolDraw,f=this._polyline,p=this._polygon,g=this._lineGroup,m=t.get("animation"),v=!l.isEmpty(),y=l.get("origin"),x=Zu(n,a,Pu(n,a,y)),_=t.get("showSymbol"),w=_&&!h&&Ku(t,a,n),b=this._data;b&&b.eachItemGraphicEl(function(t,e){t.__temp&&(o.remove(t),b.setItemGraphicEl(e,null))}),_||d.remove(),o.add(g);var S=!h&&t.get("step");f&&c.type===n.type&&S===this._step?(v&&!p?p=this._newPolygon(u,x,n,m):p&&!v&&(g.remove(p),p=this._polygon=null),g.setClipPath(ju(n,!1,!1,t)),_&&d.updateData(a,{isIgnore:w,clipShape:ju(n,!1,!0,t)}),a.eachItemGraphicEl(function(t){t.stopAnimation(!0)}),Fu(this._stackedOnPoints,x)&&Fu(this._points,u)||(m?this._updateAnimation(a,x,n,i,S,y):(S&&(u=Yu(u,n,S),x=Yu(x,n,S)),f.setShape({points:u}),p&&p.setShape({points:u,stackedOnPoints:x})))):(_&&d.updateData(a,{isIgnore:w,clipShape:ju(n,!1,!0,t)}),S&&(u=Yu(u,n,S),x=Yu(x,n,S)),f=this._newPolyline(u,n,m),v&&(p=this._newPolygon(u,x,n,m)),g.setClipPath(ju(n,!0,!1,t)));var M=qu(a,n)||a.getVisual("color");f.useStyle(r(s.getLineStyle(),{fill:"none",stroke:M,lineJoin:"bevel"}));var I=t.get("smooth");if(I=Wu(t.get("smooth")),f.setShape({smooth:I,smoothMonotone:t.get("smoothMonotone"),connectNulls:t.get("connectNulls")}),p){var T=a.getCalculationInfo("stackedOnSeries"),A=0;p.useStyle(r(l.getAreaStyle(),{fill:M,opacity:.7,lineJoin:"bevel"})),T&&(A=Wu(T.get("smooth"))),p.setShape({smooth:I,stackedOnSmooth:A,smoothMonotone:t.get("smoothMonotone"),connectNulls:t.get("connectNulls")})}this._data=a,this._coordSys=n,this._stackedOnPoints=x,this._points=u,this._step=S,this._valueOrigin=y},dispose:function(){},highlight:function(t,e,i,n){var o=t.getData(),a=zi(o,n);if(!(a instanceof Array)&&null!=a&&a>=0){var r=o.getItemGraphicEl(a);if(!r){var s=o.getItemLayout(a);if(!s)return;(r=new wu(o,a)).position=s,r.setZ(t.get("zlevel"),t.get("z")),r.ignore=isNaN(s[0])||isNaN(s[1]),r.__temp=!0,o.setItemGraphicEl(a,r),r.stopSymbolAnimation(!0),this.group.add(r)}r.highlight()}else Ar.prototype.highlight.call(this,t,e,i,n)},downplay:function(t,e,i,n){var o=t.getData(),a=zi(o,n);if(null!=a&&a>=0){var r=o.getItemGraphicEl(a);r&&(r.__temp?(o.setItemGraphicEl(a,null),this.group.remove(r)):r.downplay())}else Ar.prototype.downplay.call(this,t,e,i,n)},_newPolyline:function(t){var e=this._polyline;return e&&this._lineGroup.remove(e),e=new MD({shape:{points:t},silent:!0,z2:10}),this._lineGroup.add(e),this._polyline=e,e},_newPolygon:function(t,e){var i=this._polygon;return i&&this._lineGroup.remove(i),i=new ID({shape:{points:t,stackedOnPoints:e},silent:!0}),this._lineGroup.add(i),this._polygon=i,i},_updateAnimation:function(t,e,i,n,o,a){var r=this._polyline,s=this._polygon,l=t.hostModel,u=mD(this._data,t,this._stackedOnPoints,e,this._coordSys,i,this._valueOrigin,a),h=u.current,c=u.stackedOnCurrent,d=u.next,f=u.stackedOnNext;o&&(h=Yu(u.current,i,o),c=Yu(u.stackedOnCurrent,i,o),d=Yu(u.next,i,o),f=Yu(u.stackedOnNext,i,o)),r.shape.__points=u.current,r.shape.points=h,Io(r,{shape:{points:d}},l),s&&(s.setShape({points:h,stackedOnPoints:c}),Io(s,{shape:{points:d,stackedOnPoints:f}},l));for(var p=[],g=u.status,m=0;m<g.length;m++)if("="===g[m].cmd){var v=t.getItemGraphicEl(g[m].idx1);v&&p.push({el:v,ptIdx:m})}r.animators&&r.animators.length&&r.animators[0].during(function(){for(var t=0;t<p.length;t++)p[t].el.attr("position",r.shape.__points[p[t].ptIdx])})},remove:function(t){var e=this.group,i=this._data;this._lineGroup.removeAll(),this._symbolDraw.remove(!0),i&&i.eachItemGraphicEl(function(t,n){t.__temp&&(e.remove(t),i.setItemGraphicEl(n,null))}),this._polyline=this._polygon=this._coordSys=this._points=this._stackedOnPoints=this._data=null}});var TD=function(t,e,i){return{seriesType:t,performRawSeries:!0,reset:function(t,n,o){var a=t.getData(),r=t.get("symbol")||e,s=t.get("symbolSize"),l=t.get("symbolKeepAspect");if(a.setVisual({legendSymbol:i||r,symbol:r,symbolSize:s,symbolKeepAspect:l}),!n.isSeriesFiltered(t)){var u="function"==typeof s;return{dataEach:a.hasItemOption||u?function(e,i){if("function"==typeof s){var n=t.getRawValue(i),o=t.getDataParams(i);e.setItemVisual(i,"symbolSize",s(n,o))}if(e.hasItemOption){var a=e.getItemModel(i),r=a.getShallow("symbol",!0),l=a.getShallow("symbolSize",!0),u=a.getShallow("symbolKeepAspect",!0);null!=r&&e.setItemVisual(i,"symbol",r),null!=l&&e.setItemVisual(i,"symbolSize",l),null!=u&&e.setItemVisual(i,"symbolKeepAspect",u)}}:null}}}}},AD=function(t){return{seriesType:t,plan:$I(),reset:function(t){var e=t.getData(),i=t.coordinateSystem,n=t.pipelineContext.large;if(i){var o=f(i.dimensions,function(t){return e.mapDimension(t)}).slice(0,2),a=o.length,r=e.getCalculationInfo("stackResultDimension");return pl(e,o[0])&&(o[0]=r),pl(e,o[1])&&(o[1]=r),a&&{progress:function(t,e){for(var r=t.end-t.start,s=n&&new Float32Array(r*a),l=t.start,u=0,h=[],c=[];l<t.end;l++){var d;if(1===a)f=e.get(o[0],l),d=!isNaN(f)&&i.dataToPoint(f,null,c);else{var f=h[0]=e.get(o[0],l),p=h[1]=e.get(o[1],l);d=!isNaN(f)&&!isNaN(p)&&i.dataToPoint(h,null,c)}n?(s[u++]=d?d[0]:NaN,s[u++]=d?d[1]:NaN):e.setItemLayout(l,d&&d.slice()||[NaN,NaN])}n&&e.setLayout("symbolPoints",s)}}}}}},DD={average:function(t){for(var e=0,i=0,n=0;n<t.length;n++)isNaN(t[n])||(e+=t[n],i++);return 0===i?NaN:e/i},sum:function(t){for(var e=0,i=0;i<t.length;i++)e+=t[i]||0;return e},max:function(t){for(var e=-1/0,i=0;i<t.length;i++)t[i]>e&&(e=t[i]);return isFinite(e)?e:NaN},min:function(t){for(var e=1/0,i=0;i<t.length;i++)t[i]<e&&(e=t[i]);return isFinite(e)?e:NaN},nearest:function(t){return t[0]}},CD=function(t,e){return Math.round(t.length/2)},LD=function(t){this._axes={},this._dimList=[],this.name=t||""};LD.prototype={constructor:LD,type:"cartesian",getAxis:function(t){return this._axes[t]},getAxes:function(){return f(this._dimList,Ju,this)},getAxesByScale:function(t){return t=t.toLowerCase(),g(this.getAxes(),function(e){return e.scale.type===t})},addAxis:function(t){var e=t.dim;this._axes[e]=t,this._dimList.push(e)},dataToCoord:function(t){return this._dataCoordConvert(t,"dataToCoord")},coordToData:function(t){return this._dataCoordConvert(t,"coordToData")},_dataCoordConvert:function(t,e){for(var i=this._dimList,n=t instanceof Array?[]:{},o=0;o<i.length;o++){var a=i[o],r=this._axes[a];n[a]=r[e](t[a])}return n}},Qu.prototype={constructor:Qu,type:"cartesian2d",dimensions:["x","y"],getBaseAxis:function(){return this.getAxesByScale("ordinal")[0]||this.getAxesByScale("time")[0]||this.getAxis("x")},containPoint:function(t){var e=this.getAxis("x"),i=this.getAxis("y");return e.contain(e.toLocalCoord(t[0]))&&i.contain(i.toLocalCoord(t[1]))},containData:function(t){return this.getAxis("x").containData(t[0])&&this.getAxis("y").containData(t[1])},dataToPoint:function(t,e,i){var n=this.getAxis("x"),o=this.getAxis("y");return i=i||[],i[0]=n.toGlobalCoord(n.dataToCoord(t[0])),i[1]=o.toGlobalCoord(o.dataToCoord(t[1])),i},clampData:function(t,e){var i=this.getAxis("x").scale,n=this.getAxis("y").scale,o=i.getExtent(),a=n.getExtent(),r=i.parse(t[0]),s=n.parse(t[1]);return e=e||[],e[0]=Math.min(Math.max(Math.min(o[0],o[1]),r),Math.max(o[0],o[1])),e[1]=Math.min(Math.max(Math.min(a[0],a[1]),s),Math.max(a[0],a[1])),e},pointToData:function(t,e){var i=this.getAxis("x"),n=this.getAxis("y");return e=e||[],e[0]=i.coordToData(i.toLocalCoord(t[0])),e[1]=n.coordToData(n.toLocalCoord(t[1])),e},getOtherAxis:function(t){return this.getAxis("x"===t.dim?"y":"x")}},u(Qu,LD);var kD=function(t,e,i,n,o){aD.call(this,t,e,i),this.type=n||"value",this.position=o||"bottom"};kD.prototype={constructor:kD,index:0,getAxesOnZeroOf:null,model:null,isHorizontal:function(){var t=this.position;return"top"===t||"bottom"===t},getGlobalExtent:function(t){var e=this.getExtent();return e[0]=this.toGlobalCoord(e[0]),e[1]=this.toGlobalCoord(e[1]),t&&e[0]>e[1]&&e.reverse(),e},getOtherAxis:function(){this.grid.getOtherAxis()},pointToData:function(t,e){return this.coordToData(this.toLocalCoord(t["x"===this.dim?0:1]),e)},toLocalCoord:null,toGlobalCoord:null},u(kD,aD);var PD={show:!0,zlevel:0,z:0,inverse:!1,name:"",nameLocation:"end",nameRotate:null,nameTruncate:{maxWidth:null,ellipsis:"...",placeholder:"."},nameTextStyle:{},nameGap:15,silent:!1,triggerEvent:!1,tooltip:{show:!1},axisPointer:{},axisLine:{show:!0,onZero:!0,onZeroAxisIndex:null,lineStyle:{color:"#333",width:1,type:"solid"},symbol:["none","none"],symbolSize:[10,15]},axisTick:{show:!0,inside:!1,length:5,lineStyle:{width:1}},axisLabel:{show:!0,inside:!1,rotate:0,showMinLabel:null,showMaxLabel:null,margin:8,fontSize:12},splitLine:{show:!0,lineStyle:{color:["#ccc"],width:1,type:"solid"}},splitArea:{show:!1,areaStyle:{color:["rgba(250,250,250,0.3)","rgba(200,200,200,0.3)"]}}},ND={};ND.categoryAxis=n({boundaryGap:!0,deduplication:null,splitLine:{show:!1},axisTick:{alignWithLabel:!1,interval:"auto"},axisLabel:{interval:"auto"}},PD),ND.valueAxis=n({boundaryGap:[0,0],splitNumber:5},PD),ND.timeAxis=r({scale:!0,min:"dataMin",max:"dataMax"},ND.valueAxis),ND.logAxis=r({scale:!0,logBase:10},ND.valueAxis);var OD=["value","category","time","log"],ED=function(t,e,i,a){d(OD,function(r){e.extend({type:t+"Axis."+r,mergeDefaultAndTheme:function(e,o){var a=this.layoutMode,s=a?ga(e):{};n(e,o.getTheme().get(r+"Axis")),n(e,this.getDefaultOption()),e.type=i(t,e),a&&pa(e,s,a)},optionUpdated:function(){"category"===this.option.type&&(this.__ordinalMeta=_l.createByAxisModel(this))},getCategories:function(t){var e=this.option;if("category"===e.type)return t?e.data:this.__ordinalMeta.categories},getOrdinalMeta:function(){return this.__ordinalMeta},defaultOption:o([{},ND[r+"Axis"],a],!0)})}),lI.registerSubTypeDefaulter(t+"Axis",v(i,t))},RD=lI.extend({type:"cartesian2dAxis",axis:null,init:function(){RD.superApply(this,"init",arguments),this.resetRange()},mergeOption:function(){RD.superApply(this,"mergeOption",arguments),this.resetRange()},restoreData:function(){RD.superApply(this,"restoreData",arguments),this.resetRange()},getCoordSysModel:function(){return this.ecModel.queryComponents({mainType:"grid",index:this.option.gridIndex,id:this.option.gridId})[0]}});n(RD.prototype,UA);var zD={offset:0};ED("x",RD,th,zD),ED("y",RD,th,zD),lI.extend({type:"grid",dependencies:["xAxis","yAxis"],layoutMode:"box",coordinateSystem:null,defaultOption:{show:!1,zlevel:0,z:0,left:"10%",top:60,right:"10%",bottom:60,containLabel:!1,backgroundColor:"rgba(0,0,0,0)",borderWidth:1,borderColor:"#ccc"}});var BD=ih.prototype;BD.type="grid",BD.axisPointerEnabled=!0,BD.getRect=function(){return this._rect},BD.update=function(t,e){var i=this._axesMap;this._updateScale(t,this.model),d(i.x,function(t){Wl(t.scale,t.model)}),d(i.y,function(t){Wl(t.scale,t.model)});var n={};d(i.x,function(t){nh(i,"y",t,n)}),d(i.y,function(t){nh(i,"x",t,n)}),this.resize(this.model,e)},BD.resize=function(t,e,i){function n(){d(a,function(t){var e=t.isHorizontal(),i=e?[0,o.width]:[0,o.height],n=t.inverse?1:0;t.setExtent(i[n],i[1-n]),ah(t,e?o.x:o.y)})}var o=ca(t.getBoxLayoutParams(),{width:e.getWidth(),height:e.getHeight()});this._rect=o;var a=this._axesList;n(),!i&&t.get("containLabel")&&(d(a,function(t){if(!t.model.get("axisLabel.inside")){var e=jl(t);if(e){var i=t.isHorizontal()?"height":"width",n=t.model.get("axisLabel.margin");o[i]-=e[i]+n,"top"===t.position?o.y+=e.height+n:"left"===t.position&&(o.x+=e.width+n)}}}),n())},BD.getAxis=function(t,e){var i=this._axesMap[t];if(null!=i){if(null==e)for(var n in i)if(i.hasOwnProperty(n))return i[n];return i[e]}},BD.getAxes=function(){return this._axesList.slice()},BD.getCartesian=function(t,e){if(null!=t&&null!=e){var i="x"+t+"y"+e;return this._coordsMap[i]}w(t)&&(e=t.yAxisIndex,t=t.xAxisIndex);for(var n=0,o=this._coordsList;n<o.length;n++)if(o[n].getAxis("x").index===t||o[n].getAxis("y").index===e)return o[n]},BD.getCartesians=function(){return this._coordsList.slice()},BD.convertToPixel=function(t,e,i){var n=this._findConvertTarget(t,e);return n.cartesian?n.cartesian.dataToPoint(i):n.axis?n.axis.toGlobalCoord(n.axis.dataToCoord(i)):null},BD.convertFromPixel=function(t,e,i){var n=this._findConvertTarget(t,e);return n.cartesian?n.cartesian.pointToData(i):n.axis?n.axis.coordToData(n.axis.toLocalCoord(i)):null},BD._findConvertTarget=function(t,e){var i,n,o=e.seriesModel,a=e.xAxisModel||o&&o.getReferringComponents("xAxis")[0],r=e.yAxisModel||o&&o.getReferringComponents("yAxis")[0],s=e.gridModel,u=this._coordsList;return o?l(u,i=o.coordinateSystem)<0&&(i=null):a&&r?i=this.getCartesian(a.componentIndex,r.componentIndex):a?n=this.getAxis("x",a.componentIndex):r?n=this.getAxis("y",r.componentIndex):s&&s.coordinateSystem===this&&(i=this._coordsList[0]),{cartesian:i,axis:n}},BD.containPoint=function(t){var e=this._coordsList[0];if(e)return e.containPoint(t)},BD._initCartesian=function(t,e,i){function n(i){return function(n,s){if(eh(n,t,e)){var l=n.get("position");"x"===i?"top"!==l&&"bottom"!==l&&o[l="bottom"]&&(l="top"===l?"bottom":"top"):"left"!==l&&"right"!==l&&o[l="left"]&&(l="left"===l?"right":"left"),o[l]=!0;var u=new kD(i,Hl(n),[0,0],n.get("type"),l),h="category"===u.type;u.onBand=h&&n.get("boundaryGap"),u.inverse=n.get("inverse"),n.axis=u,u.model=n,u.grid=this,u.index=s,this._axesList.push(u),a[i][s]=u,r[i]++}}}var o={left:!1,right:!1,top:!1,bottom:!1},a={x:{},y:{}},r={x:0,y:0};if(e.eachComponent("xAxis",n("x"),this),e.eachComponent("yAxis",n("y"),this),!r.x||!r.y)return this._axesMap={},void(this._axesList=[]);this._axesMap=a,d(a.x,function(e,i){d(a.y,function(n,o){var a="x"+i+"y"+o,r=new Qu(a);r.grid=this,r.model=t,this._coordsMap[a]=r,this._coordsList.push(r),r.addAxis(e),r.addAxis(n)},this)},this)},BD._updateScale=function(t,e){function i(t,e,i){d(t.mapDimension(e.dim,!0),function(i){e.scale.unionExtentFromData(t,gl(t,i))})}d(this._axesList,function(t){t.scale.setExtent(1/0,-1/0)}),t.eachSeries(function(n){if(sh(n)){var o=rh(n),a=o[0],r=o[1];if(!eh(a,e,t)||!eh(r,e,t))return;var s=this.getCartesian(a.componentIndex,r.componentIndex),l=n.getData(),u=s.getAxis("x"),h=s.getAxis("y");"list"===l.type&&(i(l,u),i(l,h))}},this)},BD.getTooltipAxes=function(t){var e=[],i=[];return d(this.getCartesians(),function(n){var o=null!=t&&"auto"!==t?n.getAxis(t):n.getBaseAxis(),a=n.getOtherAxis(o);l(e,o)<0&&e.push(o),l(i,a)<0&&i.push(a)}),{baseAxes:e,otherAxes:i}};var VD=["xAxis","yAxis"];ih.create=function(t,e){var i=[];return t.eachComponent("grid",function(n,o){var a=new ih(n,t,e);a.name="grid_"+o,a.resize(n,e,!0),n.coordinateSystem=a,i.push(a)}),t.eachSeries(function(t){if(sh(t)){var e=rh(t),i=e[0],n=e[1],o=i.getCoordSysModel().coordinateSystem;t.coordinateSystem=o.getCartesian(i.componentIndex,n.componentIndex)}}),i},ih.dimensions=ih.prototype.dimensions=Qu.prototype.dimensions,Fa.register("cartesian2d",ih);var GD=Math.PI,FD=function(t,e){this.opt=e,this.axisModel=t,r(e,{labelOffset:0,nameDirection:1,tickDirection:1,labelDirection:1,silent:!0}),this.group=new tb;var i=new tb({position:e.position.slice(),rotation:e.rotation});i.updateTransform(),this._transform=i.transform,this._dumbGroup=i};FD.prototype={constructor:FD,hasBuilder:function(t){return!!WD[t]},add:function(t){WD[t].call(this)},getGroup:function(){return this.group}};var WD={axisLine:function(){var t=this.opt,e=this.axisModel;if(e.get("axisLine.show")){var i=this.axisModel.axis.getExtent(),n=this._transform,o=[i[0],0],r=[i[1],0];n&&(Q(o,o,n),Q(r,r,n));var s=a({lineCap:"round"},e.getModel("axisLine.lineStyle").getLineStyle());this.group.add(new _M(Kn({anid:"line",shape:{x1:o[0],y1:o[1],x2:r[0],y2:r[1]},style:s,strokeContainThreshold:t.strokeContainThreshold||5,silent:!0,z2:1})));var l=e.get("axisLine.symbol"),u=e.get("axisLine.symbolSize"),h=e.get("axisLine.symbolOffset")||0;if("number"==typeof h&&(h=[h,h]),null!=l){"string"==typeof l&&(l=[l,l]),"string"!=typeof u&&"number"!=typeof u||(u=[u,u]);var c=u[0],f=u[1];d([{rotate:t.rotation+Math.PI/2,offset:h[0],r:0},{rotate:t.rotation-Math.PI/2,offset:h[1],r:Math.sqrt((o[0]-r[0])*(o[0]-r[0])+(o[1]-r[1])*(o[1]-r[1]))}],function(e,i){if("none"!==l[i]&&null!=l[i]){var n=Jl(l[i],-c/2,-f/2,c,f,s.stroke,!0),a=e.r+e.offset,r=[o[0]+a*Math.cos(t.rotation),o[1]-a*Math.sin(t.rotation)];n.attr({rotation:e.rotate,position:r,silent:!0,z2:11}),this.group.add(n)}},this)}}},axisTickLabel:function(){var t=this.axisModel,e=this.opt,i=gh(this,t,e);ch(t,mh(this,t,e),i)},axisName:function(){var t=this.opt,e=this.axisModel,i=T(t.axisName,e.get("name"));if(i){var n,o=e.get("nameLocation"),r=t.nameDirection,s=e.getModel("nameTextStyle"),l=e.get("nameGap")||0,u=this.axisModel.axis.getExtent(),h=u[0]>u[1]?-1:1,c=["start"===o?u[0]-h*l:"end"===o?u[1]+h*l:(u[0]+u[1])/2,ph(o)?t.labelOffset+r*l:0],d=e.get("nameRotate");null!=d&&(d=d*GD/180);var f;ph(o)?n=HD(t.rotation,null!=d?d:t.rotation,r):(n=uh(t,o,d||0,u),null!=(f=t.axisNameAvailableWidth)&&(f=Math.abs(f/Math.sin(n.rotation)),!isFinite(f)&&(f=null)));var p=s.getFont(),g=e.get("nameTruncate",!0)||{},m=g.ellipsis,v=T(t.nameTruncateMaxWidth,g.maxWidth,f),y=null!=m&&null!=v?tI(i,v,p,m,{minChar:2,placeholder:g.placeholder}):i,x=e.get("tooltip",!0),_=e.mainType,w={componentType:_,name:i,$vars:["name"]};w[_+"Index"]=e.componentIndex;var b=new rM({anid:"name",__fullText:i,__truncatedText:y,position:c,rotation:n.rotation,silent:hh(e),z2:1,tooltip:x&&x.show?a({content:i,formatter:function(){return i},formatterParams:w},x):null});mo(b.style,s,{text:y,textFont:p,textFill:s.getTextColor()||e.get("axisLine.lineStyle.color"),textAlign:n.textAlign,textVerticalAlign:n.textVerticalAlign}),e.get("triggerEvent")&&(b.eventData=lh(e),b.eventData.targetType="axisName",b.eventData.name=i),this._dumbGroup.add(b),b.updateTransform(),this.group.add(b),b.decomposeTransform()}}},HD=FD.innerTextLayout=function(t,e,i){var n,o,a=Xo(e-t);return jo(a)?(o=i>0?"top":"bottom",n="center"):jo(a-GD)?(o=i>0?"bottom":"top",n="center"):(o="middle",n=a>0&&a<GD?i>0?"right":"left":i>0?"left":"right"),{rotation:a,textAlign:n,textVerticalAlign:o}},ZD=d,UD=v,XD=Ws({type:"axis",_axisPointer:null,axisPointerClass:null,render:function(t,e,i,n){this.axisPointerClass&&Sh(t),XD.superApply(this,"render",arguments),Dh(this,t,0,i,0,!0)},updateAxisPointer:function(t,e,i,n,o){Dh(this,t,0,i,0,!1)},remove:function(t,e){var i=this._axisPointer;i&&i.remove(e),XD.superApply(this,"remove",arguments)},dispose:function(t,e){Ch(this,e),XD.superApply(this,"dispose",arguments)}}),jD=[];XD.registerAxisPointerClass=function(t,e){jD[t]=e},XD.getAxisPointerClass=function(t){return t&&jD[t]};var YD=["axisLine","axisTickLabel","axisName"],qD=["splitArea","splitLine"],KD=XD.extend({type:"cartesianAxis",axisPointerClass:"CartesianAxisPointer",render:function(t,e,i,n){this.group.removeAll();var o=this._axisGroup;if(this._axisGroup=new tb,this.group.add(this._axisGroup),t.get("show")){var a=t.getCoordSysModel(),r=Lh(a,t),s=new FD(t,r);d(YD,s.add,s),this._axisGroup.add(s.getGroup()),d(qD,function(e){t.get(e+".show")&&this["_"+e](t,a)},this),Lo(o,this._axisGroup,t),KD.superCall(this,"render",t,e,i,n)}},remove:function(){this._splitAreaColors=null},_splitLine:function(t,e){var i=t.axis;if(!i.scale.isBlank()){var n=t.getModel("splitLine"),o=n.getModel("lineStyle"),a=o.get("color");a=y(a)?a:[a];for(var s=e.coordinateSystem.getRect(),l=i.isHorizontal(),u=0,h=i.getTicksCoords({tickModel:n}),c=[],d=[],f=o.getLineStyle(),p=0;p<h.length;p++){var g=i.toGlobalCoord(h[p].coord);l?(c[0]=g,c[1]=s.y,d[0]=g,d[1]=s.y+s.height):(c[0]=s.x,c[1]=g,d[0]=s.x+s.width,d[1]=g);var m=u++%a.length,v=h[p].tickValue;this._axisGroup.add(new _M(Kn({anid:null!=v?"line_"+h[p].tickValue:null,shape:{x1:c[0],y1:c[1],x2:d[0],y2:d[1]},style:r({stroke:a[m]},f),silent:!0})))}}},_splitArea:function(t,e){var i=t.axis;if(!i.scale.isBlank()){var n=t.getModel("splitArea"),o=n.getModel("areaStyle"),a=o.get("color"),s=e.coordinateSystem.getRect(),l=i.getTicksCoords({tickModel:n,clamp:!0});if(l.length){var u=a.length,h=this._splitAreaColors,c=R(),d=0;if(h)for(m=0;m<l.length;m++){var f=h.get(l[m].tickValue);if(null!=f){d=(f+(u-1)*m)%u;break}}var p=i.toGlobalCoord(l[0].coord),g=o.getAreaStyle();a=y(a)?a:[a];for(var m=1;m<l.length;m++){var v,x,_,w,b=i.toGlobalCoord(l[m].coord);i.isHorizontal()?(v=p,x=s.y,_=b-v,w=s.height,p=v+_):(v=s.x,x=p,_=s.width,p=x+(w=b-x));var S=l[m-1].tickValue;null!=S&&c.set(S,d),this._axisGroup.add(new yM({anid:null!=S?"area_"+S:null,shape:{x:v,y:x,width:_,height:w},style:r({fill:a[d]},g),silent:!0})),d=(d+1)%u}this._splitAreaColors=c}}}});KD.extend({type:"xAxis"}),KD.extend({type:"yAxis"}),Ws({type:"grid",render:function(t,e){this.group.removeAll(),t.get("show")&&this.group.add(new yM({shape:t.coordinateSystem.getRect(),style:r({fill:t.get("backgroundColor")},t.getItemStyle()),silent:!0,z2:-1}))}}),Ns(function(t){t.xAxis&&t.yAxis&&!t.grid&&(t.grid={})}),Bs(TD("line","circle","line")),zs(AD("line")),Os(VT.PROCESSOR.STATISTIC,function(t){return{seriesType:t,modifyOutputEnd:!0,reset:function(t,e,i){var n=t.getData(),o=t.get("sampling"),a=t.coordinateSystem;if("cartesian2d"===a.type&&o){var r=a.getBaseAxis(),s=a.getOtherAxis(r),l=r.getExtent(),u=l[1]-l[0],h=Math.round(n.count()/u);if(h>1){var c;"string"==typeof o?c=DD[o]:"function"==typeof o&&(c=o),c&&t.setData(n.downSample(n.mapDimension(s.dim),1/h,c,CD))}}}}}("line"));var $D=YI.extend({type:"series.__base_bar__",getInitialData:function(t,e){return ml(this.getSource(),this)},getMarkerPosition:function(t){var e=this.coordinateSystem;if(e){var i=e.dataToPoint(e.clampData(t)),n=this.getData(),o=n.getLayout("offset"),a=n.getLayout("size");return i[e.getBaseAxis().isHorizontal()?0:1]+=o+a/2,i}return[NaN,NaN]},defaultOption:{zlevel:0,z:2,coordinateSystem:"cartesian2d",legendHoverLink:!0,barMinHeight:0,barMinAngle:0,large:!1,largeThreshold:400,progressive:3e3,progressiveChunkMode:"mod",itemStyle:{},emphasis:{}}});$D.extend({type:"series.bar",dependencies:["grid","polar"],brushSelector:"rect",getProgressive:function(){return!!this.get("large")&&this.get("progressive")},getProgressiveThreshold:function(){var t=this.get("progressiveThreshold"),e=this.get("largeThreshold");return e>t&&(t=e),t}});var JD=Qb([["fill","color"],["stroke","borderColor"],["lineWidth","borderWidth"],["stroke","barBorderColor"],["lineWidth","barBorderWidth"],["opacity"],["shadowBlur"],["shadowOffsetX"],["shadowOffsetY"],["shadowColor"]]),QD={getBarItemStyle:function(t){var e=JD(this,t);if(this.getBorderLineDash){var i=this.getBorderLineDash();i&&(e.lineDash=i)}return e}},tC=["itemStyle","barBorderWidth"];a(No.prototype,QD),Zs({type:"bar",render:function(t,e,i){this._updateDrawMode(t);var n=t.get("coordinateSystem");return"cartesian2d"!==n&&"polar"!==n||(this._isLargeDraw?this._renderLarge(t,e,i):this._renderNormal(t,e,i)),this.group},incrementalPrepareRender:function(t,e,i){this._clear(),this._updateDrawMode(t)},incrementalRender:function(t,e,i,n){this._incrementalRenderLarge(t,e)},_updateDrawMode:function(t){var e=t.pipelineContext.large;(null==this._isLargeDraw||e^this._isLargeDraw)&&(this._isLargeDraw=e,this._clear())},_renderNormal:function(t,e,i){var n,o=this.group,a=t.getData(),r=this._data,s=t.coordinateSystem,l=s.getBaseAxis();"cartesian2d"===s.type?n=l.isHorizontal():"polar"===s.type&&(n="angle"===l.dim);var u=t.isAnimationEnabled()?t:null;a.diff(r).add(function(e){if(a.hasValue(e)){var i=a.getItemModel(e),r=iC[s.type](a,e,i),l=eC[s.type](a,e,i,r,n,u);a.setItemGraphicEl(e,l),o.add(l),Eh(l,a,e,i,r,t,n,"polar"===s.type)}}).update(function(e,i){var l=r.getItemGraphicEl(i);if(a.hasValue(e)){var h=a.getItemModel(e),c=iC[s.type](a,e,h);l?Io(l,{shape:c},u,e):l=eC[s.type](a,e,h,c,n,u,!0),a.setItemGraphicEl(e,l),o.add(l),Eh(l,a,e,h,c,t,n,"polar"===s.type)}else o.remove(l)}).remove(function(t){var e=r.getItemGraphicEl(t);"cartesian2d"===s.type?e&&Nh(t,u,e):e&&Oh(t,u,e)}).execute(),this._data=a},_renderLarge:function(t,e,i){this._clear(),zh(t,this.group)},_incrementalRenderLarge:function(t,e){zh(e,this.group,!0)},dispose:B,remove:function(t){this._clear(t)},_clear:function(t){var e=this.group,i=this._data;t&&t.get("animation")&&i&&!this._isLargeDraw?i.eachItemGraphicEl(function(e){"sector"===e.type?Oh(e.dataIndex,t,e):Nh(e.dataIndex,t,e)}):e.removeAll(),this._data=null}});var eC={cartesian2d:function(t,e,i,n,o,r,s){var l=new yM({shape:a({},n)});if(r){var u=l.shape,h=o?"height":"width",c={};u[h]=0,c[h]=n[h],zM[s?"updateProps":"initProps"](l,{shape:c},r,e)}return l},polar:function(t,e,i,n,o,a,s){var l=n.startAngle<n.endAngle,u=new hM({shape:r({clockwise:l},n)});if(a){var h=u.shape,c=o?"r":"endAngle",d={};h[c]=o?0:n.startAngle,d[c]=n[c],zM[s?"updateProps":"initProps"](u,{shape:d},a,e)}return u}},iC={cartesian2d:function(t,e,i){var n=t.getItemLayout(e),o=Rh(i,n),a=n.width>0?1:-1,r=n.height>0?1:-1;return{x:n.x+a*o/2,y:n.y+r*o/2,width:n.width-a*o,height:n.height-r*o}},polar:function(t,e,i){var n=t.getItemLayout(e);return{cx:n.cx,cy:n.cy,r0:n.r0,r:n.r,startAngle:n.startAngle,endAngle:n.endAngle}}},nC=Pn.extend({type:"largeBar",shape:{points:[]},buildPath:function(t,e){for(var i=e.points,n=this.__startPoint,o=this.__valueIdx,a=0;a<i.length;a+=2)n[this.__valueIdx]=i[a+o],t.moveTo(n[0],n[1]),t.lineTo(i[a],i[a+1])}});zs(v(El,"bar")),zs(CA),Bs({seriesType:"bar",reset:function(t){t.getData().setVisual("legendSymbol","roundRect")}});var oC=function(t,e,i){e=y(e)&&{coordDimensions:e}||a({},e);var n=t.getSource(),o=_A(n,e),r=new vA(o,t);return r.initData(n,i),r},aC={updateSelectedMap:function(t){this._targetList=y(t)?t.slice():[],this._selectTargetMap=p(t||[],function(t,e){return t.set(e.name,e),t},R())},select:function(t,e){var i=null!=e?this._targetList[e]:this._selectTargetMap.get(t);"single"===this.get("selectedMode")&&this._selectTargetMap.each(function(t){t.selected=!1}),i&&(i.selected=!0)},unSelect:function(t,e){var i=null!=e?this._targetList[e]:this._selectTargetMap.get(t);i&&(i.selected=!1)},toggleSelected:function(t,e){var i=null!=e?this._targetList[e]:this._selectTargetMap.get(t);if(null!=i)return this[i.selected?"unSelect":"select"](t,e),i.selected},isSelected:function(t,e){var i=null!=e?this._targetList[e]:this._selectTargetMap.get(t);return i&&i.selected}},rC=Hs({type:"series.pie",init:function(t){rC.superApply(this,"init",arguments),this.legendDataProvider=function(){return this.getRawData()},this.updateSelectedMap(this._createSelectableList()),this._defaultLabelLine(t)},mergeOption:function(t){rC.superCall(this,"mergeOption",t),this.updateSelectedMap(this._createSelectableList())},getInitialData:function(t,e){return oC(this,["value"])},_createSelectableList:function(){for(var t=this.getRawData(),e=t.mapDimension("value"),i=[],n=0,o=t.count();n<o;n++)i.push({name:t.getName(n),value:t.get(e,n),selected:pr(t,n,"selected")});return i},getDataParams:function(t){var e=this.getData(),i=rC.superCall(this,"getDataParams",t),n=[];return e.each(e.mapDimension("value"),function(t){n.push(t)}),i.percent=Uo(n,t,e.hostModel.get("percentPrecision")),i.$vars.push("percent"),i},_defaultLabelLine:function(t){Ci(t,"labelLine",["show"]);var e=t.labelLine,i=t.emphasis.labelLine;e.show=e.show&&t.label.show,i.show=i.show&&t.emphasis.label.show},defaultOption:{zlevel:0,z:2,legendHoverLink:!0,hoverAnimation:!0,center:["50%","50%"],radius:[0,"75%"],clockwise:!0,startAngle:90,minAngle:0,selectedOffset:10,hoverOffset:10,avoidLabelOverlap:!0,percentPrecision:2,stillShowZeroSum:!0,label:{rotate:!1,show:!0,position:"outer"},labelLine:{show:!0,length:15,length2:15,smooth:!1,lineStyle:{width:1,type:"solid"}},itemStyle:{borderWidth:1},animationType:"expansion",animationEasing:"cubicOut"}});h(rC,aC);var sC=Fh.prototype;sC.updateData=function(t,e,i){function n(){s.stopAnimation(!0),s.animateTo({shape:{r:h.r+l.get("hoverOffset")}},300,"elasticOut")}function o(){s.stopAnimation(!0),s.animateTo({shape:{r:h.r}},300,"elasticOut")}var s=this.childAt(0),l=t.hostModel,u=t.getItemModel(e),h=t.getItemLayout(e),c=a({},h);c.label=null,i?(s.setShape(c),"scale"===l.getShallow("animationType")?(s.shape.r=h.r0,To(s,{shape:{r:h.r}},l,e)):(s.shape.endAngle=h.startAngle,Io(s,{shape:{endAngle:h.endAngle}},l,e))):Io(s,{shape:c},l,e);var d=t.getItemVisual(e,"color");s.useStyle(r({lineJoin:"bevel",fill:d},u.getModel("itemStyle").getItemStyle())),s.hoverStyle=u.getModel("emphasis.itemStyle").getItemStyle();var f=u.getShallow("cursor");f&&s.attr("cursor",f),Gh(this,t.getItemLayout(e),l.isSelected(null,e),l.get("selectedOffset"),l.get("animation")),s.off("mouseover").off("mouseout").off("emphasis").off("normal"),u.get("hoverAnimation")&&l.isAnimationEnabled()&&s.on("mouseover",n).on("mouseout",o).on("emphasis",n).on("normal",o),this._updateLabel(t,e),fo(this)},sC._updateLabel=function(t,e){var i=this.childAt(1),n=this.childAt(2),o=t.hostModel,a=t.getItemModel(e),r=t.getItemLayout(e).label,s=t.getItemVisual(e,"color");Io(i,{shape:{points:r.linePoints||[[r.x,r.y],[r.x,r.y],[r.x,r.y]]}},o,e),Io(n,{style:{x:r.x,y:r.y}},o,e),n.attr({rotation:r.rotation,origin:[r.x,r.y],z2:10});var l=a.getModel("label"),u=a.getModel("emphasis.label"),h=a.getModel("labelLine"),c=a.getModel("emphasis.labelLine"),s=t.getItemVisual(e,"color");go(n.style,n.hoverStyle={},l,u,{labelFetcher:t.hostModel,labelDataIndex:e,defaultText:t.getName(e),autoColor:s,useInsideStyle:!!r.inside},{textAlign:r.textAlign,textVerticalAlign:r.verticalAlign,opacity:t.getItemVisual(e,"opacity")}),n.ignore=n.normalIgnore=!l.get("show"),n.hoverIgnore=!u.get("show"),i.ignore=i.normalIgnore=!h.get("show"),i.hoverIgnore=!c.get("show"),i.setStyle({stroke:s,opacity:t.getItemVisual(e,"opacity")}),i.setStyle(h.getModel("lineStyle").getLineStyle()),i.hoverStyle=c.getModel("lineStyle").getLineStyle();var d=h.get("smooth");d&&!0===d&&(d=.4),i.setShape({smooth:d})},u(Fh,tb);Ar.extend({type:"pie",init:function(){var t=new tb;this._sectorGroup=t},render:function(t,e,i,n){if(!n||n.from!==this.uid){var o=t.getData(),a=this._data,r=this.group,s=e.get("animation"),l=!a,u=t.get("animationType"),h=v(Vh,this.uid,t,s,i),c=t.get("selectedMode");if(o.diff(a).add(function(t){var e=new Fh(o,t);l&&"scale"!==u&&e.eachChild(function(t){t.stopAnimation(!0)}),c&&e.on("click",h),o.setItemGraphicEl(t,e),r.add(e)}).update(function(t,e){var i=a.getItemGraphicEl(e);i.updateData(o,t),i.off("click"),c&&i.on("click",h),r.add(i),o.setItemGraphicEl(t,i)}).remove(function(t){var e=a.getItemGraphicEl(t);r.remove(e)}).execute(),s&&l&&o.count()>0&&"scale"!==u){var d=o.getItemLayout(0),f=Math.max(i.getWidth(),i.getHeight())/2,p=m(r.removeClipPath,r);r.setClipPath(this._createClipPath(d.cx,d.cy,f,d.startAngle,d.clockwise,p,t))}else r.removeClipPath();this._data=o}},dispose:function(){},_createClipPath:function(t,e,i,n,o,a,r){var s=new hM({shape:{cx:t,cy:e,r0:0,r:i,startAngle:n,endAngle:n,clockwise:o}});return To(s,{shape:{endAngle:n+(o?1:-1)*Math.PI*2}},r,a),s},containPoint:function(t,e){var i=e.getData().getItemLayout(0);if(i){var n=t[0]-i.cx,o=t[1]-i.cy,a=Math.sqrt(n*n+o*o);return a<=i.r&&a>=i.r0}}});var lC=function(t,e){d(e,function(e){e.update="updateView",Es(e,function(i,n){var o={};return n.eachComponent({mainType:"series",subType:t,query:i},function(t){t[e.method]&&t[e.method](i.name,i.dataIndex);var n=t.getData();n.each(function(e){var i=n.getName(e);o[i]=t.isSelected(i)||!1})}),{name:i.name,selected:o}})})},uC=function(t){return{getTargetSeries:function(e){var i={},n=R();return e.eachSeriesByType(t,function(t){t.__paletteScope=i,n.set(t.uid,t)}),n},reset:function(t,e){var i=t.getRawData(),n={},o=t.getData();o.each(function(t){var e=o.getRawIndex(t);n[e]=t}),i.each(function(e){var a=n[e],r=null!=a&&o.getItemVisual(a,"color",!0);if(r)i.setItemVisual(e,"color",r);else{var s=i.getItemModel(e).get("itemStyle.color")||t.getColorFromPalette(i.getName(e)||e+"",t.__paletteScope,i.count());i.setItemVisual(e,"color",s),null!=a&&o.setItemVisual(a,"color",s)}})}}},hC=function(t,e,i,n){var o,a,r=t.getData(),s=[],l=!1;r.each(function(i){var n,u,h,c,d=r.getItemLayout(i),f=r.getItemModel(i),p=f.getModel("label"),g=p.get("position")||f.get("emphasis.label.position"),m=f.getModel("labelLine"),v=m.get("length"),y=m.get("length2"),x=(d.startAngle+d.endAngle)/2,_=Math.cos(x),w=Math.sin(x);o=d.cx,a=d.cy;var b="inside"===g||"inner"===g;if("center"===g)n=d.cx,u=d.cy,c="center";else{var S=(b?(d.r+d.r0)/2*_:d.r*_)+o,M=(b?(d.r+d.r0)/2*w:d.r*w)+a;if(n=S+3*_,u=M+3*w,!b){var I=S+_*(v+e-d.r),T=M+w*(v+e-d.r),A=I+(_<0?-1:1)*y,D=T;n=A+(_<0?-5:5),u=D,h=[[S,M],[I,T],[A,D]]}c=b?"center":_>0?"left":"right"}var C=p.getFont(),L=p.get("rotate")?_<0?-x+Math.PI:-x:0,k=ke(t.getFormattedLabel(i,"normal")||r.getName(i),C,c,"top");l=!!L,d.label={x:n,y:u,position:g,height:k.height,len:v,len2:y,linePoints:h,textAlign:c,verticalAlign:"middle",rotation:L,inside:b},b||s.push(d.label)}),!l&&t.get("avoidLabelOverlap")&&Hh(s,o,a,e,i,n)},cC=2*Math.PI,dC=Math.PI/180,fC=function(t){return{seriesType:t,reset:function(t,e){var i=e.findComponents({mainType:"legend"});if(i&&i.length){var n=t.getData();n.filterSelf(function(t){for(var e=n.getName(t),o=0;o<i.length;o++)if(!i[o].isSelected(e))return!1;return!0})}}}};lC("pie",[{type:"pieToggleSelect",event:"pieselectchanged",method:"toggleSelected"},{type:"pieSelect",event:"pieselected",method:"select"},{type:"pieUnSelect",event:"pieunselected",method:"unSelect"}]),Bs(uC("pie")),zs(v(function(t,e,i,n){e.eachSeriesByType(t,function(t){var e=t.getData(),n=e.mapDimension("value"),o=t.get("center"),a=t.get("radius");y(a)||(a=[0,a]),y(o)||(o=[o,o]);var r=i.getWidth(),s=i.getHeight(),l=Math.min(r,s),u=Vo(o[0],r),h=Vo(o[1],s),c=Vo(a[0],l/2),d=Vo(a[1],l/2),f=-t.get("startAngle")*dC,p=t.get("minAngle")*dC,g=0;e.each(n,function(t){!isNaN(t)&&g++});var m=e.getSum(n),v=Math.PI/(m||g)*2,x=t.get("clockwise"),_=t.get("roseType"),w=t.get("stillShowZeroSum"),b=e.getDataExtent(n);b[0]=0;var S=cC,M=0,I=f,T=x?1:-1;if(e.each(n,function(t,i){var n;if(isNaN(t))e.setItemLayout(i,{angle:NaN,startAngle:NaN,endAngle:NaN,clockwise:x,cx:u,cy:h,r0:c,r:_?NaN:d});else{(n="area"!==_?0===m&&w?v:t*v:cC/g)<p?(n=p,S-=p):M+=t;var o=I+T*n;e.setItemLayout(i,{angle:n,startAngle:I,endAngle:o,clockwise:x,cx:u,cy:h,r0:c,r:_?Bo(t,b,[c,d]):d}),I=o}}),S<cC&&g)if(S<=.001){var A=cC/g;e.each(n,function(t,i){if(!isNaN(t)){var n=e.getItemLayout(i);n.angle=A,n.startAngle=f+T*i*A,n.endAngle=f+T*(i+1)*A}})}else v=S/M,I=f,e.each(n,function(t,i){if(!isNaN(t)){var n=e.getItemLayout(i),o=n.angle===p?p:t*v;n.startAngle=I,n.endAngle=I+T*o,I+=T*o}});hC(t,d,r,s)})},"pie")),Os(fC("pie")),YI.extend({type:"series.scatter",dependencies:["grid","polar","geo","singleAxis","calendar"],getInitialData:function(t,e){return ml(this.getSource(),this)},brushSelector:"point",getProgressive:function(){var t=this.option.progressive;return null==t?this.option.large?5e3:this.get("progressive"):t},getProgressiveThreshold:function(){var t=this.option.progressiveThreshold;return null==t?this.option.large?1e4:this.get("progressiveThreshold"):t},defaultOption:{coordinateSystem:"cartesian2d",zlevel:0,z:2,legendHoverLink:!0,hoverAnimation:!0,symbolSize:10,large:!1,largeThreshold:2e3,itemStyle:{opacity:.8}}});var pC=Un({shape:{points:null},symbolProxy:null,buildPath:function(t,e){var i=e.points,n=e.size,o=this.symbolProxy,a=o.shape;if(!((t.getContext?t.getContext():t)&&n[0]<4))for(var r=0;r<i.length;){var s=i[r++],l=i[r++];isNaN(s)||isNaN(l)||(a.x=s-n[0]/2,a.y=l-n[1]/2,a.width=n[0],a.height=n[1],o.buildPath(t,a,!0))}},afterBrush:function(t){var e=this.shape,i=e.points,n=e.size;if(n[0]<4){this.setTransform(t);for(var o=0;o<i.length;){var a=i[o++],r=i[o++];isNaN(a)||isNaN(r)||t.fillRect(a-n[0]/2,r-n[1]/2,n[0],n[1])}this.restoreTransform(t)}},findDataIndex:function(t,e){for(var i=this.shape,n=i.points,o=i.size,a=Math.max(o[0],4),r=Math.max(o[1],4),s=n.length/2-1;s>=0;s--){var l=2*s,u=n[l]-a/2,h=n[l+1]-r/2;if(t>=u&&e>=h&&t<=u+a&&e<=h+r)return s}return-1}}),gC=Uh.prototype;gC.isPersistent=function(){return!this._incremental},gC.updateData=function(t){this.group.removeAll();var e=new pC({rectHover:!0,cursor:"default"});e.setShape({points:t.getLayout("symbolPoints")}),this._setCommon(e,t),this.group.add(e),this._incremental=null},gC.updateLayout=function(t){if(!this._incremental){var e=t.getLayout("symbolPoints");this.group.eachChild(function(t){if(null!=t.startIndex){var i=2*(t.endIndex-t.startIndex),n=4*t.startIndex*2;e=new Float32Array(e.buffer,n,i)}t.setShape("points",e)})}},gC.incrementalPrepareUpdate=function(t){this.group.removeAll(),this._clearIncremental(),t.count()>2e6?(this._incremental||(this._incremental=new Zn({silent:!0})),this.group.add(this._incremental)):this._incremental=null},gC.incrementalUpdate=function(t,e){var i;this._incremental?(i=new pC,this._incremental.addDisplayable(i,!0)):((i=new pC({rectHover:!0,cursor:"default",startIndex:t.start,endIndex:t.end})).incremental=!0,this.group.add(i)),i.setShape({points:e.getLayout("symbolPoints")}),this._setCommon(i,e,!!this._incremental)},gC._setCommon=function(t,e,i){var n=e.hostModel,o=e.getVisual("symbolSize");t.setShape("size",o instanceof Array?o:[o,o]),t.symbolProxy=Jl(e.getVisual("symbol"),0,0,0,0),t.setColor=t.symbolProxy.setColor;var a=t.shape.size[0]<4;t.useStyle(n.getModel("itemStyle").getItemStyle(a?["color","shadowBlur","shadowColor"]:["color"]));var r=e.getVisual("color");r&&t.setColor(r),i||(t.seriesIndex=n.seriesIndex,t.on("mousemove",function(e){t.dataIndex=null;var i=t.findDataIndex(e.offsetX,e.offsetY);i>=0&&(t.dataIndex=i+(t.startIndex||0))}))},gC.remove=function(){this._clearIncremental(),this._incremental=null,this.group.removeAll()},gC._clearIncremental=function(){var t=this._incremental;t&&t.clearDisplaybles()},Zs({type:"scatter",render:function(t,e,i){var n=t.getData();this._updateSymbolDraw(n,t).updateData(n),this._finished=!0},incrementalPrepareRender:function(t,e,i){var n=t.getData();this._updateSymbolDraw(n,t).incrementalPrepareUpdate(n),this._finished=!1},incrementalRender:function(t,e,i){this._symbolDraw.incrementalUpdate(t,e.getData()),this._finished=t.end===e.getData().count()},updateTransform:function(t,e,i){var n=t.getData();if(this.group.dirty(),!this._finished||n.count()>1e4||!this._symbolDraw.isPersistent())return{update:!0};var o=AD().reset(t);o.progress&&o.progress({start:0,end:n.count()},n),this._symbolDraw.updateLayout(n)},_updateSymbolDraw:function(t,e){var i=this._symbolDraw,n=e.pipelineContext.large;return i&&n===this._isLargeDraw||(i&&i.remove(),i=this._symbolDraw=n?new Uh:new Du,this._isLargeDraw=n,this.group.removeAll()),this.group.add(i.group),i},remove:function(t,e){this._symbolDraw&&this._symbolDraw.remove(!0),this._symbolDraw=null},dispose:function(){}}),Bs(TD("scatter","circle")),zs(AD("scatter")),u(Xh,aD),jh.prototype.getIndicatorAxes=function(){return this._indicatorAxes},jh.prototype.dataToPoint=function(t,e){var i=this._indicatorAxes[e];return this.coordToPoint(i.dataToCoord(t),e)},jh.prototype.coordToPoint=function(t,e){var i=this._indicatorAxes[e].angle;return[this.cx+t*Math.cos(i),this.cy-t*Math.sin(i)]},jh.prototype.pointToData=function(t){var e=t[0]-this.cx,i=t[1]-this.cy,n=Math.sqrt(e*e+i*i);e/=n,i/=n;for(var o,a=Math.atan2(-i,e),r=1/0,s=-1,l=0;l<this._indicatorAxes.length;l++){var u=this._indicatorAxes[l],h=Math.abs(a-u.angle);h<r&&(o=u,s=l,r=h)}return[s,+(o&&o.coodToData(n))]},jh.prototype.resize=function(t,e){var i=t.get("center"),n=e.getWidth(),o=e.getHeight(),a=Math.min(n,o)/2;this.cx=Vo(i[0],n),this.cy=Vo(i[1],o),this.startAngle=t.get("startAngle")*Math.PI/180;var r=t.get("radius");"string"!=typeof r&&"number"!=typeof r||(r=[0,r]),this.r0=Vo(r[0],a),this.r=Vo(r[1],a),d(this._indicatorAxes,function(t,e){t.setExtent(this.r0,this.r);var i=this.startAngle+e*Math.PI*2/this._indicatorAxes.length;i=Math.atan2(Math.sin(i),Math.cos(i)),t.angle=i},this)},jh.prototype.update=function(t,e){function i(t){var e=Math.pow(10,Math.floor(Math.log(t)/Math.LN10)),i=t/e;return 2===i?i=5:i*=2,i*e}var n=this._indicatorAxes,o=this._model;d(n,function(t){t.scale.setExtent(1/0,-1/0)}),t.eachSeriesByType("radar",function(e,i){if("radar"===e.get("coordinateSystem")&&t.getComponent("radar",e.get("radarIndex"))===o){var a=e.getData();d(n,function(t){t.scale.unionExtentFromData(a,a.mapDimension(t.dim))})}},this);var a=o.get("splitNumber");d(n,function(t,e){var n=Gl(t.scale,t.model);Wl(t.scale,t.model);var o=t.model,r=t.scale,s=o.getMin(),l=o.getMax(),u=r.getInterval();if(null!=s&&null!=l)r.setExtent(+s,+l),r.setInterval((l-s)/a);else if(null!=s){var h;do{h=s+u*a,r.setExtent(+s,h),r.setInterval(u),u=i(u)}while(h<n[1]&&isFinite(h)&&isFinite(n[1]))}else if(null!=l){var c;do{c=l-u*a,r.setExtent(c,+l),r.setInterval(u),u=i(u)}while(c>n[0]&&isFinite(c)&&isFinite(n[0]))}else{r.getTicks().length-1>a&&(u=i(u));var d=Math.round((n[0]+n[1])/2/u)*u,f=Math.round(a/2);r.setExtent(Go(d-f*u),Go(d+(a-f)*u)),r.setInterval(u)}})},jh.dimensions=[],jh.create=function(t,e){var i=[];return t.eachComponent("radar",function(n){var o=new jh(n,t,e);i.push(o),n.coordinateSystem=o}),t.eachSeriesByType("radar",function(t){"radar"===t.get("coordinateSystem")&&(t.coordinateSystem=i[t.get("radarIndex")||0])}),i},Fa.register("radar",jh);var mC=ND.valueAxis,vC=(Fs({type:"radar",optionUpdated:function(){var t=this.get("boundaryGap"),e=this.get("splitNumber"),o=this.get("scale"),s=this.get("axisLine"),l=this.get("axisTick"),u=this.get("axisLabel"),h=this.get("name"),c=this.get("name.show"),d=this.get("name.formatter"),p=this.get("nameGap"),g=this.get("triggerEvent"),m=f(this.get("indicator")||[],function(f){null!=f.max&&f.max>0&&!f.min?f.min=0:null!=f.min&&f.min<0&&!f.max&&(f.max=0);var m=h;if(null!=f.color&&(m=r({color:f.color},h)),f=n(i(f),{boundaryGap:t,splitNumber:e,scale:o,axisLine:s,axisTick:l,axisLabel:u,name:f.text,nameLocation:"end",nameGap:p,nameTextStyle:m,triggerEvent:g},!1),c||(f.name=""),"string"==typeof d){var v=f.name;f.name=d.replace("{value}",null!=v?v:"")}else"function"==typeof d&&(f.name=d(f.name,f));var y=a(new No(f,null,this.ecModel),UA);return y.mainType="radar",y.componentIndex=this.componentIndex,y},this);this.getIndicatorModels=function(){return m}},defaultOption:{zlevel:0,z:0,center:["50%","50%"],radius:"75%",startAngle:90,name:{show:!0},boundaryGap:[0,0],splitNumber:5,nameGap:15,scale:!1,shape:"polygon",axisLine:n({lineStyle:{color:"#bbb"}},mC.axisLine),axisLabel:Yh(mC.axisLabel,!1),axisTick:Yh(mC.axisTick,!1),splitLine:Yh(mC.splitLine,!0),splitArea:Yh(mC.splitArea,!0),indicator:[]}}),["axisLine","axisTickLabel","axisName"]);Ws({type:"radar",render:function(t,e,i){this.group.removeAll(),this._buildAxes(t),this._buildSplitLineAndArea(t)},_buildAxes:function(t){var e=t.coordinateSystem;d(f(e.getIndicatorAxes(),function(t){return new FD(t.model,{position:[e.cx,e.cy],rotation:t.angle,labelDirection:-1,tickDirection:-1,nameDirection:1})}),function(t){d(vC,t.add,t),this.group.add(t.getGroup())},this)},_buildSplitLineAndArea:function(t){function e(t,e,i){var n=i%e.length;return t[n]=t[n]||[],n}var i=t.coordinateSystem,n=i.getIndicatorAxes();if(n.length){var o=t.get("shape"),a=t.getModel("splitLine"),s=t.getModel("splitArea"),l=a.getModel("lineStyle"),u=s.getModel("areaStyle"),h=a.get("show"),c=s.get("show"),p=l.get("color"),g=u.get("color");p=y(p)?p:[p],g=y(g)?g:[g];var m=[],v=[];if("circle"===o)for(var x=n[0].getTicksCoords(),_=i.cx,w=i.cy,b=0;b<x.length;b++)h&&m[D=e(m,p,b)].push(new sM({shape:{cx:_,cy:w,r:x[b].coord}})),c&&b<x.length-1&&v[D=e(v,g,b)].push(new cM({shape:{cx:_,cy:w,r0:x[b].coord,r:x[b+1].coord}}));else for(var S,M=f(n,function(t,e){var n=t.getTicksCoords();return S=null==S?n.length-1:Math.min(n.length-1,S),f(n,function(t){return i.coordToPoint(t.coord,e)})}),I=[],b=0;b<=S;b++){for(var T=[],A=0;A<n.length;A++)T.push(M[A][b]);if(T[0]&&T.push(T[0].slice()),h&&m[D=e(m,p,b)].push(new gM({shape:{points:T}})),c&&I){var D=e(v,g,b-1);v[D].push(new pM({shape:{points:T.concat(I)}}))}I=T.slice().reverse()}var C=l.getLineStyle(),L=u.getAreaStyle();d(v,function(t,e){this.group.add(OM(t,{style:r({stroke:"none",fill:g[e%g.length]},L),silent:!0}))},this),d(m,function(t,e){this.group.add(OM(t,{style:r({fill:"none",stroke:p[e%p.length]},C),silent:!0}))},this)}}});var yC=YI.extend({type:"series.radar",dependencies:["radar"],init:function(t){yC.superApply(this,"init",arguments),this.legendDataProvider=function(){return this.getRawData()}},getInitialData:function(t,e){return oC(this,{generateCoord:"indicator_",generateCoordCount:1/0})},formatTooltip:function(t){var e=this.getData(),i=this.coordinateSystem.getIndicatorAxes(),n=this.getData().getName(t);return ia(""===n?this.name:n)+"<br/>"+f(i,function(i,n){var o=e.get(e.mapDimension(i.dim),t);return ia(i.name+" : "+o)}).join("<br />")},defaultOption:{zlevel:0,z:2,coordinateSystem:"radar",legendHoverLink:!0,radarIndex:0,lineStyle:{width:2,type:"solid"},label:{position:"top"},symbol:"emptyCircle",symbolSize:4}});Zs({type:"radar",render:function(t,e,n){function o(t,e){var i=t.getItemVisual(e,"symbol")||"circle",n=t.getItemVisual(e,"color");if("none"!==i){var o=qh(t.getItemVisual(e,"symbolSize")),a=Jl(i,-1,-1,2,2,n);return a.attr({style:{strokeNoScale:!0},z2:100,scale:[o[0]/2,o[1]/2]}),a}}function a(e,i,n,a,r,s){n.removeAll();for(var l=0;l<i.length-1;l++){var u=o(a,r);u&&(u.__dimIdx=l,e[l]?(u.attr("position",e[l]),zM[s?"initProps":"updateProps"](u,{position:i[l]},t,r)):u.attr("position",i[l]),n.add(u))}}function s(t){return f(t,function(t){return[l.cx,l.cy]})}var l=t.coordinateSystem,u=this.group,h=t.getData(),c=this._data;h.diff(c).add(function(e){var i=h.getItemLayout(e);if(i){var n=new pM,o=new gM,r={shape:{points:i}};n.shape.points=s(i),o.shape.points=s(i),To(n,r,t,e),To(o,r,t,e);var l=new tb,u=new tb;l.add(o),l.add(n),l.add(u),a(o.shape.points,i,u,h,e,!0),h.setItemGraphicEl(e,l)}}).update(function(e,i){var n=c.getItemGraphicEl(i),o=n.childAt(0),r=n.childAt(1),s=n.childAt(2),l={shape:{points:h.getItemLayout(e)}};l.shape.points&&(a(o.shape.points,l.shape.points,s,h,e,!1),Io(o,l,t),Io(r,l,t),h.setItemGraphicEl(e,n))}).remove(function(t){u.remove(c.getItemGraphicEl(t))}).execute(),h.eachItemGraphicEl(function(t,e){function n(){l.attr("ignore",m)}function o(){l.attr("ignore",g)}var a=h.getItemModel(e),s=t.childAt(0),l=t.childAt(1),c=t.childAt(2),d=h.getItemVisual(e,"color");u.add(t),s.useStyle(r(a.getModel("lineStyle").getLineStyle(),{fill:"none",stroke:d})),s.hoverStyle=a.getModel("emphasis.lineStyle").getLineStyle();var f=a.getModel("areaStyle"),p=a.getModel("emphasis.areaStyle"),g=f.isEmpty()&&f.parentModel.isEmpty(),m=p.isEmpty()&&p.parentModel.isEmpty();m=m&&g,l.ignore=g,l.useStyle(r(f.getAreaStyle(),{fill:d,opacity:.7})),l.hoverStyle=p.getAreaStyle();var v=a.getModel("itemStyle").getItemStyle(["color"]),y=a.getModel("emphasis.itemStyle").getItemStyle(),x=a.getModel("label"),_=a.getModel("emphasis.label");c.eachChild(function(t){t.setStyle(v),t.hoverStyle=i(y),go(t.style,t.hoverStyle,x,_,{labelFetcher:h.hostModel,labelDataIndex:e,labelDimIndex:t.__dimIdx,defaultText:h.get(h.dimensions[t.__dimIdx],e),autoColor:d,isRectText:!0})}),t.off("mouseover").off("mouseout").off("normal").off("emphasis"),t.on("emphasis",n).on("mouseover",n).on("normal",o).on("mouseout",o),fo(t)}),this._data=h},remove:function(){this.group.removeAll(),this._data=null},dispose:function(){}});Bs(uC("radar")),Bs(TD("radar","circle")),zs(function(t){t.eachSeriesByType("radar",function(t){var e=t.getData(),i=[],n=t.coordinateSystem;if(n){for(var o=n.getIndicatorAxes(),a=0;a<o.length;a++)e.each(e.mapDimension(o[a].dim),function(t,e){i[e]=i[e]||[],i[e][a]=n.dataToPoint(t,a)});e.each(function(t){i[t][0]&&i[t].push(i[t][0].slice()),e.setItemLayout(t,i[t])})}})}),Os(fC("radar")),Ns(function(t){var e=t.polar;if(e){y(e)||(e=[e]);var i=[];d(e,function(e,n){e.indicator?(e.type&&!e.shape&&(e.shape=e.type),t.radar=t.radar||[],y(t.radar)||(t.radar=[t.radar]),t.radar.push(e)):i.push(e)}),t.polar=i}d(t.series,function(t){t&&"radar"===t.type&&t.polarIndex&&(t.radarIndex=t.polarIndex)})});for(var xC=[126,25],_C=[[[0,3.5],[7,11.2],[15,11.9],[30,7],[42,.7],[52,.7],[56,7.7],[59,.7],[64,.7],[64,0],[5,0],[0,3.5]],[[13,16.1],[19,14.7],[16,21.7],[11,23.1],[13,16.1]],[[12,32.2],[14,38.5],[15,38.5],[13,32.2],[12,32.2]],[[16,47.6],[12,53.2],[13,53.2],[18,47.6],[16,47.6]],[[6,64.4],[8,70],[9,70],[8,64.4],[6,64.4]],[[23,82.6],[29,79.8],[30,79.8],[25,82.6],[23,82.6]],[[37,70.7],[43,62.3],[44,62.3],[39,70.7],[37,70.7]],[[48,51.1],[51,45.5],[53,45.5],[50,51.1],[48,51.1]],[[51,35],[51,28.7],[53,28.7],[53,35],[51,35]],[[52,22.4],[55,17.5],[56,17.5],[53,22.4],[52,22.4]],[[58,12.6],[62,7],[63,7],[60,12.6],[58,12.6]],[[0,3.5],[0,93.1],[64,93.1],[64,0],[63,0],[63,92.4],[1,92.4],[1,3.5],[0,3.5]]],wC=0;wC<_C.length;wC++)for(var bC=0;bC<_C[wC].length;bC++)_C[wC][bC][0]/=10.5,_C[wC][bC][1]/=-14,_C[wC][bC][0]+=xC[0],_C[wC][bC][1]+=xC[1];var SC=function(t,e){"china"===t&&e.push(new eu("南海诸岛",f(_C,function(t){return{type:"polygon",exterior:t}}),xC))},MC={"南海诸岛":[32,80],"广东":[0,-10],"香港":[10,5],"澳门":[-10,10],"天津":[5,5]},IC=function(t,e){if("china"===t){var i=MC[e.name];if(i){var n=e.center;n[0]+=i[0]/10.5,n[1]+=-i[1]/14}}},TC={Russia:[100,60],"United States":[-99,38],"United States of America":[-99,38]},AC=function(t,e){if("world"===t){var i=TC[e.name];if(i){var n=e.center;n[0]=i[0],n[1]=i[1]}}},DC=[[[123.45165252685547,25.73527164402261],[123.49731445312499,25.73527164402261],[123.49731445312499,25.750734064600884],[123.45165252685547,25.750734064600884],[123.45165252685547,25.73527164402261]]],CC=function(t,e){"china"===t&&"台湾"===e.name&&e.geometries.push({type:"polygon",exterior:DC[0]})},LC=Bi(),kC={load:function(t,e){var i=LC(e).parsed;if(i)return i;var n,o=e.specialAreas||{},a=e.geoJSON;try{n=a?iD(a):[]}catch(t){throw new Error("Invalid geoJson format\n"+t.message)}return d(n,function(e){var i=e.name;IC(t,e),AC(t,e),CC(t,e);var n=o[i];n&&e.transformTo(n.left,n.top,n.width,n.height)}),SC(t,n),LC(e).parsed={regions:n,boundingRect:Kh(n)}}},PC=Bi(),NC={geoJSON:kC,svg:{load:function(t,e){var i=PC(e).originRoot;if(i)return{root:i,boundingRect:PC(e).boundingRect};var n=$h(e);return PC(e).originRoot=n.root,PC(e).boundingRect=n.boundingRect,n},makeGraphic:function(t,e,i){var n=PC(e),o=n.rootMap||(n.rootMap=R()),a=o.get(i);if(a)return a;var r=n.originRoot,s=n.boundingRect;return n.originRootHostKey?a=$h(e,s).root:(n.originRootHostKey=i,a=r),o.set(i,a)},removeGraphic:function(t,e,i){var n=PC(e),o=n.rootMap;o&&o.removeKey(i),i===n.originRootHostKey&&(n.originRootHostKey=null)}}},OC={load:function(t,e){var i,n=[],o=R(),a=R();return d(Qh(t),function(r){var s=NC[r.type].load(t,r);d(s.regions,function(t){var i=t.name;e&&e.hasOwnProperty(i)&&(t=t.cloneShallow(i=e[i])),n.push(t),o.set(i,t),a.set(i,t.center)});var l=s.boundingRect;l&&(i?i.union(l):i=l.clone())}),{regions:n,regionsMap:o,nameCoordMap:a,boundingRect:i||new de(0,0,0,0)}},makeGraphic:Jh("makeGraphic"),removeGraphic:Jh("removeGraphic")};h(YI.extend({type:"series.map",dependencies:["geo"],layoutMode:"box",needsDrawMap:!1,seriesGroup:[],getInitialData:function(t){for(var e=oC(this,["value"]),i=e.mapDimension("value"),n=R(),o=[],a=[],r=0,s=e.count();r<s;r++){var l=e.getName(r);n.set(l,!0),o.push({name:l,value:e.get(i,r),selected:pr(e,r,"selected")})}return d(OC.load(this.getMapType(),this.option.nameMap).regions,function(t){var e=t.name;n.get(e)||(o.push({name:e}),a.push(e))}),this.updateSelectedMap(o),e.appendValues([],a),e},getHostGeoModel:function(){var t=this.option.geoIndex;return null!=t?this.dependentModels.geo[t]:null},getMapType:function(){return(this.getHostGeoModel()||this).option.map},getRawValue:function(t){var e=this.getData();return e.get(e.mapDimension("value"),t)},getRegionModel:function(t){var e=this.getData();return e.getItemModel(e.indexOfName(t))},formatTooltip:function(t){for(var e=this.getData(),i=ta(this.getRawValue(t)),n=e.getName(t),o=this.seriesGroup,a=[],r=0;r<o.length;r++){var s=o[r].originalData.indexOfName(n),l=e.mapDimension("value");isNaN(o[r].originalData.get(l,s))||a.push(ia(o[r].name))}return a.join(", ")+"<br />"+ia(n+" : "+i)},getTooltipPosition:function(t){if(null!=t){var e=this.getData().getName(t),i=this.coordinateSystem,n=i.getRegion(e);return n&&i.dataToPoint(n.center)}},setZoom:function(t){this.option.zoom=t},setCenter:function(t){this.option.center=t},defaultOption:{zlevel:0,z:2,coordinateSystem:"geo",map:"",left:"center",top:"center",aspectScale:.75,showLegendSymbol:!0,dataRangeHoverLink:!0,boundingCoords:null,center:null,zoom:1,scaleLimit:null,label:{show:!1,color:"#000"},itemStyle:{borderWidth:.5,borderColor:"#444",areaColor:"#eee"},emphasis:{label:{show:!0,color:"rgb(100,0,0)"},itemStyle:{areaColor:"rgba(255,215,0,0.8)"}}}}),aC);var EC="\0_ec_interaction_mutex";Es({type:"takeGlobalCursor",event:"globalCursorTaken",update:"update"},function(){}),h(oc,fw);var RC={axisPointer:1,tooltip:1,brush:1};xc.prototype={constructor:xc,draw:function(t,e,i,n,o){var a="geo"===t.mainType,r=t.getData&&t.getData();a&&e.eachComponent({mainType:"series",subType:"map"},function(e){r||e.getHostGeoModel()!==t||(r=e.getData())});var s=t.coordinateSystem;this._updateBackground(s);var l=this._regionsGroup,u=this.group,h=s.scale,c={position:s.position,scale:h};!l.childAt(0)||o?u.attr(c):Io(u,c,t),l.removeAll();var f=["itemStyle"],p=["emphasis","itemStyle"],g=["label"],m=["emphasis","label"],v=R();d(s.regions,function(e){var i=v.get(e.name)||v.set(e.name,new tb),n=new MM({shape:{paths:[]}});i.add(n);var o,s=(C=t.getRegionModel(e.name)||t).getModel(f),u=C.getModel(p),c=mc(s),y=mc(u),x=C.getModel(g),_=C.getModel(m);if(r){o=r.indexOfName(e.name);var w=r.getItemVisual(o,"color",!0);w&&(c.fill=w)}d(e.geometries,function(t){if("polygon"===t.type){n.shape.paths.push(new pM({shape:{points:t.exterior}}));for(var e=0;e<(t.interiors?t.interiors.length:0);e++)n.shape.paths.push(new pM({shape:{points:t.interiors[e]}}))}}),n.setStyle(c),n.style.strokeNoScale=!0,n.culling=!0;var b=x.get("show"),S=_.get("show"),M=r&&isNaN(r.get(r.mapDimension("value"),o)),I=r&&r.getItemLayout(o);if(a||M&&(b||S)||I&&I.showLabel){var T,A=a?e.name:o;(!r||o>=0)&&(T=t);var D=new rM({position:e.center.slice(),scale:[1/h[0],1/h[1]],z2:10,silent:!0});go(D.style,D.hoverStyle={},x,_,{labelFetcher:T,labelDataIndex:A,defaultText:e.name,useInsideStyle:!1},{textAlign:"center",textVerticalAlign:"middle"}),i.add(D)}if(r)r.setItemGraphicEl(o,i);else{var C=t.getRegionModel(e.name);n.eventData={componentType:"geo",componentIndex:t.componentIndex,geoIndex:t.componentIndex,name:e.name,region:C&&C.option||{}}}(i.__regions||(i.__regions=[])).push(e),fo(i,y,{hoverSilentOnTouch:!!t.get("selectedMode")}),l.add(i)}),this._updateController(t,e,i),vc(this,t,l,i,n),yc(t,l)},remove:function(){this._regionsGroup.removeAll(),this._backgroundGroup.removeAll(),this._controller.dispose(),this._mapName&&OC.removeGraphic(this._mapName,this.uid),this._mapName=null,this._controllerHost={}},_updateBackground:function(t){var e=t.map;this._mapName!==e&&d(OC.makeGraphic(e,this.uid),function(t){this._backgroundGroup.add(t)},this),this._mapName=e},_updateController:function(t,e,i){function n(){var e={type:"geoRoam",componentType:l};return e[l+"Id"]=t.id,e}var o=t.coordinateSystem,r=this._controller,s=this._controllerHost;s.zoomLimit=t.get("scaleLimit"),s.zoom=o.getZoom(),r.enable(t.get("roam")||!1);var l=t.mainType;r.off("pan").on("pan",function(t){this._mouseDownFlag=!1,fc(s,t.dx,t.dy),i.dispatchAction(a(n(),{dx:t.dx,dy:t.dy}))},this),r.off("zoom").on("zoom",function(t){if(this._mouseDownFlag=!1,pc(s,t.scale,t.originX,t.originY),i.dispatchAction(a(n(),{zoom:t.scale,originX:t.originX,originY:t.originY})),this._updateGroup){var e=this.group.scale;this._regionsGroup.traverse(function(t){"text"===t.type&&t.attr("scale",[1/e[0],1/e[1]])})}},this),r.setPointerChecker(function(e,n,a){return o.getViewRectAfterRoam().contain(n,a)&&!gc(e,i,t)})}};var zC="__seriesMapHighDown",BC="__seriesMapCallKey";Zs({type:"map",render:function(t,e,i,n){if(!n||"mapToggleSelect"!==n.type||n.from!==this.uid){var o=this.group;if(o.removeAll(),!t.getHostGeoModel()){if(n&&"geoRoam"===n.type&&"series"===n.componentType&&n.seriesId===t.id)(a=this._mapDraw)&&o.add(a.group);else if(t.needsDrawMap){var a=this._mapDraw||new xc(i,!0);o.add(a.group),a.draw(t,e,i,this,n),this._mapDraw=a}else this._mapDraw&&this._mapDraw.remove(),this._mapDraw=null;t.get("showLegendSymbol")&&e.getComponent("legend")&&this._renderSymbols(t,e,i)}}},remove:function(){this._mapDraw&&this._mapDraw.remove(),this._mapDraw=null,this.group.removeAll()},dispose:function(){this._mapDraw&&this._mapDraw.remove(),this._mapDraw=null},_renderSymbols:function(t,e,i){var n=t.originalData,o=this.group;n.each(n.mapDimension("value"),function(e,i){if(!isNaN(e)){var r=n.getItemLayout(i);if(r&&r.point){var s=r.point,l=r.offset,u=new sM({style:{fill:t.getData().getVisual("color")},shape:{cx:s[0]+9*l,cy:s[1],r:3},silent:!0,z2:8+(l?0:NM+1)});if(!l){var h=t.mainSeries.getData(),c=n.getName(i),d=h.indexOfName(c),f=n.getItemModel(i),p=f.getModel("label"),g=f.getModel("emphasis.label"),m=h.getItemGraphicEl(d),y=A(t.getFormattedLabel(d,"normal"),c),x=A(t.getFormattedLabel(d,"emphasis"),y),_=m[zC],w=Math.random();if(!_){_=m[zC]={};var b=v(_c,!0),S=v(_c,!1);m.on("mouseover",b).on("mouseout",S).on("emphasis",b).on("normal",S)}m[BC]=w,a(_,{recordVersion:w,circle:u,labelModel:p,hoverLabelModel:g,emphasisText:x,normalText:y}),wc(_,!1)}o.add(u)}}})}}),Es({type:"geoRoam",event:"geoRoam",update:"updateTransform"},function(t,e){var i=t.componentType||"series";e.eachComponent({mainType:i,query:t},function(e){var n=e.coordinateSystem;if("geo"===n.type){var o=bc(n,t,e.get("scaleLimit"));e.setCenter&&e.setCenter(o.center),e.setZoom&&e.setZoom(o.zoom),"series"===i&&d(e.seriesGroup,function(t){t.setCenter(o.center),t.setZoom(o.zoom)})}})});var VC=Q;h(Sc,Tw),Mc.prototype={constructor:Mc,type:"view",dimensions:["x","y"],setBoundingRect:function(t,e,i,n){return this._rect=new de(t,e,i,n),this._rect},getBoundingRect:function(){return this._rect},setViewRect:function(t,e,i,n){this.transformTo(t,e,i,n),this._viewRect=new de(t,e,i,n)},transformTo:function(t,e,i,n){var o=this.getBoundingRect(),a=this._rawTransformable;a.transform=o.calculateTransform(new de(t,e,i,n)),a.decomposeTransform(),this._updateTransform()},setCenter:function(t){t&&(this._center=t,this._updateCenterAndZoom())},setZoom:function(t){t=t||1;var e=this.zoomLimit;e&&(null!=e.max&&(t=Math.min(e.max,t)),null!=e.min&&(t=Math.max(e.min,t))),this._zoom=t,this._updateCenterAndZoom()},getDefaultCenter:function(){var t=this.getBoundingRect();return[t.x+t.width/2,t.y+t.height/2]},getCenter:function(){return this._center||this.getDefaultCenter()},getZoom:function(){return this._zoom||1},getRoamTransform:function(){return this._roamTransformable.getLocalTransform()},_updateCenterAndZoom:function(){var t=this._rawTransformable.getLocalTransform(),e=this._roamTransformable,i=this.getDefaultCenter(),n=this.getCenter(),o=this.getZoom();n=Q([],n,t),i=Q([],i,t),e.origin=n,e.position=[i[0]-n[0],i[1]-n[1]],e.scale=[o,o],this._updateTransform()},_updateTransform:function(){var t=this._roamTransformable,e=this._rawTransformable;e.parent=t,t.updateTransform(),e.updateTransform(),wt(this.transform||(this.transform=[]),e.transform||xt()),this._rawTransform=e.getLocalTransform(),this.invTransform=this.invTransform||[],Tt(this.invTransform,this.transform),this.decomposeTransform()},getViewRect:function(){return this._viewRect},getViewRectAfterRoam:function(){var t=this.getBoundingRect().clone();return t.applyTransform(this.transform),t},dataToPoint:function(t,e,i){var n=e?this._rawTransform:this.transform;return i=i||[],n?VC(i,t,n):G(i,t)},pointToData:function(t){var e=this.invTransform;return e?VC([],t,e):[t[0],t[1]]},convertToPixel:v(Ic,"dataToPoint"),convertFromPixel:v(Ic,"pointToData"),containPoint:function(t){return this.getViewRectAfterRoam().contain(t[0],t[1])}},h(Mc,Tw),Tc.prototype={constructor:Tc,type:"geo",dimensions:["lng","lat"],containCoord:function(t){for(var e=this.regions,i=0;i<e.length;i++)if(e[i].contain(t))return!0;return!1},transformTo:function(t,e,i,n){var o=this.getBoundingRect(),a=this._invertLongitute;o=o.clone(),a&&(o.y=-o.y-o.height);var r=this._rawTransformable;if(r.transform=o.calculateTransform(new de(t,e,i,n)),r.decomposeTransform(),a){var s=r.scale;s[1]=-s[1]}r.updateTransform(),this._updateTransform()},getRegion:function(t){return this._regionsMap.get(t)},getRegionByCoord:function(t){for(var e=this.regions,i=0;i<e.length;i++)if(e[i].contain(t))return e[i]},addGeoCoord:function(t,e){this._nameCoordMap.set(t,e)},getGeoCoord:function(t){return this._nameCoordMap.get(t)},getBoundingRect:function(){return this._rect},dataToPoint:function(t,e,i){if("string"==typeof t&&(t=this.getGeoCoord(t)),t)return Mc.prototype.dataToPoint.call(this,t,e,i)},convertToPixel:v(Ac,"dataToPoint"),convertFromPixel:v(Ac,"pointToData")},h(Tc,Mc);var GC={dimensions:Tc.prototype.dimensions,create:function(t,e){var i=[];t.eachComponent("geo",function(t,n){var o=t.get("map"),a=t.get("aspectScale"),r=!0,s=DT.retrieveMap(o);s&&s[0]&&"svg"===s[0].type?(null==a&&(a=1),r=!1):null==a&&(a=.75);var l=new Tc(o+n,o,t.get("nameMap"),r);l.aspectScale=a,l.zoomLimit=t.get("scaleLimit"),i.push(l),Cc(l,t),t.coordinateSystem=l,l.model=t,l.resize=Dc,l.resize(t,e)}),t.eachSeries(function(t){if("geo"===t.get("coordinateSystem")){var e=t.get("geoIndex")||0;t.coordinateSystem=i[e]}});var n={};return t.eachSeriesByType("map",function(t){if(!t.getHostGeoModel()){var e=t.getMapType();n[e]=n[e]||[],n[e].push(t)}}),d(n,function(t,n){var a=new Tc(n,n,o(f(t,function(t){return t.get("nameMap")})));a.zoomLimit=T.apply(null,f(t,function(t){return t.get("scaleLimit")})),i.push(a),a.resize=Dc,a.aspectScale=t[0].get("aspectScale"),a.resize(t[0],e),d(t,function(t){t.coordinateSystem=a,Cc(a,t)})}),i},getFilledRegions:function(t,e,i){for(var n=(t||[]).slice(),o=R(),a=0;a<n.length;a++)o.set(n[a].name,n[a]);return d(OC.load(e,i).regions,function(t){var e=t.name;!o.get(e)&&n.push({name:e})}),n}};Rs("geo",GC);zs(function(t){var e={};t.eachSeriesByType("map",function(i){var n=i.getMapType();if(!i.getHostGeoModel()&&!e[n]){var o={};d(i.seriesGroup,function(e){var i=e.coordinateSystem,n=e.originalData;e.get("showLegendSymbol")&&t.getComponent("legend")&&n.each(n.mapDimension("value"),function(t,e){var a=n.getName(e),r=i.getRegion(a);if(r&&!isNaN(t)){var s=o[a]||0,l=i.dataToPoint(r.center);o[a]=s+1,n.setItemLayout(e,{point:l,offset:s})}})});var a=i.getData();a.each(function(t){var e=a.getName(t),i=a.getItemLayout(t)||{};i.showLabel=!o[e],a.setItemLayout(t,i)}),e[n]=!0}})}),Bs(function(t){t.eachSeriesByType("map",function(t){var e=t.get("color"),i=t.getModel("itemStyle"),n=i.get("areaColor"),o=i.get("color")||e[t.seriesIndex%e.length];t.getData().setVisual({areaColor:n,color:o})})}),Os(VT.PROCESSOR.STATISTIC,function(t){var e={};t.eachSeriesByType("map",function(t){var i=t.getHostGeoModel(),n=i?"o"+i.id:"i"+t.getMapType();(e[n]=e[n]||[]).push(t)}),d(e,function(t,e){for(var i=Lc(f(t,function(t){return t.getData()}),t[0].get("mapValueCalculation")),n=0;n<t.length;n++)t[n].originalData=t[n].getData();for(n=0;n<t.length;n++)t[n].seriesGroup=t,t[n].needsDrawMap=0===n&&!t[n].getHostGeoModel(),t[n].setData(i.cloneShallow()),t[n].mainSeries=t[0]})}),Ns(function(t){var e=[];d(t.series,function(t){t&&"map"===t.type&&(e.push(t),t.map=t.map||t.mapType,r(t,t.mapLocation))})}),lC("map",[{type:"mapToggleSelect",event:"mapselectchanged",method:"toggleSelected"},{type:"mapSelect",event:"mapselected",method:"select"},{type:"mapUnSelect",event:"mapunselected",method:"unSelect"}]);var FC=d,WC="\0__link_datas",HC="\0__link_mainData",ZC=function(t,e){this.name=t||"",this.depth=0,this.height=0,this.parentNode=null,this.dataIndex=-1,this.children=[],this.viewChildren=[],this.hostTree=e};ZC.prototype={constructor:ZC,isRemoved:function(){return this.dataIndex<0},eachNode:function(t,e,i){"function"==typeof t&&(i=e,e=t,t=null),_(t=t||{})&&(t={order:t});var n,o=t.order||"preorder",a=this[t.attr||"children"];"preorder"===o&&(n=e.call(i,this));for(var r=0;!n&&r<a.length;r++)a[r].eachNode(t,e,i);"postorder"===o&&e.call(i,this)},updateDepthAndHeight:function(t){var e=0;this.depth=t;for(var i=0;i<this.children.length;i++){var n=this.children[i];n.updateDepthAndHeight(t+1),n.height>e&&(e=n.height)}this.height=e+1},getNodeById:function(t){if(this.getId()===t)return this;for(var e=0,i=this.children,n=i.length;e<n;e++){var o=i[e].getNodeById(t);if(o)return o}},contains:function(t){if(t===this)return!0;for(var e=0,i=this.children,n=i.length;e<n;e++){var o=i[e].contains(t);if(o)return o}},getAncestors:function(t){for(var e=[],i=t?this:this.parentNode;i;)e.push(i),i=i.parentNode;return e.reverse(),e},getValue:function(t){var e=this.hostTree.data;return e.get(e.getDimension(t||"value"),this.dataIndex)},setLayout:function(t,e){this.dataIndex>=0&&this.hostTree.data.setItemLayout(this.dataIndex,t,e)},getLayout:function(){return this.hostTree.data.getItemLayout(this.dataIndex)},getModel:function(t){if(!(this.dataIndex<0)){var e,i=this.hostTree,n=i.data.getItemModel(this.dataIndex),o=this.getLevelModel();return o||0!==this.children.length&&(0===this.children.length||!1!==this.isExpand)||(e=this.getLeavesModel()),n.getModel(t,(o||e||i.hostModel).getModel(t))}},getLevelModel:function(){return(this.hostTree.levelModels||[])[this.depth]},getLeavesModel:function(){return this.hostTree.leavesModel},setVisual:function(t,e){this.dataIndex>=0&&this.hostTree.data.setItemVisual(this.dataIndex,t,e)},getVisual:function(t,e){return this.hostTree.data.getItemVisual(this.dataIndex,t,e)},getRawIndex:function(){return this.hostTree.data.getRawIndex(this.dataIndex)},getId:function(){return this.hostTree.data.getId(this.dataIndex)},isAncestorOf:function(t){for(var e=t.parentNode;e;){if(e===this)return!0;e=e.parentNode}return!1},isDescendantOf:function(t){return t!==this&&t.isAncestorOf(this)}},Vc.prototype={constructor:Vc,type:"tree",eachNode:function(t,e,i){this.root.eachNode(t,e,i)},getNodeByDataIndex:function(t){var e=this.data.getRawIndex(t);return this._nodes[e]},getNodeByName:function(t){return this.root.getNodeByName(t)},update:function(){for(var t=this.data,e=this._nodes,i=0,n=e.length;i<n;i++)e[i].dataIndex=-1;for(var i=0,n=t.count();i<n;i++)e[t.getRawIndex(i)].dataIndex=i},clearLayouts:function(){this.data.clearItemLayouts()}},Vc.createTree=function(t,e,i){function n(t,e){var i=t.value;r=Math.max(r,y(i)?i.length:1),a.push(t);var s=new ZC(t.name,o);e?Gc(s,e):o.root=s,o._nodes.push(s);var l=t.children;if(l)for(var u=0;u<l.length;u++)n(l[u],s)}var o=new Vc(e,i.levels,i.leaves),a=[],r=1;n(t),o.root.updateDepthAndHeight(0);var s=_A(a,{coordDimensions:["value"],dimensionsCount:r}),l=new vA(s,e);return l.initData(a),kc({mainData:l,struct:o,structAttr:"tree"}),o.update(),o},YI.extend({type:"series.tree",layoutInfo:null,layoutMode:"box",getInitialData:function(t){var e={name:t.name,children:t.data},i=t.leaves||{},n={};n.leaves=i;var o=Vc.createTree(e,this,n),a=0;o.eachNode("preorder",function(t){t.depth>a&&(a=t.depth)});var r=t.expandAndCollapse&&t.initialTreeDepth>=0?t.initialTreeDepth:a;return o.root.eachNode("preorder",function(t){var e=t.hostTree.data.getRawDataItem(t.dataIndex);t.isExpand=e&&null!=e.collapsed?!e.collapsed:t.depth<=r}),o.data},getOrient:function(){var t=this.get("orient");return"horizontal"===t?t="LR":"vertical"===t&&(t="TB"),t},setZoom:function(t){this.option.zoom=t},setCenter:function(t){this.option.center=t},formatTooltip:function(t){for(var e=this.getData().tree,i=e.root.children[0],n=e.getNodeByDataIndex(t),o=n.getValue(),a=n.name;n&&n!==i;)a=n.parentNode.name+"."+a,n=n.parentNode;return ia(a+(isNaN(o)||null==o?"":" : "+o))},defaultOption:{zlevel:0,z:2,coordinateSystem:"view",left:"12%",top:"12%",right:"12%",bottom:"12%",layout:"orthogonal",roam:!1,nodeScaleRatio:.4,center:null,zoom:1,orient:"LR",symbol:"emptyCircle",symbolSize:7,expandAndCollapse:!0,initialTreeDepth:2,lineStyle:{color:"#ccc",width:1.5,curveness:.5},itemStyle:{color:"lightsteelblue",borderColor:"#c23531",borderWidth:1.5},label:{show:!0,color:"#555"},leaves:{label:{show:!0}},animationEasing:"linear",animationDuration:700,animationDurationUpdate:1e3}}),Zs({type:"tree",init:function(t,e){this._oldTree,this._mainGroup=new tb,this._controller=new oc(e.getZr()),this._controllerHost={target:this.group},this.group.add(this._mainGroup)},render:function(t,e,i,n){var o=t.getData(),a=t.layoutInfo,r=this._mainGroup,s=t.get("layout");"radial"===s?r.attr("position",[a.x+a.width/2,a.y+a.height/2]):r.attr("position",[a.x,a.y]),this._updateViewCoordSys(t),this._updateController(t,e,i);var l=this._data,u={expandAndCollapse:t.get("expandAndCollapse"),layout:s,orient:t.getOrient(),curvature:t.get("lineStyle.curveness"),symbolRotate:t.get("symbolRotate"),symbolOffset:t.get("symbolOffset"),hoverAnimation:t.get("hoverAnimation"),useNameLabel:!0,fadeIn:!0};o.diff(l).add(function(e){td(o,e)&&id(o,e,null,r,t,u)}).update(function(e,i){var n=l.getItemGraphicEl(i);td(o,e)?id(o,e,n,r,t,u):n&&nd(l,i,n,r,t,u)}).remove(function(e){var i=l.getItemGraphicEl(e);i&&nd(l,e,i,r,t,u)}).execute(),this._nodeScaleRatio=t.get("nodeScaleRatio"),this._updateNodeAndLinkScale(t),!0===u.expandAndCollapse&&o.eachItemGraphicEl(function(e,n){e.off("click").on("click",function(){i.dispatchAction({type:"treeExpandAndCollapse",seriesId:t.id,dataIndex:n})})}),this._data=o},_updateViewCoordSys:function(t){var e=t.getData(),i=[];e.each(function(t){var n=e.getItemLayout(t);!n||isNaN(n.x)||isNaN(n.y)||i.push([+n.x,+n.y])});var n=[],o=[];fn(i,n,o),o[0]-n[0]==0&&(o[0]+=1,n[0]-=1),o[1]-n[1]==0&&(o[1]+=1,n[1]-=1);var a=t.coordinateSystem=new Mc;a.zoomLimit=t.get("scaleLimit"),a.setBoundingRect(n[0],n[1],o[0]-n[0],o[1]-n[1]),a.setCenter(t.get("center")),a.setZoom(t.get("zoom")),this.group.attr({position:a.position,scale:a.scale}),this._viewCoordSys=a},_updateController:function(t,e,i){var n=this._controller,o=this._controllerHost,a=this.group;n.setPointerChecker(function(e,n,o){var r=a.getBoundingRect();return r.applyTransform(a.transform),r.contain(n,o)&&!gc(e,i,t)}),n.enable(t.get("roam")),o.zoomLimit=t.get("scaleLimit"),o.zoom=t.coordinateSystem.getZoom(),n.off("pan").off("zoom").on("pan",function(e){fc(o,e.dx,e.dy),i.dispatchAction({seriesId:t.id,type:"treeRoam",dx:e.dx,dy:e.dy})},this).on("zoom",function(e){pc(o,e.scale,e.originX,e.originY),i.dispatchAction({seriesId:t.id,type:"treeRoam",zoom:e.scale,originX:e.originX,originY:e.originY}),this._updateNodeAndLinkScale(t)},this)},_updateNodeAndLinkScale:function(t){var e=t.getData(),i=this._getNodeGlobalScale(t),n=[i,i];e.eachItemGraphicEl(function(t,e){t.attr("scale",n)})},_getNodeGlobalScale:function(t){var e=t.coordinateSystem;if("view"!==e.type)return 1;var i=this._nodeScaleRatio,n=e.scale,o=n&&n[0]||1;return((e.getZoom()-1)*i+1)/o},dispose:function(){this._controller&&this._controller.dispose(),this._controllerHost={}},remove:function(){this._mainGroup.removeAll(),this._data=null}}),Es({type:"treeExpandAndCollapse",event:"treeExpandAndCollapse",update:"update"},function(t,e){e.eachComponent({mainType:"series",subType:"tree",query:t},function(e){var i=t.dataIndex,n=e.getData().tree.getNodeByDataIndex(i);n.isExpand=!n.isExpand})}),Es({type:"treeRoam",event:"treeRoam",update:"none"},function(t,e){e.eachComponent({mainType:"series",subType:"tree",query:t},function(e){var i=bc(e.coordinateSystem,t);e.setCenter&&e.setCenter(i.center),e.setZoom&&e.setZoom(i.zoom)})});Bs(TD("tree","circle")),zs(function(t,e){t.eachSeriesByType("tree",function(t){sd(t,e)})}),YI.extend({type:"series.treemap",layoutMode:"box",dependencies:["grid","polar"],_viewRoot:null,defaultOption:{progressive:0,hoverLayerThreshold:1/0,left:"center",top:"middle",right:null,bottom:null,width:"80%",height:"80%",sort:!0,clipWindow:"origin",squareRatio:.5*(1+Math.sqrt(5)),leafDepth:null,drillDownIcon:"▶",zoomToNodeRatio:.1024,roam:!0,nodeClick:"zoomToNode",animation:!0,animationDurationUpdate:900,animationEasing:"quinticInOut",breadcrumb:{show:!0,height:22,left:"center",top:"bottom",emptyItemWidth:25,itemStyle:{color:"rgba(0,0,0,0.7)",borderColor:"rgba(255,255,255,0.7)",borderWidth:1,shadowColor:"rgba(150,150,150,1)",shadowBlur:3,shadowOffsetX:0,shadowOffsetY:0,textStyle:{color:"#fff"}},emphasis:{textStyle:{}}},label:{show:!0,distance:0,padding:5,position:"inside",color:"#fff",ellipsis:!0},upperLabel:{show:!1,position:[0,"50%"],height:20,color:"#fff",ellipsis:!0,verticalAlign:"middle"},itemStyle:{color:null,colorAlpha:null,colorSaturation:null,borderWidth:0,gapWidth:0,borderColor:"#fff",borderColorSaturation:null},emphasis:{upperLabel:{show:!0,position:[0,"50%"],color:"#fff",ellipsis:!0,verticalAlign:"middle"}},visualDimension:0,visualMin:null,visualMax:null,color:[],colorAlpha:null,colorSaturation:null,colorMappingBy:"index",visibleMin:10,childrenVisibleMin:null,levels:[]},getInitialData:function(t,e){var i={name:t.name,children:t.data};dd(i);var n=t.levels||[];n=t.levels=fd(n,e);var o={};return o.levels=n,Vc.createTree(i,this,o).data},optionUpdated:function(){this.resetViewRoot()},formatTooltip:function(t){var e=this.getData(),i=this.getRawValue(t),n=ta(y(i)?i[0]:i);return ia(e.getName(t)+": "+n)},getDataParams:function(t){var e=YI.prototype.getDataParams.apply(this,arguments),i=this.getData().tree.getNodeByDataIndex(t);return e.treePathInfo=cd(i,this),e},setLayoutInfo:function(t){this.layoutInfo=this.layoutInfo||{},a(this.layoutInfo,t)},mapIdToIndex:function(t){var e=this._idIndexMap;e||(e=this._idIndexMap=R(),this._idIndexMapCount=0);var i=e.get(t);return null==i&&e.set(t,i=this._idIndexMapCount++),i},getViewRoot:function(){return this._viewRoot},resetViewRoot:function(t){t?this._viewRoot=t:t=this._viewRoot;var e=this.getRawData().tree.root;t&&(t===e||e.contains(t))||(this._viewRoot=e)}});var UC=5;pd.prototype={constructor:pd,render:function(t,e,i,n){var o=t.getModel("breadcrumb"),a=this.group;if(a.removeAll(),o.get("show")&&i){var r=o.getModel("itemStyle"),s=r.getModel("textStyle"),l={pos:{left:o.get("left"),right:o.get("right"),top:o.get("top"),bottom:o.get("bottom")},box:{width:e.getWidth(),height:e.getHeight()},emptyItemWidth:o.get("emptyItemWidth"),totalWidth:0,renderList:[]};this._prepare(i,l,s),this._renderContent(t,l,r,s,n),da(a,l.pos,l.box)}},_prepare:function(t,e,i){for(var n=t;n;n=n.parentNode){var o=n.getModel().get("name"),a=i.getTextRect(o),r=Math.max(a.width+16,e.emptyItemWidth);e.totalWidth+=r+8,e.renderList.push({node:n,text:o,width:r})}},_renderContent:function(t,e,i,n,o){for(var a=0,s=e.emptyItemWidth,l=t.get("breadcrumb.height"),u=ha(e.pos,e.box),h=e.totalWidth,c=e.renderList,d=c.length-1;d>=0;d--){var f=c[d],p=f.node,g=f.width,m=f.text;h>u.width&&(h-=g-s,g=s,m=null);var y=new pM({shape:{points:gd(a,0,g,l,d===c.length-1,0===d)},style:r(i.getItemStyle(),{lineJoin:"bevel",text:m,textFill:n.getTextColor(),textFont:n.getFont()}),z:10,onclick:v(o,p)});this.group.add(y),md(y,t,p),a+=g+8}},remove:function(){this.group.removeAll()}};var XC=m,jC=tb,YC=yM,qC=d,KC=["label"],$C=["emphasis","label"],JC=["upperLabel"],QC=["emphasis","upperLabel"],tL=10,eL=1,iL=2,nL=Qb([["fill","color"],["stroke","strokeColor"],["lineWidth","strokeWidth"],["shadowBlur"],["shadowOffsetX"],["shadowOffsetY"],["shadowColor"]]),oL=function(t){var e=nL(t);return e.stroke=e.fill=e.lineWidth=null,e};Zs({type:"treemap",init:function(t,e){this._containerGroup,this._storage={nodeGroup:[],background:[],content:[]},this._oldTree,this._breadcrumb,this._controller,this._state="ready"},render:function(t,e,i,n){if(!(l(e.findComponents({mainType:"series",subType:"treemap",query:n}),t)<0)){this.seriesModel=t,this.api=i,this.ecModel=e;var o=ld(n,["treemapZoomToNode","treemapRootToNode"],t),a=n&&n.type,r=t.layoutInfo,s=!this._oldTree,u=this._storage,h="treemapRootToNode"===a&&o&&u?{rootNodeGroup:u.nodeGroup[o.node.getRawIndex()],direction:n.direction}:null,c=this._giveContainerGroup(r),d=this._doRender(c,t,h);s||a&&"treemapZoomToNode"!==a&&"treemapRootToNode"!==a?d.renderFinally():this._doAnimation(c,d,t,h),this._resetController(i),this._renderBreadcrumb(t,i,o)}},_giveContainerGroup:function(t){var e=this._containerGroup;return e||(e=this._containerGroup=new jC,this._initEvents(e),this.group.add(e)),e.attr("position",[t.x,t.y]),e},_doRender:function(t,e,i){function n(t,e,i,o,a){function r(t){return t.getId()}function s(r,s){var l=null!=r?t[r]:null,u=null!=s?e[s]:null,c=h(l,u,i,a);c&&n(l&&l.viewChildren||[],u&&u.viewChildren||[],c,o,a+1)}o?(e=t,qC(t,function(t,e){!t.isRemoved()&&s(e,e)})):new Xs(e,t,r,r).add(s).update(s).remove(v(s,null)).execute()}var o=e.getData().tree,a=this._oldTree,r={nodeGroup:[],background:[],content:[]},s={nodeGroup:[],background:[],content:[]},l=this._storage,u=[],h=v(yd,e,s,l,i,r,u);n(o.root?[o.root]:[],a&&a.root?[a.root]:[],t,o===a||!a,0);var c=function(t){var e={nodeGroup:[],background:[],content:[]};return t&&qC(t,function(t,i){var n=e[i];qC(t,function(t){t&&(n.push(t),t.__tmWillDelete=1)})}),e}(l);return this._oldTree=o,this._storage=s,{lastsForAnimation:r,willDeleteEls:c,renderFinally:function(){qC(c,function(t){qC(t,function(t){t.parent&&t.parent.remove(t)})}),qC(u,function(t){t.invisible=!0,t.dirty()})}}},_doAnimation:function(t,e,i,n){if(i.get("animation")){var o=i.get("animationDurationUpdate"),r=i.get("animationEasing"),s=vd();qC(e.willDeleteEls,function(t,e){qC(t,function(t,i){if(!t.invisible){var a,l=t.parent;if(n&&"drillDown"===n.direction)a=l===n.rootNodeGroup?{shape:{x:0,y:0,width:l.__tmNodeWidth,height:l.__tmNodeHeight},style:{opacity:0}}:{style:{opacity:0}};else{var u=0,h=0;l.__tmWillDelete||(u=l.__tmNodeWidth/2,h=l.__tmNodeHeight/2),a="nodeGroup"===e?{position:[u,h],style:{opacity:0}}:{shape:{x:u,y:h,width:0,height:0},style:{opacity:0}}}a&&s.add(t,a,o,r)}})}),qC(this._storage,function(t,i){qC(t,function(t,n){var l=e.lastsForAnimation[i][n],u={};l&&("nodeGroup"===i?l.old&&(u.position=t.position.slice(),t.attr("position",l.old)):(l.old&&(u.shape=a({},t.shape),t.setShape(l.old)),l.fadein?(t.setStyle("opacity",0),u.style={opacity:1}):1!==t.style.opacity&&(u.style={opacity:1})),s.add(t,u,o,r))})},this),this._state="animating",s.done(XC(function(){this._state="ready",e.renderFinally()},this)).start()}},_resetController:function(t){var e=this._controller;e||((e=this._controller=new oc(t.getZr())).enable(this.seriesModel.get("roam")),e.on("pan",XC(this._onPan,this)),e.on("zoom",XC(this._onZoom,this)));var i=new de(0,0,t.getWidth(),t.getHeight());e.setPointerChecker(function(t,e,n){return i.contain(e,n)})},_clearController:function(){var t=this._controller;t&&(t.dispose(),t=null)},_onPan:function(t){if("animating"!==this._state&&(Math.abs(t.dx)>3||Math.abs(t.dy)>3)){var e=this.seriesModel.getData().tree.root;if(!e)return;var i=e.getLayout();if(!i)return;this.api.dispatchAction({type:"treemapMove",from:this.uid,seriesId:this.seriesModel.id,rootRect:{x:i.x+t.dx,y:i.y+t.dy,width:i.width,height:i.height}})}},_onZoom:function(t){var e=t.originX,i=t.originY;if("animating"!==this._state){var n=this.seriesModel.getData().tree.root;if(!n)return;var o=n.getLayout();if(!o)return;var a=new de(o.x,o.y,o.width,o.height),r=this.seriesModel.layoutInfo;e-=r.x,i-=r.y;var s=xt();St(s,s,[-e,-i]),It(s,s,[t.scale,t.scale]),St(s,s,[e,i]),a.applyTransform(s),this.api.dispatchAction({type:"treemapRender",from:this.uid,seriesId:this.seriesModel.id,rootRect:{x:a.x,y:a.y,width:a.width,height:a.height}})}},_initEvents:function(t){t.on("click",function(t){if("ready"===this._state){var e=this.seriesModel.get("nodeClick",!0);if(e){var i=this.findTarget(t.offsetX,t.offsetY);if(i){var n=i.node;if(n.getLayout().isLeafRoot)this._rootToNode(i);else if("zoomToNode"===e)this._zoomToNode(i);else if("link"===e){var o=n.hostTree.data.getItemModel(n.dataIndex),a=o.get("link",!0),r=o.get("target",!0)||"blank";a&&window.open(a,r)}}}}},this)},_renderBreadcrumb:function(t,e,i){i||(i=null!=t.get("leafDepth",!0)?{node:t.getViewRoot()}:this.findTarget(e.getWidth()/2,e.getHeight()/2))||(i={node:t.getData().tree.root}),(this._breadcrumb||(this._breadcrumb=new pd(this.group))).render(t,e,i.node,XC(function(e){"animating"!==this._state&&(hd(t.getViewRoot(),e)?this._rootToNode({node:e}):this._zoomToNode({node:e}))},this))},remove:function(){this._clearController(),this._containerGroup&&this._containerGroup.removeAll(),this._storage={nodeGroup:[],background:[],content:[]},this._state="ready",this._breadcrumb&&this._breadcrumb.remove()},dispose:function(){this._clearController()},_zoomToNode:function(t){this.api.dispatchAction({type:"treemapZoomToNode",from:this.uid,seriesId:this.seriesModel.id,targetNode:t.node})},_rootToNode:function(t){this.api.dispatchAction({type:"treemapRootToNode",from:this.uid,seriesId:this.seriesModel.id,targetNode:t.node})},findTarget:function(t,e){var i;return this.seriesModel.getViewRoot().eachNode({attr:"viewChildren",order:"preorder"},function(n){var o=this._storage.background[n.getRawIndex()];if(o){var a=o.transformCoordToLocal(t,e),r=o.shape;if(!(r.x<=a[0]&&a[0]<=r.x+r.width&&r.y<=a[1]&&a[1]<=r.y+r.height))return!1;i={node:n,offsetX:a[0],offsetY:a[1]}}},this),i}});for(var aL=["treemapZoomToNode","treemapRender","treemapMove"],rL=0;rL<aL.length;rL++)Es({type:aL[rL],update:"updateView"},function(){});Es({type:"treemapRootToNode",update:"updateView"},function(t,e){e.eachComponent({mainType:"series",subType:"treemap",query:t},function(e,i){var n=ld(t,["treemapZoomToNode","treemapRootToNode"],e);if(n){var o=e.getViewRoot();o&&(t.direction=hd(o,n.node)?"rollUp":"drillDown"),e.resetViewRoot(n.node)}})});var sL=d,lL=w,uL=-1,hL=function(t){var e=t.mappingMethod,n=t.type,o=this.option=i(t);this.type=n,this.mappingMethod=e,this._normalizeData=dL[e];var a=cL[n];this.applyVisual=a.applyVisual,this.getColorMapper=a.getColorMapper,this._doMap=a._doMap[e],"piecewise"===e?(bd(o),_d(o)):"category"===e?o.categories?wd(o):bd(o,!0):(k("linear"!==e||o.dataExtent),bd(o))};hL.prototype={constructor:hL,mapValueToVisual:function(t){var e=this._normalizeData(t);return this._doMap(e,t)},getNormalizer:function(){return m(this._normalizeData,this)}};var cL=hL.visualHandlers={color:{applyVisual:Id("color"),getColorMapper:function(){var t=this.option;return m("category"===t.mappingMethod?function(t,e){return!e&&(t=this._normalizeData(t)),Td.call(this,t)}:function(e,i,n){var o=!!n;return!i&&(e=this._normalizeData(e)),n=Ut(e,t.parsedVisual,n),o?n:qt(n,"rgba")},this)},_doMap:{linear:function(t){return qt(Ut(t,this.option.parsedVisual),"rgba")},category:Td,piecewise:function(t,e){var i=Cd.call(this,e);return null==i&&(i=qt(Ut(t,this.option.parsedVisual),"rgba")),i},fixed:Ad}},colorHue:Sd(function(t,e){return jt(t,e)}),colorSaturation:Sd(function(t,e){return jt(t,null,e)}),colorLightness:Sd(function(t,e){return jt(t,null,null,e)}),colorAlpha:Sd(function(t,e){return Yt(t,e)}),opacity:{applyVisual:Id("opacity"),_doMap:Dd([0,1])},liftZ:{applyVisual:Id("liftZ"),_doMap:{linear:Ad,category:Ad,piecewise:Ad,fixed:Ad}},symbol:{applyVisual:function(t,e,i){var n=this.mapValueToVisual(t);if(_(n))i("symbol",n);else if(lL(n))for(var o in n)n.hasOwnProperty(o)&&i(o,n[o])},_doMap:{linear:Md,category:Td,piecewise:function(t,e){var i=Cd.call(this,e);return null==i&&(i=Md.call(this,t)),i},fixed:Ad}},symbolSize:{applyVisual:Id("symbolSize"),_doMap:Dd([0,1])}},dL={linear:function(t){return Bo(t,this.option.dataExtent,[0,1],!0)},piecewise:function(t){var e=this.option.pieceList,i=hL.findPieceIndex(t,e,!0);if(null!=i)return Bo(i,[0,e.length-1],[0,1],!0)},category:function(t){var e=this.option.categories?this.option.categoryMap[t]:t;return null==e?uL:e},fixed:B};hL.listVisualTypes=function(){var t=[];return d(cL,function(e,i){t.push(i)}),t},hL.addVisualHandler=function(t,e){cL[t]=e},hL.isValidType=function(t){return cL.hasOwnProperty(t)},hL.eachVisual=function(t,e,i){w(t)?d(t,e,i):e.call(i,t)},hL.mapVisual=function(t,e,i){var n,o=y(t)?[]:w(t)?{}:(n=!0,null);return hL.eachVisual(t,function(t,a){var r=e.call(i,t,a);n?o=r:o[a]=r}),o},hL.retrieveVisuals=function(t){var e,i={};return t&&sL(cL,function(n,o){t.hasOwnProperty(o)&&(i[o]=t[o],e=!0)}),e?i:null},hL.prepareVisualTypes=function(t){if(lL(t)){var e=[];sL(t,function(t,i){e.push(i)}),t=e}else{if(!y(t))return[];t=t.slice()}return t.sort(function(t,e){return"color"===e&&"color"!==t&&0===t.indexOf("color")?1:-1}),t},hL.dependsOn=function(t,e){return"color"===e?!(!t||0!==t.indexOf(e)):t===e},hL.findPieceIndex=function(t,e,i){function n(e,i){var n=Math.abs(e-t);n<a&&(a=n,o=i)}for(var o,a=1/0,r=0,s=e.length;r<s;r++){var l=e[r].value;if(null!=l){if(l===t||"string"==typeof l&&l===t+"")return r;i&&n(l,r)}}for(var r=0,s=e.length;r<s;r++){var u=e[r],h=u.interval,c=u.close;if(h){if(h[0]===-1/0){if(kd(c[1],t,h[1]))return r}else if(h[1]===1/0){if(kd(c[0],h[0],t))return r}else if(kd(c[0],h[0],t)&&kd(c[1],t,h[1]))return r;i&&n(h[0],r),i&&n(h[1],r)}}if(i)return t===1/0?e.length-1:t===-1/0?0:o};var fL=y,pL="itemStyle",gL={seriesType:"treemap",reset:function(t,e,i,n){var o=t.getData().tree,a=o.root,r=t.getModel(pL);a.isRemoved()||Pd(a,{},f(o.levelModels,function(t){return t?t.get(pL):null}),r,t.getViewRoot().getAncestors(),t)}},mL=Math.max,vL=Math.min,yL=T,xL=d,_L=["itemStyle","borderWidth"],wL=["itemStyle","gapWidth"],bL=["upperLabel","show"],SL=["upperLabel","height"],ML={seriesType:"treemap",reset:function(t,e,i,n){var o=i.getWidth(),r=i.getHeight(),s=t.option,l=ca(t.getBoxLayoutParams(),{width:i.getWidth(),height:i.getHeight()}),u=s.size||[],h=Vo(yL(l.width,u[0]),o),c=Vo(yL(l.height,u[1]),r),d=n&&n.type,f=ld(n,["treemapZoomToNode","treemapRootToNode"],t),p="treemapRender"===d||"treemapMove"===d?n.rootRect:null,g=t.getViewRoot(),m=ud(g);if("treemapMove"!==d){var v="treemapZoomToNode"===d?jd(t,f,g,h,c):p?[p.width,p.height]:[h,c],y=s.sort;y&&"asc"!==y&&"desc"!==y&&(y="desc");var x={squareRatio:s.squareRatio,sort:y,leafDepth:s.leafDepth};g.hostTree.clearLayouts();_={x:0,y:0,width:v[0],height:v[1],area:v[0]*v[1]};g.setLayout(_),Gd(g,x,!1,0);var _=g.getLayout();xL(m,function(t,e){var i=(m[e+1]||g).getValue();t.setLayout(a({dataExtent:[i,i],borderWidth:0,upperHeight:0},_))})}var w=t.getData().tree.root;w.setLayout(Yd(l,p,f),!0),t.setLayoutInfo(l),qd(w,new de(-l.x,-l.y,o,r),m,g,0)}};Bs(gL),zs(ML);var IL=function(t){this._directed=t||!1,this.nodes=[],this.edges=[],this._nodesMap={},this._edgesMap={},this.data,this.edgeData},TL=IL.prototype;TL.type="graph",TL.isDirected=function(){return this._directed},TL.addNode=function(t,e){t=t||""+e;var i=this._nodesMap;if(!i[$d(t)]){var n=new Jd(t,e);return n.hostGraph=this,this.nodes.push(n),i[$d(t)]=n,n}},TL.getNodeByIndex=function(t){var e=this.data.getRawIndex(t);return this.nodes[e]},TL.getNodeById=function(t){return this._nodesMap[$d(t)]},TL.addEdge=function(t,e,i){var n=this._nodesMap,o=this._edgesMap;if("number"==typeof t&&(t=this.nodes[t]),"number"==typeof e&&(e=this.nodes[e]),Jd.isInstance(t)||(t=n[$d(t)]),Jd.isInstance(e)||(e=n[$d(e)]),t&&e){var a=t.id+"-"+e.id;if(!o[a]){var r=new Qd(t,e,i);return r.hostGraph=this,this._directed&&(t.outEdges.push(r),e.inEdges.push(r)),t.edges.push(r),t!==e&&e.edges.push(r),this.edges.push(r),o[a]=r,r}}},TL.getEdgeByIndex=function(t){var e=this.edgeData.getRawIndex(t);return this.edges[e]},TL.getEdge=function(t,e){Jd.isInstance(t)&&(t=t.id),Jd.isInstance(e)&&(e=e.id);var i=this._edgesMap;return this._directed?i[t+"-"+e]:i[t+"-"+e]||i[e+"-"+t]},TL.eachNode=function(t,e){for(var i=this.nodes,n=i.length,o=0;o<n;o++)i[o].dataIndex>=0&&t.call(e,i[o],o)},TL.eachEdge=function(t,e){for(var i=this.edges,n=i.length,o=0;o<n;o++)i[o].dataIndex>=0&&i[o].node1.dataIndex>=0&&i[o].node2.dataIndex>=0&&t.call(e,i[o],o)},TL.breadthFirstTraverse=function(t,e,i,n){if(Jd.isInstance(e)||(e=this._nodesMap[$d(e)]),e){for(var o="out"===i?"outEdges":"in"===i?"inEdges":"edges",a=0;a<this.nodes.length;a++)this.nodes[a].__visited=!1;if(!t.call(n,e,null))for(var r=[e];r.length;)for(var s=r.shift(),l=s[o],a=0;a<l.length;a++){var u=l[a],h=u.node1===s?u.node2:u.node1;if(!h.__visited){if(t.call(n,h,s))return;r.push(h),h.__visited=!0}}}},TL.update=function(){for(var t=this.data,e=this.edgeData,i=this.nodes,n=this.edges,o=0,a=i.length;o<a;o++)i[o].dataIndex=-1;for(var o=0,a=t.count();o<a;o++)i[t.getRawIndex(o)].dataIndex=o;e.filterSelf(function(t){var i=n[e.getRawIndex(t)];return i.node1.dataIndex>=0&&i.node2.dataIndex>=0});for(var o=0,a=n.length;o<a;o++)n[o].dataIndex=-1;for(var o=0,a=e.count();o<a;o++)n[e.getRawIndex(o)].dataIndex=o},TL.clone=function(){for(var t=new IL(this._directed),e=this.nodes,i=this.edges,n=0;n<e.length;n++)t.addNode(e[n].id,e[n].dataIndex);for(n=0;n<i.length;n++){var o=i[n];t.addEdge(o.node1.id,o.node2.id,o.dataIndex)}return t},Jd.prototype={constructor:Jd,degree:function(){return this.edges.length},inDegree:function(){return this.inEdges.length},outDegree:function(){return this.outEdges.length},getModel:function(t){if(!(this.dataIndex<0))return this.hostGraph.data.getItemModel(this.dataIndex).getModel(t)}},Qd.prototype.getModel=function(t){if(!(this.dataIndex<0))return this.hostGraph.edgeData.getItemModel(this.dataIndex).getModel(t)};var AL=function(t,e){return{getValue:function(i){var n=this[t][e];return n.get(n.getDimension(i||"value"),this.dataIndex)},setVisual:function(i,n){this.dataIndex>=0&&this[t][e].setItemVisual(this.dataIndex,i,n)},getVisual:function(i,n){return this[t][e].getItemVisual(this.dataIndex,i,n)},setLayout:function(i,n){this.dataIndex>=0&&this[t][e].setItemLayout(this.dataIndex,i,n)},getLayout:function(){return this[t][e].getItemLayout(this.dataIndex)},getGraphicEl:function(){return this[t][e].getItemGraphicEl(this.dataIndex)},getRawIndex:function(){return this[t][e].getRawIndex(this.dataIndex)}}};h(Jd,AL("hostGraph","data")),h(Qd,AL("hostGraph","edgeData")),IL.Node=Jd,IL.Edge=Qd,Yi(Jd),Yi(Qd);var DL=function(t,e,i,n,o){for(var a=new IL(n),r=0;r<t.length;r++)a.addNode(T(t[r].id,t[r].name,r),r);for(var s=[],u=[],h=0,r=0;r<e.length;r++){var c=e[r],d=c.source,f=c.target;a.addEdge(d,f,h)&&(u.push(c),s.push(T(c.id,d+" > "+f)),h++)}var p,g=i.get("coordinateSystem");if("cartesian2d"===g||"polar"===g)p=ml(t,i);else{var m=Fa.get(g),v=m&&"view"!==m.type?m.dimensions||[]:[];l(v,"value")<0&&v.concat(["value"]);var y=_A(t,{coordDimensions:v});(p=new vA(y,i)).initData(t)}var x=new vA(["value"],i);return x.initData(u,s),o&&o(p,x),kc({mainData:p,struct:a,structAttr:"graph",datas:{node:p,edge:x},datasAttr:{node:"data",edge:"edgeData"}}),a.update(),a},CL=Hs({type:"series.graph",init:function(t){CL.superApply(this,"init",arguments),this.legendDataProvider=function(){return this._categoriesData},this.fillDataTextStyle(t.edges||t.links),this._updateCategoriesData()},mergeOption:function(t){CL.superApply(this,"mergeOption",arguments),this.fillDataTextStyle(t.edges||t.links),this._updateCategoriesData()},mergeDefaultAndTheme:function(t){CL.superApply(this,"mergeDefaultAndTheme",arguments),Ci(t,["edgeLabel"],["show"])},getInitialData:function(t,e){var i=t.edges||t.links||[],n=t.data||t.nodes||[],o=this;if(n&&i)return DL(n,i,this,!0,function(t,i){function n(t){return(t=this.parsePath(t))&&"label"===t[0]?r:t&&"emphasis"===t[0]&&"label"===t[1]?l:this.parentModel}t.wrapMethod("getItemModel",function(t){var e=o._categoriesModels[t.getShallow("category")];return e&&(e.parentModel=t.parentModel,t.parentModel=e),t});var a=o.getModel("edgeLabel"),r=new No({label:a.option},a.parentModel,e),s=o.getModel("emphasis.edgeLabel"),l=new No({emphasis:{label:s.option}},s.parentModel,e);i.wrapMethod("getItemModel",function(t){return t.customizeGetParent(n),t})}).data},getGraph:function(){return this.getData().graph},getEdgeData:function(){return this.getGraph().edgeData},getCategoriesData:function(){return this._categoriesData},formatTooltip:function(t,e,i){if("edge"===i){var n=this.getData(),o=this.getDataParams(t,i),a=n.graph.getEdgeByIndex(t),r=n.getName(a.node1.dataIndex),s=n.getName(a.node2.dataIndex),l=[];return null!=r&&l.push(r),null!=s&&l.push(s),l=ia(l.join(" > ")),o.value&&(l+=" : "+ia(o.value)),l}return CL.superApply(this,"formatTooltip",arguments)},_updateCategoriesData:function(){var t=f(this.option.categories||[],function(t){return null!=t.value?t:a({value:0},t)}),e=new vA(["value"],this);e.initData(t),this._categoriesData=e,this._categoriesModels=e.mapArray(function(t){return e.getItemModel(t,!0)})},setZoom:function(t){this.option.zoom=t},setCenter:function(t){this.option.center=t},isAnimationEnabled:function(){return CL.superCall(this,"isAnimationEnabled")&&!("force"===this.get("layout")&&this.get("force.layoutAnimation"))},defaultOption:{zlevel:0,z:2,coordinateSystem:"view",legendHoverLink:!0,hoverAnimation:!0,layout:null,focusNodeAdjacency:!1,circular:{rotateLabel:!1},force:{initLayout:null,repulsion:[0,50],gravity:.1,edgeLength:30,layoutAnimation:!0},left:"center",top:"center",symbol:"circle",symbolSize:10,edgeSymbol:["none","none"],edgeSymbolSize:10,edgeLabel:{position:"middle"},draggable:!1,roam:!1,center:null,zoom:1,nodeScaleRatio:.6,label:{show:!1,formatter:"{b}"},itemStyle:{},lineStyle:{color:"#aaa",width:1,curveness:0,opacity:.5},emphasis:{label:{show:!0}}}}),LL=_M.prototype,kL=bM.prototype,PL=Un({type:"ec-line",style:{stroke:"#000",fill:null},shape:{x1:0,y1:0,x2:0,y2:0,percent:1,cpx1:null,cpy1:null},buildPath:function(t,e){(tf(e)?LL:kL).buildPath(t,e)},pointAt:function(t){return tf(this.shape)?LL.pointAt.call(this,t):kL.pointAt.call(this,t)},tangentAt:function(t){var e=this.shape,i=tf(e)?[e.x2-e.x1,e.y2-e.y1]:kL.tangentAt.call(this,t);return q(i,i)}}),NL=["fromSymbol","toSymbol"],OL=rf.prototype;OL.beforeUpdate=function(){var t=this,e=t.childOfName("fromSymbol"),i=t.childOfName("toSymbol"),n=t.childOfName("label");if(e||i||!n.ignore){for(var o=1,a=this.parent;a;)a.scale&&(o/=a.scale[0]),a=a.parent;var r=t.childOfName("line");if(this.__dirty||r.__dirty){var s=r.shape.percent,l=r.pointAt(0),u=r.pointAt(s),h=U([],u,l);if(q(h,h),e&&(e.attr("position",l),c=r.tangentAt(0),e.attr("rotation",Math.PI/2-Math.atan2(c[1],c[0])),e.attr("scale",[o*s,o*s])),i){i.attr("position",u);var c=r.tangentAt(1);i.attr("rotation",-Math.PI/2-Math.atan2(c[1],c[0])),i.attr("scale",[o*s,o*s])}if(!n.ignore){n.attr("position",u);var d,f,p,g=5*o;if("end"===n.__position)d=[h[0]*g+u[0],h[1]*g+u[1]],f=h[0]>.8?"left":h[0]<-.8?"right":"center",p=h[1]>.8?"top":h[1]<-.8?"bottom":"middle";else if("middle"===n.__position){var m=s/2,v=[(c=r.tangentAt(m))[1],-c[0]],y=r.pointAt(m);v[1]>0&&(v[0]=-v[0],v[1]=-v[1]),d=[y[0]+v[0]*g,y[1]+v[1]*g],f="center",p="bottom";var x=-Math.atan2(c[1],c[0]);u[0]<l[0]&&(x=Math.PI+x),n.attr("rotation",x)}else d=[-h[0]*g+l[0],-h[1]*g+l[1]],f=h[0]>.8?"right":h[0]<-.8?"left":"center",p=h[1]>.8?"bottom":h[1]<-.8?"top":"middle";n.attr({style:{textVerticalAlign:n.__verticalAlign||p,textAlign:n.__textAlign||f},position:d,scale:[o,o]})}}}},OL._createLine=function(t,e,i){var n=t.hostModel,o=of(t.getItemLayout(e));o.shape.percent=0,To(o,{shape:{percent:1}},n,e),this.add(o);var a=new rM({name:"label",lineLabelOriginalOpacity:1});this.add(a),d(NL,function(i){var n=nf(i,t,e);this.add(n),this[ef(i)]=t.getItemVisual(e,i)},this),this._updateCommonStl(t,e,i)},OL.updateData=function(t,e,i){var n=t.hostModel,o=this.childOfName("line"),a=t.getItemLayout(e),r={shape:{}};af(r.shape,a),Io(o,r,n,e),d(NL,function(i){var n=t.getItemVisual(e,i),o=ef(i);if(this[o]!==n){this.remove(this.childOfName(i));var a=nf(i,t,e);this.add(a)}this[o]=n},this),this._updateCommonStl(t,e,i)},OL._updateCommonStl=function(t,e,i){var n=t.hostModel,o=this.childOfName("line"),a=i&&i.lineStyle,s=i&&i.hoverLineStyle,l=i&&i.labelModel,u=i&&i.hoverLabelModel;if(!i||t.hasItemOption){var h=t.getItemModel(e);a=h.getModel("lineStyle").getLineStyle(),s=h.getModel("emphasis.lineStyle").getLineStyle(),l=h.getModel("label"),u=h.getModel("emphasis.label")}var c=t.getItemVisual(e,"color"),f=D(t.getItemVisual(e,"opacity"),a.opacity,1);o.useStyle(r({strokeNoScale:!0,fill:"none",stroke:c,opacity:f},a)),o.hoverStyle=s,d(NL,function(t){var e=this.childOfName(t);e&&(e.setColor(c),e.setStyle({opacity:f}))},this);var p,g,m=l.getShallow("show"),v=u.getShallow("show"),y=this.childOfName("label");if((m||v)&&(p=c||"#000",null==(g=n.getFormattedLabel(e,"normal",t.dataType)))){var x=n.getRawValue(e);g=null==x?t.getName(e):isFinite(x)?Go(x):x}var _=m?g:null,w=v?A(n.getFormattedLabel(e,"emphasis",t.dataType),g):null,b=y.style;null==_&&null==w||(mo(y.style,l,{text:_},{autoColor:p}),y.__textAlign=b.textAlign,y.__verticalAlign=b.textVerticalAlign,y.__position=l.get("position")||"middle"),y.hoverStyle=null!=w?{text:w,textFill:u.getTextColor(!0),fontStyle:u.getShallow("fontStyle"),fontWeight:u.getShallow("fontWeight"),fontSize:u.getShallow("fontSize"),fontFamily:u.getShallow("fontFamily")}:{text:null},y.ignore=!m&&!v,fo(this)},OL.highlight=function(){this.trigger("emphasis")},OL.downplay=function(){this.trigger("normal")},OL.updateLayout=function(t,e){this.setLinePoints(t.getItemLayout(e))},OL.setLinePoints=function(t){var e=this.childOfName("line");af(e.shape,t),e.dirty()},u(rf,tb);var EL=sf.prototype;EL.isPersistent=function(){return!0},EL.updateData=function(t){var e=this,i=e.group,n=e._lineData;e._lineData=t,n||i.removeAll();var o=hf(t);t.diff(n).add(function(i){lf(e,t,i,o)}).update(function(i,a){uf(e,n,t,a,i,o)}).remove(function(t){i.remove(n.getItemGraphicEl(t))}).execute()},EL.updateLayout=function(){var t=this._lineData;t&&t.eachItemGraphicEl(function(e,i){e.updateLayout(t,i)},this)},EL.incrementalPrepareUpdate=function(t){this._seriesScope=hf(t),this._lineData=null,this.group.removeAll()},EL.incrementalUpdate=function(t,e){for(var i=t.start;i<t.end;i++)if(df(e.getItemLayout(i))){var n=new this._ctor(e,i,this._seriesScope);n.traverse(function(t){t.isGroup||(t.incremental=t.useHoverLayer=!0)}),this.group.add(n),e.setItemGraphicEl(i,n)}},EL.remove=function(){this._clearIncremental(),this._incremental=null,this.group.removeAll()},EL._clearIncremental=function(){var t=this._incremental;t&&t.clearDisplaybles()};var RL=[],zL=[],BL=[],VL=sn,GL=hw,FL=Math.abs,WL=function(t,e){function i(t){var e=t.getVisual("symbolSize");return e instanceof Array&&(e=(e[0]+e[1])/2),e}var n=[],o=cn,a=[[],[],[]],r=[[],[]],s=[];e/=2,t.eachEdge(function(t,l){var u=t.getLayout(),h=t.getVisual("fromSymbol"),c=t.getVisual("toSymbol");u.__original||(u.__original=[F(u[0]),F(u[1])],u[2]&&u.__original.push(F(u[2])));var d=u.__original;if(null!=u[2]){if(G(a[0],d[0]),G(a[1],d[2]),G(a[2],d[1]),h&&"none"!==h){var f=i(t.node1),p=ff(a,d[0],f*e);o(a[0][0],a[1][0],a[2][0],p,n),a[0][0]=n[3],a[1][0]=n[4],o(a[0][1],a[1][1],a[2][1],p,n),a[0][1]=n[3],a[1][1]=n[4]}if(c&&"none"!==c){var f=i(t.node2),p=ff(a,d[1],f*e);o(a[0][0],a[1][0],a[2][0],p,n),a[1][0]=n[1],a[2][0]=n[2],o(a[0][1],a[1][1],a[2][1],p,n),a[1][1]=n[1],a[2][1]=n[2]}G(u[0],a[0]),G(u[1],a[2]),G(u[2],a[1])}else{if(G(r[0],d[0]),G(r[1],d[1]),U(s,r[1],r[0]),q(s,s),h&&"none"!==h){f=i(t.node1);Z(r[0],r[0],s,f*e)}if(c&&"none"!==c){f=i(t.node2);Z(r[1],r[1],s,-f*e)}G(u[0],r[0]),G(u[1],r[1])}})},HL="__focusNodeAdjacency",ZL=["itemStyle","opacity"],UL=["lineStyle","opacity"];Zs({type:"graph",init:function(t,e){var i=new Du,n=new sf,o=this.group;this._controller=new oc(e.getZr()),this._controllerHost={target:o},o.add(i.group),o.add(n.group),this._symbolDraw=i,this._lineDraw=n,this._firstRender=!0},render:function(t,e,i){var n=t.coordinateSystem;this._model=t,this._nodeScaleRatio=t.get("nodeScaleRatio");var o=this._symbolDraw,a=this._lineDraw,r=this.group;if("view"===n.type){var s={position:n.position,scale:n.scale};this._firstRender?r.attr(s):Io(r,s,t)}WL(t.getGraph(),this._getNodeGlobalScale(t));var l=t.getData();o.updateData(l);var u=t.getEdgeData();a.updateData(u),this._updateNodeAndLinkScale(),this._updateController(t,e,i),clearTimeout(this._layoutTimeout);var h=t.forceLayout,c=t.get("force.layoutAnimation");h&&this._startForceLayoutIteration(h,c),l.eachItemGraphicEl(function(e,n){var o=l.getItemModel(n);e.off("drag").off("dragend");var a=o.get("draggable");a&&e.on("drag",function(){h&&(h.warmUp(),!this._layouting&&this._startForceLayoutIteration(h,c),h.setFixed(n),l.setItemLayout(n,e.position))},this).on("dragend",function(){h&&h.setUnfixed(n)},this),e.setDraggable(a&&h),e[HL]&&e.off("mouseover",e[HL]),e.__unfocusNodeAdjacency&&e.off("mouseout",e.__unfocusNodeAdjacency),o.get("focusNodeAdjacency")&&(e.on("mouseover",e[HL]=function(){i.dispatchAction({type:"focusNodeAdjacency",seriesId:t.id,dataIndex:e.dataIndex})}),e.on("mouseout",e.__unfocusNodeAdjacency=function(){i.dispatchAction({type:"unfocusNodeAdjacency",seriesId:t.id})}))},this),l.graph.eachEdge(function(e){var n=e.getGraphicEl();n[HL]&&n.off("mouseover",n[HL]),n.__unfocusNodeAdjacency&&n.off("mouseout",n.__unfocusNodeAdjacency),e.getModel().get("focusNodeAdjacency")&&(n.on("mouseover",n[HL]=function(){i.dispatchAction({type:"focusNodeAdjacency",seriesId:t.id,edgeDataIndex:e.dataIndex})}),n.on("mouseout",n.__unfocusNodeAdjacency=function(){i.dispatchAction({type:"unfocusNodeAdjacency",seriesId:t.id})}))});var d="circular"===t.get("layout")&&t.get("circular.rotateLabel"),f=l.getLayout("cx"),p=l.getLayout("cy");l.eachItemGraphicEl(function(t,e){var i=t.getSymbolPath();if(d){var n=l.getItemLayout(e),o=Math.atan2(n[1]-p,n[0]-f);o<0&&(o=2*Math.PI+o);var a=n[0]<f;a&&(o-=Math.PI);var r=a?"left":"right";i.setStyle({textRotation:-o,textPosition:r,textOrigin:"center"}),i.hoverStyle&&(i.hoverStyle.textPosition=r)}else i.setStyle({textRotation:0})}),this._firstRender=!1},dispose:function(){this._controller&&this._controller.dispose(),this._controllerHost={}},focusNodeAdjacency:function(t,e,i,n){var o=this._model.getData().graph,a=n.dataIndex,r=n.edgeDataIndex,s=o.getNodeByIndex(a),l=o.getEdgeByIndex(r);(s||l)&&(o.eachNode(function(t){gf(t,ZL,.1)}),o.eachEdge(function(t){gf(t,UL,.1)}),s&&(mf(s,ZL),d(s.edges,function(t){t.dataIndex<0||(mf(t,UL),mf(t.node1,ZL),mf(t.node2,ZL))})),l&&(mf(l,UL),mf(l.node1,ZL),mf(l.node2,ZL)))},unfocusNodeAdjacency:function(t,e,i,n){var o=this._model.getData().graph;o.eachNode(function(t){gf(t,ZL)}),o.eachEdge(function(t){gf(t,UL)})},_startForceLayoutIteration:function(t,e){var i=this;!function n(){t.step(function(t){i.updateLayout(i._model),(i._layouting=!t)&&(e?i._layoutTimeout=setTimeout(n,16):n())})}()},_updateController:function(t,e,i){var n=this._controller,o=this._controllerHost,a=this.group;n.setPointerChecker(function(e,n,o){var r=a.getBoundingRect();return r.applyTransform(a.transform),r.contain(n,o)&&!gc(e,i,t)}),"view"===t.coordinateSystem.type?(n.enable(t.get("roam")),o.zoomLimit=t.get("scaleLimit"),o.zoom=t.coordinateSystem.getZoom(),n.off("pan").off("zoom").on("pan",function(e){fc(o,e.dx,e.dy),i.dispatchAction({seriesId:t.id,type:"graphRoam",dx:e.dx,dy:e.dy})}).on("zoom",function(e){pc(o,e.scale,e.originX,e.originY),i.dispatchAction({seriesId:t.id,type:"graphRoam",zoom:e.scale,originX:e.originX,originY:e.originY}),this._updateNodeAndLinkScale(),WL(t.getGraph(),this._getNodeGlobalScale(t)),this._lineDraw.updateLayout()},this)):n.disable()},_updateNodeAndLinkScale:function(){var t=this._model,e=t.getData(),i=this._getNodeGlobalScale(t),n=[i,i];e.eachItemGraphicEl(function(t,e){t.attr("scale",n)})},_getNodeGlobalScale:function(t){var e=t.coordinateSystem;if("view"!==e.type)return 1;var i=this._nodeScaleRatio,n=e.scale,o=n&&n[0]||1;return((e.getZoom()-1)*i+1)/o},updateLayout:function(t){WL(t.getGraph(),this._getNodeGlobalScale(t)),this._symbolDraw.updateLayout(),this._lineDraw.updateLayout()},remove:function(t,e){this._symbolDraw&&this._symbolDraw.remove(),this._lineDraw&&this._lineDraw.remove()}}),Es({type:"focusNodeAdjacency",event:"focusNodeAdjacency",update:"series:focusNodeAdjacency"},function(){}),Es({type:"unfocusNodeAdjacency",event:"unfocusNodeAdjacency",update:"series:unfocusNodeAdjacency"},function(){}),Es({type:"graphRoam",event:"graphRoam",update:"none"},function(t,e){e.eachComponent({mainType:"series",query:t},function(e){var i=bc(e.coordinateSystem,t);e.setCenter&&e.setCenter(i.center),e.setZoom&&e.setZoom(i.zoom)})});var XL=Z;Os(function(t){var e=t.findComponents({mainType:"legend"});e&&e.length&&t.eachSeriesByType("graph",function(t){var i=t.getCategoriesData(),n=t.getGraph().data,o=i.mapArray(i.getName);n.filterSelf(function(t){var i=n.getItemModel(t).getShallow("category");if(null!=i){"number"==typeof i&&(i=o[i]);for(var a=0;a<e.length;a++)if(!e[a].isSelected(i))return!1}return!0})},this)}),Bs(TD("graph","circle",null)),Bs(function(t){var e={};t.eachSeriesByType("graph",function(t){var i=t.getCategoriesData(),n=t.getData(),o={};i.each(function(n){var a=i.getName(n);o["ec-"+a]=n;var r=i.getItemModel(n).get("itemStyle.color")||t.getColorFromPalette(a,e);i.setItemVisual(n,"color",r)}),i.count()&&n.each(function(t){var e=n.getItemModel(t).getShallow("category");null!=e&&("string"==typeof e&&(e=o["ec-"+e]),n.getItemVisual(t,"color",!0)||n.setItemVisual(t,"color",i.getItemVisual(e,"color")))})})}),Bs(function(t){t.eachSeriesByType("graph",function(t){var e=t.getGraph(),i=t.getEdgeData(),n=vf(t.get("edgeSymbol")),o=vf(t.get("edgeSymbolSize")),a="lineStyle.color".split("."),r="lineStyle.opacity".split(".");i.setVisual("fromSymbol",n&&n[0]),i.setVisual("toSymbol",n&&n[1]),i.setVisual("fromSymbolSize",o&&o[0]),i.setVisual("toSymbolSize",o&&o[1]),i.setVisual("color",t.get(a)),i.setVisual("opacity",t.get(r)),i.each(function(t){var n=i.getItemModel(t),o=e.getEdgeByIndex(t),s=vf(n.getShallow("symbol",!0)),l=vf(n.getShallow("symbolSize",!0)),u=n.get(a),h=n.get(r);switch(u){case"source":u=o.node1.getVisual("color");break;case"target":u=o.node2.getVisual("color")}s[0]&&o.setVisual("fromSymbol",s[0]),s[1]&&o.setVisual("toSymbol",s[1]),l[0]&&o.setVisual("fromSymbolSize",l[0]),l[1]&&o.setVisual("toSymbolSize",l[1]),o.setVisual("color",u),o.setVisual("opacity",h)})})}),zs(function(t,e){t.eachSeriesByType("graph",function(t){var e=t.get("layout"),i=t.coordinateSystem;if(i&&"view"!==i.type){var n=t.getData(),o=[];d(i.dimensions,function(t){o=o.concat(n.mapDimension(t,!0))});for(var a=0;a<n.count();a++){for(var r=[],s=!1,l=0;l<o.length;l++){var u=n.get(o[l],a);isNaN(u)||(s=!0),r.push(u)}s?n.setItemLayout(a,i.dataToPoint(r)):n.setItemLayout(a,[NaN,NaN])}xf(n.graph)}else e&&"none"!==e||yf(t)})}),zs(function(t){t.eachSeriesByType("graph",function(t){"circular"===t.get("layout")&&_f(t)})}),zs(function(t){t.eachSeriesByType("graph",function(t){var e=t.coordinateSystem;if(!e||"view"===e.type)if("force"===t.get("layout")){var i=t.preservedPoints||{},n=t.getGraph(),o=n.data,a=n.edgeData,r=t.getModel("force"),s=r.get("initLayout");t.preservedPoints?o.each(function(t){var e=o.getId(t);o.setItemLayout(t,i[e]||[NaN,NaN])}):s&&"none"!==s?"circular"===s&&_f(t):yf(t);var l=o.getDataExtent("value"),u=a.getDataExtent("value"),h=r.get("repulsion"),c=r.get("edgeLength");y(h)||(h=[h,h]),y(c)||(c=[c,c]),c=[c[1],c[0]];var d=o.mapArray("value",function(t,e){var i=o.getItemLayout(e),n=Bo(t,l,h);return isNaN(n)&&(n=(h[0]+h[1])/2),{w:n,rep:n,fixed:o.getItemModel(e).get("fixed"),p:!i||isNaN(i[0])||isNaN(i[1])?null:i}}),f=a.mapArray("value",function(t,e){var i=n.getEdgeByIndex(e),o=Bo(t,u,c);return isNaN(o)&&(o=(c[0]+c[1])/2),{n1:d[i.node1.dataIndex],n2:d[i.node2.dataIndex],d:o,curveness:i.getModel().get("lineStyle.curveness")||0}}),p=(e=t.coordinateSystem).getBoundingRect(),g=wf(d,f,{rect:p,gravity:r.get("gravity")}),m=g.step;g.step=function(t){for(var e=0,a=d.length;e<a;e++)d[e].fixed&&G(d[e].p,n.getNodeByIndex(e).getLayout());m(function(e,a,r){for(var s=0,l=e.length;s<l;s++)e[s].fixed||n.getNodeByIndex(s).setLayout(e[s].p),i[o.getId(s)]=e[s].p;for(var s=0,l=a.length;s<l;s++){var u=a[s],h=n.getEdgeByIndex(s),c=u.n1.p,d=u.n2.p,f=h.getLayout();(f=f?f.slice():[])[0]=f[0]||[],f[1]=f[1]||[],G(f[0],c),G(f[1],d),+u.curveness&&(f[2]=[(c[0]+d[0])/2-(c[1]-d[1])*u.curveness,(c[1]+d[1])/2-(d[0]-c[0])*u.curveness]),h.setLayout(f)}t&&t(r)})},t.forceLayout=g,t.preservedPoints=i,g.step()}else t.forceLayout=null})}),Rs("graphView",{create:function(t,e){var i=[];return t.eachSeriesByType("graph",function(t){var n=t.get("coordinateSystem");if(!n||"view"===n){var o=t.getData(),a=[],r=[];fn(o.mapArray(function(t){var e=o.getItemModel(t);return[+e.get("x"),+e.get("y")]}),a,r),r[0]-a[0]==0&&(r[0]+=1,a[0]-=1),r[1]-a[1]==0&&(r[1]+=1,a[1]-=1);var s=(r[0]-a[0])/(r[1]-a[1]),l=bf(t,e,s);isNaN(s)&&(a=[l.x,l.y],r=[l.x+l.width,l.y+l.height]);var u=r[0]-a[0],h=r[1]-a[1],c=l.width,d=l.height,f=t.coordinateSystem=new Mc;f.zoomLimit=t.get("scaleLimit"),f.setBoundingRect(a[0],a[1],u,h),f.setViewRect(l.x,l.y,c,d),f.setCenter(t.get("center")),f.setZoom(t.get("zoom")),i.push(f)}}),i}});YI.extend({type:"series.gauge",getInitialData:function(t,e){var i=t.data||[];return y(i)||(i=[i]),t.data=i,oC(this,["value"])},defaultOption:{zlevel:0,z:2,center:["50%","50%"],legendHoverLink:!0,radius:"75%",startAngle:225,endAngle:-45,clockwise:!0,min:0,max:100,splitNumber:10,axisLine:{show:!0,lineStyle:{color:[[.2,"#91c7ae"],[.8,"#63869e"],[1,"#c23531"]],width:30}},splitLine:{show:!0,length:30,lineStyle:{color:"#eee",width:2,type:"solid"}},axisTick:{show:!0,splitNumber:5,length:8,lineStyle:{color:"#eee",width:1,type:"solid"}},axisLabel:{show:!0,distance:5,color:"auto"},pointer:{show:!0,length:"80%",width:8},itemStyle:{color:"auto"},title:{show:!0,offsetCenter:[0,"-40%"],color:"#333",fontSize:15},detail:{show:!0,backgroundColor:"rgba(0,0,0,0)",borderWidth:0,borderColor:"#ccc",width:100,height:null,padding:[5,10],offsetCenter:[0,"40%"],color:"auto",fontSize:30}}});var jL=Pn.extend({type:"echartsGaugePointer",shape:{angle:0,width:10,r:10,x:0,y:0},buildPath:function(t,e){var i=Math.cos,n=Math.sin,o=e.r,a=e.width,r=e.angle,s=e.x-i(r)*a*(a>=o/3?1:2),l=e.y-n(r)*a*(a>=o/3?1:2);r=e.angle-Math.PI/2,t.moveTo(s,l),t.lineTo(e.x+i(r)*a,e.y+n(r)*a),t.lineTo(e.x+i(e.angle)*o,e.y+n(e.angle)*o),t.lineTo(e.x-i(r)*a,e.y-n(r)*a),t.lineTo(s,l)}}),YL=2*Math.PI,qL=(Ar.extend({type:"gauge",render:function(t,e,i){this.group.removeAll();var n=t.get("axisLine.lineStyle.color"),o=Sf(t,i);this._renderMain(t,e,i,n,o)},dispose:function(){},_renderMain:function(t,e,i,n,o){for(var a=this.group,r=t.getModel("axisLine").getModel("lineStyle"),s=t.get("clockwise"),l=-t.get("startAngle")/180*Math.PI,u=-t.get("endAngle")/180*Math.PI,h=(u-l)%YL,c=l,d=r.get("width"),f=0;f<n.length;f++){var p=Math.min(Math.max(n[f][0],0),1),g=new hM({shape:{startAngle:c,endAngle:u=l+h*p,cx:o.cx,cy:o.cy,clockwise:s,r0:o.r-d,r:o.r},silent:!0});g.setStyle({fill:n[f][1]}),g.setStyle(r.getLineStyle(["color","borderWidth","borderColor"])),a.add(g),c=u}var m=function(t){if(t<=0)return n[0][1];for(var e=0;e<n.length;e++)if(n[e][0]>=t&&(0===e?0:n[e-1][0])<t)return n[e][1];return n[e-1][1]};if(!s){var v=l;l=u,u=v}this._renderTicks(t,e,i,m,o,l,u,s),this._renderPointer(t,e,i,m,o,l,u,s),this._renderTitle(t,e,i,m,o),this._renderDetail(t,e,i,m,o)},_renderTicks:function(t,e,i,n,o,a,r,s){for(var l=this.group,u=o.cx,h=o.cy,c=o.r,d=+t.get("min"),f=+t.get("max"),p=t.getModel("splitLine"),g=t.getModel("axisTick"),m=t.getModel("axisLabel"),v=t.get("splitNumber"),y=g.get("splitNumber"),x=Vo(p.get("length"),c),_=Vo(g.get("length"),c),w=a,b=(r-a)/v,S=b/y,M=p.getModel("lineStyle").getLineStyle(),I=g.getModel("lineStyle").getLineStyle(),T=0;T<=v;T++){var A=Math.cos(w),D=Math.sin(w);if(p.get("show")){var C=new _M({shape:{x1:A*c+u,y1:D*c+h,x2:A*(c-x)+u,y2:D*(c-x)+h},style:M,silent:!0});"auto"===M.stroke&&C.setStyle({stroke:n(T/v)}),l.add(C)}if(m.get("show")){var L=Mf(Go(T/v*(f-d)+d),m.get("formatter")),k=m.get("distance"),P=n(T/v);l.add(new rM({style:mo({},m,{text:L,x:A*(c-x-k)+u,y:D*(c-x-k)+h,textVerticalAlign:D<-.4?"top":D>.4?"bottom":"middle",textAlign:A<-.4?"left":A>.4?"right":"center"},{autoColor:P}),silent:!0}))}if(g.get("show")&&T!==v){for(var N=0;N<=y;N++){var A=Math.cos(w),D=Math.sin(w),O=new _M({shape:{x1:A*c+u,y1:D*c+h,x2:A*(c-_)+u,y2:D*(c-_)+h},silent:!0,style:I});"auto"===I.stroke&&O.setStyle({stroke:n((T+N/y)/v)}),l.add(O),w+=S}w-=S}else w+=b}},_renderPointer:function(t,e,i,n,o,a,r,s){var l=this.group,u=this._data;if(t.get("pointer.show")){var h=[+t.get("min"),+t.get("max")],c=[a,r],d=t.getData(),f=d.mapDimension("value");d.diff(u).add(function(e){var i=new jL({shape:{angle:a}});To(i,{shape:{angle:Bo(d.get(f,e),h,c,!0)}},t),l.add(i),d.setItemGraphicEl(e,i)}).update(function(e,i){var n=u.getItemGraphicEl(i);Io(n,{shape:{angle:Bo(d.get(f,e),h,c,!0)}},t),l.add(n),d.setItemGraphicEl(e,n)}).remove(function(t){var e=u.getItemGraphicEl(t);l.remove(e)}).execute(),d.eachItemGraphicEl(function(t,e){var i=d.getItemModel(e),a=i.getModel("pointer");t.setShape({x:o.cx,y:o.cy,width:Vo(a.get("width"),o.r),r:Vo(a.get("length"),o.r)}),t.useStyle(i.getModel("itemStyle").getItemStyle()),"auto"===t.style.fill&&t.setStyle("fill",n(Bo(d.get(f,e),h,[0,1],!0))),fo(t,i.getModel("emphasis.itemStyle").getItemStyle())}),this._data=d}else u&&u.eachItemGraphicEl(function(t){l.remove(t)})},_renderTitle:function(t,e,i,n,o){var a=t.getData(),r=a.mapDimension("value"),s=t.getModel("title");if(s.get("show")){var l=s.get("offsetCenter"),u=o.cx+Vo(l[0],o.r),h=o.cy+Vo(l[1],o.r),c=+t.get("min"),d=+t.get("max"),f=n(Bo(t.getData().get(r,0),[c,d],[0,1],!0));this.group.add(new rM({silent:!0,style:mo({},s,{x:u,y:h,text:a.getName(0),textAlign:"center",textVerticalAlign:"middle"},{autoColor:f,forceRich:!0})}))}},_renderDetail:function(t,e,i,n,o){var a=t.getModel("detail"),r=+t.get("min"),s=+t.get("max");if(a.get("show")){var l=a.get("offsetCenter"),u=o.cx+Vo(l[0],o.r),h=o.cy+Vo(l[1],o.r),c=Vo(a.get("width"),o.r),d=Vo(a.get("height"),o.r),f=t.getData(),p=f.get(f.mapDimension("value"),0),g=n(Bo(p,[r,s],[0,1],!0));this.group.add(new rM({silent:!0,style:mo({},a,{x:u,y:h,text:Mf(p,a.get("formatter")),textWidth:isNaN(c)?null:c,textHeight:isNaN(d)?null:d,textAlign:"center",textVerticalAlign:"middle"},{autoColor:g,forceRich:!0})}))}}}),Hs({type:"series.funnel",init:function(t){qL.superApply(this,"init",arguments),this.legendDataProvider=function(){return this.getRawData()},this._defaultLabelLine(t)},getInitialData:function(t,e){return oC(this,["value"])},_defaultLabelLine:function(t){Ci(t,"labelLine",["show"]);var e=t.labelLine,i=t.emphasis.labelLine;e.show=e.show&&t.label.show,i.show=i.show&&t.emphasis.label.show},getDataParams:function(t){var e=this.getData(),i=qL.superCall(this,"getDataParams",t),n=e.mapDimension("value"),o=e.getSum(n);return i.percent=o?+(e.get(n,t)/o*100).toFixed(2):0,i.$vars.push("percent"),i},defaultOption:{zlevel:0,z:2,legendHoverLink:!0,left:80,top:60,right:80,bottom:60,minSize:"0%",maxSize:"100%",sort:"descending",gap:0,funnelAlign:"center",label:{show:!0,position:"outer"},labelLine:{show:!0,length:20,lineStyle:{width:1,type:"solid"}},itemStyle:{borderColor:"#fff",borderWidth:1},emphasis:{label:{show:!0}}}})),KL=If.prototype,$L=["itemStyle","opacity"];KL.updateData=function(t,e,i){var n=this.childAt(0),o=t.hostModel,a=t.getItemModel(e),s=t.getItemLayout(e),l=t.getItemModel(e).get($L);l=null==l?1:l,n.useStyle({}),i?(n.setShape({points:s.points}),n.setStyle({opacity:0}),To(n,{style:{opacity:l}},o,e)):Io(n,{style:{opacity:l},shape:{points:s.points}},o,e);var u=a.getModel("itemStyle"),h=t.getItemVisual(e,"color");n.setStyle(r({lineJoin:"round",fill:h},u.getItemStyle(["opacity"]))),n.hoverStyle=u.getModel("emphasis").getItemStyle(),this._updateLabel(t,e),fo(this)},KL._updateLabel=function(t,e){var i=this.childAt(1),n=this.childAt(2),o=t.hostModel,a=t.getItemModel(e),r=t.getItemLayout(e).label,s=t.getItemVisual(e,"color");Io(i,{shape:{points:r.linePoints||r.linePoints}},o,e),Io(n,{style:{x:r.x,y:r.y}},o,e),n.attr({rotation:r.rotation,origin:[r.x,r.y],z2:10});var l=a.getModel("label"),u=a.getModel("emphasis.label"),h=a.getModel("labelLine"),c=a.getModel("emphasis.labelLine"),s=t.getItemVisual(e,"color");go(n.style,n.hoverStyle={},l,u,{labelFetcher:t.hostModel,labelDataIndex:e,defaultText:t.getName(e),autoColor:s,useInsideStyle:!!r.inside},{textAlign:r.textAlign,textVerticalAlign:r.verticalAlign}),n.ignore=n.normalIgnore=!l.get("show"),n.hoverIgnore=!u.get("show"),i.ignore=i.normalIgnore=!h.get("show"),i.hoverIgnore=!c.get("show"),i.setStyle({stroke:s}),i.setStyle(h.getModel("lineStyle").getLineStyle()),i.hoverStyle=c.getModel("lineStyle").getLineStyle()},u(If,tb);Ar.extend({type:"funnel",render:function(t,e,i){var n=t.getData(),o=this._data,a=this.group;n.diff(o).add(function(t){var e=new If(n,t);n.setItemGraphicEl(t,e),a.add(e)}).update(function(t,e){var i=o.getItemGraphicEl(e);i.updateData(n,t),a.add(i),n.setItemGraphicEl(t,i)}).remove(function(t){var e=o.getItemGraphicEl(t);a.remove(e)}).execute(),this._data=n},remove:function(){this.group.removeAll(),this._data=null},dispose:function(){}});Bs(uC("funnel")),zs(function(t,e,i){t.eachSeriesByType("funnel",function(t){var i=t.getData(),n=i.mapDimension("value"),o=t.get("sort"),a=Tf(t,e),r=Af(i,o),s=[Vo(t.get("minSize"),a.width),Vo(t.get("maxSize"),a.width)],l=i.getDataExtent(n),u=t.get("min"),h=t.get("max");null==u&&(u=Math.min(l[0],0)),null==h&&(h=l[1]);var c=t.get("funnelAlign"),d=t.get("gap"),f=(a.height-d*(i.count()-1))/i.count(),p=a.y,g=function(t,e){var o,r=Bo(i.get(n,t)||0,[u,h],s,!0);switch(c){case"left":o=a.x;break;case"center":o=a.x+(a.width-r)/2;break;case"right":o=a.x+a.width-r}return[[o,e],[o+r,e]]};"ascending"===o&&(f=-f,d=-d,p+=a.height,r=r.reverse());for(var m=0;m<r.length;m++){var v=r[m],y=r[m+1],x=i.getItemModel(v).get("itemStyle.height");null==x?x=f:(x=Vo(x,a.height),"ascending"===o&&(x=-x));var _=g(v,p),w=g(y,p+x);p+=x+d,i.setItemLayout(v,{points:_.concat(w.slice().reverse())})}Df(i)})}),Os(fC("funnel"));var JL=function(t,e,i,n,o){aD.call(this,t,e,i),this.type=n||"value",this.axisIndex=o};JL.prototype={constructor:JL,model:null,isHorizontal:function(){return"horizontal"!==this.coordinateSystem.getModel().get("layout")}},u(JL,aD);var QL=function(t,e,i,n,o,a){e[0]=Pf(e[0],i),e[1]=Pf(e[1],i),t=t||0;var r=i[1]-i[0];null!=o&&(o=Pf(o,[0,r])),null!=a&&(a=Math.max(a,null!=o?o:0)),"all"===n&&(o=a=Math.abs(e[1]-e[0]),n=0);var s=kf(e,n);e[n]+=t;var l=o||0,u=i.slice();s.sign<0?u[0]+=l:u[1]-=l,e[n]=Pf(e[n],u);h=kf(e,n);null!=o&&(h.sign!==s.sign||h.span<o)&&(e[1-n]=e[n]+s.sign*o);var h=kf(e,n);return null!=a&&h.span>a&&(e[1-n]=e[n]+h.sign*a),e},tk=d,ek=Math.min,ik=Math.max,nk=Math.floor,ok=Math.ceil,ak=Go,rk=Math.PI;Nf.prototype={type:"parallel",constructor:Nf,_init:function(t,e,i){var n=t.dimensions,o=t.parallelAxisIndex;tk(n,function(t,i){var n=o[i],a=e.getComponent("parallelAxis",n),r=this._axesMap.set(t,new JL(t,Hl(a),[0,0],a.get("type"),n)),s="category"===r.type;r.onBand=s&&a.get("boundaryGap"),r.inverse=a.get("inverse"),a.axis=r,r.model=a,r.coordinateSystem=a.coordinateSystem=this},this)},update:function(t,e){this._updateAxesFromSeries(this._model,t)},containPoint:function(t){var e=this._makeLayoutInfo(),i=e.axisBase,n=e.layoutBase,o=e.pixelDimIndex,a=t[1-o],r=t[o];return a>=i&&a<=i+e.axisLength&&r>=n&&r<=n+e.layoutLength},getModel:function(){return this._model},_updateAxesFromSeries:function(t,e){e.eachSeries(function(i){if(t.contains(i,e)){var n=i.getData();tk(this.dimensions,function(t){var e=this._axesMap.get(t);e.scale.unionExtentFromData(n,n.mapDimension(t)),Wl(e.scale,e.model)},this)}},this)},resize:function(t,e){this._rect=ca(t.getBoxLayoutParams(),{width:e.getWidth(),height:e.getHeight()}),this._layoutAxes()},getRect:function(){return this._rect},_makeLayoutInfo:function(){var t,e=this._model,i=this._rect,n=["x","y"],o=["width","height"],a=e.get("layout"),r="horizontal"===a?0:1,s=i[o[r]],l=[0,s],u=this.dimensions.length,h=Of(e.get("axisExpandWidth"),l),c=Of(e.get("axisExpandCount")||0,[0,u]),d=e.get("axisExpandable")&&u>3&&u>c&&c>1&&h>0&&s>0,f=e.get("axisExpandWindow");f?(t=Of(f[1]-f[0],l),f[1]=f[0]+t):(t=Of(h*(c-1),l),(f=[h*(e.get("axisExpandCenter")||nk(u/2))-t/2])[1]=f[0]+t);var p=(s-t)/(u-c);p<3&&(p=0);var g=[nk(ak(f[0]/h,1))+1,ok(ak(f[1]/h,1))-1],m=p/h*f[0];return{layout:a,pixelDimIndex:r,layoutBase:i[n[r]],layoutLength:s,axisBase:i[n[1-r]],axisLength:i[o[1-r]],axisExpandable:d,axisExpandWidth:h,axisCollapseWidth:p,axisExpandWindow:f,axisCount:u,winInnerIndices:g,axisExpandWindow0Pos:m}},_layoutAxes:function(){var t=this._rect,e=this._axesMap,i=this.dimensions,n=this._makeLayoutInfo(),o=n.layout;e.each(function(t){var e=[0,n.axisLength],i=t.inverse?1:0;t.setExtent(e[i],e[1-i])}),tk(i,function(e,i){var a=(n.axisExpandable?Rf:Ef)(i,n),r={horizontal:{x:a.position,y:n.axisLength},vertical:{x:0,y:a.position}},s={horizontal:rk/2,vertical:0},l=[r[o].x+t.x,r[o].y+t.y],u=s[o],h=xt();Mt(h,h,u),St(h,h,l),this._axesLayout[e]={position:l,rotation:u,transform:h,axisNameAvailableWidth:a.axisNameAvailableWidth,axisLabelShow:a.axisLabelShow,nameTruncateMaxWidth:a.nameTruncateMaxWidth,tickDirection:1,labelDirection:1}},this)},getAxis:function(t){return this._axesMap.get(t)},dataToPoint:function(t,e){return this.axisCoordToPoint(this._axesMap.get(e).dataToCoord(t),e)},eachActiveState:function(t,e,i,n){null==i&&(i=0),null==n&&(n=t.count());var o=this._axesMap,a=this.dimensions,r=[],s=[];d(a,function(e){r.push(t.mapDimension(e)),s.push(o.get(e).model)});for(var l=this.hasAxisBrushed(),u=i;u<n;u++){var h;if(l){h="active";for(var c=t.getValues(r,u),f=0,p=a.length;f<p;f++)if("inactive"===s[f].getActiveState(c[f])){h="inactive";break}}else h="normal";e(h,u)}},hasAxisBrushed:function(){for(var t=this.dimensions,e=this._axesMap,i=!1,n=0,o=t.length;n<o;n++)"normal"!==e.get(t[n]).model.getActiveState()&&(i=!0);return i},axisCoordToPoint:function(t,e){return Do([t,0],this._axesLayout[e].transform)},getAxisLayout:function(t){return i(this._axesLayout[t])},getSlidedAxisExpandWindow:function(t){var e=this._makeLayoutInfo(),i=e.pixelDimIndex,n=e.axisExpandWindow.slice(),o=n[1]-n[0],a=[0,e.axisExpandWidth*(e.axisCount-1)];if(!this.containPoint(t))return{behavior:"none",axisExpandWindow:n};var r,s=t[i]-e.layoutBase-e.axisExpandWindow0Pos,l="slide",u=e.axisCollapseWidth,h=this._model.get("axisExpandSlideTriggerArea"),c=null!=h[0];if(u)c&&u&&s<o*h[0]?(l="jump",r=s-o*h[2]):c&&u&&s>o*(1-h[0])?(l="jump",r=s-o*(1-h[2])):(r=s-o*h[1])>=0&&(r=s-o*(1-h[1]))<=0&&(r=0),(r*=e.axisExpandWidth/u)?QL(r,n,a,"all"):l="none";else{o=n[1]-n[0];(n=[ik(0,a[1]*s/o-o/2)])[1]=ek(a[1],n[0]+o),n[0]=n[1]-o}return{axisExpandWindow:n,behavior:l}}},Fa.register("parallel",{create:function(t,e){var i=[];return t.eachComponent("parallel",function(n,o){var a=new Nf(n,t,e);a.name="parallel_"+o,a.resize(n,e),n.coordinateSystem=a,a.model=n,i.push(a)}),t.eachSeries(function(e){if("parallel"===e.get("coordinateSystem")){var i=t.queryComponents({mainType:"parallel",index:e.get("parallelIndex"),id:e.get("parallelId")})[0];e.coordinateSystem=i.coordinateSystem}}),i}});var sk=lI.extend({type:"baseParallelAxis",axis:null,activeIntervals:[],getAreaSelectStyle:function(){return Qb([["fill","color"],["lineWidth","borderWidth"],["stroke","borderColor"],["width","width"],["opacity","opacity"]])(this.getModel("areaSelectStyle"))},setActiveIntervals:function(t){var e=this.activeIntervals=i(t);if(e)for(var n=e.length-1;n>=0;n--)Fo(e[n])},getActiveState:function(t){var e=this.activeIntervals;if(!e.length)return"normal";if(null==t||isNaN(t))return"inactive";if(1===e.length){var i=e[0];if(i[0]<=t&&t<=i[1])return"active"}else for(var n=0,o=e.length;n<o;n++)if(e[n][0]<=t&&t<=e[n][1])return"active";return"inactive"}}),lk={type:"value",dim:null,areaSelectStyle:{width:20,borderWidth:1,borderColor:"rgba(160,197,232)",color:"rgba(160,197,232)",opacity:.3},realtime:!0,z:10};n(sk.prototype,UA),ED("parallel",sk,function(t,e){return e.type||(e.data?"category":"value")},lk),lI.extend({type:"parallel",dependencies:["parallelAxis"],coordinateSystem:null,dimensions:null,parallelAxisIndex:null,layoutMode:"box",defaultOption:{zlevel:0,z:0,left:80,top:60,right:80,bottom:60,layout:"horizontal",axisExpandable:!1,axisExpandCenter:null,axisExpandCount:0,axisExpandWidth:50,axisExpandRate:17,axisExpandDebounce:50,axisExpandSlideTriggerArea:[-.15,.05,.4],axisExpandTriggerOn:"click",parallelAxisDefault:null},init:function(){lI.prototype.init.apply(this,arguments),this.mergeOption({})},mergeOption:function(t){var e=this.option;t&&n(e,t,!0),this._initDimensions()},contains:function(t,e){var i=t.get("parallelIndex");return null!=i&&e.getComponent("parallel",i)===this},setAxisExpand:function(t){d(["axisExpandable","axisExpandCenter","axisExpandCount","axisExpandWidth","axisExpandWindow"],function(e){t.hasOwnProperty(e)&&(this.option[e]=t[e])},this)},_initDimensions:function(){var t=this.dimensions=[],e=this.parallelAxisIndex=[];d(g(this.dependentModels.parallelAxis,function(t){return(t.get("parallelIndex")||0)===this.componentIndex},this),function(i){t.push("dim"+i.get("dim")),e.push(i.componentIndex)})}}),Es({type:"axisAreaSelect",event:"axisAreaSelected"},function(t,e){e.eachComponent({mainType:"parallelAxis",query:t},function(e){e.axis.model.setActiveIntervals(t.intervals)})}),Es("parallelAxisExpand",function(t,e){e.eachComponent({mainType:"parallel",query:t},function(e){e.setAxisExpand(t)})});var uk=v,hk=d,ck=f,dk=Math.min,fk=Math.max,pk=Math.pow,gk=1e4,mk=6,vk=6,yk="globalPan",xk={w:[0,0],e:[0,1],n:[1,0],s:[1,1]},_k={w:"ew",e:"ew",n:"ns",s:"ns",ne:"nesw",sw:"nesw",nw:"nwse",se:"nwse"},wk={brushStyle:{lineWidth:2,stroke:"rgba(0,0,0,0.3)",fill:"rgba(0,0,0,0.1)"},transformable:!0,brushMode:"single",removeOnClick:!1},bk=0;zf.prototype={constructor:zf,enableBrush:function(t){return this._brushType&&Vf(this),t.brushType&&Bf(this,t),this},setPanels:function(t){if(t&&t.length){var e=this._panels={};d(t,function(t){e[t.panelId]=i(t)})}else this._panels=null;return this},mount:function(t){t=t||{},this._enableGlobalPan=t.enableGlobalPan;var e=this.group;return this._zr.add(e),e.attr({position:t.position||[0,0],rotation:t.rotation||0,scale:t.scale||[1,1]}),this._transform=e.getLocalTransform(),this},eachCover:function(t,e){hk(this._covers,t,e)},updateCovers:function(t){function e(t,e){return(null!=t.id?t.id:a+e)+"-"+t.brushType}function o(e,i){var n=t[e];if(null!=i&&r[i]===u)s[e]=r[i];else{var o=s[e]=null!=i?(r[i].__brushOption=n,r[i]):Ff(l,Gf(l,n));Zf(l,o)}}t=f(t,function(t){return n(i(wk),t,!0)});var a="\0-brush-index-",r=this._covers,s=this._covers=[],l=this,u=this._creatingCover;return new Xs(r,t,function(t,i){return e(t.__brushOption,i)},e).add(o).update(o).remove(function(t){r[t]!==u&&l.group.remove(r[t])}).execute(),this},unmount:function(){return this.enableBrush(!1),Yf(this),this._zr.remove(this.group),this},dispose:function(){this.unmount(),this.off()}},h(zf,fw);var Sk={mousedown:function(t){if(this._dragging)mp.call(this,t);else if(!t.target||!t.target.draggable){dp(t);var e=this.group.transformCoordToLocal(t.offsetX,t.offsetY);this._creatingCover=null,(this._creatingPanel=Xf(this,t,e))&&(this._dragging=!0,this._track=[e.slice()])}},mousemove:function(t){var e=this.group.transformCoordToLocal(t.offsetX,t.offsetY);if(cp(this,t,e),this._dragging){dp(t);var i=pp(this,t,e,!1);i&&qf(this,i)}},mouseup:mp},Mk={lineX:vp(0),lineY:vp(1),rect:{createCover:function(t,e){return Jf(uk(rp,function(t){return t},function(t){return t}),t,e,["w","e","n","s","se","sw","ne","nw"])},getCreatingRange:function(t){var e=$f(t);return np(e[1][0],e[1][1],e[0][0],e[0][1])},updateCoverShape:function(t,e,i,n){Qf(t,e,i,n)},updateCommon:tp,contain:fp},polygon:{createCover:function(t,e){var i=new tb;return i.add(new gM({name:"main",style:ip(e),silent:!0})),i},getCreatingRange:function(t){return t},endCreating:function(t,e){e.remove(e.childAt(0)),e.add(new pM({name:"main",draggable:!0,drift:uk(sp,t,e),ondragend:uk(qf,t,{isEnd:!0})}))},updateCoverShape:function(t,e,i,n){e.childAt(0).setShape({points:up(t,e,i)})},updateCommon:tp,contain:fp}},Ik=["axisLine","axisTickLabel","axisName"],Tk=Ws({type:"parallelAxis",init:function(t,e){Tk.superApply(this,"init",arguments),(this._brushController=new zf(e.getZr())).on("brush",m(this._onBrush,this))},render:function(t,e,i,n){if(!bp(t,e,n)){this.axisModel=t,this.api=i,this.group.removeAll();var o=this._axisGroup;if(this._axisGroup=new tb,this.group.add(this._axisGroup),t.get("show")){var r=Mp(t,e),s=r.coordinateSystem,l=t.getAreaSelectStyle(),u=l.width,h=t.axis.dim,c=a({strokeContainThreshold:u},s.getAxisLayout(h)),f=new FD(t,c);d(Ik,f.add,f),this._axisGroup.add(f.getGroup()),this._refreshBrushController(c,l,t,r,u,i);var p=n&&!1===n.animation?null:t;Lo(o,this._axisGroup,p)}}},_refreshBrushController:function(t,e,i,n,o,a){var r=i.axis.getExtent(),s=r[1]-r[0],l=Math.min(30,.1*Math.abs(s)),u=de.create({x:r[0],y:-o/2,width:s,height:o});u.x-=l,u.width+=2*l,this._brushController.mount({enableGlobalPan:!0,rotation:t.rotation,position:t.position}).setPanels([{panelId:"pl",clipPath:yp(u),isTargetByCursor:_p(u,a,n),getLinearBrushOtherExtent:xp(u,0)}]).enableBrush({brushType:"lineX",brushStyle:e,removeOnClick:!0}).updateCovers(Sp(i))},_onBrush:function(t,e){var i=this.axisModel,n=i.axis,o=f(t,function(t){return[n.coordToData(t.range[0],!0),n.coordToData(t.range[1],!0)]});(!i.option.realtime===e.isEnd||e.removeOnClick)&&this.api.dispatchAction({type:"axisAreaSelect",parallelAxisId:i.id,intervals:o})},dispose:function(){this._brushController.dispose()}});Ws({type:"parallel",render:function(t,e,i){this._model=t,this._api=i,this._handlers||(this._handlers={},d(Ak,function(t,e){i.getZr().on(e,this._handlers[e]=m(t,this))},this)),Nr(this,"_throttledDispatchExpand",t.get("axisExpandRate"),"fixRate")},dispose:function(t,e){d(this._handlers,function(t,i){e.getZr().off(i,t)}),this._handlers=null},_throttledDispatchExpand:function(t){this._dispatchExpand(t)},_dispatchExpand:function(t){t&&this._api.dispatchAction(a({type:"parallelAxisExpand"},t))}});var Ak={mousedown:function(t){Ip(this,"click")&&(this._mouseDownPoint=[t.offsetX,t.offsetY])},mouseup:function(t){var e=this._mouseDownPoint;if(Ip(this,"click")&&e){var i=[t.offsetX,t.offsetY];if(Math.pow(e[0]-i[0],2)+Math.pow(e[1]-i[1],2)>5)return;var n=this._model.coordinateSystem.getSlidedAxisExpandWindow([t.offsetX,t.offsetY]);"none"!==n.behavior&&this._dispatchExpand({axisExpandWindow:n.axisExpandWindow})}this._mouseDownPoint=null},mousemove:function(t){if(!this._mouseDownPoint&&Ip(this,"mousemove")){var e=this._model,i=e.coordinateSystem.getSlidedAxisExpandWindow([t.offsetX,t.offsetY]),n=i.behavior;"jump"===n&&this._throttledDispatchExpand.debounceNextCall(e.get("axisExpandDebounce")),this._throttledDispatchExpand("none"===n?null:{axisExpandWindow:i.axisExpandWindow,animation:"jump"===n&&null})}}};Ns(function(t){Cf(t),Lf(t)}),YI.extend({type:"series.parallel",dependencies:["parallel"],visualColorAccessPath:"lineStyle.color",getInitialData:function(t,e){var i=this.getSource();return Tp(i,this),ml(i,this)},getRawIndicesByActiveState:function(t){var e=this.coordinateSystem,i=this.getData(),n=[];return e.eachActiveState(i,function(e,o){t===e&&n.push(i.getRawIndex(o))}),n},defaultOption:{zlevel:0,z:2,coordinateSystem:"parallel",parallelIndex:0,label:{show:!1},inactiveOpacity:.05,activeOpacity:1,lineStyle:{width:1,opacity:.45,type:"solid"},emphasis:{label:{show:!1}},progressive:500,smooth:!1,animationEasing:"linear"}});var Dk=.3,Ck=(Ar.extend({type:"parallel",init:function(){this._dataGroup=new tb,this.group.add(this._dataGroup),this._data,this._initialized},render:function(t,e,i,n){var o=this._dataGroup,a=t.getData(),r=this._data,s=t.coordinateSystem,l=s.dimensions,u=kp(t);if(a.diff(r).add(function(t){Pp(Lp(a,o,t,l,s),a,t,u)}).update(function(e,i){var o=r.getItemGraphicEl(i),h=Cp(a,e,l,s);a.setItemGraphicEl(e,o),Io(o,{shape:{points:h}},n&&!1===n.animation?null:t,e),Pp(o,a,e,u)}).remove(function(t){var e=r.getItemGraphicEl(t);o.remove(e)}).execute(),!this._initialized){this._initialized=!0;var h=Dp(s,t,function(){setTimeout(function(){o.removeClipPath()})});o.setClipPath(h)}this._data=a},incrementalPrepareRender:function(t,e,i){this._initialized=!0,this._data=null,this._dataGroup.removeAll()},incrementalRender:function(t,e,i){for(var n=e.getData(),o=e.coordinateSystem,a=o.dimensions,r=kp(e),s=t.start;s<t.end;s++){var l=Lp(n,this._dataGroup,s,a,o);l.incremental=!0,Pp(l,n,s,r)}},dispose:function(){},remove:function(){this._dataGroup&&this._dataGroup.removeAll(),this._data=null}}),["lineStyle","normal","opacity"]);Bs({seriesType:"parallel",reset:function(t,e,i){var n=t.getModel("itemStyle"),o=t.getModel("lineStyle"),a=e.get("color"),r=o.get("color")||n.get("color")||a[t.seriesIndex%a.length],s=t.get("inactiveOpacity"),l=t.get("activeOpacity"),u=t.getModel("lineStyle").getLineStyle(),h=t.coordinateSystem,c=t.getData(),d={normal:u.opacity,active:l,inactive:s};return c.setVisual("color",r),{progress:function(t,e){h.eachActiveState(e,function(t,i){var n=d[t];if("normal"===t&&e.hasItemOption){var o=e.getItemModel(i).get(Ck,!0);null!=o&&(n=o)}e.setItemVisual(i,"opacity",n)},t.start,t.end)}}}});var Lk=YI.extend({type:"series.sankey",layoutInfo:null,getInitialData:function(t){var e=t.edges||t.links,i=t.data||t.nodes;if(i&&e)return DL(i,e,this,!0).data},setNodePosition:function(t,e){var i=this.option.data[t];i.localX=e[0],i.localY=e[1]},getGraph:function(){return this.getData().graph},getEdgeData:function(){return this.getGraph().edgeData},formatTooltip:function(t,e,i){if("edge"===i){var n=this.getDataParams(t,i),o=n.data,a=o.source+" -- "+o.target;return n.value&&(a+=" : "+n.value),ia(a)}return Lk.superCall(this,"formatTooltip",t,e)},optionUpdated:function(){var t=this.option;!0===t.focusNodeAdjacency&&(t.focusNodeAdjacency="allEdges")},defaultOption:{zlevel:0,z:2,coordinateSystem:"view",layout:null,left:"5%",top:"5%",right:"20%",bottom:"5%",orient:"horizontal",nodeWidth:20,nodeGap:8,draggable:!0,focusNodeAdjacency:!1,layoutIterations:32,label:{show:!0,position:"right",color:"#000",fontSize:12},itemStyle:{borderWidth:1,borderColor:"#333"},lineStyle:{color:"#314656",opacity:.2,curveness:.5},emphasis:{label:{show:!0},lineStyle:{opacity:.6}},animationEasing:"linear",animationDuration:1e3}}),kk=["itemStyle","opacity"],Pk=["lineStyle","opacity"],Nk=Un({shape:{x1:0,y1:0,x2:0,y2:0,cpx1:0,cpy1:0,cpx2:0,cpy2:0,extent:0,orient:""},buildPath:function(t,e){var i=e.extent;"vertical"===e.orient?(t.moveTo(e.x1,e.y1),t.bezierCurveTo(e.cpx1,e.cpy1,e.cpx2,e.cpy2,e.x2,e.y2),t.lineTo(e.x2+i,e.y2),t.bezierCurveTo(e.cpx2+i,e.cpy2,e.cpx1+i,e.cpy1,e.x1+i,e.y1)):(t.moveTo(e.x1,e.y1),t.bezierCurveTo(e.cpx1,e.cpy1,e.cpx2,e.cpy2,e.x2,e.y2),t.lineTo(e.x2,e.y2+i),t.bezierCurveTo(e.cpx2,e.cpy2+i,e.cpx1,e.cpy1+i,e.x1,e.y1+i)),t.closePath()}});Zs({type:"sankey",_model:null,_focusAdjacencyDisabled:!1,render:function(t,e,i){var n=this,o=t.getGraph(),a=this.group,r=t.layoutInfo,s=r.width,l=r.height,u=t.getData(),h=t.getData("edge"),c=t.get("orient");this._model=t,a.removeAll(),a.attr("position",[r.x,r.y]),o.eachEdge(function(e){var i=new Nk;i.dataIndex=e.dataIndex,i.seriesIndex=t.seriesIndex,i.dataType="edge";var n,o,r,u,d,f,p,g,m=e.getModel("lineStyle"),v=m.get("curveness"),y=e.node1.getLayout(),x=e.node1.getModel(),_=x.get("localX"),w=x.get("localY"),b=e.node2.getLayout(),S=e.node2.getModel(),M=S.get("localX"),I=S.get("localY"),T=e.getLayout();switch(i.shape.extent=Math.max(1,T.dy),i.shape.orient=c,"vertical"===c?(n=(null!=_?_*s:y.x)+T.sy,o=(null!=w?w*l:y.y)+y.dy,r=(null!=M?M*s:b.x)+T.ty,d=n,f=o*(1-v)+(u=null!=I?I*l:b.y)*v,p=r,g=o*v+u*(1-v)):(n=(null!=_?_*s:y.x)+y.dx,o=(null!=w?w*l:y.y)+T.sy,d=n*(1-v)+(r=null!=M?M*s:b.x)*v,f=o,p=n*v+r*(1-v),g=u=(null!=I?I*l:b.y)+T.ty),i.setShape({x1:n,y1:o,x2:r,y2:u,cpx1:d,cpy1:f,cpx2:p,cpy2:g}),i.setStyle(m.getItemStyle()),i.style.fill){case"source":i.style.fill=e.node1.getVisual("color");break;case"target":i.style.fill=e.node2.getVisual("color")}fo(i,e.getModel("emphasis.lineStyle").getItemStyle()),a.add(i),h.setItemGraphicEl(e.dataIndex,i)}),o.eachNode(function(e){var i=e.getLayout(),n=e.getModel(),o=n.get("localX"),r=n.get("localY"),h=n.getModel("label"),c=n.getModel("emphasis.label"),d=new yM({shape:{x:null!=o?o*s:i.x,y:null!=r?r*l:i.y,width:i.dx,height:i.dy},style:n.getModel("itemStyle").getItemStyle()}),f=e.getModel("emphasis.itemStyle").getItemStyle();go(d.style,f,h,c,{labelFetcher:t,labelDataIndex:e.dataIndex,defaultText:e.id,isRectText:!0}),d.setStyle("fill",e.getVisual("color")),fo(d,f),a.add(d),u.setItemGraphicEl(e.dataIndex,d),d.dataType="node"}),u.eachItemGraphicEl(function(e,o){var a=u.getItemModel(o);a.get("draggable")&&(e.drift=function(e,a){n._focusAdjacencyDisabled=!0,this.shape.x+=e,this.shape.y+=a,this.dirty(),i.dispatchAction({type:"dragNode",seriesId:t.id,dataIndex:u.getRawIndex(o),localX:this.shape.x/s,localY:this.shape.y/l})},e.ondragend=function(){n._focusAdjacencyDisabled=!1},e.draggable=!0,e.cursor="move"),a.get("focusNodeAdjacency")&&(e.off("mouseover").on("mouseover",function(){n._focusAdjacencyDisabled||i.dispatchAction({type:"focusNodeAdjacency",seriesId:t.id,dataIndex:e.dataIndex})}),e.off("mouseout").on("mouseout",function(){n._focusAdjacencyDisabled||i.dispatchAction({type:"unfocusNodeAdjacency",seriesId:t.id})}))}),h.eachItemGraphicEl(function(e,o){h.getItemModel(o).get("focusNodeAdjacency")&&(e.off("mouseover").on("mouseover",function(){n._focusAdjacencyDisabled||i.dispatchAction({type:"focusNodeAdjacency",seriesId:t.id,edgeDataIndex:e.dataIndex})}),e.off("mouseout").on("mouseout",function(){n._focusAdjacencyDisabled||i.dispatchAction({type:"unfocusNodeAdjacency",seriesId:t.id})}))}),!this._data&&t.get("animation")&&a.setClipPath(zp(a.getBoundingRect(),t,function(){a.removeClipPath()})),this._data=t.getData()},dispose:function(){},focusNodeAdjacency:function(t,e,i,n){var o=this._model.getData(),a=o.graph,r=n.dataIndex,s=o.getItemModel(r),l=n.edgeDataIndex;if(null!=r||null!=l){var u=a.getNodeByIndex(r),h=a.getEdgeByIndex(l);if(a.eachNode(function(t){Ep(t,kk,.1)}),a.eachEdge(function(t){Ep(t,Pk,.1)}),u){Rp(u,kk);var c=s.get("focusNodeAdjacency");"outEdges"===c?d(u.outEdges,function(t){t.dataIndex<0||(Rp(t,Pk),Rp(t.node2,kk))}):"inEdges"===c?d(u.inEdges,function(t){t.dataIndex<0||(Rp(t,Pk),Rp(t.node1,kk))}):"allEdges"===c&&d(u.edges,function(t){t.dataIndex<0||(Rp(t,Pk),Rp(t.node1,kk),Rp(t.node2,kk))})}h&&(Rp(h,Pk),Rp(h.node1,kk),Rp(h.node2,kk))}},unfocusNodeAdjacency:function(t,e,i,n){var o=this._model.getGraph();o.eachNode(function(t){Ep(t,kk)}),o.eachEdge(function(t){Ep(t,Pk)})}}),Es({type:"dragNode",event:"dragNode",update:"update"},function(t,e){e.eachComponent({mainType:"series",subType:"sankey",query:t},function(e){e.setNodePosition(t.dataIndex,[t.localX,t.localY])})});zs(function(t,e,i){t.eachSeriesByType("sankey",function(t){var i=t.get("nodeWidth"),n=t.get("nodeGap"),o=Bp(t,e);t.layoutInfo=o;var a=o.width,r=o.height,s=t.getGraph(),l=s.nodes,u=s.edges;Gp(l),Vp(l,u,i,n,a,r,0!==g(l,function(t){return 0===t.getLayout().value}).length?0:t.get("layoutIterations"),t.get("orient"))})}),Bs(function(t,e){t.eachSeriesByType("sankey",function(t){var e=t.getGraph().nodes;if(e.length){var i=1/0,n=-1/0;d(e,function(t){var e=t.getLayout().value;e<i&&(i=e),e>n&&(n=e)}),d(e,function(e){var o=new hL({type:"color",mappingMethod:"linear",dataExtent:[i,n],visual:t.get("color")}).mapValueToVisual(e.getLayout().value);e.setVisual("color",o);var a=e.getModel().get("itemStyle.color");null!=a&&e.setVisual("color",a)})}})});var Ok={_baseAxisDim:null,getInitialData:function(t,e){var i,n,o=e.getComponent("xAxis",this.get("xAxisIndex")),a=e.getComponent("yAxis",this.get("yAxisIndex")),r=o.get("type"),s=a.get("type");"category"===r?(t.layout="horizontal",i=o.getOrdinalMeta(),n=!0):"category"===s?(t.layout="vertical",i=a.getOrdinalMeta(),n=!0):t.layout=t.layout||"horizontal";var l=["x","y"],u="horizontal"===t.layout?0:1,h=this._baseAxisDim=l[u],c=l[1-u],f=[o,a],p=f[u].get("type"),g=f[1-u].get("type"),m=t.data;if(m&&n){var v=[];d(m,function(t,e){var i;t.value&&y(t.value)?(i=t.value.slice(),t.value.unshift(e)):y(t)?(i=t.slice(),t.unshift(e)):i=t,v.push(i)}),t.data=v}var x=this.defaultValueDimensions;return oC(this,{coordDimensions:[{name:h,type:qs(p),ordinalMeta:i,otherDims:{tooltip:!1,itemName:0},dimsDef:["base"]},{name:c,type:qs(g),dimsDef:x.slice()}],dimensionsCount:x.length+1})},getBaseAxis:function(){var t=this._baseAxisDim;return this.ecModel.getComponent(t+"Axis",this.get(t+"AxisIndex")).axis}};h(YI.extend({type:"series.boxplot",dependencies:["xAxis","yAxis","grid"],defaultValueDimensions:[{name:"min",defaultTooltip:!0},{name:"Q1",defaultTooltip:!0},{name:"median",defaultTooltip:!0},{name:"Q3",defaultTooltip:!0},{name:"max",defaultTooltip:!0}],dimensions:null,defaultOption:{zlevel:0,z:2,coordinateSystem:"cartesian2d",legendHoverLink:!0,hoverAnimation:!0,layout:null,boxWidth:[7,50],itemStyle:{color:"#fff",borderWidth:1},emphasis:{itemStyle:{borderWidth:2,shadowBlur:5,shadowOffsetX:2,shadowOffsetY:2,shadowColor:"rgba(0,0,0,0.4)"}},animationEasing:"elasticOut",animationDuration:800}}),Ok,!0);var Ek=["itemStyle"],Rk=["emphasis","itemStyle"],zk=(Ar.extend({type:"boxplot",render:function(t,e,i){var n=t.getData(),o=this.group,a=this._data;this._data||o.removeAll();var r="horizontal"===t.get("layout")?1:0;n.diff(a).add(function(t){if(n.hasValue(t)){var e=ig(n.getItemLayout(t),n,t,r,!0);n.setItemGraphicEl(t,e),o.add(e)}}).update(function(t,e){var i=a.getItemGraphicEl(e);if(n.hasValue(t)){var s=n.getItemLayout(t);i?ng(s,i,n,t):i=ig(s,n,t,r),o.add(i),n.setItemGraphicEl(t,i)}else o.remove(i)}).remove(function(t){var e=a.getItemGraphicEl(t);e&&o.remove(e)}).execute(),this._data=n},remove:function(t){var e=this.group,i=this._data;this._data=null,i&&i.eachItemGraphicEl(function(t){t&&e.remove(t)})},dispose:B}),Pn.extend({type:"boxplotBoxPath",shape:{},buildPath:function(t,e){var i=e.points,n=0;for(t.moveTo(i[n][0],i[n][1]),n++;n<4;n++)t.lineTo(i[n][0],i[n][1]);for(t.closePath();n<i.length;n++)t.moveTo(i[n][0],i[n][1]),n++,t.lineTo(i[n][0],i[n][1])}})),Bk=["itemStyle","borderColor"],Vk=d;Bs(function(t,e){var i=t.get("color");t.eachRawSeriesByType("boxplot",function(e){var n=i[e.seriesIndex%i.length],o=e.getData();o.setVisual({legendSymbol:"roundRect",color:e.get(Bk)||n}),t.isSeriesFiltered(e)||o.each(function(t){var e=o.getItemModel(t);o.setItemVisual(t,{color:e.get(Bk,!0)})})})}),zs(function(t){var e=ag(t);Vk(e,function(t){var e=t.seriesModels;e.length&&(rg(t),Vk(e,function(e,i){sg(e,t.boxOffsetList[i],t.boxWidthList[i])}))})}),h(YI.extend({type:"series.candlestick",dependencies:["xAxis","yAxis","grid"],defaultValueDimensions:[{name:"open",defaultTooltip:!0},{name:"close",defaultTooltip:!0},{name:"lowest",defaultTooltip:!0},{name:"highest",defaultTooltip:!0}],dimensions:null,defaultOption:{zlevel:0,z:2,coordinateSystem:"cartesian2d",legendHoverLink:!0,hoverAnimation:!0,layout:null,itemStyle:{color:"#c23531",color0:"#314656",borderWidth:1,borderColor:"#c23531",borderColor0:"#314656"},emphasis:{itemStyle:{borderWidth:2}},barMaxWidth:null,barMinWidth:null,barWidth:null,large:!0,largeThreshold:600,progressive:3e3,progressiveThreshold:1e4,progressiveChunkMode:"mod",animationUpdate:!1,animationEasing:"linear",animationDuration:300},getShadowDim:function(){return"open"},brushSelector:function(t,e,i){var n=e.getItemLayout(t);return n&&i.rect(n.brushRect)}}),Ok,!0);var Gk=["itemStyle"],Fk=["emphasis","itemStyle"],Wk=["color","color0","borderColor","borderColor0"],Hk=(Ar.extend({type:"candlestick",render:function(t,e,i){this._updateDrawMode(t),this._isLargeDraw?this._renderLarge(t):this._renderNormal(t)},incrementalPrepareRender:function(t,e,i){this._clear(),this._updateDrawMode(t)},incrementalRender:function(t,e,i,n){this._isLargeDraw?this._incrementalRenderLarge(t,e):this._incrementalRenderNormal(t,e)},_updateDrawMode:function(t){var e=t.pipelineContext.large;(null==this._isLargeDraw||e^this._isLargeDraw)&&(this._isLargeDraw=e,this._clear())},_renderNormal:function(t){var e=t.getData(),i=this._data,n=this.group,o=e.getLayout("isSimpleBox");this._data||n.removeAll(),e.diff(i).add(function(i){if(e.hasValue(i)){var a,r=e.getItemLayout(i);To(a=lg(r,0,!0),{shape:{points:r.ends}},t,i),ug(a,e,i,o),n.add(a),e.setItemGraphicEl(i,a)}}).update(function(a,r){var s=i.getItemGraphicEl(r);if(e.hasValue(a)){var l=e.getItemLayout(a);s?Io(s,{shape:{points:l.ends}},t,a):s=lg(l),ug(s,e,a,o),n.add(s),e.setItemGraphicEl(a,s)}else n.remove(s)}).remove(function(t){var e=i.getItemGraphicEl(t);e&&n.remove(e)}).execute(),this._data=e},_renderLarge:function(t){this._clear(),cg(t,this.group)},_incrementalRenderNormal:function(t,e){for(var i,n=e.getData(),o=n.getLayout("isSimpleBox");null!=(i=t.next());){var a;ug(a=lg(n.getItemLayout(i)),n,i,o),a.incremental=!0,this.group.add(a)}},_incrementalRenderLarge:function(t,e){cg(e,this.group,!0)},remove:function(t){this._clear()},_clear:function(){this.group.removeAll(),this._data=null},dispose:B}),Pn.extend({type:"normalCandlestickBox",shape:{},buildPath:function(t,e){var i=e.points;this.__simpleBox?(t.moveTo(i[4][0],i[4][1]),t.lineTo(i[6][0],i[6][1])):(t.moveTo(i[0][0],i[0][1]),t.lineTo(i[1][0],i[1][1]),t.lineTo(i[2][0],i[2][1]),t.lineTo(i[3][0],i[3][1]),t.closePath(),t.moveTo(i[4][0],i[4][1]),t.lineTo(i[5][0],i[5][1]),t.moveTo(i[6][0],i[6][1]),t.lineTo(i[7][0],i[7][1]))}})),Zk=Pn.extend({type:"largeCandlestickBox",shape:{},buildPath:function(t,e){for(var i=e.points,n=0;n<i.length;)if(this.__sign===i[n++]){var o=i[n++];t.moveTo(o,i[n++]),t.lineTo(o,i[n++])}else n+=3}}),Uk=["itemStyle","borderColor"],Xk=["itemStyle","borderColor0"],jk=["itemStyle","color"],Yk=["itemStyle","color0"],qk={seriesType:"candlestick",plan:$I(),performRawSeries:!0,reset:function(t,e){function i(t,e){return e.get(t>0?jk:Yk)}function n(t,e){return e.get(t>0?Uk:Xk)}var o=t.getData(),a=t.pipelineContext.large;if(o.setVisual({legendSymbol:"roundRect",colorP:i(1,t),colorN:i(-1,t),borderColorP:n(1,t),borderColorN:n(-1,t)}),!e.isSeriesFiltered(t))return!a&&{progress:function(t,e){for(var o;null!=(o=t.next());){var a=e.getItemModel(o),r=e.getItemLayout(o).sign;e.setItemVisual(o,{color:i(r,a),borderColor:n(r,a)})}}}}},Kk="undefined"!=typeof Float32Array?Float32Array:Array,$k={seriesType:"candlestick",plan:$I(),reset:function(t){var e=t.coordinateSystem,i=t.getData(),n=pg(t,i),o=0,a=1,r=["x","y"],s=i.mapDimension(r[o]),l=i.mapDimension(r[a],!0),u=l[0],h=l[1],c=l[2],d=l[3];if(i.setLayout({candleWidth:n,isSimpleBox:n<=1.3}),!(null==s||l.length<4))return{progress:t.pipelineContext.large?function(t,i){for(var n,r,l=new Kk(5*t.count),f=0,p=[],g=[];null!=(r=t.next());){var m=i.get(s,r),v=i.get(u,r),y=i.get(h,r),x=i.get(c,r),_=i.get(d,r);isNaN(m)||isNaN(x)||isNaN(_)?(l[f++]=NaN,f+=4):(l[f++]=fg(i,r,v,y,h),p[o]=m,p[a]=x,n=e.dataToPoint(p,null,g),l[f++]=n?n[0]:NaN,l[f++]=n?n[1]:NaN,p[a]=_,n=e.dataToPoint(p,null,g),l[f++]=n?n[1]:NaN)}i.setLayout("largePoints",l)}:function(t,i){function r(t,i){var n=[];return n[o]=i,n[a]=t,isNaN(i)||isNaN(t)?[NaN,NaN]:e.dataToPoint(n)}function l(t,e,i){var a=e.slice(),r=e.slice();a[o]=Jn(a[o]+n/2,1,!1),r[o]=Jn(r[o]-n/2,1,!0),i?t.push(a,r):t.push(r,a)}function f(t){return t[o]=Jn(t[o],1),t}for(var p;null!=(p=t.next());){var g=i.get(s,p),m=i.get(u,p),v=i.get(h,p),y=i.get(c,p),x=i.get(d,p),_=Math.min(m,v),w=Math.max(m,v),b=r(_,g),S=r(w,g),M=r(y,g),I=r(x,g),T=[];l(T,S,0),l(T,b,1),T.push(f(I),f(S),f(M),f(b)),i.setItemLayout(p,{sign:fg(i,p,m,v,h),initBaseline:m>v?S[a]:b[a],ends:T,brushRect:function(t,e,i){var s=r(t,i),l=r(e,i);return s[o]-=n/2,l[o]-=n/2,{x:s[0],y:s[1],width:a?n:l[0]-s[0],height:a?l[1]-s[1]:n}}(y,x,g)})}}}}};Ns(function(t){t&&y(t.series)&&d(t.series,function(t){w(t)&&"k"===t.type&&(t.type="candlestick")})}),Bs(qk),zs($k),YI.extend({type:"series.effectScatter",dependencies:["grid","polar"],getInitialData:function(t,e){return ml(this.getSource(),this)},brushSelector:"point",defaultOption:{coordinateSystem:"cartesian2d",zlevel:0,z:2,legendHoverLink:!0,effectType:"ripple",progressive:0,showEffectOn:"render",rippleEffect:{period:4,scale:2.5,brushType:"fill"},symbolSize:10}});var Jk=vg.prototype;Jk.stopEffectAnimation=function(){this.childAt(1).removeAll()},Jk.startEffectAnimation=function(t){for(var e=t.symbolType,i=t.color,n=this.childAt(1),o=0;o<3;o++){var a=Jl(e,-1,-1,2,2,i);a.attr({style:{strokeNoScale:!0},z2:99,silent:!0,scale:[.5,.5]});var r=-o/3*t.period+t.effectOffset;a.animate("",!0).when(t.period,{scale:[t.rippleScale/2,t.rippleScale/2]}).delay(r).start(),a.animateStyle(!0).when(t.period,{opacity:0}).delay(r).start(),n.add(a)}mg(n,t)},Jk.updateEffectAnimation=function(t){for(var e=this._effectCfg,i=this.childAt(1),n=["symbolType","period","rippleScale"],o=0;o<n.length;o++){var a=n[o];if(e[a]!==t[a])return this.stopEffectAnimation(),void this.startEffectAnimation(t)}mg(i,t)},Jk.highlight=function(){this.trigger("emphasis")},Jk.downplay=function(){this.trigger("normal")},Jk.updateData=function(t,e){var i=t.hostModel;this.childAt(0).updateData(t,e);var n=this.childAt(1),o=t.getItemModel(e),a=t.getItemVisual(e,"symbol"),r=gg(t.getItemVisual(e,"symbolSize")),s=t.getItemVisual(e,"color");n.attr("scale",r),n.traverse(function(t){t.attr({fill:s})});var l=o.getShallow("symbolOffset");if(l){var u=n.position;u[0]=Vo(l[0],r[0]),u[1]=Vo(l[1],r[1])}n.rotation=(o.getShallow("symbolRotate")||0)*Math.PI/180||0;var h={};if(h.showEffectOn=i.get("showEffectOn"),h.rippleScale=o.get("rippleEffect.scale"),h.brushType=o.get("rippleEffect.brushType"),h.period=1e3*o.get("rippleEffect.period"),h.effectOffset=e/t.count(),h.z=o.getShallow("z")||0,h.zlevel=o.getShallow("zlevel")||0,h.symbolType=a,h.color=s,this.off("mouseover").off("mouseout").off("emphasis").off("normal"),"render"===h.showEffectOn)this._effectCfg?this.updateEffectAnimation(h):this.startEffectAnimation(h),this._effectCfg=h;else{this._effectCfg=null,this.stopEffectAnimation();var c=this.childAt(0),d=function(){c.highlight(),"render"!==h.showEffectOn&&this.startEffectAnimation(h)},f=function(){c.downplay(),"render"!==h.showEffectOn&&this.stopEffectAnimation()};this.on("mouseover",d,this).on("mouseout",f,this).on("emphasis",d,this).on("normal",f,this)}this._effectCfg=h},Jk.fadeOut=function(t){this.off("mouseover").off("mouseout").off("emphasis").off("normal"),t&&t()},u(vg,tb),Zs({type:"effectScatter",init:function(){this._symbolDraw=new Du(vg)},render:function(t,e,i){var n=t.getData(),o=this._symbolDraw;o.updateData(n),this.group.add(o.group)},updateTransform:function(t,e,i){var n=t.getData();this.group.dirty();var o=AD().reset(t);o.progress&&o.progress({start:0,end:n.count()},n),this._symbolDraw.updateLayout(n)},_updateGroupTransform:function(t){var e=t.coordinateSystem;e&&e.getRoamTransform&&(this.group.transform=At(e.getRoamTransform()),this.group.decomposeTransform())},remove:function(t,e){this._symbolDraw&&this._symbolDraw.remove(e)},dispose:function(){}}),Bs(TD("effectScatter","circle")),zs(AD("effectScatter"));var Qk="undefined"==typeof Uint32Array?Array:Uint32Array,tP="undefined"==typeof Float64Array?Array:Float64Array,eP=YI.extend({type:"series.lines",dependencies:["grid","polar"],visualColorAccessPath:"lineStyle.color",init:function(t){t.data=t.data||[],yg(t);var e=this._processFlatCoordsArray(t.data);this._flatCoords=e.flatCoords,this._flatCoordsOffset=e.flatCoordsOffset,e.flatCoords&&(t.data=new Float32Array(e.count)),eP.superApply(this,"init",arguments)},mergeOption:function(t){if(t.data=t.data||[],yg(t),t.data){var e=this._processFlatCoordsArray(t.data);this._flatCoords=e.flatCoords,this._flatCoordsOffset=e.flatCoordsOffset,e.flatCoords&&(t.data=new Float32Array(e.count))}eP.superApply(this,"mergeOption",arguments)},appendData:function(t){var e=this._processFlatCoordsArray(t.data);e.flatCoords&&(this._flatCoords?(this._flatCoords=z(this._flatCoords,e.flatCoords),this._flatCoordsOffset=z(this._flatCoordsOffset,e.flatCoordsOffset)):(this._flatCoords=e.flatCoords,this._flatCoordsOffset=e.flatCoordsOffset),t.data=new Float32Array(e.count)),this.getRawData().appendData(t.data)},_getCoordsFromItemModel:function(t){var e=this.getData().getItemModel(t);return e.option instanceof Array?e.option:e.getShallow("coords")},getLineCoordsCount:function(t){return this._flatCoordsOffset?this._flatCoordsOffset[2*t+1]:this._getCoordsFromItemModel(t).length},getLineCoords:function(t,e){if(this._flatCoordsOffset){for(var i=this._flatCoordsOffset[2*t],n=this._flatCoordsOffset[2*t+1],o=0;o<n;o++)e[o]=e[o]||[],e[o][0]=this._flatCoords[i+2*o],e[o][1]=this._flatCoords[i+2*o+1];return n}for(var a=this._getCoordsFromItemModel(t),o=0;o<a.length;o++)e[o]=e[o]||[],e[o][0]=a[o][0],e[o][1]=a[o][1];return a.length},_processFlatCoordsArray:function(t){var e=0;if(this._flatCoords&&(e=this._flatCoords.length),"number"==typeof t[0]){for(var i=t.length,n=new Qk(i),o=new tP(i),a=0,r=0,s=0,l=0;l<i;){s++;var u=t[l++];n[r++]=a+e,n[r++]=u;for(var h=0;h<u;h++){var c=t[l++],d=t[l++];o[a++]=c,o[a++]=d}}return{flatCoordsOffset:new Uint32Array(n.buffer,0,r),flatCoords:o,count:s}}return{flatCoordsOffset:null,flatCoords:null,count:t.length}},getInitialData:function(t,e){var i=new vA(["value"],this);return i.hasItemOption=!1,i.initData(t.data,[],function(t,e,n,o){if(t instanceof Array)return NaN;i.hasItemOption=!0;var a=t.value;return null!=a?a instanceof Array?a[o]:a:void 0}),i},formatTooltip:function(t){var e=this.getData().getItemModel(t),i=e.get("name");if(i)return i;var n=e.get("fromName"),o=e.get("toName"),a=[];return null!=n&&a.push(n),null!=o&&a.push(o),ia(a.join(" > "))},preventIncremental:function(){return!!this.get("effect.show")},getProgressive:function(){var t=this.option.progressive;return null==t?this.option.large?1e4:this.get("progressive"):t},getProgressiveThreshold:function(){var t=this.option.progressiveThreshold;return null==t?this.option.large?2e4:this.get("progressiveThreshold"):t},defaultOption:{coordinateSystem:"geo",zlevel:0,z:2,legendHoverLink:!0,hoverAnimation:!0,xAxisIndex:0,yAxisIndex:0,symbol:["none","none"],symbolSize:[10,10],geoIndex:0,effect:{show:!1,period:4,constantSpeed:0,symbol:"circle",symbolSize:3,loop:!0,trailLength:.2},large:!1,largeThreshold:2e3,polyline:!1,label:{show:!1,position:"end"},lineStyle:{opacity:.5}}}),iP=xg.prototype;iP.createLine=function(t,e,i){return new rf(t,e,i)},iP._updateEffectSymbol=function(t,e){var i=t.getItemModel(e).getModel("effect"),n=i.get("symbolSize"),o=i.get("symbol");y(n)||(n=[n,n]);var a=i.get("color")||t.getItemVisual(e,"color"),r=this.childAt(1);this._symbolType!==o&&(this.remove(r),(r=Jl(o,-.5,-.5,1,1,a)).z2=100,r.culling=!0,this.add(r)),r&&(r.setStyle("shadowColor",a),r.setStyle(i.getItemStyle(["color"])),r.attr("scale",n),r.setColor(a),r.attr("scale",n),this._symbolType=o,this._updateEffectAnimation(t,i,e))},iP._updateEffectAnimation=function(t,e,i){var n=this.childAt(1);if(n){var o=this,a=t.getItemLayout(i),r=1e3*e.get("period"),s=e.get("loop"),l=e.get("constantSpeed"),u=T(e.get("delay"),function(e){return e/t.count()*r/3}),h="function"==typeof u;if(n.ignore=!0,this.updateAnimationPoints(n,a),l>0&&(r=this.getLineLength(n)/l*1e3),r!==this._period||s!==this._loop){n.stopAnimation();var c=u;h&&(c=u(i)),n.__t>0&&(c=-r*n.__t),n.__t=0;var d=n.animate("",s).when(r,{__t:1}).delay(c).during(function(){o.updateSymbolPosition(n)});s||d.done(function(){o.remove(n)}),d.start()}this._period=r,this._loop=s}},iP.getLineLength=function(t){return uw(t.__p1,t.__cp1)+uw(t.__cp1,t.__p2)},iP.updateAnimationPoints=function(t,e){t.__p1=e[0],t.__p2=e[1],t.__cp1=e[2]||[(e[0][0]+e[1][0])/2,(e[0][1]+e[1][1])/2]},iP.updateData=function(t,e,i){this.childAt(0).updateData(t,e,i),this._updateEffectSymbol(t,e)},iP.updateSymbolPosition=function(t){var e=t.__p1,i=t.__p2,n=t.__cp1,o=t.__t,a=t.position,r=sn,s=ln;a[0]=r(e[0],n[0],i[0],o),a[1]=r(e[1],n[1],i[1],o);var l=s(e[0],n[0],i[0],o),u=s(e[1],n[1],i[1],o);t.rotation=-Math.atan2(u,l)-Math.PI/2,t.ignore=!1},iP.updateLayout=function(t,e){this.childAt(0).updateLayout(t,e);var i=t.getItemModel(e).getModel("effect");this._updateEffectAnimation(t,i,e)},u(xg,tb);var nP=_g.prototype;nP._createPolyline=function(t,e,i){var n=t.getItemLayout(e),o=new gM({shape:{points:n}});this.add(o),this._updateCommonStl(t,e,i)},nP.updateData=function(t,e,i){var n=t.hostModel;Io(this.childAt(0),{shape:{points:t.getItemLayout(e)}},n,e),this._updateCommonStl(t,e,i)},nP._updateCommonStl=function(t,e,i){var n=this.childAt(0),o=t.getItemModel(e),a=t.getItemVisual(e,"color"),s=i&&i.lineStyle,l=i&&i.hoverLineStyle;i&&!t.hasItemOption||(s=o.getModel("lineStyle").getLineStyle(),l=o.getModel("emphasis.lineStyle").getLineStyle()),n.useStyle(r({strokeNoScale:!0,fill:"none",stroke:a},s)),n.hoverStyle=l,fo(this)},nP.updateLayout=function(t,e){this.childAt(0).setShape("points",t.getItemLayout(e))},u(_g,tb);var oP=wg.prototype;oP.createLine=function(t,e,i){return new _g(t,e,i)},oP.updateAnimationPoints=function(t,e){this._points=e;for(var i=[0],n=0,o=1;o<e.length;o++){var a=e[o-1],r=e[o];n+=uw(a,r),i.push(n)}if(0!==n){for(o=0;o<i.length;o++)i[o]/=n;this._offsets=i,this._length=n}},oP.getLineLength=function(t){return this._length},oP.updateSymbolPosition=function(t){var e=t.__t,i=this._points,n=this._offsets,o=i.length;if(n){var a=this._lastFrame;if(e<this._lastFramePercent){for(r=Math.min(a+1,o-1);r>=0&&!(n[r]<=e);r--);r=Math.min(r,o-2)}else{for(var r=a;r<o&&!(n[r]>e);r++);r=Math.min(r-1,o-2)}J(t.position,i[r],i[r+1],(e-n[r])/(n[r+1]-n[r]));var s=i[r+1][0]-i[r][0],l=i[r+1][1]-i[r][1];t.rotation=-Math.atan2(l,s)-Math.PI/2,this._lastFrame=r,this._lastFramePercent=e,t.ignore=!1}},u(wg,xg);var aP=Un({shape:{polyline:!1,curveness:0,segs:[]},buildPath:function(t,e){var i=e.segs,n=e.curveness;if(e.polyline)for(r=0;r<i.length;){var o=i[r++];if(o>0){t.moveTo(i[r++],i[r++]);for(var a=1;a<o;a++)t.lineTo(i[r++],i[r++])}}else for(var r=0;r<i.length;){var s=i[r++],l=i[r++],u=i[r++],h=i[r++];if(t.moveTo(s,l),n>0){var c=(s+u)/2-(l-h)*n,d=(l+h)/2-(u-s)*n;t.quadraticCurveTo(c,d,u,h)}else t.lineTo(u,h)}},findDataIndex:function(t,e){var i=this.shape,n=i.segs,o=i.curveness;if(i.polyline)for(var a=0,r=0;r<n.length;){var s=n[r++];if(s>0)for(var l=n[r++],u=n[r++],h=1;h<s;h++)if(yn(l,u,c=n[r++],d=n[r++]))return a;a++}else for(var a=0,r=0;r<n.length;){var l=n[r++],u=n[r++],c=n[r++],d=n[r++];if(o>0){if(_n(l,u,(l+c)/2-(u-d)*o,(u+d)/2-(c-l)*o,c,d))return a}else if(yn(l,u,c,d))return a;a++}return-1}}),rP=bg.prototype;rP.isPersistent=function(){return!this._incremental},rP.updateData=function(t){this.group.removeAll();var e=new aP({rectHover:!0,cursor:"default"});e.setShape({segs:t.getLayout("linesPoints")}),this._setCommon(e,t),this.group.add(e),this._incremental=null},rP.incrementalPrepareUpdate=function(t){this.group.removeAll(),this._clearIncremental(),t.count()>5e5?(this._incremental||(this._incremental=new Zn({silent:!0})),this.group.add(this._incremental)):this._incremental=null},rP.incrementalUpdate=function(t,e){var i=new aP;i.setShape({segs:e.getLayout("linesPoints")}),this._setCommon(i,e,!!this._incremental),this._incremental?this._incremental.addDisplayable(i,!0):(i.rectHover=!0,i.cursor="default",i.__startIndex=t.start,this.group.add(i))},rP.remove=function(){this._clearIncremental(),this._incremental=null,this.group.removeAll()},rP._setCommon=function(t,e,i){var n=e.hostModel;t.setShape({polyline:n.get("polyline"),curveness:n.get("lineStyle.curveness")}),t.useStyle(n.getModel("lineStyle").getLineStyle()),t.style.strokeNoScale=!0;var o=e.getVisual("color");o&&t.setStyle("stroke",o),t.setStyle("fill"),i||(t.seriesIndex=n.seriesIndex,t.on("mousemove",function(e){t.dataIndex=null;var i=t.findDataIndex(e.offsetX,e.offsetY);i>0&&(t.dataIndex=i+t.__startIndex)}))},rP._clearIncremental=function(){var t=this._incremental;t&&t.clearDisplaybles()};var sP={seriesType:"lines",plan:$I(),reset:function(t){var e=t.coordinateSystem,i=t.get("polyline"),n=t.pipelineContext.large;return{progress:function(o,a){var r=[];if(n){var s,l=o.end-o.start;if(i){for(var u=0,h=o.start;h<o.end;h++)u+=t.getLineCoordsCount(h);s=new Float32Array(l+2*u)}else s=new Float32Array(4*l);for(var c=0,d=[],h=o.start;h<o.end;h++){g=t.getLineCoords(h,r),i&&(s[c++]=g);for(var f=0;f<g;f++)d=e.dataToPoint(r[f],!1,d),s[c++]=d[0],s[c++]=d[1]}a.setLayout("linesPoints",s)}else for(h=o.start;h<o.end;h++){var p=a.getItemModel(h),g=t.getLineCoords(h,r),m=[];if(i)for(var v=0;v<g;v++)m.push(e.dataToPoint(r[v]));else{m[0]=e.dataToPoint(r[0]),m[1]=e.dataToPoint(r[1]);var y=p.get("lineStyle.curveness");+y&&(m[2]=[(m[0][0]+m[1][0])/2-(m[0][1]-m[1][1])*y,(m[0][1]+m[1][1])/2-(m[1][0]-m[0][0])*y])}a.setItemLayout(h,m)}}}}};Zs({type:"lines",init:function(){},render:function(t,e,i){var n=t.getData(),o=this._updateLineDraw(n,t),a=t.get("zlevel"),r=t.get("effect.trailLength"),s=i.getZr(),l="svg"===s.painter.getType();l||s.painter.getLayer(a).clear(!0),null==this._lastZlevel||l||s.configLayer(this._lastZlevel,{motionBlur:!1}),this._showEffect(t)&&r&&(l||s.configLayer(a,{motionBlur:!0,lastFrameAlpha:Math.max(Math.min(r/10+.9,1),0)})),o.updateData(n),this._lastZlevel=a,this._finished=!0},incrementalPrepareRender:function(t,e,i){var n=t.getData();this._updateLineDraw(n,t).incrementalPrepareUpdate(n),this._clearLayer(i),this._finished=!1},incrementalRender:function(t,e,i){this._lineDraw.incrementalUpdate(t,e.getData()),this._finished=t.end===e.getData().count()},updateTransform:function(t,e,i){var n=t.getData(),o=t.pipelineContext;if(!this._finished||o.large||o.progressiveRender)return{update:!0};var a=sP.reset(t);a.progress&&a.progress({start:0,end:n.count()},n),this._lineDraw.updateLayout(),this._clearLayer(i)},_updateLineDraw:function(t,e){var i=this._lineDraw,n=this._showEffect(e),o=!!e.get("polyline"),a=e.pipelineContext.large;return i&&n===this._hasEffet&&o===this._isPolyline&&a===this._isLargeDraw||(i&&i.remove(),i=this._lineDraw=a?new bg:new sf(o?n?wg:_g:n?xg:rf),this._hasEffet=n,this._isPolyline=o,this._isLargeDraw=a,this.group.removeAll()),this.group.add(i.group),i},_showEffect:function(t){return!!t.get("effect.show")},_clearLayer:function(t){var e=t.getZr();"svg"===e.painter.getType()||null==this._lastZlevel||e.painter.getLayer(this._lastZlevel).clear(!0)},remove:function(t,e){this._lineDraw&&this._lineDraw.remove(),this._lineDraw=null,this._clearLayer(e)},dispose:function(){}});var lP="lineStyle.opacity".split("."),uP={seriesType:"lines",reset:function(t,e,i){var n=Sg(t.get("symbol")),o=Sg(t.get("symbolSize")),a=t.getData();return a.setVisual("fromSymbol",n&&n[0]),a.setVisual("toSymbol",n&&n[1]),a.setVisual("fromSymbolSize",o&&o[0]),a.setVisual("toSymbolSize",o&&o[1]),a.setVisual("opacity",t.get(lP)),{dataEach:a.hasItemOption?function(t,e){var i=t.getItemModel(e),n=Sg(i.getShallow("symbol",!0)),o=Sg(i.getShallow("symbolSize",!0)),a=i.get(lP);n[0]&&t.setItemVisual(e,"fromSymbol",n[0]),n[1]&&t.setItemVisual(e,"toSymbol",n[1]),o[0]&&t.setItemVisual(e,"fromSymbolSize",o[0]),o[1]&&t.setItemVisual(e,"toSymbolSize",o[1]),t.setItemVisual(e,"opacity",a)}:null}}};zs(sP),Bs(uP),YI.extend({type:"series.heatmap",getInitialData:function(t,e){return ml(this.getSource(),this,{generateCoord:"value"})},preventIncremental:function(){var t=Fa.get(this.get("coordinateSystem"));if(t&&t.dimensions)return"lng"===t.dimensions[0]&&"lat"===t.dimensions[1]},defaultOption:{coordinateSystem:"cartesian2d",zlevel:0,z:2,geoIndex:0,blurSize:30,pointSize:20,maxOpacity:1,minOpacity:0}});Mg.prototype={update:function(t,e,i,n,o,a){var r=this._getBrush(),s=this._getGradient(t,o,"inRange"),l=this._getGradient(t,o,"outOfRange"),u=this.pointSize+this.blurSize,h=this.canvas,c=h.getContext("2d"),d=t.length;h.width=e,h.height=i;for(var f=0;f<d;++f){var p=t[f],g=p[0],m=p[1],v=n(p[2]);c.globalAlpha=v,c.drawImage(r,g-u,m-u)}if(!h.width||!h.height)return h;for(var y=c.getImageData(0,0,h.width,h.height),x=y.data,_=0,w=x.length,b=this.minOpacity,S=this.maxOpacity-b;_<w;){var v=x[_+3]/256,M=4*Math.floor(255*v);if(v>0){var I=a(v)?s:l;v>0&&(v=v*S+b),x[_++]=I[M],x[_++]=I[M+1],x[_++]=I[M+2],x[_++]=I[M+3]*v*256}else _+=4}return c.putImageData(y,0,0),h},_getBrush:function(){var t=this._brushCanvas||(this._brushCanvas=iw()),e=this.pointSize+this.blurSize,i=2*e;t.width=i,t.height=i;var n=t.getContext("2d");return n.clearRect(0,0,i,i),n.shadowOffsetX=i,n.shadowBlur=this.blurSize,n.shadowColor="#000",n.beginPath(),n.arc(-e,e,this.pointSize,0,2*Math.PI,!0),n.closePath(),n.fill(),t},_getGradient:function(t,e,i){for(var n=this._gradientPixels,o=n[i]||(n[i]=new Uint8ClampedArray(1024)),a=[0,0,0,0],r=0,s=0;s<256;s++)e[i](s/255,!0,a),o[r++]=a[0],o[r++]=a[1],o[r++]=a[2],o[r++]=a[3];return o}},Zs({type:"heatmap",render:function(t,e,i){var n;e.eachComponent("visualMap",function(e){e.eachTargetSeries(function(i){i===t&&(n=e)})}),this.group.removeAll(),this._incrementalDisplayable=null;var o=t.coordinateSystem;"cartesian2d"===o.type||"calendar"===o.type?this._renderOnCartesianAndCalendar(t,i,0,t.getData().count()):Ag(o)&&this._renderOnGeo(o,t,n,i)},incrementalPrepareRender:function(t,e,i){this.group.removeAll()},incrementalRender:function(t,e,i,n){e.coordinateSystem&&this._renderOnCartesianAndCalendar(e,n,t.start,t.end,!0)},_renderOnCartesianAndCalendar:function(t,e,i,n,o){var r,s,l=t.coordinateSystem;if("cartesian2d"===l.type){var u=l.getAxis("x"),h=l.getAxis("y");r=u.getBandWidth(),s=h.getBandWidth()}for(var c=this.group,d=t.getData(),f=t.getModel("itemStyle").getItemStyle(["color"]),p=t.getModel("emphasis.itemStyle").getItemStyle(),g=t.getModel("label"),m=t.getModel("emphasis.label"),v=l.type,y="cartesian2d"===v?[d.mapDimension("x"),d.mapDimension("y"),d.mapDimension("value")]:[d.mapDimension("time"),d.mapDimension("value")],x=i;x<n;x++){var _;if("cartesian2d"===v){if(isNaN(d.get(y[2],x)))continue;var w=l.dataToPoint([d.get(y[0],x),d.get(y[1],x)]);_=new yM({shape:{x:w[0]-r/2,y:w[1]-s/2,width:r,height:s},style:{fill:d.getItemVisual(x,"color"),opacity:d.getItemVisual(x,"opacity")}})}else{if(isNaN(d.get(y[1],x)))continue;_=new yM({z2:1,shape:l.dataToRect([d.get(y[0],x)]).contentShape,style:{fill:d.getItemVisual(x,"color"),opacity:d.getItemVisual(x,"opacity")}})}var b=d.getItemModel(x);d.hasItemOption&&(f=b.getModel("itemStyle").getItemStyle(["color"]),p=b.getModel("emphasis.itemStyle").getItemStyle(),g=b.getModel("label"),m=b.getModel("emphasis.label"));var S=t.getRawValue(x),M="-";S&&null!=S[2]&&(M=S[2]),go(f,p,g,m,{labelFetcher:t,labelDataIndex:x,defaultText:M,isRectText:!0}),_.setStyle(f),fo(_,d.hasItemOption?p:a({},p)),_.incremental=o,o&&(_.useHoverLayer=!0),c.add(_),d.setItemGraphicEl(x,_)}},_renderOnGeo:function(t,e,i,n){var o=i.targetVisuals.inRange,a=i.targetVisuals.outOfRange,r=e.getData(),s=this._hmLayer||this._hmLayer||new Mg;s.blurSize=e.get("blurSize"),s.pointSize=e.get("pointSize"),s.minOpacity=e.get("minOpacity"),s.maxOpacity=e.get("maxOpacity");var l=t.getViewRect().clone(),u=t.getRoamTransform();l.applyTransform(u);var h=Math.max(l.x,0),c=Math.max(l.y,0),d=Math.min(l.width+l.x,n.getWidth()),f=Math.min(l.height+l.y,n.getHeight()),p=d-h,g=f-c,m=[r.mapDimension("lng"),r.mapDimension("lat"),r.mapDimension("value")],v=r.mapArray(m,function(e,i,n){var o=t.dataToPoint([e,i]);return o[0]-=h,o[1]-=c,o.push(n),o}),y=i.getExtent(),x="visualMap.continuous"===i.type?Tg(y,i.option.range):Ig(y,i.getPieceList(),i.option.selected);s.update(v,p,g,o.color.getNormalizer(),{inRange:o.color.getColorMapper(),outOfRange:a.color.getColorMapper()},x);var _=new fi({style:{width:p,height:g,x:h,y:c,image:s.canvas},silent:!0});this.group.add(_)},dispose:function(){}});var hP=$D.extend({type:"series.pictorialBar",dependencies:["grid"],defaultOption:{symbol:"circle",symbolSize:null,symbolRotate:null,symbolPosition:null,symbolOffset:null,symbolMargin:null,symbolRepeat:!1,symbolRepeatDirection:"end",symbolClip:!1,symbolBoundingData:null,symbolPatternSize:400,barGap:"-100%",progressive:0,hoverAnimation:!1},getInitialData:function(t){return t.stack=null,hP.superApply(this,"getInitialData",arguments)}}),cP=["itemStyle","borderWidth"],dP=[{xy:"x",wh:"width",index:0,posDesc:["left","right"]},{xy:"y",wh:"height",index:1,posDesc:["top","bottom"]}],fP=new sM;Zs({type:"pictorialBar",render:function(t,e,i){var n=this.group,o=t.getData(),a=this._data,r=t.coordinateSystem,s=!!r.getBaseAxis().isHorizontal(),l=r.grid.getRect(),u={ecSize:{width:i.getWidth(),height:i.getHeight()},seriesModel:t,coordSys:r,coordSysExtent:[[l.x,l.x+l.width],[l.y,l.y+l.height]],isHorizontal:s,valueDim:dP[+s],categoryDim:dP[1-s]};return o.diff(a).add(function(t){if(o.hasValue(t)){var e=Vg(o,t),i=Dg(o,t,e,u),a=Hg(o,u,i);o.setItemGraphicEl(t,a),n.add(a),qg(a,u,i)}}).update(function(t,e){var i=a.getItemGraphicEl(e);if(o.hasValue(t)){var r=Vg(o,t),s=Dg(o,t,r,u),l=Xg(o,s);i&&l!==i.__pictorialShapeStr&&(n.remove(i),o.setItemGraphicEl(t,null),i=null),i?Zg(i,u,s):i=Hg(o,u,s,!0),o.setItemGraphicEl(t,i),i.__pictorialSymbolMeta=s,n.add(i),qg(i,u,s)}else n.remove(i)}).remove(function(t){var e=a.getItemGraphicEl(t);e&&Ug(a,t,e.__pictorialSymbolMeta.animationModel,e)}).execute(),this._data=o,this.group},dispose:B,remove:function(t,e){var i=this.group,n=this._data;t.get("animation")?n&&n.eachItemGraphicEl(function(e){Ug(n,e.dataIndex,t,e)}):i.removeAll()}});zs(v(El,"pictorialBar")),Bs(TD("pictorialBar","roundRect"));var pP=function(t,e,i,n,o){aD.call(this,t,e,i),this.type=n||"value",this.position=o||"bottom",this.orient=null};pP.prototype={constructor:pP,model:null,isHorizontal:function(){var t=this.position;return"top"===t||"bottom"===t},pointToData:function(t,e){return this.coordinateSystem.pointToData(t,e)[0]},toGlobalCoord:null,toLocalCoord:null},u(pP,aD),$g.prototype={type:"singleAxis",axisPointerEnabled:!0,constructor:$g,_init:function(t,e,i){var n=this.dimension,o=new pP(n,Hl(t),[0,0],t.get("type"),t.get("position")),a="category"===o.type;o.onBand=a&&t.get("boundaryGap"),o.inverse=t.get("inverse"),o.orient=t.get("orient"),t.axis=o,o.model=t,o.coordinateSystem=this,this._axis=o},update:function(t,e){t.eachSeries(function(t){if(t.coordinateSystem===this){var e=t.getData();d(e.mapDimension(this.dimension,!0),function(t){this._axis.scale.unionExtentFromData(e,t)},this),Wl(this._axis.scale,this._axis.model)}},this)},resize:function(t,e){this._rect=ca({left:t.get("left"),top:t.get("top"),right:t.get("right"),bottom:t.get("bottom"),width:t.get("width"),height:t.get("height")},{width:e.getWidth(),height:e.getHeight()}),this._adjustAxis()},getRect:function(){return this._rect},_adjustAxis:function(){var t=this._rect,e=this._axis,i=e.isHorizontal(),n=i?[0,t.width]:[0,t.height],o=e.reverse?1:0;e.setExtent(n[o],n[1-o]),this._updateAxisTransform(e,i?t.x:t.y)},_updateAxisTransform:function(t,e){var i=t.getExtent(),n=i[0]+i[1],o=t.isHorizontal();t.toGlobalCoord=o?function(t){return t+e}:function(t){return n-t+e},t.toLocalCoord=o?function(t){return t-e}:function(t){return n-t+e}},getAxis:function(){return this._axis},getBaseAxis:function(){return this._axis},getAxes:function(){return[this._axis]},getTooltipAxes:function(){return{baseAxes:[this.getAxis()]}},containPoint:function(t){var e=this.getRect(),i=this.getAxis();return"horizontal"===i.orient?i.contain(i.toLocalCoord(t[0]))&&t[1]>=e.y&&t[1]<=e.y+e.height:i.contain(i.toLocalCoord(t[1]))&&t[0]>=e.y&&t[0]<=e.y+e.height},pointToData:function(t){var e=this.getAxis();return[e.coordToData(e.toLocalCoord(t["horizontal"===e.orient?0:1]))]},dataToPoint:function(t){var e=this.getAxis(),i=this.getRect(),n=[],o="horizontal"===e.orient?0:1;return t instanceof Array&&(t=t[0]),n[o]=e.toGlobalCoord(e.dataToCoord(+t)),n[1-o]=0===o?i.y+i.height/2:i.x+i.width/2,n}},Fa.register("single",{create:function(t,e){var i=[];return t.eachComponent("singleAxis",function(n,o){var a=new $g(n,t,e);a.name="single_"+o,a.resize(n,e),n.coordinateSystem=a,i.push(a)}),t.eachSeries(function(e){if("singleAxis"===e.get("coordinateSystem")){var i=t.queryComponents({mainType:"singleAxis",index:e.get("singleAxisIndex"),id:e.get("singleAxisId")})[0];e.coordinateSystem=i&&i.coordinateSystem}}),i},dimensions:$g.prototype.dimensions});var gP=["axisLine","axisTickLabel","axisName"],mP=XD.extend({type:"singleAxis",axisPointerClass:"SingleAxisPointer",render:function(t,e,i,n){var o=this.group;o.removeAll();var a=Jg(t),r=new FD(t,a);d(gP,r.add,r),o.add(r.getGroup()),t.get("splitLine.show")&&this._splitLine(t),mP.superCall(this,"render",t,e,i,n)},_splitLine:function(t){var e=t.axis;if(!e.scale.isBlank()){var i=t.getModel("splitLine"),n=i.getModel("lineStyle"),o=n.get("width"),a=n.get("color");a=a instanceof Array?a:[a];for(var r=t.coordinateSystem.getRect(),s=e.isHorizontal(),l=[],u=0,h=e.getTicksCoords({tickModel:i}),c=[],d=[],f=0;f<h.length;++f){var p=e.toGlobalCoord(h[f].coord);s?(c[0]=p,c[1]=r.y,d[0]=p,d[1]=r.y+r.height):(c[0]=r.x,c[1]=p,d[0]=r.x+r.width,d[1]=p);var g=u++%a.length;l[g]=l[g]||[],l[g].push(new _M(Kn({shape:{x1:c[0],y1:c[1],x2:d[0],y2:d[1]},style:{lineWidth:o},silent:!0})))}for(f=0;f<l.length;++f)this.group.add(OM(l[f],{style:{stroke:a[f%a.length],lineDash:n.getLineDash(o),lineWidth:o},silent:!0}))}}}),vP=lI.extend({type:"singleAxis",layoutMode:"box",axis:null,coordinateSystem:null,getCoordSysModel:function(){return this}}),yP={left:"5%",top:"5%",right:"5%",bottom:"5%",type:"value",position:"bottom",orient:"horizontal",axisLine:{show:!0,lineStyle:{width:2,type:"solid"}},tooltip:{show:!0},axisTick:{show:!0,length:6,lineStyle:{width:2}},axisLabel:{show:!0,interval:"auto"},splitLine:{show:!0,lineStyle:{type:"dashed",opacity:.2}}};n(vP.prototype,UA),ED("single",vP,function(t,e){return e.type||(e.data?"category":"value")},yP);var xP=function(t,e){var i,n=[],o=t.seriesIndex;if(null==o||!(i=e.getSeriesByIndex(o)))return{point:[]};var a=i.getData(),r=zi(a,t);if(null==r||r<0||y(r))return{point:[]};var s=a.getItemGraphicEl(r),l=i.coordinateSystem;if(i.getTooltipPosition)n=i.getTooltipPosition(r)||[];else if(l&&l.dataToPoint)n=l.dataToPoint(a.getValues(f(l.dimensions,function(t){return a.mapDimension(t)}),r,!0))||[];else if(s){var u=s.getBoundingRect().clone();u.applyTransform(s.transform),n=[u.x+u.width/2,u.y+u.height/2]}return{point:n,el:s}},_P=d,wP=v,bP=Bi(),SP=(Fs({type:"axisPointer",coordSysAxesInfo:null,defaultOption:{show:"auto",triggerOn:null,zlevel:0,z:50,type:"line",snap:!1,triggerTooltip:!0,value:null,status:null,link:[],animation:null,animationDurationUpdate:200,lineStyle:{color:"#aaa",width:1,type:"solid"},shadowStyle:{color:"rgba(150,150,150,0.3)"},label:{show:!0,formatter:null,precision:"auto",margin:3,color:"#fff",padding:[5,7,5,7],backgroundColor:"auto",borderColor:null,borderWidth:0,shadowBlur:3,shadowColor:"#aaa"},handle:{show:!1,icon:"M10.7,11.9v-1.3H9.3v1.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4h1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z M13.3,24.4H6.7v-1.2h6.6z M13.3,22H6.7v-1.2h6.6z M13.3,19.6H6.7v-1.2h6.6z",size:45,margin:50,color:"#333",shadowBlur:3,shadowColor:"#aaa",shadowOffsetX:0,shadowOffsetY:2,throttle:40}}}),Bi()),MP=d,IP=Ws({type:"axisPointer",render:function(t,e,i){var n=e.getComponent("tooltip"),o=t.get("triggerOn")||n&&n.get("triggerOn")||"mousemove|click";um("axisPointer",i,function(t,e,i){"none"!==o&&("leave"===t||o.indexOf(t)>=0)&&i({type:"updateAxisPointer",currTrigger:t,x:e&&e.offsetX,y:e&&e.offsetY})})},remove:function(t,e){gm(e.getZr(),"axisPointer"),IP.superApply(this._model,"remove",arguments)},dispose:function(t,e){gm("axisPointer",e),IP.superApply(this._model,"dispose",arguments)}}),TP=Bi(),AP=i,DP=m;(mm.prototype={_group:null,_lastGraphicKey:null,_handle:null,_dragging:!1,_lastValue:null,_lastStatus:null,_payloadInfo:null,animationThreshold:15,render:function(t,e,i,n){var o=e.get("value"),a=e.get("status");if(this._axisModel=t,this._axisPointerModel=e,this._api=i,n||this._lastValue!==o||this._lastStatus!==a){this._lastValue=o,this._lastStatus=a;var r=this._group,s=this._handle;if(!a||"hide"===a)return r&&r.hide(),void(s&&s.hide());r&&r.show(),s&&s.show();var l={};this.makeElOption(l,o,t,e,i);var u=l.graphicKey;u!==this._lastGraphicKey&&this.clear(i),this._lastGraphicKey=u;var h=this._moveAnimation=this.determineAnimation(t,e);if(r){var c=v(vm,e,h);this.updatePointerEl(r,l,c,e),this.updateLabelEl(r,l,c,e)}else r=this._group=new tb,this.createPointerEl(r,l,t,e),this.createLabelEl(r,l,t,e),i.getZr().add(r);wm(r,e,!0),this._renderHandle(o)}},remove:function(t){this.clear(t)},dispose:function(t){this.clear(t)},determineAnimation:function(t,e){var i=e.get("animation"),n=t.axis,o="category"===n.type,a=e.get("snap");if(!a&&!o)return!1;if("auto"===i||null==i){var r=this.animationThreshold;if(o&&n.getBandWidth()>r)return!0;if(a){var s=Mh(t).seriesDataCount,l=n.getExtent();return Math.abs(l[0]-l[1])/s>r}return!1}return!0===i},makeElOption:function(t,e,i,n,o){},createPointerEl:function(t,e,i,n){var o=e.pointer;if(o){var a=TP(t).pointerEl=new zM[o.type](AP(e.pointer));t.add(a)}},createLabelEl:function(t,e,i,n){if(e.label){var o=TP(t).labelEl=new yM(AP(e.label));t.add(o),xm(o,n)}},updatePointerEl:function(t,e,i){var n=TP(t).pointerEl;n&&(n.setStyle(e.pointer.style),i(n,{shape:e.pointer.shape}))},updateLabelEl:function(t,e,i,n){var o=TP(t).labelEl;o&&(o.setStyle(e.label.style),i(o,{shape:e.label.shape,position:e.label.position}),xm(o,n))},_renderHandle:function(t){if(!this._dragging&&this.updateHandleTransform){var e=this._axisPointerModel,i=this._api.getZr(),n=this._handle,o=e.getModel("handle"),a=e.get("status");if(!o.get("show")||!a||"hide"===a)return n&&i.remove(n),void(this._handle=null);var r;this._handle||(r=!0,n=this._handle=Po(o.get("icon"),{cursor:"move",draggable:!0,onmousemove:function(t){mw(t.event)},onmousedown:DP(this._onHandleDragMove,this,0,0),drift:DP(this._onHandleDragMove,this),ondragend:DP(this._onHandleDragEnd,this)}),i.add(n)),wm(n,e,!1);var s=["color","borderColor","borderWidth","opacity","shadowColor","shadowBlur","shadowOffsetX","shadowOffsetY"];n.setStyle(o.getItemStyle(null,s));var l=o.get("size");y(l)||(l=[l,l]),n.attr("scale",[l[0]/2,l[1]/2]),Nr(this,"_doDispatchAxisPointer",o.get("throttle")||0,"fixRate"),this._moveHandleToValue(t,r)}},_moveHandleToValue:function(t,e){vm(this._axisPointerModel,!e&&this._moveAnimation,this._handle,_m(this.getHandleTransform(t,this._axisModel,this._axisPointerModel)))},_onHandleDragMove:function(t,e){var i=this._handle;if(i){this._dragging=!0;var n=this.updateHandleTransform(_m(i),[t,e],this._axisModel,this._axisPointerModel);this._payloadInfo=n,i.stopAnimation(),i.attr(_m(n)),TP(i).lastProp=null,this._doDispatchAxisPointer()}},_doDispatchAxisPointer:function(){if(this._handle){var t=this._payloadInfo,e=this._axisModel;this._api.dispatchAction({type:"updateAxisPointer",x:t.cursorPoint[0],y:t.cursorPoint[1],tooltipOption:t.tooltipOption,axesInfo:[{axisDim:e.axis.dim,axisIndex:e.componentIndex}]})}},_onHandleDragEnd:function(t){if(this._dragging=!1,this._handle){var e=this._axisPointerModel.get("value");this._moveHandleToValue(e),this._api.dispatchAction({type:"hideTip"})}},getHandleTransform:null,updateHandleTransform:null,clear:function(t){this._lastValue=null,this._lastStatus=null;var e=t.getZr(),i=this._group,n=this._handle;e&&i&&(this._lastGraphicKey=null,i&&e.remove(i),n&&e.remove(n),this._group=null,this._handle=null,this._payloadInfo=null)},doClear:function(){},buildLabel:function(t,e,i){return i=i||0,{x:t[i],y:t[1-i],width:e[i],height:e[1-i]}}}).constructor=mm,ji(mm);var CP=mm.extend({makeElOption:function(t,e,i,n,o){var a=i.axis,r=a.grid,s=n.get("type"),l=km(r,a).getOtherAxis(a).getGlobalExtent(),u=a.toGlobalCoord(a.dataToCoord(e,!0));if(s&&"none"!==s){var h=bm(n),c=LP[s](a,u,l,h);c.style=h,t.graphicKey=c.type,t.pointer=c}Am(e,t,Lh(r.model,i),i,n,o)},getHandleTransform:function(t,e,i){var n=Lh(e.axis.grid.model,e,{labelInside:!1});return n.labelMargin=i.get("handle.margin"),{position:Tm(e.axis,t,n),rotation:n.rotation+(n.labelDirection<0?Math.PI:0)}},updateHandleTransform:function(t,e,i,n){var o=i.axis,a=o.grid,r=o.getGlobalExtent(!0),s=km(a,o).getOtherAxis(o).getGlobalExtent(),l="x"===o.dim?0:1,u=t.position;u[l]+=e[l],u[l]=Math.min(r[1],u[l]),u[l]=Math.max(r[0],u[l]);var h=(s[1]+s[0])/2,c=[h,h];c[l]=u[l];var d=[{verticalAlign:"middle"},{align:"center"}];return{position:u,rotation:t.rotation,cursorPoint:c,tooltipOption:d[l]}}}),LP={line:function(t,e,i,n){var o=Dm([e,i[0]],[e,i[1]],Pm(t));return Kn({shape:o,style:n}),{type:"Line",shape:o}},shadow:function(t,e,i,n){var o=Math.max(1,t.getBandWidth()),a=i[1]-i[0];return{type:"Rect",shape:Cm([e-o/2,i[0]],[o,a],Pm(t))}}};XD.registerAxisPointerClass("CartesianAxisPointer",CP),Ns(function(t){if(t){(!t.axisPointer||0===t.axisPointer.length)&&(t.axisPointer={});var e=t.axisPointer.link;e&&!y(e)&&(t.axisPointer.link=[e])}}),Os(VT.PROCESSOR.STATISTIC,function(t,e){t.getComponent("axisPointer").coordSysAxesInfo=vh(t,e)}),Es({type:"updateAxisPointer",event:"updateAxisPointer",update:":updateAxisPointer"},function(t,e,i){var n=t.currTrigger,o=[t.x,t.y],a=t,r=t.dispatchAction||m(i.dispatchAction,i),s=e.getComponent("axisPointer").coordSysAxesInfo;if(s){lm(o)&&(o=xP({seriesIndex:a.seriesIndex,dataIndex:a.dataIndex},e).point);var l=lm(o),u=a.axesInfo,h=s.axesInfo,c="leave"===n||lm(o),d={},f={},p={list:[],map:{}},g={showPointer:wP(em,f),showTooltip:wP(im,p)};_P(s.coordSysMap,function(t,e){var i=l||t.containPoint(o);_P(s.coordSysAxesInfo[e],function(t,e){var n=t.axis,a=rm(u,t);if(!c&&i&&(!u||a)){var r=a&&a.value;null!=r||l||(r=n.pointToData(o)),null!=r&&Qg(t,r,g,!1,d)}})});var v={};return _P(h,function(t,e){var i=t.linkGroup;i&&!f[e]&&_P(i.axesInfo,function(e,n){var o=f[n];if(e!==t&&o){var a=o.value;i.mapper&&(a=t.axis.scale.parse(i.mapper(a,sm(e),sm(t)))),v[t.key]=a}})}),_P(v,function(t,e){Qg(h[e],t,g,!0,d)}),nm(f,h,d),om(p,o,t,r),am(h,0,i),d}});var kP=["x","y"],PP=["width","height"],NP=mm.extend({makeElOption:function(t,e,i,n,o){var a=i.axis,r=a.coordinateSystem,s=Om(r,1-Nm(a)),l=r.dataToPoint(e)[0],u=n.get("type");if(u&&"none"!==u){var h=bm(n),c=OP[u](a,l,s,h);c.style=h,t.graphicKey=c.type,t.pointer=c}Am(e,t,Jg(i),i,n,o)},getHandleTransform:function(t,e,i){var n=Jg(e,{labelInside:!1});return n.labelMargin=i.get("handle.margin"),{position:Tm(e.axis,t,n),rotation:n.rotation+(n.labelDirection<0?Math.PI:0)}},updateHandleTransform:function(t,e,i,n){var o=i.axis,a=o.coordinateSystem,r=Nm(o),s=Om(a,r),l=t.position;l[r]+=e[r],l[r]=Math.min(s[1],l[r]),l[r]=Math.max(s[0],l[r]);var u=Om(a,1-r),h=(u[1]+u[0])/2,c=[h,h];return c[r]=l[r],{position:l,rotation:t.rotation,cursorPoint:c,tooltipOption:{verticalAlign:"middle"}}}}),OP={line:function(t,e,i,n){var o=Dm([e,i[0]],[e,i[1]],Nm(t));return Kn({shape:o,style:n}),{type:"Line",shape:o}},shadow:function(t,e,i,n){var o=t.getBandWidth(),a=i[1]-i[0];return{type:"Rect",shape:Cm([e-o/2,i[0]],[o,a],Nm(t))}}};XD.registerAxisPointerClass("SingleAxisPointer",NP),Ws({type:"single"});var EP=YI.extend({type:"series.themeRiver",dependencies:["singleAxis"],nameMap:null,init:function(t){EP.superApply(this,"init",arguments),this.legendDataProvider=function(){return this.getRawData()}},fixData:function(t){var e=t.length,i=[];Zi(t,function(t){return t[2]}).buckets.each(function(t,e){i.push({name:e,dataList:t})});for(var n=i.length,o=-1,a=-1,r=0;r<n;++r){var s=i[r].dataList.length;s>o&&(o=s,a=r)}for(var l=0;l<n;++l)if(l!==a)for(var u=i[l].name,h=0;h<o;++h){for(var c=i[a].dataList[h][0],d=i[l].dataList.length,f=-1,p=0;p<d;++p)if(i[l].dataList[p][0]===c){f=p;break}-1===f&&(t[e]=[],t[e][0]=c,t[e][1]=0,t[e][2]=u,e++)}return t},getInitialData:function(t,e){for(var i=e.queryComponents({mainType:"singleAxis",index:this.get("singleAxisIndex"),id:this.get("singleAxisId")})[0].get("type"),n=g(t.data,function(t){return void 0!==t[2]}),o=this.fixData(n||[]),a=[],r=this.nameMap=R(),s=0,l=0;l<o.length;++l)a.push(o[l][2]),r.get(o[l][2])||(r.set(o[l][2],s),s++);var u=_A(o,{coordDimensions:["single"],dimensionsDefine:[{name:"time",type:qs(i)},{name:"value",type:"float"},{name:"name",type:"ordinal"}],encodeDefine:{single:0,value:1,itemName:2}}),h=new vA(u,this);return h.initData(o),h},getLayerSeries:function(){for(var t=this.getData(),e=t.count(),i=[],n=0;n<e;++n)i[n]=n;var o=t.mapDimension("single"),a=[];return Zi(i,function(e){return t.get("name",e)}).buckets.each(function(e,i){e.sort(function(e,i){return t.get(o,e)-t.get(o,i)}),a.push({name:i,indices:e})}),a},getAxisTooltipData:function(t,e,i){y(t)||(t=t?[t]:[]);for(var n,o=this.getData(),a=this.getLayerSeries(),r=[],s=a.length,l=0;l<s;++l){for(var u=Number.MAX_VALUE,h=-1,c=a[l].indices.length,d=0;d<c;++d){var f=o.get(t[0],a[l].indices[d]),p=Math.abs(f-e);p<=u&&(n=f,u=p,h=a[l].indices[d])}r.push(h)}return{dataIndices:r,nestestValue:n}},formatTooltip:function(t){var e=this.getData(),i=e.getName(t),n=e.get(e.mapDimension("value"),t);return(isNaN(n)||null==n)&&(n="-"),ia(i+" : "+n)},defaultOption:{zlevel:0,z:2,coordinateSystem:"singleAxis",boundaryGap:["10%","10%"],singleAxisIndex:0,animationEasing:"linear",label:{margin:4,show:!0,position:"left",color:"#000",fontSize:11},emphasis:{label:{show:!0}}}});Zs({type:"themeRiver",init:function(){this._layers=[]},render:function(t,e,i){function n(t){return t.name}function o(e,i,n){var o=this._layers;if("remove"!==e){for(var u,h=[],c=[],f=l[i].indices,p=0;p<f.length;p++){var g=r.getItemLayout(f[p]),m=g.x,v=g.y0,y=g.y;h.push([m,v]),c.push([m,v+y]),u=r.getItemVisual(f[p],"color")}var x,_,w=r.getItemLayout(f[0]),b=r.getItemModel(f[p-1]),S=b.getModel("label"),M=S.get("margin");if("add"===e){I=d[i]=new tb;x=new ID({shape:{points:h,stackedOnPoints:c,smooth:.4,stackedOnSmooth:.4,smoothConstraint:!1},z2:0}),_=new rM({style:{x:w.x-M,y:w.y0+w.y/2}}),I.add(x),I.add(_),s.add(I),x.setClipPath(Em(x.getBoundingRect(),t,function(){x.removeClipPath()}))}else{var I=o[n];x=I.childAt(0),_=I.childAt(1),s.add(I),d[i]=I,Io(x,{shape:{points:h,stackedOnPoints:c}},t),Io(_,{style:{x:w.x-M,y:w.y0+w.y/2}},t)}var T=b.getModel("emphasis.itemStyle"),A=b.getModel("itemStyle");mo(_.style,S,{text:S.get("show")?t.getFormattedLabel(f[p-1],"normal")||r.getName(f[p-1]):null,textVerticalAlign:"middle"}),x.setStyle(a({fill:u},A.getItemStyle(["color"]))),fo(x,T.getItemStyle())}else s.remove(o[i])}var r=t.getData(),s=this.group,l=t.getLayerSeries(),u=r.getLayout("layoutInfo"),h=u.rect,c=u.boundaryGap;s.attr("position",[0,h.y+c[0]]);var d={};new Xs(this._layersSeries||[],l,n,n).add(m(o,this,"add")).update(m(o,this,"update")).remove(m(o,this,"remove")).execute(),this._layersSeries=l,this._layers=d},dispose:function(){}});zs(function(t,e){t.eachSeriesByType("themeRiver",function(t){var e=t.getData(),i=t.coordinateSystem,n={},o=i.getRect();n.rect=o;var a=t.get("boundaryGap"),r=i.getAxis();n.boundaryGap=a,"horizontal"===r.orient?(a[0]=Vo(a[0],o.height),a[1]=Vo(a[1],o.height),Rm(e,t,o.height-a[0]-a[1])):(a[0]=Vo(a[0],o.width),a[1]=Vo(a[1],o.width),Rm(e,t,o.width-a[0]-a[1])),e.setLayout("layoutInfo",n)})}),Bs(function(t){t.eachSeriesByType("themeRiver",function(t){var e=t.getData(),i=t.getRawData(),n=t.get("color"),o=R();e.each(function(t){o.set(e.getRawIndex(t),t)}),i.each(function(a){var r=i.getName(a),s=n[(t.nameMap.get(r)-1)%n.length];i.setItemVisual(a,"color",s);var l=o.get(a);null!=l&&e.setItemVisual(l,"color",s)})})}),Os(fC("themeRiver")),YI.extend({type:"series.sunburst",_viewRoot:null,getInitialData:function(t,e){var i={name:t.name,children:t.data};Bm(i);var n=t.levels||[],o={};return o.levels=n,Vc.createTree(i,this,o).data},optionUpdated:function(){this.resetViewRoot()},getDataParams:function(t){var e=YI.prototype.getDataParams.apply(this,arguments),i=this.getData().tree.getNodeByDataIndex(t);return e.treePathInfo=cd(i,this),e},defaultOption:{zlevel:0,z:2,center:["50%","50%"],radius:[0,"75%"],clockwise:!0,startAngle:90,minAngle:0,percentPrecision:2,stillShowZeroSum:!0,highlightPolicy:"descendant",nodeClick:"rootToNode",renderLabelForZeroData:!1,label:{rotate:"radial",show:!0,opacity:1,align:"center",position:"inside",distance:5,silent:!0,emphasis:{}},itemStyle:{borderWidth:1,borderColor:"white",borderType:"solid",shadowBlur:0,shadowColor:"rgba(0, 0, 0, 0.2)",shadowOffsetX:0,shadowOffsetY:0,opacity:1,emphasis:{},highlight:{opacity:1},downplay:{opacity:.9}},animationType:"expansion",animationDuration:1e3,animationDurationUpdate:500,animationEasing:"cubicOut",data:[],levels:[],sort:"desc"},getViewRoot:function(){return this._viewRoot},resetViewRoot:function(t){t?this._viewRoot=t:t=this._viewRoot;var e=this.getRawData().tree.root;t&&(t===e||e.contains(t))||(this._viewRoot=e)}});var RP={NONE:"none",DESCENDANT:"descendant",ANCESTOR:"ancestor",SELF:"self"},zP=2,BP=4,VP=Vm.prototype;VP.updateData=function(t,e,i,o,s){this.node=e,e.piece=this,o=o||this._seriesModel,s=s||this._ecModel;var l=this.childAt(0);l.dataIndex=e.dataIndex;var u=e.getModel(),h=e.getLayout(),c=a({},h);c.label=null;var d=Gm(e,0,s);Hm(e,o,d);var f,p=u.getModel("itemStyle").getItemStyle();f=r({lineJoin:"bevel",fill:(f="normal"===i?p:n(u.getModel(i+".itemStyle").getItemStyle(),p)).fill||d},f),t?(l.setShape(c),l.shape.r=h.r0,Io(l,{shape:{r:h.r}},o,e.dataIndex),l.useStyle(f)):"object"==typeof f.fill&&f.fill.type||"object"==typeof l.style.fill&&l.style.fill.type?(Io(l,{shape:c},o),l.useStyle(f)):Io(l,{shape:c,style:f},o),this._updateLabel(o,d,i);var g=u.getShallow("cursor");if(g&&l.attr("cursor",g),t){var m=o.getShallow("highlightPolicy");this._initEvents(l,e,o,m)}this._seriesModel=o||this._seriesModel,this._ecModel=s||this._ecModel},VP.onEmphasis=function(t){var e=this;this.node.hostTree.root.eachNode(function(i){i.piece&&(e.node===i?i.piece.updateData(!1,i,"emphasis"):Wm(i,e.node,t)?i.piece.childAt(0).trigger("highlight"):t!==RP.NONE&&i.piece.childAt(0).trigger("downplay"))})},VP.onNormal=function(){this.node.hostTree.root.eachNode(function(t){t.piece&&t.piece.updateData(!1,t,"normal")})},VP.onHighlight=function(){this.updateData(!1,this.node,"highlight")},VP.onDownplay=function(){this.updateData(!1,this.node,"downplay")},VP._updateLabel=function(t,e,i){function n(t){var e=r.get(t);return null==e?a.get(t):e}var o=this.node.getModel(),a=o.getModel("label"),r="normal"===i||"emphasis"===i?a:o.getModel(i+".label"),s=o.getModel("emphasis.label"),l=T(t.getFormattedLabel(this.node.dataIndex,"normal",null,null,"label"),this.node.name);!1===n("show")&&(l="");var u=this.node.getLayout(),h=r.get("minAngle");null==h&&(h=a.get("minAngle")),h=h/180*Math.PI;var c=u.endAngle-u.startAngle;null!=h&&Math.abs(c)<h&&(l="");var d=this.childAt(1);go(d.style,d.hoverStyle||{},a,s,{defaultText:r.getShallow("show")?l:null,autoColor:e,useInsideStyle:!0});var f,p=(u.startAngle+u.endAngle)/2,g=Math.cos(p),m=Math.sin(p),v=n("position"),y=n("distance")||0,x=n("align");"outside"===v?(f=u.r+y,x=p>Math.PI/2?"right":"left"):x&&"center"!==x?"left"===x?(f=u.r0+y,p>Math.PI/2&&(x="right")):"right"===x&&(f=u.r-y,p>Math.PI/2&&(x="left")):(f=(u.r+u.r0)/2,x="center"),d.attr("style",{text:l,textAlign:x,textVerticalAlign:n("verticalAlign")||"middle",opacity:n("opacity")});var _=f*g+u.cx,w=f*m+u.cy;d.attr("position",[_,w]);var b=n("rotate"),S=0;"radial"===b?(S=-p)<-Math.PI/2&&(S+=Math.PI):"tangential"===b?(S=Math.PI/2-p)>Math.PI/2?S-=Math.PI:S<-Math.PI/2&&(S+=Math.PI):"number"==typeof b&&(S=b*Math.PI/180),d.attr("rotation",S)},VP._initEvents=function(t,e,i,n){t.off("mouseover").off("mouseout").off("emphasis").off("normal");var o=this,a=function(){o.onEmphasis(n)},r=function(){o.onNormal()};i.isAnimationEnabled()&&t.on("mouseover",a).on("mouseout",r).on("emphasis",a).on("normal",r).on("downplay",function(){o.onDownplay()}).on("highlight",function(){o.onHighlight()})},u(Vm,tb);Ar.extend({type:"sunburst",init:function(){},render:function(t,e,i,n){function o(i,n){if(c||!i||i.getValue()||(i=null),i!==l&&n!==l)if(n&&n.piece)i?(n.piece.updateData(!1,i,"normal",t,e),s.setItemGraphicEl(i.dataIndex,n.piece)):a(n);else if(i){var o=new Vm(i,t,e);h.add(o),s.setItemGraphicEl(i.dataIndex,o)}}function a(t){t&&t.piece&&(h.remove(t.piece),t.piece=null)}var r=this;this.seriesModel=t,this.api=i,this.ecModel=e;var s=t.getData(),l=s.tree.root,u=t.getViewRoot(),h=this.group,c=t.get("renderLabelForZeroData"),d=[];u.eachNode(function(t){d.push(t)});var f=this._oldChildren||[];if(function(t,e){function i(t){return t.getId()}function n(i,n){o(null==i?null:t[i],null==n?null:e[n])}0===t.length&&0===e.length||new Xs(e,t,i,i).add(n).update(n).remove(v(n,null)).execute()}(d,f),function(i,n){if(n.depth>0){r.virtualPiece?r.virtualPiece.updateData(!1,i,"normal",t,e):(r.virtualPiece=new Vm(i,t,e),h.add(r.virtualPiece)),n.piece._onclickEvent&&n.piece.off("click",n.piece._onclickEvent);var o=function(t){r._rootToNode(n.parentNode)};n.piece._onclickEvent=o,r.virtualPiece.on("click",o)}else r.virtualPiece&&(h.remove(r.virtualPiece),r.virtualPiece=null)}(l,u),n&&n.highlight&&n.highlight.piece){var p=t.getShallow("highlightPolicy");n.highlight.piece.onEmphasis(p)}else if(n&&n.unhighlight){var g=this.virtualPiece;!g&&l.children.length&&(g=l.children[0].piece),g&&g.onNormal()}this._initEvents(),this._oldChildren=d},dispose:function(){},_initEvents:function(){var t=this,e=function(e){var i=!1;t.seriesModel.getViewRoot().eachNode(function(n){if(!i&&n.piece&&n.piece.childAt(0)===e.target){var o=n.getModel().get("nodeClick");if("rootToNode"===o)t._rootToNode(n);else if("link"===o){var a=n.getModel(),r=a.get("link");if(r){var s=a.get("target",!0)||"_blank";window.open(r,s)}}i=!0}})};this.group._onclickEvent&&this.group.off("click",this.group._onclickEvent),this.group.on("click",e),this.group._onclickEvent=e},_rootToNode:function(t){t!==this.seriesModel.getViewRoot()&&this.api.dispatchAction({type:"sunburstRootToNode",from:this.uid,seriesId:this.seriesModel.id,targetNode:t})},containPoint:function(t,e){var i=e.getData().getItemLayout(0);if(i){var n=t[0]-i.cx,o=t[1]-i.cy,a=Math.sqrt(n*n+o*o);return a<=i.r&&a>=i.r0}}});var GP="sunburstRootToNode";Es({type:GP,update:"updateView"},function(t,e){e.eachComponent({mainType:"series",subType:"sunburst",query:t},function(e,i){var n=ld(t,[GP],e);if(n){var o=e.getViewRoot();o&&(t.direction=hd(o,n.node)?"rollUp":"drillDown"),e.resetViewRoot(n.node)}})});var FP="sunburstHighlight";Es({type:FP,update:"updateView"},function(t,e){e.eachComponent({mainType:"series",subType:"sunburst",query:t},function(e,i){var n=ld(t,[FP],e);n&&(t.highlight=n.node)})});Es({type:"sunburstUnhighlight",update:"updateView"},function(t,e){e.eachComponent({mainType:"series",subType:"sunburst",query:t},function(e,i){t.unhighlight=!0})});var WP=Math.PI/180;Bs(v(uC,"sunburst")),zs(v(function(t,e,i,n){e.eachSeriesByType(t,function(t){var e=t.get("center"),n=t.get("radius");y(n)||(n=[0,n]),y(e)||(e=[e,e]);var o=i.getWidth(),a=i.getHeight(),r=Math.min(o,a),s=Vo(e[0],o),l=Vo(e[1],a),u=Vo(n[0],r/2),h=Vo(n[1],r/2),c=-t.get("startAngle")*WP,f=t.get("minAngle")*WP,p=t.getData().tree.root,g=t.getViewRoot(),m=g.depth,v=t.get("sort");null!=v&&Zm(g,v);var x=0;d(g.children,function(t){!isNaN(t.getValue())&&x++});var _=g.getValue(),w=Math.PI/(_||x)*2,b=g.depth>0,S=g.height-(b?-1:1),M=(h-u)/(S||1),I=t.get("clockwise"),T=t.get("stillShowZeroSum"),A=I?1:-1,D=function(t,e){if(t){var i=e;if(t!==p){var n=t.getValue(),o=0===_&&T?w:n*w;o<f&&(o=f),i=e+A*o;var a=t.depth-m-(b?-1:1),h=u+M*a,c=u+M*(a+1),g=t.getModel();null!=g.get("r0")&&(h=Vo(g.get("r0"),r/2)),null!=g.get("r")&&(c=Vo(g.get("r"),r/2)),t.setLayout({angle:o,startAngle:e,endAngle:i,clockwise:I,cx:s,cy:l,r0:h,r:c})}if(t.children&&t.children.length){var v=0;d(t.children,function(t){v+=D(t,e+v)})}return i-e}};if(b){var C=u,L=u+M,k=2*Math.PI;p.setLayout({angle:k,startAngle:c,endAngle:c+k,clockwise:I,cx:s,cy:l,r0:C,r:L})}D(g,c)})},"sunburst")),Os(v(fC,"sunburst"));var HP=["itemStyle"],ZP=["emphasis","itemStyle"],UP=["label"],XP=["emphasis","label"],jP="e\0\0",YP={cartesian2d:function(t){var e=t.grid.getRect();return{coordSys:{type:"cartesian2d",x:e.x,y:e.y,width:e.width,height:e.height},api:{coord:function(e){return t.dataToPoint(e)},size:m(Xm,t)}}},geo:function(t){var e=t.getBoundingRect();return{coordSys:{type:"geo",x:e.x,y:e.y,width:e.width,height:e.height,zoom:t.getZoom()},api:{coord:function(e){return t.dataToPoint(e)},size:m(jm,t)}}},singleAxis:function(t){var e=t.getRect();return{coordSys:{type:"singleAxis",x:e.x,y:e.y,width:e.width,height:e.height},api:{coord:function(e){return t.dataToPoint(e)},size:m(Ym,t)}}},polar:function(t){var e=t.getRadiusAxis(),i=t.getAngleAxis(),n=e.getExtent();return n[0]>n[1]&&n.reverse(),{coordSys:{type:"polar",cx:t.cx,cy:t.cy,r:n[1],r0:n[0]},api:{coord:m(function(n){var o=e.dataToRadius(n[0]),a=i.dataToAngle(n[1]),r=t.coordToPoint([o,a]);return r.push(o,a*Math.PI/180),r}),size:m(qm,t)}}},calendar:function(t){var e=t.getRect(),i=t.getRangeInfo();return{coordSys:{type:"calendar",x:e.x,y:e.y,width:e.width,height:e.height,cellWidth:t.getCellWidth(),cellHeight:t.getCellHeight(),rangeInfo:{start:i.start,end:i.end,weeks:i.weeks,dayCount:i.allDay}},api:{coord:function(e,i){return t.dataToPoint(e,i)}}}}};YI.extend({type:"series.custom",dependencies:["grid","polar","geo","singleAxis","calendar"],defaultOption:{coordinateSystem:"cartesian2d",zlevel:0,z:2,legendHoverLink:!0,useTransform:!0},getInitialData:function(t,e){return ml(this.getSource(),this)},getDataParams:function(t,e,i){var n=YI.prototype.getDataParams.apply(this,arguments);return i&&(n.info=i.info),n}}),Ar.extend({type:"custom",_data:null,render:function(t,e,i,n){var o=this._data,a=t.getData(),r=this.group,s=Qm(t,a,e,i);a.diff(o).add(function(e){ev(null,e,s(e,n),t,r,a)}).update(function(e,i){ev(o.getItemGraphicEl(i),e,s(e,n),t,r,a)}).remove(function(t){var e=o.getItemGraphicEl(t);e&&r.remove(e)}).execute(),this._data=a},incrementalPrepareRender:function(t,e,i){this.group.removeAll(),this._data=null},incrementalRender:function(t,e,i,n,o){for(var a=e.getData(),r=Qm(e,a,i,n),s=t.start;s<t.end;s++)ev(null,s,r(s,o),e,this.group,a).traverse(function(t){t.isGroup||(t.incremental=!0,t.useHoverLayer=!0)})},dispose:B,filterForExposedEvent:function(t,e,i,n){var o=e.element;if(null==o||i.name===o)return!0;for(;(i=i.parent)&&i!==this.group;)if(i.name===o)return!0;return!1}}),Ns(function(t){var e=t.graphic;y(e)?e[0]&&e[0].elements?t.graphic=[t.graphic[0]]:t.graphic=[{elements:e}]:e&&!e.elements&&(t.graphic=[{elements:[e]}])});var qP=Fs({type:"graphic",defaultOption:{elements:[],parentId:null},_elOptionsToUpdate:null,mergeOption:function(t){var e=this.option.elements;this.option.elements=null,qP.superApply(this,"mergeOption",arguments),this.option.elements=e},optionUpdated:function(t,e){var i=this.option,n=(e?i:t).elements,o=i.elements=e?[]:i.elements,a=[];this._flatten(n,a);var r=Pi(o,a);Ni(r);var s=this._elOptionsToUpdate=[];d(r,function(t,e){var i=t.option;i&&(s.push(i),gv(t,i),mv(o,e,i),vv(o[e],i))},this);for(var l=o.length-1;l>=0;l--)null==o[l]?o.splice(l,1):delete o[l].$action},_flatten:function(t,e,i){d(t,function(t){if(t){i&&(t.parentOption=i),e.push(t);var n=t.children;"group"===t.type&&n&&this._flatten(n,e,t),delete t.children}},this)},useElOptionsToUpdate:function(){var t=this._elOptionsToUpdate;return this._elOptionsToUpdate=null,t}});Ws({type:"graphic",init:function(t,e){this._elMap=R(),this._lastGraphicModel},render:function(t,e,i){t!==this._lastGraphicModel&&this._clear(),this._lastGraphicModel=t,this._updateElements(t),this._relocate(t,i)},_updateElements:function(t){var e=t.useElOptionsToUpdate();if(e){var i=this._elMap,n=this.group;d(e,function(e){var o=e.$action,a=e.id,r=i.get(a),s=e.parentId,l=null!=s?i.get(s):n,u=e.style;"text"===e.type&&u&&(e.hv&&e.hv[1]&&(u.textVerticalAlign=u.textBaseline=null),!u.hasOwnProperty("textFill")&&u.fill&&(u.textFill=u.fill),!u.hasOwnProperty("textStroke")&&u.stroke&&(u.textStroke=u.stroke));var h=fv(e);o&&"merge"!==o?"replace"===o?(dv(r,i),cv(a,l,h,i)):"remove"===o&&dv(r,i):r?r.attr(h):cv(a,l,h,i);var c=i.get(a);c&&(c.__ecGraphicWidth=e.width,c.__ecGraphicHeight=e.height,yv(c,t))})}},_relocate:function(t,e){for(var i=t.option.elements,n=this.group,o=this._elMap,a=i.length-1;a>=0;a--){var r=i[a],s=o.get(r.id);if(s){var l=s.parent;da(s,r,l===n?{width:e.getWidth(),height:e.getHeight()}:{width:l.__ecGraphicWidth||0,height:l.__ecGraphicHeight||0},null,{hv:r.hv,boundingMode:r.bounding})}}},_clear:function(){var t=this._elMap;t.each(function(e){dv(e,t)}),this._elMap=R()},dispose:function(){this._clear()}});var KP=Fs({type:"legend.plain",dependencies:["series"],layoutMode:{type:"box",ignoreSize:!0},init:function(t,e,i){this.mergeDefaultAndTheme(t,i),t.selected=t.selected||{}},mergeOption:function(t){KP.superCall(this,"mergeOption",t)},optionUpdated:function(){this._updateData(this.ecModel);var t=this._data;if(t[0]&&"single"===this.get("selectedMode")){for(var e=!1,i=0;i<t.length;i++){var n=t[i].get("name");if(this.isSelected(n)){this.select(n),e=!0;break}}!e&&this.select(t[0].get("name"))}},_updateData:function(t){var e=[],i=[];t.eachRawSeries(function(n){var o=n.name;i.push(o);var a;if(n.legendDataProvider){var r=n.legendDataProvider(),s=r.mapArray(r.getName);t.isSeriesFiltered(n)||(i=i.concat(s)),s.length?e=e.concat(s):a=!0}else a=!0;a&&Oi(n)&&e.push(n.name)}),this._availableNames=i;var n=f(this.get("data")||e,function(t){return"string"!=typeof t&&"number"!=typeof t||(t={name:t}),new No(t,this,this.ecModel)},this);this._data=n},getData:function(){return this._data},select:function(t){var e=this.option.selected;"single"===this.get("selectedMode")&&d(this._data,function(t){e[t.get("name")]=!1}),e[t]=!0},unSelect:function(t){"single"!==this.get("selectedMode")&&(this.option.selected[t]=!1)},toggleSelected:function(t){var e=this.option.selected;e.hasOwnProperty(t)||(e[t]=!0),this[e[t]?"unSelect":"select"](t)},isSelected:function(t){var e=this.option.selected;return!(e.hasOwnProperty(t)&&!e[t])&&l(this._availableNames,t)>=0},defaultOption:{zlevel:0,z:4,show:!0,orient:"horizontal",left:"center",top:0,align:"auto",backgroundColor:"rgba(0,0,0,0)",borderColor:"#ccc",borderRadius:0,borderWidth:0,padding:5,itemGap:10,itemWidth:25,itemHeight:14,inactiveColor:"#ccc",textStyle:{color:"#333"},selectedMode:!0,tooltip:{show:!1}}});Es("legendToggleSelect","legendselectchanged",v(xv,"toggleSelected")),Es("legendSelect","legendselected",v(xv,"select")),Es("legendUnSelect","legendunselected",v(xv,"unSelect"));var $P=v,JP=d,QP=tb,tN=Ws({type:"legend.plain",newlineDisabled:!1,init:function(){this.group.add(this._contentGroup=new QP),this._backgroundEl,this._isFirstRender=!0},getContentGroup:function(){return this._contentGroup},render:function(t,e,i){var n=this._isFirstRender;if(this._isFirstRender=!1,this.resetInner(),t.get("show",!0)){var o=t.get("align");o&&"auto"!==o||(o="right"===t.get("left")&&"vertical"===t.get("orient")?"right":"left"),this.renderInner(o,t,e,i);var a=t.getBoxLayoutParams(),s={width:i.getWidth(),height:i.getHeight()},l=t.get("padding"),u=ca(a,s,l),h=this.layoutInner(t,o,u,n),c=ca(r({width:h.width,height:h.height},a),s,l);this.group.attr("position",[c.x-h.x,c.y-h.y]),this.group.add(this._backgroundEl=wv(h,t))}},resetInner:function(){this.getContentGroup().removeAll(),this._backgroundEl&&this.group.remove(this._backgroundEl)},renderInner:function(t,e,i,n){var o=this.getContentGroup(),a=R(),r=e.get("selectedMode"),s=[];i.eachRawSeries(function(t){!t.get("legendHoverLink")&&s.push(t.id)}),JP(e.getData(),function(l,u){var h=l.get("name");if(this.newlineDisabled||""!==h&&"\n"!==h){var c=i.getSeriesByName(h)[0];if(!a.get(h))if(c){var d=c.getData(),f=d.getVisual("color");"function"==typeof f&&(f=f(c.getDataParams(0)));var p=d.getVisual("legendSymbol")||"roundRect",g=d.getVisual("symbol");this._createItem(h,u,l,e,p,g,t,f,r).on("click",$P(bv,h,n)).on("mouseover",$P(Sv,c.name,null,n,s)).on("mouseout",$P(Mv,c.name,null,n,s)),a.set(h,!0)}else i.eachRawSeries(function(i){if(!a.get(h)&&i.legendDataProvider){var o=i.legendDataProvider(),c=o.indexOfName(h);if(c<0)return;var d=o.getItemVisual(c,"color");this._createItem(h,u,l,e,"roundRect",null,t,d,r).on("click",$P(bv,h,n)).on("mouseover",$P(Sv,null,h,n,s)).on("mouseout",$P(Mv,null,h,n,s)),a.set(h,!0)}},this)}else o.add(new QP({newline:!0}))},this)},_createItem:function(t,e,i,n,o,r,s,l,u){var h=n.get("itemWidth"),c=n.get("itemHeight"),d=n.get("inactiveColor"),f=n.get("symbolKeepAspect"),p=n.isSelected(t),g=new QP,m=i.getModel("textStyle"),v=i.get("icon"),y=i.getModel("tooltip"),x=y.parentModel;if(o=v||o,g.add(Jl(o,0,0,h,c,p?l:d,null==f||f)),!v&&r&&(r!==o||"none"===r)){var _=.8*c;"none"===r&&(r="circle"),g.add(Jl(r,(h-_)/2,(c-_)/2,_,_,p?l:d,null==f||f))}var w="left"===s?h+5:-5,b=s,S=n.get("formatter"),M=t;"string"==typeof S&&S?M=S.replace("{name}",null!=t?t:""):"function"==typeof S&&(M=S(t)),g.add(new rM({style:mo({},m,{text:M,x:w,y:c/2,textFill:p?m.getTextColor():d,textAlign:b,textVerticalAlign:"middle"})}));var I=new yM({shape:g.getBoundingRect(),invisible:!0,tooltip:y.get("show")?a({content:t,formatter:x.get("formatter",!0)||function(){return t},formatterParams:{componentType:"legend",legendIndex:n.componentIndex,name:t,$vars:["name"]}},y.option):null});return g.add(I),g.eachChild(function(t){t.silent=!0}),I.silent=!u,this.getContentGroup().add(g),fo(g),g.__legendDataIndex=e,g},layoutInner:function(t,e,i){var n=this.getContentGroup();aI(t.get("orient"),n,t.get("itemGap"),i.width,i.height);var o=n.getBoundingRect();return n.attr("position",[-o.x,-o.y]),this.group.getBoundingRect()},remove:function(){this.getContentGroup().removeAll(),this._isFirstRender=!0}});Os(function(t){var e=t.findComponents({mainType:"legend"});e&&e.length&&t.filterSeries(function(t){for(var i=0;i<e.length;i++)if(!e[i].isSelected(t.name))return!1;return!0})}),lI.registerSubTypeDefaulter("legend",function(){return"plain"});var eN=KP.extend({type:"legend.scroll",setScrollDataIndex:function(t){this.option.scrollDataIndex=t},defaultOption:{scrollDataIndex:0,pageButtonItemGap:5,pageButtonGap:null,pageButtonPosition:"end",pageFormatter:"{current}/{total}",pageIcons:{horizontal:["M0,0L12,-10L12,10z","M0,0L-12,-10L-12,10z"],vertical:["M0,0L20,0L10,-20z","M0,0L20,0L10,20z"]},pageIconColor:"#2f4554",pageIconInactiveColor:"#aaa",pageIconSize:15,pageTextStyle:{color:"#333"},animationDurationUpdate:800},init:function(t,e,i,n){var o=ga(t);eN.superCall(this,"init",t,e,i,n),Iv(this,t,o)},mergeOption:function(t,e){eN.superCall(this,"mergeOption",t,e),Iv(this,this.option,t)},getOrient:function(){return"vertical"===this.get("orient")?{index:1,name:"vertical"}:{index:0,name:"horizontal"}}}),iN=tb,nN=["width","height"],oN=["x","y"],aN=tN.extend({type:"legend.scroll",newlineDisabled:!0,init:function(){aN.superCall(this,"init"),this._currentIndex=0,this.group.add(this._containerGroup=new iN),this._containerGroup.add(this.getContentGroup()),this.group.add(this._controllerGroup=new iN),this._showController},resetInner:function(){aN.superCall(this,"resetInner"),this._controllerGroup.removeAll(),this._containerGroup.removeClipPath(),this._containerGroup.__rectSize=null},renderInner:function(t,e,i,n){function o(t,i){var o=t+"DataIndex",l=Po(e.get("pageIcons",!0)[e.getOrient().name][i],{onclick:m(a._pageGo,a,o,e,n)},{x:-s[0]/2,y:-s[1]/2,width:s[0],height:s[1]});l.name=t,r.add(l)}var a=this;aN.superCall(this,"renderInner",t,e,i,n);var r=this._controllerGroup,s=e.get("pageIconSize",!0);y(s)||(s=[s,s]),o("pagePrev",0);var l=e.getModel("pageTextStyle");r.add(new rM({name:"pageText",style:{textFill:l.getTextColor(),font:l.getFont(),textVerticalAlign:"middle",textAlign:"center"},silent:!0})),o("pageNext",1)},layoutInner:function(t,e,i,n){var o=this.getContentGroup(),a=this._containerGroup,r=this._controllerGroup,s=t.getOrient().index,l=nN[s],u=nN[1-s],h=oN[1-s];aI(t.get("orient"),o,t.get("itemGap"),s?i.width:null,s?null:i.height),aI("horizontal",r,t.get("pageButtonItemGap",!0));var c=o.getBoundingRect(),d=r.getBoundingRect(),f=this._showController=c[l]>i[l],p=[-c.x,-c.y];n||(p[s]=o.position[s]);var g=[0,0],m=[-d.x,-d.y],v=A(t.get("pageButtonGap",!0),t.get("itemGap",!0));f&&("end"===t.get("pageButtonPosition",!0)?m[s]+=i[l]-d[l]:g[s]+=d[l]+v),m[1-s]+=c[u]/2-d[u]/2,o.attr("position",p),a.attr("position",g),r.attr("position",m);var y=this.group.getBoundingRect();if((y={x:0,y:0})[l]=f?i[l]:c[l],y[u]=Math.max(c[u],d[u]),y[h]=Math.min(0,d[h]+m[1-s]),a.__rectSize=i[l],f){var x={x:0,y:0};x[l]=Math.max(i[l]-d[l]-v,0),x[u]=y[u],a.setClipPath(new yM({shape:x})),a.__rectSize=x[l]}else r.eachChild(function(t){t.attr({invisible:!0,silent:!0})});var _=this._getPageInfo(t);return null!=_.pageIndex&&Io(o,{position:_.contentPosition},!!f&&t),this._updatePageInfoView(t,_),y},_pageGo:function(t,e,i){var n=this._getPageInfo(e)[t];null!=n&&i.dispatchAction({type:"legendScroll",scrollDataIndex:n,legendId:e.id})},_updatePageInfoView:function(t,e){var i=this._controllerGroup;d(["pagePrev","pageNext"],function(n){var o=null!=e[n+"DataIndex"],a=i.childOfName(n);a&&(a.setStyle("fill",o?t.get("pageIconColor",!0):t.get("pageIconInactiveColor",!0)),a.cursor=o?"pointer":"default")});var n=i.childOfName("pageText"),o=t.get("pageFormatter"),a=e.pageIndex,r=null!=a?a+1:0,s=e.pageCount;n&&o&&n.setStyle("text",_(o)?o.replace("{current}",r).replace("{total}",s):o({current:r,total:s}))},_getPageInfo:function(t){function e(t){if(t){var e=t.getBoundingRect(),i=e[l]+t.position[r];return{s:i,e:i+e[s],i:t.__legendDataIndex}}}function i(t,e){return t.e>=e&&t.s<=e+a}var n=t.get("scrollDataIndex",!0),o=this.getContentGroup(),a=this._containerGroup.__rectSize,r=t.getOrient().index,s=nN[r],l=oN[r],u=this._findTargetItemIndex(n),h=o.children(),c=h[u],d=h.length,f=d?1:0,p={contentPosition:o.position.slice(),pageCount:f,pageIndex:f-1,pagePrevDataIndex:null,pageNextDataIndex:null};if(!c)return p;var g=e(c);p.contentPosition[r]=-g.s;for(var m=u+1,v=g,y=g,x=null;m<=d;++m)(!(x=e(h[m]))&&y.e>v.s+a||x&&!i(x,v.s))&&(v=y.i>v.i?y:x)&&(null==p.pageNextDataIndex&&(p.pageNextDataIndex=v.i),++p.pageCount),y=x;for(var m=u-1,v=g,y=g,x=null;m>=-1;--m)(x=e(h[m]))&&i(y,x.s)||!(v.i<y.i)||(y=v,null==p.pagePrevDataIndex&&(p.pagePrevDataIndex=v.i),++p.pageCount,++p.pageIndex),v=x;return p},_findTargetItemIndex:function(t){var e,i=this.getContentGroup();return this._showController?i.eachChild(function(i,n){i.__legendDataIndex===t&&(e=n)}):e=0,e}});Es("legendScroll","legendscroll",function(t,e){var i=t.scrollDataIndex;null!=i&&e.eachComponent({mainType:"legend",subType:"scroll",query:t},function(t){t.setScrollDataIndex(i)})}),Fs({type:"tooltip",dependencies:["axisPointer"],defaultOption:{zlevel:0,z:60,show:!0,showContent:!0,trigger:"item",triggerOn:"mousemove|click",alwaysShowContent:!1,displayMode:"single",renderMode:"auto",confine:!1,showDelay:0,hideDelay:100,transitionDuration:.4,enterable:!1,backgroundColor:"rgba(50,50,50,0.7)",borderColor:"#333",borderRadius:4,borderWidth:0,padding:5,extraCssText:"",axisPointer:{type:"line",axis:"auto",animation:"auto",animationDurationUpdate:200,animationEasingUpdate:"exponentialOut",crossStyle:{color:"#999",width:1,type:"dashed",textStyle:{}}},textStyle:{color:"#fff",fontSize:14}}});var rN=d,sN=ea,lN=["","-webkit-","-moz-","-o-"];Cv.prototype={constructor:Cv,_enterable:!0,update:function(){var t=this._container,e=t.currentStyle||document.defaultView.getComputedStyle(t),i=t.style;"absolute"!==i.position&&"absolute"!==e.position&&(i.position="relative")},show:function(t){clearTimeout(this._hideTimeout);var e=this.el;e.style.cssText="position:absolute;display:block;border-style:solid;white-space:nowrap;z-index:9999999;"+Dv(t)+";left:"+this._x+"px;top:"+this._y+"px;"+(t.get("extraCssText")||""),e.style.display=e.innerHTML?"block":"none",e.style.pointerEvents=this._enterable?"auto":"none",this._show=!0},setContent:function(t){this.el.innerHTML=null==t?"":t},setEnterable:function(t){this._enterable=t},getSize:function(){var t=this.el;return[t.clientWidth,t.clientHeight]},moveTo:function(t,e){var i,n=this._zr;n&&n.painter&&(i=n.painter.getViewportRootOffset())&&(t+=i.offsetLeft,e+=i.offsetTop);var o=this.el.style;o.left=t+"px",o.top=e+"px",this._x=t,this._y=e},hide:function(){this.el.style.display="none",this._show=!1},hideLater:function(t){!this._show||this._inContent&&this._enterable||(t?(this._hideDelay=t,this._show=!1,this._hideTimeout=setTimeout(m(this.hide,this),t)):this.hide())},isShow:function(){return this._show},getOuterSize:function(){var t=this.el.clientWidth,e=this.el.clientHeight;if(document.defaultView&&document.defaultView.getComputedStyle){var i=document.defaultView.getComputedStyle(this.el);i&&(t+=parseInt(i.paddingLeft,10)+parseInt(i.paddingRight,10)+parseInt(i.borderLeftWidth,10)+parseInt(i.borderRightWidth,10),e+=parseInt(i.paddingTop,10)+parseInt(i.paddingBottom,10)+parseInt(i.borderTopWidth,10)+parseInt(i.borderBottomWidth,10))}return{width:t,height:e}}},Lv.prototype={constructor:Lv,_enterable:!0,update:function(){},show:function(t){this._hideTimeout&&clearTimeout(this._hideTimeout),this.el.attr("show",!0),this._show=!0},setContent:function(t,e,i){this.el&&this._zr.remove(this.el);for(var n={},o=t,a=o.indexOf("{marker");a>=0;){var r=o.indexOf("|}"),s=o.substr(a+"{marker".length,r-a-"{marker".length);s.indexOf("sub")>-1?n["marker"+s]={textWidth:4,textHeight:4,textBorderRadius:2,textBackgroundColor:e[s],textOffset:[3,0]}:n["marker"+s]={textWidth:10,textHeight:10,textBorderRadius:5,textBackgroundColor:e[s]},a=(o=o.substr(r+1)).indexOf("{marker")}this.el=new rM({style:{rich:n,text:t,textLineHeight:20,textBackgroundColor:i.get("backgroundColor"),textBorderRadius:i.get("borderRadius"),textFill:i.get("textStyle.color"),textPadding:i.get("padding")},z:i.get("z")}),this._zr.add(this.el);var l=this;this.el.on("mouseover",function(){l._enterable&&(clearTimeout(l._hideTimeout),l._show=!0),l._inContent=!0}),this.el.on("mouseout",function(){l._enterable&&l._show&&l.hideLater(l._hideDelay),l._inContent=!1})},setEnterable:function(t){this._enterable=t},getSize:function(){var t=this.el.getBoundingRect();return[t.width,t.height]},moveTo:function(t,e){this.el&&this.el.attr("position",[t,e])},hide:function(){this.el.hide(),this._show=!1},hideLater:function(t){!this._show||this._inContent&&this._enterable||(t?(this._hideDelay=t,this._show=!1,this._hideTimeout=setTimeout(m(this.hide,this),t)):this.hide())},isShow:function(){return this._show},getOuterSize:function(){return this.getSize()}};var uN=m,hN=d,cN=Vo,dN=new yM({shape:{x:-1,y:-1,width:2,height:2}});Ws({type:"tooltip",init:function(t,e){if(!U_.node){var i=t.getComponent("tooltip").get("renderMode");this._renderMode=Hi(i);var n;"html"===this._renderMode?(n=new Cv(e.getDom(),e),this._newLine="<br/>"):(n=new Lv(e),this._newLine="\n"),this._tooltipContent=n}},render:function(t,e,i){if(!U_.node){this.group.removeAll(),this._tooltipModel=t,this._ecModel=e,this._api=i,this._lastDataByCoordSys=null,this._alwaysShowContent=t.get("alwaysShowContent");var n=this._tooltipContent;n.update(),n.setEnterable(t.get("enterable")),this._initGlobalListener(),this._keepShow()}},_initGlobalListener:function(){var t=this._tooltipModel.get("triggerOn");um("itemTooltip",this._api,uN(function(e,i,n){"none"!==t&&(t.indexOf(e)>=0?this._tryShow(i,n):"leave"===e&&this._hide(n))},this))},_keepShow:function(){var t=this._tooltipModel,e=this._ecModel,i=this._api;if(null!=this._lastX&&null!=this._lastY&&"none"!==t.get("triggerOn")){var n=this;clearTimeout(this._refreshUpdateTimeout),this._refreshUpdateTimeout=setTimeout(function(){n.manuallyShowTip(t,e,i,{x:n._lastX,y:n._lastY})})}},manuallyShowTip:function(t,e,i,n){if(n.from!==this.uid&&!U_.node){var o=Pv(n,i);this._ticket="";var a=n.dataByCoordSys;if(n.tooltip&&null!=n.x&&null!=n.y){var r=dN;r.position=[n.x,n.y],r.update(),r.tooltip=n.tooltip,this._tryShow({offsetX:n.x,offsetY:n.y,target:r},o)}else if(a)this._tryShow({offsetX:n.x,offsetY:n.y,position:n.position,event:{},dataByCoordSys:n.dataByCoordSys,tooltipOption:n.tooltipOption},o);else if(null!=n.seriesIndex){if(this._manuallyAxisShowTip(t,e,i,n))return;var s=xP(n,e),l=s.point[0],u=s.point[1];null!=l&&null!=u&&this._tryShow({offsetX:l,offsetY:u,position:n.position,target:s.el,event:{}},o)}else null!=n.x&&null!=n.y&&(i.dispatchAction({type:"updateAxisPointer",x:n.x,y:n.y}),this._tryShow({offsetX:n.x,offsetY:n.y,position:n.position,target:i.getZr().findHover(n.x,n.y).target,event:{}},o))}},manuallyHideTip:function(t,e,i,n){var o=this._tooltipContent;!this._alwaysShowContent&&this._tooltipModel&&o.hideLater(this._tooltipModel.get("hideDelay")),this._lastX=this._lastY=null,n.from!==this.uid&&this._hide(Pv(n,i))},_manuallyAxisShowTip:function(t,e,i,n){var o=n.seriesIndex,a=n.dataIndex,r=e.getComponent("axisPointer").coordSysAxesInfo;if(null!=o&&null!=a&&null!=r){var s=e.getSeriesByIndex(o);if(s&&"axis"===(t=kv([s.getData().getItemModel(a),s,(s.coordinateSystem||{}).model,t])).get("trigger"))return i.dispatchAction({type:"updateAxisPointer",seriesIndex:o,dataIndex:a,position:n.position}),!0}},_tryShow:function(t,e){var i=t.target;if(this._tooltipModel){this._lastX=t.offsetX,this._lastY=t.offsetY;var n=t.dataByCoordSys;n&&n.length?this._showAxisTooltip(n,t):i&&null!=i.dataIndex?(this._lastDataByCoordSys=null,this._showSeriesItemTooltip(t,i,e)):i&&i.tooltip?(this._lastDataByCoordSys=null,this._showComponentItemTooltip(t,i,e)):(this._lastDataByCoordSys=null,this._hide(e))}},_showOrMove:function(t,e){var i=t.get("showDelay");e=m(e,this),clearTimeout(this._showTimout),i>0?this._showTimout=setTimeout(e,i):e()},_showAxisTooltip:function(t,e){var i=this._ecModel,o=this._tooltipModel,a=[e.offsetX,e.offsetY],r=[],s=[],l=kv([e.tooltipOption,o]),u=this._renderMode,h=this._newLine,c={};hN(t,function(t){hN(t.dataByAxis,function(t){var e=i.getComponent(t.axisDim+"Axis",t.axisIndex),o=t.value,a=[];if(e&&null!=o){var l=Im(o,e.axis,i,t.seriesDataIndices,t.valueLabelOpt);d(t.seriesDataIndices,function(r){var h=i.getSeriesByIndex(r.seriesIndex),d=r.dataIndexInside,f=h&&h.getDataParams(d);if(f.axisDim=t.axisDim,f.axisIndex=t.axisIndex,f.axisType=t.axisType,f.axisId=t.axisId,f.axisValue=Xl(e.axis,o),f.axisValueLabel=l,f){s.push(f);var p,g=h.formatTooltip(d,!0,null,u);if(w(g)){p=g.html;var m=g.markers;n(c,m)}else p=g;a.push(p)}});var f=l;"html"!==u?r.push(a.join(h)):r.push((f?ia(f)+h:"")+a.join(h))}})},this),r.reverse(),r=r.join(this._newLine+this._newLine);var f=e.position;this._showOrMove(l,function(){this._updateContentNotChangedOnAxis(t)?this._updatePosition(l,f,a[0],a[1],this._tooltipContent,s):this._showTooltipContent(l,r,s,Math.random(),a[0],a[1],f,void 0,c)})},_showSeriesItemTooltip:function(t,e,i){var n=this._ecModel,o=e.seriesIndex,a=n.getSeriesByIndex(o),r=e.dataModel||a,s=e.dataIndex,l=e.dataType,u=r.getData(),h=kv([u.getItemModel(s),r,a&&(a.coordinateSystem||{}).model,this._tooltipModel]),c=h.get("trigger");if(null==c||"item"===c){var d,f,p=r.getDataParams(s,l),g=r.formatTooltip(s,!1,l,this._renderMode);w(g)?(d=g.html,f=g.markers):(d=g,f=null);var m="item_"+r.name+"_"+s;this._showOrMove(h,function(){this._showTooltipContent(h,d,p,m,t.offsetX,t.offsetY,t.position,t.target,f)}),i({type:"showTip",dataIndexInside:s,dataIndex:u.getRawIndex(s),seriesIndex:o,from:this.uid})}},_showComponentItemTooltip:function(t,e,i){var n=e.tooltip;if("string"==typeof n){var o=n;n={content:o,formatter:o}}var a=new No(n,this._tooltipModel,this._ecModel),r=a.get("content"),s=Math.random();this._showOrMove(a,function(){this._showTooltipContent(a,r,a.get("formatterParams")||{},s,t.offsetX,t.offsetY,t.position,e)}),i({type:"showTip",from:this.uid})},_showTooltipContent:function(t,e,i,n,o,a,r,s,l){if(this._ticket="",t.get("showContent")&&t.get("show")){var u=this._tooltipContent,h=t.get("formatter");r=r||t.get("position");var c=e;if(h&&"string"==typeof h)c=na(h,i,!0);else if("function"==typeof h){var d=uN(function(e,n){e===this._ticket&&(u.setContent(n,l,t),this._updatePosition(t,r,o,a,u,i,s))},this);this._ticket=n,c=h(i,n,d)}u.setContent(c,l,t),u.show(t),this._updatePosition(t,r,o,a,u,i,s)}},_updatePosition:function(t,e,i,n,o,a,r){var s=this._api.getWidth(),l=this._api.getHeight();e=e||t.get("position");var u=o.getSize(),h=t.get("align"),c=t.get("verticalAlign"),d=r&&r.getBoundingRect().clone();if(r&&d.applyTransform(r.transform),"function"==typeof e&&(e=e([i,n],a,o.el,d,{viewSize:[s,l],contentSize:u.slice()})),y(e))i=cN(e[0],s),n=cN(e[1],l);else if(w(e)){e.width=u[0],e.height=u[1];var f=ca(e,{width:s,height:l});i=f.x,n=f.y,h=null,c=null}else"string"==typeof e&&r?(i=(p=Ev(e,d,u))[0],n=p[1]):(i=(p=Nv(i,n,o,s,l,h?null:20,c?null:20))[0],n=p[1]);if(h&&(i-=Rv(h)?u[0]/2:"right"===h?u[0]:0),c&&(n-=Rv(c)?u[1]/2:"bottom"===c?u[1]:0),t.get("confine")){var p=Ov(i,n,o,s,l);i=p[0],n=p[1]}o.moveTo(i,n)},_updateContentNotChangedOnAxis:function(t){var e=this._lastDataByCoordSys,i=!!e&&e.length===t.length;return i&&hN(e,function(e,n){var o=e.dataByAxis||{},a=(t[n]||{}).dataByAxis||[];(i&=o.length===a.length)&&hN(o,function(t,e){var n=a[e]||{},o=t.seriesDataIndices||[],r=n.seriesDataIndices||[];(i&=t.value===n.value&&t.axisType===n.axisType&&t.axisId===n.axisId&&o.length===r.length)&&hN(o,function(t,e){var n=r[e];i&=t.seriesIndex===n.seriesIndex&&t.dataIndex===n.dataIndex})})}),this._lastDataByCoordSys=t,!!i},_hide:function(t){this._lastDataByCoordSys=null,t({type:"hideTip",from:this.uid})},dispose:function(t,e){U_.node||(this._tooltipContent.hide(),gm("itemTooltip",e))}}),Es({type:"showTip",event:"showTip",update:"tooltip:manuallyShowTip"},function(){}),Es({type:"hideTip",event:"hideTip",update:"tooltip:manuallyHideTip"},function(){}),Gv.prototype={constructor:Gv,pointToData:function(t,e){return this.polar.pointToData(t,e)["radius"===this.dim?0:1]},dataToRadius:aD.prototype.dataToCoord,radiusToData:aD.prototype.coordToData},u(Gv,aD);var fN=Bi();Fv.prototype={constructor:Fv,pointToData:function(t,e){return this.polar.pointToData(t,e)["radius"===this.dim?0:1]},dataToAngle:aD.prototype.dataToCoord,angleToData:aD.prototype.coordToData,calculateCategoryInterval:function(){var t=this,e=t.getLabelModel(),i=t.scale,n=i.getExtent(),o=i.count();if(n[1]-n[0]<1)return 0;var a=n[0],r=t.dataToCoord(a+1)-t.dataToCoord(a),s=Math.abs(r),l=ke(a,e.getFont(),"center","top"),u=Math.max(l.height,7)/s;isNaN(u)&&(u=1/0);var h=Math.max(0,Math.floor(u)),c=fN(t.model),d=c.lastAutoInterval,f=c.lastTickCount;return null!=d&&null!=f&&Math.abs(d-h)<=1&&Math.abs(f-o)<=1&&d>h?h=d:(c.lastTickCount=o,c.lastAutoInterval=h),h}},u(Fv,aD);var pN=function(t){this.name=t||"",this.cx=0,this.cy=0,this._radiusAxis=new Gv,this._angleAxis=new Fv,this._radiusAxis.polar=this._angleAxis.polar=this};pN.prototype={type:"polar",axisPointerEnabled:!0,constructor:pN,dimensions:["radius","angle"],model:null,containPoint:function(t){var e=this.pointToCoord(t);return this._radiusAxis.contain(e[0])&&this._angleAxis.contain(e[1])},containData:function(t){return this._radiusAxis.containData(t[0])&&this._angleAxis.containData(t[1])},getAxis:function(t){return this["_"+t+"Axis"]},getAxes:function(){return[this._radiusAxis,this._angleAxis]},getAxesByScale:function(t){var e=[],i=this._angleAxis,n=this._radiusAxis;return i.scale.type===t&&e.push(i),n.scale.type===t&&e.push(n),e},getAngleAxis:function(){return this._angleAxis},getRadiusAxis:function(){return this._radiusAxis},getOtherAxis:function(t){var e=this._angleAxis;return t===e?this._radiusAxis:e},getBaseAxis:function(){return this.getAxesByScale("ordinal")[0]||this.getAxesByScale("time")[0]||this.getAngleAxis()},getTooltipAxes:function(t){var e=null!=t&&"auto"!==t?this.getAxis(t):this.getBaseAxis();return{baseAxes:[e],otherAxes:[this.getOtherAxis(e)]}},dataToPoint:function(t,e){return this.coordToPoint([this._radiusAxis.dataToRadius(t[0],e),this._angleAxis.dataToAngle(t[1],e)])},pointToData:function(t,e){var i=this.pointToCoord(t);return[this._radiusAxis.radiusToData(i[0],e),this._angleAxis.angleToData(i[1],e)]},pointToCoord:function(t){var e=t[0]-this.cx,i=t[1]-this.cy,n=this.getAngleAxis(),o=n.getExtent(),a=Math.min(o[0],o[1]),r=Math.max(o[0],o[1]);n.inverse?a=r-360:r=a+360;var s=Math.sqrt(e*e+i*i);e/=s,i/=s;for(var l=Math.atan2(-i,e)/Math.PI*180,u=l<a?1:-1;l<a||l>r;)l+=360*u;return[s,l]},coordToPoint:function(t){var e=t[0],i=t[1]/180*Math.PI;return[Math.cos(i)*e+this.cx,-Math.sin(i)*e+this.cy]}};var gN=lI.extend({type:"polarAxis",axis:null,getCoordSysModel:function(){return this.ecModel.queryComponents({mainType:"polar",index:this.option.polarIndex,id:this.option.polarId})[0]}});n(gN.prototype,UA);var mN={angle:{startAngle:90,clockwise:!0,splitNumber:12,axisLabel:{rotate:!1}},radius:{splitNumber:5}};ED("angle",gN,Wv,mN.angle),ED("radius",gN,Wv,mN.radius),Fs({type:"polar",dependencies:["polarAxis","angleAxis"],coordinateSystem:null,findAxisModel:function(t){var e;return this.ecModel.eachComponent(t,function(t){t.getCoordSysModel()===this&&(e=t)},this),e},defaultOption:{zlevel:0,z:0,center:["50%","50%"],radius:"80%"}});var vN={dimensions:pN.prototype.dimensions,create:function(t,e){var i=[];return t.eachComponent("polar",function(t,n){var o=new pN(n);o.update=Zv;var a=o.getRadiusAxis(),r=o.getAngleAxis(),s=t.findAxisModel("radiusAxis"),l=t.findAxisModel("angleAxis");Uv(a,s),Uv(r,l),Hv(o,t,e),i.push(o),t.coordinateSystem=o,o.model=t}),t.eachSeries(function(e){if("polar"===e.get("coordinateSystem")){var i=t.queryComponents({mainType:"polar",index:e.get("polarIndex"),id:e.get("polarId")})[0];e.coordinateSystem=i.coordinateSystem}}),i}};Fa.register("polar",vN);var yN=["axisLine","axisLabel","axisTick","splitLine","splitArea"];XD.extend({type:"angleAxis",axisPointerClass:"PolarAxisPointer",render:function(t,e){if(this.group.removeAll(),t.get("show")){var n=t.axis,o=n.polar,a=o.getRadiusAxis().getExtent(),r=n.getTicksCoords(),s=f(n.getViewLabels(),function(t){return(t=i(t)).coord=n.dataToCoord(t.tickValue),t});Yv(s),Yv(r),d(yN,function(e){!t.get(e+".show")||n.scale.isBlank()&&"axisLine"!==e||this["_"+e](t,o,r,a,s)},this)}},_axisLine:function(t,e,i,n){var o=t.getModel("axisLine.lineStyle"),a=new sM({shape:{cx:e.cx,cy:e.cy,r:n[jv(e)]},style:o.getLineStyle(),z2:1,silent:!0});a.style.fill=null,this.group.add(a)},_axisTick:function(t,e,i,n){var o=t.getModel("axisTick"),a=(o.get("inside")?-1:1)*o.get("length"),s=n[jv(e)],l=f(i,function(t){return new _M({shape:Xv(e,[s,s+a],t.coord)})});this.group.add(OM(l,{style:r(o.getModel("lineStyle").getLineStyle(),{stroke:t.get("axisLine.lineStyle.color")})}))},_axisLabel:function(t,e,i,n,o){var a=t.getCategories(!0),r=t.getModel("axisLabel"),s=r.get("margin");d(o,function(i,o){var l=r,u=i.tickValue,h=n[jv(e)],c=e.coordToPoint([h+s,i.coord]),d=e.cx,f=e.cy,p=Math.abs(c[0]-d)/h<.3?"center":c[0]>d?"left":"right",g=Math.abs(c[1]-f)/h<.3?"middle":c[1]>f?"top":"bottom";a&&a[u]&&a[u].textStyle&&(l=new No(a[u].textStyle,r,r.ecModel));var m=new rM({silent:!0});this.group.add(m),mo(m.style,l,{x:c[0],y:c[1],textFill:l.getTextColor()||t.get("axisLine.lineStyle.color"),text:i.formattedLabel,textAlign:p,textVerticalAlign:g})},this)},_splitLine:function(t,e,i,n){var o=t.getModel("splitLine").getModel("lineStyle"),a=o.get("color"),s=0;a=a instanceof Array?a:[a];for(var l=[],u=0;u<i.length;u++){var h=s++%a.length;l[h]=l[h]||[],l[h].push(new _M({shape:Xv(e,n,i[u].coord)}))}for(u=0;u<l.length;u++)this.group.add(OM(l[u],{style:r({stroke:a[u%a.length]},o.getLineStyle()),silent:!0,z:t.get("z")}))},_splitArea:function(t,e,i,n){if(i.length){var o=t.getModel("splitArea").getModel("areaStyle"),a=o.get("color"),s=0;a=a instanceof Array?a:[a];for(var l=[],u=Math.PI/180,h=-i[0].coord*u,c=Math.min(n[0],n[1]),d=Math.max(n[0],n[1]),f=t.get("clockwise"),p=1;p<i.length;p++){var g=s++%a.length;l[g]=l[g]||[],l[g].push(new hM({shape:{cx:e.cx,cy:e.cy,r0:c,r:d,startAngle:h,endAngle:-i[p].coord*u,clockwise:f},silent:!0})),h=-i[p].coord*u}for(p=0;p<l.length;p++)this.group.add(OM(l[p],{style:r({fill:a[p%a.length]},o.getAreaStyle()),silent:!0}))}}});var xN=["axisLine","axisTickLabel","axisName"],_N=["splitLine","splitArea"];XD.extend({type:"radiusAxis",axisPointerClass:"PolarAxisPointer",render:function(t,e){if(this.group.removeAll(),t.get("show")){var i=t.axis,n=i.polar,o=n.getAngleAxis(),a=i.getTicksCoords(),r=o.getExtent()[0],s=i.getExtent(),l=qv(n,t,r),u=new FD(t,l);d(xN,u.add,u),this.group.add(u.getGroup()),d(_N,function(e){t.get(e+".show")&&!i.scale.isBlank()&&this["_"+e](t,n,r,s,a)},this)}},_splitLine:function(t,e,i,n,o){var a=t.getModel("splitLine").getModel("lineStyle"),s=a.get("color"),l=0;s=s instanceof Array?s:[s];for(var u=[],h=0;h<o.length;h++){var c=l++%s.length;u[c]=u[c]||[],u[c].push(new sM({shape:{cx:e.cx,cy:e.cy,r:o[h].coord},silent:!0}))}for(h=0;h<u.length;h++)this.group.add(OM(u[h],{style:r({stroke:s[h%s.length],fill:null},a.getLineStyle()),silent:!0}))},_splitArea:function(t,e,i,n,o){if(o.length){var a=t.getModel("splitArea").getModel("areaStyle"),s=a.get("color"),l=0;s=s instanceof Array?s:[s];for(var u=[],h=o[0].coord,c=1;c<o.length;c++){var d=l++%s.length;u[d]=u[d]||[],u[d].push(new hM({shape:{cx:e.cx,cy:e.cy,r0:h,r:o[c].coord,startAngle:0,endAngle:2*Math.PI},silent:!0})),h=o[c].coord}for(c=0;c<u.length;c++)this.group.add(OM(u[c],{style:r({fill:s[c%s.length]},a.getAreaStyle()),silent:!0}))}}});var wN=mm.extend({makeElOption:function(t,e,i,n,o){var a=i.axis;"angle"===a.dim&&(this.animationThreshold=Math.PI/18);var r,s=a.polar,l=s.getOtherAxis(a).getExtent();r=a["dataTo"+la(a.dim)](e);var u=n.get("type");if(u&&"none"!==u){var h=bm(n),c=bN[u](a,s,r,l,h);c.style=h,t.graphicKey=c.type,t.pointer=c}Sm(t,i,n,o,Kv(e,i,0,s,n.get("label.margin")))}}),bN={line:function(t,e,i,n,o){return"angle"===t.dim?{type:"Line",shape:Dm(e.coordToPoint([n[0],i]),e.coordToPoint([n[1],i]))}:{type:"Circle",shape:{cx:e.cx,cy:e.cy,r:i}}},shadow:function(t,e,i,n,o){var a=Math.max(1,t.getBandWidth()),r=Math.PI/180;return"angle"===t.dim?{type:"Sector",shape:Lm(e.cx,e.cy,n[0],n[1],(-i-a/2)*r,(a/2-i)*r)}:{type:"Sector",shape:Lm(e.cx,e.cy,i-a/2,i+a/2,0,2*Math.PI)}}};XD.registerAxisPointerClass("PolarAxisPointer",wN),zs(v(function(t,e,i){i.getWidth(),i.getHeight();var n={},o=Vv(g(e.getSeriesByType(t),function(t){return!e.isSeriesFiltered(t)&&t.coordinateSystem&&"polar"===t.coordinateSystem.type}));e.eachSeriesByType(t,function(t){if("polar"===t.coordinateSystem.type){var e=t.getData(),i=t.coordinateSystem,a=i.getBaseAxis(),r=zv(t),s=o[Bv(a)][r],l=s.offset,u=s.width,h=i.getOtherAxis(a),c=t.coordinateSystem.cx,d=t.coordinateSystem.cy,f=t.get("barMinHeight")||0,p=t.get("barMinAngle")||0;n[r]=n[r]||[];for(var g=e.mapDimension(h.dim),m=e.mapDimension(a.dim),v=pl(e,g),y=h.getExtent()[0],x=0,_=e.count();x<_;x++){var w=e.get(g,x),b=e.get(m,x);if(!isNaN(w)){var S=w>=0?"p":"n",M=y;v&&(n[r][b]||(n[r][b]={p:y,n:y}),M=n[r][b][S]);var I,T,A,D;if("radius"===h.dim){var C=h.dataToRadius(w)-y,L=a.dataToAngle(b);Math.abs(C)<f&&(C=(C<0?-1:1)*f),I=M,T=M+C,D=(A=L-l)-u,v&&(n[r][b][S]=T)}else{var k=h.dataToAngle(w,!0)-y,P=a.dataToRadius(b);Math.abs(k)<p&&(k=(k<0?-1:1)*p),T=(I=P+l)+u,A=M,D=M+k,v&&(n[r][b][S]=D)}e.setItemLayout(x,{cx:c,cy:d,r0:I,r:T,startAngle:-A*Math.PI/180,endAngle:-D*Math.PI/180})}}}},this)},"bar")),Ws({type:"polar"}),h(lI.extend({type:"geo",coordinateSystem:null,layoutMode:"box",init:function(t){lI.prototype.init.apply(this,arguments),Ci(t,"label",["show"])},optionUpdated:function(){var t=this.option,e=this;t.regions=GC.getFilledRegions(t.regions,t.map,t.nameMap),this._optionModelMap=p(t.regions||[],function(t,i){return i.name&&t.set(i.name,new No(i,e)),t},R()),this.updateSelectedMap(t.regions)},defaultOption:{zlevel:0,z:0,show:!0,left:"center",top:"center",aspectScale:null,silent:!1,map:"",boundingCoords:null,center:null,zoom:1,scaleLimit:null,label:{show:!1,color:"#000"},itemStyle:{borderWidth:.5,borderColor:"#444",color:"#eee"},emphasis:{label:{show:!0,color:"rgb(100,0,0)"},itemStyle:{color:"rgba(255,215,0,0.8)"}},regions:[]},getRegionModel:function(t){return this._optionModelMap.get(t)||new No(null,this,this.ecModel)},getFormattedLabel:function(t,e){var i=this.getRegionModel(t).get("label."+e+".formatter"),n={name:t};return"function"==typeof i?(n.status=e,i(n)):"string"==typeof i?i.replace("{a}",null!=t?t:""):void 0},setZoom:function(t){this.option.zoom=t},setCenter:function(t){this.option.center=t}}),aC),Ws({type:"geo",init:function(t,e){var i=new xc(e,!0);this._mapDraw=i,this.group.add(i.group)},render:function(t,e,i,n){if(!n||"geoToggleSelect"!==n.type||n.from!==this.uid){var o=this._mapDraw;t.get("show")?o.draw(t,e,i,this,n):this._mapDraw.group.removeAll(),this.group.silent=t.get("silent")}},dispose:function(){this._mapDraw&&this._mapDraw.remove()}}),$v("toggleSelected",{type:"geoToggleSelect",event:"geoselectchanged"}),$v("select",{type:"geoSelect",event:"geoselected"}),$v("unSelect",{type:"geoUnSelect",event:"geounselected"});var SN=["rect","polygon","keep","clear"],MN=d,IN={lineX:oy(0),lineY:oy(1),rect:{point:function(t,e,i){return t&&i.boundingRect.contain(t[0],t[1])},rect:function(t,e,i){return t&&i.boundingRect.intersect(t)}},polygon:{point:function(t,e,i){return t&&i.boundingRect.contain(t[0],t[1])&&tu(i.range,t[0],t[1])},rect:function(t,e,i){var n=i.range;if(!t||n.length<=1)return!1;var o=t.x,a=t.y,r=t.width,s=t.height,l=n[0];return!!(tu(n,o,a)||tu(n,o+r,a)||tu(n,o,a+s)||tu(n,o+r,a+s)||de.create(t).contain(l[0],l[1])||ry(o,a,o+r,a,n)||ry(o,a,o,a+s,n)||ry(o+r,a,o+r,a+s,n)||ry(o,a+s,o+r,a+s,n))||void 0}}},TN=d,AN=l,DN=v,CN=["dataToPoint","pointToData"],LN=["grid","xAxis","yAxis","geo","graph","polar","radiusAxis","angleAxis","bmap"],kN=hy.prototype;kN.setOutputRanges=function(t,e){this.matchOutputRanges(t,e,function(t,e,i){if((t.coordRanges||(t.coordRanges=[])).push(e),!t.coordRange){t.coordRange=e;var n=EN[t.brushType](0,i,e);t.__rangeOffset={offset:RN[t.brushType](n.values,t.range,[1,1]),xyMinMax:n.xyMinMax}}})},kN.matchOutputRanges=function(t,e,i){TN(t,function(t){var n=this.findTargetInfo(t,e);n&&!0!==n&&d(n.coordSyses,function(n){var o=EN[t.brushType](1,n,t.range);i(t,o.values,n,e)})},this)},kN.setInputRanges=function(t,e){TN(t,function(t){var i=this.findTargetInfo(t,e);if(t.range=t.range||[],i&&!0!==i){t.panelId=i.panelId;var n=EN[t.brushType](0,i.coordSys,t.coordRange),o=t.__rangeOffset;t.range=o?RN[t.brushType](n.values,o.offset,gy(n.xyMinMax,o.xyMinMax)):n.values}},this)},kN.makePanelOpts=function(t,e){return f(this._targetInfoList,function(i){var n=i.getPanelRect();return{panelId:i.panelId,defaultBrushType:e&&e(i),clipPath:yp(n),isTargetByCursor:_p(n,t,i.coordSysModel),getLinearBrushOtherExtent:xp(n)}})},kN.controlSeries=function(t,e,i){var n=this.findTargetInfo(t,i);return!0===n||n&&AN(n.coordSyses,e.coordinateSystem)>=0},kN.findTargetInfo=function(t,e){for(var i=this._targetInfoList,n=dy(e,t),o=0;o<i.length;o++){var a=i[o],r=t.panelId;if(r){if(a.panelId===r)return a}else for(o=0;o<NN.length;o++)if(NN[o](n,a))return a}return!0};var PN={grid:function(t,e){var i=t.xAxisModels,n=t.yAxisModels,o=t.gridModels,a=R(),r={},s={};(i||n||o)&&(TN(i,function(t){var e=t.axis.grid.model;a.set(e.id,e),r[e.id]=!0}),TN(n,function(t){var e=t.axis.grid.model;a.set(e.id,e),s[e.id]=!0}),TN(o,function(t){a.set(t.id,t),r[t.id]=!0,s[t.id]=!0}),a.each(function(t){var o=t.coordinateSystem,a=[];TN(o.getCartesians(),function(t,e){(AN(i,t.getAxis("x").model)>=0||AN(n,t.getAxis("y").model)>=0)&&a.push(t)}),e.push({panelId:"grid--"+t.id,gridModel:t,coordSysModel:t,coordSys:a[0],coordSyses:a,getPanelRect:ON.grid,xAxisDeclared:r[t.id],yAxisDeclared:s[t.id]})}))},geo:function(t,e){TN(t.geoModels,function(t){var i=t.coordinateSystem;e.push({panelId:"geo--"+t.id,geoModel:t,coordSysModel:t,coordSys:i,coordSyses:[i],getPanelRect:ON.geo})})}},NN=[function(t,e){var i=t.xAxisModel,n=t.yAxisModel,o=t.gridModel;return!o&&i&&(o=i.axis.grid.model),!o&&n&&(o=n.axis.grid.model),o&&o===e.gridModel},function(t,e){var i=t.geoModel;return i&&i===e.geoModel}],ON={grid:function(){return this.coordSys.grid.getRect().clone()},geo:function(){var t=this.coordSys,e=t.getBoundingRect().clone();return e.applyTransform(Ao(t)),e}},EN={lineX:DN(fy,0),lineY:DN(fy,1),rect:function(t,e,i){var n=e[CN[t]]([i[0][0],i[1][0]]),o=e[CN[t]]([i[0][1],i[1][1]]),a=[cy([n[0],o[0]]),cy([n[1],o[1]])];return{values:a,xyMinMax:a}},polygon:function(t,e,i){var n=[[1/0,-1/0],[1/0,-1/0]];return{values:f(i,function(i){var o=e[CN[t]](i);return n[0][0]=Math.min(n[0][0],o[0]),n[1][0]=Math.min(n[1][0],o[1]),n[0][1]=Math.max(n[0][1],o[0]),n[1][1]=Math.max(n[1][1],o[1]),o}),xyMinMax:n}}},RN={lineX:DN(py,0),lineY:DN(py,1),rect:function(t,e,i){return[[t[0][0]-i[0]*e[0][0],t[0][1]-i[0]*e[0][1]],[t[1][0]-i[1]*e[1][0],t[1][1]-i[1]*e[1][1]]]},polygon:function(t,e,i){return f(t,function(t,n){return[t[0]-i[0]*e[n][0],t[1]-i[1]*e[n][1]]})}},zN=["inBrush","outOfBrush"],BN="__ecBrushSelect",VN="__ecInBrushSelectEvent",GN=VT.VISUAL.BRUSH;zs(GN,function(t,e,i){t.eachComponent({mainType:"brush"},function(e){i&&"takeGlobalCursor"===i.type&&e.setBrushOption("brush"===i.key?i.brushOption:{brushType:!1}),(e.brushTargetManager=new hy(e.option,t)).setInputRanges(e.areas,t)})}),Bs(GN,function(t,e,n){var o,a,s=[];t.eachComponent({mainType:"brush"},function(e,n){function l(t){return"all"===m||v[t]}function u(t){return!!t.length}function h(t,e){var i=t.coordinateSystem;w|=i.hasAxisBrushed(),l(e)&&i.eachActiveState(t.getData(),function(t,e){"active"===t&&(x[e]=1)})}function c(i,n,o){var a=_y(i);if(a&&!wy(e,n)&&(d(b,function(n){a[n.brushType]&&e.brushTargetManager.controlSeries(n,i,t)&&o.push(n),w|=u(o)}),l(n)&&u(o))){var r=i.getData();r.each(function(t){xy(a,o,r,t)&&(x[t]=1)})}}var p={brushId:e.id,brushIndex:n,brushName:e.name,areas:i(e.areas),selected:[]};s.push(p);var g=e.option,m=g.brushLink,v=[],x=[],_=[],w=0;n||(o=g.throttleType,a=g.throttleDelay);var b=f(e.areas,function(t){return by(r({boundingRect:FN[t.brushType](t)},t))}),S=ty(e.option,zN,function(t){t.mappingMethod="fixed"});y(m)&&d(m,function(t){v[t]=1}),t.eachSeries(function(t,e){var i=_[e]=[];"parallel"===t.subType?h(t,e):c(t,e,i)}),t.eachSeries(function(t,e){var i={seriesId:t.id,seriesIndex:e,seriesName:t.name,dataIndex:[]};p.selected.push(i);var n=_y(t),o=_[e],a=t.getData(),r=l(e)?function(t){return x[t]?(i.dataIndex.push(a.getRawIndex(t)),"inBrush"):"outOfBrush"}:function(t){return xy(n,o,a,t)?(i.dataIndex.push(a.getRawIndex(t)),"inBrush"):"outOfBrush"};(l(e)?w:u(o))&&iy(zN,S,a,r)})}),vy(e,o,a,s,n)});var FN={lineX:B,lineY:B,rect:function(t){return Sy(t.range)},polygon:function(t){for(var e,i=t.range,n=0,o=i.length;n<o;n++){e=e||[[1/0,-1/0],[1/0,-1/0]];var a=i[n];a[0]<e[0][0]&&(e[0][0]=a[0]),a[0]>e[0][1]&&(e[0][1]=a[0]),a[1]<e[1][0]&&(e[1][0]=a[1]),a[1]>e[1][1]&&(e[1][1]=a[1])}return e&&Sy(e)}},WN=["#ddd"];Fs({type:"brush",dependencies:["geo","grid","xAxis","yAxis","parallel","series"],defaultOption:{toolbox:null,brushLink:null,seriesIndex:"all",geoIndex:null,xAxisIndex:null,yAxisIndex:null,brushType:"rect",brushMode:"single",transformable:!0,brushStyle:{borderWidth:1,color:"rgba(120,140,180,0.3)",borderColor:"rgba(120,140,180,0.8)"},throttleType:"fixRate",throttleDelay:0,removeOnClick:!0,z:1e4},areas:[],brushType:null,brushOption:{},coordInfoList:[],optionUpdated:function(t,e){var i=this.option;!e&&ey(i,t,["inBrush","outOfBrush"]);var n=i.inBrush=i.inBrush||{};i.outOfBrush=i.outOfBrush||{color:WN},n.hasOwnProperty("liftZ")||(n.liftZ=5)},setAreas:function(t){t&&(this.areas=f(t,function(t){return My(this.option,t)},this))},setBrushOption:function(t){this.brushOption=My(this.option,t),this.brushType=this.brushOption.brushType}});Ws({type:"brush",init:function(t,e){this.ecModel=t,this.api=e,this.model,(this._brushController=new zf(e.getZr())).on("brush",m(this._onBrush,this)).mount()},render:function(t){return this.model=t,Iy.apply(this,arguments)},updateTransform:Iy,updateView:Iy,dispose:function(){this._brushController.dispose()},_onBrush:function(t,e){var n=this.model.id;this.model.brushTargetManager.setOutputRanges(t,this.ecModel),(!e.isEnd||e.removeOnClick)&&this.api.dispatchAction({type:"brush",brushId:n,areas:i(t),$from:n})}}),Es({type:"brush",event:"brush"},function(t,e){e.eachComponent({mainType:"brush",query:t},function(e){e.setAreas(t.areas)})}),Es({type:"brushSelect",event:"brushSelected",update:"none"},function(){});var HN={},ZN=rT.toolbox.brush;Dy.defaultOption={show:!0,type:["rect","polygon","lineX","lineY","keep","clear"],icon:{rect:"M7.3,34.7 M0.4,10V-0.2h9.8 M89.6,10V-0.2h-9.8 M0.4,60v10.2h9.8 M89.6,60v10.2h-9.8 M12.3,22.4V10.5h13.1 M33.6,10.5h7.8 M49.1,10.5h7.8 M77.5,22.4V10.5h-13 M12.3,31.1v8.2 M77.7,31.1v8.2 M12.3,47.6v11.9h13.1 M33.6,59.5h7.6 M49.1,59.5 h7.7 M77.5,47.6v11.9h-13",polygon:"M55.2,34.9c1.7,0,3.1,1.4,3.1,3.1s-1.4,3.1-3.1,3.1 s-3.1-1.4-3.1-3.1S53.5,34.9,55.2,34.9z M50.4,51c1.7,0,3.1,1.4,3.1,3.1c0,1.7-1.4,3.1-3.1,3.1c-1.7,0-3.1-1.4-3.1-3.1 C47.3,52.4,48.7,51,50.4,51z M55.6,37.1l1.5-7.8 M60.1,13.5l1.6-8.7l-7.8,4 M59,19l-1,5.3 M24,16.1l6.4,4.9l6.4-3.3 M48.5,11.6 l-5.9,3.1 M19.1,12.8L9.7,5.1l1.1,7.7 M13.4,29.8l1,7.3l6.6,1.6 M11.6,18.4l1,6.1 M32.8,41.9 M26.6,40.4 M27.3,40.2l6.1,1.6 M49.9,52.1l-5.6-7.6l-4.9-1.2",lineX:"M15.2,30 M19.7,15.6V1.9H29 M34.8,1.9H40.4 M55.3,15.6V1.9H45.9 M19.7,44.4V58.1H29 M34.8,58.1H40.4 M55.3,44.4 V58.1H45.9 M12.5,20.3l-9.4,9.6l9.6,9.8 M3.1,29.9h16.5 M62.5,20.3l9.4,9.6L62.3,39.7 M71.9,29.9H55.4",lineY:"M38.8,7.7 M52.7,12h13.2v9 M65.9,26.6V32 M52.7,46.3h13.2v-9 M24.9,12H11.8v9 M11.8,26.6V32 M24.9,46.3H11.8v-9 M48.2,5.1l-9.3-9l-9.4,9.2 M38.9-3.9V12 M48.2,53.3l-9.3,9l-9.4-9.2 M38.9,62.3V46.4",keep:"M4,10.5V1h10.3 M20.7,1h6.1 M33,1h6.1 M55.4,10.5V1H45.2 M4,17.3v6.6 M55.6,17.3v6.6 M4,30.5V40h10.3 M20.7,40 h6.1 M33,40h6.1 M55.4,30.5V40H45.2 M21,18.9h62.9v48.6H21V18.9z",clear:"M22,14.7l30.9,31 M52.9,14.7L22,45.7 M4.7,16.8V4.2h13.1 M26,4.2h7.8 M41.6,4.2h7.8 M70.3,16.8V4.2H57.2 M4.7,25.9v8.6 M70.3,25.9v8.6 M4.7,43.2v12.6h13.1 M26,55.8h7.8 M41.6,55.8h7.8 M70.3,43.2v12.6H57.2"},title:i(ZN.title)};var UN=Dy.prototype;UN.render=UN.updateView=function(t,e,i){var n,o,a;e.eachComponent({mainType:"brush"},function(t){n=t.brushType,o=t.brushOption.brushMode||"single",a|=t.areas.length}),this._brushType=n,this._brushMode=o,d(t.get("type",!0),function(e){t.setIconStatus(e,("keep"===e?"multiple"===o:"clear"===e?a:e===n)?"emphasis":"normal")})},UN.getIcons=function(){var t=this.model,e=t.get("icon",!0),i={};return d(t.get("type",!0),function(t){e[t]&&(i[t]=e[t])}),i},UN.onclick=function(t,e,i){var n=this._brushType,o=this._brushMode;"clear"===i?(e.dispatchAction({type:"axisAreaSelect",intervals:[]}),e.dispatchAction({type:"brush",command:"clear",areas:[]})):e.dispatchAction({type:"takeGlobalCursor",key:"brush",brushOption:{brushType:"keep"===i?n:n!==i&&i,brushMode:"keep"===i?"multiple"===o?"single":"multiple":o}})},Ty("brush",Dy),Ns(function(t,e){var i=t&&t.brush;if(y(i)||(i=i?[i]:[]),i.length){var n=[];d(i,function(t){var e=t.hasOwnProperty("toolbox")?t.toolbox:[];e instanceof Array&&(n=n.concat(e))});var o=t&&t.toolbox;y(o)&&(o=o[0]),o||(o={feature:{}},t.toolbox=[o]);var a=o.feature||(o.feature={}),r=a.brush||(a.brush={}),s=r.type||(r.type=[]);s.push.apply(s,n),Jv(s),e&&!s.length&&s.push.apply(s,SN)}});Cy.prototype={constructor:Cy,type:"calendar",dimensions:["time","value"],getDimensionsInfo:function(){return[{name:"time",type:"time"},"value"]},getRangeInfo:function(){return this._rangeInfo},getModel:function(){return this._model},getRect:function(){return this._rect},getCellWidth:function(){return this._sw},getCellHeight:function(){return this._sh},getOrient:function(){return this._orient},getFirstDayOfWeek:function(){return this._firstDayOfWeek},getDateInfo:function(t){var e=(t=Yo(t)).getFullYear(),i=t.getMonth()+1;i=i<10?"0"+i:i;var n=t.getDate();n=n<10?"0"+n:n;var o=t.getDay();return o=Math.abs((o+7-this.getFirstDayOfWeek())%7),{y:e,m:i,d:n,day:o,time:t.getTime(),formatedDate:e+"-"+i+"-"+n,date:t}},getNextNDay:function(t,e){return 0===(e=e||0)?this.getDateInfo(t):((t=new Date(this.getDateInfo(t).time)).setDate(t.getDate()+e),this.getDateInfo(t))},update:function(t,e){function i(t,e){return null!=t[e]&&"auto"!==t[e]}this._firstDayOfWeek=+this._model.getModel("dayLabel").get("firstDay"),this._orient=this._model.get("orient"),this._lineWidth=this._model.getModel("itemStyle").getItemStyle().lineWidth||0,this._rangeInfo=this._getRangeInfo(this._initRangeOption());var n=this._rangeInfo.weeks||1,o=["width","height"],a=this._model.get("cellSize").slice(),r=this._model.getBoxLayoutParams(),s="horizontal"===this._orient?[n,7]:[7,n];d([0,1],function(t){i(a,t)&&(r[o[t]]=a[t]*s[t])});var l={width:e.getWidth(),height:e.getHeight()},u=this._rect=ca(r,l);d([0,1],function(t){i(a,t)||(a[t]=u[o[t]]/s[t])}),this._sw=a[0],this._sh=a[1]},dataToPoint:function(t,e){y(t)&&(t=t[0]),null==e&&(e=!0);var i=this.getDateInfo(t),n=this._rangeInfo,o=i.formatedDate;if(e&&!(i.time>=n.start.time&&i.time<n.end.time+864e5))return[NaN,NaN];var a=i.day,r=this._getRangeInfo([n.start.time,o]).nthWeek;return"vertical"===this._orient?[this._rect.x+a*this._sw+this._sw/2,this._rect.y+r*this._sh+this._sh/2]:[this._rect.x+r*this._sw+this._sw/2,this._rect.y+a*this._sh+this._sh/2]},pointToData:function(t){var e=this.pointToDate(t);return e&&e.time},dataToRect:function(t,e){var i=this.dataToPoint(t,e);return{contentShape:{x:i[0]-(this._sw-this._lineWidth)/2,y:i[1]-(this._sh-this._lineWidth)/2,width:this._sw-this._lineWidth,height:this._sh-this._lineWidth},center:i,tl:[i[0]-this._sw/2,i[1]-this._sh/2],tr:[i[0]+this._sw/2,i[1]-this._sh/2],br:[i[0]+this._sw/2,i[1]+this._sh/2],bl:[i[0]-this._sw/2,i[1]+this._sh/2]}},pointToDate:function(t){var e=Math.floor((t[0]-this._rect.x)/this._sw)+1,i=Math.floor((t[1]-this._rect.y)/this._sh)+1,n=this._rangeInfo.range;return"vertical"===this._orient?this._getDateByWeeksAndDay(i,e-1,n):this._getDateByWeeksAndDay(e,i-1,n)},convertToPixel:v(Ly,"dataToPoint"),convertFromPixel:v(Ly,"pointToData"),_initRangeOption:function(){var t=this._model.get("range"),e=t;if(y(e)&&1===e.length&&(e=e[0]),/^\d{4}$/.test(e)&&(t=[e+"-01-01",e+"-12-31"]),/^\d{4}[\/|-]\d{1,2}$/.test(e)){var i=this.getDateInfo(e),n=i.date;n.setMonth(n.getMonth()+1);var o=this.getNextNDay(n,-1);t=[i.formatedDate,o.formatedDate]}/^\d{4}[\/|-]\d{1,2}[\/|-]\d{1,2}$/.test(e)&&(t=[e,e]);var a=this._getRangeInfo(t);return a.start.time>a.end.time&&t.reverse(),t},_getRangeInfo:function(t){var e;(t=[this.getDateInfo(t[0]),this.getDateInfo(t[1])])[0].time>t[1].time&&(e=!0,t.reverse());var i=Math.floor(t[1].time/864e5)-Math.floor(t[0].time/864e5)+1,n=new Date(t[0].time),o=n.getDate(),a=t[1].date.getDate();if(n.setDate(o+i-1),n.getDate()!==a)for(var r=n.getTime()-t[1].time>0?1:-1;n.getDate()!==a&&(n.getTime()-t[1].time)*r>0;)i-=r,n.setDate(o+i-1);var s=Math.floor((i+t[0].day+6)/7),l=e?1-s:s-1;return e&&t.reverse(),{range:[t[0].formatedDate,t[1].formatedDate],start:t[0],end:t[1],allDay:i,weeks:s,nthWeek:l,fweek:t[0].day,lweek:t[1].day}},_getDateByWeeksAndDay:function(t,e,i){var n=this._getRangeInfo(i);if(t>n.weeks||0===t&&e<n.fweek||t===n.weeks&&e>n.lweek)return!1;var o=7*(t-1)-n.fweek+e,a=new Date(n.start.time);return a.setDate(n.start.d+o),this.getDateInfo(a)}},Cy.dimensions=Cy.prototype.dimensions,Cy.getDimensionsInfo=Cy.prototype.getDimensionsInfo,Cy.create=function(t,e){var i=[];return t.eachComponent("calendar",function(n){var o=new Cy(n,t,e);i.push(o),n.coordinateSystem=o}),t.eachSeries(function(t){"calendar"===t.get("coordinateSystem")&&(t.coordinateSystem=i[t.get("calendarIndex")||0])}),i},Fa.register("calendar",Cy);var XN=lI.extend({type:"calendar",coordinateSystem:null,defaultOption:{zlevel:0,z:2,left:80,top:60,cellSize:20,orient:"horizontal",splitLine:{show:!0,lineStyle:{color:"#000",width:1,type:"solid"}},itemStyle:{color:"#fff",borderWidth:1,borderColor:"#ccc"},dayLabel:{show:!0,firstDay:0,position:"start",margin:"50%",nameMap:"en",color:"#000"},monthLabel:{show:!0,position:"start",margin:5,align:"center",nameMap:"en",formatter:null,color:"#000"},yearLabel:{show:!0,position:null,margin:30,formatter:null,color:"#ccc",fontFamily:"sans-serif",fontWeight:"bolder",fontSize:20}},init:function(t,e,i,n){var o=ga(t);XN.superApply(this,"init",arguments),ky(t,o)},mergeOption:function(t,e){XN.superApply(this,"mergeOption",arguments),ky(this.option,t)}}),jN={EN:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],CN:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"]},YN={EN:["S","M","T","W","T","F","S"],CN:["日","一","二","三","四","五","六"]};Ws({type:"calendar",_tlpoints:null,_blpoints:null,_firstDayOfMonth:null,_firstDayPoints:null,render:function(t,e,i){var n=this.group;n.removeAll();var o=t.coordinateSystem,a=o.getRangeInfo(),r=o.getOrient();this._renderDayRect(t,a,n),this._renderLines(t,a,r,n),this._renderYearText(t,a,r,n),this._renderMonthText(t,r,n),this._renderWeekText(t,a,r,n)},_renderDayRect:function(t,e,i){for(var n=t.coordinateSystem,o=t.getModel("itemStyle").getItemStyle(),a=n.getCellWidth(),r=n.getCellHeight(),s=e.start.time;s<=e.end.time;s=n.getNextNDay(s,1).time){var l=n.dataToRect([s],!1).tl,u=new yM({shape:{x:l[0],y:l[1],width:a,height:r},cursor:"default",style:o});i.add(u)}},_renderLines:function(t,e,i,n){function o(e){a._firstDayOfMonth.push(r.getDateInfo(e)),a._firstDayPoints.push(r.dataToRect([e],!1).tl);var o=a._getLinePointsOfOneWeek(t,e,i);a._tlpoints.push(o[0]),a._blpoints.push(o[o.length-1]),l&&a._drawSplitline(o,s,n)}var a=this,r=t.coordinateSystem,s=t.getModel("splitLine.lineStyle").getLineStyle(),l=t.get("splitLine.show"),u=s.lineWidth;this._tlpoints=[],this._blpoints=[],this._firstDayOfMonth=[],this._firstDayPoints=[];for(var h=e.start,c=0;h.time<=e.end.time;c++){o(h.formatedDate),0===c&&(h=r.getDateInfo(e.start.y+"-"+e.start.m));var d=h.date;d.setMonth(d.getMonth()+1),h=r.getDateInfo(d)}o(r.getNextNDay(e.end.time,1).formatedDate),l&&this._drawSplitline(a._getEdgesPoints(a._tlpoints,u,i),s,n),l&&this._drawSplitline(a._getEdgesPoints(a._blpoints,u,i),s,n)},_getEdgesPoints:function(t,e,i){var n=[t[0].slice(),t[t.length-1].slice()],o="horizontal"===i?0:1;return n[0][o]=n[0][o]-e/2,n[1][o]=n[1][o]+e/2,n},_drawSplitline:function(t,e,i){var n=new gM({z2:20,shape:{points:t},style:e});i.add(n)},_getLinePointsOfOneWeek:function(t,e,i){var n=t.coordinateSystem;e=n.getDateInfo(e);for(var o=[],a=0;a<7;a++){var r=n.getNextNDay(e.time,a),s=n.dataToRect([r.time],!1);o[2*r.day]=s.tl,o[2*r.day+1]=s["horizontal"===i?"bl":"tr"]}return o},_formatterLabel:function(t,e){return"string"==typeof t&&t?oa(t,e):"function"==typeof t?t(e):e.nameMap},_yearTextPositionControl:function(t,e,i,n,o){e=e.slice();var a=["center","bottom"];"bottom"===n?(e[1]+=o,a=["center","top"]):"left"===n?e[0]-=o:"right"===n?(e[0]+=o,a=["center","top"]):e[1]-=o;var r=0;return"left"!==n&&"right"!==n||(r=Math.PI/2),{rotation:r,position:e,style:{textAlign:a[0],textVerticalAlign:a[1]}}},_renderYearText:function(t,e,i,n){var o=t.getModel("yearLabel");if(o.get("show")){var a=o.get("margin"),r=o.get("position");r||(r="horizontal"!==i?"top":"left");var s=[this._tlpoints[this._tlpoints.length-1],this._blpoints[0]],l=(s[0][0]+s[1][0])/2,u=(s[0][1]+s[1][1])/2,h="horizontal"===i?0:1,c={top:[l,s[h][1]],bottom:[l,s[1-h][1]],left:[s[1-h][0],u],right:[s[h][0],u]},d=e.start.y;+e.end.y>+e.start.y&&(d=d+"-"+e.end.y);var f=o.get("formatter"),p={start:e.start.y,end:e.end.y,nameMap:d},g=this._formatterLabel(f,p),m=new rM({z2:30});mo(m.style,o,{text:g}),m.attr(this._yearTextPositionControl(m,c[r],i,r,a)),n.add(m)}},_monthTextPositionControl:function(t,e,i,n,o){var a="left",r="top",s=t[0],l=t[1];return"horizontal"===i?(l+=o,e&&(a="center"),"start"===n&&(r="bottom")):(s+=o,e&&(r="middle"),"start"===n&&(a="right")),{x:s,y:l,textAlign:a,textVerticalAlign:r}},_renderMonthText:function(t,e,i){var n=t.getModel("monthLabel");if(n.get("show")){var o=n.get("nameMap"),r=n.get("margin"),s=n.get("position"),l=n.get("align"),u=[this._tlpoints,this._blpoints];_(o)&&(o=jN[o.toUpperCase()]||[]);var h="start"===s?0:1,c="horizontal"===e?0:1;r="start"===s?-r:r;for(var d="center"===l,f=0;f<u[h].length-1;f++){var p=u[h][f].slice(),g=this._firstDayOfMonth[f];if(d){var m=this._firstDayPoints[f];p[c]=(m[c]+u[0][f+1][c])/2}var v=n.get("formatter"),y=o[+g.m-1],x={yyyy:g.y,yy:(g.y+"").slice(2),MM:g.m,M:+g.m,nameMap:y},w=this._formatterLabel(v,x),b=new rM({z2:30});a(mo(b.style,n,{text:w}),this._monthTextPositionControl(p,d,e,s,r)),i.add(b)}}},_weekTextPositionControl:function(t,e,i,n,o){var a="center",r="middle",s=t[0],l=t[1],u="start"===i;return"horizontal"===e?(s=s+n+(u?1:-1)*o[0]/2,a=u?"right":"left"):(l=l+n+(u?1:-1)*o[1]/2,r=u?"bottom":"top"),{x:s,y:l,textAlign:a,textVerticalAlign:r}},_renderWeekText:function(t,e,i,n){var o=t.getModel("dayLabel");if(o.get("show")){var r=t.coordinateSystem,s=o.get("position"),l=o.get("nameMap"),u=o.get("margin"),h=r.getFirstDayOfWeek();_(l)&&(l=YN[l.toUpperCase()]||[]);var c=r.getNextNDay(e.end.time,7-e.lweek).time,d=[r.getCellWidth(),r.getCellHeight()];u=Vo(u,d["horizontal"===i?0:1]),"start"===s&&(c=r.getNextNDay(e.start.time,-(7+e.fweek)).time,u=-u);for(var f=0;f<7;f++){var p=r.getNextNDay(c,f),g=r.dataToRect([p.time],!1).center,m=f;m=Math.abs((f+h)%7);var v=new rM({z2:30});a(mo(v.style,o,{text:l[m]}),this._weekTextPositionControl(g,i,s,u,d)),n.add(v)}}}}),Fs({type:"title",layoutMode:{type:"box",ignoreSize:!0},defaultOption:{zlevel:0,z:6,show:!0,text:"",target:"blank",subtext:"",subtarget:"blank",left:0,top:0,backgroundColor:"rgba(0,0,0,0)",borderColor:"#ccc",borderWidth:0,padding:5,itemGap:10,textStyle:{fontSize:18,fontWeight:"bolder",color:"#333"},subtextStyle:{color:"#aaa"}}}),Ws({type:"title",render:function(t,e,i){if(this.group.removeAll(),t.get("show")){var n=this.group,o=t.getModel("textStyle"),a=t.getModel("subtextStyle"),r=t.get("textAlign"),s=t.get("textBaseline"),l=new rM({style:mo({},o,{text:t.get("text"),textFill:o.getTextColor()},{disableBox:!0}),z2:10}),u=l.getBoundingRect(),h=t.get("subtext"),c=new rM({style:mo({},a,{text:h,textFill:a.getTextColor(),y:u.height+t.get("itemGap"),textVerticalAlign:"top"},{disableBox:!0}),z2:10}),d=t.get("link"),f=t.get("sublink"),p=t.get("triggerEvent",!0);l.silent=!d&&!p,c.silent=!f&&!p,d&&l.on("click",function(){window.open(d,"_"+t.get("target"))}),f&&c.on("click",function(){window.open(f,"_"+t.get("subtarget"))}),l.eventData=c.eventData=p?{componentType:"title",componentIndex:t.componentIndex}:null,n.add(l),h&&n.add(c);var g=n.getBoundingRect(),m=t.getBoxLayoutParams();m.width=g.width,m.height=g.height;var v=ca(m,{width:i.getWidth(),height:i.getHeight()},t.get("padding"));r||("middle"===(r=t.get("left")||t.get("right"))&&(r="center"),"right"===r?v.x+=v.width:"center"===r&&(v.x+=v.width/2)),s||("center"===(s=t.get("top")||t.get("bottom"))&&(s="middle"),"bottom"===s?v.y+=v.height:"middle"===s&&(v.y+=v.height/2),s=s||"top"),n.attr("position",[v.x,v.y]);var y={textAlign:r,textVerticalAlign:s};l.setStyle(y),c.setStyle(y),g=n.getBoundingRect();var x=v.margin,_=t.getItemStyle(["color","opacity"]);_.fill=t.get("backgroundColor");var w=new yM({shape:{x:g.x-x[3],y:g.y-x[0],width:g.width+x[1]+x[3],height:g.height+x[0]+x[2],r:t.get("borderRadius")},style:_,silent:!0});$n(w),n.add(w)}}}),lI.registerSubTypeDefaulter("dataZoom",function(){return"slider"});var qN=["cartesian2d","polar","singleAxis"],KN=function(t,e){var i=f(t=t.slice(),la),n=f(e=(e||[]).slice(),la);return function(o,a){d(t,function(t,r){for(var s={name:t,capital:i[r]},l=0;l<e.length;l++)s[e[l]]=t+n[l];o.call(a,s)})}}(["x","y","z","radius","angle","single"],["axisIndex","axis","index","id"]),$N=d,JN=Fo,QN=function(t,e,i,n){this._dimName=t,this._axisIndex=e,this._valueWindow,this._percentWindow,this._dataExtent,this._minMaxSpan,this.ecModel=n,this._dataZoomModel=i};QN.prototype={constructor:QN,hostedBy:function(t){return this._dataZoomModel===t},getDataValueWindow:function(){return this._valueWindow.slice()},getDataPercentWindow:function(){return this._percentWindow.slice()},getTargetSeriesModels:function(){var t=[],e=this.ecModel;return e.eachSeries(function(i){if(Py(i.get("coordinateSystem"))){var n=this._dimName,o=e.queryComponents({mainType:n+"Axis",index:i.get(n+"AxisIndex"),id:i.get(n+"AxisId")})[0];this._axisIndex===(o&&o.componentIndex)&&t.push(i)}},this),t},getAxisModel:function(){return this.ecModel.getComponent(this._dimName+"Axis",this._axisIndex)},getOtherAxisModel:function(){var t,e,i=this._dimName,n=this.ecModel,o=this.getAxisModel();"x"===i||"y"===i?(e="gridIndex",t="x"===i?"y":"x"):(e="polarIndex",t="angle"===i?"radius":"angle");var a;return n.eachComponent(t+"Axis",function(t){(t.get(e)||0)===(o.get(e)||0)&&(a=t)}),a},getMinMaxSpan:function(){return i(this._minMaxSpan)},calculateDataWindow:function(t){var e=this._dataExtent,i=this.getAxisModel().axis.scale,n=this._dataZoomModel.getRangePropMode(),o=[0,100],a=[t.start,t.end],r=[];return $N(["startValue","endValue"],function(e){r.push(null!=t[e]?i.parse(t[e]):null)}),$N([0,1],function(t){var s=r[t],l=a[t];"percent"===n[t]?(null==l&&(l=o[t]),s=i.parse(Bo(l,o,e,!0))):l=Bo(s,e,o,!0),r[t]=s,a[t]=l}),{valueWindow:JN(r),percentWindow:JN(a)}},reset:function(t){if(t===this._dataZoomModel){var e=this.getTargetSeriesModels();this._dataExtent=Oy(this,this._dimName,e);var i=this.calculateDataWindow(t.option);this._valueWindow=i.valueWindow,this._percentWindow=i.percentWindow,zy(this),Ry(this)}},restore:function(t){t===this._dataZoomModel&&(this._valueWindow=this._percentWindow=null,Ry(this,!0))},filterData:function(t,e){function i(t){return t>=r[0]&&t<=r[1]}if(t===this._dataZoomModel){var n=this._dimName,o=this.getTargetSeriesModels(),a=t.get("filterMode"),r=this._valueWindow;"none"!==a&&$N(o,function(t){var e=t.getData(),o=e.mapDimension(n,!0);o.length&&("weakFilter"===a?e.filterSelf(function(t){for(var i,n,a,s=0;s<o.length;s++){var l=e.get(o[s],t),u=!isNaN(l),h=l<r[0],c=l>r[1];if(u&&!h&&!c)return!0;u&&(a=!0),h&&(i=!0),c&&(n=!0)}return a&&i&&n}):$N(o,function(n){if("empty"===a)t.setData(e.map(n,function(t){return i(t)?t:NaN}));else{var o={};o[n]=r,e.selectRange(o)}}),$N(o,function(t){e.setApproximateExtent(r,t)}))})}}};var tO=d,eO=KN,iO=Fs({type:"dataZoom",dependencies:["xAxis","yAxis","zAxis","radiusAxis","angleAxis","singleAxis","series"],defaultOption:{zlevel:0,z:4,orient:null,xAxisIndex:null,yAxisIndex:null,filterMode:"filter",throttle:null,start:0,end:100,startValue:null,endValue:null,minSpan:null,maxSpan:null,minValueSpan:null,maxValueSpan:null,rangeMode:null},init:function(t,e,i){this._dataIntervalByAxis={},this._dataInfo={},this._axisProxies={},this.textStyleModel,this._autoThrottle=!0,this._rangePropMode=["percent","percent"];var n=By(t);this.mergeDefaultAndTheme(t,i),this.doInit(n)},mergeOption:function(t){var e=By(t);n(this.option,t,!0),this.doInit(e)},doInit:function(t){var e=this.option;U_.canvasSupported||(e.realtime=!1),this._setDefaultThrottle(t),Vy(this,t),tO([["start","startValue"],["end","endValue"]],function(t,i){"value"===this._rangePropMode[i]&&(e[t[0]]=null)},this),this.textStyleModel=this.getModel("textStyle"),this._resetTarget(),this._giveAxisProxies()},_giveAxisProxies:function(){var t=this._axisProxies;this.eachTargetAxis(function(e,i,n,o){var a=this.dependentModels[e.axis][i],r=a.__dzAxisProxy||(a.__dzAxisProxy=new QN(e.name,i,this,o));t[e.name+"_"+i]=r},this)},_resetTarget:function(){var t=this.option,e=this._judgeAutoMode();eO(function(e){var i=e.axisIndex;t[i]=Di(t[i])},this),"axisIndex"===e?this._autoSetAxisIndex():"orient"===e&&this._autoSetOrient()},_judgeAutoMode:function(){var t=this.option,e=!1;eO(function(i){null!=t[i.axisIndex]&&(e=!0)},this);var i=t.orient;return null==i&&e?"orient":e?void 0:(null==i&&(t.orient="horizontal"),"axisIndex")},_autoSetAxisIndex:function(){var t=!0,e=this.get("orient",!0),i=this.option,n=this.dependentModels;if(t){var o="vertical"===e?"y":"x";n[o+"Axis"].length?(i[o+"AxisIndex"]=[0],t=!1):tO(n.singleAxis,function(n){t&&n.get("orient",!0)===e&&(i.singleAxisIndex=[n.componentIndex],t=!1)})}t&&eO(function(e){if(t){var n=[],o=this.dependentModels[e.axis];if(o.length&&!n.length)for(var a=0,r=o.length;a<r;a++)"category"===o[a].get("type")&&n.push(a);i[e.axisIndex]=n,n.length&&(t=!1)}},this),t&&this.ecModel.eachSeries(function(t){this._isSeriesHasAllAxesTypeOf(t,"value")&&eO(function(e){var n=i[e.axisIndex],o=t.get(e.axisIndex),a=t.get(e.axisId);l(n,o=t.ecModel.queryComponents({mainType:e.axis,index:o,id:a})[0].componentIndex)<0&&n.push(o)})},this)},_autoSetOrient:function(){var t;this.eachTargetAxis(function(e){!t&&(t=e.name)},this),this.option.orient="y"===t?"vertical":"horizontal"},_isSeriesHasAllAxesTypeOf:function(t,e){var i=!0;return eO(function(n){var o=t.get(n.axisIndex),a=this.dependentModels[n.axis][o];a&&a.get("type")===e||(i=!1)},this),i},_setDefaultThrottle:function(t){if(t.hasOwnProperty("throttle")&&(this._autoThrottle=!1),this._autoThrottle){var e=this.ecModel.option;this.option.throttle=e.animation&&e.animationDurationUpdate>0?100:20}},getFirstTargetAxisModel:function(){var t;return eO(function(e){if(null==t){var i=this.get(e.axisIndex);i.length&&(t=this.dependentModels[e.axis][i[0]])}},this),t},eachTargetAxis:function(t,e){var i=this.ecModel;eO(function(n){tO(this.get(n.axisIndex),function(o){t.call(e,n,o,this,i)},this)},this)},getAxisProxy:function(t,e){return this._axisProxies[t+"_"+e]},getAxisModel:function(t,e){var i=this.getAxisProxy(t,e);return i&&i.getAxisModel()},setRawRange:function(t,e){var i=this.option;tO([["start","startValue"],["end","endValue"]],function(e){null==t[e[0]]&&null==t[e[1]]||(i[e[0]]=t[e[0]],i[e[1]]=t[e[1]])},this),!e&&Vy(this,t)},getPercentRange:function(){var t=this.findRepresentativeAxisProxy();if(t)return t.getDataPercentWindow()},getValueRange:function(t,e){if(null!=t||null!=e)return this.getAxisProxy(t,e).getDataValueWindow();var i=this.findRepresentativeAxisProxy();return i?i.getDataValueWindow():void 0},findRepresentativeAxisProxy:function(t){if(t)return t.__dzAxisProxy;var e=this._axisProxies;for(var i in e)if(e.hasOwnProperty(i)&&e[i].hostedBy(this))return e[i];for(var i in e)if(e.hasOwnProperty(i)&&!e[i].hostedBy(this))return e[i]},getRangePropMode:function(){return this._rangePropMode.slice()}}),nO=qI.extend({type:"dataZoom",render:function(t,e,i,n){this.dataZoomModel=t,this.ecModel=e,this.api=i},getTargetCoordInfo:function(){function t(t,e,i,n){for(var o,a=0;a<i.length;a++)if(i[a].model===t){o=i[a];break}o||i.push(o={model:t,axisModels:[],coordIndex:n}),o.axisModels.push(e)}var e=this.dataZoomModel,i=this.ecModel,n={};return e.eachTargetAxis(function(e,o){var a=i.getComponent(e.axis,o);if(a){var r=a.getCoordSysModel();r&&t(r,a,n[r.mainType]||(n[r.mainType]=[]),r.componentIndex)}},this),n}}),oO=(iO.extend({type:"dataZoom.slider",layoutMode:"box",defaultOption:{show:!0,right:"ph",top:"ph",width:"ph",height:"ph",left:null,bottom:null,backgroundColor:"rgba(47,69,84,0)",dataBackground:{lineStyle:{color:"#2f4554",width:.5,opacity:.3},areaStyle:{color:"rgba(47,69,84,0.3)",opacity:.3}},borderColor:"#ddd",fillerColor:"rgba(167,183,204,0.4)",handleIcon:"M8.2,13.6V3.9H6.3v9.7H3.1v14.9h3.3v9.7h1.8v-9.7h3.3V13.6H8.2z M9.7,24.4H4.8v-1.4h4.9V24.4z M9.7,19.1H4.8v-1.4h4.9V19.1z",handleSize:"100%",handleStyle:{color:"#a7b7cc"},labelPrecision:null,labelFormatter:null,showDetail:!0,showDataShadow:"auto",realtime:!0,zoomLock:!1,textStyle:{color:"#333"}}}),yM),aO=Bo,rO=Fo,sO=m,lO=d,uO="horizontal",hO=5,cO=["line","bar","candlestick","scatter"],dO=nO.extend({type:"dataZoom.slider",init:function(t,e){this._displayables={},this._orient,this._range,this._handleEnds,this._size,this._handleWidth,this._handleHeight,this._location,this._dragging,this._dataShadowInfo,this.api=e},render:function(t,e,i,n){dO.superApply(this,"render",arguments),Nr(this,"_dispatchZoomAction",this.dataZoomModel.get("throttle"),"fixRate"),this._orient=t.get("orient"),!1!==this.dataZoomModel.get("show")?(n&&"dataZoom"===n.type&&n.from===this.uid||this._buildView(),this._updateView()):this.group.removeAll()},remove:function(){dO.superApply(this,"remove",arguments),Or(this,"_dispatchZoomAction")},dispose:function(){dO.superApply(this,"dispose",arguments),Or(this,"_dispatchZoomAction")},_buildView:function(){var t=this.group;t.removeAll(),this._resetLocation(),this._resetInterval();var e=this._displayables.barGroup=new tb;this._renderBackground(),this._renderHandle(),this._renderDataShadow(),t.add(e),this._positionGroup()},_resetLocation:function(){var t=this.dataZoomModel,e=this.api,i=this._findCoordRect(),n={width:e.getWidth(),height:e.getHeight()},o=this._orient===uO?{right:n.width-i.x-i.width,top:n.height-30-7,width:i.width,height:30}:{right:7,top:i.y,width:30,height:i.height},a=ga(t.option);d(["right","top","width","height"],function(t){"ph"===a[t]&&(a[t]=o[t])});var r=ca(a,n,t.padding);this._location={x:r.x,y:r.y},this._size=[r.width,r.height],"vertical"===this._orient&&this._size.reverse()},_positionGroup:function(){var t=this.group,e=this._location,i=this._orient,n=this.dataZoomModel.getFirstTargetAxisModel(),o=n&&n.get("inverse"),a=this._displayables.barGroup,r=(this._dataShadowInfo||{}).otherAxisInverse;a.attr(i!==uO||o?i===uO&&o?{scale:r?[-1,1]:[-1,-1]}:"vertical"!==i||o?{scale:r?[-1,-1]:[-1,1],rotation:Math.PI/2}:{scale:r?[1,-1]:[1,1],rotation:Math.PI/2}:{scale:r?[1,1]:[1,-1]});var s=t.getBoundingRect([a]);t.attr("position",[e.x-s.x,e.y-s.y])},_getViewExtent:function(){return[0,this._size[0]]},_renderBackground:function(){var t=this.dataZoomModel,e=this._size,i=this._displayables.barGroup;i.add(new oO({silent:!0,shape:{x:0,y:0,width:e[0],height:e[1]},style:{fill:t.get("backgroundColor")},z2:-40})),i.add(new oO({shape:{x:0,y:0,width:e[0],height:e[1]},style:{fill:"transparent"},z2:0,onclick:m(this._onClickPanelClick,this)}))},_renderDataShadow:function(){var t=this._dataShadowInfo=this._prepareDataShadowInfo();if(t){var e=this._size,i=t.series,n=i.getRawData(),o=i.getShadowDim?i.getShadowDim():t.otherDim;if(null!=o){var a=n.getDataExtent(o),s=.3*(a[1]-a[0]);a=[a[0]-s,a[1]+s];var l,u=[0,e[1]],h=[0,e[0]],c=[[e[0],0],[0,0]],d=[],f=h[1]/(n.count()-1),p=0,g=Math.round(n.count()/e[0]);n.each([o],function(t,e){if(g>0&&e%g)p+=f;else{var i=null==t||isNaN(t)||""===t,n=i?0:aO(t,a,u,!0);i&&!l&&e?(c.push([c[c.length-1][0],0]),d.push([d[d.length-1][0],0])):!i&&l&&(c.push([p,0]),d.push([p,0])),c.push([p,n]),d.push([p,n]),p+=f,l=i}});var m=this.dataZoomModel;this._displayables.barGroup.add(new pM({shape:{points:c},style:r({fill:m.get("dataBackgroundColor")},m.getModel("dataBackground.areaStyle").getAreaStyle()),silent:!0,z2:-20})),this._displayables.barGroup.add(new gM({shape:{points:d},style:m.getModel("dataBackground.lineStyle").getLineStyle(),silent:!0,z2:-19}))}}},_prepareDataShadowInfo:function(){var t=this.dataZoomModel,e=t.get("showDataShadow");if(!1!==e){var i,n=this.ecModel;return t.eachTargetAxis(function(o,a){d(t.getAxisProxy(o.name,a).getTargetSeriesModels(),function(t){if(!(i||!0!==e&&l(cO,t.get("type"))<0)){var r,s=n.getComponent(o.axis,a).axis,u=Gy(o.name),h=t.coordinateSystem;null!=u&&h.getOtherAxis&&(r=h.getOtherAxis(s).inverse),u=t.getData().mapDimension(u),i={thisAxis:s,series:t,thisDim:o.name,otherDim:u,otherAxisInverse:r}}},this)},this),i}},_renderHandle:function(){var t=this._displayables,e=t.handles=[],i=t.handleLabels=[],n=this._displayables.barGroup,o=this._size,a=this.dataZoomModel;n.add(t.filler=new oO({draggable:!0,cursor:Fy(this._orient),drift:sO(this._onDragMove,this,"all"),onmousemove:function(t){mw(t.event)},ondragstart:sO(this._showDataInfo,this,!0),ondragend:sO(this._onDragEnd,this),onmouseover:sO(this._showDataInfo,this,!0),onmouseout:sO(this._showDataInfo,this,!1),style:{fill:a.get("fillerColor"),textPosition:"inside"}})),n.add(new oO($n({silent:!0,shape:{x:0,y:0,width:o[0],height:o[1]},style:{stroke:a.get("dataBackgroundColor")||a.get("borderColor"),lineWidth:1,fill:"rgba(0,0,0,0)"}}))),lO([0,1],function(t){var o=Po(a.get("handleIcon"),{cursor:Fy(this._orient),draggable:!0,drift:sO(this._onDragMove,this,t),onmousemove:function(t){mw(t.event)},ondragend:sO(this._onDragEnd,this),onmouseover:sO(this._showDataInfo,this,!0),onmouseout:sO(this._showDataInfo,this,!1)},{x:-1,y:0,width:2,height:2}),r=o.getBoundingRect();this._handleHeight=Vo(a.get("handleSize"),this._size[1]),this._handleWidth=r.width/r.height*this._handleHeight,o.setStyle(a.getModel("handleStyle").getItemStyle());var s=a.get("handleColor");null!=s&&(o.style.fill=s),n.add(e[t]=o);var l=a.textStyleModel;this.group.add(i[t]=new rM({silent:!0,invisible:!0,style:{x:0,y:0,text:"",textVerticalAlign:"middle",textAlign:"center",textFill:l.getTextColor(),textFont:l.getFont()},z2:10}))},this)},_resetInterval:function(){var t=this._range=this.dataZoomModel.getPercentRange(),e=this._getViewExtent();this._handleEnds=[aO(t[0],[0,100],e,!0),aO(t[1],[0,100],e,!0)]},_updateInterval:function(t,e){var i=this.dataZoomModel,n=this._handleEnds,o=this._getViewExtent(),a=i.findRepresentativeAxisProxy().getMinMaxSpan(),r=[0,100];QL(e,n,o,i.get("zoomLock")?"all":t,null!=a.minSpan?aO(a.minSpan,r,o,!0):null,null!=a.maxSpan?aO(a.maxSpan,r,o,!0):null);var s=this._range,l=this._range=rO([aO(n[0],o,r,!0),aO(n[1],o,r,!0)]);return!s||s[0]!==l[0]||s[1]!==l[1]},_updateView:function(t){var e=this._displayables,i=this._handleEnds,n=rO(i.slice()),o=this._size;lO([0,1],function(t){var n=e.handles[t],a=this._handleHeight;n.attr({scale:[a/2,a/2],position:[i[t],o[1]/2-a/2]})},this),e.filler.setShape({x:n[0],y:0,width:n[1]-n[0],height:o[1]}),this._updateDataInfo(t)},_updateDataInfo:function(t){function e(t){var e=Ao(n.handles[t].parent,this.group),i=Co(0===t?"right":"left",e),s=this._handleWidth/2+hO,l=Do([c[t]+(0===t?-s:s),this._size[1]/2],e);o[t].setStyle({x:l[0],y:l[1],textVerticalAlign:a===uO?"middle":i,textAlign:a===uO?i:"center",text:r[t]})}var i=this.dataZoomModel,n=this._displayables,o=n.handleLabels,a=this._orient,r=["",""];if(i.get("showDetail")){var s=i.findRepresentativeAxisProxy();if(s){var l=s.getAxisModel().axis,u=this._range,h=t?s.calculateDataWindow({start:u[0],end:u[1]}).valueWindow:s.getDataValueWindow();r=[this._formatLabel(h[0],l),this._formatLabel(h[1],l)]}}var c=rO(this._handleEnds.slice());e.call(this,0),e.call(this,1)},_formatLabel:function(t,e){var i=this.dataZoomModel,n=i.get("labelFormatter"),o=i.get("labelPrecision");null!=o&&"auto"!==o||(o=e.getPixelPrecision());var a=null==t||isNaN(t)?"":"category"===e.type||"time"===e.type?e.scale.getLabel(Math.round(t)):t.toFixed(Math.min(o,20));return x(n)?n(t,a):_(n)?n.replace("{value}",a):a},_showDataInfo:function(t){t=this._dragging||t;var e=this._displayables.handleLabels;e[0].attr("invisible",!t),e[1].attr("invisible",!t)},_onDragMove:function(t,e,i){this._dragging=!0;var n=Do([e,i],this._displayables.barGroup.getLocalTransform(),!0),o=this._updateInterval(t,n[0]),a=this.dataZoomModel.get("realtime");this._updateView(!a),o&&a&&this._dispatchZoomAction()},_onDragEnd:function(){this._dragging=!1,this._showDataInfo(!1),!this.dataZoomModel.get("realtime")&&this._dispatchZoomAction()},_onClickPanelClick:function(t){var e=this._size,i=this._displayables.barGroup.transformCoordToLocal(t.offsetX,t.offsetY);if(!(i[0]<0||i[0]>e[0]||i[1]<0||i[1]>e[1])){var n=this._handleEnds,o=(n[0]+n[1])/2,a=this._updateInterval("all",i[0]-o);this._updateView(),a&&this._dispatchZoomAction()}},_dispatchZoomAction:function(){var t=this._range;this.api.dispatchAction({type:"dataZoom",from:this.uid,dataZoomId:this.dataZoomModel.id,start:t[0],end:t[1]})},_findCoordRect:function(){var t;if(lO(this.getTargetCoordInfo(),function(e){if(!t&&e.length){var i=e[0].model.coordinateSystem;t=i.getRect&&i.getRect()}}),!t){var e=this.api.getWidth(),i=this.api.getHeight();t={x:.2*e,y:.2*i,width:.6*e,height:.6*i}}return t}});iO.extend({type:"dataZoom.inside",defaultOption:{disabled:!1,zoomLock:!1,zoomOnMouseWheel:!0,moveOnMouseMove:!0,moveOnMouseWheel:!1,preventDefaultMouseMove:!0}});var fO="\0_ec_dataZoom_roams",pO=m,gO=nO.extend({type:"dataZoom.inside",init:function(t,e){this._range},render:function(t,e,i,n){gO.superApply(this,"render",arguments),this._range=t.getPercentRange(),d(this.getTargetCoordInfo(),function(e,n){var o=f(e,function(t){return Zy(t.model)});d(e,function(e){var a=e.model,r={};d(["pan","zoom","scrollMove"],function(t){r[t]=pO(mO[t],this,e,n)},this),Wy(i,{coordId:Zy(a),allCoordIds:o,containsPoint:function(t,e,i){return a.coordinateSystem.containPoint([e,i])},dataZoomId:t.id,dataZoomModel:t,getRange:r})},this)},this)},dispose:function(){Hy(this.api,this.dataZoomModel.id),gO.superApply(this,"dispose",arguments),this._range=null}}),mO={zoom:function(t,e,i,n){var o=this._range,a=o.slice(),r=t.axisModels[0];if(r){var s=vO[e](null,[n.originX,n.originY],r,i,t),l=(s.signal>0?s.pixelStart+s.pixelLength-s.pixel:s.pixel-s.pixelStart)/s.pixelLength*(a[1]-a[0])+a[0],u=Math.max(1/n.scale,0);a[0]=(a[0]-l)*u+l,a[1]=(a[1]-l)*u+l;var h=this.dataZoomModel.findRepresentativeAxisProxy().getMinMaxSpan();return QL(0,a,[0,100],0,h.minSpan,h.maxSpan),this._range=a,o[0]!==a[0]||o[1]!==a[1]?a:void 0}},pan:Ky(function(t,e,i,n,o,a){var r=vO[n]([a.oldX,a.oldY],[a.newX,a.newY],e,o,i);return r.signal*(t[1]-t[0])*r.pixel/r.pixelLength}),scrollMove:Ky(function(t,e,i,n,o,a){return vO[n]([0,0],[a.scrollDelta,a.scrollDelta],e,o,i).signal*(t[1]-t[0])*a.scrollDelta})},vO={grid:function(t,e,i,n,o){var a=i.axis,r={},s=o.model.coordinateSystem.getRect();return t=t||[0,0],"x"===a.dim?(r.pixel=e[0]-t[0],r.pixelLength=s.width,r.pixelStart=s.x,r.signal=a.inverse?1:-1):(r.pixel=e[1]-t[1],r.pixelLength=s.height,r.pixelStart=s.y,r.signal=a.inverse?-1:1),r},polar:function(t,e,i,n,o){var a=i.axis,r={},s=o.model.coordinateSystem,l=s.getRadiusAxis().getExtent(),u=s.getAngleAxis().getExtent();return t=t?s.pointToCoord(t):[0,0],e=s.pointToCoord(e),"radiusAxis"===i.mainType?(r.pixel=e[0]-t[0],r.pixelLength=l[1]-l[0],r.pixelStart=l[0],r.signal=a.inverse?1:-1):(r.pixel=e[1]-t[1],r.pixelLength=u[1]-u[0],r.pixelStart=u[0],r.signal=a.inverse?-1:1),r},singleAxis:function(t,e,i,n,o){var a=i.axis,r=o.model.coordinateSystem.getRect(),s={};return t=t||[0,0],"horizontal"===a.orient?(s.pixel=e[0]-t[0],s.pixelLength=r.width,s.pixelStart=r.x,s.signal=a.inverse?1:-1):(s.pixel=e[1]-t[1],s.pixelLength=r.height,s.pixelStart=r.y,s.signal=a.inverse?-1:1),s}};Os({getTargetSeries:function(t){var e=R();return t.eachComponent("dataZoom",function(t){t.eachTargetAxis(function(t,i,n){d(n.getAxisProxy(t.name,i).getTargetSeriesModels(),function(t){e.set(t.uid,t)})})}),e},modifyOutputEnd:!0,overallReset:function(t,e){t.eachComponent("dataZoom",function(t){t.eachTargetAxis(function(t,i,n){n.getAxisProxy(t.name,i).reset(n,e)}),t.eachTargetAxis(function(t,i,n){n.getAxisProxy(t.name,i).filterData(n,e)})}),t.eachComponent("dataZoom",function(t){var e=t.findRepresentativeAxisProxy(),i=e.getDataPercentWindow(),n=e.getDataValueWindow();t.setRawRange({start:i[0],end:i[1],startValue:n[0],endValue:n[1]},!0)})}}),Es("dataZoom",function(t,e){var i=Ny(m(e.eachComponent,e,"dataZoom"),KN,function(t,e){return t.get(e.axisIndex)}),n=[];e.eachComponent({mainType:"dataZoom",query:t},function(t,e){n.push.apply(n,i(t).nodes)}),d(n,function(e,i){e.setRawRange({start:t.start,end:t.end,startValue:t.startValue,endValue:t.endValue})})});var yO=d,xO=function(t){var e=t&&t.visualMap;y(e)||(e=e?[e]:[]),yO(e,function(t){if(t){$y(t,"splitList")&&!$y(t,"pieces")&&(t.pieces=t.splitList,delete t.splitList);var e=t.pieces;e&&y(e)&&yO(e,function(t){w(t)&&($y(t,"start")&&!$y(t,"min")&&(t.min=t.start),$y(t,"end")&&!$y(t,"max")&&(t.max=t.end))})}})};lI.registerSubTypeDefaulter("visualMap",function(t){return t.categories||(t.pieces?t.pieces.length>0:t.splitNumber>0)&&!t.calculable?"piecewise":"continuous"});var _O=VT.VISUAL.COMPONENT;Bs(_O,{createOnAllSeries:!0,reset:function(t,e){var i=[];return e.eachComponent("visualMap",function(e){var n=t.pipelineContext;!e.isTargetSeries(t)||n&&n.large||i.push(ny(e.stateList,e.targetVisuals,m(e.getValueState,e),e.getDataDimension(t.getData())))}),i}}),Bs(_O,{createOnAllSeries:!0,reset:function(t,e){var i=t.getData(),n=[];e.eachComponent("visualMap",function(e){if(e.isTargetSeries(t)){var o=e.getVisualMeta(m(Jy,null,t,e))||{stops:[],outerColors:[]},a=e.getDataDimension(i),r=i.getDimensionInfo(a);null!=r&&(o.dimension=r.index,n.push(o))}}),t.getData().setVisual("visualMeta",n)}});var wO={get:function(t,e,n){var o=i((bO[t]||{})[e]);return n&&y(o)?o[o.length-1]:o}},bO={color:{active:["#006edd","#e0ffff"],inactive:["rgba(0,0,0,0)"]},colorHue:{active:[0,360],inactive:[0,0]},colorSaturation:{active:[.3,1],inactive:[0,0]},colorLightness:{active:[.9,.5],inactive:[0,0]},colorAlpha:{active:[.3,1],inactive:[0,0]},opacity:{active:[.3,1],inactive:[0,0]},symbol:{active:["circle","roundRect","diamond"],inactive:["none"]},symbolSize:{active:[10,50],inactive:[0,0]}},SO=hL.mapVisual,MO=hL.eachVisual,IO=y,TO=d,AO=Fo,DO=Bo,CO=B,LO=Fs({type:"visualMap",dependencies:["series"],stateList:["inRange","outOfRange"],replacableOptionKeys:["inRange","outOfRange","target","controller","color"],dataBound:[-1/0,1/0],layoutMode:{type:"box",ignoreSize:!0},defaultOption:{show:!0,zlevel:0,z:4,seriesIndex:"all",min:0,max:200,dimension:null,inRange:null,outOfRange:null,left:0,right:null,top:null,bottom:0,itemWidth:null,itemHeight:null,inverse:!1,orient:"vertical",backgroundColor:"rgba(0,0,0,0)",borderColor:"#ccc",contentColor:"#5793f3",inactiveColor:"#aaa",borderWidth:0,padding:5,textGap:10,precision:0,color:null,formatter:null,text:null,textStyle:{color:"#333"}},init:function(t,e,i){this._dataExtent,this.targetVisuals={},this.controllerVisuals={},this.textStyleModel,this.itemSize,this.mergeDefaultAndTheme(t,i)},optionUpdated:function(t,e){var i=this.option;U_.canvasSupported||(i.realtime=!1),!e&&ey(i,t,this.replacableOptionKeys),this.textStyleModel=this.getModel("textStyle"),this.resetItemSize(),this.completeVisualOption()},resetVisual:function(t){var e=this.stateList;t=m(t,this),this.controllerVisuals=ty(this.option.controller,e,t),this.targetVisuals=ty(this.option.target,e,t)},getTargetSeriesIndices:function(){var t=this.option.seriesIndex,e=[];return null==t||"all"===t?this.ecModel.eachSeries(function(t,i){e.push(i)}):e=Di(t),e},eachTargetSeries:function(t,e){d(this.getTargetSeriesIndices(),function(i){t.call(e,this.ecModel.getSeriesByIndex(i))},this)},isTargetSeries:function(t){var e=!1;return this.eachTargetSeries(function(i){i===t&&(e=!0)}),e},formatValueText:function(t,e,i){function n(t){return t===l[0]?"min":t===l[1]?"max":(+t).toFixed(Math.min(s,20))}var o,a,r=this.option,s=r.precision,l=this.dataBound,u=r.formatter;return i=i||["<",">"],y(t)&&(t=t.slice(),o=!0),a=e?t:o?[n(t[0]),n(t[1])]:n(t),_(u)?u.replace("{value}",o?a[0]:a).replace("{value2}",o?a[1]:a):x(u)?o?u(t[0],t[1]):u(t):o?t[0]===l[0]?i[0]+" "+a[1]:t[1]===l[1]?i[1]+" "+a[0]:a[0]+" - "+a[1]:a},resetExtent:function(){var t=this.option,e=AO([t.min,t.max]);this._dataExtent=e},getDataDimension:function(t){var e=this.option.dimension,i=t.dimensions;if(null!=e||i.length){if(null!=e)return t.getDimension(e);for(var n=t.dimensions,o=n.length-1;o>=0;o--){var a=n[o];if(!t.getDimensionInfo(a).isCalculationCoord)return a}}},getExtent:function(){return this._dataExtent.slice()},completeVisualOption:function(){function t(t){IO(o.color)&&!t.inRange&&(t.inRange={color:o.color.slice().reverse()}),t.inRange=t.inRange||{color:e.get("gradientColor")},TO(this.stateList,function(e){var i=t[e];if(_(i)){var n=wO.get(i,"active",l);n?(t[e]={},t[e][i]=n):delete t[e]}},this)}var e=this.ecModel,o=this.option,a={inRange:o.inRange,outOfRange:o.outOfRange},r=o.target||(o.target={}),s=o.controller||(o.controller={});n(r,a),n(s,a);var l=this.isCategory();t.call(this,r),t.call(this,s),function(t,e,i){var n=t[e],o=t[i];n&&!o&&(o=t[i]={},TO(n,function(t,e){if(hL.isValidType(e)){var i=wO.get(e,"inactive",l);null!=i&&(o[e]=i,"color"!==e||o.hasOwnProperty("opacity")||o.hasOwnProperty("colorAlpha")||(o.opacity=[0,0]))}}))}.call(this,r,"inRange","outOfRange"),function(t){var e=(t.inRange||{}).symbol||(t.outOfRange||{}).symbol,n=(t.inRange||{}).symbolSize||(t.outOfRange||{}).symbolSize,o=this.get("inactiveColor");TO(this.stateList,function(a){var r=this.itemSize,s=t[a];s||(s=t[a]={color:l?o:[o]}),null==s.symbol&&(s.symbol=e&&i(e)||(l?"roundRect":["roundRect"])),null==s.symbolSize&&(s.symbolSize=n&&i(n)||(l?r[0]:[r[0],r[0]])),s.symbol=SO(s.symbol,function(t){return"none"===t||"square"===t?"roundRect":t});var u=s.symbolSize;if(null!=u){var h=-1/0;MO(u,function(t){t>h&&(h=t)}),s.symbolSize=SO(u,function(t){return DO(t,[0,h],[0,r[0]],!0)})}},this)}.call(this,s)},resetItemSize:function(){this.itemSize=[parseFloat(this.get("itemWidth")),parseFloat(this.get("itemHeight"))]},isCategory:function(){return!!this.option.categories},setSelected:CO,getValueState:CO,getVisualMeta:CO}),kO=[20,140],PO=LO.extend({type:"visualMap.continuous",defaultOption:{align:"auto",calculable:!1,range:null,realtime:!0,itemHeight:null,itemWidth:null,hoverLink:!0,hoverLinkDataSize:null,hoverLinkOnHandle:null},optionUpdated:function(t,e){PO.superApply(this,"optionUpdated",arguments),this.resetExtent(),this.resetVisual(function(t){t.mappingMethod="linear",t.dataExtent=this.getExtent()}),this._resetRange()},resetItemSize:function(){PO.superApply(this,"resetItemSize",arguments);var t=this.itemSize;"horizontal"===this._orient&&t.reverse(),(null==t[0]||isNaN(t[0]))&&(t[0]=kO[0]),(null==t[1]||isNaN(t[1]))&&(t[1]=kO[1])},_resetRange:function(){var t=this.getExtent(),e=this.option.range;!e||e.auto?(t.auto=1,this.option.range=t):y(e)&&(e[0]>e[1]&&e.reverse(),e[0]=Math.max(e[0],t[0]),e[1]=Math.min(e[1],t[1]))},completeVisualOption:function(){LO.prototype.completeVisualOption.apply(this,arguments),d(this.stateList,function(t){var e=this.option.controller[t].symbolSize;e&&e[0]!==e[1]&&(e[0]=0)},this)},setSelected:function(t){this.option.range=t.slice(),this._resetRange()},getSelected:function(){var t=this.getExtent(),e=Fo((this.get("range")||[]).slice());return e[0]>t[1]&&(e[0]=t[1]),e[1]>t[1]&&(e[1]=t[1]),e[0]<t[0]&&(e[0]=t[0]),e[1]<t[0]&&(e[1]=t[0]),e},getValueState:function(t){var e=this.option.range,i=this.getExtent();return(e[0]<=i[0]||e[0]<=t)&&(e[1]>=i[1]||t<=e[1])?"inRange":"outOfRange"},findTargetDataIndices:function(t){var e=[];return this.eachTargetSeries(function(i){var n=[],o=i.getData();o.each(this.getDataDimension(o),function(e,i){t[0]<=e&&e<=t[1]&&n.push(i)},this),e.push({seriesId:i.id,dataIndex:n})},this),e},getVisualMeta:function(t){function e(e,i){o.push({value:e,color:t(e,i)})}for(var i=Qy(0,0,this.getExtent()),n=Qy(0,0,this.option.range.slice()),o=[],a=0,r=0,s=n.length,l=i.length;r<l&&(!n.length||i[r]<=n[0]);r++)i[r]<n[a]&&e(i[r],"outOfRange");for(u=1;a<s;a++,u=0)u&&o.length&&e(n[a],"outOfRange"),e(n[a],"inRange");for(var u=1;r<l;r++)(!n.length||n[n.length-1]<i[r])&&(u&&(o.length&&e(o[o.length-1].value,"outOfRange"),u=0),e(i[r],"outOfRange"));var h=o.length;return{stops:o,outerColors:[h?o[0].color:"transparent",h?o[h-1].color:"transparent"]}}}),NO=Ws({type:"visualMap",autoPositionValues:{left:1,right:1,top:1,bottom:1},init:function(t,e){this.ecModel=t,this.api=e,this.visualMapModel},render:function(t,e,i,n){this.visualMapModel=t,!1!==t.get("show")?this.doRender.apply(this,arguments):this.group.removeAll()},renderBackground:function(t){var e=this.visualMapModel,i=qM(e.get("padding")||0),n=t.getBoundingRect();t.add(new yM({z2:-1,silent:!0,shape:{x:n.x-i[3],y:n.y-i[0],width:n.width+i[3]+i[1],height:n.height+i[0]+i[2]},style:{fill:e.get("backgroundColor"),stroke:e.get("borderColor"),lineWidth:e.get("borderWidth")}}))},getControllerVisual:function(t,e,i){function n(t){return s[t]}function o(t,e){s[t]=e}var a=(i=i||{}).forceState,r=this.visualMapModel,s={};if("symbol"===e&&(s.symbol=r.get("itemSymbol")),"color"===e){var l=r.get("contentColor");s.color=l}var u=r.controllerVisuals[a||r.getValueState(t)];return d(hL.prepareVisualTypes(u),function(a){var r=u[a];i.convertOpacityToAlpha&&"opacity"===a&&(a="colorAlpha",r=u.__alphaForOpacity),hL.dependsOn(a,e)&&r&&r.applyVisual(t,n,o)}),s[e]},positionGroup:function(t){var e=this.visualMapModel,i=this.api;da(t,e.getBoxLayoutParams(),{width:i.getWidth(),height:i.getHeight()})},doRender:B}),OO=Bo,EO=d,RO=Math.min,zO=Math.max,BO=12,VO=6,GO=NO.extend({type:"visualMap.continuous",init:function(){GO.superApply(this,"init",arguments),this._shapes={},this._dataInterval=[],this._handleEnds=[],this._orient,this._useHandle,this._hoverLinkDataIndices=[],this._dragging,this._hovering},doRender:function(t,e,i,n){n&&"selectDataRange"===n.type&&n.from===this.uid||this._buildView()},_buildView:function(){this.group.removeAll();var t=this.visualMapModel,e=this.group;this._orient=t.get("orient"),this._useHandle=t.get("calculable"),this._resetInterval(),this._renderBar(e);var i=t.get("text");this._renderEndsText(e,i,0),this._renderEndsText(e,i,1),this._updateView(!0),this.renderBackground(e),this._updateView(),this._enableHoverLinkToSeries(),this._enableHoverLinkFromSeries(),this.positionGroup(e)},_renderEndsText:function(t,e,i){if(e){var n=e[1-i];n=null!=n?n+"":"";var o=this.visualMapModel,a=o.get("textGap"),r=o.itemSize,s=this._shapes.barGroup,l=this._applyTransform([r[0]/2,0===i?-a:r[1]+a],s),u=this._applyTransform(0===i?"bottom":"top",s),h=this._orient,c=this.visualMapModel.textStyleModel;this.group.add(new rM({style:{x:l[0],y:l[1],textVerticalAlign:"horizontal"===h?"middle":u,textAlign:"horizontal"===h?u:"center",text:n,textFont:c.getFont(),textFill:c.getTextColor()}}))}},_renderBar:function(t){var e=this.visualMapModel,i=this._shapes,n=e.itemSize,o=this._orient,a=this._useHandle,r=tx(e,this.api,n),s=i.barGroup=this._createBarGroup(r);s.add(i.outOfRange=ix()),s.add(i.inRange=ix(null,a?sx(this._orient):null,m(this._dragHandle,this,"all",!1),m(this._dragHandle,this,"all",!0)));var l=e.textStyleModel.getTextRect("国"),u=zO(l.width,l.height);a&&(i.handleThumbs=[],i.handleLabels=[],i.handleLabelPoints=[],this._createHandle(s,0,n,u,o,r),this._createHandle(s,1,n,u,o,r)),this._createIndicator(s,n,u,o),t.add(s)},_createHandle:function(t,e,i,n,o){var a=m(this._dragHandle,this,e,!1),r=m(this._dragHandle,this,e,!0),s=ix(nx(e,n),sx(this._orient),a,r);s.position[0]=i[0],t.add(s);var l=this.visualMapModel.textStyleModel,u=new rM({draggable:!0,drift:a,onmousemove:function(t){mw(t.event)},ondragend:r,style:{x:0,y:0,text:"",textFont:l.getFont(),textFill:l.getTextColor()}});this.group.add(u);var h=["horizontal"===o?n/2:1.5*n,"horizontal"===o?0===e?-1.5*n:1.5*n:0===e?-n/2:n/2],c=this._shapes;c.handleThumbs[e]=s,c.handleLabelPoints[e]=h,c.handleLabels[e]=u},_createIndicator:function(t,e,i,n){var o=ix([[0,0]],"move");o.position[0]=e[0],o.attr({invisible:!0,silent:!0}),t.add(o);var a=this.visualMapModel.textStyleModel,r=new rM({silent:!0,invisible:!0,style:{x:0,y:0,text:"",textFont:a.getFont(),textFill:a.getTextColor()}});this.group.add(r);var s=["horizontal"===n?i/2:VO+3,0],l=this._shapes;l.indicator=o,l.indicatorLabel=r,l.indicatorLabelPoint=s},_dragHandle:function(t,e,i,n){if(this._useHandle){if(this._dragging=!e,!e){var o=this._applyTransform([i,n],this._shapes.barGroup,!0);this._updateInterval(t,o[1]),this._updateView()}e===!this.visualMapModel.get("realtime")&&this.api.dispatchAction({type:"selectDataRange",from:this.uid,visualMapId:this.visualMapModel.id,selected:this._dataInterval.slice()}),e?!this._hovering&&this._clearHoverLinkToSeries():rx(this.visualMapModel)&&this._doHoverLinkToSeries(this._handleEnds[t],!1)}},_resetInterval:function(){var t=this.visualMapModel,e=this._dataInterval=t.getSelected(),i=t.getExtent(),n=[0,t.itemSize[1]];this._handleEnds=[OO(e[0],i,n,!0),OO(e[1],i,n,!0)]},_updateInterval:function(t,e){e=e||0;var i=this.visualMapModel,n=this._handleEnds,o=[0,i.itemSize[1]];QL(e,n,o,t,0);var a=i.getExtent();this._dataInterval=[OO(n[0],o,a,!0),OO(n[1],o,a,!0)]},_updateView:function(t){var e=this.visualMapModel,i=e.getExtent(),n=this._shapes,o=[0,e.itemSize[1]],a=t?o:this._handleEnds,r=this._createBarVisual(this._dataInterval,i,a,"inRange"),s=this._createBarVisual(i,i,o,"outOfRange");n.inRange.setStyle({fill:r.barColor,opacity:r.opacity}).setShape("points",r.barPoints),n.outOfRange.setStyle({fill:s.barColor,opacity:s.opacity}).setShape("points",s.barPoints),this._updateHandle(a,r)},_createBarVisual:function(t,e,i,n){var o={forceState:n,convertOpacityToAlpha:!0},a=this._makeColorGradient(t,o),r=[this.getControllerVisual(t[0],"symbolSize",o),this.getControllerVisual(t[1],"symbolSize",o)],s=this._createBarPoints(i,r);return{barColor:new TM(0,0,0,1,a),barPoints:s,handlesColor:[a[0].color,a[a.length-1].color]}},_makeColorGradient:function(t,e){var i=[],n=(t[1]-t[0])/100;i.push({color:this.getControllerVisual(t[0],"color",e),offset:0});for(var o=1;o<100;o++){var a=t[0]+n*o;if(a>t[1])break;i.push({color:this.getControllerVisual(a,"color",e),offset:o/100})}return i.push({color:this.getControllerVisual(t[1],"color",e),offset:1}),i},_createBarPoints:function(t,e){var i=this.visualMapModel.itemSize;return[[i[0]-e[0],t[0]],[i[0],t[0]],[i[0],t[1]],[i[0]-e[1],t[1]]]},_createBarGroup:function(t){var e=this._orient,i=this.visualMapModel.get("inverse");return new tb("horizontal"!==e||i?"horizontal"===e&&i?{scale:"bottom"===t?[-1,1]:[1,1],rotation:-Math.PI/2}:"vertical"!==e||i?{scale:"left"===t?[1,1]:[-1,1]}:{scale:"left"===t?[1,-1]:[-1,-1]}:{scale:"bottom"===t?[1,1]:[-1,1],rotation:Math.PI/2})},_updateHandle:function(t,e){if(this._useHandle){var i=this._shapes,n=this.visualMapModel,o=i.handleThumbs,a=i.handleLabels;EO([0,1],function(r){var s=o[r];s.setStyle("fill",e.handlesColor[r]),s.position[1]=t[r];var l=Do(i.handleLabelPoints[r],Ao(s,this.group));a[r].setStyle({x:l[0],y:l[1],text:n.formatValueText(this._dataInterval[r]),textVerticalAlign:"middle",textAlign:this._applyTransform("horizontal"===this._orient?0===r?"bottom":"top":"left",i.barGroup)})},this)}},_showIndicator:function(t,e,i,n){var o=this.visualMapModel,a=o.getExtent(),r=o.itemSize,s=[0,r[1]],l=OO(t,a,s,!0),u=this._shapes,h=u.indicator;if(h){h.position[1]=l,h.attr("invisible",!1),h.setShape("points",ox(!!i,n,l,r[1]));var c={convertOpacityToAlpha:!0},d=this.getControllerVisual(t,"color",c);h.setStyle("fill",d);var f=Do(u.indicatorLabelPoint,Ao(h,this.group)),p=u.indicatorLabel;p.attr("invisible",!1);var g=this._applyTransform("left",u.barGroup),m=this._orient;p.setStyle({text:(i||"")+o.formatValueText(e),textVerticalAlign:"horizontal"===m?g:"middle",textAlign:"horizontal"===m?"center":g,x:f[0],y:f[1]})}},_enableHoverLinkToSeries:function(){var t=this;this._shapes.barGroup.on("mousemove",function(e){if(t._hovering=!0,!t._dragging){var i=t.visualMapModel.itemSize,n=t._applyTransform([e.offsetX,e.offsetY],t._shapes.barGroup,!0,!0);n[1]=RO(zO(0,n[1]),i[1]),t._doHoverLinkToSeries(n[1],0<=n[0]&&n[0]<=i[0])}}).on("mouseout",function(){t._hovering=!1,!t._dragging&&t._clearHoverLinkToSeries()})},_enableHoverLinkFromSeries:function(){var t=this.api.getZr();this.visualMapModel.option.hoverLink?(t.on("mouseover",this._hoverLinkFromSeriesMouseOver,this),t.on("mouseout",this._hideIndicator,this)):this._clearHoverLinkFromSeries()},_doHoverLinkToSeries:function(t,e){var i=this.visualMapModel,n=i.itemSize;if(i.option.hoverLink){var o=[0,n[1]],a=i.getExtent();t=RO(zO(o[0],t),o[1]);var r=ax(i,a,o),s=[t-r,t+r],l=OO(t,o,a,!0),u=[OO(s[0],o,a,!0),OO(s[1],o,a,!0)];s[0]<o[0]&&(u[0]=-1/0),s[1]>o[1]&&(u[1]=1/0),e&&(u[0]===-1/0?this._showIndicator(l,u[1],"< ",r):u[1]===1/0?this._showIndicator(l,u[0],"> ",r):this._showIndicator(l,l,"≈ ",r));var h=this._hoverLinkDataIndices,c=[];(e||rx(i))&&(c=this._hoverLinkDataIndices=i.findTargetDataIndices(u));var d=Ri(h,c);this._dispatchHighDown("downplay",ex(d[0])),this._dispatchHighDown("highlight",ex(d[1]))}},_hoverLinkFromSeriesMouseOver:function(t){var e=t.target,i=this.visualMapModel;if(e&&null!=e.dataIndex){var n=this.ecModel.getSeriesByIndex(e.seriesIndex);if(i.isTargetSeries(n)){var o=n.getData(e.dataType),a=o.get(i.getDataDimension(o),e.dataIndex,!0);isNaN(a)||this._showIndicator(a,a)}}},_hideIndicator:function(){var t=this._shapes;t.indicator&&t.indicator.attr("invisible",!0),t.indicatorLabel&&t.indicatorLabel.attr("invisible",!0)},_clearHoverLinkToSeries:function(){this._hideIndicator();var t=this._hoverLinkDataIndices;this._dispatchHighDown("downplay",ex(t)),t.length=0},_clearHoverLinkFromSeries:function(){this._hideIndicator();var t=this.api.getZr();t.off("mouseover",this._hoverLinkFromSeriesMouseOver),t.off("mouseout",this._hideIndicator)},_applyTransform:function(t,e,i,n){var o=Ao(e,n?null:this.group);return zM[y(t)?"applyTransform":"transformDirection"](t,o,i)},_dispatchHighDown:function(t,e){e&&e.length&&this.api.dispatchAction({type:t,batch:e})},dispose:function(){this._clearHoverLinkFromSeries(),this._clearHoverLinkToSeries()},remove:function(){this._clearHoverLinkFromSeries(),this._clearHoverLinkToSeries()}});Es({type:"selectDataRange",event:"dataRangeSelected",update:"update"},function(t,e){e.eachComponent({mainType:"visualMap",query:t},function(e){e.setSelected(t.selected)})}),Ns(xO);var FO=LO.extend({type:"visualMap.piecewise",defaultOption:{selected:null,minOpen:!1,maxOpen:!1,align:"auto",itemWidth:20,itemHeight:14,itemSymbol:"roundRect",pieceList:null,categories:null,splitNumber:5,selectedMode:"multiple",itemGap:10,hoverLink:!0,showLabel:null},optionUpdated:function(t,e){FO.superApply(this,"optionUpdated",arguments),this._pieceList=[],this.resetExtent();var n=this._mode=this._determineMode();WO[this._mode].call(this),this._resetSelected(t,e);var o=this.option.categories;this.resetVisual(function(t,e){"categories"===n?(t.mappingMethod="category",t.categories=i(o)):(t.dataExtent=this.getExtent(),t.mappingMethod="piecewise",t.pieceList=f(this._pieceList,function(t){var t=i(t);return"inRange"!==e&&(t.visual=null),t}))})},completeVisualOption:function(){function t(t,e,i){return t&&t[e]&&(w(t[e])?t[e].hasOwnProperty(i):t[e]===i)}var e=this.option,i={},n=hL.listVisualTypes(),o=this.isCategory();d(e.pieces,function(t){d(n,function(e){t.hasOwnProperty(e)&&(i[e]=1)})}),d(i,function(i,n){var a=0;d(this.stateList,function(i){a|=t(e,i,n)||t(e.target,i,n)},this),!a&&d(this.stateList,function(t){(e[t]||(e[t]={}))[n]=wO.get(n,"inRange"===t?"active":"inactive",o)})},this),LO.prototype.completeVisualOption.apply(this,arguments)},_resetSelected:function(t,e){var i=this.option,n=this._pieceList,o=(e?i:t).selected||{};if(i.selected=o,d(n,function(t,e){var i=this.getSelectedMapKey(t);o.hasOwnProperty(i)||(o[i]=!0)},this),"single"===i.selectedMode){var a=!1;d(n,function(t,e){var i=this.getSelectedMapKey(t);o[i]&&(a?o[i]=!1:a=!0)},this)}},getSelectedMapKey:function(t){return"categories"===this._mode?t.value+"":t.index+""},getPieceList:function(){return this._pieceList},_determineMode:function(){var t=this.option;return t.pieces&&t.pieces.length>0?"pieces":this.option.categories?"categories":"splitNumber"},setSelected:function(t){this.option.selected=i(t)},getValueState:function(t){var e=hL.findPieceIndex(t,this._pieceList);return null!=e&&this.option.selected[this.getSelectedMapKey(this._pieceList[e])]?"inRange":"outOfRange"},findTargetDataIndices:function(t){var e=[];return this.eachTargetSeries(function(i){var n=[],o=i.getData();o.each(this.getDataDimension(o),function(e,i){hL.findPieceIndex(e,this._pieceList)===t&&n.push(i)},this),e.push({seriesId:i.id,dataIndex:n})},this),e},getRepresentValue:function(t){var e;if(this.isCategory())e=t.value;else if(null!=t.value)e=t.value;else{var i=t.interval||[];e=i[0]===-1/0&&i[1]===1/0?0:(i[0]+i[1])/2}return e},getVisualMeta:function(t){function e(e,a){var r=o.getRepresentValue({interval:e});a||(a=o.getValueState(r));var s=t(r,a);e[0]===-1/0?n[0]=s:e[1]===1/0?n[1]=s:i.push({value:e[0],color:s},{value:e[1],color:s})}if(!this.isCategory()){var i=[],n=[],o=this,a=this._pieceList.slice();if(a.length){var r=a[0].interval[0];r!==-1/0&&a.unshift({interval:[-1/0,r]}),(r=a[a.length-1].interval[1])!==1/0&&a.push({interval:[r,1/0]})}else a.push({interval:[-1/0,1/0]});var s=-1/0;return d(a,function(t){var i=t.interval;i&&(i[0]>s&&e([s,i[0]],"outOfRange"),e(i.slice()),s=i[1])},this),{stops:i,outerColors:n}}}}),WO={splitNumber:function(){var t=this.option,e=this._pieceList,i=Math.min(t.precision,20),n=this.getExtent(),o=t.splitNumber;o=Math.max(parseInt(o,10),1),t.splitNumber=o;for(var a=(n[1]-n[0])/o;+a.toFixed(i)!==a&&i<5;)i++;t.precision=i,a=+a.toFixed(i);var r=0;t.minOpen&&e.push({index:r++,interval:[-1/0,n[0]],close:[0,0]});for(var s=n[0],l=r+o;r<l;s+=a){var u=r===o-1?n[1]:s+a;e.push({index:r++,interval:[s,u],close:[1,1]})}t.maxOpen&&e.push({index:r++,interval:[n[1],1/0],close:[0,0]}),Jo(e),d(e,function(t){t.text=this.formatValueText(t.interval)},this)},categories:function(){var t=this.option;d(t.categories,function(t){this._pieceList.push({text:this.formatValueText(t,!0),value:t})},this),lx(t,this._pieceList)},pieces:function(){var t=this.option,e=this._pieceList;d(t.pieces,function(t,i){w(t)||(t={value:t});var n={text:"",index:i};if(null!=t.label&&(n.text=t.label),t.hasOwnProperty("value")){var o=n.value=t.value;n.interval=[o,o],n.close=[1,1]}else{for(var a=n.interval=[],r=n.close=[0,0],s=[1,0,1],l=[-1/0,1/0],u=[],h=0;h<2;h++){for(var c=[["gte","gt","min"],["lte","lt","max"]][h],d=0;d<3&&null==a[h];d++)a[h]=t[c[d]],r[h]=s[d],u[h]=2===d;null==a[h]&&(a[h]=l[h])}u[0]&&a[1]===1/0&&(r[0]=0),u[1]&&a[0]===-1/0&&(r[1]=0),a[0]===a[1]&&r[0]&&r[1]&&(n.value=a[0])}n.visual=hL.retrieveVisuals(t),e.push(n)},this),lx(t,e),Jo(e),d(e,function(t){var e=t.close,i=[["<","≤"][e[1]],[">","≥"][e[0]]];t.text=t.text||this.formatValueText(null!=t.value?t.value:t.interval,!1,i)},this)}};NO.extend({type:"visualMap.piecewise",doRender:function(){var t=this.group;t.removeAll();var e=this.visualMapModel,i=e.get("textGap"),n=e.textStyleModel,o=n.getFont(),a=n.getTextColor(),r=this._getItemAlign(),s=e.itemSize,l=this._getViewData(),u=l.endsText,h=T(e.get("showLabel",!0),!u);u&&this._renderEndsText(t,u[0],s,h,r),d(l.viewPieceList,function(n){var l=n.piece,u=new tb;u.onclick=m(this._onItemClick,this,l),this._enableHoverLink(u,n.indexInModelPieceList);var c=e.getRepresentValue(l);if(this._createItemSymbol(u,c,[0,0,s[0],s[1]]),h){var d=this.visualMapModel.getValueState(c);u.add(new rM({style:{x:"right"===r?-i:s[0]+i,y:s[1]/2,text:l.text,textVerticalAlign:"middle",textAlign:r,textFont:o,textFill:a,opacity:"outOfRange"===d?.5:1}}))}t.add(u)},this),u&&this._renderEndsText(t,u[1],s,h,r),aI(e.get("orient"),t,e.get("itemGap")),this.renderBackground(t),this.positionGroup(t)},_enableHoverLink:function(t,e){function i(t){var i=this.visualMapModel;i.option.hoverLink&&this.api.dispatchAction({type:t,batch:ex(i.findTargetDataIndices(e))})}t.on("mouseover",m(i,this,"highlight")).on("mouseout",m(i,this,"downplay"))},_getItemAlign:function(){var t=this.visualMapModel,e=t.option;if("vertical"===e.orient)return tx(t,this.api,t.itemSize);var i=e.align;return i&&"auto"!==i||(i="left"),i},_renderEndsText:function(t,e,i,n,o){if(e){var a=new tb,r=this.visualMapModel.textStyleModel;a.add(new rM({style:{x:n?"right"===o?i[0]:0:i[0]/2,y:i[1]/2,textVerticalAlign:"middle",textAlign:n?o:"center",text:e,textFont:r.getFont(),textFill:r.getTextColor()}})),t.add(a)}},_getViewData:function(){var t=this.visualMapModel,e=f(t.getPieceList(),function(t,e){return{piece:t,indexInModelPieceList:e}}),i=t.get("text"),n=t.get("orient"),o=t.get("inverse");return("horizontal"===n?o:!o)?e.reverse():i&&(i=i.slice().reverse()),{viewPieceList:e,endsText:i}},_createItemSymbol:function(t,e,i){t.add(Jl(this.getControllerVisual(e,"symbol"),i[0],i[1],i[2],i[3],this.getControllerVisual(e,"color")))},_onItemClick:function(t){var e=this.visualMapModel,n=e.option,o=i(n.selected),a=e.getSelectedMapKey(t);"single"===n.selectedMode?(o[a]=!0,d(o,function(t,e){o[e]=e===a})):o[a]=!o[a],this.api.dispatchAction({type:"selectDataRange",from:this.uid,visualMapId:this.visualMapModel.id,selected:o})}});Ns(xO);var HO=ta,ZO=ia,UO=Fs({type:"marker",dependencies:["series","grid","polar","geo"],init:function(t,e,i,n){this.mergeDefaultAndTheme(t,i),this.mergeOption(t,i,n.createdBySelf,!0)},isAnimationEnabled:function(){if(U_.node)return!1;var t=this.__hostSeries;return this.getShallow("animation")&&t&&t.isAnimationEnabled()},mergeOption:function(t,e,i,n){var o=this.constructor,r=this.mainType+"Model";i||e.eachSeries(function(t){var i=t.get(this.mainType,!0),s=t[r];i&&i.data?(s?s.mergeOption(i,e,!0):(n&&ux(i),d(i.data,function(t){t instanceof Array?(ux(t[0]),ux(t[1])):ux(t)}),a(s=new o(i,this,e),{mainType:this.mainType,seriesIndex:t.seriesIndex,name:t.name,createdBySelf:!0}),s.__hostSeries=t),t[r]=s):t[r]=null},this)},formatTooltip:function(t){var e=this.getData(),i=this.getRawValue(t),n=y(i)?f(i,HO).join(", "):HO(i),o=e.getName(t),a=ZO(this.name);return(null!=i||o)&&(a+="<br />"),o&&(a+=ZO(o),null!=i&&(a+=" : ")),null!=i&&(a+=ZO(n)),a},getData:function(){return this._data},setData:function(t){this._data=t}});h(UO,ZI),UO.extend({type:"markPoint",defaultOption:{zlevel:0,z:5,symbol:"pin",symbolSize:50,tooltip:{trigger:"item"},label:{show:!0,position:"inside"},itemStyle:{borderWidth:2},emphasis:{label:{show:!0}}}});var XO=l,jO=v,YO={min:jO(dx,"min"),max:jO(dx,"max"),average:jO(dx,"average")},qO=Ws({type:"marker",init:function(){this.markerGroupMap=R()},render:function(t,e,i){var n=this.markerGroupMap;n.each(function(t){t.__keep=!1});var o=this.type+"Model";e.eachSeries(function(t){var n=t[o];n&&this.renderSeries(t,n,e,i)},this),n.each(function(t){!t.__keep&&this.group.remove(t.group)},this)},renderSeries:function(){}});qO.extend({type:"markPoint",updateTransform:function(t,e,i){e.eachSeries(function(t){var e=t.markPointModel;e&&(xx(e.getData(),t,i),this.markerGroupMap.get(t.id).updateLayout(e))},this)},renderSeries:function(t,e,i,n){var o=t.coordinateSystem,a=t.id,r=t.getData(),s=this.markerGroupMap,l=s.get(a)||s.set(a,new Du),u=_x(o,t,e);e.setData(u),xx(e.getData(),t,n),u.each(function(t){var i=u.getItemModel(t),n=i.getShallow("symbolSize");"function"==typeof n&&(n=n(e.getRawValue(t),e.getDataParams(t))),u.setItemVisual(t,{symbolSize:n,color:i.get("itemStyle.color")||r.getVisual("color"),symbol:i.getShallow("symbol")})}),l.updateData(u),this.group.add(l.group),u.eachItemGraphicEl(function(t){t.traverse(function(t){t.dataModel=e})}),l.__keep=!0,l.group.silent=e.get("silent")||t.get("silent")}}),Ns(function(t){t.markPoint=t.markPoint||{}}),UO.extend({type:"markLine",defaultOption:{zlevel:0,z:5,symbol:["circle","arrow"],symbolSize:[8,16],precision:2,tooltip:{trigger:"item"},label:{show:!0,position:"end"},lineStyle:{type:"dashed"},emphasis:{label:{show:!0},lineStyle:{width:3}},animationEasing:"linear"}});var KO=function(t,e,o,r){var s=t.getData(),l=r.type;if(!y(r)&&("min"===l||"max"===l||"average"===l||"median"===l||null!=r.xAxis||null!=r.yAxis)){var u,h;if(null!=r.yAxis||null!=r.xAxis)u=null!=r.yAxis?"y":"x",e.getAxis(u),h=T(r.yAxis,r.xAxis);else{var c=px(r,s,e,t);u=c.valueDataDim,c.valueAxis,h=yx(s,u,l)}var d="x"===u?0:1,f=1-d,p=i(r),g={};p.type=null,p.coord=[],g.coord=[],p.coord[f]=-1/0,g.coord[f]=1/0;var m=o.get("precision");m>=0&&"number"==typeof h&&(h=+h.toFixed(Math.min(m,20))),p.coord[d]=g.coord[d]=h,r=[p,g,{type:l,valueIndex:r.valueIndex,value:h}]}return r=[fx(t,r[0]),fx(t,r[1]),a({},r[2])],r[2].type=r[2].type||"",n(r[2],r[0]),n(r[2],r[1]),r};qO.extend({type:"markLine",updateTransform:function(t,e,i){e.eachSeries(function(t){var e=t.markLineModel;if(e){var n=e.getData(),o=e.__from,a=e.__to;o.each(function(e){Ix(o,e,!0,t,i),Ix(a,e,!1,t,i)}),n.each(function(t){n.setItemLayout(t,[o.getItemLayout(t),a.getItemLayout(t)])}),this.markerGroupMap.get(t.id).updateLayout()}},this)},renderSeries:function(t,e,i,n){function o(e,i,o){var a=e.getItemModel(i);Ix(e,i,o,t,n),e.setItemVisual(i,{symbolSize:a.get("symbolSize")||g[o?0:1],symbol:a.get("symbol",!0)||p[o?0:1],color:a.get("itemStyle.color")||s.getVisual("color")})}var a=t.coordinateSystem,r=t.id,s=t.getData(),l=this.markerGroupMap,u=l.get(r)||l.set(r,new sf);this.group.add(u.group);var h=Tx(a,t,e),c=h.from,d=h.to,f=h.line;e.__from=c,e.__to=d,e.setData(f);var p=e.get("symbol"),g=e.get("symbolSize");y(p)||(p=[p,p]),"number"==typeof g&&(g=[g,g]),h.from.each(function(t){o(c,t,!0),o(d,t,!1)}),f.each(function(t){var e=f.getItemModel(t).get("lineStyle.color");f.setItemVisual(t,{color:e||c.getItemVisual(t,"color")}),f.setItemLayout(t,[c.getItemLayout(t),d.getItemLayout(t)]),f.setItemVisual(t,{fromSymbolSize:c.getItemVisual(t,"symbolSize"),fromSymbol:c.getItemVisual(t,"symbol"),toSymbolSize:d.getItemVisual(t,"symbolSize"),toSymbol:d.getItemVisual(t,"symbol")})}),u.updateData(f),h.line.eachItemGraphicEl(function(t,i){t.traverse(function(t){t.dataModel=e})}),u.__keep=!0,u.group.silent=e.get("silent")||t.get("silent")}}),Ns(function(t){t.markLine=t.markLine||{}}),UO.extend({type:"markArea",defaultOption:{zlevel:0,z:1,tooltip:{trigger:"item"},animation:!1,label:{show:!0,position:"top"},itemStyle:{borderWidth:0},emphasis:{label:{show:!0,position:"top"}}}});var $O=function(t,e,i,n){var a=fx(t,n[0]),r=fx(t,n[1]),s=T,l=a.coord,u=r.coord;l[0]=s(l[0],-1/0),l[1]=s(l[1],-1/0),u[0]=s(u[0],1/0),u[1]=s(u[1],1/0);var h=o([{},a,r]);return h.coord=[a.coord,r.coord],h.x0=a.x,h.y0=a.y,h.x1=r.x,h.y1=r.y,h},JO=[["x0","y0"],["x1","y0"],["x1","y1"],["x0","y1"]];qO.extend({type:"markArea",updateTransform:function(t,e,i){e.eachSeries(function(t){var e=t.markAreaModel;if(e){var n=e.getData();n.each(function(e){var o=f(JO,function(o){return Lx(n,e,o,t,i)});n.setItemLayout(e,o),n.getItemGraphicEl(e).setShape("points",o)})}},this)},renderSeries:function(t,e,i,n){var o=t.coordinateSystem,a=t.id,s=t.getData(),l=this.markerGroupMap,u=l.get(a)||l.set(a,{group:new tb});this.group.add(u.group),u.__keep=!0;var h=kx(o,t,e);e.setData(h),h.each(function(e){h.setItemLayout(e,f(JO,function(i){return Lx(h,e,i,t,n)})),h.setItemVisual(e,{color:s.getVisual("color")})}),h.diff(u.__data).add(function(t){var e=new pM({shape:{points:h.getItemLayout(t)}});h.setItemGraphicEl(t,e),u.group.add(e)}).update(function(t,i){var n=u.__data.getItemGraphicEl(i);Io(n,{shape:{points:h.getItemLayout(t)}},e,t),u.group.add(n),h.setItemGraphicEl(t,n)}).remove(function(t){var e=u.__data.getItemGraphicEl(t);u.group.remove(e)}).execute(),h.eachItemGraphicEl(function(t,i){var n=h.getItemModel(i),o=n.getModel("label"),a=n.getModel("emphasis.label"),s=h.getItemVisual(i,"color");t.useStyle(r(n.getModel("itemStyle").getItemStyle(),{fill:Yt(s,.4),stroke:s})),t.hoverStyle=n.getModel("emphasis.itemStyle").getItemStyle(),go(t.style,t.hoverStyle,o,a,{labelFetcher:e,labelDataIndex:i,defaultText:h.getName(i)||"",isRectText:!0,autoColor:s}),fo(t,{}),t.dataModel=e}),u.__data=h,u.group.silent=e.get("silent")||t.get("silent")}}),Ns(function(t){t.markArea=t.markArea||{}});lI.registerSubTypeDefaulter("timeline",function(){return"slider"}),Es({type:"timelineChange",event:"timelineChanged",update:"prepareAndUpdate"},function(t,e){var i=e.getComponent("timeline");return i&&null!=t.currentIndex&&(i.setCurrentIndex(t.currentIndex),!i.get("loop",!0)&&i.isIndexMax()&&i.setPlayState(!1)),e.resetOption("timeline"),r({currentIndex:i.option.currentIndex},t)}),Es({type:"timelinePlayChange",event:"timelinePlayChanged",update:"update"},function(t,e){var i=e.getComponent("timeline");i&&null!=t.playState&&i.setPlayState(t.playState)});var QO=lI.extend({type:"timeline",layoutMode:"box",defaultOption:{zlevel:0,z:4,show:!0,axisType:"time",realtime:!0,left:"20%",top:null,right:"20%",bottom:0,width:null,height:40,padding:5,controlPosition:"left",autoPlay:!1,rewind:!1,loop:!0,playInterval:2e3,currentIndex:0,itemStyle:{},label:{color:"#000"},data:[]},init:function(t,e,i){this._data,this._names,this.mergeDefaultAndTheme(t,i),this._initData()},mergeOption:function(t){QO.superApply(this,"mergeOption",arguments),this._initData()},setCurrentIndex:function(t){null==t&&(t=this.option.currentIndex);var e=this._data.count();this.option.loop?t=(t%e+e)%e:(t>=e&&(t=e-1),t<0&&(t=0)),this.option.currentIndex=t},getCurrentIndex:function(){return this.option.currentIndex},isIndexMax:function(){return this.getCurrentIndex()>=this._data.count()-1},setPlayState:function(t){this.option.autoPlay=!!t},getPlayState:function(){return!!this.option.autoPlay},_initData:function(){var t=this.option,e=t.data||[],n=t.axisType,o=this._names=[];if("category"===n){var a=[];d(e,function(t,e){var n,r=Li(t);w(t)?(n=i(t)).value=e:n=e,a.push(n),_(r)||null!=r&&!isNaN(r)||(r=""),o.push(r+"")}),e=a}var r={category:"ordinal",time:"time"}[n]||"number";(this._data=new vA([{name:"value",type:r}],this)).initData(e,o)},getData:function(){return this._data},getCategories:function(){if("category"===this.get("axisType"))return this._names.slice()}});h(QO.extend({type:"timeline.slider",defaultOption:{backgroundColor:"rgba(0,0,0,0)",borderColor:"#ccc",borderWidth:0,orient:"horizontal",inverse:!1,tooltip:{trigger:"item"},symbol:"emptyCircle",symbolSize:10,lineStyle:{show:!0,width:2,color:"#304654"},label:{position:"auto",show:!0,interval:"auto",rotate:0,color:"#304654"},itemStyle:{color:"#304654",borderWidth:1},checkpointStyle:{symbol:"circle",symbolSize:13,color:"#c23531",borderWidth:5,borderColor:"rgba(194,53,49, 0.5)",animation:!0,animationDuration:300,animationEasing:"quinticInOut"},controlStyle:{show:!0,showPlayBtn:!0,showPrevBtn:!0,showNextBtn:!0,itemSize:22,itemGap:12,position:"left",playIcon:"path://M31.6,53C17.5,53,6,41.5,6,27.4S17.5,1.8,31.6,1.8C45.7,1.8,57.2,13.3,57.2,27.4S45.7,53,31.6,53z M31.6,3.3 C18.4,3.3,7.5,14.1,7.5,27.4c0,13.3,10.8,24.1,24.1,24.1C44.9,51.5,55.7,40.7,55.7,27.4C55.7,14.1,44.9,3.3,31.6,3.3z M24.9,21.3 c0-2.2,1.6-3.1,3.5-2l10.5,6.1c1.899,1.1,1.899,2.9,0,4l-10.5,6.1c-1.9,1.1-3.5,0.2-3.5-2V21.3z",stopIcon:"path://M30.9,53.2C16.8,53.2,5.3,41.7,5.3,27.6S16.8,2,30.9,2C45,2,56.4,13.5,56.4,27.6S45,53.2,30.9,53.2z M30.9,3.5C17.6,3.5,6.8,14.4,6.8,27.6c0,13.3,10.8,24.1,24.101,24.1C44.2,51.7,55,40.9,55,27.6C54.9,14.4,44.1,3.5,30.9,3.5z M36.9,35.8c0,0.601-0.4,1-0.9,1h-1.3c-0.5,0-0.9-0.399-0.9-1V19.5c0-0.6,0.4-1,0.9-1H36c0.5,0,0.9,0.4,0.9,1V35.8z M27.8,35.8 c0,0.601-0.4,1-0.9,1h-1.3c-0.5,0-0.9-0.399-0.9-1V19.5c0-0.6,0.4-1,0.9-1H27c0.5,0,0.9,0.4,0.9,1L27.8,35.8L27.8,35.8z",nextIcon:"path://M18.6,50.8l22.5-22.5c0.2-0.2,0.3-0.4,0.3-0.7c0-0.3-0.1-0.5-0.3-0.7L18.7,4.4c-0.1-0.1-0.2-0.3-0.2-0.5 c0-0.4,0.3-0.8,0.8-0.8c0.2,0,0.5,0.1,0.6,0.3l23.5,23.5l0,0c0.2,0.2,0.3,0.4,0.3,0.7c0,0.3-0.1,0.5-0.3,0.7l-0.1,0.1L19.7,52 c-0.1,0.1-0.3,0.2-0.5,0.2c-0.4,0-0.8-0.3-0.8-0.8C18.4,51.2,18.5,51,18.6,50.8z",prevIcon:"path://M43,52.8L20.4,30.3c-0.2-0.2-0.3-0.4-0.3-0.7c0-0.3,0.1-0.5,0.3-0.7L42.9,6.4c0.1-0.1,0.2-0.3,0.2-0.5 c0-0.4-0.3-0.8-0.8-0.8c-0.2,0-0.5,0.1-0.6,0.3L18.3,28.8l0,0c-0.2,0.2-0.3,0.4-0.3,0.7c0,0.3,0.1,0.5,0.3,0.7l0.1,0.1L41.9,54 c0.1,0.1,0.3,0.2,0.5,0.2c0.4,0,0.8-0.3,0.8-0.8C43.2,53.2,43.1,53,43,52.8z",color:"#304654",borderColor:"#304654",borderWidth:1},emphasis:{label:{show:!0,color:"#c23531"},itemStyle:{color:"#c23531"},controlStyle:{color:"#c23531",borderColor:"#c23531",borderWidth:2}},data:[]}}),ZI);var tE=qI.extend({type:"timeline"}),eE=function(t,e,i,n){aD.call(this,t,e,i),this.type=n||"value",this.model=null};eE.prototype={constructor:eE,getLabelModel:function(){return this.model.getModel("label")},isHorizontal:function(){return"horizontal"===this.model.get("orient")}},u(eE,aD);var iE=m,nE=d,oE=Math.PI;tE.extend({type:"timeline.slider",init:function(t,e){this.api=e,this._axis,this._viewRect,this._timer,this._currentPointer,this._mainGroup,this._labelGroup},render:function(t,e,i,n){if(this.model=t,this.api=i,this.ecModel=e,this.group.removeAll(),t.get("show",!0)){var o=this._layout(t,i),a=this._createGroup("mainGroup"),r=this._createGroup("labelGroup"),s=this._axis=this._createAxis(o,t);t.formatTooltip=function(t){return ia(s.scale.getLabel(t))},nE(["AxisLine","AxisTick","Control","CurrentPointer"],function(e){this["_render"+e](o,a,s,t)},this),this._renderAxisLabel(o,r,s,t),this._position(o,t)}this._doPlayStop()},remove:function(){this._clearTimer(),this.group.removeAll()},dispose:function(){this._clearTimer()},_layout:function(t,e){var i=t.get("label.position"),n=t.get("orient"),o=Ex(t,e);null==i||"auto"===i?i="horizontal"===n?o.y+o.height/2<e.getHeight()/2?"-":"+":o.x+o.width/2<e.getWidth()/2?"+":"-":isNaN(i)&&(i={horizontal:{top:"-",bottom:"+"},vertical:{left:"-",right:"+"}}[n][i]);var a={horizontal:"center",vertical:i>=0||"+"===i?"left":"right"},r={horizontal:i>=0||"+"===i?"top":"bottom",vertical:"middle"},s={horizontal:0,vertical:oE/2},l="vertical"===n?o.height:o.width,u=t.getModel("controlStyle"),h=u.get("show",!0),c=h?u.get("itemSize"):0,d=h?u.get("itemGap"):0,f=c+d,p=t.get("label.rotate")||0;p=p*oE/180;var g,m,v,y,x=u.get("position",!0),_=h&&u.get("showPlayBtn",!0),w=h&&u.get("showPrevBtn",!0),b=h&&u.get("showNextBtn",!0),S=0,M=l;return"left"===x||"bottom"===x?(_&&(g=[0,0],S+=f),w&&(m=[S,0],S+=f),b&&(v=[M-c,0],M-=f)):(_&&(g=[M-c,0],M-=f),w&&(m=[0,0],S+=f),b&&(v=[M-c,0],M-=f)),y=[S,M],t.get("inverse")&&y.reverse(),{viewRect:o,mainLength:l,orient:n,rotation:s[n],labelRotation:p,labelPosOpt:i,labelAlign:t.get("label.align")||a[n],labelBaseline:t.get("label.verticalAlign")||t.get("label.baseline")||r[n],playPosition:g,prevBtnPosition:m,nextBtnPosition:v,axisExtent:y,controlSize:c,controlGap:d}},_position:function(t,e){function i(t){var e=t.position;t.origin=[c[0][0]-e[0],c[1][0]-e[1]]}function n(t){return[[t.x,t.x+t.width],[t.y,t.y+t.height]]}function o(t,e,i,n,o){t[n]+=i[n][o]-e[n][o]}var a=this._mainGroup,r=this._labelGroup,s=t.viewRect;if("vertical"===t.orient){var l=xt(),u=s.x,h=s.y+s.height;St(l,l,[-u,-h]),Mt(l,l,-oE/2),St(l,l,[u,h]),(s=s.clone()).applyTransform(l)}var c=n(s),d=n(a.getBoundingRect()),f=n(r.getBoundingRect()),p=a.position,g=r.position;g[0]=p[0]=c[0][0];var m=t.labelPosOpt;if(isNaN(m))o(p,d,c,1,v="+"===m?0:1),o(g,f,c,1,1-v);else{var v=m>=0?0:1;o(p,d,c,1,v),g[1]=p[1]+m}a.attr("position",p),r.attr("position",g),a.rotation=r.rotation=t.rotation,i(a),i(r)},_createAxis:function(t,e){var i=e.getData(),n=e.get("axisType"),o=Hl(e,n);o.getTicks=function(){return i.mapArray(["value"],function(t){return t})};var a=i.getDataExtent("value");o.setExtent(a[0],a[1]),o.niceTicks();var r=new eE("value",o,t.axisExtent,n);return r.model=e,r},_createGroup:function(t){var e=this["_"+t]=new tb;return this.group.add(e),e},_renderAxisLine:function(t,e,i,n){var o=i.getExtent();n.get("lineStyle.show")&&e.add(new _M({shape:{x1:o[0],y1:0,x2:o[1],y2:0},style:a({lineCap:"round"},n.getModel("lineStyle").getLineStyle()),silent:!0,z2:1}))},_renderAxisTick:function(t,e,i,n){var o=n.getData(),a=i.scale.getTicks();nE(a,function(t){var a=i.dataToCoord(t),r=o.getItemModel(t),s=r.getModel("itemStyle"),l=r.getModel("emphasis.itemStyle"),u={position:[a,0],onclick:iE(this._changeTimeline,this,t)},h=zx(r,s,e,u);fo(h,l.getItemStyle()),r.get("tooltip")?(h.dataIndex=t,h.dataModel=n):h.dataIndex=h.dataModel=null},this)},_renderAxisLabel:function(t,e,i,n){if(i.getLabelModel().get("show")){var o=n.getData(),a=i.getViewLabels();nE(a,function(n){var a=n.tickValue,r=o.getItemModel(a),s=r.getModel("label"),l=r.getModel("emphasis.label"),u=i.dataToCoord(n.tickValue),h=new rM({position:[u,0],rotation:t.labelRotation-t.rotation,onclick:iE(this._changeTimeline,this,a),silent:!1});mo(h.style,s,{text:n.formattedLabel,textAlign:t.labelAlign,textVerticalAlign:t.labelBaseline}),e.add(h),fo(h,mo({},l))},this)}},_renderControl:function(t,e,i,n){function o(t,i,o,h){if(t){var c=Rx(n,i,u,{position:t,origin:[a/2,0],rotation:h?-r:0,rectHover:!0,style:s,onclick:o});e.add(c),fo(c,l)}}var a=t.controlSize,r=t.rotation,s=n.getModel("controlStyle").getItemStyle(),l=n.getModel("emphasis.controlStyle").getItemStyle(),u=[0,-a/2,a,a],h=n.getPlayState(),c=n.get("inverse",!0);o(t.nextBtnPosition,"controlStyle.nextIcon",iE(this._changeTimeline,this,c?"-":"+")),o(t.prevBtnPosition,"controlStyle.prevIcon",iE(this._changeTimeline,this,c?"+":"-")),o(t.playPosition,"controlStyle."+(h?"stopIcon":"playIcon"),iE(this._handlePlayClick,this,!h),!0)},_renderCurrentPointer:function(t,e,i,n){var o=n.getData(),a=n.getCurrentIndex(),r=o.getItemModel(a).getModel("checkpointStyle"),s=this,l={onCreate:function(t){t.draggable=!0,t.drift=iE(s._handlePointerDrag,s),t.ondragend=iE(s._handlePointerDragend,s),Bx(t,a,i,n,!0)},onUpdate:function(t){Bx(t,a,i,n)}};this._currentPointer=zx(r,r,this._mainGroup,{},this._currentPointer,l)},_handlePlayClick:function(t){this._clearTimer(),this.api.dispatchAction({type:"timelinePlayChange",playState:t,from:this.uid})},_handlePointerDrag:function(t,e,i){this._clearTimer(),this._pointerChangeTimeline([i.offsetX,i.offsetY])},_handlePointerDragend:function(t){this._pointerChangeTimeline([t.offsetX,t.offsetY],!0)},_pointerChangeTimeline:function(t,e){var i=this._toAxisCoord(t)[0],n=Fo(this._axis.getExtent().slice());i>n[1]&&(i=n[1]),i<n[0]&&(i=n[0]),this._currentPointer.position[0]=i,this._currentPointer.dirty();var o=this._findNearestTick(i),a=this.model;(e||o!==a.getCurrentIndex()&&a.get("realtime"))&&this._changeTimeline(o)},_doPlayStop:function(){this._clearTimer(),this.model.getPlayState()&&(this._timer=setTimeout(iE(function(){var t=this.model;this._changeTimeline(t.getCurrentIndex()+(t.get("rewind",!0)?-1:1))},this),this.model.get("playInterval")))},_toAxisCoord:function(t){return Do(t,this._mainGroup.getLocalTransform(),!0)},_findNearestTick:function(t){var e,i=this.model.getData(),n=1/0,o=this._axis;return i.each(["value"],function(i,a){var r=o.dataToCoord(i),s=Math.abs(r-t);s<n&&(n=s,e=a)}),e},_clearTimer:function(){this._timer&&(clearTimeout(this._timer),this._timer=null)},_changeTimeline:function(t){var e=this.model.getCurrentIndex();"+"===t?t=e+1:"-"===t&&(t=e-1),this.api.dispatchAction({type:"timelineChange",currentIndex:t,from:this.uid})}}),Ns(function(t){var e=t&&t.timeline;y(e)||(e=e?[e]:[]),d(e,function(t){t&&Px(t)})});var aE=Fs({type:"toolbox",layoutMode:{type:"box",ignoreSize:!0},optionUpdated:function(){aE.superApply(this,"optionUpdated",arguments),d(this.option.feature,function(t,e){var i=Ay(e);i&&n(t,i.defaultOption)})},defaultOption:{show:!0,z:6,zlevel:0,orient:"horizontal",left:"right",top:"top",backgroundColor:"transparent",borderColor:"#ccc",borderRadius:0,borderWidth:0,padding:5,itemSize:15,itemGap:8,showTitle:!0,iconStyle:{borderColor:"#666",color:"none"},emphasis:{iconStyle:{borderColor:"#3E98C5"}}}});Ws({type:"toolbox",render:function(t,e,i,n){function o(o,r){var s,c=h[o],d=h[r],f=new No(l[c],t,t.ecModel);if(c&&!d){if(Vx(c))s={model:f,onclick:f.option.onclick,featureName:c};else{var p=Ay(c);if(!p)return;s=new p(f,e,i)}u[c]=s}else{if(!(s=u[d]))return;s.model=f,s.ecModel=e,s.api=i}c||!d?f.get("show")&&!s.unusable?(a(f,s,c),f.setIconStatus=function(t,e){var i=this.option,n=this.iconPaths;i.iconStatus=i.iconStatus||{},i.iconStatus[t]=e,n[t]&&n[t].trigger(e)},s.render&&s.render(f,e,i,n)):s.remove&&s.remove(e,i):s.dispose&&s.dispose(e,i)}function a(n,o,a){var l=n.getModel("iconStyle"),u=n.getModel("emphasis.iconStyle"),h=o.getIcons?o.getIcons():n.get("icon"),c=n.get("title")||{};if("string"==typeof h){var f=h,p=c;c={},(h={})[a]=f,c[a]=p}var g=n.iconPaths={};d(h,function(a,h){var d=Po(a,{},{x:-s/2,y:-s/2,width:s,height:s});d.setStyle(l.getItemStyle()),d.hoverStyle=u.getItemStyle(),fo(d),t.get("showTitle")&&(d.__title=c[h],d.on("mouseover",function(){var t=u.getItemStyle();d.setStyle({text:c[h],textPosition:t.textPosition||"bottom",textFill:t.fill||t.stroke||"#000",textAlign:t.textAlign||"center"})}).on("mouseout",function(){d.setStyle({textFill:null})})),d.trigger(n.get("iconStatus."+h)||"normal"),r.add(d),d.on("click",m(o.onclick,o,e,i,h)),g[h]=d})}var r=this.group;if(r.removeAll(),t.get("show")){var s=+t.get("itemSize"),l=t.get("feature")||{},u=this._features||(this._features={}),h=[];d(l,function(t,e){h.push(e)}),new Xs(this._featureNames||[],h).add(o).update(o).remove(v(o,null)).execute(),this._featureNames=h,_v(r,t,i),r.add(wv(r.getBoundingRect(),t)),r.eachChild(function(t){var e=t.__title,n=t.hoverStyle;if(n&&e){var o=ke(e,Xe(n)),a=t.position[0]+r.position[0],l=!1;t.position[1]+r.position[1]+s+o.height>i.getHeight()&&(n.textPosition="top",l=!0);var u=l?-5-o.height:s+8;a+o.width/2>i.getWidth()?(n.textPosition=["100%",u],n.textAlign="right"):a-o.width/2<0&&(n.textPosition=[0,u],n.textAlign="left")}})}},updateView:function(t,e,i,n){d(this._features,function(t){t.updateView&&t.updateView(t.model,e,i,n)})},remove:function(t,e){d(this._features,function(i){i.remove&&i.remove(t,e)}),this.group.removeAll()},dispose:function(t,e){d(this._features,function(i){i.dispose&&i.dispose(t,e)})}});var rE=rT.toolbox.saveAsImage;Gx.defaultOption={show:!0,icon:"M4.7,22.9L29.3,45.5L54.7,23.4M4.6,43.6L4.6,58L53.8,58L53.8,43.6M29.2,45.1L29.2,0",title:rE.title,type:"png",name:"",excludeComponents:["toolbox"],pixelRatio:1,lang:rE.lang.slice()},Gx.prototype.unusable=!U_.canvasSupported,Gx.prototype.onclick=function(t,e){var i=this.model,n=i.get("name")||t.get("title.0.text")||"echarts",o=document.createElement("a"),a=i.get("type",!0)||"png";o.download=n+"."+a,o.target="_blank";var r=e.getConnectedDataURL({type:a,backgroundColor:i.get("backgroundColor",!0)||t.get("backgroundColor")||"#fff",excludeComponents:i.get("excludeComponents"),pixelRatio:i.get("pixelRatio")});if(o.href=r,"function"!=typeof MouseEvent||U_.browser.ie||U_.browser.edge)if(window.navigator.msSaveOrOpenBlob){for(var s=atob(r.split(",")[1]),l=s.length,u=new Uint8Array(l);l--;)u[l]=s.charCodeAt(l);var h=new Blob([u]);window.navigator.msSaveOrOpenBlob(h,n+"."+a)}else{var c=i.get("lang"),d='<body style="margin:0;"><img src="'+r+'" style="max-width:100%;" title="'+(c&&c[0]||"")+'" /></body>';window.open().document.write(d)}else{var f=new MouseEvent("click",{view:window,bubbles:!0,cancelable:!1});o.dispatchEvent(f)}},Ty("saveAsImage",Gx);var sE=rT.toolbox.magicType;Fx.defaultOption={show:!0,type:[],icon:{line:"M4.1,28.9h7.1l9.3-22l7.4,38l9.7-19.7l3,12.8h14.9M4.1,58h51.4",bar:"M6.7,22.9h10V48h-10V22.9zM24.9,13h10v35h-10V13zM43.2,2h10v46h-10V2zM3.1,58h53.7",stack:"M8.2,38.4l-8.4,4.1l30.6,15.3L60,42.5l-8.1-4.1l-21.5,11L8.2,38.4z M51.9,30l-8.1,4.2l-13.4,6.9l-13.9-6.9L8.2,30l-8.4,4.2l8.4,4.2l22.2,11l21.5-11l8.1-4.2L51.9,30z M51.9,21.7l-8.1,4.2L35.7,30l-5.3,2.8L24.9,30l-8.4-4.1l-8.3-4.2l-8.4,4.2L8.2,30l8.3,4.2l13.9,6.9l13.4-6.9l8.1-4.2l8.1-4.1L51.9,21.7zM30.4,2.2L-0.2,17.5l8.4,4.1l8.3,4.2l8.4,4.2l5.5,2.7l5.3-2.7l8.1-4.2l8.1-4.2l8.1-4.1L30.4,2.2z",tiled:"M2.3,2.2h22.8V25H2.3V2.2z M35,2.2h22.8V25H35V2.2zM2.3,35h22.8v22.8H2.3V35z M35,35h22.8v22.8H35V35z"},title:i(sE.title),option:{},seriesIndex:{}};var lE=Fx.prototype;lE.getIcons=function(){var t=this.model,e=t.get("icon"),i={};return d(t.get("type"),function(t){e[t]&&(i[t]=e[t])}),i};var uE={line:function(t,e,i,o){if("bar"===t)return n({id:e,type:"line",data:i.get("data"),stack:i.get("stack"),markPoint:i.get("markPoint"),markLine:i.get("markLine")},o.get("option.line")||{},!0)},bar:function(t,e,i,o){if("line"===t)return n({id:e,type:"bar",data:i.get("data"),stack:i.get("stack"),markPoint:i.get("markPoint"),markLine:i.get("markLine")},o.get("option.bar")||{},!0)},stack:function(t,e,i,o){if("line"===t||"bar"===t)return n({id:e,stack:"__ec_magicType_stack__"},o.get("option.stack")||{},!0)},tiled:function(t,e,i,o){if("line"===t||"bar"===t)return n({id:e,stack:""},o.get("option.tiled")||{},!0)}},hE=[["line","bar"],["stack","tiled"]];lE.onclick=function(t,e,i){var n=this.model,o=n.get("seriesIndex."+i);if(uE[i]){var a={series:[]};d(hE,function(t){l(t,i)>=0&&d(t,function(t){n.setIconStatus(t,"normal")})}),n.setIconStatus(i,"emphasis"),t.eachComponent({mainType:"series",query:null==o?null:{seriesIndex:o}},function(e){var o=e.subType,s=e.id,l=uE[i](o,s,e,n);l&&(r(l,e.option),a.series.push(l));var u=e.coordinateSystem;if(u&&"cartesian2d"===u.type&&("line"===i||"bar"===i)){var h=u.getAxesByScale("ordinal")[0];if(h){var c=h.dim+"Axis",d=t.queryComponents({mainType:c,index:e.get(name+"Index"),id:e.get(name+"Id")})[0].componentIndex;a[c]=a[c]||[];for(var f=0;f<=d;f++)a[c][d]=a[c][d]||{};a[c][d].boundaryGap="bar"===i}}}),e.dispatchAction({type:"changeMagicType",currentType:i,newOption:a})}},Es({type:"changeMagicType",event:"magicTypeChanged",update:"prepareAndUpdate"},function(t,e){e.mergeOption(t.newOption)}),Ty("magicType",Fx);var cE=rT.toolbox.dataView,dE=new Array(60).join("-"),fE="\t",pE=new RegExp("["+fE+"]+","g");$x.defaultOption={show:!0,readOnly:!1,optionToContent:null,contentToOption:null,icon:"M17.5,17.3H33 M17.5,17.3H33 M45.4,29.5h-28 M11.5,2v56H51V14.8L38.4,2H11.5z M38.4,2.2v12.7H51 M45.4,41.7h-28",title:i(cE.title),lang:i(cE.lang),backgroundColor:"#fff",textColor:"#000",textareaColor:"#fff",textareaBorderColor:"#333",buttonColor:"#c23531",buttonTextColor:"#fff"},$x.prototype.onclick=function(t,e){function i(){n.removeChild(a),x._dom=null}var n=e.getDom(),o=this.model;this._dom&&n.removeChild(this._dom);var a=document.createElement("div");a.style.cssText="position:absolute;left:5px;top:5px;bottom:5px;right:5px;",a.style.backgroundColor=o.get("backgroundColor")||"#fff";var r=document.createElement("h4"),s=o.get("lang")||[];r.innerHTML=s[0]||o.get("title"),r.style.cssText="margin: 10px 20px;",r.style.color=o.get("textColor");var l=document.createElement("div"),u=document.createElement("textarea");l.style.cssText="display:block;width:100%;overflow:auto;";var h=o.get("optionToContent"),c=o.get("contentToOption"),d=Ux(t);if("function"==typeof h){var f=h(e.getOption());"string"==typeof f?l.innerHTML=f:M(f)&&l.appendChild(f)}else l.appendChild(u),u.readOnly=o.get("readOnly"),u.style.cssText="width:100%;height:100%;font-family:monospace;font-size:14px;line-height:1.6rem;",u.style.color=o.get("textColor"),u.style.borderColor=o.get("textareaBorderColor"),u.style.backgroundColor=o.get("textareaColor"),u.value=d.value;var p=d.meta,g=document.createElement("div");g.style.cssText="position:absolute;bottom:0;left:0;right:0;";var m="float:right;margin-right:20px;border:none;cursor:pointer;padding:2px 5px;font-size:12px;border-radius:3px",v=document.createElement("div"),y=document.createElement("div");m+=";background-color:"+o.get("buttonColor"),m+=";color:"+o.get("buttonTextColor");var x=this;ht(v,"click",i),ht(y,"click",function(){var t;try{t="function"==typeof c?c(l,e.getOption()):Kx(u.value,p)}catch(t){throw i(),new Error("Data view format error "+t)}t&&e.dispatchAction({type:"changeDataView",newOption:t}),i()}),v.innerHTML=s[1],y.innerHTML=s[2],y.style.cssText=m,v.style.cssText=m,!o.get("readOnly")&&g.appendChild(y),g.appendChild(v),ht(u,"keydown",function(t){if(9===(t.keyCode||t.which)){var e=this.value,i=this.selectionStart,n=this.selectionEnd;this.value=e.substring(0,i)+fE+e.substring(n),this.selectionStart=this.selectionEnd=i+1,mw(t)}}),a.appendChild(r),a.appendChild(l),a.appendChild(g),l.style.height=n.clientHeight-80+"px",n.appendChild(a),this._dom=a},$x.prototype.remove=function(t,e){this._dom&&e.getDom().removeChild(this._dom)},$x.prototype.dispose=function(t,e){this.remove(t,e)},Ty("dataView",$x),Es({type:"changeDataView",event:"dataViewChanged",update:"prepareAndUpdate"},function(t,e){var i=[];d(t.newOption.series,function(t){var n=e.getSeriesByName(t.name)[0];if(n){var o=n.get("data");i.push({name:t.name,data:Jx(t.data,o)})}else i.push(a({type:"scatter"},t))}),e.mergeOption(r({series:i},t.newOption))});var gE=d,mE="\0_ec_hist_store";iO.extend({type:"dataZoom.select"}),nO.extend({type:"dataZoom.select"});var vE=rT.toolbox.dataZoom,yE=d,xE="\0_ec_\0toolbox-dataZoom_";o_.defaultOption={show:!0,icon:{zoom:"M0,13.5h26.9 M13.5,26.9V0 M32.1,13.5H58V58H13.5 V32.1",back:"M22,1.4L9.9,13.5l12.3,12.3 M10.3,13.5H54.9v44.6 H10.3v-26"},title:i(vE.title)};var _E=o_.prototype;_E.render=function(t,e,i,n){this.model=t,this.ecModel=e,this.api=i,s_(t,e,this,n,i),r_(t,e)},_E.onclick=function(t,e,i){wE[i].call(this)},_E.remove=function(t,e){this._brushController.unmount()},_E.dispose=function(t,e){this._brushController.dispose()};var wE={zoom:function(){var t=!this._isZoomActive;this.api.dispatchAction({type:"takeGlobalCursor",key:"dataZoomSelect",dataZoomSelectActive:t})},back:function(){this._dispatchZoomAction(t_(this.ecModel))}};_E._onBrush=function(t,e){function i(t,e,i){var r=e.getAxis(t),s=r.model,l=n(t,s,a),u=l.findRepresentativeAxisProxy(s).getMinMaxSpan();null==u.minValueSpan&&null==u.maxValueSpan||(i=QL(0,i.slice(),r.scale.getExtent(),0,u.minValueSpan,u.maxValueSpan)),l&&(o[l.id]={dataZoomId:l.id,startValue:i[0],endValue:i[1]})}function n(t,e,i){var n;return i.eachComponent({mainType:"dataZoom",subType:"select"},function(i){i.getAxisModel(t,e.componentIndex)&&(n=i)}),n}if(e.isEnd&&t.length){var o={},a=this.ecModel;this._brushController.updateCovers([]),new hy(a_(this.model.option),a,{include:["grid"]}).matchOutputRanges(t,a,function(t,e,n){if("cartesian2d"===n.type){var o=t.brushType;"rect"===o?(i("x",n,e[0]),i("y",n,e[1])):i({lineX:"x",lineY:"y"}[o],n,e)}}),Qx(a,o),this._dispatchZoomAction(o)}},_E._dispatchZoomAction=function(t){var e=[];yE(t,function(t,n){e.push(i(t))}),e.length&&this.api.dispatchAction({type:"dataZoom",from:this.uid,batch:e})},Ty("dataZoom",o_),Ns(function(t){function e(t,e){if(e){var o=t+"Index",a=e[o];null==a||"all"===a||y(a)||(a=!1===a||"none"===a?[]:[a]),i(t,function(e,i){if(null==a||"all"===a||-1!==l(a,i)){var r={type:"select",$fromToolbox:!0,id:xE+t+i};r[o]=i,n.push(r)}})}}function i(e,i){var n=t[e];y(n)||(n=n?[n]:[]),yE(n,i)}if(t){var n=t.dataZoom||(t.dataZoom=[]);y(n)||(t.dataZoom=n=[n]);var o=t.toolbox;if(o&&(y(o)&&(o=o[0]),o&&o.feature)){var a=o.feature.dataZoom;e("xAxis",a),e("yAxis",a)}}});var bE=rT.toolbox.restore;l_.defaultOption={show:!0,icon:"M3.8,33.4 M47,18.9h9.8V8.7 M56.3,20.1 C52.1,9,40.5,0.6,26.8,2.1C12.6,3.7,1.6,16.2,2.1,30.6 M13,41.1H3.1v10.2 M3.7,39.9c4.2,11.1,15.8,19.5,29.5,18 c14.2-1.6,25.2-14.1,24.7-28.5",title:bE.title},l_.prototype.onclick=function(t,e,i){e_(t),e.dispatchAction({type:"restore",from:this.uid})},Ty("restore",l_),Es({type:"restore",event:"restore",update:"prepareAndUpdate"},function(t,e){e.resetOption("recreate")});var SE,ME="urn:schemas-microsoft-com:vml",IE="undefined"==typeof window?null:window,TE=!1,AE=IE&&IE.document;if(AE&&!U_.canvasSupported)try{!AE.namespaces.zrvml&&AE.namespaces.add("zrvml",ME),SE=function(t){return AE.createElement("<zrvml:"+t+' class="zrvml">')}}catch(t){SE=function(t){return AE.createElement("<"+t+' xmlns="'+ME+'" class="zrvml">')}}var DE=ES.CMD,CE=Math.round,LE=Math.sqrt,kE=Math.abs,PE=Math.cos,NE=Math.sin,OE=Math.max;if(!U_.canvasSupported){var EE=21600,RE=EE/2,zE=function(t){t.style.cssText="position:absolute;left:0;top:0;width:1px;height:1px;",t.coordsize=EE+","+EE,t.coordorigin="0,0"},BE=function(t){return String(t).replace(/&/g,"&amp;").replace(/"/g,"&quot;")},VE=function(t,e,i){return"rgb("+[t,e,i].join(",")+")"},GE=function(t,e){e&&t&&e.parentNode!==t&&t.appendChild(e)},FE=function(t,e){e&&t&&e.parentNode===t&&t.removeChild(e)},WE=function(t,e,i){return 1e5*(parseFloat(t)||0)+1e3*(parseFloat(e)||0)+i},HE=function(t,e){return"string"==typeof t?t.lastIndexOf("%")>=0?parseFloat(t)/100*e:parseFloat(t):t},ZE=function(t,e,i){var n=Gt(e);i=+i,isNaN(i)&&(i=1),n&&(t.color=VE(n[0],n[1],n[2]),t.opacity=i*n[3])},UE=function(t){var e=Gt(t);return[VE(e[0],e[1],e[2]),e[3]]},XE=function(t,e,i){var n=e.fill;if(null!=n)if(n instanceof IM){var o,a=0,r=[0,0],s=0,l=1,u=i.getBoundingRect(),h=u.width,c=u.height;if("linear"===n.type){o="gradient";var d=i.transform,f=[n.x*h,n.y*c],p=[n.x2*h,n.y2*c];d&&(Q(f,f,d),Q(p,p,d));var g=p[0]-f[0],m=p[1]-f[1];(a=180*Math.atan2(g,m)/Math.PI)<0&&(a+=360),a<1e-6&&(a=0)}else{o="gradientradial";var f=[n.x*h,n.y*c],d=i.transform,v=i.scale,y=h,x=c;r=[(f[0]-u.x)/y,(f[1]-u.y)/x],d&&Q(f,f,d),y/=v[0]*EE,x/=v[1]*EE;var _=OE(y,x);s=0/_,l=2*n.r/_-s}var w=n.colorStops.slice();w.sort(function(t,e){return t.offset-e.offset});for(var b=w.length,S=[],M=[],I=0;I<b;I++){var T=w[I],A=UE(T.color);M.push(T.offset*l+s+" "+A[0]),0!==I&&I!==b-1||S.push(A)}if(b>=2){var D=S[0][0],C=S[1][0],L=S[0][1]*e.opacity,k=S[1][1]*e.opacity;t.type=o,t.method="none",t.focus="100%",t.angle=a,t.color=D,t.color2=C,t.colors=M.join(","),t.opacity=k,t.opacity2=L}"radial"===o&&(t.focusposition=r.join(","))}else ZE(t,n,e.opacity)},jE=function(t,e){null!=e.lineDash&&(t.dashstyle=e.lineDash.join(" ")),null==e.stroke||e.stroke instanceof IM||ZE(t,e.stroke,e.opacity)},YE=function(t,e,i,n){var o="fill"===e,a=t.getElementsByTagName(e)[0];null!=i[e]&&"none"!==i[e]&&(o||!o&&i.lineWidth)?(t[o?"filled":"stroked"]="true",i[e]instanceof IM&&FE(t,a),a||(a=u_(e)),o?XE(a,i,n):jE(a,i),GE(t,a)):(t[o?"filled":"stroked"]="false",FE(t,a))},qE=[[],[],[]],KE=function(t,e){var i,n,o,a,r,s,l=DE.M,u=DE.C,h=DE.L,c=DE.A,d=DE.Q,f=[],p=t.data,g=t.len();for(a=0;a<g;){switch(o=p[a++],n="",i=0,o){case l:n=" m ",i=1,r=p[a++],s=p[a++],qE[0][0]=r,qE[0][1]=s;break;case h:n=" l ",i=1,r=p[a++],s=p[a++],qE[0][0]=r,qE[0][1]=s;break;case d:case u:n=" c ",i=3;var m,v,y=p[a++],x=p[a++],_=p[a++],w=p[a++];o===d?(m=_,v=w,_=(_+2*y)/3,w=(w+2*x)/3,y=(r+2*y)/3,x=(s+2*x)/3):(m=p[a++],v=p[a++]),qE[0][0]=y,qE[0][1]=x,qE[1][0]=_,qE[1][1]=w,qE[2][0]=m,qE[2][1]=v,r=m,s=v;break;case c:var b=0,S=0,M=1,I=1,T=0;e&&(b=e[4],S=e[5],M=LE(e[0]*e[0]+e[1]*e[1]),I=LE(e[2]*e[2]+e[3]*e[3]),T=Math.atan2(-e[1]/I,e[0]/M));var A=p[a++],D=p[a++],C=p[a++],L=p[a++],k=p[a++]+T,P=p[a++]+k+T;a++;var N=p[a++],O=A+PE(k)*C,E=D+NE(k)*L,y=A+PE(P)*C,x=D+NE(P)*L,R=N?" wa ":" at ";Math.abs(O-y)<1e-4&&(Math.abs(P-k)>.01?N&&(O+=.0125):Math.abs(E-D)<1e-4?N&&O<A||!N&&O>A?x-=.0125:x+=.0125:N&&E<D||!N&&E>D?y+=.0125:y-=.0125),f.push(R,CE(((A-C)*M+b)*EE-RE),",",CE(((D-L)*I+S)*EE-RE),",",CE(((A+C)*M+b)*EE-RE),",",CE(((D+L)*I+S)*EE-RE),",",CE((O*M+b)*EE-RE),",",CE((E*I+S)*EE-RE),",",CE((y*M+b)*EE-RE),",",CE((x*I+S)*EE-RE)),r=y,s=x;break;case DE.R:var z=qE[0],B=qE[1];z[0]=p[a++],z[1]=p[a++],B[0]=z[0]+p[a++],B[1]=z[1]+p[a++],e&&(Q(z,z,e),Q(B,B,e)),z[0]=CE(z[0]*EE-RE),B[0]=CE(B[0]*EE-RE),z[1]=CE(z[1]*EE-RE),B[1]=CE(B[1]*EE-RE),f.push(" m ",z[0],",",z[1]," l ",B[0],",",z[1]," l ",B[0],",",B[1]," l ",z[0],",",B[1]);break;case DE.Z:f.push(" x ")}if(i>0){f.push(n);for(var V=0;V<i;V++){var G=qE[V];e&&Q(G,G,e),f.push(CE(G[0]*EE-RE),",",CE(G[1]*EE-RE),V<i-1?",":"")}}}return f.join("")};Pn.prototype.brushVML=function(t){var e=this.style,i=this._vmlEl;i||(i=u_("shape"),zE(i),this._vmlEl=i),YE(i,"fill",e,this),YE(i,"stroke",e,this);var n=this.transform,o=null!=n,a=i.getElementsByTagName("stroke")[0];if(a){var r=e.lineWidth;if(o&&!e.strokeNoScale){var s=n[0]*n[3]-n[1]*n[2];r*=LE(kE(s))}a.weight=r+"px"}var l=this.path||(this.path=new ES);this.__dirtyPath&&(l.beginPath(),l.subPixelOptimize=!1,this.buildPath(l,this.shape),l.toStatic(),this.__dirtyPath=!1),i.path=KE(l,this.transform),i.style.zIndex=WE(this.zlevel,this.z,this.z2),GE(t,i),null!=e.text?this.drawRectText(t,this.getBoundingRect()):this.removeRectText(t)},Pn.prototype.onRemove=function(t){FE(t,this._vmlEl),this.removeRectText(t)},Pn.prototype.onAdd=function(t){GE(t,this._vmlEl),this.appendRectText(t)};var $E=function(t){return"object"==typeof t&&t.tagName&&"IMG"===t.tagName.toUpperCase()};fi.prototype.brushVML=function(t){var e,i,n=this.style,o=n.image;if($E(o)){var a=o.src;if(a===this._imageSrc)e=this._imageWidth,i=this._imageHeight;else{var r=o.runtimeStyle,s=r.width,l=r.height;r.width="auto",r.height="auto",e=o.width,i=o.height,r.width=s,r.height=l,this._imageSrc=a,this._imageWidth=e,this._imageHeight=i}o=a}else o===this._imageSrc&&(e=this._imageWidth,i=this._imageHeight);if(o){var u=n.x||0,h=n.y||0,c=n.width,d=n.height,f=n.sWidth,p=n.sHeight,g=n.sx||0,m=n.sy||0,v=f&&p,y=this._vmlEl;y||(y=AE.createElement("div"),zE(y),this._vmlEl=y);var x,_=y.style,w=!1,b=1,S=1;if(this.transform&&(x=this.transform,b=LE(x[0]*x[0]+x[1]*x[1]),S=LE(x[2]*x[2]+x[3]*x[3]),w=x[1]||x[2]),w){var M=[u,h],I=[u+c,h],T=[u,h+d],A=[u+c,h+d];Q(M,M,x),Q(I,I,x),Q(T,T,x),Q(A,A,x);var D=OE(M[0],I[0],T[0],A[0]),C=OE(M[1],I[1],T[1],A[1]),L=[];L.push("M11=",x[0]/b,",","M12=",x[2]/S,",","M21=",x[1]/b,",","M22=",x[3]/S,",","Dx=",CE(u*b+x[4]),",","Dy=",CE(h*S+x[5])),_.padding="0 "+CE(D)+"px "+CE(C)+"px 0",_.filter="progid:DXImageTransform.Microsoft.Matrix("+L.join("")+", SizingMethod=clip)"}else x&&(u=u*b+x[4],h=h*S+x[5]),_.filter="",_.left=CE(u)+"px",_.top=CE(h)+"px";var k=this._imageEl,P=this._cropEl;k||(k=AE.createElement("div"),this._imageEl=k);var N=k.style;if(v){if(e&&i)N.width=CE(b*e*c/f)+"px",N.height=CE(S*i*d/p)+"px";else{var O=new Image,E=this;O.onload=function(){O.onload=null,e=O.width,i=O.height,N.width=CE(b*e*c/f)+"px",N.height=CE(S*i*d/p)+"px",E._imageWidth=e,E._imageHeight=i,E._imageSrc=o},O.src=o}P||((P=AE.createElement("div")).style.overflow="hidden",this._cropEl=P);var R=P.style;R.width=CE((c+g*c/f)*b),R.height=CE((d+m*d/p)*S),R.filter="progid:DXImageTransform.Microsoft.Matrix(Dx="+-g*c/f*b+",Dy="+-m*d/p*S+")",P.parentNode||y.appendChild(P),k.parentNode!==P&&P.appendChild(k)}else N.width=CE(b*c)+"px",N.height=CE(S*d)+"px",y.appendChild(k),P&&P.parentNode&&(y.removeChild(P),this._cropEl=null);var z="",B=n.opacity;B<1&&(z+=".Alpha(opacity="+CE(100*B)+") "),z+="progid:DXImageTransform.Microsoft.AlphaImageLoader(src="+o+", SizingMethod=scale)",N.filter=z,y.style.zIndex=WE(this.zlevel,this.z,this.z2),GE(t,y),null!=n.text&&this.drawRectText(t,this.getBoundingRect())}},fi.prototype.onRemove=function(t){FE(t,this._vmlEl),this._vmlEl=null,this._cropEl=null,this._imageEl=null,this.removeRectText(t)},fi.prototype.onAdd=function(t){GE(t,this._vmlEl),this.appendRectText(t)};var JE,QE={},tR=0,eR=document.createElement("div"),iR=function(t){var e=QE[t];if(!e){tR>100&&(tR=0,QE={});var i,n=eR.style;try{n.font=t,i=n.fontFamily.split(",")[0]}catch(t){}e={style:n.fontStyle||"normal",variant:n.fontVariant||"normal",weight:n.fontWeight||"normal",size:0|parseFloat(n.fontSize||12),family:i||"Microsoft YaHei"},QE[t]=e,tR++}return e};!function(t,e){bb[t]=e}("measureText",function(t,e){var i=AE;JE||((JE=i.createElement("div")).style.cssText="position:absolute;top:-20000px;left:0;padding:0;margin:0;border:none;white-space:pre;",AE.body.appendChild(JE));try{JE.style.font=e}catch(t){}return JE.innerHTML="",JE.appendChild(i.createTextNode(t)),{width:JE.offsetWidth}});for(var nR=new de,oR=[Db,di,fi,Pn,rM],aR=0;aR<oR.length;aR++){var rR=oR[aR].prototype;rR.drawRectText=function(t,e,i,n){var o=this.style;this.__dirty&&Ye(o);var a=o.text;if(null!=a&&(a+=""),a){if(o.rich){var r=Ze(a,o);a=[];for(var s=0;s<r.lines.length;s++){for(var l=r.lines[s].tokens,u=[],h=0;h<l.length;h++)u.push(l[h].text);a.push(u.join(""))}a=a.join("\n")}var c,d,f=o.textAlign,p=o.textVerticalAlign,g=iR(o.font),m=g.style+" "+g.variant+" "+g.weight+" "+g.size+'px "'+g.family+'"';i=i||ke(a,m,f,p,o.textPadding,o.textLineHeight);var v=this.transform;if(v&&!n&&(nR.copy(e),nR.applyTransform(v),e=nR),n)c=e.x,d=e.y;else{var y=o.textPosition,x=o.textDistance;if(y instanceof Array)c=e.x+HE(y[0],e.width),d=e.y+HE(y[1],e.height),f=f||"left";else{var _=Re(y,e,x);c=_.x,d=_.y,f=f||_.textAlign,p=p||_.textVerticalAlign}}c=Oe(c,i.width,f),d=Ee(d,i.height,p),d+=i.height/2;var w,b,S,M=u_,I=this._textVmlEl;I?b=(w=(S=I.firstChild).nextSibling).nextSibling:(I=M("line"),w=M("path"),b=M("textpath"),S=M("skew"),b.style["v-text-align"]="left",zE(I),w.textpathok=!0,b.on=!0,I.from="0 0",I.to="1000 0.05",GE(I,S),GE(I,w),GE(I,b),this._textVmlEl=I);var T=[c,d],A=I.style;v&&n?(Q(T,T,v),S.on=!0,S.matrix=v[0].toFixed(3)+","+v[2].toFixed(3)+","+v[1].toFixed(3)+","+v[3].toFixed(3)+",0,0",S.offset=(CE(T[0])||0)+","+(CE(T[1])||0),S.origin="0 0",A.left="0px",A.top="0px"):(S.on=!1,A.left=CE(c)+"px",A.top=CE(d)+"px"),b.string=BE(a);try{b.style.font=m}catch(t){}YE(I,"fill",{fill:o.textFill,opacity:o.opacity},this),YE(I,"stroke",{stroke:o.textStroke,opacity:o.opacity,lineDash:o.lineDash},this),I.style.zIndex=WE(this.zlevel,this.z,this.z2),GE(t,I)}},rR.removeRectText=function(t){FE(t,this._textVmlEl),this._textVmlEl=null},rR.appendRectText=function(t){GE(t,this._textVmlEl)}}rM.prototype.brushVML=function(t){var e=this.style;null!=e.text?this.drawRectText(t,{x:e.x||0,y:e.y||0,width:0,height:0},this.getBoundingRect(),!0):this.removeRectText(t)},rM.prototype.onRemove=function(t){this.removeRectText(t)},rM.prototype.onAdd=function(t){this.appendRectText(t)}}d_.prototype={constructor:d_,getType:function(){return"vml"},getViewportRoot:function(){return this._vmlViewport},getViewportRootOffset:function(){var t=this.getViewportRoot();if(t)return{offsetLeft:t.offsetLeft||0,offsetTop:t.offsetTop||0}},refresh:function(){var t=this.storage.getDisplayList(!0,!0);this._paintList(t)},_paintList:function(t){for(var e=this._vmlRoot,i=0;i<t.length;i++){var n=t[i];n.invisible||n.ignore?(n.__alreadyNotVisible||n.onRemove(e),n.__alreadyNotVisible=!0):(n.__alreadyNotVisible&&n.onAdd(e),n.__alreadyNotVisible=!1,n.__dirty&&(n.beforeBrush&&n.beforeBrush(),(n.brushVML||n.brush).call(n,e),n.afterBrush&&n.afterBrush())),n.__dirty=!1}this._firstPaint&&(this._vmlViewport.appendChild(e),this._firstPaint=!1)},resize:function(t,e){var t=null==t?this._getWidth():t,e=null==e?this._getHeight():e;if(this._width!==t||this._height!==e){this._width=t,this._height=e;var i=this._vmlViewport.style;i.width=t+"px",i.height=e+"px"}},dispose:function(){this.root.innerHTML="",this._vmlRoot=this._vmlViewport=this.storage=null},getWidth:function(){return this._width},getHeight:function(){return this._height},clear:function(){this._vmlViewport&&this.root.removeChild(this._vmlViewport)},_getWidth:function(){var t=this.root,e=t.currentStyle;return(t.clientWidth||c_(e.width))-c_(e.paddingLeft)-c_(e.paddingRight)|0},_getHeight:function(){var t=this.root,e=t.currentStyle;return(t.clientHeight||c_(e.height))-c_(e.paddingTop)-c_(e.paddingBottom)|0}},d(["getLayer","insertLayer","eachLayer","eachBuiltinLayer","eachOtherLayer","getLayers","modLayer","delLayer","clearLayer","toDataURL","pathToImage"],function(t){d_.prototype[t]=f_(t)}),Ti("vml",d_);var sR="http://www.w3.org/2000/svg",lR=ES.CMD,uR=Array.prototype.join,hR="none",cR=Math.round,dR=Math.sin,fR=Math.cos,pR=Math.PI,gR=2*Math.PI,mR=180/pR,vR=1e-4,yR={};yR.brush=function(t){var e=t.style,i=t.__svgEl;i||(i=p_("path"),t.__svgEl=i),t.path||t.createPathProxy();var n=t.path;if(t.__dirtyPath){n.beginPath(),n.subPixelOptimize=!1,t.buildPath(n,t.shape),t.__dirtyPath=!1;var o=S_(n);o.indexOf("NaN")<0&&__(i,"d",o)}b_(i,e,!1,t),x_(i,t.transform),null!=e.text&&bR(t,t.getBoundingRect())};var xR={};xR.brush=function(t){var e=t.style,i=e.image;if(i instanceof HTMLImageElement&&(i=i.src),i){var n=e.x||0,o=e.y||0,a=e.width,r=e.height,s=t.__svgEl;s||(s=p_("image"),t.__svgEl=s),i!==t.__imageSrc&&(w_(s,"href",i),t.__imageSrc=i),__(s,"width",a),__(s,"height",r),__(s,"x",n),__(s,"y",o),x_(s,t.transform),null!=e.text&&bR(t,t.getBoundingRect())}};var _R={},wR=new de,bR=function(t,e,i){var n=t.style;t.__dirty&&Ye(n);var o=n.text;if(null!=o){o+="";var a=t.__textSvgEl;a||(a=p_("text"),t.__textSvgEl=a);var r,s,l=n.textPosition,u=n.textDistance,h=n.textAlign||"left";"number"==typeof n.fontSize&&(n.fontSize+="px");var c=n.font||[n.fontStyle||"",n.fontWeight||"",n.fontSize||"",n.fontFamily||""].join(" ")||wb,d=M_(n.textVerticalAlign),f=(i=ke(o,c,h,d,n.textPadding,n.textLineHeight)).lineHeight;if(l instanceof Array)r=e.x+l[0],s=e.y+l[1];else{var p=Re(l,e,u);r=p.x,s=p.y,d=M_(p.textVerticalAlign),h=p.textAlign}__(a,"alignment-baseline",d),c&&(a.style.font=c);var g=n.textPadding;if(__(a,"x",r),__(a,"y",s),b_(a,n,!0,t),t instanceof rM||t.style.transformText)x_(a,t.transform);else{if(t.transform)wR.copy(e),wR.applyTransform(t.transform),e=wR;else{var m=t.transformCoordToGlobal(e.x,e.y);e.x=m[0],e.y=m[1],t.transform=_t(xt())}var v=n.textOrigin;"center"===v?(r=i.width/2+r,s=i.height/2+s):v&&(r=v[0]+r,s=v[1]+s);var y=-n.textRotation||0,x=xt();Mt(x,x,y),St(x,x,m=[t.transform[4],t.transform[5]]),x_(a,x)}var _=o.split("\n"),w=_.length,b=h;"left"===b?(b="start",g&&(r+=g[3])):"right"===b?(b="end",g&&(r-=g[1])):"center"===b&&(b="middle",g&&(r+=(g[3]-g[1])/2));var S=0;if("after-edge"===d?(S=-i.height+f,g&&(S-=g[2])):"middle"===d?(S=(-i.height+f)/2,g&&(s+=(g[0]-g[2])/2)):g&&(S+=g[0]),t.__text!==o||t.__textFont!==c){var M=t.__tspanList||[];t.__tspanList=M;for(T=0;T<w;T++)(A=M[T])?A.innerHTML="":(A=M[T]=p_("tspan"),a.appendChild(A),__(A,"alignment-baseline",d),__(A,"text-anchor",b)),__(A,"x",r),__(A,"y",s+T*f+S),A.appendChild(document.createTextNode(_[T]));for(;T<M.length;T++)a.removeChild(M[T]);M.length=w,t.__text=o,t.__textFont=c}else if(t.__tspanList.length)for(var I=t.__tspanList.length,T=0;T<I;++T){var A=t.__tspanList[T];A&&(__(A,"x",r),__(A,"y",s+T*f+S))}}};_R.drawRectText=bR,_R.brush=function(t){var e=t.style;null!=e.text&&(e.textPosition=[0,0],bR(t,{x:e.x||0,y:e.y||0,width:0,height:0},t.getBoundingRect()))},I_.prototype={diff:function(t,e,i){i||(i=function(t,e){return t===e}),this.equals=i;var n=this;t=t.slice();var o=(e=e.slice()).length,a=t.length,r=1,s=o+a,l=[{newPos:-1,components:[]}],u=this.extractCommon(l[0],e,t,0);if(l[0].newPos+1>=o&&u+1>=a){for(var h=[],c=0;c<e.length;c++)h.push(c);return[{indices:h,count:e.length}]}for(;r<=s;){var d=function(){for(var i=-1*r;i<=r;i+=2){var s,u=l[i-1],h=l[i+1],c=(h?h.newPos:0)-i;u&&(l[i-1]=void 0);var d=u&&u.newPos+1<o,f=h&&0<=c&&c<a;if(d||f){if(!d||f&&u.newPos<h.newPos?(s=A_(h),n.pushComponent(s.components,void 0,!0)):((s=u).newPos++,n.pushComponent(s.components,!0,void 0)),c=n.extractCommon(s,e,t,i),s.newPos+1>=o&&c+1>=a)return T_(0,s.components);l[i]=s}else l[i]=void 0}r++}();if(d)return d}},pushComponent:function(t,e,i){var n=t[t.length-1];n&&n.added===e&&n.removed===i?t[t.length-1]={count:n.count+1,added:e,removed:i}:t.push({count:1,added:e,removed:i})},extractCommon:function(t,e,i,n){for(var o=e.length,a=i.length,r=t.newPos,s=r-n,l=0;r+1<o&&s+1<a&&this.equals(e[r+1],i[s+1]);)r++,s++,l++;return l&&t.components.push({count:l}),t.newPos=r,s},tokenize:function(t){return t.slice()},join:function(t){return t.slice()}};var SR=new I_,MR=function(t,e,i){return SR.diff(t,e,i)};D_.prototype.createElement=p_,D_.prototype.getDefs=function(t){var e=this._svgRoot,i=this._svgRoot.getElementsByTagName("defs");return 0===i.length?t?((i=e.insertBefore(this.createElement("defs"),e.firstChild)).contains||(i.contains=function(t){var e=i.children;if(!e)return!1;for(var n=e.length-1;n>=0;--n)if(e[n]===t)return!0;return!1}),i):null:i[0]},D_.prototype.update=function(t,e){if(t){var i=this.getDefs(!1);if(t[this._domName]&&i.contains(t[this._domName]))"function"==typeof e&&e(t);else{var n=this.add(t);n&&(t[this._domName]=n)}}},D_.prototype.addDom=function(t){this.getDefs(!0).appendChild(t)},D_.prototype.removeDom=function(t){var e=this.getDefs(!1);e&&t[this._domName]&&(e.removeChild(t[this._domName]),t[this._domName]=null)},D_.prototype.getDoms=function(){var t=this.getDefs(!1);if(!t)return[];var e=[];return d(this._tagNames,function(i){var n=t.getElementsByTagName(i);e=e.concat([].slice.call(n))}),e},D_.prototype.markAllUnused=function(){var t=this;d(this.getDoms(),function(e){e[t._markLabel]="0"})},D_.prototype.markUsed=function(t){t&&(t[this._markLabel]="1")},D_.prototype.removeUnused=function(){var t=this.getDefs(!1);if(t){var e=this;d(this.getDoms(),function(i){"1"!==i[e._markLabel]&&t.removeChild(i)})}},D_.prototype.getSvgProxy=function(t){return t instanceof Pn?yR:t instanceof fi?xR:t instanceof rM?_R:yR},D_.prototype.getTextSvgElement=function(t){return t.__textSvgEl},D_.prototype.getSvgElement=function(t){return t.__svgEl},u(C_,D_),C_.prototype.addWithoutUpdate=function(t,e){if(e&&e.style){var i=this;d(["fill","stroke"],function(n){if(e.style[n]&&("linear"===e.style[n].type||"radial"===e.style[n].type)){var o,a=e.style[n],r=i.getDefs(!0);a._dom?(o=a._dom,r.contains(a._dom)||i.addDom(o)):o=i.add(a),i.markUsed(e);var s=o.getAttribute("id");t.setAttribute(n,"url(#"+s+")")}})}},C_.prototype.add=function(t){var e;if("linear"===t.type)e=this.createElement("linearGradient");else{if("radial"!==t.type)return Yw("Illegal gradient type."),null;e=this.createElement("radialGradient")}return t.id=t.id||this.nextId++,e.setAttribute("id","zr"+this._zrId+"-gradient-"+t.id),this.updateDom(t,e),this.addDom(e),e},C_.prototype.update=function(t){var e=this;D_.prototype.update.call(this,t,function(){var i=t.type,n=t._dom.tagName;"linear"===i&&"linearGradient"===n||"radial"===i&&"radialGradient"===n?e.updateDom(t,t._dom):(e.removeDom(t),e.add(t))})},C_.prototype.updateDom=function(t,e){if("linear"===t.type)e.setAttribute("x1",t.x),e.setAttribute("y1",t.y),e.setAttribute("x2",t.x2),e.setAttribute("y2",t.y2);else{if("radial"!==t.type)return void Yw("Illegal gradient type.");e.setAttribute("cx",t.x),e.setAttribute("cy",t.y),e.setAttribute("r",t.r)}t.global?e.setAttribute("gradientUnits","userSpaceOnUse"):e.setAttribute("gradientUnits","objectBoundingBox"),e.innerHTML="";for(var i=t.colorStops,n=0,o=i.length;n<o;++n){var a=this.createElement("stop");a.setAttribute("offset",100*i[n].offset+"%");var r=i[n].color;if(r.indexOf(!1)){var s=Gt(r)[3],l=Zt(r);a.setAttribute("stop-color","#"+l),a.setAttribute("stop-opacity",s)}else a.setAttribute("stop-color",i[n].color);e.appendChild(a)}t._dom=e},C_.prototype.markUsed=function(t){if(t.style){var e=t.style.fill;e&&e._dom&&D_.prototype.markUsed.call(this,e._dom),(e=t.style.stroke)&&e._dom&&D_.prototype.markUsed.call(this,e._dom)}},u(L_,D_),L_.prototype.update=function(t){var e=this.getSvgElement(t);e&&this.updateDom(e,t.__clipPaths,!1);var i=this.getTextSvgElement(t);i&&this.updateDom(i,t.__clipPaths,!0),this.markUsed(t)},L_.prototype.updateDom=function(t,e,i){if(e&&e.length>0){var n,o,a=this.getDefs(!0),r=e[0],s=i?"_textDom":"_dom";r[s]?(o=r[s].getAttribute("id"),n=r[s],a.contains(n)||a.appendChild(n)):(o="zr"+this._zrId+"-clip-"+this.nextId,++this.nextId,(n=this.createElement("clipPath")).setAttribute("id",o),a.appendChild(n),r[s]=n);var l=this.getSvgProxy(r);if(r.transform&&r.parent.invTransform&&!i){var u=Array.prototype.slice.call(r.transform);bt(r.transform,r.parent.invTransform,r.transform),l.brush(r),r.transform=u}else l.brush(r);var h=this.getSvgElement(r);n.innerHTML="",n.appendChild(h.cloneNode()),t.setAttribute("clip-path","url(#"+o+")"),e.length>1&&this.updateDom(n,e.slice(1),i)}else t&&t.setAttribute("clip-path","none")},L_.prototype.markUsed=function(t){var e=this;t.__clipPaths&&t.__clipPaths.length>0&&d(t.__clipPaths,function(t){t._dom&&D_.prototype.markUsed.call(e,t._dom),t._textDom&&D_.prototype.markUsed.call(e,t._textDom)})},u(k_,D_),k_.prototype.addWithoutUpdate=function(t,e){if(e&&P_(e.style)){var i,n=e.style;n._shadowDom?(i=n._shadowDom,this.getDefs(!0).contains(n._shadowDom)||this.addDom(i)):i=this.add(e),this.markUsed(e);var o=i.getAttribute("id");t.style.filter="url(#"+o+")"}},k_.prototype.add=function(t){var e=this.createElement("filter"),i=t.style;return i._shadowDomId=i._shadowDomId||this.nextId++,e.setAttribute("id","zr"+this._zrId+"-shadow-"+i._shadowDomId),this.updateDom(t,e),this.addDom(e),e},k_.prototype.update=function(t,e){var i=e.style;if(P_(i)){var n=this;D_.prototype.update.call(this,e,function(t){n.updateDom(e,t._shadowDom)})}else this.remove(t,i)},k_.prototype.remove=function(t,e){null!=e._shadowDomId&&(this.removeDom(e),t.style.filter="")},k_.prototype.updateDom=function(t,e){var i=e.getElementsByTagName("feDropShadow");i=0===i.length?this.createElement("feDropShadow"):i[0];var n,o,a,r,s=t.style,l=t.scale?t.scale[0]||1:1,u=t.scale?t.scale[1]||1:1;if(s.shadowBlur||s.shadowOffsetX||s.shadowOffsetY)n=s.shadowOffsetX||0,o=s.shadowOffsetY||0,a=s.shadowBlur,r=s.shadowColor;else{if(!s.textShadowBlur)return void this.removeDom(e,s);n=s.textShadowOffsetX||0,o=s.textShadowOffsetY||0,a=s.textShadowBlur,r=s.textShadowColor}i.setAttribute("dx",n/l),i.setAttribute("dy",o/u),i.setAttribute("flood-color",r);var h=a/2/l+" "+a/2/u;i.setAttribute("stdDeviation",h),e.setAttribute("x","-100%"),e.setAttribute("y","-100%"),e.setAttribute("width",Math.ceil(a/2*200)+"%"),e.setAttribute("height",Math.ceil(a/2*200)+"%"),e.appendChild(i),s._shadowDom=e},k_.prototype.markUsed=function(t){var e=t.style;e&&e._shadowDom&&D_.prototype.markUsed.call(this,e._shadowDom)};var IR=function(t,e,i,n){this.root=t,this.storage=e,this._opts=i=a({},i||{});var o=p_("svg");o.setAttribute("xmlns","http://www.w3.org/2000/svg"),o.setAttribute("version","1.1"),o.setAttribute("baseProfile","full"),o.style.cssText="user-select:none;position:absolute;left:0;top:0;",this.gradientManager=new C_(n,o),this.clipPathManager=new L_(n,o),this.shadowManager=new k_(n,o);var r=document.createElement("div");r.style.cssText="overflow:hidden;position:relative",this._svgRoot=o,this._viewport=r,t.appendChild(r),r.appendChild(o),this.resize(i.width,i.height),this._visibleList=[]};IR.prototype={constructor:IR,getType:function(){return"svg"},getViewportRoot:function(){return this._viewport},getViewportRootOffset:function(){var t=this.getViewportRoot();if(t)return{offsetLeft:t.offsetLeft||0,offsetTop:t.offsetTop||0}},refresh:function(){var t=this.storage.getDisplayList(!0);this._paintList(t)},setBackgroundColor:function(t){this._viewport.style.background=t},_paintList:function(t){this.gradientManager.markAllUnused(),this.clipPathManager.markAllUnused(),this.shadowManager.markAllUnused();var e,i=this._svgRoot,n=this._visibleList,o=t.length,a=[];for(e=0;e<o;e++){var r=O_(f=t[e]),s=G_(f)||V_(f);f.invisible||(f.__dirty&&(r&&r.brush(f),this.clipPathManager.update(f),f.style&&(this.gradientManager.update(f.style.fill),this.gradientManager.update(f.style.stroke),this.shadowManager.update(s,f)),f.__dirty=!1),a.push(f))}var l,u=MR(n,a);for(e=0;e<u.length;e++)if((c=u[e]).removed)for(d=0;d<c.count;d++){var s=G_(f=n[c.indices[d]]),h=V_(f);B_(i,s),B_(i,h)}for(e=0;e<u.length;e++){var c=u[e];if(c.added)for(d=0;d<c.count;d++){var s=G_(f=a[c.indices[d]]),h=V_(f);l?R_(i,s,l):z_(i,s),s?R_(i,h,s):l?R_(i,h,l):z_(i,h),R_(i,h,s),l=h||s||l,this.gradientManager.addWithoutUpdate(s,f),this.shadowManager.addWithoutUpdate(l,f),this.clipPathManager.markUsed(f)}else if(!c.removed)for(var d=0;d<c.count;d++){var f=a[c.indices[d]];l=s=V_(f)||G_(f)||l,this.gradientManager.markUsed(f),this.gradientManager.addWithoutUpdate(s,f),this.shadowManager.markUsed(f),this.shadowManager.addWithoutUpdate(s,f),this.clipPathManager.markUsed(f)}}this.gradientManager.removeUnused(),this.clipPathManager.removeUnused(),this.shadowManager.removeUnused(),this._visibleList=a},_getDefs:function(t){var e=this._svgRoot,i=this._svgRoot.getElementsByTagName("defs");return 0===i.length?t?((i=e.insertBefore(p_("defs"),e.firstChild)).contains||(i.contains=function(t){var e=i.children;if(!e)return!1;for(var n=e.length-1;n>=0;--n)if(e[n]===t)return!0;return!1}),i):null:i[0]},resize:function(t,e){var i=this._viewport;i.style.display="none";var n=this._opts;if(null!=t&&(n.width=t),null!=e&&(n.height=e),t=this._getSize(0),e=this._getSize(1),i.style.display="",this._width!==t||this._height!==e){this._width=t,this._height=e;var o=i.style;o.width=t+"px",o.height=e+"px";var a=this._svgRoot;a.setAttribute("width",t),a.setAttribute("height",e)}},getWidth:function(){return this._width},getHeight:function(){return this._height},_getSize:function(t){var e=this._opts,i=["width","height"][t],n=["clientWidth","clientHeight"][t],o=["paddingLeft","paddingTop"][t],a=["paddingRight","paddingBottom"][t];if(null!=e[i]&&"auto"!==e[i])return parseFloat(e[i]);var r=this.root,s=document.defaultView.getComputedStyle(r);return(r[n]||N_(s[i])||N_(r.style[i]))-(N_(s[o])||0)-(N_(s[a])||0)|0},dispose:function(){this.root.innerHTML="",this._svgRoot=this._viewport=this.storage=null},clear:function(){this._viewport&&this.root.removeChild(this._viewport)},pathToDataUrl:function(){return this.refresh(),"data:image/svg+xml;charset=UTF-8,"+this._svgRoot.outerHTML}},d(["getLayer","insertLayer","eachLayer","eachBuiltinLayer","eachOtherLayer","getLayers","modLayer","delLayer","clearLayer","toDataURL","pathToImage"],function(t){IR.prototype[t]=F_(t)}),Ti("svg",IR),t.version="4.2.1",t.dependencies=ET,t.PRIORITY=VT,t.init=function(t,e,i){var n=ks(t);if(n)return n;var o=new us(t,e,i);return o.id="ec_"+iA++,tA[o.id]=o,Fi(t,oA,o.id),Cs(o),o},t.connect=function(t){if(y(t)){var e=t;t=null,kT(e,function(e){null!=e.group&&(t=e.group)}),t=t||"g_"+nA++,kT(e,function(e){e.group=t})}return eA[t]=!0,t},t.disConnect=Ls,t.disconnect=aA,t.dispose=function(t){"string"==typeof t?t=tA[t]:t instanceof us||(t=ks(t)),t instanceof us&&!t.isDisposed()&&t.dispose()},t.getInstanceByDom=ks,t.getInstanceById=function(t){return tA[t]},t.registerTheme=Ps,t.registerPreprocessor=Ns,t.registerProcessor=Os,t.registerPostUpdate=function(t){KT.push(t)},t.registerAction=Es,t.registerCoordinateSystem=Rs,t.getCoordinateSystemDimensions=function(t){var e=Fa.get(t);if(e)return e.getDimensionsInfo?e.getDimensionsInfo():e.dimensions.slice()},t.registerLayout=zs,t.registerVisual=Bs,t.registerLoading=Gs,t.extendComponentModel=Fs,t.extendComponentView=Ws,t.extendSeriesModel=Hs,t.extendChartView=Zs,t.setCanvasCreator=function(t){e("createCanvas",t)},t.registerMap=function(t,e,i){DT.registerMap(t,e,i)},t.getMap=function(t){var e=DT.retrieveMap(t);return e&&e[0]&&{geoJson:e[0].geoJSON,specialAreas:e[0].specialAreas}},t.dataTool=rA,t.zrender=Hb,t.number=YM,t.format=eI,t.throttle=Pr,t.helper=tD,t.matrix=Sw,t.vector=cw,t.color=Ww,t.parseGeoJSON=iD,t.parseGeoJson=rD,t.util=sD,t.graphic=lD,t.List=vA,t.Model=No,t.Axis=aD,t.env=U_});
+
+
+(function (root, factory) {
+    if (typeof define === 'function' && define.amd) {
+        // AMD. Register as an anonymous module.
+        define(['exports', 'echarts'], factory);
+    } else if (typeof exports === 'object' && typeof exports.nodeName !== 'string') {
+        // CommonJS
+        factory(exports, require('echarts'));
+    } else {
+        // Browser globals
+        factory({}, root.echarts);
+    }
+}(this, function (exports, echarts) {
+    var log = function (msg) {
+        if (typeof console !== 'undefined') {
+            console && console.error && console.error(msg);
+        }
+    }
+    if (!echarts) {
+        log('ECharts is not Loaded');
+        return;
+    }
+    if (!echarts.registerMap) {
+        log('ECharts Map is not loaded')
+        return;
+    }
+    echarts.registerMap('china', {"type":"FeatureCollection","features":[{"id":"710000","type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[["@@°Ü¯Û"],["@@ƛĴÕƊÉɼģºðʀ\\ƎsÆNŌÔĚäœnÜƤɊĂǀĆĴžĤNJŨxĚĮǂƺòƌ‚–âÔ®ĮXŦţƸZûЋƕƑGđ¨ĭMó·ęcëƝɉlÝƯֹÅŃ^Ó·śŃNjƏďíåɛGɉ™¿@ăƑŽ¥ĘWǬÏĶŁâ"],["@@\\p|WoYG¿¥I†j@¢"],["@@…¡‰@ˆV^RqˆBbAŒnTXeRz¤Lž«³I"],["@@ÆEE—„kWqë @œ"],["@@fced"]],"encodeOffsets":[[[122886,24033]],[[123335,22980]],[[122375,24193]],[[122518,24117]],[[124427,22618]],[[124862,26043]]]},"properties":{"cp":[121.509062,25.044332],"name":"台湾","childNum":6}},{"id":"130000","type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[["@@o~†Z]‚ªr‰ºc_ħ²G¼s`jΟnüsœłNX_“M`ǽÓnUK…Ĝēs¤­©yrý§uģŒc†JŠ›e"],["@@U`Ts¿m‚"],["@@oºƋÄd–eVŽDJj£€J|Ådz•Ft~žKŨ¸IÆv|”‡¢r}膎onb˜}`RÎÄn°ÒdÞ²„^®’lnÐèĄlðӜ×]ªÆ}LiĂ±Ö`^°Ç¶p®đDcœŋ`–ZÔ’¶êqvFƚ†N®ĆTH®¦O’¾ŠIbÐã´BĐɢŴÆíȦp–ĐÞXR€·nndOž¤’OÀĈƒ­Qg˜µFo|gȒęSWb©osx|hYh•gŃfmÖĩnº€T̒Sp›¢dYĤ¶UĈjl’ǐpäìë|³kÛfw²Xjz~ÂqbTŠÑ„ěŨ@|oM‡’zv¢ZrÃVw¬ŧˏfŒ°ÐT€ªqŽs{Sž¯r æÝlNd®²Ğ džiGʂJ™¼lr}~K¨ŸƐÌWö€™ÆŠzRš¤lêmĞL΄’@¡|q]SvK€ÑcwpÏρ†ĿćènĪWlĄkT}ˆJ”¤~ƒÈT„d„™pddʾĬŠ”ŽBVt„EÀ¢ôPĎƗè@~‚k–ü\\rÊĔÖæW_§¼F˜†´©òDòj’ˆYÈrbĞāøŀG{ƀ|¦ðrb|ÀH`pʞkv‚GpuARhÞÆǶgƊTǼƹS£¨¡ù³ŘÍ]¿Ây™ôEP xX¶¹܇O¡“gÚ¡IwÃ鑦ÅB‡Ï|ǰ…N«úmH¯‹âŸDùŽyŜžŲIÄuШDž•¸dɂ‡‚FŸƒ•›Oh‡đ©OŸ›iÃ`ww^ƒÌkŸ‘ÑH«ƇǤŗĺtFu…{Z}Ö@U‡´…ʚLg®¯Oı°ÃwŸ ^˜—€VbÉs‡ˆmA…ê]]w„§›RRl£‡ȭµu¯b{ÍDěïÿȧŽuT£ġƒěŗƃĝ“Q¨fV†Ƌ•ƅn­a@‘³@šď„yýIĹÊKšŭfċŰóŒxV@tˆƯŒJ”]eƒR¾fe|rHA˜|h~Ėƍl§ÏŠlTíb ØoˆÅbbx³^zÃ͚¶Sj®A”yÂhðk`š«P€”ˈµEF†Û¬Y¨Ļrõqi¼‰Wi°§’б´°^[ˆÀ|ĠO@ÆxO\\tŽa\\tĕtû{ġŒȧXýĪÓjùÎRb›š^ΛfK[ݏděYfíÙTyŽuUSyŌŏů@Oi½’éŅ­aVcř§ax¹XŻác‡žWU£ôãºQ¨÷Ñws¥qEH‰Ù|‰›šYQoŕÇyáĂ£MðoťÊ‰P¡mšWO¡€v†{ôvîēÜISpÌhp¨ ‘j†deŔQÖj˜X³à™Ĉ[n`Yp@Už–cM`’RKhŒEbœ”pŞlNut®Etq‚nsÁŠgA‹iú‹oH‡qCX‡”hfgu“~ϋWP½¢G^}¯ÅīGCŸÑ^ãziMáļMTÃƘrMc|O_ž¯Ŏ´|‡morDkO\\mĆJfl@c̬¢aĦtRıҙ¾ùƀ^juųœK­ƒUFy™—Ɲ…›īÛ÷ąV×qƥV¿aȉd³B›qPBm›aËđŻģm“Å®Vйd^K‡KoŸnYg“¯Xhqa”Ldu¥•ÍpDž¡KąÅƒkĝęěhq‡}HyÓ]¹ǧ£…Í÷¿qáµ§š™g‘¤o^á¾ZE‡¤i`ij{n•ƒOl»ŸWÝĔįhg›F[¿¡—ßkOüš_‰€ū‹i„DZàUtėGylƒ}ŒÓM}€jpEC~¡FtoQi‘šHkk{Ãmï‚"]],"encodeOffsets":[[[119712,40641]],[[121616,39981]],[[116462,37237]]]},"properties":{"cp":[114.502461,38.045474],"name":"河北","childNum":3}},{"id":"140000","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@Þĩ҃S‰ra}Á€yWix±Üe´lè“ßÓǏok‘ćiµVZģ¡coœ‘TS˹ĪmnÕńe–hZg{gtwªpXaĚThȑp{¶Eh—®RćƑP¿£‘Pmc¸mQÝW•ďȥoÅîɡųAďä³aωJ‘½¥PG­ąSM­™…EÅruµé€‘Yӎ•Ō_d›ĒCo­Èµ]¯_²ÕjāŽK~©ÅØ^ԛkïçămϑk]­±ƒcݯÑÃmQÍ~_a—pm…~ç¡q“ˆu{JÅŧ·Ls}–EyÁÆcI{¤IiCfUc•ƌÃp§]웫vD@¡SÀ‘µM‚ÅwuŽYY‡¡DbÑc¡hƒ×]nkoQdaMç~eD•ÛtT‰©±@¥ù@É¡‰ZcW|WqOJmĩl«ħşvOÓ«IqăV—¥ŸD[mI~Ó¢cehiÍ]Ɠ~ĥqXŠ·eƷœn±“}v•[ěďŽŕ]_‘œ•`‰¹ƒ§ÕōI™o©b­s^}Ét±ū«³p£ÿ·Wµ|¡¥ăFÏs׌¥ŅxŸÊdÒ{ºvĴÎêÌɊ²¶€ü¨|ÞƸµȲ‘LLúÉƎ¤ϊęĔV`„_bª‹S^|ŸdŠzY|dz¥p†ZbÆ£¶ÒK}tĦÔņƠ‚PYzn€ÍvX¶Ěn ĠÔ„zý¦ª˜÷žÑĸَUȌ¸‚dòÜJð´’ìúNM¬ŒXZ´‘¤ŊǸ_tldIš{¦ƀðĠȤ¥NehXnYG‚‡R° ƬDj¬¸|CĞ„Kq‚ºfƐiĺ©ª~ĆOQª ¤@ìǦɌ²æBŒÊ”TœŸ˜ʂōĖ’šĴŞ–ȀœÆÿȄlŤĒö„t”νî¼ĨXhŒ‘˜|ªM¤Ðz"],"encodeOffsets":[[116874,41716]]},"properties":{"cp":[112.549248,37.857014],"name":"山西","childNum":1}},{"id":"150000","type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[["@@Č^â£Ăh–šĖMÈÄw‚\\fŦ°W ¢¾luŸD„wŠ\\̀ʉÌÛM…Ā[bӞEn}¶Vc…ê“sƒ–›¯PqƒFB…‰|S•³C|kñ•H‹d‘iÄ¥sˆʼnő…PóÑÑE^‘ÅPpy_YtS™hQ·aHwsOnʼnÚs©iqj›‰€USiº]ïWš‰«gW¡A–R붛ijʕ…Œů`çõh]y»ǃŸǛҤxÒm~zf}pf|ÜroÈzrKÈĵSƧ„ż؜Ġu¦ö"],["@@sKCš…GS|úþX”gp›{ÁX¿Ÿć{ƱȏñZáĔyoÁhA™}ŅĆfdʼn„_¹„Y°ėǩÑ¡H¯¶oMQqð¡Ë™|‘Ñ`ƭŁX½·óۓxğįÅcQ‡ˆ“ƒs«tȋDžF“Ÿù^i‘t«Č¯[›hAi©á¥ÇĚ×l|¹y¯YȵƓ‹ñǙµï‚ċ™Ļ|Dœ™üȭ¶¡˜›oŽäÕG\\ďT¿Òõr¯œŸLguÏYęRƩšɷŌO\\İТæ^Ŋ IJȶȆbÜGŽĝ¬¿ĚVĎgª^íu½jÿĕęjık@Ľƒ]ėl¥Ë‡ĭûÁ„ƒėéV©±ćn©­ȇžÍq¯½•YÃÔʼn“ÉNѝÅÝy¹NqáʅDǡËñ­ƁYÅy̱os§ȋµʽǘǏƬɱà‘ưN¢ƔÊuľýľώȪƺɂļžxœZĈ}ÌʼnŪ˜ĺœŽĭFЛĽ̅ȣͽÒŵìƩÇϋÿȮǡŏçƑůĕ~Ǎ›¼ȳÐUf†dIxÿ\\G ˆzâɏÙOº·pqy£†@ŒŠqþ@Ǟ˽IBäƣzsÂZ†ÁàĻdñ°ŕzéØűzșCìDȐĴĺf®ŽÀľưø@ɜÖÞKĊŇƄ§‚͑těï͡VAġÑÑ»d³öǍÝXĉĕÖ{þĉu¸ËʅğU̎éhɹƆ̗̮ȘNJ֥ड़ࡰţાíϲäʮW¬®ҌeרūȠkɬɻ̼ãüfƠSצɩςåȈHϚÎKdzͲOðÏȆƘ¼CϚǚ࢚˼ФԂ¤ƌžĞ̪Qʤ´¼mȠJˀŸƲÀɠmǐnǔĎȆÞǠN~€ʢĜ‚¶ƌĆĘźʆȬ˪ĚǏĞGȖƴƀj`ĢçĶāàŃºē̃ĖćšYŒÀŎüôQÐÂŎŞdžŞêƖš˜oˆDĤÕºÑǘÛˤ³̀gńƘĔÀ^žªƂ`ªt¾äƚêĦĀ¼Ð€Ĕǎ¨Ȕ»͠^ˮÊȦƤøxRrŜH¤¸ÂxDĝŒ|ø˂˜ƮÐ¬ɚwɲFjĔ²Äw°dždÀɞ_ĸdîàŎjʜêTĞªŌ‡ŜWÈ|tqĢUB~´°ÎFC•ŽU¼pĀēƄN¦¾O¶ŠłKĊOj“Ě”j´ĜYp˜{¦„ˆSĚÍ\\Tš×ªV–÷Ší¨ÅDK°ßtŇĔKš¨ǵÂcḷ̌ĚǣȄĽF‡lġUĵœŇ‹ȣFʉɁƒMğįʏƶɷØŭOǽ«ƽū¹Ʊő̝Ȩ§ȞʘĖiɜɶʦ}¨֪ࠜ̀ƇǬ¹ǨE˦ĥªÔêFŽxúQ„Er´W„rh¤Ɛ \\talĈDJ˜Ü|[Pll̚¸ƎGú´Pž¬W¦†^¦–H]prR“n|or¾wLVnÇIujkmon£cX^Bh`¥V”„¦U¤¸}€xRj–[^xN[~ªŠxQ„‚[`ªHÆÂExx^wšN¶Ê˜|¨ì†˜€MrœdYp‚oRzNy˜ÀDs~€bcfÌ`L–¾n‹|¾T‚°c¨È¢a‚r¤–`[|òDŞĔöxElÖdH„ÀI`„Ď\\Àì~ƎR¼tf•¦^¢ķ¶e”ÐÚMŒptgj–„ɡČÅyġLû™ŇV®ŠÄÈƀ†Ď°P|ªVV†ªj–¬ĚÒêp¬–E|ŬÂc|ÀtƐK fˆ{ĘFǜƌXƲąo½Ę‘\\¥–o}›Ûu£ç­kX‘{uĩ«āíÓUŅßŢq€Ť¥lyň[€oi{¦‹L‡ń‡ðFȪȖ”ĒL„¿Ì‹ˆfŒ£K£ʺ™oqNŸƒwğc`ue—tOj×°KJ±qƒÆġm‰Ěŗos¬…qehqsuœƒH{¸kH¡Š…ÊRǪÇƌbȆ¢´ä܍¢NìÉʖ¦â©Ż؛Ç@Vu»A—ylßí¹ĵê…ÝlISò³C¹Ìâ„²i¶’Ìoú^H“²CǜңDŽ z¼g^èöŰ_‹‚–†IJĕꄜ}gÁnUI«m‰…„‹]j‡vV¼euhwqA„aW˜ƒ_µj…»çjioQR¹ēÃßt@r³[ÛlćË^ÍÉáG“›OUۗOB±•XŸkŇ¹£k|e]ol™ŸkVͼÕqtaÏõjgÁ£§U^Œ”RLˆËnX°Ç’Bz†^~wfvˆypV ¯„ƫĉ˭ȫƗŷɿÿĿƑ˃ĝÿÃǃßËőó©ǐȍŒĖM×ÍEyx‹þp]Évïè‘vƀnÂĴÖ@‚‰†V~Ĉ™Š³MEˆĸÅĖt—ējyÄDXÄxGQuv_›i¦aBçw‘˛wD™©{ŸtāmQ€{EJ§KPśƘƿ¥@‰sCT•É}ɃwˆƇy±ŸgÑ“}T[÷kÐ禫…SÒ¥¸ëBX½‰HáŵÀğtSÝÂa[ƣ°¯¦P]£ġ“–“Òk®G²„èQ°óMq}EŠóƐÇ\\ƒ‡@áügQ͋u¥Fƒ“T՛¿Jû‡]|mvāÎYua^WoÀa·­ząÒot×¶CLƗi¯¤mƎHNJ¤îìɾŊìTdåwsRÖgĒųúÍġäÕ}Q¶—ˆ¿A•†‹[¡Œ{d×uQAƒ›M•xV‹vMOmăl«ct[wº_šÇʊŽŸjb£ĦS_é“QZ“_lwgOiýe`YYLq§IÁˆdz£ÙË[ÕªuƏ³ÍT—s·bÁĽäė[›b[ˆŗfãcn¥îC¿÷µ[ŏÀQ­ōšĉm¿Á^£mJVm‡—L[{Ï_£›F¥Ö{ŹA}…×Wu©ÅaųijƳhB{·TQqÙIķˑZđ©Yc|M¡…L•eVUóK_QWk’_ĥ‘¿ãZ•»X\\ĴuUƒè‡lG®ěłTĠğDєOrÍd‚ÆÍz]‹±…ŭ©ŸÅ’]ŒÅÐ}UË¥©Tċ™ïxgckfWgi\\ÏĒ¥HkµE˜ë{»ÏetcG±ahUiñiWsɁˆ·c–C‚Õk]wȑ|ća}w…VaĚ᠞ŒG°ùnM¬¯†{ÈˆÐÆA’¥ÄêJxÙ¢”hP¢Ûˆº€µwWOŸóFŽšÁz^ÀŗÎú´§¢T¤ǻƺSė‰ǵhÝÅQgvBHouʝl_o¿Ga{ïq{¥|ſĿHĂ÷aĝÇq‡Z‘ñiñC³ª—…»E`¨åXēÕqÉû[l•}ç@čƘóO¿¡ƒFUsA‰“ʽīccšocƒ‚ƒÇS}„“£‡IS~ălkĩXçmĈ…ŀЂoÐdxÒuL^T{r@¢‘žÍƒĝKén£kQ™‰yšÅõËXŷƏL§~}kqš»IHėDžjĝŸ»ÑÞoŸå°qTt|r©ÏS‹¯·eŨĕx«È[eMˆ¿yuˆ‘pN~¹ÏyN£{©’—g‹ħWí»Í¾s“əšDž_ÃĀɗ±ą™ijĉʍŌŷ—S›É“A‹±åǥɋ@럣R©ąP©}ĹªƏj¹erƒLDĝ·{i«ƫC£µ"]],"encodeOffsets":[[[127444,52594]],[[113793,40312]]]},"properties":{"cp":[111.670801,40.818311],"name":"内蒙古","childNum":2}},{"id":"210000","type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[["@@L–Ž@@s™a"],["@@MnNm"],["@@d‚c"],["@@eÀ‚C@b‚“‰"],["@@f‡…Xwkbr–Ä`qg"],["@@^jtW‘Q"],["@@~ Y]c"],["@@G`ĔN^_¿Z‚ÃM"],["@@iX¶B‹Y"],["@@„YƒZ"],["@@L_{Epf"],["@@^WqCT\\"],["@@\\[“‹§t|”¤_"],["@@m`n_"],["@@Ïxnj{q_×^Giip"],["@@@œé^B†‡ntˆaÊU—˜Ÿ]x ¯ÄPIJ­°h€ʙK³†VˆÕ@Y~†|EvĹsDŽ¦­L^p²ŸÒG ’Ël]„xxÄ_˜fT¤Ď¤cŽœP„–C¨¸TVjbgH²sdÎdHt`Bˆ—²¬GJję¶[ÐhjeXdlwhšðSȦªVÊπ‹Æ‘Z˜ÆŶ®²†^ŒÎyÅÎcPqń“ĚDMħĜŁH­ˆk„çvV[ij¼W–‚YÀäĦ’‘`XlžR`žôLUVžfK–¢†{NZdĒª’YĸÌÚJRr¸SA|ƴgŴĴÆbvªØX~†źBŽ|¦ÕœEž¤Ð`\\|Kˆ˜UnnI]¤ÀÂĊnŎ™R®Ő¿¶\\ÀøíDm¦ÎbŨab‰œaĘ\\ľã‚¸a˜tÎSƐ´©v\\ÖÚÌǴ¤Â‡¨JKr€Z_Z€fjþhPkx€`Y”’RIŒjJcVf~sCN¤ ˆE‚œhæm‰–sHy¨SðÑÌ\\\\ŸĐRZk°IS§fqŒßýáЍÙÉÖ[^¯ǤŲ„ê´\\¦¬ĆPM¯£Ÿˆ»uïpùzEx€žanµyoluqe¦W^£ÊL}ñrkqWňûP™‰UP¡ôJŠoo·ŒU}£Œ„[·¨@XŒĸŸ“‹‹DXm­Ûݏº‡›GU‹CÁª½{íĂ^cj‡k“¶Ã[q¤“LÉö³cux«zZfƒ²BWÇ®Yß½ve±ÃC•ý£W{Ú^’q^sÑ·¨‹ÍOt“¹·C¥‡GD›rí@wÕKţ݋˜Ÿ«V·i}xËÍ÷‘i©ĝ‡ɝǡ]ƒˆ{c™±OW‹³Ya±Ÿ‰_穂Hžĕoƫ€Ňqƒr³‰Lys[„ñ³¯OS–ďOMisZ†±ÅFC¥Pq{‚Ã[Pg}\\—¿ghćO…•k^ģÁFıĉĥM­oEqqZûěʼn³F‘¦oĵ—hŸÕP{¯~TÍlª‰N‰ßY“Ð{Ps{ÃVU™™eĎwk±ʼnVÓ½ŽJãÇÇ»Jm°dhcÀff‘dF~ˆ€ĀeĖ€d`sx² šƒ®EżĀdQ‹Âd^~ăÔHˆ¦\\›LKpĄVez¤NP ǹӗR™ÆąJSh­a[¦´Âghwm€BÐ¨źhI|žVVŽ—Ž|p] Â¼èNä¶ÜBÖ¼“L`‚¼bØæŒKV”ŸpoœúNZÞÒKxpw|ÊEMnzEQšŽIZ”ŽZ‡NBˆčÚFÜçmĩ‚WĪñt‘ÞĵÇñZ«uD‚±|Əlij¥ãn·±PmÍa‰–da‡ CL‡Ǒkùó¡³Ï«QaċϑOÃ¥ÕđQȥċƭy‹³ÃA"]],"encodeOffsets":[[[123686,41445]],[[126019,40435]],[[124393,40128]],[[126117,39963]],[[125322,40140]],[[126686,40700]],[[126041,40374]],[[125584,40168]],[[125453,40165]],[[125362,40214]],[[125280,40291]],[[125774,39997]],[[125976,40496]],[[125822,39993]],[[125509,40217]],[[122731,40949]]]},"properties":{"cp":[123.429096,41.796767],"name":"辽宁","childNum":16}},{"id":"220000","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@‘p䔳PClƒFbbÍzš€wBG’ĭ€Z„Åi“»ƒlY­ċ²SgŽkÇ£—^S‰“qd¯•‹R…©éŽ£¯S†\\cZ¹iűƏCuƍÓX‡oR}“M^o•£…R}oªU­F…uuXHlEŕ‡€Ï©¤ÛmTŽþ¤D–²ÄufàÀ­XXȱAe„yYw¬dvõ´KÊ£”\\rµÄl”iˆdā]|DÂVŒœH¹ˆÞ®ÜWnŒC”Œķ W‹§@\\¸‹ƒ~¤‹Vp¸‰póIO¢ŠVOšŇürXql~òÉK]¤¥Xrfkvzpm¶bwyFoúvð‡¼¤ N°ąO¥«³[ƒéǡű_°Õ\\ÚÊĝŽþâőàerR¨­JYlďQ[ ÏYëЧTGz•tnŠß¡gFkMŸāGÁ¤ia É‰™È¹`\\xs€¬dĆkNnuNUŠ–užP@‚vRY¾•–\\¢…ŒGªóĄ~RãÖÎĢù‚đŴÕhQŽxtcæëSɽʼníëlj£ƍG£nj°KƘµDsØÑpyƸ®¿bXp‚]vbÍZuĂ{nˆ^IüœÀSք”¦EŒvRÎûh@℈[‚Əȉô~FNr¯ôçR±ƒ­HÑl•’Ģ–^¤¢‚OðŸŒævxsŒ]ÞÁTĠs¶¿âƊGW¾ìA¦·TѬ†è¥€ÏÐJ¨¼ÒÖ¼ƒƦɄxÊ~S–tD@ŠĂ¼Ŵ¡jlºWžvЉˆzƦZЎ²CH— „Axiukd‹ŒGgetqmcžÛ£Ozy¥cE}|…¾cZ…k‚‰¿uŐã[oxGikfeäT@…šSUwpiÚFM©’£è^ڟ‚`@v¶eň†f h˜eP¶žt“äOlÔUgƒÞzŸU`lœ}ÔÆUvØ_Ō¬Öi^ĉi§²ÃŠB~¡Ĉ™ÚEgc|DC_Ȧm²rBx¼MÔ¦ŮdĨÃâYx‘ƘDVÇĺĿg¿cwÅ\\¹˜¥Yĭlœ¤žOv†šLjM_a W`zļMž·\\swqÝSA‡š—q‰Śij¯Š‘°kŠRē°wx^Đkǂғ„œž“œŽ„‹\\]˜nrĂ}²ĊŲÒøãh·M{yMzysěnĒġV·°“G³¼XÀ““™¤¹i´o¤ŃšŸÈ`̃DzÄUĞd\\i֚ŒˆmÈBĤÜɲDEh LG¾ƀľ{WaŒYÍȏĢĘÔRîĐj‹}Ǟ“ccj‡oUb½š{“h§Ǿ{K‹ƖµÎ÷žGĀÖŠåưÎs­l›•yiē«‹`姝H¥Ae^§„GK}iã\\c]v©ģZ“mÃ|“[M}ģTɟĵ‘Â`À–çm‰‘FK¥ÚíÁbXš³ÌQґHof{‰]e€pt·GŋĜYünĎųVY^’˜ydõkÅZW„«WUa~U·Sb•wGçǑ‚“iW^q‹F‚“›uNĝ—·Ew„‹UtW·Ýďæ©PuqEzwAV•—XR‰ãQ`­©GŒM‡ehc›c”ďϝd‡©ÑW_ϗYƅŒ»…é\\ƒɹ~ǙG³mØ©BšuT§Ĥ½¢Ã_ý‘L¡‘ýŸqT^rme™\\Pp•ZZbƒyŸ’uybQ—efµ]UhĿDCmûvašÙNSkCwn‰cćfv~…Y‹„ÇG"],"encodeOffsets":[[130196,42528]]},"properties":{"cp":[125.3245,43.886841],"name":"吉林","childNum":1}},{"id":"230000","type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[["@@ƨƒĶTLÇyqpÇÛqe{~oyen}s‰`q‡iXG”ù]Ëp½“©lɇÁp]Þñ´FÔ^f‘äîºkà˜z¼BUvÈ@"],["@@UƒµNÿ¥īè灋•HÍøƕ¶LŒǽ|g¨|”™Ža¾pViˆdd”~ÈiŒíďÓQġėǐZ΋ŽXb½|ſÃH½ŸKFgɱCģÛÇA‡n™‹jÕc[VĝDZÃ˄Ç_™ £ń³pŽj£º”š¿”»WH´¯”U¸đĢmžtĜyzzNN|g¸÷äűѱĉā~mq^—Œ[ƒ”››”ƒǁÑďlw]¯xQĔ‰¯l‰’€°řĴrŠ™˜BˆÞTxr[tޏĻN_yŸX`biN™Ku…P›£k‚ZĮ—¦[ºxÆÀdhŽĹŀUÈƗCw’áZħÄŭcÓ¥»NAw±qȥnD`{ChdÙFćš}¢‰A±Äj¨]ĊÕjŋ«×`VuÓś~_kŷVÝyh„“VkÄãPs”Oµ—fŸge‚Ň…µf@u_Ù ÙcŸªNªÙEojVx™T@†ãSefjlwH\\pŏäÀvŠŽlY†½d{†F~¦dyz¤PÜndsrhf‹HcŒvlwjFœ£G˜±DύƥY‡yϊu¹XikĿ¦ÏqƗǀOŜ¨LI|FRĂn sª|Cš˜zxAè¥bœfudTrFWÁ¹Am|˜ĔĕsķÆF‡´Nš‰}ć…UŠÕ@Áijſmužç’uð^ÊýowŒFzØÎĕNőžǏȎôªÌŒDŽàĀÄ˄ĞŀƒʀĀƘŸˮȬƬĊ°ƒUŸzou‡xe]}Ž…AyȑW¯ÌmK‡“Q]‹Īºif¸ÄX|sZt|½ÚUΠlkš^p{f¤lˆºlÆW –€A²˜PVܜPH”Êâ]ÎĈÌÜk´\\@qàsĔÄQºpRij¼èi†`¶—„bXƒrBgxfv»ŽuUiˆŒ^v~”J¬mVp´£Œ´VWrnP½ì¢BX‚¬h™ŠðX¹^TjVœŠriªj™tŊÄm€tPGx¸bgRšŽsT`ZozÆO]’ÒFô҆Oƒ‡ŊŒvŞ”p’cGŒêŠsx´DR–Œ{A†„EOr°Œ•žx|íœbˆ³Wm~DVjºéNN†Ëܲɶ­GƒxŷCStŸ}]ûō•SmtuÇÃĕN•™āg»šíT«u}ç½BĵÞʣ¥ëÊ¡Mێ³ãȅ¡ƋaǩÈÉQ‰†G¢·lG|›„tvgrrf«†ptęŘnŠÅĢr„I²¯LiØsPf˜_vĠd„xM prʹšL¤‹¤‡eˌƒÀđK“žïÙVY§]I‡óáĥ]ķ†Kˆ¥Œj|pŇ\\kzţ¦šnņäÔVĂîά|vW’®l¤èØr‚˜•xm¶ă~lÄƯĄ̈́öȄEÔ¤ØQĄ–Ą»ƢjȦOǺ¨ìSŖÆƬy”Qœv`–cwƒZSÌ®ü±DŽ]ŀç¬B¬©ńzƺŷɄeeOĨS’Œfm Ċ‚ƀP̎ēz©Ċ‚ÄÕÊmgŸÇsJ¥ƔˆŊśæ’΁Ñqv¿íUOµª‰ÂnĦÁ_½ä@ê텣P}Ġ[@gġ}g“ɊדûÏWXá¢užƻÌsNͽƎÁ§č՛AēeL³àydl›¦ĘVçŁpśdžĽĺſʃQíÜçÛġԏsĕ¬—Ǹ¯YßċġHµ ¡eå`ļƒrĉŘóƢFì“ĎWøxÊk†”ƈdƬv|–I|·©NqńRŀƒ¤é”eŊœŀ›ˆàŀU²ŕƀB‚Q£Ď}L¹Îk@©ĈuǰųǨ”Ú§ƈnTËÇéƟÊcfčŤ^Xm‡—HĊĕË«W·ċëx³ǔķÐċJā‚wİ_ĸ˜Ȁ^ôWr­°oú¬Ħ…ŨK~”ȰCĐ´Ƕ£’fNÎèâw¢XnŮeÂÆĶŽ¾¾xäLĴĘlļO¤ÒĨA¢Êɚ¨®‚ØCÔ ŬGƠ”ƦYĜ‡ĘÜƬDJ—g_ͥœ@čŅĻA“¶¯@wÎqC½Ĉ»NŸăëK™ďÍQ“Ùƫ[«Ãí•gßÔÇOÝáW‘ñuZ“¯ĥ€Ÿŕā¡ÑķJu¤E Ÿå¯°WKɱ_d_}}vyŸõu¬ï¹ÓU±½@gÏ¿rýD‰†g…Cd‰µ—°MFYxw¿CG£‹Rƛ½Õ{]L§{qqąš¿BÇƻğëšܭNJË|c²}Fµ}›ÙRsÓpg±ŠQNqǫŋRwŕnéÑÉKŸ†«SeYR…ŋ‹@{¤SJ}šD Ûǖ֍Ÿ]gr¡µŷjqWÛham³~S«“„›Þ]"]],"encodeOffsets":[[[127123,51780]],[[134456,44547]]]},"properties":{"cp":[126.642464,45.756967],"name":"黑龙江","childNum":2}},{"id":"320000","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@cþÅPiŠ`ZŸRu¥É\\]~°ŽY`µ†Óƒ^phÁbnÀşúŽòa–ĬºTÖŒb‚˜e¦¦€{¸ZâćNpŒ©žHr|^ˆmjhŠSEb\\afv`sz^lkŽlj‹Ätg‹¤D˜­¾Xš¿À’|ДiZ„ȀåB·î}GL¢õcßjaŸyBFµÏC^ĭ•cÙt¿sğH]j{s©HM¢ƒQnDÀ©DaÜތ·jgàiDbPufjDk`dPOîƒhw¡ĥ‡¥šG˜ŸP²ĐobºrY†„î¶aHŢ´ ]´‚rılw³r_{£DB_Ûdåuk|ˆŨ¯F Cºyr{XFy™e³Þċ‡¿Â™kĭB¿„MvÛpm`rÚã”@ƹhågËÖƿxnlč¶Åì½Ot¾dJlŠVJʜǀœŞqvnOŠ^ŸJ”Z‘ż·Q}ê͎ÅmµÒ]Žƍ¦Dq}¬R^èĂ´ŀĻĊIԒtžIJyQŐĠMNtœR®òLh‰›Ěs©»œ}OӌGZz¶A\\jĨFˆäOĤ˜HYš†JvÞHNiÜaϚɖnFQlšNM¤ˆB´ĄNöɂtp–Ŭdf先‹qm¿QûŠùއÚb¤uŃJŴu»¹Ą•lȖħŴw̌ŵ²ǹǠ͛hĭłƕrçü±Y™xci‡tğ®jű¢KOķ•Coy`å®VTa­_Ā]ŐÝɞï²ʯÊ^]afYǸÃĆēĪȣJđ͍ôƋĝÄ͎ī‰çÛɈǥ£­ÛmY`ó£Z«§°Ó³QafusNıDž_k}¢m[ÝóDµ—¡RLčiXy‡ÅNïă¡¸iĔϑNÌŕoēdōîåŤûHcs}~Ûwbù¹£¦ÓCt‹OPrƒE^ÒoŠg™ĉIµžÛÅʹK…¤½phMŠü`o怆ŀ"],"encodeOffsets":[[121740,32276]]},"properties":{"cp":[118.767413,32.041544],"name":"江苏","childNum":1}},{"id":"330000","type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[["@@E^dQ]K"],["@@jX^j‡"],["@@sfŠbU‡"],["@@qP\\xz[ck"],["@@‘Rƒ¢‚FX}°[s_"],["@@Cbœ\\—}"],["@@e|v\\la{u"],["@@v~u}"],["@@QxÂF¯}"],["@@¹nŒvÞs¯o"],["@@rSkUEj"],["@@bi­ZŒP"],["@@p[}INf"],["@@À¿€"],["@@¹dnbŒ…"],["@@rSŸBnR"],["@@g~h}"],["@@FlEk"],["@@OdPc"],["@@v[u\\"],["@@FjâL~wyoo~›sµL–\\"],["@@¬e¹aNˆ"],["@@\\nÔ¡q]L³ë\\ÿ®ŒQ֎"],["@@ÊA­©[¬"],["@@KxŒv­"],["@@@hlIk]"],["@@pW{o||j"],["@@Md|_mC"],["@@¢…X£ÏylD¼XˆtH"],["@@hlÜ[LykAvyfw^Ež›¤"],["@@fp¤Mus“R"],["@@®_ma~•LÁ¬šZ"],["@@iM„xZ"],["@@ZcYd"],["@@Z~dOSo|A¿qZv"],["@@@`”EN¡v"],["@@|–TY{"],["@@@n@m"],["@@XWkCT\\"],["@@ºwšZRkĕWO¢"],["@@™X®±Grƪ\\ÔáXq{‹"],["@@ůTG°ĄLHm°UC‹"],["@@¤Ž€aÜx~}dtüGæţŎíĔcŖpMËВj碷ðĄÆMzˆjWKĎ¢Q¶˜À_꒔_Bı€i«pZ€gf€¤Nrq]§ĂN®«H±‡yƳí¾×ŸīàLłčŴǝĂíÀBŖÕªˆŠÁŖHŗʼnåqûõi¨hÜ·ƒñt»¹ýv_[«¸m‰YL¯‰Qª…mĉÅdMˆ•gÇjcº«•ęœ¬­K­´ƒB«Âącoċ\\xKd¡gěŧ«®á’[~ıxu·Å”KsËɏc¢Ù\\ĭƛëbf¹­ģSƒĜkáƉÔ­ĈZB{ŠaM‘µ‰fzʼnfåÂŧįƋǝÊĕġć£g³ne­ą»@­¦S®‚\\ßðCšh™iqªĭiAu‡A­µ”_W¥ƣO\\lċĢttC¨£t`ˆ™PZäuXßBs‡Ļyek€OđġĵHuXBšµ]׌‡­­\\›°®¬F¢¾pµ¼kŘó¬Wät’¸|@ž•L¨¸µr“ºù³Ù~§WI‹ŸZWŽ®’±Ð¨ÒÉx€`‰²pĜ•rOògtÁZ}þÙ]„’¡ŒŸFK‚wsPlU[}¦Rvn`hq¬\\”nQ´ĘRWb”‚_ rtČFI֊kŠŠĦPJ¶ÖÀÖJĈĄTĚòžC ²@Pú…Øzœ©PœCÈÚœĒ±„hŖ‡l¬â~nm¨f©–iļ«m‡nt–u†ÖZÜÄj“ŠLŽ®E̜Fª²iÊxبžIÈhhst"],["@@o\\V’zRZ}y"],["@@†@°¡mۛGĕ¨§Ianá[ýƤjfæ‡ØL–•äGr™"]],"encodeOffsets":[[[125592,31553]],[[125785,31436]],[[125729,31431]],[[125513,31380]],[[125223,30438]],[[125115,30114]],[[124815,29155]],[[124419,28746]],[[124095,28635]],[[124005,28609]],[[125000,30713]],[[125111,30698]],[[125078,30682]],[[125150,30684]],[[124014,28103]],[[125008,31331]],[[125411,31468]],[[125329,31479]],[[125626,30916]],[[125417,30956]],[[125254,30976]],[[125199,30997]],[[125095,31058]],[[125083,30915]],[[124885,31015]],[[125218,30798]],[[124867,30838]],[[124755,30788]],[[124802,30809]],[[125267,30657]],[[125218,30578]],[[125200,30562]],[[124968,30474]],[[125167,30396]],[[124955,29879]],[[124714,29781]],[[124762,29462]],[[124325,28754]],[[123990,28459]],[[125366,31477]],[[125115,30363]],[[125369,31139]],[[122495,31878]],[[125329,30690]],[[125192,30787]]]},"properties":{"cp":[120.153576,30.287459],"name":"浙江","childNum":45}},{"id":"340000","type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[["@@^iuLX^"],["@@‚e©Ehl"],["@@°ZÆëϵmkǀwÌÕæhºgBĝâqÙĊz›ÖgņtÀÁÊÆá’hEz|WzqD¹€Ÿ°E‡ŧl{ævÜcA`¤C`|´qžxIJkq^³³ŸGšµbƒíZ…¹qpa±ď OH—¦™Ħˆx¢„gPícOl_iCveaOjCh߸i݋bÛªCC¿€m„RV§¢A|t^iĠGÀtÚs–d]ĮÐDE¶zAb àiödK¡~H¸íæAžǿYƒ“j{ď¿‘™À½W—®£ChŒÃsiŒkkly]_teu[bFa‰Tig‡n{]Gqªo‹ĈMYá|·¥f¥—őaSÕė™NµñĞ«ImŒ_m¿Âa]uĜp …Z_§{Cƒäg¤°r[_Yj‰ÆOdý“[ŽI[á·¥“Q_n‡ùgL¾mv™ˊBÜÆ¶ĊJhšp“c¹˜O]iŠ]œ¥ jtsggJǧw×jÉ©±›EFˍ­‰Ki”ÛÃÕYv…s•ˆm¬njĻª•§emná}k«ŕˆƒgđ²Ù›DǤ›í¡ªOy›†×Où±@DŸñSęćăÕIÕ¿IµĥO‰‰jNÕËT¡¿tNæŇàåyķrĕq§ÄĩsWÆßŽF¶žX®¿‰mŒ™w…RIޓfßoG‘³¾©uyH‘į{Ɓħ¯AFnuP…ÍÔzšŒV—dàôº^Ðæd´€‡oG¤{S‰¬ćxã}›ŧ×Kǥĩ«žÕOEзÖdÖsƘѨ[’Û^Xr¢¼˜§xvěƵ`K”§ tÒ´Cvlo¸fzŨð¾NY´ı~ÉĔē…ßúLÃϖ_ÈÏ|]ÂÏFl”g`bšežž€n¾¢pU‚h~ƴ˶_‚r sĄ~cž”ƈ]|r c~`¼{À{ȒiJjz`îÀT¥Û³…]’u}›f…ïQl{skl“oNdŸjŸäËzDvčoQŠďHI¦rb“tHĔ~BmlRš—V_„ħTLnñH±’DžœL‘¼L˜ªl§Ťa¸ŒĚlK²€\\RòvDcÎJbt[¤€D@®hh~kt°ǾzÖ@¾ªdb„YhüóZ ň¶vHrľ\\ʗJuxAT|dmÀO„‹[ÃԋG·ĚąĐlŪÚpSJ¨ĸˆLvÞcPæķŨŽ®mАˆálŸwKhïgA¢ųƩޖ¤OȜm’°ŒK´"]],"encodeOffsets":[[[121722,32278]],[[119475,30423]],[[119168,35472]]]},"properties":{"cp":[117.283042,31.86119],"name":"安徽","childNum":3}},{"id":"350000","type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[["@@“zht´‡]"],["@@aj^~ĆG—©O"],["@@ed¨„C}}i"],["@@@vˆPGsQ"],["@@‰sBz‚ddW]Q"],["@@SލQ“{"],["@@NŽVucW"],["@@qptBAq"],["@@‰’¸[mu"],["@@Q\\pD]_"],["@@jSwUadpF"],["@@eXª~ƒ•"],["@@AjvFso"],["@@fT–›_Çí\\Ÿ™—v|ba¦jZÆy€°"],["@@IjJi"],["@@wJI€ˆxš«¼AoNe{M­"],["@@K‰±¡Óˆ”ČäeZ"],["@@k¡¹Eh~c®wBk‹UplÀ¡I•~Māe£bN¨gZý¡a±Öcp©PhžI”Ÿ¢Qq…ÇGj‹|¥U™ g[Ky¬ŏ–v@OpˆtÉEŸF„\\@ åA¬ˆV{Xģ‰ĐBy…cpě…¼³Ăp·¤ƒ¥o“hqqÚ¡ŅLsƒ^ᗞ§qlŸÀhH¨MCe»åÇGD¥zPO£čÙkJA¼ß–ėu›ĕeûҍiÁŧSW¥˜QŠûŗ½ùěcݧSùĩąSWó«íęACµ›eR—åǃRCÒÇZÍ¢‹ź±^dlsŒtjD¸•‚ZpužÔâÒH¾oLUêÃÔjjēò´ĄW‚ƛ…^Ñ¥‹ĦŸ@Çò–ŠmŒƒOw¡õyJ†yD}¢ďÑÈġfŠZd–a©º²z£šN–ƒjD°Ötj¶¬ZSÎ~¾c°¶Ðm˜x‚O¸¢Pl´žSL|¥žA†ȪĖM’ņIJg®áIJČĒü` ŽQF‡¬h|ÓJ@zµ |ê³È ¸UÖŬŬÀEttĸr‚]€˜ðŽM¤ĶIJHtÏ A’†žĬkvsq‡^aÎbvŒd–™fÊòSD€´Z^’xPsÞrv‹ƞŀ˜jJd×ŘÉ ®A–ΦĤd€xĆqAŒ†ZR”ÀMźŒnĊ»ŒİÐZ— YX–æJŠyĊ²ˆ·¶q§·–K@·{s‘Xãô«lŗ¶»o½E¡­«¢±¨Yˆ®Ø‹¶^A™vWĶGĒĢžPlzfˆļŽtàAvWYãšO_‡¤sD§ssČġ[kƤPX¦Ž`¶“ž®ˆBBvĪjv©šjx[L¥àï[F…¼ÍË»ğV`«•Ip™}ccÅĥZE‹ãoP…´B@ŠD—¸m±“z«Ƴ—¿å³BRضˆœWlâþäą`“]Z£Tc— ĹGµ¶H™m@_©—kŒ‰¾xĨ‡ôȉðX«½đCIbćqK³Á‹Äš¬OAwã»aLʼn‡ËĥW[“ÂGI—ÂNxij¤D¢ŽîĎÎB§°_JœGsƒ¥E@…¤uć…P‘å†cuMuw¢BI¿‡]zG¹guĮck\\_"]],"encodeOffsets":[[[123250,27563]],[[122541,27268]],[[123020,27189]],[[122916,27125]],[[122887,26845]],[[122808,26762]],[[122568,25912]],[[122778,26197]],[[122515,26757]],[[122816,26587]],[[123388,27005]],[[122450,26243]],[[122578,25962]],[[121255,25103]],[[120987,24903]],[[122339,25802]],[[121042,25093]],[[122439,26024]]]},"properties":{"cp":[119.306239,26.075302],"name":"福建","childNum":18}},{"id":"360000","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@ĢĨƐgÂMD~ņªe^\\^§„ý©j׍cZ†Ø¨zdÒa¶ˆlҍJŒìõ`oz÷@¤u޸´†ôęöY¼‰HČƶajlÞƩ¥éZ[”|h}^U Œ ¥p„ĄžƦO lt¸Æ €Q\\€ŠaÆ|CnÂOjt­ĚĤd’ÈŒF`’¶„@Ð딠¦ōҞ¨Sêv†HĢûXD®…QgėWiØPÞìºr¤dž€NĠ¢l–•ĄtZoœCƞÔºCxrpĠV®Ê{f_Y`_ƒeq’’®Aot`@o‚DXfkp¨|Šs¬\\D‘ÄSfè©Hn¬…^DhÆyøJh“ØxĢĀLʈ„ƠPżċĄwȠ̦G®ǒĤäTŠÆ~ĦwŠ«|TF¡Šn€c³Ïå¹]ĉđxe{ÎӐ†vOEm°BƂĨİ|G’vz½ª´€H’àp”eJ݆Qšxn‹ÀŠW­žEµàXÅĪt¨ÃĖrÄwÀFÎ|ňÓMå¼ibµ¯»åDT±m[“r«_gŽmQu~¥V\\OkxtL E¢‹ƒ‘Ú^~ýê‹Pó–qo슱_Êw§ÑªåƗ⼋mĉŹ‹¿NQ“…YB‹ąrwģcÍ¥B•Ÿ­ŗÊcØiI—žƝĿuŒqtāwO]‘³YCñTeɕš‹caub͈]trlu€ī…B‘ПGsĵıN£ï—^ķqss¿FūūV՟·´Ç{éĈý‰ÿ›OEˆR_ŸđûIċâJh­ŅıN‘ȩĕB…¦K{Tk³¡OP·wn—µÏd¯}½TÍ«YiµÕsC¯„iM•¤™­•¦¯P|ÿUHv“he¥oFTu‰õ\\ŽOSs‹MòđƇiaºćXŸĊĵà·çhƃ÷ǜ{‘ígu^›đg’m[×zkKN‘¶Õ»lčÓ{XSƉv©_ÈëJbVk„ĔVÀ¤P¾ºÈMÖxlò~ªÚàGĂ¢B„±’ÌŒK˜y’áV‡¼Ã~­…`g›ŸsÙfI›Ƌlę¹e|–~udjˆuTlXµf`¿JdŠ[\\˜„L‚‘²"],"encodeOffsets":[[116689,26234]]},"properties":{"cp":[115.892151,28.676493],"name":"江西","childNum":1}},{"id":"370000","type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[["@@Xjd]{K"],["@@itbFHy"],["@@HlGk"],["@@T‚ŒGŸy"],["@@K¬˜•‹U"],["@@WdXc"],["@@PtOs"],["@@•LnXhc"],["@@ppVƒu]Or"],["@@cdzAUa"],["@@udRhnCI‡"],["@@ˆoIƒpR„"],["@@Ľč{fzƤî’Kš–ÎMĮ]†—ZFˆ½Y]â£ph’™š¶¨râøÀ†ÎǨ¤^ºÄ”Gzˆ~grĚĜlĞÆ„LĆdž¢Îo¦–cv“Kb€gr°Wh”mZp ˆL]LºcU‰Æ­n”żĤÌǜbAnrOAœ´žȊcÀbƦUØrĆUÜøœĬƞ†š˜Ez„VL®öØBkŖÝĐ˹ŧ̄±ÀbÎɜnb²ĦhņBĖ›žįĦåXćì@L¯´ywƕCéõė ƿ¸‘lµ¾Z|†ZWyFYŸ¨Mf~C¿`€à_RÇzwƌfQnny´INoƬˆèôº|sT„JUš›‚L„îVj„ǎ¾Ē؍‚Dz²XPn±ŴPè¸ŔLƔÜƺ_T‘üÃĤBBċȉöA´fa„˜M¨{«M`‡¶d¡ô‰Ö°šmȰBÔjjŒ´PM|”c^d¤u•ƒ¤Û´Œä«ƢfPk¶Môlˆ]Lb„}su^ke{lC‘…M•rDŠÇ­]NÑFsmoõľH‰yGă{{çrnÓE‰‹ƕZGª¹Fj¢ïW…uøCǷ돡ąuhÛ¡^Kx•C`C\\bÅxì²ĝÝ¿_N‰īCȽĿåB¥¢·IŖÕy\\‡¹kx‡Ã£Č×GDyÕ¤ÁçFQ¡„KtŵƋ]CgÏAùSed‡cÚź—ŠuYfƒyMmhUWpSyGwMPqŀ—›Á¼zK›¶†G•­Y§Ëƒ@–´śÇµƕBmœ@Io‚g——Z¯u‹TMx}C‘‰VK‚ï{éƵP—™_K«™pÛÙqċtkkù]gŽ‹Tğwo•ɁsMõ³ă‡AN£™MRkmEʕč™ÛbMjÝGu…IZ™—GPģ‡ãħE[iµBEuŸDPԛ~ª¼ętŠœ]ŒûG§€¡QMsğNPŏįzs£Ug{đJĿļā³]ç«Qr~¥CƎÑ^n¶ÆéÎR~ݏY’I“] P‰umŝrƿ›‰›Iā‹[x‰edz‹L‘¯v¯s¬ÁY…~}…ťuٌg›ƋpÝĄ_ņī¶ÏSR´ÁP~ž¿Cyžċßdwk´Ss•X|t‰`Ä Èð€AªìÎT°¦Dd–€a^lĎDĶÚY°Ž`ĪŴǒˆ”àŠv\\ebŒZH„ŖR¬ŢƱùęO•ÑM­³FۃWp[ƒ"]],"encodeOffsets":[[[123806,39303]],[[123821,39266]],[[123742,39256]],[[123702,39203]],[[123649,39066]],[[123847,38933]],[[123580,38839]],[[123894,37288]],[[123043,36624]],[[123344,38676]],[[123522,38857]],[[123628,38858]],[[118260,36742]]]},"properties":{"cp":[117.000923,36.675807],"name":"山东","childNum":13}},{"id":"410000","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@•ýL™ùµP³swIÓxcŢĞð†´E®žÚPt†ĴXØx¶˜@«ŕŕQGƒ‹Yfa[şu“ßǩ™đš_X³ijÕčC]kbc•¥CS¯ëÍB©÷‹–³­Siˆ_}m˜YTtž³xlàcȂzÀD}ÂOQ³ÐTĨ¯†ƗòËŖ[hœł‹Ŧv~††}ÂZž«¤lPǕ£ªÝŴÅR§ØnhcŒtâk‡nύ­ľŹUÓÝdKuķ‡I§oTũÙďkęĆH¸ÓŒ\\ăŒ¿PcnS{wBIvɘĽ[GqµuŸŇôYgûƒZcaŽ©@½Õǽys¯}lgg@­C\\£as€IdÍuCQñ[L±ęk·‹ţb¨©kK—’»›KC²‘òGKmĨS`ƒ˜UQ™nk}AGē”sqaJ¥ĐGR‰ĎpCuÌy ã iMc”plk|tRk†ðœev~^‘´†¦ÜŽSí¿_iyjI|ȑ|¿_»d}qŸ^{“Ƈdă}Ÿtqµ`Ƴĕg}V¡om½fa™Ço³TTj¥„tĠ—Ry”K{ùÓjuµ{t}uËR‘iŸvGŠçJFjµŠÍyqΘàQÂFewixGw½Yŷpµú³XU›½ġy™łå‰kÚwZXˆ·l„¢Á¢K”zO„Λ΀jc¼htoDHr…|­J“½}JZ_¯iPq{tę½ĕ¦Zpĵø«kQ…Ťƒ]MÛfaQpě±ǽ¾]u­Fu‹÷nƒ™čįADp}AjmcEǒaª³o³ÆÍSƇĈÙDIzˑ赟^ˆKLœ—i—Þñ€[œƒaA²zz‰Ì÷Dœ|[šíijgf‚ÕÞd®|`ƒĆ~„oĠƑô³Ŋ‘D×°¯CsŠøÀ«ì‰UMhTº¨¸ǡîS–Ô„DruÂÇZ•ÖEŽ’vPZ„žW”~؋ÐtĄE¢¦Ðy¸bŠô´oŬ¬Ž²Ês~€€]®tªašpŎJ¨Öº„_ŠŔ–`’Ŗ^Ѝ\\Ĝu–”~m²Ƹ›¸fW‰ĦrƔ}Î^gjdfÔ¡J}\\n C˜¦þWxªJRÔŠu¬ĨĨmF†dM{\\d\\ŠYÊ¢ú@@¦ª²SŠÜsC–}fNècbpRmlØ^g„d¢aÒ¢CZˆZxvÆ¶N¿’¢T@€uCœ¬^ĊðÄn|žlGl’™Rjsp¢ED}€Fio~ÔNŽ‹„~zkĘHVsDzßjƒŬŒŠŢ`Pûàl¢˜\\ÀœEhŽİgÞē X¼Pk–„|m"],"encodeOffsets":[[118256,37017]]},"properties":{"cp":[113.665412,34.757975],"name":"河南","childNum":1}},{"id":"420000","type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[["@@AB‚"],["@@lskt"],["@@¾«}{ra®pîÃ\\™›{øCŠËyyB±„b\\›ò˜Ý˜jK›‡L ]ĎĽÌ’JyÚCƈćÎT´Å´pb©È‘dFin~BCo°BĎĚømvŒ®E^vǾ½Ĝ²Ro‚bÜeNŽ„^ĺ£R†¬lĶ÷YoĖ¥Ě¾|sOr°jY`~I”¾®I†{GqpCgyl{‡£œÍƒÍyPL“¡ƒ¡¸kW‡xYlÙæŠšŁĢzœ¾žV´W¶ùŸo¾ZHxjwfx„GNÁ•³Xéæl¶‰EièIH‰ u’jÌQ~v|sv¶Ôi|ú¢Fh˜Qsğ¦ƒSiŠBg™ÐE^ÁÐ{–čnOÂȞUÎóĔ†ÊēIJ}Z³½Mŧïeyp·uk³DsѨŸL“¶_œÅuèw»—€¡WqÜ]\\‘Ò§tƗcÕ¸ÕFÏǝĉăxŻČƟO‡ƒKÉġÿ×wg”÷IÅzCg†]m«ªGeçÃTC’«[‰t§{loWeC@ps_Bp‘­r‘„f_``Z|ei¡—oċMqow€¹DƝӛDYpûs•–‹Ykıǃ}s¥ç³[§ŸcYЧHK„«Qy‰]¢“wwö€¸ïx¼ņ¾Xv®ÇÀµRĠЋžHMž±cÏd„ƒǍũȅȷ±DSyúĝ£ŤĀàtÖÿï[îb\\}pĭÉI±Ñy…¿³x¯N‰o‰|¹H™ÏÛm‹júË~Tš•u˜ęjCöAwě¬R’đl¯ Ñb­‰ŇT†Ŀ_[Œ‘IčĄʿnM¦ğ\\É[T·™k¹œ©oĕ@A¾w•ya¥Y\\¥Âaz¯ãÁ¡k¥ne£Ûw†E©Êō¶˓uoj_Uƒ¡cF¹­[Wv“P©w—huÕyBF“ƒ`R‹qJUw\\i¡{jŸŸEPïÿ½fć…QÑÀQ{ž‚°‡fLԁ~wXg—ītêݾ–ĺ‘Hdˆ³fJd]‹HJ²…E€ƒoU¥†HhwQsƐ»Xmg±çve›]Dm͂PˆoCc¾‹_h”–høYrŊU¶eD°Č_N~øĹĚ·`z’]Äþp¼…äÌQŒv\\rCŒé¾TnkžŐڀÜa‡“¼ÝƆ̶Ûo…d…ĔňТJq’Pb ¾|JŒ¾fXŠƐîĨ_Z¯À}úƲ‹N_ĒĊ^„‘ĈaŐyp»CÇĕKŠšñL³ŠġMŒ²wrIÒŭxjb[œžn«øœ˜—æˆàƒ ^²­h¯Ú€ŐªÞ¸€Y²ĒVø}Ā^İ™´‚LŠÚm„¥ÀJÞ{JVŒųÞŃx×sxxƈē ģMř–ÚðòIf–Ċ“Œ\\Ʈ±ŒdʧĘD†vČ_Àæ~DŒċ´A®µ†¨ØLV¦êHÒ¤"]],"encodeOffsets":[[[113712,34000]],[[115612,30507]],[[113649,34054]]]},"properties":{"cp":[114.298572,30.584355],"name":"湖北","childNum":3}},{"id":"430000","type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[["@@—n„FTs"],["@@ßÅÆá‰½ÔXr—†CO™“…ËR‘ïÿĩ­TooQyšÓ[‹ŅBE¬–ÎÓXa„į§Ã¸G °ITxp‰úxÚij¥Ïš–̾ŠedžÄ©ĸG…œàGh‚€M¤–Â_U}Ċ}¢pczfŠþg¤€”ÇòAV‘‹M"],["@@©K—ƒA·³CQ±Á«³BUŠƑ¹AŠtćOw™D]ŒJiØSm¯b£‘ylƒ›X…HËѱH•«–‘C^õľA–Å§¤É¥„ïyuǙuA¢^{ÌC´­¦ŷJ£^[†“ª¿‡ĕ~•Ƈ…•N… skóā‡¹¿€ï]ă~÷O§­@—Vm¡‹Qđ¦¢Ĥ{ºjԏŽŒª¥nf´•~ÕoŸž×Ûą‹MąıuZœmZcÒ IJβSÊDŽŶ¨ƚƒ’CÖŎªQؼrŭŽ­«}NÏürʬŒmjr€@ĘrTW ­SsdHzƓ^ÇÂyUi¯DÅYlŹu{hTœ}mĉ–¹¥ě‰Dÿë©ıÓ[Oº£ž“¥ót€ł¹MՄžƪƒ`Pš…Di–ÛUоÅ‌ìˆU’ñB“È£ýhe‰dy¡oċ€`pfmjP~‚kZa…ZsÐd°wj§ƒ@€Ĵ®w~^‚kÀÅKvNmX\\¨a“”сqvíó¿F„¤¡@ũÑVw}S@j}¾«pĂr–ªg àÀ²NJ¶¶Dô…K‚|^ª†Ž°LX¾ŴäPᜣEXd›”^¶›IJÞܓ~‘u¸ǔ˜Ž›MRhsR…e†`ÄofIÔ\\Ø  i”ćymnú¨cj ¢»–GČìƊÿШXeĈ¾Oð Fi ¢|[jVxrIQŒ„_E”zAN¦zLU`œcªx”OTu RLÄ¢dV„i`p˔vŎµªÉžF~ƒØ€d¢ºgİàw¸Áb[¦Zb¦–z½xBĖ@ªpº›šlS¸Ö\\Ĕ[N¥ˀmĎă’J\\‹ŀ`€…ňSڊĖÁĐiO“Ĝ«BxDõĚiv—ž–S™Ì}iùŒžÜnšÐºGŠ{Šp°M´w†ÀÒzJ²ò¨ oTçüöoÛÿñŽőФ‚ùTz²CȆȸǎۃƑÐc°dPÎŸğ˶[Ƚu¯½WM¡­Éž“’B·rížnZŸÒ `‡¨GA¾\\pē˜XhÆRC­üWGġu…T靧Ŏѝ©ò³I±³}_‘‹EÃħg®ęisÁPDmÅ{‰b[Rşs·€kPŸŽƥƒóRo”O‹ŸVŸ~]{g\\“êYƪ¦kÝbiċƵŠGZ»Ěõ…ó·³vŝž£ø@pyö_‹ëŽIkѵ‡bcѧy…×dY؎ªiþž¨ƒ[]f]Ņ©C}ÁN‡»hĻħƏ’ĩ"]],"encodeOffsets":[[[115640,30489]],[[112543,27312]],[[116690,26230]]]},"properties":{"cp":[112.982279,28.19409],"name":"湖南","childNum":3}},{"id":"440000","type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[["@@QdˆAua"],["@@ƒlxDLo"],["@@sbhNLo"],["@@Ă āŸ"],["@@WltO[["],["@@Krœ]S"],["@@e„„I]y"],["@@I|„Mym"],["@@ƒÛ³LSŒž¼Y"],["@@nvºB–ëui©`¾"],["@@zdšÛ›Jw®"],["@@†°…¯"],["@@a yAª¸ËJIx،@€ĀHAmßV¡o•fu•o"],["@@šs‰ŗÃÔėAƁ›ZšÄ ~°ČP‚‹äh"],["@@‹¶Ý’Ì‚vmĞh­ı‡Q"],["@@HœŠdSjĒ¢D}war…“u«ZqadYM"],["@@elŒ\\LqqU"],["@@~rMo\\"],["@@f„^ƒC"],["@@øPªoj÷ÍÝħXČx”°Q¨ıXNv"],["@@gÇƳˆŽˆ”oˆŠˆ[~tly"],["@@E–ÆC¿‘"],["@@OŽP"],["@@w‹†đóg‰™ĝ—[³‹¡VÙæÅöM̳¹pÁaËýý©D©Ü“JŹƕģGą¤{Ùū…ǘO²«BƱéA—Ò‰ĥ‡¡«BhlmtÃPµyU¯uc“d·w_bŝcīímGOŽ|KP’ȏ‡ŹãŝIŕŭŕ@Óoo¿ē‹±ß}Ž…ŭ‚ŸIJWÈCőâUâǙI›ğʼn©I›ijEׅÁ”³Aó›wXJþ±ÌŒÜӔĨ£L]ĈÙƺZǾĆĖMĸĤfŒÎĵl•ŨnȈ‘ĐtF”Š–FĤ–‚êk¶œ^k°f¶gŠŽœ}®Fa˜f`vXŲxl˜„¦–ÔÁ²¬ÐŸ¦pqÊ̲ˆi€XŸØRDÎ}†Ä@ZĠ’s„x®AR~®ETtĄZ†–ƈfŠŠHâÒÐA†µ\\S¸„^wĖkRzŠalŽŜ|E¨ÈNĀňZTŒ’pBh£\\ŒĎƀuXĖtKL–¶G|Ž»ĺEļĞ~ÜĢÛĊrˆO˜Ùîvd]nˆ¬VœÊĜ°R֟pM††–‚ƂªFbwžEÀˆ˜©Œž\\…¤]ŸI®¥D³|ˎ]CöAŤ¦…æ’´¥¸Lv¼€•¢ĽBaô–F~—š®²GÌҐEY„„œzk¤’°ahlV՞I^‹šCxĈPŽsB‰ƒºV‰¸@¾ªR²ĨN]´_eavSi‡vc•}p}Đ¼ƌkJœÚe thœ†_¸ ºx±ò_xN›Ë‹²‘@ƒă¡ßH©Ùñ}wkNÕ¹ÇO½¿£ĕ]ly_WìIžÇª`ŠuTÅxYĒÖ¼k֞’µ‚MžjJÚwn\\h‘œĒv]îh|’È›Ƅøègž¸Ķß ĉĈWb¹ƀdéƌNTtP[ŠöSvrCZžžaGuœbo´ŖÒÇА~¡zCI…özx¢„Pn‹•‰Èñ @ŒĥÒ¦†]ƞŠV}³ăĔñiiÄÓVépKG½Ä‘ÓávYo–C·sit‹iaÀy„ŧΡÈYDÑům}‰ý|m[węõĉZÅxUO}÷N¹³ĉo_qtă“qwµŁYلǝŕ¹tïÛUïmRCº…ˆĭ|µ›ÕÊK™½R‘ē ó]‘–GªęAx–»HO£|ām‡¡diď×YïYWªʼnOeÚtĐ«zđ¹T…ā‡úE™á²\\‹ķÍ}jYàÙÆſ¿Çdğ·ùTßÇţʄ¡XgWÀLJğ·¿ÃˆOj YÇ÷Qě‹i"]],"encodeOffsets":[[[117381,22988]],[[116552,22934]],[[116790,22617]],[[116973,22545]],[[116444,22536]],[[116931,22515]],[[116496,22490]],[[116453,22449]],[[113301,21439]],[[118726,21604]],[[118709,21486]],[[113210,20816]],[[115482,22082]],[[113171,21585]],[[113199,21590]],[[115232,22102]],[[115739,22373]],[[115134,22184]],[[113056,21175]],[[119573,21271]],[[119957,24020]],[[115859,22356]],[[116561,22649]],[[116285,22746]]]},"properties":{"cp":[113.280637,23.125178],"name":"广东","childNum":24}},{"id":"450000","type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[["@@H– TQ§•A"],["@@ĨʪƒLƒƊDÎĹĐCǦė¸zÚGn£¾›rªŀÜt¬@֛ڈSx~øOŒ˜ŶÐÂæȠ\\„ÈÜObĖw^oބLf¬°bI lTØB̈F£Ć¹gñĤaY“t¿¤VSñœK¸¤nM†¼‚JE±„½¸šŠño‹ÜCƆæĪ^ŠĚQÖ¦^‡ˆˆf´Q†üÜʝz¯šlzUĺš@쇀p¶n]sxtx¶@„~ÒĂJb©gk‚{°‚~c°`ԙ¬rV\\“la¼¤ôá`¯¹LC†ÆbŒxEræO‚v[H­˜„[~|aB£ÖsºdAĐzNÂðsŽÞƔ…Ĥªbƒ–ab`ho¡³F«èVloޤ™ÔRzpp®SŽĪº¨ÖƒºN…ij„d`’a”¦¤F³ºDÎńĀìŠCžĜº¦Ċ•~nS›|gźvZkCÆj°zVÈÁƔ]LÊFZg…čP­kini«‹qǀcz͔Y®¬Ů»qR×ō©DՄ‘§ƙǃŵTÉĩ±ŸıdÑnYY›IJvNĆÌØÜ Öp–}e³¦m‹©iÓ|¹Ÿħņ›|ª¦QF¢Â¬ʖovg¿em‡^ucà÷gՎuŒíÙćĝ}FϼĹ{µHK•sLSđƃr‹č¤[Ag‘oS‹ŇYMÿ§Ç{Fśbky‰lQxĕƒ]T·¶[B…ÑÏGáşşƇe€…•ăYSs­FQ}­Bƒw‘tYğÃ@~…C̀Q ×W‡j˱rÉ¥oÏ ±«ÓÂ¥•ƒ€k—ŽwWűŒmcih³K›~‰µh¯e]lµ›él•E쉕E“ďs‡’mǖŧē`ãògK_ÛsUʝ“ćğ¶hŒöŒO¤Ǜn³Žc‘`¡y‹¦C‘ez€YŠwa™–‘[ďĵűMę§]X˜Î_‚훘Û]é’ÛUćİÕBƣ±…dƒy¹T^džûÅÑŦ·‡PĻþÙ`K€¦˜…¢ÍeœĥR¿Œ³£[~Œäu¼dl‰t‚†W¸oRM¢ď\\zœ}Æzdvň–{ÎXF¶°Â_„ÒÂÏL©Ö•TmuŸ¼ãl‰›īkiqéfA„·Êµ\\őDc¥ÝF“y›Ôć˜c€űH_hL܋êĺШc}rn`½„Ì@¸¶ªVLŒŠhŒ‹\\•Ţĺk~ŽĠið°|gŒtTĭĸ^x‘vK˜VGréAé‘bUu›MJ‰VÃO¡…qĂXËS‰ģãlýàŸ_ju‡YÛÒB†œG^˜é֊¶§ŽƒEG”ÅzěƒƯ¤Ek‡N[kdåucé¬dnYpAyČ{`]þ¯T’bÜÈk‚¡Ġ•vŒàh„ÂƄ¢Jî¶²"]],"encodeOffsets":[[[111707,21520]],[[107619,25527]]]},"properties":{"cp":[108.320004,22.82402],"name":"广西","childNum":2}},{"id":"460000","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@š¦Ŝil¢”XƦ‘ƞò–ïè§ŞCêɕrŧůÇąĻõ™·ĉ³œ̅kÇm@ċȧƒŧĥ‰Ľʉ­ƅſ“ȓÒ˦ŝE}ºƑ[ÍĜȋ gÎfǐÏĤ¨êƺ\\Ɔ¸ĠĎvʄȀœÐ¾jNðĀÒRŒšZdž™zÐŘΰH¨Ƣb²_Ġ "],"encodeOffsets":[[112750,20508]]},"properties":{"cp":[110.33119,20.031971],"name":"海南","childNum":1}},{"id":"510000","type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[["@@LqKr"],["@@Š[ĻéV£ž_ţġñpG •réÏ·~ąSfy×͂·ºſƽiÍıƣıĻmHH}siaX@iǰÁÃ×t«ƒ­Tƒ¤J–JJŒyJ•ÈŠ`Ohߦ¡uËhIyCjmÿw…ZG……Ti‹SˆsO‰žB²ŸfNmsPaˆ{M{ŠõE‘^Hj}gYpaeuž¯‘oáwHjÁ½M¡pM“–uå‡mni{fk”\\oƒÎqCw†EZ¼K›ĝŠƒAy{m÷L‡wO×SimRI¯rK™õBS«sFe‡]fµ¢óY_ÆPRcue°Cbo׌bd£ŌIHgtrnyPt¦foaXďx›lBowz‹_{ÊéWiêE„GhܸºuFĈIxf®Ž•Y½ĀǙ]¤EyŸF²ċ’w¸¿@g¢§RGv»–áŸW`ÃĵJwi]t¥wO­½a[׈]`Ãi­üL€¦LabbTÀå’c}Íh™Æhˆ‹®BH€î|Ék­¤S†y£„ia©taį·Ɖ`ō¥Uh“O…ƒĝLk}©Fos‰´›Jm„µlŁu—…ø–nÑJWΪ–YÀïAetTžŅ‚ӍG™Ë«bo‰{ıwodƟ½ƒžOġܑµxàNÖ¾P²§HKv¾–]|•B‡ÆåoZ`¡Ø`ÀmºĠ~ÌЧnDž¿¤]wğ@sƒ‰rğu‰~‘Io”[é±¹ ¿žſđӉ@q‹gˆ¹zƱřaí°KtǤV»Ã[ĩǭƑ^ÇÓ@ỗs›Zϕ‹œÅĭ€Ƌ•ěpwDóÖሯneQˌq·•GCœýS]xŸ·ý‹q³•O՜Œ¶Qzßti{ř‰áÍÇWŝŭñzÇW‹pç¿JŒ™‚Xœĩè½cŒF–ÂLiVjx}\\N†ŇĖ¥Ge–“JA¼ÄHfÈu~¸Æ«dE³ÉMA|b˜Ò…˜ćhG¬CM‚õŠ„ƤąAvƒüV€éŀ‰_V̳ĐwQj´·ZeÈÁ¨X´Æ¡Qu·»Ÿ“˜ÕZ³ġqDo‰y`L¬gdp°şŠp¦ėìÅĮZްIä”h‚‘ˆzŠĵœf²å ›ĚрKp‹IN|‹„Ñz]ń……·FU×é»R³™MƒÉ»GM«€ki€™ér™}Ã`¹ăÞmȝnÁîRǀ³ĜoİzŔwǶVÚ£À]ɜ»ĆlƂ²Ġ…þTº·àUȞÏʦ¶†I’«dĽĢdĬ¿–»Ĕ׊h\\c¬†ä²GêëĤł¥ÀǿżÃÆMº}BÕĢyFVvw–ˆxBèĻĒ©Ĉ“tCĢɽŠȣ¦āæ·HĽî“ôNԓ~^¤Ɗœu„œ^s¼{TA¼ø°¢İªDè¾Ň¶ÝJ‘®Z´ğ~Sn|ªWÚ©òzPOȸ‚bð¢|‹øĞŠŒœŒQìÛÐ@Ğ™ǎRS¤Á§d…i“´ezÝúØã]Hq„kIŸþËQǦÃsǤ[E¬ÉŪÍxXƒ·ÖƁİlƞ¹ª¹|XÊwn‘ÆƄmÀêErĒtD®ċæcQƒ”E®³^ĭ¥©l}äQto˜ŖÜqƎkµ–„ªÔĻĴ¡@Ċ°B²Èw^^RsºT£ڿœQP‘JvÄz„^Đ¹Æ¯fLà´GC²‘dt˜­ĀRt¼¤ĦOðğfÔðDŨŁĞƘïžPȆ®âbMüÀXZ ¸£@Ś›»»QÉ­™]d“sÖ×_͖_ÌêŮPrĔĐÕGĂeZÜîĘqBhtO ¤tE[h|Y‹Ô‚ZśÎs´xº±UŒ’ñˆt|O’ĩĠºNbgþŠJy^dÂY Į„]Řz¦gC‚³€R`Šz’¢AjŒ¸CL„¤RÆ»@­Ŏk\\Ç´£YW}z@Z}‰Ã¶“oû¶]´^N‡Ò}èN‚ª–P˜Íy¹`S°´†ATe€VamdUĐwʄvĮÕ\\ƒu‹Æŗ¨Yp¹àZÂm™Wh{á„}WØǍ•Éüw™ga§áCNęÎ[ĀÕĪgÖɪX˜øx¬½Ů¦¦[€—„NΆL€ÜUÖ´òrÙŠxR^–†J˜k„ijnDX{Uƒ~ET{ļº¦PZc”jF²Ė@Žp˜g€ˆ¨“B{ƒu¨ŦyhoÚD®¯¢˜ WòàFΤ¨GDäz¦kŮPœġq˚¥À]€Ÿ˜eŽâÚ´ªKxī„Pˆ—Ö|æ[xäJÞĥ‚s’NÖ½ž€I†¬nĨY´®Ð—ƐŠ€mD™ŝuäđđEb…e’e_™v¡}ìęNJē}q”É埁T¯µRs¡M@}ůa†a­¯wvƉåZwž\\Z{åû^›"]],"encodeOffsets":[[[108815,30935]],[[110617,31811]]]},"properties":{"cp":[104.065735,30.659462],"name":"四川","childNum":2}},{"id":"520000","type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[["@@†G\\†lY£‘in"],["@@q‚|ˆ‚mc¯tχVSÎ"],["@@hÑ£Is‡NgßH†›HªķÃh_¹ƒ¡ĝħń¦uيùŽgS¯JHŸ|sÝÅtÁïyMDč»eÕtA¤{b\\}—ƒG®u\\åPFq‹wÅaD…žK°ºâ_£ùbµ”mÁ‹ÛœĹM[q|hlaªāI}тƒµ@swtwm^oµˆD鼊yV™ky°ÉžûÛR…³‚‡eˆ‡¥]RՋěħ[ƅåÛDpŒ”J„iV™™‰ÂF²I…»mN·£›LbÒYb—WsÀbŽ™pki™TZĄă¶HŒq`……ĥ_JŸ¯ae«ƒKpÝx]aĕÛPƒÇȟ[ÁåŵÏő—÷Pw}‡TœÙ@Õs«ĿÛq©½œm¤ÙH·yǥĘĉBµĨÕnđ]K„©„œá‹ŸG纍§Õßg‡ǗĦTèƤƺ{¶ÉHÎd¾ŚÊ·OÐjXWrãLyzÉAL¾ę¢bĶėy_qMĔąro¼hĊžw¶øV¤w”²Ĉ]ʚKx|`ź¦ÂÈdr„cȁbe¸›`I¼čTF´¼Óýȃr¹ÍJ©k_șl³´_pН`oÒh޶pa‚^ÓĔ}D»^Xyœ`d˜[Kv…JPhèhCrĂĚÂ^Êƌ wˆZL­Ġ£šÁbrzOIl’MM”ĪŐžËr×ÎeŦŽtw|Œ¢mKjSǘňĂStÎŦEtqFT†¾†E쬬ôxÌO¢Ÿ KгŀºäY†„”PVgŎ¦Ŋm޼VZwVlŒ„z¤…ž£Tl®ctĽÚó{G­A‡ŒÇgeš~Αd¿æaSba¥KKûj®_ć^\\ؾbP®¦x^sxjĶI_Ä X‚⼕Hu¨Qh¡À@Ëô}ޱžGNìĎlT¸ˆ…`V~R°tbÕĊ`¸úÛtπFDu€[ƒMfqGH·¥yA‰ztMFe|R‚_Gk†ChZeÚ°to˜v`x‹b„ŒDnÐ{E}šZ˜è€x—†NEފREn˜[Pv@{~rĆAB§‚EO¿|UZ~ì„Uf¨J²ĂÝÆ€‚sª–B`„s¶œfvö¦ŠÕ~dÔq¨¸º»uù[[§´sb¤¢zþFœ¢Æ…Àhˆ™ÂˆW\\ıŽËI݊o±ĭŠ£þˆÊs}¡R]ŒěƒD‚g´VG¢‚j±®è†ºÃmpU[Á›‘Œëº°r›ÜbNu¸}Žº¼‡`ni”ºÔXĄ¤¼Ôdaµ€Á_À…†ftQQgœR—‘·Ǔ’v”}Ýלĵ]µœ“Wc¤F²›OĩųãW½¯K‚©…]€{†LóµCIµ±Mß¿hŸ•©āq¬o‚½ž~@i~TUxŪÒ¢@ƒ£ÀEîôruń‚”“‚b[§nWuMÆLl¿]x}ij­€½"]],"encodeOffsets":[[[112158,27383]],[[112105,27474]],[[112095,27476]]]},"properties":{"cp":[106.713478,26.578343],"name":"贵州","childNum":3}},{"id":"530000","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@[„ùx½}ÑRH‘YīĺûsÍn‘iEoã½Ya²ė{c¬ĝg•ĂsA•ØÅwď‚õzFjw}—«Dx¿}UũlŸê™@•HÅ­F‰¨ÇoJ´Ónũuą¡Ã¢pÒŌ“Ø TF²‚xa²ËX€‚cʋlHîAßËŁkŻƑŷÉ©h™W­æßU‡“Ës¡¦}•teèÆ¶StǀÇ}Fd£j‹ĈZĆÆ‹¤T‚č\\Dƒ}O÷š£Uˆ§~ŃG™‚åŃDĝ¸œTsd¶¶Bªš¤u¢ŌĎo~t¾ÍŶÒtD¦Ú„iôö‰€z›ØX²ghįh½Û±¯€ÿm·zR¦Ɵ`ªŊÃh¢rOԍ´£Ym¼èêf¯ŪĽn„†cÚbŒw\\zlvWžªâˆ ¦g–mĿBş£¢ƹřbĥkǫßeeZkÙIKueT»sVesb‘aĕ  ¶®dNœĄÄpªyސ¼—„³BE˜®l‡ŽGœŭCœǶwêżĔÂe„pÍÀQƞpC„–¼ŲÈ­AÎô¶R„ä’Q^Øu¬°š_Èôc´¹ò¨P΢hlϦ´Ħ“Æ´sâDŽŲPnÊD^¯°’Upv†}®BP̪–jǬx–Söwlfòªv€qĸ|`H€­viļ€ndĜ­Ćhň•‚em·FyށqóžSᝑ³X_ĞçêtryvL¤§z„¦c¦¥jnŞk˜ˆlD¤øz½ĜàžĂŧMÅ|áƆàÊcðÂF܎‚áŢ¥\\\\º™İøÒÐJĴ‡„îD¦zK²ǏÎEh~’CD­hMn^ÌöÄ©ČZÀžaü„fɭyœpį´ěFűk]Ôě¢qlÅĆÙa¶~Äqššê€ljN¬¼H„ÊšNQ´ê¼VظE††^ŃÒyŒƒM{ŒJLoÒœęæŸe±Ķ›y‰’‡gã“¯JYÆĭĘëo¥Š‰o¯hcK«z_pŠrC´ĢÖY”—¼ v¸¢RŽÅW³Â§fǸYi³xR´ďUˊ`êĿU„û€uĆBƒƣö‰N€DH«Ĉg†——Ñ‚aB{ÊNF´¬c·Åv}eÇÃGB»”If•¦HňĕM…~[iwjUÁKE•Ž‹¾dĪçW›šI‹èÀŒoÈXòyŞŮÈXâÎŚŠj|àsRy‹µÖ›–Pr´þŒ ¸^wþTDŔ–Hr¸‹žRÌmf‡żÕâCôox–ĜƌÆĮŒ›Ð–œY˜tâŦÔ@]ÈǮƒ\\μģUsȯLbîƲŚºyh‡rŒŠ@ĒԝƀŸÀ²º\\êp“’JŠ}ĠvŠqt„Ġ@^xÀ£È†¨mËÏğ}n¹_¿¢×Y_æpˆÅ–A^{½•Lu¨GO±Õ½ßM¶w’ÁĢۂP‚›Ƣ¼pcIJxŠ|ap̬HšÐŒŊSfsðBZ¿©“XÏÒK•k†÷Eû¿‰S…rEFsÕūk”óVǥʼniTL‚¡n{‹uxţÏh™ôŝ¬ğōN“‘NJkyPaq™Âğ¤K®‡YŸxÉƋÁ]āęDqçgOg†ILu—\\_gz—]W¼ž~CÔē]bµogpў_oď`´³Țkl`IªºÎȄqÔþž»E³ĎSJ»œ_f·‚adÇqƒÇc¥Á_Źw{™L^ɱćx“U£µ÷xgĉp»ĆqNē`rĘzaĵĚ¡K½ÊBzyäKXqiWPÏɸ½řÍcÊG|µƕƣG˛÷Ÿk°_^ý|_zċBZocmø¯hhcæ\\lˆMFlư£Ĝ„ÆyH“„F¨‰µêÕ]—›HA…àӄ^it `þßäkŠĤÎT~Wlÿ¨„ÔPzUC–NVv [jâôDôď[}ž‰z¿–msSh‹¯{jïğl}šĹ[–őŒ‰gK‹©U·µË@¾ƒm_~q¡f¹…ÅË^»‘f³ø}Q•„¡Ö˳gͱ^ǁ…\\ëÃA_—¿bW›Ï[¶ƛ鏝£F{īZgm@|kHǭƁć¦UĔťƒ×ë}ǝƒeďºȡȘÏíBə£āĘPªij¶“ʼnÿ‡y©n‰ď£G¹¡I›Š±LÉĺÑdĉ܇W¥˜‰}g˜Á†{aqÃ¥aŠıęÏZ—ï`"],"encodeOffsets":[[104636,22969]]},"properties":{"cp":[102.712251,25.040609],"name":"云南","childNum":1}},{"id":"540000","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@hžľxŽŖ‰xƒÒVކºÅâAĪÝȆµę¯Ňa±r_w~uSÕň‘qOj]ɄQ…£Z……UDûoY’»©M[‹L¼qãË{V͕çWViŽ]ë©Ä÷àyƛh›ÚU°ŒŒa”d„cQƒ~Mx¥™cc¡ÙaSyF—ցk­ŒuRýq¿Ôµ•QĽ³aG{¿FµëªéĜÿª@¬·–K‰·àariĕĀ«V»Ŷ™Ĵū˜gèLǴŇƶaf‹tŒèBŚ£^Šâ†ǐÝ®–šM¦ÁǞÿ¬LhŸŽJ¾óƾƺcxw‹f]Y…´ƒ¦|œQLn°aœdĊ…œ\\¨o’œǀÍŎœ´ĩĀd`tÊQŞŕ|‚¨C^©œĈ¦„¦ÎJĊ{ŽëĎjª²rЉšl`¼Ą[t|¦St辉PŒÜK¸€d˜Ƅı]s¤—î_v¹ÎVòŦj˜£Əsc—¬_Ğ´|٘¦Avަw`ăaÝaa­¢e¤ı²©ªSªšÈMĄwžÉØŔì@T‘¤—Ę™\\õª@”þo´­xA s”ÂtŎKzó´ÇĊµ¢rž^nĊ­Æ¬×üGž¢‚³ {âĊ]š™G‚~bÀgVjzlhǶf€žOšfdЉªB]pj„•TO–tĊ‚n¤}®¦ƒČ¥d¢¼»ddš”Y¼Žt—¢eȤJ¤}Ǿ¡°§¤AГlc@ĝ”sªćļđAç‡wx•UuzEÖġ~AN¹ÄÅȀݦ¿ģŁéì±H…ãd«g[؉¼ēÀ•cīľġ¬cJ‘µ…ÐʥVȝ¸ßS¹†ý±ğkƁ¼ą^ɛ¤Ûÿ‰b[}¬ōõÃ]ËNm®g@•Bg}ÍF±ǐyL¥íCˆƒIij€Ï÷њį[¹¦[⚍EÛïÁÉdƅß{âNÆāŨߝ¾ě÷yC£‡k­´ÓH@¹†TZ¥¢įƒ·ÌAЧ®—Zc…v½ŸZ­¹|ŕWZqgW“|ieZÅYVӁqdq•bc²R@†c‡¥Rã»Ge†ŸeƃīQ•}J[ғK…¬Ə|o’ėjġĠÑN¡ð¯EBčnwôɍėªƒ²•CλŹġǝʅįĭạ̃ūȹ]ΓͧgšsgȽóϧµǛ†ęgſ¶ҍć`ĘąŌJޚä¤rÅň¥ÖÁUětęuůÞiĊÄÀ\\Æs¦ÓRb|Â^řÌkÄŷ¶½÷‡f±iMݑ›‰@ĥ°G¬ÃM¥n£Øą‚ğ¯ß”§aëbéüÑOčœk£{\\‘eµª×M‘šÉfm«Ƒ{Å׃Gŏǩãy³©WÑăû‚··‘Q—òı}¯ã‰I•éÕÂZ¨īès¶ZÈsŽæĔTŘvŽgÌsN@îá¾ó@‰˜ÙwU±ÉT廣TđŸWxq¹Zo‘b‹s[׌¯cĩv‡Œėŧ³BM|¹k‰ªħ—¥TzNYnݍßpęrñĠĉRS~½ŠěVVе‚õ‡«ŒM££µB•ĉ¥áºae~³AuĐh`Ü³ç@BۘïĿa©|z²Ý¼D”£à貋ŸƒIƒû›I ā€óK¥}rÝ_Á´éMaň¨€~ªSĈ½Ž½KÙóĿeƃÆBŽ·¬ën×W|Uº}LJrƳ˜lŒµ`bÔ`QˆˆÐÓ@s¬ñIŒÍ@ûws¡åQÑßÁ`ŋĴ{Ī“T•ÚÅTSij‚‹Yo|Ç[ǾµMW¢ĭiÕØ¿@˜šMh…pÕ]j†éò¿OƇĆƇp€êĉâlØw–ěsˆǩ‚ĵ¸c…bU¹ř¨WavquSMzeo_^gsÏ·¥Ó@~¯¿RiīB™Š\\”qTGªÇĜçPoŠÿfñòą¦óQīÈáP•œābß{ƒZŗĸIæÅ„hnszÁCËìñšÏ·ąĚÝUm®ó­L·ăU›Èíoù´Êj°ŁŤ_uµ^‘°Œìǖ@tĶĒ¡Æ‡M³Ģ«˜İĨÅ®ğ†RŽāð“ggheÆ¢z‚Ê©Ô\\°ÝĎz~ź¤Pn–MĪÖB£Ÿk™n鄧żćŠ˜ĆK„ǰ¼L¶è‰âz¨u¦¥LDĘz¬ýÎmĘd¾ß”Fz“hg²™Fy¦ĝ¤ċņbΛ@y‚Ąæm°NĮZRÖíŽJ²öLĸÒ¨Y®ƌÐV‰à˜tt_ڀÂyĠzž]Ţh€zĎ{†ĢX”ˆc|šÐqŽšfO¢¤ög‚ÌHNŽ„PKŖœŽ˜Uú´xx[xˆvĐCûŠìÖT¬¸^}Ìsòd´_އKgžLĴ…ÀBon|H@–Êx˜—¦BpŰˆŌ¿fµƌA¾zLjRxжF”œkĄźRzŀˆ~¶[”´Hnª–VƞuĒ­È¨ƎcƽÌm¸ÁÈM¦x͊ëÀxdžB’šú^´W†£–d„kɾĬpœw‚˂ØɦļĬIŚœÊ•n›Ŕa¸™~J°î”lɌxĤÊÈðhÌ®‚g˜T´øŽàCˆŽÀ^ªerrƘdž¢İP|Ė ŸWœªĦ^¶´ÂL„aT±üWƜ˜ǀRšŶUńšĖ[QhlLüA†‹Ü\\†qR›Ą©"],"encodeOffsets":[[90849,37210]]},"properties":{"cp":[91.132212,29.660361],"name":"西藏","childNum":1}},{"id":"610000","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@˜p¢—ȮµšûG™Ħ}Ħšðǚ¶òƄ€jɂz°{ºØkÈęâ¦jª‚Bg‚\\œċ°s¬Ž’]jžú ‚E”Ȍdž¬s„t‡”RˆÆdĠݎwܔ¸ôW¾ƮłÒ_{’Ìšû¼„jº¹¢GǪÒ¯ĘƒZ`ºŊƒecņąš~BÂgzpâēòYǠȰÌTΨÂWœ|fcŸă§uF—Œ@NŸ¢XLƒŠRMº[ğȣſï|¥J™kc`sʼnǷ’Y¹‹W@µ÷K…ãï³ÛIcñ·VȋڍÒķø©—þ¥ƒy‚ÓŸğęmWµÎumZyOŅƟĥÓ~sÑL¤µaŅY¦ocyZ{‰y c]{ŒTa©ƒ`U_Ěē£ωÊƍKù’K¶ȱÝƷ§{û»ÅÁȹÍéuij|¹cÑd‘ŠìUYƒŽO‘uF–ÕÈYvÁCqӃT•Ǣí§·S¹NgŠV¬ë÷Át‡°Dد’C´ʼnƒópģ}„ċcE˅FŸŸéGU¥×K…§­¶³B‹Č}C¿åċ`wġB·¤őcƭ²ő[Å^axwQO…ÿEËߌ•ĤNĔŸwƇˆÄŠńwĪ­Šo[„_KÓª³“ÙnK‰Çƒěœÿ]ď€ă_d©·©Ýŏ°Ù®g]±„Ÿ‡ß˜å›—¬÷m\\›iaǑkěX{¢|ZKlçhLt€Ňîŵ€œè[€É@ƉĄEœ‡tƇÏ˜³­ħZ«mJ…›×¾‘MtÝĦ£IwÄå\\Õ{‡˜ƒOwĬ©LÙ³ÙgBƕŀr̛ĢŭO¥lãyC§HÍ£ßEñŸX¡—­°ÙCgpťz‘ˆb`wI„vA|§”‡—hoĕ@E±“iYd¥OϹS|}F@¾oAO²{tfžÜ—¢Fǂ҈W²°BĤh^Wx{@„¬‚­F¸¡„ķn£P|ŸªĴ@^ĠĈæb–Ôc¶l˜Yi…–^Mi˜cϰÂ[ä€vï¶gv@À“Ĭ·lJ¸sn|¼u~a]’ÆÈtŌºJp’ƒþ£KKf~ЦUbyäIšĺãn‡Ô¿^­žŵMT–hĠܤko¼Ŏìąǜh`[tŒRd²IJ_œXPrɲ‰l‘‚XžiL§àƒ–¹ŽH˜°Ȧqº®QC—bA†„ŌJ¸ĕÚ³ĺ§ `d¨YjžiZvRĺ±öVKkjGȊĐePОZmļKÀ€‚[ŠŽ`ösìh†ïÎoĬdtKÞ{¬èÒÒBŒÔpIJÇĬJŊ¦±J«ˆY§‹@·pH€µàåVKe›pW†ftsAÅqC·¬ko«pHÆuK@oŸHĆۄķhx“e‘n›S³àǍrqƶRbzy€¸ËАl›¼EºpĤ¼Œx¼½~Ğ’”à@†ÚüdK^ˆmÌSj"],"encodeOffsets":[[110234,38774]]},"properties":{"cp":[108.948024,34.263161],"name":"陕西","childNum":1}},{"id":"620000","type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[["@@VuUv"],["@@ũ‹EĠtt~nkh`Q‰¦ÅÄÜdw˜Ab×ĠąJˆ¤DüègĺqBqœj°lI¡ĨÒ¤úSHbš‡ŠjΑBаaZˆ¢KJŽ’O[|A£žDx}Nì•HUnrk„ kp€¼Y kMJn[aG‚áÚÏ[½rc†}aQxOgsPMnUs‡nc‹Z…ž–sKúvA›t„Þġ’£®ĀYKdnFwš¢JE°”Latf`¼h¬we|€Æ‡šbj}GA€·~WŽ”—`†¢MC¤tL©IJ°qdf”O‚“bÞĬ¹ttu`^ZúE`Œ[@„Æsîz®¡’C„ƳƜG²“R‘¢R’m”fŽwĸg܃‚ą G@pzJM½mŠhVy¸uÈÔO±¨{LfæU¶ßGĂq\\ª¬‡²I‚¥IʼnÈīoı‹ÓÑAçÑ|«LÝcspīðÍg…të_õ‰\\ĉñLYnĝg’ŸRǡÁiHLlõUĹ²uQjYi§Z_c¨Ÿ´ĹĖÙ·ŋI…ƒaBD˜­R¹ȥr—¯G•ºß„K¨jWk’ɱŠOq›Wij\\a­‹Q\\sg_ĆǛōëp»£lğۀgS•ŶN®À]ˆÓäm™ĹãJaz¥V}‰Le¤L„ýo‘¹IsŋÅÇ^‘Žbz…³tmEÁ´aйcčecÇN•ĊãÁ\\蝗dNj•]j†—ZµkÓda•ćå]ğij@ ©O{¤ĸm¢ƒE·®ƒ«|@Xwg]A챝‡XǁÑdzªc›wQÚŝñsÕ³ÛV_ýƒ˜¥\\ů¥©¾÷w—Ž©WÕÊĩhÿÖÁRo¸V¬âDb¨šhûx–Ê×nj~Zâƒg|šXÁnßYoº§ZÅŘvŒ[„ĭÖʃuďxcVbnUSf…B¯³_Tzº—ΕO©çMÑ~Mˆ³]µ^püµ”ŠÄY~y@X~¤Z³€[Èōl@®Å¼£QKƒ·Di‹¡By‘ÿ‰Q_´D¥hŗyƒ^ŸĭÁZ]cIzý‰ah¹MĪğP‘s{ò‡‹‘²Vw¹t³Ŝˁ[ŽÑ}X\\gsFŸ£sPAgěp×ëfYHāďÖqēŭOÏë“dLü•\\iŒ”t^c®šRʺ¶—¢H°mˆ‘rYŸ£BŸ¹čIoľu¶uI]vģSQ{ƒUŻ”Å}QÂ|̋°ƅ¤ĩŪU ęĄžÌZҞ\\v˜²PĔ»ƢNHƒĂyAmƂwVmž`”]ȏb•”H`‰Ì¢²ILvĜ—H®¤Dlt_„¢JJÄämèÔDëþgºƫ™”aʎÌrêYi~ ÎݤNpÀA¾Ĕ¼b…ð÷’Žˆ‡®‚”üs”zMzÖĖQdȨý†v§Tè|ªH’þa¸|šÐ ƒwKĢx¦ivr^ÿ ¸l öæfƟĴ·PJv}n\\h¹¶v†·À|\\ƁĚN´Ĝ€çèÁz]ġ¤²¨QÒŨTIl‡ªťØ}¼˗ƦvÄùØE‹’«Fï˛Iq”ōŒTvāÜŏ‚íÛߜÛV—j³âwGăÂíNOŠˆŠPìyV³ʼnĖýZso§HіiYw[߆\\X¦¥c]ÔƩÜ·«j‡ÐqvÁ¦m^ċ±R™¦΋ƈťĚgÀ»IïĨʗƮްƝ˜ĻþÍAƉſ±tÍEÕÞāNU͗¡\\ſčåÒʻĘm ƭÌŹöʥ’ëQ¤µ­ÇcƕªoIýˆ‰Iɐ_mkl³ă‰Ɠ¦j—¡Yz•Ňi–}Msßõ–īʋ —}ƒÁVmŸ_[n}eı­Uĥ¼‘ª•I{ΧDӜƻėoj‘qYhĹT©oūĶ£]ďxĩ‹ǑMĝ‰q`B´ƃ˺Ч—ç~™²ņj@”¥@đ´ί}ĥtPńǾV¬ufӃÉC‹tÓ̻‰…¹£G³€]ƖƾŎĪŪĘ̖¨ʈĢƂlɘ۪üºňUðǜȢƢż̌ȦǼ‚ĤŊɲĖ­Kq´ï¦—ºĒDzņɾªǀÞĈĂD†½ĄĎÌŗĞrôñnŽœN¼â¾ʄľԆ|DŽŽ֦ज़ȗlj̘̭ɺƅêgV̍ʆĠ·ÌĊv|ýĖÕWĊǎÞ´õ¼cÒÒBĢ͢UĜð͒s¨ňƃLĉÕÝ@ɛƯ÷¿Ľ­ĹeȏijëCȚDŲyê×Ŗyò¯ļcÂßY…tÁƤyAã˾J@ǝrý‹‰@¤…rz¸oP¹ɐÚyᐇHŸĀ[Jw…cVeȴϜ»ÈŽĖ}ƒŰŐèȭǢόĀƪÈŶë;Ñ̆ȤМľĮEŔ—ĹŊũ~ËUă{ŸĻƹɁύȩþĽvĽƓÉ@ē„ĽɲßǐƫʾǗĒpäWÐxnsÀ^ƆwW©¦cÅ¡Ji§vúF¶Ž¨c~c¼īŒeXǚ‹\\đ¾JŽwÀďksãA‹fÕ¦L}wa‚o”Z’‹D½†Ml«]eÒÅaɲáo½FõÛ]ĻÒ¡wYR£¢rvÓ®y®LF‹LzĈ„ôe]gx}•|KK}xklL]c¦£fRtív¦†PĤoH{tK"]],"encodeOffsets":[[[108619,36299]],[[108589,36341]]]},"properties":{"cp":[103.823557,36.058039],"name":"甘肃","childNum":2}},{"id":"630000","type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[["@@InJm"],["@@CƒÆ½OŃĦsΰ~dz¦@@“Ņiš±è}ؘƄ˹A³r_ĞŠǒNΌĐw¤^ŬĵªpĺSZg’rpiƼĘԛ¨C|͖J’©Ħ»®VIJ~f\\m `Un„˜~ʌŸ•ĬàöNt•~ňjy–¢Zi˜Ɣ¥ĄŠk´nl`JʇŠJþ©pdƖ®È£¶ìRʦ‘źõƮËnŸʼėæÑƀĎ[‚˜¢VÎĂMÖÝÎF²sƊƀÎBļýƞ—¯ʘƭðħ¼Jh¿ŦęΌƇš¥²Q]Č¥nuÂÏriˆ¸¬ƪÛ^Ó¦d€¥[Wà…x\\ZŽjҕ¨GtpþYŊĕ´€zUO뇉P‰îMĄÁxH´á˜iÜUà›îÜՁĂÛSuŎ‹r“œJð̬EŒ‘FÁú×uÃÎkr“Ē{V}İ«O_ÌËĬ©ŽÓŧSRѱ§Ģ£^ÂyèçěM³Ƃę{[¸¿u…ºµ[gt£¸OƤĿéYŸõ·kŸq]juw¥Dĩƍ€õÇPéĽG‘ž©ã‡¤G…uȧþRcÕĕNy“yût“ˆ­‡ø‘†ï»a½ē¿BMoᣟÍj}éZËqbʍš“Ƭh¹ìÿÓAçãnIáI`ƒks£CG­ě˜Uy×Cy•…’Ÿ@¶ʡÊBnāzG„ơMē¼±O÷õJËĚăVŸĪũƆ£Œ¯{ËL½Ìzż“„VR|ĠTbuvJvµhĻĖH”Aëáa…­OÇðñęNw‡…œľ·L›mI±íĠĩPÉ×®ÿs—’cB³±JKßĊ«`…ađ»·QAmO’‘Vţéÿ¤¹SQt]]Çx€±¯A@ĉij¢Ó祖•ƒl¶ÅÛr—ŕspãRk~¦ª]Į­´“FR„åd­ČsCqđéFn¿Åƃm’Éx{W©ºƝºįkÕƂƑ¸wWūЩÈFž£\\tÈ¥ÄRÈýÌJ ƒlGr^×äùyÞ³fj”c†€¨£ÂZ|ǓMĝšÏ@ëÜőR‹›ĝ‰Œ÷¡{aïȷPu°ËXÙ{©TmĠ}Y³’­ÞIňµç½©C¡į÷¯B»|St»›]vƒųƒs»”}MÓ ÿʪƟǭA¡fs˜»PY¼c¡»¦c„ċ­¥£~msĉP•–Siƒ^o©A‰Šec‚™PeǵŽkg‚yUi¿h}aH™šĉ^|ᴟ¡HØûÅ«ĉ®]m€¡qĉ¶³ÈyôōLÁst“BŸ®wn±ă¥HSò뚣˜S’ë@לÊăxÇN©™©T±ª£IJ¡fb®ÞbŽb_Ą¥xu¥B—ž{łĝ³«`d˜Ɛt—¤ťiñžÍUuºí`£˜^tƃIJc—·ÛLO‹½Šsç¥Ts{ă\\_»™kϊ±q©čiìĉ|ÍIƒ¥ć¥›€]ª§D{ŝŖÉR_sÿc³Īō›ƿΑ›§p›[ĉ†›c¯bKm›R¥{³„Z†e^ŽŒwx¹dƽŽôIg §Mĕ ƹĴ¿—ǣÜ̓]‹Ý–]snåA{‹eŒƭ`ǻŊĿ\\ijŬű”YÂÿ¬jĖqŽßbЏ•L«¸©@ěĀ©ê¶ìÀEH|´bRľž–Ó¶rÀQþ‹vl®Õ‚E˜TzÜdb ˜hw¤{LR„ƒd“c‹b¯‹ÙVgœ‚ƜßzÃô쮍^jUèXΖ|UäÌ»rKŽ\\ŒªN‘¼pZCü†VY††¤ɃRi^rPҒTÖ}|br°qňb̰ªiƶGQ¾²„x¦PœmlŜ‘[Ĥ¡ΞsĦŸÔÏâ\\ªÚŒU\\f…¢N²§x|¤§„xĔsZPòʛ²SÐqF`ª„VƒÞŜĶƨVZŒÌL`ˆ¢dŐIqr\\oäõ–F礻Ŷ×h¹]Clـ\\¦ďÌį¬řtTӺƙgQÇÓHţĒ”´ÃbEÄlbʔC”|CˆŮˆk„Ʈ[ʼ¬ňœ´KŮÈΰÌζƶlð”ļA†TUvdTŠG†º̼ŠÔ€ŒsÊDԄveOg"]],"encodeOffsets":[[[105308,37219]],[[95370,40081]]]},"properties":{"cp":[101.778916,36.623178],"name":"青海","childNum":2}},{"id":"640000","type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[["@@KëÀęĞ«OęȿȕŸı]ʼn¡åįÕÔ«Ǵõƪ™ĚQÐZhv K°›öqÀѐS[ÃÖHƖčË‡nL]ûc…Ùß@‚“ĝ‘¾}w»»‹oģF¹œ»kÌÏ·{zPƒ§B­¢íyÅt@ƒ@áš]Yv_ssģ¼i߁”ĻL¾ġsKD£¡N_…“˜X¸}B~Haiˆ™Åf{«x»ge_bs“KF¯¡Ix™mELcÿZ¤­Ģ‘ƒÝœsuBLù•t†ŒYdˆmVtNmtOPhRw~bd…¾qÐ\\âÙH\\bImlNZŸ»loƒŸqlVm–Gā§~QCw¤™{A\\‘PKŸNY‡¯bF‡kC¥’sk‹Šs_Ã\\ă«¢ħkJi¯r›rAhĹûç£CU‡ĕĊ_ԗBixÅُĄnªÑaM~ħpOu¥sîeQ¥¤^dkKwlL~{L~–hw^‚ófćƒKyEŒ­K­zuÔ¡qQ¤xZÑ¢^ļöܾEpž±âbÊÑÆ^fk¬…NC¾‘Œ“YpxbK~¥Že֎ŒäBlt¿Đx½I[ĒǙŒWž‹f»Ĭ}d§dµùEuj¨‚IÆ¢¥dXªƅx¿]mtÏwßR͌X¢͎vÆzƂZò®ǢÌʆCrâºMÞzžÆMҔÊÓŊZľ–r°Î®Ȉmª²ĈUªĚøºˆĮ¦ÌĘk„^FłĬhĚiĀ˾iİbjÕ"],["@@mfwěwMrŢªv@G‰"]],"encodeOffsets":[[[109366,40242]],[[108600,36303]]]},"properties":{"cp":[106.278179,38.46637],"name":"宁夏","childNum":2}},{"id":"650000","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@QØĔ²X¨”~ǘBºjʐߨvK”ƔX¨vĊOžÃƒ·¢i@~c—‡ĝe_«”Eš“}QxgɪëÏÃ@sÅyXoŖ{ô«ŸuX…ê•Îf`œC‚¹ÂÿÐGĮÕĞXŪōŸMźÈƺQèĽôe|¿ƸJR¤ĘEjcUóº¯Ĩ_ŘÁMª÷Ð¥Oéȇ¿ÖğǤǷÂF҇zÉx[]­Ĥĝ‰œ¦EP}ûƥé¿İƷTėƫœŕƅ™ƱB»Đ±’ēO…¦E–•}‘`cȺrĦáŖuҞª«IJ‡πdƺÏØZƴwʄ¤ĖGЙǂZ̓èH¶}ÚZצʥĪï|ÇĦMŔ»İĝLj‹ì¥Βœba­¯¥ǕǚkĆŵĦɑĺƯxūД̵nơʃĽá½M»›òmqóŘĝč˾ăC…ćāƿÝɽ©DZŅ¹đ¥˜³ðLrÁ®ɱĕģʼnǻ̋ȥơŻǛȡVï¹Ň۩ûkɗġƁ§ʇė̕ĩũƽō^ƕŠUv£ƁQï“Ƶkŏ½ΉÃŭdzLқʻ«ƭ\\lƒ‡ŭD‡“{ʓDkaFÃÄa“³ŤđÔGRÈƚhSӹŚsİ«ĐË[¥ÚDkº^Øg¼ŵ¸£EÍö•€ůʼnT¡c_‡ËKY‹ƧUśĵ„݃U_©rETÏʜ±OñtYw獃{£¨uM³x½şL©Ùá[ÓÐĥ Νtģ¢\\‚ś’nkO›w¥±ƒT»ƷFɯàĩÞáB¹Æ…ÑUw„੍žĽw[“mG½Èå~‡Æ÷QyŠěCFmĭZī—ŵVÁ™ƿQƛ—ûXS²‰b½KϽĉS›©ŷXĕŸ{ŽĕK·¥Ɨcqq©f¿]‡ßDõU³h—­gËÇïģÉɋw“k¯í}I·šœbmœÉ–ř›īJɥĻˁ×xo›ɹī‡l•c…¤³Xù]‘™DžA¿w͉ì¥wÇN·ÂËnƾƍdǧđ®Ɲv•Um©³G\\“}µĿ‡QyŹl㓛µEw‰LJQ½yƋBe¶ŋÀů‡ož¥A—˜Éw@•{Gpm¿Aij†ŽKLhˆ³`ñcËtW‚±»ÕS‰ëüÿďD‡u\\wwwù³—V›LŕƒOMËGh£õP¡™er™Ïd{“‡ġWÁ…č|yšg^ğyÁzÙs`—s|ÉåªÇ}m¢Ń¨`x¥’ù^•}ƒÌ¥H«‰Yªƅ”Aйn~Ꝛf¤áÀz„gŠÇDIԝ´AňĀ҄¶ûEYospõD[{ù°]u›Jq•U•|Soċxţ[õÔĥkŋÞŭZ˺óYËüċrw €ÞkrťË¿XGÉbřaDü·Ē÷Aê[Ää€I®BÕИÞ_¢āĠpŠÛÄȉĖġDKwbm‡ÄNô‡ŠfœƫVÉvi†dz—H‘‹QµâFšù­Âœ³¦{YGžƒd¢ĚÜO „€{Ö¦ÞÍÀPŒ^b–ƾŠlŽ[„vt×ĈÍE˨¡Đ~´î¸ùÎh€uè`¸ŸHÕŔVºwĠââWò‡@{œÙNÝ´ə²ȕn{¿¥{l—÷eé^e’ďˆXj©î\\ªÑò˜Üìc\\üqˆÕ[Č¡xoÂċªbØ­Œø|€¶ȴZdÆÂšońéŒGš\\”¼C°ÌƁn´nxšÊOĨ’ہƴĸ¢¸òTxÊǪMīИÖŲÃɎOvˆʦƢ~FއRěò—¿ġ~åŊœú‰Nšžš¸qŽ’Ę[Ĕ¶ÂćnÒPĒÜvúĀÊbÖ{Äî¸~Ŕünp¤ÂH¾œĄYÒ©ÊfºmԈĘcDoĬMŬ’˜S¤„s²‚”ʘچžȂVŦ –ŽèW°ªB|IJXŔþÈJĦÆæFĚêŠYĂªĂ]øªŖNÞüA€’fɨJ€˜¯ÎrDDšĤ€`€mz\\„§~D¬{vJÂ˜«lµĂb–¤p€ŌŰNĄ¨ĊXW|ų ¿¾ɄĦƐMT”‡òP˜÷fØĶK¢ȝ˔Sô¹òEð­”`Ɩ½ǒÂň×äı–§ĤƝ§C~¡‚hlå‚ǺŦŞkâ’~}ŽFøàIJaĞ‚fƠ¥Ž„Ŕdž˜®U¸ˆźXœv¢aƆúŪtŠųƠjd•ƺŠƺÅìnrh\\ĺ¯äɝĦ]èpĄ¦´LƞĬŠ´ƤǬ˼Ēɸ¤rºǼ²¨zÌPðŀbþ¹ļD¢¹œ\\ĜÑŚŸ¶ZƄ³àjĨoâŠȴLʉȮŒĐ­ĚăŽÀêZǚŐ¤qȂ\\L¢ŌİfÆs|zºeªÙæ§΢{Ā´ƐÚ¬¨Ĵà²łhʺKÞºÖTŠiƢ¾ªì°`öøu®Ê¾ãØ"],"encodeOffsets":[[88824,50096]]},"properties":{"cp":[87.617733,43.792818],"name":"新疆","childNum":1}},{"id":"110000","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@ĽOÁ›ûtŷmiÍt_H»Ĩ±d`й­{bw…Yr“³S]§§o¹€qGtm_Sŧ€“oa›‹FLg‘QN_•dV€@Zom_ć\\ߚc±x¯oœRcfe…£’o§ËgToÛJíĔóu…|wP¤™XnO¢ÉˆŦ¯rNÄā¤zâŖÈRpŢZŠœÚ{GŠrFt¦Òx§ø¹RóäV¤XdˆżâºWbwڍUd®bêņ¾‘jnŎGŃŶŠnzÚSeîĜZczî¾i]͜™QaúÍÔiþĩȨWĢ‹ü|Ėu[qb[swP@ÅğP¿{\\‡¥A¨Ï‘Ѩj¯ŠX\\¯œMK‘pA³[H…īu}}"],"encodeOffsets":[[120023,41045]]},"properties":{"cp":[116.405285,39.904989],"name":"北京","childNum":1}},{"id":"120000","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@ŬgX§Ü«E…¶Ḟ“¬O_™ïlÁg“z±AXe™µÄĵ{¶]gitgšIj·›¥îakS€‰¨ÐƎk}ĕ{gB—qGf{¿a†U^fI“ư‹³õ{YƒıëNĿžk©ïËZŏ‘R§òoY×Ógc…ĥs¡bġ«@dekąI[nlPqCnp{ˆō³°`{PNdƗqSÄĻNNâyj]äžÒD ĬH°Æ]~¡HO¾ŒX}ÐxŒgp“gWˆrDGˆŒpù‚Š^L‚ˆrzWxˆZ^¨´T\\|~@I‰zƒ–bĤ‹œjeĊªz£®Ĕvě€L†mV¾Ô_ȔNW~zbĬvG†²ZmDM~”~"],"encodeOffsets":[[120237,41215]]},"properties":{"cp":[117.190182,39.125596],"name":"天津","childNum":1}},{"id":"310000","type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[["@@ɧư¬EpƸÁxc‡"],["@@©„ªƒ"],["@@”MA‹‘š"],["@@Qp݁E§ÉC¾"],["@@bŝՕÕEȣÚƥêImɇǦèÜĠŒÚžÃƌÃ͎ó"],["@@ǜûȬɋŠŭ™×^‰sYŒɍDŋ‘ŽąñCG²«ªč@h–_p¯A{‡oloY€¬j@IJ`•gQڛhr|ǀ^MIJvtbe´R¯Ô¬¨YŽô¤r]ì†Ƭį"]],"encodeOffsets":[[[124702,32062]],[[124547,32200]],[[124808,31991]],[[124726,32110]],[[124903,32376]],[[124438,32149]]]},"properties":{"cp":[121.472644,31.231706],"name":"上海","childNum":6}},{"id":"500000","type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[["@@vjG~nGŘŬĶȂƀƾ¹¸ØÎezĆT¸}êЖqHŸðqĖ䒊¥^CƒIj–²p…\\_ æüY|[YxƊæuž°xb®…Űb@~¢NQt°¶‚S栓Ê~rljĔëĚ¢~šuf`‘‚†fa‚ĔJåĊ„nÖ]„jƎćÊ@Š£¾a®£Ű{ŶĕF‹ègLk{Y|¡ĜWƔtƬJÑxq‹±ĢN´‰òK‰™–LÈüD|s`ŋ’ć]ƒÃ‰`đŒMûƱ½~Y°ħ`ƏíW‰½eI‹½{aŸ‘OIrÏ¡ĕŇa†p†µÜƅġ‘œ^ÖÛbÙŽŏml½S‹êqDu[R‹ãË»†ÿw`»y‘¸_ĺę}÷`M¯ċfCVµqʼn÷Z•gg“Œ`d½pDO‡ÎCnœ^uf²ènh¼WtƏxRGg¦…pV„†FI±ŽG^ŒIc´ec‡’G•ĹÞ½sëĬ„h˜xW‚}Kӈe­Xsbk”F¦›L‘ØgTkïƵNï¶}Gy“w\\oñ¡nmĈzjŸ•@™Óc£»Wă¹Ój“_m»ˆ¹·~MvÛaqœ»­‰êœ’\\ÂoVnŽÓØÍ™²«‹bq¿efE „€‹Ĝ^Qž~ Évý‡ş¤²Į‰pEİ}zcĺƒL‹½‡š¿gņ›¡ýE¡ya£³t\\¨\\vú»¼§·Ñr_oÒý¥u‚•_n»_ƒ•At©Þűā§IVeëƒY}{VPÀFA¨ąB}q@|Ou—\\Fm‰QF݅Mw˜å}]•€|FmϋCaƒwŒu_p—¯sfÙgY…DHl`{QEfNysBЦzG¸rHe‚„N\\CvEsÐùÜ_·ÖĉsaQ¯€}_U‡†xÃđŠq›NH¬•Äd^ÝŰR¬ã°wećJEž·vÝ·Hgƒ‚éFXjÉê`|yŒpxkAwœWĐpb¥eOsmzwqChóUQl¥F^laf‹anòsr›EvfQdÁUVf—ÎvÜ^efˆtET¬ôA\\œ¢sJŽnQTjP؈xøK|nBz‰„œĞ»LY‚…FDxӄvr“[ehľš•vN”¢o¾NiÂxGp⬐z›bfZo~hGi’]öF|‰|Nb‡tOMn eA±ŠtPT‡LjpYQ|†SH††YĀxinzDJ€Ìg¢và¥Pg‰_–ÇzII‹€II•„£®S¬„Øs쐣ŒN"],["@@ifjN@s"]],"encodeOffsets":[[[109628,30765]],[[111725,31320]]]},"properties":{"cp":[106.504962,29.533155],"name":"重庆","childNum":2}},{"id":"810000","type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[["@@AlBk"],["@@mŽn"],["@@EpFo"],["@@ea¢pl¸Eõ¹‡hj[ƒ]ÔCΖ@lj˜¡uBXŸ…•´‹AI¹…[‹yDUˆ]W`çwZkmc–…M›žp€Åv›}I‹oJlcaƒfёKްä¬XJmРđhI®æÔtSHn€Eˆ„ÒrÈc"],["@@rMUw‡AS®€e"]],"encodeOffsets":[[[117111,23002]],[[117072,22876]],[[117045,22887]],[[116975,23082]],[[116882,22747]]]},"properties":{"cp":[114.173355,22.320048],"name":"香港","childNum":5}},{"id":"820000","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@kÊd°å§s"],"encodeOffsets":[[116279,22639]]},"properties":{"cp":[113.54909,22.198951],"name":"澳门","childNum":1}}],"UTF8Encoding":true});
+}));
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/report/peity/jquery.peity.min.js b/ruoyi-admin/src/main/resources/static/ajax/libs/report/peity/jquery.peity.min.js
new file mode 100644
index 0000000..085b725
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/report/peity/jquery.peity.min.js
@@ -0,0 +1,13 @@
+// Peity jQuery plugin version 2.0.3
+// (c) 2014 Ben Pickles
+//
+// http://benpickles.github.io/peity
+//
+// Released under MIT license.
+(function(e,q,h){var o=function(a,b){var c=q.createElementNS("http://www.w3.org/2000/svg",a);e.each(b,function(a,b){c.setAttribute(a,b)});return c},t="createElementNS"in q&&o("svg",{}).createSVGRect,r=1/(window.devicePixelRatio||1),j=e.fn.peity=function(a,b){t&&this.each(function(){var c=e(this),d=c.data("peity");if(d)a&&(d.type=a),e.extend(d.opts,b);else{var f=j.defaults[a],g={};e.each(c.data(),function(a,b){a in f&&(g[a]=b)});var h=e.extend({},f,g,b),d=new s(c,a,h);c.change(function(){d.draw()}).data("peity",
+    d)}d.draw()});return this},s=function(a,b,c){this.$el=a;this.type=b;this.opts=c},m=s.prototype;m.draw=function(){j.graphers[this.type].call(this,this.opts)};m.fill=function(){var a=this.opts.fill,b=a;e.isFunction(b)||(b=function(b,d){return a[d%a.length]});return b};m.prepare=function(a,b){var c;this.svg?c=e(this.svg).empty():(this.svg=o("svg",{"class":"peity"}),this.$el.hide().after(this.svg),c=e(this.svg).data("peity",this));this.svg.setAttribute("height",b);this.svg.setAttribute("width",a);return c};
+    m.values=function(){return e.map(this.$el.text().split(this.opts.delimiter),function(a){return parseFloat(a)})};j.defaults={};j.graphers={};j.register=function(a,b,c){this.defaults[a]=b;this.graphers[a]=c};j.register("pie",{delimiter:null,diameter:16,fill:["#ff9900","#fff4dd","#ffc66e"]},function(a){if(!a.delimiter){var b=this.$el.text().match(/[^0-9\.]/);a.delimiter=b?b[0]:","}b=this.values();if("/"==a.delimiter)var c=b[0],b=[c,h.max(0,b[1]-c)];for(var d=0,c=b.length,f=0;d<c;d++)f+=b[d];for(var a=
+        this.prepare(a.width||a.diameter,a.height||a.diameter),d=a.width(),g=a.height(),a=d/2,g=g/2,p=h.min(a,g),e=h.PI,j=this.fill(),i=-e/2,d=0;d<c;d++){var n=b[d],l=n/f,k;if(0!=l){if(1==l)k=o("circle",{cx:a,cy:g,r:p});else{k=2*l*e;var l=i+k,m=p*h.cos(i)+a,i=p*h.sin(i)+g,q=p*h.cos(l)+a,r=p*h.sin(l)+g;k=o("path",{d:["M",a,g,"L",m,i,"A",p,p,0,k>e?1:0,1,q,r,"Z"].join(" ")});i=l}k.setAttribute("fill",j.call(this,n,d,b));this.svg.appendChild(k)}}});j.register("line",{delimiter:",",fill:"#c6d9fd",height:16,max:null,
+        min:0,stroke:"#4d89f9",strokeWidth:1,width:32},function(a){var b=this.values();1==b.length&&b.push(b[0]);for(var c=h.max.apply(h,b.concat([a.max])),d=h.min.apply(h,b.concat([a.min])),f=this.prepare(a.width,a.height),g=f.width(),f=f.height()-a.strokeWidth,e=g/(b.length-1),c=c-d,j=0==c?f:f/c,m=f+d*j,c=[0,m],i=0;i<b.length;i++)c.push(i*e,f-j*(b[i]-d)+a.strokeWidth/2);c.push(g,m);b=o("polygon",{fill:a.fill,points:c.join(" ")});this.svg.appendChild(b);a.strokeWidth&&(a=o("polyline",{fill:"transparent",
+        points:c.slice(2,c.length-2).join(" "),stroke:a.stroke,"stroke-width":a.strokeWidth,"stroke-linecap":"square"}),this.svg.appendChild(a))});j.register("bar",{delimiter:",",fill:["#4D89F9"],gap:1,height:16,max:null,min:0,width:32},function(a){for(var b=this.values(),c=h.max.apply(h,b.concat([a.max])),d=h.min.apply(h,b.concat([a.min])),f=this.prepare(a.width,a.height),g=f.width(),f=f.height(),e=c-d,j=0==e?0:f/e,a=a.gap,g=(g+a)/b.length,m=this.fill(),i=0;i<b.length;i++){var n=b[i],l=f-j*(n-d),k=j*n;if(0==
+        k){if(k=r,0>=d&&0<c||0==e)l-=r}else 0>k&&(l+=k,k=-k);n=o("rect",{fill:m.call(this,n,i,b),x:i*g,y:l,width:g-a,height:k});this.svg.appendChild(n)}})})(jQuery,document,Math);
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/report/sparkline/jquery.sparkline.min.js b/ruoyi-admin/src/main/resources/static/ajax/libs/report/sparkline/jquery.sparkline.min.js
new file mode 100644
index 0000000..3477d16
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/report/sparkline/jquery.sparkline.min.js
@@ -0,0 +1,5 @@
+/* jquery.sparkline 2.1.2 - http://omnipotent.net/jquery.sparkline/
+ ** Licensed under the New BSD License - see above site for details */
+
+(function(a,b,c){(function(a){typeof define=="function"&&define.amd?define(["jquery"],a):jQuery&&!jQuery.fn.sparkline&&a(jQuery)})(function(d){"use strict";var e={},f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L=0;f=function(){return{common:{type:"line",lineColor:"#00f",fillColor:"#cdf",defaultPixelsPerValue:3,width:"auto",height:"auto",composite:!1,tagValuesAttribute:"values",tagOptionsPrefix:"spark",enableTagOptions:!1,enableHighlight:!0,highlightLighten:1.4,tooltipSkipNull:!0,tooltipPrefix:"",tooltipSuffix:"",disableHiddenCheck:!1,numberFormatter:!1,numberDigitGroupCount:3,numberDigitGroupSep:",",numberDecimalMark:".",disableTooltips:!1,disableInteraction:!1},line:{spotColor:"#f80",highlightSpotColor:"#5f5",highlightLineColor:"#f22",spotRadius:1.5,minSpotColor:"#f80",maxSpotColor:"#f80",lineWidth:1,normalRangeMin:c,normalRangeMax:c,normalRangeColor:"#ccc",drawNormalOnTop:!1,chartRangeMin:c,chartRangeMax:c,chartRangeMinX:c,chartRangeMaxX:c,tooltipFormat:new h('<span style="color: {{color}}">&#9679;</span> {{prefix}}{{y}}{{suffix}}')},bar:{barColor:"#3366cc",negBarColor:"#f44",stackedBarColor:["#3366cc","#dc3912","#ff9900","#109618","#66aa00","#dd4477","#0099c6","#990099"],zeroColor:c,nullColor:c,zeroAxis:!0,barWidth:4,barSpacing:1,chartRangeMax:c,chartRangeMin:c,chartRangeClip:!1,colorMap:c,tooltipFormat:new h('<span style="color: {{color}}">&#9679;</span> {{prefix}}{{value}}{{suffix}}')},tristate:{barWidth:4,barSpacing:1,posBarColor:"#6f6",negBarColor:"#f44",zeroBarColor:"#999",colorMap:{},tooltipFormat:new h('<span style="color: {{color}}">&#9679;</span> {{value:map}}'),tooltipValueLookups:{map:{"-1":"Loss",0:"Draw",1:"Win"}}},discrete:{lineHeight:"auto",thresholdColor:c,thresholdValue:0,chartRangeMax:c,chartRangeMin:c,chartRangeClip:!1,tooltipFormat:new h("{{prefix}}{{value}}{{suffix}}")},bullet:{targetColor:"#f33",targetWidth:3,performanceColor:"#33f",rangeColors:["#d3dafe","#a8b6ff","#7f94ff"],base:c,tooltipFormat:new h("{{fieldkey:fields}} - {{value}}"),tooltipValueLookups:{fields:{r:"Range",p:"Performance",t:"Target"}}},pie:{offset:0,sliceColors:["#3366cc","#dc3912","#ff9900","#109618","#66aa00","#dd4477","#0099c6","#990099"],borderWidth:0,borderColor:"#000",tooltipFormat:new h('<span style="color: {{color}}">&#9679;</span> {{value}} ({{percent.1}}%)')},box:{raw:!1,boxLineColor:"#000",boxFillColor:"#cdf",whiskerColor:"#000",outlierLineColor:"#333",outlierFillColor:"#fff",medianColor:"#f00",showOutliers:!0,outlierIQR:1.5,spotRadius:1.5,target:c,targetColor:"#4a2",chartRangeMax:c,chartRangeMin:c,tooltipFormat:new h("{{field:fields}}: {{value}}"),tooltipFormatFieldlistKey:"field",tooltipValueLookups:{fields:{lq:"Lower Quartile",med:"Median",uq:"Upper Quartile",lo:"Left Outlier",ro:"Right Outlier",lw:"Left Whisker",rw:"Right Whisker"}}}}},E='.jqstooltip { position: absolute;left: 0px;top: 0px;visibility: hidden;background: rgb(0, 0, 0) transparent;background-color: rgba(0,0,0,0.6);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#99000000, endColorstr=#99000000);-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#99000000, endColorstr=#99000000)";color: white;font: 10px arial, san serif;text-align: left;white-space: nowrap;padding: 5px;border: 1px solid white;z-index: 10000;}.jqsfield { color: white;font: 10px arial, san serif;text-align: left;}',g=function(){var a,b;return a=function(){this.init.apply(this,arguments)},arguments.length>1?(arguments[0]?(a.prototype=d.extend(new arguments[0],arguments[arguments.length-1]),a._super=arguments[0].prototype):a.prototype=arguments[arguments.length-1],arguments.length>2&&(b=Array.prototype.slice.call(arguments,1,-1),b.unshift(a.prototype),d.extend.apply(d,b))):a.prototype=arguments[0],a.prototype.cls=a,a},d.SPFormatClass=h=g({fre:/\{\{([\w.]+?)(:(.+?))?\}\}/g,precre:/(\w+)\.(\d+)/,init:function(a,b){this.format=a,this.fclass=b},render:function(a,b,d){var e=this,f=a,g,h,i,j,k;return this.format.replace(this.fre,function(){var a;return h=arguments[1],i=arguments[3],g=e.precre.exec(h),g?(k=g[2],h=g[1]):k=!1,j=f[h],j===c?"":i&&b&&b[i]?(a=b[i],a.get?b[i].get(j)||j:b[i][j]||j):(n(j)&&(d.get("numberFormatter")?j=d.get("numberFormatter")(j):j=s(j,k,d.get("numberDigitGroupCount"),d.get("numberDigitGroupSep"),d.get("numberDecimalMark"))),j)})}}),d.spformat=function(a,b){return new h(a,b)},i=function(a,b,c){return a<b?b:a>c?c:a},j=function(a,c){var d;return c===2?(d=b.floor(a.length/2),a.length%2?a[d]:(a[d-1]+a[d])/2):a.length%2?(d=(a.length*c+c)/4,d%1?(a[b.floor(d)]+a[b.floor(d)-1])/2:a[d-1]):(d=(a.length*c+2)/4,d%1?(a[b.floor(d)]+a[b.floor(d)-1])/2:a[d-1])},k=function(a){var b;switch(a){case"undefined":a=c;break;case"null":a=null;break;case"true":a=!0;break;case"false":a=!1;break;default:b=parseFloat(a),a==b&&(a=b)}return a},l=function(a){var b,c=[];for(b=a.length;b--;)c[b]=k(a[b]);return c},m=function(a,b){var c,d,e=[];for(c=0,d=a.length;c<d;c++)a[c]!==b&&e.push(a[c]);return e},n=function(a){return!isNaN(parseFloat(a))&&isFinite(a)},s=function(a,b,c,e,f){var g,h;a=(b===!1?parseFloat(a).toString():a.toFixed(b)).split(""),g=(g=d.inArray(".",a))<0?a.length:g,g<a.length&&(a[g]=f);for(h=g-c;h>0;h-=c)a.splice(h,0,e);return a.join("")},o=function(a,b,c){var d;for(d=b.length;d--;){if(c&&b[d]===null)continue;if(b[d]!==a)return!1}return!0},p=function(a){var b=0,c;for(c=a.length;c--;)b+=typeof a[c]=="number"?a[c]:0;return b},r=function(a){return d.isArray(a)?a:[a]},q=function(b){var c;a.createStyleSheet?a.createStyleSheet().cssText=b:(c=a.createElement("style"),c.type="text/css",a.getElementsByTagName("head")[0].appendChild(c),c[typeof a.body.style.WebkitAppearance=="string"?"innerText":"innerHTML"]=b)},d.fn.simpledraw=function(b,e,f,g){var h,i;if(f&&(h=this.data("_jqs_vcanvas")))return h;if(d.fn.sparkline.canvas===!1)return!1;if(d.fn.sparkline.canvas===c){var j=a.createElement("canvas");if(!j.getContext||!j.getContext("2d")){if(!a.namespaces||!!a.namespaces.v)return d.fn.sparkline.canvas=!1,!1;a.namespaces.add("v","urn:schemas-microsoft-com:vml","#default#VML"),d.fn.sparkline.canvas=function(a,b,c,d){return new J(a,b,c)}}else d.fn.sparkline.canvas=function(a,b,c,d){return new I(a,b,c,d)}}return b===c&&(b=d(this).innerWidth()),e===c&&(e=d(this).innerHeight()),h=d.fn.sparkline.canvas(b,e,this,g),i=d(this).data("_jqs_mhandler"),i&&i.registerCanvas(h),h},d.fn.cleardraw=function(){var a=this.data("_jqs_vcanvas");a&&a.reset()},d.RangeMapClass=t=g({init:function(a){var b,c,d=[];for(b in a)a.hasOwnProperty(b)&&typeof b=="string"&&b.indexOf(":")>-1&&(c=b.split(":"),c[0]=c[0].length===0?-Infinity:parseFloat(c[0]),c[1]=c[1].length===0?Infinity:parseFloat(c[1]),c[2]=a[b],d.push(c));this.map=a,this.rangelist=d||!1},get:function(a){var b=this.rangelist,d,e,f;if((f=this.map[a])!==c)return f;if(b)for(d=b.length;d--;){e=b[d];if(e[0]<=a&&e[1]>=a)return e[2]}return c}}),d.range_map=function(a){return new t(a)},u=g({init:function(a,b){var c=d(a);this.$el=c,this.options=b,this.currentPageX=0,this.currentPageY=0,this.el=a,this.splist=[],this.tooltip=null,this.over=!1,this.displayTooltips=!b.get("disableTooltips"),this.highlightEnabled=!b.get("disableHighlight")},registerSparkline:function(a){this.splist.push(a),this.over&&this.updateDisplay()},registerCanvas:function(a){var b=d(a.canvas);this.canvas=a,this.$canvas=b,b.mouseenter(d.proxy(this.mouseenter,this)),b.mouseleave(d.proxy(this.mouseleave,this)),b.click(d.proxy(this.mouseclick,this))},reset:function(a){this.splist=[],this.tooltip&&a&&(this.tooltip.remove(),this.tooltip=c)},mouseclick:function(a){var b=d.Event("sparklineClick");b.originalEvent=a,b.sparklines=this.splist,this.$el.trigger(b)},mouseenter:function(b){d(a.body).unbind("mousemove.jqs"),d(a.body).bind("mousemove.jqs",d.proxy(this.mousemove,this)),this.over=!0,this.currentPageX=b.pageX,this.currentPageY=b.pageY,this.currentEl=b.target,!this.tooltip&&this.displayTooltips&&(this.tooltip=new v(this.options),this.tooltip.updatePosition(b.pageX,b.pageY)),this.updateDisplay()},mouseleave:function(){d(a.body).unbind("mousemove.jqs");var b=this.splist,c=b.length,e=!1,f,g;this.over=!1,this.currentEl=null,this.tooltip&&(this.tooltip.remove(),this.tooltip=null);for(g=0;g<c;g++)f=b[g],f.clearRegionHighlight()&&(e=!0);e&&this.canvas.render()},mousemove:function(a){this.currentPageX=a.pageX,this.currentPageY=a.pageY,this.currentEl=a.target,this.tooltip&&this.tooltip.updatePosition(a.pageX,a.pageY),this.updateDisplay()},updateDisplay:function(){var a=this.splist,b=a.length,c=!1,e=this.$canvas.offset(),f=this.currentPageX-e.left,g=this.currentPageY-e.top,h,i,j,k,l;if(!this.over)return;for(j=0;j<b;j++)i=a[j],k=i.setRegionHighlight(this.currentEl,f,g),k&&(c=!0);if(c){l=d.Event("sparklineRegionChange"),l.sparklines=this.splist,this.$el.trigger(l);if(this.tooltip){h="";for(j=0;j<b;j++)i=a[j],h+=i.getCurrentRegionTooltip();this.tooltip.setContent(h)}this.disableHighlight||this.canvas.render()}k===null&&this.mouseleave()}}),v=g({sizeStyle:"position: static !important;display: block !important;visibility: hidden !important;float: left !important;",init:function(b){var c=b.get("tooltipClassname","jqstooltip"),e=this.sizeStyle,f;this.container=b.get("tooltipContainer")||a.body,this.tooltipOffsetX=b.get("tooltipOffsetX",10),this.tooltipOffsetY=b.get("tooltipOffsetY",12),d("#jqssizetip").remove(),d("#jqstooltip").remove(),this.sizetip=d("<div/>",{id:"jqssizetip",style:e,"class":c}),this.tooltip=d("<div/>",{id:"jqstooltip","class":c}).appendTo(this.container),f=this.tooltip.offset(),this.offsetLeft=f.left,this.offsetTop=f.top,this.hidden=!0,d(window).unbind("resize.jqs scroll.jqs"),d(window).bind("resize.jqs scroll.jqs",d.proxy(this.updateWindowDims,this)),this.updateWindowDims()},updateWindowDims:function(){this.scrollTop=d(window).scrollTop(),this.scrollLeft=d(window).scrollLeft(),this.scrollRight=this.scrollLeft+d(window).width(),this.updatePosition()},getSize:function(a){this.sizetip.html(a).appendTo(this.container),this.width=this.sizetip.width()+1,this.height=this.sizetip.height(),this.sizetip.remove()},setContent:function(a){if(!a){this.tooltip.css("visibility","hidden"),this.hidden=!0;return}this.getSize(a),this.tooltip.html(a).css({width:this.width,height:this.height,visibility:"visible"}),this.hidden&&(this.hidden=!1,this.updatePosition())},updatePosition:function(a,b){if(a===c){if(this.mousex===c)return;a=this.mousex-this.offsetLeft,b=this.mousey-this.offsetTop}else this.mousex=a-=this.offsetLeft,this.mousey=b-=this.offsetTop;if(!this.height||!this.width||this.hidden)return;b-=this.height+this.tooltipOffsetY,a+=this.tooltipOffsetX,b<this.scrollTop&&(b=this.scrollTop),a<this.scrollLeft?a=this.scrollLeft:a+this.width>this.scrollRight&&(a=this.scrollRight-this.width),this.tooltip.css({left:a,top:b})},remove:function(){this.tooltip.remove(),this.sizetip.remove(),this.sizetip=this.tooltip=c,d(window).unbind("resize.jqs scroll.jqs")}}),F=function(){q(E)},d(F),K=[],d.fn.sparkline=function(b,e){return this.each(function(){var f=new d.fn.sparkline.options(this,e),g=d(this),h,i;h=function(){var e,h,i,j,k,l,m;if(b==="html"||b===c){m=this.getAttribute(f.get("tagValuesAttribute"));if(m===c||m===null)m=g.html();e=m.replace(/(^\s*<!--)|(-->\s*$)|\s+/g,"").split(",")}else e=b;h=f.get("width")==="auto"?e.length*f.get("defaultPixelsPerValue"):f.get("width");if(f.get("height")==="auto"){if(!f.get("composite")||!d.data(this,"_jqs_vcanvas"))j=a.createElement("span"),j.innerHTML="a",g.html(j),i=d(j).innerHeight()||d(j).height(),d(j).remove(),j=null}else i=f.get("height");f.get("disableInteraction")?k=!1:(k=d.data(this,"_jqs_mhandler"),k?f.get("composite")||k.reset():(k=new u(this,f),d.data(this,"_jqs_mhandler",k)));if(f.get("composite")&&!d.data(this,"_jqs_vcanvas")){d.data(this,"_jqs_errnotify")||(alert("Attempted to attach a composite sparkline to an element with no existing sparkline"),d.data(this,"_jqs_errnotify",!0));return}l=new(d.fn.sparkline[f.get("type")])(this,e,f,h,i),l.render(),k&&k.registerSparkline(l)};if(d(this).html()&&!f.get("disableHiddenCheck")&&d(this).is(":hidden")||!d(this).parents("body").length){if(!f.get("composite")&&d.data(this,"_jqs_pending"))for(i=K.length;i;i--)K[i-1][0]==this&&K.splice(i-1,1);K.push([this,h]),d.data(this,"_jqs_pending",!0)}else h.call(this)})},d.fn.sparkline.defaults=f(),d.sparkline_display_visible=function(){var a,b,c,e=[];for(b=0,c=K.length;b<c;b++)a=K[b][0],d(a).is(":visible")&&!d(a).parents().is(":hidden")?(K[b][1].call(a),d.data(K[b][0],"_jqs_pending",!1),e.push(b)):!d(a).closest("html").length&&!d.data(a,"_jqs_pending")&&(d.data(K[b][0],"_jqs_pending",!1),e.push(b));for(b=e.length;b;b--)K.splice(e[b-1],1)},d.fn.sparkline.options=g({init:function(a,b){var c,f,g,h;this.userOptions=b=b||{},this.tag=a,this.tagValCache={},f=d.fn.sparkline.defaults,g=f.common,this.tagOptionsPrefix=b.enableTagOptions&&(b.tagOptionsPrefix||g.tagOptionsPrefix),h=this.getTagSetting("type"),h===e?c=f[b.type||g.type]:c=f[h],this.mergedOptions=d.extend({},g,c,b)},getTagSetting:function(a){var b=this.tagOptionsPrefix,d,f,g,h;if(b===!1||b===c)return e;if(this.tagValCache.hasOwnProperty(a))d=this.tagValCache.key;else{d=this.tag.getAttribute(b+a);if(d===c||d===null)d=e;else if(d.substr(0,1)==="["){d=d.substr(1,d.length-2).split(",");for(f=d.length;f--;)d[f]=k(d[f].replace(/(^\s*)|(\s*$)/g,""))}else if(d.substr(0,1)==="{"){g=d.substr(1,d.length-2).split(","),d={};for(f=g.length;f--;)h=g[f].split(":",2),d[h[0].replace(/(^\s*)|(\s*$)/g,"")]=k(h[1].replace(/(^\s*)|(\s*$)/g,""))}else d=k(d);this.tagValCache.key=d}return d},get:function(a,b){var d=this.getTagSetting(a),f;return d!==e?d:(f=this.mergedOptions[a])===c?b:f}}),d.fn.sparkline._base=g({disabled:!1,init:function(a,b,e,f,g){this.el=a,this.$el=d(a),this.values=b,this.options=e,this.width=f,this.height=g,this.currentRegion=c},initTarget:function(){var a=!this.options.get("disableInteraction");(this.target=this.$el.simpledraw(this.width,this.height,this.options.get("composite"),a))?(this.canvasWidth=this.target.pixelWidth,this.canvasHeight=this.target.pixelHeight):this.disabled=!0},render:function(){return this.disabled?(this.el.innerHTML="",!1):!0},getRegion:function(a,b){},setRegionHighlight:function(a,b,d){var e=this.currentRegion,f=!this.options.get("disableHighlight"),g;return b>this.canvasWidth||d>this.canvasHeight||b<0||d<0?null:(g=this.getRegion(a,b,d),e!==g?(e!==c&&f&&this.removeHighlight(),this.currentRegion=g,g!==c&&f&&this.renderHighlight(),!0):!1)},clearRegionHighlight:function(){return this.currentRegion!==c?(this.removeHighlight(),this.currentRegion=c,!0):!1},renderHighlight:function(){this.changeHighlight(!0)},removeHighlight:function(){this.changeHighlight(!1)},changeHighlight:function(a){},getCurrentRegionTooltip:function(){var a=this.options,b="",e=[],f,g,i,j,k,l,m,n,o,p,q,r,s,t;if(this.currentRegion===c)return"";f=this.getCurrentRegionFields(),q=a.get("tooltipFormatter");if(q)return q(this,a,f);a.get("tooltipChartTitle")&&(b+='<div class="jqs jqstitle">'+a.get("tooltipChartTitle")+"</div>\n"),g=this.options.get("tooltipFormat");if(!g)return"";d.isArray(g)||(g=[g]),d.isArray(f)||(f=[f]),m=this.options.get("tooltipFormatFieldlist"),n=this.options.get("tooltipFormatFieldlistKey");if(m&&n){o=[];for(l=f.length;l--;)p=f[l][n],(t=d.inArray(p,m))!=-1&&(o[t]=f[l]);f=o}i=g.length,s=f.length;for(l=0;l<i;l++){r=g[l],typeof r=="string"&&(r=new h(r)),j=r.fclass||"jqsfield";for(t=0;t<s;t++)if(!f[t].isNull||!a.get("tooltipSkipNull"))d.extend(f[t],{prefix:a.get("tooltipPrefix"),suffix:a.get("tooltipSuffix")}),k=r.render(f[t],a.get("tooltipValueLookups"),a),e.push('<div class="'+j+'">'+k+"</div>")}return e.length?b+e.join("\n"):""},getCurrentRegionFields:function(){},calcHighlightColor:function(a,c){var d=c.get("highlightColor"),e=c.get("highlightLighten"),f,g,h,j;if(d)return d;if(e){f=/^#([0-9a-f])([0-9a-f])([0-9a-f])$/i.exec(a)||/^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i.exec(a);if(f){h=[],g=a.length===4?16:1;for(j=0;j<3;j++)h[j]=i(b.round(parseInt(f[j+1],16)*g*e),0,255);return"rgb("+h.join(",")+")"}}return a}}),w={changeHighlight:function(a){var b=this.currentRegion,c=this.target,e=this.regionShapes[b],f;e&&(f=this.renderRegion(b,a),d.isArray(f)||d.isArray(e)?(c.replaceWithShapes(e,f),this.regionShapes[b]=d.map(f,function(a){return a.id})):(c.replaceWithShape(e,f),this.regionShapes[b]=f.id))},render:function(){var a=this.values,b=this.target,c=this.regionShapes,e,f,g,h;if(!this.cls._super.render.call(this))return;for(g=a.length;g--;){e=this.renderRegion(g);if(e)if(d.isArray(e)){f=[];for(h=e.length;h--;)e[h].append(),f.push(e[h].id);c[g]=f}else e.append(),c[g]=e.id;else c[g]=null}b.render()}},d.fn.sparkline.line=x=g(d.fn.sparkline._base,{type:"line",init:function(a,b,c,d,e){x._super.init.call(this,a,b,c,d,e),this.vertices=[],this.regionMap=[],this.xvalues=[],this.yvalues=[],this.yminmax=[],this.hightlightSpotId=null,this.lastShapeId=null,this.initTarget()},getRegion:function(a,b,d){var e,f=this.regionMap;for(e=f.length;e--;)if(f[e]!==null&&b>=f[e][0]&&b<=f[e][1])return f[e][2];return c},getCurrentRegionFields:function(){var a=this.currentRegion;return{isNull:this.yvalues[a]===null,x:this.xvalues[a],y:this.yvalues[a],color:this.options.get("lineColor"),fillColor:this.options.get("fillColor"),offset:a}},renderHighlight:function(){var a=this.currentRegion,b=this.target,d=this.vertices[a],e=this.options,f=e.get("spotRadius"),g=e.get("highlightSpotColor"),h=e.get("highlightLineColor"),i,j;if(!d)return;f&&g&&(i=b.drawCircle(d[0],d[1],f,c,g),this.highlightSpotId=i.id,b.insertAfterShape(this.lastShapeId,i)),h&&(j=b.drawLine(d[0],this.canvasTop,d[0],this.canvasTop+this.canvasHeight,h),this.highlightLineId=j.id,b.insertAfterShape(this.lastShapeId,j))},removeHighlight:function(){var a=this.target;this.highlightSpotId&&(a.removeShapeId(this.highlightSpotId),this.highlightSpotId=null),this.highlightLineId&&(a.removeShapeId(this.highlightLineId),this.highlightLineId=null)},scanValues:function(){var a=this.values,c=a.length,d=this.xvalues,e=this.yvalues,f=this.yminmax,g,h,i,j,k;for(g=0;g<c;g++)h=a[g],i=typeof a[g]=="string",j=typeof a[g]=="object"&&a[g]instanceof Array,k=i&&a[g].split(":"),i&&k.length===2?(d.push(Number(k[0])),e.push(Number(k[1])),f.push(Number(k[1]))):j?(d.push(h[0]),e.push(h[1]),f.push(h[1])):(d.push(g),a[g]===null||a[g]==="null"?e.push(null):(e.push(Number(h)),f.push(Number(h))));this.options.get("xvalues")&&(d=this.options.get("xvalues")),this.maxy=this.maxyorg=b.max.apply(b,f),this.miny=this.minyorg=b.min.apply(b,f),this.maxx=b.max.apply(b,d),this.minx=b.min.apply(b,d),this.xvalues=d,this.yvalues=e,this.yminmax=f},processRangeOptions:function(){var a=this.options,b=a.get("normalRangeMin"),d=a.get("normalRangeMax");b!==c&&(b<this.miny&&(this.miny=b),d>this.maxy&&(this.maxy=d)),a.get("chartRangeMin")!==c&&(a.get("chartRangeClip")||a.get("chartRangeMin")<this.miny)&&(this.miny=a.get("chartRangeMin")),a.get("chartRangeMax")!==c&&(a.get("chartRangeClip")||a.get("chartRangeMax")>this.maxy)&&(this.maxy=a.get("chartRangeMax")),a.get("chartRangeMinX")!==c&&(a.get("chartRangeClipX")||a.get("chartRangeMinX")<this.minx)&&(this.minx=a.get("chartRangeMinX")),a.get("chartRangeMaxX")!==c&&(a.get("chartRangeClipX")||a.get("chartRangeMaxX")>this.maxx)&&(this.maxx=a.get("chartRangeMaxX"))},drawNormalRange:function(a,d,e,f,g){var h=this.options.get("normalRangeMin"),i=this.options.get("normalRangeMax"),j=d+b.round(e-e*((i-this.miny)/g)),k=b.round(e*(i-h)/g);this.target.drawRect(a,j,f,k,c,this.options.get("normalRangeColor")).append()},render:function(){var a=this.options,e=this.target,f=this.canvasWidth,g=this.canvasHeight,h=this.vertices,i=a.get("spotRadius"),j=this.regionMap,k,l,m,n,o,p,q,r,s,u,v,w,y,z,A,B,C,D,E,F,G,H,I,J,K;if(!x._super.render.call(this))return;this.scanValues(),this.processRangeOptions(),I=this.xvalues,J=this.yvalues;if(!this.yminmax.length||this.yvalues.length<2)return;n=o=0,k=this.maxx-this.minx===0?1:this.maxx-this.minx,l=this.maxy-this.miny===0?1:this.maxy-this.miny,m=this.yvalues.length-1,i&&(f<i*4||g<i*4)&&(i=0);if(i){G=a.get("highlightSpotColor")&&!a.get("disableInteraction");if(G||a.get("minSpotColor")||a.get("spotColor")&&J[m]===this.miny)g-=b.ceil(i);if(G||a.get("maxSpotColor")||a.get("spotColor")&&J[m]===this.maxy)g-=b.ceil(i),n+=b.ceil(i);if(G||(a.get("minSpotColor")||a.get("maxSpotColor"))&&(J[0]===this.miny||J[0]===this.maxy))o+=b.ceil(i),f-=b.ceil(i);if(G||a.get("spotColor")||a.get("minSpotColor")||a.get("maxSpotColor")&&(J[m]===this.miny||J[m]===this.maxy))f-=b.ceil(i)}g--,a.get("normalRangeMin")!==c&&!a.get("drawNormalOnTop")&&this.drawNormalRange(o,n,g,f,l),q=[],r=[q],z=A=null,B=J.length;for(K=0;K<B;K++)s=I[K],v=I[K+1],u=J[K],w=o+b.round((s-this.minx)*(f/k)),y=K<B-1?o+b.round((v-this.minx)*(f/k)):f,A=w+(y-w)/2,j[K]=[z||0,A,K],z=A,u===null?K&&(J[K-1]!==null&&(q=[],r.push(q)),h.push(null)):(u<this.miny&&(u=this.miny),u>this.maxy&&(u=this.maxy),q.length||q.push([w,n+g]),p=[w,n+b.round(g-g*((u-this.miny)/l))],q.push(p),h.push(p));C=[],D=[],E=r.length;for(K=0;K<E;K++)q=r[K],q.length&&(a.get("fillColor")&&(q.push([q[q.length-1][0],n+g]),D.push(q.slice(0)),q.pop()),q.length>2&&(q[0]=[q[0][0],q[1][1]]),C.push(q));E=D.length;for(K=0;K<E;K++)e.drawShape(D[K],a.get("fillColor"),a.get("fillColor")).append();a.get("normalRangeMin")!==c&&a.get("drawNormalOnTop")&&this.drawNormalRange(o,n,g,f,l),E=C.length;for(K=0;K<E;K++)e.drawShape(C[K],a.get("lineColor"),c,a.get("lineWidth")).append();if(i&&a.get("valueSpots")){F=a.get("valueSpots"),F.get===c&&(F=new t(F));for(K=0;K<B;K++)H=F.get(J[K]),H&&e.drawCircle(o+b.round((I[K]-this.minx)*(f/k)),n+b.round(g-g*((J[K]-this.miny)/l)),i,c,H).append()}i&&a.get("spotColor")&&J[m]!==null&&e.drawCircle(o+b.round((I[I.length-1]-this.minx)*(f/k)),n+b.round(g-g*((J[m]-this.miny)/l)),i,c,a.get("spotColor")).append(),this.maxy!==this.minyorg&&(i&&a.get("minSpotColor")&&(s=I[d.inArray(this.minyorg,J)],e.drawCircle(o+b.round((s-this.minx)*(f/k)),n+b.round(g-g*((this.minyorg-this.miny)/l)),i,c,a.get("minSpotColor")).append()),i&&a.get("maxSpotColor")&&(s=I[d.inArray(this.maxyorg,J)],e.drawCircle(o+b.round((s-this.minx)*(f/k)),n+b.round(g-g*((this.maxyorg-this.miny)/l)),i,c,a.get("maxSpotColor")).append())),this.lastShapeId=e.getLastShapeId(),this.canvasTop=n,e.render()}}),d.fn.sparkline.bar=y=g(d.fn.sparkline._base,w,{type:"bar",init:function(a,e,f,g,h){var j=parseInt(f.get("barWidth"),10),n=parseInt(f.get("barSpacing"),10),o=f.get("chartRangeMin"),p=f.get("chartRangeMax"),q=f.get("chartRangeClip"),r=Infinity,s=-Infinity,u,v,w,x,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R;y._super.init.call(this,a,e,f,g,h);for(A=0,B=e.length;A<B;A++){O=e[A],u=typeof O=="string"&&O.indexOf(":")>-1;if(u||d.isArray(O))J=!0,u&&(O=e[A]=l(O.split(":"))),O=m(O,null),v=b.min.apply(b,O),w=b.max.apply(b,O),v<r&&(r=v),w>s&&(s=w)}this.stacked=J,this.regionShapes={},this.barWidth=j,this.barSpacing=n,this.totalBarWidth=j+n,this.width=g=e.length*j+(e.length-1)*n,this.initTarget(),q&&(H=o===c?-Infinity:o,I=p===c?Infinity:p),z=[],x=J?[]:z;var S=[],T=[];for(A=0,B=e.length;A<B;A++)if(J){K=e[A],e[A]=N=[],S[A]=0,x[A]=T[A]=0;for(L=0,M=K.length;L<M;L++)O=N[L]=q?i(K[L],H,I):K[L],O!==null&&(O>0&&(S[A]+=O),r<0&&s>0?O<0?T[A]+=b.abs(O):x[A]+=O:x[A]+=b.abs(O-(O<0?s:r)),z.push(O))}else O=q?i(e[A],H,I):e[A],O=e[A]=k(O),O!==null&&z.push(O);this.max=G=b.max.apply(b,z),this.min=F=b.min.apply(b,z),this.stackMax=s=J?b.max.apply(b,S):G,this.stackMin=r=J?b.min.apply(b,z):F,f.get("chartRangeMin")!==c&&(f.get("chartRangeClip")||f.get("chartRangeMin")<F)&&(F=f.get("chartRangeMin")),f.get("chartRangeMax")!==c&&(f.get("chartRangeClip")||f.get("chartRangeMax")>G)&&(G=f.get("chartRangeMax")),this.zeroAxis=D=f.get("zeroAxis",!0),F<=0&&G>=0&&D?E=0:D==0?E=F:F>0?E=F:E=G,this.xaxisOffset=E,C=J?b.max.apply(b,x)+b.max.apply(b,T):G-F,this.canvasHeightEf=D&&F<0?this.canvasHeight-2:this.canvasHeight-1,F<E?(Q=J&&G>=0?s:G,P=(Q-E)/C*this.canvasHeight,P!==b.ceil(P)&&(this.canvasHeightEf-=2,P=b.ceil(P))):P=this.canvasHeight,this.yoffset=P,d.isArray(f.get("colorMap"))?(this.colorMapByIndex=f.get("colorMap"),this.colorMapByValue=null):(this.colorMapByIndex=null,this.colorMapByValue=f.get("colorMap"),this.colorMapByValue&&this.colorMapByValue.get===c&&(this.colorMapByValue=new t(this.colorMapByValue))),this.range=C},getRegion:function(a,d,e){var f=b.floor(d/this.totalBarWidth);return f<0||f>=this.values.length?c:f},getCurrentRegionFields:function(){var a=this.currentRegion,b=r(this.values[a]),c=[],d,e;for(e=b.length;e--;)d=b[e],c.push({isNull:d===null,value:d,color:this.calcColor(e,d,a),offset:a});return c},calcColor:function(a,b,e){var f=this.colorMapByIndex,g=this.colorMapByValue,h=this.options,i,j;return this.stacked?i=h.get("stackedBarColor"):i=b<0?h.get("negBarColor"):h.get("barColor"),b===0&&h.get("zeroColor")!==c&&(i=h.get("zeroColor")),g&&(j=g.get(b))?i=j:f&&f.length>e&&(i=f[e]),d.isArray(i)?i[a%i.length]:i},renderRegion:function(a,e){var f=this.values[a],g=this.options,h=this.xaxisOffset,i=[],j=this.range,k=this.stacked,l=this.target,m=a*this.totalBarWidth,n=this.canvasHeightEf,p=this.yoffset,q,r,s,t,u,v,w,x,y,z;f=d.isArray(f)?f:[f],w=f.length,x=f[0],t=o(null,f),z=o(h,f,!0);if(t)return g.get("nullColor")?(s=e?g.get("nullColor"):this.calcHighlightColor(g.get("nullColor"),g),q=p>0?p-1:p,l.drawRect(m,q,this.barWidth-1,0,s,s)):c;u=p;for(v=0;v<w;v++){x=f[v];if(k&&x===h){if(!z||y)continue;y=!0}j>0?r=b.floor(n*(b.abs(x-h)/j))+1:r=1,x<h||x===h&&p===0?(q=u,u+=r):(q=p-r,p-=r),s=this.calcColor(v,x,a),e&&(s=this.calcHighlightColor(s,g)),i.push(l.drawRect(m,q,this.barWidth-1,r-1,s,s))}return i.length===1?i[0]:i}}),d.fn.sparkline.tristate=z=g(d.fn.sparkline._base,w,{type:"tristate",init:function(a,b,e,f,g){var h=parseInt(e.get("barWidth"),10),i=parseInt(e.get("barSpacing"),10);z._super.init.call(this,a,b,e,f,g),this.regionShapes={},this.barWidth=h,this.barSpacing=i,this.totalBarWidth=h+i,this.values=d.map(b,Number),this.width=f=b.length*h+(b.length-1)*i,d.isArray(e.get("colorMap"))?(this.colorMapByIndex=e.get("colorMap"),this.colorMapByValue=null):(this.colorMapByIndex=null,this.colorMapByValue=e.get("colorMap"),this.colorMapByValue&&this.colorMapByValue.get===c&&(this.colorMapByValue=new t(this.colorMapByValue))),this.initTarget()},getRegion:function(a,c,d){return b.floor(c/this.totalBarWidth)},getCurrentRegionFields:function(){var a=this.currentRegion;return{isNull:this.values[a]===c,value:this.values[a],color:this.calcColor(this.values[a],a),offset:a}},calcColor:function(a,b){var c=this.values,d=this.options,e=this.colorMapByIndex,f=this.colorMapByValue,g,h;return f&&(h=f.get(a))?g=h:e&&e.length>b?g=e[b]:c[b]<0?g=d.get("negBarColor"):c[b]>0?g=d.get("posBarColor"):g=d.get("zeroBarColor"),g},renderRegion:function(a,c){var d=this.values,e=this.options,f=this.target,g,h,i,j,k,l;g=f.pixelHeight,i=b.round(g/2),j=a*this.totalBarWidth,d[a]<0?(k=i,h=i-1):d[a]>0?(k=0,h=i-1):(k=i-1,h=2),l=this.calcColor(d[a],a);if(l===null)return;return c&&(l=this.calcHighlightColor(l,e)),f.drawRect(j,k,this.barWidth-1,h-1,l,l)}}),d.fn.sparkline.discrete=A=g(d.fn.sparkline._base,w,{type:"discrete",init:function(a,e,f,g,h){A._super.init.call(this,a,e,f,g,h),this.regionShapes={},this.values=e=d.map(e,Number),this.min=b.min.apply(b,e),this.max=b.max.apply(b,e),this.range=this.max-this.min,this.width=g=f.get("width")==="auto"?e.length*2:this.width,this.interval=b.floor(g/e.length),this.itemWidth=g/e.length,f.get("chartRangeMin")!==c&&(f.get("chartRangeClip")||f.get("chartRangeMin")<this.min)&&(this.min=f.get("chartRangeMin")),f.get("chartRangeMax")!==c&&(f.get("chartRangeClip")||f.get("chartRangeMax")>this.max)&&(this.max=f.get("chartRangeMax")),this.initTarget(),this.target&&(this.lineHeight=f.get("lineHeight")==="auto"?b.round(this.canvasHeight*.3):f.get("lineHeight"))},getRegion:function(a,c,d){return b.floor(c/this.itemWidth)},getCurrentRegionFields:function(){var a=this.currentRegion;return{isNull:this.values[a]===c,value:this.values[a],offset:a}},renderRegion:function(a,c){var d=this.values,e=this.options,f=this.min,g=this.max,h=this.range,j=this.interval,k=this.target,l=this.canvasHeight,m=this.lineHeight,n=l-m,o,p,q,r;return p=i(d[a],f,g),r=a*j,o=b.round(n-n*((p-f)/h)),q=e.get("thresholdColor")&&p<e.get("thresholdValue")?e.get("thresholdColor"):e.get("lineColor"),c&&(q=this.calcHighlightColor(q,e)),k.drawLine(r,o,r,o+m,q)}}),d.fn.sparkline.bullet=B=g(d.fn.sparkline._base,{type:"bullet",init:function(a,d,e,f,g){var h,i,j;B._super.init.call(this,a,d,e,f,g),this.values=d=l(d),j=d.slice(),j[0]=j[0]===null?j[2]:j[0],j[1]=d[1]===null?j[2]:j[1],h=b.min.apply(b,d),i=b.max.apply(b,d),e.get("base")===c?h=h<0?h:0:h=e.get("base"),this.min=h,this.max=i,this.range=i-h,this.shapes={},this.valueShapes={},this.regiondata={},this.width=f=e.get("width")==="auto"?"4.0em":f,this.target=this.$el.simpledraw(f,g,e.get("composite")),d.length||(this.disabled=!0),this.initTarget()},getRegion:function(a,b,d){var e=this.target.getShapeAt(a,b,d);return e!==c&&this.shapes[e]!==c?this.shapes[e]:c},getCurrentRegionFields:function(){var a=this.currentRegion;return{fieldkey:a.substr(0,1),value:this.values[a.substr(1)],region:a}},changeHighlight:function(a){var b=this.currentRegion,c=this.valueShapes[b],d;delete this.shapes[c];switch(b.substr(0,1)){case"r":d=this.renderRange(b.substr(1),a);break;case"p":d=this.renderPerformance(a);break;case"t":d=this.renderTarget(a)}this.valueShapes[b]=d.id,this.shapes[d.id]=b,this.target.replaceWithShape(c,d)},renderRange:function(a,c){var d=this.values[a],e=b.round(this.canvasWidth*((d-this.min)/this.range)),f=this.options.get("rangeColors")[a-2];return c&&(f=this.calcHighlightColor(f,this.options)),this.target.drawRect(0,0,e-1,this.canvasHeight-1,f,f)},renderPerformance:function(a){var c=this.values[1],d=b.round(this.canvasWidth*((c-this.min)/this.range)),e=this.options.get("performanceColor");return a&&(e=this.calcHighlightColor(e,this.options)),this.target.drawRect(0,b.round(this.canvasHeight*.3),d-1,b.round(this.canvasHeight*.4)-1,e,e)},renderTarget:function(a){var c=this.values[0],d=b.round(this.canvasWidth*((c-this.min)/this.range)-this.options.get("targetWidth")/2),e=b.round(this.canvasHeight*.1),f=this.canvasHeight-e*2,g=this.options.get("targetColor");return a&&(g=this.calcHighlightColor(g,this.options)),this.target.drawRect(d,e,this.options.get("targetWidth")-1,f-1,g,g)},render:function(){var a=this.values.length,b=this.target,c,d;if(!B._super.render.call(this))return;for(c=2;c<a;c++)d=this.renderRange(c).append(),this.shapes[d.id]="r"+c,this.valueShapes["r"+c]=d.id;this.values[1]!==null&&(d=this.renderPerformance().append(),this.shapes[d.id]="p1",this.valueShapes.p1=d.id),this.values[0]!==null&&(d=this.renderTarget().append(),this.shapes[d.id]="t0",this.valueShapes.t0=d.id),b.render()}}),d.fn.sparkline.pie=C=g(d.fn.sparkline._base,{type:"pie",init:function(a,c,e,f,g){var h=0,i;C._super.init.call(this,a,c,e,f,g),this.shapes={},this.valueShapes={},this.values=c=d.map(c,Number),e.get("width")==="auto"&&(this.width=this.height);if(c.length>0)for(i=c.length;i--;)h+=c[i];this.total=h,this.initTarget(),this.radius=b.floor(b.min(this.canvasWidth,this.canvasHeight)/2)},getRegion:function(a,b,d){var e=this.target.getShapeAt(a,b,d);return e!==c&&this.shapes[e]!==c?this.shapes[e]:c},getCurrentRegionFields:function(){var a=this.currentRegion;return{isNull:this.values[a]===c,value:this.values[a],percent:this.values[a]/this.total*100,color:this.options.get("sliceColors")[a%this.options.get("sliceColors").length],offset:a}},changeHighlight:function(a){var b=this.currentRegion,c=this.renderSlice(b,a),d=this.valueShapes[b];delete this.shapes[d],this.target.replaceWithShape(d,c),this.valueShapes[b]=c.id,this.shapes[c.id]=b},renderSlice:function(a,d){var e=this.target,f=this.options,g=this.radius,h=f.get("borderWidth"),i=f.get("offset"),j=2*b.PI,k=this.values,l=this.total,m=i?2*b.PI*(i/360):0,n,o,p,q,r;q=k.length;for(p=0;p<q;p++){n=m,o=m,l>0&&(o=m+j*(k[p]/l));if(a===p)return r=f.get("sliceColors")[p%f.get("sliceColors").length],d&&(r=this.calcHighlightColor(r,f)),e.drawPieSlice(g,g,g-h,n,o,c,r);m=o}},render:function(){var a=this.target,d=this.values,e=this.options,f=this.radius,g=e.get("borderWidth"),h,i;if(!C._super.render.call(this))return;g&&a.drawCircle(f,f,b.floor(f-g/2),e.get("borderColor"),c,g).append();for(i=d.length;i--;)d[i]&&(h=this.renderSlice(i).append(),this.valueShapes[i]=h.id,this.shapes[h.id]=i);a.render()}}),d.fn.sparkline.box=D=g(d.fn.sparkline._base,{type:"box",init:function(a,b,c,e,f){D._super.init.call(this,a,b,c,e,f),this.values=d.map(b,Number),this.width=c.get("width")==="auto"?"4.0em":e,this.initTarget(),this.values.length||(this.disabled=1)},getRegion:function(){return 1},getCurrentRegionFields:function(){var a=[{field:"lq",value:this.quartiles[0]},{field:"med",value:this.quartiles
+    [1]},{field:"uq",value:this.quartiles[2]}];return this.loutlier!==c&&a.push({field:"lo",value:this.loutlier}),this.routlier!==c&&a.push({field:"ro",value:this.routlier}),this.lwhisker!==c&&a.push({field:"lw",value:this.lwhisker}),this.rwhisker!==c&&a.push({field:"rw",value:this.rwhisker}),a},render:function(){var a=this.target,d=this.values,e=d.length,f=this.options,g=this.canvasWidth,h=this.canvasHeight,i=f.get("chartRangeMin")===c?b.min.apply(b,d):f.get("chartRangeMin"),k=f.get("chartRangeMax")===c?b.max.apply(b,d):f.get("chartRangeMax"),l=0,m,n,o,p,q,r,s,t,u,v,w;if(!D._super.render.call(this))return;if(f.get("raw"))f.get("showOutliers")&&d.length>5?(n=d[0],m=d[1],p=d[2],q=d[3],r=d[4],s=d[5],t=d[6]):(m=d[0],p=d[1],q=d[2],r=d[3],s=d[4]);else{d.sort(function(a,b){return a-b}),p=j(d,1),q=j(d,2),r=j(d,3),o=r-p;if(f.get("showOutliers")){m=s=c;for(u=0;u<e;u++)m===c&&d[u]>p-o*f.get("outlierIQR")&&(m=d[u]),d[u]<r+o*f.get("outlierIQR")&&(s=d[u]);n=d[0],t=d[e-1]}else m=d[0],s=d[e-1]}this.quartiles=[p,q,r],this.lwhisker=m,this.rwhisker=s,this.loutlier=n,this.routlier=t,w=g/(k-i+1),f.get("showOutliers")&&(l=b.ceil(f.get("spotRadius")),g-=2*b.ceil(f.get("spotRadius")),w=g/(k-i+1),n<m&&a.drawCircle((n-i)*w+l,h/2,f.get("spotRadius"),f.get("outlierLineColor"),f.get("outlierFillColor")).append(),t>s&&a.drawCircle((t-i)*w+l,h/2,f.get("spotRadius"),f.get("outlierLineColor"),f.get("outlierFillColor")).append()),a.drawRect(b.round((p-i)*w+l),b.round(h*.1),b.round((r-p)*w),b.round(h*.8),f.get("boxLineColor"),f.get("boxFillColor")).append(),a.drawLine(b.round((m-i)*w+l),b.round(h/2),b.round((p-i)*w+l),b.round(h/2),f.get("lineColor")).append(),a.drawLine(b.round((m-i)*w+l),b.round(h/4),b.round((m-i)*w+l),b.round(h-h/4),f.get("whiskerColor")).append(),a.drawLine(b.round((s-i)*w+l),b.round(h/2),b.round((r-i)*w+l),b.round(h/2),f.get("lineColor")).append(),a.drawLine(b.round((s-i)*w+l),b.round(h/4),b.round((s-i)*w+l),b.round(h-h/4),f.get("whiskerColor")).append(),a.drawLine(b.round((q-i)*w+l),b.round(h*.1),b.round((q-i)*w+l),b.round(h*.9),f.get("medianColor")).append(),f.get("target")&&(v=b.ceil(f.get("spotRadius")),a.drawLine(b.round((f.get("target")-i)*w+l),b.round(h/2-v),b.round((f.get("target")-i)*w+l),b.round(h/2+v),f.get("targetColor")).append(),a.drawLine(b.round((f.get("target")-i)*w+l-v),b.round(h/2),b.round((f.get("target")-i)*w+l+v),b.round(h/2),f.get("targetColor")).append()),a.render()}}),G=g({init:function(a,b,c,d){this.target=a,this.id=b,this.type=c,this.args=d},append:function(){return this.target.appendShape(this),this}}),H=g({_pxregex:/(\d+)(px)?\s*$/i,init:function(a,b,c){if(!a)return;this.width=a,this.height=b,this.target=c,this.lastShapeId=null,c[0]&&(c=c[0]),d.data(c,"_jqs_vcanvas",this)},drawLine:function(a,b,c,d,e,f){return this.drawShape([[a,b],[c,d]],e,f)},drawShape:function(a,b,c,d){return this._genShape("Shape",[a,b,c,d])},drawCircle:function(a,b,c,d,e,f){return this._genShape("Circle",[a,b,c,d,e,f])},drawPieSlice:function(a,b,c,d,e,f,g){return this._genShape("PieSlice",[a,b,c,d,e,f,g])},drawRect:function(a,b,c,d,e,f){return this._genShape("Rect",[a,b,c,d,e,f])},getElement:function(){return this.canvas},getLastShapeId:function(){return this.lastShapeId},reset:function(){alert("reset not implemented")},_insert:function(a,b){d(b).html(a)},_calculatePixelDims:function(a,b,c){var e;e=this._pxregex.exec(b),e?this.pixelHeight=e[1]:this.pixelHeight=d(c).height(),e=this._pxregex.exec(a),e?this.pixelWidth=e[1]:this.pixelWidth=d(c).width()},_genShape:function(a,b){var c=L++;return b.unshift(c),new G(this,c,a,b)},appendShape:function(a){alert("appendShape not implemented")},replaceWithShape:function(a,b){alert("replaceWithShape not implemented")},insertAfterShape:function(a,b){alert("insertAfterShape not implemented")},removeShapeId:function(a){alert("removeShapeId not implemented")},getShapeAt:function(a,b,c){alert("getShapeAt not implemented")},render:function(){alert("render not implemented")}}),I=g(H,{init:function(b,e,f,g){I._super.init.call(this,b,e,f),this.canvas=a.createElement("canvas"),f[0]&&(f=f[0]),d.data(f,"_jqs_vcanvas",this),d(this.canvas).css({display:"inline-block",width:b,height:e,verticalAlign:"top"}),this._insert(this.canvas,f),this._calculatePixelDims(b,e,this.canvas),this.canvas.width=this.pixelWidth,this.canvas.height=this.pixelHeight,this.interact=g,this.shapes={},this.shapeseq=[],this.currentTargetShapeId=c,d(this.canvas).css({width:this.pixelWidth,height:this.pixelHeight})},_getContext:function(a,b,d){var e=this.canvas.getContext("2d");return a!==c&&(e.strokeStyle=a),e.lineWidth=d===c?1:d,b!==c&&(e.fillStyle=b),e},reset:function(){var a=this._getContext();a.clearRect(0,0,this.pixelWidth,this.pixelHeight),this.shapes={},this.shapeseq=[],this.currentTargetShapeId=c},_drawShape:function(a,b,d,e,f){var g=this._getContext(d,e,f),h,i;g.beginPath(),g.moveTo(b[0][0]+.5,b[0][1]+.5);for(h=1,i=b.length;h<i;h++)g.lineTo(b[h][0]+.5,b[h][1]+.5);d!==c&&g.stroke(),e!==c&&g.fill(),this.targetX!==c&&this.targetY!==c&&g.isPointInPath(this.targetX,this.targetY)&&(this.currentTargetShapeId=a)},_drawCircle:function(a,d,e,f,g,h,i){var j=this._getContext(g,h,i);j.beginPath(),j.arc(d,e,f,0,2*b.PI,!1),this.targetX!==c&&this.targetY!==c&&j.isPointInPath(this.targetX,this.targetY)&&(this.currentTargetShapeId=a),g!==c&&j.stroke(),h!==c&&j.fill()},_drawPieSlice:function(a,b,d,e,f,g,h,i){var j=this._getContext(h,i);j.beginPath(),j.moveTo(b,d),j.arc(b,d,e,f,g,!1),j.lineTo(b,d),j.closePath(),h!==c&&j.stroke(),i&&j.fill(),this.targetX!==c&&this.targetY!==c&&j.isPointInPath(this.targetX,this.targetY)&&(this.currentTargetShapeId=a)},_drawRect:function(a,b,c,d,e,f,g){return this._drawShape(a,[[b,c],[b+d,c],[b+d,c+e],[b,c+e],[b,c]],f,g)},appendShape:function(a){return this.shapes[a.id]=a,this.shapeseq.push(a.id),this.lastShapeId=a.id,a.id},replaceWithShape:function(a,b){var c=this.shapeseq,d;this.shapes[b.id]=b;for(d=c.length;d--;)c[d]==a&&(c[d]=b.id);delete this.shapes[a]},replaceWithShapes:function(a,b){var c=this.shapeseq,d={},e,f,g;for(f=a.length;f--;)d[a[f]]=!0;for(f=c.length;f--;)e=c[f],d[e]&&(c.splice(f,1),delete this.shapes[e],g=f);for(f=b.length;f--;)c.splice(g,0,b[f].id),this.shapes[b[f].id]=b[f]},insertAfterShape:function(a,b){var c=this.shapeseq,d;for(d=c.length;d--;)if(c[d]===a){c.splice(d+1,0,b.id),this.shapes[b.id]=b;return}},removeShapeId:function(a){var b=this.shapeseq,c;for(c=b.length;c--;)if(b[c]===a){b.splice(c,1);break}delete this.shapes[a]},getShapeAt:function(a,b,c){return this.targetX=b,this.targetY=c,this.render(),this.currentTargetShapeId},render:function(){var a=this.shapeseq,b=this.shapes,c=a.length,d=this._getContext(),e,f,g;d.clearRect(0,0,this.pixelWidth,this.pixelHeight);for(g=0;g<c;g++)e=a[g],f=b[e],this["_draw"+f.type].apply(this,f.args);this.interact||(this.shapes={},this.shapeseq=[])}}),J=g(H,{init:function(b,c,e){var f;J._super.init.call(this,b,c,e),e[0]&&(e=e[0]),d.data(e,"_jqs_vcanvas",this),this.canvas=a.createElement("span"),d(this.canvas).css({display:"inline-block",position:"relative",overflow:"hidden",width:b,height:c,margin:"0px",padding:"0px",verticalAlign:"top"}),this._insert(this.canvas,e),this._calculatePixelDims(b,c,this.canvas),this.canvas.width=this.pixelWidth,this.canvas.height=this.pixelHeight,f='<v:group coordorigin="0 0" coordsize="'+this.pixelWidth+" "+this.pixelHeight+'"'+' style="position:absolute;top:0;left:0;width:'+this.pixelWidth+"px;height="+this.pixelHeight+'px;"></v:group>',this.canvas.insertAdjacentHTML("beforeEnd",f),this.group=d(this.canvas).children()[0],this.rendered=!1,this.prerender=""},_drawShape:function(a,b,d,e,f){var g=[],h,i,j,k,l,m,n;for(n=0,m=b.length;n<m;n++)g[n]=""+b[n][0]+","+b[n][1];return h=g.splice(0,1),f=f===c?1:f,i=d===c?' stroked="false" ':' strokeWeight="'+f+'px" strokeColor="'+d+'" ',j=e===c?' filled="false"':' fillColor="'+e+'" filled="true" ',k=g[0]===g[g.length-1]?"x ":"",l='<v:shape coordorigin="0 0" coordsize="'+this.pixelWidth+" "+this.pixelHeight+'" '+' id="jqsshape'+a+'" '+i+j+' style="position:absolute;left:0px;top:0px;height:'+this.pixelHeight+"px;width:"+this.pixelWidth+'px;padding:0px;margin:0px;" '+' path="m '+h+" l "+g.join(", ")+" "+k+'e">'+" </v:shape>",l},_drawCircle:function(a,b,d,e,f,g,h){var i,j,k;return b-=e,d-=e,i=f===c?' stroked="false" ':' strokeWeight="'+h+'px" strokeColor="'+f+'" ',j=g===c?' filled="false"':' fillColor="'+g+'" filled="true" ',k='<v:oval  id="jqsshape'+a+'" '+i+j+' style="position:absolute;top:'+d+"px; left:"+b+"px; width:"+e*2+"px; height:"+e*2+'px"></v:oval>',k},_drawPieSlice:function(a,d,e,f,g,h,i,j){var k,l,m,n,o,p,q,r;if(g===h)return"";h-g===2*b.PI&&(g=0,h=2*b.PI),l=d+b.round(b.cos(g)*f),m=e+b.round(b.sin(g)*f),n=d+b.round(b.cos(h)*f),o=e+b.round(b.sin(h)*f);if(l===n&&m===o){if(h-g<b.PI)return"";l=n=d+f,m=o=e}return l===n&&m===o&&h-g<b.PI?"":(k=[d-f,e-f,d+f,e+f,l,m,n,o],p=i===c?' stroked="false" ':' strokeWeight="1px" strokeColor="'+i+'" ',q=j===c?' filled="false"':' fillColor="'+j+'" filled="true" ',r='<v:shape coordorigin="0 0" coordsize="'+this.pixelWidth+" "+this.pixelHeight+'" '+' id="jqsshape'+a+'" '+p+q+' style="position:absolute;left:0px;top:0px;height:'+this.pixelHeight+"px;width:"+this.pixelWidth+'px;padding:0px;margin:0px;" '+' path="m '+d+","+e+" wa "+k.join(", ")+' x e">'+" </v:shape>",r)},_drawRect:function(a,b,c,d,e,f,g){return this._drawShape(a,[[b,c],[b,c+e],[b+d,c+e],[b+d,c],[b,c]],f,g)},reset:function(){this.group.innerHTML=""},appendShape:function(a){var b=this["_draw"+a.type].apply(this,a.args);return this.rendered?this.group.insertAdjacentHTML("beforeEnd",b):this.prerender+=b,this.lastShapeId=a.id,a.id},replaceWithShape:function(a,b){var c=d("#jqsshape"+a),e=this["_draw"+b.type].apply(this,b.args);c[0].outerHTML=e},replaceWithShapes:function(a,b){var c=d("#jqsshape"+a[0]),e="",f=b.length,g;for(g=0;g<f;g++)e+=this["_draw"+b[g].type].apply(this,b[g].args);c[0].outerHTML=e;for(g=1;g<a.length;g++)d("#jqsshape"+a[g]).remove()},insertAfterShape:function(a,b){var c=d("#jqsshape"+a),e=this["_draw"+b.type].apply(this,b.args);c[0].insertAdjacentHTML("afterEnd",e)},removeShapeId:function(a){var b=d("#jqsshape"+a);this.group.removeChild(b[0])},getShapeAt:function(a,b,c){var d=a.id.substr(8);return d},render:function(){this.rendered||(this.group.innerHTML=this.prerender,this.rendered=!0)}})})})(document,Math);
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/select2/select2-bootstrap.min.css b/ruoyi-admin/src/main/resources/static/ajax/libs/select2/select2-bootstrap.min.css
new file mode 100644
index 0000000..69924c2
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/select2/select2-bootstrap.min.css
@@ -0,0 +1,7 @@
+/*!
+ * Select2 Bootstrap Theme v0.1.0-beta.10 (https://select2.github.io/select2-bootstrap-theme)
+ * Copyright 2015-2017 Florian Kissling and contributors (https://github.com/select2/select2-bootstrap-theme/graphs/contributors)
+ * Licensed under MIT (https://github.com/select2/select2-bootstrap-theme/blob/master/LICENSE)
+ */
+
+.select2-container--bootstrap{display:block}.select2-container--bootstrap .select2-selection{background-color:#fff;border:1px solid #e5e6e7;border-radius:4px;color:#555;font-size:14px;outline:0}.select2-container--bootstrap .select2-selection.form-control{border-radius:4px}.select2-container--bootstrap .select2-search--dropdown .select2-search__field{-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);background-color:#fff;border:1px solid #ccc;border-radius:4px;color:#555;font-size:14px}.select2-container--bootstrap .select2-search__field{outline:0}.select2-container--bootstrap .select2-search__field::-webkit-input-placeholder{color:#999}.select2-container--bootstrap .select2-search__field:-moz-placeholder{color:#999}.select2-container--bootstrap .select2-search__field::-moz-placeholder{color:#999;opacity:1}.select2-container--bootstrap .select2-search__field:-ms-input-placeholder{color:#999}.select2-container--bootstrap .select2-results__option{padding:6px 12px}.select2-container--bootstrap .select2-results__option[role=group]{padding:0}.select2-container--bootstrap .select2-results__option[aria-disabled=true]{color:#777;cursor:not-allowed}.select2-container--bootstrap .select2-results__option[aria-selected=true]{background-color:#f5f5f5;color:#262626}.select2-container--bootstrap .select2-results__option--highlighted[aria-selected]{background-color:#337ab7;color:#fff}.select2-container--bootstrap .select2-results__option .select2-results__option{padding:6px 12px}.select2-container--bootstrap .select2-results__option .select2-results__option .select2-results__group{padding-left:0}.select2-container--bootstrap .select2-results__option .select2-results__option .select2-results__option{margin-left:-12px;padding-left:24px}.select2-container--bootstrap .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-24px;padding-left:36px}.select2-container--bootstrap .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-36px;padding-left:48px}.select2-container--bootstrap .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-48px;padding-left:60px}.select2-container--bootstrap .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-60px;padding-left:72px}.select2-container--bootstrap .select2-results__group{color:#777;display:block;padding:6px 12px;font-size:12px;line-height:1.42857143;white-space:nowrap}.select2-container--bootstrap.select2-container--focus .select2-selection,.select2-container--bootstrap.select2-container--open .select2-selection{-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;border-color:#66afe9}.select2-container--bootstrap.select2-container--open .select2-selection .select2-selection__arrow b{border-color:transparent transparent #999;border-width:0 4px 4px}.select2-container--bootstrap.select2-container--open.select2-container--below .select2-selection{border-bottom-right-radius:0;border-bottom-left-radius:0;border-bottom-color:transparent}.select2-container--bootstrap.select2-container--open.select2-container--above .select2-selection{border-top-right-radius:0;border-top-left-radius:0;border-top-color:transparent}.select2-container--bootstrap .select2-selection__clear{color:#999;cursor:pointer;float:right;font-weight:700;margin-right:10px}.select2-container--bootstrap .select2-selection__clear:hover{color:#333}.select2-container--bootstrap.select2-container--disabled .select2-selection{border-color:#ccc;-webkit-box-shadow:none;box-shadow:none}.select2-container--bootstrap.select2-container--disabled .select2-search__field,.select2-container--bootstrap.select2-container--disabled .select2-selection{cursor:not-allowed}.select2-container--bootstrap.select2-container--disabled .select2-selection,.select2-container--bootstrap.select2-container--disabled .select2-selection--multiple .select2-selection__choice{background-color:#eee}.select2-container--bootstrap.select2-container--disabled .select2-selection--multiple .select2-selection__choice__remove,.select2-container--bootstrap.select2-container--disabled .select2-selection__clear{display:none}.select2-container--bootstrap .select2-dropdown{-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175);border-color:#66afe9;overflow-x:hidden;margin-top:-1px}.select2-container--bootstrap .select2-dropdown--above{-webkit-box-shadow:0 -6px 12px rgba(0,0,0,.175);box-shadow:0 -6px 12px rgba(0,0,0,.175);margin-top:1px}.select2-container--bootstrap .select2-results>.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--bootstrap .select2-selection--single{height:31px;line-height:1.42857143;padding:4px 6px 4px}.select2-container--bootstrap .select2-selection--single .select2-selection__arrow{position:absolute;bottom:0;right:12px;top:0;width:4px}.select2-container--bootstrap .select2-selection--single .select2-selection__arrow b{border-color:#999 transparent transparent;border-style:solid;border-width:4px 4px 0;height:0;left:0;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--bootstrap .select2-selection--single .select2-selection__rendered{color:#555;padding:0}.select2-container--bootstrap .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--bootstrap .select2-selection--multiple{min-height:31px;padding:0;height:auto}.select2-container--bootstrap .select2-selection--multiple .select2-selection__rendered{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:block;line-height:1.42857143;list-style:none;margin:0;overflow:hidden;padding:0;width:100%;text-overflow:ellipsis;white-space:nowrap}.select2-container--bootstrap .select2-selection--multiple .select2-selection__placeholder{color:#999;float:left;margin-top:5px}.select2-container--bootstrap .select2-selection--multiple .select2-selection__choice{color:#fff;background:#1AB394;border:1px solid #1AB394;border-radius:4px;cursor:default;float:left;margin:5px 0 0 6px;padding:0 6px}.select2-container--bootstrap .select2-selection--multiple .select2-search--inline .select2-search__field{background:0 0;padding:4px 6px 4px;height:31px;line-height:1.42857143;margin-top:0;min-width:5em}.select2-container--bootstrap .select2-selection--multiple .select2-selection__choice__remove{color:#fff;cursor:pointer;display:inline-block;font-weight:700;margin-right:3px}.select2-container--bootstrap .select2-selection--multiple .select2-selection__choice__remove:hover{color:#333}.select2-container--bootstrap .select2-selection--multiple .select2-selection__clear{margin-top:6px}.form-group-sm .select2-container--bootstrap .select2-selection--single,.input-group-sm .select2-container--bootstrap .select2-selection--single,.select2-container--bootstrap .select2-selection--single.input-sm{border-radius:3px;font-size:12px;height:30px;line-height:1.5;padding:5px 22px 5px 10px}.form-group-sm .select2-container--bootstrap .select2-selection--single .select2-selection__arrow b,.input-group-sm .select2-container--bootstrap .select2-selection--single .select2-selection__arrow b,.select2-container--bootstrap .select2-selection--single.input-sm .select2-selection__arrow b{margin-left:-5px}.form-group-sm .select2-container--bootstrap .select2-selection--multiple,.input-group-sm .select2-container--bootstrap .select2-selection--multiple,.select2-container--bootstrap .select2-selection--multiple.input-sm{min-height:30px;border-radius:3px}.form-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-selection__choice,.input-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-selection__choice,.select2-container--bootstrap .select2-selection--multiple.input-sm .select2-selection__choice{font-size:12px;line-height:1.5;margin:4px 0 0 5px;padding:0 5px}.form-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-search--inline .select2-search__field,.input-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-search--inline .select2-search__field,.select2-container--bootstrap .select2-selection--multiple.input-sm .select2-search--inline .select2-search__field{padding:0 10px;font-size:12px;height:28px;line-height:1.5}.form-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-selection__clear,.input-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-selection__clear,.select2-container--bootstrap .select2-selection--multiple.input-sm .select2-selection__clear{margin-top:5px}.form-group-lg .select2-container--bootstrap .select2-selection--single,.input-group-lg .select2-container--bootstrap .select2-selection--single,.select2-container--bootstrap .select2-selection--single.input-lg{border-radius:6px;font-size:18px;height:46px;line-height:1.3333333;padding:10px 31px 10px 16px}.form-group-lg .select2-container--bootstrap .select2-selection--single .select2-selection__arrow,.input-group-lg .select2-container--bootstrap .select2-selection--single .select2-selection__arrow,.select2-container--bootstrap .select2-selection--single.input-lg .select2-selection__arrow{width:5px}.form-group-lg .select2-container--bootstrap .select2-selection--single .select2-selection__arrow b,.input-group-lg .select2-container--bootstrap .select2-selection--single .select2-selection__arrow b,.select2-container--bootstrap .select2-selection--single.input-lg .select2-selection__arrow b{border-width:5px 5px 0;margin-left:-10px;margin-top:-2.5px}.form-group-lg .select2-container--bootstrap .select2-selection--multiple,.input-group-lg .select2-container--bootstrap .select2-selection--multiple,.select2-container--bootstrap .select2-selection--multiple.input-lg{min-height:46px;border-radius:6px}.form-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-selection__choice,.input-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-selection__choice,.select2-container--bootstrap .select2-selection--multiple.input-lg .select2-selection__choice{font-size:18px;line-height:1.3333333;border-radius:4px;margin:9px 0 0 8px;padding:0 10px}.form-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-search--inline .select2-search__field,.input-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-search--inline .select2-search__field,.select2-container--bootstrap .select2-selection--multiple.input-lg .select2-search--inline .select2-search__field{padding:0 16px;font-size:18px;height:44px;line-height:1.3333333}.form-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-selection__clear,.input-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-selection__clear,.select2-container--bootstrap .select2-selection--multiple.input-lg .select2-selection__clear{margin-top:10px}.input-group-lg .select2-container--bootstrap .select2-selection.select2-container--open .select2-selection--single .select2-selection__arrow b,.select2-container--bootstrap .select2-selection.input-lg.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #999;border-width:0 5px 5px}.select2-container--bootstrap[dir=rtl] .select2-selection--single{padding-left:24px;padding-right:12px}.select2-container--bootstrap[dir=rtl] .select2-selection--single .select2-selection__rendered{padding-right:0;padding-left:0;text-align:right}.select2-container--bootstrap[dir=rtl] .select2-selection--single .select2-selection__clear{float:left}.select2-container--bootstrap[dir=rtl] .select2-selection--single .select2-selection__arrow{left:12px;right:auto}.select2-container--bootstrap[dir=rtl] .select2-selection--single .select2-selection__arrow b{margin-left:0}.select2-container--bootstrap[dir=rtl] .select2-selection--multiple .select2-search--inline,.select2-container--bootstrap[dir=rtl] .select2-selection--multiple .select2-selection__choice,.select2-container--bootstrap[dir=rtl] .select2-selection--multiple .select2-selection__placeholder{float:right}.select2-container--bootstrap[dir=rtl] .select2-selection--multiple .select2-selection__choice{margin-left:0;margin-right:6px}.select2-container--bootstrap[dir=rtl] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.has-warning .select2-dropdown,.has-warning .select2-selection{border-color:#8a6d3b}.has-warning .select2-container--focus .select2-selection,.has-warning .select2-container--open .select2-selection{-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;border-color:#66512c}.has-warning.select2-drop-active{border-color:#66512c}.has-warning.select2-drop-active.select2-drop.select2-drop-above{border-top-color:#66512c}.has-error .select2-dropdown,.has-error .select2-selection{border-color:#a94442}.has-error .select2-container--focus .select2-selection,.has-error .select2-container--open .select2-selection{-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;border-color:#843534}.has-error.select2-drop-active{border-color:#843534}.has-error.select2-drop-active.select2-drop.select2-drop-above{border-top-color:#843534}.has-success .select2-dropdown,.has-success .select2-selection{border-color:#3c763d}.has-success .select2-container--focus .select2-selection,.has-success .select2-container--open .select2-selection{-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;border-color:#2b542c}.has-success.select2-drop-active{border-color:#2b542c}.has-success.select2-drop-active.select2-drop.select2-drop-above{border-top-color:#2b542c}.input-group>.select2-hidden-accessible:first-child+.select2-container--bootstrap>.selection>.select2-selection,.input-group>.select2-hidden-accessible:first-child+.select2-container--bootstrap>.selection>.select2-selection.form-control{border-bottom-right-radius:0;border-top-right-radius:0}.input-group>.select2-hidden-accessible:not(:first-child)+.select2-container--bootstrap:not(:last-child)>.selection>.select2-selection,.input-group>.select2-hidden-accessible:not(:first-child)+.select2-container--bootstrap:not(:last-child)>.selection>.select2-selection.form-control{border-radius:0}.input-group>.select2-hidden-accessible:not(:first-child):not(:last-child)+.select2-container--bootstrap:last-child>.selection>.select2-selection,.input-group>.select2-hidden-accessible:not(:first-child):not(:last-child)+.select2-container--bootstrap:last-child>.selection>.select2-selection.form-control{border-bottom-left-radius:0;border-top-left-radius:0}.input-group>.select2-container--bootstrap{display:table;table-layout:fixed;position:relative;z-index:2;width:100%;margin-bottom:0}.input-group>.select2-container--bootstrap>.selection>.select2-selection.form-control{float:none}.input-group>.select2-container--bootstrap.select2-container--focus,.input-group>.select2-container--bootstrap.select2-container--open{z-index:3}.input-group>.select2-container--bootstrap,.input-group>.select2-container--bootstrap .input-group-btn,.input-group>.select2-container--bootstrap .input-group-btn .btn{vertical-align:top}.form-control.select2-hidden-accessible{position:absolute!important;width:1px!important}@media (min-width:768px){.form-inline .select2-container--bootstrap{display:inline-block}}
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/select2/select2.css b/ruoyi-admin/src/main/resources/static/ajax/libs/select2/select2.css
new file mode 100644
index 0000000..750b320
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/select2/select2.css
@@ -0,0 +1,481 @@
+.select2-container {
+  box-sizing: border-box;
+  display: inline-block;
+  margin: 0;
+  position: relative;
+  vertical-align: middle; }
+  .select2-container .select2-selection--single {
+    box-sizing: border-box;
+    cursor: pointer;
+    display: block;
+    height: 28px;
+    user-select: none;
+    -webkit-user-select: none; }
+    .select2-container .select2-selection--single .select2-selection__rendered {
+      display: block;
+      padding-left: 8px;
+      padding-right: 20px;
+      overflow: hidden;
+      text-overflow: ellipsis;
+      white-space: nowrap; }
+    .select2-container .select2-selection--single .select2-selection__clear {
+      position: relative; }
+  .select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered {
+    padding-right: 8px;
+    padding-left: 20px; }
+  .select2-container .select2-selection--multiple {
+    box-sizing: border-box;
+    cursor: pointer;
+    display: block;
+    min-height: 32px;
+    user-select: none;
+    -webkit-user-select: none; }
+    .select2-container .select2-selection--multiple .select2-selection__rendered {
+      display: inline-block;
+      overflow: hidden;
+      padding-left: 8px;
+      text-overflow: ellipsis;
+      white-space: nowrap; }
+  .select2-container .select2-search--inline {
+    float: left; }
+    .select2-container .select2-search--inline .select2-search__field {
+      box-sizing: border-box;
+      border: none;
+      font-size: 100%;
+      margin-top: 5px;
+      padding: 0; }
+      .select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button {
+        -webkit-appearance: none; }
+
+.select2-dropdown {
+  background-color: white;
+  border: 1px solid #aaa;
+  border-radius: 4px;
+  box-sizing: border-box;
+  display: block;
+  position: absolute;
+  left: -100000px;
+  width: 100%;
+  z-index: 1051; }
+
+.select2-results {
+  display: block; }
+
+.select2-results__options {
+  list-style: none;
+  margin: 0;
+  padding: 0; }
+
+.select2-results__option {
+  padding: 6px;
+  user-select: none;
+  -webkit-user-select: none; }
+  .select2-results__option[aria-selected] {
+    cursor: pointer; }
+
+.select2-container--open .select2-dropdown {
+  left: 0; }
+
+.select2-container--open .select2-dropdown--above {
+  border-bottom: none;
+  border-bottom-left-radius: 0;
+  border-bottom-right-radius: 0; }
+
+.select2-container--open .select2-dropdown--below {
+  border-top: none;
+  border-top-left-radius: 0;
+  border-top-right-radius: 0; }
+
+.select2-search--dropdown {
+  display: block;
+  padding: 4px; }
+  .select2-search--dropdown .select2-search__field {
+    padding: 4px;
+    width: 100%;
+    box-sizing: border-box; }
+    .select2-search--dropdown .select2-search__field::-webkit-search-cancel-button {
+      -webkit-appearance: none; }
+  .select2-search--dropdown.select2-search--hide {
+    display: none; }
+
+.select2-close-mask {
+  border: 0;
+  margin: 0;
+  padding: 0;
+  display: block;
+  position: fixed;
+  left: 0;
+  top: 0;
+  min-height: 100%;
+  min-width: 100%;
+  height: auto;
+  width: auto;
+  opacity: 0;
+  z-index: 99;
+  background-color: #fff;
+  filter: alpha(opacity=0); }
+
+.select2-hidden-accessible {
+  border: 0 !important;
+  clip: rect(0 0 0 0) !important;
+  -webkit-clip-path: inset(50%) !important;
+  clip-path: inset(50%) !important;
+  height: 1px !important;
+  overflow: hidden !important;
+  padding: 0 !important;
+  position: absolute !important;
+  width: 1px !important;
+  white-space: nowrap !important; }
+
+.select2-container--default .select2-selection--single {
+  background-color: #fff;
+  border: 1px solid #aaa;
+  border-radius: 4px; }
+  .select2-container--default .select2-selection--single .select2-selection__rendered {
+    color: #444;
+    line-height: 28px; }
+  .select2-container--default .select2-selection--single .select2-selection__clear {
+    cursor: pointer;
+    float: right;
+    font-weight: bold; }
+  .select2-container--default .select2-selection--single .select2-selection__placeholder {
+    color: #999; }
+  .select2-container--default .select2-selection--single .select2-selection__arrow {
+    height: 26px;
+    position: absolute;
+    top: 1px;
+    right: 1px;
+    width: 20px; }
+    .select2-container--default .select2-selection--single .select2-selection__arrow b {
+      border-color: #888 transparent transparent transparent;
+      border-style: solid;
+      border-width: 5px 4px 0 4px;
+      height: 0;
+      left: 50%;
+      margin-left: -4px;
+      margin-top: -2px;
+      position: absolute;
+      top: 50%;
+      width: 0; }
+
+.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__clear {
+  float: left; }
+
+.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__arrow {
+  left: 1px;
+  right: auto; }
+
+.select2-container--default.select2-container--disabled .select2-selection--single {
+  background-color: #eee;
+  cursor: default; }
+  .select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear {
+    display: none; }
+
+.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b {
+  border-color: transparent transparent #888 transparent;
+  border-width: 0 4px 5px 4px; }
+
+.select2-container--default .select2-selection--multiple {
+  background-color: white;
+  border: 1px solid #aaa;
+  border-radius: 4px;
+  cursor: text; }
+  .select2-container--default .select2-selection--multiple .select2-selection__rendered {
+    box-sizing: border-box;
+    list-style: none;
+    margin: 0;
+    padding: 0 5px;
+    width: 100%; }
+    .select2-container--default .select2-selection--multiple .select2-selection__rendered li {
+      list-style: none; }
+  .select2-container--default .select2-selection--multiple .select2-selection__clear {
+    cursor: pointer;
+    float: right;
+    font-weight: bold;
+    margin-top: 5px;
+    margin-right: 10px;
+    padding: 1px; }
+  .select2-container--default .select2-selection--multiple .select2-selection__choice {
+    background-color: #e4e4e4;
+    border: 1px solid #aaa;
+    border-radius: 4px;
+    cursor: default;
+    float: left;
+    margin-right: 5px;
+    margin-top: 5px;
+    padding: 0 5px; }
+  .select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
+    color: #999;
+    cursor: pointer;
+    display: inline-block;
+    font-weight: bold;
+    margin-right: 2px; }
+    .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover {
+      color: #333; }
+
+.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice, .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-search--inline {
+  float: right; }
+
+.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
+  margin-left: 5px;
+  margin-right: auto; }
+
+.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove {
+  margin-left: 2px;
+  margin-right: auto; }
+
+.select2-container--default.select2-container--focus .select2-selection--multiple {
+  border: solid black 1px;
+  outline: 0; }
+
+.select2-container--default.select2-container--disabled .select2-selection--multiple {
+  background-color: #eee;
+  cursor: default; }
+
+.select2-container--default.select2-container--disabled .select2-selection__choice__remove {
+  display: none; }
+
+.select2-container--default.select2-container--open.select2-container--above .select2-selection--single, .select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple {
+  border-top-left-radius: 0;
+  border-top-right-radius: 0; }
+
+.select2-container--default.select2-container--open.select2-container--below .select2-selection--single, .select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple {
+  border-bottom-left-radius: 0;
+  border-bottom-right-radius: 0; }
+
+.select2-container--default .select2-search--dropdown .select2-search__field {
+  border: 1px solid #aaa; }
+
+.select2-container--default .select2-search--inline .select2-search__field {
+  background: transparent;
+  border: none;
+  outline: 0;
+  box-shadow: none;
+  -webkit-appearance: textfield; }
+
+.select2-container--default .select2-results > .select2-results__options {
+  max-height: 200px;
+  overflow-y: auto; }
+
+.select2-container--default .select2-results__option[role=group] {
+  padding: 0; }
+
+.select2-container--default .select2-results__option[aria-disabled=true] {
+  color: #999; }
+
+.select2-container--default .select2-results__option[aria-selected=true] {
+  background-color: #ddd; }
+
+.select2-container--default .select2-results__option .select2-results__option {
+  padding-left: 1em; }
+  .select2-container--default .select2-results__option .select2-results__option .select2-results__group {
+    padding-left: 0; }
+  .select2-container--default .select2-results__option .select2-results__option .select2-results__option {
+    margin-left: -1em;
+    padding-left: 2em; }
+    .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
+      margin-left: -2em;
+      padding-left: 3em; }
+      .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
+        margin-left: -3em;
+        padding-left: 4em; }
+        .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
+          margin-left: -4em;
+          padding-left: 5em; }
+          .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
+            margin-left: -5em;
+            padding-left: 6em; }
+
+.select2-container--default .select2-results__option--highlighted[aria-selected] {
+  background-color: #5897fb;
+  color: white; }
+
+.select2-container--default .select2-results__group {
+  cursor: default;
+  display: block;
+  padding: 6px; }
+
+.select2-container--classic .select2-selection--single {
+  background-color: #f7f7f7;
+  border: 1px solid #aaa;
+  border-radius: 4px;
+  outline: 0;
+  background-image: -webkit-linear-gradient(top, white 50%, #eeeeee 100%);
+  background-image: -o-linear-gradient(top, white 50%, #eeeeee 100%);
+  background-image: linear-gradient(to bottom, white 50%, #eeeeee 100%);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0); }
+  .select2-container--classic .select2-selection--single:focus {
+    border: 1px solid #5897fb; }
+  .select2-container--classic .select2-selection--single .select2-selection__rendered {
+    color: #444;
+    line-height: 28px; }
+  .select2-container--classic .select2-selection--single .select2-selection__clear {
+    cursor: pointer;
+    float: right;
+    font-weight: bold;
+    margin-right: 10px; }
+  .select2-container--classic .select2-selection--single .select2-selection__placeholder {
+    color: #999; }
+  .select2-container--classic .select2-selection--single .select2-selection__arrow {
+    background-color: #ddd;
+    border: none;
+    border-left: 1px solid #aaa;
+    border-top-right-radius: 4px;
+    border-bottom-right-radius: 4px;
+    height: 26px;
+    position: absolute;
+    top: 1px;
+    right: 1px;
+    width: 20px;
+    background-image: -webkit-linear-gradient(top, #eeeeee 50%, #cccccc 100%);
+    background-image: -o-linear-gradient(top, #eeeeee 50%, #cccccc 100%);
+    background-image: linear-gradient(to bottom, #eeeeee 50%, #cccccc 100%);
+    background-repeat: repeat-x;
+    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFCCCCCC', GradientType=0); }
+    .select2-container--classic .select2-selection--single .select2-selection__arrow b {
+      border-color: #888 transparent transparent transparent;
+      border-style: solid;
+      border-width: 5px 4px 0 4px;
+      height: 0;
+      left: 50%;
+      margin-left: -4px;
+      margin-top: -2px;
+      position: absolute;
+      top: 50%;
+      width: 0; }
+
+.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__clear {
+  float: left; }
+
+.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__arrow {
+  border: none;
+  border-right: 1px solid #aaa;
+  border-radius: 0;
+  border-top-left-radius: 4px;
+  border-bottom-left-radius: 4px;
+  left: 1px;
+  right: auto; }
+
+.select2-container--classic.select2-container--open .select2-selection--single {
+  border: 1px solid #5897fb; }
+  .select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow {
+    background: transparent;
+    border: none; }
+    .select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b {
+      border-color: transparent transparent #888 transparent;
+      border-width: 0 4px 5px 4px; }
+
+.select2-container--classic.select2-container--open.select2-container--above .select2-selection--single {
+  border-top: none;
+  border-top-left-radius: 0;
+  border-top-right-radius: 0;
+  background-image: -webkit-linear-gradient(top, white 0%, #eeeeee 50%);
+  background-image: -o-linear-gradient(top, white 0%, #eeeeee 50%);
+  background-image: linear-gradient(to bottom, white 0%, #eeeeee 50%);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0); }
+
+.select2-container--classic.select2-container--open.select2-container--below .select2-selection--single {
+  border-bottom: none;
+  border-bottom-left-radius: 0;
+  border-bottom-right-radius: 0;
+  background-image: -webkit-linear-gradient(top, #eeeeee 50%, white 100%);
+  background-image: -o-linear-gradient(top, #eeeeee 50%, white 100%);
+  background-image: linear-gradient(to bottom, #eeeeee 50%, white 100%);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFFFFFFF', GradientType=0); }
+
+.select2-container--classic .select2-selection--multiple {
+  background-color: white;
+  border: 1px solid #aaa;
+  border-radius: 4px;
+  cursor: text;
+  outline: 0; }
+  .select2-container--classic .select2-selection--multiple:focus {
+    border: 1px solid #5897fb; }
+  .select2-container--classic .select2-selection--multiple .select2-selection__rendered {
+    list-style: none;
+    margin: 0;
+    padding: 0 5px; }
+  .select2-container--classic .select2-selection--multiple .select2-selection__clear {
+    display: none; }
+  .select2-container--classic .select2-selection--multiple .select2-selection__choice {
+    background-color: #e4e4e4;
+    border: 1px solid #aaa;
+    border-radius: 4px;
+    cursor: default;
+    float: left;
+    margin-right: 5px;
+    margin-top: 5px;
+    padding: 0 5px; }
+  .select2-container--classic .select2-selection--multiple .select2-selection__choice__remove {
+    color: #888;
+    cursor: pointer;
+    display: inline-block;
+    font-weight: bold;
+    margin-right: 2px; }
+    .select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover {
+      color: #555; }
+
+.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
+  float: right;
+  margin-left: 5px;
+  margin-right: auto; }
+
+.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove {
+  margin-left: 2px;
+  margin-right: auto; }
+
+.select2-container--classic.select2-container--open .select2-selection--multiple {
+  border: 1px solid #5897fb; }
+
+.select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple {
+  border-top: none;
+  border-top-left-radius: 0;
+  border-top-right-radius: 0; }
+
+.select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple {
+  border-bottom: none;
+  border-bottom-left-radius: 0;
+  border-bottom-right-radius: 0; }
+
+.select2-container--classic .select2-search--dropdown .select2-search__field {
+  border: 1px solid #aaa;
+  outline: 0; }
+
+.select2-container--classic .select2-search--inline .select2-search__field {
+  outline: 0;
+  box-shadow: none; }
+
+.select2-container--classic .select2-dropdown {
+  background-color: white;
+  border: 1px solid transparent; }
+
+.select2-container--classic .select2-dropdown--above {
+  border-bottom: none; }
+
+.select2-container--classic .select2-dropdown--below {
+  border-top: none; }
+
+.select2-container--classic .select2-results > .select2-results__options {
+  max-height: 200px;
+  overflow-y: auto; }
+
+.select2-container--classic .select2-results__option[role=group] {
+  padding: 0; }
+
+.select2-container--classic .select2-results__option[aria-disabled=true] {
+  color: grey; }
+
+.select2-container--classic .select2-results__option--highlighted[aria-selected] {
+  background-color: #3875d7;
+  color: white; }
+
+.select2-container--classic .select2-results__group {
+  cursor: default;
+  display: block;
+  padding: 6px; }
+
+.select2-container--classic.select2-container--open .select2-dropdown {
+  border-color: #5897fb; }
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/select2/select2.js b/ruoyi-admin/src/main/resources/static/ajax/libs/select2/select2.js
new file mode 100644
index 0000000..7afb385
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/select2/select2.js
@@ -0,0 +1,6108 @@
+/*!
+ * Select2 4.0.13
+ * https://select2.github.io
+ *
+ * Released under the MIT license
+ * https://github.com/select2/select2/blob/master/LICENSE.md
+ */
+;(function (factory) {
+  if (typeof define === 'function' && define.amd) {
+    // AMD. Register as an anonymous module.
+    define(['jquery'], factory);
+  } else if (typeof module === 'object' && module.exports) {
+    // Node/CommonJS
+    module.exports = function (root, jQuery) {
+      if (jQuery === undefined) {
+        // require('jQuery') returns a factory that requires window to
+        // build a jQuery instance, we normalize how we use modules
+        // that require this pattern but the window provided is a noop
+        // if it's defined (how jquery works)
+        if (typeof window !== 'undefined') {
+          jQuery = require('jquery');
+        }
+        else {
+          jQuery = require('jquery')(root);
+        }
+      }
+      factory(jQuery);
+      return jQuery;
+    };
+  } else {
+    // Browser globals
+    factory(jQuery);
+  }
+} (function (jQuery) {
+  // This is needed so we can catch the AMD loader configuration and use it
+  // The inner file should be wrapped (by `banner.start.js`) in a function that
+  // returns the AMD loader references.
+  var S2 =(function () {
+  // Restore the Select2 AMD loader so it can be used
+  // Needed mostly in the language files, where the loader is not inserted
+  if (jQuery && jQuery.fn && jQuery.fn.select2 && jQuery.fn.select2.amd) {
+    var S2 = jQuery.fn.select2.amd;
+  }
+var S2;(function () { if (!S2 || !S2.requirejs) {
+if (!S2) { S2 = {}; } else { require = S2; }
+/**
+ * @license almond 0.3.3 Copyright jQuery Foundation and other contributors.
+ * Released under MIT license, http://github.com/requirejs/almond/LICENSE
+ */
+//Going sloppy to avoid 'use strict' string cost, but strict practices should
+//be followed.
+/*global setTimeout: false */
+
+var requirejs, require, define;
+(function (undef) {
+    var main, req, makeMap, handlers,
+        defined = {},
+        waiting = {},
+        config = {},
+        defining = {},
+        hasOwn = Object.prototype.hasOwnProperty,
+        aps = [].slice,
+        jsSuffixRegExp = /\.js$/;
+
+    function hasProp(obj, prop) {
+        return hasOwn.call(obj, prop);
+    }
+
+    /**
+     * Given a relative module name, like ./something, normalize it to
+     * a real name that can be mapped to a path.
+     * @param {String} name the relative name
+     * @param {String} baseName a real name that the name arg is relative
+     * to.
+     * @returns {String} normalized name
+     */
+    function normalize(name, baseName) {
+        var nameParts, nameSegment, mapValue, foundMap, lastIndex,
+            foundI, foundStarMap, starI, i, j, part, normalizedBaseParts,
+            baseParts = baseName && baseName.split("/"),
+            map = config.map,
+            starMap = (map && map['*']) || {};
+
+        //Adjust any relative paths.
+        if (name) {
+            name = name.split('/');
+            lastIndex = name.length - 1;
+
+            // If wanting node ID compatibility, strip .js from end
+            // of IDs. Have to do this here, and not in nameToUrl
+            // because node allows either .js or non .js to map
+            // to same file.
+            if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) {
+                name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');
+            }
+
+            // Starts with a '.' so need the baseName
+            if (name[0].charAt(0) === '.' && baseParts) {
+                //Convert baseName to array, and lop off the last part,
+                //so that . matches that 'directory' and not name of the baseName's
+                //module. For instance, baseName of 'one/two/three', maps to
+                //'one/two/three.js', but we want the directory, 'one/two' for
+                //this normalization.
+                normalizedBaseParts = baseParts.slice(0, baseParts.length - 1);
+                name = normalizedBaseParts.concat(name);
+            }
+
+            //start trimDots
+            for (i = 0; i < name.length; i++) {
+                part = name[i];
+                if (part === '.') {
+                    name.splice(i, 1);
+                    i -= 1;
+                } else if (part === '..') {
+                    // If at the start, or previous value is still ..,
+                    // keep them so that when converted to a path it may
+                    // still work when converted to a path, even though
+                    // as an ID it is less than ideal. In larger point
+                    // releases, may be better to just kick out an error.
+                    if (i === 0 || (i === 1 && name[2] === '..') || name[i - 1] === '..') {
+                        continue;
+                    } else if (i > 0) {
+                        name.splice(i - 1, 2);
+                        i -= 2;
+                    }
+                }
+            }
+            //end trimDots
+
+            name = name.join('/');
+        }
+
+        //Apply map config if available.
+        if ((baseParts || starMap) && map) {
+            nameParts = name.split('/');
+
+            for (i = nameParts.length; i > 0; i -= 1) {
+                nameSegment = nameParts.slice(0, i).join("/");
+
+                if (baseParts) {
+                    //Find the longest baseName segment match in the config.
+                    //So, do joins on the biggest to smallest lengths of baseParts.
+                    for (j = baseParts.length; j > 0; j -= 1) {
+                        mapValue = map[baseParts.slice(0, j).join('/')];
+
+                        //baseName segment has  config, find if it has one for
+                        //this name.
+                        if (mapValue) {
+                            mapValue = mapValue[nameSegment];
+                            if (mapValue) {
+                                //Match, update name to the new value.
+                                foundMap = mapValue;
+                                foundI = i;
+                                break;
+                            }
+                        }
+                    }
+                }
+
+                if (foundMap) {
+                    break;
+                }
+
+                //Check for a star map match, but just hold on to it,
+                //if there is a shorter segment match later in a matching
+                //config, then favor over this star map.
+                if (!foundStarMap && starMap && starMap[nameSegment]) {
+                    foundStarMap = starMap[nameSegment];
+                    starI = i;
+                }
+            }
+
+            if (!foundMap && foundStarMap) {
+                foundMap = foundStarMap;
+                foundI = starI;
+            }
+
+            if (foundMap) {
+                nameParts.splice(0, foundI, foundMap);
+                name = nameParts.join('/');
+            }
+        }
+
+        return name;
+    }
+
+    function makeRequire(relName, forceSync) {
+        return function () {
+            //A version of a require function that passes a moduleName
+            //value for items that may need to
+            //look up paths relative to the moduleName
+            var args = aps.call(arguments, 0);
+
+            //If first arg is not require('string'), and there is only
+            //one arg, it is the array form without a callback. Insert
+            //a null so that the following concat is correct.
+            if (typeof args[0] !== 'string' && args.length === 1) {
+                args.push(null);
+            }
+            return req.apply(undef, args.concat([relName, forceSync]));
+        };
+    }
+
+    function makeNormalize(relName) {
+        return function (name) {
+            return normalize(name, relName);
+        };
+    }
+
+    function makeLoad(depName) {
+        return function (value) {
+            defined[depName] = value;
+        };
+    }
+
+    function callDep(name) {
+        if (hasProp(waiting, name)) {
+            var args = waiting[name];
+            delete waiting[name];
+            defining[name] = true;
+            main.apply(undef, args);
+        }
+
+        if (!hasProp(defined, name) && !hasProp(defining, name)) {
+            throw new Error('No ' + name);
+        }
+        return defined[name];
+    }
+
+    //Turns a plugin!resource to [plugin, resource]
+    //with the plugin being undefined if the name
+    //did not have a plugin prefix.
+    function splitPrefix(name) {
+        var prefix,
+            index = name ? name.indexOf('!') : -1;
+        if (index > -1) {
+            prefix = name.substring(0, index);
+            name = name.substring(index + 1, name.length);
+        }
+        return [prefix, name];
+    }
+
+    //Creates a parts array for a relName where first part is plugin ID,
+    //second part is resource ID. Assumes relName has already been normalized.
+    function makeRelParts(relName) {
+        return relName ? splitPrefix(relName) : [];
+    }
+
+    /**
+     * Makes a name map, normalizing the name, and using a plugin
+     * for normalization if necessary. Grabs a ref to plugin
+     * too, as an optimization.
+     */
+    makeMap = function (name, relParts) {
+        var plugin,
+            parts = splitPrefix(name),
+            prefix = parts[0],
+            relResourceName = relParts[1];
+
+        name = parts[1];
+
+        if (prefix) {
+            prefix = normalize(prefix, relResourceName);
+            plugin = callDep(prefix);
+        }
+
+        //Normalize according
+        if (prefix) {
+            if (plugin && plugin.normalize) {
+                name = plugin.normalize(name, makeNormalize(relResourceName));
+            } else {
+                name = normalize(name, relResourceName);
+            }
+        } else {
+            name = normalize(name, relResourceName);
+            parts = splitPrefix(name);
+            prefix = parts[0];
+            name = parts[1];
+            if (prefix) {
+                plugin = callDep(prefix);
+            }
+        }
+
+        //Using ridiculous property names for space reasons
+        return {
+            f: prefix ? prefix + '!' + name : name, //fullName
+            n: name,
+            pr: prefix,
+            p: plugin
+        };
+    };
+
+    function makeConfig(name) {
+        return function () {
+            return (config && config.config && config.config[name]) || {};
+        };
+    }
+
+    handlers = {
+        require: function (name) {
+            return makeRequire(name);
+        },
+        exports: function (name) {
+            var e = defined[name];
+            if (typeof e !== 'undefined') {
+                return e;
+            } else {
+                return (defined[name] = {});
+            }
+        },
+        module: function (name) {
+            return {
+                id: name,
+                uri: '',
+                exports: defined[name],
+                config: makeConfig(name)
+            };
+        }
+    };
+
+    main = function (name, deps, callback, relName) {
+        var cjsModule, depName, ret, map, i, relParts,
+            args = [],
+            callbackType = typeof callback,
+            usingExports;
+
+        //Use name if no relName
+        relName = relName || name;
+        relParts = makeRelParts(relName);
+
+        //Call the callback to define the module, if necessary.
+        if (callbackType === 'undefined' || callbackType === 'function') {
+            //Pull out the defined dependencies and pass the ordered
+            //values to the callback.
+            //Default to [require, exports, module] if no deps
+            deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps;
+            for (i = 0; i < deps.length; i += 1) {
+                map = makeMap(deps[i], relParts);
+                depName = map.f;
+
+                //Fast path CommonJS standard dependencies.
+                if (depName === "require") {
+                    args[i] = handlers.require(name);
+                } else if (depName === "exports") {
+                    //CommonJS module spec 1.1
+                    args[i] = handlers.exports(name);
+                    usingExports = true;
+                } else if (depName === "module") {
+                    //CommonJS module spec 1.1
+                    cjsModule = args[i] = handlers.module(name);
+                } else if (hasProp(defined, depName) ||
+                           hasProp(waiting, depName) ||
+                           hasProp(defining, depName)) {
+                    args[i] = callDep(depName);
+                } else if (map.p) {
+                    map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {});
+                    args[i] = defined[depName];
+                } else {
+                    throw new Error(name + ' missing ' + depName);
+                }
+            }
+
+            ret = callback ? callback.apply(defined[name], args) : undefined;
+
+            if (name) {
+                //If setting exports via "module" is in play,
+                //favor that over return value and exports. After that,
+                //favor a non-undefined return value over exports use.
+                if (cjsModule && cjsModule.exports !== undef &&
+                        cjsModule.exports !== defined[name]) {
+                    defined[name] = cjsModule.exports;
+                } else if (ret !== undef || !usingExports) {
+                    //Use the return value from the function.
+                    defined[name] = ret;
+                }
+            }
+        } else if (name) {
+            //May just be an object definition for the module. Only
+            //worry about defining if have a module name.
+            defined[name] = callback;
+        }
+    };
+
+    requirejs = require = req = function (deps, callback, relName, forceSync, alt) {
+        if (typeof deps === "string") {
+            if (handlers[deps]) {
+                //callback in this case is really relName
+                return handlers[deps](callback);
+            }
+            //Just return the module wanted. In this scenario, the
+            //deps arg is the module name, and second arg (if passed)
+            //is just the relName.
+            //Normalize module name, if it contains . or ..
+            return callDep(makeMap(deps, makeRelParts(callback)).f);
+        } else if (!deps.splice) {
+            //deps is a config object, not an array.
+            config = deps;
+            if (config.deps) {
+                req(config.deps, config.callback);
+            }
+            if (!callback) {
+                return;
+            }
+
+            if (callback.splice) {
+                //callback is an array, which means it is a dependency list.
+                //Adjust args if there are dependencies
+                deps = callback;
+                callback = relName;
+                relName = null;
+            } else {
+                deps = undef;
+            }
+        }
+
+        //Support require(['a'])
+        callback = callback || function () {};
+
+        //If relName is a function, it is an errback handler,
+        //so remove it.
+        if (typeof relName === 'function') {
+            relName = forceSync;
+            forceSync = alt;
+        }
+
+        //Simulate async callback;
+        if (forceSync) {
+            main(undef, deps, callback, relName);
+        } else {
+            //Using a non-zero value because of concern for what old browsers
+            //do, and latest browsers "upgrade" to 4 if lower value is used:
+            //http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout:
+            //If want a value immediately, use require('id') instead -- something
+            //that works in almond on the global level, but not guaranteed and
+            //unlikely to work in other AMD implementations.
+            setTimeout(function () {
+                main(undef, deps, callback, relName);
+            }, 4);
+        }
+
+        return req;
+    };
+
+    /**
+     * Just drops the config on the floor, but returns req in case
+     * the config return value is used.
+     */
+    req.config = function (cfg) {
+        return req(cfg);
+    };
+
+    /**
+     * Expose module registry for debugging and tooling
+     */
+    requirejs._defined = defined;
+
+    define = function (name, deps, callback) {
+        if (typeof name !== 'string') {
+            throw new Error('See almond README: incorrect module build, no module name');
+        }
+
+        //This module may not have dependencies
+        if (!deps.splice) {
+            //deps is not an array, so probably means
+            //an object literal or factory function for
+            //the value. Adjust args.
+            callback = deps;
+            deps = [];
+        }
+
+        if (!hasProp(defined, name) && !hasProp(waiting, name)) {
+            waiting[name] = [name, deps, callback];
+        }
+    };
+
+    define.amd = {
+        jQuery: true
+    };
+}());
+
+S2.requirejs = requirejs;S2.require = require;S2.define = define;
+}
+}());
+S2.define("almond", function(){});
+
+/* global jQuery:false, $:false */
+S2.define('jquery',[],function () {
+  var _$ = jQuery || $;
+
+  if (_$ == null && console && console.error) {
+    console.error(
+      'Select2: An instance of jQuery or a jQuery-compatible library was not ' +
+      'found. Make sure that you are including jQuery before Select2 on your ' +
+      'web page.'
+    );
+  }
+
+  return _$;
+});
+
+S2.define('select2/utils',[
+  'jquery'
+], function ($) {
+  var Utils = {};
+
+  Utils.Extend = function (ChildClass, SuperClass) {
+    var __hasProp = {}.hasOwnProperty;
+
+    function BaseConstructor () {
+      this.constructor = ChildClass;
+    }
+
+    for (var key in SuperClass) {
+      if (__hasProp.call(SuperClass, key)) {
+        ChildClass[key] = SuperClass[key];
+      }
+    }
+
+    BaseConstructor.prototype = SuperClass.prototype;
+    ChildClass.prototype = new BaseConstructor();
+    ChildClass.__super__ = SuperClass.prototype;
+
+    return ChildClass;
+  };
+
+  function getMethods (theClass) {
+    var proto = theClass.prototype;
+
+    var methods = [];
+
+    for (var methodName in proto) {
+      var m = proto[methodName];
+
+      if (typeof m !== 'function') {
+        continue;
+      }
+
+      if (methodName === 'constructor') {
+        continue;
+      }
+
+      methods.push(methodName);
+    }
+
+    return methods;
+  }
+
+  Utils.Decorate = function (SuperClass, DecoratorClass) {
+    var decoratedMethods = getMethods(DecoratorClass);
+    var superMethods = getMethods(SuperClass);
+
+    function DecoratedClass () {
+      var unshift = Array.prototype.unshift;
+
+      var argCount = DecoratorClass.prototype.constructor.length;
+
+      var calledConstructor = SuperClass.prototype.constructor;
+
+      if (argCount > 0) {
+        unshift.call(arguments, SuperClass.prototype.constructor);
+
+        calledConstructor = DecoratorClass.prototype.constructor;
+      }
+
+      calledConstructor.apply(this, arguments);
+    }
+
+    DecoratorClass.displayName = SuperClass.displayName;
+
+    function ctr () {
+      this.constructor = DecoratedClass;
+    }
+
+    DecoratedClass.prototype = new ctr();
+
+    for (var m = 0; m < superMethods.length; m++) {
+      var superMethod = superMethods[m];
+
+      DecoratedClass.prototype[superMethod] =
+        SuperClass.prototype[superMethod];
+    }
+
+    var calledMethod = function (methodName) {
+      // Stub out the original method if it's not decorating an actual method
+      var originalMethod = function () {};
+
+      if (methodName in DecoratedClass.prototype) {
+        originalMethod = DecoratedClass.prototype[methodName];
+      }
+
+      var decoratedMethod = DecoratorClass.prototype[methodName];
+
+      return function () {
+        var unshift = Array.prototype.unshift;
+
+        unshift.call(arguments, originalMethod);
+
+        return decoratedMethod.apply(this, arguments);
+      };
+    };
+
+    for (var d = 0; d < decoratedMethods.length; d++) {
+      var decoratedMethod = decoratedMethods[d];
+
+      DecoratedClass.prototype[decoratedMethod] = calledMethod(decoratedMethod);
+    }
+
+    return DecoratedClass;
+  };
+
+  var Observable = function () {
+    this.listeners = {};
+  };
+
+  Observable.prototype.on = function (event, callback) {
+    this.listeners = this.listeners || {};
+
+    if (event in this.listeners) {
+      this.listeners[event].push(callback);
+    } else {
+      this.listeners[event] = [callback];
+    }
+  };
+
+  Observable.prototype.trigger = function (event) {
+    var slice = Array.prototype.slice;
+    var params = slice.call(arguments, 1);
+
+    this.listeners = this.listeners || {};
+
+    // Params should always come in as an array
+    if (params == null) {
+      params = [];
+    }
+
+    // If there are no arguments to the event, use a temporary object
+    if (params.length === 0) {
+      params.push({});
+    }
+
+    // Set the `_type` of the first object to the event
+    params[0]._type = event;
+
+    if (event in this.listeners) {
+      this.invoke(this.listeners[event], slice.call(arguments, 1));
+    }
+
+    if ('*' in this.listeners) {
+      this.invoke(this.listeners['*'], arguments);
+    }
+  };
+
+  Observable.prototype.invoke = function (listeners, params) {
+    for (var i = 0, len = listeners.length; i < len; i++) {
+      listeners[i].apply(this, params);
+    }
+  };
+
+  Utils.Observable = Observable;
+
+  Utils.generateChars = function (length) {
+    var chars = '';
+
+    for (var i = 0; i < length; i++) {
+      var randomChar = Math.floor(Math.random() * 36);
+      chars += randomChar.toString(36);
+    }
+
+    return chars;
+  };
+
+  Utils.bind = function (func, context) {
+    return function () {
+      func.apply(context, arguments);
+    };
+  };
+
+  Utils._convertData = function (data) {
+    for (var originalKey in data) {
+      var keys = originalKey.split('-');
+
+      var dataLevel = data;
+
+      if (keys.length === 1) {
+        continue;
+      }
+
+      for (var k = 0; k < keys.length; k++) {
+        var key = keys[k];
+
+        // Lowercase the first letter
+        // By default, dash-separated becomes camelCase
+        key = key.substring(0, 1).toLowerCase() + key.substring(1);
+
+        if (!(key in dataLevel)) {
+          dataLevel[key] = {};
+        }
+
+        if (k == keys.length - 1) {
+          dataLevel[key] = data[originalKey];
+        }
+
+        dataLevel = dataLevel[key];
+      }
+
+      delete data[originalKey];
+    }
+
+    return data;
+  };
+
+  Utils.hasScroll = function (index, el) {
+    // Adapted from the function created by @ShadowScripter
+    // and adapted by @BillBarry on the Stack Exchange Code Review website.
+    // The original code can be found at
+    // http://codereview.stackexchange.com/q/13338
+    // and was designed to be used with the Sizzle selector engine.
+
+    var $el = $(el);
+    var overflowX = el.style.overflowX;
+    var overflowY = el.style.overflowY;
+
+    //Check both x and y declarations
+    if (overflowX === overflowY &&
+        (overflowY === 'hidden' || overflowY === 'visible')) {
+      return false;
+    }
+
+    if (overflowX === 'scroll' || overflowY === 'scroll') {
+      return true;
+    }
+
+    return ($el.innerHeight() < el.scrollHeight ||
+      $el.innerWidth() < el.scrollWidth);
+  };
+
+  Utils.escapeMarkup = function (markup) {
+    var replaceMap = {
+      '\\': '&#92;',
+      '&': '&amp;',
+      '<': '&lt;',
+      '>': '&gt;',
+      '"': '&quot;',
+      '\'': '&#39;',
+      '/': '&#47;'
+    };
+
+    // Do not try to escape the markup if it's not a string
+    if (typeof markup !== 'string') {
+      return markup;
+    }
+
+    return String(markup).replace(/[&<>"'\/\\]/g, function (match) {
+      return replaceMap[match];
+    });
+  };
+
+  // Append an array of jQuery nodes to a given element.
+  Utils.appendMany = function ($element, $nodes) {
+    // jQuery 1.7.x does not support $.fn.append() with an array
+    // Fall back to a jQuery object collection using $.fn.add()
+    if ($.fn.jquery.substr(0, 3) === '1.7') {
+      var $jqNodes = $();
+
+      $.map($nodes, function (node) {
+        $jqNodes = $jqNodes.add(node);
+      });
+
+      $nodes = $jqNodes;
+    }
+
+    $element.append($nodes);
+  };
+
+  // Cache objects in Utils.__cache instead of $.data (see #4346)
+  Utils.__cache = {};
+
+  var id = 0;
+  Utils.GetUniqueElementId = function (element) {
+    // Get a unique element Id. If element has no id,
+    // creates a new unique number, stores it in the id
+    // attribute and returns the new id.
+    // If an id already exists, it simply returns it.
+
+    var select2Id = element.getAttribute('data-select2-id');
+    if (select2Id == null) {
+      // If element has id, use it.
+      if (element.id) {
+        select2Id = element.id;
+        element.setAttribute('data-select2-id', select2Id);
+      } else {
+        element.setAttribute('data-select2-id', ++id);
+        select2Id = id.toString();
+      }
+    }
+    return select2Id;
+  };
+
+  Utils.StoreData = function (element, name, value) {
+    // Stores an item in the cache for a specified element.
+    // name is the cache key.
+    var id = Utils.GetUniqueElementId(element);
+    if (!Utils.__cache[id]) {
+      Utils.__cache[id] = {};
+    }
+
+    Utils.__cache[id][name] = value;
+  };
+
+  Utils.GetData = function (element, name) {
+    // Retrieves a value from the cache by its key (name)
+    // name is optional. If no name specified, return
+    // all cache items for the specified element.
+    // and for a specified element.
+    var id = Utils.GetUniqueElementId(element);
+    if (name) {
+      if (Utils.__cache[id]) {
+        if (Utils.__cache[id][name] != null) {
+          return Utils.__cache[id][name];
+        }
+        return $(element).data(name); // Fallback to HTML5 data attribs.
+      }
+      return $(element).data(name); // Fallback to HTML5 data attribs.
+    } else {
+      return Utils.__cache[id];
+    }
+  };
+
+  Utils.RemoveData = function (element) {
+    // Removes all cached items for a specified element.
+    var id = Utils.GetUniqueElementId(element);
+    if (Utils.__cache[id] != null) {
+      delete Utils.__cache[id];
+    }
+
+    element.removeAttribute('data-select2-id');
+  };
+
+  return Utils;
+});
+
+S2.define('select2/results',[
+  'jquery',
+  './utils'
+], function ($, Utils) {
+  function Results ($element, options, dataAdapter) {
+    this.$element = $element;
+    this.data = dataAdapter;
+    this.options = options;
+
+    Results.__super__.constructor.call(this);
+  }
+
+  Utils.Extend(Results, Utils.Observable);
+
+  Results.prototype.render = function () {
+    var $results = $(
+      '<ul class="select2-results__options" role="listbox"></ul>'
+    );
+
+    if (this.options.get('multiple')) {
+      $results.attr('aria-multiselectable', 'true');
+    }
+
+    this.$results = $results;
+
+    return $results;
+  };
+
+  Results.prototype.clear = function () {
+    this.$results.empty();
+  };
+
+  Results.prototype.displayMessage = function (params) {
+    var escapeMarkup = this.options.get('escapeMarkup');
+
+    this.clear();
+    this.hideLoading();
+
+    var $message = $(
+      '<li role="alert" aria-live="assertive"' +
+      ' class="select2-results__option"></li>'
+    );
+
+    var message = this.options.get('translations').get(params.message);
+
+    $message.append(
+      escapeMarkup(
+        message(params.args)
+      )
+    );
+
+    $message[0].className += ' select2-results__message';
+
+    this.$results.append($message);
+  };
+
+  Results.prototype.hideMessages = function () {
+    this.$results.find('.select2-results__message').remove();
+  };
+
+  Results.prototype.append = function (data) {
+    this.hideLoading();
+
+    var $options = [];
+
+    if (data.results == null || data.results.length === 0) {
+      if (this.$results.children().length === 0) {
+        this.trigger('results:message', {
+          message: 'noResults'
+        });
+      }
+
+      return;
+    }
+
+    data.results = this.sort(data.results);
+
+    for (var d = 0; d < data.results.length; d++) {
+      var item = data.results[d];
+
+      var $option = this.option(item);
+
+      $options.push($option);
+    }
+
+    this.$results.append($options);
+  };
+
+  Results.prototype.position = function ($results, $dropdown) {
+    var $resultsContainer = $dropdown.find('.select2-results');
+    $resultsContainer.append($results);
+  };
+
+  Results.prototype.sort = function (data) {
+    var sorter = this.options.get('sorter');
+
+    return sorter(data);
+  };
+
+  Results.prototype.highlightFirstItem = function () {
+    var $options = this.$results
+      .find('.select2-results__option[aria-selected]');
+
+    var $selected = $options.filter('[aria-selected=true]');
+
+    // Check if there are any selected options
+    if ($selected.length > 0) {
+      // If there are selected options, highlight the first
+      $selected.first().trigger('mouseenter');
+    } else {
+      // If there are no selected options, highlight the first option
+      // in the dropdown
+      $options.first().trigger('mouseenter');
+    }
+
+    this.ensureHighlightVisible();
+  };
+
+  Results.prototype.setClasses = function () {
+    var self = this;
+
+    this.data.current(function (selected) {
+      var selectedIds = $.map(selected, function (s) {
+        return s.id.toString();
+      });
+
+      var $options = self.$results
+        .find('.select2-results__option[aria-selected]');
+
+      $options.each(function () {
+        var $option = $(this);
+
+        var item = Utils.GetData(this, 'data');
+
+        // id needs to be converted to a string when comparing
+        var id = '' + item.id;
+
+        if ((item.element != null && item.element.selected) ||
+            (item.element == null && $.inArray(id, selectedIds) > -1)) {
+          $option.attr('aria-selected', 'true');
+        } else {
+          $option.attr('aria-selected', 'false');
+        }
+      });
+
+    });
+  };
+
+  Results.prototype.showLoading = function (params) {
+    this.hideLoading();
+
+    var loadingMore = this.options.get('translations').get('searching');
+
+    var loading = {
+      disabled: true,
+      loading: true,
+      text: loadingMore(params)
+    };
+    var $loading = this.option(loading);
+    $loading.className += ' loading-results';
+
+    this.$results.prepend($loading);
+  };
+
+  Results.prototype.hideLoading = function () {
+    this.$results.find('.loading-results').remove();
+  };
+
+  Results.prototype.option = function (data) {
+    var option = document.createElement('li');
+    option.className = 'select2-results__option';
+
+    var attrs = {
+      'role': 'option',
+      'aria-selected': 'false'
+    };
+
+    var matches = window.Element.prototype.matches ||
+      window.Element.prototype.msMatchesSelector ||
+      window.Element.prototype.webkitMatchesSelector;
+
+    if ((data.element != null && matches.call(data.element, ':disabled')) ||
+        (data.element == null && data.disabled)) {
+      delete attrs['aria-selected'];
+      attrs['aria-disabled'] = 'true';
+    }
+
+    if (data.id == null) {
+      delete attrs['aria-selected'];
+    }
+
+    if (data._resultId != null) {
+      option.id = data._resultId;
+    }
+
+    if (data.title) {
+      option.title = data.title;
+    }
+
+    if (data.children) {
+      attrs.role = 'group';
+      attrs['aria-label'] = data.text;
+      delete attrs['aria-selected'];
+    }
+
+    for (var attr in attrs) {
+      var val = attrs[attr];
+
+      option.setAttribute(attr, val);
+    }
+
+    if (data.children) {
+      var $option = $(option);
+
+      var label = document.createElement('strong');
+      label.className = 'select2-results__group';
+
+      var $label = $(label);
+      this.template(data, label);
+
+      var $children = [];
+
+      for (var c = 0; c < data.children.length; c++) {
+        var child = data.children[c];
+
+        var $child = this.option(child);
+
+        $children.push($child);
+      }
+
+      var $childrenContainer = $('<ul></ul>', {
+        'class': 'select2-results__options select2-results__options--nested'
+      });
+
+      $childrenContainer.append($children);
+
+      $option.append(label);
+      $option.append($childrenContainer);
+    } else {
+      this.template(data, option);
+    }
+
+    Utils.StoreData(option, 'data', data);
+
+    return option;
+  };
+
+  Results.prototype.bind = function (container, $container) {
+    var self = this;
+
+    var id = container.id + '-results';
+
+    this.$results.attr('id', id);
+
+    container.on('results:all', function (params) {
+      self.clear();
+      self.append(params.data);
+
+      if (container.isOpen()) {
+        self.setClasses();
+        self.highlightFirstItem();
+      }
+    });
+
+    container.on('results:append', function (params) {
+      self.append(params.data);
+
+      if (container.isOpen()) {
+        self.setClasses();
+      }
+    });
+
+    container.on('query', function (params) {
+      self.hideMessages();
+      self.showLoading(params);
+    });
+
+    container.on('select', function () {
+      if (!container.isOpen()) {
+        return;
+      }
+
+      self.setClasses();
+
+      if (self.options.get('scrollAfterSelect')) {
+        self.highlightFirstItem();
+      }
+    });
+
+    container.on('unselect', function () {
+      if (!container.isOpen()) {
+        return;
+      }
+
+      self.setClasses();
+
+      if (self.options.get('scrollAfterSelect')) {
+        self.highlightFirstItem();
+      }
+    });
+
+    container.on('open', function () {
+      // When the dropdown is open, aria-expended="true"
+      self.$results.attr('aria-expanded', 'true');
+      self.$results.attr('aria-hidden', 'false');
+
+      self.setClasses();
+      self.ensureHighlightVisible();
+    });
+
+    container.on('close', function () {
+      // When the dropdown is closed, aria-expended="false"
+      self.$results.attr('aria-expanded', 'false');
+      self.$results.attr('aria-hidden', 'true');
+      self.$results.removeAttr('aria-activedescendant');
+    });
+
+    container.on('results:toggle', function () {
+      var $highlighted = self.getHighlightedResults();
+
+      if ($highlighted.length === 0) {
+        return;
+      }
+
+      $highlighted.trigger('mouseup');
+    });
+
+    container.on('results:select', function () {
+      var $highlighted = self.getHighlightedResults();
+
+      if ($highlighted.length === 0) {
+        return;
+      }
+
+      var data = Utils.GetData($highlighted[0], 'data');
+
+      if ($highlighted.attr('aria-selected') == 'true') {
+        self.trigger('close', {});
+      } else {
+        self.trigger('select', {
+          data: data
+        });
+      }
+    });
+
+    container.on('results:previous', function () {
+      var $highlighted = self.getHighlightedResults();
+
+      var $options = self.$results.find('[aria-selected]');
+
+      var currentIndex = $options.index($highlighted);
+
+      // If we are already at the top, don't move further
+      // If no options, currentIndex will be -1
+      if (currentIndex <= 0) {
+        return;
+      }
+
+      var nextIndex = currentIndex - 1;
+
+      // If none are highlighted, highlight the first
+      if ($highlighted.length === 0) {
+        nextIndex = 0;
+      }
+
+      var $next = $options.eq(nextIndex);
+
+      $next.trigger('mouseenter');
+
+      var currentOffset = self.$results.offset().top;
+      var nextTop = $next.offset().top;
+      var nextOffset = self.$results.scrollTop() + (nextTop - currentOffset);
+
+      if (nextIndex === 0) {
+        self.$results.scrollTop(0);
+      } else if (nextTop - currentOffset < 0) {
+        self.$results.scrollTop(nextOffset);
+      }
+    });
+
+    container.on('results:next', function () {
+      var $highlighted = self.getHighlightedResults();
+
+      var $options = self.$results.find('[aria-selected]');
+
+      var currentIndex = $options.index($highlighted);
+
+      var nextIndex = currentIndex + 1;
+
+      // If we are at the last option, stay there
+      if (nextIndex >= $options.length) {
+        return;
+      }
+
+      var $next = $options.eq(nextIndex);
+
+      $next.trigger('mouseenter');
+
+      var currentOffset = self.$results.offset().top +
+        self.$results.outerHeight(false);
+      var nextBottom = $next.offset().top + $next.outerHeight(false);
+      var nextOffset = self.$results.scrollTop() + nextBottom - currentOffset;
+
+      if (nextIndex === 0) {
+        self.$results.scrollTop(0);
+      } else if (nextBottom > currentOffset) {
+        self.$results.scrollTop(nextOffset);
+      }
+    });
+
+    container.on('results:focus', function (params) {
+      params.element.addClass('select2-results__option--highlighted');
+    });
+
+    container.on('results:message', function (params) {
+      self.displayMessage(params);
+    });
+
+    if ($.fn.mousewheel) {
+      this.$results.on('mousewheel', function (e) {
+        var top = self.$results.scrollTop();
+
+        var bottom = self.$results.get(0).scrollHeight - top + e.deltaY;
+
+        var isAtTop = e.deltaY > 0 && top - e.deltaY <= 0;
+        var isAtBottom = e.deltaY < 0 && bottom <= self.$results.height();
+
+        if (isAtTop) {
+          self.$results.scrollTop(0);
+
+          e.preventDefault();
+          e.stopPropagation();
+        } else if (isAtBottom) {
+          self.$results.scrollTop(
+            self.$results.get(0).scrollHeight - self.$results.height()
+          );
+
+          e.preventDefault();
+          e.stopPropagation();
+        }
+      });
+    }
+
+    this.$results.on('mouseup', '.select2-results__option[aria-selected]',
+      function (evt) {
+      var $this = $(this);
+
+      var data = Utils.GetData(this, 'data');
+
+      if ($this.attr('aria-selected') === 'true') {
+        if (self.options.get('multiple')) {
+          self.trigger('unselect', {
+            originalEvent: evt,
+            data: data
+          });
+        } else {
+          self.trigger('close', {});
+        }
+
+        return;
+      }
+
+      self.trigger('select', {
+        originalEvent: evt,
+        data: data
+      });
+    });
+
+    this.$results.on('mouseenter', '.select2-results__option[aria-selected]',
+      function (evt) {
+      var data = Utils.GetData(this, 'data');
+
+      self.getHighlightedResults()
+          .removeClass('select2-results__option--highlighted');
+
+      self.trigger('results:focus', {
+        data: data,
+        element: $(this)
+      });
+    });
+  };
+
+  Results.prototype.getHighlightedResults = function () {
+    var $highlighted = this.$results
+    .find('.select2-results__option--highlighted');
+
+    return $highlighted;
+  };
+
+  Results.prototype.destroy = function () {
+    this.$results.remove();
+  };
+
+  Results.prototype.ensureHighlightVisible = function () {
+    var $highlighted = this.getHighlightedResults();
+
+    if ($highlighted.length === 0) {
+      return;
+    }
+
+    var $options = this.$results.find('[aria-selected]');
+
+    var currentIndex = $options.index($highlighted);
+
+    var currentOffset = this.$results.offset().top;
+    var nextTop = $highlighted.offset().top;
+    var nextOffset = this.$results.scrollTop() + (nextTop - currentOffset);
+
+    var offsetDelta = nextTop - currentOffset;
+    nextOffset -= $highlighted.outerHeight(false) * 2;
+
+    if (currentIndex <= 2) {
+      this.$results.scrollTop(0);
+    } else if (offsetDelta > this.$results.outerHeight() || offsetDelta < 0) {
+      this.$results.scrollTop(nextOffset);
+    }
+  };
+
+  Results.prototype.template = function (result, container) {
+    var template = this.options.get('templateResult');
+    var escapeMarkup = this.options.get('escapeMarkup');
+
+    var content = template(result, container);
+
+    if (content == null) {
+      container.style.display = 'none';
+    } else if (typeof content === 'string') {
+      container.innerHTML = escapeMarkup(content);
+    } else {
+      $(container).append(content);
+    }
+  };
+
+  return Results;
+});
+
+S2.define('select2/keys',[
+
+], function () {
+  var KEYS = {
+    BACKSPACE: 8,
+    TAB: 9,
+    ENTER: 13,
+    SHIFT: 16,
+    CTRL: 17,
+    ALT: 18,
+    ESC: 27,
+    SPACE: 32,
+    PAGE_UP: 33,
+    PAGE_DOWN: 34,
+    END: 35,
+    HOME: 36,
+    LEFT: 37,
+    UP: 38,
+    RIGHT: 39,
+    DOWN: 40,
+    DELETE: 46
+  };
+
+  return KEYS;
+});
+
+S2.define('select2/selection/base',[
+  'jquery',
+  '../utils',
+  '../keys'
+], function ($, Utils, KEYS) {
+  function BaseSelection ($element, options) {
+    this.$element = $element;
+    this.options = options;
+
+    BaseSelection.__super__.constructor.call(this);
+  }
+
+  Utils.Extend(BaseSelection, Utils.Observable);
+
+  BaseSelection.prototype.render = function () {
+    var $selection = $(
+      '<span class="select2-selection" role="combobox" ' +
+      ' aria-haspopup="true" aria-expanded="false">' +
+      '</span>'
+    );
+
+    this._tabindex = 0;
+
+    if (Utils.GetData(this.$element[0], 'old-tabindex') != null) {
+      this._tabindex = Utils.GetData(this.$element[0], 'old-tabindex');
+    } else if (this.$element.attr('tabindex') != null) {
+      this._tabindex = this.$element.attr('tabindex');
+    }
+
+    $selection.attr('title', this.$element.attr('title'));
+    $selection.attr('tabindex', this._tabindex);
+    $selection.attr('aria-disabled', 'false');
+
+    this.$selection = $selection;
+
+    return $selection;
+  };
+
+  BaseSelection.prototype.bind = function (container, $container) {
+    var self = this;
+
+    var resultsId = container.id + '-results';
+
+    this.container = container;
+
+    this.$selection.on('focus', function (evt) {
+      self.trigger('focus', evt);
+    });
+
+    this.$selection.on('blur', function (evt) {
+      self._handleBlur(evt);
+    });
+
+    this.$selection.on('keydown', function (evt) {
+      self.trigger('keypress', evt);
+
+      if (evt.which === KEYS.SPACE) {
+        evt.preventDefault();
+      }
+    });
+
+    container.on('results:focus', function (params) {
+      self.$selection.attr('aria-activedescendant', params.data._resultId);
+    });
+
+    container.on('selection:update', function (params) {
+      self.update(params.data);
+    });
+
+    container.on('open', function () {
+      // When the dropdown is open, aria-expanded="true"
+      self.$selection.attr('aria-expanded', 'true');
+      self.$selection.attr('aria-owns', resultsId);
+
+      self._attachCloseHandler(container);
+    });
+
+    container.on('close', function () {
+      // When the dropdown is closed, aria-expanded="false"
+      self.$selection.attr('aria-expanded', 'false');
+      self.$selection.removeAttr('aria-activedescendant');
+      self.$selection.removeAttr('aria-owns');
+
+      self.$selection.trigger('focus');
+
+      self._detachCloseHandler(container);
+    });
+
+    container.on('enable', function () {
+      self.$selection.attr('tabindex', self._tabindex);
+      self.$selection.attr('aria-disabled', 'false');
+    });
+
+    container.on('disable', function () {
+      self.$selection.attr('tabindex', '-1');
+      self.$selection.attr('aria-disabled', 'true');
+    });
+  };
+
+  BaseSelection.prototype._handleBlur = function (evt) {
+    var self = this;
+
+    // This needs to be delayed as the active element is the body when the tab
+    // key is pressed, possibly along with others.
+    window.setTimeout(function () {
+      // Don't trigger `blur` if the focus is still in the selection
+      if (
+        (document.activeElement == self.$selection[0]) ||
+        ($.contains(self.$selection[0], document.activeElement))
+      ) {
+        return;
+      }
+
+      self.trigger('blur', evt);
+    }, 1);
+  };
+
+  BaseSelection.prototype._attachCloseHandler = function (container) {
+
+    $(document.body).on('mousedown.select2.' + container.id, function (e) {
+      var $target = $(e.target);
+
+      var $select = $target.closest('.select2');
+
+      var $all = $('.select2.select2-container--open');
+
+      $all.each(function () {
+        if (this == $select[0]) {
+          return;
+        }
+
+        var $element = Utils.GetData(this, 'element');
+
+        $element.select2('close');
+      });
+    });
+  };
+
+  BaseSelection.prototype._detachCloseHandler = function (container) {
+    $(document.body).off('mousedown.select2.' + container.id);
+  };
+
+  BaseSelection.prototype.position = function ($selection, $container) {
+    var $selectionContainer = $container.find('.selection');
+    $selectionContainer.append($selection);
+  };
+
+  BaseSelection.prototype.destroy = function () {
+    this._detachCloseHandler(this.container);
+  };
+
+  BaseSelection.prototype.update = function (data) {
+    throw new Error('The `update` method must be defined in child classes.');
+  };
+
+  /**
+   * Helper method to abstract the "enabled" (not "disabled") state of this
+   * object.
+   *
+   * @return {true} if the instance is not disabled.
+   * @return {false} if the instance is disabled.
+   */
+  BaseSelection.prototype.isEnabled = function () {
+    return !this.isDisabled();
+  };
+
+  /**
+   * Helper method to abstract the "disabled" state of this object.
+   *
+   * @return {true} if the disabled option is true.
+   * @return {false} if the disabled option is false.
+   */
+  BaseSelection.prototype.isDisabled = function () {
+    return this.options.get('disabled');
+  };
+
+  return BaseSelection;
+});
+
+S2.define('select2/selection/single',[
+  'jquery',
+  './base',
+  '../utils',
+  '../keys'
+], function ($, BaseSelection, Utils, KEYS) {
+  function SingleSelection () {
+    SingleSelection.__super__.constructor.apply(this, arguments);
+  }
+
+  Utils.Extend(SingleSelection, BaseSelection);
+
+  SingleSelection.prototype.render = function () {
+    var $selection = SingleSelection.__super__.render.call(this);
+
+    $selection.addClass('select2-selection--single');
+
+    $selection.html(
+      '<span class="select2-selection__rendered"></span>' +
+      '<span class="select2-selection__arrow" role="presentation">' +
+        '<b role="presentation"></b>' +
+      '</span>'
+    );
+
+    return $selection;
+  };
+
+  SingleSelection.prototype.bind = function (container, $container) {
+    var self = this;
+
+    SingleSelection.__super__.bind.apply(this, arguments);
+
+    var id = container.id + '-container';
+
+    this.$selection.find('.select2-selection__rendered')
+      .attr('id', id)
+      .attr('role', 'textbox')
+      .attr('aria-readonly', 'true');
+    this.$selection.attr('aria-labelledby', id);
+
+    this.$selection.on('mousedown', function (evt) {
+      // Only respond to left clicks
+      if (evt.which !== 1) {
+        return;
+      }
+
+      self.trigger('toggle', {
+        originalEvent: evt
+      });
+    });
+
+    this.$selection.on('focus', function (evt) {
+      // User focuses on the container
+    });
+
+    this.$selection.on('blur', function (evt) {
+      // User exits the container
+    });
+
+    container.on('focus', function (evt) {
+      if (!container.isOpen()) {
+        self.$selection.trigger('focus');
+      }
+    });
+  };
+
+  SingleSelection.prototype.clear = function () {
+    var $rendered = this.$selection.find('.select2-selection__rendered');
+    $rendered.empty();
+    $rendered.removeAttr('title'); // clear tooltip on empty
+  };
+
+  SingleSelection.prototype.display = function (data, container) {
+    var template = this.options.get('templateSelection');
+    var escapeMarkup = this.options.get('escapeMarkup');
+
+    return escapeMarkup(template(data, container));
+  };
+
+  SingleSelection.prototype.selectionContainer = function () {
+    return $('<span></span>');
+  };
+
+  SingleSelection.prototype.update = function (data) {
+    if (data.length === 0) {
+      this.clear();
+      return;
+    }
+
+    var selection = data[0];
+
+    var $rendered = this.$selection.find('.select2-selection__rendered');
+    var formatted = this.display(selection, $rendered);
+
+    $rendered.empty().append(formatted);
+
+    var title = selection.title || selection.text;
+
+    if (title) {
+      $rendered.attr('title', title);
+    } else {
+      $rendered.removeAttr('title');
+    }
+  };
+
+  return SingleSelection;
+});
+
+S2.define('select2/selection/multiple',[
+  'jquery',
+  './base',
+  '../utils'
+], function ($, BaseSelection, Utils) {
+  function MultipleSelection ($element, options) {
+    MultipleSelection.__super__.constructor.apply(this, arguments);
+  }
+
+  Utils.Extend(MultipleSelection, BaseSelection);
+
+  MultipleSelection.prototype.render = function () {
+    var $selection = MultipleSelection.__super__.render.call(this);
+
+    $selection.addClass('select2-selection--multiple');
+
+    $selection.html(
+      '<ul class="select2-selection__rendered"></ul>'
+    );
+
+    return $selection;
+  };
+
+  MultipleSelection.prototype.bind = function (container, $container) {
+    var self = this;
+
+    MultipleSelection.__super__.bind.apply(this, arguments);
+
+    this.$selection.on('click', function (evt) {
+      self.trigger('toggle', {
+        originalEvent: evt
+      });
+    });
+
+    this.$selection.on(
+      'click',
+      '.select2-selection__choice__remove',
+      function (evt) {
+        // Ignore the event if it is disabled
+        if (self.isDisabled()) {
+          return;
+        }
+
+        var $remove = $(this);
+        var $selection = $remove.parent();
+
+        var data = Utils.GetData($selection[0], 'data');
+
+        self.trigger('unselect', {
+          originalEvent: evt,
+          data: data
+        });
+      }
+    );
+  };
+
+  MultipleSelection.prototype.clear = function () {
+    var $rendered = this.$selection.find('.select2-selection__rendered');
+    $rendered.empty();
+    $rendered.removeAttr('title');
+  };
+
+  MultipleSelection.prototype.display = function (data, container) {
+    var template = this.options.get('templateSelection');
+    var escapeMarkup = this.options.get('escapeMarkup');
+
+    return escapeMarkup(template(data, container));
+  };
+
+  MultipleSelection.prototype.selectionContainer = function () {
+    var $container = $(
+      '<li class="select2-selection__choice">' +
+        '<span class="select2-selection__choice__remove" role="presentation">' +
+          '&times;' +
+        '</span>' +
+      '</li>'
+    );
+
+    return $container;
+  };
+
+  MultipleSelection.prototype.update = function (data) {
+    this.clear();
+
+    if (data.length === 0) {
+      return;
+    }
+
+    var $selections = [];
+
+    for (var d = 0; d < data.length; d++) {
+      var selection = data[d];
+
+      var $selection = this.selectionContainer();
+      var formatted = this.display(selection, $selection);
+
+      $selection.append(formatted);
+
+      var title = selection.title || selection.text;
+
+      if (title) {
+        $selection.attr('title', title);
+      }
+
+      Utils.StoreData($selection[0], 'data', selection);
+
+      $selections.push($selection);
+    }
+
+    var $rendered = this.$selection.find('.select2-selection__rendered');
+
+    Utils.appendMany($rendered, $selections);
+  };
+
+  return MultipleSelection;
+});
+
+S2.define('select2/selection/placeholder',[
+  '../utils'
+], function (Utils) {
+  function Placeholder (decorated, $element, options) {
+    this.placeholder = this.normalizePlaceholder(options.get('placeholder'));
+
+    decorated.call(this, $element, options);
+  }
+
+  Placeholder.prototype.normalizePlaceholder = function (_, placeholder) {
+    if (typeof placeholder === 'string') {
+      placeholder = {
+        id: '',
+        text: placeholder
+      };
+    }
+
+    return placeholder;
+  };
+
+  Placeholder.prototype.createPlaceholder = function (decorated, placeholder) {
+    var $placeholder = this.selectionContainer();
+
+    $placeholder.html(this.display(placeholder));
+    $placeholder.addClass('select2-selection__placeholder')
+                .removeClass('select2-selection__choice');
+
+    return $placeholder;
+  };
+
+  Placeholder.prototype.update = function (decorated, data) {
+    var singlePlaceholder = (
+      data.length == 1 && data[0].id != this.placeholder.id
+    );
+    var multipleSelections = data.length > 1;
+
+    if (multipleSelections || singlePlaceholder) {
+      return decorated.call(this, data);
+    }
+
+    this.clear();
+
+    var $placeholder = this.createPlaceholder(this.placeholder);
+
+    this.$selection.find('.select2-selection__rendered').append($placeholder);
+  };
+
+  return Placeholder;
+});
+
+S2.define('select2/selection/allowClear',[
+  'jquery',
+  '../keys',
+  '../utils'
+], function ($, KEYS, Utils) {
+  function AllowClear () { }
+
+  AllowClear.prototype.bind = function (decorated, container, $container) {
+    var self = this;
+
+    decorated.call(this, container, $container);
+
+    if (this.placeholder == null) {
+      if (this.options.get('debug') && window.console && console.error) {
+        console.error(
+          'Select2: The `allowClear` option should be used in combination ' +
+          'with the `placeholder` option.'
+        );
+      }
+    }
+
+    this.$selection.on('mousedown', '.select2-selection__clear',
+      function (evt) {
+        self._handleClear(evt);
+    });
+
+    container.on('keypress', function (evt) {
+      self._handleKeyboardClear(evt, container);
+    });
+  };
+
+  AllowClear.prototype._handleClear = function (_, evt) {
+    // Ignore the event if it is disabled
+    if (this.isDisabled()) {
+      return;
+    }
+
+    var $clear = this.$selection.find('.select2-selection__clear');
+
+    // Ignore the event if nothing has been selected
+    if ($clear.length === 0) {
+      return;
+    }
+
+    evt.stopPropagation();
+
+    var data = Utils.GetData($clear[0], 'data');
+
+    var previousVal = this.$element.val();
+    this.$element.val(this.placeholder.id);
+
+    var unselectData = {
+      data: data
+    };
+    this.trigger('clear', unselectData);
+    if (unselectData.prevented) {
+      this.$element.val(previousVal);
+      return;
+    }
+
+    for (var d = 0; d < data.length; d++) {
+      unselectData = {
+        data: data[d]
+      };
+
+      // Trigger the `unselect` event, so people can prevent it from being
+      // cleared.
+      this.trigger('unselect', unselectData);
+
+      // If the event was prevented, don't clear it out.
+      if (unselectData.prevented) {
+        this.$element.val(previousVal);
+        return;
+      }
+    }
+
+    this.$element.trigger('input').trigger('change');
+
+    this.trigger('toggle', {});
+  };
+
+  AllowClear.prototype._handleKeyboardClear = function (_, evt, container) {
+    if (container.isOpen()) {
+      return;
+    }
+
+    if (evt.which == KEYS.DELETE || evt.which == KEYS.BACKSPACE) {
+      this._handleClear(evt);
+    }
+  };
+
+  AllowClear.prototype.update = function (decorated, data) {
+    decorated.call(this, data);
+
+    if (this.$selection.find('.select2-selection__placeholder').length > 0 ||
+        data.length === 0) {
+      return;
+    }
+
+    var removeAll = this.options.get('translations').get('removeAllItems');
+
+    var $remove = $(
+      '<span class="select2-selection__clear" title="' + removeAll() +'">' +
+        '&times;' +
+      '</span>'
+    );
+    Utils.StoreData($remove[0], 'data', data);
+
+    this.$selection.find('.select2-selection__rendered').prepend($remove);
+  };
+
+  return AllowClear;
+});
+
+S2.define('select2/selection/search',[
+  'jquery',
+  '../utils',
+  '../keys'
+], function ($, Utils, KEYS) {
+  function Search (decorated, $element, options) {
+    decorated.call(this, $element, options);
+  }
+
+  Search.prototype.render = function (decorated) {
+    var $search = $(
+      '<li class="select2-search select2-search--inline">' +
+        '<input class="select2-search__field" type="search" tabindex="-1"' +
+        ' autocomplete="off" autocorrect="off" autocapitalize="none"' +
+        ' spellcheck="false" role="searchbox" aria-autocomplete="list" />' +
+      '</li>'
+    );
+
+    this.$searchContainer = $search;
+    this.$search = $search.find('input');
+
+    var $rendered = decorated.call(this);
+
+    this._transferTabIndex();
+
+    return $rendered;
+  };
+
+  Search.prototype.bind = function (decorated, container, $container) {
+    var self = this;
+
+    var resultsId = container.id + '-results';
+
+    decorated.call(this, container, $container);
+
+    container.on('open', function () {
+      self.$search.attr('aria-controls', resultsId);
+      self.$search.trigger('focus');
+    });
+
+    container.on('close', function () {
+      self.$search.val('');
+      self.$search.removeAttr('aria-controls');
+      self.$search.removeAttr('aria-activedescendant');
+      self.$search.trigger('focus');
+    });
+
+    container.on('enable', function () {
+      self.$search.prop('disabled', false);
+
+      self._transferTabIndex();
+    });
+
+    container.on('disable', function () {
+      self.$search.prop('disabled', true);
+    });
+
+    container.on('focus', function (evt) {
+      self.$search.trigger('focus');
+    });
+
+    container.on('results:focus', function (params) {
+      if (params.data._resultId) {
+        self.$search.attr('aria-activedescendant', params.data._resultId);
+      } else {
+        self.$search.removeAttr('aria-activedescendant');
+      }
+    });
+
+    this.$selection.on('focusin', '.select2-search--inline', function (evt) {
+      self.trigger('focus', evt);
+    });
+
+    this.$selection.on('focusout', '.select2-search--inline', function (evt) {
+      self._handleBlur(evt);
+    });
+
+    this.$selection.on('keydown', '.select2-search--inline', function (evt) {
+      evt.stopPropagation();
+
+      self.trigger('keypress', evt);
+
+      self._keyUpPrevented = evt.isDefaultPrevented();
+
+      var key = evt.which;
+
+      if (key === KEYS.BACKSPACE && self.$search.val() === '') {
+        var $previousChoice = self.$searchContainer
+          .prev('.select2-selection__choice');
+
+        if ($previousChoice.length > 0) {
+          var item = Utils.GetData($previousChoice[0], 'data');
+
+          self.searchRemoveChoice(item);
+
+          evt.preventDefault();
+        }
+      }
+    });
+
+    this.$selection.on('click', '.select2-search--inline', function (evt) {
+      if (self.$search.val()) {
+        evt.stopPropagation();
+      }
+    });
+
+    // Try to detect the IE version should the `documentMode` property that
+    // is stored on the document. This is only implemented in IE and is
+    // slightly cleaner than doing a user agent check.
+    // This property is not available in Edge, but Edge also doesn't have
+    // this bug.
+    var msie = document.documentMode;
+    var disableInputEvents = msie && msie <= 11;
+
+    // Workaround for browsers which do not support the `input` event
+    // This will prevent double-triggering of events for browsers which support
+    // both the `keyup` and `input` events.
+    this.$selection.on(
+      'input.searchcheck',
+      '.select2-search--inline',
+      function (evt) {
+        // IE will trigger the `input` event when a placeholder is used on a
+        // search box. To get around this issue, we are forced to ignore all
+        // `input` events in IE and keep using `keyup`.
+        if (disableInputEvents) {
+          self.$selection.off('input.search input.searchcheck');
+          return;
+        }
+
+        // Unbind the duplicated `keyup` event
+        self.$selection.off('keyup.search');
+      }
+    );
+
+    this.$selection.on(
+      'keyup.search input.search',
+      '.select2-search--inline',
+      function (evt) {
+        // IE will trigger the `input` event when a placeholder is used on a
+        // search box. To get around this issue, we are forced to ignore all
+        // `input` events in IE and keep using `keyup`.
+        if (disableInputEvents && evt.type === 'input') {
+          self.$selection.off('input.search input.searchcheck');
+          return;
+        }
+
+        var key = evt.which;
+
+        // We can freely ignore events from modifier keys
+        if (key == KEYS.SHIFT || key == KEYS.CTRL || key == KEYS.ALT) {
+          return;
+        }
+
+        // Tabbing will be handled during the `keydown` phase
+        if (key == KEYS.TAB) {
+          return;
+        }
+
+        self.handleSearch(evt);
+      }
+    );
+  };
+
+  /**
+   * This method will transfer the tabindex attribute from the rendered
+   * selection to the search box. This allows for the search box to be used as
+   * the primary focus instead of the selection container.
+   *
+   * @private
+   */
+  Search.prototype._transferTabIndex = function (decorated) {
+    this.$search.attr('tabindex', this.$selection.attr('tabindex'));
+    this.$selection.attr('tabindex', '-1');
+  };
+
+  Search.prototype.createPlaceholder = function (decorated, placeholder) {
+    this.$search.attr('placeholder', placeholder.text);
+  };
+
+  Search.prototype.update = function (decorated, data) {
+    var searchHadFocus = this.$search[0] == document.activeElement;
+
+    this.$search.attr('placeholder', '');
+
+    decorated.call(this, data);
+
+    this.$selection.find('.select2-selection__rendered')
+                   .append(this.$searchContainer);
+
+    this.resizeSearch();
+    if (searchHadFocus) {
+      this.$search.trigger('focus');
+    }
+  };
+
+  Search.prototype.handleSearch = function () {
+    this.resizeSearch();
+
+    if (!this._keyUpPrevented) {
+      var input = this.$search.val();
+
+      this.trigger('query', {
+        term: input
+      });
+    }
+
+    this._keyUpPrevented = false;
+  };
+
+  Search.prototype.searchRemoveChoice = function (decorated, item) {
+    this.trigger('unselect', {
+      data: item
+    });
+
+    this.$search.val(item.text);
+    this.handleSearch();
+  };
+
+  Search.prototype.resizeSearch = function () {
+    this.$search.css('width', '25px');
+
+    var width = '';
+
+    if (this.$search.attr('placeholder') !== '') {
+      width = this.$selection.find('.select2-selection__rendered').width();
+    } else {
+      var minimumWidth = this.$search.val().length + 1;
+
+      width = (minimumWidth * 0.75) + 'em';
+    }
+
+    this.$search.css('width', width);
+  };
+
+  return Search;
+});
+
+S2.define('select2/selection/eventRelay',[
+  'jquery'
+], function ($) {
+  function EventRelay () { }
+
+  EventRelay.prototype.bind = function (decorated, container, $container) {
+    var self = this;
+    var relayEvents = [
+      'open', 'opening',
+      'close', 'closing',
+      'select', 'selecting',
+      'unselect', 'unselecting',
+      'clear', 'clearing'
+    ];
+
+    var preventableEvents = [
+      'opening', 'closing', 'selecting', 'unselecting', 'clearing'
+    ];
+
+    decorated.call(this, container, $container);
+
+    container.on('*', function (name, params) {
+      // Ignore events that should not be relayed
+      if ($.inArray(name, relayEvents) === -1) {
+        return;
+      }
+
+      // The parameters should always be an object
+      params = params || {};
+
+      // Generate the jQuery event for the Select2 event
+      var evt = $.Event('select2:' + name, {
+        params: params
+      });
+
+      self.$element.trigger(evt);
+
+      // Only handle preventable events if it was one
+      if ($.inArray(name, preventableEvents) === -1) {
+        return;
+      }
+
+      params.prevented = evt.isDefaultPrevented();
+    });
+  };
+
+  return EventRelay;
+});
+
+S2.define('select2/translation',[
+  'jquery',
+  'require'
+], function ($, require) {
+  function Translation (dict) {
+    this.dict = dict || {};
+  }
+
+  Translation.prototype.all = function () {
+    return this.dict;
+  };
+
+  Translation.prototype.get = function (key) {
+    return this.dict[key];
+  };
+
+  Translation.prototype.extend = function (translation) {
+    this.dict = $.extend({}, translation.all(), this.dict);
+  };
+
+  // Static functions
+
+  Translation._cache = {};
+
+  Translation.loadPath = function (path) {
+    if (!(path in Translation._cache)) {
+      var translations = require(path);
+
+      Translation._cache[path] = translations;
+    }
+
+    return new Translation(Translation._cache[path]);
+  };
+
+  return Translation;
+});
+
+S2.define('select2/diacritics',[
+
+], function () {
+  var diacritics = {
+    '\u24B6': 'A',
+    '\uFF21': 'A',
+    '\u00C0': 'A',
+    '\u00C1': 'A',
+    '\u00C2': 'A',
+    '\u1EA6': 'A',
+    '\u1EA4': 'A',
+    '\u1EAA': 'A',
+    '\u1EA8': 'A',
+    '\u00C3': 'A',
+    '\u0100': 'A',
+    '\u0102': 'A',
+    '\u1EB0': 'A',
+    '\u1EAE': 'A',
+    '\u1EB4': 'A',
+    '\u1EB2': 'A',
+    '\u0226': 'A',
+    '\u01E0': 'A',
+    '\u00C4': 'A',
+    '\u01DE': 'A',
+    '\u1EA2': 'A',
+    '\u00C5': 'A',
+    '\u01FA': 'A',
+    '\u01CD': 'A',
+    '\u0200': 'A',
+    '\u0202': 'A',
+    '\u1EA0': 'A',
+    '\u1EAC': 'A',
+    '\u1EB6': 'A',
+    '\u1E00': 'A',
+    '\u0104': 'A',
+    '\u023A': 'A',
+    '\u2C6F': 'A',
+    '\uA732': 'AA',
+    '\u00C6': 'AE',
+    '\u01FC': 'AE',
+    '\u01E2': 'AE',
+    '\uA734': 'AO',
+    '\uA736': 'AU',
+    '\uA738': 'AV',
+    '\uA73A': 'AV',
+    '\uA73C': 'AY',
+    '\u24B7': 'B',
+    '\uFF22': 'B',
+    '\u1E02': 'B',
+    '\u1E04': 'B',
+    '\u1E06': 'B',
+    '\u0243': 'B',
+    '\u0182': 'B',
+    '\u0181': 'B',
+    '\u24B8': 'C',
+    '\uFF23': 'C',
+    '\u0106': 'C',
+    '\u0108': 'C',
+    '\u010A': 'C',
+    '\u010C': 'C',
+    '\u00C7': 'C',
+    '\u1E08': 'C',
+    '\u0187': 'C',
+    '\u023B': 'C',
+    '\uA73E': 'C',
+    '\u24B9': 'D',
+    '\uFF24': 'D',
+    '\u1E0A': 'D',
+    '\u010E': 'D',
+    '\u1E0C': 'D',
+    '\u1E10': 'D',
+    '\u1E12': 'D',
+    '\u1E0E': 'D',
+    '\u0110': 'D',
+    '\u018B': 'D',
+    '\u018A': 'D',
+    '\u0189': 'D',
+    '\uA779': 'D',
+    '\u01F1': 'DZ',
+    '\u01C4': 'DZ',
+    '\u01F2': 'Dz',
+    '\u01C5': 'Dz',
+    '\u24BA': 'E',
+    '\uFF25': 'E',
+    '\u00C8': 'E',
+    '\u00C9': 'E',
+    '\u00CA': 'E',
+    '\u1EC0': 'E',
+    '\u1EBE': 'E',
+    '\u1EC4': 'E',
+    '\u1EC2': 'E',
+    '\u1EBC': 'E',
+    '\u0112': 'E',
+    '\u1E14': 'E',
+    '\u1E16': 'E',
+    '\u0114': 'E',
+    '\u0116': 'E',
+    '\u00CB': 'E',
+    '\u1EBA': 'E',
+    '\u011A': 'E',
+    '\u0204': 'E',
+    '\u0206': 'E',
+    '\u1EB8': 'E',
+    '\u1EC6': 'E',
+    '\u0228': 'E',
+    '\u1E1C': 'E',
+    '\u0118': 'E',
+    '\u1E18': 'E',
+    '\u1E1A': 'E',
+    '\u0190': 'E',
+    '\u018E': 'E',
+    '\u24BB': 'F',
+    '\uFF26': 'F',
+    '\u1E1E': 'F',
+    '\u0191': 'F',
+    '\uA77B': 'F',
+    '\u24BC': 'G',
+    '\uFF27': 'G',
+    '\u01F4': 'G',
+    '\u011C': 'G',
+    '\u1E20': 'G',
+    '\u011E': 'G',
+    '\u0120': 'G',
+    '\u01E6': 'G',
+    '\u0122': 'G',
+    '\u01E4': 'G',
+    '\u0193': 'G',
+    '\uA7A0': 'G',
+    '\uA77D': 'G',
+    '\uA77E': 'G',
+    '\u24BD': 'H',
+    '\uFF28': 'H',
+    '\u0124': 'H',
+    '\u1E22': 'H',
+    '\u1E26': 'H',
+    '\u021E': 'H',
+    '\u1E24': 'H',
+    '\u1E28': 'H',
+    '\u1E2A': 'H',
+    '\u0126': 'H',
+    '\u2C67': 'H',
+    '\u2C75': 'H',
+    '\uA78D': 'H',
+    '\u24BE': 'I',
+    '\uFF29': 'I',
+    '\u00CC': 'I',
+    '\u00CD': 'I',
+    '\u00CE': 'I',
+    '\u0128': 'I',
+    '\u012A': 'I',
+    '\u012C': 'I',
+    '\u0130': 'I',
+    '\u00CF': 'I',
+    '\u1E2E': 'I',
+    '\u1EC8': 'I',
+    '\u01CF': 'I',
+    '\u0208': 'I',
+    '\u020A': 'I',
+    '\u1ECA': 'I',
+    '\u012E': 'I',
+    '\u1E2C': 'I',
+    '\u0197': 'I',
+    '\u24BF': 'J',
+    '\uFF2A': 'J',
+    '\u0134': 'J',
+    '\u0248': 'J',
+    '\u24C0': 'K',
+    '\uFF2B': 'K',
+    '\u1E30': 'K',
+    '\u01E8': 'K',
+    '\u1E32': 'K',
+    '\u0136': 'K',
+    '\u1E34': 'K',
+    '\u0198': 'K',
+    '\u2C69': 'K',
+    '\uA740': 'K',
+    '\uA742': 'K',
+    '\uA744': 'K',
+    '\uA7A2': 'K',
+    '\u24C1': 'L',
+    '\uFF2C': 'L',
+    '\u013F': 'L',
+    '\u0139': 'L',
+    '\u013D': 'L',
+    '\u1E36': 'L',
+    '\u1E38': 'L',
+    '\u013B': 'L',
+    '\u1E3C': 'L',
+    '\u1E3A': 'L',
+    '\u0141': 'L',
+    '\u023D': 'L',
+    '\u2C62': 'L',
+    '\u2C60': 'L',
+    '\uA748': 'L',
+    '\uA746': 'L',
+    '\uA780': 'L',
+    '\u01C7': 'LJ',
+    '\u01C8': 'Lj',
+    '\u24C2': 'M',
+    '\uFF2D': 'M',
+    '\u1E3E': 'M',
+    '\u1E40': 'M',
+    '\u1E42': 'M',
+    '\u2C6E': 'M',
+    '\u019C': 'M',
+    '\u24C3': 'N',
+    '\uFF2E': 'N',
+    '\u01F8': 'N',
+    '\u0143': 'N',
+    '\u00D1': 'N',
+    '\u1E44': 'N',
+    '\u0147': 'N',
+    '\u1E46': 'N',
+    '\u0145': 'N',
+    '\u1E4A': 'N',
+    '\u1E48': 'N',
+    '\u0220': 'N',
+    '\u019D': 'N',
+    '\uA790': 'N',
+    '\uA7A4': 'N',
+    '\u01CA': 'NJ',
+    '\u01CB': 'Nj',
+    '\u24C4': 'O',
+    '\uFF2F': 'O',
+    '\u00D2': 'O',
+    '\u00D3': 'O',
+    '\u00D4': 'O',
+    '\u1ED2': 'O',
+    '\u1ED0': 'O',
+    '\u1ED6': 'O',
+    '\u1ED4': 'O',
+    '\u00D5': 'O',
+    '\u1E4C': 'O',
+    '\u022C': 'O',
+    '\u1E4E': 'O',
+    '\u014C': 'O',
+    '\u1E50': 'O',
+    '\u1E52': 'O',
+    '\u014E': 'O',
+    '\u022E': 'O',
+    '\u0230': 'O',
+    '\u00D6': 'O',
+    '\u022A': 'O',
+    '\u1ECE': 'O',
+    '\u0150': 'O',
+    '\u01D1': 'O',
+    '\u020C': 'O',
+    '\u020E': 'O',
+    '\u01A0': 'O',
+    '\u1EDC': 'O',
+    '\u1EDA': 'O',
+    '\u1EE0': 'O',
+    '\u1EDE': 'O',
+    '\u1EE2': 'O',
+    '\u1ECC': 'O',
+    '\u1ED8': 'O',
+    '\u01EA': 'O',
+    '\u01EC': 'O',
+    '\u00D8': 'O',
+    '\u01FE': 'O',
+    '\u0186': 'O',
+    '\u019F': 'O',
+    '\uA74A': 'O',
+    '\uA74C': 'O',
+    '\u0152': 'OE',
+    '\u01A2': 'OI',
+    '\uA74E': 'OO',
+    '\u0222': 'OU',
+    '\u24C5': 'P',
+    '\uFF30': 'P',
+    '\u1E54': 'P',
+    '\u1E56': 'P',
+    '\u01A4': 'P',
+    '\u2C63': 'P',
+    '\uA750': 'P',
+    '\uA752': 'P',
+    '\uA754': 'P',
+    '\u24C6': 'Q',
+    '\uFF31': 'Q',
+    '\uA756': 'Q',
+    '\uA758': 'Q',
+    '\u024A': 'Q',
+    '\u24C7': 'R',
+    '\uFF32': 'R',
+    '\u0154': 'R',
+    '\u1E58': 'R',
+    '\u0158': 'R',
+    '\u0210': 'R',
+    '\u0212': 'R',
+    '\u1E5A': 'R',
+    '\u1E5C': 'R',
+    '\u0156': 'R',
+    '\u1E5E': 'R',
+    '\u024C': 'R',
+    '\u2C64': 'R',
+    '\uA75A': 'R',
+    '\uA7A6': 'R',
+    '\uA782': 'R',
+    '\u24C8': 'S',
+    '\uFF33': 'S',
+    '\u1E9E': 'S',
+    '\u015A': 'S',
+    '\u1E64': 'S',
+    '\u015C': 'S',
+    '\u1E60': 'S',
+    '\u0160': 'S',
+    '\u1E66': 'S',
+    '\u1E62': 'S',
+    '\u1E68': 'S',
+    '\u0218': 'S',
+    '\u015E': 'S',
+    '\u2C7E': 'S',
+    '\uA7A8': 'S',
+    '\uA784': 'S',
+    '\u24C9': 'T',
+    '\uFF34': 'T',
+    '\u1E6A': 'T',
+    '\u0164': 'T',
+    '\u1E6C': 'T',
+    '\u021A': 'T',
+    '\u0162': 'T',
+    '\u1E70': 'T',
+    '\u1E6E': 'T',
+    '\u0166': 'T',
+    '\u01AC': 'T',
+    '\u01AE': 'T',
+    '\u023E': 'T',
+    '\uA786': 'T',
+    '\uA728': 'TZ',
+    '\u24CA': 'U',
+    '\uFF35': 'U',
+    '\u00D9': 'U',
+    '\u00DA': 'U',
+    '\u00DB': 'U',
+    '\u0168': 'U',
+    '\u1E78': 'U',
+    '\u016A': 'U',
+    '\u1E7A': 'U',
+    '\u016C': 'U',
+    '\u00DC': 'U',
+    '\u01DB': 'U',
+    '\u01D7': 'U',
+    '\u01D5': 'U',
+    '\u01D9': 'U',
+    '\u1EE6': 'U',
+    '\u016E': 'U',
+    '\u0170': 'U',
+    '\u01D3': 'U',
+    '\u0214': 'U',
+    '\u0216': 'U',
+    '\u01AF': 'U',
+    '\u1EEA': 'U',
+    '\u1EE8': 'U',
+    '\u1EEE': 'U',
+    '\u1EEC': 'U',
+    '\u1EF0': 'U',
+    '\u1EE4': 'U',
+    '\u1E72': 'U',
+    '\u0172': 'U',
+    '\u1E76': 'U',
+    '\u1E74': 'U',
+    '\u0244': 'U',
+    '\u24CB': 'V',
+    '\uFF36': 'V',
+    '\u1E7C': 'V',
+    '\u1E7E': 'V',
+    '\u01B2': 'V',
+    '\uA75E': 'V',
+    '\u0245': 'V',
+    '\uA760': 'VY',
+    '\u24CC': 'W',
+    '\uFF37': 'W',
+    '\u1E80': 'W',
+    '\u1E82': 'W',
+    '\u0174': 'W',
+    '\u1E86': 'W',
+    '\u1E84': 'W',
+    '\u1E88': 'W',
+    '\u2C72': 'W',
+    '\u24CD': 'X',
+    '\uFF38': 'X',
+    '\u1E8A': 'X',
+    '\u1E8C': 'X',
+    '\u24CE': 'Y',
+    '\uFF39': 'Y',
+    '\u1EF2': 'Y',
+    '\u00DD': 'Y',
+    '\u0176': 'Y',
+    '\u1EF8': 'Y',
+    '\u0232': 'Y',
+    '\u1E8E': 'Y',
+    '\u0178': 'Y',
+    '\u1EF6': 'Y',
+    '\u1EF4': 'Y',
+    '\u01B3': 'Y',
+    '\u024E': 'Y',
+    '\u1EFE': 'Y',
+    '\u24CF': 'Z',
+    '\uFF3A': 'Z',
+    '\u0179': 'Z',
+    '\u1E90': 'Z',
+    '\u017B': 'Z',
+    '\u017D': 'Z',
+    '\u1E92': 'Z',
+    '\u1E94': 'Z',
+    '\u01B5': 'Z',
+    '\u0224': 'Z',
+    '\u2C7F': 'Z',
+    '\u2C6B': 'Z',
+    '\uA762': 'Z',
+    '\u24D0': 'a',
+    '\uFF41': 'a',
+    '\u1E9A': 'a',
+    '\u00E0': 'a',
+    '\u00E1': 'a',
+    '\u00E2': 'a',
+    '\u1EA7': 'a',
+    '\u1EA5': 'a',
+    '\u1EAB': 'a',
+    '\u1EA9': 'a',
+    '\u00E3': 'a',
+    '\u0101': 'a',
+    '\u0103': 'a',
+    '\u1EB1': 'a',
+    '\u1EAF': 'a',
+    '\u1EB5': 'a',
+    '\u1EB3': 'a',
+    '\u0227': 'a',
+    '\u01E1': 'a',
+    '\u00E4': 'a',
+    '\u01DF': 'a',
+    '\u1EA3': 'a',
+    '\u00E5': 'a',
+    '\u01FB': 'a',
+    '\u01CE': 'a',
+    '\u0201': 'a',
+    '\u0203': 'a',
+    '\u1EA1': 'a',
+    '\u1EAD': 'a',
+    '\u1EB7': 'a',
+    '\u1E01': 'a',
+    '\u0105': 'a',
+    '\u2C65': 'a',
+    '\u0250': 'a',
+    '\uA733': 'aa',
+    '\u00E6': 'ae',
+    '\u01FD': 'ae',
+    '\u01E3': 'ae',
+    '\uA735': 'ao',
+    '\uA737': 'au',
+    '\uA739': 'av',
+    '\uA73B': 'av',
+    '\uA73D': 'ay',
+    '\u24D1': 'b',
+    '\uFF42': 'b',
+    '\u1E03': 'b',
+    '\u1E05': 'b',
+    '\u1E07': 'b',
+    '\u0180': 'b',
+    '\u0183': 'b',
+    '\u0253': 'b',
+    '\u24D2': 'c',
+    '\uFF43': 'c',
+    '\u0107': 'c',
+    '\u0109': 'c',
+    '\u010B': 'c',
+    '\u010D': 'c',
+    '\u00E7': 'c',
+    '\u1E09': 'c',
+    '\u0188': 'c',
+    '\u023C': 'c',
+    '\uA73F': 'c',
+    '\u2184': 'c',
+    '\u24D3': 'd',
+    '\uFF44': 'd',
+    '\u1E0B': 'd',
+    '\u010F': 'd',
+    '\u1E0D': 'd',
+    '\u1E11': 'd',
+    '\u1E13': 'd',
+    '\u1E0F': 'd',
+    '\u0111': 'd',
+    '\u018C': 'd',
+    '\u0256': 'd',
+    '\u0257': 'd',
+    '\uA77A': 'd',
+    '\u01F3': 'dz',
+    '\u01C6': 'dz',
+    '\u24D4': 'e',
+    '\uFF45': 'e',
+    '\u00E8': 'e',
+    '\u00E9': 'e',
+    '\u00EA': 'e',
+    '\u1EC1': 'e',
+    '\u1EBF': 'e',
+    '\u1EC5': 'e',
+    '\u1EC3': 'e',
+    '\u1EBD': 'e',
+    '\u0113': 'e',
+    '\u1E15': 'e',
+    '\u1E17': 'e',
+    '\u0115': 'e',
+    '\u0117': 'e',
+    '\u00EB': 'e',
+    '\u1EBB': 'e',
+    '\u011B': 'e',
+    '\u0205': 'e',
+    '\u0207': 'e',
+    '\u1EB9': 'e',
+    '\u1EC7': 'e',
+    '\u0229': 'e',
+    '\u1E1D': 'e',
+    '\u0119': 'e',
+    '\u1E19': 'e',
+    '\u1E1B': 'e',
+    '\u0247': 'e',
+    '\u025B': 'e',
+    '\u01DD': 'e',
+    '\u24D5': 'f',
+    '\uFF46': 'f',
+    '\u1E1F': 'f',
+    '\u0192': 'f',
+    '\uA77C': 'f',
+    '\u24D6': 'g',
+    '\uFF47': 'g',
+    '\u01F5': 'g',
+    '\u011D': 'g',
+    '\u1E21': 'g',
+    '\u011F': 'g',
+    '\u0121': 'g',
+    '\u01E7': 'g',
+    '\u0123': 'g',
+    '\u01E5': 'g',
+    '\u0260': 'g',
+    '\uA7A1': 'g',
+    '\u1D79': 'g',
+    '\uA77F': 'g',
+    '\u24D7': 'h',
+    '\uFF48': 'h',
+    '\u0125': 'h',
+    '\u1E23': 'h',
+    '\u1E27': 'h',
+    '\u021F': 'h',
+    '\u1E25': 'h',
+    '\u1E29': 'h',
+    '\u1E2B': 'h',
+    '\u1E96': 'h',
+    '\u0127': 'h',
+    '\u2C68': 'h',
+    '\u2C76': 'h',
+    '\u0265': 'h',
+    '\u0195': 'hv',
+    '\u24D8': 'i',
+    '\uFF49': 'i',
+    '\u00EC': 'i',
+    '\u00ED': 'i',
+    '\u00EE': 'i',
+    '\u0129': 'i',
+    '\u012B': 'i',
+    '\u012D': 'i',
+    '\u00EF': 'i',
+    '\u1E2F': 'i',
+    '\u1EC9': 'i',
+    '\u01D0': 'i',
+    '\u0209': 'i',
+    '\u020B': 'i',
+    '\u1ECB': 'i',
+    '\u012F': 'i',
+    '\u1E2D': 'i',
+    '\u0268': 'i',
+    '\u0131': 'i',
+    '\u24D9': 'j',
+    '\uFF4A': 'j',
+    '\u0135': 'j',
+    '\u01F0': 'j',
+    '\u0249': 'j',
+    '\u24DA': 'k',
+    '\uFF4B': 'k',
+    '\u1E31': 'k',
+    '\u01E9': 'k',
+    '\u1E33': 'k',
+    '\u0137': 'k',
+    '\u1E35': 'k',
+    '\u0199': 'k',
+    '\u2C6A': 'k',
+    '\uA741': 'k',
+    '\uA743': 'k',
+    '\uA745': 'k',
+    '\uA7A3': 'k',
+    '\u24DB': 'l',
+    '\uFF4C': 'l',
+    '\u0140': 'l',
+    '\u013A': 'l',
+    '\u013E': 'l',
+    '\u1E37': 'l',
+    '\u1E39': 'l',
+    '\u013C': 'l',
+    '\u1E3D': 'l',
+    '\u1E3B': 'l',
+    '\u017F': 'l',
+    '\u0142': 'l',
+    '\u019A': 'l',
+    '\u026B': 'l',
+    '\u2C61': 'l',
+    '\uA749': 'l',
+    '\uA781': 'l',
+    '\uA747': 'l',
+    '\u01C9': 'lj',
+    '\u24DC': 'm',
+    '\uFF4D': 'm',
+    '\u1E3F': 'm',
+    '\u1E41': 'm',
+    '\u1E43': 'm',
+    '\u0271': 'm',
+    '\u026F': 'm',
+    '\u24DD': 'n',
+    '\uFF4E': 'n',
+    '\u01F9': 'n',
+    '\u0144': 'n',
+    '\u00F1': 'n',
+    '\u1E45': 'n',
+    '\u0148': 'n',
+    '\u1E47': 'n',
+    '\u0146': 'n',
+    '\u1E4B': 'n',
+    '\u1E49': 'n',
+    '\u019E': 'n',
+    '\u0272': 'n',
+    '\u0149': 'n',
+    '\uA791': 'n',
+    '\uA7A5': 'n',
+    '\u01CC': 'nj',
+    '\u24DE': 'o',
+    '\uFF4F': 'o',
+    '\u00F2': 'o',
+    '\u00F3': 'o',
+    '\u00F4': 'o',
+    '\u1ED3': 'o',
+    '\u1ED1': 'o',
+    '\u1ED7': 'o',
+    '\u1ED5': 'o',
+    '\u00F5': 'o',
+    '\u1E4D': 'o',
+    '\u022D': 'o',
+    '\u1E4F': 'o',
+    '\u014D': 'o',
+    '\u1E51': 'o',
+    '\u1E53': 'o',
+    '\u014F': 'o',
+    '\u022F': 'o',
+    '\u0231': 'o',
+    '\u00F6': 'o',
+    '\u022B': 'o',
+    '\u1ECF': 'o',
+    '\u0151': 'o',
+    '\u01D2': 'o',
+    '\u020D': 'o',
+    '\u020F': 'o',
+    '\u01A1': 'o',
+    '\u1EDD': 'o',
+    '\u1EDB': 'o',
+    '\u1EE1': 'o',
+    '\u1EDF': 'o',
+    '\u1EE3': 'o',
+    '\u1ECD': 'o',
+    '\u1ED9': 'o',
+    '\u01EB': 'o',
+    '\u01ED': 'o',
+    '\u00F8': 'o',
+    '\u01FF': 'o',
+    '\u0254': 'o',
+    '\uA74B': 'o',
+    '\uA74D': 'o',
+    '\u0275': 'o',
+    '\u0153': 'oe',
+    '\u01A3': 'oi',
+    '\u0223': 'ou',
+    '\uA74F': 'oo',
+    '\u24DF': 'p',
+    '\uFF50': 'p',
+    '\u1E55': 'p',
+    '\u1E57': 'p',
+    '\u01A5': 'p',
+    '\u1D7D': 'p',
+    '\uA751': 'p',
+    '\uA753': 'p',
+    '\uA755': 'p',
+    '\u24E0': 'q',
+    '\uFF51': 'q',
+    '\u024B': 'q',
+    '\uA757': 'q',
+    '\uA759': 'q',
+    '\u24E1': 'r',
+    '\uFF52': 'r',
+    '\u0155': 'r',
+    '\u1E59': 'r',
+    '\u0159': 'r',
+    '\u0211': 'r',
+    '\u0213': 'r',
+    '\u1E5B': 'r',
+    '\u1E5D': 'r',
+    '\u0157': 'r',
+    '\u1E5F': 'r',
+    '\u024D': 'r',
+    '\u027D': 'r',
+    '\uA75B': 'r',
+    '\uA7A7': 'r',
+    '\uA783': 'r',
+    '\u24E2': 's',
+    '\uFF53': 's',
+    '\u00DF': 's',
+    '\u015B': 's',
+    '\u1E65': 's',
+    '\u015D': 's',
+    '\u1E61': 's',
+    '\u0161': 's',
+    '\u1E67': 's',
+    '\u1E63': 's',
+    '\u1E69': 's',
+    '\u0219': 's',
+    '\u015F': 's',
+    '\u023F': 's',
+    '\uA7A9': 's',
+    '\uA785': 's',
+    '\u1E9B': 's',
+    '\u24E3': 't',
+    '\uFF54': 't',
+    '\u1E6B': 't',
+    '\u1E97': 't',
+    '\u0165': 't',
+    '\u1E6D': 't',
+    '\u021B': 't',
+    '\u0163': 't',
+    '\u1E71': 't',
+    '\u1E6F': 't',
+    '\u0167': 't',
+    '\u01AD': 't',
+    '\u0288': 't',
+    '\u2C66': 't',
+    '\uA787': 't',
+    '\uA729': 'tz',
+    '\u24E4': 'u',
+    '\uFF55': 'u',
+    '\u00F9': 'u',
+    '\u00FA': 'u',
+    '\u00FB': 'u',
+    '\u0169': 'u',
+    '\u1E79': 'u',
+    '\u016B': 'u',
+    '\u1E7B': 'u',
+    '\u016D': 'u',
+    '\u00FC': 'u',
+    '\u01DC': 'u',
+    '\u01D8': 'u',
+    '\u01D6': 'u',
+    '\u01DA': 'u',
+    '\u1EE7': 'u',
+    '\u016F': 'u',
+    '\u0171': 'u',
+    '\u01D4': 'u',
+    '\u0215': 'u',
+    '\u0217': 'u',
+    '\u01B0': 'u',
+    '\u1EEB': 'u',
+    '\u1EE9': 'u',
+    '\u1EEF': 'u',
+    '\u1EED': 'u',
+    '\u1EF1': 'u',
+    '\u1EE5': 'u',
+    '\u1E73': 'u',
+    '\u0173': 'u',
+    '\u1E77': 'u',
+    '\u1E75': 'u',
+    '\u0289': 'u',
+    '\u24E5': 'v',
+    '\uFF56': 'v',
+    '\u1E7D': 'v',
+    '\u1E7F': 'v',
+    '\u028B': 'v',
+    '\uA75F': 'v',
+    '\u028C': 'v',
+    '\uA761': 'vy',
+    '\u24E6': 'w',
+    '\uFF57': 'w',
+    '\u1E81': 'w',
+    '\u1E83': 'w',
+    '\u0175': 'w',
+    '\u1E87': 'w',
+    '\u1E85': 'w',
+    '\u1E98': 'w',
+    '\u1E89': 'w',
+    '\u2C73': 'w',
+    '\u24E7': 'x',
+    '\uFF58': 'x',
+    '\u1E8B': 'x',
+    '\u1E8D': 'x',
+    '\u24E8': 'y',
+    '\uFF59': 'y',
+    '\u1EF3': 'y',
+    '\u00FD': 'y',
+    '\u0177': 'y',
+    '\u1EF9': 'y',
+    '\u0233': 'y',
+    '\u1E8F': 'y',
+    '\u00FF': 'y',
+    '\u1EF7': 'y',
+    '\u1E99': 'y',
+    '\u1EF5': 'y',
+    '\u01B4': 'y',
+    '\u024F': 'y',
+    '\u1EFF': 'y',
+    '\u24E9': 'z',
+    '\uFF5A': 'z',
+    '\u017A': 'z',
+    '\u1E91': 'z',
+    '\u017C': 'z',
+    '\u017E': 'z',
+    '\u1E93': 'z',
+    '\u1E95': 'z',
+    '\u01B6': 'z',
+    '\u0225': 'z',
+    '\u0240': 'z',
+    '\u2C6C': 'z',
+    '\uA763': 'z',
+    '\u0386': '\u0391',
+    '\u0388': '\u0395',
+    '\u0389': '\u0397',
+    '\u038A': '\u0399',
+    '\u03AA': '\u0399',
+    '\u038C': '\u039F',
+    '\u038E': '\u03A5',
+    '\u03AB': '\u03A5',
+    '\u038F': '\u03A9',
+    '\u03AC': '\u03B1',
+    '\u03AD': '\u03B5',
+    '\u03AE': '\u03B7',
+    '\u03AF': '\u03B9',
+    '\u03CA': '\u03B9',
+    '\u0390': '\u03B9',
+    '\u03CC': '\u03BF',
+    '\u03CD': '\u03C5',
+    '\u03CB': '\u03C5',
+    '\u03B0': '\u03C5',
+    '\u03CE': '\u03C9',
+    '\u03C2': '\u03C3',
+    '\u2019': '\''
+  };
+
+  return diacritics;
+});
+
+S2.define('select2/data/base',[
+  '../utils'
+], function (Utils) {
+  function BaseAdapter ($element, options) {
+    BaseAdapter.__super__.constructor.call(this);
+  }
+
+  Utils.Extend(BaseAdapter, Utils.Observable);
+
+  BaseAdapter.prototype.current = function (callback) {
+    throw new Error('The `current` method must be defined in child classes.');
+  };
+
+  BaseAdapter.prototype.query = function (params, callback) {
+    throw new Error('The `query` method must be defined in child classes.');
+  };
+
+  BaseAdapter.prototype.bind = function (container, $container) {
+    // Can be implemented in subclasses
+  };
+
+  BaseAdapter.prototype.destroy = function () {
+    // Can be implemented in subclasses
+  };
+
+  BaseAdapter.prototype.generateResultId = function (container, data) {
+    var id = container.id + '-result-';
+
+    id += Utils.generateChars(4);
+
+    if (data.id != null) {
+      id += '-' + data.id.toString();
+    } else {
+      id += '-' + Utils.generateChars(4);
+    }
+    return id;
+  };
+
+  return BaseAdapter;
+});
+
+S2.define('select2/data/select',[
+  './base',
+  '../utils',
+  'jquery'
+], function (BaseAdapter, Utils, $) {
+  function SelectAdapter ($element, options) {
+    this.$element = $element;
+    this.options = options;
+
+    SelectAdapter.__super__.constructor.call(this);
+  }
+
+  Utils.Extend(SelectAdapter, BaseAdapter);
+
+  SelectAdapter.prototype.current = function (callback) {
+    var data = [];
+    var self = this;
+
+    this.$element.find(':selected').each(function () {
+      var $option = $(this);
+
+      var option = self.item($option);
+
+      data.push(option);
+    });
+
+    callback(data);
+  };
+
+  SelectAdapter.prototype.select = function (data) {
+    var self = this;
+
+    data.selected = true;
+
+    // If data.element is a DOM node, use it instead
+    if ($(data.element).is('option')) {
+      data.element.selected = true;
+
+      this.$element.trigger('input').trigger('change');
+
+      return;
+    }
+
+    if (this.$element.prop('multiple')) {
+      this.current(function (currentData) {
+        var val = [];
+
+        data = [data];
+        data.push.apply(data, currentData);
+
+        for (var d = 0; d < data.length; d++) {
+          var id = data[d].id;
+
+          if ($.inArray(id, val) === -1) {
+            val.push(id);
+          }
+        }
+
+        self.$element.val(val);
+        self.$element.trigger('input').trigger('change');
+      });
+    } else {
+      var val = data.id;
+
+      this.$element.val(val);
+      this.$element.trigger('input').trigger('change');
+    }
+  };
+
+  SelectAdapter.prototype.unselect = function (data) {
+    var self = this;
+
+    if (!this.$element.prop('multiple')) {
+      return;
+    }
+
+    data.selected = false;
+
+    if ($(data.element).is('option')) {
+      data.element.selected = false;
+
+      this.$element.trigger('input').trigger('change');
+
+      return;
+    }
+
+    this.current(function (currentData) {
+      var val = [];
+
+      for (var d = 0; d < currentData.length; d++) {
+        var id = currentData[d].id;
+
+        if (id !== data.id && $.inArray(id, val) === -1) {
+          val.push(id);
+        }
+      }
+
+      self.$element.val(val);
+
+      self.$element.trigger('input').trigger('change');
+    });
+  };
+
+  SelectAdapter.prototype.bind = function (container, $container) {
+    var self = this;
+
+    this.container = container;
+
+    container.on('select', function (params) {
+      self.select(params.data);
+    });
+
+    container.on('unselect', function (params) {
+      self.unselect(params.data);
+    });
+  };
+
+  SelectAdapter.prototype.destroy = function () {
+    // Remove anything added to child elements
+    this.$element.find('*').each(function () {
+      // Remove any custom data set by Select2
+      Utils.RemoveData(this);
+    });
+  };
+
+  SelectAdapter.prototype.query = function (params, callback) {
+    var data = [];
+    var self = this;
+
+    var $options = this.$element.children();
+
+    $options.each(function () {
+      var $option = $(this);
+
+      if (!$option.is('option') && !$option.is('optgroup')) {
+        return;
+      }
+
+      var option = self.item($option);
+
+      var matches = self.matches(params, option);
+
+      if (matches !== null) {
+        data.push(matches);
+      }
+    });
+
+    callback({
+      results: data
+    });
+  };
+
+  SelectAdapter.prototype.addOptions = function ($options) {
+    Utils.appendMany(this.$element, $options);
+  };
+
+  SelectAdapter.prototype.option = function (data) {
+    var option;
+
+    if (data.children) {
+      option = document.createElement('optgroup');
+      option.label = data.text;
+    } else {
+      option = document.createElement('option');
+
+      if (option.textContent !== undefined) {
+        option.textContent = data.text;
+      } else {
+        option.innerText = data.text;
+      }
+    }
+
+    if (data.id !== undefined) {
+      option.value = data.id;
+    }
+
+    if (data.disabled) {
+      option.disabled = true;
+    }
+
+    if (data.selected) {
+      option.selected = true;
+    }
+
+    if (data.title) {
+      option.title = data.title;
+    }
+
+    var $option = $(option);
+
+    var normalizedData = this._normalizeItem(data);
+    normalizedData.element = option;
+
+    // Override the option's data with the combined data
+    Utils.StoreData(option, 'data', normalizedData);
+
+    return $option;
+  };
+
+  SelectAdapter.prototype.item = function ($option) {
+    var data = {};
+
+    data = Utils.GetData($option[0], 'data');
+
+    if (data != null) {
+      return data;
+    }
+
+    if ($option.is('option')) {
+      data = {
+        id: $option.val(),
+        text: $option.text(),
+        disabled: $option.prop('disabled'),
+        selected: $option.prop('selected'),
+        title: $option.prop('title')
+      };
+    } else if ($option.is('optgroup')) {
+      data = {
+        text: $option.prop('label'),
+        children: [],
+        title: $option.prop('title')
+      };
+
+      var $children = $option.children('option');
+      var children = [];
+
+      for (var c = 0; c < $children.length; c++) {
+        var $child = $($children[c]);
+
+        var child = this.item($child);
+
+        children.push(child);
+      }
+
+      data.children = children;
+    }
+
+    data = this._normalizeItem(data);
+    data.element = $option[0];
+
+    Utils.StoreData($option[0], 'data', data);
+
+    return data;
+  };
+
+  SelectAdapter.prototype._normalizeItem = function (item) {
+    if (item !== Object(item)) {
+      item = {
+        id: item,
+        text: item
+      };
+    }
+
+    item = $.extend({}, {
+      text: ''
+    }, item);
+
+    var defaults = {
+      selected: false,
+      disabled: false
+    };
+
+    if (item.id != null) {
+      item.id = item.id.toString();
+    }
+
+    if (item.text != null) {
+      item.text = item.text.toString();
+    }
+
+    if (item._resultId == null && item.id && this.container != null) {
+      item._resultId = this.generateResultId(this.container, item);
+    }
+
+    return $.extend({}, defaults, item);
+  };
+
+  SelectAdapter.prototype.matches = function (params, data) {
+    var matcher = this.options.get('matcher');
+
+    return matcher(params, data);
+  };
+
+  return SelectAdapter;
+});
+
+S2.define('select2/data/array',[
+  './select',
+  '../utils',
+  'jquery'
+], function (SelectAdapter, Utils, $) {
+  function ArrayAdapter ($element, options) {
+    this._dataToConvert = options.get('data') || [];
+
+    ArrayAdapter.__super__.constructor.call(this, $element, options);
+  }
+
+  Utils.Extend(ArrayAdapter, SelectAdapter);
+
+  ArrayAdapter.prototype.bind = function (container, $container) {
+    ArrayAdapter.__super__.bind.call(this, container, $container);
+
+    this.addOptions(this.convertToOptions(this._dataToConvert));
+  };
+
+  ArrayAdapter.prototype.select = function (data) {
+    var $option = this.$element.find('option').filter(function (i, elm) {
+      return elm.value == data.id.toString();
+    });
+
+    if ($option.length === 0) {
+      $option = this.option(data);
+
+      this.addOptions($option);
+    }
+
+    ArrayAdapter.__super__.select.call(this, data);
+  };
+
+  ArrayAdapter.prototype.convertToOptions = function (data) {
+    var self = this;
+
+    var $existing = this.$element.find('option');
+    var existingIds = $existing.map(function () {
+      return self.item($(this)).id;
+    }).get();
+
+    var $options = [];
+
+    // Filter out all items except for the one passed in the argument
+    function onlyItem (item) {
+      return function () {
+        return $(this).val() == item.id;
+      };
+    }
+
+    for (var d = 0; d < data.length; d++) {
+      var item = this._normalizeItem(data[d]);
+
+      // Skip items which were pre-loaded, only merge the data
+      if ($.inArray(item.id, existingIds) >= 0) {
+        var $existingOption = $existing.filter(onlyItem(item));
+
+        var existingData = this.item($existingOption);
+        var newData = $.extend(true, {}, item, existingData);
+
+        var $newOption = this.option(newData);
+
+        $existingOption.replaceWith($newOption);
+
+        continue;
+      }
+
+      var $option = this.option(item);
+
+      if (item.children) {
+        var $children = this.convertToOptions(item.children);
+
+        Utils.appendMany($option, $children);
+      }
+
+      $options.push($option);
+    }
+
+    return $options;
+  };
+
+  return ArrayAdapter;
+});
+
+S2.define('select2/data/ajax',[
+  './array',
+  '../utils',
+  'jquery'
+], function (ArrayAdapter, Utils, $) {
+  function AjaxAdapter ($element, options) {
+    this.ajaxOptions = this._applyDefaults(options.get('ajax'));
+
+    if (this.ajaxOptions.processResults != null) {
+      this.processResults = this.ajaxOptions.processResults;
+    }
+
+    AjaxAdapter.__super__.constructor.call(this, $element, options);
+  }
+
+  Utils.Extend(AjaxAdapter, ArrayAdapter);
+
+  AjaxAdapter.prototype._applyDefaults = function (options) {
+    var defaults = {
+      data: function (params) {
+        return $.extend({}, params, {
+          q: params.term
+        });
+      },
+      transport: function (params, success, failure) {
+        var $request = $.ajax(params);
+
+        $request.then(success);
+        $request.fail(failure);
+
+        return $request;
+      }
+    };
+
+    return $.extend({}, defaults, options, true);
+  };
+
+  AjaxAdapter.prototype.processResults = function (results) {
+    return results;
+  };
+
+  AjaxAdapter.prototype.query = function (params, callback) {
+    var matches = [];
+    var self = this;
+
+    if (this._request != null) {
+      // JSONP requests cannot always be aborted
+      if ($.isFunction(this._request.abort)) {
+        this._request.abort();
+      }
+
+      this._request = null;
+    }
+
+    var options = $.extend({
+      type: 'GET'
+    }, this.ajaxOptions);
+
+    if (typeof options.url === 'function') {
+      options.url = options.url.call(this.$element, params);
+    }
+
+    if (typeof options.data === 'function') {
+      options.data = options.data.call(this.$element, params);
+    }
+
+    function request () {
+      var $request = options.transport(options, function (data) {
+        var results = self.processResults(data, params);
+
+        if (self.options.get('debug') && window.console && console.error) {
+          // Check to make sure that the response included a `results` key.
+          if (!results || !results.results || !$.isArray(results.results)) {
+            console.error(
+              'Select2: The AJAX results did not return an array in the ' +
+              '`results` key of the response.'
+            );
+          }
+        }
+
+        callback(results);
+      }, function () {
+        // Attempt to detect if a request was aborted
+        // Only works if the transport exposes a status property
+        if ('status' in $request &&
+            ($request.status === 0 || $request.status === '0')) {
+          return;
+        }
+
+        self.trigger('results:message', {
+          message: 'errorLoading'
+        });
+      });
+
+      self._request = $request;
+    }
+
+    if (this.ajaxOptions.delay && params.term != null) {
+      if (this._queryTimeout) {
+        window.clearTimeout(this._queryTimeout);
+      }
+
+      this._queryTimeout = window.setTimeout(request, this.ajaxOptions.delay);
+    } else {
+      request();
+    }
+  };
+
+  return AjaxAdapter;
+});
+
+S2.define('select2/data/tags',[
+  'jquery'
+], function ($) {
+  function Tags (decorated, $element, options) {
+    var tags = options.get('tags');
+
+    var createTag = options.get('createTag');
+
+    if (createTag !== undefined) {
+      this.createTag = createTag;
+    }
+
+    var insertTag = options.get('insertTag');
+
+    if (insertTag !== undefined) {
+        this.insertTag = insertTag;
+    }
+
+    decorated.call(this, $element, options);
+
+    if ($.isArray(tags)) {
+      for (var t = 0; t < tags.length; t++) {
+        var tag = tags[t];
+        var item = this._normalizeItem(tag);
+
+        var $option = this.option(item);
+
+        this.$element.append($option);
+      }
+    }
+  }
+
+  Tags.prototype.query = function (decorated, params, callback) {
+    var self = this;
+
+    this._removeOldTags();
+
+    if (params.term == null || params.page != null) {
+      decorated.call(this, params, callback);
+      return;
+    }
+
+    function wrapper (obj, child) {
+      var data = obj.results;
+
+      for (var i = 0; i < data.length; i++) {
+        var option = data[i];
+
+        var checkChildren = (
+          option.children != null &&
+          !wrapper({
+            results: option.children
+          }, true)
+        );
+
+        var optionText = (option.text || '').toUpperCase();
+        var paramsTerm = (params.term || '').toUpperCase();
+
+        var checkText = optionText === paramsTerm;
+
+        if (checkText || checkChildren) {
+          if (child) {
+            return false;
+          }
+
+          obj.data = data;
+          callback(obj);
+
+          return;
+        }
+      }
+
+      if (child) {
+        return true;
+      }
+
+      var tag = self.createTag(params);
+
+      if (tag != null) {
+        var $option = self.option(tag);
+        $option.attr('data-select2-tag', true);
+
+        self.addOptions([$option]);
+
+        self.insertTag(data, tag);
+      }
+
+      obj.results = data;
+
+      callback(obj);
+    }
+
+    decorated.call(this, params, wrapper);
+  };
+
+  Tags.prototype.createTag = function (decorated, params) {
+    var term = $.trim(params.term);
+
+    if (term === '') {
+      return null;
+    }
+
+    return {
+      id: term,
+      text: term
+    };
+  };
+
+  Tags.prototype.insertTag = function (_, data, tag) {
+    data.unshift(tag);
+  };
+
+  Tags.prototype._removeOldTags = function (_) {
+    var $options = this.$element.find('option[data-select2-tag]');
+
+    $options.each(function () {
+      if (this.selected) {
+        return;
+      }
+
+      $(this).remove();
+    });
+  };
+
+  return Tags;
+});
+
+S2.define('select2/data/tokenizer',[
+  'jquery'
+], function ($) {
+  function Tokenizer (decorated, $element, options) {
+    var tokenizer = options.get('tokenizer');
+
+    if (tokenizer !== undefined) {
+      this.tokenizer = tokenizer;
+    }
+
+    decorated.call(this, $element, options);
+  }
+
+  Tokenizer.prototype.bind = function (decorated, container, $container) {
+    decorated.call(this, container, $container);
+
+    this.$search =  container.dropdown.$search || container.selection.$search ||
+      $container.find('.select2-search__field');
+  };
+
+  Tokenizer.prototype.query = function (decorated, params, callback) {
+    var self = this;
+
+    function createAndSelect (data) {
+      // Normalize the data object so we can use it for checks
+      var item = self._normalizeItem(data);
+
+      // Check if the data object already exists as a tag
+      // Select it if it doesn't
+      var $existingOptions = self.$element.find('option').filter(function () {
+        return $(this).val() === item.id;
+      });
+
+      // If an existing option wasn't found for it, create the option
+      if (!$existingOptions.length) {
+        var $option = self.option(item);
+        $option.attr('data-select2-tag', true);
+
+        self._removeOldTags();
+        self.addOptions([$option]);
+      }
+
+      // Select the item, now that we know there is an option for it
+      select(item);
+    }
+
+    function select (data) {
+      self.trigger('select', {
+        data: data
+      });
+    }
+
+    params.term = params.term || '';
+
+    var tokenData = this.tokenizer(params, this.options, createAndSelect);
+
+    if (tokenData.term !== params.term) {
+      // Replace the search term if we have the search box
+      if (this.$search.length) {
+        this.$search.val(tokenData.term);
+        this.$search.trigger('focus');
+      }
+
+      params.term = tokenData.term;
+    }
+
+    decorated.call(this, params, callback);
+  };
+
+  Tokenizer.prototype.tokenizer = function (_, params, options, callback) {
+    var separators = options.get('tokenSeparators') || [];
+    var term = params.term;
+    var i = 0;
+
+    var createTag = this.createTag || function (params) {
+      return {
+        id: params.term,
+        text: params.term
+      };
+    };
+
+    while (i < term.length) {
+      var termChar = term[i];
+
+      if ($.inArray(termChar, separators) === -1) {
+        i++;
+
+        continue;
+      }
+
+      var part = term.substr(0, i);
+      var partParams = $.extend({}, params, {
+        term: part
+      });
+
+      var data = createTag(partParams);
+
+      if (data == null) {
+        i++;
+        continue;
+      }
+
+      callback(data);
+
+      // Reset the term to not include the tokenized portion
+      term = term.substr(i + 1) || '';
+      i = 0;
+    }
+
+    return {
+      term: term
+    };
+  };
+
+  return Tokenizer;
+});
+
+S2.define('select2/data/minimumInputLength',[
+
+], function () {
+  function MinimumInputLength (decorated, $e, options) {
+    this.minimumInputLength = options.get('minimumInputLength');
+
+    decorated.call(this, $e, options);
+  }
+
+  MinimumInputLength.prototype.query = function (decorated, params, callback) {
+    params.term = params.term || '';
+
+    if (params.term.length < this.minimumInputLength) {
+      this.trigger('results:message', {
+        message: 'inputTooShort',
+        args: {
+          minimum: this.minimumInputLength,
+          input: params.term,
+          params: params
+        }
+      });
+
+      return;
+    }
+
+    decorated.call(this, params, callback);
+  };
+
+  return MinimumInputLength;
+});
+
+S2.define('select2/data/maximumInputLength',[
+
+], function () {
+  function MaximumInputLength (decorated, $e, options) {
+    this.maximumInputLength = options.get('maximumInputLength');
+
+    decorated.call(this, $e, options);
+  }
+
+  MaximumInputLength.prototype.query = function (decorated, params, callback) {
+    params.term = params.term || '';
+
+    if (this.maximumInputLength > 0 &&
+        params.term.length > this.maximumInputLength) {
+      this.trigger('results:message', {
+        message: 'inputTooLong',
+        args: {
+          maximum: this.maximumInputLength,
+          input: params.term,
+          params: params
+        }
+      });
+
+      return;
+    }
+
+    decorated.call(this, params, callback);
+  };
+
+  return MaximumInputLength;
+});
+
+S2.define('select2/data/maximumSelectionLength',[
+
+], function (){
+  function MaximumSelectionLength (decorated, $e, options) {
+    this.maximumSelectionLength = options.get('maximumSelectionLength');
+
+    decorated.call(this, $e, options);
+  }
+
+  MaximumSelectionLength.prototype.bind =
+    function (decorated, container, $container) {
+      var self = this;
+
+      decorated.call(this, container, $container);
+
+      container.on('select', function () {
+        self._checkIfMaximumSelected();
+      });
+  };
+
+  MaximumSelectionLength.prototype.query =
+    function (decorated, params, callback) {
+      var self = this;
+
+      this._checkIfMaximumSelected(function () {
+        decorated.call(self, params, callback);
+      });
+  };
+
+  MaximumSelectionLength.prototype._checkIfMaximumSelected =
+    function (_, successCallback) {
+      var self = this;
+
+      this.current(function (currentData) {
+        var count = currentData != null ? currentData.length : 0;
+        if (self.maximumSelectionLength > 0 &&
+          count >= self.maximumSelectionLength) {
+          self.trigger('results:message', {
+            message: 'maximumSelected',
+            args: {
+              maximum: self.maximumSelectionLength
+            }
+          });
+          return;
+        }
+
+        if (successCallback) {
+          successCallback();
+        }
+      });
+  };
+
+  return MaximumSelectionLength;
+});
+
+S2.define('select2/dropdown',[
+  'jquery',
+  './utils'
+], function ($, Utils) {
+  function Dropdown ($element, options) {
+    this.$element = $element;
+    this.options = options;
+
+    Dropdown.__super__.constructor.call(this);
+  }
+
+  Utils.Extend(Dropdown, Utils.Observable);
+
+  Dropdown.prototype.render = function () {
+    var $dropdown = $(
+      '<span class="select2-dropdown">' +
+        '<span class="select2-results"></span>' +
+      '</span>'
+    );
+
+    $dropdown.attr('dir', this.options.get('dir'));
+
+    this.$dropdown = $dropdown;
+
+    return $dropdown;
+  };
+
+  Dropdown.prototype.bind = function () {
+    // Should be implemented in subclasses
+  };
+
+  Dropdown.prototype.position = function ($dropdown, $container) {
+    // Should be implemented in subclasses
+  };
+
+  Dropdown.prototype.destroy = function () {
+    // Remove the dropdown from the DOM
+    this.$dropdown.remove();
+  };
+
+  return Dropdown;
+});
+
+S2.define('select2/dropdown/search',[
+  'jquery',
+  '../utils'
+], function ($, Utils) {
+  function Search () { }
+
+  Search.prototype.render = function (decorated) {
+    var $rendered = decorated.call(this);
+
+    var $search = $(
+      '<span class="select2-search select2-search--dropdown">' +
+        '<input class="select2-search__field" type="search" tabindex="-1"' +
+        ' autocomplete="off" autocorrect="off" autocapitalize="none"' +
+        ' spellcheck="false" role="searchbox" aria-autocomplete="list" />' +
+      '</span>'
+    );
+
+    this.$searchContainer = $search;
+    this.$search = $search.find('input');
+
+    $rendered.prepend($search);
+
+    return $rendered;
+  };
+
+  Search.prototype.bind = function (decorated, container, $container) {
+    var self = this;
+
+    var resultsId = container.id + '-results';
+
+    decorated.call(this, container, $container);
+
+    this.$search.on('keydown', function (evt) {
+      self.trigger('keypress', evt);
+
+      self._keyUpPrevented = evt.isDefaultPrevented();
+    });
+
+    // Workaround for browsers which do not support the `input` event
+    // This will prevent double-triggering of events for browsers which support
+    // both the `keyup` and `input` events.
+    this.$search.on('input', function (evt) {
+      // Unbind the duplicated `keyup` event
+      $(this).off('keyup');
+    });
+
+    this.$search.on('keyup input', function (evt) {
+      self.handleSearch(evt);
+    });
+
+    container.on('open', function () {
+      self.$search.attr('tabindex', 0);
+      self.$search.attr('aria-controls', resultsId);
+
+      self.$search.trigger('focus');
+
+      window.setTimeout(function () {
+        self.$search.trigger('focus');
+      }, 0);
+    });
+
+    container.on('close', function () {
+      self.$search.attr('tabindex', -1);
+      self.$search.removeAttr('aria-controls');
+      self.$search.removeAttr('aria-activedescendant');
+
+      self.$search.val('');
+      self.$search.trigger('blur');
+    });
+
+    container.on('focus', function () {
+      if (!container.isOpen()) {
+        self.$search.trigger('focus');
+      }
+    });
+
+    container.on('results:all', function (params) {
+      if (params.query.term == null || params.query.term === '') {
+        var showSearch = self.showSearch(params);
+
+        if (showSearch) {
+          self.$searchContainer.removeClass('select2-search--hide');
+        } else {
+          self.$searchContainer.addClass('select2-search--hide');
+        }
+      }
+    });
+
+    container.on('results:focus', function (params) {
+      if (params.data._resultId) {
+        self.$search.attr('aria-activedescendant', params.data._resultId);
+      } else {
+        self.$search.removeAttr('aria-activedescendant');
+      }
+    });
+  };
+
+  Search.prototype.handleSearch = function (evt) {
+    if (!this._keyUpPrevented) {
+      var input = this.$search.val();
+
+      this.trigger('query', {
+        term: input
+      });
+    }
+
+    this._keyUpPrevented = false;
+  };
+
+  Search.prototype.showSearch = function (_, params) {
+    return true;
+  };
+
+  return Search;
+});
+
+S2.define('select2/dropdown/hidePlaceholder',[
+
+], function () {
+  function HidePlaceholder (decorated, $element, options, dataAdapter) {
+    this.placeholder = this.normalizePlaceholder(options.get('placeholder'));
+
+    decorated.call(this, $element, options, dataAdapter);
+  }
+
+  HidePlaceholder.prototype.append = function (decorated, data) {
+    data.results = this.removePlaceholder(data.results);
+
+    decorated.call(this, data);
+  };
+
+  HidePlaceholder.prototype.normalizePlaceholder = function (_, placeholder) {
+    if (typeof placeholder === 'string') {
+      placeholder = {
+        id: '',
+        text: placeholder
+      };
+    }
+
+    return placeholder;
+  };
+
+  HidePlaceholder.prototype.removePlaceholder = function (_, data) {
+    var modifiedData = data.slice(0);
+
+    for (var d = data.length - 1; d >= 0; d--) {
+      var item = data[d];
+
+      if (this.placeholder.id === item.id) {
+        modifiedData.splice(d, 1);
+      }
+    }
+
+    return modifiedData;
+  };
+
+  return HidePlaceholder;
+});
+
+S2.define('select2/dropdown/infiniteScroll',[
+  'jquery'
+], function ($) {
+  function InfiniteScroll (decorated, $element, options, dataAdapter) {
+    this.lastParams = {};
+
+    decorated.call(this, $element, options, dataAdapter);
+
+    this.$loadingMore = this.createLoadingMore();
+    this.loading = false;
+  }
+
+  InfiniteScroll.prototype.append = function (decorated, data) {
+    this.$loadingMore.remove();
+    this.loading = false;
+
+    decorated.call(this, data);
+
+    if (this.showLoadingMore(data)) {
+      this.$results.append(this.$loadingMore);
+      this.loadMoreIfNeeded();
+    }
+  };
+
+  InfiniteScroll.prototype.bind = function (decorated, container, $container) {
+    var self = this;
+
+    decorated.call(this, container, $container);
+
+    container.on('query', function (params) {
+      self.lastParams = params;
+      self.loading = true;
+    });
+
+    container.on('query:append', function (params) {
+      self.lastParams = params;
+      self.loading = true;
+    });
+
+    this.$results.on('scroll', this.loadMoreIfNeeded.bind(this));
+  };
+
+  InfiniteScroll.prototype.loadMoreIfNeeded = function () {
+    var isLoadMoreVisible = $.contains(
+      document.documentElement,
+      this.$loadingMore[0]
+    );
+
+    if (this.loading || !isLoadMoreVisible) {
+      return;
+    }
+
+    var currentOffset = this.$results.offset().top +
+      this.$results.outerHeight(false);
+    var loadingMoreOffset = this.$loadingMore.offset().top +
+      this.$loadingMore.outerHeight(false);
+
+    if (currentOffset + 50 >= loadingMoreOffset) {
+      this.loadMore();
+    }
+  };
+
+  InfiniteScroll.prototype.loadMore = function () {
+    this.loading = true;
+
+    var params = $.extend({}, {page: 1}, this.lastParams);
+
+    params.page++;
+
+    this.trigger('query:append', params);
+  };
+
+  InfiniteScroll.prototype.showLoadingMore = function (_, data) {
+    return data.pagination && data.pagination.more;
+  };
+
+  InfiniteScroll.prototype.createLoadingMore = function () {
+    var $option = $(
+      '<li ' +
+      'class="select2-results__option select2-results__option--load-more"' +
+      'role="option" aria-disabled="true"></li>'
+    );
+
+    var message = this.options.get('translations').get('loadingMore');
+
+    $option.html(message(this.lastParams));
+
+    return $option;
+  };
+
+  return InfiniteScroll;
+});
+
+S2.define('select2/dropdown/attachBody',[
+  'jquery',
+  '../utils'
+], function ($, Utils) {
+  function AttachBody (decorated, $element, options) {
+    this.$dropdownParent = $(options.get('dropdownParent') || document.body);
+
+    decorated.call(this, $element, options);
+  }
+
+  AttachBody.prototype.bind = function (decorated, container, $container) {
+    var self = this;
+
+    decorated.call(this, container, $container);
+
+    container.on('open', function () {
+      self._showDropdown();
+      self._attachPositioningHandler(container);
+
+      // Must bind after the results handlers to ensure correct sizing
+      self._bindContainerResultHandlers(container);
+    });
+
+    container.on('close', function () {
+      self._hideDropdown();
+      self._detachPositioningHandler(container);
+    });
+
+    this.$dropdownContainer.on('mousedown', function (evt) {
+      evt.stopPropagation();
+    });
+  };
+
+  AttachBody.prototype.destroy = function (decorated) {
+    decorated.call(this);
+
+    this.$dropdownContainer.remove();
+  };
+
+  AttachBody.prototype.position = function (decorated, $dropdown, $container) {
+    // Clone all of the container classes
+    $dropdown.attr('class', $container.attr('class'));
+
+    $dropdown.removeClass('select2');
+    $dropdown.addClass('select2-container--open');
+
+    $dropdown.css({
+      position: 'absolute',
+      top: -999999
+    });
+
+    this.$container = $container;
+  };
+
+  AttachBody.prototype.render = function (decorated) {
+    var $container = $('<span></span>');
+
+    var $dropdown = decorated.call(this);
+    $container.append($dropdown);
+
+    this.$dropdownContainer = $container;
+
+    return $container;
+  };
+
+  AttachBody.prototype._hideDropdown = function (decorated) {
+    this.$dropdownContainer.detach();
+  };
+
+  AttachBody.prototype._bindContainerResultHandlers =
+      function (decorated, container) {
+
+    // These should only be bound once
+    if (this._containerResultsHandlersBound) {
+      return;
+    }
+
+    var self = this;
+
+    container.on('results:all', function () {
+      self._positionDropdown();
+      self._resizeDropdown();
+    });
+
+    container.on('results:append', function () {
+      self._positionDropdown();
+      self._resizeDropdown();
+    });
+
+    container.on('results:message', function () {
+      self._positionDropdown();
+      self._resizeDropdown();
+    });
+
+    container.on('select', function () {
+      self._positionDropdown();
+      self._resizeDropdown();
+    });
+
+    container.on('unselect', function () {
+      self._positionDropdown();
+      self._resizeDropdown();
+    });
+
+    this._containerResultsHandlersBound = true;
+  };
+
+  AttachBody.prototype._attachPositioningHandler =
+      function (decorated, container) {
+    var self = this;
+
+    var scrollEvent = 'scroll.select2.' + container.id;
+    var resizeEvent = 'resize.select2.' + container.id;
+    var orientationEvent = 'orientationchange.select2.' + container.id;
+
+    var $watchers = this.$container.parents().filter(Utils.hasScroll);
+    $watchers.each(function () {
+      Utils.StoreData(this, 'select2-scroll-position', {
+        x: $(this).scrollLeft(),
+        y: $(this).scrollTop()
+      });
+    });
+
+    $watchers.on(scrollEvent, function (ev) {
+      var position = Utils.GetData(this, 'select2-scroll-position');
+      $(this).scrollTop(position.y);
+    });
+
+    $(window).on(scrollEvent + ' ' + resizeEvent + ' ' + orientationEvent,
+      function (e) {
+      self._positionDropdown();
+      self._resizeDropdown();
+    });
+  };
+
+  AttachBody.prototype._detachPositioningHandler =
+      function (decorated, container) {
+    var scrollEvent = 'scroll.select2.' + container.id;
+    var resizeEvent = 'resize.select2.' + container.id;
+    var orientationEvent = 'orientationchange.select2.' + container.id;
+
+    var $watchers = this.$container.parents().filter(Utils.hasScroll);
+    $watchers.off(scrollEvent);
+
+    $(window).off(scrollEvent + ' ' + resizeEvent + ' ' + orientationEvent);
+  };
+
+  AttachBody.prototype._positionDropdown = function () {
+    var $window = $(window);
+
+    var isCurrentlyAbove = this.$dropdown.hasClass('select2-dropdown--above');
+    var isCurrentlyBelow = this.$dropdown.hasClass('select2-dropdown--below');
+
+    var newDirection = null;
+
+    var offset = this.$container.offset();
+
+    offset.bottom = offset.top + this.$container.outerHeight(false);
+
+    var container = {
+      height: this.$container.outerHeight(false)
+    };
+
+    container.top = offset.top;
+    container.bottom = offset.top + container.height;
+
+    var dropdown = {
+      height: this.$dropdown.outerHeight(false)
+    };
+
+    var viewport = {
+      top: $window.scrollTop(),
+      bottom: $window.scrollTop() + $window.height()
+    };
+
+    var enoughRoomAbove = viewport.top < (offset.top - dropdown.height);
+    var enoughRoomBelow = viewport.bottom > (offset.bottom + dropdown.height);
+
+    var css = {
+      left: offset.left,
+      top: container.bottom
+    };
+
+    // Determine what the parent element is to use for calculating the offset
+    var $offsetParent = this.$dropdownParent;
+
+    // For statically positioned elements, we need to get the element
+    // that is determining the offset
+    if ($offsetParent.css('position') === 'static') {
+      $offsetParent = $offsetParent.offsetParent();
+    }
+
+    var parentOffset = {
+      top: 0,
+      left: 0
+    };
+
+    if (
+      $.contains(document.body, $offsetParent[0]) ||
+      $offsetParent[0].isConnected
+      ) {
+      parentOffset = $offsetParent.offset();
+    }
+
+    css.top -= parentOffset.top;
+    css.left -= parentOffset.left;
+
+    if (!isCurrentlyAbove && !isCurrentlyBelow) {
+      newDirection = 'below';
+    }
+
+    if (!enoughRoomBelow && enoughRoomAbove && !isCurrentlyAbove) {
+      newDirection = 'above';
+    } else if (!enoughRoomAbove && enoughRoomBelow && isCurrentlyAbove) {
+      newDirection = 'below';
+    }
+
+    if (newDirection == 'above' ||
+      (isCurrentlyAbove && newDirection !== 'below')) {
+      css.top = container.top - parentOffset.top - dropdown.height;
+    }
+
+    if (newDirection != null) {
+      this.$dropdown
+        .removeClass('select2-dropdown--below select2-dropdown--above')
+        .addClass('select2-dropdown--' + newDirection);
+      this.$container
+        .removeClass('select2-container--below select2-container--above')
+        .addClass('select2-container--' + newDirection);
+    }
+
+    this.$dropdownContainer.css(css);
+  };
+
+  AttachBody.prototype._resizeDropdown = function () {
+    var css = {
+      width: this.$container.outerWidth(false) + 'px'
+    };
+
+    if (this.options.get('dropdownAutoWidth')) {
+      css.minWidth = css.width;
+      css.position = 'relative';
+      css.width = 'auto';
+    }
+
+    this.$dropdown.css(css);
+  };
+
+  AttachBody.prototype._showDropdown = function (decorated) {
+    this.$dropdownContainer.appendTo(this.$dropdownParent);
+
+    this._positionDropdown();
+    this._resizeDropdown();
+  };
+
+  return AttachBody;
+});
+
+S2.define('select2/dropdown/minimumResultsForSearch',[
+
+], function () {
+  function countResults (data) {
+    var count = 0;
+
+    for (var d = 0; d < data.length; d++) {
+      var item = data[d];
+
+      if (item.children) {
+        count += countResults(item.children);
+      } else {
+        count++;
+      }
+    }
+
+    return count;
+  }
+
+  function MinimumResultsForSearch (decorated, $element, options, dataAdapter) {
+    this.minimumResultsForSearch = options.get('minimumResultsForSearch');
+
+    if (this.minimumResultsForSearch < 0) {
+      this.minimumResultsForSearch = Infinity;
+    }
+
+    decorated.call(this, $element, options, dataAdapter);
+  }
+
+  MinimumResultsForSearch.prototype.showSearch = function (decorated, params) {
+    if (countResults(params.data.results) < this.minimumResultsForSearch) {
+      return false;
+    }
+
+    return decorated.call(this, params);
+  };
+
+  return MinimumResultsForSearch;
+});
+
+S2.define('select2/dropdown/selectOnClose',[
+  '../utils'
+], function (Utils) {
+  function SelectOnClose () { }
+
+  SelectOnClose.prototype.bind = function (decorated, container, $container) {
+    var self = this;
+
+    decorated.call(this, container, $container);
+
+    container.on('close', function (params) {
+      self._handleSelectOnClose(params);
+    });
+  };
+
+  SelectOnClose.prototype._handleSelectOnClose = function (_, params) {
+    if (params && params.originalSelect2Event != null) {
+      var event = params.originalSelect2Event;
+
+      // Don't select an item if the close event was triggered from a select or
+      // unselect event
+      if (event._type === 'select' || event._type === 'unselect') {
+        return;
+      }
+    }
+
+    var $highlightedResults = this.getHighlightedResults();
+
+    // Only select highlighted results
+    if ($highlightedResults.length < 1) {
+      return;
+    }
+
+    var data = Utils.GetData($highlightedResults[0], 'data');
+
+    // Don't re-select already selected resulte
+    if (
+      (data.element != null && data.element.selected) ||
+      (data.element == null && data.selected)
+    ) {
+      return;
+    }
+
+    this.trigger('select', {
+        data: data
+    });
+  };
+
+  return SelectOnClose;
+});
+
+S2.define('select2/dropdown/closeOnSelect',[
+
+], function () {
+  function CloseOnSelect () { }
+
+  CloseOnSelect.prototype.bind = function (decorated, container, $container) {
+    var self = this;
+
+    decorated.call(this, container, $container);
+
+    container.on('select', function (evt) {
+      self._selectTriggered(evt);
+    });
+
+    container.on('unselect', function (evt) {
+      self._selectTriggered(evt);
+    });
+  };
+
+  CloseOnSelect.prototype._selectTriggered = function (_, evt) {
+    var originalEvent = evt.originalEvent;
+
+    // Don't close if the control key is being held
+    if (originalEvent && (originalEvent.ctrlKey || originalEvent.metaKey)) {
+      return;
+    }
+
+    this.trigger('close', {
+      originalEvent: originalEvent,
+      originalSelect2Event: evt
+    });
+  };
+
+  return CloseOnSelect;
+});
+
+S2.define('select2/i18n/en',[],function () {
+  // English
+  return {
+    errorLoading: function () {
+      return '无法载入结果。';
+    },
+    inputTooLong: function (args) {
+      var overChars = args.input.length - args.maximum;
+
+      var message = '请删除' + overChars + '个字符';
+
+      if (overChars != 1) {
+        message += 's';
+      }
+
+      return message;
+    },
+    inputTooShort: function (args) {
+      var remainingChars = args.minimum - args.input.length;
+
+      var message = '请再输入至少' + remainingChars + '个字符';
+
+      return message;
+    },
+    loadingMore: function () {
+      return '载入更多结果…';
+    },
+    maximumSelected: function (args) {
+      var message = '最多只能' + args.maximum + '个选项';
+
+      if (args.maximum != 1) {
+        message += 's';
+      }
+
+      return message;
+    },
+    noResults: function () {
+      return '未找到结果';
+    },
+    searching: function () {
+      return '搜索中…';
+    },
+    removeAllItems: function () {
+      return '删除所有项目';
+    }
+  };
+});
+
+S2.define('select2/defaults',[
+  'jquery',
+  'require',
+
+  './results',
+
+  './selection/single',
+  './selection/multiple',
+  './selection/placeholder',
+  './selection/allowClear',
+  './selection/search',
+  './selection/eventRelay',
+
+  './utils',
+  './translation',
+  './diacritics',
+
+  './data/select',
+  './data/array',
+  './data/ajax',
+  './data/tags',
+  './data/tokenizer',
+  './data/minimumInputLength',
+  './data/maximumInputLength',
+  './data/maximumSelectionLength',
+
+  './dropdown',
+  './dropdown/search',
+  './dropdown/hidePlaceholder',
+  './dropdown/infiniteScroll',
+  './dropdown/attachBody',
+  './dropdown/minimumResultsForSearch',
+  './dropdown/selectOnClose',
+  './dropdown/closeOnSelect',
+
+  './i18n/en'
+], function ($, require,
+
+             ResultsList,
+
+             SingleSelection, MultipleSelection, Placeholder, AllowClear,
+             SelectionSearch, EventRelay,
+
+             Utils, Translation, DIACRITICS,
+
+             SelectData, ArrayData, AjaxData, Tags, Tokenizer,
+             MinimumInputLength, MaximumInputLength, MaximumSelectionLength,
+
+             Dropdown, DropdownSearch, HidePlaceholder, InfiniteScroll,
+             AttachBody, MinimumResultsForSearch, SelectOnClose, CloseOnSelect,
+
+             EnglishTranslation) {
+  function Defaults () {
+    this.reset();
+  }
+
+  Defaults.prototype.apply = function (options) {
+    options = $.extend(true, {}, this.defaults, options);
+
+    if (options.dataAdapter == null) {
+      if (options.ajax != null) {
+        options.dataAdapter = AjaxData;
+      } else if (options.data != null) {
+        options.dataAdapter = ArrayData;
+      } else {
+        options.dataAdapter = SelectData;
+      }
+
+      if (options.minimumInputLength > 0) {
+        options.dataAdapter = Utils.Decorate(
+          options.dataAdapter,
+          MinimumInputLength
+        );
+      }
+
+      if (options.maximumInputLength > 0) {
+        options.dataAdapter = Utils.Decorate(
+          options.dataAdapter,
+          MaximumInputLength
+        );
+      }
+
+      if (options.maximumSelectionLength > 0) {
+        options.dataAdapter = Utils.Decorate(
+          options.dataAdapter,
+          MaximumSelectionLength
+        );
+      }
+
+      if (options.tags) {
+        options.dataAdapter = Utils.Decorate(options.dataAdapter, Tags);
+      }
+
+      if (options.tokenSeparators != null || options.tokenizer != null) {
+        options.dataAdapter = Utils.Decorate(
+          options.dataAdapter,
+          Tokenizer
+        );
+      }
+
+      if (options.query != null) {
+        var Query = require(options.amdBase + 'compat/query');
+
+        options.dataAdapter = Utils.Decorate(
+          options.dataAdapter,
+          Query
+        );
+      }
+
+      if (options.initSelection != null) {
+        var InitSelection = require(options.amdBase + 'compat/initSelection');
+
+        options.dataAdapter = Utils.Decorate(
+          options.dataAdapter,
+          InitSelection
+        );
+      }
+    }
+
+    if (options.resultsAdapter == null) {
+      options.resultsAdapter = ResultsList;
+
+      if (options.ajax != null) {
+        options.resultsAdapter = Utils.Decorate(
+          options.resultsAdapter,
+          InfiniteScroll
+        );
+      }
+
+      if (options.placeholder != null) {
+        options.resultsAdapter = Utils.Decorate(
+          options.resultsAdapter,
+          HidePlaceholder
+        );
+      }
+
+      if (options.selectOnClose) {
+        options.resultsAdapter = Utils.Decorate(
+          options.resultsAdapter,
+          SelectOnClose
+        );
+      }
+    }
+
+    if (options.dropdownAdapter == null) {
+      if (options.multiple) {
+        options.dropdownAdapter = Dropdown;
+      } else {
+        var SearchableDropdown = Utils.Decorate(Dropdown, DropdownSearch);
+
+        options.dropdownAdapter = SearchableDropdown;
+      }
+
+      if (options.minimumResultsForSearch !== 0) {
+        options.dropdownAdapter = Utils.Decorate(
+          options.dropdownAdapter,
+          MinimumResultsForSearch
+        );
+      }
+
+      if (options.closeOnSelect) {
+        options.dropdownAdapter = Utils.Decorate(
+          options.dropdownAdapter,
+          CloseOnSelect
+        );
+      }
+
+      if (
+        options.dropdownCssClass != null ||
+        options.dropdownCss != null ||
+        options.adaptDropdownCssClass != null
+      ) {
+        var DropdownCSS = require(options.amdBase + 'compat/dropdownCss');
+
+        options.dropdownAdapter = Utils.Decorate(
+          options.dropdownAdapter,
+          DropdownCSS
+        );
+      }
+
+      options.dropdownAdapter = Utils.Decorate(
+        options.dropdownAdapter,
+        AttachBody
+      );
+    }
+
+    if (options.selectionAdapter == null) {
+      if (options.multiple) {
+        options.selectionAdapter = MultipleSelection;
+      } else {
+        options.selectionAdapter = SingleSelection;
+      }
+
+      // Add the placeholder mixin if a placeholder was specified
+      if (options.placeholder != null) {
+        options.selectionAdapter = Utils.Decorate(
+          options.selectionAdapter,
+          Placeholder
+        );
+      }
+
+      if (options.allowClear) {
+        options.selectionAdapter = Utils.Decorate(
+          options.selectionAdapter,
+          AllowClear
+        );
+      }
+
+      if (options.multiple) {
+        options.selectionAdapter = Utils.Decorate(
+          options.selectionAdapter,
+          SelectionSearch
+        );
+      }
+
+      if (
+        options.containerCssClass != null ||
+        options.containerCss != null ||
+        options.adaptContainerCssClass != null
+      ) {
+        var ContainerCSS = require(options.amdBase + 'compat/containerCss');
+
+        options.selectionAdapter = Utils.Decorate(
+          options.selectionAdapter,
+          ContainerCSS
+        );
+      }
+
+      options.selectionAdapter = Utils.Decorate(
+        options.selectionAdapter,
+        EventRelay
+      );
+    }
+
+    // If the defaults were not previously applied from an element, it is
+    // possible for the language option to have not been resolved
+    options.language = this._resolveLanguage(options.language);
+
+    // Always fall back to English since it will always be complete
+    options.language.push('en');
+
+    var uniqueLanguages = [];
+
+    for (var l = 0; l < options.language.length; l++) {
+      var language = options.language[l];
+
+      if (uniqueLanguages.indexOf(language) === -1) {
+        uniqueLanguages.push(language);
+      }
+    }
+
+    options.language = uniqueLanguages;
+
+    options.translations = this._processTranslations(
+      options.language,
+      options.debug
+    );
+
+    return options;
+  };
+
+  Defaults.prototype.reset = function () {
+    function stripDiacritics (text) {
+      // Used 'uni range + named function' from http://jsperf.com/diacritics/18
+      function match(a) {
+        return DIACRITICS[a] || a;
+      }
+
+      return text.replace(/[^\u0000-\u007E]/g, match);
+    }
+
+    function matcher (params, data) {
+      // Always return the object if there is nothing to compare
+      if ($.trim(params.term) === '') {
+        return data;
+      }
+
+      // Do a recursive check for options with children
+      if (data.children && data.children.length > 0) {
+        // Clone the data object if there are children
+        // This is required as we modify the object to remove any non-matches
+        var match = $.extend(true, {}, data);
+
+        // Check each child of the option
+        for (var c = data.children.length - 1; c >= 0; c--) {
+          var child = data.children[c];
+
+          var matches = matcher(params, child);
+
+          // If there wasn't a match, remove the object in the array
+          if (matches == null) {
+            match.children.splice(c, 1);
+          }
+        }
+
+        // If any children matched, return the new object
+        if (match.children.length > 0) {
+          return match;
+        }
+
+        // If there were no matching children, check just the plain object
+        return matcher(params, match);
+      }
+
+      var original = stripDiacritics(data.text).toUpperCase();
+      var term = stripDiacritics(params.term).toUpperCase();
+
+      // Check if the text contains the term
+      if (original.indexOf(term) > -1) {
+        return data;
+      }
+
+      // If it doesn't contain the term, don't return anything
+      return null;
+    }
+
+    this.defaults = {
+      amdBase: './',
+      amdLanguageBase: './i18n/',
+      closeOnSelect: true,
+      debug: false,
+      dropdownAutoWidth: false,
+      escapeMarkup: Utils.escapeMarkup,
+      language: {},
+      matcher: matcher,
+      minimumInputLength: 0,
+      maximumInputLength: 0,
+      maximumSelectionLength: 0,
+      minimumResultsForSearch: 0,
+      selectOnClose: false,
+      scrollAfterSelect: false,
+      sorter: function (data) {
+        return data;
+      },
+      templateResult: function (result) {
+        return result.text;
+      },
+      templateSelection: function (selection) {
+        return selection.text;
+      },
+      theme: 'default',
+      width: 'resolve'
+    };
+  };
+
+  Defaults.prototype.applyFromElement = function (options, $element) {
+    var optionLanguage = options.language;
+    var defaultLanguage = this.defaults.language;
+    var elementLanguage = $element.prop('lang');
+    var parentLanguage = $element.closest('[lang]').prop('lang');
+
+    var languages = Array.prototype.concat.call(
+      this._resolveLanguage(elementLanguage),
+      this._resolveLanguage(optionLanguage),
+      this._resolveLanguage(defaultLanguage),
+      this._resolveLanguage(parentLanguage)
+    );
+
+    options.language = languages;
+
+    return options;
+  };
+
+  Defaults.prototype._resolveLanguage = function (language) {
+    if (!language) {
+      return [];
+    }
+
+    if ($.isEmptyObject(language)) {
+      return [];
+    }
+
+    if ($.isPlainObject(language)) {
+      return [language];
+    }
+
+    var languages;
+
+    if (!$.isArray(language)) {
+      languages = [language];
+    } else {
+      languages = language;
+    }
+
+    var resolvedLanguages = [];
+
+    for (var l = 0; l < languages.length; l++) {
+      resolvedLanguages.push(languages[l]);
+
+      if (typeof languages[l] === 'string' && languages[l].indexOf('-') > 0) {
+        // Extract the region information if it is included
+        var languageParts = languages[l].split('-');
+        var baseLanguage = languageParts[0];
+
+        resolvedLanguages.push(baseLanguage);
+      }
+    }
+
+    return resolvedLanguages;
+  };
+
+  Defaults.prototype._processTranslations = function (languages, debug) {
+    var translations = new Translation();
+
+    for (var l = 0; l < languages.length; l++) {
+      var languageData = new Translation();
+
+      var language = languages[l];
+
+      if (typeof language === 'string') {
+        try {
+          // Try to load it with the original name
+          languageData = Translation.loadPath(language);
+        } catch (e) {
+          try {
+            // If we couldn't load it, check if it wasn't the full path
+            language = this.defaults.amdLanguageBase + language;
+            languageData = Translation.loadPath(language);
+          } catch (ex) {
+            // The translation could not be loaded at all. Sometimes this is
+            // because of a configuration problem, other times this can be
+            // because of how Select2 helps load all possible translation files
+            if (debug && window.console && console.warn) {
+              console.warn(
+                'Select2: The language file for "' + language + '" could ' +
+                'not be automatically loaded. A fallback will be used instead.'
+              );
+            }
+          }
+        }
+      } else if ($.isPlainObject(language)) {
+        languageData = new Translation(language);
+      } else {
+        languageData = language;
+      }
+
+      translations.extend(languageData);
+    }
+
+    return translations;
+  };
+
+  Defaults.prototype.set = function (key, value) {
+    var camelKey = $.camelCase(key);
+
+    var data = {};
+    data[camelKey] = value;
+
+    var convertedData = Utils._convertData(data);
+
+    $.extend(true, this.defaults, convertedData);
+  };
+
+  var defaults = new Defaults();
+
+  return defaults;
+});
+
+S2.define('select2/options',[
+  'require',
+  'jquery',
+  './defaults',
+  './utils'
+], function (require, $, Defaults, Utils) {
+  function Options (options, $element) {
+    this.options = options;
+
+    if ($element != null) {
+      this.fromElement($element);
+    }
+
+    if ($element != null) {
+      this.options = Defaults.applyFromElement(this.options, $element);
+    }
+
+    this.options = Defaults.apply(this.options);
+
+    if ($element && $element.is('input')) {
+      var InputCompat = require(this.get('amdBase') + 'compat/inputData');
+
+      this.options.dataAdapter = Utils.Decorate(
+        this.options.dataAdapter,
+        InputCompat
+      );
+    }
+  }
+
+  Options.prototype.fromElement = function ($e) {
+    var excludedData = ['select2'];
+
+    if (this.options.multiple == null) {
+      this.options.multiple = $e.prop('multiple');
+    }
+
+    if (this.options.disabled == null) {
+      this.options.disabled = $e.prop('disabled');
+    }
+
+    if (this.options.dir == null) {
+      if ($e.prop('dir')) {
+        this.options.dir = $e.prop('dir');
+      } else if ($e.closest('[dir]').prop('dir')) {
+        this.options.dir = $e.closest('[dir]').prop('dir');
+      } else {
+        this.options.dir = 'ltr';
+      }
+    }
+
+    $e.prop('disabled', this.options.disabled);
+    $e.prop('multiple', this.options.multiple);
+
+    if (Utils.GetData($e[0], 'select2Tags')) {
+      if (this.options.debug && window.console && console.warn) {
+        console.warn(
+          'Select2: The `data-select2-tags` attribute has been changed to ' +
+          'use the `data-data` and `data-tags="true"` attributes and will be ' +
+          'removed in future versions of Select2.'
+        );
+      }
+
+      Utils.StoreData($e[0], 'data', Utils.GetData($e[0], 'select2Tags'));
+      Utils.StoreData($e[0], 'tags', true);
+    }
+
+    if (Utils.GetData($e[0], 'ajaxUrl')) {
+      if (this.options.debug && window.console && console.warn) {
+        console.warn(
+          'Select2: The `data-ajax-url` attribute has been changed to ' +
+          '`data-ajax--url` and support for the old attribute will be removed' +
+          ' in future versions of Select2.'
+        );
+      }
+
+      $e.attr('ajax--url', Utils.GetData($e[0], 'ajaxUrl'));
+      Utils.StoreData($e[0], 'ajax-Url', Utils.GetData($e[0], 'ajaxUrl'));
+    }
+
+    var dataset = {};
+
+    function upperCaseLetter(_, letter) {
+      return letter.toUpperCase();
+    }
+
+    // Pre-load all of the attributes which are prefixed with `data-`
+    for (var attr = 0; attr < $e[0].attributes.length; attr++) {
+      var attributeName = $e[0].attributes[attr].name;
+      var prefix = 'data-';
+
+      if (attributeName.substr(0, prefix.length) == prefix) {
+        // Get the contents of the attribute after `data-`
+        var dataName = attributeName.substring(prefix.length);
+
+        // Get the data contents from the consistent source
+        // This is more than likely the jQuery data helper
+        var dataValue = Utils.GetData($e[0], dataName);
+
+        // camelCase the attribute name to match the spec
+        var camelDataName = dataName.replace(/-([a-z])/g, upperCaseLetter);
+
+        // Store the data attribute contents into the dataset since
+        dataset[camelDataName] = dataValue;
+      }
+    }
+
+    // Prefer the element's `dataset` attribute if it exists
+    // jQuery 1.x does not correctly handle data attributes with multiple dashes
+    if ($.fn.jquery && $.fn.jquery.substr(0, 2) == '1.' && $e[0].dataset) {
+      dataset = $.extend(true, {}, $e[0].dataset, dataset);
+    }
+
+    // Prefer our internal data cache if it exists
+    var data = $.extend(true, {}, Utils.GetData($e[0]), dataset);
+
+    data = Utils._convertData(data);
+
+    for (var key in data) {
+      if ($.inArray(key, excludedData) > -1) {
+        continue;
+      }
+
+      if ($.isPlainObject(this.options[key])) {
+        $.extend(this.options[key], data[key]);
+      } else {
+        this.options[key] = data[key];
+      }
+    }
+
+    return this;
+  };
+
+  Options.prototype.get = function (key) {
+    return this.options[key];
+  };
+
+  Options.prototype.set = function (key, val) {
+    this.options[key] = val;
+  };
+
+  return Options;
+});
+
+S2.define('select2/core',[
+  'jquery',
+  './options',
+  './utils',
+  './keys'
+], function ($, Options, Utils, KEYS) {
+  var Select2 = function ($element, options) {
+    if (Utils.GetData($element[0], 'select2') != null) {
+      Utils.GetData($element[0], 'select2').destroy();
+    }
+
+    this.$element = $element;
+
+    this.id = this._generateId($element);
+
+    options = options || {};
+
+    this.options = new Options(options, $element);
+
+    Select2.__super__.constructor.call(this);
+
+    // Set up the tabindex
+
+    var tabindex = $element.attr('tabindex') || 0;
+    Utils.StoreData($element[0], 'old-tabindex', tabindex);
+    $element.attr('tabindex', '-1');
+
+    // Set up containers and adapters
+
+    var DataAdapter = this.options.get('dataAdapter');
+    this.dataAdapter = new DataAdapter($element, this.options);
+
+    var $container = this.render();
+
+    this._placeContainer($container);
+
+    var SelectionAdapter = this.options.get('selectionAdapter');
+    this.selection = new SelectionAdapter($element, this.options);
+    this.$selection = this.selection.render();
+
+    this.selection.position(this.$selection, $container);
+
+    var DropdownAdapter = this.options.get('dropdownAdapter');
+    this.dropdown = new DropdownAdapter($element, this.options);
+    this.$dropdown = this.dropdown.render();
+
+    this.dropdown.position(this.$dropdown, $container);
+
+    var ResultsAdapter = this.options.get('resultsAdapter');
+    this.results = new ResultsAdapter($element, this.options, this.dataAdapter);
+    this.$results = this.results.render();
+
+    this.results.position(this.$results, this.$dropdown);
+
+    // Bind events
+
+    var self = this;
+
+    // Bind the container to all of the adapters
+    this._bindAdapters();
+
+    // Register any DOM event handlers
+    this._registerDomEvents();
+
+    // Register any internal event handlers
+    this._registerDataEvents();
+    this._registerSelectionEvents();
+    this._registerDropdownEvents();
+    this._registerResultsEvents();
+    this._registerEvents();
+
+    // Set the initial state
+    this.dataAdapter.current(function (initialData) {
+      self.trigger('selection:update', {
+        data: initialData
+      });
+    });
+
+    // Hide the original select
+    $element.addClass('select2-hidden-accessible');
+    $element.attr('aria-hidden', 'true');
+
+    // Synchronize any monitored attributes
+    this._syncAttributes();
+
+    Utils.StoreData($element[0], 'select2', this);
+
+    // Ensure backwards compatibility with $element.data('select2').
+    $element.data('select2', this);
+  };
+
+  Utils.Extend(Select2, Utils.Observable);
+
+  Select2.prototype._generateId = function ($element) {
+    var id = '';
+
+    if ($element.attr('id') != null) {
+      id = $element.attr('id');
+    } else if ($element.attr('name') != null) {
+      id = $element.attr('name') + '-' + Utils.generateChars(2);
+    } else {
+      id = Utils.generateChars(4);
+    }
+
+    id = id.replace(/(:|\.|\[|\]|,)/g, '');
+    id = 'select2-' + id;
+
+    return id;
+  };
+
+  Select2.prototype._placeContainer = function ($container) {
+    $container.insertAfter(this.$element);
+
+    var width = this._resolveWidth(this.$element, this.options.get('width'));
+
+    if (width != null) {
+      $container.css('width', width);
+    }
+  };
+
+  Select2.prototype._resolveWidth = function ($element, method) {
+    var WIDTH = /^width:(([-+]?([0-9]*\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i;
+
+    if (method == 'resolve') {
+      var styleWidth = this._resolveWidth($element, 'style');
+
+      if (styleWidth != null) {
+        return styleWidth;
+      }
+
+      return this._resolveWidth($element, 'element');
+    }
+
+    if (method == 'element') {
+      var elementWidth = $element.outerWidth(false);
+
+      if (elementWidth <= 0) {
+        return 'auto';
+      }
+
+      return elementWidth + 'px';
+    }
+
+    if (method == 'style') {
+      var style = $element.attr('style');
+
+      if (typeof(style) !== 'string') {
+        return null;
+      }
+
+      var attrs = style.split(';');
+
+      for (var i = 0, l = attrs.length; i < l; i = i + 1) {
+        var attr = attrs[i].replace(/\s/g, '');
+        var matches = attr.match(WIDTH);
+
+        if (matches !== null && matches.length >= 1) {
+          return matches[1];
+        }
+      }
+
+      return null;
+    }
+
+    if (method == 'computedstyle') {
+      var computedStyle = window.getComputedStyle($element[0]);
+
+      return computedStyle.width;
+    }
+
+    return method;
+  };
+
+  Select2.prototype._bindAdapters = function () {
+    this.dataAdapter.bind(this, this.$container);
+    this.selection.bind(this, this.$container);
+
+    this.dropdown.bind(this, this.$container);
+    this.results.bind(this, this.$container);
+  };
+
+  Select2.prototype._registerDomEvents = function () {
+    var self = this;
+
+    this.$element.on('change.select2', function () {
+      self.dataAdapter.current(function (data) {
+        self.trigger('selection:update', {
+          data: data
+        });
+      });
+    });
+
+    this.$element.on('focus.select2', function (evt) {
+      self.trigger('focus', evt);
+    });
+
+    this._syncA = Utils.bind(this._syncAttributes, this);
+    this._syncS = Utils.bind(this._syncSubtree, this);
+
+    if (this.$element[0].attachEvent) {
+      this.$element[0].attachEvent('onpropertychange', this._syncA);
+    }
+
+    var observer = window.MutationObserver ||
+      window.WebKitMutationObserver ||
+      window.MozMutationObserver
+    ;
+
+    if (observer != null) {
+      this._observer = new observer(function (mutations) {
+        self._syncA();
+        self._syncS(null, mutations);
+      });
+      this._observer.observe(this.$element[0], {
+        attributes: true,
+        childList: true,
+        subtree: false
+      });
+    } else if (this.$element[0].addEventListener) {
+      this.$element[0].addEventListener(
+        'DOMAttrModified',
+        self._syncA,
+        false
+      );
+      this.$element[0].addEventListener(
+        'DOMNodeInserted',
+        self._syncS,
+        false
+      );
+      this.$element[0].addEventListener(
+        'DOMNodeRemoved',
+        self._syncS,
+        false
+      );
+    }
+  };
+
+  Select2.prototype._registerDataEvents = function () {
+    var self = this;
+
+    this.dataAdapter.on('*', function (name, params) {
+      self.trigger(name, params);
+    });
+  };
+
+  Select2.prototype._registerSelectionEvents = function () {
+    var self = this;
+    var nonRelayEvents = ['toggle', 'focus'];
+
+    this.selection.on('toggle', function () {
+      self.toggleDropdown();
+    });
+
+    this.selection.on('focus', function (params) {
+      self.focus(params);
+    });
+
+    this.selection.on('*', function (name, params) {
+      if ($.inArray(name, nonRelayEvents) !== -1) {
+        return;
+      }
+
+      self.trigger(name, params);
+    });
+  };
+
+  Select2.prototype._registerDropdownEvents = function () {
+    var self = this;
+
+    this.dropdown.on('*', function (name, params) {
+      self.trigger(name, params);
+    });
+  };
+
+  Select2.prototype._registerResultsEvents = function () {
+    var self = this;
+
+    this.results.on('*', function (name, params) {
+      self.trigger(name, params);
+    });
+  };
+
+  Select2.prototype._registerEvents = function () {
+    var self = this;
+
+    this.on('open', function () {
+      self.$container.addClass('select2-container--open');
+    });
+
+    this.on('close', function () {
+      self.$container.removeClass('select2-container--open');
+    });
+
+    this.on('enable', function () {
+      self.$container.removeClass('select2-container--disabled');
+    });
+
+    this.on('disable', function () {
+      self.$container.addClass('select2-container--disabled');
+    });
+
+    this.on('blur', function () {
+      self.$container.removeClass('select2-container--focus');
+    });
+
+    this.on('query', function (params) {
+      if (!self.isOpen()) {
+        self.trigger('open', {});
+      }
+
+      this.dataAdapter.query(params, function (data) {
+        self.trigger('results:all', {
+          data: data,
+          query: params
+        });
+      });
+    });
+
+    this.on('query:append', function (params) {
+      this.dataAdapter.query(params, function (data) {
+        self.trigger('results:append', {
+          data: data,
+          query: params
+        });
+      });
+    });
+
+    this.on('keypress', function (evt) {
+      var key = evt.which;
+
+      if (self.isOpen()) {
+        if (key === KEYS.ESC || key === KEYS.TAB ||
+            (key === KEYS.UP && evt.altKey)) {
+          self.close(evt);
+
+          evt.preventDefault();
+        } else if (key === KEYS.ENTER) {
+          self.trigger('results:select', {});
+
+          evt.preventDefault();
+        } else if ((key === KEYS.SPACE && evt.ctrlKey)) {
+          self.trigger('results:toggle', {});
+
+          evt.preventDefault();
+        } else if (key === KEYS.UP) {
+          self.trigger('results:previous', {});
+
+          evt.preventDefault();
+        } else if (key === KEYS.DOWN) {
+          self.trigger('results:next', {});
+
+          evt.preventDefault();
+        }
+      } else {
+        if (key === KEYS.ENTER || key === KEYS.SPACE ||
+            (key === KEYS.DOWN && evt.altKey)) {
+          self.open();
+
+          evt.preventDefault();
+        }
+      }
+    });
+  };
+
+  Select2.prototype._syncAttributes = function () {
+    this.options.set('disabled', this.$element.prop('disabled'));
+
+    if (this.isDisabled()) {
+      if (this.isOpen()) {
+        this.close();
+      }
+
+      this.trigger('disable', {});
+    } else {
+      this.trigger('enable', {});
+    }
+  };
+
+  Select2.prototype._isChangeMutation = function (evt, mutations) {
+    var changed = false;
+    var self = this;
+
+    // Ignore any mutation events raised for elements that aren't options or
+    // optgroups. This handles the case when the select element is destroyed
+    if (
+      evt && evt.target && (
+        evt.target.nodeName !== 'OPTION' && evt.target.nodeName !== 'OPTGROUP'
+      )
+    ) {
+      return;
+    }
+
+    if (!mutations) {
+      // If mutation events aren't supported, then we can only assume that the
+      // change affected the selections
+      changed = true;
+    } else if (mutations.addedNodes && mutations.addedNodes.length > 0) {
+      for (var n = 0; n < mutations.addedNodes.length; n++) {
+        var node = mutations.addedNodes[n];
+
+        if (node.selected) {
+          changed = true;
+        }
+      }
+    } else if (mutations.removedNodes && mutations.removedNodes.length > 0) {
+      changed = true;
+    } else if ($.isArray(mutations)) {
+      $.each(mutations, function(evt, mutation) {
+        if (self._isChangeMutation(evt, mutation)) {
+          // We've found a change mutation.
+          // Let's escape from the loop and continue
+          changed = true;
+          return false;
+        }
+      });
+    }
+    return changed;
+  };
+
+  Select2.prototype._syncSubtree = function (evt, mutations) {
+    var changed = this._isChangeMutation(evt, mutations);
+    var self = this;
+
+    // Only re-pull the data if we think there is a change
+    if (changed) {
+      this.dataAdapter.current(function (currentData) {
+        self.trigger('selection:update', {
+          data: currentData
+        });
+      });
+    }
+  };
+
+  /**
+   * Override the trigger method to automatically trigger pre-events when
+   * there are events that can be prevented.
+   */
+  Select2.prototype.trigger = function (name, args) {
+    var actualTrigger = Select2.__super__.trigger;
+    var preTriggerMap = {
+      'open': 'opening',
+      'close': 'closing',
+      'select': 'selecting',
+      'unselect': 'unselecting',
+      'clear': 'clearing'
+    };
+
+    if (args === undefined) {
+      args = {};
+    }
+
+    if (name in preTriggerMap) {
+      var preTriggerName = preTriggerMap[name];
+      var preTriggerArgs = {
+        prevented: false,
+        name: name,
+        args: args
+      };
+
+      actualTrigger.call(this, preTriggerName, preTriggerArgs);
+
+      if (preTriggerArgs.prevented) {
+        args.prevented = true;
+
+        return;
+      }
+    }
+
+    actualTrigger.call(this, name, args);
+  };
+
+  Select2.prototype.toggleDropdown = function () {
+    if (this.isDisabled()) {
+      return;
+    }
+
+    if (this.isOpen()) {
+      this.close();
+    } else {
+      this.open();
+    }
+  };
+
+  Select2.prototype.open = function () {
+    if (this.isOpen()) {
+      return;
+    }
+
+    if (this.isDisabled()) {
+      return;
+    }
+
+    this.trigger('query', {});
+  };
+
+  Select2.prototype.close = function (evt) {
+    if (!this.isOpen()) {
+      return;
+    }
+
+    this.trigger('close', { originalEvent : evt });
+  };
+
+  /**
+   * Helper method to abstract the "enabled" (not "disabled") state of this
+   * object.
+   *
+   * @return {true} if the instance is not disabled.
+   * @return {false} if the instance is disabled.
+   */
+  Select2.prototype.isEnabled = function () {
+    return !this.isDisabled();
+  };
+
+  /**
+   * Helper method to abstract the "disabled" state of this object.
+   *
+   * @return {true} if the disabled option is true.
+   * @return {false} if the disabled option is false.
+   */
+  Select2.prototype.isDisabled = function () {
+    return this.options.get('disabled');
+  };
+
+  Select2.prototype.isOpen = function () {
+    return this.$container.hasClass('select2-container--open');
+  };
+
+  Select2.prototype.hasFocus = function () {
+    return this.$container.hasClass('select2-container--focus');
+  };
+
+  Select2.prototype.focus = function (data) {
+    // No need to re-trigger focus events if we are already focused
+    if (this.hasFocus()) {
+      return;
+    }
+
+    this.$container.addClass('select2-container--focus');
+    this.trigger('focus', {});
+  };
+
+  Select2.prototype.enable = function (args) {
+    if (this.options.get('debug') && window.console && console.warn) {
+      console.warn(
+        'Select2: The `select2("enable")` method has been deprecated and will' +
+        ' be removed in later Select2 versions. Use $element.prop("disabled")' +
+        ' instead.'
+      );
+    }
+
+    if (args == null || args.length === 0) {
+      args = [true];
+    }
+
+    var disabled = !args[0];
+
+    this.$element.prop('disabled', disabled);
+  };
+
+  Select2.prototype.data = function () {
+    if (this.options.get('debug') &&
+        arguments.length > 0 && window.console && console.warn) {
+      console.warn(
+        'Select2: Data can no longer be set using `select2("data")`. You ' +
+        'should consider setting the value instead using `$element.val()`.'
+      );
+    }
+
+    var data = [];
+
+    this.dataAdapter.current(function (currentData) {
+      data = currentData;
+    });
+
+    return data;
+  };
+
+  Select2.prototype.val = function (args) {
+    if (this.options.get('debug') && window.console && console.warn) {
+      console.warn(
+        'Select2: The `select2("val")` method has been deprecated and will be' +
+        ' removed in later Select2 versions. Use $element.val() instead.'
+      );
+    }
+
+    if (args == null || args.length === 0) {
+      return this.$element.val();
+    }
+
+    var newVal = args[0];
+
+    if ($.isArray(newVal)) {
+      newVal = $.map(newVal, function (obj) {
+        return obj.toString();
+      });
+    }
+
+    this.$element.val(newVal).trigger('input').trigger('change');
+  };
+
+  Select2.prototype.destroy = function () {
+    this.$container.remove();
+
+    if (this.$element[0].detachEvent) {
+      this.$element[0].detachEvent('onpropertychange', this._syncA);
+    }
+
+    if (this._observer != null) {
+      this._observer.disconnect();
+      this._observer = null;
+    } else if (this.$element[0].removeEventListener) {
+      this.$element[0]
+        .removeEventListener('DOMAttrModified', this._syncA, false);
+      this.$element[0]
+        .removeEventListener('DOMNodeInserted', this._syncS, false);
+      this.$element[0]
+        .removeEventListener('DOMNodeRemoved', this._syncS, false);
+    }
+
+    this._syncA = null;
+    this._syncS = null;
+
+    this.$element.off('.select2');
+    this.$element.attr('tabindex',
+    Utils.GetData(this.$element[0], 'old-tabindex'));
+
+    this.$element.removeClass('select2-hidden-accessible');
+    this.$element.attr('aria-hidden', 'false');
+    Utils.RemoveData(this.$element[0]);
+    this.$element.removeData('select2');
+
+    this.dataAdapter.destroy();
+    this.selection.destroy();
+    this.dropdown.destroy();
+    this.results.destroy();
+
+    this.dataAdapter = null;
+    this.selection = null;
+    this.dropdown = null;
+    this.results = null;
+  };
+
+  Select2.prototype.render = function () {
+    var $container = $(
+      '<span class="select2 select2-container">' +
+        '<span class="selection"></span>' +
+        '<span class="dropdown-wrapper" aria-hidden="true"></span>' +
+      '</span>'
+    );
+
+    $container.attr('dir', this.options.get('dir'));
+
+    this.$container = $container;
+
+    this.$container.addClass('select2-container--' + this.options.get('theme'));
+
+    Utils.StoreData($container[0], 'element', this.$element);
+
+    return $container;
+  };
+
+  return Select2;
+});
+
+S2.define('jquery-mousewheel',[
+  'jquery'
+], function ($) {
+  // Used to shim jQuery.mousewheel for non-full builds.
+  return $;
+});
+
+S2.define('jquery.select2',[
+  'jquery',
+  'jquery-mousewheel',
+
+  './select2/core',
+  './select2/defaults',
+  './select2/utils'
+], function ($, _, Select2, Defaults, Utils) {
+  if ($.fn.select2 == null) {
+    // All methods that should return the element
+    var thisMethods = ['open', 'close', 'destroy'];
+
+    $.fn.select2 = function (options) {
+      options = options || {};
+
+      if (typeof options === 'object') {
+        this.each(function () {
+          var instanceOptions = $.extend(true, {}, options);
+
+          var instance = new Select2($(this), instanceOptions);
+        });
+
+        return this;
+      } else if (typeof options === 'string') {
+        var ret;
+        var args = Array.prototype.slice.call(arguments, 1);
+
+        this.each(function () {
+          var instance = Utils.GetData(this, 'select2');
+
+          if (instance == null && window.console && console.error) {
+            console.error(
+              'The select2(\'' + options + '\') method was called on an ' +
+              'element that is not using Select2.'
+            );
+          }
+
+          ret = instance[options].apply(instance, args);
+        });
+
+        // Check if we should be returning `this`
+        if ($.inArray(options, thisMethods) > -1) {
+          return this;
+        }
+
+        return ret;
+      } else {
+        throw new Error('Invalid arguments for Select2: ' + options);
+      }
+    };
+  }
+
+  if ($.fn.select2.defaults == null) {
+    $.fn.select2.defaults = Defaults;
+  }
+
+  return Select2;
+});
+
+  // Return the AMD loader configuration so it can be used outside of this file
+  return {
+    define: S2.define,
+    require: S2.require
+  };
+}());
+
+  // Autoload the jQuery bindings
+  // We know that all of the modules exist above this, so we're safe
+  var select2 = S2.require('jquery.select2');
+
+  // Hold the AMD module references on the jQuery function that was just loaded
+  // This allows Select2 to use the internal loader outside of this file, such
+  // as in the language files.
+  jQuery.fn.select2.amd = S2;
+
+  // Return the Select2 instance for anyone who is importing it.
+  return select2;
+}));
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/select2/select2.min.css b/ruoyi-admin/src/main/resources/static/ajax/libs/select2/select2.min.css
new file mode 100644
index 0000000..7c18ad5
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/select2/select2.min.css
@@ -0,0 +1 @@
+.select2-container{box-sizing:border-box;display:inline-block;margin:0;position:relative;vertical-align:middle}.select2-container .select2-selection--single{box-sizing:border-box;cursor:pointer;display:block;height:28px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--single .select2-selection__rendered{display:block;padding-left:8px;padding-right:20px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-selection--single .select2-selection__clear{position:relative}.select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered{padding-right:8px;padding-left:20px}.select2-container .select2-selection--multiple{box-sizing:border-box;cursor:pointer;display:block;min-height:32px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--multiple .select2-selection__rendered{display:inline-block;overflow:hidden;padding-left:8px;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-search--inline{float:left}.select2-container .select2-search--inline .select2-search__field{box-sizing:border-box;border:none;font-size:100%;margin-top:5px;padding:0}.select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-dropdown{background-color:white;border:1px solid #aaa;border-radius:4px;box-sizing:border-box;display:block;position:absolute;left:-100000px;width:100%;z-index:1051}.select2-results{display:block}.select2-results__options{list-style:none;margin:0;padding:0}.select2-results__option{padding:6px;user-select:none;-webkit-user-select:none}.select2-results__option[aria-selected]{cursor:pointer}.select2-container--open .select2-dropdown{left:0}.select2-container--open .select2-dropdown--above{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--open .select2-dropdown--below{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-search--dropdown{display:block;padding:4px}.select2-search--dropdown .select2-search__field{padding:4px;width:100%;box-sizing:border-box}.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-search--dropdown.select2-search--hide{display:none}.select2-close-mask{border:0;margin:0;padding:0;display:block;position:fixed;left:0;top:0;min-height:100%;min-width:100%;height:auto;width:auto;opacity:0;z-index:99;background-color:#fff;filter:alpha(opacity=0)}.select2-hidden-accessible{border:0 !important;clip:rect(0 0 0 0) !important;-webkit-clip-path:inset(50%) !important;clip-path:inset(50%) !important;height:1px !important;overflow:hidden !important;padding:0 !important;position:absolute !important;width:1px !important;white-space:nowrap !important}.select2-container--default .select2-selection--single{background-color:#fff;border:1px solid #aaa;border-radius:4px}.select2-container--default .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px}.select2-container--default .select2-selection--single .select2-selection__clear{cursor:pointer;float:right;font-weight:bold}.select2-container--default .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--default .select2-selection--single .select2-selection__arrow{height:26px;position:absolute;top:1px;right:1px;width:20px}.select2-container--default .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__clear{float:left}.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__arrow{left:1px;right:auto}.select2-container--default.select2-container--disabled .select2-selection--single{background-color:#eee;cursor:default}.select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear{display:none}.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--default .select2-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text}.select2-container--default .select2-selection--multiple .select2-selection__rendered{box-sizing:border-box;list-style:none;margin:0;padding:0 5px;width:100%}.select2-container--default .select2-selection--multiple .select2-selection__rendered li{list-style:none}.select2-container--default .select2-selection--multiple .select2-selection__clear{cursor:pointer;float:right;font-weight:bold;margin-top:5px;margin-right:10px;padding:1px}.select2-container--default .select2-selection--multiple .select2-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove{color:#999;cursor:pointer;display:inline-block;font-weight:bold;margin-right:2px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover{color:#333}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice,.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-search--inline{float:right}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice{margin-left:5px;margin-right:auto}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.select2-container--default.select2-container--focus .select2-selection--multiple{border:solid black 1px;outline:0}.select2-container--default.select2-container--disabled .select2-selection--multiple{background-color:#eee;cursor:default}.select2-container--default.select2-container--disabled .select2-selection__choice__remove{display:none}.select2-container--default.select2-container--open.select2-container--above .select2-selection--single,.select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple{border-top-left-radius:0;border-top-right-radius:0}.select2-container--default.select2-container--open.select2-container--below .select2-selection--single,.select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--default .select2-search--dropdown .select2-search__field{border:1px solid #aaa}.select2-container--default .select2-search--inline .select2-search__field{background:transparent;border:none;outline:0;box-shadow:none;-webkit-appearance:textfield}.select2-container--default .select2-results>.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--default .select2-results__option[role=group]{padding:0}.select2-container--default .select2-results__option[aria-disabled=true]{color:#999}.select2-container--default .select2-results__option[aria-selected=true]{background-color:#ddd}.select2-container--default .select2-results__option .select2-results__option{padding-left:1em}.select2-container--default .select2-results__option .select2-results__option .select2-results__group{padding-left:0}.select2-container--default .select2-results__option .select2-results__option .select2-results__option{margin-left:-1em;padding-left:2em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-2em;padding-left:3em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-3em;padding-left:4em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-4em;padding-left:5em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-5em;padding-left:6em}.select2-container--default .select2-results__option--highlighted[aria-selected]{background-color:#5897fb;color:white}.select2-container--default .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--classic .select2-selection--single{background-color:#f7f7f7;border:1px solid #aaa;border-radius:4px;outline:0;background-image:-webkit-linear-gradient(top, #fff 50%, #eee 100%);background-image:-o-linear-gradient(top, #fff 50%, #eee 100%);background-image:linear-gradient(to bottom, #fff 50%, #eee 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0)}.select2-container--classic .select2-selection--single:focus{border:1px solid #5897fb}.select2-container--classic .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px}.select2-container--classic .select2-selection--single .select2-selection__clear{cursor:pointer;float:right;font-weight:bold;margin-right:10px}.select2-container--classic .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--classic .select2-selection--single .select2-selection__arrow{background-color:#ddd;border:none;border-left:1px solid #aaa;border-top-right-radius:4px;border-bottom-right-radius:4px;height:26px;position:absolute;top:1px;right:1px;width:20px;background-image:-webkit-linear-gradient(top, #eee 50%, #ccc 100%);background-image:-o-linear-gradient(top, #eee 50%, #ccc 100%);background-image:linear-gradient(to bottom, #eee 50%, #ccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFCCCCCC', GradientType=0)}.select2-container--classic .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__clear{float:left}.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__arrow{border:none;border-right:1px solid #aaa;border-radius:0;border-top-left-radius:4px;border-bottom-left-radius:4px;left:1px;right:auto}.select2-container--classic.select2-container--open .select2-selection--single{border:1px solid #5897fb}.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow{background:transparent;border:none}.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--classic.select2-container--open.select2-container--above .select2-selection--single{border-top:none;border-top-left-radius:0;border-top-right-radius:0;background-image:-webkit-linear-gradient(top, #fff 0%, #eee 50%);background-image:-o-linear-gradient(top, #fff 0%, #eee 50%);background-image:linear-gradient(to bottom, #fff 0%, #eee 50%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0)}.select2-container--classic.select2-container--open.select2-container--below .select2-selection--single{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0;background-image:-webkit-linear-gradient(top, #eee 50%, #fff 100%);background-image:-o-linear-gradient(top, #eee 50%, #fff 100%);background-image:linear-gradient(to bottom, #eee 50%, #fff 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFFFFFFF', GradientType=0)}.select2-container--classic .select2-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text;outline:0}.select2-container--classic .select2-selection--multiple:focus{border:1px solid #5897fb}.select2-container--classic .select2-selection--multiple .select2-selection__rendered{list-style:none;margin:0;padding:0 5px}.select2-container--classic .select2-selection--multiple .select2-selection__clear{display:none}.select2-container--classic .select2-selection--multiple .select2-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove{color:#888;cursor:pointer;display:inline-block;font-weight:bold;margin-right:2px}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover{color:#555}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice{float:right;margin-left:5px;margin-right:auto}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.select2-container--classic.select2-container--open .select2-selection--multiple{border:1px solid #5897fb}.select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--classic .select2-search--dropdown .select2-search__field{border:1px solid #aaa;outline:0}.select2-container--classic .select2-search--inline .select2-search__field{outline:0;box-shadow:none}.select2-container--classic .select2-dropdown{background-color:#fff;border:1px solid transparent}.select2-container--classic .select2-dropdown--above{border-bottom:none}.select2-container--classic .select2-dropdown--below{border-top:none}.select2-container--classic .select2-results>.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--classic .select2-results__option[role=group]{padding:0}.select2-container--classic .select2-results__option[aria-disabled=true]{color:grey}.select2-container--classic .select2-results__option--highlighted[aria-selected]{background-color:#3875d7;color:#fff}.select2-container--classic .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--classic.select2-container--open .select2-dropdown{border-color:#5897fb}
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/select2/select2.min.js b/ruoyi-admin/src/main/resources/static/ajax/libs/select2/select2.min.js
new file mode 100644
index 0000000..fe769ed
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/select2/select2.min.js
@@ -0,0 +1,8 @@
+/*!
+ * Select2 4.0.13
+ * https://select2.github.io
+ *
+ * Released under the MIT license
+ * https://github.com/select2/select2/blob/master/LICENSE.md
+ */
+(function(factory){if(typeof define==="function"&&define.amd){define(["jquery"],factory)}else{if(typeof module==="object"&&module.exports){module.exports=function(root,jQuery){if(jQuery===undefined){if(typeof window!=="undefined"){jQuery=require("jquery")}else{jQuery=require("jquery")(root)}}factory(jQuery);return jQuery}}else{factory(jQuery)}}}(function(jQuery){var S2=(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd){var S2=jQuery.fn.select2.amd}var S2;(function(){if(!S2||!S2.requirejs){if(!S2){S2={}}else{require=S2}var requirejs,require,define;(function(undef){var main,req,makeMap,handlers,defined={},waiting={},config={},defining={},hasOwn=Object.prototype.hasOwnProperty,aps=[].slice,jsSuffixRegExp=/\.js$/;function hasProp(obj,prop){return hasOwn.call(obj,prop)}function normalize(name,baseName){var nameParts,nameSegment,mapValue,foundMap,lastIndex,foundI,foundStarMap,starI,i,j,part,normalizedBaseParts,baseParts=baseName&&baseName.split("/"),map=config.map,starMap=(map&&map["*"])||{};if(name){name=name.split("/");lastIndex=name.length-1;if(config.nodeIdCompat&&jsSuffixRegExp.test(name[lastIndex])){name[lastIndex]=name[lastIndex].replace(jsSuffixRegExp,"")}if(name[0].charAt(0)==="."&&baseParts){normalizedBaseParts=baseParts.slice(0,baseParts.length-1);name=normalizedBaseParts.concat(name)}for(i=0;i<name.length;i++){part=name[i];if(part==="."){name.splice(i,1);i-=1}else{if(part===".."){if(i===0||(i===1&&name[2]==="..")||name[i-1]===".."){continue}else{if(i>0){name.splice(i-1,2);i-=2}}}}}name=name.join("/")}if((baseParts||starMap)&&map){nameParts=name.split("/");for(i=nameParts.length;i>0;i-=1){nameSegment=nameParts.slice(0,i).join("/");if(baseParts){for(j=baseParts.length;j>0;j-=1){mapValue=map[baseParts.slice(0,j).join("/")];if(mapValue){mapValue=mapValue[nameSegment];if(mapValue){foundMap=mapValue;foundI=i;break}}}}if(foundMap){break}if(!foundStarMap&&starMap&&starMap[nameSegment]){foundStarMap=starMap[nameSegment];starI=i}}if(!foundMap&&foundStarMap){foundMap=foundStarMap;foundI=starI}if(foundMap){nameParts.splice(0,foundI,foundMap);name=nameParts.join("/")}}return name}function makeRequire(relName,forceSync){return function(){var args=aps.call(arguments,0);if(typeof args[0]!=="string"&&args.length===1){args.push(null)}return req.apply(undef,args.concat([relName,forceSync]))}}function makeNormalize(relName){return function(name){return normalize(name,relName)}}function makeLoad(depName){return function(value){defined[depName]=value}}function callDep(name){if(hasProp(waiting,name)){var args=waiting[name];delete waiting[name];defining[name]=true;main.apply(undef,args)}if(!hasProp(defined,name)&&!hasProp(defining,name)){throw new Error("No "+name)}return defined[name]}function splitPrefix(name){var prefix,index=name?name.indexOf("!"):-1;if(index>-1){prefix=name.substring(0,index);name=name.substring(index+1,name.length)}return[prefix,name]}function makeRelParts(relName){return relName?splitPrefix(relName):[]}makeMap=function(name,relParts){var plugin,parts=splitPrefix(name),prefix=parts[0],relResourceName=relParts[1];name=parts[1];if(prefix){prefix=normalize(prefix,relResourceName);plugin=callDep(prefix)}if(prefix){if(plugin&&plugin.normalize){name=plugin.normalize(name,makeNormalize(relResourceName))}else{name=normalize(name,relResourceName)}}else{name=normalize(name,relResourceName);parts=splitPrefix(name);prefix=parts[0];name=parts[1];if(prefix){plugin=callDep(prefix)}}return{f:prefix?prefix+"!"+name:name,n:name,pr:prefix,p:plugin}};function makeConfig(name){return function(){return(config&&config.config&&config.config[name])||{}}}handlers={require:function(name){return makeRequire(name)},exports:function(name){var e=defined[name];if(typeof e!=="undefined"){return e}else{return(defined[name]={})}},module:function(name){return{id:name,uri:"",exports:defined[name],config:makeConfig(name)}}};main=function(name,deps,callback,relName){var cjsModule,depName,ret,map,i,relParts,args=[],callbackType=typeof callback,usingExports;relName=relName||name;relParts=makeRelParts(relName);if(callbackType==="undefined"||callbackType==="function"){deps=!deps.length&&callback.length?["require","exports","module"]:deps;for(i=0;i<deps.length;i+=1){map=makeMap(deps[i],relParts);depName=map.f;if(depName==="require"){args[i]=handlers.require(name)}else{if(depName==="exports"){args[i]=handlers.exports(name);usingExports=true}else{if(depName==="module"){cjsModule=args[i]=handlers.module(name)}else{if(hasProp(defined,depName)||hasProp(waiting,depName)||hasProp(defining,depName)){args[i]=callDep(depName)}else{if(map.p){map.p.load(map.n,makeRequire(relName,true),makeLoad(depName),{});args[i]=defined[depName]}else{throw new Error(name+" missing "+depName)}}}}}}ret=callback?callback.apply(defined[name],args):undefined;if(name){if(cjsModule&&cjsModule.exports!==undef&&cjsModule.exports!==defined[name]){defined[name]=cjsModule.exports}else{if(ret!==undef||!usingExports){defined[name]=ret}}}}else{if(name){defined[name]=callback}}};requirejs=require=req=function(deps,callback,relName,forceSync,alt){if(typeof deps==="string"){if(handlers[deps]){return handlers[deps](callback)}return callDep(makeMap(deps,makeRelParts(callback)).f)}else{if(!deps.splice){config=deps;if(config.deps){req(config.deps,config.callback)}if(!callback){return}if(callback.splice){deps=callback;callback=relName;relName=null}else{deps=undef}}}callback=callback||function(){};if(typeof relName==="function"){relName=forceSync;forceSync=alt}if(forceSync){main(undef,deps,callback,relName)}else{setTimeout(function(){main(undef,deps,callback,relName)},4)}return req};req.config=function(cfg){return req(cfg)};requirejs._defined=defined;define=function(name,deps,callback){if(typeof name!=="string"){throw new Error("See almond README: incorrect module build, no module name")}if(!deps.splice){callback=deps;deps=[]}if(!hasProp(defined,name)&&!hasProp(waiting,name)){waiting[name]=[name,deps,callback]}};define.amd={jQuery:true}}());S2.requirejs=requirejs;S2.require=require;S2.define=define}}());S2.define("almond",function(){});S2.define("jquery",[],function(){var _$=jQuery||$;if(_$==null&&console&&console.error){console.error("Select2: An instance of jQuery or a jQuery-compatible library was not "+"found. Make sure that you are including jQuery before Select2 on your "+"web page.")}return _$});S2.define("select2/utils",["jquery"],function($){var Utils={};Utils.Extend=function(ChildClass,SuperClass){var __hasProp={}.hasOwnProperty;function BaseConstructor(){this.constructor=ChildClass}for(var key in SuperClass){if(__hasProp.call(SuperClass,key)){ChildClass[key]=SuperClass[key]}}BaseConstructor.prototype=SuperClass.prototype;ChildClass.prototype=new BaseConstructor();ChildClass.__super__=SuperClass.prototype;return ChildClass};function getMethods(theClass){var proto=theClass.prototype;var methods=[];for(var methodName in proto){var m=proto[methodName];if(typeof m!=="function"){continue}if(methodName==="constructor"){continue}methods.push(methodName)}return methods}Utils.Decorate=function(SuperClass,DecoratorClass){var decoratedMethods=getMethods(DecoratorClass);var superMethods=getMethods(SuperClass);function DecoratedClass(){var unshift=Array.prototype.unshift;var argCount=DecoratorClass.prototype.constructor.length;var calledConstructor=SuperClass.prototype.constructor;if(argCount>0){unshift.call(arguments,SuperClass.prototype.constructor);calledConstructor=DecoratorClass.prototype.constructor}calledConstructor.apply(this,arguments)}DecoratorClass.displayName=SuperClass.displayName;function ctr(){this.constructor=DecoratedClass}DecoratedClass.prototype=new ctr();for(var m=0;m<superMethods.length;m++){var superMethod=superMethods[m];DecoratedClass.prototype[superMethod]=SuperClass.prototype[superMethod]}var calledMethod=function(methodName){var originalMethod=function(){};if(methodName in DecoratedClass.prototype){originalMethod=DecoratedClass.prototype[methodName]}var decoratedMethod=DecoratorClass.prototype[methodName];return function(){var unshift=Array.prototype.unshift;unshift.call(arguments,originalMethod);return decoratedMethod.apply(this,arguments)}};for(var d=0;d<decoratedMethods.length;d++){var decoratedMethod=decoratedMethods[d];DecoratedClass.prototype[decoratedMethod]=calledMethod(decoratedMethod)}return DecoratedClass};var Observable=function(){this.listeners={}};Observable.prototype.on=function(event,callback){this.listeners=this.listeners||{};if(event in this.listeners){this.listeners[event].push(callback)}else{this.listeners[event]=[callback]}};Observable.prototype.trigger=function(event){var slice=Array.prototype.slice;var params=slice.call(arguments,1);this.listeners=this.listeners||{};if(params==null){params=[]}if(params.length===0){params.push({})}params[0]._type=event;if(event in this.listeners){this.invoke(this.listeners[event],slice.call(arguments,1))}if("*" in this.listeners){this.invoke(this.listeners["*"],arguments)}};Observable.prototype.invoke=function(listeners,params){for(var i=0,len=listeners.length;i<len;i++){listeners[i].apply(this,params)}};Utils.Observable=Observable;Utils.generateChars=function(length){var chars="";for(var i=0;i<length;i++){var randomChar=Math.floor(Math.random()*36);chars+=randomChar.toString(36)}return chars};Utils.bind=function(func,context){return function(){func.apply(context,arguments)}};Utils._convertData=function(data){for(var originalKey in data){var keys=originalKey.split("-");var dataLevel=data;if(keys.length===1){continue}for(var k=0;k<keys.length;k++){var key=keys[k];key=key.substring(0,1).toLowerCase()+key.substring(1);if(!(key in dataLevel)){dataLevel[key]={}}if(k==keys.length-1){dataLevel[key]=data[originalKey]}dataLevel=dataLevel[key]}delete data[originalKey]}return data};Utils.hasScroll=function(index,el){var $el=$(el);var overflowX=el.style.overflowX;var overflowY=el.style.overflowY;if(overflowX===overflowY&&(overflowY==="hidden"||overflowY==="visible")){return false}if(overflowX==="scroll"||overflowY==="scroll"){return true}return($el.innerHeight()<el.scrollHeight||$el.innerWidth()<el.scrollWidth)};Utils.escapeMarkup=function(markup){var replaceMap={"\\":"&#92;","&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","/":"&#47;"};if(typeof markup!=="string"){return markup}return String(markup).replace(/[&<>"'\/\\]/g,function(match){return replaceMap[match]})};Utils.appendMany=function($element,$nodes){if($.fn.jquery.substr(0,3)==="1.7"){var $jqNodes=$();$.map($nodes,function(node){$jqNodes=$jqNodes.add(node)});$nodes=$jqNodes}$element.append($nodes)};Utils.__cache={};var id=0;Utils.GetUniqueElementId=function(element){var select2Id=element.getAttribute("data-select2-id");if(select2Id==null){if(element.id){select2Id=element.id;element.setAttribute("data-select2-id",select2Id)}else{element.setAttribute("data-select2-id",++id);select2Id=id.toString()}}return select2Id};Utils.StoreData=function(element,name,value){var id=Utils.GetUniqueElementId(element);if(!Utils.__cache[id]){Utils.__cache[id]={}}Utils.__cache[id][name]=value};Utils.GetData=function(element,name){var id=Utils.GetUniqueElementId(element);if(name){if(Utils.__cache[id]){if(Utils.__cache[id][name]!=null){return Utils.__cache[id][name]}return $(element).data(name)}return $(element).data(name)}else{return Utils.__cache[id]}};Utils.RemoveData=function(element){var id=Utils.GetUniqueElementId(element);if(Utils.__cache[id]!=null){delete Utils.__cache[id]}element.removeAttribute("data-select2-id")};return Utils});S2.define("select2/results",["jquery","./utils"],function($,Utils){function Results($element,options,dataAdapter){this.$element=$element;this.data=dataAdapter;this.options=options;Results.__super__.constructor.call(this)}Utils.Extend(Results,Utils.Observable);Results.prototype.render=function(){var $results=$('<ul class="select2-results__options" role="listbox"></ul>');if(this.options.get("multiple")){$results.attr("aria-multiselectable","true")}this.$results=$results;return $results};Results.prototype.clear=function(){this.$results.empty()};Results.prototype.displayMessage=function(params){var escapeMarkup=this.options.get("escapeMarkup");this.clear();this.hideLoading();var $message=$('<li role="alert" aria-live="assertive"'+' class="select2-results__option"></li>');var message=this.options.get("translations").get(params.message);$message.append(escapeMarkup(message(params.args)));$message[0].className+=" select2-results__message";this.$results.append($message)};Results.prototype.hideMessages=function(){this.$results.find(".select2-results__message").remove()};Results.prototype.append=function(data){this.hideLoading();var $options=[];if(data.results==null||data.results.length===0){if(this.$results.children().length===0){this.trigger("results:message",{message:"noResults"})}return}data.results=this.sort(data.results);for(var d=0;d<data.results.length;d++){var item=data.results[d];var $option=this.option(item);$options.push($option)}this.$results.append($options)};Results.prototype.position=function($results,$dropdown){var $resultsContainer=$dropdown.find(".select2-results");$resultsContainer.append($results)};Results.prototype.sort=function(data){var sorter=this.options.get("sorter");return sorter(data)};Results.prototype.highlightFirstItem=function(){var $options=this.$results.find(".select2-results__option[aria-selected]");var $selected=$options.filter("[aria-selected=true]");if($selected.length>0){$selected.first().trigger("mouseenter")}else{$options.first().trigger("mouseenter")}this.ensureHighlightVisible()};Results.prototype.setClasses=function(){var self=this;this.data.current(function(selected){var selectedIds=$.map(selected,function(s){return s.id.toString()});var $options=self.$results.find(".select2-results__option[aria-selected]");$options.each(function(){var $option=$(this);var item=Utils.GetData(this,"data");var id=""+item.id;if((item.element!=null&&item.element.selected)||(item.element==null&&$.inArray(id,selectedIds)>-1)){$option.attr("aria-selected","true")}else{$option.attr("aria-selected","false")}})})};Results.prototype.showLoading=function(params){this.hideLoading();var loadingMore=this.options.get("translations").get("searching");var loading={disabled:true,loading:true,text:loadingMore(params)};var $loading=this.option(loading);$loading.className+=" loading-results";this.$results.prepend($loading)};Results.prototype.hideLoading=function(){this.$results.find(".loading-results").remove()};Results.prototype.option=function(data){var option=document.createElement("li");option.className="select2-results__option";var attrs={"role":"option","aria-selected":"false"};var matches=window.Element.prototype.matches||window.Element.prototype.msMatchesSelector||window.Element.prototype.webkitMatchesSelector;if((data.element!=null&&matches.call(data.element,":disabled"))||(data.element==null&&data.disabled)){delete attrs["aria-selected"];attrs["aria-disabled"]="true"}if(data.id==null){delete attrs["aria-selected"]}if(data._resultId!=null){option.id=data._resultId}if(data.title){option.title=data.title}if(data.children){attrs.role="group";attrs["aria-label"]=data.text;delete attrs["aria-selected"]}for(var attr in attrs){var val=attrs[attr];option.setAttribute(attr,val)}if(data.children){var $option=$(option);var label=document.createElement("strong");label.className="select2-results__group";var $label=$(label);this.template(data,label);var $children=[];for(var c=0;c<data.children.length;c++){var child=data.children[c];var $child=this.option(child);$children.push($child)}var $childrenContainer=$("<ul></ul>",{"class":"select2-results__options select2-results__options--nested"});$childrenContainer.append($children);$option.append(label);$option.append($childrenContainer)}else{this.template(data,option)}Utils.StoreData(option,"data",data);return option};Results.prototype.bind=function(container,$container){var self=this;var id=container.id+"-results";this.$results.attr("id",id);container.on("results:all",function(params){self.clear();self.append(params.data);if(container.isOpen()){self.setClasses();self.highlightFirstItem()}});container.on("results:append",function(params){self.append(params.data);if(container.isOpen()){self.setClasses()}});container.on("query",function(params){self.hideMessages();self.showLoading(params)});container.on("select",function(){if(!container.isOpen()){return}self.setClasses();if(self.options.get("scrollAfterSelect")){self.highlightFirstItem()}});container.on("unselect",function(){if(!container.isOpen()){return}self.setClasses();if(self.options.get("scrollAfterSelect")){self.highlightFirstItem()}});container.on("open",function(){self.$results.attr("aria-expanded","true");self.$results.attr("aria-hidden","false");self.setClasses();self.ensureHighlightVisible()});container.on("close",function(){self.$results.attr("aria-expanded","false");self.$results.attr("aria-hidden","true");self.$results.removeAttr("aria-activedescendant")});container.on("results:toggle",function(){var $highlighted=self.getHighlightedResults();if($highlighted.length===0){return}$highlighted.trigger("mouseup")});container.on("results:select",function(){var $highlighted=self.getHighlightedResults();if($highlighted.length===0){return}var data=Utils.GetData($highlighted[0],"data");if($highlighted.attr("aria-selected")=="true"){self.trigger("close",{})}else{self.trigger("select",{data:data})}});container.on("results:previous",function(){var $highlighted=self.getHighlightedResults();var $options=self.$results.find("[aria-selected]");var currentIndex=$options.index($highlighted);if(currentIndex<=0){return}var nextIndex=currentIndex-1;if($highlighted.length===0){nextIndex=0}var $next=$options.eq(nextIndex);$next.trigger("mouseenter");var currentOffset=self.$results.offset().top;var nextTop=$next.offset().top;var nextOffset=self.$results.scrollTop()+(nextTop-currentOffset);if(nextIndex===0){self.$results.scrollTop(0)}else{if(nextTop-currentOffset<0){self.$results.scrollTop(nextOffset)}}});container.on("results:next",function(){var $highlighted=self.getHighlightedResults();var $options=self.$results.find("[aria-selected]");var currentIndex=$options.index($highlighted);var nextIndex=currentIndex+1;if(nextIndex>=$options.length){return}var $next=$options.eq(nextIndex);$next.trigger("mouseenter");var currentOffset=self.$results.offset().top+self.$results.outerHeight(false);var nextBottom=$next.offset().top+$next.outerHeight(false);var nextOffset=self.$results.scrollTop()+nextBottom-currentOffset;if(nextIndex===0){self.$results.scrollTop(0)}else{if(nextBottom>currentOffset){self.$results.scrollTop(nextOffset)}}});container.on("results:focus",function(params){params.element.addClass("select2-results__option--highlighted")});container.on("results:message",function(params){self.displayMessage(params)});if($.fn.mousewheel){this.$results.on("mousewheel",function(e){var top=self.$results.scrollTop();var bottom=self.$results.get(0).scrollHeight-top+e.deltaY;var isAtTop=e.deltaY>0&&top-e.deltaY<=0;var isAtBottom=e.deltaY<0&&bottom<=self.$results.height();if(isAtTop){self.$results.scrollTop(0);e.preventDefault();e.stopPropagation()}else{if(isAtBottom){self.$results.scrollTop(self.$results.get(0).scrollHeight-self.$results.height());e.preventDefault();e.stopPropagation()}}})}this.$results.on("mouseup",".select2-results__option[aria-selected]",function(evt){var $this=$(this);var data=Utils.GetData(this,"data");if($this.attr("aria-selected")==="true"){if(self.options.get("multiple")){self.trigger("unselect",{originalEvent:evt,data:data})}else{self.trigger("close",{})}return}self.trigger("select",{originalEvent:evt,data:data})});this.$results.on("mouseenter",".select2-results__option[aria-selected]",function(evt){var data=Utils.GetData(this,"data");self.getHighlightedResults().removeClass("select2-results__option--highlighted");self.trigger("results:focus",{data:data,element:$(this)})})};Results.prototype.getHighlightedResults=function(){var $highlighted=this.$results.find(".select2-results__option--highlighted");return $highlighted};Results.prototype.destroy=function(){this.$results.remove()};Results.prototype.ensureHighlightVisible=function(){var $highlighted=this.getHighlightedResults();if($highlighted.length===0){return}var $options=this.$results.find("[aria-selected]");var currentIndex=$options.index($highlighted);var currentOffset=this.$results.offset().top;var nextTop=$highlighted.offset().top;var nextOffset=this.$results.scrollTop()+(nextTop-currentOffset);var offsetDelta=nextTop-currentOffset;nextOffset-=$highlighted.outerHeight(false)*2;if(currentIndex<=2){this.$results.scrollTop(0)}else{if(offsetDelta>this.$results.outerHeight()||offsetDelta<0){this.$results.scrollTop(nextOffset)}}};Results.prototype.template=function(result,container){var template=this.options.get("templateResult");var escapeMarkup=this.options.get("escapeMarkup");var content=template(result,container);if(content==null){container.style.display="none"}else{if(typeof content==="string"){container.innerHTML=escapeMarkup(content)}else{$(container).append(content)}}};return Results});S2.define("select2/keys",[],function(){var KEYS={BACKSPACE:8,TAB:9,ENTER:13,SHIFT:16,CTRL:17,ALT:18,ESC:27,SPACE:32,PAGE_UP:33,PAGE_DOWN:34,END:35,HOME:36,LEFT:37,UP:38,RIGHT:39,DOWN:40,DELETE:46};return KEYS});S2.define("select2/selection/base",["jquery","../utils","../keys"],function($,Utils,KEYS){function BaseSelection($element,options){this.$element=$element;this.options=options;BaseSelection.__super__.constructor.call(this)}Utils.Extend(BaseSelection,Utils.Observable);BaseSelection.prototype.render=function(){var $selection=$('<span class="select2-selection" role="combobox" '+' aria-haspopup="true" aria-expanded="false">'+"</span>");this._tabindex=0;if(Utils.GetData(this.$element[0],"old-tabindex")!=null){this._tabindex=Utils.GetData(this.$element[0],"old-tabindex")}else{if(this.$element.attr("tabindex")!=null){this._tabindex=this.$element.attr("tabindex")}}$selection.attr("title",this.$element.attr("title"));$selection.attr("tabindex",this._tabindex);$selection.attr("aria-disabled","false");this.$selection=$selection;return $selection};BaseSelection.prototype.bind=function(container,$container){var self=this;var resultsId=container.id+"-results";this.container=container;this.$selection.on("focus",function(evt){self.trigger("focus",evt)});this.$selection.on("blur",function(evt){self._handleBlur(evt)});this.$selection.on("keydown",function(evt){self.trigger("keypress",evt);if(evt.which===KEYS.SPACE){evt.preventDefault()}});container.on("results:focus",function(params){self.$selection.attr("aria-activedescendant",params.data._resultId)});container.on("selection:update",function(params){self.update(params.data)});container.on("open",function(){self.$selection.attr("aria-expanded","true");self.$selection.attr("aria-owns",resultsId);self._attachCloseHandler(container)});container.on("close",function(){self.$selection.attr("aria-expanded","false");self.$selection.removeAttr("aria-activedescendant");self.$selection.removeAttr("aria-owns");self.$selection.trigger("focus");self._detachCloseHandler(container)});container.on("enable",function(){self.$selection.attr("tabindex",self._tabindex);self.$selection.attr("aria-disabled","false")});container.on("disable",function(){self.$selection.attr("tabindex","-1");self.$selection.attr("aria-disabled","true")})};BaseSelection.prototype._handleBlur=function(evt){var self=this;window.setTimeout(function(){if((document.activeElement==self.$selection[0])||($.contains(self.$selection[0],document.activeElement))){return}self.trigger("blur",evt)},1)};BaseSelection.prototype._attachCloseHandler=function(container){$(document.body).on("mousedown.select2."+container.id,function(e){var $target=$(e.target);var $select=$target.closest(".select2");var $all=$(".select2.select2-container--open");$all.each(function(){if(this==$select[0]){return}var $element=Utils.GetData(this,"element");$element.select2("close")})})};BaseSelection.prototype._detachCloseHandler=function(container){$(document.body).off("mousedown.select2."+container.id)};BaseSelection.prototype.position=function($selection,$container){var $selectionContainer=$container.find(".selection");$selectionContainer.append($selection)};BaseSelection.prototype.destroy=function(){this._detachCloseHandler(this.container)};BaseSelection.prototype.update=function(data){throw new Error("The `update` method must be defined in child classes.")};BaseSelection.prototype.isEnabled=function(){return !this.isDisabled()};BaseSelection.prototype.isDisabled=function(){return this.options.get("disabled")};return BaseSelection});S2.define("select2/selection/single",["jquery","./base","../utils","../keys"],function($,BaseSelection,Utils,KEYS){function SingleSelection(){SingleSelection.__super__.constructor.apply(this,arguments)}Utils.Extend(SingleSelection,BaseSelection);SingleSelection.prototype.render=function(){var $selection=SingleSelection.__super__.render.call(this);$selection.addClass("select2-selection--single");$selection.html('<span class="select2-selection__rendered"></span>'+'<span class="select2-selection__arrow" role="presentation">'+'<b role="presentation"></b>'+"</span>");return $selection};SingleSelection.prototype.bind=function(container,$container){var self=this;SingleSelection.__super__.bind.apply(this,arguments);var id=container.id+"-container";this.$selection.find(".select2-selection__rendered").attr("id",id).attr("role","textbox").attr("aria-readonly","true");this.$selection.attr("aria-labelledby",id);this.$selection.on("mousedown",function(evt){if(evt.which!==1){return}self.trigger("toggle",{originalEvent:evt})});this.$selection.on("focus",function(evt){});this.$selection.on("blur",function(evt){});container.on("focus",function(evt){if(!container.isOpen()){self.$selection.trigger("focus")}})};SingleSelection.prototype.clear=function(){var $rendered=this.$selection.find(".select2-selection__rendered");$rendered.empty();$rendered.removeAttr("title")};SingleSelection.prototype.display=function(data,container){var template=this.options.get("templateSelection");var escapeMarkup=this.options.get("escapeMarkup");return escapeMarkup(template(data,container))};SingleSelection.prototype.selectionContainer=function(){return $("<span></span>")};SingleSelection.prototype.update=function(data){if(data.length===0){this.clear();return}var selection=data[0];var $rendered=this.$selection.find(".select2-selection__rendered");var formatted=this.display(selection,$rendered);$rendered.empty().append(formatted);var title=selection.title||selection.text;if(title){$rendered.attr("title",title)}else{$rendered.removeAttr("title")}};return SingleSelection});S2.define("select2/selection/multiple",["jquery","./base","../utils"],function($,BaseSelection,Utils){function MultipleSelection($element,options){MultipleSelection.__super__.constructor.apply(this,arguments)}Utils.Extend(MultipleSelection,BaseSelection);MultipleSelection.prototype.render=function(){var $selection=MultipleSelection.__super__.render.call(this);$selection.addClass("select2-selection--multiple");$selection.html('<ul class="select2-selection__rendered"></ul>');return $selection};MultipleSelection.prototype.bind=function(container,$container){var self=this;MultipleSelection.__super__.bind.apply(this,arguments);this.$selection.on("click",function(evt){self.trigger("toggle",{originalEvent:evt})});this.$selection.on("click",".select2-selection__choice__remove",function(evt){if(self.isDisabled()){return}var $remove=$(this);var $selection=$remove.parent();var data=Utils.GetData($selection[0],"data");self.trigger("unselect",{originalEvent:evt,data:data})})};MultipleSelection.prototype.clear=function(){var $rendered=this.$selection.find(".select2-selection__rendered");$rendered.empty();$rendered.removeAttr("title")};MultipleSelection.prototype.display=function(data,container){var template=this.options.get("templateSelection");var escapeMarkup=this.options.get("escapeMarkup");return escapeMarkup(template(data,container))};MultipleSelection.prototype.selectionContainer=function(){var $container=$('<li class="select2-selection__choice">'+'<span class="select2-selection__choice__remove" role="presentation">'+"&times;"+"</span>"+"</li>");return $container};MultipleSelection.prototype.update=function(data){this.clear();if(data.length===0){return}var $selections=[];for(var d=0;d<data.length;d++){var selection=data[d];var $selection=this.selectionContainer();var formatted=this.display(selection,$selection);$selection.append(formatted);var title=selection.title||selection.text;if(title){$selection.attr("title",title)}Utils.StoreData($selection[0],"data",selection);$selections.push($selection)}var $rendered=this.$selection.find(".select2-selection__rendered");Utils.appendMany($rendered,$selections)};return MultipleSelection});S2.define("select2/selection/placeholder",["../utils"],function(Utils){function Placeholder(decorated,$element,options){this.placeholder=this.normalizePlaceholder(options.get("placeholder"));decorated.call(this,$element,options)}Placeholder.prototype.normalizePlaceholder=function(_,placeholder){if(typeof placeholder==="string"){placeholder={id:"",text:placeholder}}return placeholder};Placeholder.prototype.createPlaceholder=function(decorated,placeholder){var $placeholder=this.selectionContainer();$placeholder.html(this.display(placeholder));$placeholder.addClass("select2-selection__placeholder").removeClass("select2-selection__choice");return $placeholder};Placeholder.prototype.update=function(decorated,data){var singlePlaceholder=(data.length==1&&data[0].id!=this.placeholder.id);var multipleSelections=data.length>1;if(multipleSelections||singlePlaceholder){return decorated.call(this,data)}this.clear();var $placeholder=this.createPlaceholder(this.placeholder);this.$selection.find(".select2-selection__rendered").append($placeholder)};return Placeholder});S2.define("select2/selection/allowClear",["jquery","../keys","../utils"],function($,KEYS,Utils){function AllowClear(){}AllowClear.prototype.bind=function(decorated,container,$container){var self=this;decorated.call(this,container,$container);if(this.placeholder==null){if(this.options.get("debug")&&window.console&&console.error){console.error("Select2: The `allowClear` option should be used in combination "+"with the `placeholder` option.")}}this.$selection.on("mousedown",".select2-selection__clear",function(evt){self._handleClear(evt)});container.on("keypress",function(evt){self._handleKeyboardClear(evt,container)})};AllowClear.prototype._handleClear=function(_,evt){if(this.isDisabled()){return}var $clear=this.$selection.find(".select2-selection__clear");if($clear.length===0){return}evt.stopPropagation();var data=Utils.GetData($clear[0],"data");var previousVal=this.$element.val();this.$element.val(this.placeholder.id);var unselectData={data:data};this.trigger("clear",unselectData);if(unselectData.prevented){this.$element.val(previousVal);return}for(var d=0;d<data.length;d++){unselectData={data:data[d]};this.trigger("unselect",unselectData);if(unselectData.prevented){this.$element.val(previousVal);return}}this.$element.trigger("input").trigger("change");this.trigger("toggle",{})};AllowClear.prototype._handleKeyboardClear=function(_,evt,container){if(container.isOpen()){return}if(evt.which==KEYS.DELETE||evt.which==KEYS.BACKSPACE){this._handleClear(evt)}};AllowClear.prototype.update=function(decorated,data){decorated.call(this,data);if(this.$selection.find(".select2-selection__placeholder").length>0||data.length===0){return}var removeAll=this.options.get("translations").get("removeAllItems");var $remove=$('<span class="select2-selection__clear" title="'+removeAll()+'">'+"&times;"+"</span>");Utils.StoreData($remove[0],"data",data);this.$selection.find(".select2-selection__rendered").prepend($remove)};return AllowClear});S2.define("select2/selection/search",["jquery","../utils","../keys"],function($,Utils,KEYS){function Search(decorated,$element,options){decorated.call(this,$element,options)}Search.prototype.render=function(decorated){var $search=$('<li class="select2-search select2-search--inline">'+'<input class="select2-search__field" type="search" tabindex="-1"'+' autocomplete="off" autocorrect="off" autocapitalize="none"'+' spellcheck="false" role="searchbox" aria-autocomplete="list" />'+"</li>");this.$searchContainer=$search;this.$search=$search.find("input");var $rendered=decorated.call(this);this._transferTabIndex();return $rendered};Search.prototype.bind=function(decorated,container,$container){var self=this;var resultsId=container.id+"-results";decorated.call(this,container,$container);container.on("open",function(){self.$search.attr("aria-controls",resultsId);self.$search.trigger("focus")});container.on("close",function(){self.$search.val("");self.$search.removeAttr("aria-controls");self.$search.removeAttr("aria-activedescendant");self.$search.trigger("focus")});container.on("enable",function(){self.$search.prop("disabled",false);self._transferTabIndex()});container.on("disable",function(){self.$search.prop("disabled",true)});container.on("focus",function(evt){self.$search.trigger("focus")});container.on("results:focus",function(params){if(params.data._resultId){self.$search.attr("aria-activedescendant",params.data._resultId)}else{self.$search.removeAttr("aria-activedescendant")}});this.$selection.on("focusin",".select2-search--inline",function(evt){self.trigger("focus",evt)});this.$selection.on("focusout",".select2-search--inline",function(evt){self._handleBlur(evt)});this.$selection.on("keydown",".select2-search--inline",function(evt){evt.stopPropagation();self.trigger("keypress",evt);self._keyUpPrevented=evt.isDefaultPrevented();var key=evt.which;if(key===KEYS.BACKSPACE&&self.$search.val()===""){var $previousChoice=self.$searchContainer.prev(".select2-selection__choice");if($previousChoice.length>0){var item=Utils.GetData($previousChoice[0],"data");self.searchRemoveChoice(item);evt.preventDefault()}}});this.$selection.on("click",".select2-search--inline",function(evt){if(self.$search.val()){evt.stopPropagation()}});var msie=document.documentMode;var disableInputEvents=msie&&msie<=11;this.$selection.on("input.searchcheck",".select2-search--inline",function(evt){if(disableInputEvents){self.$selection.off("input.search input.searchcheck");return}self.$selection.off("keyup.search")});this.$selection.on("keyup.search input.search",".select2-search--inline",function(evt){if(disableInputEvents&&evt.type==="input"){self.$selection.off("input.search input.searchcheck");return}var key=evt.which;if(key==KEYS.SHIFT||key==KEYS.CTRL||key==KEYS.ALT){return}if(key==KEYS.TAB){return}self.handleSearch(evt)})};Search.prototype._transferTabIndex=function(decorated){this.$search.attr("tabindex",this.$selection.attr("tabindex"));this.$selection.attr("tabindex","-1")};Search.prototype.createPlaceholder=function(decorated,placeholder){this.$search.attr("placeholder",placeholder.text)};Search.prototype.update=function(decorated,data){var searchHadFocus=this.$search[0]==document.activeElement;this.$search.attr("placeholder","");decorated.call(this,data);this.$selection.find(".select2-selection__rendered").append(this.$searchContainer);this.resizeSearch();if(searchHadFocus){this.$search.trigger("focus")}};Search.prototype.handleSearch=function(){this.resizeSearch();if(!this._keyUpPrevented){var input=this.$search.val();this.trigger("query",{term:input})}this._keyUpPrevented=false};Search.prototype.searchRemoveChoice=function(decorated,item){this.trigger("unselect",{data:item});this.$search.val(item.text);this.handleSearch()};Search.prototype.resizeSearch=function(){this.$search.css("width","25px");var width="";if(this.$search.attr("placeholder")!==""){width=this.$selection.find(".select2-selection__rendered").width()}else{var minimumWidth=this.$search.val().length+1;width=(minimumWidth*0.75)+"em"}this.$search.css("width",width)};return Search});S2.define("select2/selection/eventRelay",["jquery"],function($){function EventRelay(){}EventRelay.prototype.bind=function(decorated,container,$container){var self=this;var relayEvents=["open","opening","close","closing","select","selecting","unselect","unselecting","clear","clearing"];var preventableEvents=["opening","closing","selecting","unselecting","clearing"];decorated.call(this,container,$container);container.on("*",function(name,params){if($.inArray(name,relayEvents)===-1){return}params=params||{};var evt=$.Event("select2:"+name,{params:params});self.$element.trigger(evt);if($.inArray(name,preventableEvents)===-1){return}params.prevented=evt.isDefaultPrevented()})};return EventRelay});S2.define("select2/translation",["jquery","require"],function($,require){function Translation(dict){this.dict=dict||{}}Translation.prototype.all=function(){return this.dict};Translation.prototype.get=function(key){return this.dict[key]};Translation.prototype.extend=function(translation){this.dict=$.extend({},translation.all(),this.dict)};Translation._cache={};Translation.loadPath=function(path){if(!(path in Translation._cache)){var translations=require(path);Translation._cache[path]=translations}return new Translation(Translation._cache[path])};return Translation});S2.define("select2/diacritics",[],function(){var diacritics={"\u24B6":"A","\uFF21":"A","\u00C0":"A","\u00C1":"A","\u00C2":"A","\u1EA6":"A","\u1EA4":"A","\u1EAA":"A","\u1EA8":"A","\u00C3":"A","\u0100":"A","\u0102":"A","\u1EB0":"A","\u1EAE":"A","\u1EB4":"A","\u1EB2":"A","\u0226":"A","\u01E0":"A","\u00C4":"A","\u01DE":"A","\u1EA2":"A","\u00C5":"A","\u01FA":"A","\u01CD":"A","\u0200":"A","\u0202":"A","\u1EA0":"A","\u1EAC":"A","\u1EB6":"A","\u1E00":"A","\u0104":"A","\u023A":"A","\u2C6F":"A","\uA732":"AA","\u00C6":"AE","\u01FC":"AE","\u01E2":"AE","\uA734":"AO","\uA736":"AU","\uA738":"AV","\uA73A":"AV","\uA73C":"AY","\u24B7":"B","\uFF22":"B","\u1E02":"B","\u1E04":"B","\u1E06":"B","\u0243":"B","\u0182":"B","\u0181":"B","\u24B8":"C","\uFF23":"C","\u0106":"C","\u0108":"C","\u010A":"C","\u010C":"C","\u00C7":"C","\u1E08":"C","\u0187":"C","\u023B":"C","\uA73E":"C","\u24B9":"D","\uFF24":"D","\u1E0A":"D","\u010E":"D","\u1E0C":"D","\u1E10":"D","\u1E12":"D","\u1E0E":"D","\u0110":"D","\u018B":"D","\u018A":"D","\u0189":"D","\uA779":"D","\u01F1":"DZ","\u01C4":"DZ","\u01F2":"Dz","\u01C5":"Dz","\u24BA":"E","\uFF25":"E","\u00C8":"E","\u00C9":"E","\u00CA":"E","\u1EC0":"E","\u1EBE":"E","\u1EC4":"E","\u1EC2":"E","\u1EBC":"E","\u0112":"E","\u1E14":"E","\u1E16":"E","\u0114":"E","\u0116":"E","\u00CB":"E","\u1EBA":"E","\u011A":"E","\u0204":"E","\u0206":"E","\u1EB8":"E","\u1EC6":"E","\u0228":"E","\u1E1C":"E","\u0118":"E","\u1E18":"E","\u1E1A":"E","\u0190":"E","\u018E":"E","\u24BB":"F","\uFF26":"F","\u1E1E":"F","\u0191":"F","\uA77B":"F","\u24BC":"G","\uFF27":"G","\u01F4":"G","\u011C":"G","\u1E20":"G","\u011E":"G","\u0120":"G","\u01E6":"G","\u0122":"G","\u01E4":"G","\u0193":"G","\uA7A0":"G","\uA77D":"G","\uA77E":"G","\u24BD":"H","\uFF28":"H","\u0124":"H","\u1E22":"H","\u1E26":"H","\u021E":"H","\u1E24":"H","\u1E28":"H","\u1E2A":"H","\u0126":"H","\u2C67":"H","\u2C75":"H","\uA78D":"H","\u24BE":"I","\uFF29":"I","\u00CC":"I","\u00CD":"I","\u00CE":"I","\u0128":"I","\u012A":"I","\u012C":"I","\u0130":"I","\u00CF":"I","\u1E2E":"I","\u1EC8":"I","\u01CF":"I","\u0208":"I","\u020A":"I","\u1ECA":"I","\u012E":"I","\u1E2C":"I","\u0197":"I","\u24BF":"J","\uFF2A":"J","\u0134":"J","\u0248":"J","\u24C0":"K","\uFF2B":"K","\u1E30":"K","\u01E8":"K","\u1E32":"K","\u0136":"K","\u1E34":"K","\u0198":"K","\u2C69":"K","\uA740":"K","\uA742":"K","\uA744":"K","\uA7A2":"K","\u24C1":"L","\uFF2C":"L","\u013F":"L","\u0139":"L","\u013D":"L","\u1E36":"L","\u1E38":"L","\u013B":"L","\u1E3C":"L","\u1E3A":"L","\u0141":"L","\u023D":"L","\u2C62":"L","\u2C60":"L","\uA748":"L","\uA746":"L","\uA780":"L","\u01C7":"LJ","\u01C8":"Lj","\u24C2":"M","\uFF2D":"M","\u1E3E":"M","\u1E40":"M","\u1E42":"M","\u2C6E":"M","\u019C":"M","\u24C3":"N","\uFF2E":"N","\u01F8":"N","\u0143":"N","\u00D1":"N","\u1E44":"N","\u0147":"N","\u1E46":"N","\u0145":"N","\u1E4A":"N","\u1E48":"N","\u0220":"N","\u019D":"N","\uA790":"N","\uA7A4":"N","\u01CA":"NJ","\u01CB":"Nj","\u24C4":"O","\uFF2F":"O","\u00D2":"O","\u00D3":"O","\u00D4":"O","\u1ED2":"O","\u1ED0":"O","\u1ED6":"O","\u1ED4":"O","\u00D5":"O","\u1E4C":"O","\u022C":"O","\u1E4E":"O","\u014C":"O","\u1E50":"O","\u1E52":"O","\u014E":"O","\u022E":"O","\u0230":"O","\u00D6":"O","\u022A":"O","\u1ECE":"O","\u0150":"O","\u01D1":"O","\u020C":"O","\u020E":"O","\u01A0":"O","\u1EDC":"O","\u1EDA":"O","\u1EE0":"O","\u1EDE":"O","\u1EE2":"O","\u1ECC":"O","\u1ED8":"O","\u01EA":"O","\u01EC":"O","\u00D8":"O","\u01FE":"O","\u0186":"O","\u019F":"O","\uA74A":"O","\uA74C":"O","\u0152":"OE","\u01A2":"OI","\uA74E":"OO","\u0222":"OU","\u24C5":"P","\uFF30":"P","\u1E54":"P","\u1E56":"P","\u01A4":"P","\u2C63":"P","\uA750":"P","\uA752":"P","\uA754":"P","\u24C6":"Q","\uFF31":"Q","\uA756":"Q","\uA758":"Q","\u024A":"Q","\u24C7":"R","\uFF32":"R","\u0154":"R","\u1E58":"R","\u0158":"R","\u0210":"R","\u0212":"R","\u1E5A":"R","\u1E5C":"R","\u0156":"R","\u1E5E":"R","\u024C":"R","\u2C64":"R","\uA75A":"R","\uA7A6":"R","\uA782":"R","\u24C8":"S","\uFF33":"S","\u1E9E":"S","\u015A":"S","\u1E64":"S","\u015C":"S","\u1E60":"S","\u0160":"S","\u1E66":"S","\u1E62":"S","\u1E68":"S","\u0218":"S","\u015E":"S","\u2C7E":"S","\uA7A8":"S","\uA784":"S","\u24C9":"T","\uFF34":"T","\u1E6A":"T","\u0164":"T","\u1E6C":"T","\u021A":"T","\u0162":"T","\u1E70":"T","\u1E6E":"T","\u0166":"T","\u01AC":"T","\u01AE":"T","\u023E":"T","\uA786":"T","\uA728":"TZ","\u24CA":"U","\uFF35":"U","\u00D9":"U","\u00DA":"U","\u00DB":"U","\u0168":"U","\u1E78":"U","\u016A":"U","\u1E7A":"U","\u016C":"U","\u00DC":"U","\u01DB":"U","\u01D7":"U","\u01D5":"U","\u01D9":"U","\u1EE6":"U","\u016E":"U","\u0170":"U","\u01D3":"U","\u0214":"U","\u0216":"U","\u01AF":"U","\u1EEA":"U","\u1EE8":"U","\u1EEE":"U","\u1EEC":"U","\u1EF0":"U","\u1EE4":"U","\u1E72":"U","\u0172":"U","\u1E76":"U","\u1E74":"U","\u0244":"U","\u24CB":"V","\uFF36":"V","\u1E7C":"V","\u1E7E":"V","\u01B2":"V","\uA75E":"V","\u0245":"V","\uA760":"VY","\u24CC":"W","\uFF37":"W","\u1E80":"W","\u1E82":"W","\u0174":"W","\u1E86":"W","\u1E84":"W","\u1E88":"W","\u2C72":"W","\u24CD":"X","\uFF38":"X","\u1E8A":"X","\u1E8C":"X","\u24CE":"Y","\uFF39":"Y","\u1EF2":"Y","\u00DD":"Y","\u0176":"Y","\u1EF8":"Y","\u0232":"Y","\u1E8E":"Y","\u0178":"Y","\u1EF6":"Y","\u1EF4":"Y","\u01B3":"Y","\u024E":"Y","\u1EFE":"Y","\u24CF":"Z","\uFF3A":"Z","\u0179":"Z","\u1E90":"Z","\u017B":"Z","\u017D":"Z","\u1E92":"Z","\u1E94":"Z","\u01B5":"Z","\u0224":"Z","\u2C7F":"Z","\u2C6B":"Z","\uA762":"Z","\u24D0":"a","\uFF41":"a","\u1E9A":"a","\u00E0":"a","\u00E1":"a","\u00E2":"a","\u1EA7":"a","\u1EA5":"a","\u1EAB":"a","\u1EA9":"a","\u00E3":"a","\u0101":"a","\u0103":"a","\u1EB1":"a","\u1EAF":"a","\u1EB5":"a","\u1EB3":"a","\u0227":"a","\u01E1":"a","\u00E4":"a","\u01DF":"a","\u1EA3":"a","\u00E5":"a","\u01FB":"a","\u01CE":"a","\u0201":"a","\u0203":"a","\u1EA1":"a","\u1EAD":"a","\u1EB7":"a","\u1E01":"a","\u0105":"a","\u2C65":"a","\u0250":"a","\uA733":"aa","\u00E6":"ae","\u01FD":"ae","\u01E3":"ae","\uA735":"ao","\uA737":"au","\uA739":"av","\uA73B":"av","\uA73D":"ay","\u24D1":"b","\uFF42":"b","\u1E03":"b","\u1E05":"b","\u1E07":"b","\u0180":"b","\u0183":"b","\u0253":"b","\u24D2":"c","\uFF43":"c","\u0107":"c","\u0109":"c","\u010B":"c","\u010D":"c","\u00E7":"c","\u1E09":"c","\u0188":"c","\u023C":"c","\uA73F":"c","\u2184":"c","\u24D3":"d","\uFF44":"d","\u1E0B":"d","\u010F":"d","\u1E0D":"d","\u1E11":"d","\u1E13":"d","\u1E0F":"d","\u0111":"d","\u018C":"d","\u0256":"d","\u0257":"d","\uA77A":"d","\u01F3":"dz","\u01C6":"dz","\u24D4":"e","\uFF45":"e","\u00E8":"e","\u00E9":"e","\u00EA":"e","\u1EC1":"e","\u1EBF":"e","\u1EC5":"e","\u1EC3":"e","\u1EBD":"e","\u0113":"e","\u1E15":"e","\u1E17":"e","\u0115":"e","\u0117":"e","\u00EB":"e","\u1EBB":"e","\u011B":"e","\u0205":"e","\u0207":"e","\u1EB9":"e","\u1EC7":"e","\u0229":"e","\u1E1D":"e","\u0119":"e","\u1E19":"e","\u1E1B":"e","\u0247":"e","\u025B":"e","\u01DD":"e","\u24D5":"f","\uFF46":"f","\u1E1F":"f","\u0192":"f","\uA77C":"f","\u24D6":"g","\uFF47":"g","\u01F5":"g","\u011D":"g","\u1E21":"g","\u011F":"g","\u0121":"g","\u01E7":"g","\u0123":"g","\u01E5":"g","\u0260":"g","\uA7A1":"g","\u1D79":"g","\uA77F":"g","\u24D7":"h","\uFF48":"h","\u0125":"h","\u1E23":"h","\u1E27":"h","\u021F":"h","\u1E25":"h","\u1E29":"h","\u1E2B":"h","\u1E96":"h","\u0127":"h","\u2C68":"h","\u2C76":"h","\u0265":"h","\u0195":"hv","\u24D8":"i","\uFF49":"i","\u00EC":"i","\u00ED":"i","\u00EE":"i","\u0129":"i","\u012B":"i","\u012D":"i","\u00EF":"i","\u1E2F":"i","\u1EC9":"i","\u01D0":"i","\u0209":"i","\u020B":"i","\u1ECB":"i","\u012F":"i","\u1E2D":"i","\u0268":"i","\u0131":"i","\u24D9":"j","\uFF4A":"j","\u0135":"j","\u01F0":"j","\u0249":"j","\u24DA":"k","\uFF4B":"k","\u1E31":"k","\u01E9":"k","\u1E33":"k","\u0137":"k","\u1E35":"k","\u0199":"k","\u2C6A":"k","\uA741":"k","\uA743":"k","\uA745":"k","\uA7A3":"k","\u24DB":"l","\uFF4C":"l","\u0140":"l","\u013A":"l","\u013E":"l","\u1E37":"l","\u1E39":"l","\u013C":"l","\u1E3D":"l","\u1E3B":"l","\u017F":"l","\u0142":"l","\u019A":"l","\u026B":"l","\u2C61":"l","\uA749":"l","\uA781":"l","\uA747":"l","\u01C9":"lj","\u24DC":"m","\uFF4D":"m","\u1E3F":"m","\u1E41":"m","\u1E43":"m","\u0271":"m","\u026F":"m","\u24DD":"n","\uFF4E":"n","\u01F9":"n","\u0144":"n","\u00F1":"n","\u1E45":"n","\u0148":"n","\u1E47":"n","\u0146":"n","\u1E4B":"n","\u1E49":"n","\u019E":"n","\u0272":"n","\u0149":"n","\uA791":"n","\uA7A5":"n","\u01CC":"nj","\u24DE":"o","\uFF4F":"o","\u00F2":"o","\u00F3":"o","\u00F4":"o","\u1ED3":"o","\u1ED1":"o","\u1ED7":"o","\u1ED5":"o","\u00F5":"o","\u1E4D":"o","\u022D":"o","\u1E4F":"o","\u014D":"o","\u1E51":"o","\u1E53":"o","\u014F":"o","\u022F":"o","\u0231":"o","\u00F6":"o","\u022B":"o","\u1ECF":"o","\u0151":"o","\u01D2":"o","\u020D":"o","\u020F":"o","\u01A1":"o","\u1EDD":"o","\u1EDB":"o","\u1EE1":"o","\u1EDF":"o","\u1EE3":"o","\u1ECD":"o","\u1ED9":"o","\u01EB":"o","\u01ED":"o","\u00F8":"o","\u01FF":"o","\u0254":"o","\uA74B":"o","\uA74D":"o","\u0275":"o","\u0153":"oe","\u01A3":"oi","\u0223":"ou","\uA74F":"oo","\u24DF":"p","\uFF50":"p","\u1E55":"p","\u1E57":"p","\u01A5":"p","\u1D7D":"p","\uA751":"p","\uA753":"p","\uA755":"p","\u24E0":"q","\uFF51":"q","\u024B":"q","\uA757":"q","\uA759":"q","\u24E1":"r","\uFF52":"r","\u0155":"r","\u1E59":"r","\u0159":"r","\u0211":"r","\u0213":"r","\u1E5B":"r","\u1E5D":"r","\u0157":"r","\u1E5F":"r","\u024D":"r","\u027D":"r","\uA75B":"r","\uA7A7":"r","\uA783":"r","\u24E2":"s","\uFF53":"s","\u00DF":"s","\u015B":"s","\u1E65":"s","\u015D":"s","\u1E61":"s","\u0161":"s","\u1E67":"s","\u1E63":"s","\u1E69":"s","\u0219":"s","\u015F":"s","\u023F":"s","\uA7A9":"s","\uA785":"s","\u1E9B":"s","\u24E3":"t","\uFF54":"t","\u1E6B":"t","\u1E97":"t","\u0165":"t","\u1E6D":"t","\u021B":"t","\u0163":"t","\u1E71":"t","\u1E6F":"t","\u0167":"t","\u01AD":"t","\u0288":"t","\u2C66":"t","\uA787":"t","\uA729":"tz","\u24E4":"u","\uFF55":"u","\u00F9":"u","\u00FA":"u","\u00FB":"u","\u0169":"u","\u1E79":"u","\u016B":"u","\u1E7B":"u","\u016D":"u","\u00FC":"u","\u01DC":"u","\u01D8":"u","\u01D6":"u","\u01DA":"u","\u1EE7":"u","\u016F":"u","\u0171":"u","\u01D4":"u","\u0215":"u","\u0217":"u","\u01B0":"u","\u1EEB":"u","\u1EE9":"u","\u1EEF":"u","\u1EED":"u","\u1EF1":"u","\u1EE5":"u","\u1E73":"u","\u0173":"u","\u1E77":"u","\u1E75":"u","\u0289":"u","\u24E5":"v","\uFF56":"v","\u1E7D":"v","\u1E7F":"v","\u028B":"v","\uA75F":"v","\u028C":"v","\uA761":"vy","\u24E6":"w","\uFF57":"w","\u1E81":"w","\u1E83":"w","\u0175":"w","\u1E87":"w","\u1E85":"w","\u1E98":"w","\u1E89":"w","\u2C73":"w","\u24E7":"x","\uFF58":"x","\u1E8B":"x","\u1E8D":"x","\u24E8":"y","\uFF59":"y","\u1EF3":"y","\u00FD":"y","\u0177":"y","\u1EF9":"y","\u0233":"y","\u1E8F":"y","\u00FF":"y","\u1EF7":"y","\u1E99":"y","\u1EF5":"y","\u01B4":"y","\u024F":"y","\u1EFF":"y","\u24E9":"z","\uFF5A":"z","\u017A":"z","\u1E91":"z","\u017C":"z","\u017E":"z","\u1E93":"z","\u1E95":"z","\u01B6":"z","\u0225":"z","\u0240":"z","\u2C6C":"z","\uA763":"z","\u0386":"\u0391","\u0388":"\u0395","\u0389":"\u0397","\u038A":"\u0399","\u03AA":"\u0399","\u038C":"\u039F","\u038E":"\u03A5","\u03AB":"\u03A5","\u038F":"\u03A9","\u03AC":"\u03B1","\u03AD":"\u03B5","\u03AE":"\u03B7","\u03AF":"\u03B9","\u03CA":"\u03B9","\u0390":"\u03B9","\u03CC":"\u03BF","\u03CD":"\u03C5","\u03CB":"\u03C5","\u03B0":"\u03C5","\u03CE":"\u03C9","\u03C2":"\u03C3","\u2019":"'"};return diacritics});S2.define("select2/data/base",["../utils"],function(Utils){function BaseAdapter($element,options){BaseAdapter.__super__.constructor.call(this)}Utils.Extend(BaseAdapter,Utils.Observable);BaseAdapter.prototype.current=function(callback){throw new Error("The `current` method must be defined in child classes.")};BaseAdapter.prototype.query=function(params,callback){throw new Error("The `query` method must be defined in child classes.")};BaseAdapter.prototype.bind=function(container,$container){};BaseAdapter.prototype.destroy=function(){};BaseAdapter.prototype.generateResultId=function(container,data){var id=container.id+"-result-";id+=Utils.generateChars(4);if(data.id!=null){id+="-"+data.id.toString()}else{id+="-"+Utils.generateChars(4)}return id};return BaseAdapter});S2.define("select2/data/select",["./base","../utils","jquery"],function(BaseAdapter,Utils,$){function SelectAdapter($element,options){this.$element=$element;this.options=options;SelectAdapter.__super__.constructor.call(this)}Utils.Extend(SelectAdapter,BaseAdapter);SelectAdapter.prototype.current=function(callback){var data=[];var self=this;this.$element.find(":selected").each(function(){var $option=$(this);var option=self.item($option);data.push(option)});callback(data)};SelectAdapter.prototype.select=function(data){var self=this;data.selected=true;if($(data.element).is("option")){data.element.selected=true;this.$element.trigger("input").trigger("change");return}if(this.$element.prop("multiple")){this.current(function(currentData){var val=[];data=[data];data.push.apply(data,currentData);for(var d=0;d<data.length;d++){var id=data[d].id;if($.inArray(id,val)===-1){val.push(id)}}self.$element.val(val);self.$element.trigger("input").trigger("change")})}else{var val=data.id;this.$element.val(val);this.$element.trigger("input").trigger("change")}};SelectAdapter.prototype.unselect=function(data){var self=this;if(!this.$element.prop("multiple")){return}data.selected=false;if($(data.element).is("option")){data.element.selected=false;this.$element.trigger("input").trigger("change");return}this.current(function(currentData){var val=[];for(var d=0;d<currentData.length;d++){var id=currentData[d].id;if(id!==data.id&&$.inArray(id,val)===-1){val.push(id)}}self.$element.val(val);self.$element.trigger("input").trigger("change")})};SelectAdapter.prototype.bind=function(container,$container){var self=this;this.container=container;container.on("select",function(params){self.select(params.data)});container.on("unselect",function(params){self.unselect(params.data)})};SelectAdapter.prototype.destroy=function(){this.$element.find("*").each(function(){Utils.RemoveData(this)})};SelectAdapter.prototype.query=function(params,callback){var data=[];var self=this;var $options=this.$element.children();$options.each(function(){var $option=$(this);if(!$option.is("option")&&!$option.is("optgroup")){return}var option=self.item($option);var matches=self.matches(params,option);if(matches!==null){data.push(matches)}});callback({results:data})};SelectAdapter.prototype.addOptions=function($options){Utils.appendMany(this.$element,$options)};SelectAdapter.prototype.option=function(data){var option;if(data.children){option=document.createElement("optgroup");option.label=data.text}else{option=document.createElement("option");if(option.textContent!==undefined){option.textContent=data.text}else{option.innerText=data.text}}if(data.id!==undefined){option.value=data.id}if(data.disabled){option.disabled=true}if(data.selected){option.selected=true}if(data.title){option.title=data.title}var $option=$(option);var normalizedData=this._normalizeItem(data);normalizedData.element=option;Utils.StoreData(option,"data",normalizedData);return $option};SelectAdapter.prototype.item=function($option){var data={};data=Utils.GetData($option[0],"data");if(data!=null){return data}if($option.is("option")){data={id:$option.val(),text:$option.text(),disabled:$option.prop("disabled"),selected:$option.prop("selected"),title:$option.prop("title")}}else{if($option.is("optgroup")){data={text:$option.prop("label"),children:[],title:$option.prop("title")};var $children=$option.children("option");var children=[];for(var c=0;c<$children.length;c++){var $child=$($children[c]);var child=this.item($child);children.push(child)}data.children=children}}data=this._normalizeItem(data);data.element=$option[0];Utils.StoreData($option[0],"data",data);return data};SelectAdapter.prototype._normalizeItem=function(item){if(item!==Object(item)){item={id:item,text:item}}item=$.extend({},{text:""},item);var defaults={selected:false,disabled:false};if(item.id!=null){item.id=item.id.toString()}if(item.text!=null){item.text=item.text.toString()}if(item._resultId==null&&item.id&&this.container!=null){item._resultId=this.generateResultId(this.container,item)}return $.extend({},defaults,item)};SelectAdapter.prototype.matches=function(params,data){var matcher=this.options.get("matcher");return matcher(params,data)};return SelectAdapter});S2.define("select2/data/array",["./select","../utils","jquery"],function(SelectAdapter,Utils,$){function ArrayAdapter($element,options){this._dataToConvert=options.get("data")||[];ArrayAdapter.__super__.constructor.call(this,$element,options)}Utils.Extend(ArrayAdapter,SelectAdapter);ArrayAdapter.prototype.bind=function(container,$container){ArrayAdapter.__super__.bind.call(this,container,$container);this.addOptions(this.convertToOptions(this._dataToConvert))};ArrayAdapter.prototype.select=function(data){var $option=this.$element.find("option").filter(function(i,elm){return elm.value==data.id.toString()});if($option.length===0){$option=this.option(data);this.addOptions($option)}ArrayAdapter.__super__.select.call(this,data)};ArrayAdapter.prototype.convertToOptions=function(data){var self=this;var $existing=this.$element.find("option");var existingIds=$existing.map(function(){return self.item($(this)).id}).get();var $options=[];function onlyItem(item){return function(){return $(this).val()==item.id}}for(var d=0;d<data.length;d++){var item=this._normalizeItem(data[d]);if($.inArray(item.id,existingIds)>=0){var $existingOption=$existing.filter(onlyItem(item));var existingData=this.item($existingOption);var newData=$.extend(true,{},item,existingData);var $newOption=this.option(newData);$existingOption.replaceWith($newOption);continue}var $option=this.option(item);if(item.children){var $children=this.convertToOptions(item.children);Utils.appendMany($option,$children)}$options.push($option)}return $options};return ArrayAdapter});S2.define("select2/data/ajax",["./array","../utils","jquery"],function(ArrayAdapter,Utils,$){function AjaxAdapter($element,options){this.ajaxOptions=this._applyDefaults(options.get("ajax"));if(this.ajaxOptions.processResults!=null){this.processResults=this.ajaxOptions.processResults}AjaxAdapter.__super__.constructor.call(this,$element,options)}Utils.Extend(AjaxAdapter,ArrayAdapter);AjaxAdapter.prototype._applyDefaults=function(options){var defaults={data:function(params){return $.extend({},params,{q:params.term})},transport:function(params,success,failure){var $request=$.ajax(params);$request.then(success);$request.fail(failure);return $request}};return $.extend({},defaults,options,true)};AjaxAdapter.prototype.processResults=function(results){return results};AjaxAdapter.prototype.query=function(params,callback){var matches=[];var self=this;if(this._request!=null){if($.isFunction(this._request.abort)){this._request.abort()}this._request=null}var options=$.extend({type:"GET"},this.ajaxOptions);if(typeof options.url==="function"){options.url=options.url.call(this.$element,params)}if(typeof options.data==="function"){options.data=options.data.call(this.$element,params)}function request(){var $request=options.transport(options,function(data){var results=self.processResults(data,params);if(self.options.get("debug")&&window.console&&console.error){if(!results||!results.results||!$.isArray(results.results)){console.error("Select2: The AJAX results did not return an array in the "+"`results` key of the response.")}}callback(results)},function(){if("status" in $request&&($request.status===0||$request.status==="0")){return}self.trigger("results:message",{message:"errorLoading"})});self._request=$request}if(this.ajaxOptions.delay&&params.term!=null){if(this._queryTimeout){window.clearTimeout(this._queryTimeout)}this._queryTimeout=window.setTimeout(request,this.ajaxOptions.delay)}else{request()}};return AjaxAdapter});S2.define("select2/data/tags",["jquery"],function($){function Tags(decorated,$element,options){var tags=options.get("tags");var createTag=options.get("createTag");if(createTag!==undefined){this.createTag=createTag}var insertTag=options.get("insertTag");if(insertTag!==undefined){this.insertTag=insertTag}decorated.call(this,$element,options);if($.isArray(tags)){for(var t=0;t<tags.length;t++){var tag=tags[t];var item=this._normalizeItem(tag);var $option=this.option(item);this.$element.append($option)}}}Tags.prototype.query=function(decorated,params,callback){var self=this;this._removeOldTags();if(params.term==null||params.page!=null){decorated.call(this,params,callback);return}function wrapper(obj,child){var data=obj.results;for(var i=0;i<data.length;i++){var option=data[i];var checkChildren=(option.children!=null&&!wrapper({results:option.children},true));var optionText=(option.text||"").toUpperCase();var paramsTerm=(params.term||"").toUpperCase();var checkText=optionText===paramsTerm;if(checkText||checkChildren){if(child){return false}obj.data=data;callback(obj);return}}if(child){return true}var tag=self.createTag(params);if(tag!=null){var $option=self.option(tag);$option.attr("data-select2-tag",true);self.addOptions([$option]);self.insertTag(data,tag)}obj.results=data;callback(obj)}decorated.call(this,params,wrapper)};Tags.prototype.createTag=function(decorated,params){var term=$.trim(params.term);if(term===""){return null}return{id:term,text:term}};Tags.prototype.insertTag=function(_,data,tag){data.unshift(tag)};Tags.prototype._removeOldTags=function(_){var $options=this.$element.find("option[data-select2-tag]");$options.each(function(){if(this.selected){return}$(this).remove()})};return Tags});S2.define("select2/data/tokenizer",["jquery"],function($){function Tokenizer(decorated,$element,options){var tokenizer=options.get("tokenizer");if(tokenizer!==undefined){this.tokenizer=tokenizer}decorated.call(this,$element,options)}Tokenizer.prototype.bind=function(decorated,container,$container){decorated.call(this,container,$container);this.$search=container.dropdown.$search||container.selection.$search||$container.find(".select2-search__field")};Tokenizer.prototype.query=function(decorated,params,callback){var self=this;function createAndSelect(data){var item=self._normalizeItem(data);var $existingOptions=self.$element.find("option").filter(function(){return $(this).val()===item.id});if(!$existingOptions.length){var $option=self.option(item);$option.attr("data-select2-tag",true);self._removeOldTags();self.addOptions([$option])}select(item)}function select(data){self.trigger("select",{data:data})}params.term=params.term||"";var tokenData=this.tokenizer(params,this.options,createAndSelect);if(tokenData.term!==params.term){if(this.$search.length){this.$search.val(tokenData.term);this.$search.trigger("focus")}params.term=tokenData.term}decorated.call(this,params,callback)};Tokenizer.prototype.tokenizer=function(_,params,options,callback){var separators=options.get("tokenSeparators")||[];var term=params.term;var i=0;var createTag=this.createTag||function(params){return{id:params.term,text:params.term}};while(i<term.length){var termChar=term[i];if($.inArray(termChar,separators)===-1){i++;continue}var part=term.substr(0,i);var partParams=$.extend({},params,{term:part});var data=createTag(partParams);if(data==null){i++;continue}callback(data);term=term.substr(i+1)||"";i=0}return{term:term}};return Tokenizer});S2.define("select2/data/minimumInputLength",[],function(){function MinimumInputLength(decorated,$e,options){this.minimumInputLength=options.get("minimumInputLength");decorated.call(this,$e,options)}MinimumInputLength.prototype.query=function(decorated,params,callback){params.term=params.term||"";if(params.term.length<this.minimumInputLength){this.trigger("results:message",{message:"inputTooShort",args:{minimum:this.minimumInputLength,input:params.term,params:params}});return}decorated.call(this,params,callback)};return MinimumInputLength});S2.define("select2/data/maximumInputLength",[],function(){function MaximumInputLength(decorated,$e,options){this.maximumInputLength=options.get("maximumInputLength");decorated.call(this,$e,options)}MaximumInputLength.prototype.query=function(decorated,params,callback){params.term=params.term||"";if(this.maximumInputLength>0&&params.term.length>this.maximumInputLength){this.trigger("results:message",{message:"inputTooLong",args:{maximum:this.maximumInputLength,input:params.term,params:params}});return}decorated.call(this,params,callback)};return MaximumInputLength});S2.define("select2/data/maximumSelectionLength",[],function(){function MaximumSelectionLength(decorated,$e,options){this.maximumSelectionLength=options.get("maximumSelectionLength");decorated.call(this,$e,options)}MaximumSelectionLength.prototype.bind=function(decorated,container,$container){var self=this;decorated.call(this,container,$container);container.on("select",function(){self._checkIfMaximumSelected()})};MaximumSelectionLength.prototype.query=function(decorated,params,callback){var self=this;this._checkIfMaximumSelected(function(){decorated.call(self,params,callback)})};MaximumSelectionLength.prototype._checkIfMaximumSelected=function(_,successCallback){var self=this;this.current(function(currentData){var count=currentData!=null?currentData.length:0;if(self.maximumSelectionLength>0&&count>=self.maximumSelectionLength){self.trigger("results:message",{message:"maximumSelected",args:{maximum:self.maximumSelectionLength}});return}if(successCallback){successCallback()}})};return MaximumSelectionLength});S2.define("select2/dropdown",["jquery","./utils"],function($,Utils){function Dropdown($element,options){this.$element=$element;this.options=options;Dropdown.__super__.constructor.call(this)}Utils.Extend(Dropdown,Utils.Observable);Dropdown.prototype.render=function(){var $dropdown=$('<span class="select2-dropdown">'+'<span class="select2-results"></span>'+"</span>");$dropdown.attr("dir",this.options.get("dir"));this.$dropdown=$dropdown;return $dropdown};Dropdown.prototype.bind=function(){};Dropdown.prototype.position=function($dropdown,$container){};Dropdown.prototype.destroy=function(){this.$dropdown.remove()};return Dropdown});S2.define("select2/dropdown/search",["jquery","../utils"],function($,Utils){function Search(){}Search.prototype.render=function(decorated){var $rendered=decorated.call(this);var $search=$('<span class="select2-search select2-search--dropdown">'+'<input class="select2-search__field" type="search" tabindex="-1"'+' autocomplete="off" autocorrect="off" autocapitalize="none"'+' spellcheck="false" role="searchbox" aria-autocomplete="list" />'+"</span>");this.$searchContainer=$search;this.$search=$search.find("input");$rendered.prepend($search);return $rendered};Search.prototype.bind=function(decorated,container,$container){var self=this;var resultsId=container.id+"-results";decorated.call(this,container,$container);this.$search.on("keydown",function(evt){self.trigger("keypress",evt);self._keyUpPrevented=evt.isDefaultPrevented()});this.$search.on("input",function(evt){$(this).off("keyup")});this.$search.on("keyup input",function(evt){self.handleSearch(evt)});container.on("open",function(){self.$search.attr("tabindex",0);self.$search.attr("aria-controls",resultsId);self.$search.trigger("focus");window.setTimeout(function(){self.$search.trigger("focus")},0)});container.on("close",function(){self.$search.attr("tabindex",-1);self.$search.removeAttr("aria-controls");self.$search.removeAttr("aria-activedescendant");self.$search.val("");self.$search.trigger("blur")});container.on("focus",function(){if(!container.isOpen()){self.$search.trigger("focus")}});container.on("results:all",function(params){if(params.query.term==null||params.query.term===""){var showSearch=self.showSearch(params);if(showSearch){self.$searchContainer.removeClass("select2-search--hide")}else{self.$searchContainer.addClass("select2-search--hide")}}});container.on("results:focus",function(params){if(params.data._resultId){self.$search.attr("aria-activedescendant",params.data._resultId)}else{self.$search.removeAttr("aria-activedescendant")}})};Search.prototype.handleSearch=function(evt){if(!this._keyUpPrevented){var input=this.$search.val();this.trigger("query",{term:input})}this._keyUpPrevented=false};Search.prototype.showSearch=function(_,params){return true};return Search});S2.define("select2/dropdown/hidePlaceholder",[],function(){function HidePlaceholder(decorated,$element,options,dataAdapter){this.placeholder=this.normalizePlaceholder(options.get("placeholder"));decorated.call(this,$element,options,dataAdapter)}HidePlaceholder.prototype.append=function(decorated,data){data.results=this.removePlaceholder(data.results);decorated.call(this,data)};HidePlaceholder.prototype.normalizePlaceholder=function(_,placeholder){if(typeof placeholder==="string"){placeholder={id:"",text:placeholder}}return placeholder};HidePlaceholder.prototype.removePlaceholder=function(_,data){var modifiedData=data.slice(0);for(var d=data.length-1;d>=0;d--){var item=data[d];if(this.placeholder.id===item.id){modifiedData.splice(d,1)}}return modifiedData};return HidePlaceholder});S2.define("select2/dropdown/infiniteScroll",["jquery"],function($){function InfiniteScroll(decorated,$element,options,dataAdapter){this.lastParams={};decorated.call(this,$element,options,dataAdapter);this.$loadingMore=this.createLoadingMore();this.loading=false}InfiniteScroll.prototype.append=function(decorated,data){this.$loadingMore.remove();this.loading=false;decorated.call(this,data);if(this.showLoadingMore(data)){this.$results.append(this.$loadingMore);this.loadMoreIfNeeded()}};InfiniteScroll.prototype.bind=function(decorated,container,$container){var self=this;decorated.call(this,container,$container);container.on("query",function(params){self.lastParams=params;self.loading=true});container.on("query:append",function(params){self.lastParams=params;self.loading=true});this.$results.on("scroll",this.loadMoreIfNeeded.bind(this))};InfiniteScroll.prototype.loadMoreIfNeeded=function(){var isLoadMoreVisible=$.contains(document.documentElement,this.$loadingMore[0]);if(this.loading||!isLoadMoreVisible){return}var currentOffset=this.$results.offset().top+this.$results.outerHeight(false);var loadingMoreOffset=this.$loadingMore.offset().top+this.$loadingMore.outerHeight(false);if(currentOffset+50>=loadingMoreOffset){this.loadMore()}};InfiniteScroll.prototype.loadMore=function(){this.loading=true;var params=$.extend({},{page:1},this.lastParams);params.page++;this.trigger("query:append",params)};InfiniteScroll.prototype.showLoadingMore=function(_,data){return data.pagination&&data.pagination.more};InfiniteScroll.prototype.createLoadingMore=function(){var $option=$("<li "+'class="select2-results__option select2-results__option--load-more"'+'role="option" aria-disabled="true"></li>');var message=this.options.get("translations").get("loadingMore");$option.html(message(this.lastParams));return $option};return InfiniteScroll});S2.define("select2/dropdown/attachBody",["jquery","../utils"],function($,Utils){function AttachBody(decorated,$element,options){this.$dropdownParent=$(options.get("dropdownParent")||document.body);decorated.call(this,$element,options)}AttachBody.prototype.bind=function(decorated,container,$container){var self=this;decorated.call(this,container,$container);container.on("open",function(){self._showDropdown();self._attachPositioningHandler(container);self._bindContainerResultHandlers(container)});container.on("close",function(){self._hideDropdown();self._detachPositioningHandler(container)});this.$dropdownContainer.on("mousedown",function(evt){evt.stopPropagation()})};AttachBody.prototype.destroy=function(decorated){decorated.call(this);this.$dropdownContainer.remove()};AttachBody.prototype.position=function(decorated,$dropdown,$container){$dropdown.attr("class",$container.attr("class"));$dropdown.removeClass("select2");$dropdown.addClass("select2-container--open");$dropdown.css({position:"absolute",top:-999999});this.$container=$container};AttachBody.prototype.render=function(decorated){var $container=$("<span></span>");var $dropdown=decorated.call(this);$container.append($dropdown);this.$dropdownContainer=$container;return $container};AttachBody.prototype._hideDropdown=function(decorated){this.$dropdownContainer.detach()};AttachBody.prototype._bindContainerResultHandlers=function(decorated,container){if(this._containerResultsHandlersBound){return}var self=this;container.on("results:all",function(){self._positionDropdown();self._resizeDropdown()});container.on("results:append",function(){self._positionDropdown();self._resizeDropdown()});container.on("results:message",function(){self._positionDropdown();self._resizeDropdown()});container.on("select",function(){self._positionDropdown();self._resizeDropdown()});container.on("unselect",function(){self._positionDropdown();self._resizeDropdown()});this._containerResultsHandlersBound=true};AttachBody.prototype._attachPositioningHandler=function(decorated,container){var self=this;var scrollEvent="scroll.select2."+container.id;var resizeEvent="resize.select2."+container.id;var orientationEvent="orientationchange.select2."+container.id;var $watchers=this.$container.parents().filter(Utils.hasScroll);$watchers.each(function(){Utils.StoreData(this,"select2-scroll-position",{x:$(this).scrollLeft(),y:$(this).scrollTop()})});$watchers.on(scrollEvent,function(ev){var position=Utils.GetData(this,"select2-scroll-position");$(this).scrollTop(position.y)});$(window).on(scrollEvent+" "+resizeEvent+" "+orientationEvent,function(e){self._positionDropdown();self._resizeDropdown()})};AttachBody.prototype._detachPositioningHandler=function(decorated,container){var scrollEvent="scroll.select2."+container.id;var resizeEvent="resize.select2."+container.id;var orientationEvent="orientationchange.select2."+container.id;var $watchers=this.$container.parents().filter(Utils.hasScroll);$watchers.off(scrollEvent);$(window).off(scrollEvent+" "+resizeEvent+" "+orientationEvent)};AttachBody.prototype._positionDropdown=function(){var $window=$(window);var isCurrentlyAbove=this.$dropdown.hasClass("select2-dropdown--above");var isCurrentlyBelow=this.$dropdown.hasClass("select2-dropdown--below");var newDirection=null;var offset=this.$container.offset();offset.bottom=offset.top+this.$container.outerHeight(false);var container={height:this.$container.outerHeight(false)};container.top=offset.top;container.bottom=offset.top+container.height;var dropdown={height:this.$dropdown.outerHeight(false)};var viewport={top:$window.scrollTop(),bottom:$window.scrollTop()+$window.height()};var enoughRoomAbove=viewport.top<(offset.top-dropdown.height);var enoughRoomBelow=viewport.bottom>(offset.bottom+dropdown.height);var css={left:offset.left,top:container.bottom};var $offsetParent=this.$dropdownParent;if($offsetParent.css("position")==="static"){$offsetParent=$offsetParent.offsetParent()}var parentOffset={top:0,left:0};if($.contains(document.body,$offsetParent[0])||$offsetParent[0].isConnected){parentOffset=$offsetParent.offset()}css.top-=parentOffset.top;css.left-=parentOffset.left;if(!isCurrentlyAbove&&!isCurrentlyBelow){newDirection="below"}if(!enoughRoomBelow&&enoughRoomAbove&&!isCurrentlyAbove){newDirection="above"}else{if(!enoughRoomAbove&&enoughRoomBelow&&isCurrentlyAbove){newDirection="below"}}if(newDirection=="above"||(isCurrentlyAbove&&newDirection!=="below")){css.top=container.top-parentOffset.top-dropdown.height}if(newDirection!=null){this.$dropdown.removeClass("select2-dropdown--below select2-dropdown--above").addClass("select2-dropdown--"+newDirection);this.$container.removeClass("select2-container--below select2-container--above").addClass("select2-container--"+newDirection)}this.$dropdownContainer.css(css)};AttachBody.prototype._resizeDropdown=function(){var css={width:this.$container.outerWidth(false)+"px"};if(this.options.get("dropdownAutoWidth")){css.minWidth=css.width;css.position="relative";css.width="auto"}this.$dropdown.css(css)};AttachBody.prototype._showDropdown=function(decorated){this.$dropdownContainer.appendTo(this.$dropdownParent);this._positionDropdown();this._resizeDropdown()};return AttachBody});S2.define("select2/dropdown/minimumResultsForSearch",[],function(){function countResults(data){var count=0;for(var d=0;d<data.length;d++){var item=data[d];if(item.children){count+=countResults(item.children)}else{count++}}return count}function MinimumResultsForSearch(decorated,$element,options,dataAdapter){this.minimumResultsForSearch=options.get("minimumResultsForSearch");if(this.minimumResultsForSearch<0){this.minimumResultsForSearch=Infinity}decorated.call(this,$element,options,dataAdapter)}MinimumResultsForSearch.prototype.showSearch=function(decorated,params){if(countResults(params.data.results)<this.minimumResultsForSearch){return false}return decorated.call(this,params)};return MinimumResultsForSearch});S2.define("select2/dropdown/selectOnClose",["../utils"],function(Utils){function SelectOnClose(){}SelectOnClose.prototype.bind=function(decorated,container,$container){var self=this;decorated.call(this,container,$container);container.on("close",function(params){self._handleSelectOnClose(params)})};SelectOnClose.prototype._handleSelectOnClose=function(_,params){if(params&&params.originalSelect2Event!=null){var event=params.originalSelect2Event;if(event._type==="select"||event._type==="unselect"){return}}var $highlightedResults=this.getHighlightedResults();if($highlightedResults.length<1){return}var data=Utils.GetData($highlightedResults[0],"data");if((data.element!=null&&data.element.selected)||(data.element==null&&data.selected)){return}this.trigger("select",{data:data})};return SelectOnClose});S2.define("select2/dropdown/closeOnSelect",[],function(){function CloseOnSelect(){}CloseOnSelect.prototype.bind=function(decorated,container,$container){var self=this;decorated.call(this,container,$container);container.on("select",function(evt){self._selectTriggered(evt)});container.on("unselect",function(evt){self._selectTriggered(evt)})};CloseOnSelect.prototype._selectTriggered=function(_,evt){var originalEvent=evt.originalEvent;if(originalEvent&&(originalEvent.ctrlKey||originalEvent.metaKey)){return}this.trigger("close",{originalEvent:originalEvent,originalSelect2Event:evt})};return CloseOnSelect});S2.define("select2/i18n/en",[],function(){return{errorLoading:function(){return"无法载入结果。"},inputTooLong:function(args){var overChars=args.input.length-args.maximum;var message="请删除"+overChars+"个字符";if(overChars!=1){message+="s"}return message},inputTooShort:function(args){var remainingChars=args.minimum-args.input.length;var message="请再输入至少"+remainingChars+"个字符";return message},loadingMore:function(){return"载入更多结果…"},maximumSelected:function(args){var message="最多只能"+args.maximum+"个选项";if(args.maximum!=1){message+="s"}return message},noResults:function(){return"未找到结果"},searching:function(){return"搜索中…"},removeAllItems:function(){return"删除所有项目"}}});S2.define("select2/defaults",["jquery","require","./results","./selection/single","./selection/multiple","./selection/placeholder","./selection/allowClear","./selection/search","./selection/eventRelay","./utils","./translation","./diacritics","./data/select","./data/array","./data/ajax","./data/tags","./data/tokenizer","./data/minimumInputLength","./data/maximumInputLength","./data/maximumSelectionLength","./dropdown","./dropdown/search","./dropdown/hidePlaceholder","./dropdown/infiniteScroll","./dropdown/attachBody","./dropdown/minimumResultsForSearch","./dropdown/selectOnClose","./dropdown/closeOnSelect","./i18n/en"],function($,require,ResultsList,SingleSelection,MultipleSelection,Placeholder,AllowClear,SelectionSearch,EventRelay,Utils,Translation,DIACRITICS,SelectData,ArrayData,AjaxData,Tags,Tokenizer,MinimumInputLength,MaximumInputLength,MaximumSelectionLength,Dropdown,DropdownSearch,HidePlaceholder,InfiniteScroll,AttachBody,MinimumResultsForSearch,SelectOnClose,CloseOnSelect,EnglishTranslation){function Defaults(){this.reset()}Defaults.prototype.apply=function(options){options=$.extend(true,{},this.defaults,options);if(options.dataAdapter==null){if(options.ajax!=null){options.dataAdapter=AjaxData}else{if(options.data!=null){options.dataAdapter=ArrayData}else{options.dataAdapter=SelectData}}if(options.minimumInputLength>0){options.dataAdapter=Utils.Decorate(options.dataAdapter,MinimumInputLength)}if(options.maximumInputLength>0){options.dataAdapter=Utils.Decorate(options.dataAdapter,MaximumInputLength)}if(options.maximumSelectionLength>0){options.dataAdapter=Utils.Decorate(options.dataAdapter,MaximumSelectionLength)}if(options.tags){options.dataAdapter=Utils.Decorate(options.dataAdapter,Tags)}if(options.tokenSeparators!=null||options.tokenizer!=null){options.dataAdapter=Utils.Decorate(options.dataAdapter,Tokenizer)}if(options.query!=null){var Query=require(options.amdBase+"compat/query");options.dataAdapter=Utils.Decorate(options.dataAdapter,Query)}if(options.initSelection!=null){var InitSelection=require(options.amdBase+"compat/initSelection");options.dataAdapter=Utils.Decorate(options.dataAdapter,InitSelection)}}if(options.resultsAdapter==null){options.resultsAdapter=ResultsList;if(options.ajax!=null){options.resultsAdapter=Utils.Decorate(options.resultsAdapter,InfiniteScroll)}if(options.placeholder!=null){options.resultsAdapter=Utils.Decorate(options.resultsAdapter,HidePlaceholder)}if(options.selectOnClose){options.resultsAdapter=Utils.Decorate(options.resultsAdapter,SelectOnClose)}}if(options.dropdownAdapter==null){if(options.multiple){options.dropdownAdapter=Dropdown}else{var SearchableDropdown=Utils.Decorate(Dropdown,DropdownSearch);options.dropdownAdapter=SearchableDropdown}if(options.minimumResultsForSearch!==0){options.dropdownAdapter=Utils.Decorate(options.dropdownAdapter,MinimumResultsForSearch)}if(options.closeOnSelect){options.dropdownAdapter=Utils.Decorate(options.dropdownAdapter,CloseOnSelect)}if(options.dropdownCssClass!=null||options.dropdownCss!=null||options.adaptDropdownCssClass!=null){var DropdownCSS=require(options.amdBase+"compat/dropdownCss");options.dropdownAdapter=Utils.Decorate(options.dropdownAdapter,DropdownCSS)}options.dropdownAdapter=Utils.Decorate(options.dropdownAdapter,AttachBody)}if(options.selectionAdapter==null){if(options.multiple){options.selectionAdapter=MultipleSelection}else{options.selectionAdapter=SingleSelection}if(options.placeholder!=null){options.selectionAdapter=Utils.Decorate(options.selectionAdapter,Placeholder)}if(options.allowClear){options.selectionAdapter=Utils.Decorate(options.selectionAdapter,AllowClear)}if(options.multiple){options.selectionAdapter=Utils.Decorate(options.selectionAdapter,SelectionSearch)}if(options.containerCssClass!=null||options.containerCss!=null||options.adaptContainerCssClass!=null){var ContainerCSS=require(options.amdBase+"compat/containerCss");options.selectionAdapter=Utils.Decorate(options.selectionAdapter,ContainerCSS)}options.selectionAdapter=Utils.Decorate(options.selectionAdapter,EventRelay)}options.language=this._resolveLanguage(options.language);options.language.push("en");var uniqueLanguages=[];for(var l=0;l<options.language.length;l++){var language=options.language[l];if(uniqueLanguages.indexOf(language)===-1){uniqueLanguages.push(language)}}options.language=uniqueLanguages;options.translations=this._processTranslations(options.language,options.debug);return options};Defaults.prototype.reset=function(){function stripDiacritics(text){function match(a){return DIACRITICS[a]||a}return text.replace(/[^\u0000-\u007E]/g,match)}function matcher(params,data){if($.trim(params.term)===""){return data}if(data.children&&data.children.length>0){var match=$.extend(true,{},data);for(var c=data.children.length-1;c>=0;c--){var child=data.children[c];var matches=matcher(params,child);if(matches==null){match.children.splice(c,1)}}if(match.children.length>0){return match}return matcher(params,match)}var original=stripDiacritics(data.text).toUpperCase();var term=stripDiacritics(params.term).toUpperCase();if(original.indexOf(term)>-1){return data}return null}this.defaults={amdBase:"./",amdLanguageBase:"./i18n/",closeOnSelect:true,debug:false,dropdownAutoWidth:false,escapeMarkup:Utils.escapeMarkup,language:{},matcher:matcher,minimumInputLength:0,maximumInputLength:0,maximumSelectionLength:0,minimumResultsForSearch:0,selectOnClose:false,scrollAfterSelect:false,sorter:function(data){return data},templateResult:function(result){return result.text},templateSelection:function(selection){return selection.text},theme:"default",width:"resolve"}};Defaults.prototype.applyFromElement=function(options,$element){var optionLanguage=options.language;var defaultLanguage=this.defaults.language;var elementLanguage=$element.prop("lang");var parentLanguage=$element.closest("[lang]").prop("lang");var languages=Array.prototype.concat.call(this._resolveLanguage(elementLanguage),this._resolveLanguage(optionLanguage),this._resolveLanguage(defaultLanguage),this._resolveLanguage(parentLanguage));options.language=languages;return options};Defaults.prototype._resolveLanguage=function(language){if(!language){return[]}if($.isEmptyObject(language)){return[]}if($.isPlainObject(language)){return[language]}var languages;if(!$.isArray(language)){languages=[language]}else{languages=language}var resolvedLanguages=[];for(var l=0;l<languages.length;l++){resolvedLanguages.push(languages[l]);if(typeof languages[l]==="string"&&languages[l].indexOf("-")>0){var languageParts=languages[l].split("-");var baseLanguage=languageParts[0];resolvedLanguages.push(baseLanguage)}}return resolvedLanguages};Defaults.prototype._processTranslations=function(languages,debug){var translations=new Translation();for(var l=0;l<languages.length;l++){var languageData=new Translation();var language=languages[l];if(typeof language==="string"){try{languageData=Translation.loadPath(language)}catch(e){try{language=this.defaults.amdLanguageBase+language;languageData=Translation.loadPath(language)}catch(ex){if(debug&&window.console&&console.warn){console.warn('Select2: The language file for "'+language+'" could '+"not be automatically loaded. A fallback will be used instead.")}}}}else{if($.isPlainObject(language)){languageData=new Translation(language)}else{languageData=language}}translations.extend(languageData)}return translations};Defaults.prototype.set=function(key,value){var camelKey=$.camelCase(key);var data={};data[camelKey]=value;var convertedData=Utils._convertData(data);$.extend(true,this.defaults,convertedData)};var defaults=new Defaults();return defaults});S2.define("select2/options",["require","jquery","./defaults","./utils"],function(require,$,Defaults,Utils){function Options(options,$element){this.options=options;if($element!=null){this.fromElement($element)}if($element!=null){this.options=Defaults.applyFromElement(this.options,$element)}this.options=Defaults.apply(this.options);if($element&&$element.is("input")){var InputCompat=require(this.get("amdBase")+"compat/inputData");this.options.dataAdapter=Utils.Decorate(this.options.dataAdapter,InputCompat)}}Options.prototype.fromElement=function($e){var excludedData=["select2"];if(this.options.multiple==null){this.options.multiple=$e.prop("multiple")}if(this.options.disabled==null){this.options.disabled=$e.prop("disabled")}if(this.options.dir==null){if($e.prop("dir")){this.options.dir=$e.prop("dir")}else{if($e.closest("[dir]").prop("dir")){this.options.dir=$e.closest("[dir]").prop("dir")}else{this.options.dir="ltr"}}}$e.prop("disabled",this.options.disabled);$e.prop("multiple",this.options.multiple);if(Utils.GetData($e[0],"select2Tags")){if(this.options.debug&&window.console&&console.warn){console.warn("Select2: The `data-select2-tags` attribute has been changed to "+'use the `data-data` and `data-tags="true"` attributes and will be '+"removed in future versions of Select2.")}Utils.StoreData($e[0],"data",Utils.GetData($e[0],"select2Tags"));Utils.StoreData($e[0],"tags",true)}if(Utils.GetData($e[0],"ajaxUrl")){if(this.options.debug&&window.console&&console.warn){console.warn("Select2: The `data-ajax-url` attribute has been changed to "+"`data-ajax--url` and support for the old attribute will be removed"+" in future versions of Select2.")}$e.attr("ajax--url",Utils.GetData($e[0],"ajaxUrl"));Utils.StoreData($e[0],"ajax-Url",Utils.GetData($e[0],"ajaxUrl"))}var dataset={};function upperCaseLetter(_,letter){return letter.toUpperCase()}for(var attr=0;attr<$e[0].attributes.length;attr++){var attributeName=$e[0].attributes[attr].name;var prefix="data-";if(attributeName.substr(0,prefix.length)==prefix){var dataName=attributeName.substring(prefix.length);var dataValue=Utils.GetData($e[0],dataName);var camelDataName=dataName.replace(/-([a-z])/g,upperCaseLetter);dataset[camelDataName]=dataValue}}if($.fn.jquery&&$.fn.jquery.substr(0,2)=="1."&&$e[0].dataset){dataset=$.extend(true,{},$e[0].dataset,dataset)}var data=$.extend(true,{},Utils.GetData($e[0]),dataset);data=Utils._convertData(data);for(var key in data){if($.inArray(key,excludedData)>-1){continue}if($.isPlainObject(this.options[key])){$.extend(this.options[key],data[key])}else{this.options[key]=data[key]}}return this};Options.prototype.get=function(key){return this.options[key]};Options.prototype.set=function(key,val){this.options[key]=val};return Options});S2.define("select2/core",["jquery","./options","./utils","./keys"],function($,Options,Utils,KEYS){var Select2=function($element,options){if(Utils.GetData($element[0],"select2")!=null){Utils.GetData($element[0],"select2").destroy()}this.$element=$element;this.id=this._generateId($element);options=options||{};this.options=new Options(options,$element);Select2.__super__.constructor.call(this);var tabindex=$element.attr("tabindex")||0;Utils.StoreData($element[0],"old-tabindex",tabindex);$element.attr("tabindex","-1");var DataAdapter=this.options.get("dataAdapter");this.dataAdapter=new DataAdapter($element,this.options);var $container=this.render();this._placeContainer($container);var SelectionAdapter=this.options.get("selectionAdapter");this.selection=new SelectionAdapter($element,this.options);this.$selection=this.selection.render();this.selection.position(this.$selection,$container);var DropdownAdapter=this.options.get("dropdownAdapter");this.dropdown=new DropdownAdapter($element,this.options);this.$dropdown=this.dropdown.render();this.dropdown.position(this.$dropdown,$container);var ResultsAdapter=this.options.get("resultsAdapter");this.results=new ResultsAdapter($element,this.options,this.dataAdapter);this.$results=this.results.render();this.results.position(this.$results,this.$dropdown);var self=this;this._bindAdapters();this._registerDomEvents();this._registerDataEvents();this._registerSelectionEvents();this._registerDropdownEvents();this._registerResultsEvents();this._registerEvents();this.dataAdapter.current(function(initialData){self.trigger("selection:update",{data:initialData})});$element.addClass("select2-hidden-accessible");$element.attr("aria-hidden","true");this._syncAttributes();Utils.StoreData($element[0],"select2",this);$element.data("select2",this)};Utils.Extend(Select2,Utils.Observable);Select2.prototype._generateId=function($element){var id="";if($element.attr("id")!=null){id=$element.attr("id")}else{if($element.attr("name")!=null){id=$element.attr("name")+"-"+Utils.generateChars(2)}else{id=Utils.generateChars(4)}}id=id.replace(/(:|\.|\[|\]|,)/g,"");id="select2-"+id;return id};Select2.prototype._placeContainer=function($container){$container.insertAfter(this.$element);var width=this._resolveWidth(this.$element,this.options.get("width"));if(width!=null){$container.css("width",width)}};Select2.prototype._resolveWidth=function($element,method){var WIDTH=/^width:(([-+]?([0-9]*\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i;if(method=="resolve"){var styleWidth=this._resolveWidth($element,"style");if(styleWidth!=null){return styleWidth}return this._resolveWidth($element,"element")}if(method=="element"){var elementWidth=$element.outerWidth(false);if(elementWidth<=0){return"auto"}return elementWidth+"px"}if(method=="style"){var style=$element.attr("style");if(typeof(style)!=="string"){return null}var attrs=style.split(";");for(var i=0,l=attrs.length;i<l;i=i+1){var attr=attrs[i].replace(/\s/g,"");var matches=attr.match(WIDTH);if(matches!==null&&matches.length>=1){return matches[1]}}return null}if(method=="computedstyle"){var computedStyle=window.getComputedStyle($element[0]);return computedStyle.width}return method};Select2.prototype._bindAdapters=function(){this.dataAdapter.bind(this,this.$container);this.selection.bind(this,this.$container);this.dropdown.bind(this,this.$container);this.results.bind(this,this.$container)};Select2.prototype._registerDomEvents=function(){var self=this;this.$element.on("change.select2",function(){self.dataAdapter.current(function(data){self.trigger("selection:update",{data:data})})});this.$element.on("focus.select2",function(evt){self.trigger("focus",evt)});this._syncA=Utils.bind(this._syncAttributes,this);this._syncS=Utils.bind(this._syncSubtree,this);if(this.$element[0].attachEvent){this.$element[0].attachEvent("onpropertychange",this._syncA)}var observer=window.MutationObserver||window.WebKitMutationObserver||window.MozMutationObserver;if(observer!=null){this._observer=new observer(function(mutations){self._syncA();self._syncS(null,mutations)});this._observer.observe(this.$element[0],{attributes:true,childList:true,subtree:false})}else{if(this.$element[0].addEventListener){this.$element[0].addEventListener("DOMAttrModified",self._syncA,false);this.$element[0].addEventListener("DOMNodeInserted",self._syncS,false);this.$element[0].addEventListener("DOMNodeRemoved",self._syncS,false)}}};Select2.prototype._registerDataEvents=function(){var self=this;this.dataAdapter.on("*",function(name,params){self.trigger(name,params)})};Select2.prototype._registerSelectionEvents=function(){var self=this;var nonRelayEvents=["toggle","focus"];this.selection.on("toggle",function(){self.toggleDropdown()});this.selection.on("focus",function(params){self.focus(params)});this.selection.on("*",function(name,params){if($.inArray(name,nonRelayEvents)!==-1){return}self.trigger(name,params)})};Select2.prototype._registerDropdownEvents=function(){var self=this;this.dropdown.on("*",function(name,params){self.trigger(name,params)})};Select2.prototype._registerResultsEvents=function(){var self=this;this.results.on("*",function(name,params){self.trigger(name,params)})};Select2.prototype._registerEvents=function(){var self=this;this.on("open",function(){self.$container.addClass("select2-container--open")});this.on("close",function(){self.$container.removeClass("select2-container--open")});this.on("enable",function(){self.$container.removeClass("select2-container--disabled")});this.on("disable",function(){self.$container.addClass("select2-container--disabled")});this.on("blur",function(){self.$container.removeClass("select2-container--focus")});this.on("query",function(params){if(!self.isOpen()){self.trigger("open",{})}this.dataAdapter.query(params,function(data){self.trigger("results:all",{data:data,query:params})})});this.on("query:append",function(params){this.dataAdapter.query(params,function(data){self.trigger("results:append",{data:data,query:params})})});this.on("keypress",function(evt){var key=evt.which;if(self.isOpen()){if(key===KEYS.ESC||key===KEYS.TAB||(key===KEYS.UP&&evt.altKey)){self.close(evt);evt.preventDefault()}else{if(key===KEYS.ENTER){self.trigger("results:select",{});evt.preventDefault()}else{if((key===KEYS.SPACE&&evt.ctrlKey)){self.trigger("results:toggle",{});evt.preventDefault()}else{if(key===KEYS.UP){self.trigger("results:previous",{});evt.preventDefault()}else{if(key===KEYS.DOWN){self.trigger("results:next",{});evt.preventDefault()}}}}}}else{if(key===KEYS.ENTER||key===KEYS.SPACE||(key===KEYS.DOWN&&evt.altKey)){self.open();evt.preventDefault()}}})};Select2.prototype._syncAttributes=function(){this.options.set("disabled",this.$element.prop("disabled"));if(this.isDisabled()){if(this.isOpen()){this.close()}this.trigger("disable",{})}else{this.trigger("enable",{})}};Select2.prototype._isChangeMutation=function(evt,mutations){var changed=false;var self=this;if(evt&&evt.target&&(evt.target.nodeName!=="OPTION"&&evt.target.nodeName!=="OPTGROUP")){return}if(!mutations){changed=true}else{if(mutations.addedNodes&&mutations.addedNodes.length>0){for(var n=0;n<mutations.addedNodes.length;n++){var node=mutations.addedNodes[n];if(node.selected){changed=true}}}else{if(mutations.removedNodes&&mutations.removedNodes.length>0){changed=true}else{if($.isArray(mutations)){$.each(mutations,function(evt,mutation){if(self._isChangeMutation(evt,mutation)){changed=true;return false}})}}}}return changed};Select2.prototype._syncSubtree=function(evt,mutations){var changed=this._isChangeMutation(evt,mutations);var self=this;if(changed){this.dataAdapter.current(function(currentData){self.trigger("selection:update",{data:currentData})})}};Select2.prototype.trigger=function(name,args){var actualTrigger=Select2.__super__.trigger;var preTriggerMap={"open":"opening","close":"closing","select":"selecting","unselect":"unselecting","clear":"clearing"};if(args===undefined){args={}}if(name in preTriggerMap){var preTriggerName=preTriggerMap[name];var preTriggerArgs={prevented:false,name:name,args:args};actualTrigger.call(this,preTriggerName,preTriggerArgs);if(preTriggerArgs.prevented){args.prevented=true;return}}actualTrigger.call(this,name,args)};Select2.prototype.toggleDropdown=function(){if(this.isDisabled()){return}if(this.isOpen()){this.close()}else{this.open()}};Select2.prototype.open=function(){if(this.isOpen()){return}if(this.isDisabled()){return}this.trigger("query",{})};Select2.prototype.close=function(evt){if(!this.isOpen()){return}this.trigger("close",{originalEvent:evt})};Select2.prototype.isEnabled=function(){return !this.isDisabled()};Select2.prototype.isDisabled=function(){return this.options.get("disabled")};Select2.prototype.isOpen=function(){return this.$container.hasClass("select2-container--open")};Select2.prototype.hasFocus=function(){return this.$container.hasClass("select2-container--focus")};Select2.prototype.focus=function(data){if(this.hasFocus()){return}this.$container.addClass("select2-container--focus");this.trigger("focus",{})};Select2.prototype.enable=function(args){if(this.options.get("debug")&&window.console&&console.warn){console.warn('Select2: The `select2("enable")` method has been deprecated and will'+' be removed in later Select2 versions. Use $element.prop("disabled")'+" instead.")}if(args==null||args.length===0){args=[true]}var disabled=!args[0];this.$element.prop("disabled",disabled)};Select2.prototype.data=function(){if(this.options.get("debug")&&arguments.length>0&&window.console&&console.warn){console.warn('Select2: Data can no longer be set using `select2("data")`. You '+"should consider setting the value instead using `$element.val()`.")}var data=[];this.dataAdapter.current(function(currentData){data=currentData});return data};Select2.prototype.val=function(args){if(this.options.get("debug")&&window.console&&console.warn){console.warn('Select2: The `select2("val")` method has been deprecated and will be'+" removed in later Select2 versions. Use $element.val() instead.")}if(args==null||args.length===0){return this.$element.val()}var newVal=args[0];if($.isArray(newVal)){newVal=$.map(newVal,function(obj){return obj.toString()})}this.$element.val(newVal).trigger("input").trigger("change")};Select2.prototype.destroy=function(){this.$container.remove();if(this.$element[0].detachEvent){this.$element[0].detachEvent("onpropertychange",this._syncA)}if(this._observer!=null){this._observer.disconnect();this._observer=null}else{if(this.$element[0].removeEventListener){this.$element[0].removeEventListener("DOMAttrModified",this._syncA,false);this.$element[0].removeEventListener("DOMNodeInserted",this._syncS,false);this.$element[0].removeEventListener("DOMNodeRemoved",this._syncS,false)}}this._syncA=null;this._syncS=null;this.$element.off(".select2");this.$element.attr("tabindex",Utils.GetData(this.$element[0],"old-tabindex"));this.$element.removeClass("select2-hidden-accessible");this.$element.attr("aria-hidden","false");Utils.RemoveData(this.$element[0]);this.$element.removeData("select2");this.dataAdapter.destroy();this.selection.destroy();this.dropdown.destroy();this.results.destroy();this.dataAdapter=null;this.selection=null;this.dropdown=null;this.results=null};Select2.prototype.render=function(){var $container=$('<span class="select2 select2-container">'+'<span class="selection"></span>'+'<span class="dropdown-wrapper" aria-hidden="true"></span>'+"</span>");$container.attr("dir",this.options.get("dir"));this.$container=$container;this.$container.addClass("select2-container--"+this.options.get("theme"));Utils.StoreData($container[0],"element",this.$element);return $container};return Select2});S2.define("jquery-mousewheel",["jquery"],function($){return $});S2.define("jquery.select2",["jquery","jquery-mousewheel","./select2/core","./select2/defaults","./select2/utils"],function($,_,Select2,Defaults,Utils){if($.fn.select2==null){var thisMethods=["open","close","destroy"];$.fn.select2=function(options){options=options||{};if(typeof options==="object"){this.each(function(){var instanceOptions=$.extend(true,{},options);var instance=new Select2($(this),instanceOptions)});return this}else{if(typeof options==="string"){var ret;var args=Array.prototype.slice.call(arguments,1);this.each(function(){var instance=Utils.GetData(this,"select2");if(instance==null&&window.console&&console.error){console.error("The select2('"+options+"') method was called on an "+"element that is not using Select2.")}ret=instance[options].apply(instance,args)});if($.inArray(options,thisMethods)>-1){return this}return ret}else{throw new Error("Invalid arguments for Select2: "+options)}}}}if($.fn.select2.defaults==null){$.fn.select2.defaults=Defaults}return Select2});return{define:S2.define,require:S2.require}}());var select2=S2.require("jquery.select2");jQuery.fn.select2.amd=S2;return select2}));
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/smartwizard/jquery.smartWizard.min.js b/ruoyi-admin/src/main/resources/static/ajax/libs/smartwizard/jquery.smartWizard.min.js
new file mode 100644
index 0000000..bdbcf7e
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/smartwizard/jquery.smartWizard.min.js
@@ -0,0 +1,13 @@
+"use strict";function _classCallCheck(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function _defineProperties(t,e){for(var s=0;s<e.length;s++){var i=e[s];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,i.key,i)}}function _createClass(t,e,s){return e&&_defineProperties(t.prototype,e),s&&_defineProperties(t,s),t}function _typeof(t){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}
+/*!
+ * jQuery SmartWizard v5.1.1
+ * The awesome jQuery step wizard plugin
+ * http://www.techlaboratory.net/jquery-smartwizard
+ *
+ * Created by Dipu Raj
+ * http://dipu.me
+ *
+ * @license Licensed under the terms of the MIT License
+ * https://github.com/techlab/jquery-smartwizard/blob/master/LICENSE
+ */
+!function(s){"function"==typeof define&&define.amd?define(["jquery"],s):"object"===("undefined"==typeof module?"undefined":_typeof(module))&&module.exports?module.exports=function(t,e){return void 0===e&&(e="undefined"!=typeof window?require("jquery"):require("jquery")(t)),s(e),e}:s(jQuery)}(function(v){var i={selected:0,theme:"default",justified:!0,darkMode:!1,autoAdjustHeight:!0,cycleSteps:!1,backButtonSupport:!0,enableURLhash:!0,transition:{animation:"none",speed:"400",easing:""},toolbarSettings:{toolbarPosition:"bottom",toolbarButtonPosition:"right",showNextButton:!0,showPreviousButton:!0,toolbarExtraButtons:[]},anchorSettings:{anchorClickable:!0,enableAllAnchors:!1,markDoneStep:!0,markAllPreviousStepsAsDone:!0,removeDoneStepOnNavigateBack:!1,enableAnchorOnDoneStep:!0},keyboardSettings:{keyNavigation:!0,keyLeft:[37],keyRight:[39]},lang:{next:"Next",previous:"Previous"},disabledSteps:[],errorSteps:[],hiddenSteps:[]},s=function(){function s(t,e){_classCallCheck(this,s),this.options=v.extend(!0,{},i,e),this.main=v(t),this.nav=this._getFirstDescendant(".nav"),this.steps=this.nav.find(".nav-link"),this.container=this._getFirstDescendant(".tab-content"),this.pages=this.container.children(".tab-pane"),this._initOptions(),this._initLoad()}return _createClass(s,[{key:"_initLoad",value:function(){this.pages.hide(),this.steps.removeClass("done active"),this.current_index=null;var t=this._getStepIndex();this._setPreviousStepsDone(t),this._showStep(t)}},{key:"_initOptions",value:function(){this._setElements(),this._setToolbar(),this._setEvents()}},{key:"_getFirstDescendant",value:function(i){var n=this.main.children(i);return 0<n.length?n:(this.main.children().each(function(t,e){var s=v(e).children(i);if(0<s.length)return n=s,!1}),0<n.length?n:(this._showError("Element not found "+i),!1))}},{key:"_setElements",value:function(){this.main.addClass("sw"),this._setTheme(this.options.theme),this._setJustify(this.options.justified),this._setDarkMode(this.options.darkMode),!0===this.options.anchorSettings.enableAllAnchors&&!0===this.options.anchorSettings.anchorClickable||this.steps.addClass("inactive"),this._setCSSClass(this.options.disabledSteps,"disabled"),this._setCSSClass(this.options.errorSteps,"danger"),this._setCSSClass(this.options.hiddenSteps,"hidden")}},{key:"_setEvents",value:function(){var s=this;if(this.main.data("click-init"))return!0;this.main.data("click-init",!0),v(this.steps).on("click",function(t){if(t.preventDefault(),!1===s.options.anchorSettings.anchorClickable)return!0;var e=s.steps.index(t.currentTarget);return e===s.current_index||(!(!1!==s.options.anchorSettings.enableAnchorOnDoneStep||!s._isDone(e))||void(!1===s.options.anchorSettings.enableAllAnchors&&!s._isDone(e)||s._showStep(e)))}),this.main.find(".sw-btn-next").on("click",function(t){t.preventDefault(),s._showNext()}),this.main.find(".sw-btn-prev").on("click",function(t){t.preventDefault(),s._showPrevious()}),this.options.keyboardSettings.keyNavigation&&v(document).keyup(function(t){s._keyNav(t)}),this.options.backButtonSupport&&v(window).on("hashchange",function(t){var e=s._getURLHashIndex();!1!==e&&(t.preventDefault(),s._showStep(e))})}},{key:"_setToolbar",value:function(){if("none"===this.options.toolbarSettings.toolbarPosition)return!0;switch(this.options.toolbarSettings.toolbarPosition){case"top":this.container.before(this._createToolbar("top"));break;case"bottom":this.container.after(this._createToolbar("bottom"));break;case"both":this.container.before(this._createToolbar("top")),this.container.after(this._createToolbar("bottom"));break;default:this.container.after(this._createToolbar("bottom"))}}},{key:"_createToolbar",value:function(t){if(0<this.main.find(".toolbar-"+t).length)return null;var s=v("<div></div>").addClass("toolbar toolbar-"+t).attr("role","toolbar"),e=!1!==this.options.toolbarSettings.showNextButton?v("<button></button>").text(this.options.lang.next).addClass("btn sw-btn-next").attr("type","button"):null,i=!1!==this.options.toolbarSettings.showPreviousButton?v("<button></button>").text(this.options.lang.previous).addClass("btn sw-btn-prev").attr("type","button"):null;return s.append(i,e),this.options.toolbarSettings.toolbarExtraButtons&&0<this.options.toolbarSettings.toolbarExtraButtons.length&&v.each(this.options.toolbarSettings.toolbarExtraButtons,function(t,e){s.append(e.clone(!0))}),s.css("text-align",this.options.toolbarSettings.toolbarButtonPosition),s}},{key:"_showNext",value:function(){var t=this._getNextShowable(this.current_index);if(!1===t)return!1;this._showStep(t)}},{key:"_showPrevious",value:function(){var t=this._getPreviousShowable(this.current_index);if(!1===t)return!1;this._showStep(t)}},{key:"_showStep",value:function(t){return t!=this.current_index&&(!!this.steps.eq(t)&&(!!this._isShowable(t)&&void this._loadStep(t)))}},{key:"_getNextShowable",value:function(t){for(var e=!1,s=t+1;s<this.steps.length;s++)if(this._isShowable(s)){e=s;break}if(!1!==e&&this.steps.length<=e){if(!this.options.cycleSteps)return!1;e=0}return e}},{key:"_getPreviousShowable",value:function(t){for(var e=!1,s=t-1;0<=s;s--)if(this._isShowable(s)){e=s;break}if(!1!==e&&e<0){if(!this.options.cycleSteps)return!1;e=this.steps.length-1}return e}},{key:"_isShowable",value:function(t){var e=this.steps.eq(t);return!e.hasClass("disabled")&&!e.hasClass("hidden")}},{key:"_isDone",value:function(t){return!!this.steps.eq(t).hasClass("done")}},{key:"_setPreviousStepsDone",value:function(t){if(0<t&&this.options.anchorSettings.markDoneStep&&this.options.anchorSettings.markAllPreviousStepsAsDone)for(var e=t;0<=e;e--)this._setCSSClass(e,"done")}},{key:"_setCSSClass",value:function(t,e){var s=this;if(null===t)return!1;(v.isArray(t)?t:[t]).map(function(t){s.steps.eq(t).addClass(e)})}},{key:"_resetCSSClass",value:function(t,e){var s=this;(v.isArray(t)?t:[t]).map(function(t){s.steps.eq(t).removeClass(e)})}},{key:"_getStepDirection",value:function(t){return null==this.current_index?"":this.current_index<t?"forward":"backward"}},{key:"_getStepPosition",value:function(t){var e="middle";return 0===t?e="first":t===this.steps.length-1&&(e="last"),e}},{key:"_getStepAnchor",value:function(t){return null==t?null:this.steps.eq(t)}},{key:"_getStepPage",value:function(t){if(null==t)return null;var e=this._getStepAnchor(t);return 0<e.length?this.main.find(e.attr("href")):null}},{key:"_setStepContent",value:function(t,e){var s=this._getStepPage(t);s&&s.html(e)}},{key:"_loadStep",value:function(e){var s=this,t=this._getStepAnchor(this.current_index),i=this._getStepDirection(e);if(null!==this.current_index&&!1===this._triggerEvent("leaveStep",[t,this.current_index,e,i]))return!1;var n=this._getStepAnchor(e),o=this._triggerEvent("stepContent",[n,e,i]);o?"object"==_typeof(o)?o.then(function(t){s._setStepContent(e,t),s._transitStep(e)}).catch(function(t){console.error(t),s._setStepContent(e,t),s._transitStep(e)}):("string"==typeof o&&this._setStepContent(e,o),this._transitStep(e)):this._transitStep(e)}},{key:"_transitStep",value:function(t){var e=this,s=this._getStepAnchor(t);this._setURLHash(s.attr("href")),this._setAnchor(t);var i=this._getStepDirection(t),n=this._getStepPosition(t);this._doStepAnimation(t,function(){e._fixHeight(t),e._triggerEvent("showStep",[s,e.current_index,i,n])}),this.current_index=t,this._setButtons(t)}},{key:"_doStepAnimation",value:function(t,e){var s=this,i=this._getStepPage(this.current_index),n=this._getStepPage(t),o=this.options.transition.animation.toLowerCase();switch(this._stopAnimations(),o){case"slide-horizontal":case"slide-h":var a,r,h=this.container.width(),l=h,u=-2*h;t>this.current_index&&(l=-1*h,u=h),null==this.current_index&&this.container.height(n.outerHeight()),i&&(a=i.css("position"),r=i.css("left"),i.css("position","absolute").css("left",0).animate({left:l},this.options.transition.speed,this.options.transition.easing,function(){v(this).hide(),i.css("position",a).css("left",r)})),a=n.css("position"),r=n.css("left"),n.css("position","absolute").css("left",u).outerWidth(h).show().animate({left:0},this.options.transition.speed,this.options.transition.easing,function(){n.css("position",a).css("left",r),e()});break;case"slide-vertical":case"slide-v":var c,d,p=this.container.height(),f=p,_=-2*p;t>this.current_index&&(f=-1*p,_=p),i&&(c=i.css("position"),d=i.css("top"),i.css("position","absolute").css("top",0).animate({top:f},this.options.transition.speed,this.options.transition.easing,function(){v(this).hide(),i.css("position",c).css("top",d)})),c=n.css("position"),d=n.css("top"),n.css("position","absolute").css("top",_).show().animate({top:0},this.options.transition.speed,this.options.transition.easing,function(){n.css("position",c).css("top",d),e()});break;case"slide-swing":case"slide-s":i?i.slideUp("fast",this.options.transition.easing,function(){n.slideDown(s.options.transition.speed,s.options.transition.easing,function(){e()})}):n.slideDown(this.options.transition.speed,this.options.transition.easing,function(){e()});break;case"fade":i?i.fadeOut("fast",this.options.transition.easing,function(){n.fadeIn("fast",s.options.transition.easing,function(){e()})}):n.fadeIn(this.options.transition.speed,this.options.transition.easing,function(){e()});break;default:i&&i.hide(),n.show(),e()}}},{key:"_stopAnimations",value:function(){this.pages.finish(),this.container.finish()}},{key:"_setAnchor",value:function(t){this._resetCSSClass(this.current_index,"active"),!1!==this.options.anchorSettings.markDoneStep&&null!==this.current_index&&(this._setCSSClass(this.current_index,"done"),!1!==this.options.anchorSettings.removeDoneStepOnNavigateBack&&"backward"===this._getStepDirection(t)&&this._resetCSSClass(this.current_index,"done")),this._resetCSSClass(t,"done"),this._setCSSClass(t,"active")}},{key:"_setButtons",value:function(t){if(!this.options.cycleSteps)switch(this.main.find(".sw-btn-prev").removeClass("disabled"),this.main.find(".sw-btn-next").removeClass("disabled"),this._getStepPosition(t)){case"first":this.main.find(".sw-btn-prev").addClass("disabled");break;case"last":this.main.find(".sw-btn-next").addClass("disabled");break;default:!1===this._getNextShowable(t)&&this.main.find(".sw-btn-next").addClass("disabled"),!1===this._getPreviousShowable(t)&&this.main.find(".sw-btn-prev").addClass("disabled")}}},{key:"_getStepIndex",value:function(){var t=this._getURLHashIndex();return!1===t?this.options.selected:t}},{key:"_setTheme",value:function(t){this.main.removeClass(function(t,e){return(e.match(/(^|\s)sw-theme-\S+/g)||[]).join(" ")}).addClass("sw-theme-"+t)}},{key:"_setJustify",value:function(t){!0===t?this.main.addClass("sw-justified"):this.main.removeClass("sw-justified")}},{key:"_setDarkMode",value:function(t){!0===t?this.main.addClass("sw-dark"):this.main.removeClass("sw-dark")}},{key:"_keyNav",value:function(t){if(-1<v.inArray(t.which,this.options.keyboardSettings.keyLeft))this._showPrevious(),t.preventDefault();else{if(!(-1<v.inArray(t.which,this.options.keyboardSettings.keyRight)))return;this._showNext(),t.preventDefault()}}},{key:"_fixHeight",value:function(t){var e;this.options.autoAdjustHeight&&(e=this._getStepPage(t),this.container.finish().animate({height:e.outerHeight()},this.options.transition.speed))}},{key:"_triggerEvent",value:function(t,e){var s=v.Event(t);return this.main.trigger(s,e),!s.isDefaultPrevented()&&s.result}},{key:"_setURLHash",value:function(t){this.options.enableURLhash&&window.location.hash!==t&&history.pushState(null,null,t)}},{key:"_getURLHashIndex",value:function(){if(this.options.enableURLhash){var t=window.location.hash;if(0<t.length){var e=this.nav.find("a[href*='"+t+"']");if(0<e.length)return this.steps.index(e)}}return!1}},{key:"_loader",value:function(t){switch(t){case"show":this.main.addClass("sw-loading");break;case"hide":this.main.removeClass("sw-loading");break;default:this.main.toggleClass("sw-loading")}}},{key:"_showError",value:function(t){console.error(t)}},{key:"goToStep",value:function(t){this._showStep(t)}},{key:"next",value:function(){this._showNext()}},{key:"prev",value:function(){this._showPrevious()}},{key:"reset",value:function(){this._setURLHash("#"),this._initOptions(),this._initLoad()}},{key:"stepState",value:function(t,e){if(!t)return!1;switch(e){case"disable":this._setCSSClass(t,"disabled");break;case"enable":this._resetCSSClass(t,"disabled");break;case"hide":this._setCSSClass(t,"hidden");break;case"show":this._resetCSSClass(t,"hidden");break;case"error-on":this._setCSSClass(t,"danger");break;case"error-off":this._resetCSSClass(t,"danger")}}},{key:"setOptions",value:function(t){this.options=v.extend(!0,{},this.options,t),this._initOptions()}},{key:"getStepIndex",value:function(){return this.current_index}},{key:"loader",value:function(t){"show"===t?this.main.addClass("sw-loading"):this.main.removeClass("sw-loading")}}]),s}();v.fn.smartWizard=function(t){if(void 0===t||"object"===_typeof(t))return this.each(function(){v.data(this,"smartWizard")||v.data(this,"smartWizard",new s(this,t))});if("string"==typeof t&&"_"!==t[0]&&"init"!==t){var e=v.data(this[0],"smartWizard");return"destroy"===t&&v.data(this,"smartWizard",null),e instanceof s&&"function"==typeof e[t]?e[t].apply(e,Array.prototype.slice.call(arguments,1)):this}}});
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/smartwizard/smart_wizard_all.min.css b/ruoyi-admin/src/main/resources/static/ajax/libs/smartwizard/smart_wizard_all.min.css
new file mode 100644
index 0000000..217d3aa
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/smartwizard/smart_wizard_all.min.css
@@ -0,0 +1,11 @@
+/*!
+ * jQuery SmartWizard v5
+ * jQuery Wizard Plugin
+ * http://www.techlaboratory.net/smartwizard
+ *
+ * Created by Dipu Raj
+ * http://dipu.me
+ *
+ * Licensed under the terms of MIT License
+ * https://github.com/techlab/jquery-smartwizard/blob/master/LICENSE
+ */.sw{position:relative}.sw *,.sw ::after,.sw ::before{box-sizing:border-box}.sw>.tab-content{position:relative;overflow:hidden}.sw .toolbar{padding:.8rem}.sw .toolbar>.btn{display:inline-block;text-decoration:none;text-align:center;text-transform:none;vertical-align:middle;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;margin-left:.2rem;margin-right:.2rem;cursor:pointer}.sw .toolbar>.btn.disabled,.sw .toolbar>.btn:disabled{opacity:.65}.sw>.nav{display:flex;flex-wrap:wrap;list-style:none;padding-left:0;margin-top:0;margin-bottom:0}@media screen and (max-width:640px){.sw>.nav{flex-direction:column!important;flex:1 auto}}.sw>.nav .nav-link{display:block;padding:.5rem 1rem;text-decoration:none}.sw>.nav .nav-link:active,.sw>.nav .nav-link:focus,.sw>.nav .nav-link:hover{text-decoration:none}.sw>.nav .nav-link::-moz-focus-inner{border:0!important}.sw>.nav .nav-link.disabled{color:#ccc!important;pointer-events:none;cursor:default}.sw>.nav .nav-link.hidden{display:none!important}.sw.sw-justified>.nav .nav-link,.sw.sw-justified>.nav>li{flex-basis:0;flex-grow:1;text-align:center}.sw.sw-dark{color:rgba(255,255,255,.95);background:#000}.sw.sw-loading{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.sw.sw-loading::after{content:"";display:block;position:absolute;opacity:1;top:0;left:0;height:100%;width:100%;background:rgba(255,255,255,.7);z-index:2;transition:all .2s ease}.sw.sw-loading::before{content:'';display:inline-block;position:absolute;top:45%;left:45%;width:2rem;height:2rem;border:10px solid #f3f3f3;border-top:10px solid #3498db;border-radius:50%;z-index:10;-webkit-animation:spin 1s linear infinite;animation:spin 1s linear infinite}@-webkit-keyframes spin{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}@keyframes spin{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}.sw-theme-default{border:1px solid #eee}.sw-theme-default>.tab-content>.tab-pane{padding:10px}.sw-theme-default .toolbar>.btn{color:#fff;background-color:#17a2b8;border:1px solid #17a2b8;padding:.375rem .75rem;border-radius:.25rem;font-weight:400}.sw-theme-default>.nav{box-shadow:0 .125rem .25rem rgba(0,0,0,.1)!important}.sw-theme-default>.nav .nav-link{position:relative;height:100%;min-height:100%}.sw-theme-default>.nav .nav-link::after{content:"";position:absolute;height:2px;width:0;left:0;bottom:-1px;background:#999;transition:all .35s ease .15s}.sw-theme-default>.nav .nav-link.inactive{color:#999;cursor:not-allowed}.sw-theme-default>.nav .nav-link.active{color:#17a2b8!important;cursor:pointer}.sw-theme-default>.nav .nav-link.active::after{background:#17a2b8!important;width:100%}.sw-theme-default>.nav .nav-link.done{color:#5cb85c!important;cursor:pointer}.sw-theme-default>.nav .nav-link.done::after{background:#5cb85c;width:100%}.sw-theme-default>.nav .nav-link.disabled{color:#ddd!important;cursor:not-allowed}.sw-theme-default>.nav .nav-link.disabled::after{background:#ddd;width:100%}.sw-theme-default>.nav .nav-link.danger{color:#d9534f!important;cursor:pointer}.sw-theme-default>.nav .nav-link.danger::after{background:#d9534f;width:100%}.sw-theme-arrows{border:1px solid #eee}.sw-theme-arrows>.tab-content>.tab-pane{padding:10px}.sw-theme-arrows .toolbar>.btn{color:#fff;background-color:#17a2b8;border:1px solid #17a2b8;padding:.375rem .75rem;border-radius:.25rem;font-weight:400}.sw-theme-arrows>.nav{overflow:hidden;border-bottom:1px solid #eee}.sw-theme-arrows>.nav .nav-link{position:relative;height:100%;min-height:100%;margin-right:30px;margin-left:-30px;padding-left:40px}@media screen and (max-width:640px){.sw-theme-arrows>.nav .nav-link{overflow:hidden;margin-bottom:1px;margin-right:unset}}.sw-theme-arrows>.nav .nav-link::after{content:"";position:absolute;display:block;width:0;height:0;top:50%;left:100%;margin-top:-50px;border-top:50px solid transparent;border-bottom:50px solid transparent;border-left:30px solid #f8f8f8;z-index:2}.sw-theme-arrows>.nav .nav-link::before{content:" ";position:absolute;display:block;width:0;height:0;top:50%;left:100%;margin-top:-50px;margin-left:1px;border-top:50px solid transparent;border-bottom:50px solid transparent;border-left:30px solid #eee;z-index:1}.sw-theme-arrows>.nav .nav-link.inactive{color:#999;border-color:#f8f8f8;background:#f8f8f8;cursor:not-allowed}.sw-theme-arrows>.nav .nav-link.active{color:#fff;border-color:#5bc0de;background:#5bc0de;cursor:pointer}.sw-theme-arrows>.nav .nav-link.active::after{border-left-color:#5bc0de}.sw-theme-arrows>.nav .nav-link.done{color:#fff;border-color:#5cb85c;background:#5cb85c;cursor:pointer}.sw-theme-arrows>.nav .nav-link.done::after{border-left-color:#5cb85c}.sw-theme-arrows>.nav .nav-link.disabled{color:#eee;border-color:#f9f9f9;background:#f9f9f9;cursor:not-allowed}.sw-theme-arrows>.nav .nav-link.disabled::after{border-left-color:#f9f9f9}.sw-theme-arrows>.nav .nav-link.danger{color:#fff;border-color:#d9534f;background:#d9534f;cursor:pointer}.sw-theme-arrows>.nav .nav-link.danger::after{border-left-color:#d9534f}.sw-theme-arrows.sw-dark{color:rgba(255,255,255,.95);background:#000}.sw-theme-arrows.sw-dark>.nav{border-bottom:1px solid #555}.sw-theme-arrows.sw-dark>.nav .nav-link::after{border-left:30px solid #5f5f5f}.sw-theme-arrows.sw-dark>.nav .nav-link::before{border-left:30px solid #555}.sw-theme-arrows.sw-dark>.nav .nav-link.inactive{color:#fff;border-color:#5f5f5f;background:#5f5f5f}.sw-theme-arrows.sw-dark>.nav .nav-link.inactive::after{border-left-color:#5f5f5f}.sw-theme-arrows.sw-dark>.nav .nav-link.active{color:#fff;border-color:#010506;background:#0a2730}.sw-theme-arrows.sw-dark>.nav .nav-link.active::after{border-left-color:#0a2730}.sw-theme-arrows.sw-dark>.nav .nav-link.done{color:#fff;border-color:#000;background:#000}.sw-theme-arrows.sw-dark>.nav .nav-link.done::after{border-left-color:#000}.sw-theme-arrows.sw-dark>.nav .nav-link.disabled{color:#555!important;border-color:#f9f9f9;background:#474747}.sw-theme-arrows.sw-dark>.nav .nav-link.disabled::after{border-left-color:#474747}.sw-theme-arrows.sw-dark>.nav .nav-link.danger{color:#fff;border-color:#d9534f;background:#d9534f}.sw-theme-arrows.sw-dark>.nav .nav-link.danger::after{border-left-color:#d9534f}.sw-theme-dots>.tab-content>.tab-pane{padding:10px}.sw-theme-dots .toolbar>.btn{color:#fff;background-color:#17a2b8;border:1px solid #17a2b8;padding:.375rem .75rem;border-radius:.25rem;font-weight:400}.sw-theme-dots>.nav{position:relative;margin-bottom:10px}.sw-theme-dots>.nav::before{content:" ";position:absolute;top:18px;left:0;width:100%;height:5px;background-color:#eee;border-radius:3px;z-index:1}.sw-theme-dots>.nav .nav-link{position:relative;margin-top:40px}.sw-theme-dots>.nav .nav-link::before{content:" ";position:absolute;display:block;top:-36px;left:0;right:0;margin-left:auto;margin-right:auto;width:32px;height:32px;border-radius:50%;border:none;background:#f5f5f5;color:#428bca;text-decoration:none;z-index:98}.sw-theme-dots>.nav .nav-link::after{content:" ";position:absolute;display:block;top:-28px;left:0;right:0;margin-left:auto;margin-right:auto;width:16px;height:16px;border-radius:50%;z-index:99}.sw-theme-dots>.nav .nav-link.inactive{color:#999;cursor:not-allowed}.sw-theme-dots>.nav .nav-link.inactive::after{background-color:#999}.sw-theme-dots>.nav .nav-link.active{color:#5bc0de!important;cursor:pointer}.sw-theme-dots>.nav .nav-link.active::after{background-color:#5bc0de!important}.sw-theme-dots>.nav .nav-link.done{color:#5cb85c;cursor:pointer}.sw-theme-dots>.nav .nav-link.done::after{background-color:#5cb85c}.sw-theme-dots>.nav .nav-link.disabled{color:#f9f9f9;cursor:not-allowed}.sw-theme-dots>.nav .nav-link.disabled::after{background-color:#f9f9f9}.sw-theme-dots>.nav .nav-link.danger{color:#d9534f;cursor:pointer}.sw-theme-dots>.nav .nav-link.danger::after{background-color:#d9534f}.sw-theme-dots.sw-dark{color:rgba(255,255,255,.95);background:#000}.sw-theme-dots.sw-dark>.nav::before{background-color:#3c3c3c}.sw-theme-dots.sw-dark>.nav .nav-link::before{background:#434343;color:#000}.sw-theme-progress{border:1px solid #eee}.sw-theme-progress>.tab-content>.tab-pane{padding:10px}.sw-theme-progress .toolbar>.btn{color:#fff;background-color:#17a2b8;border:1px solid #17a2b8;padding:.375rem .75rem;border-radius:.25rem;font-weight:400}.sw-theme-progress>.nav{box-shadow:0 .125rem .25rem rgba(0,0,0,.1)!important}.sw-theme-progress>.nav .nav-link{position:relative;height:100%;min-height:100%;background:0 0;overflow:hidden;z-index:2}.sw-theme-progress>.nav .nav-link::after{content:"";position:absolute;height:150%;width:0;left:0;top:0;background:#fff;z-index:-1;transition:all .35s ease .1s}.sw-theme-progress>.nav .nav-link.inactive{color:#999;cursor:not-allowed}.sw-theme-progress>.nav .nav-link.active{color:#fff!important;cursor:pointer}.sw-theme-progress>.nav .nav-link.active::after{background-color:#5cb85c;width:100%}.sw-theme-progress>.nav .nav-link.done{color:#fff!important;cursor:pointer}.sw-theme-progress>.nav .nav-link.done::after{background:#5cb85c;width:100%}.sw-theme-progress>.nav .nav-link.disabled{color:#ddd!important;cursor:not-allowed}.sw-theme-progress>.nav .nav-link.disabled::after{background:#f9f9f9;width:100%}.sw-theme-progress>.nav .nav-link.danger{color:#fff!important;cursor:pointer}.sw-theme-progress>.nav .nav-link.danger::after{background:#d9534f;width:100%}.sw-theme-progress.sw-dark{color:rgba(255,255,255,.95)}.sw-theme-progress.sw-dark>.nav .nav-link.active{color:#fff}.sw-theme-progress.sw-dark>.nav .nav-link.active::after{background-color:#333}.sw-theme-progress.sw-dark>.nav .nav-link.done{color:#fff!important}.sw-theme-progress.sw-dark>.nav .nav-link.done::after{background:#333}.sw-theme-progress.sw-dark>.nav .nav-link.disabled{color:#2b2b2b!important}.sw-theme-progress.sw-dark>.nav .nav-link.disabled::after{background:#474747}.sw-theme-progress.sw-dark>.nav .nav-link.danger{color:#fff!important}.sw-theme-progress.sw-dark>.nav .nav-link.danger::after{background:#d9534f}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/suggest/bootstrap-suggest.js b/ruoyi-admin/src/main/resources/static/ajax/libs/suggest/bootstrap-suggest.js
new file mode 100644
index 0000000..c055407
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/suggest/bootstrap-suggest.js
@@ -0,0 +1,1180 @@
+/**
+ * bootstrap-suggest-plugin - v0.1.29
+ * @description 这是一个基于 bootstrap 按钮式下拉菜单组件的搜索建议插件,必须使用于按钮式下拉菜单组件上。
+ * @author lzwme - https://lzw.me
+ * @GitHub https://github.com/lzwme/bootstrap-suggest-plugin.git
+ * @since 2019-11-18 09:30:06
+ */
+(function(factory) {
+  if (typeof define === "function" && define.amd) {
+    define(["jquery"], factory);
+  } else if (typeof exports === "object" && typeof module === "object") {
+    factory(require("jquery"));
+  } else if (window.jQuery) {
+    factory(window.jQuery);
+  } else {
+    throw new Error("Not found jQuery.");
+  }
+})(function($) {
+  var VERSION = "VERSION_PLACEHOLDER";
+  var $window = $(window);
+  var isIe = "ActiveXObject" in window; // 用于对 IE 的兼容判断
+  var inputLock; // 用于中文输入法输入时锁定搜索
+
+  // ie 下和 chrome 51 以上浏览器版本,出现滚动条时不计算 padding
+  var chromeVer = navigator.userAgent.match(/Chrome\/(\d+)/);
+  if (chromeVer) {
+    chromeVer = +chromeVer[1];
+  }
+  var notNeedCalcPadding = isIe || chromeVer > 51;
+
+  // 一些常量
+  var BSSUGGEST = "bsSuggest";
+  var onDataRequestSuccess = "onDataRequestSuccess";
+  var DISABLED = "disabled";
+  var TRUE = true;
+  var FALSE = false;
+
+  function isUndefined(val) {
+    return val === void 0;
+  }
+
+  /**
+   * 错误处理
+   */
+  function handleError(e1, e2) {
+    if (!window.console || !window.console.trace) {
+      return;
+    }
+    console.trace(e1);
+    if (e2) {
+      console.trace(e2);
+    }
+  }
+  /**
+   * 获取当前 tr 列的关键字数据
+   */
+  function getPointKeyword($list) {
+    return $list.data();
+  }
+  /**
+   * 设置或获取输入框的 alt 值
+   */
+  function setOrGetAlt($input, val) {
+    return isUndefined(val) ? $input.attr("alt") : $input.attr("alt", val);
+  }
+  /**
+   * 设置或获取输入框的 data-id 值
+   */
+  function setOrGetDataId($input, val) {
+    return val !== void 0
+      ? $input.attr("data-id", val)
+      : $input.attr("data-id");
+  }
+  /**
+   * 设置选中的值
+   */
+  function setValue($input, keywords, options) {
+    if (!keywords || !keywords.key) {
+      return;
+    }
+
+    var separator = options.separator || ",",
+      inputValList,
+      inputIdList,
+      dataId = setOrGetDataId($input);
+
+    if (options && options.multiWord) {
+      inputValList = $input.val().split(separator);
+      inputValList[inputValList.length - 1] = keywords.key;
+
+      //多关键字检索支持设置id --- 存在 bug,不建议使用
+      if (!dataId) {
+        inputIdList = [keywords.id];
+      } else {
+        inputIdList = dataId.split(separator);
+        inputIdList.push(keywords.id);
+      }
+
+      setOrGetDataId($input, inputIdList.join(separator))
+        .val(inputValList.join(separator))
+        .focus();
+    } else {
+      setOrGetDataId($input, keywords.id || "")
+        .val(keywords.key)
+        .focus();
+    }
+
+    $input
+      .data("pre-val", $input.val())
+      .trigger("onSetSelectValue", [
+        keywords,
+        (options.data.value || options._lastData.value)[keywords.index]
+      ]);
+  }
+  /**
+   * 调整选择菜单位置
+   * @param {Object} $input
+   * @param {Object} $dropdownMenu
+   * @param {Object} options
+   */
+  function adjustDropMenuPos($input, $dropdownMenu, options) {
+    if (!$dropdownMenu.is(":visible")) {
+      return;
+    }
+
+    var $parent = $input.parent();
+    var parentHeight = $parent.height();
+    var parentWidth = $parent.width();
+
+    if (options.autoDropup) {
+      setTimeout(function() {
+        var offsetTop = $input.offset().top;
+        var winScrollTop = $window.scrollTop();
+        var menuHeight = $dropdownMenu.height();
+
+        if (
+          // 自动判断菜单向上展开
+          $window.height() + winScrollTop - offsetTop < menuHeight && // 假如向下会撑长页面
+          offsetTop > menuHeight + winScrollTop // 而且向上不会撑到顶部
+        ) {
+          $parent.addClass("dropup");
+        } else {
+          $parent.removeClass("dropup");
+        }
+      }, 10);
+    }
+
+    // 列表对齐方式
+    var dmcss = {};
+    if (options.listAlign === "left") {
+      dmcss = {
+        left: $input.siblings("div").width() - parentWidth,
+        right: "auto"
+      };
+    } else if (options.listAlign === "right") {
+      dmcss = {
+        left: "auto",
+        right: 0
+      };
+    }
+
+    // ie 下,不显示按钮时的 top/bottom
+    if (isIe && !options.showBtn) {
+      if (!$parent.hasClass("dropup")) {
+        dmcss.top = parentHeight;
+        dmcss.bottom = "auto";
+      } else {
+        dmcss.top = "auto";
+        dmcss.bottom = parentHeight;
+      }
+    }
+
+    // 是否自动最小宽度
+    if (!options.autoMinWidth) {
+      dmcss.minWidth = parentWidth;
+    }
+    /* else {
+            dmcss['width'] = 'auto';
+        }*/
+
+    $dropdownMenu.css(dmcss);
+
+    return $input;
+  }
+  /**
+   * 设置输入框背景色
+   * 当设置了 indexId,而输入框的 data-id 为空时,输入框加载警告色
+   */
+  function setBackground($input, options) {
+    var inputbg, bg, warnbg;
+    if ((options.indexId === -1 && !options.idField) || options.multiWord) {
+      return $input;
+    }
+
+    bg = options.inputBgColor;
+    warnbg = options.inputWarnColor;
+
+    var curVal = $input.val();
+    var preVal = $input.data("pre-val");
+
+    if (setOrGetDataId($input) || !curVal) {
+      $input.css("background", bg || "");
+
+      if (!curVal && preVal) {
+        $input.trigger("onUnsetSelectValue").data("pre-val", "");
+      }
+
+      return $input;
+    }
+
+    inputbg = $input
+      .css("backgroundColor")
+      .replace(/ /g, "")
+      .split(",", 3)
+      .join(",");
+    // 自由输入的内容,设置背景色
+    if (!~warnbg.indexOf(inputbg)) {
+      $input
+        .trigger("onUnsetSelectValue") // 触发取消data-id事件
+        .data("pre-val", "")
+        .css("background", warnbg);
+    }
+
+    return $input;
+  }
+  /**
+   * 调整滑动条
+   */
+  function adjustScroll($input, $dropdownMenu, options) {
+    // 控制滑动条
+    var $hover = $input.parent().find("tbody tr." + options.listHoverCSS),
+      pos,
+      maxHeight;
+
+    if ($hover.length) {
+      pos = ($hover.index() + 3) * $hover.height();
+      maxHeight = +$dropdownMenu.css("maxHeight").replace("px", "");
+
+      if (pos > maxHeight || $dropdownMenu.scrollTop() > maxHeight) {
+        pos = pos - maxHeight;
+      } else {
+        pos = 0;
+      }
+
+      $dropdownMenu.scrollTop(pos);
+    }
+  }
+  /**
+   * 解除所有列表 hover 样式
+   */
+  function unHoverAll($dropdownMenu, options) {
+    $dropdownMenu
+      .find("tr." + options.listHoverCSS)
+      .removeClass(options.listHoverCSS);
+  }
+  /**
+   * 验证 $input 对象是否符合条件
+   *   1. 必须为 bootstrap 下拉式菜单
+   *   2. 必须未初始化过
+   */
+  function checkInput($input, $dropdownMenu, options) {
+    if (
+      !$dropdownMenu.length || // 过滤非 bootstrap 下拉式菜单对象
+      $input.data(BSSUGGEST) // 是否已经初始化的检测
+    ) {
+      return FALSE;
+    }
+
+    $input.data(BSSUGGEST, {
+      options: options
+    });
+
+    return TRUE;
+  }
+  /**
+   * 数据格式检测
+   * 检测 ajax 返回成功数据或 data 参数数据是否有效
+   * data 格式:{"value": [{}, {}...]}
+   */
+  function checkData(data) {
+    var isEmpty = TRUE,
+      o;
+
+    for (o in data) {
+      if (o === "value") {
+        isEmpty = FALSE;
+        break;
+      }
+    }
+    if (isEmpty) {
+      handleError("返回数据格式错误!");
+      return FALSE;
+    }
+    if (!data.value.length) {
+      // handleError('返回数据为空!');
+      return FALSE;
+    }
+
+    return data;
+  }
+  /**
+   * 判断字段名是否在 options.effectiveFields 配置项中
+   * @param  {String} field   要判断的字段名
+   * @param  {Object} options
+   * @return {Boolean}        effectiveFields 为空时始终返回 true
+   */
+  function inEffectiveFields(field, options) {
+    var effectiveFields = options.effectiveFields;
+
+    return !(
+      field === "__index" ||
+      (effectiveFields.length && !~$.inArray(field, effectiveFields))
+    );
+  }
+  /**
+   * 判断字段名是否在 options.searchFields 搜索字段配置中
+   */
+  function inSearchFields(field, options) {
+    return ~$.inArray(field, options.searchFields);
+  }
+  /**
+   * 通过下拉菜单显示提示文案
+   */
+  function showTip(tip, $input, $dropdownMenu, options) {
+    $dropdownMenu
+      .html('<div style="padding:10px 5px 5px">' + tip + "</div>")
+      .show();
+    adjustDropMenuPos($input, $dropdownMenu, options);
+  }
+  /**
+   * 显示下拉列表
+   */
+  function showDropMenu($input, options) {
+    var $dropdownMenu = $input.parent().find("ul:eq(0)");
+    if (!$dropdownMenu.is(":visible")) {
+      // $dropdownMenu.css('display', 'block');
+      $dropdownMenu.show();
+      $input.trigger("onShowDropdown", [options ? options.data.value : []]);
+    }
+  }
+  /**
+   * 隐藏下拉列表
+   */
+  function hideDropMenu($input, options) {
+    var $dropdownMenu = $input.parent().find("ul:eq(0)");
+    if ($dropdownMenu.is(":visible")) {
+      // $dropdownMenu.css('display', '');
+      $dropdownMenu.hide();
+      $input.trigger("onHideDropdown", [options ? options.data.value : []]);
+    }
+  }
+  /**
+   * 下拉列表刷新
+   * 作为 fnGetData 的 callback 函数调用
+   */
+  function refreshDropMenu($input, data, options) {
+    var $dropdownMenu = $input.parent().find("ul:eq(0)"),
+      len,
+      i,
+      field,
+      index = 0,
+      tds,
+      html = [
+        '<table class="table table-condensed table-sm" style="margin:0">'
+      ],
+      idValue,
+      keyValue; // 作为输入框 data-id 和内容的字段值
+    var dataList = data.value;
+
+    if (!data || !(len = dataList.length)) {
+      if (options.emptyTip) {
+        showTip(options.emptyTip, $input, $dropdownMenu, options);
+      } else {
+        $dropdownMenu.empty();
+        hideDropMenu($input, options);
+      }
+      return $input;
+    }
+
+    // 相同数据,不用继续渲染了
+    if (
+      options._lastData &&
+      JSON.stringify(options._lastData) === JSON.stringify(data) &&
+      $dropdownMenu.find("tr").length === len
+    ) {
+      showDropMenu($input, options);
+      return adjustDropMenuPos($input, $dropdownMenu, options);
+    }
+    options._lastData = data;
+
+    /** 显示于列表中的字段 */
+    var columns = options.effectiveFields.length
+      ? options.effectiveFields
+      : $.map(dataList[0], function(val, key) {
+          return key;
+        });
+
+    // 生成表头
+    if (options.showHeader) {
+      html.push("<thead><tr>");
+      $.each(columns, function(index, field) {
+        if (!inEffectiveFields(field, options)) return;
+
+        html.push(
+          "<th>",
+          options.effectiveFieldsAlias[field] || field,
+          index === 0 ? "(" + len + ")" : "", // 表头第一列记录总数
+          "</th>"
+        );
+
+        index++;
+      });
+      html.push("</tr></thead>");
+    }
+    html.push("<tbody>");
+
+    // console.log(data, len);
+    // 按列加数据
+    var dataI;
+    var maxOptionCount = Math.min(options.maxOptionCount, len);
+    for (i = 0; i < maxOptionCount; i++) {
+      index = 0;
+      tds = [];
+      dataI = dataList[i];
+      idValue = dataI[options.idField];
+      keyValue = dataI[options.keyField];
+
+      for (field in dataI) {
+        // 标记作为 value 和 作为 id 的值
+        if (isUndefined(keyValue) && options.indexKey === index) {
+          keyValue = dataI[field];
+        }
+        if (isUndefined(idValue) && options.indexId === index) {
+          idValue = dataI[field];
+        }
+        index++;
+      }
+
+      $.each(columns, function(index, field) {
+        // 列表中只显示有效的字段
+        if (inEffectiveFields(field, options)) {
+          tds.push('<td data-name="', field, '">', dataI[field], "</td>");
+        }
+      });
+
+      html.push(
+        '<tr data-index="',
+        dataI.__index || i,
+        '" data-id="',
+        idValue,
+        '" data-key="',
+        keyValue,
+        '">',
+        tds.join(""),
+        "</tr>"
+      );
+    }
+    html.push("</tbody></table>");
+
+    $dropdownMenu.html(html.join(""));
+    showDropMenu($input, options);
+    //.show();
+
+    // scrollbar 存在时,延时到动画结束时调整 padding
+    setTimeout(function() {
+      if (notNeedCalcPadding) {
+        return;
+      }
+
+      var $table = $dropdownMenu.find("table:eq(0)"),
+        pdr = 0,
+        mgb = 0;
+
+      if (
+        $dropdownMenu.height() < $table.height() &&
+        +$dropdownMenu.css("minWidth").replace("px", "") < $dropdownMenu.width()
+      ) {
+        pdr = 18;
+        mgb = 20;
+      }
+
+      $dropdownMenu.css("paddingRight", pdr);
+      $table.css("marginBottom", mgb);
+    }, 301);
+
+    adjustDropMenuPos($input, $dropdownMenu, options);
+
+    return $input;
+  }
+  /**
+   * ajax 获取数据
+   * @param  {Object} options
+   * @return {Object}         $.Deferred
+   */
+  function ajax(options, keyword) {
+    keyword = keyword || "";
+
+    var preAjax = options._preAjax;
+
+    if (preAjax && preAjax.abort && preAjax.readyState !== 4) {
+      // console.log('abort pre ajax');
+      preAjax.abort();
+    }
+
+    var ajaxParam = {
+      type: "GET",
+      dataType: options.jsonp ? "jsonp" : "json",
+      timeout: 5000
+    };
+
+    // jsonp
+    if (options.jsonp) {
+      ajaxParam.jsonp = options.jsonp;
+    }
+
+    // 自定义 ajax 请求参数生成方法
+    var adjustAjaxParam,
+      fnAdjustAjaxParam = options.fnAdjustAjaxParam;
+
+    if ($.isFunction(fnAdjustAjaxParam)) {
+      adjustAjaxParam = fnAdjustAjaxParam(keyword, options);
+
+      // options.fnAdjustAjaxParam 返回false,则终止 ajax 请求
+      if (FALSE === adjustAjaxParam) {
+        return;
+      }
+
+      $.extend(ajaxParam, adjustAjaxParam);
+    }
+
+    // url 调整
+    ajaxParam.url = (function() {
+      if (!keyword || ajaxParam.data) {
+        return ajaxParam.url || options.url;
+      }
+
+      var type = "?";
+      if (/=$/.test(options.url)) {
+        type = "";
+      } else if (/\?/.test(options.url)) {
+        type = "&";
+      }
+
+      return options.url + type + encodeURIComponent(keyword);
+    })();
+
+    return (options._preAjax = $.ajax(ajaxParam)
+      .done(function(result) {
+        options.data = options.fnProcessData(result);
+      })
+      .fail(function(err) {
+        if (options.fnAjaxFail) {
+          options.fnAjaxFail(err, options);
+        }
+      }));
+  }
+  /**
+   * 检测 keyword 与 value 是否存在互相包含
+   * @param  {String}  keyword 用户输入的关键字
+   * @param  {String}  key     匹配字段的 key
+   * @param  {String}  value   key 字段对应的值
+   * @param  {Object}  options
+   * @return {Boolean}         包含/不包含
+   */
+  function isInWord(keyword, key, value, options) {
+    value = $.trim(value);
+
+    if (options.ignorecase) {
+      keyword = keyword.toLocaleLowerCase();
+      value = value.toLocaleLowerCase();
+    }
+
+    return (
+      value &&
+      (inEffectiveFields(key, options) || inSearchFields(key, options)) && // 必须在有效的搜索字段中
+      (~value.indexOf(keyword) || // 匹配值包含关键字
+        (options.twoWayMatch && ~keyword.indexOf(value))) // 关键字包含匹配值
+    );
+  }
+  /**
+   * 通过 ajax 或 json 参数获取数据
+   */
+  function getData(keyword, $input, callback, options) {
+    var data,
+      validData,
+      filterData = {
+        value: []
+      },
+      i,
+      key,
+      len,
+      fnPreprocessKeyword = options.fnPreprocessKeyword;
+
+    keyword = keyword || "";
+    // 获取数据前对关键字预处理方法
+    if ($.isFunction(fnPreprocessKeyword)) {
+      keyword = fnPreprocessKeyword(keyword, options);
+    }
+
+    // 给了url参数,则从服务器 ajax 请求
+    // console.log(options.url + keyword);
+    if (options.url) {
+      var timer;
+      if (options.searchingTip) {
+        timer = setTimeout(function() {
+          showTip(
+            options.searchingTip,
+            $input,
+            $input.parent().find("ul"),
+            options
+          );
+        }, 600);
+      }
+
+      ajax(options, keyword)
+        .done(function(result) {
+          callback($input, options.data, options); // 为 refreshDropMenu
+          $input.trigger(onDataRequestSuccess, result);
+          if (options.getDataMethod === "firstByUrl") {
+            options.url = null;
+          }
+        })
+        .always(function() {
+          timer && clearTimeout(timer);
+        });
+    } else {
+      // 没有给出 url 参数,则从 data 参数获取
+      data = options.data;
+      validData = checkData(data);
+      // 本地的 data 数据,则在本地过滤
+      if (validData) {
+        if (keyword) {
+          // 输入不为空时则进行匹配
+          len = data.value.length;
+          for (i = 0; i < len; i++) {
+            for (key in data.value[i]) {
+              if (
+                data.value[i][key] &&
+                isInWord(keyword, key, data.value[i][key] + "", options)
+              ) {
+                filterData.value.push(data.value[i]);
+                filterData.value[filterData.value.length - 1].__index = i;
+                break;
+              }
+            }
+          }
+        } else {
+          filterData = data;
+        }
+      }
+
+      callback($input, filterData, options);
+    } // else
+  }
+  /**
+   * 数据处理
+   * url 获取数据时,对数据的处理,作为 fnGetData 之后的回调处理
+   */
+  function processData(data) {
+    return checkData(data);
+  }
+  /**
+   * 取得 clearable 清除按钮
+   */
+  function getIClear($input, options) {
+    var $iClear = $input.prev("i.clearable");
+
+    // 是否可清除已输入的内容(添加清除按钮)
+    if (options.clearable && !$iClear.length) {
+      $iClear = $(
+        '<i class="clearable glyphicon glyphicon-remove fa fa-plus"></i>'
+      ).prependTo($input.parent());
+    }
+
+    return $iClear
+      .css({
+        position: "absolute",
+        top: "calc(50% - 6px)",
+        transform: "rotate(45deg)",
+        // right: options.showBtn ? Math.max($input.next('.input-group-btn').width(), 33) + 2 : 12,
+        zIndex: 4,
+        cursor: "pointer",
+        width: "14px",
+        lineHeight: "14px",
+        textAlign: "center",
+        fontSize: 12
+      })
+      .hide();
+  }
+  /**
+   * 默认的配置选项
+   * @type {Object}
+   */
+  var defaultOptions = {
+    url: null, // 请求数据的 URL 地址
+    jsonp: null, // 设置此参数名,将开启jsonp功能,否则使用json数据结构
+    data: {
+      value: []
+    }, // 提示所用的数据,注意格式
+    indexId: 0, // 每组数据的第几个数据,作为input输入框的 data-id,设为 -1 且 idField 为空则不设置此值
+    indexKey: 0, // 每组数据的第几个数据,作为input输入框的内容
+    idField: "", // 每组数据的哪个字段作为 data-id,优先级高于 indexId 设置(推荐)
+    keyField: "", // 每组数据的哪个字段作为输入框内容,优先级高于 indexKey 设置(推荐)
+
+    /* 搜索相关 */
+    autoSelect: TRUE, // 键盘向上/下方向键时,是否自动选择值
+    allowNoKeyword: TRUE, // 是否允许无关键字时请求数据
+    getDataMethod: "firstByUrl", // 获取数据的方式,url:一直从url请求;data:从 options.data 获取;firstByUrl:第一次从Url获取全部数据,之后从options.data获取
+    delayUntilKeyup: FALSE, // 获取数据的方式 为 firstByUrl 时,是否延迟到有输入时才请求数据
+    ignorecase: FALSE, // 前端搜索匹配时,是否忽略大小写
+    effectiveFields: [], // 有效显示于列表中的字段,非有效字段都会过滤,默认全部有效。
+    effectiveFieldsAlias: {}, // 有效字段的别名对象,用于 header 的显示
+    searchFields: [], // 有效搜索字段,从前端搜索过滤数据时使用,但不一定显示在列表中。effectiveFields 配置字段也会用于搜索过滤
+    twoWayMatch: TRUE, // 是否双向匹配搜索。为 true 即输入关键字包含或包含于匹配字段均认为匹配成功,为 false 则输入关键字包含于匹配字段认为匹配成功
+    multiWord: FALSE, // 以分隔符号分割的多关键字支持
+    separator: ",", // 多关键字支持时的分隔符,默认为半角逗号
+    delay: 300, // 搜索触发的延时时间间隔,单位毫秒
+    emptyTip: "", // 查询为空时显示的内容,可为 html
+    searchingTip: "搜索中...", // ajax 搜索时显示的提示内容,当搜索时间较长时给出正在搜索的提示
+    hideOnSelect: FALSE, // 鼠标从列表单击选择了值时,是否隐藏选择列表
+    maxOptionCount: 200, // 选择列表最多显示的可选项数量,默认为 200
+
+    /* UI */
+    autoDropup: FALSE, // 选择菜单是否自动判断向上展开。设为 true,则当下拉菜单高度超过窗体,且向上方向不会被窗体覆盖,则选择菜单向上弹出
+    autoMinWidth: FALSE, // 是否自动最小宽度,设为 false 则最小宽度不小于输入框宽度
+    showHeader: FALSE, // 是否显示选择列表的 header。为 true 时,有效字段大于一列则显示表头
+    showBtn: TRUE, // 是否显示下拉按钮
+    inputBgColor: "", // 输入框背景色,当与容器背景色不同时,可能需要该项的配置
+    inputWarnColor: "rgba(255,0,0,.1)", // 输入框内容不是下拉列表选择时的警告色
+    listStyle: {
+      "padding-top": 0,
+      "max-height": "375px",
+      "max-width": "800px",
+      overflow: "auto",
+      width: "auto",
+      transition: "0.3s",
+      "-webkit-transition": "0.3s",
+      "-moz-transition": "0.3s",
+      "-o-transition": "0.3s",
+      "word-break": "keep-all",
+      "white-space": "nowrap"
+    }, // 列表的样式控制
+    listAlign: "left", // 提示列表对齐位置,left/right/auto
+    listHoverStyle: "background: #07d; color:#fff", // 提示框列表鼠标悬浮的样式
+    listHoverCSS: "jhover", // 提示框列表鼠标悬浮的样式名称
+    clearable: FALSE, // 是否可清除已输入的内容
+
+    /* key */
+    keyLeft: 37, // 向左方向键,不同的操作系统可能会有差别,则自行定义
+    keyUp: 38, // 向上方向键
+    keyRight: 39, // 向右方向键
+    keyDown: 40, // 向下方向键
+    keyEnter: 13, // 回车键
+
+    /* methods */
+    fnProcessData: processData, // 格式化数据的方法,返回数据格式参考 data 参数
+    fnGetData: getData, // 获取数据的方法,无特殊需求一般不作设置
+    fnAdjustAjaxParam: null, // 调整 ajax 请求参数方法,用于更多的请求配置需求。如对请求关键字作进一步处理、修改超时时间等
+    fnPreprocessKeyword: null, // 搜索过滤数据前,对输入关键字作进一步处理方法。注意,应返回字符串
+    fnAjaxFail: null // ajax 失败时回调方法
+  };
+
+  var methods = {
+    init: function(options) {
+      // 参数设置
+      var self = this;
+      options = options || {};
+
+      // 默认配置有效显示字段多于一个,则显示列表表头,否则不显示
+      if (
+        isUndefined(options.showHeader) &&
+        options.effectiveFields &&
+        options.effectiveFields.length > 1
+      ) {
+        options.showHeader = TRUE;
+      }
+
+      options = $.extend(TRUE, {}, defaultOptions, options);
+
+      // 旧的方法兼容
+      if (options.processData) {
+        options.fnProcessData = options.processData;
+      }
+
+      if (options.getData) {
+        options.fnGetData = options.getData;
+      }
+
+      if (
+        options.getDataMethod === "firstByUrl" &&
+        options.url &&
+        !options.delayUntilKeyup
+      ) {
+        ajax(options).done(function(result) {
+          options.url = null;
+          self.trigger(onDataRequestSuccess, result);
+        });
+      }
+
+      // 鼠标滑动到条目样式
+      if (!$("#" + BSSUGGEST).length) {
+        $("head:eq(0)").append(
+          '<style id="' +
+            BSSUGGEST +
+            '">.' +
+            options.listHoverCSS +
+            "{" +
+            options.listHoverStyle +
+            "}</style>"
+        );
+      }
+
+      return self.each(function() {
+        var $input = $(this),
+          $parent = $input.parent(),
+          $iClear = getIClear($input, options),
+          isMouseenterMenu,
+          keyupTimer, // keyup 与 input 事件延时定时器
+          $dropdownMenu = $parent.find("ul:eq(0)");
+
+        // 兼容 bs4
+        $dropdownMenu.parent().css("position", "relative");
+
+        // 验证输入框对象是否符合条件
+        if (!checkInput($input, $dropdownMenu, options)) {
+          console.warn(
+            "不是一个标准的 bootstrap 下拉式菜单或已初始化:",
+            $input
+          );
+          return;
+        }
+
+        // 是否显示 button 按钮
+        if (!options.showBtn) {
+          $input.css("borderRadius", 4);
+          $parent
+            .css("width", "100%")
+            .find(".btn:eq(0)")
+            .hide();
+        }
+
+        // 移除 disabled 类,并禁用自动完成
+        $input
+          .removeClass(DISABLED)
+          .prop(DISABLED, FALSE)
+          .attr("autocomplete", "off");
+        // dropdown-menu 增加修饰
+        $dropdownMenu.css(options.listStyle);
+
+        // 默认背景色
+        if (!options.inputBgColor) {
+          options.inputBgColor = $input.css("backgroundColor");
+        }
+
+        // 开始事件处理
+        $input
+          .on("keydown.bs", function(event) {
+            var currentList, tipsKeyword; // 提示列表上被选中的关键字
+
+            // 当提示层显示时才对键盘事件处理
+            if (!$dropdownMenu.is(":visible")) {
+              setOrGetDataId($input, "");
+              return;
+            }
+
+            currentList = $dropdownMenu.find("." + options.listHoverCSS);
+            tipsKeyword = ""; // 提示列表上被选中的关键字
+
+            unHoverAll($dropdownMenu, options);
+
+            if (event.keyCode === options.keyDown) {
+              // 如果按的是向下方向键
+              if (!currentList.length) {
+                // 如果提示列表没有一个被选中,则将列表第一个选中
+                tipsKeyword = getPointKeyword(
+                  $dropdownMenu.find("tbody tr:first").mouseover()
+                );
+              } else if (!currentList.next().length) {
+                // 如果是最后一个被选中,则取消选中,即可认为是输入框被选中,并恢复输入的值
+                if (options.autoSelect) {
+                  setOrGetDataId($input, "").val(setOrGetAlt($input));
+                }
+              } else {
+                // 选中下一行
+                tipsKeyword = getPointKeyword(currentList.next().mouseover());
+              }
+              // 控制滑动条
+              adjustScroll($input, $dropdownMenu, options);
+
+              if (!options.autoSelect) {
+                return;
+              }
+            } else if (event.keyCode === options.keyUp) {
+              // 如果按的是向上方向键
+              if (!currentList.length) {
+                tipsKeyword = getPointKeyword(
+                  $dropdownMenu.find("tbody tr:last").mouseover()
+                );
+              } else if (!currentList.prev().length) {
+                if (options.autoSelect) {
+                  setOrGetDataId($input, "").val(setOrGetAlt($input));
+                }
+              } else {
+                // 选中前一行
+                tipsKeyword = getPointKeyword(currentList.prev().mouseover());
+              }
+
+              // 控制滑动条
+              adjustScroll($input, $dropdownMenu, options);
+
+              if (!options.autoSelect) {
+                return;
+              }
+            } else if (event.keyCode === options.keyEnter) {
+              tipsKeyword = getPointKeyword(currentList);
+              hideDropMenu($input, options);
+            } else {
+              setOrGetDataId($input, "");
+            }
+
+            // 设置值 tipsKeyword
+            // console.log(tipsKeyword);
+            setValue($input, tipsKeyword, options);
+          })
+          .on("compositionstart.bs", function(event) {
+            // 中文输入开始,锁定
+            // console.log('compositionstart');
+            inputLock = TRUE;
+          })
+          .on("compositionend.bs", function(event) {
+            // 中文输入结束,解除锁定
+            // console.log('compositionend');
+            inputLock = FALSE;
+          })
+          .on("keyup.bs input.bs paste.bs", function(event) {
+            var word;
+
+            if (event.keyCode) {
+              setBackground($input, options);
+            }
+
+            // 如果弹起的键是回车、向上或向下方向键则返回
+            if (
+              ~$.inArray(event.keyCode, [
+                options.keyDown,
+                options.keyUp,
+                options.keyEnter
+              ])
+            ) {
+              $input.val($input.val()); // 让鼠标输入跳到最后
+              return;
+            }
+
+            clearTimeout(keyupTimer);
+            keyupTimer = setTimeout(function() {
+              // console.log('input keyup', event);
+
+              // 锁定状态,返回
+              if (inputLock) {
+                return;
+              }
+
+              word = $input.val();
+
+              // 若输入框值没有改变则返回
+              if ($.trim(word) && word === setOrGetAlt($input)) {
+                return;
+              }
+
+              // 当按下键之前记录输入框值,以方便查看键弹起时值有没有变
+              setOrGetAlt($input, word);
+
+              if (options.multiWord) {
+                word = word.split(options.separator).reverse()[0];
+              }
+
+              // 是否允许空数据查询
+              if (!word.length && !options.allowNoKeyword) {
+                return;
+              }
+
+              options.fnGetData($.trim(word), $input, refreshDropMenu, options);
+            }, options.delay || 300);
+          })
+          .on("focus.bs", function() {
+            // console.log('input focus');
+            adjustDropMenuPos($input, $dropdownMenu, options);
+          })
+          .on("blur.bs", function() {
+            if (!isMouseenterMenu) {
+              // 不是进入下拉列表状态,则隐藏列表
+              hideDropMenu($input, options);
+              inputLock = true;
+              setTimeout(function() {
+                inputLock = FALSE;
+              });
+            }
+          })
+          .on("click.bs", function() {
+            // console.log('input click');
+            var word = $input.val();
+
+            if (
+              $.trim(word) &&
+              word === setOrGetAlt($input) &&
+              $dropdownMenu.find("table tr").length
+            ) {
+              return showDropMenu($input, options);
+            }
+
+            if ($dropdownMenu.is(":visible")) {
+              return;
+            }
+
+            if (options.multiWord) {
+              word = word.split(options.separator).reverse()[0];
+            }
+
+            // 是否允许空数据查询
+            if (!word.length && !options.allowNoKeyword) {
+              return;
+            }
+
+            // console.log('word', word);
+            options.fnGetData($.trim(word), $input, refreshDropMenu, options);
+          });
+
+        // 下拉按钮点击时
+        $parent
+          .find(".btn:eq(0)")
+          .attr("data-toggle", "")
+          .click(function() {
+            if (!$dropdownMenu.is(":visible")) {
+              if (options.url) {
+                $input.click().focus();
+                if (!$dropdownMenu.find("tr").length) {
+                  return FALSE;
+                }
+              } else {
+                // 不以 keyword 作为过滤,展示所有的数据
+                refreshDropMenu($input, options.data, options);
+              }
+              showDropMenu($input, options);
+            } else {
+              hideDropMenu($input, options);
+            }
+
+            return FALSE;
+          });
+
+        // 列表中滑动时,输入框失去焦点
+        $dropdownMenu
+          .mouseenter(function() {
+            // console.log('mouseenter')
+            isMouseenterMenu = 1;
+            $input.blur();
+          })
+          .mouseleave(function() {
+            // console.log('mouseleave')
+            isMouseenterMenu = 0;
+            $input.focus();
+          })
+          .on("mouseenter", "tbody tr", function() {
+            // 行上的移动事件
+            unHoverAll($dropdownMenu, options);
+            $(this).addClass(options.listHoverCSS);
+
+            return FALSE; // 阻止冒泡
+          })
+          .on("mousedown", "tbody tr", function() {
+            var keywords = getPointKeyword($(this));
+            setValue($input, keywords, options);
+            setOrGetAlt($input, keywords.key);
+            setBackground($input, options);
+
+            if (options.hideOnSelect) {
+              hideDropMenu($input, options);
+            }
+          });
+
+        // 存在清空按钮
+        if ($iClear.length) {
+          $iClear.click(function() {
+            setOrGetDataId($input, "").val("");
+            setBackground($input, options);
+          });
+
+          $parent
+            .mouseenter(function() {
+              if (!$input.prop(DISABLED)) {
+                $iClear
+                  .css(
+                    "right",
+                    options.showBtn
+                      ? Math.max($input.next().width(), 33) + 2
+                      : 12
+                  )
+                  .show();
+              }
+            })
+            .mouseleave(function() {
+              $iClear.hide();
+            });
+        }
+      });
+    },
+    show: function() {
+      return this.each(function() {
+        $(this).click();
+      });
+    },
+    hide: function() {
+      return this.each(function() {
+        hideDropMenu($(this));
+      });
+    },
+    disable: function() {
+      return this.each(function() {
+        $(this)
+          .attr(DISABLED, TRUE)
+          .parent()
+          .find(".btn:eq(0)")
+          .prop(DISABLED, TRUE);
+      });
+    },
+    enable: function() {
+      return this.each(function() {
+        $(this)
+          .attr(DISABLED, FALSE)
+          .parent()
+          .find(".btn:eq(0)")
+          .prop(DISABLED, FALSE);
+      });
+    },
+    destroy: function() {
+      return this.each(function() {
+        var evNameList =
+          "click.bs keydown.bs compositionstart.bs compositionend.bs keyup.bs input.bs paste.bs focus.bs click.bs";
+        $(this)
+          .off(evNameList)
+          .removeData(BSSUGGEST)
+          .removeAttr("style")
+          .parent()
+          .find(".btn:eq(0)")
+          .off()
+          .show()
+          .attr("data-toggle", "dropdown")
+          .prop(DISABLED, FALSE) // .addClass(DISABLED);
+          .next()
+          .css("display", "")
+          .off();
+      });
+    },
+    version: function() {
+      return VERSION;
+    }
+  };
+
+  $.fn[BSSUGGEST] = function(options) {
+    // 方法判断
+    if (typeof options === "string" && methods[options]) {
+      var inited = TRUE;
+      this.each(function() {
+        if (!$(this).data(BSSUGGEST)) {
+          return (inited = FALSE);
+        }
+      });
+      // 只要有一个未初始化,则全部都不执行方法,除非是 init 或 version
+      if (!inited && "init" !== options && "version" !== options) {
+        return this;
+      }
+
+      // 如果是方法,则参数第一个为函数名,从第二个开始为函数参数
+      return methods[options].apply(this, [].slice.call(arguments, 1));
+    } else {
+      // 调用初始化方法
+      return methods.init.apply(this, arguments);
+    }
+  };
+});
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/suggest/bootstrap-suggest.min.js b/ruoyi-admin/src/main/resources/static/ajax/libs/suggest/bootstrap-suggest.min.js
new file mode 100644
index 0000000..e68a276
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/suggest/bootstrap-suggest.min.js
@@ -0,0 +1,9 @@
+/**
+ * bootstrap-suggest-plugin - v0.1.29
+ * @description 这是一个基于 bootstrap 按钮式下拉菜单组件的搜索建议插件,必须使用于按钮式下拉菜单组件上。
+ * @author lzwme - https://lzw.me
+ * @GitHub https://github.com/lzwme/bootstrap-suggest-plugin.git
+ * @since 2019-11-18 09:30:06
+ */
+
+!function(e){if("function"==typeof define&&define.amd)define(["jquery"],e);else if("object"==typeof exports&&"object"==typeof module)e(require("jquery"));else{if(!window.jQuery)throw new Error("Not found jQuery.");e(window.jQuery)}}(function(g){var c,s=g(window),l="ActiveXObject"in window,e=navigator.userAgent.match(/Chrome\/(\d+)/);e&&(e=+e[1]);var y=l||51<e,p="bsSuggest",h="onDataRequestSuccess",v="disabled",b=!0,m=!1;function w(e){return void 0===e}function x(e){return e.data()}function k(e,t){return w(t)?e.attr("alt"):e.attr("alt",t)}function S(e,t){return void 0!==t?e.attr("data-id",t):e.attr("data-id")}function C(e,t,n){if(t&&t.key){var i,o,a=n.separator||",",r=S(e);n&&n.multiWord?((i=e.val().split(a))[i.length-1]=t.key,r?(o=r.split(a)).push(t.id):o=[t.id],S(e,o.join(a)).val(i.join(a)).focus()):S(e,t.id||"").val(t.key).focus(),e.data("pre-val",e.val()).trigger("onSetSelectValue",[t,(n.data.value||n._lastData.value)[t.index]])}}function j(i,o,e){if(o.is(":visible")){var a=i.parent(),t=a.height(),n=a.width();e.autoDropup&&setTimeout(function(){var e=i.offset().top,t=s.scrollTop(),n=o.height();s.height()+t-e<n&&n+t<e?a.addClass("dropup"):a.removeClass("dropup")},10);var r={};return"left"===e.listAlign?r={left:i.siblings("div").width()-n,right:"auto"}:"right"===e.listAlign&&(r={left:"auto",right:0}),l&&!e.showBtn&&(a.hasClass("dropup")?(r.top="auto",r.bottom=t):(r.top=t,r.bottom="auto")),e.autoMinWidth||(r.minWidth=n),o.css(r),i}}function D(e,t){var n,i,o;if(-1===t.indexId&&!t.idField||t.multiWord)return e;i=t.inputBgColor,o=t.inputWarnColor;var a=e.val(),r=e.data("pre-val");return S(e)||!a?(e.css("background",i||""),!a&&r&&e.trigger("onUnsetSelectValue").data("pre-val","")):(n=e.css("backgroundColor").replace(/ /g,"").split(",",3).join(","),~o.indexOf(n)||e.trigger("onUnsetSelectValue").data("pre-val","").css("background",o)),e}function A(e,t,n){var i,o,a=e.parent().find("tbody tr."+n.listHoverCSS);a.length&&(i=(a.index()+3)*a.height(),(o=+t.css("maxHeight").replace("px",""))<i||t.scrollTop()>o?i-=o:i=0,t.scrollTop(i))}function F(e,t){e.find("tr."+t.listHoverCSS).removeClass(t.listHoverCSS)}function f(e){var t,n=b;for(t in e)if("value"===t){n=m;break}return n?(window.console&&window.console.trace,m):e.value.length?e:m}function T(e,t){var n=t.effectiveFields;return!("__index"===e||n.length&&!~g.inArray(e,n))}function H(e,t,n,i){n.html('<div style="padding:10px 5px 5px">'+e+"</div>").show(),j(t,n,i)}function q(e,t){var n=e.parent().find("ul:eq(0)");n.is(":visible")||(n.show(),e.trigger("onShowDropdown",[t?t.data.value:[]]))}function W(e,t){var n=e.parent().find("ul:eq(0)");n.is(":visible")&&(n.hide(),e.trigger("onHideDropdown",[t?t.data.value:[]]))}function B(e,t,n){var i,o,a,r,s,l,u=e.parent().find("ul:eq(0)"),d=0,f=['<table class="table table-condensed table-sm" style="margin:0">'],c=t.value;if(!t||!(i=c.length))return n.emptyTip?H(n.emptyTip,e,u,n):(u.empty(),W(e,n)),e;if(n._lastData&&JSON.stringify(n._lastData)===JSON.stringify(t)&&u.find("tr").length===i)return q(e,n),j(e,u,n);n._lastData=t;var p,h=n.effectiveFields.length?n.effectiveFields:g.map(c[0],function(e,t){return t});n.showHeader&&(f.push("<thead><tr>"),g.each(h,function(e,t){T(t,n)&&(f.push("<th>",n.effectiveFieldsAlias[t]||t,0===e?"("+i+")":"","</th>"),e++)}),f.push("</tr></thead>")),f.push("<tbody>");var v=Math.min(n.maxOptionCount,i);for(o=0;o<v;o++){for(a in d=0,r=[],s=(p=c[o])[n.idField],l=p[n.keyField],p)w(l)&&n.indexKey===d&&(l=p[a]),w(s)&&n.indexId===d&&(s=p[a]),d++;g.each(h,function(e,t){T(t,n)&&r.push('<td data-name="',t,'">',p[t],"</td>")}),f.push('<tr data-index="',p.__index||o,'" data-id="',s,'" data-key="',l,'">',r.join(""),"</tr>")}return f.push("</tbody></table>"),u.html(f.join("")),q(e,n),setTimeout(function(){if(!y){var e=u.find("table:eq(0)"),t=0,n=0;u.height()<e.height()&&+u.css("minWidth").replace("px","")<u.width()&&(t=18,n=20),u.css("paddingRight",t),e.css("marginBottom",n)}},301),j(e,u,n),e}function _(t,n){n=n||"";var e=t._preAjax;e&&e.abort&&4!==e.readyState&&e.abort();var i={type:"GET",dataType:t.jsonp?"jsonp":"json",timeout:5e3};t.jsonp&&(i.jsonp=t.jsonp);var o,a=t.fnAdjustAjaxParam;if(g.isFunction(a)){if(o=a(n,t),m===o)return;g.extend(i,o)}return i.url=function(){if(!n||i.data)return i.url||t.url;var e="?";return/=$/.test(t.url)?e="":/\?/.test(t.url)&&(e="&"),t.url+e+encodeURIComponent(n)}(),t._preAjax=g.ajax(i).done(function(e){t.data=t.fnProcessData(e)}).fail(function(e){t.fnAjaxFail&&t.fnAjaxFail(e,t)})}function U(e,t,n,i){return n=g.trim(n),i.ignorecase&&(e=e.toLocaleLowerCase(),n=n.toLocaleLowerCase()),n&&(T(t,i)||(o=t,a=i,~g.inArray(o,a.searchFields)))&&(~n.indexOf(e)||i.twoWayMatch&&~e.indexOf(n));var o,a}var n={url:null,jsonp:null,data:{value:[]},indexId:0,indexKey:0,idField:"",keyField:"",autoSelect:b,allowNoKeyword:b,getDataMethod:"firstByUrl",delayUntilKeyup:m,ignorecase:m,effectiveFields:[],effectiveFieldsAlias:{},searchFields:[],twoWayMatch:b,multiWord:m,separator:",",delay:300,emptyTip:"",searchingTip:"搜索中...",hideOnSelect:m,maxOptionCount:200,autoDropup:m,autoMinWidth:m,showHeader:m,showBtn:b,inputBgColor:"",inputWarnColor:"rgba(255,0,0,.1)",listStyle:{"padding-top":0,"max-height":"375px","max-width":"800px",overflow:"auto",width:"auto",transition:"0.3s","-webkit-transition":"0.3s","-moz-transition":"0.3s","-o-transition":"0.3s","word-break":"keep-all","white-space":"nowrap"},listAlign:"left",listHoverStyle:"background: #07d; color:#fff",listHoverCSS:"jhover",clearable:m,keyLeft:37,keyUp:38,keyRight:39,keyDown:40,keyEnter:13,fnProcessData:function(e){return f(e)},fnGetData:function(e,t,n,i){var o,a,r,s,l={value:[]},u=i.fnPreprocessKeyword;if(e=e||"",g.isFunction(u)&&(e=u(e,i)),i.url){var d;i.searchingTip&&(d=setTimeout(function(){H(i.searchingTip,t,t.parent().find("ul"),i)},600)),_(i,e).done(function(e){n(t,i.data,i),t.trigger(h,e),"firstByUrl"===i.getDataMethod&&(i.url=null)}).always(function(){d&&clearTimeout(d)})}else{if(f(o=i.data))if(e){for(s=o.value.length,a=0;a<s;a++)for(r in o.value[a])if(o.value[a][r]&&U(e,r,o.value[a][r]+"",i)){l.value.push(o.value[a]),l.value[l.value.length-1].__index=a;break}}else l=o;n(t,l,i)}},fnAdjustAjaxParam:null,fnPreprocessKeyword:null,fnAjaxFail:null},i={init:function(f){var t=this;return w((f=f||{}).showHeader)&&f.effectiveFields&&1<f.effectiveFields.length&&(f.showHeader=b),(f=g.extend(b,{},n,f)).processData&&(f.fnProcessData=f.processData),f.getData&&(f.fnGetData=f.getData),"firstByUrl"===f.getDataMethod&&f.url&&!f.delayUntilKeyup&&_(f).done(function(e){f.url=null,t.trigger(h,e)}),g("#"+p).length||g("head:eq(0)").append('<style id="'+p+'">.'+f.listHoverCSS+"{"+f.listHoverStyle+"}</style>"),t.each(function(){var e,n,t,i,o,a,r,s=g(this),l=s.parent(),u=(i=f,o=(t=s).prev("i.clearable"),i.clearable&&!o.length&&(o=g('<i class="clearable glyphicon glyphicon-remove fa fa-plus"></i>').prependTo(t.parent())),o.css({position:"absolute",top:"calc(50% - 6px)",transform:"rotate(45deg)",zIndex:4,cursor:"pointer",width:"14px",lineHeight:"14px",textAlign:"center",fontSize:12}).hide()),d=l.find("ul:eq(0)");(d.parent().css("position","relative"),a=s,r=f,!d.length||a.data(p)?m:(a.data(p,{options:r}),b))&&(f.showBtn||(s.css("borderRadius",4),l.css("width","100%").find(".btn:eq(0)").hide()),s.removeClass(v).prop(v,m).attr("autocomplete","off"),d.css(f.listStyle),f.inputBgColor||(f.inputBgColor=s.css("backgroundColor")),s.on("keydown.bs",function(e){var t,n;if(d.is(":visible")){if(t=d.find("."+f.listHoverCSS),n="",F(d,f),e.keyCode===f.keyDown){if(t.length?t.next().length?n=x(t.next().mouseover()):f.autoSelect&&S(s,"").val(k(s)):n=x(d.find("tbody tr:first").mouseover()),A(s,d,f),!f.autoSelect)return}else if(e.keyCode===f.keyUp){if(t.length?t.prev().length?n=x(t.prev().mouseover()):f.autoSelect&&S(s,"").val(k(s)):n=x(d.find("tbody tr:last").mouseover()),A(s,d,f),!f.autoSelect)return}else e.keyCode===f.keyEnter?(n=x(t),W(s,f)):S(s,"");C(s,n,f)}else S(s,"")}).on("compositionstart.bs",function(e){c=b}).on("compositionend.bs",function(e){c=m}).on("keyup.bs input.bs paste.bs",function(e){var t;e.keyCode&&D(s,f),~g.inArray(e.keyCode,[f.keyDown,f.keyUp,f.keyEnter])?s.val(s.val()):(clearTimeout(n),n=setTimeout(function(){c||(t=s.val(),g.trim(t)&&t===k(s)||(k(s,t),f.multiWord&&(t=t.split(f.separator).reverse()[0]),(t.length||f.allowNoKeyword)&&f.fnGetData(g.trim(t),s,B,f)))},f.delay||300))}).on("focus.bs",function(){j(s,d,f)}).on("blur.bs",function(){e||(W(s,f),c=!0,setTimeout(function(){c=m}))}).on("click.bs",function(){var e=s.val();if(g.trim(e)&&e===k(s)&&d.find("table tr").length)return q(s,f);d.is(":visible")||(f.multiWord&&(e=e.split(f.separator).reverse()[0]),(e.length||f.allowNoKeyword)&&f.fnGetData(g.trim(e),s,B,f))}),l.find(".btn:eq(0)").attr("data-toggle","").click(function(){if(d.is(":visible"))W(s,f);else{if(f.url){if(s.click().focus(),!d.find("tr").length)return m}else B(s,f.data,f);q(s,f)}return m}),d.mouseenter(function(){e=1,s.blur()}).mouseleave(function(){e=0,s.focus()}).on("mouseenter","tbody tr",function(){return F(d,f),g(this).addClass(f.listHoverCSS),m}).on("mousedown","tbody tr",function(){var e=x(g(this));C(s,e,f),k(s,e.key),D(s,f),f.hideOnSelect&&W(s,f)}),u.length&&(u.click(function(){S(s,"").val(""),D(s,f)}),l.mouseenter(function(){s.prop(v)||u.css("right",f.showBtn?Math.max(s.next().width(),33)+2:12).show()}).mouseleave(function(){u.hide()})))})},show:function(){return this.each(function(){g(this).click()})},hide:function(){return this.each(function(){W(g(this))})},disable:function(){return this.each(function(){g(this).attr(v,b).parent().find(".btn:eq(0)").prop(v,b)})},enable:function(){return this.each(function(){g(this).attr(v,m).parent().find(".btn:eq(0)").prop(v,m)})},destroy:function(){return this.each(function(){g(this).off("click.bs keydown.bs compositionstart.bs compositionend.bs keyup.bs input.bs paste.bs focus.bs click.bs").removeData(p).removeAttr("style").parent().find(".btn:eq(0)").off().show().attr("data-toggle","dropdown").prop(v,m).next().css("display","").off()})},version:function(){return"0.1.29"}};g.fn[p]=function(e){if("string"==typeof e&&i[e]){var t=b;return this.each(function(){if(!g(this).data(p))return t=m}),t||"init"===e||"version"===e?i[e].apply(this,[].slice.call(arguments,1)):this}return i.init.apply(this,arguments)}});
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/summernote/font/summernote.eot b/ruoyi-admin/src/main/resources/static/ajax/libs/summernote/font/summernote.eot
new file mode 100644
index 0000000..4f047db
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/summernote/font/summernote.eot
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/summernote/font/summernote.ttf b/ruoyi-admin/src/main/resources/static/ajax/libs/summernote/font/summernote.ttf
new file mode 100644
index 0000000..64ef84c
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/summernote/font/summernote.ttf
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/summernote/font/summernote.woff b/ruoyi-admin/src/main/resources/static/ajax/libs/summernote/font/summernote.woff
new file mode 100644
index 0000000..dfd4f66
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/summernote/font/summernote.woff
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/summernote/font/summernote.woff2 b/ruoyi-admin/src/main/resources/static/ajax/libs/summernote/font/summernote.woff2
new file mode 100644
index 0000000..40b2030
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/summernote/font/summernote.woff2
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/summernote/summernote-zh-CN.js b/ruoyi-admin/src/main/resources/static/ajax/libs/summernote/summernote-zh-CN.js
new file mode 100644
index 0000000..21e7536
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/summernote/summernote-zh-CN.js
@@ -0,0 +1,155 @@
+(function ($) {
+  $.extend($.summernote.lang, {
+    'zh-CN': {
+      font: {
+        bold: '粗体',
+        italic: '斜体',
+        underline: '下划线',
+        clear: '清除格式',
+        height: '行高',
+        name: '字体',
+        strikethrough: '删除线',
+        subscript: '下标',
+        superscript: '上标',
+        size: '字号'
+      },
+      image: {
+        image: '图片',
+        insert: '插入图片',
+        resizeFull: '缩放至 100%',
+        resizeHalf: '缩放至 50%',
+        resizeQuarter: '缩放至 25%',
+        floatLeft: '靠左浮动',
+        floatRight: '靠右浮动',
+        floatNone: '取消浮动',
+        shapeRounded: '形状: 圆角',
+        shapeCircle: '形状: 圆',
+        shapeThumbnail: '形状: 缩略图',
+        shapeNone: '形状: 无',
+        dragImageHere: '将图片拖拽至此处',
+        dropImage: '拖拽图片或文本',
+        selectFromFiles: '从本地上传',
+        maximumFileSize: '文件大小最大值',
+        maximumFileSizeError: '文件大小超出最大值。',
+        url: '图片地址',
+        remove: '移除图片',
+        original: '原始图片'
+      },
+      video: {
+        video: '视频',
+        videoLink: '视频链接',
+        insert: '插入视频',
+        url: '视频地址',
+        providers: '(优酷, 腾讯, Instagram, DailyMotion, Youtube等)'
+      },
+      link: {
+        link: '链接',
+        insert: '插入链接',
+        unlink: '去除链接',
+        edit: '编辑链接',
+        textToDisplay: '显示文本',
+        url: '链接地址',
+        openInNewWindow: '在新窗口打开'
+      },
+      table: {
+        table: '表格',
+        addRowAbove: '在上方插入行',
+        addRowBelow: '在下方插入行',
+        addColLeft: '在左侧插入列',
+        addColRight: '在右侧插入列',
+        delRow: '删除行',
+        delCol: '删除列',
+        delTable: '删除表格'
+      },
+      hr: {
+        insert: '水平线'
+      },
+      style: {
+        style: '样式',
+        p: '普通',
+        blockquote: '引用',
+        pre: '代码',
+        h1: '标题 1',
+        h2: '标题 2',
+        h3: '标题 3',
+        h4: '标题 4',
+        h5: '标题 5',
+        h6: '标题 6'
+      },
+      lists: {
+        unordered: '无序列表',
+        ordered: '有序列表'
+      },
+      options: {
+        help: '帮助',
+        fullscreen: '全屏',
+        codeview: '源代码'
+      },
+      paragraph: {
+        paragraph: '段落',
+        outdent: '减少缩进',
+        indent: '增加缩进',
+        left: '左对齐',
+        center: '居中对齐',
+        right: '右对齐',
+        justify: '两端对齐'
+      },
+      color: {
+        recent: '最近使用',
+        more: '更多',
+        background: '背景',
+        foreground: '前景',
+        transparent: '透明',
+        setTransparent: '透明',
+        reset: '重置',
+        resetToDefault: '默认'
+      },
+      shortcut: {
+        shortcuts: '快捷键',
+        close: '关闭',
+        textFormatting: '文本格式',
+        action: '动作',
+        paragraphFormatting: '段落格式',
+        documentStyle: '文档样式',
+        extraKeys: '额外按键'
+      },
+      help: {
+        insertParagraph: '插入段落',
+        undo: '撤销',
+        redo: '重做',
+        tab: '增加缩进',
+        untab: '减少缩进',
+        bold: '粗体',
+        italic: '斜体',
+        underline: '下划线',
+        strikethrough: '删除线',
+        removeFormat: '清除格式',
+        justifyLeft: '左对齐',
+        justifyCenter: '居中对齐',
+        justifyRight: '右对齐',
+        justifyFull: '两端对齐',
+        insertUnorderedList: '无序列表',
+        insertOrderedList: '有序列表',
+        outdent: '减少缩进',
+        indent: '增加缩进',
+        formatPara: '设置选中内容样式为 普通',
+        formatH1: '设置选中内容样式为 标题1',
+        formatH2: '设置选中内容样式为 标题2',
+        formatH3: '设置选中内容样式为 标题3',
+        formatH4: '设置选中内容样式为 标题4',
+        formatH5: '设置选中内容样式为 标题5',
+        formatH6: '设置选中内容样式为 标题6',
+        insertHorizontalRule: '插入水平线',
+        'linkDialog.show': '显示链接对话框'
+      },
+      history: {
+        undo: '撤销',
+        redo: '重做'
+      },
+      specialChar: {
+        specialChar: '特殊字符',
+        select: '选取特殊字符'
+      }
+    }
+  });
+})(jQuery);
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/summernote/summernote.css b/ruoyi-admin/src/main/resources/static/ajax/libs/summernote/summernote.css
new file mode 100644
index 0000000..a9613fe
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/summernote/summernote.css
@@ -0,0 +1,13 @@
+/*!
+ * 
+ * Super simple wysiwyg editor v0.8.18
+ * https://summernote.org
+ * 
+ * 
+ * Copyright 2013- Alan Hong. and other contributors
+ * summernote may be freely distributed under the MIT license.
+ * 
+ * Date: 2020-05-20T18:09Z
+ * 
+ */
+@font-face{font-family:"summernote";font-style:normal;font-weight:400;font-display:auto;src:url(font/summernote.eot);src:url(font/summernote.eot?#iefix) format("embedded-opentype"),url(font/summernote.woff2) format("woff2"),url(font/summernote.woff) format("woff"),url(font/summernote.ttf) format("truetype")}[class^=note-icon]:before,[class*=" note-icon"]:before{display:inline-block;font-family:summernote;font-style:normal;font-size:inherit;text-decoration:inherit;text-rendering:auto;text-transform:none;vertical-align:middle;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;speak:none}.note-icon-fw{text-align:center;width:1.25em}.note-icon-border{border:solid .08em #eee;border-radius:.1em;padding:.2em .25em .15em}.note-icon-pull-left{float:left}.note-icon-pull-right{float:right}.note-icon.note-icon-pull-left{margin-right:.3em}.note-icon.note-icon-pull-right{margin-left:.3em}.note-icon-align::before{content:""}.note-icon-align-center::before{content:""}.note-icon-align-indent::before{content:""}.note-icon-align-justify::before{content:""}.note-icon-align-left::before{content:""}.note-icon-align-outdent::before{content:""}.note-icon-align-right::before{content:""}.note-icon-arrow-circle-down::before{content:""}.note-icon-arrow-circle-left::before{content:""}.note-icon-arrow-circle-right::before{content:""}.note-icon-arrow-circle-up::before{content:""}.note-icon-arrows-alt::before{content:""}.note-icon-arrows-h::before{content:""}.note-icon-arrows-v::before{content:""}.note-icon-bold::before{content:""}.note-icon-caret::before{content:""}.note-icon-chain-broken::before{content:""}.note-icon-circle::before{content:""}.note-icon-close::before{content:""}.note-icon-code::before{content:""}.note-icon-col-after::before{content:""}.note-icon-col-before::before{content:""}.note-icon-col-remove::before{content:""}.note-icon-eraser::before{content:""}.note-icon-float-left::before{content:""}.note-icon-float-none::before{content:""}.note-icon-float-right::before{content:""}.note-icon-font::before{content:""}.note-icon-frame::before{content:""}.note-icon-italic::before{content:""}.note-icon-link::before{content:""}.note-icon-magic::before{content:""}.note-icon-menu-check::before{content:""}.note-icon-minus::before{content:""}.note-icon-orderedlist::before{content:""}.note-icon-pencil::before{content:""}.note-icon-picture::before{content:""}.note-icon-question::before{content:""}.note-icon-redo::before{content:""}.note-icon-rollback::before{content:""}.note-icon-row-above::before{content:""}.note-icon-row-below::before{content:""}.note-icon-row-remove::before{content:""}.note-icon-special-character::before{content:""}.note-icon-square::before{content:""}.note-icon-strikethrough::before{content:""}.note-icon-subscript::before{content:""}.note-icon-summernote::before{content:""}.note-icon-superscript::before{content:""}.note-icon-table::before{content:""}.note-icon-text-height::before{content:""}.note-icon-trash::before{content:""}.note-icon-underline::before{content:""}.note-icon-undo::before{content:""}.note-icon-unorderedlist::before{content:""}.note-icon-video::before{content:""}.note-editor{position:relative}.note-editor .note-dropzone{position:absolute;display:none;z-index:100;color:#87cefa;background-color:#fff;opacity:.95}.note-editor .note-dropzone .note-dropzone-message{display:table-cell;vertical-align:middle;text-align:center;font-size:28px;font-weight:700}.note-editor .note-dropzone.hover{color:#098ddf}.note-editor.dragover .note-dropzone{display:table}.note-editor .note-editing-area{position:relative}.note-editor .note-editing-area .note-editable{outline:none}.note-editor .note-editing-area .note-editable sup{vertical-align:super}.note-editor .note-editing-area .note-editable sub{vertical-align:sub}.note-editor .note-editing-area .note-editable img.note-float-left{margin-right:10px}.note-editor .note-editing-area .note-editable img.note-float-right{margin-left:10px}.note-editor.note-frame,.note-editor.note-airframe{border:1px solid #00000032}.note-editor.note-frame.codeview .note-editing-area .note-editable,.note-editor.note-airframe.codeview .note-editing-area .note-editable{display:none}.note-editor.note-frame.codeview .note-editing-area .note-codable,.note-editor.note-airframe.codeview .note-editing-area .note-codable{display:block}.note-editor.note-frame .note-editing-area,.note-editor.note-airframe .note-editing-area{overflow:hidden}.note-editor.note-frame .note-editing-area .note-editable,.note-editor.note-airframe .note-editing-area .note-editable{padding:10px;overflow:auto;word-wrap:break-word}.note-editor.note-frame .note-editing-area .note-editable[contenteditable=false],.note-editor.note-airframe .note-editing-area .note-editable[contenteditable=false]{background-color:#8080801d}.note-editor.note-frame .note-editing-area .note-codable,.note-editor.note-airframe .note-editing-area .note-codable{display:none;width:100%;padding:10px;border:none;box-shadow:none;font-family:Menlo,Monaco,monospace,sans-serif;font-size:14px;color:#ccc;background-color:#222;resize:none;outline:none;-ms-box-sizing:border-box;box-sizing:border-box;border-radius:0;margin-bottom:0}.note-editor.note-frame.fullscreen,.note-editor.note-airframe.fullscreen{position:fixed;top:0;left:0;width:100% !important;z-index:1050}.note-editor.note-frame.fullscreen .note-resizebar,.note-editor.note-airframe.fullscreen .note-resizebar{display:none}.note-editor.note-frame .note-status-output,.note-editor.note-airframe .note-status-output{display:block;width:100%;font-size:14px;line-height:1.42857143;height:20px;margin-bottom:0;color:#000;border:0;border-top:1px solid #e2e2e2}.note-editor.note-frame .note-status-output:empty,.note-editor.note-airframe .note-status-output:empty{height:0;border-top:0 solid transparent}.note-editor.note-frame .note-status-output .pull-right,.note-editor.note-airframe .note-status-output .pull-right{float:right !important}.note-editor.note-frame .note-status-output .text-muted,.note-editor.note-airframe .note-status-output .text-muted{color:#777}.note-editor.note-frame .note-status-output .text-primary,.note-editor.note-airframe .note-status-output .text-primary{color:#286090}.note-editor.note-frame .note-status-output .text-success,.note-editor.note-airframe .note-status-output .text-success{color:#3c763d}.note-editor.note-frame .note-status-output .text-info,.note-editor.note-airframe .note-status-output .text-info{color:#31708f}.note-editor.note-frame .note-status-output .text-warning,.note-editor.note-airframe .note-status-output .text-warning{color:#8a6d3b}.note-editor.note-frame .note-status-output .text-danger,.note-editor.note-airframe .note-status-output .text-danger{color:#a94442}.note-editor.note-frame .note-status-output .alert,.note-editor.note-airframe .note-status-output .alert{margin:-7px 0 0 0;padding:7px 10px 2px 10px;border-radius:0;color:#000;background-color:#f5f5f5}.note-editor.note-frame .note-status-output .alert .note-icon,.note-editor.note-airframe .note-status-output .alert .note-icon{margin-right:5px}.note-editor.note-frame .note-status-output .alert-success,.note-editor.note-airframe .note-status-output .alert-success{color:#3c763d !important;background-color:#dff0d8 !important}.note-editor.note-frame .note-status-output .alert-info,.note-editor.note-airframe .note-status-output .alert-info{color:#31708f !important;background-color:#d9edf7 !important}.note-editor.note-frame .note-status-output .alert-warning,.note-editor.note-airframe .note-status-output .alert-warning{color:#8a6d3b !important;background-color:#fcf8e3 !important}.note-editor.note-frame .note-status-output .alert-danger,.note-editor.note-airframe .note-status-output .alert-danger{color:#a94442 !important;background-color:#f2dede !important}.note-editor.note-frame .note-statusbar,.note-editor.note-airframe .note-statusbar{background-color:#8080801d;border-bottom-left-radius:4px;border-bottom-right-radius:4px;border-top:1px solid #00000032}.note-editor.note-frame .note-statusbar .note-resizebar,.note-editor.note-airframe .note-statusbar .note-resizebar{padding-top:1px;height:9px;width:100%;cursor:ns-resize}.note-editor.note-frame .note-statusbar .note-resizebar .note-icon-bar,.note-editor.note-airframe .note-statusbar .note-resizebar .note-icon-bar{width:20px;margin:1px auto;border-top:1px solid #00000032}.note-editor.note-frame .note-statusbar.locked .note-resizebar,.note-editor.note-airframe .note-statusbar.locked .note-resizebar{cursor:default}.note-editor.note-frame .note-statusbar.locked .note-resizebar .note-icon-bar,.note-editor.note-airframe .note-statusbar.locked .note-resizebar .note-icon-bar{display:none}.note-editor.note-frame .note-placeholder,.note-editor.note-airframe .note-placeholder{padding:10px}.note-editor.note-airframe{border:0}.note-editor.note-airframe .note-editing-area .note-editable{padding:0}.note-popover.popover{display:none;max-width:none}.note-popover.popover .popover-content a{display:inline-block;max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:middle}.note-popover.popover .arrow{left:20px !important}.note-toolbar{position:relative}.note-popover .popover-content,.note-editor .note-toolbar{margin:0;padding:0 0 5px 5px}.note-popover .popover-content>.note-btn-group,.note-editor .note-toolbar>.note-btn-group{margin-top:5px;margin-left:0;margin-right:5px}.note-popover .popover-content .note-btn-group .note-table,.note-editor .note-toolbar .note-btn-group .note-table{min-width:0;padding:5px}.note-popover .popover-content .note-btn-group .note-table .note-dimension-picker,.note-editor .note-toolbar .note-btn-group .note-table .note-dimension-picker{font-size:18px}.note-popover .popover-content .note-btn-group .note-table .note-dimension-picker .note-dimension-picker-mousecatcher,.note-editor .note-toolbar .note-btn-group .note-table .note-dimension-picker .note-dimension-picker-mousecatcher{position:absolute !important;z-index:3;width:10em;height:10em;cursor:pointer}.note-popover .popover-content .note-btn-group .note-table .note-dimension-picker .note-dimension-picker-unhighlighted,.note-editor .note-toolbar .note-btn-group .note-table .note-dimension-picker .note-dimension-picker-unhighlighted{position:relative !important;z-index:1;width:5em;height:5em;background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASAgMAAAAroGbEAAAACVBMVEUAAIj4+Pjp6ekKlAqjAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfYAR0BKhmnaJzPAAAAG0lEQVQI12NgAAOtVatWMTCohoaGUY+EmIkEAEruEzK2J7tvAAAAAElFTkSuQmCC") repeat}.note-popover .popover-content .note-btn-group .note-table .note-dimension-picker .note-dimension-picker-highlighted,.note-editor .note-toolbar .note-btn-group .note-table .note-dimension-picker .note-dimension-picker-highlighted{position:absolute !important;z-index:2;width:1em;height:1em;background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASAgMAAAAroGbEAAAACVBMVEUAAIjd6vvD2f9LKLW+AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfYAR0BKwNDEVT0AAAAG0lEQVQI12NgAAOtVatWMTCohoaGUY+EmIkEAEruEzK2J7tvAAAAAElFTkSuQmCC") repeat}.note-popover .popover-content .note-style .dropdown-style blockquote,.note-popover .popover-content .note-style .dropdown-style pre,.note-editor .note-toolbar .note-style .dropdown-style blockquote,.note-editor .note-toolbar .note-style .dropdown-style pre{margin:0;padding:5px 10px}.note-popover .popover-content .note-style .dropdown-style h1,.note-popover .popover-content .note-style .dropdown-style h2,.note-popover .popover-content .note-style .dropdown-style h3,.note-popover .popover-content .note-style .dropdown-style h4,.note-popover .popover-content .note-style .dropdown-style h5,.note-popover .popover-content .note-style .dropdown-style h6,.note-popover .popover-content .note-style .dropdown-style p,.note-editor .note-toolbar .note-style .dropdown-style h1,.note-editor .note-toolbar .note-style .dropdown-style h2,.note-editor .note-toolbar .note-style .dropdown-style h3,.note-editor .note-toolbar .note-style .dropdown-style h4,.note-editor .note-toolbar .note-style .dropdown-style h5,.note-editor .note-toolbar .note-style .dropdown-style h6,.note-editor .note-toolbar .note-style .dropdown-style p{margin:0;padding:0}.note-popover .popover-content .note-color-all .note-dropdown-menu,.note-editor .note-toolbar .note-color-all .note-dropdown-menu{min-width:337px}.note-popover .popover-content .note-color .dropdown-toggle,.note-editor .note-toolbar .note-color .dropdown-toggle{width:20px;padding-left:5px}.note-popover .popover-content .note-color .note-dropdown-menu .note-palette,.note-editor .note-toolbar .note-color .note-dropdown-menu .note-palette{display:inline-block;margin:0;width:160px}.note-popover .popover-content .note-color .note-dropdown-menu .note-palette:first-child,.note-editor .note-toolbar .note-color .note-dropdown-menu .note-palette:first-child{margin:0 5px}.note-popover .popover-content .note-color .note-dropdown-menu .note-palette .note-palette-title,.note-editor .note-toolbar .note-color .note-dropdown-menu .note-palette .note-palette-title{font-size:12px;margin:2px 7px;text-align:center;border-bottom:1px solid #eee}.note-popover .popover-content .note-color .note-dropdown-menu .note-palette .note-color-reset,.note-popover .popover-content .note-color .note-dropdown-menu .note-palette .note-color-select,.note-editor .note-toolbar .note-color .note-dropdown-menu .note-palette .note-color-reset,.note-editor .note-toolbar .note-color .note-dropdown-menu .note-palette .note-color-select{font-size:11px;margin:3px;padding:0 3px;cursor:pointer;width:100%;border-radius:5px}.note-popover .popover-content .note-color .note-dropdown-menu .note-palette .note-color-reset:hover,.note-popover .popover-content .note-color .note-dropdown-menu .note-palette .note-color-select:hover,.note-editor .note-toolbar .note-color .note-dropdown-menu .note-palette .note-color-reset:hover,.note-editor .note-toolbar .note-color .note-dropdown-menu .note-palette .note-color-select:hover{background:#eee}.note-popover .popover-content .note-color .note-dropdown-menu .note-palette .note-color-row,.note-editor .note-toolbar .note-color .note-dropdown-menu .note-palette .note-color-row{height:20px}.note-popover .popover-content .note-color .note-dropdown-menu .note-palette .note-color-select-btn,.note-editor .note-toolbar .note-color .note-dropdown-menu .note-palette .note-color-select-btn{display:none}.note-popover .popover-content .note-color .note-dropdown-menu .note-palette .note-holder-custom .note-color-btn,.note-editor .note-toolbar .note-color .note-dropdown-menu .note-palette .note-holder-custom .note-color-btn{border:1px solid #eee}.note-popover .popover-content .note-para .note-dropdown-menu,.note-editor .note-toolbar .note-para .note-dropdown-menu{min-width:228px;padding:5px}.note-popover .popover-content .note-para .note-dropdown-menu>div+div,.note-editor .note-toolbar .note-para .note-dropdown-menu>div+div{margin-left:5px}.note-popover .popover-content .note-dropdown-menu,.note-editor .note-toolbar .note-dropdown-menu{min-width:160px}.note-popover .popover-content .note-dropdown-menu.right,.note-editor .note-toolbar .note-dropdown-menu.right{right:0;left:auto}.note-popover .popover-content .note-dropdown-menu.right::before,.note-editor .note-toolbar .note-dropdown-menu.right::before{right:9px;left:auto !important}.note-popover .popover-content .note-dropdown-menu.right::after,.note-editor .note-toolbar .note-dropdown-menu.right::after{right:10px;left:auto !important}.note-popover .popover-content .note-dropdown-menu.note-check a i,.note-editor .note-toolbar .note-dropdown-menu.note-check a i{color:#00bfff;visibility:hidden}.note-popover .popover-content .note-dropdown-menu.note-check a.checked i,.note-editor .note-toolbar .note-dropdown-menu.note-check a.checked i{visibility:visible}.note-popover .popover-content .note-fontsize-10,.note-editor .note-toolbar .note-fontsize-10{font-size:10px}.note-popover .popover-content .note-color-palette,.note-editor .note-toolbar .note-color-palette{line-height:1}.note-popover .popover-content .note-color-palette div .note-color-btn,.note-editor .note-toolbar .note-color-palette div .note-color-btn{width:20px;height:20px;padding:0;margin:0;border:0;border-radius:0}.note-popover .popover-content .note-color-palette div .note-color-btn:hover,.note-editor .note-toolbar .note-color-palette div .note-color-btn:hover{transform:scale(1.2);transition:all .2s}.note-modal .modal-dialog{outline:0;border-radius:5px;}.note-modal .form-group{margin-left:0;margin-right:0}.note-modal .note-modal-form{margin:0}.note-modal .note-image-dialog .note-dropzone{min-height:100px;font-size:30px;line-height:4;color:#d3d3d3;text-align:center;border:4px dashed #d3d3d3;margin-bottom:10px}@-moz-document url-prefix(){.note-modal .note-image-input{height:auto}}.note-placeholder{position:absolute;display:none;color:gray}.note-handle .note-control-selection{position:absolute;display:none;border:1px solid #000}.note-handle .note-control-selection>div{position:absolute}.note-handle .note-control-selection .note-control-selection-bg{width:100%;height:100%;background-color:#000;-webkit-opacity:.3;-khtml-opacity:.3;-moz-opacity:.3;opacity:.3;-ms-filter:progid:DXImageTransform.Microsoft.Alpha(opacity=30);filter:alpha(opacity=30)}.note-handle .note-control-selection .note-control-handle,.note-handle .note-control-selection .note-control-sizing,.note-handle .note-control-selection .note-control-holder{width:7px;height:7px;border:1px solid #000}.note-handle .note-control-selection .note-control-sizing{background-color:#000}.note-handle .note-control-selection .note-control-nw{top:-5px;left:-5px;border-right:none;border-bottom:none}.note-handle .note-control-selection .note-control-ne{top:-5px;right:-5px;border-bottom:none;border-left:none}.note-handle .note-control-selection .note-control-sw{bottom:-5px;left:-5px;border-top:none;border-right:none}.note-handle .note-control-selection .note-control-se{right:-5px;bottom:-5px;cursor:se-resize}.note-handle .note-control-selection .note-control-se.note-control-holder{cursor:default;border-top:none;border-left:none}.note-handle .note-control-selection .note-control-selection-info{right:0;bottom:0;padding:5px;margin:5px;color:#fff;background-color:#000;font-size:12px;border-radius:5px;-webkit-opacity:.7;-khtml-opacity:.7;-moz-opacity:.7;opacity:.7;-ms-filter:progid:DXImageTransform.Microsoft.Alpha(opacity=70);filter:alpha(opacity=70)}.note-hint-popover{min-width:100px;padding:2px}.note-hint-popover .popover-content{padding:3px;max-height:150px;overflow:auto}.note-hint-popover .popover-content .note-hint-group .note-hint-item{display:block !important;padding:3px}.note-hint-popover .popover-content .note-hint-group .note-hint-item.active,.note-hint-popover .popover-content .note-hint-group .note-hint-item:hover{display:block;clear:both;font-weight:400;line-height:1.4;color:#fff;white-space:nowrap;text-decoration:none;background-color:#428bca;outline:0;cursor:pointer}
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/summernote/summernote.js b/ruoyi-admin/src/main/resources/static/ajax/libs/summernote/summernote.js
new file mode 100644
index 0000000..3d8e6bb
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/summernote/summernote.js
@@ -0,0 +1,10227 @@
+/*!
+ * 
+ * Super simple wysiwyg editor v0.8.18
+ * https://summernote.org
+ * 
+ * 
+ * Copyright 2013- Alan Hong. and other contributors
+ * summernote may be freely distributed under the MIT license.
+ * 
+ * Date: 2020-05-20T18:09Z
+ * 
+ */
+(function webpackUniversalModuleDefinition(root, factory) {
+	if(typeof exports === 'object' && typeof module === 'object')
+		module.exports = factory(require("jquery"));
+	else if(typeof define === 'function' && define.amd)
+		define(["jquery"], factory);
+	else {
+		var a = typeof exports === 'object' ? factory(require("jquery")) : factory(root["jQuery"]);
+		for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
+	}
+})(window, function(__WEBPACK_EXTERNAL_MODULE__0__) {
+return /******/ (function(modules) { // webpackBootstrap
+/******/ 	// The module cache
+/******/ 	var installedModules = {};
+/******/
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+/******/
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId]) {
+/******/ 			return installedModules[moduleId].exports;
+/******/ 		}
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			i: moduleId,
+/******/ 			l: false,
+/******/ 			exports: {}
+/******/ 		};
+/******/
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ 		// Flag the module as loaded
+/******/ 		module.l = true;
+/******/
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/
+/******/
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = modules;
+/******/
+/******/ 	// expose the module cache
+/******/ 	__webpack_require__.c = installedModules;
+/******/
+/******/ 	// define getter function for harmony exports
+/******/ 	__webpack_require__.d = function(exports, name, getter) {
+/******/ 		if(!__webpack_require__.o(exports, name)) {
+/******/ 			Object.defineProperty(exports, name, { enumerable: true, get: getter });
+/******/ 		}
+/******/ 	};
+/******/
+/******/ 	// define __esModule on exports
+/******/ 	__webpack_require__.r = function(exports) {
+/******/ 		if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
+/******/ 			Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
+/******/ 		}
+/******/ 		Object.defineProperty(exports, '__esModule', { value: true });
+/******/ 	};
+/******/
+/******/ 	// create a fake namespace object
+/******/ 	// mode & 1: value is a module id, require it
+/******/ 	// mode & 2: merge all properties of value into the ns
+/******/ 	// mode & 4: return value when already ns object
+/******/ 	// mode & 8|1: behave like require
+/******/ 	__webpack_require__.t = function(value, mode) {
+/******/ 		if(mode & 1) value = __webpack_require__(value);
+/******/ 		if(mode & 8) return value;
+/******/ 		if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
+/******/ 		var ns = Object.create(null);
+/******/ 		__webpack_require__.r(ns);
+/******/ 		Object.defineProperty(ns, 'default', { enumerable: true, value: value });
+/******/ 		if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
+/******/ 		return ns;
+/******/ 	};
+/******/
+/******/ 	// getDefaultExport function for compatibility with non-harmony modules
+/******/ 	__webpack_require__.n = function(module) {
+/******/ 		var getter = module && module.__esModule ?
+/******/ 			function getDefault() { return module['default']; } :
+/******/ 			function getModuleExports() { return module; };
+/******/ 		__webpack_require__.d(getter, 'a', getter);
+/******/ 		return getter;
+/******/ 	};
+/******/
+/******/ 	// Object.prototype.hasOwnProperty.call
+/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ 	// __webpack_public_path__
+/******/ 	__webpack_require__.p = "";
+/******/
+/******/
+/******/ 	// Load entry module and return exports
+/******/ 	return __webpack_require__(__webpack_require__.s = 52);
+/******/ })
+/************************************************************************/
+/******/ ({
+
+/***/ 0:
+/***/ (function(module, exports) {
+
+module.exports = __WEBPACK_EXTERNAL_MODULE__0__;
+
+/***/ }),
+
+/***/ 1:
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+/* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
+/* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(jquery__WEBPACK_IMPORTED_MODULE_0__);
+function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+
+
+var Renderer = /*#__PURE__*/function () {
+  function Renderer(markup, children, options, callback) {
+    _classCallCheck(this, Renderer);
+
+    this.markup = markup;
+    this.children = children;
+    this.options = options;
+    this.callback = callback;
+  }
+
+  _createClass(Renderer, [{
+    key: "render",
+    value: function render($parent) {
+      var $node = jquery__WEBPACK_IMPORTED_MODULE_0___default()(this.markup);
+
+      if (this.options && this.options.contents) {
+        $node.html(this.options.contents);
+      }
+
+      if (this.options && this.options.className) {
+        $node.addClass(this.options.className);
+      }
+
+      if (this.options && this.options.data) {
+        jquery__WEBPACK_IMPORTED_MODULE_0___default.a.each(this.options.data, function (k, v) {
+          $node.attr('data-' + k, v);
+        });
+      }
+
+      if (this.options && this.options.click) {
+        $node.on('click', this.options.click);
+      }
+
+      if (this.children) {
+        var $container = $node.find('.note-children-container');
+        this.children.forEach(function (child) {
+          child.render($container.length ? $container : $node);
+        });
+      }
+
+      if (this.callback) {
+        this.callback($node, this.options);
+      }
+
+      if (this.options && this.options.callback) {
+        this.options.callback($node);
+      }
+
+      if ($parent) {
+        $parent.append($node);
+      }
+
+      return $node;
+    }
+  }]);
+
+  return Renderer;
+}();
+
+/* harmony default export */ __webpack_exports__["a"] = ({
+  create: function create(markup, callback) {
+    return function () {
+      var options = _typeof(arguments[1]) === 'object' ? arguments[1] : arguments[0];
+      var children = Array.isArray(arguments[0]) ? arguments[0] : [];
+
+      if (options && options.children) {
+        children = options.children;
+      }
+
+      return new Renderer(markup, children, options, callback);
+    };
+  }
+});
+
+/***/ }),
+
+/***/ 2:
+/***/ (function(module, exports) {
+
+/* WEBPACK VAR INJECTION */(function(__webpack_amd_options__) {/* globals __webpack_amd_options__ */
+module.exports = __webpack_amd_options__;
+
+/* WEBPACK VAR INJECTION */}.call(this, {}))
+
+/***/ }),
+
+/***/ 3:
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+
+// EXTERNAL MODULE: external {"root":"jQuery","commonjs2":"jquery","commonjs":"jquery","amd":"jquery"}
+var external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_ = __webpack_require__(0);
+var external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default = /*#__PURE__*/__webpack_require__.n(external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_);
+
+// CONCATENATED MODULE: ./src/js/base/summernote-en-US.js
+
+external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.summernote = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.summernote || {
+  lang: {}
+};
+external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.extend(external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.summernote.lang, {
+  'en-US': {
+    font: {
+      bold: 'Bold',
+      italic: 'Italic',
+      underline: 'Underline',
+      clear: 'Remove Font Style',
+      height: 'Line Height',
+      name: 'Font Family',
+      strikethrough: 'Strikethrough',
+      subscript: 'Subscript',
+      superscript: 'Superscript',
+      size: 'Font Size',
+      sizeunit: 'Font Size Unit'
+    },
+    image: {
+      image: 'Picture',
+      insert: 'Insert Image',
+      resizeFull: 'Resize full',
+      resizeHalf: 'Resize half',
+      resizeQuarter: 'Resize quarter',
+      resizeNone: 'Original size',
+      floatLeft: 'Float Left',
+      floatRight: 'Float Right',
+      floatNone: 'Remove float',
+      shapeRounded: 'Shape: Rounded',
+      shapeCircle: 'Shape: Circle',
+      shapeThumbnail: 'Shape: Thumbnail',
+      shapeNone: 'Shape: None',
+      dragImageHere: 'Drag image or text here',
+      dropImage: 'Drop image or Text',
+      selectFromFiles: 'Select from files',
+      maximumFileSize: 'Maximum file size',
+      maximumFileSizeError: 'Maximum file size exceeded.',
+      url: 'Image URL',
+      remove: 'Remove Image',
+      original: 'Original'
+    },
+    video: {
+      video: 'Video',
+      videoLink: 'Video Link',
+      insert: 'Insert Video',
+      url: 'Video URL',
+      providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion or Youku)'
+    },
+    link: {
+      link: 'Link',
+      insert: 'Insert Link',
+      unlink: 'Unlink',
+      edit: 'Edit',
+      textToDisplay: 'Text to display',
+      url: 'To what URL should this link go?',
+      openInNewWindow: 'Open in new window',
+      useProtocol: 'Use default protocol'
+    },
+    table: {
+      table: 'Table',
+      addRowAbove: 'Add row above',
+      addRowBelow: 'Add row below',
+      addColLeft: 'Add column left',
+      addColRight: 'Add column right',
+      delRow: 'Delete row',
+      delCol: 'Delete column',
+      delTable: 'Delete table'
+    },
+    hr: {
+      insert: 'Insert Horizontal Rule'
+    },
+    style: {
+      style: 'Style',
+      p: 'Normal',
+      blockquote: 'Quote',
+      pre: 'Code',
+      h1: 'Header 1',
+      h2: 'Header 2',
+      h3: 'Header 3',
+      h4: 'Header 4',
+      h5: 'Header 5',
+      h6: 'Header 6'
+    },
+    lists: {
+      unordered: 'Unordered list',
+      ordered: 'Ordered list'
+    },
+    options: {
+      help: 'Help',
+      fullscreen: 'Full Screen',
+      codeview: 'Code View'
+    },
+    paragraph: {
+      paragraph: 'Paragraph',
+      outdent: 'Outdent',
+      indent: 'Indent',
+      left: 'Align left',
+      center: 'Align center',
+      right: 'Align right',
+      justify: 'Justify full'
+    },
+    color: {
+      recent: 'Recent Color',
+      more: 'More Color',
+      background: 'Background Color',
+      foreground: 'Text Color',
+      transparent: 'Transparent',
+      setTransparent: 'Set transparent',
+      reset: 'Reset',
+      resetToDefault: 'Reset to default',
+      cpSelect: 'Select'
+    },
+    shortcut: {
+      shortcuts: 'Keyboard shortcuts',
+      close: 'Close',
+      textFormatting: 'Text formatting',
+      action: 'Action',
+      paragraphFormatting: 'Paragraph formatting',
+      documentStyle: 'Document Style',
+      extraKeys: 'Extra keys'
+    },
+    help: {
+      'escape': 'Escape',
+      'insertParagraph': 'Insert Paragraph',
+      'undo': 'Undo the last command',
+      'redo': 'Redo the last command',
+      'tab': 'Tab',
+      'untab': 'Untab',
+      'bold': 'Set a bold style',
+      'italic': 'Set a italic style',
+      'underline': 'Set a underline style',
+      'strikethrough': 'Set a strikethrough style',
+      'removeFormat': 'Clean a style',
+      'justifyLeft': 'Set left align',
+      'justifyCenter': 'Set center align',
+      'justifyRight': 'Set right align',
+      'justifyFull': 'Set full align',
+      'insertUnorderedList': 'Toggle unordered list',
+      'insertOrderedList': 'Toggle ordered list',
+      'outdent': 'Outdent on current paragraph',
+      'indent': 'Indent on current paragraph',
+      'formatPara': 'Change current block\'s format as a paragraph(P tag)',
+      'formatH1': 'Change current block\'s format as H1',
+      'formatH2': 'Change current block\'s format as H2',
+      'formatH3': 'Change current block\'s format as H3',
+      'formatH4': 'Change current block\'s format as H4',
+      'formatH5': 'Change current block\'s format as H5',
+      'formatH6': 'Change current block\'s format as H6',
+      'insertHorizontalRule': 'Insert horizontal rule',
+      'linkDialog.show': 'Show Link Dialog'
+    },
+    history: {
+      undo: 'Undo',
+      redo: 'Redo'
+    },
+    specialChar: {
+      specialChar: 'SPECIAL CHARACTERS',
+      select: 'Select Special characters'
+    },
+    output: {
+      noSelection: 'No Selection Made!'
+    }
+  }
+});
+// CONCATENATED MODULE: ./src/js/base/core/env.js
+
+var isSupportAmd = typeof define === 'function' && __webpack_require__(2); // eslint-disable-line
+
+/**
+ * returns whether font is installed or not.
+ *
+ * @param {String} fontName
+ * @return {Boolean}
+ */
+
+var genericFontFamilies = ['sans-serif', 'serif', 'monospace', 'cursive', 'fantasy'];
+
+function validFontName(fontName) {
+  return external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.inArray(fontName.toLowerCase(), genericFontFamilies) === -1 ? "'".concat(fontName, "'") : fontName;
+}
+
+function env_isFontInstalled(fontName) {
+  var testFontName = fontName === 'Comic Sans MS' ? 'Courier New' : 'Comic Sans MS';
+  var testText = 'mmmmmmmmmmwwwww';
+  var testSize = '200px';
+  var canvas = document.createElement('canvas');
+  var context = canvas.getContext('2d');
+  context.font = testSize + " '" + testFontName + "'";
+  var originalWidth = context.measureText(testText).width;
+  context.font = testSize + ' ' + validFontName(fontName) + ', "' + testFontName + '"';
+  var width = context.measureText(testText).width;
+  return originalWidth !== width;
+}
+
+var userAgent = navigator.userAgent;
+var isMSIE = /MSIE|Trident/i.test(userAgent);
+var browserVersion;
+
+if (isMSIE) {
+  var matches = /MSIE (\d+[.]\d+)/.exec(userAgent);
+
+  if (matches) {
+    browserVersion = parseFloat(matches[1]);
+  }
+
+  matches = /Trident\/.*rv:([0-9]{1,}[.0-9]{0,})/.exec(userAgent);
+
+  if (matches) {
+    browserVersion = parseFloat(matches[1]);
+  }
+}
+
+var isEdge = /Edge\/\d+/.test(userAgent);
+var isSupportTouch = 'ontouchstart' in window || navigator.MaxTouchPoints > 0 || navigator.msMaxTouchPoints > 0; // [workaround] IE doesn't have input events for contentEditable
+// - see: https://goo.gl/4bfIvA
+
+var inputEventName = isMSIE ? 'DOMCharacterDataModified DOMSubtreeModified DOMNodeInserted' : 'input';
+/**
+ * @class core.env
+ *
+ * Object which check platform and agent
+ *
+ * @singleton
+ * @alternateClassName env
+ */
+
+/* harmony default export */ var env = ({
+  isMac: navigator.appVersion.indexOf('Mac') > -1,
+  isMSIE: isMSIE,
+  isEdge: isEdge,
+  isFF: !isEdge && /firefox/i.test(userAgent),
+  isPhantom: /PhantomJS/i.test(userAgent),
+  isWebkit: !isEdge && /webkit/i.test(userAgent),
+  isChrome: !isEdge && /chrome/i.test(userAgent),
+  isSafari: !isEdge && /safari/i.test(userAgent) && !/chrome/i.test(userAgent),
+  browserVersion: browserVersion,
+  jqueryVersion: parseFloat(external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.fn.jquery),
+  isSupportAmd: isSupportAmd,
+  isSupportTouch: isSupportTouch,
+  isFontInstalled: env_isFontInstalled,
+  isW3CRangeSupport: !!document.createRange,
+  inputEventName: inputEventName,
+  genericFontFamilies: genericFontFamilies,
+  validFontName: validFontName
+});
+// CONCATENATED MODULE: ./src/js/base/core/func.js
+
+/**
+ * @class core.func
+ *
+ * func utils (for high-order func's arg)
+ *
+ * @singleton
+ * @alternateClassName func
+ */
+
+function eq(itemA) {
+  return function (itemB) {
+    return itemA === itemB;
+  };
+}
+
+function eq2(itemA, itemB) {
+  return itemA === itemB;
+}
+
+function peq2(propName) {
+  return function (itemA, itemB) {
+    return itemA[propName] === itemB[propName];
+  };
+}
+
+function ok() {
+  return true;
+}
+
+function fail() {
+  return false;
+}
+
+function not(f) {
+  return function () {
+    return !f.apply(f, arguments);
+  };
+}
+
+function and(fA, fB) {
+  return function (item) {
+    return fA(item) && fB(item);
+  };
+}
+
+function func_self(a) {
+  return a;
+}
+
+function func_invoke(obj, method) {
+  return function () {
+    return obj[method].apply(obj, arguments);
+  };
+}
+
+var idCounter = 0;
+/**
+ * reset globally-unique id
+ *
+ */
+
+function resetUniqueId() {
+  idCounter = 0;
+}
+/**
+ * generate a globally-unique id
+ *
+ * @param {String} [prefix]
+ */
+
+
+function uniqueId(prefix) {
+  var id = ++idCounter + '';
+  return prefix ? prefix + id : id;
+}
+/**
+ * returns bnd (bounds) from rect
+ *
+ * - IE Compatibility Issue: http://goo.gl/sRLOAo
+ * - Scroll Issue: http://goo.gl/sNjUc
+ *
+ * @param {Rect} rect
+ * @return {Object} bounds
+ * @return {Number} bounds.top
+ * @return {Number} bounds.left
+ * @return {Number} bounds.width
+ * @return {Number} bounds.height
+ */
+
+
+function rect2bnd(rect) {
+  var $document = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(document);
+  return {
+    top: rect.top + $document.scrollTop(),
+    left: rect.left + $document.scrollLeft(),
+    width: rect.right - rect.left,
+    height: rect.bottom - rect.top
+  };
+}
+/**
+ * returns a copy of the object where the keys have become the values and the values the keys.
+ * @param {Object} obj
+ * @return {Object}
+ */
+
+
+function invertObject(obj) {
+  var inverted = {};
+
+  for (var key in obj) {
+    if (Object.prototype.hasOwnProperty.call(obj, key)) {
+      inverted[obj[key]] = key;
+    }
+  }
+
+  return inverted;
+}
+/**
+ * @param {String} namespace
+ * @param {String} [prefix]
+ * @return {String}
+ */
+
+
+function namespaceToCamel(namespace, prefix) {
+  prefix = prefix || '';
+  return prefix + namespace.split('.').map(function (name) {
+    return name.substring(0, 1).toUpperCase() + name.substring(1);
+  }).join('');
+}
+/**
+ * Returns a function, that, as long as it continues to be invoked, will not
+ * be triggered. The function will be called after it stops being called for
+ * N milliseconds. If `immediate` is passed, trigger the function on the
+ * leading edge, instead of the trailing.
+ * @param {Function} func
+ * @param {Number} wait
+ * @param {Boolean} immediate
+ * @return {Function}
+ */
+
+
+function debounce(func, wait, immediate) {
+  var timeout;
+  return function () {
+    var context = this;
+    var args = arguments;
+
+    var later = function later() {
+      timeout = null;
+
+      if (!immediate) {
+        func.apply(context, args);
+      }
+    };
+
+    var callNow = immediate && !timeout;
+    clearTimeout(timeout);
+    timeout = setTimeout(later, wait);
+
+    if (callNow) {
+      func.apply(context, args);
+    }
+  };
+}
+/**
+ *
+ * @param {String} url
+ * @return {Boolean}
+ */
+
+
+function isValidUrl(url) {
+  var expression = /[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/gi;
+  return expression.test(url);
+}
+
+/* harmony default export */ var func = ({
+  eq: eq,
+  eq2: eq2,
+  peq2: peq2,
+  ok: ok,
+  fail: fail,
+  self: func_self,
+  not: not,
+  and: and,
+  invoke: func_invoke,
+  resetUniqueId: resetUniqueId,
+  uniqueId: uniqueId,
+  rect2bnd: rect2bnd,
+  invertObject: invertObject,
+  namespaceToCamel: namespaceToCamel,
+  debounce: debounce,
+  isValidUrl: isValidUrl
+});
+// CONCATENATED MODULE: ./src/js/base/core/lists.js
+
+/**
+ * returns the first item of an array.
+ *
+ * @param {Array} array
+ */
+
+function lists_head(array) {
+  return array[0];
+}
+/**
+ * returns the last item of an array.
+ *
+ * @param {Array} array
+ */
+
+
+function lists_last(array) {
+  return array[array.length - 1];
+}
+/**
+ * returns everything but the last entry of the array.
+ *
+ * @param {Array} array
+ */
+
+
+function initial(array) {
+  return array.slice(0, array.length - 1);
+}
+/**
+ * returns the rest of the items in an array.
+ *
+ * @param {Array} array
+ */
+
+
+function tail(array) {
+  return array.slice(1);
+}
+/**
+ * returns item of array
+ */
+
+
+function find(array, pred) {
+  for (var idx = 0, len = array.length; idx < len; idx++) {
+    var item = array[idx];
+
+    if (pred(item)) {
+      return item;
+    }
+  }
+}
+/**
+ * returns true if all of the values in the array pass the predicate truth test.
+ */
+
+
+function lists_all(array, pred) {
+  for (var idx = 0, len = array.length; idx < len; idx++) {
+    if (!pred(array[idx])) {
+      return false;
+    }
+  }
+
+  return true;
+}
+/**
+ * returns true if the value is present in the list.
+ */
+
+
+function contains(array, item) {
+  if (array && array.length && item) {
+    if (array.indexOf) {
+      return array.indexOf(item) !== -1;
+    } else if (array.contains) {
+      // `DOMTokenList` doesn't implement `.indexOf`, but it implements `.contains`
+      return array.contains(item);
+    }
+  }
+
+  return false;
+}
+/**
+ * get sum from a list
+ *
+ * @param {Array} array - array
+ * @param {Function} fn - iterator
+ */
+
+
+function sum(array, fn) {
+  fn = fn || func.self;
+  return array.reduce(function (memo, v) {
+    return memo + fn(v);
+  }, 0);
+}
+/**
+ * returns a copy of the collection with array type.
+ * @param {Collection} collection - collection eg) node.childNodes, ...
+ */
+
+
+function from(collection) {
+  var result = [];
+  var length = collection.length;
+  var idx = -1;
+
+  while (++idx < length) {
+    result[idx] = collection[idx];
+  }
+
+  return result;
+}
+/**
+ * returns whether list is empty or not
+ */
+
+
+function lists_isEmpty(array) {
+  return !array || !array.length;
+}
+/**
+ * cluster elements by predicate function.
+ *
+ * @param {Array} array - array
+ * @param {Function} fn - predicate function for cluster rule
+ * @param {Array[]}
+ */
+
+
+function clusterBy(array, fn) {
+  if (!array.length) {
+    return [];
+  }
+
+  var aTail = tail(array);
+  return aTail.reduce(function (memo, v) {
+    var aLast = lists_last(memo);
+
+    if (fn(lists_last(aLast), v)) {
+      aLast[aLast.length] = v;
+    } else {
+      memo[memo.length] = [v];
+    }
+
+    return memo;
+  }, [[lists_head(array)]]);
+}
+/**
+ * returns a copy of the array with all false values removed
+ *
+ * @param {Array} array - array
+ * @param {Function} fn - predicate function for cluster rule
+ */
+
+
+function compact(array) {
+  var aResult = [];
+
+  for (var idx = 0, len = array.length; idx < len; idx++) {
+    if (array[idx]) {
+      aResult.push(array[idx]);
+    }
+  }
+
+  return aResult;
+}
+/**
+ * produces a duplicate-free version of the array
+ *
+ * @param {Array} array
+ */
+
+
+function unique(array) {
+  var results = [];
+
+  for (var idx = 0, len = array.length; idx < len; idx++) {
+    if (!contains(results, array[idx])) {
+      results.push(array[idx]);
+    }
+  }
+
+  return results;
+}
+/**
+ * returns next item.
+ * @param {Array} array
+ */
+
+
+function lists_next(array, item) {
+  if (array && array.length && item) {
+    var idx = array.indexOf(item);
+    return idx === -1 ? null : array[idx + 1];
+  }
+
+  return null;
+}
+/**
+ * returns prev item.
+ * @param {Array} array
+ */
+
+
+function prev(array, item) {
+  if (array && array.length && item) {
+    var idx = array.indexOf(item);
+    return idx === -1 ? null : array[idx - 1];
+  }
+
+  return null;
+}
+/**
+ * @class core.list
+ *
+ * list utils
+ *
+ * @singleton
+ * @alternateClassName list
+ */
+
+
+/* harmony default export */ var lists = ({
+  head: lists_head,
+  last: lists_last,
+  initial: initial,
+  tail: tail,
+  prev: prev,
+  next: lists_next,
+  find: find,
+  contains: contains,
+  all: lists_all,
+  sum: sum,
+  from: from,
+  isEmpty: lists_isEmpty,
+  clusterBy: clusterBy,
+  compact: compact,
+  unique: unique
+});
+// CONCATENATED MODULE: ./src/js/base/core/dom.js
+
+
+
+
+var NBSP_CHAR = String.fromCharCode(160);
+var ZERO_WIDTH_NBSP_CHAR = "\uFEFF";
+/**
+ * @method isEditable
+ *
+ * returns whether node is `note-editable` or not.
+ *
+ * @param {Node} node
+ * @return {Boolean}
+ */
+
+function isEditable(node) {
+  return node && external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(node).hasClass('note-editable');
+}
+/**
+ * @method isControlSizing
+ *
+ * returns whether node is `note-control-sizing` or not.
+ *
+ * @param {Node} node
+ * @return {Boolean}
+ */
+
+
+function isControlSizing(node) {
+  return node && external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(node).hasClass('note-control-sizing');
+}
+/**
+ * @method makePredByNodeName
+ *
+ * returns predicate which judge whether nodeName is same
+ *
+ * @param {String} nodeName
+ * @return {Function}
+ */
+
+
+function makePredByNodeName(nodeName) {
+  nodeName = nodeName.toUpperCase();
+  return function (node) {
+    return node && node.nodeName.toUpperCase() === nodeName;
+  };
+}
+/**
+ * @method isText
+ *
+ *
+ *
+ * @param {Node} node
+ * @return {Boolean} true if node's type is text(3)
+ */
+
+
+function isText(node) {
+  return node && node.nodeType === 3;
+}
+/**
+ * @method isElement
+ *
+ *
+ *
+ * @param {Node} node
+ * @return {Boolean} true if node's type is element(1)
+ */
+
+
+function isElement(node) {
+  return node && node.nodeType === 1;
+}
+/**
+ * ex) br, col, embed, hr, img, input, ...
+ * @see http://www.w3.org/html/wg/drafts/html/master/syntax.html#void-elements
+ */
+
+
+function isVoid(node) {
+  return node && /^BR|^IMG|^HR|^IFRAME|^BUTTON|^INPUT|^AUDIO|^VIDEO|^EMBED/.test(node.nodeName.toUpperCase());
+}
+
+function isPara(node) {
+  if (isEditable(node)) {
+    return false;
+  } // Chrome(v31.0), FF(v25.0.1) use DIV for paragraph
+
+
+  return node && /^DIV|^P|^LI|^H[1-7]/.test(node.nodeName.toUpperCase());
+}
+
+function isHeading(node) {
+  return node && /^H[1-7]/.test(node.nodeName.toUpperCase());
+}
+
+var isPre = makePredByNodeName('PRE');
+var isLi = makePredByNodeName('LI');
+
+function isPurePara(node) {
+  return isPara(node) && !isLi(node);
+}
+
+var isTable = makePredByNodeName('TABLE');
+var isData = makePredByNodeName('DATA');
+
+function dom_isInline(node) {
+  return !isBodyContainer(node) && !isList(node) && !isHr(node) && !isPara(node) && !isTable(node) && !isBlockquote(node) && !isData(node);
+}
+
+function isList(node) {
+  return node && /^UL|^OL/.test(node.nodeName.toUpperCase());
+}
+
+var isHr = makePredByNodeName('HR');
+
+function dom_isCell(node) {
+  return node && /^TD|^TH/.test(node.nodeName.toUpperCase());
+}
+
+var isBlockquote = makePredByNodeName('BLOCKQUOTE');
+
+function isBodyContainer(node) {
+  return dom_isCell(node) || isBlockquote(node) || isEditable(node);
+}
+
+var isAnchor = makePredByNodeName('A');
+
+function isParaInline(node) {
+  return dom_isInline(node) && !!dom_ancestor(node, isPara);
+}
+
+function isBodyInline(node) {
+  return dom_isInline(node) && !dom_ancestor(node, isPara);
+}
+
+var isBody = makePredByNodeName('BODY');
+/**
+ * returns whether nodeB is closest sibling of nodeA
+ *
+ * @param {Node} nodeA
+ * @param {Node} nodeB
+ * @return {Boolean}
+ */
+
+function isClosestSibling(nodeA, nodeB) {
+  return nodeA.nextSibling === nodeB || nodeA.previousSibling === nodeB;
+}
+/**
+ * returns array of closest siblings with node
+ *
+ * @param {Node} node
+ * @param {function} [pred] - predicate function
+ * @return {Node[]}
+ */
+
+
+function withClosestSiblings(node, pred) {
+  pred = pred || func.ok;
+  var siblings = [];
+
+  if (node.previousSibling && pred(node.previousSibling)) {
+    siblings.push(node.previousSibling);
+  }
+
+  siblings.push(node);
+
+  if (node.nextSibling && pred(node.nextSibling)) {
+    siblings.push(node.nextSibling);
+  }
+
+  return siblings;
+}
+/**
+ * blank HTML for cursor position
+ * - [workaround] old IE only works with &nbsp;
+ * - [workaround] IE11 and other browser works with bogus br
+ */
+
+
+var blankHTML = env.isMSIE && env.browserVersion < 11 ? '&nbsp;' : '<br>';
+/**
+ * @method nodeLength
+ *
+ * returns #text's text size or element's childNodes size
+ *
+ * @param {Node} node
+ */
+
+function nodeLength(node) {
+  if (isText(node)) {
+    return node.nodeValue.length;
+  }
+
+  if (node) {
+    return node.childNodes.length;
+  }
+
+  return 0;
+}
+/**
+ * returns whether deepest child node is empty or not.
+ *
+ * @param {Node} node
+ * @return {Boolean}
+ */
+
+
+function deepestChildIsEmpty(node) {
+  do {
+    if (node.firstElementChild === null || node.firstElementChild.innerHTML === '') break;
+  } while (node = node.firstElementChild);
+
+  return dom_isEmpty(node);
+}
+/**
+ * returns whether node is empty or not.
+ *
+ * @param {Node} node
+ * @return {Boolean}
+ */
+
+
+function dom_isEmpty(node) {
+  var len = nodeLength(node);
+
+  if (len === 0) {
+    return true;
+  } else if (!isText(node) && len === 1 && node.innerHTML === blankHTML) {
+    // ex) <p><br></p>, <span><br></span>
+    return true;
+  } else if (lists.all(node.childNodes, isText) && node.innerHTML === '') {
+    // ex) <p></p>, <span></span>
+    return true;
+  }
+
+  return false;
+}
+/**
+ * padding blankHTML if node is empty (for cursor position)
+ */
+
+
+function paddingBlankHTML(node) {
+  if (!isVoid(node) && !nodeLength(node)) {
+    node.innerHTML = blankHTML;
+  }
+}
+/**
+ * find nearest ancestor predicate hit
+ *
+ * @param {Node} node
+ * @param {Function} pred - predicate function
+ */
+
+
+function dom_ancestor(node, pred) {
+  while (node) {
+    if (pred(node)) {
+      return node;
+    }
+
+    if (isEditable(node)) {
+      break;
+    }
+
+    node = node.parentNode;
+  }
+
+  return null;
+}
+/**
+ * find nearest ancestor only single child blood line and predicate hit
+ *
+ * @param {Node} node
+ * @param {Function} pred - predicate function
+ */
+
+
+function singleChildAncestor(node, pred) {
+  node = node.parentNode;
+
+  while (node) {
+    if (nodeLength(node) !== 1) {
+      break;
+    }
+
+    if (pred(node)) {
+      return node;
+    }
+
+    if (isEditable(node)) {
+      break;
+    }
+
+    node = node.parentNode;
+  }
+
+  return null;
+}
+/**
+ * returns new array of ancestor nodes (until predicate hit).
+ *
+ * @param {Node} node
+ * @param {Function} [optional] pred - predicate function
+ */
+
+
+function listAncestor(node, pred) {
+  pred = pred || func.fail;
+  var ancestors = [];
+  dom_ancestor(node, function (el) {
+    if (!isEditable(el)) {
+      ancestors.push(el);
+    }
+
+    return pred(el);
+  });
+  return ancestors;
+}
+/**
+ * find farthest ancestor predicate hit
+ */
+
+
+function lastAncestor(node, pred) {
+  var ancestors = listAncestor(node);
+  return lists.last(ancestors.filter(pred));
+}
+/**
+ * returns common ancestor node between two nodes.
+ *
+ * @param {Node} nodeA
+ * @param {Node} nodeB
+ */
+
+
+function dom_commonAncestor(nodeA, nodeB) {
+  var ancestors = listAncestor(nodeA);
+
+  for (var n = nodeB; n; n = n.parentNode) {
+    if (ancestors.indexOf(n) > -1) return n;
+  }
+
+  return null; // difference document area
+}
+/**
+ * listing all previous siblings (until predicate hit).
+ *
+ * @param {Node} node
+ * @param {Function} [optional] pred - predicate function
+ */
+
+
+function listPrev(node, pred) {
+  pred = pred || func.fail;
+  var nodes = [];
+
+  while (node) {
+    if (pred(node)) {
+      break;
+    }
+
+    nodes.push(node);
+    node = node.previousSibling;
+  }
+
+  return nodes;
+}
+/**
+ * listing next siblings (until predicate hit).
+ *
+ * @param {Node} node
+ * @param {Function} [pred] - predicate function
+ */
+
+
+function listNext(node, pred) {
+  pred = pred || func.fail;
+  var nodes = [];
+
+  while (node) {
+    if (pred(node)) {
+      break;
+    }
+
+    nodes.push(node);
+    node = node.nextSibling;
+  }
+
+  return nodes;
+}
+/**
+ * listing descendant nodes
+ *
+ * @param {Node} node
+ * @param {Function} [pred] - predicate function
+ */
+
+
+function listDescendant(node, pred) {
+  var descendants = [];
+  pred = pred || func.ok; // start DFS(depth first search) with node
+
+  (function fnWalk(current) {
+    if (node !== current && pred(current)) {
+      descendants.push(current);
+    }
+
+    for (var idx = 0, len = current.childNodes.length; idx < len; idx++) {
+      fnWalk(current.childNodes[idx]);
+    }
+  })(node);
+
+  return descendants;
+}
+/**
+ * wrap node with new tag.
+ *
+ * @param {Node} node
+ * @param {Node} tagName of wrapper
+ * @return {Node} - wrapper
+ */
+
+
+function wrap(node, wrapperName) {
+  var parent = node.parentNode;
+  var wrapper = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()('<' + wrapperName + '>')[0];
+  parent.insertBefore(wrapper, node);
+  wrapper.appendChild(node);
+  return wrapper;
+}
+/**
+ * insert node after preceding
+ *
+ * @param {Node} node
+ * @param {Node} preceding - predicate function
+ */
+
+
+function insertAfter(node, preceding) {
+  var next = preceding.nextSibling;
+  var parent = preceding.parentNode;
+
+  if (next) {
+    parent.insertBefore(node, next);
+  } else {
+    parent.appendChild(node);
+  }
+
+  return node;
+}
+/**
+ * append elements.
+ *
+ * @param {Node} node
+ * @param {Collection} aChild
+ */
+
+
+function appendChildNodes(node, aChild) {
+  external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.each(aChild, function (idx, child) {
+    node.appendChild(child);
+  });
+  return node;
+}
+/**
+ * returns whether boundaryPoint is left edge or not.
+ *
+ * @param {BoundaryPoint} point
+ * @return {Boolean}
+ */
+
+
+function isLeftEdgePoint(point) {
+  return point.offset === 0;
+}
+/**
+ * returns whether boundaryPoint is right edge or not.
+ *
+ * @param {BoundaryPoint} point
+ * @return {Boolean}
+ */
+
+
+function isRightEdgePoint(point) {
+  return point.offset === nodeLength(point.node);
+}
+/**
+ * returns whether boundaryPoint is edge or not.
+ *
+ * @param {BoundaryPoint} point
+ * @return {Boolean}
+ */
+
+
+function isEdgePoint(point) {
+  return isLeftEdgePoint(point) || isRightEdgePoint(point);
+}
+/**
+ * returns whether node is left edge of ancestor or not.
+ *
+ * @param {Node} node
+ * @param {Node} ancestor
+ * @return {Boolean}
+ */
+
+
+function dom_isLeftEdgeOf(node, ancestor) {
+  while (node && node !== ancestor) {
+    if (dom_position(node) !== 0) {
+      return false;
+    }
+
+    node = node.parentNode;
+  }
+
+  return true;
+}
+/**
+ * returns whether node is right edge of ancestor or not.
+ *
+ * @param {Node} node
+ * @param {Node} ancestor
+ * @return {Boolean}
+ */
+
+
+function isRightEdgeOf(node, ancestor) {
+  if (!ancestor) {
+    return false;
+  }
+
+  while (node && node !== ancestor) {
+    if (dom_position(node) !== nodeLength(node.parentNode) - 1) {
+      return false;
+    }
+
+    node = node.parentNode;
+  }
+
+  return true;
+}
+/**
+ * returns whether point is left edge of ancestor or not.
+ * @param {BoundaryPoint} point
+ * @param {Node} ancestor
+ * @return {Boolean}
+ */
+
+
+function isLeftEdgePointOf(point, ancestor) {
+  return isLeftEdgePoint(point) && dom_isLeftEdgeOf(point.node, ancestor);
+}
+/**
+ * returns whether point is right edge of ancestor or not.
+ * @param {BoundaryPoint} point
+ * @param {Node} ancestor
+ * @return {Boolean}
+ */
+
+
+function isRightEdgePointOf(point, ancestor) {
+  return isRightEdgePoint(point) && isRightEdgeOf(point.node, ancestor);
+}
+/**
+ * returns offset from parent.
+ *
+ * @param {Node} node
+ */
+
+
+function dom_position(node) {
+  var offset = 0;
+
+  while (node = node.previousSibling) {
+    offset += 1;
+  }
+
+  return offset;
+}
+
+function hasChildren(node) {
+  return !!(node && node.childNodes && node.childNodes.length);
+}
+/**
+ * returns previous boundaryPoint
+ *
+ * @param {BoundaryPoint} point
+ * @param {Boolean} isSkipInnerOffset
+ * @return {BoundaryPoint}
+ */
+
+
+function dom_prevPoint(point, isSkipInnerOffset) {
+  var node;
+  var offset;
+
+  if (point.offset === 0) {
+    if (isEditable(point.node)) {
+      return null;
+    }
+
+    node = point.node.parentNode;
+    offset = dom_position(point.node);
+  } else if (hasChildren(point.node)) {
+    node = point.node.childNodes[point.offset - 1];
+    offset = nodeLength(node);
+  } else {
+    node = point.node;
+    offset = isSkipInnerOffset ? 0 : point.offset - 1;
+  }
+
+  return {
+    node: node,
+    offset: offset
+  };
+}
+/**
+ * returns next boundaryPoint
+ *
+ * @param {BoundaryPoint} point
+ * @param {Boolean} isSkipInnerOffset
+ * @return {BoundaryPoint}
+ */
+
+
+function dom_nextPoint(point, isSkipInnerOffset) {
+  var node, offset;
+
+  if (nodeLength(point.node) === point.offset) {
+    if (isEditable(point.node)) {
+      return null;
+    }
+
+    var nextTextNode = getNextTextNode(point.node);
+
+    if (nextTextNode) {
+      node = nextTextNode;
+      offset = 0;
+    } else {
+      node = point.node.parentNode;
+      offset = dom_position(point.node) + 1;
+    }
+  } else if (hasChildren(point.node)) {
+    node = point.node.childNodes[point.offset];
+    offset = 0;
+  } else {
+    node = point.node;
+    offset = isSkipInnerOffset ? nodeLength(point.node) : point.offset + 1;
+  }
+
+  return {
+    node: node,
+    offset: offset
+  };
+}
+/**
+ * returns next boundaryPoint with empty node
+ *
+ * @param {BoundaryPoint} point
+ * @param {Boolean} isSkipInnerOffset
+ * @return {BoundaryPoint}
+ */
+
+
+function nextPointWithEmptyNode(point, isSkipInnerOffset) {
+  var node, offset; // if node is empty string node, return current node's sibling.
+
+  if (dom_isEmpty(point.node)) {
+    node = point.node.nextSibling;
+    offset = 0;
+    return {
+      node: node,
+      offset: offset
+    };
+  }
+
+  if (nodeLength(point.node) === point.offset) {
+    if (isEditable(point.node)) {
+      return null;
+    }
+
+    var nextTextNode = getNextTextNode(point.node);
+
+    if (nextTextNode) {
+      node = nextTextNode;
+      offset = 0;
+    } else {
+      node = point.node.parentNode;
+      offset = dom_position(point.node) + 1;
+    } // if next node is editable, return current node's sibling node.
+
+
+    if (isEditable(node)) {
+      node = point.node.nextSibling;
+      offset = 0;
+    }
+  } else if (hasChildren(point.node)) {
+    node = point.node.childNodes[point.offset];
+    offset = 0;
+
+    if (dom_isEmpty(node)) {
+      return null;
+    }
+  } else {
+    node = point.node;
+    offset = isSkipInnerOffset ? nodeLength(point.node) : point.offset + 1;
+
+    if (dom_isEmpty(node)) {
+      return null;
+    }
+  }
+
+  return {
+    node: node,
+    offset: offset
+  };
+}
+/*
+* returns the next Text node index or 0 if not found.
+*/
+
+
+function getNextTextNode(actual) {
+  if (!actual.nextSibling) return undefined;
+  if (actual.parent !== actual.nextSibling.parent) return undefined;
+  if (isText(actual.nextSibling)) return actual.nextSibling;
+  return getNextTextNode(actual.nextSibling);
+}
+/**
+ * returns whether pointA and pointB is same or not.
+ *
+ * @param {BoundaryPoint} pointA
+ * @param {BoundaryPoint} pointB
+ * @return {Boolean}
+ */
+
+
+function isSamePoint(pointA, pointB) {
+  return pointA.node === pointB.node && pointA.offset === pointB.offset;
+}
+/**
+ * returns whether point is visible (can set cursor) or not.
+ *
+ * @param {BoundaryPoint} point
+ * @return {Boolean}
+ */
+
+
+function isVisiblePoint(point) {
+  if (isText(point.node) || !hasChildren(point.node) || dom_isEmpty(point.node)) {
+    return true;
+  }
+
+  var leftNode = point.node.childNodes[point.offset - 1];
+  var rightNode = point.node.childNodes[point.offset];
+
+  if ((!leftNode || isVoid(leftNode)) && (!rightNode || isVoid(rightNode))) {
+    return true;
+  }
+
+  return false;
+}
+/**
+ * @method prevPointUtil
+ *
+ * @param {BoundaryPoint} point
+ * @param {Function} pred
+ * @return {BoundaryPoint}
+ */
+
+
+function prevPointUntil(point, pred) {
+  while (point) {
+    if (pred(point)) {
+      return point;
+    }
+
+    point = dom_prevPoint(point);
+  }
+
+  return null;
+}
+/**
+ * @method nextPointUntil
+ *
+ * @param {BoundaryPoint} point
+ * @param {Function} pred
+ * @return {BoundaryPoint}
+ */
+
+
+function nextPointUntil(point, pred) {
+  while (point) {
+    if (pred(point)) {
+      return point;
+    }
+
+    point = dom_nextPoint(point);
+  }
+
+  return null;
+}
+/**
+ * returns whether point has character or not.
+ *
+ * @param {Point} point
+ * @return {Boolean}
+ */
+
+
+function isCharPoint(point) {
+  if (!isText(point.node)) {
+    return false;
+  }
+
+  var ch = point.node.nodeValue.charAt(point.offset - 1);
+  return ch && ch !== ' ' && ch !== NBSP_CHAR;
+}
+/**
+ * returns whether point has space or not.
+ *
+ * @param {Point} point
+ * @return {Boolean}
+ */
+
+
+function isSpacePoint(point) {
+  if (!isText(point.node)) {
+    return false;
+  }
+
+  var ch = point.node.nodeValue.charAt(point.offset - 1);
+  return ch === ' ' || ch === NBSP_CHAR;
+}
+/**
+ * @method walkPoint
+ *
+ * @param {BoundaryPoint} startPoint
+ * @param {BoundaryPoint} endPoint
+ * @param {Function} handler
+ * @param {Boolean} isSkipInnerOffset
+ */
+
+
+function walkPoint(startPoint, endPoint, handler, isSkipInnerOffset) {
+  var point = startPoint;
+
+  while (point) {
+    handler(point);
+
+    if (isSamePoint(point, endPoint)) {
+      break;
+    }
+
+    var isSkipOffset = isSkipInnerOffset && startPoint.node !== point.node && endPoint.node !== point.node;
+    point = nextPointWithEmptyNode(point, isSkipOffset);
+  }
+}
+/**
+ * @method makeOffsetPath
+ *
+ * return offsetPath(array of offset) from ancestor
+ *
+ * @param {Node} ancestor - ancestor node
+ * @param {Node} node
+ */
+
+
+function makeOffsetPath(ancestor, node) {
+  var ancestors = listAncestor(node, func.eq(ancestor));
+  return ancestors.map(dom_position).reverse();
+}
+/**
+ * @method fromOffsetPath
+ *
+ * return element from offsetPath(array of offset)
+ *
+ * @param {Node} ancestor - ancestor node
+ * @param {array} offsets - offsetPath
+ */
+
+
+function fromOffsetPath(ancestor, offsets) {
+  var current = ancestor;
+
+  for (var i = 0, len = offsets.length; i < len; i++) {
+    if (current.childNodes.length <= offsets[i]) {
+      current = current.childNodes[current.childNodes.length - 1];
+    } else {
+      current = current.childNodes[offsets[i]];
+    }
+  }
+
+  return current;
+}
+/**
+ * @method splitNode
+ *
+ * split element or #text
+ *
+ * @param {BoundaryPoint} point
+ * @param {Object} [options]
+ * @param {Boolean} [options.isSkipPaddingBlankHTML] - default: false
+ * @param {Boolean} [options.isNotSplitEdgePoint] - default: false
+ * @param {Boolean} [options.isDiscardEmptySplits] - default: false
+ * @return {Node} right node of boundaryPoint
+ */
+
+
+function splitNode(point, options) {
+  var isSkipPaddingBlankHTML = options && options.isSkipPaddingBlankHTML;
+  var isNotSplitEdgePoint = options && options.isNotSplitEdgePoint;
+  var isDiscardEmptySplits = options && options.isDiscardEmptySplits;
+
+  if (isDiscardEmptySplits) {
+    isSkipPaddingBlankHTML = true;
+  } // edge case
+
+
+  if (isEdgePoint(point) && (isText(point.node) || isNotSplitEdgePoint)) {
+    if (isLeftEdgePoint(point)) {
+      return point.node;
+    } else if (isRightEdgePoint(point)) {
+      return point.node.nextSibling;
+    }
+  } // split #text
+
+
+  if (isText(point.node)) {
+    return point.node.splitText(point.offset);
+  } else {
+    var childNode = point.node.childNodes[point.offset];
+    var clone = insertAfter(point.node.cloneNode(false), point.node);
+    appendChildNodes(clone, listNext(childNode));
+
+    if (!isSkipPaddingBlankHTML) {
+      paddingBlankHTML(point.node);
+      paddingBlankHTML(clone);
+    }
+
+    if (isDiscardEmptySplits) {
+      if (dom_isEmpty(point.node)) {
+        remove(point.node);
+      }
+
+      if (dom_isEmpty(clone)) {
+        remove(clone);
+        return point.node.nextSibling;
+      }
+    }
+
+    return clone;
+  }
+}
+/**
+ * @method splitTree
+ *
+ * split tree by point
+ *
+ * @param {Node} root - split root
+ * @param {BoundaryPoint} point
+ * @param {Object} [options]
+ * @param {Boolean} [options.isSkipPaddingBlankHTML] - default: false
+ * @param {Boolean} [options.isNotSplitEdgePoint] - default: false
+ * @return {Node} right node of boundaryPoint
+ */
+
+
+function splitTree(root, point, options) {
+  // ex) [#text, <span>, <p>]
+  var ancestors = listAncestor(point.node, func.eq(root));
+
+  if (!ancestors.length) {
+    return null;
+  } else if (ancestors.length === 1) {
+    return splitNode(point, options);
+  }
+
+  return ancestors.reduce(function (node, parent) {
+    if (node === point.node) {
+      node = splitNode(point, options);
+    }
+
+    return splitNode({
+      node: parent,
+      offset: node ? dom_position(node) : nodeLength(parent)
+    }, options);
+  });
+}
+/**
+ * split point
+ *
+ * @param {Point} point
+ * @param {Boolean} isInline
+ * @return {Object}
+ */
+
+
+function splitPoint(point, isInline) {
+  // find splitRoot, container
+  //  - inline: splitRoot is a child of paragraph
+  //  - block: splitRoot is a child of bodyContainer
+  var pred = isInline ? isPara : isBodyContainer;
+  var ancestors = listAncestor(point.node, pred);
+  var topAncestor = lists.last(ancestors) || point.node;
+  var splitRoot, container;
+
+  if (pred(topAncestor)) {
+    splitRoot = ancestors[ancestors.length - 2];
+    container = topAncestor;
+  } else {
+    splitRoot = topAncestor;
+    container = splitRoot.parentNode;
+  } // if splitRoot is exists, split with splitTree
+
+
+  var pivot = splitRoot && splitTree(splitRoot, point, {
+    isSkipPaddingBlankHTML: isInline,
+    isNotSplitEdgePoint: isInline
+  }); // if container is point.node, find pivot with point.offset
+
+  if (!pivot && container === point.node) {
+    pivot = point.node.childNodes[point.offset];
+  }
+
+  return {
+    rightNode: pivot,
+    container: container
+  };
+}
+
+function dom_create(nodeName) {
+  return document.createElement(nodeName);
+}
+
+function createText(text) {
+  return document.createTextNode(text);
+}
+/**
+ * @method remove
+ *
+ * remove node, (isRemoveChild: remove child or not)
+ *
+ * @param {Node} node
+ * @param {Boolean} isRemoveChild
+ */
+
+
+function remove(node, isRemoveChild) {
+  if (!node || !node.parentNode) {
+    return;
+  }
+
+  if (node.removeNode) {
+    return node.removeNode(isRemoveChild);
+  }
+
+  var parent = node.parentNode;
+
+  if (!isRemoveChild) {
+    var nodes = [];
+
+    for (var i = 0, len = node.childNodes.length; i < len; i++) {
+      nodes.push(node.childNodes[i]);
+    }
+
+    for (var _i = 0, _len = nodes.length; _i < _len; _i++) {
+      parent.insertBefore(nodes[_i], node);
+    }
+  }
+
+  parent.removeChild(node);
+}
+/**
+ * @method removeWhile
+ *
+ * @param {Node} node
+ * @param {Function} pred
+ */
+
+
+function removeWhile(node, pred) {
+  while (node) {
+    if (isEditable(node) || !pred(node)) {
+      break;
+    }
+
+    var parent = node.parentNode;
+    remove(node);
+    node = parent;
+  }
+}
+/**
+ * @method replace
+ *
+ * replace node with provided nodeName
+ *
+ * @param {Node} node
+ * @param {String} nodeName
+ * @return {Node} - new node
+ */
+
+
+function dom_replace(node, nodeName) {
+  if (node.nodeName.toUpperCase() === nodeName.toUpperCase()) {
+    return node;
+  }
+
+  var newNode = dom_create(nodeName);
+
+  if (node.style.cssText) {
+    newNode.style.cssText = node.style.cssText;
+  }
+
+  appendChildNodes(newNode, lists.from(node.childNodes));
+  insertAfter(newNode, node);
+  remove(node);
+  return newNode;
+}
+
+var isTextarea = makePredByNodeName('TEXTAREA');
+/**
+ * @param {jQuery} $node
+ * @param {Boolean} [stripLinebreaks] - default: false
+ */
+
+function dom_value($node, stripLinebreaks) {
+  var val = isTextarea($node[0]) ? $node.val() : $node.html();
+
+  if (stripLinebreaks) {
+    return val.replace(/[\n\r]/g, '');
+  }
+
+  return val;
+}
+/**
+ * @method html
+ *
+ * get the HTML contents of node
+ *
+ * @param {jQuery} $node
+ * @param {Boolean} [isNewlineOnBlock]
+ */
+
+
+function dom_html($node, isNewlineOnBlock) {
+  var markup = dom_value($node);
+
+  if (isNewlineOnBlock) {
+    var regexTag = /<(\/?)(\b(?!!)[^>\s]*)(.*?)(\s*\/?>)/g;
+    markup = markup.replace(regexTag, function (match, endSlash, name) {
+      name = name.toUpperCase();
+      var isEndOfInlineContainer = /^DIV|^TD|^TH|^P|^LI|^H[1-7]/.test(name) && !!endSlash;
+      var isBlockNode = /^BLOCKQUOTE|^TABLE|^TBODY|^TR|^HR|^UL|^OL/.test(name);
+      return match + (isEndOfInlineContainer || isBlockNode ? '\n' : '');
+    });
+    markup = markup.trim();
+  }
+
+  return markup;
+}
+
+function posFromPlaceholder(placeholder) {
+  var $placeholder = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(placeholder);
+  var pos = $placeholder.offset();
+  var height = $placeholder.outerHeight(true); // include margin
+
+  return {
+    left: pos.left,
+    top: pos.top + height
+  };
+}
+
+function attachEvents($node, events) {
+  Object.keys(events).forEach(function (key) {
+    $node.on(key, events[key]);
+  });
+}
+
+function detachEvents($node, events) {
+  Object.keys(events).forEach(function (key) {
+    $node.off(key, events[key]);
+  });
+}
+/**
+ * @method isCustomStyleTag
+ *
+ * assert if a node contains a "note-styletag" class,
+ * which implies that's a custom-made style tag node
+ *
+ * @param {Node} an HTML DOM node
+ */
+
+
+function isCustomStyleTag(node) {
+  return node && !isText(node) && lists.contains(node.classList, 'note-styletag');
+}
+
+/* harmony default export */ var dom = ({
+  /** @property {String} NBSP_CHAR */
+  NBSP_CHAR: NBSP_CHAR,
+
+  /** @property {String} ZERO_WIDTH_NBSP_CHAR */
+  ZERO_WIDTH_NBSP_CHAR: ZERO_WIDTH_NBSP_CHAR,
+
+  /** @property {String} blank */
+  blank: blankHTML,
+
+  /** @property {String} emptyPara */
+  emptyPara: "<p>".concat(blankHTML, "</p>"),
+  makePredByNodeName: makePredByNodeName,
+  isEditable: isEditable,
+  isControlSizing: isControlSizing,
+  isText: isText,
+  isElement: isElement,
+  isVoid: isVoid,
+  isPara: isPara,
+  isPurePara: isPurePara,
+  isHeading: isHeading,
+  isInline: dom_isInline,
+  isBlock: func.not(dom_isInline),
+  isBodyInline: isBodyInline,
+  isBody: isBody,
+  isParaInline: isParaInline,
+  isPre: isPre,
+  isList: isList,
+  isTable: isTable,
+  isData: isData,
+  isCell: dom_isCell,
+  isBlockquote: isBlockquote,
+  isBodyContainer: isBodyContainer,
+  isAnchor: isAnchor,
+  isDiv: makePredByNodeName('DIV'),
+  isLi: isLi,
+  isBR: makePredByNodeName('BR'),
+  isSpan: makePredByNodeName('SPAN'),
+  isB: makePredByNodeName('B'),
+  isU: makePredByNodeName('U'),
+  isS: makePredByNodeName('S'),
+  isI: makePredByNodeName('I'),
+  isImg: makePredByNodeName('IMG'),
+  isTextarea: isTextarea,
+  deepestChildIsEmpty: deepestChildIsEmpty,
+  isEmpty: dom_isEmpty,
+  isEmptyAnchor: func.and(isAnchor, dom_isEmpty),
+  isClosestSibling: isClosestSibling,
+  withClosestSiblings: withClosestSiblings,
+  nodeLength: nodeLength,
+  isLeftEdgePoint: isLeftEdgePoint,
+  isRightEdgePoint: isRightEdgePoint,
+  isEdgePoint: isEdgePoint,
+  isLeftEdgeOf: dom_isLeftEdgeOf,
+  isRightEdgeOf: isRightEdgeOf,
+  isLeftEdgePointOf: isLeftEdgePointOf,
+  isRightEdgePointOf: isRightEdgePointOf,
+  prevPoint: dom_prevPoint,
+  nextPoint: dom_nextPoint,
+  nextPointWithEmptyNode: nextPointWithEmptyNode,
+  isSamePoint: isSamePoint,
+  isVisiblePoint: isVisiblePoint,
+  prevPointUntil: prevPointUntil,
+  nextPointUntil: nextPointUntil,
+  isCharPoint: isCharPoint,
+  isSpacePoint: isSpacePoint,
+  walkPoint: walkPoint,
+  ancestor: dom_ancestor,
+  singleChildAncestor: singleChildAncestor,
+  listAncestor: listAncestor,
+  lastAncestor: lastAncestor,
+  listNext: listNext,
+  listPrev: listPrev,
+  listDescendant: listDescendant,
+  commonAncestor: dom_commonAncestor,
+  wrap: wrap,
+  insertAfter: insertAfter,
+  appendChildNodes: appendChildNodes,
+  position: dom_position,
+  hasChildren: hasChildren,
+  makeOffsetPath: makeOffsetPath,
+  fromOffsetPath: fromOffsetPath,
+  splitTree: splitTree,
+  splitPoint: splitPoint,
+  create: dom_create,
+  createText: createText,
+  remove: remove,
+  removeWhile: removeWhile,
+  replace: dom_replace,
+  html: dom_html,
+  value: dom_value,
+  posFromPlaceholder: posFromPlaceholder,
+  attachEvents: attachEvents,
+  detachEvents: detachEvents,
+  isCustomStyleTag: isCustomStyleTag
+});
+// CONCATENATED MODULE: ./src/js/base/Context.js
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+
+
+
+
+
+var Context_Context = /*#__PURE__*/function () {
+  /**
+   * @param {jQuery} $note
+   * @param {Object} options
+   */
+  function Context($note, options) {
+    _classCallCheck(this, Context);
+
+    this.$note = $note;
+    this.memos = {};
+    this.modules = {};
+    this.layoutInfo = {};
+    this.options = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.extend(true, {}, options); // init ui with options
+
+    external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.summernote.ui = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.summernote.ui_template(this.options);
+    this.ui = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.summernote.ui;
+    this.initialize();
+  }
+  /**
+   * create layout and initialize modules and other resources
+   */
+
+
+  _createClass(Context, [{
+    key: "initialize",
+    value: function initialize() {
+      this.layoutInfo = this.ui.createLayout(this.$note);
+
+      this._initialize();
+
+      this.$note.hide();
+      return this;
+    }
+    /**
+     * destroy modules and other resources and remove layout
+     */
+
+  }, {
+    key: "destroy",
+    value: function destroy() {
+      this._destroy();
+
+      this.$note.removeData('summernote');
+      this.ui.removeLayout(this.$note, this.layoutInfo);
+    }
+    /**
+     * destory modules and other resources and initialize it again
+     */
+
+  }, {
+    key: "reset",
+    value: function reset() {
+      var disabled = this.isDisabled();
+      this.code(dom.emptyPara);
+
+      this._destroy();
+
+      this._initialize();
+
+      if (disabled) {
+        this.disable();
+      }
+    }
+  }, {
+    key: "_initialize",
+    value: function _initialize() {
+      var _this = this;
+
+      // set own id
+      this.options.id = func.uniqueId(external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.now()); // set default container for tooltips, popovers, and dialogs
+
+      this.options.container = this.options.container || this.layoutInfo.editor; // add optional buttons
+
+      var buttons = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.extend({}, this.options.buttons);
+      Object.keys(buttons).forEach(function (key) {
+        _this.memo('button.' + key, buttons[key]);
+      });
+      var modules = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.extend({}, this.options.modules, external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.summernote.plugins || {}); // add and initialize modules
+
+      Object.keys(modules).forEach(function (key) {
+        _this.module(key, modules[key], true);
+      });
+      Object.keys(this.modules).forEach(function (key) {
+        _this.initializeModule(key);
+      });
+    }
+  }, {
+    key: "_destroy",
+    value: function _destroy() {
+      var _this2 = this;
+
+      // destroy modules with reversed order
+      Object.keys(this.modules).reverse().forEach(function (key) {
+        _this2.removeModule(key);
+      });
+      Object.keys(this.memos).forEach(function (key) {
+        _this2.removeMemo(key);
+      }); // trigger custom onDestroy callback
+
+      this.triggerEvent('destroy', this);
+    }
+  }, {
+    key: "code",
+    value: function code(html) {
+      var isActivated = this.invoke('codeview.isActivated');
+
+      if (html === undefined) {
+        this.invoke('codeview.sync');
+        return isActivated ? this.layoutInfo.codable.val() : this.layoutInfo.editable.html();
+      } else {
+        if (isActivated) {
+          this.invoke('codeview.sync', html);
+        } else {
+          this.layoutInfo.editable.html(html);
+        }
+
+        this.$note.val(html);
+        this.triggerEvent('change', html, this.layoutInfo.editable);
+      }
+    }
+  }, {
+    key: "isDisabled",
+    value: function isDisabled() {
+      return this.layoutInfo.editable.attr('contenteditable') === 'false';
+    }
+  }, {
+    key: "enable",
+    value: function enable() {
+      this.layoutInfo.editable.attr('contenteditable', true);
+      this.invoke('toolbar.activate', true);
+      this.triggerEvent('disable', false);
+      this.options.editing = true;
+    }
+  }, {
+    key: "disable",
+    value: function disable() {
+      // close codeview if codeview is opend
+      if (this.invoke('codeview.isActivated')) {
+        this.invoke('codeview.deactivate');
+      }
+
+      this.layoutInfo.editable.attr('contenteditable', false);
+      this.options.editing = false;
+      this.invoke('toolbar.deactivate', true);
+      this.triggerEvent('disable', true);
+    }
+  }, {
+    key: "triggerEvent",
+    value: function triggerEvent() {
+      var namespace = lists.head(arguments);
+      var args = lists.tail(lists.from(arguments));
+      var callback = this.options.callbacks[func.namespaceToCamel(namespace, 'on')];
+
+      if (callback) {
+        callback.apply(this.$note[0], args);
+      }
+
+      this.$note.trigger('summernote.' + namespace, args);
+    }
+  }, {
+    key: "initializeModule",
+    value: function initializeModule(key) {
+      var module = this.modules[key];
+      module.shouldInitialize = module.shouldInitialize || func.ok;
+
+      if (!module.shouldInitialize()) {
+        return;
+      } // initialize module
+
+
+      if (module.initialize) {
+        module.initialize();
+      } // attach events
+
+
+      if (module.events) {
+        dom.attachEvents(this.$note, module.events);
+      }
+    }
+  }, {
+    key: "module",
+    value: function module(key, ModuleClass, withoutIntialize) {
+      if (arguments.length === 1) {
+        return this.modules[key];
+      }
+
+      this.modules[key] = new ModuleClass(this);
+
+      if (!withoutIntialize) {
+        this.initializeModule(key);
+      }
+    }
+  }, {
+    key: "removeModule",
+    value: function removeModule(key) {
+      var module = this.modules[key];
+
+      if (module.shouldInitialize()) {
+        if (module.events) {
+          dom.detachEvents(this.$note, module.events);
+        }
+
+        if (module.destroy) {
+          module.destroy();
+        }
+      }
+
+      delete this.modules[key];
+    }
+  }, {
+    key: "memo",
+    value: function memo(key, obj) {
+      if (arguments.length === 1) {
+        return this.memos[key];
+      }
+
+      this.memos[key] = obj;
+    }
+  }, {
+    key: "removeMemo",
+    value: function removeMemo(key) {
+      if (this.memos[key] && this.memos[key].destroy) {
+        this.memos[key].destroy();
+      }
+
+      delete this.memos[key];
+    }
+    /**
+     * Some buttons need to change their visual style immediately once they get pressed
+     */
+
+  }, {
+    key: "createInvokeHandlerAndUpdateState",
+    value: function createInvokeHandlerAndUpdateState(namespace, value) {
+      var _this3 = this;
+
+      return function (event) {
+        _this3.createInvokeHandler(namespace, value)(event);
+
+        _this3.invoke('buttons.updateCurrentStyle');
+      };
+    }
+  }, {
+    key: "createInvokeHandler",
+    value: function createInvokeHandler(namespace, value) {
+      var _this4 = this;
+
+      return function (event) {
+        event.preventDefault();
+        var $target = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(event.target);
+
+        _this4.invoke(namespace, value || $target.closest('[data-value]').data('value'), $target);
+      };
+    }
+  }, {
+    key: "invoke",
+    value: function invoke() {
+      var namespace = lists.head(arguments);
+      var args = lists.tail(lists.from(arguments));
+      var splits = namespace.split('.');
+      var hasSeparator = splits.length > 1;
+      var moduleName = hasSeparator && lists.head(splits);
+      var methodName = hasSeparator ? lists.last(splits) : lists.head(splits);
+      var module = this.modules[moduleName || 'editor'];
+
+      if (!moduleName && this[methodName]) {
+        return this[methodName].apply(this, args);
+      } else if (module && module[methodName] && module.shouldInitialize()) {
+        return module[methodName].apply(module, args);
+      }
+    }
+  }]);
+
+  return Context;
+}();
+
+
+// CONCATENATED MODULE: ./src/js/summernote.js
+
+
+
+
+external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.fn.extend({
+  /**
+   * Summernote API
+   *
+   * @param {Object|String}
+   * @return {this}
+   */
+  summernote: function summernote() {
+    var type = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.type(lists.head(arguments));
+    var isExternalAPICalled = type === 'string';
+    var hasInitOptions = type === 'object';
+    var options = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.extend({}, external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.summernote.options, hasInitOptions ? lists.head(arguments) : {}); // Update options
+
+    options.langInfo = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.extend(true, {}, external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.summernote.lang['en-US'], external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.summernote.lang[options.lang]);
+    options.icons = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.extend(true, {}, external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.summernote.options.icons, options.icons);
+    options.tooltip = options.tooltip === 'auto' ? !env.isSupportTouch : options.tooltip;
+    this.each(function (idx, note) {
+      var $note = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(note);
+
+      if (!$note.data('summernote')) {
+        var context = new Context_Context($note, options);
+        $note.data('summernote', context);
+        $note.data('summernote').triggerEvent('init', context.layoutInfo);
+      }
+    });
+    var $note = this.first();
+
+    if ($note.length) {
+      var context = $note.data('summernote');
+
+      if (isExternalAPICalled) {
+        return context.invoke.apply(context, lists.from(arguments));
+      } else if (options.focus) {
+        context.invoke('editor.focus');
+      }
+    }
+
+    return this;
+  }
+});
+// CONCATENATED MODULE: ./src/js/base/core/range.js
+function range_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function range_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function range_createClass(Constructor, protoProps, staticProps) { if (protoProps) range_defineProperties(Constructor.prototype, protoProps); if (staticProps) range_defineProperties(Constructor, staticProps); return Constructor; }
+
+
+
+
+
+
+/**
+ * return boundaryPoint from TextRange, inspired by Andy Na's HuskyRange.js
+ *
+ * @param {TextRange} textRange
+ * @param {Boolean} isStart
+ * @return {BoundaryPoint}
+ *
+ * @see http://msdn.microsoft.com/en-us/library/ie/ms535872(v=vs.85).aspx
+ */
+
+function textRangeToPoint(textRange, isStart) {
+  var container = textRange.parentElement();
+  var offset;
+  var tester = document.body.createTextRange();
+  var prevContainer;
+  var childNodes = lists.from(container.childNodes);
+
+  for (offset = 0; offset < childNodes.length; offset++) {
+    if (dom.isText(childNodes[offset])) {
+      continue;
+    }
+
+    tester.moveToElementText(childNodes[offset]);
+
+    if (tester.compareEndPoints('StartToStart', textRange) >= 0) {
+      break;
+    }
+
+    prevContainer = childNodes[offset];
+  }
+
+  if (offset !== 0 && dom.isText(childNodes[offset - 1])) {
+    var textRangeStart = document.body.createTextRange();
+    var curTextNode = null;
+    textRangeStart.moveToElementText(prevContainer || container);
+    textRangeStart.collapse(!prevContainer);
+    curTextNode = prevContainer ? prevContainer.nextSibling : container.firstChild;
+    var pointTester = textRange.duplicate();
+    pointTester.setEndPoint('StartToStart', textRangeStart);
+    var textCount = pointTester.text.replace(/[\r\n]/g, '').length;
+
+    while (textCount > curTextNode.nodeValue.length && curTextNode.nextSibling) {
+      textCount -= curTextNode.nodeValue.length;
+      curTextNode = curTextNode.nextSibling;
+    } // [workaround] enforce IE to re-reference curTextNode, hack
+
+
+    var dummy = curTextNode.nodeValue; // eslint-disable-line
+
+    if (isStart && curTextNode.nextSibling && dom.isText(curTextNode.nextSibling) && textCount === curTextNode.nodeValue.length) {
+      textCount -= curTextNode.nodeValue.length;
+      curTextNode = curTextNode.nextSibling;
+    }
+
+    container = curTextNode;
+    offset = textCount;
+  }
+
+  return {
+    cont: container,
+    offset: offset
+  };
+}
+/**
+ * return TextRange from boundary point (inspired by google closure-library)
+ * @param {BoundaryPoint} point
+ * @return {TextRange}
+ */
+
+
+function pointToTextRange(point) {
+  var textRangeInfo = function textRangeInfo(container, offset) {
+    var node, isCollapseToStart;
+
+    if (dom.isText(container)) {
+      var prevTextNodes = dom.listPrev(container, func.not(dom.isText));
+      var prevContainer = lists.last(prevTextNodes).previousSibling;
+      node = prevContainer || container.parentNode;
+      offset += lists.sum(lists.tail(prevTextNodes), dom.nodeLength);
+      isCollapseToStart = !prevContainer;
+    } else {
+      node = container.childNodes[offset] || container;
+
+      if (dom.isText(node)) {
+        return textRangeInfo(node, 0);
+      }
+
+      offset = 0;
+      isCollapseToStart = false;
+    }
+
+    return {
+      node: node,
+      collapseToStart: isCollapseToStart,
+      offset: offset
+    };
+  };
+
+  var textRange = document.body.createTextRange();
+  var info = textRangeInfo(point.node, point.offset);
+  textRange.moveToElementText(info.node);
+  textRange.collapse(info.collapseToStart);
+  textRange.moveStart('character', info.offset);
+  return textRange;
+}
+/**
+   * Wrapped Range
+   *
+   * @constructor
+   * @param {Node} sc - start container
+   * @param {Number} so - start offset
+   * @param {Node} ec - end container
+   * @param {Number} eo - end offset
+   */
+
+
+var range_WrappedRange = /*#__PURE__*/function () {
+  function WrappedRange(sc, so, ec, eo) {
+    range_classCallCheck(this, WrappedRange);
+
+    this.sc = sc;
+    this.so = so;
+    this.ec = ec;
+    this.eo = eo; // isOnEditable: judge whether range is on editable or not
+
+    this.isOnEditable = this.makeIsOn(dom.isEditable); // isOnList: judge whether range is on list node or not
+
+    this.isOnList = this.makeIsOn(dom.isList); // isOnAnchor: judge whether range is on anchor node or not
+
+    this.isOnAnchor = this.makeIsOn(dom.isAnchor); // isOnCell: judge whether range is on cell node or not
+
+    this.isOnCell = this.makeIsOn(dom.isCell); // isOnData: judge whether range is on data node or not
+
+    this.isOnData = this.makeIsOn(dom.isData);
+  } // nativeRange: get nativeRange from sc, so, ec, eo
+
+
+  range_createClass(WrappedRange, [{
+    key: "nativeRange",
+    value: function nativeRange() {
+      if (env.isW3CRangeSupport) {
+        var w3cRange = document.createRange();
+        w3cRange.setStart(this.sc, this.so);
+        w3cRange.setEnd(this.ec, this.eo);
+        return w3cRange;
+      } else {
+        var textRange = pointToTextRange({
+          node: this.sc,
+          offset: this.so
+        });
+        textRange.setEndPoint('EndToEnd', pointToTextRange({
+          node: this.ec,
+          offset: this.eo
+        }));
+        return textRange;
+      }
+    }
+  }, {
+    key: "getPoints",
+    value: function getPoints() {
+      return {
+        sc: this.sc,
+        so: this.so,
+        ec: this.ec,
+        eo: this.eo
+      };
+    }
+  }, {
+    key: "getStartPoint",
+    value: function getStartPoint() {
+      return {
+        node: this.sc,
+        offset: this.so
+      };
+    }
+  }, {
+    key: "getEndPoint",
+    value: function getEndPoint() {
+      return {
+        node: this.ec,
+        offset: this.eo
+      };
+    }
+    /**
+     * select update visible range
+     */
+
+  }, {
+    key: "select",
+    value: function select() {
+      var nativeRng = this.nativeRange();
+
+      if (env.isW3CRangeSupport) {
+        var selection = document.getSelection();
+
+        if (selection.rangeCount > 0) {
+          selection.removeAllRanges();
+        }
+
+        selection.addRange(nativeRng);
+      } else {
+        nativeRng.select();
+      }
+
+      return this;
+    }
+    /**
+     * Moves the scrollbar to start container(sc) of current range
+     *
+     * @return {WrappedRange}
+     */
+
+  }, {
+    key: "scrollIntoView",
+    value: function scrollIntoView(container) {
+      var height = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(container).height();
+
+      if (container.scrollTop + height < this.sc.offsetTop) {
+        container.scrollTop += Math.abs(container.scrollTop + height - this.sc.offsetTop);
+      }
+
+      return this;
+    }
+    /**
+     * @return {WrappedRange}
+     */
+
+  }, {
+    key: "normalize",
+    value: function normalize() {
+      /**
+       * @param {BoundaryPoint} point
+       * @param {Boolean} isLeftToRight - true: prefer to choose right node
+       *                                - false: prefer to choose left node
+       * @return {BoundaryPoint}
+       */
+      var getVisiblePoint = function getVisiblePoint(point, isLeftToRight) {
+        if (!point) {
+          return point;
+        } // Just use the given point [XXX:Adhoc]
+        //  - case 01. if the point is on the middle of the node
+        //  - case 02. if the point is on the right edge and prefer to choose left node
+        //  - case 03. if the point is on the left edge and prefer to choose right node
+        //  - case 04. if the point is on the right edge and prefer to choose right node but the node is void
+        //  - case 05. if the point is on the left edge and prefer to choose left node but the node is void
+        //  - case 06. if the point is on the block node and there is no children
+
+
+        if (dom.isVisiblePoint(point)) {
+          if (!dom.isEdgePoint(point) || dom.isRightEdgePoint(point) && !isLeftToRight || dom.isLeftEdgePoint(point) && isLeftToRight || dom.isRightEdgePoint(point) && isLeftToRight && dom.isVoid(point.node.nextSibling) || dom.isLeftEdgePoint(point) && !isLeftToRight && dom.isVoid(point.node.previousSibling) || dom.isBlock(point.node) && dom.isEmpty(point.node)) {
+            return point;
+          }
+        } // point on block's edge
+
+
+        var block = dom.ancestor(point.node, dom.isBlock);
+        var hasRightNode = false;
+
+        if (!hasRightNode) {
+          var prevPoint = dom.prevPoint(point) || {
+            node: null
+          };
+          hasRightNode = (dom.isLeftEdgePointOf(point, block) || dom.isVoid(prevPoint.node)) && !isLeftToRight;
+        }
+
+        var hasLeftNode = false;
+
+        if (!hasLeftNode) {
+          var _nextPoint = dom.nextPoint(point) || {
+            node: null
+          };
+
+          hasLeftNode = (dom.isRightEdgePointOf(point, block) || dom.isVoid(_nextPoint.node)) && isLeftToRight;
+        }
+
+        if (hasRightNode || hasLeftNode) {
+          // returns point already on visible point
+          if (dom.isVisiblePoint(point)) {
+            return point;
+          } // reverse direction
+
+
+          isLeftToRight = !isLeftToRight;
+        }
+
+        var nextPoint = isLeftToRight ? dom.nextPointUntil(dom.nextPoint(point), dom.isVisiblePoint) : dom.prevPointUntil(dom.prevPoint(point), dom.isVisiblePoint);
+        return nextPoint || point;
+      };
+
+      var endPoint = getVisiblePoint(this.getEndPoint(), false);
+      var startPoint = this.isCollapsed() ? endPoint : getVisiblePoint(this.getStartPoint(), true);
+      return new WrappedRange(startPoint.node, startPoint.offset, endPoint.node, endPoint.offset);
+    }
+    /**
+     * returns matched nodes on range
+     *
+     * @param {Function} [pred] - predicate function
+     * @param {Object} [options]
+     * @param {Boolean} [options.includeAncestor]
+     * @param {Boolean} [options.fullyContains]
+     * @return {Node[]}
+     */
+
+  }, {
+    key: "nodes",
+    value: function nodes(pred, options) {
+      pred = pred || func.ok;
+      var includeAncestor = options && options.includeAncestor;
+      var fullyContains = options && options.fullyContains; // TODO compare points and sort
+
+      var startPoint = this.getStartPoint();
+      var endPoint = this.getEndPoint();
+      var nodes = [];
+      var leftEdgeNodes = [];
+      dom.walkPoint(startPoint, endPoint, function (point) {
+        if (dom.isEditable(point.node)) {
+          return;
+        }
+
+        var node;
+
+        if (fullyContains) {
+          if (dom.isLeftEdgePoint(point)) {
+            leftEdgeNodes.push(point.node);
+          }
+
+          if (dom.isRightEdgePoint(point) && lists.contains(leftEdgeNodes, point.node)) {
+            node = point.node;
+          }
+        } else if (includeAncestor) {
+          node = dom.ancestor(point.node, pred);
+        } else {
+          node = point.node;
+        }
+
+        if (node && pred(node)) {
+          nodes.push(node);
+        }
+      }, true);
+      return lists.unique(nodes);
+    }
+    /**
+     * returns commonAncestor of range
+     * @return {Element} - commonAncestor
+     */
+
+  }, {
+    key: "commonAncestor",
+    value: function commonAncestor() {
+      return dom.commonAncestor(this.sc, this.ec);
+    }
+    /**
+     * returns expanded range by pred
+     *
+     * @param {Function} pred - predicate function
+     * @return {WrappedRange}
+     */
+
+  }, {
+    key: "expand",
+    value: function expand(pred) {
+      var startAncestor = dom.ancestor(this.sc, pred);
+      var endAncestor = dom.ancestor(this.ec, pred);
+
+      if (!startAncestor && !endAncestor) {
+        return new WrappedRange(this.sc, this.so, this.ec, this.eo);
+      }
+
+      var boundaryPoints = this.getPoints();
+
+      if (startAncestor) {
+        boundaryPoints.sc = startAncestor;
+        boundaryPoints.so = 0;
+      }
+
+      if (endAncestor) {
+        boundaryPoints.ec = endAncestor;
+        boundaryPoints.eo = dom.nodeLength(endAncestor);
+      }
+
+      return new WrappedRange(boundaryPoints.sc, boundaryPoints.so, boundaryPoints.ec, boundaryPoints.eo);
+    }
+    /**
+     * @param {Boolean} isCollapseToStart
+     * @return {WrappedRange}
+     */
+
+  }, {
+    key: "collapse",
+    value: function collapse(isCollapseToStart) {
+      if (isCollapseToStart) {
+        return new WrappedRange(this.sc, this.so, this.sc, this.so);
+      } else {
+        return new WrappedRange(this.ec, this.eo, this.ec, this.eo);
+      }
+    }
+    /**
+     * splitText on range
+     */
+
+  }, {
+    key: "splitText",
+    value: function splitText() {
+      var isSameContainer = this.sc === this.ec;
+      var boundaryPoints = this.getPoints();
+
+      if (dom.isText(this.ec) && !dom.isEdgePoint(this.getEndPoint())) {
+        this.ec.splitText(this.eo);
+      }
+
+      if (dom.isText(this.sc) && !dom.isEdgePoint(this.getStartPoint())) {
+        boundaryPoints.sc = this.sc.splitText(this.so);
+        boundaryPoints.so = 0;
+
+        if (isSameContainer) {
+          boundaryPoints.ec = boundaryPoints.sc;
+          boundaryPoints.eo = this.eo - this.so;
+        }
+      }
+
+      return new WrappedRange(boundaryPoints.sc, boundaryPoints.so, boundaryPoints.ec, boundaryPoints.eo);
+    }
+    /**
+     * delete contents on range
+     * @return {WrappedRange}
+     */
+
+  }, {
+    key: "deleteContents",
+    value: function deleteContents() {
+      if (this.isCollapsed()) {
+        return this;
+      }
+
+      var rng = this.splitText();
+      var nodes = rng.nodes(null, {
+        fullyContains: true
+      }); // find new cursor point
+
+      var point = dom.prevPointUntil(rng.getStartPoint(), function (point) {
+        return !lists.contains(nodes, point.node);
+      });
+      var emptyParents = [];
+      external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.each(nodes, function (idx, node) {
+        // find empty parents
+        var parent = node.parentNode;
+
+        if (point.node !== parent && dom.nodeLength(parent) === 1) {
+          emptyParents.push(parent);
+        }
+
+        dom.remove(node, false);
+      }); // remove empty parents
+
+      external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.each(emptyParents, function (idx, node) {
+        dom.remove(node, false);
+      });
+      return new WrappedRange(point.node, point.offset, point.node, point.offset).normalize();
+    }
+    /**
+     * makeIsOn: return isOn(pred) function
+     */
+
+  }, {
+    key: "makeIsOn",
+    value: function makeIsOn(pred) {
+      return function () {
+        var ancestor = dom.ancestor(this.sc, pred);
+        return !!ancestor && ancestor === dom.ancestor(this.ec, pred);
+      };
+    }
+    /**
+     * @param {Function} pred
+     * @return {Boolean}
+     */
+
+  }, {
+    key: "isLeftEdgeOf",
+    value: function isLeftEdgeOf(pred) {
+      if (!dom.isLeftEdgePoint(this.getStartPoint())) {
+        return false;
+      }
+
+      var node = dom.ancestor(this.sc, pred);
+      return node && dom.isLeftEdgeOf(this.sc, node);
+    }
+    /**
+     * returns whether range was collapsed or not
+     */
+
+  }, {
+    key: "isCollapsed",
+    value: function isCollapsed() {
+      return this.sc === this.ec && this.so === this.eo;
+    }
+    /**
+     * wrap inline nodes which children of body with paragraph
+     *
+     * @return {WrappedRange}
+     */
+
+  }, {
+    key: "wrapBodyInlineWithPara",
+    value: function wrapBodyInlineWithPara() {
+      if (dom.isBodyContainer(this.sc) && dom.isEmpty(this.sc)) {
+        this.sc.innerHTML = dom.emptyPara;
+        return new WrappedRange(this.sc.firstChild, 0, this.sc.firstChild, 0);
+      }
+      /**
+       * [workaround] firefox often create range on not visible point. so normalize here.
+       *  - firefox: |<p>text</p>|
+       *  - chrome: <p>|text|</p>
+       */
+
+
+      var rng = this.normalize();
+
+      if (dom.isParaInline(this.sc) || dom.isPara(this.sc)) {
+        return rng;
+      } // find inline top ancestor
+
+
+      var topAncestor;
+
+      if (dom.isInline(rng.sc)) {
+        var ancestors = dom.listAncestor(rng.sc, func.not(dom.isInline));
+        topAncestor = lists.last(ancestors);
+
+        if (!dom.isInline(topAncestor)) {
+          topAncestor = ancestors[ancestors.length - 2] || rng.sc.childNodes[rng.so];
+        }
+      } else {
+        topAncestor = rng.sc.childNodes[rng.so > 0 ? rng.so - 1 : 0];
+      }
+
+      if (topAncestor) {
+        // siblings not in paragraph
+        var inlineSiblings = dom.listPrev(topAncestor, dom.isParaInline).reverse();
+        inlineSiblings = inlineSiblings.concat(dom.listNext(topAncestor.nextSibling, dom.isParaInline)); // wrap with paragraph
+
+        if (inlineSiblings.length) {
+          var para = dom.wrap(lists.head(inlineSiblings), 'p');
+          dom.appendChildNodes(para, lists.tail(inlineSiblings));
+        }
+      }
+
+      return this.normalize();
+    }
+    /**
+     * insert node at current cursor
+     *
+     * @param {Node} node
+     * @return {Node}
+     */
+
+  }, {
+    key: "insertNode",
+    value: function insertNode(node) {
+      var rng = this;
+
+      if (dom.isText(node) || dom.isInline(node)) {
+        rng = this.wrapBodyInlineWithPara().deleteContents();
+      }
+
+      var info = dom.splitPoint(rng.getStartPoint(), dom.isInline(node));
+
+      if (info.rightNode) {
+        info.rightNode.parentNode.insertBefore(node, info.rightNode);
+
+        if (dom.isEmpty(info.rightNode) && dom.isPara(node)) {
+          info.rightNode.parentNode.removeChild(info.rightNode);
+        }
+      } else {
+        info.container.appendChild(node);
+      }
+
+      return node;
+    }
+    /**
+     * insert html at current cursor
+     */
+
+  }, {
+    key: "pasteHTML",
+    value: function pasteHTML(markup) {
+      markup = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.trim(markup);
+      var contentsContainer = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()('<div></div>').html(markup)[0];
+      var childNodes = lists.from(contentsContainer.childNodes); // const rng = this.wrapBodyInlineWithPara().deleteContents();
+
+      var rng = this;
+      var reversed = false;
+
+      if (rng.so >= 0) {
+        childNodes = childNodes.reverse();
+        reversed = true;
+      }
+
+      childNodes = childNodes.map(function (childNode) {
+        return rng.insertNode(childNode);
+      });
+
+      if (reversed) {
+        childNodes = childNodes.reverse();
+      }
+
+      return childNodes;
+    }
+    /**
+     * returns text in range
+     *
+     * @return {String}
+     */
+
+  }, {
+    key: "toString",
+    value: function toString() {
+      var nativeRng = this.nativeRange();
+      return env.isW3CRangeSupport ? nativeRng.toString() : nativeRng.text;
+    }
+    /**
+     * returns range for word before cursor
+     *
+     * @param {Boolean} [findAfter] - find after cursor, default: false
+     * @return {WrappedRange}
+     */
+
+  }, {
+    key: "getWordRange",
+    value: function getWordRange(findAfter) {
+      var endPoint = this.getEndPoint();
+
+      if (!dom.isCharPoint(endPoint)) {
+        return this;
+      }
+
+      var startPoint = dom.prevPointUntil(endPoint, function (point) {
+        return !dom.isCharPoint(point);
+      });
+
+      if (findAfter) {
+        endPoint = dom.nextPointUntil(endPoint, function (point) {
+          return !dom.isCharPoint(point);
+        });
+      }
+
+      return new WrappedRange(startPoint.node, startPoint.offset, endPoint.node, endPoint.offset);
+    }
+    /**
+     * returns range for words before cursor
+     *
+     * @param {Boolean} [findAfter] - find after cursor, default: false
+     * @return {WrappedRange}
+     */
+
+  }, {
+    key: "getWordsRange",
+    value: function getWordsRange(findAfter) {
+      var endPoint = this.getEndPoint();
+
+      var isNotTextPoint = function isNotTextPoint(point) {
+        return !dom.isCharPoint(point) && !dom.isSpacePoint(point);
+      };
+
+      if (isNotTextPoint(endPoint)) {
+        return this;
+      }
+
+      var startPoint = dom.prevPointUntil(endPoint, isNotTextPoint);
+
+      if (findAfter) {
+        endPoint = dom.nextPointUntil(endPoint, isNotTextPoint);
+      }
+
+      return new WrappedRange(startPoint.node, startPoint.offset, endPoint.node, endPoint.offset);
+    }
+    /**
+     * returns range for words before cursor that match with a Regex
+     *
+     * example:
+     *  range: 'hi @Peter Pan'
+     *  regex: '/@[a-z ]+/i'
+     *  return range: '@Peter Pan'
+     *
+     * @param {RegExp} [regex]
+     * @return {WrappedRange|null}
+     */
+
+  }, {
+    key: "getWordsMatchRange",
+    value: function getWordsMatchRange(regex) {
+      var endPoint = this.getEndPoint();
+      var startPoint = dom.prevPointUntil(endPoint, function (point) {
+        if (!dom.isCharPoint(point) && !dom.isSpacePoint(point)) {
+          return true;
+        }
+
+        var rng = new WrappedRange(point.node, point.offset, endPoint.node, endPoint.offset);
+        var result = regex.exec(rng.toString());
+        return result && result.index === 0;
+      });
+      var rng = new WrappedRange(startPoint.node, startPoint.offset, endPoint.node, endPoint.offset);
+      var text = rng.toString();
+      var result = regex.exec(text);
+
+      if (result && result[0].length === text.length) {
+        return rng;
+      } else {
+        return null;
+      }
+    }
+    /**
+     * create offsetPath bookmark
+     *
+     * @param {Node} editable
+     */
+
+  }, {
+    key: "bookmark",
+    value: function bookmark(editable) {
+      return {
+        s: {
+          path: dom.makeOffsetPath(editable, this.sc),
+          offset: this.so
+        },
+        e: {
+          path: dom.makeOffsetPath(editable, this.ec),
+          offset: this.eo
+        }
+      };
+    }
+    /**
+     * create offsetPath bookmark base on paragraph
+     *
+     * @param {Node[]} paras
+     */
+
+  }, {
+    key: "paraBookmark",
+    value: function paraBookmark(paras) {
+      return {
+        s: {
+          path: lists.tail(dom.makeOffsetPath(lists.head(paras), this.sc)),
+          offset: this.so
+        },
+        e: {
+          path: lists.tail(dom.makeOffsetPath(lists.last(paras), this.ec)),
+          offset: this.eo
+        }
+      };
+    }
+    /**
+     * getClientRects
+     * @return {Rect[]}
+     */
+
+  }, {
+    key: "getClientRects",
+    value: function getClientRects() {
+      var nativeRng = this.nativeRange();
+      return nativeRng.getClientRects();
+    }
+  }]);
+
+  return WrappedRange;
+}();
+/**
+ * Data structure
+ *  * BoundaryPoint: a point of dom tree
+ *  * BoundaryPoints: two boundaryPoints corresponding to the start and the end of the Range
+ *
+ * See to http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Position
+ */
+
+
+/* harmony default export */ var range = ({
+  /**
+   * create Range Object From arguments or Browser Selection
+   *
+   * @param {Node} sc - start container
+   * @param {Number} so - start offset
+   * @param {Node} ec - end container
+   * @param {Number} eo - end offset
+   * @return {WrappedRange}
+   */
+  create: function create(sc, so, ec, eo) {
+    if (arguments.length === 4) {
+      return new range_WrappedRange(sc, so, ec, eo);
+    } else if (arguments.length === 2) {
+      // collapsed
+      ec = sc;
+      eo = so;
+      return new range_WrappedRange(sc, so, ec, eo);
+    } else {
+      var wrappedRange = this.createFromSelection();
+
+      if (!wrappedRange && arguments.length === 1) {
+        var bodyElement = arguments[0];
+
+        if (dom.isEditable(bodyElement)) {
+          bodyElement = bodyElement.lastChild;
+        }
+
+        return this.createFromBodyElement(bodyElement, dom.emptyPara === arguments[0].innerHTML);
+      }
+
+      return wrappedRange;
+    }
+  },
+  createFromBodyElement: function createFromBodyElement(bodyElement) {
+    var isCollapseToStart = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
+    var wrappedRange = this.createFromNode(bodyElement);
+    return wrappedRange.collapse(isCollapseToStart);
+  },
+  createFromSelection: function createFromSelection() {
+    var sc, so, ec, eo;
+
+    if (env.isW3CRangeSupport) {
+      var selection = document.getSelection();
+
+      if (!selection || selection.rangeCount === 0) {
+        return null;
+      } else if (dom.isBody(selection.anchorNode)) {
+        // Firefox: returns entire body as range on initialization.
+        // We won't never need it.
+        return null;
+      }
+
+      var nativeRng = selection.getRangeAt(0);
+      sc = nativeRng.startContainer;
+      so = nativeRng.startOffset;
+      ec = nativeRng.endContainer;
+      eo = nativeRng.endOffset;
+    } else {
+      // IE8: TextRange
+      var textRange = document.selection.createRange();
+      var textRangeEnd = textRange.duplicate();
+      textRangeEnd.collapse(false);
+      var textRangeStart = textRange;
+      textRangeStart.collapse(true);
+      var startPoint = textRangeToPoint(textRangeStart, true);
+      var endPoint = textRangeToPoint(textRangeEnd, false); // same visible point case: range was collapsed.
+
+      if (dom.isText(startPoint.node) && dom.isLeftEdgePoint(startPoint) && dom.isTextNode(endPoint.node) && dom.isRightEdgePoint(endPoint) && endPoint.node.nextSibling === startPoint.node) {
+        startPoint = endPoint;
+      }
+
+      sc = startPoint.cont;
+      so = startPoint.offset;
+      ec = endPoint.cont;
+      eo = endPoint.offset;
+    }
+
+    return new range_WrappedRange(sc, so, ec, eo);
+  },
+
+  /**
+   * @method
+   *
+   * create WrappedRange from node
+   *
+   * @param {Node} node
+   * @return {WrappedRange}
+   */
+  createFromNode: function createFromNode(node) {
+    var sc = node;
+    var so = 0;
+    var ec = node;
+    var eo = dom.nodeLength(ec); // browsers can't target a picture or void node
+
+    if (dom.isVoid(sc)) {
+      so = dom.listPrev(sc).length - 1;
+      sc = sc.parentNode;
+    }
+
+    if (dom.isBR(ec)) {
+      eo = dom.listPrev(ec).length - 1;
+      ec = ec.parentNode;
+    } else if (dom.isVoid(ec)) {
+      eo = dom.listPrev(ec).length;
+      ec = ec.parentNode;
+    }
+
+    return this.create(sc, so, ec, eo);
+  },
+
+  /**
+   * create WrappedRange from node after position
+   *
+   * @param {Node} node
+   * @return {WrappedRange}
+   */
+  createFromNodeBefore: function createFromNodeBefore(node) {
+    return this.createFromNode(node).collapse(true);
+  },
+
+  /**
+   * create WrappedRange from node after position
+   *
+   * @param {Node} node
+   * @return {WrappedRange}
+   */
+  createFromNodeAfter: function createFromNodeAfter(node) {
+    return this.createFromNode(node).collapse();
+  },
+
+  /**
+   * @method
+   *
+   * create WrappedRange from bookmark
+   *
+   * @param {Node} editable
+   * @param {Object} bookmark
+   * @return {WrappedRange}
+   */
+  createFromBookmark: function createFromBookmark(editable, bookmark) {
+    var sc = dom.fromOffsetPath(editable, bookmark.s.path);
+    var so = bookmark.s.offset;
+    var ec = dom.fromOffsetPath(editable, bookmark.e.path);
+    var eo = bookmark.e.offset;
+    return new range_WrappedRange(sc, so, ec, eo);
+  },
+
+  /**
+   * @method
+   *
+   * create WrappedRange from paraBookmark
+   *
+   * @param {Object} bookmark
+   * @param {Node[]} paras
+   * @return {WrappedRange}
+   */
+  createFromParaBookmark: function createFromParaBookmark(bookmark, paras) {
+    var so = bookmark.s.offset;
+    var eo = bookmark.e.offset;
+    var sc = dom.fromOffsetPath(lists.head(paras), bookmark.s.path);
+    var ec = dom.fromOffsetPath(lists.last(paras), bookmark.e.path);
+    return new range_WrappedRange(sc, so, ec, eo);
+  }
+});
+// CONCATENATED MODULE: ./src/js/base/core/key.js
+
+
+var KEY_MAP = {
+  'BACKSPACE': 8,
+  'TAB': 9,
+  'ENTER': 13,
+  'ESCAPE': 27,
+  'SPACE': 32,
+  'DELETE': 46,
+  // Arrow
+  'LEFT': 37,
+  'UP': 38,
+  'RIGHT': 39,
+  'DOWN': 40,
+  // Number: 0-9
+  'NUM0': 48,
+  'NUM1': 49,
+  'NUM2': 50,
+  'NUM3': 51,
+  'NUM4': 52,
+  'NUM5': 53,
+  'NUM6': 54,
+  'NUM7': 55,
+  'NUM8': 56,
+  // Alphabet: a-z
+  'B': 66,
+  'E': 69,
+  'I': 73,
+  'J': 74,
+  'K': 75,
+  'L': 76,
+  'R': 82,
+  'S': 83,
+  'U': 85,
+  'V': 86,
+  'Y': 89,
+  'Z': 90,
+  'SLASH': 191,
+  'LEFTBRACKET': 219,
+  'BACKSLASH': 220,
+  'RIGHTBRACKET': 221,
+  // Navigation
+  'HOME': 36,
+  'END': 35,
+  'PAGEUP': 33,
+  'PAGEDOWN': 34
+};
+/**
+ * @class core.key
+ *
+ * Object for keycodes.
+ *
+ * @singleton
+ * @alternateClassName key
+ */
+
+/* harmony default export */ var core_key = ({
+  /**
+   * @method isEdit
+   *
+   * @param {Number} keyCode
+   * @return {Boolean}
+   */
+  isEdit: function isEdit(keyCode) {
+    return lists.contains([KEY_MAP.BACKSPACE, KEY_MAP.TAB, KEY_MAP.ENTER, KEY_MAP.SPACE, KEY_MAP.DELETE], keyCode);
+  },
+
+  /**
+   * @method isMove
+   *
+   * @param {Number} keyCode
+   * @return {Boolean}
+   */
+  isMove: function isMove(keyCode) {
+    return lists.contains([KEY_MAP.LEFT, KEY_MAP.UP, KEY_MAP.RIGHT, KEY_MAP.DOWN], keyCode);
+  },
+
+  /**
+   * @method isNavigation
+   *
+   * @param {Number} keyCode
+   * @return {Boolean}
+   */
+  isNavigation: function isNavigation(keyCode) {
+    return lists.contains([KEY_MAP.HOME, KEY_MAP.END, KEY_MAP.PAGEUP, KEY_MAP.PAGEDOWN], keyCode);
+  },
+
+  /**
+   * @property {Object} nameFromCode
+   * @property {String} nameFromCode.8 "BACKSPACE"
+   */
+  nameFromCode: func.invertObject(KEY_MAP),
+  code: KEY_MAP
+});
+// CONCATENATED MODULE: ./src/js/base/core/async.js
+
+/**
+ * @method readFileAsDataURL
+ *
+ * read contents of file as representing URL
+ *
+ * @param {File} file
+ * @return {Promise} - then: dataUrl
+ */
+
+function readFileAsDataURL(file) {
+  return external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.Deferred(function (deferred) {
+    external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.extend(new FileReader(), {
+      onload: function onload(e) {
+        var dataURL = e.target.result;
+        deferred.resolve(dataURL);
+      },
+      onerror: function onerror(err) {
+        deferred.reject(err);
+      }
+    }).readAsDataURL(file);
+  }).promise();
+}
+/**
+ * @method createImage
+ *
+ * create `<image>` from url string
+ *
+ * @param {String} url
+ * @return {Promise} - then: $image
+ */
+
+function createImage(url) {
+  return external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.Deferred(function (deferred) {
+    var $img = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()('<img>');
+    $img.one('load', function () {
+      $img.off('error abort');
+      deferred.resolve($img);
+    }).one('error abort', function () {
+      $img.off('load').detach();
+      deferred.reject($img);
+    }).css({
+      display: 'none'
+    }).appendTo(document.body).attr('src', url);
+  }).promise();
+}
+// CONCATENATED MODULE: ./src/js/base/editing/History.js
+function History_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function History_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function History_createClass(Constructor, protoProps, staticProps) { if (protoProps) History_defineProperties(Constructor.prototype, protoProps); if (staticProps) History_defineProperties(Constructor, staticProps); return Constructor; }
+
+
+
+var History_History = /*#__PURE__*/function () {
+  function History(context) {
+    History_classCallCheck(this, History);
+
+    this.stack = [];
+    this.stackOffset = -1;
+    this.context = context;
+    this.$editable = context.layoutInfo.editable;
+    this.editable = this.$editable[0];
+  }
+
+  History_createClass(History, [{
+    key: "makeSnapshot",
+    value: function makeSnapshot() {
+      var rng = range.create(this.editable);
+      var emptyBookmark = {
+        s: {
+          path: [],
+          offset: 0
+        },
+        e: {
+          path: [],
+          offset: 0
+        }
+      };
+      return {
+        contents: this.$editable.html(),
+        bookmark: rng && rng.isOnEditable() ? rng.bookmark(this.editable) : emptyBookmark
+      };
+    }
+  }, {
+    key: "applySnapshot",
+    value: function applySnapshot(snapshot) {
+      if (snapshot.contents !== null) {
+        this.$editable.html(snapshot.contents);
+      }
+
+      if (snapshot.bookmark !== null) {
+        range.createFromBookmark(this.editable, snapshot.bookmark).select();
+      }
+    }
+    /**
+    * @method rewind
+    * Rewinds the history stack back to the first snapshot taken.
+    * Leaves the stack intact, so that "Redo" can still be used.
+    */
+
+  }, {
+    key: "rewind",
+    value: function rewind() {
+      // Create snap shot if not yet recorded
+      if (this.$editable.html() !== this.stack[this.stackOffset].contents) {
+        this.recordUndo();
+      } // Return to the first available snapshot.
+
+
+      this.stackOffset = 0; // Apply that snapshot.
+
+      this.applySnapshot(this.stack[this.stackOffset]);
+    }
+    /**
+    *  @method commit
+    *  Resets history stack, but keeps current editor's content.
+    */
+
+  }, {
+    key: "commit",
+    value: function commit() {
+      // Clear the stack.
+      this.stack = []; // Restore stackOffset to its original value.
+
+      this.stackOffset = -1; // Record our first snapshot (of nothing).
+
+      this.recordUndo();
+    }
+    /**
+    * @method reset
+    * Resets the history stack completely; reverting to an empty editor.
+    */
+
+  }, {
+    key: "reset",
+    value: function reset() {
+      // Clear the stack.
+      this.stack = []; // Restore stackOffset to its original value.
+
+      this.stackOffset = -1; // Clear the editable area.
+
+      this.$editable.html(''); // Record our first snapshot (of nothing).
+
+      this.recordUndo();
+    }
+    /**
+     * undo
+     */
+
+  }, {
+    key: "undo",
+    value: function undo() {
+      // Create snap shot if not yet recorded
+      if (this.$editable.html() !== this.stack[this.stackOffset].contents) {
+        this.recordUndo();
+      }
+
+      if (this.stackOffset > 0) {
+        this.stackOffset--;
+        this.applySnapshot(this.stack[this.stackOffset]);
+      }
+    }
+    /**
+     * redo
+     */
+
+  }, {
+    key: "redo",
+    value: function redo() {
+      if (this.stack.length - 1 > this.stackOffset) {
+        this.stackOffset++;
+        this.applySnapshot(this.stack[this.stackOffset]);
+      }
+    }
+    /**
+     * recorded undo
+     */
+
+  }, {
+    key: "recordUndo",
+    value: function recordUndo() {
+      this.stackOffset++; // Wash out stack after stackOffset
+
+      if (this.stack.length > this.stackOffset) {
+        this.stack = this.stack.slice(0, this.stackOffset);
+      } // Create new snapshot and push it to the end
+
+
+      this.stack.push(this.makeSnapshot()); // If the stack size reachs to the limit, then slice it
+
+      if (this.stack.length > this.context.options.historyLimit) {
+        this.stack.shift();
+        this.stackOffset -= 1;
+      }
+    }
+  }]);
+
+  return History;
+}();
+
+
+// CONCATENATED MODULE: ./src/js/base/editing/Style.js
+function Style_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function Style_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function Style_createClass(Constructor, protoProps, staticProps) { if (protoProps) Style_defineProperties(Constructor.prototype, protoProps); if (staticProps) Style_defineProperties(Constructor, staticProps); return Constructor; }
+
+
+
+
+
+
+
+var Style_Style = /*#__PURE__*/function () {
+  function Style() {
+    Style_classCallCheck(this, Style);
+  }
+
+  Style_createClass(Style, [{
+    key: "jQueryCSS",
+
+    /**
+     * @method jQueryCSS
+     *
+     * [workaround] for old jQuery
+     * passing an array of style properties to .css()
+     * will result in an object of property-value pairs.
+     * (compability with version < 1.9)
+     *
+     * @private
+     * @param  {jQuery} $obj
+     * @param  {Array} propertyNames - An array of one or more CSS properties.
+     * @return {Object}
+     */
+    value: function jQueryCSS($obj, propertyNames) {
+      if (env.jqueryVersion < 1.9) {
+        var result = {};
+        external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.each(propertyNames, function (idx, propertyName) {
+          result[propertyName] = $obj.css(propertyName);
+        });
+        return result;
+      }
+
+      return $obj.css(propertyNames);
+    }
+    /**
+     * returns style object from node
+     *
+     * @param {jQuery} $node
+     * @return {Object}
+     */
+
+  }, {
+    key: "fromNode",
+    value: function fromNode($node) {
+      var properties = ['font-family', 'font-size', 'text-align', 'list-style-type', 'line-height'];
+      var styleInfo = this.jQueryCSS($node, properties) || {};
+      var fontSize = $node[0].style.fontSize || styleInfo['font-size'];
+      styleInfo['font-size'] = parseInt(fontSize, 10);
+      styleInfo['font-size-unit'] = fontSize.match(/[a-z%]+$/);
+      return styleInfo;
+    }
+    /**
+     * paragraph level style
+     *
+     * @param {WrappedRange} rng
+     * @param {Object} styleInfo
+     */
+
+  }, {
+    key: "stylePara",
+    value: function stylePara(rng, styleInfo) {
+      external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.each(rng.nodes(dom.isPara, {
+        includeAncestor: true
+      }), function (idx, para) {
+        external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(para).css(styleInfo);
+      });
+    }
+    /**
+     * insert and returns styleNodes on range.
+     *
+     * @param {WrappedRange} rng
+     * @param {Object} [options] - options for styleNodes
+     * @param {String} [options.nodeName] - default: `SPAN`
+     * @param {Boolean} [options.expandClosestSibling] - default: `false`
+     * @param {Boolean} [options.onlyPartialContains] - default: `false`
+     * @return {Node[]}
+     */
+
+  }, {
+    key: "styleNodes",
+    value: function styleNodes(rng, options) {
+      rng = rng.splitText();
+      var nodeName = options && options.nodeName || 'SPAN';
+      var expandClosestSibling = !!(options && options.expandClosestSibling);
+      var onlyPartialContains = !!(options && options.onlyPartialContains);
+
+      if (rng.isCollapsed()) {
+        return [rng.insertNode(dom.create(nodeName))];
+      }
+
+      var pred = dom.makePredByNodeName(nodeName);
+      var nodes = rng.nodes(dom.isText, {
+        fullyContains: true
+      }).map(function (text) {
+        return dom.singleChildAncestor(text, pred) || dom.wrap(text, nodeName);
+      });
+
+      if (expandClosestSibling) {
+        if (onlyPartialContains) {
+          var nodesInRange = rng.nodes(); // compose with partial contains predication
+
+          pred = func.and(pred, function (node) {
+            return lists.contains(nodesInRange, node);
+          });
+        }
+
+        return nodes.map(function (node) {
+          var siblings = dom.withClosestSiblings(node, pred);
+          var head = lists.head(siblings);
+          var tails = lists.tail(siblings);
+          external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.each(tails, function (idx, elem) {
+            dom.appendChildNodes(head, elem.childNodes);
+            dom.remove(elem);
+          });
+          return lists.head(siblings);
+        });
+      } else {
+        return nodes;
+      }
+    }
+    /**
+     * get current style on cursor
+     *
+     * @param {WrappedRange} rng
+     * @return {Object} - object contains style properties.
+     */
+
+  }, {
+    key: "current",
+    value: function current(rng) {
+      var $cont = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(!dom.isElement(rng.sc) ? rng.sc.parentNode : rng.sc);
+      var styleInfo = this.fromNode($cont); // document.queryCommandState for toggle state
+      // [workaround] prevent Firefox nsresult: "0x80004005 (NS_ERROR_FAILURE)"
+
+      try {
+        styleInfo = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.extend(styleInfo, {
+          'font-bold': document.queryCommandState('bold') ? 'bold' : 'normal',
+          'font-italic': document.queryCommandState('italic') ? 'italic' : 'normal',
+          'font-underline': document.queryCommandState('underline') ? 'underline' : 'normal',
+          'font-subscript': document.queryCommandState('subscript') ? 'subscript' : 'normal',
+          'font-superscript': document.queryCommandState('superscript') ? 'superscript' : 'normal',
+          'font-strikethrough': document.queryCommandState('strikethrough') ? 'strikethrough' : 'normal',
+          'font-family': document.queryCommandValue('fontname') || styleInfo['font-family']
+        });
+      } catch (e) {} // eslint-disable-next-line
+      // list-style-type to list-style(unordered, ordered)
+
+
+      if (!rng.isOnList()) {
+        styleInfo['list-style'] = 'none';
+      } else {
+        var orderedTypes = ['circle', 'disc', 'disc-leading-zero', 'square'];
+        var isUnordered = orderedTypes.indexOf(styleInfo['list-style-type']) > -1;
+        styleInfo['list-style'] = isUnordered ? 'unordered' : 'ordered';
+      }
+
+      var para = dom.ancestor(rng.sc, dom.isPara);
+
+      if (para && para.style['line-height']) {
+        styleInfo['line-height'] = para.style.lineHeight;
+      } else {
+        var lineHeight = parseInt(styleInfo['line-height'], 10) / parseInt(styleInfo['font-size'], 10);
+        styleInfo['line-height'] = lineHeight.toFixed(1);
+      }
+
+      styleInfo.anchor = rng.isOnAnchor() && dom.ancestor(rng.sc, dom.isAnchor);
+      styleInfo.ancestors = dom.listAncestor(rng.sc, dom.isEditable);
+      styleInfo.range = rng;
+      return styleInfo;
+    }
+  }]);
+
+  return Style;
+}();
+
+
+// CONCATENATED MODULE: ./src/js/base/editing/Bullet.js
+function Bullet_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function Bullet_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function Bullet_createClass(Constructor, protoProps, staticProps) { if (protoProps) Bullet_defineProperties(Constructor.prototype, protoProps); if (staticProps) Bullet_defineProperties(Constructor, staticProps); return Constructor; }
+
+
+
+
+
+
+
+var Bullet_Bullet = /*#__PURE__*/function () {
+  function Bullet() {
+    Bullet_classCallCheck(this, Bullet);
+  }
+
+  Bullet_createClass(Bullet, [{
+    key: "insertOrderedList",
+
+    /**
+     * toggle ordered list
+     */
+    value: function insertOrderedList(editable) {
+      this.toggleList('OL', editable);
+    }
+    /**
+     * toggle unordered list
+     */
+
+  }, {
+    key: "insertUnorderedList",
+    value: function insertUnorderedList(editable) {
+      this.toggleList('UL', editable);
+    }
+    /**
+     * indent
+     */
+
+  }, {
+    key: "indent",
+    value: function indent(editable) {
+      var _this = this;
+
+      var rng = range.create(editable).wrapBodyInlineWithPara();
+      var paras = rng.nodes(dom.isPara, {
+        includeAncestor: true
+      });
+      var clustereds = lists.clusterBy(paras, func.peq2('parentNode'));
+      external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.each(clustereds, function (idx, paras) {
+        var head = lists.head(paras);
+
+        if (dom.isLi(head)) {
+          var previousList = _this.findList(head.previousSibling);
+
+          if (previousList) {
+            paras.map(function (para) {
+              return previousList.appendChild(para);
+            });
+          } else {
+            _this.wrapList(paras, head.parentNode.nodeName);
+
+            paras.map(function (para) {
+              return para.parentNode;
+            }).map(function (para) {
+              return _this.appendToPrevious(para);
+            });
+          }
+        } else {
+          external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.each(paras, function (idx, para) {
+            external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(para).css('marginLeft', function (idx, val) {
+              return (parseInt(val, 10) || 0) + 25;
+            });
+          });
+        }
+      });
+      rng.select();
+    }
+    /**
+     * outdent
+     */
+
+  }, {
+    key: "outdent",
+    value: function outdent(editable) {
+      var _this2 = this;
+
+      var rng = range.create(editable).wrapBodyInlineWithPara();
+      var paras = rng.nodes(dom.isPara, {
+        includeAncestor: true
+      });
+      var clustereds = lists.clusterBy(paras, func.peq2('parentNode'));
+      external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.each(clustereds, function (idx, paras) {
+        var head = lists.head(paras);
+
+        if (dom.isLi(head)) {
+          _this2.releaseList([paras]);
+        } else {
+          external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.each(paras, function (idx, para) {
+            external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(para).css('marginLeft', function (idx, val) {
+              val = parseInt(val, 10) || 0;
+              return val > 25 ? val - 25 : '';
+            });
+          });
+        }
+      });
+      rng.select();
+    }
+    /**
+     * toggle list
+     *
+     * @param {String} listName - OL or UL
+     */
+
+  }, {
+    key: "toggleList",
+    value: function toggleList(listName, editable) {
+      var _this3 = this;
+
+      var rng = range.create(editable).wrapBodyInlineWithPara();
+      var paras = rng.nodes(dom.isPara, {
+        includeAncestor: true
+      });
+      var bookmark = rng.paraBookmark(paras);
+      var clustereds = lists.clusterBy(paras, func.peq2('parentNode')); // paragraph to list
+
+      if (lists.find(paras, dom.isPurePara)) {
+        var wrappedParas = [];
+        external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.each(clustereds, function (idx, paras) {
+          wrappedParas = wrappedParas.concat(_this3.wrapList(paras, listName));
+        });
+        paras = wrappedParas; // list to paragraph or change list style
+      } else {
+        var diffLists = rng.nodes(dom.isList, {
+          includeAncestor: true
+        }).filter(function (listNode) {
+          return !external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.nodeName(listNode, listName);
+        });
+
+        if (diffLists.length) {
+          external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.each(diffLists, function (idx, listNode) {
+            dom.replace(listNode, listName);
+          });
+        } else {
+          paras = this.releaseList(clustereds, true);
+        }
+      }
+
+      range.createFromParaBookmark(bookmark, paras).select();
+    }
+    /**
+     * @param {Node[]} paras
+     * @param {String} listName
+     * @return {Node[]}
+     */
+
+  }, {
+    key: "wrapList",
+    value: function wrapList(paras, listName) {
+      var head = lists.head(paras);
+      var last = lists.last(paras);
+      var prevList = dom.isList(head.previousSibling) && head.previousSibling;
+      var nextList = dom.isList(last.nextSibling) && last.nextSibling;
+      var listNode = prevList || dom.insertAfter(dom.create(listName || 'UL'), last); // P to LI
+
+      paras = paras.map(function (para) {
+        return dom.isPurePara(para) ? dom.replace(para, 'LI') : para;
+      }); // append to list(<ul>, <ol>)
+
+      dom.appendChildNodes(listNode, paras);
+
+      if (nextList) {
+        dom.appendChildNodes(listNode, lists.from(nextList.childNodes));
+        dom.remove(nextList);
+      }
+
+      return paras;
+    }
+    /**
+     * @method releaseList
+     *
+     * @param {Array[]} clustereds
+     * @param {Boolean} isEscapseToBody
+     * @return {Node[]}
+     */
+
+  }, {
+    key: "releaseList",
+    value: function releaseList(clustereds, isEscapseToBody) {
+      var _this4 = this;
+
+      var releasedParas = [];
+      external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.each(clustereds, function (idx, paras) {
+        var head = lists.head(paras);
+        var last = lists.last(paras);
+        var headList = isEscapseToBody ? dom.lastAncestor(head, dom.isList) : head.parentNode;
+        var parentItem = headList.parentNode;
+
+        if (headList.parentNode.nodeName === 'LI') {
+          paras.map(function (para) {
+            var newList = _this4.findNextSiblings(para);
+
+            if (parentItem.nextSibling) {
+              parentItem.parentNode.insertBefore(para, parentItem.nextSibling);
+            } else {
+              parentItem.parentNode.appendChild(para);
+            }
+
+            if (newList.length) {
+              _this4.wrapList(newList, headList.nodeName);
+
+              para.appendChild(newList[0].parentNode);
+            }
+          });
+
+          if (headList.children.length === 0) {
+            parentItem.removeChild(headList);
+          }
+
+          if (parentItem.childNodes.length === 0) {
+            parentItem.parentNode.removeChild(parentItem);
+          }
+        } else {
+          var lastList = headList.childNodes.length > 1 ? dom.splitTree(headList, {
+            node: last.parentNode,
+            offset: dom.position(last) + 1
+          }, {
+            isSkipPaddingBlankHTML: true
+          }) : null;
+          var middleList = dom.splitTree(headList, {
+            node: head.parentNode,
+            offset: dom.position(head)
+          }, {
+            isSkipPaddingBlankHTML: true
+          });
+          paras = isEscapseToBody ? dom.listDescendant(middleList, dom.isLi) : lists.from(middleList.childNodes).filter(dom.isLi); // LI to P
+
+          if (isEscapseToBody || !dom.isList(headList.parentNode)) {
+            paras = paras.map(function (para) {
+              return dom.replace(para, 'P');
+            });
+          }
+
+          external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.each(lists.from(paras).reverse(), function (idx, para) {
+            dom.insertAfter(para, headList);
+          }); // remove empty lists
+
+          var rootLists = lists.compact([headList, middleList, lastList]);
+          external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.each(rootLists, function (idx, rootList) {
+            var listNodes = [rootList].concat(dom.listDescendant(rootList, dom.isList));
+            external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.each(listNodes.reverse(), function (idx, listNode) {
+              if (!dom.nodeLength(listNode)) {
+                dom.remove(listNode, true);
+              }
+            });
+          });
+        }
+
+        releasedParas = releasedParas.concat(paras);
+      });
+      return releasedParas;
+    }
+    /**
+     * @method appendToPrevious
+     *
+     * Appends list to previous list item, if
+     * none exist it wraps the list in a new list item.
+     *
+     * @param {HTMLNode} ListItem
+     * @return {HTMLNode}
+     */
+
+  }, {
+    key: "appendToPrevious",
+    value: function appendToPrevious(node) {
+      return node.previousSibling ? dom.appendChildNodes(node.previousSibling, [node]) : this.wrapList([node], 'LI');
+    }
+    /**
+     * @method findList
+     *
+     * Finds an existing list in list item
+     *
+     * @param {HTMLNode} ListItem
+     * @return {Array[]}
+     */
+
+  }, {
+    key: "findList",
+    value: function findList(node) {
+      return node ? lists.find(node.children, function (child) {
+        return ['OL', 'UL'].indexOf(child.nodeName) > -1;
+      }) : null;
+    }
+    /**
+     * @method findNextSiblings
+     *
+     * Finds all list item siblings that follow it
+     *
+     * @param {HTMLNode} ListItem
+     * @return {HTMLNode}
+     */
+
+  }, {
+    key: "findNextSiblings",
+    value: function findNextSiblings(node) {
+      var siblings = [];
+
+      while (node.nextSibling) {
+        siblings.push(node.nextSibling);
+        node = node.nextSibling;
+      }
+
+      return siblings;
+    }
+  }]);
+
+  return Bullet;
+}();
+
+
+// CONCATENATED MODULE: ./src/js/base/editing/Typing.js
+function Typing_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function Typing_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function Typing_createClass(Constructor, protoProps, staticProps) { if (protoProps) Typing_defineProperties(Constructor.prototype, protoProps); if (staticProps) Typing_defineProperties(Constructor, staticProps); return Constructor; }
+
+
+
+
+
+/**
+ * @class editing.Typing
+ *
+ * Typing
+ *
+ */
+
+var Typing_Typing = /*#__PURE__*/function () {
+  function Typing(context) {
+    Typing_classCallCheck(this, Typing);
+
+    // a Bullet instance to toggle lists off
+    this.bullet = new Bullet_Bullet();
+    this.options = context.options;
+  }
+  /**
+   * insert tab
+   *
+   * @param {WrappedRange} rng
+   * @param {Number} tabsize
+   */
+
+
+  Typing_createClass(Typing, [{
+    key: "insertTab",
+    value: function insertTab(rng, tabsize) {
+      var tab = dom.createText(new Array(tabsize + 1).join(dom.NBSP_CHAR));
+      rng = rng.deleteContents();
+      rng.insertNode(tab, true);
+      rng = range.create(tab, tabsize);
+      rng.select();
+    }
+    /**
+     * insert paragraph
+     *
+     * @param {jQuery} $editable
+     * @param {WrappedRange} rng Can be used in unit tests to "mock" the range
+     *
+     * blockquoteBreakingLevel
+     *   0 - No break, the new paragraph remains inside the quote
+     *   1 - Break the first blockquote in the ancestors list
+     *   2 - Break all blockquotes, so that the new paragraph is not quoted (this is the default)
+     */
+
+  }, {
+    key: "insertParagraph",
+    value: function insertParagraph(editable, rng) {
+      rng = rng || range.create(editable); // deleteContents on range.
+
+      rng = rng.deleteContents(); // Wrap range if it needs to be wrapped by paragraph
+
+      rng = rng.wrapBodyInlineWithPara(); // finding paragraph
+
+      var splitRoot = dom.ancestor(rng.sc, dom.isPara);
+      var nextPara; // on paragraph: split paragraph
+
+      if (splitRoot) {
+        // if it is an empty line with li
+        if (dom.isLi(splitRoot) && (dom.isEmpty(splitRoot) || dom.deepestChildIsEmpty(splitRoot))) {
+          // toggle UL/OL and escape
+          this.bullet.toggleList(splitRoot.parentNode.nodeName);
+          return;
+        } else {
+          var blockquote = null;
+
+          if (this.options.blockquoteBreakingLevel === 1) {
+            blockquote = dom.ancestor(splitRoot, dom.isBlockquote);
+          } else if (this.options.blockquoteBreakingLevel === 2) {
+            blockquote = dom.lastAncestor(splitRoot, dom.isBlockquote);
+          }
+
+          if (blockquote) {
+            // We're inside a blockquote and options ask us to break it
+            nextPara = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(dom.emptyPara)[0]; // If the split is right before a <br>, remove it so that there's no "empty line"
+            // after the split in the new blockquote created
+
+            if (dom.isRightEdgePoint(rng.getStartPoint()) && dom.isBR(rng.sc.nextSibling)) {
+              external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(rng.sc.nextSibling).remove();
+            }
+
+            var split = dom.splitTree(blockquote, rng.getStartPoint(), {
+              isDiscardEmptySplits: true
+            });
+
+            if (split) {
+              split.parentNode.insertBefore(nextPara, split);
+            } else {
+              dom.insertAfter(nextPara, blockquote); // There's no split if we were at the end of the blockquote
+            }
+          } else {
+            nextPara = dom.splitTree(splitRoot, rng.getStartPoint()); // not a blockquote, just insert the paragraph
+
+            var emptyAnchors = dom.listDescendant(splitRoot, dom.isEmptyAnchor);
+            emptyAnchors = emptyAnchors.concat(dom.listDescendant(nextPara, dom.isEmptyAnchor));
+            external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.each(emptyAnchors, function (idx, anchor) {
+              dom.remove(anchor);
+            }); // replace empty heading, pre or custom-made styleTag with P tag
+
+            if ((dom.isHeading(nextPara) || dom.isPre(nextPara) || dom.isCustomStyleTag(nextPara)) && dom.isEmpty(nextPara)) {
+              nextPara = dom.replace(nextPara, 'p');
+            }
+          }
+        } // no paragraph: insert empty paragraph
+
+      } else {
+        var next = rng.sc.childNodes[rng.so];
+        nextPara = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(dom.emptyPara)[0];
+
+        if (next) {
+          rng.sc.insertBefore(nextPara, next);
+        } else {
+          rng.sc.appendChild(nextPara);
+        }
+      }
+
+      range.create(nextPara, 0).normalize().select().scrollIntoView(editable);
+    }
+  }]);
+
+  return Typing;
+}();
+
+
+// CONCATENATED MODULE: ./src/js/base/editing/Table.js
+function Table_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function Table_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function Table_createClass(Constructor, protoProps, staticProps) { if (protoProps) Table_defineProperties(Constructor.prototype, protoProps); if (staticProps) Table_defineProperties(Constructor, staticProps); return Constructor; }
+
+
+
+
+
+/**
+ * @class Create a virtual table to create what actions to do in change.
+ * @param {object} startPoint Cell selected to apply change.
+ * @param {enum} where  Where change will be applied Row or Col. Use enum: TableResultAction.where
+ * @param {enum} action Action to be applied. Use enum: TableResultAction.requestAction
+ * @param {object} domTable Dom element of table to make changes.
+ */
+
+var TableResultAction = function TableResultAction(startPoint, where, action, domTable) {
+  var _startPoint = {
+    'colPos': 0,
+    'rowPos': 0
+  };
+  var _virtualTable = [];
+  var _actionCellList = []; /// ///////////////////////////////////////////
+  // Private functions
+  /// ///////////////////////////////////////////
+
+  /**
+   * Set the startPoint of action.
+   */
+
+  function setStartPoint() {
+    if (!startPoint || !startPoint.tagName || startPoint.tagName.toLowerCase() !== 'td' && startPoint.tagName.toLowerCase() !== 'th') {
+      // Impossible to identify start Cell point
+      return;
+    }
+
+    _startPoint.colPos = startPoint.cellIndex;
+
+    if (!startPoint.parentElement || !startPoint.parentElement.tagName || startPoint.parentElement.tagName.toLowerCase() !== 'tr') {
+      // Impossible to identify start Row point
+      return;
+    }
+
+    _startPoint.rowPos = startPoint.parentElement.rowIndex;
+  }
+  /**
+   * Define virtual table position info object.
+   *
+   * @param {int} rowIndex Index position in line of virtual table.
+   * @param {int} cellIndex Index position in column of virtual table.
+   * @param {object} baseRow Row affected by this position.
+   * @param {object} baseCell Cell affected by this position.
+   * @param {bool} isSpan Inform if it is an span cell/row.
+   */
+
+
+  function setVirtualTablePosition(rowIndex, cellIndex, baseRow, baseCell, isRowSpan, isColSpan, isVirtualCell) {
+    var objPosition = {
+      'baseRow': baseRow,
+      'baseCell': baseCell,
+      'isRowSpan': isRowSpan,
+      'isColSpan': isColSpan,
+      'isVirtual': isVirtualCell
+    };
+
+    if (!_virtualTable[rowIndex]) {
+      _virtualTable[rowIndex] = [];
+    }
+
+    _virtualTable[rowIndex][cellIndex] = objPosition;
+  }
+  /**
+   * Create action cell object.
+   *
+   * @param {object} virtualTableCellObj Object of specific position on virtual table.
+   * @param {enum} resultAction Action to be applied in that item.
+   */
+
+
+  function getActionCell(virtualTableCellObj, resultAction, virtualRowPosition, virtualColPosition) {
+    return {
+      'baseCell': virtualTableCellObj.baseCell,
+      'action': resultAction,
+      'virtualTable': {
+        'rowIndex': virtualRowPosition,
+        'cellIndex': virtualColPosition
+      }
+    };
+  }
+  /**
+   * Recover free index of row to append Cell.
+   *
+   * @param {int} rowIndex Index of row to find free space.
+   * @param {int} cellIndex Index of cell to find free space in table.
+   */
+
+
+  function recoverCellIndex(rowIndex, cellIndex) {
+    if (!_virtualTable[rowIndex]) {
+      return cellIndex;
+    }
+
+    if (!_virtualTable[rowIndex][cellIndex]) {
+      return cellIndex;
+    }
+
+    var newCellIndex = cellIndex;
+
+    while (_virtualTable[rowIndex][newCellIndex]) {
+      newCellIndex++;
+
+      if (!_virtualTable[rowIndex][newCellIndex]) {
+        return newCellIndex;
+      }
+    }
+  }
+  /**
+   * Recover info about row and cell and add information to virtual table.
+   *
+   * @param {object} row Row to recover information.
+   * @param {object} cell Cell to recover information.
+   */
+
+
+  function addCellInfoToVirtual(row, cell) {
+    var cellIndex = recoverCellIndex(row.rowIndex, cell.cellIndex);
+    var cellHasColspan = cell.colSpan > 1;
+    var cellHasRowspan = cell.rowSpan > 1;
+    var isThisSelectedCell = row.rowIndex === _startPoint.rowPos && cell.cellIndex === _startPoint.colPos;
+    setVirtualTablePosition(row.rowIndex, cellIndex, row, cell, cellHasRowspan, cellHasColspan, false); // Add span rows to virtual Table.
+
+    var rowspanNumber = cell.attributes.rowSpan ? parseInt(cell.attributes.rowSpan.value, 10) : 0;
+
+    if (rowspanNumber > 1) {
+      for (var rp = 1; rp < rowspanNumber; rp++) {
+        var rowspanIndex = row.rowIndex + rp;
+        adjustStartPoint(rowspanIndex, cellIndex, cell, isThisSelectedCell);
+        setVirtualTablePosition(rowspanIndex, cellIndex, row, cell, true, cellHasColspan, true);
+      }
+    } // Add span cols to virtual table.
+
+
+    var colspanNumber = cell.attributes.colSpan ? parseInt(cell.attributes.colSpan.value, 10) : 0;
+
+    if (colspanNumber > 1) {
+      for (var cp = 1; cp < colspanNumber; cp++) {
+        var cellspanIndex = recoverCellIndex(row.rowIndex, cellIndex + cp);
+        adjustStartPoint(row.rowIndex, cellspanIndex, cell, isThisSelectedCell);
+        setVirtualTablePosition(row.rowIndex, cellspanIndex, row, cell, cellHasRowspan, true, true);
+      }
+    }
+  }
+  /**
+   * Process validation and adjust of start point if needed
+   *
+   * @param {int} rowIndex
+   * @param {int} cellIndex
+   * @param {object} cell
+   * @param {bool} isSelectedCell
+   */
+
+
+  function adjustStartPoint(rowIndex, cellIndex, cell, isSelectedCell) {
+    if (rowIndex === _startPoint.rowPos && _startPoint.colPos >= cell.cellIndex && cell.cellIndex <= cellIndex && !isSelectedCell) {
+      _startPoint.colPos++;
+    }
+  }
+  /**
+   * Create virtual table of cells with all cells, including span cells.
+   */
+
+
+  function createVirtualTable() {
+    var rows = domTable.rows;
+
+    for (var rowIndex = 0; rowIndex < rows.length; rowIndex++) {
+      var cells = rows[rowIndex].cells;
+
+      for (var cellIndex = 0; cellIndex < cells.length; cellIndex++) {
+        addCellInfoToVirtual(rows[rowIndex], cells[cellIndex]);
+      }
+    }
+  }
+  /**
+   * Get action to be applied on the cell.
+   *
+   * @param {object} cell virtual table cell to apply action
+   */
+
+
+  function getDeleteResultActionToCell(cell) {
+    switch (where) {
+      case TableResultAction.where.Column:
+        if (cell.isColSpan) {
+          return TableResultAction.resultAction.SubtractSpanCount;
+        }
+
+        break;
+
+      case TableResultAction.where.Row:
+        if (!cell.isVirtual && cell.isRowSpan) {
+          return TableResultAction.resultAction.AddCell;
+        } else if (cell.isRowSpan) {
+          return TableResultAction.resultAction.SubtractSpanCount;
+        }
+
+        break;
+    }
+
+    return TableResultAction.resultAction.RemoveCell;
+  }
+  /**
+   * Get action to be applied on the cell.
+   *
+   * @param {object} cell virtual table cell to apply action
+   */
+
+
+  function getAddResultActionToCell(cell) {
+    switch (where) {
+      case TableResultAction.where.Column:
+        if (cell.isColSpan) {
+          return TableResultAction.resultAction.SumSpanCount;
+        } else if (cell.isRowSpan && cell.isVirtual) {
+          return TableResultAction.resultAction.Ignore;
+        }
+
+        break;
+
+      case TableResultAction.where.Row:
+        if (cell.isRowSpan) {
+          return TableResultAction.resultAction.SumSpanCount;
+        } else if (cell.isColSpan && cell.isVirtual) {
+          return TableResultAction.resultAction.Ignore;
+        }
+
+        break;
+    }
+
+    return TableResultAction.resultAction.AddCell;
+  }
+
+  function init() {
+    setStartPoint();
+    createVirtualTable();
+  } /// ///////////////////////////////////////////
+  // Public functions
+  /// ///////////////////////////////////////////
+
+  /**
+   * Recover array os what to do in table.
+   */
+
+
+  this.getActionList = function () {
+    var fixedRow = where === TableResultAction.where.Row ? _startPoint.rowPos : -1;
+    var fixedCol = where === TableResultAction.where.Column ? _startPoint.colPos : -1;
+    var actualPosition = 0;
+    var canContinue = true;
+
+    while (canContinue) {
+      var rowPosition = fixedRow >= 0 ? fixedRow : actualPosition;
+      var colPosition = fixedCol >= 0 ? fixedCol : actualPosition;
+      var row = _virtualTable[rowPosition];
+
+      if (!row) {
+        canContinue = false;
+        return _actionCellList;
+      }
+
+      var cell = row[colPosition];
+
+      if (!cell) {
+        canContinue = false;
+        return _actionCellList;
+      } // Define action to be applied in this cell
+
+
+      var resultAction = TableResultAction.resultAction.Ignore;
+
+      switch (action) {
+        case TableResultAction.requestAction.Add:
+          resultAction = getAddResultActionToCell(cell);
+          break;
+
+        case TableResultAction.requestAction.Delete:
+          resultAction = getDeleteResultActionToCell(cell);
+          break;
+      }
+
+      _actionCellList.push(getActionCell(cell, resultAction, rowPosition, colPosition));
+
+      actualPosition++;
+    }
+
+    return _actionCellList;
+  };
+
+  init();
+};
+/**
+*
+* Where action occours enum.
+*/
+
+
+TableResultAction.where = {
+  'Row': 0,
+  'Column': 1
+};
+/**
+*
+* Requested action to apply enum.
+*/
+
+TableResultAction.requestAction = {
+  'Add': 0,
+  'Delete': 1
+};
+/**
+*
+* Result action to be executed enum.
+*/
+
+TableResultAction.resultAction = {
+  'Ignore': 0,
+  'SubtractSpanCount': 1,
+  'RemoveCell': 2,
+  'AddCell': 3,
+  'SumSpanCount': 4
+};
+/**
+ *
+ * @class editing.Table
+ *
+ * Table
+ *
+ */
+
+var Table_Table = /*#__PURE__*/function () {
+  function Table() {
+    Table_classCallCheck(this, Table);
+  }
+
+  Table_createClass(Table, [{
+    key: "tab",
+
+    /**
+     * handle tab key
+     *
+     * @param {WrappedRange} rng
+     * @param {Boolean} isShift
+     */
+    value: function tab(rng, isShift) {
+      var cell = dom.ancestor(rng.commonAncestor(), dom.isCell);
+      var table = dom.ancestor(cell, dom.isTable);
+      var cells = dom.listDescendant(table, dom.isCell);
+      var nextCell = lists[isShift ? 'prev' : 'next'](cells, cell);
+
+      if (nextCell) {
+        range.create(nextCell, 0).select();
+      }
+    }
+    /**
+     * Add a new row
+     *
+     * @param {WrappedRange} rng
+     * @param {String} position (top/bottom)
+     * @return {Node}
+     */
+
+  }, {
+    key: "addRow",
+    value: function addRow(rng, position) {
+      var cell = dom.ancestor(rng.commonAncestor(), dom.isCell);
+      var currentTr = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(cell).closest('tr');
+      var trAttributes = this.recoverAttributes(currentTr);
+      var html = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()('<tr' + trAttributes + '></tr>');
+      var vTable = new TableResultAction(cell, TableResultAction.where.Row, TableResultAction.requestAction.Add, external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(currentTr).closest('table')[0]);
+      var actions = vTable.getActionList();
+
+      for (var idCell = 0; idCell < actions.length; idCell++) {
+        var currentCell = actions[idCell];
+        var tdAttributes = this.recoverAttributes(currentCell.baseCell);
+
+        switch (currentCell.action) {
+          case TableResultAction.resultAction.AddCell:
+            html.append('<td' + tdAttributes + '>' + dom.blank + '</td>');
+            break;
+
+          case TableResultAction.resultAction.SumSpanCount:
+            {
+              if (position === 'top') {
+                var baseCellTr = currentCell.baseCell.parent;
+                var isTopFromRowSpan = (!baseCellTr ? 0 : currentCell.baseCell.closest('tr').rowIndex) <= currentTr[0].rowIndex;
+
+                if (isTopFromRowSpan) {
+                  var newTd = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()('<div></div>').append(external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()('<td' + tdAttributes + '>' + dom.blank + '</td>').removeAttr('rowspan')).html();
+                  html.append(newTd);
+                  break;
+                }
+              }
+
+              var rowspanNumber = parseInt(currentCell.baseCell.rowSpan, 10);
+              rowspanNumber++;
+              currentCell.baseCell.setAttribute('rowSpan', rowspanNumber);
+            }
+            break;
+        }
+      }
+
+      if (position === 'top') {
+        currentTr.before(html);
+      } else {
+        var cellHasRowspan = cell.rowSpan > 1;
+
+        if (cellHasRowspan) {
+          var lastTrIndex = currentTr[0].rowIndex + (cell.rowSpan - 2);
+          external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(currentTr).parent().find('tr')[lastTrIndex]).after(external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(html));
+          return;
+        }
+
+        currentTr.after(html);
+      }
+    }
+    /**
+     * Add a new col
+     *
+     * @param {WrappedRange} rng
+     * @param {String} position (left/right)
+     * @return {Node}
+     */
+
+  }, {
+    key: "addCol",
+    value: function addCol(rng, position) {
+      var cell = dom.ancestor(rng.commonAncestor(), dom.isCell);
+      var row = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(cell).closest('tr');
+      var rowsGroup = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(row).siblings();
+      rowsGroup.push(row);
+      var vTable = new TableResultAction(cell, TableResultAction.where.Column, TableResultAction.requestAction.Add, external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(row).closest('table')[0]);
+      var actions = vTable.getActionList();
+
+      for (var actionIndex = 0; actionIndex < actions.length; actionIndex++) {
+        var currentCell = actions[actionIndex];
+        var tdAttributes = this.recoverAttributes(currentCell.baseCell);
+
+        switch (currentCell.action) {
+          case TableResultAction.resultAction.AddCell:
+            if (position === 'right') {
+              external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(currentCell.baseCell).after('<td' + tdAttributes + '>' + dom.blank + '</td>');
+            } else {
+              external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(currentCell.baseCell).before('<td' + tdAttributes + '>' + dom.blank + '</td>');
+            }
+
+            break;
+
+          case TableResultAction.resultAction.SumSpanCount:
+            if (position === 'right') {
+              var colspanNumber = parseInt(currentCell.baseCell.colSpan, 10);
+              colspanNumber++;
+              currentCell.baseCell.setAttribute('colSpan', colspanNumber);
+            } else {
+              external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(currentCell.baseCell).before('<td' + tdAttributes + '>' + dom.blank + '</td>');
+            }
+
+            break;
+        }
+      }
+    }
+    /*
+    * Copy attributes from element.
+    *
+    * @param {object} Element to recover attributes.
+    * @return {string} Copied string elements.
+    */
+
+  }, {
+    key: "recoverAttributes",
+    value: function recoverAttributes(el) {
+      var resultStr = '';
+
+      if (!el) {
+        return resultStr;
+      }
+
+      var attrList = el.attributes || [];
+
+      for (var i = 0; i < attrList.length; i++) {
+        if (attrList[i].name.toLowerCase() === 'id') {
+          continue;
+        }
+
+        if (attrList[i].specified) {
+          resultStr += ' ' + attrList[i].name + '=\'' + attrList[i].value + '\'';
+        }
+      }
+
+      return resultStr;
+    }
+    /**
+     * Delete current row
+     *
+     * @param {WrappedRange} rng
+     * @return {Node}
+     */
+
+  }, {
+    key: "deleteRow",
+    value: function deleteRow(rng) {
+      var cell = dom.ancestor(rng.commonAncestor(), dom.isCell);
+      var row = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(cell).closest('tr');
+      var cellPos = row.children('td, th').index(external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(cell));
+      var rowPos = row[0].rowIndex;
+      var vTable = new TableResultAction(cell, TableResultAction.where.Row, TableResultAction.requestAction.Delete, external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(row).closest('table')[0]);
+      var actions = vTable.getActionList();
+
+      for (var actionIndex = 0; actionIndex < actions.length; actionIndex++) {
+        if (!actions[actionIndex]) {
+          continue;
+        }
+
+        var baseCell = actions[actionIndex].baseCell;
+        var virtualPosition = actions[actionIndex].virtualTable;
+        var hasRowspan = baseCell.rowSpan && baseCell.rowSpan > 1;
+        var rowspanNumber = hasRowspan ? parseInt(baseCell.rowSpan, 10) : 0;
+
+        switch (actions[actionIndex].action) {
+          case TableResultAction.resultAction.Ignore:
+            continue;
+
+          case TableResultAction.resultAction.AddCell:
+            {
+              var nextRow = row.next('tr')[0];
+
+              if (!nextRow) {
+                continue;
+              }
+
+              var cloneRow = row[0].cells[cellPos];
+
+              if (hasRowspan) {
+                if (rowspanNumber > 2) {
+                  rowspanNumber--;
+                  nextRow.insertBefore(cloneRow, nextRow.cells[cellPos]);
+                  nextRow.cells[cellPos].setAttribute('rowSpan', rowspanNumber);
+                  nextRow.cells[cellPos].innerHTML = '';
+                } else if (rowspanNumber === 2) {
+                  nextRow.insertBefore(cloneRow, nextRow.cells[cellPos]);
+                  nextRow.cells[cellPos].removeAttribute('rowSpan');
+                  nextRow.cells[cellPos].innerHTML = '';
+                }
+              }
+            }
+            continue;
+
+          case TableResultAction.resultAction.SubtractSpanCount:
+            if (hasRowspan) {
+              if (rowspanNumber > 2) {
+                rowspanNumber--;
+                baseCell.setAttribute('rowSpan', rowspanNumber);
+
+                if (virtualPosition.rowIndex !== rowPos && baseCell.cellIndex === cellPos) {
+                  baseCell.innerHTML = '';
+                }
+              } else if (rowspanNumber === 2) {
+                baseCell.removeAttribute('rowSpan');
+
+                if (virtualPosition.rowIndex !== rowPos && baseCell.cellIndex === cellPos) {
+                  baseCell.innerHTML = '';
+                }
+              }
+            }
+
+            continue;
+
+          case TableResultAction.resultAction.RemoveCell:
+            // Do not need remove cell because row will be deleted.
+            continue;
+        }
+      }
+
+      row.remove();
+    }
+    /**
+     * Delete current col
+     *
+     * @param {WrappedRange} rng
+     * @return {Node}
+     */
+
+  }, {
+    key: "deleteCol",
+    value: function deleteCol(rng) {
+      var cell = dom.ancestor(rng.commonAncestor(), dom.isCell);
+      var row = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(cell).closest('tr');
+      var cellPos = row.children('td, th').index(external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(cell));
+      var vTable = new TableResultAction(cell, TableResultAction.where.Column, TableResultAction.requestAction.Delete, external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(row).closest('table')[0]);
+      var actions = vTable.getActionList();
+
+      for (var actionIndex = 0; actionIndex < actions.length; actionIndex++) {
+        if (!actions[actionIndex]) {
+          continue;
+        }
+
+        switch (actions[actionIndex].action) {
+          case TableResultAction.resultAction.Ignore:
+            continue;
+
+          case TableResultAction.resultAction.SubtractSpanCount:
+            {
+              var baseCell = actions[actionIndex].baseCell;
+              var hasColspan = baseCell.colSpan && baseCell.colSpan > 1;
+
+              if (hasColspan) {
+                var colspanNumber = baseCell.colSpan ? parseInt(baseCell.colSpan, 10) : 0;
+
+                if (colspanNumber > 2) {
+                  colspanNumber--;
+                  baseCell.setAttribute('colSpan', colspanNumber);
+
+                  if (baseCell.cellIndex === cellPos) {
+                    baseCell.innerHTML = '';
+                  }
+                } else if (colspanNumber === 2) {
+                  baseCell.removeAttribute('colSpan');
+
+                  if (baseCell.cellIndex === cellPos) {
+                    baseCell.innerHTML = '';
+                  }
+                }
+              }
+            }
+            continue;
+
+          case TableResultAction.resultAction.RemoveCell:
+            dom.remove(actions[actionIndex].baseCell, true);
+            continue;
+        }
+      }
+    }
+    /**
+     * create empty table element
+     *
+     * @param {Number} rowCount
+     * @param {Number} colCount
+     * @return {Node}
+     */
+
+  }, {
+    key: "createTable",
+    value: function createTable(colCount, rowCount, options) {
+      var tds = [];
+      var tdHTML;
+
+      for (var idxCol = 0; idxCol < colCount; idxCol++) {
+        tds.push('<td>' + dom.blank + '</td>');
+      }
+
+      tdHTML = tds.join('');
+      var trs = [];
+      var trHTML;
+
+      for (var idxRow = 0; idxRow < rowCount; idxRow++) {
+        trs.push('<tr>' + tdHTML + '</tr>');
+      }
+
+      trHTML = trs.join('');
+      var $table = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()('<table>' + trHTML + '</table>');
+
+      if (options && options.tableClassName) {
+        $table.addClass(options.tableClassName);
+      }
+
+      return $table[0];
+    }
+    /**
+     * Delete current table
+     *
+     * @param {WrappedRange} rng
+     * @return {Node}
+     */
+
+  }, {
+    key: "deleteTable",
+    value: function deleteTable(rng) {
+      var cell = dom.ancestor(rng.commonAncestor(), dom.isCell);
+      external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(cell).closest('table').remove();
+    }
+  }]);
+
+  return Table;
+}();
+
+
+// CONCATENATED MODULE: ./src/js/base/module/Editor.js
+function Editor_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function Editor_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function Editor_createClass(Constructor, protoProps, staticProps) { if (protoProps) Editor_defineProperties(Constructor.prototype, protoProps); if (staticProps) Editor_defineProperties(Constructor, staticProps); return Constructor; }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+var KEY_BOGUS = 'bogus';
+/**
+ * @class Editor
+ */
+
+var Editor_Editor = /*#__PURE__*/function () {
+  function Editor(context) {
+    var _this = this;
+
+    Editor_classCallCheck(this, Editor);
+
+    this.context = context;
+    this.$note = context.layoutInfo.note;
+    this.$editor = context.layoutInfo.editor;
+    this.$editable = context.layoutInfo.editable;
+    this.options = context.options;
+    this.lang = this.options.langInfo;
+    this.editable = this.$editable[0];
+    this.lastRange = null;
+    this.snapshot = null;
+    this.style = new Style_Style();
+    this.table = new Table_Table();
+    this.typing = new Typing_Typing(context);
+    this.bullet = new Bullet_Bullet();
+    this.history = new History_History(context);
+    this.context.memo('help.escape', this.lang.help.escape);
+    this.context.memo('help.undo', this.lang.help.undo);
+    this.context.memo('help.redo', this.lang.help.redo);
+    this.context.memo('help.tab', this.lang.help.tab);
+    this.context.memo('help.untab', this.lang.help.untab);
+    this.context.memo('help.insertParagraph', this.lang.help.insertParagraph);
+    this.context.memo('help.insertOrderedList', this.lang.help.insertOrderedList);
+    this.context.memo('help.insertUnorderedList', this.lang.help.insertUnorderedList);
+    this.context.memo('help.indent', this.lang.help.indent);
+    this.context.memo('help.outdent', this.lang.help.outdent);
+    this.context.memo('help.formatPara', this.lang.help.formatPara);
+    this.context.memo('help.insertHorizontalRule', this.lang.help.insertHorizontalRule);
+    this.context.memo('help.fontName', this.lang.help.fontName); // native commands(with execCommand), generate function for execCommand
+
+    var commands = ['bold', 'italic', 'underline', 'strikethrough', 'superscript', 'subscript', 'justifyLeft', 'justifyCenter', 'justifyRight', 'justifyFull', 'formatBlock', 'removeFormat', 'backColor'];
+
+    for (var idx = 0, len = commands.length; idx < len; idx++) {
+      this[commands[idx]] = function (sCmd) {
+        return function (value) {
+          _this.beforeCommand();
+
+          document.execCommand(sCmd, false, value);
+
+          _this.afterCommand(true);
+        };
+      }(commands[idx]);
+
+      this.context.memo('help.' + commands[idx], this.lang.help[commands[idx]]);
+    }
+
+    this.fontName = this.wrapCommand(function (value) {
+      return _this.fontStyling('font-family', env.validFontName(value));
+    });
+    this.fontSize = this.wrapCommand(function (value) {
+      var unit = _this.currentStyle()['font-size-unit'];
+
+      return _this.fontStyling('font-size', value + unit);
+    });
+    this.fontSizeUnit = this.wrapCommand(function (value) {
+      var size = _this.currentStyle()['font-size'];
+
+      return _this.fontStyling('font-size', size + value);
+    });
+
+    for (var _idx = 1; _idx <= 6; _idx++) {
+      this['formatH' + _idx] = function (idx) {
+        return function () {
+          _this.formatBlock('H' + idx);
+        };
+      }(_idx);
+
+      this.context.memo('help.formatH' + _idx, this.lang.help['formatH' + _idx]);
+    }
+
+    this.insertParagraph = this.wrapCommand(function () {
+      _this.typing.insertParagraph(_this.editable);
+    });
+    this.insertOrderedList = this.wrapCommand(function () {
+      _this.bullet.insertOrderedList(_this.editable);
+    });
+    this.insertUnorderedList = this.wrapCommand(function () {
+      _this.bullet.insertUnorderedList(_this.editable);
+    });
+    this.indent = this.wrapCommand(function () {
+      _this.bullet.indent(_this.editable);
+    });
+    this.outdent = this.wrapCommand(function () {
+      _this.bullet.outdent(_this.editable);
+    });
+    /**
+     * insertNode
+     * insert node
+     * @param {Node} node
+     */
+
+    this.insertNode = this.wrapCommand(function (node) {
+      if (_this.isLimited(external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(node).text().length)) {
+        return;
+      }
+
+      var rng = _this.getLastRange();
+
+      rng.insertNode(node);
+
+      _this.setLastRange(range.createFromNodeAfter(node).select());
+    });
+    /**
+     * insert text
+     * @param {String} text
+     */
+
+    this.insertText = this.wrapCommand(function (text) {
+      if (_this.isLimited(text.length)) {
+        return;
+      }
+
+      var rng = _this.getLastRange();
+
+      var textNode = rng.insertNode(dom.createText(text));
+
+      _this.setLastRange(range.create(textNode, dom.nodeLength(textNode)).select());
+    });
+    /**
+     * paste HTML
+     * @param {String} markup
+     */
+
+    this.pasteHTML = this.wrapCommand(function (markup) {
+      if (_this.isLimited(markup.length)) {
+        return;
+      }
+
+      markup = _this.context.invoke('codeview.purify', markup);
+
+      var contents = _this.getLastRange().pasteHTML(markup);
+
+      _this.setLastRange(range.createFromNodeAfter(lists.last(contents)).select());
+    });
+    /**
+     * formatBlock
+     *
+     * @param {String} tagName
+     */
+
+    this.formatBlock = this.wrapCommand(function (tagName, $target) {
+      var onApplyCustomStyle = _this.options.callbacks.onApplyCustomStyle;
+
+      if (onApplyCustomStyle) {
+        onApplyCustomStyle.call(_this, $target, _this.context, _this.onFormatBlock);
+      } else {
+        _this.onFormatBlock(tagName, $target);
+      }
+    });
+    /**
+     * insert horizontal rule
+     */
+
+    this.insertHorizontalRule = this.wrapCommand(function () {
+      var hrNode = _this.getLastRange().insertNode(dom.create('HR'));
+
+      if (hrNode.nextSibling) {
+        _this.setLastRange(range.create(hrNode.nextSibling, 0).normalize().select());
+      }
+    });
+    /**
+     * lineHeight
+     * @param {String} value
+     */
+
+    this.lineHeight = this.wrapCommand(function (value) {
+      _this.style.stylePara(_this.getLastRange(), {
+        lineHeight: value
+      });
+    });
+    /**
+     * create link (command)
+     *
+     * @param {Object} linkInfo
+     */
+
+    this.createLink = this.wrapCommand(function (linkInfo) {
+      var linkUrl = linkInfo.url;
+      var linkText = linkInfo.text;
+      var isNewWindow = linkInfo.isNewWindow;
+      var checkProtocol = linkInfo.checkProtocol;
+
+      var rng = linkInfo.range || _this.getLastRange();
+
+      var additionalTextLength = linkText.length - rng.toString().length;
+
+      if (additionalTextLength > 0 && _this.isLimited(additionalTextLength)) {
+        return;
+      }
+
+      var isTextChanged = rng.toString() !== linkText; // handle spaced urls from input
+
+      if (typeof linkUrl === 'string') {
+        linkUrl = linkUrl.trim();
+      }
+
+      if (_this.options.onCreateLink) {
+        linkUrl = _this.options.onCreateLink(linkUrl);
+      } else if (checkProtocol) {
+        // if url doesn't have any protocol and not even a relative or a label, use http:// as default
+        linkUrl = /^([A-Za-z][A-Za-z0-9+-.]*\:|#|\/)/.test(linkUrl) ? linkUrl : _this.options.defaultProtocol + linkUrl;
+      }
+
+      var anchors = [];
+
+      if (isTextChanged) {
+        rng = rng.deleteContents();
+        var anchor = rng.insertNode(external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()('<A>' + linkText + '</A>')[0]);
+        anchors.push(anchor);
+      } else {
+        anchors = _this.style.styleNodes(rng, {
+          nodeName: 'A',
+          expandClosestSibling: true,
+          onlyPartialContains: true
+        });
+      }
+
+      external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.each(anchors, function (idx, anchor) {
+        external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(anchor).attr('href', linkUrl);
+
+        if (isNewWindow) {
+          external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(anchor).attr('target', '_blank');
+        } else {
+          external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(anchor).removeAttr('target');
+        }
+      });
+
+      _this.setLastRange(_this.createRangeFromList(anchors).select());
+    });
+    /**
+     * setting color
+     *
+     * @param {Object} sObjColor  color code
+     * @param {String} sObjColor.foreColor foreground color
+     * @param {String} sObjColor.backColor background color
+     */
+
+    this.color = this.wrapCommand(function (colorInfo) {
+      var foreColor = colorInfo.foreColor;
+      var backColor = colorInfo.backColor;
+
+      if (foreColor) {
+        document.execCommand('foreColor', false, foreColor);
+      }
+
+      if (backColor) {
+        document.execCommand('backColor', false, backColor);
+      }
+    });
+    /**
+     * Set foreground color
+     *
+     * @param {String} colorCode foreground color code
+     */
+
+    this.foreColor = this.wrapCommand(function (colorInfo) {
+      document.execCommand('foreColor', false, colorInfo);
+    });
+    /**
+     * insert Table
+     *
+     * @param {String} dimension of table (ex : "5x5")
+     */
+
+    this.insertTable = this.wrapCommand(function (dim) {
+      var dimension = dim.split('x');
+
+      var rng = _this.getLastRange().deleteContents();
+
+      rng.insertNode(_this.table.createTable(dimension[0], dimension[1], _this.options));
+    });
+    /**
+     * remove media object and Figure Elements if media object is img with Figure.
+     */
+
+    this.removeMedia = this.wrapCommand(function () {
+      var $target = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(_this.restoreTarget()).parent();
+
+      if ($target.closest('figure').length) {
+        $target.closest('figure').remove();
+      } else {
+        $target = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(_this.restoreTarget()).detach();
+      }
+
+      _this.context.triggerEvent('media.delete', $target, _this.$editable);
+    });
+    /**
+     * float me
+     *
+     * @param {String} value
+     */
+
+    this.floatMe = this.wrapCommand(function (value) {
+      var $target = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(_this.restoreTarget());
+      $target.toggleClass('note-float-left', value === 'left');
+      $target.toggleClass('note-float-right', value === 'right');
+      $target.css('float', value === 'none' ? '' : value);
+    });
+    /**
+     * resize overlay element
+     * @param {String} value
+     */
+
+    this.resize = this.wrapCommand(function (value) {
+      var $target = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(_this.restoreTarget());
+      value = parseFloat(value);
+
+      if (value === 0) {
+        $target.css('width', '');
+      } else {
+        $target.css({
+          width: value * 100 + '%',
+          height: ''
+        });
+      }
+    });
+  }
+
+  Editor_createClass(Editor, [{
+    key: "initialize",
+    value: function initialize() {
+      var _this2 = this;
+
+      // bind custom events
+      this.$editable.on('keydown', function (event) {
+        if (event.keyCode === core_key.code.ENTER) {
+          _this2.context.triggerEvent('enter', event);
+        }
+
+        _this2.context.triggerEvent('keydown', event); // keep a snapshot to limit text on input event
+
+
+        _this2.snapshot = _this2.history.makeSnapshot();
+        _this2.hasKeyShortCut = false;
+
+        if (!event.isDefaultPrevented()) {
+          if (_this2.options.shortcuts) {
+            _this2.hasKeyShortCut = _this2.handleKeyMap(event);
+          } else {
+            _this2.preventDefaultEditableShortCuts(event);
+          }
+        }
+
+        if (_this2.isLimited(1, event)) {
+          var lastRange = _this2.getLastRange();
+
+          if (lastRange.eo - lastRange.so === 0) {
+            return false;
+          }
+        }
+
+        _this2.setLastRange(); // record undo in the key event except keyMap.
+
+
+        if (_this2.options.recordEveryKeystroke) {
+          if (_this2.hasKeyShortCut === false) {
+            _this2.history.recordUndo();
+          }
+        }
+      }).on('keyup', function (event) {
+        _this2.setLastRange();
+
+        _this2.context.triggerEvent('keyup', event);
+      }).on('focus', function (event) {
+        _this2.setLastRange();
+
+        _this2.context.triggerEvent('focus', event);
+      }).on('blur', function (event) {
+        _this2.context.triggerEvent('blur', event);
+      }).on('mousedown', function (event) {
+        _this2.context.triggerEvent('mousedown', event);
+      }).on('mouseup', function (event) {
+        _this2.setLastRange();
+
+        _this2.history.recordUndo();
+
+        _this2.context.triggerEvent('mouseup', event);
+      }).on('scroll', function (event) {
+        _this2.context.triggerEvent('scroll', event);
+      }).on('paste', function (event) {
+        _this2.setLastRange();
+
+        _this2.context.triggerEvent('paste', event);
+      }).on('input', function () {
+        // To limit composition characters (e.g. Korean)
+        if (_this2.isLimited(0) && _this2.snapshot) {
+          _this2.history.applySnapshot(_this2.snapshot);
+        }
+      });
+      this.$editable.attr('spellcheck', this.options.spellCheck);
+      this.$editable.attr('autocorrect', this.options.spellCheck);
+
+      if (this.options.disableGrammar) {
+        this.$editable.attr('data-gramm', false);
+      } // init content before set event
+
+
+      this.$editable.html(dom.html(this.$note) || dom.emptyPara);
+      this.$editable.on(env.inputEventName, func.debounce(function () {
+        _this2.context.triggerEvent('change', _this2.$editable.html(), _this2.$editable);
+      }, 10));
+      this.$editable.on('focusin', function (event) {
+        _this2.context.triggerEvent('focusin', event);
+      }).on('focusout', function (event) {
+        _this2.context.triggerEvent('focusout', event);
+      });
+
+      if (this.options.airMode) {
+        if (this.options.overrideContextMenu) {
+          this.$editor.on('contextmenu', function (event) {
+            _this2.context.triggerEvent('contextmenu', event);
+
+            return false;
+          });
+        }
+      } else {
+        if (this.options.width) {
+          this.$editor.outerWidth(this.options.width);
+        }
+
+        if (this.options.height) {
+          this.$editable.outerHeight(this.options.height);
+        }
+
+        if (this.options.maxHeight) {
+          this.$editable.css('max-height', this.options.maxHeight);
+        }
+
+        if (this.options.minHeight) {
+          this.$editable.css('min-height', this.options.minHeight);
+        }
+      }
+
+      this.history.recordUndo();
+      this.setLastRange();
+    }
+  }, {
+    key: "destroy",
+    value: function destroy() {
+      this.$editable.off();
+    }
+  }, {
+    key: "handleKeyMap",
+    value: function handleKeyMap(event) {
+      var keyMap = this.options.keyMap[env.isMac ? 'mac' : 'pc'];
+      var keys = [];
+
+      if (event.metaKey) {
+        keys.push('CMD');
+      }
+
+      if (event.ctrlKey && !event.altKey) {
+        keys.push('CTRL');
+      }
+
+      if (event.shiftKey) {
+        keys.push('SHIFT');
+      }
+
+      var keyName = core_key.nameFromCode[event.keyCode];
+
+      if (keyName) {
+        keys.push(keyName);
+      }
+
+      var eventName = keyMap[keys.join('+')];
+
+      if (keyName === 'TAB' && !this.options.tabDisable) {
+        this.afterCommand();
+      } else if (eventName) {
+        if (this.context.invoke(eventName) !== false) {
+          event.preventDefault(); // if keyMap action was invoked
+
+          return true;
+        }
+      } else if (core_key.isEdit(event.keyCode)) {
+        this.afterCommand();
+      }
+
+      return false;
+    }
+  }, {
+    key: "preventDefaultEditableShortCuts",
+    value: function preventDefaultEditableShortCuts(event) {
+      // B(Bold, 66) / I(Italic, 73) / U(Underline, 85)
+      if ((event.ctrlKey || event.metaKey) && lists.contains([66, 73, 85], event.keyCode)) {
+        event.preventDefault();
+      }
+    }
+  }, {
+    key: "isLimited",
+    value: function isLimited(pad, event) {
+      pad = pad || 0;
+
+      if (typeof event !== 'undefined') {
+        if (core_key.isMove(event.keyCode) || core_key.isNavigation(event.keyCode) || event.ctrlKey || event.metaKey || lists.contains([core_key.code.BACKSPACE, core_key.code.DELETE], event.keyCode)) {
+          return false;
+        }
+      }
+
+      if (this.options.maxTextLength > 0) {
+        if (this.$editable.text().length + pad > this.options.maxTextLength) {
+          return true;
+        }
+      }
+
+      return false;
+    }
+    /**
+     * create range
+     * @return {WrappedRange}
+     */
+
+  }, {
+    key: "createRange",
+    value: function createRange() {
+      this.focus();
+      this.setLastRange();
+      return this.getLastRange();
+    }
+    /**
+     * create a new range from the list of elements
+     *
+     * @param {list} dom element list
+     * @return {WrappedRange}
+     */
+
+  }, {
+    key: "createRangeFromList",
+    value: function createRangeFromList(lst) {
+      var startRange = range.createFromNodeBefore(lists.head(lst));
+      var startPoint = startRange.getStartPoint();
+      var endRange = range.createFromNodeAfter(lists.last(lst));
+      var endPoint = endRange.getEndPoint();
+      return range.create(startPoint.node, startPoint.offset, endPoint.node, endPoint.offset);
+    }
+    /**
+     * set the last range
+     *
+     * if given rng is exist, set rng as the last range
+     * or create a new range at the end of the document
+     *
+     * @param {WrappedRange} rng
+     */
+
+  }, {
+    key: "setLastRange",
+    value: function setLastRange(rng) {
+      if (rng) {
+        this.lastRange = rng;
+      } else {
+        this.lastRange = range.create(this.editable);
+
+        if (external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(this.lastRange.sc).closest('.note-editable').length === 0) {
+          this.lastRange = range.createFromBodyElement(this.editable);
+        }
+      }
+    }
+    /**
+     * get the last range
+     *
+     * if there is a saved last range, return it
+     * or create a new range and return it
+     *
+     * @return {WrappedRange}
+     */
+
+  }, {
+    key: "getLastRange",
+    value: function getLastRange() {
+      if (!this.lastRange) {
+        this.setLastRange();
+      }
+
+      return this.lastRange;
+    }
+    /**
+     * saveRange
+     *
+     * save current range
+     *
+     * @param {Boolean} [thenCollapse=false]
+     */
+
+  }, {
+    key: "saveRange",
+    value: function saveRange(thenCollapse) {
+      if (thenCollapse) {
+        this.getLastRange().collapse().select();
+      }
+    }
+    /**
+     * restoreRange
+     *
+     * restore lately range
+     */
+
+  }, {
+    key: "restoreRange",
+    value: function restoreRange() {
+      if (this.lastRange) {
+        this.lastRange.select();
+        this.focus();
+      }
+    }
+  }, {
+    key: "saveTarget",
+    value: function saveTarget(node) {
+      this.$editable.data('target', node);
+    }
+  }, {
+    key: "clearTarget",
+    value: function clearTarget() {
+      this.$editable.removeData('target');
+    }
+  }, {
+    key: "restoreTarget",
+    value: function restoreTarget() {
+      return this.$editable.data('target');
+    }
+    /**
+     * currentStyle
+     *
+     * current style
+     * @return {Object|Boolean} unfocus
+     */
+
+  }, {
+    key: "currentStyle",
+    value: function currentStyle() {
+      var rng = range.create();
+
+      if (rng) {
+        rng = rng.normalize();
+      }
+
+      return rng ? this.style.current(rng) : this.style.fromNode(this.$editable);
+    }
+    /**
+     * style from node
+     *
+     * @param {jQuery} $node
+     * @return {Object}
+     */
+
+  }, {
+    key: "styleFromNode",
+    value: function styleFromNode($node) {
+      return this.style.fromNode($node);
+    }
+    /**
+     * undo
+     */
+
+  }, {
+    key: "undo",
+    value: function undo() {
+      this.context.triggerEvent('before.command', this.$editable.html());
+      this.history.undo();
+      this.context.triggerEvent('change', this.$editable.html(), this.$editable);
+    }
+    /*
+    * commit
+    */
+
+  }, {
+    key: "commit",
+    value: function commit() {
+      this.context.triggerEvent('before.command', this.$editable.html());
+      this.history.commit();
+      this.context.triggerEvent('change', this.$editable.html(), this.$editable);
+    }
+    /**
+     * redo
+     */
+
+  }, {
+    key: "redo",
+    value: function redo() {
+      this.context.triggerEvent('before.command', this.$editable.html());
+      this.history.redo();
+      this.context.triggerEvent('change', this.$editable.html(), this.$editable);
+    }
+    /**
+     * before command
+     */
+
+  }, {
+    key: "beforeCommand",
+    value: function beforeCommand() {
+      this.context.triggerEvent('before.command', this.$editable.html()); // Set styleWithCSS before run a command
+
+      document.execCommand('styleWithCSS', false, this.options.styleWithCSS); // keep focus on editable before command execution
+
+      this.focus();
+    }
+    /**
+     * after command
+     * @param {Boolean} isPreventTrigger
+     */
+
+  }, {
+    key: "afterCommand",
+    value: function afterCommand(isPreventTrigger) {
+      this.normalizeContent();
+      this.history.recordUndo();
+
+      if (!isPreventTrigger) {
+        this.context.triggerEvent('change', this.$editable.html(), this.$editable);
+      }
+    }
+    /**
+     * handle tab key
+     */
+
+  }, {
+    key: "tab",
+    value: function tab() {
+      var rng = this.getLastRange();
+
+      if (rng.isCollapsed() && rng.isOnCell()) {
+        this.table.tab(rng);
+      } else {
+        if (this.options.tabSize === 0) {
+          return false;
+        }
+
+        if (!this.isLimited(this.options.tabSize)) {
+          this.beforeCommand();
+          this.typing.insertTab(rng, this.options.tabSize);
+          this.afterCommand();
+        }
+      }
+    }
+    /**
+     * handle shift+tab key
+     */
+
+  }, {
+    key: "untab",
+    value: function untab() {
+      var rng = this.getLastRange();
+
+      if (rng.isCollapsed() && rng.isOnCell()) {
+        this.table.tab(rng, true);
+      } else {
+        if (this.options.tabSize === 0) {
+          return false;
+        }
+      }
+    }
+    /**
+     * run given function between beforeCommand and afterCommand
+     */
+
+  }, {
+    key: "wrapCommand",
+    value: function wrapCommand(fn) {
+      return function () {
+        this.beforeCommand();
+        fn.apply(this, arguments);
+        this.afterCommand();
+      };
+    }
+    /**
+     * insert image
+     *
+     * @param {String} src
+     * @param {String|Function} param
+     * @return {Promise}
+     */
+
+  }, {
+    key: "insertImage",
+    value: function insertImage(src, param) {
+      var _this3 = this;
+
+      return createImage(src, param).then(function ($image) {
+        _this3.beforeCommand();
+
+        if (typeof param === 'function') {
+          param($image);
+        } else {
+          if (typeof param === 'string') {
+            $image.attr('data-filename', param);
+          }
+
+          $image.css('width', Math.min(_this3.$editable.width(), $image.width()));
+        }
+
+        $image.show();
+
+        _this3.getLastRange().insertNode($image[0]);
+
+        _this3.setLastRange(range.createFromNodeAfter($image[0]).select());
+
+        _this3.afterCommand();
+      }).fail(function (e) {
+        _this3.context.triggerEvent('image.upload.error', e);
+      });
+    }
+    /**
+     * insertImages
+     * @param {File[]} files
+     */
+
+  }, {
+    key: "insertImagesAsDataURL",
+    value: function insertImagesAsDataURL(files) {
+      var _this4 = this;
+
+      external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.each(files, function (idx, file) {
+        var filename = file.name;
+
+        if (_this4.options.maximumImageFileSize && _this4.options.maximumImageFileSize < file.size) {
+          _this4.context.triggerEvent('image.upload.error', _this4.lang.image.maximumFileSizeError);
+        } else {
+          readFileAsDataURL(file).then(function (dataURL) {
+            return _this4.insertImage(dataURL, filename);
+          }).fail(function () {
+            _this4.context.triggerEvent('image.upload.error');
+          });
+        }
+      });
+    }
+    /**
+     * insertImagesOrCallback
+     * @param {File[]} files
+     */
+
+  }, {
+    key: "insertImagesOrCallback",
+    value: function insertImagesOrCallback(files) {
+      var callbacks = this.options.callbacks; // If onImageUpload set,
+
+      if (callbacks.onImageUpload) {
+        this.context.triggerEvent('image.upload', files); // else insert Image as dataURL
+      } else {
+        this.insertImagesAsDataURL(files);
+      }
+    }
+    /**
+     * return selected plain text
+     * @return {String} text
+     */
+
+  }, {
+    key: "getSelectedText",
+    value: function getSelectedText() {
+      var rng = this.getLastRange(); // if range on anchor, expand range with anchor
+
+      if (rng.isOnAnchor()) {
+        rng = range.createFromNode(dom.ancestor(rng.sc, dom.isAnchor));
+      }
+
+      return rng.toString();
+    }
+  }, {
+    key: "onFormatBlock",
+    value: function onFormatBlock(tagName, $target) {
+      // [workaround] for MSIE, IE need `<`
+      document.execCommand('FormatBlock', false, env.isMSIE ? '<' + tagName + '>' : tagName); // support custom class
+
+      if ($target && $target.length) {
+        // find the exact element has given tagName
+        if ($target[0].tagName.toUpperCase() !== tagName.toUpperCase()) {
+          $target = $target.find(tagName);
+        }
+
+        if ($target && $target.length) {
+          var className = $target[0].className || '';
+
+          if (className) {
+            var currentRange = this.createRange();
+            var $parent = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()([currentRange.sc, currentRange.ec]).closest(tagName);
+            $parent.addClass(className);
+          }
+        }
+      }
+    }
+  }, {
+    key: "formatPara",
+    value: function formatPara() {
+      this.formatBlock('P');
+    }
+  }, {
+    key: "fontStyling",
+    value: function fontStyling(target, value) {
+      var rng = this.getLastRange();
+
+      if (rng !== '') {
+        var spans = this.style.styleNodes(rng);
+        this.$editor.find('.note-status-output').html('');
+        external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(spans).css(target, value); // [workaround] added styled bogus span for style
+        //  - also bogus character needed for cursor position
+
+        if (rng.isCollapsed()) {
+          var firstSpan = lists.head(spans);
+
+          if (firstSpan && !dom.nodeLength(firstSpan)) {
+            firstSpan.innerHTML = dom.ZERO_WIDTH_NBSP_CHAR;
+            range.createFromNode(firstSpan.firstChild).select();
+            this.setLastRange();
+            this.$editable.data(KEY_BOGUS, firstSpan);
+          }
+        } else {
+          this.setLastRange(this.createRangeFromList(spans).select());
+        }
+      } else {
+        var noteStatusOutput = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.now();
+        this.$editor.find('.note-status-output').html('<div id="note-status-output-' + noteStatusOutput + '" class="alert alert-info">' + this.lang.output.noSelection + '</div>');
+        setTimeout(function () {
+          external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()('#note-status-output-' + noteStatusOutput).remove();
+        }, 5000);
+      }
+    }
+    /**
+     * unlink
+     *
+     * @type command
+     */
+
+  }, {
+    key: "unlink",
+    value: function unlink() {
+      var rng = this.getLastRange();
+
+      if (rng.isOnAnchor()) {
+        var anchor = dom.ancestor(rng.sc, dom.isAnchor);
+        rng = range.createFromNode(anchor);
+        rng.select();
+        this.setLastRange();
+        this.beforeCommand();
+        document.execCommand('unlink');
+        this.afterCommand();
+      }
+    }
+    /**
+     * returns link info
+     *
+     * @return {Object}
+     * @return {WrappedRange} return.range
+     * @return {String} return.text
+     * @return {Boolean} [return.isNewWindow=true]
+     * @return {String} [return.url=""]
+     */
+
+  }, {
+    key: "getLinkInfo",
+    value: function getLinkInfo() {
+      var rng = this.getLastRange().expand(dom.isAnchor); // Get the first anchor on range(for edit).
+
+      var $anchor = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(lists.head(rng.nodes(dom.isAnchor)));
+      var linkInfo = {
+        range: rng,
+        text: rng.toString(),
+        url: $anchor.length ? $anchor.attr('href') : ''
+      }; // When anchor exists,
+
+      if ($anchor.length) {
+        // Set isNewWindow by checking its target.
+        linkInfo.isNewWindow = $anchor.attr('target') === '_blank';
+      }
+
+      return linkInfo;
+    }
+  }, {
+    key: "addRow",
+    value: function addRow(position) {
+      var rng = this.getLastRange(this.$editable);
+
+      if (rng.isCollapsed() && rng.isOnCell()) {
+        this.beforeCommand();
+        this.table.addRow(rng, position);
+        this.afterCommand();
+      }
+    }
+  }, {
+    key: "addCol",
+    value: function addCol(position) {
+      var rng = this.getLastRange(this.$editable);
+
+      if (rng.isCollapsed() && rng.isOnCell()) {
+        this.beforeCommand();
+        this.table.addCol(rng, position);
+        this.afterCommand();
+      }
+    }
+  }, {
+    key: "deleteRow",
+    value: function deleteRow() {
+      var rng = this.getLastRange(this.$editable);
+
+      if (rng.isCollapsed() && rng.isOnCell()) {
+        this.beforeCommand();
+        this.table.deleteRow(rng);
+        this.afterCommand();
+      }
+    }
+  }, {
+    key: "deleteCol",
+    value: function deleteCol() {
+      var rng = this.getLastRange(this.$editable);
+
+      if (rng.isCollapsed() && rng.isOnCell()) {
+        this.beforeCommand();
+        this.table.deleteCol(rng);
+        this.afterCommand();
+      }
+    }
+  }, {
+    key: "deleteTable",
+    value: function deleteTable() {
+      var rng = this.getLastRange(this.$editable);
+
+      if (rng.isCollapsed() && rng.isOnCell()) {
+        this.beforeCommand();
+        this.table.deleteTable(rng);
+        this.afterCommand();
+      }
+    }
+    /**
+     * @param {Position} pos
+     * @param {jQuery} $target - target element
+     * @param {Boolean} [bKeepRatio] - keep ratio
+     */
+
+  }, {
+    key: "resizeTo",
+    value: function resizeTo(pos, $target, bKeepRatio) {
+      var imageSize;
+
+      if (bKeepRatio) {
+        var newRatio = pos.y / pos.x;
+        var ratio = $target.data('ratio');
+        imageSize = {
+          width: ratio > newRatio ? pos.x : pos.y / ratio,
+          height: ratio > newRatio ? pos.x * ratio : pos.y
+        };
+      } else {
+        imageSize = {
+          width: pos.x,
+          height: pos.y
+        };
+      }
+
+      $target.css(imageSize);
+    }
+    /**
+     * returns whether editable area has focus or not.
+     */
+
+  }, {
+    key: "hasFocus",
+    value: function hasFocus() {
+      return this.$editable.is(':focus');
+    }
+    /**
+     * set focus
+     */
+
+  }, {
+    key: "focus",
+    value: function focus() {
+      // [workaround] Screen will move when page is scolled in IE.
+      //  - do focus when not focused
+      if (!this.hasFocus()) {
+        this.$editable.focus();
+      }
+    }
+    /**
+     * returns whether contents is empty or not.
+     * @return {Boolean}
+     */
+
+  }, {
+    key: "isEmpty",
+    value: function isEmpty() {
+      return dom.isEmpty(this.$editable[0]) || dom.emptyPara === this.$editable.html();
+    }
+    /**
+     * Removes all contents and restores the editable instance to an _emptyPara_.
+     */
+
+  }, {
+    key: "empty",
+    value: function empty() {
+      this.context.invoke('code', dom.emptyPara);
+    }
+    /**
+     * normalize content
+     */
+
+  }, {
+    key: "normalizeContent",
+    value: function normalizeContent() {
+      this.$editable[0].normalize();
+    }
+  }]);
+
+  return Editor;
+}();
+
+
+// CONCATENATED MODULE: ./src/js/base/module/Clipboard.js
+function Clipboard_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function Clipboard_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function Clipboard_createClass(Constructor, protoProps, staticProps) { if (protoProps) Clipboard_defineProperties(Constructor.prototype, protoProps); if (staticProps) Clipboard_defineProperties(Constructor, staticProps); return Constructor; }
+
+
+
+var Clipboard_Clipboard = /*#__PURE__*/function () {
+  function Clipboard(context) {
+    Clipboard_classCallCheck(this, Clipboard);
+
+    this.context = context;
+    this.$editable = context.layoutInfo.editable;
+  }
+
+  Clipboard_createClass(Clipboard, [{
+    key: "initialize",
+    value: function initialize() {
+      this.$editable.on('paste', this.pasteByEvent.bind(this));
+    }
+    /**
+     * paste by clipboard event
+     *
+     * @param {Event} event
+     */
+
+  }, {
+    key: "pasteByEvent",
+    value: function pasteByEvent(event) {
+      var _this = this;
+
+      var clipboardData = event.originalEvent.clipboardData;
+
+      if (clipboardData && clipboardData.items && clipboardData.items.length) {
+        var item = clipboardData.items.length > 1 ? clipboardData.items[1] : lists.head(clipboardData.items);
+
+        if (item.kind === 'file' && item.type.indexOf('image/') !== -1) {
+          // paste img file
+          this.context.invoke('editor.insertImagesOrCallback', [item.getAsFile()]);
+          event.preventDefault();
+        } else if (item.kind === 'string') {
+          // paste text with maxTextLength check
+          if (this.context.invoke('editor.isLimited', clipboardData.getData('Text').length)) {
+            event.preventDefault();
+          }
+        }
+      } else if (window.clipboardData) {
+        // for IE
+        var text = window.clipboardData.getData('text');
+
+        if (this.context.invoke('editor.isLimited', text.length)) {
+          event.preventDefault();
+        }
+      } // Call editor.afterCommand after proceeding default event handler
+
+
+      setTimeout(function () {
+        _this.context.invoke('editor.afterCommand');
+      }, 10);
+    }
+  }]);
+
+  return Clipboard;
+}();
+
+
+// CONCATENATED MODULE: ./src/js/base/module/Dropzone.js
+function Dropzone_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function Dropzone_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function Dropzone_createClass(Constructor, protoProps, staticProps) { if (protoProps) Dropzone_defineProperties(Constructor.prototype, protoProps); if (staticProps) Dropzone_defineProperties(Constructor, staticProps); return Constructor; }
+
+
+
+var Dropzone_Dropzone = /*#__PURE__*/function () {
+  function Dropzone(context) {
+    Dropzone_classCallCheck(this, Dropzone);
+
+    this.context = context;
+    this.$eventListener = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(document);
+    this.$editor = context.layoutInfo.editor;
+    this.$editable = context.layoutInfo.editable;
+    this.options = context.options;
+    this.lang = this.options.langInfo;
+    this.documentEventHandlers = {};
+    this.$dropzone = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(['<div class="note-dropzone">', '<div class="note-dropzone-message"></div>', '</div>'].join('')).prependTo(this.$editor);
+  }
+  /**
+   * attach Drag and Drop Events
+   */
+
+
+  Dropzone_createClass(Dropzone, [{
+    key: "initialize",
+    value: function initialize() {
+      if (this.options.disableDragAndDrop) {
+        // prevent default drop event
+        this.documentEventHandlers.onDrop = function (e) {
+          e.preventDefault();
+        }; // do not consider outside of dropzone
+
+
+        this.$eventListener = this.$dropzone;
+        this.$eventListener.on('drop', this.documentEventHandlers.onDrop);
+      } else {
+        this.attachDragAndDropEvent();
+      }
+    }
+    /**
+     * attach Drag and Drop Events
+     */
+
+  }, {
+    key: "attachDragAndDropEvent",
+    value: function attachDragAndDropEvent() {
+      var _this = this;
+
+      var collection = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()();
+      var $dropzoneMessage = this.$dropzone.find('.note-dropzone-message');
+
+      this.documentEventHandlers.onDragenter = function (e) {
+        var isCodeview = _this.context.invoke('codeview.isActivated');
+
+        var hasEditorSize = _this.$editor.width() > 0 && _this.$editor.height() > 0;
+
+        if (!isCodeview && !collection.length && hasEditorSize) {
+          _this.$editor.addClass('dragover');
+
+          _this.$dropzone.width(_this.$editor.width());
+
+          _this.$dropzone.height(_this.$editor.height());
+
+          $dropzoneMessage.text(_this.lang.image.dragImageHere);
+        }
+
+        collection = collection.add(e.target);
+      };
+
+      this.documentEventHandlers.onDragleave = function (e) {
+        collection = collection.not(e.target); // If nodeName is BODY, then just make it over (fix for IE)
+
+        if (!collection.length || e.target.nodeName === 'BODY') {
+          collection = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()();
+
+          _this.$editor.removeClass('dragover');
+        }
+      };
+
+      this.documentEventHandlers.onDrop = function () {
+        collection = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()();
+
+        _this.$editor.removeClass('dragover');
+      }; // show dropzone on dragenter when dragging a object to document
+      // -but only if the editor is visible, i.e. has a positive width and height
+
+
+      this.$eventListener.on('dragenter', this.documentEventHandlers.onDragenter).on('dragleave', this.documentEventHandlers.onDragleave).on('drop', this.documentEventHandlers.onDrop); // change dropzone's message on hover.
+
+      this.$dropzone.on('dragenter', function () {
+        _this.$dropzone.addClass('hover');
+
+        $dropzoneMessage.text(_this.lang.image.dropImage);
+      }).on('dragleave', function () {
+        _this.$dropzone.removeClass('hover');
+
+        $dropzoneMessage.text(_this.lang.image.dragImageHere);
+      }); // attach dropImage
+
+      this.$dropzone.on('drop', function (event) {
+        var dataTransfer = event.originalEvent.dataTransfer; // stop the browser from opening the dropped content
+
+        event.preventDefault();
+
+        if (dataTransfer && dataTransfer.files && dataTransfer.files.length) {
+          _this.$editable.focus();
+
+          _this.context.invoke('editor.insertImagesOrCallback', dataTransfer.files);
+        } else {
+          external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.each(dataTransfer.types, function (idx, type) {
+            // skip moz-specific types
+            if (type.toLowerCase().indexOf('_moz_') > -1) {
+              return;
+            }
+
+            var content = dataTransfer.getData(type);
+
+            if (type.toLowerCase().indexOf('text') > -1) {
+              _this.context.invoke('editor.pasteHTML', content);
+            } else {
+              external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(content).each(function (idx, item) {
+                _this.context.invoke('editor.insertNode', item);
+              });
+            }
+          });
+        }
+      }).on('dragover', false); // prevent default dragover event
+    }
+  }, {
+    key: "destroy",
+    value: function destroy() {
+      var _this2 = this;
+
+      Object.keys(this.documentEventHandlers).forEach(function (key) {
+        _this2.$eventListener.off(key.substr(2).toLowerCase(), _this2.documentEventHandlers[key]);
+      });
+      this.documentEventHandlers = {};
+    }
+  }]);
+
+  return Dropzone;
+}();
+
+
+// CONCATENATED MODULE: ./src/js/base/module/Codeview.js
+function _createForOfIteratorHelper(o) { if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (o = _unsupportedIterableToArray(o))) { var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var it, normalCompletion = true, didErr = false, err; return { s: function s() { it = o[Symbol.iterator](); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }
+
+function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(n); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
+
+function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
+
+function Codeview_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function Codeview_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function Codeview_createClass(Constructor, protoProps, staticProps) { if (protoProps) Codeview_defineProperties(Constructor.prototype, protoProps); if (staticProps) Codeview_defineProperties(Constructor, staticProps); return Constructor; }
+
+
+
+/**
+ * @class Codeview
+ */
+
+var Codeview_CodeView = /*#__PURE__*/function () {
+  function CodeView(context) {
+    Codeview_classCallCheck(this, CodeView);
+
+    this.context = context;
+    this.$editor = context.layoutInfo.editor;
+    this.$editable = context.layoutInfo.editable;
+    this.$codable = context.layoutInfo.codable;
+    this.options = context.options;
+    this.CodeMirrorConstructor = window.CodeMirror;
+
+    if (this.options.codemirror.CodeMirrorConstructor) {
+      this.CodeMirrorConstructor = this.options.codemirror.CodeMirrorConstructor;
+    }
+  }
+
+  Codeview_createClass(CodeView, [{
+    key: "sync",
+    value: function sync(html) {
+      var isCodeview = this.isActivated();
+      var CodeMirror = this.CodeMirrorConstructor;
+
+      if (isCodeview) {
+        if (html) {
+          if (CodeMirror) {
+            this.$codable.data('cmEditor').getDoc().setValue(html);
+          } else {
+            this.$codable.val(html);
+          }
+        } else {
+          if (CodeMirror) {
+            this.$codable.data('cmEditor').save();
+          }
+        }
+      }
+    }
+  }, {
+    key: "initialize",
+    value: function initialize() {
+      var _this = this;
+
+      this.$codable.on('keyup', function (event) {
+        if (event.keyCode === core_key.code.ESCAPE) {
+          _this.deactivate();
+        }
+      });
+    }
+    /**
+     * @return {Boolean}
+     */
+
+  }, {
+    key: "isActivated",
+    value: function isActivated() {
+      return this.$editor.hasClass('codeview');
+    }
+    /**
+     * toggle codeview
+     */
+
+  }, {
+    key: "toggle",
+    value: function toggle() {
+      if (this.isActivated()) {
+        this.deactivate();
+      } else {
+        this.activate();
+      }
+
+      this.context.triggerEvent('codeview.toggled');
+    }
+    /**
+     * purify input value
+     * @param value
+     * @returns {*}
+     */
+
+  }, {
+    key: "purify",
+    value: function purify(value) {
+      if (this.options.codeviewFilter) {
+        // filter code view regex
+        value = value.replace(this.options.codeviewFilterRegex, ''); // allow specific iframe tag
+
+        if (this.options.codeviewIframeFilter) {
+          var whitelist = this.options.codeviewIframeWhitelistSrc.concat(this.options.codeviewIframeWhitelistSrcBase);
+          value = value.replace(/(<iframe.*?>.*?(?:<\/iframe>)?)/gi, function (tag) {
+            // remove if src attribute is duplicated
+            if (/<.+src(?==?('|"|\s)?)[\s\S]+src(?=('|"|\s)?)[^>]*?>/i.test(tag)) {
+              return '';
+            }
+
+            var _iterator = _createForOfIteratorHelper(whitelist),
+                _step;
+
+            try {
+              for (_iterator.s(); !(_step = _iterator.n()).done;) {
+                var src = _step.value;
+
+                // pass if src is trusted
+                if (new RegExp('src="(https?:)?\/\/' + src.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') + '\/(.+)"').test(tag)) {
+                  return tag;
+                }
+              }
+            } catch (err) {
+              _iterator.e(err);
+            } finally {
+              _iterator.f();
+            }
+
+            return '';
+          });
+        }
+      }
+
+      return value;
+    }
+    /**
+     * activate code view
+     */
+
+  }, {
+    key: "activate",
+    value: function activate() {
+      var _this2 = this;
+
+      var CodeMirror = this.CodeMirrorConstructor;
+      this.$codable.val(dom.html(this.$editable, this.options.prettifyHtml));
+      this.$codable.height(this.$editable.height());
+      this.context.invoke('toolbar.updateCodeview', true);
+      this.context.invoke('airPopover.updateCodeview', true);
+      this.$editor.addClass('codeview');
+      this.$codable.focus(); // activate CodeMirror as codable
+
+      if (CodeMirror) {
+        var cmEditor = CodeMirror.fromTextArea(this.$codable[0], this.options.codemirror); // CodeMirror TernServer
+
+        if (this.options.codemirror.tern) {
+          var server = new CodeMirror.TernServer(this.options.codemirror.tern);
+          cmEditor.ternServer = server;
+          cmEditor.on('cursorActivity', function (cm) {
+            server.updateArgHints(cm);
+          });
+        }
+
+        cmEditor.on('blur', function (event) {
+          _this2.context.triggerEvent('blur.codeview', cmEditor.getValue(), event);
+        });
+        cmEditor.on('change', function () {
+          _this2.context.triggerEvent('change.codeview', cmEditor.getValue(), cmEditor);
+        }); // CodeMirror hasn't Padding.
+
+        cmEditor.setSize(null, this.$editable.outerHeight());
+        this.$codable.data('cmEditor', cmEditor);
+      } else {
+        this.$codable.on('blur', function (event) {
+          _this2.context.triggerEvent('blur.codeview', _this2.$codable.val(), event);
+        });
+        this.$codable.on('input', function () {
+          _this2.context.triggerEvent('change.codeview', _this2.$codable.val(), _this2.$codable);
+        });
+      }
+    }
+    /**
+     * deactivate code view
+     */
+
+  }, {
+    key: "deactivate",
+    value: function deactivate() {
+      var CodeMirror = this.CodeMirrorConstructor; // deactivate CodeMirror as codable
+
+      if (CodeMirror) {
+        var cmEditor = this.$codable.data('cmEditor');
+        this.$codable.val(cmEditor.getValue());
+        cmEditor.toTextArea();
+      }
+
+      var value = this.purify(dom.value(this.$codable, this.options.prettifyHtml) || dom.emptyPara);
+      var isChange = this.$editable.html() !== value;
+      this.$editable.html(value);
+      this.$editable.height(this.options.height ? this.$codable.height() : 'auto');
+      this.$editor.removeClass('codeview');
+
+      if (isChange) {
+        this.context.triggerEvent('change', this.$editable.html(), this.$editable);
+      }
+
+      this.$editable.focus();
+      this.context.invoke('toolbar.updateCodeview', false);
+      this.context.invoke('airPopover.updateCodeview', false);
+    }
+  }, {
+    key: "destroy",
+    value: function destroy() {
+      if (this.isActivated()) {
+        this.deactivate();
+      }
+    }
+  }]);
+
+  return CodeView;
+}();
+
+
+// CONCATENATED MODULE: ./src/js/base/module/Statusbar.js
+function Statusbar_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function Statusbar_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function Statusbar_createClass(Constructor, protoProps, staticProps) { if (protoProps) Statusbar_defineProperties(Constructor.prototype, protoProps); if (staticProps) Statusbar_defineProperties(Constructor, staticProps); return Constructor; }
+
+
+var EDITABLE_PADDING = 24;
+
+var Statusbar_Statusbar = /*#__PURE__*/function () {
+  function Statusbar(context) {
+    Statusbar_classCallCheck(this, Statusbar);
+
+    this.$document = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(document);
+    this.$statusbar = context.layoutInfo.statusbar;
+    this.$editable = context.layoutInfo.editable;
+    this.options = context.options;
+  }
+
+  Statusbar_createClass(Statusbar, [{
+    key: "initialize",
+    value: function initialize() {
+      var _this = this;
+
+      if (this.options.airMode || this.options.disableResizeEditor) {
+        this.destroy();
+        return;
+      }
+
+      this.$statusbar.on('mousedown', function (event) {
+        event.preventDefault();
+        event.stopPropagation();
+
+        var editableTop = _this.$editable.offset().top - _this.$document.scrollTop();
+
+        var onMouseMove = function onMouseMove(event) {
+          var height = event.clientY - (editableTop + EDITABLE_PADDING);
+          height = _this.options.minheight > 0 ? Math.max(height, _this.options.minheight) : height;
+          height = _this.options.maxHeight > 0 ? Math.min(height, _this.options.maxHeight) : height;
+
+          _this.$editable.height(height);
+        };
+
+        _this.$document.on('mousemove', onMouseMove).one('mouseup', function () {
+          _this.$document.off('mousemove', onMouseMove);
+        });
+      });
+    }
+  }, {
+    key: "destroy",
+    value: function destroy() {
+      this.$statusbar.off();
+      this.$statusbar.addClass('locked');
+    }
+  }]);
+
+  return Statusbar;
+}();
+
+
+// CONCATENATED MODULE: ./src/js/base/module/Fullscreen.js
+function Fullscreen_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function Fullscreen_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function Fullscreen_createClass(Constructor, protoProps, staticProps) { if (protoProps) Fullscreen_defineProperties(Constructor.prototype, protoProps); if (staticProps) Fullscreen_defineProperties(Constructor, staticProps); return Constructor; }
+
+
+
+var Fullscreen_Fullscreen = /*#__PURE__*/function () {
+  function Fullscreen(context) {
+    var _this = this;
+
+    Fullscreen_classCallCheck(this, Fullscreen);
+
+    this.context = context;
+    this.$editor = context.layoutInfo.editor;
+    this.$toolbar = context.layoutInfo.toolbar;
+    this.$editable = context.layoutInfo.editable;
+    this.$codable = context.layoutInfo.codable;
+    this.$window = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(window);
+    this.$scrollbar = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()('html, body');
+
+    this.onResize = function () {
+      _this.resizeTo({
+        h: _this.$window.height() - _this.$toolbar.outerHeight()
+      });
+    };
+  }
+
+  Fullscreen_createClass(Fullscreen, [{
+    key: "resizeTo",
+    value: function resizeTo(size) {
+      this.$editable.css('height', size.h);
+      this.$codable.css('height', size.h);
+
+      if (this.$codable.data('cmeditor')) {
+        this.$codable.data('cmeditor').setsize(null, size.h);
+      }
+    }
+    /**
+     * toggle fullscreen
+     */
+
+  }, {
+    key: "toggle",
+    value: function toggle() {
+      this.$editor.toggleClass('fullscreen');
+
+      if (this.isFullscreen()) {
+        this.$editable.data('orgHeight', this.$editable.css('height'));
+        this.$editable.data('orgMaxHeight', this.$editable.css('maxHeight'));
+        this.$editable.css('maxHeight', '');
+        this.$window.on('resize', this.onResize).trigger('resize');
+        this.$scrollbar.css('overflow', 'hidden');
+      } else {
+        this.$window.off('resize', this.onResize);
+        this.resizeTo({
+          h: this.$editable.data('orgHeight')
+        });
+        this.$editable.css('maxHeight', this.$editable.css('orgMaxHeight'));
+        this.$scrollbar.css('overflow', 'visible');
+      }
+
+      this.context.invoke('toolbar.updateFullscreen', this.isFullscreen());
+    }
+  }, {
+    key: "isFullscreen",
+    value: function isFullscreen() {
+      return this.$editor.hasClass('fullscreen');
+    }
+  }]);
+
+  return Fullscreen;
+}();
+
+
+// CONCATENATED MODULE: ./src/js/base/module/Handle.js
+function Handle_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function Handle_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function Handle_createClass(Constructor, protoProps, staticProps) { if (protoProps) Handle_defineProperties(Constructor.prototype, protoProps); if (staticProps) Handle_defineProperties(Constructor, staticProps); return Constructor; }
+
+
+
+
+var Handle_Handle = /*#__PURE__*/function () {
+  function Handle(context) {
+    var _this = this;
+
+    Handle_classCallCheck(this, Handle);
+
+    this.context = context;
+    this.$document = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(document);
+    this.$editingArea = context.layoutInfo.editingArea;
+    this.options = context.options;
+    this.lang = this.options.langInfo;
+    this.events = {
+      'summernote.mousedown': function summernoteMousedown(we, e) {
+        if (_this.update(e.target, e)) {
+          e.preventDefault();
+        }
+      },
+      'summernote.keyup summernote.scroll summernote.change summernote.dialog.shown': function summernoteKeyupSummernoteScrollSummernoteChangeSummernoteDialogShown() {
+        _this.update();
+      },
+      'summernote.disable summernote.blur': function summernoteDisableSummernoteBlur() {
+        _this.hide();
+      },
+      'summernote.codeview.toggled': function summernoteCodeviewToggled() {
+        _this.update();
+      }
+    };
+  }
+
+  Handle_createClass(Handle, [{
+    key: "initialize",
+    value: function initialize() {
+      var _this2 = this;
+
+      this.$handle = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(['<div class="note-handle">', '<div class="note-control-selection">', '<div class="note-control-selection-bg"></div>', '<div class="note-control-holder note-control-nw"></div>', '<div class="note-control-holder note-control-ne"></div>', '<div class="note-control-holder note-control-sw"></div>', '<div class="', this.options.disableResizeImage ? 'note-control-holder' : 'note-control-sizing', ' note-control-se"></div>', this.options.disableResizeImage ? '' : '<div class="note-control-selection-info"></div>', '</div>', '</div>'].join('')).prependTo(this.$editingArea);
+      this.$handle.on('mousedown', function (event) {
+        if (dom.isControlSizing(event.target)) {
+          event.preventDefault();
+          event.stopPropagation();
+
+          var $target = _this2.$handle.find('.note-control-selection').data('target');
+
+          var posStart = $target.offset();
+
+          var scrollTop = _this2.$document.scrollTop();
+
+          var onMouseMove = function onMouseMove(event) {
+            _this2.context.invoke('editor.resizeTo', {
+              x: event.clientX - posStart.left,
+              y: event.clientY - (posStart.top - scrollTop)
+            }, $target, !event.shiftKey);
+
+            _this2.update($target[0], event);
+          };
+
+          _this2.$document.on('mousemove', onMouseMove).one('mouseup', function (e) {
+            e.preventDefault();
+
+            _this2.$document.off('mousemove', onMouseMove);
+
+            _this2.context.invoke('editor.afterCommand');
+          });
+
+          if (!$target.data('ratio')) {
+            // original ratio.
+            $target.data('ratio', $target.height() / $target.width());
+          }
+        }
+      }); // Listen for scrolling on the handle overlay.
+
+      this.$handle.on('wheel', function (e) {
+        e.preventDefault();
+
+        _this2.update();
+      });
+    }
+  }, {
+    key: "destroy",
+    value: function destroy() {
+      this.$handle.remove();
+    }
+  }, {
+    key: "update",
+    value: function update(target, event) {
+      if (this.context.isDisabled()) {
+        return false;
+      }
+
+      var isImage = dom.isImg(target);
+      var $selection = this.$handle.find('.note-control-selection');
+      this.context.invoke('imagePopover.update', target, event);
+
+      if (isImage) {
+        var $image = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(target);
+        var position = $image.position();
+        var pos = {
+          left: position.left + parseInt($image.css('marginLeft'), 10),
+          top: position.top + parseInt($image.css('marginTop'), 10)
+        }; // exclude margin
+
+        var imageSize = {
+          w: $image.outerWidth(false),
+          h: $image.outerHeight(false)
+        };
+        $selection.css({
+          display: 'block',
+          left: pos.left,
+          top: pos.top,
+          width: imageSize.w,
+          height: imageSize.h
+        }).data('target', $image); // save current image element.
+
+        var origImageObj = new Image();
+        origImageObj.src = $image.attr('src');
+        var sizingText = imageSize.w + 'x' + imageSize.h + ' (' + this.lang.image.original + ': ' + origImageObj.width + 'x' + origImageObj.height + ')';
+        $selection.find('.note-control-selection-info').text(sizingText);
+        this.context.invoke('editor.saveTarget', target);
+      } else {
+        this.hide();
+      }
+
+      return isImage;
+    }
+    /**
+     * hide
+     *
+     * @param {jQuery} $handle
+     */
+
+  }, {
+    key: "hide",
+    value: function hide() {
+      this.context.invoke('editor.clearTarget');
+      this.$handle.children().hide();
+    }
+  }]);
+
+  return Handle;
+}();
+
+
+// CONCATENATED MODULE: ./src/js/base/module/AutoLink.js
+function AutoLink_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function AutoLink_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function AutoLink_createClass(Constructor, protoProps, staticProps) { if (protoProps) AutoLink_defineProperties(Constructor.prototype, protoProps); if (staticProps) AutoLink_defineProperties(Constructor, staticProps); return Constructor; }
+
+
+
+
+var defaultScheme = 'http://';
+var linkPattern = /^([A-Za-z][A-Za-z0-9+-.]*\:[\/]{2}|tel:|mailto:[A-Z0-9._%+-]+@)?(www\.)?(.+)$/i;
+
+var AutoLink_AutoLink = /*#__PURE__*/function () {
+  function AutoLink(context) {
+    var _this = this;
+
+    AutoLink_classCallCheck(this, AutoLink);
+
+    this.context = context;
+    this.options = context.options;
+    this.events = {
+      'summernote.keyup': function summernoteKeyup(we, e) {
+        if (!e.isDefaultPrevented()) {
+          _this.handleKeyup(e);
+        }
+      },
+      'summernote.keydown': function summernoteKeydown(we, e) {
+        _this.handleKeydown(e);
+      }
+    };
+  }
+
+  AutoLink_createClass(AutoLink, [{
+    key: "initialize",
+    value: function initialize() {
+      this.lastWordRange = null;
+    }
+  }, {
+    key: "destroy",
+    value: function destroy() {
+      this.lastWordRange = null;
+    }
+  }, {
+    key: "replace",
+    value: function replace() {
+      if (!this.lastWordRange) {
+        return;
+      }
+
+      var keyword = this.lastWordRange.toString();
+      var match = keyword.match(linkPattern);
+
+      if (match && (match[1] || match[2])) {
+        var link = match[1] ? keyword : defaultScheme + keyword;
+        var urlText = this.options.showDomainOnlyForAutolink ? keyword.replace(/^(?:https?:\/\/)?(?:tel?:?)?(?:mailto?:?)?(?:www\.)?/i, '').split('/')[0] : keyword;
+        var node = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()('<a />').html(urlText).attr('href', link)[0];
+
+        if (this.context.options.linkTargetBlank) {
+          external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(node).attr('target', '_blank');
+        }
+
+        this.lastWordRange.insertNode(node);
+        this.lastWordRange = null;
+        this.context.invoke('editor.focus');
+      }
+    }
+  }, {
+    key: "handleKeydown",
+    value: function handleKeydown(e) {
+      if (lists.contains([core_key.code.ENTER, core_key.code.SPACE], e.keyCode)) {
+        var wordRange = this.context.invoke('editor.createRange').getWordRange();
+        this.lastWordRange = wordRange;
+      }
+    }
+  }, {
+    key: "handleKeyup",
+    value: function handleKeyup(e) {
+      if (lists.contains([core_key.code.ENTER, core_key.code.SPACE], e.keyCode)) {
+        this.replace();
+      }
+    }
+  }]);
+
+  return AutoLink;
+}();
+
+
+// CONCATENATED MODULE: ./src/js/base/module/AutoSync.js
+function AutoSync_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function AutoSync_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function AutoSync_createClass(Constructor, protoProps, staticProps) { if (protoProps) AutoSync_defineProperties(Constructor.prototype, protoProps); if (staticProps) AutoSync_defineProperties(Constructor, staticProps); return Constructor; }
+
+
+/**
+ * textarea auto sync.
+ */
+
+var AutoSync_AutoSync = /*#__PURE__*/function () {
+  function AutoSync(context) {
+    var _this = this;
+
+    AutoSync_classCallCheck(this, AutoSync);
+
+    this.$note = context.layoutInfo.note;
+    this.events = {
+      'summernote.change': function summernoteChange() {
+        _this.$note.val(context.invoke('code'));
+      }
+    };
+  }
+
+  AutoSync_createClass(AutoSync, [{
+    key: "shouldInitialize",
+    value: function shouldInitialize() {
+      return dom.isTextarea(this.$note[0]);
+    }
+  }]);
+
+  return AutoSync;
+}();
+
+
+// CONCATENATED MODULE: ./src/js/base/module/AutoReplace.js
+function AutoReplace_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function AutoReplace_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function AutoReplace_createClass(Constructor, protoProps, staticProps) { if (protoProps) AutoReplace_defineProperties(Constructor.prototype, protoProps); if (staticProps) AutoReplace_defineProperties(Constructor, staticProps); return Constructor; }
+
+
+
+
+
+var AutoReplace_AutoReplace = /*#__PURE__*/function () {
+  function AutoReplace(context) {
+    var _this = this;
+
+    AutoReplace_classCallCheck(this, AutoReplace);
+
+    this.context = context;
+    this.options = context.options.replace || {};
+    this.keys = [core_key.code.ENTER, core_key.code.SPACE, core_key.code.PERIOD, core_key.code.COMMA, core_key.code.SEMICOLON, core_key.code.SLASH];
+    this.previousKeydownCode = null;
+    this.events = {
+      'summernote.keyup': function summernoteKeyup(we, e) {
+        if (!e.isDefaultPrevented()) {
+          _this.handleKeyup(e);
+        }
+      },
+      'summernote.keydown': function summernoteKeydown(we, e) {
+        _this.handleKeydown(e);
+      }
+    };
+  }
+
+  AutoReplace_createClass(AutoReplace, [{
+    key: "shouldInitialize",
+    value: function shouldInitialize() {
+      return !!this.options.match;
+    }
+  }, {
+    key: "initialize",
+    value: function initialize() {
+      this.lastWord = null;
+    }
+  }, {
+    key: "destroy",
+    value: function destroy() {
+      this.lastWord = null;
+    }
+  }, {
+    key: "replace",
+    value: function replace() {
+      if (!this.lastWord) {
+        return;
+      }
+
+      var self = this;
+      var keyword = this.lastWord.toString();
+      this.options.match(keyword, function (match) {
+        if (match) {
+          var node = '';
+
+          if (typeof match === 'string') {
+            node = dom.createText(match);
+          } else if (match instanceof jQuery) {
+            node = match[0];
+          } else if (match instanceof Node) {
+            node = match;
+          }
+
+          if (!node) return;
+          self.lastWord.insertNode(node);
+          self.lastWord = null;
+          self.context.invoke('editor.focus');
+        }
+      });
+    }
+  }, {
+    key: "handleKeydown",
+    value: function handleKeydown(e) {
+      // this forces it to remember the last whole word, even if multiple termination keys are pressed
+      // before the previous key is let go.
+      if (this.previousKeydownCode && lists.contains(this.keys, this.previousKeydownCode)) {
+        this.previousKeydownCode = e.keyCode;
+        return;
+      }
+
+      if (lists.contains(this.keys, e.keyCode)) {
+        var wordRange = this.context.invoke('editor.createRange').getWordRange();
+        this.lastWord = wordRange;
+      }
+
+      this.previousKeydownCode = e.keyCode;
+    }
+  }, {
+    key: "handleKeyup",
+    value: function handleKeyup(e) {
+      if (lists.contains(this.keys, e.keyCode)) {
+        this.replace();
+      }
+    }
+  }]);
+
+  return AutoReplace;
+}();
+
+
+// CONCATENATED MODULE: ./src/js/base/module/Placeholder.js
+function Placeholder_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function Placeholder_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function Placeholder_createClass(Constructor, protoProps, staticProps) { if (protoProps) Placeholder_defineProperties(Constructor.prototype, protoProps); if (staticProps) Placeholder_defineProperties(Constructor, staticProps); return Constructor; }
+
+
+
+var Placeholder_Placeholder = /*#__PURE__*/function () {
+  function Placeholder(context) {
+    var _this = this;
+
+    Placeholder_classCallCheck(this, Placeholder);
+
+    this.context = context;
+    this.$editingArea = context.layoutInfo.editingArea;
+    this.options = context.options;
+
+    if (this.options.inheritPlaceholder === true) {
+      // get placeholder value from the original element
+      this.options.placeholder = this.context.$note.attr('placeholder') || this.options.placeholder;
+    }
+
+    this.events = {
+      'summernote.init summernote.change': function summernoteInitSummernoteChange() {
+        _this.update();
+      },
+      'summernote.codeview.toggled': function summernoteCodeviewToggled() {
+        _this.update();
+      }
+    };
+  }
+
+  Placeholder_createClass(Placeholder, [{
+    key: "shouldInitialize",
+    value: function shouldInitialize() {
+      return !!this.options.placeholder;
+    }
+  }, {
+    key: "initialize",
+    value: function initialize() {
+      var _this2 = this;
+
+      this.$placeholder = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()('<div class="note-placeholder">');
+      this.$placeholder.on('click', function () {
+        _this2.context.invoke('focus');
+      }).html(this.options.placeholder).prependTo(this.$editingArea);
+      this.update();
+    }
+  }, {
+    key: "destroy",
+    value: function destroy() {
+      this.$placeholder.remove();
+    }
+  }, {
+    key: "update",
+    value: function update() {
+      var isShow = !this.context.invoke('codeview.isActivated') && this.context.invoke('editor.isEmpty');
+      this.$placeholder.toggle(isShow);
+    }
+  }]);
+
+  return Placeholder;
+}();
+
+
+// CONCATENATED MODULE: ./src/js/base/module/Buttons.js
+function Buttons_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function Buttons_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function Buttons_createClass(Constructor, protoProps, staticProps) { if (protoProps) Buttons_defineProperties(Constructor.prototype, protoProps); if (staticProps) Buttons_defineProperties(Constructor, staticProps); return Constructor; }
+
+
+
+
+
+
+var Buttons_Buttons = /*#__PURE__*/function () {
+  function Buttons(context) {
+    Buttons_classCallCheck(this, Buttons);
+
+    this.ui = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.summernote.ui;
+    this.context = context;
+    this.$toolbar = context.layoutInfo.toolbar;
+    this.options = context.options;
+    this.lang = this.options.langInfo;
+    this.invertedKeyMap = func.invertObject(this.options.keyMap[env.isMac ? 'mac' : 'pc']);
+  }
+
+  Buttons_createClass(Buttons, [{
+    key: "representShortcut",
+    value: function representShortcut(editorMethod) {
+      var shortcut = this.invertedKeyMap[editorMethod];
+
+      if (!this.options.shortcuts || !shortcut) {
+        return '';
+      }
+
+      if (env.isMac) {
+        shortcut = shortcut.replace('CMD', '⌘').replace('SHIFT', '⇧');
+      }
+
+      shortcut = shortcut.replace('BACKSLASH', '\\').replace('SLASH', '/').replace('LEFTBRACKET', '[').replace('RIGHTBRACKET', ']');
+      return ' (' + shortcut + ')';
+    }
+  }, {
+    key: "button",
+    value: function button(o) {
+      if (!this.options.tooltip && o.tooltip) {
+        delete o.tooltip;
+      }
+
+      o.container = this.options.container;
+      return this.ui.button(o);
+    }
+  }, {
+    key: "initialize",
+    value: function initialize() {
+      this.addToolbarButtons();
+      this.addImagePopoverButtons();
+      this.addLinkPopoverButtons();
+      this.addTablePopoverButtons();
+      this.fontInstalledMap = {};
+    }
+  }, {
+    key: "destroy",
+    value: function destroy() {
+      delete this.fontInstalledMap;
+    }
+  }, {
+    key: "isFontInstalled",
+    value: function isFontInstalled(name) {
+      if (!Object.prototype.hasOwnProperty.call(this.fontInstalledMap, name)) {
+        this.fontInstalledMap[name] = env.isFontInstalled(name) || lists.contains(this.options.fontNamesIgnoreCheck, name);
+      }
+
+      return this.fontInstalledMap[name];
+    }
+  }, {
+    key: "isFontDeservedToAdd",
+    value: function isFontDeservedToAdd(name) {
+      name = name.toLowerCase();
+      return name !== '' && this.isFontInstalled(name) && env.genericFontFamilies.indexOf(name) === -1;
+    }
+  }, {
+    key: "colorPalette",
+    value: function colorPalette(className, tooltip, backColor, foreColor) {
+      var _this = this;
+
+      return this.ui.buttonGroup({
+        className: 'note-color ' + className,
+        children: [this.button({
+          className: 'note-current-color-button',
+          contents: this.ui.icon(this.options.icons.font + ' note-recent-color'),
+          tooltip: tooltip,
+          click: function click(e) {
+            var $button = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(e.currentTarget);
+
+            if (backColor && foreColor) {
+              _this.context.invoke('editor.color', {
+                backColor: $button.attr('data-backColor'),
+                foreColor: $button.attr('data-foreColor')
+              });
+            } else if (backColor) {
+              _this.context.invoke('editor.color', {
+                backColor: $button.attr('data-backColor')
+              });
+            } else if (foreColor) {
+              _this.context.invoke('editor.color', {
+                foreColor: $button.attr('data-foreColor')
+              });
+            }
+          },
+          callback: function callback($button) {
+            var $recentColor = $button.find('.note-recent-color');
+
+            if (backColor) {
+              $recentColor.css('background-color', _this.options.colorButton.backColor);
+              $button.attr('data-backColor', _this.options.colorButton.backColor);
+            }
+
+            if (foreColor) {
+              $recentColor.css('color', _this.options.colorButton.foreColor);
+              $button.attr('data-foreColor', _this.options.colorButton.foreColor);
+            } else {
+              $recentColor.css('color', 'transparent');
+            }
+          }
+        }), this.button({
+          className: 'dropdown-toggle',
+          contents: this.ui.dropdownButtonContents('', this.options),
+          tooltip: this.lang.color.more,
+          data: {
+            toggle: 'dropdown'
+          }
+        }), this.ui.dropdown({
+          items: (backColor ? ['<div class="note-palette">', '<div class="note-palette-title">' + this.lang.color.background + '</div>', '<div>', '<button type="button" class="note-color-reset btn btn-light btn-default" data-event="backColor" data-value="transparent">', this.lang.color.transparent, '</button>', '</div>', '<div class="note-holder" data-event="backColor"><!-- back colors --></div>', '<div>', '<button type="button" class="note-color-select btn btn-light btn-default" data-event="openPalette" data-value="backColorPicker">', this.lang.color.cpSelect, '</button>', '<input type="color" id="backColorPicker" class="note-btn note-color-select-btn" value="' + this.options.colorButton.backColor + '" data-event="backColorPalette">', '</div>', '<div class="note-holder-custom" id="backColorPalette" data-event="backColor"></div>', '</div>'].join('') : '') + (foreColor ? ['<div class="note-palette">', '<div class="note-palette-title">' + this.lang.color.foreground + '</div>', '<div>', '<button type="button" class="note-color-reset btn btn-light btn-default" data-event="removeFormat" data-value="foreColor">', this.lang.color.resetToDefault, '</button>', '</div>', '<div class="note-holder" data-event="foreColor"><!-- fore colors --></div>', '<div>', '<button type="button" class="note-color-select btn btn-light btn-default" data-event="openPalette" data-value="foreColorPicker">', this.lang.color.cpSelect, '</button>', '<input type="color" id="foreColorPicker" class="note-btn note-color-select-btn" value="' + this.options.colorButton.foreColor + '" data-event="foreColorPalette">', '</div>', // Fix missing Div, Commented to find easily if it's wrong
+          '<div class="note-holder-custom" id="foreColorPalette" data-event="foreColor"></div>', '</div>'].join('') : ''),
+          callback: function callback($dropdown) {
+            $dropdown.find('.note-holder').each(function (idx, item) {
+              var $holder = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(item);
+              $holder.append(_this.ui.palette({
+                colors: _this.options.colors,
+                colorsName: _this.options.colorsName,
+                eventName: $holder.data('event'),
+                container: _this.options.container,
+                tooltip: _this.options.tooltip
+              }).render());
+            });
+            /* TODO: do we have to record recent custom colors within cookies? */
+
+            var customColors = [['#FFFFFF', '#FFFFFF', '#FFFFFF', '#FFFFFF', '#FFFFFF', '#FFFFFF', '#FFFFFF', '#FFFFFF']];
+            $dropdown.find('.note-holder-custom').each(function (idx, item) {
+              var $holder = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(item);
+              $holder.append(_this.ui.palette({
+                colors: customColors,
+                colorsName: customColors,
+                eventName: $holder.data('event'),
+                container: _this.options.container,
+                tooltip: _this.options.tooltip
+              }).render());
+            });
+            $dropdown.find('input[type=color]').each(function (idx, item) {
+              external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(item).change(function () {
+                var $chip = $dropdown.find('#' + external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(this).data('event')).find('.note-color-btn').first();
+                var color = this.value.toUpperCase();
+                $chip.css('background-color', color).attr('aria-label', color).attr('data-value', color).attr('data-original-title', color);
+                $chip.click();
+              });
+            });
+          },
+          click: function click(event) {
+            event.stopPropagation();
+            var $parent = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()('.' + className).find('.note-dropdown-menu');
+            var $button = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(event.target);
+            var eventName = $button.data('event');
+            var value = $button.attr('data-value');
+
+            if (eventName === 'openPalette') {
+              var $picker = $parent.find('#' + value);
+              var $palette = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()($parent.find('#' + $picker.data('event')).find('.note-color-row')[0]); // Shift palette chips
+
+              var $chip = $palette.find('.note-color-btn').last().detach(); // Set chip attributes
+
+              var color = $picker.val();
+              $chip.css('background-color', color).attr('aria-label', color).attr('data-value', color).attr('data-original-title', color);
+              $palette.prepend($chip);
+              $picker.click();
+            } else {
+              if (lists.contains(['backColor', 'foreColor'], eventName)) {
+                var key = eventName === 'backColor' ? 'background-color' : 'color';
+                var $color = $button.closest('.note-color').find('.note-recent-color');
+                var $currentButton = $button.closest('.note-color').find('.note-current-color-button');
+                $color.css(key, value);
+                $currentButton.attr('data-' + eventName, value);
+              }
+
+              _this.context.invoke('editor.' + eventName, value);
+            }
+          }
+        })]
+      }).render();
+    }
+  }, {
+    key: "addToolbarButtons",
+    value: function addToolbarButtons() {
+      var _this2 = this;
+
+      this.context.memo('button.style', function () {
+        return _this2.ui.buttonGroup([_this2.button({
+          className: 'dropdown-toggle',
+          contents: _this2.ui.dropdownButtonContents(_this2.ui.icon(_this2.options.icons.magic), _this2.options),
+          tooltip: _this2.lang.style.style,
+          data: {
+            toggle: 'dropdown'
+          }
+        }), _this2.ui.dropdown({
+          className: 'dropdown-style',
+          items: _this2.options.styleTags,
+          title: _this2.lang.style.style,
+          template: function template(item) {
+            // TBD: need to be simplified
+            if (typeof item === 'string') {
+              item = {
+                tag: item,
+                title: Object.prototype.hasOwnProperty.call(_this2.lang.style, item) ? _this2.lang.style[item] : item
+              };
+            }
+
+            var tag = item.tag;
+            var title = item.title;
+            var style = item.style ? ' style="' + item.style + '" ' : '';
+            var className = item.className ? ' class="' + item.className + '"' : '';
+            return '<' + tag + style + className + '>' + title + '</' + tag + '>';
+          },
+          click: _this2.context.createInvokeHandler('editor.formatBlock')
+        })]).render();
+      });
+
+      var _loop = function _loop(styleIdx, styleLen) {
+        var item = _this2.options.styleTags[styleIdx];
+
+        _this2.context.memo('button.style.' + item, function () {
+          return _this2.button({
+            className: 'note-btn-style-' + item,
+            contents: '<div data-value="' + item + '">' + item.toUpperCase() + '</div>',
+            tooltip: _this2.lang.style[item],
+            click: _this2.context.createInvokeHandler('editor.formatBlock')
+          }).render();
+        });
+      };
+
+      for (var styleIdx = 0, styleLen = this.options.styleTags.length; styleIdx < styleLen; styleIdx++) {
+        _loop(styleIdx, styleLen);
+      }
+
+      this.context.memo('button.bold', function () {
+        return _this2.button({
+          className: 'note-btn-bold',
+          contents: _this2.ui.icon(_this2.options.icons.bold),
+          tooltip: _this2.lang.font.bold + _this2.representShortcut('bold'),
+          click: _this2.context.createInvokeHandlerAndUpdateState('editor.bold')
+        }).render();
+      });
+      this.context.memo('button.italic', function () {
+        return _this2.button({
+          className: 'note-btn-italic',
+          contents: _this2.ui.icon(_this2.options.icons.italic),
+          tooltip: _this2.lang.font.italic + _this2.representShortcut('italic'),
+          click: _this2.context.createInvokeHandlerAndUpdateState('editor.italic')
+        }).render();
+      });
+      this.context.memo('button.underline', function () {
+        return _this2.button({
+          className: 'note-btn-underline',
+          contents: _this2.ui.icon(_this2.options.icons.underline),
+          tooltip: _this2.lang.font.underline + _this2.representShortcut('underline'),
+          click: _this2.context.createInvokeHandlerAndUpdateState('editor.underline')
+        }).render();
+      });
+      this.context.memo('button.clear', function () {
+        return _this2.button({
+          contents: _this2.ui.icon(_this2.options.icons.eraser),
+          tooltip: _this2.lang.font.clear + _this2.representShortcut('removeFormat'),
+          click: _this2.context.createInvokeHandler('editor.removeFormat')
+        }).render();
+      });
+      this.context.memo('button.strikethrough', function () {
+        return _this2.button({
+          className: 'note-btn-strikethrough',
+          contents: _this2.ui.icon(_this2.options.icons.strikethrough),
+          tooltip: _this2.lang.font.strikethrough + _this2.representShortcut('strikethrough'),
+          click: _this2.context.createInvokeHandlerAndUpdateState('editor.strikethrough')
+        }).render();
+      });
+      this.context.memo('button.superscript', function () {
+        return _this2.button({
+          className: 'note-btn-superscript',
+          contents: _this2.ui.icon(_this2.options.icons.superscript),
+          tooltip: _this2.lang.font.superscript,
+          click: _this2.context.createInvokeHandlerAndUpdateState('editor.superscript')
+        }).render();
+      });
+      this.context.memo('button.subscript', function () {
+        return _this2.button({
+          className: 'note-btn-subscript',
+          contents: _this2.ui.icon(_this2.options.icons.subscript),
+          tooltip: _this2.lang.font.subscript,
+          click: _this2.context.createInvokeHandlerAndUpdateState('editor.subscript')
+        }).render();
+      });
+      this.context.memo('button.fontname', function () {
+        var styleInfo = _this2.context.invoke('editor.currentStyle');
+
+        if (_this2.options.addDefaultFonts) {
+          // Add 'default' fonts into the fontnames array if not exist
+          external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.each(styleInfo['font-family'].split(','), function (idx, fontname) {
+            fontname = fontname.trim().replace(/['"]+/g, '');
+
+            if (_this2.isFontDeservedToAdd(fontname)) {
+              if (_this2.options.fontNames.indexOf(fontname) === -1) {
+                _this2.options.fontNames.push(fontname);
+              }
+            }
+          });
+        }
+
+        return _this2.ui.buttonGroup([_this2.button({
+          className: 'dropdown-toggle',
+          contents: _this2.ui.dropdownButtonContents('<span class="note-current-fontname"></span>', _this2.options),
+          tooltip: _this2.lang.font.name,
+          data: {
+            toggle: 'dropdown'
+          }
+        }), _this2.ui.dropdownCheck({
+          className: 'dropdown-fontname',
+          checkClassName: _this2.options.icons.menuCheck,
+          items: _this2.options.fontNames.filter(_this2.isFontInstalled.bind(_this2)),
+          title: _this2.lang.font.name,
+          template: function template(item) {
+            return '<span style="font-family: ' + env.validFontName(item) + '">' + item + '</span>';
+          },
+          click: _this2.context.createInvokeHandlerAndUpdateState('editor.fontName')
+        })]).render();
+      });
+      this.context.memo('button.fontsize', function () {
+        return _this2.ui.buttonGroup([_this2.button({
+          className: 'dropdown-toggle',
+          contents: _this2.ui.dropdownButtonContents('<span class="note-current-fontsize"></span>', _this2.options),
+          tooltip: _this2.lang.font.size,
+          data: {
+            toggle: 'dropdown'
+          }
+        }), _this2.ui.dropdownCheck({
+          className: 'dropdown-fontsize',
+          checkClassName: _this2.options.icons.menuCheck,
+          items: _this2.options.fontSizes,
+          title: _this2.lang.font.size,
+          click: _this2.context.createInvokeHandlerAndUpdateState('editor.fontSize')
+        })]).render();
+      });
+      this.context.memo('button.fontsizeunit', function () {
+        return _this2.ui.buttonGroup([_this2.button({
+          className: 'dropdown-toggle',
+          contents: _this2.ui.dropdownButtonContents('<span class="note-current-fontsizeunit"></span>', _this2.options),
+          tooltip: _this2.lang.font.sizeunit,
+          data: {
+            toggle: 'dropdown'
+          }
+        }), _this2.ui.dropdownCheck({
+          className: 'dropdown-fontsizeunit',
+          checkClassName: _this2.options.icons.menuCheck,
+          items: _this2.options.fontSizeUnits,
+          title: _this2.lang.font.sizeunit,
+          click: _this2.context.createInvokeHandlerAndUpdateState('editor.fontSizeUnit')
+        })]).render();
+      });
+      this.context.memo('button.color', function () {
+        return _this2.colorPalette('note-color-all', _this2.lang.color.recent, true, true);
+      });
+      this.context.memo('button.forecolor', function () {
+        return _this2.colorPalette('note-color-fore', _this2.lang.color.foreground, false, true);
+      });
+      this.context.memo('button.backcolor', function () {
+        return _this2.colorPalette('note-color-back', _this2.lang.color.background, true, false);
+      });
+      this.context.memo('button.ul', function () {
+        return _this2.button({
+          contents: _this2.ui.icon(_this2.options.icons.unorderedlist),
+          tooltip: _this2.lang.lists.unordered + _this2.representShortcut('insertUnorderedList'),
+          click: _this2.context.createInvokeHandler('editor.insertUnorderedList')
+        }).render();
+      });
+      this.context.memo('button.ol', function () {
+        return _this2.button({
+          contents: _this2.ui.icon(_this2.options.icons.orderedlist),
+          tooltip: _this2.lang.lists.ordered + _this2.representShortcut('insertOrderedList'),
+          click: _this2.context.createInvokeHandler('editor.insertOrderedList')
+        }).render();
+      });
+      var justifyLeft = this.button({
+        contents: this.ui.icon(this.options.icons.alignLeft),
+        tooltip: this.lang.paragraph.left + this.representShortcut('justifyLeft'),
+        click: this.context.createInvokeHandler('editor.justifyLeft')
+      });
+      var justifyCenter = this.button({
+        contents: this.ui.icon(this.options.icons.alignCenter),
+        tooltip: this.lang.paragraph.center + this.representShortcut('justifyCenter'),
+        click: this.context.createInvokeHandler('editor.justifyCenter')
+      });
+      var justifyRight = this.button({
+        contents: this.ui.icon(this.options.icons.alignRight),
+        tooltip: this.lang.paragraph.right + this.representShortcut('justifyRight'),
+        click: this.context.createInvokeHandler('editor.justifyRight')
+      });
+      var justifyFull = this.button({
+        contents: this.ui.icon(this.options.icons.alignJustify),
+        tooltip: this.lang.paragraph.justify + this.representShortcut('justifyFull'),
+        click: this.context.createInvokeHandler('editor.justifyFull')
+      });
+      var outdent = this.button({
+        contents: this.ui.icon(this.options.icons.outdent),
+        tooltip: this.lang.paragraph.outdent + this.representShortcut('outdent'),
+        click: this.context.createInvokeHandler('editor.outdent')
+      });
+      var indent = this.button({
+        contents: this.ui.icon(this.options.icons.indent),
+        tooltip: this.lang.paragraph.indent + this.representShortcut('indent'),
+        click: this.context.createInvokeHandler('editor.indent')
+      });
+      this.context.memo('button.justifyLeft', func.invoke(justifyLeft, 'render'));
+      this.context.memo('button.justifyCenter', func.invoke(justifyCenter, 'render'));
+      this.context.memo('button.justifyRight', func.invoke(justifyRight, 'render'));
+      this.context.memo('button.justifyFull', func.invoke(justifyFull, 'render'));
+      this.context.memo('button.outdent', func.invoke(outdent, 'render'));
+      this.context.memo('button.indent', func.invoke(indent, 'render'));
+      this.context.memo('button.paragraph', function () {
+        return _this2.ui.buttonGroup([_this2.button({
+          className: 'dropdown-toggle',
+          contents: _this2.ui.dropdownButtonContents(_this2.ui.icon(_this2.options.icons.alignLeft), _this2.options),
+          tooltip: _this2.lang.paragraph.paragraph,
+          data: {
+            toggle: 'dropdown'
+          }
+        }), _this2.ui.dropdown([_this2.ui.buttonGroup({
+          className: 'note-align',
+          children: [justifyLeft, justifyCenter, justifyRight, justifyFull]
+        }), _this2.ui.buttonGroup({
+          className: 'note-list',
+          children: [outdent, indent]
+        })])]).render();
+      });
+      this.context.memo('button.height', function () {
+        return _this2.ui.buttonGroup([_this2.button({
+          className: 'dropdown-toggle',
+          contents: _this2.ui.dropdownButtonContents(_this2.ui.icon(_this2.options.icons.textHeight), _this2.options),
+          tooltip: _this2.lang.font.height,
+          data: {
+            toggle: 'dropdown'
+          }
+        }), _this2.ui.dropdownCheck({
+          items: _this2.options.lineHeights,
+          checkClassName: _this2.options.icons.menuCheck,
+          className: 'dropdown-line-height',
+          title: _this2.lang.font.height,
+          click: _this2.context.createInvokeHandler('editor.lineHeight')
+        })]).render();
+      });
+      this.context.memo('button.table', function () {
+        return _this2.ui.buttonGroup([_this2.button({
+          className: 'dropdown-toggle',
+          contents: _this2.ui.dropdownButtonContents(_this2.ui.icon(_this2.options.icons.table), _this2.options),
+          tooltip: _this2.lang.table.table,
+          data: {
+            toggle: 'dropdown'
+          }
+        }), _this2.ui.dropdown({
+          title: _this2.lang.table.table,
+          className: 'note-table',
+          items: ['<div class="note-dimension-picker">', '<div class="note-dimension-picker-mousecatcher" data-event="insertTable" data-value="1x1"></div>', '<div class="note-dimension-picker-highlighted"></div>', '<div class="note-dimension-picker-unhighlighted"></div>', '</div>', '<div class="note-dimension-display">1 x 1</div>'].join('')
+        })], {
+          callback: function callback($node) {
+            var $catcher = $node.find('.note-dimension-picker-mousecatcher');
+            $catcher.css({
+              width: _this2.options.insertTableMaxSize.col + 'em',
+              height: _this2.options.insertTableMaxSize.row + 'em'
+            }).mousedown(_this2.context.createInvokeHandler('editor.insertTable')).on('mousemove', _this2.tableMoveHandler.bind(_this2));
+          }
+        }).render();
+      });
+      this.context.memo('button.link', function () {
+        return _this2.button({
+          contents: _this2.ui.icon(_this2.options.icons.link),
+          tooltip: _this2.lang.link.link + _this2.representShortcut('linkDialog.show'),
+          click: _this2.context.createInvokeHandler('linkDialog.show')
+        }).render();
+      });
+      this.context.memo('button.picture', function () {
+        return _this2.button({
+          contents: _this2.ui.icon(_this2.options.icons.picture),
+          tooltip: _this2.lang.image.image,
+          click: _this2.context.createInvokeHandler('imageDialog.show')
+        }).render();
+      });
+      this.context.memo('button.video', function () {
+        return _this2.button({
+          contents: _this2.ui.icon(_this2.options.icons.video),
+          tooltip: _this2.lang.video.video,
+          click: _this2.context.createInvokeHandler('videoDialog.show')
+        }).render();
+      });
+      this.context.memo('button.hr', function () {
+        return _this2.button({
+          contents: _this2.ui.icon(_this2.options.icons.minus),
+          tooltip: _this2.lang.hr.insert + _this2.representShortcut('insertHorizontalRule'),
+          click: _this2.context.createInvokeHandler('editor.insertHorizontalRule')
+        }).render();
+      });
+      this.context.memo('button.fullscreen', function () {
+        return _this2.button({
+          className: 'btn-fullscreen note-codeview-keep',
+          contents: _this2.ui.icon(_this2.options.icons.arrowsAlt),
+          tooltip: _this2.lang.options.fullscreen,
+          click: _this2.context.createInvokeHandler('fullscreen.toggle')
+        }).render();
+      });
+      this.context.memo('button.codeview', function () {
+        return _this2.button({
+          className: 'btn-codeview note-codeview-keep',
+          contents: _this2.ui.icon(_this2.options.icons.code),
+          tooltip: _this2.lang.options.codeview,
+          click: _this2.context.createInvokeHandler('codeview.toggle')
+        }).render();
+      });
+      this.context.memo('button.redo', function () {
+        return _this2.button({
+          contents: _this2.ui.icon(_this2.options.icons.redo),
+          tooltip: _this2.lang.history.redo + _this2.representShortcut('redo'),
+          click: _this2.context.createInvokeHandler('editor.redo')
+        }).render();
+      });
+      this.context.memo('button.undo', function () {
+        return _this2.button({
+          contents: _this2.ui.icon(_this2.options.icons.undo),
+          tooltip: _this2.lang.history.undo + _this2.representShortcut('undo'),
+          click: _this2.context.createInvokeHandler('editor.undo')
+        }).render();
+      });
+      this.context.memo('button.help', function () {
+        return _this2.button({
+          contents: _this2.ui.icon(_this2.options.icons.question),
+          tooltip: _this2.lang.options.help,
+          click: _this2.context.createInvokeHandler('helpDialog.show')
+        }).render();
+      });
+    }
+    /**
+     * image: [
+     *   ['imageResize', ['resizeFull', 'resizeHalf', 'resizeQuarter', 'resizeNone']],
+     *   ['float', ['floatLeft', 'floatRight', 'floatNone']],
+     *   ['remove', ['removeMedia']],
+     * ],
+     */
+
+  }, {
+    key: "addImagePopoverButtons",
+    value: function addImagePopoverButtons() {
+      var _this3 = this;
+
+      // Image Size Buttons
+      this.context.memo('button.resizeFull', function () {
+        return _this3.button({
+          contents: '<span class="note-fontsize-10">100%</span>',
+          tooltip: _this3.lang.image.resizeFull,
+          click: _this3.context.createInvokeHandler('editor.resize', '1')
+        }).render();
+      });
+      this.context.memo('button.resizeHalf', function () {
+        return _this3.button({
+          contents: '<span class="note-fontsize-10">50%</span>',
+          tooltip: _this3.lang.image.resizeHalf,
+          click: _this3.context.createInvokeHandler('editor.resize', '0.5')
+        }).render();
+      });
+      this.context.memo('button.resizeQuarter', function () {
+        return _this3.button({
+          contents: '<span class="note-fontsize-10">25%</span>',
+          tooltip: _this3.lang.image.resizeQuarter,
+          click: _this3.context.createInvokeHandler('editor.resize', '0.25')
+        }).render();
+      });
+      this.context.memo('button.resizeNone', function () {
+        return _this3.button({
+          contents: _this3.ui.icon(_this3.options.icons.rollback),
+          tooltip: _this3.lang.image.resizeNone,
+          click: _this3.context.createInvokeHandler('editor.resize', '0')
+        }).render();
+      }); // Float Buttons
+
+      this.context.memo('button.floatLeft', function () {
+        return _this3.button({
+          contents: _this3.ui.icon(_this3.options.icons.floatLeft),
+          tooltip: _this3.lang.image.floatLeft,
+          click: _this3.context.createInvokeHandler('editor.floatMe', 'left')
+        }).render();
+      });
+      this.context.memo('button.floatRight', function () {
+        return _this3.button({
+          contents: _this3.ui.icon(_this3.options.icons.floatRight),
+          tooltip: _this3.lang.image.floatRight,
+          click: _this3.context.createInvokeHandler('editor.floatMe', 'right')
+        }).render();
+      });
+      this.context.memo('button.floatNone', function () {
+        return _this3.button({
+          contents: _this3.ui.icon(_this3.options.icons.rollback),
+          tooltip: _this3.lang.image.floatNone,
+          click: _this3.context.createInvokeHandler('editor.floatMe', 'none')
+        }).render();
+      }); // Remove Buttons
+
+      this.context.memo('button.removeMedia', function () {
+        return _this3.button({
+          contents: _this3.ui.icon(_this3.options.icons.trash),
+          tooltip: _this3.lang.image.remove,
+          click: _this3.context.createInvokeHandler('editor.removeMedia')
+        }).render();
+      });
+    }
+  }, {
+    key: "addLinkPopoverButtons",
+    value: function addLinkPopoverButtons() {
+      var _this4 = this;
+
+      this.context.memo('button.linkDialogShow', function () {
+        return _this4.button({
+          contents: _this4.ui.icon(_this4.options.icons.link),
+          tooltip: _this4.lang.link.edit,
+          click: _this4.context.createInvokeHandler('linkDialog.show')
+        }).render();
+      });
+      this.context.memo('button.unlink', function () {
+        return _this4.button({
+          contents: _this4.ui.icon(_this4.options.icons.unlink),
+          tooltip: _this4.lang.link.unlink,
+          click: _this4.context.createInvokeHandler('editor.unlink')
+        }).render();
+      });
+    }
+    /**
+     * table : [
+     *  ['add', ['addRowDown', 'addRowUp', 'addColLeft', 'addColRight']],
+     *  ['delete', ['deleteRow', 'deleteCol', 'deleteTable']]
+     * ],
+     */
+
+  }, {
+    key: "addTablePopoverButtons",
+    value: function addTablePopoverButtons() {
+      var _this5 = this;
+
+      this.context.memo('button.addRowUp', function () {
+        return _this5.button({
+          className: 'btn-md',
+          contents: _this5.ui.icon(_this5.options.icons.rowAbove),
+          tooltip: _this5.lang.table.addRowAbove,
+          click: _this5.context.createInvokeHandler('editor.addRow', 'top')
+        }).render();
+      });
+      this.context.memo('button.addRowDown', function () {
+        return _this5.button({
+          className: 'btn-md',
+          contents: _this5.ui.icon(_this5.options.icons.rowBelow),
+          tooltip: _this5.lang.table.addRowBelow,
+          click: _this5.context.createInvokeHandler('editor.addRow', 'bottom')
+        }).render();
+      });
+      this.context.memo('button.addColLeft', function () {
+        return _this5.button({
+          className: 'btn-md',
+          contents: _this5.ui.icon(_this5.options.icons.colBefore),
+          tooltip: _this5.lang.table.addColLeft,
+          click: _this5.context.createInvokeHandler('editor.addCol', 'left')
+        }).render();
+      });
+      this.context.memo('button.addColRight', function () {
+        return _this5.button({
+          className: 'btn-md',
+          contents: _this5.ui.icon(_this5.options.icons.colAfter),
+          tooltip: _this5.lang.table.addColRight,
+          click: _this5.context.createInvokeHandler('editor.addCol', 'right')
+        }).render();
+      });
+      this.context.memo('button.deleteRow', function () {
+        return _this5.button({
+          className: 'btn-md',
+          contents: _this5.ui.icon(_this5.options.icons.rowRemove),
+          tooltip: _this5.lang.table.delRow,
+          click: _this5.context.createInvokeHandler('editor.deleteRow')
+        }).render();
+      });
+      this.context.memo('button.deleteCol', function () {
+        return _this5.button({
+          className: 'btn-md',
+          contents: _this5.ui.icon(_this5.options.icons.colRemove),
+          tooltip: _this5.lang.table.delCol,
+          click: _this5.context.createInvokeHandler('editor.deleteCol')
+        }).render();
+      });
+      this.context.memo('button.deleteTable', function () {
+        return _this5.button({
+          className: 'btn-md',
+          contents: _this5.ui.icon(_this5.options.icons.trash),
+          tooltip: _this5.lang.table.delTable,
+          click: _this5.context.createInvokeHandler('editor.deleteTable')
+        }).render();
+      });
+    }
+  }, {
+    key: "build",
+    value: function build($container, groups) {
+      for (var groupIdx = 0, groupLen = groups.length; groupIdx < groupLen; groupIdx++) {
+        var group = groups[groupIdx];
+        var groupName = Array.isArray(group) ? group[0] : group;
+        var buttons = Array.isArray(group) ? group.length === 1 ? [group[0]] : group[1] : [group];
+        var $group = this.ui.buttonGroup({
+          className: 'note-' + groupName
+        }).render();
+
+        for (var idx = 0, len = buttons.length; idx < len; idx++) {
+          var btn = this.context.memo('button.' + buttons[idx]);
+
+          if (btn) {
+            $group.append(typeof btn === 'function' ? btn(this.context) : btn);
+          }
+        }
+
+        $group.appendTo($container);
+      }
+    }
+    /**
+     * @param {jQuery} [$container]
+     */
+
+  }, {
+    key: "updateCurrentStyle",
+    value: function updateCurrentStyle($container) {
+      var _this6 = this;
+
+      var $cont = $container || this.$toolbar;
+      var styleInfo = this.context.invoke('editor.currentStyle');
+      this.updateBtnStates($cont, {
+        '.note-btn-bold': function noteBtnBold() {
+          return styleInfo['font-bold'] === 'bold';
+        },
+        '.note-btn-italic': function noteBtnItalic() {
+          return styleInfo['font-italic'] === 'italic';
+        },
+        '.note-btn-underline': function noteBtnUnderline() {
+          return styleInfo['font-underline'] === 'underline';
+        },
+        '.note-btn-subscript': function noteBtnSubscript() {
+          return styleInfo['font-subscript'] === 'subscript';
+        },
+        '.note-btn-superscript': function noteBtnSuperscript() {
+          return styleInfo['font-superscript'] === 'superscript';
+        },
+        '.note-btn-strikethrough': function noteBtnStrikethrough() {
+          return styleInfo['font-strikethrough'] === 'strikethrough';
+        }
+      });
+
+      if (styleInfo['font-family']) {
+        var fontNames = styleInfo['font-family'].split(',').map(function (name) {
+          return name.replace(/[\'\"]/g, '').replace(/\s+$/, '').replace(/^\s+/, '');
+        });
+        var fontName = lists.find(fontNames, this.isFontInstalled.bind(this));
+        $cont.find('.dropdown-fontname a').each(function (idx, item) {
+          var $item = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(item); // always compare string to avoid creating another func.
+
+          var isChecked = $item.data('value') + '' === fontName + '';
+          $item.toggleClass('checked', isChecked);
+        });
+        $cont.find('.note-current-fontname').text(fontName).css('font-family', fontName);
+      }
+
+      if (styleInfo['font-size']) {
+        var fontSize = styleInfo['font-size'];
+        $cont.find('.dropdown-fontsize a').each(function (idx, item) {
+          var $item = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(item); // always compare with string to avoid creating another func.
+
+          var isChecked = $item.data('value') + '' === fontSize + '';
+          $item.toggleClass('checked', isChecked);
+        });
+        $cont.find('.note-current-fontsize').text(fontSize);
+        var fontSizeUnit = styleInfo['font-size-unit'];
+        $cont.find('.dropdown-fontsizeunit a').each(function (idx, item) {
+          var $item = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(item);
+          var isChecked = $item.data('value') + '' === fontSizeUnit + '';
+          $item.toggleClass('checked', isChecked);
+        });
+        $cont.find('.note-current-fontsizeunit').text(fontSizeUnit);
+      }
+
+      if (styleInfo['line-height']) {
+        var lineHeight = styleInfo['line-height'];
+        $cont.find('.dropdown-line-height li a').each(function (idx, item) {
+          // always compare with string to avoid creating another func.
+          var isChecked = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(item).data('value') + '' === lineHeight + '';
+          _this6.className = isChecked ? 'checked' : '';
+        });
+      }
+    }
+  }, {
+    key: "updateBtnStates",
+    value: function updateBtnStates($container, infos) {
+      var _this7 = this;
+
+      external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.each(infos, function (selector, pred) {
+        _this7.ui.toggleBtnActive($container.find(selector), pred());
+      });
+    }
+  }, {
+    key: "tableMoveHandler",
+    value: function tableMoveHandler(event) {
+      var PX_PER_EM = 18;
+      var $picker = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(event.target.parentNode); // target is mousecatcher
+
+      var $dimensionDisplay = $picker.next();
+      var $catcher = $picker.find('.note-dimension-picker-mousecatcher');
+      var $highlighted = $picker.find('.note-dimension-picker-highlighted');
+      var $unhighlighted = $picker.find('.note-dimension-picker-unhighlighted');
+      var posOffset; // HTML5 with jQuery - e.offsetX is undefined in Firefox
+
+      if (event.offsetX === undefined) {
+        var posCatcher = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(event.target).offset();
+        posOffset = {
+          x: event.pageX - posCatcher.left,
+          y: event.pageY - posCatcher.top
+        };
+      } else {
+        posOffset = {
+          x: event.offsetX,
+          y: event.offsetY
+        };
+      }
+
+      var dim = {
+        c: Math.ceil(posOffset.x / PX_PER_EM) || 1,
+        r: Math.ceil(posOffset.y / PX_PER_EM) || 1
+      };
+      $highlighted.css({
+        width: dim.c + 'em',
+        height: dim.r + 'em'
+      });
+      $catcher.data('value', dim.c + 'x' + dim.r);
+
+      if (dim.c > 3 && dim.c < this.options.insertTableMaxSize.col) {
+        $unhighlighted.css({
+          width: dim.c + 1 + 'em'
+        });
+      }
+
+      if (dim.r > 3 && dim.r < this.options.insertTableMaxSize.row) {
+        $unhighlighted.css({
+          height: dim.r + 1 + 'em'
+        });
+      }
+
+      $dimensionDisplay.html(dim.c + ' x ' + dim.r);
+    }
+  }]);
+
+  return Buttons;
+}();
+
+
+// CONCATENATED MODULE: ./src/js/base/module/Toolbar.js
+function Toolbar_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function Toolbar_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function Toolbar_createClass(Constructor, protoProps, staticProps) { if (protoProps) Toolbar_defineProperties(Constructor.prototype, protoProps); if (staticProps) Toolbar_defineProperties(Constructor, staticProps); return Constructor; }
+
+
+
+var Toolbar_Toolbar = /*#__PURE__*/function () {
+  function Toolbar(context) {
+    Toolbar_classCallCheck(this, Toolbar);
+
+    this.context = context;
+    this.$window = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(window);
+    this.$document = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(document);
+    this.ui = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.summernote.ui;
+    this.$note = context.layoutInfo.note;
+    this.$editor = context.layoutInfo.editor;
+    this.$toolbar = context.layoutInfo.toolbar;
+    this.$editable = context.layoutInfo.editable;
+    this.$statusbar = context.layoutInfo.statusbar;
+    this.options = context.options;
+    this.isFollowing = false;
+    this.followScroll = this.followScroll.bind(this);
+  }
+
+  Toolbar_createClass(Toolbar, [{
+    key: "shouldInitialize",
+    value: function shouldInitialize() {
+      return !this.options.airMode;
+    }
+  }, {
+    key: "initialize",
+    value: function initialize() {
+      var _this = this;
+
+      this.options.toolbar = this.options.toolbar || [];
+
+      if (!this.options.toolbar.length) {
+        this.$toolbar.hide();
+      } else {
+        this.context.invoke('buttons.build', this.$toolbar, this.options.toolbar);
+      }
+
+      if (this.options.toolbarContainer) {
+        this.$toolbar.appendTo(this.options.toolbarContainer);
+      }
+
+      this.changeContainer(false);
+      this.$note.on('summernote.keyup summernote.mouseup summernote.change', function () {
+        _this.context.invoke('buttons.updateCurrentStyle');
+      });
+      this.context.invoke('buttons.updateCurrentStyle');
+
+      if (this.options.followingToolbar) {
+        this.$window.on('scroll resize', this.followScroll);
+      }
+    }
+  }, {
+    key: "destroy",
+    value: function destroy() {
+      this.$toolbar.children().remove();
+
+      if (this.options.followingToolbar) {
+        this.$window.off('scroll resize', this.followScroll);
+      }
+    }
+  }, {
+    key: "followScroll",
+    value: function followScroll() {
+      if (this.$editor.hasClass('fullscreen')) {
+        return false;
+      }
+
+      var editorHeight = this.$editor.outerHeight();
+      var editorWidth = this.$editor.width();
+      var toolbarHeight = this.$toolbar.height();
+      var statusbarHeight = this.$statusbar.height(); // check if the web app is currently using another static bar
+
+      var otherBarHeight = 0;
+
+      if (this.options.otherStaticBar) {
+        otherBarHeight = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(this.options.otherStaticBar).outerHeight();
+      }
+
+      var currentOffset = this.$document.scrollTop();
+      var editorOffsetTop = this.$editor.offset().top;
+      var editorOffsetBottom = editorOffsetTop + editorHeight;
+      var activateOffset = editorOffsetTop - otherBarHeight;
+      var deactivateOffsetBottom = editorOffsetBottom - otherBarHeight - toolbarHeight - statusbarHeight;
+
+      if (!this.isFollowing && currentOffset > activateOffset && currentOffset < deactivateOffsetBottom - toolbarHeight) {
+        this.isFollowing = true;
+        this.$editable.css({
+          marginTop: this.$toolbar.outerHeight()
+        });
+        this.$toolbar.css({
+          position: 'fixed',
+          top: otherBarHeight,
+          width: editorWidth,
+          zIndex: 1000
+        });
+      } else if (this.isFollowing && (currentOffset < activateOffset || currentOffset > deactivateOffsetBottom)) {
+        this.isFollowing = false;
+        this.$toolbar.css({
+          position: 'relative',
+          top: 0,
+          width: '100%',
+          zIndex: 'auto'
+        });
+        this.$editable.css({
+          marginTop: ''
+        });
+      }
+    }
+  }, {
+    key: "changeContainer",
+    value: function changeContainer(isFullscreen) {
+      if (isFullscreen) {
+        this.$toolbar.prependTo(this.$editor);
+      } else {
+        if (this.options.toolbarContainer) {
+          this.$toolbar.appendTo(this.options.toolbarContainer);
+        }
+      }
+
+      if (this.options.followingToolbar) {
+        this.followScroll();
+      }
+    }
+  }, {
+    key: "updateFullscreen",
+    value: function updateFullscreen(isFullscreen) {
+      this.ui.toggleBtnActive(this.$toolbar.find('.btn-fullscreen'), isFullscreen);
+      this.changeContainer(isFullscreen);
+    }
+  }, {
+    key: "updateCodeview",
+    value: function updateCodeview(isCodeview) {
+      this.ui.toggleBtnActive(this.$toolbar.find('.btn-codeview'), isCodeview);
+
+      if (isCodeview) {
+        this.deactivate();
+      } else {
+        this.activate();
+      }
+    }
+  }, {
+    key: "activate",
+    value: function activate(isIncludeCodeview) {
+      var $btn = this.$toolbar.find('button');
+
+      if (!isIncludeCodeview) {
+        $btn = $btn.not('.note-codeview-keep');
+      }
+
+      this.ui.toggleBtn($btn, true);
+    }
+  }, {
+    key: "deactivate",
+    value: function deactivate(isIncludeCodeview) {
+      var $btn = this.$toolbar.find('button');
+
+      if (!isIncludeCodeview) {
+        $btn = $btn.not('.note-codeview-keep');
+      }
+
+      this.ui.toggleBtn($btn, false);
+    }
+  }]);
+
+  return Toolbar;
+}();
+
+
+// CONCATENATED MODULE: ./src/js/base/module/LinkDialog.js
+function LinkDialog_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function LinkDialog_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function LinkDialog_createClass(Constructor, protoProps, staticProps) { if (protoProps) LinkDialog_defineProperties(Constructor.prototype, protoProps); if (staticProps) LinkDialog_defineProperties(Constructor, staticProps); return Constructor; }
+
+
+
+
+
+
+var LinkDialog_LinkDialog = /*#__PURE__*/function () {
+  function LinkDialog(context) {
+    LinkDialog_classCallCheck(this, LinkDialog);
+
+    this.context = context;
+    this.ui = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.summernote.ui;
+    this.$body = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(document.body);
+    this.$editor = context.layoutInfo.editor;
+    this.options = context.options;
+    this.lang = this.options.langInfo;
+    context.memo('help.linkDialog.show', this.options.langInfo.help['linkDialog.show']);
+  }
+
+  LinkDialog_createClass(LinkDialog, [{
+    key: "initialize",
+    value: function initialize() {
+      var $container = this.options.dialogsInBody ? this.$body : this.options.container;
+      var body = ['<div class="form-group note-form-group">', "<label for=\"note-dialog-link-txt-".concat(this.options.id, "\" class=\"note-form-label\">").concat(this.lang.link.textToDisplay, "</label>"), "<input id=\"note-dialog-link-txt-".concat(this.options.id, "\" class=\"note-link-text form-control note-form-control note-input\" type=\"text\"/>"), '</div>', '<div class="form-group note-form-group">', "<label for=\"note-dialog-link-url-".concat(this.options.id, "\" class=\"note-form-label\">").concat(this.lang.link.url, "</label>"), "<input id=\"note-dialog-link-url-".concat(this.options.id, "\" class=\"note-link-url form-control note-form-control note-input\" type=\"text\" value=\"http://\"/>"), '</div>', !this.options.disableLinkTarget ? external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()('<div/>').append(this.ui.checkbox({
+        className: 'sn-checkbox-open-in-new-window',
+        text: this.lang.link.openInNewWindow,
+        checked: true
+      }).render()).html() : '', external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()('<div/>').append(this.ui.checkbox({
+        className: 'sn-checkbox-use-protocol',
+        text: this.lang.link.useProtocol,
+        checked: true
+      }).render()).html()].join('');
+      var buttonClass = 'btn btn-primary note-btn note-btn-primary note-link-btn';
+      var footer = "<input type=\"button\" href=\"#\" class=\"".concat(buttonClass, "\" value=\"").concat(this.lang.link.insert, "\" disabled>");
+      this.$dialog = this.ui.dialog({
+        className: 'link-dialog',
+        title: this.lang.link.insert,
+        fade: this.options.dialogsFade,
+        body: body,
+        footer: footer
+      }).render().appendTo($container);
+    }
+  }, {
+    key: "destroy",
+    value: function destroy() {
+      this.ui.hideDialog(this.$dialog);
+      this.$dialog.remove();
+    }
+  }, {
+    key: "bindEnterKey",
+    value: function bindEnterKey($input, $btn) {
+      $input.on('keypress', function (event) {
+        if (event.keyCode === core_key.code.ENTER) {
+          event.preventDefault();
+          $btn.trigger('click');
+        }
+      });
+    }
+    /**
+     * toggle update button
+     */
+
+  }, {
+    key: "toggleLinkBtn",
+    value: function toggleLinkBtn($linkBtn, $linkText, $linkUrl) {
+      this.ui.toggleBtn($linkBtn, $linkText.val() && $linkUrl.val());
+    }
+    /**
+     * Show link dialog and set event handlers on dialog controls.
+     *
+     * @param {Object} linkInfo
+     * @return {Promise}
+     */
+
+  }, {
+    key: "showLinkDialog",
+    value: function showLinkDialog(linkInfo) {
+      var _this = this;
+
+      return external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.Deferred(function (deferred) {
+        var $linkText = _this.$dialog.find('.note-link-text');
+
+        var $linkUrl = _this.$dialog.find('.note-link-url');
+
+        var $linkBtn = _this.$dialog.find('.note-link-btn');
+
+        var $openInNewWindow = _this.$dialog.find('.sn-checkbox-open-in-new-window input[type=checkbox]');
+
+        var $useProtocol = _this.$dialog.find('.sn-checkbox-use-protocol input[type=checkbox]');
+
+        _this.ui.onDialogShown(_this.$dialog, function () {
+          _this.context.triggerEvent('dialog.shown'); // If no url was given and given text is valid URL then copy that into URL Field
+
+
+          if (!linkInfo.url && func.isValidUrl(linkInfo.text)) {
+            linkInfo.url = linkInfo.text;
+          }
+
+          $linkText.on('input paste propertychange', function () {
+            // If linktext was modified by input events,
+            // cloning text from linkUrl will be stopped.
+            linkInfo.text = $linkText.val();
+
+            _this.toggleLinkBtn($linkBtn, $linkText, $linkUrl);
+          }).val(linkInfo.text);
+          $linkUrl.on('input paste propertychange', function () {
+            // Display same text on `Text to display` as default
+            // when linktext has no text
+            if (!linkInfo.text) {
+              $linkText.val($linkUrl.val());
+            }
+
+            _this.toggleLinkBtn($linkBtn, $linkText, $linkUrl);
+          }).val(linkInfo.url);
+
+          if (!env.isSupportTouch) {
+            $linkUrl.trigger('focus');
+          }
+
+          _this.toggleLinkBtn($linkBtn, $linkText, $linkUrl);
+
+          _this.bindEnterKey($linkUrl, $linkBtn);
+
+          _this.bindEnterKey($linkText, $linkBtn);
+
+          var isNewWindowChecked = linkInfo.isNewWindow !== undefined ? linkInfo.isNewWindow : _this.context.options.linkTargetBlank;
+          $openInNewWindow.prop('checked', isNewWindowChecked);
+          var useProtocolChecked = linkInfo.url ? false : _this.context.options.useProtocol;
+          $useProtocol.prop('checked', useProtocolChecked);
+          $linkBtn.one('click', function (event) {
+            event.preventDefault();
+            deferred.resolve({
+              range: linkInfo.range,
+              url: $linkUrl.val(),
+              text: $linkText.val(),
+              isNewWindow: $openInNewWindow.is(':checked'),
+              checkProtocol: $useProtocol.is(':checked')
+            });
+
+            _this.ui.hideDialog(_this.$dialog);
+          });
+        });
+
+        _this.ui.onDialogHidden(_this.$dialog, function () {
+          // detach events
+          $linkText.off();
+          $linkUrl.off();
+          $linkBtn.off();
+
+          if (deferred.state() === 'pending') {
+            deferred.reject();
+          }
+        });
+
+        _this.ui.showDialog(_this.$dialog);
+      }).promise();
+    }
+    /**
+     * @param {Object} layoutInfo
+     */
+
+  }, {
+    key: "show",
+    value: function show() {
+      var _this2 = this;
+
+      var linkInfo = this.context.invoke('editor.getLinkInfo');
+      this.context.invoke('editor.saveRange');
+      this.showLinkDialog(linkInfo).then(function (linkInfo) {
+        _this2.context.invoke('editor.restoreRange');
+
+        _this2.context.invoke('editor.createLink', linkInfo);
+      }).fail(function () {
+        _this2.context.invoke('editor.restoreRange');
+      });
+    }
+  }]);
+
+  return LinkDialog;
+}();
+
+
+// CONCATENATED MODULE: ./src/js/base/module/LinkPopover.js
+function LinkPopover_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function LinkPopover_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function LinkPopover_createClass(Constructor, protoProps, staticProps) { if (protoProps) LinkPopover_defineProperties(Constructor.prototype, protoProps); if (staticProps) LinkPopover_defineProperties(Constructor, staticProps); return Constructor; }
+
+
+
+
+
+var LinkPopover_LinkPopover = /*#__PURE__*/function () {
+  function LinkPopover(context) {
+    var _this = this;
+
+    LinkPopover_classCallCheck(this, LinkPopover);
+
+    this.context = context;
+    this.ui = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.summernote.ui;
+    this.options = context.options;
+    this.events = {
+      'summernote.keyup summernote.mouseup summernote.change summernote.scroll': function summernoteKeyupSummernoteMouseupSummernoteChangeSummernoteScroll() {
+        _this.update();
+      },
+      'summernote.disable summernote.dialog.shown summernote.blur': function summernoteDisableSummernoteDialogShownSummernoteBlur() {
+        _this.hide();
+      }
+    };
+  }
+
+  LinkPopover_createClass(LinkPopover, [{
+    key: "shouldInitialize",
+    value: function shouldInitialize() {
+      return !lists.isEmpty(this.options.popover.link);
+    }
+  }, {
+    key: "initialize",
+    value: function initialize() {
+      this.$popover = this.ui.popover({
+        className: 'note-link-popover',
+        callback: function callback($node) {
+          var $content = $node.find('.popover-content,.note-popover-content');
+          $content.prepend('<span><a target="_blank"></a>&nbsp;</span>');
+        }
+      }).render().appendTo(this.options.container);
+      var $content = this.$popover.find('.popover-content,.note-popover-content');
+      this.context.invoke('buttons.build', $content, this.options.popover.link);
+      this.$popover.on('mousedown', function (e) {
+        e.preventDefault();
+      });
+    }
+  }, {
+    key: "destroy",
+    value: function destroy() {
+      this.$popover.remove();
+    }
+  }, {
+    key: "update",
+    value: function update() {
+      // Prevent focusing on editable when invoke('code') is executed
+      if (!this.context.invoke('editor.hasFocus')) {
+        this.hide();
+        return;
+      }
+
+      var rng = this.context.invoke('editor.getLastRange');
+
+      if (rng.isCollapsed() && rng.isOnAnchor()) {
+        var anchor = dom.ancestor(rng.sc, dom.isAnchor);
+        var href = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(anchor).attr('href');
+        this.$popover.find('a').attr('href', href).text(href);
+        var pos = dom.posFromPlaceholder(anchor);
+        var containerOffset = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(this.options.container).offset();
+        pos.top -= containerOffset.top;
+        pos.left -= containerOffset.left;
+        this.$popover.css({
+          display: 'block',
+          left: pos.left,
+          top: pos.top
+        });
+      } else {
+        this.hide();
+      }
+    }
+  }, {
+    key: "hide",
+    value: function hide() {
+      this.$popover.hide();
+    }
+  }]);
+
+  return LinkPopover;
+}();
+
+
+// CONCATENATED MODULE: ./src/js/base/module/ImageDialog.js
+function ImageDialog_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function ImageDialog_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function ImageDialog_createClass(Constructor, protoProps, staticProps) { if (protoProps) ImageDialog_defineProperties(Constructor.prototype, protoProps); if (staticProps) ImageDialog_defineProperties(Constructor, staticProps); return Constructor; }
+
+
+
+
+
+var ImageDialog_ImageDialog = /*#__PURE__*/function () {
+  function ImageDialog(context) {
+    ImageDialog_classCallCheck(this, ImageDialog);
+
+    this.context = context;
+    this.ui = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.summernote.ui;
+    this.$body = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(document.body);
+    this.$editor = context.layoutInfo.editor;
+    this.options = context.options;
+    this.lang = this.options.langInfo;
+  }
+
+  ImageDialog_createClass(ImageDialog, [{
+    key: "initialize",
+    value: function initialize() {
+      var imageLimitation = '';
+
+      if (this.options.maximumImageFileSize) {
+        var unit = Math.floor(Math.log(this.options.maximumImageFileSize) / Math.log(1024));
+        var readableSize = (this.options.maximumImageFileSize / Math.pow(1024, unit)).toFixed(2) * 1 + ' ' + ' KMGTP'[unit] + 'B';
+        imageLimitation = "<small>".concat(this.lang.image.maximumFileSize + ' : ' + readableSize, "</small>");
+      }
+
+      var $container = this.options.dialogsInBody ? this.$body : this.options.container;
+      var body = ['<div class="form-group note-form-group note-group-select-from-files">', '<label for="note-dialog-image-file-' + this.options.id + '" class="note-form-label">' + this.lang.image.selectFromFiles + '</label>', '<input id="note-dialog-image-file-' + this.options.id + '" class="note-image-input form-control-file note-form-control note-input" ', ' type="file" name="files" accept="image/*" multiple="multiple"/>', imageLimitation, '</div>', '<div class="form-group note-group-image-url">', '<label for="note-dialog-image-url-' + this.options.id + '" class="note-form-label">' + this.lang.image.url + '</label>', '<input id="note-dialog-image-url-' + this.options.id + '" class="note-image-url form-control note-form-control note-input" type="text"/>', '</div>'].join('');
+      var buttonClass = 'btn btn-primary note-btn note-btn-primary note-image-btn';
+      var footer = "<input type=\"button\" href=\"#\" class=\"".concat(buttonClass, "\" value=\"").concat(this.lang.image.insert, "\" disabled>");
+      this.$dialog = this.ui.dialog({
+        title: this.lang.image.insert,
+        fade: this.options.dialogsFade,
+        body: body,
+        footer: footer
+      }).render().appendTo($container);
+    }
+  }, {
+    key: "destroy",
+    value: function destroy() {
+      this.ui.hideDialog(this.$dialog);
+      this.$dialog.remove();
+    }
+  }, {
+    key: "bindEnterKey",
+    value: function bindEnterKey($input, $btn) {
+      $input.on('keypress', function (event) {
+        if (event.keyCode === core_key.code.ENTER) {
+          event.preventDefault();
+          $btn.trigger('click');
+        }
+      });
+    }
+  }, {
+    key: "show",
+    value: function show() {
+      var _this = this;
+
+      this.context.invoke('editor.saveRange');
+      this.showImageDialog().then(function (data) {
+        // [workaround] hide dialog before restore range for IE range focus
+        _this.ui.hideDialog(_this.$dialog);
+
+        _this.context.invoke('editor.restoreRange');
+
+        if (typeof data === 'string') {
+          // image url
+          // If onImageLinkInsert set,
+          if (_this.options.callbacks.onImageLinkInsert) {
+            _this.context.triggerEvent('image.link.insert', data);
+          } else {
+            _this.context.invoke('editor.insertImage', data);
+          }
+        } else {
+          // array of files
+          _this.context.invoke('editor.insertImagesOrCallback', data);
+        }
+      }).fail(function () {
+        _this.context.invoke('editor.restoreRange');
+      });
+    }
+    /**
+     * show image dialog
+     *
+     * @param {jQuery} $dialog
+     * @return {Promise}
+     */
+
+  }, {
+    key: "showImageDialog",
+    value: function showImageDialog() {
+      var _this2 = this;
+
+      return external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.Deferred(function (deferred) {
+        var $imageInput = _this2.$dialog.find('.note-image-input');
+
+        var $imageUrl = _this2.$dialog.find('.note-image-url');
+
+        var $imageBtn = _this2.$dialog.find('.note-image-btn');
+
+        _this2.ui.onDialogShown(_this2.$dialog, function () {
+          _this2.context.triggerEvent('dialog.shown'); // Cloning imageInput to clear element.
+
+
+          $imageInput.replaceWith($imageInput.clone().on('change', function (event) {
+            deferred.resolve(event.target.files || event.target.value);
+          }).val(''));
+          $imageUrl.on('input paste propertychange', function () {
+            _this2.ui.toggleBtn($imageBtn, $imageUrl.val());
+          }).val('');
+
+          if (!env.isSupportTouch) {
+            $imageUrl.trigger('focus');
+          }
+
+          $imageBtn.click(function (event) {
+            event.preventDefault();
+            deferred.resolve($imageUrl.val());
+          });
+
+          _this2.bindEnterKey($imageUrl, $imageBtn);
+        });
+
+        _this2.ui.onDialogHidden(_this2.$dialog, function () {
+          $imageInput.off();
+          $imageUrl.off();
+          $imageBtn.off();
+
+          if (deferred.state() === 'pending') {
+            deferred.reject();
+          }
+        });
+
+        _this2.ui.showDialog(_this2.$dialog);
+      });
+    }
+  }]);
+
+  return ImageDialog;
+}();
+
+
+// CONCATENATED MODULE: ./src/js/base/module/ImagePopover.js
+function ImagePopover_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function ImagePopover_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function ImagePopover_createClass(Constructor, protoProps, staticProps) { if (protoProps) ImagePopover_defineProperties(Constructor.prototype, protoProps); if (staticProps) ImagePopover_defineProperties(Constructor, staticProps); return Constructor; }
+
+
+
+
+/**
+ * Image popover module
+ *  mouse events that show/hide popover will be handled by Handle.js.
+ *  Handle.js will receive the events and invoke 'imagePopover.update'.
+ */
+
+var ImagePopover_ImagePopover = /*#__PURE__*/function () {
+  function ImagePopover(context) {
+    var _this = this;
+
+    ImagePopover_classCallCheck(this, ImagePopover);
+
+    this.context = context;
+    this.ui = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.summernote.ui;
+    this.editable = context.layoutInfo.editable[0];
+    this.options = context.options;
+    this.events = {
+      'summernote.disable summernote.blur': function summernoteDisableSummernoteBlur() {
+        _this.hide();
+      }
+    };
+  }
+
+  ImagePopover_createClass(ImagePopover, [{
+    key: "shouldInitialize",
+    value: function shouldInitialize() {
+      return !lists.isEmpty(this.options.popover.image);
+    }
+  }, {
+    key: "initialize",
+    value: function initialize() {
+      this.$popover = this.ui.popover({
+        className: 'note-image-popover'
+      }).render().appendTo(this.options.container);
+      var $content = this.$popover.find('.popover-content,.note-popover-content');
+      this.context.invoke('buttons.build', $content, this.options.popover.image);
+      this.$popover.on('mousedown', function (e) {
+        e.preventDefault();
+      });
+    }
+  }, {
+    key: "destroy",
+    value: function destroy() {
+      this.$popover.remove();
+    }
+  }, {
+    key: "update",
+    value: function update(target, event) {
+      if (dom.isImg(target)) {
+        var position = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(target).offset();
+        var containerOffset = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(this.options.container).offset();
+        var pos = {};
+
+        if (this.options.popatmouse) {
+          pos.left = event.pageX - 20;
+          pos.top = event.pageY;
+        } else {
+          pos = position;
+        }
+
+        pos.top -= containerOffset.top;
+        pos.left -= containerOffset.left;
+        this.$popover.css({
+          display: 'block',
+          left: pos.left,
+          top: pos.top
+        });
+      } else {
+        this.hide();
+      }
+    }
+  }, {
+    key: "hide",
+    value: function hide() {
+      this.$popover.hide();
+    }
+  }]);
+
+  return ImagePopover;
+}();
+
+
+// CONCATENATED MODULE: ./src/js/base/module/TablePopover.js
+function TablePopover_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function TablePopover_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function TablePopover_createClass(Constructor, protoProps, staticProps) { if (protoProps) TablePopover_defineProperties(Constructor.prototype, protoProps); if (staticProps) TablePopover_defineProperties(Constructor, staticProps); return Constructor; }
+
+
+
+
+
+
+var TablePopover_TablePopover = /*#__PURE__*/function () {
+  function TablePopover(context) {
+    var _this = this;
+
+    TablePopover_classCallCheck(this, TablePopover);
+
+    this.context = context;
+    this.ui = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.summernote.ui;
+    this.options = context.options;
+    this.events = {
+      'summernote.mousedown': function summernoteMousedown(we, e) {
+        _this.update(e.target);
+      },
+      'summernote.keyup summernote.scroll summernote.change': function summernoteKeyupSummernoteScrollSummernoteChange() {
+        _this.update();
+      },
+      'summernote.disable summernote.blur': function summernoteDisableSummernoteBlur() {
+        _this.hide();
+      }
+    };
+  }
+
+  TablePopover_createClass(TablePopover, [{
+    key: "shouldInitialize",
+    value: function shouldInitialize() {
+      return !lists.isEmpty(this.options.popover.table);
+    }
+  }, {
+    key: "initialize",
+    value: function initialize() {
+      this.$popover = this.ui.popover({
+        className: 'note-table-popover'
+      }).render().appendTo(this.options.container);
+      var $content = this.$popover.find('.popover-content,.note-popover-content');
+      this.context.invoke('buttons.build', $content, this.options.popover.table); // [workaround] Disable Firefox's default table editor
+
+      if (env.isFF) {
+        document.execCommand('enableInlineTableEditing', false, false);
+      }
+
+      this.$popover.on('mousedown', function (e) {
+        e.preventDefault();
+      });
+    }
+  }, {
+    key: "destroy",
+    value: function destroy() {
+      this.$popover.remove();
+    }
+  }, {
+    key: "update",
+    value: function update(target) {
+      if (this.context.isDisabled()) {
+        return false;
+      }
+
+      var isCell = dom.isCell(target);
+
+      if (isCell) {
+        var pos = dom.posFromPlaceholder(target);
+        var containerOffset = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(this.options.container).offset();
+        pos.top -= containerOffset.top;
+        pos.left -= containerOffset.left;
+        this.$popover.css({
+          display: 'block',
+          left: pos.left,
+          top: pos.top
+        });
+      } else {
+        this.hide();
+      }
+
+      return isCell;
+    }
+  }, {
+    key: "hide",
+    value: function hide() {
+      this.$popover.hide();
+    }
+  }]);
+
+  return TablePopover;
+}();
+
+
+// CONCATENATED MODULE: ./src/js/base/module/VideoDialog.js
+function VideoDialog_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function VideoDialog_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function VideoDialog_createClass(Constructor, protoProps, staticProps) { if (protoProps) VideoDialog_defineProperties(Constructor.prototype, protoProps); if (staticProps) VideoDialog_defineProperties(Constructor, staticProps); return Constructor; }
+
+
+
+
+
+var VideoDialog_VideoDialog = /*#__PURE__*/function () {
+  function VideoDialog(context) {
+    VideoDialog_classCallCheck(this, VideoDialog);
+
+    this.context = context;
+    this.ui = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.summernote.ui;
+    this.$body = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(document.body);
+    this.$editor = context.layoutInfo.editor;
+    this.options = context.options;
+    this.lang = this.options.langInfo;
+  }
+
+  VideoDialog_createClass(VideoDialog, [{
+    key: "initialize",
+    value: function initialize() {
+      var $container = this.options.dialogsInBody ? this.$body : this.options.container;
+      var body = ['<div class="form-group note-form-group row-fluid">', "<label for=\"note-dialog-video-url-".concat(this.options.id, "\" class=\"note-form-label\">").concat(this.lang.video.url, " <small class=\"text-muted\">").concat(this.lang.video.providers, "</small></label>"), "<input id=\"note-dialog-video-url-".concat(this.options.id, "\" class=\"note-video-url form-control note-form-control note-input\" type=\"text\"/>"), '</div>'].join('');
+      var buttonClass = 'btn btn-primary note-btn note-btn-primary note-video-btn';
+      var footer = "<input type=\"button\" href=\"#\" class=\"".concat(buttonClass, "\" value=\"").concat(this.lang.video.insert, "\" disabled>");
+      this.$dialog = this.ui.dialog({
+        title: this.lang.video.insert,
+        fade: this.options.dialogsFade,
+        body: body,
+        footer: footer
+      }).render().appendTo($container);
+    }
+  }, {
+    key: "destroy",
+    value: function destroy() {
+      this.ui.hideDialog(this.$dialog);
+      this.$dialog.remove();
+    }
+  }, {
+    key: "bindEnterKey",
+    value: function bindEnterKey($input, $btn) {
+      $input.on('keypress', function (event) {
+        if (event.keyCode === core_key.code.ENTER) {
+          event.preventDefault();
+          $btn.trigger('click');
+        }
+      });
+    }
+  }, {
+    key: "createVideoNode",
+    value: function createVideoNode(url) {
+      // video url patterns(youtube, instagram, vimeo, dailymotion, youku, mp4, ogg, webm)
+      var ytRegExp = /\/\/(?:(?:www|m)\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))([\w|-]{11})(?:(?:[\?&]t=)(\S+))?$/;
+      var ytRegExpForStart = /^(?:(\d+)h)?(?:(\d+)m)?(?:(\d+)s)?$/;
+      var ytMatch = url.match(ytRegExp);
+      var igRegExp = /(?:www\.|\/\/)instagram\.com\/p\/(.[a-zA-Z0-9_-]*)/;
+      var igMatch = url.match(igRegExp);
+      var vRegExp = /\/\/vine\.co\/v\/([a-zA-Z0-9]+)/;
+      var vMatch = url.match(vRegExp);
+      var vimRegExp = /\/\/(player\.)?vimeo\.com\/([a-z]*\/)*(\d+)[?]?.*/;
+      var vimMatch = url.match(vimRegExp);
+      var dmRegExp = /.+dailymotion.com\/(video|hub)\/([^_]+)[^#]*(#video=([^_&]+))?/;
+      var dmMatch = url.match(dmRegExp);
+      var youkuRegExp = /\/\/v\.youku\.com\/v_show\/id_(\w+)=*\.html/;
+      var youkuMatch = url.match(youkuRegExp);
+      var qqRegExp = /\/\/v\.qq\.com.*?vid=(.+)/;
+      var qqMatch = url.match(qqRegExp);
+      var qqRegExp2 = /\/\/v\.qq\.com\/x?\/?(page|cover).*?\/([^\/]+)\.html\??.*/;
+      var qqMatch2 = url.match(qqRegExp2);
+      var mp4RegExp = /^.+.(mp4|m4v)$/;
+      var mp4Match = url.match(mp4RegExp);
+      var oggRegExp = /^.+.(ogg|ogv)$/;
+      var oggMatch = url.match(oggRegExp);
+      var webmRegExp = /^.+.(webm)$/;
+      var webmMatch = url.match(webmRegExp);
+      var fbRegExp = /(?:www\.|\/\/)facebook\.com\/([^\/]+)\/videos\/([0-9]+)/;
+      var fbMatch = url.match(fbRegExp);
+      var $video;
+
+      if (ytMatch && ytMatch[1].length === 11) {
+        var youtubeId = ytMatch[1];
+        var start = 0;
+
+        if (typeof ytMatch[2] !== 'undefined') {
+          var ytMatchForStart = ytMatch[2].match(ytRegExpForStart);
+
+          if (ytMatchForStart) {
+            for (var n = [3600, 60, 1], i = 0, r = n.length; i < r; i++) {
+              start += typeof ytMatchForStart[i + 1] !== 'undefined' ? n[i] * parseInt(ytMatchForStart[i + 1], 10) : 0;
+            }
+          }
+        }
+
+        $video = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()('<iframe>').attr('frameborder', 0).attr('src', '//www.youtube.com/embed/' + youtubeId + (start > 0 ? '?start=' + start : '')).attr('width', '640').attr('height', '360');
+      } else if (igMatch && igMatch[0].length) {
+        $video = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()('<iframe>').attr('frameborder', 0).attr('src', 'https://instagram.com/p/' + igMatch[1] + '/embed/').attr('width', '612').attr('height', '710').attr('scrolling', 'no').attr('allowtransparency', 'true');
+      } else if (vMatch && vMatch[0].length) {
+        $video = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()('<iframe>').attr('frameborder', 0).attr('src', vMatch[0] + '/embed/simple').attr('width', '600').attr('height', '600').attr('class', 'vine-embed');
+      } else if (vimMatch && vimMatch[3].length) {
+        $video = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()('<iframe webkitallowfullscreen mozallowfullscreen allowfullscreen>').attr('frameborder', 0).attr('src', '//player.vimeo.com/video/' + vimMatch[3]).attr('width', '640').attr('height', '360');
+      } else if (dmMatch && dmMatch[2].length) {
+        $video = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()('<iframe>').attr('frameborder', 0).attr('src', '//www.dailymotion.com/embed/video/' + dmMatch[2]).attr('width', '640').attr('height', '360');
+      } else if (youkuMatch && youkuMatch[1].length) {
+        $video = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()('<iframe webkitallowfullscreen mozallowfullscreen allowfullscreen>').attr('frameborder', 0).attr('height', '498').attr('width', '510').attr('src', '//player.youku.com/embed/' + youkuMatch[1]);
+      } else if (qqMatch && qqMatch[1].length || qqMatch2 && qqMatch2[2].length) {
+        var vid = qqMatch && qqMatch[1].length ? qqMatch[1] : qqMatch2[2];
+        $video = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()('<iframe webkitallowfullscreen mozallowfullscreen allowfullscreen>').attr('frameborder', 0).attr('height', '310').attr('width', '500').attr('src', 'https://v.qq.com/txp/iframe/player.html?vid=' + vid + '&amp;auto=0');
+      } else if (mp4Match || oggMatch || webmMatch) {
+        $video = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()('<video controls>').attr('src', url).attr('width', '640').attr('height', '360');
+      } else if (fbMatch && fbMatch[0].length) {
+        $video = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()('<iframe>').attr('frameborder', 0).attr('src', 'https://www.facebook.com/plugins/video.php?href=' + encodeURIComponent(fbMatch[0]) + '&show_text=0&width=560').attr('width', '560').attr('height', '301').attr('scrolling', 'no').attr('allowtransparency', 'true');
+      } else {
+        // this is not a known video link. Now what, Cat? Now what?
+        return false;
+      }
+
+      $video.addClass('note-video-clip');
+      return $video[0];
+    }
+  }, {
+    key: "show",
+    value: function show() {
+      var _this = this;
+
+      var text = this.context.invoke('editor.getSelectedText');
+      this.context.invoke('editor.saveRange');
+      this.showVideoDialog(text).then(function (url) {
+        // [workaround] hide dialog before restore range for IE range focus
+        _this.ui.hideDialog(_this.$dialog);
+
+        _this.context.invoke('editor.restoreRange'); // build node
+
+
+        var $node = _this.createVideoNode(url);
+
+        if ($node) {
+          // insert video node
+          _this.context.invoke('editor.insertNode', $node);
+        }
+      }).fail(function () {
+        _this.context.invoke('editor.restoreRange');
+      });
+    }
+    /**
+     * show video dialog
+     *
+     * @param {jQuery} $dialog
+     * @return {Promise}
+     */
+
+  }, {
+    key: "showVideoDialog",
+    value: function showVideoDialog()
+    /* text */
+    {
+      var _this2 = this;
+
+      return external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.Deferred(function (deferred) {
+        var $videoUrl = _this2.$dialog.find('.note-video-url');
+
+        var $videoBtn = _this2.$dialog.find('.note-video-btn');
+
+        _this2.ui.onDialogShown(_this2.$dialog, function () {
+          _this2.context.triggerEvent('dialog.shown');
+
+          $videoUrl.on('input paste propertychange', function () {
+            _this2.ui.toggleBtn($videoBtn, $videoUrl.val());
+          });
+
+          if (!env.isSupportTouch) {
+            $videoUrl.trigger('focus');
+          }
+
+          $videoBtn.click(function (event) {
+            event.preventDefault();
+            deferred.resolve($videoUrl.val());
+          });
+
+          _this2.bindEnterKey($videoUrl, $videoBtn);
+        });
+
+        _this2.ui.onDialogHidden(_this2.$dialog, function () {
+          $videoUrl.off();
+          $videoBtn.off();
+
+          if (deferred.state() === 'pending') {
+            deferred.reject();
+          }
+        });
+
+        _this2.ui.showDialog(_this2.$dialog);
+      });
+    }
+  }]);
+
+  return VideoDialog;
+}();
+
+
+// CONCATENATED MODULE: ./src/js/base/module/HelpDialog.js
+function HelpDialog_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function HelpDialog_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function HelpDialog_createClass(Constructor, protoProps, staticProps) { if (protoProps) HelpDialog_defineProperties(Constructor.prototype, protoProps); if (staticProps) HelpDialog_defineProperties(Constructor, staticProps); return Constructor; }
+
+
+
+
+var HelpDialog_HelpDialog = /*#__PURE__*/function () {
+  function HelpDialog(context) {
+    HelpDialog_classCallCheck(this, HelpDialog);
+
+    this.context = context;
+    this.ui = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.summernote.ui;
+    this.$body = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(document.body);
+    this.$editor = context.layoutInfo.editor;
+    this.options = context.options;
+    this.lang = this.options.langInfo;
+  }
+
+  HelpDialog_createClass(HelpDialog, [{
+    key: "initialize",
+    value: function initialize() {
+      var $container = this.options.dialogsInBody ? this.$body : this.options.container;
+      var body = ['<p class="text-center">', '<a href="http://summernote.org/" target="_blank">Summernote 0.8.18</a> · ', '<a href="https://github.com/summernote/summernote" target="_blank">Project</a> · ', '<a href="https://github.com/summernote/summernote/issues" target="_blank">Issues</a>', '</p>'].join('');
+      this.$dialog = this.ui.dialog({
+        title: this.lang.options.help,
+        fade: this.options.dialogsFade,
+        body: this.createShortcutList(),
+        footer: body,
+        callback: function callback($node) {
+          $node.find('.modal-body,.note-modal-body').css({
+            'max-height': 300,
+            'overflow': 'scroll'
+          });
+        }
+      }).render().appendTo($container);
+    }
+  }, {
+    key: "destroy",
+    value: function destroy() {
+      this.ui.hideDialog(this.$dialog);
+      this.$dialog.remove();
+    }
+  }, {
+    key: "createShortcutList",
+    value: function createShortcutList() {
+      var _this = this;
+
+      var keyMap = this.options.keyMap[env.isMac ? 'mac' : 'pc'];
+      return Object.keys(keyMap).map(function (key) {
+        var command = keyMap[key];
+        var $row = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()('<div><div class="help-list-item"></div></div>');
+        $row.append(external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()('<label><kbd>' + key + '</kdb></label>').css({
+          'width': 180,
+          'margin-right': 10
+        })).append(external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()('<span/>').html(_this.context.memo('help.' + command) || command));
+        return $row.html();
+      }).join('');
+    }
+    /**
+     * show help dialog
+     *
+     * @return {Promise}
+     */
+
+  }, {
+    key: "showHelpDialog",
+    value: function showHelpDialog() {
+      var _this2 = this;
+
+      return external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.Deferred(function (deferred) {
+        _this2.ui.onDialogShown(_this2.$dialog, function () {
+          _this2.context.triggerEvent('dialog.shown');
+
+          deferred.resolve();
+        });
+
+        _this2.ui.showDialog(_this2.$dialog);
+      }).promise();
+    }
+  }, {
+    key: "show",
+    value: function show() {
+      var _this3 = this;
+
+      this.context.invoke('editor.saveRange');
+      this.showHelpDialog().then(function () {
+        _this3.context.invoke('editor.restoreRange');
+      });
+    }
+  }]);
+
+  return HelpDialog;
+}();
+
+
+// CONCATENATED MODULE: ./src/js/base/module/AirPopover.js
+function AirPopover_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function AirPopover_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function AirPopover_createClass(Constructor, protoProps, staticProps) { if (protoProps) AirPopover_defineProperties(Constructor.prototype, protoProps); if (staticProps) AirPopover_defineProperties(Constructor, staticProps); return Constructor; }
+
+
+
+var AIRMODE_POPOVER_X_OFFSET = -5;
+var AIRMODE_POPOVER_Y_OFFSET = 5;
+
+var AirPopover_AirPopover = /*#__PURE__*/function () {
+  function AirPopover(context) {
+    var _this = this;
+
+    AirPopover_classCallCheck(this, AirPopover);
+
+    this.context = context;
+    this.ui = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.summernote.ui;
+    this.options = context.options;
+    this.hidable = true;
+    this.onContextmenu = false;
+    this.pageX = null;
+    this.pageY = null;
+    this.events = {
+      'summernote.contextmenu': function summernoteContextmenu(e) {
+        if (_this.options.editing) {
+          e.preventDefault();
+          e.stopPropagation();
+          _this.onContextmenu = true;
+
+          _this.update(true);
+        }
+      },
+      'summernote.mousedown': function summernoteMousedown(we, e) {
+        _this.pageX = e.pageX;
+        _this.pageY = e.pageY;
+      },
+      'summernote.keyup summernote.mouseup summernote.scroll': function summernoteKeyupSummernoteMouseupSummernoteScroll(we, e) {
+        if (_this.options.editing && !_this.onContextmenu) {
+          _this.pageX = e.pageX;
+          _this.pageY = e.pageY;
+
+          _this.update();
+        }
+
+        _this.onContextmenu = false;
+      },
+      'summernote.disable summernote.change summernote.dialog.shown summernote.blur': function summernoteDisableSummernoteChangeSummernoteDialogShownSummernoteBlur() {
+        _this.hide();
+      },
+      'summernote.focusout': function summernoteFocusout() {
+        if (!_this.$popover.is(':active,:focus')) {
+          _this.hide();
+        }
+      }
+    };
+  }
+
+  AirPopover_createClass(AirPopover, [{
+    key: "shouldInitialize",
+    value: function shouldInitialize() {
+      return this.options.airMode && !lists.isEmpty(this.options.popover.air);
+    }
+  }, {
+    key: "initialize",
+    value: function initialize() {
+      var _this2 = this;
+
+      this.$popover = this.ui.popover({
+        className: 'note-air-popover'
+      }).render().appendTo(this.options.container);
+      var $content = this.$popover.find('.popover-content');
+      this.context.invoke('buttons.build', $content, this.options.popover.air); // disable hiding this popover preemptively by 'summernote.blur' event.
+
+      this.$popover.on('mousedown', function () {
+        _this2.hidable = false;
+      }); // (re-)enable hiding after 'summernote.blur' has been handled (aka. ignored).
+
+      this.$popover.on('mouseup', function () {
+        _this2.hidable = true;
+      });
+    }
+  }, {
+    key: "destroy",
+    value: function destroy() {
+      this.$popover.remove();
+    }
+  }, {
+    key: "update",
+    value: function update(forcelyOpen) {
+      var styleInfo = this.context.invoke('editor.currentStyle');
+
+      if (styleInfo.range && (!styleInfo.range.isCollapsed() || forcelyOpen)) {
+        var rect = {
+          left: this.pageX,
+          top: this.pageY
+        };
+        var containerOffset = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(this.options.container).offset();
+        rect.top -= containerOffset.top;
+        rect.left -= containerOffset.left;
+        this.$popover.css({
+          display: 'block',
+          left: Math.max(rect.left, 0) + AIRMODE_POPOVER_X_OFFSET,
+          top: rect.top + AIRMODE_POPOVER_Y_OFFSET
+        });
+        this.context.invoke('buttons.updateCurrentStyle', this.$popover);
+      } else {
+        this.hide();
+      }
+    }
+  }, {
+    key: "updateCodeview",
+    value: function updateCodeview(isCodeview) {
+      this.ui.toggleBtnActive(this.$popover.find('.btn-codeview'), isCodeview);
+
+      if (isCodeview) {
+        this.hide();
+      }
+    }
+  }, {
+    key: "hide",
+    value: function hide() {
+      if (this.hidable) {
+        this.$popover.hide();
+      }
+    }
+  }]);
+
+  return AirPopover;
+}();
+
+
+// CONCATENATED MODULE: ./src/js/base/module/HintPopover.js
+function HintPopover_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function HintPopover_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function HintPopover_createClass(Constructor, protoProps, staticProps) { if (protoProps) HintPopover_defineProperties(Constructor.prototype, protoProps); if (staticProps) HintPopover_defineProperties(Constructor, staticProps); return Constructor; }
+
+
+
+
+
+
+
+var POPOVER_DIST = 5;
+
+var HintPopover_HintPopover = /*#__PURE__*/function () {
+  function HintPopover(context) {
+    var _this = this;
+
+    HintPopover_classCallCheck(this, HintPopover);
+
+    this.context = context;
+    this.ui = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.summernote.ui;
+    this.$editable = context.layoutInfo.editable;
+    this.options = context.options;
+    this.hint = this.options.hint || [];
+    this.direction = this.options.hintDirection || 'bottom';
+    this.hints = Array.isArray(this.hint) ? this.hint : [this.hint];
+    this.events = {
+      'summernote.keyup': function summernoteKeyup(we, e) {
+        if (!e.isDefaultPrevented()) {
+          _this.handleKeyup(e);
+        }
+      },
+      'summernote.keydown': function summernoteKeydown(we, e) {
+        _this.handleKeydown(e);
+      },
+      'summernote.disable summernote.dialog.shown summernote.blur': function summernoteDisableSummernoteDialogShownSummernoteBlur() {
+        _this.hide();
+      }
+    };
+  }
+
+  HintPopover_createClass(HintPopover, [{
+    key: "shouldInitialize",
+    value: function shouldInitialize() {
+      return this.hints.length > 0;
+    }
+  }, {
+    key: "initialize",
+    value: function initialize() {
+      var _this2 = this;
+
+      this.lastWordRange = null;
+      this.matchingWord = null;
+      this.$popover = this.ui.popover({
+        className: 'note-hint-popover',
+        hideArrow: true,
+        direction: ''
+      }).render().appendTo(this.options.container);
+      this.$popover.hide();
+      this.$content = this.$popover.find('.popover-content,.note-popover-content');
+      this.$content.on('click', '.note-hint-item', function (e) {
+        _this2.$content.find('.active').removeClass('active');
+
+        external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(e.currentTarget).addClass('active');
+
+        _this2.replace();
+      });
+      this.$popover.on('mousedown', function (e) {
+        e.preventDefault();
+      });
+    }
+  }, {
+    key: "destroy",
+    value: function destroy() {
+      this.$popover.remove();
+    }
+  }, {
+    key: "selectItem",
+    value: function selectItem($item) {
+      this.$content.find('.active').removeClass('active');
+      $item.addClass('active');
+      this.$content[0].scrollTop = $item[0].offsetTop - this.$content.innerHeight() / 2;
+    }
+  }, {
+    key: "moveDown",
+    value: function moveDown() {
+      var $current = this.$content.find('.note-hint-item.active');
+      var $next = $current.next();
+
+      if ($next.length) {
+        this.selectItem($next);
+      } else {
+        var $nextGroup = $current.parent().next();
+
+        if (!$nextGroup.length) {
+          $nextGroup = this.$content.find('.note-hint-group').first();
+        }
+
+        this.selectItem($nextGroup.find('.note-hint-item').first());
+      }
+    }
+  }, {
+    key: "moveUp",
+    value: function moveUp() {
+      var $current = this.$content.find('.note-hint-item.active');
+      var $prev = $current.prev();
+
+      if ($prev.length) {
+        this.selectItem($prev);
+      } else {
+        var $prevGroup = $current.parent().prev();
+
+        if (!$prevGroup.length) {
+          $prevGroup = this.$content.find('.note-hint-group').last();
+        }
+
+        this.selectItem($prevGroup.find('.note-hint-item').last());
+      }
+    }
+  }, {
+    key: "replace",
+    value: function replace() {
+      var $item = this.$content.find('.note-hint-item.active');
+
+      if ($item.length) {
+        var node = this.nodeFromItem($item); // If matchingWord length = 0 -> capture OK / open hint / but as mention capture "" (\w*)
+
+        if (this.matchingWord !== null && this.matchingWord.length === 0) {
+          this.lastWordRange.so = this.lastWordRange.eo; // Else si > 0 and normal case -> adjust range "before" for correct position of insertion
+        } else if (this.matchingWord !== null && this.matchingWord.length > 0 && !this.lastWordRange.isCollapsed()) {
+          var rangeCompute = this.lastWordRange.eo - this.lastWordRange.so - this.matchingWord.length;
+
+          if (rangeCompute > 0) {
+            this.lastWordRange.so += rangeCompute;
+          }
+        }
+
+        this.lastWordRange.insertNode(node);
+
+        if (this.options.hintSelect === 'next') {
+          var blank = document.createTextNode('');
+          external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(node).after(blank);
+          range.createFromNodeBefore(blank).select();
+        } else {
+          range.createFromNodeAfter(node).select();
+        }
+
+        this.lastWordRange = null;
+        this.hide();
+        this.context.invoke('editor.focus');
+      }
+    }
+  }, {
+    key: "nodeFromItem",
+    value: function nodeFromItem($item) {
+      var hint = this.hints[$item.data('index')];
+      var item = $item.data('item');
+      var node = hint.content ? hint.content(item) : item;
+
+      if (typeof node === 'string') {
+        node = dom.createText(node);
+      }
+
+      return node;
+    }
+  }, {
+    key: "createItemTemplates",
+    value: function createItemTemplates(hintIdx, items) {
+      var hint = this.hints[hintIdx];
+      return items.map(function (item
+      /*, idx */
+      ) {
+        var $item = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()('<div class="note-hint-item"/>');
+        $item.append(hint.template ? hint.template(item) : item + '');
+        $item.data({
+          'index': hintIdx,
+          'item': item
+        });
+        return $item;
+      });
+    }
+  }, {
+    key: "handleKeydown",
+    value: function handleKeydown(e) {
+      if (!this.$popover.is(':visible')) {
+        return;
+      }
+
+      if (e.keyCode === core_key.code.ENTER) {
+        e.preventDefault();
+        this.replace();
+      } else if (e.keyCode === core_key.code.UP) {
+        e.preventDefault();
+        this.moveUp();
+      } else if (e.keyCode === core_key.code.DOWN) {
+        e.preventDefault();
+        this.moveDown();
+      }
+    }
+  }, {
+    key: "searchKeyword",
+    value: function searchKeyword(index, keyword, callback) {
+      var hint = this.hints[index];
+
+      if (hint && hint.match.test(keyword) && hint.search) {
+        var matches = hint.match.exec(keyword);
+        this.matchingWord = matches[0];
+        hint.search(matches[1], callback);
+      } else {
+        callback();
+      }
+    }
+  }, {
+    key: "createGroup",
+    value: function createGroup(idx, keyword) {
+      var _this3 = this;
+
+      var $group = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()('<div class="note-hint-group note-hint-group-' + idx + '"></div>');
+      this.searchKeyword(idx, keyword, function (items) {
+        items = items || [];
+
+        if (items.length) {
+          $group.html(_this3.createItemTemplates(idx, items));
+
+          _this3.show();
+        }
+      });
+      return $group;
+    }
+  }, {
+    key: "handleKeyup",
+    value: function handleKeyup(e) {
+      var _this4 = this;
+
+      if (!lists.contains([core_key.code.ENTER, core_key.code.UP, core_key.code.DOWN], e.keyCode)) {
+        var _range = this.context.invoke('editor.getLastRange');
+
+        var wordRange, keyword;
+
+        if (this.options.hintMode === 'words') {
+          wordRange = _range.getWordsRange(_range);
+          keyword = wordRange.toString();
+          this.hints.forEach(function (hint) {
+            if (hint.match.test(keyword)) {
+              wordRange = _range.getWordsMatchRange(hint.match);
+              return false;
+            }
+          });
+
+          if (!wordRange) {
+            this.hide();
+            return;
+          }
+
+          keyword = wordRange.toString();
+        } else {
+          wordRange = _range.getWordRange();
+          keyword = wordRange.toString();
+        }
+
+        if (this.hints.length && keyword) {
+          this.$content.empty();
+          var bnd = func.rect2bnd(lists.last(wordRange.getClientRects()));
+          var containerOffset = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(this.options.container).offset();
+
+          if (bnd) {
+            bnd.top -= containerOffset.top;
+            bnd.left -= containerOffset.left;
+            this.$popover.hide();
+            this.lastWordRange = wordRange;
+            this.hints.forEach(function (hint, idx) {
+              if (hint.match.test(keyword)) {
+                _this4.createGroup(idx, keyword).appendTo(_this4.$content);
+              }
+            }); // select first .note-hint-item
+
+            this.$content.find('.note-hint-item:first').addClass('active'); // set position for popover after group is created
+
+            if (this.direction === 'top') {
+              this.$popover.css({
+                left: bnd.left,
+                top: bnd.top - this.$popover.outerHeight() - POPOVER_DIST
+              });
+            } else {
+              this.$popover.css({
+                left: bnd.left,
+                top: bnd.top + bnd.height + POPOVER_DIST
+              });
+            }
+          }
+        } else {
+          this.hide();
+        }
+      }
+    }
+  }, {
+    key: "show",
+    value: function show() {
+      this.$popover.show();
+    }
+  }, {
+    key: "hide",
+    value: function hide() {
+      this.$popover.hide();
+    }
+  }]);
+
+  return HintPopover;
+}();
+
+
+// CONCATENATED MODULE: ./src/js/base/settings.js
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.summernote = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.extend(external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.summernote, {
+  version: '0.8.18',
+  plugins: {},
+  dom: dom,
+  range: range,
+  lists: lists,
+  options: {
+    langInfo: external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.summernote.lang['en-US'],
+    editing: true,
+    modules: {
+      'editor': Editor_Editor,
+      'clipboard': Clipboard_Clipboard,
+      'dropzone': Dropzone_Dropzone,
+      'codeview': Codeview_CodeView,
+      'statusbar': Statusbar_Statusbar,
+      'fullscreen': Fullscreen_Fullscreen,
+      'handle': Handle_Handle,
+      // FIXME: HintPopover must be front of autolink
+      //  - Script error about range when Enter key is pressed on hint popover
+      'hintPopover': HintPopover_HintPopover,
+      'autoLink': AutoLink_AutoLink,
+      'autoSync': AutoSync_AutoSync,
+      'autoReplace': AutoReplace_AutoReplace,
+      'placeholder': Placeholder_Placeholder,
+      'buttons': Buttons_Buttons,
+      'toolbar': Toolbar_Toolbar,
+      'linkDialog': LinkDialog_LinkDialog,
+      'linkPopover': LinkPopover_LinkPopover,
+      'imageDialog': ImageDialog_ImageDialog,
+      'imagePopover': ImagePopover_ImagePopover,
+      'tablePopover': TablePopover_TablePopover,
+      'videoDialog': VideoDialog_VideoDialog,
+      'helpDialog': HelpDialog_HelpDialog,
+      'airPopover': AirPopover_AirPopover
+    },
+    buttons: {},
+    lang: 'en-US',
+    followingToolbar: false,
+    toolbarPosition: 'top',
+    otherStaticBar: '',
+    // toolbar
+    codeviewKeepButton: false,
+    toolbar: [['style', ['style']], ['font', ['bold', 'underline', 'clear']], ['fontsize',['fontsize']], ['fontname', ['fontname']], ['color', ['color']], ['para', ['ul', 'ol', 'paragraph']], ['table', ['table']], ['insert', ['link', 'picture', 'video']], ['view', ['fullscreen', 'codeview', 'help']]],
+    // popover
+    popatmouse: true,
+    popover: {
+      image: [['resize', ['resizeFull', 'resizeHalf', 'resizeQuarter', 'resizeNone']], ['float', ['floatLeft', 'floatRight', 'floatNone']], ['remove', ['removeMedia']]],
+      link: [['link', ['linkDialogShow', 'unlink']]],
+      table: [['add', ['addRowDown', 'addRowUp', 'addColLeft', 'addColRight']], ['delete', ['deleteRow', 'deleteCol', 'deleteTable']]],
+      air: [['color', ['color']], ['font', ['bold', 'underline', 'clear']], ['para', ['ul', 'paragraph']], ['table', ['table']], ['insert', ['link', 'picture']], ['view', ['fullscreen', 'codeview']]]
+    },
+    // air mode: inline editor
+    airMode: false,
+    overrideContextMenu: false,
+    // TBD
+    width: null,
+    height: null,
+    linkTargetBlank: true,
+    useProtocol: true,
+    defaultProtocol: 'http://',
+    focus: false,
+    tabDisabled: false,
+    tabSize: 4,
+    styleWithCSS: false,
+    shortcuts: true,
+    textareaAutoSync: true,
+    tooltip: 'auto',
+    container: null,
+    maxTextLength: 0,
+    blockquoteBreakingLevel: 2,
+    spellCheck: true,
+    disableGrammar: false,
+    placeholder: null,
+    inheritPlaceholder: false,
+    // TODO: need to be documented
+    recordEveryKeystroke: false,
+    historyLimit: 200,
+    // TODO: need to be documented
+    showDomainOnlyForAutolink: false,
+    // TODO: need to be documented
+    hintMode: 'word',
+    hintSelect: 'after',
+    hintDirection: 'bottom',
+    styleTags: ['p', 'blockquote', 'pre', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'],
+    fontNames: ['Arial', 'Arial Black', 'Comic Sans MS', 'Courier New', 'Helvetica Neue', 'Helvetica', 'Impact', 'Lucida Grande', 'Tahoma', 'Times New Roman', 'Verdana'],
+    fontNamesIgnoreCheck: [],
+    addDefaultFonts: true,
+    fontSizes: ['8', '9', '10', '11', '12', '14', '18', '24', '36'],
+    fontSizeUnits: ['px', 'pt'],
+    // pallete colors(n x n)
+    colors: [['#000000', '#424242', '#636363', '#9C9C94', '#CEC6CE', '#EFEFEF', '#F7F7F7', '#FFFFFF'], ['#FF0000', '#FF9C00', '#FFFF00', '#00FF00', '#00FFFF', '#0000FF', '#9C00FF', '#FF00FF'], ['#F7C6CE', '#FFE7CE', '#FFEFC6', '#D6EFD6', '#CEDEE7', '#CEE7F7', '#D6D6E7', '#E7D6DE'], ['#E79C9C', '#FFC69C', '#FFE79C', '#B5D6A5', '#A5C6CE', '#9CC6EF', '#B5A5D6', '#D6A5BD'], ['#E76363', '#F7AD6B', '#FFD663', '#94BD7B', '#73A5AD', '#6BADDE', '#8C7BC6', '#C67BA5'], ['#CE0000', '#E79439', '#EFC631', '#6BA54A', '#4A7B8C', '#3984C6', '#634AA5', '#A54A7B'], ['#9C0000', '#B56308', '#BD9400', '#397B21', '#104A5A', '#085294', '#311873', '#731842'], ['#630000', '#7B3900', '#846300', '#295218', '#083139', '#003163', '#21104A', '#4A1031']],
+    // http://chir.ag/projects/name-that-color/
+    colorsName: [['Black', 'Tundora', 'Dove Gray', 'Star Dust', 'Pale Slate', 'Gallery', 'Alabaster', 'White'], ['Red', 'Orange Peel', 'Yellow', 'Green', 'Cyan', 'Blue', 'Electric Violet', 'Magenta'], ['Azalea', 'Karry', 'Egg White', 'Zanah', 'Botticelli', 'Tropical Blue', 'Mischka', 'Twilight'], ['Tonys Pink', 'Peach Orange', 'Cream Brulee', 'Sprout', 'Casper', 'Perano', 'Cold Purple', 'Careys Pink'], ['Mandy', 'Rajah', 'Dandelion', 'Olivine', 'Gulf Stream', 'Viking', 'Blue Marguerite', 'Puce'], ['Guardsman Red', 'Fire Bush', 'Golden Dream', 'Chelsea Cucumber', 'Smalt Blue', 'Boston Blue', 'Butterfly Bush', 'Cadillac'], ['Sangria', 'Mai Tai', 'Buddha Gold', 'Forest Green', 'Eden', 'Venice Blue', 'Meteorite', 'Claret'], ['Rosewood', 'Cinnamon', 'Olive', 'Parsley', 'Tiber', 'Midnight Blue', 'Valentino', 'Loulou']],
+    colorButton: {
+      foreColor: '#000000',
+      backColor: '#FFFF00'
+    },
+    lineHeights: ['1.0', '1.2', '1.4', '1.5', '1.6', '1.8', '2.0', '3.0'],
+    tableClassName: 'table table-bordered',
+    insertTableMaxSize: {
+      col: 10,
+      row: 10
+    },
+    // By default, dialogs are attached in container.
+    dialogsInBody: false,
+    dialogsFade: false,
+    maximumImageFileSize: null,
+    callbacks: {
+      onBeforeCommand: null,
+      onBlur: null,
+      onBlurCodeview: null,
+      onChange: null,
+      onChangeCodeview: null,
+      onDialogShown: null,
+      onEnter: null,
+      onFocus: null,
+      onImageLinkInsert: null,
+      onImageUpload: null,
+      onImageUploadError: null,
+      onInit: null,
+      onKeydown: null,
+      onKeyup: null,
+      onMousedown: null,
+      onMouseup: null,
+      onPaste: null,
+      onScroll: null
+    },
+    codemirror: {
+      mode: 'text/html',
+      htmlMode: true,
+      lineNumbers: true
+    },
+    codeviewFilter: false,
+    codeviewFilterRegex: /<\/*(?:applet|b(?:ase|gsound|link)|embed|frame(?:set)?|ilayer|l(?:ayer|ink)|meta|object|s(?:cript|tyle)|t(?:itle|extarea)|xml)[^>]*?>/gi,
+    codeviewIframeFilter: true,
+    codeviewIframeWhitelistSrc: [],
+    codeviewIframeWhitelistSrcBase: ['www.youtube.com', 'www.youtube-nocookie.com', 'www.facebook.com', 'vine.co', 'instagram.com', 'player.vimeo.com', 'www.dailymotion.com', 'player.youku.com', 'v.qq.com'],
+    keyMap: {
+      pc: {
+        'ESC': 'escape',
+        'ENTER': 'insertParagraph',
+        'CTRL+Z': 'undo',
+        'CTRL+Y': 'redo',
+        'TAB': 'tab',
+        'SHIFT+TAB': 'untab',
+        'CTRL+B': 'bold',
+        'CTRL+I': 'italic',
+        'CTRL+U': 'underline',
+        'CTRL+SHIFT+S': 'strikethrough',
+        'CTRL+BACKSLASH': 'removeFormat',
+        'CTRL+SHIFT+L': 'justifyLeft',
+        'CTRL+SHIFT+E': 'justifyCenter',
+        'CTRL+SHIFT+R': 'justifyRight',
+        'CTRL+SHIFT+J': 'justifyFull',
+        'CTRL+SHIFT+NUM7': 'insertUnorderedList',
+        'CTRL+SHIFT+NUM8': 'insertOrderedList',
+        'CTRL+LEFTBRACKET': 'outdent',
+        'CTRL+RIGHTBRACKET': 'indent',
+        'CTRL+NUM0': 'formatPara',
+        'CTRL+NUM1': 'formatH1',
+        'CTRL+NUM2': 'formatH2',
+        'CTRL+NUM3': 'formatH3',
+        'CTRL+NUM4': 'formatH4',
+        'CTRL+NUM5': 'formatH5',
+        'CTRL+NUM6': 'formatH6',
+        'CTRL+ENTER': 'insertHorizontalRule',
+        'CTRL+K': 'linkDialog.show'
+      },
+      mac: {
+        'ESC': 'escape',
+        'ENTER': 'insertParagraph',
+        'CMD+Z': 'undo',
+        'CMD+SHIFT+Z': 'redo',
+        'TAB': 'tab',
+        'SHIFT+TAB': 'untab',
+        'CMD+B': 'bold',
+        'CMD+I': 'italic',
+        'CMD+U': 'underline',
+        'CMD+SHIFT+S': 'strikethrough',
+        'CMD+BACKSLASH': 'removeFormat',
+        'CMD+SHIFT+L': 'justifyLeft',
+        'CMD+SHIFT+E': 'justifyCenter',
+        'CMD+SHIFT+R': 'justifyRight',
+        'CMD+SHIFT+J': 'justifyFull',
+        'CMD+SHIFT+NUM7': 'insertUnorderedList',
+        'CMD+SHIFT+NUM8': 'insertOrderedList',
+        'CMD+LEFTBRACKET': 'outdent',
+        'CMD+RIGHTBRACKET': 'indent',
+        'CMD+NUM0': 'formatPara',
+        'CMD+NUM1': 'formatH1',
+        'CMD+NUM2': 'formatH2',
+        'CMD+NUM3': 'formatH3',
+        'CMD+NUM4': 'formatH4',
+        'CMD+NUM5': 'formatH5',
+        'CMD+NUM6': 'formatH6',
+        'CMD+ENTER': 'insertHorizontalRule',
+        'CMD+K': 'linkDialog.show'
+      }
+    },
+    icons: {
+      'align': 'note-icon-align',
+      'alignCenter': 'note-icon-align-center',
+      'alignJustify': 'note-icon-align-justify',
+      'alignLeft': 'note-icon-align-left',
+      'alignRight': 'note-icon-align-right',
+      'rowBelow': 'note-icon-row-below',
+      'colBefore': 'note-icon-col-before',
+      'colAfter': 'note-icon-col-after',
+      'rowAbove': 'note-icon-row-above',
+      'rowRemove': 'note-icon-row-remove',
+      'colRemove': 'note-icon-col-remove',
+      'indent': 'note-icon-align-indent',
+      'outdent': 'note-icon-align-outdent',
+      'arrowsAlt': 'note-icon-arrows-alt',
+      'bold': 'note-icon-bold',
+      'caret': 'note-icon-caret',
+      'circle': 'note-icon-circle',
+      'close': 'note-icon-close',
+      'code': 'note-icon-code',
+      'eraser': 'note-icon-eraser',
+      'floatLeft': 'note-icon-float-left',
+      'floatRight': 'note-icon-float-right',
+      'font': 'note-icon-font',
+      'frame': 'note-icon-frame',
+      'italic': 'note-icon-italic',
+      'link': 'note-icon-link',
+      'unlink': 'note-icon-chain-broken',
+      'magic': 'note-icon-magic',
+      'menuCheck': 'note-icon-menu-check',
+      'minus': 'note-icon-minus',
+      'orderedlist': 'note-icon-orderedlist',
+      'pencil': 'note-icon-pencil',
+      'picture': 'note-icon-picture',
+      'question': 'note-icon-question',
+      'redo': 'note-icon-redo',
+      'rollback': 'note-icon-rollback',
+      'square': 'note-icon-square',
+      'strikethrough': 'note-icon-strikethrough',
+      'subscript': 'note-icon-subscript',
+      'superscript': 'note-icon-superscript',
+      'table': 'note-icon-table',
+      'textHeight': 'note-icon-text-height',
+      'trash': 'note-icon-trash',
+      'underline': 'note-icon-underline',
+      'undo': 'note-icon-undo',
+      'unorderedlist': 'note-icon-unorderedlist',
+      'video': 'note-icon-video'
+    }
+  }
+});
+
+/***/ }),
+
+/***/ 4:
+/***/ (function(module, exports, __webpack_require__) {
+
+// extracted by mini-css-extract-plugin
+
+/***/ }),
+
+/***/ 52:
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+// ESM COMPAT FLAG
+__webpack_require__.r(__webpack_exports__);
+
+// EXTERNAL MODULE: external {"root":"jQuery","commonjs2":"jquery","commonjs":"jquery","amd":"jquery"}
+var external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_ = __webpack_require__(0);
+var external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default = /*#__PURE__*/__webpack_require__.n(external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_);
+
+// EXTERNAL MODULE: ./src/js/base/renderer.js
+var renderer = __webpack_require__(1);
+
+// CONCATENATED MODULE: ./src/js/bs3/ui.js
+function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+
+
+var editor = renderer["a" /* default */].create('<div class="note-editor note-frame panel panel-default"/>');
+var toolbar = renderer["a" /* default */].create('<div class="panel-heading note-toolbar" role="toolbar"/>');
+var editingArea = renderer["a" /* default */].create('<div class="note-editing-area"/>');
+var codable = renderer["a" /* default */].create('<textarea class="note-codable" aria-multiline="true"/>');
+var editable = renderer["a" /* default */].create('<div class="note-editable" contentEditable="true" role="textbox" aria-multiline="true"/>');
+var statusbar = renderer["a" /* default */].create(['<output class="note-status-output" role="status" aria-live="polite"></output>', '<div class="note-statusbar" role="status">', '<div class="note-resizebar" aria-label="Resize">', '<div class="note-icon-bar"></div>', '<div class="note-icon-bar"></div>', '<div class="note-icon-bar"></div>', '</div>', '</div>'].join(''));
+var airEditor = renderer["a" /* default */].create('<div class="note-editor note-airframe"/>');
+var airEditable = renderer["a" /* default */].create(['<div class="note-editable" contentEditable="true" role="textbox" aria-multiline="true"></div>', '<output class="note-status-output" role="status" aria-live="polite"></output>'].join(''));
+var buttonGroup = renderer["a" /* default */].create('<div class="note-btn-group btn-group">');
+var dropdown = renderer["a" /* default */].create('<ul class="note-dropdown-menu dropdown-menu">', function ($node, options) {
+  var markup = Array.isArray(options.items) ? options.items.map(function (item) {
+    var value = typeof item === 'string' ? item : item.value || '';
+    var content = options.template ? options.template(item) : item;
+    var option = _typeof(item) === 'object' ? item.option : undefined;
+    var dataValue = 'data-value="' + value + '"';
+    var dataOption = option !== undefined ? ' data-option="' + option + '"' : '';
+    return '<li aria-label="' + value + '"><a href="#" ' + (dataValue + dataOption) + '>' + content + '</a></li>';
+  }).join('') : options.items;
+  $node.html(markup).attr({
+    'aria-label': options.title
+  });
+
+  if (options && options.codeviewKeepButton) {
+    $node.addClass('note-codeview-keep');
+  }
+});
+
+var dropdownButtonContents = function dropdownButtonContents(contents, options) {
+  return contents + ' ' + icon(options.icons.caret, 'span');
+};
+
+var dropdownCheck = renderer["a" /* default */].create('<ul class="note-dropdown-menu dropdown-menu note-check">', function ($node, options) {
+  var markup = Array.isArray(options.items) ? options.items.map(function (item) {
+    var value = typeof item === 'string' ? item : item.value || '';
+    var content = options.template ? options.template(item) : item;
+    return '<li aria-label="' + item + '"><a href="#" data-value="' + value + '">' + icon(options.checkClassName) + ' ' + content + '</a></li>';
+  }).join('') : options.items;
+  $node.html(markup).attr({
+    'aria-label': options.title
+  });
+
+  if (options && options.codeviewKeepButton) {
+    $node.addClass('note-codeview-keep');
+  }
+});
+var dialog = renderer["a" /* default */].create('<div class="modal note-modal" aria-hidden="false" tabindex="-1" role="dialog"/>', function ($node, options) {
+  if (options.fade) {
+    $node.addClass('fade');
+  }
+
+  $node.attr({
+    'aria-label': options.title
+  });
+  $node.html(['<div class="modal-dialog">', '<div class="modal-content">', options.title ? '<div class="modal-header">' + '<button type="button" class="close" data-dismiss="modal" aria-label="Close" aria-hidden="true">&times;</button>' + '<h4 class="modal-title">' + options.title + '</h4>' + '</div>' : '', '<div class="modal-body">' + options.body + '</div>', options.footer ? '<div class="modal-footer">' + options.footer + '</div>' : '', '</div>', '</div>'].join(''));
+});
+var popover = renderer["a" /* default */].create(['<div class="note-popover popover in">', '<div class="arrow"></div>', '<div class="popover-content note-children-container"></div>', '</div>'].join(''), function ($node, options) {
+  var direction = typeof options.direction !== 'undefined' ? options.direction : 'bottom';
+  $node.addClass(direction);
+
+  if (options.hideArrow) {
+    $node.find('.arrow').hide();
+  }
+});
+var ui_checkbox = renderer["a" /* default */].create('<div class="checkbox"></div>', function ($node, options) {
+  $node.html(['<label' + (options.id ? ' for="note-' + options.id + '"' : '') + '>', '<input type="checkbox"' + (options.id ? ' id="note-' + options.id + '"' : ''), options.checked ? ' checked' : '', ' aria-checked="' + (options.checked ? 'true' : 'false') + '"/>', options.text ? options.text : '', '</label>'].join(''));
+});
+
+var icon = function icon(iconClassName, tagName) {
+  tagName = tagName || 'i';
+  return '<' + tagName + ' class="' + iconClassName + '"></' + tagName + '>';
+};
+
+var ui_ui = function ui(editorOptions) {
+  return {
+    editor: editor,
+    toolbar: toolbar,
+    editingArea: editingArea,
+    codable: codable,
+    editable: editable,
+    statusbar: statusbar,
+    airEditor: airEditor,
+    airEditable: airEditable,
+    buttonGroup: buttonGroup,
+    dropdown: dropdown,
+    dropdownButtonContents: dropdownButtonContents,
+    dropdownCheck: dropdownCheck,
+    dialog: dialog,
+    popover: popover,
+    checkbox: ui_checkbox,
+    icon: icon,
+    options: editorOptions,
+    palette: function palette($node, options) {
+      return renderer["a" /* default */].create('<div class="note-color-palette"/>', function ($node, options) {
+        var contents = [];
+
+        for (var row = 0, rowSize = options.colors.length; row < rowSize; row++) {
+          var eventName = options.eventName;
+          var colors = options.colors[row];
+          var colorsName = options.colorsName[row];
+          var buttons = [];
+
+          for (var col = 0, colSize = colors.length; col < colSize; col++) {
+            var color = colors[col];
+            var colorName = colorsName[col];
+            buttons.push(['<button type="button" class="note-color-btn"', 'style="background-color:', color, '" ', 'data-event="', eventName, '" ', 'data-value="', color, '" ', 'title="', colorName, '" ', 'aria-label="', colorName, '" ', 'data-toggle="button" tabindex="-1"></button>'].join(''));
+          }
+
+          contents.push('<div class="note-color-row">' + buttons.join('') + '</div>');
+        }
+
+        $node.html(contents.join(''));
+
+        if (options.tooltip) {
+          $node.find('.note-color-btn').tooltip({
+            container: options.container || editorOptions.container,
+            trigger: 'hover',
+            placement: 'bottom'
+          });
+        }
+      })($node, options);
+    },
+    button: function button($node, options) {
+      return renderer["a" /* default */].create('<button type="button" class="note-btn btn btn-default btn-sm" tabindex="-1">', function ($node, options) {
+        if (options && options.tooltip) {
+          $node.attr({
+            title: options.tooltip,
+            'aria-label': options.tooltip
+          }).tooltip({
+            container: options.container || editorOptions.container,
+            trigger: 'hover',
+            placement: 'bottom'
+          }).on('click', function (e) {
+            external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default()(e.currentTarget).tooltip('hide');
+          });
+        }
+
+        if (options && options.codeviewButton) {
+          $node.addClass('note-codeview-keep');
+        }
+      })($node, options);
+    },
+    toggleBtn: function toggleBtn($btn, isEnable) {
+      $btn.toggleClass('disabled', !isEnable);
+      $btn.attr('disabled', !isEnable);
+    },
+    toggleBtnActive: function toggleBtnActive($btn, isActive) {
+      $btn.toggleClass('active', isActive);
+    },
+    onDialogShown: function onDialogShown($dialog, handler) {
+      $dialog.one('shown.bs.modal', handler);
+    },
+    onDialogHidden: function onDialogHidden($dialog, handler) {
+      $dialog.one('hidden.bs.modal', handler);
+    },
+    showDialog: function showDialog($dialog) {
+      $dialog.modal('show');
+    },
+    hideDialog: function hideDialog($dialog) {
+      $dialog.modal('hide');
+    },
+    createLayout: function createLayout($note) {
+      var $editor = (editorOptions.airMode ? airEditor([editingArea([codable(), airEditable()])]) : editorOptions.toolbarPosition === 'bottom' ? editor([editingArea([codable(), editable()]), toolbar(), statusbar()]) : editor([toolbar(), editingArea([codable(), editable()]), statusbar()])).render();
+      $editor.insertAfter($note);
+      return {
+        note: $note,
+        editor: $editor,
+        toolbar: $editor.find('.note-toolbar'),
+        editingArea: $editor.find('.note-editing-area'),
+        editable: $editor.find('.note-editable'),
+        codable: $editor.find('.note-codable'),
+        statusbar: $editor.find('.note-statusbar')
+      };
+    },
+    removeLayout: function removeLayout($note, layoutInfo) {
+      $note.html(layoutInfo.editable.html());
+      layoutInfo.editor.remove();
+      $note.show();
+    }
+  };
+};
+
+/* harmony default export */ var bs3_ui = (ui_ui);
+// EXTERNAL MODULE: ./src/js/base/settings.js + 37 modules
+var settings = __webpack_require__(3);
+
+// EXTERNAL MODULE: ./src/styles/summernote-bs3.scss
+var summernote_bs3 = __webpack_require__(4);
+
+// CONCATENATED MODULE: ./src/js/bs3/settings.js
+
+
+
+
+external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.summernote = external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.extend(external_root_jQuery_commonjs2_jquery_commonjs_jquery_amd_jquery_default.a.summernote, {
+  ui_template: bs3_ui,
+  "interface": 'bs3'
+});
+
+/***/ })
+
+/******/ });
+});
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/summernote/summernote.min.js b/ruoyi-admin/src/main/resources/static/ajax/libs/summernote/summernote.min.js
new file mode 100644
index 0000000..2e18848
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/summernote/summernote.min.js
@@ -0,0 +1,2 @@
+/*! Summernote v0.8.18 | (c) 2013- Alan Hong and other contributors | MIT license */
+!function(t,e){if("object"==typeof exports&&"object"==typeof module)module.exports=e(require("jquery"));else if("function"==typeof define&&define.amd)define(["jquery"],e);else{var n="object"==typeof exports?e(require("jquery")):e(t.jQuery);for(var o in n)("object"==typeof exports?exports:t)[o]=n[o]}}(window,(function(t){return function(t){var e={};function n(o){if(e[o])return e[o].exports;var i=e[o]={i:o,l:!1,exports:{}};return t[o].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=t,n.c=e,n.d=function(t,e,o){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:o})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var i in t)n.d(o,i,function(e){return t[e]}.bind(null,i));return o},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=52)}({0:function(e,n){e.exports=t},1:function(t,e,n){"use strict";var o=n(0),i=n.n(o);function r(t){return(r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function a(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}var s=function(){function t(e,n,o,i){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.markup=e,this.children=n,this.options=o,this.callback=i}var e,n,o;return e=t,(n=[{key:"render",value:function(t){var e=i()(this.markup);if(this.options&&this.options.contents&&e.html(this.options.contents),this.options&&this.options.className&&e.addClass(this.options.className),this.options&&this.options.data&&i.a.each(this.options.data,(function(t,n){e.attr("data-"+t,n)})),this.options&&this.options.click&&e.on("click",this.options.click),this.children){var n=e.find(".note-children-container");this.children.forEach((function(t){t.render(n.length?n:e)}))}return this.callback&&this.callback(e,this.options),this.options&&this.options.callback&&this.options.callback(e),t&&t.append(e),e}}])&&a(e.prototype,n),o&&a(e,o),t}();e.a={create:function(t,e){return function(){var n="object"===r(arguments[1])?arguments[1]:arguments[0],o=Array.isArray(arguments[0])?arguments[0]:[];return n&&n.children&&(o=n.children),new s(t,o,n,e)}}}},2:function(t,e){(function(e){t.exports=e}).call(this,{})},3:function(t,e,n){"use strict";var o=n(0),i=n.n(o);i.a.summernote=i.a.summernote||{lang:{}},i.a.extend(i.a.summernote.lang,{"en-US":{font:{bold:"Bold",italic:"Italic",underline:"Underline",clear:"Remove Font Style",height:"Line Height",name:"Font Family",strikethrough:"Strikethrough",subscript:"Subscript",superscript:"Superscript",size:"Font Size",sizeunit:"Font Size Unit"},image:{image:"Picture",insert:"Insert Image",resizeFull:"Resize full",resizeHalf:"Resize half",resizeQuarter:"Resize quarter",resizeNone:"Original size",floatLeft:"Float Left",floatRight:"Float Right",floatNone:"Remove float",shapeRounded:"Shape: Rounded",shapeCircle:"Shape: Circle",shapeThumbnail:"Shape: Thumbnail",shapeNone:"Shape: None",dragImageHere:"Drag image or text here",dropImage:"Drop image or Text",selectFromFiles:"Select from files",maximumFileSize:"Maximum file size",maximumFileSizeError:"Maximum file size exceeded.",url:"Image URL",remove:"Remove Image",original:"Original"},video:{video:"Video",videoLink:"Video Link",insert:"Insert Video",url:"Video URL",providers:"(YouTube, Vimeo, Vine, Instagram, DailyMotion or Youku)"},link:{link:"Link",insert:"Insert Link",unlink:"Unlink",edit:"Edit",textToDisplay:"Text to display",url:"To what URL should this link go?",openInNewWindow:"Open in new window",useProtocol:"Use default protocol"},table:{table:"Table",addRowAbove:"Add row above",addRowBelow:"Add row below",addColLeft:"Add column left",addColRight:"Add column right",delRow:"Delete row",delCol:"Delete column",delTable:"Delete table"},hr:{insert:"Insert Horizontal Rule"},style:{style:"Style",p:"Normal",blockquote:"Quote",pre:"Code",h1:"Header 1",h2:"Header 2",h3:"Header 3",h4:"Header 4",h5:"Header 5",h6:"Header 6"},lists:{unordered:"Unordered list",ordered:"Ordered list"},options:{help:"Help",fullscreen:"Full Screen",codeview:"Code View"},paragraph:{paragraph:"Paragraph",outdent:"Outdent",indent:"Indent",left:"Align left",center:"Align center",right:"Align right",justify:"Justify full"},color:{recent:"Recent Color",more:"More Color",background:"Background Color",foreground:"Text Color",transparent:"Transparent",setTransparent:"Set transparent",reset:"Reset",resetToDefault:"Reset to default",cpSelect:"Select"},shortcut:{shortcuts:"Keyboard shortcuts",close:"Close",textFormatting:"Text formatting",action:"Action",paragraphFormatting:"Paragraph formatting",documentStyle:"Document Style",extraKeys:"Extra keys"},help:{escape:"Escape",insertParagraph:"Insert Paragraph",undo:"Undo the last command",redo:"Redo the last command",tab:"Tab",untab:"Untab",bold:"Set a bold style",italic:"Set a italic style",underline:"Set a underline style",strikethrough:"Set a strikethrough style",removeFormat:"Clean a style",justifyLeft:"Set left align",justifyCenter:"Set center align",justifyRight:"Set right align",justifyFull:"Set full align",insertUnorderedList:"Toggle unordered list",insertOrderedList:"Toggle ordered list",outdent:"Outdent on current paragraph",indent:"Indent on current paragraph",formatPara:"Change current block's format as a paragraph(P tag)",formatH1:"Change current block's format as H1",formatH2:"Change current block's format as H2",formatH3:"Change current block's format as H3",formatH4:"Change current block's format as H4",formatH5:"Change current block's format as H5",formatH6:"Change current block's format as H6",insertHorizontalRule:"Insert horizontal rule","linkDialog.show":"Show Link Dialog"},history:{undo:"Undo",redo:"Redo"},specialChar:{specialChar:"SPECIAL CHARACTERS",select:"Select Special characters"},output:{noSelection:"No Selection Made!"}}});var r="function"==typeof define&&n(2),a=["sans-serif","serif","monospace","cursive","fantasy"];function s(t){return-1===i.a.inArray(t.toLowerCase(),a)?"'".concat(t,"'"):t}var l,c=navigator.userAgent,u=/MSIE|Trident/i.test(c);if(u){var d=/MSIE (\d+[.]\d+)/.exec(c);d&&(l=parseFloat(d[1])),(d=/Trident\/.*rv:([0-9]{1,}[.0-9]{0,})/.exec(c))&&(l=parseFloat(d[1]))}var h=/Edge\/\d+/.test(c),f="ontouchstart"in window||navigator.MaxTouchPoints>0||navigator.msMaxTouchPoints>0,p=u?"DOMCharacterDataModified DOMSubtreeModified DOMNodeInserted":"input",m={isMac:navigator.appVersion.indexOf("Mac")>-1,isMSIE:u,isEdge:h,isFF:!h&&/firefox/i.test(c),isPhantom:/PhantomJS/i.test(c),isWebkit:!h&&/webkit/i.test(c),isChrome:!h&&/chrome/i.test(c),isSafari:!h&&/safari/i.test(c)&&!/chrome/i.test(c),browserVersion:l,jqueryVersion:parseFloat(i.a.fn.jquery),isSupportAmd:r,isSupportTouch:f,isFontInstalled:function(t){var e="Comic Sans MS"===t?"Courier New":"Comic Sans MS",n=document.createElement("canvas").getContext("2d");n.font="200px '"+e+"'";var o=n.measureText("mmmmmmmmmmwwwww").width;return n.font="200px "+s(t)+', "'+e+'"',o!==n.measureText("mmmmmmmmmmwwwww").width},isW3CRangeSupport:!!document.createRange,inputEventName:p,genericFontFamilies:a,validFontName:s};var v=0;var g={eq:function(t){return function(e){return t===e}},eq2:function(t,e){return t===e},peq2:function(t){return function(e,n){return e[t]===n[t]}},ok:function(){return!0},fail:function(){return!1},self:function(t){return t},not:function(t){return function(){return!t.apply(t,arguments)}},and:function(t,e){return function(n){return t(n)&&e(n)}},invoke:function(t,e){return function(){return t[e].apply(t,arguments)}},resetUniqueId:function(){v=0},uniqueId:function(t){var e=++v+"";return t?t+e:e},rect2bnd:function(t){var e=i()(document);return{top:t.top+e.scrollTop(),left:t.left+e.scrollLeft(),width:t.right-t.left,height:t.bottom-t.top}},invertObject:function(t){var e={};for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[t[n]]=n);return e},namespaceToCamel:function(t,e){return(e=e||"")+t.split(".").map((function(t){return t.substring(0,1).toUpperCase()+t.substring(1)})).join("")},debounce:function(t,e,n){var o;return function(){var i=this,r=arguments,a=function(){o=null,n||t.apply(i,r)},s=n&&!o;clearTimeout(o),o=setTimeout(a,e),s&&t.apply(i,r)}},isValidUrl:function(t){return/[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/gi.test(t)}};function b(t){return t[0]}function y(t){return t[t.length-1]}function k(t){return t.slice(1)}function w(t,e){if(t&&t.length&&e){if(t.indexOf)return-1!==t.indexOf(e);if(t.contains)return t.contains(e)}return!1}var C={head:b,last:y,initial:function(t){return t.slice(0,t.length-1)},tail:k,prev:function(t,e){if(t&&t.length&&e){var n=t.indexOf(e);return-1===n?null:t[n-1]}return null},next:function(t,e){if(t&&t.length&&e){var n=t.indexOf(e);return-1===n?null:t[n+1]}return null},find:function(t,e){for(var n=0,o=t.length;n<o;n++){var i=t[n];if(e(i))return i}},contains:w,all:function(t,e){for(var n=0,o=t.length;n<o;n++)if(!e(t[n]))return!1;return!0},sum:function(t,e){return e=e||g.self,t.reduce((function(t,n){return t+e(n)}),0)},from:function(t){for(var e=[],n=t.length,o=-1;++o<n;)e[o]=t[o];return e},isEmpty:function(t){return!t||!t.length},clusterBy:function(t,e){return t.length?k(t).reduce((function(t,n){var o=y(t);return e(y(o),n)?o[o.length]=n:t[t.length]=[n],t}),[[b(t)]]):[]},compact:function(t){for(var e=[],n=0,o=t.length;n<o;n++)t[n]&&e.push(t[n]);return e},unique:function(t){for(var e=[],n=0,o=t.length;n<o;n++)w(e,t[n])||e.push(t[n]);return e}},x=String.fromCharCode(160);function S(t){return t&&i()(t).hasClass("note-editable")}function T(t){return t=t.toUpperCase(),function(e){return e&&e.nodeName.toUpperCase()===t}}function E(t){return t&&3===t.nodeType}function I(t){return t&&/^BR|^IMG|^HR|^IFRAME|^BUTTON|^INPUT|^AUDIO|^VIDEO|^EMBED/.test(t.nodeName.toUpperCase())}function $(t){return!S(t)&&(t&&/^DIV|^P|^LI|^H[1-7]/.test(t.nodeName.toUpperCase()))}var N=T("PRE"),P=T("LI");var R=T("TABLE"),L=T("DATA");function A(t){return!(B(t)||F(t)||D(t)||$(t)||R(t)||z(t)||L(t))}function F(t){return t&&/^UL|^OL/.test(t.nodeName.toUpperCase())}var D=T("HR");function H(t){return t&&/^TD|^TH/.test(t.nodeName.toUpperCase())}var z=T("BLOCKQUOTE");function B(t){return H(t)||z(t)||S(t)}var M=T("A");var O=T("BODY");var j=m.isMSIE&&m.browserVersion<11?"&nbsp;":"<br>";function U(t){return E(t)?t.nodeValue.length:t?t.childNodes.length:0}function W(t){var e=U(t);return 0===e||(!E(t)&&1===e&&t.innerHTML===j||!(!C.all(t.childNodes,E)||""!==t.innerHTML))}function K(t){I(t)||U(t)||(t.innerHTML=j)}function V(t,e){for(;t;){if(e(t))return t;if(S(t))break;t=t.parentNode}return null}function q(t,e){e=e||g.fail;var n=[];return V(t,(function(t){return S(t)||n.push(t),e(t)})),n}function _(t,e){e=e||g.fail;for(var n=[];t&&!e(t);)n.push(t),t=t.nextSibling;return n}function G(t,e){var n=e.nextSibling,o=e.parentNode;return n?o.insertBefore(t,n):o.appendChild(t),t}function Y(t,e){return i.a.each(e,(function(e,n){t.appendChild(n)})),t}function Z(t){return 0===t.offset}function X(t){return t.offset===U(t.node)}function Q(t){return Z(t)||X(t)}function J(t,e){for(;t&&t!==e;){if(0!==et(t))return!1;t=t.parentNode}return!0}function tt(t,e){if(!e)return!1;for(;t&&t!==e;){if(et(t)!==U(t.parentNode)-1)return!1;t=t.parentNode}return!0}function et(t){for(var e=0;t=t.previousSibling;)e+=1;return e}function nt(t){return!!(t&&t.childNodes&&t.childNodes.length)}function ot(t,e){var n,o;if(0===t.offset){if(S(t.node))return null;n=t.node.parentNode,o=et(t.node)}else nt(t.node)?o=U(n=t.node.childNodes[t.offset-1]):(n=t.node,o=e?0:t.offset-1);return{node:n,offset:o}}function it(t,e){var n,o;if(U(t.node)===t.offset){if(S(t.node))return null;var i=at(t.node);i?(n=i,o=0):(n=t.node.parentNode,o=et(t.node)+1)}else nt(t.node)?(n=t.node.childNodes[t.offset],o=0):(n=t.node,o=e?U(t.node):t.offset+1);return{node:n,offset:o}}function rt(t,e){var n,o;if(W(t.node))return{node:n=t.node.nextSibling,offset:o=0};if(U(t.node)===t.offset){if(S(t.node))return null;var i=at(t.node);i?(n=i,o=0):(n=t.node.parentNode,o=et(t.node)+1),S(n)&&(n=t.node.nextSibling,o=0)}else if(nt(t.node)){if(o=0,W(n=t.node.childNodes[t.offset]))return null}else if(n=t.node,o=e?U(t.node):t.offset+1,W(n))return null;return{node:n,offset:o}}function at(t){if(t.nextSibling&&t.parent===t.nextSibling.parent)return E(t.nextSibling)?t.nextSibling:at(t.nextSibling)}function st(t,e){return t.node===e.node&&t.offset===e.offset}function lt(t,e){var n=e&&e.isSkipPaddingBlankHTML,o=e&&e.isNotSplitEdgePoint,i=e&&e.isDiscardEmptySplits;if(i&&(n=!0),Q(t)&&(E(t.node)||o)){if(Z(t))return t.node;if(X(t))return t.node.nextSibling}if(E(t.node))return t.node.splitText(t.offset);var r=t.node.childNodes[t.offset],a=G(t.node.cloneNode(!1),t.node);return Y(a,_(r)),n||(K(t.node),K(a)),i&&(W(t.node)&&dt(t.node),W(a))?(dt(a),t.node.nextSibling):a}function ct(t,e,n){var o=q(e.node,g.eq(t));return o.length?1===o.length?lt(e,n):o.reduce((function(t,o){return t===e.node&&(t=lt(e,n)),lt({node:o,offset:t?et(t):U(o)},n)})):null}function ut(t){return document.createElement(t)}function dt(t,e){if(t&&t.parentNode){if(t.removeNode)return t.removeNode(e);var n=t.parentNode;if(!e){for(var o=[],i=0,r=t.childNodes.length;i<r;i++)o.push(t.childNodes[i]);for(var a=0,s=o.length;a<s;a++)n.insertBefore(o[a],t)}n.removeChild(t)}}var ht=T("TEXTAREA");function ft(t,e){var n=ht(t[0])?t.val():t.html();return e?n.replace(/[\n\r]/g,""):n}var pt={NBSP_CHAR:x,ZERO_WIDTH_NBSP_CHAR:"\ufeff",blank:j,emptyPara:"<p>".concat(j,"</p>"),makePredByNodeName:T,isEditable:S,isControlSizing:function(t){return t&&i()(t).hasClass("note-control-sizing")},isText:E,isElement:function(t){return t&&1===t.nodeType},isVoid:I,isPara:$,isPurePara:function(t){return $(t)&&!P(t)},isHeading:function(t){return t&&/^H[1-7]/.test(t.nodeName.toUpperCase())},isInline:A,isBlock:g.not(A),isBodyInline:function(t){return A(t)&&!V(t,$)},isBody:O,isParaInline:function(t){return A(t)&&!!V(t,$)},isPre:N,isList:F,isTable:R,isData:L,isCell:H,isBlockquote:z,isBodyContainer:B,isAnchor:M,isDiv:T("DIV"),isLi:P,isBR:T("BR"),isSpan:T("SPAN"),isB:T("B"),isU:T("U"),isS:T("S"),isI:T("I"),isImg:T("IMG"),isTextarea:ht,deepestChildIsEmpty:function(t){do{if(null===t.firstElementChild||""===t.firstElementChild.innerHTML)break}while(t=t.firstElementChild);return W(t)},isEmpty:W,isEmptyAnchor:g.and(M,W),isClosestSibling:function(t,e){return t.nextSibling===e||t.previousSibling===e},withClosestSiblings:function(t,e){e=e||g.ok;var n=[];return t.previousSibling&&e(t.previousSibling)&&n.push(t.previousSibling),n.push(t),t.nextSibling&&e(t.nextSibling)&&n.push(t.nextSibling),n},nodeLength:U,isLeftEdgePoint:Z,isRightEdgePoint:X,isEdgePoint:Q,isLeftEdgeOf:J,isRightEdgeOf:tt,isLeftEdgePointOf:function(t,e){return Z(t)&&J(t.node,e)},isRightEdgePointOf:function(t,e){return X(t)&&tt(t.node,e)},prevPoint:ot,nextPoint:it,nextPointWithEmptyNode:rt,isSamePoint:st,isVisiblePoint:function(t){if(E(t.node)||!nt(t.node)||W(t.node))return!0;var e=t.node.childNodes[t.offset-1],n=t.node.childNodes[t.offset];return!(e&&!I(e)||n&&!I(n))},prevPointUntil:function(t,e){for(;t;){if(e(t))return t;t=ot(t)}return null},nextPointUntil:function(t,e){for(;t;){if(e(t))return t;t=it(t)}return null},isCharPoint:function(t){if(!E(t.node))return!1;var e=t.node.nodeValue.charAt(t.offset-1);return e&&" "!==e&&e!==x},isSpacePoint:function(t){if(!E(t.node))return!1;var e=t.node.nodeValue.charAt(t.offset-1);return" "===e||e===x},walkPoint:function(t,e,n,o){for(var i=t;i&&(n(i),!st(i,e));){i=rt(i,o&&t.node!==i.node&&e.node!==i.node)}},ancestor:V,singleChildAncestor:function(t,e){for(t=t.parentNode;t&&1===U(t);){if(e(t))return t;if(S(t))break;t=t.parentNode}return null},listAncestor:q,lastAncestor:function(t,e){var n=q(t);return C.last(n.filter(e))},listNext:_,listPrev:function(t,e){e=e||g.fail;for(var n=[];t&&!e(t);)n.push(t),t=t.previousSibling;return n},listDescendant:function(t,e){var n=[];return e=e||g.ok,function o(i){t!==i&&e(i)&&n.push(i);for(var r=0,a=i.childNodes.length;r<a;r++)o(i.childNodes[r])}(t),n},commonAncestor:function(t,e){for(var n=q(t),o=e;o;o=o.parentNode)if(n.indexOf(o)>-1)return o;return null},wrap:function(t,e){var n=t.parentNode,o=i()("<"+e+">")[0];return n.insertBefore(o,t),o.appendChild(t),o},insertAfter:G,appendChildNodes:Y,position:et,hasChildren:nt,makeOffsetPath:function(t,e){return q(e,g.eq(t)).map(et).reverse()},fromOffsetPath:function(t,e){for(var n=t,o=0,i=e.length;o<i;o++)n=n.childNodes.length<=e[o]?n.childNodes[n.childNodes.length-1]:n.childNodes[e[o]];return n},splitTree:ct,splitPoint:function(t,e){var n,o,i=e?$:B,r=q(t.node,i),a=C.last(r)||t.node;i(a)?(n=r[r.length-2],o=a):o=(n=a).parentNode;var s=n&&ct(n,t,{isSkipPaddingBlankHTML:e,isNotSplitEdgePoint:e});return s||o!==t.node||(s=t.node.childNodes[t.offset]),{rightNode:s,container:o}},create:ut,createText:function(t){return document.createTextNode(t)},remove:dt,removeWhile:function(t,e){for(;t&&!S(t)&&e(t);){var n=t.parentNode;dt(t),t=n}},replace:function(t,e){if(t.nodeName.toUpperCase()===e.toUpperCase())return t;var n=ut(e);return t.style.cssText&&(n.style.cssText=t.style.cssText),Y(n,C.from(t.childNodes)),G(n,t),dt(t),n},html:function(t,e){var n=ft(t);if(e){n=(n=n.replace(/<(\/?)(\b(?!!)[^>\s]*)(.*?)(\s*\/?>)/g,(function(t,e,n){n=n.toUpperCase();var o=/^DIV|^TD|^TH|^P|^LI|^H[1-7]/.test(n)&&!!e,i=/^BLOCKQUOTE|^TABLE|^TBODY|^TR|^HR|^UL|^OL/.test(n);return t+(o||i?"\n":"")}))).trim()}return n},value:ft,posFromPlaceholder:function(t){var e=i()(t),n=e.offset(),o=e.outerHeight(!0);return{left:n.left,top:n.top+o}},attachEvents:function(t,e){Object.keys(e).forEach((function(n){t.on(n,e[n])}))},detachEvents:function(t,e){Object.keys(e).forEach((function(n){t.off(n,e[n])}))},isCustomStyleTag:function(t){return t&&!E(t)&&C.contains(t.classList,"note-styletag")}};function mt(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}var vt=function(){function t(e,n){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.$note=e,this.memos={},this.modules={},this.layoutInfo={},this.options=i.a.extend(!0,{},n),i.a.summernote.ui=i.a.summernote.ui_template(this.options),this.ui=i.a.summernote.ui,this.initialize()}var e,n,o;return e=t,(n=[{key:"initialize",value:function(){return this.layoutInfo=this.ui.createLayout(this.$note),this._initialize(),this.$note.hide(),this}},{key:"destroy",value:function(){this._destroy(),this.$note.removeData("summernote"),this.ui.removeLayout(this.$note,this.layoutInfo)}},{key:"reset",value:function(){var t=this.isDisabled();this.code(pt.emptyPara),this._destroy(),this._initialize(),t&&this.disable()}},{key:"_initialize",value:function(){var t=this;this.options.id=g.uniqueId(i.a.now()),this.options.container=this.options.container||this.layoutInfo.editor;var e=i.a.extend({},this.options.buttons);Object.keys(e).forEach((function(n){t.memo("button."+n,e[n])}));var n=i.a.extend({},this.options.modules,i.a.summernote.plugins||{});Object.keys(n).forEach((function(e){t.module(e,n[e],!0)})),Object.keys(this.modules).forEach((function(e){t.initializeModule(e)}))}},{key:"_destroy",value:function(){var t=this;Object.keys(this.modules).reverse().forEach((function(e){t.removeModule(e)})),Object.keys(this.memos).forEach((function(e){t.removeMemo(e)})),this.triggerEvent("destroy",this)}},{key:"code",value:function(t){var e=this.invoke("codeview.isActivated");if(void 0===t)return this.invoke("codeview.sync"),e?this.layoutInfo.codable.val():this.layoutInfo.editable.html();e?this.invoke("codeview.sync",t):this.layoutInfo.editable.html(t),this.$note.val(t),this.triggerEvent("change",t,this.layoutInfo.editable)}},{key:"isDisabled",value:function(){return"false"===this.layoutInfo.editable.attr("contenteditable")}},{key:"enable",value:function(){this.layoutInfo.editable.attr("contenteditable",!0),this.invoke("toolbar.activate",!0),this.triggerEvent("disable",!1),this.options.editing=!0}},{key:"disable",value:function(){this.invoke("codeview.isActivated")&&this.invoke("codeview.deactivate"),this.layoutInfo.editable.attr("contenteditable",!1),this.options.editing=!1,this.invoke("toolbar.deactivate",!0),this.triggerEvent("disable",!0)}},{key:"triggerEvent",value:function(){var t=C.head(arguments),e=C.tail(C.from(arguments)),n=this.options.callbacks[g.namespaceToCamel(t,"on")];n&&n.apply(this.$note[0],e),this.$note.trigger("summernote."+t,e)}},{key:"initializeModule",value:function(t){var e=this.modules[t];e.shouldInitialize=e.shouldInitialize||g.ok,e.shouldInitialize()&&(e.initialize&&e.initialize(),e.events&&pt.attachEvents(this.$note,e.events))}},{key:"module",value:function(t,e,n){if(1===arguments.length)return this.modules[t];this.modules[t]=new e(this),n||this.initializeModule(t)}},{key:"removeModule",value:function(t){var e=this.modules[t];e.shouldInitialize()&&(e.events&&pt.detachEvents(this.$note,e.events),e.destroy&&e.destroy()),delete this.modules[t]}},{key:"memo",value:function(t,e){if(1===arguments.length)return this.memos[t];this.memos[t]=e}},{key:"removeMemo",value:function(t){this.memos[t]&&this.memos[t].destroy&&this.memos[t].destroy(),delete this.memos[t]}},{key:"createInvokeHandlerAndUpdateState",value:function(t,e){var n=this;return function(o){n.createInvokeHandler(t,e)(o),n.invoke("buttons.updateCurrentStyle")}}},{key:"createInvokeHandler",value:function(t,e){var n=this;return function(o){o.preventDefault();var r=i()(o.target);n.invoke(t,e||r.closest("[data-value]").data("value"),r)}}},{key:"invoke",value:function(){var t=C.head(arguments),e=C.tail(C.from(arguments)),n=t.split("."),o=n.length>1,i=o&&C.head(n),r=o?C.last(n):C.head(n),a=this.modules[i||"editor"];return!i&&this[r]?this[r].apply(this,e):a&&a[r]&&a.shouldInitialize()?a[r].apply(a,e):void 0}}])&&mt(e.prototype,n),o&&mt(e,o),t}();function gt(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}function bt(t,e){var n,o,i=t.parentElement(),r=document.body.createTextRange(),a=C.from(i.childNodes);for(n=0;n<a.length;n++)if(!pt.isText(a[n])){if(r.moveToElementText(a[n]),r.compareEndPoints("StartToStart",t)>=0)break;o=a[n]}if(0!==n&&pt.isText(a[n-1])){var s=document.body.createTextRange(),l=null;s.moveToElementText(o||i),s.collapse(!o),l=o?o.nextSibling:i.firstChild;var c=t.duplicate();c.setEndPoint("StartToStart",s);for(var u=c.text.replace(/[\r\n]/g,"").length;u>l.nodeValue.length&&l.nextSibling;)u-=l.nodeValue.length,l=l.nextSibling;l.nodeValue;e&&l.nextSibling&&pt.isText(l.nextSibling)&&u===l.nodeValue.length&&(u-=l.nodeValue.length,l=l.nextSibling),i=l,n=u}return{cont:i,offset:n}}function yt(t){var e=document.body.createTextRange(),n=function t(e,n){var o,i;if(pt.isText(e)){var r=pt.listPrev(e,g.not(pt.isText)),a=C.last(r).previousSibling;o=a||e.parentNode,n+=C.sum(C.tail(r),pt.nodeLength),i=!a}else{if(o=e.childNodes[n]||e,pt.isText(o))return t(o,0);n=0,i=!1}return{node:o,collapseToStart:i,offset:n}}(t.node,t.offset);return e.moveToElementText(n.node),e.collapse(n.collapseToStart),e.moveStart("character",n.offset),e}i.a.fn.extend({summernote:function(){var t=i.a.type(C.head(arguments)),e="string"===t,n="object"===t,o=i.a.extend({},i.a.summernote.options,n?C.head(arguments):{});o.langInfo=i.a.extend(!0,{},i.a.summernote.lang["en-US"],i.a.summernote.lang[o.lang]),o.icons=i.a.extend(!0,{},i.a.summernote.options.icons,o.icons),o.tooltip="auto"===o.tooltip?!m.isSupportTouch:o.tooltip,this.each((function(t,e){var n=i()(e);if(!n.data("summernote")){var r=new vt(n,o);n.data("summernote",r),n.data("summernote").triggerEvent("init",r.layoutInfo)}}));var r=this.first();if(r.length){var a=r.data("summernote");if(e)return a.invoke.apply(a,C.from(arguments));o.focus&&a.invoke("editor.focus")}return this}});var kt=function(){function t(e,n,o,i){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.sc=e,this.so=n,this.ec=o,this.eo=i,this.isOnEditable=this.makeIsOn(pt.isEditable),this.isOnList=this.makeIsOn(pt.isList),this.isOnAnchor=this.makeIsOn(pt.isAnchor),this.isOnCell=this.makeIsOn(pt.isCell),this.isOnData=this.makeIsOn(pt.isData)}var e,n,o;return e=t,(n=[{key:"nativeRange",value:function(){if(m.isW3CRangeSupport){var t=document.createRange();return t.setStart(this.sc,this.so),t.setEnd(this.ec,this.eo),t}var e=yt({node:this.sc,offset:this.so});return e.setEndPoint("EndToEnd",yt({node:this.ec,offset:this.eo})),e}},{key:"getPoints",value:function(){return{sc:this.sc,so:this.so,ec:this.ec,eo:this.eo}}},{key:"getStartPoint",value:function(){return{node:this.sc,offset:this.so}}},{key:"getEndPoint",value:function(){return{node:this.ec,offset:this.eo}}},{key:"select",value:function(){var t=this.nativeRange();if(m.isW3CRangeSupport){var e=document.getSelection();e.rangeCount>0&&e.removeAllRanges(),e.addRange(t)}else t.select();return this}},{key:"scrollIntoView",value:function(t){var e=i()(t).height();return t.scrollTop+e<this.sc.offsetTop&&(t.scrollTop+=Math.abs(t.scrollTop+e-this.sc.offsetTop)),this}},{key:"normalize",value:function(){var e=function(t,e){if(!t)return t;if(pt.isVisiblePoint(t)&&(!pt.isEdgePoint(t)||pt.isRightEdgePoint(t)&&!e||pt.isLeftEdgePoint(t)&&e||pt.isRightEdgePoint(t)&&e&&pt.isVoid(t.node.nextSibling)||pt.isLeftEdgePoint(t)&&!e&&pt.isVoid(t.node.previousSibling)||pt.isBlock(t.node)&&pt.isEmpty(t.node)))return t;var n=pt.ancestor(t.node,pt.isBlock),o=!1;if(!o){var i=pt.prevPoint(t)||{node:null};o=(pt.isLeftEdgePointOf(t,n)||pt.isVoid(i.node))&&!e}var r=!1;if(!r){var a=pt.nextPoint(t)||{node:null};r=(pt.isRightEdgePointOf(t,n)||pt.isVoid(a.node))&&e}if(o||r){if(pt.isVisiblePoint(t))return t;e=!e}return(e?pt.nextPointUntil(pt.nextPoint(t),pt.isVisiblePoint):pt.prevPointUntil(pt.prevPoint(t),pt.isVisiblePoint))||t},n=e(this.getEndPoint(),!1),o=this.isCollapsed()?n:e(this.getStartPoint(),!0);return new t(o.node,o.offset,n.node,n.offset)}},{key:"nodes",value:function(t,e){t=t||g.ok;var n=e&&e.includeAncestor,o=e&&e.fullyContains,i=this.getStartPoint(),r=this.getEndPoint(),a=[],s=[];return pt.walkPoint(i,r,(function(e){var i;pt.isEditable(e.node)||(o?(pt.isLeftEdgePoint(e)&&s.push(e.node),pt.isRightEdgePoint(e)&&C.contains(s,e.node)&&(i=e.node)):i=n?pt.ancestor(e.node,t):e.node,i&&t(i)&&a.push(i))}),!0),C.unique(a)}},{key:"commonAncestor",value:function(){return pt.commonAncestor(this.sc,this.ec)}},{key:"expand",value:function(e){var n=pt.ancestor(this.sc,e),o=pt.ancestor(this.ec,e);if(!n&&!o)return new t(this.sc,this.so,this.ec,this.eo);var i=this.getPoints();return n&&(i.sc=n,i.so=0),o&&(i.ec=o,i.eo=pt.nodeLength(o)),new t(i.sc,i.so,i.ec,i.eo)}},{key:"collapse",value:function(e){return e?new t(this.sc,this.so,this.sc,this.so):new t(this.ec,this.eo,this.ec,this.eo)}},{key:"splitText",value:function(){var e=this.sc===this.ec,n=this.getPoints();return pt.isText(this.ec)&&!pt.isEdgePoint(this.getEndPoint())&&this.ec.splitText(this.eo),pt.isText(this.sc)&&!pt.isEdgePoint(this.getStartPoint())&&(n.sc=this.sc.splitText(this.so),n.so=0,e&&(n.ec=n.sc,n.eo=this.eo-this.so)),new t(n.sc,n.so,n.ec,n.eo)}},{key:"deleteContents",value:function(){if(this.isCollapsed())return this;var e=this.splitText(),n=e.nodes(null,{fullyContains:!0}),o=pt.prevPointUntil(e.getStartPoint(),(function(t){return!C.contains(n,t.node)})),r=[];return i.a.each(n,(function(t,e){var n=e.parentNode;o.node!==n&&1===pt.nodeLength(n)&&r.push(n),pt.remove(e,!1)})),i.a.each(r,(function(t,e){pt.remove(e,!1)})),new t(o.node,o.offset,o.node,o.offset).normalize()}},{key:"makeIsOn",value:function(t){return function(){var e=pt.ancestor(this.sc,t);return!!e&&e===pt.ancestor(this.ec,t)}}},{key:"isLeftEdgeOf",value:function(t){if(!pt.isLeftEdgePoint(this.getStartPoint()))return!1;var e=pt.ancestor(this.sc,t);return e&&pt.isLeftEdgeOf(this.sc,e)}},{key:"isCollapsed",value:function(){return this.sc===this.ec&&this.so===this.eo}},{key:"wrapBodyInlineWithPara",value:function(){if(pt.isBodyContainer(this.sc)&&pt.isEmpty(this.sc))return this.sc.innerHTML=pt.emptyPara,new t(this.sc.firstChild,0,this.sc.firstChild,0);var e,n=this.normalize();if(pt.isParaInline(this.sc)||pt.isPara(this.sc))return n;if(pt.isInline(n.sc)){var o=pt.listAncestor(n.sc,g.not(pt.isInline));e=C.last(o),pt.isInline(e)||(e=o[o.length-2]||n.sc.childNodes[n.so])}else e=n.sc.childNodes[n.so>0?n.so-1:0];if(e){var i=pt.listPrev(e,pt.isParaInline).reverse();if((i=i.concat(pt.listNext(e.nextSibling,pt.isParaInline))).length){var r=pt.wrap(C.head(i),"p");pt.appendChildNodes(r,C.tail(i))}}return this.normalize()}},{key:"insertNode",value:function(t){var e=this;(pt.isText(t)||pt.isInline(t))&&(e=this.wrapBodyInlineWithPara().deleteContents());var n=pt.splitPoint(e.getStartPoint(),pt.isInline(t));return n.rightNode?(n.rightNode.parentNode.insertBefore(t,n.rightNode),pt.isEmpty(n.rightNode)&&pt.isPara(t)&&n.rightNode.parentNode.removeChild(n.rightNode)):n.container.appendChild(t),t}},{key:"pasteHTML",value:function(t){t=i.a.trim(t);var e=i()("<div></div>").html(t)[0],n=C.from(e.childNodes),o=this,r=!1;return o.so>=0&&(n=n.reverse(),r=!0),n=n.map((function(t){return o.insertNode(t)})),r&&(n=n.reverse()),n}},{key:"toString",value:function(){var t=this.nativeRange();return m.isW3CRangeSupport?t.toString():t.text}},{key:"getWordRange",value:function(e){var n=this.getEndPoint();if(!pt.isCharPoint(n))return this;var o=pt.prevPointUntil(n,(function(t){return!pt.isCharPoint(t)}));return e&&(n=pt.nextPointUntil(n,(function(t){return!pt.isCharPoint(t)}))),new t(o.node,o.offset,n.node,n.offset)}},{key:"getWordsRange",value:function(e){var n=this.getEndPoint(),o=function(t){return!pt.isCharPoint(t)&&!pt.isSpacePoint(t)};if(o(n))return this;var i=pt.prevPointUntil(n,o);return e&&(n=pt.nextPointUntil(n,o)),new t(i.node,i.offset,n.node,n.offset)}},{key:"getWordsMatchRange",value:function(e){var n=this.getEndPoint(),o=pt.prevPointUntil(n,(function(o){if(!pt.isCharPoint(o)&&!pt.isSpacePoint(o))return!0;var i=new t(o.node,o.offset,n.node,n.offset),r=e.exec(i.toString());return r&&0===r.index})),i=new t(o.node,o.offset,n.node,n.offset),r=i.toString(),a=e.exec(r);return a&&a[0].length===r.length?i:null}},{key:"bookmark",value:function(t){return{s:{path:pt.makeOffsetPath(t,this.sc),offset:this.so},e:{path:pt.makeOffsetPath(t,this.ec),offset:this.eo}}}},{key:"paraBookmark",value:function(t){return{s:{path:C.tail(pt.makeOffsetPath(C.head(t),this.sc)),offset:this.so},e:{path:C.tail(pt.makeOffsetPath(C.last(t),this.ec)),offset:this.eo}}}},{key:"getClientRects",value:function(){return this.nativeRange().getClientRects()}}])&&gt(e.prototype,n),o&&gt(e,o),t}(),wt={create:function(t,e,n,o){if(4===arguments.length)return new kt(t,e,n,o);if(2===arguments.length)return new kt(t,e,n=t,o=e);var i=this.createFromSelection();if(!i&&1===arguments.length){var r=arguments[0];return pt.isEditable(r)&&(r=r.lastChild),this.createFromBodyElement(r,pt.emptyPara===arguments[0].innerHTML)}return i},createFromBodyElement:function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=this.createFromNode(t);return n.collapse(e)},createFromSelection:function(){var t,e,n,o;if(m.isW3CRangeSupport){var i=document.getSelection();if(!i||0===i.rangeCount)return null;if(pt.isBody(i.anchorNode))return null;var r=i.getRangeAt(0);t=r.startContainer,e=r.startOffset,n=r.endContainer,o=r.endOffset}else{var a=document.selection.createRange(),s=a.duplicate();s.collapse(!1);var l=a;l.collapse(!0);var c=bt(l,!0),u=bt(s,!1);pt.isText(c.node)&&pt.isLeftEdgePoint(c)&&pt.isTextNode(u.node)&&pt.isRightEdgePoint(u)&&u.node.nextSibling===c.node&&(c=u),t=c.cont,e=c.offset,n=u.cont,o=u.offset}return new kt(t,e,n,o)},createFromNode:function(t){var e=t,n=0,o=t,i=pt.nodeLength(o);return pt.isVoid(e)&&(n=pt.listPrev(e).length-1,e=e.parentNode),pt.isBR(o)?(i=pt.listPrev(o).length-1,o=o.parentNode):pt.isVoid(o)&&(i=pt.listPrev(o).length,o=o.parentNode),this.create(e,n,o,i)},createFromNodeBefore:function(t){return this.createFromNode(t).collapse(!0)},createFromNodeAfter:function(t){return this.createFromNode(t).collapse()},createFromBookmark:function(t,e){var n=pt.fromOffsetPath(t,e.s.path),o=e.s.offset,i=pt.fromOffsetPath(t,e.e.path),r=e.e.offset;return new kt(n,o,i,r)},createFromParaBookmark:function(t,e){var n=t.s.offset,o=t.e.offset,i=pt.fromOffsetPath(C.head(e),t.s.path),r=pt.fromOffsetPath(C.last(e),t.e.path);return new kt(i,n,r,o)}},Ct={BACKSPACE:8,TAB:9,ENTER:13,ESCAPE:27,SPACE:32,DELETE:46,LEFT:37,UP:38,RIGHT:39,DOWN:40,NUM0:48,NUM1:49,NUM2:50,NUM3:51,NUM4:52,NUM5:53,NUM6:54,NUM7:55,NUM8:56,B:66,E:69,I:73,J:74,K:75,L:76,R:82,S:83,U:85,V:86,Y:89,Z:90,SLASH:191,LEFTBRACKET:219,BACKSLASH:220,RIGHTBRACKET:221,HOME:36,END:35,PAGEUP:33,PAGEDOWN:34},xt={isEdit:function(t){return C.contains([Ct.BACKSPACE,Ct.TAB,Ct.ENTER,Ct.SPACE,Ct.DELETE],t)},isMove:function(t){return C.contains([Ct.LEFT,Ct.UP,Ct.RIGHT,Ct.DOWN],t)},isNavigation:function(t){return C.contains([Ct.HOME,Ct.END,Ct.PAGEUP,Ct.PAGEDOWN],t)},nameFromCode:g.invertObject(Ct),code:Ct};function St(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}var Tt=function(){function t(e){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.stack=[],this.stackOffset=-1,this.context=e,this.$editable=e.layoutInfo.editable,this.editable=this.$editable[0]}var e,n,o;return e=t,(n=[{key:"makeSnapshot",value:function(){var t=wt.create(this.editable);return{contents:this.$editable.html(),bookmark:t&&t.isOnEditable()?t.bookmark(this.editable):{s:{path:[],offset:0},e:{path:[],offset:0}}}}},{key:"applySnapshot",value:function(t){null!==t.contents&&this.$editable.html(t.contents),null!==t.bookmark&&wt.createFromBookmark(this.editable,t.bookmark).select()}},{key:"rewind",value:function(){this.$editable.html()!==this.stack[this.stackOffset].contents&&this.recordUndo(),this.stackOffset=0,this.applySnapshot(this.stack[this.stackOffset])}},{key:"commit",value:function(){this.stack=[],this.stackOffset=-1,this.recordUndo()}},{key:"reset",value:function(){this.stack=[],this.stackOffset=-1,this.$editable.html(""),this.recordUndo()}},{key:"undo",value:function(){this.$editable.html()!==this.stack[this.stackOffset].contents&&this.recordUndo(),this.stackOffset>0&&(this.stackOffset--,this.applySnapshot(this.stack[this.stackOffset]))}},{key:"redo",value:function(){this.stack.length-1>this.stackOffset&&(this.stackOffset++,this.applySnapshot(this.stack[this.stackOffset]))}},{key:"recordUndo",value:function(){this.stackOffset++,this.stack.length>this.stackOffset&&(this.stack=this.stack.slice(0,this.stackOffset)),this.stack.push(this.makeSnapshot()),this.stack.length>this.context.options.historyLimit&&(this.stack.shift(),this.stackOffset-=1)}}])&&St(e.prototype,n),o&&St(e,o),t}();function Et(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}var It=function(){function t(){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t)}var e,n,o;return e=t,(n=[{key:"jQueryCSS",value:function(t,e){if(m.jqueryVersion<1.9){var n={};return i.a.each(e,(function(e,o){n[o]=t.css(o)})),n}return t.css(e)}},{key:"fromNode",value:function(t){var e=this.jQueryCSS(t,["font-family","font-size","text-align","list-style-type","line-height"])||{},n=t[0].style.fontSize||e["font-size"];return e["font-size"]=parseInt(n,10),e["font-size-unit"]=n.match(/[a-z%]+$/),e}},{key:"stylePara",value:function(t,e){i.a.each(t.nodes(pt.isPara,{includeAncestor:!0}),(function(t,n){i()(n).css(e)}))}},{key:"styleNodes",value:function(t,e){t=t.splitText();var n=e&&e.nodeName||"SPAN",o=!(!e||!e.expandClosestSibling),r=!(!e||!e.onlyPartialContains);if(t.isCollapsed())return[t.insertNode(pt.create(n))];var a=pt.makePredByNodeName(n),s=t.nodes(pt.isText,{fullyContains:!0}).map((function(t){return pt.singleChildAncestor(t,a)||pt.wrap(t,n)}));if(o){if(r){var l=t.nodes();a=g.and(a,(function(t){return C.contains(l,t)}))}return s.map((function(t){var e=pt.withClosestSiblings(t,a),n=C.head(e),o=C.tail(e);return i.a.each(o,(function(t,e){pt.appendChildNodes(n,e.childNodes),pt.remove(e)})),C.head(e)}))}return s}},{key:"current",value:function(t){var e=i()(pt.isElement(t.sc)?t.sc:t.sc.parentNode),n=this.fromNode(e);try{n=i.a.extend(n,{"font-bold":document.queryCommandState("bold")?"bold":"normal","font-italic":document.queryCommandState("italic")?"italic":"normal","font-underline":document.queryCommandState("underline")?"underline":"normal","font-subscript":document.queryCommandState("subscript")?"subscript":"normal","font-superscript":document.queryCommandState("superscript")?"superscript":"normal","font-strikethrough":document.queryCommandState("strikethrough")?"strikethrough":"normal","font-family":document.queryCommandValue("fontname")||n["font-family"]})}catch(t){}if(t.isOnList()){var o=["circle","disc","disc-leading-zero","square"].indexOf(n["list-style-type"])>-1;n["list-style"]=o?"unordered":"ordered"}else n["list-style"]="none";var r=pt.ancestor(t.sc,pt.isPara);if(r&&r.style["line-height"])n["line-height"]=r.style.lineHeight;else{var a=parseInt(n["line-height"],10)/parseInt(n["font-size"],10);n["line-height"]=a.toFixed(1)}return n.anchor=t.isOnAnchor()&&pt.ancestor(t.sc,pt.isAnchor),n.ancestors=pt.listAncestor(t.sc,pt.isEditable),n.range=t,n}}])&&Et(e.prototype,n),o&&Et(e,o),t}();function $t(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}var Nt=function(){function t(){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t)}var e,n,o;return e=t,(n=[{key:"insertOrderedList",value:function(t){this.toggleList("OL",t)}},{key:"insertUnorderedList",value:function(t){this.toggleList("UL",t)}},{key:"indent",value:function(t){var e=this,n=wt.create(t).wrapBodyInlineWithPara(),o=n.nodes(pt.isPara,{includeAncestor:!0}),r=C.clusterBy(o,g.peq2("parentNode"));i.a.each(r,(function(t,n){var o=C.head(n);if(pt.isLi(o)){var r=e.findList(o.previousSibling);r?n.map((function(t){return r.appendChild(t)})):(e.wrapList(n,o.parentNode.nodeName),n.map((function(t){return t.parentNode})).map((function(t){return e.appendToPrevious(t)})))}else i.a.each(n,(function(t,e){i()(e).css("marginLeft",(function(t,e){return(parseInt(e,10)||0)+25}))}))})),n.select()}},{key:"outdent",value:function(t){var e=this,n=wt.create(t).wrapBodyInlineWithPara(),o=n.nodes(pt.isPara,{includeAncestor:!0}),r=C.clusterBy(o,g.peq2("parentNode"));i.a.each(r,(function(t,n){var o=C.head(n);pt.isLi(o)?e.releaseList([n]):i.a.each(n,(function(t,e){i()(e).css("marginLeft",(function(t,e){return(e=parseInt(e,10)||0)>25?e-25:""}))}))})),n.select()}},{key:"toggleList",value:function(t,e){var n=this,o=wt.create(e).wrapBodyInlineWithPara(),r=o.nodes(pt.isPara,{includeAncestor:!0}),a=o.paraBookmark(r),s=C.clusterBy(r,g.peq2("parentNode"));if(C.find(r,pt.isPurePara)){var l=[];i.a.each(s,(function(e,o){l=l.concat(n.wrapList(o,t))})),r=l}else{var c=o.nodes(pt.isList,{includeAncestor:!0}).filter((function(e){return!i.a.nodeName(e,t)}));c.length?i.a.each(c,(function(e,n){pt.replace(n,t)})):r=this.releaseList(s,!0)}wt.createFromParaBookmark(a,r).select()}},{key:"wrapList",value:function(t,e){var n=C.head(t),o=C.last(t),i=pt.isList(n.previousSibling)&&n.previousSibling,r=pt.isList(o.nextSibling)&&o.nextSibling,a=i||pt.insertAfter(pt.create(e||"UL"),o);return t=t.map((function(t){return pt.isPurePara(t)?pt.replace(t,"LI"):t})),pt.appendChildNodes(a,t),r&&(pt.appendChildNodes(a,C.from(r.childNodes)),pt.remove(r)),t}},{key:"releaseList",value:function(t,e){var n=this,o=[];return i.a.each(t,(function(t,r){var a=C.head(r),s=C.last(r),l=e?pt.lastAncestor(a,pt.isList):a.parentNode,c=l.parentNode;if("LI"===l.parentNode.nodeName)r.map((function(t){var e=n.findNextSiblings(t);c.nextSibling?c.parentNode.insertBefore(t,c.nextSibling):c.parentNode.appendChild(t),e.length&&(n.wrapList(e,l.nodeName),t.appendChild(e[0].parentNode))})),0===l.children.length&&c.removeChild(l),0===c.childNodes.length&&c.parentNode.removeChild(c);else{var u=l.childNodes.length>1?pt.splitTree(l,{node:s.parentNode,offset:pt.position(s)+1},{isSkipPaddingBlankHTML:!0}):null,d=pt.splitTree(l,{node:a.parentNode,offset:pt.position(a)},{isSkipPaddingBlankHTML:!0});r=e?pt.listDescendant(d,pt.isLi):C.from(d.childNodes).filter(pt.isLi),!e&&pt.isList(l.parentNode)||(r=r.map((function(t){return pt.replace(t,"P")}))),i.a.each(C.from(r).reverse(),(function(t,e){pt.insertAfter(e,l)}));var h=C.compact([l,d,u]);i.a.each(h,(function(t,e){var n=[e].concat(pt.listDescendant(e,pt.isList));i.a.each(n.reverse(),(function(t,e){pt.nodeLength(e)||pt.remove(e,!0)}))}))}o=o.concat(r)})),o}},{key:"appendToPrevious",value:function(t){return t.previousSibling?pt.appendChildNodes(t.previousSibling,[t]):this.wrapList([t],"LI")}},{key:"findList",value:function(t){return t?C.find(t.children,(function(t){return["OL","UL"].indexOf(t.nodeName)>-1})):null}},{key:"findNextSiblings",value:function(t){for(var e=[];t.nextSibling;)e.push(t.nextSibling),t=t.nextSibling;return e}}])&&$t(e.prototype,n),o&&$t(e,o),t}();function Pt(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}var Rt=function(){function t(e){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.bullet=new Nt,this.options=e.options}var e,n,o;return e=t,(n=[{key:"insertTab",value:function(t,e){var n=pt.createText(new Array(e+1).join(pt.NBSP_CHAR));(t=t.deleteContents()).insertNode(n,!0),(t=wt.create(n,e)).select()}},{key:"insertParagraph",value:function(t,e){e=(e=(e=e||wt.create(t)).deleteContents()).wrapBodyInlineWithPara();var n,o=pt.ancestor(e.sc,pt.isPara);if(o){if(pt.isLi(o)&&(pt.isEmpty(o)||pt.deepestChildIsEmpty(o)))return void this.bullet.toggleList(o.parentNode.nodeName);var r=null;if(1===this.options.blockquoteBreakingLevel?r=pt.ancestor(o,pt.isBlockquote):2===this.options.blockquoteBreakingLevel&&(r=pt.lastAncestor(o,pt.isBlockquote)),r){n=i()(pt.emptyPara)[0],pt.isRightEdgePoint(e.getStartPoint())&&pt.isBR(e.sc.nextSibling)&&i()(e.sc.nextSibling).remove();var a=pt.splitTree(r,e.getStartPoint(),{isDiscardEmptySplits:!0});a?a.parentNode.insertBefore(n,a):pt.insertAfter(n,r)}else{n=pt.splitTree(o,e.getStartPoint());var s=pt.listDescendant(o,pt.isEmptyAnchor);s=s.concat(pt.listDescendant(n,pt.isEmptyAnchor)),i.a.each(s,(function(t,e){pt.remove(e)})),(pt.isHeading(n)||pt.isPre(n)||pt.isCustomStyleTag(n))&&pt.isEmpty(n)&&(n=pt.replace(n,"p"))}}else{var l=e.sc.childNodes[e.so];n=i()(pt.emptyPara)[0],l?e.sc.insertBefore(n,l):e.sc.appendChild(n)}wt.create(n,0).normalize().select().scrollIntoView(t)}}])&&Pt(e.prototype,n),o&&Pt(e,o),t}();function Lt(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}var At=function t(e,n,o,i){var r={colPos:0,rowPos:0},a=[],s=[];function l(t,e,n,o,i,r,s){var l={baseRow:n,baseCell:o,isRowSpan:i,isColSpan:r,isVirtual:s};a[t]||(a[t]=[]),a[t][e]=l}function c(t,e,n,o){return{baseCell:t.baseCell,action:e,virtualTable:{rowIndex:n,cellIndex:o}}}function u(t,e){if(!a[t])return e;if(!a[t][e])return e;for(var n=e;a[t][n];)if(n++,!a[t][n])return n}function d(t,e){var n=u(t.rowIndex,e.cellIndex),o=e.colSpan>1,i=e.rowSpan>1,a=t.rowIndex===r.rowPos&&e.cellIndex===r.colPos;l(t.rowIndex,n,t,e,i,o,!1);var s=e.attributes.rowSpan?parseInt(e.attributes.rowSpan.value,10):0;if(s>1)for(var c=1;c<s;c++){var d=t.rowIndex+c;h(d,n,e,a),l(d,n,t,e,!0,o,!0)}var f=e.attributes.colSpan?parseInt(e.attributes.colSpan.value,10):0;if(f>1)for(var p=1;p<f;p++){var m=u(t.rowIndex,n+p);h(t.rowIndex,m,e,a),l(t.rowIndex,m,t,e,i,!0,!0)}}function h(t,e,n,o){t===r.rowPos&&r.colPos>=n.cellIndex&&n.cellIndex<=e&&!o&&r.colPos++}function f(e){switch(n){case t.where.Column:if(e.isColSpan)return t.resultAction.SubtractSpanCount;break;case t.where.Row:if(!e.isVirtual&&e.isRowSpan)return t.resultAction.AddCell;if(e.isRowSpan)return t.resultAction.SubtractSpanCount}return t.resultAction.RemoveCell}function p(e){switch(n){case t.where.Column:if(e.isColSpan)return t.resultAction.SumSpanCount;if(e.isRowSpan&&e.isVirtual)return t.resultAction.Ignore;break;case t.where.Row:if(e.isRowSpan)return t.resultAction.SumSpanCount;if(e.isColSpan&&e.isVirtual)return t.resultAction.Ignore}return t.resultAction.AddCell}this.getActionList=function(){for(var e=n===t.where.Row?r.rowPos:-1,i=n===t.where.Column?r.colPos:-1,l=0,u=!0;u;){var d=e>=0?e:l,h=i>=0?i:l,m=a[d];if(!m)return u=!1,s;var v=m[h];if(!v)return u=!1,s;var g=t.resultAction.Ignore;switch(o){case t.requestAction.Add:g=p(v);break;case t.requestAction.Delete:g=f(v)}s.push(c(v,g,d,h)),l++}return s},e&&e.tagName&&("td"===e.tagName.toLowerCase()||"th"===e.tagName.toLowerCase())&&(r.colPos=e.cellIndex,e.parentElement&&e.parentElement.tagName&&"tr"===e.parentElement.tagName.toLowerCase()&&(r.rowPos=e.parentElement.rowIndex)),function(){for(var t=i.rows,e=0;e<t.length;e++)for(var n=t[e].cells,o=0;o<n.length;o++)d(t[e],n[o])}()};At.where={Row:0,Column:1},At.requestAction={Add:0,Delete:1},At.resultAction={Ignore:0,SubtractSpanCount:1,RemoveCell:2,AddCell:3,SumSpanCount:4};var Ft=function(){function t(){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t)}var e,n,o;return e=t,(n=[{key:"tab",value:function(t,e){var n=pt.ancestor(t.commonAncestor(),pt.isCell),o=pt.ancestor(n,pt.isTable),i=pt.listDescendant(o,pt.isCell),r=C[e?"prev":"next"](i,n);r&&wt.create(r,0).select()}},{key:"addRow",value:function(t,e){for(var n=pt.ancestor(t.commonAncestor(),pt.isCell),o=i()(n).closest("tr"),r=this.recoverAttributes(o),a=i()("<tr"+r+"></tr>"),s=new At(n,At.where.Row,At.requestAction.Add,i()(o).closest("table")[0]).getActionList(),l=0;l<s.length;l++){var c=s[l],u=this.recoverAttributes(c.baseCell);switch(c.action){case At.resultAction.AddCell:a.append("<td"+u+">"+pt.blank+"</td>");break;case At.resultAction.SumSpanCount:if("top"===e&&(c.baseCell.parent?c.baseCell.closest("tr").rowIndex:0)<=o[0].rowIndex){var d=i()("<div></div>").append(i()("<td"+u+">"+pt.blank+"</td>").removeAttr("rowspan")).html();a.append(d);break}var h=parseInt(c.baseCell.rowSpan,10);h++,c.baseCell.setAttribute("rowSpan",h)}}if("top"===e)o.before(a);else{if(n.rowSpan>1){var f=o[0].rowIndex+(n.rowSpan-2);return void i()(i()(o).parent().find("tr")[f]).after(i()(a))}o.after(a)}}},{key:"addCol",value:function(t,e){var n=pt.ancestor(t.commonAncestor(),pt.isCell),o=i()(n).closest("tr");i()(o).siblings().push(o);for(var r=new At(n,At.where.Column,At.requestAction.Add,i()(o).closest("table")[0]).getActionList(),a=0;a<r.length;a++){var s=r[a],l=this.recoverAttributes(s.baseCell);switch(s.action){case At.resultAction.AddCell:"right"===e?i()(s.baseCell).after("<td"+l+">"+pt.blank+"</td>"):i()(s.baseCell).before("<td"+l+">"+pt.blank+"</td>");break;case At.resultAction.SumSpanCount:if("right"===e){var c=parseInt(s.baseCell.colSpan,10);c++,s.baseCell.setAttribute("colSpan",c)}else i()(s.baseCell).before("<td"+l+">"+pt.blank+"</td>")}}}},{key:"recoverAttributes",value:function(t){var e="";if(!t)return e;for(var n=t.attributes||[],o=0;o<n.length;o++)"id"!==n[o].name.toLowerCase()&&n[o].specified&&(e+=" "+n[o].name+"='"+n[o].value+"'");return e}},{key:"deleteRow",value:function(t){for(var e=pt.ancestor(t.commonAncestor(),pt.isCell),n=i()(e).closest("tr"),o=n.children("td, th").index(i()(e)),r=n[0].rowIndex,a=new At(e,At.where.Row,At.requestAction.Delete,i()(n).closest("table")[0]).getActionList(),s=0;s<a.length;s++)if(a[s]){var l=a[s].baseCell,c=a[s].virtualTable,u=l.rowSpan&&l.rowSpan>1,d=u?parseInt(l.rowSpan,10):0;switch(a[s].action){case At.resultAction.Ignore:continue;case At.resultAction.AddCell:var h=n.next("tr")[0];if(!h)continue;var f=n[0].cells[o];u&&(d>2?(d--,h.insertBefore(f,h.cells[o]),h.cells[o].setAttribute("rowSpan",d),h.cells[o].innerHTML=""):2===d&&(h.insertBefore(f,h.cells[o]),h.cells[o].removeAttribute("rowSpan"),h.cells[o].innerHTML=""));continue;case At.resultAction.SubtractSpanCount:u&&(d>2?(d--,l.setAttribute("rowSpan",d),c.rowIndex!==r&&l.cellIndex===o&&(l.innerHTML="")):2===d&&(l.removeAttribute("rowSpan"),c.rowIndex!==r&&l.cellIndex===o&&(l.innerHTML="")));continue;case At.resultAction.RemoveCell:continue}}n.remove()}},{key:"deleteCol",value:function(t){for(var e=pt.ancestor(t.commonAncestor(),pt.isCell),n=i()(e).closest("tr"),o=n.children("td, th").index(i()(e)),r=new At(e,At.where.Column,At.requestAction.Delete,i()(n).closest("table")[0]).getActionList(),a=0;a<r.length;a++)if(r[a])switch(r[a].action){case At.resultAction.Ignore:continue;case At.resultAction.SubtractSpanCount:var s=r[a].baseCell;if(s.colSpan&&s.colSpan>1){var l=s.colSpan?parseInt(s.colSpan,10):0;l>2?(l--,s.setAttribute("colSpan",l),s.cellIndex===o&&(s.innerHTML="")):2===l&&(s.removeAttribute("colSpan"),s.cellIndex===o&&(s.innerHTML=""))}continue;case At.resultAction.RemoveCell:pt.remove(r[a].baseCell,!0);continue}}},{key:"createTable",value:function(t,e,n){for(var o,r=[],a=0;a<t;a++)r.push("<td>"+pt.blank+"</td>");o=r.join("");for(var s,l=[],c=0;c<e;c++)l.push("<tr>"+o+"</tr>");s=l.join("");var u=i()("<table>"+s+"</table>");return n&&n.tableClassName&&u.addClass(n.tableClassName),u[0]}},{key:"deleteTable",value:function(t){var e=pt.ancestor(t.commonAncestor(),pt.isCell);i()(e).closest("table").remove()}}])&&Lt(e.prototype,n),o&&Lt(e,o),t}();function Dt(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}var Ht=function(){function t(e){var n=this;!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.context=e,this.$note=e.layoutInfo.note,this.$editor=e.layoutInfo.editor,this.$editable=e.layoutInfo.editable,this.options=e.options,this.lang=this.options.langInfo,this.editable=this.$editable[0],this.lastRange=null,this.snapshot=null,this.style=new It,this.table=new Ft,this.typing=new Rt(e),this.bullet=new Nt,this.history=new Tt(e),this.context.memo("help.escape",this.lang.help.escape),this.context.memo("help.undo",this.lang.help.undo),this.context.memo("help.redo",this.lang.help.redo),this.context.memo("help.tab",this.lang.help.tab),this.context.memo("help.untab",this.lang.help.untab),this.context.memo("help.insertParagraph",this.lang.help.insertParagraph),this.context.memo("help.insertOrderedList",this.lang.help.insertOrderedList),this.context.memo("help.insertUnorderedList",this.lang.help.insertUnorderedList),this.context.memo("help.indent",this.lang.help.indent),this.context.memo("help.outdent",this.lang.help.outdent),this.context.memo("help.formatPara",this.lang.help.formatPara),this.context.memo("help.insertHorizontalRule",this.lang.help.insertHorizontalRule),this.context.memo("help.fontName",this.lang.help.fontName);for(var o=["bold","italic","underline","strikethrough","superscript","subscript","justifyLeft","justifyCenter","justifyRight","justifyFull","formatBlock","removeFormat","backColor"],r=0,a=o.length;r<a;r++)this[o[r]]=function(t){return function(e){n.beforeCommand(),document.execCommand(t,!1,e),n.afterCommand(!0)}}(o[r]),this.context.memo("help."+o[r],this.lang.help[o[r]]);this.fontName=this.wrapCommand((function(t){return n.fontStyling("font-family",m.validFontName(t))})),this.fontSize=this.wrapCommand((function(t){var e=n.currentStyle()["font-size-unit"];return n.fontStyling("font-size",t+e)})),this.fontSizeUnit=this.wrapCommand((function(t){var e=n.currentStyle()["font-size"];return n.fontStyling("font-size",e+t)}));for(var s=1;s<=6;s++)this["formatH"+s]=function(t){return function(){n.formatBlock("H"+t)}}(s),this.context.memo("help.formatH"+s,this.lang.help["formatH"+s]);this.insertParagraph=this.wrapCommand((function(){n.typing.insertParagraph(n.editable)})),this.insertOrderedList=this.wrapCommand((function(){n.bullet.insertOrderedList(n.editable)})),this.insertUnorderedList=this.wrapCommand((function(){n.bullet.insertUnorderedList(n.editable)})),this.indent=this.wrapCommand((function(){n.bullet.indent(n.editable)})),this.outdent=this.wrapCommand((function(){n.bullet.outdent(n.editable)})),this.insertNode=this.wrapCommand((function(t){n.isLimited(i()(t).text().length)||(n.getLastRange().insertNode(t),n.setLastRange(wt.createFromNodeAfter(t).select()))})),this.insertText=this.wrapCommand((function(t){if(!n.isLimited(t.length)){var e=n.getLastRange().insertNode(pt.createText(t));n.setLastRange(wt.create(e,pt.nodeLength(e)).select())}})),this.pasteHTML=this.wrapCommand((function(t){if(!n.isLimited(t.length)){t=n.context.invoke("codeview.purify",t);var e=n.getLastRange().pasteHTML(t);n.setLastRange(wt.createFromNodeAfter(C.last(e)).select())}})),this.formatBlock=this.wrapCommand((function(t,e){var o=n.options.callbacks.onApplyCustomStyle;o?o.call(n,e,n.context,n.onFormatBlock):n.onFormatBlock(t,e)})),this.insertHorizontalRule=this.wrapCommand((function(){var t=n.getLastRange().insertNode(pt.create("HR"));t.nextSibling&&n.setLastRange(wt.create(t.nextSibling,0).normalize().select())})),this.lineHeight=this.wrapCommand((function(t){n.style.stylePara(n.getLastRange(),{lineHeight:t})})),this.createLink=this.wrapCommand((function(t){var e=t.url,o=t.text,r=t.isNewWindow,a=t.checkProtocol,s=t.range||n.getLastRange(),l=o.length-s.toString().length;if(!(l>0&&n.isLimited(l))){var c=s.toString()!==o;"string"==typeof e&&(e=e.trim()),n.options.onCreateLink?e=n.options.onCreateLink(e):a&&(e=/^([A-Za-z][A-Za-z0-9+-.]*\:|#|\/)/.test(e)?e:n.options.defaultProtocol+e);var u=[];if(c){var d=(s=s.deleteContents()).insertNode(i()("<A>"+o+"</A>")[0]);u.push(d)}else u=n.style.styleNodes(s,{nodeName:"A",expandClosestSibling:!0,onlyPartialContains:!0});i.a.each(u,(function(t,n){i()(n).attr("href",e),r?i()(n).attr("target","_blank"):i()(n).removeAttr("target")})),n.setLastRange(n.createRangeFromList(u).select())}})),this.color=this.wrapCommand((function(t){var e=t.foreColor,n=t.backColor;e&&document.execCommand("foreColor",!1,e),n&&document.execCommand("backColor",!1,n)})),this.foreColor=this.wrapCommand((function(t){document.execCommand("foreColor",!1,t)})),this.insertTable=this.wrapCommand((function(t){var e=t.split("x");n.getLastRange().deleteContents().insertNode(n.table.createTable(e[0],e[1],n.options))})),this.removeMedia=this.wrapCommand((function(){var t=i()(n.restoreTarget()).parent();t.closest("figure").length?t.closest("figure").remove():t=i()(n.restoreTarget()).detach(),n.context.triggerEvent("media.delete",t,n.$editable)})),this.floatMe=this.wrapCommand((function(t){var e=i()(n.restoreTarget());e.toggleClass("note-float-left","left"===t),e.toggleClass("note-float-right","right"===t),e.css("float","none"===t?"":t)})),this.resize=this.wrapCommand((function(t){var e=i()(n.restoreTarget());0===(t=parseFloat(t))?e.css("width",""):e.css({width:100*t+"%",height:""})}))}var e,n,o;return e=t,(n=[{key:"initialize",value:function(){var t=this;this.$editable.on("keydown",(function(e){if(e.keyCode===xt.code.ENTER&&t.context.triggerEvent("enter",e),t.context.triggerEvent("keydown",e),t.snapshot=t.history.makeSnapshot(),t.hasKeyShortCut=!1,e.isDefaultPrevented()||(t.options.shortcuts?t.hasKeyShortCut=t.handleKeyMap(e):t.preventDefaultEditableShortCuts(e)),t.isLimited(1,e)){var n=t.getLastRange();if(n.eo-n.so==0)return!1}t.setLastRange(),t.options.recordEveryKeystroke&&!1===t.hasKeyShortCut&&t.history.recordUndo()})).on("keyup",(function(e){t.setLastRange(),t.context.triggerEvent("keyup",e)})).on("focus",(function(e){t.setLastRange(),t.context.triggerEvent("focus",e)})).on("blur",(function(e){t.context.triggerEvent("blur",e)})).on("mousedown",(function(e){t.context.triggerEvent("mousedown",e)})).on("mouseup",(function(e){t.setLastRange(),t.history.recordUndo(),t.context.triggerEvent("mouseup",e)})).on("scroll",(function(e){t.context.triggerEvent("scroll",e)})).on("paste",(function(e){t.setLastRange(),t.context.triggerEvent("paste",e)})).on("input",(function(){t.isLimited(0)&&t.snapshot&&t.history.applySnapshot(t.snapshot)})),this.$editable.attr("spellcheck",this.options.spellCheck),this.$editable.attr("autocorrect",this.options.spellCheck),this.options.disableGrammar&&this.$editable.attr("data-gramm",!1),this.$editable.html(pt.html(this.$note)||pt.emptyPara),this.$editable.on(m.inputEventName,g.debounce((function(){t.context.triggerEvent("change",t.$editable.html(),t.$editable)}),10)),this.$editable.on("focusin",(function(e){t.context.triggerEvent("focusin",e)})).on("focusout",(function(e){t.context.triggerEvent("focusout",e)})),this.options.airMode?this.options.overrideContextMenu&&this.$editor.on("contextmenu",(function(e){return t.context.triggerEvent("contextmenu",e),!1})):(this.options.width&&this.$editor.outerWidth(this.options.width),this.options.height&&this.$editable.outerHeight(this.options.height),this.options.maxHeight&&this.$editable.css("max-height",this.options.maxHeight),this.options.minHeight&&this.$editable.css("min-height",this.options.minHeight)),this.history.recordUndo(),this.setLastRange()}},{key:"destroy",value:function(){this.$editable.off()}},{key:"handleKeyMap",value:function(t){var e=this.options.keyMap[m.isMac?"mac":"pc"],n=[];t.metaKey&&n.push("CMD"),t.ctrlKey&&!t.altKey&&n.push("CTRL"),t.shiftKey&&n.push("SHIFT");var o=xt.nameFromCode[t.keyCode];o&&n.push(o);var i=e[n.join("+")];if("TAB"!==o||this.options.tabDisable)if(i){if(!1!==this.context.invoke(i))return t.preventDefault(),!0}else xt.isEdit(t.keyCode)&&this.afterCommand();else this.afterCommand();return!1}},{key:"preventDefaultEditableShortCuts",value:function(t){(t.ctrlKey||t.metaKey)&&C.contains([66,73,85],t.keyCode)&&t.preventDefault()}},{key:"isLimited",value:function(t,e){return t=t||0,(void 0===e||!(xt.isMove(e.keyCode)||xt.isNavigation(e.keyCode)||e.ctrlKey||e.metaKey||C.contains([xt.code.BACKSPACE,xt.code.DELETE],e.keyCode)))&&this.options.maxTextLength>0&&this.$editable.text().length+t>this.options.maxTextLength}},{key:"createRange",value:function(){return this.focus(),this.setLastRange(),this.getLastRange()}},{key:"createRangeFromList",value:function(t){var e=wt.createFromNodeBefore(C.head(t)).getStartPoint(),n=wt.createFromNodeAfter(C.last(t)).getEndPoint();return wt.create(e.node,e.offset,n.node,n.offset)}},{key:"setLastRange",value:function(t){t?this.lastRange=t:(this.lastRange=wt.create(this.editable),0===i()(this.lastRange.sc).closest(".note-editable").length&&(this.lastRange=wt.createFromBodyElement(this.editable)))}},{key:"getLastRange",value:function(){return this.lastRange||this.setLastRange(),this.lastRange}},{key:"saveRange",value:function(t){t&&this.getLastRange().collapse().select()}},{key:"restoreRange",value:function(){this.lastRange&&(this.lastRange.select(),this.focus())}},{key:"saveTarget",value:function(t){this.$editable.data("target",t)}},{key:"clearTarget",value:function(){this.$editable.removeData("target")}},{key:"restoreTarget",value:function(){return this.$editable.data("target")}},{key:"currentStyle",value:function(){var t=wt.create();return t&&(t=t.normalize()),t?this.style.current(t):this.style.fromNode(this.$editable)}},{key:"styleFromNode",value:function(t){return this.style.fromNode(t)}},{key:"undo",value:function(){this.context.triggerEvent("before.command",this.$editable.html()),this.history.undo(),this.context.triggerEvent("change",this.$editable.html(),this.$editable)}},{key:"commit",value:function(){this.context.triggerEvent("before.command",this.$editable.html()),this.history.commit(),this.context.triggerEvent("change",this.$editable.html(),this.$editable)}},{key:"redo",value:function(){this.context.triggerEvent("before.command",this.$editable.html()),this.history.redo(),this.context.triggerEvent("change",this.$editable.html(),this.$editable)}},{key:"beforeCommand",value:function(){this.context.triggerEvent("before.command",this.$editable.html()),document.execCommand("styleWithCSS",!1,this.options.styleWithCSS),this.focus()}},{key:"afterCommand",value:function(t){this.normalizeContent(),this.history.recordUndo(),t||this.context.triggerEvent("change",this.$editable.html(),this.$editable)}},{key:"tab",value:function(){var t=this.getLastRange();if(t.isCollapsed()&&t.isOnCell())this.table.tab(t);else{if(0===this.options.tabSize)return!1;this.isLimited(this.options.tabSize)||(this.beforeCommand(),this.typing.insertTab(t,this.options.tabSize),this.afterCommand())}}},{key:"untab",value:function(){var t=this.getLastRange();if(t.isCollapsed()&&t.isOnCell())this.table.tab(t,!0);else if(0===this.options.tabSize)return!1}},{key:"wrapCommand",value:function(t){return function(){this.beforeCommand(),t.apply(this,arguments),this.afterCommand()}}},{key:"insertImage",value:function(t,e){var n,o=this;return(n=t,i.a.Deferred((function(t){var e=i()("<img>");e.one("load",(function(){e.off("error abort"),t.resolve(e)})).one("error abort",(function(){e.off("load").detach(),t.reject(e)})).css({display:"none"}).appendTo(document.body).attr("src",n)})).promise()).then((function(t){o.beforeCommand(),"function"==typeof e?e(t):("string"==typeof e&&t.attr("data-filename",e),t.css("width",Math.min(o.$editable.width(),t.width()))),t.show(),o.getLastRange().insertNode(t[0]),o.setLastRange(wt.createFromNodeAfter(t[0]).select()),o.afterCommand()})).fail((function(t){o.context.triggerEvent("image.upload.error",t)}))}},{key:"insertImagesAsDataURL",value:function(t){var e=this;i.a.each(t,(function(t,n){var o=n.name;e.options.maximumImageFileSize&&e.options.maximumImageFileSize<n.size?e.context.triggerEvent("image.upload.error",e.lang.image.maximumFileSizeError):function(t){return i.a.Deferred((function(e){i.a.extend(new FileReader,{onload:function(t){var n=t.target.result;e.resolve(n)},onerror:function(t){e.reject(t)}}).readAsDataURL(t)})).promise()}(n).then((function(t){return e.insertImage(t,o)})).fail((function(){e.context.triggerEvent("image.upload.error")}))}))}},{key:"insertImagesOrCallback",value:function(t){this.options.callbacks.onImageUpload?this.context.triggerEvent("image.upload",t):this.insertImagesAsDataURL(t)}},{key:"getSelectedText",value:function(){var t=this.getLastRange();return t.isOnAnchor()&&(t=wt.createFromNode(pt.ancestor(t.sc,pt.isAnchor))),t.toString()}},{key:"onFormatBlock",value:function(t,e){if(document.execCommand("FormatBlock",!1,m.isMSIE?"<"+t+">":t),e&&e.length&&(e[0].tagName.toUpperCase()!==t.toUpperCase()&&(e=e.find(t)),e&&e.length)){var n=e[0].className||"";if(n){var o=this.createRange();i()([o.sc,o.ec]).closest(t).addClass(n)}}}},{key:"formatPara",value:function(){this.formatBlock("P")}},{key:"fontStyling",value:function(t,e){var n=this.getLastRange();if(""!==n){var o=this.style.styleNodes(n);if(this.$editor.find(".note-status-output").html(""),i()(o).css(t,e),n.isCollapsed()){var r=C.head(o);r&&!pt.nodeLength(r)&&(r.innerHTML=pt.ZERO_WIDTH_NBSP_CHAR,wt.createFromNode(r.firstChild).select(),this.setLastRange(),this.$editable.data("bogus",r))}else this.setLastRange(this.createRangeFromList(o).select())}else{var a=i.a.now();this.$editor.find(".note-status-output").html('<div id="note-status-output-'+a+'" class="alert alert-info">'+this.lang.output.noSelection+"</div>"),setTimeout((function(){i()("#note-status-output-"+a).remove()}),5e3)}}},{key:"unlink",value:function(){var t=this.getLastRange();if(t.isOnAnchor()){var e=pt.ancestor(t.sc,pt.isAnchor);(t=wt.createFromNode(e)).select(),this.setLastRange(),this.beforeCommand(),document.execCommand("unlink"),this.afterCommand()}}},{key:"getLinkInfo",value:function(){var t=this.getLastRange().expand(pt.isAnchor),e=i()(C.head(t.nodes(pt.isAnchor))),n={range:t,text:t.toString(),url:e.length?e.attr("href"):""};return e.length&&(n.isNewWindow="_blank"===e.attr("target")),n}},{key:"addRow",value:function(t){var e=this.getLastRange(this.$editable);e.isCollapsed()&&e.isOnCell()&&(this.beforeCommand(),this.table.addRow(e,t),this.afterCommand())}},{key:"addCol",value:function(t){var e=this.getLastRange(this.$editable);e.isCollapsed()&&e.isOnCell()&&(this.beforeCommand(),this.table.addCol(e,t),this.afterCommand())}},{key:"deleteRow",value:function(){var t=this.getLastRange(this.$editable);t.isCollapsed()&&t.isOnCell()&&(this.beforeCommand(),this.table.deleteRow(t),this.afterCommand())}},{key:"deleteCol",value:function(){var t=this.getLastRange(this.$editable);t.isCollapsed()&&t.isOnCell()&&(this.beforeCommand(),this.table.deleteCol(t),this.afterCommand())}},{key:"deleteTable",value:function(){var t=this.getLastRange(this.$editable);t.isCollapsed()&&t.isOnCell()&&(this.beforeCommand(),this.table.deleteTable(t),this.afterCommand())}},{key:"resizeTo",value:function(t,e,n){var o;if(n){var i=t.y/t.x,r=e.data("ratio");o={width:r>i?t.x:t.y/r,height:r>i?t.x*r:t.y}}else o={width:t.x,height:t.y};e.css(o)}},{key:"hasFocus",value:function(){return this.$editable.is(":focus")}},{key:"focus",value:function(){this.hasFocus()||this.$editable.focus()}},{key:"isEmpty",value:function(){return pt.isEmpty(this.$editable[0])||pt.emptyPara===this.$editable.html()}},{key:"empty",value:function(){this.context.invoke("code",pt.emptyPara)}},{key:"normalizeContent",value:function(){this.$editable[0].normalize()}}])&&Dt(e.prototype,n),o&&Dt(e,o),t}();function zt(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}var Bt=function(){function t(e){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.context=e,this.$editable=e.layoutInfo.editable}var e,n,o;return e=t,(n=[{key:"initialize",value:function(){this.$editable.on("paste",this.pasteByEvent.bind(this))}},{key:"pasteByEvent",value:function(t){var e=this,n=t.originalEvent.clipboardData;if(n&&n.items&&n.items.length){var o=n.items.length>1?n.items[1]:C.head(n.items);"file"===o.kind&&-1!==o.type.indexOf("image/")?(this.context.invoke("editor.insertImagesOrCallback",[o.getAsFile()]),t.preventDefault()):"string"===o.kind&&this.context.invoke("editor.isLimited",n.getData("Text").length)&&t.preventDefault()}else if(window.clipboardData){var i=window.clipboardData.getData("text");this.context.invoke("editor.isLimited",i.length)&&t.preventDefault()}setTimeout((function(){e.context.invoke("editor.afterCommand")}),10)}}])&&zt(e.prototype,n),o&&zt(e,o),t}();function Mt(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}var Ot=function(){function t(e){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.context=e,this.$eventListener=i()(document),this.$editor=e.layoutInfo.editor,this.$editable=e.layoutInfo.editable,this.options=e.options,this.lang=this.options.langInfo,this.documentEventHandlers={},this.$dropzone=i()(['<div class="note-dropzone">','<div class="note-dropzone-message"></div>',"</div>"].join("")).prependTo(this.$editor)}var e,n,o;return e=t,(n=[{key:"initialize",value:function(){this.options.disableDragAndDrop?(this.documentEventHandlers.onDrop=function(t){t.preventDefault()},this.$eventListener=this.$dropzone,this.$eventListener.on("drop",this.documentEventHandlers.onDrop)):this.attachDragAndDropEvent()}},{key:"attachDragAndDropEvent",value:function(){var t=this,e=i()(),n=this.$dropzone.find(".note-dropzone-message");this.documentEventHandlers.onDragenter=function(o){var i=t.context.invoke("codeview.isActivated"),r=t.$editor.width()>0&&t.$editor.height()>0;i||e.length||!r||(t.$editor.addClass("dragover"),t.$dropzone.width(t.$editor.width()),t.$dropzone.height(t.$editor.height()),n.text(t.lang.image.dragImageHere)),e=e.add(o.target)},this.documentEventHandlers.onDragleave=function(n){(e=e.not(n.target)).length&&"BODY"!==n.target.nodeName||(e=i()(),t.$editor.removeClass("dragover"))},this.documentEventHandlers.onDrop=function(){e=i()(),t.$editor.removeClass("dragover")},this.$eventListener.on("dragenter",this.documentEventHandlers.onDragenter).on("dragleave",this.documentEventHandlers.onDragleave).on("drop",this.documentEventHandlers.onDrop),this.$dropzone.on("dragenter",(function(){t.$dropzone.addClass("hover"),n.text(t.lang.image.dropImage)})).on("dragleave",(function(){t.$dropzone.removeClass("hover"),n.text(t.lang.image.dragImageHere)})),this.$dropzone.on("drop",(function(e){var n=e.originalEvent.dataTransfer;e.preventDefault(),n&&n.files&&n.files.length?(t.$editable.focus(),t.context.invoke("editor.insertImagesOrCallback",n.files)):i.a.each(n.types,(function(e,o){if(!(o.toLowerCase().indexOf("_moz_")>-1)){var r=n.getData(o);o.toLowerCase().indexOf("text")>-1?t.context.invoke("editor.pasteHTML",r):i()(r).each((function(e,n){t.context.invoke("editor.insertNode",n)}))}}))})).on("dragover",!1)}},{key:"destroy",value:function(){var t=this;Object.keys(this.documentEventHandlers).forEach((function(e){t.$eventListener.off(e.substr(2).toLowerCase(),t.documentEventHandlers[e])})),this.documentEventHandlers={}}}])&&Mt(e.prototype,n),o&&Mt(e,o),t}();function jt(t){if("undefined"==typeof Symbol||null==t[Symbol.iterator]){if(Array.isArray(t)||(t=function(t,e){if(!t)return;if("string"==typeof t)return Ut(t,e);var n=Object.prototype.toString.call(t).slice(8,-1);"Object"===n&&t.constructor&&(n=t.constructor.name);if("Map"===n||"Set"===n)return Array.from(n);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return Ut(t,e)}(t))){var e=0,n=function(){};return{s:n,n:function(){return e>=t.length?{done:!0}:{done:!1,value:t[e++]}},e:function(t){throw t},f:n}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,i,r=!0,a=!1;return{s:function(){o=t[Symbol.iterator]()},n:function(){var t=o.next();return r=t.done,t},e:function(t){a=!0,i=t},f:function(){try{r||null==o.return||o.return()}finally{if(a)throw i}}}}function Ut(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,o=new Array(e);n<e;n++)o[n]=t[n];return o}function Wt(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}var Kt=function(){function t(e){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.context=e,this.$editor=e.layoutInfo.editor,this.$editable=e.layoutInfo.editable,this.$codable=e.layoutInfo.codable,this.options=e.options,this.CodeMirrorConstructor=window.CodeMirror,this.options.codemirror.CodeMirrorConstructor&&(this.CodeMirrorConstructor=this.options.codemirror.CodeMirrorConstructor)}var e,n,o;return e=t,(n=[{key:"sync",value:function(t){var e=this.isActivated(),n=this.CodeMirrorConstructor;e&&(t?n?this.$codable.data("cmEditor").getDoc().setValue(t):this.$codable.val(t):n&&this.$codable.data("cmEditor").save())}},{key:"initialize",value:function(){var t=this;this.$codable.on("keyup",(function(e){e.keyCode===xt.code.ESCAPE&&t.deactivate()}))}},{key:"isActivated",value:function(){return this.$editor.hasClass("codeview")}},{key:"toggle",value:function(){this.isActivated()?this.deactivate():this.activate(),this.context.triggerEvent("codeview.toggled")}},{key:"purify",value:function(t){if(this.options.codeviewFilter&&(t=t.replace(this.options.codeviewFilterRegex,""),this.options.codeviewIframeFilter)){var e=this.options.codeviewIframeWhitelistSrc.concat(this.options.codeviewIframeWhitelistSrcBase);t=t.replace(/(<iframe.*?>.*?(?:<\/iframe>)?)/gi,(function(t){if(/<.+src(?==?('|"|\s)?)[\s\S]+src(?=('|"|\s)?)[^>]*?>/i.test(t))return"";var n,o=jt(e);try{for(o.s();!(n=o.n()).done;){var i=n.value;if(new RegExp('src="(https?:)?//'+i.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")+'/(.+)"').test(t))return t}}catch(t){o.e(t)}finally{o.f()}return""}))}return t}},{key:"activate",value:function(){var t=this,e=this.CodeMirrorConstructor;if(this.$codable.val(pt.html(this.$editable,this.options.prettifyHtml)),this.$codable.height(this.$editable.height()),this.context.invoke("toolbar.updateCodeview",!0),this.context.invoke("airPopover.updateCodeview",!0),this.$editor.addClass("codeview"),this.$codable.focus(),e){var n=e.fromTextArea(this.$codable[0],this.options.codemirror);if(this.options.codemirror.tern){var o=new e.TernServer(this.options.codemirror.tern);n.ternServer=o,n.on("cursorActivity",(function(t){o.updateArgHints(t)}))}n.on("blur",(function(e){t.context.triggerEvent("blur.codeview",n.getValue(),e)})),n.on("change",(function(){t.context.triggerEvent("change.codeview",n.getValue(),n)})),n.setSize(null,this.$editable.outerHeight()),this.$codable.data("cmEditor",n)}else this.$codable.on("blur",(function(e){t.context.triggerEvent("blur.codeview",t.$codable.val(),e)})),this.$codable.on("input",(function(){t.context.triggerEvent("change.codeview",t.$codable.val(),t.$codable)}))}},{key:"deactivate",value:function(){if(this.CodeMirrorConstructor){var t=this.$codable.data("cmEditor");this.$codable.val(t.getValue()),t.toTextArea()}var e=this.purify(pt.value(this.$codable,this.options.prettifyHtml)||pt.emptyPara),n=this.$editable.html()!==e;this.$editable.html(e),this.$editable.height(this.options.height?this.$codable.height():"auto"),this.$editor.removeClass("codeview"),n&&this.context.triggerEvent("change",this.$editable.html(),this.$editable),this.$editable.focus(),this.context.invoke("toolbar.updateCodeview",!1),this.context.invoke("airPopover.updateCodeview",!1)}},{key:"destroy",value:function(){this.isActivated()&&this.deactivate()}}])&&Wt(e.prototype,n),o&&Wt(e,o),t}();function Vt(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}var qt=function(){function t(e){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.$document=i()(document),this.$statusbar=e.layoutInfo.statusbar,this.$editable=e.layoutInfo.editable,this.options=e.options}var e,n,o;return e=t,(n=[{key:"initialize",value:function(){var t=this;this.options.airMode||this.options.disableResizeEditor?this.destroy():this.$statusbar.on("mousedown",(function(e){e.preventDefault(),e.stopPropagation();var n=t.$editable.offset().top-t.$document.scrollTop(),o=function(e){var o=e.clientY-(n+24);o=t.options.minheight>0?Math.max(o,t.options.minheight):o,o=t.options.maxHeight>0?Math.min(o,t.options.maxHeight):o,t.$editable.height(o)};t.$document.on("mousemove",o).one("mouseup",(function(){t.$document.off("mousemove",o)}))}))}},{key:"destroy",value:function(){this.$statusbar.off(),this.$statusbar.addClass("locked")}}])&&Vt(e.prototype,n),o&&Vt(e,o),t}();function _t(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}var Gt=function(){function t(e){var n=this;!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.context=e,this.$editor=e.layoutInfo.editor,this.$toolbar=e.layoutInfo.toolbar,this.$editable=e.layoutInfo.editable,this.$codable=e.layoutInfo.codable,this.$window=i()(window),this.$scrollbar=i()("html, body"),this.onResize=function(){n.resizeTo({h:n.$window.height()-n.$toolbar.outerHeight()})}}var e,n,o;return e=t,(n=[{key:"resizeTo",value:function(t){this.$editable.css("height",t.h),this.$codable.css("height",t.h),this.$codable.data("cmeditor")&&this.$codable.data("cmeditor").setsize(null,t.h)}},{key:"toggle",value:function(){this.$editor.toggleClass("fullscreen"),this.isFullscreen()?(this.$editable.data("orgHeight",this.$editable.css("height")),this.$editable.data("orgMaxHeight",this.$editable.css("maxHeight")),this.$editable.css("maxHeight",""),this.$window.on("resize",this.onResize).trigger("resize"),this.$scrollbar.css("overflow","hidden")):(this.$window.off("resize",this.onResize),this.resizeTo({h:this.$editable.data("orgHeight")}),this.$editable.css("maxHeight",this.$editable.css("orgMaxHeight")),this.$scrollbar.css("overflow","visible")),this.context.invoke("toolbar.updateFullscreen",this.isFullscreen())}},{key:"isFullscreen",value:function(){return this.$editor.hasClass("fullscreen")}}])&&_t(e.prototype,n),o&&_t(e,o),t}();function Yt(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}var Zt=function(){function t(e){var n=this;!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.context=e,this.$document=i()(document),this.$editingArea=e.layoutInfo.editingArea,this.options=e.options,this.lang=this.options.langInfo,this.events={"summernote.mousedown":function(t,e){n.update(e.target,e)&&e.preventDefault()},"summernote.keyup summernote.scroll summernote.change summernote.dialog.shown":function(){n.update()},"summernote.disable summernote.blur":function(){n.hide()},"summernote.codeview.toggled":function(){n.update()}}}var e,n,o;return e=t,(n=[{key:"initialize",value:function(){var t=this;this.$handle=i()(['<div class="note-handle">','<div class="note-control-selection">','<div class="note-control-selection-bg"></div>','<div class="note-control-holder note-control-nw"></div>','<div class="note-control-holder note-control-ne"></div>','<div class="note-control-holder note-control-sw"></div>','<div class="',this.options.disableResizeImage?"note-control-holder":"note-control-sizing",' note-control-se"></div>',this.options.disableResizeImage?"":'<div class="note-control-selection-info"></div>',"</div>","</div>"].join("")).prependTo(this.$editingArea),this.$handle.on("mousedown",(function(e){if(pt.isControlSizing(e.target)){e.preventDefault(),e.stopPropagation();var n=t.$handle.find(".note-control-selection").data("target"),o=n.offset(),i=t.$document.scrollTop(),r=function(e){t.context.invoke("editor.resizeTo",{x:e.clientX-o.left,y:e.clientY-(o.top-i)},n,!e.shiftKey),t.update(n[0],e)};t.$document.on("mousemove",r).one("mouseup",(function(e){e.preventDefault(),t.$document.off("mousemove",r),t.context.invoke("editor.afterCommand")})),n.data("ratio")||n.data("ratio",n.height()/n.width())}})),this.$handle.on("wheel",(function(e){e.preventDefault(),t.update()}))}},{key:"destroy",value:function(){this.$handle.remove()}},{key:"update",value:function(t,e){if(this.context.isDisabled())return!1;var n=pt.isImg(t),o=this.$handle.find(".note-control-selection");if(this.context.invoke("imagePopover.update",t,e),n){var r=i()(t),a=r.position(),s={left:a.left+parseInt(r.css("marginLeft"),10),top:a.top+parseInt(r.css("marginTop"),10)},l={w:r.outerWidth(!1),h:r.outerHeight(!1)};o.css({display:"block",left:s.left,top:s.top,width:l.w,height:l.h}).data("target",r);var c=new Image;c.src=r.attr("src");var u=l.w+"x"+l.h+" ("+this.lang.image.original+": "+c.width+"x"+c.height+")";o.find(".note-control-selection-info").text(u),this.context.invoke("editor.saveTarget",t)}else this.hide();return n}},{key:"hide",value:function(){this.context.invoke("editor.clearTarget"),this.$handle.children().hide()}}])&&Yt(e.prototype,n),o&&Yt(e,o),t}();function Xt(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}var Qt=/^([A-Za-z][A-Za-z0-9+-.]*\:[\/]{2}|tel:|mailto:[A-Z0-9._%+-]+@)?(www\.)?(.+)$/i,Jt=function(){function t(e){var n=this;!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.context=e,this.options=e.options,this.events={"summernote.keyup":function(t,e){e.isDefaultPrevented()||n.handleKeyup(e)},"summernote.keydown":function(t,e){n.handleKeydown(e)}}}var e,n,o;return e=t,(n=[{key:"initialize",value:function(){this.lastWordRange=null}},{key:"destroy",value:function(){this.lastWordRange=null}},{key:"replace",value:function(){if(this.lastWordRange){var t=this.lastWordRange.toString(),e=t.match(Qt);if(e&&(e[1]||e[2])){var n=e[1]?t:"http://"+t,o=this.options.showDomainOnlyForAutolink?t.replace(/^(?:https?:\/\/)?(?:tel?:?)?(?:mailto?:?)?(?:www\.)?/i,"").split("/")[0]:t,r=i()("<a />").html(o).attr("href",n)[0];this.context.options.linkTargetBlank&&i()(r).attr("target","_blank"),this.lastWordRange.insertNode(r),this.lastWordRange=null,this.context.invoke("editor.focus")}}}},{key:"handleKeydown",value:function(t){if(C.contains([xt.code.ENTER,xt.code.SPACE],t.keyCode)){var e=this.context.invoke("editor.createRange").getWordRange();this.lastWordRange=e}}},{key:"handleKeyup",value:function(t){C.contains([xt.code.ENTER,xt.code.SPACE],t.keyCode)&&this.replace()}}])&&Xt(e.prototype,n),o&&Xt(e,o),t}();function te(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}var ee=function(){function t(e){var n=this;!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.$note=e.layoutInfo.note,this.events={"summernote.change":function(){n.$note.val(e.invoke("code"))}}}var e,n,o;return e=t,(n=[{key:"shouldInitialize",value:function(){return pt.isTextarea(this.$note[0])}}])&&te(e.prototype,n),o&&te(e,o),t}();function ne(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}var oe=function(){function t(e){var n=this;!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.context=e,this.options=e.options.replace||{},this.keys=[xt.code.ENTER,xt.code.SPACE,xt.code.PERIOD,xt.code.COMMA,xt.code.SEMICOLON,xt.code.SLASH],this.previousKeydownCode=null,this.events={"summernote.keyup":function(t,e){e.isDefaultPrevented()||n.handleKeyup(e)},"summernote.keydown":function(t,e){n.handleKeydown(e)}}}var e,n,o;return e=t,(n=[{key:"shouldInitialize",value:function(){return!!this.options.match}},{key:"initialize",value:function(){this.lastWord=null}},{key:"destroy",value:function(){this.lastWord=null}},{key:"replace",value:function(){if(this.lastWord){var t=this,e=this.lastWord.toString();this.options.match(e,(function(e){if(e){var n="";if("string"==typeof e?n=pt.createText(e):e instanceof jQuery?n=e[0]:e instanceof Node&&(n=e),!n)return;t.lastWord.insertNode(n),t.lastWord=null,t.context.invoke("editor.focus")}}))}}},{key:"handleKeydown",value:function(t){if(this.previousKeydownCode&&C.contains(this.keys,this.previousKeydownCode))this.previousKeydownCode=t.keyCode;else{if(C.contains(this.keys,t.keyCode)){var e=this.context.invoke("editor.createRange").getWordRange();this.lastWord=e}this.previousKeydownCode=t.keyCode}}},{key:"handleKeyup",value:function(t){C.contains(this.keys,t.keyCode)&&this.replace()}}])&&ne(e.prototype,n),o&&ne(e,o),t}();function ie(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}var re=function(){function t(e){var n=this;!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.context=e,this.$editingArea=e.layoutInfo.editingArea,this.options=e.options,!0===this.options.inheritPlaceholder&&(this.options.placeholder=this.context.$note.attr("placeholder")||this.options.placeholder),this.events={"summernote.init summernote.change":function(){n.update()},"summernote.codeview.toggled":function(){n.update()}}}var e,n,o;return e=t,(n=[{key:"shouldInitialize",value:function(){return!!this.options.placeholder}},{key:"initialize",value:function(){var t=this;this.$placeholder=i()('<div class="note-placeholder">'),this.$placeholder.on("click",(function(){t.context.invoke("focus")})).html(this.options.placeholder).prependTo(this.$editingArea),this.update()}},{key:"destroy",value:function(){this.$placeholder.remove()}},{key:"update",value:function(){var t=!this.context.invoke("codeview.isActivated")&&this.context.invoke("editor.isEmpty");this.$placeholder.toggle(t)}}])&&ie(e.prototype,n),o&&ie(e,o),t}();function ae(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}var se=function(){function t(e){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.ui=i.a.summernote.ui,this.context=e,this.$toolbar=e.layoutInfo.toolbar,this.options=e.options,this.lang=this.options.langInfo,this.invertedKeyMap=g.invertObject(this.options.keyMap[m.isMac?"mac":"pc"])}var e,n,o;return e=t,(n=[{key:"representShortcut",value:function(t){var e=this.invertedKeyMap[t];return this.options.shortcuts&&e?(m.isMac&&(e=e.replace("CMD","⌘").replace("SHIFT","⇧"))," ("+(e=e.replace("BACKSLASH","\\").replace("SLASH","/").replace("LEFTBRACKET","[").replace("RIGHTBRACKET","]"))+")"):""}},{key:"button",value:function(t){return!this.options.tooltip&&t.tooltip&&delete t.tooltip,t.container=this.options.container,this.ui.button(t)}},{key:"initialize",value:function(){this.addToolbarButtons(),this.addImagePopoverButtons(),this.addLinkPopoverButtons(),this.addTablePopoverButtons(),this.fontInstalledMap={}}},{key:"destroy",value:function(){delete this.fontInstalledMap}},{key:"isFontInstalled",value:function(t){return Object.prototype.hasOwnProperty.call(this.fontInstalledMap,t)||(this.fontInstalledMap[t]=m.isFontInstalled(t)||C.contains(this.options.fontNamesIgnoreCheck,t)),this.fontInstalledMap[t]}},{key:"isFontDeservedToAdd",value:function(t){return""!==(t=t.toLowerCase())&&this.isFontInstalled(t)&&-1===m.genericFontFamilies.indexOf(t)}},{key:"colorPalette",value:function(t,e,n,o){var r=this;return this.ui.buttonGroup({className:"note-color "+t,children:[this.button({className:"note-current-color-button",contents:this.ui.icon(this.options.icons.font+" note-recent-color"),tooltip:e,click:function(t){var e=i()(t.currentTarget);n&&o?r.context.invoke("editor.color",{backColor:e.attr("data-backColor"),foreColor:e.attr("data-foreColor")}):n?r.context.invoke("editor.color",{backColor:e.attr("data-backColor")}):o&&r.context.invoke("editor.color",{foreColor:e.attr("data-foreColor")})},callback:function(t){var e=t.find(".note-recent-color");n&&(e.css("background-color",r.options.colorButton.backColor),t.attr("data-backColor",r.options.colorButton.backColor)),o?(e.css("color",r.options.colorButton.foreColor),t.attr("data-foreColor",r.options.colorButton.foreColor)):e.css("color","transparent")}}),this.button({className:"dropdown-toggle",contents:this.ui.dropdownButtonContents("",this.options),tooltip:this.lang.color.more,data:{toggle:"dropdown"}}),this.ui.dropdown({items:(n?['<div class="note-palette">','<div class="note-palette-title">'+this.lang.color.background+"</div>","<div>",'<button type="button" class="note-color-reset btn btn-light btn-default" data-event="backColor" data-value="transparent">',this.lang.color.transparent,"</button>","</div>",'<div class="note-holder" data-event="backColor">\x3c!-- back colors --\x3e</div>',"<div>",'<button type="button" class="note-color-select btn btn-light btn-default" data-event="openPalette" data-value="backColorPicker">',this.lang.color.cpSelect,"</button>",'<input type="color" id="backColorPicker" class="note-btn note-color-select-btn" value="'+this.options.colorButton.backColor+'" data-event="backColorPalette">',"</div>",'<div class="note-holder-custom" id="backColorPalette" data-event="backColor"></div>',"</div>"].join(""):"")+(o?['<div class="note-palette">','<div class="note-palette-title">'+this.lang.color.foreground+"</div>","<div>",'<button type="button" class="note-color-reset btn btn-light btn-default" data-event="removeFormat" data-value="foreColor">',this.lang.color.resetToDefault,"</button>","</div>",'<div class="note-holder" data-event="foreColor">\x3c!-- fore colors --\x3e</div>',"<div>",'<button type="button" class="note-color-select btn btn-light btn-default" data-event="openPalette" data-value="foreColorPicker">',this.lang.color.cpSelect,"</button>",'<input type="color" id="foreColorPicker" class="note-btn note-color-select-btn" value="'+this.options.colorButton.foreColor+'" data-event="foreColorPalette">',"</div>",'<div class="note-holder-custom" id="foreColorPalette" data-event="foreColor"></div>',"</div>"].join(""):""),callback:function(t){t.find(".note-holder").each((function(t,e){var n=i()(e);n.append(r.ui.palette({colors:r.options.colors,colorsName:r.options.colorsName,eventName:n.data("event"),container:r.options.container,tooltip:r.options.tooltip}).render())}));var e=[["#FFFFFF","#FFFFFF","#FFFFFF","#FFFFFF","#FFFFFF","#FFFFFF","#FFFFFF","#FFFFFF"]];t.find(".note-holder-custom").each((function(t,n){var o=i()(n);o.append(r.ui.palette({colors:e,colorsName:e,eventName:o.data("event"),container:r.options.container,tooltip:r.options.tooltip}).render())})),t.find("input[type=color]").each((function(e,n){i()(n).change((function(){var e=t.find("#"+i()(this).data("event")).find(".note-color-btn").first(),n=this.value.toUpperCase();e.css("background-color",n).attr("aria-label",n).attr("data-value",n).attr("data-original-title",n),e.click()}))}))},click:function(e){e.stopPropagation();var n=i()("."+t).find(".note-dropdown-menu"),o=i()(e.target),a=o.data("event"),s=o.attr("data-value");if("openPalette"===a){var l=n.find("#"+s),c=i()(n.find("#"+l.data("event")).find(".note-color-row")[0]),u=c.find(".note-color-btn").last().detach(),d=l.val();u.css("background-color",d).attr("aria-label",d).attr("data-value",d).attr("data-original-title",d),c.prepend(u),l.click()}else{if(C.contains(["backColor","foreColor"],a)){var h="backColor"===a?"background-color":"color",f=o.closest(".note-color").find(".note-recent-color"),p=o.closest(".note-color").find(".note-current-color-button");f.css(h,s),p.attr("data-"+a,s)}r.context.invoke("editor."+a,s)}}})]}).render()}},{key:"addToolbarButtons",value:function(){var t=this;this.context.memo("button.style",(function(){return t.ui.buttonGroup([t.button({className:"dropdown-toggle",contents:t.ui.dropdownButtonContents(t.ui.icon(t.options.icons.magic),t.options),tooltip:t.lang.style.style,data:{toggle:"dropdown"}}),t.ui.dropdown({className:"dropdown-style",items:t.options.styleTags,title:t.lang.style.style,template:function(e){"string"==typeof e&&(e={tag:e,title:Object.prototype.hasOwnProperty.call(t.lang.style,e)?t.lang.style[e]:e});var n=e.tag,o=e.title;return"<"+n+(e.style?' style="'+e.style+'" ':"")+(e.className?' class="'+e.className+'"':"")+">"+o+"</"+n+">"},click:t.context.createInvokeHandler("editor.formatBlock")})]).render()}));for(var e=function(e,n){var o=t.options.styleTags[e];t.context.memo("button.style."+o,(function(){return t.button({className:"note-btn-style-"+o,contents:'<div data-value="'+o+'">'+o.toUpperCase()+"</div>",tooltip:t.lang.style[o],click:t.context.createInvokeHandler("editor.formatBlock")}).render()}))},n=0,o=this.options.styleTags.length;n<o;n++)e(n);this.context.memo("button.bold",(function(){return t.button({className:"note-btn-bold",contents:t.ui.icon(t.options.icons.bold),tooltip:t.lang.font.bold+t.representShortcut("bold"),click:t.context.createInvokeHandlerAndUpdateState("editor.bold")}).render()})),this.context.memo("button.italic",(function(){return t.button({className:"note-btn-italic",contents:t.ui.icon(t.options.icons.italic),tooltip:t.lang.font.italic+t.representShortcut("italic"),click:t.context.createInvokeHandlerAndUpdateState("editor.italic")}).render()})),this.context.memo("button.underline",(function(){return t.button({className:"note-btn-underline",contents:t.ui.icon(t.options.icons.underline),tooltip:t.lang.font.underline+t.representShortcut("underline"),click:t.context.createInvokeHandlerAndUpdateState("editor.underline")}).render()})),this.context.memo("button.clear",(function(){return t.button({contents:t.ui.icon(t.options.icons.eraser),tooltip:t.lang.font.clear+t.representShortcut("removeFormat"),click:t.context.createInvokeHandler("editor.removeFormat")}).render()})),this.context.memo("button.strikethrough",(function(){return t.button({className:"note-btn-strikethrough",contents:t.ui.icon(t.options.icons.strikethrough),tooltip:t.lang.font.strikethrough+t.representShortcut("strikethrough"),click:t.context.createInvokeHandlerAndUpdateState("editor.strikethrough")}).render()})),this.context.memo("button.superscript",(function(){return t.button({className:"note-btn-superscript",contents:t.ui.icon(t.options.icons.superscript),tooltip:t.lang.font.superscript,click:t.context.createInvokeHandlerAndUpdateState("editor.superscript")}).render()})),this.context.memo("button.subscript",(function(){return t.button({className:"note-btn-subscript",contents:t.ui.icon(t.options.icons.subscript),tooltip:t.lang.font.subscript,click:t.context.createInvokeHandlerAndUpdateState("editor.subscript")}).render()})),this.context.memo("button.fontname",(function(){var e=t.context.invoke("editor.currentStyle");return t.options.addDefaultFonts&&i.a.each(e["font-family"].split(","),(function(e,n){n=n.trim().replace(/['"]+/g,""),t.isFontDeservedToAdd(n)&&-1===t.options.fontNames.indexOf(n)&&t.options.fontNames.push(n)})),t.ui.buttonGroup([t.button({className:"dropdown-toggle",contents:t.ui.dropdownButtonContents('<span class="note-current-fontname"></span>',t.options),tooltip:t.lang.font.name,data:{toggle:"dropdown"}}),t.ui.dropdownCheck({className:"dropdown-fontname",checkClassName:t.options.icons.menuCheck,items:t.options.fontNames.filter(t.isFontInstalled.bind(t)),title:t.lang.font.name,template:function(t){return'<span style="font-family: '+m.validFontName(t)+'">'+t+"</span>"},click:t.context.createInvokeHandlerAndUpdateState("editor.fontName")})]).render()})),this.context.memo("button.fontsize",(function(){return t.ui.buttonGroup([t.button({className:"dropdown-toggle",contents:t.ui.dropdownButtonContents('<span class="note-current-fontsize"></span>',t.options),tooltip:t.lang.font.size,data:{toggle:"dropdown"}}),t.ui.dropdownCheck({className:"dropdown-fontsize",checkClassName:t.options.icons.menuCheck,items:t.options.fontSizes,title:t.lang.font.size,click:t.context.createInvokeHandlerAndUpdateState("editor.fontSize")})]).render()})),this.context.memo("button.fontsizeunit",(function(){return t.ui.buttonGroup([t.button({className:"dropdown-toggle",contents:t.ui.dropdownButtonContents('<span class="note-current-fontsizeunit"></span>',t.options),tooltip:t.lang.font.sizeunit,data:{toggle:"dropdown"}}),t.ui.dropdownCheck({className:"dropdown-fontsizeunit",checkClassName:t.options.icons.menuCheck,items:t.options.fontSizeUnits,title:t.lang.font.sizeunit,click:t.context.createInvokeHandlerAndUpdateState("editor.fontSizeUnit")})]).render()})),this.context.memo("button.color",(function(){return t.colorPalette("note-color-all",t.lang.color.recent,!0,!0)})),this.context.memo("button.forecolor",(function(){return t.colorPalette("note-color-fore",t.lang.color.foreground,!1,!0)})),this.context.memo("button.backcolor",(function(){return t.colorPalette("note-color-back",t.lang.color.background,!0,!1)})),this.context.memo("button.ul",(function(){return t.button({contents:t.ui.icon(t.options.icons.unorderedlist),tooltip:t.lang.lists.unordered+t.representShortcut("insertUnorderedList"),click:t.context.createInvokeHandler("editor.insertUnorderedList")}).render()})),this.context.memo("button.ol",(function(){return t.button({contents:t.ui.icon(t.options.icons.orderedlist),tooltip:t.lang.lists.ordered+t.representShortcut("insertOrderedList"),click:t.context.createInvokeHandler("editor.insertOrderedList")}).render()}));var r=this.button({contents:this.ui.icon(this.options.icons.alignLeft),tooltip:this.lang.paragraph.left+this.representShortcut("justifyLeft"),click:this.context.createInvokeHandler("editor.justifyLeft")}),a=this.button({contents:this.ui.icon(this.options.icons.alignCenter),tooltip:this.lang.paragraph.center+this.representShortcut("justifyCenter"),click:this.context.createInvokeHandler("editor.justifyCenter")}),s=this.button({contents:this.ui.icon(this.options.icons.alignRight),tooltip:this.lang.paragraph.right+this.representShortcut("justifyRight"),click:this.context.createInvokeHandler("editor.justifyRight")}),l=this.button({contents:this.ui.icon(this.options.icons.alignJustify),tooltip:this.lang.paragraph.justify+this.representShortcut("justifyFull"),click:this.context.createInvokeHandler("editor.justifyFull")}),c=this.button({contents:this.ui.icon(this.options.icons.outdent),tooltip:this.lang.paragraph.outdent+this.representShortcut("outdent"),click:this.context.createInvokeHandler("editor.outdent")}),u=this.button({contents:this.ui.icon(this.options.icons.indent),tooltip:this.lang.paragraph.indent+this.representShortcut("indent"),click:this.context.createInvokeHandler("editor.indent")});this.context.memo("button.justifyLeft",g.invoke(r,"render")),this.context.memo("button.justifyCenter",g.invoke(a,"render")),this.context.memo("button.justifyRight",g.invoke(s,"render")),this.context.memo("button.justifyFull",g.invoke(l,"render")),this.context.memo("button.outdent",g.invoke(c,"render")),this.context.memo("button.indent",g.invoke(u,"render")),this.context.memo("button.paragraph",(function(){return t.ui.buttonGroup([t.button({className:"dropdown-toggle",contents:t.ui.dropdownButtonContents(t.ui.icon(t.options.icons.alignLeft),t.options),tooltip:t.lang.paragraph.paragraph,data:{toggle:"dropdown"}}),t.ui.dropdown([t.ui.buttonGroup({className:"note-align",children:[r,a,s,l]}),t.ui.buttonGroup({className:"note-list",children:[c,u]})])]).render()})),this.context.memo("button.height",(function(){return t.ui.buttonGroup([t.button({className:"dropdown-toggle",contents:t.ui.dropdownButtonContents(t.ui.icon(t.options.icons.textHeight),t.options),tooltip:t.lang.font.height,data:{toggle:"dropdown"}}),t.ui.dropdownCheck({items:t.options.lineHeights,checkClassName:t.options.icons.menuCheck,className:"dropdown-line-height",title:t.lang.font.height,click:t.context.createInvokeHandler("editor.lineHeight")})]).render()})),this.context.memo("button.table",(function(){return t.ui.buttonGroup([t.button({className:"dropdown-toggle",contents:t.ui.dropdownButtonContents(t.ui.icon(t.options.icons.table),t.options),tooltip:t.lang.table.table,data:{toggle:"dropdown"}}),t.ui.dropdown({title:t.lang.table.table,className:"note-table",items:['<div class="note-dimension-picker">','<div class="note-dimension-picker-mousecatcher" data-event="insertTable" data-value="1x1"></div>','<div class="note-dimension-picker-highlighted"></div>','<div class="note-dimension-picker-unhighlighted"></div>',"</div>",'<div class="note-dimension-display">1 x 1</div>'].join("")})],{callback:function(e){e.find(".note-dimension-picker-mousecatcher").css({width:t.options.insertTableMaxSize.col+"em",height:t.options.insertTableMaxSize.row+"em"}).mousedown(t.context.createInvokeHandler("editor.insertTable")).on("mousemove",t.tableMoveHandler.bind(t))}}).render()})),this.context.memo("button.link",(function(){return t.button({contents:t.ui.icon(t.options.icons.link),tooltip:t.lang.link.link+t.representShortcut("linkDialog.show"),click:t.context.createInvokeHandler("linkDialog.show")}).render()})),this.context.memo("button.picture",(function(){return t.button({contents:t.ui.icon(t.options.icons.picture),tooltip:t.lang.image.image,click:t.context.createInvokeHandler("imageDialog.show")}).render()})),this.context.memo("button.video",(function(){return t.button({contents:t.ui.icon(t.options.icons.video),tooltip:t.lang.video.video,click:t.context.createInvokeHandler("videoDialog.show")}).render()})),this.context.memo("button.hr",(function(){return t.button({contents:t.ui.icon(t.options.icons.minus),tooltip:t.lang.hr.insert+t.representShortcut("insertHorizontalRule"),click:t.context.createInvokeHandler("editor.insertHorizontalRule")}).render()})),this.context.memo("button.fullscreen",(function(){return t.button({className:"btn-fullscreen note-codeview-keep",contents:t.ui.icon(t.options.icons.arrowsAlt),tooltip:t.lang.options.fullscreen,click:t.context.createInvokeHandler("fullscreen.toggle")}).render()})),this.context.memo("button.codeview",(function(){return t.button({className:"btn-codeview note-codeview-keep",contents:t.ui.icon(t.options.icons.code),tooltip:t.lang.options.codeview,click:t.context.createInvokeHandler("codeview.toggle")}).render()})),this.context.memo("button.redo",(function(){return t.button({contents:t.ui.icon(t.options.icons.redo),tooltip:t.lang.history.redo+t.representShortcut("redo"),click:t.context.createInvokeHandler("editor.redo")}).render()})),this.context.memo("button.undo",(function(){return t.button({contents:t.ui.icon(t.options.icons.undo),tooltip:t.lang.history.undo+t.representShortcut("undo"),click:t.context.createInvokeHandler("editor.undo")}).render()})),this.context.memo("button.help",(function(){return t.button({contents:t.ui.icon(t.options.icons.question),tooltip:t.lang.options.help,click:t.context.createInvokeHandler("helpDialog.show")}).render()}))}},{key:"addImagePopoverButtons",value:function(){var t=this;this.context.memo("button.resizeFull",(function(){return t.button({contents:'<span class="note-fontsize-10">100%</span>',tooltip:t.lang.image.resizeFull,click:t.context.createInvokeHandler("editor.resize","1")}).render()})),this.context.memo("button.resizeHalf",(function(){return t.button({contents:'<span class="note-fontsize-10">50%</span>',tooltip:t.lang.image.resizeHalf,click:t.context.createInvokeHandler("editor.resize","0.5")}).render()})),this.context.memo("button.resizeQuarter",(function(){return t.button({contents:'<span class="note-fontsize-10">25%</span>',tooltip:t.lang.image.resizeQuarter,click:t.context.createInvokeHandler("editor.resize","0.25")}).render()})),this.context.memo("button.resizeNone",(function(){return t.button({contents:t.ui.icon(t.options.icons.rollback),tooltip:t.lang.image.resizeNone,click:t.context.createInvokeHandler("editor.resize","0")}).render()})),this.context.memo("button.floatLeft",(function(){return t.button({contents:t.ui.icon(t.options.icons.floatLeft),tooltip:t.lang.image.floatLeft,click:t.context.createInvokeHandler("editor.floatMe","left")}).render()})),this.context.memo("button.floatRight",(function(){return t.button({contents:t.ui.icon(t.options.icons.floatRight),tooltip:t.lang.image.floatRight,click:t.context.createInvokeHandler("editor.floatMe","right")}).render()})),this.context.memo("button.floatNone",(function(){return t.button({contents:t.ui.icon(t.options.icons.rollback),tooltip:t.lang.image.floatNone,click:t.context.createInvokeHandler("editor.floatMe","none")}).render()})),this.context.memo("button.removeMedia",(function(){return t.button({contents:t.ui.icon(t.options.icons.trash),tooltip:t.lang.image.remove,click:t.context.createInvokeHandler("editor.removeMedia")}).render()}))}},{key:"addLinkPopoverButtons",value:function(){var t=this;this.context.memo("button.linkDialogShow",(function(){return t.button({contents:t.ui.icon(t.options.icons.link),tooltip:t.lang.link.edit,click:t.context.createInvokeHandler("linkDialog.show")}).render()})),this.context.memo("button.unlink",(function(){return t.button({contents:t.ui.icon(t.options.icons.unlink),tooltip:t.lang.link.unlink,click:t.context.createInvokeHandler("editor.unlink")}).render()}))}},{key:"addTablePopoverButtons",value:function(){var t=this;this.context.memo("button.addRowUp",(function(){return t.button({className:"btn-md",contents:t.ui.icon(t.options.icons.rowAbove),tooltip:t.lang.table.addRowAbove,click:t.context.createInvokeHandler("editor.addRow","top")}).render()})),this.context.memo("button.addRowDown",(function(){return t.button({className:"btn-md",contents:t.ui.icon(t.options.icons.rowBelow),tooltip:t.lang.table.addRowBelow,click:t.context.createInvokeHandler("editor.addRow","bottom")}).render()})),this.context.memo("button.addColLeft",(function(){return t.button({className:"btn-md",contents:t.ui.icon(t.options.icons.colBefore),tooltip:t.lang.table.addColLeft,click:t.context.createInvokeHandler("editor.addCol","left")}).render()})),this.context.memo("button.addColRight",(function(){return t.button({className:"btn-md",contents:t.ui.icon(t.options.icons.colAfter),tooltip:t.lang.table.addColRight,click:t.context.createInvokeHandler("editor.addCol","right")}).render()})),this.context.memo("button.deleteRow",(function(){return t.button({className:"btn-md",contents:t.ui.icon(t.options.icons.rowRemove),tooltip:t.lang.table.delRow,click:t.context.createInvokeHandler("editor.deleteRow")}).render()})),this.context.memo("button.deleteCol",(function(){return t.button({className:"btn-md",contents:t.ui.icon(t.options.icons.colRemove),tooltip:t.lang.table.delCol,click:t.context.createInvokeHandler("editor.deleteCol")}).render()})),this.context.memo("button.deleteTable",(function(){return t.button({className:"btn-md",contents:t.ui.icon(t.options.icons.trash),tooltip:t.lang.table.delTable,click:t.context.createInvokeHandler("editor.deleteTable")}).render()}))}},{key:"build",value:function(t,e){for(var n=0,o=e.length;n<o;n++){for(var i=e[n],r=Array.isArray(i)?i[0]:i,a=Array.isArray(i)?1===i.length?[i[0]]:i[1]:[i],s=this.ui.buttonGroup({className:"note-"+r}).render(),l=0,c=a.length;l<c;l++){var u=this.context.memo("button."+a[l]);u&&s.append("function"==typeof u?u(this.context):u)}s.appendTo(t)}}},{key:"updateCurrentStyle",value:function(t){var e=this,n=t||this.$toolbar,o=this.context.invoke("editor.currentStyle");if(this.updateBtnStates(n,{".note-btn-bold":function(){return"bold"===o["font-bold"]},".note-btn-italic":function(){return"italic"===o["font-italic"]},".note-btn-underline":function(){return"underline"===o["font-underline"]},".note-btn-subscript":function(){return"subscript"===o["font-subscript"]},".note-btn-superscript":function(){return"superscript"===o["font-superscript"]},".note-btn-strikethrough":function(){return"strikethrough"===o["font-strikethrough"]}}),o["font-family"]){var r=o["font-family"].split(",").map((function(t){return t.replace(/[\'\"]/g,"").replace(/\s+$/,"").replace(/^\s+/,"")})),a=C.find(r,this.isFontInstalled.bind(this));n.find(".dropdown-fontname a").each((function(t,e){var n=i()(e),o=n.data("value")+""==a+"";n.toggleClass("checked",o)})),n.find(".note-current-fontname").text(a).css("font-family",a)}if(o["font-size"]){var s=o["font-size"];n.find(".dropdown-fontsize a").each((function(t,e){var n=i()(e),o=n.data("value")+""==s+"";n.toggleClass("checked",o)})),n.find(".note-current-fontsize").text(s);var l=o["font-size-unit"];n.find(".dropdown-fontsizeunit a").each((function(t,e){var n=i()(e),o=n.data("value")+""==l+"";n.toggleClass("checked",o)})),n.find(".note-current-fontsizeunit").text(l)}if(o["line-height"]){var c=o["line-height"];n.find(".dropdown-line-height li a").each((function(t,n){var o=i()(n).data("value")+""==c+"";e.className=o?"checked":""}))}}},{key:"updateBtnStates",value:function(t,e){var n=this;i.a.each(e,(function(e,o){n.ui.toggleBtnActive(t.find(e),o())}))}},{key:"tableMoveHandler",value:function(t){var e,n=i()(t.target.parentNode),o=n.next(),r=n.find(".note-dimension-picker-mousecatcher"),a=n.find(".note-dimension-picker-highlighted"),s=n.find(".note-dimension-picker-unhighlighted");if(void 0===t.offsetX){var l=i()(t.target).offset();e={x:t.pageX-l.left,y:t.pageY-l.top}}else e={x:t.offsetX,y:t.offsetY};var c=Math.ceil(e.x/18)||1,u=Math.ceil(e.y/18)||1;a.css({width:c+"em",height:u+"em"}),r.data("value",c+"x"+u),c>3&&c<this.options.insertTableMaxSize.col&&s.css({width:c+1+"em"}),u>3&&u<this.options.insertTableMaxSize.row&&s.css({height:u+1+"em"}),o.html(c+" x "+u)}}])&&ae(e.prototype,n),o&&ae(e,o),t}();function le(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}var ce=function(){function t(e){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.context=e,this.$window=i()(window),this.$document=i()(document),this.ui=i.a.summernote.ui,this.$note=e.layoutInfo.note,this.$editor=e.layoutInfo.editor,this.$toolbar=e.layoutInfo.toolbar,this.$editable=e.layoutInfo.editable,this.$statusbar=e.layoutInfo.statusbar,this.options=e.options,this.isFollowing=!1,this.followScroll=this.followScroll.bind(this)}var e,n,o;return e=t,(n=[{key:"shouldInitialize",value:function(){return!this.options.airMode}},{key:"initialize",value:function(){var t=this;this.options.toolbar=this.options.toolbar||[],this.options.toolbar.length?this.context.invoke("buttons.build",this.$toolbar,this.options.toolbar):this.$toolbar.hide(),this.options.toolbarContainer&&this.$toolbar.appendTo(this.options.toolbarContainer),this.changeContainer(!1),this.$note.on("summernote.keyup summernote.mouseup summernote.change",(function(){t.context.invoke("buttons.updateCurrentStyle")})),this.context.invoke("buttons.updateCurrentStyle"),this.options.followingToolbar&&this.$window.on("scroll resize",this.followScroll)}},{key:"destroy",value:function(){this.$toolbar.children().remove(),this.options.followingToolbar&&this.$window.off("scroll resize",this.followScroll)}},{key:"followScroll",value:function(){if(this.$editor.hasClass("fullscreen"))return!1;var t=this.$editor.outerHeight(),e=this.$editor.width(),n=this.$toolbar.height(),o=this.$statusbar.height(),r=0;this.options.otherStaticBar&&(r=i()(this.options.otherStaticBar).outerHeight());var a=this.$document.scrollTop(),s=this.$editor.offset().top,l=s-r,c=s+t-r-n-o;!this.isFollowing&&a>l&&a<c-n?(this.isFollowing=!0,this.$editable.css({marginTop:this.$toolbar.outerHeight()}),this.$toolbar.css({position:"fixed",top:r,width:e,zIndex:1e3})):this.isFollowing&&(a<l||a>c)&&(this.isFollowing=!1,this.$toolbar.css({position:"relative",top:0,width:"100%",zIndex:"auto"}),this.$editable.css({marginTop:""}))}},{key:"changeContainer",value:function(t){t?this.$toolbar.prependTo(this.$editor):this.options.toolbarContainer&&this.$toolbar.appendTo(this.options.toolbarContainer),this.options.followingToolbar&&this.followScroll()}},{key:"updateFullscreen",value:function(t){this.ui.toggleBtnActive(this.$toolbar.find(".btn-fullscreen"),t),this.changeContainer(t)}},{key:"updateCodeview",value:function(t){this.ui.toggleBtnActive(this.$toolbar.find(".btn-codeview"),t),t?this.deactivate():this.activate()}},{key:"activate",value:function(t){var e=this.$toolbar.find("button");t||(e=e.not(".note-codeview-keep")),this.ui.toggleBtn(e,!0)}},{key:"deactivate",value:function(t){var e=this.$toolbar.find("button");t||(e=e.not(".note-codeview-keep")),this.ui.toggleBtn(e,!1)}}])&&le(e.prototype,n),o&&le(e,o),t}();function ue(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}var de=function(){function t(e){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.context=e,this.ui=i.a.summernote.ui,this.$body=i()(document.body),this.$editor=e.layoutInfo.editor,this.options=e.options,this.lang=this.options.langInfo,e.memo("help.linkDialog.show",this.options.langInfo.help["linkDialog.show"])}var e,n,o;return e=t,(n=[{key:"initialize",value:function(){var t=this.options.dialogsInBody?this.$body:this.options.container,e=['<div class="form-group note-form-group">','<label for="note-dialog-link-txt-'.concat(this.options.id,'" class="note-form-label">').concat(this.lang.link.textToDisplay,"</label>"),'<input id="note-dialog-link-txt-'.concat(this.options.id,'" class="note-link-text form-control note-form-control note-input" type="text"/>'),"</div>",'<div class="form-group note-form-group">','<label for="note-dialog-link-url-'.concat(this.options.id,'" class="note-form-label">').concat(this.lang.link.url,"</label>"),'<input id="note-dialog-link-url-'.concat(this.options.id,'" class="note-link-url form-control note-form-control note-input" type="text" value="http://"/>'),"</div>",this.options.disableLinkTarget?"":i()("<div/>").append(this.ui.checkbox({className:"sn-checkbox-open-in-new-window",text:this.lang.link.openInNewWindow,checked:!0}).render()).html(),i()("<div/>").append(this.ui.checkbox({className:"sn-checkbox-use-protocol",text:this.lang.link.useProtocol,checked:!0}).render()).html()].join(""),n='<input type="button" href="#" class="'.concat("btn btn-primary note-btn note-btn-primary note-link-btn",'" value="').concat(this.lang.link.insert,'" disabled>');this.$dialog=this.ui.dialog({className:"link-dialog",title:this.lang.link.insert,fade:this.options.dialogsFade,body:e,footer:n}).render().appendTo(t)}},{key:"destroy",value:function(){this.ui.hideDialog(this.$dialog),this.$dialog.remove()}},{key:"bindEnterKey",value:function(t,e){t.on("keypress",(function(t){t.keyCode===xt.code.ENTER&&(t.preventDefault(),e.trigger("click"))}))}},{key:"toggleLinkBtn",value:function(t,e,n){this.ui.toggleBtn(t,e.val()&&n.val())}},{key:"showLinkDialog",value:function(t){var e=this;return i.a.Deferred((function(n){var o=e.$dialog.find(".note-link-text"),i=e.$dialog.find(".note-link-url"),r=e.$dialog.find(".note-link-btn"),a=e.$dialog.find(".sn-checkbox-open-in-new-window input[type=checkbox]"),s=e.$dialog.find(".sn-checkbox-use-protocol input[type=checkbox]");e.ui.onDialogShown(e.$dialog,(function(){e.context.triggerEvent("dialog.shown"),!t.url&&g.isValidUrl(t.text)&&(t.url=t.text),o.on("input paste propertychange",(function(){t.text=o.val(),e.toggleLinkBtn(r,o,i)})).val(t.text),i.on("input paste propertychange",(function(){t.text||o.val(i.val()),e.toggleLinkBtn(r,o,i)})).val(t.url),m.isSupportTouch||i.trigger("focus"),e.toggleLinkBtn(r,o,i),e.bindEnterKey(i,r),e.bindEnterKey(o,r);var l=void 0!==t.isNewWindow?t.isNewWindow:e.context.options.linkTargetBlank;a.prop("checked",l);var c=!t.url&&e.context.options.useProtocol;s.prop("checked",c),r.one("click",(function(r){r.preventDefault(),n.resolve({range:t.range,url:i.val(),text:o.val(),isNewWindow:a.is(":checked"),checkProtocol:s.is(":checked")}),e.ui.hideDialog(e.$dialog)}))})),e.ui.onDialogHidden(e.$dialog,(function(){o.off(),i.off(),r.off(),"pending"===n.state()&&n.reject()})),e.ui.showDialog(e.$dialog)})).promise()}},{key:"show",value:function(){var t=this,e=this.context.invoke("editor.getLinkInfo");this.context.invoke("editor.saveRange"),this.showLinkDialog(e).then((function(e){t.context.invoke("editor.restoreRange"),t.context.invoke("editor.createLink",e)})).fail((function(){t.context.invoke("editor.restoreRange")}))}}])&&ue(e.prototype,n),o&&ue(e,o),t}();function he(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}var fe=function(){function t(e){var n=this;!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.context=e,this.ui=i.a.summernote.ui,this.options=e.options,this.events={"summernote.keyup summernote.mouseup summernote.change summernote.scroll":function(){n.update()},"summernote.disable summernote.dialog.shown summernote.blur":function(){n.hide()}}}var e,n,o;return e=t,(n=[{key:"shouldInitialize",value:function(){return!C.isEmpty(this.options.popover.link)}},{key:"initialize",value:function(){this.$popover=this.ui.popover({className:"note-link-popover",callback:function(t){t.find(".popover-content,.note-popover-content").prepend('<span><a target="_blank"></a>&nbsp;</span>')}}).render().appendTo(this.options.container);var t=this.$popover.find(".popover-content,.note-popover-content");this.context.invoke("buttons.build",t,this.options.popover.link),this.$popover.on("mousedown",(function(t){t.preventDefault()}))}},{key:"destroy",value:function(){this.$popover.remove()}},{key:"update",value:function(){if(this.context.invoke("editor.hasFocus")){var t=this.context.invoke("editor.getLastRange");if(t.isCollapsed()&&t.isOnAnchor()){var e=pt.ancestor(t.sc,pt.isAnchor),n=i()(e).attr("href");this.$popover.find("a").attr("href",n).text(n);var o=pt.posFromPlaceholder(e),r=i()(this.options.container).offset();o.top-=r.top,o.left-=r.left,this.$popover.css({display:"block",left:o.left,top:o.top})}else this.hide()}else this.hide()}},{key:"hide",value:function(){this.$popover.hide()}}])&&he(e.prototype,n),o&&he(e,o),t}();function pe(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}var me=function(){function t(e){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.context=e,this.ui=i.a.summernote.ui,this.$body=i()(document.body),this.$editor=e.layoutInfo.editor,this.options=e.options,this.lang=this.options.langInfo}var e,n,o;return e=t,(n=[{key:"initialize",value:function(){var t="";if(this.options.maximumImageFileSize){var e=Math.floor(Math.log(this.options.maximumImageFileSize)/Math.log(1024)),n=1*(this.options.maximumImageFileSize/Math.pow(1024,e)).toFixed(2)+" "+" KMGTP"[e]+"B";t="<small>".concat(this.lang.image.maximumFileSize+" : "+n,"</small>")}var o=this.options.dialogsInBody?this.$body:this.options.container,i=['<div class="form-group note-form-group note-group-select-from-files">','<label for="note-dialog-image-file-'+this.options.id+'" class="note-form-label">'+this.lang.image.selectFromFiles+"</label>",'<input id="note-dialog-image-file-'+this.options.id+'" class="note-image-input form-control-file note-form-control note-input" ',' type="file" name="files" accept="image/*" multiple="multiple"/>',t,"</div>",'<div class="form-group note-group-image-url">','<label for="note-dialog-image-url-'+this.options.id+'" class="note-form-label">'+this.lang.image.url+"</label>",'<input id="note-dialog-image-url-'+this.options.id+'" class="note-image-url form-control note-form-control note-input" type="text"/>',"</div>"].join(""),r='<input type="button" href="#" class="'.concat("btn btn-primary note-btn note-btn-primary note-image-btn",'" value="').concat(this.lang.image.insert,'" disabled>');this.$dialog=this.ui.dialog({title:this.lang.image.insert,fade:this.options.dialogsFade,body:i,footer:r}).render().appendTo(o)}},{key:"destroy",value:function(){this.ui.hideDialog(this.$dialog),this.$dialog.remove()}},{key:"bindEnterKey",value:function(t,e){t.on("keypress",(function(t){t.keyCode===xt.code.ENTER&&(t.preventDefault(),e.trigger("click"))}))}},{key:"show",value:function(){var t=this;this.context.invoke("editor.saveRange"),this.showImageDialog().then((function(e){t.ui.hideDialog(t.$dialog),t.context.invoke("editor.restoreRange"),"string"==typeof e?t.options.callbacks.onImageLinkInsert?t.context.triggerEvent("image.link.insert",e):t.context.invoke("editor.insertImage",e):t.context.invoke("editor.insertImagesOrCallback",e)})).fail((function(){t.context.invoke("editor.restoreRange")}))}},{key:"showImageDialog",value:function(){var t=this;return i.a.Deferred((function(e){var n=t.$dialog.find(".note-image-input"),o=t.$dialog.find(".note-image-url"),i=t.$dialog.find(".note-image-btn");t.ui.onDialogShown(t.$dialog,(function(){t.context.triggerEvent("dialog.shown"),n.replaceWith(n.clone().on("change",(function(t){e.resolve(t.target.files||t.target.value)})).val("")),o.on("input paste propertychange",(function(){t.ui.toggleBtn(i,o.val())})).val(""),m.isSupportTouch||o.trigger("focus"),i.click((function(t){t.preventDefault(),e.resolve(o.val())})),t.bindEnterKey(o,i)})),t.ui.onDialogHidden(t.$dialog,(function(){n.off(),o.off(),i.off(),"pending"===e.state()&&e.reject()})),t.ui.showDialog(t.$dialog)}))}}])&&pe(e.prototype,n),o&&pe(e,o),t}();function ve(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}var ge=function(){function t(e){var n=this;!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.context=e,this.ui=i.a.summernote.ui,this.editable=e.layoutInfo.editable[0],this.options=e.options,this.events={"summernote.disable summernote.blur":function(){n.hide()}}}var e,n,o;return e=t,(n=[{key:"shouldInitialize",value:function(){return!C.isEmpty(this.options.popover.image)}},{key:"initialize",value:function(){this.$popover=this.ui.popover({className:"note-image-popover"}).render().appendTo(this.options.container);var t=this.$popover.find(".popover-content,.note-popover-content");this.context.invoke("buttons.build",t,this.options.popover.image),this.$popover.on("mousedown",(function(t){t.preventDefault()}))}},{key:"destroy",value:function(){this.$popover.remove()}},{key:"update",value:function(t,e){if(pt.isImg(t)){var n=i()(t).offset(),o=i()(this.options.container).offset(),r={};this.options.popatmouse?(r.left=e.pageX-20,r.top=e.pageY):r=n,r.top-=o.top,r.left-=o.left,this.$popover.css({display:"block",left:r.left,top:r.top})}else this.hide()}},{key:"hide",value:function(){this.$popover.hide()}}])&&ve(e.prototype,n),o&&ve(e,o),t}();function be(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}var ye=function(){function t(e){var n=this;!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.context=e,this.ui=i.a.summernote.ui,this.options=e.options,this.events={"summernote.mousedown":function(t,e){n.update(e.target)},"summernote.keyup summernote.scroll summernote.change":function(){n.update()},"summernote.disable summernote.blur":function(){n.hide()}}}var e,n,o;return e=t,(n=[{key:"shouldInitialize",value:function(){return!C.isEmpty(this.options.popover.table)}},{key:"initialize",value:function(){this.$popover=this.ui.popover({className:"note-table-popover"}).render().appendTo(this.options.container);var t=this.$popover.find(".popover-content,.note-popover-content");this.context.invoke("buttons.build",t,this.options.popover.table),m.isFF&&document.execCommand("enableInlineTableEditing",!1,!1),this.$popover.on("mousedown",(function(t){t.preventDefault()}))}},{key:"destroy",value:function(){this.$popover.remove()}},{key:"update",value:function(t){if(this.context.isDisabled())return!1;var e=pt.isCell(t);if(e){var n=pt.posFromPlaceholder(t),o=i()(this.options.container).offset();n.top-=o.top,n.left-=o.left,this.$popover.css({display:"block",left:n.left,top:n.top})}else this.hide();return e}},{key:"hide",value:function(){this.$popover.hide()}}])&&be(e.prototype,n),o&&be(e,o),t}();function ke(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}var we=function(){function t(e){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.context=e,this.ui=i.a.summernote.ui,this.$body=i()(document.body),this.$editor=e.layoutInfo.editor,this.options=e.options,this.lang=this.options.langInfo}var e,n,o;return e=t,(n=[{key:"initialize",value:function(){var t=this.options.dialogsInBody?this.$body:this.options.container,e=['<div class="form-group note-form-group row-fluid">','<label for="note-dialog-video-url-'.concat(this.options.id,'" class="note-form-label">').concat(this.lang.video.url,' <small class="text-muted">').concat(this.lang.video.providers,"</small></label>"),'<input id="note-dialog-video-url-'.concat(this.options.id,'" class="note-video-url form-control note-form-control note-input" type="text"/>'),"</div>"].join(""),n='<input type="button" href="#" class="'.concat("btn btn-primary note-btn note-btn-primary note-video-btn",'" value="').concat(this.lang.video.insert,'" disabled>');this.$dialog=this.ui.dialog({title:this.lang.video.insert,fade:this.options.dialogsFade,body:e,footer:n}).render().appendTo(t)}},{key:"destroy",value:function(){this.ui.hideDialog(this.$dialog),this.$dialog.remove()}},{key:"bindEnterKey",value:function(t,e){t.on("keypress",(function(t){t.keyCode===xt.code.ENTER&&(t.preventDefault(),e.trigger("click"))}))}},{key:"createVideoNode",value:function(t){var e,n=t.match(/\/\/(?:(?:www|m)\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))([\w|-]{11})(?:(?:[\?&]t=)(\S+))?$/),o=t.match(/(?:www\.|\/\/)instagram\.com\/p\/(.[a-zA-Z0-9_-]*)/),r=t.match(/\/\/vine\.co\/v\/([a-zA-Z0-9]+)/),a=t.match(/\/\/(player\.)?vimeo\.com\/([a-z]*\/)*(\d+)[?]?.*/),s=t.match(/.+dailymotion.com\/(video|hub)\/([^_]+)[^#]*(#video=([^_&]+))?/),l=t.match(/\/\/v\.youku\.com\/v_show\/id_(\w+)=*\.html/),c=t.match(/\/\/v\.qq\.com.*?vid=(.+)/),u=t.match(/\/\/v\.qq\.com\/x?\/?(page|cover).*?\/([^\/]+)\.html\??.*/),d=t.match(/^.+.(mp4|m4v)$/),h=t.match(/^.+.(ogg|ogv)$/),f=t.match(/^.+.(webm)$/),p=t.match(/(?:www\.|\/\/)facebook\.com\/([^\/]+)\/videos\/([0-9]+)/);if(n&&11===n[1].length){var m=n[1],v=0;if(void 0!==n[2]){var g=n[2].match(/^(?:(\d+)h)?(?:(\d+)m)?(?:(\d+)s)?$/);if(g)for(var b=[3600,60,1],y=0,k=b.length;y<k;y++)v+=void 0!==g[y+1]?b[y]*parseInt(g[y+1],10):0}e=i()("<iframe>").attr("frameborder",0).attr("src","//www.youtube.com/embed/"+m+(v>0?"?start="+v:"")).attr("width","640").attr("height","360")}else if(o&&o[0].length)e=i()("<iframe>").attr("frameborder",0).attr("src","https://instagram.com/p/"+o[1]+"/embed/").attr("width","612").attr("height","710").attr("scrolling","no").attr("allowtransparency","true");else if(r&&r[0].length)e=i()("<iframe>").attr("frameborder",0).attr("src",r[0]+"/embed/simple").attr("width","600").attr("height","600").attr("class","vine-embed");else if(a&&a[3].length)e=i()("<iframe webkitallowfullscreen mozallowfullscreen allowfullscreen>").attr("frameborder",0).attr("src","//player.vimeo.com/video/"+a[3]).attr("width","640").attr("height","360");else if(s&&s[2].length)e=i()("<iframe>").attr("frameborder",0).attr("src","//www.dailymotion.com/embed/video/"+s[2]).attr("width","640").attr("height","360");else if(l&&l[1].length)e=i()("<iframe webkitallowfullscreen mozallowfullscreen allowfullscreen>").attr("frameborder",0).attr("height","498").attr("width","510").attr("src","//player.youku.com/embed/"+l[1]);else if(c&&c[1].length||u&&u[2].length){var w=c&&c[1].length?c[1]:u[2];e=i()("<iframe webkitallowfullscreen mozallowfullscreen allowfullscreen>").attr("frameborder",0).attr("height","310").attr("width","500").attr("src","https://v.qq.com/txp/iframe/player.html?vid="+w+"&amp;auto=0")}else if(d||h||f)e=i()("<video controls>").attr("src",t).attr("width","640").attr("height","360");else{if(!p||!p[0].length)return!1;e=i()("<iframe>").attr("frameborder",0).attr("src","https://www.facebook.com/plugins/video.php?href="+encodeURIComponent(p[0])+"&show_text=0&width=560").attr("width","560").attr("height","301").attr("scrolling","no").attr("allowtransparency","true")}return e.addClass("note-video-clip"),e[0]}},{key:"show",value:function(){var t=this,e=this.context.invoke("editor.getSelectedText");this.context.invoke("editor.saveRange"),this.showVideoDialog(e).then((function(e){t.ui.hideDialog(t.$dialog),t.context.invoke("editor.restoreRange");var n=t.createVideoNode(e);n&&t.context.invoke("editor.insertNode",n)})).fail((function(){t.context.invoke("editor.restoreRange")}))}},{key:"showVideoDialog",value:function(){var t=this;return i.a.Deferred((function(e){var n=t.$dialog.find(".note-video-url"),o=t.$dialog.find(".note-video-btn");t.ui.onDialogShown(t.$dialog,(function(){t.context.triggerEvent("dialog.shown"),n.on("input paste propertychange",(function(){t.ui.toggleBtn(o,n.val())})),m.isSupportTouch||n.trigger("focus"),o.click((function(t){t.preventDefault(),e.resolve(n.val())})),t.bindEnterKey(n,o)})),t.ui.onDialogHidden(t.$dialog,(function(){n.off(),o.off(),"pending"===e.state()&&e.reject()})),t.ui.showDialog(t.$dialog)}))}}])&&ke(e.prototype,n),o&&ke(e,o),t}();function Ce(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}var xe=function(){function t(e){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.context=e,this.ui=i.a.summernote.ui,this.$body=i()(document.body),this.$editor=e.layoutInfo.editor,this.options=e.options,this.lang=this.options.langInfo}var e,n,o;return e=t,(n=[{key:"initialize",value:function(){var t=this.options.dialogsInBody?this.$body:this.options.container,e=['<p class="text-center">','<a href="http://summernote.org/" target="_blank">Summernote 0.8.18</a> · ','<a href="https://github.com/summernote/summernote" target="_blank">Project</a> · ','<a href="https://github.com/summernote/summernote/issues" target="_blank">Issues</a>',"</p>"].join("");this.$dialog=this.ui.dialog({title:this.lang.options.help,fade:this.options.dialogsFade,body:this.createShortcutList(),footer:e,callback:function(t){t.find(".modal-body,.note-modal-body").css({"max-height":300,overflow:"scroll"})}}).render().appendTo(t)}},{key:"destroy",value:function(){this.ui.hideDialog(this.$dialog),this.$dialog.remove()}},{key:"createShortcutList",value:function(){var t=this,e=this.options.keyMap[m.isMac?"mac":"pc"];return Object.keys(e).map((function(n){var o=e[n],r=i()('<div><div class="help-list-item"></div></div>');return r.append(i()("<label><kbd>"+n+"</kdb></label>").css({width:180,"margin-right":10})).append(i()("<span/>").html(t.context.memo("help."+o)||o)),r.html()})).join("")}},{key:"showHelpDialog",value:function(){var t=this;return i.a.Deferred((function(e){t.ui.onDialogShown(t.$dialog,(function(){t.context.triggerEvent("dialog.shown"),e.resolve()})),t.ui.showDialog(t.$dialog)})).promise()}},{key:"show",value:function(){var t=this;this.context.invoke("editor.saveRange"),this.showHelpDialog().then((function(){t.context.invoke("editor.restoreRange")}))}}])&&Ce(e.prototype,n),o&&Ce(e,o),t}();function Se(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}var Te=function(){function t(e){var n=this;!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.context=e,this.ui=i.a.summernote.ui,this.options=e.options,this.hidable=!0,this.onContextmenu=!1,this.pageX=null,this.pageY=null,this.events={"summernote.contextmenu":function(t){n.options.editing&&(t.preventDefault(),t.stopPropagation(),n.onContextmenu=!0,n.update(!0))},"summernote.mousedown":function(t,e){n.pageX=e.pageX,n.pageY=e.pageY},"summernote.keyup summernote.mouseup summernote.scroll":function(t,e){n.options.editing&&!n.onContextmenu&&(n.pageX=e.pageX,n.pageY=e.pageY,n.update()),n.onContextmenu=!1},"summernote.disable summernote.change summernote.dialog.shown summernote.blur":function(){n.hide()},"summernote.focusout":function(){n.$popover.is(":active,:focus")||n.hide()}}}var e,n,o;return e=t,(n=[{key:"shouldInitialize",value:function(){return this.options.airMode&&!C.isEmpty(this.options.popover.air)}},{key:"initialize",value:function(){var t=this;this.$popover=this.ui.popover({className:"note-air-popover"}).render().appendTo(this.options.container);var e=this.$popover.find(".popover-content");this.context.invoke("buttons.build",e,this.options.popover.air),this.$popover.on("mousedown",(function(){t.hidable=!1})),this.$popover.on("mouseup",(function(){t.hidable=!0}))}},{key:"destroy",value:function(){this.$popover.remove()}},{key:"update",value:function(t){var e=this.context.invoke("editor.currentStyle");if(!e.range||e.range.isCollapsed()&&!t)this.hide();else{var n={left:this.pageX,top:this.pageY},o=i()(this.options.container).offset();n.top-=o.top,n.left-=o.left,this.$popover.css({display:"block",left:Math.max(n.left,0)+-5,top:n.top+5}),this.context.invoke("buttons.updateCurrentStyle",this.$popover)}}},{key:"updateCodeview",value:function(t){this.ui.toggleBtnActive(this.$popover.find(".btn-codeview"),t),t&&this.hide()}},{key:"hide",value:function(){this.hidable&&this.$popover.hide()}}])&&Se(e.prototype,n),o&&Se(e,o),t}();function Ee(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}var Ie=function(){function t(e){var n=this;!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.context=e,this.ui=i.a.summernote.ui,this.$editable=e.layoutInfo.editable,this.options=e.options,this.hint=this.options.hint||[],this.direction=this.options.hintDirection||"bottom",this.hints=Array.isArray(this.hint)?this.hint:[this.hint],this.events={"summernote.keyup":function(t,e){e.isDefaultPrevented()||n.handleKeyup(e)},"summernote.keydown":function(t,e){n.handleKeydown(e)},"summernote.disable summernote.dialog.shown summernote.blur":function(){n.hide()}}}var e,n,o;return e=t,(n=[{key:"shouldInitialize",value:function(){return this.hints.length>0}},{key:"initialize",value:function(){var t=this;this.lastWordRange=null,this.matchingWord=null,this.$popover=this.ui.popover({className:"note-hint-popover",hideArrow:!0,direction:""}).render().appendTo(this.options.container),this.$popover.hide(),this.$content=this.$popover.find(".popover-content,.note-popover-content"),this.$content.on("click",".note-hint-item",(function(e){t.$content.find(".active").removeClass("active"),i()(e.currentTarget).addClass("active"),t.replace()})),this.$popover.on("mousedown",(function(t){t.preventDefault()}))}},{key:"destroy",value:function(){this.$popover.remove()}},{key:"selectItem",value:function(t){this.$content.find(".active").removeClass("active"),t.addClass("active"),this.$content[0].scrollTop=t[0].offsetTop-this.$content.innerHeight()/2}},{key:"moveDown",value:function(){var t=this.$content.find(".note-hint-item.active"),e=t.next();if(e.length)this.selectItem(e);else{var n=t.parent().next();n.length||(n=this.$content.find(".note-hint-group").first()),this.selectItem(n.find(".note-hint-item").first())}}},{key:"moveUp",value:function(){var t=this.$content.find(".note-hint-item.active"),e=t.prev();if(e.length)this.selectItem(e);else{var n=t.parent().prev();n.length||(n=this.$content.find(".note-hint-group").last()),this.selectItem(n.find(".note-hint-item").last())}}},{key:"replace",value:function(){var t=this.$content.find(".note-hint-item.active");if(t.length){var e=this.nodeFromItem(t);if(null!==this.matchingWord&&0===this.matchingWord.length)this.lastWordRange.so=this.lastWordRange.eo;else if(null!==this.matchingWord&&this.matchingWord.length>0&&!this.lastWordRange.isCollapsed()){var n=this.lastWordRange.eo-this.lastWordRange.so-this.matchingWord.length;n>0&&(this.lastWordRange.so+=n)}if(this.lastWordRange.insertNode(e),"next"===this.options.hintSelect){var o=document.createTextNode("");i()(e).after(o),wt.createFromNodeBefore(o).select()}else wt.createFromNodeAfter(e).select();this.lastWordRange=null,this.hide(),this.context.invoke("editor.focus")}}},{key:"nodeFromItem",value:function(t){var e=this.hints[t.data("index")],n=t.data("item"),o=e.content?e.content(n):n;return"string"==typeof o&&(o=pt.createText(o)),o}},{key:"createItemTemplates",value:function(t,e){var n=this.hints[t];return e.map((function(e){var o=i()('<div class="note-hint-item"/>');return o.append(n.template?n.template(e):e+""),o.data({index:t,item:e}),o}))}},{key:"handleKeydown",value:function(t){this.$popover.is(":visible")&&(t.keyCode===xt.code.ENTER?(t.preventDefault(),this.replace()):t.keyCode===xt.code.UP?(t.preventDefault(),this.moveUp()):t.keyCode===xt.code.DOWN&&(t.preventDefault(),this.moveDown()))}},{key:"searchKeyword",value:function(t,e,n){var o=this.hints[t];if(o&&o.match.test(e)&&o.search){var i=o.match.exec(e);this.matchingWord=i[0],o.search(i[1],n)}else n()}},{key:"createGroup",value:function(t,e){var n=this,o=i()('<div class="note-hint-group note-hint-group-'+t+'"></div>');return this.searchKeyword(t,e,(function(e){(e=e||[]).length&&(o.html(n.createItemTemplates(t,e)),n.show())})),o}},{key:"handleKeyup",value:function(t){var e=this;if(!C.contains([xt.code.ENTER,xt.code.UP,xt.code.DOWN],t.keyCode)){var n,o,r=this.context.invoke("editor.getLastRange");if("words"===this.options.hintMode){if(n=r.getWordsRange(r),o=n.toString(),this.hints.forEach((function(t){if(t.match.test(o))return n=r.getWordsMatchRange(t.match),!1})),!n)return void this.hide();o=n.toString()}else n=r.getWordRange(),o=n.toString();if(this.hints.length&&o){this.$content.empty();var a=g.rect2bnd(C.last(n.getClientRects())),s=i()(this.options.container).offset();a&&(a.top-=s.top,a.left-=s.left,this.$popover.hide(),this.lastWordRange=n,this.hints.forEach((function(t,n){t.match.test(o)&&e.createGroup(n,o).appendTo(e.$content)})),this.$content.find(".note-hint-item:first").addClass("active"),"top"===this.direction?this.$popover.css({left:a.left,top:a.top-this.$popover.outerHeight()-5}):this.$popover.css({left:a.left,top:a.top+a.height+5}))}else this.hide()}}},{key:"show",value:function(){this.$popover.show()}},{key:"hide",value:function(){this.$popover.hide()}}])&&Ee(e.prototype,n),o&&Ee(e,o),t}();i.a.summernote=i.a.extend(i.a.summernote,{version:"0.8.18",plugins:{},dom:pt,range:wt,lists:C,options:{langInfo:i.a.summernote.lang["en-US"],editing:!0,modules:{editor:Ht,clipboard:Bt,dropzone:Ot,codeview:Kt,statusbar:qt,fullscreen:Gt,handle:Zt,hintPopover:Ie,autoLink:Jt,autoSync:ee,autoReplace:oe,placeholder:re,buttons:se,toolbar:ce,linkDialog:de,linkPopover:fe,imageDialog:me,imagePopover:ge,tablePopover:ye,videoDialog:we,helpDialog:xe,airPopover:Te},buttons:{},lang:"en-US",followingToolbar:!1,toolbarPosition:"top",otherStaticBar:"",codeviewKeepButton:!1,toolbar:[["style",["style"]],["font",["bold","underline","clear"]],['fontsize',['fontsize']],["fontname",["fontname"]],["color",["color"]],["para",["ul","ol","paragraph"]],["table",["table"]],["insert",["link","picture","video"]],["view",["fullscreen","codeview","help"]]],popatmouse:!0,popover:{image:[["resize",["resizeFull","resizeHalf","resizeQuarter","resizeNone"]],["float",["floatLeft","floatRight","floatNone"]],["remove",["removeMedia"]]],link:[["link",["linkDialogShow","unlink"]]],table:[["add",["addRowDown","addRowUp","addColLeft","addColRight"]],["delete",["deleteRow","deleteCol","deleteTable"]]],air:[["color",["color"]],["font",["bold","underline","clear"]],["para",["ul","paragraph"]],["table",["table"]],["insert",["link","picture"]],["view",["fullscreen","codeview"]]]},airMode:!1,overrideContextMenu:!1,width:null,height:null,linkTargetBlank:!0,useProtocol:!0,defaultProtocol:"http://",focus:!1,tabDisabled:!1,tabSize:4,styleWithCSS:!1,shortcuts:!0,textareaAutoSync:!0,tooltip:"auto",container:null,maxTextLength:0,blockquoteBreakingLevel:2,spellCheck:!0,disableGrammar:!1,placeholder:null,inheritPlaceholder:!1,recordEveryKeystroke:!1,historyLimit:200,showDomainOnlyForAutolink:!1,hintMode:"word",hintSelect:"after",hintDirection:"bottom",styleTags:["p","blockquote","pre","h1","h2","h3","h4","h5","h6"],fontNames:["Arial","Arial Black","Comic Sans MS","Courier New","Helvetica Neue","Helvetica","Impact","Lucida Grande","Tahoma","Times New Roman","Verdana"],fontNamesIgnoreCheck:[],addDefaultFonts:!0,fontSizes:["8","9","10","11","12","14","18","24","36"],fontSizeUnits:["px","pt"],colors:[["#000000","#424242","#636363","#9C9C94","#CEC6CE","#EFEFEF","#F7F7F7","#FFFFFF"],["#FF0000","#FF9C00","#FFFF00","#00FF00","#00FFFF","#0000FF","#9C00FF","#FF00FF"],["#F7C6CE","#FFE7CE","#FFEFC6","#D6EFD6","#CEDEE7","#CEE7F7","#D6D6E7","#E7D6DE"],["#E79C9C","#FFC69C","#FFE79C","#B5D6A5","#A5C6CE","#9CC6EF","#B5A5D6","#D6A5BD"],["#E76363","#F7AD6B","#FFD663","#94BD7B","#73A5AD","#6BADDE","#8C7BC6","#C67BA5"],["#CE0000","#E79439","#EFC631","#6BA54A","#4A7B8C","#3984C6","#634AA5","#A54A7B"],["#9C0000","#B56308","#BD9400","#397B21","#104A5A","#085294","#311873","#731842"],["#630000","#7B3900","#846300","#295218","#083139","#003163","#21104A","#4A1031"]],colorsName:[["Black","Tundora","Dove Gray","Star Dust","Pale Slate","Gallery","Alabaster","White"],["Red","Orange Peel","Yellow","Green","Cyan","Blue","Electric Violet","Magenta"],["Azalea","Karry","Egg White","Zanah","Botticelli","Tropical Blue","Mischka","Twilight"],["Tonys Pink","Peach Orange","Cream Brulee","Sprout","Casper","Perano","Cold Purple","Careys Pink"],["Mandy","Rajah","Dandelion","Olivine","Gulf Stream","Viking","Blue Marguerite","Puce"],["Guardsman Red","Fire Bush","Golden Dream","Chelsea Cucumber","Smalt Blue","Boston Blue","Butterfly Bush","Cadillac"],["Sangria","Mai Tai","Buddha Gold","Forest Green","Eden","Venice Blue","Meteorite","Claret"],["Rosewood","Cinnamon","Olive","Parsley","Tiber","Midnight Blue","Valentino","Loulou"]],colorButton:{foreColor:"#000000",backColor:"#FFFF00"},lineHeights:["1.0","1.2","1.4","1.5","1.6","1.8","2.0","3.0"],tableClassName:"table table-bordered",insertTableMaxSize:{col:10,row:10},dialogsInBody:!1,dialogsFade:!1,maximumImageFileSize:null,callbacks:{onBeforeCommand:null,onBlur:null,onBlurCodeview:null,onChange:null,onChangeCodeview:null,onDialogShown:null,onEnter:null,onFocus:null,onImageLinkInsert:null,onImageUpload:null,onImageUploadError:null,onInit:null,onKeydown:null,onKeyup:null,onMousedown:null,onMouseup:null,onPaste:null,onScroll:null},codemirror:{mode:"text/html",htmlMode:!0,lineNumbers:!0},codeviewFilter:!1,codeviewFilterRegex:/<\/*(?:applet|b(?:ase|gsound|link)|embed|frame(?:set)?|ilayer|l(?:ayer|ink)|meta|object|s(?:cript|tyle)|t(?:itle|extarea)|xml)[^>]*?>/gi,codeviewIframeFilter:!0,codeviewIframeWhitelistSrc:[],codeviewIframeWhitelistSrcBase:["www.youtube.com","www.youtube-nocookie.com","www.facebook.com","vine.co","instagram.com","player.vimeo.com","www.dailymotion.com","player.youku.com","v.qq.com"],keyMap:{pc:{ESC:"escape",ENTER:"insertParagraph","CTRL+Z":"undo","CTRL+Y":"redo",TAB:"tab","SHIFT+TAB":"untab","CTRL+B":"bold","CTRL+I":"italic","CTRL+U":"underline","CTRL+SHIFT+S":"strikethrough","CTRL+BACKSLASH":"removeFormat","CTRL+SHIFT+L":"justifyLeft","CTRL+SHIFT+E":"justifyCenter","CTRL+SHIFT+R":"justifyRight","CTRL+SHIFT+J":"justifyFull","CTRL+SHIFT+NUM7":"insertUnorderedList","CTRL+SHIFT+NUM8":"insertOrderedList","CTRL+LEFTBRACKET":"outdent","CTRL+RIGHTBRACKET":"indent","CTRL+NUM0":"formatPara","CTRL+NUM1":"formatH1","CTRL+NUM2":"formatH2","CTRL+NUM3":"formatH3","CTRL+NUM4":"formatH4","CTRL+NUM5":"formatH5","CTRL+NUM6":"formatH6","CTRL+ENTER":"insertHorizontalRule","CTRL+K":"linkDialog.show"},mac:{ESC:"escape",ENTER:"insertParagraph","CMD+Z":"undo","CMD+SHIFT+Z":"redo",TAB:"tab","SHIFT+TAB":"untab","CMD+B":"bold","CMD+I":"italic","CMD+U":"underline","CMD+SHIFT+S":"strikethrough","CMD+BACKSLASH":"removeFormat","CMD+SHIFT+L":"justifyLeft","CMD+SHIFT+E":"justifyCenter","CMD+SHIFT+R":"justifyRight","CMD+SHIFT+J":"justifyFull","CMD+SHIFT+NUM7":"insertUnorderedList","CMD+SHIFT+NUM8":"insertOrderedList","CMD+LEFTBRACKET":"outdent","CMD+RIGHTBRACKET":"indent","CMD+NUM0":"formatPara","CMD+NUM1":"formatH1","CMD+NUM2":"formatH2","CMD+NUM3":"formatH3","CMD+NUM4":"formatH4","CMD+NUM5":"formatH5","CMD+NUM6":"formatH6","CMD+ENTER":"insertHorizontalRule","CMD+K":"linkDialog.show"}},icons:{align:"note-icon-align",alignCenter:"note-icon-align-center",alignJustify:"note-icon-align-justify",alignLeft:"note-icon-align-left",alignRight:"note-icon-align-right",rowBelow:"note-icon-row-below",colBefore:"note-icon-col-before",colAfter:"note-icon-col-after",rowAbove:"note-icon-row-above",rowRemove:"note-icon-row-remove",colRemove:"note-icon-col-remove",indent:"note-icon-align-indent",outdent:"note-icon-align-outdent",arrowsAlt:"note-icon-arrows-alt",bold:"note-icon-bold",caret:"note-icon-caret",circle:"note-icon-circle",close:"note-icon-close",code:"note-icon-code",eraser:"note-icon-eraser",floatLeft:"note-icon-float-left",floatRight:"note-icon-float-right",font:"note-icon-font",frame:"note-icon-frame",italic:"note-icon-italic",link:"note-icon-link",unlink:"note-icon-chain-broken",magic:"note-icon-magic",menuCheck:"note-icon-menu-check",minus:"note-icon-minus",orderedlist:"note-icon-orderedlist",pencil:"note-icon-pencil",picture:"note-icon-picture",question:"note-icon-question",redo:"note-icon-redo",rollback:"note-icon-rollback",square:"note-icon-square",strikethrough:"note-icon-strikethrough",subscript:"note-icon-subscript",superscript:"note-icon-superscript",table:"note-icon-table",textHeight:"note-icon-text-height",trash:"note-icon-trash",underline:"note-icon-underline",undo:"note-icon-undo",unorderedlist:"note-icon-unorderedlist",video:"note-icon-video"}}})},4:function(t,e,n){},52:function(t,e,n){"use strict";n.r(e);var o=n(0),i=n.n(o),r=n(1);function a(t){return(a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}var s=r.a.create('<div class="note-editor note-frame panel panel-default"/>'),l=r.a.create('<div class="panel-heading note-toolbar" role="toolbar"/>'),c=r.a.create('<div class="note-editing-area"/>'),u=r.a.create('<textarea class="note-codable" aria-multiline="true"/>'),d=r.a.create('<div class="note-editable" contentEditable="true" role="textbox" aria-multiline="true"/>'),h=r.a.create(['<output class="note-status-output" role="status" aria-live="polite"></output>','<div class="note-statusbar" role="status">','<div class="note-resizebar" aria-label="Resize">','<div class="note-icon-bar"></div>','<div class="note-icon-bar"></div>','<div class="note-icon-bar"></div>',"</div>","</div>"].join("")),f=r.a.create('<div class="note-editor note-airframe"/>'),p=r.a.create(['<div class="note-editable" contentEditable="true" role="textbox" aria-multiline="true"></div>','<output class="note-status-output" role="status" aria-live="polite"></output>'].join("")),m=r.a.create('<div class="note-btn-group btn-group">'),v=r.a.create('<ul class="note-dropdown-menu dropdown-menu">',(function(t,e){var n=Array.isArray(e.items)?e.items.map((function(t){var n="string"==typeof t?t:t.value||"",o=e.template?e.template(t):t,i="object"===a(t)?t.option:void 0;return'<li aria-label="'+n+'"><a href="#" '+('data-value="'+n+'"'+(void 0!==i?' data-option="'+i+'"':""))+">"+o+"</a></li>"})).join(""):e.items;t.html(n).attr({"aria-label":e.title}),e&&e.codeviewKeepButton&&t.addClass("note-codeview-keep")})),g=function(t,e){return t+" "+C(e.icons.caret,"span")},b=r.a.create('<ul class="note-dropdown-menu dropdown-menu note-check">',(function(t,e){var n=Array.isArray(e.items)?e.items.map((function(t){var n="string"==typeof t?t:t.value||"",o=e.template?e.template(t):t;return'<li aria-label="'+t+'"><a href="#" data-value="'+n+'">'+C(e.checkClassName)+" "+o+"</a></li>"})).join(""):e.items;t.html(n).attr({"aria-label":e.title}),e&&e.codeviewKeepButton&&t.addClass("note-codeview-keep")})),y=r.a.create('<div class="modal note-modal" aria-hidden="false" tabindex="-1" role="dialog"/>',(function(t,e){e.fade&&t.addClass("fade"),t.attr({"aria-label":e.title}),t.html(['<div class="modal-dialog">','<div class="modal-content">',e.title?'<div class="modal-header"><button type="button" class="close" data-dismiss="modal" aria-label="Close" aria-hidden="true">&times;</button><h4 class="modal-title">'+e.title+"</h4></div>":"",'<div class="modal-body">'+e.body+"</div>",e.footer?'<div class="modal-footer">'+e.footer+"</div>":"","</div>","</div>"].join(""))})),k=r.a.create(['<div class="note-popover popover in">','<div class="arrow"></div>','<div class="popover-content note-children-container"></div>',"</div>"].join(""),(function(t,e){var n=void 0!==e.direction?e.direction:"bottom";t.addClass(n),e.hideArrow&&t.find(".arrow").hide()})),w=r.a.create('<div class="checkbox"></div>',(function(t,e){t.html(["<label"+(e.id?' for="note-'+e.id+'"':"")+">",'<input type="checkbox"'+(e.id?' id="note-'+e.id+'"':""),e.checked?" checked":"",' aria-checked="'+(e.checked?"true":"false")+'"/>',e.text?e.text:"","</label>"].join(""))})),C=function(t,e){return"<"+(e=e||"i")+' class="'+t+'"></'+e+">"},x=function(t){return{editor:s,toolbar:l,editingArea:c,codable:u,editable:d,statusbar:h,airEditor:f,airEditable:p,buttonGroup:m,dropdown:v,dropdownButtonContents:g,dropdownCheck:b,dialog:y,popover:k,checkbox:w,icon:C,options:t,palette:function(e,n){return r.a.create('<div class="note-color-palette"/>',(function(e,n){for(var o=[],i=0,r=n.colors.length;i<r;i++){for(var a=n.eventName,s=n.colors[i],l=n.colorsName[i],c=[],u=0,d=s.length;u<d;u++){var h=s[u],f=l[u];c.push(['<button type="button" class="note-color-btn"','style="background-color:',h,'" ','data-event="',a,'" ','data-value="',h,'" ','title="',f,'" ','aria-label="',f,'" ','data-toggle="button" tabindex="-1"></button>'].join(""))}o.push('<div class="note-color-row">'+c.join("")+"</div>")}e.html(o.join("")),n.tooltip&&e.find(".note-color-btn").tooltip({container:n.container||t.container,trigger:"hover",placement:"bottom"})}))(e,n)},button:function(e,n){return r.a.create('<button type="button" class="note-btn btn btn-default btn-sm" tabindex="-1">',(function(e,n){n&&n.tooltip&&e.attr({title:n.tooltip,"aria-label":n.tooltip}).tooltip({container:n.container||t.container,trigger:"hover",placement:"bottom"}).on("click",(function(t){i()(t.currentTarget).tooltip("hide")})),n&&n.codeviewButton&&e.addClass("note-codeview-keep")}))(e,n)},toggleBtn:function(t,e){t.toggleClass("disabled",!e),t.attr("disabled",!e)},toggleBtnActive:function(t,e){t.toggleClass("active",e)},onDialogShown:function(t,e){t.one("shown.bs.modal",e)},onDialogHidden:function(t,e){t.one("hidden.bs.modal",e)},showDialog:function(t){t.modal("show")},hideDialog:function(t){t.modal("hide")},createLayout:function(e){var n=(t.airMode?f([c([u(),p()])]):"bottom"===t.toolbarPosition?s([c([u(),d()]),l(),h()]):s([l(),c([u(),d()]),h()])).render();return n.insertAfter(e),{note:e,editor:n,toolbar:n.find(".note-toolbar"),editingArea:n.find(".note-editing-area"),editable:n.find(".note-editable"),codable:n.find(".note-codable"),statusbar:n.find(".note-statusbar")}},removeLayout:function(t,e){t.html(e.editable.html()),e.editor.remove(),t.show()}}};n(3),n(4);i.a.summernote=i.a.extend(i.a.summernote,{ui_template:x,interface:"bs3"})}})}));
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/typeahead/bootstrap-typeahead.js b/ruoyi-admin/src/main/resources/static/ajax/libs/typeahead/bootstrap-typeahead.js
new file mode 100644
index 0000000..b26b84b
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/typeahead/bootstrap-typeahead.js
@@ -0,0 +1,774 @@
+/* =============================================================
+ * bootstrap3-typeahead.js v4.0.2
+ * https://github.com/bassjobsen/Bootstrap-3-Typeahead
+ * =============================================================
+ * Original written by @mdo and @fat
+ * =============================================================
+ * Copyright 2014 Bass Jobsen @bassjobsen
+ *
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================ */
+
+
+(function (root, factory) {
+
+    'use strict';
+
+    // CommonJS module is defined
+    if (typeof module !== 'undefined' && module.exports) {
+        module.exports = factory(require('jquery'));
+    }
+    // AMD module is defined
+    else if (typeof define === 'function' && define.amd) {
+        define(['jquery'], function ($) {
+            return factory($);
+        });
+    } else {
+        factory(root.jQuery);
+    }
+
+}(this, function ($) {
+
+    'use strict';
+    // jshint laxcomma: true
+
+
+    /* TYPEAHEAD PUBLIC CLASS DEFINITION
+     * ================================= */
+
+    var Typeahead = function (element, options) {
+        this.$element = $(element);
+        this.options = $.extend({}, Typeahead.defaults, options);
+        this.matcher = this.options.matcher || this.matcher;
+        this.sorter = this.options.sorter || this.sorter;
+        this.select = this.options.select || this.select;
+        this.autoSelect = typeof this.options.autoSelect == 'boolean' ? this.options.autoSelect : true;
+        this.highlighter = this.options.highlighter || this.highlighter;
+        this.render = this.options.render || this.render;
+        this.updater = this.options.updater || this.updater;
+        this.displayText = this.options.displayText || this.displayText;
+        this.itemLink = this.options.itemLink || this.itemLink;
+        this.itemTitle = this.options.itemTitle || this.itemTitle;
+        this.followLinkOnSelect = this.options.followLinkOnSelect || this.followLinkOnSelect;
+        this.source = this.options.source;
+        this.delay = this.options.delay;
+        this.theme = this.options.theme && this.options.themes && this.options.themes[this.options.theme] || Typeahead.defaults.themes[Typeahead.defaults.theme];
+        this.$menu = $(this.options.menu || this.theme.menu);
+        this.$appendTo = this.options.appendTo ? $(this.options.appendTo) : null;
+        this.fitToElement = typeof this.options.fitToElement == 'boolean' ? this.options.fitToElement : false;
+        this.shown = false;
+        this.listen();
+        this.showHintOnFocus = typeof this.options.showHintOnFocus == 'boolean' || this.options.showHintOnFocus === 'all' ? this.options.showHintOnFocus : false;
+        this.afterSelect = this.options.afterSelect;
+        this.afterEmptySelect = this.options.afterEmptySelect;
+        this.addItem = false;
+        this.value = this.$element.val() || this.$element.text();
+        this.keyPressed = false;
+        this.focused = this.$element.is(':focus');
+        this.changeInputOnSelect = this.options.changeInputOnSelect || this.changeInputOnSelect;
+        this.changeInputOnMove = this.options.changeInputOnMove || this.changeInputOnMove;
+        this.openLinkInNewTab = this.options.openLinkInNewTab || this.openLinkInNewTab;
+        this.selectOnBlur = this.options.selectOnBlur || this.selectOnBlur;
+        this.showCategoryHeader = this.options.showCategoryHeader || this.showCategoryHeader;
+    };
+
+    Typeahead.prototype = {
+
+        constructor: Typeahead,
+
+
+        setDefault: function (val) {
+            // var val = this.$menu.find('.active').data('value');
+            this.$element.data('active', val);
+            if (this.autoSelect || val) {
+                var newVal = this.updater(val);
+                // Updater can be set to any random functions via "options" parameter in constructor above.
+                // Add null check for cases when updater returns void or undefined.
+                if (!newVal) {
+                    newVal = '';
+                }
+                this.$element
+                    .val(this.displayText(newVal) || newVal)
+                    .text(this.displayText(newVal) || newVal)
+                    .change();
+                this.afterSelect(newVal);
+            }
+            return this.hide();
+        },
+
+        select: function () {
+            var val = this.$menu.find('.active').data('value');
+
+            this.$element.data('active', val);
+            if (this.autoSelect || val) {
+                var newVal = this.updater(val);
+                // Updater can be set to any random functions via "options" parameter in constructor above.
+                // Add null check for cases when updater returns void or undefined.
+                if (!newVal) {
+                    newVal = '';
+                }
+
+                if (this.changeInputOnSelect) {
+                    this.$element
+                        .val(this.displayText(newVal) || newVal)
+                        .text(this.displayText(newVal) || newVal)
+                        .change();
+                }
+
+                if (this.followLinkOnSelect && this.itemLink(val)) {
+                    if (this.openLinkInNewTab) {
+                        window.open(this.itemLink(val), '_blank');
+                    } else {
+                        document.location = this.itemLink(val);
+                    }
+                    this.afterSelect(newVal);
+                } else if (this.followLinkOnSelect && !this.itemLink(val)) {
+                    this.afterEmptySelect(newVal);
+                } else {
+                    this.afterSelect(newVal);
+                }
+            } else {
+                this.afterEmptySelect();
+            }
+
+            return this.hide();
+        },
+
+        updater: function (item) {
+            return item;
+        },
+
+        setSource: function (source) {
+            this.source = source;
+        },
+
+        show: function () {
+            var pos = $.extend({}, this.$element.position(), {
+                height: this.$element[0].offsetHeight
+            });
+
+            var scrollHeight = typeof this.options.scrollHeight == 'function' ?
+                this.options.scrollHeight.call() :
+                this.options.scrollHeight;
+
+            var element;
+            if (this.shown) {
+                element = this.$menu;
+            } else if (this.$appendTo) {
+                element = this.$menu.appendTo(this.$appendTo);
+                this.hasSameParent = this.$appendTo.is(this.$element.parent());
+            } else {
+                element = this.$menu.insertAfter(this.$element);
+                this.hasSameParent = true;
+            }
+
+            if (!this.hasSameParent) {
+                // We cannot rely on the element position, need to position relative to the window
+                element.css('position', 'fixed');
+                var offset = this.$element.offset();
+                pos.top = offset.top;
+                pos.left = offset.left;
+            }
+            // The rules for bootstrap are: 'dropup' in the parent and 'dropdown-menu-right' in the element.
+            // Note that to get right alignment, you'll need to specify `menu` in the options to be:
+            // '<ul class="typeahead dropdown-menu" role="listbox"></ul>'
+            var dropup = $(element).parent().hasClass('dropup');
+            var newTop = dropup ? 'auto' : (pos.top + pos.height + scrollHeight);
+            var right = $(element).hasClass('dropdown-menu-right');
+            var newLeft = right ? 'auto' : pos.left;
+            // it seems like setting the css is a bad idea (just let Bootstrap do it), but I'll keep the old
+            // logic in place except for the dropup/right-align cases.
+            element.css({ top: newTop, left: newLeft }).show();
+
+            if (this.options.fitToElement === true) {
+                element.css('width', this.$element.outerWidth() + 'px');
+            }
+
+            this.shown = true;
+            return this;
+        },
+
+        hide: function () {
+            this.$menu.hide();
+            this.shown = false;
+            return this;
+        },
+
+        lookup: function (query) {
+            if (typeof(query) != 'undefined' && query !== null) {
+                this.query = query;
+            } else {
+                this.query = this.$element.val();
+            }
+
+            if (this.query.length < this.options.minLength && !this.options.showHintOnFocus) {
+                return this.shown ? this.hide() : this;
+            }
+
+            var worker = $.proxy(function () {
+
+                // Bloodhound (since 0.11) needs three arguments.
+                // Two of them are callback functions (sync and async) for local and remote data processing
+                // see https://github.com/twitter/typeahead.js/blob/master/src/bloodhound/bloodhound.js#L132
+                if ($.isFunction(this.source) && this.source.length === 3) {
+                    this.source(this.query, $.proxy(this.process, this), $.proxy(this.process, this));
+                } else if ($.isFunction(this.source)) {
+                    this.source(this.query, $.proxy(this.process, this));
+                } else if (this.source) {
+                    this.process(this.source);
+                }
+            }, this);
+
+            clearTimeout(this.lookupWorker);
+            this.lookupWorker = setTimeout(worker, this.delay);
+        },
+
+        process: function (items) {
+            var that = this;
+
+            items = $.grep(items, function (item) {
+                return that.matcher(item);
+            });
+
+            items = this.sorter(items);
+
+            if (!items.length && !this.options.addItem) {
+                return this.shown ? this.hide() : this;
+            }
+
+            if (items.length > 0) {
+                this.$element.data('active', items[0]);
+            } else {
+                this.$element.data('active', null);
+            }
+
+            if (this.options.items != 'all') {
+                items = items.slice(0, this.options.items);
+            }
+
+            // Add item
+            if (this.options.addItem) {
+                items.push(this.options.addItem);
+            }
+
+            return this.render(items).show();
+        },
+
+        matcher: function (item) {
+            var it = this.displayText(item);
+            return ~it.toLowerCase().indexOf(this.query.toLowerCase());
+        },
+
+        sorter: function (items) {
+            var beginswith = [];
+            var caseSensitive = [];
+            var caseInsensitive = [];
+            var item;
+
+            while ((item = items.shift())) {
+                var it = this.displayText(item);
+                if (!it.toLowerCase().indexOf(this.query.toLowerCase())) {
+                    beginswith.push(item);
+                } else if (~it.indexOf(this.query)) {
+                    caseSensitive.push(item);
+                } else {
+                    caseInsensitive.push(item);
+                }
+            }
+
+            return beginswith.concat(caseSensitive, caseInsensitive);
+        },
+
+        highlighter: function (item) {
+            var text = this.query;
+            if (text === '') {
+                return item;
+            }
+            var matches = item.match(/(>)([^<]*)(<)/g);
+            var first = [];
+            var second = [];
+            var i;
+            if (matches && matches.length) {
+                // html
+                for (i = 0; i < matches.length; ++i) {
+                    if (matches[i].length > 2) {// escape '><'
+                        first.push(matches[i]);
+                    }
+                }
+            } else {
+                // text
+                first = [];
+                first.push(item);
+            }
+            text = text.replace((/[\(\)\/\.\*\+\?\[\]]/g), function (mat) {
+                return '\\' + mat;
+            });
+            var reg = new RegExp(text, 'g');
+            var m;
+            for (i = 0; i < first.length; ++i) {
+                m = first[i].match(reg);
+                if (m && m.length > 0) {// find all text nodes matches
+                    second.push(first[i]);
+                }
+            }
+            for (i = 0; i < second.length; ++i) {
+                item = item.replace(second[i], second[i].replace(reg, '<strong>$&</strong>'));
+            }
+            return item;
+        },
+
+        render: function (items) {
+            var that = this;
+            var self = this;
+            var activeFound = false;
+            var data = [];
+            var _category = that.options.separator;
+
+            $.each(items, function (key, value) {
+                // inject separator
+                if (key > 0 && value[_category] !== items[key - 1][_category]) {
+                    data.push({
+                        __type: 'divider'
+                    });
+                }
+
+                if (this.showCategoryHeader) {
+                    // inject category header
+                    if (value[_category] && (key === 0 || value[_category] !== items[key - 1][_category])) {
+                        data.push({
+                            __type: 'category',
+                            name: value[_category]
+                        });
+                    }
+                }
+
+                data.push(value);
+            });
+
+            items = $(data).map(function (i, item) {
+                    if ((item.__type || false) == 'category'){
+                        return $(that.options.headerHtml || that.theme.headerHtml).text(item.name)[0];
+                    }
+
+                    if ((item.__type || false) == 'divider'){
+                        return $(that.options.headerDivider || that.theme.headerDivider)[0];
+                    }
+
+                    var text = self.displayText(item);
+                    i = $(that.options.item || that.theme.item).data('value', item);
+                    i.find(that.options.itemContentSelector || that.theme.itemContentSelector)
+                        .addBack(that.options.itemContentSelector || that.theme.itemContentSelector)
+                        .html(that.highlighter(text, item));
+                    if(that.options.followLinkOnSelect) {
+                        i.find('a').attr('href', self.itemLink(item));
+                    }
+                    i.find('a').attr('title', self.itemTitle(item));
+                    if (text == self.$element.val()) {
+                        i.addClass('active');
+                        self.$element.data('active', item);
+                        activeFound = true;
+                    }
+                    return i[0];
+                });
+
+            if (this.autoSelect && !activeFound) {
+                items.filter(':not(.dropdown-header)').first().addClass('active');
+                this.$element.data('active', items.first().data('value'));
+            }
+            this.$menu.html(items);
+            return this;
+        },
+
+        displayText: function (item) {
+            return typeof item !== 'undefined' && typeof item.name != 'undefined' ? item.name : item;
+        },
+
+        itemLink: function (item) {
+            return null;
+        },
+
+        itemTitle: function (item) {
+            return null;
+        },
+
+        next: function (event) {
+            var active = this.$menu.find('.active').removeClass('active');
+            var next = active.next();
+
+            if (!next.length) {
+                next = $(this.$menu.find($(this.options.item || this.theme.item).prop('tagName'))[0]);
+            }
+
+            while (next.hasClass('divider') || next.hasClass('dropdown-header')) {
+                next = next.next();
+            }
+
+            next.addClass('active');
+            // added for screen reader
+            var newVal = this.updater(next.data('value'));
+            if (this.changeInputOnMove) {
+                this.$element.val(this.displayText(newVal) || newVal);
+            }
+        },
+
+        prev: function (event) {
+            var active = this.$menu.find('.active').removeClass('active');
+            var prev = active.prev();
+
+            if (!prev.length) {
+                prev = this.$menu.find($(this.options.item || this.theme.item).prop('tagName')).last();
+            }
+
+            while (prev.hasClass('divider') || prev.hasClass('dropdown-header')) {
+                prev = prev.prev();
+            }
+
+            prev.addClass('active');
+            // added for screen reader
+            var newVal = this.updater(prev.data('value'));
+            if (this.changeInputOnMove) {
+                this.$element.val(this.displayText(newVal) || newVal);
+            }
+        },
+
+        listen: function () {
+            this.$element
+                .on('focus.bootstrap3Typeahead', $.proxy(this.focus, this))
+                .on('blur.bootstrap3Typeahead', $.proxy(this.blur, this))
+                .on('keypress.bootstrap3Typeahead', $.proxy(this.keypress, this))
+                .on('propertychange.bootstrap3Typeahead input.bootstrap3Typeahead', $.proxy(this.input, this))
+                .on('keyup.bootstrap3Typeahead', $.proxy(this.keyup, this));
+
+            if (this.eventSupported('keydown')) {
+                this.$element.on('keydown.bootstrap3Typeahead', $.proxy(this.keydown, this));
+            }
+
+            var itemTagName = $(this.options.item || this.theme.item).prop('tagName');
+            if ('ontouchstart' in document.documentElement && 'onmousemove' in document.documentElement) {
+		        this.$menu
+		            .on('touchstart', itemTagName, $.proxy(this.touchstart, this))
+		            .on('touchend', itemTagName, $.proxy(this.click, this))
+		            .on('click', $.proxy(this.click, this))
+		            .on('mouseenter', itemTagName, $.proxy(this.mouseenter, this))
+		            .on('mouseleave', itemTagName, $.proxy(this.mouseleave, this))
+		            .on('mousedown', $.proxy(this.mousedown,this));
+	        } else if ('ontouchstart' in document.documentElement) {
+		        this.$menu
+		            .on('touchstart', itemTagName, $.proxy(this.touchstart, this))
+		            .on('touchend', itemTagName, $.proxy(this.click, this));
+	        } else {
+                this.$menu
+                    .on('click', $.proxy(this.click, this))
+                    .on('mouseenter', itemTagName, $.proxy(this.mouseenter, this))
+                    .on('mouseleave', itemTagName, $.proxy(this.mouseleave, this))
+                    .on('mousedown', $.proxy(this.mousedown, this));
+            }
+        },
+
+        destroy: function () {
+            this.$element.data('typeahead', null);
+            this.$element.data('active', null);
+            this.$element
+                .unbind('focus.bootstrap3Typeahead')
+                .unbind('blur.bootstrap3Typeahead')
+                .unbind('keypress.bootstrap3Typeahead')
+                .unbind('propertychange.bootstrap3Typeahead input.bootstrap3Typeahead')
+                .unbind('keyup.bootstrap3Typeahead');
+
+            if (this.eventSupported('keydown')) {
+                this.$element.unbind('keydown.bootstrap3-typeahead');
+            }
+
+            this.$menu.remove();
+            this.destroyed = true;
+        },
+
+        eventSupported: function (eventName) {
+            var isSupported = eventName in this.$element;
+            if (!isSupported) {
+                this.$element.setAttribute(eventName, 'return;');
+                isSupported = typeof this.$element[eventName] === 'function';
+            }
+            return isSupported;
+        },
+
+        move: function (e) {
+            if (!this.shown) {
+                return;
+            }
+
+            switch (e.keyCode) {
+                case 9: // tab
+                case 13: // enter
+                case 27: // escape
+                    e.preventDefault();
+                    break;
+
+                case 38: // up arrow
+                    // with the shiftKey (this is actually the left parenthesis)
+                    if (e.shiftKey) {
+                        return;
+                    }
+                    e.preventDefault();
+                    this.prev();
+                    break;
+
+                case 40: // down arrow
+                    // with the shiftKey (this is actually the right parenthesis)
+                    if (e.shiftKey) {
+                        return;
+                    }
+                    e.preventDefault();
+                    this.next();
+                    break;
+            }
+        },
+
+        keydown: function (e) {
+            /**
+             * Prevent to make an ajax call while copying and pasting.
+             *
+             * @author Simone Sacchi
+             * @version 2018/01/18
+             */
+            if (e.keyCode === 17) { // ctrl
+                return;
+            }
+            this.keyPressed = true;
+            this.suppressKeyPressRepeat = ~$.inArray(e.keyCode, [40, 38, 9, 13, 27]);
+            if (!this.shown && e.keyCode == 40) {
+                this.lookup();
+            } else {
+                this.move(e);
+            }
+        },
+
+        keypress: function (e) {
+            if (this.suppressKeyPressRepeat) {
+                return;
+            }
+            this.move(e);
+        },
+
+        input: function (e) {
+            // This is a fixed for IE10/11 that fires the input event when a placehoder is changed
+            // (https://connect.microsoft.com/IE/feedback/details/810538/ie-11-fires-input-event-on-focus)
+            var currentValue = this.$element.val() || this.$element.text();
+            if (this.value !== currentValue) {
+                this.value = currentValue;
+                this.lookup();
+            }
+        },
+
+        keyup: function (e) {
+            if (this.destroyed) {
+                return;
+            }
+            switch (e.keyCode) {
+                case 40: // down arrow
+                case 38: // up arrow
+                case 16: // shift
+                case 17: // ctrl
+                case 18: // alt
+                    break;
+
+                case 9: // tab
+                    if (!this.shown || (this.showHintOnFocus && !this.keyPressed)) {
+                        return;
+                    }
+                    this.select();
+                    break;
+                case 13: // enter
+                    if (!this.shown) {
+                        return;
+                    }
+                    this.select();
+                    break;
+
+                case 27: // escape
+                    if (!this.shown) {
+                        return;
+                    }
+                    this.hide();
+                    break;
+            }
+
+        },
+
+        focus: function (e) {
+            if (!this.focused) {
+                this.focused = true;
+                this.keyPressed = false;
+                if (this.options.showHintOnFocus && this.skipShowHintOnFocus !== true) {
+                    if (this.options.showHintOnFocus === 'all') {
+                        this.lookup('');
+                    } else {
+                        this.lookup();
+                    }
+                }
+            }
+            if (this.skipShowHintOnFocus) {
+                this.skipShowHintOnFocus = false;
+            }
+        },
+
+        blur: function (e) {
+            if (!this.mousedover && !this.mouseddown && this.shown) {
+                if (this.selectOnBlur) {
+                    this.select();
+                }
+                this.hide();
+                this.focused = false;
+                this.keyPressed = false;
+            } else if (this.mouseddown) {
+                // This is for IE that blurs the input when user clicks on scroll.
+                // We set the focus back on the input and prevent the lookup to occur again
+                this.skipShowHintOnFocus = true;
+                this.$element.focus();
+                this.mouseddown = false;
+            }
+        },
+
+        click: function (e) {
+            e.preventDefault();
+            this.skipShowHintOnFocus = true;
+            this.select();
+            this.$element.focus();
+            this.hide();
+        },
+
+        mouseenter: function (e) {
+            this.mousedover = true;
+            this.$menu.find('.active').removeClass('active');
+            $(e.currentTarget).addClass('active');
+        },
+
+        mouseleave: function (e) {
+            this.mousedover = false;
+            if (!this.focused && this.shown) {
+                this.hide();
+            }
+        },
+
+        /**
+         * We track the mousedown for IE. When clicking on the menu scrollbar, IE makes the input blur thus hiding the menu.
+         */
+        mousedown: function (e) {
+            this.mouseddown = true;
+            this.$menu.one('mouseup', function (e) {
+                // IE won't fire this, but FF and Chrome will so we reset our flag for them here
+                this.mouseddown = false;
+            }.bind(this));
+        },
+
+        touchstart: function (e) {
+            e.preventDefault();
+            this.$menu.find('.active').removeClass('active');
+            $(e.currentTarget).addClass('active');
+        },
+
+        touchend: function (e) {
+            e.preventDefault();
+            this.select();
+            this.$element.focus();
+        }
+
+    };
+
+
+    /* TYPEAHEAD PLUGIN DEFINITION
+     * =========================== */
+
+    var old = $.fn.typeahead;
+
+    $.fn.typeahead = function (option) {
+        var arg = arguments;
+        if (typeof option == 'string' && option == 'getActive') {
+            return this.data('active');
+        }
+        return this.each(function () {
+            var $this = $(this);
+            var data = $this.data('typeahead');
+            var options = typeof option == 'object' && option;
+            if (!data) {
+                $this.data('typeahead', (data = new Typeahead(this, options)));
+            }
+            if (typeof option == 'string' && data[option]) {
+                if (arg.length > 1) {
+                    data[option].apply(data, Array.prototype.slice.call(arg, 1));
+                } else {
+                    data[option]();
+                }
+            }
+        });
+    };
+
+    Typeahead.defaults = {
+        source: [],
+        items: 8,
+        minLength: 1,
+        scrollHeight: 0,
+        autoSelect: true,
+        afterSelect: $.noop,
+        afterEmptySelect: $.noop,
+        addItem: false,
+        followLinkOnSelect: false,
+        delay: 0,
+        separator: 'category',
+        changeInputOnSelect: true,
+        changeInputOnMove: true,
+        openLinkInNewTab: false,
+        selectOnBlur: true,
+        showCategoryHeader: true,
+        theme: "bootstrap3",
+        themes: {
+        bootstrap3: {
+            menu: '<ul class="typeahead dropdown-menu" role="listbox"></ul>',
+            item: '<li><a class="dropdown-item" href="#" role="option"></a></li>',
+            itemContentSelector: "a",
+            headerHtml: '<li class="dropdown-header"></li>',
+            headerDivider: '<li class="divider" role="separator"></li>'
+        },
+        bootstrap4: {
+            menu: '<div class="typeahead dropdown-menu" role="listbox"></div>',
+            item: '<button class="dropdown-item" role="option"></button>',
+            itemContentSelector: '.dropdown-item',
+            headerHtml: '<h6 class="dropdown-header"></h6>',
+            headerDivider: '<div class="dropdown-divider"></div>'
+        }
+    }
+};
+
+    $.fn.typeahead.Constructor = Typeahead;
+
+    /* TYPEAHEAD NO CONFLICT
+     * =================== */
+
+    $.fn.typeahead.noConflict = function () {
+        $.fn.typeahead = old;
+        return this;
+    };
+
+
+    /* TYPEAHEAD DATA-API
+     * ================== */
+
+    $(document).on('focus.typeahead.data-api', '[data-provide="typeahead"]', function (e) {
+        var $this = $(this);
+        if ($this.data('typeahead')) {
+            return;
+        }
+        $this.typeahead($this.data());
+    });
+
+}));
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/typeahead/bootstrap-typeahead.min.js b/ruoyi-admin/src/main/resources/static/ajax/libs/typeahead/bootstrap-typeahead.min.js
new file mode 100644
index 0000000..f184d08
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/typeahead/bootstrap-typeahead.min.js
@@ -0,0 +1 @@
+!function(t,e){"use strict";"undefined"!=typeof module&&module.exports?module.exports=e(require("jquery")):"function"==typeof define&&define.amd?define(["jquery"],function(t){return e(t)}):e(t.jQuery)}(this,function(t){"use strict";var e=function(s,i){this.$element=t(s),this.options=t.extend({},e.defaults,i),this.matcher=this.options.matcher||this.matcher,this.sorter=this.options.sorter||this.sorter,this.select=this.options.select||this.select,this.autoSelect="boolean"!=typeof this.options.autoSelect||this.options.autoSelect,this.highlighter=this.options.highlighter||this.highlighter,this.render=this.options.render||this.render,this.updater=this.options.updater||this.updater,this.displayText=this.options.displayText||this.displayText,this.itemLink=this.options.itemLink||this.itemLink,this.itemTitle=this.options.itemTitle||this.itemTitle,this.followLinkOnSelect=this.options.followLinkOnSelect||this.followLinkOnSelect,this.source=this.options.source,this.delay=this.options.delay,this.theme=this.options.theme&&this.options.themes&&this.options.themes[this.options.theme]||e.defaults.themes[e.defaults.theme],this.$menu=t(this.options.menu||this.theme.menu),this.$appendTo=this.options.appendTo?t(this.options.appendTo):null,this.fitToElement="boolean"==typeof this.options.fitToElement&&this.options.fitToElement,this.shown=!1,this.listen(),this.showHintOnFocus=("boolean"==typeof this.options.showHintOnFocus||"all"===this.options.showHintOnFocus)&&this.options.showHintOnFocus,this.afterSelect=this.options.afterSelect,this.afterEmptySelect=this.options.afterEmptySelect,this.addItem=!1,this.value=this.$element.val()||this.$element.text(),this.keyPressed=!1,this.focused=this.$element.is(":focus"),this.changeInputOnSelect=this.options.changeInputOnSelect||this.changeInputOnSelect,this.changeInputOnMove=this.options.changeInputOnMove||this.changeInputOnMove,this.openLinkInNewTab=this.options.openLinkInNewTab||this.openLinkInNewTab,this.selectOnBlur=this.options.selectOnBlur||this.selectOnBlur,this.showCategoryHeader=this.options.showCategoryHeader||this.showCategoryHeader};e.prototype={constructor:e,setDefault:function(t){if(this.$element.data("active",t),this.autoSelect||t){var e=this.updater(t);e||(e=""),this.$element.val(this.displayText(e)||e).text(this.displayText(e)||e).change(),this.afterSelect(e)}return this.hide()},select:function(){var t=this.$menu.find(".active").data("value");if(this.$element.data("active",t),this.autoSelect||t){var e=this.updater(t);e||(e=""),this.changeInputOnSelect&&this.$element.val(this.displayText(e)||e).text(this.displayText(e)||e).change(),this.followLinkOnSelect&&this.itemLink(t)?(this.openLinkInNewTab?window.open(this.itemLink(t),"_blank"):document.location=this.itemLink(t),this.afterSelect(e)):this.followLinkOnSelect&&!this.itemLink(t)?this.afterEmptySelect(e):this.afterSelect(e)}else this.afterEmptySelect();return this.hide()},updater:function(t){return t},setSource:function(t){this.source=t},show:function(){var e,s=t.extend({},this.$element.position(),{height:this.$element[0].offsetHeight}),i="function"==typeof this.options.scrollHeight?this.options.scrollHeight.call():this.options.scrollHeight;if(this.shown?e=this.$menu:this.$appendTo?(e=this.$menu.appendTo(this.$appendTo),this.hasSameParent=this.$appendTo.is(this.$element.parent())):(e=this.$menu.insertAfter(this.$element),this.hasSameParent=!0),!this.hasSameParent){e.css("position","fixed");var o=this.$element.offset();s.top=o.top,s.left=o.left}var n=t(e).parent().hasClass("dropup")?"auto":s.top+s.height+i,h=t(e).hasClass("dropdown-menu-right")?"auto":s.left;return e.css({top:n,left:h}).show(),!0===this.options.fitToElement&&e.css("width",this.$element.outerWidth()+"px"),this.shown=!0,this},hide:function(){return this.$menu.hide(),this.shown=!1,this},lookup:function(e){if(this.query=null!=e?e:this.$element.val(),this.query.length<this.options.minLength&&!this.options.showHintOnFocus)return this.shown?this.hide():this;var s=t.proxy(function(){t.isFunction(this.source)&&3===this.source.length?this.source(this.query,t.proxy(this.process,this),t.proxy(this.process,this)):t.isFunction(this.source)?this.source(this.query,t.proxy(this.process,this)):this.source&&this.process(this.source)},this);clearTimeout(this.lookupWorker),this.lookupWorker=setTimeout(s,this.delay)},process:function(e){var s=this;return e=t.grep(e,function(t){return s.matcher(t)}),(e=this.sorter(e)).length||this.options.addItem?(e.length>0?this.$element.data("active",e[0]):this.$element.data("active",null),"all"!=this.options.items&&(e=e.slice(0,this.options.items)),this.options.addItem&&e.push(this.options.addItem),this.render(e).show()):this.shown?this.hide():this},matcher:function(t){return~this.displayText(t).toLowerCase().indexOf(this.query.toLowerCase())},sorter:function(t){for(var e,s=[],i=[],o=[];e=t.shift();){var n=this.displayText(e);n.toLowerCase().indexOf(this.query.toLowerCase())?~n.indexOf(this.query)?i.push(e):o.push(e):s.push(e)}return s.concat(i,o)},highlighter:function(t){var e=this.query;if(""===e)return t;var s,i=t.match(/(>)([^<]*)(<)/g),o=[],n=[];if(i&&i.length)for(s=0;s<i.length;++s)i[s].length>2&&o.push(i[s]);else(o=[]).push(t);e=e.replace(/[\(\)\/\.\*\+\?\[\]]/g,function(t){return"\\"+t});var h,a=new RegExp(e,"g");for(s=0;s<o.length;++s)(h=o[s].match(a))&&h.length>0&&n.push(o[s]);for(s=0;s<n.length;++s)t=t.replace(n[s],n[s].replace(a,"<strong>$&</strong>"));return t},render:function(e){var s=this,i=this,o=!1,n=[],h=s.options.separator;return t.each(e,function(t,s){t>0&&s[h]!==e[t-1][h]&&n.push({__type:"divider"}),this.showCategoryHeader&&(!s[h]||0!==t&&s[h]===e[t-1][h]||n.push({__type:"category",name:s[h]})),n.push(s)}),e=t(n).map(function(e,n){if("category"==(n.__type||!1))return t(s.options.headerHtml||s.theme.headerHtml).text(n.name)[0];if("divider"==(n.__type||!1))return t(s.options.headerDivider||s.theme.headerDivider)[0];var h=i.displayText(n);return(e=t(s.options.item||s.theme.item).data("value",n)).find(s.options.itemContentSelector||s.theme.itemContentSelector).addBack(s.options.itemContentSelector||s.theme.itemContentSelector).html(s.highlighter(h,n)),s.options.followLinkOnSelect&&e.find("a").attr("href",i.itemLink(n)),e.find("a").attr("title",i.itemTitle(n)),h==i.$element.val()&&(e.addClass("active"),i.$element.data("active",n),o=!0),e[0]}),this.autoSelect&&!o&&(e.filter(":not(.dropdown-header)").first().addClass("active"),this.$element.data("active",e.first().data("value"))),this.$menu.html(e),this},displayText:function(t){return void 0!==t&&void 0!==t.name?t.name:t},itemLink:function(t){return null},itemTitle:function(t){return null},next:function(e){var s=this.$menu.find(".active").removeClass("active").next();for(s.length||(s=t(this.$menu.find(t(this.options.item||this.theme.item).prop("tagName"))[0]));s.hasClass("divider")||s.hasClass("dropdown-header");)s=s.next();s.addClass("active");var i=this.updater(s.data("value"));this.changeInputOnMove&&this.$element.val(this.displayText(i)||i)},prev:function(e){var s=this.$menu.find(".active").removeClass("active").prev();for(s.length||(s=this.$menu.find(t(this.options.item||this.theme.item).prop("tagName")).last());s.hasClass("divider")||s.hasClass("dropdown-header");)s=s.prev();s.addClass("active");var i=this.updater(s.data("value"));this.changeInputOnMove&&this.$element.val(this.displayText(i)||i)},listen:function(){this.$element.on("focus.bootstrap3Typeahead",t.proxy(this.focus,this)).on("blur.bootstrap3Typeahead",t.proxy(this.blur,this)).on("keypress.bootstrap3Typeahead",t.proxy(this.keypress,this)).on("propertychange.bootstrap3Typeahead input.bootstrap3Typeahead",t.proxy(this.input,this)).on("keyup.bootstrap3Typeahead",t.proxy(this.keyup,this)),this.eventSupported("keydown")&&this.$element.on("keydown.bootstrap3Typeahead",t.proxy(this.keydown,this));var e=t(this.options.item||this.theme.item).prop("tagName");"ontouchstart"in document.documentElement?this.$menu.on("touchstart",e,t.proxy(this.touchstart,this)).on("touchend",e,t.proxy(this.click,this)):this.$menu.on("click",t.proxy(this.click,this)).on("mouseenter",e,t.proxy(this.mouseenter,this)).on("mouseleave",e,t.proxy(this.mouseleave,this)).on("mousedown",t.proxy(this.mousedown,this))},destroy:function(){this.$element.data("typeahead",null),this.$element.data("active",null),this.$element.unbind("focus.bootstrap3Typeahead").unbind("blur.bootstrap3Typeahead").unbind("keypress.bootstrap3Typeahead").unbind("propertychange.bootstrap3Typeahead input.bootstrap3Typeahead").unbind("keyup.bootstrap3Typeahead"),this.eventSupported("keydown")&&this.$element.unbind("keydown.bootstrap3-typeahead"),this.$menu.remove(),this.destroyed=!0},eventSupported:function(t){var e=t in this.$element;return e||(this.$element.setAttribute(t,"return;"),e="function"==typeof this.$element[t]),e},move:function(t){if(this.shown)switch(t.keyCode){case 9:case 13:case 27:t.preventDefault();break;case 38:if(t.shiftKey)return;t.preventDefault(),this.prev();break;case 40:if(t.shiftKey)return;t.preventDefault(),this.next()}},keydown:function(e){17!==e.keyCode&&(this.keyPressed=!0,this.suppressKeyPressRepeat=~t.inArray(e.keyCode,[40,38,9,13,27]),this.shown||40!=e.keyCode?this.move(e):this.lookup())},keypress:function(t){this.suppressKeyPressRepeat||this.move(t)},input:function(t){var e=this.$element.val()||this.$element.text();this.value!==e&&(this.value=e,this.lookup())},keyup:function(t){if(!this.destroyed)switch(t.keyCode){case 40:case 38:case 16:case 17:case 18:break;case 9:if(!this.shown||this.showHintOnFocus&&!this.keyPressed)return;this.select();break;case 13:if(!this.shown)return;this.select();break;case 27:if(!this.shown)return;this.hide()}},focus:function(t){this.focused||(this.focused=!0,this.keyPressed=!1,this.options.showHintOnFocus&&!0!==this.skipShowHintOnFocus&&("all"===this.options.showHintOnFocus?this.lookup(""):this.lookup())),this.skipShowHintOnFocus&&(this.skipShowHintOnFocus=!1)},blur:function(t){this.mousedover||this.mouseddown||!this.shown?this.mouseddown&&(this.skipShowHintOnFocus=!0,this.$element.focus(),this.mouseddown=!1):(this.selectOnBlur&&this.select(),this.hide(),this.focused=!1,this.keyPressed=!1)},click:function(t){t.preventDefault(),this.skipShowHintOnFocus=!0,this.select(),this.$element.focus(),this.hide()},mouseenter:function(e){this.mousedover=!0,this.$menu.find(".active").removeClass("active"),t(e.currentTarget).addClass("active")},mouseleave:function(t){this.mousedover=!1,!this.focused&&this.shown&&this.hide()},mousedown:function(t){this.mouseddown=!0,this.$menu.one("mouseup",function(t){this.mouseddown=!1}.bind(this))},touchstart:function(e){e.preventDefault(),this.$menu.find(".active").removeClass("active"),t(e.currentTarget).addClass("active")},touchend:function(t){t.preventDefault(),this.select(),this.$element.focus()}};var s=t.fn.typeahead;t.fn.typeahead=function(s){var i=arguments;return"string"==typeof s&&"getActive"==s?this.data("active"):this.each(function(){var o=t(this),n=o.data("typeahead"),h="object"==typeof s&&s;n||o.data("typeahead",n=new e(this,h)),"string"==typeof s&&n[s]&&(i.length>1?n[s].apply(n,Array.prototype.slice.call(i,1)):n[s]())})},e.defaults={source:[],items:8,minLength:1,scrollHeight:0,autoSelect:!0,afterSelect:t.noop,afterEmptySelect:t.noop,addItem:!1,followLinkOnSelect:!1,delay:0,separator:"category",changeInputOnSelect:!0,changeInputOnMove:!0,openLinkInNewTab:!1,selectOnBlur:!0,showCategoryHeader:!0,theme:"bootstrap3",themes:{bootstrap3:{menu:'<ul class="typeahead dropdown-menu" role="listbox"></ul>',item:'<li><a class="dropdown-item" href="#" role="option"></a></li>',itemContentSelector:"a",headerHtml:'<li class="dropdown-header"></li>',headerDivider:'<li class="divider" role="separator"></li>'},bootstrap4:{menu:'<div class="typeahead dropdown-menu" role="listbox"></div>',item:'<button class="dropdown-item" role="option"></button>',itemContentSelector:".dropdown-item",headerHtml:'<h6 class="dropdown-header"></h6>',headerDivider:'<div class="dropdown-divider"></div>'}}},t.fn.typeahead.Constructor=e,t.fn.typeahead.noConflict=function(){return t.fn.typeahead=s,this},t(document).on("focus.typeahead.data-api",'[data-provide="typeahead"]',function(e){var s=t(this);s.data("typeahead")||s.typeahead(s.data())})});
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/validate/additional-methods.min.js b/ruoyi-admin/src/main/resources/static/ajax/libs/validate/additional-methods.min.js
new file mode 100644
index 0000000..e1e0ba8
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/validate/additional-methods.min.js
@@ -0,0 +1,4 @@
+/*! jQuery Validation Plugin - v1.19.3 - 1/9/2021
+ * https://jqueryvalidation.org/
+ * Copyright (c) 2021 Jörn Zaefferer; Licensed MIT */
+!function(a){"function"==typeof define&&define.amd?define(["jquery","./jquery.validate.min"],a):"object"==typeof module&&module.exports?module.exports=a(require("jquery")):a(jQuery)}(function(a){return function(){function b(a){return a.replace(/<.[^<>]*?>/g," ").replace(/&nbsp;|&#160;/gi," ").replace(/[.(),;:!?%#$'\"_+=\/\-“”’]*/g,"")}a.validator.addMethod("maxWords",function(a,c,d){return this.optional(c)||b(a).match(/\b\w+\b/g).length<=d},a.validator.format("Please enter {0} words or less.")),a.validator.addMethod("minWords",function(a,c,d){return this.optional(c)||b(a).match(/\b\w+\b/g).length>=d},a.validator.format("Please enter at least {0} words.")),a.validator.addMethod("rangeWords",function(a,c,d){var e=b(a),f=/\b\w+\b/g;return this.optional(c)||e.match(f).length>=d[0]&&e.match(f).length<=d[1]},a.validator.format("Please enter between {0} and {1} words."))}(),a.validator.addMethod("abaRoutingNumber",function(a){var b=0,c=a.split(""),d=c.length;if(9!==d)return!1;for(var e=0;e<d;e+=3)b+=3*parseInt(c[e],10)+7*parseInt(c[e+1],10)+parseInt(c[e+2],10);return 0!==b&&b%10===0},"Please enter a valid routing number."),a.validator.addMethod("accept",function(b,c,d){var e,f,g,h="string"==typeof d?d.replace(/\s/g,""):"image/*",i=this.optional(c);if(i)return i;if("file"===a(c).attr("type")&&(h=h.replace(/[\-\[\]\/\{\}\(\)\+\?\.\\\^\$\|]/g,"\\$&").replace(/,/g,"|").replace(/\/\*/g,"/.*"),c.files&&c.files.length))for(g=new RegExp(".?("+h+")$","i"),e=0;e<c.files.length;e++)if(f=c.files[e],!f.type.match(g))return!1;return!0},a.validator.format("Please enter a value with a valid mimetype.")),a.validator.addMethod("alphanumeric",function(a,b){return this.optional(b)||/^\w+$/i.test(a)},"Letters, numbers, and underscores only please"),a.validator.addMethod("bankaccountNL",function(a,b){if(this.optional(b))return!0;if(!/^[0-9]{9}|([0-9]{2} ){3}[0-9]{3}$/.test(a))return!1;var c,d,e,f=a.replace(/ /g,""),g=0,h=f.length;for(c=0;c<h;c++)d=h-c,e=f.substring(c,c+1),g+=d*e;return g%11===0},"Please specify a valid bank account number"),a.validator.addMethod("bankorgiroaccountNL",function(b,c){return this.optional(c)||a.validator.methods.bankaccountNL.call(this,b,c)||a.validator.methods.giroaccountNL.call(this,b,c)},"Please specify a valid bank or giro account number"),a.validator.addMethod("bic",function(a,b){return this.optional(b)||/^([A-Z]{6}[A-Z2-9][A-NP-Z1-9])(X{3}|[A-WY-Z0-9][A-Z0-9]{2})?$/.test(a.toUpperCase())},"Please specify a valid BIC code"),a.validator.addMethod("cifES",function(a,b){"use strict";function c(a){return a%2===0}if(this.optional(b))return!0;var d,e,f,g,h=new RegExp(/^([ABCDEFGHJKLMNPQRSUVW])(\d{7})([0-9A-J])$/gi),i=a.substring(0,1),j=a.substring(1,8),k=a.substring(8,9),l=0,m=0,n=0;if(9!==a.length||!h.test(a))return!1;for(d=0;d<j.length;d++)e=parseInt(j[d],10),c(d)?(e*=2,n+=e<10?e:e-9):m+=e;return l=m+n,f=(10-l.toString().substr(-1)).toString(),f=parseInt(f,10)>9?"0":f,g="JABCDEFGHI".substr(f,1).toString(),i.match(/[ABEH]/)?k===f:i.match(/[KPQS]/)?k===g:k===f||k===g},"Please specify a valid CIF number."),a.validator.addMethod("cnhBR",function(a){if(a=a.replace(/([~!@#$%^&*()_+=`{}\[\]\-|\\:;'<>,.\/? ])+/g,""),11!==a.length)return!1;var b,c,d,e,f,g,h=0,i=0;if(b=a.charAt(0),new Array(12).join(b)===a)return!1;for(e=0,f=9,g=0;e<9;++e,--f)h+=+(a.charAt(e)*f);for(c=h%11,c>=10&&(c=0,i=2),h=0,e=0,f=1,g=0;e<9;++e,++f)h+=+(a.charAt(e)*f);return d=h%11,d>=10?d=0:d-=i,String(c).concat(d)===a.substr(-2)},"Please specify a valid CNH number"),a.validator.addMethod("cnpjBR",function(a,b){"use strict";if(this.optional(b))return!0;if(a=a.replace(/[^\d]+/g,""),14!==a.length)return!1;if("00000000000000"===a||"11111111111111"===a||"22222222222222"===a||"33333333333333"===a||"44444444444444"===a||"55555555555555"===a||"66666666666666"===a||"77777777777777"===a||"88888888888888"===a||"99999999999999"===a)return!1;for(var c=a.length-2,d=a.substring(0,c),e=a.substring(c),f=0,g=c-7,h=c;h>=1;h--)f+=d.charAt(c-h)*g--,g<2&&(g=9);var i=f%11<2?0:11-f%11;if(i!==parseInt(e.charAt(0),10))return!1;c+=1,d=a.substring(0,c),f=0,g=c-7;for(var j=c;j>=1;j--)f+=d.charAt(c-j)*g--,g<2&&(g=9);return i=f%11<2?0:11-f%11,i===parseInt(e.charAt(1),10)},"Please specify a CNPJ value number"),a.validator.addMethod("cpfBR",function(a,b){"use strict";if(this.optional(b))return!0;if(a=a.replace(/([~!@#$%^&*()_+=`{}\[\]\-|\\:;'<>,.\/? ])+/g,""),11!==a.length)return!1;var c,d,e,f,g=0;if(c=parseInt(a.substring(9,10),10),d=parseInt(a.substring(10,11),10),e=function(a,b){var c=10*a%11;return 10!==c&&11!==c||(c=0),c===b},""===a||"00000000000"===a||"11111111111"===a||"22222222222"===a||"33333333333"===a||"44444444444"===a||"55555555555"===a||"66666666666"===a||"77777777777"===a||"88888888888"===a||"99999999999"===a)return!1;for(f=1;f<=9;f++)g+=parseInt(a.substring(f-1,f),10)*(11-f);if(e(g,c)){for(g=0,f=1;f<=10;f++)g+=parseInt(a.substring(f-1,f),10)*(12-f);return e(g,d)}return!1},"Please specify a valid CPF number"),a.validator.addMethod("creditcard",function(a,b){if(this.optional(b))return"dependency-mismatch";if(/[^0-9 \-]+/.test(a))return!1;var c,d,e=0,f=0,g=!1;if(a=a.replace(/\D/g,""),a.length<13||a.length>19)return!1;for(c=a.length-1;c>=0;c--)d=a.charAt(c),f=parseInt(d,10),g&&(f*=2)>9&&(f-=9),e+=f,g=!g;return e%10===0},"Please enter a valid credit card number."),a.validator.addMethod("creditcardtypes",function(a,b,c){if(/[^0-9\-]+/.test(a))return!1;a=a.replace(/\D/g,"");var d=0;return c.mastercard&&(d|=1),c.visa&&(d|=2),c.amex&&(d|=4),c.dinersclub&&(d|=8),c.enroute&&(d|=16),c.discover&&(d|=32),c.jcb&&(d|=64),c.unknown&&(d|=128),c.all&&(d=255),1&d&&(/^(5[12345])/.test(a)||/^(2[234567])/.test(a))?16===a.length:2&d&&/^(4)/.test(a)?16===a.length:4&d&&/^(3[47])/.test(a)?15===a.length:8&d&&/^(3(0[012345]|[68]))/.test(a)?14===a.length:16&d&&/^(2(014|149))/.test(a)?15===a.length:32&d&&/^(6011)/.test(a)?16===a.length:64&d&&/^(3)/.test(a)?16===a.length:64&d&&/^(2131|1800)/.test(a)?15===a.length:!!(128&d)},"Please enter a valid credit card number."),a.validator.addMethod("currency",function(a,b,c){var d,e="string"==typeof c,f=e?c:c[0],g=!!e||c[1];return f=f.replace(/,/g,""),f=g?f+"]":f+"]?",d="^["+f+"([1-9]{1}[0-9]{0,2}(\\,[0-9]{3})*(\\.[0-9]{0,2})?|[1-9]{1}[0-9]{0,}(\\.[0-9]{0,2})?|0(\\.[0-9]{0,2})?|(\\.[0-9]{1,2})?)$",d=new RegExp(d),this.optional(b)||d.test(a)},"Please specify a valid currency"),a.validator.addMethod("dateFA",function(a,b){return this.optional(b)||/^[1-4]\d{3}\/((0?[1-6]\/((3[0-1])|([1-2][0-9])|(0?[1-9])))|((1[0-2]|(0?[7-9]))\/(30|([1-2][0-9])|(0?[1-9]))))$/.test(a)},a.validator.messages.date),a.validator.addMethod("dateITA",function(a,b){var c,d,e,f,g,h=!1,i=/^\d{1,2}\/\d{1,2}\/\d{4}$/;return i.test(a)?(c=a.split("/"),d=parseInt(c[0],10),e=parseInt(c[1],10),f=parseInt(c[2],10),g=new Date(Date.UTC(f,e-1,d,12,0,0,0)),h=g.getUTCFullYear()===f&&g.getUTCMonth()===e-1&&g.getUTCDate()===d):h=!1,this.optional(b)||h},a.validator.messages.date),a.validator.addMethod("dateNL",function(a,b){return this.optional(b)||/^(0?[1-9]|[12]\d|3[01])[\.\/\-](0?[1-9]|1[012])[\.\/\-]([12]\d)?(\d\d)$/.test(a)},a.validator.messages.date),a.validator.addMethod("extension",function(a,b,c){return c="string"==typeof c?c.replace(/,/g,"|"):"png|jpe?g|gif",this.optional(b)||a.match(new RegExp("\\.("+c+")$","i"))},a.validator.format("Please enter a value with a valid extension.")),a.validator.addMethod("giroaccountNL",function(a,b){return this.optional(b)||/^[0-9]{1,7}$/.test(a)},"Please specify a valid giro account number"),a.validator.addMethod("greaterThan",function(b,c,d){var e=a(d);return this.settings.onfocusout&&e.not(".validate-greaterThan-blur").length&&e.addClass("validate-greaterThan-blur").on("blur.validate-greaterThan",function(){a(c).valid()}),b>e.val()},"Please enter a greater value."),a.validator.addMethod("greaterThanEqual",function(b,c,d){var e=a(d);return this.settings.onfocusout&&e.not(".validate-greaterThanEqual-blur").length&&e.addClass("validate-greaterThanEqual-blur").on("blur.validate-greaterThanEqual",function(){a(c).valid()}),b>=e.val()},"Please enter a greater value."),a.validator.addMethod("iban",function(a,b){if(this.optional(b))return!0;var c,d,e,f,g,h,i,j,k,l=a.replace(/ /g,"").toUpperCase(),m="",n=!0,o="",p="",q=5;if(l.length<q)return!1;if(c=l.substring(0,2),h={AL:"\\d{8}[\\dA-Z]{16}",AD:"\\d{8}[\\dA-Z]{12}",AT:"\\d{16}",AZ:"[\\dA-Z]{4}\\d{20}",BE:"\\d{12}",BH:"[A-Z]{4}[\\dA-Z]{14}",BA:"\\d{16}",BR:"\\d{23}[A-Z][\\dA-Z]",BG:"[A-Z]{4}\\d{6}[\\dA-Z]{8}",CR:"\\d{17}",HR:"\\d{17}",CY:"\\d{8}[\\dA-Z]{16}",CZ:"\\d{20}",DK:"\\d{14}",DO:"[A-Z]{4}\\d{20}",EE:"\\d{16}",FO:"\\d{14}",FI:"\\d{14}",FR:"\\d{10}[\\dA-Z]{11}\\d{2}",GE:"[\\dA-Z]{2}\\d{16}",DE:"\\d{18}",GI:"[A-Z]{4}[\\dA-Z]{15}",GR:"\\d{7}[\\dA-Z]{16}",GL:"\\d{14}",GT:"[\\dA-Z]{4}[\\dA-Z]{20}",HU:"\\d{24}",IS:"\\d{22}",IE:"[\\dA-Z]{4}\\d{14}",IL:"\\d{19}",IT:"[A-Z]\\d{10}[\\dA-Z]{12}",KZ:"\\d{3}[\\dA-Z]{13}",KW:"[A-Z]{4}[\\dA-Z]{22}",LV:"[A-Z]{4}[\\dA-Z]{13}",LB:"\\d{4}[\\dA-Z]{20}",LI:"\\d{5}[\\dA-Z]{12}",LT:"\\d{16}",LU:"\\d{3}[\\dA-Z]{13}",MK:"\\d{3}[\\dA-Z]{10}\\d{2}",MT:"[A-Z]{4}\\d{5}[\\dA-Z]{18}",MR:"\\d{23}",MU:"[A-Z]{4}\\d{19}[A-Z]{3}",MC:"\\d{10}[\\dA-Z]{11}\\d{2}",MD:"[\\dA-Z]{2}\\d{18}",ME:"\\d{18}",NL:"[A-Z]{4}\\d{10}",NO:"\\d{11}",PK:"[\\dA-Z]{4}\\d{16}",PS:"[\\dA-Z]{4}\\d{21}",PL:"\\d{24}",PT:"\\d{21}",RO:"[A-Z]{4}[\\dA-Z]{16}",SM:"[A-Z]\\d{10}[\\dA-Z]{12}",SA:"\\d{2}[\\dA-Z]{18}",RS:"\\d{18}",SK:"\\d{20}",SI:"\\d{15}",ES:"\\d{20}",SE:"\\d{20}",CH:"\\d{5}[\\dA-Z]{12}",TN:"\\d{20}",TR:"\\d{5}[\\dA-Z]{17}",AE:"\\d{3}\\d{16}",GB:"[A-Z]{4}\\d{14}",VG:"[\\dA-Z]{4}\\d{16}"},g=h[c],"undefined"!=typeof g&&(i=new RegExp("^[A-Z]{2}\\d{2}"+g+"$",""),!i.test(l)))return!1;for(d=l.substring(4,l.length)+l.substring(0,4),j=0;j<d.length;j++)e=d.charAt(j),"0"!==e&&(n=!1),n||(m+="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".indexOf(e));for(k=0;k<m.length;k++)f=m.charAt(k),p=""+o+f,o=p%97;return 1===o},"Please specify a valid IBAN"),a.validator.addMethod("integer",function(a,b){return this.optional(b)||/^-?\d+$/.test(a)},"A positive or negative non-decimal number please"),a.validator.addMethod("ipv4",function(a,b){return this.optional(b)||/^(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)$/i.test(a)},"Please enter a valid IP v4 address."),a.validator.addMethod("ipv6",function(a,b){return this.optional(b)||/^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$/i.test(a)},"Please enter a valid IP v6 address."),a.validator.addMethod("lessThan",function(b,c,d){var e=a(d);return this.settings.onfocusout&&e.not(".validate-lessThan-blur").length&&e.addClass("validate-lessThan-blur").on("blur.validate-lessThan",function(){a(c).valid()}),b<e.val()},"Please enter a lesser value."),a.validator.addMethod("lessThanEqual",function(b,c,d){var e=a(d);return this.settings.onfocusout&&e.not(".validate-lessThanEqual-blur").length&&e.addClass("validate-lessThanEqual-blur").on("blur.validate-lessThanEqual",function(){a(c).valid()}),b<=e.val()},"Please enter a lesser value."),a.validator.addMethod("lettersonly",function(a,b){return this.optional(b)||/^[a-z]+$/i.test(a)},"Letters only please"),a.validator.addMethod("letterswithbasicpunc",function(a,b){return this.optional(b)||/^[a-z\-.,()'"\s]+$/i.test(a)},"Letters or punctuation only please"),a.validator.addMethod("maxfiles",function(b,c,d){return!!this.optional(c)||!("file"===a(c).attr("type")&&c.files&&c.files.length>d)},a.validator.format("Please select no more than {0} files.")),a.validator.addMethod("maxsize",function(b,c,d){if(this.optional(c))return!0;if("file"===a(c).attr("type")&&c.files&&c.files.length)for(var e=0;e<c.files.length;e++)if(c.files[e].size>d)return!1;return!0},a.validator.format("File size must not exceed {0} bytes each.")),a.validator.addMethod("maxsizetotal",function(b,c,d){if(this.optional(c))return!0;if("file"===a(c).attr("type")&&c.files&&c.files.length)for(var e=0,f=0;f<c.files.length;f++)if(e+=c.files[f].size,e>d)return!1;return!0},a.validator.format("Total size of all files must not exceed {0} bytes.")),a.validator.addMethod("mobileNL",function(a,b){return this.optional(b)||/^((\+|00(\s|\s?\-\s?)?)31(\s|\s?\-\s?)?(\(0\)[\-\s]?)?|0)6((\s|\s?\-\s?)?[0-9]){8}$/.test(a)},"Please specify a valid mobile number"),a.validator.addMethod("mobileRU",function(a,b){var c=a.replace(/\(|\)|\s+|-/g,"");return this.optional(b)||c.length>9&&/^((\+7|7|8)+([0-9]){10})$/.test(c)},"Please specify a valid mobile number"),a.validator.addMethod("mobileUK",function(a,b){return a=a.replace(/\(|\)|\s+|-/g,""),this.optional(b)||a.length>9&&a.match(/^(?:(?:(?:00\s?|\+)44\s?|0)7(?:[1345789]\d{2}|624)\s?\d{3}\s?\d{3})$/)},"Please specify a valid mobile number"),a.validator.addMethod("netmask",function(a,b){return this.optional(b)||/^(254|252|248|240|224|192|128)\.0\.0\.0|255\.(254|252|248|240|224|192|128|0)\.0\.0|255\.255\.(254|252|248|240|224|192|128|0)\.0|255\.255\.255\.(254|252|248|240|224|192|128|0)/i.test(a)},"Please enter a valid netmask."),a.validator.addMethod("nieES",function(a,b){"use strict";if(this.optional(b))return!0;var c,d=new RegExp(/^[MXYZ]{1}[0-9]{7,8}[TRWAGMYFPDXBNJZSQVHLCKET]{1}$/gi),e="TRWAGMYFPDXBNJZSQVHLCKET",f=a.substr(a.length-1).toUpperCase();return a=a.toString().toUpperCase(),!(a.length>10||a.length<9||!d.test(a))&&(a=a.replace(/^[X]/,"0").replace(/^[Y]/,"1").replace(/^[Z]/,"2"),c=9===a.length?a.substr(0,8):a.substr(0,9),e.charAt(parseInt(c,10)%23)===f)},"Please specify a valid NIE number."),a.validator.addMethod("nifES",function(a,b){"use strict";return!!this.optional(b)||(a=a.toUpperCase(),!!a.match("((^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$|^[T]{1}[A-Z0-9]{8}$)|^[0-9]{8}[A-Z]{1}$)")&&(/^[0-9]{8}[A-Z]{1}$/.test(a)?"TRWAGMYFPDXBNJZSQVHLCKE".charAt(a.substring(8,0)%23)===a.charAt(8):!!/^[KLM]{1}/.test(a)&&a[8]==="TRWAGMYFPDXBNJZSQVHLCKE".charAt(a.substring(8,1)%23)))},"Please specify a valid NIF number."),a.validator.addMethod("nipPL",function(a){"use strict";if(a=a.replace(/[^0-9]/g,""),10!==a.length)return!1;for(var b=[6,5,7,2,3,4,5,6,7],c=0,d=0;d<9;d++)c+=b[d]*a[d];var e=c%11,f=10===e?0:e;return f===parseInt(a[9],10)},"Please specify a valid NIP number."),a.validator.addMethod("nisBR",function(a){var b,c,d,e,f,g=0;if(a=a.replace(/([~!@#$%^&*()_+=`{}\[\]\-|\\:;'<>,.\/? ])+/g,""),11!==a.length)return!1;for(c=parseInt(a.substring(10,11),10),b=parseInt(a.substring(0,10),10),e=2;e<12;e++)f=e,10===e&&(f=2),11===e&&(f=3),g+=b%10*f,b=parseInt(b/10,10);return d=g%11,d=d>1?11-d:0,c===d},"Please specify a valid NIS/PIS number"),a.validator.addMethod("notEqualTo",function(b,c,d){return this.optional(c)||!a.validator.methods.equalTo.call(this,b,c,d)},"Please enter a different value, values must not be the same."),a.validator.addMethod("nowhitespace",function(a,b){return this.optional(b)||/^\S+$/i.test(a)},"No white space please"),a.validator.addMethod("pattern",function(a,b,c){return!!this.optional(b)||("string"==typeof c&&(c=new RegExp("^(?:"+c+")$")),c.test(a))},"Invalid format."),a.validator.addMethod("phoneNL",function(a,b){return this.optional(b)||/^((\+|00(\s|\s?\-\s?)?)31(\s|\s?\-\s?)?(\(0\)[\-\s]?)?|0)[1-9]((\s|\s?\-\s?)?[0-9]){8}$/.test(a)},"Please specify a valid phone number."),a.validator.addMethod("phonePL",function(a,b){a=a.replace(/\s+/g,"");var c=/^(?:(?:(?:\+|00)?48)|(?:\(\+?48\)))?(?:1[2-8]|2[2-69]|3[2-49]|4[1-68]|5[0-9]|6[0-35-9]|[7-8][1-9]|9[145])\d{7}$/;return this.optional(b)||c.test(a)},"Please specify a valid phone number"),a.validator.addMethod("phonesUK",function(a,b){return a=a.replace(/\(|\)|\s+|-/g,""),this.optional(b)||a.length>9&&a.match(/^(?:(?:(?:00\s?|\+)44\s?|0)(?:1\d{8,9}|[23]\d{9}|7(?:[1345789]\d{8}|624\d{6})))$/)},"Please specify a valid uk phone number"),a.validator.addMethod("phoneUK",function(a,b){return a=a.replace(/\(|\)|\s+|-/g,""),this.optional(b)||a.length>9&&a.match(/^(?:(?:(?:00\s?|\+)44\s?)|(?:\(?0))(?:\d{2}\)?\s?\d{4}\s?\d{4}|\d{3}\)?\s?\d{3}\s?\d{3,4}|\d{4}\)?\s?(?:\d{5}|\d{3}\s?\d{3})|\d{5}\)?\s?\d{4,5})$/)},"Please specify a valid phone number"),a.validator.addMethod("phoneUS",function(a,b){return a=a.replace(/\s+/g,""),this.optional(b)||a.length>9&&a.match(/^(\+?1-?)?(\([2-9]([02-9]\d|1[02-9])\)|[2-9]([02-9]\d|1[02-9]))-?[2-9]\d{2}-?\d{4}$/)},"Please specify a valid phone number"),a.validator.addMethod("postalcodeBR",function(a,b){return this.optional(b)||/^\d{2}.\d{3}-\d{3}?$|^\d{5}-?\d{3}?$/.test(a)},"Informe um CEP válido."),a.validator.addMethod("postalCodeCA",function(a,b){return this.optional(b)||/^[ABCEGHJKLMNPRSTVXY]\d[ABCEGHJKLMNPRSTVWXYZ] *\d[ABCEGHJKLMNPRSTVWXYZ]\d$/i.test(a)},"Please specify a valid postal code"),a.validator.addMethod("postalcodeIT",function(a,b){return this.optional(b)||/^\d{5}$/.test(a)},"Please specify a valid postal code"),a.validator.addMethod("postalcodeNL",function(a,b){return this.optional(b)||/^[1-9][0-9]{3}\s?[a-zA-Z]{2}$/.test(a)},"Please specify a valid postal code"),a.validator.addMethod("postcodeUK",function(a,b){return this.optional(b)||/^((([A-PR-UWYZ][0-9])|([A-PR-UWYZ][0-9][0-9])|([A-PR-UWYZ][A-HK-Y][0-9])|([A-PR-UWYZ][A-HK-Y][0-9][0-9])|([A-PR-UWYZ][0-9][A-HJKSTUW])|([A-PR-UWYZ][A-HK-Y][0-9][ABEHMNPRVWXY]))\s?([0-9][ABD-HJLNP-UW-Z]{2})|(GIR)\s?(0AA))$/i.test(a)},"Please specify a valid UK postcode"),a.validator.addMethod("require_from_group",function(b,c,d){var e=a(d[1],c.form),f=e.eq(0),g=f.data("valid_req_grp")?f.data("valid_req_grp"):a.extend({},this),h=e.filter(function(){return g.elementValue(this)}).length>=d[0];return f.data("valid_req_grp",g),a(c).data("being_validated")||(e.data("being_validated",!0),e.each(function(){g.element(this)}),e.data("being_validated",!1)),h},a.validator.format("Please fill at least {0} of these fields.")),a.validator.addMethod("skip_or_fill_minimum",function(b,c,d){var e=a(d[1],c.form),f=e.eq(0),g=f.data("valid_skip")?f.data("valid_skip"):a.extend({},this),h=e.filter(function(){return g.elementValue(this)}).length,i=0===h||h>=d[0];return f.data("valid_skip",g),a(c).data("being_validated")||(e.data("being_validated",!0),e.each(function(){g.element(this)}),e.data("being_validated",!1)),i},a.validator.format("Please either skip these fields or fill at least {0} of them.")),a.validator.addMethod("stateUS",function(a,b,c){var d,e="undefined"==typeof c,f=!e&&"undefined"!=typeof c.caseSensitive&&c.caseSensitive,g=!e&&"undefined"!=typeof c.includeTerritories&&c.includeTerritories,h=!e&&"undefined"!=typeof c.includeMilitary&&c.includeMilitary;return d=g||h?g&&h?"^(A[AEKLPRSZ]|C[AOT]|D[CE]|FL|G[AU]|HI|I[ADLN]|K[SY]|LA|M[ADEINOPST]|N[CDEHJMVY]|O[HKR]|P[AR]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY])$":g?"^(A[KLRSZ]|C[AOT]|D[CE]|FL|G[AU]|HI|I[ADLN]|K[SY]|LA|M[ADEINOPST]|N[CDEHJMVY]|O[HKR]|P[AR]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY])$":"^(A[AEKLPRZ]|C[AOT]|D[CE]|FL|GA|HI|I[ADLN]|K[SY]|LA|M[ADEINOST]|N[CDEHJMVY]|O[HKR]|PA|RI|S[CD]|T[NX]|UT|V[AT]|W[AIVY])$":"^(A[KLRZ]|C[AOT]|D[CE]|FL|GA|HI|I[ADLN]|K[SY]|LA|M[ADEINOST]|N[CDEHJMVY]|O[HKR]|PA|RI|S[CD]|T[NX]|UT|V[AT]|W[AIVY])$",d=f?new RegExp(d):new RegExp(d,"i"),this.optional(b)||d.test(a)},"Please specify a valid state"),a.validator.addMethod("strippedminlength",function(b,c,d){return a(b).text().length>=d},a.validator.format("Please enter at least {0} characters")),a.validator.addMethod("time",function(a,b){return this.optional(b)||/^([01]\d|2[0-3]|[0-9])(:[0-5]\d){1,2}$/.test(a)},"Please enter a valid time, between 00:00 and 23:59"),a.validator.addMethod("time12h",function(a,b){return this.optional(b)||/^((0?[1-9]|1[012])(:[0-5]\d){1,2}(\ ?[AP]M))$/i.test(a)},"Please enter a valid time in 12-hour am/pm format"),a.validator.addMethod("url2",function(a,b){return this.optional(b)||/^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)*(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(a)},a.validator.messages.url),a.validator.addMethod("vinUS",function(a){if(17!==a.length)return!1;var b,c,d,e,f,g,h=["A","B","C","D","E","F","G","H","J","K","L","M","N","P","R","S","T","U","V","W","X","Y","Z"],i=[1,2,3,4,5,6,7,8,1,2,3,4,5,7,9,2,3,4,5,6,7,8,9],j=[8,7,6,5,4,3,2,10,0,9,8,7,6,5,4,3,2],k=0;for(b=0;b<17;b++){if(e=j[b],d=a.slice(b,b+1),8===b&&(g=d),isNaN(d)){for(c=0;c<h.length;c++)if(d.toUpperCase()===h[c]){d=i[c],d*=e,isNaN(g)&&8===c&&(g=h[c]);break}}else d*=e;k+=d}return f=k%11,10===f&&(f="X"),f===g},"The specified vehicle identification number (VIN) is invalid."),a.validator.addMethod("zipcodeUS",function(a,b){return this.optional(b)||/^\d{5}(-\d{4})?$/.test(a)},"The specified US ZIP Code is invalid"),a.validator.addMethod("ziprange",function(a,b){return this.optional(b)||/^90[2-5]\d\{2\}-\d{4}$/.test(a)},"Your ZIP-code must be in the range 902xx-xxxx to 905xx-xxxx"),a});
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/validate/jquery.validate.extend.js b/ruoyi-admin/src/main/resources/static/ajax/libs/validate/jquery.validate.extend.js
new file mode 100644
index 0000000..dfd7168
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/validate/jquery.validate.extend.js
@@ -0,0 +1,189 @@
+/*this is basic form validation using for validation person's basic information author:Clara Guo data:2017/07/20*/
+$(document).ready(function(){
+	$.validator.setDefaults({       
+		submitHandler: function(form) {    
+			form.submit();    
+		}       
+	});
+	// 非法字符验证
+	jQuery.validator.addMethod("specialSign",function(value,element) {
+		var char = /^[^<>"'|\\]+$/;
+		return this.optional(element) || (char.test(value));
+	},"不能包含非法字符:< > \" ' \\\ |");
+	// 手机号码验证身份证正则合并:(^\d{15}$)|(^\d{17}([0-9]|X)$)
+	jQuery.validator.addMethod("isPhone",function(value,element) {
+		var length = value.length;
+		var phone = /^1[3-9]\d{9}$/;
+		return this.optional(element)||(length == 11 && phone.test(value));
+	},"请填写正确的11位手机号");
+	// 电话号码验证
+	jQuery.validator.addMethod("isTel",function(value,element) {
+		var tel = /^(0\d{2,3}-)?\d{7,8}$/g;//区号3,4位,号码7,8位
+		return this.optional(element) || (tel.test(value));
+	},"请填写正确的座机号码");
+	// 姓名校验
+	jQuery.validator.addMethod("isName",function(value,element) {
+		var name = /^[\u4e00-\u9fa5]{2,6}$/;
+		return this.optional(element) || (name.test(value));
+	},"姓名只能用汉字,长度2-4位");
+	// 校验用户名
+	jQuery.validator.addMethod("isUserName",function(value,element) {
+		var userName = /^[a-zA-Z0-9]{2,13}$/;
+		return this.optional(element) || (userName).test(value);
+	},'请输入数字或者字母,不包含特殊字符');
+	// 校验身份证
+	jQuery.validator.addMethod("isIdentity",function(value,element) {
+		var id = /^(\d{15}$|^\d{18}$|^\d{17}(\d|X))$/;
+		return this.optional(element) || (id.test(value));
+	},"请输入正确的15或18位身份证号,末尾若为X请大写");
+	// 校验二代身份证
+	jQuery.validator.addMethod("isIdentity18",function(value,element) {
+		var id = /^(^\d{17}(\d|X))$/;
+		return this.optional(element) || (id.test(value));
+	},"请输入正确的18位身份证号,末尾若为X请大写");
+	// 校验出生日期
+	jQuery.validator.addMethod("isBirth",function(value,element) {
+		var birth = /^(19|20)\d{2}-(1[0-2]|0?[1-9])-(0?[1-9]|[1-2][0-9]|3[0-1])$/;
+		return this.optional(element) || (birth).test(value);
+	},"出生日期格式示例2000-01-01");
+	// 校验IP地址
+	jQuery.validator.addMethod("isIp",function(value,element) {
+		var ip = /^(?:(?:2[0-4][0-9]\.)|(?:25[0-5]\.)|(?:1[0-9][0-9]\.)|(?:[1-9][0-9]\.)|(?:[0-9]\.)){3}(?:(?:2[0-4][0-9])|(?:25[0-5])|(?:1[0-9][0-9])|(?:[1-9][0-9])|(?:[0-9]))$/;
+		return this.optional(element) || (ip).test(value);
+	},"IP地址格式示例127.0.0.1");
+	jQuery.validator.addMethod("notEqual", function(value, element, param) {
+        return value != param;
+    }, $.validator.format("输入值不允许为{0}"));
+	jQuery.validator.addMethod("gt", function(value, element, param) {
+        return value > param;
+    }, $.validator.format("输入值必须大于{0}"));
+	// 校验新旧密码是否相同
+	jQuery.validator.addMethod("isdiff",function(){
+		var p1=$("#pwdOld").val();
+		var p2=$("#pwdNew").val();
+		if(p1==p2){
+			return false;
+		}else{
+			 return true;
+		}
+		});
+	// 校验新密码和确认密码是否相同
+	jQuery.validator.addMethod("issame",function(){
+		var p3=$("#confirm_password").val();
+		var p4=$("#pwdNew").val();
+		if(p3==p4){
+			return true;
+		}else{
+			 return false;
+		}
+		});
+	// 校验基础信息表单
+	$("#basicInfoForm").validate({
+		errorElement:'span',
+		errorClass:'help-block error-mes',
+		rules:{
+			name:{
+				required:true,
+				isName:true
+			},
+			sex:"required",
+			birth:"required",
+            mobile:{
+				required:true,
+				isPhone:true
+			},
+			email:{
+				required:true,
+				email:true
+			}
+		},
+		messages:{
+			name:{
+				required:"请输入中文姓名",
+				isName:"姓名只能为汉字"
+			},
+			sex:{
+				required:"请输入性别"
+			},
+			birth:{
+				required:"请输入出生年月"
+			},
+            mobile:{
+				required:"请输入手机号",
+				isPhone:"请填写正确的11位手机号"
+			},
+			email:{
+				required:"请输入邮箱",
+				email:"请填写正确的邮箱格式"
+			}
+		},
+	
+		errorPlacement:function(error,element){
+			element.next().remove();
+			element.closest('.gg-formGroup').append(error);
+		},
+		
+		highlight:function(element){
+			$(element).closest('.gg-formGroup').addClass('has-error has-feedback');
+		},
+		success:function(label){
+			var el = label.closest('.gg-formGroup').find("input");
+			el.next().remove();
+			label.closest('.gg-formGroup').removeClass('has-error').addClass("has-feedback has-success");
+			label.remove();
+		},
+		submitHandler:function(form){
+			alert("保存成功!");
+		}
+	});
+	
+	// 校验修改密码表单
+	$("#modifyPwd").validate({
+		onfocusout: function(element) { $(element).valid()},
+		 debug:false,   // 表示校验通过后是否直接提交表单
+		 onkeyup:false, // 表示按键松开时候监听验证
+		rules:{
+			pwdOld:{
+				required:true,
+				minlength:6
+			},
+            pwdNew:{
+			   required:true,
+			   minlength:6,
+			   isdiff:true,
+			   //issame:true,
+		   },
+			confirm_password:{
+			  required:true,
+			  minlength:6,
+			  issame:true,
+			}
+		  
+		   },
+		messages:{
+			 	pwdOld : {
+					 required:'必填',
+					 minlength:$.validator.format('密码长度要大于6')
+				},
+            	pwdNew:{
+				   required:'必填',
+				   minlength:$.validator.format('密码长度要大于6'),
+				   isdiff:'原密码与新密码不能重复',
+				  
+			   },
+				confirm_password:{
+				   required:'必填',
+				   minlength:$.validator.format('密码长度要大于6'),
+				   issame:'新密码要与确认新密码一致',
+				}
+		
+		},
+		errorElement:"mes",
+		errorClass:"gg-star",
+		errorPlacement: function(error, element) 
+		{ 
+			element.closest('.gg-formGroup').append(error);
+
+		}
+	});
+});
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/validate/jquery.validate.min.js b/ruoyi-admin/src/main/resources/static/ajax/libs/validate/jquery.validate.min.js
new file mode 100644
index 0000000..6f6064e
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/validate/jquery.validate.min.js
@@ -0,0 +1,4 @@
+/*! jQuery Validation Plugin - v1.21.0 - 7/17/2024
+ * https://jqueryvalidation.org/
+ * Copyright (c) 2024 Jörn Zaefferer; Licensed MIT */
+!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof module&&module.exports?module.exports=a(require("jquery")):a(jQuery)}(function(a){a.extend(a.fn,{validate:function(b){if(!this.length)return void(b&&b.debug&&window.console&&console.warn("Nothing selected, can't validate, returning nothing."));var c=a.data(this[0],"validator");return c?c:(this.attr("novalidate","novalidate"),c=new a.validator(b,this[0]),a.data(this[0],"validator",c),c.settings.onsubmit&&(this.on("click.validate",":submit",function(b){c.submitButton=b.currentTarget,a(this).hasClass("cancel")&&(c.cancelSubmit=!0),void 0!==a(this).attr("formnovalidate")&&(c.cancelSubmit=!0)}),this.on("submit.validate",function(b){function d(){var d,e;return c.submitButton&&(c.settings.submitHandler||c.formSubmitted)&&(d=a("<input type='hidden'/>").attr("name",c.submitButton.name).val(a(c.submitButton).val()).appendTo(c.currentForm)),!(c.settings.submitHandler&&!c.settings.debug)||(e=c.settings.submitHandler.call(c,c.currentForm,b),d&&d.remove(),void 0!==e&&e)}return c.settings.debug&&b.preventDefault(),c.cancelSubmit?(c.cancelSubmit=!1,d()):c.form()?c.pendingRequest?(c.formSubmitted=!0,!1):d():(c.focusInvalid(),!1)})),c)},valid:function(){var b,c,d;return a(this[0]).is("form")?b=this.validate().form():(d=[],b=!0,c=a(this[0].form).validate(),this.each(function(){b=c.element(this)&&b,b||(d=d.concat(c.errorList))}),c.errorList=d),b},rules:function(b,c){var d,e,f,g,h,i,j=this[0],k="undefined"!=typeof this.attr("contenteditable")&&"false"!==this.attr("contenteditable");if(null!=j&&(!j.form&&k&&(j.form=this.closest("form")[0],j.name=this.attr("name")),null!=j.form)){if(b)switch(d=a.data(j.form,"validator").settings,e=d.rules,f=a.validator.staticRules(j),b){case"add":a.extend(f,a.validator.normalizeRule(c)),delete f.messages,e[j.name]=f,c.messages&&(d.messages[j.name]=a.extend(d.messages[j.name],c.messages));break;case"remove":return c?(i={},a.each(c.split(/\s/),function(a,b){i[b]=f[b],delete f[b]}),i):(delete e[j.name],f)}return g=a.validator.normalizeRules(a.extend({},a.validator.classRules(j),a.validator.attributeRules(j),a.validator.dataRules(j),a.validator.staticRules(j)),j),g.required&&(h=g.required,delete g.required,g=a.extend({required:h},g)),g.remote&&(h=g.remote,delete g.remote,g=a.extend(g,{remote:h})),g}}});var b=function(a){return a.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"")};a.extend(a.expr.pseudos||a.expr[":"],{blank:function(c){return!b(""+a(c).val())},filled:function(c){var d=a(c).val();return null!==d&&!!b(""+d)},unchecked:function(b){return!a(b).prop("checked")}}),a.validator=function(b,c){this.settings=a.extend(!0,{},a.validator.defaults,b),this.currentForm=c,this.init()},a.validator.format=function(b,c){return 1===arguments.length?function(){var c=a.makeArray(arguments);return c.unshift(b),a.validator.format.apply(this,c)}:void 0===c?b:(arguments.length>2&&c.constructor!==Array&&(c=a.makeArray(arguments).slice(1)),c.constructor!==Array&&(c=[c]),a.each(c,function(a,c){b=b.replace(new RegExp("\\{"+a+"\\}","g"),function(){return c})}),b)},a.extend(a.validator,{defaults:{messages:{},groups:{},rules:{},errorClass:"error",pendingClass:"pending",validClass:"valid",errorElement:"label",focusCleanup:!1,focusInvalid:!0,errorContainer:a([]),errorLabelContainer:a([]),onsubmit:!0,ignore:":hidden",ignoreTitle:!1,customElements:[],onfocusin:function(a){this.lastActive=a,this.settings.focusCleanup&&(this.settings.unhighlight&&this.settings.unhighlight.call(this,a,this.settings.errorClass,this.settings.validClass),this.hideThese(this.errorsFor(a)))},onfocusout:function(a){this.checkable(a)||!(a.name in this.submitted)&&this.optional(a)||this.element(a)},onkeyup:function(b,c){var d=[16,17,18,20,35,36,37,38,39,40,45,144,225];9===c.which&&""===this.elementValue(b)||a.inArray(c.keyCode,d)!==-1||(b.name in this.submitted||b.name in this.invalid)&&this.element(b)},onclick:function(a){a.name in this.submitted?this.element(a):a.parentNode.name in this.submitted&&this.element(a.parentNode)},highlight:function(b,c,d){"radio"===b.type?this.findByName(b.name).addClass(c).removeClass(d):a(b).addClass(c).removeClass(d)},unhighlight:function(b,c,d){"radio"===b.type?this.findByName(b.name).removeClass(c).addClass(d):a(b).removeClass(c).addClass(d)}},setDefaults:function(b){a.extend(a.validator.defaults,b)},messages:{required:"This field is required.",remote:"Please fix this field.",email:"Please enter a valid email address.",url:"Please enter a valid URL.",date:"Please enter a valid date.",dateISO:"Please enter a valid date (ISO).",number:"Please enter a valid number.",digits:"Please enter only digits.",equalTo:"Please enter the same value again.",maxlength:a.validator.format("Please enter no more than {0} characters."),minlength:a.validator.format("Please enter at least {0} characters."),rangelength:a.validator.format("Please enter a value between {0} and {1} characters long."),range:a.validator.format("Please enter a value between {0} and {1}."),max:a.validator.format("Please enter a value less than or equal to {0}."),min:a.validator.format("Please enter a value greater than or equal to {0}."),step:a.validator.format("Please enter a multiple of {0}.")},autoCreateRanges:!1,prototype:{init:function(){function b(b){var c="undefined"!=typeof a(this).attr("contenteditable")&&"false"!==a(this).attr("contenteditable");if(!this.form&&c&&(this.form=a(this).closest("form")[0],this.name=a(this).attr("name")),d===this.form){var e=a.data(this.form,"validator"),f="on"+b.type.replace(/^validate/,""),g=e.settings;g[f]&&!a(this).is(g.ignore)&&g[f].call(e,this,b)}}this.labelContainer=a(this.settings.errorLabelContainer),this.errorContext=this.labelContainer.length&&this.labelContainer||a(this.currentForm),this.containers=a(this.settings.errorContainer).add(this.settings.errorLabelContainer),this.submitted={},this.valueCache={},this.pendingRequest=0,this.pending={},this.invalid={},this.reset();var c,d=this.currentForm,e=this.groups={};a.each(this.settings.groups,function(b,c){"string"==typeof c&&(c=c.split(/\s/)),a.each(c,function(a,c){e[c]=b})}),c=this.settings.rules,a.each(c,function(b,d){c[b]=a.validator.normalizeRule(d)});var f=[":text","[type='password']","[type='file']","select","textarea","[type='number']","[type='search']","[type='tel']","[type='url']","[type='email']","[type='datetime']","[type='date']","[type='month']","[type='week']","[type='time']","[type='datetime-local']","[type='range']","[type='color']","[type='radio']","[type='checkbox']","[contenteditable]","[type='button']"],g=["select","option","[type='radio']","[type='checkbox']"];a(this.currentForm).on("focusin.validate focusout.validate keyup.validate",f.concat(this.settings.customElements).join(", "),b).on("click.validate",g.concat(this.settings.customElements).join(", "),b),this.settings.invalidHandler&&a(this.currentForm).on("invalid-form.validate",this.settings.invalidHandler)},form:function(){return this.checkForm(),a.extend(this.submitted,this.errorMap),this.invalid=a.extend({},this.errorMap),this.valid()||a(this.currentForm).triggerHandler("invalid-form",[this]),this.showErrors(),this.valid()},checkForm:function(){this.prepareForm();for(var a=0,b=this.currentElements=this.elements();b[a];a++)this.check(b[a]);return this.valid()},element:function(b){var c,d,e=this.clean(b),f=this.validationTargetFor(e),g=this,h=!0;return void 0===f?delete this.invalid[e.name]:(this.prepareElement(f),this.currentElements=a(f),d=this.groups[f.name],d&&a.each(this.groups,function(a,b){b===d&&a!==f.name&&(e=g.validationTargetFor(g.clean(g.findByName(a))),e&&e.name in g.invalid&&(g.currentElements.push(e),h=g.check(e)&&h))}),c=this.check(f)!==!1,h=h&&c,c?this.invalid[f.name]=!1:this.invalid[f.name]=!0,this.numberOfInvalids()||(this.toHide=this.toHide.add(this.containers)),this.showErrors(),a(b).attr("aria-invalid",!c)),h},showErrors:function(b){if(b){var c=this;a.extend(this.errorMap,b),this.errorList=a.map(this.errorMap,function(a,b){return{message:a,element:c.findByName(b)[0]}}),this.successList=a.grep(this.successList,function(a){return!(a.name in b)})}this.settings.showErrors?this.settings.showErrors.call(this,this.errorMap,this.errorList):this.defaultShowErrors()},resetForm:function(){a.fn.resetForm&&a(this.currentForm).resetForm(),this.invalid={},this.submitted={},this.prepareForm(),this.hideErrors();var b=this.elements().removeData("previousValue").removeAttr("aria-invalid");this.resetElements(b)},resetElements:function(a){var b;if(this.settings.unhighlight)for(b=0;a[b];b++)this.settings.unhighlight.call(this,a[b],this.settings.errorClass,""),this.findByName(a[b].name).removeClass(this.settings.validClass);else a.removeClass(this.settings.errorClass).removeClass(this.settings.validClass)},numberOfInvalids:function(){return this.objectLength(this.invalid)},objectLength:function(a){var b,c=0;for(b in a)void 0!==a[b]&&null!==a[b]&&a[b]!==!1&&c++;return c},hideErrors:function(){this.hideThese(this.toHide)},hideThese:function(a){a.not(this.containers).text(""),this.addWrapper(a).hide()},valid:function(){return 0===this.size()},size:function(){return this.errorList.length},focusInvalid:function(){if(this.settings.focusInvalid)try{a(this.findLastActive()||this.errorList.length&&this.errorList[0].element||[]).filter(":visible").trigger("focus").trigger("focusin")}catch(b){}},findLastActive:function(){var b=this.lastActive;return b&&1===a.grep(this.errorList,function(a){return a.element.name===b.name}).length&&b},elements:function(){var b=this,c={},d=["input","select","textarea","[contenteditable]"];return a(this.currentForm).find(d.concat(this.settings.customElements).join(", ")).not(":submit, :reset, :image, :disabled").not(this.settings.ignore).filter(function(){var d=this.name||a(this).attr("name"),e="undefined"!=typeof a(this).attr("contenteditable")&&"false"!==a(this).attr("contenteditable");return!d&&b.settings.debug&&window.console&&console.error("%o has no name assigned",this),e&&(this.form=a(this).closest("form")[0],this.name=d),this.form===b.currentForm&&(!(d in c||!b.objectLength(a(this).rules()))&&(c[d]=!0,!0))})},clean:function(b){return a(b)[0]},errors:function(){var b=this.settings.errorClass.split(" ").join(".");return a(this.settings.errorElement+"."+b,this.errorContext)},resetInternals:function(){this.successList=[],this.errorList=[],this.errorMap={},this.toShow=a([]),this.toHide=a([])},reset:function(){this.resetInternals(),this.currentElements=a([])},prepareForm:function(){this.reset(),this.toHide=this.errors().add(this.containers)},prepareElement:function(a){this.reset(),this.toHide=this.errorsFor(a)},elementValue:function(b){var c,d,e=a(b),f=b.type,g="undefined"!=typeof e.attr("contenteditable")&&"false"!==e.attr("contenteditable");return"radio"===f||"checkbox"===f?this.findByName(b.name).filter(":checked").val():"number"===f&&"undefined"!=typeof b.validity?b.validity.badInput?"NaN":e.val():(c=g?e.text():e.val(),"file"===f?"C:\\fakepath\\"===c.substr(0,12)?c.substr(12):(d=c.lastIndexOf("/"),d>=0?c.substr(d+1):(d=c.lastIndexOf("\\"),d>=0?c.substr(d+1):c)):"string"==typeof c?c.replace(/\r/g,""):c)},check:function(b){b=this.validationTargetFor(this.clean(b));var c,d,e,f,g=a(b).rules(),h=a.map(g,function(a,b){return b}).length,i=!1,j=this.elementValue(b);this.abortRequest(b),"function"==typeof g.normalizer?f=g.normalizer:"function"==typeof this.settings.normalizer&&(f=this.settings.normalizer),f&&(j=f.call(b,j),delete g.normalizer);for(d in g){e={method:d,parameters:g[d]};try{if(c=a.validator.methods[d].call(this,j,b,e.parameters),"dependency-mismatch"===c&&1===h){i=!0;continue}if(i=!1,"pending"===c)return void(this.toHide=this.toHide.not(this.errorsFor(b)));if(!c)return this.formatAndAdd(b,e),!1}catch(k){throw this.settings.debug&&window.console&&console.log("Exception occurred when checking element "+b.id+", check the '"+e.method+"' method.",k),k instanceof TypeError&&(k.message+=".  Exception occurred when checking element "+b.id+", check the '"+e.method+"' method."),k}}if(!i)return this.objectLength(g)&&this.successList.push(b),!0},customDataMessage:function(b,c){return a(b).data("msg"+c.charAt(0).toUpperCase()+c.substring(1).toLowerCase())||a(b).data("msg")},customMessage:function(a,b){var c=this.settings.messages[a];return c&&(c.constructor===String?c:c[b])},findDefined:function(){for(var a=0;a<arguments.length;a++)if(void 0!==arguments[a])return arguments[a]},defaultMessage:function(b,c){"string"==typeof c&&(c={method:c});var d=this.findDefined(this.customMessage(b.name,c.method),this.customDataMessage(b,c.method),!this.settings.ignoreTitle&&b.title||void 0,a.validator.messages[c.method],"<strong>Warning: No message defined for "+b.name+"</strong>"),e=/\$?\{(\d+)\}/g;return"function"==typeof d?d=d.call(this,c.parameters,b):e.test(d)&&(d=a.validator.format(d.replace(e,"{$1}"),c.parameters)),d},formatAndAdd:function(a,b){var c=this.defaultMessage(a,b);this.errorList.push({message:c,element:a,method:b.method}),this.errorMap[a.name]=c,this.submitted[a.name]=c},addWrapper:function(a){return this.settings.wrapper&&(a=a.add(a.parent(this.settings.wrapper))),a},defaultShowErrors:function(){var a,b,c;for(a=0;this.errorList[a];a++)c=this.errorList[a],this.settings.highlight&&this.settings.highlight.call(this,c.element,this.settings.errorClass,this.settings.validClass),this.showLabel(c.element,c.message);if(this.errorList.length&&(this.toShow=this.toShow.add(this.containers)),this.settings.success)for(a=0;this.successList[a];a++)this.showLabel(this.successList[a]);if(this.settings.unhighlight)for(a=0,b=this.validElements();b[a];a++)this.settings.unhighlight.call(this,b[a],this.settings.errorClass,this.settings.validClass);this.toHide=this.toHide.not(this.toShow),this.hideErrors(),this.addWrapper(this.toShow).show()},validElements:function(){return this.currentElements.not(this.invalidElements())},invalidElements:function(){return a(this.errorList).map(function(){return this.element})},showLabel:function(b,c){var d,e,f,g,h=this.errorsFor(b),i=this.idOrName(b),j=a(b).attr("aria-describedby");h.length?(h.removeClass(this.settings.validClass).addClass(this.settings.errorClass),this.settings&&this.settings.escapeHtml?h.text(c||""):h.html(c||"")):(h=a("<"+this.settings.errorElement+">").attr("id",i+"-error").addClass(this.settings.errorClass),this.settings&&this.settings.escapeHtml?h.text(c||""):h.html(c||""),d=h,this.settings.wrapper&&(d=h.hide().show().wrap("<"+this.settings.wrapper+"/>").parent()),this.labelContainer.length?this.labelContainer.append(d):this.settings.errorPlacement?this.settings.errorPlacement.call(this,d,a(b)):d.insertAfter(b),h.is("label")?h.attr("for",i):0===h.parents("label[for='"+this.escapeCssMeta(i)+"']").length&&(f=h.attr("id"),j?j.match(new RegExp("\\b"+this.escapeCssMeta(f)+"\\b"))||(j+=" "+f):j=f,a(b).attr("aria-describedby",j),e=this.groups[b.name],e&&(g=this,a.each(g.groups,function(b,c){c===e&&a("[name='"+g.escapeCssMeta(b)+"']",g.currentForm).attr("aria-describedby",h.attr("id"))})))),!c&&this.settings.success&&(h.text(""),"string"==typeof this.settings.success?h.addClass(this.settings.success):this.settings.success(h,b)),this.toShow=this.toShow.add(h)},errorsFor:function(b){var c=this.escapeCssMeta(this.idOrName(b)),d=a(b).attr("aria-describedby"),e="label[for='"+c+"'], label[for='"+c+"'] *";return d&&(e=e+", #"+this.escapeCssMeta(d).replace(/\s+/g,", #")),this.errors().filter(e)},escapeCssMeta:function(a){return void 0===a?"":a.replace(/([\\!"#$%&'()*+,./:;<=>?@\[\]^`{|}~])/g,"\\$1")},idOrName:function(a){return this.groups[a.name]||(this.checkable(a)?a.name:a.id||a.name)},validationTargetFor:function(b){return this.checkable(b)&&(b=this.findByName(b.name)),a(b).not(this.settings.ignore)[0]},checkable:function(a){return/radio|checkbox/i.test(a.type)},findByName:function(b){return a(this.currentForm).find("[name='"+this.escapeCssMeta(b)+"']")},getLength:function(b,c){switch(c.nodeName.toLowerCase()){case"select":return a("option:selected",c).length;case"input":if(this.checkable(c))return this.findByName(c.name).filter(":checked").length}return b.length},depend:function(a,b){return!this.dependTypes[typeof a]||this.dependTypes[typeof a](a,b)},dependTypes:{"boolean":function(a){return a},string:function(b,c){return!!a(b,c.form).length},"function":function(a,b){return a(b)}},optional:function(b){var c=this.elementValue(b);return!a.validator.methods.required.call(this,c,b)&&"dependency-mismatch"},elementAjaxPort:function(a){return"validate"+a.name},startRequest:function(b){this.pending[b.name]||(this.pendingRequest++,a(b).addClass(this.settings.pendingClass),this.pending[b.name]=!0)},stopRequest:function(b,c){this.pendingRequest--,this.pendingRequest<0&&(this.pendingRequest=0),delete this.pending[b.name],a(b).removeClass(this.settings.pendingClass),c&&0===this.pendingRequest&&this.formSubmitted&&this.form()&&0===this.pendingRequest?(a(this.currentForm).trigger("submit"),this.submitButton&&a("input:hidden[name='"+this.submitButton.name+"']",this.currentForm).remove(),this.formSubmitted=!1):!c&&0===this.pendingRequest&&this.formSubmitted&&(a(this.currentForm).triggerHandler("invalid-form",[this]),this.formSubmitted=!1)},abortRequest:function(b){var c;this.pending[b.name]&&(c=this.elementAjaxPort(b),a.ajaxAbort(c),this.pendingRequest--,this.pendingRequest<0&&(this.pendingRequest=0),delete this.pending[b.name],a(b).removeClass(this.settings.pendingClass))},previousValue:function(b,c){return c="string"==typeof c&&c||"remote",a.data(b,"previousValue")||a.data(b,"previousValue",{old:null,valid:!0,message:this.defaultMessage(b,{method:c})})},destroy:function(){this.resetForm(),a(this.currentForm).off(".validate").removeData("validator").find(".validate-equalTo-blur").off(".validate-equalTo").removeClass("validate-equalTo-blur").find(".validate-lessThan-blur").off(".validate-lessThan").removeClass("validate-lessThan-blur").find(".validate-lessThanEqual-blur").off(".validate-lessThanEqual").removeClass("validate-lessThanEqual-blur").find(".validate-greaterThanEqual-blur").off(".validate-greaterThanEqual").removeClass("validate-greaterThanEqual-blur").find(".validate-greaterThan-blur").off(".validate-greaterThan").removeClass("validate-greaterThan-blur")}},classRuleSettings:{required:{required:!0},email:{email:!0},url:{url:!0},date:{date:!0},dateISO:{dateISO:!0},number:{number:!0},digits:{digits:!0},creditcard:{creditcard:!0}},addClassRules:function(b,c){b.constructor===String?this.classRuleSettings[b]=c:a.extend(this.classRuleSettings,b)},classRules:function(b){var c={},d=a(b).attr("class");return d&&a.each(d.split(" "),function(){this in a.validator.classRuleSettings&&a.extend(c,a.validator.classRuleSettings[this])}),c},normalizeAttributeRule:function(a,b,c,d){/min|max|step/.test(c)&&(null===b||/number|range|text/.test(b))&&(d=Number(d),isNaN(d)&&(d=void 0)),d||0===d?a[c]=d:b===c&&"range"!==b&&(a["date"===b?"dateISO":c]=!0)},attributeRules:function(b){var c,d,e={},f=a(b),g=b.getAttribute("type");for(c in a.validator.methods)"required"===c?(d=b.getAttribute(c),""===d&&(d=!0),d=!!d):d=f.attr(c),this.normalizeAttributeRule(e,g,c,d);return e.maxlength&&/-1|2147483647|524288/.test(e.maxlength)&&delete e.maxlength,e},dataRules:function(b){var c,d,e={},f=a(b),g=b.getAttribute("type");for(c in a.validator.methods)d=f.data("rule"+c.charAt(0).toUpperCase()+c.substring(1).toLowerCase()),""===d&&(d=!0),this.normalizeAttributeRule(e,g,c,d);return e},staticRules:function(b){var c={},d=a.data(b.form,"validator");return d.settings.rules&&(c=a.validator.normalizeRule(d.settings.rules[b.name])||{}),c},normalizeRules:function(b,c){return a.each(b,function(d,e){if(e===!1)return void delete b[d];if(e.param||e.depends){var f=!0;switch(typeof e.depends){case"string":f=!!a(e.depends,c.form).length;break;case"function":f=e.depends.call(c,c)}f?b[d]=void 0===e.param||e.param:(a.data(c.form,"validator").resetElements(a(c)),delete b[d])}}),a.each(b,function(a,d){b[a]="function"==typeof d&&"normalizer"!==a?d(c):d}),a.each(["minlength","maxlength"],function(){b[this]&&(b[this]=Number(b[this]))}),a.each(["rangelength","range"],function(){var a;b[this]&&(Array.isArray(b[this])?b[this]=[Number(b[this][0]),Number(b[this][1])]:"string"==typeof b[this]&&(a=b[this].replace(/[\[\]]/g,"").split(/[\s,]+/),b[this]=[Number(a[0]),Number(a[1])]))}),a.validator.autoCreateRanges&&(null!=b.min&&null!=b.max&&(b.range=[b.min,b.max],delete b.min,delete b.max),null!=b.minlength&&null!=b.maxlength&&(b.rangelength=[b.minlength,b.maxlength],delete b.minlength,delete b.maxlength)),b},normalizeRule:function(b){if("string"==typeof b){var c={};a.each(b.split(/\s/),function(){c[this]=!0}),b=c}return b},addMethod:function(b,c,d){a.validator.methods[b]=c,a.validator.messages[b]=void 0!==d?d:a.validator.messages[b],c.length<3&&a.validator.addClassRules(b,a.validator.normalizeRule(b))},methods:{required:function(b,c,d){if(!this.depend(d,c))return"dependency-mismatch";if("select"===c.nodeName.toLowerCase()){var e=a(c).val();return e&&e.length>0}return this.checkable(c)?this.getLength(b,c)>0:void 0!==b&&null!==b&&b.length>0},email:function(a,b){return this.optional(b)||/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test(a)},url:function(a,b){return this.optional(b)||/^(?:(?:(?:https?|ftp):)?\/\/)(?:(?:[^\]\[?\/<~#`!@$^&*()+=}|:";',>{ ]|%[0-9A-Fa-f]{2})+(?::(?:[^\]\[?\/<~#`!@$^&*()+=}|:";',>{ ]|%[0-9A-Fa-f]{2})*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z0-9\u00a1-\uffff][a-z0-9\u00a1-\uffff_-]{0,62})?[a-z0-9\u00a1-\uffff]\.)+(?:[a-z\u00a1-\uffff]{2,}\.?))(?::\d{2,5})?(?:[/?#]\S*)?$/i.test(a)},date:function(){var a=!1;return function(b,c){return a||(a=!0,this.settings.debug&&window.console&&console.warn("The `date` method is deprecated and will be removed in version '2.0.0'.\nPlease don't use it, since it relies on the Date constructor, which\nbehaves very differently across browsers and locales. Use `dateISO`\ninstead or one of the locale specific methods in `localizations/`\nand `additional-methods.js`.")),this.optional(c)||!/Invalid|NaN/.test(new Date(b).toString())}}(),dateISO:function(a,b){return this.optional(b)||/^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test(a)},number:function(a,b){return this.optional(b)||/^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:-?\.\d+)?$/.test(a)},digits:function(a,b){return this.optional(b)||/^\d+$/.test(a)},minlength:function(a,b,c){var d=Array.isArray(a)?a.length:this.getLength(a,b);return this.optional(b)||d>=c},maxlength:function(a,b,c){var d=Array.isArray(a)?a.length:this.getLength(a,b);return this.optional(b)||d<=c},rangelength:function(a,b,c){var d=Array.isArray(a)?a.length:this.getLength(a,b);return this.optional(b)||d>=c[0]&&d<=c[1]},min:function(a,b,c){return this.optional(b)||a>=c},max:function(a,b,c){return this.optional(b)||a<=c},range:function(a,b,c){return this.optional(b)||a>=c[0]&&a<=c[1]},step:function(b,c,d){var e,f=a(c).attr("type"),g="Step attribute on input type "+f+" is not supported.",h=["text","number","range"],i=new RegExp("\\b"+f+"\\b"),j=f&&!i.test(h.join()),k=function(a){var b=(""+a).match(/(?:\.(\d+))?$/);return b&&b[1]?b[1].length:0},l=function(a){return Math.round(a*Math.pow(10,e))},m=!0;if(j)throw new Error(g);return e=k(d),(k(b)>e||l(b)%l(d)!==0)&&(m=!1),this.optional(c)||m},equalTo:function(b,c,d){var e=a(d);return this.settings.onfocusout&&e.not(".validate-equalTo-blur").length&&e.addClass("validate-equalTo-blur").on("blur.validate-equalTo",function(){a(c).valid()}),b===e.val()},remote:function(b,c,d,e){if(this.optional(c))return"dependency-mismatch";e="string"==typeof e&&e||"remote";var f,g,h,i=this.previousValue(c,e);return this.settings.messages[c.name]||(this.settings.messages[c.name]={}),i.originalMessage=i.originalMessage||this.settings.messages[c.name][e],this.settings.messages[c.name][e]=i.message,d="string"==typeof d&&{url:d}||d,h=a.param(a.extend({data:b},d.data)),null!==i.valid&&i.old===h?i.valid:(i.old=h,i.valid=null,f=this,this.startRequest(c),g={},g[c.name]=b,a.ajax(a.extend(!0,{mode:"abort",port:this.elementAjaxPort(c),dataType:"json",data:g,context:f.currentForm,success:function(a){var d,g,h,j=a===!0||"true"===a;f.settings.messages[c.name][e]=i.originalMessage,j?(h=f.formSubmitted,f.toHide=f.errorsFor(c),f.formSubmitted=h,f.successList.push(c),f.invalid[c.name]=!1,f.showErrors()):(d={},g=a||f.defaultMessage(c,{method:e,parameters:b}),d[c.name]=i.message=g,f.invalid[c.name]=!0,f.showErrors(d)),i.valid=j,f.stopRequest(c,j)}},d)),"pending")}}});var c,d={};return a.ajaxPrefilter?a.ajaxPrefilter(function(b,c,e){var f=b.port;"abort"===b.mode&&(a.ajaxAbort(f),d[f]=e)}):(c=a.ajax,a.ajax=function(b){var e=("mode"in b?b:a.ajaxSettings).mode,f=("port"in b?b:a.ajaxSettings).port;return"abort"===e?(a.ajaxAbort(f),d[f]=c.apply(this,arguments),d[f]):c.apply(this,arguments)}),a.ajaxAbort=function(a){d[a]&&(d[a].abort(),delete d[a])},a});
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/validate/messages_zh.js b/ruoyi-admin/src/main/resources/static/ajax/libs/validate/messages_zh.js
new file mode 100644
index 0000000..e5ea9b1
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/validate/messages_zh.js
@@ -0,0 +1,25 @@
+/*
+ * Translated default messages for the jQuery validation plugin.
+ * Locale: ZH (Chinese, 中文 (Zhōngwén), 汉语, 漢語)
+ */
+var icon = "<i class='fa fa-times-circle'></i>  ";
+$.extend($.validator.messages, {
+	required: icon + "必填",
+	remote: icon + "请修正此字段",
+	email: icon + "请输入有效的电子邮件",
+	url: icon + "请输入有效的网址",
+	date: icon + "请输入有效的日期",
+	dateISO: icon + "请输入有效的日期 (YYYY-MM-DD)",
+	number: icon + "请输入有效的数字",
+	digits: icon + "只能输入数字",
+	creditcard: icon + "请输入有效的信用卡号码",
+	equalTo: icon + "你的输入不相同",
+	extension: icon + "请输入有效的后缀",
+	maxlength: $.validator.format(icon + "最多可以输入 {0} 个字符"),
+	minlength: $.validator.format(icon + "最少要输入 {0} 个字符"),
+	rangelength: $.validator.format(icon + "请输入长度在 {0} 到 {1} 之间的字符串"),
+	range: $.validator.format(icon + "请输入范围在 {0} 到 {1} 之间的数值"),
+	step: $.validator.format(icon + "请输入 {0} 的整数倍值" ),
+	max: $.validator.format(icon + "请输入不大于 {0} 的数值"),
+	min: $.validator.format(icon + "请输入不小于 {0} 的数值")
+});
diff --git a/ruoyi-admin/src/main/resources/static/css/animate.min.css b/ruoyi-admin/src/main/resources/static/css/animate.min.css
new file mode 100644
index 0000000..81b04ee
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/css/animate.min.css
@@ -0,0 +1,12 @@
+@charset "UTF-8";/*!
+Animate.css - http://daneden.me/animate
+Licensed under the MIT license
+
+Copyright (c) 2013 Daniel Eden
+
+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.
+*/.animated{-webkit-animation-duration:1s;animation-duration:1s;-webkit-animation-fill-mode:both;animation-fill-mode:both;z-index:100}.animated.infinite{-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}.animated.hinge{-webkit-animation-duration:2s;animation-duration:2s}@-webkit-keyframes bounce{0%,100%,20%,50%,80%{-webkit-transform:translateY(0);transform:translateY(0)}40%{-webkit-transform:translateY(-30px);transform:translateY(-30px)}60%{-webkit-transform:translateY(-15px);transform:translateY(-15px)}}@keyframes bounce{0%,100%,20%,50%,80%{-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}40%{-webkit-transform:translateY(-30px);-ms-transform:translateY(-30px);transform:translateY(-30px)}60%{-webkit-transform:translateY(-15px);-ms-transform:translateY(-15px);transform:translateY(-15px)}}.bounce{-webkit-animation-name:bounce;animation-name:bounce}@-webkit-keyframes flash{0%,100%,50%{opacity:1}25%,75%{opacity:0}}@keyframes flash{0%,100%,50%{opacity:1}25%,75%{opacity:0}}.flash{-webkit-animation-name:flash;animation-name:flash}@-webkit-keyframes pulse{0%{-webkit-transform:scale(1);transform:scale(1)}50%{-webkit-transform:scale(1.1);transform:scale(1.1)}100%{-webkit-transform:scale(1);transform:scale(1)}}@keyframes pulse{0%{-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}50%{-webkit-transform:scale(1.1);-ms-transform:scale(1.1);transform:scale(1.1)}100%{-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}.pulse{-webkit-animation-name:pulse;animation-name:pulse}@-webkit-keyframes rubberBand{0%{-webkit-transform:scale(1);transform:scale(1)}30%{-webkit-transform:scaleX(1.25) scaleY(0.75);transform:scaleX(1.25) scaleY(0.75)}40%{-webkit-transform:scaleX(0.75) scaleY(1.25);transform:scaleX(0.75) scaleY(1.25)}60%{-webkit-transform:scaleX(1.15) scaleY(0.85);transform:scaleX(1.15) scaleY(0.85)}100%{-webkit-transform:scale(1);transform:scale(1)}}@keyframes rubberBand{0%{-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}30%{-webkit-transform:scaleX(1.25) scaleY(0.75);-ms-transform:scaleX(1.25) scaleY(0.75);transform:scaleX(1.25) scaleY(0.75)}40%{-webkit-transform:scaleX(0.75) scaleY(1.25);-ms-transform:scaleX(0.75) scaleY(1.25);transform:scaleX(0.75) scaleY(1.25)}60%{-webkit-transform:scaleX(1.15) scaleY(0.85);-ms-transform:scaleX(1.15) scaleY(0.85);transform:scaleX(1.15) scaleY(0.85)}100%{-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}.rubberBand{-webkit-animation-name:rubberBand;animation-name:rubberBand}@-webkit-keyframes shake{0%,100%{-webkit-transform:translateX(0);transform:translateX(0)}10%,30%,50%,70%,90%{-webkit-transform:translateX(-10px);transform:translateX(-10px)}20%,40%,60%,80%{-webkit-transform:translateX(10px);transform:translateX(10px)}}@keyframes shake{0%,100%{-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}10%,30%,50%,70%,90%{-webkit-transform:translateX(-10px);-ms-transform:translateX(-10px);transform:translateX(-10px)}20%,40%,60%,80%{-webkit-transform:translateX(10px);-ms-transform:translateX(10px);transform:translateX(10px)}}.shake{-webkit-animation-name:shake;animation-name:shake}@-webkit-keyframes swing{20%{-webkit-transform:rotate(15deg);transform:rotate(15deg)}40%{-webkit-transform:rotate(-10deg);transform:rotate(-10deg)}60%{-webkit-transform:rotate(5deg);transform:rotate(5deg)}80%{-webkit-transform:rotate(-5deg);transform:rotate(-5deg)}100%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}}@keyframes swing{20%{-webkit-transform:rotate(15deg);-ms-transform:rotate(15deg);transform:rotate(15deg)}40%{-webkit-transform:rotate(-10deg);-ms-transform:rotate(-10deg);transform:rotate(-10deg)}60%{-webkit-transform:rotate(5deg);-ms-transform:rotate(5deg);transform:rotate(5deg)}80%{-webkit-transform:rotate(-5deg);-ms-transform:rotate(-5deg);transform:rotate(-5deg)}100%{-webkit-transform:rotate(0deg);-ms-transform:rotate(0deg);transform:rotate(0deg)}}.swing{-webkit-transform-origin:top center;-ms-transform-origin:top center;transform-origin:top center;-webkit-animation-name:swing;animation-name:swing}@-webkit-keyframes tada{0%{-webkit-transform:scale(1);transform:scale(1)}10%,20%{-webkit-transform:scale(0.9) rotate(-3deg);transform:scale(0.9) rotate(-3deg)}30%,50%,70%,90%{-webkit-transform:scale(1.1) rotate(3deg);transform:scale(1.1) rotate(3deg)}40%,60%,80%{-webkit-transform:scale(1.1) rotate(-3deg);transform:scale(1.1) rotate(-3deg)}100%{-webkit-transform:scale(1) rotate(0);transform:scale(1) rotate(0)}}@keyframes tada{0%{-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}10%,20%{-webkit-transform:scale(0.9) rotate(-3deg);-ms-transform:scale(0.9) rotate(-3deg);transform:scale(0.9) rotate(-3deg)}30%,50%,70%,90%{-webkit-transform:scale(1.1) rotate(3deg);-ms-transform:scale(1.1) rotate(3deg);transform:scale(1.1) rotate(3deg)}40%,60%,80%{-webkit-transform:scale(1.1) rotate(-3deg);-ms-transform:scale(1.1) rotate(-3deg);transform:scale(1.1) rotate(-3deg)}100%{-webkit-transform:scale(1) rotate(0);-ms-transform:scale(1) rotate(0);transform:scale(1) rotate(0)}}.tada{-webkit-animation-name:tada;animation-name:tada}@-webkit-keyframes wobble{0%{-webkit-transform:translateX(0%);transform:translateX(0%)}15%{-webkit-transform:translateX(-25%) rotate(-5deg);transform:translateX(-25%) rotate(-5deg)}30%{-webkit-transform:translateX(20%) rotate(3deg);transform:translateX(20%) rotate(3deg)}45%{-webkit-transform:translateX(-15%) rotate(-3deg);transform:translateX(-15%) rotate(-3deg)}60%{-webkit-transform:translateX(10%) rotate(2deg);transform:translateX(10%) rotate(2deg)}75%{-webkit-transform:translateX(-5%) rotate(-1deg);transform:translateX(-5%) rotate(-1deg)}100%{-webkit-transform:translateX(0%);transform:translateX(0%)}}@keyframes wobble{0%{-webkit-transform:translateX(0%);-ms-transform:translateX(0%);transform:translateX(0%)}15%{-webkit-transform:translateX(-25%) rotate(-5deg);-ms-transform:translateX(-25%) rotate(-5deg);transform:translateX(-25%) rotate(-5deg)}30%{-webkit-transform:translateX(20%) rotate(3deg);-ms-transform:translateX(20%) rotate(3deg);transform:translateX(20%) rotate(3deg)}45%{-webkit-transform:translateX(-15%) rotate(-3deg);-ms-transform:translateX(-15%) rotate(-3deg);transform:translateX(-15%) rotate(-3deg)}60%{-webkit-transform:translateX(10%) rotate(2deg);-ms-transform:translateX(10%) rotate(2deg);transform:translateX(10%) rotate(2deg)}75%{-webkit-transform:translateX(-5%) rotate(-1deg);-ms-transform:translateX(-5%) rotate(-1deg);transform:translateX(-5%) rotate(-1deg)}100%{-webkit-transform:translateX(0%);-ms-transform:translateX(0%);transform:translateX(0%)}}.wobble{-webkit-animation-name:wobble;animation-name:wobble}@-webkit-keyframes bounceIn{0%{opacity:0;-webkit-transform:scale(.3);transform:scale(.3)}50%{opacity:1;-webkit-transform:scale(1.05);transform:scale(1.05)}70%{-webkit-transform:scale(.9);transform:scale(.9)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}@keyframes bounceIn{0%{opacity:0;-webkit-transform:scale(.3);-ms-transform:scale(.3);transform:scale(.3)}50%{opacity:1;-webkit-transform:scale(1.05);-ms-transform:scale(1.05);transform:scale(1.05)}70%{-webkit-transform:scale(.9);-ms-transform:scale(.9);transform:scale(.9)}100%{opacity:1;-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}.bounceIn{-webkit-animation-name:bounceIn;animation-name:bounceIn}@-webkit-keyframes bounceInDown{0%{opacity:0;-webkit-transform:translateY(-2000px);transform:translateY(-2000px)}60%{opacity:1;-webkit-transform:translateY(30px);transform:translateY(30px)}80%{-webkit-transform:translateY(-10px);transform:translateY(-10px)}100%{-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes bounceInDown{0%{opacity:0;-webkit-transform:translateY(-2000px);-ms-transform:translateY(-2000px);transform:translateY(-2000px)}60%{opacity:1;-webkit-transform:translateY(30px);-ms-transform:translateY(30px);transform:translateY(30px)}80%{-webkit-transform:translateY(-10px);-ms-transform:translateY(-10px);transform:translateY(-10px)}100%{-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}.bounceInDown{-webkit-animation-name:bounceInDown;animation-name:bounceInDown}@-webkit-keyframes bounceInLeft{0%{opacity:0;-webkit-transform:translateX(-2000px);transform:translateX(-2000px)}60%{opacity:1;-webkit-transform:translateX(30px);transform:translateX(30px)}80%{-webkit-transform:translateX(-10px);transform:translateX(-10px)}100%{-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes bounceInLeft{0%{opacity:0;-webkit-transform:translateX(-2000px);-ms-transform:translateX(-2000px);transform:translateX(-2000px)}60%{opacity:1;-webkit-transform:translateX(30px);-ms-transform:translateX(30px);transform:translateX(30px)}80%{-webkit-transform:translateX(-10px);-ms-transform:translateX(-10px);transform:translateX(-10px)}100%{-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}}.bounceInLeft{-webkit-animation-name:bounceInLeft;animation-name:bounceInLeft}@-webkit-keyframes bounceInRight{0%{opacity:0;-webkit-transform:translateX(2000px);transform:translateX(2000px)}60%{opacity:1;-webkit-transform:translateX(-30px);transform:translateX(-30px)}80%{-webkit-transform:translateX(10px);transform:translateX(10px)}100%{-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes bounceInRight{0%{opacity:0;-webkit-transform:translateX(2000px);-ms-transform:translateX(2000px);transform:translateX(2000px)}60%{opacity:1;-webkit-transform:translateX(-30px);-ms-transform:translateX(-30px);transform:translateX(-30px)}80%{-webkit-transform:translateX(10px);-ms-transform:translateX(10px);transform:translateX(10px)}100%{-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}}.bounceInRight{-webkit-animation-name:bounceInRight;animation-name:bounceInRight}@-webkit-keyframes bounceInUp{0%{opacity:0;-webkit-transform:translateY(2000px);transform:translateY(2000px)}60%{opacity:1;-webkit-transform:translateY(-30px);transform:translateY(-30px)}80%{-webkit-transform:translateY(10px);transform:translateY(10px)}100%{-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes bounceInUp{0%{opacity:0;-webkit-transform:translateY(2000px);-ms-transform:translateY(2000px);transform:translateY(2000px)}60%{opacity:1;-webkit-transform:translateY(-30px);-ms-transform:translateY(-30px);transform:translateY(-30px)}80%{-webkit-transform:translateY(10px);-ms-transform:translateY(10px);transform:translateY(10px)}100%{-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}.bounceInUp{-webkit-animation-name:bounceInUp;animation-name:bounceInUp}@-webkit-keyframes bounceOut{0%{-webkit-transform:scale(1);transform:scale(1)}25%{-webkit-transform:scale(.95);transform:scale(.95)}50%{opacity:1;-webkit-transform:scale(1.1);transform:scale(1.1)}100%{opacity:0;-webkit-transform:scale(.3);transform:scale(.3)}}@keyframes bounceOut{0%{-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}25%{-webkit-transform:scale(.95);-ms-transform:scale(.95);transform:scale(.95)}50%{opacity:1;-webkit-transform:scale(1.1);-ms-transform:scale(1.1);transform:scale(1.1)}100%{opacity:0;-webkit-transform:scale(.3);-ms-transform:scale(.3);transform:scale(.3)}}.bounceOut{-webkit-animation-name:bounceOut;animation-name:bounceOut}@-webkit-keyframes bounceOutDown{0%{-webkit-transform:translateY(0);transform:translateY(0)}20%{opacity:1;-webkit-transform:translateY(-20px);transform:translateY(-20px)}100%{opacity:0;-webkit-transform:translateY(2000px);transform:translateY(2000px)}}@keyframes bounceOutDown{0%{-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}20%{opacity:1;-webkit-transform:translateY(-20px);-ms-transform:translateY(-20px);transform:translateY(-20px)}100%{opacity:0;-webkit-transform:translateY(2000px);-ms-transform:translateY(2000px);transform:translateY(2000px)}}.bounceOutDown{-webkit-animation-name:bounceOutDown;animation-name:bounceOutDown}@-webkit-keyframes bounceOutLeft{0%{-webkit-transform:translateX(0);transform:translateX(0)}20%{opacity:1;-webkit-transform:translateX(20px);transform:translateX(20px)}100%{opacity:0;-webkit-transform:translateX(-2000px);transform:translateX(-2000px)}}@keyframes bounceOutLeft{0%{-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}20%{opacity:1;-webkit-transform:translateX(20px);-ms-transform:translateX(20px);transform:translateX(20px)}100%{opacity:0;-webkit-transform:translateX(-2000px);-ms-transform:translateX(-2000px);transform:translateX(-2000px)}}.bounceOutLeft{-webkit-animation-name:bounceOutLeft;animation-name:bounceOutLeft}@-webkit-keyframes bounceOutRight{0%{-webkit-transform:translateX(0);transform:translateX(0)}20%{opacity:1;-webkit-transform:translateX(-20px);transform:translateX(-20px)}100%{opacity:0;-webkit-transform:translateX(2000px);transform:translateX(2000px)}}@keyframes bounceOutRight{0%{-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}20%{opacity:1;-webkit-transform:translateX(-20px);-ms-transform:translateX(-20px);transform:translateX(-20px)}100%{opacity:0;-webkit-transform:translateX(2000px);-ms-transform:translateX(2000px);transform:translateX(2000px)}}.bounceOutRight{-webkit-animation-name:bounceOutRight;animation-name:bounceOutRight}@-webkit-keyframes bounceOutUp{0%{-webkit-transform:translateY(0);transform:translateY(0)}20%{opacity:1;-webkit-transform:translateY(20px);transform:translateY(20px)}100%{opacity:0;-webkit-transform:translateY(-2000px);transform:translateY(-2000px)}}@keyframes bounceOutUp{0%{-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}20%{opacity:1;-webkit-transform:translateY(20px);-ms-transform:translateY(20px);transform:translateY(20px)}100%{opacity:0;-webkit-transform:translateY(-2000px);-ms-transform:translateY(-2000px);transform:translateY(-2000px)}}.bounceOutUp{-webkit-animation-name:bounceOutUp;animation-name:bounceOutUp}@-webkit-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}@keyframes fadeIn{0%{opacity:0}100%{opacity:1}}.fadeIn{-webkit-animation-name:fadeIn;animation-name:fadeIn}@-webkit-keyframes fadeInDown{0%{opacity:0;-webkit-transform:translateY(-20px);transform:translateY(-20px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes fadeInDown{0%{opacity:0;-webkit-transform:translateY(-20px);-ms-transform:translateY(-20px);transform:translateY(-20px)}100%{opacity:1;-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}.fadeInDown{-webkit-animation-name:fadeInDown;animation-name:fadeInDown}@-webkit-keyframes fadeInDownBig{0%{opacity:0;-webkit-transform:translateY(-2000px);transform:translateY(-2000px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes fadeInDownBig{0%{opacity:0;-webkit-transform:translateY(-2000px);-ms-transform:translateY(-2000px);transform:translateY(-2000px)}100%{opacity:1;-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}.fadeInDownBig{-webkit-animation-name:fadeInDownBig;animation-name:fadeInDownBig}@-webkit-keyframes fadeInLeft{0%{opacity:0;-webkit-transform:translateX(-20px);transform:translateX(-20px)}100%{opacity:1;-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes fadeInLeft{0%{opacity:0;-webkit-transform:translateX(-20px);-ms-transform:translateX(-20px);transform:translateX(-20px)}100%{opacity:1;-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}}.fadeInLeft{-webkit-animation-name:fadeInLeft;animation-name:fadeInLeft}@-webkit-keyframes fadeInLeftBig{0%{opacity:0;-webkit-transform:translateX(-2000px);transform:translateX(-2000px)}100%{opacity:1;-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes fadeInLeftBig{0%{opacity:0;-webkit-transform:translateX(-2000px);-ms-transform:translateX(-2000px);transform:translateX(-2000px)}100%{opacity:1;-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}}.fadeInLeftBig{-webkit-animation-name:fadeInLeftBig;animation-name:fadeInLeftBig}@-webkit-keyframes fadeInRight{0%{opacity:0;-webkit-transform:translateX(20px);transform:translateX(20px)}100%{opacity:1;-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes fadeInRight{0%{opacity:0;-webkit-transform:translateX(40px);-ms-transform:translateX(40px);transform:translateX(40px)}100%{opacity:1;-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}}.fadeInRight{-webkit-animation-name:fadeInRight;animation-name:fadeInRight}@-webkit-keyframes fadeInRightBig{0%{opacity:0;-webkit-transform:translateX(2000px);transform:translateX(2000px)}100%{opacity:1;-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes fadeInRightBig{0%{opacity:0;-webkit-transform:translateX(2000px);-ms-transform:translateX(2000px);transform:translateX(2000px)}100%{opacity:1;-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}}.fadeInRightBig{-webkit-animation-name:fadeInRightBig;animation-name:fadeInRightBig}@-webkit-keyframes fadeInUp{0%{opacity:0;-webkit-transform:translateY(20px);transform:translateY(20px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes fadeInUp{0%{opacity:0;-webkit-transform:translateY(20px);-ms-transform:translateY(20px);transform:translateY(20px)}100%{opacity:1;-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}.fadeInUp{-webkit-animation-name:fadeInUp;animation-name:fadeInUp}@-webkit-keyframes fadeInUpBig{0%{opacity:0;-webkit-transform:translateY(2000px);transform:translateY(2000px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes fadeInUpBig{0%{opacity:0;-webkit-transform:translateY(2000px);-ms-transform:translateY(2000px);transform:translateY(2000px)}100%{opacity:1;-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}.fadeInUpBig{-webkit-animation-name:fadeInUpBig;animation-name:fadeInUpBig}@-webkit-keyframes fadeOut{0%{opacity:1}100%{opacity:0}}@keyframes fadeOut{0%{opacity:1}100%{opacity:0}}.fadeOut{-webkit-animation-name:fadeOut;animation-name:fadeOut}@-webkit-keyframes fadeOutDown{0%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}100%{opacity:0;-webkit-transform:translateY(20px);transform:translateY(20px)}}@keyframes fadeOutDown{0%{opacity:1;-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}100%{opacity:0;-webkit-transform:translateY(20px);-ms-transform:translateY(20px);transform:translateY(20px)}}.fadeOutDown{-webkit-animation-name:fadeOutDown;animation-name:fadeOutDown}@-webkit-keyframes fadeOutDownBig{0%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}100%{opacity:0;-webkit-transform:translateY(2000px);transform:translateY(2000px)}}@keyframes fadeOutDownBig{0%{opacity:1;-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}100%{opacity:0;-webkit-transform:translateY(2000px);-ms-transform:translateY(2000px);transform:translateY(2000px)}}.fadeOutDownBig{-webkit-animation-name:fadeOutDownBig;animation-name:fadeOutDownBig}@-webkit-keyframes fadeOutLeft{0%{opacity:1;-webkit-transform:translateX(0);transform:translateX(0)}100%{opacity:0;-webkit-transform:translateX(-20px);transform:translateX(-20px)}}@keyframes fadeOutLeft{0%{opacity:1;-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}100%{opacity:0;-webkit-transform:translateX(-20px);-ms-transform:translateX(-20px);transform:translateX(-20px)}}.fadeOutLeft{-webkit-animation-name:fadeOutLeft;animation-name:fadeOutLeft}@-webkit-keyframes fadeOutLeftBig{0%{opacity:1;-webkit-transform:translateX(0);transform:translateX(0)}100%{opacity:0;-webkit-transform:translateX(-2000px);transform:translateX(-2000px)}}@keyframes fadeOutLeftBig{0%{opacity:1;-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}100%{opacity:0;-webkit-transform:translateX(-2000px);-ms-transform:translateX(-2000px);transform:translateX(-2000px)}}.fadeOutLeftBig{-webkit-animation-name:fadeOutLeftBig;animation-name:fadeOutLeftBig}@-webkit-keyframes fadeOutRight{0%{opacity:1;-webkit-transform:translateX(0);transform:translateX(0)}100%{opacity:0;-webkit-transform:translateX(20px);transform:translateX(20px)}}@keyframes fadeOutRight{0%{opacity:1;-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}100%{opacity:0;-webkit-transform:translateX(20px);-ms-transform:translateX(20px);transform:translateX(20px)}}.fadeOutRight{-webkit-animation-name:fadeOutRight;animation-name:fadeOutRight}@-webkit-keyframes fadeOutRightBig{0%{opacity:1;-webkit-transform:translateX(0);transform:translateX(0)}100%{opacity:0;-webkit-transform:translateX(2000px);transform:translateX(2000px)}}@keyframes fadeOutRightBig{0%{opacity:1;-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}100%{opacity:0;-webkit-transform:translateX(2000px);-ms-transform:translateX(2000px);transform:translateX(2000px)}}.fadeOutRightBig{-webkit-animation-name:fadeOutRightBig;animation-name:fadeOutRightBig}@-webkit-keyframes fadeOutUp{0%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}100%{opacity:0;-webkit-transform:translateY(-20px);transform:translateY(-20px)}}@keyframes fadeOutUp{0%{opacity:1;-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}100%{opacity:0;-webkit-transform:translateY(-20px);-ms-transform:translateY(-20px);transform:translateY(-20px)}}.fadeOutUp{-webkit-animation-name:fadeOutUp;animation-name:fadeOutUp}@-webkit-keyframes fadeOutUpBig{0%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}100%{opacity:0;-webkit-transform:translateY(-2000px);transform:translateY(-2000px)}}@keyframes fadeOutUpBig{0%{opacity:1;-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}100%{opacity:0;-webkit-transform:translateY(-2000px);-ms-transform:translateY(-2000px);transform:translateY(-2000px)}}.fadeOutUpBig{-webkit-animation-name:fadeOutUpBig;animation-name:fadeOutUpBig}@-webkit-keyframes flip{0%{-webkit-transform:perspective(400px) translateZ(0) rotateY(0) scale(1);transform:perspective(400px) translateZ(0) rotateY(0) scale(1);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}40%{-webkit-transform:perspective(400px) translateZ(150px) rotateY(170deg) scale(1);transform:perspective(400px) translateZ(150px) rotateY(170deg) scale(1);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}50%{-webkit-transform:perspective(400px) translateZ(150px) rotateY(190deg) scale(1);transform:perspective(400px) translateZ(150px) rotateY(190deg) scale(1);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}80%{-webkit-transform:perspective(400px) translateZ(0) rotateY(360deg) scale(.95);transform:perspective(400px) translateZ(0) rotateY(360deg) scale(.95);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}100%{-webkit-transform:perspective(400px) translateZ(0) rotateY(360deg) scale(1);transform:perspective(400px) translateZ(0) rotateY(360deg) scale(1);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}}@keyframes flip{0%{-webkit-transform:perspective(400px) translateZ(0) rotateY(0) scale(1);-ms-transform:perspective(400px) translateZ(0) rotateY(0) scale(1);transform:perspective(400px) translateZ(0) rotateY(0) scale(1);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}40%{-webkit-transform:perspective(400px) translateZ(150px) rotateY(170deg) scale(1);-ms-transform:perspective(400px) translateZ(150px) rotateY(170deg) scale(1);transform:perspective(400px) translateZ(150px) rotateY(170deg) scale(1);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}50%{-webkit-transform:perspective(400px) translateZ(150px) rotateY(190deg) scale(1);-ms-transform:perspective(400px) translateZ(150px) rotateY(190deg) scale(1);transform:perspective(400px) translateZ(150px) rotateY(190deg) scale(1);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}80%{-webkit-transform:perspective(400px) translateZ(0) rotateY(360deg) scale(.95);-ms-transform:perspective(400px) translateZ(0) rotateY(360deg) scale(.95);transform:perspective(400px) translateZ(0) rotateY(360deg) scale(.95);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}100%{-webkit-transform:perspective(400px) translateZ(0) rotateY(360deg) scale(1);-ms-transform:perspective(400px) translateZ(0) rotateY(360deg) scale(1);transform:perspective(400px) translateZ(0) rotateY(360deg) scale(1);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}}.animated.flip{-webkit-backface-visibility:visible;-ms-backface-visibility:visible;backface-visibility:visible;-webkit-animation-name:flip;animation-name:flip}@-webkit-keyframes flipInX{0%{-webkit-transform:perspective(400px) rotateX(90deg);transform:perspective(400px) rotateX(90deg);opacity:0}40%{-webkit-transform:perspective(400px) rotateX(-10deg);transform:perspective(400px) rotateX(-10deg)}70%{-webkit-transform:perspective(400px) rotateX(10deg);transform:perspective(400px) rotateX(10deg)}100%{-webkit-transform:perspective(400px) rotateX(0deg);transform:perspective(400px) rotateX(0deg);opacity:1}}@keyframes flipInX{0%{-webkit-transform:perspective(400px) rotateX(90deg);-ms-transform:perspective(400px) rotateX(90deg);transform:perspective(400px) rotateX(90deg);opacity:0}40%{-webkit-transform:perspective(400px) rotateX(-10deg);-ms-transform:perspective(400px) rotateX(-10deg);transform:perspective(400px) rotateX(-10deg)}70%{-webkit-transform:perspective(400px) rotateX(10deg);-ms-transform:perspective(400px) rotateX(10deg);transform:perspective(400px) rotateX(10deg)}100%{-webkit-transform:perspective(400px) rotateX(0deg);-ms-transform:perspective(400px) rotateX(0deg);transform:perspective(400px) rotateX(0deg);opacity:1}}.flipInX{-webkit-backface-visibility:visible!important;-ms-backface-visibility:visible!important;backface-visibility:visible!important;-webkit-animation-name:flipInX;animation-name:flipInX}@-webkit-keyframes flipInY{0%{-webkit-transform:perspective(400px) rotateY(90deg);transform:perspective(400px) rotateY(90deg);opacity:0}40%{-webkit-transform:perspective(400px) rotateY(-10deg);transform:perspective(400px) rotateY(-10deg)}70%{-webkit-transform:perspective(400px) rotateY(10deg);transform:perspective(400px) rotateY(10deg)}100%{-webkit-transform:perspective(400px) rotateY(0deg);transform:perspective(400px) rotateY(0deg);opacity:1}}@keyframes flipInY{0%{-webkit-transform:perspective(400px) rotateY(90deg);-ms-transform:perspective(400px) rotateY(90deg);transform:perspective(400px) rotateY(90deg);opacity:0}40%{-webkit-transform:perspective(400px) rotateY(-10deg);-ms-transform:perspective(400px) rotateY(-10deg);transform:perspective(400px) rotateY(-10deg)}70%{-webkit-transform:perspective(400px) rotateY(10deg);-ms-transform:perspective(400px) rotateY(10deg);transform:perspective(400px) rotateY(10deg)}100%{-webkit-transform:perspective(400px) rotateY(0deg);-ms-transform:perspective(400px) rotateY(0deg);transform:perspective(400px) rotateY(0deg);opacity:1}}.flipInY{-webkit-backface-visibility:visible!important;-ms-backface-visibility:visible!important;backface-visibility:visible!important;-webkit-animation-name:flipInY;animation-name:flipInY}@-webkit-keyframes flipOutX{0%{-webkit-transform:perspective(400px) rotateX(0deg);transform:perspective(400px) rotateX(0deg);opacity:1}100%{-webkit-transform:perspective(400px) rotateX(90deg);transform:perspective(400px) rotateX(90deg);opacity:0}}@keyframes flipOutX{0%{-webkit-transform:perspective(400px) rotateX(0deg);-ms-transform:perspective(400px) rotateX(0deg);transform:perspective(400px) rotateX(0deg);opacity:1}100%{-webkit-transform:perspective(400px) rotateX(90deg);-ms-transform:perspective(400px) rotateX(90deg);transform:perspective(400px) rotateX(90deg);opacity:0}}.flipOutX{-webkit-animation-name:flipOutX;animation-name:flipOutX;-webkit-backface-visibility:visible!important;-ms-backface-visibility:visible!important;backface-visibility:visible!important}@-webkit-keyframes flipOutY{0%{-webkit-transform:perspective(400px) rotateY(0deg);transform:perspective(400px) rotateY(0deg);opacity:1}100%{-webkit-transform:perspective(400px) rotateY(90deg);transform:perspective(400px) rotateY(90deg);opacity:0}}@keyframes flipOutY{0%{-webkit-transform:perspective(400px) rotateY(0deg);-ms-transform:perspective(400px) rotateY(0deg);transform:perspective(400px) rotateY(0deg);opacity:1}100%{-webkit-transform:perspective(400px) rotateY(90deg);-ms-transform:perspective(400px) rotateY(90deg);transform:perspective(400px) rotateY(90deg);opacity:0}}.flipOutY{-webkit-backface-visibility:visible!important;-ms-backface-visibility:visible!important;backface-visibility:visible!important;-webkit-animation-name:flipOutY;animation-name:flipOutY}@-webkit-keyframes lightSpeedIn{0%{-webkit-transform:translateX(100%) skewX(-30deg);transform:translateX(100%) skewX(-30deg);opacity:0}60%{-webkit-transform:translateX(-20%) skewX(30deg);transform:translateX(-20%) skewX(30deg);opacity:1}80%{-webkit-transform:translateX(0%) skewX(-15deg);transform:translateX(0%) skewX(-15deg);opacity:1}100%{-webkit-transform:translateX(0%) skewX(0deg);transform:translateX(0%) skewX(0deg);opacity:1}}@keyframes lightSpeedIn{0%{-webkit-transform:translateX(100%) skewX(-30deg);-ms-transform:translateX(100%) skewX(-30deg);transform:translateX(100%) skewX(-30deg);opacity:0}60%{-webkit-transform:translateX(-20%) skewX(30deg);-ms-transform:translateX(-20%) skewX(30deg);transform:translateX(-20%) skewX(30deg);opacity:1}80%{-webkit-transform:translateX(0%) skewX(-15deg);-ms-transform:translateX(0%) skewX(-15deg);transform:translateX(0%) skewX(-15deg);opacity:1}100%{-webkit-transform:translateX(0%) skewX(0deg);-ms-transform:translateX(0%) skewX(0deg);transform:translateX(0%) skewX(0deg);opacity:1}}.lightSpeedIn{-webkit-animation-name:lightSpeedIn;animation-name:lightSpeedIn;-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}@-webkit-keyframes lightSpeedOut{0%{-webkit-transform:translateX(0%) skewX(0deg);transform:translateX(0%) skewX(0deg);opacity:1}100%{-webkit-transform:translateX(100%) skewX(-30deg);transform:translateX(100%) skewX(-30deg);opacity:0}}@keyframes lightSpeedOut{0%{-webkit-transform:translateX(0%) skewX(0deg);-ms-transform:translateX(0%) skewX(0deg);transform:translateX(0%) skewX(0deg);opacity:1}100%{-webkit-transform:translateX(100%) skewX(-30deg);-ms-transform:translateX(100%) skewX(-30deg);transform:translateX(100%) skewX(-30deg);opacity:0}}.lightSpeedOut{-webkit-animation-name:lightSpeedOut;animation-name:lightSpeedOut;-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}@-webkit-keyframes rotateIn{0%{-webkit-transform-origin:center center;transform-origin:center center;-webkit-transform:rotate(-200deg);transform:rotate(-200deg);opacity:0}100%{-webkit-transform-origin:center center;transform-origin:center center;-webkit-transform:rotate(0);transform:rotate(0);opacity:1}}@keyframes rotateIn{0%{-webkit-transform-origin:center center;-ms-transform-origin:center center;transform-origin:center center;-webkit-transform:rotate(-200deg);-ms-transform:rotate(-200deg);transform:rotate(-200deg);opacity:0}100%{-webkit-transform-origin:center center;-ms-transform-origin:center center;transform-origin:center center;-webkit-transform:rotate(0);-ms-transform:rotate(0);transform:rotate(0);opacity:1}}.rotateIn{-webkit-animation-name:rotateIn;animation-name:rotateIn}@-webkit-keyframes rotateInDownLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate(-90deg);transform:rotate(-90deg);opacity:0}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate(0);transform:rotate(0);opacity:1}}@keyframes rotateInDownLeft{0%{-webkit-transform-origin:left bottom;-ms-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate(-90deg);-ms-transform:rotate(-90deg);transform:rotate(-90deg);opacity:0}100%{-webkit-transform-origin:left bottom;-ms-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate(0);-ms-transform:rotate(0);transform:rotate(0);opacity:1}}.rotateInDownLeft{-webkit-animation-name:rotateInDownLeft;animation-name:rotateInDownLeft}@-webkit-keyframes rotateInDownRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate(90deg);transform:rotate(90deg);opacity:0}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate(0);transform:rotate(0);opacity:1}}@keyframes rotateInDownRight{0%{-webkit-transform-origin:right bottom;-ms-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg);opacity:0}100%{-webkit-transform-origin:right bottom;-ms-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate(0);-ms-transform:rotate(0);transform:rotate(0);opacity:1}}.rotateInDownRight{-webkit-animation-name:rotateInDownRight;animation-name:rotateInDownRight}@-webkit-keyframes rotateInUpLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate(90deg);transform:rotate(90deg);opacity:0}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate(0);transform:rotate(0);opacity:1}}@keyframes rotateInUpLeft{0%{-webkit-transform-origin:left bottom;-ms-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg);opacity:0}100%{-webkit-transform-origin:left bottom;-ms-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate(0);-ms-transform:rotate(0);transform:rotate(0);opacity:1}}.rotateInUpLeft{-webkit-animation-name:rotateInUpLeft;animation-name:rotateInUpLeft}@-webkit-keyframes rotateInUpRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate(-90deg);transform:rotate(-90deg);opacity:0}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate(0);transform:rotate(0);opacity:1}}@keyframes rotateInUpRight{0%{-webkit-transform-origin:right bottom;-ms-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate(-90deg);-ms-transform:rotate(-90deg);transform:rotate(-90deg);opacity:0}100%{-webkit-transform-origin:right bottom;-ms-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate(0);-ms-transform:rotate(0);transform:rotate(0);opacity:1}}.rotateInUpRight{-webkit-animation-name:rotateInUpRight;animation-name:rotateInUpRight}@-webkit-keyframes rotateOut{0%{-webkit-transform-origin:center center;transform-origin:center center;-webkit-transform:rotate(0);transform:rotate(0);opacity:1}100%{-webkit-transform-origin:center center;transform-origin:center center;-webkit-transform:rotate(200deg);transform:rotate(200deg);opacity:0}}@keyframes rotateOut{0%{-webkit-transform-origin:center center;-ms-transform-origin:center center;transform-origin:center center;-webkit-transform:rotate(0);-ms-transform:rotate(0);transform:rotate(0);opacity:1}100%{-webkit-transform-origin:center center;-ms-transform-origin:center center;transform-origin:center center;-webkit-transform:rotate(200deg);-ms-transform:rotate(200deg);transform:rotate(200deg);opacity:0}}.rotateOut{-webkit-animation-name:rotateOut;animation-name:rotateOut}@-webkit-keyframes rotateOutDownLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate(0);transform:rotate(0);opacity:1}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate(90deg);transform:rotate(90deg);opacity:0}}@keyframes rotateOutDownLeft{0%{-webkit-transform-origin:left bottom;-ms-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate(0);-ms-transform:rotate(0);transform:rotate(0);opacity:1}100%{-webkit-transform-origin:left bottom;-ms-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg);opacity:0}}.rotateOutDownLeft{-webkit-animation-name:rotateOutDownLeft;animation-name:rotateOutDownLeft}@-webkit-keyframes rotateOutDownRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate(0);transform:rotate(0);opacity:1}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate(-90deg);transform:rotate(-90deg);opacity:0}}@keyframes rotateOutDownRight{0%{-webkit-transform-origin:right bottom;-ms-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate(0);-ms-transform:rotate(0);transform:rotate(0);opacity:1}100%{-webkit-transform-origin:right bottom;-ms-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate(-90deg);-ms-transform:rotate(-90deg);transform:rotate(-90deg);opacity:0}}.rotateOutDownRight{-webkit-animation-name:rotateOutDownRight;animation-name:rotateOutDownRight}@-webkit-keyframes rotateOutUpLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate(0);transform:rotate(0);opacity:1}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate(-90deg);transform:rotate(-90deg);opacity:0}}@keyframes rotateOutUpLeft{0%{-webkit-transform-origin:left bottom;-ms-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate(0);-ms-transform:rotate(0);transform:rotate(0);opacity:1}100%{-webkit-transform-origin:left bottom;-ms-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate(-90deg);-ms-transform:rotate(-90deg);transform:rotate(-90deg);opacity:0}}.rotateOutUpLeft{-webkit-animation-name:rotateOutUpLeft;animation-name:rotateOutUpLeft}@-webkit-keyframes rotateOutUpRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate(0);transform:rotate(0);opacity:1}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate(90deg);transform:rotate(90deg);opacity:0}}@keyframes rotateOutUpRight{0%{-webkit-transform-origin:right bottom;-ms-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate(0);-ms-transform:rotate(0);transform:rotate(0);opacity:1}100%{-webkit-transform-origin:right bottom;-ms-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg);opacity:0}}.rotateOutUpRight{-webkit-animation-name:rotateOutUpRight;animation-name:rotateOutUpRight}@-webkit-keyframes slideInDown{0%{opacity:0;-webkit-transform:translateY(-2000px);transform:translateY(-2000px)}100%{-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes slideInDown{0%{opacity:0;-webkit-transform:translateY(-2000px);-ms-transform:translateY(-2000px);transform:translateY(-2000px)}100%{-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}.slideInDown{-webkit-animation-name:slideInDown;animation-name:slideInDown}@-webkit-keyframes slideInLeft{0%{opacity:0;-webkit-transform:translateX(-2000px);transform:translateX(-2000px)}100%{-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes slideInLeft{0%{opacity:0;-webkit-transform:translateX(-2000px);-ms-transform:translateX(-2000px);transform:translateX(-2000px)}100%{-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}}.slideInLeft{-webkit-animation-name:slideInLeft;animation-name:slideInLeft}@-webkit-keyframes slideInRight{0%{opacity:0;-webkit-transform:translateX(2000px);transform:translateX(2000px)}100%{-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes slideInRight{0%{opacity:0;-webkit-transform:translateX(2000px);-ms-transform:translateX(2000px);transform:translateX(2000px)}100%{-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}}.slideInRight{-webkit-animation-name:slideInRight;animation-name:slideInRight}@-webkit-keyframes slideOutLeft{0%{-webkit-transform:translateX(0);transform:translateX(0)}100%{opacity:0;-webkit-transform:translateX(-2000px);transform:translateX(-2000px)}}@keyframes slideOutLeft{0%{-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}100%{opacity:0;-webkit-transform:translateX(-2000px);-ms-transform:translateX(-2000px);transform:translateX(-2000px)}}.slideOutLeft{-webkit-animation-name:slideOutLeft;animation-name:slideOutLeft}@-webkit-keyframes slideOutRight{0%{-webkit-transform:translateX(0);transform:translateX(0)}100%{opacity:0;-webkit-transform:translateX(2000px);transform:translateX(2000px)}}@keyframes slideOutRight{0%{-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}100%{opacity:0;-webkit-transform:translateX(2000px);-ms-transform:translateX(2000px);transform:translateX(2000px)}}.slideOutRight{-webkit-animation-name:slideOutRight;animation-name:slideOutRight}@-webkit-keyframes slideOutUp{0%{-webkit-transform:translateY(0);transform:translateY(0)}100%{opacity:0;-webkit-transform:translateY(-2000px);transform:translateY(-2000px)}}@keyframes slideOutUp{0%{-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}100%{opacity:0;-webkit-transform:translateY(-2000px);-ms-transform:translateY(-2000px);transform:translateY(-2000px)}}.slideOutUp{-webkit-animation-name:slideOutUp;animation-name:slideOutUp}@-webkit-keyframes slideOutDown{0%{-webkit-transform:translateY(0);transform:translateY(0)}100%{opacity:0;-webkit-transform:translateY(2000px);transform:translateY(2000px)}}@keyframes slideOutDown{0%{-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}100%{opacity:0;-webkit-transform:translateY(2000px);-ms-transform:translateY(2000px);transform:translateY(2000px)}}.slideOutDown{-webkit-animation-name:slideOutDown;animation-name:slideOutDown}@-webkit-keyframes hinge{0%{-webkit-transform:rotate(0);transform:rotate(0);-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}20%,60%{-webkit-transform:rotate(80deg);transform:rotate(80deg);-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}40%{-webkit-transform:rotate(60deg);transform:rotate(60deg);-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}80%{-webkit-transform:rotate(60deg) translateY(0);transform:rotate(60deg) translateY(0);-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;opacity:1}100%{-webkit-transform:translateY(700px);transform:translateY(700px);opacity:0}}@keyframes hinge{0%{-webkit-transform:rotate(0);-ms-transform:rotate(0);transform:rotate(0);-webkit-transform-origin:top left;-ms-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}20%,60%{-webkit-transform:rotate(80deg);-ms-transform:rotate(80deg);transform:rotate(80deg);-webkit-transform-origin:top left;-ms-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}40%{-webkit-transform:rotate(60deg);-ms-transform:rotate(60deg);transform:rotate(60deg);-webkit-transform-origin:top left;-ms-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}80%{-webkit-transform:rotate(60deg) translateY(0);-ms-transform:rotate(60deg) translateY(0);transform:rotate(60deg) translateY(0);-webkit-transform-origin:top left;-ms-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;opacity:1}100%{-webkit-transform:translateY(700px);-ms-transform:translateY(700px);transform:translateY(700px);opacity:0}}.hinge{-webkit-animation-name:hinge;animation-name:hinge}@-webkit-keyframes rollIn{0%{opacity:0;-webkit-transform:translateX(-100%) rotate(-120deg);transform:translateX(-100%) rotate(-120deg)}100%{opacity:1;-webkit-transform:translateX(0px) rotate(0deg);transform:translateX(0px) rotate(0deg)}}@keyframes rollIn{0%{opacity:0;-webkit-transform:translateX(-100%) rotate(-120deg);-ms-transform:translateX(-100%) rotate(-120deg);transform:translateX(-100%) rotate(-120deg)}100%{opacity:1;-webkit-transform:translateX(0px) rotate(0deg);-ms-transform:translateX(0px) rotate(0deg);transform:translateX(0px) rotate(0deg)}}.rollIn{-webkit-animation-name:rollIn;animation-name:rollIn}@-webkit-keyframes rollOut{0%{opacity:1;-webkit-transform:translateX(0px) rotate(0deg);transform:translateX(0px) rotate(0deg)}100%{opacity:0;-webkit-transform:translateX(100%) rotate(120deg);transform:translateX(100%) rotate(120deg)}}@keyframes rollOut{0%{opacity:1;-webkit-transform:translateX(0px) rotate(0deg);-ms-transform:translateX(0px) rotate(0deg);transform:translateX(0px) rotate(0deg)}100%{opacity:0;-webkit-transform:translateX(100%) rotate(120deg);-ms-transform:translateX(100%) rotate(120deg);transform:translateX(100%) rotate(120deg)}}.rollOut{-webkit-animation-name:rollOut;animation-name:rollOut}
diff --git a/ruoyi-admin/src/main/resources/static/css/bootstrap.min.css b/ruoyi-admin/src/main/resources/static/css/bootstrap.min.css
new file mode 100644
index 0000000..73bd8ae
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/css/bootstrap.min.css
@@ -0,0 +1,5 @@
+/*!
+ * Bootstrap v3.3.7 (http://getbootstrap.com)
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff2) format('woff2'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\002a"}.glyphicon-plus:before{content:"\002b"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:focus,a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:focus,a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:focus,a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:focus,a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:focus,a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:focus,a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:focus,a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:focus,a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:focus,a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:focus,a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;margin-left:-5px;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:''}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px\9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=checkbox]:focus,input[type=radio]:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control::-ms-expand{background-color:transparent;border:0}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date].form-control,input[type=time].form-control,input[type=datetime-local].form-control,input[type=month].form-control{line-height:34px}.input-group-sm input[type=date],.input-group-sm input[type=time],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:30px}.input-group-lg input[type=date],.input-group-lg input[type=time],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-top:4px\9;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}.checkbox-inline.disabled,.radio-inline.disabled,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio-inline{cursor:not-allowed}.checkbox.disabled label,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .radio label{cursor:not-allowed}.form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm select[multiple].form-control,.form-group-sm textarea.form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg select[multiple].form-control,.form-group-lg textarea.form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.form-group-lg .form-control+.form-control-feedback,.input-group-lg+.form-control-feedback,.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.form-group-sm .form-control+.form-control-feedback,.input-group-sm+.form-control-feedback,.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:11px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.focus,.btn-default:focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active.focus,.btn-default.active:focus,.btn-default.active:hover,.btn-default:active.focus,.btn-default:active:focus,.btn-default:active:hover,.open>.dropdown-toggle.btn-default.focus,.open>.dropdown-toggle.btn-default:focus,.open>.dropdown-toggle.btn-default:hover{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled.focus,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled].focus,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active.focus,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active.focus,.btn-primary:active:focus,.btn-primary:active:hover,.open>.dropdown-toggle.btn-primary.focus,.open>.dropdown-toggle.btn-primary:focus,.open>.dropdown-toggle.btn-primary:hover{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled.focus,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled].focus,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active.focus,.btn-success.active:focus,.btn-success.active:hover,.btn-success:active.focus,.btn-success:active:focus,.btn-success:active:hover,.open>.dropdown-toggle.btn-success.focus,.open>.dropdown-toggle.btn-success:focus,.open>.dropdown-toggle.btn-success:hover{color:#fff;background-color:#398439;border-color:#255625}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled.focus,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled].focus,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active.focus,.btn-info.active:focus,.btn-info.active:hover,.btn-info:active.focus,.btn-info:active:focus,.btn-info:active:hover,.open>.dropdown-toggle.btn-info.focus,.open>.dropdown-toggle.btn-info:focus,.open>.dropdown-toggle.btn-info:hover{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled.focus,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled].focus,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.focus,.btn-warning:focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active.focus,.btn-warning.active:focus,.btn-warning.active:hover,.btn-warning:active.focus,.btn-warning:active:focus,.btn-warning:active:hover,.open>.dropdown-toggle.btn-warning.focus,.open>.dropdown-toggle.btn-warning:focus,.open>.dropdown-toggle.btn-warning:hover{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled.focus,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled].focus,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active.focus,.btn-danger.active:focus,.btn-danger.active:hover,.btn-danger:active.focus,.btn-danger:active:focus,.btn-danger:active:hover,.open>.dropdown-toggle.btn-danger.focus,.open>.dropdown-toggle.btn-danger:focus,.open>.dropdown-toggle.btn-danger:hover{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled.focus,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled].focus,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid\9;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px dashed;border-bottom:4px solid\9}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn,textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn,textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:2;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:3;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-group-xs>.btn .badge,.btn-xs .badge{top:0;padding:1px 5px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{padding-right:15px;padding-left:15px;border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{margin-right:auto;margin-left:auto}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-bar-striped,.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover,button.list-group-item:focus,button.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover,button.list-group-item-success.active,button.list-group-item-success.active:focus,button.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover,button.list-group-item-info.active,button.list-group-item-info.active:focus,button.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover,button.list-group-item-warning.active,button.list-group-item-warning.active:focus,button.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover,button.list-group-item-danger.active,button.list-group-item-danger.active:focus,button.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-right:15px;padding-left:15px}.panel>.table-responsive:first-child>.table:first-child,.panel>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child,.panel>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:12px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;filter:alpha(opacity=0);opacity:0;line-break:auto}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);line-break:auto}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.active.right,.carousel-inner>.item.next{left:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{left:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{left:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);background-color:rgba(0,0,0,0);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;filter:alpha(opacity=90);outline:0;opacity:.9}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block;margin-top:-10px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000\9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-10px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.modal-header:after,.modal-header:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager:after,.pager:before,.panel-body:after,.panel-body:before,.row:after,.row:before{display:table;content:" "}.btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.modal-footer:after,.modal-header:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-md,.visible-sm,.visible-xs{display:none!important}.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}}
diff --git a/ruoyi-admin/src/main/resources/static/css/font-awesome.min.css b/ruoyi-admin/src/main/resources/static/css/font-awesome.min.css
new file mode 100644
index 0000000..540440c
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/css/font-awesome.min.css
@@ -0,0 +1,4 @@
+/*!
+ *  Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome
+ *  License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
+ */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.7.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-resistance:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}.fa-gitlab:before{content:"\f296"}.fa-wpbeginner:before{content:"\f297"}.fa-wpforms:before{content:"\f298"}.fa-envira:before{content:"\f299"}.fa-universal-access:before{content:"\f29a"}.fa-wheelchair-alt:before{content:"\f29b"}.fa-question-circle-o:before{content:"\f29c"}.fa-blind:before{content:"\f29d"}.fa-audio-description:before{content:"\f29e"}.fa-volume-control-phone:before{content:"\f2a0"}.fa-braille:before{content:"\f2a1"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:"\f2a4"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-signing:before,.fa-sign-language:before{content:"\f2a7"}.fa-low-vision:before{content:"\f2a8"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-pied-piper:before{content:"\f2ae"}.fa-first-order:before{content:"\f2b0"}.fa-yoast:before{content:"\f2b1"}.fa-themeisle:before{content:"\f2b2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\f2b3"}.fa-fa:before,.fa-font-awesome:before{content:"\f2b4"}.fa-handshake-o:before{content:"\f2b5"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-o:before{content:"\f2b7"}.fa-linode:before{content:"\f2b8"}.fa-address-book:before{content:"\f2b9"}.fa-address-book-o:before{content:"\f2ba"}.fa-vcard:before,.fa-address-card:before{content:"\f2bb"}.fa-vcard-o:before,.fa-address-card-o:before{content:"\f2bc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-circle-o:before{content:"\f2be"}.fa-user-o:before{content:"\f2c0"}.fa-id-badge:before{content:"\f2c1"}.fa-drivers-license:before,.fa-id-card:before{content:"\f2c2"}.fa-drivers-license-o:before,.fa-id-card-o:before{content:"\f2c3"}.fa-quora:before{content:"\f2c4"}.fa-free-code-camp:before{content:"\f2c5"}.fa-telegram:before{content:"\f2c6"}.fa-thermometer-4:before,.fa-thermometer:before,.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\f2cb"}.fa-shower:before{content:"\f2cc"}.fa-bathtub:before,.fa-s15:before,.fa-bath:before{content:"\f2cd"}.fa-podcast:before{content:"\f2ce"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-times-rectangle:before,.fa-window-close:before{content:"\f2d3"}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:"\f2d4"}.fa-bandcamp:before{content:"\f2d5"}.fa-grav:before{content:"\f2d6"}.fa-etsy:before{content:"\f2d7"}.fa-imdb:before{content:"\f2d8"}.fa-ravelry:before{content:"\f2d9"}.fa-eercast:before{content:"\f2da"}.fa-microchip:before{content:"\f2db"}.fa-snowflake-o:before{content:"\f2dc"}.fa-superpowers:before{content:"\f2dd"}.fa-wpexplorer:before{content:"\f2de"}.fa-meetup:before{content:"\f2e0"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}
diff --git a/ruoyi-admin/src/main/resources/static/css/jquery.contextMenu.min.css b/ruoyi-admin/src/main/resources/static/css/jquery.contextMenu.min.css
new file mode 100644
index 0000000..b0c6e63
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/css/jquery.contextMenu.min.css
@@ -0,0 +1,15 @@
+@charset "UTF-8";/*!
+ * jQuery contextMenu - Plugin for simple contextMenu handling
+ *
+ * Version: v2.8.0
+ *
+ * Authors: Björn Brala (SWIS.nl), Rodney Rehm, Addy Osmani (patches for FF)
+ * Web: http://swisnl.github.io/jQuery-contextMenu/
+ *
+ * Copyright (c) 2011-2019 SWIS BV and contributors
+ *
+ * Licensed under
+ *   MIT License http://www.opensource.org/licenses/mit-license
+ *
+ * Date: 2019-01-16T15:45:48.418Z
+ */@-webkit-keyframes cm-spin{0%{-webkit-transform:translateY(-50%) rotate(0);transform:translateY(-50%) rotate(0)}100%{-webkit-transform:translateY(-50%) rotate(359deg);transform:translateY(-50%) rotate(359deg)}}@-o-keyframes cm-spin{0%{-webkit-transform:translateY(-50%) rotate(0);-o-transform:translateY(-50%) rotate(0);transform:translateY(-50%) rotate(0)}100%{-webkit-transform:translateY(-50%) rotate(359deg);-o-transform:translateY(-50%) rotate(359deg);transform:translateY(-50%) rotate(359deg)}}@keyframes cm-spin{0%{-webkit-transform:translateY(-50%) rotate(0);-o-transform:translateY(-50%) rotate(0);transform:translateY(-50%) rotate(0)}100%{-webkit-transform:translateY(-50%) rotate(359deg);-o-transform:translateY(-50%) rotate(359deg);transform:translateY(-50%) rotate(359deg)}}@font-face{font-family:context-menu-icons;font-style:normal;font-weight:400;src:url(font/context-menu-icons.eot?2lkho);src:url(font/context-menu-icons.eot?2lkho#iefix) format("embedded-opentype"),url(font/context-menu-icons.woff2?2lkho) format("woff2"),url(font/context-menu-icons.woff?2lkho) format("woff"),url(font/context-menu-icons.ttf?2lkho) format("truetype")}.context-menu-icon-add:before{content:"\EA01"}.context-menu-icon-copy:before{content:"\EA02"}.context-menu-icon-cut:before{content:"\EA03"}.context-menu-icon-delete:before{content:"\EA04"}.context-menu-icon-edit:before{content:"\EA05"}.context-menu-icon-loading:before{content:"\EA06"}.context-menu-icon-paste:before{content:"\EA07"}.context-menu-icon-quit:before{content:"\EA08"}.context-menu-icon::before{position:absolute;top:50%;left:0;width:2em;font-family:context-menu-icons;font-size:1em;font-style:normal;font-weight:400;line-height:1;color:#2980b9;text-align:center;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);-o-transform:translateY(-50%);transform:translateY(-50%);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.context-menu-icon.context-menu-hover:before{color:#fff}.context-menu-icon.context-menu-disabled::before{color:#bbb}.context-menu-icon.context-menu-icon-loading:before{-webkit-animation:cm-spin 2s infinite;-o-animation:cm-spin 2s infinite;animation:cm-spin 2s infinite}.context-menu-icon.context-menu-icon--fa{display:list-item;font-family:inherit;line-height:inherit}.context-menu-icon.context-menu-icon--fa::before{position:absolute;top:50%;left:0;width:2em;font-family:FontAwesome;font-size:1em;font-style:normal;font-weight:400;line-height:1;color:#2980b9;text-align:center;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);-o-transform:translateY(-50%);transform:translateY(-50%);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.context-menu-icon.context-menu-icon--fa.context-menu-hover:before{color:#fff}.context-menu-icon.context-menu-icon--fa.context-menu-disabled::before{color:#bbb}.context-menu-icon.context-menu-icon--fa5{display:list-item;font-family:inherit;line-height:inherit}.context-menu-icon.context-menu-icon--fa5 i,.context-menu-icon.context-menu-icon--fa5 svg{position:absolute;top:.3em;left:.5em;color:#2980b9}.context-menu-icon.context-menu-icon--fa5.context-menu-hover>i,.context-menu-icon.context-menu-icon--fa5.context-menu-hover>svg{color:#fff}.context-menu-icon.context-menu-icon--fa5.context-menu-disabled i,.context-menu-icon.context-menu-icon--fa5.context-menu-disabled svg{color:#bbb}.context-menu-list{position:absolute;display:inline-block;min-width:0em;max-width:26em;padding:.25em 0;margin:.3em;font-family:inherit;font-size:inherit;list-style-type:none;background:#fff;border:1px solid #bebebe;border-radius:.2em;-webkit-box-shadow:0 2px 5px rgba(0,0,0,.5);box-shadow:0 2px 5px rgba(0,0,0,.5)}.context-menu-item{position:relative;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;padding:.2em 2em;color:#2f2f2f;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:#fff}.context-menu-separator{padding:0;margin:.35em 0;border-bottom:1px solid #e6e6e6}.context-menu-item>label>input,.context-menu-item>label>textarea{-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text;user-select:text}.context-menu-item.context-menu-hover{color:#fff;cursor:pointer;background-color:#2980b9}.context-menu-item.context-menu-disabled{color:#bbb;cursor:default;background-color:#fff}.context-menu-input.context-menu-hover{color:#2f2f2f;cursor:default}.context-menu-submenu:after{position:absolute;top:50%;right:.5em;z-index:1;width:0;height:0;content:'';border-color:transparent transparent transparent #2f2f2f;border-style:solid;border-width:.25em 0 .25em .25em;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);-o-transform:translateY(-50%);transform:translateY(-50%)}.context-menu-item.context-menu-input{padding:.3em .6em}.context-menu-input>label>*{vertical-align:top}.context-menu-input>label>input[type=checkbox],.context-menu-input>label>input[type=radio]{position:relative;top:.12em;margin-right:.4em}.context-menu-input>label{margin:0}.context-menu-input>label,.context-menu-input>label>input[type=text],.context-menu-input>label>select,.context-menu-input>label>textarea{display:block;width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.context-menu-input>label>textarea{height:7em}.context-menu-item>.context-menu-list{top:.3em;right:-.3em;display:none}.context-menu-item.context-menu-visible>.context-menu-list{display:block}.context-menu-accesskey{text-decoration:underline}
diff --git a/ruoyi-admin/src/main/resources/static/css/login.css b/ruoyi-admin/src/main/resources/static/css/login.css
new file mode 100644
index 0000000..40fba89
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/css/login.css
@@ -0,0 +1,175 @@
+html {
+	height:100%
+}
+body.signin {
+	height:auto;
+	background:url(../img/login-background.jpg) no-repeat center fixed;
+	-webkit-background-size:cover;
+	-moz-background-size:cover;
+	-o-background-size:cover;
+	background-size:cover
+}
+.signinpanel {
+	width:750px;
+	margin:10% auto 0;
+	color:rgba(255,255,255,.95)
+}
+.signinpanel .logopanel {
+	float:none;
+	width:auto;
+	padding:0;
+	background:0 0
+}
+.signinpanel .signin-info ul {
+	list-style:none;
+	padding:0;
+	margin:20px 0
+}
+.signinpanel .form-control {
+	display:block;
+	margin-top:15px
+}
+.signinpanel .uname {
+	background:#fff url(../img/user.png) no-repeat 95% center;
+	color:#333
+}
+.signinpanel .pword {
+	background:#fff url(../img/locked.png) no-repeat 95% center;
+	color:#333
+}
+.signinpanel .code {
+    background: #fff no-repeat 95% center;color:#333; margin:0 0 15px 0;
+}
+.signinpanel .btn {
+	margin-top:15px
+}
+.signinpanel form {
+	background:rgba(255,255,255,.2);
+	border:1px solid rgba(255,255,255,.3);
+	-moz-box-shadow:0 3px 0 rgba(12,12,12,.03);
+	-webkit-box-shadow:0 3px 0 rgba(12,12,12,.03);
+	box-shadow:0 3px 0 rgba(12,12,12,.03);
+	-moz-border-radius:3px;
+	-webkit-border-radius:3px;
+	border-radius:3px;
+	padding:30px
+}
+.signup-footer {
+	border-top:solid 1px rgba(255,255,255,.3);
+	margin:20px 0;
+	padding-top:15px
+}
+@media screen and (max-width:768px) {
+	.signinpanel,.signuppanel {
+	margin:0 auto;
+	width:380px!important;
+	padding:20px
+}
+.signinpanel form {
+	margin-top:20px
+}
+.signup-footer,.signuppanel .form-control {
+	margin-bottom:10px
+}
+.signup-footer .pull-left,.signup-footer .pull-right {
+	float:none!important;
+	text-align:center
+}
+.signinpanel .signin-info ul {
+	display:none
+}
+}@media screen and (max-width:320px) {
+	.signinpanel,.signuppanel {
+	margin:0 20px;
+	width:auto
+}
+}
+/*
+登录界面check样式
+*/
+.checkbox-custom {
+    position: relative;
+    padding: 0 15px 0 25px;
+    margin-bottom: 7px;
+    display: inline-block;
+}
+/*
+将初始的checkbox的样式改变
+*/
+.checkbox-custom input[type="checkbox"] {
+    opacity: 0; /*将初始的checkbox隐藏起来*/
+    position: absolute;
+    cursor: pointer;
+    z-index: 2;
+    margin: -6px 0 0 0;
+    top: 50%;
+    left: 3px;
+}
+/*
+设计新的checkbox,位置
+*/
+.checkbox-custom label:before {
+    content: '';
+    position: absolute;
+    top: 50%;
+    left: 0;
+    margin-top: -9px;
+    width: 18px;
+    height: 17px;
+    display: inline-block;
+    border-radius: 2px;
+    border: 1px solid #bbb;
+    background: #fff;
+}
+/*
+点击初始的checkbox,将新的checkbox关联起来
+*/
+.checkbox-custom input[type="checkbox"]:checked +label:after {
+    position: absolute;
+    display: inline-block;
+    font-family: 'Glyphicons Halflings';
+    content: "\e013";
+    top: 42%;
+    left: 3px;
+    margin-top: -5px;
+    font-size: 11px;
+    line-height: 1;
+    width: 16px;
+    height: 16px;
+    color: #333;
+}
+.checkbox-custom label {
+    cursor: pointer;
+    line-height: 1.2;
+    font-weight: normal; /*改变了rememberme的字体*/
+    margin-bottom: 0;
+    text-align: left;
+}
+
+.form-control, .form-control:focus, .has-error .form-control:focus,  .has-success .form-control:focus, .has-warning .form-control:focus,  .navbar-collapse, .navbar-form, .navbar-form-custom .form-control:focus,  .navbar-form-custom .form-control:hover, .open .btn.dropdown-toggle,  .panel, .popover, .progress, .progress-bar {
+    box-shadow: none;
+}
+
+.form-control {
+    border-radius: 1px!important;
+    padding: 6px 12px!important;
+    height: 34px!important;
+}
+
+.form-control:focus {
+    border-color: #1ab394 !important;
+}
+
+body .layer-ext-moon-msg[type="dialog"]{
+    min-width: 100px !important;
+}
+body .layer-ext-moon-msg { 
+    background-color: rgba(0,0,0,0.6);
+    color: #fff;
+    border: none;
+}
+
+body .layer-ext-moon-msg .layui-layer-content{ 
+    padding: 12px 25px;
+    text-align: center;
+}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/css/login.min.css b/ruoyi-admin/src/main/resources/static/css/login.min.css
new file mode 100644
index 0000000..484ee2c
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/css/login.min.css
@@ -0,0 +1 @@
+html{height:100%}body.signin{height:auto;background:url(../img/login-background.jpg) no-repeat center fixed;-webkit-background-size:cover;-moz-background-size:cover;-o-background-size:cover;background-size:cover}.signinpanel{width:750px;margin:10% auto 0;color:rgba(255,255,255,.95)}.signinpanel .logopanel{float:none;width:auto;padding:0;background:0}.signinpanel .signin-info ul{list-style:none;padding:0;margin:20px 0}.signinpanel .form-control{display:block;margin-top:15px}.signinpanel .uname{background:#fff url(../img/user.png) no-repeat 95% center;color:#333}.signinpanel .pword{background:#fff url(../img/locked.png) no-repeat 95% center;color:#333}.signinpanel .code{background:#fff no-repeat 95% center;color:#333;margin:0 0 15px 0}.signinpanel .btn{margin-top:15px}.signinpanel form{background:rgba(255,255,255,.2);border:1px solid rgba(255,255,255,.3);-moz-box-shadow:0 3px 0 rgba(12,12,12,.03);-webkit-box-shadow:0 3px 0 rgba(12,12,12,.03);box-shadow:0 3px 0 rgba(12,12,12,.03);-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;padding:30px}.signup-footer{border-top:solid 1px rgba(255,255,255,.3);margin:20px 0;padding-top:15px}@media screen and (max-width:768px){.signinpanel,.signuppanel{margin:0 auto;width:380px!important;padding:20px}.signinpanel form{margin-top:20px}.signup-footer,.signuppanel .form-control{margin-bottom:10px}.signup-footer .pull-left,.signup-footer .pull-right{float:none!important;text-align:center}.signinpanel .signin-info ul{display:none}}@media screen and (max-width:320px){.signinpanel,.signuppanel{margin:0 20px;width:auto}}.checkbox-custom{position:relative;padding:0 15px 0 25px;margin-bottom:7px;display:inline-block}.checkbox-custom input[type="checkbox"]{opacity:0;position:absolute;cursor:pointer;z-index:2;margin:-6px 0 0 0;top:50%;left:3px}.checkbox-custom label:before{content:'';position:absolute;top:50%;left:0;margin-top:-9px;width:18px;height:17px;display:inline-block;border-radius:2px;border:1px solid #bbb;background:#fff}.checkbox-custom input[type="checkbox"]:checked+label:after{position:absolute;display:inline-block;font-family:'Glyphicons Halflings';content:"\e013";top:42%;left:3px;margin-top:-5px;font-size:11px;line-height:1;width:16px;height:16px;color:#333}.checkbox-custom label{cursor:pointer;line-height:1.2;font-weight:normal;margin-bottom:0;text-align:left}.form-control,.form-control:focus,.has-error .form-control:focus,.has-success .form-control:focus,.has-warning .form-control:focus,.navbar-collapse,.navbar-form,.navbar-form-custom .form-control:focus,.navbar-form-custom .form-control:hover,.open .btn.dropdown-toggle,.panel,.popover,.progress,.progress-bar{box-shadow:none}.form-control{border-radius:1px!important;padding:6px 12px!important;height:34px!important}.form-control:focus{border-color:#1ab394!important}body .layer-ext-moon-msg[type="dialog"]{min-width:100px!important}body .layer-ext-moon-msg{background-color:rgba(0,0,0,0.6);color:#fff;border:0}body .layer-ext-moon-msg .layui-layer-content{padding:12px 25px;text-align:center}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/css/skins.css b/ruoyi-admin/src/main/resources/static/css/skins.css
new file mode 100644
index 0000000..e55a3ed
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/css/skins.css
@@ -0,0 +1,1028 @@
+/*
+ *
+ *   SKIN blue 若依管理系统
+ *   NAME - blue/green/purple/red/yellow
+ *
+*/
+.nav-tabs {
+    border-bottom: 0px;
+}
+
+.navbar .navbar-toolbar>li>a {
+    border: none !important;
+}
+
+/** 蓝色主题 skin-blue **/
+.navbar, .skin-blue .navbar {
+	background-color: #3c8dbc
+}
+
+.skin-blue .navbar-default .nav>li.selected>a,
+.skin-blue .navbar-default .nav>li.selected>a:focus {
+	background-color: #1890ff;
+    color: rgba(255,255,255,1);
+}
+
+.skin-blue .navbar .nav>li>a {
+	color: #fff
+}
+
+.skin-blue .navbar .nav>li>a:hover,
+.skin-blue .navbar .nav>li>a:active,
+.skin-blue .navbar .nav>li>a:focus,
+.skin-blue .navbar .nav .open>a,
+.skin-blue .navbar .nav .open>a:hover,
+.skin-blue .navbar .nav .open>a:focus,
+.skin-blue .navbar .nav>.active>a {
+	background: rgba(0, 0, 0, 0.1);
+	color: #f6f6f6
+}
+
+.skin-blue .navbar .sidebar-toggle {
+	color: #fff
+}
+
+.skin-blue .navbar .sidebar-toggle:hover {
+	color: #f6f6f6;
+	background: rgba(0, 0, 0, 0.1)
+}
+
+.skin-blue .navbar .sidebar-toggle {
+	color: #fff
+}
+
+.skin-blue .navbar .sidebar-toggle:hover {
+	background-color: #367fa9
+}
+
+@media ( max-width :767px) {
+	.skin-blue .navbar .dropdown-menu li.divider {
+		background-color: rgba(255, 255, 255, 0.1)
+	}
+	.skin-blue .navbar .dropdown-menu li a {
+		color: #fff
+	}
+	.skin-blue .navbar .dropdown-menu li a:hover {
+		background: #367fa9
+	}
+}
+
+.skin-blue .logo {
+	background-color: #367fa9;
+	color: #fff;
+	border-bottom: 0 solid transparent
+}
+
+.skin-blue .logo:hover {
+	background-color: #357ca5
+}
+
+.skin-blue li.user-header {
+	background-color: #3c8dbc
+}
+
+.skin-blue .content-header {
+	background: transparent
+}
+
+.skin-blue .wrapper,
+.skin-blue .main-sidebar,
+.skin-blue .left-side {
+	background-color: #222d32
+}
+
+.skin-blue .user-panel>.info,
+.skin-blue .user-panel>.info>a {
+	color: #fff
+}
+
+.skin-blue .nav>li.header {
+	color: #4b646f;
+	background: #1a2226
+}
+
+.skin-blue .nav:not(.navbar-toolbar)>li.active {
+	color: #fff;
+	background: #293846;
+	border-left: 3px solid #3c8dbc;
+}
+
+.skin-blue .nav>li.active>ul li.active {
+	border-left: none;
+}
+
+.skin-blue .dropdown-menu > .active > a, .skin-blue .dropdown-menu > .active > a:hover, .skin-blue .dropdown-menu > .active > a:focus {
+    color: #fff !important;
+    text-decoration: none;
+    outline: 0;
+    background-color: #3c8dbc;
+}
+
+.skin-blue .sidebar a {
+	color: #b8c7ce
+}
+
+.skin-blue .sidebar a:hover {
+	text-decoration: none
+}
+
+.skin-blue .sidebar-form {
+	border-radius: 3px;
+	border: 1px solid #374850;
+	margin: 10px 10px
+}
+
+.skin-blue .sidebar-form input[type="text"],
+.skin-blue .sidebar-form .btn {
+	box-shadow: none;
+	background-color: #374850;
+	border: 1px solid transparent;
+	height: 35px
+}
+
+.skin-blue .sidebar-form input[type="text"] {
+	color: #666;
+	border-top-left-radius: 2px;
+	border-top-right-radius: 0;
+	border-bottom-right-radius: 0;
+	border-bottom-left-radius: 2px
+}
+
+.skin-blue .sidebar-form input[type="text"]:focus,
+.skin-blue .sidebar-form input[type="text"]:focus+.input-group-btn .btn {
+	background-color: #fff;
+	color: #666
+}
+
+.skin-blue .sidebar-form input[type="text"]:focus+.input-group-btn .btn {
+	border-left-color: #fff
+}
+
+.skin-blue .sidebar-form .btn {
+	color: #999;
+	border-top-left-radius: 0;
+	border-top-right-radius: 2px;
+	border-bottom-right-radius: 2px;
+	border-bottom-left-radius: 0
+}
+
+.skin-blue.layout-top-nav>.logo {
+	background-color: #3c8dbc;
+	color: #fff;
+	border-bottom: 0 solid transparent
+}
+
+.skin-blue.layout-top-nav>.logo:hover {
+	background-color: #3b8ab8
+}
+
+.skin-blue .content-tabs {
+	border-bottom: 1px solid #e5e5e5;
+}
+
+.skin-blue.layout-top-nav>.logo {
+	background-color: #3c8dbc;
+	color: #fff;
+	border-bottom: 0 solid transparent
+}
+
+.skin-blue.layout-top-nav>.logo:hover {
+	background-color: #3b8ab8
+}
+
+/** 绿色主题 skin-green **/
+.skin-green .navbar {
+	background-color: #00a65a;
+}
+
+.skin-green .navbar-default .nav>li.selected>a,
+.skin-green .navbar-default .nav>li.selected>a:focus {
+	background-color: #52c41a;
+    color: rgba(255,255,255,1);
+}
+
+.skin-green .content-tabs {
+	border-bottom: 1px solid #e5e5e5;
+}
+
+.skin-green .navbar .nav>li>a {
+	color: #fff
+}
+
+.skin-green .navbar .nav>li>a:hover,
+.skin-green .navbar .nav>li>a:active,
+.skin-green .navbar .nav>li>a:focus,
+.skin-green .navbar .nav .open>a,
+.skin-green .navbar .nav .open>a:hover,
+.skin-green .navbar .nav .open>a:focus,
+.skin-green .navbar .nav>.active>a {
+	background: rgba(0, 0, 0, 0.1);
+	color: #f6f6f6
+}
+
+.skin-green .navbar .sidebar-toggle {
+	color: #fff
+}
+
+.skin-green .navbar .sidebar-toggle:hover {
+	color: #f6f6f6;
+	background: rgba(0, 0, 0, 0.1)
+}
+
+.skin-green .navbar .sidebar-toggle {
+	color: #fff
+}
+
+.skin-green .navbar .sidebar-toggle:hover {
+	background-color: #008d4c
+}
+
+@media ( max-width :767px) {
+	.skin-green .navbar .dropdown-menu li.divider {
+		background-color: rgba(255, 255, 255, 0.1)
+	}
+	.skin-green .navbar .dropdown-menu li a {
+		color: #fff
+	}
+	.skin-green .navbar .dropdown-menu li a:hover {
+		background: #008d4c
+	}
+}
+
+.skin-green .logo {
+	background-color: #008d4c;
+	color: #fff;
+	border-bottom: 0 solid transparent
+}
+
+.skin-green .logo:hover {
+	background-color: #008749
+}
+
+.skin-green li.user-header {
+	background-color: #00a65a
+}
+
+.skin-green .content-header {
+	background: transparent
+}
+
+.skin-green .wrapper,
+.skin-green .main-sidebar,
+.skin-green .left-side {
+	background-color: #222d32
+}
+
+.skin-green .user-panel>.info,
+.skin-green .user-panel>.info>a {
+	color: #fff
+}
+
+.skin-green .nav>li.header {
+	color: #4b646f;
+	background: #1a2226;
+}
+
+.skin-green .nav:not(.navbar-toolbar)>li.active {
+	color: #fff;
+	background: #293846;
+	border-left: 3px solid #00a65a;
+}
+
+.skin-green .nav>li.active>ul li.active {
+	border-left: none;
+}
+
+.skin-green .dropdown-menu > .active > a, .skin-green .dropdown-menu > .active > a:hover, .skin-green .dropdown-menu > .active > a:focus {
+    color: #fff !important;
+    text-decoration: none;
+    outline: 0;
+    background-color: #00a65a;
+}
+
+.skin-green .sidebar a {
+	color: #b8c7ce
+}
+
+.skin-green .sidebar a:hover {
+	text-decoration: none
+}
+
+.skin-green .sidebar-form {
+	border-radius: 3px;
+	border: 1px solid #374850;
+	margin: 10px 10px
+}
+
+.skin-green .sidebar-form input[type="text"],
+.skin-green .sidebar-form .btn {
+	box-shadow: none;
+	background-color: #374850;
+	border: 1px solid transparent;
+	height: 35px
+}
+
+.skin-green .sidebar-form input[type="text"] {
+	color: #666;
+	border-top-left-radius: 2px;
+	border-top-right-radius: 0;
+	border-bottom-right-radius: 0;
+	border-bottom-left-radius: 2px
+}
+
+.skin-green .sidebar-form input[type="text"]:focus,
+.skin-green .sidebar-form input[type="text"]:focus+.input-group-btn .btn {
+	background-color: #fff;
+	color: #666
+}
+
+.skin-green .sidebar-form input[type="text"]:focus+.input-group-btn .btn {
+	border-left-color: #fff
+}
+
+.skin-green .sidebar-form .btn {
+	color: #999;
+	border-top-left-radius: 0;
+	border-top-right-radius: 2px;
+	border-bottom-right-radius: 2px;
+	border-bottom-left-radius: 0
+}
+
+/** 红色主题 skin-red **/
+.skin-red .navbar {
+	background-color: #dd4b39
+}
+
+.skin-red .navbar-default .nav>li.selected>a,
+.skin-red .navbar-default .nav>li.selected>a:focus {
+	background-color: #f5222d;
+    color: rgba(255,255,255,1);
+}
+
+.skin-red .navbar .nav>li>a {
+	color: #fff
+}
+
+.skin-red .navbar .nav>li>a:hover,
+.skin-red .navbar .nav>li>a:active,
+.skin-red .navbar .nav>li>a:focus,
+.skin-red .navbar .nav .open>a,
+.skin-red .navbar .nav .open>a:hover,
+.skin-red .navbar .nav .open>a:focus,
+.skin-red .navbar .nav>.active>a {
+	background: rgba(0, 0, 0, 0.1);
+	color: #f6f6f6
+}
+
+.skin-red .navbar .sidebar-toggle {
+	color: #fff
+}
+
+.skin-red .navbar .sidebar-toggle:hover {
+	color: #f6f6f6;
+	background: rgba(0, 0, 0, 0.1)
+}
+
+.skin-red .navbar .sidebar-toggle {
+	color: #fff
+}
+
+.skin-red .navbar .sidebar-toggle:hover {
+	background-color: #d73925
+}
+
+@media ( max-width :767px) {
+	.skin-red .navbar .dropdown-menu li.divider {
+		background-color: rgba(255, 255, 255, 0.1)
+	}
+	.skin-red .navbar .dropdown-menu li a {
+		color: #fff
+	}
+	.skin-red .navbar .dropdown-menu li a:hover {
+		background: #d73925
+	}
+}
+
+.skin-red .logo {
+	background-color: #d73925;
+	color: #fff;
+	border-bottom: 0 solid transparent
+}
+
+.skin-red .logo:hover {
+	background-color: #d33724
+}
+
+.skin-red li.user-header {
+	background-color: #dd4b39
+}
+
+.skin-red .content-header {
+	background: transparent
+}
+
+.skin-red .wrapper,
+.skin-red .main-sidebar,
+.skin-red .left-side {
+	background-color: #222d32
+}
+
+.skin-red .user-panel>.info,
+.skin-red .user-panel>.info>a {
+	color: #fff
+}
+
+.skin-red .nav>li.header {
+	color: #4b646f;
+	background: #1a2226
+}
+
+.skin-red .nav:not(.navbar-toolbar)>li.active {
+	color: #fff;
+	border-left: 3px solid #dd4b39;
+	background: #293846;
+}
+
+.skin-red .nav>li.active>ul li.active {
+	border-left: none;
+}
+
+.skin-red .dropdown-menu > .active > a, .skin-red .dropdown-menu > .active > a:hover, .skin-red .dropdown-menu > .active > a:focus {
+    color: #fff !important;
+    text-decoration: none;
+    outline: 0;
+    background-color: #dd4b39;
+}
+
+.skin-red .content-tabs {
+	border-bottom: 1px solid #e5e5e5;
+}
+
+.skin-red .sidebar a {
+	color: #b8c7ce
+}
+
+.skin-red .sidebar a:hover {
+	text-decoration: none
+}
+
+.skin-red .sidebar-form {
+	border-radius: 3px;
+	border: 1px solid #374850;
+	margin: 10px 10px
+}
+
+.skin-red .sidebar-form input[type="text"],
+.skin-red .sidebar-form .btn {
+	box-shadow: none;
+	background-color: #374850;
+	border: 1px solid transparent;
+	height: 35px
+}
+
+.skin-red .sidebar-form input[type="text"] {
+	color: #fff;
+	border-top-left-radius: 2px;
+	border-top-right-radius: 0;
+	border-bottom-right-radius: 0;
+	border-bottom-left-radius: 2px
+}
+
+.skin-red .sidebar-form input[type="text"]:focus,
+.skin-red .sidebar-form input[type="text"]:focus+.input-group-btn .btn {
+	background-color: #fff;
+	color: #666
+}
+
+.skin-red .sidebar-form input[type="text"]:focus+.input-group-btn .btn {
+	border-left-color: #fff
+}
+
+.skin-red .sidebar-form .btn {
+	color: #999;
+	border-top-left-radius: 0;
+	border-top-right-radius: 2px;
+	border-bottom-right-radius: 2px;
+	border-bottom-left-radius: 0
+}
+
+/** 黄色主题 skin-red **/
+.skin-yellow .navbar {
+	background-color: #f39c12
+}
+
+.skin-yellow .navbar-default .nav>li.selected>a,
+.skin-yellow .navbar-default .nav>li.selected>a:focus {
+	background-color: #faad14;
+    color: rgba(255,255,255,1);
+}
+
+.skin-yellow .navbar .nav>li>a {
+	color: #fff
+}
+
+.skin-yellow .navbar .nav>li>a:hover,
+.skin-yellow .navbar .nav>li>a:active,
+.skin-yellow .navbar .nav>li>a:focus,
+.skin-yellow .navbar .nav .open>a,
+.skin-yellow .navbar .nav .open>a:hover,
+.skin-yellow .navbar .nav .open>a:focus,
+.skin-yellow .navbar .nav>.active>a {
+	background: rgba(0, 0, 0, 0.1);
+	color: #f6f6f6
+}
+
+.skin-yellow .navbar .sidebar-toggle {
+	color: #fff
+}
+
+.skin-yellow .navbar .sidebar-toggle:hover {
+	color: #f6f6f6;
+	background: rgba(0, 0, 0, 0.1)
+}
+
+.skin-yellow .navbar .sidebar-toggle {
+	color: #fff
+}
+
+.skin-yellow .navbar .sidebar-toggle:hover {
+	background-color: #e08e0b
+}
+
+@media ( max-width :767px) {
+	.skin-yellow .navbar .dropdown-menu li.divider {
+		background-color: rgba(255, 255, 255, 0.1)
+	}
+	.skin-yellow .navbar .dropdown-menu li a {
+		color: #fff
+	}
+	.skin-yellow .navbar .dropdown-menu li a:hover {
+		background: #e08e0b
+	}
+}
+
+.skin-yellow .logo {
+	background-color: #e08e0b;
+	color: #fff;
+	border-bottom: 0 solid transparent
+}
+
+.skin-yellow .logo:hover {
+	background-color: #db8b0b
+}
+
+.skin-yellow li.user-header {
+	background-color: #f39c12
+}
+
+.skin-yellow .content-header {
+	background: transparent
+}
+
+.skin-yellow .wrapper,
+.skin-yellow .main-sidebar,
+.skin-yellow .left-side {
+	background-color: #222d32
+}
+
+.skin-yellow .user-panel>.info,
+.skin-yellow .user-panel>.info>a {
+	color: #fff
+}
+
+.skin-yellow .nav>li.header {
+	color: #4b646f;
+	background: #1a2226
+}
+
+.skin-yellow .nav:not(.navbar-toolbar)>li.active {
+	color: #fff;
+	background: #293846;
+	border-left: 3px solid #f39c12;
+}
+
+.skin-yellow .nav>li.active>ul li.active {
+	border-left: none;
+}
+
+.skin-yellow .dropdown-menu > .active > a, .skin-yellow .dropdown-menu > .active > a:hover, .skin-yellow .dropdown-menu > .active > a:focus {
+    color: #fff !important;
+    text-decoration: none;
+    outline: 0;
+    background-color: #f39c12;
+}
+
+.skin-yellow .content-tabs {
+	 border-bottom: 1px solid #e5e5e5;
+}
+
+.skin-yellow .sidebar a {
+	color: #b8c7ce
+}
+
+.skin-yellow .sidebar a:hover {
+	text-decoration: none
+}
+
+.skin-yellow .sidebar-form {
+	border-radius: 3px;
+	border: 1px solid #374850;
+	margin: 10px 10px
+}
+
+.skin-yellow .sidebar-form input[type="text"],
+.skin-yellow .sidebar-form .btn {
+	box-shadow: none;
+	background-color: #374850;
+	border: 1px solid transparent;
+	height: 35px
+}
+
+.skin-yellow .sidebar-form input[type="text"] {
+	color: #666;
+	border-top-left-radius: 2px;
+	border-top-right-radius: 0;
+	border-bottom-right-radius: 0;
+	border-bottom-left-radius: 2px
+}
+
+.skin-yellow .sidebar-form input[type="text"]:focus,
+.skin-yellow .sidebar-form input[type="text"]:focus+.input-group-btn .btn {
+	background-color: #fff;
+	color: #666
+}
+
+.skin-yellow .sidebar-form input[type="text"]:focus+.input-group-btn .btn {
+	border-left-color: #fff
+}
+
+.skin-yellow .sidebar-form .btn {
+	color: #999;
+	border-top-left-radius: 0;
+	border-top-right-radius: 2px;
+	border-bottom-right-radius: 2px;
+	border-bottom-left-radius: 0
+}
+
+/** 紫色主题 skin-purple **/
+.skin-purple .navbar {
+	background-color: #605ca8
+}
+
+.skin-purple .navbar-default .nav>li.selected>a,
+.skin-purple .navbar-default .nav>li.selected>a:focus {
+	background-color: #722ed1;
+    color: rgba(255,255,255,1);
+}
+
+.skin-purple .navbar .nav>li>a {
+	color: #fff
+}
+
+.skin-purple .navbar .nav>li>a:hover,
+.skin-purple .navbar .nav>li>a:active,
+.skin-purple .navbar .nav>li>a:focus,
+.skin-purple .navbar .nav .open>a,
+.skin-purple .navbar .nav .open>a:hover,
+.skin-purple .navbar .nav .open>a:focus,
+.skin-purple .navbar .nav>.active>a {
+	background: rgba(0, 0, 0, 0.1);
+	color: #f6f6f6
+}
+
+.skin-purple .navbar .sidebar-toggle {
+	color: #fff
+}
+
+.skin-purple .navbar .sidebar-toggle:hover {
+	color: #f6f6f6;
+	background: rgba(0, 0, 0, 0.1)
+}
+
+.skin-purple .navbar .sidebar-toggle {
+	color: #fff
+}
+
+.skin-purple .navbar .sidebar-toggle:hover {
+	background-color: #555299
+}
+
+@media ( max-width :767px) {
+	.skin-purple .navbar .dropdown-menu li.divider {
+		background-color: rgba(255, 255, 255, 0.1)
+	}
+	.skin-purple .navbar .dropdown-menu li a {
+		color: #fff
+	}
+	.skin-purple .navbar .dropdown-menu li a:hover {
+		background: #555299
+	}
+}
+
+.skin-purple .logo {
+	background-color: #555299;
+	color: #fff;
+	border-bottom: 0 solid transparent
+}
+
+.skin-purple .logo:hover {
+	background-color: #545096
+}
+
+.skin-purple li.user-header {
+	background-color: #605ca8
+}
+
+.skin-purple .content-header {
+	background: transparent
+}
+
+.skin-purple .wrapper,
+.skin-purple .main-sidebar,
+.skin-purple .left-side {
+	background-color: #222d32
+}
+
+.skin-purple .user-panel>.info,
+.skin-purple .user-panel>.info>a {
+	color: #fff
+}
+
+.skin-purple .nav>li.header {
+	color: #4b646f;
+	background: #1a2226
+}
+
+.skin-purple .nav:not(.navbar-toolbar)>li.active {
+	color: #fff;
+	background: #293846;
+	border-left: 3px solid #605ca8;
+}
+
+.skin-purple .nav>li.active>ul li.active {
+	border-left: none;
+}
+
+.skin-purple .dropdown-menu > .active > a, .skin-purple .dropdown-menu > .active > a:hover, .skin-purple .dropdown-menu > .active > a:focus {
+    color: #fff !important;
+    text-decoration: none;
+    outline: 0;
+    background-color: #605ca8;
+}
+
+.skin-purple .content-tabs {
+	 border-bottom: 1px solid #e5e5e5;
+}
+
+.skin-purple .sidebar a {
+	color: #b8c7ce
+}
+
+.skin-purple .sidebar a:hover {
+	text-decoration: none
+}
+
+.skin-purple .sidebar-form {
+	border-radius: 3px;
+	border: 1px solid #374850;
+	margin: 10px 10px
+}
+
+.skin-purple .sidebar-form input[type="text"],
+.skin-purple .sidebar-form .btn {
+	box-shadow: none;
+	background-color: #374850;
+	border: 1px solid transparent;
+	height: 35px
+}
+
+.skin-purple .sidebar-form input[type="text"] {
+	color: #666;
+	border-top-left-radius: 2px;
+	border-top-right-radius: 0;
+	border-bottom-right-radius: 0;
+	border-bottom-left-radius: 2px
+}
+
+.skin-purple .sidebar-form input[type="text"]:focus,
+.skin-purple .sidebar-form input[type="text"]:focus+.input-group-btn .btn {
+	background-color: #fff;
+	color: #666
+}
+
+.skin-purple .sidebar-form input[type="text"]:focus+.input-group-btn .btn {
+	border-left-color: #fff
+}
+
+.skin-purple .sidebar-form .btn {
+	color: #999;
+	border-top-left-radius: 0;
+	border-top-right-radius: 2px;
+	border-bottom-right-radius: 2px;
+	border-bottom-left-radius: 0
+}
+
+/*
+ *
+ *   侧边栏主题 若依管理系统
+ *   NAME - .theme-dark/theme-light
+ *
+*/
+/** 深黑主题 .theme-dark **/
+.theme-dark .user-panel>.info>p, .theme-dark .user-panel>.info, .theme-dark .user-panel>.info>a{
+	color: #fff
+}
+
+.theme-dark .nav:not(.navbar-toolbar)>li.active {
+	background: #293846;
+}
+
+.theme-dark .navbar-static-side {
+	background-color: #2f4050;
+}
+
+.theme-dark .user-panel {
+	background-color: #2f4050;
+}
+
+.theme-dark .navbar-default .nav>li>a:hover,
+.theme-dark .navbar-default .nav>li>a:focus {
+	background: #293846;
+}
+
+/** 浅色主题 theme-light **/
+.theme-light .user-panel>.info>p, .theme-light .user-panel>.info, .theme-light .user-panel>.info>a{
+	color: #555
+}
+
+.theme-light .nav:not(.navbar-toolbar)>li.active{
+	background: #f9fafc;
+}
+
+.theme-light .navbar-static-side {
+	background-color: #f9fafc;
+	box-shadow: 2px 0 2px 0 rgba(29,35,41,.05);
+}
+
+.theme-light .user-panel {
+	background-color: #f9fafc;
+}
+
+.theme-light .navbar-default .nav>li>a {
+	color: #777;
+}
+
+.theme-light.skin-blue .navbar-default .nav>li.active>a {
+	color: #1890ff;
+}
+
+.theme-light.skin-blue .navbar-default .nav>li.selected>a,
+.theme-light.skin-blue .navbar-default .nav>li.selected>a:focus {
+	background-color: rgb(240, 245, 255);
+	color: rgb(47, 84, 235);
+}
+
+.theme-light.skin-green .navbar-default .nav>li.active>a {
+	color: #52c41a;
+}
+
+.theme-light.skin-green .navbar-default .nav>li.selected>a,
+.theme-light.skin-green .navbar-default .nav>li.selected>a:focus {
+	background-color: rgb(246, 255, 237);
+	color: rgb(82, 196, 26);
+}
+
+.theme-light.skin-purple .navbar-default .nav>li.active>a {
+	color: rgb(114, 46, 209);
+}
+
+.theme-light.skin-purple .navbar-default .nav>li.selected>a,
+.theme-light.skin-purple .navbar-default .nav>li.selected>a:focus {
+	background-color: #f9f0ff;
+	color: #722ed1;
+}
+
+.theme-light.skin-red .navbar-default .nav>li.active>a {
+	color: rgb(245, 34, 45);
+}
+
+.theme-light.skin-red .navbar-default .nav>li.selected>a,
+.theme-light.skin-red .navbar-default .nav>li.selected>a:focus {
+	background-color: rgb(255, 241, 240);
+	color: rgb(245, 34, 45);
+}
+
+.theme-light.skin-yellow .navbar-default .nav>li.active>a {
+	color: rgb(250, 173, 20);
+}
+
+.theme-light.skin-yellow .navbar-default .nav>li.selected>a,
+.theme-light.skin-yellow .navbar-default .nav>li.selected>a:focus {
+	background-color: #fffbe6;
+	color: #faad14;
+}
+
+.theme-light .navbar-default .nav>li>a:hover,
+.theme-light .navbar-default .nav>li>a:focus {
+	background-color: rgb(240, 245, 255);
+}
+
+.fixed-sidebar.theme-light.mini-navbar .nav li:hover>a> span.nav-label {
+    background-color: #f9fafc;
+}
+
+.fixed-sidebar.theme-light.mini-navbar .nav li:hover>.nav-second-level {
+    background-color: #f9fafc;
+}
+
+/** 深蓝主题 theme-light **/
+/**
+.skin-blue.theme-blue .logo, .skin-white.theme-blue .logo {
+	background-color: rgba(15,41,80,1) !important;
+	color: #fff;
+}
+**/
+.theme-blue .user-panel>.info>p, .theme-blue .user-panel>.info, .theme-blue .user-panel>.info>a{
+	color: #a3b1cc
+}
+
+.theme-blue .nav:not(.navbar-toolbar)>li.active{
+	background-color: rgba(15,41,80,1);
+}
+
+.theme-blue .navbar-static-side {
+	background-color: rgba(15,41,80,1);
+	box-shadow: 2px 0 2px 0 rgba(29,35,41,.05);
+}
+
+.theme-blue .user-panel {
+	background-color: rgba(15,41,80,1);
+}
+
+.theme-blue .navbar-default .nav>li>a {
+	color: #a3b1cc;
+}
+
+.theme-blue.skin-blue .navbar-default .nav>li.active>a {
+	color: #1890ff;
+}
+
+.theme-blue.skin-blue .navbar-default .nav>li.selected>a,
+.theme-blue.skin-blue .navbar-default .nav>li.selected>a:focus {
+	background-color: #1890ff;
+	color: rgba(255,255,255,1);
+}
+
+.theme-blue.skin-green .navbar-default .nav>li.active>a {
+	color: #52c41a;
+}
+
+.theme-blue.skin-green .navbar-default .nav>li.selected>a,
+.theme-blue.skin-green .navbar-default .nav>li.selected>a:focus {
+	background-color: #52c41a;
+    color: rgba(255,255,255,1);
+}
+
+.theme-blue.skin-purple .navbar-default .nav>li.active>a {
+	color: rgb(114, 46, 209);
+}
+
+.theme-blue.skin-purple .navbar-default .nav>li.selected>a,
+.theme-blue.skin-purple .navbar-default .nav>li.selected>a:focus {
+	background-color: #722ed1;
+    color: rgba(255,255,255,1);
+}
+
+.theme-blue.skin-red .navbar-default .nav>li.active>a {
+	color: rgb(245, 34, 45);
+}
+
+.theme-blue.skin-red .navbar-default .nav>li.selected>a,
+.theme-blue.skin-red .navbar-default .nav>li.selected>a:focus {
+	background-color: #f5222d;
+    color: rgba(255,255,255,1);
+}
+
+.theme-blue.skin-yellow .navbar-default .nav>li.active>a {
+	color: rgb(250, 173, 20);
+}
+
+.theme-blue.skin-yellow .navbar-default .nav>li.selected>a,
+.theme-blue.skin-yellow .navbar-default .nav>li.selected>a:focus {
+	background-color: #faad14;
+    color: rgba(255,255,255,1);
+}
+
+.theme-blue .navbar-default .nav>li>a:hover,
+.theme-blue .navbar-default .nav>li>a:focus {
+	background-color: rgba(15,41,80,1);
+	box-shadow: 2px 0 2px 0 rgba(29,35,41,.05);
+}
+
+.fixed-sidebar.theme-blue.mini-navbar .nav li:hover>a> span.nav-label {
+    background-color: rgba(15,41,80,1);
+}
+
+.fixed-sidebar.theme-blue.mini-navbar .nav li:hover>.nav-second-level {
+    background-color: rgba(15,41,80,1);
+}
diff --git a/ruoyi-admin/src/main/resources/static/css/style.css b/ruoyi-admin/src/main/resources/static/css/style.css
new file mode 100644
index 0000000..897b219
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/css/style.css
@@ -0,0 +1,7047 @@
+h1, h2, h3, h4, h5, h6 {
+    font-weight: 100;
+}
+
+h1 {
+    font-size: 30px;
+}
+
+h2 {
+    font-size: 24px;
+}
+
+h3 {
+    font-size: 16px;
+}
+
+h4 {
+    font-size: 14px;
+}
+
+h5 {
+    font-size: 12px;
+}
+
+h6 {
+    font-size: 10px;
+}
+
+h3, h4, h5 {
+    margin-top: 5px;
+    font-weight: 600;
+}
+
+a:focus {
+    outline: none;
+}
+
+.nav>li>a {
+    color: #a7b1c2;
+    font-weight: 600;
+    padding: 14px 20px 14px 25px;
+}
+
+.nav li>a {
+    display: block;
+    /*white-space: nowrap;*/
+}
+
+.nav.navbar-right>li>a, .nav.navbar-left>li>a {
+	color: #fff;
+	font-size: 14px;
+	height: 50px;
+	padding: 15px 15px;
+}
+
+.nav>li.active>a {
+    color: #ffffff;
+}
+
+.nav.navbar-right>li>a>.label, .nav.navbar-left>li>a>.label {
+	position: absolute;
+	top: 9px;
+	right: 5px;
+	text-align: center;
+	font-size: 9px;
+	padding: 2px 4px;
+	line-height: .9;
+}
+.nav.navbar-right>li>a:hover, .nav.navbar-left>li>a:hover {
+	background-color: #367fa9;
+	color: #fff;
+}
+
+.navbar-default .nav>li>a:hover,
+.navbar-default .nav>li>a:focus {
+	background-color: #293846;
+	color: white;
+}
+
+.nav .open>a,
+.nav .open>a:hover,
+.nav .open>a:focus {
+	background: #fff;
+}
+
+.navbar {
+	border: 0;
+}
+
+.navbar-default {
+    background-color: transparent;
+    border-color: #2f4050;
+    position: relative;
+}
+
+.nav.navbar-top-links li {
+	display: inline-block;
+}
+
+.navbar-top-links li:last-child {
+    margin-right: 16px;
+}
+
+body.body-small .navbar-top-links li:last-child {
+    margin-right: 10px;
+}
+
+.navbar-top-links li a {
+    padding: 20px 10px;
+    min-height: 50px;
+}
+
+.dropdown-menu {
+    border: medium none;
+    display: none;
+    float: left;
+    font-size: 12px;
+    left: 0;
+    list-style: none outside none;
+    padding: 0;
+    position: absolute;
+    text-shadow: none;
+    top: 100%;
+    z-index: 1000;
+    border-radius: 0;
+    box-shadow: 0 0 3px rgba(86, 96, 117, 0.3);
+}
+
+.dropdown-menu>li>a {
+    border-radius: 3px;
+    color: inherit;
+    line-height: 25px;
+    margin: 4px;
+    text-align: left;
+    font-weight: normal;
+}
+
+.dropdown-menu>li>a.font-bold {
+    font-weight: 600;
+}
+
+.navbar-top-links .dropdown-menu li {
+    display: block;
+}
+
+.navbar-top-links .dropdown-menu li:last-child {
+    margin-right: 0;
+}
+
+.navbar-top-links .dropdown-menu li a {
+    padding: 3px 20px;
+    min-height: 0;
+}
+
+.navbar-top-links .dropdown-menu li a div {
+    white-space: normal;
+}
+
+.navbar-top-links .dropdown-messages, .navbar-top-links .dropdown-tasks,  .navbar-top-links .dropdown-alerts {
+    width: 310px;
+    min-width: 0;
+}
+
+.navbar-top-links .dropdown-messages {
+    margin-left: 5px;
+}
+
+.navbar-top-links .dropdown-tasks {
+    margin-left: -59px;
+}
+
+.navbar-top-links .dropdown-alerts {
+    margin-left: -123px;
+}
+
+.navbar-top-links .dropdown-user {
+    right: 0;
+    left: auto;
+}
+
+.dropdown-messages, .dropdown-alerts {
+    padding: 10px 10px 10px 10px;
+}
+
+.dropdown-messages li a, .dropdown-alerts li a {
+    font-size: 12px;
+}
+
+.dropdown-messages li em, .dropdown-alerts li em {
+    font-size: 10px;
+}
+
+.nav.navbar-top-links .dropdown-alerts a {
+    font-size: 12px;
+}
+
+.nav>li.active {
+    border-left: 4px solid #19aa8d;
+    background: #293846;
+}
+
+.nav.nav-second-level>li.active {
+    border: none;
+}
+
+.nav.nav-second-level.collapse[style] {
+    height: auto !important;
+}
+
+.nav-header a {
+    color: #DFE4ED;
+}
+
+.nav-header .text-muted {
+    color: #8095a8;
+}
+
+.minimalize-styl-2 {
+    padding: 4px 12px;
+    margin: 12px 5px 5px 15px;
+    font-size: 14px;
+    float: left;
+}
+
+.navbar-form-custom {
+    float: left;
+    height: 50px;
+    padding: 0;
+    width: 200px;
+    display: inline-table;
+}
+
+.navbar-form-custom .form-group {
+    margin-bottom: 0;
+}
+
+.nav.navbar-top-links a {
+    font-size: 14px;
+}
+
+.navbar-form-custom .form-control {
+    background: none repeat scroll 0 0 rgba(0, 0, 0, 0);
+    border: medium none;
+    font-size: 14px;
+    height: 60px;
+    margin: 0;
+    z-index: 2000;
+}
+
+.count-info .label {
+    line-height: 12px;
+    padding: 1px 5px;
+    position: absolute;
+    right: 6px;
+    top: 12px;
+}
+
+.arrow {
+    float: right;
+    margin-top: 2px;
+}
+
+.fa.arrow:before {
+    content: "\f104";
+}
+
+.active>a>.fa.arrow:before {
+    content: "\f107";
+}
+
+.nav-second-level li, .nav-third-level li {
+    border-bottom: none !important;
+    padding-left: 2px;
+    padding-right: 2px;
+}
+
+.nav-second-level li a {
+    padding: 7px 15px 7px 10px;
+    padding-left: 52px;
+}
+
+.nav-third-level li a {
+    padding-left: 70px;
+}
+
+.nav-second-level li:last-child {
+    margin-bottom: 10px;
+}
+
+body:not(.fixed-sidebar ):not(.canvas-menu ).mini-navbar .nav li:hover>.nav-second-level,.mini-navbar .nav li:focus>.nav-second-level {
+    display: block;
+    border-radius: 0 2px 2px 0;
+    min-width: 140px;
+    height: auto;
+}
+
+body.mini-navbar .navbar-default .nav>li>.nav-second-level li a {
+    font-size: 12px;
+    border-radius: 0 2px 2px 0;
+}
+
+body.mini-navbar .navbar-default .nav>li>.nav-third-level li a {
+    padding-left: 31px;
+}
+
+.fixed-nav .slimScrollDiv #side-menu {
+    padding-bottom: 60px;
+    position: relative;
+}
+
+.fixed-sidebar.mini-navbar .slimScrollDiv>* {
+    overflow: visible!important;
+}
+
+.fixed-sidebar .slimScrollDiv>* {
+    overflow-y: hidden;
+    overflow-x: visible;
+}
+
+.mini-navbar .nav-second-level li a {
+    padding: 10px 10px 10px 15px;
+}
+
+.canvas-menu.mini-navbar .nav-second-level {
+    background: #293846;
+}
+
+.mini-navbar li.active .nav-second-level {
+    left: 65px;
+}
+
+.navbar-default .special_link a {
+    background: #1ab394;
+    color: white;
+}
+
+.navbar-default .special_link a:hover {
+    background: #17987e !important;
+    color: white;
+}
+
+.navbar-default .special_link a span.label {
+    background: #fff;
+    color: #1ab394;
+}
+
+.navbar-default .landing_link a {
+    background: #1cc09f;
+    color: white;
+}
+
+.navbar-default .landing_link a:hover {
+    background: #1ab394 !important;
+    color: white;
+}
+
+.navbar-default .landing_link a span.label {
+    background: #fff;
+    color: #1cc09f;
+}
+
+.logo-element {
+    text-align: center;
+    font-size: 18px;
+    font-weight: 600;
+    color: white;
+    display: none;
+    padding: 18px 0;
+}
+
+.navbar-fixed-top {
+    background: #fff;
+    -webkit-transition-duration: 0.5s;
+    transition-duration: 0.5s;
+    z-index: 2030;
+}
+
+.fixed-nav #wrapper {
+    padding-top: 60px;
+    box-sizing: border-box;
+}
+
+.fixed-nav .minimalize-styl-2 {
+    margin: 14px 5px 5px 15px;
+}
+
+.body-small .navbar-fixed-top {
+    margin-left: 0px;
+}
+
+body.mini-navbar .navbar-static-side {
+    width: 70px;
+}
+
+body.mini-navbar .profile-element, body.mini-navbar .nav-label, body.mini-navbar .navbar-default .nav li a span {
+    display: none;
+}
+
+body.canvas-menu .profile-element {
+    display: block;
+}
+
+body:not(.fixed-sidebar ):not(.canvas-menu ).mini-navbar .nav-second-level {
+    display: none;
+}
+
+body.mini-navbar .navbar-default .nav>li>a {
+    font-size: 16px;
+}
+
+body.mini-navbar .logo-element {
+    display: block;
+}
+
+body.canvas-menu .logo-element {
+    display: none;
+}
+
+body.mini-navbar .nav-header {
+    padding: 0;
+    background-color: #1ab394;
+}
+
+body.canvas-menu .nav-header {
+    padding: 33px 25px;
+}
+
+body.mini-navbar #page-wrapper {
+    margin: 0 0 0 70px;
+}
+
+body.canvas-menu.mini-navbar #page-wrapper, body.canvas-menu.mini-navbar .footer {
+    margin: 0 0 0 0;
+}
+
+body.fixed-sidebar .navbar-static-side, body.canvas-menu .navbar-static-side {
+    position: fixed;
+    width: 200px;
+    z-index: 2001;
+    height: 100%;
+}
+
+body.fixed-sidebar.mini-navbar .navbar-static-side {
+    width: 70px;
+}
+
+body.fixed-sidebar.mini-navbar #page-wrapper {
+    margin: 0 0 0 70px;
+}
+
+body.body-small.fixed-sidebar.mini-navbar #page-wrapper {
+    margin: 0 0 0 70px;
+}
+
+body.body-small.fixed-sidebar.mini-navbar .navbar-static-side {
+    width: 70px;
+}
+
+.fixed-sidebar.mini-navbar .nav li>.nav-second-level {
+    display: none;
+}
+
+.fixed-sidebar.mini-navbar .nav li.active {
+    border-left-width: 0;
+}
+
+/* 伸缩菜单 */
+.fixed-sidebar.mini-navbar .nav li:hover>a> span.nav-label {
+    top: 0px;
+    padding: 10px 10px 10px 10px;
+    text-align: center;
+    background-color: #243747;
+}
+
+.fixed-sidebar.mini-navbar .nav li:hover>.nav-second-level {
+    top: 40px;
+    font-size: 12px;
+    background-color: #2f4050;
+}
+
+.fixed-sidebar.mini-navbar .nav li:hover>.nav-second-level, .fixed-sidebar.mini-navbar .nav li:hover>a> span.nav-label {
+    position: absolute;
+    left: 70px;
+    display: block;
+    min-width: 140px;
+    border-radius: 2px;
+}
+
+.fixed-sidebar.mini-navbar .nav li.active:hover>.nav-second-level, .fixed-sidebar.mini-navbar .nav li.active:hover>a> span.nav-label {
+    left: 67px;
+}
+
+.fixed-sidebar.mini-navbar .nav .nav-second-level a> span, .fixed-sidebar.mini-navbar .nav .nav-third-level a> span {
+    display: inline-block;
+}
+
+/*伸缩菜单结束*/
+
+body.fixed-sidebar.mini-navbar .navbar-default .nav>li>.nav-second-level li a {
+    font-size: 12px;
+    border-radius: 3px;
+}
+
+body.canvas-menu.mini-navbar .navbar-default .nav>li>.nav-second-level li a {
+    font-size: 13px;
+    border-radius: 3px;
+}
+
+.fixed-sidebar.mini-navbar .nav-second-level li a, .canvas-menu.mini-navbar .nav-second-level li a {
+    padding: 10px 10px 10px 15px;
+}
+
+.fixed-sidebar.mini-navbar .nav-second-level, .canvas-menu.mini-navbar .nav-second-level {
+    position: relative;
+    padding: 0;
+    font-size: 13px;
+}
+
+.fixed-sidebar.mini-navbar li.active .nav-second-level, .canvas-menu.mini-navbar li.active .nav-second-level {
+    left: 0px;
+}
+
+body.canvas-menu nav.navbar-static-side {
+    z-index: 2001;
+    background: #2f4050;
+    height: 100%;
+    position: fixed;
+    display: none;
+}
+
+body.canvas-menu.mini-navbar nav.navbar-static-side {
+    display: block;
+    width: 70px;
+}
+
+.top-navigation #page-wrapper {
+    margin-left: 0;
+}
+
+.top-navigation .navbar-nav .dropdown-menu>.active>a {
+    background: white;
+    color: #1ab394;
+    font-weight: bold;
+}
+
+.white-bg .navbar-fixed-top, .white-bg .navbar-static-top {
+    background: #fff;
+}
+
+.top-navigation .navbar {
+    margin-bottom: 0;
+}
+
+.top-navigation .nav>li>a {
+    padding: 15px 20px;
+    color: #676a6c;
+}
+
+.top-navigation .nav>li a:hover, .top-navigation .nav>li a:focus {
+    background: #fff;
+    color: #1ab394;
+}
+
+.top-navigation .nav>li.active {
+    background: #fff;
+    border: none;
+}
+
+.top-navigation .nav>li.active>a {
+    color: #1ab394;
+}
+
+.top-navigation .navbar-right {
+    padding-right: 10px;
+}
+
+.top-navigation .navbar-nav .dropdown-menu {
+    box-shadow: none;
+    border: 1px solid #e7eaec;
+}
+
+.top-navigation .dropdown-menu>li>a {
+    margin: 0;
+    padding: 7px 20px;
+}
+
+.navbar .dropdown-menu {
+    margin-top: 0px;
+}
+
+.top-navigation .navbar-brand {
+    background: #1ab394;
+    color: #fff;
+    padding: 15px 25px;
+}
+
+.top-navigation .navbar-top-links li:last-child {
+    margin-right: 0;
+}
+
+.top-navigation.mini-navbar #page-wrapper, .top-navigation.body-small.fixed-sidebar.mini-navbar #page-wrapper,  .mini-navbar .top-navigation #page-wrapper, .body-small.fixed-sidebar.mini-navbar .top-navigation #page-wrapper,  .canvas-menu #page-wrapper {
+    margin: 0;
+}
+
+.top-navigation.fixed-nav #wrapper, .fixed-nav #wrapper.top-navigation {
+    margin-top: 50px;
+}
+
+.top-navigation .footer.fixed {
+    margin-left: 0 !important;
+}
+
+.top-navigation .wrapper.wrapper-content {
+    padding: 40px;
+}
+
+.top-navigation.body-small .wrapper.wrapper-content, .body-small .top-navigation .wrapper.wrapper-content {
+    padding: 40px 0px 40px 0px;
+}
+
+.navbar-toggle {
+    background-color: #1ab394;
+    color: #fff;
+    padding: 6px 12px;
+    font-size: 14px;
+}
+
+.top-navigation .navbar-nav .open .dropdown-menu>li>a, .top-navigation .navbar-nav .open .dropdown-menu .dropdown-header {
+    padding: 10px 15px 10px 20px;
+}
+
+@media ( max-width : 768px) {
+    .top-navigation .navbar-header {
+        display: block;
+        float: none;
+    }
+}
+
+.menu-visible-lg, .menu-visible-md {
+    display: none !important;
+}
+
+@media ( min-width : 1200px) {
+    .menu-visible-lg {
+        display: block !important;
+    }
+}
+
+@media ( min-width : 992px) {
+    .menu-visible-md {
+        display: block !important;
+    }
+}
+
+@media ( max-width : 767px) {
+    .menu-visible-md {
+        display: block !important;
+    }
+
+    .menu-visible-lg {
+        display: block !important;
+    }
+}
+
+.btn {
+    border-radius: 3px;
+}
+
+.float-e-margins .btn {
+    margin-bottom: 5px;
+}
+
+.btn-w-m {
+    min-width: 120px;
+}
+
+.btn-primary.btn-outline {
+    color: #1ab394;
+}
+
+.btn-success.btn-outline {
+    color: #1c84c6;
+}
+
+.btn-info.btn-outline {
+    color: #23c6c8;
+}
+
+.btn-warning.btn-outline {
+    color: #f8ac59;
+}
+
+.btn-danger.btn-outline {
+    color: #ed5565;
+}
+
+.btn-primary.btn-outline:hover, .btn-success.btn-outline:hover,  .btn-info.btn-outline:hover, .btn-warning.btn-outline:hover,  .btn-danger.btn-outline:hover {
+    color: #fff;
+}
+
+.btn-primary {
+    background-color: #1ab394;
+    border-color: #1ab394;
+    color: #FFFFFF;
+}
+
+.btn-primary:hover, .btn-primary:focus, .btn-primary:active,  .btn-primary.active, .open .dropdown-toggle.btn-primary {
+    background-color: #18a689;
+    border-color: #18a689;
+    color: #FFFFFF;
+}
+
+.btn-primary:active, .btn-primary.active, .open .dropdown-toggle.btn-primary {
+    background-image: none;
+}
+
+.btn-primary.disabled, .btn-primary.disabled:hover, .btn-primary.disabled:focus,  .btn-primary.disabled:active, .btn-primary.disabled.active,  .btn-primary[disabled], .btn-primary[disabled]:hover, .btn-primary[disabled]:focus,  .btn-primary[disabled]:active, .btn-primary.active[disabled], fieldset[disabled] .btn-primary,  fieldset[disabled] .btn-primary:hover, fieldset[disabled] .btn-primary:focus,  fieldset[disabled] .btn-primary:active, fieldset[disabled] .btn-primary.active {
+    background-color: #1dc5a3;
+    border-color: #1dc5a3;
+}
+
+.btn-success {
+    background-color: #1c84c6;
+    border-color: #1c84c6;
+    color: #FFFFFF;
+}
+
+.btn-success:hover, .btn-success:focus, .btn-success:active,  .btn-success.active, .open .dropdown-toggle.btn-success {
+    background-color: #1a7bb9 !important;
+    border-color: #1a7bb9 !important;
+    color: #FFFFFF;
+}
+
+.btn-success:active, .btn-success.active, .open .dropdown-toggle.btn-success {
+    background-image: none;
+}
+
+.btn-success.disabled, .btn-success.disabled:hover, .btn-success.disabled:focus,  .btn-success.disabled:active, .btn-success.disabled.active,  .btn-success[disabled], .btn-success[disabled]:hover, .btn-success[disabled]:focus,  .btn-success[disabled]:active, .btn-success.active[disabled], fieldset[disabled] .btn-success,  fieldset[disabled] .btn-success:hover, fieldset[disabled] .btn-success:focus,  fieldset[disabled] .btn-success:active, fieldset[disabled] .btn-success.active {
+    background-color: #1f90d8;
+    border-color: #1f90d8;
+}
+
+.btn-info {
+    background-color: #23c6c8;
+    border-color: #23c6c8;
+    color: #FFFFFF;
+}
+
+.btn-info:hover, .btn-info:focus, .btn-info:active, .btn-info.active,  .open .dropdown-toggle.btn-info {
+    background-color: #21b9bb;
+    border-color: #21b9bb;
+    color: #FFFFFF;
+}
+
+.btn-info:active, .btn-info.active, .open .dropdown-toggle.btn-info {
+    background-image: none;
+}
+
+.btn-info.disabled, .btn-info.disabled:hover, .btn-info.disabled:focus,  .btn-info.disabled:active, .btn-info.disabled.active, .btn-info[disabled],  .btn-info[disabled]:hover, .btn-info[disabled]:focus, .btn-info[disabled]:active,  .btn-info.active[disabled], fieldset[disabled] .btn-info, fieldset[disabled] .btn-info:hover,  fieldset[disabled] .btn-info:focus, fieldset[disabled] .btn-info:active,  fieldset[disabled] .btn-info.active {
+    background-color: #26d7d9;
+    border-color: #26d7d9;
+}
+
+.btn-default {
+    background-color: #f4f4f4;
+    border-color: #ddd;
+    color: #444;
+}
+
+.btn-default:hover, .btn-default:focus, .btn-default:active,  .btn-default.active, .open .dropdown-toggle.btn-default {
+    background-color: #e7e7e7;
+    border-color: #e7e7e7;
+    color: #444;
+}
+
+.btn-default:active, .btn-default.active, .open .dropdown-toggle.btn-default {
+    background-image: none;
+}
+
+.btn-default.disabled, .btn-default.disabled:hover, .btn-default.disabled:focus,  .btn-default.disabled:active, .btn-default.disabled.active,  .btn-default[disabled], .btn-default[disabled]:hover, .btn-default[disabled]:focus,  .btn-default[disabled]:active, .btn-default.active[disabled], fieldset[disabled] .btn-default,  fieldset[disabled] .btn-default:hover, fieldset[disabled] .btn-default:focus,  fieldset[disabled] .btn-default:active, fieldset[disabled] .btn-default.active {
+    background-color: #cccccc;
+    border-color: #cccccc;
+}
+
+.btn-warning {
+    background-color: #f8ac59;
+    border-color: #f8ac59;
+    color: #FFFFFF;
+}
+
+.btn-warning:hover, .btn-warning:focus, .btn-warning:active,  .btn-warning.active, .open .dropdown-toggle.btn-warning {
+    background-color: #f7a54a;
+    border-color: #f7a54a;
+    color: #FFFFFF;
+}
+
+.btn-warning:active, .btn-warning.active, .open .dropdown-toggle.btn-warning {
+    background-image: none;
+}
+
+.btn-warning.disabled, .btn-warning.disabled:hover, .btn-warning.disabled:focus,  .btn-warning.disabled:active, .btn-warning.disabled.active,  .btn-warning[disabled], .btn-warning[disabled]:hover, .btn-warning[disabled]:focus,  .btn-warning[disabled]:active, .btn-warning.active[disabled], fieldset[disabled] .btn-warning,  fieldset[disabled] .btn-warning:hover, fieldset[disabled] .btn-warning:focus,  fieldset[disabled] .btn-warning:active, fieldset[disabled] .btn-warning.active {
+    background-color: #f9b66d;
+    border-color: #f9b66d;
+}
+
+.btn-danger {
+    background-color: #ed5565;
+    border-color: #ed5565;
+    color: #FFFFFF;
+}
+
+.btn-danger:hover, .btn-danger:focus, .btn-danger:active, .btn-danger.active,  .open .dropdown-toggle.btn-danger {
+    background-color: #ec4758;
+    border-color: #ec4758;
+    color: #FFFFFF;
+}
+
+.btn-danger:active, .btn-danger.active, .open .dropdown-toggle.btn-danger {
+    background-image: none;
+}
+
+.btn-danger.disabled, .btn-danger.disabled:hover, .btn-danger.disabled:focus,  .btn-danger.disabled:active, .btn-danger.disabled.active, .btn-danger[disabled],  .btn-danger[disabled]:hover, .btn-danger[disabled]:focus, .btn-danger[disabled]:active,  .btn-danger.active[disabled], fieldset[disabled] .btn-danger, fieldset[disabled] .btn-danger:hover,  fieldset[disabled] .btn-danger:focus, fieldset[disabled] .btn-danger:active,  fieldset[disabled] .btn-danger.active {
+    background-color: #ef6776;
+    border-color: #ef6776;
+}
+
+.btn-link {
+    color: inherit;
+}
+
+.btn-link:hover, .btn-link:focus, .btn-link:active, .btn-link.active,  .open .dropdown-toggle.btn-link {
+    color: #1ab394;
+    text-decoration: none;
+}
+
+.btn-link:active, .btn-link.active, .open .dropdown-toggle.btn-link {
+    background-image: none;
+}
+
+.btn-link.disabled, .btn-link.disabled:hover, .btn-link.disabled:focus,  .btn-link.disabled:active, .btn-link.disabled.active, .btn-link[disabled],  .btn-link[disabled]:hover, .btn-link[disabled]:focus, .btn-link[disabled]:active,  .btn-link.active[disabled], fieldset[disabled] .btn-link, fieldset[disabled] .btn-link:hover,  fieldset[disabled] .btn-link:focus, fieldset[disabled] .btn-link:active,  fieldset[disabled] .btn-link.active {
+    color: #cacaca;
+}
+
+.btn-white {
+    color: inherit;
+    background: white;
+    border: 1px solid #e7eaec;
+}
+
+.btn-white:hover, .btn-white:focus, .btn-white:active, .btn-white.active,  .open .dropdown-toggle.btn-white {
+    color: inherit;
+    border: 1px solid #d2d2d2;
+}
+
+.btn-white:active, .btn-white.active {
+    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15) inset;
+}
+
+.btn-white:active, .btn-white.active, .open .dropdown-toggle.btn-white {
+    background-image: none;
+}
+
+.btn-white.disabled, .btn-white.disabled:hover, .btn-white.disabled:focus,  .btn-white.disabled:active, .btn-white.disabled.active, .btn-white[disabled],  .btn-white[disabled]:hover, .btn-white[disabled]:focus, .btn-white[disabled]:active,  .btn-white.active[disabled], fieldset[disabled] .btn-white, fieldset[disabled] .btn-white:hover,  fieldset[disabled] .btn-white:focus, fieldset[disabled] .btn-white:active,  fieldset[disabled] .btn-white.active {
+    color: #cacaca;
+}
+
+.form-control, .has-error .form-control:focus,  .has-success .form-control:focus, .has-warning .form-control:focus,  .navbar-collapse, .navbar-form, .navbar-form-custom .form-control:focus,  .navbar-form-custom .form-control:hover, .open .btn.dropdown-toggle,  .panel, .popover, .progress, .progress-bar {
+    box-shadow: none;
+}
+
+.btn-outline {
+    color: inherit;
+    background-color: transparent;
+    -webkit-transition: all .5s;
+    transition: all .5s;
+}
+
+.btn-rounded {
+    border-radius: 50px;
+}
+
+.btn-large-dim {
+    width: 90px;
+    height: 90px;
+    font-size: 42px;
+}
+
+button.dim {
+    display: inline-block;
+    color: #fff;
+    text-decoration: none;
+    text-transform: uppercase;
+    text-align: center;
+    padding-top: 6px;
+    margin-right: 10px;
+    position: relative;
+    cursor: pointer;
+    border-radius: 5px;
+    font-weight: 600;
+    margin-bottom: 20px !important;
+}
+
+button.dim:active {
+    top: 3px;
+}
+
+button.btn-primary.dim {
+    box-shadow: inset 0px 0px 0px #16987e, 0px 5px 0px 0px #16987e, 0px 10px  5px #999999;
+}
+
+button.btn-primary.dim:active {
+    box-shadow: inset 0px 0px 0px #16987e, 0px 2px 0px 0px #16987e, 0px 5px  3px #999999;
+}
+
+button.btn-default.dim {
+    box-shadow: inset 0px 0px 0px #b3b3b3, 0px 5px 0px 0px #b3b3b3, 0px 10px  5px #999999;
+}
+
+button.btn-default.dim:active {
+    box-shadow: inset 0px 0px 0px #b3b3b3, 0px 2px 0px 0px #b3b3b3, 0px 5px  3px #999999;
+}
+
+button.btn-warning.dim {
+    box-shadow: inset 0px 0px 0px #f79d3c, 0px 5px 0px 0px #f79d3c, 0px 10px  5px #999999;
+}
+
+button.btn-warning.dim:active {
+    box-shadow: inset 0px 0px 0px #f79d3c, 0px 2px 0px 0px #f79d3c, 0px 5px  3px #999999;
+}
+
+button.btn-info.dim {
+    box-shadow: inset 0px 0px 0px #1eacae, 0px 5px 0px 0px #1eacae, 0px 10px  5px #999999;
+}
+
+button.btn-info.dim:active {
+    box-shadow: inset 0px 0px 0px #1eacae, 0px 2px 0px 0px #1eacae, 0px 5px  3px #999999;
+}
+
+button.btn-success.dim {
+    box-shadow: inset 0px 0px 0px #1872ab, 0px 5px 0px 0px #1872ab, 0px 10px  5px #999999;
+}
+
+button.btn-success.dim:active {
+    box-shadow: inset 0px 0px 0px #1872ab, 0px 2px 0px 0px #1872ab, 0px 5px  3px #999999;
+}
+
+button.btn-danger.dim {
+    box-shadow: inset 0px 0px 0px #ea394c, 0px 5px 0px 0px #ea394c, 0px 10px  5px #999999;
+}
+
+button.btn-danger.dim:active {
+    box-shadow: inset 0px 0px 0px #ea394c, 0px 2px 0px 0px #ea394c, 0px 5px  3px #999999;
+}
+
+button.dim:before {
+    font-size: 50px;
+    line-height: 1em;
+    font-weight: normal;
+    color: #fff;
+    display: block;
+    padding-top: 10px;
+}
+
+button.dim:active:before {
+    top: 7px;
+    font-size: 50px;
+}
+
+.label {
+    background-color: #d1dade;
+    color: #5e5e5e;
+    font-size: 10px;
+    font-weight: 600;
+    padding: 3px 8px;
+    text-shadow: none;
+}
+
+.badge {
+    background-color: #d1dade;
+    color: #5e5e5e;
+    font-size: 11px;
+    font-weight: 600;
+    padding-bottom: 4px;
+    padding-left: 6px;
+    padding-right: 6px;
+    text-shadow: none;
+}
+
+.label-primary, .badge-primary {
+    background-color: #1ab394;
+    color: #FFFFFF;
+}
+
+.label-success, .badge-success {
+    background-color: #1c84c6;
+    color: #FFFFFF;
+}
+
+.label-warning, .badge-warning {
+    background-color: #f8ac59;
+    color: #FFFFFF;
+}
+
+.label-warning-light, .badge-warning-light {
+    background-color: #f8ac59;
+    color: #ffffff;
+}
+
+.label-danger, .badge-danger {
+    background-color: #ed5565;
+    color: #FFFFFF;
+}
+
+.label-info, .badge-info {
+    background-color: #23c6c8;
+    color: #FFFFFF;
+}
+
+.label-inverse, .badge-inverse {
+    background-color: #262626;
+    color: #FFFFFF;
+}
+
+.label-white, .badge-white {
+    background-color: #FFFFFF;
+    color: #5E5E5E;
+}
+
+.label-white, .badge-disable {
+    background-color: #2A2E36;
+    color: #8B91A0;
+}
+/* TOOGLE SWICH */
+.onoffswitch {
+    position: relative;
+    width: 64px;
+    -webkit-user-select: none;
+    -moz-user-select: none;
+    -ms-user-select: none;
+}
+
+.onoffswitch-checkbox {
+    display: none;
+}
+
+.onoffswitch-label {
+    display: block;
+    overflow: hidden;
+    cursor: pointer;
+    border: 2px solid #1ab394;
+    border-radius: 2px;
+}
+
+.onoffswitch-inner {
+    width: 200%;
+    margin-left: -100%;
+    -webkit-transition: margin 0.3s ease-in 0s;
+    transition: margin 0.3s ease-in 0s;
+}
+
+.onoffswitch-inner:before, .onoffswitch-inner:after {
+    float: left;
+    width: 50%;
+    height: 20px;
+    padding: 0;
+    line-height: 20px;
+    font-size: 12px;
+    color: white;
+    font-family: Trebuchet, Arial, sans-serif;
+    font-weight: bold;
+    box-sizing: border-box;
+}
+
+.onoffswitch-inner:before {
+    content: "ON";
+    padding-left: 10px;
+    background-color: #1ab394;
+    color: #FFFFFF;
+}
+
+.onoffswitch-inner:after {
+    content: "OFF";
+    padding-right: 10px;
+    background-color: #FFFFFF;
+    color: #999999;
+    text-align: right;
+}
+
+.onoffswitch-switch {
+    width: 20px;
+    margin: 0px;
+    background: #FFFFFF;
+    border: 2px solid #1ab394;
+    border-radius: 2px;
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    right: 44px;
+    -webkit-transition: all 0.3s ease-in 0s;
+    transition: all 0.3s ease-in 0s;
+}
+
+.onoffswitch-checkbox:checked+.onoffswitch-label .onoffswitch-inner {
+    margin-left: 0;
+}
+
+.onoffswitch-checkbox:checked+.onoffswitch-label .onoffswitch-switch {
+    right: 0px;
+}
+/* CHOSEN PLUGIN */
+.chosen-container-single .chosen-single {
+    background: #ffffff;
+    box-shadow: none;
+    -moz-box-sizing: border-box;
+    background-color: #FFFFFF;
+    border: 1px solid #CBD5DD;
+    border-radius: 2px;
+    cursor: text;
+    height: auto !important;
+    margin: 0;
+    min-height: 30px;
+    overflow: hidden;
+    padding: 4px 12px;
+    position: relative;
+    width: 100%;
+}
+
+.chosen-container-multi .chosen-choices li.search-choice {
+    background: #f1f1f1;
+    border: 1px solid #ededed;
+    border-radius: 2px;
+    box-shadow: none;
+    color: #333333;
+    cursor: default;
+    line-height: 13px;
+    margin: 3px 0 3px 5px;
+    padding: 3px 20px 3px 5px;
+    position: relative;
+}
+/* PAGINATIN */
+.pagination>.active>a, .pagination>.active>span, .pagination>.active>a:hover,  .pagination>.active>span:hover, .pagination>.active>a:focus,  .pagination>.active>span:focus {
+    background-color: #f4f4f4;
+    border-color: #DDDDDD;
+    color: inherit;
+    cursor: default;
+    z-index: 2;
+}
+
+.pagination>li>a, .pagination>li>span {
+    background-color: #FFFFFF;
+    border: 1px solid #DDDDDD;
+    color: inherit;
+    float: left;
+    line-height: 1.42857;
+    margin-left: -1px;
+    padding: 4px 10px;
+    position: relative;
+    text-decoration: none;
+}
+/* TOOLTIPS */
+.tooltip-inner {
+    background-color: #2F4050;
+   	word-break: break-all;
+    overflow-wrap: break-word;
+}
+
+.tooltip.top .tooltip-arrow {
+    border-top-color: #2F4050;
+}
+
+.tooltip.right .tooltip-arrow {
+    border-right-color: #2F4050;
+}
+
+.tooltip.bottom .tooltip-arrow {
+    border-bottom-color: #2F4050;
+}
+
+.tooltip.left .tooltip-arrow {
+    border-left-color: #2F4050;
+}
+/* EASY PIE CHART*/
+.easypiechart {
+    position: relative;
+    text-align: center;
+}
+
+.easypiechart .h2 {
+    margin-left: 10px;
+    margin-top: 10px;
+    display: inline-block;
+}
+
+.easypiechart canvas {
+    top: 0;
+    left: 0;
+}
+
+.easypiechart .easypie-text {
+    line-height: 1;
+    position: absolute;
+    top: 33px;
+    width: 100%;
+    z-index: 1;
+}
+
+.easypiechart img {
+    margin-top: -4px;
+}
+
+.jqstooltip {
+    box-sizing: content-box;
+}
+/* FULLCALENDAR */
+.fc-state-default {
+    background-color: #ffffff;
+    background-image: none;
+    background-repeat: repeat-x;
+    box-shadow: none;
+    color: #333333;
+    text-shadow: none;
+}
+
+.fc-state-default {
+    border: 1px solid;
+}
+
+.fc-button {
+    color: inherit;
+    border: 1px solid #e7eaec;
+    cursor: pointer;
+    display: inline-block;
+    height: 1.9em;
+    line-height: 1.9em;
+    overflow: hidden;
+    padding: 0 0.6em;
+    position: relative;
+    white-space: nowrap;
+}
+
+.fc-state-active {
+    background-color: #1ab394;
+    border-color: #1ab394;
+    color: #ffffff;
+}
+
+.fc-header-title h2 {
+    font-size: 16px;
+    font-weight: 600;
+    color: inherit;
+}
+
+.fc-content .fc-widget-header, .fc-content .fc-widget-content {
+    border-color: #e7eaec;
+    font-weight: normal;
+}
+
+.fc-border-separate tbody {
+    background-color: #F8F8F8;
+}
+
+.fc-state-highlight {
+    background: none repeat scroll 0 0 #FCF8E3;
+}
+
+.external-event {
+    padding: 5px 10px;
+    border-radius: 2px;
+    cursor: pointer;
+    margin-bottom: 5px;
+}
+
+.fc-ltr .fc-event-hori.fc-event-end, .fc-rtl .fc-event-hori.fc-event-start {
+    border-radius: 2px;
+}
+
+.fc-event, .fc-agenda .fc-event-time, .fc-event a {
+    padding: 4px 6px;
+    background-color: #1ab394;
+    /* background color */
+    border-color: #1ab394;
+    /* border color */
+}
+
+.fc-event-time, .fc-event-title {
+    color: #717171;
+    padding: 0 1px;
+}
+
+.ui-calendar .fc-event-time, .ui-calendar .fc-event-title {
+    color: #fff;
+}
+/* Chat */
+.chat-activity-list .chat-element {
+    border-bottom: 1px solid #e7eaec;
+}
+
+.chat-element:first-child {
+    margin-top: 0;
+}
+
+.chat-element {
+    padding-bottom: 15px;
+}
+
+.chat-element, .chat-element .media {
+    margin-top: 15px;
+}
+
+.chat-element, .media-body {
+    overflow: hidden;
+}
+
+.media-body {
+    display: block;
+    width: auto;
+}
+
+.chat-element>.pull-left {
+    margin-right: 10px;
+}
+
+.chat-element img.img-circle, .dropdown-messages-box img.img-circle {
+    width: 38px;
+    height: 38px;
+}
+
+.chat-element .well {
+    border: 1px solid #e7eaec;
+    box-shadow: none;
+    margin-top: 10px;
+    margin-bottom: 5px;
+    padding: 10px 20px;
+    font-size: 11px;
+    line-height: 16px;
+}
+
+.chat-element .actions {
+    margin-top: 10px;
+}
+
+.chat-element .photos {
+    margin: 10px 0;
+}
+
+.right.chat-element>.pull-right {
+    margin-left: 10px;
+}
+
+.chat-photo {
+    max-height: 180px;
+    border-radius: 4px;
+    overflow: hidden;
+    margin-right: 10px;
+    margin-bottom: 10px;
+}
+
+.chat {
+    margin: 0;
+    padding: 0;
+    list-style: none;
+}
+
+.chat li {
+    margin-bottom: 10px;
+    padding-bottom: 5px;
+    border-bottom: 1px dotted #B3A9A9;
+}
+
+.chat li.left .chat-body {
+    margin-left: 60px;
+}
+
+.chat li.right .chat-body {
+    margin-right: 60px;
+}
+
+.chat li .chat-body p {
+    margin: 0;
+    color: #777777;
+}
+
+.panel .slidedown .glyphicon, .chat .glyphicon {
+    margin-right: 5px;
+}
+
+.chat-panel .panel-body {
+    height: 350px;
+    overflow-y: scroll;
+}
+/* LIST GROUP */
+a.list-group-item.active, a.list-group-item.active:hover, a.list-group-item.active:focus {
+    background-color: #1ab394;
+    border-color: #1ab394;
+    color: #FFFFFF;
+    z-index: 2;
+}
+
+.list-group-item-heading {
+    margin-top: 10px;
+}
+
+.list-group-item-text {
+    margin: 0 0 10px;
+    color: inherit;
+    font-size: 12px;
+    line-height: inherit;
+}
+
+.no-padding .list-group-item {
+    border-left: none;
+    border-right: none;
+    border-bottom: none;
+}
+
+.no-padding .list-group-item:first-child {
+    border-left: none;
+    border-right: none;
+    border-bottom: none;
+    border-top: none;
+}
+
+.no-padding .list-group {
+    margin-bottom: 0;
+}
+
+.list-group-item {
+    background-color: inherit;
+    border: 1px solid #e7eaec;
+    display: block;
+    margin-bottom: -1px;
+    padding: 10px 15px;
+    position: relative;
+}
+
+.elements-list .list-group-item {
+    border-left: none;
+    border-right: none;
+    /*border-top: none;*/
+    padding: 15px 25px;
+}
+
+.elements-list .list-group-item:first-child {
+    border-left: none;
+    border-right: none;
+    border-top: none !important;
+}
+
+.elements-list .list-group {
+    margin-bottom: 0;
+}
+
+.elements-list a {
+    color: inherit;
+}
+
+.elements-list .list-group-item.active, .elements-list .list-group-item:hover {
+    background: #f3f3f4;
+    color: inherit;
+    border-color: #e7eaec;
+    /*border-bottom: 1px solid #e7eaec;*/
+    /*border-top: 1px solid #e7eaec;*/
+    border-radius: 0;
+}
+
+.elements-list li.active {
+    -webkit-transition: none;
+    transition: none;
+}
+
+.element-detail-box {
+    padding: 25px;
+}
+/* FLOT CHART  */
+.flot-chart {
+    display: block;
+    height: 200px;
+}
+
+.widget .flot-chart.dashboard-chart {
+    display: block;
+    height: 120px;
+    margin-top: 40px;
+}
+
+.flot-chart.dashboard-chart {
+    display: block;
+    height: 180px;
+    margin-top: 40px;
+}
+
+.flot-chart-content {
+    width: 100%;
+    height: 100%;
+}
+
+.flot-chart-pie-content {
+    width: 200px;
+    height: 200px;
+    margin: auto;
+}
+
+.jqstooltip {
+    position: absolute;
+    display: block;
+    left: 0px;
+    top: 0px;
+    visibility: hidden;
+    background: #2b303a;
+    background-color: rgba(43, 48, 58, 0.8);
+    color: white;
+    text-align: left;
+    white-space: nowrap;
+    z-index: 10000;
+    padding: 5px 5px 5px 5px;
+    min-height: 22px;
+    border-radius: 3px;
+}
+
+.jqsfield {
+    color: white;
+    text-align: left;
+}
+
+.h-200 {
+    min-height: 200px;
+}
+
+.legendLabel {
+    padding-left: 5px;
+}
+
+.stat-list li:first-child {
+    margin-top: 0;
+}
+
+.stat-list {
+    list-style: none;
+    padding: 0;
+    margin: 0;
+}
+
+.stat-percent {
+    float: right;
+}
+
+.stat-list li {
+    margin-top: 15px;
+    position: relative;
+}
+/* DATATABLES */
+table.dataTable thead .sorting, table.dataTable thead .sorting_asc:after,  table.dataTable thead .sorting_desc, table.dataTable thead .sorting_asc_disabled,  table.dataTable thead .sorting_desc_disabled {
+    background: transparent;
+}
+
+table.dataTable thead .sorting_asc:after {
+    float: right;
+    font-family: fontawesome;
+}
+
+table.dataTable thead .sorting_desc:after {
+    content: "\f0dd";
+    float: right;
+    font-family: fontawesome;
+}
+
+table.dataTable thead .sorting:after {
+    content: "\f0dc";
+    float: right;
+    font-family: fontawesome;
+    color: rgba(50, 50, 50, 0.5);
+}
+
+.dataTables_wrapper {
+    padding-bottom: 30px;
+}
+/* CIRCLE */
+.img-circle {
+    border-radius: 50%;
+}
+
+.btn-circle {
+    width: 30px;
+    height: 30px;
+    padding: 6px 0;
+    border-radius: 15px;
+    text-align: center;
+    font-size: 12px;
+    line-height: 1.428571429;
+}
+
+.btn-circle.btn-lg {
+    width: 50px;
+    height: 50px;
+    padding: 10px 16px;
+    border-radius: 25px;
+    font-size: 18px;
+    line-height: 1.33;
+}
+
+.btn-circle.btn-xl {
+    width: 70px;
+    height: 70px;
+    padding: 10px 16px;
+    border-radius: 35px;
+    font-size: 24px;
+    line-height: 1.33;
+}
+
+.show-grid [class^="col-"] {
+    padding-top: 10px;
+    padding-bottom: 10px;
+    border: 1px solid #ddd;
+    background-color: #eee !important;
+}
+
+.show-grid {
+    margin: 15px 0;
+}
+/* ANIMATION */
+.css-animation-box h1 {
+    font-size: 44px;
+}
+
+.animation-efect-links a {
+    padding: 4px 6px;
+    font-size: 12px;
+}
+
+#animation_box {
+    background-color: #f9f8f8;
+    border-radius: 16px;
+    width: 80%;
+    margin: 0 auto;
+    padding-top: 80px;
+}
+
+.animation-text-box {
+    position: absolute;
+    margin-top: 40px;
+    left: 50%;
+    margin-left: -100px;
+    width: 200px;
+}
+
+.animation-text-info {
+    position: absolute;
+    margin-top: -60px;
+    left: 50%;
+    margin-left: -100px;
+    width: 200px;
+    font-size: 10px;
+}
+
+.animation-text-box h2 {
+    font-size: 54px;
+    font-weight: 600;
+    margin-bottom: 5px;
+}
+
+.animation-text-box p {
+    font-size: 12px;
+    text-transform: uppercase;
+}
+/* PEACE */
+.pace {
+    -webkit-pointer-events: none;
+    pointer-events: none;
+    -webkit-user-select: none;
+    -moz-user-select: none;
+    -ms-user-select: none;
+    user-select: none;
+}
+
+.pace-inactive {
+    display: none;
+}
+
+.pace .pace-progress {
+    background: #1ab394;
+    position: fixed;
+    z-index: 2000;
+    top: 0;
+    width: 100%;
+    height: 2px;
+}
+
+.pace-inactive {
+    display: none;
+}
+/* WIDGETS */
+.widget {
+    border-radius: 5px;
+    padding: 15px 20px;
+    margin-bottom: 10px;
+    margin-top: 10px;
+}
+
+.widget.style1 h2 {
+    font-size: 30px;
+}
+
+.widget h2, .widget h3 {
+    margin-top: 5px;
+    margin-bottom: 0;
+}
+
+.widget-text-box {
+    padding: 20px;
+    border: 1px solid #e7eaec;
+    background: #ffffff;
+}
+
+.widget-head-color-box {
+    border-radius: 5px 5px 0px 0px;
+    margin-top: 10px;
+}
+
+.widget .flot-chart {
+    height: 100px;
+}
+
+.vertical-align div {
+    display: inline-block;
+    vertical-align: middle;
+}
+
+.vertical-align h2, .vertical-align h3 {
+    margin: 0;
+}
+
+.todo-list {
+    list-style: none outside none;
+    margin: 0;
+    padding: 0;
+    font-size: 14px;
+}
+
+.todo-list.small-list {
+    font-size: 12px;
+}
+
+.todo-list.small-list>li {
+    background: #f3f3f4;
+    border-left: none;
+    border-right: none;
+    border-radius: 4px;
+    color: inherit;
+    margin-bottom: 2px;
+    padding: 6px 6px 6px 12px;
+}
+
+.todo-list.small-list .btn-xs, .todo-list.small-list .btn-group-xs>.btn {
+    border-radius: 5px;
+    font-size: 10px;
+    line-height: 1.5;
+    padding: 1px 2px 1px 5px;
+}
+
+.todo-list>li {
+    background: #f3f3f4;
+    border-left: 6px solid #e7eaec;
+    border-right: 6px solid #e7eaec;
+    border-radius: 4px;
+    color: inherit;
+    margin-bottom: 2px;
+    padding: 10px;
+}
+
+.todo-list .handle {
+    cursor: move;
+    display: inline-block;
+    font-size: 16px;
+    margin: 0 5px;
+}
+
+.todo-list>li .label {
+    font-size: 9px;
+    margin-left: 10px;
+}
+
+.check-link {
+    font-size: 16px;
+}
+
+.todo-completed {
+    text-decoration: line-through;
+}
+
+.geo-statistic h1 {
+    font-size: 36px;
+    margin-bottom: 0;
+}
+
+.glyphicon.fa {
+    font-family: "FontAwesome";
+}
+/* INPUTS */
+.inline {
+    display: inline-block !important;
+}
+
+.input-s-sm {
+    width: 120px;
+}
+
+.input-s {
+    width: 200px;
+}
+
+.input-s-lg {
+    width: 250px;
+}
+
+.i-checks {
+    padding-left: 0;
+}
+
+.form-control, .single-line {
+    background: #FFFFFF none;
+    border: 1px solid #e5e6e7;
+    border-radius: 4px;
+    color: inherit;
+    display: block;
+    padding: 3px 6px 4px;
+    -webkit-transition: border-color 0.15s ease-in-out 0s, box-shadow 0.15s  ease-in-out 0s;
+    transition: border-color 0.15s ease-in-out 0s, box-shadow 0.15s  ease-in-out 0s;
+    width: 100%;
+    height: 31px;
+    font-size: 14px;
+}
+
+.form-control.kv-fileinput-caption {
+    height: 34px!important;
+}
+
+.form-control:focus, .single-line:focus {
+    border-color: #3c8dbc !important;
+}
+
+.has-success .form-control {
+    border-color: #1ab394;
+}
+
+.has-warning .form-control {
+    border-color: #f8ac59;
+}
+
+.has-error .form-control {
+    border-color: #ed5565;
+}
+
+.has-success .control-label {
+    color: #1ab394;
+}
+
+.has-warning .control-label {
+    color: #f8ac59;
+}
+
+.has-error .control-label {
+    color: #ed5565;
+}
+
+.input-group-addon {
+    background-color: #fff;
+    border: 1px solid #e5e6e7;
+    border-radius: 4px;
+    color: inherit;
+    font-size: 14px;
+    font-weight: 400;
+    line-height: 1;
+    padding: 6px 12px;
+    text-align: center;
+}
+
+.spinner-buttons.input-group-btn .btn-xs {
+    line-height: 1.13;
+}
+
+.spinner-buttons.input-group-btn {
+    width: 20%;
+}
+
+.noUi-connect {
+    background: none repeat scroll 0 0 #1ab394;
+    box-shadow: none;
+}
+
+.slider_red .noUi-connect {
+    background: none repeat scroll 0 0 #ed5565;
+    box-shadow: none;
+}
+/* UI Sortable */
+.ui-sortable .ibox-title {
+    cursor: move;
+}
+
+.ui-sortable-placeholder {
+    border: 1px dashed #cecece !important;
+    visibility: visible !important;
+    background: #e7eaec;
+}
+
+.ibox.ui-sortable-placeholder {
+    margin: 0px 0px 23px !important;
+}
+/* Tabs */
+.tabs-container .panel-body {
+    background: #fff;
+    border: 1px solid #e7eaec;
+    border-radius: 2px;
+    padding: 20px;
+    position: relative;
+}
+
+.tabs-container .nav-tabs>li.active>a, .tabs-container .nav-tabs>li.active>a:hover,  .tabs-container .nav-tabs>li.active>a:focus {
+    border: 1px solid #e7eaec;
+    border-bottom-color: transparent;
+    background-color: #fff;
+}
+
+.tabs-container .nav-tabs>li {
+    float: left;
+    margin-bottom: -1px;
+}
+
+.tabs-container .tab-pane .panel-body {
+    border-top: none;
+}
+
+.tabs-container .nav-tabs>li.active>a, .tabs-container .nav-tabs>li.active>a:hover,  .tabs-container .nav-tabs>li.active>a:focus {
+    border: 1px solid #e7eaec;
+    border-bottom-color: transparent;
+}
+
+.tabs-container .nav-tabs {
+    border-bottom: 1px solid #e7eaec;
+}
+
+.tabs-container .tab-pane .panel-body {
+    border-top: none;
+}
+
+.tabs-container .tabs-left .tab-pane .panel-body, .tabs-container .tabs-right .tab-pane .panel-body {
+    border-top: 1px solid #e7eaec;
+}
+
+.tabs-container .nav-tabs>li a:hover {
+    background: transparent;
+    border-color: transparent;
+}
+
+.tabs-container .tabs-below>.nav-tabs, .tabs-container .tabs-right>.nav-tabs,  .tabs-container .tabs-left>.nav-tabs {
+    border-bottom: 0;
+}
+
+.tabs-container .tabs-left .panel-body {
+    position: static;
+}
+
+.tabs-container .tabs-left>.nav-tabs, .tabs-container .tabs-right>.nav-tabs {
+    width: 20%;
+}
+
+.tabs-container .tabs-left .panel-body {
+    width: 80%;
+    margin-left: 20%;
+}
+
+.tabs-container .tabs-right .panel-body {
+    width: 80%;
+    margin-right: 20%;
+}
+
+.tabs-container .tab-content>.tab-pane, .tabs-container .pill-content>.pill-pane {
+    display: none;
+}
+
+.tabs-container .tab-content>.active, .tabs-container .pill-content>.active {
+    display: block;
+}
+
+.tabs-container .tabs-below>.nav-tabs {
+    border-top: 1px solid #e7eaec;
+}
+
+.tabs-container .tabs-below>.nav-tabs>li {
+    margin-top: -1px;
+    margin-bottom: 0;
+}
+
+.tabs-container .tabs-below>.nav-tabs>li>a {
+    border-radius: 0 0 4px 4px;
+}
+
+.tabs-container .tabs-below>.nav-tabs>li>a:hover, .tabs-container .tabs-below>.nav-tabs>li>a:focus {
+    border-top-color: #e7eaec;
+    border-bottom-color: transparent;
+}
+
+.tabs-container .tabs-left>.nav-tabs>li, .tabs-container .tabs-right>.nav-tabs>li {
+    float: none;
+}
+
+.tabs-container .tabs-left>.nav-tabs>li>a, .tabs-container .tabs-right>.nav-tabs>li>a {
+    min-width: 74px;
+    margin-right: 0;
+    margin-bottom: 3px;
+}
+
+.tabs-container .tabs-left>.nav-tabs {
+    float: left;
+    margin-right: 19px;
+}
+
+.tabs-container .tabs-left>.nav-tabs>li>a {
+    margin-right: -1px;
+    border-radius: 4px 0 0 4px;
+}
+
+.tabs-container .tabs-left>.nav-tabs .active>a, .tabs-container .tabs-left>.nav-tabs .active>a:hover,  .tabs-container .tabs-left>.nav-tabs .active>a:focus {
+    border-color: #e7eaec transparent #e7eaec #e7eaec;
+    border-right-color: #ffffff;
+}
+
+.tabs-container .tabs-right>.nav-tabs {
+    float: right;
+    margin-left: 19px;
+}
+
+.tabs-container .tabs-right>.nav-tabs>li>a {
+    margin-left: -1px;
+    border-radius: 0 4px 4px 0;
+}
+
+.tabs-container .tabs-right>.nav-tabs .active>a, .tabs-container .tabs-right>.nav-tabs .active>a:hover,  .tabs-container .tabs-right>.nav-tabs .active>a:focus {
+    border-color: #e7eaec #e7eaec #e7eaec transparent;
+    border-left-color: #ffffff;
+    z-index: 1;
+}
+/*SWITCHES */
+
+.onoffswitch{
+    position: relative;
+    width: 54px;
+    -webkit-user-select: none;
+    -moz-user-select: none;
+    -ms-user-select: none;
+}
+
+.onoffswitch-checkbox {
+    display: none;
+}
+
+.onoffswitch-label {
+    display: block;
+    overflow: hidden;
+    cursor: pointer;
+    border: 2px solid #1AB394;
+    border-radius: 3px;
+}
+
+.onoffswitch-inner {
+    display: block;
+    width: 200%;
+    margin-left: -100%;
+    -webkit-transition: margin 0.3s ease-in 0s;
+    transition: margin 0.3s ease-in 0s;
+}
+
+.onoffswitch-inner:before, .onoffswitch-inner:after {
+    display: block;
+    float: left;
+    width: 50%;
+    /* height: 16px; */
+    padding: 0;
+    /*  line-height: 16px; */
+    font-size: 10px;
+    color: white;
+    font-family: Trebuchet, Arial, sans-serif;
+    font-weight: bold;
+    box-sizing: border-box;
+}
+
+.onoffswitch-inner:before {
+    content: "ON";
+    padding-left: 7px;
+    background-color: #1AB394;
+    color: #FFFFFF;
+}
+
+.onoffswitch-inner:after {
+    content: "OFF";
+    padding-right: 7px;
+    background-color: #FFFFFF;
+    color: #919191;
+    text-align: right;
+}
+
+.onoffswitch-switch {
+    display: block;
+    width: 18px;
+    margin: 0px;
+    background: #FFFFFF;
+    border: 2px solid #1AB394;
+    border-radius: 3px;
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    right: 36px;
+    -webkit-transition: all 0.3s ease-in 0s;
+    transition: all 0.3s ease-in 0s;
+}
+
+.onoffswitch-checkbox:checked+.onoffswitch-label .onoffswitch-inner {
+    margin-left: 0;
+}
+
+.onoffswitch-checkbox:checked+.onoffswitch-label .onoffswitch-switch {
+    right: 0px;
+}
+/* Nestable list */
+.dd {
+    position: relative;
+    display: block;
+    margin: 0;
+    padding: 0;
+    list-style: none;
+    font-size: 13px;
+    line-height: 20px;
+}
+
+.dd-list {
+    display: block;
+    position: relative;
+    margin: 0;
+    padding: 0;
+    list-style: none;
+}
+
+.dd-list .dd-list {
+    padding-left: 30px;
+}
+
+.dd-collapsed .dd-list {
+    display: none;
+}
+
+.dd-item, .dd-empty, .dd-placeholder {
+    display: block;
+    position: relative;
+    margin: 0;
+    padding: 0;
+    min-height: 20px;
+    font-size: 13px;
+    line-height: 20px;
+}
+
+.dd-handle {
+    display: block;
+    margin: 5px 0;
+    padding: 5px 10px;
+    color: #333;
+    text-decoration: none;
+    border: 1px solid #e7eaec;
+    background: #f5f5f5;
+    border-radius: 3px;
+    box-sizing: border-box;
+    -moz-box-sizing: border-box;
+}
+
+.dd-handle span {
+    font-weight: bold;
+}
+
+.dd-handle:hover {
+    background: #f0f0f0;
+    cursor: pointer;
+    font-weight: bold;
+}
+
+.dd-item>button {
+    display: block;
+    position: relative;
+    cursor: pointer;
+    float: left;
+    width: 25px;
+    height: 20px;
+    margin: 5px 0;
+    padding: 0;
+    text-indent: 100%;
+    white-space: nowrap;
+    overflow: hidden;
+    border: 0;
+    background: transparent;
+    font-size: 12px;
+    line-height: 1;
+    text-align: center;
+    font-weight: bold;
+}
+
+.dd-item>button:before {
+    content: '+';
+    display: block;
+    position: absolute;
+    width: 100%;
+    text-align: center;
+    text-indent: 0;
+}
+
+.dd-item>button[data-action="collapse"]:before {
+    content: '-';
+}
+
+#nestable2 .dd-item>button {
+    font-family: FontAwesome;
+    height: 34px;
+    width: 33px;
+    color: #c1c1c1;
+}
+
+#nestable2 .dd-item>button:before {
+    content: "\f067";
+}
+
+#nestable2 .dd-item>button[data-action="collapse"]:before {
+    content: "\f068";
+}
+
+.dd-placeholder, .dd-empty {
+    margin: 5px 0;
+    padding: 0;
+    min-height: 30px;
+    background: #f2fbff;
+    border: 1px dashed #b6bcbf;
+    box-sizing: border-box;
+    -moz-box-sizing: border-box;
+}
+
+.dd-empty {
+    border: 1px dashed #bbb;
+    min-height: 100px;
+    background-color: #e5e5e5;
+    background-image: -webkit-linear-gradient(45deg, #ffffff 25%, transparent 25%, transparent  75%, #ffffff 75%, #ffffff),  -webkit-linear-gradient(45deg, #ffffff 25%, transparent 25%, transparent  75%, #ffffff 75%, #ffffff);
+    background-image: linear-gradient(45deg, #ffffff 25%, transparent 25%, transparent 75%,  #ffffff 75%, #ffffff),  linear-gradient(45deg, #ffffff 25%, transparent 25%, transparent 75%,  #ffffff 75%, #ffffff);
+    background-size: 60px 60px;
+    background-position: 0 0, 30px 30px;
+}
+
+.dd-dragel {
+    position: absolute;
+    z-index: 9999;
+    pointer-events: none;
+}
+
+.dd-dragel>.dd-item .dd-handle {
+    margin-top: 0;
+}
+
+.dd-dragel .dd-handle {
+    box-shadow: 2px 4px 6px 0 rgba(0, 0, 0, 0.1);
+}
+/**
+* Nestable Extras
+*/
+.nestable-lists {
+    display: block;
+    clear: both;
+    padding: 30px 0;
+    width: 100%;
+    border: 0;
+    border-top: 2px solid #ddd;
+    border-bottom: 2px solid #ddd;
+}
+
+#nestable-menu {
+    padding: 0;
+    margin: 10px 0 20px 0;
+}
+
+#nestable-output, #nestable2-output {
+    width: 100%;
+    font-size: 0.75em;
+    line-height: 1.333333em;
+    font-family: lucida grande, lucida sans unicode, helvetica, arial,  sans-serif;
+    padding: 5px;
+    box-sizing: border-box;
+    -moz-box-sizing: border-box;
+}
+
+#nestable2 .dd-handle {
+    color: inherit;
+    border: 1px dashed #e7eaec;
+    background: #f3f3f4;
+    padding: 10px;
+}
+
+#nestable2 .dd-handle:hover {
+    /*background: #bbb;*/
+}
+
+#nestable2 span.label {
+    margin-right: 10px;
+}
+
+#nestable-output, #nestable2-output {
+    font-size: 12px;
+    padding: 25px;
+    box-sizing: border-box;
+    -moz-box-sizing: border-box;
+}
+/* CodeMirror */
+.CodeMirror {
+    border: 1px solid #eee;
+    height: auto;
+}
+
+.CodeMirror-scroll {
+    overflow-y: hidden;
+    overflow-x: auto;
+}
+/* Google Maps */
+.google-map {
+    height: 300px;
+}
+/* ngGrid */
+.gridStyle {
+    border: 1px solid #d4d4d4;
+    width: 100%;
+    height: 400px;
+}
+
+.gridStyle2 {
+    border: 1px solid #d4d4d4;
+    width: 500px;
+    height: 300px;
+}
+
+.ngH eaderCell {
+    border-right: none;
+    border-bottom: 1px solid #e7eaec;
+}
+
+.ngCell {
+    border-right: none;
+}
+
+.ngTopPanel {
+    background: #F5F5F6;
+}
+
+.ngRow.even {
+    background: #f9f9f9;
+}
+
+.ngRow.selected {
+    background: #EBF2F1;
+}
+
+.ngRow {
+    border-bottom: 1px solid #e7eaec;
+}
+
+.ngCell {
+    background-color: transparent;
+}
+
+.ngHeaderCell {
+    border-right: none;
+}
+/* Toastr custom style */
+#toast-container>.toast {
+    background-image: none !important;
+}
+
+#toast-container>.toast:before {
+    position: fixed;
+    font-family: FontAwesome;
+    font-size: 24px;
+    line-height: 24px;
+    float: left;
+    color: #FFF;
+    padding-right: 0.5em;
+    margin: auto 0.5em auto -1.5em;
+}
+
+#toast-container>div {
+    box-shadow: 0 0 3px #999;
+    opacity: .9;
+    -ms-filter: alpha(opacity = 90);
+    filter: alpha(opacity = 90);
+}
+
+#toast-container>:hover {
+    box-shadow: 0 0 4px #999;
+    opacity: 1;
+    -ms-filter: alpha(opacity = 100);
+    filter: alpha(opacity = 100);
+    cursor: pointer;
+}
+
+.toast {
+    background-color: #1ab394;
+}
+
+.toast-success {
+    background-color: #1ab394;
+}
+
+.toast-error {
+    background-color: #ed5565;
+}
+
+.toast-info {
+    background-color: #23c6c8;
+}
+
+.toast-warning {
+    background-color: #f8ac59;
+}
+
+.toast-top-full-width {
+    margin-top: 20px;
+}
+
+.toast-bottom-full-width {
+    margin-bottom: 20px;
+}
+/* Image cropper style */
+.img-container, .img-preview {
+    overflow: hidden;
+    text-align: center;
+    width: 100%;
+}
+
+.img-preview-sm {
+    height: 130px;
+    width: 200px;
+}
+/* Forum styles  */
+.forum-post-container .media {
+    margin: 10px 10px 10px 10px;
+    padding: 20px 10px 20px 10px;
+    border-bottom: 1px solid #f1f1f1;
+}
+
+.forum-avatar {
+    float: left;
+    margin-right: 20px;
+    text-align: center;
+    width: 110px;
+}
+
+.forum-avatar .img-circle {
+    height: 48px;
+    width: 48px;
+}
+
+.author-info {
+    color: #676a6c;
+    font-size: 11px;
+    margin-top: 5px;
+    text-align: center;
+}
+
+.forum-post-info {
+    padding: 9px 12px 6px 12px;
+    background: #f9f9f9;
+    border: 1px solid #f1f1f1;
+}
+
+.media-body>.media {
+    background: #f9f9f9;
+    border-radius: 3px;
+    border: 1px solid #f1f1f1;
+}
+
+.forum-post-container .media-body .photos {
+    margin: 10px 0;
+}
+
+.forum-photo {
+    max-width: 140px;
+    border-radius: 3px;
+}
+
+.media-body>.media .forum-avatar {
+    width: 70px;
+    margin-right: 10px;
+}
+
+.media-body>.media .forum-avatar .img-circle {
+    height: 38px;
+    width: 38px;
+}
+
+.mid-icon {
+    font-size: 66px;
+}
+
+.forum-item {
+    margin: 10px 0;
+    padding: 10px 0 20px;
+    border-bottom: 1px solid #f1f1f1;
+}
+
+.views-number {
+    font-size: 24px;
+    line-height: 18px;
+    font-weight: 400;
+}
+
+.forum-container, .forum-post-container {
+    padding: 30px !important;
+}
+
+.forum-item small {
+    color: #999;
+}
+
+.forum-item .forum-sub-title {
+    color: #999;
+    margin-left: 50px;
+}
+
+.forum-title {
+    margin: 15px 0 15px 0;
+}
+
+.forum-info {
+    text-align: center;
+}
+
+.forum-desc {
+    color: #999;
+}
+
+.forum-icon {
+    float: left;
+    width: 30px;
+    margin-right: 20px;
+    text-align: center;
+}
+
+a.forum-item-title {
+    color: inherit;
+    display: block;
+    font-size: 18px;
+    font-weight: 600;
+}
+
+a.forum-item-title:hover {
+    color: inherit;
+}
+
+.forum-icon .fa {
+    font-size: 30px;
+    margin-top: 8px;
+    color: #9b9b9b;
+}
+
+.forum-item.active .fa {
+    color: #1ab394;
+}
+
+.forum-item.active a.forum-item-title {
+    color: #1ab394;
+}
+
+@media ( max-width : 992px) {
+    .forum-info {
+        margin: 15px 0 10px 0px;
+        /* Comment this is you want to show forum info in small devices */
+        display: none;
+    }
+
+    .forum-desc {
+        float: none !important;
+    }
+}
+/* New Timeline style */
+.vertical-container {
+    /* this class is used to give a max-width to the element it is applied to, and center it horizontally when it reaches that max-width */
+    width: 90%;
+    max-width: 1170px;
+    margin: 0 auto;
+}
+
+.vertical-container::after {
+    /* clearfix */
+    content: '';
+    display: table;
+    clear: both;
+}
+
+#vertical-timeline {
+    position: relative;
+    padding: 0;
+    margin-top: 2em;
+    margin-bottom: 2em;
+}
+
+#vertical-timeline::before {
+    content: '';
+    position: absolute;
+    top: 0;
+    left: 18px;
+    height: 100%;
+    width: 4px;
+    background: #f1f1f1;
+}
+
+.vertical-timeline-content .btn {
+    float: right;
+}
+
+#vertical-timeline.light-timeline:before {
+    background: #e7eaec;
+}
+
+.dark-timeline .vertical-timeline-content:before {
+    border-color: transparent #f5f5f5 transparent transparent;
+}
+
+.dark-timeline.center-orientation .vertical-timeline-content:before {
+    border-color: transparent transparent transparent #f5f5f5;
+}
+
+.dark-timeline .vertical-timeline-block:nth-child(2n) .vertical-timeline-content:before,  .dark-timeline.center-orientation .vertical-timeline-block:nth-child(2n) .vertical-timeline-content:before {
+    border-color: transparent #f5f5f5 transparent transparent;
+}
+
+.dark-timeline .vertical-timeline-content, .dark-timeline.center-orientation .vertical-timeline-content {
+    background: #f5f5f5;
+}
+
+@media only screen and (min-width: 1170px) {
+    #vertical-timeline.center-orientation {
+        margin-top: 3em;
+        margin-bottom: 3em;
+    }
+
+    #vertical-timeline.center-orientation:before {
+        left: 50%;
+        margin-left: -2px;
+    }
+}
+
+@media only screen and (max-width: 1170px) {
+    .center-orientation.dark-timeline .vertical-timeline-content:before {
+        border-color: transparent #f5f5f5 transparent transparent;
+    }
+}
+
+.vertical-timeline-block {
+    position: relative;
+    margin: 2em 0;
+}
+
+.vertical-timeline-block:after {
+    content: "";
+    display: table;
+    clear: both;
+}
+
+.vertical-timeline-block:first-child {
+    margin-top: 0;
+}
+
+.vertical-timeline-block:last-child {
+    margin-bottom: 0;
+}
+
+@media only screen and (min-width: 1170px) {
+    .center-orientation .vertical-timeline-block {
+        margin: 4em 0;
+    }
+
+    .center-orientation .vertical-timeline-block:first-child {
+        margin-top: 0;
+    }
+
+    .center-orientation .vertical-timeline-block:last-child {
+        margin-bottom: 0;
+    }
+}
+
+.vertical-timeline-icon {
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 40px;
+    height: 40px;
+    border-radius: 50%;
+    font-size: 16px;
+    border: 3px solid #f1f1f1;
+    text-align: center;
+}
+
+.vertical-timeline-icon i {
+    display: block;
+    width: 24px;
+    height: 24px;
+    position: relative;
+    left: 50%;
+    top: 50%;
+    margin-left: -12px;
+    margin-top: -9px;
+}
+
+@media only screen and (min-width: 1170px) {
+    .center-orientation .vertical-timeline-icon {
+        width: 50px;
+        height: 50px;
+        left: 50%;
+        margin-left: -25px;
+        -webkit-transform: translateZ(0);
+        -webkit-backface-visibility: hidden;
+        font-size: 19px;
+    }
+
+    .center-orientation .vertical-timeline-icon i {
+        margin-left: -12px;
+        margin-top: -10px;
+    }
+
+    .center-orientation .cssanimations .vertical-timeline-icon.is-hidden {
+        visibility: hidden;
+    }
+}
+
+.vertical-timeline-content {
+    position: relative;
+    margin-left: 60px;
+    background: white;
+    border-radius: 0.25em;
+    padding: 1em;
+}
+
+.vertical-timeline-content:after {
+    content: "";
+    display: table;
+    clear: both;
+}
+
+.vertical-timeline-content h2 {
+    font-weight: 400;
+    margin-top: 4px;
+}
+
+.vertical-timeline-content p {
+    margin: 1em 0;
+    line-height: 1.6;
+}
+
+.vertical-timeline-content .vertical-date {
+    float: left;
+    font-weight: 500;
+}
+
+.vertical-date small {
+    color: #1ab394;
+    font-weight: 400;
+}
+
+.vertical-timeline-content::before {
+    content: '';
+    position: absolute;
+    top: 16px;
+    right: 100%;
+    height: 0;
+    width: 0;
+    border: 7px solid transparent;
+    border-right: 7px solid white;
+}
+
+@media only screen and (min-width: 768px) {
+    .vertical-timeline-content h2 {
+        font-size: 18px;
+    }
+
+    .vertical-timeline-content p {
+        font-size: 13px;
+    }
+}
+
+@media only screen and (min-width: 1170px) {
+    .center-orientation .vertical-timeline-content {
+        margin-left: 0;
+        padding: 1.6em;
+        width: 45%;
+    }
+
+    .center-orientation .vertical-timeline-content::before {
+        top: 24px;
+        left: 100%;
+        border-color: transparent;
+        border-left-color: white;
+    }
+
+    .center-orientation .vertical-timeline-content .btn {
+        float: left;
+    }
+
+    .center-orientation .vertical-timeline-content .vertical-date {
+        position: absolute;
+        width: 100%;
+        left: 122%;
+        top: 2px;
+        font-size: 14px;
+    }
+
+    .center-orientation .vertical-timeline-block:nth-child(even) .vertical-timeline-content {
+        float: right;
+    }
+
+    .center-orientation .vertical-timeline-block:nth-child(even) .vertical-timeline-content::before {
+        top: 24px;
+        left: auto;
+        right: 100%;
+        border-color: transparent;
+        border-right-color: white;
+    }
+
+    .center-orientation .vertical-timeline-block:nth-child(even) .vertical-timeline-content .btn {
+        float: right;
+    }
+
+    .center-orientation .vertical-timeline-block:nth-child(even) .vertical-timeline-content .vertical-date {
+        left: auto;
+        right: 122%;
+        text-align: right;
+    }
+
+    .center-orientation .cssanimations .vertical-timeline-content.is-hidden {
+        visibility: hidden;
+    }
+}
+
+.sidebard-panel {
+    width: 220px;
+    background: #ebebed;
+    padding: 10px 20px;
+    position: absolute;
+    right: 0;
+}
+
+.sidebard-panel .feed-element img.img-circle {
+    width: 32px;
+    height: 32px;
+}
+
+.sidebard-panel .feed-element, .media-body, .sidebard-panel p {
+    font-size: 12px;
+}
+
+.sidebard-panel .feed-element {
+    margin-top: 20px;
+    padding-bottom: 0;
+}
+
+.sidebard-panel .list-group {
+    margin-bottom: 10px;
+}
+
+.sidebard-panel .list-group .list-group-item {
+    padding: 5px 0;
+    font-size: 12px;
+    border: 0;
+}
+
+.sidebar-content .wrapper, .wrapper.sidebar-content {
+    padding-right: 240px !important;
+}
+
+#right-sidebar {
+    background-color: #fff;
+    border-left: 1px solid #e7eaec;
+    border-top: 1px solid #e7eaec;
+    overflow: hidden;
+    position: fixed;
+    top: 60px;
+    width: 260px !important;
+    z-index: 1009;
+    bottom: 0;
+    right: -260px;
+}
+
+#right-sidebar.sidebar-open {
+    right: 0;
+}
+
+#right-sidebar.sidebar-open.sidebar-top {
+    top: 0;
+    border-top: none;
+}
+
+.sidebar-container ul.nav-tabs {
+    border: none;
+}
+
+.sidebar-container ul.nav-tabs.navs-4 li {
+    width: 25%;
+}
+
+.sidebar-container ul.nav-tabs.navs-3 li {
+    width: 33.3333%;
+}
+
+.sidebar-container ul.nav-tabs.navs-2 li {
+    width: 50%;
+}
+
+.sidebar-container ul.nav-tabs li {
+    border: none;
+}
+
+.sidebar-container ul.nav-tabs li a {
+    border: none;
+    padding: 12px 10px;
+    margin: 0;
+    border-radius: 0;
+    background: #2f4050;
+    color: #fff;
+    text-align: center;
+    border-right: 1px solid #334556;
+}
+
+.sidebar-container ul.nav-tabs li.active a {
+    border: none;
+    background: #f9f9f9;
+    color: #676a6c;
+    font-weight: bold;
+}
+
+.sidebar-container .nav-tabs>li.active>a:hover, .sidebar-container .nav-tabs>li.active>a:focus {
+    border: none;
+}
+
+.sidebar-container ul.sidebar-list {
+    margin: 0;
+    padding: 0;
+}
+
+.sidebar-container ul.sidebar-list li {
+    border-bottom: 1px solid #e7eaec;
+    padding: 15px 20px;
+    list-style: none;
+    font-size: 12px;
+}
+
+.sidebar-container .sidebar-message:nth-child(2n+2) {
+    background: #f9f9f9;
+}
+
+.sidebar-container ul.sidebar-list li a {
+    text-decoration: none;
+    color: inherit;
+}
+
+.sidebar-container .sidebar-content {
+    padding: 15px 20px;
+    font-size: 12px;
+}
+
+.sidebar-container .sidebar-title {
+    background: #f9f9f9;
+    padding: 20px;
+    border-bottom: 1px solid #e7eaec;
+}
+
+.sidebar-container .sidebar-title h3 {
+    margin-bottom: 3px;
+    padding-left: 2px;
+}
+
+.sidebar-container .tab-content h4 {
+    margin-bottom: 5px;
+}
+
+.sidebar-container .sidebar-message>a>.pull-left {
+    margin-right: 10px;
+}
+
+.sidebar-container .sidebar-message>a {
+    text-decoration: none;
+    color: inherit;
+}
+
+.sidebar-container .sidebar-message {
+    padding: 15px 20px;
+}
+
+.sidebar-container .sidebar-message .message-avatar {
+    height: 38px;
+    width: 38px;
+    border-radius: 50%;
+}
+
+.sidebar-container .setings-item {
+    padding: 15px 20px;
+    border-bottom: 1px solid #e7eaec;
+}
+
+body {
+    font-family: "open sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
+    font-size: 13px;
+    color: #676a6c;
+    overflow-x: hidden;
+}
+
+html, body {
+    height: 100%;
+}
+
+body.full-height-layout #wrapper, body.full-height-layout #page-wrapper {
+    height: 100%;
+}
+
+#page-wrapper {
+    min-height: auto;
+}
+
+body.boxed-layout #wrapper {
+    background-color: #2f4050;
+    max-width: 1200px;
+    margin: 0 auto;
+}
+
+.top-navigation.boxed-layout #wrapper, .boxed-layout #wrapper.top-navigation {
+    max-width: 1300px !important;
+}
+
+.block {
+    display: block;
+}
+
+a {
+    cursor: pointer;
+}
+
+a:hover, a:focus {
+    text-decoration: none;
+}
+
+.border-bottom {
+    border-bottom: 1px solid #e7eaec !important;
+}
+
+.font-bold {
+    font-weight: 600;
+}
+
+.font-noraml {
+    font-weight: 400;
+}
+
+.text-uppercase {
+    text-transform: uppercase;
+}
+
+.b-r {
+    border-right: 1px solid #e7eaec;
+}
+
+.hr-line-dashed {
+    border-top: 1px dashed #e7eaec;
+    color: #ffffff;
+    background-color: #ffffff;
+    height: 1px;
+    margin: 20px 0;
+}
+
+.hr-line-solid {
+    border-bottom: 1px solid #e7eaec;
+    background-color: rgba(0, 0, 0, 0);
+    border-style: solid !important;
+    margin-top: 15px;
+    margin-bottom: 15px;
+}
+
+video {
+    width: 100% !important;
+    height: auto !important;
+}
+/* GALLERY */
+.gallery>.row>div {
+    margin-bottom: 15px;
+}
+
+.fancybox img {
+    margin-bottom: 5px;
+    /* Only for demo */
+    width: 24%;
+}
+/* Summernote text editor  */
+.note-editor {
+    height: auto !important;
+    min-height: 100px;
+    border: solid 1px #e5e6e7;
+}
+/* MODAL */
+.modal-content {
+    background-clip: padding-box;
+    background-color: #FFFFFF;
+    border: 1px solid rgba(0, 0, 0, 0);
+    border-radius: 4px;
+    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
+    outline: 0 none;
+}
+
+.modal-dialog {
+    z-index: 1200;
+}
+
+.modal-body {
+    padding: 20px 30px 30px 30px;
+}
+
+.inmodal .modal-body {
+    background: #f8fafb;
+}
+
+.inmodal .modal-header {
+    padding: 30px 15px;
+    text-align: center;
+}
+
+.animated.modal.fade .modal-dialog {
+    -webkit-transform: none;
+    -ms-transform: none;
+    transform: none;
+}
+
+.inmodal .modal-title {
+    font-size: 26px;
+}
+
+.inmodal .modal-icon {
+    font-size: 84px;
+    color: #e2e3e3;
+}
+
+.modal-footer {
+    margin-top: 0;
+}
+/* WRAPPERS */
+#wrapper {
+    width: 100%;
+    overflow-x: hidden;
+    background-color: #2f4050;
+}
+
+.wrapper {
+    padding: 0 20px;
+}
+
+.wrapper-content {
+    padding: 20px;
+}
+
+#page-wrapper {
+    padding: 0 15px;
+    position: inherit;
+    margin: 0 0 0 200px;
+}
+
+.title-action {
+    text-align: right;
+    padding-top: 30px;
+}
+
+.ibox-content h1, .ibox-content h2, .ibox-content h3, .ibox-content h4,  .ibox-content h5, .ibox-title h1, .ibox-title h2, .ibox-title h3,  .ibox-title h4, .ibox-title h5 {
+    margin-top: 5px;
+}
+
+ul.unstyled, ol.unstyled {
+    list-style: none outside none;
+    margin-left: 0;
+}
+
+.big-icon {
+    font-size: 160px;
+    color: #e5e6e7;
+}
+/* FOOTER */
+.footer {
+    background: none repeat scroll 0 0 white;
+    border-top: 1px solid #e7eaec;
+    overflow: hidden;
+    padding: 10px 20px;
+    margin: 0 -15px;
+    height: 36px;
+}
+
+.footer.fixed_full {
+    position: fixed;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    z-index: 1000;
+    padding: 10px 20px;
+    background: white;
+    border-top: 1px solid #e7eaec;
+}
+
+.footer.fixed {
+    position: fixed;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    z-index: 1000;
+    padding: 10px 20px;
+    background: white;
+    border-top: 1px solid #e7eaec;
+    margin-left: 220px;
+}
+
+body.mini-navbar .footer.fixed, body.body-small.mini-navbar .footer.fixed {
+    margin: 0 0 0 70px;
+}
+
+body.mini-navbar.canvas-menu .footer.fixed, body.canvas-menu .footer.fixed {
+    margin: 0 !important;
+}
+
+body.fixed-sidebar.body-small.mini-navbar .footer.fixed {
+    margin: 0 0 0 220px;
+}
+
+body.body-small .footer.fixed {
+    margin-left: 0px;
+}
+/* PANELS */
+.page-heading {
+    border-top: 0;
+    padding: 0px 20px 20px;
+}
+
+.panel-heading h1, .panel-heading h2 {
+    margin-bottom: 5px;
+}
+/*CONTENTTABS*/
+.content-tabs {
+    position: relative;
+    height: 39px;
+    background: #fafafa;
+    line-height: 39px;
+}
+
+.content-tabs .roll-nav, .page-tabs-list {
+    position: absolute;
+    width: 30px;
+    height: 38px;
+    text-align: center;
+    color: #999;
+    z-index: 2;
+    top: 0;
+}
+
+.content-tabs .roll-left {
+    left: 0;
+    border-right: solid 1px #eee;
+}
+
+.content-tabs .roll-right {
+    right: 0;
+    border-left: solid 1px #eee;
+}
+
+.content-tabs button {
+    background: #fff;
+    border: 0;
+    height: 40px;
+    width: 40px;
+    outline: none;
+}
+
+.content-tabs button:hover {
+    background: #fafafa;
+}
+
+nav.page-tabs {
+    margin-left: 30px;
+    width: 100000px;
+    height: 39px;
+    overflow: hidden;
+}
+
+nav.page-tabs .page-tabs-content {
+    float: left;
+}
+
+.page-tabs a {
+    display: block;
+    float: left;
+    border-right: solid 1px #eee;
+    padding: 0 15px;
+}
+
+.page-tabs a i:hover {
+    color: #c00;
+}
+
+.page-tabs a:hover, .content-tabs .roll-nav:hover {
+    color: #777;
+    background: #f2f2f2;
+    cursor: pointer;
+}
+
+.roll-right.tabRight {
+    right: 60px;
+}
+
+.roll-right.btn-group {
+    right: 60px;
+    width: 80px;
+    padding: 0;
+}
+
+.roll-right.btn-group button {
+    width: 80px;
+}
+
+.roll-right.tabReload {
+    background: #fff;
+    height: 38px;
+    width: 60px;
+    outline: none;
+}
+
+.dropdown-menu-right {
+    left: auto;
+}
+
+#content-main {
+    height: calc(100% - 127px);
+    overflow: hidden;
+}
+
+.tagsview-hide#content-main {
+    height: calc(100% - 88px);
+    overflow: hidden;
+}
+
+.footer-hide#content-main {
+    height: calc(100% - 91px);
+    overflow: hidden;
+}
+
+.tagsview-footer-hide#content-main {
+    height: calc(100% - 52px);
+    overflow: hidden;
+}
+
+.fixed-nav #content-main {
+    height: calc(100% - 80px);
+    overflow: hidden;
+}
+/* TABLES */
+.table-bordered {
+    border: 1px solid #EBEBEB;
+}
+
+.table-bordered>thead>tr>th, .table-bordered>thead>tr>td {
+    background-color: #F5F5F6;
+    border-bottom-width: 1px;
+}
+
+.table-bordered>thead>tr>th, .table-bordered>tbody>tr>th,  .table-bordered>tfoot>tr>th, .table-bordered>thead>tr>td,  .table-bordered>tbody>tr>td, .table-bordered>tfoot>tr>td {
+    border: 1px solid #e7e7e7;
+}
+
+.table>thead>tr>th {
+    border-bottom: 1px solid #DDDDDD;
+    vertical-align: bottom;
+}
+
+.table>thead>tr>th, .table>tbody>tr>th, .table>tfoot>tr>th, .table>thead>tr>td,  .table>tbody>tr>td, .table>tfoot>tr>td {
+    border-top: 1px solid #e7eaec;
+    line-height: 1.42857;
+    padding: 8px;
+    vertical-align: middle;
+}
+/* PANELS */
+.panel.blank-panel {
+    background: none;
+    margin: 0;
+}
+
+.blank-panel .panel-heading {
+    padding-bottom: 0;
+}
+
+.nav-tabs>li.active>a, .nav-tabs>li.active>a:hover, .nav-tabs>li.active>a:focus {
+    -moz-border-bottom-colors: none;
+    -moz-border-left-colors: none;
+    -moz-border-right-colors: none;
+    -moz-border-top-colors: none;
+    background: none;
+    border-color: #dddddd #dddddd rgba(0, 0, 0, 0);
+    border-bottom: #f3f3f4;
+    -webkit-border-image: none;
+    -o-border-image: none;
+    border-image: none;
+    border-style: solid;
+    border-width: 1px;
+    color: #555555;
+    cursor: default;
+}
+
+.nav.nav-tabs li {
+    background: none;
+    border: none;
+}
+
+.nav-tabs>li>a {
+    color: #A7B1C2;
+    font-weight: 600;
+    padding: 10px 20px 10px 25px;
+}
+
+.nav-tabs>li>a:hover, .nav-tabs>li>a:focus {
+    background-color: #e6e6e6;
+    color: #676a6c;
+}
+
+.ui-tab .tab-content {
+    padding: 20px 0px;
+}
+/* GLOBAL  */
+.no-padding {
+    padding: 0 !important;
+}
+
+.no-borders {
+    border: none !important;
+}
+
+.no-margins {
+    margin: 0 !important;
+}
+
+.no-top-border {
+    border-top: 0 !important;
+}
+
+.ibox-content.text-box {
+    padding-bottom: 0px;
+    padding-top: 15px;
+}
+
+.border-left-right {
+    border-left: 1px solid #e7eaec;
+    border-right: 1px solid #e7eaec;
+    border-top: none;
+    border-bottom: none;
+}
+
+.border-left {
+    border-left: 1px solid #e7eaec;
+    border-right: none;
+    border-top: none;
+    border-bottom: none;
+}
+
+.border-right {
+    border-left: none;
+    border-right: 1px solid #e7eaec;
+    border-top: none;
+    border-bottom: none;
+}
+
+.full-width {
+    width: 100% !important;
+}
+
+.link-block {
+    font-size: 12px;
+    padding: 10px;
+}
+
+.nav.navbar-top-links .link-block a {
+    font-size: 12px;
+}
+
+.link-block a {
+    font-size: 10px;
+    color: inherit;
+}
+
+body.mini-navbar .branding {
+    display: none;
+}
+
+img.circle-border {
+    border: 6px solid #FFFFFF;
+    border-radius: 50%;
+}
+
+.branding {
+    float: left;
+    color: #FFFFFF;
+    font-size: 18px;
+    font-weight: 600;
+    padding: 17px 20px;
+    text-align: center;
+    background-color: #1ab394;
+}
+
+.login-panel {
+    margin-top: 25%;
+}
+
+.page-header {
+    padding: 20px 0 9px;
+    margin: 0 0 20px;
+    border-bottom: 1px solid #eeeeee;
+}
+
+.fontawesome-icon-list {
+    margin-top: 22px;
+}
+
+.fontawesome-icon-list .fa-hover a {
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+    display: block;
+    color: #222222;
+    line-height: 32px;
+    height: 32px;
+    padding-left: 10px;
+    border-radius: 4px;
+}
+
+.fontawesome-icon-list .fa-hover a .fa {
+    width: 32px;
+    font-size: 14px;
+    display: inline-block;
+    text-align: right;
+    margin-right: 10px;
+}
+
+.fontawesome-icon-list .fa-hover a:hover {
+    background-color: #1d9d74;
+    color: #ffffff;
+    text-decoration: none;
+}
+
+.fontawesome-icon-list .fa-hover a:hover .fa {
+    font-size: 30px;
+    vertical-align: -6px;
+}
+
+.fontawesome-icon-list .fa-hover a:hover .text-muted {
+    color: #bbe2d5;
+}
+
+.feature-list .col-md-4 {
+    margin-bottom: 22px;
+}
+
+.feature-list h4 .fa:before {
+    vertical-align: -10%;
+    font-size: 28px;
+    display: inline-block;
+    width: 1.07142857em;
+    text-align: center;
+    margin-right: 5px;
+}
+
+.ui-draggable .ibox-title {
+    cursor: move;
+}
+
+.breadcrumb {
+    background-color: #ffffff;
+    padding: 0;
+    margin-bottom: 0;
+}
+
+.breadcrumb>li a {
+    color: inherit;
+}
+
+.breadcrumb>.active {
+    color: inherit;
+}
+
+code {
+    background-color: #F9F2F4;
+    border-radius: 4px;
+    color: #ca4440;
+    font-size: 90%;
+    padding: 2px 4px;
+    white-space: nowrap;
+}
+
+.ibox {
+    clear: both;
+    margin-bottom: 25px;
+    margin-top: 0;
+    padding: 0;
+}
+
+.ibox.collapsed .ibox-content {
+    display: none;
+}
+
+.ibox.collapsed .fa.fa-chevron-up:before {
+    content: "\f078";
+}
+
+.ibox.collapsed .fa.fa-chevron-down:before {
+    content: "\f077";
+}
+
+.ibox:after, .ibox:before {
+    display: table;
+}
+
+.ibox-title {
+    -moz-border-bottom-colors: none;
+    -moz-border-left-colors: none;
+    -moz-border-right-colors: none;
+    -moz-border-top-colors: none;
+    background-color: #ffffff;
+    border-color: #e7eaec;
+    -webkit-border-image: none;
+    -o-border-image: none;
+    border-image: none;
+    border-style: solid solid none;
+    border-width: 0px 0px 0;
+    color: inherit;
+    margin-bottom: 0;
+    padding: 14px 15px 7px;
+    min-height: 40px;
+}
+
+.ibox-content {
+    background-color: #ffffff;
+    color: inherit;
+    padding: 15px 20px 20px 20px;
+    border-color: #e7eaec;
+    -webkit-border-image: none;
+    -o-border-image: none;
+    border-image: none;
+    border-style: solid solid none;
+    border-width: 1px 0px;
+}
+
+table.table-mail tr td {
+    padding: 12px;
+}
+
+.table-mail .check-mail {
+    padding-left: 20px;
+}
+
+.table-mail .mail-date {
+    padding-right: 20px;
+}
+
+.star-mail, .check-mail {
+    width: 40px;
+}
+
+.unread td a, .unread td {
+    font-weight: 600;
+    color: inherit;
+}
+
+.read td a, .read td {
+    font-weight: normal;
+    color: inherit;
+}
+
+.unread td {
+    background-color: #f9f8f8;
+}
+
+.ibox-content {
+    clear: both;
+}
+
+.ibox-heading {
+    background-color: #f3f6fb;
+    border-bottom: none;
+}
+
+.ibox-heading h3 {
+    font-weight: 200;
+    font-size: 24px;
+}
+
+.ibox-title h5 {
+    display: inline-block;
+    font-size: 14px;
+    margin: 0 0 7px;
+    padding: 0;
+    text-overflow: ellipsis;
+    float: left;
+}
+
+.ibox-title .label {
+    float: left;
+    margin-left: 4px;
+}
+
+.ibox-tools {
+    display: inline-block;
+    float: right;
+    margin-top: 0;
+    position: relative;
+    padding: 0;
+}
+
+.ibox-tools a {
+    cursor: pointer;
+    margin-left: 5px;
+    color: #676a6c;
+}
+
+.ibox-tools a.btn-primary {
+    color: #fff;
+}
+
+.ibox-tools .dropdown-menu>li>a {
+    padding: 4px 10px;
+    font-size: 12px;
+}
+
+.ibox .open>.dropdown-menu {
+    left: auto;
+    right: 0;
+}
+/* BACKGROUNDS */
+.gray-bg {
+    background-color: #f3f3f4;
+}
+
+.white-bg {
+    background-color: #ffffff;
+}
+
+.navy-bg {
+    background-color: #1ab394;
+    color: #ffffff;
+}
+
+.blue-bg {
+    background-color: #1c84c6;
+    color: #ffffff;
+}
+
+.lazur-bg {
+    background-color: #23c6c8;
+    color: #ffffff;
+}
+
+.yellow-bg {
+    background-color: #f8ac59;
+    color: #ffffff;
+}
+
+.red-bg {
+    background-color: #ed5565;
+    color: #ffffff;
+}
+
+.black-bg {
+    background-color: #262626;
+}
+
+.panel-primary {
+    border-color: #1ab394;
+}
+
+.panel-primary>.panel-heading {
+    background-color: #1ab394;
+    border-color: #1ab394;
+}
+
+.panel-success {
+    border-color: #1c84c6;
+}
+
+.panel-success>.panel-heading {
+    background-color: #1c84c6;
+    border-color: #1c84c6;
+    color: #ffffff;
+}
+
+.panel-info {
+    border-color: #23c6c8;
+}
+
+.panel-info>.panel-heading {
+    background-color: #23c6c8;
+    border-color: #23c6c8;
+    color: #ffffff;
+}
+
+.panel-warning {
+    border-color: #f8ac59;
+}
+
+.panel-warning>.panel-heading {
+    background-color: #f8ac59;
+    border-color: #f8ac59;
+    color: #ffffff;
+}
+
+.panel-danger {
+    border-color: #ed5565;
+}
+
+.panel-danger>.panel-heading {
+    background-color: #ed5565;
+    border-color: #ed5565;
+    color: #ffffff;
+}
+
+.progress-bar {
+    background-color: #1ab394;
+}
+
+.progress-small, .progress-small .progress-bar {
+    height: 10px;
+}
+
+.progress-small, .progress-mini {
+    margin-top: 5px;
+}
+
+.progress-mini, .progress-mini .progress-bar {
+    height: 5px;
+    margin-bottom: 0px;
+}
+
+.progress-bar-navy-light {
+    background-color: #3dc7ab;
+}
+
+.progress-bar-success {
+    background-color: #1c84c6;
+}
+
+.progress-bar-info {
+    background-color: #23c6c8;
+}
+
+.progress-bar-warning {
+    background-color: #f8ac59;
+}
+
+.progress-bar-danger {
+    background-color: #ed5565;
+}
+
+.panel-title {
+    font-size: inherit;
+}
+
+.jumbotron {
+    border-radius: 6px;
+    padding: 40px;
+}
+
+.jumbotron h1 {
+    margin-top: 0;
+}
+/* COLORS */
+.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;
+}
+
+.simple_tag {
+    background-color: #f3f3f4;
+    border: 1px solid #e7eaec;
+    border-radius: 2px;
+    color: inherit;
+    font-size: 10px;
+    margin-right: 5px;
+    margin-top: 5px;
+    padding: 5px 12px;
+    display: inline-block;
+}
+
+.img-shadow {
+    box-shadow: 0px 0px 3px 0px #919191;
+}
+/* For handle diferent bg color in AngularJS version */
+.dashboards\.dashboard_2 nav.navbar, .dashboards\.dashboard_3 nav.navbar,  .mailbox\.inbox nav.navbar, .mailbox\.email_view nav.navbar,  .mailbox\.email_compose nav.navbar, .dashboards\.dashboard_4_1 nav.navbar {
+    background: #fff;
+}
+/* For handle diferent bg color in MVC version */
+.Dashboard_2 .navbar.navbar-static-top, .Dashboard_3 .navbar.navbar-static-top,  .Dashboard_4_1 .navbar.navbar-static-top, .ComposeEmail .navbar.navbar-static-top,  .EmailView .navbar.navbar-static-top, .Inbox .navbar.navbar-static-top {
+    background: #fff;
+}
+
+a.close-canvas-menu {
+    position: absolute;
+    top: 10px;
+    right: 15px;
+    z-index: 1011;
+    color: #a7b1c2;
+}
+
+a.close-canvas-menu:hover {
+    color: #fff;
+}
+/* FULL HEIGHT */
+.full-height {
+    height: 100%;
+}
+
+.fh-breadcrumb {
+    height: calc(100% - 196px);
+    margin: 0 -15px;
+    position: relative;
+}
+
+.fh-no-breadcrumb {
+    height: calc(100% - 99px);
+    margin: 0 -15px;
+    position: relative;
+}
+
+.fh-column {
+    background: #fff;
+    height: 100%;
+    width: 240px;
+    float: left;
+}
+
+.modal-backdrop {
+    z-index: 2040 !important;
+}
+
+.modal {
+    z-index: 2050 !important;
+}
+
+.spiner-example {
+    height: 200px;
+    padding-top: 70px;
+}
+/* MARGINS & PADDINGS */
+.p-xxs {
+    padding: 5px;
+}
+
+.p-xs {
+    padding: 10px;
+}
+
+.p-sm {
+    padding: 15px;
+}
+
+.p-m {
+    padding: 20px;
+}
+
+.p-md {
+    padding: 25px;
+}
+
+.p-lg {
+    padding: 30px;
+}
+
+.p-xl {
+    padding: 40px;
+}
+
+.m-xxs {
+    margin: 2px 4px;
+}
+
+.m-xs {
+    margin: 5px;
+}
+
+.m-sm {
+    margin: 10px;
+}
+
+.m {
+    margin: 15px;
+}
+
+.m-md {
+    margin: 20px;
+}
+
+.m-lg {
+    margin: 30px;
+}
+
+.m-xl {
+    margin: 50px;
+}
+
+.m-n {
+    margin: 0 !important;
+}
+
+.m-l-none {
+    margin-left: 0;
+}
+
+.m-l-xs {
+    margin-left: 5px;
+}
+
+.m-l-sm {
+    margin-left: 10px;
+}
+
+.m-l {
+    margin-left: 15px;
+}
+
+.m-l-md {
+    margin-left: 20px;
+}
+
+.m-l-lg {
+    margin-left: 30px;
+}
+
+.m-l-xl {
+    margin-left: 40px;
+}
+
+.m-l-n-xxs {
+    margin-left: -1px;
+}
+
+.m-l-n-xs {
+    margin-left: -5px;
+}
+
+.m-l-n-sm {
+    margin-left: -10px;
+}
+
+.m-l-n {
+    margin-left: -15px;
+}
+
+.m-l-n-md {
+    margin-left: -20px;
+}
+
+.m-l-n-lg {
+    margin-left: -30px;
+}
+
+.m-l-n-xl {
+    margin-left: -40px;
+}
+
+.m-t-none {
+    margin-top: 0;
+}
+
+.m-t-xxs {
+    margin-top: 1px;
+}
+
+.m-t-xs {
+    margin-top: 5px;
+}
+
+.m-t-sm {
+    margin-top: 10px;
+}
+
+.m-t {
+    margin-top: 15px;
+}
+
+.m-t-md {
+    margin-top: 20px;
+}
+
+.m-t-lg {
+    margin-top: 30px;
+}
+
+.m-t-xl {
+    margin-top: 40px;
+}
+
+.m-t-n-xxs {
+    margin-top: -1px;
+}
+
+.m-t-n-xs {
+    margin-top: -5px;
+}
+
+.m-t-n-sm {
+    margin-top: -10px;
+}
+
+.m-t-n {
+    margin-top: -15px;
+}
+
+.m-t-n-md {
+    margin-top: -20px;
+}
+
+.m-t-n-lg {
+    margin-top: -30px;
+}
+
+.m-t-n-xl {
+    margin-top: -40px;
+}
+
+.m-r-none {
+    margin-right: 0;
+}
+
+.m-r-xxs {
+    margin-right: 1px;
+}
+
+.m-r-xs {
+    margin-right: 5px;
+}
+
+.m-r-sm {
+    margin-right: 10px;
+}
+
+.m-r {
+    margin-right: 15px;
+}
+
+.m-r-md {
+    margin-right: 20px;
+}
+
+.m-r-lg {
+    margin-right: 30px;
+}
+
+.m-r-xl {
+    margin-right: 40px;
+}
+
+.m-r-n-xxs {
+    margin-right: -1px;
+}
+
+.m-r-n-xs {
+    margin-right: -5px;
+}
+
+.m-r-n-sm {
+    margin-right: -10px;
+}
+
+.m-r-n {
+    margin-right: -15px;
+}
+
+.m-r-n-md {
+    margin-right: -20px;
+}
+
+.m-r-n-lg {
+    margin-right: -30px;
+}
+
+.m-r-n-xl {
+    margin-right: -40px;
+}
+
+.m-b-none {
+    margin-bottom: 0;
+}
+
+.m-b-xxs {
+    margin-bottom: 1px;
+}
+
+.m-b-xs {
+    margin-bottom: 5px;
+}
+
+.m-b-sm {
+    margin-bottom: 10px;
+}
+
+.m-b {
+    margin-bottom: 15px;
+}
+
+.m-b-md {
+    margin-bottom: 20px;
+}
+
+.m-b-lg {
+    margin-bottom: 30px;
+}
+
+.m-b-xl {
+    margin-bottom: 40px;
+}
+
+.m-b-n-xxs {
+    margin-bottom: -1px;
+}
+
+.m-b-n-xs {
+    margin-bottom: -5px;
+}
+
+.m-b-n-sm {
+    margin-bottom: -10px;
+}
+
+.m-b-n {
+    margin-bottom: -15px;
+}
+
+.m-b-n-md {
+    margin-bottom: -20px;
+}
+
+.m-b-n-lg {
+    margin-bottom: -30px;
+}
+
+.m-b-n-xl {
+    margin-bottom: -40px;
+}
+
+.space-15 {
+    margin: 15px 0;
+}
+
+.space-20 {
+    margin: 20px 0;
+}
+
+.space-25 {
+    margin: 25px 0;
+}
+
+.space-30 {
+    margin: 30px 0;
+}
+
+body.modal-open {
+    padding-right: inherit !important;
+}
+/* SEARCH PAGE */
+.search-form {
+    margin-top: 10px;
+}
+
+.search-result h3 {
+    margin-bottom: 0;
+    color: #1E0FBE;
+}
+
+.search-result .search-link {
+    color: #006621;
+}
+
+.search-result p {
+    font-size: 12px;
+    margin-top: 5px;
+}
+/* CONTACTS */
+.contact-box {
+    background-color: #ffffff;
+    border: 1px solid #e7eaec;
+    padding: 20px;
+    margin-bottom: 20px;
+}
+
+.contact-box a {
+    color: inherit;
+}
+
+/* INVOICE */
+.invoice-table tbody>tr>td:last-child, .invoice-table tbody>tr>td:nth-child(4),  .invoice-table tbody>tr>td:nth-child(3), .invoice-table tbody>tr>td:nth-child(2) {
+    text-align: right;
+}
+
+.invoice-table thead>tr>th:last-child, .invoice-table thead>tr>th:nth-child(4),  .invoice-table thead>tr>th:nth-child(3), .invoice-table thead>tr>th:nth-child(2) {
+    text-align: right;
+}
+
+.invoice-total>tbody>tr>td:first-child {
+    text-align: right;
+}
+
+.invoice-total>tbody>tr>td {
+    border: 0 none;
+}
+
+.invoice-total>tbody>tr>td:last-child {
+    border-bottom: 1px solid #DDDDDD;
+    text-align: right;
+    width: 15%;
+}
+/* ERROR & LOGIN & LOCKSCREEN*/
+.middle-box {
+    max-width: 400px;
+    z-index: 100;
+    margin: 0 auto;
+    padding-top: 40px;
+}
+
+.lockscreen.middle-box {
+    width: 200px;
+    padding-top: 110px;
+}
+
+.loginscreen.middle-box {
+    width: 300px;
+}
+
+.loginColumns {
+    max-width: 800px;
+    margin: 0 auto;
+    padding: 100px 20px 20px 20px;
+}
+
+.passwordBox {
+    max-width: 460px;
+    margin: 0 auto;
+    padding: 100px 20px 20px 20px;
+}
+
+.logo-name {
+    color: #e6e6e6;
+    font-size: 180px;
+    font-weight: 800;
+    letter-spacing: -10px;
+    margin-bottom: 0px;
+}
+
+.middle-box h1 {
+    font-size: 170px;
+}
+
+.wrapper .middle-box {
+    margin-top: 140px;
+}
+
+.lock-word {
+    z-index: 10;
+    position: absolute;
+    top: 110px;
+    left: 50%;
+    margin-left: -470px;
+}
+
+.lock-word span {
+    font-size: 100px;
+    font-weight: 600;
+    color: #e9e9e9;
+    display: inline-block;
+}
+
+.lock-word .first-word {
+    margin-right: 160px;
+}
+/* DASBOARD */
+.dashboard-header {
+    border-top: 0;
+    padding: 20px 20px 20px 20px;
+}
+
+.dashboard-header h2 {
+    margin-top: 10px;
+    font-size: 26px;
+}
+
+.fist-item {
+    border-top: none !important;
+}
+
+.statistic-box {
+    margin-top: 40px;
+}
+
+.dashboard-header .list-group-item span.label {
+    margin-right: 10px;
+}
+
+.list-group.clear-list .list-group-item {
+    border-top: 1px solid #e7eaec;
+    border-bottom: 0;
+    border-right: 0;
+    border-left: 0;
+    padding: 10px 0;
+}
+
+ul.clear-list:first-child {
+    border-top: none !important;
+}
+/* Intimeline */
+.timeline-item .date i {
+    position: absolute;
+    top: 0;
+    right: 0;
+    padding: 5px;
+    width: 30px;
+    text-align: center;
+    border-top: 1px solid #e7eaec;
+    border-bottom: 1px solid #e7eaec;
+    border-left: 1px solid #e7eaec;
+    background: #f8f8f8;
+}
+
+.timeline-item .date {
+    text-align: right;
+    width: 110px;
+    position: relative;
+    padding-top: 30px;
+}
+
+.timeline-item .content {
+    border-left: 1px solid #e7eaec;
+    border-top: 1px solid #e7eaec;
+    padding-top: 10px;
+    min-height: 100px;
+}
+
+.timeline-item .content:hover {
+    background: #f6f6f6;
+}
+/* PIN BOARD */
+ul.notes li, ul.tag-list li {
+    list-style: none;
+}
+
+ul.notes li h4 {
+    margin-top: 20px;
+    font-size: 16px;
+}
+
+ul.notes li div {
+    text-decoration: none;
+    color: #000;
+    background: #ffc;
+    display: block;
+    height: 140px;
+    width: 140px;
+    padding: 1em;
+    position: relative;
+}
+
+ul.notes li div small {
+    position: absolute;
+    top: 5px;
+    right: 5px;
+    font-size: 10px;
+}
+
+ul.notes li div a {
+    position: absolute;
+    right: 10px;
+    bottom: 10px;
+    color: inherit;
+}
+
+ul.notes li {
+    margin: 10px 40px 50px 0px;
+    float: left;
+}
+
+ul.notes li div p {
+    font-size: 12px;
+}
+
+ul.notes li div {
+    text-decoration: none;
+    color: #000;
+    background: #ffc;
+    display: block;
+    height: 140px;
+    width: 140px;
+    padding: 1em;
+    /* Firefox */
+    /* Safari+Chrome */
+    /* Opera */
+    box-shadow: 5px 5px 2px rgba(33, 33, 33, 0.7);
+}
+
+ul.notes li div {
+    -webkit-transform: rotate(-6deg);
+    -o-transform: rotate(-6deg);
+    -moz-transform: rotate(-6deg);
+}
+
+ul.notes li:nth-child(even) div {
+    -o-transform: rotate(4deg);
+    -webkit-transform: rotate(4deg);
+    -moz-transform: rotate(4deg);
+    position: relative;
+    top: 5px;
+}
+
+ul.notes li:nth-child(3n) div {
+    -o-transform: rotate(-3deg);
+    -webkit-transform: rotate(-3deg);
+    -moz-transform: rotate(-3deg);
+    position: relative;
+    top: -5px;
+}
+
+ul.notes li:nth-child(5n) div {
+    -o-transform: rotate(5deg);
+    -webkit-transform: rotate(5deg);
+    -moz-transform: rotate(5deg);
+    position: relative;
+    top: -10px;
+}
+
+ul.notes li div:hover, ul.notes li div:focus {
+    -webkit-transform: scale(1.1);
+    -moz-transform: scale(1.1);
+    -o-transform: scale(1.1);
+    position: relative;
+    z-index: 5;
+}
+
+ul.notes li div {
+    text-decoration: none;
+    color: #000;
+    background: #ffc;
+    display: block;
+    height: 210px;
+    width: 210px;
+    padding: 1em;
+    box-shadow: 5px 5px 7px rgba(33, 33, 33, 0.7);
+    -webkit-transition: -webkit-transform 0.15s linear;
+}
+/* FILE MANAGER */
+.file-box {
+    float: left;
+    width: 220px;
+}
+
+.file-manager h5 {
+    text-transform: uppercase;
+}
+
+.file-manager {
+    list-style: none outside none;
+    margin: 0;
+    padding: 0;
+}
+
+.folder-list li a {
+    color: #666666;
+    display: block;
+    padding: 5px 0;
+}
+
+.folder-list li {
+    border-bottom: 1px solid #e7eaec;
+    display: block;
+}
+
+.folder-list li i {
+    margin-right: 8px;
+    color: #3d4d5d;
+}
+
+.category-list li a {
+    color: #666666;
+    display: block;
+    padding: 5px 0;
+}
+
+.category-list li {
+    display: block;
+}
+
+.category-list li i {
+    margin-right: 8px;
+    color: #3d4d5d;
+}
+
+.category-list li a .text-navy {
+    color: #1ab394;
+}
+
+.category-list li a .text-primary {
+    color: #1c84c6;
+}
+
+.category-list li a .text-info {
+    color: #23c6c8;
+}
+
+.category-list li a .text-danger {
+    color: #EF5352;
+}
+
+.category-list li a .text-warning {
+    color: #F8AC59;
+}
+
+.file-manager h5.tag-title {
+    margin-top: 20px;
+}
+
+.tag-list li {
+    float: left;
+}
+
+.tag-list li a {
+    font-size: 10px;
+    background-color: #f3f3f4;
+    padding: 5px 12px;
+    color: inherit;
+    border-radius: 2px;
+    border: 1px solid #e7eaec;
+    margin-right: 5px;
+    margin-top: 5px;
+    display: block;
+}
+
+.file {
+    border: 1px solid #e7eaec;
+    padding: 0;
+    background-color: #ffffff;
+    position: relative;
+    margin-bottom: 20px;
+    margin-right: 20px;
+}
+
+.file-manager .hr-line-dashed {
+    margin: 15px 0;
+}
+
+.file .icon, .file .image {
+    height: 100px;
+    overflow: hidden;
+}
+
+.file .icon {
+    padding: 15px 10px;
+    text-align: center;
+}
+
+.file-control {
+    color: inherit;
+    font-size: 14px;
+    margin-right: 10px;
+}
+
+.file-control.active {
+    text-decoration: underline;
+}
+
+.file .icon i {
+    font-size: 70px;
+    color: #dadada;
+}
+
+.file .file-name {
+    padding: 10px;
+    background-color: #f8f8f8;
+    border-top: 1px solid #e7eaec;
+}
+
+.file-name small {
+    color: #676a6c;
+}
+
+.corner {
+    position: absolute;
+    display: inline-block;
+    width: 0;
+    height: 0;
+    line-height: 0;
+    border: 0.6em solid transparent;
+    border-right: 0.6em solid #f1f1f1;
+    border-bottom: 0.6em solid #f1f1f1;
+    right: 0em;
+    bottom: 0em;
+}
+
+a.compose-mail {
+    padding: 8px 10px;
+}
+
+.mail-search {
+    max-width: 300px;
+}
+/* PROFILE */
+.profile-content {
+    border-top: none !important;
+}
+
+.feed-activity-list .feed-element {
+    border-bottom: 1px solid #e7eaec;
+}
+
+.feed-element:first-child {
+    margin-top: 0;
+}
+
+.feed-element {
+    padding-bottom: 15px;
+}
+
+.feed-element, .feed-element .media {
+    margin-top: 15px;
+}
+
+.feed-element, .media-body {
+    overflow: hidden;
+}
+
+.feed-element>.pull-left {
+    margin-right: 10px;
+}
+
+.feed-element img.img-circle, .dropdown-messages-box img.img-circle {
+    width: 38px;
+    height: 38px;
+}
+
+.feed-element .well {
+    border: 1px solid #e7eaec;
+    box-shadow: none;
+    margin-top: 10px;
+    margin-bottom: 5px;
+    padding: 10px 20px;
+    font-size: 11px;
+    line-height: 16px;
+}
+
+.feed-element .actions {
+    margin-top: 10px;
+}
+
+.feed-element .photos {
+    margin: 10px 0;
+}
+
+.feed-photo {
+    max-height: 180px;
+    border-radius: 4px;
+    overflow: hidden;
+    margin-right: 10px;
+    margin-bottom: 10px;
+}
+/* MAILBOX */
+.mail-box {
+    background-color: #ffffff;
+    border: 1px solid #e7eaec;
+    border-top: 0;
+    padding: 0px;
+    margin-bottom: 20px;
+}
+
+.mail-box-header {
+    background-color: #ffffff;
+    border: 1px solid #e7eaec;
+    border-bottom: 0;
+    padding: 30px 20px 20px 20px;
+}
+
+.mail-box-header h2 {
+    margin-top: 0px;
+}
+
+.mailbox-content .tag-list li a {
+    background: #ffffff;
+}
+
+.mail-body {
+    border-top: 1px solid #e7eaec;
+    padding: 20px;
+}
+
+.mail-text {
+    border-top: 1px solid #e7eaec;
+}
+
+.mail-text .note-toolbar {
+    padding: 10px 15px;
+}
+
+.mail-body .form-group {
+    margin-bottom: 5px;
+}
+
+.mail-text .note-editor .note-toolbar {
+    background-color: #F9F8F8;
+}
+
+.mail-attachment {
+    border-top: 1px solid #e7eaec;
+    padding: 20px;
+    font-size: 12px;
+}
+
+.mailbox-content {
+    background: none;
+    border: none;
+    padding: 10px;
+}
+
+.mail-ontact {
+    width: 23%;
+}
+/* PROJECTS */
+.project-people, .project-actions {
+    text-align: right;
+    vertical-align: middle;
+}
+
+dd.project-people {
+    text-align: left;
+    margin-top: 5px;
+}
+
+.project-people img {
+    width: 32px;
+    height: 32px;
+}
+
+.project-title a {
+    font-size: 14px;
+    color: #676a6c;
+    font-weight: 600;
+}
+
+.project-list table tr td {
+    border-top: none;
+    border-bottom: 1px solid #e7eaec;
+    padding: 15px 10px;
+    vertical-align: middle;
+}
+
+.project-manager .tag-list li a {
+    font-size: 10px;
+    background-color: white;
+    padding: 5px 12px;
+    color: inherit;
+    border-radius: 2px;
+    border: 1px solid #e7eaec;
+    margin-right: 5px;
+    margin-top: 5px;
+    display: block;
+}
+
+.project-files li a {
+    font-size: 11px;
+    color: #676a6c;
+    margin-left: 10px;
+    line-height: 22px;
+}
+/* FAQ */
+.faq-item {
+    padding: 20px;
+    margin-bottom: 2px;
+    background: #fff;
+}
+
+.faq-question {
+    font-size: 18px;
+    font-weight: 600;
+    color: #1ab394;
+    display: block;
+}
+
+.faq-question:hover {
+    color: #179d82;
+}
+
+.faq-answer {
+    margin-top: 10px;
+    background: #f3f3f4;
+    border: 1px solid #e7eaec;
+    border-radius: 3px;
+    padding: 15px;
+}
+
+.faq-item .tag-item {
+    background: #f3f3f4;
+    padding: 2px 6px;
+    font-size: 10px;
+    text-transform: uppercase;
+}
+
+/* Chat view */
+.message-input {
+    height: 90px !important;
+}
+
+.chat-avatar {
+    width: 36px;
+    height: 36px;
+    float: left;
+    margin-right: 10px;
+}
+
+.chat-user-name {
+    padding: 10px;
+}
+
+.chat-user {
+    padding: 8px 10px;
+    border-bottom: 1px solid #e7eaec;
+}
+
+.chat-user a {
+    color: inherit;
+}
+
+.chat-view {
+    z-index: 20012;
+}
+
+.chat-users, .chat-statistic {
+    margin-left: -30px;
+}
+
+@media (max-width: 992px) {
+    .chat-users,
+    .chat-statistic {
+        margin-left: 0;
+    }
+}
+
+.chat-view .ibox-content {
+    padding: 0;
+}
+
+.chat-message {
+    padding: 10px 20px;
+}
+
+.message-avatar {
+    height: 48px;
+    width: 48px;
+    border: 1px solid #e7eaec;
+    border-radius: 4px;
+    margin-top: 1px;
+}
+
+.chat-discussion .chat-message.left .message-avatar {
+    float: left;
+    margin-right: 10px;
+}
+
+.chat-discussion .chat-message.right .message-avatar {
+    float: right;
+    margin-left: 10px;
+}
+
+.message {
+    background-color: #fff;
+    border: 1px solid #e7eaec;
+    text-align: left;
+    display: block;
+    padding: 10px 20px;
+    position: relative;
+    border-radius: 4px;
+}
+
+.chat-discussion .chat-message.left .message-date {
+    float: right;
+}
+
+.chat-discussion .chat-message.right .message-date {
+    float: left;
+}
+
+.chat-discussion .chat-message.left .message {
+    text-align: left;
+    margin-left: 55px;
+}
+
+.chat-discussion .chat-message.right .message {
+    text-align: right;
+    margin-right: 55px;
+}
+
+.message-date {
+    font-size: 10px;
+    color: #888888;
+}
+
+.message-content {
+    display: block;
+}
+
+.chat-discussion {
+    background: #eee;
+    padding: 15px;
+    height: 400px;
+    overflow-y: auto;
+}
+
+.chat-users {
+    overflow-y: auto;
+    height: 400px;
+}
+
+.chat-message-form .form-group {
+    margin-bottom: 0;
+}
+
+/* jsTree */
+.jstree-open>.jstree-anchor>.fa-folder:before {
+    content: "\f07c";
+}
+
+.jstree-default .jstree-icon.none {
+    width: 0;
+}
+/* CLIENTS */
+.clients-list {
+    margin-top: 20px;
+}
+
+.clients-list .tab-pane {
+    position: relative;
+    height: 600px;
+}
+
+.client-detail {
+    position: relative;
+    height: 620px;
+}
+
+.clients-list table tr td {
+    height: 46px;
+    vertical-align: middle;
+    border: none;
+}
+
+.client-link {
+    font-weight: 600;
+    color: inherit;
+}
+
+.client-link:hover {
+    color: inherit;
+}
+
+.client-avatar {
+    width: 42px;
+}
+
+.client-avatar img {
+    width: 28px;
+    height: 28px;
+    border-radius: 50%;
+}
+
+.contact-type {
+    width: 20px;
+    color: #c1c3c4;
+}
+
+.client-status {
+    text-align: left;
+}
+
+.client-detail .vertical-timeline-content p {
+    margin: 0;
+}
+
+.client-detail .vertical-timeline-icon.gray-bg {
+    color: #a7aaab;
+}
+
+.clients-list .nav-tabs>li.active>a, .clients-list .nav-tabs>li.active>a:hover,  .clients-list .nav-tabs>li.active>a:focus {
+    border-bottom: 1px solid #fff;
+}
+/* BLOG ARTICLE */
+.blog h2 {
+    font-weight: 700;
+}
+
+.blog h5 {
+    margin: 0 0 5px 0;
+}
+
+.blog .btn {
+    margin: 0 0 5px 0;
+}
+
+.article h1 {
+    font-size: 48px;
+    font-weight: 700;
+    color: #2F4050;
+}
+
+.article p {
+    font-size: 15px;
+    line-height: 26px;
+}
+
+.article-title {
+    text-align: center;
+    margin: 60px 0 40px 0;
+}
+
+.article .ibox-content {
+    padding: 40px;
+}
+/* ISSUE TRACKER */
+.issue-tracker .btn-link {
+    color: #1ab394;
+}
+
+table.issue-tracker tbody tr td {
+    vertical-align: middle;
+    height: 50px;
+}
+
+.issue-info {
+    width: 50%;
+}
+
+.issue-info a {
+    font-weight: 600;
+    color: #676a6c;
+}
+
+.issue-info small {
+    display: block;
+}
+/* TEAMS */
+.team-members {
+    margin: 10px 0;
+}
+
+.team-members img.img-circle {
+    width: 42px;
+    height: 42px;
+    margin-bottom: 5px;
+}
+/* AGILE BOARD */
+.sortable-list {
+    padding: 10px 0;
+}
+
+.agile-list {
+    list-style: none;
+    margin: 0;
+}
+
+.agile-list li {
+    background: #FAFAFB;
+    border: 1px solid #e7eaec;
+    margin: 0px 0 10px 0;
+    padding: 10px;
+    border-radius: 2px;
+}
+
+.agile-list li:hover {
+    cursor: pointer;
+    background: #fff;
+}
+
+.agile-list li.warning-element {
+    border-left: 3px solid #f8ac59;
+}
+
+.agile-list li.danger-element {
+    border-left: 3px solid #ed5565;
+}
+
+.agile-list li.info-element {
+    border-left: 3px solid #1c84c6;
+}
+
+.agile-list li.success-element {
+    border-left: 3px solid #1ab394;
+}
+
+.agile-detail {
+    margin-top: 5px;
+    font-size: 12px;
+}
+/* DIFF */
+ins {
+    background-color: #c6ffc6;
+    text-decoration: none;
+}
+
+del {
+    background-color: #ffc6c6;
+}
+
+#small-chat {
+    position: fixed;
+    bottom: 50px;
+    right: 26px;
+    z-index: 100;
+}
+
+#small-chat .badge {
+    position: absolute;
+    top: -3px;
+    right: -4px;
+}
+
+.open-small-chat {
+    height: 38px;
+    width: 38px;
+    display: block;
+    background: #1ab394;
+    padding: 9px 8px;
+    text-align: center;
+    color: #fff;
+    border-radius: 50%;
+}
+
+.open-small-chat:hover {
+    color: white;
+    background: #1ab394;
+}
+
+.small-chat-box {
+    display: none;
+    position: fixed;
+    bottom: 50px;
+    right: 80px;
+    background: #fff;
+    border: 1px solid #e7eaec;
+    width: 230px;
+    height: 320px;
+    border-radius: 4px;
+}
+
+.small-chat-box.ng-small-chat {
+    display: block;
+}
+
+.body-small .small-chat-box {
+    bottom: 70px;
+    right: 20px;
+}
+
+.small-chat-box.active {
+    display: block;
+}
+
+.small-chat-box .heading {
+    background: #2f4050;
+    padding: 8px 15px;
+    font-weight: bold;
+    color: #fff;
+}
+
+.small-chat-box .chat-date {
+    opacity: 0.6;
+    font-size: 10px;
+    font-weight: normal;
+}
+
+.small-chat-box .content {
+    padding: 15px 15px;
+}
+
+.small-chat-box .content .author-name {
+    font-weight: bold;
+    margin-bottom: 3px;
+    font-size: 11px;
+}
+
+.small-chat-box .content>div {
+    padding-bottom: 20px;
+}
+
+.small-chat-box .content .chat-message {
+    padding: 5px 10px;
+    border-radius: 6px;
+    font-size: 11px;
+    line-height: 14px;
+    max-width: 80%;
+    background: #f3f3f4;
+    margin-bottom: 10px;
+}
+
+.small-chat-box .content .chat-message.active {
+    background: #1ab394;
+    color: #fff;
+}
+
+.small-chat-box .content .left {
+    text-align: left;
+    clear: both;
+}
+
+.small-chat-box .content .left .chat-message {
+    float: left;
+}
+
+.small-chat-box .content .right {
+    text-align: right;
+    clear: both;
+}
+
+.small-chat-box .content .right .chat-message {
+    float: right;
+}
+
+.small-chat-box .form-chat {
+    padding: 10px 10px;
+}
+/*
+ *  Usage:
+ *
+ *    <div class="sk-spinner sk-spinner-rotating-plane"></div>
+ *
+ */
+.sk-spinner-rotating-plane.sk-spinner {
+    width: 30px;
+    height: 30px;
+    background-color: #1ab394;
+    margin: 0 auto;
+    -webkit-animation: sk-rotatePlane 1.2s infinite ease-in-out;
+    animation: sk-rotatePlane 1.2s infinite ease-in-out;
+}
+
+@-webkit-keyframes sk-rotatePlane {
+    0% {
+        -webkit-transform: perspective(120px) rotateX(0deg) rotateY(0deg);
+        transform: perspective(120px) rotateX(0deg) rotateY(0deg);
+    }
+
+    50% {
+        -webkit-transform: perspective(120px)  rotateX(-180 .1deg )  rotateY(0deg);
+        transform: perspective(120px)  rotateX(-180 .1deg )  rotateY(0deg);
+    }
+
+    100% {
+        -webkit-transform: perspective(120px)  rotateX(-180deg)  rotateY(-180deg);
+        transform: perspective(120px)  rotateX(-180deg)  rotateY(-180deg);
+    }
+}
+
+@keyframes sk-rotatePlane {
+    0% {
+        -webkit-transform: perspective(120px) rotateX(0deg) rotateY(0deg);
+        transform: perspective(120px) rotateX(0deg) rotateY(0deg);
+    }
+
+    50% {
+        -webkit-transform: perspective(120px)  rotateX(-180 .1deg)  rotateY(0deg);
+        transform: perspective(120px)  rotateX(-180 .1deg)  rotateY(0deg);
+    }
+
+    100% {
+        -webkit-transform: perspective(120px)  rotateX(-180deg)  rotateY(-179 .9deg );
+        transform: perspective(120px)  rotateX(-180deg)  rotateY(-179 .9deg );
+    }
+}
+/*
+ *  Usage:
+ *
+ *    <div class="sk-spinner sk-spinner-double-bounce">
+ *      <div class="sk-double-bounce1"></div>
+ *      <div class="sk-double-bounce2"></div>
+ *    </div>
+ *
+ */
+.sk-spinner-double-bounce.sk-spinner {
+    width: 40px;
+    height: 40px;
+    position: relative;
+    margin: 0 auto;
+}
+
+.sk-spinner-double-bounce .sk-double-bounce1, .sk-spinner-double-bounce .sk-double-bounce2 {
+    width: 100%;
+    height: 100%;
+    border-radius: 50%;
+    background-color: #1ab394;
+    opacity: 0.6;
+    position: absolute;
+    top: 0;
+    left: 0;
+    -webkit-animation: sk-doubleBounce 2s infinite ease-in-out;
+    animation: sk-doubleBounce 2s infinite ease-in-out;
+}
+
+.sk-spinner-double-bounce .sk-double-bounce2 {
+    -webkit-animation-delay: -1s;
+    animation-delay: -1s;
+}
+
+@-webkit-keyframes sk-doubleBounce {
+    0%, 100% {
+        -webkit-transform: scale(0);
+        transform: scale(0);
+    }
+
+    50% {
+        -webkit-transform: scale(1);
+        transform: scale(1);
+    }
+}
+
+@keyframes sk-doubleBounce {
+    0%, 100% {
+        -webkit-transform: scale(0);
+        transform: scale(0);
+    }
+
+    50% {
+        -webkit-transform: scale(1);
+        transform: scale(1);
+    }
+}
+/*
+ *  Usage:
+ *
+ *    <div class="sk-spinner sk-spinner-wave">
+ *      <div class="sk-rect1"></div>
+ *      <div class="sk-rect2"></div>
+ *      <div class="sk-rect3"></div>
+ *      <div class="sk-rect4"></div>
+ *      <div class="sk-rect5"></div>
+ *    </div>
+ *
+ */
+.sk-spinner-wave.sk-spinner {
+    margin: 0 auto;
+    width: 50px;
+    height: 30px;
+    text-align: center;
+    font-size: 10px;
+}
+
+.sk-spinner-wave div {
+    background-color: #1ab394;
+    height: 100%;
+    width: 6px;
+    display: inline-block;
+    -webkit-animation: sk-waveStretchDelay 1.2s infinite ease-in-out;
+    animation: sk-waveStretchDelay 1.2s infinite ease-in-out;
+}
+
+.sk-spinner-wave .sk-rect2 {
+    -webkit-animation-delay: -1.1s;
+    animation-delay: -1.1s;
+}
+
+.sk-spinner-wave .sk-rect3 {
+    -webkit-animation-delay: -1s;
+    animation-delay: -1s;
+}
+
+.sk-spinner-wave .sk-rect4 {
+    -webkit-animation-delay: -0.9s;
+    animation-delay: -0.9s;
+}
+
+.sk-spinner-wave .sk-rect5 {
+    -webkit-animation-delay: -0.8s;
+    animation-delay: -0.8s;
+}
+
+@-webkit-keyframes sk-waveStretchDelay {
+    0%, 40%, 100% {
+        -webkit-transform: scaleY(0.4);
+        transform: scaleY(0.4);
+    }
+
+    20% {
+        -webkit-transform: scaleY(1);
+        transform: scaleY(1);
+    }
+}
+
+@keyframes sk-waveStretchDelay {
+    0%, 40%, 100% {
+        -webkit-transform: scaleY(0.4);
+        transform: scaleY(0.4);
+    }
+
+    20% {
+        -webkit-transform: scaleY(1);
+        transform: scaleY(1);
+    }
+}
+/*
+ *  Usage:
+ *
+ *    <div class="sk-spinner sk-spinner-wandering-cubes">
+ *      <div class="sk-cube1"></div>
+ *      <div class="sk-cube2"></div>
+ *    </div>
+ *
+ */
+.sk-spinner-wandering-cubes.sk-spinner {
+    margin: 0 auto;
+    width: 32px;
+    height: 32px;
+    position: relative;
+}
+
+.sk-spinner-wandering-cubes .sk-cube1, .sk-spinner-wandering-cubes .sk-cube2 {
+    background-color: #1ab394;
+    width: 10px;
+    height: 10px;
+    position: absolute;
+    top: 0;
+    left: 0;
+    -webkit-animation: sk-wanderingCubeMove 1.8s infinite ease-in-out;
+    animation: sk-wanderingCubeMove 1.8s infinite ease-in-out;
+}
+
+.sk-spinner-wandering-cubes .sk-cube2 {
+    -webkit-animation-delay: -0.9s;
+    animation-delay: -0.9s;
+}
+
+@-webkit-keyframes sk-wanderingCubeMove {
+    25% {
+        -webkit-transform: translateX(42px) rotate(-90deg) scale(0.5);
+        transform: translateX(42px) rotate(-90deg) scale(0.5);
+    }
+
+    50% {
+        /* Hack to make FF rotate in the right direction */
+        -webkit-transform: translateX(42px)  translateY(42px)  rotate(-179deg);
+        transform: translateX(42px)  translateY(42px)  rotate(-179deg);
+    }
+
+    50.1% {
+        -webkit-transform: translateX(42px) translateY(42px) rotate(-180deg);
+        transform: translateX(42px) translateY(42px) rotate(-180deg);
+    }
+
+    75% {
+        -webkit-transform: translateX(0px)  translateY(42px)  rotate(-270deg)  scale(0 .5 );
+        transform: translateX(0px)  translateY(42px)  rotate(-270deg)  scale(0 .5 );
+    }
+
+    100% {
+        -webkit-transform: rotate(-360deg);
+        transform: rotate(-360deg);
+    }
+}
+
+@keyframes sk-wanderingCubeMove {
+    25% {
+        -webkit-transform: translateX(42px) rotate(-90deg) scale(0.5);
+        transform: translateX(42px) rotate(-90deg) scale(0.5);
+    }
+
+    50% {
+        /* Hack to make FF rotate in the right direction */
+        -webkit-transform: translateX(42px)  translateY(42px)  rotate(-179deg);
+        transform: translateX(42px)  translateY(42px)  rotate(-179deg);
+    }
+
+    50.1%{
+        -webkit-transform: translateX(42px) translateY(42px) rotate(-180deg);
+        transform: translateX(42px) translateY(42px) rotate(-180deg);
+    }
+
+    75% {
+        -webkit-transform: translateX(0px)  translateY(42px)  rotate(-270deg)  scale(0 .5 );
+        transform: translateX(0px)  translateY(42px)  rotate(-270deg)  scale(0 .5 );
+    }
+
+    100% {
+        -webkit-transform: rotate(-360deg);
+        transform: rotate(-360deg);
+    }
+}
+/*
+ *  Usage:
+ *
+ *    <div class="sk-spinner sk-spinner-pulse"></div>
+ *
+ */
+.sk-spinner-pulse.sk-spinner {
+    width: 40px;
+    height: 40px;
+    margin: 0 auto;
+    background-color: #1ab394;
+    border-radius: 100%;
+    -webkit-animation: sk-pulseScaleOut 1s infinite ease-in-out;
+    animation: sk-pulseScaleOut 1s infinite ease-in-out;
+}
+
+@-webkit-keyframes sk-pulseScaleOut {
+    0% {
+        -webkit-transform: scale(0);
+        transform: scale(0);
+    }
+
+    100% {
+        -webkit-transform: scale(1);
+        transform: scale(1);
+        opacity: 0;
+    }
+}
+
+@keyframes sk-pulseScaleOut {
+    0% {
+        -webkit-transform: scale(0);
+        transform: scale(0);
+    }
+
+    100% {
+        -webkit-transform: scale(1);
+        transform: scale(1);
+        opacity: 0;
+    }
+}
+/*
+ *  Usage:
+ *
+ *    <div class="sk-spinner sk-spinner-chasing-dots">
+ *      <div class="sk-dot1"></div>
+ *      <div class="sk-dot2"></div>
+ *    </div>
+ *
+ */
+.sk-spinner-chasing-dots.sk-spinner {
+    margin: 0 auto;
+    width: 40px;
+    height: 40px;
+    position: relative;
+    text-align: center;
+    -webkit-animation: sk-chasingDotsRotate 2s infinite linear;
+    animation: sk-chasingDotsRotate 2s infinite linear;
+}
+
+.sk-spinner-chasing-dots .sk-dot1, .sk-spinner-chasing-dots .sk-dot2 {
+    width: 60%;
+    height: 60%;
+    display: inline-block;
+    position: absolute;
+    top: 0;
+    background-color: #1ab394;
+    border-radius: 100%;
+    -webkit-animation: sk-chasingDotsBounce 2s infinite ease-in-out;
+    animation: sk-chasingDotsBounce 2s infinite ease-in-out;
+}
+
+.sk-spinner-chasing-dots .sk-dot2 {
+    top: auto;
+    bottom: 0px;
+    -webkit-animation-delay: -1s;
+    animation-delay: -1s;
+}
+
+@-webkit-keyframes sk-chasingDotsRotate {
+    100% {
+        -webkit-transform: rotate(360deg);
+        transform: rotate(360deg);
+    }
+}
+
+@keyframes sk-chasingDotsRotate {
+    100% {
+        -webkit-transform: rotate(360deg);
+        transform: rotate(360deg);
+    }
+}
+
+@-webkit-keyframes sk-chasingDotsBounce {
+    0%, 100% {
+        -webkit-transform: scale(0);
+        transform: scale(0);
+    }
+
+    50% {
+        -webkit-transform: scale(1);
+        transform: scale(1);
+    }
+}
+
+@keyframes sk-chasingDotsBounce {
+    0%, 100% {
+        -webkit-transform: scale(0);
+        transform: scale(0);
+    }
+
+    50% {
+        -webkit-transform: scale(1);
+        transform: scale(1);
+    }
+}
+/*
+ *  Usage:
+ *
+ *    <div class="sk-spinner sk-spinner-three-bounce">
+ *      <div class="sk-bounce1"></div>
+ *      <div class="sk-bounce2"></div>
+ *      <div class="sk-bounce3"></div>
+ *    </div>
+ *
+ */
+.sk-spinner-three-bounce.sk-spinner {
+    margin: 0 auto;
+    width: 70px;
+    text-align: center;
+}
+
+.sk-spinner-three-bounce div {
+    width: 18px;
+    height: 18px;
+    background-color: #1ab394;
+    border-radius: 100%;
+    display: inline-block;
+    -webkit-animation: sk-threeBounceDelay 1.4s infinite ease-in-out;
+    animation: sk-threeBounceDelay 1.4s infinite ease-in-out;
+    /* Prevent first frame from flickering when animation starts */
+    -webkit-animation-fill-mode: both;
+    animation-fill-mode: both;
+}
+
+.sk-spinner-three-bounce .sk-bounce1 {
+    -webkit-animation-delay: -0.32s;
+    animation-delay: -0.32s;
+}
+
+.sk-spinner-three-bounce .sk-bounce2 {
+    -webkit-animation-delay: -0.16s;
+    animation-delay: -0.16s;
+}
+
+@-webkit-keyframes sk-threeBounceDelay {
+    0%, 80%, 100% {
+        -webkit-transform: scale(0);
+        transform: scale(0);
+    }
+
+    40% {
+        -webkit-transform: scale(1);
+        transform: scale(1);
+    }
+}
+
+@keyframes sk-threeBounceDelay {
+    0%, 80%, 100% {
+        -webkit-transform: scale(0);
+        transform: scale(0);
+    }
+
+    40% {
+        -webkit-transform: scale(1);
+        transform: scale(1);
+    }
+}
+/*
+ *  Usage:
+ *
+ *    <div class="sk-spinner sk-spinner-circle">
+ *      <div class="sk-circle1 sk-circle"></div>
+ *      <div class="sk-circle2 sk-circle"></div>
+ *      <div class="sk-circle3 sk-circle"></div>
+ *      <div class="sk-circle4 sk-circle"></div>
+ *      <div class="sk-circle5 sk-circle"></div>
+ *      <div class="sk-circle6 sk-circle"></div>
+ *      <div class="sk-circle7 sk-circle"></div>
+ *      <div class="sk-circle8 sk-circle"></div>
+ *      <div class="sk-circle9 sk-circle"></div>
+ *      <div class="sk-circle10 sk-circle"></div>
+ *      <div class="sk-circle11 sk-circle"></div>
+ *      <div class="sk-circle12 sk-circle"></div>
+ *    </div>
+ *
+ */
+.sk-spinner-circle.sk-spinner {
+    margin: 0 auto;
+    width: 22px;
+    height: 22px;
+    position: relative;
+}
+
+.sk-spinner-circle .sk-circle {
+    width: 100%;
+    height: 100%;
+    position: absolute;
+    left: 0;
+    top: 0;
+}
+
+.sk-spinner-circle .sk-circle:before {
+    content: '';
+    display: block;
+    margin: 0 auto;
+    width: 20%;
+    height: 20%;
+    background-color: #1ab394;
+    border-radius: 100%;
+    -webkit-animation: sk-circleBounceDelay 1.2s infinite ease-in-out;
+    animation: sk-circleBounceDelay 1.2s infinite ease-in-out;
+    /* Prevent first frame from flickering when animation starts */
+    -webkit-animation-fill-mode: both;
+    animation-fill-mode: both;
+}
+
+.sk-spinner-circle .sk-circle2 {
+    -webkit-transform: rotate(30deg);
+    -ms-transform: rotate(30deg);
+    transform: rotate(30deg);
+}
+
+.sk-spinner-circle .sk-circle3 {
+    -webkit-transform: rotate(60deg);
+    -ms-transform: rotate(60deg);
+    transform: rotate(60deg);
+}
+
+.sk-spinner-circle .sk-circle4 {
+    -webkit-transform: rotate(90deg);
+    -ms-transform: rotate(90deg);
+    transform: rotate(90deg);
+}
+
+.sk-spinner-circle .sk-circle5 {
+    -webkit-transform: rotate(120deg);
+    -ms-transform: rotate(120deg);
+    transform: rotate(120deg);
+}
+
+.sk-spinner-circle .sk-circle6 {
+    -webkit-transform: rotate(150deg);
+    -ms-transform: rotate(150deg);
+    transform: rotate(150deg);
+}
+
+.sk-spinner-circle .sk-circle7 {
+    -webkit-transform: rotate(180deg);
+    -ms-transform: rotate(180deg);
+    transform: rotate(180deg);
+}
+
+.sk-spinner-circle .sk-circle8 {
+    -webkit-transform: rotate(210deg);
+    -ms-transform: rotate(210deg);
+    transform: rotate(210deg);
+}
+
+.sk-spinner-circle .sk-circle9 {
+    -webkit-transform: rotate(240deg);
+    -ms-transform: rotate(240deg);
+    transform: rotate(240deg);
+}
+
+.sk-spinner-circle .sk-circle10 {
+    -webkit-transform: rotate(270deg);
+    -ms-transform: rotate(270deg);
+    transform: rotate(270deg);
+}
+
+.sk-spinner-circle .sk-circle11 {
+    -webkit-transform: rotate(300deg);
+    -ms-transform: rotate(300deg);
+    transform: rotate(300deg);
+}
+
+.sk-spinner-circle .sk-circle12 {
+    -webkit-transform: rotate(330deg);
+    -ms-transform: rotate(330deg);
+    transform: rotate(330deg);
+}
+
+.sk-spinner-circle .sk-circle2:before {
+    -webkit-animation-delay: -1.1s;
+    animation-delay: -1.1s;
+}
+
+.sk-spinner-circle .sk-circle3:before {
+    -webkit-animation-delay: -1s;
+    animation-delay: -1s;
+}
+
+.sk-spinner-circle .sk-circle4:before {
+    -webkit-animation-delay: -0.9s;
+    animation-delay: -0.9s;
+}
+
+.sk-spinner-circle .sk-circle5:before {
+    -webkit-animation-delay: -0.8s;
+    animation-delay: -0.8s;
+}
+
+.sk-spinner-circle .sk-circle6:before {
+    -webkit-animation-delay: -0.7s;
+    animation-delay: -0.7s;
+}
+
+.sk-spinner-circle .sk-circle7:before {
+    -webkit-animation-delay: -0.6s;
+    animation-delay: -0.6s;
+}
+
+.sk-spinner-circle .sk-circle8:before {
+    -webkit-animation-delay: -0.5s;
+    animation-delay: -0.5s;
+}
+
+.sk-spinner-circle .sk-circle9:before {
+    -webkit-animation-delay: -0.4s;
+    animation-delay: -0.4s;
+}
+
+.sk-spinner-circle .sk-circle10:before {
+    -webkit-animation-delay: -0.3s;
+    animation-delay: -0.3s;
+}
+
+.sk-spinner-circle .sk-circle11:before {
+    -webkit-animation-delay: -0.2s;
+    animation-delay: -0.2s;
+}
+
+.sk-spinner-circle .sk-circle12:before {
+    -webkit-animation-delay: -0.1s;
+    animation-delay: -0.1s;
+}
+
+@-webkit-keyframes sk-circleBounceDelay {
+    0%, 80%, 100% {
+        -webkit-transform: scale(0);
+        transform: scale(0);
+    }
+
+    40% {
+        -webkit-transform: scale(1);
+        transform: scale(1);
+    }
+}
+
+@keyframes sk-circleBounceDelay {
+    0%, 80%, 100% {
+        -webkit-transform: scale(0);
+        transform: scale(0);
+    }
+
+    40% {
+        -webkit-transform: scale(1);
+        transform: scale(1);
+    }
+}
+/*
+ *  Usage:
+ *
+ *    <div class="sk-spinner sk-spinner-cube-grid">
+ *      <div class="sk-cube"></div>
+ *      <div class="sk-cube"></div>
+ *      <div class="sk-cube"></div>
+ *      <div class="sk-cube"></div>
+ *      <div class="sk-cube"></div>
+ *      <div class="sk-cube"></div>
+ *      <div class="sk-cube"></div>
+ *      <div class="sk-cube"></div>
+ *      <div class="sk-cube"></div>
+ *    </div>
+ *
+ */
+.sk-spinner-cube-grid {
+    /*
+       * Spinner positions
+       * 1 2 3
+       * 4 5 6
+       * 7 8 9
+       */
+}
+
+.sk-spinner-cube-grid.sk-spinner {
+    width: 30px;
+    height: 30px;
+    margin: 0 auto;
+}
+
+.sk-spinner-cube-grid .sk-cube {
+    width: 33%;
+    height: 33%;
+    background-color: #1ab394;
+    float: left;
+    -webkit-animation: sk-cubeGridScaleDelay 1.3s infinite ease-in-out;
+    animation: sk-cubeGridScaleDelay 1.3s infinite ease-in-out;
+}
+
+.sk-spinner-cube-grid .sk-cube:nth-child(1) {
+    -webkit-animation-delay: 0.2s;
+    animation-delay: 0.2s;
+}
+
+.sk-spinner-cube-grid .sk-cube:nth-child(2) {
+    -webkit-animation-delay: 0.3s;
+    animation-delay: 0.3s;
+}
+
+.sk-spinner-cube-grid .sk-cube:nth-child(3) {
+    -webkit-animation-delay: 0.4s;
+    animation-delay: 0.4s;
+}
+
+.sk-spinner-cube-grid .sk-cube:nth-child(4) {
+    -webkit-animation-delay: 0.1s;
+    animation-delay: 0.1s;
+}
+
+.sk-spinner-cube-grid .sk-cube:nth-child(5) {
+    -webkit-animation-delay: 0.2s;
+    animation-delay: 0.2s;
+}
+
+.sk-spinner-cube-grid .sk-cube:nth-child(6) {
+    -webkit-animation-delay: 0.3s;
+    animation-delay: 0.3s;
+}
+
+.sk-spinner-cube-grid .sk-cube:nth-child(7) {
+    -webkit-animation-delay: 0s;
+    animation-delay: 0s;
+}
+
+.sk-spinner-cube-grid .sk-cube:nth-child(8) {
+    -webkit-animation-delay: 0.1s;
+    animation-delay: 0.1s;
+}
+
+.sk-spinner-cube-grid .sk-cube:nth-child(9) {
+    -webkit-animation-delay: 0.2s;
+    animation-delay: 0.2s;
+}
+
+@-webkit-keyframes sk-cubeGridScaleDelay {
+    0%, 70%, 100% {
+        -webkit-transform: scale3D(1, 1, 1);
+        transform: scale3D(1, 1, 1);
+    }
+
+    35% {
+        -webkit-transform: scale3D(0, 0, 1);
+        transform: scale3D(0, 0, 1);
+    }
+}
+
+@keyframes sk-cubeGridScaleDelay {
+    0%, 70%, 100% {
+        -webkit-transform: scale3D(1, 1, 1);
+        transform: scale3D(1, 1, 1);
+    }
+
+    35% {
+        -webkit-transform: scale3D(0, 0, 1);
+        transform: scale3D(0, 0, 1);
+    }
+}
+/*
+ *  Usage:
+ *
+ *    <div class="sk-spinner sk-spinner-wordpress">
+ *      <span class="sk-inner-circle"></span>
+ *    </div>
+ *
+ */
+.sk-spinner-wordpress.sk-spinner {
+    background-color: #1ab394;
+    width: 30px;
+    height: 30px;
+    border-radius: 30px;
+    position: relative;
+    margin: 0 auto;
+    -webkit-animation: sk-innerCircle 1s linear infinite;
+    animation: sk-innerCircle 1s linear infinite;
+}
+
+.sk-spinner-wordpress .sk-inner-circle {
+    display: block;
+    background-color: #fff;
+    width: 8px;
+    height: 8px;
+    position: absolute;
+    border-radius: 8px;
+    top: 5px;
+    left: 5px;
+}
+
+@-webkit-keyframes sk-innerCircle {
+    0% {
+        -webkit-transform: rotate(0);
+        transform: rotate(0);
+    }
+
+    100% {
+        -webkit-transform: rotate(360deg);
+        transform: rotate(360deg);
+    }
+}
+
+@keyframes sk-innerCircle {
+    0% {
+        -webkit-transform: rotate(0);
+        transform: rotate(0);
+    }
+
+    100% {
+        -webkit-transform: rotate(360deg);
+        transform: rotate(360deg);
+    }
+}
+/*
+ *  Usage:
+ *
+ *    <div class="sk-spinner sk-spinner-fading-circle">
+ *      <div class="sk-circle1 sk-circle"></div>
+ *      <div class="sk-circle2 sk-circle"></div>
+ *      <div class="sk-circle3 sk-circle"></div>
+ *      <div class="sk-circle4 sk-circle"></div>
+ *      <div class="sk-circle5 sk-circle"></div>
+ *      <div class="sk-circle6 sk-circle"></div>
+ *      <div class="sk-circle7 sk-circle"></div>
+ *      <div class="sk-circle8 sk-circle"></div>
+ *      <div class="sk-circle9 sk-circle"></div>
+ *      <div class="sk-circle10 sk-circle"></div>
+ *      <div class="sk-circle11 sk-circle"></div>
+ *      <div class="sk-circle12 sk-circle"></div>
+ *    </div>
+ *
+ */
+.sk-spinner-fading-circle.sk-spinner {
+    margin: 0 auto;
+    width: 22px;
+    height: 22px;
+    position: relative;
+}
+
+.sk-spinner-fading-circle .sk-circle {
+    width: 100%;
+    height: 100%;
+    position: absolute;
+    left: 0;
+    top: 0;
+}
+
+.sk-spinner-fading-circle .sk-circle:before {
+    content: '';
+    display: block;
+    margin: 0 auto;
+    width: 18%;
+    height: 18%;
+    background-color: #1ab394;
+    border-radius: 100%;
+    -webkit-animation: sk-circleFadeDelay 1.2s infinite ease-in-out;
+    animation: sk-circleFadeDelay 1.2s infinite ease-in-out;
+    /* Prevent first frame from flickering when animation starts */
+    -webkit-animation-fill-mode: both;
+    animation-fill-mode: both;
+}
+
+.sk-spinner-fading-circle .sk-circle2 {
+    -webkit-transform: rotate(30deg);
+    -ms-transform: rotate(30deg);
+    transform: rotate(30deg);
+}
+
+.sk-spinner-fading-circle .sk-circle3 {
+    -webkit-transform: rotate(60deg);
+    -ms-transform: rotate(60deg);
+    transform: rotate(60deg);
+}
+
+.sk-spinner-fading-circle .sk-circle4 {
+    -webkit-transform: rotate(90deg);
+    -ms-transform: rotate(90deg);
+    transform: rotate(90deg);
+}
+
+.sk-spinner-fading-circle .sk-circle5 {
+    -webkit-transform: rotate(120deg);
+    -ms-transform: rotate(120deg);
+    transform: rotate(120deg);
+}
+
+.sk-spinner-fading-circle .sk-circle6 {
+    -webkit-transform: rotate(150deg);
+    -ms-transform: rotate(150deg);
+    transform: rotate(150deg);
+}
+
+.sk-spinner-fading-circle .sk-circle7 {
+    -webkit-transform: rotate(180deg);
+    -ms-transform: rotate(180deg);
+    transform: rotate(180deg);
+}
+
+.sk-spinner-fading-circle .sk-circle8 {
+    -webkit-transform: rotate(210deg);
+    -ms-transform: rotate(210deg);
+    transform: rotate(210deg);
+}
+
+.sk-spinner-fading-circle .sk-circle9 {
+    -webkit-transform: rotate(240deg);
+    -ms-transform: rotate(240deg);
+    transform: rotate(240deg);
+}
+
+.sk-spinner-fading-circle .sk-circle10 {
+    -webkit-transform: rotate(270deg);
+    -ms-transform: rotate(270deg);
+    transform: rotate(270deg);
+}
+
+.sk-spinner-fading-circle .sk-circle11 {
+    -webkit-transform: rotate(300deg);
+    -ms-transform: rotate(300deg);
+    transform: rotate(300deg);
+}
+
+.sk-spinner-fading-circle .sk-circle12 {
+    -webkit-transform: rotate(330deg);
+    -ms-transform: rotate(330deg);
+    transform: rotate(330deg);
+}
+
+.sk-spinner-fading-circle .sk-circle2:before {
+    -webkit-animation-delay: -1.1s;
+    animation-delay: -1.1s;
+}
+
+.sk-spinner-fading-circle .sk-circle3:before {
+    -webkit-animation-delay: -1s;
+    animation-delay: -1s;
+}
+
+.sk-spinner-fading-circle .sk-circle4:before {
+    -webkit-animation-delay: -0.9s;
+    animation-delay: -0.9s;
+}
+
+.sk-spinner-fading-circle .sk-circle5:before {
+    -webkit-animation-delay: -0.8s;
+    animation-delay: -0.8s;
+}
+
+.sk-spinner-fading-circle .sk-circle6:before {
+    -webkit-animation-delay: -0.7s;
+    animation-delay: -0.7s;
+}
+
+.sk-spinner-fading-circle .sk-circle7:before {
+    -webkit-animation-delay: -0.6s;
+    animation-delay: -0.6s;
+}
+
+.sk-spinner-fading-circle .sk-circle8:before {
+    -webkit-animation-delay: -0.5s;
+    animation-delay: -0.5s;
+}
+
+.sk-spinner-fading-circle .sk-circle9:before {
+    -webkit-animation-delay: -0.4s;
+    animation-delay: -0.4s;
+}
+
+.sk-spinner-fading-circle .sk-circle10:before {
+    -webkit-animation-delay: -0.3s;
+    animation-delay: -0.3s;
+}
+
+.sk-spinner-fading-circle .sk-circle11:before {
+    -webkit-animation-delay: -0.2s;
+    animation-delay: -0.2s;
+}
+
+.sk-spinner-fading-circle .sk-circle12:before {
+    -webkit-animation-delay: -0.1s;
+    animation-delay: -0.1s;
+}
+
+@-webkit-keyframes sk-circleFadeDelay {
+    0%, 39%, 100% {
+        opacity: 0;
+    }
+
+    40% {
+        opacity: 1;
+    }
+}
+
+@keyframes sk-circleFadeDelay {
+    0%,39%,100% {
+        opacity: 0;
+    }
+
+    40% {
+        opacity: 1;
+    }
+}
+
+body.rtls {
+    /* Theme config */
+}
+
+body.rtls #page-wrapper {
+    margin: 0 220px 0 0;
+}
+
+body.rtls .nav-second-level li a {
+    padding: 7px 35px 7px 10px;
+}
+
+body.rtls .ibox-title h5 {
+    float: right;
+}
+
+body.rtls .pull-right {
+    float: left !important;
+}
+
+body.rtls .pull-left {
+    float: right !important;
+}
+
+body.rtls .ibox-tools {
+    float: left;
+}
+
+body.rtls .stat-percent {
+    float: left;
+}
+
+body.rtls .navbar-right {
+    float: left !important;
+}
+
+body.rtls .navbar-top-links li:last-child {
+    margin-left: 40px;
+    margin-right: 0;
+}
+
+body.rtls .minimalize-styl-2 {
+    float: right;
+    margin: 14px 20px 5px 5px;
+}
+
+body.rtls .feed-element>.pull-left {
+    margin-left: 10px;
+    margin-right: 0;
+}
+
+body.rtls .timeline-item .date {
+    text-align: left;
+}
+
+body.rtls .timeline-item .date i {
+    left: 0;
+    right: auto;
+}
+
+body.rtls .timeline-item .content {
+    border-right: 1px solid #e7eaec;
+    border-left: none;
+}
+
+body.rtls .toast-close-button {
+    float: left;
+}
+
+body.rtls #toast-container>.toast:before {
+    margin: auto -1.5em auto 0.5em;
+}
+
+body.rtls #toast-container>div {
+    padding: 15px 50px 15px 15px;
+}
+
+body.rtls .center-orientation .vertical-timeline-icon i {
+    margin-left: 0;
+    margin-right: -12px;
+}
+
+body.rtls .vertical-timeline-icon i {
+    right: 50%;
+    left: auto;
+    margin-left: auto;
+    margin-right: -12px;
+}
+
+body.rtls .file-box {
+    float: right;
+}
+
+body.rtls ul.notes li {
+    float: right;
+}
+
+body.rtls .chat-users, body.rtls .chat-statistic {
+    margin-right: -30px;
+    margin-left: auto;
+}
+
+body.rtls .dropdown-menu>li>a {
+    text-align: right;
+}
+
+body.rtls .b-r {
+    border-left: 1px solid #e7eaec;
+    border-right: none;
+}
+
+body.rtls .dd-list .dd-list {
+    padding-right: 30px;
+    padding-left: 0;
+}
+
+body.rtls .dd-item>button {
+    float: right;
+}
+
+body.rtls .skin-setttings {
+    margin-right: 40px;
+    margin-left: 0;
+}
+
+body.rtls .skin-setttings {
+    direction: ltr;
+}
+
+body.rtls .footer.fixed {
+    margin-right: 220px;
+    margin-left: 0;
+}
+
+@media ( max-width : 992px) {
+    body.rtls .chat-users, body.rtls .chat-statistic {
+        margin-right: 0px;
+    }
+}
+
+body.rtls.mini-navbar .footer.fixed, body.body-small.mini-navbar .footer.fixed {
+    margin: 0 70px 0 0;
+}
+
+body.rtls.mini-navbar.fixed-sidebar .footer.fixed, body.body-small.mini-navbar .footer.fixed {
+    margin: 0 0 0 0;
+}
+
+body.rtls.top-navigation .navbar-toggle {
+    float: right;
+    margin-left: 15px;
+    margin-right: 15px;
+}
+
+.body-small.rtls.top-navigation .navbar-header {
+    float: none;
+}
+
+body.rtls.top-navigation #page-wrapper {
+    margin: 0;
+}
+
+body.rtls.mini-navbar #page-wrapper {
+    margin: 0 70px 0 0;
+}
+
+body.rtls.mini-navbar.fixed-sidebar #page-wrapper {
+    margin: 0 0 0 0;
+}
+
+body.rtls.body-small.fixed-sidebar.mini-navbar #page-wrapper {
+    margin: 0 220px 0 0;
+}
+
+body.rtls.body-small.fixed-sidebar.mini-navbar .navbar-static-side {
+    width: 220px;
+}
+
+.body-small.rtls .navbar-fixed-top {
+    margin-right: 0px;
+}
+
+.body-small.rtls .navbar-header {
+    float: right;
+}
+
+body.rtls .navbar-top-links li:last-child {
+    margin-left: 20px;
+}
+
+body.rtls .top-navigation #page-wrapper, body.rtls.mini-navbar .top-navigation #page-wrapper,  body.rtls.mini-navbar.top-navigation #page-wrapper {
+    margin: 0;
+}
+
+body.rtls .top-navigation .footer.fixed, body.rtls.top-navigation .footer.fixed {
+    margin: 0;
+}
+
+@media ( max-width : 768px) {
+    body.rtls .navbar-top-links li:last-child {
+        margin-left: 20px;
+    }
+
+    .body-small.rtls #page-wrapper {
+        position: inherit;
+        margin: 0 0 0 0px;
+        min-height: 1000px;
+    }
+
+    .body-small.rtls .navbar-static-side {
+        display: none;
+        z-index: 2001;
+        position: absolute;
+        width: 70px;
+    }
+
+    .body-small.rtls.mini-navbar .navbar-static-side {
+        display: block;
+    }
+
+    .rtls.fixed-sidebar.body-small .navbar-static-side {
+        display: none;
+        z-index: 2001;
+        position: fixed;
+        width: 220px;
+    }
+
+    .rtls.fixed-sidebar.body-small.mini-navbar .navbar-static-side {
+        display: block;
+    }
+}
+
+.rtls .ltr-support {
+    direction: ltr;
+}
+.page-tabs a {
+    color: #999;
+}
+
+.page-tabs a i {
+    color: #ccc;
+	margin-left: 2px;
+	font-size: 13px;
+}
+
+.page-tabs a.active {
+	background: #eaedf1;
+	color: #23508e;
+}
+.page-tabs a.active:hover,
+.page-tabs a.active i:hover {
+	background: #eaedf1;
+	color: #23508e;
+}
+
+@media ( min-width : 768px) {
+    .navbar-top-links .dropdown-messages, .navbar-top-links .dropdown-tasks,  .navbar-top-links .dropdown-alerts {
+        margin-left: auto;
+    }
+}
+
+@media ( max-width : 768px) {
+    body.fixed-sidebar .navbar-static-side {
+        display: none;
+    }
+
+    body.fixed-sidebar.mini-navbar .navbar-static-side {
+        width: 70px;
+    }
+
+    .lock-word {
+        display: none;
+    }
+
+    .navbar-form-custom {
+        display: none;
+    }
+
+    .navbar-header {
+        display: inline;
+        float: left;
+    }
+
+    .sidebard-panel {
+        z-index: 2;
+        position: relative;
+        width: auto;
+        min-height: 100% !important;
+    }
+
+    .sidebar-content .wrapper {
+        padding-right: 0px;
+        z-index: 1;
+    }
+
+    .fixed-sidebar.body-small .navbar-static-side {
+        display: none;
+        z-index: 2001;
+        position: fixed;
+        width: 220px;
+    }
+
+    .fixed-sidebar.body-small.mini-navbar .navbar-static-side {
+        display: block;
+    }
+
+    .ibox-tools {
+        float: none;
+        text-align: right;
+        display: block;
+    }
+
+    .content-tabs {
+        display: none;
+    }
+
+    #content-main {
+        height: calc(100% - 100px);
+    }
+
+    .fixed-nav #content-main {
+        height: calc(100% - 38px);
+    }
+}
+
+.navbar-static-side {
+    background: #2f4050;
+}
+
+.nav-close {
+    padding: 10px;
+    display: block;
+    position: absolute;
+    right: 5px;
+    top: 5px;
+    font-size: 1.4em;
+    cursor: pointer;
+    z-index: 10;
+    display: none;
+    color: rgba(255, 255, 255, .3);
+}
+
+@media ( max-width : 350px) {
+    body.fixed-sidebar.mini-navbar .navbar-static-side {
+        width: 0;
+    }
+
+    .nav-close {
+        display: block;
+    }
+
+    #page-wrapper {
+        margin-left: 0 !important;
+    }
+
+    .timeline-item .date {
+        text-align: left;
+        width: 110px;
+        position: relative;
+        padding-top: 30px;
+    }
+
+    .timeline-item .date i {
+        position: absolute;
+        top: 0;
+        left: 15px;
+        padding: 5px;
+        width: 30px;
+        text-align: center;
+        border: 1px solid #e7eaec;
+        background: #f8f8f8;
+    }
+
+    .timeline-item .content {
+        border-left: none;
+        border-top: 1px solid #e7eaec;
+        padding-top: 10px;
+        min-height: 100px;
+    }
+
+    .nav.navbar-top-links li.dropdown {
+        display: none;
+    }
+
+    .ibox-tools {
+        float: none;
+        text-align: left;
+        display: inline-block;
+    }
+}
+/*JQGRID*/
+.ui-jqgrid-titlebar {
+    height: 40px;
+    line-height: 24px;
+    color: #676a6c;
+    background-color: #F9F9F9;
+    text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
+}
+
+.ui-jqgrid .ui-jqgrid-title {
+    float: left;
+    margin-left: 5px;
+    font-weight: 700;
+}
+
+.ui-jqgrid .ui-jqgrid-titlebar {
+    position: relative;
+    border-left: 0px solid;
+    border-right: 0px solid;
+    border-top: 0px solid;
+}
+/* Social feed */
+.social-feed-separated .social-feed-box {
+    margin-left: 62px;
+}
+
+.social-feed-separated .social-avatar {
+    float: left;
+    padding: 0;
+}
+
+.social-feed-separated .social-avatar img {
+    width: 52px;
+    height: 52px;
+    border: 1px solid #e7eaec;
+}
+
+.social-feed-separated .social-feed-box .social-avatar {
+    padding: 15px 15px 0 15px;
+    float: none;
+}
+
+.social-feed-box {
+    /*padding: 15px;*/
+    border: 1px solid #e7eaec;
+    background: #fff;
+    margin-bottom: 15px;
+}
+
+.article .social-feed-box {
+    margin-bottom: 0;
+    border-bottom: none;
+}
+
+.article .social-feed-box:last-child {
+    margin-bottom: 0;
+    border-bottom: 1px solid #e7eaec;
+}
+
+.article .social-feed-box p {
+    font-size: 13px;
+    line-height: 18px;
+}
+
+.social-action {
+    margin: 15px;
+}
+
+.social-avatar {
+    padding: 15px 15px 0 15px;
+}
+
+.social-comment .social-comment {
+    margin-left: 45px;
+}
+
+.social-avatar img {
+    height: 40px;
+    width: 40px;
+    margin-right: 10px;
+}
+
+.social-avatar .media-body a {
+    font-size: 14px;
+    display: block;
+}
+
+.social-body {
+    padding: 15px;
+}
+
+.social-body img {
+    margin-bottom: 10px;
+}
+
+.social-footer {
+    border-top: 1px solid #e7eaec;
+    padding: 10px 15px;
+    background: #f9f9f9;
+}
+
+.social-footer .social-comment img {
+    width: 32px;
+    margin-right: 10px;
+}
+
+.social-comment:first-child {
+    margin-top: 0;
+}
+
+.social-comment {
+    margin-top: 15px;
+}
+
+.social-comment textarea {
+    font-size: 12px;
+}
+
+.checkbox input[type=checkbox], .checkbox-inline input[type=checkbox],  .radio input[type=radio], .radio-inline input[type=radio] {
+    /* margin-top: -4px; */
+}
+
+/* Only demo */
+@media ( max-width : 1000px) {
+    .welcome-message {
+        display: none;
+    }
+}
+/* ECHARTS  */
+.echarts {
+    height: 240px;
+}
+
+.checkbox-inline, .radio-inline, .checkbox-inline+.checkbox-inline,  .radio-inline+.radio-inline {
+    margin: 0 15px 0 0;
+    font-size: 14px;
+}
+
+.navbar-toggle {
+    background-color: #fff;
+}
+
+.menuTab {
+    -webkit-transition: all .3s ease-out 0s;
+    transition: all .3s ease-out 0s;
+}
+
+@media only screen and (-webkit-min-device-pixel-ratio : 2) {
+    #content-main {
+        -webkit-overflow-scrolling: touch;
+    }
+}
+
+.navbar-header {
+	/* width: 10%; */
+	height: 50px;
+}
+
+.bs-glyphicons {
+    margin: 0 -10px 20px;
+    overflow: hidden
+}
+
+.bs-glyphicons-list {
+    padding-left: 0;
+    list-style: none
+}
+
+.bs-glyphicons li {
+    float: left;
+    width: 25%;
+    height: 115px;
+    padding: 10px;
+    font-size: 10px;
+    line-height: 1.4;
+    text-align: center;
+    background-color: #f9f9f9;
+    border: 1px solid #fff
+}
+
+.bs-glyphicons .glyphicon {
+    margin-top: 5px;
+    margin-bottom: 10px;
+    font-size: 24px
+}
+
+.bs-glyphicons .glyphicon-class {
+    display: block;
+    text-align: center;
+    word-wrap: break-word
+}
+
+.bs-glyphicons li:hover {
+    color: #fff;
+    background-color: #1ab394;
+}
+
+@media ( min-width : 768px) {
+    .bs-glyphicons {
+        margin-right: 0;
+        margin-left: 0
+    }
+
+    .bs-glyphicons li {
+        width: 12.5%;
+        font-size: 12px
+    }
+}
+
+.t-bar {
+    padding-bottom: 10px;
+}
+.nopadding{
+    padding:0;
+}
+
+/*编辑器按钮样式冲突*/
+.note-editor .btn-default {
+    color: #333333!important;
+    background-color: #ffffff!important;
+    border-color: #cccccc!important;
+}
+
+.folder-list li.active a {
+	color: #2791df;
+	background: #f5f5f5;
+}
+
+nav .logo {
+	background-color: #367fa9;
+	color: #fff;
+	border-bottom: 0 solid transparent;
+	-webkit-transition: width .3s ease-in-out;
+	-o-transition: width .3s ease-in-out;
+	transition: width .3s ease-in-out;
+	display: block;
+	height: 50px;
+	font-size: 20px;
+	line-height: 50px;
+	text-align: center;
+	width: 200px;
+	font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+	padding: 0 15px;
+	font-weight: 300;
+	overflow: hidden
+}
+
+.logo-mini {
+	display: none;
+}
+
+.logo-lg {
+	display: block;
+}
+
+.roleList {
+	color: #d5d5d5;
+	margin-right: 10px;
+	padding-top: 10px;
+	line-height: 1;
+	white-space: nowrap;
+	overflow: hidden;
+	width: 110px;
+}
+
+.sidebar-collapse .user-panel {
+	white-space: nowrap;
+	position: relative;
+	width: 100%;
+	padding: 15px;
+	overflow: hidden;
+}
+
+.sidebar-collapse .user-panel .image>img {
+	width: 100%;
+	max-width: 45px;
+	height: auto;
+}
+
+.sidebar-collapse .user-panel>.info {
+	padding: 5px 5px 5px 15px;
+	line-height: 1;
+	position: absolute;
+	left: 55px;
+}
+
+.sidebar-collapse .user-panel>.info a {
+	color: #fff;
+	font-size: 12px;
+}
+
+.sidebar-collapse .user-panel>.info>p {
+	font-weight: 600;
+	margin-bottom: 9px;
+	color: #fff;
+	font-size: 12px;
+}
+
+.user-panel>.info>a>.fa,
+.user-panel>.info>a>.ion,
+.user-panel>.info>a>.glyphicon {
+	margin-right: 3px;
+}
+
+.nav>li:hover .dropdown-menu {
+	display: block;
+}
+
+#content-main.max {
+	height: calc(100% - 110px);
+	overflow: hidden;
+	width: 100%;
+	height: 100%;
+	left: 0px;
+	position: absolute;
+	top: 0px;
+	z-index: 9998;
+	margin: 0;
+}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/css/style.min.css b/ruoyi-admin/src/main/resources/static/css/style.min.css
new file mode 100644
index 0000000..7fb8ef3
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/css/style.min.css
@@ -0,0 +1 @@
+h1,h2,h3,h4,h5,h6{font-weight:100}h1{font-size:30px}h2{font-size:24px}h3{font-size:16px}h4{font-size:14px}h5{font-size:12px}h6{font-size:10px}h3,h4,h5{margin-top:5px;font-weight:600}a:focus{outline:0}.nav>li>a{color:#a7b1c2;font-weight:600;padding:14px 20px 14px 25px}.nav li>a{display:block}.nav.navbar-right>li>a,.nav.navbar-left>li>a{color:#fff;font-size:14px;height:50px;padding:15px 15px}.nav>li.active>a{color:#fff}.nav.navbar-right>li>a>.label,.nav.navbar-left>li>a>.label{position:absolute;top:9px;right:5px;text-align:center;font-size:9px;padding:2px 4px;line-height:.9}.nav.navbar-right>li>a:hover,.nav.navbar-left>li>a:hover{background-color:#367fa9;color:#fff}.navbar-default .nav>li>a:hover,.navbar-default .nav>li>a:focus{background-color:#293846;color:white}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background:#fff}.navbar{border:0}.navbar-default{background-color:transparent;border-color:#2f4050;position:relative}.nav.navbar-top-links li{display:inline-block}.navbar-top-links li:last-child{margin-right:16px}body.body-small .navbar-top-links li:last-child{margin-right:10px}.navbar-top-links li a{padding:20px 10px;min-height:50px}.dropdown-menu{border:medium none;display:none;float:left;font-size:12px;left:0;list-style:none outside none;padding:0;position:absolute;text-shadow:none;top:100%;z-index:1000;border-radius:0;box-shadow:0 0 3px rgba(86,96,117,0.3)}.dropdown-menu>li>a{border-radius:3px;color:inherit;line-height:25px;margin:4px;text-align:left;font-weight:normal}.dropdown-menu>li>a.font-bold{font-weight:600}.navbar-top-links .dropdown-menu li{display:block}.navbar-top-links .dropdown-menu li:last-child{margin-right:0}.navbar-top-links .dropdown-menu li a{padding:3px 20px;min-height:0}.navbar-top-links .dropdown-menu li a div{white-space:normal}.navbar-top-links .dropdown-messages,.navbar-top-links .dropdown-tasks,.navbar-top-links .dropdown-alerts{width:310px;min-width:0}.navbar-top-links .dropdown-messages{margin-left:5px}.navbar-top-links .dropdown-tasks{margin-left:-59px}.navbar-top-links .dropdown-alerts{margin-left:-123px}.navbar-top-links .dropdown-user{right:0;left:auto}.dropdown-messages,.dropdown-alerts{padding:10px 10px 10px 10px}.dropdown-messages li a,.dropdown-alerts li a{font-size:12px}.dropdown-messages li em,.dropdown-alerts li em{font-size:10px}.nav.navbar-top-links .dropdown-alerts a{font-size:12px}.nav>li.active{border-left:4px solid #19aa8d;background:#293846}.nav.nav-second-level>li.active{border:0}.nav.nav-second-level.collapse[style]{height:auto!important}.nav-header a{color:#dfe4ed}.nav-header .text-muted{color:#8095a8}.minimalize-styl-2{padding:4px 12px;margin:12px 5px 5px 15px;font-size:14px;float:left}.navbar-form-custom{float:left;height:50px;padding:0;width:200px;display:inline-table}.navbar-form-custom .form-group{margin-bottom:0}.nav.navbar-top-links a{font-size:14px}.navbar-form-custom .form-control{background:none repeat scroll 0 0 rgba(0,0,0,0);border:medium none;font-size:14px;height:60px;margin:0;z-index:2000}.count-info .label{line-height:12px;padding:1px 5px;position:absolute;right:6px;top:12px}.arrow{float:right;margin-top:2px}.fa.arrow:before{content:"\f104"}.active>a>.fa.arrow:before{content:"\f107"}.nav-second-level li,.nav-third-level li{border-bottom:none!important;padding-left:2px;padding-right:2px}.nav-second-level li a{padding:7px 15px 7px 10px;padding-left:52px}.nav-third-level li a{padding-left:70px}.nav-second-level li:last-child{margin-bottom:10px}body:not(.fixed-sidebar):not(.canvas-menu).mini-navbar .nav li:hover>.nav-second-level,.mini-navbar .nav li:focus>.nav-second-level{display:block;border-radius:0 2px 2px 0;min-width:140px;height:auto}body.mini-navbar .navbar-default .nav>li>.nav-second-level li a{font-size:12px;border-radius:0 2px 2px 0}body.mini-navbar .navbar-default .nav>li>.nav-third-level li a{padding-left:31px}.fixed-nav .slimScrollDiv #side-menu{padding-bottom:60px;position:relative}.fixed-sidebar.mini-navbar .slimScrollDiv>*{overflow:visible!important}.fixed-sidebar .slimScrollDiv>*{overflow-y:hidden;overflow-x:visible}.mini-navbar .nav-second-level li a{padding:10px 10px 10px 15px}.canvas-menu.mini-navbar .nav-second-level{background:#293846}.mini-navbar li.active .nav-second-level{left:65px}.navbar-default .special_link a{background:#1ab394;color:white}.navbar-default .special_link a:hover{background:#17987e!important;color:white}.navbar-default .special_link a span.label{background:#fff;color:#1ab394}.navbar-default .landing_link a{background:#1cc09f;color:white}.navbar-default .landing_link a:hover{background:#1ab394!important;color:white}.navbar-default .landing_link a span.label{background:#fff;color:#1cc09f}.logo-element{text-align:center;font-size:18px;font-weight:600;color:white;display:none;padding:18px 0}.navbar-fixed-top{background:#fff;-webkit-transition-duration:.5s;transition-duration:.5s;z-index:2030}.fixed-nav #wrapper{padding-top:60px;box-sizing:border-box}.fixed-nav .minimalize-styl-2{margin:14px 5px 5px 15px}.body-small .navbar-fixed-top{margin-left:0}body.mini-navbar .navbar-static-side{width:70px}body.mini-navbar .profile-element,body.mini-navbar .nav-label,body.mini-navbar .navbar-default .nav li a span{display:none}body.canvas-menu .profile-element{display:block}body:not(.fixed-sidebar):not(.canvas-menu).mini-navbar .nav-second-level{display:none}body.mini-navbar .navbar-default .nav>li>a{font-size:16px}body.mini-navbar .logo-element{display:block}body.canvas-menu .logo-element{display:none}body.mini-navbar .nav-header{padding:0;background-color:#1ab394}body.canvas-menu .nav-header{padding:33px 25px}body.mini-navbar #page-wrapper{margin:0 0 0 70px}body.canvas-menu.mini-navbar #page-wrapper,body.canvas-menu.mini-navbar .footer{margin:0}body.fixed-sidebar .navbar-static-side,body.canvas-menu .navbar-static-side{position:fixed;width:200px;z-index:2001;height:100%}body.fixed-sidebar.mini-navbar .navbar-static-side{width:70px}body.fixed-sidebar.mini-navbar #page-wrapper{margin:0 0 0 70px}body.body-small.fixed-sidebar.mini-navbar #page-wrapper{margin:0 0 0 70px}body.body-small.fixed-sidebar.mini-navbar .navbar-static-side{width:70px}.fixed-sidebar.mini-navbar .nav li>.nav-second-level{display:none}.fixed-sidebar.mini-navbar .nav li.active{border-left-width:0}.fixed-sidebar.mini-navbar .nav li:hover>a>span.nav-label{top:0;padding:10px 10px 10px 10px;text-align:center;background-color:#243747}.fixed-sidebar.mini-navbar .nav li:hover>.nav-second-level{top:40px;font-size:12px;background-color:#2f4050}.fixed-sidebar.mini-navbar .nav li:hover>.nav-second-level,.fixed-sidebar.mini-navbar .nav li:hover>a>span.nav-label{position:absolute;left:70px;display:block;min-width:140px;border-radius:2px}.fixed-sidebar.mini-navbar .nav li.active:hover>.nav-second-level,.fixed-sidebar.mini-navbar .nav li.active:hover>a>span.nav-label{left:67px}.fixed-sidebar.mini-navbar .nav .nav-second-level a>span,.fixed-sidebar.mini-navbar .nav .nav-third-level a>span{display:inline-block}body.fixed-sidebar.mini-navbar .navbar-default .nav>li>.nav-second-level li a{font-size:12px;border-radius:3px}body.canvas-menu.mini-navbar .navbar-default .nav>li>.nav-second-level li a{font-size:13px;border-radius:3px}.fixed-sidebar.mini-navbar .nav-second-level li a,.canvas-menu.mini-navbar .nav-second-level li a{padding:10px 10px 10px 15px}.fixed-sidebar.mini-navbar .nav-second-level,.canvas-menu.mini-navbar .nav-second-level{position:relative;padding:0;font-size:13px}.fixed-sidebar.mini-navbar li.active .nav-second-level,.canvas-menu.mini-navbar li.active .nav-second-level{left:0}body.canvas-menu nav.navbar-static-side{z-index:2001;background:#2f4050;height:100%;position:fixed;display:none}body.canvas-menu.mini-navbar nav.navbar-static-side{display:block;width:70px}.top-navigation #page-wrapper{margin-left:0}.top-navigation .navbar-nav .dropdown-menu>.active>a{background:white;color:#1ab394;font-weight:bold}.white-bg .navbar-fixed-top,.white-bg .navbar-static-top{background:#fff}.top-navigation .navbar{margin-bottom:0}.top-navigation .nav>li>a{padding:15px 20px;color:#676a6c}.top-navigation .nav>li a:hover,.top-navigation .nav>li a:focus{background:#fff;color:#1ab394}.top-navigation .nav>li.active{background:#fff;border:0}.top-navigation .nav>li.active>a{color:#1ab394}.top-navigation .navbar-right{padding-right:10px}.top-navigation .navbar-nav .dropdown-menu{box-shadow:none;border:1px solid #e7eaec}.top-navigation .dropdown-menu>li>a{margin:0;padding:7px 20px}.navbar .dropdown-menu{margin-top:0}.top-navigation .navbar-brand{background:#1ab394;color:#fff;padding:15px 25px}.top-navigation .navbar-top-links li:last-child{margin-right:0}.top-navigation.mini-navbar #page-wrapper,.top-navigation.body-small.fixed-sidebar.mini-navbar #page-wrapper,.mini-navbar .top-navigation #page-wrapper,.body-small.fixed-sidebar.mini-navbar .top-navigation #page-wrapper,.canvas-menu #page-wrapper{margin:0}.top-navigation.fixed-nav #wrapper,.fixed-nav #wrapper.top-navigation{margin-top:50px}.top-navigation .footer.fixed{margin-left:0!important}.top-navigation .wrapper.wrapper-content{padding:40px}.top-navigation.body-small .wrapper.wrapper-content,.body-small .top-navigation .wrapper.wrapper-content{padding:40px 0 40px 0}.navbar-toggle{background-color:#1ab394;color:#fff;padding:6px 12px;font-size:14px}.top-navigation .navbar-nav .open .dropdown-menu>li>a,.top-navigation .navbar-nav .open .dropdown-menu .dropdown-header{padding:10px 15px 10px 20px}@media(max-width :768px){.top-navigation .navbar-header{display:block;float:none}}.menu-visible-lg,.menu-visible-md{display:none!important}@media(min-width :1200px){.menu-visible-lg{display:block!important}}@media(min-width :992px){.menu-visible-md{display:block!important}}@media(max-width :767px){.menu-visible-md{display:block!important}.menu-visible-lg{display:block!important}}.btn{border-radius:3px}.float-e-margins .btn{margin-bottom:5px}.btn-w-m{min-width:120px}.btn-primary.btn-outline{color:#1ab394}.btn-success.btn-outline{color:#1c84c6}.btn-info.btn-outline{color:#23c6c8}.btn-warning.btn-outline{color:#f8ac59}.btn-danger.btn-outline{color:#ed5565}.btn-primary.btn-outline:hover,.btn-success.btn-outline:hover,.btn-info.btn-outline:hover,.btn-warning.btn-outline:hover,.btn-danger.btn-outline:hover{color:#fff}.btn-primary{background-color:#1ab394;border-color:#1ab394;color:#fff}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{background-color:#18a689;border-color:#18a689;color:#fff}.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary.disabled:hover,.btn-primary.disabled:focus,.btn-primary.disabled:active,.btn-primary.disabled.active,.btn-primary[disabled],.btn-primary[disabled]:hover,.btn-primary[disabled]:focus,.btn-primary[disabled]:active,.btn-primary.active[disabled],fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary:hover,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary.active{background-color:#1dc5a3;border-color:#1dc5a3}.btn-success{background-color:#1c84c6;border-color:#1c84c6;color:#fff}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{background-color:#1a7bb9!important;border-color:#1a7bb9!important;color:#fff}.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success.disabled:hover,.btn-success.disabled:focus,.btn-success.disabled:active,.btn-success.disabled.active,.btn-success[disabled],.btn-success[disabled]:hover,.btn-success[disabled]:focus,.btn-success[disabled]:active,.btn-success.active[disabled],fieldset[disabled] .btn-success,fieldset[disabled] .btn-success:hover,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success.active{background-color:#1f90d8;border-color:#1f90d8}.btn-info{background-color:#23c6c8;border-color:#23c6c8;color:#fff}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{background-color:#21b9bb;border-color:#21b9bb;color:#fff}.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info.disabled:hover,.btn-info.disabled:focus,.btn-info.disabled:active,.btn-info.disabled.active,.btn-info[disabled],.btn-info[disabled]:hover,.btn-info[disabled]:focus,.btn-info[disabled]:active,.btn-info.active[disabled],fieldset[disabled] .btn-info,fieldset[disabled] .btn-info:hover,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info.active{background-color:#26d7d9;border-color:#26d7d9}.btn-default{background-color:#f4f4f4;border-color:#ddd;color:#444}.btn-default:hover,.btn-default:focus,.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{background-color:#e7e7e7;border-color:#e7e7e7;color:#444}.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default.disabled:hover,.btn-default.disabled:focus,.btn-default.disabled:active,.btn-default.disabled.active,.btn-default[disabled],.btn-default[disabled]:hover,.btn-default[disabled]:focus,.btn-default[disabled]:active,.btn-default.active[disabled],fieldset[disabled] .btn-default,fieldset[disabled] .btn-default:hover,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default.active{background-color:#ccc;border-color:#ccc}.btn-warning{background-color:#f8ac59;border-color:#f8ac59;color:#fff}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{background-color:#f7a54a;border-color:#f7a54a;color:#fff}.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning.disabled:hover,.btn-warning.disabled:focus,.btn-warning.disabled:active,.btn-warning.disabled.active,.btn-warning[disabled],.btn-warning[disabled]:hover,.btn-warning[disabled]:focus,.btn-warning[disabled]:active,.btn-warning.active[disabled],fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning:hover,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning.active{background-color:#f9b66d;border-color:#f9b66d}.btn-danger{background-color:#ed5565;border-color:#ed5565;color:#fff}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{background-color:#ec4758;border-color:#ec4758;color:#fff}.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger.disabled:hover,.btn-danger.disabled:focus,.btn-danger.disabled:active,.btn-danger.disabled.active,.btn-danger[disabled],.btn-danger[disabled]:hover,.btn-danger[disabled]:focus,.btn-danger[disabled]:active,.btn-danger.active[disabled],fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger:hover,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger.active{background-color:#ef6776;border-color:#ef6776}.btn-link{color:inherit}.btn-link:hover,.btn-link:focus,.btn-link:active,.btn-link.active,.open .dropdown-toggle.btn-link{color:#1ab394;text-decoration:none}.btn-link:active,.btn-link.active,.open .dropdown-toggle.btn-link{background-image:none}.btn-link.disabled,.btn-link.disabled:hover,.btn-link.disabled:focus,.btn-link.disabled:active,.btn-link.disabled.active,.btn-link[disabled],.btn-link[disabled]:hover,.btn-link[disabled]:focus,.btn-link[disabled]:active,.btn-link.active[disabled],fieldset[disabled] .btn-link,fieldset[disabled] .btn-link:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:active,fieldset[disabled] .btn-link.active{color:#cacaca}.btn-white{color:inherit;background:white;border:1px solid #e7eaec}.btn-white:hover,.btn-white:focus,.btn-white:active,.btn-white.active,.open .dropdown-toggle.btn-white{color:inherit;border:1px solid #d2d2d2}.btn-white:active,.btn-white.active{box-shadow:0 2px 5px rgba(0,0,0,0.15) inset}.btn-white:active,.btn-white.active,.open .dropdown-toggle.btn-white{background-image:none}.btn-white.disabled,.btn-white.disabled:hover,.btn-white.disabled:focus,.btn-white.disabled:active,.btn-white.disabled.active,.btn-white[disabled],.btn-white[disabled]:hover,.btn-white[disabled]:focus,.btn-white[disabled]:active,.btn-white.active[disabled],fieldset[disabled] .btn-white,fieldset[disabled] .btn-white:hover,fieldset[disabled] .btn-white:focus,fieldset[disabled] .btn-white:active,fieldset[disabled] .btn-white.active{color:#cacaca}.form-control,.has-error .form-control:focus,.has-success .form-control:focus,.has-warning .form-control:focus,.navbar-collapse,.navbar-form,.navbar-form-custom .form-control:focus,.navbar-form-custom .form-control:hover,.open .btn.dropdown-toggle,.panel,.popover,.progress,.progress-bar{box-shadow:none}.btn-outline{color:inherit;background-color:transparent;-webkit-transition:all .5s;transition:all .5s}.btn-rounded{border-radius:50px}.btn-large-dim{width:90px;height:90px;font-size:42px}button.dim{display:inline-block;color:#fff;text-decoration:none;text-transform:uppercase;text-align:center;padding-top:6px;margin-right:10px;position:relative;cursor:pointer;border-radius:5px;font-weight:600;margin-bottom:20px!important}button.dim:active{top:3px}button.btn-primary.dim{box-shadow:inset 0 0 0 #16987e,0px 5px 0 0 #16987e,0px 10px 5px #999}button.btn-primary.dim:active{box-shadow:inset 0 0 0 #16987e,0px 2px 0 0 #16987e,0px 5px 3px #999}button.btn-default.dim{box-shadow:inset 0 0 0 #b3b3b3,0px 5px 0 0 #b3b3b3,0px 10px 5px #999}button.btn-default.dim:active{box-shadow:inset 0 0 0 #b3b3b3,0px 2px 0 0 #b3b3b3,0px 5px 3px #999}button.btn-warning.dim{box-shadow:inset 0 0 0 #f79d3c,0px 5px 0 0 #f79d3c,0px 10px 5px #999}button.btn-warning.dim:active{box-shadow:inset 0 0 0 #f79d3c,0px 2px 0 0 #f79d3c,0px 5px 3px #999}button.btn-info.dim{box-shadow:inset 0 0 0 #1eacae,0px 5px 0 0 #1eacae,0px 10px 5px #999}button.btn-info.dim:active{box-shadow:inset 0 0 0 #1eacae,0px 2px 0 0 #1eacae,0px 5px 3px #999}button.btn-success.dim{box-shadow:inset 0 0 0 #1872ab,0px 5px 0 0 #1872ab,0px 10px 5px #999}button.btn-success.dim:active{box-shadow:inset 0 0 0 #1872ab,0px 2px 0 0 #1872ab,0px 5px 3px #999}button.btn-danger.dim{box-shadow:inset 0 0 0 #ea394c,0px 5px 0 0 #ea394c,0px 10px 5px #999}button.btn-danger.dim:active{box-shadow:inset 0 0 0 #ea394c,0px 2px 0 0 #ea394c,0px 5px 3px #999}button.dim:before{font-size:50px;line-height:1em;font-weight:normal;color:#fff;display:block;padding-top:10px}button.dim:active:before{top:7px;font-size:50px}.label{background-color:#d1dade;color:#5e5e5e;font-size:10px;font-weight:600;padding:3px 8px;text-shadow:none}.badge{background-color:#d1dade;color:#5e5e5e;font-size:11px;font-weight:600;padding-bottom:4px;padding-left:6px;padding-right:6px;text-shadow:none}.label-primary,.badge-primary{background-color:#1ab394;color:#fff}.label-success,.badge-success{background-color:#1c84c6;color:#fff}.label-warning,.badge-warning{background-color:#f8ac59;color:#fff}.label-warning-light,.badge-warning-light{background-color:#f8ac59;color:#fff}.label-danger,.badge-danger{background-color:#ed5565;color:#fff}.label-info,.badge-info{background-color:#23c6c8;color:#fff}.label-inverse,.badge-inverse{background-color:#262626;color:#fff}.label-white,.badge-white{background-color:#fff;color:#5e5e5e}.label-white,.badge-disable{background-color:#2a2e36;color:#8b91a0}.onoffswitch{position:relative;width:64px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.onoffswitch-checkbox{display:none}.onoffswitch-label{display:block;overflow:hidden;cursor:pointer;border:2px solid #1ab394;border-radius:2px}.onoffswitch-inner{width:200%;margin-left:-100%;-webkit-transition:margin .3s ease-in 0s;transition:margin .3s ease-in 0s}.onoffswitch-inner:before,.onoffswitch-inner:after{float:left;width:50%;height:20px;padding:0;line-height:20px;font-size:12px;color:white;font-family:Trebuchet,Arial,sans-serif;font-weight:bold;box-sizing:border-box}.onoffswitch-inner:before{content:"ON";padding-left:10px;background-color:#1ab394;color:#fff}.onoffswitch-inner:after{content:"OFF";padding-right:10px;background-color:#fff;color:#999;text-align:right}.onoffswitch-switch{width:20px;margin:0;background:#fff;border:2px solid #1ab394;border-radius:2px;position:absolute;top:0;bottom:0;right:44px;-webkit-transition:all .3s ease-in 0s;transition:all .3s ease-in 0s}.onoffswitch-checkbox:checked+.onoffswitch-label .onoffswitch-inner{margin-left:0}.onoffswitch-checkbox:checked+.onoffswitch-label .onoffswitch-switch{right:0}.chosen-container-single .chosen-single{background:#fff;box-shadow:none;-moz-box-sizing:border-box;background-color:#fff;border:1px solid #cbd5dd;border-radius:2px;cursor:text;height:auto!important;margin:0;min-height:30px;overflow:hidden;padding:4px 12px;position:relative;width:100%}.chosen-container-multi .chosen-choices li.search-choice{background:#f1f1f1;border:1px solid #ededed;border-radius:2px;box-shadow:none;color:#333;cursor:default;line-height:13px;margin:3px 0 3px 5px;padding:3px 20px 3px 5px;position:relative}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{background-color:#f4f4f4;border-color:#ddd;color:inherit;cursor:default;z-index:2}.pagination>li>a,.pagination>li>span{background-color:#fff;border:1px solid #ddd;color:inherit;float:left;line-height:1.42857;margin-left:-1px;padding:4px 10px;position:relative;text-decoration:none}.tooltip-inner{background-color:#2f4050;word-break:break-all;overflow-wrap:break-word}.tooltip.top .tooltip-arrow{border-top-color:#2f4050}.tooltip.right .tooltip-arrow{border-right-color:#2f4050}.tooltip.bottom .tooltip-arrow{border-bottom-color:#2f4050}.tooltip.left .tooltip-arrow{border-left-color:#2f4050}.easypiechart{position:relative;text-align:center}.easypiechart .h2{margin-left:10px;margin-top:10px;display:inline-block}.easypiechart canvas{top:0;left:0}.easypiechart .easypie-text{line-height:1;position:absolute;top:33px;width:100%;z-index:1}.easypiechart img{margin-top:-4px}.jqstooltip{box-sizing:content-box}.fc-state-default{background-color:#fff;background-image:none;background-repeat:repeat-x;box-shadow:none;color:#333;text-shadow:none}.fc-state-default{border:1px solid}.fc-button{color:inherit;border:1px solid #e7eaec;cursor:pointer;display:inline-block;height:1.9em;line-height:1.9em;overflow:hidden;padding:0 .6em;position:relative;white-space:nowrap}.fc-state-active{background-color:#1ab394;border-color:#1ab394;color:#fff}.fc-header-title h2{font-size:16px;font-weight:600;color:inherit}.fc-content .fc-widget-header,.fc-content .fc-widget-content{border-color:#e7eaec;font-weight:normal}.fc-border-separate tbody{background-color:#f8f8f8}.fc-state-highlight{background:none repeat scroll 0 0 #fcf8e3}.external-event{padding:5px 10px;border-radius:2px;cursor:pointer;margin-bottom:5px}.fc-ltr .fc-event-hori.fc-event-end,.fc-rtl .fc-event-hori.fc-event-start{border-radius:2px}.fc-event,.fc-agenda .fc-event-time,.fc-event a{padding:4px 6px;background-color:#1ab394;border-color:#1ab394}.fc-event-time,.fc-event-title{color:#717171;padding:0 1px}.ui-calendar .fc-event-time,.ui-calendar .fc-event-title{color:#fff}.chat-activity-list .chat-element{border-bottom:1px solid #e7eaec}.chat-element:first-child{margin-top:0}.chat-element{padding-bottom:15px}.chat-element,.chat-element .media{margin-top:15px}.chat-element,.media-body{overflow:hidden}.media-body{display:block;width:auto}.chat-element>.pull-left{margin-right:10px}.chat-element img.img-circle,.dropdown-messages-box img.img-circle{width:38px;height:38px}.chat-element .well{border:1px solid #e7eaec;box-shadow:none;margin-top:10px;margin-bottom:5px;padding:10px 20px;font-size:11px;line-height:16px}.chat-element .actions{margin-top:10px}.chat-element .photos{margin:10px 0}.right.chat-element>.pull-right{margin-left:10px}.chat-photo{max-height:180px;border-radius:4px;overflow:hidden;margin-right:10px;margin-bottom:10px}.chat{margin:0;padding:0;list-style:none}.chat li{margin-bottom:10px;padding-bottom:5px;border-bottom:1px dotted #b3a9a9}.chat li.left .chat-body{margin-left:60px}.chat li.right .chat-body{margin-right:60px}.chat li .chat-body p{margin:0;color:#777}.panel .slidedown .glyphicon,.chat .glyphicon{margin-right:5px}.chat-panel .panel-body{height:350px;overflow-y:scroll}a.list-group-item.active,a.list-group-item.active:hover,a.list-group-item.active:focus{background-color:#1ab394;border-color:#1ab394;color:#fff;z-index:2}.list-group-item-heading{margin-top:10px}.list-group-item-text{margin:0 0 10px;color:inherit;font-size:12px;line-height:inherit}.no-padding .list-group-item{border-left:none;border-right:0;border-bottom:0}.no-padding .list-group-item:first-child{border-left:none;border-right:0;border-bottom:0;border-top:0}.no-padding .list-group{margin-bottom:0}.list-group-item{background-color:inherit;border:1px solid #e7eaec;display:block;margin-bottom:-1px;padding:10px 15px;position:relative}.elements-list .list-group-item{border-left:none;border-right:0;padding:15px 25px}.elements-list .list-group-item:first-child{border-left:none;border-right:0;border-top:none!important}.elements-list .list-group{margin-bottom:0}.elements-list a{color:inherit}.elements-list .list-group-item.active,.elements-list .list-group-item:hover{background:#f3f3f4;color:inherit;border-color:#e7eaec;border-radius:0}.elements-list li.active{-webkit-transition:none;transition:none}.element-detail-box{padding:25px}.flot-chart{display:block;height:200px}.widget .flot-chart.dashboard-chart{display:block;height:120px;margin-top:40px}.flot-chart.dashboard-chart{display:block;height:180px;margin-top:40px}.flot-chart-content{width:100%;height:100%}.flot-chart-pie-content{width:200px;height:200px;margin:auto}.jqstooltip{position:absolute;display:block;left:0;top:0;visibility:hidden;background:#2b303a;background-color:rgba(43,48,58,0.8);color:white;text-align:left;white-space:nowrap;z-index:10000;padding:5px 5px 5px 5px;min-height:22px;border-radius:3px}.jqsfield{color:white;text-align:left}.h-200{min-height:200px}.legendLabel{padding-left:5px}.stat-list li:first-child{margin-top:0}.stat-list{list-style:none;padding:0;margin:0}.stat-percent{float:right}.stat-list li{margin-top:15px;position:relative}table.dataTable thead .sorting,table.dataTable thead .sorting_asc:after,table.dataTable thead .sorting_desc,table.dataTable thead .sorting_asc_disabled,table.dataTable thead .sorting_desc_disabled{background:transparent}table.dataTable thead .sorting_asc:after{float:right;font-family:fontawesome}table.dataTable thead .sorting_desc:after{content:"\f0dd";float:right;font-family:fontawesome}table.dataTable thead .sorting:after{content:"\f0dc";float:right;font-family:fontawesome;color:rgba(50,50,50,0.5)}.dataTables_wrapper{padding-bottom:30px}.img-circle{border-radius:50%}.btn-circle{width:30px;height:30px;padding:6px 0;border-radius:15px;text-align:center;font-size:12px;line-height:1.428571429}.btn-circle.btn-lg{width:50px;height:50px;padding:10px 16px;border-radius:25px;font-size:18px;line-height:1.33}.btn-circle.btn-xl{width:70px;height:70px;padding:10px 16px;border-radius:35px;font-size:24px;line-height:1.33}.show-grid [class^="col-"]{padding-top:10px;padding-bottom:10px;border:1px solid #ddd;background-color:#eee!important}.show-grid{margin:15px 0}.css-animation-box h1{font-size:44px}.animation-efect-links a{padding:4px 6px;font-size:12px}#animation_box{background-color:#f9f8f8;border-radius:16px;width:80%;margin:0 auto;padding-top:80px}.animation-text-box{position:absolute;margin-top:40px;left:50%;margin-left:-100px;width:200px}.animation-text-info{position:absolute;margin-top:-60px;left:50%;margin-left:-100px;width:200px;font-size:10px}.animation-text-box h2{font-size:54px;font-weight:600;margin-bottom:5px}.animation-text-box p{font-size:12px;text-transform:uppercase}.pace{-webkit-pointer-events:none;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.pace-inactive{display:none}.pace .pace-progress{background:#1ab394;position:fixed;z-index:2000;top:0;width:100%;height:2px}.pace-inactive{display:none}.widget{border-radius:5px;padding:15px 20px;margin-bottom:10px;margin-top:10px}.widget.style1 h2{font-size:30px}.widget h2,.widget h3{margin-top:5px;margin-bottom:0}.widget-text-box{padding:20px;border:1px solid #e7eaec;background:#fff}.widget-head-color-box{border-radius:5px 5px 0 0;margin-top:10px}.widget .flot-chart{height:100px}.vertical-align div{display:inline-block;vertical-align:middle}.vertical-align h2,.vertical-align h3{margin:0}.todo-list{list-style:none outside none;margin:0;padding:0;font-size:14px}.todo-list.small-list{font-size:12px}.todo-list.small-list>li{background:#f3f3f4;border-left:none;border-right:0;border-radius:4px;color:inherit;margin-bottom:2px;padding:6px 6px 6px 12px}.todo-list.small-list .btn-xs,.todo-list.small-list .btn-group-xs>.btn{border-radius:5px;font-size:10px;line-height:1.5;padding:1px 2px 1px 5px}.todo-list>li{background:#f3f3f4;border-left:6px solid #e7eaec;border-right:6px solid #e7eaec;border-radius:4px;color:inherit;margin-bottom:2px;padding:10px}.todo-list .handle{cursor:move;display:inline-block;font-size:16px;margin:0 5px}.todo-list>li .label{font-size:9px;margin-left:10px}.check-link{font-size:16px}.todo-completed{text-decoration:line-through}.geo-statistic h1{font-size:36px;margin-bottom:0}.glyphicon.fa{font-family:"FontAwesome"}.inline{display:inline-block!important}.input-s-sm{width:120px}.input-s{width:200px}.input-s-lg{width:250px}.i-checks{padding-left:0}.form-control,.single-line{background:#fff none;border:1px solid #e5e6e7;border-radius:4px;color:inherit;display:block;padding:3px 6px 4px;-webkit-transition:border-color .15s ease-in-out 0s,box-shadow .15s ease-in-out 0s;transition:border-color .15s ease-in-out 0s,box-shadow .15s ease-in-out 0s;width:100%;height:31px;font-size:14px}.form-control.kv-fileinput-caption{height:34px!important}.form-control:focus,.single-line:focus{border-color:#3c8dbc!important}.has-success .form-control{border-color:#1ab394}.has-warning .form-control{border-color:#f8ac59}.has-error .form-control{border-color:#ed5565}.has-success .control-label{color:#1ab394}.has-warning .control-label{color:#f8ac59}.has-error .control-label{color:#ed5565}.input-group-addon{background-color:#fff;border:1px solid #e5e6e7;border-radius:4px;color:inherit;font-size:14px;font-weight:400;line-height:1;padding:6px 12px;text-align:center}.spinner-buttons.input-group-btn .btn-xs{line-height:1.13}.spinner-buttons.input-group-btn{width:20%}.noUi-connect{background:none repeat scroll 0 0 #1ab394;box-shadow:none}.slider_red .noUi-connect{background:none repeat scroll 0 0 #ed5565;box-shadow:none}.ui-sortable .ibox-title{cursor:move}.ui-sortable-placeholder{border:1px dashed #cecece!important;visibility:visible!important;background:#e7eaec}.ibox.ui-sortable-placeholder{margin:0 0 23px!important}.tabs-container .panel-body{background:#fff;border:1px solid #e7eaec;border-radius:2px;padding:20px;position:relative}.tabs-container .nav-tabs>li.active>a,.tabs-container .nav-tabs>li.active>a:hover,.tabs-container .nav-tabs>li.active>a:focus{border:1px solid #e7eaec;border-bottom-color:transparent;background-color:#fff}.tabs-container .nav-tabs>li{float:left;margin-bottom:-1px}.tabs-container .tab-pane .panel-body{border-top:0}.tabs-container .nav-tabs>li.active>a,.tabs-container .nav-tabs>li.active>a:hover,.tabs-container .nav-tabs>li.active>a:focus{border:1px solid #e7eaec;border-bottom-color:transparent}.tabs-container .nav-tabs{border-bottom:1px solid #e7eaec}.tabs-container .tab-pane .panel-body{border-top:0}.tabs-container .tabs-left .tab-pane .panel-body,.tabs-container .tabs-right .tab-pane .panel-body{border-top:1px solid #e7eaec}.tabs-container .nav-tabs>li a:hover{background:transparent;border-color:transparent}.tabs-container .tabs-below>.nav-tabs,.tabs-container .tabs-right>.nav-tabs,.tabs-container .tabs-left>.nav-tabs{border-bottom:0}.tabs-container .tabs-left .panel-body{position:static}.tabs-container .tabs-left>.nav-tabs,.tabs-container .tabs-right>.nav-tabs{width:20%}.tabs-container .tabs-left .panel-body{width:80%;margin-left:20%}.tabs-container .tabs-right .panel-body{width:80%;margin-right:20%}.tabs-container .tab-content>.tab-pane,.tabs-container .pill-content>.pill-pane{display:none}.tabs-container .tab-content>.active,.tabs-container .pill-content>.active{display:block}.tabs-container .tabs-below>.nav-tabs{border-top:1px solid #e7eaec}.tabs-container .tabs-below>.nav-tabs>li{margin-top:-1px;margin-bottom:0}.tabs-container .tabs-below>.nav-tabs>li>a{border-radius:0 0 4px 4px}.tabs-container .tabs-below>.nav-tabs>li>a:hover,.tabs-container .tabs-below>.nav-tabs>li>a:focus{border-top-color:#e7eaec;border-bottom-color:transparent}.tabs-container .tabs-left>.nav-tabs>li,.tabs-container .tabs-right>.nav-tabs>li{float:none}.tabs-container .tabs-left>.nav-tabs>li>a,.tabs-container .tabs-right>.nav-tabs>li>a{min-width:74px;margin-right:0;margin-bottom:3px}.tabs-container .tabs-left>.nav-tabs{float:left;margin-right:19px}.tabs-container .tabs-left>.nav-tabs>li>a{margin-right:-1px;border-radius:4px 0 0 4px}.tabs-container .tabs-left>.nav-tabs .active>a,.tabs-container .tabs-left>.nav-tabs .active>a:hover,.tabs-container .tabs-left>.nav-tabs .active>a:focus{border-color:#e7eaec transparent #e7eaec #e7eaec;border-right-color:#fff}.tabs-container .tabs-right>.nav-tabs{float:right;margin-left:19px}.tabs-container .tabs-right>.nav-tabs>li>a{margin-left:-1px;border-radius:0 4px 4px 0}.tabs-container .tabs-right>.nav-tabs .active>a,.tabs-container .tabs-right>.nav-tabs .active>a:hover,.tabs-container .tabs-right>.nav-tabs .active>a:focus{border-color:#e7eaec #e7eaec #e7eaec transparent;border-left-color:#fff;z-index:1}.onoffswitch{position:relative;width:54px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.onoffswitch-checkbox{display:none}.onoffswitch-label{display:block;overflow:hidden;cursor:pointer;border:2px solid #1ab394;border-radius:3px}.onoffswitch-inner{display:block;width:200%;margin-left:-100%;-webkit-transition:margin .3s ease-in 0s;transition:margin .3s ease-in 0s}.onoffswitch-inner:before,.onoffswitch-inner:after{display:block;float:left;width:50%;padding:0;font-size:10px;color:white;font-family:Trebuchet,Arial,sans-serif;font-weight:bold;box-sizing:border-box}.onoffswitch-inner:before{content:"ON";padding-left:7px;background-color:#1ab394;color:#fff}.onoffswitch-inner:after{content:"OFF";padding-right:7px;background-color:#fff;color:#919191;text-align:right}.onoffswitch-switch{display:block;width:18px;margin:0;background:#fff;border:2px solid #1ab394;border-radius:3px;position:absolute;top:0;bottom:0;right:36px;-webkit-transition:all .3s ease-in 0s;transition:all .3s ease-in 0s}.onoffswitch-checkbox:checked+.onoffswitch-label .onoffswitch-inner{margin-left:0}.onoffswitch-checkbox:checked+.onoffswitch-label .onoffswitch-switch{right:0}.dd{position:relative;display:block;margin:0;padding:0;list-style:none;font-size:13px;line-height:20px}.dd-list{display:block;position:relative;margin:0;padding:0;list-style:none}.dd-list .dd-list{padding-left:30px}.dd-collapsed .dd-list{display:none}.dd-item,.dd-empty,.dd-placeholder{display:block;position:relative;margin:0;padding:0;min-height:20px;font-size:13px;line-height:20px}.dd-handle{display:block;margin:5px 0;padding:5px 10px;color:#333;text-decoration:none;border:1px solid #e7eaec;background:#f5f5f5;border-radius:3px;box-sizing:border-box;-moz-box-sizing:border-box}.dd-handle span{font-weight:bold}.dd-handle:hover{background:#f0f0f0;cursor:pointer;font-weight:bold}.dd-item>button{display:block;position:relative;cursor:pointer;float:left;width:25px;height:20px;margin:5px 0;padding:0;text-indent:100%;white-space:nowrap;overflow:hidden;border:0;background:transparent;font-size:12px;line-height:1;text-align:center;font-weight:bold}.dd-item>button:before{content:'+';display:block;position:absolute;width:100%;text-align:center;text-indent:0}.dd-item>button[data-action="collapse"]:before{content:'-'}#nestable2 .dd-item>button{font-family:FontAwesome;height:34px;width:33px;color:#c1c1c1}#nestable2 .dd-item>button:before{content:"\f067"}#nestable2 .dd-item>button[data-action="collapse"]:before{content:"\f068"}.dd-placeholder,.dd-empty{margin:5px 0;padding:0;min-height:30px;background:#f2fbff;border:1px dashed #b6bcbf;box-sizing:border-box;-moz-box-sizing:border-box}.dd-empty{border:1px dashed #bbb;min-height:100px;background-color:#e5e5e5;background-image:-webkit-linear-gradient(45deg,#fff 25%,transparent 25%,transparent 75%,#fff 75%,#fff),-webkit-linear-gradient(45deg,#fff 25%,transparent 25%,transparent 75%,#fff 75%,#fff);background-image:linear-gradient(45deg,#fff 25%,transparent 25%,transparent 75%,#fff 75%,#fff),linear-gradient(45deg,#fff 25%,transparent 25%,transparent 75%,#fff 75%,#fff);background-size:60px 60px;background-position:0 0,30px 30px}.dd-dragel{position:absolute;z-index:9999;pointer-events:none}.dd-dragel>.dd-item .dd-handle{margin-top:0}.dd-dragel .dd-handle{box-shadow:2px 4px 6px 0 rgba(0,0,0,0.1)}.nestable-lists{display:block;clear:both;padding:30px 0;width:100%;border:0;border-top:2px solid #ddd;border-bottom:2px solid #ddd}#nestable-menu{padding:0;margin:10px 0 20px 0}#nestable-output,#nestable2-output{width:100%;font-size:.75em;line-height:1.333333em;font-family:lucida grande,lucida sans unicode,helvetica,arial,sans-serif;padding:5px;box-sizing:border-box;-moz-box-sizing:border-box}#nestable2 .dd-handle{color:inherit;border:1px dashed #e7eaec;background:#f3f3f4;padding:10px}#nestable2 span.label{margin-right:10px}#nestable-output,#nestable2-output{font-size:12px;padding:25px;box-sizing:border-box;-moz-box-sizing:border-box}.CodeMirror{border:1px solid #eee;height:auto}.CodeMirror-scroll{overflow-y:hidden;overflow-x:auto}.google-map{height:300px}.gridStyle{border:1px solid #d4d4d4;width:100%;height:400px}.gridStyle2{border:1px solid #d4d4d4;width:500px;height:300px}.ngH eaderCell{border-right:0;border-bottom:1px solid #e7eaec}.ngCell{border-right:0}.ngTopPanel{background:#f5f5f6}.ngRow.even{background:#f9f9f9}.ngRow.selected{background:#ebf2f1}.ngRow{border-bottom:1px solid #e7eaec}.ngCell{background-color:transparent}.ngHeaderCell{border-right:0}#toast-container>.toast{background-image:none!important}#toast-container>.toast:before{position:fixed;font-family:FontAwesome;font-size:24px;line-height:24px;float:left;color:#FFF;padding-right:.5em;margin:auto .5em auto -1.5em}#toast-container>div{box-shadow:0 0 3px #999;opacity:.9;-ms-filter:alpha(opacity = 90);filter:alpha(opacity = 90)}#toast-container>:hover{box-shadow:0 0 4px #999;opacity:1;-ms-filter:alpha(opacity = 100);filter:alpha(opacity = 100);cursor:pointer}.toast{background-color:#1ab394}.toast-success{background-color:#1ab394}.toast-error{background-color:#ed5565}.toast-info{background-color:#23c6c8}.toast-warning{background-color:#f8ac59}.toast-top-full-width{margin-top:20px}.toast-bottom-full-width{margin-bottom:20px}.img-container,.img-preview{overflow:hidden;text-align:center;width:100%}.img-preview-sm{height:130px;width:200px}.forum-post-container .media{margin:10px 10px 10px 10px;padding:20px 10px 20px 10px;border-bottom:1px solid #f1f1f1}.forum-avatar{float:left;margin-right:20px;text-align:center;width:110px}.forum-avatar .img-circle{height:48px;width:48px}.author-info{color:#676a6c;font-size:11px;margin-top:5px;text-align:center}.forum-post-info{padding:9px 12px 6px 12px;background:#f9f9f9;border:1px solid #f1f1f1}.media-body>.media{background:#f9f9f9;border-radius:3px;border:1px solid #f1f1f1}.forum-post-container .media-body .photos{margin:10px 0}.forum-photo{max-width:140px;border-radius:3px}.media-body>.media .forum-avatar{width:70px;margin-right:10px}.media-body>.media .forum-avatar .img-circle{height:38px;width:38px}.mid-icon{font-size:66px}.forum-item{margin:10px 0;padding:10px 0 20px;border-bottom:1px solid #f1f1f1}.views-number{font-size:24px;line-height:18px;font-weight:400}.forum-container,.forum-post-container{padding:30px!important}.forum-item small{color:#999}.forum-item .forum-sub-title{color:#999;margin-left:50px}.forum-title{margin:15px 0 15px 0}.forum-info{text-align:center}.forum-desc{color:#999}.forum-icon{float:left;width:30px;margin-right:20px;text-align:center}a.forum-item-title{color:inherit;display:block;font-size:18px;font-weight:600}a.forum-item-title:hover{color:inherit}.forum-icon .fa{font-size:30px;margin-top:8px;color:#9b9b9b}.forum-item.active .fa{color:#1ab394}.forum-item.active a.forum-item-title{color:#1ab394}@media(max-width :992px){.forum-info{margin:15px 0 10px 0;display:none}.forum-desc{float:none!important}}.vertical-container{width:90%;max-width:1170px;margin:0 auto}.vertical-container::after{content:'';display:table;clear:both}#vertical-timeline{position:relative;padding:0;margin-top:2em;margin-bottom:2em}#vertical-timeline::before{content:'';position:absolute;top:0;left:18px;height:100%;width:4px;background:#f1f1f1}.vertical-timeline-content .btn{float:right}#vertical-timeline.light-timeline:before{background:#e7eaec}.dark-timeline .vertical-timeline-content:before{border-color:transparent #f5f5f5 transparent transparent}.dark-timeline.center-orientation .vertical-timeline-content:before{border-color:transparent transparent transparent #f5f5f5}.dark-timeline .vertical-timeline-block:nth-child(2n) .vertical-timeline-content:before,.dark-timeline.center-orientation .vertical-timeline-block:nth-child(2n) .vertical-timeline-content:before{border-color:transparent #f5f5f5 transparent transparent}.dark-timeline .vertical-timeline-content,.dark-timeline.center-orientation .vertical-timeline-content{background:#f5f5f5}@media only screen and (min-width:1170px){#vertical-timeline.center-orientation{margin-top:3em;margin-bottom:3em}#vertical-timeline.center-orientation:before{left:50%;margin-left:-2px}}@media only screen and (max-width:1170px){.center-orientation.dark-timeline .vertical-timeline-content:before{border-color:transparent #f5f5f5 transparent transparent}}.vertical-timeline-block{position:relative;margin:2em 0}.vertical-timeline-block:after{content:"";display:table;clear:both}.vertical-timeline-block:first-child{margin-top:0}.vertical-timeline-block:last-child{margin-bottom:0}@media only screen and (min-width:1170px){.center-orientation .vertical-timeline-block{margin:4em 0}.center-orientation .vertical-timeline-block:first-child{margin-top:0}.center-orientation .vertical-timeline-block:last-child{margin-bottom:0}}.vertical-timeline-icon{position:absolute;top:0;left:0;width:40px;height:40px;border-radius:50%;font-size:16px;border:3px solid #f1f1f1;text-align:center}.vertical-timeline-icon i{display:block;width:24px;height:24px;position:relative;left:50%;top:50%;margin-left:-12px;margin-top:-9px}@media only screen and (min-width:1170px){.center-orientation .vertical-timeline-icon{width:50px;height:50px;left:50%;margin-left:-25px;-webkit-transform:translateZ(0);-webkit-backface-visibility:hidden;font-size:19px}.center-orientation .vertical-timeline-icon i{margin-left:-12px;margin-top:-10px}.center-orientation .cssanimations .vertical-timeline-icon.is-hidden{visibility:hidden}}.vertical-timeline-content{position:relative;margin-left:60px;background:white;border-radius:.25em;padding:1em}.vertical-timeline-content:after{content:"";display:table;clear:both}.vertical-timeline-content h2{font-weight:400;margin-top:4px}.vertical-timeline-content p{margin:1em 0;line-height:1.6}.vertical-timeline-content .vertical-date{float:left;font-weight:500}.vertical-date small{color:#1ab394;font-weight:400}.vertical-timeline-content::before{content:'';position:absolute;top:16px;right:100%;height:0;width:0;border:7px solid transparent;border-right:7px solid white}@media only screen and (min-width:768px){.vertical-timeline-content h2{font-size:18px}.vertical-timeline-content p{font-size:13px}}@media only screen and (min-width:1170px){.center-orientation .vertical-timeline-content{margin-left:0;padding:1.6em;width:45%}.center-orientation .vertical-timeline-content::before{top:24px;left:100%;border-color:transparent;border-left-color:white}.center-orientation .vertical-timeline-content .btn{float:left}.center-orientation .vertical-timeline-content .vertical-date{position:absolute;width:100%;left:122%;top:2px;font-size:14px}.center-orientation .vertical-timeline-block:nth-child(even) .vertical-timeline-content{float:right}.center-orientation .vertical-timeline-block:nth-child(even) .vertical-timeline-content::before{top:24px;left:auto;right:100%;border-color:transparent;border-right-color:white}.center-orientation .vertical-timeline-block:nth-child(even) .vertical-timeline-content .btn{float:right}.center-orientation .vertical-timeline-block:nth-child(even) .vertical-timeline-content .vertical-date{left:auto;right:122%;text-align:right}.center-orientation .cssanimations .vertical-timeline-content.is-hidden{visibility:hidden}}.sidebard-panel{width:220px;background:#ebebed;padding:10px 20px;position:absolute;right:0}.sidebard-panel .feed-element img.img-circle{width:32px;height:32px}.sidebard-panel .feed-element,.media-body,.sidebard-panel p{font-size:12px}.sidebard-panel .feed-element{margin-top:20px;padding-bottom:0}.sidebard-panel .list-group{margin-bottom:10px}.sidebard-panel .list-group .list-group-item{padding:5px 0;font-size:12px;border:0}.sidebar-content .wrapper,.wrapper.sidebar-content{padding-right:240px!important}#right-sidebar{background-color:#fff;border-left:1px solid #e7eaec;border-top:1px solid #e7eaec;overflow:hidden;position:fixed;top:60px;width:260px!important;z-index:1009;bottom:0;right:-260px}#right-sidebar.sidebar-open{right:0}#right-sidebar.sidebar-open.sidebar-top{top:0;border-top:0}.sidebar-container ul.nav-tabs{border:0}.sidebar-container ul.nav-tabs.navs-4 li{width:25%}.sidebar-container ul.nav-tabs.navs-3 li{width:33.3333%}.sidebar-container ul.nav-tabs.navs-2 li{width:50%}.sidebar-container ul.nav-tabs li{border:0}.sidebar-container ul.nav-tabs li a{border:0;padding:12px 10px;margin:0;border-radius:0;background:#2f4050;color:#fff;text-align:center;border-right:1px solid #334556}.sidebar-container ul.nav-tabs li.active a{border:0;background:#f9f9f9;color:#676a6c;font-weight:bold}.sidebar-container .nav-tabs>li.active>a:hover,.sidebar-container .nav-tabs>li.active>a:focus{border:0}.sidebar-container ul.sidebar-list{margin:0;padding:0}.sidebar-container ul.sidebar-list li{border-bottom:1px solid #e7eaec;padding:15px 20px;list-style:none;font-size:12px}.sidebar-container .sidebar-message:nth-child(2n+2){background:#f9f9f9}.sidebar-container ul.sidebar-list li a{text-decoration:none;color:inherit}.sidebar-container .sidebar-content{padding:15px 20px;font-size:12px}.sidebar-container .sidebar-title{background:#f9f9f9;padding:20px;border-bottom:1px solid #e7eaec}.sidebar-container .sidebar-title h3{margin-bottom:3px;padding-left:2px}.sidebar-container .tab-content h4{margin-bottom:5px}.sidebar-container .sidebar-message>a>.pull-left{margin-right:10px}.sidebar-container .sidebar-message>a{text-decoration:none;color:inherit}.sidebar-container .sidebar-message{padding:15px 20px}.sidebar-container .sidebar-message .message-avatar{height:38px;width:38px;border-radius:50%}.sidebar-container .setings-item{padding:15px 20px;border-bottom:1px solid #e7eaec}body{font-family:"open sans","Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;color:#676a6c;overflow-x:hidden}html,body{height:100%}body.full-height-layout #wrapper,body.full-height-layout #page-wrapper{height:100%}#page-wrapper{min-height:auto}body.boxed-layout #wrapper{background-color:#2f4050;max-width:1200px;margin:0 auto}.top-navigation.boxed-layout #wrapper,.boxed-layout #wrapper.top-navigation{max-width:1300px!important}.block{display:block}a{cursor:pointer}a:hover,a:focus{text-decoration:none}.border-bottom{border-bottom:1px solid #e7eaec!important}.font-bold{font-weight:600}.font-noraml{font-weight:400}.text-uppercase{text-transform:uppercase}.b-r{border-right:1px solid #e7eaec}.hr-line-dashed{border-top:1px dashed #e7eaec;color:#fff;background-color:#fff;height:1px;margin:20px 0}.hr-line-solid{border-bottom:1px solid #e7eaec;background-color:rgba(0,0,0,0);border-style:solid!important;margin-top:15px;margin-bottom:15px}video{width:100%!important;height:auto!important}.gallery>.row>div{margin-bottom:15px}.fancybox img{margin-bottom:5px;width:24%}.note-editor{height:auto!important;min-height:100px;border:solid 1px #e5e6e7}.modal-content{background-clip:padding-box;background-color:#fff;border:1px solid rgba(0,0,0,0);border-radius:4px;box-shadow:0 1px 3px rgba(0,0,0,0.3);outline:0 none}.modal-dialog{z-index:1200}.modal-body{padding:20px 30px 30px 30px}.inmodal .modal-body{background:#f8fafb}.inmodal .modal-header{padding:30px 15px;text-align:center}.animated.modal.fade .modal-dialog{-webkit-transform:none;-ms-transform:none;transform:none}.inmodal .modal-title{font-size:26px}.inmodal .modal-icon{font-size:84px;color:#e2e3e3}.modal-footer{margin-top:0}#wrapper{width:100%;overflow-x:hidden;background-color:#2f4050}.wrapper{padding:0 20px}.wrapper-content{padding:20px}#page-wrapper{padding:0 15px;position:inherit;margin:0 0 0 200px}.title-action{text-align:right;padding-top:30px}.ibox-content h1,.ibox-content h2,.ibox-content h3,.ibox-content h4,.ibox-content h5,.ibox-title h1,.ibox-title h2,.ibox-title h3,.ibox-title h4,.ibox-title h5{margin-top:5px}ul.unstyled,ol.unstyled{list-style:none outside none;margin-left:0}.big-icon{font-size:160px;color:#e5e6e7}.footer{background:none repeat scroll 0 0 white;border-top:1px solid #e7eaec;overflow:hidden;padding:10px 20px;margin:0 -15px;height:36px}.footer.fixed_full{position:fixed;bottom:0;left:0;right:0;z-index:1000;padding:10px 20px;background:white;border-top:1px solid #e7eaec}.footer.fixed{position:fixed;bottom:0;left:0;right:0;z-index:1000;padding:10px 20px;background:white;border-top:1px solid #e7eaec;margin-left:220px}body.mini-navbar .footer.fixed,body.body-small.mini-navbar .footer.fixed{margin:0 0 0 70px}body.mini-navbar.canvas-menu .footer.fixed,body.canvas-menu .footer.fixed{margin:0!important}body.fixed-sidebar.body-small.mini-navbar .footer.fixed{margin:0 0 0 220px}body.body-small .footer.fixed{margin-left:0}.page-heading{border-top:0;padding:0 20px 20px}.panel-heading h1,.panel-heading h2{margin-bottom:5px}.content-tabs{position:relative;height:39px;background:#fafafa;line-height:39px}.content-tabs .roll-nav,.page-tabs-list{position:absolute;width:30px;height:38px;text-align:center;color:#999;z-index:2;top:0}.content-tabs .roll-left{left:0;border-right:solid 1px #eee}.content-tabs .roll-right{right:0;border-left:solid 1px #eee}.content-tabs button{background:#fff;border:0;height:40px;width:40px;outline:0}.content-tabs button:hover{background:#fafafa}nav.page-tabs{margin-left:30px;width:100000px;height:39px;overflow:hidden}nav.page-tabs .page-tabs-content{float:left}.page-tabs a{display:block;float:left;border-right:solid 1px #eee;padding:0 15px}.page-tabs a i:hover{color:#c00}.page-tabs a:hover,.content-tabs .roll-nav:hover{color:#777;background:#f2f2f2;cursor:pointer}.roll-right.tabRight{right:60px}.roll-right.btn-group{right:60px;width:80px;padding:0}.roll-right.btn-group button{width:80px}.roll-right.tabReload{background:#fff;height:38px;width:60px;outline:0}.dropdown-menu-right{left:auto}#content-main{height:calc(100% - 127px);overflow:hidden}.tagsview-hide#content-main{height:calc(100% - 88px);overflow:hidden}.footer-hide#content-main{height:calc(100% - 91px);overflow:hidden}.tagsview-footer-hide#content-main{height:calc(100% - 52px);overflow:hidden}.fixed-nav #content-main{height:calc(100% - 80px);overflow:hidden}.table-bordered{border:1px solid #ebebeb}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{background-color:#f5f5f6;border-bottom-width:1px}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #e7e7e7}.table>thead>tr>th{border-bottom:1px solid #ddd;vertical-align:bottom}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{border-top:1px solid #e7eaec;line-height:1.42857;padding:8px;vertical-align:middle}.panel.blank-panel{background:0;margin:0}.blank-panel .panel-heading{padding-bottom:0}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{-moz-border-bottom-colors:none;-moz-border-left-colors:none;-moz-border-right-colors:none;-moz-border-top-colors:none;background:0;border-color:#ddd #ddd rgba(0,0,0,0);border-bottom:#f3f3f4;-webkit-border-image:none;-o-border-image:none;border-image:none;border-style:solid;border-width:1px;color:#555;cursor:default}.nav.nav-tabs li{background:0;border:0}.nav-tabs>li>a{color:#a7b1c2;font-weight:600;padding:10px 20px 10px 25px}.nav-tabs>li>a:hover,.nav-tabs>li>a:focus{background-color:#e6e6e6;color:#676a6c}.ui-tab .tab-content{padding:20px 0}.no-padding{padding:0!important}.no-borders{border:none!important}.no-margins{margin:0!important}.no-top-border{border-top:0!important}.ibox-content.text-box{padding-bottom:0;padding-top:15px}.border-left-right{border-left:1px solid #e7eaec;border-right:1px solid #e7eaec;border-top:0;border-bottom:0}.border-left{border-left:1px solid #e7eaec;border-right:0;border-top:0;border-bottom:0}.border-right{border-left:none;border-right:1px solid #e7eaec;border-top:0;border-bottom:0}.full-width{width:100%!important}.link-block{font-size:12px;padding:10px}.nav.navbar-top-links .link-block a{font-size:12px}.link-block a{font-size:10px;color:inherit}body.mini-navbar .branding{display:none}img.circle-border{border:6px solid #fff;border-radius:50%}.branding{float:left;color:#fff;font-size:18px;font-weight:600;padding:17px 20px;text-align:center;background-color:#1ab394}.login-panel{margin-top:25%}.page-header{padding:20px 0 9px;margin:0 0 20px;border-bottom:1px solid #eee}.fontawesome-icon-list{margin-top:22px}.fontawesome-icon-list .fa-hover a{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block;color:#222;line-height:32px;height:32px;padding-left:10px;border-radius:4px}.fontawesome-icon-list .fa-hover a .fa{width:32px;font-size:14px;display:inline-block;text-align:right;margin-right:10px}.fontawesome-icon-list .fa-hover a:hover{background-color:#1d9d74;color:#fff;text-decoration:none}.fontawesome-icon-list .fa-hover a:hover .fa{font-size:30px;vertical-align:-6px}.fontawesome-icon-list .fa-hover a:hover .text-muted{color:#bbe2d5}.feature-list .col-md-4{margin-bottom:22px}.feature-list h4 .fa:before{vertical-align:-10%;font-size:28px;display:inline-block;width:1.07142857em;text-align:center;margin-right:5px}.ui-draggable .ibox-title{cursor:move}.breadcrumb{background-color:#fff;padding:0;margin-bottom:0}.breadcrumb>li a{color:inherit}.breadcrumb>.active{color:inherit}code{background-color:#f9f2f4;border-radius:4px;color:#ca4440;font-size:90%;padding:2px 4px;white-space:nowrap}.ibox{clear:both;margin-bottom:25px;margin-top:0;padding:0}.ibox.collapsed .ibox-content{display:none}.ibox.collapsed .fa.fa-chevron-up:before{content:"\f078"}.ibox.collapsed .fa.fa-chevron-down:before{content:"\f077"}.ibox:after,.ibox:before{display:table}.ibox-title{-moz-border-bottom-colors:none;-moz-border-left-colors:none;-moz-border-right-colors:none;-moz-border-top-colors:none;background-color:#fff;border-color:#e7eaec;-webkit-border-image:none;-o-border-image:none;border-image:none;border-style:solid solid none;border-width:0;color:inherit;margin-bottom:0;padding:14px 15px 7px;min-height:40px}.ibox-content{background-color:#fff;color:inherit;padding:15px 20px 20px 20px;border-color:#e7eaec;-webkit-border-image:none;-o-border-image:none;border-image:none;border-style:solid solid none;border-width:1px 0}table.table-mail tr td{padding:12px}.table-mail .check-mail{padding-left:20px}.table-mail .mail-date{padding-right:20px}.star-mail,.check-mail{width:40px}.unread td a,.unread td{font-weight:600;color:inherit}.read td a,.read td{font-weight:normal;color:inherit}.unread td{background-color:#f9f8f8}.ibox-content{clear:both}.ibox-heading{background-color:#f3f6fb;border-bottom:0}.ibox-heading h3{font-weight:200;font-size:24px}.ibox-title h5{display:inline-block;font-size:14px;margin:0 0 7px;padding:0;text-overflow:ellipsis;float:left}.ibox-title .label{float:left;margin-left:4px}.ibox-tools{display:inline-block;float:right;margin-top:0;position:relative;padding:0}.ibox-tools a{cursor:pointer;margin-left:5px;color:#676a6c}.ibox-tools a.btn-primary{color:#fff}.ibox-tools .dropdown-menu>li>a{padding:4px 10px;font-size:12px}.ibox .open>.dropdown-menu{left:auto;right:0}.gray-bg{background-color:#f3f3f4}.white-bg{background-color:#fff}.navy-bg{background-color:#1ab394;color:#fff}.blue-bg{background-color:#1c84c6;color:#fff}.lazur-bg{background-color:#23c6c8;color:#fff}.yellow-bg{background-color:#f8ac59;color:#fff}.red-bg{background-color:#ed5565;color:#fff}.black-bg{background-color:#262626}.panel-primary{border-color:#1ab394}.panel-primary>.panel-heading{background-color:#1ab394;border-color:#1ab394}.panel-success{border-color:#1c84c6}.panel-success>.panel-heading{background-color:#1c84c6;border-color:#1c84c6;color:#fff}.panel-info{border-color:#23c6c8}.panel-info>.panel-heading{background-color:#23c6c8;border-color:#23c6c8;color:#fff}.panel-warning{border-color:#f8ac59}.panel-warning>.panel-heading{background-color:#f8ac59;border-color:#f8ac59;color:#fff}.panel-danger{border-color:#ed5565}.panel-danger>.panel-heading{background-color:#ed5565;border-color:#ed5565;color:#fff}.progress-bar{background-color:#1ab394}.progress-small,.progress-small .progress-bar{height:10px}.progress-small,.progress-mini{margin-top:5px}.progress-mini,.progress-mini .progress-bar{height:5px;margin-bottom:0}.progress-bar-navy-light{background-color:#3dc7ab}.progress-bar-success{background-color:#1c84c6}.progress-bar-info{background-color:#23c6c8}.progress-bar-warning{background-color:#f8ac59}.progress-bar-danger{background-color:#ed5565}.panel-title{font-size:inherit}.jumbotron{border-radius:6px;padding:40px}.jumbotron h1{margin-top:0}.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:#888}.simple_tag{background-color:#f3f3f4;border:1px solid #e7eaec;border-radius:2px;color:inherit;font-size:10px;margin-right:5px;margin-top:5px;padding:5px 12px;display:inline-block}.img-shadow{box-shadow:0 0 3px 0 #919191}.dashboards\.dashboard_2 nav.navbar,.dashboards\.dashboard_3 nav.navbar,.mailbox\.inbox nav.navbar,.mailbox\.email_view nav.navbar,.mailbox\.email_compose nav.navbar,.dashboards\.dashboard_4_1 nav.navbar{background:#fff}.Dashboard_2 .navbar.navbar-static-top,.Dashboard_3 .navbar.navbar-static-top,.Dashboard_4_1 .navbar.navbar-static-top,.ComposeEmail .navbar.navbar-static-top,.EmailView .navbar.navbar-static-top,.Inbox .navbar.navbar-static-top{background:#fff}a.close-canvas-menu{position:absolute;top:10px;right:15px;z-index:1011;color:#a7b1c2}a.close-canvas-menu:hover{color:#fff}.full-height{height:100%}.fh-breadcrumb{height:calc(100% - 196px);margin:0 -15px;position:relative}.fh-no-breadcrumb{height:calc(100% - 99px);margin:0 -15px;position:relative}.fh-column{background:#fff;height:100%;width:240px;float:left}.modal-backdrop{z-index:2040!important}.modal{z-index:2050!important}.spiner-example{height:200px;padding-top:70px}.p-xxs{padding:5px}.p-xs{padding:10px}.p-sm{padding:15px}.p-m{padding:20px}.p-md{padding:25px}.p-lg{padding:30px}.p-xl{padding:40px}.m-xxs{margin:2px 4px}.m-xs{margin:5px}.m-sm{margin:10px}.m{margin:15px}.m-md{margin:20px}.m-lg{margin:30px}.m-xl{margin:50px}.m-n{margin:0!important}.m-l-none{margin-left:0}.m-l-xs{margin-left:5px}.m-l-sm{margin-left:10px}.m-l{margin-left:15px}.m-l-md{margin-left:20px}.m-l-lg{margin-left:30px}.m-l-xl{margin-left:40px}.m-l-n-xxs{margin-left:-1px}.m-l-n-xs{margin-left:-5px}.m-l-n-sm{margin-left:-10px}.m-l-n{margin-left:-15px}.m-l-n-md{margin-left:-20px}.m-l-n-lg{margin-left:-30px}.m-l-n-xl{margin-left:-40px}.m-t-none{margin-top:0}.m-t-xxs{margin-top:1px}.m-t-xs{margin-top:5px}.m-t-sm{margin-top:10px}.m-t{margin-top:15px}.m-t-md{margin-top:20px}.m-t-lg{margin-top:30px}.m-t-xl{margin-top:40px}.m-t-n-xxs{margin-top:-1px}.m-t-n-xs{margin-top:-5px}.m-t-n-sm{margin-top:-10px}.m-t-n{margin-top:-15px}.m-t-n-md{margin-top:-20px}.m-t-n-lg{margin-top:-30px}.m-t-n-xl{margin-top:-40px}.m-r-none{margin-right:0}.m-r-xxs{margin-right:1px}.m-r-xs{margin-right:5px}.m-r-sm{margin-right:10px}.m-r{margin-right:15px}.m-r-md{margin-right:20px}.m-r-lg{margin-right:30px}.m-r-xl{margin-right:40px}.m-r-n-xxs{margin-right:-1px}.m-r-n-xs{margin-right:-5px}.m-r-n-sm{margin-right:-10px}.m-r-n{margin-right:-15px}.m-r-n-md{margin-right:-20px}.m-r-n-lg{margin-right:-30px}.m-r-n-xl{margin-right:-40px}.m-b-none{margin-bottom:0}.m-b-xxs{margin-bottom:1px}.m-b-xs{margin-bottom:5px}.m-b-sm{margin-bottom:10px}.m-b{margin-bottom:15px}.m-b-md{margin-bottom:20px}.m-b-lg{margin-bottom:30px}.m-b-xl{margin-bottom:40px}.m-b-n-xxs{margin-bottom:-1px}.m-b-n-xs{margin-bottom:-5px}.m-b-n-sm{margin-bottom:-10px}.m-b-n{margin-bottom:-15px}.m-b-n-md{margin-bottom:-20px}.m-b-n-lg{margin-bottom:-30px}.m-b-n-xl{margin-bottom:-40px}.space-15{margin:15px 0}.space-20{margin:20px 0}.space-25{margin:25px 0}.space-30{margin:30px 0}body.modal-open{padding-right:inherit!important}.search-form{margin-top:10px}.search-result h3{margin-bottom:0;color:#1e0fbe}.search-result .search-link{color:#006621}.search-result p{font-size:12px;margin-top:5px}.contact-box{background-color:#fff;border:1px solid #e7eaec;padding:20px;margin-bottom:20px}.contact-box a{color:inherit}.invoice-table tbody>tr>td:last-child,.invoice-table tbody>tr>td:nth-child(4),.invoice-table tbody>tr>td:nth-child(3),.invoice-table tbody>tr>td:nth-child(2){text-align:right}.invoice-table thead>tr>th:last-child,.invoice-table thead>tr>th:nth-child(4),.invoice-table thead>tr>th:nth-child(3),.invoice-table thead>tr>th:nth-child(2){text-align:right}.invoice-total>tbody>tr>td:first-child{text-align:right}.invoice-total>tbody>tr>td{border:0 none}.invoice-total>tbody>tr>td:last-child{border-bottom:1px solid #ddd;text-align:right;width:15%}.middle-box{max-width:400px;z-index:100;margin:0 auto;padding-top:40px}.lockscreen.middle-box{width:200px;padding-top:110px}.loginscreen.middle-box{width:300px}.loginColumns{max-width:800px;margin:0 auto;padding:100px 20px 20px 20px}.passwordBox{max-width:460px;margin:0 auto;padding:100px 20px 20px 20px}.logo-name{color:#e6e6e6;font-size:180px;font-weight:800;letter-spacing:-10px;margin-bottom:0}.middle-box h1{font-size:170px}.wrapper .middle-box{margin-top:140px}.lock-word{z-index:10;position:absolute;top:110px;left:50%;margin-left:-470px}.lock-word span{font-size:100px;font-weight:600;color:#e9e9e9;display:inline-block}.lock-word .first-word{margin-right:160px}.dashboard-header{border-top:0;padding:20px 20px 20px 20px}.dashboard-header h2{margin-top:10px;font-size:26px}.fist-item{border-top:none!important}.statistic-box{margin-top:40px}.dashboard-header .list-group-item span.label{margin-right:10px}.list-group.clear-list .list-group-item{border-top:1px solid #e7eaec;border-bottom:0;border-right:0;border-left:0;padding:10px 0}ul.clear-list:first-child{border-top:none!important}.timeline-item .date i{position:absolute;top:0;right:0;padding:5px;width:30px;text-align:center;border-top:1px solid #e7eaec;border-bottom:1px solid #e7eaec;border-left:1px solid #e7eaec;background:#f8f8f8}.timeline-item .date{text-align:right;width:110px;position:relative;padding-top:30px}.timeline-item .content{border-left:1px solid #e7eaec;border-top:1px solid #e7eaec;padding-top:10px;min-height:100px}.timeline-item .content:hover{background:#f6f6f6}ul.notes li,ul.tag-list li{list-style:none}ul.notes li h4{margin-top:20px;font-size:16px}ul.notes li div{text-decoration:none;color:#000;background:#ffc;display:block;height:140px;width:140px;padding:1em;position:relative}ul.notes li div small{position:absolute;top:5px;right:5px;font-size:10px}ul.notes li div a{position:absolute;right:10px;bottom:10px;color:inherit}ul.notes li{margin:10px 40px 50px 0;float:left}ul.notes li div p{font-size:12px}ul.notes li div{text-decoration:none;color:#000;background:#ffc;display:block;height:140px;width:140px;padding:1em;box-shadow:5px 5px 2px rgba(33,33,33,0.7)}ul.notes li div{-webkit-transform:rotate(-6deg);-o-transform:rotate(-6deg);-moz-transform:rotate(-6deg)}ul.notes li:nth-child(even) div{-o-transform:rotate(4deg);-webkit-transform:rotate(4deg);-moz-transform:rotate(4deg);position:relative;top:5px}ul.notes li:nth-child(3n) div{-o-transform:rotate(-3deg);-webkit-transform:rotate(-3deg);-moz-transform:rotate(-3deg);position:relative;top:-5px}ul.notes li:nth-child(5n) div{-o-transform:rotate(5deg);-webkit-transform:rotate(5deg);-moz-transform:rotate(5deg);position:relative;top:-10px}ul.notes li div:hover,ul.notes li div:focus{-webkit-transform:scale(1.1);-moz-transform:scale(1.1);-o-transform:scale(1.1);position:relative;z-index:5}ul.notes li div{text-decoration:none;color:#000;background:#ffc;display:block;height:210px;width:210px;padding:1em;box-shadow:5px 5px 7px rgba(33,33,33,0.7);-webkit-transition:-webkit-transform .15s linear}.file-box{float:left;width:220px}.file-manager h5{text-transform:uppercase}.file-manager{list-style:none outside none;margin:0;padding:0}.folder-list li a{color:#666;display:block;padding:5px 0}.folder-list li{border-bottom:1px solid #e7eaec;display:block}.folder-list li i{margin-right:8px;color:#3d4d5d}.category-list li a{color:#666;display:block;padding:5px 0}.category-list li{display:block}.category-list li i{margin-right:8px;color:#3d4d5d}.category-list li a .text-navy{color:#1ab394}.category-list li a .text-primary{color:#1c84c6}.category-list li a .text-info{color:#23c6c8}.category-list li a .text-danger{color:#ef5352}.category-list li a .text-warning{color:#f8ac59}.file-manager h5.tag-title{margin-top:20px}.tag-list li{float:left}.tag-list li a{font-size:10px;background-color:#f3f3f4;padding:5px 12px;color:inherit;border-radius:2px;border:1px solid #e7eaec;margin-right:5px;margin-top:5px;display:block}.file{border:1px solid #e7eaec;padding:0;background-color:#fff;position:relative;margin-bottom:20px;margin-right:20px}.file-manager .hr-line-dashed{margin:15px 0}.file .icon,.file .image{height:100px;overflow:hidden}.file .icon{padding:15px 10px;text-align:center}.file-control{color:inherit;font-size:14px;margin-right:10px}.file-control.active{text-decoration:underline}.file .icon i{font-size:70px;color:#dadada}.file .file-name{padding:10px;background-color:#f8f8f8;border-top:1px solid #e7eaec}.file-name small{color:#676a6c}.corner{position:absolute;display:inline-block;width:0;height:0;line-height:0;border:.6em solid transparent;border-right:.6em solid #f1f1f1;border-bottom:.6em solid #f1f1f1;right:0;bottom:0}a.compose-mail{padding:8px 10px}.mail-search{max-width:300px}.profile-content{border-top:none!important}.feed-activity-list .feed-element{border-bottom:1px solid #e7eaec}.feed-element:first-child{margin-top:0}.feed-element{padding-bottom:15px}.feed-element,.feed-element .media{margin-top:15px}.feed-element,.media-body{overflow:hidden}.feed-element>.pull-left{margin-right:10px}.feed-element img.img-circle,.dropdown-messages-box img.img-circle{width:38px;height:38px}.feed-element .well{border:1px solid #e7eaec;box-shadow:none;margin-top:10px;margin-bottom:5px;padding:10px 20px;font-size:11px;line-height:16px}.feed-element .actions{margin-top:10px}.feed-element .photos{margin:10px 0}.feed-photo{max-height:180px;border-radius:4px;overflow:hidden;margin-right:10px;margin-bottom:10px}.mail-box{background-color:#fff;border:1px solid #e7eaec;border-top:0;padding:0;margin-bottom:20px}.mail-box-header{background-color:#fff;border:1px solid #e7eaec;border-bottom:0;padding:30px 20px 20px 20px}.mail-box-header h2{margin-top:0}.mailbox-content .tag-list li a{background:#fff}.mail-body{border-top:1px solid #e7eaec;padding:20px}.mail-text{border-top:1px solid #e7eaec}.mail-text .note-toolbar{padding:10px 15px}.mail-body .form-group{margin-bottom:5px}.mail-text .note-editor .note-toolbar{background-color:#f9f8f8}.mail-attachment{border-top:1px solid #e7eaec;padding:20px;font-size:12px}.mailbox-content{background:0;border:0;padding:10px}.mail-ontact{width:23%}.project-people,.project-actions{text-align:right;vertical-align:middle}dd.project-people{text-align:left;margin-top:5px}.project-people img{width:32px;height:32px}.project-title a{font-size:14px;color:#676a6c;font-weight:600}.project-list table tr td{border-top:0;border-bottom:1px solid #e7eaec;padding:15px 10px;vertical-align:middle}.project-manager .tag-list li a{font-size:10px;background-color:white;padding:5px 12px;color:inherit;border-radius:2px;border:1px solid #e7eaec;margin-right:5px;margin-top:5px;display:block}.project-files li a{font-size:11px;color:#676a6c;margin-left:10px;line-height:22px}.faq-item{padding:20px;margin-bottom:2px;background:#fff}.faq-question{font-size:18px;font-weight:600;color:#1ab394;display:block}.faq-question:hover{color:#179d82}.faq-answer{margin-top:10px;background:#f3f3f4;border:1px solid #e7eaec;border-radius:3px;padding:15px}.faq-item .tag-item{background:#f3f3f4;padding:2px 6px;font-size:10px;text-transform:uppercase}.message-input{height:90px!important}.chat-avatar{width:36px;height:36px;float:left;margin-right:10px}.chat-user-name{padding:10px}.chat-user{padding:8px 10px;border-bottom:1px solid #e7eaec}.chat-user a{color:inherit}.chat-view{z-index:20012}.chat-users,.chat-statistic{margin-left:-30px}@media(max-width:992px){.chat-users,.chat-statistic{margin-left:0}}.chat-view .ibox-content{padding:0}.chat-message{padding:10px 20px}.message-avatar{height:48px;width:48px;border:1px solid #e7eaec;border-radius:4px;margin-top:1px}.chat-discussion .chat-message.left .message-avatar{float:left;margin-right:10px}.chat-discussion .chat-message.right .message-avatar{float:right;margin-left:10px}.message{background-color:#fff;border:1px solid #e7eaec;text-align:left;display:block;padding:10px 20px;position:relative;border-radius:4px}.chat-discussion .chat-message.left .message-date{float:right}.chat-discussion .chat-message.right .message-date{float:left}.chat-discussion .chat-message.left .message{text-align:left;margin-left:55px}.chat-discussion .chat-message.right .message{text-align:right;margin-right:55px}.message-date{font-size:10px;color:#888}.message-content{display:block}.chat-discussion{background:#eee;padding:15px;height:400px;overflow-y:auto}.chat-users{overflow-y:auto;height:400px}.chat-message-form .form-group{margin-bottom:0}.jstree-open>.jstree-anchor>.fa-folder:before{content:"\f07c"}.jstree-default .jstree-icon.none{width:0}.clients-list{margin-top:20px}.clients-list .tab-pane{position:relative;height:600px}.client-detail{position:relative;height:620px}.clients-list table tr td{height:46px;vertical-align:middle;border:0}.client-link{font-weight:600;color:inherit}.client-link:hover{color:inherit}.client-avatar{width:42px}.client-avatar img{width:28px;height:28px;border-radius:50%}.contact-type{width:20px;color:#c1c3c4}.client-status{text-align:left}.client-detail .vertical-timeline-content p{margin:0}.client-detail .vertical-timeline-icon.gray-bg{color:#a7aaab}.clients-list .nav-tabs>li.active>a,.clients-list .nav-tabs>li.active>a:hover,.clients-list .nav-tabs>li.active>a:focus{border-bottom:1px solid #fff}.blog h2{font-weight:700}.blog h5{margin:0 0 5px 0}.blog .btn{margin:0 0 5px 0}.article h1{font-size:48px;font-weight:700;color:#2f4050}.article p{font-size:15px;line-height:26px}.article-title{text-align:center;margin:60px 0 40px 0}.article .ibox-content{padding:40px}.issue-tracker .btn-link{color:#1ab394}table.issue-tracker tbody tr td{vertical-align:middle;height:50px}.issue-info{width:50%}.issue-info a{font-weight:600;color:#676a6c}.issue-info small{display:block}.team-members{margin:10px 0}.team-members img.img-circle{width:42px;height:42px;margin-bottom:5px}.sortable-list{padding:10px 0}.agile-list{list-style:none;margin:0}.agile-list li{background:#fafafb;border:1px solid #e7eaec;margin:0 0 10px 0;padding:10px;border-radius:2px}.agile-list li:hover{cursor:pointer;background:#fff}.agile-list li.warning-element{border-left:3px solid #f8ac59}.agile-list li.danger-element{border-left:3px solid #ed5565}.agile-list li.info-element{border-left:3px solid #1c84c6}.agile-list li.success-element{border-left:3px solid #1ab394}.agile-detail{margin-top:5px;font-size:12px}ins{background-color:#c6ffc6;text-decoration:none}del{background-color:#ffc6c6}#small-chat{position:fixed;bottom:50px;right:26px;z-index:100}#small-chat .badge{position:absolute;top:-3px;right:-4px}.open-small-chat{height:38px;width:38px;display:block;background:#1ab394;padding:9px 8px;text-align:center;color:#fff;border-radius:50%}.open-small-chat:hover{color:white;background:#1ab394}.small-chat-box{display:none;position:fixed;bottom:50px;right:80px;background:#fff;border:1px solid #e7eaec;width:230px;height:320px;border-radius:4px}.small-chat-box.ng-small-chat{display:block}.body-small .small-chat-box{bottom:70px;right:20px}.small-chat-box.active{display:block}.small-chat-box .heading{background:#2f4050;padding:8px 15px;font-weight:bold;color:#fff}.small-chat-box .chat-date{opacity:.6;font-size:10px;font-weight:normal}.small-chat-box .content{padding:15px 15px}.small-chat-box .content .author-name{font-weight:bold;margin-bottom:3px;font-size:11px}.small-chat-box .content>div{padding-bottom:20px}.small-chat-box .content .chat-message{padding:5px 10px;border-radius:6px;font-size:11px;line-height:14px;max-width:80%;background:#f3f3f4;margin-bottom:10px}.small-chat-box .content .chat-message.active{background:#1ab394;color:#fff}.small-chat-box .content .left{text-align:left;clear:both}.small-chat-box .content .left .chat-message{float:left}.small-chat-box .content .right{text-align:right;clear:both}.small-chat-box .content .right .chat-message{float:right}.small-chat-box .form-chat{padding:10px 10px}.sk-spinner-rotating-plane.sk-spinner{width:30px;height:30px;background-color:#1ab394;margin:0 auto;-webkit-animation:sk-rotatePlane 1.2s infinite ease-in-out;animation:sk-rotatePlane 1.2s infinite ease-in-out}@-webkit-keyframes sk-rotatePlane{0%{-webkit-transform:perspective(120px) rotateX(0deg) rotateY(0deg);transform:perspective(120px) rotateX(0deg) rotateY(0deg)}50%{-webkit-transform:perspective(120px) rotateX(-180 .1deg) rotateY(0deg);transform:perspective(120px) rotateX(-180 .1deg) rotateY(0deg)}100%{-webkit-transform:perspective(120px) rotateX(-180deg) rotateY(-180deg);transform:perspective(120px) rotateX(-180deg) rotateY(-180deg)}}@keyframes sk-rotatePlane{0%{-webkit-transform:perspective(120px) rotateX(0deg) rotateY(0deg);transform:perspective(120px) rotateX(0deg) rotateY(0deg)}50%{-webkit-transform:perspective(120px) rotateX(-180 .1deg) rotateY(0deg);transform:perspective(120px) rotateX(-180 .1deg) rotateY(0deg)}100%{-webkit-transform:perspective(120px) rotateX(-180deg) rotateY(-179 .9deg);transform:perspective(120px) rotateX(-180deg) rotateY(-179 .9deg)}}.sk-spinner-double-bounce.sk-spinner{width:40px;height:40px;position:relative;margin:0 auto}.sk-spinner-double-bounce .sk-double-bounce1,.sk-spinner-double-bounce .sk-double-bounce2{width:100%;height:100%;border-radius:50%;background-color:#1ab394;opacity:.6;position:absolute;top:0;left:0;-webkit-animation:sk-doubleBounce 2s infinite ease-in-out;animation:sk-doubleBounce 2s infinite ease-in-out}.sk-spinner-double-bounce .sk-double-bounce2{-webkit-animation-delay:-1s;animation-delay:-1s}@-webkit-keyframes sk-doubleBounce{0%,100%{-webkit-transform:scale(0);transform:scale(0)}50%{-webkit-transform:scale(1);transform:scale(1)}}@keyframes sk-doubleBounce{0%,100%{-webkit-transform:scale(0);transform:scale(0)}50%{-webkit-transform:scale(1);transform:scale(1)}}.sk-spinner-wave.sk-spinner{margin:0 auto;width:50px;height:30px;text-align:center;font-size:10px}.sk-spinner-wave div{background-color:#1ab394;height:100%;width:6px;display:inline-block;-webkit-animation:sk-waveStretchDelay 1.2s infinite ease-in-out;animation:sk-waveStretchDelay 1.2s infinite ease-in-out}.sk-spinner-wave .sk-rect2{-webkit-animation-delay:-1.1s;animation-delay:-1.1s}.sk-spinner-wave .sk-rect3{-webkit-animation-delay:-1s;animation-delay:-1s}.sk-spinner-wave .sk-rect4{-webkit-animation-delay:-0.9s;animation-delay:-0.9s}.sk-spinner-wave .sk-rect5{-webkit-animation-delay:-0.8s;animation-delay:-0.8s}@-webkit-keyframes sk-waveStretchDelay{0%,40%,100%{-webkit-transform:scaleY(0.4);transform:scaleY(0.4)}20%{-webkit-transform:scaleY(1);transform:scaleY(1)}}@keyframes sk-waveStretchDelay{0%,40%,100%{-webkit-transform:scaleY(0.4);transform:scaleY(0.4)}20%{-webkit-transform:scaleY(1);transform:scaleY(1)}}.sk-spinner-wandering-cubes.sk-spinner{margin:0 auto;width:32px;height:32px;position:relative}.sk-spinner-wandering-cubes .sk-cube1,.sk-spinner-wandering-cubes .sk-cube2{background-color:#1ab394;width:10px;height:10px;position:absolute;top:0;left:0;-webkit-animation:sk-wanderingCubeMove 1.8s infinite ease-in-out;animation:sk-wanderingCubeMove 1.8s infinite ease-in-out}.sk-spinner-wandering-cubes .sk-cube2{-webkit-animation-delay:-0.9s;animation-delay:-0.9s}@-webkit-keyframes sk-wanderingCubeMove{25%{-webkit-transform:translateX(42px) rotate(-90deg) scale(0.5);transform:translateX(42px) rotate(-90deg) scale(0.5)}50%{-webkit-transform:translateX(42px) translateY(42px) rotate(-179deg);transform:translateX(42px) translateY(42px) rotate(-179deg)}50.1%{-webkit-transform:translateX(42px) translateY(42px) rotate(-180deg);transform:translateX(42px) translateY(42px) rotate(-180deg)}75%{-webkit-transform:translateX(0px) translateY(42px) rotate(-270deg) scale(0 .5);transform:translateX(0px) translateY(42px) rotate(-270deg) scale(0 .5)}100%{-webkit-transform:rotate(-360deg);transform:rotate(-360deg)}}@keyframes sk-wanderingCubeMove{25%{-webkit-transform:translateX(42px) rotate(-90deg) scale(0.5);transform:translateX(42px) rotate(-90deg) scale(0.5)}50%{-webkit-transform:translateX(42px) translateY(42px) rotate(-179deg);transform:translateX(42px) translateY(42px) rotate(-179deg)}50.1%{-webkit-transform:translateX(42px) translateY(42px) rotate(-180deg);transform:translateX(42px) translateY(42px) rotate(-180deg)}75%{-webkit-transform:translateX(0px) translateY(42px) rotate(-270deg) scale(0 .5);transform:translateX(0px) translateY(42px) rotate(-270deg) scale(0 .5)}100%{-webkit-transform:rotate(-360deg);transform:rotate(-360deg)}}.sk-spinner-pulse.sk-spinner{width:40px;height:40px;margin:0 auto;background-color:#1ab394;border-radius:100%;-webkit-animation:sk-pulseScaleOut 1s infinite ease-in-out;animation:sk-pulseScaleOut 1s infinite ease-in-out}@-webkit-keyframes sk-pulseScaleOut{0%{-webkit-transform:scale(0);transform:scale(0)}100%{-webkit-transform:scale(1);transform:scale(1);opacity:0}}@keyframes sk-pulseScaleOut{0%{-webkit-transform:scale(0);transform:scale(0)}100%{-webkit-transform:scale(1);transform:scale(1);opacity:0}}.sk-spinner-chasing-dots.sk-spinner{margin:0 auto;width:40px;height:40px;position:relative;text-align:center;-webkit-animation:sk-chasingDotsRotate 2s infinite linear;animation:sk-chasingDotsRotate 2s infinite linear}.sk-spinner-chasing-dots .sk-dot1,.sk-spinner-chasing-dots .sk-dot2{width:60%;height:60%;display:inline-block;position:absolute;top:0;background-color:#1ab394;border-radius:100%;-webkit-animation:sk-chasingDotsBounce 2s infinite ease-in-out;animation:sk-chasingDotsBounce 2s infinite ease-in-out}.sk-spinner-chasing-dots .sk-dot2{top:auto;bottom:0;-webkit-animation-delay:-1s;animation-delay:-1s}@-webkit-keyframes sk-chasingDotsRotate{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes sk-chasingDotsRotate{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes sk-chasingDotsBounce{0%,100%{-webkit-transform:scale(0);transform:scale(0)}50%{-webkit-transform:scale(1);transform:scale(1)}}@keyframes sk-chasingDotsBounce{0%,100%{-webkit-transform:scale(0);transform:scale(0)}50%{-webkit-transform:scale(1);transform:scale(1)}}.sk-spinner-three-bounce.sk-spinner{margin:0 auto;width:70px;text-align:center}.sk-spinner-three-bounce div{width:18px;height:18px;background-color:#1ab394;border-radius:100%;display:inline-block;-webkit-animation:sk-threeBounceDelay 1.4s infinite ease-in-out;animation:sk-threeBounceDelay 1.4s infinite ease-in-out;-webkit-animation-fill-mode:both;animation-fill-mode:both}.sk-spinner-three-bounce .sk-bounce1{-webkit-animation-delay:-0.32s;animation-delay:-0.32s}.sk-spinner-three-bounce .sk-bounce2{-webkit-animation-delay:-0.16s;animation-delay:-0.16s}@-webkit-keyframes sk-threeBounceDelay{0%,80%,100%{-webkit-transform:scale(0);transform:scale(0)}40%{-webkit-transform:scale(1);transform:scale(1)}}@keyframes sk-threeBounceDelay{0%,80%,100%{-webkit-transform:scale(0);transform:scale(0)}40%{-webkit-transform:scale(1);transform:scale(1)}}.sk-spinner-circle.sk-spinner{margin:0 auto;width:22px;height:22px;position:relative}.sk-spinner-circle .sk-circle{width:100%;height:100%;position:absolute;left:0;top:0}.sk-spinner-circle .sk-circle:before{content:'';display:block;margin:0 auto;width:20%;height:20%;background-color:#1ab394;border-radius:100%;-webkit-animation:sk-circleBounceDelay 1.2s infinite ease-in-out;animation:sk-circleBounceDelay 1.2s infinite ease-in-out;-webkit-animation-fill-mode:both;animation-fill-mode:both}.sk-spinner-circle .sk-circle2{-webkit-transform:rotate(30deg);-ms-transform:rotate(30deg);transform:rotate(30deg)}.sk-spinner-circle .sk-circle3{-webkit-transform:rotate(60deg);-ms-transform:rotate(60deg);transform:rotate(60deg)}.sk-spinner-circle .sk-circle4{-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.sk-spinner-circle .sk-circle5{-webkit-transform:rotate(120deg);-ms-transform:rotate(120deg);transform:rotate(120deg)}.sk-spinner-circle .sk-circle6{-webkit-transform:rotate(150deg);-ms-transform:rotate(150deg);transform:rotate(150deg)}.sk-spinner-circle .sk-circle7{-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.sk-spinner-circle .sk-circle8{-webkit-transform:rotate(210deg);-ms-transform:rotate(210deg);transform:rotate(210deg)}.sk-spinner-circle .sk-circle9{-webkit-transform:rotate(240deg);-ms-transform:rotate(240deg);transform:rotate(240deg)}.sk-spinner-circle .sk-circle10{-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.sk-spinner-circle .sk-circle11{-webkit-transform:rotate(300deg);-ms-transform:rotate(300deg);transform:rotate(300deg)}.sk-spinner-circle .sk-circle12{-webkit-transform:rotate(330deg);-ms-transform:rotate(330deg);transform:rotate(330deg)}.sk-spinner-circle .sk-circle2:before{-webkit-animation-delay:-1.1s;animation-delay:-1.1s}.sk-spinner-circle .sk-circle3:before{-webkit-animation-delay:-1s;animation-delay:-1s}.sk-spinner-circle .sk-circle4:before{-webkit-animation-delay:-0.9s;animation-delay:-0.9s}.sk-spinner-circle .sk-circle5:before{-webkit-animation-delay:-0.8s;animation-delay:-0.8s}.sk-spinner-circle .sk-circle6:before{-webkit-animation-delay:-0.7s;animation-delay:-0.7s}.sk-spinner-circle .sk-circle7:before{-webkit-animation-delay:-0.6s;animation-delay:-0.6s}.sk-spinner-circle .sk-circle8:before{-webkit-animation-delay:-0.5s;animation-delay:-0.5s}.sk-spinner-circle .sk-circle9:before{-webkit-animation-delay:-0.4s;animation-delay:-0.4s}.sk-spinner-circle .sk-circle10:before{-webkit-animation-delay:-0.3s;animation-delay:-0.3s}.sk-spinner-circle .sk-circle11:before{-webkit-animation-delay:-0.2s;animation-delay:-0.2s}.sk-spinner-circle .sk-circle12:before{-webkit-animation-delay:-0.1s;animation-delay:-0.1s}@-webkit-keyframes sk-circleBounceDelay{0%,80%,100%{-webkit-transform:scale(0);transform:scale(0)}40%{-webkit-transform:scale(1);transform:scale(1)}}@keyframes sk-circleBounceDelay{0%,80%,100%{-webkit-transform:scale(0);transform:scale(0)}40%{-webkit-transform:scale(1);transform:scale(1)}}.sk-spinner-cube-grid.sk-spinner{width:30px;height:30px;margin:0 auto}.sk-spinner-cube-grid .sk-cube{width:33%;height:33%;background-color:#1ab394;float:left;-webkit-animation:sk-cubeGridScaleDelay 1.3s infinite ease-in-out;animation:sk-cubeGridScaleDelay 1.3s infinite ease-in-out}.sk-spinner-cube-grid .sk-cube:nth-child(1){-webkit-animation-delay:.2s;animation-delay:.2s}.sk-spinner-cube-grid .sk-cube:nth-child(2){-webkit-animation-delay:.3s;animation-delay:.3s}.sk-spinner-cube-grid .sk-cube:nth-child(3){-webkit-animation-delay:.4s;animation-delay:.4s}.sk-spinner-cube-grid .sk-cube:nth-child(4){-webkit-animation-delay:.1s;animation-delay:.1s}.sk-spinner-cube-grid .sk-cube:nth-child(5){-webkit-animation-delay:.2s;animation-delay:.2s}.sk-spinner-cube-grid .sk-cube:nth-child(6){-webkit-animation-delay:.3s;animation-delay:.3s}.sk-spinner-cube-grid .sk-cube:nth-child(7){-webkit-animation-delay:0s;animation-delay:0s}.sk-spinner-cube-grid .sk-cube:nth-child(8){-webkit-animation-delay:.1s;animation-delay:.1s}.sk-spinner-cube-grid .sk-cube:nth-child(9){-webkit-animation-delay:.2s;animation-delay:.2s}@-webkit-keyframes sk-cubeGridScaleDelay{0%,70%,100%{-webkit-transform:scale3D(1,1,1);transform:scale3D(1,1,1)}35%{-webkit-transform:scale3D(0,0,1);transform:scale3D(0,0,1)}}@keyframes sk-cubeGridScaleDelay{0%,70%,100%{-webkit-transform:scale3D(1,1,1);transform:scale3D(1,1,1)}35%{-webkit-transform:scale3D(0,0,1);transform:scale3D(0,0,1)}}.sk-spinner-wordpress.sk-spinner{background-color:#1ab394;width:30px;height:30px;border-radius:30px;position:relative;margin:0 auto;-webkit-animation:sk-innerCircle 1s linear infinite;animation:sk-innerCircle 1s linear infinite}.sk-spinner-wordpress .sk-inner-circle{display:block;background-color:#fff;width:8px;height:8px;position:absolute;border-radius:8px;top:5px;left:5px}@-webkit-keyframes sk-innerCircle{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes sk-innerCircle{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.sk-spinner-fading-circle.sk-spinner{margin:0 auto;width:22px;height:22px;position:relative}.sk-spinner-fading-circle .sk-circle{width:100%;height:100%;position:absolute;left:0;top:0}.sk-spinner-fading-circle .sk-circle:before{content:'';display:block;margin:0 auto;width:18%;height:18%;background-color:#1ab394;border-radius:100%;-webkit-animation:sk-circleFadeDelay 1.2s infinite ease-in-out;animation:sk-circleFadeDelay 1.2s infinite ease-in-out;-webkit-animation-fill-mode:both;animation-fill-mode:both}.sk-spinner-fading-circle .sk-circle2{-webkit-transform:rotate(30deg);-ms-transform:rotate(30deg);transform:rotate(30deg)}.sk-spinner-fading-circle .sk-circle3{-webkit-transform:rotate(60deg);-ms-transform:rotate(60deg);transform:rotate(60deg)}.sk-spinner-fading-circle .sk-circle4{-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.sk-spinner-fading-circle .sk-circle5{-webkit-transform:rotate(120deg);-ms-transform:rotate(120deg);transform:rotate(120deg)}.sk-spinner-fading-circle .sk-circle6{-webkit-transform:rotate(150deg);-ms-transform:rotate(150deg);transform:rotate(150deg)}.sk-spinner-fading-circle .sk-circle7{-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.sk-spinner-fading-circle .sk-circle8{-webkit-transform:rotate(210deg);-ms-transform:rotate(210deg);transform:rotate(210deg)}.sk-spinner-fading-circle .sk-circle9{-webkit-transform:rotate(240deg);-ms-transform:rotate(240deg);transform:rotate(240deg)}.sk-spinner-fading-circle .sk-circle10{-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.sk-spinner-fading-circle .sk-circle11{-webkit-transform:rotate(300deg);-ms-transform:rotate(300deg);transform:rotate(300deg)}.sk-spinner-fading-circle .sk-circle12{-webkit-transform:rotate(330deg);-ms-transform:rotate(330deg);transform:rotate(330deg)}.sk-spinner-fading-circle .sk-circle2:before{-webkit-animation-delay:-1.1s;animation-delay:-1.1s}.sk-spinner-fading-circle .sk-circle3:before{-webkit-animation-delay:-1s;animation-delay:-1s}.sk-spinner-fading-circle .sk-circle4:before{-webkit-animation-delay:-0.9s;animation-delay:-0.9s}.sk-spinner-fading-circle .sk-circle5:before{-webkit-animation-delay:-0.8s;animation-delay:-0.8s}.sk-spinner-fading-circle .sk-circle6:before{-webkit-animation-delay:-0.7s;animation-delay:-0.7s}.sk-spinner-fading-circle .sk-circle7:before{-webkit-animation-delay:-0.6s;animation-delay:-0.6s}.sk-spinner-fading-circle .sk-circle8:before{-webkit-animation-delay:-0.5s;animation-delay:-0.5s}.sk-spinner-fading-circle .sk-circle9:before{-webkit-animation-delay:-0.4s;animation-delay:-0.4s}.sk-spinner-fading-circle .sk-circle10:before{-webkit-animation-delay:-0.3s;animation-delay:-0.3s}.sk-spinner-fading-circle .sk-circle11:before{-webkit-animation-delay:-0.2s;animation-delay:-0.2s}.sk-spinner-fading-circle .sk-circle12:before{-webkit-animation-delay:-0.1s;animation-delay:-0.1s}@-webkit-keyframes sk-circleFadeDelay{0%,39%,100%{opacity:0}40%{opacity:1}}@keyframes sk-circleFadeDelay{0%,39%,100%{opacity:0}40%{opacity:1}}body.rtls #page-wrapper{margin:0 220px 0 0}body.rtls .nav-second-level li a{padding:7px 35px 7px 10px}body.rtls .ibox-title h5{float:right}body.rtls .pull-right{float:left!important}body.rtls .pull-left{float:right!important}body.rtls .ibox-tools{float:left}body.rtls .stat-percent{float:left}body.rtls .navbar-right{float:left!important}body.rtls .navbar-top-links li:last-child{margin-left:40px;margin-right:0}body.rtls .minimalize-styl-2{float:right;margin:14px 20px 5px 5px}body.rtls .feed-element>.pull-left{margin-left:10px;margin-right:0}body.rtls .timeline-item .date{text-align:left}body.rtls .timeline-item .date i{left:0;right:auto}body.rtls .timeline-item .content{border-right:1px solid #e7eaec;border-left:none}body.rtls .toast-close-button{float:left}body.rtls #toast-container>.toast:before{margin:auto -1.5em auto .5em}body.rtls #toast-container>div{padding:15px 50px 15px 15px}body.rtls .center-orientation .vertical-timeline-icon i{margin-left:0;margin-right:-12px}body.rtls .vertical-timeline-icon i{right:50%;left:auto;margin-left:auto;margin-right:-12px}body.rtls .file-box{float:right}body.rtls ul.notes li{float:right}body.rtls .chat-users,body.rtls .chat-statistic{margin-right:-30px;margin-left:auto}body.rtls .dropdown-menu>li>a{text-align:right}body.rtls .b-r{border-left:1px solid #e7eaec;border-right:0}body.rtls .dd-list .dd-list{padding-right:30px;padding-left:0}body.rtls .dd-item>button{float:right}body.rtls .skin-setttings{margin-right:40px;margin-left:0}body.rtls .skin-setttings{direction:ltr}body.rtls .footer.fixed{margin-right:220px;margin-left:0}@media(max-width :992px){body.rtls .chat-users,body.rtls .chat-statistic{margin-right:0}}body.rtls.mini-navbar .footer.fixed,body.body-small.mini-navbar .footer.fixed{margin:0 70px 0 0}body.rtls.mini-navbar.fixed-sidebar .footer.fixed,body.body-small.mini-navbar .footer.fixed{margin:0}body.rtls.top-navigation .navbar-toggle{float:right;margin-left:15px;margin-right:15px}.body-small.rtls.top-navigation .navbar-header{float:none}body.rtls.top-navigation #page-wrapper{margin:0}body.rtls.mini-navbar #page-wrapper{margin:0 70px 0 0}body.rtls.mini-navbar.fixed-sidebar #page-wrapper{margin:0}body.rtls.body-small.fixed-sidebar.mini-navbar #page-wrapper{margin:0 220px 0 0}body.rtls.body-small.fixed-sidebar.mini-navbar .navbar-static-side{width:220px}.body-small.rtls .navbar-fixed-top{margin-right:0}.body-small.rtls .navbar-header{float:right}body.rtls .navbar-top-links li:last-child{margin-left:20px}body.rtls .top-navigation #page-wrapper,body.rtls.mini-navbar .top-navigation #page-wrapper,body.rtls.mini-navbar.top-navigation #page-wrapper{margin:0}body.rtls .top-navigation .footer.fixed,body.rtls.top-navigation .footer.fixed{margin:0}@media(max-width :768px){body.rtls .navbar-top-links li:last-child{margin-left:20px}.body-small.rtls #page-wrapper{position:inherit;margin:0;min-height:1000px}.body-small.rtls .navbar-static-side{display:none;z-index:2001;position:absolute;width:70px}.body-small.rtls.mini-navbar .navbar-static-side{display:block}.rtls.fixed-sidebar.body-small .navbar-static-side{display:none;z-index:2001;position:fixed;width:220px}.rtls.fixed-sidebar.body-small.mini-navbar .navbar-static-side{display:block}}.rtls .ltr-support{direction:ltr}.page-tabs a{color:#999}.page-tabs a i{color:#ccc;margin-left:2px;font-size:13px}.page-tabs a.active{background:#eaedf1;color:#23508e}.page-tabs a.active:hover,.page-tabs a.active i:hover{background:#eaedf1;color:#23508e}@media(min-width :768px){.navbar-top-links .dropdown-messages,.navbar-top-links .dropdown-tasks,.navbar-top-links .dropdown-alerts{margin-left:auto}}@media(max-width :768px){body.fixed-sidebar .navbar-static-side{display:none}body.fixed-sidebar.mini-navbar .navbar-static-side{width:70px}.lock-word{display:none}.navbar-form-custom{display:none}.navbar-header{display:inline;float:left}.sidebard-panel{z-index:2;position:relative;width:auto;min-height:100%!important}.sidebar-content .wrapper{padding-right:0;z-index:1}.fixed-sidebar.body-small .navbar-static-side{display:none;z-index:2001;position:fixed;width:220px}.fixed-sidebar.body-small.mini-navbar .navbar-static-side{display:block}.ibox-tools{float:none;text-align:right;display:block}.content-tabs{display:none}#content-main{height:calc(100% - 100px)}.fixed-nav #content-main{height:calc(100% - 38px)}}.navbar-static-side{background:#2f4050}.nav-close{padding:10px;display:block;position:absolute;right:5px;top:5px;font-size:1.4em;cursor:pointer;z-index:10;display:none;color:rgba(255,255,255,.3)}@media(max-width :350px){body.fixed-sidebar.mini-navbar .navbar-static-side{width:0}.nav-close{display:block}#page-wrapper{margin-left:0!important}.timeline-item .date{text-align:left;width:110px;position:relative;padding-top:30px}.timeline-item .date i{position:absolute;top:0;left:15px;padding:5px;width:30px;text-align:center;border:1px solid #e7eaec;background:#f8f8f8}.timeline-item .content{border-left:none;border-top:1px solid #e7eaec;padding-top:10px;min-height:100px}.nav.navbar-top-links li.dropdown{display:none}.ibox-tools{float:none;text-align:left;display:inline-block}}.ui-jqgrid-titlebar{height:40px;line-height:24px;color:#676a6c;background-color:#f9f9f9;text-shadow:0 1px 0 rgba(255,255,255,0.5)}.ui-jqgrid .ui-jqgrid-title{float:left;margin-left:5px;font-weight:700}.ui-jqgrid .ui-jqgrid-titlebar{position:relative;border-left:0 solid;border-right:0 solid;border-top:0 solid}.social-feed-separated .social-feed-box{margin-left:62px}.social-feed-separated .social-avatar{float:left;padding:0}.social-feed-separated .social-avatar img{width:52px;height:52px;border:1px solid #e7eaec}.social-feed-separated .social-feed-box .social-avatar{padding:15px 15px 0 15px;float:none}.social-feed-box{border:1px solid #e7eaec;background:#fff;margin-bottom:15px}.article .social-feed-box{margin-bottom:0;border-bottom:0}.article .social-feed-box:last-child{margin-bottom:0;border-bottom:1px solid #e7eaec}.article .social-feed-box p{font-size:13px;line-height:18px}.social-action{margin:15px}.social-avatar{padding:15px 15px 0 15px}.social-comment .social-comment{margin-left:45px}.social-avatar img{height:40px;width:40px;margin-right:10px}.social-avatar .media-body a{font-size:14px;display:block}.social-body{padding:15px}.social-body img{margin-bottom:10px}.social-footer{border-top:1px solid #e7eaec;padding:10px 15px;background:#f9f9f9}.social-footer .social-comment img{width:32px;margin-right:10px}.social-comment:first-child{margin-top:0}.social-comment{margin-top:15px}.social-comment textarea{font-size:12px}@media(max-width :1000px){.welcome-message{display:none}}.echarts{height:240px}.checkbox-inline,.radio-inline,.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin:0 15px 0 0;font-size:14px}.navbar-toggle{background-color:#fff}.menuTab{-webkit-transition:all .3s ease-out 0s;transition:all .3s ease-out 0s}@media only screen and (-webkit-min-device-pixel-ratio :2){#content-main{-webkit-overflow-scrolling:touch}}.navbar-header{height:50px}.bs-glyphicons{margin:0 -10px 20px;overflow:hidden}.bs-glyphicons-list{padding-left:0;list-style:none}.bs-glyphicons li{float:left;width:25%;height:115px;padding:10px;font-size:10px;line-height:1.4;text-align:center;background-color:#f9f9f9;border:1px solid #fff}.bs-glyphicons .glyphicon{margin-top:5px;margin-bottom:10px;font-size:24px}.bs-glyphicons .glyphicon-class{display:block;text-align:center;word-wrap:break-word}.bs-glyphicons li:hover{color:#fff;background-color:#1ab394}@media(min-width :768px){.bs-glyphicons{margin-right:0;margin-left:0}.bs-glyphicons li{width:12.5%;font-size:12px}}.t-bar{padding-bottom:10px}.nopadding{padding:0}.note-editor .btn-default{color:#333!important;background-color:#fff!important;border-color:#ccc!important}.folder-list li.active a{color:#2791df;background:#f5f5f5}nav .logo{background-color:#367fa9;color:#fff;border-bottom:0 solid transparent;-webkit-transition:width .3s ease-in-out;-o-transition:width .3s ease-in-out;transition:width .3s ease-in-out;display:block;height:50px;font-size:20px;line-height:50px;text-align:center;width:200px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;padding:0 15px;font-weight:300;overflow:hidden}.logo-mini{display:none}.logo-lg{display:block}.roleList{color:#d5d5d5;margin-right:10px;padding-top:10px;line-height:1;white-space:nowrap;overflow:hidden;width:110px}.sidebar-collapse .user-panel{white-space:nowrap;position:relative;width:100%;padding:15px;overflow:hidden}.sidebar-collapse .user-panel .image>img{width:100%;max-width:45px;height:auto}.sidebar-collapse .user-panel>.info{padding:5px 5px 5px 15px;line-height:1;position:absolute;left:55px}.sidebar-collapse .user-panel>.info a{color:#fff;font-size:12px}.sidebar-collapse .user-panel>.info>p{font-weight:600;margin-bottom:9px;color:#fff;font-size:12px}.user-panel>.info>a>.fa,.user-panel>.info>a>.ion,.user-panel>.info>a>.glyphicon{margin-right:3px}.nav>li:hover .dropdown-menu{display:block}#content-main.max{height:calc(100% - 110px);overflow:hidden;width:100%;height:100%;left:0;position:absolute;top:0;z-index:9998;margin:0}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/css/zen-checkbox.css b/ruoyi-admin/src/main/resources/static/css/zen-checkbox.css
new file mode 100644
index 0000000..c8186e9
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/css/zen-checkbox.css
@@ -0,0 +1,149 @@
+@font-face {
+	font-family:ZenIcon;src:url(../fonts/zenicon.woff?v=2.2.0) format('woff')
+}
+
+.checkbox-primary,.radio-primary {
+	position: relative;
+	display: block
+}
+
+.checkbox-primary>input,.radio-primary>input {
+	position: absolute;
+	top: 0;
+	left: 0;
+	z-index: 3;
+	width: 100%;
+	width: 20px;
+	height: 100%;
+	margin: 0;
+	opacity: 0
+}
+
+.checkbox-primary>label,.radio-primary>label {
+	padding-left: 25px;
+	font-weight: 400;
+	cursor: pointer
+}
+
+.checkbox-primary>label:after,.checkbox-primary>label:before,.radio-primary>label:after,.radio-primary>label:before {
+	position: absolute;
+	top: 2px;
+	right: 0;
+	left: 0;
+	display: block;
+	width: 16px;
+	height: 16px;
+	line-height: 16px;
+	text-align: center;
+	content: ' ';
+	border-radius: 2px
+}
+
+.checkbox-primary>label:after,.radio-primary>label:after {
+	z-index: 1;
+	border: 1px solid gray;
+	-webkit-transition: .4s cubic-bezier(.175,.885,.32,1);
+	-o-transition: .4s cubic-bezier(.175,.885,.32,1);
+	transition: .4s cubic-bezier(.175,.885,.32,1);
+	-webkit-transition-property: border,background-color;
+	-o-transition-property: border,background-color;
+	transition-property: border,background-color
+}
+
+.checkbox-primary>label:before,.radio-primary>label:before {
+	top: 3px;
+	z-index: 2;
+	font-family: ZenIcon;
+	font-size: 14px;
+	font-style: normal;
+	font-weight: 400;
+	font-variant: normal;
+	line-height: 1;
+	text-transform: none;
+	content: '\e60d';
+	opacity: 0;
+	-webkit-transition: .2s cubic-bezier(.175,.885,.32,1);
+	-o-transition: .2s cubic-bezier(.175,.885,.32,1);
+	transition: .2s cubic-bezier(.175,.885,.32,1);
+	-webkit-transition-property: opacity,-webkit-transform;
+	-o-transition-property: opacity,-o-transform;
+	transition-property: opacity,-webkit-transform;
+	transition-property: opacity,transform;
+	transition-property: opacity,transform,-webkit-transform,-o-transform;
+	-webkit-transform: scale(0);
+	-ms-transform: scale(0);
+	-o-transform: scale(0);
+	transform: scale(0);
+	speak: none;
+	-webkit-font-smoothing: antialiased;
+	-moz-osx-font-smoothing: grayscale
+}
+
+.checkbox-primary.checked>label:after,.checkbox-primary>input:checked+label:after,.radio-primary.checked>label:after,.radio-primary>input:checked+label:after {
+	background-color: #3280fc;
+	border-color: #3280fc;
+	border-width: 4px
+}
+
+.checkbox-primary.checked>label:before,.checkbox-primary>input:checked+label:before,.radio-primary.checked>label:before,.radio-primary>input:checked+label:before {
+	color: #fff;
+	opacity: 1;
+	-webkit-transform: scale(1);
+	-ms-transform: scale(1);
+	-o-transform: scale(1);
+	transform: scale(1)
+}
+
+.checkbox-primary.focus>label:after,.checkbox-primary>input:focus+label:after,.radio-primary.focus>label:after,.radio-primary>input:focus+label:after {
+	border-color: #3280fc;
+	-webkit-box-shadow: 0 0 8px #3280fc;
+	box-shadow: 0 0 8px #3280fc
+}
+
+.checkbox-primary input:disabled+label:after,.checkbox-primary.disabled>label:after,.radio-primary input:disabled+label:after,.radio-primary.disabled>label:after {
+	background-color: #e5e5e5;
+	border-color: #bbb
+}
+
+.checkbox-primary input:disabled:checked+label:after,.checkbox-primary.checked.disabled>label:after,.radio-primary input:disabled:checked+label:after,.radio-primary.checked.disabled>label:after {
+	background-color: #bbb
+}
+
+.radio-primary>label:after {
+	border-radius: 50%
+}
+
+.radio-primary>label:before {
+	top: 7px;
+	left: 5px;
+	width: 6px;
+	height: 6px;
+	content: ' ';
+	border: 0;
+	border-radius: 50%
+}
+
+.radio-primary.checked>label:after,.radio-primary>input:checked+label:after {
+	background-color: transparent;
+	border-color: #3280fc;
+	border-width: 2px
+}
+
+.radio-primary.checked>label:before,.radio-primary>input:checked+label:before {
+	background-color: #3280fc
+}
+
+.radio-primary input:disabled:checked+label:after,.radio-primary.checked.disabled>label:after {
+	background-color: transparent;
+	border-color: #bbb
+}
+
+.radio-primary input:disabled:checked+label:before,.radio-primary.checked.disabled>label:before {
+	background-color: #bbb
+}
+
+.tab-cron .tab-pane .tabsecondchk .checkbox-primary,.tab-qqskey .tab-pane .tabsecondchk .checkbox-primary {
+	width: 50px;
+	display: inline-block;
+	margin-bottom: 10px
+}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/favicon.ico b/ruoyi-admin/src/main/resources/static/favicon.ico
new file mode 100644
index 0000000..6f07782
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/favicon.ico
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/file/rml.txt b/ruoyi-admin/src/main/resources/static/file/rml.txt
new file mode 100644
index 0000000..2e2db92
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/file/rml.txt
@@ -0,0 +1 @@
+下载临时目录
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/fonts/FontAwesome.otf b/ruoyi-admin/src/main/resources/static/fonts/FontAwesome.otf
new file mode 100644
index 0000000..401ec0f
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/fonts/FontAwesome.otf
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/fonts/Simple-Line-Icons.woff2 b/ruoyi-admin/src/main/resources/static/fonts/Simple-Line-Icons.woff2
new file mode 100644
index 0000000..c49fccf
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/fonts/Simple-Line-Icons.woff2
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/fonts/fontawesome-webfont.eot b/ruoyi-admin/src/main/resources/static/fonts/fontawesome-webfont.eot
new file mode 100644
index 0000000..e9f60ca
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/fonts/fontawesome-webfont.eot
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/fonts/fontawesome-webfont.svg b/ruoyi-admin/src/main/resources/static/fonts/fontawesome-webfont.svg
new file mode 100644
index 0000000..855c845
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/fonts/fontawesome-webfont.svg
@@ -0,0 +1,2671 @@
+<?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>
+<metadata>
+Created by FontForge 20120731 at Mon Oct 24 17:37:40 2016
+ By ,,,
+Copyright Dave Gandy 2016. All rights reserved.
+</metadata>
+<defs>
+<font id="FontAwesome" horiz-adv-x="1536" >
+  <font-face 
+    font-family="FontAwesome"
+    font-weight="400"
+    font-stretch="normal"
+    units-per-em="1792"
+    panose-1="0 0 0 0 0 0 0 0 0 0"
+    ascent="1536"
+    descent="-256"
+    bbox="-1.02083 -256.962 2304.6 1537.02"
+    underline-thickness="0"
+    underline-position="0"
+    unicode-range="U+0020-F500"
+  />
+<missing-glyph horiz-adv-x="896" 
+d="M224 112h448v1312h-448v-1312zM112 0v1536h672v-1536h-672z" />
+    <glyph glyph-name=".notdef" horiz-adv-x="896" 
+d="M224 112h448v1312h-448v-1312zM112 0v1536h672v-1536h-672z" />
+    <glyph glyph-name=".null" horiz-adv-x="0" 
+ />
+    <glyph glyph-name="nonmarkingreturn" horiz-adv-x="597" 
+ />
+    <glyph glyph-name="space" unicode=" " horiz-adv-x="448" 
+ />
+    <glyph glyph-name="dieresis" unicode="&#xa8;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="copyright" unicode="&#xa9;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="registered" unicode="&#xae;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="acute" unicode="&#xb4;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="AE" unicode="&#xc6;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="Oslash" unicode="&#xd8;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="trademark" unicode="&#x2122;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="infinity" unicode="&#x221e;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="notequal" unicode="&#x2260;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="glass" unicode="&#xf000;" horiz-adv-x="1792" 
+d="M1699 1350q0 -35 -43 -78l-632 -632v-768h320q26 0 45 -19t19 -45t-19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45t45 19h320v768l-632 632q-43 43 -43 78q0 23 18 36.5t38 17.5t43 4h1408q23 0 43 -4t38 -17.5t18 -36.5z" />
+    <glyph glyph-name="music" unicode="&#xf001;" 
+d="M1536 1312v-1120q0 -50 -34 -89t-86 -60.5t-103.5 -32t-96.5 -10.5t-96.5 10.5t-103.5 32t-86 60.5t-34 89t34 89t86 60.5t103.5 32t96.5 10.5q105 0 192 -39v537l-768 -237v-709q0 -50 -34 -89t-86 -60.5t-103.5 -32t-96.5 -10.5t-96.5 10.5t-103.5 32t-86 60.5t-34 89
+t34 89t86 60.5t103.5 32t96.5 10.5q105 0 192 -39v967q0 31 19 56.5t49 35.5l832 256q12 4 28 4q40 0 68 -28t28 -68z" />
+    <glyph glyph-name="search" unicode="&#xf002;" horiz-adv-x="1664" 
+d="M1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1664 -128q0 -52 -38 -90t-90 -38q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5
+t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z" />
+    <glyph glyph-name="envelope" unicode="&#xf003;" horiz-adv-x="1792" 
+d="M1664 32v768q-32 -36 -69 -66q-268 -206 -426 -338q-51 -43 -83 -67t-86.5 -48.5t-102.5 -24.5h-1h-1q-48 0 -102.5 24.5t-86.5 48.5t-83 67q-158 132 -426 338q-37 30 -69 66v-768q0 -13 9.5 -22.5t22.5 -9.5h1472q13 0 22.5 9.5t9.5 22.5zM1664 1083v11v13.5t-0.5 13
+t-3 12.5t-5.5 9t-9 7.5t-14 2.5h-1472q-13 0 -22.5 -9.5t-9.5 -22.5q0 -168 147 -284q193 -152 401 -317q6 -5 35 -29.5t46 -37.5t44.5 -31.5t50.5 -27.5t43 -9h1h1q20 0 43 9t50.5 27.5t44.5 31.5t46 37.5t35 29.5q208 165 401 317q54 43 100.5 115.5t46.5 131.5z
+M1792 1120v-1088q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1472q66 0 113 -47t47 -113z" />
+    <glyph glyph-name="heart" unicode="&#xf004;" horiz-adv-x="1792" 
+d="M896 -128q-26 0 -44 18l-624 602q-10 8 -27.5 26t-55.5 65.5t-68 97.5t-53.5 121t-23.5 138q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5q224 0 351 -124t127 -344q0 -221 -229 -450l-623 -600
+q-18 -18 -44 -18z" />
+    <glyph glyph-name="star" unicode="&#xf005;" horiz-adv-x="1664" 
+d="M1664 889q0 -22 -26 -48l-363 -354l86 -500q1 -7 1 -20q0 -21 -10.5 -35.5t-30.5 -14.5q-19 0 -40 12l-449 236l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41t49 -41l225 -455
+l502 -73q56 -9 56 -46z" />
+    <glyph glyph-name="star_empty" unicode="&#xf006;" horiz-adv-x="1664" 
+d="M1137 532l306 297l-422 62l-189 382l-189 -382l-422 -62l306 -297l-73 -421l378 199l377 -199zM1664 889q0 -22 -26 -48l-363 -354l86 -500q1 -7 1 -20q0 -50 -41 -50q-19 0 -40 12l-449 236l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500
+l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41t49 -41l225 -455l502 -73q56 -9 56 -46z" />
+    <glyph glyph-name="user" unicode="&#xf007;" horiz-adv-x="1280" 
+d="M1280 137q0 -109 -62.5 -187t-150.5 -78h-854q-88 0 -150.5 78t-62.5 187q0 85 8.5 160.5t31.5 152t58.5 131t94 89t134.5 34.5q131 -128 313 -128t313 128q76 0 134.5 -34.5t94 -89t58.5 -131t31.5 -152t8.5 -160.5zM1024 1024q0 -159 -112.5 -271.5t-271.5 -112.5
+t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5z" />
+    <glyph glyph-name="film" unicode="&#xf008;" horiz-adv-x="1920" 
+d="M384 -64v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM384 320v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM384 704v128q0 26 -19 45t-45 19h-128
+q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1408 -64v512q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-512q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM384 1088v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45
+t45 -19h128q26 0 45 19t19 45zM1792 -64v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1408 704v512q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-512q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM1792 320v128
+q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1792 704v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1792 1088v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19
+t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1920 1248v-1344q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1344q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
+    <glyph glyph-name="th_large" unicode="&#xf009;" horiz-adv-x="1664" 
+d="M768 512v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM768 1280v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM1664 512v-384q0 -52 -38 -90t-90 -38
+h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM1664 1280v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90z" />
+    <glyph glyph-name="th" unicode="&#xf00a;" horiz-adv-x="1792" 
+d="M512 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 288v-192q0 -40 -28 -68t-68 -28h-320
+q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28
+h320q40 0 68 -28t28 -68zM1792 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 800v-192
+q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68z" />
+    <glyph glyph-name="th_list" unicode="&#xf00b;" horiz-adv-x="1792" 
+d="M512 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 288v-192q0 -40 -28 -68t-68 -28h-960
+q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h960q40 0 68 -28t28 -68zM512 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 800v-192q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v192q0 40 28 68t68 28
+h960q40 0 68 -28t28 -68zM1792 1312v-192q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h960q40 0 68 -28t28 -68z" />
+    <glyph glyph-name="ok" unicode="&#xf00c;" horiz-adv-x="1792" 
+d="M1671 970q0 -40 -28 -68l-724 -724l-136 -136q-28 -28 -68 -28t-68 28l-136 136l-362 362q-28 28 -28 68t28 68l136 136q28 28 68 28t68 -28l294 -295l656 657q28 28 68 28t68 -28l136 -136q28 -28 28 -68z" />
+    <glyph glyph-name="remove" unicode="&#xf00d;" horiz-adv-x="1408" 
+d="M1298 214q0 -40 -28 -68l-136 -136q-28 -28 -68 -28t-68 28l-294 294l-294 -294q-28 -28 -68 -28t-68 28l-136 136q-28 28 -28 68t28 68l294 294l-294 294q-28 28 -28 68t28 68l136 136q28 28 68 28t68 -28l294 -294l294 294q28 28 68 28t68 -28l136 -136q28 -28 28 -68
+t-28 -68l-294 -294l294 -294q28 -28 28 -68z" />
+    <glyph glyph-name="zoom_in" unicode="&#xf00e;" horiz-adv-x="1664" 
+d="M1024 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-224v-224q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v224h-224q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h224v224q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5v-224h224
+q13 0 22.5 -9.5t9.5 -22.5zM1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1664 -128q0 -53 -37.5 -90.5t-90.5 -37.5q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5
+t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z" />
+    <glyph glyph-name="zoom_out" unicode="&#xf010;" horiz-adv-x="1664" 
+d="M1024 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-576q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h576q13 0 22.5 -9.5t9.5 -22.5zM1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5z
+M1664 -128q0 -53 -37.5 -90.5t-90.5 -37.5q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z
+" />
+    <glyph glyph-name="off" unicode="&#xf011;" 
+d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61t-298 61t-245 164t-164 245t-61 298q0 182 80.5 343t226.5 270q43 32 95.5 25t83.5 -50q32 -42 24.5 -94.5t-49.5 -84.5q-98 -74 -151.5 -181t-53.5 -228q0 -104 40.5 -198.5t109.5 -163.5t163.5 -109.5
+t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5q0 121 -53.5 228t-151.5 181q-42 32 -49.5 84.5t24.5 94.5q31 43 84 50t95 -25q146 -109 226.5 -270t80.5 -343zM896 1408v-640q0 -52 -38 -90t-90 -38t-90 38t-38 90v640q0 52 38 90t90 38t90 -38t38 -90z" />
+    <glyph glyph-name="signal" unicode="&#xf012;" horiz-adv-x="1792" 
+d="M256 96v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM640 224v-320q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v320q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1024 480v-576q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23
+v576q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1408 864v-960q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v960q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1792 1376v-1472q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v1472q0 14 9 23t23 9h192q14 0 23 -9t9 -23z" />
+    <glyph glyph-name="cog" unicode="&#xf013;" 
+d="M1024 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1536 749v-222q0 -12 -8 -23t-20 -13l-185 -28q-19 -54 -39 -91q35 -50 107 -138q10 -12 10 -25t-9 -23q-27 -37 -99 -108t-94 -71q-12 0 -26 9l-138 108q-44 -23 -91 -38
+q-16 -136 -29 -186q-7 -28 -36 -28h-222q-14 0 -24.5 8.5t-11.5 21.5l-28 184q-49 16 -90 37l-141 -107q-10 -9 -25 -9q-14 0 -25 11q-126 114 -165 168q-7 10 -7 23q0 12 8 23q15 21 51 66.5t54 70.5q-27 50 -41 99l-183 27q-13 2 -21 12.5t-8 23.5v222q0 12 8 23t19 13
+l186 28q14 46 39 92q-40 57 -107 138q-10 12 -10 24q0 10 9 23q26 36 98.5 107.5t94.5 71.5q13 0 26 -10l138 -107q44 23 91 38q16 136 29 186q7 28 36 28h222q14 0 24.5 -8.5t11.5 -21.5l28 -184q49 -16 90 -37l142 107q9 9 24 9q13 0 25 -10q129 -119 165 -170q7 -8 7 -22
+q0 -12 -8 -23q-15 -21 -51 -66.5t-54 -70.5q26 -50 41 -98l183 -28q13 -2 21 -12.5t8 -23.5z" />
+    <glyph glyph-name="trash" unicode="&#xf014;" horiz-adv-x="1408" 
+d="M512 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM768 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1024 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576
+q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1152 76v948h-896v-948q0 -22 7 -40.5t14.5 -27t10.5 -8.5h832q3 0 10.5 8.5t14.5 27t7 40.5zM480 1152h448l-48 117q-7 9 -17 11h-317q-10 -2 -17 -11zM1408 1120v-64q0 -14 -9 -23t-23 -9h-96v-948q0 -83 -47 -143.5t-113 -60.5h-832
+q-66 0 -113 58.5t-47 141.5v952h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h309l70 167q15 37 54 63t79 26h320q40 0 79 -26t54 -63l70 -167h309q14 0 23 -9t9 -23z" />
+    <glyph glyph-name="home" unicode="&#xf015;" horiz-adv-x="1664" 
+d="M1408 544v-480q0 -26 -19 -45t-45 -19h-384v384h-256v-384h-384q-26 0 -45 19t-19 45v480q0 1 0.5 3t0.5 3l575 474l575 -474q1 -2 1 -6zM1631 613l-62 -74q-8 -9 -21 -11h-3q-13 0 -21 7l-692 577l-692 -577q-12 -8 -24 -7q-13 2 -21 11l-62 74q-8 10 -7 23.5t11 21.5
+l719 599q32 26 76 26t76 -26l244 -204v195q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-408l219 -182q10 -8 11 -21.5t-7 -23.5z" />
+    <glyph glyph-name="file_alt" unicode="&#xf016;" 
+d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z
+" />
+    <glyph glyph-name="time" unicode="&#xf017;" 
+d="M896 992v-448q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h224v352q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640
+q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="road" unicode="&#xf018;" horiz-adv-x="1920" 
+d="M1111 540v4l-24 320q-1 13 -11 22.5t-23 9.5h-186q-13 0 -23 -9.5t-11 -22.5l-24 -320v-4q-1 -12 8 -20t21 -8h244q12 0 21 8t8 20zM1870 73q0 -73 -46 -73h-704q13 0 22 9.5t8 22.5l-20 256q-1 13 -11 22.5t-23 9.5h-272q-13 0 -23 -9.5t-11 -22.5l-20 -256
+q-1 -13 8 -22.5t22 -9.5h-704q-46 0 -46 73q0 54 26 116l417 1044q8 19 26 33t38 14h339q-13 0 -23 -9.5t-11 -22.5l-15 -192q-1 -14 8 -23t22 -9h166q13 0 22 9t8 23l-15 192q-1 13 -11 22.5t-23 9.5h339q20 0 38 -14t26 -33l417 -1044q26 -62 26 -116z" />
+    <glyph glyph-name="download_alt" unicode="&#xf019;" horiz-adv-x="1664" 
+d="M1280 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 416v-320q0 -40 -28 -68t-68 -28h-1472q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h465l135 -136
+q58 -56 136 -56t136 56l136 136h464q40 0 68 -28t28 -68zM1339 985q17 -41 -14 -70l-448 -448q-18 -19 -45 -19t-45 19l-448 448q-31 29 -14 70q17 39 59 39h256v448q0 26 19 45t45 19h256q26 0 45 -19t19 -45v-448h256q42 0 59 -39z" />
+    <glyph glyph-name="download" unicode="&#xf01a;" 
+d="M1120 608q0 -12 -10 -24l-319 -319q-11 -9 -23 -9t-23 9l-320 320q-15 16 -7 35q8 20 30 20h192v352q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-352h192q14 0 23 -9t9 -23zM768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273
+t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="upload" unicode="&#xf01b;" 
+d="M1118 660q-8 -20 -30 -20h-192v-352q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v352h-192q-14 0 -23 9t-9 23q0 12 10 24l319 319q11 9 23 9t23 -9l320 -320q15 -16 7 -35zM768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198
+t73 273t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="inbox" unicode="&#xf01c;" 
+d="M1023 576h316q-1 3 -2.5 8.5t-2.5 7.5l-212 496h-708l-212 -496q-1 -3 -2.5 -8.5t-2.5 -7.5h316l95 -192h320zM1536 546v-482q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v482q0 62 25 123l238 552q10 25 36.5 42t52.5 17h832q26 0 52.5 -17t36.5 -42l238 -552
+q25 -61 25 -123z" />
+    <glyph glyph-name="play_circle" unicode="&#xf01d;" 
+d="M1184 640q0 -37 -32 -55l-544 -320q-15 -9 -32 -9q-16 0 -32 8q-32 19 -32 56v640q0 37 32 56q33 18 64 -1l544 -320q32 -18 32 -55zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640
+q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="repeat" unicode="&#xf01e;" 
+d="M1536 1280v-448q0 -26 -19 -45t-45 -19h-448q-42 0 -59 40q-17 39 14 69l138 138q-148 137 -349 137q-104 0 -198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5q119 0 225 52t179 147q7 10 23 12q15 0 25 -9
+l137 -138q9 -8 9.5 -20.5t-7.5 -22.5q-109 -132 -264 -204.5t-327 -72.5q-156 0 -298 61t-245 164t-164 245t-61 298t61 298t164 245t245 164t298 61q147 0 284.5 -55.5t244.5 -156.5l130 129q29 31 70 14q39 -17 39 -59z" />
+    <glyph glyph-name="refresh" unicode="&#xf021;" 
+d="M1511 480q0 -5 -1 -7q-64 -268 -268 -434.5t-478 -166.5q-146 0 -282.5 55t-243.5 157l-129 -129q-19 -19 -45 -19t-45 19t-19 45v448q0 26 19 45t45 19h448q26 0 45 -19t19 -45t-19 -45l-137 -137q71 -66 161 -102t187 -36q134 0 250 65t186 179q11 17 53 117
+q8 23 30 23h192q13 0 22.5 -9.5t9.5 -22.5zM1536 1280v-448q0 -26 -19 -45t-45 -19h-448q-26 0 -45 19t-19 45t19 45l138 138q-148 137 -349 137q-134 0 -250 -65t-186 -179q-11 -17 -53 -117q-8 -23 -30 -23h-199q-13 0 -22.5 9.5t-9.5 22.5v7q65 268 270 434.5t480 166.5
+q146 0 284 -55.5t245 -156.5l130 129q19 19 45 19t45 -19t19 -45z" />
+    <glyph glyph-name="list_alt" unicode="&#xf022;" horiz-adv-x="1792" 
+d="M384 352v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 608v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M384 864v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1536 352v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5t9.5 -22.5z
+M1536 608v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5t9.5 -22.5zM1536 864v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5
+t9.5 -22.5zM1664 160v832q0 13 -9.5 22.5t-22.5 9.5h-1472q-13 0 -22.5 -9.5t-9.5 -22.5v-832q0 -13 9.5 -22.5t22.5 -9.5h1472q13 0 22.5 9.5t9.5 22.5zM1792 1248v-1088q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1472q66 0 113 -47
+t47 -113z" />
+    <glyph glyph-name="lock" unicode="&#xf023;" horiz-adv-x="1152" 
+d="M320 768h512v192q0 106 -75 181t-181 75t-181 -75t-75 -181v-192zM1152 672v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h32v192q0 184 132 316t316 132t316 -132t132 -316v-192h32q40 0 68 -28t28 -68z" />
+    <glyph glyph-name="flag" unicode="&#xf024;" horiz-adv-x="1792" 
+d="M320 1280q0 -72 -64 -110v-1266q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v1266q-64 38 -64 110q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -25 -12.5 -38.5t-39.5 -27.5q-215 -116 -369 -116q-61 0 -123.5 22t-108.5 48
+t-115.5 48t-142.5 22q-192 0 -464 -146q-17 -9 -33 -9q-26 0 -45 19t-19 45v742q0 32 31 55q21 14 79 43q236 120 421 120q107 0 200 -29t219 -88q38 -19 88 -19q54 0 117.5 21t110 47t88 47t54.5 21q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="headphones" unicode="&#xf025;" horiz-adv-x="1664" 
+d="M1664 650q0 -166 -60 -314l-20 -49l-185 -33q-22 -83 -90.5 -136.5t-156.5 -53.5v-32q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-32q71 0 130 -35.5t93 -95.5l68 12q29 95 29 193q0 148 -88 279t-236.5 209t-315.5 78
+t-315.5 -78t-236.5 -209t-88 -279q0 -98 29 -193l68 -12q34 60 93 95.5t130 35.5v32q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v32q-88 0 -156.5 53.5t-90.5 136.5l-185 33l-20 49q-60 148 -60 314q0 151 67 291t179 242.5
+t266 163.5t320 61t320 -61t266 -163.5t179 -242.5t67 -291z" />
+    <glyph glyph-name="volume_off" unicode="&#xf026;" horiz-adv-x="768" 
+d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45z" />
+    <glyph glyph-name="volume_down" unicode="&#xf027;" horiz-adv-x="1152" 
+d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45zM1152 640q0 -76 -42.5 -141.5t-112.5 -93.5q-10 -5 -25 -5q-26 0 -45 18.5t-19 45.5q0 21 12 35.5t29 25t34 23t29 36
+t12 56.5t-12 56.5t-29 36t-34 23t-29 25t-12 35.5q0 27 19 45.5t45 18.5q15 0 25 -5q70 -27 112.5 -93t42.5 -142z" />
+    <glyph glyph-name="volume_up" unicode="&#xf028;" horiz-adv-x="1664" 
+d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45zM1152 640q0 -76 -42.5 -141.5t-112.5 -93.5q-10 -5 -25 -5q-26 0 -45 18.5t-19 45.5q0 21 12 35.5t29 25t34 23t29 36
+t12 56.5t-12 56.5t-29 36t-34 23t-29 25t-12 35.5q0 27 19 45.5t45 18.5q15 0 25 -5q70 -27 112.5 -93t42.5 -142zM1408 640q0 -153 -85 -282.5t-225 -188.5q-13 -5 -25 -5q-27 0 -46 19t-19 45q0 39 39 59q56 29 76 44q74 54 115.5 135.5t41.5 173.5t-41.5 173.5
+t-115.5 135.5q-20 15 -76 44q-39 20 -39 59q0 26 19 45t45 19q13 0 26 -5q140 -59 225 -188.5t85 -282.5zM1664 640q0 -230 -127 -422.5t-338 -283.5q-13 -5 -26 -5q-26 0 -45 19t-19 45q0 36 39 59q7 4 22.5 10.5t22.5 10.5q46 25 82 51q123 91 192 227t69 289t-69 289
+t-192 227q-36 26 -82 51q-7 4 -22.5 10.5t-22.5 10.5q-39 23 -39 59q0 26 19 45t45 19q13 0 26 -5q211 -91 338 -283.5t127 -422.5z" />
+    <glyph glyph-name="qrcode" unicode="&#xf029;" horiz-adv-x="1408" 
+d="M384 384v-128h-128v128h128zM384 1152v-128h-128v128h128zM1152 1152v-128h-128v128h128zM128 129h384v383h-384v-383zM128 896h384v384h-384v-384zM896 896h384v384h-384v-384zM640 640v-640h-640v640h640zM1152 128v-128h-128v128h128zM1408 128v-128h-128v128h128z
+M1408 640v-384h-384v128h-128v-384h-128v640h384v-128h128v128h128zM640 1408v-640h-640v640h640zM1408 1408v-640h-640v640h640z" />
+    <glyph glyph-name="barcode" unicode="&#xf02a;" horiz-adv-x="1792" 
+d="M63 0h-63v1408h63v-1408zM126 1h-32v1407h32v-1407zM220 1h-31v1407h31v-1407zM377 1h-31v1407h31v-1407zM534 1h-62v1407h62v-1407zM660 1h-31v1407h31v-1407zM723 1h-31v1407h31v-1407zM786 1h-31v1407h31v-1407zM943 1h-63v1407h63v-1407zM1100 1h-63v1407h63v-1407z
+M1226 1h-63v1407h63v-1407zM1352 1h-63v1407h63v-1407zM1446 1h-63v1407h63v-1407zM1635 1h-94v1407h94v-1407zM1698 1h-32v1407h32v-1407zM1792 0h-63v1408h63v-1408z" />
+    <glyph glyph-name="tag" unicode="&#xf02b;" 
+d="M448 1088q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1515 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-53 0 -90 37l-715 716q-38 37 -64.5 101t-26.5 117v416q0 52 38 90t90 38h416q53 0 117 -26.5t102 -64.5
+l715 -714q37 -39 37 -91z" />
+    <glyph glyph-name="tags" unicode="&#xf02c;" horiz-adv-x="1920" 
+d="M448 1088q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1515 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-53 0 -90 37l-715 716q-38 37 -64.5 101t-26.5 117v416q0 52 38 90t90 38h416q53 0 117 -26.5t102 -64.5
+l715 -714q37 -39 37 -91zM1899 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-36 0 -59 14t-53 45l470 470q37 37 37 90q0 52 -37 91l-715 714q-38 38 -102 64.5t-117 26.5h224q53 0 117 -26.5t102 -64.5l715 -714q37 -39 37 -91z" />
+    <glyph glyph-name="book" unicode="&#xf02d;" horiz-adv-x="1664" 
+d="M1639 1058q40 -57 18 -129l-275 -906q-19 -64 -76.5 -107.5t-122.5 -43.5h-923q-77 0 -148.5 53.5t-99.5 131.5q-24 67 -2 127q0 4 3 27t4 37q1 8 -3 21.5t-3 19.5q2 11 8 21t16.5 23.5t16.5 23.5q23 38 45 91.5t30 91.5q3 10 0.5 30t-0.5 28q3 11 17 28t17 23
+q21 36 42 92t25 90q1 9 -2.5 32t0.5 28q4 13 22 30.5t22 22.5q19 26 42.5 84.5t27.5 96.5q1 8 -3 25.5t-2 26.5q2 8 9 18t18 23t17 21q8 12 16.5 30.5t15 35t16 36t19.5 32t26.5 23.5t36 11.5t47.5 -5.5l-1 -3q38 9 51 9h761q74 0 114 -56t18 -130l-274 -906
+q-36 -119 -71.5 -153.5t-128.5 -34.5h-869q-27 0 -38 -15q-11 -16 -1 -43q24 -70 144 -70h923q29 0 56 15.5t35 41.5l300 987q7 22 5 57q38 -15 59 -43zM575 1056q-4 -13 2 -22.5t20 -9.5h608q13 0 25.5 9.5t16.5 22.5l21 64q4 13 -2 22.5t-20 9.5h-608q-13 0 -25.5 -9.5
+t-16.5 -22.5zM492 800q-4 -13 2 -22.5t20 -9.5h608q13 0 25.5 9.5t16.5 22.5l21 64q4 13 -2 22.5t-20 9.5h-608q-13 0 -25.5 -9.5t-16.5 -22.5z" />
+    <glyph glyph-name="bookmark" unicode="&#xf02e;" horiz-adv-x="1280" 
+d="M1164 1408q23 0 44 -9q33 -13 52.5 -41t19.5 -62v-1289q0 -34 -19.5 -62t-52.5 -41q-19 -8 -44 -8q-48 0 -83 32l-441 424l-441 -424q-36 -33 -83 -33q-23 0 -44 9q-33 13 -52.5 41t-19.5 62v1289q0 34 19.5 62t52.5 41q21 9 44 9h1048z" />
+    <glyph glyph-name="print" unicode="&#xf02f;" horiz-adv-x="1664" 
+d="M384 0h896v256h-896v-256zM384 640h896v384h-160q-40 0 -68 28t-28 68v160h-640v-640zM1536 576q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 576v-416q0 -13 -9.5 -22.5t-22.5 -9.5h-224v-160q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68
+v160h-224q-13 0 -22.5 9.5t-9.5 22.5v416q0 79 56.5 135.5t135.5 56.5h64v544q0 40 28 68t68 28h672q40 0 88 -20t76 -48l152 -152q28 -28 48 -76t20 -88v-256h64q79 0 135.5 -56.5t56.5 -135.5z" />
+    <glyph glyph-name="camera" unicode="&#xf030;" horiz-adv-x="1920" 
+d="M960 864q119 0 203.5 -84.5t84.5 -203.5t-84.5 -203.5t-203.5 -84.5t-203.5 84.5t-84.5 203.5t84.5 203.5t203.5 84.5zM1664 1280q106 0 181 -75t75 -181v-896q0 -106 -75 -181t-181 -75h-1408q-106 0 -181 75t-75 181v896q0 106 75 181t181 75h224l51 136
+q19 49 69.5 84.5t103.5 35.5h512q53 0 103.5 -35.5t69.5 -84.5l51 -136h224zM960 128q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+    <glyph glyph-name="font" unicode="&#xf031;" horiz-adv-x="1664" 
+d="M725 977l-170 -450q33 0 136.5 -2t160.5 -2q19 0 57 2q-87 253 -184 452zM0 -128l2 79q23 7 56 12.5t57 10.5t49.5 14.5t44.5 29t31 50.5l237 616l280 724h75h53q8 -14 11 -21l205 -480q33 -78 106 -257.5t114 -274.5q15 -34 58 -144.5t72 -168.5q20 -45 35 -57
+q19 -15 88 -29.5t84 -20.5q6 -38 6 -57q0 -5 -0.5 -13.5t-0.5 -12.5q-63 0 -190 8t-191 8q-76 0 -215 -7t-178 -8q0 43 4 78l131 28q1 0 12.5 2.5t15.5 3.5t14.5 4.5t15 6.5t11 8t9 11t2.5 14q0 16 -31 96.5t-72 177.5t-42 100l-450 2q-26 -58 -76.5 -195.5t-50.5 -162.5
+q0 -22 14 -37.5t43.5 -24.5t48.5 -13.5t57 -8.5t41 -4q1 -19 1 -58q0 -9 -2 -27q-58 0 -174.5 10t-174.5 10q-8 0 -26.5 -4t-21.5 -4q-80 -14 -188 -14z" />
+    <glyph glyph-name="bold" unicode="&#xf032;" horiz-adv-x="1408" 
+d="M555 15q74 -32 140 -32q376 0 376 335q0 114 -41 180q-27 44 -61.5 74t-67.5 46.5t-80.5 25t-84 10.5t-94.5 2q-73 0 -101 -10q0 -53 -0.5 -159t-0.5 -158q0 -8 -1 -67.5t-0.5 -96.5t4.5 -83.5t12 -66.5zM541 761q42 -7 109 -7q82 0 143 13t110 44.5t74.5 89.5t25.5 142
+q0 70 -29 122.5t-79 82t-108 43.5t-124 14q-50 0 -130 -13q0 -50 4 -151t4 -152q0 -27 -0.5 -80t-0.5 -79q0 -46 1 -69zM0 -128l2 94q15 4 85 16t106 27q7 12 12.5 27t8.5 33.5t5.5 32.5t3 37.5t0.5 34v35.5v30q0 982 -22 1025q-4 8 -22 14.5t-44.5 11t-49.5 7t-48.5 4.5
+t-30.5 3l-4 83q98 2 340 11.5t373 9.5q23 0 68 -0.5t68 -0.5q70 0 136.5 -13t128.5 -42t108 -71t74 -104.5t28 -137.5q0 -52 -16.5 -95.5t-39 -72t-64.5 -57.5t-73 -45t-84 -40q154 -35 256.5 -134t102.5 -248q0 -100 -35 -179.5t-93.5 -130.5t-138 -85.5t-163.5 -48.5
+t-176 -14q-44 0 -132 3t-132 3q-106 0 -307 -11t-231 -12z" />
+    <glyph glyph-name="italic" unicode="&#xf033;" horiz-adv-x="1024" 
+d="M0 -126l17 85q22 7 61.5 16.5t72 19t59.5 23.5q28 35 41 101q1 7 62 289t114 543.5t52 296.5v25q-24 13 -54.5 18.5t-69.5 8t-58 5.5l19 103q33 -2 120 -6.5t149.5 -7t120.5 -2.5q48 0 98.5 2.5t121 7t98.5 6.5q-5 -39 -19 -89q-30 -10 -101.5 -28.5t-108.5 -33.5
+q-8 -19 -14 -42.5t-9 -40t-7.5 -45.5t-6.5 -42q-27 -148 -87.5 -419.5t-77.5 -355.5q-2 -9 -13 -58t-20 -90t-16 -83.5t-6 -57.5l1 -18q17 -4 185 -31q-3 -44 -16 -99q-11 0 -32.5 -1.5t-32.5 -1.5q-29 0 -87 10t-86 10q-138 2 -206 2q-51 0 -143 -9t-121 -11z" />
+    <glyph glyph-name="text_height" unicode="&#xf034;" horiz-adv-x="1792" 
+d="M1744 128q33 0 42 -18.5t-11 -44.5l-126 -162q-20 -26 -49 -26t-49 26l-126 162q-20 26 -11 44.5t42 18.5h80v1024h-80q-33 0 -42 18.5t11 44.5l126 162q20 26 49 26t49 -26l126 -162q20 -26 11 -44.5t-42 -18.5h-80v-1024h80zM81 1407l54 -27q12 -5 211 -5q44 0 132 2
+t132 2q36 0 107.5 -0.5t107.5 -0.5h293q6 0 21 -0.5t20.5 0t16 3t17.5 9t15 17.5l42 1q4 0 14 -0.5t14 -0.5q2 -112 2 -336q0 -80 -5 -109q-39 -14 -68 -18q-25 44 -54 128q-3 9 -11 48t-14.5 73.5t-7.5 35.5q-6 8 -12 12.5t-15.5 6t-13 2.5t-18 0.5t-16.5 -0.5
+q-17 0 -66.5 0.5t-74.5 0.5t-64 -2t-71 -6q-9 -81 -8 -136q0 -94 2 -388t2 -455q0 -16 -2.5 -71.5t0 -91.5t12.5 -69q40 -21 124 -42.5t120 -37.5q5 -40 5 -50q0 -14 -3 -29l-34 -1q-76 -2 -218 8t-207 10q-50 0 -151 -9t-152 -9q-3 51 -3 52v9q17 27 61.5 43t98.5 29t78 27
+q19 42 19 383q0 101 -3 303t-3 303v117q0 2 0.5 15.5t0.5 25t-1 25.5t-3 24t-5 14q-11 12 -162 12q-33 0 -93 -12t-80 -26q-19 -13 -34 -72.5t-31.5 -111t-42.5 -53.5q-42 26 -56 44v383z" />
+    <glyph glyph-name="text_width" unicode="&#xf035;" 
+d="M81 1407l54 -27q12 -5 211 -5q44 0 132 2t132 2q70 0 246.5 1t304.5 0.5t247 -4.5q33 -1 56 31l42 1q4 0 14 -0.5t14 -0.5q2 -112 2 -336q0 -80 -5 -109q-39 -14 -68 -18q-25 44 -54 128q-3 9 -11 47.5t-15 73.5t-7 36q-10 13 -27 19q-5 2 -66 2q-30 0 -93 1t-103 1
+t-94 -2t-96 -7q-9 -81 -8 -136l1 -152v52q0 -55 1 -154t1.5 -180t0.5 -153q0 -16 -2.5 -71.5t0 -91.5t12.5 -69q40 -21 124 -42.5t120 -37.5q5 -40 5 -50q0 -14 -3 -29l-34 -1q-76 -2 -218 8t-207 10q-50 0 -151 -9t-152 -9q-3 51 -3 52v9q17 27 61.5 43t98.5 29t78 27
+q7 16 11.5 74t6 145.5t1.5 155t-0.5 153.5t-0.5 89q0 7 -2.5 21.5t-2.5 22.5q0 7 0.5 44t1 73t0 76.5t-3 67.5t-6.5 32q-11 12 -162 12q-41 0 -163 -13.5t-138 -24.5q-19 -12 -34 -71.5t-31.5 -111.5t-42.5 -54q-42 26 -56 44v383zM1310 125q12 0 42 -19.5t57.5 -41.5
+t59.5 -49t36 -30q26 -21 26 -49t-26 -49q-4 -3 -36 -30t-59.5 -49t-57.5 -41.5t-42 -19.5q-13 0 -20.5 10.5t-10 28.5t-2.5 33.5t1.5 33t1.5 19.5h-1024q0 -2 1.5 -19.5t1.5 -33t-2.5 -33.5t-10 -28.5t-20.5 -10.5q-12 0 -42 19.5t-57.5 41.5t-59.5 49t-36 30q-26 21 -26 49
+t26 49q4 3 36 30t59.5 49t57.5 41.5t42 19.5q13 0 20.5 -10.5t10 -28.5t2.5 -33.5t-1.5 -33t-1.5 -19.5h1024q0 2 -1.5 19.5t-1.5 33t2.5 33.5t10 28.5t20.5 10.5z" />
+    <glyph glyph-name="align_left" unicode="&#xf036;" horiz-adv-x="1792" 
+d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1408 576v-128q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1280q26 0 45 -19t19 -45zM1664 960v-128q0 -26 -19 -45
+t-45 -19h-1536q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1536q26 0 45 -19t19 -45zM1280 1344v-128q0 -26 -19 -45t-45 -19h-1152q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="align_center" unicode="&#xf037;" horiz-adv-x="1792" 
+d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1408 576v-128q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h896q26 0 45 -19t19 -45zM1664 960v-128q0 -26 -19 -45t-45 -19
+h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1280 1344v-128q0 -26 -19 -45t-45 -19h-640q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h640q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="align_right" unicode="&#xf038;" horiz-adv-x="1792" 
+d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 576v-128q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1280q26 0 45 -19t19 -45zM1792 960v-128q0 -26 -19 -45
+t-45 -19h-1536q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1536q26 0 45 -19t19 -45zM1792 1344v-128q0 -26 -19 -45t-45 -19h-1152q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="align_justify" unicode="&#xf039;" horiz-adv-x="1792" 
+d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 576v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 960v-128q0 -26 -19 -45
+t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 1344v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="list" unicode="&#xf03a;" horiz-adv-x="1792" 
+d="M256 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM256 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5
+t9.5 -22.5zM256 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1344
+q13 0 22.5 -9.5t9.5 -22.5zM256 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5
+t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192
+q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5z" />
+    <glyph glyph-name="indent_left" unicode="&#xf03b;" horiz-adv-x="1792" 
+d="M384 992v-576q0 -13 -9.5 -22.5t-22.5 -9.5q-14 0 -23 9l-288 288q-9 9 -9 23t9 23l288 288q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5
+t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088
+q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5t9.5 -22.5z" />
+    <glyph glyph-name="indent_right" unicode="&#xf03c;" horiz-adv-x="1792" 
+d="M352 704q0 -14 -9 -23l-288 -288q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v576q0 13 9.5 22.5t22.5 9.5q14 0 23 -9l288 -288q9 -9 9 -23zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5
+t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088
+q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5t9.5 -22.5z" />
+    <glyph glyph-name="facetime_video" unicode="&#xf03d;" horiz-adv-x="1792" 
+d="M1792 1184v-1088q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-403 403v-166q0 -119 -84.5 -203.5t-203.5 -84.5h-704q-119 0 -203.5 84.5t-84.5 203.5v704q0 119 84.5 203.5t203.5 84.5h704q119 0 203.5 -84.5t84.5 -203.5v-165l403 402q18 19 45 19q12 0 25 -5
+q39 -17 39 -59z" />
+    <glyph glyph-name="picture" unicode="&#xf03e;" horiz-adv-x="1920" 
+d="M640 960q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1664 576v-448h-1408v192l320 320l160 -160l512 512zM1760 1280h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-1216q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5v1216
+q0 13 -9.5 22.5t-22.5 9.5zM1920 1248v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
+    <glyph glyph-name="pencil" unicode="&#xf040;" 
+d="M363 0l91 91l-235 235l-91 -91v-107h128v-128h107zM886 928q0 22 -22 22q-10 0 -17 -7l-542 -542q-7 -7 -7 -17q0 -22 22 -22q10 0 17 7l542 542q7 7 7 17zM832 1120l416 -416l-832 -832h-416v416zM1515 1024q0 -53 -37 -90l-166 -166l-416 416l166 165q36 38 90 38
+q53 0 91 -38l235 -234q37 -39 37 -91z" />
+    <glyph glyph-name="map_marker" unicode="&#xf041;" horiz-adv-x="1024" 
+d="M768 896q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1024 896q0 -109 -33 -179l-364 -774q-16 -33 -47.5 -52t-67.5 -19t-67.5 19t-46.5 52l-365 774q-33 70 -33 179q0 212 150 362t362 150t362 -150t150 -362z" />
+    <glyph glyph-name="adjust" unicode="&#xf042;" 
+d="M768 96v1088q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="tint" unicode="&#xf043;" horiz-adv-x="1024" 
+d="M512 384q0 36 -20 69q-1 1 -15.5 22.5t-25.5 38t-25 44t-21 50.5q-4 16 -21 16t-21 -16q-7 -23 -21 -50.5t-25 -44t-25.5 -38t-15.5 -22.5q-20 -33 -20 -69q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1024 512q0 -212 -150 -362t-362 -150t-362 150t-150 362
+q0 145 81 275q6 9 62.5 90.5t101 151t99.5 178t83 201.5q9 30 34 47t51 17t51.5 -17t33.5 -47q28 -93 83 -201.5t99.5 -178t101 -151t62.5 -90.5q81 -127 81 -275z" />
+    <glyph glyph-name="edit" unicode="&#xf044;" horiz-adv-x="1792" 
+d="M888 352l116 116l-152 152l-116 -116v-56h96v-96h56zM1328 1072q-16 16 -33 -1l-350 -350q-17 -17 -1 -33t33 1l350 350q17 17 1 33zM1408 478v-190q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832
+q63 0 117 -25q15 -7 18 -23q3 -17 -9 -29l-49 -49q-14 -14 -32 -8q-23 6 -45 6h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v126q0 13 9 22l64 64q15 15 35 7t20 -29zM1312 1216l288 -288l-672 -672h-288v288zM1756 1084l-92 -92
+l-288 288l92 92q28 28 68 28t68 -28l152 -152q28 -28 28 -68t-28 -68z" />
+    <glyph glyph-name="share" unicode="&#xf045;" horiz-adv-x="1664" 
+d="M1408 547v-259q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h255v0q13 0 22.5 -9.5t9.5 -22.5q0 -27 -26 -32q-77 -26 -133 -60q-10 -4 -16 -4h-112q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832
+q66 0 113 47t47 113v214q0 19 18 29q28 13 54 37q16 16 35 8q21 -9 21 -29zM1645 1043l-384 -384q-18 -19 -45 -19q-12 0 -25 5q-39 17 -39 59v192h-160q-323 0 -438 -131q-119 -137 -74 -473q3 -23 -20 -34q-8 -2 -12 -2q-16 0 -26 13q-10 14 -21 31t-39.5 68.5t-49.5 99.5
+t-38.5 114t-17.5 122q0 49 3.5 91t14 90t28 88t47 81.5t68.5 74t94.5 61.5t124.5 48.5t159.5 30.5t196.5 11h160v192q0 42 39 59q13 5 25 5q26 0 45 -19l384 -384q19 -19 19 -45t-19 -45z" />
+    <glyph glyph-name="check" unicode="&#xf046;" horiz-adv-x="1664" 
+d="M1408 606v-318q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q63 0 117 -25q15 -7 18 -23q3 -17 -9 -29l-49 -49q-10 -10 -23 -10q-3 0 -9 2q-23 6 -45 6h-832q-66 0 -113 -47t-47 -113v-832
+q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v254q0 13 9 22l64 64q10 10 23 10q6 0 12 -3q20 -8 20 -29zM1639 1095l-814 -814q-24 -24 -57 -24t-57 24l-430 430q-24 24 -24 57t24 57l110 110q24 24 57 24t57 -24l263 -263l647 647q24 24 57 24t57 -24l110 -110
+q24 -24 24 -57t-24 -57z" />
+    <glyph glyph-name="move" unicode="&#xf047;" horiz-adv-x="1792" 
+d="M1792 640q0 -26 -19 -45l-256 -256q-19 -19 -45 -19t-45 19t-19 45v128h-384v-384h128q26 0 45 -19t19 -45t-19 -45l-256 -256q-19 -19 -45 -19t-45 19l-256 256q-19 19 -19 45t19 45t45 19h128v384h-384v-128q0 -26 -19 -45t-45 -19t-45 19l-256 256q-19 19 -19 45
+t19 45l256 256q19 19 45 19t45 -19t19 -45v-128h384v384h-128q-26 0 -45 19t-19 45t19 45l256 256q19 19 45 19t45 -19l256 -256q19 -19 19 -45t-19 -45t-45 -19h-128v-384h384v128q0 26 19 45t45 19t45 -19l256 -256q19 -19 19 -45z" />
+    <glyph glyph-name="step_backward" unicode="&#xf048;" horiz-adv-x="1024" 
+d="M979 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-678q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-678q4 10 13 19z" />
+    <glyph glyph-name="fast_backward" unicode="&#xf049;" horiz-adv-x="1792" 
+d="M1747 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-710q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-678q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-678q4 10 13 19l710 710
+q19 19 32 13t13 -32v-710q4 10 13 19z" />
+    <glyph glyph-name="backward" unicode="&#xf04a;" horiz-adv-x="1664" 
+d="M1619 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-710q0 -26 -13 -32t-32 13l-710 710q-19 19 -19 45t19 45l710 710q19 19 32 13t13 -32v-710q4 10 13 19z" />
+    <glyph glyph-name="play" unicode="&#xf04b;" horiz-adv-x="1408" 
+d="M1384 609l-1328 -738q-23 -13 -39.5 -3t-16.5 36v1472q0 26 16.5 36t39.5 -3l1328 -738q23 -13 23 -31t-23 -31z" />
+    <glyph glyph-name="pause" unicode="&#xf04c;" 
+d="M1536 1344v-1408q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h512q26 0 45 -19t19 -45zM640 1344v-1408q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h512q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="stop" unicode="&#xf04d;" 
+d="M1536 1344v-1408q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="forward" unicode="&#xf04e;" horiz-adv-x="1664" 
+d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q9 -9 13 -19v710q0 26 13 32t32 -13l710 -710q19 -19 19 -45t-19 -45l-710 -710q-19 -19 -32 -13t-13 32v710q-4 -10 -13 -19z" />
+    <glyph glyph-name="fast_forward" unicode="&#xf050;" horiz-adv-x="1792" 
+d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q9 -9 13 -19v710q0 26 13 32t32 -13l710 -710q9 -9 13 -19v678q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-1408q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v678q-4 -10 -13 -19l-710 -710
+q-19 -19 -32 -13t-13 32v710q-4 -10 -13 -19z" />
+    <glyph glyph-name="step_forward" unicode="&#xf051;" horiz-adv-x="1024" 
+d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q9 -9 13 -19v678q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-1408q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v678q-4 -10 -13 -19z" />
+    <glyph glyph-name="eject" unicode="&#xf052;" horiz-adv-x="1538" 
+d="M14 557l710 710q19 19 45 19t45 -19l710 -710q19 -19 13 -32t-32 -13h-1472q-26 0 -32 13t13 32zM1473 0h-1408q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1408q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19z" />
+    <glyph glyph-name="chevron_left" unicode="&#xf053;" horiz-adv-x="1280" 
+d="M1171 1235l-531 -531l531 -531q19 -19 19 -45t-19 -45l-166 -166q-19 -19 -45 -19t-45 19l-742 742q-19 19 -19 45t19 45l742 742q19 19 45 19t45 -19l166 -166q19 -19 19 -45t-19 -45z" />
+    <glyph glyph-name="chevron_right" unicode="&#xf054;" horiz-adv-x="1280" 
+d="M1107 659l-742 -742q-19 -19 -45 -19t-45 19l-166 166q-19 19 -19 45t19 45l531 531l-531 531q-19 19 -19 45t19 45l166 166q19 19 45 19t45 -19l742 -742q19 -19 19 -45t-19 -45z" />
+    <glyph glyph-name="plus_sign" unicode="&#xf055;" 
+d="M1216 576v128q0 26 -19 45t-45 19h-256v256q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-256h-256q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h256v-256q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v256h256q26 0 45 19t19 45zM1536 640q0 -209 -103 -385.5
+t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="minus_sign" unicode="&#xf056;" 
+d="M1216 576v128q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5
+t103 -385.5z" />
+    <glyph glyph-name="remove_sign" unicode="&#xf057;" 
+d="M1149 414q0 26 -19 45l-181 181l181 181q19 19 19 45q0 27 -19 46l-90 90q-19 19 -46 19q-26 0 -45 -19l-181 -181l-181 181q-19 19 -45 19q-27 0 -46 -19l-90 -90q-19 -19 -19 -46q0 -26 19 -45l181 -181l-181 -181q-19 -19 -19 -45q0 -27 19 -46l90 -90q19 -19 46 -19
+q26 0 45 19l181 181l181 -181q19 -19 45 -19q27 0 46 19l90 90q19 19 19 46zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="ok_sign" unicode="&#xf058;" 
+d="M1284 802q0 28 -18 46l-91 90q-19 19 -45 19t-45 -19l-408 -407l-226 226q-19 19 -45 19t-45 -19l-91 -90q-18 -18 -18 -46q0 -27 18 -45l362 -362q19 -19 45 -19q27 0 46 19l543 543q18 18 18 45zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103
+t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="question_sign" unicode="&#xf059;" 
+d="M896 160v192q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h192q14 0 23 9t9 23zM1152 832q0 88 -55.5 163t-138.5 116t-170 41q-243 0 -371 -213q-15 -24 8 -42l132 -100q7 -6 19 -6q16 0 25 12q53 68 86 92q34 24 86 24q48 0 85.5 -26t37.5 -59
+q0 -38 -20 -61t-68 -45q-63 -28 -115.5 -86.5t-52.5 -125.5v-36q0 -14 9 -23t23 -9h192q14 0 23 9t9 23q0 19 21.5 49.5t54.5 49.5q32 18 49 28.5t46 35t44.5 48t28 60.5t12.5 81zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5
+t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="info_sign" unicode="&#xf05a;" 
+d="M1024 160v160q0 14 -9 23t-23 9h-96v512q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-160q0 -14 9 -23t23 -9h96v-320h-96q-14 0 -23 -9t-9 -23v-160q0 -14 9 -23t23 -9h448q14 0 23 9t9 23zM896 1056v160q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-160q0 -14 9 -23
+t23 -9h192q14 0 23 9t9 23zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="screenshot" unicode="&#xf05b;" 
+d="M1197 512h-109q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h109q-32 108 -112.5 188.5t-188.5 112.5v-109q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v109q-108 -32 -188.5 -112.5t-112.5 -188.5h109q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-109
+q32 -108 112.5 -188.5t188.5 -112.5v109q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-109q108 32 188.5 112.5t112.5 188.5zM1536 704v-128q0 -26 -19 -45t-45 -19h-143q-37 -161 -154.5 -278.5t-278.5 -154.5v-143q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v143
+q-161 37 -278.5 154.5t-154.5 278.5h-143q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h143q37 161 154.5 278.5t278.5 154.5v143q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-143q161 -37 278.5 -154.5t154.5 -278.5h143q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="remove_circle" unicode="&#xf05c;" 
+d="M1097 457l-146 -146q-10 -10 -23 -10t-23 10l-137 137l-137 -137q-10 -10 -23 -10t-23 10l-146 146q-10 10 -10 23t10 23l137 137l-137 137q-10 10 -10 23t10 23l146 146q10 10 23 10t23 -10l137 -137l137 137q10 10 23 10t23 -10l146 -146q10 -10 10 -23t-10 -23
+l-137 -137l137 -137q10 -10 10 -23t-10 -23zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5
+t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="ok_circle" unicode="&#xf05d;" 
+d="M1171 723l-422 -422q-19 -19 -45 -19t-45 19l-294 294q-19 19 -19 45t19 45l102 102q19 19 45 19t45 -19l147 -147l275 275q19 19 45 19t45 -19l102 -102q19 -19 19 -45t-19 -45zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198
+t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="ban_circle" unicode="&#xf05e;" 
+d="M1312 643q0 161 -87 295l-754 -753q137 -89 297 -89q111 0 211.5 43.5t173.5 116.5t116 174.5t43 212.5zM313 344l755 754q-135 91 -300 91q-148 0 -273 -73t-198 -199t-73 -274q0 -162 89 -299zM1536 643q0 -157 -61 -300t-163.5 -246t-245 -164t-298.5 -61t-298.5 61
+t-245 164t-163.5 246t-61 300t61 299.5t163.5 245.5t245 164t298.5 61t298.5 -61t245 -164t163.5 -245.5t61 -299.5z" />
+    <glyph glyph-name="arrow_left" unicode="&#xf060;" 
+d="M1536 640v-128q0 -53 -32.5 -90.5t-84.5 -37.5h-704l293 -294q38 -36 38 -90t-38 -90l-75 -76q-37 -37 -90 -37q-52 0 -91 37l-651 652q-37 37 -37 90q0 52 37 91l651 650q38 38 91 38q52 0 90 -38l75 -74q38 -38 38 -91t-38 -91l-293 -293h704q52 0 84.5 -37.5
+t32.5 -90.5z" />
+    <glyph glyph-name="arrow_right" unicode="&#xf061;" 
+d="M1472 576q0 -54 -37 -91l-651 -651q-39 -37 -91 -37q-51 0 -90 37l-75 75q-38 38 -38 91t38 91l293 293h-704q-52 0 -84.5 37.5t-32.5 90.5v128q0 53 32.5 90.5t84.5 37.5h704l-293 294q-38 36 -38 90t38 90l75 75q38 38 90 38q53 0 91 -38l651 -651q37 -35 37 -90z" />
+    <glyph glyph-name="arrow_up" unicode="&#xf062;" horiz-adv-x="1664" 
+d="M1611 565q0 -51 -37 -90l-75 -75q-38 -38 -91 -38q-54 0 -90 38l-294 293v-704q0 -52 -37.5 -84.5t-90.5 -32.5h-128q-53 0 -90.5 32.5t-37.5 84.5v704l-294 -293q-36 -38 -90 -38t-90 38l-75 75q-38 38 -38 90q0 53 38 91l651 651q35 37 90 37q54 0 91 -37l651 -651
+q37 -39 37 -91z" />
+    <glyph glyph-name="arrow_down" unicode="&#xf063;" horiz-adv-x="1664" 
+d="M1611 704q0 -53 -37 -90l-651 -652q-39 -37 -91 -37q-53 0 -90 37l-651 652q-38 36 -38 90q0 53 38 91l74 75q39 37 91 37q53 0 90 -37l294 -294v704q0 52 38 90t90 38h128q52 0 90 -38t38 -90v-704l294 294q37 37 90 37q52 0 91 -37l75 -75q37 -39 37 -91z" />
+    <glyph glyph-name="share_alt" unicode="&#xf064;" horiz-adv-x="1792" 
+d="M1792 896q0 -26 -19 -45l-512 -512q-19 -19 -45 -19t-45 19t-19 45v256h-224q-98 0 -175.5 -6t-154 -21.5t-133 -42.5t-105.5 -69.5t-80 -101t-48.5 -138.5t-17.5 -181q0 -55 5 -123q0 -6 2.5 -23.5t2.5 -26.5q0 -15 -8.5 -25t-23.5 -10q-16 0 -28 17q-7 9 -13 22
+t-13.5 30t-10.5 24q-127 285 -127 451q0 199 53 333q162 403 875 403h224v256q0 26 19 45t45 19t45 -19l512 -512q19 -19 19 -45z" />
+    <glyph glyph-name="resize_full" unicode="&#xf065;" 
+d="M755 480q0 -13 -10 -23l-332 -332l144 -144q19 -19 19 -45t-19 -45t-45 -19h-448q-26 0 -45 19t-19 45v448q0 26 19 45t45 19t45 -19l144 -144l332 332q10 10 23 10t23 -10l114 -114q10 -10 10 -23zM1536 1344v-448q0 -26 -19 -45t-45 -19t-45 19l-144 144l-332 -332
+q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l332 332l-144 144q-19 19 -19 45t19 45t45 19h448q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="resize_small" unicode="&#xf066;" 
+d="M768 576v-448q0 -26 -19 -45t-45 -19t-45 19l-144 144l-332 -332q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l332 332l-144 144q-19 19 -19 45t19 45t45 19h448q26 0 45 -19t19 -45zM1523 1248q0 -13 -10 -23l-332 -332l144 -144q19 -19 19 -45t-19 -45
+t-45 -19h-448q-26 0 -45 19t-19 45v448q0 26 19 45t45 19t45 -19l144 -144l332 332q10 10 23 10t23 -10l114 -114q10 -10 10 -23z" />
+    <glyph glyph-name="plus" unicode="&#xf067;" horiz-adv-x="1408" 
+d="M1408 800v-192q0 -40 -28 -68t-68 -28h-416v-416q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v416h-416q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h416v416q0 40 28 68t68 28h192q40 0 68 -28t28 -68v-416h416q40 0 68 -28t28 -68z" />
+    <glyph glyph-name="minus" unicode="&#xf068;" horiz-adv-x="1408" 
+d="M1408 800v-192q0 -40 -28 -68t-68 -28h-1216q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h1216q40 0 68 -28t28 -68z" />
+    <glyph glyph-name="asterisk" unicode="&#xf069;" horiz-adv-x="1664" 
+d="M1482 486q46 -26 59.5 -77.5t-12.5 -97.5l-64 -110q-26 -46 -77.5 -59.5t-97.5 12.5l-266 153v-307q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v307l-266 -153q-46 -26 -97.5 -12.5t-77.5 59.5l-64 110q-26 46 -12.5 97.5t59.5 77.5l266 154l-266 154
+q-46 26 -59.5 77.5t12.5 97.5l64 110q26 46 77.5 59.5t97.5 -12.5l266 -153v307q0 52 38 90t90 38h128q52 0 90 -38t38 -90v-307l266 153q46 26 97.5 12.5t77.5 -59.5l64 -110q26 -46 12.5 -97.5t-59.5 -77.5l-266 -154z" />
+    <glyph glyph-name="exclamation_sign" unicode="&#xf06a;" 
+d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM896 161v190q0 14 -9 23.5t-22 9.5h-192q-13 0 -23 -10t-10 -23v-190q0 -13 10 -23t23 -10h192
+q13 0 22 9.5t9 23.5zM894 505l18 621q0 12 -10 18q-10 8 -24 8h-220q-14 0 -24 -8q-10 -6 -10 -18l17 -621q0 -10 10 -17.5t24 -7.5h185q14 0 23.5 7.5t10.5 17.5z" />
+    <glyph glyph-name="gift" unicode="&#xf06b;" 
+d="M928 180v56v468v192h-320v-192v-468v-56q0 -25 18 -38.5t46 -13.5h192q28 0 46 13.5t18 38.5zM472 1024h195l-126 161q-26 31 -69 31q-40 0 -68 -28t-28 -68t28 -68t68 -28zM1160 1120q0 40 -28 68t-68 28q-43 0 -69 -31l-125 -161h194q40 0 68 28t28 68zM1536 864v-320
+q0 -14 -9 -23t-23 -9h-96v-416q0 -40 -28 -68t-68 -28h-1088q-40 0 -68 28t-28 68v416h-96q-14 0 -23 9t-9 23v320q0 14 9 23t23 9h440q-93 0 -158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5q107 0 168 -77l128 -165l128 165q61 77 168 77q93 0 158.5 -65.5t65.5 -158.5
+t-65.5 -158.5t-158.5 -65.5h440q14 0 23 -9t9 -23z" />
+    <glyph glyph-name="leaf" unicode="&#xf06c;" horiz-adv-x="1792" 
+d="M1280 832q0 26 -19 45t-45 19q-172 0 -318 -49.5t-259.5 -134t-235.5 -219.5q-19 -21 -19 -45q0 -26 19 -45t45 -19q24 0 45 19q27 24 74 71t67 66q137 124 268.5 176t313.5 52q26 0 45 19t19 45zM1792 1030q0 -95 -20 -193q-46 -224 -184.5 -383t-357.5 -268
+q-214 -108 -438 -108q-148 0 -286 47q-15 5 -88 42t-96 37q-16 0 -39.5 -32t-45 -70t-52.5 -70t-60 -32q-43 0 -63.5 17.5t-45.5 59.5q-2 4 -6 11t-5.5 10t-3 9.5t-1.5 13.5q0 35 31 73.5t68 65.5t68 56t31 48q0 4 -14 38t-16 44q-9 51 -9 104q0 115 43.5 220t119 184.5
+t170.5 139t204 95.5q55 18 145 25.5t179.5 9t178.5 6t163.5 24t113.5 56.5l29.5 29.5t29.5 28t27 20t36.5 16t43.5 4.5q39 0 70.5 -46t47.5 -112t24 -124t8 -96z" />
+    <glyph glyph-name="fire" unicode="&#xf06d;" horiz-adv-x="1408" 
+d="M1408 -160v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1152 896q0 -78 -24.5 -144t-64 -112.5t-87.5 -88t-96 -77.5t-87.5 -72t-64 -81.5t-24.5 -96.5q0 -96 67 -224l-4 1l1 -1
+q-90 41 -160 83t-138.5 100t-113.5 122.5t-72.5 150.5t-27.5 184q0 78 24.5 144t64 112.5t87.5 88t96 77.5t87.5 72t64 81.5t24.5 96.5q0 94 -66 224l3 -1l-1 1q90 -41 160 -83t138.5 -100t113.5 -122.5t72.5 -150.5t27.5 -184z" />
+    <glyph glyph-name="eye_open" unicode="&#xf06e;" horiz-adv-x="1792" 
+d="M1664 576q-152 236 -381 353q61 -104 61 -225q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 121 61 225q-229 -117 -381 -353q133 -205 333.5 -326.5t434.5 -121.5t434.5 121.5t333.5 326.5zM944 960q0 20 -14 34t-34 14q-125 0 -214.5 -89.5
+t-89.5 -214.5q0 -20 14 -34t34 -14t34 14t14 34q0 86 61 147t147 61q20 0 34 14t14 34zM1792 576q0 -34 -20 -69q-140 -230 -376.5 -368.5t-499.5 -138.5t-499.5 139t-376.5 368q-20 35 -20 69t20 69q140 229 376.5 368t499.5 139t499.5 -139t376.5 -368q20 -35 20 -69z" />
+    <glyph glyph-name="eye_close" unicode="&#xf070;" horiz-adv-x="1792" 
+d="M555 201l78 141q-87 63 -136 159t-49 203q0 121 61 225q-229 -117 -381 -353q167 -258 427 -375zM944 960q0 20 -14 34t-34 14q-125 0 -214.5 -89.5t-89.5 -214.5q0 -20 14 -34t34 -14t34 14t14 34q0 86 61 147t147 61q20 0 34 14t14 34zM1307 1151q0 -7 -1 -9
+q-106 -189 -316 -567t-315 -566l-49 -89q-10 -16 -28 -16q-12 0 -134 70q-16 10 -16 28q0 12 44 87q-143 65 -263.5 173t-208.5 245q-20 31 -20 69t20 69q153 235 380 371t496 136q89 0 180 -17l54 97q10 16 28 16q5 0 18 -6t31 -15.5t33 -18.5t31.5 -18.5t19.5 -11.5
+q16 -10 16 -27zM1344 704q0 -139 -79 -253.5t-209 -164.5l280 502q8 -45 8 -84zM1792 576q0 -35 -20 -69q-39 -64 -109 -145q-150 -172 -347.5 -267t-419.5 -95l74 132q212 18 392.5 137t301.5 307q-115 179 -282 294l63 112q95 -64 182.5 -153t144.5 -184q20 -34 20 -69z
+" />
+    <glyph glyph-name="warning_sign" unicode="&#xf071;" horiz-adv-x="1792" 
+d="M1024 161v190q0 14 -9.5 23.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -23.5v-190q0 -14 9.5 -23.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 23.5zM1022 535l18 459q0 12 -10 19q-13 11 -24 11h-220q-11 0 -24 -11q-10 -7 -10 -21l17 -457q0 -10 10 -16.5t24 -6.5h185
+q14 0 23.5 6.5t10.5 16.5zM1008 1469l768 -1408q35 -63 -2 -126q-17 -29 -46.5 -46t-63.5 -17h-1536q-34 0 -63.5 17t-46.5 46q-37 63 -2 126l768 1408q17 31 47 49t65 18t65 -18t47 -49z" />
+    <glyph glyph-name="plane" unicode="&#xf072;" horiz-adv-x="1408" 
+d="M1376 1376q44 -52 12 -148t-108 -172l-161 -161l160 -696q5 -19 -12 -33l-128 -96q-7 -6 -19 -6q-4 0 -7 1q-15 3 -21 16l-279 508l-259 -259l53 -194q5 -17 -8 -31l-96 -96q-9 -9 -23 -9h-2q-15 2 -24 13l-189 252l-252 189q-11 7 -13 23q-1 13 9 25l96 97q9 9 23 9
+q6 0 8 -1l194 -53l259 259l-508 279q-14 8 -17 24q-2 16 9 27l128 128q14 13 30 8l665 -159l160 160q76 76 172 108t148 -12z" />
+    <glyph glyph-name="calendar" unicode="&#xf073;" horiz-adv-x="1664" 
+d="M128 -128h288v288h-288v-288zM480 -128h320v288h-320v-288zM128 224h288v320h-288v-320zM480 224h320v320h-320v-320zM128 608h288v288h-288v-288zM864 -128h320v288h-320v-288zM480 608h320v288h-320v-288zM1248 -128h288v288h-288v-288zM864 224h320v320h-320v-320z
+M512 1088v288q0 13 -9.5 22.5t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-288q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1248 224h288v320h-288v-320zM864 608h320v288h-320v-288zM1248 608h288v288h-288v-288zM1280 1088v288q0 13 -9.5 22.5t-22.5 9.5h-64
+q-13 0 -22.5 -9.5t-9.5 -22.5v-288q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1664 1152v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47
+h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" />
+    <glyph glyph-name="random" unicode="&#xf074;" horiz-adv-x="1792" 
+d="M666 1055q-60 -92 -137 -273q-22 45 -37 72.5t-40.5 63.5t-51 56.5t-63 35t-81.5 14.5h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224q250 0 410 -225zM1792 256q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v192q-32 0 -85 -0.5t-81 -1t-73 1
+t-71 5t-64 10.5t-63 18.5t-58 28.5t-59 40t-55 53.5t-56 69.5q59 93 136 273q22 -45 37 -72.5t40.5 -63.5t51 -56.5t63 -35t81.5 -14.5h256v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23zM1792 1152q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5
+v192h-256q-48 0 -87 -15t-69 -45t-51 -61.5t-45 -77.5q-32 -62 -78 -171q-29 -66 -49.5 -111t-54 -105t-64 -100t-74 -83t-90 -68.5t-106.5 -42t-128 -16.5h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224q48 0 87 15t69 45t51 61.5t45 77.5q32 62 78 171q29 66 49.5 111
+t54 105t64 100t74 83t90 68.5t106.5 42t128 16.5h256v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23z" />
+    <glyph glyph-name="comment" unicode="&#xf075;" horiz-adv-x="1792" 
+d="M1792 640q0 -174 -120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22q-17 -2 -30.5 9t-17.5 29v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5t34.5 38t31 39.5t32.5 51t27 59t26 76q-157 89 -247.5 220t-90.5 281
+q0 130 71 248.5t191 204.5t286 136.5t348 50.5q244 0 450 -85.5t326 -233t120 -321.5z" />
+    <glyph glyph-name="magnet" unicode="&#xf076;" 
+d="M1536 704v-128q0 -201 -98.5 -362t-274 -251.5t-395.5 -90.5t-395.5 90.5t-274 251.5t-98.5 362v128q0 26 19 45t45 19h384q26 0 45 -19t19 -45v-128q0 -52 23.5 -90t53.5 -57t71 -30t64 -13t44 -2t44 2t64 13t71 30t53.5 57t23.5 90v128q0 26 19 45t45 19h384
+q26 0 45 -19t19 -45zM512 1344v-384q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h384q26 0 45 -19t19 -45zM1536 1344v-384q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h384q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="chevron_up" unicode="&#xf077;" horiz-adv-x="1792" 
+d="M1683 205l-166 -165q-19 -19 -45 -19t-45 19l-531 531l-531 -531q-19 -19 -45 -19t-45 19l-166 165q-19 19 -19 45.5t19 45.5l742 741q19 19 45 19t45 -19l742 -741q19 -19 19 -45.5t-19 -45.5z" />
+    <glyph glyph-name="chevron_down" unicode="&#xf078;" horiz-adv-x="1792" 
+d="M1683 728l-742 -741q-19 -19 -45 -19t-45 19l-742 741q-19 19 -19 45.5t19 45.5l166 165q19 19 45 19t45 -19l531 -531l531 531q19 19 45 19t45 -19l166 -165q19 -19 19 -45.5t-19 -45.5z" />
+    <glyph glyph-name="retweet" unicode="&#xf079;" horiz-adv-x="1920" 
+d="M1280 32q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-8 0 -13.5 2t-9 7t-5.5 8t-3 11.5t-1 11.5v13v11v160v416h-192q-26 0 -45 19t-19 45q0 24 15 41l320 384q19 22 49 22t49 -22l320 -384q15 -17 15 -41q0 -26 -19 -45t-45 -19h-192v-384h576q16 0 25 -11l160 -192q7 -10 7 -21
+zM1920 448q0 -24 -15 -41l-320 -384q-20 -23 -49 -23t-49 23l-320 384q-15 17 -15 41q0 26 19 45t45 19h192v384h-576q-16 0 -25 12l-160 192q-7 9 -7 20q0 13 9.5 22.5t22.5 9.5h960q8 0 13.5 -2t9 -7t5.5 -8t3 -11.5t1 -11.5v-13v-11v-160v-416h192q26 0 45 -19t19 -45z
+" />
+    <glyph glyph-name="shopping_cart" unicode="&#xf07a;" horiz-adv-x="1664" 
+d="M640 0q0 -52 -38 -90t-90 -38t-90 38t-38 90t38 90t90 38t90 -38t38 -90zM1536 0q0 -52 -38 -90t-90 -38t-90 38t-38 90t38 90t90 38t90 -38t38 -90zM1664 1088v-512q0 -24 -16.5 -42.5t-40.5 -21.5l-1044 -122q13 -60 13 -70q0 -16 -24 -64h920q26 0 45 -19t19 -45
+t-19 -45t-45 -19h-1024q-26 0 -45 19t-19 45q0 11 8 31.5t16 36t21.5 40t15.5 29.5l-177 823h-204q-26 0 -45 19t-19 45t19 45t45 19h256q16 0 28.5 -6.5t19.5 -15.5t13 -24.5t8 -26t5.5 -29.5t4.5 -26h1201q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="folder_close" unicode="&#xf07b;" horiz-adv-x="1664" 
+d="M1664 928v-704q0 -92 -66 -158t-158 -66h-1216q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h672q92 0 158 -66t66 -158z" />
+    <glyph glyph-name="folder_open" unicode="&#xf07c;" horiz-adv-x="1920" 
+d="M1879 584q0 -31 -31 -66l-336 -396q-43 -51 -120.5 -86.5t-143.5 -35.5h-1088q-34 0 -60.5 13t-26.5 43q0 31 31 66l336 396q43 51 120.5 86.5t143.5 35.5h1088q34 0 60.5 -13t26.5 -43zM1536 928v-160h-832q-94 0 -197 -47.5t-164 -119.5l-337 -396l-5 -6q0 4 -0.5 12.5
+t-0.5 12.5v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h544q92 0 158 -66t66 -158z" />
+    <glyph glyph-name="resize_vertical" unicode="&#xf07d;" horiz-adv-x="768" 
+d="M704 1216q0 -26 -19 -45t-45 -19h-128v-1024h128q26 0 45 -19t19 -45t-19 -45l-256 -256q-19 -19 -45 -19t-45 19l-256 256q-19 19 -19 45t19 45t45 19h128v1024h-128q-26 0 -45 19t-19 45t19 45l256 256q19 19 45 19t45 -19l256 -256q19 -19 19 -45z" />
+    <glyph glyph-name="resize_horizontal" unicode="&#xf07e;" horiz-adv-x="1792" 
+d="M1792 640q0 -26 -19 -45l-256 -256q-19 -19 -45 -19t-45 19t-19 45v128h-1024v-128q0 -26 -19 -45t-45 -19t-45 19l-256 256q-19 19 -19 45t19 45l256 256q19 19 45 19t45 -19t19 -45v-128h1024v128q0 26 19 45t45 19t45 -19l256 -256q19 -19 19 -45z" />
+    <glyph glyph-name="bar_chart" unicode="&#xf080;" horiz-adv-x="2048" 
+d="M640 640v-512h-256v512h256zM1024 1152v-1024h-256v1024h256zM2048 0v-128h-2048v1536h128v-1408h1920zM1408 896v-768h-256v768h256zM1792 1280v-1152h-256v1152h256z" />
+    <glyph glyph-name="twitter_sign" unicode="&#xf081;" 
+d="M1280 926q-56 -25 -121 -34q68 40 93 117q-65 -38 -134 -51q-61 66 -153 66q-87 0 -148.5 -61.5t-61.5 -148.5q0 -29 5 -48q-129 7 -242 65t-192 155q-29 -50 -29 -106q0 -114 91 -175q-47 1 -100 26v-2q0 -75 50 -133.5t123 -72.5q-29 -8 -51 -8q-13 0 -39 4
+q21 -63 74.5 -104t121.5 -42q-116 -90 -261 -90q-26 0 -50 3q148 -94 322 -94q112 0 210 35.5t168 95t120.5 137t75 162t24.5 168.5q0 18 -1 27q63 45 105 109zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5
+t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="facebook_sign" unicode="&#xf082;" 
+d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-188v595h199l30 232h-229v148q0 56 23.5 84t91.5 28l122 1v207q-63 9 -178 9q-136 0 -217.5 -80t-81.5 -226v-171h-200v-232h200v-595h-532q-119 0 -203.5 84.5t-84.5 203.5v960
+q0 119 84.5 203.5t203.5 84.5h960z" />
+    <glyph glyph-name="camera_retro" unicode="&#xf083;" horiz-adv-x="1792" 
+d="M928 704q0 14 -9 23t-23 9q-66 0 -113 -47t-47 -113q0 -14 9 -23t23 -9t23 9t9 23q0 40 28 68t68 28q14 0 23 9t9 23zM1152 574q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM128 0h1536v128h-1536v-128zM1280 574q0 159 -112.5 271.5
+t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5zM256 1216h384v128h-384v-128zM128 1024h1536v118v138h-828l-64 -128h-644v-128zM1792 1280v-1280q0 -53 -37.5 -90.5t-90.5 -37.5h-1536q-53 0 -90.5 37.5t-37.5 90.5v1280
+q0 53 37.5 90.5t90.5 37.5h1536q53 0 90.5 -37.5t37.5 -90.5z" />
+    <glyph glyph-name="key" unicode="&#xf084;" horiz-adv-x="1792" 
+d="M832 1024q0 80 -56 136t-136 56t-136 -56t-56 -136q0 -42 19 -83q-41 19 -83 19q-80 0 -136 -56t-56 -136t56 -136t136 -56t136 56t56 136q0 42 -19 83q41 -19 83 -19q80 0 136 56t56 136zM1683 320q0 -17 -49 -66t-66 -49q-9 0 -28.5 16t-36.5 33t-38.5 40t-24.5 26
+l-96 -96l220 -220q28 -28 28 -68q0 -42 -39 -81t-81 -39q-40 0 -68 28l-671 671q-176 -131 -365 -131q-163 0 -265.5 102.5t-102.5 265.5q0 160 95 313t248 248t313 95q163 0 265.5 -102.5t102.5 -265.5q0 -189 -131 -365l355 -355l96 96q-3 3 -26 24.5t-40 38.5t-33 36.5
+t-16 28.5q0 17 49 66t66 49q13 0 23 -10q6 -6 46 -44.5t82 -79.5t86.5 -86t73 -78t28.5 -41z" />
+    <glyph glyph-name="cogs" unicode="&#xf085;" horiz-adv-x="1920" 
+d="M896 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1664 128q0 52 -38 90t-90 38t-90 -38t-38 -90q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1664 1152q0 52 -38 90t-90 38t-90 -38t-38 -90q0 -53 37.5 -90.5t90.5 -37.5
+t90.5 37.5t37.5 90.5zM1280 731v-185q0 -10 -7 -19.5t-16 -10.5l-155 -24q-11 -35 -32 -76q34 -48 90 -115q7 -11 7 -20q0 -12 -7 -19q-23 -30 -82.5 -89.5t-78.5 -59.5q-11 0 -21 7l-115 90q-37 -19 -77 -31q-11 -108 -23 -155q-7 -24 -30 -24h-186q-11 0 -20 7.5t-10 17.5
+l-23 153q-34 10 -75 31l-118 -89q-7 -7 -20 -7q-11 0 -21 8q-144 133 -144 160q0 9 7 19q10 14 41 53t47 61q-23 44 -35 82l-152 24q-10 1 -17 9.5t-7 19.5v185q0 10 7 19.5t16 10.5l155 24q11 35 32 76q-34 48 -90 115q-7 11 -7 20q0 12 7 20q22 30 82 89t79 59q11 0 21 -7
+l115 -90q34 18 77 32q11 108 23 154q7 24 30 24h186q11 0 20 -7.5t10 -17.5l23 -153q34 -10 75 -31l118 89q8 7 20 7q11 0 21 -8q144 -133 144 -160q0 -8 -7 -19q-12 -16 -42 -54t-45 -60q23 -48 34 -82l152 -23q10 -2 17 -10.5t7 -19.5zM1920 198v-140q0 -16 -149 -31
+q-12 -27 -30 -52q51 -113 51 -138q0 -4 -4 -7q-122 -71 -124 -71q-8 0 -46 47t-52 68q-20 -2 -30 -2t-30 2q-14 -21 -52 -68t-46 -47q-2 0 -124 71q-4 3 -4 7q0 25 51 138q-18 25 -30 52q-149 15 -149 31v140q0 16 149 31q13 29 30 52q-51 113 -51 138q0 4 4 7q4 2 35 20
+t59 34t30 16q8 0 46 -46.5t52 -67.5q20 2 30 2t30 -2q51 71 92 112l6 2q4 0 124 -70q4 -3 4 -7q0 -25 -51 -138q17 -23 30 -52q149 -15 149 -31zM1920 1222v-140q0 -16 -149 -31q-12 -27 -30 -52q51 -113 51 -138q0 -4 -4 -7q-122 -71 -124 -71q-8 0 -46 47t-52 68
+q-20 -2 -30 -2t-30 2q-14 -21 -52 -68t-46 -47q-2 0 -124 71q-4 3 -4 7q0 25 51 138q-18 25 -30 52q-149 15 -149 31v140q0 16 149 31q13 29 30 52q-51 113 -51 138q0 4 4 7q4 2 35 20t59 34t30 16q8 0 46 -46.5t52 -67.5q20 2 30 2t30 -2q51 71 92 112l6 2q4 0 124 -70
+q4 -3 4 -7q0 -25 -51 -138q17 -23 30 -52q149 -15 149 -31z" />
+    <glyph glyph-name="comments" unicode="&#xf086;" horiz-adv-x="1792" 
+d="M1408 768q0 -139 -94 -257t-256.5 -186.5t-353.5 -68.5q-86 0 -176 16q-124 -88 -278 -128q-36 -9 -86 -16h-3q-11 0 -20.5 8t-11.5 21q-1 3 -1 6.5t0.5 6.5t2 6l2.5 5t3.5 5.5t4 5t4.5 5t4 4.5q5 6 23 25t26 29.5t22.5 29t25 38.5t20.5 44q-124 72 -195 177t-71 224
+q0 139 94 257t256.5 186.5t353.5 68.5t353.5 -68.5t256.5 -186.5t94 -257zM1792 512q0 -120 -71 -224.5t-195 -176.5q10 -24 20.5 -44t25 -38.5t22.5 -29t26 -29.5t23 -25q1 -1 4 -4.5t4.5 -5t4 -5t3.5 -5.5l2.5 -5t2 -6t0.5 -6.5t-1 -6.5q-3 -14 -13 -22t-22 -7
+q-50 7 -86 16q-154 40 -278 128q-90 -16 -176 -16q-271 0 -472 132q58 -4 88 -4q161 0 309 45t264 129q125 92 192 212t67 254q0 77 -23 152q129 -71 204 -178t75 -230z" />
+    <glyph glyph-name="thumbs_up_alt" unicode="&#xf087;" 
+d="M256 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 768q0 51 -39 89.5t-89 38.5h-352q0 58 48 159.5t48 160.5q0 98 -32 145t-128 47q-26 -26 -38 -85t-30.5 -125.5t-59.5 -109.5q-22 -23 -77 -91q-4 -5 -23 -30t-31.5 -41t-34.5 -42.5
+t-40 -44t-38.5 -35.5t-40 -27t-35.5 -9h-32v-640h32q13 0 31.5 -3t33 -6.5t38 -11t35 -11.5t35.5 -12.5t29 -10.5q211 -73 342 -73h121q192 0 192 167q0 26 -5 56q30 16 47.5 52.5t17.5 73.5t-18 69q53 50 53 119q0 25 -10 55.5t-25 47.5q32 1 53.5 47t21.5 81zM1536 769
+q0 -89 -49 -163q9 -33 9 -69q0 -77 -38 -144q3 -21 3 -43q0 -101 -60 -178q1 -139 -85 -219.5t-227 -80.5h-36h-93q-96 0 -189.5 22.5t-216.5 65.5q-116 40 -138 40h-288q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5h274q36 24 137 155q58 75 107 128
+q24 25 35.5 85.5t30.5 126.5t62 108q39 37 90 37q84 0 151 -32.5t102 -101.5t35 -186q0 -93 -48 -192h176q104 0 180 -76t76 -179z" />
+    <glyph glyph-name="thumbs_down_alt" unicode="&#xf088;" 
+d="M256 1088q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 512q0 35 -21.5 81t-53.5 47q15 17 25 47.5t10 55.5q0 69 -53 119q18 31 18 69q0 37 -17.5 73.5t-47.5 52.5q5 30 5 56q0 85 -49 126t-136 41h-128q-131 0 -342 -73q-5 -2 -29 -10.5
+t-35.5 -12.5t-35 -11.5t-38 -11t-33 -6.5t-31.5 -3h-32v-640h32q16 0 35.5 -9t40 -27t38.5 -35.5t40 -44t34.5 -42.5t31.5 -41t23 -30q55 -68 77 -91q41 -43 59.5 -109.5t30.5 -125.5t38 -85q96 0 128 47t32 145q0 59 -48 160.5t-48 159.5h352q50 0 89 38.5t39 89.5z
+M1536 511q0 -103 -76 -179t-180 -76h-176q48 -99 48 -192q0 -118 -35 -186q-35 -69 -102 -101.5t-151 -32.5q-51 0 -90 37q-34 33 -54 82t-25.5 90.5t-17.5 84.5t-31 64q-48 50 -107 127q-101 131 -137 155h-274q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5
+h288q22 0 138 40q128 44 223 66t200 22h112q140 0 226.5 -79t85.5 -216v-5q60 -77 60 -178q0 -22 -3 -43q38 -67 38 -144q0 -36 -9 -69q49 -73 49 -163z" />
+    <glyph glyph-name="star_half" unicode="&#xf089;" horiz-adv-x="896" 
+d="M832 1504v-1339l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41z" />
+    <glyph glyph-name="heart_empty" unicode="&#xf08a;" horiz-adv-x="1792" 
+d="M1664 940q0 81 -21.5 143t-55 98.5t-81.5 59.5t-94 31t-98 8t-112 -25.5t-110.5 -64t-86.5 -72t-60 -61.5q-18 -22 -49 -22t-49 22q-24 28 -60 61.5t-86.5 72t-110.5 64t-112 25.5t-98 -8t-94 -31t-81.5 -59.5t-55 -98.5t-21.5 -143q0 -168 187 -355l581 -560l580 559
+q188 188 188 356zM1792 940q0 -221 -229 -450l-623 -600q-18 -18 -44 -18t-44 18l-624 602q-10 8 -27.5 26t-55.5 65.5t-68 97.5t-53.5 121t-23.5 138q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5
+q224 0 351 -124t127 -344z" />
+    <glyph glyph-name="signout" unicode="&#xf08b;" horiz-adv-x="1664" 
+d="M640 96q0 -4 1 -20t0.5 -26.5t-3 -23.5t-10 -19.5t-20.5 -6.5h-320q-119 0 -203.5 84.5t-84.5 203.5v704q0 119 84.5 203.5t203.5 84.5h320q13 0 22.5 -9.5t9.5 -22.5q0 -4 1 -20t0.5 -26.5t-3 -23.5t-10 -19.5t-20.5 -6.5h-320q-66 0 -113 -47t-47 -113v-704
+q0 -66 47 -113t113 -47h288h11h13t11.5 -1t11.5 -3t8 -5.5t7 -9t2 -13.5zM1568 640q0 -26 -19 -45l-544 -544q-19 -19 -45 -19t-45 19t-19 45v288h-448q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h448v288q0 26 19 45t45 19t45 -19l544 -544q19 -19 19 -45z" />
+    <glyph glyph-name="linkedin_sign" unicode="&#xf08c;" 
+d="M237 122h231v694h-231v-694zM483 1030q-1 52 -36 86t-93 34t-94.5 -34t-36.5 -86q0 -51 35.5 -85.5t92.5 -34.5h1q59 0 95 34.5t36 85.5zM1068 122h231v398q0 154 -73 233t-193 79q-136 0 -209 -117h2v101h-231q3 -66 0 -694h231v388q0 38 7 56q15 35 45 59.5t74 24.5
+q116 0 116 -157v-371zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="pushpin" unicode="&#xf08d;" horiz-adv-x="1152" 
+d="M480 672v448q0 14 -9 23t-23 9t-23 -9t-9 -23v-448q0 -14 9 -23t23 -9t23 9t9 23zM1152 320q0 -26 -19 -45t-45 -19h-429l-51 -483q-2 -12 -10.5 -20.5t-20.5 -8.5h-1q-27 0 -32 27l-76 485h-404q-26 0 -45 19t-19 45q0 123 78.5 221.5t177.5 98.5v512q-52 0 -90 38
+t-38 90t38 90t90 38h640q52 0 90 -38t38 -90t-38 -90t-90 -38v-512q99 0 177.5 -98.5t78.5 -221.5z" />
+    <glyph glyph-name="external_link" unicode="&#xf08e;" horiz-adv-x="1792" 
+d="M1408 608v-320q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h704q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v320
+q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1792 1472v-512q0 -26 -19 -45t-45 -19t-45 19l-176 176l-652 -652q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l652 652l-176 176q-19 19 -19 45t19 45t45 19h512q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="signin" unicode="&#xf090;" 
+d="M1184 640q0 -26 -19 -45l-544 -544q-19 -19 -45 -19t-45 19t-19 45v288h-448q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h448v288q0 26 19 45t45 19t45 -19l544 -544q19 -19 19 -45zM1536 992v-704q0 -119 -84.5 -203.5t-203.5 -84.5h-320q-13 0 -22.5 9.5t-9.5 22.5
+q0 4 -1 20t-0.5 26.5t3 23.5t10 19.5t20.5 6.5h320q66 0 113 47t47 113v704q0 66 -47 113t-113 47h-288h-11h-13t-11.5 1t-11.5 3t-8 5.5t-7 9t-2 13.5q0 4 -1 20t-0.5 26.5t3 23.5t10 19.5t20.5 6.5h320q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="trophy" unicode="&#xf091;" horiz-adv-x="1664" 
+d="M458 653q-74 162 -74 371h-256v-96q0 -78 94.5 -162t235.5 -113zM1536 928v96h-256q0 -209 -74 -371q141 29 235.5 113t94.5 162zM1664 1056v-128q0 -71 -41.5 -143t-112 -130t-173 -97.5t-215.5 -44.5q-42 -54 -95 -95q-38 -34 -52.5 -72.5t-14.5 -89.5q0 -54 30.5 -91
+t97.5 -37q75 0 133.5 -45.5t58.5 -114.5v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v64q0 69 58.5 114.5t133.5 45.5q67 0 97.5 37t30.5 91q0 51 -14.5 89.5t-52.5 72.5q-53 41 -95 95q-113 5 -215.5 44.5t-173 97.5t-112 130t-41.5 143v128q0 40 28 68t68 28h288v96
+q0 66 47 113t113 47h576q66 0 113 -47t47 -113v-96h288q40 0 68 -28t28 -68z" />
+    <glyph glyph-name="github_sign" unicode="&#xf092;" 
+d="M519 336q4 6 -3 13q-9 7 -14 2q-4 -6 3 -13q9 -7 14 -2zM491 377q-5 7 -12 4q-6 -4 0 -12q7 -8 12 -5q6 4 0 13zM450 417q2 4 -5 8q-7 2 -8 -2q-3 -5 4 -8q8 -2 9 2zM471 394q2 1 1.5 4.5t-3.5 5.5q-6 7 -10 3t1 -11q6 -6 11 -2zM557 319q2 7 -9 11q-9 3 -13 -4
+q-2 -7 9 -11q9 -3 13 4zM599 316q0 8 -12 8q-10 0 -10 -8t11 -8t11 8zM638 323q-2 7 -13 5t-9 -9q2 -8 12 -6t10 10zM1280 640q0 212 -150 362t-362 150t-362 -150t-150 -362q0 -167 98 -300.5t252 -185.5q18 -3 26.5 5t8.5 20q0 52 -1 95q-6 -1 -15.5 -2.5t-35.5 -2t-48 4
+t-43.5 20t-29.5 41.5q-23 59 -57 74q-2 1 -4.5 3.5l-8 8t-7 9.5t4 7.5t19.5 3.5q6 0 15 -2t30 -15.5t33 -35.5q16 -28 37.5 -42t43.5 -14t38 3.5t30 9.5q7 47 33 69q-49 6 -86 18.5t-73 39t-55.5 76t-19.5 119.5q0 79 53 137q-24 62 5 136q19 6 54.5 -7.5t60.5 -29.5l26 -16
+q58 17 128 17t128 -17q11 7 28.5 18t55.5 26t57 9q29 -74 5 -136q53 -58 53 -137q0 -57 -14 -100.5t-35.5 -70t-53.5 -44.5t-62.5 -26t-68.5 -12q35 -31 35 -95q0 -40 -0.5 -89t-0.5 -51q0 -12 8.5 -20t26.5 -5q154 52 252 185.5t98 300.5zM1536 1120v-960
+q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="upload_alt" unicode="&#xf093;" horiz-adv-x="1664" 
+d="M1280 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 288v-320q0 -40 -28 -68t-68 -28h-1472q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h427q21 -56 70.5 -92
+t110.5 -36h256q61 0 110.5 36t70.5 92h427q40 0 68 -28t28 -68zM1339 936q-17 -40 -59 -40h-256v-448q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v448h-256q-42 0 -59 40q-17 39 14 69l448 448q18 19 45 19t45 -19l448 -448q31 -30 14 -69z" />
+    <glyph glyph-name="lemon" unicode="&#xf094;" 
+d="M1407 710q0 44 -7 113.5t-18 96.5q-12 30 -17 44t-9 36.5t-4 48.5q0 23 5 68.5t5 67.5q0 37 -10 55q-4 1 -13 1q-19 0 -58 -4.5t-59 -4.5q-60 0 -176 24t-175 24q-43 0 -94.5 -11.5t-85 -23.5t-89.5 -34q-137 -54 -202 -103q-96 -73 -159.5 -189.5t-88 -236t-24.5 -248.5
+q0 -40 12.5 -120t12.5 -121q0 -23 -11 -66.5t-11 -65.5t12 -36.5t34 -14.5q24 0 72.5 11t73.5 11q57 0 169.5 -15.5t169.5 -15.5q181 0 284 36q129 45 235.5 152.5t166 245.5t59.5 275zM1535 712q0 -165 -70 -327.5t-196 -288t-281 -180.5q-124 -44 -326 -44
+q-57 0 -170 14.5t-169 14.5q-24 0 -72.5 -14.5t-73.5 -14.5q-73 0 -123.5 55.5t-50.5 128.5q0 24 11 68t11 67q0 40 -12.5 120.5t-12.5 121.5q0 111 18 217.5t54.5 209.5t100.5 194t150 156q78 59 232 120q194 78 316 78q60 0 175.5 -24t173.5 -24q19 0 57 5t58 5
+q81 0 118 -50.5t37 -134.5q0 -23 -5 -68t-5 -68q0 -13 2 -25t3.5 -16.5t7.5 -20.5t8 -20q16 -40 25 -118.5t9 -136.5z" />
+    <glyph glyph-name="phone" unicode="&#xf095;" horiz-adv-x="1408" 
+d="M1408 296q0 -27 -10 -70.5t-21 -68.5q-21 -50 -122 -106q-94 -51 -186 -51q-27 0 -53 3.5t-57.5 12.5t-47 14.5t-55.5 20.5t-49 18q-98 35 -175 83q-127 79 -264 216t-216 264q-48 77 -83 175q-3 9 -18 49t-20.5 55.5t-14.5 47t-12.5 57.5t-3.5 53q0 92 51 186
+q56 101 106 122q25 11 68.5 21t70.5 10q14 0 21 -3q18 -6 53 -76q11 -19 30 -54t35 -63.5t31 -53.5q3 -4 17.5 -25t21.5 -35.5t7 -28.5q0 -20 -28.5 -50t-62 -55t-62 -53t-28.5 -46q0 -9 5 -22.5t8.5 -20.5t14 -24t11.5 -19q76 -137 174 -235t235 -174q2 -1 19 -11.5t24 -14
+t20.5 -8.5t22.5 -5q18 0 46 28.5t53 62t55 62t50 28.5q14 0 28.5 -7t35.5 -21.5t25 -17.5q25 -15 53.5 -31t63.5 -35t54 -30q70 -35 76 -53q3 -7 3 -21z" />
+    <glyph glyph-name="check_empty" unicode="&#xf096;" horiz-adv-x="1408" 
+d="M1120 1280h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v832q0 66 -47 113t-113 47zM1408 1120v-832q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832
+q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="bookmark_empty" unicode="&#xf097;" horiz-adv-x="1280" 
+d="M1152 1280h-1024v-1242l423 406l89 85l89 -85l423 -406v1242zM1164 1408q23 0 44 -9q33 -13 52.5 -41t19.5 -62v-1289q0 -34 -19.5 -62t-52.5 -41q-19 -8 -44 -8q-48 0 -83 32l-441 424l-441 -424q-36 -33 -83 -33q-23 0 -44 9q-33 13 -52.5 41t-19.5 62v1289
+q0 34 19.5 62t52.5 41q21 9 44 9h1048z" />
+    <glyph glyph-name="phone_sign" unicode="&#xf098;" 
+d="M1280 343q0 11 -2 16t-18 16.5t-40.5 25t-47.5 26.5t-45.5 25t-28.5 15q-5 3 -19 13t-25 15t-21 5q-15 0 -36.5 -20.5t-39.5 -45t-38.5 -45t-33.5 -20.5q-7 0 -16.5 3.5t-15.5 6.5t-17 9.5t-14 8.5q-99 55 -170 126.5t-127 170.5q-2 3 -8.5 14t-9.5 17t-6.5 15.5
+t-3.5 16.5q0 13 20.5 33.5t45 38.5t45 39.5t20.5 36.5q0 10 -5 21t-15 25t-13 19q-3 6 -15 28.5t-25 45.5t-26.5 47.5t-25 40.5t-16.5 18t-16 2q-48 0 -101 -22q-46 -21 -80 -94.5t-34 -130.5q0 -16 2.5 -34t5 -30.5t9 -33t10 -29.5t12.5 -33t11 -30q60 -164 216.5 -320.5
+t320.5 -216.5q6 -2 30 -11t33 -12.5t29.5 -10t33 -9t30.5 -5t34 -2.5q57 0 130.5 34t94.5 80q22 53 22 101zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z
+" />
+    <glyph glyph-name="twitter" unicode="&#xf099;" horiz-adv-x="1664" 
+d="M1620 1128q-67 -98 -162 -167q1 -14 1 -42q0 -130 -38 -259.5t-115.5 -248.5t-184.5 -210.5t-258 -146t-323 -54.5q-271 0 -496 145q35 -4 78 -4q225 0 401 138q-105 2 -188 64.5t-114 159.5q33 -5 61 -5q43 0 85 11q-112 23 -185.5 111.5t-73.5 205.5v4q68 -38 146 -41
+q-66 44 -105 115t-39 154q0 88 44 163q121 -149 294.5 -238.5t371.5 -99.5q-8 38 -8 74q0 134 94.5 228.5t228.5 94.5q140 0 236 -102q109 21 205 78q-37 -115 -142 -178q93 10 186 50z" />
+    <glyph glyph-name="facebook" unicode="&#xf09a;" horiz-adv-x="1024" 
+d="M959 1524v-264h-157q-86 0 -116 -36t-30 -108v-189h293l-39 -296h-254v-759h-306v759h-255v296h255v218q0 186 104 288.5t277 102.5q147 0 228 -12z" />
+    <glyph glyph-name="github" unicode="&#xf09b;" 
+d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5q0 -251 -146.5 -451.5t-378.5 -277.5q-27 -5 -40 7t-13 30q0 3 0.5 76.5t0.5 134.5q0 97 -52 142q57 6 102.5 18t94 39t81 66.5t53 105t20.5 150.5q0 119 -79 206q37 91 -8 204q-28 9 -81 -11t-92 -44l-38 -24
+q-93 26 -192 26t-192 -26q-16 11 -42.5 27t-83.5 38.5t-85 13.5q-45 -113 -8 -204q-79 -87 -79 -206q0 -85 20.5 -150t52.5 -105t80.5 -67t94 -39t102.5 -18q-39 -36 -49 -103q-21 -10 -45 -15t-57 -5t-65.5 21.5t-55.5 62.5q-19 32 -48.5 52t-49.5 24l-20 3q-21 0 -29 -4.5
+t-5 -11.5t9 -14t13 -12l7 -5q22 -10 43.5 -38t31.5 -51l10 -23q13 -38 44 -61.5t67 -30t69.5 -7t55.5 3.5l23 4q0 -38 0.5 -88.5t0.5 -54.5q0 -18 -13 -30t-40 -7q-232 77 -378.5 277.5t-146.5 451.5q0 209 103 385.5t279.5 279.5t385.5 103zM291 305q3 7 -7 12
+q-10 3 -13 -2q-3 -7 7 -12q9 -6 13 2zM322 271q7 5 -2 16q-10 9 -16 3q-7 -5 2 -16q10 -10 16 -3zM352 226q9 7 0 19q-8 13 -17 6q-9 -5 0 -18t17 -7zM394 184q8 8 -4 19q-12 12 -20 3q-9 -8 4 -19q12 -12 20 -3zM451 159q3 11 -13 16q-15 4 -19 -7t13 -15q15 -6 19 6z
+M514 154q0 13 -17 11q-16 0 -16 -11q0 -13 17 -11q16 0 16 11zM572 164q-2 11 -18 9q-16 -3 -14 -15t18 -8t14 14z" />
+    <glyph glyph-name="unlock" unicode="&#xf09c;" horiz-adv-x="1664" 
+d="M1664 960v-256q0 -26 -19 -45t-45 -19h-64q-26 0 -45 19t-19 45v256q0 106 -75 181t-181 75t-181 -75t-75 -181v-192h96q40 0 68 -28t28 -68v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h672v192q0 185 131.5 316.5t316.5 131.5
+t316.5 -131.5t131.5 -316.5z" />
+    <glyph glyph-name="credit_card" unicode="&#xf09d;" horiz-adv-x="1920" 
+d="M1760 1408q66 0 113 -47t47 -113v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600zM160 1280q-13 0 -22.5 -9.5t-9.5 -22.5v-224h1664v224q0 13 -9.5 22.5t-22.5 9.5h-1600zM1760 0q13 0 22.5 9.5t9.5 22.5v608h-1664v-608
+q0 -13 9.5 -22.5t22.5 -9.5h1600zM256 128v128h256v-128h-256zM640 128v128h384v-128h-384z" />
+    <glyph glyph-name="rss" unicode="&#xf09e;" horiz-adv-x="1408" 
+d="M384 192q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM896 69q2 -28 -17 -48q-18 -21 -47 -21h-135q-25 0 -43 16.5t-20 41.5q-22 229 -184.5 391.5t-391.5 184.5q-25 2 -41.5 20t-16.5 43v135q0 29 21 47q17 17 43 17h5q160 -13 306 -80.5
+t259 -181.5q114 -113 181.5 -259t80.5 -306zM1408 67q2 -27 -18 -47q-18 -20 -46 -20h-143q-26 0 -44.5 17.5t-19.5 42.5q-12 215 -101 408.5t-231.5 336t-336 231.5t-408.5 102q-25 1 -42.5 19.5t-17.5 43.5v143q0 28 20 46q18 18 44 18h3q262 -13 501.5 -120t425.5 -294
+q187 -186 294 -425.5t120 -501.5z" />
+    <glyph glyph-name="hdd" unicode="&#xf0a0;" 
+d="M1040 320q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5zM1296 320q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5zM1408 160v320q0 13 -9.5 22.5t-22.5 9.5
+h-1216q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h1216q13 0 22.5 9.5t9.5 22.5zM178 640h1180l-157 482q-4 13 -16 21.5t-26 8.5h-782q-14 0 -26 -8.5t-16 -21.5zM1536 480v-320q0 -66 -47 -113t-113 -47h-1216q-66 0 -113 47t-47 113v320q0 25 16 75
+l197 606q17 53 63 86t101 33h782q55 0 101 -33t63 -86l197 -606q16 -50 16 -75z" />
+    <glyph glyph-name="bullhorn" unicode="&#xf0a1;" horiz-adv-x="1792" 
+d="M1664 896q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5v-384q0 -52 -38 -90t-90 -38q-417 347 -812 380q-58 -19 -91 -66t-31 -100.5t40 -92.5q-20 -33 -23 -65.5t6 -58t33.5 -55t48 -50t61.5 -50.5q-29 -58 -111.5 -83t-168.5 -11.5t-132 55.5q-7 23 -29.5 87.5
+t-32 94.5t-23 89t-15 101t3.5 98.5t22 110.5h-122q-66 0 -113 47t-47 113v192q0 66 47 113t113 47h480q435 0 896 384q52 0 90 -38t38 -90v-384zM1536 292v954q-394 -302 -768 -343v-270q377 -42 768 -341z" />
+    <glyph glyph-name="bell" unicode="&#xf0a2;" horiz-adv-x="1792" 
+d="M912 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM246 128h1300q-266 300 -266 832q0 51 -24 105t-69 103t-121.5 80.5t-169.5 31.5t-169.5 -31.5t-121.5 -80.5t-69 -103t-24 -105q0 -532 -266 -832z
+M1728 128q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-181 75t-75 181h-448q-52 0 -90 38t-38 90q50 42 91 88t85 119.5t74.5 158.5t50 206t19.5 260q0 152 117 282.5t307 158.5q-8 19 -8 39q0 40 28 68t68 28t68 -28t28 -68q0 -20 -8 -39q190 -28 307 -158.5
+t117 -282.5q0 -139 19.5 -260t50 -206t74.5 -158.5t85 -119.5t91 -88z" />
+    <glyph glyph-name="certificate" unicode="&#xf0a3;" 
+d="M1376 640l138 -135q30 -28 20 -70q-12 -41 -52 -51l-188 -48l53 -186q12 -41 -19 -70q-29 -31 -70 -19l-186 53l-48 -188q-10 -40 -51 -52q-12 -2 -19 -2q-31 0 -51 22l-135 138l-135 -138q-28 -30 -70 -20q-41 11 -51 52l-48 188l-186 -53q-41 -12 -70 19q-31 29 -19 70
+l53 186l-188 48q-40 10 -52 51q-10 42 20 70l138 135l-138 135q-30 28 -20 70q12 41 52 51l188 48l-53 186q-12 41 19 70q29 31 70 19l186 -53l48 188q10 41 51 51q41 12 70 -19l135 -139l135 139q29 30 70 19q41 -10 51 -51l48 -188l186 53q41 12 70 -19q31 -29 19 -70
+l-53 -186l188 -48q40 -10 52 -51q10 -42 -20 -70z" />
+    <glyph glyph-name="hand_right" unicode="&#xf0a4;" horiz-adv-x="1792" 
+d="M256 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 768q0 51 -39 89.5t-89 38.5h-576q0 20 15 48.5t33 55t33 68t15 84.5q0 67 -44.5 97.5t-115.5 30.5q-24 0 -90 -139q-24 -44 -37 -65q-40 -64 -112 -145q-71 -81 -101 -106
+q-69 -57 -140 -57h-32v-640h32q72 0 167 -32t193.5 -64t179.5 -32q189 0 189 167q0 26 -5 56q30 16 47.5 52.5t17.5 73.5t-18 69q53 50 53 119q0 25 -10 55.5t-25 47.5h331q52 0 90 38t38 90zM1792 769q0 -105 -75.5 -181t-180.5 -76h-169q-4 -62 -37 -119q3 -21 3 -43
+q0 -101 -60 -178q1 -139 -85 -219.5t-227 -80.5q-133 0 -322 69q-164 59 -223 59h-288q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5h288q10 0 21.5 4.5t23.5 14t22.5 18t24 22.5t20.5 21.5t19 21.5t14 17q65 74 100 129q13 21 33 62t37 72t40.5 63t55 49.5
+t69.5 17.5q125 0 206.5 -67t81.5 -189q0 -68 -22 -128h374q104 0 180 -76t76 -179z" />
+    <glyph glyph-name="hand_left" unicode="&#xf0a5;" horiz-adv-x="1792" 
+d="M1376 128h32v640h-32q-35 0 -67.5 12t-62.5 37t-50 46t-49 54q-8 9 -12 14q-72 81 -112 145q-14 22 -38 68q-1 3 -10.5 22.5t-18.5 36t-20 35.5t-21.5 30.5t-18.5 11.5q-71 0 -115.5 -30.5t-44.5 -97.5q0 -43 15 -84.5t33 -68t33 -55t15 -48.5h-576q-50 0 -89 -38.5
+t-39 -89.5q0 -52 38 -90t90 -38h331q-15 -17 -25 -47.5t-10 -55.5q0 -69 53 -119q-18 -32 -18 -69t17.5 -73.5t47.5 -52.5q-4 -24 -4 -56q0 -85 48.5 -126t135.5 -41q84 0 183 32t194 64t167 32zM1664 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45z
+M1792 768v-640q0 -53 -37.5 -90.5t-90.5 -37.5h-288q-59 0 -223 -59q-190 -69 -317 -69q-142 0 -230 77.5t-87 217.5l1 5q-61 76 -61 178q0 22 3 43q-33 57 -37 119h-169q-105 0 -180.5 76t-75.5 181q0 103 76 179t180 76h374q-22 60 -22 128q0 122 81.5 189t206.5 67
+q38 0 69.5 -17.5t55 -49.5t40.5 -63t37 -72t33 -62q35 -55 100 -129q2 -3 14 -17t19 -21.5t20.5 -21.5t24 -22.5t22.5 -18t23.5 -14t21.5 -4.5h288q53 0 90.5 -37.5t37.5 -90.5z" />
+    <glyph glyph-name="hand_up" unicode="&#xf0a6;" 
+d="M1280 -64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 700q0 189 -167 189q-26 0 -56 -5q-16 30 -52.5 47.5t-73.5 17.5t-69 -18q-50 53 -119 53q-25 0 -55.5 -10t-47.5 -25v331q0 52 -38 90t-90 38q-51 0 -89.5 -39t-38.5 -89v-576
+q-20 0 -48.5 15t-55 33t-68 33t-84.5 15q-67 0 -97.5 -44.5t-30.5 -115.5q0 -24 139 -90q44 -24 65 -37q64 -40 145 -112q81 -71 106 -101q57 -69 57 -140v-32h640v32q0 72 32 167t64 193.5t32 179.5zM1536 705q0 -133 -69 -322q-59 -164 -59 -223v-288q0 -53 -37.5 -90.5
+t-90.5 -37.5h-640q-53 0 -90.5 37.5t-37.5 90.5v288q0 10 -4.5 21.5t-14 23.5t-18 22.5t-22.5 24t-21.5 20.5t-21.5 19t-17 14q-74 65 -129 100q-21 13 -62 33t-72 37t-63 40.5t-49.5 55t-17.5 69.5q0 125 67 206.5t189 81.5q68 0 128 -22v374q0 104 76 180t179 76
+q105 0 181 -75.5t76 -180.5v-169q62 -4 119 -37q21 3 43 3q101 0 178 -60q139 1 219.5 -85t80.5 -227z" />
+    <glyph glyph-name="hand_down" unicode="&#xf0a7;" 
+d="M1408 576q0 84 -32 183t-64 194t-32 167v32h-640v-32q0 -35 -12 -67.5t-37 -62.5t-46 -50t-54 -49q-9 -8 -14 -12q-81 -72 -145 -112q-22 -14 -68 -38q-3 -1 -22.5 -10.5t-36 -18.5t-35.5 -20t-30.5 -21.5t-11.5 -18.5q0 -71 30.5 -115.5t97.5 -44.5q43 0 84.5 15t68 33
+t55 33t48.5 15v-576q0 -50 38.5 -89t89.5 -39q52 0 90 38t38 90v331q46 -35 103 -35q69 0 119 53q32 -18 69 -18t73.5 17.5t52.5 47.5q24 -4 56 -4q85 0 126 48.5t41 135.5zM1280 1344q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 580
+q0 -142 -77.5 -230t-217.5 -87l-5 1q-76 -61 -178 -61q-22 0 -43 3q-54 -30 -119 -37v-169q0 -105 -76 -180.5t-181 -75.5q-103 0 -179 76t-76 180v374q-54 -22 -128 -22q-121 0 -188.5 81.5t-67.5 206.5q0 38 17.5 69.5t49.5 55t63 40.5t72 37t62 33q55 35 129 100
+q3 2 17 14t21.5 19t21.5 20.5t22.5 24t18 22.5t14 23.5t4.5 21.5v288q0 53 37.5 90.5t90.5 37.5h640q53 0 90.5 -37.5t37.5 -90.5v-288q0 -59 59 -223q69 -190 69 -317z" />
+    <glyph glyph-name="circle_arrow_left" unicode="&#xf0a8;" 
+d="M1280 576v128q0 26 -19 45t-45 19h-502l189 189q19 19 19 45t-19 45l-91 91q-18 18 -45 18t-45 -18l-362 -362l-91 -91q-18 -18 -18 -45t18 -45l91 -91l362 -362q18 -18 45 -18t45 18l91 91q18 18 18 45t-18 45l-189 189h502q26 0 45 19t19 45zM1536 640
+q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="circle_arrow_right" unicode="&#xf0a9;" 
+d="M1285 640q0 27 -18 45l-91 91l-362 362q-18 18 -45 18t-45 -18l-91 -91q-18 -18 -18 -45t18 -45l189 -189h-502q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h502l-189 -189q-19 -19 -19 -45t19 -45l91 -91q18 -18 45 -18t45 18l362 362l91 91q18 18 18 45zM1536 640
+q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="circle_arrow_up" unicode="&#xf0aa;" 
+d="M1284 641q0 27 -18 45l-362 362l-91 91q-18 18 -45 18t-45 -18l-91 -91l-362 -362q-18 -18 -18 -45t18 -45l91 -91q18 -18 45 -18t45 18l189 189v-502q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v502l189 -189q19 -19 45 -19t45 19l91 91q18 18 18 45zM1536 640
+q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="circle_arrow_down" unicode="&#xf0ab;" 
+d="M1284 639q0 27 -18 45l-91 91q-18 18 -45 18t-45 -18l-189 -189v502q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-502l-189 189q-19 19 -45 19t-45 -19l-91 -91q-18 -18 -18 -45t18 -45l362 -362l91 -91q18 -18 45 -18t45 18l91 91l362 362q18 18 18 45zM1536 640
+q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="globe" unicode="&#xf0ac;" 
+d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM1042 887q-2 -1 -9.5 -9.5t-13.5 -9.5q2 0 4.5 5t5 11t3.5 7q6 7 22 15q14 6 52 12q34 8 51 -11
+q-2 2 9.5 13t14.5 12q3 2 15 4.5t15 7.5l2 22q-12 -1 -17.5 7t-6.5 21q0 -2 -6 -8q0 7 -4.5 8t-11.5 -1t-9 -1q-10 3 -15 7.5t-8 16.5t-4 15q-2 5 -9.5 11t-9.5 10q-1 2 -2.5 5.5t-3 6.5t-4 5.5t-5.5 2.5t-7 -5t-7.5 -10t-4.5 -5q-3 2 -6 1.5t-4.5 -1t-4.5 -3t-5 -3.5
+q-3 -2 -8.5 -3t-8.5 -2q15 5 -1 11q-10 4 -16 3q9 4 7.5 12t-8.5 14h5q-1 4 -8.5 8.5t-17.5 8.5t-13 6q-8 5 -34 9.5t-33 0.5q-5 -6 -4.5 -10.5t4 -14t3.5 -12.5q1 -6 -5.5 -13t-6.5 -12q0 -7 14 -15.5t10 -21.5q-3 -8 -16 -16t-16 -12q-5 -8 -1.5 -18.5t10.5 -16.5
+q2 -2 1.5 -4t-3.5 -4.5t-5.5 -4t-6.5 -3.5l-3 -2q-11 -5 -20.5 6t-13.5 26q-7 25 -16 30q-23 8 -29 -1q-5 13 -41 26q-25 9 -58 4q6 1 0 15q-7 15 -19 12q3 6 4 17.5t1 13.5q3 13 12 23q1 1 7 8.5t9.5 13.5t0.5 6q35 -4 50 11q5 5 11.5 17t10.5 17q9 6 14 5.5t14.5 -5.5
+t14.5 -5q14 -1 15.5 11t-7.5 20q12 -1 3 17q-4 7 -8 9q-12 4 -27 -5q-8 -4 2 -8q-1 1 -9.5 -10.5t-16.5 -17.5t-16 5q-1 1 -5.5 13.5t-9.5 13.5q-8 0 -16 -15q3 8 -11 15t-24 8q19 12 -8 27q-7 4 -20.5 5t-19.5 -4q-5 -7 -5.5 -11.5t5 -8t10.5 -5.5t11.5 -4t8.5 -3
+q14 -10 8 -14q-2 -1 -8.5 -3.5t-11.5 -4.5t-6 -4q-3 -4 0 -14t-2 -14q-5 5 -9 17.5t-7 16.5q7 -9 -25 -6l-10 1q-4 0 -16 -2t-20.5 -1t-13.5 8q-4 8 0 20q1 4 4 2q-4 3 -11 9.5t-10 8.5q-46 -15 -94 -41q6 -1 12 1q5 2 13 6.5t10 5.5q34 14 42 7l5 5q14 -16 20 -25
+q-7 4 -30 1q-20 -6 -22 -12q7 -12 5 -18q-4 3 -11.5 10t-14.5 11t-15 5q-16 0 -22 -1q-146 -80 -235 -222q7 -7 12 -8q4 -1 5 -9t2.5 -11t11.5 3q9 -8 3 -19q1 1 44 -27q19 -17 21 -21q3 -11 -10 -18q-1 2 -9 9t-9 4q-3 -5 0.5 -18.5t10.5 -12.5q-7 0 -9.5 -16t-2.5 -35.5
+t-1 -23.5l2 -1q-3 -12 5.5 -34.5t21.5 -19.5q-13 -3 20 -43q6 -8 8 -9q3 -2 12 -7.5t15 -10t10 -10.5q4 -5 10 -22.5t14 -23.5q-2 -6 9.5 -20t10.5 -23q-1 0 -2.5 -1t-2.5 -1q3 -7 15.5 -14t15.5 -13q1 -3 2 -10t3 -11t8 -2q2 20 -24 62q-15 25 -17 29q-3 5 -5.5 15.5
+t-4.5 14.5q2 0 6 -1.5t8.5 -3.5t7.5 -4t2 -3q-3 -7 2 -17.5t12 -18.5t17 -19t12 -13q6 -6 14 -19.5t0 -13.5q9 0 20 -10.5t17 -19.5q5 -8 8 -26t5 -24q2 -7 8.5 -13.5t12.5 -9.5l16 -8t13 -7q5 -2 18.5 -10.5t21.5 -11.5q10 -4 16 -4t14.5 2.5t13.5 3.5q15 2 29 -15t21 -21
+q36 -19 55 -11q-2 -1 0.5 -7.5t8 -15.5t9 -14.5t5.5 -8.5q5 -6 18 -15t18 -15q6 4 7 9q-3 -8 7 -20t18 -10q14 3 14 32q-31 -15 -49 18q0 1 -2.5 5.5t-4 8.5t-2.5 8.5t0 7.5t5 3q9 0 10 3.5t-2 12.5t-4 13q-1 8 -11 20t-12 15q-5 -9 -16 -8t-16 9q0 -1 -1.5 -5.5t-1.5 -6.5
+q-13 0 -15 1q1 3 2.5 17.5t3.5 22.5q1 4 5.5 12t7.5 14.5t4 12.5t-4.5 9.5t-17.5 2.5q-19 -1 -26 -20q-1 -3 -3 -10.5t-5 -11.5t-9 -7q-7 -3 -24 -2t-24 5q-13 8 -22.5 29t-9.5 37q0 10 2.5 26.5t3 25t-5.5 24.5q3 2 9 9.5t10 10.5q2 1 4.5 1.5t4.5 0t4 1.5t3 6q-1 1 -4 3
+q-3 3 -4 3q7 -3 28.5 1.5t27.5 -1.5q15 -11 22 2q0 1 -2.5 9.5t-0.5 13.5q5 -27 29 -9q3 -3 15.5 -5t17.5 -5q3 -2 7 -5.5t5.5 -4.5t5 0.5t8.5 6.5q10 -14 12 -24q11 -40 19 -44q7 -3 11 -2t4.5 9.5t0 14t-1.5 12.5l-1 8v18l-1 8q-15 3 -18.5 12t1.5 18.5t15 18.5q1 1 8 3.5
+t15.5 6.5t12.5 8q21 19 15 35q7 0 11 9q-1 0 -5 3t-7.5 5t-4.5 2q9 5 2 16q5 3 7.5 11t7.5 10q9 -12 21 -2q8 8 1 16q5 7 20.5 10.5t18.5 9.5q7 -2 8 2t1 12t3 12q4 5 15 9t13 5l17 11q3 4 0 4q18 -2 31 11q10 11 -6 20q3 6 -3 9.5t-15 5.5q3 1 11.5 0.5t10.5 1.5
+q15 10 -7 16q-17 5 -43 -12zM879 10q206 36 351 189q-3 3 -12.5 4.5t-12.5 3.5q-18 7 -24 8q1 7 -2.5 13t-8 9t-12.5 8t-11 7q-2 2 -7 6t-7 5.5t-7.5 4.5t-8.5 2t-10 -1l-3 -1q-3 -1 -5.5 -2.5t-5.5 -3t-4 -3t0 -2.5q-21 17 -36 22q-5 1 -11 5.5t-10.5 7t-10 1.5t-11.5 -7
+q-5 -5 -6 -15t-2 -13q-7 5 0 17.5t2 18.5q-3 6 -10.5 4.5t-12 -4.5t-11.5 -8.5t-9 -6.5t-8.5 -5.5t-8.5 -7.5q-3 -4 -6 -12t-5 -11q-2 4 -11.5 6.5t-9.5 5.5q2 -10 4 -35t5 -38q7 -31 -12 -48q-27 -25 -29 -40q-4 -22 12 -26q0 -7 -8 -20.5t-7 -21.5q0 -6 2 -16z" />
+    <glyph glyph-name="wrench" unicode="&#xf0ad;" horiz-adv-x="1664" 
+d="M384 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1028 484l-682 -682q-37 -37 -90 -37q-52 0 -91 37l-106 108q-38 36 -38 90q0 53 38 91l681 681q39 -98 114.5 -173.5t173.5 -114.5zM1662 919q0 -39 -23 -106q-47 -134 -164.5 -217.5
+t-258.5 -83.5q-185 0 -316.5 131.5t-131.5 316.5t131.5 316.5t316.5 131.5q58 0 121.5 -16.5t107.5 -46.5q16 -11 16 -28t-16 -28l-293 -169v-224l193 -107q5 3 79 48.5t135.5 81t70.5 35.5q15 0 23.5 -10t8.5 -25z" />
+    <glyph glyph-name="tasks" unicode="&#xf0ae;" horiz-adv-x="1792" 
+d="M1024 128h640v128h-640v-128zM640 640h1024v128h-1024v-128zM1280 1152h384v128h-384v-128zM1792 320v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 832v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19
+t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 1344v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="filter" unicode="&#xf0b0;" horiz-adv-x="1408" 
+d="M1403 1241q17 -41 -14 -70l-493 -493v-742q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-256 256q-19 19 -19 45v486l-493 493q-31 29 -14 70q17 39 59 39h1280q42 0 59 -39z" />
+    <glyph glyph-name="briefcase" unicode="&#xf0b1;" horiz-adv-x="1792" 
+d="M640 1280h512v128h-512v-128zM1792 640v-480q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v480h672v-160q0 -26 19 -45t45 -19h320q26 0 45 19t19 45v160h672zM1024 640v-128h-256v128h256zM1792 1120v-384h-1792v384q0 66 47 113t113 47h352v160q0 40 28 68
+t68 28h576q40 0 68 -28t28 -68v-160h352q66 0 113 -47t47 -113z" />
+    <glyph glyph-name="fullscreen" unicode="&#xf0b2;" 
+d="M1283 995l-355 -355l355 -355l144 144q29 31 70 14q39 -17 39 -59v-448q0 -26 -19 -45t-45 -19h-448q-42 0 -59 40q-17 39 14 69l144 144l-355 355l-355 -355l144 -144q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45v448q0 42 40 59q39 17 69 -14l144 -144
+l355 355l-355 355l-144 -144q-19 -19 -45 -19q-12 0 -24 5q-40 17 -40 59v448q0 26 19 45t45 19h448q42 0 59 -40q17 -39 -14 -69l-144 -144l355 -355l355 355l-144 144q-31 30 -14 69q17 40 59 40h448q26 0 45 -19t19 -45v-448q0 -42 -39 -59q-13 -5 -25 -5q-26 0 -45 19z
+" />
+    <glyph glyph-name="group" unicode="&#xf0c0;" horiz-adv-x="1920" 
+d="M593 640q-162 -5 -265 -128h-134q-82 0 -138 40.5t-56 118.5q0 353 124 353q6 0 43.5 -21t97.5 -42.5t119 -21.5q67 0 133 23q-5 -37 -5 -66q0 -139 81 -256zM1664 3q0 -120 -73 -189.5t-194 -69.5h-874q-121 0 -194 69.5t-73 189.5q0 53 3.5 103.5t14 109t26.5 108.5
+t43 97.5t62 81t85.5 53.5t111.5 20q10 0 43 -21.5t73 -48t107 -48t135 -21.5t135 21.5t107 48t73 48t43 21.5q61 0 111.5 -20t85.5 -53.5t62 -81t43 -97.5t26.5 -108.5t14 -109t3.5 -103.5zM640 1280q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75
+t75 -181zM1344 896q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5zM1920 671q0 -78 -56 -118.5t-138 -40.5h-134q-103 123 -265 128q81 117 81 256q0 29 -5 66q66 -23 133 -23q59 0 119 21.5t97.5 42.5
+t43.5 21q124 0 124 -353zM1792 1280q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181z" />
+    <glyph glyph-name="link" unicode="&#xf0c1;" horiz-adv-x="1664" 
+d="M1456 320q0 40 -28 68l-208 208q-28 28 -68 28q-42 0 -72 -32q3 -3 19 -18.5t21.5 -21.5t15 -19t13 -25.5t3.5 -27.5q0 -40 -28 -68t-68 -28q-15 0 -27.5 3.5t-25.5 13t-19 15t-21.5 21.5t-18.5 19q-33 -31 -33 -73q0 -40 28 -68l206 -207q27 -27 68 -27q40 0 68 26
+l147 146q28 28 28 67zM753 1025q0 40 -28 68l-206 207q-28 28 -68 28q-39 0 -68 -27l-147 -146q-28 -28 -28 -67q0 -40 28 -68l208 -208q27 -27 68 -27q42 0 72 31q-3 3 -19 18.5t-21.5 21.5t-15 19t-13 25.5t-3.5 27.5q0 40 28 68t68 28q15 0 27.5 -3.5t25.5 -13t19 -15
+t21.5 -21.5t18.5 -19q33 31 33 73zM1648 320q0 -120 -85 -203l-147 -146q-83 -83 -203 -83q-121 0 -204 85l-206 207q-83 83 -83 203q0 123 88 209l-88 88q-86 -88 -208 -88q-120 0 -204 84l-208 208q-84 84 -84 204t85 203l147 146q83 83 203 83q121 0 204 -85l206 -207
+q83 -83 83 -203q0 -123 -88 -209l88 -88q86 88 208 88q120 0 204 -84l208 -208q84 -84 84 -204z" />
+    <glyph glyph-name="cloud" unicode="&#xf0c2;" horiz-adv-x="1920" 
+d="M1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088q-185 0 -316.5 131.5t-131.5 316.5q0 132 71 241.5t187 163.5q-2 28 -2 43q0 212 150 362t362 150q158 0 286.5 -88t187.5 -230q70 62 166 62q106 0 181 -75t75 -181q0 -75 -41 -138q129 -30 213 -134.5t84 -239.5z
+" />
+    <glyph glyph-name="beaker" unicode="&#xf0c3;" horiz-adv-x="1664" 
+d="M1527 88q56 -89 21.5 -152.5t-140.5 -63.5h-1152q-106 0 -140.5 63.5t21.5 152.5l503 793v399h-64q-26 0 -45 19t-19 45t19 45t45 19h512q26 0 45 -19t19 -45t-19 -45t-45 -19h-64v-399zM748 813l-272 -429h712l-272 429l-20 31v37v399h-128v-399v-37z" />
+    <glyph glyph-name="cut" unicode="&#xf0c4;" horiz-adv-x="1792" 
+d="M960 640q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1260 576l507 -398q28 -20 25 -56q-5 -35 -35 -51l-128 -64q-13 -7 -29 -7q-17 0 -31 8l-690 387l-110 -66q-8 -4 -12 -5q14 -49 10 -97q-7 -77 -56 -147.5t-132 -123.5q-132 -84 -277 -84
+q-136 0 -222 78q-90 84 -79 207q7 76 56 147t131 124q132 84 278 84q83 0 151 -31q9 13 22 22l122 73l-122 73q-13 9 -22 22q-68 -31 -151 -31q-146 0 -278 84q-82 53 -131 124t-56 147q-5 59 15.5 113t63.5 93q85 79 222 79q145 0 277 -84q83 -52 132 -123t56 -148
+q4 -48 -10 -97q4 -1 12 -5l110 -66l690 387q14 8 31 8q16 0 29 -7l128 -64q30 -16 35 -51q3 -36 -25 -56zM579 836q46 42 21 108t-106 117q-92 59 -192 59q-74 0 -113 -36q-46 -42 -21 -108t106 -117q92 -59 192 -59q74 0 113 36zM494 91q81 51 106 117t-21 108
+q-39 36 -113 36q-100 0 -192 -59q-81 -51 -106 -117t21 -108q39 -36 113 -36q100 0 192 59zM672 704l96 -58v11q0 36 33 56l14 8l-79 47l-26 -26q-3 -3 -10 -11t-12 -12q-2 -2 -4 -3.5t-3 -2.5zM896 480l96 -32l736 576l-128 64l-768 -431v-113l-160 -96l9 -8q2 -2 7 -6
+q4 -4 11 -12t11 -12l26 -26zM1600 64l128 64l-520 408l-177 -138q-2 -3 -13 -7z" />
+    <glyph glyph-name="copy" unicode="&#xf0c5;" horiz-adv-x="1792" 
+d="M1696 1152q40 0 68 -28t28 -68v-1216q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v288h-544q-40 0 -68 28t-28 68v672q0 40 20 88t48 76l408 408q28 28 76 48t88 20h416q40 0 68 -28t28 -68v-328q68 40 128 40h416zM1152 939l-299 -299h299v299zM512 1323l-299 -299
+h299v299zM708 676l316 316v416h-384v-416q0 -40 -28 -68t-68 -28h-416v-640h512v256q0 40 20 88t48 76zM1664 -128v1152h-384v-416q0 -40 -28 -68t-68 -28h-416v-640h896z" />
+    <glyph glyph-name="paper_clip" unicode="&#xf0c6;" horiz-adv-x="1408" 
+d="M1404 151q0 -117 -79 -196t-196 -79q-135 0 -235 100l-777 776q-113 115 -113 271q0 159 110 270t269 111q158 0 273 -113l605 -606q10 -10 10 -22q0 -16 -30.5 -46.5t-46.5 -30.5q-13 0 -23 10l-606 607q-79 77 -181 77q-106 0 -179 -75t-73 -181q0 -105 76 -181
+l776 -777q63 -63 145 -63q64 0 106 42t42 106q0 82 -63 145l-581 581q-26 24 -60 24q-29 0 -48 -19t-19 -48q0 -32 25 -59l410 -410q10 -10 10 -22q0 -16 -31 -47t-47 -31q-12 0 -22 10l-410 410q-63 61 -63 149q0 82 57 139t139 57q88 0 149 -63l581 -581q100 -98 100 -235
+z" />
+    <glyph glyph-name="save" unicode="&#xf0c7;" 
+d="M384 0h768v384h-768v-384zM1280 0h128v896q0 14 -10 38.5t-20 34.5l-281 281q-10 10 -34 20t-39 10v-416q0 -40 -28 -68t-68 -28h-576q-40 0 -68 28t-28 68v416h-128v-1280h128v416q0 40 28 68t68 28h832q40 0 68 -28t28 -68v-416zM896 928v320q0 13 -9.5 22.5t-22.5 9.5
+h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5zM1536 896v-928q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h928q40 0 88 -20t76 -48l280 -280q28 -28 48 -76t20 -88z" />
+    <glyph glyph-name="sign_blank" unicode="&#xf0c8;" 
+d="M1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="reorder" unicode="&#xf0c9;" 
+d="M1536 192v-128q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1536 704v-128q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1536 1216v-128q0 -26 -19 -45
+t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="ul" unicode="&#xf0ca;" horiz-adv-x="1792" 
+d="M384 128q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM384 640q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5
+t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5zM384 1152q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1792 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z
+M1792 1248v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z" />
+    <glyph glyph-name="ol" unicode="&#xf0cb;" horiz-adv-x="1792" 
+d="M381 -84q0 -80 -54.5 -126t-135.5 -46q-106 0 -172 66l57 88q49 -45 106 -45q29 0 50.5 14.5t21.5 42.5q0 64 -105 56l-26 56q8 10 32.5 43.5t42.5 54t37 38.5v1q-16 0 -48.5 -1t-48.5 -1v-53h-106v152h333v-88l-95 -115q51 -12 81 -49t30 -88zM383 543v-159h-362
+q-6 36 -6 54q0 51 23.5 93t56.5 68t66 47.5t56.5 43.5t23.5 45q0 25 -14.5 38.5t-39.5 13.5q-46 0 -81 -58l-85 59q24 51 71.5 79.5t105.5 28.5q73 0 123 -41.5t50 -112.5q0 -50 -34 -91.5t-75 -64.5t-75.5 -50.5t-35.5 -52.5h127v60h105zM1792 224v-192q0 -13 -9.5 -22.5
+t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 14 9 23t23 9h1216q13 0 22.5 -9.5t9.5 -22.5zM384 1123v-99h-335v99h107q0 41 0.5 121.5t0.5 121.5v12h-2q-8 -17 -50 -54l-71 76l136 127h106v-404h108zM1792 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216
+q-13 0 -22.5 9.5t-9.5 22.5v192q0 14 9 23t23 9h1216q13 0 22.5 -9.5t9.5 -22.5zM1792 1248v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z" />
+    <glyph glyph-name="strikethrough" unicode="&#xf0cc;" horiz-adv-x="1792" 
+d="M1760 640q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1728q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h1728zM483 704q-28 35 -51 80q-48 98 -48 188q0 181 134 309q133 127 393 127q50 0 167 -19q66 -12 177 -48q10 -38 21 -118q14 -123 14 -183q0 -18 -5 -45l-12 -3l-84 6
+l-14 2q-50 149 -103 205q-88 91 -210 91q-114 0 -182 -59q-67 -58 -67 -146q0 -73 66 -140t279 -129q69 -20 173 -66q58 -28 95 -52h-743zM990 448h411q7 -39 7 -92q0 -111 -41 -212q-23 -56 -71 -104q-37 -35 -109 -81q-80 -48 -153 -66q-80 -21 -203 -21q-114 0 -195 23
+l-140 40q-57 16 -72 28q-8 8 -8 22v13q0 108 -2 156q-1 30 0 68l2 37v44l102 2q15 -34 30 -71t22.5 -56t12.5 -27q35 -57 80 -94q43 -36 105 -57q59 -22 132 -22q64 0 139 27q77 26 122 86q47 61 47 129q0 84 -81 157q-34 29 -137 71z" />
+    <glyph glyph-name="underline" unicode="&#xf0cd;" 
+d="M48 1313q-37 2 -45 4l-3 88q13 1 40 1q60 0 112 -4q132 -7 166 -7q86 0 168 3q116 4 146 5q56 0 86 2l-1 -14l2 -64v-9q-60 -9 -124 -9q-60 0 -79 -25q-13 -14 -13 -132q0 -13 0.5 -32.5t0.5 -25.5l1 -229l14 -280q6 -124 51 -202q35 -59 96 -92q88 -47 177 -47
+q104 0 191 28q56 18 99 51q48 36 65 64q36 56 53 114q21 73 21 229q0 79 -3.5 128t-11 122.5t-13.5 159.5l-4 59q-5 67 -24 88q-34 35 -77 34l-100 -2l-14 3l2 86h84l205 -10q76 -3 196 10l18 -2q6 -38 6 -51q0 -7 -4 -31q-45 -12 -84 -13q-73 -11 -79 -17q-15 -15 -15 -41
+q0 -7 1.5 -27t1.5 -31q8 -19 22 -396q6 -195 -15 -304q-15 -76 -41 -122q-38 -65 -112 -123q-75 -57 -182 -89q-109 -33 -255 -33q-167 0 -284 46q-119 47 -179 122q-61 76 -83 195q-16 80 -16 237v333q0 188 -17 213q-25 36 -147 39zM1536 -96v64q0 14 -9 23t-23 9h-1472
+q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h1472q14 0 23 9t9 23z" />
+    <glyph glyph-name="table" unicode="&#xf0ce;" horiz-adv-x="1664" 
+d="M512 160v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM512 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 160v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23
+v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM512 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 160v192
+q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192
+q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1664 1248v-1088q0 -66 -47 -113t-113 -47h-1344q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1344q66 0 113 -47t47 -113
+z" />
+    <glyph glyph-name="magic" unicode="&#xf0d0;" horiz-adv-x="1664" 
+d="M1190 955l293 293l-107 107l-293 -293zM1637 1248q0 -27 -18 -45l-1286 -1286q-18 -18 -45 -18t-45 18l-198 198q-18 18 -18 45t18 45l1286 1286q18 18 45 18t45 -18l198 -198q18 -18 18 -45zM286 1438l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98zM636 1276
+l196 -60l-196 -60l-60 -196l-60 196l-196 60l196 60l60 196zM1566 798l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98zM926 1438l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98z" />
+    <glyph glyph-name="truck" unicode="&#xf0d1;" horiz-adv-x="1792" 
+d="M640 128q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM256 640h384v256h-158q-13 0 -22 -9l-195 -195q-9 -9 -9 -22v-30zM1536 128q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM1792 1216v-1024q0 -15 -4 -26.5t-13.5 -18.5
+t-16.5 -11.5t-23.5 -6t-22.5 -2t-25.5 0t-22.5 0.5q0 -106 -75 -181t-181 -75t-181 75t-75 181h-384q0 -106 -75 -181t-181 -75t-181 75t-75 181h-64q-3 0 -22.5 -0.5t-25.5 0t-22.5 2t-23.5 6t-16.5 11.5t-13.5 18.5t-4 26.5q0 26 19 45t45 19v320q0 8 -0.5 35t0 38
+t2.5 34.5t6.5 37t14 30.5t22.5 30l198 198q19 19 50.5 32t58.5 13h160v192q0 26 19 45t45 19h1024q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="pinterest" unicode="&#xf0d2;" 
+d="M1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103q-111 0 -218 32q59 93 78 164q9 34 54 211q20 -39 73 -67.5t114 -28.5q121 0 216 68.5t147 188.5t52 270q0 114 -59.5 214t-172.5 163t-255 63q-105 0 -196 -29t-154.5 -77t-109 -110.5t-67 -129.5t-21.5 -134
+q0 -104 40 -183t117 -111q30 -12 38 20q2 7 8 31t8 30q6 23 -11 43q-51 61 -51 151q0 151 104.5 259.5t273.5 108.5q151 0 235.5 -82t84.5 -213q0 -170 -68.5 -289t-175.5 -119q-61 0 -98 43.5t-23 104.5q8 35 26.5 93.5t30 103t11.5 75.5q0 50 -27 83t-77 33
+q-62 0 -105 -57t-43 -142q0 -73 25 -122l-99 -418q-17 -70 -13 -177q-206 91 -333 281t-127 423q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="pinterest_sign" unicode="&#xf0d3;" 
+d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-725q85 122 108 210q9 34 53 209q21 -39 73.5 -67t112.5 -28q181 0 295.5 147.5t114.5 373.5q0 84 -35 162.5t-96.5 139t-152.5 97t-197 36.5q-104 0 -194.5 -28.5t-153 -76.5
+t-107.5 -109.5t-66.5 -128t-21.5 -132.5q0 -102 39.5 -180t116.5 -110q13 -5 23.5 0t14.5 19q10 44 15 61q6 23 -11 42q-50 62 -50 150q0 150 103.5 256.5t270.5 106.5q149 0 232.5 -81t83.5 -210q0 -168 -67.5 -286t-173.5 -118q-60 0 -97 43.5t-23 103.5q8 34 26.5 92.5
+t29.5 102t11 74.5q0 49 -26.5 81.5t-75.5 32.5q-61 0 -103.5 -56.5t-42.5 -139.5q0 -72 24 -121l-98 -414q-24 -100 -7 -254h-183q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960z" />
+    <glyph glyph-name="google_plus_sign" unicode="&#xf0d4;" 
+d="M917 631q0 26 -6 64h-362v-132h217q-3 -24 -16.5 -50t-37.5 -53t-66.5 -44.5t-96.5 -17.5q-99 0 -169 71t-70 171t70 171t169 71q92 0 153 -59l104 101q-108 100 -257 100q-160 0 -272 -112.5t-112 -271.5t112 -271.5t272 -112.5q165 0 266.5 105t101.5 270zM1262 585
+h109v110h-109v110h-110v-110h-110v-110h110v-110h110v110zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="google_plus" unicode="&#xf0d5;" horiz-adv-x="2304" 
+d="M1437 623q0 -208 -87 -370.5t-248 -254t-369 -91.5q-149 0 -285 58t-234 156t-156 234t-58 285t58 285t156 234t234 156t285 58q286 0 491 -192l-199 -191q-117 113 -292 113q-123 0 -227.5 -62t-165.5 -168.5t-61 -232.5t61 -232.5t165.5 -168.5t227.5 -62
+q83 0 152.5 23t114.5 57.5t78.5 78.5t49 83t21.5 74h-416v252h692q12 -63 12 -122zM2304 745v-210h-209v-209h-210v209h-209v210h209v209h210v-209h209z" />
+    <glyph glyph-name="money" unicode="&#xf0d6;" horiz-adv-x="1920" 
+d="M768 384h384v96h-128v448h-114l-148 -137l77 -80q42 37 55 57h2v-288h-128v-96zM1280 640q0 -70 -21 -142t-59.5 -134t-101.5 -101t-138 -39t-138 39t-101.5 101t-59.5 134t-21 142t21 142t59.5 134t101.5 101t138 39t138 -39t101.5 -101t59.5 -134t21 -142zM1792 384
+v512q-106 0 -181 75t-75 181h-1152q0 -106 -75 -181t-181 -75v-512q106 0 181 -75t75 -181h1152q0 106 75 181t181 75zM1920 1216v-1152q0 -26 -19 -45t-45 -19h-1792q-26 0 -45 19t-19 45v1152q0 26 19 45t45 19h1792q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="caret_down" unicode="&#xf0d7;" horiz-adv-x="1024" 
+d="M1024 832q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="caret_up" unicode="&#xf0d8;" horiz-adv-x="1024" 
+d="M1024 320q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" />
+    <glyph glyph-name="caret_left" unicode="&#xf0d9;" horiz-adv-x="640" 
+d="M640 1088v-896q0 -26 -19 -45t-45 -19t-45 19l-448 448q-19 19 -19 45t19 45l448 448q19 19 45 19t45 -19t19 -45z" />
+    <glyph glyph-name="caret_right" unicode="&#xf0da;" horiz-adv-x="640" 
+d="M576 640q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19t-19 45v896q0 26 19 45t45 19t45 -19l448 -448q19 -19 19 -45z" />
+    <glyph glyph-name="columns" unicode="&#xf0db;" horiz-adv-x="1664" 
+d="M160 0h608v1152h-640v-1120q0 -13 9.5 -22.5t22.5 -9.5zM1536 32v1120h-640v-1152h608q13 0 22.5 9.5t9.5 22.5zM1664 1248v-1216q0 -66 -47 -113t-113 -47h-1344q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1344q66 0 113 -47t47 -113z" />
+    <glyph glyph-name="sort" unicode="&#xf0dc;" horiz-adv-x="1024" 
+d="M1024 448q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45zM1024 832q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" />
+    <glyph glyph-name="sort_down" unicode="&#xf0dd;" horiz-adv-x="1024" 
+d="M1024 448q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="sort_up" unicode="&#xf0de;" horiz-adv-x="1024" 
+d="M1024 832q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" />
+    <glyph glyph-name="envelope_alt" unicode="&#xf0e0;" horiz-adv-x="1792" 
+d="M1792 826v-794q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v794q44 -49 101 -87q362 -246 497 -345q57 -42 92.5 -65.5t94.5 -48t110 -24.5h1h1q51 0 110 24.5t94.5 48t92.5 65.5q170 123 498 345q57 39 100 87zM1792 1120q0 -79 -49 -151t-122 -123
+q-376 -261 -468 -325q-10 -7 -42.5 -30.5t-54 -38t-52 -32.5t-57.5 -27t-50 -9h-1h-1q-23 0 -50 9t-57.5 27t-52 32.5t-54 38t-42.5 30.5q-91 64 -262 182.5t-205 142.5q-62 42 -117 115.5t-55 136.5q0 78 41.5 130t118.5 52h1472q65 0 112.5 -47t47.5 -113z" />
+    <glyph glyph-name="linkedin" unicode="&#xf0e1;" 
+d="M349 911v-991h-330v991h330zM370 1217q1 -73 -50.5 -122t-135.5 -49h-2q-82 0 -132 49t-50 122q0 74 51.5 122.5t134.5 48.5t133 -48.5t51 -122.5zM1536 488v-568h-329v530q0 105 -40.5 164.5t-126.5 59.5q-63 0 -105.5 -34.5t-63.5 -85.5q-11 -30 -11 -81v-553h-329
+q2 399 2 647t-1 296l-1 48h329v-144h-2q20 32 41 56t56.5 52t87 43.5t114.5 15.5q171 0 275 -113.5t104 -332.5z" />
+    <glyph glyph-name="undo" unicode="&#xf0e2;" 
+d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61q-172 0 -327 72.5t-264 204.5q-7 10 -6.5 22.5t8.5 20.5l137 138q10 9 25 9q16 -2 23 -12q73 -95 179 -147t225 -52q104 0 198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5t-40.5 198.5t-109.5 163.5
+t-163.5 109.5t-198.5 40.5q-98 0 -188 -35.5t-160 -101.5l137 -138q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45v448q0 42 40 59q39 17 69 -14l130 -129q107 101 244.5 156.5t284.5 55.5q156 0 298 -61t245 -164t164 -245t61 -298z" />
+    <glyph glyph-name="legal" unicode="&#xf0e3;" horiz-adv-x="1792" 
+d="M1771 0q0 -53 -37 -90l-107 -108q-39 -37 -91 -37q-53 0 -90 37l-363 364q-38 36 -38 90q0 53 43 96l-256 256l-126 -126q-14 -14 -34 -14t-34 14q2 -2 12.5 -12t12.5 -13t10 -11.5t10 -13.5t6 -13.5t5.5 -16.5t1.5 -18q0 -38 -28 -68q-3 -3 -16.5 -18t-19 -20.5
+t-18.5 -16.5t-22 -15.5t-22 -9t-26 -4.5q-40 0 -68 28l-408 408q-28 28 -28 68q0 13 4.5 26t9 22t15.5 22t16.5 18.5t20.5 19t18 16.5q30 28 68 28q10 0 18 -1.5t16.5 -5.5t13.5 -6t13.5 -10t11.5 -10t13 -12.5t12 -12.5q-14 14 -14 34t14 34l348 348q14 14 34 14t34 -14
+q-2 2 -12.5 12t-12.5 13t-10 11.5t-10 13.5t-6 13.5t-5.5 16.5t-1.5 18q0 38 28 68q3 3 16.5 18t19 20.5t18.5 16.5t22 15.5t22 9t26 4.5q40 0 68 -28l408 -408q28 -28 28 -68q0 -13 -4.5 -26t-9 -22t-15.5 -22t-16.5 -18.5t-20.5 -19t-18 -16.5q-30 -28 -68 -28
+q-10 0 -18 1.5t-16.5 5.5t-13.5 6t-13.5 10t-11.5 10t-13 12.5t-12 12.5q14 -14 14 -34t-14 -34l-126 -126l256 -256q43 43 96 43q52 0 91 -37l363 -363q37 -39 37 -91z" />
+    <glyph glyph-name="dashboard" unicode="&#xf0e4;" horiz-adv-x="1792" 
+d="M384 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM576 832q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1004 351l101 382q6 26 -7.5 48.5t-38.5 29.5
+t-48 -6.5t-30 -39.5l-101 -382q-60 -5 -107 -43.5t-63 -98.5q-20 -77 20 -146t117 -89t146 20t89 117q16 60 -6 117t-72 91zM1664 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1024 1024q0 53 -37.5 90.5
+t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1472 832q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1792 384q0 -261 -141 -483q-19 -29 -54 -29h-1402q-35 0 -54 29
+q-141 221 -141 483q0 182 71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
+    <glyph glyph-name="comment_alt" unicode="&#xf0e5;" horiz-adv-x="1792" 
+d="M896 1152q-204 0 -381.5 -69.5t-282 -187.5t-104.5 -255q0 -112 71.5 -213.5t201.5 -175.5l87 -50l-27 -96q-24 -91 -70 -172q152 63 275 171l43 38l57 -6q69 -8 130 -8q204 0 381.5 69.5t282 187.5t104.5 255t-104.5 255t-282 187.5t-381.5 69.5zM1792 640
+q0 -174 -120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22h-5q-15 0 -27 10.5t-16 27.5v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5t34.5 38t31 39.5t32.5 51t27 59t26 76q-157 89 -247.5 220t-90.5 281q0 174 120 321.5
+t326 233t450 85.5t450 -85.5t326 -233t120 -321.5z" />
+    <glyph glyph-name="comments_alt" unicode="&#xf0e6;" horiz-adv-x="1792" 
+d="M704 1152q-153 0 -286 -52t-211.5 -141t-78.5 -191q0 -82 53 -158t149 -132l97 -56l-35 -84q34 20 62 39l44 31l53 -10q78 -14 153 -14q153 0 286 52t211.5 141t78.5 191t-78.5 191t-211.5 141t-286 52zM704 1280q191 0 353.5 -68.5t256.5 -186.5t94 -257t-94 -257
+t-256.5 -186.5t-353.5 -68.5q-86 0 -176 16q-124 -88 -278 -128q-36 -9 -86 -16h-3q-11 0 -20.5 8t-11.5 21q-1 3 -1 6.5t0.5 6.5t2 6l2.5 5t3.5 5.5t4 5t4.5 5t4 4.5q5 6 23 25t26 29.5t22.5 29t25 38.5t20.5 44q-124 72 -195 177t-71 224q0 139 94 257t256.5 186.5
+t353.5 68.5zM1526 111q10 -24 20.5 -44t25 -38.5t22.5 -29t26 -29.5t23 -25q1 -1 4 -4.5t4.5 -5t4 -5t3.5 -5.5l2.5 -5t2 -6t0.5 -6.5t-1 -6.5q-3 -14 -13 -22t-22 -7q-50 7 -86 16q-154 40 -278 128q-90 -16 -176 -16q-271 0 -472 132q58 -4 88 -4q161 0 309 45t264 129
+q125 92 192 212t67 254q0 77 -23 152q129 -71 204 -178t75 -230q0 -120 -71 -224.5t-195 -176.5z" />
+    <glyph glyph-name="bolt" unicode="&#xf0e7;" horiz-adv-x="896" 
+d="M885 970q18 -20 7 -44l-540 -1157q-13 -25 -42 -25q-4 0 -14 2q-17 5 -25.5 19t-4.5 30l197 808l-406 -101q-4 -1 -12 -1q-18 0 -31 11q-18 15 -13 39l201 825q4 14 16 23t28 9h328q19 0 32 -12.5t13 -29.5q0 -8 -5 -18l-171 -463l396 98q8 2 12 2q19 0 34 -15z" />
+    <glyph glyph-name="sitemap" unicode="&#xf0e8;" horiz-adv-x="1792" 
+d="M1792 288v-320q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192h-512v-192h96q40 0 68 -28t28 -68v-320q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192h-512v-192h96q40 0 68 -28t28 -68v-320
+q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192q0 52 38 90t90 38h512v192h-96q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h320q40 0 68 -28t28 -68v-320q0 -40 -28 -68t-68 -28h-96v-192h512q52 0 90 -38t38 -90v-192h96q40 0 68 -28t28 -68
+z" />
+    <glyph glyph-name="umbrella" unicode="&#xf0e9;" horiz-adv-x="1664" 
+d="M896 708v-580q0 -104 -76 -180t-180 -76t-180 76t-76 180q0 26 19 45t45 19t45 -19t19 -45q0 -50 39 -89t89 -39t89 39t39 89v580q33 11 64 11t64 -11zM1664 681q0 -13 -9.5 -22.5t-22.5 -9.5q-11 0 -23 10q-49 46 -93 69t-102 23q-68 0 -128 -37t-103 -97
+q-7 -10 -17.5 -28t-14.5 -24q-11 -17 -28 -17q-18 0 -29 17q-4 6 -14.5 24t-17.5 28q-43 60 -102.5 97t-127.5 37t-127.5 -37t-102.5 -97q-7 -10 -17.5 -28t-14.5 -24q-11 -17 -29 -17q-17 0 -28 17q-4 6 -14.5 24t-17.5 28q-43 60 -103 97t-128 37q-58 0 -102 -23t-93 -69
+q-12 -10 -23 -10q-13 0 -22.5 9.5t-9.5 22.5q0 5 1 7q45 183 172.5 319.5t298 204.5t360.5 68q140 0 274.5 -40t246.5 -113.5t194.5 -187t115.5 -251.5q1 -2 1 -7zM896 1408v-98q-42 2 -64 2t-64 -2v98q0 26 19 45t45 19t45 -19t19 -45z" />
+    <glyph glyph-name="paste" unicode="&#xf0ea;" horiz-adv-x="1792" 
+d="M768 -128h896v640h-416q-40 0 -68 28t-28 68v416h-384v-1152zM1024 1312v64q0 13 -9.5 22.5t-22.5 9.5h-704q-13 0 -22.5 -9.5t-9.5 -22.5v-64q0 -13 9.5 -22.5t22.5 -9.5h704q13 0 22.5 9.5t9.5 22.5zM1280 640h299l-299 299v-299zM1792 512v-672q0 -40 -28 -68t-68 -28
+h-960q-40 0 -68 28t-28 68v160h-544q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h1088q40 0 68 -28t28 -68v-328q21 -13 36 -28l408 -408q28 -28 48 -76t20 -88z" />
+    <glyph glyph-name="light_bulb" unicode="&#xf0eb;" horiz-adv-x="1024" 
+d="M736 960q0 -13 -9.5 -22.5t-22.5 -9.5t-22.5 9.5t-9.5 22.5q0 46 -54 71t-106 25q-13 0 -22.5 9.5t-9.5 22.5t9.5 22.5t22.5 9.5q50 0 99.5 -16t87 -54t37.5 -90zM896 960q0 72 -34.5 134t-90 101.5t-123 62t-136.5 22.5t-136.5 -22.5t-123 -62t-90 -101.5t-34.5 -134
+q0 -101 68 -180q10 -11 30.5 -33t30.5 -33q128 -153 141 -298h228q13 145 141 298q10 11 30.5 33t30.5 33q68 79 68 180zM1024 960q0 -155 -103 -268q-45 -49 -74.5 -87t-59.5 -95.5t-34 -107.5q47 -28 47 -82q0 -37 -25 -64q25 -27 25 -64q0 -52 -45 -81q13 -23 13 -47
+q0 -46 -31.5 -71t-77.5 -25q-20 -44 -60 -70t-87 -26t-87 26t-60 70q-46 0 -77.5 25t-31.5 71q0 24 13 47q-45 29 -45 81q0 37 25 64q-25 27 -25 64q0 54 47 82q-4 50 -34 107.5t-59.5 95.5t-74.5 87q-103 113 -103 268q0 99 44.5 184.5t117 142t164 89t186.5 32.5
+t186.5 -32.5t164 -89t117 -142t44.5 -184.5z" />
+    <glyph glyph-name="exchange" unicode="&#xf0ec;" horiz-adv-x="1792" 
+d="M1792 352v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5q-12 0 -24 10l-319 320q-9 9 -9 22q0 14 9 23l320 320q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5v-192h1376q13 0 22.5 -9.5t9.5 -22.5zM1792 896q0 -14 -9 -23l-320 -320q-9 -9 -23 -9
+q-13 0 -22.5 9.5t-9.5 22.5v192h-1376q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1376v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23z" />
+    <glyph glyph-name="cloud_download" unicode="&#xf0ed;" horiz-adv-x="1920" 
+d="M1280 608q0 14 -9 23t-23 9h-224v352q0 13 -9.5 22.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-352h-224q-13 0 -22.5 -9.5t-9.5 -22.5q0 -14 9 -23l352 -352q9 -9 23 -9t23 9l351 351q10 12 10 24zM1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088
+q-185 0 -316.5 131.5t-131.5 316.5q0 130 70 240t188 165q-2 30 -2 43q0 212 150 362t362 150q156 0 285.5 -87t188.5 -231q71 62 166 62q106 0 181 -75t75 -181q0 -76 -41 -138q130 -31 213.5 -135.5t83.5 -238.5z" />
+    <glyph glyph-name="cloud_upload" unicode="&#xf0ee;" horiz-adv-x="1920" 
+d="M1280 672q0 14 -9 23l-352 352q-9 9 -23 9t-23 -9l-351 -351q-10 -12 -10 -24q0 -14 9 -23t23 -9h224v-352q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5v352h224q13 0 22.5 9.5t9.5 22.5zM1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088
+q-185 0 -316.5 131.5t-131.5 316.5q0 130 70 240t188 165q-2 30 -2 43q0 212 150 362t362 150q156 0 285.5 -87t188.5 -231q71 62 166 62q106 0 181 -75t75 -181q0 -76 -41 -138q130 -31 213.5 -135.5t83.5 -238.5z" />
+    <glyph glyph-name="user_md" unicode="&#xf0f0;" horiz-adv-x="1408" 
+d="M384 192q0 -26 -19 -45t-45 -19t-45 19t-19 45t19 45t45 19t45 -19t19 -45zM1408 131q0 -121 -73 -190t-194 -69h-874q-121 0 -194 69t-73 190q0 68 5.5 131t24 138t47.5 132.5t81 103t120 60.5q-22 -52 -22 -120v-203q-58 -20 -93 -70t-35 -111q0 -80 56 -136t136 -56
+t136 56t56 136q0 61 -35.5 111t-92.5 70v203q0 62 25 93q132 -104 295 -104t295 104q25 -31 25 -93v-64q-106 0 -181 -75t-75 -181v-89q-32 -29 -32 -71q0 -40 28 -68t68 -28t68 28t28 68q0 42 -32 71v89q0 52 38 90t90 38t90 -38t38 -90v-89q-32 -29 -32 -71q0 -40 28 -68
+t68 -28t68 28t28 68q0 42 -32 71v89q0 68 -34.5 127.5t-93.5 93.5q0 10 0.5 42.5t0 48t-2.5 41.5t-7 47t-13 40q68 -15 120 -60.5t81 -103t47.5 -132.5t24 -138t5.5 -131zM1088 1024q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5
+t271.5 -112.5t112.5 -271.5z" />
+    <glyph glyph-name="stethoscope" unicode="&#xf0f1;" horiz-adv-x="1408" 
+d="M1280 832q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 832q0 -62 -35.5 -111t-92.5 -70v-395q0 -159 -131.5 -271.5t-316.5 -112.5t-316.5 112.5t-131.5 271.5v132q-164 20 -274 128t-110 252v512q0 26 19 45t45 19q6 0 16 -2q17 30 47 48
+t65 18q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5q-33 0 -64 18v-402q0 -106 94 -181t226 -75t226 75t94 181v402q-31 -18 -64 -18q-53 0 -90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5q35 0 65 -18t47 -48q10 2 16 2q26 0 45 -19t19 -45v-512q0 -144 -110 -252
+t-274 -128v-132q0 -106 94 -181t226 -75t226 75t94 181v395q-57 21 -92.5 70t-35.5 111q0 80 56 136t136 56t136 -56t56 -136z" />
+    <glyph glyph-name="suitcase" unicode="&#xf0f2;" horiz-adv-x="1792" 
+d="M640 1152h512v128h-512v-128zM288 1152v-1280h-64q-92 0 -158 66t-66 158v832q0 92 66 158t158 66h64zM1408 1152v-1280h-1024v1280h128v160q0 40 28 68t68 28h576q40 0 68 -28t28 -68v-160h128zM1792 928v-832q0 -92 -66 -158t-158 -66h-64v1280h64q92 0 158 -66
+t66 -158z" />
+    <glyph glyph-name="bell_alt" unicode="&#xf0f3;" horiz-adv-x="1792" 
+d="M912 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM1728 128q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-181 75t-75 181h-448q-52 0 -90 38t-38 90q50 42 91 88t85 119.5t74.5 158.5
+t50 206t19.5 260q0 152 117 282.5t307 158.5q-8 19 -8 39q0 40 28 68t68 28t68 -28t28 -68q0 -20 -8 -39q190 -28 307 -158.5t117 -282.5q0 -139 19.5 -260t50 -206t74.5 -158.5t85 -119.5t91 -88z" />
+    <glyph glyph-name="coffee" unicode="&#xf0f4;" horiz-adv-x="1920" 
+d="M1664 896q0 80 -56 136t-136 56h-64v-384h64q80 0 136 56t56 136zM0 128h1792q0 -106 -75 -181t-181 -75h-1280q-106 0 -181 75t-75 181zM1856 896q0 -159 -112.5 -271.5t-271.5 -112.5h-64v-32q0 -92 -66 -158t-158 -66h-704q-92 0 -158 66t-66 158v736q0 26 19 45
+t45 19h1152q159 0 271.5 -112.5t112.5 -271.5z" />
+    <glyph glyph-name="food" unicode="&#xf0f5;" horiz-adv-x="1408" 
+d="M640 1472v-640q0 -61 -35.5 -111t-92.5 -70v-779q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v779q-57 20 -92.5 70t-35.5 111v640q0 26 19 45t45 19t45 -19t19 -45v-416q0 -26 19 -45t45 -19t45 19t19 45v416q0 26 19 45t45 19t45 -19t19 -45v-416q0 -26 19 -45
+t45 -19t45 19t19 45v416q0 26 19 45t45 19t45 -19t19 -45zM1408 1472v-1600q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v512h-224q-13 0 -22.5 9.5t-9.5 22.5v800q0 132 94 226t226 94h256q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="file_text_alt" unicode="&#xf0f6;" 
+d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z
+M384 736q0 14 9 23t23 9h704q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23v64zM1120 512q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h704zM1120 256q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704
+q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h704z" />
+    <glyph glyph-name="building" unicode="&#xf0f7;" horiz-adv-x="1408" 
+d="M384 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M640 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M1152 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M640 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M1152 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M640 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M1152 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M640 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M896 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M896 -128h384v1536h-1152v-1536h384v224q0 13 9.5 22.5t22.5 9.5h320q13 0 22.5 -9.5t9.5 -22.5v-224zM1408 1472v-1664q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v1664q0 26 19 45t45 19h1280q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="hospital" unicode="&#xf0f8;" horiz-adv-x="1408" 
+d="M384 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M640 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M1152 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M640 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M896 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M896 -128h384v1152h-256v-32q0 -40 -28 -68t-68 -28h-448q-40 0 -68 28t-28 68v32h-256v-1152h384v224q0 13 9.5 22.5t22.5 9.5h320q13 0 22.5 -9.5t9.5 -22.5v-224zM896 1056v320q0 13 -9.5 22.5t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-96h-128v96q0 13 -9.5 22.5
+t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5v96h128v-96q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1408 1088v-1280q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v1280q0 26 19 45t45 19h320
+v288q0 40 28 68t68 28h448q40 0 68 -28t28 -68v-288h320q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="ambulance" unicode="&#xf0f9;" horiz-adv-x="1920" 
+d="M640 128q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM256 640h384v256h-158q-14 -2 -22 -9l-195 -195q-7 -12 -9 -22v-30zM1536 128q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5
+t90.5 37.5t37.5 90.5zM1664 800v192q0 14 -9 23t-23 9h-224v224q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-224h-224q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h224v-224q0 -14 9 -23t23 -9h192q14 0 23 9t9 23v224h224q14 0 23 9t9 23zM1920 1344v-1152
+q0 -26 -19 -45t-45 -19h-192q0 -106 -75 -181t-181 -75t-181 75t-75 181h-384q0 -106 -75 -181t-181 -75t-181 75t-75 181h-128q-26 0 -45 19t-19 45t19 45t45 19v416q0 26 13 58t32 51l198 198q19 19 51 32t58 13h160v320q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="medkit" unicode="&#xf0fa;" horiz-adv-x="1792" 
+d="M1280 416v192q0 14 -9 23t-23 9h-224v224q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-224h-224q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h224v-224q0 -14 9 -23t23 -9h192q14 0 23 9t9 23v224h224q14 0 23 9t9 23zM640 1152h512v128h-512v-128zM256 1152v-1280h-32
+q-92 0 -158 66t-66 158v832q0 92 66 158t158 66h32zM1440 1152v-1280h-1088v1280h160v160q0 40 28 68t68 28h576q40 0 68 -28t28 -68v-160h160zM1792 928v-832q0 -92 -66 -158t-158 -66h-32v1280h32q92 0 158 -66t66 -158z" />
+    <glyph glyph-name="fighter_jet" unicode="&#xf0fb;" horiz-adv-x="1920" 
+d="M1920 576q-1 -32 -288 -96l-352 -32l-224 -64h-64l-293 -352h69q26 0 45 -4.5t19 -11.5t-19 -11.5t-45 -4.5h-96h-160h-64v32h64v416h-160l-192 -224h-96l-32 32v192h32v32h128v8l-192 24v128l192 24v8h-128v32h-32v192l32 32h96l192 -224h160v416h-64v32h64h160h96
+q26 0 45 -4.5t19 -11.5t-19 -11.5t-45 -4.5h-69l293 -352h64l224 -64l352 -32q128 -28 200 -52t80 -34z" />
+    <glyph glyph-name="beer" unicode="&#xf0fc;" horiz-adv-x="1664" 
+d="M640 640v384h-256v-256q0 -53 37.5 -90.5t90.5 -37.5h128zM1664 192v-192h-1152v192l128 192h-128q-159 0 -271.5 112.5t-112.5 271.5v320l-64 64l32 128h480l32 128h960l32 -192l-64 -32v-800z" />
+    <glyph glyph-name="h_sign" unicode="&#xf0fd;" 
+d="M1280 192v896q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-320h-512v320q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-896q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v320h512v-320q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1536 1120v-960
+q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="f0fe" unicode="&#xf0fe;" 
+d="M1280 576v128q0 26 -19 45t-45 19h-320v320q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-320h-320q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h320v-320q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v320h320q26 0 45 19t19 45zM1536 1120v-960
+q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="double_angle_left" unicode="&#xf100;" horiz-adv-x="1024" 
+d="M627 160q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23zM1011 160q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23
+t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23z" />
+    <glyph glyph-name="double_angle_right" unicode="&#xf101;" horiz-adv-x="1024" 
+d="M595 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23zM979 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23
+l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
+    <glyph glyph-name="double_angle_up" unicode="&#xf102;" horiz-adv-x="1152" 
+d="M1075 224q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23zM1075 608q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393
+q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
+    <glyph glyph-name="double_angle_down" unicode="&#xf103;" horiz-adv-x="1152" 
+d="M1075 672q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23zM1075 1056q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23
+t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" />
+    <glyph glyph-name="angle_left" unicode="&#xf104;" horiz-adv-x="640" 
+d="M627 992q0 -13 -10 -23l-393 -393l393 -393q10 -10 10 -23t-10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" />
+    <glyph glyph-name="angle_right" unicode="&#xf105;" horiz-adv-x="640" 
+d="M595 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
+    <glyph glyph-name="angle_up" unicode="&#xf106;" horiz-adv-x="1152" 
+d="M1075 352q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
+    <glyph glyph-name="angle_down" unicode="&#xf107;" horiz-adv-x="1152" 
+d="M1075 800q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" />
+    <glyph glyph-name="desktop" unicode="&#xf108;" horiz-adv-x="1920" 
+d="M1792 544v832q0 13 -9.5 22.5t-22.5 9.5h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-832q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5zM1920 1376v-1088q0 -66 -47 -113t-113 -47h-544q0 -37 16 -77.5t32 -71t16 -43.5q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19
+t-19 45q0 14 16 44t32 70t16 78h-544q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
+    <glyph glyph-name="laptop" unicode="&#xf109;" horiz-adv-x="1920" 
+d="M416 256q-66 0 -113 47t-47 113v704q0 66 47 113t113 47h1088q66 0 113 -47t47 -113v-704q0 -66 -47 -113t-113 -47h-1088zM384 1120v-704q0 -13 9.5 -22.5t22.5 -9.5h1088q13 0 22.5 9.5t9.5 22.5v704q0 13 -9.5 22.5t-22.5 9.5h-1088q-13 0 -22.5 -9.5t-9.5 -22.5z
+M1760 192h160v-96q0 -40 -47 -68t-113 -28h-1600q-66 0 -113 28t-47 68v96h160h1600zM1040 96q16 0 16 16t-16 16h-160q-16 0 -16 -16t16 -16h160z" />
+    <glyph glyph-name="tablet" unicode="&#xf10a;" horiz-adv-x="1152" 
+d="M640 128q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1024 288v960q0 13 -9.5 22.5t-22.5 9.5h-832q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h832q13 0 22.5 9.5t9.5 22.5zM1152 1248v-1088q0 -66 -47 -113t-113 -47h-832
+q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h832q66 0 113 -47t47 -113z" />
+    <glyph glyph-name="mobile_phone" unicode="&#xf10b;" horiz-adv-x="768" 
+d="M464 128q0 33 -23.5 56.5t-56.5 23.5t-56.5 -23.5t-23.5 -56.5t23.5 -56.5t56.5 -23.5t56.5 23.5t23.5 56.5zM672 288v704q0 13 -9.5 22.5t-22.5 9.5h-512q-13 0 -22.5 -9.5t-9.5 -22.5v-704q0 -13 9.5 -22.5t22.5 -9.5h512q13 0 22.5 9.5t9.5 22.5zM480 1136
+q0 16 -16 16h-160q-16 0 -16 -16t16 -16h160q16 0 16 16zM768 1152v-1024q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v1024q0 52 38 90t90 38h512q52 0 90 -38t38 -90z" />
+    <glyph glyph-name="circle_blank" unicode="&#xf10c;" 
+d="M768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103
+t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="quote_left" unicode="&#xf10d;" horiz-adv-x="1664" 
+d="M768 576v-384q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136v704q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5h64q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-64q-106 0 -181 -75t-75 -181v-32q0 -40 28 -68t68 -28h224q80 0 136 -56t56 -136z
+M1664 576v-384q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136v704q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5h64q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-64q-106 0 -181 -75t-75 -181v-32q0 -40 28 -68t68 -28h224q80 0 136 -56t56 -136z" />
+    <glyph glyph-name="quote_right" unicode="&#xf10e;" horiz-adv-x="1664" 
+d="M768 1216v-704q0 -104 -40.5 -198.5t-109.5 -163.5t-163.5 -109.5t-198.5 -40.5h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64q106 0 181 75t75 181v32q0 40 -28 68t-68 28h-224q-80 0 -136 56t-56 136v384q0 80 56 136t136 56h384q80 0 136 -56t56 -136zM1664 1216
+v-704q0 -104 -40.5 -198.5t-109.5 -163.5t-163.5 -109.5t-198.5 -40.5h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64q106 0 181 75t75 181v32q0 40 -28 68t-68 28h-224q-80 0 -136 56t-56 136v384q0 80 56 136t136 56h384q80 0 136 -56t56 -136z" />
+    <glyph glyph-name="spinner" unicode="&#xf110;" horiz-adv-x="1792" 
+d="M526 142q0 -53 -37.5 -90.5t-90.5 -37.5q-52 0 -90 38t-38 90q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1024 -64q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM320 640q0 -53 -37.5 -90.5t-90.5 -37.5
+t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1522 142q0 -52 -38 -90t-90 -38q-53 0 -90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM558 1138q0 -66 -47 -113t-113 -47t-113 47t-47 113t47 113t113 47t113 -47t47 -113z
+M1728 640q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1088 1344q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1618 1138q0 -93 -66 -158.5t-158 -65.5q-93 0 -158.5 65.5t-65.5 158.5
+q0 92 65.5 158t158.5 66q92 0 158 -66t66 -158z" />
+    <glyph glyph-name="circle" unicode="&#xf111;" 
+d="M1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="reply" unicode="&#xf112;" horiz-adv-x="1792" 
+d="M1792 416q0 -166 -127 -451q-3 -7 -10.5 -24t-13.5 -30t-13 -22q-12 -17 -28 -17q-15 0 -23.5 10t-8.5 25q0 9 2.5 26.5t2.5 23.5q5 68 5 123q0 101 -17.5 181t-48.5 138.5t-80 101t-105.5 69.5t-133 42.5t-154 21.5t-175.5 6h-224v-256q0 -26 -19 -45t-45 -19t-45 19
+l-512 512q-19 19 -19 45t19 45l512 512q19 19 45 19t45 -19t19 -45v-256h224q713 0 875 -403q53 -134 53 -333z" />
+    <glyph glyph-name="github_alt" unicode="&#xf113;" horiz-adv-x="1664" 
+d="M640 320q0 -40 -12.5 -82t-43 -76t-72.5 -34t-72.5 34t-43 76t-12.5 82t12.5 82t43 76t72.5 34t72.5 -34t43 -76t12.5 -82zM1280 320q0 -40 -12.5 -82t-43 -76t-72.5 -34t-72.5 34t-43 76t-12.5 82t12.5 82t43 76t72.5 34t72.5 -34t43 -76t12.5 -82zM1440 320
+q0 120 -69 204t-187 84q-41 0 -195 -21q-71 -11 -157 -11t-157 11q-152 21 -195 21q-118 0 -187 -84t-69 -204q0 -88 32 -153.5t81 -103t122 -60t140 -29.5t149 -7h168q82 0 149 7t140 29.5t122 60t81 103t32 153.5zM1664 496q0 -207 -61 -331q-38 -77 -105.5 -133t-141 -86
+t-170 -47.5t-171.5 -22t-167 -4.5q-78 0 -142 3t-147.5 12.5t-152.5 30t-137 51.5t-121 81t-86 115q-62 123 -62 331q0 237 136 396q-27 82 -27 170q0 116 51 218q108 0 190 -39.5t189 -123.5q147 35 309 35q148 0 280 -32q105 82 187 121t189 39q51 -102 51 -218
+q0 -87 -27 -168q136 -160 136 -398z" />
+    <glyph glyph-name="folder_close_alt" unicode="&#xf114;" horiz-adv-x="1664" 
+d="M1536 224v704q0 40 -28 68t-68 28h-704q-40 0 -68 28t-28 68v64q0 40 -28 68t-68 28h-320q-40 0 -68 -28t-28 -68v-960q0 -40 28 -68t68 -28h1216q40 0 68 28t28 68zM1664 928v-704q0 -92 -66 -158t-158 -66h-1216q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320
+q92 0 158 -66t66 -158v-32h672q92 0 158 -66t66 -158z" />
+    <glyph glyph-name="folder_open_alt" unicode="&#xf115;" horiz-adv-x="1920" 
+d="M1781 605q0 35 -53 35h-1088q-40 0 -85.5 -21.5t-71.5 -52.5l-294 -363q-18 -24 -18 -40q0 -35 53 -35h1088q40 0 86 22t71 53l294 363q18 22 18 39zM640 768h768v160q0 40 -28 68t-68 28h-576q-40 0 -68 28t-28 68v64q0 40 -28 68t-68 28h-320q-40 0 -68 -28t-28 -68
+v-853l256 315q44 53 116 87.5t140 34.5zM1909 605q0 -62 -46 -120l-295 -363q-43 -53 -116 -87.5t-140 -34.5h-1088q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h544q92 0 158 -66t66 -158v-160h192q54 0 99 -24.5t67 -70.5q15 -32 15 -68z
+" />
+    <glyph glyph-name="expand_alt" unicode="&#xf116;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="collapse_alt" unicode="&#xf117;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="smile" unicode="&#xf118;" 
+d="M1134 461q-37 -121 -138 -195t-228 -74t-228 74t-138 195q-8 25 4 48.5t38 31.5q25 8 48.5 -4t31.5 -38q25 -80 92.5 -129.5t151.5 -49.5t151.5 49.5t92.5 129.5q8 26 32 38t49 4t37 -31.5t4 -48.5zM640 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5
+t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1152 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5
+t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="frown" unicode="&#xf119;" 
+d="M1134 307q8 -25 -4 -48.5t-37 -31.5t-49 4t-32 38q-25 80 -92.5 129.5t-151.5 49.5t-151.5 -49.5t-92.5 -129.5q-8 -26 -31.5 -38t-48.5 -4q-26 8 -38 31.5t-4 48.5q37 121 138 195t228 74t228 -74t138 -195zM640 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5
+t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1152 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204
+t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="meh" unicode="&#xf11a;" 
+d="M1152 448q0 -26 -19 -45t-45 -19h-640q-26 0 -45 19t-19 45t19 45t45 19h640q26 0 45 -19t19 -45zM640 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1152 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5
+t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640
+q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="gamepad" unicode="&#xf11b;" horiz-adv-x="1920" 
+d="M832 448v128q0 14 -9 23t-23 9h-192v192q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-192h-192q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h192v-192q0 -14 9 -23t23 -9h128q14 0 23 9t9 23v192h192q14 0 23 9t9 23zM1408 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5
+t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1664 640q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1920 512q0 -212 -150 -362t-362 -150q-192 0 -338 128h-220q-146 -128 -338 -128q-212 0 -362 150
+t-150 362t150 362t362 150h896q212 0 362 -150t150 -362z" />
+    <glyph glyph-name="keyboard" unicode="&#xf11c;" horiz-adv-x="1920" 
+d="M384 368v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM512 624v-96q0 -16 -16 -16h-224q-16 0 -16 16v96q0 16 16 16h224q16 0 16 -16zM384 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1408 368v-96q0 -16 -16 -16
+h-864q-16 0 -16 16v96q0 16 16 16h864q16 0 16 -16zM768 624v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM640 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1024 624v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16
+h96q16 0 16 -16zM896 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1280 624v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1664 368v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1152 880v-96
+q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1408 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1664 880v-352q0 -16 -16 -16h-224q-16 0 -16 16v96q0 16 16 16h112v240q0 16 16 16h96q16 0 16 -16zM1792 128v896h-1664v-896
+h1664zM1920 1024v-896q0 -53 -37.5 -90.5t-90.5 -37.5h-1664q-53 0 -90.5 37.5t-37.5 90.5v896q0 53 37.5 90.5t90.5 37.5h1664q53 0 90.5 -37.5t37.5 -90.5z" />
+    <glyph glyph-name="flag_alt" unicode="&#xf11d;" horiz-adv-x="1792" 
+d="M1664 491v616q-169 -91 -306 -91q-82 0 -145 32q-100 49 -184 76.5t-178 27.5q-173 0 -403 -127v-599q245 113 433 113q55 0 103.5 -7.5t98 -26t77 -31t82.5 -39.5l28 -14q44 -22 101 -22q120 0 293 92zM320 1280q0 -35 -17.5 -64t-46.5 -46v-1266q0 -14 -9 -23t-23 -9
+h-64q-14 0 -23 9t-9 23v1266q-29 17 -46.5 46t-17.5 64q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -39 -35 -57q-10 -5 -17 -9q-218 -116 -369 -116q-88 0 -158 35l-28 14q-64 33 -99 48t-91 29t-114 14q-102 0 -235.5 -44t-228.5 -102
+q-15 -9 -33 -9q-16 0 -32 8q-32 19 -32 56v742q0 35 31 55q35 21 78.5 42.5t114 52t152.5 49.5t155 19q112 0 209 -31t209 -86q38 -19 89 -19q122 0 310 112q22 12 31 17q31 16 62 -2q31 -20 31 -55z" />
+    <glyph glyph-name="flag_checkered" unicode="&#xf11e;" horiz-adv-x="1792" 
+d="M832 536v192q-181 -16 -384 -117v-185q205 96 384 110zM832 954v197q-172 -8 -384 -126v-189q215 111 384 118zM1664 491v184q-235 -116 -384 -71v224q-20 6 -39 15q-5 3 -33 17t-34.5 17t-31.5 15t-34.5 15.5t-32.5 13t-36 12.5t-35 8.5t-39.5 7.5t-39.5 4t-44 2
+q-23 0 -49 -3v-222h19q102 0 192.5 -29t197.5 -82q19 -9 39 -15v-188q42 -17 91 -17q120 0 293 92zM1664 918v189q-169 -91 -306 -91q-45 0 -78 8v-196q148 -42 384 90zM320 1280q0 -35 -17.5 -64t-46.5 -46v-1266q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v1266
+q-29 17 -46.5 46t-17.5 64q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -39 -35 -57q-10 -5 -17 -9q-218 -116 -369 -116q-88 0 -158 35l-28 14q-64 33 -99 48t-91 29t-114 14q-102 0 -235.5 -44t-228.5 -102q-15 -9 -33 -9q-16 0 -32 8
+q-32 19 -32 56v742q0 35 31 55q35 21 78.5 42.5t114 52t152.5 49.5t155 19q112 0 209 -31t209 -86q38 -19 89 -19q122 0 310 112q22 12 31 17q31 16 62 -2q31 -20 31 -55z" />
+    <glyph glyph-name="terminal" unicode="&#xf120;" horiz-adv-x="1664" 
+d="M585 553l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23t-10 -23zM1664 96v-64q0 -14 -9 -23t-23 -9h-960q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h960q14 0 23 -9
+t9 -23z" />
+    <glyph glyph-name="code" unicode="&#xf121;" horiz-adv-x="1920" 
+d="M617 137l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23t-10 -23zM1208 1204l-373 -1291q-4 -13 -15.5 -19.5t-23.5 -2.5l-62 17q-13 4 -19.5 15.5t-2.5 24.5
+l373 1291q4 13 15.5 19.5t23.5 2.5l62 -17q13 -4 19.5 -15.5t2.5 -24.5zM1865 553l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23t-10 -23z" />
+    <glyph glyph-name="reply_all" unicode="&#xf122;" horiz-adv-x="1792" 
+d="M640 454v-70q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-512 512q-19 19 -19 45t19 45l512 512q29 31 70 14q39 -17 39 -59v-69l-397 -398q-19 -19 -19 -45t19 -45zM1792 416q0 -58 -17 -133.5t-38.5 -138t-48 -125t-40.5 -90.5l-20 -40q-8 -17 -28 -17q-6 0 -9 1
+q-25 8 -23 34q43 400 -106 565q-64 71 -170.5 110.5t-267.5 52.5v-251q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-512 512q-19 19 -19 45t19 45l512 512q29 31 70 14q39 -17 39 -59v-262q411 -28 599 -221q169 -173 169 -509z" />
+    <glyph glyph-name="star_half_empty" unicode="&#xf123;" horiz-adv-x="1664" 
+d="M1186 579l257 250l-356 52l-66 10l-30 60l-159 322v-963l59 -31l318 -168l-60 355l-12 66zM1638 841l-363 -354l86 -500q5 -33 -6 -51.5t-34 -18.5q-17 0 -40 12l-449 236l-449 -236q-23 -12 -40 -12q-23 0 -34 18.5t-6 51.5l86 500l-364 354q-32 32 -23 59.5t54 34.5
+l502 73l225 455q20 41 49 41q28 0 49 -41l225 -455l502 -73q45 -7 54 -34.5t-24 -59.5z" />
+    <glyph glyph-name="location_arrow" unicode="&#xf124;" horiz-adv-x="1408" 
+d="M1401 1187l-640 -1280q-17 -35 -57 -35q-5 0 -15 2q-22 5 -35.5 22.5t-13.5 39.5v576h-576q-22 0 -39.5 13.5t-22.5 35.5t4 42t29 30l1280 640q13 7 29 7q27 0 45 -19q15 -14 18.5 -34.5t-6.5 -39.5z" />
+    <glyph glyph-name="crop" unicode="&#xf125;" horiz-adv-x="1664" 
+d="M557 256h595v595zM512 301l595 595h-595v-595zM1664 224v-192q0 -14 -9 -23t-23 -9h-224v-224q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v224h-864q-14 0 -23 9t-9 23v864h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224v224q0 14 9 23t23 9h192q14 0 23 -9t9 -23
+v-224h851l246 247q10 9 23 9t23 -9q9 -10 9 -23t-9 -23l-247 -246v-851h224q14 0 23 -9t9 -23z" />
+    <glyph glyph-name="code_fork" unicode="&#xf126;" horiz-adv-x="1024" 
+d="M288 64q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM288 1216q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM928 1088q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM1024 1088q0 -52 -26 -96.5t-70 -69.5
+q-2 -287 -226 -414q-67 -38 -203 -81q-128 -40 -169.5 -71t-41.5 -100v-26q44 -25 70 -69.5t26 -96.5q0 -80 -56 -136t-136 -56t-136 56t-56 136q0 52 26 96.5t70 69.5v820q-44 25 -70 69.5t-26 96.5q0 80 56 136t136 56t136 -56t56 -136q0 -52 -26 -96.5t-70 -69.5v-497
+q54 26 154 57q55 17 87.5 29.5t70.5 31t59 39.5t40.5 51t28 69.5t8.5 91.5q-44 25 -70 69.5t-26 96.5q0 80 56 136t136 56t136 -56t56 -136z" />
+    <glyph glyph-name="unlink" unicode="&#xf127;" horiz-adv-x="1664" 
+d="M439 265l-256 -256q-11 -9 -23 -9t-23 9q-9 10 -9 23t9 23l256 256q10 9 23 9t23 -9q9 -10 9 -23t-9 -23zM608 224v-320q0 -14 -9 -23t-23 -9t-23 9t-9 23v320q0 14 9 23t23 9t23 -9t9 -23zM384 448q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23t9 23t23 9h320
+q14 0 23 -9t9 -23zM1648 320q0 -120 -85 -203l-147 -146q-83 -83 -203 -83q-121 0 -204 85l-334 335q-21 21 -42 56l239 18l273 -274q27 -27 68 -27.5t68 26.5l147 146q28 28 28 67q0 40 -28 68l-274 275l18 239q35 -21 56 -42l336 -336q84 -86 84 -204zM1031 1044l-239 -18
+l-273 274q-28 28 -68 28q-39 0 -68 -27l-147 -146q-28 -28 -28 -67q0 -40 28 -68l274 -274l-18 -240q-35 21 -56 42l-336 336q-84 86 -84 204q0 120 85 203l147 146q83 83 203 83q121 0 204 -85l334 -335q21 -21 42 -56zM1664 960q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9
+t-9 23t9 23t23 9h320q14 0 23 -9t9 -23zM1120 1504v-320q0 -14 -9 -23t-23 -9t-23 9t-9 23v320q0 14 9 23t23 9t23 -9t9 -23zM1527 1353l-256 -256q-11 -9 -23 -9t-23 9q-9 10 -9 23t9 23l256 256q10 9 23 9t23 -9q9 -10 9 -23t-9 -23z" />
+    <glyph glyph-name="question" unicode="&#xf128;" horiz-adv-x="1024" 
+d="M704 280v-240q0 -16 -12 -28t-28 -12h-240q-16 0 -28 12t-12 28v240q0 16 12 28t28 12h240q16 0 28 -12t12 -28zM1020 880q0 -54 -15.5 -101t-35 -76.5t-55 -59.5t-57.5 -43.5t-61 -35.5q-41 -23 -68.5 -65t-27.5 -67q0 -17 -12 -32.5t-28 -15.5h-240q-15 0 -25.5 18.5
+t-10.5 37.5v45q0 83 65 156.5t143 108.5q59 27 84 56t25 76q0 42 -46.5 74t-107.5 32q-65 0 -108 -29q-35 -25 -107 -115q-13 -16 -31 -16q-12 0 -25 8l-164 125q-13 10 -15.5 25t5.5 28q160 266 464 266q80 0 161 -31t146 -83t106 -127.5t41 -158.5z" />
+    <glyph glyph-name="_279" unicode="&#xf129;" horiz-adv-x="640" 
+d="M640 192v-128q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64v384h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h384q26 0 45 -19t19 -45v-576h64q26 0 45 -19t19 -45zM512 1344v-192q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v192
+q0 26 19 45t45 19h256q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="exclamation" unicode="&#xf12a;" horiz-adv-x="640" 
+d="M512 288v-224q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v224q0 26 19 45t45 19h256q26 0 45 -19t19 -45zM542 1344l-28 -768q-1 -26 -20.5 -45t-45.5 -19h-256q-26 0 -45.5 19t-20.5 45l-28 768q-1 26 17.5 45t44.5 19h320q26 0 44.5 -19t17.5 -45z" />
+    <glyph glyph-name="superscript" unicode="&#xf12b;" 
+d="M897 167v-167h-248l-159 252l-24 42q-8 9 -11 21h-3q-1 -3 -2.5 -6.5t-3.5 -8t-3 -6.5q-10 -20 -25 -44l-155 -250h-258v167h128l197 291l-185 272h-137v168h276l139 -228q2 -4 23 -42q8 -9 11 -21h3q3 9 11 21l25 42l140 228h257v-168h-125l-184 -267l204 -296h109z
+M1534 846v-206h-514l-3 27q-4 28 -4 46q0 64 26 117t65 86.5t84 65t84 54.5t65 54t26 64q0 38 -29.5 62.5t-70.5 24.5q-51 0 -97 -39q-14 -11 -36 -38l-105 92q26 37 63 66q83 65 188 65q110 0 178 -59.5t68 -158.5q0 -56 -24.5 -103t-62 -76.5t-81.5 -58.5t-82 -50.5
+t-65.5 -51.5t-30.5 -63h232v80h126z" />
+    <glyph glyph-name="subscript" unicode="&#xf12c;" 
+d="M897 167v-167h-248l-159 252l-24 42q-8 9 -11 21h-3q-1 -3 -2.5 -6.5t-3.5 -8t-3 -6.5q-10 -20 -25 -44l-155 -250h-258v167h128l197 291l-185 272h-137v168h276l139 -228q2 -4 23 -42q8 -9 11 -21h3q3 9 11 21l25 42l140 228h257v-168h-125l-184 -267l204 -296h109z
+M1536 -50v-206h-514l-4 27q-3 45 -3 46q0 64 26 117t65 86.5t84 65t84 54.5t65 54t26 64q0 38 -29.5 62.5t-70.5 24.5q-51 0 -97 -39q-14 -11 -36 -38l-105 92q26 37 63 66q80 65 188 65q110 0 178 -59.5t68 -158.5q0 -66 -34.5 -118.5t-84 -86t-99.5 -62.5t-87 -63t-41 -73
+h232v80h126z" />
+    <glyph glyph-name="_283" unicode="&#xf12d;" horiz-adv-x="1920" 
+d="M896 128l336 384h-768l-336 -384h768zM1909 1205q15 -34 9.5 -71.5t-30.5 -65.5l-896 -1024q-38 -44 -96 -44h-768q-38 0 -69.5 20.5t-47.5 54.5q-15 34 -9.5 71.5t30.5 65.5l896 1024q38 44 96 44h768q38 0 69.5 -20.5t47.5 -54.5z" />
+    <glyph glyph-name="puzzle_piece" unicode="&#xf12e;" horiz-adv-x="1664" 
+d="M1664 438q0 -81 -44.5 -135t-123.5 -54q-41 0 -77.5 17.5t-59 38t-56.5 38t-71 17.5q-110 0 -110 -124q0 -39 16 -115t15 -115v-5q-22 0 -33 -1q-34 -3 -97.5 -11.5t-115.5 -13.5t-98 -5q-61 0 -103 26.5t-42 83.5q0 37 17.5 71t38 56.5t38 59t17.5 77.5q0 79 -54 123.5
+t-135 44.5q-84 0 -143 -45.5t-59 -127.5q0 -43 15 -83t33.5 -64.5t33.5 -53t15 -50.5q0 -45 -46 -89q-37 -35 -117 -35q-95 0 -245 24q-9 2 -27.5 4t-27.5 4l-13 2q-1 0 -3 1q-2 0 -2 1v1024q2 -1 17.5 -3.5t34 -5t21.5 -3.5q150 -24 245 -24q80 0 117 35q46 44 46 89
+q0 22 -15 50.5t-33.5 53t-33.5 64.5t-15 83q0 82 59 127.5t144 45.5q80 0 134 -44.5t54 -123.5q0 -41 -17.5 -77.5t-38 -59t-38 -56.5t-17.5 -71q0 -57 42 -83.5t103 -26.5q64 0 180 15t163 17v-2q-1 -2 -3.5 -17.5t-5 -34t-3.5 -21.5q-24 -150 -24 -245q0 -80 35 -117
+q44 -46 89 -46q22 0 50.5 15t53 33.5t64.5 33.5t83 15q82 0 127.5 -59t45.5 -143z" />
+    <glyph glyph-name="microphone" unicode="&#xf130;" horiz-adv-x="1152" 
+d="M1152 832v-128q0 -221 -147.5 -384.5t-364.5 -187.5v-132h256q26 0 45 -19t19 -45t-19 -45t-45 -19h-640q-26 0 -45 19t-19 45t19 45t45 19h256v132q-217 24 -364.5 187.5t-147.5 384.5v128q0 26 19 45t45 19t45 -19t19 -45v-128q0 -185 131.5 -316.5t316.5 -131.5
+t316.5 131.5t131.5 316.5v128q0 26 19 45t45 19t45 -19t19 -45zM896 1216v-512q0 -132 -94 -226t-226 -94t-226 94t-94 226v512q0 132 94 226t226 94t226 -94t94 -226z" />
+    <glyph glyph-name="microphone_off" unicode="&#xf131;" horiz-adv-x="1408" 
+d="M271 591l-101 -101q-42 103 -42 214v128q0 26 19 45t45 19t45 -19t19 -45v-128q0 -53 15 -113zM1385 1193l-361 -361v-128q0 -132 -94 -226t-226 -94q-55 0 -109 19l-96 -96q97 -51 205 -51q185 0 316.5 131.5t131.5 316.5v128q0 26 19 45t45 19t45 -19t19 -45v-128
+q0 -221 -147.5 -384.5t-364.5 -187.5v-132h256q26 0 45 -19t19 -45t-19 -45t-45 -19h-640q-26 0 -45 19t-19 45t19 45t45 19h256v132q-125 13 -235 81l-254 -254q-10 -10 -23 -10t-23 10l-82 82q-10 10 -10 23t10 23l1234 1234q10 10 23 10t23 -10l82 -82q10 -10 10 -23
+t-10 -23zM1005 1325l-621 -621v512q0 132 94 226t226 94q102 0 184.5 -59t116.5 -152z" />
+    <glyph glyph-name="shield" unicode="&#xf132;" horiz-adv-x="1280" 
+d="M1088 576v640h-448v-1137q119 63 213 137q235 184 235 360zM1280 1344v-768q0 -86 -33.5 -170.5t-83 -150t-118 -127.5t-126.5 -103t-121 -77.5t-89.5 -49.5t-42.5 -20q-12 -6 -26 -6t-26 6q-16 7 -42.5 20t-89.5 49.5t-121 77.5t-126.5 103t-118 127.5t-83 150
+t-33.5 170.5v768q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="calendar_empty" unicode="&#xf133;" horiz-adv-x="1664" 
+d="M128 -128h1408v1024h-1408v-1024zM512 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1280 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1664 1152v-1280
+q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" />
+    <glyph glyph-name="fire_extinguisher" unicode="&#xf134;" horiz-adv-x="1408" 
+d="M512 1344q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 1376v-320q0 -16 -12 -25q-8 -7 -20 -7q-4 0 -7 1l-448 96q-11 2 -18 11t-7 20h-256v-102q111 -23 183.5 -111t72.5 -203v-800q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v800
+q0 106 62.5 190.5t161.5 114.5v111h-32q-59 0 -115 -23.5t-91.5 -53t-66 -66.5t-40.5 -53.5t-14 -24.5q-17 -35 -57 -35q-16 0 -29 7q-23 12 -31.5 37t3.5 49q5 10 14.5 26t37.5 53.5t60.5 70t85 67t108.5 52.5q-25 42 -25 86q0 66 47 113t113 47t113 -47t47 -113
+q0 -33 -14 -64h302q0 11 7 20t18 11l448 96q3 1 7 1q12 0 20 -7q12 -9 12 -25z" />
+    <glyph glyph-name="rocket" unicode="&#xf135;" horiz-adv-x="1664" 
+d="M1440 1088q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM1664 1376q0 -249 -75.5 -430.5t-253.5 -360.5q-81 -80 -195 -176l-20 -379q-2 -16 -16 -26l-384 -224q-7 -4 -16 -4q-12 0 -23 9l-64 64q-13 14 -8 32l85 276l-281 281l-276 -85q-3 -1 -9 -1
+q-14 0 -23 9l-64 64q-17 19 -5 39l224 384q10 14 26 16l379 20q96 114 176 195q188 187 358 258t431 71q14 0 24 -9.5t10 -22.5z" />
+    <glyph glyph-name="maxcdn" unicode="&#xf136;" horiz-adv-x="1792" 
+d="M1745 763l-164 -763h-334l178 832q13 56 -15 88q-27 33 -83 33h-169l-204 -953h-334l204 953h-286l-204 -953h-334l204 953l-153 327h1276q101 0 189.5 -40.5t147.5 -113.5q60 -73 81 -168.5t0 -194.5z" />
+    <glyph glyph-name="chevron_sign_left" unicode="&#xf137;" 
+d="M909 141l102 102q19 19 19 45t-19 45l-307 307l307 307q19 19 19 45t-19 45l-102 102q-19 19 -45 19t-45 -19l-454 -454q-19 -19 -19 -45t19 -45l454 -454q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5
+t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="chevron_sign_right" unicode="&#xf138;" 
+d="M717 141l454 454q19 19 19 45t-19 45l-454 454q-19 19 -45 19t-45 -19l-102 -102q-19 -19 -19 -45t19 -45l307 -307l-307 -307q-19 -19 -19 -45t19 -45l102 -102q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5
+t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="chevron_sign_up" unicode="&#xf139;" 
+d="M1165 397l102 102q19 19 19 45t-19 45l-454 454q-19 19 -45 19t-45 -19l-454 -454q-19 -19 -19 -45t19 -45l102 -102q19 -19 45 -19t45 19l307 307l307 -307q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5
+t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="chevron_sign_down" unicode="&#xf13a;" 
+d="M813 237l454 454q19 19 19 45t-19 45l-102 102q-19 19 -45 19t-45 -19l-307 -307l-307 307q-19 19 -45 19t-45 -19l-102 -102q-19 -19 -19 -45t19 -45l454 -454q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5
+t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="html5" unicode="&#xf13b;" horiz-adv-x="1408" 
+d="M1130 939l16 175h-884l47 -534h612l-22 -228l-197 -53l-196 53l-13 140h-175l22 -278l362 -100h4v1l359 99l50 544h-644l-15 181h674zM0 1408h1408l-128 -1438l-578 -162l-574 162z" />
+    <glyph glyph-name="css3" unicode="&#xf13c;" horiz-adv-x="1792" 
+d="M275 1408h1505l-266 -1333l-804 -267l-698 267l71 356h297l-29 -147l422 -161l486 161l68 339h-1208l58 297h1209l38 191h-1208z" />
+    <glyph glyph-name="anchor" unicode="&#xf13d;" horiz-adv-x="1792" 
+d="M960 1280q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1792 352v-352q0 -22 -20 -30q-8 -2 -12 -2q-12 0 -23 9l-93 93q-119 -143 -318.5 -226.5t-429.5 -83.5t-429.5 83.5t-318.5 226.5l-93 -93q-9 -9 -23 -9q-4 0 -12 2q-20 8 -20 30v352
+q0 14 9 23t23 9h352q22 0 30 -20q8 -19 -7 -35l-100 -100q67 -91 189.5 -153.5t271.5 -82.5v647h-192q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h192v163q-58 34 -93 92.5t-35 128.5q0 106 75 181t181 75t181 -75t75 -181q0 -70 -35 -128.5t-93 -92.5v-163h192q26 0 45 -19
+t19 -45v-128q0 -26 -19 -45t-45 -19h-192v-647q149 20 271.5 82.5t189.5 153.5l-100 100q-15 16 -7 35q8 20 30 20h352q14 0 23 -9t9 -23z" />
+    <glyph glyph-name="unlock_alt" unicode="&#xf13e;" horiz-adv-x="1152" 
+d="M1056 768q40 0 68 -28t28 -68v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h32v320q0 185 131.5 316.5t316.5 131.5t316.5 -131.5t131.5 -316.5q0 -26 -19 -45t-45 -19h-64q-26 0 -45 19t-19 45q0 106 -75 181t-181 75t-181 -75t-75 -181
+v-320h736z" />
+    <glyph glyph-name="bullseye" unicode="&#xf140;" 
+d="M1024 640q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM1152 640q0 159 -112.5 271.5t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5zM1280 640q0 -212 -150 -362t-362 -150t-362 150
+t-150 362t150 362t362 150t362 -150t150 -362zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640
+q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="ellipsis_horizontal" unicode="&#xf141;" horiz-adv-x="1408" 
+d="M384 800v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM896 800v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM1408 800v-192q0 -40 -28 -68t-68 -28h-192
+q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68z" />
+    <glyph glyph-name="ellipsis_vertical" unicode="&#xf142;" horiz-adv-x="384" 
+d="M384 288v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM384 800v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM384 1312v-192q0 -40 -28 -68t-68 -28h-192
+q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68z" />
+    <glyph glyph-name="_303" unicode="&#xf143;" 
+d="M512 256q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM863 162q-13 233 -176.5 396.5t-396.5 176.5q-14 1 -24 -9t-10 -23v-128q0 -13 8.5 -22t21.5 -10q154 -11 264 -121t121 -264q1 -13 10 -21.5t22 -8.5h128
+q13 0 23 10t9 24zM1247 161q-5 154 -56 297.5t-139.5 260t-205 205t-260 139.5t-297.5 56q-14 1 -23 -9q-10 -10 -10 -23v-128q0 -13 9 -22t22 -10q204 -7 378 -111.5t278.5 -278.5t111.5 -378q1 -13 10 -22t22 -9h128q13 0 23 10q11 9 9 23zM1536 1120v-960
+q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="play_sign" unicode="&#xf144;" 
+d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM1152 585q32 18 32 55t-32 55l-544 320q-31 19 -64 1q-32 -19 -32 -56v-640q0 -37 32 -56
+q16 -8 32 -8q17 0 32 9z" />
+    <glyph glyph-name="ticket" unicode="&#xf145;" horiz-adv-x="1792" 
+d="M1024 1084l316 -316l-572 -572l-316 316zM813 105l618 618q19 19 19 45t-19 45l-362 362q-18 18 -45 18t-45 -18l-618 -618q-19 -19 -19 -45t19 -45l362 -362q18 -18 45 -18t45 18zM1702 742l-907 -908q-37 -37 -90.5 -37t-90.5 37l-126 126q56 56 56 136t-56 136
+t-136 56t-136 -56l-125 126q-37 37 -37 90.5t37 90.5l907 906q37 37 90.5 37t90.5 -37l125 -125q-56 -56 -56 -136t56 -136t136 -56t136 56l126 -125q37 -37 37 -90.5t-37 -90.5z" />
+    <glyph glyph-name="minus_sign_alt" unicode="&#xf146;" 
+d="M1280 576v128q0 26 -19 45t-45 19h-896q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h896q26 0 45 19t19 45zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5
+t84.5 -203.5z" />
+    <glyph glyph-name="check_minus" unicode="&#xf147;" horiz-adv-x="1408" 
+d="M1152 736v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h832q14 0 23 -9t9 -23zM1280 288v832q0 66 -47 113t-113 47h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113zM1408 1120v-832q0 -119 -84.5 -203.5
+t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="level_up" unicode="&#xf148;" horiz-adv-x="1024" 
+d="M1018 933q-18 -37 -58 -37h-192v-864q0 -14 -9 -23t-23 -9h-704q-21 0 -29 18q-8 20 4 35l160 192q9 11 25 11h320v640h-192q-40 0 -58 37q-17 37 9 68l320 384q18 22 49 22t49 -22l320 -384q27 -32 9 -68z" />
+    <glyph glyph-name="level_down" unicode="&#xf149;" horiz-adv-x="1024" 
+d="M32 1280h704q13 0 22.5 -9.5t9.5 -23.5v-863h192q40 0 58 -37t-9 -69l-320 -384q-18 -22 -49 -22t-49 22l-320 384q-26 31 -9 69q18 37 58 37h192v640h-320q-14 0 -25 11l-160 192q-13 14 -4 34q9 19 29 19z" />
+    <glyph glyph-name="check_sign" unicode="&#xf14a;" 
+d="M685 237l614 614q19 19 19 45t-19 45l-102 102q-19 19 -45 19t-45 -19l-467 -467l-211 211q-19 19 -45 19t-45 -19l-102 -102q-19 -19 -19 -45t19 -45l358 -358q19 -19 45 -19t45 19zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5
+t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="edit_sign" unicode="&#xf14b;" 
+d="M404 428l152 -152l-52 -52h-56v96h-96v56zM818 818q14 -13 -3 -30l-291 -291q-17 -17 -30 -3q-14 13 3 30l291 291q17 17 30 3zM544 128l544 544l-288 288l-544 -544v-288h288zM1152 736l92 92q28 28 28 68t-28 68l-152 152q-28 28 -68 28t-68 -28l-92 -92zM1536 1120
+v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="_312" unicode="&#xf14c;" 
+d="M1280 608v480q0 26 -19 45t-45 19h-480q-42 0 -59 -39q-17 -41 14 -70l144 -144l-534 -534q-19 -19 -19 -45t19 -45l102 -102q19 -19 45 -19t45 19l534 534l144 -144q18 -19 45 -19q12 0 25 5q39 17 39 59zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960
+q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="share_sign" unicode="&#xf14d;" 
+d="M1005 435l352 352q19 19 19 45t-19 45l-352 352q-30 31 -69 14q-40 -17 -40 -59v-160q-119 0 -216 -19.5t-162.5 -51t-114 -79t-76.5 -95.5t-44.5 -109t-21.5 -111.5t-5 -110.5q0 -181 167 -404q11 -12 25 -12q7 0 13 3q22 9 19 33q-44 354 62 473q46 52 130 75.5
+t224 23.5v-160q0 -42 40 -59q12 -5 24 -5q26 0 45 19zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="compass" unicode="&#xf14e;" 
+d="M640 448l256 128l-256 128v-256zM1024 1039v-542l-512 -256v542zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103
+t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="collapse" unicode="&#xf150;" 
+d="M1145 861q18 -35 -5 -66l-320 -448q-19 -27 -52 -27t-52 27l-320 448q-23 31 -5 66q17 35 57 35h640q40 0 57 -35zM1280 160v960q0 13 -9.5 22.5t-22.5 9.5h-960q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5zM1536 1120
+v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="collapse_top" unicode="&#xf151;" 
+d="M1145 419q-17 -35 -57 -35h-640q-40 0 -57 35q-18 35 5 66l320 448q19 27 52 27t52 -27l320 -448q23 -31 5 -66zM1280 160v960q0 13 -9.5 22.5t-22.5 9.5h-960q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5zM1536 1120v-960
+q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="_317" unicode="&#xf152;" 
+d="M1088 640q0 -33 -27 -52l-448 -320q-31 -23 -66 -5q-35 17 -35 57v640q0 40 35 57q35 18 66 -5l448 -320q27 -19 27 -52zM1280 160v960q0 14 -9 23t-23 9h-960q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h960q14 0 23 9t9 23zM1536 1120v-960q0 -119 -84.5 -203.5
+t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="eur" unicode="&#xf153;" horiz-adv-x="1024" 
+d="M976 229l35 -159q3 -12 -3 -22.5t-17 -14.5l-5 -1q-4 -2 -10.5 -3.5t-16 -4.5t-21.5 -5.5t-25.5 -5t-30 -5t-33.5 -4.5t-36.5 -3t-38.5 -1q-234 0 -409 130.5t-238 351.5h-95q-13 0 -22.5 9.5t-9.5 22.5v113q0 13 9.5 22.5t22.5 9.5h66q-2 57 1 105h-67q-14 0 -23 9
+t-9 23v114q0 14 9 23t23 9h98q67 210 243.5 338t400.5 128q102 0 194 -23q11 -3 20 -15q6 -11 3 -24l-43 -159q-3 -13 -14 -19.5t-24 -2.5l-4 1q-4 1 -11.5 2.5l-17.5 3.5t-22.5 3.5t-26 3t-29 2.5t-29.5 1q-126 0 -226 -64t-150 -176h468q16 0 25 -12q10 -12 7 -26
+l-24 -114q-5 -26 -32 -26h-488q-3 -37 0 -105h459q15 0 25 -12q9 -12 6 -27l-24 -112q-2 -11 -11 -18.5t-20 -7.5h-387q48 -117 149.5 -185.5t228.5 -68.5q18 0 36 1.5t33.5 3.5t29.5 4.5t24.5 5t18.5 4.5l12 3l5 2q13 5 26 -2q12 -7 15 -21z" />
+    <glyph glyph-name="gbp" unicode="&#xf154;" horiz-adv-x="1024" 
+d="M1020 399v-367q0 -14 -9 -23t-23 -9h-956q-14 0 -23 9t-9 23v150q0 13 9.5 22.5t22.5 9.5h97v383h-95q-14 0 -23 9.5t-9 22.5v131q0 14 9 23t23 9h95v223q0 171 123.5 282t314.5 111q185 0 335 -125q9 -8 10 -20.5t-7 -22.5l-103 -127q-9 -11 -22 -12q-13 -2 -23 7
+q-5 5 -26 19t-69 32t-93 18q-85 0 -137 -47t-52 -123v-215h305q13 0 22.5 -9t9.5 -23v-131q0 -13 -9.5 -22.5t-22.5 -9.5h-305v-379h414v181q0 13 9 22.5t23 9.5h162q14 0 23 -9.5t9 -22.5z" />
+    <glyph glyph-name="usd" unicode="&#xf155;" horiz-adv-x="1024" 
+d="M978 351q0 -153 -99.5 -263.5t-258.5 -136.5v-175q0 -14 -9 -23t-23 -9h-135q-13 0 -22.5 9.5t-9.5 22.5v175q-66 9 -127.5 31t-101.5 44.5t-74 48t-46.5 37.5t-17.5 18q-17 21 -2 41l103 135q7 10 23 12q15 2 24 -9l2 -2q113 -99 243 -125q37 -8 74 -8q81 0 142.5 43
+t61.5 122q0 28 -15 53t-33.5 42t-58.5 37.5t-66 32t-80 32.5q-39 16 -61.5 25t-61.5 26.5t-62.5 31t-56.5 35.5t-53.5 42.5t-43.5 49t-35.5 58t-21 66.5t-8.5 78q0 138 98 242t255 134v180q0 13 9.5 22.5t22.5 9.5h135q14 0 23 -9t9 -23v-176q57 -6 110.5 -23t87 -33.5
+t63.5 -37.5t39 -29t15 -14q17 -18 5 -38l-81 -146q-8 -15 -23 -16q-14 -3 -27 7q-3 3 -14.5 12t-39 26.5t-58.5 32t-74.5 26t-85.5 11.5q-95 0 -155 -43t-60 -111q0 -26 8.5 -48t29.5 -41.5t39.5 -33t56 -31t60.5 -27t70 -27.5q53 -20 81 -31.5t76 -35t75.5 -42.5t62 -50
+t53 -63.5t31.5 -76.5t13 -94z" />
+    <glyph glyph-name="inr" unicode="&#xf156;" horiz-adv-x="898" 
+d="M898 1066v-102q0 -14 -9 -23t-23 -9h-168q-23 -144 -129 -234t-276 -110q167 -178 459 -536q14 -16 4 -34q-8 -18 -29 -18h-195q-16 0 -25 12q-306 367 -498 571q-9 9 -9 22v127q0 13 9.5 22.5t22.5 9.5h112q132 0 212.5 43t102.5 125h-427q-14 0 -23 9t-9 23v102
+q0 14 9 23t23 9h413q-57 113 -268 113h-145q-13 0 -22.5 9.5t-9.5 22.5v133q0 14 9 23t23 9h832q14 0 23 -9t9 -23v-102q0 -14 -9 -23t-23 -9h-233q47 -61 64 -144h171q14 0 23 -9t9 -23z" />
+    <glyph glyph-name="jpy" unicode="&#xf157;" horiz-adv-x="1027" 
+d="M603 0h-172q-13 0 -22.5 9t-9.5 23v330h-288q-13 0 -22.5 9t-9.5 23v103q0 13 9.5 22.5t22.5 9.5h288v85h-288q-13 0 -22.5 9t-9.5 23v104q0 13 9.5 22.5t22.5 9.5h214l-321 578q-8 16 0 32q10 16 28 16h194q19 0 29 -18l215 -425q19 -38 56 -125q10 24 30.5 68t27.5 61
+l191 420q8 19 29 19h191q17 0 27 -16q9 -14 1 -31l-313 -579h215q13 0 22.5 -9.5t9.5 -22.5v-104q0 -14 -9.5 -23t-22.5 -9h-290v-85h290q13 0 22.5 -9.5t9.5 -22.5v-103q0 -14 -9.5 -23t-22.5 -9h-290v-330q0 -13 -9.5 -22.5t-22.5 -9.5z" />
+    <glyph glyph-name="rub" unicode="&#xf158;" horiz-adv-x="1280" 
+d="M1043 971q0 100 -65 162t-171 62h-320v-448h320q106 0 171 62t65 162zM1280 971q0 -193 -126.5 -315t-326.5 -122h-340v-118h505q14 0 23 -9t9 -23v-128q0 -14 -9 -23t-23 -9h-505v-192q0 -14 -9.5 -23t-22.5 -9h-167q-14 0 -23 9t-9 23v192h-224q-14 0 -23 9t-9 23v128
+q0 14 9 23t23 9h224v118h-224q-14 0 -23 9t-9 23v149q0 13 9 22.5t23 9.5h224v629q0 14 9 23t23 9h539q200 0 326.5 -122t126.5 -315z" />
+    <glyph glyph-name="krw" unicode="&#xf159;" horiz-adv-x="1792" 
+d="M514 341l81 299h-159l75 -300q1 -1 1 -3t1 -3q0 1 0.5 3.5t0.5 3.5zM630 768l35 128h-292l32 -128h225zM822 768h139l-35 128h-70zM1271 340l78 300h-162l81 -299q0 -1 0.5 -3.5t1.5 -3.5q0 1 0.5 3t0.5 3zM1382 768l33 128h-297l34 -128h230zM1792 736v-64q0 -14 -9 -23
+t-23 -9h-213l-164 -616q-7 -24 -31 -24h-159q-24 0 -31 24l-166 616h-209l-167 -616q-7 -24 -31 -24h-159q-11 0 -19.5 7t-10.5 17l-160 616h-208q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h175l-33 128h-142q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h109l-89 344q-5 15 5 28
+q10 12 26 12h137q26 0 31 -24l90 -360h359l97 360q7 24 31 24h126q24 0 31 -24l98 -360h365l93 360q5 24 31 24h137q16 0 26 -12q10 -13 5 -28l-91 -344h111q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-145l-34 -128h179q14 0 23 -9t9 -23z" />
+    <glyph glyph-name="btc" unicode="&#xf15a;" horiz-adv-x="1280" 
+d="M1167 896q18 -182 -131 -258q117 -28 175 -103t45 -214q-7 -71 -32.5 -125t-64.5 -89t-97 -58.5t-121.5 -34.5t-145.5 -15v-255h-154v251q-80 0 -122 1v-252h-154v255q-18 0 -54 0.5t-55 0.5h-200l31 183h111q50 0 58 51v402h16q-6 1 -16 1v287q-13 68 -89 68h-111v164
+l212 -1q64 0 97 1v252h154v-247q82 2 122 2v245h154v-252q79 -7 140 -22.5t113 -45t82.5 -78t36.5 -114.5zM952 351q0 36 -15 64t-37 46t-57.5 30.5t-65.5 18.5t-74 9t-69 3t-64.5 -1t-47.5 -1v-338q8 0 37 -0.5t48 -0.5t53 1.5t58.5 4t57 8.5t55.5 14t47.5 21t39.5 30
+t24.5 40t9.5 51zM881 827q0 33 -12.5 58.5t-30.5 42t-48 28t-55 16.5t-61.5 8t-58 2.5t-54 -1t-39.5 -0.5v-307q5 0 34.5 -0.5t46.5 0t50 2t55 5.5t51.5 11t48.5 18.5t37 27t27 38.5t9 51z" />
+    <glyph glyph-name="file" unicode="&#xf15b;" 
+d="M1024 1024v472q22 -14 36 -28l408 -408q14 -14 28 -36h-472zM896 992q0 -40 28 -68t68 -28h544v-1056q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h800v-544z" />
+    <glyph glyph-name="file_text" unicode="&#xf15c;" 
+d="M1468 1060q14 -14 28 -36h-472v472q22 -14 36 -28zM992 896h544v-1056q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h800v-544q0 -40 28 -68t68 -28zM1152 160v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704
+q14 0 23 9t9 23zM1152 416v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704q14 0 23 9t9 23zM1152 672v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704q14 0 23 9t9 23z" />
+    <glyph glyph-name="sort_by_alphabet" unicode="&#xf15d;" horiz-adv-x="1664" 
+d="M1191 1128h177l-72 218l-12 47q-2 16 -2 20h-4l-3 -20q0 -1 -3.5 -18t-7.5 -29zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23zM1572 -23
+v-233h-584v90l369 529q12 18 21 27l11 9v3q-2 0 -6.5 -0.5t-7.5 -0.5q-12 -3 -30 -3h-232v-115h-120v229h567v-89l-369 -530q-6 -8 -21 -26l-11 -11v-2l14 2q9 2 30 2h248v119h121zM1661 874v-106h-288v106h75l-47 144h-243l-47 -144h75v-106h-287v106h70l230 662h162
+l230 -662h70z" />
+    <glyph glyph-name="_329" unicode="&#xf15e;" horiz-adv-x="1664" 
+d="M1191 104h177l-72 218l-12 47q-2 16 -2 20h-4l-3 -20q0 -1 -3.5 -18t-7.5 -29zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23zM1661 -150
+v-106h-288v106h75l-47 144h-243l-47 -144h75v-106h-287v106h70l230 662h162l230 -662h70zM1572 1001v-233h-584v90l369 529q12 18 21 27l11 9v3q-2 0 -6.5 -0.5t-7.5 -0.5q-12 -3 -30 -3h-232v-115h-120v229h567v-89l-369 -530q-6 -8 -21 -26l-11 -10v-3l14 3q9 1 30 1h248
+v119h121z" />
+    <glyph glyph-name="sort_by_attributes" unicode="&#xf160;" horiz-adv-x="1792" 
+d="M736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23zM1792 -32v-192q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h832
+q14 0 23 -9t9 -23zM1600 480v-192q0 -14 -9 -23t-23 -9h-640q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h640q14 0 23 -9t9 -23zM1408 992v-192q0 -14 -9 -23t-23 -9h-448q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h448q14 0 23 -9t9 -23zM1216 1504v-192q0 -14 -9 -23t-23 -9h-256
+q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h256q14 0 23 -9t9 -23z" />
+    <glyph glyph-name="sort_by_attributes_alt" unicode="&#xf161;" horiz-adv-x="1792" 
+d="M1216 -32v-192q0 -14 -9 -23t-23 -9h-256q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h256q14 0 23 -9t9 -23zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192
+q14 0 23 -9t9 -23zM1408 480v-192q0 -14 -9 -23t-23 -9h-448q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h448q14 0 23 -9t9 -23zM1600 992v-192q0 -14 -9 -23t-23 -9h-640q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h640q14 0 23 -9t9 -23zM1792 1504v-192q0 -14 -9 -23t-23 -9h-832
+q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h832q14 0 23 -9t9 -23z" />
+    <glyph glyph-name="sort_by_order" unicode="&#xf162;" 
+d="M1346 223q0 63 -44 116t-103 53q-52 0 -83 -37t-31 -94t36.5 -95t104.5 -38q50 0 85 27t35 68zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23
+zM1486 165q0 -62 -13 -121.5t-41 -114t-68 -95.5t-98.5 -65.5t-127.5 -24.5q-62 0 -108 16q-24 8 -42 15l39 113q15 -7 31 -11q37 -13 75 -13q84 0 134.5 58.5t66.5 145.5h-2q-21 -23 -61.5 -37t-84.5 -14q-106 0 -173 71.5t-67 172.5q0 105 72 178t181 73q123 0 205 -94.5
+t82 -252.5zM1456 882v-114h-469v114h167v432q0 7 0.5 19t0.5 17v16h-2l-7 -12q-8 -13 -26 -31l-62 -58l-82 86l192 185h123v-654h165z" />
+    <glyph glyph-name="sort_by_order_alt" unicode="&#xf163;" 
+d="M1346 1247q0 63 -44 116t-103 53q-52 0 -83 -37t-31 -94t36.5 -95t104.5 -38q50 0 85 27t35 68zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9
+t9 -23zM1456 -142v-114h-469v114h167v432q0 7 0.5 19t0.5 17v16h-2l-7 -12q-8 -13 -26 -31l-62 -58l-82 86l192 185h123v-654h165zM1486 1189q0 -62 -13 -121.5t-41 -114t-68 -95.5t-98.5 -65.5t-127.5 -24.5q-62 0 -108 16q-24 8 -42 15l39 113q15 -7 31 -11q37 -13 75 -13
+q84 0 134.5 58.5t66.5 145.5h-2q-21 -23 -61.5 -37t-84.5 -14q-106 0 -173 71.5t-67 172.5q0 105 72 178t181 73q123 0 205 -94.5t82 -252.5z" />
+    <glyph glyph-name="_334" unicode="&#xf164;" horiz-adv-x="1664" 
+d="M256 192q0 26 -19 45t-45 19q-27 0 -45.5 -19t-18.5 -45q0 -27 18.5 -45.5t45.5 -18.5q26 0 45 18.5t19 45.5zM416 704v-640q0 -26 -19 -45t-45 -19h-288q-26 0 -45 19t-19 45v640q0 26 19 45t45 19h288q26 0 45 -19t19 -45zM1600 704q0 -86 -55 -149q15 -44 15 -76
+q3 -76 -43 -137q17 -56 0 -117q-15 -57 -54 -94q9 -112 -49 -181q-64 -76 -197 -78h-36h-76h-17q-66 0 -144 15.5t-121.5 29t-120.5 39.5q-123 43 -158 44q-26 1 -45 19.5t-19 44.5v641q0 25 18 43.5t43 20.5q24 2 76 59t101 121q68 87 101 120q18 18 31 48t17.5 48.5
+t13.5 60.5q7 39 12.5 61t19.5 52t34 50q19 19 45 19q46 0 82.5 -10.5t60 -26t40 -40.5t24 -45t12 -50t5 -45t0.5 -39q0 -38 -9.5 -76t-19 -60t-27.5 -56q-3 -6 -10 -18t-11 -22t-8 -24h277q78 0 135 -57t57 -135z" />
+    <glyph glyph-name="_335" unicode="&#xf165;" horiz-adv-x="1664" 
+d="M256 960q0 -26 -19 -45t-45 -19q-27 0 -45.5 19t-18.5 45q0 27 18.5 45.5t45.5 18.5q26 0 45 -18.5t19 -45.5zM416 448v640q0 26 -19 45t-45 19h-288q-26 0 -45 -19t-19 -45v-640q0 -26 19 -45t45 -19h288q26 0 45 19t19 45zM1545 597q55 -61 55 -149q-1 -78 -57.5 -135
+t-134.5 -57h-277q4 -14 8 -24t11 -22t10 -18q18 -37 27 -57t19 -58.5t10 -76.5q0 -24 -0.5 -39t-5 -45t-12 -50t-24 -45t-40 -40.5t-60 -26t-82.5 -10.5q-26 0 -45 19q-20 20 -34 50t-19.5 52t-12.5 61q-9 42 -13.5 60.5t-17.5 48.5t-31 48q-33 33 -101 120q-49 64 -101 121
+t-76 59q-25 2 -43 20.5t-18 43.5v641q0 26 19 44.5t45 19.5q35 1 158 44q77 26 120.5 39.5t121.5 29t144 15.5h17h76h36q133 -2 197 -78q58 -69 49 -181q39 -37 54 -94q17 -61 0 -117q46 -61 43 -137q0 -32 -15 -76z" />
+    <glyph glyph-name="youtube_sign" unicode="&#xf166;" 
+d="M919 233v157q0 50 -29 50q-17 0 -33 -16v-224q16 -16 33 -16q29 0 29 49zM1103 355h66v34q0 51 -33 51t-33 -51v-34zM532 621v-70h-80v-423h-74v423h-78v70h232zM733 495v-367h-67v40q-39 -45 -76 -45q-33 0 -42 28q-6 17 -6 54v290h66v-270q0 -24 1 -26q1 -15 15 -15
+q20 0 42 31v280h67zM985 384v-146q0 -52 -7 -73q-12 -42 -53 -42q-35 0 -68 41v-36h-67v493h67v-161q32 40 68 40q41 0 53 -42q7 -21 7 -74zM1236 255v-9q0 -29 -2 -43q-3 -22 -15 -40q-27 -40 -80 -40q-52 0 -81 38q-21 27 -21 86v129q0 59 20 86q29 38 80 38t78 -38
+q21 -29 21 -86v-76h-133v-65q0 -51 34 -51q24 0 30 26q0 1 0.5 7t0.5 16.5v21.5h68zM785 1079v-156q0 -51 -32 -51t-32 51v156q0 52 32 52t32 -52zM1318 366q0 177 -19 260q-10 44 -43 73.5t-76 34.5q-136 15 -412 15q-275 0 -411 -15q-44 -5 -76.5 -34.5t-42.5 -73.5
+q-20 -87 -20 -260q0 -176 20 -260q10 -43 42.5 -73t75.5 -35q137 -15 412 -15t412 15q43 5 75.5 35t42.5 73q20 84 20 260zM563 1017l90 296h-75l-51 -195l-53 195h-78q7 -23 23 -69l24 -69q35 -103 46 -158v-201h74v201zM852 936v130q0 58 -21 87q-29 38 -78 38
+q-51 0 -78 -38q-21 -29 -21 -87v-130q0 -58 21 -87q27 -38 78 -38q49 0 78 38q21 27 21 87zM1033 816h67v370h-67v-283q-22 -31 -42 -31q-15 0 -16 16q-1 2 -1 26v272h-67v-293q0 -37 6 -55q11 -27 43 -27q36 0 77 45v-40zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5
+h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="youtube" unicode="&#xf167;" 
+d="M971 292v-211q0 -67 -39 -67q-23 0 -45 22v301q22 22 45 22q39 0 39 -67zM1309 291v-46h-90v46q0 68 45 68t45 -68zM343 509h107v94h-312v-94h105v-569h100v569zM631 -60h89v494h-89v-378q-30 -42 -57 -42q-18 0 -21 21q-1 3 -1 35v364h-89v-391q0 -49 8 -73
+q12 -37 58 -37q48 0 102 61v-54zM1060 88v197q0 73 -9 99q-17 56 -71 56q-50 0 -93 -54v217h-89v-663h89v48q45 -55 93 -55q54 0 71 55q9 27 9 100zM1398 98v13h-91q0 -51 -2 -61q-7 -36 -40 -36q-46 0 -46 69v87h179v103q0 79 -27 116q-39 51 -106 51q-68 0 -107 -51
+q-28 -37 -28 -116v-173q0 -79 29 -116q39 -51 108 -51q72 0 108 53q18 27 21 54q2 9 2 58zM790 1011v210q0 69 -43 69t-43 -69v-210q0 -70 43 -70t43 70zM1509 260q0 -234 -26 -350q-14 -59 -58 -99t-102 -46q-184 -21 -555 -21t-555 21q-58 6 -102.5 46t-57.5 99
+q-26 112 -26 350q0 234 26 350q14 59 58 99t103 47q183 20 554 20t555 -20q58 -7 102.5 -47t57.5 -99q26 -112 26 -350zM511 1536h102l-121 -399v-271h-100v271q-14 74 -61 212q-37 103 -65 187h106l71 -263zM881 1203v-175q0 -81 -28 -118q-38 -51 -106 -51q-67 0 -105 51
+q-28 38 -28 118v175q0 80 28 117q38 51 105 51q68 0 106 -51q28 -37 28 -117zM1216 1365v-499h-91v55q-53 -62 -103 -62q-46 0 -59 37q-8 24 -8 75v394h91v-367q0 -33 1 -35q3 -22 21 -22q27 0 57 43v381h91z" />
+    <glyph glyph-name="xing" unicode="&#xf168;" horiz-adv-x="1408" 
+d="M597 869q-10 -18 -257 -456q-27 -46 -65 -46h-239q-21 0 -31 17t0 36l253 448q1 0 0 1l-161 279q-12 22 -1 37q9 15 32 15h239q40 0 66 -45zM1403 1511q11 -16 0 -37l-528 -934v-1l336 -615q11 -20 1 -37q-10 -15 -32 -15h-239q-42 0 -66 45l-339 622q18 32 531 942
+q25 45 64 45h241q22 0 31 -15z" />
+    <glyph glyph-name="xing_sign" unicode="&#xf169;" 
+d="M685 771q0 1 -126 222q-21 34 -52 34h-184q-18 0 -26 -11q-7 -12 1 -29l125 -216v-1l-196 -346q-9 -14 0 -28q8 -13 24 -13h185q31 0 50 36zM1309 1268q-7 12 -24 12h-187q-30 0 -49 -35l-411 -729q1 -2 262 -481q20 -35 52 -35h184q18 0 25 12q8 13 -1 28l-260 476v1
+l409 723q8 16 0 28zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="youtube_play" unicode="&#xf16a;" horiz-adv-x="1792" 
+d="M711 408l484 250l-484 253v-503zM896 1270q168 0 324.5 -4.5t229.5 -9.5l73 -4q1 0 17 -1.5t23 -3t23.5 -4.5t28.5 -8t28 -13t31 -19.5t29 -26.5q6 -6 15.5 -18.5t29 -58.5t26.5 -101q8 -64 12.5 -136.5t5.5 -113.5v-40v-136q1 -145 -18 -290q-7 -55 -25 -99.5t-32 -61.5
+l-14 -17q-14 -15 -29 -26.5t-31 -19t-28 -12.5t-28.5 -8t-24 -4.5t-23 -3t-16.5 -1.5q-251 -19 -627 -19q-207 2 -359.5 6.5t-200.5 7.5l-49 4l-36 4q-36 5 -54.5 10t-51 21t-56.5 41q-6 6 -15.5 18.5t-29 58.5t-26.5 101q-8 64 -12.5 136.5t-5.5 113.5v40v136
+q-1 145 18 290q7 55 25 99.5t32 61.5l14 17q14 15 29 26.5t31 19.5t28 13t28.5 8t23.5 4.5t23 3t17 1.5q251 18 627 18z" />
+    <glyph glyph-name="dropbox" unicode="&#xf16b;" horiz-adv-x="1792" 
+d="M402 829l494 -305l-342 -285l-490 319zM1388 274v-108l-490 -293v-1l-1 1l-1 -1v1l-489 293v108l147 -96l342 284v2l1 -1l1 1v-2l343 -284zM554 1418l342 -285l-494 -304l-338 270zM1390 829l338 -271l-489 -319l-343 285zM1239 1418l489 -319l-338 -270l-494 304z" />
+    <glyph glyph-name="stackexchange" unicode="&#xf16c;" 
+d="M1289 -96h-1118v480h-160v-640h1438v640h-160v-480zM347 428l33 157l783 -165l-33 -156zM450 802l67 146l725 -339l-67 -145zM651 1158l102 123l614 -513l-102 -123zM1048 1536l477 -641l-128 -96l-477 641zM330 65v159h800v-159h-800z" />
+    <glyph glyph-name="instagram" unicode="&#xf16d;" 
+d="M1024 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1162 640q0 -164 -115 -279t-279 -115t-279 115t-115 279t115 279t279 115t279 -115t115 -279zM1270 1050q0 -38 -27 -65t-65 -27t-65 27t-27 65t27 65t65 27t65 -27t27 -65zM768 1270
+q-7 0 -76.5 0.5t-105.5 0t-96.5 -3t-103 -10t-71.5 -18.5q-50 -20 -88 -58t-58 -88q-11 -29 -18.5 -71.5t-10 -103t-3 -96.5t0 -105.5t0.5 -76.5t-0.5 -76.5t0 -105.5t3 -96.5t10 -103t18.5 -71.5q20 -50 58 -88t88 -58q29 -11 71.5 -18.5t103 -10t96.5 -3t105.5 0t76.5 0.5
+t76.5 -0.5t105.5 0t96.5 3t103 10t71.5 18.5q50 20 88 58t58 88q11 29 18.5 71.5t10 103t3 96.5t0 105.5t-0.5 76.5t0.5 76.5t0 105.5t-3 96.5t-10 103t-18.5 71.5q-20 50 -58 88t-88 58q-29 11 -71.5 18.5t-103 10t-96.5 3t-105.5 0t-76.5 -0.5zM1536 640q0 -229 -5 -317
+q-10 -208 -124 -322t-322 -124q-88 -5 -317 -5t-317 5q-208 10 -322 124t-124 322q-5 88 -5 317t5 317q10 208 124 322t322 124q88 5 317 5t317 -5q208 -10 322 -124t124 -322q5 -88 5 -317z" />
+    <glyph glyph-name="flickr" unicode="&#xf16e;" 
+d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960zM698 640q0 88 -62 150t-150 62t-150 -62t-62 -150t62 -150t150 -62t150 62t62 150zM1262 640q0 88 -62 150
+t-150 62t-150 -62t-62 -150t62 -150t150 -62t150 62t62 150z" />
+    <glyph glyph-name="adn" unicode="&#xf170;" 
+d="M768 914l201 -306h-402zM1133 384h94l-459 691l-459 -691h94l104 160h522zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="f171" unicode="&#xf171;" horiz-adv-x="1408" 
+d="M815 677q8 -63 -50.5 -101t-111.5 -6q-39 17 -53.5 58t-0.5 82t52 58q36 18 72.5 12t64 -35.5t27.5 -67.5zM926 698q-14 107 -113 164t-197 13q-63 -28 -100.5 -88.5t-34.5 -129.5q4 -91 77.5 -155t165.5 -56q91 8 152 84t50 168zM1165 1240q-20 27 -56 44.5t-58 22
+t-71 12.5q-291 47 -566 -2q-43 -7 -66 -12t-55 -22t-50 -43q30 -28 76 -45.5t73.5 -22t87.5 -11.5q228 -29 448 -1q63 8 89.5 12t72.5 21.5t75 46.5zM1222 205q-8 -26 -15.5 -76.5t-14 -84t-28.5 -70t-58 -56.5q-86 -48 -189.5 -71.5t-202 -22t-201.5 18.5q-46 8 -81.5 18
+t-76.5 27t-73 43.5t-52 61.5q-25 96 -57 292l6 16l18 9q223 -148 506.5 -148t507.5 148q21 -6 24 -23t-5 -45t-8 -37zM1403 1166q-26 -167 -111 -655q-5 -30 -27 -56t-43.5 -40t-54.5 -31q-252 -126 -610 -88q-248 27 -394 139q-15 12 -25.5 26.5t-17 35t-9 34t-6 39.5
+t-5.5 35q-9 50 -26.5 150t-28 161.5t-23.5 147.5t-22 158q3 26 17.5 48.5t31.5 37.5t45 30t46 22.5t48 18.5q125 46 313 64q379 37 676 -50q155 -46 215 -122q16 -20 16.5 -51t-5.5 -54z" />
+    <glyph glyph-name="bitbucket_sign" unicode="&#xf172;" 
+d="M848 666q0 43 -41 66t-77 1q-43 -20 -42.5 -72.5t43.5 -70.5q39 -23 81 4t36 72zM928 682q8 -66 -36 -121t-110 -61t-119 40t-56 113q-2 49 25.5 93t72.5 64q70 31 141.5 -10t81.5 -118zM1100 1073q-20 -21 -53.5 -34t-53 -16t-63.5 -8q-155 -20 -324 0q-44 6 -63 9.5
+t-52.5 16t-54.5 32.5q13 19 36 31t40 15.5t47 8.5q198 35 408 1q33 -5 51 -8.5t43 -16t39 -31.5zM1142 327q0 7 5.5 26.5t3 32t-17.5 16.5q-161 -106 -365 -106t-366 106l-12 -6l-5 -12q26 -154 41 -210q47 -81 204 -108q249 -46 428 53q34 19 49 51.5t22.5 85.5t12.5 71z
+M1272 1020q9 53 -8 75q-43 55 -155 88q-216 63 -487 36q-132 -12 -226 -46q-38 -15 -59.5 -25t-47 -34t-29.5 -54q8 -68 19 -138t29 -171t24 -137q1 -5 5 -31t7 -36t12 -27t22 -28q105 -80 284 -100q259 -28 440 63q24 13 39.5 23t31 29t19.5 40q48 267 80 473zM1536 1120
+v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="tumblr" unicode="&#xf173;" horiz-adv-x="1024" 
+d="M944 207l80 -237q-23 -35 -111 -66t-177 -32q-104 -2 -190.5 26t-142.5 74t-95 106t-55.5 120t-16.5 118v544h-168v215q72 26 129 69.5t91 90t58 102t34 99t15 88.5q1 5 4.5 8.5t7.5 3.5h244v-424h333v-252h-334v-518q0 -30 6.5 -56t22.5 -52.5t49.5 -41.5t81.5 -14
+q78 2 134 29z" />
+    <glyph glyph-name="tumblr_sign" unicode="&#xf174;" 
+d="M1136 75l-62 183q-44 -22 -103 -22q-36 -1 -62 10.5t-38.5 31.5t-17.5 40.5t-5 43.5v398h257v194h-256v326h-188q-8 0 -9 -10q-5 -44 -17.5 -87t-39 -95t-77 -95t-118.5 -68v-165h130v-418q0 -57 21.5 -115t65 -111t121 -85.5t176.5 -30.5q69 1 136.5 25t85.5 50z
+M1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="long_arrow_down" unicode="&#xf175;" horiz-adv-x="768" 
+d="M765 237q8 -19 -5 -35l-350 -384q-10 -10 -23 -10q-14 0 -24 10l-355 384q-13 16 -5 35q9 19 29 19h224v1248q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1248h224q21 0 29 -19z" />
+    <glyph glyph-name="long_arrow_up" unicode="&#xf176;" horiz-adv-x="768" 
+d="M765 1043q-9 -19 -29 -19h-224v-1248q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v1248h-224q-21 0 -29 19t5 35l350 384q10 10 23 10q14 0 24 -10l355 -384q13 -16 5 -35z" />
+    <glyph glyph-name="long_arrow_left" unicode="&#xf177;" horiz-adv-x="1792" 
+d="M1792 736v-192q0 -14 -9 -23t-23 -9h-1248v-224q0 -21 -19 -29t-35 5l-384 350q-10 10 -10 23q0 14 10 24l384 354q16 14 35 6q19 -9 19 -29v-224h1248q14 0 23 -9t9 -23z" />
+    <glyph glyph-name="long_arrow_right" unicode="&#xf178;" horiz-adv-x="1792" 
+d="M1728 643q0 -14 -10 -24l-384 -354q-16 -14 -35 -6q-19 9 -19 29v224h-1248q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h1248v224q0 21 19 29t35 -5l384 -350q10 -10 10 -23z" />
+    <glyph glyph-name="apple" unicode="&#xf179;" horiz-adv-x="1408" 
+d="M1393 321q-39 -125 -123 -250q-129 -196 -257 -196q-49 0 -140 32q-86 32 -151 32q-61 0 -142 -33q-81 -34 -132 -34q-152 0 -301 259q-147 261 -147 503q0 228 113 374q113 144 284 144q72 0 177 -30q104 -30 138 -30q45 0 143 34q102 34 173 34q119 0 213 -65
+q52 -36 104 -100q-79 -67 -114 -118q-65 -94 -65 -207q0 -124 69 -223t158 -126zM1017 1494q0 -61 -29 -136q-30 -75 -93 -138q-54 -54 -108 -72q-37 -11 -104 -17q3 149 78 257q74 107 250 148q1 -3 2.5 -11t2.5 -11q0 -4 0.5 -10t0.5 -10z" />
+    <glyph glyph-name="windows" unicode="&#xf17a;" horiz-adv-x="1664" 
+d="M682 530v-651l-682 94v557h682zM682 1273v-659h-682v565zM1664 530v-786l-907 125v661h907zM1664 1408v-794h-907v669z" />
+    <glyph glyph-name="android" unicode="&#xf17b;" horiz-adv-x="1408" 
+d="M493 1053q16 0 27.5 11.5t11.5 27.5t-11.5 27.5t-27.5 11.5t-27 -11.5t-11 -27.5t11 -27.5t27 -11.5zM915 1053q16 0 27 11.5t11 27.5t-11 27.5t-27 11.5t-27.5 -11.5t-11.5 -27.5t11.5 -27.5t27.5 -11.5zM103 869q42 0 72 -30t30 -72v-430q0 -43 -29.5 -73t-72.5 -30
+t-73 30t-30 73v430q0 42 30 72t73 30zM1163 850v-666q0 -46 -32 -78t-77 -32h-75v-227q0 -43 -30 -73t-73 -30t-73 30t-30 73v227h-138v-227q0 -43 -30 -73t-73 -30q-42 0 -72 30t-30 73l-1 227h-74q-46 0 -78 32t-32 78v666h918zM931 1255q107 -55 171 -153.5t64 -215.5
+h-925q0 117 64 215.5t172 153.5l-71 131q-7 13 5 20q13 6 20 -6l72 -132q95 42 201 42t201 -42l72 132q7 12 20 6q12 -7 5 -20zM1408 767v-430q0 -43 -30 -73t-73 -30q-42 0 -72 30t-30 73v430q0 43 30 72.5t72 29.5q43 0 73 -29.5t30 -72.5z" />
+    <glyph glyph-name="linux" unicode="&#xf17c;" 
+d="M663 1125q-11 -1 -15.5 -10.5t-8.5 -9.5q-5 -1 -5 5q0 12 19 15h10zM750 1111q-4 -1 -11.5 6.5t-17.5 4.5q24 11 32 -2q3 -6 -3 -9zM399 684q-4 1 -6 -3t-4.5 -12.5t-5.5 -13.5t-10 -13q-10 -11 -1 -12q4 -1 12.5 7t12.5 18q1 3 2 7t2 6t1.5 4.5t0.5 4v3t-1 2.5t-3 2z
+M1254 325q0 18 -55 42q4 15 7.5 27.5t5 26t3 21.5t0.5 22.5t-1 19.5t-3.5 22t-4 20.5t-5 25t-5.5 26.5q-10 48 -47 103t-72 75q24 -20 57 -83q87 -162 54 -278q-11 -40 -50 -42q-31 -4 -38.5 18.5t-8 83.5t-11.5 107q-9 39 -19.5 69t-19.5 45.5t-15.5 24.5t-13 15t-7.5 7
+q-14 62 -31 103t-29.5 56t-23.5 33t-15 40q-4 21 6 53.5t4.5 49.5t-44.5 25q-15 3 -44.5 18t-35.5 16q-8 1 -11 26t8 51t36 27q37 3 51 -30t4 -58q-11 -19 -2 -26.5t30 -0.5q13 4 13 36v37q-5 30 -13.5 50t-21 30.5t-23.5 15t-27 7.5q-107 -8 -89 -134q0 -15 -1 -15
+q-9 9 -29.5 10.5t-33 -0.5t-15.5 5q1 57 -16 90t-45 34q-27 1 -41.5 -27.5t-16.5 -59.5q-1 -15 3.5 -37t13 -37.5t15.5 -13.5q10 3 16 14q4 9 -7 8q-7 0 -15.5 14.5t-9.5 33.5q-1 22 9 37t34 14q17 0 27 -21t9.5 -39t-1.5 -22q-22 -15 -31 -29q-8 -12 -27.5 -23.5
+t-20.5 -12.5q-13 -14 -15.5 -27t7.5 -18q14 -8 25 -19.5t16 -19t18.5 -13t35.5 -6.5q47 -2 102 15q2 1 23 7t34.5 10.5t29.5 13t21 17.5q9 14 20 8q5 -3 6.5 -8.5t-3 -12t-16.5 -9.5q-20 -6 -56.5 -21.5t-45.5 -19.5q-44 -19 -70 -23q-25 -5 -79 2q-10 2 -9 -2t17 -19
+q25 -23 67 -22q17 1 36 7t36 14t33.5 17.5t30 17t24.5 12t17.5 2.5t8.5 -11q0 -2 -1 -4.5t-4 -5t-6 -4.5t-8.5 -5t-9 -4.5t-10 -5t-9.5 -4.5q-28 -14 -67.5 -44t-66.5 -43t-49 -1q-21 11 -63 73q-22 31 -25 22q-1 -3 -1 -10q0 -25 -15 -56.5t-29.5 -55.5t-21 -58t11.5 -63
+q-23 -6 -62.5 -90t-47.5 -141q-2 -18 -1.5 -69t-5.5 -59q-8 -24 -29 -3q-32 31 -36 94q-2 28 4 56q4 19 -1 18q-2 -1 -4 -5q-36 -65 10 -166q5 -12 25 -28t24 -20q20 -23 104 -90.5t93 -76.5q16 -15 17.5 -38t-14 -43t-45.5 -23q8 -15 29 -44.5t28 -54t7 -70.5q46 24 7 92
+q-4 8 -10.5 16t-9.5 12t-2 6q3 5 13 9.5t20 -2.5q46 -52 166 -36q133 15 177 87q23 38 34 30q12 -6 10 -52q-1 -25 -23 -92q-9 -23 -6 -37.5t24 -15.5q3 19 14.5 77t13.5 90q2 21 -6.5 73.5t-7.5 97t23 70.5q15 18 51 18q1 37 34.5 53t72.5 10.5t60 -22.5zM626 1152
+q3 17 -2.5 30t-11.5 15q-9 2 -9 -7q2 -5 5 -6q10 0 7 -15q-3 -20 8 -20q3 0 3 3zM1045 955q-2 8 -6.5 11.5t-13 5t-14.5 5.5q-5 3 -9.5 8t-7 8t-5.5 6.5t-4 4t-4 -1.5q-14 -16 7 -43.5t39 -31.5q9 -1 14.5 8t3.5 20zM867 1168q0 11 -5 19.5t-11 12.5t-9 3q-6 0 -8 -2t0 -4
+t5 -3q14 -4 18 -31q0 -3 8 2q2 2 2 3zM921 1401q0 2 -2.5 5t-9 7t-9.5 6q-15 15 -24 15q-9 -1 -11.5 -7.5t-1 -13t-0.5 -12.5q-1 -4 -6 -10.5t-6 -9t3 -8.5q4 -3 8 0t11 9t15 9q1 1 9 1t15 2t9 7zM1486 60q20 -12 31 -24.5t12 -24t-2.5 -22.5t-15.5 -22t-23.5 -19.5
+t-30 -18.5t-31.5 -16.5t-32 -15.5t-27 -13q-38 -19 -85.5 -56t-75.5 -64q-17 -16 -68 -19.5t-89 14.5q-18 9 -29.5 23.5t-16.5 25.5t-22 19.5t-47 9.5q-44 1 -130 1q-19 0 -57 -1.5t-58 -2.5q-44 -1 -79.5 -15t-53.5 -30t-43.5 -28.5t-53.5 -11.5q-29 1 -111 31t-146 43
+q-19 4 -51 9.5t-50 9t-39.5 9.5t-33.5 14.5t-17 19.5q-10 23 7 66.5t18 54.5q1 16 -4 40t-10 42.5t-4.5 36.5t10.5 27q14 12 57 14t60 12q30 18 42 35t12 51q21 -73 -32 -106q-32 -20 -83 -15q-34 3 -43 -10q-13 -15 5 -57q2 -6 8 -18t8.5 -18t4.5 -17t1 -22q0 -15 -17 -49
+t-14 -48q3 -17 37 -26q20 -6 84.5 -18.5t99.5 -20.5q24 -6 74 -22t82.5 -23t55.5 -4q43 6 64.5 28t23 48t-7.5 58.5t-19 52t-20 36.5q-121 190 -169 242q-68 74 -113 40q-11 -9 -15 15q-3 16 -2 38q1 29 10 52t24 47t22 42q8 21 26.5 72t29.5 78t30 61t39 54
+q110 143 124 195q-12 112 -16 310q-2 90 24 151.5t106 104.5q39 21 104 21q53 1 106 -13.5t89 -41.5q57 -42 91.5 -121.5t29.5 -147.5q-5 -95 30 -214q34 -113 133 -218q55 -59 99.5 -163t59.5 -191q8 -49 5 -84.5t-12 -55.5t-20 -22q-10 -2 -23.5 -19t-27 -35.5
+t-40.5 -33.5t-61 -14q-18 1 -31.5 5t-22.5 13.5t-13.5 15.5t-11.5 20.5t-9 19.5q-22 37 -41 30t-28 -49t7 -97q20 -70 1 -195q-10 -65 18 -100.5t73 -33t85 35.5q59 49 89.5 66.5t103.5 42.5q53 18 77 36.5t18.5 34.5t-25 28.5t-51.5 23.5q-33 11 -49.5 48t-15 72.5
+t15.5 47.5q1 -31 8 -56.5t14.5 -40.5t20.5 -28.5t21 -19t21.5 -13t16.5 -9.5z" />
+    <glyph glyph-name="dribble" unicode="&#xf17d;" 
+d="M1024 36q-42 241 -140 498h-2l-2 -1q-16 -6 -43 -16.5t-101 -49t-137 -82t-131 -114.5t-103 -148l-15 11q184 -150 418 -150q132 0 256 52zM839 643q-21 49 -53 111q-311 -93 -673 -93q-1 -7 -1 -21q0 -124 44 -236.5t124 -201.5q50 89 123.5 166.5t142.5 124.5t130.5 81
+t99.5 48l37 13q4 1 13 3.5t13 4.5zM732 855q-120 213 -244 378q-138 -65 -234 -186t-128 -272q302 0 606 80zM1416 536q-210 60 -409 29q87 -239 128 -469q111 75 185 189.5t96 250.5zM611 1277q-1 0 -2 -1q1 1 2 1zM1201 1132q-185 164 -433 164q-76 0 -155 -19
+q131 -170 246 -382q69 26 130 60.5t96.5 61.5t65.5 57t37.5 40.5zM1424 647q-3 232 -149 410l-1 -1q-9 -12 -19 -24.5t-43.5 -44.5t-71 -60.5t-100 -65t-131.5 -64.5q25 -53 44 -95q2 -5 6.5 -17t7.5 -17q36 5 74.5 7t73.5 2t69 -1.5t64 -4t56.5 -5.5t48 -6.5t36.5 -6
+t25 -4.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="skype" unicode="&#xf17e;" 
+d="M1173 473q0 50 -19.5 91.5t-48.5 68.5t-73 49t-82.5 34t-87.5 23l-104 24q-30 7 -44 10.5t-35 11.5t-30 16t-16.5 21t-7.5 30q0 77 144 77q43 0 77 -12t54 -28.5t38 -33.5t40 -29t48 -12q47 0 75.5 32t28.5 77q0 55 -56 99.5t-142 67.5t-182 23q-68 0 -132 -15.5
+t-119.5 -47t-89 -87t-33.5 -128.5q0 -61 19 -106.5t56 -75.5t80 -48.5t103 -32.5l146 -36q90 -22 112 -36q32 -20 32 -60q0 -39 -40 -64.5t-105 -25.5q-51 0 -91.5 16t-65 38.5t-45.5 45t-46 38.5t-54 16q-50 0 -75.5 -30t-25.5 -75q0 -92 122 -157.5t291 -65.5
+q73 0 140 18.5t122.5 53.5t88.5 93.5t33 131.5zM1536 256q0 -159 -112.5 -271.5t-271.5 -112.5q-130 0 -234 80q-77 -16 -150 -16q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5q0 73 16 150q-80 104 -80 234q0 159 112.5 271.5t271.5 112.5q130 0 234 -80
+q77 16 150 16q143 0 273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -73 -16 -150q80 -104 80 -234z" />
+    <glyph glyph-name="foursquare" unicode="&#xf180;" horiz-adv-x="1280" 
+d="M1000 1102l37 194q5 23 -9 40t-35 17h-712q-23 0 -38.5 -17t-15.5 -37v-1101q0 -7 6 -1l291 352q23 26 38 33.5t48 7.5h239q22 0 37 14.5t18 29.5q24 130 37 191q4 21 -11.5 40t-36.5 19h-294q-29 0 -48 19t-19 48v42q0 29 19 47.5t48 18.5h346q18 0 35 13.5t20 29.5z
+M1227 1324q-15 -73 -53.5 -266.5t-69.5 -350t-35 -173.5q-6 -22 -9 -32.5t-14 -32.5t-24.5 -33t-38.5 -21t-58 -10h-271q-13 0 -22 -10q-8 -9 -426 -494q-22 -25 -58.5 -28.5t-48.5 5.5q-55 22 -55 98v1410q0 55 38 102.5t120 47.5h888q95 0 127 -53t10 -159zM1227 1324
+l-158 -790q4 17 35 173.5t69.5 350t53.5 266.5z" />
+    <glyph glyph-name="trello" unicode="&#xf181;" 
+d="M704 192v1024q0 14 -9 23t-23 9h-480q-14 0 -23 -9t-9 -23v-1024q0 -14 9 -23t23 -9h480q14 0 23 9t9 23zM1376 576v640q0 14 -9 23t-23 9h-480q-14 0 -23 -9t-9 -23v-640q0 -14 9 -23t23 -9h480q14 0 23 9t9 23zM1536 1344v-1408q0 -26 -19 -45t-45 -19h-1408
+q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="female" unicode="&#xf182;" horiz-adv-x="1280" 
+d="M1280 480q0 -40 -28 -68t-68 -28q-51 0 -80 43l-227 341h-45v-132l247 -411q9 -15 9 -33q0 -26 -19 -45t-45 -19h-192v-272q0 -46 -33 -79t-79 -33h-160q-46 0 -79 33t-33 79v272h-192q-26 0 -45 19t-19 45q0 18 9 33l247 411v132h-45l-227 -341q-29 -43 -80 -43
+q-40 0 -68 28t-28 68q0 29 16 53l256 384q73 107 176 107h384q103 0 176 -107l256 -384q16 -24 16 -53zM864 1280q0 -93 -65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5z" />
+    <glyph glyph-name="male" unicode="&#xf183;" horiz-adv-x="1024" 
+d="M1024 832v-416q0 -40 -28 -68t-68 -28t-68 28t-28 68v352h-64v-912q0 -46 -33 -79t-79 -33t-79 33t-33 79v464h-64v-464q0 -46 -33 -79t-79 -33t-79 33t-33 79v912h-64v-352q0 -40 -28 -68t-68 -28t-68 28t-28 68v416q0 80 56 136t136 56h640q80 0 136 -56t56 -136z
+M736 1280q0 -93 -65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5z" />
+    <glyph glyph-name="gittip" unicode="&#xf184;" 
+d="M773 234l350 473q16 22 24.5 59t-6 85t-61.5 79q-40 26 -83 25.5t-73.5 -17.5t-54.5 -45q-36 -40 -96 -40q-59 0 -95 40q-24 28 -54.5 45t-73.5 17.5t-84 -25.5q-46 -31 -60.5 -79t-6 -85t24.5 -59zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103
+t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="sun" unicode="&#xf185;" horiz-adv-x="1792" 
+d="M1472 640q0 117 -45.5 223.5t-123 184t-184 123t-223.5 45.5t-223.5 -45.5t-184 -123t-123 -184t-45.5 -223.5t45.5 -223.5t123 -184t184 -123t223.5 -45.5t223.5 45.5t184 123t123 184t45.5 223.5zM1748 363q-4 -15 -20 -20l-292 -96v-306q0 -16 -13 -26q-15 -10 -29 -4
+l-292 94l-180 -248q-10 -13 -26 -13t-26 13l-180 248l-292 -94q-14 -6 -29 4q-13 10 -13 26v306l-292 96q-16 5 -20 20q-5 17 4 29l180 248l-180 248q-9 13 -4 29q4 15 20 20l292 96v306q0 16 13 26q15 10 29 4l292 -94l180 248q9 12 26 12t26 -12l180 -248l292 94
+q14 6 29 -4q13 -10 13 -26v-306l292 -96q16 -5 20 -20q5 -16 -4 -29l-180 -248l180 -248q9 -12 4 -29z" />
+    <glyph glyph-name="_366" unicode="&#xf186;" 
+d="M1262 233q-54 -9 -110 -9q-182 0 -337 90t-245 245t-90 337q0 192 104 357q-201 -60 -328.5 -229t-127.5 -384q0 -130 51 -248.5t136.5 -204t204 -136.5t248.5 -51q144 0 273.5 61.5t220.5 171.5zM1465 318q-94 -203 -283.5 -324.5t-413.5 -121.5q-156 0 -298 61
+t-245 164t-164 245t-61 298q0 153 57.5 292.5t156 241.5t235.5 164.5t290 68.5q44 2 61 -39q18 -41 -15 -72q-86 -78 -131.5 -181.5t-45.5 -218.5q0 -148 73 -273t198 -198t273 -73q118 0 228 51q41 18 72 -13q14 -14 17.5 -34t-4.5 -38z" />
+    <glyph glyph-name="archive" unicode="&#xf187;" horiz-adv-x="1792" 
+d="M1088 704q0 26 -19 45t-45 19h-256q-26 0 -45 -19t-19 -45t19 -45t45 -19h256q26 0 45 19t19 45zM1664 896v-960q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v960q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1728 1344v-256q0 -26 -19 -45t-45 -19h-1536
+q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1536q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="bug" unicode="&#xf188;" horiz-adv-x="1664" 
+d="M1632 576q0 -26 -19 -45t-45 -19h-224q0 -171 -67 -290l208 -209q19 -19 19 -45t-19 -45q-18 -19 -45 -19t-45 19l-198 197q-5 -5 -15 -13t-42 -28.5t-65 -36.5t-82 -29t-97 -13v896h-128v-896q-51 0 -101.5 13.5t-87 33t-66 39t-43.5 32.5l-15 14l-183 -207
+q-20 -21 -48 -21q-24 0 -43 16q-19 18 -20.5 44.5t15.5 46.5l202 227q-58 114 -58 274h-224q-26 0 -45 19t-19 45t19 45t45 19h224v294l-173 173q-19 19 -19 45t19 45t45 19t45 -19l173 -173h844l173 173q19 19 45 19t45 -19t19 -45t-19 -45l-173 -173v-294h224q26 0 45 -19
+t19 -45zM1152 1152h-640q0 133 93.5 226.5t226.5 93.5t226.5 -93.5t93.5 -226.5z" />
+    <glyph glyph-name="vk" unicode="&#xf189;" horiz-adv-x="1920" 
+d="M1917 1016q23 -64 -150 -294q-24 -32 -65 -85q-40 -51 -55 -72t-30.5 -49.5t-12 -42t13 -34.5t32.5 -43t57 -53q4 -2 5 -4q141 -131 191 -221q3 -5 6.5 -12.5t7 -26.5t-0.5 -34t-25 -27.5t-59 -12.5l-256 -4q-24 -5 -56 5t-52 22l-20 12q-30 21 -70 64t-68.5 77.5t-61 58
+t-56.5 15.5q-3 -1 -8 -3.5t-17 -14.5t-21.5 -29.5t-17 -52t-6.5 -77.5q0 -15 -3.5 -27.5t-7.5 -18.5l-4 -5q-18 -19 -53 -22h-115q-71 -4 -146 16.5t-131.5 53t-103 66t-70.5 57.5l-25 24q-10 10 -27.5 30t-71.5 91t-106 151t-122.5 211t-130.5 272q-6 16 -6 27t3 16l4 6
+q15 19 57 19l274 2q12 -2 23 -6.5t16 -8.5l5 -3q16 -11 24 -32q20 -50 46 -103.5t41 -81.5l16 -29q29 -60 56 -104t48.5 -68.5t41.5 -38.5t34 -14t27 5q2 1 5 5t12 22t13.5 47t9.5 81t0 125q-2 40 -9 73t-14 46l-6 12q-25 34 -85 43q-13 2 5 24q16 19 38 30q53 26 239 24
+q82 -1 135 -13q20 -5 33.5 -13.5t20.5 -24t10.5 -32t3.5 -45.5t-1 -55t-2.5 -70.5t-1.5 -82.5q0 -11 -1 -42t-0.5 -48t3.5 -40.5t11.5 -39t22.5 -24.5q8 -2 17 -4t26 11t38 34.5t52 67t68 107.5q60 104 107 225q4 10 10 17.5t11 10.5l4 3l5 2.5t13 3t20 0.5l288 2
+q39 5 64 -2.5t31 -16.5z" />
+    <glyph glyph-name="weibo" unicode="&#xf18a;" horiz-adv-x="1792" 
+d="M675 252q21 34 11 69t-45 50q-34 14 -73 1t-60 -46q-22 -34 -13 -68.5t43 -50.5t74.5 -2.5t62.5 47.5zM769 373q8 13 3.5 26.5t-17.5 18.5q-14 5 -28.5 -0.5t-21.5 -18.5q-17 -31 13 -45q14 -5 29 0.5t22 18.5zM943 266q-45 -102 -158 -150t-224 -12
+q-107 34 -147.5 126.5t6.5 187.5q47 93 151.5 139t210.5 19q111 -29 158.5 -119.5t2.5 -190.5zM1255 426q-9 96 -89 170t-208.5 109t-274.5 21q-223 -23 -369.5 -141.5t-132.5 -264.5q9 -96 89 -170t208.5 -109t274.5 -21q223 23 369.5 141.5t132.5 264.5zM1563 422
+q0 -68 -37 -139.5t-109 -137t-168.5 -117.5t-226 -83t-270.5 -31t-275 33.5t-240.5 93t-171.5 151t-65 199.5q0 115 69.5 245t197.5 258q169 169 341.5 236t246.5 -7q65 -64 20 -209q-4 -14 -1 -20t10 -7t14.5 0.5t13.5 3.5l6 2q139 59 246 59t153 -61q45 -63 0 -178
+q-2 -13 -4.5 -20t4.5 -12.5t12 -7.5t17 -6q57 -18 103 -47t80 -81.5t34 -116.5zM1489 1046q42 -47 54.5 -108.5t-6.5 -117.5q-8 -23 -29.5 -34t-44.5 -4q-23 8 -34 29.5t-4 44.5q20 63 -24 111t-107 35q-24 -5 -45 8t-25 37q-5 24 8 44.5t37 25.5q60 13 119 -5.5t101 -65.5z
+M1670 1209q87 -96 112.5 -222.5t-13.5 -241.5q-9 -27 -34 -40t-52 -4t-40 34t-5 52q28 82 10 172t-80 158q-62 69 -148 95.5t-173 8.5q-28 -6 -52 9.5t-30 43.5t9.5 51.5t43.5 29.5q123 26 244 -11.5t208 -134.5z" />
+    <glyph glyph-name="renren" unicode="&#xf18b;" 
+d="M1133 -34q-171 -94 -368 -94q-196 0 -367 94q138 87 235.5 211t131.5 268q35 -144 132.5 -268t235.5 -211zM638 1394v-485q0 -252 -126.5 -459.5t-330.5 -306.5q-181 215 -181 495q0 187 83.5 349.5t229.5 269.5t325 137zM1536 638q0 -280 -181 -495
+q-204 99 -330.5 306.5t-126.5 459.5v485q179 -30 325 -137t229.5 -269.5t83.5 -349.5z" />
+    <glyph glyph-name="_372" unicode="&#xf18c;" horiz-adv-x="1408" 
+d="M1402 433q-32 -80 -76 -138t-91 -88.5t-99 -46.5t-101.5 -14.5t-96.5 8.5t-86.5 22t-69.5 27.5t-46 22.5l-17 10q-113 -228 -289.5 -359.5t-384.5 -132.5q-19 0 -32 13t-13 32t13 31.5t32 12.5q173 1 322.5 107.5t251.5 294.5q-36 -14 -72 -23t-83 -13t-91 2.5t-93 28.5
+t-92 59t-84.5 100t-74.5 146q114 47 214 57t167.5 -7.5t124.5 -56.5t88.5 -77t56.5 -82q53 131 79 291q-7 -1 -18 -2.5t-46.5 -2.5t-69.5 0.5t-81.5 10t-88.5 23t-84 42.5t-75 65t-54.5 94.5t-28.5 127.5q70 28 133.5 36.5t112.5 -1t92 -30t73.5 -50t56 -61t42 -63t27.5 -56
+t16 -39.5l4 -16q12 122 12 195q-8 6 -21.5 16t-49 44.5t-63.5 71.5t-54 93t-33 112.5t12 127t70 138.5q73 -25 127.5 -61.5t84.5 -76.5t48 -85t20.5 -89t-0.5 -85.5t-13 -76.5t-19 -62t-17 -42l-7 -15q1 -4 1 -50t-1 -72q3 7 10 18.5t30.5 43t50.5 58t71 55.5t91.5 44.5
+t112 14.5t132.5 -24q-2 -78 -21.5 -141.5t-50 -104.5t-69.5 -71.5t-81.5 -45.5t-84.5 -24t-80 -9.5t-67.5 1t-46.5 4.5l-17 3q-23 -147 -73 -283q6 7 18 18.5t49.5 41t77.5 52.5t99.5 42t117.5 20t129 -23.5t137 -77.5z" />
+    <glyph glyph-name="stack_exchange" unicode="&#xf18d;" horiz-adv-x="1280" 
+d="M1259 283v-66q0 -85 -57.5 -144.5t-138.5 -59.5h-57l-260 -269v269h-529q-81 0 -138.5 59.5t-57.5 144.5v66h1238zM1259 609v-255h-1238v255h1238zM1259 937v-255h-1238v255h1238zM1259 1077v-67h-1238v67q0 84 57.5 143.5t138.5 59.5h846q81 0 138.5 -59.5t57.5 -143.5z
+" />
+    <glyph glyph-name="_374" unicode="&#xf18e;" 
+d="M1152 640q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v192h-352q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h352v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198
+t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="arrow_circle_alt_left" unicode="&#xf190;" 
+d="M1152 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-352v-192q0 -14 -9 -23t-23 -9q-12 0 -24 10l-319 319q-9 9 -9 23t9 23l320 320q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5v-192h352q13 0 22.5 -9.5t9.5 -22.5zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198
+t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="_376" unicode="&#xf191;" 
+d="M1024 960v-640q0 -26 -19 -45t-45 -19q-20 0 -37 12l-448 320q-27 19 -27 52t27 52l448 320q17 12 37 12q26 0 45 -19t19 -45zM1280 160v960q0 13 -9.5 22.5t-22.5 9.5h-960q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5z
+M1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="dot_circle_alt" unicode="&#xf192;" 
+d="M1024 640q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5
+t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="_378" unicode="&#xf193;" horiz-adv-x="1664" 
+d="M1023 349l102 -204q-58 -179 -210 -290t-339 -111q-156 0 -288.5 77.5t-210 210t-77.5 288.5q0 181 104.5 330t274.5 211l17 -131q-122 -54 -195 -165.5t-73 -244.5q0 -185 131.5 -316.5t316.5 -131.5q126 0 232.5 65t165 175.5t49.5 236.5zM1571 249l58 -114l-256 -128
+q-13 -7 -29 -7q-40 0 -57 35l-239 477h-472q-24 0 -42.5 16.5t-21.5 40.5l-96 779q-2 17 6 42q14 51 57 82.5t97 31.5q66 0 113 -47t47 -113q0 -69 -52 -117.5t-120 -41.5l37 -289h423v-128h-407l16 -128h455q40 0 57 -35l228 -455z" />
+    <glyph glyph-name="vimeo_square" unicode="&#xf194;" 
+d="M1292 898q10 216 -161 222q-231 8 -312 -261q44 19 82 19q85 0 74 -96q-4 -57 -74 -167t-105 -110q-43 0 -82 169q-13 54 -45 255q-30 189 -160 177q-59 -7 -164 -100l-81 -72l-81 -72l52 -67q76 52 87 52q57 0 107 -179q15 -55 45 -164.5t45 -164.5q68 -179 164 -179
+q157 0 383 294q220 283 226 444zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="_380" unicode="&#xf195;" horiz-adv-x="1152" 
+d="M1152 704q0 -191 -94.5 -353t-256.5 -256.5t-353 -94.5h-160q-14 0 -23 9t-9 23v611l-215 -66q-3 -1 -9 -1q-10 0 -19 6q-13 10 -13 26v128q0 23 23 31l233 71v93l-215 -66q-3 -1 -9 -1q-10 0 -19 6q-13 10 -13 26v128q0 23 23 31l233 71v250q0 14 9 23t23 9h160
+q14 0 23 -9t9 -23v-181l375 116q15 5 28 -5t13 -26v-128q0 -23 -23 -31l-393 -121v-93l375 116q15 5 28 -5t13 -26v-128q0 -23 -23 -31l-393 -121v-487q188 13 318 151t130 328q0 14 9 23t23 9h160q14 0 23 -9t9 -23z" />
+    <glyph glyph-name="plus_square_o" unicode="&#xf196;" horiz-adv-x="1408" 
+d="M1152 736v-64q0 -14 -9 -23t-23 -9h-352v-352q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v352h-352q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h352v352q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-352h352q14 0 23 -9t9 -23zM1280 288v832q0 66 -47 113t-113 47h-832
+q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113zM1408 1120v-832q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="_382" unicode="&#xf197;" horiz-adv-x="2176" 
+d="M620 416q-110 -64 -268 -64h-128v64h-64q-13 0 -22.5 23.5t-9.5 56.5q0 24 7 49q-58 2 -96.5 10.5t-38.5 20.5t38.5 20.5t96.5 10.5q-7 25 -7 49q0 33 9.5 56.5t22.5 23.5h64v64h128q158 0 268 -64h1113q42 -7 106.5 -18t80.5 -14q89 -15 150 -40.5t83.5 -47.5t22.5 -40
+t-22.5 -40t-83.5 -47.5t-150 -40.5q-16 -3 -80.5 -14t-106.5 -18h-1113zM1739 668q53 -36 53 -92t-53 -92l81 -30q68 48 68 122t-68 122zM625 400h1015q-217 -38 -456 -80q-57 0 -113 -24t-83 -48l-28 -24l-288 -288q-26 -26 -70.5 -45t-89.5 -19h-96l-93 464h29
+q157 0 273 64zM352 816h-29l93 464h96q46 0 90 -19t70 -45l288 -288q4 -4 11 -10.5t30.5 -23t48.5 -29t61.5 -23t72.5 -10.5l456 -80h-1015q-116 64 -273 64z" />
+    <glyph glyph-name="_383" unicode="&#xf198;" horiz-adv-x="1664" 
+d="M1519 760q62 0 103.5 -40.5t41.5 -101.5q0 -97 -93 -130l-172 -59l56 -167q7 -21 7 -47q0 -59 -42 -102t-101 -43q-47 0 -85.5 27t-53.5 72l-55 165l-310 -106l55 -164q8 -24 8 -47q0 -59 -42 -102t-102 -43q-47 0 -85 27t-53 72l-55 163l-153 -53q-29 -9 -50 -9
+q-61 0 -101.5 40t-40.5 101q0 47 27.5 85t71.5 53l156 53l-105 313l-156 -54q-26 -8 -48 -8q-60 0 -101 40.5t-41 100.5q0 47 27.5 85t71.5 53l157 53l-53 159q-8 24 -8 47q0 60 42 102.5t102 42.5q47 0 85 -27t53 -72l54 -160l310 105l-54 160q-8 24 -8 47q0 59 42.5 102
+t101.5 43q47 0 85.5 -27.5t53.5 -71.5l53 -161l162 55q21 6 43 6q60 0 102.5 -39.5t42.5 -98.5q0 -45 -30 -81.5t-74 -51.5l-157 -54l105 -316l164 56q24 8 46 8zM725 498l310 105l-105 315l-310 -107z" />
+    <glyph glyph-name="_384" unicode="&#xf199;" 
+d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960zM1280 352v436q-31 -35 -64 -55q-34 -22 -132.5 -85t-151.5 -99q-98 -69 -164 -69v0v0q-66 0 -164 69
+q-47 32 -142 92.5t-142 92.5q-12 8 -33 27t-31 27v-436q0 -40 28 -68t68 -28h832q40 0 68 28t28 68zM1280 925q0 41 -27.5 70t-68.5 29h-832q-40 0 -68 -28t-28 -68q0 -37 30.5 -76.5t67.5 -64.5q47 -32 137.5 -89t129.5 -83q3 -2 17 -11.5t21 -14t21 -13t23.5 -13
+t21.5 -9.5t22.5 -7.5t20.5 -2.5t20.5 2.5t22.5 7.5t21.5 9.5t23.5 13t21 13t21 14t17 11.5l267 174q35 23 66.5 62.5t31.5 73.5z" />
+    <glyph glyph-name="_385" unicode="&#xf19a;" horiz-adv-x="1792" 
+d="M127 640q0 163 67 313l367 -1005q-196 95 -315 281t-119 411zM1415 679q0 -19 -2.5 -38.5t-10 -49.5t-11.5 -44t-17.5 -59t-17.5 -58l-76 -256l-278 826q46 3 88 8q19 2 26 18.5t-2.5 31t-28.5 13.5l-205 -10q-75 1 -202 10q-12 1 -20.5 -5t-11.5 -15t-1.5 -18.5t9 -16.5
+t19.5 -8l80 -8l120 -328l-168 -504l-280 832q46 3 88 8q19 2 26 18.5t-2.5 31t-28.5 13.5l-205 -10q-7 0 -23 0.5t-26 0.5q105 160 274.5 253.5t367.5 93.5q147 0 280.5 -53t238.5 -149h-10q-55 0 -92 -40.5t-37 -95.5q0 -12 2 -24t4 -21.5t8 -23t9 -21t12 -22.5t12.5 -21
+t14.5 -24t14 -23q63 -107 63 -212zM909 573l237 -647q1 -6 5 -11q-126 -44 -255 -44q-112 0 -217 32zM1570 1009q95 -174 95 -369q0 -209 -104 -385.5t-279 -278.5l235 678q59 169 59 276q0 42 -6 79zM896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348t-191 -286
+t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71zM896 -215q173 0 331.5 68t273 182.5t182.5 273t68 331.5t-68 331.5t-182.5 273t-273 182.5t-331.5 68t-331.5 -68t-273 -182.5t-182.5 -273t-68 -331.5t68 -331.5t182.5 -273
+t273 -182.5t331.5 -68z" />
+    <glyph glyph-name="_386" unicode="&#xf19b;" horiz-adv-x="1792" 
+d="M1086 1536v-1536l-272 -128q-228 20 -414 102t-293 208.5t-107 272.5q0 140 100.5 263.5t275 205.5t391.5 108v-172q-217 -38 -356.5 -150t-139.5 -255q0 -152 154.5 -267t388.5 -145v1360zM1755 954l37 -390l-525 114l147 83q-119 70 -280 99v172q277 -33 481 -157z" />
+    <glyph glyph-name="_387" unicode="&#xf19c;" horiz-adv-x="2048" 
+d="M960 1536l960 -384v-128h-128q0 -26 -20.5 -45t-48.5 -19h-1526q-28 0 -48.5 19t-20.5 45h-128v128zM256 896h256v-768h128v768h256v-768h128v768h256v-768h128v768h256v-768h59q28 0 48.5 -19t20.5 -45v-64h-1664v64q0 26 20.5 45t48.5 19h59v768zM1851 -64
+q28 0 48.5 -19t20.5 -45v-128h-1920v128q0 26 20.5 45t48.5 19h1782z" />
+    <glyph glyph-name="_388" unicode="&#xf19d;" horiz-adv-x="2304" 
+d="M1774 700l18 -316q4 -69 -82 -128t-235 -93.5t-323 -34.5t-323 34.5t-235 93.5t-82 128l18 316l574 -181q22 -7 48 -7t48 7zM2304 1024q0 -23 -22 -31l-1120 -352q-4 -1 -10 -1t-10 1l-652 206q-43 -34 -71 -111.5t-34 -178.5q63 -36 63 -109q0 -69 -58 -107l58 -433
+q2 -14 -8 -25q-9 -11 -24 -11h-192q-15 0 -24 11q-10 11 -8 25l58 433q-58 38 -58 107q0 73 65 111q11 207 98 330l-333 104q-22 8 -22 31t22 31l1120 352q4 1 10 1t10 -1l1120 -352q22 -8 22 -31z" />
+    <glyph glyph-name="_389" unicode="&#xf19e;" 
+d="M859 579l13 -707q-62 11 -105 11q-41 0 -105 -11l13 707q-40 69 -168.5 295.5t-216.5 374.5t-181 287q58 -15 108 -15q44 0 111 15q63 -111 133.5 -229.5t167 -276.5t138.5 -227q37 61 109.5 177.5t117.5 190t105 176t107 189.5q54 -14 107 -14q56 0 114 14v0
+q-28 -39 -60 -88.5t-49.5 -78.5t-56.5 -96t-49 -84q-146 -248 -353 -610z" />
+    <glyph glyph-name="uniF1A0" unicode="&#xf1a0;" 
+d="M768 750h725q12 -67 12 -128q0 -217 -91 -387.5t-259.5 -266.5t-386.5 -96q-157 0 -299 60.5t-245 163.5t-163.5 245t-60.5 299t60.5 299t163.5 245t245 163.5t299 60.5q300 0 515 -201l-209 -201q-123 119 -306 119q-129 0 -238.5 -65t-173.5 -176.5t-64 -243.5
+t64 -243.5t173.5 -176.5t238.5 -65q87 0 160 24t120 60t82 82t51.5 87t22.5 78h-436v264z" />
+    <glyph glyph-name="f1a1" unicode="&#xf1a1;" horiz-adv-x="1792" 
+d="M1095 369q16 -16 0 -31q-62 -62 -199 -62t-199 62q-16 15 0 31q6 6 15 6t15 -6q48 -49 169 -49q120 0 169 49q6 6 15 6t15 -6zM788 550q0 -37 -26 -63t-63 -26t-63.5 26t-26.5 63q0 38 26.5 64t63.5 26t63 -26.5t26 -63.5zM1183 550q0 -37 -26.5 -63t-63.5 -26t-63 26
+t-26 63t26 63.5t63 26.5t63.5 -26t26.5 -64zM1434 670q0 49 -35 84t-85 35t-86 -36q-130 90 -311 96l63 283l200 -45q0 -37 26 -63t63 -26t63.5 26.5t26.5 63.5t-26.5 63.5t-63.5 26.5q-54 0 -80 -50l-221 49q-19 5 -25 -16l-69 -312q-180 -7 -309 -97q-35 37 -87 37
+q-50 0 -85 -35t-35 -84q0 -35 18.5 -64t49.5 -44q-6 -27 -6 -56q0 -142 140 -243t337 -101q198 0 338 101t140 243q0 32 -7 57q30 15 48 43.5t18 63.5zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191
+t348 71t348 -71t286 -191t191 -286t71 -348z" />
+    <glyph glyph-name="_392" unicode="&#xf1a2;" 
+d="M939 407q13 -13 0 -26q-53 -53 -171 -53t-171 53q-13 13 0 26q5 6 13 6t13 -6q42 -42 145 -42t145 42q5 6 13 6t13 -6zM676 563q0 -31 -23 -54t-54 -23t-54 23t-23 54q0 32 22.5 54.5t54.5 22.5t54.5 -22.5t22.5 -54.5zM1014 563q0 -31 -23 -54t-54 -23t-54 23t-23 54
+q0 32 22.5 54.5t54.5 22.5t54.5 -22.5t22.5 -54.5zM1229 666q0 42 -30 72t-73 30q-42 0 -73 -31q-113 78 -267 82l54 243l171 -39q1 -32 23.5 -54t53.5 -22q32 0 54.5 22.5t22.5 54.5t-22.5 54.5t-54.5 22.5q-48 0 -69 -43l-189 42q-17 5 -21 -13l-60 -268q-154 -6 -265 -83
+q-30 32 -74 32q-43 0 -73 -30t-30 -72q0 -30 16 -55t42 -38q-5 -25 -5 -48q0 -122 120 -208.5t289 -86.5q170 0 290 86.5t120 208.5q0 25 -6 49q25 13 40.5 37.5t15.5 54.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960
+q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="_393" unicode="&#xf1a3;" 
+d="M866 697l90 27v62q0 79 -58 135t-138 56t-138 -55.5t-58 -134.5v-283q0 -20 -14 -33.5t-33 -13.5t-32.5 13.5t-13.5 33.5v120h-151v-122q0 -82 57.5 -139t139.5 -57q81 0 138.5 56.5t57.5 136.5v280q0 19 13.5 33t33.5 14q19 0 32.5 -14t13.5 -33v-54zM1199 502v122h-150
+v-126q0 -20 -13.5 -33.5t-33.5 -13.5q-19 0 -32.5 14t-13.5 33v123l-90 -26l-60 28v-123q0 -80 58 -137t139 -57t138.5 57t57.5 139zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103
+t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="f1a4" unicode="&#xf1a4;" horiz-adv-x="1920" 
+d="M1062 824v118q0 42 -30 72t-72 30t-72 -30t-30 -72v-612q0 -175 -126 -299t-303 -124q-178 0 -303.5 125.5t-125.5 303.5v266h328v-262q0 -43 30 -72.5t72 -29.5t72 29.5t30 72.5v620q0 171 126.5 292t301.5 121q176 0 302 -122t126 -294v-136l-195 -58zM1592 602h328
+v-266q0 -178 -125.5 -303.5t-303.5 -125.5q-177 0 -303 124.5t-126 300.5v268l131 -61l195 58v-270q0 -42 30 -71.5t72 -29.5t72 29.5t30 71.5v275z" />
+    <glyph glyph-name="_395" unicode="&#xf1a5;" 
+d="M1472 160v480h-704v704h-480q-93 0 -158.5 -65.5t-65.5 -158.5v-480h704v-704h480q93 0 158.5 65.5t65.5 158.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5
+t84.5 -203.5z" />
+    <glyph glyph-name="_396" unicode="&#xf1a6;" horiz-adv-x="2048" 
+d="M328 1254h204v-983h-532v697h328v286zM328 435v369h-123v-369h123zM614 968v-697h205v697h-205zM614 1254v-204h205v204h-205zM901 968h533v-942h-533v163h328v82h-328v697zM1229 435v369h-123v-369h123zM1516 968h532v-942h-532v163h327v82h-327v697zM1843 435v369h-123
+v-369h123z" />
+    <glyph glyph-name="_397" unicode="&#xf1a7;" 
+d="M1046 516q0 -64 -38 -109t-91 -45q-43 0 -70 15v277q28 17 70 17q53 0 91 -45.5t38 -109.5zM703 944q0 -64 -38 -109.5t-91 -45.5q-43 0 -70 15v277q28 17 70 17q53 0 91 -45t38 -109zM1265 513q0 134 -88 229t-213 95q-20 0 -39 -3q-23 -78 -78 -136q-87 -95 -211 -101
+v-636l211 41v206q51 -19 117 -19q125 0 213 95t88 229zM922 940q0 134 -88.5 229t-213.5 95q-74 0 -141 -36h-186v-840l211 41v206q55 -19 116 -19q125 0 213.5 95t88.5 229zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960
+q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="_398" unicode="&#xf1a8;" horiz-adv-x="2038" 
+d="M1222 607q75 3 143.5 -20.5t118 -58.5t101 -94.5t84 -108t75.5 -120.5q33 -56 78.5 -109t75.5 -80.5t99 -88.5q-48 -30 -108.5 -57.5t-138.5 -59t-114 -47.5q-44 37 -74 115t-43.5 164.5t-33 180.5t-42.5 168.5t-72.5 123t-122.5 48.5l-10 -2l-6 -4q4 -5 13 -14
+q6 -5 28 -23.5t25.5 -22t19 -18t18 -20.5t11.5 -21t10.5 -27.5t4.5 -31t4 -40.5l1 -33q1 -26 -2.5 -57.5t-7.5 -52t-12.5 -58.5t-11.5 -53q-35 1 -101 -9.5t-98 -10.5q-39 0 -72 10q-2 16 -2 47q0 74 3 96q2 13 31.5 41.5t57 59t26.5 51.5q-24 2 -43 -24
+q-36 -53 -111.5 -99.5t-136.5 -46.5q-25 0 -75.5 63t-106.5 139.5t-84 96.5q-6 4 -27 30q-482 -112 -513 -112q-16 0 -28 11t-12 27q0 15 8.5 26.5t22.5 14.5l486 106q-8 14 -8 25t5.5 17.5t16 11.5t20 7t23 4.5t18.5 4.5q4 1 15.5 7.5t17.5 6.5q15 0 28 -16t20 -33
+q163 37 172 37q17 0 29.5 -11t12.5 -28q0 -15 -8.5 -26t-23.5 -14l-182 -40l-1 -16q-1 -26 81.5 -117.5t104.5 -91.5q47 0 119 80t72 129q0 36 -23.5 53t-51 18.5t-51 11.5t-23.5 34q0 16 10 34l-68 19q43 44 43 117q0 26 -5 58q82 16 144 16q44 0 71.5 -1.5t48.5 -8.5
+t31 -13.5t20.5 -24.5t15.5 -33.5t17 -47.5t24 -60l50 25q-3 -40 -23 -60t-42.5 -21t-40 -6.5t-16.5 -20.5zM1282 842q-5 5 -13.5 15.5t-12 14.5t-10.5 11.5t-10 10.5l-8 8t-8.5 7.5t-8 5t-8.5 4.5q-7 3 -14.5 5t-20.5 2.5t-22 0.5h-32.5h-37.5q-126 0 -217 -43
+q16 30 36 46.5t54 29.5t65.5 36t46 36.5t50 55t43.5 50.5q12 -9 28 -31.5t32 -36.5t38 -13l12 1v-76l22 -1q247 95 371 190q28 21 50 39t42.5 37.5t33 31t29.5 34t24 31t24.5 37t23 38t27 47.5t29.5 53l7 9q-2 -53 -43 -139q-79 -165 -205 -264t-306 -142q-14 -3 -42 -7.5
+t-50 -9.5t-39 -14q3 -19 24.5 -46t21.5 -34q0 -11 -26 -30zM1061 -79q39 26 131.5 47.5t146.5 21.5q9 0 22.5 -15.5t28 -42.5t26 -50t24 -51t14.5 -33q-121 -45 -244 -45q-61 0 -125 11zM822 568l48 12l109 -177l-73 -48zM1323 51q3 -15 3 -16q0 -7 -17.5 -14.5t-46 -13
+t-54 -9.5t-53.5 -7.5t-32 -4.5l-7 43q21 2 60.5 8.5t72 10t60.5 3.5h14zM866 679l-96 -20l-6 17q10 1 32.5 7t34.5 6q19 0 35 -10zM1061 45h31l10 -83l-41 -12v95zM1950 1535v1v-1zM1950 1535l-1 -5l-2 -2l1 3zM1950 1535l1 1z" />
+    <glyph glyph-name="_399" unicode="&#xf1a9;" 
+d="M1167 -50q-5 19 -24 5q-30 -22 -87 -39t-131 -17q-129 0 -193 49q-5 4 -13 4q-11 0 -26 -12q-7 -6 -7.5 -16t7.5 -20q34 -32 87.5 -46t102.5 -12.5t99 4.5q41 4 84.5 20.5t65 30t28.5 20.5q12 12 7 29zM1128 65q-19 47 -39 61q-23 15 -76 15q-47 0 -71 -10
+q-29 -12 -78 -56q-26 -24 -12 -44q9 -8 17.5 -4.5t31.5 23.5q3 2 10.5 8.5t10.5 8.5t10 7t11.5 7t12.5 5t15 4.5t16.5 2.5t20.5 1q27 0 44.5 -7.5t23 -14.5t13.5 -22q10 -17 12.5 -20t12.5 1q23 12 14 34zM1483 346q0 22 -5 44.5t-16.5 45t-34 36.5t-52.5 14
+q-33 0 -97 -41.5t-129 -83.5t-101 -42q-27 -1 -63.5 19t-76 49t-83.5 58t-100 49t-111 19q-115 -1 -197 -78.5t-84 -178.5q-2 -112 74 -164q29 -20 62.5 -28.5t103.5 -8.5q57 0 132 32.5t134 71t120 70.5t93 31q26 -1 65 -31.5t71.5 -67t68 -67.5t55.5 -32q35 -3 58.5 14
+t55.5 63q28 41 42.5 101t14.5 106zM1536 506q0 -164 -62 -304.5t-166 -236t-242.5 -149.5t-290.5 -54t-293 57.5t-247.5 157t-170.5 241.5t-64 302q0 89 19.5 172.5t49 145.5t70.5 118.5t78.5 94t78.5 69.5t64.5 46.5t42.5 24.5q14 8 51 26.5t54.5 28.5t48 30t60.5 44
+q36 28 58 72.5t30 125.5q129 -155 186 -193q44 -29 130 -68t129 -66q21 -13 39 -25t60.5 -46.5t76 -70.5t75 -95t69 -122t47 -148.5t19.5 -177.5z" />
+    <glyph glyph-name="_400" unicode="&#xf1aa;" 
+d="M1070 463l-160 -160l-151 -152l-30 -30q-65 -64 -151.5 -87t-171.5 -2q-16 -70 -72 -115t-129 -45q-85 0 -145 60.5t-60 145.5q0 72 44.5 128t113.5 72q-22 86 1 173t88 152l12 12l151 -152l-11 -11q-37 -37 -37 -89t37 -90q37 -37 89 -37t89 37l30 30l151 152l161 160z
+M729 1145l12 -12l-152 -152l-12 12q-37 37 -89 37t-89 -37t-37 -89.5t37 -89.5l29 -29l152 -152l160 -160l-151 -152l-161 160l-151 152l-30 30q-68 67 -90 159.5t5 179.5q-70 15 -115 71t-45 129q0 85 60 145.5t145 60.5q76 0 133.5 -49t69.5 -123q84 20 169.5 -3.5
+t149.5 -87.5zM1536 78q0 -85 -60 -145.5t-145 -60.5q-74 0 -131 47t-71 118q-86 -28 -179.5 -6t-161.5 90l-11 12l151 152l12 -12q37 -37 89 -37t89 37t37 89t-37 89l-30 30l-152 152l-160 160l152 152l160 -160l152 -152l29 -30q64 -64 87.5 -150.5t2.5 -171.5
+q76 -11 126.5 -68.5t50.5 -134.5zM1534 1202q0 -77 -51 -135t-127 -69q26 -85 3 -176.5t-90 -158.5l-12 -12l-151 152l12 12q37 37 37 89t-37 89t-89 37t-89 -37l-30 -30l-152 -152l-160 -160l-152 152l161 160l152 152l29 30q67 67 159 89.5t178 -3.5q11 75 68.5 126
+t135.5 51q85 0 145 -60.5t60 -145.5z" />
+    <glyph glyph-name="f1ab" unicode="&#xf1ab;" 
+d="M654 458q-1 -3 -12.5 0.5t-31.5 11.5l-20 9q-44 20 -87 49q-7 5 -41 31.5t-38 28.5q-67 -103 -134 -181q-81 -95 -105 -110q-4 -2 -19.5 -4t-18.5 0q6 4 82 92q21 24 85.5 115t78.5 118q17 30 51 98.5t36 77.5q-8 1 -110 -33q-8 -2 -27.5 -7.5t-34.5 -9.5t-17 -5
+q-2 -2 -2 -10.5t-1 -9.5q-5 -10 -31 -15q-23 -7 -47 0q-18 4 -28 21q-4 6 -5 23q6 2 24.5 5t29.5 6q58 16 105 32q100 35 102 35q10 2 43 19.5t44 21.5q9 3 21.5 8t14.5 5.5t6 -0.5q2 -12 -1 -33q0 -2 -12.5 -27t-26.5 -53.5t-17 -33.5q-25 -50 -77 -131l64 -28
+q12 -6 74.5 -32t67.5 -28q4 -1 10.5 -25.5t4.5 -30.5zM449 944q3 -15 -4 -28q-12 -23 -50 -38q-30 -12 -60 -12q-26 3 -49 26q-14 15 -18 41l1 3q3 -3 19.5 -5t26.5 0t58 16q36 12 55 14q17 0 21 -17zM1147 815l63 -227l-139 42zM39 15l694 232v1032l-694 -233v-1031z
+M1280 332l102 -31l-181 657l-100 31l-216 -536l102 -31l45 110l211 -65zM777 1294l573 -184v380zM1088 -29l158 -13l-54 -160l-40 66q-130 -83 -276 -108q-58 -12 -91 -12h-84q-79 0 -199.5 39t-183.5 85q-8 7 -8 16q0 8 5 13.5t13 5.5q4 0 18 -7.5t30.5 -16.5t20.5 -11
+q73 -37 159.5 -61.5t157.5 -24.5q95 0 167 14.5t157 50.5q15 7 30.5 15.5t34 19t28.5 16.5zM1536 1050v-1079l-774 246q-14 -6 -375 -127.5t-368 -121.5q-13 0 -18 13q0 1 -1 3v1078q3 9 4 10q5 6 20 11q107 36 149 50v384l558 -198q2 0 160.5 55t316 108.5t161.5 53.5
+q20 0 20 -21v-418z" />
+    <glyph glyph-name="_402" unicode="&#xf1ac;" horiz-adv-x="1792" 
+d="M288 1152q66 0 113 -47t47 -113v-1088q0 -66 -47 -113t-113 -47h-128q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h128zM1664 989q58 -34 93 -93t35 -128v-768q0 -106 -75 -181t-181 -75h-864q-66 0 -113 47t-47 113v1536q0 40 28 68t68 28h672q40 0 88 -20t76 -48
+l152 -152q28 -28 48 -76t20 -88v-163zM928 0v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM928 256v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM928 512v128q0 14 -9 23
+t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1184 0v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1184 256v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128
+q14 0 23 9t9 23zM1184 512v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1440 0v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1440 256v128q0 14 -9 23t-23 9h-128
+q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1440 512v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1536 896v256h-160q-40 0 -68 28t-28 68v160h-640v-512h896z" />
+    <glyph glyph-name="_403" unicode="&#xf1ad;" 
+d="M1344 1536q26 0 45 -19t19 -45v-1664q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v1664q0 26 19 45t45 19h1280zM512 1248v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM512 992v-64q0 -14 9 -23t23 -9h64q14 0 23 9
+t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM512 736v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM512 480v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM384 160v64
+q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM384 416v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM384 672v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64
+q14 0 23 9t9 23zM384 928v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM384 1184v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM896 -96v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9
+t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM896 416v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM896 672v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM896 928v64
+q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM896 1184v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1152 160v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64
+q14 0 23 9t9 23zM1152 416v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1152 672v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1152 928v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9
+t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1152 1184v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23z" />
+    <glyph glyph-name="_404" unicode="&#xf1ae;" horiz-adv-x="1280" 
+d="M1188 988l-292 -292v-824q0 -46 -33 -79t-79 -33t-79 33t-33 79v384h-64v-384q0 -46 -33 -79t-79 -33t-79 33t-33 79v824l-292 292q-28 28 -28 68t28 68q29 28 68.5 28t67.5 -28l228 -228h368l228 228q28 28 68 28t68 -28q28 -29 28 -68.5t-28 -67.5zM864 1152
+q0 -93 -65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5z" />
+    <glyph glyph-name="uniF1B1" unicode="&#xf1b0;" horiz-adv-x="1664" 
+d="M780 1064q0 -60 -19 -113.5t-63 -92.5t-105 -39q-76 0 -138 57.5t-92 135.5t-30 151q0 60 19 113.5t63 92.5t105 39q77 0 138.5 -57.5t91.5 -135t30 -151.5zM438 581q0 -80 -42 -139t-119 -59q-76 0 -141.5 55.5t-100.5 133.5t-35 152q0 80 42 139.5t119 59.5
+q76 0 141.5 -55.5t100.5 -134t35 -152.5zM832 608q118 0 255 -97.5t229 -237t92 -254.5q0 -46 -17 -76.5t-48.5 -45t-64.5 -20t-76 -5.5q-68 0 -187.5 45t-182.5 45q-66 0 -192.5 -44.5t-200.5 -44.5q-183 0 -183 146q0 86 56 191.5t139.5 192.5t187.5 146t193 59zM1071 819
+q-61 0 -105 39t-63 92.5t-19 113.5q0 74 30 151.5t91.5 135t138.5 57.5q61 0 105 -39t63 -92.5t19 -113.5q0 -73 -30 -151t-92 -135.5t-138 -57.5zM1503 923q77 0 119 -59.5t42 -139.5q0 -74 -35 -152t-100.5 -133.5t-141.5 -55.5q-77 0 -119 59t-42 139q0 74 35 152.5
+t100.5 134t141.5 55.5z" />
+    <glyph glyph-name="_406" unicode="&#xf1b1;" horiz-adv-x="768" 
+d="M704 1008q0 -145 -57 -243.5t-152 -135.5l45 -821q2 -26 -16 -45t-44 -19h-192q-26 0 -44 19t-16 45l45 821q-95 37 -152 135.5t-57 243.5q0 128 42.5 249.5t117.5 200t160 78.5t160 -78.5t117.5 -200t42.5 -249.5z" />
+    <glyph glyph-name="_407" unicode="&#xf1b2;" horiz-adv-x="1792" 
+d="M896 -93l640 349v636l-640 -233v-752zM832 772l698 254l-698 254l-698 -254zM1664 1024v-768q0 -35 -18 -65t-49 -47l-704 -384q-28 -16 -61 -16t-61 16l-704 384q-31 17 -49 47t-18 65v768q0 40 23 73t61 47l704 256q22 8 44 8t44 -8l704 -256q38 -14 61 -47t23 -73z
+" />
+    <glyph glyph-name="_408" unicode="&#xf1b3;" horiz-adv-x="2304" 
+d="M640 -96l384 192v314l-384 -164v-342zM576 358l404 173l-404 173l-404 -173zM1664 -96l384 192v314l-384 -164v-342zM1600 358l404 173l-404 173l-404 -173zM1152 651l384 165v266l-384 -164v-267zM1088 1030l441 189l-441 189l-441 -189zM2176 512v-416q0 -36 -19 -67
+t-52 -47l-448 -224q-25 -14 -57 -14t-57 14l-448 224q-4 2 -7 4q-2 -2 -7 -4l-448 -224q-25 -14 -57 -14t-57 14l-448 224q-33 16 -52 47t-19 67v416q0 38 21.5 70t56.5 48l434 186v400q0 38 21.5 70t56.5 48l448 192q23 10 50 10t50 -10l448 -192q35 -16 56.5 -48t21.5 -70
+v-400l434 -186q36 -16 57 -48t21 -70z" />
+    <glyph glyph-name="_409" unicode="&#xf1b4;" horiz-adv-x="2048" 
+d="M1848 1197h-511v-124h511v124zM1596 771q-90 0 -146 -52.5t-62 -142.5h408q-18 195 -200 195zM1612 186q63 0 122 32t76 87h221q-100 -307 -427 -307q-214 0 -340.5 132t-126.5 347q0 208 130.5 345.5t336.5 137.5q138 0 240.5 -68t153 -179t50.5 -248q0 -17 -2 -47h-658
+q0 -111 57.5 -171.5t166.5 -60.5zM277 236h296q205 0 205 167q0 180 -199 180h-302v-347zM277 773h281q78 0 123.5 36.5t45.5 113.5q0 144 -190 144h-260v-294zM0 1282h594q87 0 155 -14t126.5 -47.5t90 -96.5t31.5 -154q0 -181 -172 -263q114 -32 172 -115t58 -204
+q0 -75 -24.5 -136.5t-66 -103.5t-98.5 -71t-121 -42t-134 -13h-611v1260z" />
+    <glyph glyph-name="_410" unicode="&#xf1b5;" 
+d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960zM499 1041h-371v-787h382q117 0 197 57.5t80 170.5q0 158 -143 200q107 52 107 164q0 57 -19.5 96.5
+t-56.5 60.5t-79 29.5t-97 8.5zM477 723h-176v184h163q119 0 119 -90q0 -94 -106 -94zM486 388h-185v217h189q124 0 124 -113q0 -104 -128 -104zM1136 356q-68 0 -104 38t-36 107h411q1 10 1 30q0 132 -74.5 220.5t-203.5 88.5q-128 0 -210 -86t-82 -216q0 -135 79 -217
+t213 -82q205 0 267 191h-138q-11 -34 -47.5 -54t-75.5 -20zM1126 722q113 0 124 -122h-254q4 56 39 89t91 33zM964 988h319v-77h-319v77z" />
+    <glyph glyph-name="_411" unicode="&#xf1b6;" horiz-adv-x="1792" 
+d="M1582 954q0 -101 -71.5 -172.5t-172.5 -71.5t-172.5 71.5t-71.5 172.5t71.5 172.5t172.5 71.5t172.5 -71.5t71.5 -172.5zM812 212q0 104 -73 177t-177 73q-27 0 -54 -6l104 -42q77 -31 109.5 -106.5t1.5 -151.5q-31 -77 -107 -109t-152 -1q-21 8 -62 24.5t-61 24.5
+q32 -60 91 -96.5t130 -36.5q104 0 177 73t73 177zM1642 953q0 126 -89.5 215.5t-215.5 89.5q-127 0 -216.5 -89.5t-89.5 -215.5q0 -127 89.5 -216t216.5 -89q126 0 215.5 89t89.5 216zM1792 953q0 -189 -133.5 -322t-321.5 -133l-437 -319q-12 -129 -109 -218t-229 -89
+q-121 0 -214 76t-118 192l-230 92v429l389 -157q79 48 173 48q13 0 35 -2l284 407q2 187 135.5 319t320.5 132q188 0 321.5 -133.5t133.5 -321.5z" />
+    <glyph glyph-name="_412" unicode="&#xf1b7;" 
+d="M1242 889q0 80 -57 136.5t-137 56.5t-136.5 -57t-56.5 -136q0 -80 56.5 -136.5t136.5 -56.5t137 56.5t57 136.5zM632 301q0 -83 -58 -140.5t-140 -57.5q-56 0 -103 29t-72 77q52 -20 98 -40q60 -24 120 1.5t85 86.5q24 60 -1.5 120t-86.5 84l-82 33q22 5 42 5
+q82 0 140 -57.5t58 -140.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v153l172 -69q20 -92 93.5 -152t168.5 -60q104 0 181 70t87 173l345 252q150 0 255.5 105.5t105.5 254.5q0 150 -105.5 255.5t-255.5 105.5
+q-148 0 -253 -104.5t-107 -252.5l-225 -322q-9 1 -28 1q-75 0 -137 -37l-297 119v468q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5zM1289 887q0 -100 -71 -170.5t-171 -70.5t-170.5 70.5t-70.5 170.5t70.5 171t170.5 71q101 0 171.5 -70.5t70.5 -171.5z
+" />
+    <glyph glyph-name="_413" unicode="&#xf1b8;" horiz-adv-x="1792" 
+d="M836 367l-15 -368l-2 -22l-420 29q-36 3 -67 31.5t-47 65.5q-11 27 -14.5 55t4 65t12 55t21.5 64t19 53q78 -12 509 -28zM449 953l180 -379l-147 92q-63 -72 -111.5 -144.5t-72.5 -125t-39.5 -94.5t-18.5 -63l-4 -21l-190 357q-17 26 -18 56t6 47l8 18q35 63 114 188
+l-140 86zM1680 436l-188 -359q-12 -29 -36.5 -46.5t-43.5 -20.5l-18 -4q-71 -7 -219 -12l8 -164l-230 367l211 362l7 -173q170 -16 283 -5t170 33zM895 1360q-47 -63 -265 -435l-317 187l-19 12l225 356q20 31 60 45t80 10q24 -2 48.5 -12t42 -21t41.5 -33t36 -34.5
+t36 -39.5t32 -35zM1550 1053l212 -363q18 -37 12.5 -76t-27.5 -74q-13 -20 -33 -37t-38 -28t-48.5 -22t-47 -16t-51.5 -14t-46 -12q-34 72 -265 436l313 195zM1407 1279l142 83l-220 -373l-419 20l151 86q-34 89 -75 166t-75.5 123.5t-64.5 80t-47 46.5l-17 13l405 -1
+q31 3 58 -10.5t39 -28.5l11 -15q39 -61 112 -190z" />
+    <glyph glyph-name="_414" unicode="&#xf1b9;" horiz-adv-x="2048" 
+d="M480 448q0 66 -47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47t113 47t47 113zM516 768h1016l-89 357q-2 8 -14 17.5t-21 9.5h-768q-9 0 -21 -9.5t-14 -17.5zM1888 448q0 66 -47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47t113 47t47 113zM2048 544v-384
+q0 -14 -9 -23t-23 -9h-96v-128q0 -80 -56 -136t-136 -56t-136 56t-56 136v128h-1024v-128q0 -80 -56 -136t-136 -56t-136 56t-56 136v128h-96q-14 0 -23 9t-9 23v384q0 93 65.5 158.5t158.5 65.5h28l105 419q23 94 104 157.5t179 63.5h768q98 0 179 -63.5t104 -157.5
+l105 -419h28q93 0 158.5 -65.5t65.5 -158.5z" />
+    <glyph glyph-name="_415" unicode="&#xf1ba;" horiz-adv-x="2048" 
+d="M1824 640q93 0 158.5 -65.5t65.5 -158.5v-384q0 -14 -9 -23t-23 -9h-96v-64q0 -80 -56 -136t-136 -56t-136 56t-56 136v64h-1024v-64q0 -80 -56 -136t-136 -56t-136 56t-56 136v64h-96q-14 0 -23 9t-9 23v384q0 93 65.5 158.5t158.5 65.5h28l105 419q23 94 104 157.5
+t179 63.5h128v224q0 14 9 23t23 9h448q14 0 23 -9t9 -23v-224h128q98 0 179 -63.5t104 -157.5l105 -419h28zM320 160q66 0 113 47t47 113t-47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47zM516 640h1016l-89 357q-2 8 -14 17.5t-21 9.5h-768q-9 0 -21 -9.5t-14 -17.5z
+M1728 160q66 0 113 47t47 113t-47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47z" />
+    <glyph glyph-name="_416" unicode="&#xf1bb;" 
+d="M1504 64q0 -26 -19 -45t-45 -19h-462q1 -17 6 -87.5t5 -108.5q0 -25 -18 -42.5t-43 -17.5h-320q-25 0 -43 17.5t-18 42.5q0 38 5 108.5t6 87.5h-462q-26 0 -45 19t-19 45t19 45l402 403h-229q-26 0 -45 19t-19 45t19 45l402 403h-197q-26 0 -45 19t-19 45t19 45l384 384
+q19 19 45 19t45 -19l384 -384q19 -19 19 -45t-19 -45t-45 -19h-197l402 -403q19 -19 19 -45t-19 -45t-45 -19h-229l402 -403q19 -19 19 -45z" />
+    <glyph glyph-name="_417" unicode="&#xf1bc;" 
+d="M1127 326q0 32 -30 51q-193 115 -447 115q-133 0 -287 -34q-42 -9 -42 -52q0 -20 13.5 -34.5t35.5 -14.5q5 0 37 8q132 27 243 27q226 0 397 -103q19 -11 33 -11q19 0 33 13.5t14 34.5zM1223 541q0 40 -35 61q-237 141 -548 141q-153 0 -303 -42q-48 -13 -48 -64
+q0 -25 17.5 -42.5t42.5 -17.5q7 0 37 8q122 33 251 33q279 0 488 -124q24 -13 38 -13q25 0 42.5 17.5t17.5 42.5zM1331 789q0 47 -40 70q-126 73 -293 110.5t-343 37.5q-204 0 -364 -47q-23 -7 -38.5 -25.5t-15.5 -48.5q0 -31 20.5 -52t51.5 -21q11 0 40 8q133 37 307 37
+q159 0 309.5 -34t253.5 -95q21 -12 40 -12q29 0 50.5 20.5t21.5 51.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="_418" unicode="&#xf1bd;" horiz-adv-x="1024" 
+d="M1024 1233l-303 -582l24 -31h279v-415h-507l-44 -30l-142 -273l-30 -30h-301v303l303 583l-24 30h-279v415h507l44 30l142 273l30 30h301v-303z" />
+    <glyph glyph-name="_419" unicode="&#xf1be;" horiz-adv-x="2304" 
+d="M784 164l16 241l-16 523q-1 10 -7.5 17t-16.5 7q-9 0 -16 -7t-7 -17l-14 -523l14 -241q1 -10 7.5 -16.5t15.5 -6.5q22 0 24 23zM1080 193l11 211l-12 586q0 16 -13 24q-8 5 -16 5t-16 -5q-13 -8 -13 -24l-1 -6l-10 -579q0 -1 11 -236v-1q0 -10 6 -17q9 -11 23 -11
+q11 0 20 9q9 7 9 20zM35 533l20 -128l-20 -126q-2 -9 -9 -9t-9 9l-17 126l17 128q2 9 9 9t9 -9zM121 612l26 -207l-26 -203q-2 -9 -10 -9q-9 0 -9 10l-23 202l23 207q0 9 9 9q8 0 10 -9zM401 159zM213 650l25 -245l-25 -237q0 -11 -11 -11q-10 0 -12 11l-21 237l21 245
+q2 12 12 12q11 0 11 -12zM307 657l23 -252l-23 -244q-2 -13 -14 -13q-13 0 -13 13l-21 244l21 252q0 13 13 13q12 0 14 -13zM401 639l21 -234l-21 -246q-2 -16 -16 -16q-6 0 -10.5 4.5t-4.5 11.5l-20 246l20 234q0 6 4.5 10.5t10.5 4.5q14 0 16 -15zM784 164zM495 785
+l21 -380l-21 -246q0 -7 -5 -12.5t-12 -5.5q-16 0 -18 18l-18 246l18 380q2 18 18 18q7 0 12 -5.5t5 -12.5zM589 871l19 -468l-19 -244q0 -8 -5.5 -13.5t-13.5 -5.5q-18 0 -20 19l-16 244l16 468q2 19 20 19q8 0 13.5 -5.5t5.5 -13.5zM687 911l18 -506l-18 -242
+q-2 -21 -22 -21q-19 0 -21 21l-16 242l16 506q0 9 6.5 15.5t14.5 6.5q9 0 15 -6.5t7 -15.5zM1079 169v0v0v0zM881 915l15 -510l-15 -239q0 -10 -7.5 -17.5t-17.5 -7.5t-17 7t-8 18l-14 239l14 510q0 11 7.5 18t17.5 7t17.5 -7t7.5 -18zM980 896l14 -492l-14 -236
+q0 -11 -8 -19t-19 -8t-19 8t-9 19l-12 236l12 492q1 12 9 20t19 8t18.5 -8t8.5 -20zM1192 404l-14 -231v0q0 -13 -9 -22t-22 -9t-22 9t-10 22l-6 114l-6 117l12 636v3q2 15 12 24q9 7 20 7q8 0 15 -5q14 -8 16 -26zM2304 423q0 -117 -83 -199.5t-200 -82.5h-786
+q-13 2 -22 11t-9 22v899q0 23 28 33q85 34 181 34q195 0 338 -131.5t160 -323.5q53 22 110 22q117 0 200 -83t83 -201z" />
+    <glyph glyph-name="uniF1C0" unicode="&#xf1c0;" 
+d="M768 768q237 0 443 43t325 127v-170q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5t-103 128v170q119 -84 325 -127t443 -43zM768 0q237 0 443 43t325 127v-170q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5t-103 128v170q119 -84 325 -127
+t443 -43zM768 384q237 0 443 43t325 127v-170q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5t-103 128v170q119 -84 325 -127t443 -43zM768 1536q208 0 385 -34.5t280 -93.5t103 -128v-128q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5
+t-103 128v128q0 69 103 128t280 93.5t385 34.5z" />
+    <glyph glyph-name="uniF1C1" unicode="&#xf1c1;" 
+d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z
+M894 465q33 -26 84 -56q59 7 117 7q147 0 177 -49q16 -22 2 -52q0 -1 -1 -2l-2 -2v-1q-6 -38 -71 -38q-48 0 -115 20t-130 53q-221 -24 -392 -83q-153 -262 -242 -262q-15 0 -28 7l-24 12q-1 1 -6 5q-10 10 -6 36q9 40 56 91.5t132 96.5q14 9 23 -6q2 -2 2 -4q52 85 107 197
+q68 136 104 262q-24 82 -30.5 159.5t6.5 127.5q11 40 42 40h21h1q23 0 35 -15q18 -21 9 -68q-2 -6 -4 -8q1 -3 1 -8v-30q-2 -123 -14 -192q55 -164 146 -238zM318 54q52 24 137 158q-51 -40 -87.5 -84t-49.5 -74zM716 974q-15 -42 -2 -132q1 7 7 44q0 3 7 43q1 4 4 8
+q-1 1 -1 2q-1 2 -1 3q-1 22 -13 36q0 -1 -1 -2v-2zM592 313q135 54 284 81q-2 1 -13 9.5t-16 13.5q-76 67 -127 176q-27 -86 -83 -197q-30 -56 -45 -83zM1238 329q-24 24 -140 24q76 -28 124 -28q14 0 18 1q0 1 -2 3z" />
+    <glyph glyph-name="_422" unicode="&#xf1c2;" 
+d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z
+M233 768v-107h70l164 -661h159l128 485q7 20 10 46q2 16 2 24h4l3 -24q1 -3 3.5 -20t5.5 -26l128 -485h159l164 661h70v107h-300v-107h90l-99 -438q-5 -20 -7 -46l-2 -21h-4q0 3 -0.5 6.5t-1.5 8t-1 6.5q-1 5 -4 21t-5 25l-144 545h-114l-144 -545q-2 -9 -4.5 -24.5
+t-3.5 -21.5l-4 -21h-4l-2 21q-2 26 -7 46l-99 438h90v107h-300z" />
+    <glyph glyph-name="_423" unicode="&#xf1c3;" 
+d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z
+M429 106v-106h281v106h-75l103 161q5 7 10 16.5t7.5 13.5t3.5 4h2q1 -4 5 -10q2 -4 4.5 -7.5t6 -8t6.5 -8.5l107 -161h-76v-106h291v106h-68l-192 273l195 282h67v107h-279v-107h74l-103 -159q-4 -7 -10 -16.5t-9 -13.5l-2 -3h-2q-1 4 -5 10q-6 11 -17 23l-106 159h76v107
+h-290v-107h68l189 -272l-194 -283h-68z" />
+    <glyph glyph-name="_424" unicode="&#xf1c4;" 
+d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z
+M416 106v-106h327v106h-93v167h137q76 0 118 15q67 23 106.5 87t39.5 146q0 81 -37 141t-100 87q-48 19 -130 19h-368v-107h92v-555h-92zM769 386h-119v268h120q52 0 83 -18q56 -33 56 -115q0 -89 -62 -120q-31 -15 -78 -15z" />
+    <glyph glyph-name="_425" unicode="&#xf1c5;" 
+d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z
+M1280 320v-320h-1024v192l192 192l128 -128l384 384zM448 512q-80 0 -136 56t-56 136t56 136t136 56t136 -56t56 -136t-56 -136t-136 -56z" />
+    <glyph glyph-name="_426" unicode="&#xf1c6;" 
+d="M640 1152v128h-128v-128h128zM768 1024v128h-128v-128h128zM640 896v128h-128v-128h128zM768 768v128h-128v-128h128zM1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400
+v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-128v-128h-128v128h-512v-1536h1280zM781 593l107 -349q8 -27 8 -52q0 -83 -72.5 -137.5t-183.5 -54.5t-183.5 54.5t-72.5 137.5q0 25 8 52q21 63 120 396v128h128v-128h79
+q22 0 39 -13t23 -34zM640 128q53 0 90.5 19t37.5 45t-37.5 45t-90.5 19t-90.5 -19t-37.5 -45t37.5 -45t90.5 -19z" />
+    <glyph glyph-name="_427" unicode="&#xf1c7;" 
+d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z
+M620 686q20 -8 20 -30v-544q0 -22 -20 -30q-8 -2 -12 -2q-12 0 -23 9l-166 167h-131q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h131l166 167q16 15 35 7zM1037 -3q31 0 50 24q129 159 129 363t-129 363q-16 21 -43 24t-47 -14q-21 -17 -23.5 -43.5t14.5 -47.5
+q100 -123 100 -282t-100 -282q-17 -21 -14.5 -47.5t23.5 -42.5q18 -15 40 -15zM826 145q27 0 47 20q87 93 87 219t-87 219q-18 19 -45 20t-46 -17t-20 -44.5t18 -46.5q52 -57 52 -131t-52 -131q-19 -20 -18 -46.5t20 -44.5q20 -17 44 -17z" />
+    <glyph glyph-name="_428" unicode="&#xf1c8;" 
+d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z
+M768 768q52 0 90 -38t38 -90v-384q0 -52 -38 -90t-90 -38h-384q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h384zM1260 766q20 -8 20 -30v-576q0 -22 -20 -30q-8 -2 -12 -2q-14 0 -23 9l-265 266v90l265 266q9 9 23 9q4 0 12 -2z" />
+    <glyph glyph-name="_429" unicode="&#xf1c9;" 
+d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z
+M480 768q8 11 21 12.5t24 -6.5l51 -38q11 -8 12.5 -21t-6.5 -24l-182 -243l182 -243q8 -11 6.5 -24t-12.5 -21l-51 -38q-11 -8 -24 -6.5t-21 12.5l-226 301q-14 19 0 38zM1282 467q14 -19 0 -38l-226 -301q-8 -11 -21 -12.5t-24 6.5l-51 38q-11 8 -12.5 21t6.5 24l182 243
+l-182 243q-8 11 -6.5 24t12.5 21l51 38q11 8 24 6.5t21 -12.5zM662 6q-13 2 -20.5 13t-5.5 24l138 831q2 13 13 20.5t24 5.5l63 -10q13 -2 20.5 -13t5.5 -24l-138 -831q-2 -13 -13 -20.5t-24 -5.5z" />
+    <glyph glyph-name="_430" unicode="&#xf1ca;" 
+d="M1497 709v-198q-101 -23 -198 -23q-65 -136 -165.5 -271t-181.5 -215.5t-128 -106.5q-80 -45 -162 3q-28 17 -60.5 43.5t-85 83.5t-102.5 128.5t-107.5 184t-105.5 244t-91.5 314.5t-70.5 390h283q26 -218 70 -398.5t104.5 -317t121.5 -235.5t140 -195q169 169 287 406
+q-142 72 -223 220t-81 333q0 192 104 314.5t284 122.5q178 0 273 -105.5t95 -297.5q0 -159 -58 -286q-7 -1 -19.5 -3t-46 -2t-63 6t-62 25.5t-50.5 51.5q31 103 31 184q0 87 -29 132t-79 45q-53 0 -85 -49.5t-32 -140.5q0 -186 105 -293.5t267 -107.5q62 0 121 14z" />
+    <glyph glyph-name="_431" unicode="&#xf1cb;" horiz-adv-x="1792" 
+d="M216 367l603 -402v359l-334 223zM154 511l193 129l-193 129v-258zM973 -35l603 402l-269 180l-334 -223v-359zM896 458l272 182l-272 182l-272 -182zM485 733l334 223v359l-603 -402zM1445 640l193 -129v258zM1307 733l269 180l-603 402v-359zM1792 913v-546
+q0 -41 -34 -64l-819 -546q-21 -13 -43 -13t-43 13l-819 546q-34 23 -34 64v546q0 41 34 64l819 546q21 13 43 13t43 -13l819 -546q34 -23 34 -64z" />
+    <glyph glyph-name="_432" unicode="&#xf1cc;" horiz-adv-x="2048" 
+d="M1800 764q111 -46 179.5 -145.5t68.5 -221.5q0 -164 -118 -280.5t-285 -116.5q-4 0 -11.5 0.5t-10.5 0.5h-1209h-1h-2h-5q-170 10 -288 125.5t-118 280.5q0 110 55 203t147 147q-12 39 -12 82q0 115 82 196t199 81q95 0 172 -58q75 154 222.5 248t326.5 94
+q166 0 306 -80.5t221.5 -218.5t81.5 -301q0 -6 -0.5 -18t-0.5 -18zM468 498q0 -122 84 -193t208 -71q137 0 240 99q-16 20 -47.5 56.5t-43.5 50.5q-67 -65 -144 -65q-55 0 -93.5 33.5t-38.5 87.5q0 53 38.5 87t91.5 34q44 0 84.5 -21t73 -55t65 -75t69 -82t77 -75t97 -55
+t121.5 -21q121 0 204.5 71.5t83.5 190.5q0 121 -84 192t-207 71q-143 0 -241 -97l93 -108q66 64 142 64q52 0 92 -33t40 -84q0 -57 -37 -91.5t-94 -34.5q-43 0 -82.5 21t-72 55t-65.5 75t-69.5 82t-77.5 75t-96.5 55t-118.5 21q-122 0 -207 -70.5t-85 -189.5z" />
+    <glyph glyph-name="_433" unicode="&#xf1cd;" horiz-adv-x="1792" 
+d="M896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71zM896 1408q-190 0 -361 -90l194 -194q82 28 167 28t167 -28l194 194q-171 90 -361 90zM218 279l194 194
+q-28 82 -28 167t28 167l-194 194q-90 -171 -90 -361t90 -361zM896 -128q190 0 361 90l-194 194q-82 -28 -167 -28t-167 28l-194 -194q171 -90 361 -90zM896 256q159 0 271.5 112.5t112.5 271.5t-112.5 271.5t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5
+t271.5 -112.5zM1380 473l194 -194q90 171 90 361t-90 361l-194 -194q28 -82 28 -167t-28 -167z" />
+    <glyph glyph-name="_434" unicode="&#xf1ce;" horiz-adv-x="1792" 
+d="M1760 640q0 -176 -68.5 -336t-184 -275.5t-275.5 -184t-336 -68.5t-336 68.5t-275.5 184t-184 275.5t-68.5 336q0 213 97 398.5t265 305.5t374 151v-228q-221 -45 -366.5 -221t-145.5 -406q0 -130 51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5
+t136.5 204t51 248.5q0 230 -145.5 406t-366.5 221v228q206 -31 374 -151t265 -305.5t97 -398.5z" />
+    <glyph glyph-name="uniF1D0" unicode="&#xf1d0;" horiz-adv-x="1792" 
+d="M19 662q8 217 116 406t305 318h5q0 -1 -1 -3q-8 -8 -28 -33.5t-52 -76.5t-60 -110.5t-44.5 -135.5t-14 -150.5t39 -157.5t108.5 -154q50 -50 102 -69.5t90.5 -11.5t69.5 23.5t47 32.5l16 16q39 51 53 116.5t6.5 122.5t-21 107t-26.5 80l-14 29q-10 25 -30.5 49.5t-43 41
+t-43.5 29.5t-35 19l-13 6l104 115q39 -17 78 -52t59 -61l19 -27q1 48 -18.5 103.5t-40.5 87.5l-20 31l161 183l160 -181q-33 -46 -52.5 -102.5t-22.5 -90.5l-4 -33q22 37 61.5 72.5t67.5 52.5l28 17l103 -115q-44 -14 -85 -50t-60 -65l-19 -29q-31 -56 -48 -133.5t-7 -170
+t57 -156.5q33 -45 77.5 -60.5t85 -5.5t76 26.5t57.5 33.5l21 16q60 53 96.5 115t48.5 121.5t10 121.5t-18 118t-37 107.5t-45.5 93t-45 72t-34.5 47.5l-13 17q-14 13 -7 13l10 -3q40 -29 62.5 -46t62 -50t64 -58t58.5 -65t55.5 -77t45.5 -88t38 -103t23.5 -117t10.5 -136
+q3 -259 -108 -465t-312 -321t-456 -115q-185 0 -351 74t-283.5 198t-184 293t-60.5 353z" />
+    <glyph glyph-name="uniF1D1" unicode="&#xf1d1;" horiz-adv-x="1792" 
+d="M874 -102v-66q-208 6 -385 109.5t-283 275.5l58 34q29 -49 73 -99l65 57q148 -168 368 -212l-17 -86q65 -12 121 -13zM276 428l-83 -28q22 -60 49 -112l-57 -33q-98 180 -98 385t98 385l57 -33q-30 -56 -49 -112l82 -28q-35 -100 -35 -212q0 -109 36 -212zM1528 251
+l58 -34q-106 -172 -283 -275.5t-385 -109.5v66q56 1 121 13l-17 86q220 44 368 212l65 -57q44 50 73 99zM1377 805l-233 -80q14 -42 14 -85t-14 -85l232 -80q-31 -92 -98 -169l-185 162q-57 -67 -147 -85l48 -241q-52 -10 -98 -10t-98 10l48 241q-90 18 -147 85l-185 -162
+q-67 77 -98 169l232 80q-14 42 -14 85t14 85l-233 80q33 93 99 169l185 -162q59 68 147 86l-48 240q44 10 98 10t98 -10l-48 -240q88 -18 147 -86l185 162q66 -76 99 -169zM874 1448v-66q-65 -2 -121 -13l17 -86q-220 -42 -368 -211l-65 56q-38 -42 -73 -98l-57 33
+q106 172 282 275.5t385 109.5zM1705 640q0 -205 -98 -385l-57 33q27 52 49 112l-83 28q36 103 36 212q0 112 -35 212l82 28q-19 56 -49 112l57 33q98 -180 98 -385zM1585 1063l-57 -33q-35 56 -73 98l-65 -56q-148 169 -368 211l17 86q-56 11 -121 13v66q209 -6 385 -109.5
+t282 -275.5zM1748 640q0 173 -67.5 331t-181.5 272t-272 181.5t-331 67.5t-331 -67.5t-272 -181.5t-181.5 -272t-67.5 -331t67.5 -331t181.5 -272t272 -181.5t331 -67.5t331 67.5t272 181.5t181.5 272t67.5 331zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71
+t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
+    <glyph glyph-name="uniF1D2" unicode="&#xf1d2;" 
+d="M582 228q0 -66 -93 -66q-107 0 -107 63q0 64 98 64q102 0 102 -61zM546 694q0 -85 -74 -85q-77 0 -77 84q0 90 77 90q36 0 55 -25.5t19 -63.5zM712 769v125q-78 -29 -135 -29q-50 29 -110 29q-86 0 -145 -57t-59 -143q0 -50 29.5 -102t73.5 -67v-3q-38 -17 -38 -85
+q0 -53 41 -77v-3q-113 -37 -113 -139q0 -45 20 -78.5t54 -51t72 -25.5t81 -8q224 0 224 188q0 67 -48 99t-126 46q-27 5 -51.5 20.5t-24.5 39.5q0 44 49 52q77 15 122 70t45 134q0 24 -10 52q37 9 49 13zM771 350h137q-2 27 -2 82v387q0 46 2 69h-137q3 -23 3 -71v-392
+q0 -50 -3 -75zM1280 366v121q-30 -21 -68 -21q-53 0 -53 82v225h52q9 0 26.5 -1t26.5 -1v117h-105q0 82 3 102h-140q4 -24 4 -55v-47h-60v-117q36 3 37 3q3 0 11 -0.5t12 -0.5v-2h-2v-217q0 -37 2.5 -64t11.5 -56.5t24.5 -48.5t43.5 -31t66 -12q64 0 108 24zM924 1072
+q0 36 -24 63.5t-60 27.5t-60.5 -27t-24.5 -64q0 -36 25 -62.5t60 -26.5t59.5 27t24.5 62zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="_438" unicode="&#xf1d3;" horiz-adv-x="1792" 
+d="M595 22q0 100 -165 100q-158 0 -158 -104q0 -101 172 -101q151 0 151 105zM536 777q0 61 -30 102t-89 41q-124 0 -124 -145q0 -135 124 -135q119 0 119 137zM805 1101v-202q-36 -12 -79 -22q16 -43 16 -84q0 -127 -73 -216.5t-197 -112.5q-40 -8 -59.5 -27t-19.5 -58
+q0 -31 22.5 -51.5t58 -32t78.5 -22t86 -25.5t78.5 -37.5t58 -64t22.5 -98.5q0 -304 -363 -304q-69 0 -130 12.5t-116 41t-87.5 82t-32.5 127.5q0 165 182 225v4q-67 41 -67 126q0 109 63 137v4q-72 24 -119.5 108.5t-47.5 165.5q0 139 95 231.5t235 92.5q96 0 178 -47
+q98 0 218 47zM1123 220h-222q4 45 4 134v609q0 94 -4 128h222q-4 -33 -4 -124v-613q0 -89 4 -134zM1724 442v-196q-71 -39 -174 -39q-62 0 -107 20t-70 50t-39.5 78t-18.5 92t-4 103v351h2v4q-7 0 -19 1t-18 1q-21 0 -59 -6v190h96v76q0 54 -6 89h227q-6 -41 -6 -165h171
+v-190q-15 0 -43.5 2t-42.5 2h-85v-365q0 -131 87 -131q61 0 109 33zM1148 1389q0 -58 -39 -101.5t-96 -43.5q-58 0 -98 43.5t-40 101.5q0 59 39.5 103t98.5 44q58 0 96.5 -44.5t38.5 -102.5z" />
+    <glyph glyph-name="_439" unicode="&#xf1d4;" 
+d="M809 532l266 499h-112l-157 -312q-24 -48 -44 -92l-42 92l-155 312h-120l263 -493v-324h101v318zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="uniF1D5" unicode="&#xf1d5;" horiz-adv-x="1280" 
+d="M842 964q0 -80 -57 -136.5t-136 -56.5q-60 0 -111 35q-62 -67 -115 -146q-247 -371 -202 -859q1 -22 -12.5 -38.5t-34.5 -18.5h-5q-20 0 -35 13.5t-17 33.5q-14 126 -3.5 247.5t29.5 217t54 186t69 155.5t74 125q61 90 132 165q-16 35 -16 77q0 80 56.5 136.5t136.5 56.5
+t136.5 -56.5t56.5 -136.5zM1223 953q0 -158 -78 -292t-212.5 -212t-292.5 -78q-64 0 -131 14q-21 5 -32.5 23.5t-6.5 39.5q5 20 23 31.5t39 7.5q51 -13 108 -13q97 0 186 38t153 102t102 153t38 186t-38 186t-102 153t-153 102t-186 38t-186 -38t-153 -102t-102 -153
+t-38 -186q0 -114 52 -218q10 -20 3.5 -40t-25.5 -30t-39.5 -3t-30.5 26q-64 123 -64 265q0 119 46.5 227t124.5 186t186 124t226 46q158 0 292.5 -78t212.5 -212.5t78 -292.5z" />
+    <glyph glyph-name="uniF1D6" unicode="&#xf1d6;" horiz-adv-x="1792" 
+d="M270 730q-8 19 -8 52q0 20 11 49t24 45q-1 22 7.5 53t22.5 43q0 139 92.5 288.5t217.5 209.5q139 66 324 66q133 0 266 -55q49 -21 90 -48t71 -56t55 -68t42 -74t32.5 -84.5t25.5 -89.5t22 -98l1 -5q55 -83 55 -150q0 -14 -9 -40t-9 -38q0 -1 1.5 -3.5t3.5 -5t2 -3.5
+q77 -114 120.5 -214.5t43.5 -208.5q0 -43 -19.5 -100t-55.5 -57q-9 0 -19.5 7.5t-19 17.5t-19 26t-16 26.5t-13.5 26t-9 17.5q-1 1 -3 1l-5 -4q-59 -154 -132 -223q20 -20 61.5 -38.5t69 -41.5t35.5 -65q-2 -4 -4 -16t-7 -18q-64 -97 -302 -97q-53 0 -110.5 9t-98 20
+t-104.5 30q-15 5 -23 7q-14 4 -46 4.5t-40 1.5q-41 -45 -127.5 -65t-168.5 -20q-35 0 -69 1.5t-93 9t-101 20.5t-74.5 40t-32.5 64q0 40 10 59.5t41 48.5q11 2 40.5 13t49.5 12q4 0 14 2q2 2 2 4l-2 3q-48 11 -108 105.5t-73 156.5l-5 3q-4 0 -12 -20q-18 -41 -54.5 -74.5
+t-77.5 -37.5h-1q-4 0 -6 4.5t-5 5.5q-23 54 -23 100q0 275 252 466z" />
+    <glyph glyph-name="uniF1D7" unicode="&#xf1d7;" horiz-adv-x="2048" 
+d="M580 1075q0 41 -25 66t-66 25q-43 0 -76 -25.5t-33 -65.5q0 -39 33 -64.5t76 -25.5q41 0 66 24.5t25 65.5zM1323 568q0 28 -25.5 50t-65.5 22q-27 0 -49.5 -22.5t-22.5 -49.5q0 -28 22.5 -50.5t49.5 -22.5q40 0 65.5 22t25.5 51zM1087 1075q0 41 -24.5 66t-65.5 25
+q-43 0 -76 -25.5t-33 -65.5q0 -39 33 -64.5t76 -25.5q41 0 65.5 24.5t24.5 65.5zM1722 568q0 28 -26 50t-65 22q-27 0 -49.5 -22.5t-22.5 -49.5q0 -28 22.5 -50.5t49.5 -22.5q39 0 65 22t26 51zM1456 965q-31 4 -70 4q-169 0 -311 -77t-223.5 -208.5t-81.5 -287.5
+q0 -78 23 -152q-35 -3 -68 -3q-26 0 -50 1.5t-55 6.5t-44.5 7t-54.5 10.5t-50 10.5l-253 -127l72 218q-290 203 -290 490q0 169 97.5 311t264 223.5t363.5 81.5q176 0 332.5 -66t262 -182.5t136.5 -260.5zM2048 404q0 -117 -68.5 -223.5t-185.5 -193.5l55 -181l-199 109
+q-150 -37 -218 -37q-169 0 -311 70.5t-223.5 191.5t-81.5 264t81.5 264t223.5 191.5t311 70.5q161 0 303 -70.5t227.5 -192t85.5 -263.5z" />
+    <glyph glyph-name="_443" unicode="&#xf1d8;" horiz-adv-x="1792" 
+d="M1764 1525q33 -24 27 -64l-256 -1536q-5 -29 -32 -45q-14 -8 -31 -8q-11 0 -24 5l-453 185l-242 -295q-18 -23 -49 -23q-13 0 -22 4q-19 7 -30.5 23.5t-11.5 36.5v349l864 1059l-1069 -925l-395 162q-37 14 -40 55q-2 40 32 59l1664 960q15 9 32 9q20 0 36 -11z" />
+    <glyph glyph-name="_444" unicode="&#xf1d9;" horiz-adv-x="1792" 
+d="M1764 1525q33 -24 27 -64l-256 -1536q-5 -29 -32 -45q-14 -8 -31 -8q-11 0 -24 5l-527 215l-298 -327q-18 -21 -47 -21q-14 0 -23 4q-19 7 -30 23.5t-11 36.5v452l-472 193q-37 14 -40 55q-3 39 32 59l1664 960q35 21 68 -2zM1422 26l221 1323l-1434 -827l336 -137
+l863 639l-478 -797z" />
+    <glyph glyph-name="_445" unicode="&#xf1da;" 
+d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61q-172 0 -327 72.5t-264 204.5q-7 10 -6.5 22.5t8.5 20.5l137 138q10 9 25 9q16 -2 23 -12q73 -95 179 -147t225 -52q104 0 198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5t-40.5 198.5t-109.5 163.5
+t-163.5 109.5t-198.5 40.5q-98 0 -188 -35.5t-160 -101.5l137 -138q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45v448q0 42 40 59q39 17 69 -14l130 -129q107 101 244.5 156.5t284.5 55.5q156 0 298 -61t245 -164t164 -245t61 -298zM896 928v-448q0 -14 -9 -23
+t-23 -9h-320q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h224v352q0 14 9 23t23 9h64q14 0 23 -9t9 -23z" />
+    <glyph glyph-name="_446" unicode="&#xf1db;" 
+d="M768 1280q-130 0 -248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5t-51 248.5t-136.5 204t-204 136.5t-248.5 51zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103
+t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="_447" unicode="&#xf1dc;" horiz-adv-x="1792" 
+d="M1682 -128q-44 0 -132.5 3.5t-133.5 3.5q-44 0 -132 -3.5t-132 -3.5q-24 0 -37 20.5t-13 45.5q0 31 17 46t39 17t51 7t45 15q33 21 33 140l-1 391q0 21 -1 31q-13 4 -50 4h-675q-38 0 -51 -4q-1 -10 -1 -31l-1 -371q0 -142 37 -164q16 -10 48 -13t57 -3.5t45 -15
+t20 -45.5q0 -26 -12.5 -48t-36.5 -22q-47 0 -139.5 3.5t-138.5 3.5q-43 0 -128 -3.5t-127 -3.5q-23 0 -35.5 21t-12.5 45q0 30 15.5 45t36 17.5t47.5 7.5t42 15q33 23 33 143l-1 57v813q0 3 0.5 26t0 36.5t-1.5 38.5t-3.5 42t-6.5 36.5t-11 31.5t-16 18q-15 10 -45 12t-53 2
+t-41 14t-18 45q0 26 12 48t36 22q46 0 138.5 -3.5t138.5 -3.5q42 0 126.5 3.5t126.5 3.5q25 0 37.5 -22t12.5 -48q0 -30 -17 -43.5t-38.5 -14.5t-49.5 -4t-43 -13q-35 -21 -35 -160l1 -320q0 -21 1 -32q13 -3 39 -3h699q25 0 38 3q1 11 1 32l1 320q0 139 -35 160
+q-18 11 -58.5 12.5t-66 13t-25.5 49.5q0 26 12.5 48t37.5 22q44 0 132 -3.5t132 -3.5q43 0 129 3.5t129 3.5q25 0 37.5 -22t12.5 -48q0 -30 -17.5 -44t-40 -14.5t-51.5 -3t-44 -12.5q-35 -23 -35 -161l1 -943q0 -119 34 -140q16 -10 46 -13.5t53.5 -4.5t41.5 -15.5t18 -44.5
+q0 -26 -12 -48t-36 -22z" />
+    <glyph glyph-name="_448" unicode="&#xf1dd;" horiz-adv-x="1280" 
+d="M1278 1347v-73q0 -29 -18.5 -61t-42.5 -32q-50 0 -54 -1q-26 -6 -32 -31q-3 -11 -3 -64v-1152q0 -25 -18 -43t-43 -18h-108q-25 0 -43 18t-18 43v1218h-143v-1218q0 -25 -17.5 -43t-43.5 -18h-108q-26 0 -43.5 18t-17.5 43v496q-147 12 -245 59q-126 58 -192 179
+q-64 117 -64 259q0 166 88 286q88 118 209 159q111 37 417 37h479q25 0 43 -18t18 -43z" />
+    <glyph glyph-name="_449" unicode="&#xf1de;" 
+d="M352 128v-128h-352v128h352zM704 256q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h256zM864 640v-128h-864v128h864zM224 1152v-128h-224v128h224zM1536 128v-128h-736v128h736zM576 1280q26 0 45 -19t19 -45v-256
+q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h256zM1216 768q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h256zM1536 640v-128h-224v128h224zM1536 1152v-128h-864v128h864z" />
+    <glyph glyph-name="uniF1E0" unicode="&#xf1e0;" 
+d="M1216 512q133 0 226.5 -93.5t93.5 -226.5t-93.5 -226.5t-226.5 -93.5t-226.5 93.5t-93.5 226.5q0 12 2 34l-360 180q-92 -86 -218 -86q-133 0 -226.5 93.5t-93.5 226.5t93.5 226.5t226.5 93.5q126 0 218 -86l360 180q-2 22 -2 34q0 133 93.5 226.5t226.5 93.5
+t226.5 -93.5t93.5 -226.5t-93.5 -226.5t-226.5 -93.5q-126 0 -218 86l-360 -180q2 -22 2 -34t-2 -34l360 -180q92 86 218 86z" />
+    <glyph glyph-name="_451" unicode="&#xf1e1;" 
+d="M1280 341q0 88 -62.5 151t-150.5 63q-84 0 -145 -58l-241 120q2 16 2 23t-2 23l241 120q61 -58 145 -58q88 0 150.5 63t62.5 151t-62.5 150.5t-150.5 62.5t-151 -62.5t-63 -150.5q0 -7 2 -23l-241 -120q-62 57 -145 57q-88 0 -150.5 -62.5t-62.5 -150.5t62.5 -150.5
+t150.5 -62.5q83 0 145 57l241 -120q-2 -16 -2 -23q0 -88 63 -150.5t151 -62.5t150.5 62.5t62.5 150.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="_452" unicode="&#xf1e2;" horiz-adv-x="1792" 
+d="M571 947q-10 25 -34 35t-49 0q-108 -44 -191 -127t-127 -191q-10 -25 0 -49t35 -34q13 -5 24 -5q42 0 60 40q34 84 98.5 148.5t148.5 98.5q25 11 35 35t0 49zM1513 1303l46 -46l-244 -243l68 -68q19 -19 19 -45.5t-19 -45.5l-64 -64q89 -161 89 -343q0 -143 -55.5 -273.5
+t-150 -225t-225 -150t-273.5 -55.5t-273.5 55.5t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5q182 0 343 -89l64 64q19 19 45.5 19t45.5 -19l68 -68zM1521 1359q-10 -10 -22 -10q-13 0 -23 10l-91 90q-9 10 -9 23t9 23q10 9 23 9t23 -9l90 -91
+q10 -9 10 -22.5t-10 -22.5zM1751 1129q-11 -9 -23 -9t-23 9l-90 91q-10 9 -10 22.5t10 22.5q9 10 22.5 10t22.5 -10l91 -90q9 -10 9 -23t-9 -23zM1792 1312q0 -14 -9 -23t-23 -9h-96q-14 0 -23 9t-9 23t9 23t23 9h96q14 0 23 -9t9 -23zM1600 1504v-96q0 -14 -9 -23t-23 -9
+t-23 9t-9 23v96q0 14 9 23t23 9t23 -9t9 -23zM1751 1449l-91 -90q-10 -10 -22 -10q-13 0 -23 10q-10 9 -10 22.5t10 22.5l90 91q10 9 23 9t23 -9q9 -10 9 -23t-9 -23z" />
+    <glyph glyph-name="_453" unicode="&#xf1e3;" horiz-adv-x="1792" 
+d="M609 720l287 208l287 -208l-109 -336h-355zM896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71zM1515 186q149 203 149 454v3l-102 -89l-240 224l63 323
+l134 -12q-150 206 -389 282l53 -124l-287 -159l-287 159l53 124q-239 -76 -389 -282l135 12l62 -323l-240 -224l-102 89v-3q0 -251 149 -454l30 132l326 -40l139 -298l-116 -69q117 -39 240 -39t240 39l-116 69l139 298l326 40z" />
+    <glyph glyph-name="_454" unicode="&#xf1e4;" horiz-adv-x="1792" 
+d="M448 224v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM256 608v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM832 224v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23
+v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM640 608v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM66 768q-28 0 -47 19t-19 46v129h514v-129q0 -27 -19 -46t-46 -19h-383zM1216 224v-192q0 -14 -9 -23t-23 -9h-192
+q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1024 608v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1600 224v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23
+zM1408 608v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1792 1016v-13h-514v10q0 104 -382 102q-382 -1 -382 -102v-10h-514v13q0 17 8.5 43t34 64t65.5 75.5t110.5 76t160 67.5t224 47.5t293.5 18.5t293 -18.5t224 -47.5
+t160.5 -67.5t110.5 -76t65.5 -75.5t34 -64t8.5 -43zM1792 608v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1792 962v-129q0 -27 -19 -46t-46 -19h-384q-27 0 -46 19t-19 46v129h514z" />
+    <glyph glyph-name="_455" unicode="&#xf1e5;" horiz-adv-x="1792" 
+d="M704 1216v-768q0 -26 -19 -45t-45 -19v-576q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v512l249 873q7 23 31 23h424zM1024 1216v-704h-256v704h256zM1792 320v-512q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v576q-26 0 -45 19t-19 45v768h424q24 0 31 -23z
+M736 1504v-224h-352v224q0 14 9 23t23 9h288q14 0 23 -9t9 -23zM1408 1504v-224h-352v224q0 14 9 23t23 9h288q14 0 23 -9t9 -23z" />
+    <glyph glyph-name="_456" unicode="&#xf1e6;" horiz-adv-x="1792" 
+d="M1755 1083q37 -38 37 -90.5t-37 -90.5l-401 -400l150 -150l-160 -160q-163 -163 -389.5 -186.5t-411.5 100.5l-362 -362h-181v181l362 362q-124 185 -100.5 411.5t186.5 389.5l160 160l150 -150l400 401q38 37 91 37t90 -37t37 -90.5t-37 -90.5l-400 -401l234 -234
+l401 400q38 37 91 37t90 -37z" />
+    <glyph glyph-name="_457" unicode="&#xf1e7;" horiz-adv-x="1792" 
+d="M873 796q0 -83 -63.5 -142.5t-152.5 -59.5t-152.5 59.5t-63.5 142.5q0 84 63.5 143t152.5 59t152.5 -59t63.5 -143zM1375 796q0 -83 -63 -142.5t-153 -59.5q-89 0 -152.5 59.5t-63.5 142.5q0 84 63.5 143t152.5 59q90 0 153 -59t63 -143zM1600 616v667q0 87 -32 123.5
+t-111 36.5h-1112q-83 0 -112.5 -34t-29.5 -126v-673q43 -23 88.5 -40t81 -28t81 -18.5t71 -11t70 -4t58.5 -0.5t56.5 2t44.5 2q68 1 95 -27q6 -6 10 -9q26 -25 61 -51q7 91 118 87q5 0 36.5 -1.5t43 -2t45.5 -1t53 1t54.5 4.5t61 8.5t62 13.5t67 19.5t67.5 27t72 34.5z
+M1763 621q-121 -149 -372 -252q84 -285 -23 -465q-66 -113 -183 -148q-104 -32 -182 15q-86 51 -82 164l-1 326v1q-8 2 -24.5 6t-23.5 5l-1 -338q4 -114 -83 -164q-79 -47 -183 -15q-117 36 -182 150q-105 180 -22 463q-251 103 -372 252q-25 37 -4 63t60 -1q4 -2 11.5 -7
+t10.5 -8v694q0 72 47 123t114 51h1257q67 0 114 -51t47 -123v-694l21 15q39 27 60 1t-4 -63z" />
+    <glyph glyph-name="_458" unicode="&#xf1e8;" horiz-adv-x="1792" 
+d="M896 1102v-434h-145v434h145zM1294 1102v-434h-145v434h145zM1294 342l253 254v795h-1194v-1049h326v-217l217 217h398zM1692 1536v-1013l-434 -434h-326l-217 -217h-217v217h-398v1158l109 289h1483z" />
+    <glyph glyph-name="_459" unicode="&#xf1e9;" 
+d="M773 217v-127q-1 -292 -6 -305q-12 -32 -51 -40q-54 -9 -181.5 38t-162.5 89q-13 15 -17 36q-1 12 4 26q4 10 34 47t181 216q1 0 60 70q15 19 39.5 24.5t49.5 -3.5q24 -10 37.5 -29t12.5 -42zM624 468q-3 -55 -52 -70l-120 -39q-275 -88 -292 -88q-35 2 -54 36
+q-12 25 -17 75q-8 76 1 166.5t30 124.5t56 32q13 0 202 -77q71 -29 115 -47l84 -34q23 -9 35.5 -30.5t11.5 -48.5zM1450 171q-7 -54 -91.5 -161t-135.5 -127q-37 -14 -63 7q-14 10 -184 287l-47 77q-14 21 -11.5 46t19.5 46q35 43 83 26q1 -1 119 -40q203 -66 242 -79.5
+t47 -20.5q28 -22 22 -61zM778 803q5 -102 -54 -122q-58 -17 -114 71l-378 598q-8 35 19 62q41 43 207.5 89.5t224.5 31.5q40 -10 49 -45q3 -18 22 -305.5t24 -379.5zM1440 695q3 -39 -26 -59q-15 -10 -329 -86q-67 -15 -91 -23l1 2q-23 -6 -46 4t-37 32q-30 47 0 87
+q1 1 75 102q125 171 150 204t34 39q28 19 65 2q48 -23 123 -133.5t81 -167.5v-3z" />
+    <glyph glyph-name="_460" unicode="&#xf1ea;" horiz-adv-x="2048" 
+d="M1024 1024h-384v-384h384v384zM1152 384v-128h-640v128h640zM1152 1152v-640h-640v640h640zM1792 384v-128h-512v128h512zM1792 640v-128h-512v128h512zM1792 896v-128h-512v128h512zM1792 1152v-128h-512v128h512zM256 192v960h-128v-960q0 -26 19 -45t45 -19t45 19
+t19 45zM1920 192v1088h-1536v-1088q0 -33 -11 -64h1483q26 0 45 19t19 45zM2048 1408v-1216q0 -80 -56 -136t-136 -56h-1664q-80 0 -136 56t-56 136v1088h256v128h1792z" />
+    <glyph glyph-name="_461" unicode="&#xf1eb;" horiz-adv-x="2048" 
+d="M1024 13q-20 0 -93 73.5t-73 93.5q0 32 62.5 54t103.5 22t103.5 -22t62.5 -54q0 -20 -73 -93.5t-93 -73.5zM1294 284q-2 0 -40 25t-101.5 50t-128.5 25t-128.5 -25t-101 -50t-40.5 -25q-18 0 -93.5 75t-75.5 93q0 13 10 23q78 77 196 121t233 44t233 -44t196 -121
+q10 -10 10 -23q0 -18 -75.5 -93t-93.5 -75zM1567 556q-11 0 -23 8q-136 105 -252 154.5t-268 49.5q-85 0 -170.5 -22t-149 -53t-113.5 -62t-79 -53t-31 -22q-17 0 -92 75t-75 93q0 12 10 22q132 132 320 205t380 73t380 -73t320 -205q10 -10 10 -22q0 -18 -75 -93t-92 -75z
+M1838 827q-11 0 -22 9q-179 157 -371.5 236.5t-420.5 79.5t-420.5 -79.5t-371.5 -236.5q-11 -9 -22 -9q-17 0 -92.5 75t-75.5 93q0 13 10 23q187 186 445 288t527 102t527 -102t445 -288q10 -10 10 -23q0 -18 -75.5 -93t-92.5 -75z" />
+    <glyph glyph-name="_462" unicode="&#xf1ec;" horiz-adv-x="1792" 
+d="M384 0q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM768 0q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM384 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5
+t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1152 0q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM768 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5
+t37.5 90.5zM384 768q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1152 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM768 768q0 53 -37.5 90.5t-90.5 37.5
+t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1536 0v384q0 52 -38 90t-90 38t-90 -38t-38 -90v-384q0 -52 38 -90t90 -38t90 38t38 90zM1152 768q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5z
+M1536 1088v256q0 26 -19 45t-45 19h-1280q-26 0 -45 -19t-19 -45v-256q0 -26 19 -45t45 -19h1280q26 0 45 19t19 45zM1536 768q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1664 1408v-1536q0 -52 -38 -90t-90 -38
+h-1408q-52 0 -90 38t-38 90v1536q0 52 38 90t90 38h1408q52 0 90 -38t38 -90z" />
+    <glyph glyph-name="_463" unicode="&#xf1ed;" 
+d="M1519 890q18 -84 -4 -204q-87 -444 -565 -444h-44q-25 0 -44 -16.5t-24 -42.5l-4 -19l-55 -346l-2 -15q-5 -26 -24.5 -42.5t-44.5 -16.5h-251q-21 0 -33 15t-9 36q9 56 26.5 168t26.5 168t27 167.5t27 167.5q5 37 43 37h131q133 -2 236 21q175 39 287 144q102 95 155 246
+q24 70 35 133q1 6 2.5 7.5t3.5 1t6 -3.5q79 -59 98 -162zM1347 1172q0 -107 -46 -236q-80 -233 -302 -315q-113 -40 -252 -42q0 -1 -90 -1l-90 1q-100 0 -118 -96q-2 -8 -85 -530q-1 -10 -12 -10h-295q-22 0 -36.5 16.5t-11.5 38.5l232 1471q5 29 27.5 48t51.5 19h598
+q34 0 97.5 -13t111.5 -32q107 -41 163.5 -123t56.5 -196z" />
+    <glyph glyph-name="_464" unicode="&#xf1ee;" horiz-adv-x="1792" 
+d="M441 864q33 0 52 -26q266 -364 362 -774h-446q-127 441 -367 749q-12 16 -3 33.5t29 17.5h373zM1000 507q-49 -199 -125 -393q-79 310 -256 594q40 221 44 449q211 -340 337 -650zM1099 1216q235 -324 384.5 -698.5t184.5 -773.5h-451q-41 665 -553 1472h435zM1792 640
+q0 -424 -101 -812q-67 560 -359 1083q-25 301 -106 584q-4 16 5.5 28.5t25.5 12.5h359q21 0 38.5 -13t22.5 -33q115 -409 115 -850z" />
+    <glyph glyph-name="uniF1F0" unicode="&#xf1f0;" horiz-adv-x="2304" 
+d="M1975 546h-138q14 37 66 179l3 9q4 10 10 26t9 26l12 -55zM531 611l-58 295q-11 54 -75 54h-268l-2 -13q311 -79 403 -336zM710 960l-162 -438l-17 89q-26 70 -85 129.5t-131 88.5l135 -510h175l261 641h-176zM849 318h166l104 642h-166zM1617 944q-69 27 -149 27
+q-123 0 -201 -59t-79 -153q-1 -102 145 -174q48 -23 67 -41t19 -39q0 -30 -30 -46t-69 -16q-86 0 -156 33l-22 11l-23 -144q74 -34 185 -34q130 -1 208.5 59t80.5 160q0 106 -140 174q-49 25 -71 42t-22 38q0 22 24.5 38.5t70.5 16.5q70 1 124 -24l15 -8zM2042 960h-128
+q-65 0 -87 -54l-246 -588h174l35 96h212q5 -22 20 -96h154zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" />
+    <glyph glyph-name="_466" unicode="&#xf1f1;" horiz-adv-x="2304" 
+d="M1119 1195q-128 85 -281 85q-103 0 -197.5 -40.5t-162.5 -108.5t-108.5 -162t-40.5 -197q0 -104 40.5 -198t108.5 -162t162 -108.5t198 -40.5q153 0 281 85q-131 107 -178 265.5t0.5 316.5t177.5 265zM1152 1171q-126 -99 -172 -249.5t-0.5 -300.5t172.5 -249
+q127 99 172.5 249t-0.5 300.5t-172 249.5zM1185 1195q130 -107 177.5 -265.5t0.5 -317t-178 -264.5q128 -85 281 -85q104 0 198 40.5t162 108.5t108.5 162t40.5 198q0 103 -40.5 197t-108.5 162t-162.5 108.5t-197.5 40.5q-153 0 -281 -85zM1926 473h7v3h-17v-3h7v-17h3v17z
+M1955 456h4v20h-5l-6 -13l-6 13h-5v-20h3v15l6 -13h4l5 13v-15zM1947 16v-2h-2h-3v3h3h2v-1zM1947 7h3l-4 5h2l1 1q1 1 1 3t-1 3l-1 1h-3h-6v-13h3v5h1zM685 75q0 19 11 31t30 12q18 0 29 -12.5t11 -30.5q0 -19 -11 -31t-29 -12q-19 0 -30 12t-11 31zM1158 119q30 0 35 -32
+h-70q5 32 35 32zM1514 75q0 19 11 31t29 12t29.5 -12.5t11.5 -30.5q0 -19 -11 -31t-30 -12q-18 0 -29 12t-11 31zM1786 75q0 18 11.5 30.5t29.5 12.5t29.5 -12.5t11.5 -30.5q0 -19 -11.5 -31t-29.5 -12t-29.5 12.5t-11.5 30.5zM1944 3q-2 0 -4 1q-1 0 -3 2t-2 3q-1 2 -1 4
+q0 3 1 4q0 2 2 4l1 1q2 0 2 1q2 1 4 1q3 0 4 -1l4 -2l2 -4v-1q1 -2 1 -3l-1 -1v-3t-1 -1l-1 -2q-2 -2 -4 -2q-1 -1 -4 -1zM599 7h30v85q0 24 -14.5 38.5t-39.5 15.5q-32 0 -47 -24q-14 24 -45 24q-24 0 -39 -20v16h-30v-135h30v75q0 36 33 36q30 0 30 -36v-75h29v75
+q0 36 33 36q30 0 30 -36v-75zM765 7h29v68v67h-29v-16q-17 20 -43 20q-29 0 -48 -20t-19 -51t19 -51t48 -20q28 0 43 20v-17zM943 48q0 34 -47 40l-14 2q-23 4 -23 14q0 15 25 15q23 0 43 -11l12 24q-22 14 -55 14q-26 0 -41 -12t-15 -32q0 -33 47 -39l13 -2q24 -4 24 -14
+q0 -17 -31 -17q-25 0 -45 14l-13 -23q25 -17 58 -17q29 0 45.5 12t16.5 32zM1073 14l-8 25q-13 -7 -26 -7q-19 0 -19 22v61h48v27h-48v41h-30v-41h-28v-27h28v-61q0 -50 47 -50q21 0 36 10zM1159 146q-29 0 -48 -20t-19 -51q0 -32 19.5 -51.5t49.5 -19.5q33 0 55 19l-14 22
+q-18 -15 -39 -15q-34 0 -41 33h101v12q0 32 -18 51.5t-46 19.5zM1318 146q-23 0 -35 -20v16h-30v-135h30v76q0 35 29 35q10 0 18 -4l9 28q-9 4 -21 4zM1348 75q0 -31 19.5 -51t52.5 -20q29 0 48 16l-14 24q-18 -13 -35 -12q-18 0 -29.5 12t-11.5 31t11.5 31t29.5 12
+q19 0 35 -12l14 24q-20 16 -48 16q-33 0 -52.5 -20t-19.5 -51zM1593 7h30v68v67h-30v-16q-15 20 -42 20q-29 0 -48.5 -20t-19.5 -51t19.5 -51t48.5 -20q28 0 42 20v-17zM1726 146q-23 0 -35 -20v16h-29v-135h29v76q0 35 29 35q10 0 18 -4l9 28q-8 4 -21 4zM1866 7h29v68v122
+h-29v-71q-15 20 -43 20t-47.5 -20.5t-19.5 -50.5t19.5 -50.5t47.5 -20.5q29 0 43 20v-17zM1944 27l-2 -1h-3q-2 -1 -4 -3q-3 -1 -3 -4q-1 -2 -1 -6q0 -3 1 -5q0 -2 3 -4q2 -2 4 -3t5 -1q4 0 6 1q0 1 2 2l2 1q1 1 3 4q1 2 1 5q0 4 -1 6q-1 1 -3 4q0 1 -2 2l-2 1q-1 0 -3 0.5
+t-3 0.5zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" />
+    <glyph glyph-name="_467" unicode="&#xf1f2;" horiz-adv-x="2304" 
+d="M313 759q0 -51 -36 -84q-29 -26 -89 -26h-17v220h17q61 0 89 -27q36 -31 36 -83zM2089 824q0 -52 -64 -52h-19v101h20q63 0 63 -49zM380 759q0 74 -50 120.5t-129 46.5h-95v-333h95q74 0 119 38q60 51 60 128zM410 593h65v333h-65v-333zM730 694q0 40 -20.5 62t-75.5 42
+q-29 10 -39.5 19t-10.5 23q0 16 13.5 26.5t34.5 10.5q29 0 53 -27l34 44q-41 37 -98 37q-44 0 -74 -27.5t-30 -67.5q0 -35 18 -55.5t64 -36.5q37 -13 45 -19q19 -12 19 -34q0 -20 -14 -33.5t-36 -13.5q-48 0 -71 44l-42 -40q44 -64 115 -64q51 0 83 30.5t32 79.5zM1008 604
+v77q-37 -37 -78 -37q-49 0 -80.5 32.5t-31.5 82.5q0 48 31.5 81.5t77.5 33.5q43 0 81 -38v77q-40 20 -80 20q-74 0 -125.5 -50.5t-51.5 -123.5t51 -123.5t125 -50.5q42 0 81 19zM2240 0v527q-65 -40 -144.5 -84t-237.5 -117t-329.5 -137.5t-417.5 -134.5t-504 -118h1569
+q26 0 45 19t19 45zM1389 757q0 75 -53 128t-128 53t-128 -53t-53 -128t53 -128t128 -53t128 53t53 128zM1541 584l144 342h-71l-90 -224l-89 224h-71l142 -342h35zM1714 593h184v56h-119v90h115v56h-115v74h119v57h-184v-333zM2105 593h80l-105 140q76 16 76 94q0 47 -31 73
+t-87 26h-97v-333h65v133h9zM2304 1274v-1268q0 -56 -38.5 -95t-93.5 -39h-2040q-55 0 -93.5 39t-38.5 95v1268q0 56 38.5 95t93.5 39h2040q55 0 93.5 -39t38.5 -95z" />
+    <glyph glyph-name="f1f3" unicode="&#xf1f3;" horiz-adv-x="2304" 
+d="M119 854h89l-45 108zM740 328l74 79l-70 79h-163v-49h142v-55h-142v-54h159zM898 406l99 -110v217zM1186 453q0 33 -40 33h-84v-69h83q41 0 41 36zM1475 457q0 29 -42 29h-82v-61h81q43 0 43 32zM1197 923q0 29 -42 29h-82v-60h81q43 0 43 31zM1656 854h89l-44 108z
+M699 1009v-271h-66v212l-94 -212h-57l-94 212v-212h-132l-25 60h-135l-25 -60h-70l116 271h96l110 -257v257h106l85 -184l77 184h108zM1255 453q0 -20 -5.5 -35t-14 -25t-22.5 -16.5t-26 -10t-31.5 -4.5t-31.5 -1t-32.5 0.5t-29.5 0.5v-91h-126l-80 90l-83 -90h-256v271h260
+l80 -89l82 89h207q109 0 109 -89zM964 794v-56h-217v271h217v-57h-152v-49h148v-55h-148v-54h152zM2304 235v-229q0 -55 -38.5 -94.5t-93.5 -39.5h-2040q-55 0 -93.5 39.5t-38.5 94.5v678h111l25 61h55l25 -61h218v46l19 -46h113l20 47v-47h541v99l10 1q10 0 10 -14v-86h279
+v23q23 -12 55 -18t52.5 -6.5t63 0.5t51.5 1l25 61h56l25 -61h227v58l34 -58h182v378h-180v-44l-25 44h-185v-44l-23 44h-249q-69 0 -109 -22v22h-172v-22q-24 22 -73 22h-628l-43 -97l-43 97h-198v-44l-22 44h-169l-78 -179v391q0 55 38.5 94.5t93.5 39.5h2040
+q55 0 93.5 -39.5t38.5 -94.5v-678h-120q-51 0 -81 -22v22h-177q-55 0 -78 -22v22h-316v-22q-31 22 -87 22h-209v-22q-23 22 -91 22h-234l-54 -58l-50 58h-349v-378h343l55 59l52 -59h211v89h21q59 0 90 13v-102h174v99h8q8 0 10 -2t2 -10v-87h529q57 0 88 24v-24h168
+q60 0 95 17zM1546 469q0 -23 -12 -43t-34 -29q25 -9 34 -26t9 -46v-54h-65v45q0 33 -12 43.5t-46 10.5h-69v-99h-65v271h154q48 0 77 -15t29 -58zM1269 936q0 -24 -12.5 -44t-33.5 -29q26 -9 34.5 -25.5t8.5 -46.5v-53h-65q0 9 0.5 26.5t0 25t-3 18.5t-8.5 16t-17.5 8.5
+t-29.5 3.5h-70v-98h-64v271l153 -1q49 0 78 -14.5t29 -57.5zM1798 327v-56h-216v271h216v-56h-151v-49h148v-55h-148v-54zM1372 1009v-271h-66v271h66zM2065 357q0 -86 -102 -86h-126v58h126q34 0 34 25q0 16 -17 21t-41.5 5t-49.5 3.5t-42 22.5t-17 55q0 39 26 60t66 21
+h130v-57h-119q-36 0 -36 -25q0 -16 17.5 -20.5t42 -4t49 -2.5t42 -21.5t17.5 -54.5zM2304 407v-101q-24 -35 -88 -35h-125v58h125q33 0 33 25q0 13 -12.5 19t-31 5.5t-40 2t-40 8t-31 24t-12.5 48.5q0 39 26.5 60t66.5 21h129v-57h-118q-36 0 -36 -25q0 -20 29 -22t68.5 -5
+t56.5 -26zM2139 1008v-270h-92l-122 203v-203h-132l-26 60h-134l-25 -60h-75q-129 0 -129 133q0 138 133 138h63v-59q-7 0 -28 1t-28.5 0.5t-23 -2t-21.5 -6.5t-14.5 -13.5t-11.5 -23t-3 -33.5q0 -38 13.5 -58t49.5 -20h29l92 213h97l109 -256v256h99l114 -188v188h66z" />
+    <glyph glyph-name="_469" unicode="&#xf1f4;" horiz-adv-x="2304" 
+d="M745 630q0 -37 -25.5 -61.5t-62.5 -24.5q-29 0 -46.5 16t-17.5 44q0 37 25 62.5t62 25.5q28 0 46.5 -16.5t18.5 -45.5zM1530 779q0 -42 -22 -57t-66 -15l-32 -1l17 107q2 11 13 11h18q22 0 35 -2t25 -12.5t12 -30.5zM1881 630q0 -36 -25.5 -61t-61.5 -25q-29 0 -47 16
+t-18 44q0 37 25 62.5t62 25.5q28 0 46.5 -16.5t18.5 -45.5zM513 801q0 59 -38.5 85.5t-100.5 26.5h-160q-19 0 -21 -19l-65 -408q-1 -6 3 -11t10 -5h76q20 0 22 19l18 110q1 8 7 13t15 6.5t17 1.5t19 -1t14 -1q86 0 135 48.5t49 134.5zM822 489l41 261q1 6 -3 11t-10 5h-76
+q-14 0 -17 -33q-27 40 -95 40q-72 0 -122.5 -54t-50.5 -127q0 -59 34.5 -94t92.5 -35q28 0 58 12t48 32q-4 -12 -4 -21q0 -16 13 -16h69q19 0 22 19zM1269 752q0 5 -4 9.5t-9 4.5h-77q-11 0 -18 -10l-106 -156l-44 150q-5 16 -22 16h-75q-5 0 -9 -4.5t-4 -9.5q0 -2 19.5 -59
+t42 -123t23.5 -70q-82 -112 -82 -120q0 -13 13 -13h77q11 0 18 10l255 368q2 2 2 7zM1649 801q0 59 -38.5 85.5t-100.5 26.5h-159q-20 0 -22 -19l-65 -408q-1 -6 3 -11t10 -5h82q12 0 16 13l18 116q1 8 7 13t15 6.5t17 1.5t19 -1t14 -1q86 0 135 48.5t49 134.5zM1958 489
+l41 261q1 6 -3 11t-10 5h-76q-14 0 -17 -33q-26 40 -95 40q-72 0 -122.5 -54t-50.5 -127q0 -59 34.5 -94t92.5 -35q29 0 59 12t47 32q0 -1 -2 -9t-2 -12q0 -16 13 -16h69q19 0 22 19zM2176 898v1q0 14 -13 14h-74q-11 0 -13 -11l-65 -416l-1 -2q0 -5 4 -9.5t10 -4.5h66
+q19 0 21 19zM392 764q-5 -35 -26 -46t-60 -11l-33 -1l17 107q2 11 13 11h19q40 0 58 -11.5t12 -48.5zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" />
+    <glyph glyph-name="_470" unicode="&#xf1f5;" horiz-adv-x="2304" 
+d="M1597 633q0 -69 -21 -106q-19 -35 -52 -35q-23 0 -41 9v224q29 30 57 30q57 0 57 -122zM2035 669h-110q6 98 56 98q51 0 54 -98zM476 534q0 59 -33 91.5t-101 57.5q-36 13 -52 24t-16 25q0 26 38 26q58 0 124 -33l18 112q-67 32 -149 32q-77 0 -123 -38q-48 -39 -48 -109
+q0 -58 32.5 -90.5t99.5 -56.5q39 -14 54.5 -25.5t15.5 -27.5q0 -31 -48 -31q-29 0 -70 12.5t-72 30.5l-18 -113q72 -41 168 -41q81 0 129 37q51 41 51 117zM771 749l19 111h-96v135l-129 -21l-18 -114l-46 -8l-17 -103h62v-219q0 -84 44 -120q38 -30 111 -30q32 0 79 11v118
+q-32 -7 -44 -7q-42 0 -42 50v197h77zM1087 724v139q-15 3 -28 3q-32 0 -55.5 -16t-33.5 -46l-10 56h-131v-471h150v306q26 31 82 31q16 0 26 -2zM1124 389h150v471h-150v-471zM1746 638q0 122 -45 179q-40 52 -111 52q-64 0 -117 -56l-8 47h-132v-645l150 25v151
+q36 -11 68 -11q83 0 134 56q61 65 61 202zM1278 986q0 33 -23 56t-56 23t-56 -23t-23 -56t23 -56.5t56 -23.5t56 23.5t23 56.5zM2176 629q0 113 -48 176q-50 64 -144 64q-96 0 -151.5 -66t-55.5 -180q0 -128 63 -188q55 -55 161 -55q101 0 160 40l-16 103q-57 -31 -128 -31
+q-43 0 -63 19q-23 19 -28 66h248q2 14 2 52zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" />
+    <glyph glyph-name="_471" unicode="&#xf1f6;" horiz-adv-x="2048" 
+d="M1558 684q61 -356 298 -556q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-180.5 74.5t-75.5 180.5zM1024 -176q16 0 16 16t-16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5zM2026 1424q8 -10 7.5 -23.5t-10.5 -22.5
+l-1872 -1622q-10 -8 -23.5 -7t-21.5 11l-84 96q-8 10 -7.5 23.5t10.5 21.5l186 161q-19 32 -19 66q50 42 91 88t85 119.5t74.5 158.5t50 206t19.5 260q0 152 117 282.5t307 158.5q-8 19 -8 39q0 40 28 68t68 28t68 -28t28 -68q0 -20 -8 -39q124 -18 219 -82.5t148 -157.5
+l418 363q10 8 23.5 7t21.5 -11z" />
+    <glyph glyph-name="_472" unicode="&#xf1f7;" horiz-adv-x="2048" 
+d="M1040 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM503 315l877 760q-42 88 -132.5 146.5t-223.5 58.5q-93 0 -169.5 -31.5t-121.5 -80.5t-69 -103t-24 -105q0 -384 -137 -645zM1856 128
+q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-180.5 74.5t-75.5 180.5l149 129h757q-166 187 -227 459l111 97q61 -356 298 -556zM1942 1520l84 -96q8 -10 7.5 -23.5t-10.5 -22.5l-1872 -1622q-10 -8 -23.5 -7t-21.5 11l-84 96q-8 10 -7.5 23.5t10.5 21.5l186 161
+q-19 32 -19 66q50 42 91 88t85 119.5t74.5 158.5t50 206t19.5 260q0 152 117 282.5t307 158.5q-8 19 -8 39q0 40 28 68t68 28t68 -28t28 -68q0 -20 -8 -39q124 -18 219 -82.5t148 -157.5l418 363q10 8 23.5 7t21.5 -11z" />
+    <glyph glyph-name="_473" unicode="&#xf1f8;" horiz-adv-x="1408" 
+d="M512 160v704q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-704q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM768 160v704q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-704q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1024 160v704q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-704
+q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM480 1152h448l-48 117q-7 9 -17 11h-317q-10 -2 -17 -11zM1408 1120v-64q0 -14 -9 -23t-23 -9h-96v-948q0 -83 -47 -143.5t-113 -60.5h-832q-66 0 -113 58.5t-47 141.5v952h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h309l70 167
+q15 37 54 63t79 26h320q40 0 79 -26t54 -63l70 -167h309q14 0 23 -9t9 -23z" />
+    <glyph glyph-name="_474" unicode="&#xf1f9;" 
+d="M1150 462v-109q0 -50 -36.5 -89t-94 -60.5t-118 -32.5t-117.5 -11q-205 0 -342.5 139t-137.5 346q0 203 136 339t339 136q34 0 75.5 -4.5t93 -18t92.5 -34t69 -56.5t28 -81v-109q0 -16 -16 -16h-118q-16 0 -16 16v70q0 43 -65.5 67.5t-137.5 24.5q-140 0 -228.5 -91.5
+t-88.5 -237.5q0 -151 91.5 -249.5t233.5 -98.5q68 0 138 24t70 66v70q0 7 4.5 11.5t10.5 4.5h119q6 0 11 -4.5t5 -11.5zM768 1280q-130 0 -248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5
+t-51 248.5t-136.5 204t-204 136.5t-248.5 51zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="_475" unicode="&#xf1fa;" 
+d="M972 761q0 108 -53.5 169t-147.5 61q-63 0 -124 -30.5t-110 -84.5t-79.5 -137t-30.5 -180q0 -112 53.5 -173t150.5 -61q96 0 176 66.5t122.5 166t42.5 203.5zM1536 640q0 -111 -37 -197t-98.5 -135t-131.5 -74.5t-145 -27.5q-6 0 -15.5 -0.5t-16.5 -0.5q-95 0 -142 53
+q-28 33 -33 83q-52 -66 -131.5 -110t-173.5 -44q-161 0 -249.5 95.5t-88.5 269.5q0 157 66 290t179 210.5t246 77.5q87 0 155 -35.5t106 -99.5l2 19l11 56q1 6 5.5 12t9.5 6h118q5 0 13 -11q5 -5 3 -16l-120 -614q-5 -24 -5 -48q0 -39 12.5 -52t44.5 -13q28 1 57 5.5t73 24
+t77 50t57 89.5t24 137q0 292 -174 466t-466 174q-130 0 -248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51q228 0 405 144q11 9 24 8t21 -12l41 -49q8 -12 7 -24q-2 -13 -12 -22q-102 -83 -227.5 -128t-258.5 -45q-156 0 -298 61
+t-245 164t-164 245t-61 298t61 298t164 245t245 164t298 61q344 0 556 -212t212 -556z" />
+    <glyph glyph-name="_476" unicode="&#xf1fb;" horiz-adv-x="1792" 
+d="M1698 1442q94 -94 94 -226.5t-94 -225.5l-225 -223l104 -104q10 -10 10 -23t-10 -23l-210 -210q-10 -10 -23 -10t-23 10l-105 105l-603 -603q-37 -37 -90 -37h-203l-256 -128l-64 64l128 256v203q0 53 37 90l603 603l-105 105q-10 10 -10 23t10 23l210 210q10 10 23 10
+t23 -10l104 -104l223 225q93 94 225.5 94t226.5 -94zM512 64l576 576l-192 192l-576 -576v-192h192z" />
+    <glyph glyph-name="f1fc" unicode="&#xf1fc;" horiz-adv-x="1792" 
+d="M1615 1536q70 0 122.5 -46.5t52.5 -116.5q0 -63 -45 -151q-332 -629 -465 -752q-97 -91 -218 -91q-126 0 -216.5 92.5t-90.5 219.5q0 128 92 212l638 579q59 54 130 54zM706 502q39 -76 106.5 -130t150.5 -76l1 -71q4 -213 -129.5 -347t-348.5 -134q-123 0 -218 46.5
+t-152.5 127.5t-86.5 183t-29 220q7 -5 41 -30t62 -44.5t59 -36.5t46 -17q41 0 55 37q25 66 57.5 112.5t69.5 76t88 47.5t103 25.5t125 10.5z" />
+    <glyph glyph-name="_478" unicode="&#xf1fd;" horiz-adv-x="1792" 
+d="M1792 128v-384h-1792v384q45 0 85 14t59 27.5t47 37.5q30 27 51.5 38t56.5 11q24 0 44 -7t31 -15t33 -27q29 -25 47 -38t58 -27t86 -14q45 0 85 14.5t58 27t48 37.5q21 19 32.5 27t31 15t43.5 7q35 0 56.5 -11t51.5 -38q28 -24 47 -37.5t59 -27.5t85 -14t85 14t59 27.5
+t47 37.5q30 27 51.5 38t56.5 11q34 0 55.5 -11t51.5 -38q28 -24 47 -37.5t59 -27.5t85 -14zM1792 448v-192q-24 0 -44 7t-31 15t-33 27q-29 25 -47 38t-58 27t-85 14q-46 0 -86 -14t-58 -27t-47 -38q-22 -19 -33 -27t-31 -15t-44 -7q-35 0 -56.5 11t-51.5 38q-29 25 -47 38
+t-58 27t-86 14q-45 0 -85 -14.5t-58 -27t-48 -37.5q-21 -19 -32.5 -27t-31 -15t-43.5 -7q-35 0 -56.5 11t-51.5 38q-28 24 -47 37.5t-59 27.5t-85 14q-46 0 -86 -14t-58 -27t-47 -38q-30 -27 -51.5 -38t-56.5 -11v192q0 80 56 136t136 56h64v448h256v-448h256v448h256v-448
+h256v448h256v-448h64q80 0 136 -56t56 -136zM512 1312q0 -77 -36 -118.5t-92 -41.5q-53 0 -90.5 37.5t-37.5 90.5q0 29 9.5 51t23.5 34t31 28t31 31.5t23.5 44.5t9.5 67q38 0 83 -74t45 -150zM1024 1312q0 -77 -36 -118.5t-92 -41.5q-53 0 -90.5 37.5t-37.5 90.5
+q0 29 9.5 51t23.5 34t31 28t31 31.5t23.5 44.5t9.5 67q38 0 83 -74t45 -150zM1536 1312q0 -77 -36 -118.5t-92 -41.5q-53 0 -90.5 37.5t-37.5 90.5q0 29 9.5 51t23.5 34t31 28t31 31.5t23.5 44.5t9.5 67q38 0 83 -74t45 -150z" />
+    <glyph glyph-name="_479" unicode="&#xf1fe;" horiz-adv-x="2048" 
+d="M2048 0v-128h-2048v1536h128v-1408h1920zM1664 1024l256 -896h-1664v576l448 576l576 -576z" />
+    <glyph glyph-name="_480" unicode="&#xf200;" horiz-adv-x="1792" 
+d="M768 646l546 -546q-106 -108 -247.5 -168t-298.5 -60q-209 0 -385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103v-762zM955 640h773q0 -157 -60 -298.5t-168 -247.5zM1664 768h-768v768q209 0 385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="_481" unicode="&#xf201;" horiz-adv-x="2048" 
+d="M2048 0v-128h-2048v1536h128v-1408h1920zM1920 1248v-435q0 -21 -19.5 -29.5t-35.5 7.5l-121 121l-633 -633q-10 -10 -23 -10t-23 10l-233 233l-416 -416l-192 192l585 585q10 10 23 10t23 -10l233 -233l464 464l-121 121q-16 16 -7.5 35.5t29.5 19.5h435q14 0 23 -9
+t9 -23z" />
+    <glyph glyph-name="_482" unicode="&#xf202;" horiz-adv-x="1792" 
+d="M1292 832q0 -6 10 -41q10 -29 25 -49.5t41 -34t44 -20t55 -16.5q325 -91 325 -332q0 -146 -105.5 -242.5t-254.5 -96.5q-59 0 -111.5 18.5t-91.5 45.5t-77 74.5t-63 87.5t-53.5 103.5t-43.5 103t-39.5 106.5t-35.5 95q-32 81 -61.5 133.5t-73.5 96.5t-104 64t-142 20
+q-96 0 -183 -55.5t-138 -144.5t-51 -185q0 -160 106.5 -279.5t263.5 -119.5q177 0 258 95q56 63 83 116l84 -152q-15 -34 -44 -70l1 -1q-131 -152 -388 -152q-147 0 -269.5 79t-190.5 207.5t-68 274.5q0 105 43.5 206t116 176.5t172 121.5t204.5 46q87 0 159 -19t123.5 -50
+t95 -80t72.5 -99t58.5 -117t50.5 -124.5t50 -130.5t55 -127q96 -200 233 -200q81 0 138.5 48.5t57.5 128.5q0 42 -19 72t-50.5 46t-72.5 31.5t-84.5 27t-87.5 34t-81 52t-65 82t-39 122.5q-3 16 -3 33q0 110 87.5 192t198.5 78q78 -3 120.5 -14.5t90.5 -53.5h-1
+q12 -11 23 -24.5t26 -36t19 -27.5l-129 -99q-26 49 -54 70v1q-23 21 -97 21q-49 0 -84 -33t-35 -83z" />
+    <glyph glyph-name="_483" unicode="&#xf203;" 
+d="M1432 484q0 173 -234 239q-35 10 -53 16.5t-38 25t-29 46.5q0 2 -2 8.5t-3 12t-1 7.5q0 36 24.5 59.5t60.5 23.5q54 0 71 -15h-1q20 -15 39 -51l93 71q-39 54 -49 64q-33 29 -67.5 39t-85.5 10q-80 0 -142 -57.5t-62 -137.5q0 -7 2 -23q16 -96 64.5 -140t148.5 -73
+q29 -8 49 -15.5t45 -21.5t38.5 -34.5t13.5 -46.5v-5q1 -58 -40.5 -93t-100.5 -35q-97 0 -167 144q-23 47 -51.5 121.5t-48 125.5t-54 110.5t-74 95.5t-103.5 60.5t-147 24.5q-101 0 -192 -56t-144 -148t-50 -192v-1q4 -108 50.5 -199t133.5 -147.5t196 -56.5q186 0 279 110
+q20 27 31 51l-60 109q-42 -80 -99 -116t-146 -36q-115 0 -191 87t-76 204q0 105 82 189t186 84q112 0 170 -53.5t104 -172.5q8 -21 25.5 -68.5t28.5 -76.5t31.5 -74.5t38.5 -74t45.5 -62.5t55.5 -53.5t66 -33t80 -13.5q107 0 183 69.5t76 174.5zM1536 1120v-960
+q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="_484" unicode="&#xf204;" horiz-adv-x="2048" 
+d="M1152 640q0 104 -40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM1920 640q0 104 -40.5 198.5
+t-109.5 163.5t-163.5 109.5t-198.5 40.5h-386q119 -90 188.5 -224t69.5 -288t-69.5 -288t-188.5 -224h386q104 0 198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM2048 640q0 -130 -51 -248.5t-136.5 -204t-204 -136.5t-248.5 -51h-768q-130 0 -248.5 51t-204 136.5
+t-136.5 204t-51 248.5t51 248.5t136.5 204t204 136.5t248.5 51h768q130 0 248.5 -51t204 -136.5t136.5 -204t51 -248.5z" />
+    <glyph glyph-name="_485" unicode="&#xf205;" horiz-adv-x="2048" 
+d="M0 640q0 130 51 248.5t136.5 204t204 136.5t248.5 51h768q130 0 248.5 -51t204 -136.5t136.5 -204t51 -248.5t-51 -248.5t-136.5 -204t-204 -136.5t-248.5 -51h-768q-130 0 -248.5 51t-204 136.5t-136.5 204t-51 248.5zM1408 128q104 0 198.5 40.5t163.5 109.5
+t109.5 163.5t40.5 198.5t-40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5z" />
+    <glyph glyph-name="_486" unicode="&#xf206;" horiz-adv-x="2304" 
+d="M762 384h-314q-40 0 -57.5 35t6.5 67l188 251q-65 31 -137 31q-132 0 -226 -94t-94 -226t94 -226t226 -94q115 0 203 72.5t111 183.5zM576 512h186q-18 85 -75 148zM1056 512l288 384h-480l-99 -132q105 -103 126 -252h165zM2176 448q0 132 -94 226t-226 94
+q-60 0 -121 -24l174 -260q15 -23 10 -49t-27 -40q-15 -11 -36 -11q-35 0 -53 29l-174 260q-93 -95 -93 -225q0 -132 94 -226t226 -94t226 94t94 226zM2304 448q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 97 39.5 183.5t109.5 149.5l-65 98l-353 -469
+q-18 -26 -51 -26h-197q-23 -164 -149 -274t-294 -110q-185 0 -316.5 131.5t-131.5 316.5t131.5 316.5t316.5 131.5q114 0 215 -55l137 183h-224q-26 0 -45 19t-19 45t19 45t45 19h384v-128h435l-85 128h-222q-26 0 -45 19t-19 45t19 45t45 19h256q33 0 53 -28l267 -400
+q91 44 192 44q185 0 316.5 -131.5t131.5 -316.5z" />
+    <glyph glyph-name="_487" unicode="&#xf207;" 
+d="M384 320q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1408 320q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1362 716l-72 384q-5 23 -22.5 37.5t-40.5 14.5
+h-918q-23 0 -40.5 -14.5t-22.5 -37.5l-72 -384q-5 -30 14 -53t49 -23h1062q30 0 49 23t14 53zM1136 1328q0 20 -14 34t-34 14h-640q-20 0 -34 -14t-14 -34t14 -34t34 -14h640q20 0 34 14t14 34zM1536 603v-603h-128v-128q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5
+t-37.5 90.5v128h-768v-128q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5v128h-128v603q0 112 25 223l103 454q9 78 97.5 137t230 89t312.5 30t312.5 -30t230 -89t97.5 -137l105 -454q23 -102 23 -223z" />
+    <glyph glyph-name="_488" unicode="&#xf208;" horiz-adv-x="2048" 
+d="M1463 704q0 -35 -25 -60.5t-61 -25.5h-702q-36 0 -61 25.5t-25 60.5t25 60.5t61 25.5h702q36 0 61 -25.5t25 -60.5zM1677 704q0 86 -23 170h-982q-36 0 -61 25t-25 60q0 36 25 61t61 25h908q-88 143 -235 227t-320 84q-177 0 -327.5 -87.5t-238 -237.5t-87.5 -327
+q0 -86 23 -170h982q36 0 61 -25t25 -60q0 -36 -25 -61t-61 -25h-908q88 -143 235.5 -227t320.5 -84q132 0 253 51.5t208 139t139 208t52 253.5zM2048 959q0 -35 -25 -60t-61 -25h-131q17 -85 17 -170q0 -167 -65.5 -319.5t-175.5 -263t-262.5 -176t-319.5 -65.5
+q-246 0 -448.5 133t-301.5 350h-189q-36 0 -61 25t-25 61q0 35 25 60t61 25h132q-17 85 -17 170q0 167 65.5 319.5t175.5 263t262.5 176t320.5 65.5q245 0 447.5 -133t301.5 -350h188q36 0 61 -25t25 -61z" />
+    <glyph glyph-name="_489" unicode="&#xf209;" horiz-adv-x="1280" 
+d="M953 1158l-114 -328l117 -21q165 451 165 518q0 56 -38 56q-57 0 -130 -225zM654 471l33 -88q37 42 71 67l-33 5.5t-38.5 7t-32.5 8.5zM362 1367q0 -98 159 -521q17 10 49 10q15 0 75 -5l-121 351q-75 220 -123 220q-19 0 -29 -17.5t-10 -37.5zM283 608q0 -36 51.5 -119
+t117.5 -153t100 -70q14 0 25.5 13t11.5 27q0 24 -32 102q-13 32 -32 72t-47.5 89t-61.5 81t-62 32q-20 0 -45.5 -27t-25.5 -47zM125 273q0 -41 25 -104q59 -145 183.5 -227t281.5 -82q227 0 382 170q152 169 152 427q0 43 -1 67t-11.5 62t-30.5 56q-56 49 -211.5 75.5
+t-270.5 26.5q-37 0 -49 -11q-12 -5 -12 -35q0 -34 21.5 -60t55.5 -40t77.5 -23.5t87.5 -11.5t85 -4t70 0h23q24 0 40 -19q15 -19 19 -55q-28 -28 -96 -54q-61 -22 -93 -46q-64 -46 -108.5 -114t-44.5 -137q0 -31 18.5 -88.5t18.5 -87.5l-3 -12q-4 -12 -4 -14
+q-137 10 -146 216q-8 -2 -41 -2q2 -7 2 -21q0 -53 -40.5 -89.5t-94.5 -36.5q-82 0 -166.5 78t-84.5 159q0 34 33 67q52 -64 60 -76q77 -104 133 -104q12 0 26.5 8.5t14.5 20.5q0 34 -87.5 145t-116.5 111q-43 0 -70 -44.5t-27 -90.5zM11 264q0 101 42.5 163t136.5 88
+q-28 74 -28 104q0 62 61 123t122 61q29 0 70 -15q-163 462 -163 567q0 80 41 130.5t119 50.5q131 0 325 -581q6 -17 8 -23q6 16 29 79.5t43.5 118.5t54 127.5t64.5 123t70.5 86.5t76.5 36q71 0 112 -49t41 -122q0 -108 -159 -550q61 -15 100.5 -46t58.5 -78t26 -93.5
+t7 -110.5q0 -150 -47 -280t-132 -225t-211 -150t-278 -55q-111 0 -223 42q-149 57 -258 191.5t-109 286.5z" />
+    <glyph glyph-name="_490" unicode="&#xf20a;" horiz-adv-x="2048" 
+d="M785 528h207q-14 -158 -98.5 -248.5t-214.5 -90.5q-162 0 -254.5 116t-92.5 316q0 194 93 311.5t233 117.5q148 0 232 -87t97 -247h-203q-5 64 -35.5 99t-81.5 35q-57 0 -88.5 -60.5t-31.5 -177.5q0 -48 5 -84t18 -69.5t40 -51.5t66 -18q95 0 109 139zM1497 528h206
+q-14 -158 -98 -248.5t-214 -90.5q-162 0 -254.5 116t-92.5 316q0 194 93 311.5t233 117.5q148 0 232 -87t97 -247h-204q-4 64 -35 99t-81 35q-57 0 -88.5 -60.5t-31.5 -177.5q0 -48 5 -84t18 -69.5t39.5 -51.5t65.5 -18q49 0 76.5 38t33.5 101zM1856 647q0 207 -15.5 307
+t-60.5 161q-6 8 -13.5 14t-21.5 15t-16 11q-86 63 -697 63q-625 0 -710 -63q-5 -4 -17.5 -11.5t-21 -14t-14.5 -14.5q-45 -60 -60 -159.5t-15 -308.5q0 -208 15 -307.5t60 -160.5q6 -8 15 -15t20.5 -14t17.5 -12q44 -33 239.5 -49t470.5 -16q610 0 697 65q5 4 17 11t20.5 14
+t13.5 16q46 60 61 159t15 309zM2048 1408v-1536h-2048v1536h2048z" />
+    <glyph glyph-name="_491" unicode="&#xf20b;" 
+d="M992 912v-496q0 -14 -9 -23t-23 -9h-160q-14 0 -23 9t-9 23v496q0 112 -80 192t-192 80h-272v-1152q0 -14 -9 -23t-23 -9h-160q-14 0 -23 9t-9 23v1344q0 14 9 23t23 9h464q135 0 249 -66.5t180.5 -180.5t66.5 -249zM1376 1376v-880q0 -135 -66.5 -249t-180.5 -180.5
+t-249 -66.5h-464q-14 0 -23 9t-9 23v960q0 14 9 23t23 9h160q14 0 23 -9t9 -23v-768h272q112 0 192 80t80 192v880q0 14 9 23t23 9h160q14 0 23 -9t9 -23z" />
+    <glyph glyph-name="_492" unicode="&#xf20c;" 
+d="M1311 694v-114q0 -24 -13.5 -38t-37.5 -14h-202q-24 0 -38 14t-14 38v114q0 24 14 38t38 14h202q24 0 37.5 -14t13.5 -38zM821 464v250q0 53 -32.5 85.5t-85.5 32.5h-133q-68 0 -96 -52q-28 52 -96 52h-130q-53 0 -85.5 -32.5t-32.5 -85.5v-250q0 -22 21 -22h55
+q22 0 22 22v230q0 24 13.5 38t38.5 14h94q24 0 38 -14t14 -38v-230q0 -22 21 -22h54q22 0 22 22v230q0 24 14 38t38 14h97q24 0 37.5 -14t13.5 -38v-230q0 -22 22 -22h55q21 0 21 22zM1410 560v154q0 53 -33 85.5t-86 32.5h-264q-53 0 -86 -32.5t-33 -85.5v-410
+q0 -21 22 -21h55q21 0 21 21v180q31 -42 94 -42h191q53 0 86 32.5t33 85.5zM1536 1176v-1072q0 -96 -68 -164t-164 -68h-1072q-96 0 -164 68t-68 164v1072q0 96 68 164t164 68h1072q96 0 164 -68t68 -164z" />
+    <glyph glyph-name="_493" unicode="&#xf20d;" 
+d="M915 450h-294l147 551zM1001 128h311l-324 1024h-440l-324 -1024h311l383 314zM1536 1120v-960q0 -118 -85 -203t-203 -85h-960q-118 0 -203 85t-85 203v960q0 118 85 203t203 85h960q118 0 203 -85t85 -203z" />
+    <glyph glyph-name="_494" unicode="&#xf20e;" horiz-adv-x="2048" 
+d="M2048 641q0 -21 -13 -36.5t-33 -19.5l-205 -356q3 -9 3 -18q0 -20 -12.5 -35.5t-32.5 -19.5l-193 -337q3 -8 3 -16q0 -23 -16.5 -40t-40.5 -17q-25 0 -41 18h-400q-17 -20 -43 -20t-43 20h-399q-17 -20 -43 -20q-23 0 -40 16.5t-17 40.5q0 8 4 20l-193 335
+q-20 4 -32.5 19.5t-12.5 35.5q0 9 3 18l-206 356q-20 5 -32.5 20.5t-12.5 35.5q0 21 13.5 36.5t33.5 19.5l199 344q0 1 -0.5 3t-0.5 3q0 36 34 51l209 363q-4 10 -4 18q0 24 17 40.5t40 16.5q26 0 44 -21h396q16 21 43 21t43 -21h398q18 21 44 21q23 0 40 -16.5t17 -40.5
+q0 -6 -4 -18l207 -358q23 -1 39 -17.5t16 -38.5q0 -13 -7 -27l187 -324q19 -4 31.5 -19.5t12.5 -35.5zM1063 -158h389l-342 354h-143l-342 -354h360q18 16 39 16t39 -16zM112 654q1 -4 1 -13q0 -10 -2 -15l208 -360l15 -6l188 199v347l-187 194q-13 -8 -29 -10zM986 1438
+h-388l190 -200l554 200h-280q-16 -16 -38 -16t-38 16zM1689 226q1 6 5 11l-64 68l-17 -79h76zM1583 226l22 105l-252 266l-296 -307l63 -64h463zM1495 -142l16 28l65 310h-427l333 -343q8 4 13 5zM578 -158h5l342 354h-373v-335l4 -6q14 -5 22 -13zM552 226h402l64 66
+l-309 321l-157 -166v-221zM359 226h163v189l-168 -177q4 -8 5 -12zM358 1051q0 -1 0.5 -2t0.5 -2q0 -16 -8 -29l171 -177v269zM552 1121v-311l153 -157l297 314l-223 236zM556 1425l-4 -8v-264l205 74l-191 201q-6 -2 -10 -3zM1447 1438h-16l-621 -224l213 -225zM1023 946
+l-297 -315l311 -319l296 307zM688 634l-136 141v-284zM1038 270l-42 -44h85zM1374 618l238 -251l132 624l-3 5l-1 1zM1718 1018q-8 13 -8 29v2l-216 376q-5 1 -13 5l-437 -463l310 -327zM522 1142v223l-163 -282zM522 196h-163l163 -283v283zM1607 196l-48 -227l130 227h-82
+zM1729 266l207 361q-2 10 -2 14q0 1 3 16l-171 296l-129 -612l77 -82q5 3 15 7z" />
+    <glyph glyph-name="f210" unicode="&#xf210;" 
+d="M0 856q0 131 91.5 226.5t222.5 95.5h742l352 358v-1470q0 -132 -91.5 -227t-222.5 -95h-780q-131 0 -222.5 95t-91.5 227v790zM1232 102l-176 180v425q0 46 -32 79t-78 33h-484q-46 0 -78 -33t-32 -79v-492q0 -46 32.5 -79.5t77.5 -33.5h770z" />
+    <glyph glyph-name="_496" unicode="&#xf211;" 
+d="M934 1386q-317 -121 -556 -362.5t-358 -560.5q-20 89 -20 176q0 208 102.5 384.5t278.5 279t384 102.5q82 0 169 -19zM1203 1267q93 -65 164 -155q-389 -113 -674.5 -400.5t-396.5 -676.5q-93 72 -155 162q112 386 395 671t667 399zM470 -67q115 356 379.5 622t619.5 384
+q40 -92 54 -195q-292 -120 -516 -345t-343 -518q-103 14 -194 52zM1536 -125q-193 50 -367 115q-135 -84 -290 -107q109 205 274 370.5t369 275.5q-21 -152 -101 -284q65 -175 115 -370z" />
+    <glyph glyph-name="f212" unicode="&#xf212;" horiz-adv-x="2048" 
+d="M1893 1144l155 -1272q-131 0 -257 57q-200 91 -393 91q-226 0 -374 -148q-148 148 -374 148q-193 0 -393 -91q-128 -57 -252 -57h-5l155 1272q224 127 482 127q233 0 387 -106q154 106 387 106q258 0 482 -127zM1398 157q129 0 232 -28.5t260 -93.5l-124 1021
+q-171 78 -368 78q-224 0 -374 -141q-150 141 -374 141q-197 0 -368 -78l-124 -1021q105 43 165.5 65t148.5 39.5t178 17.5q202 0 374 -108q172 108 374 108zM1438 191l-55 907q-211 -4 -359 -155q-152 155 -374 155q-176 0 -336 -66l-114 -941q124 51 228.5 76t221.5 25
+q209 0 374 -102q172 107 374 102z" />
+    <glyph glyph-name="_498" unicode="&#xf213;" horiz-adv-x="2048" 
+d="M1500 165v733q0 21 -15 36t-35 15h-93q-20 0 -35 -15t-15 -36v-733q0 -20 15 -35t35 -15h93q20 0 35 15t15 35zM1216 165v531q0 20 -15 35t-35 15h-101q-20 0 -35 -15t-15 -35v-531q0 -20 15 -35t35 -15h101q20 0 35 15t15 35zM924 165v429q0 20 -15 35t-35 15h-101
+q-20 0 -35 -15t-15 -35v-429q0 -20 15 -35t35 -15h101q20 0 35 15t15 35zM632 165v362q0 20 -15 35t-35 15h-101q-20 0 -35 -15t-15 -35v-362q0 -20 15 -35t35 -15h101q20 0 35 15t15 35zM2048 311q0 -166 -118 -284t-284 -118h-1244q-166 0 -284 118t-118 284
+q0 116 63 214.5t168 148.5q-10 34 -10 73q0 113 80.5 193.5t193.5 80.5q102 0 180 -67q45 183 194 300t338 117q149 0 275 -73.5t199.5 -199.5t73.5 -275q0 -66 -14 -122q135 -33 221 -142.5t86 -247.5z" />
+    <glyph glyph-name="_499" unicode="&#xf214;" 
+d="M0 1536h1536v-1392l-776 -338l-760 338v1392zM1436 209v926h-1336v-926l661 -294zM1436 1235v201h-1336v-201h1336zM181 937v-115h-37v115h37zM181 789v-115h-37v115h37zM181 641v-115h-37v115h37zM181 493v-115h-37v115h37zM181 345v-115h-37v115h37zM207 202l15 34
+l105 -47l-15 -33zM343 142l15 34l105 -46l-15 -34zM478 82l15 34l105 -46l-15 -34zM614 23l15 33l104 -46l-15 -34zM797 10l105 46l15 -33l-105 -47zM932 70l105 46l15 -34l-105 -46zM1068 130l105 46l15 -34l-105 -46zM1203 189l105 47l15 -34l-105 -46zM259 1389v-36h-114
+v36h114zM421 1389v-36h-115v36h115zM583 1389v-36h-115v36h115zM744 1389v-36h-114v36h114zM906 1389v-36h-114v36h114zM1068 1389v-36h-115v36h115zM1230 1389v-36h-115v36h115zM1391 1389v-36h-114v36h114zM181 1049v-79h-37v115h115v-36h-78zM421 1085v-36h-115v36h115z
+M583 1085v-36h-115v36h115zM744 1085v-36h-114v36h114zM906 1085v-36h-114v36h114zM1068 1085v-36h-115v36h115zM1230 1085v-36h-115v36h115zM1355 970v79h-78v36h115v-115h-37zM1355 822v115h37v-115h-37zM1355 674v115h37v-115h-37zM1355 526v115h37v-115h-37zM1355 378
+v115h37v-115h-37zM1355 230v115h37v-115h-37zM760 265q-129 0 -221 91.5t-92 221.5q0 129 92 221t221 92q130 0 221.5 -92t91.5 -221q0 -130 -91.5 -221.5t-221.5 -91.5zM595 646q0 -36 19.5 -56.5t49.5 -25t64 -7t64 -2t49.5 -9t19.5 -30.5q0 -49 -112 -49q-97 0 -123 51
+h-3l-31 -63q67 -42 162 -42q29 0 56.5 5t55.5 16t45.5 33t17.5 53q0 46 -27.5 69.5t-67.5 27t-79.5 3t-67 5t-27.5 25.5q0 21 20.5 33t40.5 15t41 3q34 0 70.5 -11t51.5 -34h3l30 58q-3 1 -21 8.5t-22.5 9t-19.5 7t-22 7t-20 4.5t-24 4t-23 1q-29 0 -56.5 -5t-54 -16.5
+t-43 -34t-16.5 -53.5z" />
+    <glyph glyph-name="_500" unicode="&#xf215;" horiz-adv-x="2048" 
+d="M863 504q0 112 -79.5 191.5t-191.5 79.5t-191 -79.5t-79 -191.5t79 -191t191 -79t191.5 79t79.5 191zM1726 505q0 112 -79 191t-191 79t-191.5 -79t-79.5 -191q0 -113 79.5 -192t191.5 -79t191 79.5t79 191.5zM2048 1314v-1348q0 -44 -31.5 -75.5t-76.5 -31.5h-1832
+q-45 0 -76.5 31.5t-31.5 75.5v1348q0 44 31.5 75.5t76.5 31.5h431q44 0 76 -31.5t32 -75.5v-161h754v161q0 44 32 75.5t76 31.5h431q45 0 76.5 -31.5t31.5 -75.5z" />
+    <glyph glyph-name="_501" unicode="&#xf216;" horiz-adv-x="2048" 
+d="M1430 953zM1690 749q148 0 253 -98.5t105 -244.5q0 -157 -109 -261.5t-267 -104.5q-85 0 -162 27.5t-138 73.5t-118 106t-109 126t-103.5 132.5t-108.5 126.5t-117 106t-136 73.5t-159 27.5q-154 0 -251.5 -91.5t-97.5 -244.5q0 -157 104 -250t263 -93q100 0 208 37.5
+t193 98.5q5 4 21 18.5t30 24t22 9.5q14 0 24.5 -10.5t10.5 -24.5q0 -24 -60 -77q-101 -88 -234.5 -142t-260.5 -54q-133 0 -245.5 58t-180 165t-67.5 241q0 205 141.5 341t347.5 136q120 0 226.5 -43.5t185.5 -113t151.5 -153t139 -167.5t133.5 -153.5t149.5 -113
+t172.5 -43.5q102 0 168.5 61.5t66.5 162.5q0 95 -64.5 159t-159.5 64q-30 0 -81.5 -18.5t-68.5 -18.5q-20 0 -35.5 15t-15.5 35q0 18 8.5 57t8.5 59q0 159 -107.5 263t-266.5 104q-58 0 -111.5 -18.5t-84 -40.5t-55.5 -40.5t-33 -18.5q-15 0 -25.5 10.5t-10.5 25.5
+q0 19 25 46q59 67 147 103.5t182 36.5q191 0 318 -125.5t127 -315.5q0 -37 -4 -66q57 15 115 15z" />
+    <glyph glyph-name="_502" unicode="&#xf217;" horiz-adv-x="1664" 
+d="M1216 832q0 26 -19 45t-45 19h-128v128q0 26 -19 45t-45 19t-45 -19t-19 -45v-128h-128q-26 0 -45 -19t-19 -45t19 -45t45 -19h128v-128q0 -26 19 -45t45 -19t45 19t19 45v128h128q26 0 45 19t19 45zM640 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5
+t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1536 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1664 1088v-512q0 -24 -16 -42.5t-41 -21.5l-1044 -122q1 -7 4.5 -21.5t6 -26.5t2.5 -22q0 -16 -24 -64h920
+q26 0 45 -19t19 -45t-19 -45t-45 -19h-1024q-26 0 -45 19t-19 45q0 14 11 39.5t29.5 59.5t20.5 38l-177 823h-204q-26 0 -45 19t-19 45t19 45t45 19h256q16 0 28.5 -6.5t20 -15.5t13 -24.5t7.5 -26.5t5.5 -29.5t4.5 -25.5h1201q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="_503" unicode="&#xf218;" horiz-adv-x="1664" 
+d="M1280 832q0 26 -19 45t-45 19t-45 -19l-147 -146v293q0 26 -19 45t-45 19t-45 -19t-19 -45v-293l-147 146q-19 19 -45 19t-45 -19t-19 -45t19 -45l256 -256q19 -19 45 -19t45 19l256 256q19 19 19 45zM640 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5
+t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1536 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1664 1088v-512q0 -24 -16 -42.5t-41 -21.5l-1044 -122q1 -7 4.5 -21.5t6 -26.5t2.5 -22q0 -16 -24 -64h920
+q26 0 45 -19t19 -45t-19 -45t-45 -19h-1024q-26 0 -45 19t-19 45q0 14 11 39.5t29.5 59.5t20.5 38l-177 823h-204q-26 0 -45 19t-19 45t19 45t45 19h256q16 0 28.5 -6.5t20 -15.5t13 -24.5t7.5 -26.5t5.5 -29.5t4.5 -25.5h1201q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="_504" unicode="&#xf219;" horiz-adv-x="2048" 
+d="M212 768l623 -665l-300 665h-323zM1024 -4l349 772h-698zM538 896l204 384h-262l-288 -384h346zM1213 103l623 665h-323zM683 896h682l-204 384h-274zM1510 896h346l-288 384h-262zM1651 1382l384 -512q14 -18 13 -41.5t-17 -40.5l-960 -1024q-18 -20 -47 -20t-47 20
+l-960 1024q-16 17 -17 40.5t13 41.5l384 512q18 26 51 26h1152q33 0 51 -26z" />
+    <glyph glyph-name="_505" unicode="&#xf21a;" horiz-adv-x="2048" 
+d="M1811 -19q19 19 45 19t45 -19l128 -128l-90 -90l-83 83l-83 -83q-18 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83
+q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-128 128l90 90l83 -83l83 83q19 19 45 19t45 -19l83 -83l83 83q19 19 45 19t45 -19l83 -83l83 83q19 19 45 19t45 -19l83 -83l83 83q19 19 45 19t45 -19l83 -83l83 83q19 19 45 19t45 -19l83 -83l83 83
+q19 19 45 19t45 -19l83 -83zM237 19q-19 -19 -45 -19t-45 19l-128 128l90 90l83 -82l83 82q19 19 45 19t45 -19l83 -82l64 64v293l-210 314q-17 26 -7 56.5t40 40.5l177 58v299h128v128h256v128h256v-128h256v-128h128v-299l177 -58q30 -10 40 -40.5t-7 -56.5l-210 -314
+v-293l19 18q19 19 45 19t45 -19l83 -82l83 82q19 19 45 19t45 -19l128 -128l-90 -90l-83 83l-83 -83q-18 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83
+q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83zM640 1152v-128l384 128l384 -128v128h-128v128h-512v-128h-128z" />
+    <glyph glyph-name="_506" unicode="&#xf21b;" 
+d="M576 0l96 448l-96 128l-128 64zM832 0l128 640l-128 -64l-96 -128zM992 1010q-2 4 -4 6q-10 8 -96 8q-70 0 -167 -19q-7 -2 -21 -2t-21 2q-97 19 -167 19q-86 0 -96 -8q-2 -2 -4 -6q2 -18 4 -27q2 -3 7.5 -6.5t7.5 -10.5q2 -4 7.5 -20.5t7 -20.5t7.5 -17t8.5 -17t9 -14
+t12 -13.5t14 -9.5t17.5 -8t20.5 -4t24.5 -2q36 0 59 12.5t32.5 30t14.5 34.5t11.5 29.5t17.5 12.5h12q11 0 17.5 -12.5t11.5 -29.5t14.5 -34.5t32.5 -30t59 -12.5q13 0 24.5 2t20.5 4t17.5 8t14 9.5t12 13.5t9 14t8.5 17t7.5 17t7 20.5t7.5 20.5q2 7 7.5 10.5t7.5 6.5
+q2 9 4 27zM1408 131q0 -121 -73 -190t-194 -69h-874q-121 0 -194 69t-73 190q0 61 4.5 118t19 125.5t37.5 123.5t63.5 103.5t93.5 74.5l-90 220h214q-22 64 -22 128q0 12 2 32q-194 40 -194 96q0 57 210 99q17 62 51.5 134t70.5 114q32 37 76 37q30 0 84 -31t84 -31t84 31
+t84 31q44 0 76 -37q36 -42 70.5 -114t51.5 -134q210 -42 210 -99q0 -56 -194 -96q7 -81 -20 -160h214l-82 -225q63 -33 107.5 -96.5t65.5 -143.5t29 -151.5t8 -148.5z" />
+    <glyph glyph-name="_507" unicode="&#xf21c;" horiz-adv-x="2304" 
+d="M2301 500q12 -103 -22 -198.5t-99 -163.5t-158.5 -106t-196.5 -31q-161 11 -279.5 125t-134.5 274q-12 111 27.5 210.5t118.5 170.5l-71 107q-96 -80 -151 -194t-55 -244q0 -27 -18.5 -46.5t-45.5 -19.5h-256h-69q-23 -164 -149 -274t-294 -110q-185 0 -316.5 131.5
+t-131.5 316.5t131.5 316.5t316.5 131.5q76 0 152 -27l24 45q-123 110 -304 110h-64q-26 0 -45 19t-19 45t19 45t45 19h128q78 0 145 -13.5t116.5 -38.5t71.5 -39.5t51 -36.5h512h115l-85 128h-222q-30 0 -49 22.5t-14 52.5q4 23 23 38t43 15h253q33 0 53 -28l70 -105
+l114 114q19 19 46 19h101q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-179l115 -172q131 63 275 36q143 -26 244 -134.5t118 -253.5zM448 128q115 0 203 72.5t111 183.5h-314q-35 0 -55 31q-18 32 -1 63l147 277q-47 13 -91 13q-132 0 -226 -94t-94 -226t94 -226
+t226 -94zM1856 128q132 0 226 94t94 226t-94 226t-226 94q-60 0 -121 -24l174 -260q15 -23 10 -49t-27 -40q-15 -11 -36 -11q-35 0 -53 29l-174 260q-93 -95 -93 -225q0 -132 94 -226t226 -94z" />
+    <glyph glyph-name="_508" unicode="&#xf21d;" 
+d="M1408 0q0 -63 -61.5 -113.5t-164 -81t-225 -46t-253.5 -15.5t-253.5 15.5t-225 46t-164 81t-61.5 113.5q0 49 33 88.5t91 66.5t118 44.5t131 29.5q26 5 48 -10.5t26 -41.5q5 -26 -10.5 -48t-41.5 -26q-58 -10 -106 -23.5t-76.5 -25.5t-48.5 -23.5t-27.5 -19.5t-8.5 -12
+q3 -11 27 -26.5t73 -33t114 -32.5t160.5 -25t201.5 -10t201.5 10t160.5 25t114 33t73 33.5t27 27.5q-1 4 -8.5 11t-27.5 19t-48.5 23.5t-76.5 25t-106 23.5q-26 4 -41.5 26t-10.5 48q4 26 26 41.5t48 10.5q71 -12 131 -29.5t118 -44.5t91 -66.5t33 -88.5zM1024 896v-384
+q0 -26 -19 -45t-45 -19h-64v-384q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v384h-64q-26 0 -45 19t-19 45v384q0 53 37.5 90.5t90.5 37.5h384q53 0 90.5 -37.5t37.5 -90.5zM928 1280q0 -93 -65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5
+t158.5 -65.5t65.5 -158.5z" />
+    <glyph glyph-name="_509" unicode="&#xf21e;" horiz-adv-x="1792" 
+d="M1280 512h305q-5 -6 -10 -10.5t-9 -7.5l-3 -4l-623 -600q-18 -18 -44 -18t-44 18l-624 602q-5 2 -21 20h369q22 0 39.5 13.5t22.5 34.5l70 281l190 -667q6 -20 23 -33t39 -13q21 0 38 13t23 33l146 485l56 -112q18 -35 57 -35zM1792 940q0 -145 -103 -300h-369l-111 221
+q-8 17 -25.5 27t-36.5 8q-45 -5 -56 -46l-129 -430l-196 686q-6 20 -23.5 33t-39.5 13t-39 -13.5t-22 -34.5l-116 -464h-423q-103 155 -103 300q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5q224 0 351 -124
+t127 -344z" />
+    <glyph glyph-name="venus" unicode="&#xf221;" horiz-adv-x="1280" 
+d="M1152 960q0 -221 -147.5 -384.5t-364.5 -187.5v-260h224q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-224v-224q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v224h-224q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h224v260q-150 16 -271.5 103t-186 224t-52.5 292
+q11 134 80.5 249t182 188t245.5 88q170 19 319 -54t236 -212t87 -306zM128 960q0 -185 131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5z" />
+    <glyph glyph-name="_511" unicode="&#xf222;" 
+d="M1472 1408q26 0 45 -19t19 -45v-416q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v262l-382 -383q126 -156 126 -359q0 -117 -45.5 -223.5t-123 -184t-184 -123t-223.5 -45.5t-223.5 45.5t-184 123t-123 184t-45.5 223.5t45.5 223.5t123 184t184 123t223.5 45.5
+q203 0 359 -126l382 382h-261q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h416zM576 0q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+    <glyph glyph-name="_512" unicode="&#xf223;" horiz-adv-x="1280" 
+d="M830 1220q145 -72 233.5 -210.5t88.5 -305.5q0 -221 -147.5 -384.5t-364.5 -187.5v-132h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96v-96q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v96h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96v132q-217 24 -364.5 187.5
+t-147.5 384.5q0 167 88.5 305.5t233.5 210.5q-165 96 -228 273q-6 16 3.5 29.5t26.5 13.5h69q21 0 29 -20q44 -106 140 -171t214 -65t214 65t140 171q8 20 37 20h61q17 0 26.5 -13.5t3.5 -29.5q-63 -177 -228 -273zM576 256q185 0 316.5 131.5t131.5 316.5t-131.5 316.5
+t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+    <glyph glyph-name="_513" unicode="&#xf224;" 
+d="M1024 1504q0 14 9 23t23 9h288q26 0 45 -19t19 -45v-288q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v134l-254 -255q126 -158 126 -359q0 -221 -147.5 -384.5t-364.5 -187.5v-132h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96v-96q0 -14 -9 -23t-23 -9h-64
+q-14 0 -23 9t-9 23v96h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96v132q-149 16 -270.5 103t-186.5 223.5t-53 291.5q16 204 160 353.5t347 172.5q118 14 228 -19t198 -103l255 254h-134q-14 0 -23 9t-9 23v64zM576 256q185 0 316.5 131.5t131.5 316.5t-131.5 316.5
+t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+    <glyph glyph-name="_514" unicode="&#xf225;" horiz-adv-x="1792" 
+d="M1280 1504q0 14 9 23t23 9h288q26 0 45 -19t19 -45v-288q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v134l-254 -255q126 -158 126 -359q0 -221 -147.5 -384.5t-364.5 -187.5v-132h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96v-96q0 -14 -9 -23t-23 -9h-64
+q-14 0 -23 9t-9 23v96h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96v132q-217 24 -364.5 187.5t-147.5 384.5q0 201 126 359l-52 53l-101 -111q-9 -10 -22 -10.5t-23 7.5l-48 44q-10 8 -10.5 21.5t8.5 23.5l105 115l-111 112v-134q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9
+t-9 23v288q0 26 19 45t45 19h288q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-133l106 -107l86 94q9 10 22 10.5t23 -7.5l48 -44q10 -8 10.5 -21.5t-8.5 -23.5l-90 -99l57 -56q158 126 359 126t359 -126l255 254h-134q-14 0 -23 9t-9 23v64zM832 256q185 0 316.5 131.5
+t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+    <glyph glyph-name="_515" unicode="&#xf226;" horiz-adv-x="1792" 
+d="M1790 1007q12 -155 -52.5 -292t-186 -224t-271.5 -103v-260h224q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-224v-224q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v224h-512v-224q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v224h-224q-14 0 -23 9t-9 23v64q0 14 9 23
+t23 9h224v260q-150 16 -271.5 103t-186 224t-52.5 292q17 206 164.5 356.5t352.5 169.5q206 21 377 -94q171 115 377 94q205 -19 352.5 -169.5t164.5 -356.5zM896 647q128 131 128 313t-128 313q-128 -131 -128 -313t128 -313zM576 512q115 0 218 57q-154 165 -154 391
+q0 224 154 391q-103 57 -218 57q-185 0 -316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5zM1152 128v260q-137 15 -256 94q-119 -79 -256 -94v-260h512zM1216 512q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5q-115 0 -218 -57q154 -167 154 -391
+q0 -226 -154 -391q103 -57 218 -57z" />
+    <glyph glyph-name="_516" unicode="&#xf227;" horiz-adv-x="1920" 
+d="M1536 1120q0 14 9 23t23 9h288q26 0 45 -19t19 -45v-288q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v134l-254 -255q76 -95 107.5 -214t9.5 -247q-31 -182 -166 -312t-318 -156q-210 -29 -384.5 80t-241.5 300q-117 6 -221 57.5t-177.5 133t-113.5 192.5t-32 230
+q9 135 78 252t182 191.5t248 89.5q118 14 227.5 -19t198.5 -103l255 254h-134q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h288q26 0 45 -19t19 -45v-288q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v134l-254 -255q59 -74 93 -169q182 -9 328 -124l255 254h-134q-14 0 -23 9
+t-9 23v64zM1024 704q0 20 -4 58q-162 -25 -271 -150t-109 -292q0 -20 4 -58q162 25 271 150t109 292zM128 704q0 -168 111 -294t276 -149q-3 29 -3 59q0 210 135 369.5t338 196.5q-53 120 -163.5 193t-245.5 73q-185 0 -316.5 -131.5t-131.5 -316.5zM1088 -128
+q185 0 316.5 131.5t131.5 316.5q0 168 -111 294t-276 149q3 -28 3 -59q0 -210 -135 -369.5t-338 -196.5q53 -120 163.5 -193t245.5 -73z" />
+    <glyph glyph-name="_517" unicode="&#xf228;" horiz-adv-x="2048" 
+d="M1664 1504q0 14 9 23t23 9h288q26 0 45 -19t19 -45v-288q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v134l-254 -255q76 -95 107.5 -214t9.5 -247q-32 -180 -164.5 -310t-313.5 -157q-223 -34 -409 90q-117 -78 -256 -93v-132h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23
+t-23 -9h-96v-96q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v96h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96v132q-155 17 -279.5 109.5t-187 237.5t-39.5 307q25 187 159.5 322.5t320.5 164.5q224 34 410 -90q146 97 320 97q201 0 359 -126l255 254h-134q-14 0 -23 9
+t-9 23v64zM896 391q128 131 128 313t-128 313q-128 -131 -128 -313t128 -313zM128 704q0 -185 131.5 -316.5t316.5 -131.5q117 0 218 57q-154 167 -154 391t154 391q-101 57 -218 57q-185 0 -316.5 -131.5t-131.5 -316.5zM1216 256q185 0 316.5 131.5t131.5 316.5
+t-131.5 316.5t-316.5 131.5q-117 0 -218 -57q154 -167 154 -391t-154 -391q101 -57 218 -57z" />
+    <glyph glyph-name="_518" unicode="&#xf229;" 
+d="M1472 1408q26 0 45 -19t19 -45v-416q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v262l-213 -214l140 -140q9 -10 9 -23t-9 -22l-46 -46q-9 -9 -22 -9t-23 9l-140 141l-78 -79q126 -156 126 -359q0 -117 -45.5 -223.5t-123 -184t-184 -123t-223.5 -45.5t-223.5 45.5
+t-184 123t-123 184t-45.5 223.5t45.5 223.5t123 184t184 123t223.5 45.5q203 0 359 -126l78 78l-172 172q-9 10 -9 23t9 22l46 46q9 9 22 9t23 -9l172 -172l213 213h-261q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h416zM576 0q185 0 316.5 131.5t131.5 316.5t-131.5 316.5
+t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+    <glyph glyph-name="_519" unicode="&#xf22a;" horiz-adv-x="1280" 
+d="M640 892q217 -24 364.5 -187.5t147.5 -384.5q0 -167 -87 -306t-236 -212t-319 -54q-133 15 -245.5 88t-182 188t-80.5 249q-12 155 52.5 292t186 224t271.5 103v132h-160q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h160v165l-92 -92q-10 -9 -23 -9t-22 9l-46 46q-9 9 -9 22
+t9 23l202 201q19 19 45 19t45 -19l202 -201q9 -10 9 -23t-9 -22l-46 -46q-9 -9 -22 -9t-23 9l-92 92v-165h160q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-160v-132zM576 -128q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5
+t131.5 -316.5t316.5 -131.5z" />
+    <glyph glyph-name="_520" unicode="&#xf22b;" horiz-adv-x="2048" 
+d="M1901 621q19 -19 19 -45t-19 -45l-294 -294q-9 -10 -22.5 -10t-22.5 10l-45 45q-10 9 -10 22.5t10 22.5l185 185h-294v-224q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v224h-132q-24 -217 -187.5 -364.5t-384.5 -147.5q-167 0 -306 87t-212 236t-54 319q15 133 88 245.5
+t188 182t249 80.5q155 12 292 -52.5t224 -186t103 -271.5h132v224q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-224h294l-185 185q-10 9 -10 22.5t10 22.5l45 45q9 10 22.5 10t22.5 -10zM576 128q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5
+t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+    <glyph glyph-name="_521" unicode="&#xf22c;" horiz-adv-x="1280" 
+d="M1152 960q0 -221 -147.5 -384.5t-364.5 -187.5v-612q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v612q-217 24 -364.5 187.5t-147.5 384.5q0 117 45.5 223.5t123 184t184 123t223.5 45.5t223.5 -45.5t184 -123t123 -184t45.5 -223.5zM576 512q185 0 316.5 131.5
+t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+    <glyph glyph-name="_522" unicode="&#xf22d;" horiz-adv-x="1280" 
+d="M1024 576q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1152 576q0 -117 -45.5 -223.5t-123 -184t-184 -123t-223.5 -45.5t-223.5 45.5t-184 123t-123 184t-45.5 223.5t45.5 223.5t123 184t184 123
+t223.5 45.5t223.5 -45.5t184 -123t123 -184t45.5 -223.5z" />
+    <glyph glyph-name="_523" unicode="&#xf22e;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="_524" unicode="&#xf22f;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="_525" unicode="&#xf230;" 
+d="M1451 1408q35 0 60 -25t25 -60v-1366q0 -35 -25 -60t-60 -25h-391v595h199l30 232h-229v148q0 56 23.5 84t91.5 28l122 1v207q-63 9 -178 9q-136 0 -217.5 -80t-81.5 -226v-171h-200v-232h200v-595h-735q-35 0 -60 25t-25 60v1366q0 35 25 60t60 25h1366z" />
+    <glyph glyph-name="_526" unicode="&#xf231;" horiz-adv-x="1280" 
+d="M0 939q0 108 37.5 203.5t103.5 166.5t152 123t185 78t202 26q158 0 294 -66.5t221 -193.5t85 -287q0 -96 -19 -188t-60 -177t-100 -149.5t-145 -103t-189 -38.5q-68 0 -135 32t-96 88q-10 -39 -28 -112.5t-23.5 -95t-20.5 -71t-26 -71t-32 -62.5t-46 -77.5t-62 -86.5
+l-14 -5l-9 10q-15 157 -15 188q0 92 21.5 206.5t66.5 287.5t52 203q-32 65 -32 169q0 83 52 156t132 73q61 0 95 -40.5t34 -102.5q0 -66 -44 -191t-44 -187q0 -63 45 -104.5t109 -41.5q55 0 102 25t78.5 68t56 95t38 110.5t20 111t6.5 99.5q0 173 -109.5 269.5t-285.5 96.5
+q-200 0 -334 -129.5t-134 -328.5q0 -44 12.5 -85t27 -65t27 -45.5t12.5 -30.5q0 -28 -15 -73t-37 -45q-2 0 -17 3q-51 15 -90.5 56t-61 94.5t-32.5 108t-11 106.5z" />
+    <glyph glyph-name="_527" unicode="&#xf232;" 
+d="M985 562q13 0 97.5 -44t89.5 -53q2 -5 2 -15q0 -33 -17 -76q-16 -39 -71 -65.5t-102 -26.5q-57 0 -190 62q-98 45 -170 118t-148 185q-72 107 -71 194v8q3 91 74 158q24 22 52 22q6 0 18 -1.5t19 -1.5q19 0 26.5 -6.5t15.5 -27.5q8 -20 33 -88t25 -75q0 -21 -34.5 -57.5
+t-34.5 -46.5q0 -7 5 -15q34 -73 102 -137q56 -53 151 -101q12 -7 22 -7q15 0 54 48.5t52 48.5zM782 32q127 0 243.5 50t200.5 134t134 200.5t50 243.5t-50 243.5t-134 200.5t-200.5 134t-243.5 50t-243.5 -50t-200.5 -134t-134 -200.5t-50 -243.5q0 -203 120 -368l-79 -233
+l242 77q158 -104 345 -104zM782 1414q153 0 292.5 -60t240.5 -161t161 -240.5t60 -292.5t-60 -292.5t-161 -240.5t-240.5 -161t-292.5 -60q-195 0 -365 94l-417 -134l136 405q-108 178 -108 389q0 153 60 292.5t161 240.5t240.5 161t292.5 60z" />
+    <glyph glyph-name="_528" unicode="&#xf233;" horiz-adv-x="1792" 
+d="M128 128h1024v128h-1024v-128zM128 640h1024v128h-1024v-128zM1696 192q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM128 1152h1024v128h-1024v-128zM1696 704q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM1696 1216
+q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM1792 384v-384h-1792v384h1792zM1792 896v-384h-1792v384h1792zM1792 1408v-384h-1792v384h1792z" />
+    <glyph glyph-name="_529" unicode="&#xf234;" horiz-adv-x="2048" 
+d="M704 640q-159 0 -271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5t-112.5 -271.5t-271.5 -112.5zM1664 512h352q13 0 22.5 -9.5t9.5 -22.5v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-352v-352q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5
+t-9.5 22.5v352h-352q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h352v352q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5v-352zM928 288q0 -52 38 -90t90 -38h256v-238q-68 -50 -171 -50h-874q-121 0 -194 69t-73 190q0 53 3.5 103.5t14 109t26.5 108.5
+t43 97.5t62 81t85.5 53.5t111.5 20q19 0 39 -17q79 -61 154.5 -91.5t164.5 -30.5t164.5 30.5t154.5 91.5q20 17 39 17q132 0 217 -96h-223q-52 0 -90 -38t-38 -90v-192z" />
+    <glyph glyph-name="_530" unicode="&#xf235;" horiz-adv-x="2048" 
+d="M704 640q-159 0 -271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5t-112.5 -271.5t-271.5 -112.5zM1781 320l249 -249q9 -9 9 -23q0 -13 -9 -22l-136 -136q-9 -9 -22 -9q-14 0 -23 9l-249 249l-249 -249q-9 -9 -23 -9q-13 0 -22 9l-136 136
+q-9 9 -9 22q0 14 9 23l249 249l-249 249q-9 9 -9 23q0 13 9 22l136 136q9 9 22 9q14 0 23 -9l249 -249l249 249q9 9 23 9q13 0 22 -9l136 -136q9 -9 9 -22q0 -14 -9 -23zM1283 320l-181 -181q-37 -37 -37 -91q0 -53 37 -90l83 -83q-21 -3 -44 -3h-874q-121 0 -194 69
+t-73 190q0 53 3.5 103.5t14 109t26.5 108.5t43 97.5t62 81t85.5 53.5t111.5 20q19 0 39 -17q154 -122 319 -122t319 122q20 17 39 17q28 0 57 -6q-28 -27 -41 -50t-13 -56q0 -54 37 -91z" />
+    <glyph glyph-name="_531" unicode="&#xf236;" horiz-adv-x="2048" 
+d="M256 512h1728q26 0 45 -19t19 -45v-448h-256v256h-1536v-256h-256v1216q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-704zM832 832q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM2048 576v64q0 159 -112.5 271.5t-271.5 112.5h-704
+q-26 0 -45 -19t-19 -45v-384h1152z" />
+    <glyph glyph-name="_532" unicode="&#xf237;" 
+d="M1536 1536l-192 -448h192v-192h-274l-55 -128h329v-192h-411l-357 -832l-357 832h-411v192h329l-55 128h-274v192h192l-192 448h256l323 -768h378l323 768h256zM768 320l108 256h-216z" />
+    <glyph glyph-name="_533" unicode="&#xf238;" 
+d="M1088 1536q185 0 316.5 -93.5t131.5 -226.5v-896q0 -130 -125.5 -222t-305.5 -97l213 -202q16 -15 8 -35t-30 -20h-1056q-22 0 -30 20t8 35l213 202q-180 5 -305.5 97t-125.5 222v896q0 133 131.5 226.5t316.5 93.5h640zM768 192q80 0 136 56t56 136t-56 136t-136 56
+t-136 -56t-56 -136t56 -136t136 -56zM1344 768v512h-1152v-512h1152z" />
+    <glyph glyph-name="_534" unicode="&#xf239;" 
+d="M1088 1536q185 0 316.5 -93.5t131.5 -226.5v-896q0 -130 -125.5 -222t-305.5 -97l213 -202q16 -15 8 -35t-30 -20h-1056q-22 0 -30 20t8 35l213 202q-180 5 -305.5 97t-125.5 222v896q0 133 131.5 226.5t316.5 93.5h640zM288 224q66 0 113 47t47 113t-47 113t-113 47
+t-113 -47t-47 -113t47 -113t113 -47zM704 768v512h-544v-512h544zM1248 224q66 0 113 47t47 113t-47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47zM1408 768v512h-576v-512h576z" />
+    <glyph glyph-name="_535" unicode="&#xf23a;" horiz-adv-x="1792" 
+d="M597 1115v-1173q0 -25 -12.5 -42.5t-36.5 -17.5q-17 0 -33 8l-465 233q-21 10 -35.5 33.5t-14.5 46.5v1140q0 20 10 34t29 14q14 0 44 -15l511 -256q3 -3 3 -5zM661 1014l534 -866l-534 266v600zM1792 996v-1054q0 -25 -14 -40.5t-38 -15.5t-47 13l-441 220zM1789 1116
+q0 -3 -256.5 -419.5t-300.5 -487.5l-390 634l324 527q17 28 52 28q14 0 26 -6l541 -270q4 -2 4 -6z" />
+    <glyph glyph-name="_536" unicode="&#xf23b;" 
+d="M809 532l266 499h-112l-157 -312q-24 -48 -44 -92l-42 92l-155 312h-120l263 -493v-324h101v318zM1536 1408v-1536h-1536v1536h1536z" />
+    <glyph glyph-name="_537" unicode="&#xf23c;" horiz-adv-x="2296" 
+d="M478 -139q-8 -16 -27 -34.5t-37 -25.5q-25 -9 -51.5 3.5t-28.5 31.5q-1 22 40 55t68 38q23 4 34 -21.5t2 -46.5zM1819 -139q7 -16 26 -34.5t38 -25.5q25 -9 51.5 3.5t27.5 31.5q2 22 -39.5 55t-68.5 38q-22 4 -33 -21.5t-2 -46.5zM1867 -30q13 -27 56.5 -59.5t77.5 -41.5
+q45 -13 82 4.5t37 50.5q0 46 -67.5 100.5t-115.5 59.5q-40 5 -63.5 -37.5t-6.5 -76.5zM428 -30q-13 -27 -56 -59.5t-77 -41.5q-45 -13 -82 4.5t-37 50.5q0 46 67.5 100.5t115.5 59.5q40 5 63 -37.5t6 -76.5zM1158 1094h1q-41 0 -76 -15q27 -8 44 -30.5t17 -49.5
+q0 -35 -27 -60t-65 -25q-52 0 -80 43q-5 -23 -5 -42q0 -74 56 -126.5t135 -52.5q80 0 136 52.5t56 126.5t-56 126.5t-136 52.5zM1462 1312q-99 109 -220.5 131.5t-245.5 -44.5q27 60 82.5 96.5t118 39.5t121.5 -17t99.5 -74.5t44.5 -131.5zM2212 73q8 -11 -11 -42
+q7 -23 7 -40q1 -56 -44.5 -112.5t-109.5 -91.5t-118 -37q-48 -2 -92 21.5t-66 65.5q-687 -25 -1259 0q-23 -41 -66.5 -65t-92.5 -22q-86 3 -179.5 80.5t-92.5 160.5q2 22 7 40q-19 31 -11 42q6 10 31 1q14 22 41 51q-7 29 2 38q11 10 39 -4q29 20 59 34q0 29 13 37
+q23 12 51 -16q35 5 61 -2q18 -4 38 -19v73q-11 0 -18 2q-53 10 -97 44.5t-55 87.5q-9 38 0 81q15 62 93 95q2 17 19 35.5t36 23.5t33 -7.5t19 -30.5h13q46 -5 60 -23q3 -3 5 -7q10 1 30.5 3.5t30.5 3.5q-15 11 -30 17q-23 40 -91 43q0 6 1 10q-62 2 -118.5 18.5t-84.5 47.5
+q-32 36 -42.5 92t-2.5 112q16 126 90 179q23 16 52 4.5t32 -40.5q0 -1 1.5 -14t2.5 -21t3 -20t5.5 -19t8.5 -10q27 -14 76 -12q48 46 98 74q-40 4 -162 -14l47 46q61 58 163 111q145 73 282 86q-20 8 -41 15.5t-47 14t-42.5 10.5t-47.5 11t-43 10q595 126 904 -139
+q98 -84 158 -222q85 -10 121 9h1q5 3 8.5 10t5.5 19t3 19.5t3 21.5l1 14q3 28 32 40t52 -5q73 -52 91 -178q7 -57 -3.5 -113t-42.5 -91q-28 -32 -83.5 -48.5t-115.5 -18.5v-10q-71 -2 -95 -43q-14 -5 -31 -17q11 -1 32 -3.5t30 -3.5q1 5 5 8q16 18 60 23h13q5 18 19 30t33 8
+t36 -23t19 -36q79 -32 93 -95q9 -40 1 -81q-12 -53 -56 -88t-97 -44q-10 -2 -17 -2q0 -49 -1 -73q20 15 38 19q26 7 61 2q28 28 51 16q14 -9 14 -37q33 -16 59 -34q27 13 38 4q10 -10 2 -38q28 -30 41 -51q23 8 31 -1zM1937 1025q0 -29 -9 -54q82 -32 112 -132
+q4 37 -9.5 98.5t-41.5 90.5q-20 19 -36 17t-16 -20zM1859 925q35 -42 47.5 -108.5t-0.5 -124.5q67 13 97 45q13 14 18 28q-3 64 -31 114.5t-79 66.5q-15 -15 -52 -21zM1822 921q-30 0 -44 1q42 -115 53 -239q21 0 43 3q16 68 1 135t-53 100zM258 839q30 100 112 132
+q-9 25 -9 54q0 18 -16.5 20t-35.5 -17q-28 -29 -41.5 -90.5t-9.5 -98.5zM294 737q29 -31 97 -45q-13 58 -0.5 124.5t47.5 108.5v0q-37 6 -52 21q-51 -16 -78.5 -66t-31.5 -115q9 -17 18 -28zM471 683q14 124 73 235q-19 -4 -55 -18l-45 -19v1q-46 -89 -20 -196q25 -3 47 -3z
+M1434 644q8 -38 16.5 -108.5t11.5 -89.5q3 -18 9.5 -21.5t23.5 4.5q40 20 62 85.5t23 125.5q-24 2 -146 4zM1152 1285q-116 0 -199 -82.5t-83 -198.5q0 -117 83 -199.5t199 -82.5t199 82.5t83 199.5q0 116 -83 198.5t-199 82.5zM1380 646q-105 2 -211 0v1q-1 -27 2.5 -86
+t13.5 -66q29 -14 93.5 -14.5t95.5 10.5q9 3 11 39t-0.5 69.5t-4.5 46.5zM1112 447q8 4 9.5 48t-0.5 88t-4 63v1q-212 -3 -214 -3q-4 -20 -7 -62t0 -83t14 -46q34 -15 101 -16t101 10zM718 636q-16 -59 4.5 -118.5t77.5 -84.5q15 -8 24 -5t12 21q3 16 8 90t10 103
+q-69 -2 -136 -6zM591 510q3 -23 -34 -36q132 -141 271.5 -240t305.5 -154q172 49 310.5 146t293.5 250q-33 13 -30 34q0 2 0.5 3.5t1.5 3t1 2.5v1v-1q-17 2 -50 5.5t-48 4.5q-26 -90 -82 -132q-51 -38 -82 1q-5 6 -9 14q-7 13 -17 62q-2 -5 -5 -9t-7.5 -7t-8 -5.5t-9.5 -4
+l-10 -2.5t-12 -2l-12 -1.5t-13.5 -1t-13.5 -0.5q-106 -9 -163 11q-4 -17 -10 -26.5t-21 -15t-23 -7t-36 -3.5q-6 -1 -9 -1q-179 -17 -203 40q-2 -63 -56 -54q-47 8 -91 54q-12 13 -20 26q-17 29 -26 65q-58 -6 -87 -10q1 -2 4 -10zM507 -118q3 14 3 30q-17 71 -51 130
+t-73 70q-41 12 -101.5 -14.5t-104.5 -80t-39 -107.5q35 -53 100 -93t119 -42q51 -2 94 28t53 79zM510 53q23 -63 27 -119q195 113 392 174q-98 52 -180.5 120t-179.5 165q-6 -4 -29 -13q0 -1 -1 -4t-1 -5q31 -18 22 -37q-12 -23 -56 -34q-10 -13 -29 -24h-1q-2 -83 1 -150
+q19 -34 35 -73zM579 -113q532 -21 1145 0q-254 147 -428 196q-76 -35 -156 -57q-8 -3 -16 0q-65 21 -129 49q-208 -60 -416 -188h-1v-1q1 0 1 1zM1763 -67q4 54 28 120q14 38 33 71l-1 -1q3 77 3 153q-15 8 -30 25q-42 9 -56 33q-9 20 22 38q-2 4 -2 9q-16 4 -28 12
+q-204 -190 -383 -284q198 -59 414 -176zM2155 -90q5 54 -39 107.5t-104 80t-102 14.5q-38 -11 -72.5 -70.5t-51.5 -129.5q0 -16 3 -30q10 -49 53 -79t94 -28q54 2 119 42t100 93z" />
+    <glyph glyph-name="_538" unicode="&#xf23d;" horiz-adv-x="2304" 
+d="M1524 -25q0 -68 -48 -116t-116 -48t-116.5 48t-48.5 116t48.5 116.5t116.5 48.5t116 -48.5t48 -116.5zM775 -25q0 -68 -48.5 -116t-116.5 -48t-116 48t-48 116t48 116.5t116 48.5t116.5 -48.5t48.5 -116.5zM0 1469q57 -60 110.5 -104.5t121 -82t136 -63t166 -45.5
+t200 -31.5t250 -18.5t304 -9.5t372.5 -2.5q139 0 244.5 -5t181 -16.5t124 -27.5t71 -39.5t24 -51.5t-19.5 -64t-56.5 -76.5t-89.5 -91t-116 -104.5t-139 -119q-185 -157 -286 -247q29 51 76.5 109t94 105.5t94.5 98.5t83 91.5t54 80.5t13 70t-45.5 55.5t-116.5 41t-204 23.5
+t-304 5q-168 -2 -314 6t-256 23t-204.5 41t-159.5 51.5t-122.5 62.5t-91.5 66.5t-68 71.5t-50.5 69.5t-40 68t-36.5 59.5z" />
+    <glyph glyph-name="_539" unicode="&#xf23e;" horiz-adv-x="1792" 
+d="M896 1472q-169 0 -323 -66t-265.5 -177.5t-177.5 -265.5t-66 -323t66 -323t177.5 -265.5t265.5 -177.5t323 -66t323 66t265.5 177.5t177.5 265.5t66 323t-66 323t-177.5 265.5t-265.5 177.5t-323 66zM896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348
+t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71zM496 704q16 0 16 -16v-480q0 -16 -16 -16h-32q-16 0 -16 16v480q0 16 16 16h32zM896 640q53 0 90.5 -37.5t37.5 -90.5q0 -35 -17.5 -64t-46.5 -46v-114q0 -14 -9 -23
+t-23 -9h-64q-14 0 -23 9t-9 23v114q-29 17 -46.5 46t-17.5 64q0 53 37.5 90.5t90.5 37.5zM896 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM544 928v-96
+q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v96q0 93 65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5v-96q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v96q0 146 -103 249t-249 103t-249 -103t-103 -249zM1408 192v512q0 26 -19 45t-45 19h-896q-26 0 -45 -19t-19 -45v-512
+q0 -26 19 -45t45 -19h896q26 0 45 19t19 45z" />
+    <glyph glyph-name="_540" unicode="&#xf240;" horiz-adv-x="2304" 
+d="M1920 1024v-768h-1664v768h1664zM2048 448h128v384h-128v288q0 14 -9 23t-23 9h-1856q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h1856q14 0 23 9t9 23v288zM2304 832v-384q0 -53 -37.5 -90.5t-90.5 -37.5v-160q0 -66 -47 -113t-113 -47h-1856q-66 0 -113 47t-47 113
+v960q0 66 47 113t113 47h1856q66 0 113 -47t47 -113v-160q53 0 90.5 -37.5t37.5 -90.5z" />
+    <glyph glyph-name="_541" unicode="&#xf241;" horiz-adv-x="2304" 
+d="M256 256v768h1280v-768h-1280zM2176 960q53 0 90.5 -37.5t37.5 -90.5v-384q0 -53 -37.5 -90.5t-90.5 -37.5v-160q0 -66 -47 -113t-113 -47h-1856q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h1856q66 0 113 -47t47 -113v-160zM2176 448v384h-128v288q0 14 -9 23t-23 9
+h-1856q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h1856q14 0 23 9t9 23v288h128z" />
+    <glyph glyph-name="_542" unicode="&#xf242;" horiz-adv-x="2304" 
+d="M256 256v768h896v-768h-896zM2176 960q53 0 90.5 -37.5t37.5 -90.5v-384q0 -53 -37.5 -90.5t-90.5 -37.5v-160q0 -66 -47 -113t-113 -47h-1856q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h1856q66 0 113 -47t47 -113v-160zM2176 448v384h-128v288q0 14 -9 23t-23 9
+h-1856q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h1856q14 0 23 9t9 23v288h128z" />
+    <glyph glyph-name="_543" unicode="&#xf243;" horiz-adv-x="2304" 
+d="M256 256v768h512v-768h-512zM2176 960q53 0 90.5 -37.5t37.5 -90.5v-384q0 -53 -37.5 -90.5t-90.5 -37.5v-160q0 -66 -47 -113t-113 -47h-1856q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h1856q66 0 113 -47t47 -113v-160zM2176 448v384h-128v288q0 14 -9 23t-23 9
+h-1856q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h1856q14 0 23 9t9 23v288h128z" />
+    <glyph glyph-name="_544" unicode="&#xf244;" horiz-adv-x="2304" 
+d="M2176 960q53 0 90.5 -37.5t37.5 -90.5v-384q0 -53 -37.5 -90.5t-90.5 -37.5v-160q0 -66 -47 -113t-113 -47h-1856q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h1856q66 0 113 -47t47 -113v-160zM2176 448v384h-128v288q0 14 -9 23t-23 9h-1856q-14 0 -23 -9t-9 -23
+v-960q0 -14 9 -23t23 -9h1856q14 0 23 9t9 23v288h128z" />
+    <glyph glyph-name="_545" unicode="&#xf245;" horiz-adv-x="1280" 
+d="M1133 493q31 -30 14 -69q-17 -40 -59 -40h-382l201 -476q10 -25 0 -49t-34 -35l-177 -75q-25 -10 -49 0t-35 34l-191 452l-312 -312q-19 -19 -45 -19q-12 0 -24 5q-40 17 -40 59v1504q0 42 40 59q12 5 24 5q27 0 45 -19z" />
+    <glyph glyph-name="_546" unicode="&#xf246;" horiz-adv-x="1024" 
+d="M832 1408q-320 0 -320 -224v-416h128v-128h-128v-544q0 -224 320 -224h64v-128h-64q-272 0 -384 146q-112 -146 -384 -146h-64v128h64q320 0 320 224v544h-128v128h128v416q0 224 -320 224h-64v128h64q272 0 384 -146q112 146 384 146h64v-128h-64z" />
+    <glyph glyph-name="_547" unicode="&#xf247;" horiz-adv-x="2048" 
+d="M2048 1152h-128v-1024h128v-384h-384v128h-1280v-128h-384v384h128v1024h-128v384h384v-128h1280v128h384v-384zM1792 1408v-128h128v128h-128zM128 1408v-128h128v128h-128zM256 -128v128h-128v-128h128zM1664 0v128h128v1024h-128v128h-1280v-128h-128v-1024h128v-128
+h1280zM1920 -128v128h-128v-128h128zM1280 896h384v-768h-896v256h-384v768h896v-256zM512 512h640v512h-640v-512zM1536 256v512h-256v-384h-384v-128h640z" />
+    <glyph glyph-name="_548" unicode="&#xf248;" horiz-adv-x="2304" 
+d="M2304 768h-128v-640h128v-384h-384v128h-896v-128h-384v384h128v128h-384v-128h-384v384h128v640h-128v384h384v-128h896v128h384v-384h-128v-128h384v128h384v-384zM2048 1024v-128h128v128h-128zM1408 1408v-128h128v128h-128zM128 1408v-128h128v128h-128zM256 256
+v128h-128v-128h128zM1536 384h-128v-128h128v128zM384 384h896v128h128v640h-128v128h-896v-128h-128v-640h128v-128zM896 -128v128h-128v-128h128zM2176 -128v128h-128v-128h128zM2048 128v640h-128v128h-384v-384h128v-384h-384v128h-384v-128h128v-128h896v128h128z" />
+    <glyph glyph-name="_549" unicode="&#xf249;" 
+d="M1024 288v-416h-928q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h1344q40 0 68 -28t28 -68v-928h-416q-40 0 -68 -28t-28 -68zM1152 256h381q-15 -82 -65 -132l-184 -184q-50 -50 -132 -65v381z" />
+    <glyph glyph-name="_550" unicode="&#xf24a;" 
+d="M1400 256h-248v-248q29 10 41 22l185 185q12 12 22 41zM1120 384h288v896h-1280v-1280h896v288q0 40 28 68t68 28zM1536 1312v-1024q0 -40 -20 -88t-48 -76l-184 -184q-28 -28 -76 -48t-88 -20h-1024q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h1344q40 0 68 -28t28 -68
+z" />
+    <glyph glyph-name="_551" unicode="&#xf24b;" horiz-adv-x="2304" 
+d="M1951 538q0 -26 -15.5 -44.5t-38.5 -23.5q-8 -2 -18 -2h-153v140h153q10 0 18 -2q23 -5 38.5 -23.5t15.5 -44.5zM1933 751q0 -25 -15 -42t-38 -21q-3 -1 -15 -1h-139v129h139q3 0 8.5 -0.5t6.5 -0.5q23 -4 38 -21.5t15 -42.5zM728 587v308h-228v-308q0 -58 -38 -94.5
+t-105 -36.5q-108 0 -229 59v-112q53 -15 121 -23t109 -9l42 -1q328 0 328 217zM1442 403v113q-99 -52 -200 -59q-108 -8 -169 41t-61 142t61 142t169 41q101 -7 200 -58v112q-48 12 -100 19.5t-80 9.5l-28 2q-127 6 -218.5 -14t-140.5 -60t-71 -88t-22 -106t22 -106t71 -88
+t140.5 -60t218.5 -14q101 4 208 31zM2176 518q0 54 -43 88.5t-109 39.5v3q57 8 89 41.5t32 79.5q0 55 -41 88t-107 36q-3 0 -12 0.5t-14 0.5h-455v-510h491q74 0 121.5 36.5t47.5 96.5zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90
+t90 38h2048q52 0 90 -38t38 -90z" />
+    <glyph glyph-name="_552" unicode="&#xf24c;" horiz-adv-x="2304" 
+d="M858 295v693q-106 -41 -172 -135.5t-66 -211.5t66 -211.5t172 -134.5zM1362 641q0 117 -66 211.5t-172 135.5v-694q106 41 172 135.5t66 211.5zM1577 641q0 -159 -78.5 -294t-213.5 -213.5t-294 -78.5q-119 0 -227.5 46.5t-187 125t-125 187t-46.5 227.5q0 159 78.5 294
+t213.5 213.5t294 78.5t294 -78.5t213.5 -213.5t78.5 -294zM1960 634q0 139 -55.5 261.5t-147.5 205.5t-213.5 131t-252.5 48h-301q-176 0 -323.5 -81t-235 -230t-87.5 -335q0 -171 87 -317.5t236 -231.5t323 -85h301q129 0 251.5 50.5t214.5 135t147.5 202.5t55.5 246z
+M2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" />
+    <glyph glyph-name="_553" unicode="&#xf24d;" horiz-adv-x="1792" 
+d="M1664 -96v1088q0 13 -9.5 22.5t-22.5 9.5h-1088q-13 0 -22.5 -9.5t-9.5 -22.5v-1088q0 -13 9.5 -22.5t22.5 -9.5h1088q13 0 22.5 9.5t9.5 22.5zM1792 992v-1088q0 -66 -47 -113t-113 -47h-1088q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1088q66 0 113 -47t47 -113
+zM1408 1376v-160h-128v160q0 13 -9.5 22.5t-22.5 9.5h-1088q-13 0 -22.5 -9.5t-9.5 -22.5v-1088q0 -13 9.5 -22.5t22.5 -9.5h160v-128h-160q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1088q66 0 113 -47t47 -113z" />
+    <glyph glyph-name="_554" unicode="&#xf24e;" horiz-adv-x="2304" 
+d="M1728 1088l-384 -704h768zM448 1088l-384 -704h768zM1269 1280q-14 -40 -45.5 -71.5t-71.5 -45.5v-1291h608q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1344q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h608v1291q-40 14 -71.5 45.5t-45.5 71.5h-491q-14 0 -23 9t-9 23v64
+q0 14 9 23t23 9h491q21 57 70 92.5t111 35.5t111 -35.5t70 -92.5h491q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-491zM1088 1264q33 0 56.5 23.5t23.5 56.5t-23.5 56.5t-56.5 23.5t-56.5 -23.5t-23.5 -56.5t23.5 -56.5t56.5 -23.5zM2176 384q0 -73 -46.5 -131t-117.5 -91
+t-144.5 -49.5t-139.5 -16.5t-139.5 16.5t-144.5 49.5t-117.5 91t-46.5 131q0 11 35 81t92 174.5t107 195.5t102 184t56 100q18 33 56 33t56 -33q4 -7 56 -100t102 -184t107 -195.5t92 -174.5t35 -81zM896 384q0 -73 -46.5 -131t-117.5 -91t-144.5 -49.5t-139.5 -16.5
+t-139.5 16.5t-144.5 49.5t-117.5 91t-46.5 131q0 11 35 81t92 174.5t107 195.5t102 184t56 100q18 33 56 33t56 -33q4 -7 56 -100t102 -184t107 -195.5t92 -174.5t35 -81z" />
+    <glyph glyph-name="_555" unicode="&#xf250;" 
+d="M1408 1408q0 -261 -106.5 -461.5t-266.5 -306.5q160 -106 266.5 -306.5t106.5 -461.5h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1472q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96q0 261 106.5 461.5t266.5 306.5q-160 106 -266.5 306.5t-106.5 461.5h-96q-14 0 -23 9
+t-9 23v64q0 14 9 23t23 9h1472q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96zM874 700q77 29 149 92.5t129.5 152.5t92.5 210t35 253h-1024q0 -132 35 -253t92.5 -210t129.5 -152.5t149 -92.5q19 -7 30.5 -23.5t11.5 -36.5t-11.5 -36.5t-30.5 -23.5q-77 -29 -149 -92.5
+t-129.5 -152.5t-92.5 -210t-35 -253h1024q0 132 -35 253t-92.5 210t-129.5 152.5t-149 92.5q-19 7 -30.5 23.5t-11.5 36.5t11.5 36.5t30.5 23.5z" />
+    <glyph glyph-name="_556" unicode="&#xf251;" 
+d="M1408 1408q0 -261 -106.5 -461.5t-266.5 -306.5q160 -106 266.5 -306.5t106.5 -461.5h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1472q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96q0 261 106.5 461.5t266.5 306.5q-160 106 -266.5 306.5t-106.5 461.5h-96q-14 0 -23 9
+t-9 23v64q0 14 9 23t23 9h1472q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96zM1280 1408h-1024q0 -66 9 -128h1006q9 61 9 128zM1280 -128q0 130 -34 249.5t-90.5 208t-126.5 152t-146 94.5h-230q-76 -31 -146 -94.5t-126.5 -152t-90.5 -208t-34 -249.5h1024z" />
+    <glyph glyph-name="_557" unicode="&#xf252;" 
+d="M1408 1408q0 -261 -106.5 -461.5t-266.5 -306.5q160 -106 266.5 -306.5t106.5 -461.5h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1472q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96q0 261 106.5 461.5t266.5 306.5q-160 106 -266.5 306.5t-106.5 461.5h-96q-14 0 -23 9
+t-9 23v64q0 14 9 23t23 9h1472q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96zM1280 1408h-1024q0 -206 85 -384h854q85 178 85 384zM1223 192q-54 141 -145.5 241.5t-194.5 142.5h-230q-103 -42 -194.5 -142.5t-145.5 -241.5h910z" />
+    <glyph glyph-name="_558" unicode="&#xf253;" 
+d="M1408 1408q0 -261 -106.5 -461.5t-266.5 -306.5q160 -106 266.5 -306.5t106.5 -461.5h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1472q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96q0 261 106.5 461.5t266.5 306.5q-160 106 -266.5 306.5t-106.5 461.5h-96q-14 0 -23 9
+t-9 23v64q0 14 9 23t23 9h1472q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96zM874 700q77 29 149 92.5t129.5 152.5t92.5 210t35 253h-1024q0 -132 35 -253t92.5 -210t129.5 -152.5t149 -92.5q19 -7 30.5 -23.5t11.5 -36.5t-11.5 -36.5t-30.5 -23.5q-137 -51 -244 -196
+h700q-107 145 -244 196q-19 7 -30.5 23.5t-11.5 36.5t11.5 36.5t30.5 23.5z" />
+    <glyph glyph-name="_559" unicode="&#xf254;" 
+d="M1504 -64q14 0 23 -9t9 -23v-128q0 -14 -9 -23t-23 -9h-1472q-14 0 -23 9t-9 23v128q0 14 9 23t23 9h1472zM130 0q3 55 16 107t30 95t46 87t53.5 76t64.5 69.5t66 60t70.5 55t66.5 47.5t65 43q-43 28 -65 43t-66.5 47.5t-70.5 55t-66 60t-64.5 69.5t-53.5 76t-46 87
+t-30 95t-16 107h1276q-3 -55 -16 -107t-30 -95t-46 -87t-53.5 -76t-64.5 -69.5t-66 -60t-70.5 -55t-66.5 -47.5t-65 -43q43 -28 65 -43t66.5 -47.5t70.5 -55t66 -60t64.5 -69.5t53.5 -76t46 -87t30 -95t16 -107h-1276zM1504 1536q14 0 23 -9t9 -23v-128q0 -14 -9 -23t-23 -9
+h-1472q-14 0 -23 9t-9 23v128q0 14 9 23t23 9h1472z" />
+    <glyph glyph-name="_560" unicode="&#xf255;" 
+d="M768 1152q-53 0 -90.5 -37.5t-37.5 -90.5v-128h-32v93q0 48 -32 81.5t-80 33.5q-46 0 -79 -33t-33 -79v-429l-32 30v172q0 48 -32 81.5t-80 33.5q-46 0 -79 -33t-33 -79v-224q0 -47 35 -82l310 -296q39 -39 39 -102q0 -26 19 -45t45 -19h640q26 0 45 19t19 45v25
+q0 41 10 77l108 436q10 36 10 77v246q0 48 -32 81.5t-80 33.5q-46 0 -79 -33t-33 -79v-32h-32v125q0 40 -25 72.5t-64 40.5q-14 2 -23 2q-46 0 -79 -33t-33 -79v-128h-32v122q0 51 -32.5 89.5t-82.5 43.5q-5 1 -13 1zM768 1280q84 0 149 -50q57 34 123 34q59 0 111 -27
+t86 -76q27 7 59 7q100 0 170 -71.5t70 -171.5v-246q0 -51 -13 -108l-109 -436q-6 -24 -6 -71q0 -80 -56 -136t-136 -56h-640q-84 0 -138 58.5t-54 142.5l-308 296q-76 73 -76 175v224q0 99 70.5 169.5t169.5 70.5q11 0 16 -1q6 95 75.5 160t164.5 65q52 0 98 -21
+q72 69 174 69z" />
+    <glyph glyph-name="_561" unicode="&#xf256;" horiz-adv-x="1792" 
+d="M880 1408q-46 0 -79 -33t-33 -79v-656h-32v528q0 46 -33 79t-79 33t-79 -33t-33 -79v-528v-256l-154 205q-38 51 -102 51q-53 0 -90.5 -37.5t-37.5 -90.5q0 -43 26 -77l384 -512q38 -51 102 -51h688q34 0 61 22t34 56l76 405q5 32 5 59v498q0 46 -33 79t-79 33t-79 -33
+t-33 -79v-272h-32v528q0 46 -33 79t-79 33t-79 -33t-33 -79v-528h-32v656q0 46 -33 79t-79 33zM880 1536q68 0 125.5 -35.5t88.5 -96.5q19 4 42 4q99 0 169.5 -70.5t70.5 -169.5v-17q105 6 180.5 -64t75.5 -175v-498q0 -40 -8 -83l-76 -404q-14 -79 -76.5 -131t-143.5 -52
+h-688q-60 0 -114.5 27.5t-90.5 74.5l-384 512q-51 68 -51 154q0 106 75 181t181 75q78 0 128 -34v434q0 99 70.5 169.5t169.5 70.5q23 0 42 -4q31 61 88.5 96.5t125.5 35.5z" />
+    <glyph glyph-name="_562" unicode="&#xf257;" horiz-adv-x="1792" 
+d="M1073 -128h-177q-163 0 -226 141q-23 49 -23 102v5q-62 30 -98.5 88.5t-36.5 127.5q0 38 5 48h-261q-106 0 -181 75t-75 181t75 181t181 75h113l-44 17q-74 28 -119.5 93.5t-45.5 145.5q0 106 75 181t181 75q46 0 91 -17l628 -239h401q106 0 181 -75t75 -181v-668
+q0 -88 -54 -157.5t-140 -90.5l-339 -85q-92 -23 -186 -23zM1024 583l-155 -71l-163 -74q-30 -14 -48 -41.5t-18 -60.5q0 -46 33 -79t79 -33q26 0 46 10l338 154q-49 10 -80.5 50t-31.5 90v55zM1344 272q0 46 -33 79t-79 33q-26 0 -46 -10l-290 -132q-28 -13 -37 -17
+t-30.5 -17t-29.5 -23.5t-16 -29t-8 -40.5q0 -50 31.5 -82t81.5 -32q20 0 38 9l352 160q30 14 48 41.5t18 60.5zM1112 1024l-650 248q-24 8 -46 8q-53 0 -90.5 -37.5t-37.5 -90.5q0 -40 22.5 -73t59.5 -47l526 -200v-64h-640q-53 0 -90.5 -37.5t-37.5 -90.5t37.5 -90.5
+t90.5 -37.5h535l233 106v198q0 63 46 106l111 102h-69zM1073 0q82 0 155 19l339 85q43 11 70 45.5t27 78.5v668q0 53 -37.5 90.5t-90.5 37.5h-308l-136 -126q-36 -33 -36 -82v-296q0 -46 33 -77t79 -31t79 35t33 81v208h32v-208q0 -70 -57 -114q52 -8 86.5 -48.5t34.5 -93.5
+q0 -42 -23 -78t-61 -53l-310 -141h91z" />
+    <glyph glyph-name="_563" unicode="&#xf258;" horiz-adv-x="2048" 
+d="M1151 1536q61 0 116 -28t91 -77l572 -781q118 -159 118 -359v-355q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136v177l-286 143h-546q-80 0 -136 56t-56 136v32q0 119 84.5 203.5t203.5 84.5h420l42 128h-686q-100 0 -173.5 67.5t-81.5 166.5q-65 79 -65 182v32
+q0 80 56 136t136 56h959zM1920 -64v355q0 157 -93 284l-573 781q-39 52 -103 52h-959q-26 0 -45 -19t-19 -45q0 -32 1.5 -49.5t9.5 -40.5t25 -43q10 31 35.5 50t56.5 19h832v-32h-832q-26 0 -45 -19t-19 -45q0 -44 3 -58q8 -44 44 -73t81 -29h640h91q40 0 68 -28t28 -68
+q0 -15 -5 -30l-64 -192q-10 -29 -35 -47.5t-56 -18.5h-443q-66 0 -113 -47t-47 -113v-32q0 -26 19 -45t45 -19h561q16 0 29 -7l317 -158q24 -13 38.5 -36t14.5 -50v-197q0 -26 19 -45t45 -19h384q26 0 45 19t19 45z" />
+    <glyph glyph-name="_564" unicode="&#xf259;" horiz-adv-x="2048" 
+d="M459 -256q-77 0 -137.5 47.5t-79.5 122.5l-101 401q-13 57 -13 108q0 45 -5 67l-116 477q-7 27 -7 57q0 93 62 161t155 78q17 85 82.5 139t152.5 54q83 0 148 -51.5t85 -132.5l83 -348l103 428q20 81 85 132.5t148 51.5q89 0 155.5 -57.5t80.5 -144.5q92 -10 152 -79
+t60 -162q0 -24 -7 -59l-123 -512q10 7 37.5 28.5t38.5 29.5t35 23t41 20.5t41.5 11t49.5 5.5q105 0 180 -74t75 -179q0 -62 -28.5 -118t-78.5 -94l-507 -380q-68 -51 -153 -51h-694zM1104 1408q-38 0 -68.5 -24t-39.5 -62l-164 -682h-127l-145 602q-9 38 -39.5 62t-68.5 24
+q-48 0 -80 -33t-32 -80q0 -15 3 -28l132 -547h-26l-99 408q-9 37 -40 62.5t-69 25.5q-47 0 -80 -33t-33 -79q0 -14 3 -26l116 -478q7 -28 9 -86t10 -88l100 -401q8 -32 34 -52.5t59 -20.5h694q42 0 76 26l507 379q56 43 56 110q0 52 -37.5 88.5t-89.5 36.5q-43 0 -77 -26
+l-307 -230v227q0 4 32 138t68 282t39 161q4 18 4 29q0 47 -32 81t-79 34q-39 0 -69.5 -24t-39.5 -62l-116 -482h-26l150 624q3 14 3 28q0 48 -31.5 82t-79.5 34z" />
+    <glyph glyph-name="_565" unicode="&#xf25a;" horiz-adv-x="1792" 
+d="M640 1408q-53 0 -90.5 -37.5t-37.5 -90.5v-512v-384l-151 202q-41 54 -107 54q-52 0 -89 -38t-37 -90q0 -43 26 -77l384 -512q38 -51 102 -51h718q22 0 39.5 13.5t22.5 34.5l92 368q24 96 24 194v217q0 41 -28 71t-68 30t-68 -28t-28 -68h-32v61q0 48 -32 81.5t-80 33.5
+q-46 0 -79 -33t-33 -79v-64h-32v90q0 55 -37 94.5t-91 39.5q-53 0 -90.5 -37.5t-37.5 -90.5v-96h-32v570q0 55 -37 94.5t-91 39.5zM640 1536q107 0 181.5 -77.5t74.5 -184.5v-220q22 2 32 2q99 0 173 -69q47 21 99 21q113 0 184 -87q27 7 56 7q94 0 159 -67.5t65 -161.5
+v-217q0 -116 -28 -225l-92 -368q-16 -64 -68 -104.5t-118 -40.5h-718q-60 0 -114.5 27.5t-90.5 74.5l-384 512q-51 68 -51 154q0 105 74.5 180.5t179.5 75.5q71 0 130 -35v547q0 106 75 181t181 75zM768 128v384h-32v-384h32zM1024 128v384h-32v-384h32zM1280 128v384h-32
+v-384h32z" />
+    <glyph glyph-name="_566" unicode="&#xf25b;" 
+d="M1288 889q60 0 107 -23q141 -63 141 -226v-177q0 -94 -23 -186l-85 -339q-21 -86 -90.5 -140t-157.5 -54h-668q-106 0 -181 75t-75 181v401l-239 628q-17 45 -17 91q0 106 75 181t181 75q80 0 145.5 -45.5t93.5 -119.5l17 -44v113q0 106 75 181t181 75t181 -75t75 -181
+v-261q27 5 48 5q69 0 127.5 -36.5t88.5 -98.5zM1072 896q-33 0 -60.5 -18t-41.5 -48l-74 -163l-71 -155h55q50 0 90 -31.5t50 -80.5l154 338q10 20 10 46q0 46 -33 79t-79 33zM1293 761q-22 0 -40.5 -8t-29 -16t-23.5 -29.5t-17 -30.5t-17 -37l-132 -290q-10 -20 -10 -46
+q0 -46 33 -79t79 -33q33 0 60.5 18t41.5 48l160 352q9 18 9 38q0 50 -32 81.5t-82 31.5zM128 1120q0 -22 8 -46l248 -650v-69l102 111q43 46 106 46h198l106 233v535q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5v-640h-64l-200 526q-14 37 -47 59.5t-73 22.5
+q-53 0 -90.5 -37.5t-37.5 -90.5zM1180 -128q44 0 78.5 27t45.5 70l85 339q19 73 19 155v91l-141 -310q-17 -38 -53 -61t-78 -23q-53 0 -93.5 34.5t-48.5 86.5q-44 -57 -114 -57h-208v32h208q46 0 81 33t35 79t-31 79t-77 33h-296q-49 0 -82 -36l-126 -136v-308
+q0 -53 37.5 -90.5t90.5 -37.5h668z" />
+    <glyph glyph-name="_567" unicode="&#xf25c;" horiz-adv-x="1973" 
+d="M857 992v-117q0 -13 -9.5 -22t-22.5 -9h-298v-812q0 -13 -9 -22.5t-22 -9.5h-135q-13 0 -22.5 9t-9.5 23v812h-297q-13 0 -22.5 9t-9.5 22v117q0 14 9 23t23 9h793q13 0 22.5 -9.5t9.5 -22.5zM1895 995l77 -961q1 -13 -8 -24q-10 -10 -23 -10h-134q-12 0 -21 8.5
+t-10 20.5l-46 588l-189 -425q-8 -19 -29 -19h-120q-20 0 -29 19l-188 427l-45 -590q-1 -12 -10 -20.5t-21 -8.5h-135q-13 0 -23 10q-9 10 -9 24l78 961q1 12 10 20.5t21 8.5h142q20 0 29 -19l220 -520q10 -24 20 -51q3 7 9.5 24.5t10.5 26.5l221 520q9 19 29 19h141
+q13 0 22 -8.5t10 -20.5z" />
+    <glyph glyph-name="_568" unicode="&#xf25d;" horiz-adv-x="1792" 
+d="M1042 833q0 88 -60 121q-33 18 -117 18h-123v-281h162q66 0 102 37t36 105zM1094 548l205 -373q8 -17 -1 -31q-8 -16 -27 -16h-152q-20 0 -28 17l-194 365h-155v-350q0 -14 -9 -23t-23 -9h-134q-14 0 -23 9t-9 23v960q0 14 9 23t23 9h294q128 0 190 -24q85 -31 134 -109
+t49 -180q0 -92 -42.5 -165.5t-115.5 -109.5q6 -10 9 -16zM896 1376q-150 0 -286 -58.5t-234.5 -157t-157 -234.5t-58.5 -286t58.5 -286t157 -234.5t234.5 -157t286 -58.5t286 58.5t234.5 157t157 234.5t58.5 286t-58.5 286t-157 234.5t-234.5 157t-286 58.5zM1792 640
+q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
+    <glyph glyph-name="_569" unicode="&#xf25e;" horiz-adv-x="1792" 
+d="M605 303q153 0 257 104q14 18 3 36l-45 82q-6 13 -24 17q-16 2 -27 -11l-4 -3q-4 -4 -11.5 -10t-17.5 -13.5t-23.5 -14.5t-28.5 -13t-33.5 -9.5t-37.5 -3.5q-76 0 -125 50t-49 127q0 76 48 125.5t122 49.5q37 0 71.5 -14t50.5 -28l16 -14q11 -11 26 -10q16 2 24 14l53 78
+q13 20 -2 39q-3 4 -11 12t-30 23.5t-48.5 28t-67.5 22.5t-86 10q-148 0 -246 -96.5t-98 -240.5q0 -146 97 -241.5t247 -95.5zM1235 303q153 0 257 104q14 18 4 36l-45 82q-8 14 -25 17q-16 2 -27 -11l-4 -3q-4 -4 -11.5 -10t-17.5 -13.5t-23.5 -14.5t-28.5 -13t-33.5 -9.5
+t-37.5 -3.5q-76 0 -125 50t-49 127q0 76 48 125.5t122 49.5q37 0 71.5 -14t50.5 -28l16 -14q11 -11 26 -10q16 2 24 14l53 78q13 20 -2 39q-3 4 -11 12t-30 23.5t-48.5 28t-67.5 22.5t-86 10q-147 0 -245.5 -96.5t-98.5 -240.5q0 -146 97 -241.5t247 -95.5zM896 1376
+q-150 0 -286 -58.5t-234.5 -157t-157 -234.5t-58.5 -286t58.5 -286t157 -234.5t234.5 -157t286 -58.5t286 58.5t234.5 157t157 234.5t58.5 286t-58.5 286t-157 234.5t-234.5 157t-286 58.5zM896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348t-191 -286t-286 -191
+t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71z" />
+    <glyph glyph-name="f260" unicode="&#xf260;" horiz-adv-x="2048" 
+d="M736 736l384 -384l-384 -384l-672 672l672 672l168 -168l-96 -96l-72 72l-480 -480l480 -480l193 193l-289 287zM1312 1312l672 -672l-672 -672l-168 168l96 96l72 -72l480 480l-480 480l-193 -193l289 -287l-96 -96l-384 384z" />
+    <glyph glyph-name="f261" unicode="&#xf261;" horiz-adv-x="1792" 
+d="M717 182l271 271l-279 279l-88 -88l192 -191l-96 -96l-279 279l279 279l40 -40l87 87l-127 128l-454 -454zM1075 190l454 454l-454 454l-271 -271l279 -279l88 88l-192 191l96 96l279 -279l-279 -279l-40 40l-87 -88zM1792 640q0 -182 -71 -348t-191 -286t-286 -191
+t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
+    <glyph glyph-name="_572" unicode="&#xf262;" horiz-adv-x="2304" 
+d="M651 539q0 -39 -27.5 -66.5t-65.5 -27.5q-39 0 -66.5 27.5t-27.5 66.5q0 38 27.5 65.5t66.5 27.5q38 0 65.5 -27.5t27.5 -65.5zM1805 540q0 -39 -27.5 -66.5t-66.5 -27.5t-66.5 27.5t-27.5 66.5t27.5 66t66.5 27t66.5 -27t27.5 -66zM765 539q0 79 -56.5 136t-136.5 57
+t-136.5 -56.5t-56.5 -136.5t56.5 -136.5t136.5 -56.5t136.5 56.5t56.5 136.5zM1918 540q0 80 -56.5 136.5t-136.5 56.5q-79 0 -136 -56.5t-57 -136.5t56.5 -136.5t136.5 -56.5t136.5 56.5t56.5 136.5zM850 539q0 -116 -81.5 -197.5t-196.5 -81.5q-116 0 -197.5 82t-81.5 197
+t82 196.5t197 81.5t196.5 -81.5t81.5 -196.5zM2004 540q0 -115 -81.5 -196.5t-197.5 -81.5q-115 0 -196.5 81.5t-81.5 196.5t81.5 196.5t196.5 81.5q116 0 197.5 -81.5t81.5 -196.5zM1040 537q0 191 -135.5 326.5t-326.5 135.5q-125 0 -231 -62t-168 -168.5t-62 -231.5
+t62 -231.5t168 -168.5t231 -62q191 0 326.5 135.5t135.5 326.5zM1708 1110q-254 111 -556 111q-319 0 -573 -110q117 0 223 -45.5t182.5 -122.5t122 -183t45.5 -223q0 115 43.5 219.5t118 180.5t177.5 123t217 50zM2187 537q0 191 -135 326.5t-326 135.5t-326.5 -135.5
+t-135.5 -326.5t135.5 -326.5t326.5 -135.5t326 135.5t135 326.5zM1921 1103h383q-44 -51 -75 -114.5t-40 -114.5q110 -151 110 -337q0 -156 -77 -288t-209 -208.5t-287 -76.5q-133 0 -249 56t-196 155q-47 -56 -129 -179q-11 22 -53.5 82.5t-74.5 97.5
+q-80 -99 -196.5 -155.5t-249.5 -56.5q-155 0 -287 76.5t-209 208.5t-77 288q0 186 110 337q-9 51 -40 114.5t-75 114.5h365q149 100 355 156.5t432 56.5q224 0 421 -56t348 -157z" />
+    <glyph glyph-name="f263" unicode="&#xf263;" horiz-adv-x="1280" 
+d="M640 629q-188 0 -321 133t-133 320q0 188 133 321t321 133t321 -133t133 -321q0 -187 -133 -320t-321 -133zM640 1306q-92 0 -157.5 -65.5t-65.5 -158.5q0 -92 65.5 -157.5t157.5 -65.5t157.5 65.5t65.5 157.5q0 93 -65.5 158.5t-157.5 65.5zM1163 574q13 -27 15 -49.5
+t-4.5 -40.5t-26.5 -38.5t-42.5 -37t-61.5 -41.5q-115 -73 -315 -94l73 -72l267 -267q30 -31 30 -74t-30 -73l-12 -13q-31 -30 -74 -30t-74 30q-67 68 -267 268l-267 -268q-31 -30 -74 -30t-73 30l-12 13q-31 30 -31 73t31 74l267 267l72 72q-203 21 -317 94
+q-39 25 -61.5 41.5t-42.5 37t-26.5 38.5t-4.5 40.5t15 49.5q10 20 28 35t42 22t56 -2t65 -35q5 -4 15 -11t43 -24.5t69 -30.5t92 -24t113 -11q91 0 174 25.5t120 50.5l38 25q33 26 65 35t56 2t42 -22t28 -35z" />
+    <glyph glyph-name="_574" unicode="&#xf264;" 
+d="M927 956q0 -66 -46.5 -112.5t-112.5 -46.5t-112.5 46.5t-46.5 112.5t46.5 112.5t112.5 46.5t112.5 -46.5t46.5 -112.5zM1141 593q-10 20 -28 32t-47.5 9.5t-60.5 -27.5q-10 -8 -29 -20t-81 -32t-127 -20t-124 18t-86 36l-27 18q-31 25 -60.5 27.5t-47.5 -9.5t-28 -32
+q-22 -45 -2 -74.5t87 -73.5q83 -53 226 -67l-51 -52q-142 -142 -191 -190q-22 -22 -22 -52.5t22 -52.5l9 -9q22 -22 52.5 -22t52.5 22l191 191q114 -115 191 -191q22 -22 52.5 -22t52.5 22l9 9q22 22 22 52.5t-22 52.5l-191 190l-52 52q141 14 225 67q67 44 87 73.5t-2 74.5
+zM1092 956q0 134 -95 229t-229 95t-229 -95t-95 -229t95 -229t229 -95t229 95t95 229zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="_575" unicode="&#xf265;" horiz-adv-x="1720" 
+d="M1565 1408q65 0 110 -45.5t45 -110.5v-519q0 -176 -68 -336t-182.5 -275t-274 -182.5t-334.5 -67.5q-176 0 -335.5 67.5t-274.5 182.5t-183 275t-68 336v519q0 64 46 110t110 46h1409zM861 344q47 0 82 33l404 388q37 35 37 85q0 49 -34.5 83.5t-83.5 34.5q-47 0 -82 -33
+l-323 -310l-323 310q-35 33 -81 33q-49 0 -83.5 -34.5t-34.5 -83.5q0 -51 36 -85l405 -388q33 -33 81 -33z" />
+    <glyph glyph-name="_576" unicode="&#xf266;" horiz-adv-x="2304" 
+d="M1494 -103l-295 695q-25 -49 -158.5 -305.5t-198.5 -389.5q-1 -1 -27.5 -0.5t-26.5 1.5q-82 193 -255.5 587t-259.5 596q-21 50 -66.5 107.5t-103.5 100.5t-102 43q0 5 -0.5 24t-0.5 27h583v-50q-39 -2 -79.5 -16t-66.5 -43t-10 -64q26 -59 216.5 -499t235.5 -540
+q31 61 140 266.5t131 247.5q-19 39 -126 281t-136 295q-38 69 -201 71v50l513 -1v-47q-60 -2 -93.5 -25t-12.5 -69q33 -70 87 -189.5t86 -187.5q110 214 173 363q24 55 -10 79.5t-129 26.5q1 7 1 25v24q64 0 170.5 0.5t180 1t92.5 0.5v-49q-62 -2 -119 -33t-90 -81
+l-213 -442q13 -33 127.5 -290t121.5 -274l441 1017q-14 38 -49.5 62.5t-65 31.5t-55.5 8v50l460 -4l1 -2l-1 -44q-139 -4 -201 -145q-526 -1216 -559 -1291h-49z" />
+    <glyph glyph-name="_577" unicode="&#xf267;" horiz-adv-x="1792" 
+d="M949 643q0 -26 -16.5 -45t-41.5 -19q-26 0 -45 16.5t-19 41.5q0 26 17 45t42 19t44 -16.5t19 -41.5zM964 585l350 581q-9 -8 -67.5 -62.5t-125.5 -116.5t-136.5 -127t-117 -110.5t-50.5 -51.5l-349 -580q7 7 67 62t126 116.5t136 127t117 111t50 50.5zM1611 640
+q0 -201 -104 -371q-3 2 -17 11t-26.5 16.5t-16.5 7.5q-13 0 -13 -13q0 -10 59 -44q-74 -112 -184.5 -190.5t-241.5 -110.5l-16 67q-1 10 -15 10q-5 0 -8 -5.5t-2 -9.5l16 -68q-72 -15 -146 -15q-199 0 -372 105q1 2 13 20.5t21.5 33.5t9.5 19q0 13 -13 13q-6 0 -17 -14.5
+t-22.5 -34.5t-13.5 -23q-113 75 -192 187.5t-110 244.5l69 15q10 3 10 15q0 5 -5.5 8t-10.5 2l-68 -15q-14 72 -14 139q0 206 109 379q2 -1 18.5 -12t30 -19t17.5 -8q13 0 13 12q0 6 -12.5 15.5t-32.5 21.5l-20 12q77 112 189 189t244 107l15 -67q2 -10 15 -10q5 0 8 5.5
+t2 10.5l-15 66q71 13 134 13q204 0 379 -109q-39 -56 -39 -65q0 -13 12 -13q11 0 48 64q111 -75 187.5 -186t107.5 -241l-56 -12q-10 -2 -10 -16q0 -5 5.5 -8t9.5 -2l57 13q14 -72 14 -140zM1696 640q0 163 -63.5 311t-170.5 255t-255 170.5t-311 63.5t-311 -63.5
+t-255 -170.5t-170.5 -255t-63.5 -311t63.5 -311t170.5 -255t255 -170.5t311 -63.5t311 63.5t255 170.5t170.5 255t63.5 311zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191
+t191 -286t71 -348z" />
+    <glyph glyph-name="_578" unicode="&#xf268;" horiz-adv-x="1792" 
+d="M893 1536q240 2 451 -120q232 -134 352 -372l-742 39q-160 9 -294 -74.5t-185 -229.5l-276 424q128 159 311 245.5t383 87.5zM146 1131l337 -663q72 -143 211 -217t293 -45l-230 -451q-212 33 -385 157.5t-272.5 316t-99.5 411.5q0 267 146 491zM1732 962
+q58 -150 59.5 -310.5t-48.5 -306t-153 -272t-246 -209.5q-230 -133 -498 -119l405 623q88 131 82.5 290.5t-106.5 277.5zM896 942q125 0 213.5 -88.5t88.5 -213.5t-88.5 -213.5t-213.5 -88.5t-213.5 88.5t-88.5 213.5t88.5 213.5t213.5 88.5z" />
+    <glyph glyph-name="_579" unicode="&#xf269;" horiz-adv-x="1792" 
+d="M903 -256q-283 0 -504.5 150.5t-329.5 398.5q-58 131 -67 301t26 332.5t111 312t179 242.5l-11 -281q11 14 68 15.5t70 -15.5q42 81 160.5 138t234.5 59q-54 -45 -119.5 -148.5t-58.5 -163.5q25 -8 62.5 -13.5t63 -7.5t68 -4t50.5 -3q15 -5 9.5 -45.5t-30.5 -75.5
+q-5 -7 -16.5 -18.5t-56.5 -35.5t-101 -34l15 -189l-139 67q-18 -43 -7.5 -81.5t36 -66.5t65.5 -41.5t81 -6.5q51 9 98 34.5t83.5 45t73.5 17.5q61 -4 89.5 -33t19.5 -65q-1 -2 -2.5 -5.5t-8.5 -12.5t-18 -15.5t-31.5 -10.5t-46.5 -1q-60 -95 -144.5 -135.5t-209.5 -29.5
+q74 -61 162.5 -82.5t168.5 -6t154.5 52t128 87.5t80.5 104q43 91 39 192.5t-37.5 188.5t-78.5 125q87 -38 137 -79.5t77 -112.5q15 170 -57.5 343t-209.5 284q265 -77 412 -279.5t151 -517.5q2 -127 -40.5 -255t-123.5 -238t-189 -196t-247.5 -135.5t-288.5 -49.5z" />
+    <glyph glyph-name="_580" unicode="&#xf26a;" horiz-adv-x="1792" 
+d="M1493 1308q-165 110 -359 110q-155 0 -293 -73t-240 -200q-75 -93 -119.5 -218t-48.5 -266v-42q4 -141 48.5 -266t119.5 -218q102 -127 240 -200t293 -73q194 0 359 110q-121 -108 -274.5 -168t-322.5 -60q-29 0 -43 1q-175 8 -333 82t-272 193t-181 281t-67 339
+q0 182 71 348t191 286t286 191t348 71h3q168 -1 320.5 -60.5t273.5 -167.5zM1792 640q0 -192 -77 -362.5t-213 -296.5q-104 -63 -222 -63q-137 0 -255 84q154 56 253.5 233t99.5 405q0 227 -99 404t-253 234q119 83 254 83q119 0 226 -65q135 -125 210.5 -295t75.5 -361z
+" />
+    <glyph glyph-name="_581" unicode="&#xf26b;" horiz-adv-x="1792" 
+d="M1792 599q0 -56 -7 -104h-1151q0 -146 109.5 -244.5t257.5 -98.5q99 0 185.5 46.5t136.5 130.5h423q-56 -159 -170.5 -281t-267.5 -188.5t-321 -66.5q-187 0 -356 83q-228 -116 -394 -116q-237 0 -237 263q0 115 45 275q17 60 109 229q199 360 475 606
+q-184 -79 -427 -354q63 274 283.5 449.5t501.5 175.5q30 0 45 -1q255 117 433 117q64 0 116 -13t94.5 -40.5t66.5 -76.5t24 -115q0 -116 -75 -286q101 -182 101 -390zM1722 1239q0 83 -53 132t-137 49q-108 0 -254 -70q121 -47 222.5 -131.5t170.5 -195.5q51 135 51 216z
+M128 2q0 -86 48.5 -132.5t134.5 -46.5q115 0 266 83q-122 72 -213.5 183t-137.5 245q-98 -205 -98 -332zM632 715h728q-5 142 -113 237t-251 95q-144 0 -251.5 -95t-112.5 -237z" />
+    <glyph glyph-name="_582" unicode="&#xf26c;" horiz-adv-x="2048" 
+d="M1792 288v960q0 13 -9.5 22.5t-22.5 9.5h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5zM1920 1248v-960q0 -66 -47 -113t-113 -47h-736v-128h352q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23
+v64q0 14 9 23t23 9h352v128h-736q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
+    <glyph glyph-name="_583" unicode="&#xf26d;" horiz-adv-x="1792" 
+d="M138 1408h197q-70 -64 -126 -149q-36 -56 -59 -115t-30 -125.5t-8.5 -120t10.5 -132t21 -126t28 -136.5q4 -19 6 -28q51 -238 81 -329q57 -171 152 -275h-272q-48 0 -82 34t-34 82v1304q0 48 34 82t82 34zM1346 1408h308q48 0 82 -34t34 -82v-1304q0 -48 -34 -82t-82 -34
+h-178q212 210 196 565l-469 -101q-2 -45 -12 -82t-31 -72t-59.5 -59.5t-93.5 -36.5q-123 -26 -199 40q-32 27 -53 61t-51.5 129t-64.5 258q-35 163 -45.5 263t-5.5 139t23 77q20 41 62.5 73t102.5 45q45 12 83.5 6.5t67 -17t54 -35t43 -48t34.5 -56.5l468 100
+q-68 175 -180 287z" />
+    <glyph glyph-name="_584" unicode="&#xf26e;" 
+d="M1401 -11l-6 -6q-113 -113 -259 -175q-154 -64 -317 -64q-165 0 -317 64q-148 63 -259 175q-113 112 -175 258q-42 103 -54 189q-4 28 48 36q51 8 56 -20q1 -1 1 -4q18 -90 46 -159q50 -124 152 -226q98 -98 226 -152q132 -56 276 -56q143 0 276 56q128 55 225 152l6 6
+q10 10 25 6q12 -3 33 -22q36 -37 17 -58zM929 604l-66 -66l63 -63q21 -21 -7 -49q-17 -17 -32 -17q-10 0 -19 10l-62 61l-66 -66q-5 -5 -15 -5q-15 0 -31 16l-2 2q-18 15 -18 29q0 7 8 17l66 65l-66 66q-16 16 14 45q18 18 31 18q6 0 13 -5l65 -66l65 65q18 17 48 -13
+q27 -27 11 -44zM1400 547q0 -118 -46 -228q-45 -105 -126 -186q-80 -80 -187 -126t-228 -46t-228 46t-187 126q-82 82 -125 186q-15 33 -15 40h-1q-9 27 43 44q50 16 60 -12q37 -99 97 -167h1v339v2q3 136 102 232q105 103 253 103q147 0 251 -103t104 -249
+q0 -147 -104.5 -251t-250.5 -104q-58 0 -112 16q-28 11 -13 61q16 51 44 43l14 -3q14 -3 33 -6t30 -3q104 0 176 71.5t72 174.5q0 101 -72 171q-71 71 -175 71q-107 0 -178 -80q-64 -72 -64 -160v-413q110 -67 242 -67q96 0 185 36.5t156 103.5t103.5 155t36.5 183
+q0 198 -141 339q-140 140 -339 140q-200 0 -340 -140q-53 -53 -77 -87l-2 -2q-8 -11 -13 -15.5t-21.5 -9.5t-38.5 3q-21 5 -36.5 16.5t-15.5 26.5v680q0 15 10.5 26.5t27.5 11.5h877q30 0 30 -55t-30 -55h-811v-483h1q40 42 102 84t108 61q109 46 231 46q121 0 228 -46
+t187 -126q81 -81 126 -186q46 -112 46 -229zM1369 1128q9 -8 9 -18t-5.5 -18t-16.5 -21q-26 -26 -39 -26q-9 0 -16 7q-106 91 -207 133q-128 56 -276 56q-133 0 -262 -49q-27 -10 -45 37q-9 25 -8 38q3 16 16 20q130 57 299 57q164 0 316 -64q137 -58 235 -152z" />
+    <glyph glyph-name="_585" unicode="&#xf270;" horiz-adv-x="1792" 
+d="M1551 60q15 6 26 3t11 -17.5t-15 -33.5q-13 -16 -44 -43.5t-95.5 -68t-141 -74t-188 -58t-229.5 -24.5q-119 0 -238 31t-209 76.5t-172.5 104t-132.5 105t-84 87.5q-8 9 -10 16.5t1 12t8 7t11.5 2t11.5 -4.5q192 -117 300 -166q389 -176 799 -90q190 40 391 135z
+M1758 175q11 -16 2.5 -69.5t-28.5 -102.5q-34 -83 -85 -124q-17 -14 -26 -9t0 24q21 45 44.5 121.5t6.5 98.5q-5 7 -15.5 11.5t-27 6t-29.5 2.5t-35 0t-31.5 -2t-31 -3t-22.5 -2q-6 -1 -13 -1.5t-11 -1t-8.5 -1t-7 -0.5h-5.5h-4.5t-3 0.5t-2 1.5l-1.5 3q-6 16 47 40t103 30
+q46 7 108 1t76 -24zM1364 618q0 -31 13.5 -64t32 -58t37.5 -46t33 -32l13 -11l-227 -224q-40 37 -79 75.5t-58 58.5l-19 20q-11 11 -25 33q-38 -59 -97.5 -102.5t-127.5 -63.5t-140 -23t-137.5 21t-117.5 65.5t-83 113t-31 162.5q0 84 28 154t72 116.5t106.5 83t122.5 57
+t130 34.5t119.5 18.5t99.5 6.5v127q0 65 -21 97q-34 53 -121 53q-6 0 -16.5 -1t-40.5 -12t-56 -29.5t-56 -59.5t-48 -96l-294 27q0 60 22 119t67 113t108 95t151.5 65.5t190.5 24.5q100 0 181 -25t129.5 -61.5t81 -83t45 -86t12.5 -73.5v-589zM692 597q0 -86 70 -133
+q66 -44 139 -22q84 25 114 123q14 45 14 101v162q-59 -2 -111 -12t-106.5 -33.5t-87 -71t-32.5 -114.5z" />
+    <glyph glyph-name="_586" unicode="&#xf271;" horiz-adv-x="1792" 
+d="M1536 1280q52 0 90 -38t38 -90v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h128zM1152 1376v-288q0 -14 9 -23t23 -9
+h64q14 0 23 9t9 23v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM384 1376v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM1536 -128v1024h-1408v-1024h1408zM896 448h224q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-224
+v-224q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v224h-224q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h224v224q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-224z" />
+    <glyph glyph-name="_587" unicode="&#xf272;" horiz-adv-x="1792" 
+d="M1152 416v-64q0 -14 -9 -23t-23 -9h-576q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h576q14 0 23 -9t9 -23zM128 -128h1408v1024h-1408v-1024zM512 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1280 1088v288q0 14 -9 23
+t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1664 1152v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47
+t47 -113v-96h128q52 0 90 -38t38 -90z" />
+    <glyph glyph-name="_588" unicode="&#xf273;" horiz-adv-x="1792" 
+d="M1111 151l-46 -46q-9 -9 -22 -9t-23 9l-188 189l-188 -189q-10 -9 -23 -9t-22 9l-46 46q-9 9 -9 22t9 23l189 188l-189 188q-9 10 -9 23t9 22l46 46q9 9 22 9t23 -9l188 -188l188 188q10 9 23 9t22 -9l46 -46q9 -9 9 -22t-9 -23l-188 -188l188 -188q9 -10 9 -23t-9 -22z
+M128 -128h1408v1024h-1408v-1024zM512 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1280 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1664 1152v-1280
+q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" />
+    <glyph glyph-name="_589" unicode="&#xf274;" horiz-adv-x="1792" 
+d="M1303 572l-512 -512q-10 -9 -23 -9t-23 9l-288 288q-9 10 -9 23t9 22l46 46q9 9 22 9t23 -9l220 -220l444 444q10 9 23 9t22 -9l46 -46q9 -9 9 -22t-9 -23zM128 -128h1408v1024h-1408v-1024zM512 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23
+t23 -9h64q14 0 23 9t9 23zM1280 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1664 1152v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47
+t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" />
+    <glyph glyph-name="_590" unicode="&#xf275;" horiz-adv-x="1792" 
+d="M448 1536q26 0 45 -19t19 -45v-891l536 429q17 14 40 14q26 0 45 -19t19 -45v-379l536 429q17 14 40 14q26 0 45 -19t19 -45v-1152q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v1664q0 26 19 45t45 19h384z" />
+    <glyph glyph-name="_591" unicode="&#xf276;" horiz-adv-x="1024" 
+d="M512 448q66 0 128 15v-655q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v655q62 -15 128 -15zM512 1536q212 0 362 -150t150 -362t-150 -362t-362 -150t-362 150t-150 362t150 362t362 150zM512 1312q14 0 23 9t9 23t-9 23t-23 9q-146 0 -249 -103t-103 -249
+q0 -14 9 -23t23 -9t23 9t9 23q0 119 84.5 203.5t203.5 84.5z" />
+    <glyph glyph-name="_592" unicode="&#xf277;" horiz-adv-x="1792" 
+d="M1745 1239q10 -10 10 -23t-10 -23l-141 -141q-28 -28 -68 -28h-1344q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h576v64q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-64h512q40 0 68 -28zM768 320h256v-512q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v512zM1600 768
+q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19h-1344q-40 0 -68 28l-141 141q-10 10 -10 23t10 23l141 141q28 28 68 28h512v192h256v-192h576z" />
+    <glyph glyph-name="_593" unicode="&#xf278;" horiz-adv-x="2048" 
+d="M2020 1525q28 -20 28 -53v-1408q0 -20 -11 -36t-29 -23l-640 -256q-24 -11 -48 0l-616 246l-616 -246q-10 -5 -24 -5q-19 0 -36 11q-28 20 -28 53v1408q0 20 11 36t29 23l640 256q24 11 48 0l616 -246l616 246q32 13 60 -6zM736 1390v-1270l576 -230v1270zM128 1173
+v-1270l544 217v1270zM1920 107v1270l-544 -217v-1270z" />
+    <glyph glyph-name="_594" unicode="&#xf279;" horiz-adv-x="1792" 
+d="M512 1536q13 0 22.5 -9.5t9.5 -22.5v-1472q0 -20 -17 -28l-480 -256q-7 -4 -15 -4q-13 0 -22.5 9.5t-9.5 22.5v1472q0 20 17 28l480 256q7 4 15 4zM1760 1536q13 0 22.5 -9.5t9.5 -22.5v-1472q0 -20 -17 -28l-480 -256q-7 -4 -15 -4q-13 0 -22.5 9.5t-9.5 22.5v1472
+q0 20 17 28l480 256q7 4 15 4zM640 1536q8 0 14 -3l512 -256q18 -10 18 -29v-1472q0 -13 -9.5 -22.5t-22.5 -9.5q-8 0 -14 3l-512 256q-18 10 -18 29v1472q0 13 9.5 22.5t22.5 9.5z" />
+    <glyph glyph-name="_595" unicode="&#xf27a;" horiz-adv-x="1792" 
+d="M640 640q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1024 640q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1408 640q0 53 -37.5 90.5t-90.5 37.5
+t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1792 640q0 -174 -120 -321.5t-326 -233t-450 -85.5q-110 0 -211 18q-173 -173 -435 -229q-52 -10 -86 -13q-12 -1 -22 6t-13 18q-4 15 20 37q5 5 23.5 21.5t25.5 23.5t23.5 25.5t24 31.5t20.5 37
+t20 48t14.5 57.5t12.5 72.5q-146 90 -229.5 216.5t-83.5 269.5q0 174 120 321.5t326 233t450 85.5t450 -85.5t326 -233t120 -321.5z" />
+    <glyph glyph-name="_596" unicode="&#xf27b;" horiz-adv-x="1792" 
+d="M640 640q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1024 640q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 -53 -37.5 -90.5t-90.5 -37.5
+t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM896 1152q-204 0 -381.5 -69.5t-282 -187.5t-104.5 -255q0 -112 71.5 -213.5t201.5 -175.5l87 -50l-27 -96q-24 -91 -70 -172q152 63 275 171l43 38l57 -6q69 -8 130 -8q204 0 381.5 69.5t282 187.5
+t104.5 255t-104.5 255t-282 187.5t-381.5 69.5zM1792 640q0 -174 -120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22h-5q-15 0 -27 10.5t-16 27.5v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5t34.5 38t31 39.5t32.5 51
+t27 59t26 76q-157 89 -247.5 220t-90.5 281q0 130 71 248.5t191 204.5t286 136.5t348 50.5t348 -50.5t286 -136.5t191 -204.5t71 -248.5z" />
+    <glyph glyph-name="_597" unicode="&#xf27c;" horiz-adv-x="1024" 
+d="M512 345l512 295v-591l-512 -296v592zM0 640v-591l512 296zM512 1527v-591l-512 -296v591zM512 936l512 295v-591z" />
+    <glyph glyph-name="_598" unicode="&#xf27d;" horiz-adv-x="1792" 
+d="M1709 1018q-10 -236 -332 -651q-333 -431 -562 -431q-142 0 -240 263q-44 160 -132 482q-72 262 -157 262q-18 0 -127 -76l-77 98q24 21 108 96.5t130 115.5q156 138 241 146q95 9 153 -55.5t81 -203.5q44 -287 66 -373q55 -249 120 -249q51 0 154 161q101 161 109 246
+q13 139 -109 139q-57 0 -121 -26q120 393 459 382q251 -8 236 -326z" />
+    <glyph glyph-name="f27e" unicode="&#xf27e;" 
+d="M0 1408h1536v-1536h-1536v1536zM1085 293l-221 631l221 297h-634l221 -297l-221 -631l317 -304z" />
+    <glyph glyph-name="uniF280" unicode="&#xf280;" 
+d="M0 1408h1536v-1536h-1536v1536zM908 1088l-12 -33l75 -83l-31 -114l25 -25l107 57l107 -57l25 25l-31 114l75 83l-12 33h-95l-53 96h-32l-53 -96h-95zM641 925q32 0 44.5 -16t11.5 -63l174 21q0 55 -17.5 92.5t-50.5 56t-69 25.5t-85 7q-133 0 -199 -57.5t-66 -182.5v-72
+h-96v-128h76q20 0 20 -8v-382q0 -14 -5 -20t-18 -7l-73 -7v-88h448v86l-149 14q-6 1 -8.5 1.5t-3.5 2.5t-0.5 4t1 7t0.5 10v387h191l38 128h-231q-6 0 -2 6t4 9v80q0 27 1.5 40.5t7.5 28t19.5 20t36.5 5.5zM1248 96v86l-54 9q-7 1 -9.5 2.5t-2.5 3t1 7.5t1 12v520h-275
+l-23 -101l83 -22q23 -7 23 -27v-370q0 -14 -6 -18.5t-20 -6.5l-70 -9v-86h352z" />
+    <glyph glyph-name="uniF281" unicode="&#xf281;" horiz-adv-x="1792" 
+d="M1792 690q0 -58 -29.5 -105.5t-79.5 -72.5q12 -46 12 -96q0 -155 -106.5 -287t-290.5 -208.5t-400 -76.5t-399.5 76.5t-290 208.5t-106.5 287q0 47 11 94q-51 25 -82 73.5t-31 106.5q0 82 58 140.5t141 58.5q85 0 145 -63q218 152 515 162l116 521q3 13 15 21t26 5
+l369 -81q18 37 54 59.5t79 22.5q62 0 106 -43.5t44 -105.5t-44 -106t-106 -44t-105.5 43.5t-43.5 105.5l-334 74l-104 -472q300 -9 519 -160q58 61 143 61q83 0 141 -58.5t58 -140.5zM418 491q0 -62 43.5 -106t105.5 -44t106 44t44 106t-44 105.5t-106 43.5q-61 0 -105 -44
+t-44 -105zM1228 136q11 11 11 26t-11 26q-10 10 -25 10t-26 -10q-41 -42 -121 -62t-160 -20t-160 20t-121 62q-11 10 -26 10t-25 -10q-11 -10 -11 -25.5t11 -26.5q43 -43 118.5 -68t122.5 -29.5t91 -4.5t91 4.5t122.5 29.5t118.5 68zM1225 341q62 0 105.5 44t43.5 106
+q0 61 -44 105t-105 44q-62 0 -106 -43.5t-44 -105.5t44 -106t106 -44z" />
+    <glyph glyph-name="_602" unicode="&#xf282;" horiz-adv-x="1792" 
+d="M69 741h1q16 126 58.5 241.5t115 217t167.5 176t223.5 117.5t276.5 43q231 0 414 -105.5t294 -303.5q104 -187 104 -442v-188h-1125q1 -111 53.5 -192.5t136.5 -122.5t189.5 -57t213 -3t208 46.5t173.5 84.5v-377q-92 -55 -229.5 -92t-312.5 -38t-316 53
+q-189 73 -311.5 249t-124.5 372q-3 242 111 412t325 268q-48 -60 -78 -125.5t-46 -159.5h635q8 77 -8 140t-47 101.5t-70.5 66.5t-80.5 41t-75 20.5t-56 8.5l-22 1q-135 -5 -259.5 -44.5t-223.5 -104.5t-176 -140.5t-138 -163.5z" />
+    <glyph glyph-name="_603" unicode="&#xf283;" horiz-adv-x="2304" 
+d="M0 32v608h2304v-608q0 -66 -47 -113t-113 -47h-1984q-66 0 -113 47t-47 113zM640 256v-128h384v128h-384zM256 256v-128h256v128h-256zM2144 1408q66 0 113 -47t47 -113v-224h-2304v224q0 66 47 113t113 47h1984z" />
+    <glyph glyph-name="_604" unicode="&#xf284;" horiz-adv-x="1792" 
+d="M1584 246l-218 111q-74 -120 -196.5 -189t-263.5 -69q-147 0 -271 72t-196 196t-72 270q0 110 42.5 209.5t115 172t172 115t209.5 42.5q131 0 247.5 -60.5t192.5 -168.5l215 125q-110 169 -286.5 265t-378.5 96q-161 0 -308 -63t-253 -169t-169 -253t-63 -308t63 -308
+t169 -253t253 -169t308 -63q213 0 397.5 107t290.5 292zM1030 643l693 -352q-116 -253 -334.5 -400t-492.5 -147q-182 0 -348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71q260 0 470.5 -133.5t335.5 -366.5zM1543 640h-39v-160h-96v352h136q32 0 54.5 -20
+t28.5 -48t1 -56t-27.5 -48t-57.5 -20z" />
+    <glyph glyph-name="uniF285" unicode="&#xf285;" horiz-adv-x="1792" 
+d="M1427 827l-614 386l92 151h855zM405 562l-184 116v858l1183 -743zM1424 697l147 -95v-858l-532 335zM1387 718l-500 -802h-855l356 571z" />
+    <glyph glyph-name="uniF286" unicode="&#xf286;" horiz-adv-x="1792" 
+d="M640 528v224q0 16 -16 16h-96q-16 0 -16 -16v-224q0 -16 16 -16h96q16 0 16 16zM1152 528v224q0 16 -16 16h-96q-16 0 -16 -16v-224q0 -16 16 -16h96q16 0 16 16zM1664 496v-752h-640v320q0 80 -56 136t-136 56t-136 -56t-56 -136v-320h-640v752q0 16 16 16h96
+q16 0 16 -16v-112h128v624q0 16 16 16h96q16 0 16 -16v-112h128v112q0 16 16 16h96q16 0 16 -16v-112h128v112q0 6 2.5 9.5t8.5 5t9.5 2t11.5 0t9 -0.5v391q-32 15 -32 50q0 23 16.5 39t38.5 16t38.5 -16t16.5 -39q0 -35 -32 -50v-17q45 10 83 10q21 0 59.5 -7.5t54.5 -7.5
+q17 0 47 7.5t37 7.5q16 0 16 -16v-210q0 -15 -35 -21.5t-62 -6.5q-18 0 -54.5 7.5t-55.5 7.5q-40 0 -90 -12v-133q1 0 9 0.5t11.5 0t9.5 -2t8.5 -5t2.5 -9.5v-112h128v112q0 16 16 16h96q16 0 16 -16v-112h128v112q0 16 16 16h96q16 0 16 -16v-624h128v112q0 16 16 16h96
+q16 0 16 -16z" />
+    <glyph glyph-name="_607" unicode="&#xf287;" horiz-adv-x="2304" 
+d="M2288 731q16 -8 16 -27t-16 -27l-320 -192q-8 -5 -16 -5q-9 0 -16 4q-16 10 -16 28v128h-858q37 -58 83 -165q16 -37 24.5 -55t24 -49t27 -47t27 -34t31.5 -26t33 -8h96v96q0 14 9 23t23 9h320q14 0 23 -9t9 -23v-320q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23v96h-96
+q-32 0 -61 10t-51 23.5t-45 40.5t-37 46t-33.5 57t-28.5 57.5t-28 60.5q-23 53 -37 81.5t-36 65t-44.5 53.5t-46.5 17h-360q-22 -84 -91 -138t-157 -54q-106 0 -181 75t-75 181t75 181t181 75q88 0 157 -54t91 -138h104q24 0 46.5 17t44.5 53.5t36 65t37 81.5q19 41 28 60.5
+t28.5 57.5t33.5 57t37 46t45 40.5t51 23.5t61 10h107q21 57 70 92.5t111 35.5q80 0 136 -56t56 -136t-56 -136t-136 -56q-62 0 -111 35.5t-70 92.5h-107q-17 0 -33 -8t-31.5 -26t-27 -34t-27 -47t-24 -49t-24.5 -55q-46 -107 -83 -165h1114v128q0 18 16 28t32 -1z" />
+    <glyph glyph-name="_608" unicode="&#xf288;" horiz-adv-x="1792" 
+d="M1150 774q0 -56 -39.5 -95t-95.5 -39h-253v269h253q56 0 95.5 -39.5t39.5 -95.5zM1329 774q0 130 -91.5 222t-222.5 92h-433v-896h180v269h253q130 0 222 91.5t92 221.5zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348
+t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
+    <glyph glyph-name="_609" unicode="&#xf289;" horiz-adv-x="2304" 
+d="M1645 438q0 59 -34 106.5t-87 68.5q-7 -45 -23 -92q-7 -24 -27.5 -38t-44.5 -14q-12 0 -24 3q-31 10 -45 38.5t-4 58.5q23 71 23 143q0 123 -61 227.5t-166 165.5t-228 61q-134 0 -247 -73t-167 -194q108 -28 188 -106q22 -23 22 -55t-22 -54t-54 -22t-55 22
+q-75 75 -180 75q-106 0 -181 -74.5t-75 -180.5t75 -180.5t181 -74.5h1046q79 0 134.5 55.5t55.5 133.5zM1798 438q0 -142 -100.5 -242t-242.5 -100h-1046q-169 0 -289 119.5t-120 288.5q0 153 100 267t249 136q62 184 221 298t354 114q235 0 408.5 -158.5t196.5 -389.5
+q116 -25 192.5 -118.5t76.5 -214.5zM2048 438q0 -175 -97 -319q-23 -33 -64 -33q-24 0 -43 13q-26 17 -32 48.5t12 57.5q71 104 71 233t-71 233q-18 26 -12 57t32 49t57.5 11.5t49.5 -32.5q97 -142 97 -318zM2304 438q0 -244 -134 -443q-23 -34 -64 -34q-23 0 -42 13
+q-26 18 -32.5 49t11.5 57q108 164 108 358q0 195 -108 357q-18 26 -11.5 57.5t32.5 48.5q26 18 57 12t49 -33q134 -198 134 -442z" />
+    <glyph glyph-name="_610" unicode="&#xf28a;" 
+d="M1500 -13q0 -89 -63 -152.5t-153 -63.5t-153.5 63.5t-63.5 152.5q0 90 63.5 153.5t153.5 63.5t153 -63.5t63 -153.5zM1267 268q-115 -15 -192.5 -102.5t-77.5 -205.5q0 -74 33 -138q-146 -78 -379 -78q-109 0 -201 21t-153.5 54.5t-110.5 76.5t-76 85t-44.5 83
+t-23.5 66.5t-6 39.5q0 19 4.5 42.5t18.5 56t36.5 58t64 43.5t94.5 18t94 -17.5t63 -41t35.5 -53t17.5 -49t4 -33.5q0 -34 -23 -81q28 -27 82 -42t93 -17l40 -1q115 0 190 51t75 133q0 26 -9 48.5t-31.5 44.5t-49.5 41t-74 44t-93.5 47.5t-119.5 56.5q-28 13 -43 20
+q-116 55 -187 100t-122.5 102t-72 125.5t-20.5 162.5q0 78 20.5 150t66 137.5t112.5 114t166.5 77t221.5 28.5q120 0 220 -26t164.5 -67t109.5 -94t64 -105.5t19 -103.5q0 -46 -15 -82.5t-36.5 -58t-48.5 -36t-49 -19.5t-39 -5h-8h-32t-39 5t-44 14t-41 28t-37 46t-24 70.5
+t-10 97.5q-15 16 -59 25.5t-81 10.5l-37 1q-68 0 -117.5 -31t-70.5 -70t-21 -76q0 -24 5 -43t24 -46t53 -51t97 -53.5t150 -58.5q76 -25 138.5 -53.5t109 -55.5t83 -59t60.5 -59.5t41 -62.5t26.5 -62t14.5 -63.5t6 -62t1 -62.5z" />
+    <glyph glyph-name="_611" unicode="&#xf28b;" 
+d="M704 352v576q0 14 -9 23t-23 9h-256q-14 0 -23 -9t-9 -23v-576q0 -14 9 -23t23 -9h256q14 0 23 9t9 23zM1152 352v576q0 14 -9 23t-23 9h-256q-14 0 -23 -9t-9 -23v-576q0 -14 9 -23t23 -9h256q14 0 23 9t9 23zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103
+t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="_612" unicode="&#xf28c;" 
+d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM768 96q148 0 273 73t198 198t73 273t-73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273
+t73 -273t198 -198t273 -73zM864 320q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-192zM480 320q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-192z" />
+    <glyph glyph-name="_613" unicode="&#xf28d;" 
+d="M1088 352v576q0 14 -9 23t-23 9h-576q-14 0 -23 -9t-9 -23v-576q0 -14 9 -23t23 -9h576q14 0 23 9t9 23zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5
+t103 -385.5z" />
+    <glyph glyph-name="_614" unicode="&#xf28e;" 
+d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM768 96q148 0 273 73t198 198t73 273t-73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273
+t73 -273t198 -198t273 -73zM480 320q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h576q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-576z" />
+    <glyph glyph-name="_615" unicode="&#xf290;" horiz-adv-x="1792" 
+d="M1757 128l35 -313q3 -28 -16 -50q-19 -21 -48 -21h-1664q-29 0 -48 21q-19 22 -16 50l35 313h1722zM1664 967l86 -775h-1708l86 775q3 24 21 40.5t43 16.5h256v-128q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5v128h384v-128q0 -53 37.5 -90.5t90.5 -37.5
+t90.5 37.5t37.5 90.5v128h256q25 0 43 -16.5t21 -40.5zM1280 1152v-256q0 -26 -19 -45t-45 -19t-45 19t-19 45v256q0 106 -75 181t-181 75t-181 -75t-75 -181v-256q0 -26 -19 -45t-45 -19t-45 19t-19 45v256q0 159 112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5z" />
+    <glyph glyph-name="_616" unicode="&#xf291;" horiz-adv-x="2048" 
+d="M1920 768q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5h-15l-115 -662q-8 -46 -44 -76t-82 -30h-1280q-46 0 -82 30t-44 76l-115 662h-15q-53 0 -90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5h1792zM485 -32q26 2 43.5 22.5t15.5 46.5l-32 416q-2 26 -22.5 43.5
+t-46.5 15.5t-43.5 -22.5t-15.5 -46.5l32 -416q2 -25 20.5 -42t43.5 -17h5zM896 32v416q0 26 -19 45t-45 19t-45 -19t-19 -45v-416q0 -26 19 -45t45 -19t45 19t19 45zM1280 32v416q0 26 -19 45t-45 19t-45 -19t-19 -45v-416q0 -26 19 -45t45 -19t45 19t19 45zM1632 27l32 416
+q2 26 -15.5 46.5t-43.5 22.5t-46.5 -15.5t-22.5 -43.5l-32 -416q-2 -26 15.5 -46.5t43.5 -22.5h5q25 0 43.5 17t20.5 42zM476 1244l-93 -412h-132l101 441q19 88 89 143.5t160 55.5h167q0 26 19 45t45 19h384q26 0 45 -19t19 -45h167q90 0 160 -55.5t89 -143.5l101 -441
+h-132l-93 412q-11 44 -45.5 72t-79.5 28h-167q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45h-167q-45 0 -79.5 -28t-45.5 -72z" />
+    <glyph glyph-name="_617" unicode="&#xf292;" horiz-adv-x="1792" 
+d="M991 512l64 256h-254l-64 -256h254zM1759 1016l-56 -224q-7 -24 -31 -24h-327l-64 -256h311q15 0 25 -12q10 -14 6 -28l-56 -224q-5 -24 -31 -24h-327l-81 -328q-7 -24 -31 -24h-224q-16 0 -26 12q-9 12 -6 28l78 312h-254l-81 -328q-7 -24 -31 -24h-225q-15 0 -25 12
+q-9 12 -6 28l78 312h-311q-15 0 -25 12q-9 12 -6 28l56 224q7 24 31 24h327l64 256h-311q-15 0 -25 12q-10 14 -6 28l56 224q5 24 31 24h327l81 328q7 24 32 24h224q15 0 25 -12q9 -12 6 -28l-78 -312h254l81 328q7 24 32 24h224q15 0 25 -12q9 -12 6 -28l-78 -312h311
+q15 0 25 -12q9 -12 6 -28z" />
+    <glyph glyph-name="_618" unicode="&#xf293;" 
+d="M841 483l148 -148l-149 -149zM840 1094l149 -149l-148 -148zM710 -130l464 464l-306 306l306 306l-464 464v-611l-255 255l-93 -93l320 -321l-320 -321l93 -93l255 255v-611zM1429 640q0 -209 -32 -365.5t-87.5 -257t-140.5 -162.5t-181.5 -86.5t-219.5 -24.5
+t-219.5 24.5t-181.5 86.5t-140.5 162.5t-87.5 257t-32 365.5t32 365.5t87.5 257t140.5 162.5t181.5 86.5t219.5 24.5t219.5 -24.5t181.5 -86.5t140.5 -162.5t87.5 -257t32 -365.5z" />
+    <glyph glyph-name="_619" unicode="&#xf294;" horiz-adv-x="1024" 
+d="M596 113l173 172l-173 172v-344zM596 823l173 172l-173 172v-344zM628 640l356 -356l-539 -540v711l-297 -296l-108 108l372 373l-372 373l108 108l297 -296v711l539 -540z" />
+    <glyph glyph-name="_620" unicode="&#xf295;" 
+d="M1280 256q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM512 1024q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM1536 256q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5
+t112.5 -271.5zM1440 1344q0 -20 -13 -38l-1056 -1408q-19 -26 -51 -26h-160q-26 0 -45 19t-19 45q0 20 13 38l1056 1408q19 26 51 26h160q26 0 45 -19t19 -45zM768 1024q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5
+t271.5 -112.5t112.5 -271.5z" />
+    <glyph glyph-name="_621" unicode="&#xf296;" horiz-adv-x="1792" 
+d="M104 830l792 -1015l-868 630q-18 13 -25 34.5t0 42.5l101 308v0zM566 830h660l-330 -1015v0zM368 1442l198 -612h-462l198 612q8 23 33 23t33 -23zM1688 830l101 -308q7 -21 0 -42.5t-25 -34.5l-868 -630l792 1015v0zM1688 830h-462l198 612q8 23 33 23t33 -23z" />
+    <glyph glyph-name="_622" unicode="&#xf297;" horiz-adv-x="1792" 
+d="M384 704h160v224h-160v-224zM1221 372v92q-104 -36 -243 -38q-135 -1 -259.5 46.5t-220.5 122.5l1 -96q88 -80 212 -128.5t272 -47.5q129 0 238 49zM640 704h640v224h-640v-224zM1792 736q0 -187 -99 -352q89 -102 89 -229q0 -157 -129.5 -268t-313.5 -111
+q-122 0 -225 52.5t-161 140.5q-19 -1 -57 -1t-57 1q-58 -88 -161 -140.5t-225 -52.5q-184 0 -313.5 111t-129.5 268q0 127 89 229q-99 165 -99 352q0 209 120 385.5t326.5 279.5t449.5 103t449.5 -103t326.5 -279.5t120 -385.5z" />
+    <glyph glyph-name="_623" unicode="&#xf298;" 
+d="M515 625v-128h-252v128h252zM515 880v-127h-252v127h252zM1273 369v-128h-341v128h341zM1273 625v-128h-672v128h672zM1273 880v-127h-672v127h672zM1408 20v1240q0 8 -6 14t-14 6h-32l-378 -256l-210 171l-210 -171l-378 256h-32q-8 0 -14 -6t-6 -14v-1240q0 -8 6 -14
+t14 -6h1240q8 0 14 6t6 14zM553 1130l185 150h-406zM983 1130l221 150h-406zM1536 1260v-1240q0 -62 -43 -105t-105 -43h-1240q-62 0 -105 43t-43 105v1240q0 62 43 105t105 43h1240q62 0 105 -43t43 -105z" />
+    <glyph glyph-name="_624" unicode="&#xf299;" horiz-adv-x="1792" 
+d="M896 720q-104 196 -160 278q-139 202 -347 318q-34 19 -70 36q-89 40 -94 32t34 -38l39 -31q62 -43 112.5 -93.5t94.5 -116.5t70.5 -113t70.5 -131q9 -17 13 -25q44 -84 84 -153t98 -154t115.5 -150t131 -123.5t148.5 -90.5q153 -66 154 -60q1 3 -49 37q-53 36 -81 57
+q-77 58 -179 211t-185 310zM549 177q-76 60 -132.5 125t-98 143.5t-71 154.5t-58.5 186t-52 209t-60.5 252t-76.5 289q273 0 497.5 -36t379 -92t271 -144.5t185.5 -172.5t110 -198.5t56 -199.5t12.5 -198.5t-9.5 -173t-20 -143.5t-13 -107l323 -327h-104l-281 285
+q-22 -2 -91.5 -14t-121.5 -19t-138 -6t-160.5 17t-167.5 59t-179 111z" />
+    <glyph glyph-name="_625" unicode="&#xf29a;" horiz-adv-x="1792" 
+d="M1374 879q-6 26 -28.5 39.5t-48.5 7.5q-261 -62 -401 -62t-401 62q-26 6 -48.5 -7.5t-28.5 -39.5t7.5 -48.5t39.5 -28.5q194 -46 303 -58q-2 -158 -15.5 -269t-26.5 -155.5t-41 -115.5l-9 -21q-10 -25 1 -49t36 -34q9 -4 23 -4q44 0 60 41l8 20q54 139 71 259h42
+q17 -120 71 -259l8 -20q16 -41 60 -41q14 0 23 4q25 10 36 34t1 49l-9 21q-28 71 -41 115.5t-26.5 155.5t-15.5 269q109 12 303 58q26 6 39.5 28.5t7.5 48.5zM1024 1024q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5z
+M1600 640q0 -143 -55.5 -273.5t-150 -225t-225 -150t-273.5 -55.5t-273.5 55.5t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5zM896 1408q-156 0 -298 -61t-245 -164t-164 -245t-61 -298t61 -298
+t164 -245t245 -164t298 -61t298 61t245 164t164 245t61 298t-61 298t-164 245t-245 164t-298 61zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
+    <glyph glyph-name="_626" unicode="&#xf29b;" 
+d="M1438 723q34 -35 29 -82l-44 -551q-4 -42 -34.5 -70t-71.5 -28q-6 0 -9 1q-44 3 -72.5 36.5t-25.5 77.5l35 429l-143 -8q55 -113 55 -240q0 -216 -148 -372l-137 137q91 101 91 235q0 145 -102.5 248t-247.5 103q-134 0 -236 -92l-137 138q120 114 284 141l264 300
+l-149 87l-181 -161q-33 -30 -77 -27.5t-73 35.5t-26.5 77t34.5 73l239 213q26 23 60 26.5t64 -14.5l488 -283q36 -21 48 -68q17 -67 -26 -117l-205 -232l371 20q49 3 83 -32zM1240 1180q-74 0 -126 52t-52 126t52 126t126 52t126.5 -52t52.5 -126t-52.5 -126t-126.5 -52z
+M613 -62q106 0 196 61l139 -139q-146 -116 -335 -116q-148 0 -273.5 73t-198.5 198t-73 273q0 188 116 336l139 -139q-60 -88 -60 -197q0 -145 102.5 -247.5t247.5 -102.5z" />
+    <glyph glyph-name="_627" unicode="&#xf29c;" 
+d="M880 336v-160q0 -14 -9 -23t-23 -9h-160q-14 0 -23 9t-9 23v160q0 14 9 23t23 9h160q14 0 23 -9t9 -23zM1136 832q0 -50 -15 -90t-45.5 -69t-52 -44t-59.5 -36q-32 -18 -46.5 -28t-26 -24t-11.5 -29v-32q0 -14 -9 -23t-23 -9h-160q-14 0 -23 9t-9 23v68q0 35 10.5 64.5
+t24 47.5t39 35.5t41 25.5t44.5 21q53 25 75 43t22 49q0 42 -43.5 71.5t-95.5 29.5q-56 0 -95 -27q-29 -20 -80 -83q-9 -12 -25 -12q-11 0 -19 6l-108 82q-10 7 -12 20t5 23q122 192 349 192q129 0 238.5 -89.5t109.5 -214.5zM768 1280q-130 0 -248.5 -51t-204 -136.5
+t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5t-51 248.5t-136.5 204t-204 136.5t-248.5 51zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5
+t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="_628" unicode="&#xf29d;" horiz-adv-x="1408" 
+d="M366 1225q-64 0 -110 45.5t-46 110.5q0 64 46 109.5t110 45.5t109.5 -45.5t45.5 -109.5q0 -65 -45.5 -110.5t-109.5 -45.5zM917 583q0 -50 -30 -67.5t-63.5 -6.5t-47.5 34l-367 438q-7 12 -14 15.5t-11 1.5l-3 -3q-7 -8 4 -21l122 -139l1 -354l-161 -457
+q-67 -192 -92 -234q-15 -26 -28 -32q-50 -26 -103 -1q-29 13 -41.5 43t-9.5 57q2 17 197 618l5 416l-85 -164l35 -222q4 -24 -1 -42t-14 -27.5t-19 -16t-17 -7.5l-7 -2q-19 -3 -34.5 3t-24 16t-14 22t-7.5 19.5t-2 9.5l-46 299l211 381q23 34 113 34q75 0 107 -40l424 -521
+q7 -5 14 -17l3 -3l-1 -1q7 -13 7 -29zM514 433q43 -113 88.5 -225t69.5 -168l24 -55q36 -93 42 -125q11 -70 -36 -97q-35 -22 -66 -16t-51 22t-29 35h-1q-6 16 -8 25l-124 351zM1338 -159q31 -49 31 -57q0 -5 -3 -7q-9 -5 -14.5 0.5t-15.5 26t-16 30.5q-114 172 -423 661
+q3 -1 7 1t7 4l3 2q11 9 11 17z" />
+    <glyph glyph-name="_629" unicode="&#xf29e;" horiz-adv-x="2304" 
+d="M504 542h171l-1 265zM1530 641q0 87 -50.5 140t-146.5 53h-54v-388h52q91 0 145 57t54 138zM956 1018l1 -756q0 -14 -9.5 -24t-23.5 -10h-216q-14 0 -23.5 10t-9.5 24v62h-291l-55 -81q-10 -15 -28 -15h-267q-21 0 -30.5 18t3.5 35l556 757q9 14 27 14h332q14 0 24 -10
+t10 -24zM1783 641q0 -193 -125.5 -303t-324.5 -110h-270q-14 0 -24 10t-10 24v756q0 14 10 24t24 10h268q200 0 326 -109t126 -302zM1939 640q0 -11 -0.5 -29t-8 -71.5t-21.5 -102t-44.5 -108t-73.5 -102.5h-51q38 45 66.5 104.5t41.5 112t21 98t9 72.5l1 27q0 8 -0.5 22.5
+t-7.5 60t-20 91.5t-41 111.5t-66 124.5h43q41 -47 72 -107t45.5 -111.5t23 -96t10.5 -70.5zM2123 640q0 -11 -0.5 -29t-8 -71.5t-21.5 -102t-45 -108t-74 -102.5h-51q38 45 66.5 104.5t41.5 112t21 98t9 72.5l1 27q0 8 -0.5 22.5t-7.5 60t-19.5 91.5t-40.5 111.5t-66 124.5
+h43q41 -47 72 -107t45.5 -111.5t23 -96t10.5 -70.5zM2304 640q0 -11 -0.5 -29t-8 -71.5t-21.5 -102t-44.5 -108t-73.5 -102.5h-51q38 45 66 104.5t41 112t21 98t9 72.5l1 27q0 8 -0.5 22.5t-7.5 60t-19.5 91.5t-40.5 111.5t-66 124.5h43q41 -47 72 -107t45.5 -111.5t23 -96
+t9.5 -70.5z" />
+    <glyph glyph-name="uniF2A0" unicode="&#xf2a0;" horiz-adv-x="1408" 
+d="M617 -153q0 11 -13 58t-31 107t-20 69q-1 4 -5 26.5t-8.5 36t-13.5 21.5q-15 14 -51 14q-23 0 -70 -5.5t-71 -5.5q-34 0 -47 11q-6 5 -11 15.5t-7.5 20t-6.5 24t-5 18.5q-37 128 -37 255t37 255q1 4 5 18.5t6.5 24t7.5 20t11 15.5q13 11 47 11q24 0 71 -5.5t70 -5.5
+q36 0 51 14q9 8 13.5 21.5t8.5 36t5 26.5q2 9 20 69t31 107t13 58q0 22 -43.5 52.5t-75.5 42.5q-20 8 -45 8q-34 0 -98 -18q-57 -17 -96.5 -40.5t-71 -66t-46 -70t-45.5 -94.5q-6 -12 -9 -19q-49 -107 -68 -216t-19 -244t19 -244t68 -216q56 -122 83 -161q63 -91 179 -127
+l6 -2q64 -18 98 -18q25 0 45 8q32 12 75.5 42.5t43.5 52.5zM776 760q-26 0 -45 19t-19 45.5t19 45.5q37 37 37 90q0 52 -37 91q-19 19 -19 45t19 45t45 19t45 -19q75 -75 75 -181t-75 -181q-21 -19 -45 -19zM957 579q-27 0 -45 19q-19 19 -19 45t19 45q112 114 112 272
+t-112 272q-19 19 -19 45t19 45t45 19t45 -19q150 -150 150 -362t-150 -362q-18 -19 -45 -19zM1138 398q-27 0 -45 19q-19 19 -19 45t19 45q90 91 138.5 208t48.5 245t-48.5 245t-138.5 208q-19 19 -19 45t19 45t45 19t45 -19q109 -109 167 -249t58 -294t-58 -294t-167 -249
+q-18 -19 -45 -19z" />
+    <glyph glyph-name="uniF2A1" unicode="&#xf2a1;" horiz-adv-x="2176" 
+d="M192 352q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM704 352q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM704 864q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM1472 352
+q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM1984 352q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM1472 864q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM1984 864
+q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM1984 1376q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM384 192q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM896 192q0 -80 -56 -136
+t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM384 704q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM896 704q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM384 1216q0 -80 -56 -136t-136 -56
+t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1664 192q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM896 1216q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM2176 192q0 -80 -56 -136t-136 -56t-136 56
+t-56 136t56 136t136 56t136 -56t56 -136zM1664 704q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM2176 704q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1664 1216q0 -80 -56 -136t-136 -56t-136 56t-56 136
+t56 136t136 56t136 -56t56 -136zM2176 1216q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136z" />
+    <glyph glyph-name="uniF2A2" unicode="&#xf2a2;" horiz-adv-x="1792" 
+d="M128 -192q0 -26 -19 -45t-45 -19t-45 19t-19 45t19 45t45 19t45 -19t19 -45zM320 0q0 -26 -19 -45t-45 -19t-45 19t-19 45t19 45t45 19t45 -19t19 -45zM365 365l256 -256l-90 -90l-256 256zM704 384q0 -26 -19 -45t-45 -19t-45 19t-19 45t19 45t45 19t45 -19t19 -45z
+M1411 704q0 -59 -11.5 -108.5t-37.5 -93.5t-44 -67.5t-53 -64.5q-31 -35 -45.5 -54t-33.5 -50t-26.5 -64t-7.5 -74q0 -159 -112.5 -271.5t-271.5 -112.5q-26 0 -45 19t-19 45t19 45t45 19q106 0 181 75t75 181q0 57 11.5 105.5t37 91t43.5 66.5t52 63q40 46 59.5 72
+t37.5 74.5t18 103.5q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5q0 -26 -19 -45t-45 -19t-45 19t-19 45q0 117 45.5 223.5t123 184t184 123t223.5 45.5t223.5 -45.5t184 -123t123 -184t45.5 -223.5zM896 576q0 -26 -19 -45t-45 -19t-45 19t-19 45t19 45
+t45 19t45 -19t19 -45zM1184 704q0 -26 -19 -45t-45 -19t-45 19t-19 45q0 93 -65.5 158.5t-158.5 65.5q-92 0 -158 -65.5t-66 -158.5q0 -26 -19 -45t-45 -19t-45 19t-19 45q0 146 103 249t249 103t249 -103t103 -249zM1578 993q10 -25 -1 -49t-36 -34q-9 -4 -23 -4
+q-19 0 -35.5 11t-23.5 30q-68 178 -224 295q-21 16 -25 42t12 47q17 21 43 25t47 -12q183 -137 266 -351zM1788 1074q9 -25 -1.5 -49t-35.5 -34q-11 -4 -23 -4q-44 0 -60 41q-92 238 -297 393q-22 16 -25.5 42t12.5 47q16 22 42 25.5t47 -12.5q235 -175 341 -449z" />
+    <glyph glyph-name="uniF2A3" unicode="&#xf2a3;" horiz-adv-x="2304" 
+d="M1032 576q-59 2 -84 55q-17 34 -48 53.5t-68 19.5q-53 0 -90.5 -37.5t-37.5 -90.5q0 -56 36 -89l10 -8q34 -31 82 -31q37 0 68 19.5t48 53.5q25 53 84 55zM1600 704q0 56 -36 89l-10 8q-34 31 -82 31q-37 0 -68 -19.5t-48 -53.5q-25 -53 -84 -55q59 -2 84 -55
+q17 -34 48 -53.5t68 -19.5q53 0 90.5 37.5t37.5 90.5zM1174 925q-17 -35 -55 -48t-73 4q-62 31 -134 31q-51 0 -99 -17q3 0 9.5 0.5t9.5 0.5q92 0 170.5 -50t118.5 -133q17 -36 3.5 -73.5t-49.5 -54.5q-18 -9 -39 -9q21 0 39 -9q36 -17 49.5 -54.5t-3.5 -73.5
+q-40 -83 -118.5 -133t-170.5 -50h-6q-16 2 -44 4l-290 27l-239 -120q-14 -7 -29 -7q-40 0 -57 35l-160 320q-11 23 -4 47.5t29 37.5l209 119l148 267q17 155 91.5 291.5t195.5 236.5q31 25 70.5 21.5t64.5 -34.5t21.5 -70t-34.5 -65q-70 -59 -117 -128q123 84 267 101
+q40 5 71.5 -19t35.5 -64q5 -40 -19 -71.5t-64 -35.5q-84 -10 -159 -55q46 10 99 10q115 0 218 -50q36 -18 49 -55.5t-5 -73.5zM2137 1085l160 -320q11 -23 4 -47.5t-29 -37.5l-209 -119l-148 -267q-17 -155 -91.5 -291.5t-195.5 -236.5q-26 -22 -61 -22q-45 0 -74 35
+q-25 31 -21.5 70t34.5 65q70 59 117 128q-123 -84 -267 -101q-4 -1 -12 -1q-36 0 -63.5 24t-31.5 60q-5 40 19 71.5t64 35.5q84 10 159 55q-46 -10 -99 -10q-115 0 -218 50q-36 18 -49 55.5t5 73.5q17 35 55 48t73 -4q62 -31 134 -31q51 0 99 17q-3 0 -9.5 -0.5t-9.5 -0.5
+q-92 0 -170.5 50t-118.5 133q-17 36 -3.5 73.5t49.5 54.5q18 9 39 9q-21 0 -39 9q-36 17 -49.5 54.5t3.5 73.5q40 83 118.5 133t170.5 50h6h1q14 -2 42 -4l291 -27l239 120q14 7 29 7q40 0 57 -35z" />
+    <glyph glyph-name="uniF2A4" unicode="&#xf2a4;" horiz-adv-x="1792" 
+d="M1056 704q0 -26 19 -45t45 -19t45 19t19 45q0 146 -103 249t-249 103t-249 -103t-103 -249q0 -26 19 -45t45 -19t45 19t19 45q0 93 66 158.5t158 65.5t158 -65.5t66 -158.5zM835 1280q-117 0 -223.5 -45.5t-184 -123t-123 -184t-45.5 -223.5q0 -26 19 -45t45 -19t45 19
+t19 45q0 185 131.5 316.5t316.5 131.5t316.5 -131.5t131.5 -316.5q0 -55 -18 -103.5t-37.5 -74.5t-59.5 -72q-34 -39 -52 -63t-43.5 -66.5t-37 -91t-11.5 -105.5q0 -106 -75 -181t-181 -75q-26 0 -45 -19t-19 -45t19 -45t45 -19q159 0 271.5 112.5t112.5 271.5q0 41 7.5 74
+t26.5 64t33.5 50t45.5 54q35 41 53 64.5t44 67.5t37.5 93.5t11.5 108.5q0 117 -45.5 223.5t-123 184t-184 123t-223.5 45.5zM591 561l226 -226l-579 -579q-12 -12 -29 -12t-29 12l-168 168q-12 12 -12 29t12 29zM1612 1524l168 -168q12 -12 12 -29t-12 -30l-233 -233
+l-26 -25l-71 -71q-66 153 -195 258l91 91l207 207q13 12 30 12t29 -12z" />
+    <glyph glyph-name="uniF2A5" unicode="&#xf2a5;" 
+d="M866 1021q0 -27 -13 -94q-11 -50 -31.5 -150t-30.5 -150q-2 -11 -4.5 -12.5t-13.5 -2.5q-20 -2 -31 -2q-58 0 -84 49.5t-26 113.5q0 88 35 174t103 124q28 14 51 14q28 0 36.5 -16.5t8.5 -47.5zM1352 597q0 14 -39 75.5t-52 66.5q-21 8 -34 8q-91 0 -226 -77l-2 2
+q3 22 27.5 135t24.5 178q0 233 -242 233q-24 0 -68 -6q-94 -17 -168.5 -89.5t-111.5 -166.5t-37 -189q0 -146 80.5 -225t227.5 -79q25 0 25 -3t-1 -5q-4 -34 -26 -117q-14 -52 -51.5 -101t-82.5 -49q-42 0 -42 47q0 24 10.5 47.5t25 39.5t29.5 28.5t26 20t11 8.5q0 3 -7 10
+q-24 22 -58.5 36.5t-65.5 14.5q-35 0 -63.5 -34t-41 -75t-12.5 -75q0 -88 51.5 -142t138.5 -54q82 0 155 53t117.5 126t65.5 153q6 22 15.5 66.5t14.5 66.5q3 12 14 18q118 60 227 60q48 0 127 -18q1 -1 4 -1q5 0 9.5 4.5t4.5 8.5zM1536 1120v-960q0 -119 -84.5 -203.5
+t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="uniF2A6" unicode="&#xf2a6;" horiz-adv-x="1535" 
+d="M744 1231q0 24 -2 38.5t-8.5 30t-21 23t-37.5 7.5q-39 0 -78 -23q-105 -58 -159 -190.5t-54 -269.5q0 -44 8.5 -85.5t26.5 -80.5t52.5 -62.5t81.5 -23.5q4 0 18 -0.5t20 0t16 3t15 8.5t7 16q16 77 48 231.5t48 231.5q19 91 19 146zM1498 575q0 -7 -7.5 -13.5t-15.5 -6.5
+l-6 1q-22 3 -62 11t-72 12.5t-63 4.5q-167 0 -351 -93q-15 -8 -21 -27q-10 -36 -24.5 -105.5t-22.5 -100.5q-23 -91 -70 -179.5t-112.5 -164.5t-154.5 -123t-185 -47q-135 0 -214.5 83.5t-79.5 219.5q0 53 19.5 117t63 116.5t97.5 52.5q38 0 120 -33.5t83 -61.5
+q0 -1 -16.5 -12.5t-39.5 -31t-46 -44.5t-39 -61t-16 -74q0 -33 16.5 -53t48.5 -20q45 0 85 31.5t66.5 78t48 105.5t32.5 107t16 90v9q0 2 -3.5 3.5t-8.5 1.5h-10t-10 -0.5t-6 -0.5q-227 0 -352 122.5t-125 348.5q0 108 34.5 221t96 210t156 167.5t204.5 89.5q52 9 106 9
+q374 0 374 -360q0 -98 -38 -273t-43 -211l3 -3q101 57 182.5 88t167.5 31q22 0 53 -13q19 -7 80 -102.5t61 -116.5z" />
+    <glyph glyph-name="uniF2A7" unicode="&#xf2a7;" horiz-adv-x="1664" 
+d="M831 863q32 0 59 -18l222 -148q61 -40 110 -97l146 -170q40 -46 29 -106l-72 -413q-6 -32 -29.5 -53.5t-55.5 -25.5l-527 -56l-352 -32h-9q-39 0 -67.5 28t-28.5 68q0 37 27 64t65 32l260 32h-448q-41 0 -69.5 30t-26.5 71q2 39 32 65t69 26l442 1l-521 64q-41 5 -66 37
+t-19 73q6 35 34.5 57.5t65.5 22.5h10l481 -60l-351 94q-38 10 -62 41.5t-18 68.5q6 36 33 58.5t62 22.5q6 0 20 -2l448 -96l217 -37q1 0 3 -0.5t3 -0.5q23 0 30.5 23t-12.5 36l-186 125q-35 23 -42 63.5t18 73.5q27 38 76 38zM761 661l186 -125l-218 37l-5 2l-36 38
+l-238 262q-1 1 -2.5 3.5t-2.5 3.5q-24 31 -18.5 70t37.5 64q31 23 68 17.5t64 -33.5l142 -147q-2 -1 -5 -3.5t-4 -4.5q-32 -45 -23 -99t55 -85zM1648 1115l15 -266q4 -73 -11 -147l-48 -219q-12 -59 -67 -87l-106 -54q2 62 -39 109l-146 170q-53 61 -117 103l-222 148
+q-34 23 -76 23q-51 0 -88 -37l-235 312q-25 33 -18 73.5t41 63.5q33 22 71.5 14t62.5 -40l266 -352l-262 455q-21 35 -10.5 75t47.5 59q35 18 72.5 6t57.5 -46l241 -420l-136 337q-15 35 -4.5 74t44.5 56q37 19 76 6t56 -51l193 -415l101 -196q8 -15 23 -17.5t27 7.5t11 26
+l-12 224q-2 41 26 71t69 31q39 0 67 -28.5t30 -67.5z" />
+    <glyph glyph-name="uniF2A8" unicode="&#xf2a8;" horiz-adv-x="1792" 
+d="M335 180q-2 0 -6 2q-86 57 -168.5 145t-139.5 180q-21 30 -21 69q0 9 2 19t4 18t7 18t8.5 16t10.5 17t10 15t12 15.5t11 14.5q184 251 452 365q-110 198 -110 211q0 19 17 29q116 64 128 64q18 0 28 -16l124 -229q92 19 192 19q266 0 497.5 -137.5t378.5 -369.5
+q20 -31 20 -69t-20 -69q-91 -142 -218.5 -253.5t-278.5 -175.5q110 -198 110 -211q0 -20 -17 -29q-116 -64 -127 -64q-19 0 -29 16l-124 229l-64 119l-444 820l7 7q-58 -24 -99 -47q3 -5 127 -234t243 -449t119 -223q0 -7 -9 -9q-13 -3 -72 -3q-57 0 -60 7l-456 841
+q-39 -28 -82 -68q24 -43 214 -393.5t190 -354.5q0 -10 -11 -10q-14 0 -82.5 22t-72.5 28l-106 197l-224 413q-44 -53 -78 -106q2 -3 18 -25t23 -34l176 -327q0 -10 -10 -10zM1165 282l49 -91q273 111 450 385q-180 277 -459 389q67 -64 103 -148.5t36 -176.5
+q0 -106 -47 -200.5t-132 -157.5zM848 896q0 -20 14 -34t34 -14q86 0 147 -61t61 -147q0 -20 14 -34t34 -14t34 14t14 34q0 126 -89 215t-215 89q-20 0 -34 -14t-14 -34zM1214 961l-9 4l7 -7z" />
+    <glyph glyph-name="uniF2A9" unicode="&#xf2a9;" horiz-adv-x="1280" 
+d="M1050 430q0 -215 -147 -374q-148 -161 -378 -161q-232 0 -378 161q-147 159 -147 374q0 147 68 270.5t189 196.5t268 73q96 0 182 -31q-32 -62 -39 -126q-66 28 -143 28q-167 0 -280.5 -123t-113.5 -291q0 -170 112.5 -288.5t281.5 -118.5t281 118.5t112 288.5
+q0 89 -32 166q66 13 123 49q41 -98 41 -212zM846 619q0 -192 -79.5 -345t-238.5 -253l-14 -1q-29 0 -62 5q83 32 146.5 102.5t99.5 154.5t58.5 189t30 192.5t7.5 178.5q0 69 -3 103q55 -160 55 -326zM791 947v-2q-73 214 -206 440q88 -59 142.5 -186.5t63.5 -251.5z
+M1035 744q-83 0 -160 75q218 120 290 247q19 37 21 56q-42 -94 -139.5 -166.5t-204.5 -97.5q-35 54 -35 113q0 37 17 79t43 68q46 44 157 74q59 16 106 58.5t74 100.5q74 -105 74 -253q0 -109 -24 -170q-32 -77 -88.5 -130.5t-130.5 -53.5z" />
+    <glyph glyph-name="uniF2AA" unicode="&#xf2aa;" 
+d="M1050 495q0 78 -28 147q-41 -25 -85 -34q22 -50 22 -114q0 -117 -77 -198.5t-193 -81.5t-193.5 81.5t-77.5 198.5q0 115 78 199.5t193 84.5q53 0 98 -19q4 43 27 87q-60 21 -125 21q-154 0 -257.5 -108.5t-103.5 -263.5t103.5 -261t257.5 -106t257.5 106.5t103.5 260.5z
+M872 850q2 -24 2 -71q0 -63 -5 -123t-20.5 -132.5t-40.5 -130t-68.5 -106t-100.5 -70.5q21 -3 42 -3h10q219 139 219 411q0 116 -38 225zM872 850q-4 80 -44 171.5t-98 130.5q92 -156 142 -302zM1207 955q0 102 -51 174q-41 -86 -124 -109q-69 -19 -109 -53.5t-40 -99.5
+q0 -40 24 -77q74 17 140.5 67t95.5 115q-4 -52 -74.5 -111.5t-138.5 -97.5q52 -52 110 -52q51 0 90 37t60 90q17 42 17 117zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5
+t84.5 -203.5z" />
+    <glyph glyph-name="uniF2AB" unicode="&#xf2ab;" 
+d="M1279 388q0 22 -22 27q-67 15 -118 59t-80 108q-7 19 -7 25q0 15 19.5 26t43 17t43 20.5t19.5 36.5q0 19 -18.5 31.5t-38.5 12.5q-12 0 -32 -8t-31 -8q-4 0 -12 2q5 95 5 114q0 79 -17 114q-36 78 -103 121.5t-152 43.5q-199 0 -275 -165q-17 -35 -17 -114q0 -19 5 -114
+q-4 -2 -14 -2q-12 0 -32 7.5t-30 7.5q-21 0 -38.5 -12t-17.5 -32q0 -21 19.5 -35.5t43 -20.5t43 -17t19.5 -26q0 -6 -7 -25q-64 -138 -198 -167q-22 -5 -22 -27q0 -46 137 -68q2 -5 6 -26t11.5 -30.5t23.5 -9.5q12 0 37.5 4.5t39.5 4.5q35 0 67 -15t54 -32.5t57.5 -32.5
+t76.5 -15q43 0 79 15t57.5 32.5t53.5 32.5t67 15q14 0 39.5 -4t38.5 -4q16 0 23 10t11 30t6 25q137 22 137 68zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5
+t103 -385.5z" />
+    <glyph glyph-name="uniF2AC" unicode="&#xf2ac;" horiz-adv-x="1664" 
+d="M848 1408q134 1 240.5 -68.5t163.5 -192.5q27 -58 27 -179q0 -47 -9 -191q14 -7 28 -7q18 0 51 13.5t51 13.5q29 0 56 -18t27 -46q0 -32 -31.5 -54t-69 -31.5t-69 -29t-31.5 -47.5q0 -15 12 -43q37 -82 102.5 -150t144.5 -101q28 -12 80 -23q28 -6 28 -35
+q0 -70 -219 -103q-7 -11 -11 -39t-14 -46.5t-33 -18.5q-20 0 -62 6.5t-64 6.5q-37 0 -62 -5q-32 -5 -63 -22.5t-58 -38t-58 -40.5t-76 -33.5t-99 -13.5q-52 0 -96.5 13.5t-75 33.5t-57.5 40.5t-58 38t-62 22.5q-26 5 -63 5q-24 0 -65.5 -7.5t-58.5 -7.5q-25 0 -35 18.5
+t-14 47.5t-11 40q-219 33 -219 103q0 29 28 35q52 11 80 23q78 32 144.5 101t102.5 150q12 28 12 43q0 28 -31.5 47.5t-69.5 29.5t-69.5 31.5t-31.5 52.5q0 27 26 45.5t55 18.5q15 0 48 -13t53 -13q18 0 32 7q-9 142 -9 190q0 122 27 180q64 137 172 198t264 63z" />
+    <glyph glyph-name="uniF2AD" unicode="&#xf2ad;" 
+d="M1280 388q0 22 -22 27q-67 14 -118 58t-80 109q-7 14 -7 25q0 15 19.5 26t42.5 17t42.5 20.5t19.5 36.5q0 19 -18.5 31.5t-38.5 12.5q-11 0 -31 -8t-32 -8q-4 0 -12 2q5 63 5 115q0 78 -17 114q-36 78 -102.5 121.5t-152.5 43.5q-198 0 -275 -165q-18 -38 -18 -115
+q0 -38 6 -114q-10 -2 -15 -2q-11 0 -31.5 8t-30.5 8q-20 0 -37.5 -12.5t-17.5 -32.5q0 -21 19.5 -35.5t42.5 -20.5t42.5 -17t19.5 -26q0 -11 -7 -25q-64 -138 -198 -167q-22 -5 -22 -27q0 -47 138 -69q2 -5 6 -26t11 -30.5t23 -9.5q13 0 38.5 5t38.5 5q35 0 67.5 -15
+t54.5 -32.5t57.5 -32.5t76.5 -15q43 0 79 15t57.5 32.5t54 32.5t67.5 15q13 0 39 -4.5t39 -4.5q15 0 22.5 9.5t11.5 31t5 24.5q138 22 138 69zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960
+q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="uniF2AE" unicode="&#xf2ae;" horiz-adv-x="2304" 
+d="M2304 1536q-69 -46 -125 -92t-89 -81t-59.5 -71.5t-37.5 -57.5t-22 -44.5t-14 -29.5q-10 -18 -35.5 -136.5t-48.5 -164.5q-15 -29 -50 -60.5t-67.5 -50.5t-72.5 -41t-48 -28q-47 -31 -151 -231q-341 14 -630 -158q-92 -53 -303 -179q47 16 86 31t55 22l15 7
+q71 27 163 64.5t133.5 53.5t108 34.5t142.5 31.5q186 31 465 -7q1 0 10 -3q11 -6 14 -17t-3 -22l-194 -345q-15 -29 -47 -22q-128 24 -354 24q-146 0 -402 -44.5t-392 -46.5q-82 -1 -149 13t-107 37t-61 40t-33 34l-1 1v2q0 6 6 6q138 0 371 55q192 366 374.5 524t383.5 158
+q5 0 14.5 -0.5t38 -5t55 -12t61.5 -24.5t63 -39.5t54 -59t40 -82.5l102 177q2 4 21 42.5t44.5 86.5t61 109.5t84 133.5t100.5 137q66 82 128 141.5t121.5 96.5t92.5 53.5t88 39.5z" />
+    <glyph glyph-name="uniF2B0" unicode="&#xf2b0;" 
+d="M1322 640q0 -45 -5 -76l-236 14l224 -78q-19 -73 -58 -141l-214 103l177 -158q-44 -61 -107 -108l-157 178l103 -215q-61 -37 -140 -59l-79 228l14 -240q-38 -6 -76 -6t-76 6l14 238l-78 -226q-74 19 -140 59l103 215l-157 -178q-59 43 -108 108l178 158l-214 -104
+q-39 69 -58 141l224 79l-237 -14q-5 42 -5 76q0 35 5 77l238 -14l-225 79q19 73 58 140l214 -104l-177 159q46 61 107 108l158 -178l-103 215q67 39 140 58l77 -224l-13 236q36 6 75 6q38 0 76 -6l-14 -237l78 225q74 -19 140 -59l-103 -214l158 178q61 -47 107 -108
+l-177 -159l213 104q37 -62 58 -141l-224 -78l237 14q5 -31 5 -77zM1352 640q0 160 -78.5 295.5t-213 214t-292.5 78.5q-119 0 -227 -46.5t-186.5 -125t-124.5 -187.5t-46 -229q0 -119 46 -228t124.5 -187.5t186.5 -125t227 -46.5q158 0 292.5 78.5t213 214t78.5 294.5z
+M1425 1023v-766l-657 -383l-657 383v766l657 383zM768 -183l708 412v823l-708 411l-708 -411v-823zM1536 1088v-896l-768 -448l-768 448v896l768 448z" />
+    <glyph glyph-name="uniF2B1" unicode="&#xf2b1;" horiz-adv-x="1664" 
+d="M339 1318h691l-26 -72h-665q-110 0 -188.5 -79t-78.5 -189v-771q0 -95 60.5 -169.5t153.5 -93.5q23 -5 98 -5v-72h-45q-140 0 -239.5 100t-99.5 240v771q0 140 99.5 240t239.5 100zM1190 1536h247l-482 -1294q-23 -61 -40.5 -103.5t-45 -98t-54 -93.5t-64.5 -78.5
+t-79.5 -65t-95.5 -41t-116 -18.5v195q163 26 220 182q20 52 20 105q0 54 -20 106l-285 733h228l187 -585zM1664 978v-1111h-795q37 55 45 73h678v1038q0 85 -49.5 155t-129.5 99l25 67q101 -34 163.5 -123.5t62.5 -197.5z" />
+    <glyph glyph-name="uniF2B2" unicode="&#xf2b2;" horiz-adv-x="1792" 
+d="M852 1227q0 -29 -17 -52.5t-45 -23.5t-45 23.5t-17 52.5t17 52.5t45 23.5t45 -23.5t17 -52.5zM688 -149v114q0 30 -20.5 51.5t-50.5 21.5t-50 -21.5t-20 -51.5v-114q0 -30 20.5 -52t49.5 -22q30 0 50.5 22t20.5 52zM860 -149v114q0 30 -20 51.5t-50 21.5t-50.5 -21.5
+t-20.5 -51.5v-114q0 -30 20.5 -52t50.5 -22q29 0 49.5 22t20.5 52zM1034 -149v114q0 30 -20.5 51.5t-50.5 21.5t-50.5 -21.5t-20.5 -51.5v-114q0 -30 20.5 -52t50.5 -22t50.5 22t20.5 52zM1208 -149v114q0 30 -20.5 51.5t-50.5 21.5t-50.5 -21.5t-20.5 -51.5v-114
+q0 -30 20.5 -52t50.5 -22t50.5 22t20.5 52zM1476 535q-84 -160 -232 -259.5t-323 -99.5q-123 0 -229.5 51.5t-178.5 137t-113 197.5t-41 232q0 88 21 174q-104 -175 -104 -390q0 -162 65 -312t185 -251q30 57 91 57q56 0 86 -50q32 50 87 50q56 0 86 -50q32 50 87 50t87 -50
+q30 50 86 50q28 0 52.5 -15.5t37.5 -40.5q112 94 177 231.5t73 287.5zM1326 564q0 75 -72 75q-17 0 -47 -6q-95 -19 -149 -19q-226 0 -226 243q0 86 30 204q-83 -127 -83 -275q0 -150 89 -260.5t235 -110.5q111 0 210 70q13 48 13 79zM884 1223q0 50 -32 89.5t-81 39.5
+t-81 -39.5t-32 -89.5q0 -51 31.5 -90.5t81.5 -39.5t81.5 39.5t31.5 90.5zM1513 884q0 96 -37.5 179t-113 137t-173.5 54q-77 0 -149 -35t-127 -94q-48 -159 -48 -268q0 -104 45.5 -157t147.5 -53q53 0 142 19q36 6 53 6q51 0 77.5 -28t26.5 -80q0 -26 -4 -46
+q75 68 117.5 165.5t42.5 200.5zM1792 667q0 -111 -33.5 -249.5t-93.5 -204.5q-58 -64 -195 -142.5t-228 -104.5l-4 -1v-114q0 -43 -29.5 -75t-72.5 -32q-56 0 -86 50q-32 -50 -87 -50t-87 50q-30 -50 -86 -50q-55 0 -87 50q-30 -50 -86 -50q-47 0 -75 33.5t-28 81.5
+q-90 -68 -198 -68q-118 0 -211 80q54 1 106 20q-113 31 -182 127q32 -7 71 -7q89 0 164 46q-192 192 -240 306q-24 56 -24 160q0 57 9 125.5t31.5 146.5t55 141t86.5 105t120 42q59 0 81 -52q19 29 42 54q2 3 12 13t13 16q10 15 23 38t25 42t28 39q87 111 211.5 177
+t260.5 66q35 0 62 -4q59 64 146 64q83 0 140 -57q5 -5 5 -12q0 -5 -6 -13.5t-12.5 -16t-16 -17l-10.5 -10.5q17 -6 36 -18t19 -24q0 -6 -16 -25q157 -138 197 -378q25 30 60 30q45 0 100 -49q90 -80 90 -279z" />
+    <glyph glyph-name="uniF2B3" unicode="&#xf2b3;" 
+d="M917 631q0 33 -6 64h-362v-132h217q-12 -76 -74.5 -120.5t-142.5 -44.5q-99 0 -169 71.5t-70 170.5t70 170.5t169 71.5q93 0 153 -59l104 101q-108 100 -257 100q-160 0 -272 -112.5t-112 -271.5t112 -271.5t272 -112.5q165 0 266.5 105t101.5 270zM1262 585h109v110
+h-109v110h-110v-110h-110v-110h110v-110h110v110zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="uniF2B4" unicode="&#xf2b4;" 
+d="M1536 1024v-839q0 -48 -49 -62q-174 -52 -338 -52q-73 0 -215.5 29.5t-227.5 29.5q-164 0 -370 -48v-338h-160v1368q-63 25 -101 81t-38 124q0 91 64 155t155 64t155 -64t64 -155q0 -68 -38 -124t-101 -81v-68q190 44 343 44q99 0 198 -15q14 -2 111.5 -22.5t149.5 -20.5
+q77 0 165 18q11 2 80 21t89 19q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="uniF2B5" unicode="&#xf2b5;" horiz-adv-x="2304" 
+d="M192 384q40 0 56 32t0 64t-56 32t-56 -32t0 -64t56 -32zM1665 442q-10 13 -38.5 50t-41.5 54t-38 49t-42.5 53t-40.5 47t-45 49l-125 -140q-83 -94 -208.5 -92t-205.5 98q-57 69 -56.5 158t58.5 157l177 206q-22 11 -51 16.5t-47.5 6t-56.5 -0.5t-49 -1q-92 0 -158 -66
+l-158 -158h-155v-544q5 0 21 0.5t22 0t19.5 -2t20.5 -4.5t17.5 -8.5t18.5 -13.5l297 -292q115 -111 227 -111q78 0 125 47q57 -20 112.5 8t72.5 85q74 -6 127 44q20 18 36 45.5t14 50.5q10 -10 43 -10q43 0 77 21t49.5 53t12 71.5t-30.5 73.5zM1824 384h96v512h-93l-157 180
+q-66 76 -169 76h-167q-89 0 -146 -67l-209 -243q-28 -33 -28 -75t27 -75q43 -51 110 -52t111 49l193 218q25 23 53.5 21.5t47 -27t8.5 -56.5q16 -19 56 -63t60 -68q29 -36 82.5 -105.5t64.5 -84.5q52 -66 60 -140zM2112 384q40 0 56 32t0 64t-56 32t-56 -32t0 -64t56 -32z
+M2304 960v-640q0 -26 -19 -45t-45 -19h-434q-27 -65 -82 -106.5t-125 -51.5q-33 -48 -80.5 -81.5t-102.5 -45.5q-42 -53 -104.5 -81.5t-128.5 -24.5q-60 -34 -126 -39.5t-127.5 14t-117 53.5t-103.5 81l-287 282h-358q-26 0 -45 19t-19 45v672q0 26 19 45t45 19h421
+q14 14 47 48t47.5 48t44 40t50.5 37.5t51 25.5t62 19.5t68 5.5h117q99 0 181 -56q82 56 181 56h167q35 0 67 -6t56.5 -14.5t51.5 -26.5t44.5 -31t43 -39.5t39 -42t41 -48t41.5 -48.5h355q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="uniF2B6" unicode="&#xf2b6;" horiz-adv-x="1792" 
+d="M1792 882v-978q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v978q0 15 11 24q8 7 39 34.5t41.5 36t45.5 37.5t70 55.5t96 73t143.5 107t192.5 140.5q5 4 52.5 40t71.5 52.5t64 35t69 18.5t69 -18.5t65 -35.5t71 -52t52 -40q110 -80 192.5 -140.5t143.5 -107
+t96 -73t70 -55.5t45.5 -37.5t41.5 -36t39 -34.5q11 -9 11 -24zM1228 297q263 191 345 252q11 8 12.5 20.5t-6.5 23.5l-38 52q-8 11 -21 12.5t-24 -6.5q-231 -169 -343 -250q-5 -3 -52 -39t-71.5 -52.5t-64.5 -35t-69 -18.5t-69 18.5t-64.5 35t-71.5 52.5t-52 39
+q-186 134 -343 250q-11 8 -24 6.5t-21 -12.5l-38 -52q-8 -11 -6.5 -23.5t12.5 -20.5q82 -61 345 -252q10 -8 50 -38t65 -47t64 -39.5t77.5 -33.5t75.5 -11t75.5 11t79 34.5t64.5 39.5t65 47.5t48 36.5z" />
+    <glyph glyph-name="uniF2B7" unicode="&#xf2b7;" horiz-adv-x="1792" 
+d="M1474 623l39 -51q8 -11 6.5 -23.5t-11.5 -20.5q-43 -34 -126.5 -98.5t-146.5 -113t-67 -51.5q-39 -32 -60 -48t-60.5 -41t-76.5 -36.5t-74 -11.5h-1h-1q-37 0 -74 11.5t-76 36.5t-61 41.5t-60 47.5q-5 4 -65 50.5t-143.5 111t-122.5 94.5q-11 8 -12.5 20.5t6.5 23.5
+l37 52q8 11 21.5 13t24.5 -7q94 -73 306 -236q5 -4 43.5 -35t60.5 -46.5t56.5 -32.5t58.5 -17h1h1q24 0 58.5 17t56.5 32.5t60.5 46.5t43.5 35q258 198 313 242q11 8 24 6.5t21 -12.5zM1664 -96v928q-90 83 -159 139q-91 74 -389 304q-3 2 -43 35t-61 48t-56 32.5t-59 17.5
+h-1h-1q-24 0 -59 -17.5t-56 -32.5t-61 -48t-43 -35q-215 -166 -315.5 -245.5t-129.5 -104t-82 -74.5q-14 -12 -21 -19v-928q0 -13 9.5 -22.5t22.5 -9.5h1472q13 0 22.5 9.5t9.5 22.5zM1792 832v-928q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v928q0 56 41 94
+q123 114 350 290.5t233 181.5q36 30 59 47.5t61.5 42t76 36.5t74.5 12h1h1q37 0 74.5 -12t76 -36.5t61.5 -42t59 -47.5q43 -36 156 -122t226 -177t201 -173q41 -38 41 -94z" />
+    <glyph glyph-name="uniF2B8" unicode="&#xf2b8;" 
+d="M330 1l202 -214l-34 236l-216 213zM556 -225l274 218l-11 245l-300 -215zM245 413l227 -213l-48 327l-245 204zM495 189l317 214l-14 324l-352 -200zM843 178l95 -80l-2 239l-103 79q0 -1 1 -8.5t0 -12t-5 -7.5l-78 -52l85 -70q7 -6 7 -88zM138 930l256 -200l-68 465
+l-279 173zM1173 267l15 234l-230 -164l2 -240zM417 722l373 194l-19 441l-423 -163zM1270 357l20 233l-226 142l-2 -105l144 -95q6 -4 4 -9l-7 -119zM1461 496l30 222l-179 -128l-20 -228zM1273 329l-71 49l-8 -117q0 -5 -4 -8l-234 -187q-7 -5 -14 0l-98 83l7 -161
+q0 -5 -4 -8l-293 -234q-4 -2 -6 -2q-8 2 -8 3l-228 242q-4 4 -59 277q-2 7 5 11l61 37q-94 86 -95 92l-72 351q-2 7 6 12l94 45q-133 100 -135 108l-96 466q-2 10 7 13l433 135q5 0 8 -1l317 -153q6 -4 6 -9l20 -463q0 -7 -6 -10l-118 -61l126 -85q5 -2 5 -8l5 -123l121 74
+q5 4 11 0l84 -56l3 110q0 6 5 9l206 126q6 3 11 0l245 -135q4 -4 5 -7t-6.5 -60t-17.5 -124.5t-10 -70.5q0 -5 -4 -7l-191 -153q-6 -5 -13 0z" />
+    <glyph glyph-name="uniF2B9" unicode="&#xf2b9;" horiz-adv-x="1664" 
+d="M1201 298q0 57 -5.5 107t-21 100.5t-39.5 86t-64 58t-91 22.5q-6 -4 -33.5 -20.5t-42.5 -24.5t-40.5 -20t-49 -17t-46.5 -5t-46.5 5t-49 17t-40.5 20t-42.5 24.5t-33.5 20.5q-51 0 -91 -22.5t-64 -58t-39.5 -86t-21 -100.5t-5.5 -107q0 -73 42 -121.5t103 -48.5h576
+q61 0 103 48.5t42 121.5zM1028 892q0 108 -76.5 184t-183.5 76t-183.5 -76t-76.5 -184q0 -107 76.5 -183t183.5 -76t183.5 76t76.5 183zM1664 352v-192q0 -14 -9 -23t-23 -9h-96v-224q0 -66 -47 -113t-113 -47h-1216q-66 0 -113 47t-47 113v1472q0 66 47 113t113 47h1216
+q66 0 113 -47t47 -113v-224h96q14 0 23 -9t9 -23v-192q0 -14 -9 -23t-23 -9h-96v-128h96q14 0 23 -9t9 -23v-192q0 -14 -9 -23t-23 -9h-96v-128h96q14 0 23 -9t9 -23z" />
+    <glyph glyph-name="uniF2BA" unicode="&#xf2ba;" horiz-adv-x="1664" 
+d="M1028 892q0 -107 -76.5 -183t-183.5 -76t-183.5 76t-76.5 183q0 108 76.5 184t183.5 76t183.5 -76t76.5 -184zM980 672q46 0 82.5 -17t60 -47.5t39.5 -67t24 -81t11.5 -82.5t3.5 -79q0 -67 -39.5 -118.5t-105.5 -51.5h-576q-66 0 -105.5 51.5t-39.5 118.5q0 48 4.5 93.5
+t18.5 98.5t36.5 91.5t63 64.5t93.5 26h5q7 -4 32 -19.5t35.5 -21t33 -17t37 -16t35 -9t39.5 -4.5t39.5 4.5t35 9t37 16t33 17t35.5 21t32 19.5zM1664 928q0 -13 -9.5 -22.5t-22.5 -9.5h-96v-128h96q13 0 22.5 -9.5t9.5 -22.5v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-96v-128h96
+q13 0 22.5 -9.5t9.5 -22.5v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-96v-224q0 -66 -47 -113t-113 -47h-1216q-66 0 -113 47t-47 113v1472q0 66 47 113t113 47h1216q66 0 113 -47t47 -113v-224h96q13 0 22.5 -9.5t9.5 -22.5v-192zM1408 -96v1472q0 13 -9.5 22.5t-22.5 9.5h-1216
+q-13 0 -22.5 -9.5t-9.5 -22.5v-1472q0 -13 9.5 -22.5t22.5 -9.5h1216q13 0 22.5 9.5t9.5 22.5z" />
+    <glyph glyph-name="uniF2BB" unicode="&#xf2bb;" horiz-adv-x="2048" 
+d="M1024 405q0 64 -9 117.5t-29.5 103t-60.5 78t-97 28.5q-6 -4 -30 -18t-37.5 -21.5t-35.5 -17.5t-43 -14.5t-42 -4.5t-42 4.5t-43 14.5t-35.5 17.5t-37.5 21.5t-30 18q-57 0 -97 -28.5t-60.5 -78t-29.5 -103t-9 -117.5t37 -106.5t91 -42.5h512q54 0 91 42.5t37 106.5z
+M867 925q0 94 -66.5 160.5t-160.5 66.5t-160.5 -66.5t-66.5 -160.5t66.5 -160.5t160.5 -66.5t160.5 66.5t66.5 160.5zM1792 416v64q0 14 -9 23t-23 9h-576q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h576q14 0 23 9t9 23zM1792 676v56q0 15 -10.5 25.5t-25.5 10.5h-568
+q-15 0 -25.5 -10.5t-10.5 -25.5v-56q0 -15 10.5 -25.5t25.5 -10.5h568q15 0 25.5 10.5t10.5 25.5zM1792 928v64q0 14 -9 23t-23 9h-576q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h576q14 0 23 9t9 23zM2048 1248v-1216q0 -66 -47 -113t-113 -47h-352v96q0 14 -9 23t-23 9
+h-64q-14 0 -23 -9t-9 -23v-96h-768v96q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-96h-352q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1728q66 0 113 -47t47 -113z" />
+    <glyph glyph-name="uniF2BC" unicode="&#xf2bc;" horiz-adv-x="2048" 
+d="M1024 405q0 -64 -37 -106.5t-91 -42.5h-512q-54 0 -91 42.5t-37 106.5t9 117.5t29.5 103t60.5 78t97 28.5q6 -4 30 -18t37.5 -21.5t35.5 -17.5t43 -14.5t42 -4.5t42 4.5t43 14.5t35.5 17.5t37.5 21.5t30 18q57 0 97 -28.5t60.5 -78t29.5 -103t9 -117.5zM867 925
+q0 -94 -66.5 -160.5t-160.5 -66.5t-160.5 66.5t-66.5 160.5t66.5 160.5t160.5 66.5t160.5 -66.5t66.5 -160.5zM1792 480v-64q0 -14 -9 -23t-23 -9h-576q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h576q14 0 23 -9t9 -23zM1792 732v-56q0 -15 -10.5 -25.5t-25.5 -10.5h-568
+q-15 0 -25.5 10.5t-10.5 25.5v56q0 15 10.5 25.5t25.5 10.5h568q15 0 25.5 -10.5t10.5 -25.5zM1792 992v-64q0 -14 -9 -23t-23 -9h-576q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h576q14 0 23 -9t9 -23zM1920 32v1216q0 13 -9.5 22.5t-22.5 9.5h-1728q-13 0 -22.5 -9.5
+t-9.5 -22.5v-1216q0 -13 9.5 -22.5t22.5 -9.5h352v96q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-96h768v96q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-96h352q13 0 22.5 9.5t9.5 22.5zM2048 1248v-1216q0 -66 -47 -113t-113 -47h-1728q-66 0 -113 47t-47 113v1216q0 66 47 113
+t113 47h1728q66 0 113 -47t47 -113z" />
+    <glyph glyph-name="uniF2BD" unicode="&#xf2bd;" horiz-adv-x="1792" 
+d="M1523 197q-22 155 -87.5 257.5t-184.5 118.5q-67 -74 -159.5 -115.5t-195.5 -41.5t-195.5 41.5t-159.5 115.5q-119 -16 -184.5 -118.5t-87.5 -257.5q106 -150 271 -237.5t356 -87.5t356 87.5t271 237.5zM1280 896q0 159 -112.5 271.5t-271.5 112.5t-271.5 -112.5
+t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5zM1792 640q0 -182 -71 -347.5t-190.5 -286t-285.5 -191.5t-349 -71q-182 0 -348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
+    <glyph glyph-name="uniF2BE" unicode="&#xf2be;" horiz-adv-x="1792" 
+d="M896 1536q182 0 348 -71t286 -191t191 -286t71 -348q0 -181 -70.5 -347t-190.5 -286t-286 -191.5t-349 -71.5t-349 71t-285.5 191.5t-190.5 286t-71 347.5t71 348t191 286t286 191t348 71zM1515 185q149 205 149 455q0 156 -61 298t-164 245t-245 164t-298 61t-298 -61
+t-245 -164t-164 -245t-61 -298q0 -250 149 -455q66 327 306 327q131 -128 313 -128t313 128q240 0 306 -327zM1280 832q0 159 -112.5 271.5t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5z" />
+    <glyph glyph-name="uniF2C0" unicode="&#xf2c0;" 
+d="M1201 752q47 -14 89.5 -38t89 -73t79.5 -115.5t55 -172t22 -236.5q0 -154 -100 -263.5t-241 -109.5h-854q-141 0 -241 109.5t-100 263.5q0 131 22 236.5t55 172t79.5 115.5t89 73t89.5 38q-79 125 -79 272q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5
+t198.5 -40.5t163.5 -109.5t109.5 -163.5t40.5 -198.5q0 -147 -79 -272zM768 1408q-159 0 -271.5 -112.5t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5t-112.5 271.5t-271.5 112.5zM1195 -128q88 0 150.5 71.5t62.5 173.5q0 239 -78.5 377t-225.5 145
+q-145 -127 -336 -127t-336 127q-147 -7 -225.5 -145t-78.5 -377q0 -102 62.5 -173.5t150.5 -71.5h854z" />
+    <glyph glyph-name="uniF2C1" unicode="&#xf2c1;" horiz-adv-x="1280" 
+d="M1024 278q0 -64 -37 -107t-91 -43h-512q-54 0 -91 43t-37 107t9 118t29.5 104t61 78.5t96.5 28.5q80 -75 188 -75t188 75q56 0 96.5 -28.5t61 -78.5t29.5 -104t9 -118zM870 797q0 -94 -67.5 -160.5t-162.5 -66.5t-162.5 66.5t-67.5 160.5t67.5 160.5t162.5 66.5
+t162.5 -66.5t67.5 -160.5zM1152 -96v1376h-1024v-1376q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5zM1280 1376v-1472q0 -66 -47 -113t-113 -47h-960q-66 0 -113 47t-47 113v1472q0 66 47 113t113 47h352v-96q0 -14 9 -23t23 -9h192q14 0 23 9t9 23v96h352
+q66 0 113 -47t47 -113z" />
+    <glyph glyph-name="uniF2C2" unicode="&#xf2c2;" horiz-adv-x="2048" 
+d="M896 324q0 54 -7.5 100.5t-24.5 90t-51 68.5t-81 25q-64 -64 -156 -64t-156 64q-47 0 -81 -25t-51 -68.5t-24.5 -90t-7.5 -100.5q0 -55 31.5 -93.5t75.5 -38.5h426q44 0 75.5 38.5t31.5 93.5zM768 768q0 80 -56 136t-136 56t-136 -56t-56 -136t56 -136t136 -56t136 56
+t56 136zM1792 288v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704q14 0 23 9t9 23zM1408 544v64q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1792 544v64q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23
+v-64q0 -14 9 -23t23 -9h192q14 0 23 9t9 23zM1792 800v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704q14 0 23 9t9 23zM128 1152h1792v96q0 14 -9 23t-23 9h-1728q-14 0 -23 -9t-9 -23v-96zM2048 1248v-1216q0 -66 -47 -113t-113 -47h-1728
+q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1728q66 0 113 -47t47 -113z" />
+    <glyph glyph-name="uniF2C3" unicode="&#xf2c3;" horiz-adv-x="2048" 
+d="M896 324q0 -55 -31.5 -93.5t-75.5 -38.5h-426q-44 0 -75.5 38.5t-31.5 93.5q0 54 7.5 100.5t24.5 90t51 68.5t81 25q64 -64 156 -64t156 64q47 0 81 -25t51 -68.5t24.5 -90t7.5 -100.5zM768 768q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136z
+M1792 352v-64q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h704q14 0 23 -9t9 -23zM1408 608v-64q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h320q14 0 23 -9t9 -23zM1792 608v-64q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v64
+q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1792 864v-64q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h704q14 0 23 -9t9 -23zM1920 32v1120h-1792v-1120q0 -13 9.5 -22.5t22.5 -9.5h1728q13 0 22.5 9.5t9.5 22.5zM2048 1248v-1216q0 -66 -47 -113t-113 -47
+h-1728q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1728q66 0 113 -47t47 -113z" />
+    <glyph glyph-name="uniF2C4" unicode="&#xf2c4;" horiz-adv-x="1792" 
+d="M1255 749q0 318 -105 474.5t-330 156.5q-222 0 -326 -157t-104 -474q0 -316 104 -471.5t326 -155.5q74 0 131 17q-22 43 -39 73t-44 65t-53.5 56.5t-63 36t-77.5 14.5q-46 0 -79 -16l-49 97q105 91 276 91q132 0 215.5 -54t150.5 -155q67 149 67 402zM1645 117h117
+q3 -27 -2 -67t-26.5 -95t-58 -100.5t-107 -78t-162.5 -32.5q-71 0 -130.5 19t-105.5 56t-79 78t-66 96q-97 -27 -205 -27q-150 0 -292.5 58t-253 158.5t-178 249t-67.5 317.5q0 170 67.5 319.5t178.5 250.5t253.5 159t291.5 58q121 0 238.5 -36t217 -106t176 -164.5
+t119.5 -219t43 -261.5q0 -190 -80.5 -347.5t-218.5 -264.5q47 -70 93.5 -106.5t104.5 -36.5q61 0 94 37.5t38 85.5z" />
+    <glyph glyph-name="uniF2C5" unicode="&#xf2c5;" horiz-adv-x="2304" 
+d="M453 -101q0 -21 -16 -37.5t-37 -16.5q-1 0 -13 3q-63 15 -162 140q-225 284 -225 676q0 341 213 614q39 51 95 103.5t94 52.5q19 0 35 -13.5t16 -32.5q0 -27 -63 -90q-98 -102 -147 -184q-119 -199 -119 -449q0 -281 123 -491q50 -85 136 -173q2 -3 14.5 -16t19.5 -21
+t17 -20.5t14.5 -23.5t4.5 -21zM1796 33q0 -29 -17.5 -48.5t-46.5 -19.5h-1081q-26 0 -45 19t-19 45q0 29 17.5 48.5t46.5 19.5h1081q26 0 45 -19t19 -45zM1581 644q0 -134 -67 -233q-25 -38 -69.5 -78.5t-83.5 -60.5q-16 -10 -27 -10q-7 0 -15 6t-8 12q0 9 19 30t42 46
+t42 67.5t19 88.5q0 76 -35 130q-29 42 -46 42q-3 0 -3 -5q0 -12 7.5 -35.5t7.5 -36.5q0 -22 -21.5 -35t-44.5 -13q-66 0 -66 76q0 15 1.5 44t1.5 44q0 25 -10 46q-13 25 -42 53.5t-51 28.5q-5 0 -7 -0.5t-3.5 -2.5t-1.5 -6q0 -2 16 -26t16 -54q0 -37 -19 -68t-46 -54
+t-53.5 -46t-45.5 -54t-19 -68q0 -98 42 -160q29 -43 79 -63q16 -5 17 -10q1 -2 1 -5q0 -16 -18 -16q-6 0 -33 11q-119 43 -195 139.5t-76 218.5q0 55 24.5 115.5t60 115t70.5 108.5t59.5 113.5t24.5 111.5q0 53 -25 94q-29 48 -56 64q-19 9 -19 21q0 20 41 20q50 0 110 -29
+q41 -19 71 -44.5t49.5 -51t33.5 -62.5t22 -69t16 -80q0 -1 3 -17.5t4.5 -25t5.5 -25t9 -27t11 -21.5t14.5 -16.5t18.5 -5.5q23 0 37 14t14 37q0 25 -20 67t-20 52t10 10q27 0 93 -70q72 -76 102.5 -156t30.5 -186zM2304 615q0 -274 -138 -503q-19 -32 -48 -72t-68 -86.5
+t-81 -77t-74 -30.5q-16 0 -31 15.5t-15 31.5q0 15 29 50.5t68.5 77t48.5 52.5q183 230 183 531q0 131 -20.5 235t-72.5 211q-58 119 -163 228q-2 3 -13 13.5t-16.5 16.5t-15 17.5t-15 20t-9.5 18.5t-4 19q0 19 16 35.5t35 16.5q70 0 196 -169q98 -131 146 -273t60 -314
+q2 -42 2 -64z" />
+    <glyph glyph-name="uniF2C6" unicode="&#xf2c6;" horiz-adv-x="1792" 
+d="M1189 229l147 693q9 44 -10.5 63t-51.5 7l-864 -333q-29 -11 -39.5 -25t-2.5 -26.5t32 -19.5l221 -69l513 323q21 14 32 6q7 -5 -4 -15l-415 -375v0v0l-16 -228q23 0 45 22l108 104l224 -165q64 -36 81 38zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71
+t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
+    <glyph glyph-name="uniF2C7" unicode="&#xf2c7;" horiz-adv-x="1024" 
+d="M640 192q0 -80 -56 -136t-136 -56t-136 56t-56 136q0 60 35 110t93 71v907h128v-907q58 -21 93 -71t35 -110zM768 192q0 77 -34 144t-94 112v768q0 80 -56 136t-136 56t-136 -56t-56 -136v-768q-60 -45 -94 -112t-34 -144q0 -133 93.5 -226.5t226.5 -93.5t226.5 93.5
+t93.5 226.5zM896 192q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 182 128 313v711q0 133 93.5 226.5t226.5 93.5t226.5 -93.5t93.5 -226.5v-711q128 -131 128 -313zM1024 768v-128h-192v128h192zM1024 1024v-128h-192v128h192zM1024 1280v-128h-192
+v128h192z" />
+    <glyph glyph-name="uniF2C8" unicode="&#xf2c8;" horiz-adv-x="1024" 
+d="M640 192q0 -80 -56 -136t-136 -56t-136 56t-56 136q0 60 35 110t93 71v651h128v-651q58 -21 93 -71t35 -110zM768 192q0 77 -34 144t-94 112v768q0 80 -56 136t-136 56t-136 -56t-56 -136v-768q-60 -45 -94 -112t-34 -144q0 -133 93.5 -226.5t226.5 -93.5t226.5 93.5
+t93.5 226.5zM896 192q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 182 128 313v711q0 133 93.5 226.5t226.5 93.5t226.5 -93.5t93.5 -226.5v-711q128 -131 128 -313zM1024 768v-128h-192v128h192zM1024 1024v-128h-192v128h192zM1024 1280v-128h-192
+v128h192z" />
+    <glyph glyph-name="uniF2C9" unicode="&#xf2c9;" horiz-adv-x="1024" 
+d="M640 192q0 -80 -56 -136t-136 -56t-136 56t-56 136q0 60 35 110t93 71v395h128v-395q58 -21 93 -71t35 -110zM768 192q0 77 -34 144t-94 112v768q0 80 -56 136t-136 56t-136 -56t-56 -136v-768q-60 -45 -94 -112t-34 -144q0 -133 93.5 -226.5t226.5 -93.5t226.5 93.5
+t93.5 226.5zM896 192q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 182 128 313v711q0 133 93.5 226.5t226.5 93.5t226.5 -93.5t93.5 -226.5v-711q128 -131 128 -313zM1024 768v-128h-192v128h192zM1024 1024v-128h-192v128h192zM1024 1280v-128h-192
+v128h192z" />
+    <glyph glyph-name="uniF2CA" unicode="&#xf2ca;" horiz-adv-x="1024" 
+d="M640 192q0 -80 -56 -136t-136 -56t-136 56t-56 136q0 60 35 110t93 71v139h128v-139q58 -21 93 -71t35 -110zM768 192q0 77 -34 144t-94 112v768q0 80 -56 136t-136 56t-136 -56t-56 -136v-768q-60 -45 -94 -112t-34 -144q0 -133 93.5 -226.5t226.5 -93.5t226.5 93.5
+t93.5 226.5zM896 192q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 182 128 313v711q0 133 93.5 226.5t226.5 93.5t226.5 -93.5t93.5 -226.5v-711q128 -131 128 -313zM1024 768v-128h-192v128h192zM1024 1024v-128h-192v128h192zM1024 1280v-128h-192
+v128h192z" />
+    <glyph glyph-name="uniF2CB" unicode="&#xf2cb;" horiz-adv-x="1024" 
+d="M640 192q0 -80 -56 -136t-136 -56t-136 56t-56 136q0 79 56 135.5t136 56.5t136 -56.5t56 -135.5zM768 192q0 77 -34 144t-94 112v768q0 80 -56 136t-136 56t-136 -56t-56 -136v-768q-60 -45 -94 -112t-34 -144q0 -133 93.5 -226.5t226.5 -93.5t226.5 93.5t93.5 226.5z
+M896 192q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 182 128 313v711q0 133 93.5 226.5t226.5 93.5t226.5 -93.5t93.5 -226.5v-711q128 -131 128 -313zM1024 768v-128h-192v128h192zM1024 1024v-128h-192v128h192zM1024 1280v-128h-192v128h192z" />
+    <glyph glyph-name="uniF2CC" unicode="&#xf2cc;" horiz-adv-x="1920" 
+d="M1433 1287q10 -10 10 -23t-10 -23l-626 -626q-10 -10 -23 -10t-23 10l-82 82q-10 10 -10 23t10 23l44 44q-72 91 -81.5 207t46.5 215q-74 71 -176 71q-106 0 -181 -75t-75 -181v-1280h-256v1280q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5q106 0 201 -41
+t166 -115q94 39 197 24.5t185 -79.5l44 44q10 10 23 10t23 -10zM1344 1024q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1600 896q-26 0 -45 19t-19 45t19 45t45 19t45 -19t19 -45t-19 -45t-45 -19zM1856 1024q26 0 45 -19t19 -45t-19 -45t-45 -19
+t-45 19t-19 45t19 45t45 19zM1216 896q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1408 832q0 26 19 45t45 19t45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45zM1728 896q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1088 768
+q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1344 640q-26 0 -45 19t-19 45t19 45t45 19t45 -19t19 -45t-19 -45t-45 -19zM1600 768q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1216 512q-26 0 -45 19t-19 45t19 45t45 19t45 -19
+t19 -45t-19 -45t-45 -19zM1472 640q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1088 512q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1344 512q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1216 384
+q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1088 256q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19z" />
+    <glyph glyph-name="uniF2CD" unicode="&#xf2cd;" horiz-adv-x="1792" 
+d="M1664 448v-192q0 -169 -128 -286v-194q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v118q-63 -22 -128 -22h-768q-65 0 -128 22v-110q0 -17 -9.5 -28.5t-22.5 -11.5h-64q-13 0 -22.5 11.5t-9.5 28.5v186q-128 117 -128 286v192h1536zM704 864q0 -14 -9 -23t-23 -9t-23 9
+t-9 23t9 23t23 9t23 -9t9 -23zM768 928q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM704 992q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM832 992q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM768 1056q0 -14 -9 -23t-23 -9t-23 9
+t-9 23t9 23t23 9t23 -9t9 -23zM704 1120q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM1792 608v-64q0 -14 -9 -23t-23 -9h-1728q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96v640q0 106 75 181t181 75q108 0 184 -78q46 19 98 12t93 -39l22 22q11 11 22 0l42 -42
+q11 -11 0 -22l-314 -314q-11 -11 -22 0l-42 42q-11 11 0 22l22 22q-36 46 -40.5 104t23.5 108q-37 35 -88 35q-53 0 -90.5 -37.5t-37.5 -90.5v-640h1504q14 0 23 -9t9 -23zM896 1056q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM832 1120q0 -14 -9 -23t-23 -9
+t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM768 1184q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM960 1120q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM896 1184q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM832 1248q0 -14 -9 -23
+t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM1024 1184q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM960 1248q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM1088 1248q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23z" />
+    <glyph glyph-name="uniF2CE" unicode="&#xf2ce;" 
+d="M994 344q0 -86 -17 -197q-31 -215 -55 -313q-22 -90 -152 -90t-152 90q-24 98 -55 313q-17 110 -17 197q0 168 224 168t224 -168zM1536 768q0 -240 -134 -434t-350 -280q-8 -3 -15 3t-6 15q7 48 10 66q4 32 6 47q1 9 9 12q159 81 255.5 234t96.5 337q0 180 -91 330.5
+t-247 234.5t-337 74q-124 -7 -237 -61t-193.5 -140.5t-128 -202t-46.5 -240.5q1 -184 99 -336.5t257 -231.5q7 -3 9 -12q3 -21 6 -45q1 -9 5 -32.5t6 -35.5q1 -9 -6.5 -15t-15.5 -2q-148 58 -261 169.5t-173.5 264t-52.5 319.5q7 143 66 273.5t154.5 227t225 157.5t272.5 70
+q164 10 315.5 -46.5t261 -160.5t175 -250.5t65.5 -308.5zM994 800q0 -93 -65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5zM1282 768q0 -122 -53.5 -228.5t-146.5 -177.5q-8 -6 -16 -2t-10 14q-6 52 -29 92q-7 10 3 20
+q58 54 91 127t33 155q0 111 -58.5 204t-157.5 141.5t-212 36.5q-133 -15 -229 -113t-109 -231q-10 -92 23.5 -176t98.5 -144q10 -10 3 -20q-24 -41 -29 -93q-2 -9 -10 -13t-16 2q-95 74 -148.5 183t-51.5 234q3 131 69 244t177 181.5t241 74.5q144 7 268 -60t196.5 -187.5
+t72.5 -263.5z" />
+    <glyph glyph-name="uniF2D0" unicode="&#xf2d0;" horiz-adv-x="1792" 
+d="M256 128h1280v768h-1280v-768zM1792 1248v-1216q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1472q66 0 113 -47t47 -113z" />
+    <glyph glyph-name="uniF2D1" unicode="&#xf2d1;" horiz-adv-x="1792" 
+d="M1792 224v-192q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v192q0 66 47 113t113 47h1472q66 0 113 -47t47 -113z" />
+    <glyph glyph-name="uniF2D2" unicode="&#xf2d2;" horiz-adv-x="2048" 
+d="M256 0h768v512h-768v-512zM1280 512h512v768h-768v-256h96q66 0 113 -47t47 -113v-352zM2048 1376v-960q0 -66 -47 -113t-113 -47h-608v-352q0 -66 -47 -113t-113 -47h-960q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h608v352q0 66 47 113t113 47h960q66 0 113 -47
+t47 -113z" />
+    <glyph glyph-name="uniF2D3" unicode="&#xf2d3;" horiz-adv-x="1792" 
+d="M1175 215l146 146q10 10 10 23t-10 23l-233 233l233 233q10 10 10 23t-10 23l-146 146q-10 10 -23 10t-23 -10l-233 -233l-233 233q-10 10 -23 10t-23 -10l-146 -146q-10 -10 -10 -23t10 -23l233 -233l-233 -233q-10 -10 -10 -23t10 -23l146 -146q10 -10 23 -10t23 10
+l233 233l233 -233q10 -10 23 -10t23 10zM1792 1248v-1216q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1472q66 0 113 -47t47 -113z" />
+    <glyph glyph-name="uniF2D4" unicode="&#xf2d4;" horiz-adv-x="1792" 
+d="M1257 425l-146 -146q-10 -10 -23 -10t-23 10l-169 169l-169 -169q-10 -10 -23 -10t-23 10l-146 146q-10 10 -10 23t10 23l169 169l-169 169q-10 10 -10 23t10 23l146 146q10 10 23 10t23 -10l169 -169l169 169q10 10 23 10t23 -10l146 -146q10 -10 10 -23t-10 -23
+l-169 -169l169 -169q10 -10 10 -23t-10 -23zM256 128h1280v1024h-1280v-1024zM1792 1248v-1216q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1472q66 0 113 -47t47 -113z" />
+    <glyph glyph-name="uniF2D5" unicode="&#xf2d5;" horiz-adv-x="1792" 
+d="M1070 358l306 564h-654l-306 -564h654zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
+    <glyph glyph-name="uniF2D6" unicode="&#xf2d6;" horiz-adv-x="1794" 
+d="M1291 1060q-15 17 -35 8.5t-26 -28.5t5 -38q14 -17 40 -14.5t34 20.5t-18 52zM895 814q-8 -8 -19.5 -8t-18.5 8q-8 8 -8 19t8 18q7 8 18.5 8t19.5 -8q7 -7 7 -18t-7 -19zM1060 740l-35 -35q-12 -13 -29.5 -13t-30.5 13l-38 38q-12 13 -12 30t12 30l35 35q12 12 29.5 12
+t30.5 -12l38 -39q12 -12 12 -29.5t-12 -29.5zM951 870q-7 -8 -18.5 -8t-19.5 8q-7 8 -7 19t7 19q8 8 19 8t19 -8t8 -19t-8 -19zM1354 968q-34 -64 -107.5 -85.5t-127.5 16.5q-38 28 -61 66.5t-21 87.5t39 92t75.5 53t70.5 -5t70 -51q2 -2 13 -12.5t14.5 -13.5t13 -13.5
+t12.5 -15.5t10 -15.5t8.5 -18t4 -18.5t1 -21t-5 -22t-9.5 -24zM1555 486q3 20 -8.5 34.5t-27.5 21.5t-33 17t-23 20q-40 71 -84 98.5t-113 11.5q19 13 40 18.5t33 4.5l12 -1q2 45 -34 90q6 20 6.5 40.5t-2.5 30.5l-3 10q43 24 71 65t34 91q10 84 -43 150.5t-137 76.5
+q-60 7 -114 -18.5t-82 -74.5q-30 -51 -33.5 -101t14.5 -87t43.5 -64t56.5 -42q-45 4 -88 36t-57 88q-28 108 32 222q-16 21 -29 32q-50 0 -89 -19q19 24 42 37t36 14l13 1q0 50 -13 78q-10 21 -32.5 28.5t-47 -3.5t-37.5 -40q2 4 4 7q-7 -28 -6.5 -75.5t19 -117t48.5 -122.5
+q-25 -14 -47 -36q-35 -16 -85.5 -70.5t-84.5 -101.5l-33 -46q-90 -34 -181 -125.5t-75 -162.5q1 -16 11 -27q-15 -12 -30 -30q-21 -25 -21 -54t21.5 -40t63.5 6q41 19 77 49.5t55 60.5q-2 2 -6.5 5t-20.5 7.5t-33 3.5q23 5 51 12.5t40 10t27.5 6t26 4t23.5 0.5q14 -7 22 34
+q7 37 7 90q0 102 -40 150q106 -103 101 -219q-1 -29 -15 -50t-27 -27l-13 -6q-4 -7 -19 -32t-26 -45.5t-26.5 -52t-25 -61t-17 -63t-6.5 -66.5t10 -63q-35 54 -37 80q-22 -24 -34.5 -39t-33.5 -42t-30.5 -46t-16.5 -41t-0.5 -38t25.5 -27q45 -25 144 64t190.5 221.5
+t122.5 228.5q86 52 145 115.5t86 119.5q47 -93 154 -178q104 -83 167 -80q39 2 46 43zM1794 640q0 -182 -71 -348t-191 -286t-286.5 -191t-348.5 -71t-348.5 71t-286.5 191t-191 286t-71 348t71 348t191 286t286.5 191t348.5 71t348.5 -71t286.5 -191t191 -286t71 -348z" />
+    <glyph glyph-name="uniF2D7" unicode="&#xf2d7;" 
+d="M518 1353v-655q103 -1 191.5 1.5t125.5 5.5l37 3q68 2 90.5 24.5t39.5 94.5l33 142h103l-14 -322l7 -319h-103l-29 127q-15 68 -45 93t-84 26q-87 8 -352 8v-556q0 -78 43.5 -115.5t133.5 -37.5h357q35 0 59.5 2t55 7.5t54 18t48.5 32t46 50.5t39 73l93 216h89
+q-6 -37 -31.5 -252t-30.5 -276q-146 5 -263.5 8t-162.5 4h-44h-628l-376 -12v102l127 25q67 13 91.5 37t25.5 79l8 643q3 402 -8 645q-2 61 -25.5 84t-91.5 36l-127 24v102l376 -12h702q139 0 374 27q-6 -68 -14 -194.5t-12 -219.5l-5 -92h-93l-32 124q-31 121 -74 179.5
+t-113 58.5h-548q-28 0 -35.5 -8.5t-7.5 -30.5z" />
+    <glyph glyph-name="uniF2D8" unicode="&#xf2d8;" 
+d="M922 739v-182q0 -4 0.5 -15t0 -15l-1.5 -12t-3.5 -11.5t-6.5 -7.5t-11 -5.5t-16 -1.5v309q9 0 16 -1t11 -5t6.5 -5.5t3.5 -9.5t1 -10.5v-13.5v-14zM1238 643v-121q0 -1 0.5 -12.5t0 -15.5t-2.5 -11.5t-7.5 -10.5t-13.5 -3q-9 0 -14 9q-4 10 -4 165v7v8.5v9t1.5 8.5l3.5 7
+t5 5.5t8 1.5q6 0 10 -1.5t6.5 -4.5t4 -6t2 -8.5t0.5 -8v-9.5v-9zM180 407h122v472h-122v-472zM614 407h106v472h-159l-28 -221q-20 148 -32 221h-158v-472h107v312l45 -312h76l43 319v-319zM1039 712q0 67 -5 90q-3 16 -11 28.5t-17 20.5t-25 14t-26.5 8.5t-31 4t-29 1.5
+h-29.5h-12h-91v-472h56q169 -1 197 24.5t25 180.5q-1 62 -1 100zM1356 515v133q0 29 -2 45t-9.5 33.5t-24.5 25t-46 7.5q-46 0 -77 -34v154h-117v-472h110l7 30q30 -36 77 -36q50 0 66 30.5t16 83.5zM1536 1248v-1216q0 -66 -47 -113t-113 -47h-1216q-66 0 -113 47t-47 113
+v1216q0 66 47 113t113 47h1216q66 0 113 -47t47 -113z" />
+    <glyph glyph-name="uniF2D9" unicode="&#xf2d9;" horiz-adv-x="2176" 
+d="M1143 -197q-6 1 -11 4q-13 8 -36 23t-86 65t-116.5 104.5t-112 140t-89.5 172.5q-17 3 -175 37q66 -213 235 -362t391 -184zM502 409l168 -28q-25 76 -41 167.5t-19 145.5l-4 53q-84 -82 -121 -224q5 -65 17 -114zM612 1018q-43 -64 -77 -148q44 46 74 68zM2049 584
+q0 161 -62 307t-167.5 252t-250.5 168.5t-304 62.5q-147 0 -281 -52.5t-240 -148.5q-30 -58 -45 -160q60 51 143 83.5t158.5 43t143 13.5t108.5 -1l40 -3q33 -1 53 -15.5t24.5 -33t6.5 -37t-1 -28.5q-126 11 -227.5 0.5t-183 -43.5t-142.5 -71.5t-131 -98.5
+q4 -36 11.5 -92.5t35.5 -178t62 -179.5q123 -6 247.5 14.5t214.5 53.5t162.5 67t109.5 59l37 24q22 16 39.5 20.5t30.5 -5t17 -34.5q14 -97 -39 -121q-208 -97 -467 -134q-135 -20 -317 -16q41 -96 110 -176.5t137 -127t130.5 -79t101.5 -43.5l39 -12q143 -23 263 15
+q195 99 314 289t119 418zM2123 621q-14 -135 -40 -212q-70 -208 -181.5 -346.5t-318.5 -253.5q-48 -33 -82 -44q-72 -26 -163 -16q-36 -3 -73 -3q-283 0 -504.5 173t-295.5 442q-1 0 -4 0.5t-5 0.5q-6 -50 2.5 -112.5t26 -115t36 -98t31.5 -71.5l14 -26q8 -12 54 -82
+q-71 38 -124.5 106.5t-78.5 140t-39.5 137t-17.5 107.5l-2 42q-5 2 -33.5 12.5t-48.5 18t-53 20.5t-57.5 25t-50 25.5t-42.5 27t-25 25.5q19 -10 50.5 -25.5t113 -45.5t145.5 -38l2 32q11 149 94 290q41 202 176 365q28 115 81 214q15 28 32 45t49 32q158 74 303.5 104
+t302 11t306.5 -97q220 -115 333 -336t87 -474z" />
+    <glyph glyph-name="uniF2DA" unicode="&#xf2da;" horiz-adv-x="1792" 
+d="M1341 752q29 44 -6.5 129.5t-121.5 142.5q-58 39 -125.5 53.5t-118 4.5t-68.5 -37q-12 -23 -4.5 -28t42.5 -10q23 -3 38.5 -5t44.5 -9.5t56 -17.5q36 -13 67.5 -31.5t53 -37t40 -38.5t30.5 -38t22 -34.5t16.5 -28.5t12 -18.5t10.5 -6t11 9.5zM1704 178
+q-52 -127 -148.5 -220t-214.5 -141.5t-253 -60.5t-266 13.5t-251 91t-210 161.5t-141.5 235.5t-46.5 303.5q1 41 8.5 84.5t12.5 64t24 80.5t23 73q-51 -208 1 -397t173 -318t291 -206t346 -83t349 74.5t289 244.5q20 27 18 14q0 -4 -4 -14zM1465 627q0 -104 -40.5 -199
+t-108.5 -164t-162 -109.5t-198 -40.5t-198 40.5t-162 109.5t-108.5 164t-40.5 199t40.5 199t108.5 164t162 109.5t198 40.5t198 -40.5t162 -109.5t108.5 -164t40.5 -199zM1752 915q-65 147 -180.5 251t-253 153.5t-292 53.5t-301 -36.5t-275.5 -129t-220 -211.5t-131 -297
+t-10 -373q-49 161 -51.5 311.5t35.5 272.5t109 227t165.5 180.5t207 126t232 71t242.5 9t236 -54t216 -124.5t178 -197q33 -50 62 -121t31 -112zM1690 573q12 244 -136.5 416t-396.5 240q-8 0 -10 5t24 8q125 -4 230 -50t173 -120t116 -168.5t58.5 -199t-1 -208
+t-61.5 -197.5t-122.5 -167t-185 -117.5t-248.5 -46.5q108 30 201.5 80t174 123t129.5 176.5t55 225.5z" />
+    <glyph glyph-name="uniF2DB" unicode="&#xf2db;" 
+d="M192 256v-128h-112q-16 0 -16 16v16h-48q-16 0 -16 16v32q0 16 16 16h48v16q0 16 16 16h112zM192 512v-128h-112q-16 0 -16 16v16h-48q-16 0 -16 16v32q0 16 16 16h48v16q0 16 16 16h112zM192 768v-128h-112q-16 0 -16 16v16h-48q-16 0 -16 16v32q0 16 16 16h48v16
+q0 16 16 16h112zM192 1024v-128h-112q-16 0 -16 16v16h-48q-16 0 -16 16v32q0 16 16 16h48v16q0 16 16 16h112zM192 1280v-128h-112q-16 0 -16 16v16h-48q-16 0 -16 16v32q0 16 16 16h48v16q0 16 16 16h112zM1280 1440v-1472q0 -40 -28 -68t-68 -28h-832q-40 0 -68 28
+t-28 68v1472q0 40 28 68t68 28h832q40 0 68 -28t28 -68zM1536 208v-32q0 -16 -16 -16h-48v-16q0 -16 -16 -16h-112v128h112q16 0 16 -16v-16h48q16 0 16 -16zM1536 464v-32q0 -16 -16 -16h-48v-16q0 -16 -16 -16h-112v128h112q16 0 16 -16v-16h48q16 0 16 -16zM1536 720v-32
+q0 -16 -16 -16h-48v-16q0 -16 -16 -16h-112v128h112q16 0 16 -16v-16h48q16 0 16 -16zM1536 976v-32q0 -16 -16 -16h-48v-16q0 -16 -16 -16h-112v128h112q16 0 16 -16v-16h48q16 0 16 -16zM1536 1232v-32q0 -16 -16 -16h-48v-16q0 -16 -16 -16h-112v128h112q16 0 16 -16v-16
+h48q16 0 16 -16z" />
+    <glyph glyph-name="uniF2DC" unicode="&#xf2dc;" horiz-adv-x="1664" 
+d="M1566 419l-167 -33l186 -107q23 -13 29.5 -38.5t-6.5 -48.5q-14 -23 -39 -29.5t-48 6.5l-186 106l55 -160q13 -38 -12 -63.5t-60.5 -20.5t-48.5 42l-102 300l-271 156v-313l208 -238q16 -18 17 -39t-11 -36.5t-28.5 -25t-37 -5.5t-36.5 22l-112 128v-214q0 -26 -19 -45
+t-45 -19t-45 19t-19 45v214l-112 -128q-16 -18 -36.5 -22t-37 5.5t-28.5 25t-11 36.5t17 39l208 238v313l-271 -156l-102 -300q-13 -37 -48.5 -42t-60.5 20.5t-12 63.5l55 160l-186 -106q-23 -13 -48 -6.5t-39 29.5q-13 23 -6.5 48.5t29.5 38.5l186 107l-167 33
+q-29 6 -42 29t-8.5 46.5t25.5 40t50 10.5l310 -62l271 157l-271 157l-310 -62q-4 -1 -13 -1q-27 0 -44 18t-19 40t11 43t40 26l167 33l-186 107q-23 13 -29.5 38.5t6.5 48.5t39 30t48 -7l186 -106l-55 160q-13 38 12 63.5t60.5 20.5t48.5 -42l102 -300l271 -156v313
+l-208 238q-16 18 -17 39t11 36.5t28.5 25t37 5.5t36.5 -22l112 -128v214q0 26 19 45t45 19t45 -19t19 -45v-214l112 128q16 18 36.5 22t37 -5.5t28.5 -25t11 -36.5t-17 -39l-208 -238v-313l271 156l102 300q13 37 48.5 42t60.5 -20.5t12 -63.5l-55 -160l186 106
+q23 13 48 6.5t39 -29.5q13 -23 6.5 -48.5t-29.5 -38.5l-186 -107l167 -33q27 -5 40 -26t11 -43t-19 -40t-44 -18q-9 0 -13 1l-310 62l-271 -157l271 -157l310 62q29 6 50 -10.5t25.5 -40t-8.5 -46.5t-42 -29z" />
+    <glyph glyph-name="uniF2DD" unicode="&#xf2dd;" horiz-adv-x="1792" 
+d="M1473 607q7 118 -33 226.5t-113 189t-177 131t-221 57.5q-116 7 -225.5 -32t-192 -110.5t-135 -175t-59.5 -220.5q-7 -118 33 -226.5t113 -189t177.5 -131t221.5 -57.5q155 -9 293 59t224 195.5t94 283.5zM1792 1536l-349 -348q120 -117 180.5 -272t50.5 -321
+q-11 -183 -102 -339t-241 -255.5t-332 -124.5l-999 -132l347 347q-120 116 -180.5 271.5t-50.5 321.5q11 184 102 340t241.5 255.5t332.5 124.5q167 22 500 66t500 66z" />
+    <glyph glyph-name="uniF2DE" unicode="&#xf2de;" horiz-adv-x="1792" 
+d="M948 508l163 -329h-51l-175 350l-171 -350h-49l179 374l-78 33l21 49l240 -102l-21 -50zM563 1100l304 -130l-130 -304l-304 130zM907 915l240 -103l-103 -239l-239 102zM1188 765l191 -81l-82 -190l-190 81zM1680 640q0 159 -62 304t-167.5 250.5t-250.5 167.5t-304 62
+t-304 -62t-250.5 -167.5t-167.5 -250.5t-62 -304t62 -304t167.5 -250.5t250.5 -167.5t304 -62t304 62t250.5 167.5t167.5 250.5t62 304zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71
+t286 -191t191 -286t71 -348z" />
+    <glyph glyph-name="uniF2E0" unicode="&#xf2e0;" horiz-adv-x="1920" 
+d="M1334 302q-4 24 -27.5 34t-49.5 10.5t-48.5 12.5t-25.5 38q-5 47 33 139.5t75 181t32 127.5q-14 101 -117 103q-45 1 -75 -16l-3 -2l-5 -2.5t-4.5 -2t-5 -2t-5 -0.5t-6 1.5t-6 3.5t-6.5 5q-3 2 -9 8.5t-9 9t-8.5 7.5t-9.5 7.5t-9.5 5.5t-11 4.5t-11.5 2.5q-30 5 -48 -3
+t-45 -31q-1 -1 -9 -8.5t-12.5 -11t-15 -10t-16.5 -5.5t-17 3q-54 27 -84 40q-41 18 -94 -5t-76 -65q-16 -28 -41 -98.5t-43.5 -132.5t-40 -134t-21.5 -73q-22 -69 18.5 -119t110.5 -46q30 2 50.5 15t38.5 46q7 13 79 199.5t77 194.5q6 11 21.5 18t29.5 0q27 -15 21 -53
+q-2 -18 -51 -139.5t-50 -132.5q-6 -38 19.5 -56.5t60.5 -7t55 49.5q4 8 45.5 92t81.5 163.5t46 88.5q20 29 41 28q29 0 25 -38q-2 -16 -65.5 -147.5t-70.5 -159.5q-12 -53 13 -103t74 -74q17 -9 51 -15.5t71.5 -8t62.5 14t20 48.5zM383 86q3 -15 -5 -27.5t-23 -15.5
+q-14 -3 -26.5 5t-15.5 23q-3 14 5 27t22 16t27 -5t16 -23zM953 -177q12 -17 8.5 -37.5t-20.5 -32.5t-37.5 -8t-32.5 21q-11 17 -7.5 37.5t20.5 32.5t37.5 8t31.5 -21zM177 635q-18 -27 -49.5 -33t-57.5 13q-26 18 -32 50t12 58q18 27 49.5 33t57.5 -12q26 -19 32 -50.5
+t-12 -58.5zM1467 -42q19 -28 13 -61.5t-34 -52.5t-60.5 -13t-51.5 34t-13 61t33 53q28 19 60.5 13t52.5 -34zM1579 562q69 -113 42.5 -244.5t-134.5 -207.5q-90 -63 -199 -60q-20 -80 -84.5 -127t-143.5 -44.5t-140 57.5q-12 -9 -13 -10q-103 -71 -225 -48.5t-193 126.5
+q-50 73 -53 164q-83 14 -142.5 70.5t-80.5 128t-2 152t81 138.5q-36 60 -38 128t24.5 125t79.5 98.5t121 50.5q32 85 99 148t146.5 91.5t168 17t159.5 -66.5q72 21 140 17.5t128.5 -36t104.5 -80t67.5 -115t17.5 -140.5q52 -16 87 -57t45.5 -89t-5.5 -99.5t-58 -87.5z
+M455 1222q14 -20 9.5 -44.5t-24.5 -38.5q-19 -14 -43.5 -9.5t-37.5 24.5q-14 20 -9.5 44.5t24.5 38.5q19 14 43.5 9.5t37.5 -24.5zM614 1503q4 -16 -5 -30.5t-26 -18.5t-31 5.5t-18 26.5q-3 17 6.5 31t25.5 18q17 4 31 -5.5t17 -26.5zM1800 555q4 -20 -6.5 -37t-30.5 -21
+q-19 -4 -36 6.5t-21 30.5t6.5 37t30.5 22q20 4 36.5 -7.5t20.5 -30.5zM1136 1448q16 -27 8.5 -58.5t-35.5 -47.5q-27 -16 -57.5 -8.5t-46.5 34.5q-16 28 -8.5 59t34.5 48t58 9t47 -36zM1882 792q4 -15 -4 -27.5t-23 -16.5q-15 -3 -27.5 5.5t-15.5 22.5q-3 15 5 28t23 16
+q14 3 26.5 -5t15.5 -23zM1691 1033q15 -22 10.5 -49t-26.5 -43q-22 -15 -49 -10t-42 27t-10 49t27 43t48.5 11t41.5 -28z" />
+    <glyph glyph-name="uniF2E1" unicode="&#xf2e1;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="uniF2E2" unicode="&#xf2e2;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="uniF2E3" unicode="&#xf2e3;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="uniF2E4" unicode="&#xf2e4;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="uniF2E5" unicode="&#xf2e5;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="uniF2E6" unicode="&#xf2e6;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="uniF2E7" unicode="&#xf2e7;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="_698" unicode="&#xf2e8;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="uniF2E9" unicode="&#xf2e9;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="uniF2EA" unicode="&#xf2ea;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="uniF2EB" unicode="&#xf2eb;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="uniF2EC" unicode="&#xf2ec;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="uniF2ED" unicode="&#xf2ed;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="uniF2EE" unicode="&#xf2ee;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="lessequal" unicode="&#xf500;" horiz-adv-x="1792" 
+ />
+  </font>
+</defs></svg>
diff --git a/ruoyi-admin/src/main/resources/static/fonts/fontawesome-webfont.ttf b/ruoyi-admin/src/main/resources/static/fonts/fontawesome-webfont.ttf
new file mode 100644
index 0000000..35acda2
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/fonts/fontawesome-webfont.ttf
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/fonts/fontawesome-webfont.woff b/ruoyi-admin/src/main/resources/static/fonts/fontawesome-webfont.woff
new file mode 100644
index 0000000..400014a
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/fonts/fontawesome-webfont.woff
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/fonts/fontawesome-webfont.woff2 b/ruoyi-admin/src/main/resources/static/fonts/fontawesome-webfont.woff2
new file mode 100644
index 0000000..4d13fc6
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/fonts/fontawesome-webfont.woff2
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/fonts/glyphicons-halflings-regular.eot b/ruoyi-admin/src/main/resources/static/fonts/glyphicons-halflings-regular.eot
new file mode 100644
index 0000000..b93a495
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/fonts/glyphicons-halflings-regular.eot
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/fonts/glyphicons-halflings-regular.svg b/ruoyi-admin/src/main/resources/static/fonts/glyphicons-halflings-regular.svg
new file mode 100644
index 0000000..187805a
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/fonts/glyphicons-halflings-regular.svg
@@ -0,0 +1,288 @@
+<?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 xmlns="http://www.w3.org/2000/svg">
+<metadata></metadata>
+<defs>
+<font id="glyphicons_halflingsregular" horiz-adv-x="1200" >
+<font-face units-per-em="1200" ascent="960" descent="-240" />
+<missing-glyph horiz-adv-x="500" />
+<glyph horiz-adv-x="0" />
+<glyph horiz-adv-x="400" />
+<glyph unicode=" " />
+<glyph unicode="*" d="M600 1100q15 0 34 -1.5t30 -3.5l11 -1q10 -2 17.5 -10.5t7.5 -18.5v-224l158 158q7 7 18 8t19 -6l106 -106q7 -8 6 -19t-8 -18l-158 -158h224q10 0 18.5 -7.5t10.5 -17.5q6 -41 6 -75q0 -15 -1.5 -34t-3.5 -30l-1 -11q-2 -10 -10.5 -17.5t-18.5 -7.5h-224l158 -158 q7 -7 8 -18t-6 -19l-106 -106q-8 -7 -19 -6t-18 8l-158 158v-224q0 -10 -7.5 -18.5t-17.5 -10.5q-41 -6 -75 -6q-15 0 -34 1.5t-30 3.5l-11 1q-10 2 -17.5 10.5t-7.5 18.5v224l-158 -158q-7 -7 -18 -8t-19 6l-106 106q-7 8 -6 19t8 18l158 158h-224q-10 0 -18.5 7.5 t-10.5 17.5q-6 41 -6 75q0 15 1.5 34t3.5 30l1 11q2 10 10.5 17.5t18.5 7.5h224l-158 158q-7 7 -8 18t6 19l106 106q8 7 19 6t18 -8l158 -158v224q0 10 7.5 18.5t17.5 10.5q41 6 75 6z" />
+<glyph unicode="+" d="M450 1100h200q21 0 35.5 -14.5t14.5 -35.5v-350h350q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-350v-350q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v350h-350q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5 h350v350q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xa0;" />
+<glyph unicode="&#xa5;" d="M825 1100h250q10 0 12.5 -5t-5.5 -13l-364 -364q-6 -6 -11 -18h268q10 0 13 -6t-3 -14l-120 -160q-6 -8 -18 -14t-22 -6h-125v-100h275q10 0 13 -6t-3 -14l-120 -160q-6 -8 -18 -14t-22 -6h-125v-174q0 -11 -7.5 -18.5t-18.5 -7.5h-148q-11 0 -18.5 7.5t-7.5 18.5v174 h-275q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h125v100h-275q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h118q-5 12 -11 18l-364 364q-8 8 -5.5 13t12.5 5h250q25 0 43 -18l164 -164q8 -8 18 -8t18 8l164 164q18 18 43 18z" />
+<glyph unicode="&#x2000;" horiz-adv-x="650" />
+<glyph unicode="&#x2001;" horiz-adv-x="1300" />
+<glyph unicode="&#x2002;" horiz-adv-x="650" />
+<glyph unicode="&#x2003;" horiz-adv-x="1300" />
+<glyph unicode="&#x2004;" horiz-adv-x="433" />
+<glyph unicode="&#x2005;" horiz-adv-x="325" />
+<glyph unicode="&#x2006;" horiz-adv-x="216" />
+<glyph unicode="&#x2007;" horiz-adv-x="216" />
+<glyph unicode="&#x2008;" horiz-adv-x="162" />
+<glyph unicode="&#x2009;" horiz-adv-x="260" />
+<glyph unicode="&#x200a;" horiz-adv-x="72" />
+<glyph unicode="&#x202f;" horiz-adv-x="260" />
+<glyph unicode="&#x205f;" horiz-adv-x="325" />
+<glyph unicode="&#x20ac;" d="M744 1198q242 0 354 -189q60 -104 66 -209h-181q0 45 -17.5 82.5t-43.5 61.5t-58 40.5t-60.5 24t-51.5 7.5q-19 0 -40.5 -5.5t-49.5 -20.5t-53 -38t-49 -62.5t-39 -89.5h379l-100 -100h-300q-6 -50 -6 -100h406l-100 -100h-300q9 -74 33 -132t52.5 -91t61.5 -54.5t59 -29 t47 -7.5q22 0 50.5 7.5t60.5 24.5t58 41t43.5 61t17.5 80h174q-30 -171 -128 -278q-107 -117 -274 -117q-206 0 -324 158q-36 48 -69 133t-45 204h-217l100 100h112q1 47 6 100h-218l100 100h134q20 87 51 153.5t62 103.5q117 141 297 141z" />
+<glyph unicode="&#x20bd;" d="M428 1200h350q67 0 120 -13t86 -31t57 -49.5t35 -56.5t17 -64.5t6.5 -60.5t0.5 -57v-16.5v-16.5q0 -36 -0.5 -57t-6.5 -61t-17 -65t-35 -57t-57 -50.5t-86 -31.5t-120 -13h-178l-2 -100h288q10 0 13 -6t-3 -14l-120 -160q-6 -8 -18 -14t-22 -6h-138v-175q0 -11 -5.5 -18 t-15.5 -7h-149q-10 0 -17.5 7.5t-7.5 17.5v175h-267q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h117v100h-267q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h117v475q0 10 7.5 17.5t17.5 7.5zM600 1000v-300h203q64 0 86.5 33t22.5 119q0 84 -22.5 116t-86.5 32h-203z" />
+<glyph unicode="&#x2212;" d="M250 700h800q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#x231b;" d="M1000 1200v-150q0 -21 -14.5 -35.5t-35.5 -14.5h-50v-100q0 -91 -49.5 -165.5t-130.5 -109.5q81 -35 130.5 -109.5t49.5 -165.5v-150h50q21 0 35.5 -14.5t14.5 -35.5v-150h-800v150q0 21 14.5 35.5t35.5 14.5h50v150q0 91 49.5 165.5t130.5 109.5q-81 35 -130.5 109.5 t-49.5 165.5v100h-50q-21 0 -35.5 14.5t-14.5 35.5v150h800zM400 1000v-100q0 -60 32.5 -109.5t87.5 -73.5q28 -12 44 -37t16 -55t-16 -55t-44 -37q-55 -24 -87.5 -73.5t-32.5 -109.5v-150h400v150q0 60 -32.5 109.5t-87.5 73.5q-28 12 -44 37t-16 55t16 55t44 37 q55 24 87.5 73.5t32.5 109.5v100h-400z" />
+<glyph unicode="&#x25fc;" horiz-adv-x="500" d="M0 0z" />
+<glyph unicode="&#x2601;" d="M503 1089q110 0 200.5 -59.5t134.5 -156.5q44 14 90 14q120 0 205 -86.5t85 -206.5q0 -121 -85 -207.5t-205 -86.5h-750q-79 0 -135.5 57t-56.5 137q0 69 42.5 122.5t108.5 67.5q-2 12 -2 37q0 153 108 260.5t260 107.5z" />
+<glyph unicode="&#x26fa;" d="M774 1193.5q16 -9.5 20.5 -27t-5.5 -33.5l-136 -187l467 -746h30q20 0 35 -18.5t15 -39.5v-42h-1200v42q0 21 15 39.5t35 18.5h30l468 746l-135 183q-10 16 -5.5 34t20.5 28t34 5.5t28 -20.5l111 -148l112 150q9 16 27 20.5t34 -5zM600 200h377l-182 112l-195 534v-646z " />
+<glyph unicode="&#x2709;" d="M25 1100h1150q10 0 12.5 -5t-5.5 -13l-564 -567q-8 -8 -18 -8t-18 8l-564 567q-8 8 -5.5 13t12.5 5zM18 882l264 -264q8 -8 8 -18t-8 -18l-264 -264q-8 -8 -13 -5.5t-5 12.5v550q0 10 5 12.5t13 -5.5zM918 618l264 264q8 8 13 5.5t5 -12.5v-550q0 -10 -5 -12.5t-13 5.5 l-264 264q-8 8 -8 18t8 18zM818 482l364 -364q8 -8 5.5 -13t-12.5 -5h-1150q-10 0 -12.5 5t5.5 13l364 364q8 8 18 8t18 -8l164 -164q8 -8 18 -8t18 8l164 164q8 8 18 8t18 -8z" />
+<glyph unicode="&#x270f;" d="M1011 1210q19 0 33 -13l153 -153q13 -14 13 -33t-13 -33l-99 -92l-214 214l95 96q13 14 32 14zM1013 800l-615 -614l-214 214l614 614zM317 96l-333 -112l110 335z" />
+<glyph unicode="&#xe001;" d="M700 650v-550h250q21 0 35.5 -14.5t14.5 -35.5v-50h-800v50q0 21 14.5 35.5t35.5 14.5h250v550l-500 550h1200z" />
+<glyph unicode="&#xe002;" d="M368 1017l645 163q39 15 63 0t24 -49v-831q0 -55 -41.5 -95.5t-111.5 -63.5q-79 -25 -147 -4.5t-86 75t25.5 111.5t122.5 82q72 24 138 8v521l-600 -155v-606q0 -42 -44 -90t-109 -69q-79 -26 -147 -5.5t-86 75.5t25.5 111.5t122.5 82.5q72 24 138 7v639q0 38 14.5 59 t53.5 34z" />
+<glyph unicode="&#xe003;" d="M500 1191q100 0 191 -39t156.5 -104.5t104.5 -156.5t39 -191l-1 -2l1 -5q0 -141 -78 -262l275 -274q23 -26 22.5 -44.5t-22.5 -42.5l-59 -58q-26 -20 -46.5 -20t-39.5 20l-275 274q-119 -77 -261 -77l-5 1l-2 -1q-100 0 -191 39t-156.5 104.5t-104.5 156.5t-39 191 t39 191t104.5 156.5t156.5 104.5t191 39zM500 1022q-88 0 -162 -43t-117 -117t-43 -162t43 -162t117 -117t162 -43t162 43t117 117t43 162t-43 162t-117 117t-162 43z" />
+<glyph unicode="&#xe005;" d="M649 949q48 68 109.5 104t121.5 38.5t118.5 -20t102.5 -64t71 -100.5t27 -123q0 -57 -33.5 -117.5t-94 -124.5t-126.5 -127.5t-150 -152.5t-146 -174q-62 85 -145.5 174t-150 152.5t-126.5 127.5t-93.5 124.5t-33.5 117.5q0 64 28 123t73 100.5t104 64t119 20 t120.5 -38.5t104.5 -104z" />
+<glyph unicode="&#xe006;" d="M407 800l131 353q7 19 17.5 19t17.5 -19l129 -353h421q21 0 24 -8.5t-14 -20.5l-342 -249l130 -401q7 -20 -0.5 -25.5t-24.5 6.5l-343 246l-342 -247q-17 -12 -24.5 -6.5t-0.5 25.5l130 400l-347 251q-17 12 -14 20.5t23 8.5h429z" />
+<glyph unicode="&#xe007;" d="M407 800l131 353q7 19 17.5 19t17.5 -19l129 -353h421q21 0 24 -8.5t-14 -20.5l-342 -249l130 -401q7 -20 -0.5 -25.5t-24.5 6.5l-343 246l-342 -247q-17 -12 -24.5 -6.5t-0.5 25.5l130 400l-347 251q-17 12 -14 20.5t23 8.5h429zM477 700h-240l197 -142l-74 -226 l193 139l195 -140l-74 229l192 140h-234l-78 211z" />
+<glyph unicode="&#xe008;" d="M600 1200q124 0 212 -88t88 -212v-250q0 -46 -31 -98t-69 -52v-75q0 -10 6 -21.5t15 -17.5l358 -230q9 -5 15 -16.5t6 -21.5v-93q0 -10 -7.5 -17.5t-17.5 -7.5h-1150q-10 0 -17.5 7.5t-7.5 17.5v93q0 10 6 21.5t15 16.5l358 230q9 6 15 17.5t6 21.5v75q-38 0 -69 52 t-31 98v250q0 124 88 212t212 88z" />
+<glyph unicode="&#xe009;" d="M25 1100h1150q10 0 17.5 -7.5t7.5 -17.5v-1050q0 -10 -7.5 -17.5t-17.5 -7.5h-1150q-10 0 -17.5 7.5t-7.5 17.5v1050q0 10 7.5 17.5t17.5 7.5zM100 1000v-100h100v100h-100zM875 1000h-550q-10 0 -17.5 -7.5t-7.5 -17.5v-350q0 -10 7.5 -17.5t17.5 -7.5h550 q10 0 17.5 7.5t7.5 17.5v350q0 10 -7.5 17.5t-17.5 7.5zM1000 1000v-100h100v100h-100zM100 800v-100h100v100h-100zM1000 800v-100h100v100h-100zM100 600v-100h100v100h-100zM1000 600v-100h100v100h-100zM875 500h-550q-10 0 -17.5 -7.5t-7.5 -17.5v-350q0 -10 7.5 -17.5 t17.5 -7.5h550q10 0 17.5 7.5t7.5 17.5v350q0 10 -7.5 17.5t-17.5 7.5zM100 400v-100h100v100h-100zM1000 400v-100h100v100h-100zM100 200v-100h100v100h-100zM1000 200v-100h100v100h-100z" />
+<glyph unicode="&#xe010;" d="M50 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM650 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400 q0 21 14.5 35.5t35.5 14.5zM50 500h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM650 500h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe011;" d="M50 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200 q0 21 14.5 35.5t35.5 14.5zM850 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM50 700h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200 q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 700h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM850 700h200q21 0 35.5 -14.5t14.5 -35.5v-200 q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM50 300h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 300h200 q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM850 300h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5 t35.5 14.5z" />
+<glyph unicode="&#xe012;" d="M50 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 1100h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v200 q0 21 14.5 35.5t35.5 14.5zM50 700h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 700h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700 q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM50 300h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 300h700q21 0 35.5 -14.5t14.5 -35.5v-200 q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe013;" d="M465 477l571 571q8 8 18 8t17 -8l177 -177q8 -7 8 -17t-8 -18l-783 -784q-7 -8 -17.5 -8t-17.5 8l-384 384q-8 8 -8 18t8 17l177 177q7 8 17 8t18 -8l171 -171q7 -7 18 -7t18 7z" />
+<glyph unicode="&#xe014;" d="M904 1083l178 -179q8 -8 8 -18.5t-8 -17.5l-267 -268l267 -268q8 -7 8 -17.5t-8 -18.5l-178 -178q-8 -8 -18.5 -8t-17.5 8l-268 267l-268 -267q-7 -8 -17.5 -8t-18.5 8l-178 178q-8 8 -8 18.5t8 17.5l267 268l-267 268q-8 7 -8 17.5t8 18.5l178 178q8 8 18.5 8t17.5 -8 l268 -267l268 268q7 7 17.5 7t18.5 -7z" />
+<glyph unicode="&#xe015;" d="M507 1177q98 0 187.5 -38.5t154.5 -103.5t103.5 -154.5t38.5 -187.5q0 -141 -78 -262l300 -299q8 -8 8 -18.5t-8 -18.5l-109 -108q-7 -8 -17.5 -8t-18.5 8l-300 299q-119 -77 -261 -77q-98 0 -188 38.5t-154.5 103t-103 154.5t-38.5 188t38.5 187.5t103 154.5 t154.5 103.5t188 38.5zM506.5 1023q-89.5 0 -165.5 -44t-120 -120.5t-44 -166t44 -165.5t120 -120t165.5 -44t166 44t120.5 120t44 165.5t-44 166t-120.5 120.5t-166 44zM425 900h150q10 0 17.5 -7.5t7.5 -17.5v-75h75q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5 t-17.5 -7.5h-75v-75q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v75h-75q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h75v75q0 10 7.5 17.5t17.5 7.5z" />
+<glyph unicode="&#xe016;" d="M507 1177q98 0 187.5 -38.5t154.5 -103.5t103.5 -154.5t38.5 -187.5q0 -141 -78 -262l300 -299q8 -8 8 -18.5t-8 -18.5l-109 -108q-7 -8 -17.5 -8t-18.5 8l-300 299q-119 -77 -261 -77q-98 0 -188 38.5t-154.5 103t-103 154.5t-38.5 188t38.5 187.5t103 154.5 t154.5 103.5t188 38.5zM506.5 1023q-89.5 0 -165.5 -44t-120 -120.5t-44 -166t44 -165.5t120 -120t165.5 -44t166 44t120.5 120t44 165.5t-44 166t-120.5 120.5t-166 44zM325 800h350q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-350q-10 0 -17.5 7.5 t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5z" />
+<glyph unicode="&#xe017;" d="M550 1200h100q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM800 975v166q167 -62 272 -209.5t105 -331.5q0 -117 -45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5 t-184.5 123t-123 184.5t-45.5 224q0 184 105 331.5t272 209.5v-166q-103 -55 -165 -155t-62 -220q0 -116 57 -214.5t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5q0 120 -62 220t-165 155z" />
+<glyph unicode="&#xe018;" d="M1025 1200h150q10 0 17.5 -7.5t7.5 -17.5v-1150q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v1150q0 10 7.5 17.5t17.5 7.5zM725 800h150q10 0 17.5 -7.5t7.5 -17.5v-750q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v750 q0 10 7.5 17.5t17.5 7.5zM425 500h150q10 0 17.5 -7.5t7.5 -17.5v-450q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v450q0 10 7.5 17.5t17.5 7.5zM125 300h150q10 0 17.5 -7.5t7.5 -17.5v-250q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5 v250q0 10 7.5 17.5t17.5 7.5z" />
+<glyph unicode="&#xe019;" d="M600 1174q33 0 74 -5l38 -152l5 -1q49 -14 94 -39l5 -2l134 80q61 -48 104 -105l-80 -134l3 -5q25 -44 39 -93l1 -6l152 -38q5 -43 5 -73q0 -34 -5 -74l-152 -38l-1 -6q-15 -49 -39 -93l-3 -5l80 -134q-48 -61 -104 -105l-134 81l-5 -3q-44 -25 -94 -39l-5 -2l-38 -151 q-43 -5 -74 -5q-33 0 -74 5l-38 151l-5 2q-49 14 -94 39l-5 3l-134 -81q-60 48 -104 105l80 134l-3 5q-25 45 -38 93l-2 6l-151 38q-6 42 -6 74q0 33 6 73l151 38l2 6q13 48 38 93l3 5l-80 134q47 61 105 105l133 -80l5 2q45 25 94 39l5 1l38 152q43 5 74 5zM600 815 q-89 0 -152 -63t-63 -151.5t63 -151.5t152 -63t152 63t63 151.5t-63 151.5t-152 63z" />
+<glyph unicode="&#xe020;" d="M500 1300h300q41 0 70.5 -29.5t29.5 -70.5v-100h275q10 0 17.5 -7.5t7.5 -17.5v-75h-1100v75q0 10 7.5 17.5t17.5 7.5h275v100q0 41 29.5 70.5t70.5 29.5zM500 1200v-100h300v100h-300zM1100 900v-800q0 -41 -29.5 -70.5t-70.5 -29.5h-700q-41 0 -70.5 29.5t-29.5 70.5 v800h900zM300 800v-700h100v700h-100zM500 800v-700h100v700h-100zM700 800v-700h100v700h-100zM900 800v-700h100v700h-100z" />
+<glyph unicode="&#xe021;" d="M18 618l620 608q8 7 18.5 7t17.5 -7l608 -608q8 -8 5.5 -13t-12.5 -5h-175v-575q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v375h-300v-375q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v575h-175q-10 0 -12.5 5t5.5 13z" />
+<glyph unicode="&#xe022;" d="M600 1200v-400q0 -41 29.5 -70.5t70.5 -29.5h300v-650q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v1100q0 21 14.5 35.5t35.5 14.5h450zM1000 800h-250q-21 0 -35.5 14.5t-14.5 35.5v250z" />
+<glyph unicode="&#xe023;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM525 900h50q10 0 17.5 -7.5t7.5 -17.5v-275h175q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5z" />
+<glyph unicode="&#xe024;" d="M1300 0h-538l-41 400h-242l-41 -400h-538l431 1200h209l-21 -300h162l-20 300h208zM515 800l-27 -300h224l-27 300h-170z" />
+<glyph unicode="&#xe025;" d="M550 1200h200q21 0 35.5 -14.5t14.5 -35.5v-450h191q20 0 25.5 -11.5t-7.5 -27.5l-327 -400q-13 -16 -32 -16t-32 16l-327 400q-13 16 -7.5 27.5t25.5 11.5h191v450q0 21 14.5 35.5t35.5 14.5zM1125 400h50q10 0 17.5 -7.5t7.5 -17.5v-350q0 -10 -7.5 -17.5t-17.5 -7.5 h-1050q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h50q10 0 17.5 -7.5t7.5 -17.5v-175h900v175q0 10 7.5 17.5t17.5 7.5z" />
+<glyph unicode="&#xe026;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM525 900h150q10 0 17.5 -7.5t7.5 -17.5v-275h137q21 0 26 -11.5t-8 -27.5l-223 -275q-13 -16 -32 -16t-32 16l-223 275q-13 16 -8 27.5t26 11.5h137v275q0 10 7.5 17.5t17.5 7.5z " />
+<glyph unicode="&#xe027;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM632 914l223 -275q13 -16 8 -27.5t-26 -11.5h-137v-275q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v275h-137q-21 0 -26 11.5t8 27.5l223 275q13 16 32 16 t32 -16z" />
+<glyph unicode="&#xe028;" d="M225 1200h750q10 0 19.5 -7t12.5 -17l186 -652q7 -24 7 -49v-425q0 -12 -4 -27t-9 -17q-12 -6 -37 -6h-1100q-12 0 -27 4t-17 8q-6 13 -6 38l1 425q0 25 7 49l185 652q3 10 12.5 17t19.5 7zM878 1000h-556q-10 0 -19 -7t-11 -18l-87 -450q-2 -11 4 -18t16 -7h150 q10 0 19.5 -7t11.5 -17l38 -152q2 -10 11.5 -17t19.5 -7h250q10 0 19.5 7t11.5 17l38 152q2 10 11.5 17t19.5 7h150q10 0 16 7t4 18l-87 450q-2 11 -11 18t-19 7z" />
+<glyph unicode="&#xe029;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM540 820l253 -190q17 -12 17 -30t-17 -30l-253 -190q-16 -12 -28 -6.5t-12 26.5v400q0 21 12 26.5t28 -6.5z" />
+<glyph unicode="&#xe030;" d="M947 1060l135 135q7 7 12.5 5t5.5 -13v-362q0 -10 -7.5 -17.5t-17.5 -7.5h-362q-11 0 -13 5.5t5 12.5l133 133q-109 76 -238 76q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5h150q0 -117 -45.5 -224 t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5q192 0 347 -117z" />
+<glyph unicode="&#xe031;" d="M947 1060l135 135q7 7 12.5 5t5.5 -13v-361q0 -11 -7.5 -18.5t-18.5 -7.5h-361q-11 0 -13 5.5t5 12.5l134 134q-110 75 -239 75q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5h-150q0 117 45.5 224t123 184.5t184.5 123t224 45.5q192 0 347 -117zM1027 600h150 q0 -117 -45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5q-192 0 -348 118l-134 -134q-7 -8 -12.5 -5.5t-5.5 12.5v360q0 11 7.5 18.5t18.5 7.5h360q10 0 12.5 -5.5t-5.5 -12.5l-133 -133q110 -76 240 -76q116 0 214.5 57t155.5 155.5t57 214.5z" />
+<glyph unicode="&#xe032;" d="M125 1200h1050q10 0 17.5 -7.5t7.5 -17.5v-1150q0 -10 -7.5 -17.5t-17.5 -7.5h-1050q-10 0 -17.5 7.5t-7.5 17.5v1150q0 10 7.5 17.5t17.5 7.5zM1075 1000h-850q-10 0 -17.5 -7.5t-7.5 -17.5v-850q0 -10 7.5 -17.5t17.5 -7.5h850q10 0 17.5 7.5t7.5 17.5v850 q0 10 -7.5 17.5t-17.5 7.5zM325 900h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 900h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5zM325 700h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 700h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5zM325 500h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 500h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5zM325 300h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 300h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5z" />
+<glyph unicode="&#xe033;" d="M900 800v200q0 83 -58.5 141.5t-141.5 58.5h-300q-82 0 -141 -59t-59 -141v-200h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-600q0 -41 29.5 -70.5t70.5 -29.5h900q41 0 70.5 29.5t29.5 70.5v600q0 41 -29.5 70.5t-70.5 29.5h-100zM400 800v150q0 21 15 35.5t35 14.5h200 q20 0 35 -14.5t15 -35.5v-150h-300z" />
+<glyph unicode="&#xe034;" d="M125 1100h50q10 0 17.5 -7.5t7.5 -17.5v-1075h-100v1075q0 10 7.5 17.5t17.5 7.5zM1075 1052q4 0 9 -2q16 -6 16 -23v-421q0 -6 -3 -12q-33 -59 -66.5 -99t-65.5 -58t-56.5 -24.5t-52.5 -6.5q-26 0 -57.5 6.5t-52.5 13.5t-60 21q-41 15 -63 22.5t-57.5 15t-65.5 7.5 q-85 0 -160 -57q-7 -5 -15 -5q-6 0 -11 3q-14 7 -14 22v438q22 55 82 98.5t119 46.5q23 2 43 0.5t43 -7t32.5 -8.5t38 -13t32.5 -11q41 -14 63.5 -21t57 -14t63.5 -7q103 0 183 87q7 8 18 8z" />
+<glyph unicode="&#xe035;" d="M600 1175q116 0 227 -49.5t192.5 -131t131 -192.5t49.5 -227v-300q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v300q0 127 -70.5 231.5t-184.5 161.5t-245 57t-245 -57t-184.5 -161.5t-70.5 -231.5v-300q0 -10 -7.5 -17.5t-17.5 -7.5h-50 q-10 0 -17.5 7.5t-7.5 17.5v300q0 116 49.5 227t131 192.5t192.5 131t227 49.5zM220 500h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14v460q0 8 6 14t14 6zM820 500h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14v460 q0 8 6 14t14 6z" />
+<glyph unicode="&#xe036;" d="M321 814l258 172q9 6 15 2.5t6 -13.5v-750q0 -10 -6 -13.5t-15 2.5l-258 172q-21 14 -46 14h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h250q25 0 46 14zM900 668l120 120q7 7 17 7t17 -7l34 -34q7 -7 7 -17t-7 -17l-120 -120l120 -120q7 -7 7 -17 t-7 -17l-34 -34q-7 -7 -17 -7t-17 7l-120 119l-120 -119q-7 -7 -17 -7t-17 7l-34 34q-7 7 -7 17t7 17l119 120l-119 120q-7 7 -7 17t7 17l34 34q7 8 17 8t17 -8z" />
+<glyph unicode="&#xe037;" d="M321 814l258 172q9 6 15 2.5t6 -13.5v-750q0 -10 -6 -13.5t-15 2.5l-258 172q-21 14 -46 14h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h250q25 0 46 14zM766 900h4q10 -1 16 -10q96 -129 96 -290q0 -154 -90 -281q-6 -9 -17 -10l-3 -1q-9 0 -16 6 l-29 23q-7 7 -8.5 16.5t4.5 17.5q72 103 72 229q0 132 -78 238q-6 8 -4.5 18t9.5 17l29 22q7 5 15 5z" />
+<glyph unicode="&#xe038;" d="M967 1004h3q11 -1 17 -10q135 -179 135 -396q0 -105 -34 -206.5t-98 -185.5q-7 -9 -17 -10h-3q-9 0 -16 6l-42 34q-8 6 -9 16t5 18q111 150 111 328q0 90 -29.5 176t-84.5 157q-6 9 -5 19t10 16l42 33q7 5 15 5zM321 814l258 172q9 6 15 2.5t6 -13.5v-750q0 -10 -6 -13.5 t-15 2.5l-258 172q-21 14 -46 14h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h250q25 0 46 14zM766 900h4q10 -1 16 -10q96 -129 96 -290q0 -154 -90 -281q-6 -9 -17 -10l-3 -1q-9 0 -16 6l-29 23q-7 7 -8.5 16.5t4.5 17.5q72 103 72 229q0 132 -78 238 q-6 8 -4.5 18.5t9.5 16.5l29 22q7 5 15 5z" />
+<glyph unicode="&#xe039;" d="M500 900h100v-100h-100v-100h-400v-100h-100v600h500v-300zM1200 700h-200v-100h200v-200h-300v300h-200v300h-100v200h600v-500zM100 1100v-300h300v300h-300zM800 1100v-300h300v300h-300zM300 900h-100v100h100v-100zM1000 900h-100v100h100v-100zM300 500h200v-500 h-500v500h200v100h100v-100zM800 300h200v-100h-100v-100h-200v100h-100v100h100v200h-200v100h300v-300zM100 400v-300h300v300h-300zM300 200h-100v100h100v-100zM1200 200h-100v100h100v-100zM700 0h-100v100h100v-100zM1200 0h-300v100h300v-100z" />
+<glyph unicode="&#xe040;" d="M100 200h-100v1000h100v-1000zM300 200h-100v1000h100v-1000zM700 200h-200v1000h200v-1000zM900 200h-100v1000h100v-1000zM1200 200h-200v1000h200v-1000zM400 0h-300v100h300v-100zM600 0h-100v91h100v-91zM800 0h-100v91h100v-91zM1100 0h-200v91h200v-91z" />
+<glyph unicode="&#xe041;" d="M500 1200l682 -682q8 -8 8 -18t-8 -18l-464 -464q-8 -8 -18 -8t-18 8l-682 682l1 475q0 10 7.5 17.5t17.5 7.5h474zM319.5 1024.5q-29.5 29.5 -71 29.5t-71 -29.5t-29.5 -71.5t29.5 -71.5t71 -29.5t71 29.5t29.5 71.5t-29.5 71.5z" />
+<glyph unicode="&#xe042;" d="M500 1200l682 -682q8 -8 8 -18t-8 -18l-464 -464q-8 -8 -18 -8t-18 8l-682 682l1 475q0 10 7.5 17.5t17.5 7.5h474zM800 1200l682 -682q8 -8 8 -18t-8 -18l-464 -464q-8 -8 -18 -8t-18 8l-56 56l424 426l-700 700h150zM319.5 1024.5q-29.5 29.5 -71 29.5t-71 -29.5 t-29.5 -71.5t29.5 -71.5t71 -29.5t71 29.5t29.5 71.5t-29.5 71.5z" />
+<glyph unicode="&#xe043;" d="M300 1200h825q75 0 75 -75v-900q0 -25 -18 -43l-64 -64q-8 -8 -13 -5.5t-5 12.5v950q0 10 -7.5 17.5t-17.5 7.5h-700q-25 0 -43 -18l-64 -64q-8 -8 -5.5 -13t12.5 -5h700q10 0 17.5 -7.5t7.5 -17.5v-950q0 -10 -7.5 -17.5t-17.5 -7.5h-850q-10 0 -17.5 7.5t-7.5 17.5v975 q0 25 18 43l139 139q18 18 43 18z" />
+<glyph unicode="&#xe044;" d="M250 1200h800q21 0 35.5 -14.5t14.5 -35.5v-1150l-450 444l-450 -445v1151q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe045;" d="M822 1200h-444q-11 0 -19 -7.5t-9 -17.5l-78 -301q-7 -24 7 -45l57 -108q6 -9 17.5 -15t21.5 -6h450q10 0 21.5 6t17.5 15l62 108q14 21 7 45l-83 301q-1 10 -9 17.5t-19 7.5zM1175 800h-150q-10 0 -21 -6.5t-15 -15.5l-78 -156q-4 -9 -15 -15.5t-21 -6.5h-550 q-10 0 -21 6.5t-15 15.5l-78 156q-4 9 -15 15.5t-21 6.5h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-650q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h750q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5 t7.5 17.5v650q0 10 -7.5 17.5t-17.5 7.5zM850 200h-500q-10 0 -19.5 -7t-11.5 -17l-38 -152q-2 -10 3.5 -17t15.5 -7h600q10 0 15.5 7t3.5 17l-38 152q-2 10 -11.5 17t-19.5 7z" />
+<glyph unicode="&#xe046;" d="M500 1100h200q56 0 102.5 -20.5t72.5 -50t44 -59t25 -50.5l6 -20h150q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v600q0 41 29.5 70.5t70.5 29.5h150q2 8 6.5 21.5t24 48t45 61t72 48t102.5 21.5zM900 800v-100 h100v100h-100zM600 730q-95 0 -162.5 -67.5t-67.5 -162.5t67.5 -162.5t162.5 -67.5t162.5 67.5t67.5 162.5t-67.5 162.5t-162.5 67.5zM600 603q43 0 73 -30t30 -73t-30 -73t-73 -30t-73 30t-30 73t30 73t73 30z" />
+<glyph unicode="&#xe047;" d="M681 1199l385 -998q20 -50 60 -92q18 -19 36.5 -29.5t27.5 -11.5l10 -2v-66h-417v66q53 0 75 43.5t5 88.5l-82 222h-391q-58 -145 -92 -234q-11 -34 -6.5 -57t25.5 -37t46 -20t55 -6v-66h-365v66q56 24 84 52q12 12 25 30.5t20 31.5l7 13l399 1006h93zM416 521h340 l-162 457z" />
+<glyph unicode="&#xe048;" d="M753 641q5 -1 14.5 -4.5t36 -15.5t50.5 -26.5t53.5 -40t50.5 -54.5t35.5 -70t14.5 -87q0 -67 -27.5 -125.5t-71.5 -97.5t-98.5 -66.5t-108.5 -40.5t-102 -13h-500v89q41 7 70.5 32.5t29.5 65.5v827q0 24 -0.5 34t-3.5 24t-8.5 19.5t-17 13.5t-28 12.5t-42.5 11.5v71 l471 -1q57 0 115.5 -20.5t108 -57t80.5 -94t31 -124.5q0 -51 -15.5 -96.5t-38 -74.5t-45 -50.5t-38.5 -30.5zM400 700h139q78 0 130.5 48.5t52.5 122.5q0 41 -8.5 70.5t-29.5 55.5t-62.5 39.5t-103.5 13.5h-118v-350zM400 200h216q80 0 121 50.5t41 130.5q0 90 -62.5 154.5 t-156.5 64.5h-159v-400z" />
+<glyph unicode="&#xe049;" d="M877 1200l2 -57q-83 -19 -116 -45.5t-40 -66.5l-132 -839q-9 -49 13 -69t96 -26v-97h-500v97q186 16 200 98l173 832q3 17 3 30t-1.5 22.5t-9 17.5t-13.5 12.5t-21.5 10t-26 8.5t-33.5 10q-13 3 -19 5v57h425z" />
+<glyph unicode="&#xe050;" d="M1300 900h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-200v-850q0 -22 25 -34.5t50 -13.5l25 -2v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v850h-200q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h1000v-300zM175 1000h-75v-800h75l-125 -167l-125 167h75v800h-75l125 167z" />
+<glyph unicode="&#xe051;" d="M1100 900h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-200v-650q0 -22 25 -34.5t50 -13.5l25 -2v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v650h-200q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h1000v-300zM1167 50l-167 -125v75h-800v-75l-167 125l167 125v-75h800v75z" />
+<glyph unicode="&#xe052;" d="M50 1100h600q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 800h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM50 500h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe053;" d="M250 1100h700q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 800h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM250 500h700q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe054;" d="M500 950v100q0 21 14.5 35.5t35.5 14.5h600q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5zM100 650v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000 q-21 0 -35.5 14.5t-14.5 35.5zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5zM0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100 q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5z" />
+<glyph unicode="&#xe055;" d="M50 1100h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 800h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM50 500h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe056;" d="M50 1100h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 1100h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM50 800h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 800h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 500h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 500h800q21 0 35.5 -14.5t14.5 -35.5v-100 q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 200h800 q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe057;" d="M400 0h-100v1100h100v-1100zM550 1100h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM550 800h500q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-500 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM267 550l-167 -125v75h-200v100h200v75zM550 500h300q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM550 200h600 q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe058;" d="M50 1100h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM900 0h-100v1100h100v-1100zM50 800h500q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-500 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM1100 600h200v-100h-200v-75l-167 125l167 125v-75zM50 500h300q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h600 q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe059;" d="M75 1000h750q31 0 53 -22t22 -53v-650q0 -31 -22 -53t-53 -22h-750q-31 0 -53 22t-22 53v650q0 31 22 53t53 22zM1200 300l-300 300l300 300v-600z" />
+<glyph unicode="&#xe060;" d="M44 1100h1112q18 0 31 -13t13 -31v-1012q0 -18 -13 -31t-31 -13h-1112q-18 0 -31 13t-13 31v1012q0 18 13 31t31 13zM100 1000v-737l247 182l298 -131l-74 156l293 318l236 -288v500h-1000zM342 884q56 0 95 -39t39 -94.5t-39 -95t-95 -39.5t-95 39.5t-39 95t39 94.5 t95 39z" />
+<glyph unicode="&#xe062;" d="M648 1169q117 0 216 -60t156.5 -161t57.5 -218q0 -115 -70 -258q-69 -109 -158 -225.5t-143 -179.5l-54 -62q-9 8 -25.5 24.5t-63.5 67.5t-91 103t-98.5 128t-95.5 148q-60 132 -60 249q0 88 34 169.5t91.5 142t137 96.5t166.5 36zM652.5 974q-91.5 0 -156.5 -65 t-65 -157t65 -156.5t156.5 -64.5t156.5 64.5t65 156.5t-65 157t-156.5 65z" />
+<glyph unicode="&#xe063;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 173v854q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57z" />
+<glyph unicode="&#xe064;" d="M554 1295q21 -72 57.5 -143.5t76 -130t83 -118t82.5 -117t70 -116t49.5 -126t18.5 -136.5q0 -71 -25.5 -135t-68.5 -111t-99 -82t-118.5 -54t-125.5 -23q-84 5 -161.5 34t-139.5 78.5t-99 125t-37 164.5q0 69 18 136.5t49.5 126.5t69.5 116.5t81.5 117.5t83.5 119 t76.5 131t58.5 143zM344 710q-23 -33 -43.5 -70.5t-40.5 -102.5t-17 -123q1 -37 14.5 -69.5t30 -52t41 -37t38.5 -24.5t33 -15q21 -7 32 -1t13 22l6 34q2 10 -2.5 22t-13.5 19q-5 4 -14 12t-29.5 40.5t-32.5 73.5q-26 89 6 271q2 11 -6 11q-8 1 -15 -10z" />
+<glyph unicode="&#xe065;" d="M1000 1013l108 115q2 1 5 2t13 2t20.5 -1t25 -9.5t28.5 -21.5q22 -22 27 -43t0 -32l-6 -10l-108 -115zM350 1100h400q50 0 105 -13l-187 -187h-368q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v182l200 200v-332 q0 -165 -93.5 -257.5t-256.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5zM1009 803l-362 -362l-161 -50l55 170l355 355z" />
+<glyph unicode="&#xe066;" d="M350 1100h361q-164 -146 -216 -200h-195q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5l200 153v-103q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5z M824 1073l339 -301q8 -7 8 -17.5t-8 -17.5l-340 -306q-7 -6 -12.5 -4t-6.5 11v203q-26 1 -54.5 0t-78.5 -7.5t-92 -17.5t-86 -35t-70 -57q10 59 33 108t51.5 81.5t65 58.5t68.5 40.5t67 24.5t56 13.5t40 4.5v210q1 10 6.5 12.5t13.5 -4.5z" />
+<glyph unicode="&#xe067;" d="M350 1100h350q60 0 127 -23l-178 -177h-349q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v69l200 200v-219q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5z M643 639l395 395q7 7 17.5 7t17.5 -7l101 -101q7 -7 7 -17.5t-7 -17.5l-531 -532q-7 -7 -17.5 -7t-17.5 7l-248 248q-7 7 -7 17.5t7 17.5l101 101q7 7 17.5 7t17.5 -7l111 -111q8 -7 18 -7t18 7z" />
+<glyph unicode="&#xe068;" d="M318 918l264 264q8 8 18 8t18 -8l260 -264q7 -8 4.5 -13t-12.5 -5h-170v-200h200v173q0 10 5 12t13 -5l264 -260q8 -7 8 -17.5t-8 -17.5l-264 -265q-8 -7 -13 -5t-5 12v173h-200v-200h170q10 0 12.5 -5t-4.5 -13l-260 -264q-8 -8 -18 -8t-18 8l-264 264q-8 8 -5.5 13 t12.5 5h175v200h-200v-173q0 -10 -5 -12t-13 5l-264 265q-8 7 -8 17.5t8 17.5l264 260q8 7 13 5t5 -12v-173h200v200h-175q-10 0 -12.5 5t5.5 13z" />
+<glyph unicode="&#xe069;" d="M250 1100h100q21 0 35.5 -14.5t14.5 -35.5v-438l464 453q15 14 25.5 10t10.5 -25v-1000q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v1000q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe070;" d="M50 1100h100q21 0 35.5 -14.5t14.5 -35.5v-438l464 453q15 14 25.5 10t10.5 -25v-438l464 453q15 14 25.5 10t10.5 -25v-1000q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5 t-14.5 35.5v1000q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe071;" d="M1200 1050v-1000q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -10.5 -25t-25.5 10l-492 480q-15 14 -15 35t15 35l492 480q15 14 25.5 10t10.5 -25v-438l464 453q15 14 25.5 10t10.5 -25z" />
+<glyph unicode="&#xe072;" d="M243 1074l814 -498q18 -11 18 -26t-18 -26l-814 -498q-18 -11 -30.5 -4t-12.5 28v1000q0 21 12.5 28t30.5 -4z" />
+<glyph unicode="&#xe073;" d="M250 1000h200q21 0 35.5 -14.5t14.5 -35.5v-800q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v800q0 21 14.5 35.5t35.5 14.5zM650 1000h200q21 0 35.5 -14.5t14.5 -35.5v-800q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v800 q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe074;" d="M1100 950v-800q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v800q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5z" />
+<glyph unicode="&#xe075;" d="M500 612v438q0 21 10.5 25t25.5 -10l492 -480q15 -14 15 -35t-15 -35l-492 -480q-15 -14 -25.5 -10t-10.5 25v438l-464 -453q-15 -14 -25.5 -10t-10.5 25v1000q0 21 10.5 25t25.5 -10z" />
+<glyph unicode="&#xe076;" d="M1048 1102l100 1q20 0 35 -14.5t15 -35.5l5 -1000q0 -21 -14.5 -35.5t-35.5 -14.5l-100 -1q-21 0 -35.5 14.5t-14.5 35.5l-2 437l-463 -454q-14 -15 -24.5 -10.5t-10.5 25.5l-2 437l-462 -455q-15 -14 -25.5 -9.5t-10.5 24.5l-5 1000q0 21 10.5 25.5t25.5 -10.5l466 -450 l-2 438q0 20 10.5 24.5t25.5 -9.5l466 -451l-2 438q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe077;" d="M850 1100h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438l-464 -453q-15 -14 -25.5 -10t-10.5 25v1000q0 21 10.5 25t25.5 -10l464 -453v438q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe078;" d="M686 1081l501 -540q15 -15 10.5 -26t-26.5 -11h-1042q-22 0 -26.5 11t10.5 26l501 540q15 15 36 15t36 -15zM150 400h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe079;" d="M885 900l-352 -353l352 -353l-197 -198l-552 552l552 550z" />
+<glyph unicode="&#xe080;" d="M1064 547l-551 -551l-198 198l353 353l-353 353l198 198z" />
+<glyph unicode="&#xe081;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM650 900h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-150h-150 q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -21 14.5 -35.5t35.5 -14.5h150v-150q0 -21 14.5 -35.5t35.5 -14.5h100q21 0 35.5 14.5t14.5 35.5v150h150q21 0 35.5 14.5t14.5 35.5v100q0 21 -14.5 35.5t-35.5 14.5h-150v150q0 21 -14.5 35.5t-35.5 14.5z" />
+<glyph unicode="&#xe082;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM850 700h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -21 14.5 -35.5 t35.5 -14.5h500q21 0 35.5 14.5t14.5 35.5v100q0 21 -14.5 35.5t-35.5 14.5z" />
+<glyph unicode="&#xe083;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM741.5 913q-12.5 0 -21.5 -9l-120 -120l-120 120q-9 9 -21.5 9 t-21.5 -9l-141 -141q-9 -9 -9 -21.5t9 -21.5l120 -120l-120 -120q-9 -9 -9 -21.5t9 -21.5l141 -141q9 -9 21.5 -9t21.5 9l120 120l120 -120q9 -9 21.5 -9t21.5 9l141 141q9 9 9 21.5t-9 21.5l-120 120l120 120q9 9 9 21.5t-9 21.5l-141 141q-9 9 -21.5 9z" />
+<glyph unicode="&#xe084;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM546 623l-84 85q-7 7 -17.5 7t-18.5 -7l-139 -139q-7 -8 -7 -18t7 -18 l242 -241q7 -8 17.5 -8t17.5 8l375 375q7 7 7 17.5t-7 18.5l-139 139q-7 7 -17.5 7t-17.5 -7z" />
+<glyph unicode="&#xe085;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM588 941q-29 0 -59 -5.5t-63 -20.5t-58 -38.5t-41.5 -63t-16.5 -89.5 q0 -25 20 -25h131q30 -5 35 11q6 20 20.5 28t45.5 8q20 0 31.5 -10.5t11.5 -28.5q0 -23 -7 -34t-26 -18q-1 0 -13.5 -4t-19.5 -7.5t-20 -10.5t-22 -17t-18.5 -24t-15.5 -35t-8 -46q-1 -8 5.5 -16.5t20.5 -8.5h173q7 0 22 8t35 28t37.5 48t29.5 74t12 100q0 47 -17 83 t-42.5 57t-59.5 34.5t-64 18t-59 4.5zM675 400h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5z" />
+<glyph unicode="&#xe086;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM675 1000h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5 t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5zM675 700h-250q-10 0 -17.5 -7.5t-7.5 -17.5v-50q0 -10 7.5 -17.5t17.5 -7.5h75v-200h-75q-10 0 -17.5 -7.5t-7.5 -17.5v-50q0 -10 7.5 -17.5t17.5 -7.5h350q10 0 17.5 7.5t7.5 17.5v50q0 10 -7.5 17.5 t-17.5 7.5h-75v275q0 10 -7.5 17.5t-17.5 7.5z" />
+<glyph unicode="&#xe087;" d="M525 1200h150q10 0 17.5 -7.5t7.5 -17.5v-194q103 -27 178.5 -102.5t102.5 -178.5h194q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-194q-27 -103 -102.5 -178.5t-178.5 -102.5v-194q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v194 q-103 27 -178.5 102.5t-102.5 178.5h-194q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h194q27 103 102.5 178.5t178.5 102.5v194q0 10 7.5 17.5t17.5 7.5zM700 893v-168q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v168q-68 -23 -119 -74 t-74 -119h168q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-168q23 -68 74 -119t119 -74v168q0 10 7.5 17.5t17.5 7.5h150q10 0 17.5 -7.5t7.5 -17.5v-168q68 23 119 74t74 119h-168q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h168 q-23 68 -74 119t-119 74z" />
+<glyph unicode="&#xe088;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM759 823l64 -64q7 -7 7 -17.5t-7 -17.5l-124 -124l124 -124q7 -7 7 -17.5t-7 -17.5l-64 -64q-7 -7 -17.5 -7t-17.5 7l-124 124l-124 -124q-7 -7 -17.5 -7t-17.5 7l-64 64 q-7 7 -7 17.5t7 17.5l124 124l-124 124q-7 7 -7 17.5t7 17.5l64 64q7 7 17.5 7t17.5 -7l124 -124l124 124q7 7 17.5 7t17.5 -7z" />
+<glyph unicode="&#xe089;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM782 788l106 -106q7 -7 7 -17.5t-7 -17.5l-320 -321q-8 -7 -18 -7t-18 7l-202 203q-8 7 -8 17.5t8 17.5l106 106q7 8 17.5 8t17.5 -8l79 -79l197 197q7 7 17.5 7t17.5 -7z" />
+<glyph unicode="&#xe090;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5q0 -120 65 -225 l587 587q-105 65 -225 65zM965 819l-584 -584q104 -62 219 -62q116 0 214.5 57t155.5 155.5t57 214.5q0 115 -62 219z" />
+<glyph unicode="&#xe091;" d="M39 582l522 427q16 13 27.5 8t11.5 -26v-291h550q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-550v-291q0 -21 -11.5 -26t-27.5 8l-522 427q-16 13 -16 32t16 32z" />
+<glyph unicode="&#xe092;" d="M639 1009l522 -427q16 -13 16 -32t-16 -32l-522 -427q-16 -13 -27.5 -8t-11.5 26v291h-550q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h550v291q0 21 11.5 26t27.5 -8z" />
+<glyph unicode="&#xe093;" d="M682 1161l427 -522q13 -16 8 -27.5t-26 -11.5h-291v-550q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v550h-291q-21 0 -26 11.5t8 27.5l427 522q13 16 32 16t32 -16z" />
+<glyph unicode="&#xe094;" d="M550 1200h200q21 0 35.5 -14.5t14.5 -35.5v-550h291q21 0 26 -11.5t-8 -27.5l-427 -522q-13 -16 -32 -16t-32 16l-427 522q-13 16 -8 27.5t26 11.5h291v550q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe095;" d="M639 1109l522 -427q16 -13 16 -32t-16 -32l-522 -427q-16 -13 -27.5 -8t-11.5 26v291q-94 -2 -182 -20t-170.5 -52t-147 -92.5t-100.5 -135.5q5 105 27 193.5t67.5 167t113 135t167 91.5t225.5 42v262q0 21 11.5 26t27.5 -8z" />
+<glyph unicode="&#xe096;" d="M850 1200h300q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -10.5 -25t-24.5 10l-94 94l-249 -249q-8 -7 -18 -7t-18 7l-106 106q-7 8 -7 18t7 18l249 249l-94 94q-14 14 -10 24.5t25 10.5zM350 0h-300q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 10.5 25t24.5 -10l94 -94l249 249 q8 7 18 7t18 -7l106 -106q7 -8 7 -18t-7 -18l-249 -249l94 -94q14 -14 10 -24.5t-25 -10.5z" />
+<glyph unicode="&#xe097;" d="M1014 1120l106 -106q7 -8 7 -18t-7 -18l-249 -249l94 -94q14 -14 10 -24.5t-25 -10.5h-300q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 10.5 25t24.5 -10l94 -94l249 249q8 7 18 7t18 -7zM250 600h300q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -10.5 -25t-24.5 10l-94 94 l-249 -249q-8 -7 -18 -7t-18 7l-106 106q-7 8 -7 18t7 18l249 249l-94 94q-14 14 -10 24.5t25 10.5z" />
+<glyph unicode="&#xe101;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM704 900h-208q-20 0 -32 -14.5t-8 -34.5l58 -302q4 -20 21.5 -34.5 t37.5 -14.5h54q20 0 37.5 14.5t21.5 34.5l58 302q4 20 -8 34.5t-32 14.5zM675 400h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5z" />
+<glyph unicode="&#xe102;" d="M260 1200q9 0 19 -2t15 -4l5 -2q22 -10 44 -23l196 -118q21 -13 36 -24q29 -21 37 -12q11 13 49 35l196 118q22 13 45 23q17 7 38 7q23 0 47 -16.5t37 -33.5l13 -16q14 -21 18 -45l25 -123l8 -44q1 -9 8.5 -14.5t17.5 -5.5h61q10 0 17.5 -7.5t7.5 -17.5v-50 q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 -7.5t-7.5 -17.5v-175h-400v300h-200v-300h-400v175q0 10 -7.5 17.5t-17.5 7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5h61q11 0 18 3t7 8q0 4 9 52l25 128q5 25 19 45q2 3 5 7t13.5 15t21.5 19.5t26.5 15.5 t29.5 7zM915 1079l-166 -162q-7 -7 -5 -12t12 -5h219q10 0 15 7t2 17l-51 149q-3 10 -11 12t-15 -6zM463 917l-177 157q-8 7 -16 5t-11 -12l-51 -143q-3 -10 2 -17t15 -7h231q11 0 12.5 5t-5.5 12zM500 0h-375q-10 0 -17.5 7.5t-7.5 17.5v375h400v-400zM1100 400v-375 q0 -10 -7.5 -17.5t-17.5 -7.5h-375v400h400z" />
+<glyph unicode="&#xe103;" d="M1165 1190q8 3 21 -6.5t13 -17.5q-2 -178 -24.5 -323.5t-55.5 -245.5t-87 -174.5t-102.5 -118.5t-118 -68.5t-118.5 -33t-120 -4.5t-105 9.5t-90 16.5q-61 12 -78 11q-4 1 -12.5 0t-34 -14.5t-52.5 -40.5l-153 -153q-26 -24 -37 -14.5t-11 43.5q0 64 42 102q8 8 50.5 45 t66.5 58q19 17 35 47t13 61q-9 55 -10 102.5t7 111t37 130t78 129.5q39 51 80 88t89.5 63.5t94.5 45t113.5 36t129 31t157.5 37t182 47.5zM1116 1098q-8 9 -22.5 -3t-45.5 -50q-38 -47 -119 -103.5t-142 -89.5l-62 -33q-56 -30 -102 -57t-104 -68t-102.5 -80.5t-85.5 -91 t-64 -104.5q-24 -56 -31 -86t2 -32t31.5 17.5t55.5 59.5q25 30 94 75.5t125.5 77.5t147.5 81q70 37 118.5 69t102 79.5t99 111t86.5 148.5q22 50 24 60t-6 19z" />
+<glyph unicode="&#xe104;" d="M653 1231q-39 -67 -54.5 -131t-10.5 -114.5t24.5 -96.5t47.5 -80t63.5 -62.5t68.5 -46.5t65 -30q-4 7 -17.5 35t-18.5 39.5t-17 39.5t-17 43t-13 42t-9.5 44.5t-2 42t4 43t13.5 39t23 38.5q96 -42 165 -107.5t105 -138t52 -156t13 -159t-19 -149.5q-13 -55 -44 -106.5 t-68 -87t-78.5 -64.5t-72.5 -45t-53 -22q-72 -22 -127 -11q-31 6 -13 19q6 3 17 7q13 5 32.5 21t41 44t38.5 63.5t21.5 81.5t-6.5 94.5t-50 107t-104 115.5q10 -104 -0.5 -189t-37 -140.5t-65 -93t-84 -52t-93.5 -11t-95 24.5q-80 36 -131.5 114t-53.5 171q-2 23 0 49.5 t4.5 52.5t13.5 56t27.5 60t46 64.5t69.5 68.5q-8 -53 -5 -102.5t17.5 -90t34 -68.5t44.5 -39t49 -2q31 13 38.5 36t-4.5 55t-29 64.5t-36 75t-26 75.5q-15 85 2 161.5t53.5 128.5t85.5 92.5t93.5 61t81.5 25.5z" />
+<glyph unicode="&#xe105;" d="M600 1094q82 0 160.5 -22.5t140 -59t116.5 -82.5t94.5 -95t68 -95t42.5 -82.5t14 -57.5t-14 -57.5t-43 -82.5t-68.5 -95t-94.5 -95t-116.5 -82.5t-140 -59t-159.5 -22.5t-159.5 22.5t-140 59t-116.5 82.5t-94.5 95t-68.5 95t-43 82.5t-14 57.5t14 57.5t42.5 82.5t68 95 t94.5 95t116.5 82.5t140 59t160.5 22.5zM888 829q-15 15 -18 12t5 -22q25 -57 25 -119q0 -124 -88 -212t-212 -88t-212 88t-88 212q0 59 23 114q8 19 4.5 22t-17.5 -12q-70 -69 -160 -184q-13 -16 -15 -40.5t9 -42.5q22 -36 47 -71t70 -82t92.5 -81t113 -58.5t133.5 -24.5 t133.5 24t113 58.5t92.5 81.5t70 81.5t47 70.5q11 18 9 42.5t-14 41.5q-90 117 -163 189zM448 727l-35 -36q-15 -15 -19.5 -38.5t4.5 -41.5q37 -68 93 -116q16 -13 38.5 -11t36.5 17l35 34q14 15 12.5 33.5t-16.5 33.5q-44 44 -89 117q-11 18 -28 20t-32 -12z" />
+<glyph unicode="&#xe106;" d="M592 0h-148l31 120q-91 20 -175.5 68.5t-143.5 106.5t-103.5 119t-66.5 110t-22 76q0 21 14 57.5t42.5 82.5t68 95t94.5 95t116.5 82.5t140 59t160.5 22.5q61 0 126 -15l32 121h148zM944 770l47 181q108 -85 176.5 -192t68.5 -159q0 -26 -19.5 -71t-59.5 -102t-93 -112 t-129 -104.5t-158 -75.5l46 173q77 49 136 117t97 131q11 18 9 42.5t-14 41.5q-54 70 -107 130zM310 824q-70 -69 -160 -184q-13 -16 -15 -40.5t9 -42.5q18 -30 39 -60t57 -70.5t74 -73t90 -61t105 -41.5l41 154q-107 18 -178.5 101.5t-71.5 193.5q0 59 23 114q8 19 4.5 22 t-17.5 -12zM448 727l-35 -36q-15 -15 -19.5 -38.5t4.5 -41.5q37 -68 93 -116q16 -13 38.5 -11t36.5 17l12 11l22 86l-3 4q-44 44 -89 117q-11 18 -28 20t-32 -12z" />
+<glyph unicode="&#xe107;" d="M-90 100l642 1066q20 31 48 28.5t48 -35.5l642 -1056q21 -32 7.5 -67.5t-50.5 -35.5h-1294q-37 0 -50.5 34t7.5 66zM155 200h345v75q0 10 7.5 17.5t17.5 7.5h150q10 0 17.5 -7.5t7.5 -17.5v-75h345l-445 723zM496 700h208q20 0 32 -14.5t8 -34.5l-58 -252 q-4 -20 -21.5 -34.5t-37.5 -14.5h-54q-20 0 -37.5 14.5t-21.5 34.5l-58 252q-4 20 8 34.5t32 14.5z" />
+<glyph unicode="&#xe108;" d="M650 1200q62 0 106 -44t44 -106v-339l363 -325q15 -14 26 -38.5t11 -44.5v-41q0 -20 -12 -26.5t-29 5.5l-359 249v-263q100 -93 100 -113v-64q0 -21 -13 -29t-32 1l-205 128l-205 -128q-19 -9 -32 -1t-13 29v64q0 20 100 113v263l-359 -249q-17 -12 -29 -5.5t-12 26.5v41 q0 20 11 44.5t26 38.5l363 325v339q0 62 44 106t106 44z" />
+<glyph unicode="&#xe109;" d="M850 1200h100q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-150h-1100v150q0 21 14.5 35.5t35.5 14.5h50v50q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-50h500v50q0 21 14.5 35.5t35.5 14.5zM1100 800v-750q0 -21 -14.5 -35.5 t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v750h1100zM100 600v-100h100v100h-100zM300 600v-100h100v100h-100zM500 600v-100h100v100h-100zM700 600v-100h100v100h-100zM900 600v-100h100v100h-100zM100 400v-100h100v100h-100zM300 400v-100h100v100h-100zM500 400 v-100h100v100h-100zM700 400v-100h100v100h-100zM900 400v-100h100v100h-100zM100 200v-100h100v100h-100zM300 200v-100h100v100h-100zM500 200v-100h100v100h-100zM700 200v-100h100v100h-100zM900 200v-100h100v100h-100z" />
+<glyph unicode="&#xe110;" d="M1135 1165l249 -230q15 -14 15 -35t-15 -35l-249 -230q-14 -14 -24.5 -10t-10.5 25v150h-159l-600 -600h-291q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h209l600 600h241v150q0 21 10.5 25t24.5 -10zM522 819l-141 -141l-122 122h-209q-21 0 -35.5 14.5 t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h291zM1135 565l249 -230q15 -14 15 -35t-15 -35l-249 -230q-14 -14 -24.5 -10t-10.5 25v150h-241l-181 181l141 141l122 -122h159v150q0 21 10.5 25t24.5 -10z" />
+<glyph unicode="&#xe111;" d="M100 1100h1000q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-596l-304 -300v300h-100q-41 0 -70.5 29.5t-29.5 70.5v600q0 41 29.5 70.5t70.5 29.5z" />
+<glyph unicode="&#xe112;" d="M150 1200h200q21 0 35.5 -14.5t14.5 -35.5v-250h-300v250q0 21 14.5 35.5t35.5 14.5zM850 1200h200q21 0 35.5 -14.5t14.5 -35.5v-250h-300v250q0 21 14.5 35.5t35.5 14.5zM1100 800v-300q0 -41 -3 -77.5t-15 -89.5t-32 -96t-58 -89t-89 -77t-129 -51t-174 -20t-174 20 t-129 51t-89 77t-58 89t-32 96t-15 89.5t-3 77.5v300h300v-250v-27v-42.5t1.5 -41t5 -38t10 -35t16.5 -30t25.5 -24.5t35 -19t46.5 -12t60 -4t60 4.5t46.5 12.5t35 19.5t25 25.5t17 30.5t10 35t5 38t2 40.5t-0.5 42v25v250h300z" />
+<glyph unicode="&#xe113;" d="M1100 411l-198 -199l-353 353l-353 -353l-197 199l551 551z" />
+<glyph unicode="&#xe114;" d="M1101 789l-550 -551l-551 551l198 199l353 -353l353 353z" />
+<glyph unicode="&#xe115;" d="M404 1000h746q21 0 35.5 -14.5t14.5 -35.5v-551h150q21 0 25 -10.5t-10 -24.5l-230 -249q-14 -15 -35 -15t-35 15l-230 249q-14 14 -10 24.5t25 10.5h150v401h-381zM135 984l230 -249q14 -14 10 -24.5t-25 -10.5h-150v-400h385l215 -200h-750q-21 0 -35.5 14.5 t-14.5 35.5v550h-150q-21 0 -25 10.5t10 24.5l230 249q14 15 35 15t35 -15z" />
+<glyph unicode="&#xe116;" d="M56 1200h94q17 0 31 -11t18 -27l38 -162h896q24 0 39 -18.5t10 -42.5l-100 -475q-5 -21 -27 -42.5t-55 -21.5h-633l48 -200h535q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-50q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v50h-300v-50 q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v50h-31q-18 0 -32.5 10t-20.5 19l-5 10l-201 961h-54q-20 0 -35 14.5t-15 35.5t15 35.5t35 14.5z" />
+<glyph unicode="&#xe117;" d="M1200 1000v-100h-1200v100h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500zM0 800h1200v-800h-1200v800z" />
+<glyph unicode="&#xe118;" d="M200 800l-200 -400v600h200q0 41 29.5 70.5t70.5 29.5h300q42 0 71 -29.5t29 -70.5h500v-200h-1000zM1500 700l-300 -700h-1200l300 700h1200z" />
+<glyph unicode="&#xe119;" d="M635 1184l230 -249q14 -14 10 -24.5t-25 -10.5h-150v-601h150q21 0 25 -10.5t-10 -24.5l-230 -249q-14 -15 -35 -15t-35 15l-230 249q-14 14 -10 24.5t25 10.5h150v601h-150q-21 0 -25 10.5t10 24.5l230 249q14 15 35 15t35 -15z" />
+<glyph unicode="&#xe120;" d="M936 864l249 -229q14 -15 14 -35.5t-14 -35.5l-249 -229q-15 -15 -25.5 -10.5t-10.5 24.5v151h-600v-151q0 -20 -10.5 -24.5t-25.5 10.5l-249 229q-14 15 -14 35.5t14 35.5l249 229q15 15 25.5 10.5t10.5 -25.5v-149h600v149q0 21 10.5 25.5t25.5 -10.5z" />
+<glyph unicode="&#xe121;" d="M1169 400l-172 732q-5 23 -23 45.5t-38 22.5h-672q-20 0 -38 -20t-23 -41l-172 -739h1138zM1100 300h-1000q-41 0 -70.5 -29.5t-29.5 -70.5v-100q0 -41 29.5 -70.5t70.5 -29.5h1000q41 0 70.5 29.5t29.5 70.5v100q0 41 -29.5 70.5t-70.5 29.5zM800 100v100h100v-100h-100 zM1000 100v100h100v-100h-100z" />
+<glyph unicode="&#xe122;" d="M1150 1100q21 0 35.5 -14.5t14.5 -35.5v-850q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v850q0 21 14.5 35.5t35.5 14.5zM1000 200l-675 200h-38l47 -276q3 -16 -5.5 -20t-29.5 -4h-7h-84q-20 0 -34.5 14t-18.5 35q-55 337 -55 351v250v6q0 16 1 23.5t6.5 14 t17.5 6.5h200l675 250v-850zM0 750v-250q-4 0 -11 0.5t-24 6t-30 15t-24 30t-11 48.5v50q0 26 10.5 46t25 30t29 16t25.5 7z" />
+<glyph unicode="&#xe123;" d="M553 1200h94q20 0 29 -10.5t3 -29.5l-18 -37q83 -19 144 -82.5t76 -140.5l63 -327l118 -173h17q19 0 33 -14.5t14 -35t-13 -40.5t-31 -27q-8 -4 -23 -9.5t-65 -19.5t-103 -25t-132.5 -20t-158.5 -9q-57 0 -115 5t-104 12t-88.5 15.5t-73.5 17.5t-54.5 16t-35.5 12l-11 4 q-18 8 -31 28t-13 40.5t14 35t33 14.5h17l118 173l63 327q15 77 76 140t144 83l-18 32q-6 19 3.5 32t28.5 13zM498 110q50 -6 102 -6q53 0 102 6q-12 -49 -39.5 -79.5t-62.5 -30.5t-63 30.5t-39 79.5z" />
+<glyph unicode="&#xe124;" d="M800 946l224 78l-78 -224l234 -45l-180 -155l180 -155l-234 -45l78 -224l-224 78l-45 -234l-155 180l-155 -180l-45 234l-224 -78l78 224l-234 45l180 155l-180 155l234 45l-78 224l224 -78l45 234l155 -180l155 180z" />
+<glyph unicode="&#xe125;" d="M650 1200h50q40 0 70 -40.5t30 -84.5v-150l-28 -125h328q40 0 70 -40.5t30 -84.5v-100q0 -45 -29 -74l-238 -344q-16 -24 -38 -40.5t-45 -16.5h-250q-7 0 -42 25t-66 50l-31 25h-61q-45 0 -72.5 18t-27.5 57v400q0 36 20 63l145 196l96 198q13 28 37.5 48t51.5 20z M650 1100l-100 -212l-150 -213v-375h100l136 -100h214l250 375v125h-450l50 225v175h-50zM50 800h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v500q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe126;" d="M600 1100h250q23 0 45 -16.5t38 -40.5l238 -344q29 -29 29 -74v-100q0 -44 -30 -84.5t-70 -40.5h-328q28 -118 28 -125v-150q0 -44 -30 -84.5t-70 -40.5h-50q-27 0 -51.5 20t-37.5 48l-96 198l-145 196q-20 27 -20 63v400q0 39 27.5 57t72.5 18h61q124 100 139 100z M50 1000h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v500q0 21 14.5 35.5t35.5 14.5zM636 1000l-136 -100h-100v-375l150 -213l100 -212h50v175l-50 225h450v125l-250 375h-214z" />
+<glyph unicode="&#xe127;" d="M356 873l363 230q31 16 53 -6l110 -112q13 -13 13.5 -32t-11.5 -34l-84 -121h302q84 0 138 -38t54 -110t-55 -111t-139 -39h-106l-131 -339q-6 -21 -19.5 -41t-28.5 -20h-342q-7 0 -90 81t-83 94v525q0 17 14 35.5t28 28.5zM400 792v-503l100 -89h293l131 339 q6 21 19.5 41t28.5 20h203q21 0 30.5 25t0.5 50t-31 25h-456h-7h-6h-5.5t-6 0.5t-5 1.5t-5 2t-4 2.5t-4 4t-2.5 4.5q-12 25 5 47l146 183l-86 83zM50 800h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v500 q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe128;" d="M475 1103l366 -230q2 -1 6 -3.5t14 -10.5t18 -16.5t14.5 -20t6.5 -22.5v-525q0 -13 -86 -94t-93 -81h-342q-15 0 -28.5 20t-19.5 41l-131 339h-106q-85 0 -139.5 39t-54.5 111t54 110t138 38h302l-85 121q-11 15 -10.5 34t13.5 32l110 112q22 22 53 6zM370 945l146 -183 q17 -22 5 -47q-2 -2 -3.5 -4.5t-4 -4t-4 -2.5t-5 -2t-5 -1.5t-6 -0.5h-6h-6.5h-6h-475v-100h221q15 0 29 -20t20 -41l130 -339h294l106 89v503l-342 236zM1050 800h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5 v500q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe129;" d="M550 1294q72 0 111 -55t39 -139v-106l339 -131q21 -6 41 -19.5t20 -28.5v-342q0 -7 -81 -90t-94 -83h-525q-17 0 -35.5 14t-28.5 28l-9 14l-230 363q-16 31 6 53l112 110q13 13 32 13.5t34 -11.5l121 -84v302q0 84 38 138t110 54zM600 972v203q0 21 -25 30.5t-50 0.5 t-25 -31v-456v-7v-6v-5.5t-0.5 -6t-1.5 -5t-2 -5t-2.5 -4t-4 -4t-4.5 -2.5q-25 -12 -47 5l-183 146l-83 -86l236 -339h503l89 100v293l-339 131q-21 6 -41 19.5t-20 28.5zM450 200h500q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-500 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe130;" d="M350 1100h500q21 0 35.5 14.5t14.5 35.5v100q0 21 -14.5 35.5t-35.5 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -21 14.5 -35.5t35.5 -14.5zM600 306v-106q0 -84 -39 -139t-111 -55t-110 54t-38 138v302l-121 -84q-15 -12 -34 -11.5t-32 13.5l-112 110 q-22 22 -6 53l230 363q1 2 3.5 6t10.5 13.5t16.5 17t20 13.5t22.5 6h525q13 0 94 -83t81 -90v-342q0 -15 -20 -28.5t-41 -19.5zM308 900l-236 -339l83 -86l183 146q22 17 47 5q2 -1 4.5 -2.5t4 -4t2.5 -4t2 -5t1.5 -5t0.5 -6v-5.5v-6v-7v-456q0 -22 25 -31t50 0.5t25 30.5 v203q0 15 20 28.5t41 19.5l339 131v293l-89 100h-503z" />
+<glyph unicode="&#xe131;" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM914 632l-275 223q-16 13 -27.5 8t-11.5 -26v-137h-275 q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h275v-137q0 -21 11.5 -26t27.5 8l275 223q16 13 16 32t-16 32z" />
+<glyph unicode="&#xe132;" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM561 855l-275 -223q-16 -13 -16 -32t16 -32l275 -223q16 -13 27.5 -8 t11.5 26v137h275q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5h-275v137q0 21 -11.5 26t-27.5 -8z" />
+<glyph unicode="&#xe133;" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM855 639l-223 275q-13 16 -32 16t-32 -16l-223 -275q-13 -16 -8 -27.5 t26 -11.5h137v-275q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v275h137q21 0 26 11.5t-8 27.5z" />
+<glyph unicode="&#xe134;" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM675 900h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-275h-137q-21 0 -26 -11.5 t8 -27.5l223 -275q13 -16 32 -16t32 16l223 275q13 16 8 27.5t-26 11.5h-137v275q0 10 -7.5 17.5t-17.5 7.5z" />
+<glyph unicode="&#xe135;" d="M600 1176q116 0 222.5 -46t184 -123.5t123.5 -184t46 -222.5t-46 -222.5t-123.5 -184t-184 -123.5t-222.5 -46t-222.5 46t-184 123.5t-123.5 184t-46 222.5t46 222.5t123.5 184t184 123.5t222.5 46zM627 1101q-15 -12 -36.5 -20.5t-35.5 -12t-43 -8t-39 -6.5 q-15 -3 -45.5 0t-45.5 -2q-20 -7 -51.5 -26.5t-34.5 -34.5q-3 -11 6.5 -22.5t8.5 -18.5q-3 -34 -27.5 -91t-29.5 -79q-9 -34 5 -93t8 -87q0 -9 17 -44.5t16 -59.5q12 0 23 -5t23.5 -15t19.5 -14q16 -8 33 -15t40.5 -15t34.5 -12q21 -9 52.5 -32t60 -38t57.5 -11 q7 -15 -3 -34t-22.5 -40t-9.5 -38q13 -21 23 -34.5t27.5 -27.5t36.5 -18q0 -7 -3.5 -16t-3.5 -14t5 -17q104 -2 221 112q30 29 46.5 47t34.5 49t21 63q-13 8 -37 8.5t-36 7.5q-15 7 -49.5 15t-51.5 19q-18 0 -41 -0.5t-43 -1.5t-42 -6.5t-38 -16.5q-51 -35 -66 -12 q-4 1 -3.5 25.5t0.5 25.5q-6 13 -26.5 17.5t-24.5 6.5q1 15 -0.5 30.5t-7 28t-18.5 11.5t-31 -21q-23 -25 -42 4q-19 28 -8 58q6 16 22 22q6 -1 26 -1.5t33.5 -4t19.5 -13.5q7 -12 18 -24t21.5 -20.5t20 -15t15.5 -10.5l5 -3q2 12 7.5 30.5t8 34.5t-0.5 32q-3 18 3.5 29 t18 22.5t15.5 24.5q6 14 10.5 35t8 31t15.5 22.5t34 22.5q-6 18 10 36q8 0 24 -1.5t24.5 -1.5t20 4.5t20.5 15.5q-10 23 -31 42.5t-37.5 29.5t-49 27t-43.5 23q0 1 2 8t3 11.5t1.5 10.5t-1 9.5t-4.5 4.5q31 -13 58.5 -14.5t38.5 2.5l12 5q5 28 -9.5 46t-36.5 24t-50 15 t-41 20q-18 -4 -37 0zM613 994q0 -17 8 -42t17 -45t9 -23q-8 1 -39.5 5.5t-52.5 10t-37 16.5q3 11 16 29.5t16 25.5q10 -10 19 -10t14 6t13.5 14.5t16.5 12.5z" />
+<glyph unicode="&#xe136;" d="M756 1157q164 92 306 -9l-259 -138l145 -232l251 126q6 -89 -34 -156.5t-117 -110.5q-60 -34 -127 -39.5t-126 16.5l-596 -596q-15 -16 -36.5 -16t-36.5 16l-111 110q-15 15 -15 36.5t15 37.5l600 599q-34 101 5.5 201.5t135.5 154.5z" />
+<glyph unicode="&#xe137;" horiz-adv-x="1220" d="M100 1196h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 1096h-200v-100h200v100zM100 796h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 696h-500v-100h500v100zM100 396h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 296h-300v-100h300v100z " />
+<glyph unicode="&#xe138;" d="M150 1200h900q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM700 500v-300l-200 -200v500l-350 500h900z" />
+<glyph unicode="&#xe139;" d="M500 1200h200q41 0 70.5 -29.5t29.5 -70.5v-100h300q41 0 70.5 -29.5t29.5 -70.5v-400h-500v100h-200v-100h-500v400q0 41 29.5 70.5t70.5 29.5h300v100q0 41 29.5 70.5t70.5 29.5zM500 1100v-100h200v100h-200zM1200 400v-200q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5v200h1200z" />
+<glyph unicode="&#xe140;" d="M50 1200h300q21 0 25 -10.5t-10 -24.5l-94 -94l199 -199q7 -8 7 -18t-7 -18l-106 -106q-8 -7 -18 -7t-18 7l-199 199l-94 -94q-14 -14 -24.5 -10t-10.5 25v300q0 21 14.5 35.5t35.5 14.5zM850 1200h300q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -10.5 -25t-24.5 10l-94 94 l-199 -199q-8 -7 -18 -7t-18 7l-106 106q-7 8 -7 18t7 18l199 199l-94 94q-14 14 -10 24.5t25 10.5zM364 470l106 -106q7 -8 7 -18t-7 -18l-199 -199l94 -94q14 -14 10 -24.5t-25 -10.5h-300q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 10.5 25t24.5 -10l94 -94l199 199 q8 7 18 7t18 -7zM1071 271l94 94q14 14 24.5 10t10.5 -25v-300q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -25 10.5t10 24.5l94 94l-199 199q-7 8 -7 18t7 18l106 106q8 7 18 7t18 -7z" />
+<glyph unicode="&#xe141;" d="M596 1192q121 0 231.5 -47.5t190 -127t127 -190t47.5 -231.5t-47.5 -231.5t-127 -190.5t-190 -127t-231.5 -47t-231.5 47t-190.5 127t-127 190.5t-47 231.5t47 231.5t127 190t190.5 127t231.5 47.5zM596 1010q-112 0 -207.5 -55.5t-151 -151t-55.5 -207.5t55.5 -207.5 t151 -151t207.5 -55.5t207.5 55.5t151 151t55.5 207.5t-55.5 207.5t-151 151t-207.5 55.5zM454.5 905q22.5 0 38.5 -16t16 -38.5t-16 -39t-38.5 -16.5t-38.5 16.5t-16 39t16 38.5t38.5 16zM754.5 905q22.5 0 38.5 -16t16 -38.5t-16 -39t-38 -16.5q-14 0 -29 10l-55 -145 q17 -23 17 -51q0 -36 -25.5 -61.5t-61.5 -25.5t-61.5 25.5t-25.5 61.5q0 32 20.5 56.5t51.5 29.5l122 126l1 1q-9 14 -9 28q0 23 16 39t38.5 16zM345.5 709q22.5 0 38.5 -16t16 -38.5t-16 -38.5t-38.5 -16t-38.5 16t-16 38.5t16 38.5t38.5 16zM854.5 709q22.5 0 38.5 -16 t16 -38.5t-16 -38.5t-38.5 -16t-38.5 16t-16 38.5t16 38.5t38.5 16z" />
+<glyph unicode="&#xe142;" d="M546 173l469 470q91 91 99 192q7 98 -52 175.5t-154 94.5q-22 4 -47 4q-34 0 -66.5 -10t-56.5 -23t-55.5 -38t-48 -41.5t-48.5 -47.5q-376 -375 -391 -390q-30 -27 -45 -41.5t-37.5 -41t-32 -46.5t-16 -47.5t-1.5 -56.5q9 -62 53.5 -95t99.5 -33q74 0 125 51l548 548 q36 36 20 75q-7 16 -21.5 26t-32.5 10q-26 0 -50 -23q-13 -12 -39 -38l-341 -338q-15 -15 -35.5 -15.5t-34.5 13.5t-14 34.5t14 34.5q327 333 361 367q35 35 67.5 51.5t78.5 16.5q14 0 29 -1q44 -8 74.5 -35.5t43.5 -68.5q14 -47 2 -96.5t-47 -84.5q-12 -11 -32 -32 t-79.5 -81t-114.5 -115t-124.5 -123.5t-123 -119.5t-96.5 -89t-57 -45q-56 -27 -120 -27q-70 0 -129 32t-93 89q-48 78 -35 173t81 163l511 511q71 72 111 96q91 55 198 55q80 0 152 -33q78 -36 129.5 -103t66.5 -154q17 -93 -11 -183.5t-94 -156.5l-482 -476 q-15 -15 -36 -16t-37 14t-17.5 34t14.5 35z" />
+<glyph unicode="&#xe143;" d="M649 949q48 68 109.5 104t121.5 38.5t118.5 -20t102.5 -64t71 -100.5t27 -123q0 -57 -33.5 -117.5t-94 -124.5t-126.5 -127.5t-150 -152.5t-146 -174q-62 85 -145.5 174t-150 152.5t-126.5 127.5t-93.5 124.5t-33.5 117.5q0 64 28 123t73 100.5t104 64t119 20 t120.5 -38.5t104.5 -104zM896 972q-33 0 -64.5 -19t-56.5 -46t-47.5 -53.5t-43.5 -45.5t-37.5 -19t-36 19t-40 45.5t-43 53.5t-54 46t-65.5 19q-67 0 -122.5 -55.5t-55.5 -132.5q0 -23 13.5 -51t46 -65t57.5 -63t76 -75l22 -22q15 -14 44 -44t50.5 -51t46 -44t41 -35t23 -12 t23.5 12t42.5 36t46 44t52.5 52t44 43q4 4 12 13q43 41 63.5 62t52 55t46 55t26 46t11.5 44q0 79 -53 133.5t-120 54.5z" />
+<glyph unicode="&#xe144;" d="M776.5 1214q93.5 0 159.5 -66l141 -141q66 -66 66 -160q0 -42 -28 -95.5t-62 -87.5l-29 -29q-31 53 -77 99l-18 18l95 95l-247 248l-389 -389l212 -212l-105 -106l-19 18l-141 141q-66 66 -66 159t66 159l283 283q65 66 158.5 66zM600 706l105 105q10 -8 19 -17l141 -141 q66 -66 66 -159t-66 -159l-283 -283q-66 -66 -159 -66t-159 66l-141 141q-66 66 -66 159.5t66 159.5l55 55q29 -55 75 -102l18 -17l-95 -95l247 -248l389 389z" />
+<glyph unicode="&#xe145;" d="M603 1200q85 0 162 -15t127 -38t79 -48t29 -46v-953q0 -41 -29.5 -70.5t-70.5 -29.5h-600q-41 0 -70.5 29.5t-29.5 70.5v953q0 21 30 46.5t81 48t129 37.5t163 15zM300 1000v-700h600v700h-600zM600 254q-43 0 -73.5 -30.5t-30.5 -73.5t30.5 -73.5t73.5 -30.5t73.5 30.5 t30.5 73.5t-30.5 73.5t-73.5 30.5z" />
+<glyph unicode="&#xe146;" d="M902 1185l283 -282q15 -15 15 -36t-14.5 -35.5t-35.5 -14.5t-35 15l-36 35l-279 -267v-300l-212 210l-308 -307l-280 -203l203 280l307 308l-210 212h300l267 279l-35 36q-15 14 -15 35t14.5 35.5t35.5 14.5t35 -15z" />
+<glyph unicode="&#xe148;" d="M700 1248v-78q38 -5 72.5 -14.5t75.5 -31.5t71 -53.5t52 -84t24 -118.5h-159q-4 36 -10.5 59t-21 45t-40 35.5t-64.5 20.5v-307l64 -13q34 -7 64 -16.5t70 -32t67.5 -52.5t47.5 -80t20 -112q0 -139 -89 -224t-244 -97v-77h-100v79q-150 16 -237 103q-40 40 -52.5 93.5 t-15.5 139.5h139q5 -77 48.5 -126t117.5 -65v335l-27 8q-46 14 -79 26.5t-72 36t-63 52t-40 72.5t-16 98q0 70 25 126t67.5 92t94.5 57t110 27v77h100zM600 754v274q-29 -4 -50 -11t-42 -21.5t-31.5 -41.5t-10.5 -65q0 -29 7 -50.5t16.5 -34t28.5 -22.5t31.5 -14t37.5 -10 q9 -3 13 -4zM700 547v-310q22 2 42.5 6.5t45 15.5t41.5 27t29 42t12 59.5t-12.5 59.5t-38 44.5t-53 31t-66.5 24.5z" />
+<glyph unicode="&#xe149;" d="M561 1197q84 0 160.5 -40t123.5 -109.5t47 -147.5h-153q0 40 -19.5 71.5t-49.5 48.5t-59.5 26t-55.5 9q-37 0 -79 -14.5t-62 -35.5q-41 -44 -41 -101q0 -26 13.5 -63t26.5 -61t37 -66q6 -9 9 -14h241v-100h-197q8 -50 -2.5 -115t-31.5 -95q-45 -62 -99 -112 q34 10 83 17.5t71 7.5q32 1 102 -16t104 -17q83 0 136 30l50 -147q-31 -19 -58 -30.5t-55 -15.5t-42 -4.5t-46 -0.5q-23 0 -76 17t-111 32.5t-96 11.5q-39 -3 -82 -16t-67 -25l-23 -11l-55 145q4 3 16 11t15.5 10.5t13 9t15.5 12t14.5 14t17.5 18.5q48 55 54 126.5 t-30 142.5h-221v100h166q-23 47 -44 104q-7 20 -12 41.5t-6 55.5t6 66.5t29.5 70.5t58.5 71q97 88 263 88z" />
+<glyph unicode="&#xe150;" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM935 1184l230 -249q14 -14 10 -24.5t-25 -10.5h-150v-900h-200v900h-150q-21 0 -25 10.5t10 24.5l230 249q14 15 35 15t35 -15z" />
+<glyph unicode="&#xe151;" d="M1000 700h-100v100h-100v-100h-100v500h300v-500zM400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM801 1100v-200h100v200h-100zM1000 350l-200 -250h200v-100h-300v150l200 250h-200v100h300v-150z " />
+<glyph unicode="&#xe152;" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1000 1050l-200 -250h200v-100h-300v150l200 250h-200v100h300v-150zM1000 0h-100v100h-100v-100h-100v500h300v-500zM801 400v-200h100v200h-100z " />
+<glyph unicode="&#xe153;" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1000 700h-100v400h-100v100h200v-500zM1100 0h-100v100h-200v400h300v-500zM901 400v-200h100v200h-100z" />
+<glyph unicode="&#xe154;" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1100 700h-100v100h-200v400h300v-500zM901 1100v-200h100v200h-100zM1000 0h-100v400h-100v100h200v-500z" />
+<glyph unicode="&#xe155;" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM900 1000h-200v200h200v-200zM1000 700h-300v200h300v-200zM1100 400h-400v200h400v-200zM1200 100h-500v200h500v-200z" />
+<glyph unicode="&#xe156;" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1200 1000h-500v200h500v-200zM1100 700h-400v200h400v-200zM1000 400h-300v200h300v-200zM900 100h-200v200h200v-200z" />
+<glyph unicode="&#xe157;" d="M350 1100h400q162 0 256 -93.5t94 -256.5v-400q0 -165 -93.5 -257.5t-256.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5z" />
+<glyph unicode="&#xe158;" d="M350 1100h400q165 0 257.5 -92.5t92.5 -257.5v-400q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-163 0 -256.5 92.5t-93.5 257.5v400q0 163 94 256.5t256 93.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5zM440 770l253 -190q17 -12 17 -30t-17 -30l-253 -190q-16 -12 -28 -6.5t-12 26.5v400q0 21 12 26.5t28 -6.5z" />
+<glyph unicode="&#xe159;" d="M350 1100h400q163 0 256.5 -94t93.5 -256v-400q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 163 92.5 256.5t257.5 93.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5zM350 700h400q21 0 26.5 -12t-6.5 -28l-190 -253q-12 -17 -30 -17t-30 17l-190 253q-12 16 -6.5 28t26.5 12z" />
+<glyph unicode="&#xe160;" d="M350 1100h400q165 0 257.5 -92.5t92.5 -257.5v-400q0 -163 -92.5 -256.5t-257.5 -93.5h-400q-163 0 -256.5 94t-93.5 256v400q0 165 92.5 257.5t257.5 92.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5zM580 693l190 -253q12 -16 6.5 -28t-26.5 -12h-400q-21 0 -26.5 12t6.5 28l190 253q12 17 30 17t30 -17z" />
+<glyph unicode="&#xe161;" d="M550 1100h400q165 0 257.5 -92.5t92.5 -257.5v-400q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h450q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5h-450q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM338 867l324 -284q16 -14 16 -33t-16 -33l-324 -284q-16 -14 -27 -9t-11 26v150h-250q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h250v150q0 21 11 26t27 -9z" />
+<glyph unicode="&#xe162;" d="M793 1182l9 -9q8 -10 5 -27q-3 -11 -79 -225.5t-78 -221.5l300 1q24 0 32.5 -17.5t-5.5 -35.5q-1 0 -133.5 -155t-267 -312.5t-138.5 -162.5q-12 -15 -26 -15h-9l-9 8q-9 11 -4 32q2 9 42 123.5t79 224.5l39 110h-302q-23 0 -31 19q-10 21 6 41q75 86 209.5 237.5 t228 257t98.5 111.5q9 16 25 16h9z" />
+<glyph unicode="&#xe163;" d="M350 1100h400q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-450q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h450q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400 q0 165 92.5 257.5t257.5 92.5zM938 867l324 -284q16 -14 16 -33t-16 -33l-324 -284q-16 -14 -27 -9t-11 26v150h-250q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h250v150q0 21 11 26t27 -9z" />
+<glyph unicode="&#xe164;" d="M750 1200h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -10.5 -25t-24.5 10l-109 109l-312 -312q-15 -15 -35.5 -15t-35.5 15l-141 141q-15 15 -15 35.5t15 35.5l312 312l-109 109q-14 14 -10 24.5t25 10.5zM456 900h-156q-41 0 -70.5 -29.5t-29.5 -70.5v-500 q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v148l200 200v-298q0 -165 -93.5 -257.5t-256.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5h300z" />
+<glyph unicode="&#xe165;" d="M600 1186q119 0 227.5 -46.5t187 -125t125 -187t46.5 -227.5t-46.5 -227.5t-125 -187t-187 -125t-227.5 -46.5t-227.5 46.5t-187 125t-125 187t-46.5 227.5t46.5 227.5t125 187t187 125t227.5 46.5zM600 1022q-115 0 -212 -56.5t-153.5 -153.5t-56.5 -212t56.5 -212 t153.5 -153.5t212 -56.5t212 56.5t153.5 153.5t56.5 212t-56.5 212t-153.5 153.5t-212 56.5zM600 794q80 0 137 -57t57 -137t-57 -137t-137 -57t-137 57t-57 137t57 137t137 57z" />
+<glyph unicode="&#xe166;" d="M450 1200h200q21 0 35.5 -14.5t14.5 -35.5v-350h245q20 0 25 -11t-9 -26l-383 -426q-14 -15 -33.5 -15t-32.5 15l-379 426q-13 15 -8.5 26t25.5 11h250v350q0 21 14.5 35.5t35.5 14.5zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5z M900 200v-50h100v50h-100z" />
+<glyph unicode="&#xe167;" d="M583 1182l378 -435q14 -15 9 -31t-26 -16h-244v-250q0 -20 -17 -35t-39 -15h-200q-20 0 -32 14.5t-12 35.5v250h-250q-20 0 -25.5 16.5t8.5 31.5l383 431q14 16 33.5 17t33.5 -14zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5z M900 200v-50h100v50h-100z" />
+<glyph unicode="&#xe168;" d="M396 723l369 369q7 7 17.5 7t17.5 -7l139 -139q7 -8 7 -18.5t-7 -17.5l-525 -525q-7 -8 -17.5 -8t-17.5 8l-292 291q-7 8 -7 18t7 18l139 139q8 7 18.5 7t17.5 -7zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5zM900 200v-50h100v50 h-100z" />
+<glyph unicode="&#xe169;" d="M135 1023l142 142q14 14 35 14t35 -14l77 -77l-212 -212l-77 76q-14 15 -14 36t14 35zM655 855l210 210q14 14 24.5 10t10.5 -25l-2 -599q-1 -20 -15.5 -35t-35.5 -15l-597 -1q-21 0 -25 10.5t10 24.5l208 208l-154 155l212 212zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5 v-250h-1100v250q0 21 14.5 35.5t35.5 14.5zM900 200v-50h100v50h-100z" />
+<glyph unicode="&#xe170;" d="M350 1200l599 -2q20 -1 35 -15.5t15 -35.5l1 -597q0 -21 -10.5 -25t-24.5 10l-208 208l-155 -154l-212 212l155 154l-210 210q-14 14 -10 24.5t25 10.5zM524 512l-76 -77q-15 -14 -36 -14t-35 14l-142 142q-14 14 -14 35t14 35l77 77zM50 300h1000q21 0 35.5 -14.5 t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5zM900 200v-50h100v50h-100z" />
+<glyph unicode="&#xe171;" d="M1200 103l-483 276l-314 -399v423h-399l1196 796v-1096zM483 424v-230l683 953z" />
+<glyph unicode="&#xe172;" d="M1100 1000v-850q0 -21 -14.5 -35.5t-35.5 -14.5h-150v400h-700v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200z" />
+<glyph unicode="&#xe173;" d="M1100 1000l-2 -149l-299 -299l-95 95q-9 9 -21.5 9t-21.5 -9l-149 -147h-312v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM1132 638l106 -106q7 -7 7 -17.5t-7 -17.5l-420 -421q-8 -7 -18 -7 t-18 7l-202 203q-8 7 -8 17.5t8 17.5l106 106q7 8 17.5 8t17.5 -8l79 -79l297 297q7 7 17.5 7t17.5 -7z" />
+<glyph unicode="&#xe174;" d="M1100 1000v-269l-103 -103l-134 134q-15 15 -33.5 16.5t-34.5 -12.5l-266 -266h-329v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM1202 572l70 -70q15 -15 15 -35.5t-15 -35.5l-131 -131 l131 -131q15 -15 15 -35.5t-15 -35.5l-70 -70q-15 -15 -35.5 -15t-35.5 15l-131 131l-131 -131q-15 -15 -35.5 -15t-35.5 15l-70 70q-15 15 -15 35.5t15 35.5l131 131l-131 131q-15 15 -15 35.5t15 35.5l70 70q15 15 35.5 15t35.5 -15l131 -131l131 131q15 15 35.5 15 t35.5 -15z" />
+<glyph unicode="&#xe175;" d="M1100 1000v-300h-350q-21 0 -35.5 -14.5t-14.5 -35.5v-150h-500v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM850 600h100q21 0 35.5 -14.5t14.5 -35.5v-250h150q21 0 25 -10.5t-10 -24.5 l-230 -230q-14 -14 -35 -14t-35 14l-230 230q-14 14 -10 24.5t25 10.5h150v250q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe176;" d="M1100 1000v-400l-165 165q-14 15 -35 15t-35 -15l-263 -265h-402v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM935 565l230 -229q14 -15 10 -25.5t-25 -10.5h-150v-250q0 -20 -14.5 -35 t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35v250h-150q-21 0 -25 10.5t10 25.5l230 229q14 15 35 15t35 -15z" />
+<glyph unicode="&#xe177;" d="M50 1100h1100q21 0 35.5 -14.5t14.5 -35.5v-150h-1200v150q0 21 14.5 35.5t35.5 14.5zM1200 800v-550q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v550h1200zM100 500v-200h400v200h-400z" />
+<glyph unicode="&#xe178;" d="M935 1165l248 -230q14 -14 14 -35t-14 -35l-248 -230q-14 -14 -24.5 -10t-10.5 25v150h-400v200h400v150q0 21 10.5 25t24.5 -10zM200 800h-50q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h50v-200zM400 800h-100v200h100v-200zM18 435l247 230 q14 14 24.5 10t10.5 -25v-150h400v-200h-400v-150q0 -21 -10.5 -25t-24.5 10l-247 230q-15 14 -15 35t15 35zM900 300h-100v200h100v-200zM1000 500h51q20 0 34.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-34.5 -14.5h-51v200z" />
+<glyph unicode="&#xe179;" d="M862 1073l276 116q25 18 43.5 8t18.5 -41v-1106q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v397q-4 1 -11 5t-24 17.5t-30 29t-24 42t-11 56.5v359q0 31 18.5 65t43.5 52zM550 1200q22 0 34.5 -12.5t14.5 -24.5l1 -13v-450q0 -28 -10.5 -59.5 t-25 -56t-29 -45t-25.5 -31.5l-10 -11v-447q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v447q-4 4 -11 11.5t-24 30.5t-30 46t-24 55t-11 60v450q0 2 0.5 5.5t4 12t8.5 15t14.5 12t22.5 5.5q20 0 32.5 -12.5t14.5 -24.5l3 -13v-350h100v350v5.5t2.5 12 t7 15t15 12t25.5 5.5q23 0 35.5 -12.5t13.5 -24.5l1 -13v-350h100v350q0 2 0.5 5.5t3 12t7 15t15 12t24.5 5.5z" />
+<glyph unicode="&#xe180;" d="M1200 1100v-56q-4 0 -11 -0.5t-24 -3t-30 -7.5t-24 -15t-11 -24v-888q0 -22 25 -34.5t50 -13.5l25 -2v-56h-400v56q75 0 87.5 6.5t12.5 43.5v394h-500v-394q0 -37 12.5 -43.5t87.5 -6.5v-56h-400v56q4 0 11 0.5t24 3t30 7.5t24 15t11 24v888q0 22 -25 34.5t-50 13.5 l-25 2v56h400v-56q-75 0 -87.5 -6.5t-12.5 -43.5v-394h500v394q0 37 -12.5 43.5t-87.5 6.5v56h400z" />
+<glyph unicode="&#xe181;" d="M675 1000h375q21 0 35.5 -14.5t14.5 -35.5v-150h-105l-295 -98v98l-200 200h-400l100 100h375zM100 900h300q41 0 70.5 -29.5t29.5 -70.5v-500q0 -41 -29.5 -70.5t-70.5 -29.5h-300q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5zM100 800v-200h300v200 h-300zM1100 535l-400 -133v163l400 133v-163zM100 500v-200h300v200h-300zM1100 398v-248q0 -21 -14.5 -35.5t-35.5 -14.5h-375l-100 -100h-375l-100 100h400l200 200h105z" />
+<glyph unicode="&#xe182;" d="M17 1007l162 162q17 17 40 14t37 -22l139 -194q14 -20 11 -44.5t-20 -41.5l-119 -118q102 -142 228 -268t267 -227l119 118q17 17 42.5 19t44.5 -12l192 -136q19 -14 22.5 -37.5t-13.5 -40.5l-163 -162q-3 -1 -9.5 -1t-29.5 2t-47.5 6t-62.5 14.5t-77.5 26.5t-90 42.5 t-101.5 60t-111 83t-119 108.5q-74 74 -133.5 150.5t-94.5 138.5t-60 119.5t-34.5 100t-15 74.5t-4.5 48z" />
+<glyph unicode="&#xe183;" d="M600 1100q92 0 175 -10.5t141.5 -27t108.5 -36.5t81.5 -40t53.5 -37t31 -27l9 -10v-200q0 -21 -14.5 -33t-34.5 -9l-202 34q-20 3 -34.5 20t-14.5 38v146q-141 24 -300 24t-300 -24v-146q0 -21 -14.5 -38t-34.5 -20l-202 -34q-20 -3 -34.5 9t-14.5 33v200q3 4 9.5 10.5 t31 26t54 37.5t80.5 39.5t109 37.5t141 26.5t175 10.5zM600 795q56 0 97 -9.5t60 -23.5t30 -28t12 -24l1 -10v-50l365 -303q14 -15 24.5 -40t10.5 -45v-212q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v212q0 20 10.5 45t24.5 40l365 303v50 q0 4 1 10.5t12 23t30 29t60 22.5t97 10z" />
+<glyph unicode="&#xe184;" d="M1100 700l-200 -200h-600l-200 200v500h200v-200h200v200h200v-200h200v200h200v-500zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-12l137 -100h-950l137 100h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5 t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe185;" d="M700 1100h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-1000h300v1000q0 41 -29.5 70.5t-70.5 29.5zM1100 800h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-700h300v700q0 41 -29.5 70.5t-70.5 29.5zM400 0h-300v400q0 41 29.5 70.5t70.5 29.5h100q41 0 70.5 -29.5t29.5 -70.5v-400z " />
+<glyph unicode="&#xe186;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 700h-200v-100h200v-300h-300v100h200v100h-200v300h300v-100zM900 700v-300l-100 -100h-200v500h200z M700 700v-300h100v300h-100z" />
+<glyph unicode="&#xe187;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 300h-100v200h-100v-200h-100v500h100v-200h100v200h100v-500zM900 700v-300l-100 -100h-200v500h200z M700 700v-300h100v300h-100z" />
+<glyph unicode="&#xe188;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 700h-200v-300h200v-100h-300v500h300v-100zM900 700h-200v-300h200v-100h-300v500h300v-100z" />
+<glyph unicode="&#xe189;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 400l-300 150l300 150v-300zM900 550l-300 -150v300z" />
+<glyph unicode="&#xe190;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM900 300h-700v500h700v-500zM800 700h-130q-38 0 -66.5 -43t-28.5 -108t27 -107t68 -42h130v300zM300 700v-300 h130q41 0 68 42t27 107t-28.5 108t-66.5 43h-130z" />
+<glyph unicode="&#xe191;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 700h-200v-100h200v-300h-300v100h200v100h-200v300h300v-100zM900 300h-100v400h-100v100h200v-500z M700 300h-100v100h100v-100z" />
+<glyph unicode="&#xe192;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM300 700h200v-400h-300v500h100v-100zM900 300h-100v400h-100v100h200v-500zM300 600v-200h100v200h-100z M700 300h-100v100h100v-100z" />
+<glyph unicode="&#xe193;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 500l-199 -200h-100v50l199 200v150h-200v100h300v-300zM900 300h-100v400h-100v100h200v-500zM701 300h-100 v100h100v-100z" />
+<glyph unicode="&#xe194;" d="M600 1191q120 0 229.5 -47t188.5 -126t126 -188.5t47 -229.5t-47 -229.5t-126 -188.5t-188.5 -126t-229.5 -47t-229.5 47t-188.5 126t-126 188.5t-47 229.5t47 229.5t126 188.5t188.5 126t229.5 47zM600 1021q-114 0 -211 -56.5t-153.5 -153.5t-56.5 -211t56.5 -211 t153.5 -153.5t211 -56.5t211 56.5t153.5 153.5t56.5 211t-56.5 211t-153.5 153.5t-211 56.5zM800 700h-300v-200h300v-100h-300l-100 100v200l100 100h300v-100z" />
+<glyph unicode="&#xe195;" d="M600 1191q120 0 229.5 -47t188.5 -126t126 -188.5t47 -229.5t-47 -229.5t-126 -188.5t-188.5 -126t-229.5 -47t-229.5 47t-188.5 126t-126 188.5t-47 229.5t47 229.5t126 188.5t188.5 126t229.5 47zM600 1021q-114 0 -211 -56.5t-153.5 -153.5t-56.5 -211t56.5 -211 t153.5 -153.5t211 -56.5t211 56.5t153.5 153.5t56.5 211t-56.5 211t-153.5 153.5t-211 56.5zM800 700v-100l-50 -50l100 -100v-50h-100l-100 100h-150v-100h-100v400h300zM500 700v-100h200v100h-200z" />
+<glyph unicode="&#xe197;" d="M503 1089q110 0 200.5 -59.5t134.5 -156.5q44 14 90 14q120 0 205 -86.5t85 -207t-85 -207t-205 -86.5h-128v250q0 21 -14.5 35.5t-35.5 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-250h-222q-80 0 -136 57.5t-56 136.5q0 69 43 122.5t108 67.5q-2 19 -2 37q0 100 49 185 t134 134t185 49zM525 500h150q10 0 17.5 -7.5t7.5 -17.5v-275h137q21 0 26 -11.5t-8 -27.5l-223 -244q-13 -16 -32 -16t-32 16l-223 244q-13 16 -8 27.5t26 11.5h137v275q0 10 7.5 17.5t17.5 7.5z" />
+<glyph unicode="&#xe198;" d="M502 1089q110 0 201 -59.5t135 -156.5q43 15 89 15q121 0 206 -86.5t86 -206.5q0 -99 -60 -181t-150 -110l-378 360q-13 16 -31.5 16t-31.5 -16l-381 -365h-9q-79 0 -135.5 57.5t-56.5 136.5q0 69 43 122.5t108 67.5q-2 19 -2 38q0 100 49 184.5t133.5 134t184.5 49.5z M632 467l223 -228q13 -16 8 -27.5t-26 -11.5h-137v-275q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v275h-137q-21 0 -26 11.5t8 27.5q199 204 223 228q19 19 31.5 19t32.5 -19z" />
+<glyph unicode="&#xe199;" d="M700 100v100h400l-270 300h170l-270 300h170l-300 333l-300 -333h170l-270 -300h170l-270 -300h400v-100h-50q-21 0 -35.5 -14.5t-14.5 -35.5v-50h400v50q0 21 -14.5 35.5t-35.5 14.5h-50z" />
+<glyph unicode="&#xe200;" d="M600 1179q94 0 167.5 -56.5t99.5 -145.5q89 -6 150.5 -71.5t61.5 -155.5q0 -61 -29.5 -112.5t-79.5 -82.5q9 -29 9 -55q0 -74 -52.5 -126.5t-126.5 -52.5q-55 0 -100 30v-251q21 0 35.5 -14.5t14.5 -35.5v-50h-300v50q0 21 14.5 35.5t35.5 14.5v251q-45 -30 -100 -30 q-74 0 -126.5 52.5t-52.5 126.5q0 18 4 38q-47 21 -75.5 65t-28.5 97q0 74 52.5 126.5t126.5 52.5q5 0 23 -2q0 2 -1 10t-1 13q0 116 81.5 197.5t197.5 81.5z" />
+<glyph unicode="&#xe201;" d="M1010 1010q111 -111 150.5 -260.5t0 -299t-150.5 -260.5q-83 -83 -191.5 -126.5t-218.5 -43.5t-218.5 43.5t-191.5 126.5q-111 111 -150.5 260.5t0 299t150.5 260.5q83 83 191.5 126.5t218.5 43.5t218.5 -43.5t191.5 -126.5zM476 1065q-4 0 -8 -1q-121 -34 -209.5 -122.5 t-122.5 -209.5q-4 -12 2.5 -23t18.5 -14l36 -9q3 -1 7 -1q23 0 29 22q27 96 98 166q70 71 166 98q11 3 17.5 13.5t3.5 22.5l-9 35q-3 13 -14 19q-7 4 -15 4zM512 920q-4 0 -9 -2q-80 -24 -138.5 -82.5t-82.5 -138.5q-4 -13 2 -24t19 -14l34 -9q4 -1 8 -1q22 0 28 21 q18 58 58.5 98.5t97.5 58.5q12 3 18 13.5t3 21.5l-9 35q-3 12 -14 19q-7 4 -15 4zM719.5 719.5q-49.5 49.5 -119.5 49.5t-119.5 -49.5t-49.5 -119.5t49.5 -119.5t119.5 -49.5t119.5 49.5t49.5 119.5t-49.5 119.5zM855 551q-22 0 -28 -21q-18 -58 -58.5 -98.5t-98.5 -57.5 q-11 -4 -17 -14.5t-3 -21.5l9 -35q3 -12 14 -19q7 -4 15 -4q4 0 9 2q80 24 138.5 82.5t82.5 138.5q4 13 -2.5 24t-18.5 14l-34 9q-4 1 -8 1zM1000 515q-23 0 -29 -22q-27 -96 -98 -166q-70 -71 -166 -98q-11 -3 -17.5 -13.5t-3.5 -22.5l9 -35q3 -13 14 -19q7 -4 15 -4 q4 0 8 1q121 34 209.5 122.5t122.5 209.5q4 12 -2.5 23t-18.5 14l-36 9q-3 1 -7 1z" />
+<glyph unicode="&#xe202;" d="M700 800h300v-380h-180v200h-340v-200h-380v755q0 10 7.5 17.5t17.5 7.5h575v-400zM1000 900h-200v200zM700 300h162l-212 -212l-212 212h162v200h100v-200zM520 0h-395q-10 0 -17.5 7.5t-7.5 17.5v395zM1000 220v-195q0 -10 -7.5 -17.5t-17.5 -7.5h-195z" />
+<glyph unicode="&#xe203;" d="M700 800h300v-520l-350 350l-550 -550v1095q0 10 7.5 17.5t17.5 7.5h575v-400zM1000 900h-200v200zM862 200h-162v-200h-100v200h-162l212 212zM480 0h-355q-10 0 -17.5 7.5t-7.5 17.5v55h380v-80zM1000 80v-55q0 -10 -7.5 -17.5t-17.5 -7.5h-155v80h180z" />
+<glyph unicode="&#xe204;" d="M1162 800h-162v-200h100l100 -100h-300v300h-162l212 212zM200 800h200q27 0 40 -2t29.5 -10.5t23.5 -30t7 -57.5h300v-100h-600l-200 -350v450h100q0 36 7 57.5t23.5 30t29.5 10.5t40 2zM800 400h240l-240 -400h-800l300 500h500v-100z" />
+<glyph unicode="&#xe205;" d="M650 1100h100q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h50v50q0 21 14.5 35.5t35.5 14.5zM1000 850v150q41 0 70.5 -29.5t29.5 -70.5v-800 q0 -41 -29.5 -70.5t-70.5 -29.5h-600q-1 0 -20 4l246 246l-326 326v324q0 41 29.5 70.5t70.5 29.5v-150q0 -62 44 -106t106 -44h300q62 0 106 44t44 106zM412 250l-212 -212v162h-200v100h200v162z" />
+<glyph unicode="&#xe206;" d="M450 1100h100q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h50v50q0 21 14.5 35.5t35.5 14.5zM800 850v150q41 0 70.5 -29.5t29.5 -70.5v-500 h-200v-300h200q0 -36 -7 -57.5t-23.5 -30t-29.5 -10.5t-40 -2h-600q-41 0 -70.5 29.5t-29.5 70.5v800q0 41 29.5 70.5t70.5 29.5v-150q0 -62 44 -106t106 -44h300q62 0 106 44t44 106zM1212 250l-212 -212v162h-200v100h200v162z" />
+<glyph unicode="&#xe209;" d="M658 1197l637 -1104q23 -38 7 -65.5t-60 -27.5h-1276q-44 0 -60 27.5t7 65.5l637 1104q22 39 54 39t54 -39zM704 800h-208q-20 0 -32 -14.5t-8 -34.5l58 -302q4 -20 21.5 -34.5t37.5 -14.5h54q20 0 37.5 14.5t21.5 34.5l58 302q4 20 -8 34.5t-32 14.5zM500 300v-100h200 v100h-200z" />
+<glyph unicode="&#xe210;" d="M425 1100h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM425 800h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5 t17.5 7.5zM825 800h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM25 500h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150 q0 10 7.5 17.5t17.5 7.5zM425 500h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM825 500h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5 v150q0 10 7.5 17.5t17.5 7.5zM25 200h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM425 200h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5 t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM825 200h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5z" />
+<glyph unicode="&#xe211;" d="M700 1200h100v-200h-100v-100h350q62 0 86.5 -39.5t-3.5 -94.5l-66 -132q-41 -83 -81 -134h-772q-40 51 -81 134l-66 132q-28 55 -3.5 94.5t86.5 39.5h350v100h-100v200h100v100h200v-100zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-12l137 -100 h-950l138 100h-13q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe212;" d="M600 1300q40 0 68.5 -29.5t28.5 -70.5h-194q0 41 28.5 70.5t68.5 29.5zM443 1100h314q18 -37 18 -75q0 -8 -3 -25h328q41 0 44.5 -16.5t-30.5 -38.5l-175 -145h-678l-178 145q-34 22 -29 38.5t46 16.5h328q-3 17 -3 25q0 38 18 75zM250 700h700q21 0 35.5 -14.5 t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-150v-200l275 -200h-950l275 200v200h-150q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe213;" d="M600 1181q75 0 128 -53t53 -128t-53 -128t-128 -53t-128 53t-53 128t53 128t128 53zM602 798h46q34 0 55.5 -28.5t21.5 -86.5q0 -76 39 -183h-324q39 107 39 183q0 58 21.5 86.5t56.5 28.5h45zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-13 l138 -100h-950l137 100h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe214;" d="M600 1300q47 0 92.5 -53.5t71 -123t25.5 -123.5q0 -78 -55.5 -133.5t-133.5 -55.5t-133.5 55.5t-55.5 133.5q0 62 34 143l144 -143l111 111l-163 163q34 26 63 26zM602 798h46q34 0 55.5 -28.5t21.5 -86.5q0 -76 39 -183h-324q39 107 39 183q0 58 21.5 86.5t56.5 28.5h45 zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-13l138 -100h-950l137 100h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe215;" d="M600 1200l300 -161v-139h-300q0 -57 18.5 -108t50 -91.5t63 -72t70 -67.5t57.5 -61h-530q-60 83 -90.5 177.5t-30.5 178.5t33 164.5t87.5 139.5t126 96.5t145.5 41.5v-98zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-13l138 -100h-950l137 100 h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe216;" d="M600 1300q41 0 70.5 -29.5t29.5 -70.5v-78q46 -26 73 -72t27 -100v-50h-400v50q0 54 27 100t73 72v78q0 41 29.5 70.5t70.5 29.5zM400 800h400q54 0 100 -27t72 -73h-172v-100h200v-100h-200v-100h200v-100h-200v-100h200q0 -83 -58.5 -141.5t-141.5 -58.5h-400 q-83 0 -141.5 58.5t-58.5 141.5v400q0 83 58.5 141.5t141.5 58.5z" />
+<glyph unicode="&#xe218;" d="M150 1100h900q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v500q0 21 14.5 35.5t35.5 14.5zM125 400h950q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-283l224 -224q13 -13 13 -31.5t-13 -32 t-31.5 -13.5t-31.5 13l-88 88h-524l-87 -88q-13 -13 -32 -13t-32 13.5t-13 32t13 31.5l224 224h-289q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM541 300l-100 -100h324l-100 100h-124z" />
+<glyph unicode="&#xe219;" d="M200 1100h800q83 0 141.5 -58.5t58.5 -141.5v-200h-100q0 41 -29.5 70.5t-70.5 29.5h-250q-41 0 -70.5 -29.5t-29.5 -70.5h-100q0 41 -29.5 70.5t-70.5 29.5h-250q-41 0 -70.5 -29.5t-29.5 -70.5h-100v200q0 83 58.5 141.5t141.5 58.5zM100 600h1000q41 0 70.5 -29.5 t29.5 -70.5v-300h-1200v300q0 41 29.5 70.5t70.5 29.5zM300 100v-50q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v50h200zM1100 100v-50q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v50h200z" />
+<glyph unicode="&#xe221;" d="M480 1165l682 -683q31 -31 31 -75.5t-31 -75.5l-131 -131h-481l-517 518q-32 31 -32 75.5t32 75.5l295 296q31 31 75.5 31t76.5 -31zM108 794l342 -342l303 304l-341 341zM250 100h800q21 0 35.5 -14.5t14.5 -35.5v-50h-900v50q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe223;" d="M1057 647l-189 506q-8 19 -27.5 33t-40.5 14h-400q-21 0 -40.5 -14t-27.5 -33l-189 -506q-8 -19 1.5 -33t30.5 -14h625v-150q0 -21 14.5 -35.5t35.5 -14.5t35.5 14.5t14.5 35.5v150h125q21 0 30.5 14t1.5 33zM897 0h-595v50q0 21 14.5 35.5t35.5 14.5h50v50 q0 21 14.5 35.5t35.5 14.5h48v300h200v-300h47q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-50z" />
+<glyph unicode="&#xe224;" d="M900 800h300v-575q0 -10 -7.5 -17.5t-17.5 -7.5h-375v591l-300 300v84q0 10 7.5 17.5t17.5 7.5h375v-400zM1200 900h-200v200zM400 600h300v-575q0 -10 -7.5 -17.5t-17.5 -7.5h-650q-10 0 -17.5 7.5t-7.5 17.5v950q0 10 7.5 17.5t17.5 7.5h375v-400zM700 700h-200v200z " />
+<glyph unicode="&#xe225;" d="M484 1095h195q75 0 146 -32.5t124 -86t89.5 -122.5t48.5 -142q18 -14 35 -20q31 -10 64.5 6.5t43.5 48.5q10 34 -15 71q-19 27 -9 43q5 8 12.5 11t19 -1t23.5 -16q41 -44 39 -105q-3 -63 -46 -106.5t-104 -43.5h-62q-7 -55 -35 -117t-56 -100l-39 -234q-3 -20 -20 -34.5 t-38 -14.5h-100q-21 0 -33 14.5t-9 34.5l12 70q-49 -14 -91 -14h-195q-24 0 -65 8l-11 -64q-3 -20 -20 -34.5t-38 -14.5h-100q-21 0 -33 14.5t-9 34.5l26 157q-84 74 -128 175l-159 53q-19 7 -33 26t-14 40v50q0 21 14.5 35.5t35.5 14.5h124q11 87 56 166l-111 95 q-16 14 -12.5 23.5t24.5 9.5h203q116 101 250 101zM675 1000h-250q-10 0 -17.5 -7.5t-7.5 -17.5v-50q0 -10 7.5 -17.5t17.5 -7.5h250q10 0 17.5 7.5t7.5 17.5v50q0 10 -7.5 17.5t-17.5 7.5z" />
+<glyph unicode="&#xe226;" d="M641 900l423 247q19 8 42 2.5t37 -21.5l32 -38q14 -15 12.5 -36t-17.5 -34l-139 -120h-390zM50 1100h106q67 0 103 -17t66 -71l102 -212h823q21 0 35.5 -14.5t14.5 -35.5v-50q0 -21 -14 -40t-33 -26l-737 -132q-23 -4 -40 6t-26 25q-42 67 -100 67h-300q-62 0 -106 44 t-44 106v200q0 62 44 106t106 44zM173 928h-80q-19 0 -28 -14t-9 -35v-56q0 -51 42 -51h134q16 0 21.5 8t5.5 24q0 11 -16 45t-27 51q-18 28 -43 28zM550 727q-32 0 -54.5 -22.5t-22.5 -54.5t22.5 -54.5t54.5 -22.5t54.5 22.5t22.5 54.5t-22.5 54.5t-54.5 22.5zM130 389 l152 130q18 19 34 24t31 -3.5t24.5 -17.5t25.5 -28q28 -35 50.5 -51t48.5 -13l63 5l48 -179q13 -61 -3.5 -97.5t-67.5 -79.5l-80 -69q-47 -40 -109 -35.5t-103 51.5l-130 151q-40 47 -35.5 109.5t51.5 102.5zM380 377l-102 -88q-31 -27 2 -65l37 -43q13 -15 27.5 -19.5 t31.5 6.5l61 53q19 16 14 49q-2 20 -12 56t-17 45q-11 12 -19 14t-23 -8z" />
+<glyph unicode="&#xe227;" d="M625 1200h150q10 0 17.5 -7.5t7.5 -17.5v-109q79 -33 131 -87.5t53 -128.5q1 -46 -15 -84.5t-39 -61t-46 -38t-39 -21.5l-17 -6q6 0 15 -1.5t35 -9t50 -17.5t53 -30t50 -45t35.5 -64t14.5 -84q0 -59 -11.5 -105.5t-28.5 -76.5t-44 -51t-49.5 -31.5t-54.5 -16t-49.5 -6.5 t-43.5 -1v-75q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v75h-100v-75q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v75h-175q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h75v600h-75q-10 0 -17.5 7.5t-7.5 17.5v150 q0 10 7.5 17.5t17.5 7.5h175v75q0 10 7.5 17.5t17.5 7.5h150q10 0 17.5 -7.5t7.5 -17.5v-75h100v75q0 10 7.5 17.5t17.5 7.5zM400 900v-200h263q28 0 48.5 10.5t30 25t15 29t5.5 25.5l1 10q0 4 -0.5 11t-6 24t-15 30t-30 24t-48.5 11h-263zM400 500v-200h363q28 0 48.5 10.5 t30 25t15 29t5.5 25.5l1 10q0 4 -0.5 11t-6 24t-15 30t-30 24t-48.5 11h-363z" />
+<glyph unicode="&#xe230;" d="M212 1198h780q86 0 147 -61t61 -147v-416q0 -51 -18 -142.5t-36 -157.5l-18 -66q-29 -87 -93.5 -146.5t-146.5 -59.5h-572q-82 0 -147 59t-93 147q-8 28 -20 73t-32 143.5t-20 149.5v416q0 86 61 147t147 61zM600 1045q-70 0 -132.5 -11.5t-105.5 -30.5t-78.5 -41.5 t-57 -45t-36 -41t-20.5 -30.5l-6 -12l156 -243h560l156 243q-2 5 -6 12.5t-20 29.5t-36.5 42t-57 44.5t-79 42t-105 29.5t-132.5 12zM762 703h-157l195 261z" />
+<glyph unicode="&#xe231;" d="M475 1300h150q103 0 189 -86t86 -189v-500q0 -41 -42 -83t-83 -42h-450q-41 0 -83 42t-42 83v500q0 103 86 189t189 86zM700 300v-225q0 -21 -27 -48t-48 -27h-150q-21 0 -48 27t-27 48v225h300z" />
+<glyph unicode="&#xe232;" d="M475 1300h96q0 -150 89.5 -239.5t239.5 -89.5v-446q0 -41 -42 -83t-83 -42h-450q-41 0 -83 42t-42 83v500q0 103 86 189t189 86zM700 300v-225q0 -21 -27 -48t-48 -27h-150q-21 0 -48 27t-27 48v225h300z" />
+<glyph unicode="&#xe233;" d="M1294 767l-638 -283l-378 170l-78 -60v-224l100 -150v-199l-150 148l-150 -149v200l100 150v250q0 4 -0.5 10.5t0 9.5t1 8t3 8t6.5 6l47 40l-147 65l642 283zM1000 380l-350 -166l-350 166v147l350 -165l350 165v-147z" />
+<glyph unicode="&#xe234;" d="M250 800q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM650 800q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM1050 800q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44z" />
+<glyph unicode="&#xe235;" d="M550 1100q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM550 700q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM550 300q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44z" />
+<glyph unicode="&#xe236;" d="M125 1100h950q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-950q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM125 700h950q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-950q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5 t17.5 7.5zM125 300h950q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-950q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5z" />
+<glyph unicode="&#xe237;" d="M350 1200h500q162 0 256 -93.5t94 -256.5v-500q0 -165 -93.5 -257.5t-256.5 -92.5h-500q-165 0 -257.5 92.5t-92.5 257.5v500q0 165 92.5 257.5t257.5 92.5zM900 1000h-600q-41 0 -70.5 -29.5t-29.5 -70.5v-600q0 -41 29.5 -70.5t70.5 -29.5h600q41 0 70.5 29.5 t29.5 70.5v600q0 41 -29.5 70.5t-70.5 29.5zM350 900h500q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -14.5 -35.5t-35.5 -14.5h-500q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 14.5 35.5t35.5 14.5zM400 800v-200h400v200h-400z" />
+<glyph unicode="&#xe238;" d="M150 1100h1000q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-200h50q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-200h50q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-200h50q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5 t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5h50v200h-50q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5h50v200h-50q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5h50v200h-50q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe239;" d="M650 1187q87 -67 118.5 -156t0 -178t-118.5 -155q-87 66 -118.5 155t0 178t118.5 156zM300 800q124 0 212 -88t88 -212q-124 0 -212 88t-88 212zM1000 800q0 -124 -88 -212t-212 -88q0 124 88 212t212 88zM300 500q124 0 212 -88t88 -212q-124 0 -212 88t-88 212z M1000 500q0 -124 -88 -212t-212 -88q0 124 88 212t212 88zM700 199v-144q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v142q40 -4 43 -4q17 0 57 6z" />
+<glyph unicode="&#xe240;" d="M745 878l69 19q25 6 45 -12l298 -295q11 -11 15 -26.5t-2 -30.5q-5 -14 -18 -23.5t-28 -9.5h-8q1 0 1 -13q0 -29 -2 -56t-8.5 -62t-20 -63t-33 -53t-51 -39t-72.5 -14h-146q-184 0 -184 288q0 24 10 47q-20 4 -62 4t-63 -4q11 -24 11 -47q0 -288 -184 -288h-142 q-48 0 -84.5 21t-56 51t-32 71.5t-16 75t-3.5 68.5q0 13 2 13h-7q-15 0 -27.5 9.5t-18.5 23.5q-6 15 -2 30.5t15 25.5l298 296q20 18 46 11l76 -19q20 -5 30.5 -22.5t5.5 -37.5t-22.5 -31t-37.5 -5l-51 12l-182 -193h891l-182 193l-44 -12q-20 -5 -37.5 6t-22.5 31t6 37.5 t31 22.5z" />
+<glyph unicode="&#xe241;" d="M1200 900h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-200v-850q0 -22 25 -34.5t50 -13.5l25 -2v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v850h-200q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h1000v-300zM500 450h-25q0 15 -4 24.5t-9 14.5t-17 7.5t-20 3t-25 0.5h-100v-425q0 -11 12.5 -17.5t25.5 -7.5h12v-50h-200v50q50 0 50 25v425h-100q-17 0 -25 -0.5t-20 -3t-17 -7.5t-9 -14.5t-4 -24.5h-25v150h500v-150z" />
+<glyph unicode="&#xe242;" d="M1000 300v50q-25 0 -55 32q-14 14 -25 31t-16 27l-4 11l-289 747h-69l-300 -754q-18 -35 -39 -56q-9 -9 -24.5 -18.5t-26.5 -14.5l-11 -5v-50h273v50q-49 0 -78.5 21.5t-11.5 67.5l69 176h293l61 -166q13 -34 -3.5 -66.5t-55.5 -32.5v-50h312zM412 691l134 342l121 -342 h-255zM1100 150v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5z" />
+<glyph unicode="&#xe243;" d="M50 1200h1100q21 0 35.5 -14.5t14.5 -35.5v-1100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v1100q0 21 14.5 35.5t35.5 14.5zM611 1118h-70q-13 0 -18 -12l-299 -753q-17 -32 -35 -51q-18 -18 -56 -34q-12 -5 -12 -18v-50q0 -8 5.5 -14t14.5 -6 h273q8 0 14 6t6 14v50q0 8 -6 14t-14 6q-55 0 -71 23q-10 14 0 39l63 163h266l57 -153q11 -31 -6 -55q-12 -17 -36 -17q-8 0 -14 -6t-6 -14v-50q0 -8 6 -14t14 -6h313q8 0 14 6t6 14v50q0 7 -5.5 13t-13.5 7q-17 0 -42 25q-25 27 -40 63h-1l-288 748q-5 12 -19 12zM639 611 h-197l103 264z" />
+<glyph unicode="&#xe244;" d="M1200 1100h-1200v100h1200v-100zM50 1000h400q21 0 35.5 -14.5t14.5 -35.5v-900q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v900q0 21 14.5 35.5t35.5 14.5zM650 1000h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM700 900v-300h300v300h-300z" />
+<glyph unicode="&#xe245;" d="M50 1200h400q21 0 35.5 -14.5t14.5 -35.5v-900q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v900q0 21 14.5 35.5t35.5 14.5zM650 700h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400 q0 21 14.5 35.5t35.5 14.5zM700 600v-300h300v300h-300zM1200 0h-1200v100h1200v-100z" />
+<glyph unicode="&#xe246;" d="M50 1000h400q21 0 35.5 -14.5t14.5 -35.5v-350h100v150q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-150h100v-100h-100v-150q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v150h-100v-350q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5v800q0 21 14.5 35.5t35.5 14.5zM700 700v-300h300v300h-300z" />
+<glyph unicode="&#xe247;" d="M100 0h-100v1200h100v-1200zM250 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM300 1000v-300h300v300h-300zM250 500h900q21 0 35.5 -14.5t14.5 -35.5v-400 q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe248;" d="M600 1100h150q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-150v-100h450q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5h350v100h-150q-21 0 -35.5 14.5 t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5h150v100h100v-100zM400 1000v-300h300v300h-300z" />
+<glyph unicode="&#xe249;" d="M1200 0h-100v1200h100v-1200zM550 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM600 1000v-300h300v300h-300zM50 500h900q21 0 35.5 -14.5t14.5 -35.5v-400 q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe250;" d="M865 565l-494 -494q-23 -23 -41 -23q-14 0 -22 13.5t-8 38.5v1000q0 25 8 38.5t22 13.5q18 0 41 -23l494 -494q14 -14 14 -35t-14 -35z" />
+<glyph unicode="&#xe251;" d="M335 635l494 494q29 29 50 20.5t21 -49.5v-1000q0 -41 -21 -49.5t-50 20.5l-494 494q-14 14 -14 35t14 35z" />
+<glyph unicode="&#xe252;" d="M100 900h1000q41 0 49.5 -21t-20.5 -50l-494 -494q-14 -14 -35 -14t-35 14l-494 494q-29 29 -20.5 50t49.5 21z" />
+<glyph unicode="&#xe253;" d="M635 865l494 -494q29 -29 20.5 -50t-49.5 -21h-1000q-41 0 -49.5 21t20.5 50l494 494q14 14 35 14t35 -14z" />
+<glyph unicode="&#xe254;" d="M700 741v-182l-692 -323v221l413 193l-413 193v221zM1200 0h-800v200h800v-200z" />
+<glyph unicode="&#xe255;" d="M1200 900h-200v-100h200v-100h-300v300h200v100h-200v100h300v-300zM0 700h50q0 21 4 37t9.5 26.5t18 17.5t22 11t28.5 5.5t31 2t37 0.5h100v-550q0 -22 -25 -34.5t-50 -13.5l-25 -2v-100h400v100q-4 0 -11 0.5t-24 3t-30 7t-24 15t-11 24.5v550h100q25 0 37 -0.5t31 -2 t28.5 -5.5t22 -11t18 -17.5t9.5 -26.5t4 -37h50v300h-800v-300z" />
+<glyph unicode="&#xe256;" d="M800 700h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-100v-550q0 -22 25 -34.5t50 -14.5l25 -1v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v550h-100q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h800v-300zM1100 200h-200v-100h200v-100h-300v300h200v100h-200v100h300v-300z" />
+<glyph unicode="&#xe257;" d="M701 1098h160q16 0 21 -11t-7 -23l-464 -464l464 -464q12 -12 7 -23t-21 -11h-160q-13 0 -23 9l-471 471q-7 8 -7 18t7 18l471 471q10 9 23 9z" />
+<glyph unicode="&#xe258;" d="M339 1098h160q13 0 23 -9l471 -471q7 -8 7 -18t-7 -18l-471 -471q-10 -9 -23 -9h-160q-16 0 -21 11t7 23l464 464l-464 464q-12 12 -7 23t21 11z" />
+<glyph unicode="&#xe259;" d="M1087 882q11 -5 11 -21v-160q0 -13 -9 -23l-471 -471q-8 -7 -18 -7t-18 7l-471 471q-9 10 -9 23v160q0 16 11 21t23 -7l464 -464l464 464q12 12 23 7z" />
+<glyph unicode="&#xe260;" d="M618 993l471 -471q9 -10 9 -23v-160q0 -16 -11 -21t-23 7l-464 464l-464 -464q-12 -12 -23 -7t-11 21v160q0 13 9 23l471 471q8 7 18 7t18 -7z" />
+<glyph unicode="&#xf8ff;" d="M1000 1200q0 -124 -88 -212t-212 -88q0 124 88 212t212 88zM450 1000h100q21 0 40 -14t26 -33l79 -194q5 1 16 3q34 6 54 9.5t60 7t65.5 1t61 -10t56.5 -23t42.5 -42t29 -64t5 -92t-19.5 -121.5q-1 -7 -3 -19.5t-11 -50t-20.5 -73t-32.5 -81.5t-46.5 -83t-64 -70 t-82.5 -50q-13 -5 -42 -5t-65.5 2.5t-47.5 2.5q-14 0 -49.5 -3.5t-63 -3.5t-43.5 7q-57 25 -104.5 78.5t-75 111.5t-46.5 112t-26 90l-7 35q-15 63 -18 115t4.5 88.5t26 64t39.5 43.5t52 25.5t58.5 13t62.5 2t59.5 -4.5t55.5 -8l-147 192q-12 18 -5.5 30t27.5 12z" />
+<glyph unicode="&#x1f511;" d="M250 1200h600q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-150v-500l-255 -178q-19 -9 -32 -1t-13 29v650h-150q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM400 1100v-100h300v100h-300z" />
+<glyph unicode="&#x1f6aa;" d="M250 1200h750q39 0 69.5 -40.5t30.5 -84.5v-933l-700 -117v950l600 125h-700v-1000h-100v1025q0 23 15.5 49t34.5 26zM500 525v-100l100 20v100z" />
+</font>
+</defs></svg>
diff --git a/ruoyi-admin/src/main/resources/static/fonts/glyphicons-halflings-regular.ttf b/ruoyi-admin/src/main/resources/static/fonts/glyphicons-halflings-regular.ttf
new file mode 100644
index 0000000..1413fc6
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/fonts/glyphicons-halflings-regular.ttf
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/fonts/glyphicons-halflings-regular.woff b/ruoyi-admin/src/main/resources/static/fonts/glyphicons-halflings-regular.woff
new file mode 100644
index 0000000..9e61285
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/fonts/glyphicons-halflings-regular.woff
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/fonts/glyphicons-halflings-regular.woff2 b/ruoyi-admin/src/main/resources/static/fonts/glyphicons-halflings-regular.woff2
new file mode 100644
index 0000000..64539b5
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/fonts/glyphicons-halflings-regular.woff2
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/fonts/iconfont.eot b/ruoyi-admin/src/main/resources/static/fonts/iconfont.eot
new file mode 100644
index 0000000..3f5e98b
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/fonts/iconfont.eot
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/fonts/iconfont.svg b/ruoyi-admin/src/main/resources/static/fonts/iconfont.svg
new file mode 100644
index 0000000..4f1920d
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/fonts/iconfont.svg
@@ -0,0 +1,405 @@
+<?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 xmlns="http://www.w3.org/2000/svg">
+  <metadata>Created by iconfont</metadata>
+  <defs>
+  <font id="layui-icon" horiz-adv-x="1024">
+    <font-face
+      font-family="layui-icon"
+      font-weight="400"
+      font-stretch="normal"
+      units-per-em="1024"
+      ascent="896"
+      descent="-128"
+    />
+      <missing-glyph />
+      
+      <glyph glyph-name="edge" unicode="&#59019;" d="M240.185509 821.062741C322.180562 871.479699 415.37494 897.48813 509.969233 895.934224 845.948962 895.934224 1023.938224 648.353161 1023.938224 456.964708c-0.199988-65.396055-25.998431-127.79229-71.795669-174.389479-45.797237-46.397201-107.993485-72.995596-173.389539-73.995536-150.390927 0-182.98896 46.197213-182.98896 63.996139 0 7.599542 2.399855 12.399252 9.599421 18.798866l1.99988 2.399855 0.799951 3.199807c20.998733 22.998612 31.798082 52.396839 31.798082 83.194981 0 157.390504-164.390082 285.382782-367.977799 285.382782-75.075471 0.599964-149.071006-17.798926-215.027027-53.796754 53.996742 115.03306 165.430019 195.188224 182.628981 207.627473 1.599903 1.099934 0.599964 1.679899 0.599964 1.679899z m31.198118-636.081624c-2.799831-59.99638 9.199445-119.992761 32.798021-174.389479 27.198359-52.796815 65.396055-101.993847 112.993183-138.591638-118.992821 22.998612-222.966548 87.794703-298.781974 178.589225C42.237452 143.383627 0 259.176641 0 380.169341c0 102.393822 124.792471 188.78861 271.983591 188.78861 73.195584 1.199928 144.791264-21.798685 203.587717-65.396054l-7.199566-2.399856c-102.993786-35.197876-196.988115-181.389056-196.988115-316.180924zM939.543315 95.986486l-1.399915-0.199987c-23.598576-37.597732-51.796875-70.195765-84.394908-98.994028-61.596284-55.996622-136.191783-90.99451-217.586873-99.793979-37.197756-0.599964-73.59556 6.399614-107.593509 22.798624-51.196911 20.598757-94.194317 59.99638-123.192567 105.993605-28.798263 47.797116-42.197454 103.393762-37.997708 159.190396-1.199928 40.197575 10.799348 80.595138 29.99819 116.392978 27.798323-66.196006 74.995475-122.592604 135.191844-161.590251 60.196368-38.997647 130.992097-58.996441 202.787766-57.196549 61.99626-0.599964 124.192507 13.399192 180.389116 40.997526l3.799771 1.799892c7.799529 4.599722 15.399071 7.799529 23.1986 0 8.999457-9.799409 3.599783-18.39889-2.399855-27.998311-0.399976-0.399976-0.599964-0.99994-0.799952-1.399916z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="leaf" unicode="&#59137;" d="M1017.948269 886.876437c-4.863707 5.785251-12.031275 9.113051-19.557222 9.113051l-26.110427 0c-258.032454 0.102394-461.847374 0.153591-611.905533-35.735447-80.635142-19.301237-142.992985-48.432282-190.606116-89.031436-51.401703-43.82456-86.420393-101.216302-107.155144-175.554223-13.77197-49.353826-20.222782-138.487656 6.96278-227.160714 10.034595-32.766026 25.700852-63.688963 46.589193-92.103251-62.255449-97.530124-116.063407-225.983185-116.063407-378.805977 0-14.130349 11.468109-25.598458 25.598458-25.598458s25.598458 11.468109 25.598458 25.598458c0 235.761795 139.665185 410.650458 222.91137 493.845446 59.7468 59.7468 127.275532 110.175762 195.367429 145.808815 63.381781 33.175601 123.947732 51.4529 170.536925 51.4529 14.130349 0 25.598458 11.468109 25.598458 25.598458s-11.468109 25.598458-25.598458 25.598458c-55.497456 0-122.667809-19.813206-194.241097-57.340545-72.597226-38.039308-144.477695-91.591282-207.80828-154.973063-26.72479-26.72479-58.876453-62.357843-90.823328-105.977615-12.389654 19.506025-22.014674 40.189579-28.619076 61.794677-25.598458 83.553366-16.178225 164.034917-6.604402 198.388047 73.211589 262.384191 351.313233 263.049751 855.858835 262.896161-60.156376-321.926204-172.328817-530.29765-333.599101-619.533873-149.597387-82.785412-297.966048-37.629733-354.845821-14.335136-11.980078 4.914904-24.06255 10.95614-35.786644 17.91892-12.133669 7.218765-27.851122 3.225406-35.069887-8.908263s-3.225406-27.851122 8.908263-35.069887c13.925561-8.2939 28.260697-15.461468 42.595834-21.349114 31.844481-13.004017 83.143791-29.694211 146.679163-35.172281 14.027955-1.228726 27.902319-1.791892 41.674289-1.791892 75.208269 0 145.860012 18.072511 210.675307 53.910352 82.375837 45.565255 153.641943 119.749585 211.904033 220.351524 68.296685 118.00889 119.698388 274.51786 152.720399 465.175173 1.279923 7.423553-0.767954 15.051893-5.631661 20.837145z"  horiz-adv-x="1025" />
+      
+      <glyph glyph-name="folder" unicode="&#60094;" d="M970.666667 682.666667H542.173333L429.793333 795.046667A52.986667 52.986667 0 0 1 392.08 810.666667H96a53.393333 53.393333 0 0 1-53.333333-53.333334v-704a53.393333 53.393333 0 0 1 53.333333-53.333333h874.666667a53.393333 53.393333 0 0 1 53.333333 53.333333V629.333333a53.393333 53.393333 0 0 1-53.333333 53.333334zM96 768h296.08a10.573333 10.573333 0 0 0 7.54-3.126667L481.826667 682.666667H96a53.546667 53.546667 0 0 1-10.666667-1.073334V757.333333a10.666667 10.666667 0 0 0 10.666667 10.666667z m885.333333-714.666667a10.666667 10.666667 0 0 0-10.666666-10.666666H96a10.666667 10.666667 0 0 0-10.666667 10.666666V629.333333a10.666667 10.666667 0 0 0 10.666667 10.666667h874.666667a10.666667 10.666667 0 0 0 10.666666-10.666667z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="folder-open" unicode="&#60097;" d="M1003.153333 491.04a52.933333 52.933333 0 0 1-42.38 20.96H896V629.333333a53.393333 53.393333 0 0 1-53.333333 53.333334H461.253333a10.573333 10.573333 0 0 0-7.54 3.126666L344.46 795.046667A52.986667 52.986667 0 0 1 306.746667 810.666667H53.333333a53.393333 53.393333 0 0 1-53.333333-53.333334v-704a53.393333 53.393333 0 0 1 53.333333-53.333333h796.893334a53.453333 53.453333 0 0 1 51.453333 39.333333l110.546667 405.333334a52.953333 52.953333 0 0 1-9.073334 46.373333zM53.333333 768h253.413334a10.573333 10.573333 0 0 0 7.54-3.126667l109.253333-109.253333A52.986667 52.986667 0 0 1 461.253333 640H842.666667a10.666667 10.666667 0 0 0 10.666666-10.666667v-117.333333H173.773333a53.453333 53.453333 0 0 1-51.453333-39.333333L42.666667 180.633333V757.333333a10.666667 10.666667 0 0 0 10.666666 10.666667z m917.726667-312.14l-110.546667-405.333333a10.666667 10.666667 0 0 0-10.286666-7.86H63.226667a10.666667 10.666667 0 0 0-10.286667 13.473333l110.546667 405.333333A10.666667 10.666667 0 0 0 173.773333 469.333333h787a10.666667 10.666667 0 0 0 10.286667-13.473333z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="gitee" unicode="&#59035;" d="M512-128C229.222-128 0 101.222 0 384S229.222 896 512 896s512-229.222 512-512-229.222-512-512-512z m259.149 568.883h-290.74a25.293 25.293 0 0 1-25.292-25.293l-0.026-63.206c0-13.952 11.315-25.293 25.267-25.293h177.024c13.978 0 25.293-11.315 25.293-25.267v-12.646a75.853 75.853 0 0 0-75.853-75.853h-240.23a25.293 25.293 0 0 0-25.267 25.293V478.797a75.853 75.853 0 0 0 75.827 75.853h353.946a25.293 25.293 0 0 1 25.267 25.292l0.077 63.207a25.293 25.293 0 0 1-25.268 25.293H417.152a189.62 189.62 0 0 1-189.62-189.645V124.85c0-13.977 11.316-25.293 25.294-25.293h372.94a170.65 170.65 0 0 1 170.65 170.65V415.616a25.293 25.293 0 0 1-25.293 25.267z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="github" unicode="&#59047;" d="M512 883.32190493c275.66730126 0 499.32190493-223.65460366 499.32190493-499.32190493 0-220.40901063-143.01411555-407.65472541-341.32813256-473.98131826-25.34058667-4.53550763-34.45321159 11.06830222-34.45321159 24.05067207 0 16.26957255 0.6657627 70.19633778 0.66576271 137.18869334 0 46.81142841-15.60380985 76.72913237-33.7874489 92.33294222 111.18234397 12.35821682 228.19011015 54.63413874 228.1901113 246.41536 0 54.63413874-19.51516445 98.82412715-51.34693604 133.9431003 5.20127033 13.02397952 22.09499477 63.70515285-5.20127033 132.61157604-41.61015922 13.02397952-137.18869333-51.34693603-137.18869333-51.34693604a469.36259015 469.36259015 0 0 1-249.6609519 0S291.63259904 689.58500523 250.02244096 676.56102571c-27.29626397-68.90642318-10.40253952-119.62920619-5.20127033-132.61157604-31.87338126-35.11897429-51.34693603-79.3089627-51.34693604-133.9431003 0-191.15706937 116.38361429-234.05714318 227.56595826-246.41536-14.31389411-13.02397952-27.29626397-35.11897429-31.87338126-66.95074588-28.62778937-13.02397952-101.44556715-35.11897429-144.96979285 41.61015921-27.29626397 47.47719111-76.72913237 51.34693603-76.72913351 51.34693604-48.76710571 0.6657627-3.24559189-30.54185699-3.2455919-30.541857 32.49753429-14.93804715 55.25829063-72.81777778 55.25829064-72.81777777 29.25194126-89.08735033 168.39631189-59.16964523 168.39631302-59.16964523 0-41.61015922 0.6657627-80.5988773 0.66576157-92.95709525 0-13.02397952-9.11262493-28.62778937-34.45321045-24.05067094C155.77543111-23.61311459000001 12.76131555 163.63259903999995 12.76131555 384.04160967c0 275.66730126 223.65460366 499.32190493 499.32190493 499.32190492zM201.87948715 166.21242937c1.28991459 2.62144-0.6657627 5.86703189-4.53550763 7.78109952-3.91135459 1.28991459-7.15694763 0.6657627-8.44686222-1.2899146-1.28991459-2.62144 0.6657627-5.86703189 4.53550763-7.78109952 3.24559189-1.9556773 7.15694763-1.28991459 8.44686222 1.2899146z m20.13931634-22.13660444c2.62144 1.9556773 1.9556773 6.49118493-1.2899146 10.40253952-3.24559189 3.24559189-7.78109952 4.53550763-10.40253952 1.95567729-2.62144-1.9556773-1.9556773-6.49118493 1.2899146-10.40253952 3.24559189-3.24559189 7.78109952-4.53550763 10.40253952-1.95567729z m19.51516444-29.25194127c3.24559189 2.62144 3.24559189 7.78109952 0 12.35821682-2.62144 4.53550763-7.78109952 6.49118493-11.06830222 3.91135459-3.24559189-1.9556773-3.24559189-7.15694763 0-11.69245411s8.44686222-6.49118493 11.06830222-4.53550763z m27.29626396-27.2962651c2.62144 2.62144 1.28991459 8.44686222-2.62144 12.35821795-4.53550763 4.53550763-10.40253952 5.20127033-13.02397952 1.9556773-3.24559189-2.62144-1.9556773-8.44686222 2.62144-12.35821682 4.53550763-4.53550763 10.40253952-5.20127033 13.02397952-1.95567843z m37.0746516-16.26957141c1.28991459 3.91135459-2.62144 8.44686222-8.44686223 10.40253952-5.20127033 1.28991459-11.06830222-0.6657627-12.35821681-4.53550763s2.62144-8.44686222 8.44686222-9.73677682c5.20127033-1.9556773 11.06830222 0 12.35821682 3.9113546z m40.94439651-3.24559304c0 4.53550763-5.20127033 7.78109952-11.06830222 7.15694763-5.86703189 0-10.40253952-3.24559189-10.40253952-7.15694763 0-4.53550763 4.53550763-7.78109952 11.06830222-7.15694648 5.86703189 0 10.40253952 3.24559189 10.40253952 7.15694648z m37.69880349 6.49118493c-0.6657627 3.91135459-5.86703189 6.49118493-11.69245412 5.86703303-5.86703189-1.28991459-9.73677682-5.20127033-9.11262492-9.73677796 0.6657627-3.91135459 5.86703189-6.49118493 11.69245411-5.20126918s9.73677682 5.20127033 9.11262493 9.11262492z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="disabled" unicode="&#59084;" d="M509.20496914 834c-245.9627332 0-447.20496914-201.24223594-447.20496914-447.20496914s201.24223594-447.20496914 447.20496914-447.20496914 447.20496914 201.24223594 447.20496914 447.20496914-201.24223594 447.20496914-447.20496914 447.20496914zM509.20496914-10.09937930000001C291.19254628-10.09937930000001 112.31055898 168.78260888 112.31055898 386.79503086c0 95.03105625 33.54037295 184.4720499 95.03105625 257.14285752l553.41614883-553.41614883C693.67701904 23.440993649999996 604.23602451-10.09937930000001 509.20496914-10.09937930000001z m296.27329131 134.16149092l-559.00621055 553.41614883C319.14285752 738.96894375 408.58385117 778.0993793 509.20496914 778.0993793c218.01242197 0 396.89441016-178.8819873 396.89441016-396.89441016 0-95.03105625-39.13043467-190.06211162-100.62111885-257.14285752z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="moon" unicode="&#59074;" d="M696.832 680.448c98.816-62.976 162.304-173.056 162.304-294.912 0-192.512-156.672-349.184-349.184-349.184-121.856 0-232.448 63.488-294.912 162.816h5.12c263.168 0 477.184 214.016 477.184 477.184-0.512 1.536-0.512 3.072-0.512 4.096m-78.336 103.936c9.216-34.304 14.336-70.656 14.336-108.032 0-228.352-184.832-413.184-413.184-413.184-37.376 0-73.728 5.12-108.544 14.336 47.616-175.616 207.872-305.152 398.848-305.152 228.352 0 413.184 184.832 413.184 413.184 0 190.976-129.024 351.232-304.64 398.848z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="error" unicode="&#59027;" d="M512-60.09287109000002c-245.26845703 0-444.09550781 198.82880859-444.09550781 444.09550781s198.82705078 444.09287109 444.09550781 444.09287109c245.26669922 0 444.09550781-198.82880859 444.09550781-444.09550781s-198.82880859-444.09287109-444.09550781-444.09287109zM512 772.58378906c-214.60166016 0-388.58378906-173.97861328-388.58378906-388.58378906s173.98125-388.58115234 388.58378906-388.58115234c214.60166016 0 388.58115234 173.97861328 388.58115234 388.58115234s-173.97861328 388.58378906-388.58115234 388.58378906zM551.41103516 383.85585937999997l117.60029297-117.62138672c10.84306641-10.82460938 10.84306641-28.40625 0-39.24580079-10.83955078-10.84306641-28.42119141-10.84306641-39.24580079 0l-117.62138671 117.60029297-118.39570313-118.39570312c-10.93271484-10.93095703-28.64091797-10.93095703-39.55517578 0-10.93271484 10.93095703-10.93271484 28.64091797 0 39.55693359l118.39570312 118.41240235-117.60292968 117.60292968c-10.84130859 10.84130859-10.84130859 28.40625 0 39.24931641 10.84306641 10.83955078 28.40625 10.83955078 39.2493164 0l117.60292969-117.60292969 119.28164063 119.28164063c10.93095703 10.91513672 28.64091797 10.91513672 39.55693359 0 10.93095703-10.93095703 10.93095703-28.64091797 0-39.57363281l-119.26757813-119.26582032z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="success" unicode="&#59031;" d="M661.31818174 521.04545479c10.22727305 12.27272695 30.68181826 14.31818174 42.95454521 4.09090868 12.27272695-10.22727305 14.31818174-30.68181826 4.09090957-42.95454521l-204.54545478-243.40909131c-10.22727305-12.27272695-30.68181826-14.31818174-42.95454522-4.09090869L327.90909131 345.13636347c-12.27272695 10.22727305-14.31818174 30.68181826-4.09090957 42.95454522 10.22727305 12.27272695 30.68181826 14.31818174 42.95454521 4.09090957l110.4545461-92.04545478 184.09090869 220.90909131zM512-66C262.45454521-66 62 134.45454521 62 384S262.45454521 834 512 834s450-200.45454521 450-450-200.45454521-450-450-450z m0 40.90909131c225 0 409.09090869 184.09090869 409.09090869 409.09090869S737 793.09090869 512 793.09090869 102.90909131 609 102.90909131 384s184.09090869-409.09090869 409.09090869-409.09090869z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="question" unicode="&#59033;" d="M468.125 159a37.50000029 37.50000029 0 1 1 37.50000029 37.50000029 37.50000029 37.50000029 0 0 1-37.50000029-37.50000029z m37.50000029 92.62500029h-3.00000058a31.5 31.5 0 0 0-28.49999942 34.49999971A203.24999971 203.24999971 0 0 0 549.50000029 400.12500029c56.62500029 56.62500029 57.75000029 74.99999971 58.5 93.74999942a81.37500029 81.37500029 0 0 1-23.25000058 60.75A98.62499971 98.62499971 0 0 1 512 584.99999971a94.5 94.5 0 0 1-94.5-94.5 31.5 31.5 0 1 0-63.37500029 0A157.5 157.5 0 0 0 512 646.50000029a162.37500029 162.37500029 0 0 0 117.74999971-50.25000058 144.37500029 144.37500029 0 0 0 39.75000029-105.75c-2.25-40.87500029-14.625-72.74999971-77.24999971-135-31.5-31.5-51.75-55.50000029-53.62500058-74.99999971a31.5 31.5 0 0 0-31.12499971-29.99999971z m277.875-139.87500029A386.62499971 386.62499971 0 1 0 361.99999971 740.24999971a386.62499971 386.62499971 0 0 0 423.37500029-629.62499971zM512 834a450 450 0 1 1 450-450A450 450 0 0 1 512 834z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="lock" unicode="&#59034;" d="M512-66A450 450 0 1 0 962 384 450.39130401 450.39130401 0 0 0 512-66z m0 860.86956533A410.86956533 410.86956533 0 1 1 922.86956533 384 411.26086934 411.26086934 0 0 1 512 794.86956533zM665.78260888 398.86956533h-14.47826132v78.26086934a139.69565244 139.69565244 0 0 1-279-7.82608711v-70.04347823h-11.73912979a19.95652177 19.95652177 0 0 1-19.95652178-20.34782577v-199.56521778a19.95652177 19.95652177 0 0 1 19.95652178-20.34782578h302.86956445a19.95652177 19.95652177 0 0 1 19.95652179 20.34782578v199.56521778a20.73913067 20.73913067 0 0 1-17.60869513 19.95652177z m-254.34782665 70.43478223a100.56521777 100.56521777 0 0 0 200.73913066 4.69565244v-74.73913067H411.43478223z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="eye" unicode="&#59029;" d="M513.92 449.493333a64 64 0 1 0-64-64 64 64 0 0 0 64 64m0 64a128 128 0 1 1 128-128 128 128 0 0 1-128 128zM512 606.2933330000001c128 0 257.706667-67.84 397.226667-207.146666a21.333333 21.333333 0 0 0 0-30.08C770.133333 229.54666699999996 640 161.70666700000004 512 161.70666700000004s-257.28 67.84-396.8 207.146666a21.333333 21.333333 0 0 0 0 30.08c139.52 139.52 268.8 207.36 396.8 207.36m0 64c-145.92 0-291.84-75.306667-442.453333-225.92a85.333333 85.333333 0 0 1 0-120.746666C220.586667 173.013333 366.506667 97.70666700000004 512 97.70666700000004s292.266667 75.306667 442.666667 225.92a85.333333 85.333333 0 0 1 0 120.746666C804.266667 594.986667 658.346667 670.293333 512 670.293333z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="eye-invisible" unicode="&#59030;" d="M386.346667 391.466667l121.813333 121.813333a128 128 0 0 1-121.813333-121.813333z m238.72 57.6L576 400.213333a64 64 0 0 0-76.8-76.8l-48.853333-48.853333a128 128 0 0 1 174.506666 174.506667zM109.013333 384a21.333333 21.333333 0 0 0 6.186667 15.146667c139.52 139.306667 268.8 207.146667 396.8 207.146666a372.266667 372.266667 0 0 0 79.786667-8.96l52.266666 52.266667a443.52 443.52 0 0 1-132.053333 21.333333c-145.92 0-291.84-75.306667-442.453333-225.92a85.333333 85.333333 0 0 1 0-120.746666 1063.04 1063.04 0 0 1 134.186666-115.2l45.866667 45.866666a985.813333 985.813333 0 0 0-134.4 114.133334 21.333333 21.333333 0 0 0-6.186667 14.933333z m845.653334 60.373333a966.613333 966.613333 0 0 1-185.813334 149.333334l-46.72-46.72a877.653333 877.653333 0 0 0 187.306667-147.2 21.333333 21.333333 0 0 0 0-30.08C770.133333 229.54666699999996 640 161.70666700000004 512 161.70666700000004a393.386667 393.386667 0 0 0-145.706667 29.013333l-48.64-48.64A466.133333 466.133333 0 0 1 512 97.70666700000004c145.92 0 291.84 75.306667 442.453333 225.92a85.333333 85.333333 0 0 1 0.213334 120.746666zM777.267604 692.049287m22.627417-22.627417l0 0q22.627417-22.627417 0-45.254834l-527.973064-527.973063q-22.627417-22.627417-45.254834 0l0 0q-22.627417 22.627417 0 45.254834l527.973064 527.973063q22.627417 22.627417 45.254834 0Z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="backspace" unicode="&#59028;" d="M484.46100645 268.09861505000003a28.76779355 28.76779355 0 0 0-20.34016344 49.107957l174.2671828 174.27268816a28.76779355 28.76779355 0 0 0 40.68473118-40.68032687l-174.2671828-174.27819355a28.6940215 28.6940215 0 0 0-20.34456774-8.42322581zM658.72708818 268.09861505000003a28.68301076 28.68301076 0 0 0-20.34016345 8.42322581l-174.26718279 174.27709248a28.76228818 28.76228818 0 0 0 0 40.68032687 28.75127742 28.75127742 0 0 0 40.68142795 0l174.2671828-174.27268816a28.77990537 28.77990537 0 0 0-20.34126451-49.107957zM834.5379785 74.81145805999995H340.57028818c-28.46940215 0-55.25305806 12.53684301-73.49016775 34.39428818L75.75838279 339.01887310999996c-10.54830108 13.06205592-16.20232258 28.91974194-16.1968172 44.98663226 0.00660645 15.39083011 4.67406452 29.85015053 13.50248602 41.81333334 0.33803011 0.45694624 0.68266666 0.90288172 1.04822366 1.33009892L266.70685592 658.36593548a95.32449032 95.32449032 0 0 0 73.86233118 34.82921291H834.5379785c51.98286452 0 94.27516559-42.28789677 94.27516558-94.27076129v-429.83776344c0-51.98286452-42.29230108-94.27516559-94.27516558-94.2751656zM119.01522581 391.16579785c-0.90728602-1.35872689-1.91587097-3.52344086-1.91587097-7.17680861 0-2.92005161 1.14952258-6.01517419 3.15568172-8.50140214l191.02114409-229.45307528a38.55965592 38.55965592 0 0 1 29.29300645-13.69297203H834.5379785a36.78472258 36.78472258 0 0 1 36.74508387 36.74508387v429.83776344a36.78472258 36.78472258 0 0 1-36.74508387 36.73957849H340.5691871a38.60590108 38.60590108 0 0 1-29.53524302-13.96934193L119.01522581 391.16579785z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="tips-fill" unicode="&#60206;" d="M512 832C264.6 832 64 631.4 64 384s200.6-448 448-448 448 200.6 448 448S759.4 832 512 832z m-32-232c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8v-272c0-4.4-3.6-8-8-8h-48c-4.4 0-8 3.6-8 8V600z m32-440c-26.5 0-48 21.5-48 48s21.5 48 48 48 48-21.5 48-48-21.5-48-48-48z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="test" unicode="&#59026;" d="M513.058-31.072000000000003c-56.004 0-110.35 10.976-161.528 32.622-49.416 20.901-93.789 50.816-131.887 88.914-38.098 38.099-68.013 82.472-88.915 131.888-21.646 51.178-32.622 105.524-32.622 161.528s10.976 110.35 32.622 161.528c20.901 49.416 50.816 93.789 88.915 131.887s82.471 68.013 131.887 88.915c51.178 21.646 105.524 32.622 161.528 32.622 64.817 0 126.912-14.538 184.56-43.209 54.937-27.323 104.055-67.35 142.042-115.754 10.911-13.903 8.486-34.019-5.417-44.93-13.903-10.91-34.018-8.485-44.929 5.417-67.071 85.461-167.763 134.476-276.256 134.476-193.516 0-350.952-157.436-350.952-350.952s157.436-350.952 350.952-350.952c200.075 0 350.952 141.419 350.952 328.952 0 17.673 14.327 32 32 32s32-14.327 32-32c0-109.988-43.501-210.61-122.49-283.33-76.785-70.692-180.65-109.622-292.462-109.622zM636.555 275.40700000000004c-5.39 0-10.85 1.362-15.862 4.23-15.34 8.776-20.66 28.327-11.884 43.667L781.3 624.79c8.776 15.341 28.33 20.661 43.667 11.884 15.34-8.777 20.66-28.327 11.884-43.667L664.359 291.52099999999996c-5.908-10.327-16.703-16.114-27.804-16.114zM628.023 263.38199999999995a31.856 31.856 0 0 0-19.204 6.424L403.383 424.242c-14.127 10.62-16.97 30.681-6.35 44.807 10.62 14.127 30.68 16.97 44.807 6.35l205.437-154.438c14.127-10.619 16.97-30.68 6.35-44.807-6.289-8.363-15.888-12.772-25.604-12.772zM219.079 140.418a31.849 31.849 0 0 0-18.931 6.222c-14.238 10.47-17.293 30.499-6.823 44.737l202.489 275.372c10.468 14.239 30.499 17.294 44.737 6.823 14.238-10.47 17.293-30.499 6.823-44.737L244.885 153.46299999999997c-6.271-8.528-15.974-13.045-25.806-13.045z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="clear" unicode="&#59272;" d="M508.412288-59.874413000000004c-246.585071 0-447.224718 200.684672-447.224718 447.441659 0 246.738567 200.639646 447.448822 447.224718 447.448822 246.622934 0 447.2503-200.710254 447.2503-447.448822C955.661565 140.81025899999997 755.035222-59.874413000000004 508.412288-59.874413000000004zM685.286672 527.07151l-45.177945 45.215808L504.588193 436.690036 369.06766 572.287317l-45.184085-45.215808 135.520533-135.591141L323.883575 255.88411099999996l45.184085-45.184085 135.520533 135.583978 135.520533-135.583978 45.177945 45.184085L549.766139 391.480368 685.286672 527.07151z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="heart-fill" unicode="&#59023;" d="M729.068827 776.44202c-94.686523 0-176.905082-48.314379-217.069851-118.640074-40.163745 70.325695-122.382305 118.640074-217.044268 118.640074-143.767358 0-229.665727-123.660414-229.665727-243.219417 0-283.128359 415.870616-527.841803 433.576883-538.126031 4.062526-2.363837 8.584516-3.538593 13.132088-3.538593 4.547573 0 9.070586 1.174756 13.132088 3.538593 17.706267 10.283204 433.576883 254.997672 433.576883 538.126031C958.708971 652.781606 872.811626 776.44202 729.068827 776.44202z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="light" unicode="&#59208;" d="M512 72c-172.313 0-312 139.687-312 312s139.687 312 312 312 312-139.687 312-312-139.687-312-312-312z m0 64c136.967 0 248 111.033 248 248 0 136.967-111.033 248-248 248-136.967 0-248-111.033-248-248 0-136.967 111.033-248 248-248z m0 696c17.673 0 32-14.327 32-32v-51c0-17.673-14.327-32-32-32-17.673 0-32 14.327-32 32V800c0 17.673 14.327 32 32 32z m0-785c17.673 0 32-14.327 32-32v-51c0-17.673-14.327-32-32-32-17.673 0-32 14.327-32 32v51c0 17.673 14.327 32 32 32z m325.945 11.055c-12.497-12.496-32.758-12.496-45.255 0l-36.063 36.063c-12.496 12.497-12.496 32.758 0 45.255 12.497 12.496 32.758 12.496 45.255 0l36.063-36.063c12.496-12.497 12.496-32.758 0-45.255z m-568 565c-12.497-12.496-32.758-12.496-45.255 0l-36.063 36.063c-12.496 12.497-12.496 32.758 0 45.255 12.497 12.496 32.758 12.496 45.255 0l36.063-36.063c12.496-12.497 12.496-32.758 0-45.255z m561 81.318c12.496-12.497 12.496-32.758 0-45.255l-36.063-36.063c-12.497-12.496-32.758-12.496-45.255 0-12.496 12.497-12.496 32.758 0 45.255l36.063 36.063c12.497 12.496 32.758 12.496 45.255 0z m-563.572-565c12.496-12.497 12.496-32.758 0-45.255l-36.063-36.063c-12.497-12.496-32.758-12.496-45.255 0-12.496 12.497-12.496 32.758 0 45.255l36.063 36.063c12.497 12.496 32.758 12.496 45.255 0zM960 384c0-17.673-14.327-32-32-32h-51c-17.673 0-32 14.327-32 32 0 17.673 14.327 32 32 32h51c17.673 0 32-14.327 32-32z m-781 0c0-17.673-14.327-32-32-32H96c-17.673 0-32 14.327-32 32 0 17.673 14.327 32 32 32h51c17.673 0 32-14.327 32-32z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="music" unicode="&#59024;" d="M575.4 832h-74.5v-633.5C385 251.20000000000005 249.3 180.70000000000005 226.8 76c-7.3-34.1 7.9-70.9 21.9-87.8 79.3-94.6 252.2-50.5 331.6 51.3 35.2 45.2 32.3 84.6 32.3 181.3V608.5c48.8-36.3 103.9-70.1 123.7-135 12.2-40.3-4.1-107.3-17-141.5-3.9-10.3-14.7-18.9-9.7-29.2 34.2-25.4 51.1 28.6 60.9 51.2 10.6 24.5 20.8 54.7 24.4 75.6C833.2 653.2 595.5 661.7 575.4 832z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="time" unicode="&#59021;" d="M511.98464 829.44c-118.97856 0-230.83008-46.35136-314.95168-130.4832C112.90624 614.84032 66.56 502.95808 66.56 384.00512c0-118.9632 46.34624-230.84544 130.47296-314.9568C281.15456-15.093759999999975 393.00608-61.440000000000055 511.98464-61.440000000000055c118.98368 0 230.84032 46.34624 314.9824 130.48832C911.09376 153.15967999999998 957.44 265.02144 957.44 384.00512c0 118.97856-46.34624 230.8352-130.47296 314.95168C742.82496 783.0886399999999 630.96832 829.44 511.98464 829.44z m275.58912-721.02912c-73.61024-73.63584-171.47904-114.18624-275.58912-114.18624s-201.97376 40.5504-275.57888 114.18624c-73.63584 73.61024-114.16064 171.47904-114.16064 275.59424 0 104.11008 40.54528 201.97376 114.18112 275.58912 73.60512 73.63072 171.47392 114.176 275.584 114.176s201.97376-40.54528 275.584-114.176c73.63584-73.61536 114.18112-171.47904 114.18112-275.58912 0-104.1152-40.56576-201.984-114.2016-275.59424zM519.1168 340.20863999999995V628.08064a27.8528 27.8528 0 0 1-27.84256 27.84768 27.8528 27.8528 0 0 1-27.84256-27.84768v-306.23232a27.81184 27.81184 0 0 1 16.88064-25.58976M734.70464 321.84831999999994a31.0784 31.0784 0 0 0-31.07328-31.0784H496.44544a31.08864 31.08864 0 0 0-31.07328 31.0784 31.09376 31.09376 0 0 0 31.07328 31.0784h207.18592a31.08864 31.08864 0 0 0 31.07328-31.0784z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="ie" unicode="&#59323;" d="M740.32 314.46399999000005l221.2992 0c1.7088 15.3408 2.3808 31.0272 2.3808 47.0592 0 75.2064-20.1792 145.7472-55.4304 206.496 36.4416 96.8448 35.1552 179.0592-13.6512 228.1728-46.4064 46.1952-170.8992 38.7072-311.6352-23.616-10.4064 0.7872-20.928 1.1904-31.5264 1.1904-193.1712 0-355.2384-132.9408-400.032-312.0384 60.5952 77.5872 124.3392 133.824 209.5104 174.7968-7.7376-7.2576-52.9344-52.1664-60.5184-59.7696-224.5824-224.5056-295.392-517.7856-219.1872-594.0096 57.9264-57.9072 162.8928-48.1344 283.4688 10.9248 56.064-28.5504 119.5392-44.6592 186.7584-44.6592 181.056 0 334.5024 116.544 390.0864 278.8608l-223.008 0c-30.6816-56.6016-90.7008-95.136-159.5712-95.136s-128.8896 38.5344-159.5712 95.136c-13.632 25.5744-21.4848 54.8928-21.4848 85.92l0 0.672 362.112 0zM378.5344 423.25119999c5.1072 91.0464 80.8128 163.68 173.2224 163.68s168.096-72.6336 173.2224-163.68l-346.4448 0zM892.9024 750.43839999c31.4304-31.7568 30.6432-90.2016 3.7632-163.1424-46.0608 70.2336-112.992 125.568-192 157.1712 84.48 36.2304 153.1968 41.0304 188.2368 5.9904zM139.648-2.79680000999997c-40.1088 40.128-28.0128 124.32 23.6544 225.7728 32.16-90.2592 94.8288-166.0224 175.6224-214.8288-89.472-40.608-162.6816-47.5008-199.2768-10.944z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="firefox" unicode="&#59014;" d="M515.52500029-47.25q-142.12500029 0-253.36874971 75.58125029t-165.4875 200.1375q-29.1375 65.79375029-33.6562497 151.18125029t13.05 166.98750029 55.74375 156.6937503 89.9062497 121.7999997l-5.5312497-141.13125q5.53124971 7.03125 34.14375 7.78124971t35.15625-7.78124971q21.09375 40.68749971 80.60625 69.3t117.76875029 29.6250003q-27.1125-22.59375029-60.01875-74.5875t-29.38124971-82.1062503q12.56249971-4.01249971 31.3875-6.78750029t31.65000029-3.76875 34.14375-2.00625029 25.36875-1.50000029q7.5375-2.51250029 4.7625003-22.85624971t-15.31874971-37.9125q-2.51250029-3.52500029-8.28749971-9.29999971t-28.36874971-17.83125-50.71875029-17.08125029l7.5375-94.93125029-69.80625 33.6562497q-9.03750029-21.6-3.76875-40.93125029t18.07499971-33.39375029 32.88750029-20.85000029 40.68749971-3.2625q25.61249971 4.51874971 49.21875 17.325t41.94375029 22.59375029 36.91874971 8.79374971q30.63750029-2.00625029 44.94375-16.5750003t9.7875-32.6437497q-0.50625-1.0125-1.25624971-2.75625t-4.275-6.2812503-9.03750029-7.7812497-15.82499971-5.2687503-23.3624997-0.50625q-30.13125029-47.71874971-72.5812497-68.04375029t-105.2250003-14.81249971q37.16250029-30.63750029 81.61875-41.43750029t84.6187497-3.01875029 77.58749971 26.11874971 64.29375 43.9499997 40.42500029 52.2375003q21.6 45.71250029 19.59374971 96.67500029t-18.82500029 94.66875-39.43125 62.775q43.68750029-19.08749971 68.8124997-39.91875029t38.6812503-56.49374971q7.5375 85.3875-28.87499971 172.27500029t-105.22500029 142.63125029q133.0875-38.68125029 206.92500029-140.38125029t75.84374971-259.91250029q1.0125-63.7875-20.3437503-128.06250029t-62.02500029-119.53125-94.93125029-98.4375-124.29375029-68.0437503-144.9-24.8625z"  horiz-adv-x="1025" />
+      
+      <glyph glyph-name="at" unicode="&#59015;" d="M514.162246 831.556269c-246.201331 0-446.51045-200.783932-446.51045-447.571618 0-246.772336 201.037712-447.539896 448.157973-447.539896 50.29857 0 99.615788 8.224312 146.523121 24.436552 18.414395 6.370081 31.060413 12.423961 31.472805 12.630668 7.194866 3.217275 12.614296 9.049097 15.213493 16.401552 2.63092 7.305383 2.155083 15.133675-1.299599 22.043039l-2.883677 5.831822c-7.131421 14.262842-24.974811 20.569478-40.156582 13.850449-0.031722-0.031722-5.8001-3.02694-20.094664-8.082072-41.075511-14.627139-84.21196-22.059412-128.235616-22.059412-210.92592 0-382.487298 171.57775-382.487298 382.487298S305.423131 766.487298 516.349051 766.487298c210.894198 0 382.455575-171.5931 382.455575-382.423853-0.887206-51.868321-13.882172-100.486622-36.606733-136.855948-20.664645-33.104979-46.939055-51.994188-72.199369-51.994188-0.317225 0-0.601704 0-0.887206 0-45.829791 0.792039-75.433016 68.586075-75.433016 172.718737l0 185.269587c0 5.53097-1.426489 9.635451-4.373611 12.550851-4.944616 4.944616-12.360516 4.817726-21.267373 4.864798l-2.472308-0.016373-9.223059 0.016373c-7.701402-0.031722-13.469779 0.063445-17.495466-3.945869-3.645017-3.613294-4.119831-9.096169-4.119831-13.469779l0-31.060413c-45.196365 36.100196-80.440054 59.474556-131.9758 60.378136-1.045819 0.016373-2.059915 0.031722-3.074012 0.031722-108.74368 0-198.470237-99.218746-200.657043-222.779899-2.155083-124.701117 84.845387-227.723491 193.969737-229.625818 1.045819-0.01535 2.059915-0.031722 3.074012-0.031722 63.293535 0 122.276904 34.087353 159.992901 92.103698 24.373107-60.251246 61.519122-91.216491 110.48637-92.071975 0.697895-0.01535 1.394766-0.01535 2.060939-0.01535 33.945113 0 66.716494 14.610766 94.924953 42.328038 47.63695 46.796816 76.066443 124.796284 76.066443 208.643947l0 2.883677C959.595154 630.772336 759.761873 831.556269 514.162246 831.556269zM646.73975 354.651578c0-92.230588-58.475809-167.282934-130.390699-167.282934s-130.390699 75.052347-130.390699 167.282934c0 92.246961 58.475809 167.298284 130.390699 167.298284S646.73975 446.897515 646.73975 354.651578z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="bluetooth" unicode="&#59017;" d="M844.799642 221.19607699999995L538.533306 374.84141l307.696917 177.029926c10.583033 5.006014 17.398252 15.59621 17.569144 27.302833s-6.332219 22.491247-16.764825 27.804253L475.584626 830.045869c-9.517771 4.846378-20.869307 4.39817-29.974685-1.181919-9.105379-5.581112-14.656815-15.493879-14.656815-26.174126l0-288.760636L210.662931 699.284733c-12.974499 10.915607-32.339546 9.248641-43.255153-3.724835-10.915607-12.973476-9.248641-32.339546 3.724835-43.255153L430.953126 433.687656l0-102.83511L171.558307 120.428046c-13.166881-10.68127-15.181771-30.013571-4.500501-43.180452 6.068206-7.480368 14.924921-11.360745 23.859407-11.360745 6.794753 0 13.634532 2.245134 19.322068 6.859221l220.714867 179.046862 0-283.065937c0-10.689457 5.561669-20.61041 14.680351-26.188452 4.903683-2.99931 10.455119-4.510734 16.019859-4.510734 4.78498 0 9.580193 1.118474 13.980409 3.368724l371.449917 224.085638c10.664897 5.456269 17.182334 16.618493 16.691147 28.589129C863.284645 206.04091200000005 855.875908 216.63110800000004 844.799642 221.19607699999995zM763.458055 580.639542L492.351498 420.917818l0 21.60711c0.563842 3.368724 0.558725 6.801916 0 10.153244L492.351498 752.604102 763.458055 580.639542zM492.351498 18.915047999999956L492.351498 311.51001199999996c0.558725 3.347235 0.562818 6.777357 0 10.146081l0 5.809309 267.472797-137.65822L492.351498 18.915047999999956z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="chrome" unicode="&#59018;" d="M515.436 583.685H914.285C840.842 730.955 688.748 832.132 513 832.132c-141.284 0-267.274-65.395-349.42-167.546l151.66-262.682c8.535 102.325 95.704 181.781 200.196 181.781zM514.218 550.803c-91.476 0-165.631-74.155-165.631-165.631s74.155-165.631 165.631-165.631c52.7 0 99.615 24.642 129.95 62.999l1.428 2.474 0.355-0.205c21.252 27.852 33.898 62.624 33.898 100.363 0 84.774-63.702 154.626-145.841 164.413l-6.393 0.632c-4.424 0.354-8.882 0.586-13.397 0.586zM929.561 549.585H627.443c52.209-36.066 86.506-96.297 86.506-164.413 0-45.547-18.268-81.598-41.12-121.192L483.898-63.257c9.624-0.617 19.322-0.966 29.102-0.966 247.521 0 448.177 200.656 448.177 448.177 0 58.508-11.225 114.391-31.616 165.631zM514.218 185.441c-83.583 0-144.927 54.804-185.034 124.651l-0.235-0.136-187.482 324.727C93.081 563.124 64.823 476.84 64.823 383.954c0-225.02 165.839-411.288 381.958-443.298l152.278 263.752c-25.769-12.143-54.518-18.967-84.841-18.967z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="heart" unicode="&#59020;" d="M512 4.100000000000023c-108.9 0-447.3 277.5-447.3 522.2 0 131 106.6 237.6 237.6 237.6 94.9 0 174.8-50.2 209.7-76.1 34.9 25.9 114.8 76.1 209.7 76.1 131 0 237.6-106.6 237.6-237.6 0-244.7-338.4-522.2-447.3-522.2zM302.3 708c-100.2 0-181.7-81.5-181.7-181.7 0-221 326.8-466.3 391.4-466.3s391.4 245.3 391.4 466.3c0 100.2-81.5 181.7-181.7 181.7-103.9 0-190.2-76-191.1-76.8-10.6-9.5-26.7-9.5-37.3 0-0.8 0.8-87.7 76.8-191 76.8z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="key" unicode="&#59011;" d="M819.2 588.8c0-172.8-140.8-307.2-307.2-307.2-172.8 0-307.2 140.8-307.2 307.2C204.8 755.2 339.2 896 512 896S819.2 755.2 819.2 588.8L819.2 588.8zM512 838.4c-140.8 0-249.6-115.2-249.6-249.6 0-134.4 108.8-256 249.6-256s256 115.2 256 249.6S652.8 838.4 512 838.4L512 838.4zM480 300.79999999999995l64 0L544-128l-64 0L480 300.79999999999995 480 300.79999999999995zM512 192l192 0 0-64L512 128 512 192 512 192zM512 64l192 0 0-64L512 0 512 64 512 64z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="android" unicode="&#59012;" d="M391.405714 662.66209566a22.308571 22.308571 0 0 1 0 44.544c-11.995429 0-21.723429-10.276571-21.723428-22.272s9.728-22.272 21.723428-22.272z m241.152 0c11.995429 0 21.723429 10.276571 21.723429 22.272s-9.728 22.272-21.723429 22.272a22.308571 22.308571 0 0 1 0-44.544zM168.539429 557.51923766a58.514286 58.514286 0 0 0 58.294857-58.294857v-245.723428c0-32.585143-25.709714-58.843429-58.294857-58.843429S109.696 220.95238066000002 109.696 253.50095266000005v245.723428c0 32 26.294857 58.294857 58.843429 58.294857z m605.732571-10.861714v-380.562286c0-34.852571-28.013714-62.866286-62.281143-62.866285h-42.861714v-129.718857c0-32.585143-26.294857-58.843429-58.843429-58.843429s-58.843429 26.294857-58.843428 58.843429v129.718857H472.594286v-129.718857c0-32.585143-26.294857-58.843429-58.843429-58.843429a58.660571 58.660571 0 0 0-58.294857 58.843429l-0.585143 129.718857H312.594286a62.683429 62.683429 0 0 0-62.866286 62.866285V546.6575236599999h524.580571z m-132.571429 231.424c80.018286-41.142857 134.290286-119.990857 134.290286-210.870857H247.424c0 90.843429 54.272 169.728 134.838857 210.870857L341.705143 852.94323766a8.338286 8.338286 0 0 0 2.852571 11.446858c3.986286 1.718857 9.142857 0.585143 11.446857-3.437715L397.147429 785.50552366c34.852571 15.433143 73.728 23.990857 114.870857 23.990857s80.018286-8.557714 114.870857-23.990857l41.142857 75.446857c2.304 3.986286 7.424 5.156571 11.446857 3.437715a8.338286 8.338286 0 0 0 2.852572-11.446858zM914.267429 499.22438066v-245.723428c0-32.585143-26.294857-58.843429-58.843429-58.843429a58.660571 58.660571 0 0 0-58.294857 58.843429v245.723428a58.148571 58.148571 0 0 0 58.294857 58.294857c32.585143 0 58.843429-25.709714 58.843429-58.294857z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="mike" unicode="&#59100;" d="M512 256c115.2 0 208 92.8 208 208V624c0 115.2-92.8 208-208 208s-208-92.8-208-208v-160c0-115.2 92.8-208 208-208zM368 624c0 80 64 144 144 144s144-64 144-144v-160c0-80-64-144-144-144s-144 64-144 144V624zM844.8 416c0 17.6-14.4 32-32 32-16 0-30.4-12.8-32-28.8C758.4 289.6 646.4 192 512 192s-246.4 97.6-268.8 227.2c-1.6 16-16 28.8-32 28.8-17.6 0-32-14.4-32-32v-4.8C204.8 260.79999999999995 328 144 480 129.60000000000002V-32c0-17.6 14.4-32 32-32s32 14.4 32 32V129.60000000000002c152 14.4 275.2 131.2 299.2 280 0 1.6 1.6 4.8 1.6 6.4z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="mute" unicode="&#59013;" d="M739 294.4l180.2 180.2M735.391 297.9l180.24 180.24 7.07-7.07-180.239-180.24zM631.4-29.700000000000045c-5.1 0-10.1 1.3-14.5 3.7L277.1 162.20000000000005H116.8c-16 0-28.9 13-28.9 28.9v384c0 16 13 28.9 28.9 28.9h160.3l339.7 189.9c4.5 2.5 9.5 3.8 14.6 3.8 5.3 0 10.6-1.4 15.1-4.1 9.1-5.3 14.8-15.2 14.8-25.8v-767.6c0-10.5-5.6-20.4-14.7-25.8-4.6-2.7-9.9-4.1-15.2-4.1zM305.8 551.5v-336.7L601.4 51V716.8L305.8 551.5zM145.7 220.10000000000002h102.2v326H145.7v-326zM913.2 258.9c-9.3 0-18.1 3.6-24.7 10.3l-63.4 63.4-63.4-63.4c-6.6-6.6-15.4-10.3-24.7-10.3s-18.1 3.6-24.7 10.3c-13.6 13.6-13.6 35.9 0 49.5l63.4 63.4-67.4 67.4c-6.6 6.6-10.3 15.4-10.3 24.7 0 9.3 3.6 18.1 10.3 24.7 6.6 6.6 15.4 10.3 24.7 10.3s18.1-3.6 24.7-10.3l67.4-67.4 67.4 67.4c6.6 6.6 15.4 10.3 24.7 10.3s18.1-3.6 24.7-10.3c6.6-6.6 10.3-15.4 10.3-24.7 0-9.3-3.6-18.1-10.3-24.7L874.6 382l63.4-63.4c13.6-13.6 13.6-35.9 0-49.5-6.7-6.6-15.5-10.2-24.8-10.2z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="gift" unicode="&#58919;" d="M796.3 600h-6.7c5.1 6.7 9.6 13.4 13.4 20.1 18.3 32.2 20.8 63.1 7 87.1-9.1 15.7-33 41.2-91.9 36-35.4-3.2-76.1-17.2-114.7-39.4-37.9-21.9-68.9-49.3-89-77.5-4.5 6.4-9.5 12.8-15.1 19.1-19.8 22.3-45.4 42.8-74.1 59.4-38.4 22.2-79.3 35.9-115.1 38.5-43.3 3.2-75.8-10-91.4-37-13.8-24-11.3-54.8 7-86.7 3.7-6.5 8.1-13 13.1-19.5H236c-21.3 0-41.6-7.2-57.4-20.2-17.8-14.9-27.6-35.4-27.6-58v-50.8c0-34.4 23-64.6 55-76.6v-283.9c0-23.3 10.9-47.1 30.1-65.3 18.3-17.4 41.4-27.3 63.4-27.3h434.3c22 0 44.9 10 63 27.6 18.7 18.1 29.3 41.8 29.3 65.1V395c11 4.3 19.6 10.9 27.2 19.5 13.3 15.1 20.8 35.2 20.8 56.6v50.8c-0.1 45.3-32.8 78.1-77.8 78.1z m17.7-78.1v-50.8c0-7.7-3.2-20.3-15-22-0.9 0.1-1.7 0.1-2.6 0.1-1.5 0-2.9-0.1-4.3-0.3H543v91h253.3c11.9 0.1 17.7-5.8 17.7-18zM633.4 651.8c30.7 17.7 63.5 29.2 90 31.6 21.5 1.9 32.6-2.8 34.6-6.3 4.2-7.3-6.3-41.2-52.9-77.2H569.8c14 17 35.3 35.6 63.6 51.9z m-362.8 24.4c2.2 3.7 13.3 8.7 35 7.1 26.6-1.9 59.2-13.1 89.5-30.6 27.7-16 49.4-35.1 63.9-52.8H323.5c-20.3 15.6-36.4 32.9-45.8 49.4-8.9 15.6-8.5 24.4-7.1 26.9zM211 521.9c0 11.2 12.9 18.1 24.9 18.1H483v-91H240.1c-1.4 0.2-2.8 0.3-4.3 0.3-0.9 0-1.8 0-2.7-0.1-11.5 1.5-22.1 11.6-22.1 22v50.7z m55-411.3V389h217v-311H299.4c-13.2 0-33.4 17.5-33.4 32.6zM733.7 78H543V389h223v-278.4c0-15.5-19.1-32.6-32.3-32.6z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="windows" unicode="&#59007;" d="M437 329l0-325.5-341 47 0 278.5 341 0zm0 371.5l0-329.5-341 0 0 282.5zm491-371.5l0-393-453.5 62.5 0 330.5 453.5 0zm0 439l0-397-453.5 0 0 334.5z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="ios" unicode="&#59008;" d="M821.235026 351.984884c-1.287001 129.729651 105.791442 191.891776 110.553344 194.980577-60.102924 88.030835-153.796561 100.12864-187.258574 101.54434-79.794032 7.979403-155.598362-46.975519-196.010178-46.975519-40.411816 0-102.831341 45.688518-168.983167 44.530218-86.872534-1.287001-167.052666-50.57912-211.840284-128.442651-90.347436-156.756662-23.166009-388.931554 64.864826-515.958505 42.985817-62.162125 94.337137-132.046252 161.647264-129.600951 64.864826 2.574001 89.317835 41.956217 167.696167 41.956217s100.38604-41.956217 169.111867-40.669216c69.755428 1.287001 114.028245 63.449125 156.756662 125.86865 49.42082 72.200729 69.755428 142.084856 70.913728 145.559758C957.14228 145.550002 822.522026 197.030023 821.235026 351.984884L821.235026 351.984884 821.235026 351.984884zM692.277575 732.550935c35.778614 43.371917 59.845524 103.474841 53.281821 163.449065-51.48002-2.059201-113.899545-34.234214-150.83646-77.477431C561.647023 780.041254 532.560811 718.78003 540.411514 660.092806 597.811737 655.588305 656.49896 689.307718 692.277575 732.550935L692.277575 732.550935 692.277575 732.550935z"  horiz-adv-x="1084" />
+      
+      <glyph glyph-name="logout" unicode="&#59010;" d="M512 832a32 32 0 0 1-32-32v-416a32 32 0 0 1 64 0V800a32 32 0 0 1-32 32zM683.34 798.06a32 32 0 0 1-24.48-59.15C798.07 681.24 896 544.06 896 384c0-212.08-171.92-384-384-384S128 171.91999999999996 128 384c0 160.06 97.93 297.24 237.14 354.91a32 32 0 0 1-24.48 59.15C178.25 730.78 64 570.74 64 384c0-247.42 200.58-448 448-448s448 200.58 448 448c0 186.74-114.25 346.78-276.66 414.06z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="wifi" unicode="&#59360;" d="M723 275.5C666.8 324.4 593.4 354 513 354s-153.8-29.6-210.1-78.6c-3.2-2.8-3.6-7.8-0.8-11.2l36-42.9c2.9-3.4 8-3.8 11.4-0.9C393.1 258.8 450.3 282 513 282s119.9-23.2 163.5-61.5c3.4-2.9 8.5-2.5 11.4 0.9l36 42.9c2.8 3.3 2.4 8.3-0.9 11.2zM840.4 415.6C751.7 489.5 637.6 534 513 534s-238.7-44.5-327.5-118.4c-3.4-2.8-3.8-7.9-1-11.3l36-42.9c2.8-3.4 7.9-3.8 11.2-1C308 423.8 406.1 462 513 462s205-38.2 281.2-101.6c3.4-2.8 8.4-2.4 11.2 1l36 42.9c2.8 3.4 2.4 8.5-1 11.3zM957.1 554.6C835.7 654.2 680.3 714 511 714c-168.2 0-322.6-59-443.7-157.4-3.5-2.8-4-7.9-1.1-11.4l36-42.9c2.8-3.3 7.8-3.8 11.1-1.1C222 589.3 360.3 642 511 642c151.8 0 291-53.5 400-142.7 3.4-2.8 8.4-2.3 11.2 1.1l36 42.9c2.9 3.4 2.4 8.5-1.1 11.3zM512 118m-64 0a64 64 0 1 1 128 0 64 64 0 1 1-128 0Z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="rss" unicode="&#59400;" d="M810.666667 63.95733332999998C810.666667 416.89600033 523.562667 704.00000033 170.666667 704.00000033v-85.333334c305.834667 0 554.666667-248.832 554.666666-554.709333h85.333334zM512 63.95733332999998h85.333333C597.333333 299.26400033000004 405.930667 490.66666633 170.666667 490.66666633v-85.333333c188.202667 0 341.333333-153.130667 341.333333-341.376zM256 149.33333332999996m-85.333333 0a85.333333 85.333333 0 1 1 170.666666 0 85.333333 85.333333 0 1 1-170.666666 0Z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="email" unicode="&#58904;" d="M834.446 682.553H194.105c-50.176 0-91.022-40.846-91.022-91.022v-423.026c0-50.176 40.846-91.022 91.022-91.022h640.341c50.176 0 91.022 40.846 91.022 91.022V591.531c0 50.176-40.846 91.022-91.022 91.022z m36.409-514.048c0-20.025-16.384-36.409-36.409-36.409H194.105c-20.025 0-36.409 16.384-36.409 36.409V591.531c0 20.025 16.384 36.409 36.409 36.409h640.341c20.025 0 36.409-16.384 36.409-36.409v-423.026zM786.773 537.941L514.275 366.023 241.777 537.941c-12.743 8.078-29.582 4.21-37.661-8.533-8.078-12.743-4.21-29.582 8.533-37.661l286.72-180.907c4.551-2.845 9.557-4.21 14.563-4.21h0.91c5.006 0 10.013 1.365 14.563 4.21l286.72 180.907c12.743 8.078 16.611 24.917 8.533 37.661-8.306 12.857-25.145 16.611-37.888 8.533z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="reduce-circle" unicode="&#58902;" d="M512-65.5c-60.6 0-119.4 11.9-174.8 35.3-53.5 22.6-101.5 55-142.7 96.2-41.2 41.2-73.6 89.2-96.2 142.7C74.9 264.1 63 322.9 63 383.5s11.9 119.4 35.3 174.8c22.6 53.5 55 101.5 96.2 142.7 41.2 41.2 89.2 73.6 142.7 96.2C392.6 820.6 451.4 832.5 512 832.5s119.4-11.9 174.8-35.3c53.5-22.6 101.5-55 142.7-96.2 41.2-41.2 73.6-89.2 96.2-142.7 23.4-55.4 35.3-114.2 35.3-174.8s-11.9-119.4-35.3-174.8c-22.6-53.5-55-101.5-96.2-142.7s-89.2-73.6-142.7-96.2c-55.4-23.4-114.2-35.3-174.8-35.3z m0 848c-220 0-399-179-399-399s179-399 399-399 399 179 399 399-179 399-399 399zM772 359H252c-13.8 0-25 11.2-25 25s11.2 25 25 25h520c13.8 0 25-11.2 25-25s-11.2-25-25-25z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="transfer" unicode="&#59025;" d="M320 768H128c-35.2 0-64-28.8-64-64v-640c0-35.2 28.8-64 64-64h192c35.2 0 64 28.8 64 64V704c0 35.2-28.8 64-64 64z m0-672c0-16-16-32-32-32H160c-16 0-32 16-32 32V672c0 16 16 32 32 32h128c16 0 32-16 32-32v-576z m256 544h-64c-19.2 0-32-12.8-32-32s16-32 32-32h64c19.2 0 32 12.8 32 32s-16 32-32 32z m-64-448h-64c-19.2 0-32-12.8-32-32s16-32 32-32h64c19.2 0 32 12.8 32 32s-16 32-32 32z m384 576H704c-35.2 0-64-28.8-64-64v-640c0-35.2 28.8-64 64-64h192c35.2 0 64 28.8 64 64V704c0 35.2-28.8 64-64 64z m0-672c0-16-16-32-32-32H736c-16 0-32 16-32 32V672c0 16 16 32 32 32h128c16 0 32-16 32-32v-576z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="service" unicode="&#58918;" d="M849.00812012 487.71642715A27.54528398 27.54528398 0 0 1 849.00812012 496.71080566 337.28919434 337.28919434 0 0 1 174.42973145 496.71080566a27.54528398 27.54528398 0 0 1-1e-8-8.99437852 147.28294776 147.28294776 0 0 1-112.42973144-140.53716386V328.06620849a148.40724551 148.40724551 0 0 1 123.67270459-143.34790781A308.6196126 308.6196126 0 0 1 414.4672083-9.222985839999978h5.05933769a84.32229815 84.32229815 0 1 1 0 56.21486573 252.40474688 252.40474688 0 0 0-172.01748955 137.16427235h31.48032481A35.41536562 35.41536562 0 0 1 314.96689531 215.63647705000005V458.48469697a35.41536562 35.41536562 0 0 1-35.97751406 34.29106787H230.64459717A26.42098711 26.42098711 0 0 1 230.64459717 496.71080566a281.07432862 281.07432862 0 0 0 562.14865723 0 26.42098711 26.42098711 0 0 1 0-3.3728915h-48.34478497a35.41536562 35.41536562 0 0 1-35.97751406-34.29106875V215.63647705000005a35.41536562 35.41536562 0 0 1 35.97751406-34.29106787h63.52279893A150.0936917 150.0936917 0 0 1 961.43785156 328.06620849v19.11305479a147.28294776 147.28294776 0 0 1-112.42973144 140.53716386zM498.22735801 46.991879880000056a28.10743242 28.10743242 0 1 0-28.1074333-28.10743242 28.10743242 28.10743242 0 0 0 28.10743329 28.10743242zM258.75202959 240.37101797000003h-43.28544639A93.87882598 93.87882598 0 0 0 118.21486572 328.06620849v19.11305479a93.87882598 93.87882598 0 0 0 97.25171748 89.94378516h43.28544639zM905.22298584 328.06620849a93.87882598 93.87882598 0 0 0-97.25171748-89.94378515h-43.28544727V437.12304844h43.28544727A93.87882598 93.87882598 0 0 0 905.22298584 347.17926328zM633.70518418 705.83010615l-20.7995001 7.30793232a28.10743242 28.10743242 0 0 1-17.42660859-56.21486571l16.30231084-6.18363458a28.10743242 28.10743242 0 1 1 21.92379785 51.71767646zM330.14490928 639.49656503A28.10743242 28.10743242 0 0 1 376.80324805 609.14053711 177.63897568 177.63897568 0 0 0 511.71892578 676.59837597a28.10743242 28.10743242 0 0 1 0 56.21486573 231.60524678 231.60524678 0 0 1-181.57401651-93.31667667z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="addition" unicode="&#58916;" d="M544 768L480 768 480 416 128 416 128 352 480 352 480 0 544 0 544 352 895.936 352 895.936 416 544 416Z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="subtraction" unicode="&#59006;" d="M785 348H239c-19.8 0-36 16.2-36 36s16.2 36 36 36h546c19.8 0 36-16.2 36-36s-16.2-36-36-36z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="slider" unicode="&#59156;" d="M228.7 683.9v-66.7H112v66.7h116.7z m333.2-266.6v-66.7H112v66.7h449.9zM295.4 150.60000000000002V84H112v66.7h183.4v-0.1z m116.6 600c9 0 16.8-3.3 23.5-9.9 6.5-6.5 9.9-14.5 9.9-23.5v-133.3c0-9-3.3-16.8-9.9-23.5-6.5-6.5-14.5-9.9-23.5-9.9H278.8c-9 0-16.8 3.3-23.5 9.9-6.5 6.5-9.9 14.3-9.9 23.5V717.1c0 9 3.3 16.8 9.9 23.5 6.5 6.5 14.3 9.9 23.5 9.9h133.3v0.1h-0.1z m66.7-533.3c9 0 16.8-3.3 23.5-9.9 6.5-6.5 9.9-14.5 9.9-23.5v-133.3c0-9-3.3-16.8-9.9-23.5-6.5-6.5-14.5-9.9-23.5-9.9H345.3c-9 0-16.8 3.3-23.5 9.9-6.5 6.5-9.9 14.5-9.9 23.5V183.89999999999998c0 9 3.3 16.8 9.9 23.5 6.5 6.5 14.3 9.9 23.5 9.9h133.4v0.1zM912 683.9v-66.7H462.1v66.7H912z m0-533.3V84H528.6v66.7h383.3v-0.1h0.1zM745.2 483.9c9 0 16.8-3.3 23.5-9.9 6.5-6.5 9.9-14.5 9.9-23.5v-133.3c0-9-3.3-16.8-9.9-23.5-6.5-6.5-14.5-9.9-23.5-9.9H612c-9 0-16.8 3.3-23.5 9.9-6.5 6.5-9.9 14.3-9.9 23.5V450.6c0 9 3.3 16.8 9.9 23.5 6.5 6.5 14.5 9.9 23.5 9.9l133.2-0.1zM912 417.3v-66.7H795.3v66.7H912z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="print" unicode="&#58989;" d="M843.946667 603.733333h-47.36V725.333333a90.026667 90.026667 0 0 1-94.72 85.333334H312.32a81.493333 81.493333 0 0 1-85.333333-85.333334v-121.6H170.666667a81.493333 81.493333 0 0 1-85.333334-85.333333v-325.12a89.173333 89.173333 0 0 1 85.333334-93.866667h56.746666v-52.48a89.6 89.6 0 0 1 89.6-89.6h389.973334a89.6 89.6 0 0 1 89.6 89.6v52.48h47.36a97.706667 97.706667 0 0 1 94.72 93.866667V518.4a90.026667 90.026667 0 0 1-94.72 85.333333zM279.466667 725.333333a30.72 30.72 0 0 0 32.853333 33.706667h389.546667c18.773333 0 42.666667-11.52 42.666666-33.706667v-121.6H279.466667z m465.066666-678.4a37.546667 37.546667 0 0 0-37.546666-37.973333H317.013333a37.546667 37.546667 0 0 0-37.546666 37.973333v170.666667a37.546667 37.546667 0 0 0 37.546666 38.4h389.973334a37.546667 37.546667 0 0 0 37.546666-37.973333z m142.506667 146.346667a45.653333 45.653333 0 0 0-42.666667-42.666667h-47.786666v66.133334a89.6 89.6 0 0 1-89.6 89.6H317.013333a89.6 89.6 0 0 1-89.6-89.6v-65.28H170.666667a37.546667 37.546667 0 0 0-33.28 42.666666v324.266667A31.146667 31.146667 0 0 0 170.666667 552.106667h673.28c19.2 0 42.666667-11.52 42.666666-33.706667z m-640 281.173333h-37.546667a13.226667 13.226667 0 0 0 0 26.026667h38.826667a13.226667 13.226667 0 1 0 0-26.026667z m94.293333 0H298.666667a13.226667 13.226667 0 1 0 0 26.026667h42.666666a13.226667 13.226667 0 0 0 0-26.026667z m426.666667-116.48H248.32a13.226667 13.226667 0 0 0 0 26.026667H768a13.226667 13.226667 0 0 0 0-26.026667z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="export" unicode="&#59005;" d="M896.4374528 479.830016c0 26.673152-21.6236032 48.2967552-48.2967552 48.2967552H630.8069376c-26.673152 0-48.2967552-21.6236032-48.2967552-48.2967552v-83.04831147H384.69522773l-2.71428266 5.36849067c-41.336832 87.44686933-35.95195733 204.128256 150.601728 199.94487467v-108.91537067l172.19037866 164.757504L532.58267307 822.7110912v-106.57245867c-228.64418133 5.70709333-263.651328-183.517184-157.433856-314.01028266l4.6891008-5.34664534h-88.46595414c-26.673152 0-48.2967552-21.6236032-48.2967552-48.2967552v-66.78882986h-98.43616426c-26.673152 0-40.4258816-21.6236032-30.71781547-48.2967552l79.10304427-217.33485227c9.70806613-26.673152 39.20145067-48.2967552 65.87460266-48.2967552h603.70670934c23.75898453 0 37.2506624 17.16169387 33.05745066 39.76178347 0.4980736 2.77108053 0.77441707 5.619712 0.77441707 8.53497173v463.765504z m-60.37067093-306.4528896l-21.8464256 60.02223787c-9.70806613 26.673152-39.20145067 48.2967552-65.87460267 48.2967552H303.44697173v30.56708266c0 13.336576 10.81125547 24.14783147 24.14783147 24.14783147h315.28605013v107.1972352c0 13.336576 10.81125547 24.14783147 24.14783147 24.14783147h144.88917333c13.336576 0 24.14783147-10.81125547 24.14783147-24.14783147v-270.2311424z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="cols" unicode="&#58896;" d="M128 426.66666667h384V810.66666667H128z m64 320h256v-256H192zM576 810.66666667v-384h384V810.66666667z m320-320H640V746.66666667h256zM192 362.66666667000004h64v-384H192zM384 362.66666667000004h64v-384H384zM640 362.66666667000004h64v-384H640zM832 362.66666667000004h64v-384h-64z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="screen-full" unicode="&#58914;" d="M641.750109 511.899972l205.227128 204.519-0.704035-115.89966c-0.282433-9.611915 7.489578-18.09103 17.101493-17.808598l12.297071 0c9.611915 0.283456 17.667382 5.936199 17.808598 15.689331l0.565888 172.57752c0 0.14224 0.282433 9.187243 0.282433 9.187243 0.14224 4.804423-0.99056 9.187243-4.100388 12.297071-3.109828 3.109828-7.347339 5.086855-12.297071 4.946662l-8.763594-0.14224c-0.141216 0-0.278339 0-0.420579-0.14224L697.581696 797.833213c-9.611915-0.283456-17.667382-8.200776-17.808598-17.950837l0-12.297071c1.416256-11.44875 10.458189-18.092054 20.070104-17.808598l112.789832-0.283456-204.66124-203.814965c-9.329483-9.329483-9.329483-24.449855 0-33.778314 9.329483-9.470699 24.452925-9.470699 33.782408 0L641.750109 511.899972zM383.095141 319.11010699999997L177.726797 115.29411900000002l0.707105 115.338888c0.283456 9.607822-7.492648 18.086937-17.104563 17.808598l-13.001105 0c-9.611915-0.283456-17.667382-5.937223-17.808598-15.690354l-0.565888-172.718737c0-0.14224-0.282433-9.187243-0.282433-9.187243-0.14224-4.808516 0.99056-9.187243 4.096295-12.297071 3.109828-3.109828 7.351432-5.086855 12.297071-4.946662l8.762571 0.14224c0.14224 0 0.283456 0 0.425695 0.14224l171.873486-0.708128c9.607822 0.283456 17.667382 8.196683 17.808598 17.950837L344.93503 63.42477399999996c-1.415232 11.44875-10.461259 18.092054-20.074198 17.808598L212.069977 81.51682800000003 416.59 285.32872299999997c9.329483 9.329483 9.329483 24.453948 0 33.782408C407.40685 328.58182999999997 392.424624 328.58182999999997 383.095141 319.11010699999997L383.095141 319.11010699999997zM894.047276 60.03251399999999l-0.424672 172.718737c-0.283456 9.612938-8.200776 15.406898-17.809621 15.690354l-12.296047 0c-9.612938 0.278339-17.243733-8.200776-17.105586-17.808598l0.708128-115.903753L641.750109 319.11010699999997c-9.329483 9.329483-24.452925 9.329483-33.782408 0-9.325389-9.328459-9.325389-24.452925 0-33.782408L812.490795 81.51682800000003l-112.789832-0.283456c-9.611915 0.283456-18.515702-6.502088-20.073174-17.808598l0-12.297071c0.282433-9.611915 8.200776-17.667382 17.808598-17.950837l171.166381 0.708128c0.141216 0 0.282433-0.14224 0.424672-0.14224l8.763594-0.14224c4.803399-0.141216 9.187243 1.694595 12.296047 4.946662 3.109828 3.109828 4.238534 7.488555 4.097318 12.297071 0 0-0.14224 9.046027-0.14224 9.187243L894.047276 60.03149099999996zM212.216309 749.493252l112.789832 0.283456c9.607822-0.283456 18.512632 6.502088 20.070104 17.808598L345.076246 779.883399c-0.283456 9.611915-8.196683 17.667382-17.808598 17.950837l-172.011632-0.708128c-0.14224 0-0.283456 0.14224-0.425695 0.14224l-8.761548 0.14224c-4.808516 0.141216-9.187243-1.694595-12.297071-4.946662-3.109828-3.109828-4.242627-7.488555-4.096295-12.297071 0 0 0.282433-9.046027 0.282433-9.187243l0.420579-172.718737c0.14224-9.608845 8.200776-15.406898 17.808598-15.686261l13.005198 0c9.611915-0.282433 17.242709 8.196683 17.10047 17.808598l-0.564865 115.334795 205.231221-203.958228c9.324366-9.329483 24.448832-9.329483 33.777291 0 9.329483 9.329483 9.329483 24.452925 0 33.782408L212.216309 749.493252 212.216309 749.493252zM212.216309 749.493252"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="screen-restore" unicode="&#59224;" d="M582.6 454.6v320h50V540l274 274 35.4-35.4-274-274h234.6v-50h-320zM117.4-46l274 274v-234.6h50v320h-320v-50H356l-274-274 35.4-35.4zM132 764h302V814H82v-352h50V764z m760-760H590v-50h352V306h-50v-302z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="rate-half" unicode="&#59081;" d="M1012.064 504l-359.552 31.008-140.512 331.04-140.512-331.552-359.552-30.496 273.024-236.544-82.016-351.552 309.056 186.528 309.056-186.528-81.504 351.552 272.544 236.544zM512 195.96799999999996l0 465.056 85.504-202.016 219.04-19.008-166.016-144.032 50.016-214.016-188.512 114.016z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="rate-solid" unicode="&#59002;" d="M957.111079 492.519576c-3.927449 11.669784-14.447037 19.86442-26.723641 20.816095L647.68068 535.250796 540.183388 811.873997c-4.586458 11.803837-15.951297 19.579941-28.614711 19.579941s-24.02723-7.776104-28.614711-19.579941L375.458719 535.250796l-282.708803-21.915126c-12.276604-0.951675-22.796192-9.146311-26.723641-20.816095-3.927449-11.669784-0.50142-24.557302 8.701173-32.737612l217.547735-193.358823-67.980277-291.298436c-2.848884-12.20702 2.009773-24.919553 12.273535-32.114418 10.264784-7.195889 23.87271-7.42818 34.375925-0.586354l240.624313 156.709111 240.625336-156.709111c5.099135-3.320629 10.92891-4.974291 16.752546-4.974291 6.173606 0 12.342096 1.858324 17.623379 5.561669 10.263761 7.194866 15.122419 19.907399 12.273535 32.114418l-67.980277 291.299459L948.409906 459.781964C957.613522 467.962274 961.037505 480.849792 957.111079 492.519576z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="rate" unicode="&#59003;" d="M959.008 489.984l-308 47.008L512 832 372.992 536.992l-308-47.008 223.008-228-52.992-324L512 90.976l276.992-152.992-52.992 324zM512 156L304 39.00800000000004l40 235.008-179.008 182.016 242.016 32 104.992 224 104-224 240.992-34.016L680 273.024l36.992-235.008z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="cellphone" unicode="&#59000;" d="M785.066667 896H238.933333a102.4 102.4 0 0 1-102.4-102.4v-819.2a102.4 102.4 0 0 1 102.4-102.4h546.133334a102.4 102.4 0 0 1 102.4 102.4V793.6a102.4 102.4 0 0 1-102.4 102.4zM238.933333 827.733333h546.133334a34.133333 34.133333 0 0 0 34.133333-34.133333v-648.533333H204.8V793.6a34.133333 34.133333 0 0 0 34.133333 34.133333z m546.133334-887.466666H238.933333a34.133333 34.133333 0 0 0-34.133333 34.133333v102.4h614.4v-102.4a34.133333 34.133333 0 0 0-34.133333-34.133333zM512 8.53333299999997m-34.133333 0a34.133333 34.133333 0 1 1 68.266666 0 34.133333 34.133333 0 1 1-68.266666 0ZM426.666667 725.333333h170.666666a17.066667 17.066667 0 0 1 0 34.133334h-170.666666a17.066667 17.066667 0 0 1 0-34.133334z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="vercode" unicode="&#59001;" d="M513.807059-128C351.171765-128 58.428235 126.19294100000002 54.211765 376.16941199999997V662.287059a93.364706 93.364706 0 0 0 81.317647 88.545882 570.428235 570.428235 0 0 1 163.237647 40.357647A393.336471 393.336471 0 0 1 446.945882 872.508235a101.797647 101.797647 0 0 0 120.470589 5.421177A629.458824 629.458824 0 0 1 716.8 792.395294a1255.303529 1255.303529 0 0 1 169.863529-38.550588 98.785882 98.785882 0 0 0 79.510589-90.955294 2911.171765 2911.171765 0 0 0-3.011765-291.538824C924.611765 49.09176500000001 672.828235-128 513.807059-128z m0 963.764706a39.152941 39.152941 0 0 1-24.696471-7.830588A438.512941 438.512941 0 0 0 319.247059 734.569412a608.376471 608.376471 0 0 0-180.705883-43.369412 33.731765 33.731765 0 0 1-24.094117-30.117647v-283.708235C118.663529 155.10588199999995 389.722353-67.76470600000005 513.807059-67.76470600000005s354.183529 148.178824 391.529412 444.536471c9.035294 175.887059 0 281.901176 0 283.105882a38.550588 38.550588 0 0 1-29.515295 33.731765 1287.830588 1287.830588 0 0 0-180.705882 41.562353A676.442353 676.442353 0 0 0 536.094118 829.741176a37.345882 37.345882 0 0 1-24.094118 6.02353zM784.865882 479.171765L487.905882 198.47529399999996a40.357647 40.357647 0 0 0-49.392941-4.818823l-7.830588 6.625882-161.430588 171.068235a40.357647 40.357647 0 1 0 60.235294 55.416471l133.722353-141.552941 267.444706 252.988235a40.357647 40.357647 0 1 0 55.41647-60.235294"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="login-weibo" unicode="&#58997;" d="M411.270737 288.350316c-17.973895 7.504842-41.189053-0.229053-52.264421-17.542737-11.223579-17.394526-5.955368-38.103579 11.870316-46.201263 18.108632-8.232421 42.132211-0.417684 53.342316 17.421474C435.253895 260.05557899999997 429.446737 280.62989500000003 411.270737 288.350316zM455.545263 306.64757899999995c-6.885053 2.721684-15.508211-0.579368-19.550316-7.329684-3.920842-6.790737-1.751579-14.524632 5.146947-17.367579 7.019789-2.883368 16.006737 0.458105 20.048842 7.370105C465.071158 296.259368 462.551579 304.087579 455.545263 306.64757899999995zM427.52 426.684632c-115.968-11.439158-203.924211-82.216421-196.378947-158.073263 7.531789-75.910737 107.654737-128.161684 223.649684-116.749474 115.994947 11.439158 203.924211 82.216421 196.392421 158.140632C643.664842 385.859368 543.541895 438.110316 427.52 426.684632zM529.300211 247.70021099999997c-23.673263-53.355789-91.769263-81.798737-149.530947-63.232-55.754105 17.933474-79.373474 72.811789-54.945684 122.246737 23.956211 48.464842 86.352842 75.870316 141.541053 61.561263C523.506526 353.562947 552.663579 299.85684200000003 529.300211 247.70021099999997zM512 896C229.241263 896 0 666.772211 0 384c0-282.758737 229.241263-512 512-512 282.772211 0 512 229.241263 512 512C1024 666.772211 794.772211 896 512 896zM455.531789 101.02568399999996c-145.354105 0-293.941895 70.197895-293.941895 185.667368 0 60.362105 38.386526 130.182737 104.474947 196.069053 88.252632 87.929263 191.164632 127.986526 229.874526 89.397895 17.084632-17.003789 18.741895-46.457263 7.760842-81.623579-5.726316-17.690947 16.666947-7.895579 16.666947-7.936 71.343158 29.763368 133.564632 31.514947 156.321684-0.862316 12.139789-17.246316 10.954105-41.472-0.215579-69.510737-5.173895-12.921263 1.589895-14.928842 11.466105-17.879579 40.178526-12.422737 84.924632-42.455579 84.924632-95.380211C772.837053 211.36168399999997 646.090105 101.02568399999996 455.531789 101.02568399999996zM718.672842 468.197053c4.715789 14.457263 1.765053 30.962526-9.202526 43.061895-10.954105 12.072421-27.136 16.666947-42.037895 13.527579l0 0.026947c-12.463158-2.694737-24.724211 5.268211-27.392 17.664-2.667789 12.463158 5.281684 24.697263 17.744842 27.338105 30.531368 6.467368 63.595789-2.937263 85.989053-27.715368 22.447158-24.764632 28.456421-58.489263 18.849684-88.064-3.907368-12.099368-16.936421-18.728421-29.062737-14.848-12.139789 3.920842-18.782316 16.922947-14.874947 28.995368L718.672842 468.183579zM853.261474 424.865684c-0.013474-0.013474-0.013474-0.080842-0.013474-0.107789-4.567579-14.026105-19.712-21.706105-33.778526-17.165474-14.133895 4.554105-21.854316 19.590737-17.300211 33.670737l0 0.013474c13.999158 43.169684 5.12 92.429474-27.567158 128.565895-32.714105 36.122947-80.949895 49.92-125.507368 40.488421-14.484211-3.085474-28.752842 6.130526-31.838316 20.574316-3.098947 14.403368 6.144 28.631579 20.641684 31.717053l0.026947 0c62.625684 13.271579 130.519579-6.117053 176.545684-56.966737C860.483368 554.886737 872.892632 485.618526 853.261474 424.865684z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="login-qq" unicode="&#58998;" d="M512 896C229.227789 896 0 666.772211 0 384c0-282.745263 229.227789-512 512-512s512 229.254737 512 512C1024 666.772211 794.772211 896 512 896L512 896zM738.856421 258.93726300000003c0 0-16.208842-44.220632-45.945263-83.941053 0 0 53.126737-18.054737 48.64-64.983579 0 0 1.778526-52.345263-113.461895-48.734316 0 0-81.071158 6.319158-105.377684 40.609684l-21.423158 0c-24.306526-34.304-105.350737-40.609684-105.350737-40.609684-115.280842-3.610947-113.475368 48.734316-113.475368 48.734316-4.500211 46.928842 48.626526 64.983579 48.626526 64.983579-29.709474 39.720421-45.918316 83.941053-45.918316 83.941053-72.057263-116.439579-64.848842 16.249263-64.848842 16.249263 13.527579 78.524632 70.238316 129.967158 70.238316 129.967158-8.111158 71.316211 21.611789 83.941053 21.611789 83.941053C318.410105 709.712842 508.025263 705.859368 512 705.751579c3.988211 0.107789 193.576421 3.961263 199.828211-216.643368 0 0 29.709474-12.638316 21.611789-83.941053 0 0 56.737684-51.442526 70.238316-129.967158l0 0C803.678316 275.18652599999996 810.873263 142.49768400000005 738.856421 258.93726300000003L738.856421 258.93726300000003zM738.856421 258.93726300000003"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="login-wechat" unicode="&#58999;" d="M516.464646 896C233.714646 896 4.464646 666.75 4.464646 384S233.714646-128 516.464646-128s512 229.25 512 512S799.214646 896 516.464646 896z m-74-523.375c-0.25-0.75-0.5-1.125-0.75-1.875-0.25-0.75-0.5-1.125-0.75-1.875-0.25-0.75-0.5-1.125-0.75-1.875-0.25-0.75-0.5-1.125-0.75-1.875-0.25-0.75-0.5-1.125-0.75-1.875-0.25-0.75-0.5-1.125-0.75-1.875-0.25-0.75-0.5-1.125-0.75-1.875-0.25-0.75-0.5-1.125-0.75-1.875-0.25-0.75-0.5-1.125-0.5-1.875-0.25-0.75-0.5-1.125-0.5-1.875-0.25-0.75-0.5-1.125-0.5-1.875-0.25-0.75-0.25-1.125-0.5-1.875s-0.5-1.125-0.5-1.875c-0.25-0.75-0.25-1.125-0.5-1.875s-0.25-1.125-0.5-1.875-0.25-1.125-0.5-1.875-0.25-1.125-0.5-1.875-0.25-1.125-0.5-1.875-0.25-1.125-0.5-1.875-0.25-1.125-0.5-1.875-0.25-1.125-0.5-1.875c0-0.75-0.25-1.125-0.25-1.875s-0.25-1.125-0.25-1.875-0.25-1.125-0.25-1.875-0.25-1.125-0.25-1.875-0.25-1.125-0.25-1.875-0.25-1.125-0.25-1.875-0.25-1.125-0.25-1.875-0.25-1.125-0.25-1.875-0.25-1.125-0.25-1.875 0-1.125-0.25-1.875c0-0.75-0.25-1.125-0.25-1.875s0-1.125-0.25-1.875c0-0.75 0-1.125-0.25-1.875 0-0.75 0-1.125-0.25-1.875v-22.5c0-0.75 0-1.125 0.25-1.875 0-0.75 0-1.125 0.25-1.875 0-0.75 0-1.125 0.25-1.875 0-0.75 0-1.125 0.25-1.875 0-0.75 0.25-1.125 0.25-1.875s0.25-1.125 0.25-1.875 0.25-1.125 0.25-1.875 0.25-1.125 0.25-1.875 0.25-1.125 0.25-1.875 0.25-1.125 0.25-1.875 0.25-1.125 0.25-1.875 0.25-1.125 0.25-1.875 0.25-1.125 0.25-1.875 0.25-1.125 0.5-1.875 0.25-1.125 0.5-1.875 0.25-1.125 0.5-1.875 0.25-1.125 0.5-1.875 0.25-1.125 0.5-1.875 0.25-1.125 0.5-1.875 0.25-1.125 0.5-1.875 0.25-1.125 0.5-1.875 0.25-1.125 0.5-1.875 0.25-1.125 0.5-1.875l0.25-0.875c-4.25-0.25-8.625-0.75-12.75-0.75-3.75-0.25-7.25-0.25-11-0.25-3.5 0-7 0-10.5 0.25-7.25 0.25-14 0.875-20.75 1.875-4.25 0.5-8.125 1.125-12.375 1.875-3.5 0.5-6.75 1.125-10.25 1.875-3 0.5-6.25 1.125-9.25 1.875-3 0.75-5.875 1.125-8.875 1.875-2.75 0.75-5.875 1.125-8.875 1.875-2.75 0.5-5.625 1.125-8.375 1.625l-3.25-1.625-3.75-1.875-4 1.375-3.75-1.875-3.75-1.875-3.75-1.875-3.75-1.875-3.75-1.875-3.75-1.875-3.75-1.875-3.75-1.875-2.75-1.375-3.75-1.875-3.75-1.875-3.75-1.875-3.75-1.875-3.75-1.875-3.75-1.875-3.75-1.875-3.75-1.875-3.75-1.875-3.75-1.875-3.75-1.875-3.75-1.875-2.5-1.375 0.5 1.375 0.75 1.875 0.75 1.875 0.75 1.875 0.75 1.875 0.75 1.875 0.75 1.875 0.75 1.875 0.75 1.875 0.75 1.875 0.75 1.875 0.75 1.875 0.75 1.875 0.75 1.875 0.75 1.875 0.75 1.875 0.75 1.875 0.75 1.875 0.75 1.875 0.75 1.875 0.75 1.875 0.75 1.875 0.75 1.875 0.75 1.875 0.75 1.875 0.75 1.875 0.75 1.875 0.75 1.875 0.75 1.875 0.75 1.875 0.75 1.875 0.75 1.875 0.75 1.875 0.75 1.875 0.75 1.875 0.75 1.875 0.75 1.875 0.75 1.875 0.75 1.875 0.75 1.875 0.75 1.875 0.75 1.875 0.5 1.125c-0.5 0.25-0.75 0.5-1.125 0.75-0.875 0.75-1.625 1.125-2.5 1.875s-1.625 1.125-2.5 1.875-1.625 1.125-2.5 1.875c-0.75 0.75-1.625 1.125-2.375 1.875-0.75 0.75-1.625 1.125-2.375 1.875-0.75 0.75-1.625 1.125-2.375 1.875-0.75 0.75-1.625 1.125-2.375 1.875-0.75 0.75-1.375 1.125-2.375 1.875-0.75 0.75-1.375 1.125-2.125 1.875-0.75 0.75-1.375 1.125-2.125 1.875-0.75 0.75-1.375 1.125-2.125 1.875-0.75 0.75-1.375 1.125-2.125 1.875-0.75 0.75-1.375 1.125-2.125 1.875-0.75 0.75-1.375 1.125-2.125 1.875-0.75 0.75-1.375 1.125-1.875 1.875-0.75 0.75-1.375 1.125-1.875 1.875l-1.875 1.875-1.875 1.875-1.875 1.875-1.875 1.875c-0.75 0.75-1.125 1.125-1.625 1.875s-1.125 1.125-1.625 1.875-1.125 1.125-1.625 1.875-1.125 1.125-1.625 1.875-1.125 1.125-1.625 1.875-1.125 1.125-1.625 1.875-0.875 1.125-1.625 1.875c-0.5 0.75-0.875 1.125-1.625 1.875-0.5 0.75-0.875 1.125-1.375 1.875-0.5 0.75-0.875 1.125-1.375 1.875-0.5 0.75-0.875 1.125-1.375 1.875-0.5 0.75-0.875 1.125-1.375 1.875-0.5 0.75-0.875 1.125-1.375 1.875-0.5 0.75-0.875 1.125-1.375 1.875-0.5 0.75-0.875 1.125-1.375 1.875-0.5 0.75-0.875 1.125-1.375 1.875-0.5 0.75-0.875 1.125-1.125 1.875-0.5 0.75-0.875 1.125-1.125 1.875-0.5 0.75-0.75 1.125-1.125 1.875-0.5 0.75-0.75 1.125-1.125 1.875-0.5 0.75-0.75 1.125-1.125 1.875-0.5 0.75-0.75 1.125-1.125 1.875-0.5 0.75-0.75 1.125-1.125 1.875-0.5 0.75-0.75 1.125-1.125 1.875-0.25 0.75-0.75 1.125-0.875 1.875-0.25 0.75-0.75 1.125-0.875 1.875-0.25 0.75-0.75 1.125-0.875 1.875-0.25 0.75-0.75 1.125-0.875 1.875-0.25 0.75-0.75 1.125-0.875 1.875-0.25 0.75-0.75 1.125-0.875 1.875-0.25 0.75-0.75 1.125-0.875 1.875-0.25 0.75-0.5 1.125-0.875 1.875-0.25 0.75-0.5 1.125-0.875 1.875-0.25 0.75-0.5 1.125-0.875 1.875-0.25 0.75-0.5 1.125-0.75 1.875-0.25 0.75-0.5 1.125-0.75 1.875-0.25 0.75-0.5 1.125-0.75 1.875-0.25 0.75-0.5 1.125-0.75 1.875-0.25 0.75-0.5 1.125-0.75 1.875-0.25 0.75-0.5 1.125-0.75 1.875-0.25 0.75-0.5 1.125-0.75 1.875-0.25 0.75-0.5 1.125-0.75 1.875-0.25 0.75-0.5 1.125-0.75 1.875-0.25 0.75-0.5 1.125-0.75 1.875-0.25 0.75-0.5 1.125-0.5 1.875-0.25 0.75-0.5 1.125-0.5 1.875-0.25 0.75-0.5 1.125-0.5 1.875-0.25 0.75-0.25 1.125-0.5 1.875s-0.25 1.125-0.5 1.875-0.25 1.125-0.5 1.875-0.25 1.125-0.5 1.875-0.25 1.125-0.5 1.875-0.25 1.125-0.5 1.875-0.25 1.125-0.5 1.875-0.25 1.125-0.5 1.875-0.25 1.125-0.25 1.875-0.25 1.125-0.25 1.875-0.25 1.125-0.25 1.875-0.25 1.125-0.25 1.875-0.25 1.125-0.25 1.875-0.25 1.125-0.25 1.875-0.25 1.125-0.25 1.875-0.25 1.125-0.25 1.875-0.25 1.125-0.25 1.875 0 1.125-0.25 1.875c0 0.75 0 1.125-0.25 1.875 0 0.75 0 1.125-0.25 1.875 0 0.75 0 1.125-0.25 1.875V457.25v1.875 1.875 1.875 1.875 1.875 0.875 0.875 1.875 1.875 1.875 1.875 1.875 1.875c0 0.75 0 1.125 0.25 1.875 0 0.75 0 1.125 0.25 1.875 0 0.75 0 1.125 0.25 1.875 0 0.75 0.25 1.125 0.25 1.875s0.25 1.125 0.25 1.875 0.25 1.125 0.25 1.875 0.25 1.125 0.25 1.875 0.25 1.125 0.25 1.875 0.25 1.125 0.25 1.875 0.25 1.125 0.25 1.875 0.25 1.125 0.25 1.875 0.25 1.125 0.25 1.875 0.25 1.125 0.5 1.875c0 0.75 0.25 1.125 0.5 1.875s0.25 1.125 0.5 1.875 0.25 1.125 0.5 1.875 0.25 1.125 0.5 1.875 0.25 1.125 0.5 1.875 0.25 1.125 0.5 1.875 0.25 1.125 0.5 1.875 0.25 1.125 0.5 1.875 0.25 1.125 0.5 1.875 0.25 1.125 0.5 1.875 0.5 1.125 0.5 1.875c0.25 0.75 0.5 1.125 0.5 1.875 0.25 0.75 0.5 1.125 0.5 1.875 0.25 0.75 0.5 1.125 0.75 1.875 0.25 0.75 0.5 1.125 0.75 1.875 0.25 0.75 0.5 1.125 0.75 1.875 0.25 0.75 0.5 1.125 0.75 1.875 0.25 0.75 0.5 1.125 0.75 1.875 0.25 0.75 0.5 1.125 0.75 1.875 0.25 0.75 0.5 1.125 0.75 1.875 0.25 0.75 0.5 1.125 0.75 1.875 0.25 0.75 0.5 1.125 0.75 1.875 0.25 0.75 0.5 1.125 0.75 1.875 0.25 0.75 0.5 1.125 0.75 1.875 0.25 0.75 0.5 1.125 0.875 1.875 0.25 0.75 0.5 1.125 0.875 1.875 0.25 0.75 0.5 1.125 0.875 1.875 0.25 0.75 0.75 1.125 0.875 1.875 0.25 0.75 0.75 1.125 0.875 1.875 0.25 0.75 0.75 1.125 0.875 1.875 0.25 0.75 0.75 1.125 0.875 1.875 0.25 0.75 0.75 1.125 0.875 1.875 0.25 0.75 0.75 1.125 0.875 1.875 0.25 0.75 0.75 1.125 1.125 1.875 0.5 0.75 0.75 1.125 1.125 1.875 0.5 0.75 0.75 1.125 1.125 1.875 0.5 0.75 0.75 1.125 1.125 1.875 0.5 0.75 0.75 1.125 1.125 1.875 0.5 0.75 0.75 1.125 1.125 1.875 0.5 0.75 0.75 1.125 1.125 1.875 0.5 0.75 0.875 1.125 1.125 1.875 0.5 0.75 0.875 1.125 1.125 1.875 0.5 0.75 0.875 1.125 1.125 1.875 0.5 0.75 0.875 1.125 1.375 1.875 0.5 0.75 0.875 1.125 1.375 1.875 0.5 0.75 0.875 1.125 1.375 1.875 0.5 0.75 0.875 1.125 1.375 1.875 0.5 0.75 0.875 1.125 1.375 1.875 0.5 0.75 0.875 1.125 1.375 1.875 0.5 0.75 0.875 1.125 1.375 1.875 0.5 0.75 0.875 1.125 1.625 1.875 0.5 0.75 0.875 1.125 1.625 1.875 0.5 0.75 1.125 1.125 1.625 1.875s1.125 1.125 1.625 1.875 1.125 1.125 1.625 1.875 1.125 1.125 1.625 1.875 1.125 1.125 1.625 1.875l1.875 1.875 1.875 1.875 1.875 1.875 1.875 1.875c0.75 0.75 1.375 1.125 1.875 1.875 0.75 0.75 1.375 1.125 2.125 1.875 0.75 0.75 1.375 1.125 2.125 1.875 0.75 0.75 1.375 1.125 2.125 1.875 0.75 0.75 1.375 1.125 2.125 1.875 0.75 0.75 1.375 1.125 2.125 1.875 0.75 0.75 1.375 1.125 2.375 1.875 0.75 0.75 1.625 1.125 2.375 1.875 0.75 0.75 1.625 1.125 2.375 1.875 0.75 0.75 1.625 1.125 2.375 1.875 0.875 0.75 1.625 1.125 2.5 1.875s1.625 1.125 2.5 1.875 1.875 1.125 2.5 1.875c0.875 0.75 1.875 1.125 2.75 1.875 0.875 0.75 1.875 1.125 2.75 1.875 0.875 0.75 1.875 1.125 2.75 1.875 0.875 0.75 1.875 1.125 3 1.875 0.875 0.75 2.125 1.125 3 1.875s2.125 1.125 3 1.875c1.125 0.75 2.125 1.125 3.25 1.875 1.125 0.75 2.375 1.125 3.25 1.875 1.125 0.75 2.375 1.125 3.5 1.875 1.125 0.75 2.375 1.125 3.75 1.875 1.125 0.75 2.5 1.125 3.75 1.875 1.375 0.75 2.5 1.125 4 1.875 1.375 0.75 2.75 1.125 4.25 1.875 1.375 0.75 2.75 1.125 4.25 1.875 1.375 0.75 3 1.125 4.375 1.875 1.625 0.75 3 1.125 4.625 1.875 1.625 0.75 3.25 1.125 4.875 1.875 1.875 0.75 3.5 1.125 5.375 1.875s3.75 1.125 5.625 1.875c2.125 0.75 4.25 1.125 6 1.875 2.375 0.75 4.375 1.125 6.75 1.875 2.5 0.75 4.875 1.125 7.5 1.875 2.75 0.75 5.625 1.125 8.625 1.875 3.5 0.75 6.75 1.125 10.25 1.875 4.375 0.75 8.875 1.375 13.25 1.875 11 1.125 22.125 1.875 33.25 1.875h2.5c11.125 0 22.375-0.75 33.5-1.875 4.375-0.5 8.875-1.125 13.25-1.875 3.5-0.5 7-1.125 10.25-1.875 2.75-0.5 5.875-1.125 8.625-1.875 2.5-0.5 5.125-1.125 7.625-1.875 2.375-0.5 4.625-1.125 6.75-1.875 2.125-0.5 4.25-1.125 6.25-1.875 1.875-0.75 4-1.125 5.875-1.875s3.75-1.125 5.375-1.875c1.625-0.75 3.5-1.125 5.125-1.875 1.625-0.75 3.25-1.125 4.875-1.875 1.625-0.75 3-1.125 4.625-1.875 1.375-0.75 3-1.125 4.375-1.875s2.75-1.125 4.25-1.875c1.375-0.75 2.75-1.125 4-1.875 1.375-0.75 2.5-1.125 3.75-1.875 1.125-0.75 2.5-1.125 3.75-1.875 1.125-0.75 2.375-1.125 3.5-1.875 1.125-0.75 2.375-1.125 3.5-1.875 1.125-0.75 2.375-1.125 3.25-1.875 1.125-0.75 2.125-1.125 3.25-1.875 1.125-0.75 2.125-1.125 3-1.875s2.125-1.125 3-1.875 1.875-1.125 3-1.875c0.875-0.75 1.875-1.125 2.75-1.875 0.875-0.75 1.875-1.125 2.75-1.875 0.875-0.75 1.875-1.125 2.75-1.875 0.875-0.75 1.875-1.125 2.5-1.875 0.875-0.75 1.625-1.125 2.5-1.875s1.625-1.125 2.5-1.875 1.625-1.125 2.375-1.875c0.75-0.75 1.625-1.125 2.375-1.875 0.75-0.75 1.625-1.125 2.375-1.875 0.75-0.75 1.375-1.125 2.375-1.875 0.75-0.75 1.375-1.125 2.375-1.875 0.75-0.75 1.375-1.125 2.125-1.875 0.75-0.75 1.375-1.125 2.125-1.875 0.75-0.75 1.375-1.125 2.125-1.875 0.75-0.75 1.375-1.125 2.125-1.875 0.75-0.75 1.375-1.125 1.875-1.875 0.75-0.75 1.375-1.125 1.875-1.875l1.875-1.875 1.875-1.875 1.875-1.875 1.875-1.875c0.75-0.75 1.125-1.125 1.625-1.875s1.125-1.125 1.625-1.875 1.125-1.125 1.625-1.875 1.125-1.125 1.625-1.875 1.125-1.125 1.625-1.875 0.875-1.125 1.625-1.875c0.5-0.75 0.875-1.125 1.625-1.875 0.5-0.75 0.875-1.125 1.375-1.875 0.5-0.75 0.875-1.125 1.375-1.875 0.5-0.75 0.875-1.125 1.375-1.875 0.5-0.75 0.875-1.125 1.375-1.875 0.5-0.75 0.875-1.125 1.375-1.875 0.5-0.75 0.875-1.125 1.375-1.875 0.5-0.75 0.875-1.125 1.375-1.875 0.5-0.75 0.875-1.125 1.125-1.875 0.5-0.75 0.875-1.125 1.125-1.875 0.5-0.75 0.875-1.125 1.125-1.875 0.5-0.75 0.75-1.125 1.125-1.875 0.5-0.75 0.75-1.125 1.125-1.875 0.5-0.75 0.75-1.125 1.125-1.875 0.5-0.75 0.75-1.125 1.125-1.875 0.5-0.75 0.75-1.125 1.125-1.875 0.5-0.75 0.75-1.125 1.125-1.875 0.5-0.75 0.75-1.125 0.875-1.875 0.25-0.75 0.75-1.125 0.875-1.875 0.25-0.75 0.75-1.125 0.875-1.875 0.25-0.75 0.75-1.125 0.875-1.875 0.25-0.75 0.75-1.125 0.875-1.875 0.25-0.75 0.75-1.125 0.875-1.875 0.25-0.75 0.75-1.125 0.875-1.875 0.25-0.75 0.75-1.125 0.875-1.875 0.25-0.75 0.5-1.125 0.875-1.875 0.25-0.75 0.5-1.125 0.875-1.875 0.25-0.75 0.5-1.125 0.75-1.875 0.25-0.75 0.5-1.125 0.75-1.875 0.25-0.75 0.5-1.125 0.75-1.875 0.25-0.75 0.5-1.125 0.75-1.875 0.25-0.75 0.5-1.125 0.75-1.875 0.25-0.75 0.5-1.125 0.75-1.875 0.25-0.75 0.5-1.125 0.75-1.875 0.25-0.75 0.5-1.125 0.75-1.875 0.25-0.75 0.5-1.125 0.75-1.875 0.25-0.75 0.5-1.125 0.75-1.875 0.25-0.75 0.5-1.125 0.75-1.875 0.25-0.75 0.5-1.125 0.5-1.875 0.25-0.75 0.5-1.125 0.5-1.875 0.25-0.75 0.25-1.125 0.5-1.875s0.5-1.125 0.5-1.875c0.25-0.75 0.25-1.125 0.5-1.875s0.25-1.125 0.5-1.875 0.25-1.125 0.5-1.875 0.25-1.125 0.5-1.875 0.25-1.125 0.5-1.875c0-0.5 0.25-0.75 0.25-1.125-4.625 0.5-9.25 0.875-14 1.125-3.5 0.25-7 0.25-10.75 0.25-4 0-8.125 0-12.125-0.25-6.75-0.25-13.25-0.875-19.5-1.875-3.75-0.5-7.625-1.125-11.375-1.875-3-0.5-5.875-1.125-8.875-1.875-2.5-0.5-5.125-1.125-7.5-1.875-2.125-0.5-4.375-1.125-6.5-1.875-1.875-0.5-4-1.125-5.875-1.875-1.875-0.5-3.5-1.125-5.375-1.875-1.625-0.75-3.25-1.125-4.875-1.875-1.625-0.75-3-1.125-4.625-1.875-1.375-0.75-3-1.125-4.375-1.875s-2.75-1.125-4.25-1.875c-1.375-0.75-2.5-1.125-4-1.875-1.125-0.75-2.5-1.125-3.75-1.875-1.125-0.75-2.375-1.125-3.5-1.875-1.125-0.75-2.375-1.125-3.5-1.875-1.125-0.75-2.125-1.125-3.25-1.875-0.875-0.75-2.125-1.125-3-1.875s-2.125-1.125-3-1.875-1.875-1.125-3-1.875c-0.875-0.75-1.875-1.125-2.75-1.875-0.875-0.75-1.875-1.125-2.75-1.875-0.875-0.75-1.875-1.125-2.5-1.875-0.875-0.75-1.625-1.125-2.5-1.875s-1.625-1.125-2.5-1.875c-0.75-0.75-1.625-1.125-2.375-1.875-0.75-0.75-1.625-1.125-2.375-1.875-0.75-0.75-1.625-1.125-2.375-1.875-0.75-0.75-1.375-1.125-2.125-1.875-0.75-0.75-1.375-1.125-2.125-1.875-0.75-0.75-1.375-1.125-2.125-1.875-0.75-0.75-1.375-1.125-2.125-1.875-0.75-0.75-1.375-1.125-2.125-1.875-0.75-0.75-1.375-1.125-1.875-1.875l-1.875-1.875-1.875-1.875-1.875-1.875c-0.75-0.75-1.125-1.125-1.625-1.875s-1.125-1.125-1.625-1.875-1.125-1.125-1.625-1.875-1.125-1.125-1.625-1.875-1.125-1.125-1.625-1.875-0.875-1.125-1.625-1.875c-0.5-0.75-0.875-1.125-1.625-1.875-0.5-0.75-0.875-1.125-1.375-1.875-0.5-0.75-0.875-1.125-1.375-1.875-0.5-0.75-0.875-1.125-1.375-1.875-0.5-0.75-0.875-1.125-1.375-1.875-0.5-0.75-0.875-1.125-1.375-1.875-0.5-0.75-0.875-1.125-1.375-1.875-0.5-0.75-0.875-1.125-1.125-1.875-0.5-0.75-0.875-1.125-1.125-1.875-0.5-0.75-0.75-1.125-1.125-1.875-0.5-0.75-0.75-1.125-1.125-1.875-0.5-0.75-0.75-1.125-1.125-1.875-0.5-0.75-0.75-1.125-1.125-1.875-0.5-0.75-0.75-1.125-1.125-1.875-0.5-0.75-0.75-1.125-1.125-1.875-0.5-0.75-0.75-1.125-1.125-1.875-0.25-0.75-0.75-1.125-0.875-1.875-0.25-0.75-0.75-1.125-0.875-1.875-0.25-0.75-0.75-1.125-0.875-1.875-0.25-0.75-0.75-1.125-0.875-1.875-0.25-0.75-0.75-1.125-0.875-1.875-0.25-0.75-0.75-1.125-0.875-1.875-0.25-0.75-0.75-1.125-0.875-1.875-0.25-0.75-0.5-1.125-0.875-1.875-0.25-0.75-0.5-1.125-0.875-1.875-0.25-0.75-0.5-1.125-0.875-1.875-0.25-0.75-0.5-1.125-0.75-1.875-3.125-4.625-3.375-5.125-3.625-5.75z m433.625-71.25v-11.375c0-0.5 0-0.875-0.25-1.625 0-0.5 0-0.875-0.25-1.625 0-0.5 0-0.875-0.25-1.625 0-0.5-0.25-0.875-0.25-1.625 0-0.5-0.25-0.875-0.25-1.625 0-0.5-0.25-0.875-0.25-1.625 0-0.5-0.25-0.875-0.25-1.625 0-0.5-0.25-0.875-0.25-1.625 0-0.5-0.25-0.875-0.25-1.625 0-0.5-0.25-0.875-0.25-1.625 0-0.5-0.25-0.875-0.25-1.625 0-0.5-0.25-0.875-0.25-1.625 0-0.5-0.25-0.875-0.5-1.625-0.25-0.5-0.25-0.875-0.5-1.625-0.25-0.5-0.25-0.875-0.5-1.625-0.25-0.5-0.25-0.875-0.5-1.625-0.25-0.5-0.25-0.875-0.5-1.625-0.25-0.5-0.25-0.875-0.5-1.625-0.25-0.5-0.25-0.875-0.5-1.625-0.25-0.5-0.25-0.875-0.5-1.625-0.25-0.5-0.25-0.875-0.5-1.625-0.25-0.5-0.25-0.875-0.5-1.625-0.25-0.5-0.5-0.875-0.5-1.625-0.25-0.5-0.5-0.875-0.5-1.625-0.25-0.5-0.5-0.875-0.5-1.625-0.25-0.5-0.5-0.875-0.75-1.625-0.25-0.5-0.5-0.875-0.75-1.625-0.25-0.5-0.5-0.875-0.75-1.625-0.25-0.5-0.5-0.875-0.75-1.625-0.25-0.5-0.5-0.875-0.75-1.625-0.25-0.5-0.5-0.875-0.75-1.625-0.25-0.5-0.5-0.875-0.75-1.625-0.25-0.5-0.5-0.875-0.75-1.625-0.25-0.5-0.5-0.875-0.75-1.625-0.25-0.5-0.5-0.875-0.75-1.625-0.25-0.5-0.5-0.875-0.75-1.625-0.25-0.5-0.5-0.875-0.875-1.625-0.25-0.5-0.5-0.875-0.875-1.625-0.25-0.5-0.5-0.875-0.875-1.625-0.25-0.5-0.5-0.875-0.875-1.625-0.25-0.5-0.75-0.875-0.875-1.625-0.25-0.5-0.75-0.875-0.875-1.625-0.25-0.5-0.75-0.875-0.875-1.625-0.25-0.5-0.75-0.875-0.875-1.625-0.25-0.5-0.75-0.875-0.875-1.625-0.25-0.5-0.75-0.875-0.875-1.625-0.25-0.5-0.75-0.875-0.875-1.625-0.25-0.5-0.75-0.875-0.875-1.625-0.5-0.5-0.75-0.875-1.125-1.625-0.5-0.5-0.75-0.875-1.125-1.625-0.5-0.5-0.75-0.875-1.125-1.625-0.5-0.5-0.75-0.875-1.125-1.625-0.5-0.5-0.75-0.875-1.125-1.625-0.5-0.5-0.75-0.875-1.125-1.625-0.5-0.5-0.75-0.875-1.125-1.625-0.5-0.5-0.75-0.875-1.125-1.625-0.5-0.5-0.75-0.875-1.125-1.625-0.5-0.5-0.875-0.875-1.125-1.625-0.5-0.5-0.875-0.875-1.125-1.625-0.5-0.5-0.875-0.875-1.375-1.625-0.5-0.5-0.875-0.875-1.375-1.625-0.5-0.5-0.875-0.875-1.375-1.625-0.5-0.5-0.875-0.875-1.375-1.625-0.5-0.5-0.875-0.875-1.375-1.625-0.5-0.5-0.875-0.875-1.375-1.625-0.5-0.5-0.875-0.875-1.375-1.625-0.5-0.5-0.875-0.875-1.375-1.625-0.5-0.5-0.875-0.875-1.375-1.625-0.5-0.5-0.875-0.875-1.375-1.625l-1.625-1.625-1.625-1.625c-0.5-0.5-1.125-0.875-1.625-1.625-0.5-0.5-1.125-0.875-1.625-1.625-0.5-0.5-1.125-0.875-1.625-1.625-0.5-0.5-1.125-0.875-1.625-1.625-0.5-0.5-1.125-0.875-1.625-1.625-0.5-0.5-1.125-0.875-1.625-1.625-0.5-0.5-1.125-0.875-1.625-1.625-0.75-0.5-1.125-0.875-1.875-1.625-0.75-0.5-1.125-0.875-1.875-1.625-0.75-0.5-1.125-0.875-1.875-1.625-0.75-0.5-1.125-0.875-1.875-1.625-0.75-0.5-1.125-0.875-1.875-1.625-0.75-0.5-1.125-0.875-1.875-1.625-0.75-0.5-1.375-0.875-1.875-1.625-0.75-0.5-1.375-0.875-1.875-1.625-0.75-0.5-1.375-0.875-2.125-1.625-0.75-0.5-1.375-0.875-2.125-1.625l-0.75-0.5 0.25-0.875 0.5-1.625 0.5-1.625 0.5-1.625 0.5-1.625 0.5-1.625 0.5-1.625 0.5-1.625 0.5-1.625 0.5-1.625 0.5-1.625 0.5-1.625 0.5-1.625 0.5-1.625 0.5-1.625 0.5-1.625 0.5-1.625 0.5-1.625 0.5-1.625 0.5-1.625 0.5-1.625 0.5-1.625 0.5-1.625 0.5-1.625 0.5-1.625 0.5-1.625 0.5-1.625 0.5-1.625 0.5-1.625 0.5-1.625 0.5-1.625 0.5-1.625 0.5-1.625 0.5-1.625 0.5-1.625 0.5-1.625 0.5-1.625 0.5-1.625 0.5-1.625 0.5-1.625 0.5-1.625 0.25-1.125-2.125 1.125-2.75 1.625-2.75 1.625-2.75 1.625-2.75 1.625-2.75 1.625-2.75 1.625-2.75 1.625-2.75 1.625-2.75 1.625-2.75 1.625-2.75 1.625-2.75 1.625-2.75 1.625-2.75 1.625-2.75 1.625-2.75 1.625-2.75 1.625-2.75 1.625-2.75 1.625-2.75 1.625-2.75 1.625-2.75 1.625-2.75 1.625-2.75 1.625-0.5 0.25-0.875-0.25c-2.125-0.5-4.25-0.875-6-1.625-2.125-0.5-4.25-0.875-6.25-1.625-2.125-0.5-4.25-0.875-6.5-1.625-2.375-0.5-4.375-0.875-6.75-1.625-2.375-0.5-4.875-1.125-7.25-1.625-2.75-0.5-5.375-1.125-8.125-1.625-3.25-0.5-6.5-1.125-9.75-1.625-5.375-0.75-10.75-1.125-15.875-1.625-2.75-0.25-5.875-0.25-8.625-0.25-3.75 0-7.5 0-11.125 0.25-6.5 0.25-12.75 0.75-19.125 1.625-3.75 0.5-7.5 0.875-11 1.625-2.75 0.5-5.875 0.875-8.625 1.625-2.375 0.5-4.875 0.875-7.25 1.625-2.125 0.5-4.25 0.875-6.25 1.625-1.875 0.5-3.75 0.875-5.625 1.625-1.875 0.5-3.5 0.875-5.125 1.625-1.625 0.5-3.25 0.875-4.875 1.625-1.375 0.5-3 0.875-4.375 1.625-1.375 0.5-2.75 0.875-4.25 1.625-1.375 0.5-2.5 0.875-4 1.625-1.125 0.5-2.5 0.875-3.75 1.625-1.125 0.5-2.375 0.875-3.75 1.625-1.125 0.5-2.375 0.875-3.5 1.625-1.125 0.5-2.125 0.875-3.25 1.625-1.125 0.5-2.125 0.875-3.25 1.625-0.875 0.5-2.125 0.875-3 1.625-0.875 0.5-1.875 0.875-3 1.625-0.875 0.5-1.875 0.875-2.75 1.625-0.875 0.5-1.875 0.875-2.75 1.625-0.875 0.5-1.875 0.875-2.5 1.625-0.875 0.5-1.625 0.875-2.5 1.625-0.875 0.5-1.625 0.875-2.5 1.625-0.75 0.5-1.625 0.875-2.375 1.625-0.75 0.5-1.625 0.875-2.375 1.625-0.75 0.5-1.625 0.875-2.375 1.625-0.75 0.5-1.375 0.875-2.375 1.625-0.75 0.5-1.375 0.875-2.125 1.625-0.75 0.5-1.375 0.875-2.125 1.625-0.75 0.5-1.375 0.875-2.125 1.625-0.75 0.5-1.375 0.875-2.125 1.625-0.75 0.5-1.375 0.875-1.875 1.625-0.75 0.5-1.375 0.875-1.875 1.625-0.75 0.5-1.125 0.875-1.875 1.625-0.75 0.5-1.125 0.875-1.875 1.625-0.75 0.5-1.125 0.875-1.875 1.625-0.75 0.5-1.125 0.875-1.875 1.625-0.5 0.5-1.125 0.875-1.625 1.625-0.5 0.5-1.125 0.875-1.625 1.625-0.5 0.5-1.125 0.875-1.625 1.625-0.5 0.5-1.125 0.875-1.625 1.625l-1.625 1.625-1.625 1.625c-0.5 0.5-0.875 0.875-1.375 1.625-0.5 0.5-0.875 0.875-1.375 1.625-0.5 0.5-0.875 0.875-1.375 1.625-0.5 0.5-0.875 0.875-1.375 1.625-0.5 0.5-0.875 0.875-1.375 1.625-0.5 0.5-0.875 0.875-1.375 1.625-0.5 0.5-0.875 0.875-1.375 1.625-0.5 0.5-0.875 0.875-1.125 1.625-0.5 0.5-0.875 0.875-1.125 1.625-0.5 0.5-0.875 0.875-1.125 1.625-0.5 0.5-0.75 0.875-1.125 1.625-0.5 0.5-0.75 0.875-1.125 1.625-0.5 0.5-0.75 0.875-1.125 1.625-0.5 0.5-0.75 0.875-1.125 1.625-0.5 0.5-0.75 0.875-1.125 1.625-0.5 0.5-0.75 0.875-1.125 1.625-0.5 0.5-0.75 0.875-1.125 1.625-0.25 0.5-0.75 0.875-0.875 1.625-0.25 0.5-0.75 0.875-0.875 1.625-0.25 0.5-0.75 0.875-0.875 1.625-0.25 0.5-0.75 0.875-0.875 1.625-0.25 0.5-0.75 0.875-0.875 1.625-0.25 0.5-0.75 0.875-0.875 1.625-0.25 0.5-0.75 0.875-0.875 1.625-0.25 0.5-0.75 0.875-0.875 1.625-0.25 0.5-0.5 0.875-0.875 1.625-0.25 0.5-0.5 0.875-0.875 1.625-0.25 0.5-0.5 0.875-0.75 1.625-0.25 0.5-0.5 0.875-0.75 1.625-0.25 0.5-0.5 0.875-0.75 1.625-0.25 0.5-0.5 0.875-0.75 1.625-0.25 0.5-0.5 0.875-0.75 1.625-0.25 0.5-0.5 0.875-0.75 1.625-0.25 0.5-0.5 0.875-0.75 1.625-0.25 0.5-0.5 0.875-0.75 1.625-0.25 0.5-0.5 0.875-0.75 1.625-0.25 0.5-0.5 0.875-0.75 1.625-0.25 0.5-0.5 0.875-0.75 1.625-0.25 0.5-0.5 0.875-0.75 1.625-0.25 0.5-0.5 0.875-0.5 1.625-0.25 0.5-0.5 0.875-0.5 1.625-0.25 0.5-0.5 0.875-0.5 1.625-0.25 0.5-0.5 0.875-0.5 1.625-0.25 0.5-0.5 0.875-0.5 1.625-0.25 0.5-0.25 0.875-0.5 1.625-0.25 0.5-0.25 0.875-0.5 1.625-0.25 0.5-0.25 0.875-0.5 1.625-0.25 0.5-0.25 0.875-0.5 1.625-0.25 0.5-0.25 0.875-0.5 1.625-0.25 0.5-0.25 0.875-0.5 1.625-0.25 0.5-0.25 0.875-0.5 1.625-0.25 0.5-0.25 0.875-0.5 1.625-0.25 0.5-0.25 0.875-0.5 1.625-0.25 0.5-0.25 0.875-0.25 1.625 0 0.5-0.25 0.875-0.25 1.625 0 0.5-0.25 0.875-0.25 1.625 0 0.5-0.25 0.875-0.25 1.625 0 0.5-0.25 0.875-0.25 1.625 0 0.5-0.25 0.875-0.25 1.625 0 0.5-0.25 0.875-0.25 1.625 0 0.5-0.25 0.875-0.25 1.625 0 0.5-0.25 0.875-0.25 1.625 0 0.5-0.25 0.875-0.25 1.625 0 0.5-0.25 0.875-0.25 1.625 0 0.5-0.25 0.875-0.25 1.625 0 0.5 0 0.875-0.25 1.625 0 0.5 0 0.875-0.25 1.625 0 0.5 0 0.875-0.25 1.625v1.625 1.625 1.625 3.25 1.625 3.25 1.375 1.625 1.625 1.625 1.625 1.625 1.625 1.625 1.625 1.625c0 0.5 0 0.875 0.25 1.625 0 0.5 0 0.875 0.25 1.625 0 0.5 0 0.875 0.25 1.625 0 0.5 0.25 0.875 0.25 1.625 0 0.5 0.25 0.875 0.25 1.625 0 0.5 0.25 0.875 0.25 1.625 0 0.5 0.25 0.875 0.25 1.625 0 0.5 0.25 0.875 0.25 1.625 0 0.5 0.25 0.875 0.25 1.625 0 0.5 0.25 0.875 0.25 1.625 0 0.5 0.25 0.875 0.25 1.625 0 0.5 0.25 0.875 0.25 1.625 0 0.5 0.25 0.875 0.25 1.625 0 0.5 0.25 0.875 0.25 1.625 0 0.5 0.25 0.875 0.25 1.625 0.25 0.5 0.25 0.875 0.5 1.625 0.25 0.5 0.25 0.875 0.5 1.625 0.25 0.5 0.25 0.875 0.5 1.625 0.25 0.5 0.25 0.875 0.5 1.625 0.25 0.5 0.25 0.875 0.5 1.625 0.25 0.5 0.25 0.875 0.5 1.625 0.25 0.5 0.25 0.875 0.5 1.625 0.25 0.5 0.25 0.875 0.5 1.625 0.25 0.5 0.25 0.875 0.5 1.625 0.25 0.5 0.5 0.875 0.5 1.625 0.25 0.5 0.5 0.875 0.5 1.625 0.25 0.5 0.5 0.875 0.5 1.625 0.25 0.5 0.5 0.875 0.5 1.625 0.25 0.5 0.5 0.875 0.5 1.625 0.25 0.5 0.5 0.875 0.75 1.625 0.25 0.5 0.5 0.875 0.75 1.625 0.25 0.5 0.5 0.875 0.75 1.625 0.25 0.5 0.5 0.875 0.75 1.625 0.25 0.5 0.5 0.875 0.75 1.625 0.25 0.5 0.5 0.875 0.75 1.625 0.25 0.5 0.5 0.875 0.75 1.625 0.25 0.5 0.5 0.875 0.75 1.625 0.25 0.5 0.5 0.875 0.75 1.625 0.25 0.5 0.5 0.875 0.75 1.625 0.25 0.5 0.5 0.875 0.75 1.625 0.25 0.5 0.5 0.875 0.875 1.625 0.25 0.5 0.5 0.875 0.875 1.625 0.25 0.5 0.5 0.875 0.875 1.625 0.25 0.5 0.75 0.875 0.875 1.625 0.25 0.5 0.75 0.875 0.875 1.625 0.25 0.5 0.75 0.875 0.875 1.625 0.25 0.5 0.75 0.875 0.875 1.625 0.25 0.5 0.75 0.875 0.875 1.625 0.25 0.5 0.75 0.875 0.875 1.625 0.25 0.5 0.75 0.875 0.875 1.625 0.25 0.5 0.75 0.875 0.875 1.625 0.25 0.5 0.75 0.875 1.125 1.625 0.5 0.5 0.75 0.875 1.125 1.625 0.5 0.5 0.75 0.875 1.125 1.625 0.5 0.5 0.75 0.875 1.125 1.625 0.5 0.5 0.75 0.875 1.125 1.625 0.5 0.5 0.75 0.875 1.125 1.625 0.5 0.5 0.75 0.875 1.125 1.625 0.5 0.5 0.875 0.875 1.125 1.625 0.5 0.5 0.875 0.875 1.125 1.625 0.5 0.5 0.875 0.875 1.125 1.625 0.5 0.5 0.875 0.875 1.375 1.625 0.5 0.5 0.875 0.875 1.375 1.625 0.5 0.5 0.875 0.875 1.375 1.625 0.5 0.5 0.875 0.875 1.375 1.625 0.5 0.5 0.875 0.875 1.375 1.625 0.5 0.5 0.875 0.875 1.375 1.625 0.5 0.5 0.875 0.875 1.375 1.625l1.625 1.625 1.625 1.625c0.5 0.5 1.125 0.875 1.625 1.625 0.5 0.5 1.125 0.875 1.625 1.625 0.5 0.5 1.125 0.875 1.625 1.625 0.5 0.5 1.125 0.875 1.625 1.625 0.5 0.5 1.125 0.875 1.875 1.625 0.75 0.5 1.125 0.875 1.875 1.625 0.75 0.5 1.125 0.875 1.875 1.625 0.75 0.5 1.125 0.875 1.875 1.625 0.75 0.5 1.375 0.875 1.875 1.625 0.75 0.5 1.375 0.875 1.875 1.625 0.75 0.5 1.375 0.875 2.125 1.625 0.75 0.5 1.375 0.875 2.125 1.625 0.75 0.5 1.375 0.875 2.125 1.625 0.75 0.5 1.375 0.875 2.125 1.625 0.75 0.5 1.375 0.875 2.375 1.625 0.75 0.5 1.625 0.875 2.375 1.625 0.75 0.5 1.625 0.875 2.375 1.625 0.75 0.5 1.625 0.875 2.375 1.625 0.875 0.5 1.625 0.875 2.5 1.625 0.875 0.5 1.625 0.875 2.5 1.625 0.875 0.5 1.875 0.875 2.5 1.625 0.875 0.5 1.875 0.875 2.75 1.625 0.875 0.5 1.875 0.875 2.75 1.625 0.875 0.5 1.875 0.875 3 1.625 0.875 0.5 2.125 0.875 3 1.625 1.125 0.5 2.125 0.875 3.25 1.625 1.125 0.5 2.125 0.875 3.25 1.625 1.125 0.5 2.375 0.875 3.5 1.625 1.125 0.5 2.375 0.875 3.75 1.625 1.125 0.5 2.5 0.875 3.75 1.625 1.375 0.5 2.5 0.875 4 1.625 1.375 0.5 2.75 0.875 4.25 1.625 1.375 0.5 3 0.875 4.375 1.625 1.625 0.5 3.25 0.875 4.875 1.625 1.625 0.5 3.5 0.875 5.125 1.625 1.875 0.5 3.75 0.875 5.875 1.625 2.125 0.5 4.25 1.125 6.25 1.625 2.375 0.5 4.875 1.125 7.25 1.625 2.75 0.5 5.875 1.125 8.625 1.625 3.75 0.75 7.5 1.125 11.125 1.625 9.25 1.125 19.125 1.625 28.875 1.625h1.375c9.25 0 18.375-0.75 27.5-1.625 3.75-0.5 7.25-0.875 10.75-1.625 2.75-0.5 5.625-0.875 8.375-1.625 2.375-0.5 4.625-0.875 7-1.625 2.125-0.5 4.25-0.875 6.25-1.625 1.875-0.5 3.75-0.875 5.625-1.625 1.625-0.5 3.5-0.875 5.125-1.625 1.625-0.5 3.25-0.875 4.625-1.625 1.375-0.5 3-0.875 4.375-1.625 1.375-0.5 2.75-0.875 4.25-1.625 1.375-0.5 2.5-0.875 4-1.625 1.125-0.5 2.5-0.875 3.75-1.625 1.125-0.5 2.375-0.875 3.5-1.625 1.125-0.5 2.375-0.875 3.5-1.625 1.125-0.5 2.125-0.875 3.25-1.625 1.125-0.5 2.125-0.875 3.25-1.625 0.875-0.5 2.125-0.875 3-1.625 0.875-0.5 1.875-0.875 3-1.625 0.875-0.5 1.875-0.875 2.75-1.625 0.875-0.5 1.875-0.875 2.75-1.625 0.875-0.5 1.875-0.875 2.5-1.625 0.875-0.5 1.625-0.875 2.5-1.625 0.875-0.5 1.625-0.875 2.5-1.625 0.875-0.5 1.625-0.875 2.5-1.625 0.75-0.5 1.625-0.875 2.375-1.625 0.75-0.5 1.625-0.875 2.375-1.625 0.75-0.5 1.375-0.875 2.375-1.625 0.75-0.5 1.375-0.875 2.125-1.625 0.75-0.5 1.375-0.875 2.125-1.625 0.75-0.5 1.375-0.875 2.125-1.625 0.75-0.5 1.375-0.875 2.125-1.625 0.75-0.5 1.375-0.875 1.875-1.625 0.75-0.5 1.375-0.875 1.875-1.625 0.75-0.5 1.125-0.875 1.875-1.625 0.75-0.5 1.125-0.875 1.875-1.625 0.75-0.5 1.125-0.875 1.875-1.625 0.75-0.5 1.125-0.875 1.875-1.625 0.5-0.5 1.125-0.875 1.625-1.625 0.5-0.5 1.125-0.875 1.625-1.625 0.5-0.5 1.125-0.875 1.625-1.625 0.5-0.5 1.125-0.875 1.625-1.625 0.5-0.5 1.125-0.875 1.625-1.625l1.625-1.625 1.625-1.625c0.5-0.5 0.875-0.875 1.375-1.625 0.5-0.5 0.875-0.875 1.375-1.625 0.5-0.5 0.875-0.875 1.375-1.625 0.5-0.5 0.875-0.875 1.375-1.625 0.5-0.5 0.875-0.875 1.375-1.625 0.5-0.5 0.875-0.875 1.375-1.625 0.5-0.5 0.875-0.875 1.375-1.625 0.5-0.5 0.875-0.875 1.375-1.625 0.5-0.5 0.875-0.875 1.125-1.625 0.5-0.5 0.75-0.875 1.125-1.625 0.5-0.5 0.875-0.875 1.125-1.625 0.5-0.5 0.75-0.875 1.125-1.625 0.5-0.5 0.75-0.875 1.125-1.625 0.5-0.5 0.75-0.875 1.125-1.625 0.5-0.5 0.75-0.875 1.125-1.625 0.5-0.5 0.75-0.875 1.125-1.625 0.5-0.5 0.75-0.875 1.125-1.625 0.5-0.5 0.75-0.875 0.875-1.625 0.25-0.5 0.75-0.875 0.875-1.625 0.25-0.5 0.75-0.875 0.875-1.625 0.25-0.5 0.75-0.875 0.875-1.625 0.25-0.5 0.75-0.875 0.875-1.625 0.25-0.5 0.75-0.875 0.875-1.625 0.25-0.5 0.75-0.875 0.875-1.625 0.25-0.5 0.5-0.875 0.875-1.625 0.25-0.5 0.75-0.875 0.875-1.625 0.25-0.5 0.5-0.875 0.875-1.625 0.25-0.5 0.5-0.875 0.875-1.625 0.25-0.5 0.5-0.875 0.875-1.625 0.25-0.5 0.5-0.875 0.75-1.625 0.25-0.5 0.5-0.875 0.75-1.625 0.25-0.5 0.5-0.875 0.75-1.625 0.25-0.5 0.5-0.875 0.75-1.625 0.25-0.5 0.5-0.875 0.75-1.625 0.25-0.5 0.5-0.875 0.75-1.625 0.25-0.5 0.5-0.875 0.75-1.625 0.25-0.5 0.5-0.875 0.75-1.625 0.25-0.5 0.5-0.875 0.75-1.625 0.25-0.5 0.5-0.875 0.75-1.625 0.25-0.5 0.5-0.875 0.75-1.625 0.25-0.5 0.5-0.875 0.5-1.625 0.25-0.5 0.5-0.875 0.5-1.625 0.25-0.5 0.5-0.875 0.5-1.625 0.25-0.5 0.25-0.875 0.5-1.625 0.25-0.5 0.25-0.875 0.5-1.625 0.25-0.5 0.25-0.875 0.5-1.625 0.25-0.5 0.25-0.875 0.5-1.625 0.25-0.5 0.25-0.875 0.5-1.625 0.25-0.5 0.25-0.875 0.5-1.625 0.25-0.5 0.25-0.875 0.5-1.625 0.25-0.5 0.25-0.875 0.5-1.625 0.25-0.5 0.25-0.875 0.5-1.625 0.25-0.5 0.25-0.875 0.5-1.625 0.25-0.5 0.25-0.875 0.5-1.625 0.25-0.5 0.25-0.875 0.5-1.625 0-0.5 0.25-0.875 0.25-1.625 0-0.5 0.25-0.875 0.25-1.625 0-0.5 0.25-0.875 0.25-1.625 0-0.5 0.25-0.875 0.25-1.625 0-0.5 0.25-0.875 0.25-1.625 0-0.5 0.25-0.875 0.25-1.625 0-0.5 0.25-0.875 0.25-1.625 0-0.5 0.25-0.875 0.25-1.625 0-0.5 0.25-0.875 0.25-1.625 0-0.5 0-0.875 0.25-1.625 0-0.5 0-0.875 0.25-1.625 0-0.5 0-0.875 0.25-1.625 0-0.5 0-0.875 0.25-1.625 0-0.5 0-0.875 0.25-1.625v-11.375h-3.125zM589.714646 384c-12.625 0-25.375-12.75-25.375-25.375 0-12.75 12.75-25.375 25.375-25.375 19.375 0 31.875 12.625 31.875 25.375-0.125 12.625-12.75 25.375-31.875 25.375zM729.589646 384c-12.625 0-25.375-12.75-25.375-25.375 0-12.75 12.75-25.375 25.375-25.375 19.125 0 31.875 12.625 31.875 25.375 0 12.625-12.75 25.375-31.875 25.375zM328.714646 568.75c-19.125 0-38.375-12.625-38.375-31.625 0-19.125 19.375-31.875 38.375-31.875s31.875 12.75 31.875 31.875-12.875 31.625-31.875 31.625zM506.964646 568.75c-19.125 0-38.125-12.625-38.125-31.625 0-19.125 19.125-31.875 38.125-31.875 19.125 0 31.875 12.75 31.875 31.875s-12.875 31.625-31.875 31.625z"  horiz-adv-x="1059" />
+      
+      <glyph glyph-name="username" unicode="&#58991;" d="M514.594 824.888c-144.11 0-260.979-118.46-260.979-264.558 0-88.783 43.497-166.928 109.711-214.898-135.361-59.354-230.159-195.858-230.159-354.931h0.894c1.541-21.375 18.641-38.377 40.117-38.377s38.575 17.051 40.117 38.377h0.645c0 0.944-0.099 1.79-0.099 2.734 0 0.05 0 0.099 0 0.149 0 0.099-0.05 0.149-0.05 0.199 0.05 159.967 120 291.054 273.009 304.924 8.948-0.944 17.598-2.734 26.844-2.734 144.11 0 260.979 118.46 260.979 264.558s-116.919 264.558-261.029 264.558zM514.594 377.54499999999996c-99.769 0-180.698 81.972-180.698 183.183s80.879 183.183 180.698 183.183c99.719 0 180.647-81.972 180.647-183.183s-80.879-183.183-180.647-183.183zM896.021-6.615000000000009c0 0.348-0.199 0.645-0.199 0.994-1.043 105.038-43.397 200.034-111.35 269.131v0c-7.157 7.357-17.001 11.98-27.986 11.98-21.574 0-39.122-17.747-39.122-39.668 0-11.135 4.573-21.127 11.83-28.334l-0.099-0.05c52.742-55.229 85.302-130.589 85.302-213.853 0-1.043-0.149-1.987-0.149-3.034h0.994c1.491-21.375 18.691-38.377 40.117-38.377 21.475 0 38.575 17.051 40.117 38.377h0.597c0 0.796-0.099 1.491-0.099 2.287-0.05 0.149 0.05 0.348 0.05 0.547z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="password" unicode="&#58995;" d="M519.2 343.29999999999995c-41.1 0-74.4-33.3-74.4-74.4 0-29.7 17.5-55 42.5-67.1v-81.9c0-17.6 14.3-31.9 31.9-31.9 17.6 0 31.9 14.3 31.9 31.9v81.9c25.1 12 42.5 37.4 42.5 66.9 0 41.3-33.2 74.6-74.4 74.6zM827.6-62.10000000000002H189.4c-35.9 0-65.1 29.2-65.1 65.1V428.4c0 35.9 29.2 65.1 65.1 65.1h638.2c17.3 0 33.7-6.7 46-19.1 12.3-12.3 19.1-28.7 19.1-46V3c0-35.9-29.2-65.1-65.1-65.1zM231.9 427.2c-34.8 0-41.3-6.6-41.3-41.3v-340.4c0-34.8 6.6-41.3 41.3-41.3h553.2c34.8 0 41.3 6.6 41.3 41.3V385.9c0 34.8-6.6 41.3-41.3 41.3H231.9zM519.2 86.70000000000005c-18.3 0-33.2 14.8-33.2 33.2V201c-26.3 12.8-42.6 38.8-42.6 67.8 0 41.8 33.9 75.7 75.7 75.7s75.7-33.9 75.7-75.7c0-29-16.3-55-42.5-67.8v-81.1c0.1-18.2-14.9-33.2-33.1-33.2zM519.2 342c-40.4 0-73.2-32.9-73.2-73.2 0-28.3 16.1-53.6 41.9-65.8l0.7-0.4V120c0-17 13.7-30.7 30.7-30.7S550 103.10000000000002 550 120v82.6l0.7 0.4c25.8 12.3 41.9 37.5 41.9 65.8-0.2 40.4-33.1 73.2-73.4 73.2zM207 523.1c-9.1 0-17.6 3.5-23.9 10-6.4 6.4-10 15-10 23.9v2h-0.2l0.2 1.4c0.1 0.5 0.1 0.9 0.2 1.4l0.2 1c0.1 0.6 0.2 1.4 0.4 2 15.3 75.7 57 144.2 117.2 193 29.9 24.2 63.4 43 99.8 56 37.5 13.3 77 20.2 117.5 20.2 61 0 120.8-16.3 173-47.2 50.6-29.9 93-72.8 122.5-123.8 4-5.6 6.1-12.2 6.1-19.2 0-18.3-15-33.3-33.3-33.3-13.2 0-25.1 7.7-30.4 19.8-49.2 84.6-140.4 137.4-238 137.4-128.1 0-238.2-87.1-267.6-211.8v-0.2c-0.7-18.4-15.4-32.6-33.7-32.6z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="refresh-3" unicode="&#59818;" d="M820.376904 697.14807C740.637816 774.519228 631.884926 822.157201 511.999488 822.157201c-244.621347 0-442.925808-198.305485-442.925808-442.926832 0-244.6193 198.304462-442.925808 442.925808-442.925808 206.075449 0 379.271046 140.739395 428.740738 331.337337L822.859445 267.64189899999997c-45.759183-127.45381-167.656441-218.623229-310.859957-218.623229-182.371584 0-330.210677 147.842163-330.210677 330.210677 0 182.371584 147.840116 330.2117 330.210677 330.2117 88.762603 0 169.32443-35.035958 228.655723-92.015693L557.051567 433.822732l280.641725 0 113.880677 0 3.351328 0L954.925297 831.695438 820.376904 697.14807z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="auz" unicode="&#58994;" d="M324.266667 435.2c-17.066667 17.066667-39.822222 17.066667-51.2 0-17.066667-17.066667-17.066667-39.822222 0-51.2l153.6-159.288889c5.688889-5.688889 17.066667-11.377778 28.444444-11.377778s17.066667 5.688889 28.444445 11.377778l295.822222 290.133333c17.066667 17.066667 17.066667 39.822222 0 51.2-17.066667 17.066667-39.822222 17.066667-51.2 0L455.111111 304.355556 324.266667 435.2zM927.288889 753.777778L523.377778 896h-22.755556L96.711111 753.777778c-17.066667-5.688889-28.444444-17.066667-28.444444-34.133334v-432.355555c11.377778-250.311111 409.6-409.6 426.666666-415.288889h22.755556c17.066667 5.688889 415.288889 159.288889 426.666667 415.288889V719.644444c11.377778 17.066667 0 28.444444-17.066667 34.133334z m-45.511111-460.8c-5.688889-182.044444-301.511111-312.888889-369.777778-341.333334-113.777778 45.511111-358.4 182.044444-369.777778 341.333334v398.222222L512 822.044444l369.777778-125.155555v-403.911111z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="shrink-right" unicode="&#58984;" d="M52.294-28.71900000000005h899.793c16.546 0 29.999 13.405 29.999 29.999v59.974c-0.013 16.562-13.436 29.985-29.998 29.999h-899.795c-16.57 0-29.999-13.429-29.999-29.999v-59.974c0-16.617 13.429-29.999 29.999-29.999zM952.087 451.165h-479.884c-16.57 0-29.999-13.405-29.999-29.999v-59.974c0 0 0 0 0 0 0-16.572 13.428-30.01 29.997-30.022h479.885c16.571 0.013 29.999 13.448 29.999 30.022 0 0 0 0 0 0v59.974c0 16.593-13.429 29.999-29.999 29.999zM52.294 691.0840000000001h899.793c16.554 0.013 29.972 13.423 29.999 29.974v59.999c0 16.57-13.429 29.999-29.999 29.999h-899.793c-16.57 0-29.999-13.429-29.999-29.999v-59.997c0-16.546 13.429-29.975 29.999-29.975zM45.183 383.53499999999997l239.919-150.598v301.196l-239.919-150.598z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="spread-left" unicode="&#58987;" d="M942.974 770.924h-843.556c-15.513 0-28.124-12.567-28.124-28.124v-56.226c0.012-15.527 12.596-28.111 28.123-28.124h843.559c15.534 0 28.124 12.59 28.124 28.124v56.226c0 15.578-12.59 28.124-28.124 28.124zM99.418 321.033h449.891c15.534 0 28.124 12.567 28.124 28.124v56.226c0 0 0 0 0 0 0 15.537-12.589 28.134-28.122 28.146h-449.892c-15.534-0.012-28.124-12.608-28.124-28.146 0 0 0 0 0 0v-56.226c0-15.556 12.59-28.124 28.124-28.124zM942.974 96.10900000000004h-843.556c-15.519-0.012-28.099-12.584-28.124-28.101v-56.249c0-15.534 12.59-28.124 28.124-28.124h843.556c15.534 0 28.124 12.59 28.124 28.124v56.248c0 15.513-12.59 28.103-28.124 28.102zM949.641 384.436l-224.924 141.186v-282.37l224.924 141.186z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="snowflake" unicode="&#59057;" d="M480.695-64h63.725V59.291000000000054l68.854-68.242 44.945 44.546-113.798 112.79v180.02l177.271-102.44 41.67-155.652 60.725 16.284-25.398 94.872 85.259-49.266 31.87 55.246-84.726 48.961 94.497 25.343-16.495 61.622-156.068-41.855-176.934 102.245 177.667 102.667 155.513-41.709 16.274 60.793-94.78 25.418 85.255 49.264-31.869 55.247-84.733-48.965 25.326 94.594-61.557 16.51-41.817-156.206-176.948-102.251V644.461l113.849 113.951-44.459 44.496-69.392-69.454V832h-63.725v-97.935l-69.188 69.249-45.068-45.107 114.256-114.355V438.89l-156.557 90.469L283.45 684.39l-60.188-16.458 24.84-94.632-107.544 62.145-31.868-55.247 106.667-61.639-93.463-25.557 16.074-61.237 154.482 42.243 156.169-90.243-156.138-90.226-154.485 42.243-15.855-60.409 94.289-25.784-107.534-62.14 31.868-55.247 106.672 61.642-24.621-93.801 61.012-16.685 40.69 155.028 156.179 90.25v-180.455l-113.801-112.79 44.338-43.944 69.463 68.845V-64z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="tips" unicode="&#59138;" d="M967.280184 578.537671c-24.915459 58.887178-60.544935 111.76755-105.96745 157.161413-45.393863 45.393863-98.273211 81.051991-157.160389 105.96745-60.988026 25.803689-125.735679 38.853913-192.494129 38.853913-66.729797 0-131.504056-13.0799-192.494129-38.853913-58.887178-24.916483-111.766526-60.544935-157.160389-105.96745-45.393863-45.393863-81.051991-98.274234-105.96745-157.161413-25.803689-60.988026-38.884612-125.734656-38.884612-192.464453s13.0799-131.50508 38.884612-192.464453c24.915459-58.887178 60.544935-111.737874 105.96745-157.161413 45.393863-45.393863 98.273211-81.051991 157.160389-105.96745 60.988026-25.803689 125.735679-38.853913 192.494129-38.853913 66.729797 0 131.504056 13.0799 192.494129 38.853913 58.887178 24.916483 111.766526 60.544935 157.160389 105.96745 45.393863 45.393863 81.051991 98.274234 105.96745 157.161413 25.803689 60.988026 38.853913 125.734656 38.853913 192.464453S993.084896 517.549645 967.280184 578.537671zM511.687892-55.138552000000004c-243.302305 0-441.241446 197.909465-441.241446 441.21177S268.385587 827.284989 511.687892 827.284989c243.273652-0.029676 441.210747-197.938118 441.210747-441.21177S754.990197-55.138552000000004 511.687892-55.138552000000004zM511.657192 573.565427m-45.511543 0a44.475 44.475 0 1 1 91.023086 0 44.475 44.475 0 1 1-91.023086 0ZM542.729885 184.14011300000004c0-17.162892-13.906731-31.071669-31.070646-31.071669l0 0c-17.163915 0-31.070646 13.907755-31.070646 31.071669L480.588593 426.998303c0 17.162892 13.906731 31.071669 31.070646 31.071669l0 0c17.163915 0 31.070646-13.907755 31.070646-31.071669L542.729885 184.14011300000004z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="note" unicode="&#58990;" d="M987.2 384.36L512.43 859.13a84.75 84.75 0 0 1-65 24.71L111.55 864.09a84.83 84.83 0 0 1-79.65-79.65L12.15 448.57a84.57 84.57 0 0 1 24.69-65l474.8-474.8a84.91 84.91 0 0 1 119.93 0L987.2 264.41999999999996a84.9 84.9 0 0 1 0 119.94z m-39.28-80.66L592.29-51.91999999999996a29.31 29.31 0 0 0-41.37 0L76.1 422.9a29.22 29.22 0 0 0-8.49 22.38l19.74 335.88a29.29 29.29 0 0 0 27.48 27.48l335.9 19.75a29.32 29.32 0 0 0 22.38-8.52l474.8-474.8a29.31 29.31 0 0 0 0.01-41.37zM236.86 659.14c-50.92-50.95-50.92-133.8 0-184.72a130.61 130.61 0 1 1 184.71 184.72c-50.89 50.86-133.77 50.86-184.71 0zM382.29 513.7c-28.38-28.38-77.78-28.38-106.15 0a75.08 75.08 0 1 0 106.15 0z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="senior" unicode="&#58996;" d="M719.9 292.06666666L514.7 422.16666666V527.76666666C615.6 461.66666666 731.5 386.66666666 731.5 386.66666666s139.2-45.6 139.2 106.5c0 93-172.5 112.1-197.2 11.8l-69.6 47.3s24.2 101.5 162.4 106.5c138.2 4.9 192-94.6 190.9-199.6-1.2-104.7-136-198.3-237.3-167.1zM561 456.66666666c-4-19-23-33.7-47.6-33.7l-6.9 4.3-217.3 137.8S171 597.86666666 160.8 481.66666666c-10.2-116.1 147.4-129.5 186.8-23.8l81.7-47.6s-65.1-119.1-198.5-119.1C97.3 291.16666666000003 0.6 466.46666666 114 588.96666666c113.5 122.4 218.6 64.6 257 35.7 16.4-12.4 85.3-57.9 158.6-105.9l3.1-2.4c28.3-18.2 33.4-35.6 28.3-59.7zM434.1 192.36666665999996h212c16.7 0 30.3-13.6 30.3-30.3v-15.1c0-16.7-13.6-30.3-30.3-30.3h-212c-16.7 0-30.3 13.6-30.3 30.3v15.1c0 16.8 13.6 30.3 30.3 30.3z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="refresh-1" unicode="&#58982;" d="M688.146 736l-192 128v-256l192 128.001zM496.146 767.7090000000001c-231.174-8.416-416-198.479-416-431.709 0-238.587 193.413-432 432-432 233.23 0 423.293 184.826 431.709 416h-64.05c-8.377-195.817-169.778-352-367.658-352-203.241 0-368 164.759-368 368 0 197.88 156.183 359.282 352 367.658v64.051z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="refresh" unicode="&#58985;" d="M928 810.666667c-18.133333 0-32-13.866667-32-32v-164.266667C816 747.733333 669.866667 832 512 832 264.533333 832 64 631.4666669999999 64 384s200.533333-448 448-448c230.4 0 422.4 172.8 445.866667 402.133333 2.133333 17.066667-10.666667 33.066667-28.8 35.2-17.066667 2.133333-33.066667-10.666667-35.2-28.8C873.6 148.26666699999998 709.333333 0 512 0c-212.266667 0-384 171.733333-384 384s171.733333 384 384 384c137.6 0 264.533333-74.666667 332.8-192H693.333333c-18.133333 0-32-13.866667-32-32s13.866667-32 32-32h266.666667V778.666667c0 18.133333-14.933333 32-32 32z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="flag" unicode="&#58988;" d="M878.368178 798.272211c-11.363815 4.799306-24.470321 2.360767-33.31578-6.245238-0.36532-0.350994-37.162388-35.304064-95.163383-56.05262-75.462692-26.993794-150.763702-18.409279-223.812415 25.517163-38.347376 23.060205-81.875752 40.665165-129.376603 52.327786-37.582967 9.228175-77.742619 14.777565-119.363552 16.496719-70.805626 2.925632-121.493052-6.224772-123.615389-6.615675-14.56574-2.682086-25.140587-15.380292-25.140587-30.191626L128.58047-31.312913999999978c0-16.954137 13.745049-30.699186 30.699186-30.699186s30.699186 13.745049 30.699186 30.699186L189.978842 266.68306099999995c15.562441 5.250584 47.994084 14.447037 91.40171 17.48728 35.985586 2.51938 72.440869 0.378623 108.35073-6.363941 44.847417-8.420787 89.059362-24.102954 131.409912-46.611597 46.26879-24.591071 93.776803-41.069371 141.203976-48.977481 38.270629-6.380314 76.541257-7.219425 113.740484-2.491751 64.277956 8.16803 103.877859 30.461779 105.532545 31.406291 9.56689 5.464455 15.471366 15.637142 15.471366 26.656103L897.089565 769.958352C897.091612 782.298402 889.73711 793.470859 878.368178 798.272211zM835.69324 257.496841c-14.58416-5.755074-38.82526-13.530155-70.319555-17.225313-30.990828-3.635807-62.940494-2.676969-94.952582 2.851954-40.201607 6.943133-80.731696 21.171182-120.464629 42.289152-48.455595 25.753547-99.208513 43.61945-150.848637 53.101405-29.29214 5.378497-58.896388 8.079002-88.407516 8.079002-12.228509 0-24.443715-0.464581-36.609803-1.39272-34.879392-2.663666-63.618946-8.741082-84.111676-14.355963L189.978842 766.569162c19.971867 2.003634 50.446949 3.910053 86.392626 2.334161 58.186214-2.554172 143.250588-15.041578 218.064504-60.029188 61.32674-36.877909 119.196753-49.491181 169.691797-49.488111 42.293245 0.002047 79.416747 8.854669 109.019972 19.711947 24.269753 8.901741 45.327348 19.747763 62.544475 30.179346L835.692217 257.496841z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="theme" unicode="&#58986;" d="M512 800C229.696 800 0 570.304 0 288c0-90.368 30.304-174.496 85.344-236.896 55.264-62.624 129.152-97.12 208.128-97.12 81.568 0 161.536 36.832 231.264 106.592l2.272 2.496c65.792 81.472 132.896 121.056 205.088 121.056 46.72 0 89.216-15.872 126.688-29.92 30.336-11.328 56.576-21.12 81.216-21.12C1024 133.08799999999997 1024 241.664 1024 288c0 282.304-229.696 512-512 512z m428-602.912c-13.088 0-35.296 8.288-58.784 17.088-40.48 15.136-90.848 33.952-149.12 33.952-92.352 0-175.328-46.944-253.76-143.456-57.184-56.704-121.056-86.688-184.832-86.688-60.352 0-117.216 26.784-160.128 75.456C88.64 144.12800000000004 64 213.216 64 288 64 535.04 264.96 736 512 736s448-200.96 448-448c0-27.328-1.952-90.912-20-90.912zM800.704 379.93600000000004m-64 0a64 64 0 1 1 128 0 64 64 0 1 1-128 0ZM457.024 582.624m-64 0a64 64 0 1 1 128 0 64 64 0 1 1-128 0ZM672.704 555.9359999999999m-64 0a64 64 0 1 1 128 0 64 64 0 1 1-128 0ZM291.392 443.936m-64 0a64 64 0 1 1 128 0 64 64 0 1 1-128 0ZM278.4 197.24800000000005m-96 0a96 96 0 1 1 192 0 96 96 0 1 1-192 0Z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="notice" unicode="&#58983;" d="M544 798.976V864h-64v-65.024C289.536 786.304 160 658.624 160 416v-288h64V416c0 192 115.456 320 288 320 180.544 0 288-128 288-320v-288h64V416c0 242.88-122.496 370.56-320 382.976zM672 64a160 160 0 1 0-320 0h64a96 96 0 0 1 192 0h64zM64 128h896v-64H64v64z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="console" unicode="&#58981;" d="M30.552 104.72699999999998c4.654-16.29 23.272-23.272 37.236-18.618 16.291 4.655 23.273 23.273 18.618 37.236C16.588 314.182 84.08 521.31 237.68 640c11.636 9.31 23.273 16.29 37.236 25.6 25.6 16.29 53.528 30.255 83.782 39.564 58.182 20.945 118.691 30.254 176.873 27.927h25.6c6.982 0 11.636 0 18.618-2.327 30.255-4.655 58.182-11.637 88.436-23.273 235.055-86.11 356.073-346.764 269.964-581.818-4.654-16.291 2.327-32.582 18.618-37.237 16.291-4.654 32.582 2.328 37.237 18.619 41.89 116.363 39.563 239.709 0 349.09h2.327C921.897 656.2909999999999 738.043 784.2909999999999 537.897 793.6h-48.873c-200.145-9.31-384-137.31-458.472-337.455-39.564-109.381-41.891-232.727 0-351.418z m707.49 386.328a29.498 29.498 0 0 1-41.89 0L521.606 316.509c-4.654 2.327-9.309 2.327-13.963 2.327-32.582 0-58.182-25.6-58.182-58.181s25.6-58.182 58.182-58.182 58.181 25.6 58.181 58.182c0 4.654 0 9.309-2.327 16.29l174.546 174.546c11.636 11.636 11.636 30.254 0 39.564z m228.073-458.473H58.48c-16.29 0-30.255-13.964-30.255-30.255 0-16.29 13.964-30.254 30.255-30.254h907.636c16.291 0 30.255 13.963 30.255 30.254 0 16.291-13.964 30.255-30.255 30.255z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="website" unicode="&#59310;" d="M777.073418 147.443038c-30.460759 21.387342-40.83038 40.182278-76.47595 53.792405 25.275949 60.273418 40.182278 83.605063 42.126583 154.896203H887.898734c-3.888608-99.159494-45.367089-143.878481-110.825316-208.688608zM136.101266 356.13164600000005h167.210126c1.944304-71.291139 16.850633-94.622785 42.126583-154.896203-34.997468-13.610127-68.050633-31.756962-98.511393-53.792405C181.468354 212.25316499999997 139.989873 256.97215200000005 136.101266 356.13164600000005z m103.048101 259.888607c29.164557-23.979747 61.56962-42.774684 96.567089-57.681012-19.443038-53.792405-30.460759-90.734177-31.756962-152.951899H136.101266c3.240506 90.734177 46.663291 147.767089 103.048101 210.632911z m309.144304-209.98481V523.989873c47.311392 1.296203 71.291139 10.36962 114.065823 25.27595 18.146835-51.2 28.516456-84.901266 30.460759-143.23038H548.293671z m104.344304-195.078481c-40.182278 12.962025-60.273418 20.091139-104.344304 21.387342V356.13164600000005h144.526582c-1.944304-68.050633-16.202532-88.141772-40.182278-145.174684z m36.941772-57.681013c31.756962-12.313924 39.534177-28.516456 66.75443-47.311392-51.848101-44.718987-114.713924-73.883544-182.116455-84.901266 36.941772 37.589873 90.734177 82.308861 115.362025 132.212658z m-163.321519-137.397468l22.035443 165.913924c40.182278-1.296203 56.38481-7.777215 92.678481-18.794937-27.220253-56.38481-66.106329-106.288608-113.417722-147.118987h-1.296202z m-75.827848 5.18481c-67.402532 11.017722-130.268354 40.83038-182.764557 84.901266 27.868354 19.443038 57.681013 34.997468 88.789873 47.311392 23.331646-48.607595 55.088608-93.326582 93.974684-132.212658z m47.311392 335.068355v-123.787342c-44.070886-1.296203-64.162025-8.425316-104.344304-21.387342-23.979747 57.681013-38.237975 77.124051-40.182278 145.174684h144.526582zM383.675949 549.265823c42.774684-14.906329 66.75443-23.331646 114.065823-25.27595v-117.95443H353.21519c1.944304 58.329114 12.313924 92.03038 30.460759 143.23038z m-37.589873 57.032911c-31.756962 12.962025-60.921519 30.460759-88.141772 51.848101 53.792405 51.848101 115.362025 91.382278 192.486076 104.344304-44.718987-44.718987-80.364557-97.863291-104.344304-156.192405z m151.655696 161.377215v-193.782278c-44.070886 1.296203-64.162025 9.073418-103.696202 22.683544 29.164557 68.698734 49.903797 127.027848 102.4 171.098734h1.296202z m75.827848-4.536708c77.772152-13.610127 149.711392-49.903797 206.744304-104.344304-29.164557-22.035443-46.01519-37.589873-80.364557-51.848102-25.275949 59.625316-82.956962 112.76962-126.379747 156.192406z m-46.01519 4.536708c54.440506-46.01519 97.21519-104.992405 124.435443-171.098734-39.534177-13.610127-59.625316-21.387342-103.696202-22.683544l-22.035443 193.782278h1.296202z m-31.10886-751.149367c-46.663291 38.886076-62.865823 88.789873-91.382279 147.118988 36.293671 11.665823 53.144304 17.498734 93.326582 18.794936v-165.913924h-1.944303zM887.898734 406.035443h-145.174683c-1.296203 61.56962-12.313924 98.511392-31.756962 152.303798 37.589873 15.55443 57.032911 33.053165 88.789873 57.681012 56.38481-62.865823 84.901266-119.898734 88.141772-209.98481z m-375.898734 427.746835c-244.334177 0-442.005063-197.670886-442.005063-442.005063S267.665823-50.227847999999994 512-50.227847999999994s442.005063 197.670886 442.005063 442.005063S756.334177 833.782278 512 833.782278z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="face-surprised" unicode="&#58980;" d="M485.656116-128C221.592397-128 6.762016 86.81718000000001 6.762016 350.87649799999997s214.830381 478.867697 478.8941 478.867697c264.041716 0 478.854495-214.812779 478.854495-478.867697S749.697832-128 485.656116-128zM485.656116 798.834741c-247.024795 0-447.975846-200.959852-447.975846-447.962644 0-247.002792 200.951051-447.962644 447.975846-447.962644 247.002792 0 447.953843 200.959852 447.953843 447.962644C933.609959 597.8748889999999 732.658908 798.834741 485.656116 798.834741zM352.033458 447.380528c0-30.469398-24.682677-55.147675-55.143274-55.147675-30.451796 0-55.143274 24.678276-55.143274 55.147675 0 30.460597 24.691478 55.138874 55.143274 55.138874C327.350781 502.519402 352.033458 477.845526 352.033458 447.380528zM674.417647 502.519402c-30.460597 0-55.156476-24.678276-55.156476-55.138874 0-30.469398 24.695879-55.147675 55.156476-55.147675 30.451796 0 55.143274 24.678276 55.143274 55.147675C729.560922 477.845526 704.869444 502.519402 674.417647 502.519402zM562.005634 165.30976499999997c0-59.733046-34.192262-108.165484-76.349518-108.165484-42.166057 0-76.36272 48.432438-76.36272 108.165484 0 59.724245 34.196663 108.152282 76.36272 108.152282C527.813371 273.45764699999995 562.005634 225.03400999999997 562.005634 165.30976499999997zM835.631745 793.712503c0 0 12.871605 56.819883 41.959231 85.925112 29.083226 29.096427 69.915916 15.124685 78.492585-8.801097 9.461179-26.385689-2.033053-50.069442-29.092027-56.164202C899.404495 808.463141 874.880237 826.192952 835.631745 793.712503zM916.698651 757.570797c0 0 35.767659 20.576965 64.877288 19.393218 29.136032-1.174946 41.431165-29.144833 33.109728-45.110024-9.192746-17.588993-27.054573-22.966463-43.217788-11.797871C954.979023 731.44034 952.453108 752.721393 916.698651 757.570797z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="set" unicode="&#59158;" d="M466.496-126.62400000000002l-1.056 0.064c-25.184 2.08-47.456 22.368-51.744 47.232l-17.344 102.4c-0.672 4.064-6.624 11.04-10.56 12.416l-30.336 12.416c-5.44 2.496-15.424 0.8-17.472-0.64l-84.992-60.16c-19.584-14.016-51.456-12.736-70.08 3.168l-64.288 64c-17.952 20.48-19.488 50.592-4.736 71.296l60.416 84.672c2.176 3.072 2.784 11.52 1.024 15.04l0 0c0 0-1.664 3.104-7.264 16.608-6.176 14.848-6.816 17.44-6.816 17.44-0.992 3.04-7.456 8.672-11.36 9.376l-102.56 17.248c-25.152 4.288-45.44 26.624-47.168 52L0 428.288c2.112 27.36 22.496 49.6 47.52 53.728l102.528 17.344c4.128 0.672 11.008 6.56 12.416 10.496l12.608 30.336c2.368 4.992 1.6 14.112-0.8 17.504L113.984 642.24C99.36 662.88 100.704 692.896 117.056 712.192l64.416 64.224c20.672 18.208 51.296 18.784 71.36 4.64l84.992-60.16c1.952-1.376 13.28-2.016 15.04-1.056 0.384 0.192 2.528 1.344 16.704 7.168 14.24 5.92 16.576 6.592 16.576 6.592 3.84 1.184 9.504 7.648 10.144 11.424l17.44 102.4c4.32 25.152 26.752 45.376 52.128 47.104l90.528 0.064c27.328-2.112 49.632-22.368 53.952-47.232l17.344-102.432c0.672-4.064 6.656-11.04 10.624-12.48l30.304-12.352c6.24-2.784 15.456-0.8 17.44 0.608l85.024 60.16c19.52 14.016 51.392 12.704 70.08-3.136l64.288-64.032c17.952-20.48 19.456-50.56 4.736-71.264l-60.416-84.672c-2.208-3.136-2.848-11.616-1.056-15.04 0.16-0.352 1.376-2.56 7.232-16.672 5.856-14.112 6.592-16.512 6.592-16.512 1.248-4.032 7.712-9.6 11.648-10.304l102.56-17.248c25.152-4.224 45.44-26.592 47.168-52l0.096-90.304c-2.112-27.392-22.528-49.6-47.552-53.728l-102.528-17.376c-4.128-0.672-10.944-6.496-12.32-10.432l-12.736-30.432c-2.336-4.928-1.568-14.112 0.832-17.472l60.288-84.512c14.624-20.736 13.216-50.816-3.232-70.048l-64.192-64.096c-11.328-9.92-24.64-14.72-38.784-14.72l0 0c-11.904 0-23.52 3.552-32.704 10.016l-84.992 60.16c-1.952 1.408-13.312 2.016-15.072 1.056-0.288-0.16-2.432-1.312-16.608-7.2-14.08-5.792-16.384-6.496-16.384-6.496-4.16-1.28-9.792-7.776-10.432-11.52l-17.408-102.4c-4.352-25.152-26.72-45.344-52.032-47.104L466.496-126.62400000000002zM347.84 100.60799999999995c10.368 0 20.192-2.112 28.48-6.112l27.648-11.296c20.416-7.072 38.976-28.992 42.848-51.584l17.344-102.336c0.288-1.6 3.136-4.32 5.056-4.832l87.296 0.064c-0.032 0.064 3.04 2.944 3.328 4.672l17.408 102.368c3.872 22.656 23.328 44.832 45.28 51.584 0 0 0 0 0 0-0.096 0 2.976 1.152 12.448 5.056 9.472 3.936 12.384 5.248 13.12 5.568 18.208 9.6 49.44 8.032 67.776-4.96l84.928-60.16c0.192-0.128 1.312-0.64 3.104-0.64l0 0c2.048 0 3.52 0.672 3.872 0.96l61.536 61.408 0 0c-0.16 0 0.064 4.416-0.992 5.952l-60.224 84.448c-13.248 18.624-15.68 47.168-5.792 67.872l11.648 27.84c6.944 19.968 29.408 38.912 51.68 42.496l102.464 17.376c1.824 0.384 4.736 3.648 4.864 5.408L972.8 428.288l0 0c-0.096 0-2.88 3.072-4.576 3.424l-102.72 17.28c-23.168 4.032-44.896 22.976-51.776 45.056l0 0c-0.032 0-1.216 3.04-5.12 12.512-3.968 9.568-5.28 12.512-5.632 13.248-10.24 19.36-8.288 48.736 4.96 67.456L868.448 672c0.96 1.408 0.736 5.6-0.384 6.912l-61.408 61.184c0.704-0.8-0.768-0.192-2.848-0.192-1.728 0-2.784-0.416-3.008-0.576l-85.024-60.16c-17.824-12.8-47.776-15.36-68-5.664l-27.712 11.296c-20.512 7.2-39.04 29.088-42.88 51.584l-17.344 102.336c-0.288 1.76-3.616 4.704-5.504 4.864L467.616 843.52c0-0.064-3.104-2.944-3.392-4.672l-17.408-102.336c-3.84-22.624-23.264-44.8-45.216-51.584 0-0.032-3.008-1.184-12.416-5.088-9.568-3.936-12.512-5.248-13.248-5.568-17.984-9.568-49.344-8.032-67.744 4.992L223.264 739.36c-0.416 0.32-6.176 0.288-6.848-0.224L154.688 677.6320000000001c0 0 0 0 0 0 0.224 0 0.032-4.384 1.056-5.856L216 587.264c13.312-18.752 15.744-47.296 5.76-67.968l-11.52-27.648c-6.976-20.032-29.472-38.944-51.776-42.624L55.968 431.68c-1.824-0.384-4.704-3.648-4.832-5.408l0.096-86.56 0 0c0.096 0 2.912-3.104 4.608-3.424l102.656-17.28c23.04-4 44.704-22.912 51.712-44.928 0.256-0.736 1.44-3.84 5.088-12.64 3.68-8.832 5.024-11.84 5.472-12.736 10.592-20.288 8.672-48.96-4.672-67.904l-60.512-84.768c-0.96-1.408-0.736-5.632 0.384-6.912l61.408-61.184c-0.736 0.8 0.736 0.224 2.816 0.192 1.728 0 2.784 0.416 3.008 0.576l84.992 60.16C318.624 96.32000000000005 333.088 100.60799999999995 347.84 100.60799999999995zM512.032 133.856c-138.336 0-250.848 112.224-250.848 250.176 0 137.92 112.544 250.144 250.848 250.144s250.848-112.224 250.848-250.144C762.88 246.08000000000004 650.336 133.856 512.032 133.856zM512.032 583.136c-110.08 0-199.648-89.312-199.648-199.104s89.568-199.136 199.648-199.136 199.648 89.344 199.648 199.136S622.112 583.136 512.032 583.136z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="template" unicode="&#58979;" d="M734 172.89999999999998v82.8h-59.9v-37l-35.7-9.7 15.7-57.8zM674.1 419.3H734v-81.8h-59.9zM734 600.2l-95.6-26 15.7-57.8 20 5.4v-20.7H734zM866.1 131.29999999999995v-37l-35.7-9.7 7.9-28.9 7.8-28.9 79.9 21.7v82.8h-29.9zM740.9 60.299999999999955L651.4 36l7.9-28.9 7.8-29 89.5 24.4-7.8 28.9zM740.9 781.7l-89.5-24.3 7.9-28.9 7.8-28.9 89.5 24.3-7.8 28.9zM830.4 806l7.9-28.9 7.8-28.9 20 5.5v-20.8H926V832zM866.1 612.6v-120.3H926V612.6h-29.9zM866.1 371.9v-120.3H926V371.9h-29.9zM541.9 665.6l35.7 9.7-7.8 28.9-7.8 28.9-50-13.6L98 832v-783.5l384.1-104.3L512-64l29.9 8.1 35.7 9.7-7.8 28.9-7.8 28.9-20-5.4V120.79999999999995l35.7 9.7-15.7 57.8-20-5.4V486l35.7 9.7-15.7 57.8-20-5.4V665.6z m-59.8-659.4l-324.2 88.1V753.7l324.2-88.1V548l-192 52.2v-427.3l192-52.2v-114.5z m0 360.9V182.79999999999995l-132.2 35.9V521.8l132.2-35.9v-118.8z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="app" unicode="&#58963;" d="M432.022 818.946h-376.324c-6.627 0-12.078-5.45-12.078-12.078v-376.324c0-6.627 5.45-12.078 12.078-12.078h376.324c6.627 0 12.078 5.45 12.078 12.078v376.473c0 6.627-5.45 11.93-12.078 11.93zM391.517 471.196h-295.169v295.169h295.021v-295.169zM976.847 635.717l-211.95 211.95c-8.837 8.837-23.124 8.837-31.963 0l-211.95-211.95c-8.837-8.837-8.837-23.124 0-31.963l211.95-212.098c8.837-8.837 23.124-8.837 31.963 0l211.95 211.95c8.837 8.987 8.837 23.271 0 32.109zM432.022 313.45000000000005h-376.324c-6.627 0-12.078-5.45-12.078-12.078v-376.324c0-6.627 5.45-12.078 12.078-12.078h376.324c6.627 0 12.078 5.45 12.078 12.078v376.473c0 6.627-5.45 11.93-12.078 11.93zM391.517-34.15499999999997h-295.169v295.021h295.021v-295.021zM932.511 313.45000000000005h-376.324c-6.627 0-12.078-5.45-12.078-12.078v-376.324c0-6.627 5.45-12.078 12.078-12.078h376.324c6.627 0 12.078 5.45 12.078 12.078v376.473c0 6.627-5.45 11.93-12.078 11.93zM891.859-34.15499999999997h-295.021v295.021h295.021v-295.021z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="template-1" unicode="&#58966;" d="M512 384zM43.52 601.6l409.6-176.64c58.88-30.72 110.08 0 110.08 0l414.72 174.08 2.56 2.56c10.24 5.12 15.36 15.36 15.36 28.16 0 15.36-10.24 28.16-23.04 30.72L563.2 837.12c-56.32 23.04-97.28 0-97.28 0L46.08 660.48c-12.8-5.12-20.48-17.92-20.48-30.72s7.68-23.04 17.92-28.16z m0 0M512 222.72000000000003c-2.56 0-7.68 0-10.24 2.56l-486.4 215.04c-12.8 5.12-17.92 20.48-12.8 33.28 5.12 12.8 20.48 17.92 33.28 12.8L512 276.48 988.16 486.4c12.8 5.12 28.16 0 33.28-12.8 5.12-12.8 0-28.16-12.8-33.28l-486.4-215.04c-2.56-2.56-7.68-2.56-10.24-2.56zM512 71.67999999999995c-2.56 0-7.68 0-10.24 2.56l-486.4 215.04c-12.8 5.12-17.92 20.48-12.8 33.28 5.12 10.24 20.48 17.92 33.28 10.24L512 125.44000000000005 988.16 332.79999999999995c12.8 5.12 28.16 0 33.28-12.8 5.12-12.8 0-28.16-12.8-33.28l-486.4-215.04H512zM512-79.36000000000001c-2.56 0-7.68 0-10.24 2.56l-486.4 215.04c-12.8 5.12-17.92 20.48-12.8 33.28 5.12 12.8 20.48 17.92 33.28 12.8L512-25.600000000000023l476.16 209.92c12.8 5.12 28.16 0 33.28-12.8 5.12-12.8 0-28.16-12.8-33.28l-486.4-215.04c-2.56-2.56-7.68-2.56-10.24-2.56z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="home" unicode="&#59022;" d="M824.084343-40.42033900000001H232.898863c-74.604138 0-85.85232 28.334325-85.852321 49.997718l-0.584307 5.314029V447.645552h48.806589v-402.916582c0-25.547863 13.548574-36.343743 37.629015-36.343743h568.020898c25.928532 0 27.978215 6.220678 27.978215 37.84391V447.585177l48.806589 0.118704c0.022513-14.346753 0-382.76666 0-433.098999 0-38.130436-12.726859-54.765301-51.858088-54.765301l-1.76111-0.25992zM1012.470921 493.103884C849.773422 615.120868 687.101505 737.137853 524.404006 859.153814c-6.207375 4.659113-18.433838 4.659113-24.641213 0C337.077573 737.137853 174.393377 615.120868 11.696902 493.103884c-24.856108-18.635429-0.572028-61.044308 24.642236-42.13361A15995638.709915 15995638.709915 0 0 1 512.025071 807.737794c0.988514-0.715291 1.644453-1.144056 2.823302-2.037403 18.040888-13.524015 36.057217-27.036773 54.073546-40.560788 58.291614-43.718711 116.583229-87.437421 174.874843-131.143852 81.33647-61.008492 162.696476-122.015961 244.033969-183.024454 25.212218-18.911722 49.496298 23.497157 24.64019 42.132587z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="female" unicode="&#58977;" d="M774.4 800c-48 35.2-108.8 51.2-172.8 51.2-105.6 0-208-51.2-268.8-150.4-89.6-134.4-57.6-313.6 60.8-416l-32-51.2-188.8 121.6S128 384 108.8 352c-22.4-35.2 22.4-64 22.4-64l188.8-121.6-105.6-163.2s-19.2-32 16-51.2c38.4-22.4 57.6 12.8 57.6 12.8l102.4 160 185.6-121.6s48-28.8 70.4 6.4c19.2 28.8-25.6 57.6-25.6 57.6L432 192l32 48c44.8-22.4 92.8-32 137.6-32 105.6 0 208 51.2 268.8 150.4 96 147.2 51.2 345.6-96 441.6z m35.2-400c-44.8-67.2-118.4-108.8-201.6-108.8-44.8 0-92.8 12.8-131.2 38.4-112 73.6-147.2 220.8-73.6 332.8 44.8 64 121.6 105.6 201.6 108.8 44.8 0 92.8-12.8 131.2-38.4 112-73.6 147.2-220.8 73.6-332.8z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="male" unicode="&#58978;" d="M889.6 800h-240s-35.2 0-38.4-41.6c0-19.2 16-38.4 38.4-38.4h140.8l-179.2-179.2C556.8 582.4 489.6 608 416 608 240 608 96 464 96 288s144-320 320-320 320 144 320 320c0 73.6-25.6 140.8-67.2 195.2l179.2 179.2v-140.8c0-22.4 19.2-38.4 38.4-38.4 22.4 0 38.4 19.2 38.4 41.6V764.8h3.2C924.8 800 889.6 800 889.6 800zM416 48c-131.2 0-236.8 105.6-236.8 236.8 0 131.2 105.6 236.8 236.8 236.8s236.8-105.6 236.8-236.8c0-131.2-105.6-236.8-236.8-236.8z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="tread" unicode="&#59077;" d="M860.8 172.79999999999995l6.4-57.6-6.4 57.6c12.8 0 25.6 3.2 35.2 12.8 6.4 9.6 6.4 22.4 3.2 32l57.6 12.8-57.6-12.8L800 553.6c-6.4 28.8-25.6 51.2-48 64-9.6 6.4-22.4 9.6-32 9.6H182.4c-22.4 3.2-41.6-6.4-51.2-25.6-6.4-9.6-6.4-19.2-9.6-28.8v-342.4c0-19.2 9.6-38.4 28.8-48 6.4-3.2 12.8-6.4 19.2-6.4h192l19.2-25.6 147.2-188.8c6.4-9.6 19.2-12.8 28.8-9.6 16 3.2 25.6 19.2 22.4 35.2l-9.6 118.4-6.4 67.2h297.6z m-233.6-57.6l9.6-128c3.2-28.8-9.6-54.4-28.8-73.6-35.2-32-92.8-28.8-124.8 6.4l-156.8 195.2H179.2c-19.2 0-38.4 6.4-57.6 16-35.2 19.2-57.6 57.6-57.6 99.2V572.8c0 19.2 6.4 38.4 16 57.6 19.2 38.4 57.6 60.8 99.2 54.4h537.6c67.2-3.2 121.6-48 137.6-112l102.4-339.2c6.4-28.8 3.2-57.6-12.8-80-19.2-22.4-48-38.4-76.8-38.4h-240zM304 627.2v-451.2h57.6V627.2H304z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="praise" unicode="&#59078;" d="M860.8 595.2h-297.6l6.4 67.2 9.6 118.4c3.2 16-6.4 32-22.4 35.2-9.6 3.2-22.4 0-28.8-9.6l-147.2-188.8-19.2-25.6h-192c-6.4 0-12.8-3.2-19.2-6.4-19.2-9.6-28.8-28.8-28.8-48v-342.4c0-9.6 3.2-22.4 9.6-28.8 9.6-19.2 28.8-28.8 48-25.6h537.6c12.8 0 22.4 3.2 32 9.6 25.6 12.8 44.8 35.2 48 64l102.4 336 57.6-12.8-57.6 12.8c3.2 9.6 0 22.4-3.2 32-9.6 6.4-22.4 12.8-35.2 12.8l6.4 57.6-6.4-57.6z m-233.6 57.6h240c28.8 0 57.6-12.8 76.8-38.4 16-22.4 19.2-54.4 12.8-80l-102.4-339.2c-16-64-70.4-108.8-137.6-112H179.2c-41.6-3.2-80 19.2-99.2 54.4-9.6 19.2-16 38.4-16 57.6V537.6c0 41.6 22.4 80 57.6 99.2 19.2 9.6 38.4 12.8 57.6 16h144L480 848c32 35.2 89.6 38.4 124.8 6.4 19.2-19.2 32-44.8 28.8-73.6l-6.4-128z m-323.2-512h57.6V592H304v-451.2z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="rmb" unicode="&#58974;" d="M511.998465 896C229.23338 896 0.004605 666.769178 0.004605 384.001023c0-282.773272 229.227752-512.001023 511.99386-512.001023 282.769178 0 511.994883 229.227752 511.994883 512.001023C1023.994372 666.769178 794.767644 896 511.998465 896zM511.998465-91.59690499999999c-262.660188 0-475.589742 212.930577-475.589742 475.597929 0 262.663258 212.929554 475.594859 475.589742 475.594859 262.663258 0 475.590765-212.9316 475.590765-475.594859C987.590254 121.33469500000001 774.662747-91.59690499999999 511.998465-91.59690499999999zM738.742652 301.137781L544.432155 301.137781l0 69.780273 194.310497 0c17.835204 0 32.249495 14.43885 32.249495 32.220842 0 17.784038-14.414291 32.19526-32.249495 32.19526L589.7462 435.334155l149.620669 209.579249c8.916067 15.397688 3.63069 35.099403-11.82021 43.988864-15.398712 8.891508-35.097356 3.629667-44.017516-11.793604L512.187777 437.098335 340.84334 677.108664c-8.864902 15.423271-28.617781 20.685111-44.016493 11.793604-15.395642-8.889461-20.685111-28.590152-11.82021-43.988864l149.622716-209.579249L285.628808 435.334155c-17.781992 0-32.245402-14.411221-32.245402-32.19526 0-17.781992 14.46341-32.220842 32.245402-32.220842l194.310497 0 0-69.780273L285.628808 301.137781c-17.781992 0-32.245402-14.413268-32.245402-32.19526s14.46341-32.220842 32.245402-32.220842l194.310497 0 0-132.435265c0-17.780969 14.46341-32.19526 32.248472-32.19526 17.835204 0 32.245402 14.414291 32.245402 32.19526L544.433178 236.72065499999997l194.310497 0c17.835204 0 32.249495 14.43885 32.249495 32.220842S756.577856 301.137781 738.742652 301.137781"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="more" unicode="&#58975;" d="M224 288c-52.928 0-96 43.072-96 96s43.072 96 96 96 96-43.072 96-96-43.072-96-96-96z m288 0c-52.928 0-96 43.072-96 96s43.072 96 96 96 96-43.072 96-96-43.072-96-96-96z m288 0c-52.928 0-96 43.072-96 96s43.072 96 96 96 96-43.072 96-96-43.072-96-96-96z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="camera" unicode="&#58976;" d="M884.3 648.6H704.2L679.5 698l-0.2 0.4c-1.9 3.6-3.6 6.9-5.1 9.9-12 23.4-21.5 41.9-54.1 41.9H416.7c-32.9 0-43.7-21.3-55.1-43.8-1.3-2.6-2.7-5.3-4.2-8.1l-24.8-49.7H152.4c-34 0-61.7-27.7-61.7-61.7v-488c0-34 27.7-61.7 61.7-61.7h731.9c34 0 61.7 27.7 61.7 61.7v488c0 34-27.7 61.7-61.7 61.7zM904 98.89999999999998c0-10.8-8.8-19.7-19.7-19.7H152.4c-10.8 0-19.7 8.8-19.7 19.7v488c0 10.8 8.8 19.7 19.7 19.7h206.1l36.2 72.5c1.5 2.9 2.9 5.7 4.3 8.3 10.6 20.8 11.1 20.8 17.7 20.8H620c4.6 0 5.8-0.6 5.8-0.6 2-1.2 7.2-11.2 10.9-18.5 1.6-3.1 3.3-6.5 5.3-10.1l36.2-72.4h206.1c10.8 0 19.7-8.8 19.7-19.7v-488zM525.5 565.5c-123.5 0-223.6-100.1-223.6-223.6S402 118.20000000000005 525.5 118.20000000000005s223.7 100.1 223.7 223.7c0 123.5-100.2 223.6-223.7 223.6z m0-402.5c-98.8 0-178.9 80.1-178.9 178.9 0 98.8 80.1 178.9 178.9 178.9 98.8 0 178.9-80.1 178.9-178.9 0-98.8-80.1-178.9-178.9-178.9z m246 402.5v-44.7H861v44.7h-89.5z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="cart-simple" unicode="&#59032;" d="M235.097303 196.866982C247.384597 160.417152 286.382106 132.37606800000003 324.772759 132.37606800000003L861.658537 132.37606800000003 880.429732 132.37606800000003 885.649214 150.54185399999994 1009.08775 580.154957C1021.388907 622.967661 993.187631 660.786325 949.051586 660.786325L424.585365 660.786325C410.791718 660.786325 399.609756 649.5207379999999 399.609756 635.623932 399.609756 621.727125 410.791718 610.461538 424.585365 610.461538L949.051586 610.461538C959.924 610.461538 964.161052 604.779539 961.106394 594.148171L837.667859 164.53506800000002 861.658537 182.70085500000005 324.772759 182.70085500000005C307.742153 182.70085500000005 287.789837 197.04752900000005 282.395194 213.05054900000005L73.600164 832.433664C69.16437 845.592294 54.980454 852.636656 41.919502 848.167687 28.858551 843.698719 21.86648 829.408727 26.302275 816.250097L235.097303 196.866982ZM399.609756-6.017094000000043C399.609756 49.57012899999995 354.881911 94.63247799999999 299.707317 94.63247799999999 244.532723 94.63247799999999 199.804878 49.57012899999995 199.804878-6.017094000000043 199.804878-61.604318000000035 244.532723-106.66666699999996 299.707317-106.66666699999996 354.881911-106.66666699999996 399.609756-61.604318000000035 399.609756-6.017094000000043ZM249.756098-6.017094000000043C249.756098 21.77651800000001 272.120021 44.30769299999997 299.707317 44.30769299999997 327.294613 44.30769299999997 349.658537 21.77651800000001 349.658537-6.017094000000043 349.658537-33.810704999999984 327.294613-56.34187899999995 299.707317-56.34187899999995 272.120021-56.34187899999995 249.756098-33.810704999999984 249.756098-6.017094000000043ZM924.097562-6.017094000000043C924.097562 49.57012899999995 879.369715 94.63247799999999 824.195121 94.63247799999999 769.020529 94.63247799999999 724.292683 49.57012899999995 724.292683-6.017094000000043 724.292683-61.604318000000035 769.020529-106.66666699999996 824.195121-106.66666699999996 879.369715-106.66666699999996 924.097562-61.604318000000035 924.097562-6.017094000000043ZM774.243902-6.017094000000043C774.243902 21.77651800000001 796.607825 44.30769299999997 824.195121 44.30769299999997 851.782419 44.30769299999997 874.146342 21.77651800000001 874.146342-6.017094000000043 874.146342-33.810704999999984 851.782419-56.34187899999995 824.195121-56.34187899999995 796.607825-56.34187899999995 774.243902-33.810704999999984 774.243902-6.017094000000043Z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="face-cry" unicode="&#59036;" d="M1024 384C1024 666.769792 794.769792 896 512 896 229.230208 896 0 666.769792 0 384 0 101.23020799999995 229.230208-128 512-128 629.410831-128 740.826187-88.33104600000001 830.768465-16.686661999999956 841.557579-8.092490999999995 843.33693 7.620766000000003 834.742758 18.409879000000046 826.148587 29.198990999999978 810.43533 30.978341999999998 799.646219 22.384173000000033 718.470035-42.277495000000044 618.001779-78.04878099999996 512-78.04878099999996 256.817504-78.04878099999996 49.951219 128.81750399999999 49.951219 384 49.951219 639.182496 256.817504 846.048781 512 846.048781 767.182496 846.048781 974.048781 639.182496 974.048781 384 974.048781 296.507166 949.714859 212.66323599999998 904.470807 140.039307 897.177109 128.33175700000004 900.755245 112.92820300000005 912.462793 105.63450699999999 924.170342 98.34080900000004 939.573897 101.91894200000002 946.867595 113.62649199999998 997.013826 194.11920399999997 1024 287.101621 1024 384ZM337.170731 396.487806C371.654852 396.487806 399.609756 424.442709 399.609756 458.926829 399.609756 493.41095 371.654852 521.365854 337.170731 521.365854 302.686611 521.365854 274.731708 493.41095 274.731708 458.926829 274.731708 424.442709 302.686611 396.487806 337.170731 396.487806ZM711.804879 396.487806C746.288998 396.487806 774.243902 424.442709 774.243902 458.926829 774.243902 493.41095 746.288998 521.365854 711.804879 521.365854 677.320757 521.365854 649.365854 493.41095 649.365854 458.926829 649.365854 424.442709 677.320757 396.487806 711.804879 396.487806ZM352.788105 191.21547499999997C396.165222 225.91716899999994 453.151987 246.639629 524.487806 246.639629 595.823622 246.639629 652.810387 225.91716899999994 696.187505 191.21547499999997 722.700531 170.00505399999997 738.882517 148.42907300000002 746.631548 132.931012 752.800254 120.59359800000004 747.799529 105.59142399999996 735.462114 99.42271600000004 723.124702 93.25401 708.122526 98.25473499999998 701.953818 110.59214899999995 701.03616 112.42746499999998 698.492224 116.61747600000001 694.165854 122.38597100000004 686.602473 132.47047699999996 676.927317 142.654852 664.983226 152.21012499999995 630.311565 179.947456 584.273939 196.68840999999998 524.487806 196.68840999999998 464.70167 196.68840999999998 418.664045 179.947456 383.992384 152.21012499999995 372.048292 142.654852 362.373137 132.47047699999996 354.809756 122.38597100000004 350.483386 116.61747600000001 347.93945 112.42746499999998 347.021792 110.59214899999995 340.853084 98.25473499999998 325.850908 93.25401 313.513495 99.42271600000004 301.176081 105.59142399999996 296.175356 120.59359800000004 302.344062 132.931012 310.093092 148.42907300000002 326.275078 170.00505399999997 352.788105 191.21547499999997Z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="face-smile" unicode="&#59055;" d="M1024 384C1024 666.769792 794.769792 896 512 896 229.230208 896 0 666.769792 0 384 0 101.23020799999995 229.230208-128 512-128 629.410831-128 740.826187-88.33104600000001 830.768465-16.686661999999956 841.557579-8.092490999999995 843.33693 7.620766000000003 834.742758 18.409879000000046 826.148587 29.198990999999978 810.43533 30.978341999999998 799.646219 22.384173000000033 718.470035-42.277495000000044 618.001779-78.04878099999996 512-78.04878099999996 256.817504-78.04878099999996 49.951219 128.81750399999999 49.951219 384 49.951219 639.182496 256.817504 846.048781 512 846.048781 767.182496 846.048781 974.048781 639.182496 974.048781 384 974.048781 296.507166 949.714859 212.66323599999998 904.470807 140.039307 897.177109 128.33175700000004 900.755245 112.92820300000005 912.462793 105.63450699999999 924.170342 98.34080900000004 939.573897 101.91894200000002 946.867595 113.62649199999998 997.013826 194.11920399999997 1024 287.101621 1024 384ZM337.170731 396.487806C371.654852 396.487806 399.609756 424.442709 399.609756 458.926829 399.609756 493.41095 371.654852 521.365854 337.170731 521.365854 302.686611 521.365854 274.731708 493.41095 274.731708 458.926829 274.731708 424.442709 302.686611 396.487806 337.170731 396.487806ZM711.804879 396.487806C746.288998 396.487806 774.243902 424.442709 774.243902 458.926829 774.243902 493.41095 746.288998 521.365854 711.804879 521.365854 677.320757 521.365854 649.365854 493.41095 649.365854 458.926829 649.365854 424.442709 677.320757 396.487806 711.804879 396.487806ZM352.788105 127.22903299999996C396.165222 92.52733899999998 453.151987 71.80487900000003 524.487806 71.80487900000003 595.823622 71.80487900000003 652.810387 92.52733899999998 696.187505 127.22903299999996 722.700531 148.43945399999996 738.882517 170.01543500000002 746.631548 185.51349500000003 752.800254 197.850908 747.799529 212.85308399999997 735.462114 219.021792 723.124702 225.19049800000005 708.122526 220.18977299999995 701.953818 207.85235799999998 701.03616 206.01704299999994 698.492224 201.82703100000003 694.165854 196.058537 686.602473 185.97402899999997 676.927317 175.78965500000004 664.983226 166.23438299999998 630.311565 138.49705200000005 584.273939 121.75609799999995 524.487806 121.75609799999995 464.70167 121.75609799999995 418.664045 138.49705200000005 383.992384 166.23438299999998 372.048292 175.78965500000004 362.373137 185.97402899999997 354.809756 196.058537 350.483386 201.82703100000003 347.93945 206.01704299999994 347.021792 207.85235799999998 340.853084 220.18977299999995 325.850908 225.19049800000005 313.513495 219.021792 301.176081 212.85308399999997 296.175356 197.850908 302.344062 185.51349500000003 310.093092 170.01543500000002 326.275078 148.43945399999996 352.788105 127.22903299999996Z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="survey" unicode="&#59058;" d="M722.355804 849.454545C761.006291 849.454545 792.380951 818.166023 792.380951 779.627344L792.380951 437.500928 799.081094 453.813218 401.874746 51.22138 418.539682 58.181818 138.070006 58.181818C99.387643 58.181818 68.063492 89.328555 68.063492 127.771428L68.063492 872.727273 44.698413 849.454545 722.355804 849.454545ZM21.333333 896 21.333333 872.727273 21.333333 127.771428C21.333333 63.604277 73.59726 11.636363 138.070006 11.636363L418.539682 11.636363 428.337293 11.636363 435.204619 18.596802 832.410967 421.18864 839.11111 427.979625 839.11111 437.500928 839.11111 779.627344C839.11111 843.859757 786.827324 896 722.355804 896L44.698413 896 21.333333 896ZM775.859347 307.365395 759.337741 290.90909 775.859347 274.452787 869.319663 181.361879 885.841269 164.905574 902.362876 181.361879 972.458114 251.18006 988.979721 267.636363 972.458114 284.092668 878.997796 377.183575 862.47619 393.639878 845.954583 377.183575 775.859347 307.365395ZM845.954583 344.27097 939.414901 251.18006 939.414901 284.092668 869.319663 214.274485 902.362876 214.274485 808.902558 307.365395 808.902558 274.452787 878.997796 344.27097 845.954583 344.27097ZM518.843473 51.365395 513.841133 46.382827 512.453734 39.473248 489.088655-76.890387 482.215251-111.121568 516.58227-104.275332 633.407665-81.002605 640.344663-79.620689 645.347004-74.638121 902.362876 181.361879 918.884482 197.818182 902.362876 214.274485 808.902558 307.365395 792.380951 323.821698 775.859347 307.365395 518.843473 51.365395ZM775.859347 274.452787 869.319663 181.361879 869.319663 214.274485 612.303791-41.725515 624.243127-35.361033 507.41773-58.633758 534.911345-86.018703 558.276425 30.344934 551.886686 18.452787 808.902558 274.452787 775.859347 274.452787ZM426.576706 298.269073C444.201086 298.269073 458.488469 284.053815 458.488469 266.500753L458.488469 258.086116C458.488469 240.540958 444.323959 226.317797 426.576706 226.317797L426.576706 226.317797C408.952326 226.317797 394.664943 240.533054 394.664943 258.086116L394.664943 266.500753C394.664943 284.045911 408.829453 298.269073 426.576706 298.269073L426.576706 298.269073ZM278.349205 552.435127C278.349205 552.435127 280.851125 530.485568 305.477133 530.485568 330.103138 530.485568 331.559155 552.435127 331.559155 552.435127 329.927383 623.508937 362.988497 657.25782 430.67155 653.905282 475.722639 648.839223 499.06407 623.508937 500.624896 577.839917 497.503245 557.501184 480.405116 531.202385 449.969026 499.092521 409.671358 458.489557 389.522524 422.133143 389.522524 390.023279L389.522524 357.093903C389.522524 357.093903 392.614705 337.454532 414.885933 337.454532 437.157161 337.454532 440.249342 357.093903 440.249342 357.093903L440.249342 379.965664C440.249342 406.785969 459.546816 439.044836 498.21271 476.369762 538.652271 513.471183 558.730159 547.369069 558.730159 577.839917 555.395669 662.323878 511.195938 706.353877 425.776235 709.780917 327.515198 711.419936 278.349205 658.971339 278.349205 552.435127Z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="read" unicode="&#59141;" d="M335.282306 712.495464C399.587328 713.451107 442.778899 696.882717 470.183494 669.3706540000001 479.127332 660.39174 485.691302 650.857363 490.241971 641.442689 492.795622 636.159553 494.049041 632.438701 494.358795 631.0740940000001L493.723712 636.7409230000001 493.723706 196.90019600000005C493.723706 199.018106 495.816045 203.920655 503.591595 207.36436700000002 511.039185 210.66283299999998 515.68422 209.16527399999995 517.176538 207.906613L500.671543 188.33763 521.297207 203.50146800000005C514.140179 213.23636899999997 499.631258 225.71450900000002 476.134074 237.35914000000002 439.577969 255.475456 390.86048 266.10507900000005 328.491925 266.10508200000004 265.860796 266.10508200000004 219.424582 255.71817999999996 186.827162 237.741581 164.977332 225.69198700000004 152.538132 212.28117299999997 147.220271 201.30886999999996L170.257196 190.14374199999997 151.035786 207.05224299999998C152.884078 209.15336100000002 158.307299 211.80336599999998 167.849005 208.050434 177.092077 204.41496099999995 179.2 199.20011699999998 179.2 196.66445199999998L179.2 497.049743 179.2 636.7409230000001 175.817447 624.023021C177.078908 626.226721 180.088681 630.807811 184.828724 636.965629 192.95423 647.521524 202.792594 658.127492 214.297641 668.007961 247.526453 696.544681 287.381649 713.209056 334.514421 712.495571L335.282306 712.495464ZM335.289387 763.689705C274.661039 764.607483 223.081402 743.04085 180.940156 706.850184 156.32698 685.712527 139.975514 664.470237 131.382553 649.4588249999999L128 643.549699 128 636.7409230000001 128 497.049743 128 196.66445199999998C128 159.26104999999995 164.542545 144.88818300000003 189.478606 173.23524099999997L191.776657 175.84764199999995 193.294121 178.978613C194.07832 180.59664399999997 199.156367 186.07133399999998 211.552092 192.907243 236.030601 206.40648099999999 274.024879 214.905082 328.491925 214.905082 383.221547 214.905079 424.163878 205.97190999999998 453.399258 191.483569 469.376966 183.56540600000005 477.614626 176.48075300000005 480.045882 173.17379000000005L481.844905 170.72677999999996 484.166551 168.768644C511.279708 145.90070000000003 544.923706 160.801293 544.923706 196.90019600000005L544.923712 636.740922 544.288627 642.407751C540.427211 659.419023 529.175531 682.697124 506.45814 705.503602 468.987716 743.1209699999999 412.352271 764.846461 334.521502 763.689812L335.289387 763.689705ZM0 506.026694L0 27.856867999999963C0-8.875636999999983 34.793167-23.40043300000002 61.4635 1.2485080000000153L63.46242 3.315859000000046C65.301149 5.444836000000009 69.655573 9.862312999999972 76.498228 15.820363000000043 88.306297 26.101906999999983 102.566352 36.46294 119.251411 46.17438500000003 167.295691 74.13829099999998 224.90855 90.95018200000004 292.337329 90.95018200000004 358.378978 90.95018000000005 409.459345 71.66956600000003 448.125308 39.64774 461.506042 28.56627400000002 472.380655 16.734758000000056 480.912593 4.997000999999955 485.832384-1.7713730000000396 488.762874-6.741985999999997 489.872527-9.02252199999998 496.058545-21.73590200000001 511.379537-27.027375000000006 524.092917-20.84135500000002 536.806298-14.655337000000031 542.097771 0.6656550000000152 535.91175 13.379036000000042 527.471002 30.726293000000055 509.777717 55.06771800000001 480.782336 79.08069999999998 433.134118 118.54132300000003 370.586889 142.15017999999998 292.337329 142.15018199999997 215.474895 142.15018499999996 149.074727 122.77408400000002 93.495781 90.424668 59.761154 70.78961500000003 36.872315 50.859801999999945 24.713677 36.78188399999999L44.088049 20.048869999999965 26.712598 38.84923500000002C28.162783 40.189508000000046 32.877261 41.946117999999956 40.792576 38.64178100000004 49.035365 35.200736000000006 51.2 30.12989200000004 51.2 27.856867999999963L51.2 506.026694C51.2 520.165184 39.73849 531.626694 25.6 531.626694 11.46151 531.626694 0 520.165184 0 506.026694L0 506.026694ZM696.80221 763.689812C618.971441 764.846461 562.335996 743.1209699999999 524.86557 705.503602 502.148181 682.697124 490.896501 659.419023 487.035083 642.407751L486.4 636.740922 486.400004 196.90019600000005C486.400006 160.801293 520.044004 145.90070000000003 547.157161 168.768644L549.478807 170.72677999999996 551.27783 173.17379000000005C553.709086 176.48075300000005 561.946746 183.56540600000005 577.924452 191.483569 607.159834 205.97190999999998 648.102165 214.905079 702.831787 214.905082 757.298833 214.905082 795.293111 206.40648099999999 819.77162 192.907243 832.167345 186.07133399999998 837.245391 180.59664399999997 838.029591 178.978613L839.547055 175.84764199999995 841.845105 173.23524099999997C866.781167 144.88818300000003 903.323712 159.26104999999995 903.323712 196.66445199999998L903.323712 497.049743 903.323712 636.7409230000001 903.323712 643.549699 899.941158 649.4588249999999C891.348196 664.470237 874.996732 685.712527 850.383556 706.850184 808.24231 743.04085 756.662673 764.607483 696.034325 763.689705L696.80221 763.689812ZM696.809291 712.495571C743.942063 713.209056 783.797257 696.544681 817.026071 668.007961 828.531119 658.127492 838.369481 647.521524 846.494989 636.965629 851.235031 630.807811 854.244804 626.226721 855.506263 624.023021L852.123712 636.7409230000001 852.123712 497.049743 852.123712 196.66445199999998C852.123712 199.20011699999998 854.231635 204.41496099999995 863.474707 208.050434 873.016412 211.80336599999998 878.439633 209.15336100000002 880.287925 207.05224299999998L861.066515 190.14374199999997 884.103441 201.30886999999996C878.785579 212.28117299999997 866.346381 225.69198700000004 844.49655 237.741581 811.89913 255.71817999999996 765.462916 266.10508200000004 702.831785 266.10508200000004 640.463232 266.10507900000005 591.745741 255.475456 555.189638 237.35914000000002 531.692454 225.71450900000002 517.183533 213.23636899999997 510.026502 203.50146800000005L530.652166 188.33763 514.147172 207.906613C515.63949 209.16527399999995 520.284527 210.66283299999998 527.732117 207.36436700000002 535.507665 203.920655 537.600004 199.018106 537.600004 196.90019600000005L537.6 636.7409230000001 536.964917 631.0740940000001C537.274671 632.438701 538.52809 636.159553 541.081741 641.442689 545.63241 650.857363 552.196378 660.39174 561.140218 669.3706540000001 588.544813 696.882717 631.736384 713.451107 696.041406 712.495464L696.809291 712.495571ZM972.799998 506.026694L972.799998 27.856867999999963C972.799998 30.12989200000004 974.964631 35.200736000000006 983.207422 38.64178100000004 991.122737 41.946117999999956 995.837214 40.189508000000046 997.287401 38.84923500000002L979.911949 20.048869999999965 999.286321 36.78188399999999C987.127682 50.859801999999945 964.238844 70.78961500000003 930.504218 90.424668 874.925269 122.77408400000002 808.525103 142.15018499999996 731.662669 142.15018199999997 653.132708 142.15017999999998 590.55104 117.26282200000003 543.127755 75.73800100000005 514.370099 50.55719499999998 496.945662 25.10259599999995 488.705389 7.022771000000034 482.841769-5.842485000000011 488.517717-21.02524200000005 501.382974-26.888862000000017 514.248233-32.752481999999986 529.430987-27.07653300000004 535.294607-14.211275 536.420563-11.740835999999945 539.350332-6.450639000000024 544.25735 0.7178109999999833 552.731727 13.097653000000037 563.54464 25.561581000000047 576.856734 37.21792900000003 615.190044 70.78337499999998 665.901421 90.95018000000005 731.662669 90.95018200000004 799.091447 90.95018200000004 856.704307 74.13829099999998 904.748587 46.17438500000003 921.433645 36.46294 935.6937 26.101906999999983 947.501771 15.820363000000043 954.344425 9.862312999999972 958.698848 5.444836000000009 960.537577 3.315859000000046L962.536497 1.2485080000000153C989.206831-23.40043300000002 1023.999998-8.875636999999983 1023.999998 27.856867999999963L1023.999998 506.026694C1023.999998 520.165184 1012.538487 531.626694 998.399998 531.626694 984.261508 531.626694 972.799998 520.165184 972.799998 506.026694L972.799998 506.026694Z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="location" unicode="&#59157;" d="M451.673935-98.39569900000004C478.883834-129.01914699999998 524.254807-128.8089789999999 551.400292-97.92885100000001 553.755808-95.38790800000004 558.821323-89.79676199999994 565.872444-81.84834999999998 577.572838-68.65901699999995 590.597131-53.62432000000001 604.615947-36.99831500000005 644.662065 10.495494000000008 684.708678 61.282182000000034 722.129538 113.35355300000003 759.658524 165.575381 792.492213 216.29072599999995 819.314991 264.54153799999995 868.685946 353.35368300000005 896 430.456574 896 493.714285 896 715.890551 719.301715 896 501.333333 896 283.364952 896 106.666667 715.890551 106.666667 493.714285 106.666667 430.401284 134.05152 353.19426999999996 183.54613 264.23737800000004 210.371803 216.02347099999997 243.193308 165.34812399999998 280.699364 113.16684599999996 318.155192 61.05544999999995 358.239268 10.22578999999996 398.322835-37.31103099999996 412.354743-53.95207300000004 425.391185-69.00072999999998 437.102468-82.20257900000001 444.160087-90.15846599999998 449.230214-95.75492099999997 451.982775-98.73670600000003L451.673935-98.39569900000004ZM486.822684-65.32134799999994C484.281231-62.568254000000024 479.425084-57.207989 472.585916-49.49835900000005 461.135889-36.591016999999965 448.364015-21.84776099999999 434.602351-5.527214999999956 395.275714 41.11192700000004 355.949587 90.98045200000001 319.289224 141.985137 282.808749 192.739548 250.983685 241.87642200000005 225.158316 288.29247799999996 179.388826 370.55419500000005 154.50505 440.709839 154.50505 493.714285 154.50505 688.960095 309.785362 847.238095 501.333333 847.238095 692.881306 847.238095 848.161617 688.960095 848.161617 493.714285 848.161617 440.753978 823.345286 370.701737 777.693969 288.58074899999997 751.873483 242.13293399999998 720.038415 192.96007499999996 683.537446 142.16873799999996 646.912604 91.20503299999996 607.624538 41.38032599999997 568.335977-5.21503800000005 554.587654-21.52024300000005 541.828177-36.24924999999996 530.389289-49.14379699999995 523.556841-56.84571100000005 518.705521-62.20043499999997 516.166694-64.95052599999997 507.543772-74.74891100000002 495.255793-74.80583000000001 487.131524-65.66235300000005L486.822684-65.32134799999994ZM714.955981 428.971194C723.919106 453.372045 728.565658 479.331002 728.565658 505.904762 728.565658 627.091817 632.184774 725.333333 513.29293 725.333333 394.401086 725.333333 298.020202 627.091817 298.020202 505.904762 298.020202 384.717709 394.401086 286.47619 513.29293 286.47619 549.003859 286.47619 583.510052 295.36805300000003 614.373097 312.125591 626.032316 318.456132 630.449257 333.22218 624.238611 345.10648100000003 618.027966 356.99078199999997 603.541579 361.49299399999995 591.882359 355.16245100000003 567.900883 342.14136099999996 541.111735 335.23809500000004 513.29293 335.23809500000004 420.821495 335.23809500000004 345.858586 411.648164 345.858586 505.904762 345.858586 600.161359 420.821495 676.571428 513.29293 676.571428 605.764365 676.571428 680.727273 600.161359 680.727273 505.904762 680.727273 485.192019 677.117041 465.022684 670.154965 446.069408 665.522846 433.459117 671.796821 419.408892 684.168282 414.687349 696.53974 409.965809 710.323861 416.360905 714.955981 428.971194L714.955981 428.971194Z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="dollar" unicode="&#58969;" d="M517.565-65.45399999999995c-244.263 0-442.299 198.014-442.299 442.299s198.014 442.299 442.299 442.299c244.263 0 442.299-198.014 442.299-442.299 0-244.263-198.014-442.299-442.299-442.299zM517.565 863.383c-268.751 0-486.564-217.834-486.564-486.564s217.834-486.564 486.564-486.564c268.751 0 486.564 217.834 486.564 486.564 0 268.751-217.834 486.564-486.564 486.564zM497.036 425.349c-18.443 6.957-33.605 16.314-45.238 27.617-11.581 11.306-20.059 23.465-25.468 36.742-5.423 13.177-8.178 26.235-8.178 39.172-0.004 18.194 2.564 34.357 7.846 48.514 5.327 14.231 13.748 25.85 25.468 35.02 11.581 9.167 26.798 15.204 45.482 18.295v-205.52zM534.455 356.13199999999995c16.937-6.756 32.277-14.997 46.035-24.855 13.748-9.678 24.613-21.601 32.929-35.57 8.204-13.909 12.436-30.734 12.622-50.307 0-14.231-1.859-27.907-5.785-40.833-3.858-12.866-9.542-24.531-17.271-34.804-7.691-10.211-17.271-18.443-28.678-24.613-11.328-6.318-24.613-9.678-39.76-10.341v221.377zM534.455 94.18299999999999c29.037 3.318 53.978 11.306 74.785 24.134 20.985 12.866 37.018 30.15 48.281 51.734 11.125 21.535 16.876 46.832 16.937 76.196 0 16.08-1.67 30.377-5.033 42.985-3.318 12.622-8.204 24.15-14.836 34.357-6.739 10.341-14.836 20.189-24.613 29.326-8.853 8.204-19.107 15.957-30.659 23.041-11.328 7.197-22.836 13.706-34.281 19.261-11.581 5.694-21.601 10.516-30.659 14.231v221.377c14.527-3.318 26.662-8.594 36.62-16.192 9.859-7.395 17.766-16.192 23.776-26.384 5.941-10.211 10.341-20.985 12.972-32.345 2.666-11.328 4.026-22.836 3.858-34.097h46.155c0.004 16.314-1.566 32.345-5.327 48.281-3.543 15.957-9.938 30.909-19.107 44.969-8.996 13.909-21.601 26.235-37.684 36.742-16.192 10.521-36.62 18.295-61.318 23.562v49.426h-37.441v-53.316c-23.465-2.624-42.985-8.178-58.595-16.314-15.633-8.204-28.279-18.194-37.684-29.562-9.441-11.328-16.523-23.302-21.226-35.317-4.59-12.062-7.846-23.302-9.316-33.326-1.566-10.211-2.256-18.194-2.115-24.029 0.004-21.601 3.452-40.612 9.863-57.238 6.479-16.523 15.58-30.909 27.178-43.441 11.659-12.436 25.361-23.562 40.833-33.204 15.633-9.678 32.649-18.443 51.098-26.235v-237.329c-18.194 1.984-33.326 7.197-45.094 15.633-11.97 8.369-21.074 19.107-27.714 31.902-6.739 12.972-11.011 27.178-13.363 42.701-2.256 15.58-3.034 31.313-2.115 47.367h-47.803c-1.183-23.776 0.397-46.035 5.033-66.676s12.357-39.03 23.376-55.019c10.892-16.08 25.361-29.037 43.142-39.03 17.847-9.863 39.472-16.08 64.586-18.295v-65.283h37.441v65.283z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="diamond" unicode="&#59189;" d="M998.4 526.933333L797.866667 802.133333c-4.266667 6.4-12.8 10.666667-19.2 10.666667L243.2 812.8c0 0-14.933333-2.133333-23.466667-17.066667C194.133333 753.066667 32 512 32 512L21.333333 494.933333l12.8-14.933333L469.333333-27.733333000000016c4.266667-4.266667 6.4-6.4 10.666667-8.533333 6.4-4.266667 32-10.666667 46.933333 0 4.266667 2.133333 6.4 6.4 10.666667 8.533333l409.6 420.266667c10.666667 8.533333 10.666667 25.6 0 34.133333-8.533333 10.666667-23.466667 10.666667-32 0L561.066667 61.86666700000001l153.6 422.4 0 0 251.733333 0c2.133333 0 19.2 0 23.466667 4.266667l2.133333 2.133333C1004.8 497.066667 1006.933333 512 998.4 526.933333zM782.933333 763.733333l-96-226.133333L341.333333 537.6l-85.333333 226.133333L782.933333 763.733333zM221.866667 714.666667l72.533333-179.2-192 0L221.866667 714.666667zM91.733333 488.533333l215.466667 0 138.666667-416L91.733333 488.533333zM503.466667 44.799999999999955l-147.2 443.733333 307.2 0L503.466667 44.799999999999955zM736 535.4666669999999L810.666667 701.866667l119.466667-168.533333L736 533.333333z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="return" unicode="&#58972;" d="M927.858848 417.938973L168.863431 417.938973l308.721247 308.86758c11.685133 11.69025 11.435447 30.881334-0.557702 42.868343-11.992125 11.985986-31.18321 12.226462-42.868343 0.536212L75.199191 411.071565c-1.994424-1.662873-3.773953-3.583618-5.294586-5.713119-4.047176-5.373381-6.013971-11.839653-5.9055-18.328437-0.12996-7.794523 2.725064-15.561417 8.595772-21.432125l361.565802-361.744881c11.685133-11.691273 30.876218-11.449773 42.868343 0.535189 11.993149 11.985986 12.242835 31.17707 0.557702 42.868343L168.441828 356.54571799999997l759.417019 0c16.527418 0 29.925566 13.738909 29.925566 30.694069S944.386266 417.938973 927.858848 417.938973z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="camera-fill" unicode="&#58973;" d="M512 480C436.515555 480 375.111111 419.712 375.111111 345.6 375.111111 271.48800000000006 436.515555 211.20000000000005 512 211.20000000000005 587.484446 211.20000000000005 648.888887 271.48800000000006 648.888887 345.6 648.888887 419.712 587.484446 480 512 480M512 172.79999999999995C414.808889 172.79999999999995 336 250.15679999999998 336 345.6 336 441.0432 414.808889 518.4 512 518.4 609.210667 518.4 688 441.0432 688 345.6 688 250.15679999999998 609.210667 172.79999999999995 512 172.79999999999995M903.111113 691.2L723.767113 691.2C713.383113 691.2 703.448887 695.2512 696.115554 702.4512L640.792887 756.7488C633.459554 763.9488 623.505779 768 613.141333 768L512 768 410.878222 768C400.494222 768 390.56 763.9488 383.226667 756.7488L327.904 702.4512C320.570667 695.2512 310.616889 691.2 300.252445 691.2L120.888889 691.2C77.866667 691.2 42.666667 656.64 42.666667 614.4L42.666667 76.79999999999995C42.666667 34.559999999999945 77.866667 0 120.888889 0L903.111113 0C946.133333 0 981.333333 34.559999999999945 981.333333 76.79999999999995L981.333333 614.4C981.333333 656.64 946.133333 691.2 903.111113 691.2"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="fire" unicode="&#59222;" d="M890.059904 352.19948999999997C845.890699 458.956706 840.554889 548.4951550000001 857.396326 618.42714 859.144623 625.686731 860.991676 631.9776790000001 862.858846 637.425182 863.763607 640.064841 865.906573 645.659889 866.16406 646.532651L880.890349 696.448108 833.062903 675.9309969999999C832.106692 675.5208 830.618069 674.894716 827.426684 673.550492 824.667648 672.380966 822.310677 671.354022 819.868514 670.244809 813.291441 667.2575449999999 807.049466 664.090938 800.697749 660.4128450000001 784.089623 650.795565 768.486253 638.656896 753.86285 623.033596 727.630498 595.007563 706.526618 557.766355 691.78157 509.713231 675.041103 455.157161 671.516484 411.46006 673.004574 347.939834 673.477918 327.73476900000003 673.463923 322.197583 672.83965 318.324215 673.779618 324.156339 684.455526 333.67819899999995 696.104608 329.19567600000005 693.056849 330.36844199999996 685.695898 339.012828 676.314007 361.368339 660.550914 398.92921 646.834249 460.170272 636.817284 549.350468 625.445924 650.588768 630.103925 734.7280519999999 644.646978 801.338628 647.677924 815.221065 650.899934 827.082435 654.086773 836.904609 655.91465 842.538316 657.254607 846.094657 657.880284 847.554385L678.645286 896 628.243642 880.578031C617.409833 877.263087 599.94569 869.52239 578.105438 855.845223 542.547644 833.577626 507.199569 802.385036 474.400401 760.836776 447.596676 726.883228 423.611383 687.30061 403.118547 641.7016189999999 378.907516 587.829195 363.003277 542.798944 353.158029 503.238462 349.274261 487.632585 346.433259 473.323627 344.1945 458.925156 343.334411 453.39353 342.592734 448.063234 341.804612 441.911844 341.502524 439.553997 340.356619 430.329551 340.073506 428.145504 337.596047 409.033293 335.848224 404.35337 329.235273 398.312868 336.081933 404.566848 343.232634 404.098227 346.608002 402.086756 344.852318 403.133013 341.598345 406.493651 337.991853 411.887149 327.030897 428.279226 317.980358 454.883162 313.690598 489.339595 311.250185 508.941598 310.203772 539.08627 310.370048 576.545325 310.480474 601.422138 311.113088 628.122479 312.099068 654.977888 312.481453 665.393013 312.891081 675.105466 313.30045 683.8491750000001 313.545346 689.079919 313.735044 692.813105 313.84201 694.783403L317.55517 763.179488 271.360516 712.604139C270.467691 711.626645 268.852992 709.837042 266.618705 707.326295 262.927895 703.178805 258.823678 698.493751 254.407949 693.3614689999999 241.78797 678.693606 229.164348 663.340425 217.341267 648.004036 211.724185 640.717803 206.411389 633.591345 201.450577 626.6638379999999 176.017063 591.147305 156.617347 555.4025280000001 138.122768 512.155497 90.841957 401.595812 76.97672 299.64870599999995 99.261816 188.13489300000003 126.80821 50.29373899999996 188.553235-37.64422200000001 278.8297-84.690336 344.19104-118.75233700000001 408.837235-128 507.940695-128 525.713007-128 557.977207-125.567138 590.857378-120.46215900000004 641.152493-112.65333099999998 687.496192-99.78932299999997 726.063273-80.59104400000001 738.155853-74.57148800000004 743.07901-59.88870199999997 737.059454-47.79612199999997 731.039898-35.70354299999997 716.357111-30.780384000000026 704.264531-36.79993999999999 670.855859-53.43041900000003 629.092954-65.02289699999994 583.352478-72.12456999999995 552.984316-76.83953499999996 523.228215-79.08327499999996 507.940695-79.08327499999996 416.16215-79.08327499999996 357.934257-70.75375399999996 301.436271-41.310745999999995 224.830174-1.3887230000000272 171.977796 73.88423 147.230072 197.72094500000003 126.99711 298.965952 139.514783 391.004811 183.099329 492.921284 200.282663 533.1021499999999 218.020237 565.784358 241.22153 598.183718 245.831691 604.6215589999999 250.802959 611.289899 256.082244 618.137961 267.31885 632.713596 279.402035 647.409487 291.488864 661.457681 298.732051 669.8762429999999 304.338773 676.1767130000001 307.478705 679.614406L264.997214 697.435142C264.883874 695.347445 264.688038 691.493511 264.43725 686.13688 264.020474 677.234965 263.603959 667.359281 263.215279 656.7726250000001 262.21142 629.430212 261.566827 602.224414 261.453805 576.7624579999999 261.278897 537.3588179999999 262.385015 505.49418 265.148621 483.296209 276.058157 395.668083 322.627019 326.024497 362.226031 362.19561799999997 379.341732 377.829698 384.756649 392.328523 388.584361 421.857186 397.932742 493.974714 407.332926 531.746825 447.736538 621.64966 466.587287 663.594818 488.484326 699.731218 512.795234 730.526996 542.034492 767.565749 573.156162 795.028785 604.068111 814.386984 614.696751 821.043029 624.472062 826.201428 633.124687 830.036563 638.02329 832.207788 641.258688 833.404991 642.556233 833.802016L612.91959 866.825663C608.658554 856.884484 602.686705 838.478616 596.856038 811.772799 581.186705 740.003594 576.231674 650.498985 588.206246 543.890345 607.295279 373.94226100000003 638.819345 298.82556999999997 678.537329 283.542234 701.302332 274.78234499999996 717.731637 289.43566899999996 721.133156 310.5407 722.475759 318.870999 722.489387 324.26340300000004 721.907881 349.08549100000005 720.532565 407.791853 723.691247 446.952173 738.546223 495.36355 751.151827 536.44438 768.544047 567.135763 789.576147 589.605967 809.230566 610.60429 821.725461 617.839716 852.347733 630.9761169999999L842.705318 653.453557 819.246577 660.374464C822.235501 670.505564 813.450321 644.87463 809.839253 629.8801189999999 790.647573 550.1890470000001 796.611315 450.1135 844.8591 333.498332 883.105728 241.056017 874.587669 126.06492400000002 824.002925 61.39712899999995 815.680378 50.75754500000005 817.558709 35.38570000000004 828.198295 27.063153000000057 838.837879 18.740607999999952 854.209724 20.618939999999952 862.532269 31.258523999999966 924.762731 110.81426299999998 934.658528 244.404363 890.059904 352.19948999999997Z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="more-vertical" unicode="&#58993;" d="M511.998465 623.681848c40.525995 0 73.386404 35.771715 73.386404 79.892585s-32.860409 79.892585-73.386404 79.892585c-40.524972 0-73.384357-35.771715-73.384357-79.892585S471.47247 623.681848 511.998465 623.681848L511.998465 623.681848zM511.998465 463.893608c-40.524972 0-73.384357-35.772738-73.384357-79.893608 0-44.12087 32.859385-79.892585 73.384357-79.892585 40.525995 0 73.386404 35.772738 73.386404 79.892585C585.384869 428.12087 552.52446 463.893608 511.998465 463.893608L511.998465 463.893608zM511.998465 144.320199c-40.524972 0-73.384357-35.733852-73.384357-79.894631 0-44.119847 32.859385-79.893608 73.384357-79.893608 40.525995 0 73.386404 35.772738 73.386404 79.893608C585.383846 108.58634600000005 552.52446 144.320199 511.998465 144.320199L511.998465 144.320199z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="cart" unicode="&#58967;" d="M365.920994 84.618469c-39.030945 0-70.78516-31.754215-70.78516-70.78516s31.754215-70.784136 70.78516-70.784136c39.030945 0 70.784136 31.753191 70.784136 70.784136S404.951939 84.618469 365.920994 84.618469zM365.920994-5.784493999999995c-10.818393 0-19.61985 8.801457-19.61985 19.618826 0 10.818393 8.801457 19.61985 19.61985 19.61985s19.618826-8.801457 19.618826-19.61985C385.540843 3.015939000000003 376.739387-5.784493999999995 365.920994-5.784493999999995zM808.821219 84.618469c-39.030945 0-70.784136-31.754215-70.784136-70.78516s31.753191-70.784136 70.784136-70.784136 70.78516 31.753191 70.78516 70.784136S847.852164 84.618469 808.821219 84.618469zM808.821219-5.784493999999995c-10.81737 0-19.618826 8.801457-19.618826 19.618826 0 10.818393 8.801457 19.61985 19.618826 19.61985 10.818393 0 19.61985-8.801457 19.61985-19.61985C828.441069 3.015939000000003 819.640636-5.784493999999995 808.821219-5.784493999999995zM443.99107 305.940157c-14.057157-1.416256-24.305569-13.959943-22.890336-28.0171 1.328251-13.187347 12.446473-23.02132 25.423019-23.02132 0.856507 0 1.723248 0.042979 2.594081 0.130983l439.314561 44.245713c0.088004 0.007163 0.174985 0.01842 0.261966 0.026606l0.180102 0.01842c0.50449 0.051165 1.001817 0.119727 1.496074 0.198521 0.222057 0.035816 0.443092 0.076748 0.663102 0.11768 0.552585 0.103354 1.100054 0.217964 1.638313 0.355087 0.085958 0.022513 0.169869 0.047072 0.254803 0.069585 0.586354 0.156566 1.161453 0.334621 1.728364 0.530073 0.077771 0.026606 0.155543 0.051165 0.233314 0.078795 0.626263 0.222057 1.239224 0.469698 1.840928 0.737804 0.039909 0.017396 0.078795 0.035816 0.118704 0.054235 1.277086 0.577145 2.496867 1.252527 3.647063 2.020006 0.001023 0.001023 0.002047 0.001023 0.00307 0.002047 0.553609 0.369414 1.088798 0.76134 1.609661 1.170662 0.069585 0.054235 0.137123 0.10847 0.205685 0.163729 0.48607 0.38988 0.958838 0.795109 1.413186 1.218758 0.092098 0.084934 0.180102 0.173962 0.270153 0.25992 0.394996 0.378623 0.778736 0.76748 1.14815 1.169639 0.11154 0.121773 0.222057 0.243547 0.331551 0.367367 0.333598 0.3776 0.653893 0.766456 0.964978 1.163499 0.12382 0.158612 0.249687 0.314155 0.370437 0.475837 0.322341 0.432859 0.629333 0.876973 0.925069 1.329275 0.113587 0.173962 0.224104 0.348947 0.333598 0.525979 0.296759 0.479931 0.580215 0.968048 0.845251 1.467421 0.069585 0.130983 0.134053 0.265036 0.201591 0.397043 0.289596 0.568958 0.563842 1.147126 0.811482 1.738597 0.00307 0.007163 0.005117 0.014326 0.008186 0.021489 0.569982 1.369184 1.019213 2.796696 1.345648 4.26514 0 0.001023 0 0.002047 0.001023 0.00307l0.00307 0.013303c0.035816 0.162706 0.075725 0.323365 0.10847 0.487094l56.17951 252.734118c0.895393 4.030803 0.780783 8.04728-0.165776 11.794627 0.50449 2.003634 0.774643 4.101411 0.774643 6.261611 0 14.128789-11.452843 25.582655-25.582655 25.582655L195.47502 616.098125l-52.358485 159.553902c-3.631714 11.067057-14.093996 17.972327-25.177426 17.590634-0.207731 0.005117-0.413416 0.01535-0.62217 0.01535L54.663994 793.258011c-14.128789 0-25.582655-11.453866-25.582655-25.582655s11.453866-25.582655 25.582655-25.582655l45.614897 0 197.955514-603.235934c3.536546-10.776438 13.546527-17.613146 24.303522-17.613146 2.067079 0 4.16281 0.26299 6.245238 0.788969l567.583946 0c14.129812 0 25.582655 11.453866 25.582655 25.582655s-11.452843 25.582655-25.582655 25.582655L340.816223 173.1979 212.265428 564.933839l701.224666 0-48.137347-216.557174L443.99107 305.940157z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="star-fill" unicode="&#58968;" d="M752-43.200000000000045c-9.6 0-20.8 3.2-30.4 8l-208 104-209.6-104c-20.8-11.2-48-9.6-67.2 4.8-19.2 14.4-30.4 40-25.6 64l43.2 224L89.6 411.2C72 428.8 65.6 456 72 478.4c8 24 27.2 41.6 52.8 44.8l228.8 41.6 102.4 208c11.2 22.4 33.6 36.8 57.6 36.8s48-14.4 57.6-36.8l102.4-208 228.8-40c24-3.2 44.8-20.8 51.2-44.8 8-24 1.6-49.6-16-67.2L772.8 257.6l41.6-224c4.8-25.6-6.4-49.6-25.6-64-9.6-8-22.4-12.8-36.8-12.8z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="prev" unicode="&#58970;" d="M62.573 384.103l423.401 423.662c18.985 18.985 49.757 18.985 68.727 0 18.982-18.972 18.985-49.746 0-68.729l-355.058-355.067 356.796-356.796c18.977-18.971 18.976-49.746 0-68.727-18.982-18.976-49.751-18.976-68.727 0l-39.753 39.753 0.269 0.246-385.655 385.661zM451.365 384.103l423.407 423.662c18.985 18.985 49.757 18.985 68.727 0 18.982-18.972 18.985-49.746 0-68.729l-355.058-355.067 356.796-356.796c18.977-18.971 18.976-49.746 0-68.727-18.982-18.976-49.757-18.977-68.727 0l-39.762 39.754 0.273 0.249-385.662 385.661zM451.365 384.103z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="next" unicode="&#58971;" d="M948.066926 382.958838l-411.990051-412.24426c-18.47333-18.47333-48.417689-18.47333-66.875207 0-18.47333 18.461167-18.47333 48.405526 0 66.875207L814.691135 383.088983 467.512212 730.269123c-18.466032 18.458735-18.466032 48.405526 0 66.873991 18.468465 18.464816 48.410391 18.464816 66.872774 0l38.682336-38.682336-0.261507-0.239614 375.259894-375.265975v0.003649m-378.312834 0L157.756743-29.28542200000004c-18.47333-18.47333-48.415256-18.47333-66.872775 0-18.47333 18.461167-18.47333 48.405526 0 66.875207L436.369787 383.088983 89.19208 730.269123c-18.4636 18.458735-18.4636 48.405526 0 66.873991 18.470898 18.464816 48.415256 18.464816 66.872774 0l38.692067-38.682336-0.266372-0.239614 375.267191-375.265975-0.004865 0.003649m0 0z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="upload" unicode="&#59004;" d="M831.488 478.208C831.488 478.208 831.488 478.208 831.488 478.208c0 143.36-114.688 258.048-253.952 258.048-98.304 0-184.32-57.344-225.28-139.264C327.68 605.184 307.2 609.28 286.72 609.28c-90.112 0-159.744-73.728-159.744-159.744 0-16.384 4.096-28.672 8.192-40.96C57.344 379.904 0 310.27200000000005 0 224.25599999999997c0-106.496 86.016-192.512 192.512-192.512l192.512 0 0 192.512L258.048 224.25599999999997l258.048 258.048 258.048-258.048-126.976 0 0-192.512 192.512 0L839.68 35.84000000000003c106.496 16.384 192.512 110.592 192.512 221.184C1024 371.712 937.984 465.92 831.488 478.208z"  horiz-adv-x="1033" />
+      
+      <glyph glyph-name="upload-drag" unicode="&#59009;" d="M666.931 445.918l-124.245 99.362c-7.221 5.639-16.428 9.042-26.429 9.042-9.963 0-19.136-3.376-26.438-9.047l-124.215-99.391c-9.615-7.772-15.713-19.565-15.713-32.782 0-9.946 3.453-19.084 9.223-26.284 13.828-17.359 41.51-20.465 58.918-6.505l56.252 45.022v-261.12c0-23.177 18.842-41.984 41.95-41.984s41.95 18.842 41.95 41.984v261.12l56.286-45.056c17.545-13.892 45.09-10.718 58.914 6.554 5.754 7.137 9.236 16.316 9.236 26.308 0 13.211-6.086 24.999-15.609 32.716zM235.827 142.95000000000005c-85.026 0-152.542 31.71-188.655 89.839-36.113 58.095-34.406 134.724 4.335 195.174 37.342 58.334 102.366 92.023 178.995 94.549-19.866 130.492 42.667 202.377 84.753 235.008 90.112 69.871 234.257 79.053 335.565 21.367 58.982-33.587 94.037-85.675 100.454-146.978 113.937 18.978 177.562-33.826 206.814-69.905 63.317-78.131 71.27-204.39 18.91-300.203-46.524-85.06-130.389-127.317-229.82-116.497-18.739 2.116-32.222 18.978-30.174 37.683s19.285 32.017 37.683 30.174c96.7-10.718 143.258 46.353 162.406 81.408 39.014 71.373 33.826 167.868-12.049 224.495-38.673 47.684-100.352 60.518-178.483 37.069-2.94-0.916-6.319-1.443-9.822-1.443-18.851 0-34.133 15.282-34.133 34.133 0 1.495 0.096 2.969 0.283 4.414 8.549 68.506-31.114 106.53-65.93 126.362-77.346 44.066-191.522 37.035-259.925-15.974-58.266-45.193-75.947-117.18-51.132-208.179 0.761-2.688 1.198-5.775 1.198-8.963 0-18.851-15.282-34.133-34.133-34.133-1.481 0-2.94 0.094-4.371 0.277-70.759 8.822-128.991-13.535-159.677-61.424-24.61-38.434-26.146-86.46-3.823-122.368 27.716-44.578 86.05-64.375 164.147-55.637 1.132 0.133 2.443 0.209 3.772 0.209 18.853 0 34.138-15.284 34.138-34.138 0-17.525-13.205-31.965-30.208-33.914-14.153-1.653-27.874-2.404-41.118-2.404z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="user" unicode="&#59248;" d="M611.2 342.4c70.4 54.4 115.2 140.8 115.2 230.4 0 156.8-128 288-284.8 288s-284.8-128-284.8-284.8c0-92.8 44.8-182.4 115.2-236.8C108.8 272 0 105.60000000000002 0-80c0-9.6 9.6-19.2 19.2-19.2h848c9.6 0 19.2 9.6 19.2 19.2 0 188.8-112 355.2-275.2 422.4z m-576-396.8C44.8 115.20000000000005 156.8 268.79999999999995 320 320c6.4 3.2 12.8 9.6 12.8 16s-3.2 16-9.6 19.2c-76.8 41.6-128 131.2-128 224 0 134.4 112 246.4 246.4 246.4s246.4-112 246.4-249.6c0-89.6-51.2-176-128-220.8-6.4-3.2-9.6-9.6-9.6-19.2 0-6.4 6.4-12.8 12.8-16 160-51.2 275.2-204.8 281.6-377.6H35.2zM812.8 361.6c54.4 41.6 86.4 108.8 86.4 176 0 89.6-54.4 172.8-134.4 208-9.6 3.2-22.4 0-25.6-9.6-3.2-9.6 0-22.4 9.6-25.6 67.2-28.8 112-99.2 112-172.8 0-67.2-38.4-131.2-96-163.2-6.4-3.2-9.6-9.6-9.6-19.2 0-6.4 6.4-12.8 12.8-16 131.2-41.6 217.6-160 217.6-297.6 0-9.6 9.6-19.2 19.2-19.2s19.2 9.6 19.2 19.2c-3.2 140.8-86.4 262.4-211.2 320z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="file-b" unicode="&#58965;" d="M790.08 177.91999999999996l-138.112-119.232V177.91999999999996h138.112zM198.848 763.008h627.328v-516.16H617.088a34.56 34.56 0 0 1-34.816-34.432v-206.528H198.848V763.008z m662.208 68.8H164.032a34.56 34.56 0 0 1-34.816-34.432v-825.92a34.56 34.56 0 0 1 34.816-34.432h453.056l278.784 240.896V797.376a34.56 34.56 0 0 1-34.816 34.432z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="component" unicode="&#59479;" d="M917.376 652.544L500.8 891.2a34.304 34.304 0 0 1-34.176 0L50.112 652.48a33.92 33.92 0 0 1-17.088-29.376v-477.44c0-12.16 6.528-23.296 17.088-29.44l416.512-238.72a35.136 35.136 0 0 1 34.176 0l416.576 238.72a33.92 33.92 0 0 1 17.088 29.44v477.44a33.92 33.92 0 0 1-17.088 29.44z m-51.264-487.36l-382.4-219.136-382.336 219.136V603.52l382.336 219.136 382.4-219.136v-438.272zM198.784 535.488a33.792 33.792 0 0 1 12.544-46.4l237.824-136.32V83.20000000000005c0-18.816 15.232-33.92 34.176-33.92a33.92 33.92 0 0 1 34.176 33.92V352.384l238.656 136.832a33.856 33.856 0 0 1 12.544 46.4 34.368 34.368 0 0 1-46.72 12.416L483.712 411.52 245.504 548.0319999999999a34.432 34.432 0 0 1-46.72-12.544z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="find-fill" unicode="&#58992;" d="M512 896C229.236364 896 0 666.763636 0 384c0-282.786909 229.236364-512 512-512s512 229.213091 512 512C1024 666.763636 794.763636 896 512 896zM657.291636 383.976727c0-77.195636-60.392727-139.729455-136.424727-144.407273l-175.732364-151.714909-22.877091 13.242182 58.228364 222.021818c-8.634182 18.548364-13.800727 39.074909-13.800727 60.858182 0 77.195636 60.369455 139.729455 136.378182 144.430545l175.802182 151.714909 22.877091-13.172364-58.251636-222.068364C652.125091 426.309818 657.291636 405.806545 657.291636 383.976727zM512 384m-66.048 0a2.838 2.838 0 1 1 132.096 0 2.838 2.838 0 1 1-132.096 0Z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="loading" unicode="&#58941;" d="M511.999488 756.654348m-70.608128 0a69 69 0 1 1 141.216255 0 69 69 0 1 1-141.216255 0ZM236.047576 639.997442m-68.561515 0a67 67 0 1 1 137.123031 0 67 67 0 1 1-137.123031 0ZM125.530506 382.12428m-62.421678 0a61 61 0 1 1 124.843356 0 61 61 0 1 1-124.843356 0ZM227.861126 100.71507499999996m-54.235229 0a53 53 0 1 1 108.470457 0 53 53 0 1 1-108.470457 0ZM514.166851-16.84438799999998m-47.192835 0a46.118 46.118 0 1 1 94.385671 0 46.118 46.118 0 1 1-94.385671 0ZM804.730553 91.450061m-33.834596 0a33.064 33.064 0 1 1 67.669192 0 33.064 33.064 0 1 1-67.669192 0ZM935.55411 383.395226m-23.969924 0a23.424 23.424 0 1 1 47.939849 0 23.424 23.424 0 1 1-47.939849 0ZM856.723717 634.80007m-17.135262 0a16.745 16.745 0 1 1 34.270525 0 16.745 16.745 0 1 1-34.270525 0Z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="loading-1" unicode="&#58942;" d="M537.574469 831.696462c-14.123672 0-25.574469-11.447726-25.574469-25.574469 0-14.123672 11.450796-25.574469 25.574469-25.574469 204.495464 0 370.82877-166.358889 370.82877-370.82877 0-14.123672 11.450796-25.574469 25.574469-25.574469 14.123672 0 25.574469 11.450796 25.574469 25.574469C959.551152 642.385838 770.241552 831.696462 537.574469 831.696462z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="add-1" unicode="&#58964;" d="M566.935 78.97233332999997c0-30.366-24.612-54.972-54.935-54.972v0c-30.384 0-54.996 24.612-54.996 54.972v610.057c0 30.361 24.612 54.972 54.996 54.972v0c30.33 0 54.935-24.612 54.935-54.972v-610.057zM817.004 438.96633333c30.384 0 54.996-24.606 54.996-54.966v0c0-30.354-24.612-54.966-54.996-54.966h-610.062c-30.33 0-54.942 24.612-54.942 54.966v0c0 30.359 24.612 54.966 54.942 54.966h610.062zM817.004 438.96633333z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="pause" unicode="&#58961;" d="M512-128c-282.714 0-511.893 229.232-511.893 512 0 282.768 229.179 512 511.893 512 282.714 0 511.893-229.232 511.893-512 0-282.768-229.179-512-511.893-512zM512 863.996c-265.043 0-479.9-214.91-479.9-479.996 0-265.097 214.857-479.996 479.9-479.996 265.043 0 479.9 214.899 479.9 479.996 0 265.086-214.857 479.996-479.9 479.996zM639.973 181.32299999999998h-21.329c-23.558 0-42.658 19.1-42.658 42.658v319.933c0 23.558 19.1 42.658 42.658 42.658h21.329c23.558 0 42.658-19.1 42.658-42.658v-319.933c0-23.558-19.1-42.658-42.658-42.658zM405.356 181.32299999999998h-21.329c-23.558 0-42.658 19.1-42.658 42.658v319.933c0 23.558 19.1 42.658 42.658 42.658h21.329c23.558 0 42.658-19.1 42.658-42.658v-319.933c0-23.558-19.1-42.658-42.658-42.658z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="play" unicode="&#58962;" d="M512 896C229.376 896 0 666.624 0 384 0 101.37599999999998 229.376-128 512-128 794.624-128 1024 101.37599999999998 1024 384 1024 666.624 794.624 896 512 896L512 896 512 896zM512-95.23199999999997C245.76-95.23199999999997 32.768 117.75999999999999 32.768 384 32.768 650.24 245.76 863.232 512 863.232S991.232 650.24 991.232 384C991.232 117.75999999999999 778.24-95.23199999999997 512-95.23199999999997L512-95.23199999999997 512-95.23199999999997zM733.184 392.192L393.216 588.8c-4.096 4.096-8.192 4.096-12.288 0C376.832 588.8 372.736 584.704 372.736 580.608l0-393.216c0-4.096 4.096-8.192 4.096-8.192 4.096-4.096 8.192-4.096 12.288 0l344.064 196.608c4.096 4.096 4.096 4.096 4.096 8.192C741.376 388.096 737.28 392.192 733.184 392.192L733.184 392.192 733.184 392.192zM733.184 392.192"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="video" unicode="&#59117;" d="M952.523633 599.2477269999999L952.523633 599.2477269999999 952.523633 599.2477269999999zM100.53762400000005 661.054062C100.53762400000005 661.054062 100.53762400000005 661.054062 100.53762400000005 661.054062 100.53762400000005 661.054062 100.53762400000005 661.054062 100.53762400000005 661.054062zM100.74228 720.404517L100.74228 720.404517 100.74228 720.404517zM660.990107 739.9449716666666c8.697911 0 17.498151-0.511642 25.684421-2.353553 12.279404-2.865194 23.22854-8.18627 34.382332-16.679524 15.144599-11.460777 26.196063-29.572899 32.02878-52.187469 3.479165-13.405016 2.967523-28.651944 2.558209-42.05696-0.102328-4.195463-0.204657-8.083941-0.204657-11.665434l0-37.759169 101.407415 70.401919 25.479764 17.60048c0.511642 0.306985 1.330269 1.023284 2.148896 1.637254 4.40012 3.376836 11.051464 8.595583 20.977316 11.051464 3.274508 0.818627 6.549016 1.22794 10.02818 1.22794 9.618867 0 19.44239-3.274508 27.730987999999996-9.311882 18.82842-13.916657999999998 18.726092-35.405616 18.726092-51.061857 0-1.023284 0-2.148896 0-3.172179l0-409.620466c0-15.963226 0.102328-37.963825-19.647047-51.982812-6.753672-4.809433-16.679524-8.390926-27.219346-8.390926-5.01409 0-10.130509 0.818627-15.144599 2.762866-7.162986 2.762866-12.279404 6.856000999999999-16.065554 9.823524-0.920955 0.716299-1.841911 1.432597-2.353553 1.841911l-24.968122 17.395823-101.10043 70.094934 0-37.963825c0-3.581493 0.102328-7.367643 0.204657-11.460777 0.409313-14.735285 0.818627-29.982212-2.865194-43.796542-5.62806-21.488957999999997-16.679524-39.396423-31.107825-50.447886-7.879285-6.037374-18.930748-13.405016-34.075347-16.986509-7.776956-1.841911-16.167882-2.353553-24.45648-2.353553-4.297792 0-8.595583 0.102328-12.688718 0.204657-3.683821 0.102328-7.162986 0.204657-10.232837 0.204657L167.15339300000005 84.94107466666674c-1.944239 0-3.888478 0-5.832717 0-1.944239 0-3.990806 0-5.935045 0-16.577196 0-33.461377 0.61397-47.787349 6.549016-27.935644999999997 11.563106-46.764065 37.759169-53.006096 73.574098l-0.409313 2.251224 0 2.353553c-0.102328 18.930748-0.204657 37.861497-0.306985 56.792245l0 0.511642L53.87588699999998 598.0155226666666c0 4.40012-0.102328 8.902568-0.102328 13.712001999999998-0.306985 27.01469-0.716299 54.950335 9.311882 76.643949 9.823524 21.284300999999996 27.526331999999996 38.066154 48.708304 45.945438 5.730389 2.148896 11.051464 2.762866 15.04227 3.172179 1.023284 0.102328 2.353553 0.306985 3.069851 0.409313l4.093135 1.534926 500.9997 0c3.581493 0 7.572299 0.102328 11.767763 0.306985C651.166583 739.7403146666667 656.078345 739.9449716666666 660.990107 739.9449716666666M304.273409 266.7785886666668L559.889677 394.2797376666667l0 33.973019L304.273409 555.9585626666667 304.273409 266.7785886666668M660.990107 780.8763196666666c-5.62806 0-10.949136-0.204657-15.758569-0.306985-3.888478-0.102328-7.469971-0.204657-10.437494-0.204657L133.79434400000002 780.3646776666667l-7.265314 0-6.446687-2.353553c-5.3210749999999996-0.61397-13.609673-1.841911-22.716898-5.218747-31.210153-11.665434-57.303887-36.121915-71.629859-67.229739-13.814329999999998-30.084541-13.405016-64.159888-12.995703-94.244429 0.102328-4.604777 0.102328-9.004897 0.102328-13.20036l0-371.349655 0-0.102328 0-0.102328 0-0.511642c0.102328-18.930748 0.204657-37.861497 0.306985-56.792245l0-2.251224 0-3.479165 0.61397-3.376836 0.409313-2.251224c4.195463-23.944839 12.791046-45.126811 25.479764-62.727291 13.609673-18.82842 31.107825-32.847407 52.08514-41.545318 21.488957999999997-8.902568 44.001199-9.618867 63.443589-9.618867 2.046567 0 4.093135 0 6.139702 0 1.841911 0 3.78615 0 5.62806 0l473.166384 0c2.558209 0 5.62806-0.102328 9.004897-0.204657 4.195463-0.102328 8.902568-0.306985 13.916657999999998-0.306985 13.302688 0 24.149495 1.125612 33.973019 3.479165 22.819227 5.423404 39.089437 16.474868 49.322274 24.251824 21.693613999999997 16.577196 37.963825 42.363944999999994 45.84311 72.653143 2.251224 8.595583 3.376836 17.088838 3.990806 25.377436l36.838213-25.582093 24.558809-17.088838c0.306985-0.204657 0.61397-0.511642 0.920955-0.716299 4.809433-3.683821 13.609673-10.642149999999999 26.400719-15.656241 9.516538-3.683821 19.647047-5.62806 30.084541-5.62806 18.009793 0 36.53122799999999 5.832717 50.8572 15.963226 16.577196 11.767763 27.730987999999996 27.935644999999997 33.052064 48.094334 3.78615 14.4283 3.78615 27.628659999999996 3.78615 37.34985499999999l0 409.518137c0 0.920955 0 1.739582 0 2.660538l0 0.409313c0 9.41421 0.102328 22.409913-3.479165 36.53122799999999-5.116419 19.749375-15.758569 35.81493-31.721795 47.68502-15.144599 11.153792-33.666034 17.293495-52.08514 17.293495-6.753672 0-13.507345-0.818627-19.954032-2.455881-18.21445-4.604777-30.289198-13.916657999999998-36.019586-18.419107l0 0c-0.204657-0.204657-0.511642-0.409313-0.716299-0.511642l-25.172779-17.293495-0.102328 0-0.102328 0-37.14519799999999-25.786749c-0.511642 7.674628-1.637254 15.553912-3.683821 23.433197-8.18627 31.721795-24.354152 57.508544-46.866394 74.597382-15.758569 11.972419-32.02878 19.851704-49.833916 23.944839C685.8559009999999 779.7507076666667 674.702109 780.8763196666666 660.990107 780.8763196666666L660.990107 780.8763196666666zM345.204757 332.9850436666668L345.204757 489.75210666666663l157.074048-78.48586L345.204757 332.9850436666668 345.204757 332.9850436666668zM347.455981 429.177975L347.455981 308.02118499999995 347.455981 429.177975Z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="headset" unicode="&#59132;" d="M356.285031 2.1522690000000466L356.396571 2.1522690000000466 356.396571 285.236626 253.462201 285.236626 253.462201 2.1522690000000466ZM665.076886 285.236626l103.042841 0 0-283.08538-103.042841 0 0 283.08538ZM63.809793 301.950286c0-38.758746-3.195785-112.220874 5.457292-148.208507l65.735144 0c-10.112312 35.644825-7.747451 109.176538-7.747451 148.208507 0 219.937155 172.264389 398.231887 384.763131 398.231887 212.498742 0 384.763131-178.294732 384.763131-398.231887 0-39.031968 2.266623-112.563682-7.845689-148.208507l65.735144 0c8.653077 35.987632 5.555529 109.449761 5.555529 148.208507 0 256.20415-200.670346 463.898469-448.208115 463.898469C264.479115 765.848755 63.809793 558.1544349999999 63.809793 301.950286z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="voice" unicode="&#59016;" d="M463.380164 644.0568969999999v-0.003069c-4.550643 4.549619-10.484795 7.02295-16.913205 7.02295s-12.365632-2.473331-16.915251-7.02295c-4.549619-4.551666-7.020904-10.485819-7.020904-16.914229s2.471284-12.365632 7.020904-16.915251c60.437487-60.438511 93.675496-140.756791 93.675496-226.222301 0-85.464487-33.238009-165.783791-93.675496-226.220255-4.549619-4.551666-7.020904-10.487865-7.020904-16.915252 0-6.429433 2.471284-12.365632 7.020904-16.914228 4.550643-4.549619 10.486842-7.02295 16.915251-7.02295s12.364609 2.473331 16.913205 7.02295c35.114752 35.116799 62.317301 76.06849 80.814584 121.668037 17.904789 44.018539 26.90579 90.608647 26.90579 138.384768s-9.101285 94.26799-26.90579 138.384767c-18.59552 45.697785-45.698808 86.550215-80.814584 121.667013zM781.892405 618.929614v-0.002047c-31.358195 77.452-77.550237 146.990772-137.098471 206.539007-4.550643 4.549619-10.485819 7.02295-16.915252 7.02295-6.42841 0-12.363585-2.473331-16.914228-7.02295-9.29776-9.299807-9.29776-24.531719 0-33.82948 54.997592-54.998615 97.631598-119.195729 126.613676-190.71153 27.993564-69.044516 42.237987-142.045133 42.237987-216.924541s-14.244422-147.882072-42.237987-216.923518c-28.982078-71.517847-71.616084-135.616724-126.613676-190.711529-9.29776-9.298783-9.29776-24.531719 0-33.82948 4.551666-4.551666 10.485819-7.02295 16.914228-7.02295 6.429433 0 12.366655 2.471284 16.915252 7.02295 59.547211 59.547211 105.740276 129.085984 137.098471 206.53696 30.369681 74.78117 45.699832 153.817248 45.699831 234.928591 0 81.111343-15.331173 160.146397-45.699831 234.927567zM299.474141 427.621497c-11.670807 11.573593-27.103288 18.004049-43.522236 18.004049-16.419971 0-31.852452-6.429433-43.52326-18.004049-11.57257-11.57257-18.003026-27.104311-18.003026-43.522236 0-16.420995 6.42841-31.851429 18.003026-43.52326 11.574616-11.57257 27.103288-18.003026 43.52326-18.003025s31.852452 6.429433 43.522236 18.003025c11.573593 11.573593 18.003026 27.104311 18.003025 43.52326 0 16.419971-6.427386 31.852452-18.003025 43.522236z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="speaker" unicode="&#58949;" d="M587.182306 754.7203c-6.003737 2.705622-13.043061 1.642406-17.984606-2.721994l-259.223926-229.293243-148.246369 0c-9.253758 0-16.752546-7.498788-16.752546-16.756639l0-267.886213c0-9.249665 7.498788-16.756639 16.752546-16.756639l144.050814 0c9.253758 0 16.752546 7.506974 16.752546 16.756639L322.530764 490.391099c1.774413 0.704035 3.433192 1.719154 4.892427 3.010567l236.127905 208.861912 0-653.332912-160.751171 137.64287c-2.12643 1.824555-90.300632 78.69941-93.927229 76.162634-4.427846-3.097548-15.768125-17.59882-18.419512-22.512736-0.953721-1.768273-2.196015-1.334391 15.413038-16.379039 25.674753-21.936615 73.780377-61.548798 75.144444-62.717414l10.007935-8.570189 178.388876-152.761196c3.093455-2.653433 6.978948-4.028757 10.900258-4.028757 2.369977 0 4.756327 0.503467 7.003508 1.534959 5.939269 2.738367 9.749038 8.677637 9.749038 15.217586L597.060281 739.446431C597.060281 746.034477 593.190137 752.013655 587.182306 754.7203L587.182306 754.7203zM290.453185 254.814756l-115.040083 0L175.413102 489.195877l115.03906 0 0-234.381122L290.453185 254.814756zM747.742119 375.98444300000006c0-51.55212-34.83232-96.658434-84.702124-109.693308-1.415232-0.375553-2.846838-0.551562-4.245697-0.551562-7.438413 0-14.234189 4.992711-16.200984 12.523221-2.338255 8.949836 3.021823 18.104333 11.967566 20.442588 35.136242 9.18929 59.672054 40.96397 59.672054 77.279061 0 36.307927-24.535813 68.090794-59.672054 77.271898-8.945743 2.346441-14.305821 11.492752-11.967566 20.450774 2.342348 8.953929 11.499915 14.305821 20.446681 11.967566C712.909799 472.643899 747.742119 427.530422 747.742119 375.98444300000006L747.742119 375.98444300000006zM864.950588 375.793084c0-88.87619-48.554856-170.44495-126.718053-212.883505-2.537799-1.375324-5.276167-2.02717-7.982812-2.02717-5.939269 0-11.69946 3.166109-14.733563 8.762571-4.417613 8.134261-1.39886 18.303878 6.727215 22.720468 67.350944 36.566824 109.198028 106.851587 109.198028 183.427636 0 76.844156-42.055838 147.272181-109.741403 183.78784-8.154727 4.396123-11.192923 14.557554-6.795776 22.700001 4.38896 8.142447 14.558577 11.184737 22.701025 6.795776C816.151162 546.697499 864.950588 464.976266 864.950588 375.793084L864.950588 375.793084z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="fonts-del" unicode="&#58959;" d="M928 448l-143.616 0c-3.456 55.616-14.272 106.56-29.504 144.96C725.504 666.816 617.344 768 464.32 768L256 768l0-320L96 448C78.336 448 64 433.664 64 416S78.336 384 96 384L256 384l0-320 229.632 0c156.288 0 240.768 97.856 267.904 167.488C772.736 280.96000000000004 782.272 333.312 784.96 384L928 384C945.664 384 960 398.336 960 416S945.664 448 928 448zM349.376 711.488l63.936 0c35.712 0 251.84 27.968 266.944-263.488l-330.88 0L349.376 711.488zM439.296 120.51199999999994L349.376 120.51199999999994 349.376 382.528 349.376 384l330.88 0C665.344 113.98400000000004 467.968 120.51199999999994 439.296 120.51199999999994z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="fonts-html" unicode="&#58955;" d="M194.33 416.235h-101.295v101.28h-46.035v-267.03h46.035v119.7h101.28v-119.7h46.035v267.03h-46.035v-101.28zM277.205 480.69h73.665v-230.205h46.035v230.205h73.665v36.825h-193.365v-36.825zM627.815 335.58000000000004l-46.755 181.935h-73.665v-267.03h46.035v211.785l46.035-211.785h55.245l46.83 213.93-0.795-213.93h46.035v267.03h-73.665l-45.3-181.935zM848.09 287.30999999999995v230.205h-46.035v-267.03h174.945v36.825h-128.91z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="fonts-code" unicode="&#58958;" d="M270 626c-12 12-32 12-44 0L9 409c-12-12-12-32 0-44l217-217c6-6 14-9 22-9s16 3 22 9c12 12 12 32 0 44L75 387 270 582C282 595 282 614 270 626zM1015 409L798 626c-12 12-32 12-44 0-12-12-12-32 0-44l195-195L754 192c-12-12-12-32 0-44 6-6 14-9 22-9s16 3 22 9l217 217C1027 377 1027 397 1015 409zM624 696L624 696c-16 6-34-3-40-19L382 119c-6-16 2-34 19-40l0 0c16-6 34 3 40 19l202 558C648 672 640 690 624 696z"  horiz-adv-x="1025" />
+      
+      <glyph glyph-name="fonts-strong" unicode="&#58923;" d="M199.092919 848.487893l355.326704 0c70.335928 0 122.780371-2.942005 157.349701-8.809643 34.568307-5.884011 65.491597-18.131963 92.78522-36.759205 27.27725-18.627243 50.01409-43.427068 68.209498-74.397431 18.195408-30.986735 27.293623-65.699328 27.293623-104.169501 0-41.7161-11.17655-79.977519-33.496905-114.802676s-52.604078-60.951187-90.818425-78.362742c54.075593-15.765055 95.647407-42.626843 124.715443-80.585363s43.602054-82.58388 43.602054-133.877103c0-40.388872-9.417487-79.673597-28.220738-117.839849-18.803251-38.182624-44.482097-68.673056-77.035514-91.489714-32.55444-22.833031-72.702835-36.855396-120.414487-42.09984-29.931706-3.229554-102.122889-5.260817-216.572524-6.060019L199.092919-40.765192999999954 199.092919 848.487893zM378.171504 700.1084940000001l0-205.684546 117.64849 0c69.935816 0 113.410979 1.006933 130.390699 3.038196 30.730908 3.629667 54.891168 14.246469 72.478731 31.850405 17.588587 17.588587 26.381857 40.756239 26.381857 69.473281 0 27.501354-7.594979 49.838082-22.75219 67.042929-15.158235 17.188474-37.702694 27.597545-67.618027 31.242562-17.796318 2.01489-68.945255 3.038196-153.431461 3.038196L378.171504 700.109518zM378.171504 346.04454999999996l0-236.383732 166.622902 0c64.85203 0 106.008382 1.807159 123.43631 5.420453 26.750247 4.828982 48.543599 16.58063 65.363683 35.272341s25.247011 43.714617 25.247011 75.085092c0 26.526143-6.491855 49.03888-19.459191 67.538209-12.983709 18.48398-31.722492 31.961946-56.250118 40.404222s-77.739549 12.663414-159.619394 12.663414L378.171504 346.04454999999996z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="unlink" unicode="&#58957;" d="M150.336 767.6800000000001C133.44 762.304 124.16 744.3199999999999 129.472 727.488 131.2 722.1759999999999 134.208 717.44 138.304 713.664l122.624-122.432C270.208 576.192 289.92 571.52 304.96 580.736 320 590.0799999999999 324.672 609.7280000000001 315.456 624.832 312.832 629.056 309.184 632.64 304.96 635.264L182.336 757.696C175.168 765.44 164.672 769.216 154.304 767.6800000000001 152.96 767.808 151.552 767.808 150.336 767.6800000000001L150.336 767.6800000000001zM406.08 831.424c-13.696-4.48-22.72-17.6-22.016-32L384.064 672c0-17.664 14.336-32 32-32s31.872 14.336 31.872 32L447.936 799.424C448.256 817.088 434.304 831.6800000000001 416.64 832 414.464 832.064 412.16 831.808 410.048 831.424 408.704 831.552 407.296 831.552 406.08 831.424L406.08 831.424zM91.392 511.872C73.728 509.12 61.632 492.544 64.384 474.88 67.136 457.28 83.712 445.248 101.376 448L224 448C241.664 448 256 462.208 256 479.872s-14.336 32-32 32L101.376 511.872c-1.984 0.192-3.968 0.192-6.016 0C94.016 512 92.608 512 91.392 511.872L91.392 511.872zM795.456 320c-17.728-2.752-29.824-14.08-27.072-31.744 2.752-17.6 19.328-35.008 36.992-32.256L928 256c17.664 0 32 19.584 32 37.248S945.664 320 928 320l-122.624 0c-1.984 0.192-3.968 0.192-6.016 0-1.344 0.128-2.688 0.128-4.032 0L795.456 320zM598.272 127.42399999999998c-13.76-4.48-22.72-17.6-22.08-32L576.192-32c0-17.664 14.336-32 32-32S640-49.66399999999999 640-32l0 127.424c0.32 17.6-13.568 32.256-31.232 32.576-2.176 0.064-4.352-0.192-6.592-0.576-1.344 0.128-2.688 0.128-4.032 0L598.272 127.42399999999998zM726.272 191.67999999999995c-16.896-5.376-26.24-23.36-20.864-40.192 1.664-5.312 4.736-10.048 8.832-13.824l122.56-122.432c9.28-15.04 28.928-19.776 44.032-10.496 14.976 9.344 19.712 28.992 10.368 44.032-2.624 4.224-6.144 7.808-10.368 10.432l-122.56 122.432c-7.168 7.744-17.6 11.52-28.032 9.984-1.344 0.128-2.688 0.128-4.032 0L726.272 191.61599999999999zM339.968 28.03200000000004c-49.152 0-98.304 18.688-135.744 56.128-74.816 74.88-74.816 196.608 0 271.488l87.744 87.744c12.48 12.48 32.768 12.48 45.248 0s12.48-32.768 0-45.248L249.408 310.46400000000006c-49.92-49.856-49.92-131.136 0-180.992 49.856-49.856 131.136-49.856 180.992 0l87.744 87.744c12.48 12.48 32.768 12.48 45.248 0s12.48-32.768 0-45.248l-87.744-87.744C438.272 46.72000000000003 389.12 28.03200000000004 339.968 28.03200000000004zM702.144 323.712c-8.192 0-16.384 3.136-22.656 9.344-12.48 12.48-12.48 32.768 0 45.248l87.744 87.744c49.856 49.92 49.856 131.072 0 180.992-49.856 49.856-131.136 49.856-180.992 0L498.496 559.296c-12.48-12.48-32.768-12.48-45.248 0s-12.48 32.768 0 45.248l87.744 87.744c74.88 74.88 196.608 74.88 271.488 0 74.88-74.816 74.88-196.672 0-271.488l-87.744-87.744C718.528 326.784 710.336 323.712 702.144 323.712z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="picture" unicode="&#58954;" d="M765.376 615.424c0 0 103.04 1.024 103.04-100.992 0 0 9.536-98.752-103.04-100.928 0 0-100.864-2.176-99.84 100.928C665.536 514.496 664.448 605.8879999999999 765.376 615.424ZM968.32 770.56c0 0 54.208-4.224 54.208-52.032l0-712.832c0 0-3.2-51.008-54.208-52.096L968.32 770.56ZM1.472 5.631999999999948c0 0 2.176-52.096 52.096-52.096L968.32-46.464000000000055l0 150.848-99.712 0-203.072 206.144-153.024-153.984L304.32 413.568l-205.056-307.072-45.632-1.024L52.48 718.4639999999999 1.472 718.4639999999999 1.472 5.631999999999948ZM968.32 770.56L53.568 770.56c0 0-52.096 1.088-52.096-52.032L968.32 718.528 968.32 770.56Z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="link" unicode="&#58956;" d="M262.4-121.60000000000002c-64 0-128 25.6-179.2 76.8-102.4 102.4-102.4 262.4 0 364.8l134.4 134.4 89.6-89.6-134.4-134.4c-51.2-51.2-51.2-128 0-179.2 51.2-51.2 128-51.2 179.2 0l179.2 179.2c25.6 25.6 38.4 57.6 38.4 89.6S556.8 384 537.6 409.6L467.2 473.6l89.6 89.6 70.4-70.4C672 448 697.6 384 697.6 313.6c0-70.4-25.6-134.4-76.8-179.2l-179.2-179.2C396.8-96 326.4-121.60000000000002 262.4-121.60000000000002zM467.2 204.79999999999995L396.8 268.79999999999995c-102.4 102.4-102.4 262.4 0 364.8l179.2 179.2c102.4 102.4 262.4 102.4 364.8 0 102.4-102.4 102.4-262.4 0-364.8l-134.4-134.4-89.6 89.6 134.4 134.4c51.2 51.2 51.2 128 0 179.2-51.2 51.2-134.4 51.2-179.2 0L486.4 544c-51.2-51.2-51.2-128 0-179.2l70.4-70.4L467.2 204.79999999999995z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="face-smile-b" unicode="&#58960;" d="M511.931733-128c-136.738133 0-265.284267 53.213867-361.984 149.879467C53.282133 118.51093300000002 0 247.09119999999996 0 384c0 136.738133 53.282133 265.3184 150.050133 362.0864C246.749867 842.683733 375.296 896 512.136533 896s265.4208-53.316267 362.1888-149.9136c199.645867-199.714133 199.543467-524.5952 0-724.206933C777.454933-74.71786699999996 648.772267-128 511.931733-128L511.931733-128 511.931733-128 511.931733-128 511.931733-128 511.931733-128zM512.034133 829.303467c-118.920533 0-230.741333-46.2848-314.914133-130.389333C113.083733 614.8778669999999 66.7648 502.8864 66.7648 384c0-118.9888 46.2848-230.912 130.3552-315.016533 84.0704-84.0704 195.857067-130.321067 314.811733-130.321067 119.022933 0 230.946133 46.318933 315.016533 130.423467 173.704533 173.636267 173.704533 456.157867 0 629.794133C742.877867 782.984533 631.057067 829.303467 512.034133 829.303467L512.034133 829.303467 512.034133 829.303467 512.034133 829.303467 512.034133 829.303467 512.034133 829.303467zM330.103467 244.25813300000004c0 0 59.904-95.9488 181.828267-95.9488s201.8304 95.9488 201.8304 95.9488 45.294933 0.136533 45.192533-47.957333c0 0-78.506667-111.8208-247.022933-111.8208s-223.368533 111.8208-223.368533 111.8208S286.856533 244.25813300000004 330.103467 244.25813300000004L330.103467 244.25813300000004 330.103467 244.25813300000004 330.103467 244.25813300000004 330.103467 244.25813300000004zM363.2128 548.590933c-34.5088 0-62.702933-28.091733-62.702933-62.737067 0-34.679467 28.194133-62.6688 62.702933-62.6688 34.679467 0 62.702933 28.091733 62.702933 62.6688C425.915733 520.4992 397.858133 548.590933 363.2128 548.590933L363.2128 548.590933 363.2128 548.590933 363.2128 548.590933 363.2128 548.590933 363.2128 548.590933zM684.544 548.590933c-34.679467 0-62.702933-28.091733-62.702933-62.737067 0-34.679467 28.023467-62.6688 62.702933-62.6688 34.6112 0 62.600533 28.091733 62.600533 62.6688C747.144533 520.4992 719.121067 548.590933 684.544 548.590933L684.544 548.590933 684.544 548.590933 684.544 548.590933 684.544 548.590933 684.544 548.590933zM684.544 548.590933"  horiz-adv-x="1025" />
+      
+      <glyph glyph-name="align-center" unicode="&#58951;" d="M992 448L32 448C14.32 448 0 462.336 0 480 0 497.664 14.32 512 32 512L992 512C1009.68 512 1024 497.664 1024 480 1024 462.336 1009.68 448 992 448ZM800 704C817.664 704 832 689.664 832 672 832 654.336 817.664 640 800 640L224 640C206.32 640 192 654.336 192 672 192 689.664 206.32 704 224 704L800 704ZM992 832L32 832C14.32 832 0 846.336 0 864 0 881.664 14.32 896 32 896L992 896C1009.68 896 1024 881.664 1024 864 1024 846.336 1009.68 832 992 832ZM224 256C206.32 256 192 270.336 192 288 192 305.664 206.32 320 224 320L800 320C817.664 320 832 305.664 832 288 832 270.336 817.664 256 800 256L224 256ZM32 128L992 128C1009.68 128 1024 113.66399999999999 1024 96 1024 78.33600000000001 1009.68 64 992 64L32 64C14.32 64 0 78.33600000000001 0 96 0 113.66399999999999 14.32 128 32 128ZM224-64L800-64C817.664-64 832-78.33600000000001 832-96 832-113.66399999999999 817.664-128 800-128L224-128C206.32-128 192-113.66399999999999 192-96 192-78.33600000000001 206.32-64 224-64Z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="align-right" unicode="&#58952;" d="M992 64L32 64C14.32 64 0 78.33600000000001 0 96 0 113.66399999999999 14.32 128 32 128L992 128C1009.68 128 1024 113.66399999999999 1024 96 1024 78.33600000000001 1009.68 64 992 64ZM992 256L288 256C270.32 256 256 270.336 256 288 256 305.664 270.32 320 288 320L992 320C1009.68 320 1024 305.664 1024 288 1024 270.336 1009.68 256 992 256ZM992 448L32 448C14.32 448 0 462.336 0 480 0 497.664 14.32 512 32 512L992 512C1009.68 512 1024 497.664 1024 480 1024 462.336 1009.68 448 992 448ZM992 640L288 640C270.32 640 256 654.336 256 672 256 689.664 270.32 704 288 704L992 704C1009.68 704 1024 689.664 1024 672 1024 654.336 1009.68 640 992 640ZM992 832L32 832C14.32 832 0 846.336 0 864 0 881.664 14.32 896 32 896L992 896C1009.68 896 1024 881.664 1024 864 1024 846.336 1009.68 832 992 832ZM288-64L992-64C1009.68-64 1024-78.33600000000001 1024-96 1024-113.66399999999999 1009.68-128 992-128L288-128C270.32-128 256-113.66399999999999 256-96 256-78.33600000000001 270.32-64 288-64Z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="align-left" unicode="&#58953;" d="M992 448L32 448C14.336 448 0 462.336 0 480 0 497.664 14.336 512 32 512L992 512C1009.664 512 1024 497.664 1024 480 1024 462.336 1009.664 448 992 448ZM32 704L736 704C753.68 704 768 689.664 768 672 768 654.336 753.68 640 736 640L32 640C14.336 640 0 654.336 0 672 0 689.664 14.336 704 32 704ZM992 832L32 832C14.336 832 0 846.336 0 864 0 881.664 14.336 896 32 896L992 896C1009.664 896 1024 881.664 1024 864 1024 846.336 1009.664 832 992 832ZM32 320L736 320C753.68 320 768 305.664 768 288 768 270.336 753.68 256 736 256L32 256C14.336 256 0 270.336 0 288 0 305.664 14.336 320 32 320ZM32 128L992 128C1009.664 128 1024 113.66399999999999 1024 96 1024 78.33600000000001 1009.664 64 992 64L32 64C14.336 64 0 78.33600000000001 0 96 0 113.66399999999999 14.336 128 32 128ZM32-64L736-64C753.68-64 768-78.33600000000001 768-96 768-113.66399999999999 753.68-128 736-128L32-128C14.336-128 0-113.66399999999999 0-96 0-78.33600000000001 14.336-64 32-64Z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="fonts-u" unicode="&#58950;" d="M0-49.23076900000001L945.230769-49.23076900000001 945.230769-128 0-128 0-49.23076900000001ZM0 896L407.076943 896 407.076943 834.065644 319.153861 827.872177 299.076923 809.911217 299.076923 365.841959C299.076923 281.19796199999996 317.076716 220.709337 353.076933 184.37435100000005 389.077071 148.03936499999998 448.153442 129.87210800000003 530.307702 129.87210800000003 606.000364 129.87210800000003 660.807522 149.17482299999995 694.730752 187.78072599999996 728.653982 226.38662899999997 745.61536 289.66226700000004 745.61536 377.60953099999995L745.61536 804.956475 724.153817 826.633531 633.461524 834.065644 633.461524 896 955.384596 896 955.384596 834.065644 868.846119 826.633531 849.461563 804.956475 849.461563 364.60331299999996C849.461563 246.92743900000005 819.923338 161.66533900000002 760.846178 108.81441500000005 701.76894 55.96348999999998 606.462188 29.53846199999998 474.923087 29.53846199999998 406.153531 29.53846199999998 345.807951 38.51886300000001 293.884613 56.47990200000004 241.961275 74.44093999999996 201.230887 100.143419 171.692347 133.58820400000002 149.076834 160.01362700000004 133.038474 190.25793999999996 123.57695 224.32200899999998 114.115348 258.386078 109.384625 307.21047599999997 109.384625 370.796702L109.384625 809.911217 89.307687 827.872177 0 834.065644 0 896Z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="fonts-i" unicode="&#58948;" d="M897.948 834.255l0-64.322-128.65 0L447.674-1.9329999999999927l128.65 0 0-64.32L126.052-66.25300000000004l0 64.32 128.65 0 321.622 771.866-128.65 0L447.674 834.255 897.948 834.255z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="tabs" unicode="&#58922;" d="M310.30303 523.636364L124.121212 523.636364c-17.128727 0-31.030303-13.901576-31.030303-31.030303l0-186.181818c0-17.128727 13.901576-31.030303 31.030303-31.030303l186.181818 0c17.128727 0 31.030303 13.901576 31.030303 31.030303L341.333333 492.606061C341.333333 509.734788 327.431758 523.636364 310.30303 523.636364zM294.787879 306.42424200000005L139.636364 306.42424200000005c-17.128727 0-15.515152-1.613576-15.515152 15.515152L124.121212 477.090909c0 17.128727-1.613576 15.515152 15.515152 15.515152l155.151515 0c17.128727 0 15.515152 1.613576 15.515152-15.515152l0-155.151515C310.30303 304.81066699999997 311.916606 306.42424200000005 294.787879 306.42424200000005zM418.909091 352.969697l480.969697 0 0 31.030303L418.909091 384 418.909091 352.969697zM418.909091 228.84848499999998l480.969697 0 0 31.030303L418.909091 259.878788 418.909091 228.84848499999998zM418.909091 89.21212100000002l480.969697 0 0 31.030303L418.909091 120.24242400000003 418.909091 89.21212100000002zM418.909091 492.606061l480.969697 0 0 31.030303L418.909091 523.636364 418.909091 492.606061zM992.969697 725.333333l-15.515152 0L977.454545 849.454545c0 17.128727-13.901576 31.030303-31.030303 31.030303L775.757576 880.484848c-17.128727 0-31.030303-13.901576-31.030303-31.030303l0-124.121212-139.636364 0L605.090909 849.454545c0 17.128727-13.901576 31.030303-31.030303 31.030303L403.393939 880.484848c-17.128727 0-31.030303-13.901576-31.030303-31.030303l0-124.121212-124.121212 0L248.242424 849.454545c0 17.128727-13.901576 31.030303-31.030303 31.030303L31.030303 880.484848C13.901576 880.484848 0 866.583273 0 849.454545l0-946.424242c0-17.128727 13.901576-31.030303 31.030303-31.030303l961.939394 0c17.128727 0 31.030303 13.901576 31.030303 31.030303L1024 694.30303C1024 711.431758 1010.098424 725.333333 992.969697 725.333333zM992.969697-65.939394c0-17.128727-13.901576-31.030303-31.030303-31.030303L62.060606-96.969697c-17.128727 0-31.030303 13.901576-31.030303 31.030303L31.030303 818.424242c0 17.128727 13.901576 31.030303 31.030303 31.030303l124.121212 0c17.128727 0 31.030303-13.901576 31.030303-31.030303l0-124.121212 744.727273 0c17.128727 0 31.030303-13.901576 31.030303-31.030303L992.969697-65.939394z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="circle" unicode="&#58943;" d="M511.998 847.999C255.739 847.999 48 640.26 48 383.999c0-256.258 207.739-463.998 463.998-463.998C768.261-79.99900000000002 976 127.74199999999996 976 383.999 976 640.26 768.261 847.999 511.998 847.999zM512.002-16.000999999999976c-220.915 0-400.002 179.088-400.002 400 0 220.917 179.086 400 400.002 400 220.912 0 399.998-179.083 399.998-400C912 163.087 732.914-16.000999999999976 512.002-16.000999999999976z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="radio" unicode="&#58947;" d="M512.5 383.5m-192 0a192 192 0 1 1 384 0 192 192 0 1 1-384 0ZM511.998 847.999C255.739 847.999 48 640.26 48 383.999c0-256.258 207.739-463.998 463.998-463.998C768.261-79.99900000000002 976 127.74199999999996 976 383.999 976 640.26 768.261 847.999 511.998 847.999zM512.002-16.000999999999976c-220.915 0-400.002 179.088-400.002 400 0 220.917 179.086 400 400.002 400 220.912 0 399.998-179.083 399.998-400C912 163.087 732.914-16.000999999999976 512.002-16.000999999999976z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="share" unicode="&#58945;" d="M769.714 306.453c-51.754 0-97.702-24.851-126.571-63.269L394.479 367.94100000000003c3.93 13.798 6.034 28.364 6.034 43.424 0 16.496-2.527 32.399-7.211 47.35l247.724 124.288c28.71-40.052 75.647-66.151 128.687-66.151 87.388 0 158.229 70.84 158.229 158.229 0 87.388-70.841 158.229-158.229 158.229-87.389 0-158.229-70.841-158.229-158.229 0-6.046 0.352-12.009 1.011-17.88L351.22 526.116c-28.371 26.943-66.723 43.479-108.938 43.479-87.388 0-158.229-70.84-158.229-158.229s70.84-158.229 158.229-158.229c43.752 0 83.354 17.758 111.997 46.459l258.676-129.779c-0.964-7.062-1.474-14.266-1.474-21.592 0-87.389 70.84-158.229 158.229-158.229s158.229 70.84 158.229 158.229C927.938 235.61199999999997 857.103 306.453 769.714 306.453L769.714 306.453z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="edit" unicode="&#58946;" d="M769.089 516.251l-125.896 125.89 62.974 62.947c20.866 20.838 54.652 20.838 75.517 0l50.353-50.351c20.865-20.865 20.865-54.703 0-75.567L769.089 516.251zM403.349 150.52700000000004L277.453 276.418 619.706 615.982 745.601 490.09ZM176.314 47.283000000000015L252.912 251.87699999999995 377.753 127.01199999999994Z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="delete" unicode="&#58944;" d="M724.7403125 66.76999999999998h-423.70875c-25.5 0-46.2440625 20.2528125-46.2440625 45.1471875v391.8909375c0 24.88875 20.7459375 45.1378125 46.2440625 45.1378125h423.70875c25.5 0 46.2440625-20.248125 46.2440625-45.1378125v-391.8909375c0-24.8953125-20.7459375-45.1471875-46.2440625-45.1471875zM301.030625 507.6378125c-4.1690625 0-6.72-2.47875-6.72-3.82875v-391.8909375c0-1.3528125 2.551875-3.8371875 6.72-3.8371875h423.70875c4.17 0 6.72 2.4853125 6.72 3.8371875v391.8909375c0 1.35-2.551875 3.82875-6.72 3.82875h-423.70875zM812.1865625 509.283125h-600.3759375c-25.5009375 0-46.2440625 18.8728125-46.2440625 42.07125v57.2296875c0 23.19375 20.745 42.0628125 46.2440625 42.0628125h600.3759375c25.5 0 46.2440625-18.8690625 46.2440625-42.0628125v-57.2296875c0-23.1975-20.7459375-42.07125-46.2440625-42.07125zM205.0915625 551.4940624999999c0.3628125-0.6871875 2.551875-2.686875 6.72-2.686875h600.3759375c4.1671875 0 6.358125 1.99875 6.72 2.6878125v56.9446875c-0.3684375 0.69-2.5621875 2.6840625-6.72 2.6840625h-600.3759375c-4.1596875 0-6.3525-1.995-6.72-2.6840625v-56.945625zM595.20125 611.5193750000001h-163.636875c-25.5009375 0-46.2440625 18.871875-46.2440625 42.07125v10.065c0 23.19375 20.745 42.0628125 46.2440625 42.0628125h163.636875c25.5 0 46.2440625-18.868125 46.2440625-42.0628125v-10.065c0-23.1984375-20.745-42.07125-46.2440625-42.07125zM424.844375 653.729375c0.3628125-0.6871875 2.551875-2.6859375 6.72-2.6859375h163.636875c4.168125 0 6.358125 1.9978125 6.72 2.6859375v9.78c-0.3684375 0.69-2.563125 2.683125-6.72 2.683125h-163.636875c-4.1596875 0-6.3525-1.993125-6.72-2.683125v-9.78zM410.8428125 447.9059375h-28.2159375c-6.8409375 0-12.3871875-5.54625-12.3871875-12.3871875v-255.31875c0-6.8409375 5.54625-12.38625 12.3871875-12.38625h28.216875c6.8409375 0 12.38625 5.54625 12.38625 12.38625v255.3196875c0 6.8409375-5.54625 12.3871875-12.38625 12.3871875zM650.3590625 447.9059375h-28.2159375c-6.841875 0-12.3871875-5.54625-12.3871875-12.3871875v-255.31875c0-6.8409375 5.5471875-12.38625 12.3871875-12.38625h28.2159375c6.8409375 0 12.38625 5.54625 12.38625 12.38625v255.3196875c0 6.8409375-5.54625 12.3871875-12.38625 12.3871875zM530.6009375 447.9059375h-28.216875c-6.8409375 0-12.3871875-5.54625-12.3871875-12.3871875v-255.31875c0-6.8409375 5.5471875-12.38625 12.3871875-12.38625h28.216875c6.8409375 0 12.38625 5.54625 12.38625 12.38625v255.3196875c0 6.8409375-5.54625 12.3871875-12.38625 12.3871875z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="engine" unicode="&#58920;" d="M422.214332 360.70413299999996L186.183684 360.70413299999996l0 46.568461 236.030648 0c10.379577 40.075407 46.47537 69.794509 89.785668 69.794509 51.432433 0 93.067103-41.657943 93.067103-93.067103C605.067103 332.56756700000005 563.40916 290.909624 512 290.909624 468.689703 290.909624 432.593909 320.65199900000005 422.214332 360.70413299999996L422.214332 360.70413299999996zM512 779.634098c-218.529658 0-395.634098-177.10444-395.634098-395.634098 0-218.529658 177.10444-395.634098 395.634098-395.634098 154.76275 0 288.417257 89.064217 353.440885 218.55293l101.398692-59.112389-23.063141-39.959044-62.161099 35.909613c-33.745261-51.595341-77.42792-96.115813-129.093079-129.744711l35.653614-61.765464-40.308133-23.295867-35.653614 61.765464c-53.620057-27.345298-113.360805-44.404109-176.894987-47.73209L535.319139-127.99706800000001l-46.568461 0 0 70.981412c-63.534182 3.327981-123.27493 20.386792-176.894987 47.73209l-35.653614-61.765464-40.308133 23.295867 35.653614 61.765464c-51.665159 33.628898-95.347818 78.149371-129.093079 129.744711l-62.161099-35.909613-23.295867 40.308133 62.114553 35.863067c-27.415116 53.550239-44.799743 113.104807-48.127724 176.685534L0.002932 360.70413299999996l0 46.568461 70.958139 0c3.327981 63.580727 20.712609 123.135295 48.127724 176.685534l-62.114553 35.863067 23.295867 40.308133 62.161099-35.909613c33.745261 51.595341 77.42792 96.115813 129.093079 129.744711l-35.653614 61.765464 40.308133 23.295867 35.653614-61.765464c53.620057 27.345298 113.360805 44.404109 176.894987 47.73209L488.727406 895.997068l46.568461 0 0-70.981412c63.534182-3.327981 123.27493-20.386792 176.894987-47.73209l35.653614 61.765464 40.308133-23.295867-35.653614-61.765464c51.665159-33.628898 95.347818-78.149371 129.093079-129.744711l62.161099 35.909613 23.063141-39.959044-101.398692-59.112389C800.417257 690.569881 666.76275 779.634098 512 779.634098L512 779.634098z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="chart-screen" unicode="&#58921;" d="M963.930903 179.21903299999997l0 34.824133-37.354769-2.675946L926.576133 694.8538169999999 691.413206 694.8538169999999l0 70.462818L330.260819 765.316635l0-70.462818L95.690386 694.8538169999999l0-480.809627-35.621289 0 0-34.824133 432.583253 0 0-141.228535-90.313935 0 0-35.307134 216.753649 0 0 35.307134-90.313935 0L528.778128 179.21903299999997 963.930903 179.21903299999997zM366.212636 730.008478L655.216819 730.008478l0-35.307134L366.212636 694.7013440000001 366.212636 730.008478zM364.817869 332.73133600000006L222.224244 406.252817l14.295588 27.736715 123.238812-63.523779 173.928285 159.755494 127.5807-92.634794 93.13826 122.414027 12.420891-9.449209 12.420891-9.449209L667.639756 394.365068l-131.636063 95.621824L364.817869 332.73133600000006z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="chart" unicode="&#58924;" d="M953.440991 315.668729L784.061302 315.668729 681.06451 437.392024c-0.312108 0.373507-0.635473 0.737804-0.969071 1.094938-0.013303 0.014326-0.026606 0.027629-0.039909 0.041956-0.276293 0.293689-0.559748 0.582261-0.851391 0.86367-0.053212 0.051165-0.107447 0.099261-0.160659 0.150426-0.249687 0.237407-0.50142 0.470721-0.76134 0.697895-0.089028 0.078795-0.181125 0.153496-0.272199 0.230244-0.225127 0.191358-0.451278 0.381693-0.683569 0.565888-0.124843 0.099261-0.251733 0.192382-0.3776 0.288572-0.200568 0.153496-0.402159 0.306992-0.607844 0.454348-0.159636 0.11461-0.322341 0.224104-0.485047 0.334621-0.177032 0.12075-0.354064 0.242524-0.535189 0.35918-0.195451 0.12689-0.394996 0.246617-0.593518 0.367367-0.152473 0.092098-0.302899 0.186242-0.457418 0.275269-0.237407 0.137123-0.477884 0.268106-0.718361 0.397043-0.121773 0.065492-0.2415 0.132006-0.364297 0.195451-0.283456 0.146333-0.571005 0.285502-0.859577 0.420579-0.085958 0.040932-0.170892 0.082888-0.257873 0.122797-0.337691 0.154519-0.679475 0.298805-1.022283 0.437975-0.044002 0.017396-0.086981 0.036839-0.130983 0.055259-1.604544 0.638543-3.2623 1.113357-4.948709 1.416256-0.343831 0.062422-0.687662 0.112564-1.031493 0.160659-0.055259 0.008186-0.110517 0.01842-0.165776 0.025583-1.633197 0.216941-3.25923 0.26913-4.861728 0.173962-0.013303-0.001023-0.026606-0.001023-0.040932-0.002047-0.363274-0.022513-0.724501-0.054235-1.085728-0.091074-0.060375-0.00614-0.119727-0.011256-0.180102-0.017396-0.310062-0.034792-0.618077-0.077771-0.926092-0.122797-0.116657-0.017396-0.232291-0.032746-0.348947-0.051165-0.24764-0.040932-0.494257-0.086981-0.740874-0.135076-0.178055-0.033769-0.355087-0.067538-0.532119-0.105401-0.183172-0.039909-0.36532-0.083911-0.547469-0.127913-0.237407-0.056282-0.474814-0.113587-0.710175-0.176009-0.12075-0.032746-0.240477-0.068562-0.360204-0.102331-0.292666-0.082888-0.584308-0.168846-0.874927-0.26299-0.063445-0.020466-0.125867-0.042979-0.188288-0.063445-0.338714-0.112564-0.675382-0.230244-1.010003-0.357134-0.019443-0.007163-0.038886-0.01535-0.058328-0.022513-1.493004-0.571005-2.948145-1.284249-4.340865-2.149966-0.067538-0.041956-0.13303-0.088004-0.200568-0.12996-0.273223-0.172939-0.545422-0.346901-0.813528-0.531096-1.416256-0.971118-2.734274-2.089591-3.936659-3.333932-0.025583-0.026606-0.049119-0.053212-0.074701-0.079818-0.26299-0.275269-0.521886-0.555655-0.773619-0.843204-0.058328-0.066515-0.112564-0.134053-0.169869-0.200568-0.211824-0.246617-0.420579-0.496304-0.62217-0.751107-0.083911-0.106424-0.164752-0.214894-0.246617-0.322341-0.167822-0.218988-0.334621-0.437975-0.49528-0.663102-0.102331-0.14224-0.199545-0.287549-0.298805-0.431835-0.13303-0.194428-0.26606-0.387833-0.393973-0.586354-0.115634-0.179079-0.225127-0.360204-0.335644-0.541329-0.103354-0.168846-0.207731-0.336668-0.306992-0.508583-0.12689-0.220011-0.24764-0.443092-0.36839-0.666172-0.074701-0.138146-0.151449-0.275269-0.223081-0.416486-0.137123-0.265036-0.265036-0.533143-0.39295-0.802272-0.050142-0.105401-0.101307-0.209778-0.150426-0.316202-0.144286-0.317225-0.279363-0.63752-0.410346-0.958838-0.026606-0.064468-0.055259-0.127913-0.080841-0.193405-0.150426-0.378623-0.291642-0.760317-0.423649-1.14508-0.005117-0.016373-0.011256-0.031722-0.017396-0.048095-0.157589-0.463558-0.303922-0.930185-0.434905-1.400906l-97.897657-342.642824L435.093423 811.832042c-0.071631 0.569982-0.165776 1.13587-0.275269 1.696642-0.008186 0.040932-0.017396 0.081864-0.025583 0.12382-0.071631 0.356111-0.148379 0.709151-0.234337 1.061169-0.031722 0.128937-0.065492 0.255827-0.099261 0.38374-0.066515 0.254803-0.135076 0.508583-0.208754 0.760317-0.060375 0.206708-0.124843 0.411369-0.190335 0.615007-0.053212 0.166799-0.107447 0.332575-0.164752 0.49835-0.092098 0.26913-0.190335 0.535189-0.290619 0.800225-0.037862 0.098237-0.074701 0.196475-0.113587 0.293689-0.12382 0.313132-0.25378 0.623193-0.38988 0.930185-0.022513 0.050142-0.044002 0.100284-0.066515 0.150426-0.152473 0.338714-0.311085 0.672312-0.477884 1.00284-0.01228 0.024559-0.024559 0.049119-0.037862 0.074701-0.173962 0.343831-0.356111 0.682545-0.545422 1.017166-0.011256 0.019443-0.022513 0.039909-0.033769 0.059352-0.188288 0.330528-0.382717 0.654916-0.584308 0.975211-0.021489 0.034792-0.044002 0.068562-0.065492 0.103354-0.190335 0.298805-0.385786 0.592494-0.587378 0.88209-0.045025 0.065492-0.091074 0.12996-0.137123 0.194428-0.180102 0.252757-0.363274 0.502443-0.551562 0.74906-0.079818 0.105401-0.162706 0.208754-0.24457 0.312108-0.157589 0.199545-0.317225 0.396019-0.480954 0.590448-0.124843 0.149403-0.252757 0.295735-0.381693 0.442068-0.125867 0.14224-0.251733 0.284479-0.38067 0.424672-0.174985 0.191358-0.355087 0.378623-0.536212 0.563842-0.088004 0.090051-0.176009 0.180102-0.26606 0.26913-0.224104 0.222057-0.452301 0.440022-0.684592 0.653893-0.054235 0.050142-0.10847 0.100284-0.163729 0.150426-0.265036 0.240477-0.535189 0.474814-0.810459 0.704035-0.028653 0.023536-0.056282 0.047072-0.084934 0.070608-0.294712 0.243547-0.595564 0.479931-0.902556 0.711198-0.01535 0.011256-0.029676 0.022513-0.045025 0.033769-0.311085 0.232291-0.627287 0.458441-0.949628 0.677429-0.019443 0.013303-0.037862 0.025583-0.057305 0.038886-0.309038 0.208754-0.623193 0.411369-0.942465 0.606821-0.045025 0.027629-0.090051 0.054235-0.134053 0.081864-0.288572 0.174985-0.581238 0.343831-0.877997 0.50756-0.090051 0.050142-0.181125 0.098237-0.272199 0.147356-0.25071 0.134053-0.502443 0.265036-0.759293 0.391926-0.156566 0.077771-0.314155 0.151449-0.472767 0.226151-0.194428 0.091074-0.38988 0.182149-0.587378 0.268106-0.239454 0.105401-0.481977 0.204661-0.724501 0.302899-0.12382 0.049119-0.246617 0.100284-0.37146 0.148379-0.334621 0.128937-0.673335 0.249687-1.014096 0.36532-0.042979 0.014326-0.085958 0.029676-0.128937 0.044002-1.6158 0.536212-3.296069 0.915859-5.02034 1.119497-0.01535 0.002047-0.029676 0.004093-0.044002 0.00614-0.309038 0.035816-0.620124 0.062422-0.931209 0.086981-0.132006 0.010233-0.265036 0.025583-0.397043 0.033769-0.174985 0.011256-0.349971 0.01535-0.525979 0.022513-0.270153 0.01228-0.539282 0.024559-0.808412 0.027629-0.054235 0.001023-0.10847-0.001023-0.162706-0.001023-1.696642 0.010233-3.371794-0.149403-5.006014-0.466628-0.065492-0.01228-0.12996-0.027629-0.195451-0.039909-0.331551-0.067538-0.662079-0.13917-0.989537-0.218988-0.148379-0.035816-0.295735-0.075725-0.443092-0.11461-0.234337-0.061398-0.468674-0.124843-0.700965-0.192382-0.224104-0.065492-0.445138-0.135076-0.666172-0.206708-0.149403-0.048095-0.297782-0.096191-0.446162-0.147356-0.286526-0.098237-0.568958-0.201591-0.850367-0.309038-0.079818-0.030699-0.160659-0.061398-0.240477-0.093121-0.330528-0.12996-0.655939-0.267083-0.979304-0.410346-0.033769-0.01535-0.067538-0.029676-0.101307-0.045025-0.355087-0.159636-0.705058-0.325411-1.050935-0.500397-0.008186-0.004093-0.016373-0.008186-0.023536-0.01228-0.360204-0.182149-0.714268-0.372483-1.064238-0.569982-0.004093-0.002047-0.008186-0.005117-0.013303-0.007163-0.344854-0.196475-0.684592-0.399089-1.019213-0.610914-0.020466-0.013303-0.040932-0.025583-0.060375-0.038886-0.313132-0.199545-0.621147-0.404206-0.925069-0.61603-0.050142-0.034792-0.099261-0.070608-0.149403-0.105401-0.268106-0.190335-0.532119-0.38374-0.791016-0.583285-0.091074-0.069585-0.181125-0.141216-0.271176-0.212848-0.212848-0.167822-0.422625-0.337691-0.629333-0.512676-0.137123-0.11461-0.271176-0.232291-0.406253-0.349971-0.154519-0.1361-0.308015-0.272199-0.459464-0.412392-0.179079-0.164752-0.354064-0.332575-0.528026-0.502443-0.102331-0.100284-0.204661-0.199545-0.304945-0.301875-0.211824-0.212848-0.418532-0.430812-0.623193-0.651846-0.059352-0.064468-0.119727-0.128937-0.179079-0.194428-0.231267-0.254803-0.456395-0.515746-0.678452-0.780783-0.031722-0.037862-0.063445-0.075725-0.095167-0.11461-0.23536-0.285502-0.465604-0.577145-0.688685-0.874927-0.01842-0.024559-0.036839-0.048095-0.055259-0.072655-0.226151-0.301875-0.445138-0.60989-0.657986-0.923022-0.019443-0.028653-0.038886-0.057305-0.058328-0.084934-0.202615-0.300852-0.400113-0.606821-0.590448-0.916882-0.032746-0.053212-0.064468-0.105401-0.096191-0.158612-0.169869-0.282433-0.335644-0.567935-0.49528-0.857531-0.053212-0.097214-0.105401-0.194428-0.158612-0.292666-0.130983-0.24457-0.258896-0.490164-0.381693-0.73985-0.080841-0.162706-0.157589-0.326435-0.234337-0.491187-0.088004-0.189312-0.177032-0.378623-0.260943-0.571005-0.107447-0.245593-0.209778-0.493234-0.310062-0.741897-0.047072-0.11768-0.095167-0.234337-0.141216-0.354064-0.130983-0.340761-0.25378-0.684592-0.370437-1.030469-0.013303-0.037862-0.026606-0.075725-0.038886-0.113587-0.180102-0.543376-0.345877-1.092891-0.48914-1.650593L244.22942 305.59939599999996 67.355037 305.59939599999996c-14.128789 0-25.582655-11.453866-25.582655-25.582655s11.453866-25.582655 25.582655-25.582655l191.314257 0c0.867764 0 1.725294 0.044002 2.570545 0.128937 0.828878-0.080841 1.656733-0.1361 2.478448-0.1361 11.218506 0 21.512966 7.439436 24.644283 18.779715l113.358791 410.43686 103.412254-723.884758c0.00921-0.072655 0.021489-0.145309 0.030699-0.217964l0.046049-0.320295c0.002047-0.011256 0.005117-0.021489 0.00614-0.032746 0.109494-0.7552 0.25071-1.502213 0.425695-2.238994 0.01535-0.064468 0.031722-0.12689 0.047072-0.191358 0.166799-0.679475 0.358157-1.350764 0.579191-2.01182 0.041956-0.124843 0.088004-0.24764 0.130983-0.37146 0.210801-0.600681 0.437975-1.194198 0.692778-1.77646 0.068562-0.156566 0.144286-0.309038 0.215918-0.464581 0.223081-0.484024 0.460488-0.961908 0.713244-1.431605 0.106424-0.196475 0.213871-0.390903 0.325411-0.584308 0.265036-0.462534 0.545422-0.914836 0.838088-1.359974 0.088004-0.13303 0.170892-0.268106 0.260943-0.399089 0.354064-0.51677 0.732687-1.016143 1.12359-1.506307 0.078795-0.099261 0.156566-0.198521 0.237407-0.296759 0.420579-0.511653 0.864694-1.004887 1.325182-1.482771 0.051165-0.052189 0.101307-0.105401 0.152473-0.157589 0.494257-0.50449 1.010003-0.989537 1.548262-1.454118 0.00921-0.007163 0.017396-0.014326 0.026606-0.022513 1.636267-1.408069 3.466961-2.620687 5.466502-3.592828 0.075725-0.036839 0.151449-0.074701 0.228197-0.11154 0.576121-0.273223 1.165546-0.525979 1.768273-0.75827 0.158612-0.061398 0.319272-0.118704 0.478907-0.177032 0.558725-0.202615 1.124614-0.393973 1.704828-0.559748 0.005117-0.001023 0.010233-0.002047 0.01535-0.004093 0.278339-0.079818 0.562818-0.13917 0.844228-0.209778 0.394996-0.098237 0.789992-0.194428 1.184989-0.274246 0.283456-0.056282 0.568958-0.103354 0.854461-0.149403 0.445138-0.073678 0.889253-0.134053 1.333368-0.183172 0.229221-0.024559 0.456395-0.052189 0.686638-0.071631 0.710175-0.059352 1.418302-0.099261 2.122337-0.099261 0.337691 0 0.671289 0.027629 1.007957 0.040932 0.276293 0.011256 0.550539 0.013303 0.828878 0.033769 0.401136 0.029676 0.799202 0.079818 1.196245 0.127913 0.191358 0.022513 0.38067 0.033769 0.572028 0.061398 0.069585 0.010233 0.1361 0.024559 0.205685 0.034792 0.232291 0.034792 0.462534 0.075725 0.692778 0.116657 0.463558 0.082888 0.921999 0.176009 1.3743 0.283456 0.109494 0.025583 0.218988 0.047072 0.327458 0.074701 0.582261 0.145309 1.152243 0.316202 1.716084 0.499373 0.098237 0.031722 0.196475 0.063445 0.293689 0.097214 1.90335 0.644683 3.694135 1.50119 5.351891 2.540869 0.014326 0.00921 0.028653 0.01842 0.042979 0.027629 1.089821 0.686638 2.121314 1.452071 3.087315 2.287089 0.083911 0.071631 0.167822 0.143263 0.25071 0.215918 0.424672 0.3776 0.837064 0.76748 1.235131 1.170662 0.12382 0.124843 0.243547 0.254803 0.36532 0.382717 0.317225 0.334621 0.626263 0.677429 0.925069 1.028423 0.155543 0.183172 0.308015 0.36839 0.458441 0.556679 0.26606 0.331551 0.523933 0.670266 0.773619 1.01512 0.130983 0.180102 0.261966 0.35918 0.387833 0.543376 0.294712 0.429789 0.575098 0.86981 0.843204 1.316995 0.099261 0.165776 0.195451 0.334621 0.290619 0.503467 0.283456 0.499373 0.555655 1.004887 0.806365 1.52268 0.031722 0.065492 0.060375 0.13303 0.091074 0.199545 0.276293 0.584308 0.530073 1.178849 0.762363 1.784646 0.00614 0.017396 0.014326 0.034792 0.020466 0.051165 0.251733 0.661056 0.472767 1.336438 0.669242 2.020006 0.002047 0.008186 0.00614 0.016373 0.008186 0.024559l0.061398 0.215918c0.029676 0.106424 0.062422 0.210801 0.090051 0.317225l117.579929 411.527704 79.800487-94.308923c0.070608-0.083911 0.146333-0.161682 0.217964-0.243547 0.190335-0.220011 0.38374-0.436952 0.581238-0.649799 0.134053-0.144286 0.26913-0.285502 0.405229-0.425695 0.164752-0.168846 0.331551-0.335644 0.50142-0.500397 0.164752-0.159636 0.329505-0.319272 0.496304-0.473791 0.138146-0.12689 0.279363-0.25071 0.419556-0.37453 0.198521-0.174985 0.397043-0.350994 0.599657-0.518816 0.081864-0.067538 0.166799-0.132006 0.249687-0.198521 0.817622-0.661056 1.667989-1.264806 2.545986-1.811252 0.098237-0.061398 0.195451-0.125867 0.294712-0.185218 0.228197-0.138146 0.459464-0.267083 0.691755-0.398066 0.157589-0.089028 0.315178-0.178055 0.474814-0.264013 0.200568-0.107447 0.403183-0.208754 0.606821-0.311085 0.202615-0.101307 0.406253-0.201591 0.611937-0.297782 0.173962-0.080841 0.348947-0.159636 0.523933-0.237407 0.245593-0.10847 0.494257-0.212848 0.743944-0.313132 0.144286-0.058328 0.289596-0.115634 0.434905-0.171915 0.291642-0.11154 0.586354-0.216941 0.883113-0.317225 0.11154-0.037862 0.223081-0.076748 0.334621-0.113587 0.337691-0.109494 0.677429-0.210801 1.02126-0.305969 0.078795-0.021489 0.157589-0.046049 0.236384-0.066515 0.376577-0.101307 0.757247-0.193405 1.140986-0.277316 0.050142-0.011256 0.100284-0.023536 0.150426-0.034792 0.405229-0.085958 0.813528-0.162706 1.225921-0.229221 0.031722-0.005117 0.063445-0.01228 0.096191-0.017396 0.412392-0.065492 0.828878-0.12075 1.24741-0.165776 0.032746-0.004093 0.064468-0.00921 0.097214-0.01228 0.382717-0.039909 0.768503-0.068562 1.155313-0.092098 0.068562-0.004093 0.1361-0.01228 0.204661-0.01535 0.25992-0.013303 0.521886-0.01535 0.782829-0.020466 0.188288-0.004093 0.376577-0.01535 0.564865-0.01535 0.008186 0 0.01535 0.001023 0.023536 0.001023l181.208085 0c14.129812 0 25.582655 11.453866 25.582655 25.582655S967.56978 315.668729 953.440991 315.668729z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="table" unicode="&#58925;" d="M304.738028 343.684806M729.544153 511.153982M595.52788 637.723655M143.806755 686.614156l0-601.704045L881.172549 84.91011100000003l0 601.704045L143.806755 686.614156zM420.318416 299.80441299999995l0 128.936581 184.341448 0 0-128.936581L420.318416 299.80441299999995zM604.659865 256.825552l0-128.936581L420.318416 127.88897099999997l0 128.936581L604.659865 256.825552zM604.659865 600.656435l0-128.936581L420.318416 471.719854l0 128.936581L604.659865 600.656435zM374.232798 600.656435l0-128.936581L189.89135 471.719854l0 128.936581L374.232798 600.656435zM189.89135 428.740994L374.232798 428.740994l0-128.936581L189.89135 299.80441299999995 189.89135 428.740994zM650.745483 428.740994l184.341448 0 0-128.936581L650.745483 299.80441299999995 650.745483 428.740994zM650.745483 471.719854l0 128.936581 184.341448 0 0-128.936581L650.745483 471.719854zM189.89135 256.825552L374.232798 256.825552l0-128.936581L189.89135 127.88897099999997 189.89135 256.825552zM650.745483 127.88897099999997l0 128.936581 184.341448 0 0-128.936581L650.745483 127.88897099999997z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="tree" unicode="&#58926;" d="M962.691679 258.53447400000005c-8.721639 54.163597-34.298154 97.584526-73.089645 133.8638-44.721551 41.825594-99.282191 65.724911-156.512636 84.432994-26.935466 8.80555-54.079686 16.971533-81.129762 25.427112 41.188074 7.485485 81.495082 10.991332 121.872698 12.269441 39.906895 1.26276 79.885422 0.276293 120.633475 0.276293-30.644951 44.233434-74.588789 71.110571-127.260405 84.384899-53.004191 13.357216-103.742782 9.715269-152.261822-32.081673 18.715247 66.336848 12.464893 120.18936-38.810934 160.830989-32.450063 25.719778-77.127611 31.000038-111.319341 14.916734 58.583257-31.127951 82.051761-84.265172 94.304829-145.102772-44.638663 69.056795-110.067838 96.432283-187.710173 86.487793-56.123228-7.187703-110.723777-26.270317-166.003801-40.048111 15.677051-14.358009 31.136138-24.116257 47.932686-27.839045 51.427276-11.399631 103.405091-20.301372 155.098427-30.524201 37.036521-7.323802 75.163887-12.144598 104.448864-40.879036-78.096682 23.458271-155.928329 30.034037-235.541551 9.092076C186.718589 530.20385 104.838743 479.821369 81.996502 429.437865c46.955428 23.955598 95.807043 18.776645 144.606469 17.139356 37.737486-1.266853 76.089979-3.461845 113.238041 1.594311 52.683896 7.170307 104.513332 20.624736 159.209048 31.909757-91.88164-62.077847-186.516997-122.342396-159.194722-259.889075 58.852386 100.205213 163.392324 150.107763 229.951229 238.105956-16.239869-91.498924 6.980995-169.376619 66.432015-237.83785 41.815361-48.152696 89.979314-92.010577 110.706381-156.013263 12.758582 141.877311-25.823132 270.789333-97.911984 396.334677C755.996107 391.809873 858.199837 325.909977 962.691679 258.53447400000005zM513.476631 320.10169099999996c-27.767414-14.065344-39.008432-35.954887-42.252313-64.998363-6.078439-54.437843-15.162328-108.532879-21.799492-162.916487-3.90903-32.026414-5.519714-64.333214-8.16496-96.53052 30.078039 0 55.507198 0 79.961146 0 9.912767 78.200036 19.732413 154.247037 28.913517 230.369761 0.883113 7.322779-0.756223 15.746636-3.705392 22.591531C536.246217 272.25086999999996 524.967336 295.41135899999995 513.476631 320.10169099999996z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="upload-circle" unicode="&#58927;" d="M512-128c282.768 0 512 229.216 512 512C1024 666.768 794.768 896 512 896 229.216 896 0 666.768 0 384 0 101.21600000000001 229.216-128 512-128zM512 848c256.272 0 464-207.744 464-464 0-256.272-207.728-464-464-464S48 127.72799999999995 48 384C48 640.256 255.728 848 512 848zM377.728 534.544L480 534.544l0-478c0-17.664 14.336-32 32-32s32 14.336 32 32L544 534.544l102.272 0c17.616 0 23.424 11.568 12.944 25.68l-128.128 172.624c-10.496 14.128-27.664 14.128-38.16 0L364.8 560.24C354.32 546.1120000000001 360.128 534.544 377.728 534.544z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="templeate-1" unicode="&#58928;" d="M320 384L106.666667 384c-35.349333 0-64-28.650667-64-64l0-213.333333c0-35.349333 28.650667-64 64-64l213.333333 0c35.349333 0 64 28.650667 64 64L384 320C384 355.349333 355.349333 384 320 384zM256 341.33333300000004l0-256L170.666667 85.33333300000004 170.666667 341.33333300000004 256 341.33333300000004zM85.333333 106.66666699999996L85.333333 320c0 11.754667 9.578667 21.333333 21.333333 21.333333l42.666667 0 0-256L106.666667 85.33333300000004C94.912 85.33333300000004 85.333333 94.91200000000003 85.333333 106.66666699999996zM341.333333 106.66666699999996c0-11.754667-9.578667-21.333333-21.333333-21.333333l-42.666667 0L277.333333 341.33333300000004l42.666667 0c11.754667 0 21.333333-9.578667 21.333333-21.333333L341.333333 106.66666699999996zM576 554.666667L234.666667 554.666667c-47.061333 0-85.333333-38.272-85.333333-85.333333l0-42.666667 42.666667 0 0 42.666667c0 23.530667 19.136 42.666667 42.666667 42.666667l42.666667 0 0-96 21.333333 0L298.666667 512l213.333333 0 0-426.666667-85.333333 0-21.333333-42.666667 170.666667 0c47.061333 0 85.333333 38.272 85.333333 85.333333L661.333333 469.333333C661.333333 516.394667 623.061333 554.666667 576 554.666667zM618.666667 128c0-23.530667-19.136-42.666667-42.666667-42.666667l-42.666667 0L533.333333 512l42.666667 0c23.530667 0 42.666667-19.136 42.666667-42.666667L618.666667 128zM853.333333 42.66666699999996c47.061333 0 85.333333 38.272 85.333333 85.333333L938.666667 640c0 47.061333-38.272 85.333333-85.333333 85.333333L341.333333 725.333333c-47.061333 0-85.333333-38.272-85.333333-85.333333l0-42.666667 42.666667 0 0 42.666667c0 23.530667 19.136 42.666667 42.666667 42.666667l85.333333 0 0-85.333333 21.333333 0 0 85.333333 298.666667 0 0-597.333333-42.666667 0-21.333333-42.666667L853.333333 42.66666699999996zM896 128c0-23.530667-19.136-42.666667-42.666667-42.666667l-85.333333 0L768 682.666667l85.333333 0c23.530667 0 42.666667-19.136 42.666667-42.666667L896 128z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="util" unicode="&#58929;" d="M282.127566 639.0826059999999c-13.120832-13.221116-30.625508-20.50808-49.278333-20.50808-18.618033 0-36.157501 7.286963-49.311079 20.50808l-32.885991 33.019021 98.623181 99.027387 32.885991-33.019021c13.186324-13.221116 20.473287-30.829146 20.473287-49.548486C302.599829 669.8769589999999 295.347658 652.26893 282.127566 639.0826059999999L282.127566 639.0826059999999zM249.308089 705.0899489999999l-0.032746 0-32.884968-32.987299c4.418636-4.417613 10.252505-6.845918 16.458857-6.845918 6.206352 0 12.041244 2.428306 16.426111 6.813173 4.418636 4.452405 6.845918 10.288321 6.845918 16.493649C256.121262 694.802652 253.693979 700.671313 249.308089 705.0899489999999L249.308089 705.0899489999999zM396.703067 496.343671L249.578242 638.778684l32.278147 33.626865 147.157571-142.468782L396.703067 496.343671 396.703067 496.343671zM751.45979 133.92852400000004L618.131179 274.071332l32.884968 32.985252 133.330658-140.141784L751.45979 133.92852400000004 751.45979 133.92852400000004zM850.184279 67.95597399999997c-22.700001-22.766516-52.481282-34.168194-82.264609-34.168194-29.714765 0-59.395762 11.333116-81.994456 34.033118L538.194592 222.398462l32.884968 33.021068L718.811206 100.806149c27.117614-27.183106 71.269183-27.116591 98.488105 0.169869 27.186176 27.287483 27.117614 71.773673-0.135076 99.196233l-147.426701 154.273642 32.851199 33.021068 147.461493-154.308435C895.447159 187.557956 895.514697 113.421468 850.184279 67.95597399999997L850.184279 67.95597399999997zM801.716404 468.380806c-30.726815-30.860868-71.605851-47.861054-115.082038-47.861054-43.442418 0-84.321454 16.999163-115.082038 47.861054-30.760584 30.861892-47.692209 71.877027-47.692209 115.521037s16.931624 84.691891 47.692209 115.554806l42.497906 42.666752 32.885991-32.986275-42.497906-42.667775c-21.99085-22.090111-34.099632-51.367925-34.065863-82.566484 0-31.163767 12.108782-60.441581 34.065863-82.499969 21.956058-22.058388 51.16531-34.20094 82.196047-34.20094 31.064506 0 60.239989 12.142551 82.196047 34.20094l42.49893 42.665729 32.884968-33.019021L801.716404 468.380806 801.716404 468.380806zM844.214311 511.049604l-49.311079 49.51267-16.45988-16.493649c-17.538445-17.638729-40.879036-27.352975-65.73719-27.352975l-0.032746 0c-24.824385 0-48.198745 9.713222-65.73719 27.352975-17.539468 17.607006-27.252691 41.082674-27.252691 66.007343 0 24.925692 9.679453 48.400337 27.252691 66.040089l16.458857 16.495696-49.344848 49.51267 32.885991 33.021068 82.196047-82.533738-49.311079-49.482995c-8.769734-8.835226-13.626345-20.571525-13.626345-33.051767 0-12.446473 4.856611-24.183795 13.626345-32.987299 8.768711-8.835226 20.439518-13.69286 32.884968-13.69286 12.411681 0 24.082488 4.857635 32.852222 13.69286l49.344848 49.514717 82.196047-82.534761L844.214311 511.049604 844.214311 511.049604zM233.591129 129.139451l0 46.681182 46.512337 0 0-46.681182L233.591129 129.139451 233.591129 129.139451zM538.160823 356.538555l-92.247984 91.572602 32.717146 33.18889 92.214215-91.539856L538.160823 356.538555 538.160823 356.538555zM304.2187 101.04355599999997l173.634596 239.842507 37.641295-27.454282L338.318332 69.23715300000003c-21.923312-22.057365-51.132564-34.20094-82.19707-34.20094-31.028691 0-60.237943 12.143575-82.196047 34.168194-21.958104 22.057365-34.065863 51.335179-34.065863 82.533738 0 31.198559 12.107759 60.476373 34.065863 82.533738l2.765997 2.360767L417.243893 412.054963l27.353998-37.742603L205.596542 200.00340600000004c-12.411681-13.053294-19.224854-30.119995-19.224854-48.26526 0-18.71934 7.252171-36.291554 20.438495-49.513694C232.747925 76.15265599999998 277.775444 75.71263499999998 304.2187 101.04355599999997L304.2187 101.04355599999997z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="layouts" unicode="&#58930;" d="M917.213-103.239h-810.426c-23.151 0-41.918 18.766-41.918 41.917l0 698.644c0 23.148 18.767 41.917 41.918 41.917h810.426c23.149 0 41.918-18.769 41.918-41.917v-698.643c0-23.151-18.769-41.918-41.918-41.918zM316.38-61.321h600.833v363.294h-600.833v-363.294zM106.787-61.321h167.674v363.294h-167.674v-363.294zM148.705 637.322c-23.151 0-41.918-18.769-41.918-41.92s18.767-41.92 41.918-41.92 41.92 18.768 41.92 41.92-18.769 41.92-41.92 41.92zM274.461 637.322c-23.151 0-41.918-18.769-41.918-41.92s18.767-41.92 41.918-41.92c23.151 0 41.92 18.768 41.92 41.92s-18.77 41.92-41.92 41.92zM400.216 637.322c-23.15 0-41.918-18.769-41.918-41.92s18.769-41.92 41.918-41.92c23.152 0 41.92 18.768 41.92 41.92s-18.768 41.92-41.92 41.92zM875.293 511.566h-768.506v-167.675h810.426l0 167.675h-41.921z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="prev-circle" unicode="&#58931;" d="M508.638018 827.97307c-246.403458 0-446.845649-200.463469-446.845649-446.845649 0-246.382179 200.442191-446.845649 446.845649-446.845649 246.382179 0 446.845649 200.463469 446.845649 446.845649C955.483667 627.5096 755.041476 827.97307 508.638018 827.97307zM508.638018-23.16149900000005c-222.933422 0-404.28892 181.355498-404.28892 404.28892 0 222.933422 181.355498 404.28892 404.28892 404.28892 222.912144 0 404.28892-181.355498 404.28892-404.28892C912.926939 158.19399899999996 731.57144-23.16149900000005 508.638018-23.16149900000005zM252.87208 485.1999c8.639016 26.129831-32.470784 37.215859-41.067243 11.32009-27.810822-83.730363-22.321004-168.545923 14.086277-248.573851 11.362646-24.938243 48.025268-3.298146 36.747735 21.491148C230.976644 339.081373 228.806251 412.853462 252.87208 485.1999zM599.262572 247.73335499999996l-127.627629 133.394065 127.47868 133.223838c9.043305 9.064583 9.022026 23.789211-0.021278 32.832516-8.809243 8.830521-24.087108 8.766686-32.832516 0l-148.310199-148.310199c-4.617405-4.638683-6.979303-11.064749-6.553736-17.746156-0.404289-6.702685 1.936331-13.107472 6.575015-17.788712l148.310199-148.28892c4.383343-4.383343 10.213615-6.787798 16.405619-6.787798 6.170726 0 12.000997 2.404455 16.405619 6.787798C608.156928 224.114371 608.156928 238.83899899999994 599.262572 247.73335499999996z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="carousel" unicode="&#58932;" d="M1002.069333 144.38400000000001L1002.069333 611.6906670000001c0 24.213333-16.917333 49.578667-42.069333 49.578667l-64 0 1.152 6.4c0 31.338667-26.005333 57.6-58.538667 57.6L186.432 725.269333c-31.936 0-58.410667-31.957333-58.410667-64l-0.213333 0.96L67.178667 662.229333c-25.152 0-45.226667-20.288-45.226667-44.501333l0-467.328L21.354667 150.39999999999998c0-24.789333 20.629333-44.693333 45.312-44.693333L127.786667 105.70666700000004l0-5.184C127.786667 69.03466700000001 153.792 42.66666699999996 186.432 42.66666699999996l652.842667 0c31.658667 0 56.277333 10.901333 56.725333 42.602667l64 0c24.661333 0 42.666667 34.325333 42.666667 59.114667L1002.069333 144.38400000000001zM128 149.26933299999996L64 149.26933299999996l0 469.333333 64 0L128 149.26933299999996zM853.333333 106.602667c0-6.421333-14.848-21.333333-21.333333-21.333333l-640 0c-6.485333 0-21.333333 14.848-21.333333 21.333333l0 554.666667c0 6.378667 9.258667 18.56 15.744 18.56l5.589333 2.773333 640 0c6.442667 0 21.333333-14.954667 21.333333-21.333333L853.333333 106.602667zM960 127.93600000000004l-64 0 0 490.666667 60.842667 1.984c4.970667 0 3.157333 2.944 3.157333-1.984l0-469.333333C960 144.29866700000002 965.013333 127.93600000000004 960 127.93600000000004zM412.458667 399.829333c43.925333 0 79.637333 34.773333 79.637333 77.482667 0 42.752-35.712 77.482667-79.637333 77.482667-43.925333 0-79.637333-34.730667-79.637333-77.482667C332.8 434.602667 368.533333 399.829333 412.458667 399.829333zM412.458667 516.0533330000001c21.952 0 39.829333-17.365333 39.829333-38.741333 0-21.333333-17.877333-38.741333-39.829333-38.741333-21.952 0-39.829333 17.408-39.829333 38.741333C372.629333 498.709333 390.506667 516.0533330000001 412.458667 516.0533330000001zM785.92 457.386667c-95.914667-23.338667-137.728-87.765333-168.256-134.805333-24.213333-37.269333-39.082667-58.346667-65.109333-58.346667l-0.042667 0c-35.456 0-57.109333 14.272-80.042667 28.16-24.362667 14.741333-49.536 29.952-88.64 29.952-75.648 0-156.906667-93.269333-165.930667-103.893333L213.333333 167.38133300000004c0-10.709333 8.917333-18.112 19.925333-18.112l557.504 0c10.986667 0 19.904 7.402667 19.904 18.112L810.666667 438.570667c0 5.973333-2.837333 11.626667-7.658667 15.296C798.186667 457.536 791.872 458.858667 785.92 457.386667zM770.858667 188.52266699999996L253.162667 188.52266699999996c24.874667 27.733333 85.290667 95.082667 130.666667 95.082667 27.733333 0 46.229333-11.157333 67.605333-24.128 25.152-15.168 53.632-32.426667 99.712-33.941333l2.944-0.064c47.637333 0 71.722667 37.12 97.237333 76.416 26.645333 41.088 56.469333 79.104 119.530667 102.485333L770.858667 188.52266699999996z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="code-circle" unicode="&#58933;" d="M513.544163 893.525741c-282.101629 0-510.78094-228.679311-510.78094-510.76288 0-282.083569 228.679311-510.76288 510.78094-510.76288s510.76288 228.679311 510.76288 510.76288C1024.325103 664.8464309999999 795.645793 893.525741 513.544163 893.525741zM513.544163-83.46335899999997c-257.503523 0-466.22622 208.740757-466.22622 466.22622S256.0587 848.989082 513.544163 848.989082s466.22622-208.740757 466.22622-466.22622S771.047686-83.46335899999997 513.544163-83.46335899999997zM171.771357 359.77212099999997L414.357086 256.088033 414.357086 300.805295 221.978945 380.50532599999997 414.357086 459.464886 414.357086 504.182148 171.771357 401.76228ZM442.585309 193.38272800000004L478.814238 193.38272800000004 584.737801 572.1429949999999 548.743656 572.1429949999999ZM612.749301 504.182148L612.749301 459.464886 804.874598 380.50532599999997 612.749301 300.805295 612.749301 256.088033 855.33503 359.77212099999997 855.33503 401.76228Z"  horiz-adv-x="1025" />
+      
+      <glyph glyph-name="water" unicode="&#58934;" d="M862.315763 33.684211000000005C802.869868 33.684211000000005 754.526289 82.94399999999996 754.526289 143.50371900000005 754.526289 162.33094700000004 759.35885 180.96056099999998 768.520956 197.43438600000002 768.64671 197.79368399999998 768.808394 198.15298199999995 769.006008 198.49431600000003L849.075622 334.542596 849.057657 334.542596 862.315763 357.052632 875.573868 334.542596 875.573868 334.542596 955.140464 199.356632C955.715341 198.67396499999995 956.164464 197.865544 956.380043 196.96729800000003 965.380464 180.60126300000002 970.123201 162.151298 970.105236 143.50371900000005 970.105236 82.94399999999996 921.761657 33.684211000000005 862.315763 33.684211000000005L862.315763 33.684211000000005ZM924.33064 188.57768399999998C924.204885 188.79326300000002 924.115061 189.02680699999996 924.025236 189.27831600000002L862.315763 302.996211 800.606289 189.260351C800.516464 189.02680699999996 800.42664 188.79326300000002 800.300885 188.57768399999998 793.977236 176.505263 790.635763 162.81600000000003 790.635763 148.965053 790.635763 105.29235100000005 822.792956 69.75775399999998 862.333727 69.75775399999998 901.856534 69.75775399999998 933.995763 105.29235100000005 933.995763 148.98301800000002 933.995763 162.81600000000003 930.654289 176.52322800000002 924.33064 188.57768399999998L924.33064 188.57768399999998ZM682.684605 392.982456C593.50678 392.982456 520.982429 469.602807 520.982429 563.8108070000001 520.982429 593.093614 528.240254 622.071018 541.965447 647.706947 542.163061 648.281825 542.396605 648.820772 542.684043 649.341754L662.815412 860.968421 662.797447 860.968421 682.684605 896 702.571763 860.968421 702.535833 860.968421 821.89471 650.689123C822.774991 649.647158 823.439692 648.3716489999999 823.781026 646.970386 837.25471 621.514105 844.368815 592.8241399999999 844.35085 563.8108070000001 844.35085 469.602807 771.844464 392.982456 682.684605 392.982456L682.684605 392.982456ZM791.408254 630.1192980000001C791.21064 630.4965609999999 791.030991 630.891789 790.887271 631.322947L682.684605 823.924772 574.446008 631.287018C574.320254 630.891789 574.140605 630.4965609999999 573.942991 630.1013330000001 562.840675 609.6931930000001 556.912254 596.075789 556.912254 572.631579 556.912254 498.634105 613.375973 428.876351 682.684605 428.876351 751.993236 428.876351 808.367131 489.058807 808.367131 563.056281 808.367131 586.500491 802.492605 609.6931930000001 791.408254 630.1192980000001L791.408254 630.1192980000001ZM538.695833 276.983018C540.115061 275.330246 541.174991 273.33614 541.713938 271.12645599999996 563.433517 231.11859600000003 574.895131 186.02666699999997 574.895131 140.43171900000004 574.895131-7.581192999999985 458.051341-128 314.403903-128 170.738499-128 53.89471-7.581192999999985 53.89471 140.43171900000004 53.89471 186.47578899999996 65.589868 231.998877 87.704675 272.294175 88.010078 273.17445599999996 88.387341 274.01880700000004 88.872394 274.863158L282.408394 607.411649 282.372464 607.411649 314.403903 662.45614 346.453306 607.411649 346.399412 607.411649 538.695833 276.983018 538.695833 276.983018ZM314.403903 590.614456L119.807973 257.79649099999995C119.556464 257.113825 119.251061 256.449123 118.873798 255.78442099999995 98.932745 220.48336800000004 88.387341 180.42161399999998 88.387341 139.91073700000004 88.387341 12.072420999999963 189.799271-91.89052600000002 314.421868-91.89052600000002 439.026499-91.89052600000002 540.420464 12.072420999999963 540.402499 139.91073700000004 540.402499 180.42161399999998 529.857096 220.50133300000005 509.916043 255.78442099999995 509.53878 256.449123 509.233377 257.131789 508.963903 257.86835099999996L314.403903 590.614456 314.403903 590.614456Z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="date" unicode="&#58935;" d="M933.185668 758.3591759999999l-167.054737 0 0 56.506968L732.333174 814.866145l0-56.506968L539.505447 758.3591759999999l0 56.506968-33.796734 0 0-56.506968-216.255299 0 0 56.506968-33.796734 0 0-56.506968L88.005356 758.3591759999999c-12.255115 0-22.224164-9.970072-22.224164-22.224164l0-706.60521c0-12.255115 9.970072-22.225187 22.224164-22.225187l845.179288 0c12.255115 0 22.225187 9.970072 22.225187 22.225187L955.409832 736.135012C955.409832 748.389104 945.43976 758.3591759999999 933.185668 758.3591759999999zM939.036933 29.528778999999986c0-3.226484-2.62478-5.852288-5.852288-5.852288l-845.179288 0c-3.226484 0-5.851265 2.62478-5.851265 5.852288L82.154092 736.135012c0 3.226484 2.62478 5.851265 5.851265 5.851265l167.650301 0 0-55.657624 33.796734 0 0 55.657624 216.255299 0 0-55.657624 33.796734 0 0 55.657624L732.333174 741.986277l0-55.657624 33.796734 0 0 55.657624 167.054737 0c3.226484 0 5.852288-2.62478 5.852288-5.851265L939.036933 29.528778999999986zM206.835765 608.260623l129.098263 0 0-94.008071-129.098263 0 0 94.008071ZM458.879152 608.260623l129.098263 0 0-94.008071-129.098263 0 0 94.008071ZM684.827207 608.260623l129.098263 0 0-94.008071-129.098263 0 0 94.008071ZM206.835765 433.345871l129.098263 0 0-94.008071-129.098263 0 0 94.008071ZM458.879152 433.345871l129.098263 0 0-94.008071-129.098263 0 0 94.008071ZM684.827207 433.345871l129.098263 0 0-94.008071-129.098263 0 0 94.008071ZM206.835765 257.877511l129.098263 0 0-94.008071-129.098263 0 0 94.008071ZM458.879152 257.877511l129.098263 0 0-94.008071-129.098263 0 0 94.008071ZM684.827207 257.877511l129.098263 0 0-94.008071-129.098263 0 0 94.008071Z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="layer" unicode="&#58936;" d="M96.089 724.318l0-684.236 831.822 0L927.911 724.318 96.089 724.318zM884.178 84.457L140.464 84.457 140.464 489.559l743.714 0L884.178 84.457z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="fonts-clear" unicode="&#58937;" d="M944.787709 197.20939699999997L857.081297 197.20939699999997 741.092979-127.73993700000005 815.146059-127.73993700000005 832.440281-65.58476199999996 966.82809-65.58476199999996 984.512408-127.73993700000005 1062.011328-127.73993700000005 944.787709 197.20939699999997 944.787709 197.20939699999997ZM848.04409 1.1865400000000363L898.951519 153.25866699999995 949.923963 1.1865400000000363 848.04409 1.1865400000000363 848.04409 1.1865400000000363ZM210.238376 489.910857L183.386821 513.121524 12.46009 313.522794C-5.874386 292.652698-3.728862 260.989968 17.271265 242.720508 38.401424 224.45104800000001 70.454249 226.66158700000005 88.853741 247.53168300000004L100.361551 260.599873C106.603075 267.55657099999996 117.200662 268.20673 124.287392 262.22527 131.309106 256.048762 132.024281 245.51619000000005 125.912789 238.55949199999998 107.448281 217.62438099999997 98.085995 173.08850800000005 119.216154 154.81904799999995 140.281297 136.614603 183.841932 151.76330199999995 202.371455 172.69841299999996 208.417932 179.525079 219.145551 180.30526999999995 226.167265 174.19377799999995 233.188979 168.14730199999997 233.904154 157.61473 227.792662 150.65803200000005 209.328154 129.85295199999996 199.965868 85.05701599999998 221.096027 66.91758700000003 242.16117 48.648127000000045 285.656789 63.86184100000003 304.186313 84.666921 310.362821 91.62361899999996 321.025424 92.40381000000002 327.982122 86.29231700000003 335.068852 80.18082500000003 335.784027 69.71326999999997 329.672535 62.75657100000001 311.143011 41.82146 301.845741-2.9094599999999673 322.910884-20.983873000000017 344.041043-39.253333 387.601678-24.039619000000016 406.00117-3.234540000000038 412.177678 3.7221590000000333 422.840281 4.437332999999967 429.927011-1.6091430000000173 436.948725-7.720635000000016 437.598884-18.31822199999999 431.487392-25.144889000000035 413.022884-46.08000000000004 403.725614-90.81092100000001 424.790757-109.01536499999997 445.920916-127.15479400000004 477.973741-125.00927000000001 496.373233-104.20419000000004L667.299963 95.52457100000004 658.652852 132.90869799999996 210.238376 489.910857 210.238376 489.910857ZM844.013106 329.516698L680.10809 471.12127 929.639011 715.190857C933.2799 718.376635 936.725741 721.562413 939.976535 725.203302 977.815773 768.048762 973.524725 833.129651 930.28917 870.513778 887.183646 907.702857 821.58263 903.281778 783.808408 860.631365L783.483328 860.761397 564.249805 571.3107299999999 399.824662 713.56546C385.391138 726.113524 363.480789 724.553143 350.867709 710.249651L248.14263 593.871238 225.322059 567.994921 251.393424 545.434413 695.7119 161.25561900000002 726.26936 136.679619 847.328916 281.014857C859.941995 295.318349 858.44663 316.96863499999995 844.013106 329.516698L844.013106 329.516698ZM817.941741 830.724063C839.136916 854.779937 876.000916 857.315556 900.186821 836.250413 924.372725 815.380317 926.908344 778.906413 905.648154 754.85054 884.452979 730.924698 847.588979 728.389079 823.403075 749.3892060000001 799.21717 770.324317 796.811582 806.798222 817.941741 830.724063L817.941741 830.724063ZM765.473932 758.491429C768.919773 741.522286 777.6319 725.593397 791.80536 713.305397 806.043836 701.017397 823.533106 694.580825 841.087392 693.540571L643.634186 494.526984 593.116852 538.2176509999999 765.473932 758.491429 765.473932 758.491429ZM776.006503 299.739429L709.755328 219.314794 307.502122 566.369524 376.809043 645.03873C382.920535 651.865397 393.38809 652.5155560000001 400.409805 646.534095L774.381106 323.01511100000005C781.337805 317.098667 782.117995 306.69612700000005 776.006503 299.739429L776.006503 299.739429Z"  horiz-adv-x="1063" />
+      
+      <glyph glyph-name="dialogue" unicode="&#58938;" d="M998.4 500.992C998.4 682.24 811.392 829.696 581.632 829.696c-121.216 0-235.904-41.472-315.264-114.048 37.504 8.192 76.416 13.056 115.456 14.464 59.264 30.592 128.256 46.72 199.808 46.72 198.144 0 359.296-123.776 359.296-275.968 0-31.872-7.04-63.232-20.992-93.056 7.552-28.16 11.264-57.344 11.008-86.528C975.104 374.784 998.4 436.736 998.4 500.992L998.4 500.992zM442.368 398.72c-30.72 0-55.808-23.04-55.808-51.328s25.088-51.328 55.808-51.328 55.808 23.04 55.808 51.328S473.088 398.72 442.368 398.72zM243.328 398.72c-30.72 0-55.808-23.04-55.808-51.328s25.088-51.328 55.808-51.328 55.808 23.04 55.808 51.328C299.264 375.67999999999995 274.176 398.72 243.328 398.72zM641.28 398.72c-30.72 0-55.808-23.04-55.808-51.328s25.088-51.328 55.808-51.328 55.808 23.04 55.808 51.328S672.128 398.72 641.28 398.72zM442.368 677.888C212.608 677.888 25.6 530.432 25.6 349.312c0-179.968 173.696-296.192 332.544-321.664l60.8-78.336c5.632-7.424 14.464-11.008 23.296-11.008 8.832 0 17.792 3.712 23.424 11.008l60.8 78.464C685.312 53.24800000000005 859.008 169.47199999999998 859.008 349.44000000000005 859.136 530.432 672.128 677.888 442.368 677.888zM714.88 173.82399999999996c-52.224-45.184-124.288-77.952-197.376-89.6C503.168 81.91999999999996 490.112 74.24000000000001 481.28 62.72000000000003l-38.784-49.92-38.912 49.92c-8.96 11.52-21.888 19.2-36.224 21.504-73.216 11.776-145.152 44.416-197.376 89.728-39.68 34.304-86.912 92.544-86.912 175.36 0 69.76 35.584 136.192 100.352 187.264 68.736 54.144 160.768 84.096 258.944 84.096 98.304 0 190.336-29.824 259.072-84.096 64.768-51.072 100.352-117.504 100.352-187.264C801.664 266.36800000000005 754.56 208.12800000000004 714.88 173.82399999999996z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="cellphone-fine" unicode="&#58939;" d="M731.514252 896L292.485748 896C195.323702 896 116.154627 816.830925 116.154627 719.6688790000001l0-671.337759c0-97.162046 79.169075-176.331121 176.331121-176.331121l438.628661 0c97.162046 0 176.331121 79.169075 176.331121 176.331121L907.445529 719.6688790000001C907.845373 816.830925 828.676298 896 731.514252 896zM292.485748 853.216712l438.628661 0c70.772355 0 128.349863-55.178446 133.147989-124.751269L159.737602 728.465443C164.135884 798.038266 222.113237 853.216712 292.485748 853.216712zM865.062085 48.73096399999997c0-73.571261-59.976572-133.547833-133.547833-133.547833L292.485748-84.816868c-73.571261 0-133.547833 59.976572-133.547833 133.547833l0 45.582194 705.724326 0L864.662241 48.73096399999997zM865.062085 137.096447L158.937915 137.096447 158.937915 685.682155l705.724326 0L864.662241 137.096447zM512-54.82858299999998c13.59469 0 26.789535 5.597813 36.385787 15.194065 9.596251 9.596251 15.194065 22.791097 15.194065 36.385787 0 13.59469-5.597813 26.789535-15.194065 36.385787-9.596251 9.596251-22.791097 15.194065-36.385787 15.194065-13.59469 0-26.789535-5.597813-36.385787-15.194065-9.596251-9.596251-15.194065-22.791097-15.194065-36.385787 0-13.59469 5.597813-26.789535 15.194065-36.385787C485.210465-49.23076900000001 498.40531-54.82858299999998 512-54.82858299999998z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="form" unicode="&#58940;" d="M314.278111 437.019389l395.439892 0 0-30.297458-395.439892 0L314.278111 437.019389zM314.278111 315.83495200000004l395.439892 0 0-30.297458-395.439892 0L314.278111 315.83495200000004zM314.278111 194.62833l263.626661 0 0-30.297458L314.278111 164.330872 314.278111 194.62833zM609.376235 739.9931730000001c-7.849678 42.966669-48.394988 75.742447-97.378777 75.742447-48.961604 0-89.51311-32.775778-97.380776-75.742447L116.55177 739.9931730000001l0-787.725922 790.893774 0 0 787.725922L609.376235 739.9931730000001zM446.091342 670.440529l0 17.613058 0 36.791056c0 33.410348 29.57295 60.594317 65.906116 60.594317 36.352353 0 65.907115-27.183969 65.907115-60.594317l0-36.791056 0-17.621053 16.672696-8.712493c32.358061-16.929922 57.169039-42.663874 71.406386-73.213161L358.043239 588.50688c14.240345 30.555683 39.051523 56.281241 71.408385 73.213161L446.091342 670.440529zM874.489888-17.436289999999985L149.505227-17.436289999999985 149.505227 709.694715 413.138884 709.694715l0-21.641327c-51.44492-26.923746-88.727643-74.124144-98.86377-129.845165l395.44289 0c-10.102151 55.730615-47.40466 102.921419-98.859773 129.845165l0 21.641327 263.631658 0L874.489888-17.436289999999985z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="file" unicode="&#58913;" d="M887.443911 598.6304l0-44.578133 0-45.511111 0-477.866667c0-37.705956-30.560711-68.266667-68.266667-68.266667l-614.4 0c-37.705956 0-68.266667 30.560711-68.266667 68.266667l0 705.422222c0 37.6832 30.560711 68.266667 68.266667 68.266667l386.844444 0 45.511111 0 38.024533 0c7.805156 2.594133 16.566044 1.2288 22.778311-5.006222l183.136711-183.159467C885.919289 611.373511 887.876267 604.9564439999999 887.443911 598.6304zM659.888356 531.296711c-12.583822 0-22.755556 10.171733-22.755556 22.755556l0 204.8-45.511111 0-364.088889 0c-25.122133 0-45.511111-20.388978-45.511111-45.511111l0-659.911111c0-25.122133 20.388978-45.511111 45.511111-45.511111l568.888889 0c25.122133 0 45.511111 20.388978 45.511111 45.511111l0 455.111111 0 22.755556L659.888356 531.296711zM682.643911 750.273422l0-173.4656 159.288889 0 0 14.176711L682.643911 750.273422z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="triangle-r" unicode="&#58915;" d="M293.291 728.256l426.88-355.456-426.88-355.52z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="triangle-d" unicode="&#58917;" d="M773.128299 88.65234199999998M889.696178 575.195553L158.862147 575.195553 524.357446 209.64704300000005 889.696178 575.195553Z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="set-sm" unicode="&#58912;" d="M946.367 405.895c0.02 21.85-13.04 38.49-31.74 41.57-18.69 3.07-79.05 13.01-85.99 14.14-6.95 1.15-14.09 8.07-15.4 11.45-1.32 3.37-8.94 22.2-11.87 29.46-2.95 7.27-1.92 16.58 4.39 25.52 6.3 8.93 39.9 55.87 48.38 67.72 8.49 11.87 8.65 34.61-4.84 48.39-13.48 13.78-47.75 47.09-56.73 55.86-8.99 8.76-31.08 8.64-42.67 0.43-11.58-8.2-71.69-51.01-71.69-51.01s-9.97-6.89-20.67-2.64c-10.7 4.24-33.43 14.07-33.43 14.07s-7.19 5.43-9.68 19.79c-2.5 14.37-11.11 65.28-14.07 82.7-2.97 17.42-20.67 29.62-37.83 29.46-17.16-0.14-57.91 0-74.33 0s-32.26-15.68-34.75-29.46c-2.49-13.79-11.56-69.16-14.07-84.45-2.52-15.3-11.44-18.48-11.44-18.48s-19.56-8.06-29.91-12.31c-10.34-4.26-15.39-2.64-30.35 7.48-14.95 10.11-44.74 31.03-63.04 43.83-18.3 12.81-38.12 7.92-49.26-3.52s-36.06-35.77-51.02-50.43c-14.95-14.66-12.61-37.54 0.58-55.71 13.2-18.18 32.34-45.43 41.35-58.21 9.01-12.78 10.84-19.5 8.36-26.82-2.49-7.34-6.64-16.58-11.43-27.72-4.81-11.13-9.69-13.64-27.86-17.01-17.36-3.21-58.42-9.92-77.4-13.31-18.99-3.37-30.66-21.43-30.66-41.81l0-64.66c0-24.34 13.2-37.24 38.42-41.93 25.22-4.69 62.66-10.66 74.77-12.61 12.1-1.95 17.67-6.6 21.41-15.54 3.73-8.94 5.13-10.12 9.37-22.57 4.26-12.47 6.46-15.55-4.98-31.67-11.44-16.13-34.31-48.11-46.03-64.51-11.74-16.4-6.45-37.83 4.98-49.85 11.44-12.03 35.47-35.64 48.97-48.97 13.49-13.33 35.19-16.28 53.36-3.52 18.19 12.75 54.98 38.99 65.69 46.62 10.7 7.63 21.91 5.28 27.85 2.94 5.94-2.35 11.25-4.6 22-9.1 10.73-4.48 13.85-11.2 16.41-23.45 2.57-12.24 10.19-56.85 13.93-78.59 3.75-21.72 18.91-33.43 40.62-33.72 21.7-0.29 33.27-0.12 61.57 0 28.29 0.13 41.86 12.61 45.45 31.38 3.59 18.76 12.45 72.94 14.22 83.72 1.78 10.76 5.94 14.73 13.63 18.47 7.7 3.74 14.32 6.47 26.84 11.88 12.51 5.4 18.91 0.66 27.7-5.72 8.8-6.39 47.51-33.78 63.78-45.31 16.28-11.53 36.73-10.33 51.9 4.4 15.18 14.73 31.62 30.99 49.27 48.38 17.64 17.4 12.16 39.59 4.4 51.46-7.77 11.88-44.49 62.95-49.71 70.23-5.21 7.28-4.4 18.62-1.75 24.63 2.64 6.01 8.44 18.24 11.72 25.22 3.29 6.97 9.6 11.22 18.18 12.9 8.58 1.69 62.72 11 83.75 14.61 21.03 3.64 31.11 19.92 31.26 39.92C946.427 359.93499999999995 946.347 388.525 946.367 405.895zM908.587 338.615c0.21-5.76-4.66-10.65-8.82-11.38-4.17-0.73-63.26-11.38-81.48-14.29-18.21-2.92-33.23-15.07-38.72-28.06-3.98-9.44-5.47-13.51-10.59-26.96-5.12-13.44-4.64-32.19 2.56-42.26 7.2-10.08 46.82-64.9 50.38-70.45s4.27-11.95-1.28-17.5-40.99-41.2-47.39-47.39c-6.41-6.19-11.83-4.8-18.79 0-6.95 4.8-39.61 26.39-64.44 44.36-16.96 12.28-32.82 12.43-48.7 6.02-15.87-6.42 1.28 0.28-22.2-8.97-23.48-9.25-30.23-27.62-33.73-48.24-3.5-20.63-10.67-62.98-11.95-70.45-1.28-7.47-5.55-11.1-13.66-11.1l-64.9 0c-8.11 0-11.74 2.99-14.52 11.95-2.77 8.97-10.03 54.87-12.8 74.29-2.78 19.43-13.82 36.12-24.77 40.56-10.94 4.45-4.98 2.14-27.32 11.1-22.34 8.97-39.63 4.5-51.23-3.84-11.61-8.34-58.64-42.69-65.33-46.96-6.68-4.28-14.65-3.28-18.35 0.42-3.7 3.7-40.56 40.56-46.54 46.54-5.98 5.98-5.36 12.92 0 20.49 5.36 7.58 28.39 40.76 40.99 57.95 12.59 17.2 17.93 34.74 9.82 53.49-8.12 18.74-4.42 10.24-12.39 28.6-7.96 18.36-24.28 24.46-38.42 26.9-14.14 2.43-68.88 11.53-76.85 13.23-7.97 1.71-11.95 7.26-11.95 14.09l0 66.18c0 9.53 7.67 12.44 12.38 13.23 4.7 0.8 54.22 9.18 73 12.39 18.79 3.2 36.36 11.32 43.55 29.03 7.19 17.7 4.27 11.1 11.1 27.32 6.83 16.23 3.8 33.94-7.68 49.96-11.49 16.01-38.85 54-44.4 61.9-5.55 7.9-5.77 12.6 0.85 19.21 6.62 6.62 42.05 42.48 46.96 46.97 4.91 4.48 12.07 5.4 18.36 0.85 6.3-4.55 49.31-35.65 64.04-46.11 14.73-10.46 32.35-12.56 49.1-5.55 16.75 7.02 10.25 4.48 26.9 11.1s24.84 19.09 28.18 39.71c3.33 20.61 11.95 74.14 12.81 77.7 0.85 3.55 5.55 10.46 11.74 10.46s65.82-0.07 69.8 0c3.99 0.07 10.3-3.29 11.32-9.18 1.02-5.9 13.02-74.29 14.94-86.25 1.92-11.95 15.58-28.57 25.54-32.73 9.96-4.16 21.35-8.75 31.31-13.09 9.97-4.34 30.13-1.91 36.15 2.28 6.03 4.18 70.52 48.81 75.43 52.37 4.91 3.56 11.52 3.27 17.64-2.85s43.34-43.19 47.54-47.53c4.19-4.34 4.66-8.66 1.14-13.66-3.53-5.01-36.72-51.8-47.54-67.46-10.81-15.65-11.73-33.73-5.41-48.96 6.33-15.22 3.99-9.39 9.11-21.91 5.13-12.53 16.28-29.03 33.59-31.88 17.31-2.85 76.92-12.74 84.82-13.95 7.9-1.21 11.1-7.18 11.1-13.37S908.377 344.385 908.587 338.615zM526.833 573.1949999999999c-110.45 0-200-89.54-200-200s89.55-200 200-200c110.46 0 200 89.54 200 200S637.293 573.1949999999999 526.833 573.1949999999999zM526.833 208.19500000000005c-91.12 0-165 73.87-165 165s73.88 165 165 165c91.13 0 165-73.87 165-165S617.963 208.19500000000005 526.833 208.19500000000005z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="add-circle" unicode="&#58911;" d="M675.04 412.736l-127.04 0 0 127.264c0 20.064-16.288 36.32-36.32 36.32-20.064 0-36.32-16.192-36.32-36.32l0-127.232-127.072 0c-20.064 0-36.352-16.32-36.352-36.352 0-20.064 16.224-36.352 36.352-36.352l127.072 0 0-127.232c0-20 16.256-36.384 36.32-36.384 20.032 0 36.32 16.256 36.32 36.384l0 127.136 127.04 0c19.968 0 36.352 16.256 36.352 36.384C711.36 396.448 695.136 412.736 675.04 412.736L675.04 412.736zM511.328 830.56c-250.24 0-453.952-203.616-453.952-453.952 0-250.336 203.712-453.952 453.952-453.952 250.336 0 453.984 203.584 453.984 453.952C965.312 626.944 761.696 830.56 511.328 830.56L511.328 830.56zM511.328-20.576000000000022c-219.04 0-397.184 178.176-397.184 397.152 0 219.104 178.144 397.216 397.184 397.216s397.216-178.112 397.216-397.216C908.576 157.63199999999995 730.368-20.576000000000022 511.328-20.576000000000022L511.328-20.576000000000022zM511.328-20.576000000000022"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="layim-download" unicode="&#58910;" d="M186.888458 77.07363199999998l0 581.729108c14.85022-14.450107 35.050284-23.436782 57.359382-23.436782l560.03604 0 0-151.561881 25.029046 0 0 176.591951-585.065086 0c-31.191396 0-57.359382 26.166963-57.359382 57.359382 0 31.191396 26.165939 57.359382 57.359382 57.359382l572.551074 0L816.798914 800.143838 244.24784 800.143838c-45.431725 0-82.388429-36.957727-82.388429-82.388429l0-640.681778c0-41.796942 34.000372-75.789127 75.789127-75.789127l225.950102 0 0 25.029046L237.648538 26.31355099999996C209.661114 26.31355099999996 186.888458 49.078021000000035 186.888458 77.07363199999998zM236.947574 730.269421l560.38601 0 0-25.029046-560.38601 0 0 25.029046ZM686.086897 428.171012c-85.917812 0-164.908864-55.248302-194.553021-135.882783-30.013571-81.641415-4.269233-175.567621 62.624293-230.942813 67.00302-55.465243 164.474982-62.808488 238.931764-17.720593 74.094532 44.868907 113.272833 133.533272 96.080266 218.517829C869.882923 357.47283300000004 783.297916 428.171012 686.086897 428.171012zM686.086897 38.82858599999997c-75.595722 0-145.060817 48.634674-171.092703 119.595842-26.354228 71.839165-3.63069 154.438395 55.287187 203.074092 59.017138 48.718585 144.762011 55.029314 210.191186 15.237029 65.11195-39.59888 99.396801-117.681236 84.064604-192.408171C847.384513 100.72940100000005 771.387655 38.82858599999997 686.086897 38.82858599999997zM698.600909 152.23547199999996L698.600909 311.02496499999995 673.571862 311.02496499999995 673.571862 152.28459099999998 604.675726 221.17254100000002 586.978668 203.47548400000005 686.111456 104.35190499999999 785.185916 203.42738799999995 767.489882 221.123422Z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="layim-uploadfile" unicode="&#58909;" d="M914.7359263333336 663.0359498888887c-20.806884999999987 20.806885000000012-48.471967999999976 32.265868000000026-77.89816099999994 32.265868000000054l-352.221993 2.2737367544323206e-13-120.26099099999992 95.03035300000005-11.157106999999995 8.816806000000007-14.220886 9.769962616701378e-15L197.09333633333344 799.148976888889c-51.69538300000001 2.1316282072803006e-14-93.75224400000005-42.88778599999995-93.75224400000006-95.60442799999993l-1.5631940186722204e-13-255.13888799999998c-1.7763568394002505e-15-2.302439 0.08391099999999785-4.716417999999999 0.24968699999999489-7.196911999999999l-1.9895196601282805e-13-340.692403c-1.9539925233402755e-14-29.426192999999998 11.458982999999954-57.09127599999999 32.26586799999994-77.89816100000002 20.806884999999987-20.806885000000012 48.471967999999976-32.265868000000026 77.89816099999994-32.265868000000054l623.083981-3.410605131648481e-13c29.426192999999998-1.9539925233402755e-14 57.09127599999999 11.458982999999954 77.89816100000002 32.26586799999994 20.806885000000012 20.806884999999987 32.265868000000026 48.471967999999976 32.265868000000054 77.89816099999994L947.0028173333335 585.1377888888885C947.0017943333336 614.5639818888885 935.5428113333334 642.2280418888886 914.7359263333336 663.0359498888887zM197.09333633333372 758.2167298888891l141.88345099999998-8.526512829121202e-14L470.3948853333333 654.369569888889l366.44287999999995-2.2737367544323206e-13c38.236859-2.1316282072803006e-14 69.23178099999997-30.99492100000004 69.23178099999994-69.23178100000004L906.0695463333333 465.9195468888886 144.27334033333327 465.91954688888893 144.2733403333336 703.5445488888892C144.2733403333336 733.7361748888891 167.92296933333355 758.2167298888891 197.09333633333372 758.2167298888891zM836.8377653333331 31.28558888888881L213.75480733333322 31.28558888888915c-38.236859 2.1316282072803006e-14-69.23178099999997 30.99492100000004-69.23178099999994 69.23178100000004L144.52302633333338 424.4776928888892l761.546519-6.252776074688882e-13-2.2737367544323206e-13-323.96134599999993C906.0695463333333 62.28050988888867 875.0746243333334 31.285588888888583 836.8377653333331 31.28558888888881z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="404" unicode="&#58908;" d="M300.197309 299.705317l4.427931 1.803972c1.147982-2.787956 10.167841-7.543882 26.89558-14.267777l5.411915-12.955798c10.659833-24.927611 23.123639-62.483024 37.555413-112.66624 14.431775 5.575913 34.439462 0.983985 60.351057-13.611787l1.803972-4.427931L389.575913 107.828315l18.203716-42.639334c2.459962-5.575913-12.463805-15.579757-44.7713-29.847534-11.151826 7.215887-19.84369 9.675849-26.403587 7.05189l-0.983985 2.131967c-10.823831 25.419603-16.235746 42.311339-16.399744 50.675208l-4.427931-1.803972 6.3959-14.923767-11.151826-4.263933c-41.655349-16.235746-71.830878-18.695708-90.690583-7.871877l-4.427931-1.803972-1.803972 4.263933c-7.05189 16.727739 3.607944 77.406791 32.307495 182.037156 11.479821 4.427931 19.1877 14.923767 22.959641 31.323511C281.337604 290.685458 291.83344 296.425368 300.197309 299.705317L300.197309 299.705317zM216.230621 80.276746c28.371557 19.515695 40.999359 32.799488 38.047406 39.68738-0.983985 2.131967-0.65599 5.575913 0.65599 10.167841l-0.983985 2.131967c-25.5836-21.483664-38.047406-32.963485-37.391416-34.439462C215.246637 88.804612 215.082639 83.064702 216.230621 80.276746L216.230621 80.276746zM216.722614 72.896861l0.983985-2.131967c11.643818 1.147982 21.155669 3.279949 28.699552 6.231903 0.819987 0.327995 7.379885 5.411915 19.84369 15.251762l-0.983985 2.131967c-7.543882-2.951954-12.7918-0.983985-15.743754 6.067905C226.398463 85.032671 215.574632 75.848815 216.722614 72.896861L216.722614 72.896861zM225.90647 143.743754l11.151826 4.263933c-1.147982-2.623959-6.3959-8.691864-15.579757-18.53171-2.295964-10.823831-2.787956-17.547726-1.639974-20.335682 27.715567 20.663677 40.34337 33.783472 37.883408 39.523382l0.819987 10.331839-3.443946-3.935939-9.019859-3.443946-0.983985 2.131967c11.151826 4.263933 17.875721 16.891736 20.49968 37.719411l-0.983985 2.131967C239.35426 172.443306 227.21845 160.307495 227.874439 157.027546L225.90647 143.743754 225.90647 143.743754zM231.646381 173.42729l0.983985-2.131967 2.131967 0.819987c28.371557 23.123639 40.179372 40.179372 35.423447 51.331198 1.475977 0.65599 1.967969 1.639974 1.475977 2.951954l-2.295964-0.819987c-28.863549-21.647662-40.999359-38.047406-36.407431-49.035234C231.482383 175.723254 230.990391 174.73927 231.646381 173.42729L231.646381 173.42729zM240.994234 211.966688l0.983985-2.131967c13.775785 10.331839 35.915439 29.847534 66.418962 58.21909l2.131967 0.819987-6.3959 14.923767 0.491992 5.083921-2.295964-0.819987c-36.571429-32.963485-55.431134-51.82319-56.579116-56.743113L240.994234 211.966688 240.994234 211.966688zM311.67713 107.336323l-35.751441-13.939782c-1.475977-0.491992-6.887892-4.263933-16.235746-11.315823l0.819987-1.967969 12.299808 2.131967 20.007687 7.871877c11.643818 4.591928 32.143498 19.84369 61.171044 46.08328l-6.3959 14.923767-2.131967-0.819987c-24.107623-16.891736-34.439462-29.191544-31.159513-36.899423C315.449071 110.616272 314.629084 108.484305 311.67713 107.336323L311.67713 107.336323zM267.889814 264.773863l0.819987-1.967969c17.875721 16.891736 27.387572 25.419603 28.207559 25.747598l-0.983985 2.131967-8.855862-3.443946C274.941704 282.485586 268.545804 274.941704 267.889814 264.773863L267.889814 264.773863zM275.597694 222.954516c16.071749-37.883408 20.007687-67.894939 11.971813-90.034593l-3.443946-28.863549 26.89558 10.495836c-7.543882 30.011531-18.367713 65.598975-32.471493 106.926329l-0.983985 2.131967L275.597694 222.954516 275.597694 222.954516zM279.369635 231.810378l6.3959-14.923767c13.44779 15.087764 24.435618 24.271621 32.63549 27.55157l-3.607944 8.527867-2.459962 11.643818-2.131967-0.819987C289.045484 247.06214 278.713645 236.566304 279.369635 231.810378L279.369635 231.810378zM292.817425 194.58296c23.943626 17.219731 33.619475 30.995516 29.191544 41.491352l-2.787956 6.3959-2.295964-0.819987c-21.483664-18.859705-30.667521-31.651505-27.879564-38.3754L292.817425 194.58296 292.817425 194.58296zM294.457399 190.483024l2.787956-6.3959 2.295964-11.807816 2.295964 0.819987-0.491992-5.083921 6.3959-14.923767 32.471493 27.387572-6.3959 15.087764c-9.347854-10.331839-16.235746-16.399744-20.827675-18.203716l-2.295964-0.983985c-0.65599 1.639974 6.067905 10.167841 20.335682 25.419603l-3.115951 13.611787-0.983985 2.131967L294.457399 190.483024 294.457399 190.483024zM307.413197 148.171685l2.787956-6.3959 2.295964-11.643818c23.943626 17.219731 35.259449 27.387572 33.94747 30.503523l-5.411915 12.955798C329.224856 165.719411 318.07303 157.191544 307.413197 148.171685L307.413197 148.171685zM355.792441 131.935939c-23.779628-17.711723-34.111467-30.011531-30.995516-37.227418l1.475977-9.347854c25.255605 18.039718 36.899423 29.355541 34.931454 33.783472 24.435618 21.155669 38.703395 32.471493 42.803331 33.94747l-0.819987 1.967969c-1.803972 2.787956-6.723895 4.099936-14.595772 4.427931l-30.831518-31.9795L355.792441 131.935939 355.792441 131.935939zM327.912876 81.26073l4.591928-10.659833-0.491992-5.083921 2.295964 0.819987c23.451634 14.595772 34.275464 23.615631 32.63549 27.55157l-5.411915 12.955798L327.912876 81.26073 327.912876 81.26073zM333.816784 61.253043l5.411915-12.7918c25.747598 13.283792 37.719411 22.139654 35.915439 26.403587l-4.591928 10.659833C348.412556 70.272902 336.112748 62.237028 333.816784 61.253043L333.816784 61.253043zM357.596413 139.971813l1.803972-4.099936c4.919923 1.967969 8.527867 9.839846 10.823831 23.943626l-2.295964-0.819987C364.648302 147.679693 361.204356 141.44779 357.596413 139.971813L357.596413 139.971813zM731.674568 256.081999l3.935939-0.163997c-0.163997-2.459962 4.755926-9.019859 14.759769-19.515695l-0.65599-11.315823c-1.147982-21.975657-5.411915-53.955157-12.955798-95.774504 12.627803-0.65599 25.911595-10.659833 39.68738-30.175529l-0.163997-3.935939-47.887252-10.823831-1.967969-37.719411c-0.327995-4.919923-14.923767-7.379885-43.951313-7.379885-5.575913 9.019859-11.151826 13.775785-16.891736 13.939782l0.163997 1.967969c1.147982 22.467649 3.279949 36.735426 6.231903 42.967329l-3.935939 0.163997-0.65599-13.119795-9.839846 0.491992c-36.571429 1.803972-60.023062 9.839846-70.026906 24.271621l-3.935939 0.163997 0.163997 3.771941c0.819987 14.759769 30.667521 56.087124 89.706598 124.14606 10.167841-0.491992 19.515695 4.755926 28.371557 15.579757C714.290839 255.754004 724.294683 256.573991 731.674568 256.081999L731.674568 256.081999zM587.848815 115.86419l-0.163997-1.967969c9.019859-2.951954 16.891736-4.591928 23.615631-4.919923 0.65599 0 7.379885 1.475977 20.171685 4.755926l0.163997 1.967969c-6.723895 0.327995-9.839846 3.607944-9.511851 9.675849C599.328635 121.6041 588.012812 118.324151 587.848815 115.86419L587.848815 115.86419zM590.144779 121.440102c28.043562 5.083921 42.147341 10.659833 42.475336 16.727739 0.163997 1.803972 1.475977 4.263933 4.099936 7.215887l0.163997 1.967969c-26.731582-7.379885-40.015375-11.807816-40.179372-13.119795C592.440743 128.163997 590.308776 123.900064 590.144779 121.440102L590.144779 121.440102zM620.15631 165.227418l9.839846-0.491992c-1.803972-1.475977-7.871877-4.427931-18.367713-8.527867-5.575913-7.215887-8.527867-12.13581-8.527867-14.595772 28.043562 6.067905 42.147341 11.643818 42.311339 16.727739l4.263933 7.379885-3.935939-1.803972-8.035874 0.327995 0.163997 1.967969c9.839846-0.491992 19.351698 6.559898 28.863549 21.155669l0.163997 1.967969c-26.23959-7.379885-39.68738-12.463805-40.34337-14.923767L620.15631 165.227418 620.15631 165.227418zM670.667521 109.960282l-31.487508 1.475977c-1.31198 0-6.559898-0.983985-16.071749-2.951954l-0.163997-1.803972 9.839846-2.459962 17.711723-0.819987c10.331839-0.491992 30.995516 4.099936 61.991031 13.939782l0.65599 13.119795-1.803972 0.163997c-23.943626-4.591928-36.079436-10.167841-36.407431-16.891736C674.603459 110.944266 673.29148 109.796284 670.667521 109.960282L670.667521 109.960282zM635.244074 185.399103l-0.163997-1.967969 1.803972-0.163997c29.355541 7.70788 44.279308 16.563741 44.7713 26.23959 1.31198 0 2.131967 0.491992 2.131967 1.639974l-1.967969 0.163997c-29.191544-6.3959-44.115311-14.595772-44.607303-24.271621C635.900064 187.039078 635.244074 186.547085 635.244074 185.399103L635.244074 185.399103zM685.755285 207.37476c-1.803972-33.29148-9.675849-56.907111-23.615631-70.682896l-12.955798-20.171685 23.779628-1.147982c5.247918 24.763613 10.167841 54.611147 14.595772 89.870596l0.163997 1.967969L685.755285 207.37476 685.755285 207.37476zM656.071749 210.818706l-0.163997-1.967969c13.939782 3.115951 37.391416 10.167841 70.354901 21.155669l1.803972-0.163997 0.65599 13.119795 2.295964 3.607944-1.967969 0.163997c-39.03139-12.299808-59.859065-20.007687-62.483024-23.287636L656.071749 210.818706 656.071749 210.818706zM670.339526 68.46893l-0.65599-11.315823c23.943626 1.31198 35.915439 3.935939 36.079436 7.70788l0.491992 9.347854C684.443306 70.272902 672.471493 68.304933 670.339526 68.46893L670.339526 68.46893zM673.29148 85.196669l-0.491992-9.347854-2.295964-3.607944 1.967969-0.163997c22.631646 2.951954 33.94747 6.231903 34.111467 9.511851l0.65599 11.315823L673.29148 85.196669 673.29148 85.196669zM712.158873 113.568225c-23.943626-5.247918-36.079436-10.987828-36.407431-17.219731l-2.295964-7.379885c25.255605 5.083921 37.883408 9.511851 38.211403 13.44779 25.747598 7.543882 40.34337 11.151826 43.951313 10.987828l0.163997 1.803972c-0.327995 2.623959-3.443946 5.247918-9.347854 8.035874l-34.439462-13.44779L712.158873 113.568225 712.158873 113.568225zM682.147341 141.611787l-0.327995-5.73991-2.459962-9.347854c23.943626 4.755926 36.079436 8.691864 36.079436 11.479821l0.65599 11.315823C704.778988 147.351698 693.463165 144.727739 682.147341 141.611787L682.147341 141.611787zM688.051249 177.199231l-0.327995-5.73991-2.623959-9.511851 1.967969-0.163997-2.295964-3.607944-0.65599-13.119795 33.94747 9.511851 0.65599 13.283792c-10.659833-4.591928-18.039718-6.723895-21.975657-6.559898l-1.967969 0.163997c0 1.475977 8.199872 5.411915 24.271621 12.13581l2.623959 11.151826 0.163997 1.967969L688.051249 177.199231 688.051249 177.199231zM688.215247 180.807175c23.943626 4.755926 36.243434 11.807816 36.735426 20.991672l0.327995 5.73991-1.967969 0.163997c-22.631646-6.887892-34.275464-13.283792-34.603459-19.1877L688.215247 180.807175 688.215247 180.807175zM691.82319 212.786675l-0.65599-13.119795c15.415759 6.723895 26.89558 10.003844 34.111467 9.511851l0.327995 7.543882 2.459962 9.511851-1.803972 0.163997C704.450993 220.986547 692.971172 216.558616 691.82319 212.786675L691.82319 212.786675zM695.103139 240.994234l-0.163997-1.803972c19.351698 6.559898 29.355541 9.839846 30.339526 9.839846l0.163997 1.967969-7.871877 0.327995C706.746957 251.818065 699.367072 248.374119 695.103139 240.994234L695.103139 240.994234zM716.422806 118.980141l-0.163997-3.607944c4.427931-0.163997 10.003844 4.427931 16.727739 14.10378l-1.967969 0.163997C724.45868 122.26009 719.538757 118.816143 716.422806 118.980141L716.422806 118.980141zM479.118514 382.196028c53.627162 10.167841 89.870596 1.967969 109.222293-24.599616 9.675849-18.695708 15.579757-33.455477 17.875721-44.279308 11.807816-56.743113-5.903908-103.154388-53.299167-138.741832-12.463805-5.083921-22.631646-8.363869-30.339526-10.003844-31.651505-6.067905-63.631006 5.083921-95.938501 33.455477-9.347854 16.399744-15.251762 31.159513-18.039718 44.279308-13.283792 63.795003 1.967969 108.238309 45.919283 133.165919L479.118514 382.196028 479.118514 382.196028zM410.075593 265.429853c6.231903 5.247918 11.479821 8.199872 15.579757 9.019859-9.675849-9.347854-14.431775-15.087764-13.939782-17.219731-0.327995-5.411915-0.163997-10.167841 0.819987-14.267777l2.131967 0.327995c24.271621 15.743754 35.915439 25.5836 35.095452 29.519539l-2.131967 10.003844c-4.099936-3.607944-8.035874-5.73991-11.643818-6.559898l-0.819987 4.099936c10.823831 2.131967 15.251762 11.971813 13.44779 29.519539l-1.967969-0.327995c-22.467649-16.399744-34.603459-27.715567-36.407431-33.94747C409.255605 273.30173 409.255605 269.857783 410.075593 265.429853L410.075593 265.429853zM410.23959 286.257527c33.127482 21.647662 47.887252 40.34337 44.607303 56.251121-29.683536-23.615631-44.443306-36.079436-44.279308-37.555413C409.747598 295.769379 409.5836 289.537476 410.23959 286.257527L410.23959 286.257527zM412.699552 315.777066l0.491992-2.131967c27.059577 20.663677 44.607303 37.227418 52.643177 49.527226 10.331839 1.967969 17.055734 7.379885 20.49968 16.235746l-2.131967-0.491992C447.303011 372.028187 423.523382 350.872518 412.699552 315.777066L412.699552 315.777066zM414.339526 234.926329c2.459962-4.919923 4.263933-9.347854 5.083921-13.44779 18.859705 14.759769 30.339526 22.467649 34.111467 23.123639l-3.771941 18.039718C444.18706 261.493914 432.379244 252.310058 414.339526 234.926329L414.339526 234.926329zM421.883408 220.002562c2.131967-9.839846 5.247918-14.759769 9.675849-14.759769l27.879564 21.975657c-0.327995 1.147982-2.131967 6.231903-5.411915 15.415759C437.299167 228.530429 426.639334 220.986547 421.883408 220.002562L421.883408 220.002562zM432.707239 199.174888c5.083921-5.903908 8.527867-8.691864 10.495836-8.363869l3.935939 0.819987c10.987828 10.495836 19.1877 16.235746 24.599616 17.219731-0.819987 3.935939-3.935939 8.855862-9.511851 14.759769C442.21909 209.014734 432.379244 200.814862 432.707239 199.174888L432.707239 199.174888zM448.450993 185.563101l0.491992-2.131967c2.459962 0.491992 6.3959-0.819987 11.807816-3.771941 18.859705 10.003844 28.207559 16.727739 28.207559 19.84369-6.067905 1.639974-9.511851 4.427931-10.331839 8.363869C466.818706 202.946829 456.814862 195.566944 448.450993 185.563101L448.450993 185.563101zM469.442665 179.331198l0.491992-2.131967 14.923767 0.65599 12.627803 2.459962c2.459962 0.491992 8.199872 3.771941 17.547726 9.839846l-0.491992 2.131967c-6.887892-1.31198-13.611787 0.163997-20.49968 4.263933L469.442665 179.331198 469.442665 179.331198zM476.494555 249.030109l4.591928-21.811659c2.951954-14.431775 12.463805-25.091608 28.535554-31.9795l4.099936 0.819987c24.599616 34.275464 32.143498 73.798847 22.795644 118.570147l-2.459962 11.971813-6.231903 19.515695-6.067905-1.147982c-3.935939-0.819987-14.267777 0-30.831518 2.295964C473.870596 316.597053 469.278668 283.961563 476.494555 249.030109L476.494555 249.030109zM476.494555 363.172325l0.327995-1.967969c10.823831-2.131967 17.547726-3.115951 20.007687-2.623959 13.939782 10.167841 21.647662 17.875721 23.287636 23.287636l-21.319667-1.967969C496.174247 379.408072 488.630365 373.832159 476.494555 363.172325L476.494555 363.172325zM508.966047 363.172325l3.771941 2.787956c1.147982 0.163997 6.231903-2.951954 15.087764-9.675849 10.331839 13.119795 18.203716 20.171685 23.779628 21.155669-0.65599 2.951954-8.199872 4.263933-22.467649 4.099936C515.361947 370.716208 508.638053 364.648302 508.966047 363.172325L508.966047 363.172325zM511.590006 185.235106l0.491992-2.131967 4.099936 0.819987c19.84369 3.771941 35.751441 17.219731 47.723254 40.34337C554.557335 214.754644 537.173607 201.634849 511.590006 185.235106L511.590006 185.235106zM521.921845 197.534914c38.211403 24.271621 56.087124 42.311339 53.79116 53.79116 1.967969 4.919923 2.623959 8.527867 2.295964 10.823831-35.095452-26.567585-51.495195-44.935298-49.363229-54.939142C526.349776 206.71877 524.217809 203.602819 521.921845 197.534914L521.921845 197.534914zM528.64574 352.348495l7.543882-15.251762 2.131967 0.491992c4.263933 5.73991 13.283792 14.431775 27.059577 25.911595l-0.491992 2.131967c-5.411915 5.247918-8.363869 8.855862-8.855862 10.823831l-4.099936-0.819987L528.64574 352.348495 528.64574 352.348495zM536.845612 333.324792l4.263933-9.675849-0.491992-8.363869 4.099936 0.819987c19.515695 17.711723 29.027546 27.059577 28.863549 28.371557l-0.491992 2.131967c-1.967969 9.347854-4.263933 13.611787-7.05189 13.119795C548.817425 342.508648 539.141576 333.652787 536.845612 333.324792L536.845612 333.324792zM539.797566 236.402306c27.715567 19.84369 40.999359 32.63549 39.68738 38.703395 1.31198 7.215887 1.803972 12.13581 1.147982 14.759769l-1.967969-0.327995-35.095452-29.519539C540.78155 245.586163 539.469571 237.714286 539.797566 236.402306L539.797566 236.402306zM542.257527 307.413197l2.459962-11.971813 10.003844 3.935939c-7.05189-7.871877-10.331839-12.627803-10.003844-14.267777-0.65599-10.495836-0.819987-16.727739-0.327995-18.695708 18.695708 13.611787 30.831518 24.927611 36.243434 33.94747l-2.459962 11.971813c-7.05189-7.05189-12.7918-10.987828-16.727739-11.807816 8.035874 11.315823 13.939782 17.383728 17.711723 18.039718l-4.099936 19.84369C554.557335 320.532992 543.733504 310.201153 542.257527 307.413197L542.257527 307.413197zM307.249199 569.153107c-9.675849 0-17.711723-6.887892-19.84369-16.071749-4.263933-12.463805 1.639974-28.863549 29.519539-35.751441 1.31198 35.587444 0 49.527226 0 49.527226C313.809097 568.33312 310.693145 569.153107 307.249199 569.153107L307.249199 569.153107zM709.862908 537.173607c0-1.147982 0-2.131967-0.163997-3.115951 2.131967 3.279949 3.279949 7.215887 3.279949 11.479821 0 11.643818-9.183857 21.155669-20.49968 21.155669-3.443946 0-6.723895-0.819987-9.511851-2.459962C697.891095 563.905189 709.862908 551.933376 709.862908 537.173607L709.862908 537.173607zM531.761691 520.281871c0.65599 15.743754-32.963485 49.199231-32.963485 49.199231 0-18.203716 9.347854-42.803331 12.463805-48.707239-8.035874-11.643818-13.283792-32.307495-13.283792-32.307495S531.105701 504.374119 531.761691 520.281871L531.761691 520.281871zM488.794363 507.326073c2.459962 0 4.427931 1.967969 4.427931 4.427931 0 2.459962-1.967969 4.427931-4.427931 4.427931-2.459962 0-4.427931-1.967969-4.427931-4.427931C484.366432 509.294042 486.334401 507.326073 488.794363 507.326073L488.794363 507.326073zM445.335042 629.668161c-0.819987 8.855862-2.131967 16.235746-2.131967 16.235746s-53.627162 7.05189-63.959001-30.503523C395.151826 632.94811 427.623318 631.144138 445.335042 629.668161L445.335042 629.668161zM620.648302 614.908392c-9.675849 37.719411-63.303011 31.651505-63.303011 31.651505s-1.475977-7.379885-2.459962-16.235746C572.597053 631.636131 605.232543 632.784113 620.648302 614.908392L620.648302 614.908392zM419.587444 518.313901c29.847534 0 53.955157 21.975657 53.955157 49.035234 0 27.059577-24.271621 49.035234-53.955157 49.035234-29.847534 0-53.955157-21.975657-53.955157-49.035234C365.632287 540.289558 389.903908 518.313901 419.587444 518.313901L419.587444 518.313901zM419.587444 613.76041c28.371557 0 51.331198-20.827675 51.331198-46.411275 0-25.5836-22.959641-46.411275-51.331198-46.411275-28.207559 0-51.331198 20.827675-51.331198 46.411275C368.256246 592.932735 391.379885 613.76041 419.587444 613.76041L419.587444 613.76041zM419.587444 534.38565c20.007687 0 36.243434 14.759769 36.243434 32.799488 0 18.203716-16.235746 32.799488-36.243434 32.799488s-36.243434-14.759769-36.243434-32.799488C383.34401 549.14542 399.579757 534.38565 419.587444 534.38565L419.587444 534.38565zM435.331198 552.261371c1.967969 2.131967 4.919923 2.623959 6.559898 1.147982 1.639974-1.475977 1.475977-4.263933-0.491992-6.3959-1.967969-2.131967-4.919923-2.623959-6.559898-1.147982C433.035234 547.341448 433.199231 550.129404 435.331198 552.261371L435.331198 552.261371zM395.971813 585.880846c5.411915 5.73991 13.283792 7.05189 17.875721 3.115951 4.591928-3.935939 3.935939-11.807816-1.475977-17.547726-5.411915-5.73991-13.283792-7.05189-17.875721-3.115951C389.903908 572.433056 390.559898 580.304933 395.971813 585.880846L395.971813 585.880846zM584.240871 518.313901c29.847534 0 53.955157 21.975657 53.955157 49.035234 0 27.059577-24.271621 49.035234-53.955157 49.035234-29.847534 0-53.955157-21.975657-53.955157-49.035234C530.121717 540.289558 554.393338 518.313901 584.240871 518.313901L584.240871 518.313901zM584.240871 613.76041c28.371557 0 51.331198-20.827675 51.331198-46.411275 0-25.5836-22.959641-46.411275-51.331198-46.411275-28.207559 0-51.331198 20.827675-51.331198 46.411275C532.909673 592.932735 555.869315 613.76041 584.240871 613.76041L584.240871 613.76041zM584.240871 534.38565c20.007687 0 36.243434 14.759769 36.243434 32.799488 0 18.203716-16.235746 32.799488-36.243434 32.799488-20.007687 0-36.243434-14.759769-36.243434-32.799488C547.997438 549.14542 564.233184 534.38565 584.240871 534.38565L584.240871 534.38565zM599.820628 552.261371c1.967969 2.131967 4.919923 2.623959 6.559898 1.147982 1.639974-1.475977 1.475977-4.263933-0.491992-6.3959-1.967969-2.131967-4.919923-2.623959-6.559898-1.147982C597.688661 547.341448 597.852659 550.129404 599.820628 552.261371L599.820628 552.261371zM560.62524 585.880846c5.411915 5.73991 13.283792 7.05189 17.875721 3.115951 4.591928-3.935939 3.935939-11.807816-1.475977-17.547726-5.411915-5.73991-13.283792-7.05189-17.875721-3.115951C554.557335 572.433056 555.213325 580.304933 560.62524 585.880846L560.62524 585.880846zM957.171044 381.540038C957.171044 381.540038 957.171044 381.540038 957.171044 381.540038c-0.65599 0.983985-1.31198 1.803972-1.967969 2.951954-0.327995 0.327995-0.491992 0.65599-0.819987 0.983985-0.327995 0.327995-1.967969 0.65599-2.295964 0.983985-11.315823 14.759769-29.355541 40.34337-62.975016 46.247277l0 34.931454c0 4.263933-0.819987 8.691864-5.083921 8.691864L685.919283 476.330557c-0.163997 10.331839-0.327995 18.203716-0.65599 27.879564 24.435618 1.803972 43.295324 19.351698 43.295324 41.491352 0 22.467649-19.84369 40.671365-45.263293 41.819347-1.967969 78.226778-5.903908 143.98975-7.70788 150.549648l-0.491992 0.983985c-1.967969 2.295964-9.511851 5.247918-21.155669 8.363869 0.327995 13.939782-3.279949 29.355541-11.643818 46.08328 3.443946-21.647662-22.795644-36.079436-26.567585-38.047406-0.163997 0-0.327995 0-0.491992 0 0.163997 4.427931 0 57.727098-88.230621 97.90647-1.475977-44.115311-14.10378-70.682896-31.9795-86.754644L494.534273 766.606022l-5.411915-0.327995 0-0.163997 0 0 0 0 0.327995 0 0.327995-0.163997c-0.819987-0.163997-0.983985-0.491992-1.147982-1.147982-10.331839-8.035874-28.043562-18.203716-64.450993-18.203716-13.283792 0-28.207559 1.31198-44.607303 3.935939-4.099936 0.819987-7.70788 1.147982-11.151826 1.147982-5.575913 0-10.003844-0.983985-16.071749-2.295964l-0.327995 0-0.327995-0.163997c-17.547726-4.099936-27.55157-7.70788-30.011531-10.659833l-0.491992-0.983985c-0.491992-2.131967-2.295964-8.363869-5.73991-150.549648-25.255605-0.983985-45.263293-19.351698-45.263293-41.983344 0-22.139654 18.859705-39.523382 43.459321-41.163357-0.163997-9.675849-0.327995-17.547726-0.65599-27.879564L132.099936 476.002562c-4.427931 0-10.495836-4.591928-10.495836-8.691864l0-97.414478c-11.807816-0.65599-19.679693-2.295964-26.731582-4.755926-29.027546-10.495836-35.751441-35.915439-35.587444-60.023062 0-1.475977 0.491992-2.787956 0.983985-3.771941-6.723895-11.643818-6.231903-25.5836-5.083921-35.587444 0.983985-8.035874 2.623959-12.13581 4.427931-13.939782-4.263933-8.855862-0.983985-18.859705 1.967969-26.731582 3.771941-10.167841 12.13581-11.971813 22.139654-10.003844-4.755926-9.019859-2.459962-17.219731 11.643818-28.699552 4.427931-3.607944 14.267777 7.05189 26.075593 16.071749l0-267.151826c0-4.263933 6.067905-6.067905 10.331839-6.067905l751.928251 0c4.427931 0 5.083921 1.803972 5.083921 6.067905L888.784113 248.374119c16.727739 0.983985 29.355541 7.70788 38.539398 19.84369 4.591928 6.231903 7.871877 11.807816 8.691864 16.891736C977.670724 313.153107 982.262652 344.640615 957.171044 381.540038L957.171044 381.540038zM316.433056 508.638053c-22.959641 0.491992-40.835362 16.727739-40.835362 36.735426 0 20.335682 18.859705 36.899423 41.983344 36.899423l0 2.623959 0.163997-0.65599c0-0.819987 0-1.475977 0-2.295964 0.491992 0.163997 0.983985 0.163997 1.475977 0.327995l1.803972 0 0 0.491992c5.247918 1.31198 12.7918 2.951954 19.351698 3.771941 10.003844 35.095452 34.111467 64.122998 34.111467 64.122998s-9.839846 28.863549-13.939782 67.238949c51.167201-85.11467 229.268418-81.178732 280.107623-10.823831-4.591928-32.799488-12.627803-56.415119-12.627803-56.415119s24.107623-28.863549 34.111467-64.122998c6.559898-0.819987 13.939782-1.147982 19.023703-2.295964 0 0.491992 0 2.623959 0 2.623959l0.491992 0c23.123639 0 41.983344-18.695708 41.983344-39.03139 0-9.347854-3.935939-18.695708-10.495836-25.419603-10.167841-6.723895-25.091608-10.331839-40.835362-10.331839 0-6.723895 0.983985-19.351698 1.803972-35.423447L318.401025 476.658552c0.163997 10.331839 0.491992 19.84369 0.65599 30.175529l0 2.131967L316.433056 508.638053 316.433056 508.638053zM126.524023 462.554773c0 4.099936 6.3959 9.183857 10.823831 9.183857l741.432415 0c4.263933 0 5.575913-4.919923 5.575913-9.183857l0-29.027546c0 0.491992-6.723895 1.475977-10.823831 1.147982-22.795644-2.295964-44.443306-3.607944-60.679052-9.183857L176.215247 425.491352l-1.31198-2.787956 0-60.18706c-10.823831 5.903908-25.5836 8.363869-48.215247 7.871877L126.68802 462.554773 126.524023 462.554773zM821.381166-13.693786 180.807175-13.693786 180.807175 282.649584c10.823831 4.263933 15.579757 10.987828 15.087764 21.975657-0.491992 8.363869-4.263933 13.611787-15.087764 16.727739l0 7.379885c5.903908 1.967969 3.935939 4.263933 5.247918 6.723895 5.411915 10.495836 5.575913 18.203716-5.247918 23.779628l0 55.759129 615.318386 0c-2.787956-5.575913-4.755926-7.871877-5.575913-12.299808-1.475977-8.035874-1.639974-18.367713-1.147982-28.207559L697.891095 315.449071c0 0-28.371557-15.251762-16.727739-32.799488 11.643818-17.383728 32.307495-11.479821 50.511211-0.327995 12.13581 7.379885 39.68738 23.287636 63.959001 40.179372 0.163997-0.163997 0.327995-0.163997 0.491992-0.327995-1.803972-1.31198-2.951954-2.295964-2.951954-2.295964-11.151826-7.543882-6.887892-36.899423 15.415759-41.327354 3.115951-0.65599 9.675849 0 9.675849 1.147982l0-293.391416L821.381166-13.693786 821.381166-13.693786zM177.855221 271.169763c0 3.443946-2.131967 6.231903-4.755926 8.035874 1.639974 0.491992 3.771941 0.983985 4.755926 1.475977L177.855221 271.169763 177.855221 271.169763zM177.855221 322.828956c-0.983985 0.163997-1.639974 0.327995-2.459962 0.491992 0.819987 0.491992 1.475977 0.983985 2.459962 1.475977L177.855221 322.828956 177.855221 322.828956zM878.780269-65.516976 137.347854-65.516976c-4.263933 0-10.823831 2.131967-10.823831 6.3959L126.524023 206.882767c5.903908 1.147982 4.919923 2.295964 6.723895 3.279949 19.679693 8.035874 38.047406 25.255605 25.747598 33.127482-0.163997 0-1.475977 0.163997-1.639974 0.163997 9.511851 3.771941 17.547726 9.839846 17.547726 20.663677l0-289.29148 655.169763 2.459962 0 291.915439c9.839846-9.675849 21.647662-14.595772 34.603459-10.331839 3.279949-6.559898 13.611787-9.839846 19.515695-10.331839l0-307.495195C884.192184-63.38501 883.044202-65.516976 878.780269-65.516976L878.780269-65.516976zM878.780269-65.516976"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="about" unicode="&#58891;" d="M514.27174 834.607768c-249.516844 0-451.789687-202.272843-451.789687-451.789687s202.272843-451.789687 451.789687-451.789687 451.789687 202.272843 451.789687 451.789687S763.788583 834.607768 514.27174 834.607768zM514.27174-20.12919999999997c-222.541469 0-402.947282 180.405813-402.947282 402.947282s180.405813 402.947282 402.947282 402.947282 402.947282-180.405813 402.947282-402.947282S736.814232-20.12919999999997 514.27174-20.12919999999997zM514.295276 593.979362c-9.44614-10.360975-14.307867-22.951735-14.307867-37.483706 0-11.960403 3.886517-22.396079 11.534707-30.457686 7.783267-8.211009 17.853623-12.450567 29.313629-12.450567 9.312086 0 23.139 2.849908 35.782971 16.900925 9.865695 10.641361 14.866592 23.437805 14.866592 37.693484 0 11.68104-4.031826 21.900799-11.744485 29.832446C562.925856 615.325529 532.358677 613.449809 514.295276 593.979362zM549.461193 293.282882c-12.110829-11.541871-20.589944-18.759249-26.236548-23.316032 2.77009 14.953573 9.976212 44.614104 27.330462 103.023398 17.297968 57.890478 18.799158 67.991534 18.799158 72.955592 0 8.65717-3.63683 16.335037-9.921977 21.642926-14.124695 11.661597-39.035038 9.349949-69.131497-7.677866-16.779152-9.408277-34.595936-24.759917-54.493102-46.576805l-10.377348-11.541871 34.425044-26.548656 8.818853 8.715499c9.573029 9.292644 16.086373 15.35164 20.411889 19.393699-26.294876-86.460164-39.093367-140.190903-39.093367-164.262134 0-10.907421 3.172249-19.970844 9.573029-26.839275 6.460132-7.039323 15.510252-10.736529 25.891693-10.736529 10.146081 0 21.792329 3.926426 35.922141 11.949146 12.741185 7.212262 31.883151 23.029506 58.641585 48.190559l10.837836 10.391674-31.30703 30.475082L549.461193 293.282882z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="layim-theme" unicode="&#58907;" d="M958.830745 538.643056L740.659817 692.753993l-100.539834 0-3.977591-9.332553c-0.37146-0.871857-38.021965-86.8613-124.772748-88.667435-35.691897 0.76441-67.206658 15.500019-93.680613 43.828204-20.658506 22.106484-30.374798 44.584428-30.456662 44.776809l-3.955078 9.393951-100.587929 0L64.518433 538.643056 169.320337 379.756349l89.956801 65.019853-19.016099-368.05254 268.86654 0 4.093225 0 269.866311 0-19.016099 368.051517 89.956801-65.018829L958.830745 538.643056zM730.105437 507.20402l20.655436-399.781172-237.540068 0-4.093225 0L272.587282 107.42284700000005l20.656459 399.781172-115.938546-83.797521-36.3243 55.070246 159.440315 111.641683-19.276019 30.638811L121.066333 508.667348l-14.548344 22.056342 185.921433 131.330094 71.077825 0c5.332449-10.04375 15.433504-26.779923 30.951943-43.580564 32.047904-34.69622 72.256674-53.486168 116.345822-54.411237l0-0.031722c0.203638 0.00307 0.406253 0.01228 0.60989 0.016373 0.203638-0.00307 0.406253-0.013303 0.60989-0.016373l0 0.031722c44.073798 0.925069 84.359316 19.703761 116.566856 54.379515 15.623839 16.821107 25.814945 33.579793 31.188326 43.612287l71.120804 0 185.921433-131.330094-14.548344-22.056342L742.203986 620.7551920000001l-19.276019-30.638811 159.440315-111.641683-36.3243-55.070246L730.105437 507.20402z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="down" unicode="&#58906;" d="M842.73769531 591.36914063c13.72412109 13.72587891 35.97363281 13.72587891 49.69775391-1e-8v0c13.72587891-13.72412109 13.72587891-35.97363281 0-49.6977539l-356.60126953-356.60214844c-13.72412109-13.72587891-35.971875-13.72587891-49.69775391 0v0c-13.72412109 13.72412109-13.72412109 35.97363281 0 49.69775391l356.60126953 356.60214844zM535.39560547 234.76699219c13.72587891-13.72412109 13.72587891-35.97363281 0-49.69775391v0c-13.72412109-13.72587891-35.971875-13.72587891-49.69775391 0l-356.60214844 356.60214844c-13.72412109 13.72412109-13.72412109 35.97363281 1e-8 49.69775391v0c13.72587891 13.72587891 35.97363281 13.72587891 49.69951171 0l356.60039063-356.60214844zM535.39560547 234.76699219z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="up" unicode="&#58905;" d="M513.40625 520.40625l337.5-337.5c11.25-11.25 28.125-11.25 39.375 0 11.25087891 11.25 11.25087891 28.125 0 39.375l-354.375 354.375C530.28125 582.28125 519.03125 587.90625 513.40625 587.90625c-5.625 0-16.875 0-22.49912109-5.625L130.90537109 222.28125c-11.25-11.25-11.25-28.125 0-39.375s28.125-11.25 39.375 0L513.40625 520.40625z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="circle-dot" unicode="&#58903;" d="M513.133312 830.6731560000001c-247.538793 0-448.208115-200.669322-448.208115-448.207092 0-247.538793 200.670346-448.208115 448.208115-448.208115 247.538793 0 448.208115 200.670346 448.208115 448.208115C961.341427 630.004857 760.673128 830.6731560000001 513.133312 830.6731560000001zM513.132288-6.649187999999981c-214.901465 0-389.113205 174.212764-389.113205 389.114229 0 214.902488 174.21174 389.115252 389.113205 389.115252 214.903511 0 389.115252-174.212764 389.115252-389.115252C902.24754 167.563576 728.0358-6.649187999999981 513.132288-6.649187999999981zM513.133312 382.46504100000004m-344.602456 0a336.754 336.754 0 1 1 689.204911 0 336.754 336.754 0 1 1-689.204911 0Z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="set-fill" unicode="&#58900;" d="M916.9398 445.2101l-69.9664 10.7833c-18.6619 2.863-38.1388 17.826-43.3424 33.2487-5.1618 15.3809-15.0883 65.4524-3.9288 80.6661l41.9004 57.135c11.1595 15.2346 9.3832 38.5985-3.9706 51.9314l-30.6364 30.6573c-13.3538 13.3538-36.7177 15.151-51.9314 3.9497l-57.135-41.8795c-15.2346-11.1804-39.4344-14.3987-53.7704-7.168-14.3569 7.2307-57.3022 35.7773-60.1652 54.4183l-10.7833 69.9664C570.3471 807.6016 552.542 822.8571 533.6712 822.8571h-43.34236734693877c-18.8709 0-36.6759-15.2555-39.5389-33.9174l-10.7833-69.9664c-2.863-18.6619-17.826-38.1388-33.2487-43.3424-15.4018-5.1827-65.4524-15.1092-80.687-3.9288L268.9567 713.5817c-15.2346 11.1804-38.6194 9.3832-51.9523-3.9497l-30.6364-30.6573c-13.3747-13.3538-15.151-36.7177-3.9706-51.9314l41.9004-57.135c11.1595-15.2346 14.3778-39.4136 7.168-53.7704-7.2307-14.3569-35.7773-57.2813-54.4183-60.1443l-69.9664-10.7833C88.3984 442.3471 73.1429 424.542 73.1429 405.6712v-43.34236734693877c0-18.8709 15.2555-36.6759 33.9174-39.5389l69.9664-10.7833c18.6619-2.863 38.1388-17.8469 43.3424-33.2487 5.1618-15.4018 15.0883-65.4733 3.9288-80.687l-41.9004-57.135c-11.1595-15.2346-9.3832-38.6194 3.9706-51.9314l30.6364-30.6573c13.3538-13.3538 36.7177-15.151 51.9523-3.9706l57.135 41.9213c15.2346 11.1386 39.4136 14.3778 53.7704 7.168 14.3569-7.2307 57.2813-35.7773 60.1443-54.4183l10.7833-69.9664c2.863-18.6619 20.6472-33.9174 39.5389-33.9174h43.34236734693877c18.8709 0 36.6759 15.2555 39.5389 33.9174l10.7833 69.9664c2.863 18.6619 17.826 38.1388 33.2487 43.3215 15.4018 5.1827 65.4524 15.0883 80.6661 3.9288l57.1559-41.9213c15.2346-11.1595 38.5985-9.3623 51.9314 3.9706l30.6364 30.6573c13.3747 13.3329 15.151 36.7177 3.9706 51.9314l-41.9004 57.135c-11.1595 15.2346-14.3778 39.4136-7.168 53.7496 7.2307 14.3778 35.7773 57.3231 54.4183 60.1861l69.9664 10.7833c18.6619 2.863 33.9174 20.6472 33.9174 39.5389v43.34236734693877C950.8571 424.542 935.6016 442.3471 916.9398 445.2101zM512 210.4633c-95.838 0-173.5367 77.6986-173.5367 173.5367s77.6986 173.5367 173.5367 173.5367 173.5367-77.6986 173.5367-173.5367S607.838 210.4633 512 210.4633zM512 384m-104.7824 0a5.014 5.014 0 1 1 209.5647 0 5.014 5.014 0 1 1-209.5647 0Z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="search" unicode="&#58901;" d="M439.323351 120.52219c-49.280352 0-97.09834 9.656941-142.126681 28.699646-43.480015 18.388812-82.522793 44.706201-116.043584 78.225619s-59.841305 72.560596-78.230871 116.03883C83.878729 388.513804 74.222416 436.330856 74.222416 485.609189c0 49.284473 9.656313 97.104595 28.699798 142.133138 18.388542 43.479257 44.71008 82.520435 78.231894 116.03883 33.518745 33.515325 72.562546 59.832713 116.043584 78.219479 45.027318 19.039635 92.846329 28.694529 142.125658 28.694529 49.280352 0 97.099364-9.653871 142.126681-28.694529 43.481039-18.385742 82.525863-44.704155 116.044608-78.220502 33.520791-33.518395 59.842328-72.559573 78.230871-116.03883 19.042462-45.028543 28.699798-92.848665 28.699798-142.133138 0-49.278333-9.657336-97.095385-28.701845-142.122905-18.388542-43.47721-44.708033-82.520435-78.228824-116.03883s-72.563569-59.838853-116.043584-78.226642C536.422715 130.177084 488.603703 120.52219 439.323351 120.52219zM439.323351 797.483242c-171.975699 0-311.887855-139.906423-311.887855-311.875077S267.347652 173.734112 439.323351 173.734112s311.887855 139.907447 311.887855 311.874053S611.299051 797.483242 439.323351 797.483242zM890.678206-48.734702c-22.121716 0-42.90387 8.562003-58.541653 24.115234L674.672953 128.025071l37.039062 38.20616 157.888289-153.058978c5.606924-5.606695 13.091693-8.692986 21.077901-8.692986 7.983139 0 15.464837 3.087315 21.070738 8.69094 5.616135 5.622044 8.715856 13.126972 8.715856 21.123087 0 7.980765-3.091535 15.46318-8.702552 21.067828l-0.301888 0.306992L758.714395 213.230662l38.207726 37.035498 152.611906-157.427472c15.571265-15.638165 24.144876-36.422538 24.144876-58.549487 0-22.195511-8.625801-43.054585-24.287121-58.735729C933.723298-40.112324 912.876674-48.734702 890.678206-48.734702zM281.015489 327.245392c-42.340005 42.320874-65.652899 98.584296-65.643689 158.421102 0.008187 59.818387 23.319034 116.074645 65.637549 158.4078l37.634651-37.619806c-66.60666-66.629513-66.60973-175.00071-0.007163-241.577011L281.015489 327.245392z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="friends" unicode="&#58898;" d="M672.02974 765.933689c7.66047-32.266891 8.420787-62.237483 7.713682-95.365998-0.283456-12.778024-7.291057-71.832002-5.3918-89.926102 1.561565-14.936177 5.132904-16.128329 10.759041-28.436656 9.803273-21.422915 6.51846-50.970882 2.76088-72.566736-2.056845-11.816117-6.404873-28.64541-13.017478-38.287001-7.291057-10.645454-21.864984-10.711969-28.319999-23.12365-9.29469-17.848507-4.045129-42.930765-9.903557-62.21497-6.65763-21.883403-23.599488-23.420409-24.877597-52.040237 8.316409-1.243317 16.59598-2.479471 24.877597-3.722788 8.316409-18.498306 23.533996-55.70265 39.08518-66.900689 13.024641-3.728928 26.048259-7.448646 39.07904-11.156084 45.641503-19.593244 96.365768-43.032072 142.108578-63.215764 41.656749-18.381649 91.51325-24.937972 106.575294-70.629617 0-31.026644 2.795673-104.309694 2.025123-144.978952L58.155515-56.631556000000046c-0.757247 40.669258 2.029216 113.952308 2.029216 144.978952 15.065114 45.691645 64.928778 52.247968 106.578364 70.629617 45.74281 20.182668 96.467075 43.62252 142.098345 63.215764 13.027711 3.707438 26.054399 7.427156 39.08211 11.156084 15.554254 11.197016 30.78105 48.402383 39.09439 66.900689l18.492166 4.710278c-4.196579 24.429389-18.658965 26.322505-24.682146 43.62559-2.356674 26.013467-4.729721 52.052516-7.095605 78.079286 0.107447-1.234107-17.006326 3.246951-19.252483 4.716418-24.130583 15.838733-24.618701 80.075757-26.941606 106.793258-1.063215 12.222369 15.163351 22.240537 10.654664 44.62536-26.433022 131.125433 11.437493 219.776496 71.330582 240.123916 41.564651 17.633612 119.167077 50.323129 191.563944 3.716648l17.971303-17.428951 29.061896-5.237281C662.71663 795.172617 672.02974 765.933689 672.02974 765.933689z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="group" unicode="&#58899;" d="M1328.72893437-13.274022189999982L1325.7954575 10.932401249999998 1319.19311938 40.27361905999999 1309.65730438 68.14729219000003 1296.45423969 96.75473719000001 1283.25117594 118.75984405999998 1264.91331781 140.03117906 1244.37414312 156.90310406000003 1215.76669813 173.03964562 1195.22913594 182.57546062999995 1168.08923563 189.17779874999997 1140.94772187 195.77852437 1117.47507031 204.58056750000003 1088.13546594 218.51740312000004 1064.66281438 229.52076375000001 1036.05536844 242.72382749999997 1014.0502625 255.19473187999995 1014.0502625 332.94718406000004 1023.58446406 343.95054469 1032.38811969 358.61954062999996 1038.98884531 373.29014906 1044.12363969 391.62800719 1049.992205 413.63472656 1052.19191 430.50504 1055.370515 429.77126719 1061.727725 430.75016813 1066.61900281 434.662545 1071.99731188 443.46458812 1075.42104594 453.7325625 1077.37723437 466.4469825 1079.82206656 489.43099031 1080.799355 508.991265 1079.82206656 525.61806187 1076.39833344 535.88764969 1069.55247969 539.80002656 1065.64010188 538.82112656 1069.06383594 560.82623344 1071.99731188 587.2339743800001 1072.97621281 611.19526969 1072.48595656 630.26689969 1069.55247969 647.870985 1064.17255719 664.98642656 1056.83805969 680.63432344 1046.56847188 698.24002125 1034.83295281 712.91063063 1021.13963187 724.15750594 1003.53554656 735.40438125 981.53043969 745.67396812 962.94745344 750.56363437 940.45370281 754.47601125 918.4469825 754.964655 895.95323188 751.05227812 874.43676969 743.71777969 855.36513875 735.893025 838.73834188 725.1347934400001 823.33396063 711.44308594 808.66335125 695.30493188 795.4602875 676.23330187 785.9244725 655.69573969 780.05751875 632.22308813 779.32374687 602.14809844 782.25722375 574.27442531 785.9244725 538.3324818799999 777.85620219 538.3324818799999 772.72140875 531.73014375 771.25547656 519.99462469 772.72140875 492.12095156 776.3886575 459.84625688 779.32374687 443.70810375 784.45854031 434.90606063 793.99435531 429.77126719 799.86130906 430.50504 803.53017031 404.83268344 807.19742 389.42830219 813.06598531 372.55637719000003 821.13425656 355.68606375 830.67007156 342.48299999999995 838.00456906 332.94718406000004 837.27079719 253.72718719 845.06329813 250.99690875 855.81346625 248.0392425 867.37158969 243.73981969 878.39107625 239.43878530999996 888.6058325 235.67638781000005 897.74331406 231.10603405999996 908.76441312 226.53729375 920.85956187 219.54952313 932.95471062 212.56014000000005 942.898535 205.30305094000005 955.80002656 195.62693156 966.82112656 185.41378874999998 977.30358781 172.51229719000003 988.32307531 158.26743750000003 1000.01505219 141.87125344000003 1010.0943425 122.51901655999995 1018.69641219 101.55409219 1026.22120719 82.20185436999998 1031.46243781 64.05913219000001 1035.09098281 45.110066250000045 1038.71952688 23.741970000000038 1041.13855625-1.2546703100000514 1041.54172812-18.187877810000032 1040.73538531-33.30681374999995 1037.30842625-44.99879062000002 1030.79156-57.83254968999995 1023.19742-66.36688593999997 1009.28799875-73.42238906 1298.65555719-73.42238906 1311.85862094-66.82005093999999 1322.12820875-56.552076560000046 1328.72893437-45.54871687000002 1330.19647906-31.611880309999947ZM443.23504906 789.36487031L427.10818437 771.62531906 412.59400625 750.66039469 402.11154406 728.08278469 395.66079781 702.27980156 394.854455 669.21972844 398.07982813 638.57868562 402.11154406 599.06786719 393.24176844 599.06786719 387.59736594 591.81077812 385.98467938 578.90928656 387.59736594 548.26824375 391.62908187 512.7891412500001 394.854455 495.04959 400.4988575 485.37347156 410.98131969 479.72906906 417.43206594 480.53541188 421.46378187 452.31339844 425.49549781 435.38019094 431.94624406 416.83429687 440.81601969 398.28840187 451.29848094 383.77422375000003 459.36191375 373.29176156000005 458.55557094 286.20669281000005 444.84773562 277.33691719 412.59400625 262.01639531 379.53393406 247.50221719 352.92460719 234.60072562000005 331.95968281 225.73095 308.57572906 218.47386094 284.3854325 213.63580125 261.00147875 207.99139875000003 236.81118125 197.50893656000005 214.23357031 186.22013156000003 194.07498969 171.70595344000003 171.49737969 149.12834250000003 155.370515 125.74438874999998 143.27536625 103.16677875000005 133.59924781 78.97648125 123.92312844 51.56081156000005 119.08506875 29.789544370000044 115.05335281 11.243650310000021 112.63432344-10.527616869999974 112.63432344-29.879854690000002 115.85969656-49.23209250000002 125.535815-62.133584059999976 140.04999313-71.80970344000002 158.59588719-73.42238906 965.74546437-73.42238906 980.2596425-66.1653 991.5484475-54.87649499999998 998.80553656-42.781346249999956 1000.41822312-27.46082531000002 998.80553656-7.302244689999952 995.58016438 19.30708218999996 988.32307531 51.56081156000005 977.84061313 82.20185436999998 963.326435 113.64924094000003 948.81225688 137.8395375 928.65367531 161.22349125000005 906.07606531 179.76938625000003 874.62867875 197.50893656000005 852.05106875 207.99139875000003 822.21636875 215.24848781000003 792.38166875 222.50557688000004 766.57868562 232.18169624999996 734.32495625 247.50221719 708.52197312 259.59736594000003 677.07458656 274.11154406 652.88429 287.81937937 652.88429 373.29176156000005 663.36675219 385.38691031 673.04287063 401.513775 680.29995969 417.64063969 685.94436219 437.79922031 692.39510844 461.98951781 694.81413781 480.53541188 698.30882938 479.72906906 705.2966 480.80473031 710.67168406 485.10415312 716.585405 494.78027156 720.3478025 506.06907656 722.49912688 520.04623031 725.18586219 545.31218906 726.26152437 566.8141378099999 725.18586219 585.09071344 721.42346469 596.3795184400001 713.89705719 600.68055375 709.59763438 599.6048915599999 713.36003188 623.79518906 716.585405 652.82354531 717.66106719 679.16516625 717.12242937 700.13008969 713.89705719 719.4823275 707.98494781 738.2959275000001 699.92151594 755.49845437 688.63271094 774.85069219 675.73121937 790.97755688 660.67840344 803.34202406 641.32616563 815.70487875 617.13586906 826.99368375 596.7095825 832.37038031 571.98064812 836.66980219 547.79035063 837.20844 523.06302875 832.90740469 499.40975656 824.84397281 478.44483313 816.24351562 460.16825656 804.4160728100001Z"  horiz-adv-x="1449" />
+      
+      <glyph glyph-name="reply-fill" unicode="&#58897;" d="M507.904 835.5840000000001q93.184 1.024 175.104-33.792t143.872-94.72 97.792-141.312 36.864-174.592q1.024-88.064-30.208-165.888t-87.04-137.728-131.072-98.816-162.304-48.128q-22.528-3.072-48.128-5.12t-56.832-3.072-69.632 0-86.528 6.144q-106.496 10.24-158.208 26.624t-41.472 18.432q54.272 9.216 93.184 29.696 20.48 11.264 16.896 32.256t-19.968 39.424q-52.224 57.344-84.48 133.632t-34.304 164.352q-1.024 93.184 33.792 175.104t95.232 143.36 142.336 97.28 175.104 36.864zM707.584 385.024q0-26.624 18.432-45.568t45.056-18.944 45.568 18.944 18.944 45.568-18.944 45.056-45.568 18.432-45.056-18.432-18.432-45.056zM450.56 385.024q0-26.624 19.456-46.08t46.08-19.456q27.648 0 46.592 19.456t18.944 46.08q0 27.648-18.944 46.592t-46.592 18.944q-26.624 0-46.08-18.944t-19.456-46.592zM196.608 386.048q0-26.624 18.944-46.08t45.568-19.456q27.648 0 46.592 19.456t18.944 46.08-18.944 45.568-46.592 18.944q-26.624 0-45.568-18.944t-18.944-45.568z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="menu-fill" unicode="&#58895;" d="M511.999488 834.254727c-248.678712 0-450.273176-201.585181-450.273176-450.254727s201.594464-450.254727 450.273176-450.254727 450.273176 201.585181 450.273176 450.254727S760.6782 834.254727 511.999488 834.254727zM266.371377 589.705012l491.256222 0 0-33.772174L266.371377 555.932838 266.371377 589.705012zM757.627599 178.29396499999996L266.371377 178.29396499999996l0 33.773198 491.256222 0L757.627599 178.29396499999996zM140.487278 367.11340099999995l0 33.771151 743.024421 0 0-33.771151L140.487278 367.11340099999995z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="face-smile-fine" unicode="&#58892;" d="M511.558443 852.9315573333333c-246.787686 0-447.597201-200.783932-447.597201-447.598224 0-246.815315 200.783932-447.598224 447.597201-447.598224 246.841921 0 447.64939 200.782909 447.64939 447.598224C959.207833 652.1476253333334 758.400365 852.9315573333333 511.558443 852.9315573333333zM511.558443-4.962310666666667c-226.247884 0-410.295644 184.046736-410.295644 410.295644 0 226.249931 184.072319 410.296667 410.295644 410.296667 226.27449 0 410.346809-184.046736 410.346809-410.296667C921.905252 179.08442633333334 737.832933-4.962310666666667 511.558443-4.962310666666667zM724.38055 303.5726953333334c-9.698896 3.457752-20.366863-1.566682-23.848151-11.264555-28.500101-79.45461-104.372116-132.844587-188.82353-132.844587-84.798315 0-160.770614 53.689806-189.070146 133.590578-3.432169 9.723455-14.075577 14.772448-23.823592 11.364839-9.699919-3.432169-14.797008-14.100136-11.364839-23.823592 33.547047-94.77248 123.668601-158.434405 224.234017-158.434405 100.142791 0 190.140525 63.314001 223.935212 157.564595C739.125369 289.3978573333334 734.102982 300.0903843333334 724.38055 303.5726953333334zM302.49494 515.3479593333334c0-24.653493 19.98517-44.638663 44.638663-44.638663 24.653493 0 44.638663 19.98517 44.638663 44.638663s-19.98517 44.63764-44.638663 44.63764C322.48011 559.9855993333333 302.49494 540.0014523333333 302.49494 515.3479593333334L302.49494 515.3479593333334zM631.398856 515.3479593333334c0-24.653493 19.98517-44.638663 44.63764-44.638663 24.653493 0 44.63764 19.98517 44.63764 44.638663s-19.984147 44.63764-44.63764 44.63764C651.384026 559.9855993333333 631.398856 540.0014523333333 631.398856 515.3479593333334L631.398856 515.3479593333334z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="picture-fine" unicode="&#58893;" d="M958.648085 84.30682933333333L65.772494 84.30682933333333 65.772494 721.9115253333333l892.87559 0L958.648085 84.30682933333333zM97.660762 116.20328333333339l829.099055 0L926.759817 690.0570263333334 97.660762 690.0570263333334 97.660762 116.20328333333339zM648.731616 419.05893933333334l-1.991354 0c-47.801702 0-86.696548 38.900985-86.696548 86.695524l0 1.978051c0 47.809889 38.894845 86.671988 86.696548 86.671988l1.991354 0c47.801702 0 86.698594-38.862099 86.698594-86.671988l0-1.978051C735.43021 457.95992433333333 696.533318 419.05893933333334 648.731616 419.05893933333334zM646.740262 562.5193053333333c-30.224372 0-54.810327-24.582885-54.810327-54.787814l0-1.978051c0-30.230512 24.584931-54.803163 54.810327-54.803163l1.991354 0c30.222325 0 54.810327 24.572652 54.810327 54.803163l0 1.978051c0 30.203906-24.586978 54.787814-54.810327 54.787814L646.740262 562.5193053333333zM91.097276 181.7900473333334l-22.748097 22.338774 274.373974 279.332916 22.750143-22.351054L91.097276 181.7900473333334zM604.886015 215.92242633333342L339.999113 480.74793033333333l22.548552 22.525016L627.433544 238.4638153333334 604.886015 215.92242633333342zM619.007641 202.70744933333333l-22.763446 22.337751 167.989015 171.035398 22.765493-22.350031L619.007641 202.70744933333333zM925.622924 222.7939273333334L758.534418 389.8343373333333l22.548552 22.529109 167.086459-167.044504L925.622924 222.7939273333334z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="log" unicode="&#58894;" d="M828.01742 700.357158C743.476979 784.899646 631.076002 831.458031 511.516999 831.458031c-119.55798 0-231.959979-46.558385-316.500421-131.09985C110.47716 615.81774 63.918775 503.41574 63.918775 383.85776c0-87.103824 25.045419-171.548074 72.429613-244.204861 9.393951-14.402011 28.685319-18.46249 43.087331-9.071609 14.404058 9.393951 18.46556 28.685319 9.072633 43.089377-40.768519 62.511729-62.317301 135.194098-62.317301 210.187093 0 212.469066 172.85586 385.326972 385.325949 385.326972s385.325949-172.857906 385.325949-385.326972-172.85586-385.326972-385.325949-385.326972c-70.357418 0-139.188062 19.131733-199.052498 55.323003-14.71412 8.900717-33.856086 4.180206-42.753733-10.534937-8.896624-14.71719-4.180206-33.856086 10.534937-42.753733 69.584821-42.070164 149.556201-64.307631 231.271294-64.307631 119.559003 0 231.959979 46.558385 316.500421 131.09985 84.539418 84.539418 131.097804 196.941418 131.097804 316.499397S912.556838 615.81774 828.01742 700.357158zM494.28964 690.216193c-21.782096 0-39.397289-17.658172-39.397289-39.439244l0-283.524378c0-1.360997 0.358157-2.706645 0.493234-4.03285 2.020006-19.886933 18.959817-34.573423 39.379892-34.573423l0 0 0.146333 0.832971 223.590358 0c21.782096 0 39.438221 17.616216 39.438221 39.397289s-17.658172 39.397289-39.439244 39.397289L533.686928 408.273846l0 242.503103C533.686928 672.5580219999999 516.071735 690.216193 494.28964 690.216193z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="list" unicode="&#58890;" d="M618.04471 733.97072l-397.175835 0c-16.927531 0-30.699186-13.771655-30.699186-30.699186l0-638.543068c0-16.927531 13.771655-30.699186 30.699186-30.699186l582.261227 0c16.927531 0 30.699186 13.771655 30.699186 30.699186l-0.726547 476.760404L618.04471 733.97072zM803.771715 541.488871 619.537713 541.488871 619.537713 705.552483 803.771715 541.488871zM813.363164 64.728466c0-5.64251-4.590552-10.233062-10.233062-10.233062l-582.261227 0c-5.64251 0-10.233062 4.590552-10.233062 10.233062l0 638.543068c0 5.64251 4.590552 10.233062 10.233062 10.233062l378.202715 0 0-192.481849 214.291574 0L813.363164 64.728466zM298.129516 482.495268l55.258535 0 0-55.258535-55.258535 0 0 55.258535ZM399.777591 468.168981l323.364759 0 0-26.605961-323.364759 0 0 26.605961ZM298.129516 342.044446l55.258535 0 0-55.258535-55.258535 0 0 55.258535ZM399.777591 327.718159l323.364759 0 0-26.605961-323.364759 0 0 26.605961ZM298.129516 199.804884l55.258535 0 0-55.258535-55.258535 0 0 55.258535ZM399.777591 185.478598l323.364759 0 0-26.605961-323.364759 0 0 26.605961ZM881.315812 53.053566"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="release" unicode="&#58889;" d="M990.78144 828.5388800000001c-3.35872 1.59744-7.04512 2.37568-11.01824 2.37568-14.45888 0-27.60704-10.81344-27.40224-10.81344-8.8064-4.42368-880.59904-443.22816-911.44192-459.44832-17.408-9.13408-27.36128-24.73984-25.92768-40.71424 1.10592-13.14816 9.78944-23.51104 23.10144-27.77088 26.17344-8.27392 290.24256-91.58656 290.24256-91.58656l4.83328-1.47456 16.67072 50.05312-254.32064 79.54432 780.73856 406.28224c-82.82112-93.88032-420.53632-476.32384-436.10112-493.93664-20.11136-22.48704-29.4912-45.09696-29.40928-70.98368l0.28672-153.27232-0.08192 0c0 0 0.08192-53.49376 0.08192-53.6576l0-1.96608 0 0c1.18784-13.5168 12.73856-24.24832 26.54208-24.24832s25.51808 10.73152 26.74688 24.24832l0 0c0 0 0.53248 191.03744 0 205.08672-0.49152 12.4928 5.07904 26.54208 10.69056 33.05472 5.65248 6.38976 390.63552 442.61376 465.75616 527.81056-21.38112-106.41408-126.68928-629.76-128.24576-637.41952-0.8192-4.05504-2.58048-4.05504-3.35872-4.05504-0.6144 0-1.31072 0.12288-2.048 0.36864-7.45472 2.37568-268.82048 81.55136-279.92064 84.91008l-4.7104 1.4336-17.16224-50.50368 5.07904-1.59744c2.58048-0.77824 258.90816-79.09376 284.38528-86.46656 5.07904-1.47456 10.24-2.2528 15.44192-2.2528 26.99264 0 49.5616 19.37408 54.8864 46.98112 2.08896 10.93632 27.0336 134.67648 55.9104 277.99552 39.77216 197.14048 84.7872 420.61824 85.93408 427.6224l0.6144 3.31776C1009.70496 798.96576 1013.26848 817.9712 990.78144 828.5388800000001z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="add-circle-fine" unicode="&#58888;" d="M509.989715-60.972421000000054c-246.734474 0-446.75195 200.023616-446.75195 446.75809 0 246.732427 200.017476 446.75195 446.75195 446.75195 246.733451 0 446.757067-200.019523 446.757067-446.75195C956.746782 139.051195 756.723166-60.972421000000054 509.989715-60.972421000000054L509.989715-60.972421000000054zM509.989715 812.433746c-235.633648 0-426.650123-191.014428-426.650123-426.648077 0-235.639788 191.016475-426.654216 426.650123-426.654216 235.638765 0 426.654216 191.014428 426.654216 426.654216C936.643931 621.419318 745.62848 812.433746 509.989715 812.433746L509.989715 812.433746zM527.863804 153.46957999999995l-35.741016 0L492.122789 367.909533 277.678742 367.909533 277.678742 403.653619l214.443024 0L492.121765 618.0956189999999l35.741016 0L527.862781 403.653619l214.442 0 0-35.744086L527.863804 367.909533 527.863804 153.46957999999995 527.863804 153.46957999999995zM527.863804 153.46957999999995"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="ok" unicode="&#58885;" d="M960 640L915.2 684.8 371.2 172.79999999999995 108.8 454.4 64 409.6 358.4 83.20000000000005 364.8 89.60000000000002 371.2 83.20000000000005Z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="help" unicode="&#58887;" d="M690.2 741.8C635.2 783.6 573.2 798 494.6 798c-59.6 0-110.6-12.2-151-39.4C284 718 256 649.8 256 542l153.6 0c0 28.8-2.8 59.8 14 86.4 16.8 26.6 40.2 47 80.4 47 40.8 0 61.8-11.8 81.6-36.2 16.8-20.8 23.2-45.6 23.2-72 0-22.8-11.6-43.8-25.4-62.8-7.6-11.2-17.6-21.2-30.2-30.8 0 0-83-49.4-112.2-96.2-21.8-34.8-29.6-78.4-31.4-130.6-0.2-3.8 1.2-11.6 14.4-11.6 13 0 112 0 123.6 0 11.6 0 14 8.8 14.2 12.4 0.8 19 3.2 48.2 6.6 59.2 6.6 20.8 19.4 39 39.4 54.6l41.4 28.6c37.4 29.2 67.2 53 80.4 71.8 22.6 30.8 38.4 68.8 38.4 113.8C768 649 741 703.2 690.2 741.8zM484 155.6c-51.8 1.6-94.6-34.4-96.4-90.6-1.6-56.4 39-93.4 91-95 54-1.6 95.8 33.2 97.4 89.4C577.6 115.6 538 154 484 155.6z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="chat" unicode="&#58886;" d="M132.682393 414.567179c0 208.287837 166.471452 377.143593 379.317095 377.143593s385.380184-168.855756 385.380184-377.143593c0-177.196725-122.197086-325.812507-290.49821-366.259708l-116.291586-51.04763 0 41.126676C290.570353 52.175568999999996 132.682393 215.31206599999996 132.682393 414.567179zM83.799056 414.567179c0-211.946157 160.764474-387.135154 369.469819-415.152255-3.2623-20.458961-10.036587-65.024969-7.286963-65.024969 2.384303 0 114.89068 47.294143 189.700503 78.865185 176.193885 51.91437 304.518528 211.946157 304.518528 401.312038 0 231.432976-191.70823 419.042865-428.200432 419.042865S83.799056 646.0001560000001 83.799056 414.567179zM340.71952 276.63573699999995c22.935362-41.481763 89.831958-75.102489 170.391738-75.102489 79.650061 0 148.489916 32.909527 172.168198 73.681116-12.701277 5.979178-19.068288 8.02886-28.131711 12.21009-19.894096-31.257911-75.425853-59.661821-142.729725-59.661821-66.969251 0-122.836653 28.40391-143.598512 61.083194L340.71952 276.63573699999995z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="top" unicode="&#58884;" d="M812 153.4l-300 172.8-300-172.8 300 604L812 153.4zM264.5 209.2l247.5 142.5 247.5-142.5L512 707.5 264.5 209.2zM371.7 138.3l0-126.2-15.9 0 0 126.2-45.9 0L309.9 153l107.4 0 0-14.8L371.7 138.2zM506.6 154.5c26.6 0 43.3-3.9 50-11.7 6.7-7.8 10-27.2 10-58.3 0-33.5-3.2-54.2-9.6-62-6.4-7.8-23.2-11.8-50.4-11.8-27 0-43.8 3.9-50.3 11.7-6.5 7.8-9.8 27.9-9.8 60.3l0 9.9 0.2 13.3c0 18.7 4.2 31.5 12.6 38.4C467.8 151 483.5 154.5 506.6 154.5zM506.5 141c-22.3 0-35.3-2.5-39.1-7.4-3.8-5-5.7-22-5.7-51 0-29.1 1.9-46.1 5.7-51.1 3.8-5 16.8-7.4 39.1-7.4 22.4 0 35.4 2.5 39.2 7.4 3.8 5 5.7 22 5.7 51.1l0 9.2-0.1 13.3c0 15.6-2.6 25.4-7.8 29.6S525.9 141 506.5 141zM608.4 12.1 608.4 153l59.2 0 5.4 0c15.9 0 26.7-3.1 32.5-9.2 5.8-6.1 8.7-17.6 8.7-34.4 0-16.1-3-27.1-9-32.9-6-5.9-17.3-8.8-33.9-8.8l-6.2-0.1-40.7 0 0-55.5L608.4 12.1zM624.3 81.1l37.7 0c15.8 0 25.9 1.6 30.3 4.9 4.4 3.2 6.7 10.7 6.7 22.3 0 13.6-1.5 22.2-4.5 25.9-3 3.6-10.1 5.4-21.3 5.4l-6.1 0.1-42.7 0L624.4 81.1z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="right" unicode="&#58882;" d="M283.648 721.9189759999999L340.873216 780.926976 740.352 383.99795200000005 340.876288-12.925952000000052 283.648 46.07795199999998 619.52 383.99795200000005Z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="left" unicode="&#58883;" d="M740.352 721.9189759999999L683.126784 780.926976 283.648 383.99795200000005 683.123712-12.925952000000052 740.352 46.07795199999998 404.48 383.99795200000005Z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="star" unicode="&#58880;" d="M749.624889-84.152889c-15.672889 0-31.246222 3.882667-45.084444 11.306667l-192.526222 103.637333L319.544889-72.817778c-31.203556-16.64-70.314667-14.392889-99.043556 5.304889-29.511111 20.337778-44.743111 55.921778-38.840889 90.695111l37.703111 225.251556L56.661333 410.908444c-25.002667 24.888889-33.464889 60.984889-22.058667 94.193778 11.349333 32.910222 40.064 56.576 74.965333 61.752889l221.326222 32.896 96.128 199.580444c15.488 32.085333 48.853333 52.807111 84.992 52.807111 36.167111 0 69.518222-20.736 84.963556-52.807111l96.156444-199.580444 221.297778-32.910222c34.872889-5.162667 63.616-28.8 74.979556-61.696 11.392-33.28 2.944-69.361778-22.030222-94.250667L804.622222 248.433778l37.745778-225.28c5.845333-34.773333-9.386667-70.357333-38.812444-90.638222C787.569778-78.392889 768.938667-84.152889 749.624889-84.152889zM512.014222 91.548444c4.636444 0 9.272889-1.137778 13.482667-3.384889l205.937778-110.862222c12.373333-6.641778 28.316444-5.802667 39.936 2.133333 11.392 7.836444 17.123556 21.006222 14.890667 34.304L746.097778 253.496889c-1.507556 9.088 1.450667 18.332444 7.964444 24.832l173.141333 172.842667c9.457778 9.429333 12.686222 23.025778 8.405333 35.484444-4.380444 12.672-15.701333 21.873778-29.525333 23.921778L669.866667 545.706667c-9.315556 1.379556-17.365333 7.296-21.447111 15.786667L545.720889 774.641778c-6.030222 12.529778-19.256889 20.608-33.706667 20.608s-27.690667-8.092444-33.763556-20.622222L375.608889 561.493333c-4.081778-8.490667-12.131556-14.407111-21.447111-15.786667L117.930667 510.577778c-13.624889-2.033778-25.201778-11.434667-29.539556-23.992889-4.266667-12.416-1.024-25.984 8.433778-35.399111L269.937778 278.328889c6.513778-6.499556 9.472-15.744 7.964444-24.832l-40.135111-239.744c-2.247111-13.312 3.484444-26.439111 14.976-34.360889 11.434667-7.836444 27.349333-8.775111 39.950222-2.062222l205.852444 110.833778C502.741333 90.410667 507.377778 91.548444 512.014222 91.548444zM200.32 439.210667c-6.840889 0-12.885333 4.963556-14.023111 11.946667-1.251556 7.751111 4.010667 15.061333 11.761778 16.312889l9.443556 1.536c7.793778 1.336889 15.061333-4.010667 16.312889-11.761778 1.251556-7.751111-4.010667-15.061333-11.761778-16.312889l-9.443556-1.536C201.856 439.267556 201.073778 439.210667 200.32 439.210667zM252.544 447.687111c-6.684444 0-12.643556 4.721778-13.937778 11.534222-1.493333 7.708444 3.555556 15.175111 11.264 16.654222l153.927111 29.696 58.055111 133.148444c3.157333 7.182222 11.548444 10.496 18.716444 7.352889 7.210667-3.143111 10.510222-11.52 7.367111-18.716444l-61.056-140.017778c-1.877333-4.295111-5.745778-7.395556-10.353778-8.277333l-161.28-31.118222C254.336 447.758222 253.44 447.687111 252.544 447.687111z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="download-circle" unicode="&#58881;" d="M510.771521 828.211081c-244.998947 0-443.597097-198.60429-443.597097-443.590957s198.59815-443.591981 443.597097-443.591981c244.986667 0 443.583794 198.60429 443.583794 443.591981S755.758188 828.211081 510.771521 828.211081zM510.771521-30.044013999999947c-229.010811 0-414.664138 185.65435-414.664138 414.664138 0 229.010811 185.653327 414.657998 414.664138 414.657998 228.996484 0 414.652881-185.647187 414.652881-414.657998C925.424402 155.60931300000004 739.768005-30.044013999999947 510.771521-30.044013999999947zM662.749888 352.39518799999996L537.719266 245.82501100000002l0 324.388065c0 14.887059-12.06478 26.953885-26.947745 26.953885-14.894222 0-26.961048-12.066827-26.961048-26.953885l0-325.410348L357.936647 352.39518799999996c-10.56359 10.599406-27.693736 10.599406-38.267559 0-10.56359-10.596336-10.56359-27.777647 0-38.375006l170.181961-161.220868c5.629207-5.652743 13.111622-8.060583 20.49887-7.680936 7.373944-0.379647 14.859429 2.02717 20.488637 7.680936l170.181961 161.220868c10.562567 10.597359 10.562567 27.77867 0 38.375006C690.443623 362.99561700000004 673.313477 362.99561700000004 662.749888 352.39518799999996z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="close" unicode="&#4102;" d="M783.483 701.249L512 429.775 240.517 701.249c-10.082 10.083-26.429 10.083-36.51 0-10.083-10.082-10.083-26.429 0-36.509l271.481-271.475L204.008 121.78800000000001c-10.083-10.081-10.083-26.428 0-36.508 10.082-10.082 26.429-10.082 36.51 0L512 356.755l271.483-271.475c10.082-10.082 26.429-10.082 36.513 0 10.081 10.083 10.081 26.428 0 36.508L548.51 393.265l271.485 271.474c10.081 10.083 10.081 26.429 0 36.509C809.912 711.33 793.564 711.33 783.483 701.249z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="close-fill" unicode="&#4103;" d="M512 822.022125c-217.47508 0-394.423141-176.949085-394.423141-394.423141 0-217.474057 176.948061-394.422118 394.423141-394.422118 217.473033 0 394.422118 176.948061 394.422118 394.422118C906.422118 645.07304 729.473033 822.022125 512 822.022125zM702.228529 270.92978200000005c8.030907-8.030907 8.030907-21.052478 0-29.083385s-21.052478-8.030907-29.083385 0L512 402.992563 350.853833 241.84741899999995c-8.030907-8.030907-21.052478-8.030907-29.083385 0s-8.030907 21.052478 0 29.083385l161.146167 161.146167L321.771471 593.222115c-8.030907 8.030907-8.030907 21.052478 0 29.083385s21.052478 8.030907 29.083385 0l161.146167-161.146167L673.145144 622.305501c8.030907 8.030907 21.052478 8.030907 29.083385 0s8.030907-21.052478 0-29.083385L541.082362 432.075949 702.228529 270.92978200000005z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="ok-circle" unicode="&#4101;" d="M516.152065-63.152063c-60.696384 0-119.594819 11.894911-175.056991 35.353183-53.55473 22.651906-101.646028 55.073316-142.936433 96.364745-41.291428 41.291428-73.712839 89.381703-96.363721 142.936433-23.458271 55.462173-35.353183 114.359584-35.353183 175.055968s11.894911 119.594819 35.353183 175.056991c22.651906 53.55473 55.073316 101.646028 96.363721 142.936433 41.290405 41.291428 89.381703 73.712839 142.936433 96.363721 55.462173 23.458271 114.359584 35.353183 175.056991 35.353183s119.594819-11.894911 175.056991-35.353183c53.55473-22.651906 101.645005-55.073316 142.936433-96.363721 41.291428-41.290405 73.711815-89.38068 96.363721-142.936433 23.459295-55.462173 35.353183-114.359584 35.353183-175.056991 0-60.696384-11.893888-119.593795-35.353183-175.055968-22.651906-53.55473-55.072293-101.645005-96.363721-142.936433s-89.381703-73.712839-142.936433-96.364745C635.747907-51.25715200000002 576.849472-63.152063 516.152065-63.152063zM516.152065 774.870222c-214.115566 0-388.311956-174.196391-388.311956-388.311956s174.196391-388.311956 388.311956-388.311956 388.311956 174.196391 388.311956 388.311956S730.268654 774.870222 516.152065 774.870222zM434.74908 132.830517L209.49278 358.08784 289.087583 437.68162 434.74908 292.020122 743.218594 600.488613 822.812373 520.89381Z"  horiz-adv-x="1024" />
+      
+    </font>
+  </defs>
+</svg>
diff --git a/ruoyi-admin/src/main/resources/static/fonts/iconfont.ttf b/ruoyi-admin/src/main/resources/static/fonts/iconfont.ttf
new file mode 100644
index 0000000..6e84a89
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/fonts/iconfont.ttf
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/fonts/iconfont.woff b/ruoyi-admin/src/main/resources/static/fonts/iconfont.woff
new file mode 100644
index 0000000..acd7ed6
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/fonts/iconfont.woff
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/fonts/zenicon.woff b/ruoyi-admin/src/main/resources/static/fonts/zenicon.woff
new file mode 100644
index 0000000..8dd67e0
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/fonts/zenicon.woff
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/html/ie.html b/ruoyi-admin/src/main/resources/static/html/ie.html
new file mode 100644
index 0000000..166c60a
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/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 的早期版本(IE9以下版本或使用该内核的浏览器)。这意味着在升级浏览器前,您将无法访问此网站。</p>
+<hr>
+<h2>请注意:微软公司对Windows XP 及 Internet Explorer 早期版本的支持已经结束</h2>
+<p>自 2016 年 1 月 12 日起,Microsoft 不再为 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/ruoyi-admin/src/main/resources/static/i18n/messages.properties b/ruoyi-admin/src/main/resources/static/i18n/messages.properties
new file mode 100644
index 0000000..8f65ed2
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/i18n/messages.properties
@@ -0,0 +1,37 @@
+#错误消息
+not.null=* 必须填写
+user.jcaptcha.error=验证码错误
+user.not.exists=用户不存在/密码错误
+user.password.not.match=用户不存在/密码错误
+user.password.retry.limit.count=密码输入错误{0}次
+user.password.retry.limit.exceed=密码输入错误{0}次,帐户锁定10分钟
+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/ruoyi-admin/src/main/resources/static/img/blue.png b/ruoyi-admin/src/main/resources/static/img/blue.png
new file mode 100644
index 0000000..7081c95
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/img/blue.png
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/img/loading-upload.gif b/ruoyi-admin/src/main/resources/static/img/loading-upload.gif
new file mode 100644
index 0000000..6fba776
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/img/loading-upload.gif
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/img/loading.gif b/ruoyi-admin/src/main/resources/static/img/loading.gif
new file mode 100644
index 0000000..2c0238a
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/img/loading.gif
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/img/locked.png b/ruoyi-admin/src/main/resources/static/img/locked.png
new file mode 100644
index 0000000..c831c1f
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/img/locked.png
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/img/login-background.jpg b/ruoyi-admin/src/main/resources/static/img/login-background.jpg
new file mode 100644
index 0000000..adfa3f9
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/img/login-background.jpg
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/img/pay.png b/ruoyi-admin/src/main/resources/static/img/pay.png
new file mode 100644
index 0000000..bb8b967
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/img/pay.png
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/img/profile.jpg b/ruoyi-admin/src/main/resources/static/img/profile.jpg
new file mode 100644
index 0000000..b3a940b
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/img/profile.jpg
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/img/progress.png b/ruoyi-admin/src/main/resources/static/img/progress.png
new file mode 100644
index 0000000..717c486
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/img/progress.png
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/img/qr_code.png b/ruoyi-admin/src/main/resources/static/img/qr_code.png
new file mode 100644
index 0000000..f274086
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/img/qr_code.png
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/img/user.png b/ruoyi-admin/src/main/resources/static/img/user.png
new file mode 100644
index 0000000..7f77fd0
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/img/user.png
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/js/bootstrap.min.js b/ruoyi-admin/src/main/resources/static/js/bootstrap.min.js
new file mode 100644
index 0000000..9f359aa
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/js/bootstrap.min.js
@@ -0,0 +1,6 @@
+/*!
+ * Bootstrap v3.3.7 (http://getbootstrap.com)
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under the MIT license
+ */
+if(typeof jQuery==="undefined"){throw new Error("Bootstrap's JavaScript requires jQuery")}+function(b){var a=b.fn.jquery.split(" ")[0].split(".");if((a[0]<2&&a[1]<9)||(a[0]==1&&a[1]==9&&a[2]<1)||(a[0]>3)){throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4")}}(jQuery);+function(b){function a(){var e=document.createElement("bootstrap");var d={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in d){if(e.style[c]!==undefined){return{end:d[c]}}}return false}b.fn.emulateTransitionEnd=function(e){var d=false;var c=this;b(this).one("bsTransitionEnd",function(){d=true});var f=function(){if(!d){b(c).trigger(b.support.transition.end)}};setTimeout(f,e);return this};b(function(){b.support.transition=a();if(!b.support.transition){return}b.event.special.bsTransitionEnd={bindType:b.support.transition.end,delegateType:b.support.transition.end,handle:function(c){if(b(c.target).is(this)){return c.handleObj.handler.apply(this,arguments)}}}})}(jQuery);+function(e){var d='[data-dismiss="alert"]';var b=function(f){e(f).on("click",d,this.close)};b.VERSION="3.3.7";b.TRANSITION_DURATION=150;b.prototype.close=function(j){var i=e(this);var g=i.attr("data-target");if(!g){g=i.attr("href");g=g&&g.replace(/.*(?=#[^\s]*$)/,"")}var h=e(g==="#"?[]:g);if(j){j.preventDefault()}if(!h.length){h=i.closest(".alert")}h.trigger(j=e.Event("close.bs.alert"));if(j.isDefaultPrevented()){return}h.removeClass("in");function f(){h.detach().trigger("closed.bs.alert").remove()}e.support.transition&&h.hasClass("fade")?h.one("bsTransitionEnd",f).emulateTransitionEnd(b.TRANSITION_DURATION):f()};function c(f){return this.each(function(){var h=e(this);var g=h.data("bs.alert");if(!g){h.data("bs.alert",(g=new b(this)))}if(typeof f=="string"){g[f].call(h)}})}var a=e.fn.alert;e.fn.alert=c;e.fn.alert.Constructor=b;e.fn.alert.noConflict=function(){e.fn.alert=a;return this};e(document).on("click.bs.alert.data-api",d,b.prototype.close)}(jQuery);+function(d){var b=function(f,e){this.$element=d(f);this.options=d.extend({},b.DEFAULTS,e);this.isLoading=false};b.VERSION="3.3.7";b.DEFAULTS={loadingText:"loading..."};b.prototype.setState=function(g){var i="disabled";var e=this.$element;var h=e.is("input")?"val":"html";var f=e.data();g+="Text";if(f.resetText==null){e.data("resetText",e[h]())}setTimeout(d.proxy(function(){e[h](f[g]==null?this.options[g]:f[g]);if(g=="loadingText"){this.isLoading=true;e.addClass(i).attr(i,i).prop(i,true)}else{if(this.isLoading){this.isLoading=false;e.removeClass(i).removeAttr(i).prop(i,false)}}},this),0)};b.prototype.toggle=function(){var f=true;var e=this.$element.closest('[data-toggle="buttons"]');if(e.length){var g=this.$element.find("input");if(g.prop("type")=="radio"){if(g.prop("checked")){f=false}e.find(".active").removeClass("active");this.$element.addClass("active")}else{if(g.prop("type")=="checkbox"){if((g.prop("checked"))!==this.$element.hasClass("active")){f=false}this.$element.toggleClass("active")}}g.prop("checked",this.$element.hasClass("active"));if(f){g.trigger("change")}}else{this.$element.attr("aria-pressed",!this.$element.hasClass("active"));this.$element.toggleClass("active")}};function c(e){return this.each(function(){var h=d(this);var g=h.data("bs.button");var f=typeof e=="object"&&e;if(!g){h.data("bs.button",(g=new b(this,f)))}if(e=="toggle"){g.toggle()}else{if(e){g.setState(e)}}})}var a=d.fn.button;d.fn.button=c;d.fn.button.Constructor=b;d.fn.button.noConflict=function(){d.fn.button=a;return this};d(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(g){var f=d(g.target).closest(".btn");c.call(f,"toggle");if(!(d(g.target).is('input[type="radio"], input[type="checkbox"]'))){g.preventDefault();if(f.is("input,button")){f.trigger("focus")}else{f.find("input:visible,button:visible").first().trigger("focus")}}}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(f){d(f.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(f.type))})}(jQuery);+function(c){var d=function(g,f){this.$element=c(g);this.$indicators=this.$element.find(".carousel-indicators");this.options=f;this.paused=null;this.sliding=null;this.interval=null;this.$active=null;this.$items=null;this.options.keyboard&&this.$element.on("keydown.bs.carousel",c.proxy(this.keydown,this));this.options.pause=="hover"&&!("ontouchstart" in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",c.proxy(this.pause,this)).on("mouseleave.bs.carousel",c.proxy(this.cycle,this))};d.VERSION="3.3.7";d.TRANSITION_DURATION=600;d.DEFAULTS={interval:5000,pause:"hover",wrap:true,keyboard:true};d.prototype.keydown=function(f){if(/input|textarea/i.test(f.target.tagName)){return}switch(f.which){case 37:this.prev();break;case 39:this.next();break;default:return}f.preventDefault()};d.prototype.cycle=function(f){f||(this.paused=false);this.interval&&clearInterval(this.interval);this.options.interval&&!this.paused&&(this.interval=setInterval(c.proxy(this.next,this),this.options.interval));return this};d.prototype.getItemIndex=function(f){this.$items=f.parent().children(".item");return this.$items.index(f||this.$active)};d.prototype.getItemForDirection=function(j,i){var f=this.getItemIndex(i);var g=(j=="prev"&&f===0)||(j=="next"&&f==(this.$items.length-1));if(g&&!this.options.wrap){return i}var k=j=="prev"?-1:1;var h=(f+k)%this.$items.length;return this.$items.eq(h)};d.prototype.to=function(h){var g=this;var f=this.getItemIndex(this.$active=this.$element.find(".item.active"));if(h>(this.$items.length-1)||h<0){return}if(this.sliding){return this.$element.one("slid.bs.carousel",function(){g.to(h)})}if(f==h){return this.pause().cycle()}return this.slide(h>f?"next":"prev",this.$items.eq(h))};d.prototype.pause=function(f){f||(this.paused=true);if(this.$element.find(".next, .prev").length&&c.support.transition){this.$element.trigger(c.support.transition.end);this.cycle(true)}this.interval=clearInterval(this.interval);return this};d.prototype.next=function(){if(this.sliding){return}return this.slide("next")};d.prototype.prev=function(){if(this.sliding){return}return this.slide("prev")};d.prototype.slide=function(m,i){var p=this.$element.find(".item.active");var g=i||this.getItemForDirection(m,p);var k=this.interval;var n=m=="next"?"left":"right";var j=this;if(g.hasClass("active")){return(this.sliding=false)}var l=g[0];var f=c.Event("slide.bs.carousel",{relatedTarget:l,direction:n});this.$element.trigger(f);if(f.isDefaultPrevented()){return}this.sliding=true;k&&this.pause();if(this.$indicators.length){this.$indicators.find(".active").removeClass("active");var h=c(this.$indicators.children()[this.getItemIndex(g)]);h&&h.addClass("active")}var o=c.Event("slid.bs.carousel",{relatedTarget:l,direction:n});if(c.support.transition&&this.$element.hasClass("slide")){g.addClass(m);g[0].offsetWidth;p.addClass(n);g.addClass(n);p.one("bsTransitionEnd",function(){g.removeClass([m,n].join(" ")).addClass("active");p.removeClass(["active",n].join(" "));j.sliding=false;setTimeout(function(){j.$element.trigger(o)},0)}).emulateTransitionEnd(d.TRANSITION_DURATION)}else{p.removeClass("active");g.addClass("active");this.sliding=false;this.$element.trigger(o)}k&&this.cycle();return this};function b(f){return this.each(function(){var j=c(this);var i=j.data("bs.carousel");var g=c.extend({},d.DEFAULTS,j.data(),typeof f=="object"&&f);var h=typeof f=="string"?f:g.slide;if(!i){j.data("bs.carousel",(i=new d(this,g)))}if(typeof f=="number"){i.to(f)}else{if(h){i[h]()}else{if(g.interval){i.pause().cycle()}}}})}var a=c.fn.carousel;c.fn.carousel=b;c.fn.carousel.Constructor=d;c.fn.carousel.noConflict=function(){c.fn.carousel=a;return this};var e=function(k){var g;var j=c(this);var f=c(j.attr("data-target")||(g=j.attr("href"))&&g.replace(/.*(?=#[^\s]+$)/,""));if(!f.hasClass("carousel")){return}var h=c.extend({},f.data(),j.data());var i=j.attr("data-slide-to");if(i){h.interval=false}b.call(f,h);if(i){f.data("bs.carousel").to(i)}k.preventDefault()};c(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e);c(window).on("load",function(){c('[data-ride="carousel"]').each(function(){var f=c(this);b.call(f,f.data())})})}(jQuery);+function(d){var e=function(g,f){this.$element=d(g);this.options=d.extend({},e.DEFAULTS,f);this.$trigger=d('[data-toggle="collapse"][href="#'+g.id+'"],'+'[data-toggle="collapse"][data-target="#'+g.id+'"]');this.transitioning=null;if(this.options.parent){this.$parent=this.getParent()}else{this.addAriaAndCollapsedClass(this.$element,this.$trigger)}if(this.options.toggle){this.toggle()}};e.VERSION="3.3.7";e.TRANSITION_DURATION=350;e.DEFAULTS={toggle:true};e.prototype.dimension=function(){var f=this.$element.hasClass("width");return f?"width":"height"};e.prototype.show=function(){if(this.transitioning||this.$element.hasClass("in")){return}var h;var j=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(j&&j.length){h=j.data("bs.collapse");if(h&&h.transitioning){return}}var g=d.Event("show.bs.collapse");this.$element.trigger(g);if(g.isDefaultPrevented()){return}if(j&&j.length){b.call(j,"hide");h||j.data("bs.collapse",null)}var k=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[k](0).attr("aria-expanded",true);this.$trigger.removeClass("collapsed").attr("aria-expanded",true);this.transitioning=1;var f=function(){this.$element.removeClass("collapsing").addClass("collapse in")[k]("");this.transitioning=0;this.$element.trigger("shown.bs.collapse")};if(!d.support.transition){return f.call(this)}var i=d.camelCase(["scroll",k].join("-"));this.$element.one("bsTransitionEnd",d.proxy(f,this)).emulateTransitionEnd(e.TRANSITION_DURATION)[k](this.$element[0][i])};e.prototype.hide=function(){if(this.transitioning||!this.$element.hasClass("in")){return}var g=d.Event("hide.bs.collapse");this.$element.trigger(g);if(g.isDefaultPrevented()){return}var h=this.dimension();this.$element[h](this.$element[h]())[0].offsetHeight;this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",false);this.$trigger.addClass("collapsed").attr("aria-expanded",false);this.transitioning=1;var f=function(){this.transitioning=0;this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};if(!d.support.transition){return f.call(this)}this.$element[h](0).one("bsTransitionEnd",d.proxy(f,this)).emulateTransitionEnd(e.TRANSITION_DURATION)};e.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};e.prototype.getParent=function(){return d(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(d.proxy(function(h,g){var f=d(g);this.addAriaAndCollapsedClass(c(f),f)},this)).end()};e.prototype.addAriaAndCollapsedClass=function(g,f){var h=g.hasClass("in");g.attr("aria-expanded",h);f.toggleClass("collapsed",!h).attr("aria-expanded",h)};function c(f){var g;var h=f.attr("data-target")||(g=f.attr("href"))&&g.replace(/.*(?=#[^\s]+$)/,"");return d(h)}function b(f){return this.each(function(){var i=d(this);var h=i.data("bs.collapse");var g=d.extend({},e.DEFAULTS,i.data(),typeof f=="object"&&f);if(!h&&g.toggle&&/show|hide/.test(f)){g.toggle=false}if(!h){i.data("bs.collapse",(h=new e(this,g)))}if(typeof f=="string"){h[f]()}})}var a=d.fn.collapse;d.fn.collapse=b;d.fn.collapse.Constructor=e;d.fn.collapse.noConflict=function(){d.fn.collapse=a;return this};d(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(j){var i=d(this);if(!i.attr("data-target")){j.preventDefault()}var f=c(i);var h=f.data("bs.collapse");var g=h?"toggle":i.data();b.call(f,g)})}(jQuery);+function(h){var e=".dropdown-backdrop";var b='[data-toggle="dropdown"]';var a=function(i){h(i).on("click.bs.dropdown",this.toggle)};a.VERSION="3.3.7";function f(k){var i=k.attr("data-target");if(!i){i=k.attr("href");i=i&&/#[A-Za-z]/.test(i)&&i.replace(/.*(?=#[^\s]*$)/,"")}var j=i&&h(i);return j&&j.length?j:k.parent()}function d(i){if(i&&i.which===3){return}h(e).remove();h(b).each(function(){var l=h(this);var k=f(l);var j={relatedTarget:this};if(!k.hasClass("open")){return}if(i&&i.type=="click"&&/input|textarea/i.test(i.target.tagName)&&h.contains(k[0],i.target)){return}k.trigger(i=h.Event("hide.bs.dropdown",j));if(i.isDefaultPrevented()){return}l.attr("aria-expanded","false");k.removeClass("open").trigger(h.Event("hidden.bs.dropdown",j))})}a.prototype.toggle=function(m){var l=h(this);if(l.is(".disabled, :disabled")){return}var k=f(l);var j=k.hasClass("open");d();if(!j){if("ontouchstart" in document.documentElement&&!k.closest(".navbar-nav").length){h(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(h(this)).on("click",d)}var i={relatedTarget:this};k.trigger(m=h.Event("show.bs.dropdown",i));if(m.isDefaultPrevented()){return}l.trigger("focus").attr("aria-expanded","true");k.toggleClass("open").trigger(h.Event("shown.bs.dropdown",i))}return false};a.prototype.keydown=function(m){if(!/(38|40|27|32)/.test(m.which)||/input|textarea/i.test(m.target.tagName)){return}var l=h(this);m.preventDefault();m.stopPropagation();if(l.is(".disabled, :disabled")){return}var k=f(l);var j=k.hasClass("open");if(!j&&m.which!=27||j&&m.which==27){if(m.which==27){k.find(b).trigger("focus")}return l.trigger("click")}var n=" li:not(.disabled):visible a";var o=k.find(".dropdown-menu"+n);if(!o.length){return}var i=o.index(m.target);if(m.which==38&&i>0){i--}if(m.which==40&&i<o.length-1){i++}if(!~i){i=0}o.eq(i).trigger("focus")};function g(i){return this.each(function(){var k=h(this);var j=k.data("bs.dropdown");if(!j){k.data("bs.dropdown",(j=new a(this)))}if(typeof i=="string"){j[i].call(k)}})}var c=h.fn.dropdown;h.fn.dropdown=g;h.fn.dropdown.Constructor=a;h.fn.dropdown.noConflict=function(){h.fn.dropdown=c;return this};h(document).on("click.bs.dropdown.data-api",d).on("click.bs.dropdown.data-api",".dropdown form",function(i){i.stopPropagation()}).on("click.bs.dropdown.data-api",b,a.prototype.toggle).on("keydown.bs.dropdown.data-api",b,a.prototype.keydown).on("keydown.bs.dropdown.data-api",".dropdown-menu",a.prototype.keydown)}(jQuery);+function(d){var b=function(f,e){this.options=e;this.$body=d(document.body);this.$element=d(f);this.$dialog=this.$element.find(".modal-dialog");this.$backdrop=null;this.isShown=null;this.originalBodyPad=null;this.scrollbarWidth=0;this.ignoreBackdropClick=false;if(this.options.remote){this.$element.find(".modal-content").load(this.options.remote,d.proxy(function(){this.$element.trigger("loaded.bs.modal")},this))}};b.VERSION="3.3.7";b.TRANSITION_DURATION=300;b.BACKDROP_TRANSITION_DURATION=150;b.DEFAULTS={backdrop:true,keyboard:true,show:true};b.prototype.toggle=function(e){return this.isShown?this.hide():this.show(e)};b.prototype.show=function(h){var f=this;var g=d.Event("show.bs.modal",{relatedTarget:h});this.$element.trigger(g);if(this.isShown||g.isDefaultPrevented()){return}this.isShown=true;this.checkScrollbar();this.setScrollbar();this.$body.addClass("modal-open");this.escape();this.resize();this.$element.on("click.dismiss.bs.modal",'[data-dismiss="modal"]',d.proxy(this.hide,this));this.$dialog.on("mousedown.dismiss.bs.modal",function(){f.$element.one("mouseup.dismiss.bs.modal",function(i){if(d(i.target).is(f.$element)){f.ignoreBackdropClick=true}})});this.backdrop(function(){var j=d.support.transition&&f.$element.hasClass("fade");if(!f.$element.parent().length){f.$element.appendTo(f.$body)}f.$element.show().scrollTop(0);f.adjustDialog();if(j){f.$element[0].offsetWidth}f.$element.addClass("in");f.enforceFocus();var i=d.Event("shown.bs.modal",{relatedTarget:h});j?f.$dialog.one("bsTransitionEnd",function(){f.$element.trigger("focus").trigger(i)}).emulateTransitionEnd(b.TRANSITION_DURATION):f.$element.trigger("focus").trigger(i)})};b.prototype.hide=function(f){if(f){f.preventDefault()}f=d.Event("hide.bs.modal");this.$element.trigger(f);if(!this.isShown||f.isDefaultPrevented()){return}this.isShown=false;this.escape();this.resize();d(document).off("focusin.bs.modal");this.$element.removeClass("in").off("click.dismiss.bs.modal").off("mouseup.dismiss.bs.modal");this.$dialog.off("mousedown.dismiss.bs.modal");d.support.transition&&this.$element.hasClass("fade")?this.$element.one("bsTransitionEnd",d.proxy(this.hideModal,this)).emulateTransitionEnd(b.TRANSITION_DURATION):this.hideModal()};b.prototype.enforceFocus=function(){d(document).off("focusin.bs.modal").on("focusin.bs.modal",d.proxy(function(f){if(document!==f.target&&this.$element[0]!==f.target&&!this.$element.has(f.target).length){this.$element.trigger("focus")}},this))};b.prototype.escape=function(){if(this.isShown&&this.options.keyboard){this.$element.on("keydown.dismiss.bs.modal",d.proxy(function(f){f.which==27&&this.hide()},this))}else{if(!this.isShown){this.$element.off("keydown.dismiss.bs.modal")}}};b.prototype.resize=function(){if(this.isShown){d(window).on("resize.bs.modal",d.proxy(this.handleUpdate,this))}else{d(window).off("resize.bs.modal")}};b.prototype.hideModal=function(){var e=this;this.$element.hide();this.backdrop(function(){e.$body.removeClass("modal-open");e.resetAdjustments();e.resetScrollbar();e.$element.trigger("hidden.bs.modal")})};b.prototype.removeBackdrop=function(){this.$backdrop&&this.$backdrop.remove();this.$backdrop=null};b.prototype.backdrop=function(i){var h=this;var f=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var e=d.support.transition&&f;this.$backdrop=d(document.createElement("div")).addClass("modal-backdrop "+f).appendTo(this.$body);this.$element.on("click.dismiss.bs.modal",d.proxy(function(j){if(this.ignoreBackdropClick){this.ignoreBackdropClick=false;return}if(j.target!==j.currentTarget){return}this.options.backdrop=="static"?this.$element[0].focus():this.hide()},this));if(e){this.$backdrop[0].offsetWidth}this.$backdrop.addClass("in");if(!i){return}e?this.$backdrop.one("bsTransitionEnd",i).emulateTransitionEnd(b.BACKDROP_TRANSITION_DURATION):i()}else{if(!this.isShown&&this.$backdrop){this.$backdrop.removeClass("in");var g=function(){h.removeBackdrop();i&&i()};d.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one("bsTransitionEnd",g).emulateTransitionEnd(b.BACKDROP_TRANSITION_DURATION):g()}else{if(i){i()}}}};b.prototype.handleUpdate=function(){this.adjustDialog()};b.prototype.adjustDialog=function(){var e=this.$element[0].scrollHeight>document.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&e?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!e?this.scrollbarWidth:""})};b.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})};b.prototype.checkScrollbar=function(){var f=window.innerWidth;if(!f){var e=document.documentElement.getBoundingClientRect();f=e.right-Math.abs(e.left)}this.bodyIsOverflowing=document.body.clientWidth<f;this.scrollbarWidth=this.measureScrollbar()};b.prototype.setScrollbar=function(){var e=parseInt((this.$body.css("padding-right")||0),10);this.originalBodyPad=document.body.style.paddingRight||"";if(this.bodyIsOverflowing){this.$body.css("padding-right",e+this.scrollbarWidth)}};b.prototype.resetScrollbar=function(){this.$body.css("padding-right",this.originalBodyPad)};b.prototype.measureScrollbar=function(){var f=document.createElement("div");f.className="modal-scrollbar-measure";this.$body.append(f);var e=f.offsetWidth-f.clientWidth;this.$body[0].removeChild(f);return e};function c(e,f){return this.each(function(){var i=d(this);var h=i.data("bs.modal");var g=d.extend({},b.DEFAULTS,i.data(),typeof e=="object"&&e);if(!h){i.data("bs.modal",(h=new b(this,g)))}if(typeof e=="string"){h[e](f)}else{if(g.show){h.show(f)}}})}var a=d.fn.modal;d.fn.modal=c;d.fn.modal.Constructor=b;d.fn.modal.noConflict=function(){d.fn.modal=a;return this};d(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(j){var i=d(this);var g=i.attr("href");var f=d(i.attr("data-target")||(g&&g.replace(/.*(?=#[^\s]+$)/,"")));var h=f.data("bs.modal")?"toggle":d.extend({remote:!/#/.test(g)&&g},f.data(),i.data());if(i.is("a")){j.preventDefault()}f.one("show.bs.modal",function(e){if(e.isDefaultPrevented()){return}f.one("hidden.bs.modal",function(){i.is(":visible")&&i.trigger("focus")})});c.call(f,h,this)})}(jQuery);+function(d){var c=function(f,e){this.type=null;this.options=null;this.enabled=null;this.timeout=null;this.hoverState=null;this.$element=null;this.inState=null;this.init("tooltip",f,e)};c.VERSION="3.3.7";c.TRANSITION_DURATION=150;c.DEFAULTS={animation:true,placement:"top",selector:false,template:'<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:false,container:false,viewport:{selector:"body",padding:0}};c.prototype.init=function(l,j,g){this.enabled=true;this.type=l;this.$element=d(j);this.options=this.getOptions(g);this.$viewport=this.options.viewport&&d(d.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):(this.options.viewport.selector||this.options.viewport));this.inState={click:false,hover:false,focus:false};if(l==="popover"&&this.options.trigger==="hover"){this.options.template='<div class="popover" role="tooltip"><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}if(this.$element[0] instanceof document.constructor&&!this.options.selector){throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!")}var k=this.options.trigger.split(" ");for(var h=k.length;h--;){var f=k[h];if(f=="click"){this.$element.on("click."+this.type,this.options.selector,d.proxy(this.toggle,this))}else{if(f!="manual"){var m=f=="hover"?"mouseenter":"focusin";var e=f=="hover"?"mouseleave":"focusout";this.$element.on(m+"."+this.type,this.options.selector,d.proxy(this.enter,this));if(l!=="popover"||f==="focus"){this.$element.on(e+"."+this.type,this.options.selector,d.proxy(this.leave,this))}}}}this.options.selector?(this._options=d.extend({},this.options,{trigger:"manual",selector:""})):this.fixTitle()};c.prototype.getDefaults=function(){return c.DEFAULTS};c.prototype.getOptions=function(e){e=d.extend({},this.getDefaults(),this.$element.data(),e);if(e.delay&&typeof e.delay=="number"){e.delay={show:e.delay,hide:e.delay}}return e};c.prototype.getDelegateOptions=function(){var e={};var f=this.getDefaults();this._options&&d.each(this._options,function(g,h){if(f[g]!=h){e[g]=h}});return e};c.prototype.enter=function(f){var e=f instanceof this.constructor?f:d(f.currentTarget).data("bs."+this.type);if(!e){e=new this.constructor(f.currentTarget,this.getDelegateOptions());d(f.currentTarget).data("bs."+this.type,e)}if(f instanceof d.Event){e.inState[f.type=="focusin"?"focus":"hover"]=true}if((e.tip().hasClass("in")||e.hoverState=="in")&&!(e.type==="popover"&&e.inState.hover)){e.hoverState="in";return}clearTimeout(e.timeout);e.hoverState="in";if(!e.options.delay||!e.options.delay.show){if(e.type==="popover"&&e.inState.hover){d('[role="tooltip"]').each(function(){d(this).removeClass("in");d(this).remove()})}e.show();if(e.type==="popover"&&e.inState.hover){d(e.$tip).on("mouseleave",this.options.selector,d.proxy(this.leave,this))}return}e.timeout=setTimeout(function(){if(e.hoverState=="in"){e.show()}},e.options.delay.show)};c.prototype.isInStateTrue=function(){for(var e in this.inState){if(this.inState[e]){return true}}return false};c.prototype.leave=function(f){var e=f instanceof this.constructor?f:d(f.currentTarget).data("bs."+this.type);if(!e){e=new this.constructor(f.currentTarget,this.getDelegateOptions());d(f.currentTarget).data("bs."+this.type,e)}if(f instanceof d.Event){e.inState[f.type=="focusout"?"focus":"hover"]=false}if(e.isInStateTrue()){return}clearTimeout(e.timeout);e.hoverState="out";if(!e.options.delay||!e.options.delay.hide){return e.hide()}e.timeout=setTimeout(function(){if(e.hoverState=="out"){e.hide()}},e.options.delay.hide)};c.prototype.show=function(){var o=d.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(o);var p=d.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(o.isDefaultPrevented()||!p){return}var n=this;var l=this.tip();var h=this.getUID(this.type);this.setContent();l.attr("id",h);this.$element.attr("aria-describedby",h);if(this.options.animation){l.addClass("fade")}var k=typeof this.options.placement=="function"?this.options.placement.call(this,l[0],this.$element[0]):this.options.placement;var s=/\s?auto?\s?/i;var t=s.test(k);if(t){k=k.replace(s,"")||"top"}l.detach().css({top:0,left:0,display:"block"}).addClass(k).data("bs."+this.type,this);this.options.container?l.appendTo(this.options.container):l.insertAfter(this.$element);this.$element.trigger("inserted.bs."+this.type);var q=this.getPosition();var f=l[0].offsetWidth;var m=l[0].offsetHeight;if(t){var j=k;var r=this.getPosition(this.$viewport);k=k=="bottom"&&q.bottom+m>r.bottom?"top":k=="top"&&q.top-m<r.top?"bottom":k=="right"&&q.right+f>r.width?"left":k=="left"&&q.left-f<r.left?"right":k;l.removeClass(j).addClass(k)}var i=this.getCalculatedOffset(k,q,f,m);if(this.type==="popover"&&this.options.trigger==="hover"){if(i.left){i.left+=15}}this.applyPlacement(i,k);var g=function(){var e=n.hoverState;n.$element.trigger("shown.bs."+n.type);n.hoverState=null;if(e=="out"){n.leave(n)}};d.support.transition&&this.$tip.hasClass("fade")?l.one("bsTransitionEnd",g).emulateTransitionEnd(c.TRANSITION_DURATION):g()}};c.prototype.applyPlacement=function(j,k){var l=this.tip();var g=l[0].offsetWidth;var q=l[0].offsetHeight;var f=parseInt(l.css("margin-top"),10);var i=parseInt(l.css("margin-left"),10);if(isNaN(f)){f=0}if(isNaN(i)){i=0}j.top+=f;j.left+=i;d.offset.setOffset(l[0],d.extend({using:function(r){l.css({top:Math.round(r.top),left:Math.round(r.left)})}},j),0);l.addClass("in");var e=l[0].offsetWidth;var m=l[0].offsetHeight;if(k=="top"&&m!=q){j.top=j.top+q-m}var p=this.getViewportAdjustedDelta(k,j,e,m);if(p.left){j.left+=p.left}else{j.top+=p.top}var n=/top|bottom/.test(k);var h=n?p.left*2-g+e:p.top*2-q+m;var o=n?"offsetWidth":"offsetHeight";l.offset(j);this.replaceArrow(h,l[0][o],n)};c.prototype.replaceArrow=function(g,e,f){this.arrow().css(f?"left":"top",50*(1-g/e)+"%").css(f?"top":"left","")};c.prototype.setContent=function(){var f=this.tip();var e=this.getTitle();f.find(".tooltip-inner")[this.options.html?"html":"text"](e);f.removeClass("fade in top bottom left right")};c.prototype.hide=function(j){var g=this;var i=d(this.$tip);var h=d.Event("hide.bs."+this.type);function f(){if(g.hoverState!="in"){i.detach()}if(g.$element){g.$element.removeAttr("aria-describedby").trigger("hidden.bs."+g.type)}j&&j()}this.$element.trigger(h);if(h.isDefaultPrevented()){return}i.removeClass("in");d.support.transition&&i.hasClass("fade")?i.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f();this.hoverState=null;return this};c.prototype.fixTitle=function(){var e=this.$element;if(e.attr("title")||typeof e.attr("data-original-title")!="string"){e.attr("data-original-title",e.attr("title")||"").attr("title","")}};c.prototype.hasContent=function(){return this.getTitle()};c.prototype.getPosition=function(g){g=g||this.$element;var i=g[0];var f=i.tagName=="BODY";var h=i.getBoundingClientRect();if(h.width==null){h=d.extend({},h,{width:h.right-h.left,height:h.bottom-h.top})}var k=window.SVGElement&&i instanceof window.SVGElement;var l=f?{top:0,left:0}:(k?null:g.offset());var e={scroll:f?document.documentElement.scrollTop||document.body.scrollTop:g.scrollTop()};var j=f?{width:d(window).width(),height:d(window).height()}:null;return d.extend({},h,e,j,l)};c.prototype.getCalculatedOffset=function(e,h,f,g){return e=="bottom"?{top:h.top+h.height,left:h.left+h.width/2-f/2}:e=="top"?{top:h.top-g,left:h.left+h.width/2-f/2}:e=="left"?{top:h.top+h.height/2-g/2,left:h.left-f}:{top:h.top+h.height/2-g/2,left:h.left+h.width}};c.prototype.getViewportAdjustedDelta=function(h,k,e,j){var m={top:0,left:0};if(!this.$viewport){return m}var g=this.options.viewport&&this.options.viewport.padding||0;var l=this.getPosition(this.$viewport);if(/right|left/.test(h)){var n=k.top-g-l.scroll;var i=k.top+g-l.scroll+j;if(n<l.top){m.top=l.top-n}else{if(i>l.top+l.height){m.top=l.top+l.height-i}}}else{var o=k.left-g;var f=k.left+g+e;if(o<l.left){m.left=l.left-o}else{if(f>l.right){m.left=l.left+l.width-f}}}return m};c.prototype.getTitle=function(){var g;var e=this.$element;var f=this.options;g=e.attr("data-original-title")||(typeof f.title=="function"?f.title.call(e[0]):f.title);return g};c.prototype.getUID=function(e){do{e+=~~(Math.random()*1000000)}while(document.getElementById(e));return e};c.prototype.tip=function(){if(!this.$tip){this.$tip=d(this.options.template);if(this.$tip.length!=1){throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!")}}return this.$tip};c.prototype.arrow=function(){return(this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow"))};c.prototype.enable=function(){this.enabled=true};c.prototype.disable=function(){this.enabled=false};c.prototype.toggleEnabled=function(){this.enabled=!this.enabled};c.prototype.toggle=function(g){var f=this;if(g){f=d(g.currentTarget).data("bs."+this.type);if(!f){f=new this.constructor(g.currentTarget,this.getDelegateOptions());d(g.currentTarget).data("bs."+this.type,f)}}if(g){f.inState.click=!f.inState.click;if(f.isInStateTrue()){f.enter(f)}else{f.leave(f)}}else{f.tip().hasClass("in")?f.leave(f):f.enter(f)}};c.prototype.destroy=function(){var e=this;clearTimeout(this.timeout);this.hide(function(){e.$element.off("."+e.type).removeData("bs."+e.type);if(e.$tip){e.$tip.detach()}e.$tip=null;e.$arrow=null;e.$viewport=null;e.$element=null})};function b(e){return this.each(function(){var h=d(this);var g=h.data("bs.tooltip");var f=typeof e=="object"&&e;if(!g&&/destroy|hide/.test(e)){return}if(!g){h.data("bs.tooltip",(g=new c(this,f)))}if(typeof e=="string"){g[e]()}})}var a=d.fn.tooltip;d.fn.tooltip=b;d.fn.tooltip.Constructor=c;d.fn.tooltip.noConflict=function(){d.fn.tooltip=a;return this}}(jQuery);+function(d){var c=function(f,e){this.init("popover",f,e)};if(!d.fn.tooltip){throw new Error("Popover requires tooltip.js")}c.VERSION="3.3.7";c.DEFAULTS=d.extend({},d.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:'<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'});c.prototype=d.extend({},d.fn.tooltip.Constructor.prototype);c.prototype.constructor=c;c.prototype.getDefaults=function(){return c.DEFAULTS};c.prototype.setContent=function(){var g=this.tip();var f=this.getTitle();var e=this.getContent();g.find(".popover-title")[this.options.html?"html":"text"](f);g.find(".popover-content").children().detach().end()[this.options.html?(typeof e=="string"?"html":"append"):"text"](e);g.removeClass("fade top bottom left right in");if(!g.find(".popover-title").html()){g.find(".popover-title").hide()}};c.prototype.hasContent=function(){return this.getTitle()||this.getContent()};c.prototype.getContent=function(){var e=this.$element;var f=this.options;return e.attr("data-content")||(typeof f.content=="function"?f.content.call(e[0]):f.content)};c.prototype.arrow=function(){return(this.$arrow=this.$arrow||this.tip().find(".arrow"))};function b(e){return this.each(function(){var h=d(this);var g=h.data("bs.popover");var f=typeof e=="object"&&e;if(!g&&/destroy|hide/.test(e)){return}if(!g){h.data("bs.popover",(g=new c(this,f)))}if(typeof e=="string"){g[e]()}})}var a=d.fn.popover;d.fn.popover=b;d.fn.popover.Constructor=c;d.fn.popover.noConflict=function(){d.fn.popover=a;return this}}(jQuery);+function(d){function c(f,e){this.$body=d(document.body);this.$scrollElement=d(f).is(document.body)?d(window):d(f);this.options=d.extend({},c.DEFAULTS,e);this.selector=(this.options.target||"")+" .nav li > a";this.offsets=[];this.targets=[];this.activeTarget=null;this.scrollHeight=0;this.$scrollElement.on("scroll.bs.scrollspy",d.proxy(this.process,this));this.refresh();this.process()}c.VERSION="3.3.7";c.DEFAULTS={offset:10};c.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)};c.prototype.refresh=function(){var g=this;var e="offset";var f=0;this.offsets=[];this.targets=[];this.scrollHeight=this.getScrollHeight();if(!d.isWindow(this.$scrollElement[0])){e="position";f=this.$scrollElement.scrollTop()}this.$body.find(this.selector).map(function(){var i=d(this);var h=i.data("target")||i.attr("href");var j=/^#./.test(h)&&d(h);return(j&&j.length&&j.is(":visible")&&[[j[e]().top+f,h]])||null}).sort(function(i,h){return i[0]-h[0]}).each(function(){g.offsets.push(this[0]);g.targets.push(this[1])})};c.prototype.process=function(){var k=this.$scrollElement.scrollTop()+this.options.offset;var g=this.getScrollHeight();var j=this.options.offset+g-this.$scrollElement.height();var h=this.offsets;var e=this.targets;var l=this.activeTarget;var f;if(this.scrollHeight!=g){this.refresh()}if(k>=j){return l!=(f=e[e.length-1])&&this.activate(f)}if(l&&k<h[0]){this.activeTarget=null;return this.clear()}for(f=h.length;f--;){l!=e[f]&&k>=h[f]&&(h[f+1]===undefined||k<h[f+1])&&this.activate(e[f])}};c.prototype.activate=function(g){this.activeTarget=g;this.clear();var e=this.selector+'[data-target="'+g+'"],'+this.selector+'[href="'+g+'"]';var f=d(e).parents("li").addClass("active");if(f.parent(".dropdown-menu").length){f=f.closest("li.dropdown").addClass("active")}f.trigger("activate.bs.scrollspy")};c.prototype.clear=function(){d(this.selector).parentsUntil(this.options.target,".active").removeClass("active")};function b(e){return this.each(function(){var h=d(this);var g=h.data("bs.scrollspy");var f=typeof e=="object"&&e;if(!g){h.data("bs.scrollspy",(g=new c(this,f)))}if(typeof e=="string"){g[e]()}})}var a=d.fn.scrollspy;d.fn.scrollspy=b;d.fn.scrollspy.Constructor=c;d.fn.scrollspy.noConflict=function(){d.fn.scrollspy=a;return this};d(window).on("load.bs.scrollspy.data-api",function(){d('[data-spy="scroll"]').each(function(){var e=d(this);b.call(e,e.data())})})}(jQuery);+function(d){var b=function(f){this.element=d(f)};b.VERSION="3.3.7";b.TRANSITION_DURATION=150;b.prototype.show=function(){var l=this.element;var h=l.closest("ul:not(.dropdown-menu)");var g=l.data("target");if(!g){g=l.attr("href");g=g&&g.replace(/.*(?=#[^\s]*$)/,"")}if(l.parent("li").hasClass("active")){return}var j=h.find(".active:last a");var k=d.Event("hide.bs.tab",{relatedTarget:l[0]});var i=d.Event("show.bs.tab",{relatedTarget:j[0]});j.trigger(k);l.trigger(i);if(i.isDefaultPrevented()||k.isDefaultPrevented()){return}var f=d(g);this.activate(l.closest("li"),h);this.activate(f,f.parent(),function(){j.trigger({type:"hidden.bs.tab",relatedTarget:l[0]});l.trigger({type:"shown.bs.tab",relatedTarget:j[0]})})};b.prototype.activate=function(h,g,k){var f=g.find("> .active");var j=k&&d.support.transition&&(f.length&&f.hasClass("fade")||!!g.find("> .fade").length);function i(){f.removeClass("active").find("> .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",false);h.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",true);if(j){h[0].offsetWidth;h.addClass("in")}else{h.removeClass("fade")}if(h.parent(".dropdown-menu").length){h.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",true)}k&&k()}f.length&&j?f.one("bsTransitionEnd",i).emulateTransitionEnd(b.TRANSITION_DURATION):i();f.removeClass("in")};function c(f){return this.each(function(){var h=d(this);var g=h.data("bs.tab");if(!g){h.data("bs.tab",(g=new b(this)))}if(typeof f=="string"){g[f]()}})}var a=d.fn.tab;d.fn.tab=c;d.fn.tab.Constructor=b;d.fn.tab.noConflict=function(){d.fn.tab=a;return this};var e=function(f){f.preventDefault();c.call(d(this),"show")};d(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery);+function(d){var c=function(f,e){this.options=d.extend({},c.DEFAULTS,e);this.$target=d(this.options.target).on("scroll.bs.affix.data-api",d.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",d.proxy(this.checkPositionWithEventLoop,this));this.$element=d(f);this.affixed=null;this.unpin=null;this.pinnedOffset=null;this.checkPosition()};c.VERSION="3.3.7";c.RESET="affix affix-top affix-bottom";c.DEFAULTS={offset:0,target:window};c.prototype.getState=function(n,m,f,g){var e=this.$target.scrollTop();var i=this.$element.offset();var j=this.$target.height();if(f!=null&&this.affixed=="top"){return e<f?"top":false}if(this.affixed=="bottom"){if(f!=null){return(e+this.unpin<=i.top)?false:"bottom"}return(e+j<=n-g)?false:"bottom"}var h=this.affixed==null;var l=h?e:i.top;var k=h?j:m;if(f!=null&&e<=f){return"top"}if(g!=null&&(l+k>=n-g)){return"bottom"}return false};c.prototype.getPinnedOffset=function(){if(this.pinnedOffset){return this.pinnedOffset}this.$element.removeClass(c.RESET).addClass("affix");var f=this.$target.scrollTop();var e=this.$element.offset();return(this.pinnedOffset=e.top-f)};c.prototype.checkPositionWithEventLoop=function(){setTimeout(d.proxy(this.checkPosition,this),1)};c.prototype.checkPosition=function(){if(!this.$element.is(":visible")){return}var f=this.$element.height();var l=this.options.offset;var j=l.top;var h=l.bottom;var i=Math.max(d(document).height(),d(document.body).height());if(typeof l!="object"){h=j=l}if(typeof j=="function"){j=l.top(this.$element)}if(typeof h=="function"){h=l.bottom(this.$element)}var g=this.getState(i,f,j,h);if(this.affixed!=g){if(this.unpin!=null){this.$element.css("top","")}var m="affix"+(g?"-"+g:"");var k=d.Event(m+".bs.affix");this.$element.trigger(k);if(k.isDefaultPrevented()){return}this.affixed=g;this.unpin=g=="bottom"?this.getPinnedOffset():null;this.$element.removeClass(c.RESET).addClass(m).trigger(m.replace("affix","affixed")+".bs.affix")}if(g=="bottom"){this.$element.offset({top:i-f-h})}};function b(e){return this.each(function(){var h=d(this);var g=h.data("bs.affix");var f=typeof e=="object"&&e;if(!g){h.data("bs.affix",(g=new c(this,f)))}if(typeof e=="string"){g[e]()}})}var a=d.fn.affix;d.fn.affix=b;d.fn.affix.Constructor=c;d.fn.affix.noConflict=function(){d.fn.affix=a;return this};d(window).on("load",function(){d('[data-spy="affix"]').each(function(){var f=d(this);var e=f.data();e.offset=e.offset||{};if(e.offsetBottom!=null){e.offset.bottom=e.offsetBottom}if(e.offsetTop!=null){e.offset.top=e.offsetTop}b.call(f,e)})})}(jQuery);
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/js/cron.js b/ruoyi-admin/src/main/resources/static/js/cron.js
new file mode 100644
index 0000000..9a4baff
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/js/cron.js
@@ -0,0 +1,926 @@
+$().ready(function () {
+    $("#unrunBtn").click(function () {
+        var str = $("#cron").val();
+        var str_arr = str.split(" ");
+        try {
+            $("#v_second").val(str_arr[0])
+            $("#v_min").val(str_arr[1])
+            $("#v_hour").val(str_arr[2])
+            $("#v_day").val(str_arr[3])
+            $("#v_month").val(str_arr[4])
+            $("#v_week").val(str_arr[5])
+            $("#v_year").val(str_arr[6])
+        } catch (e) {
+        }
+    });
+    //second
+    $("#sec_all").click(function () {
+        if ($(this).prop('checked')) {
+            $("#v_second").val("*");
+            gen_cron();
+        }
+    });
+    $("#sec_circle").click(function () {
+        if ($(this).prop('checked')) {
+            change_sec_circle();
+        }
+    });
+    $("#sec_circle1").change(function () {
+        if ($("#sec_circle").prop('checked')) {
+            change_sec_circle();
+        }
+    });
+    $("#sec_circle2").change(function () {
+        if ($("#sec_circle").prop('checked')) {
+            change_sec_circle();
+        }
+    });
+    $("#sec_per").click(function () {
+        if ($(this).prop('checked')) {
+            change_sec_per();
+        }
+    });
+    $("#sec_per1").change(function () {
+        if ($("#sec_per").prop('checked')) {
+            change_sec_per();
+        }
+    });
+    $("#sec_per2").change(function () {
+        if ($("#sec_per").prop('checked')) {
+            change_sec_per();
+        }
+    });
+    $("#sec_assign").click(function () {
+        if ($("#sec_assign").prop('checked')) {
+            change_sec_assign();
+        }
+    });
+    $("input[name='zd_second']").click(function () {
+        if ($("#sec_assign").prop('checked')) {
+            change_sec_assign();
+        }
+    });
+
+    //minute
+    $("#min_all").click(function () {
+        if ($(this).prop('checked')) {
+            $("#v_min").val("*");
+            gen_cron();
+        }
+    });
+    $("#min_circle").click(function () {
+        if ($(this).prop('checked')) {
+            change_min_circle();
+        }
+    });
+    $("#min_circle1").change(function () {
+        if ($("#min_circle").prop('checked')) {
+            change_min_circle();
+        }
+    });
+    $("#min_circle2").change(function () {
+        if ($("#min_circle").prop('checked')) {
+            change_min_circle();
+        }
+    });
+    $("#min_per").click(function () {
+        if ($(this).prop('checked')) {
+            change_min_per();
+        }
+    });
+    $("#min_per1").change(function () {
+        if ($("#min_per").prop('checked')) {
+            change_min_per();
+        }
+    });
+    $("#min_per2").change(function () {
+        if ($("#min_per").prop('checked')) {
+            change_min_per();
+        }
+    });
+    $("#min_assign").click(function () {
+        if ($("#min_assign").prop('checked')) {
+            change_min_assign();
+        }
+    });
+    $("input[name='zd_minute']").click(function () {
+        if ($("#min_assign").prop('checked')) {
+            change_min_assign();
+        }
+    });
+
+    //hour
+    $("#hour_all").click(function () {
+        if ($(this).prop('checked')) {
+            $("#v_hour").val("*");
+            gen_cron();
+        }
+    });
+    $("#hour_circle").click(function () {
+        if ($(this).prop('checked')) {
+            change_hour_circle();
+        }
+    });
+    $("#hour_circle1").change(function () {
+        if ($("#hour_circle").prop('checked')) {
+            change_hour_circle();
+        }
+    });
+    $("#hour_circle2").change(function () {
+        if ($("#hour_circle").prop('checked')) {
+            change_hour_circle();
+        }
+    });
+    $("#hour_per").click(function () {
+        if ($(this).prop('checked')) {
+            change_hour_per();
+        }
+    });
+    $("#hour_per1").change(function () {
+        if ($("#hour_per").prop('checked')) {
+            change_hour_per();
+        }
+    });
+    $("#hour_per2").change(function () {
+        if ($("#hour_per").prop('checked')) {
+            change_hour_per();
+        }
+    });
+    $("#hour_assign").click(function () {
+        if ($("#hour_assign").prop('checked')) {
+            change_hour_assign();
+        }
+    });
+    $("input[name='zd_hour']").click(function () {
+        if ($("#hour_assign").prop('checked')) {
+            change_hour_assign();
+        }
+    });
+
+    //day
+    $("#day_all").click(function () {
+        if ($(this).prop('checked')) {
+            $("#v_day").val("*");
+            gen_cron();
+        }
+    });
+    $("#day_no").click(function () {
+        if ($(this).prop('checked')) {
+            $("#v_day").val("?");
+            gen_cron();
+        }
+    });
+    $("#day_last").click(function () {
+        if ($(this).prop('checked')) {
+            $("#v_day").val("L");
+            gen_cron();
+        }
+    });
+    $("#day_circle").click(function () {
+        if ($(this).prop('checked')) {
+            change_day_circle();
+        }
+    });
+    $("#day_circle1").change(function () {
+        if ($("#day_circle").prop('checked')) {
+            change_day_circle();
+        }
+    });
+    $("#day_circle2").change(function () {
+        if ($("#day_circle").prop('checked')) {
+            change_day_circle();
+        }
+    });
+    $("#day_per").click(function () {
+        if ($(this).prop('checked')) {
+            change_day_per();
+        }
+    });
+    $("#day_per1").change(function () {
+        if ($("#day_per").prop('checked')) {
+            change_day_per();
+        }
+    });
+    $("#day_per2").change(function () {
+        if ($("#day_per").prop('checked')) {
+            change_day_per();
+        }
+    });
+    $("#day_work").click(function () {
+        if ($("#day_work").prop('checked')) {
+            change_day_work();
+        }
+    });
+    $("#day_work1").change(function () {
+        if ($("#day_work").prop('checked')) {
+            change_day_work();
+        }
+    });
+    $("#day_assign").click(function () {
+        if ($("#day_assign").prop('checked')) {
+            change_day_assign();
+        }
+    });
+    $("input[name='zd_day']").click(function () {
+        if ($("#day_assign").prop('checked')) {
+            change_day_assign();
+        }
+    });
+
+    //month
+    $("#month_all").click(function () {
+        if ($(this).prop('checked')) {
+            $("#v_month").val("*");
+            gen_cron();
+        }
+    });
+    $("#month_no").click(function () {
+        if ($(this).prop('checked')) {
+            $("#v_month").val("?");
+            gen_cron();
+        }
+    });
+    $("#month_last").click(function () {
+        if ($(this).prop('checked')) {
+            $("#v_month").val("L");
+            gen_cron();
+        }
+    });
+    $("#month_circle").click(function () {
+        if ($(this).prop('checked')) {
+            change_month_circle();
+        }
+    });
+    $("#month_circle1").change(function () {
+        if ($("#month_circle").prop('checked')) {
+            change_month_circle();
+        }
+    });
+    $("#month_circle2").change(function () {
+        if ($("#month_circle").prop('checked')) {
+            change_month_circle();
+        }
+    });
+    $("#month_per").click(function () {
+        if ($(this).prop('checked')) {
+            change_month_per();
+        }
+    });
+    $("#month_per1").change(function () {
+        if ($("#month_per").prop('checked')) {
+            change_month_per();
+        }
+    });
+    $("#month_per2").change(function () {
+        if ($("#month_per").prop('checked')) {
+            change_month_per();
+        }
+    });
+    $("#month_assign").click(function () {
+        if ($("#month_assign").prop('checked')) {
+            change_month_assign();
+        }
+    });
+    $("input[name='zd_month']").click(function () {
+        if ($("#month_assign").prop('checked')) {
+            change_month_assign();
+        }
+    });
+    
+    //week
+    $("#week_all").click(function () {
+        if ($(this).prop('checked')) {
+            $("#v_week").val("*");
+            gen_cron();
+        }
+    });
+    $("#week_no").click(function () {
+        if ($(this).prop('checked')) {
+            $("#v_week").val("?");
+            gen_cron();
+        }
+    });
+    $("#week_circle").click(function () {
+        if ($(this).prop('checked')) {
+            change_week_circle();
+        }
+    });
+    $("#week_circle1").change(function () {
+        if ($("#week_circle").prop('checked')) {
+            change_week_circle();
+        }
+    });
+    $("#week_circle2").change(function () {
+        if ($("#week_circle").prop('checked')) {
+            change_week_circle();
+        }
+    });
+    $("#week_last").click(function () {
+        if ($("#week_last").prop('checked')) {
+            change_week_last();
+        }
+    });
+    $("#week_last1").change(function () {
+        if ($("#week_last").prop('checked')) {
+            change_week_last();
+        }
+    });
+    $("#week_num").click(function () {
+        if ($("#week_num").prop('checked')) {
+            change_week_num();
+        }
+    });
+    $("#week_num1").change(function () {
+        if ($("#week_num").prop('checked')) {
+            change_week_num();
+        }
+    });
+    $("#week_num2").change(function () {
+        if ($("#week_num").prop('checked')) {
+            change_week_num();
+        }
+    });
+    $("#week_assign").click(function () {
+        if ($("#week_assign").prop('checked')) {
+            change_week_assign();
+        }
+    });
+    $("input[name='zd_week']").click(function () {
+        if ($("#week_assign").prop('checked')) {
+            change_week_assign();
+        }
+    });
+    
+    //year
+    $("#year_all").click(function () {
+        if ($(this).prop('checked')) {
+            $("#v_year").val("*");
+            gen_cron();
+        }
+    });
+    $("#year_no").click(function () {
+        if ($(this).prop('checked')) {
+            $("#v_year").val("");
+            gen_cron();
+        }
+    });
+    $("#year_circle").click(function () {
+        if ($(this).prop('checked')) {
+            change_year_circle();
+        }
+    });
+    $("#year_circle1").change(function () {
+        if ($("#year_circle").prop('checked')) {
+            change_year_circle();
+        }
+    });
+    $("#year_circle2").change(function () {
+        if ($("#year_circle").prop('checked')) {
+            change_year_circle();
+        }
+    });
+});
+
+function change_sec_assign() {
+    var sec_array = new Array();
+    $("input[name='zd_second']:checked").each(function () {
+        sec_array[sec_array.length] = $(this).val();
+    });
+    sec_array = sec_array.join(",");
+    if (sec_array == null || sec_array == '') {
+        $("#v_second").val("*");
+    } else {
+        $("#v_second").val(sec_array);
+    }
+    gen_cron();
+}
+
+function change_sec_circle() {
+    var v1 = $("#sec_circle1").val();
+    var v2 = $("#sec_circle2").val();
+    if (v1 == null || v1 == '' || v2 == null || v2 == '') {
+        return;
+    }
+    if (v1 < 1) {
+        v1 = 1;
+        $("#sec_circle1").val(v1);
+    }
+    if (v2 < 2) {
+        v2 = 2;
+        $("#sec_circle2").val(v2);
+    }
+    if (v2 > 59) {
+        v2 = 59;
+        $("#sec_circle2").val(v2);
+    }
+    if (v1 > 59) {
+        v1 = 59;
+        $("#sec_circle1").val(v1);
+    }
+    if (v1 >= v2) {
+        v1 = v2 - 1;
+        $("#sec_circle1").val(v1);
+    }
+    if (v1 > 60 || v2 > 60) {
+        return;
+    }
+    if (v1 > v2) {
+        return;
+    }
+    $("#v_second").val(v1 + "-" + v2);
+    gen_cron();
+}
+
+function change_sec_per() {
+    var v1 = $("#sec_per1").val();
+    var v2 = $("#sec_per2").val();
+    if (v1 == null || v1 == '' || v2 == null || v2 == '') {
+        return;
+    }
+    if (v1 < 0) {
+        v1 = 0;
+        $("#sec_per1").val(v1);
+    }
+    if (v1 > 59) {
+        v1 = 59;
+        $("#sec_per1").val(v1);
+    }
+    if (v2 < 1) {
+        v2 = 1;
+        $("#sec_per2").val(v2);
+    }
+    if (v2 > 59) {
+        v2 = 59;
+        $("#sec_per2").val(v2);
+    }
+    $("#v_second").val(v1 + "/" + v2);
+    gen_cron()
+}
+
+function change_min_assign() {
+    var sec_array = new Array();
+    $("input[name='zd_minute']:checked").each(function () {
+        sec_array[sec_array.length] = $(this).val();
+    });
+    sec_array = sec_array.join(",");
+    if (sec_array == null || sec_array == '') {
+        $("#v_min").val("*");
+    } else {
+        $("#v_min").val(sec_array);
+    }
+    gen_cron();
+}
+
+function change_min_circle() {
+    var v1 = $("#min_circle1").val();
+    var v2 = $("#min_circle2").val();
+    if (v1 == null || v1 == '' || v2 == null || v2 == '') {
+        return;
+    }
+    if (v1 < 1) {
+        v1 = 1;
+        $("#min_circle1").val(v1);
+    }
+    if (v2 < 2) {
+        v2 = 2;
+        $("#min_circle2").val(v2);
+    }
+    if (v2 > 59) {
+        v2 = 59;
+        $("#min_circle2").val(v2);
+    }
+    if (v1 > 59) {
+        v1 = 59;
+        $("#min_circle1").val(v1);
+    }
+    if (v1 >= v2) {
+        v1 = v2 - 1;
+        $("#min_circle1").val(v1);
+    }
+    if (v1 > 60 || v2 > 60) {
+        return;
+    }
+    if (v1 > v2) {
+        return;
+    }
+    $("#v_min").val(v1 + "-" + v2);
+    gen_cron();
+}
+
+function change_min_per() {
+    var v1 = $("#min_per1").val();
+    var v2 = $("#min_per2").val();
+    if (v1 == null || v1 == '' || v2 == null || v2 == '') {
+        return;
+    }
+    if (v1 < 0) {
+        v1 = 0;
+        $("#min_per1").val(v1);
+    }
+    if (v1 > 59) {
+        v1 = 59;
+        $("#min_per1").val(v1);
+    }
+    if (v2 < 1) {
+        v2 = 1;
+        $("#min_per2").val(v2);
+    }
+    if (v2 > 59) {
+        v2 = 59;
+        $("#min_per2").val(v2);
+    }
+
+    $("#v_min").val(v1 + "/" + v2);
+    gen_cron()
+}
+
+function change_hour_assign() {
+    var sec_array = new Array();
+    $("input[name='zd_hour']:checked").each(function () {
+        sec_array[sec_array.length] = $(this).val();
+    });
+    sec_array = sec_array.join(",");
+    if (sec_array == null || sec_array == '') {
+        $("#v_hour").val("*");
+    } else {
+        $("#v_hour").val(sec_array);
+    }
+    gen_cron();
+}
+
+function change_hour_circle() {
+    var v1 = $("#hour_circle1").val();
+    var v2 = $("#hour_circle2").val();
+    if (v1 == null || v1 == '' || v2 == null || v2 == '') {
+        return;
+    }
+    if (v1 < 1) {
+        v1 = 1;
+        $("#hour_circle1").val(v1);
+    }
+    if (v2 < 2) {
+        v2 = 2;
+        $("#hour_circle2").val(v2);
+    }
+    if (v2 > 23) {
+        v2 = 23;
+        $("#hour_circle2").val(v2);
+    }
+    if (v1 > 23) {
+        v1 = 23;
+        $("#hour_circle1").val(v1);
+    }
+    if (v1 >= v2) {
+        v1 = v2 - 1;
+        $("#hour_circle1").val(v1);
+    }
+    if (v1 > 23 || v2 > 23) {
+        return;
+    }
+    if (v1 > v2) {
+        return;
+    }
+    $("#v_hour").val(v1 + "-" + v2);
+    gen_cron();
+}
+
+function change_hour_per() {
+    var v1 = $("#hour_per1").val();
+    var v2 = $("#hour_per2").val();
+    if (v1 == null || v1 == '' || v2 == null || v2 == '') {
+        return;
+    }
+    if (v1 < 0) {
+        v1 = 0;
+        $("#hour_per1").val(v1);
+    }
+    if (v1 > 23) {
+        v1 = 23;
+        $("#hour_per1").val(v1);
+    }
+    if (v2 < 1) {
+        v2 = 1;
+        $("#hour_per2").val(v2);
+    }
+    if (v2 > 23) {
+        v2 = 23;
+        $("#hour_per2").val(v2);
+    }
+
+    $("#v_hour").val(v1 + "/" + v2);
+    gen_cron()
+}
+
+function change_day_assign() {
+    var sec_array = new Array();
+    $("input[name='zd_day']:checked").each(function () {
+        sec_array[sec_array.length] = $(this).val();
+    });
+    sec_array = sec_array.join(",");
+    if (sec_array == null || sec_array == '') {
+        $("#v_day").val("*");
+    } else {
+        $("#v_day").val(sec_array);
+    }
+    gen_cron();
+}
+
+function change_day_circle() {
+    var v1 = $("#day_circle1").val();
+    var v2 = $("#day_circle2").val();
+    if (v1 == null || v1 == '' || v2 == null || v2 == '') {
+        return;
+    }
+    if (v1 < 1) {
+        v1 = 1;
+        $("#day_circle1").val(v1);
+    }
+    if (v2 < 2) {
+        v2 = 2;
+        $("#day_circle2").val(v2);
+    }
+    if (v2 > 31) {
+        v2 = 31;
+        $("#day_circle2").val(v2);
+    }
+    if (v1 > 31) {
+        v1 = 31;
+        $("#day_circle1").val(v1);
+    }
+    if (v1 >= v2) {
+        v1 = v2 - 1;
+        $("#day_circle1").val(v1);
+    }
+    if (v1 > 31 || v2 > 31) {
+        return;
+    }
+    if (v1 > v2) {
+        return;
+    }
+    $("#v_day").val(v1 + "-" + v2);
+    gen_cron();
+}
+
+function change_day_per() {
+    var v1 = $("#day_per1").val();
+    var v2 = $("#day_per2").val();
+    if (v1 == null || v1 == '' || v2 == null || v2 == '') {
+        return;
+    }
+    if (v1 < 1) {
+        v1 = 1;
+        $("#day_per1").val(v1);
+    }
+    if (v1 > 31) {
+        v1 = 31;
+        $("#day_per1").val(v1);
+    }
+    if (v2 < 1) {
+        v2 = 1;
+        $("#day_per2").val(v2);
+    }
+    if (v2 > 31) {
+        v2 = 31;
+        $("#day_per2").val(v2);
+    }
+
+    $("#v_day").val(v1 + "/" + v2);
+    gen_cron()
+}
+
+function change_day_work() {
+    var v1 = $("#day_work1").val();
+
+    if (v1 == null || v1 == '') {
+        return;
+    }
+    if (v1 < 1) {
+        v1 = 1;
+        $("#day_work1").val(v1);
+    }
+    if (v1 > 31) {
+        v1 = 31;
+        $("#day_work1").val(v1);
+    }
+    $("#v_day").val(v1 + "W");
+    gen_cron()
+}
+
+function change_month_assign() {
+    var sec_array = new Array();
+    $("input[name='zd_month']:checked").each(function () {
+        sec_array[sec_array.length] = $(this).val();
+    });
+    sec_array = sec_array.join(",");
+    if (sec_array == null || sec_array == '') {
+        $("#v_month").val("*");
+    } else {
+        $("#v_month").val(sec_array);
+    }
+    gen_cron();
+}
+
+function change_month_circle() {
+    var v1 = $("#month_circle1").val();
+    var v2 = $("#month_circle2").val();
+    if (v1 == null || v1 == '' || v2 == null || v2 == '') {
+        return;
+    }
+    if (v1 < 1) {
+        v1 = 1;
+        $("#month_circle1").val(v1);
+    }
+    if (v2 < 2) {
+        v2 = 2;
+        $("#month_circle2").val(v2);
+    }
+    if (v2 > 12) {
+        v2 = 12;
+        $("#month_circle2").val(v2);
+    }
+    if (v1 > 12) {
+        v1 = 12;
+        $("#month_circle1").val(v1);
+    }
+    if (v1 >= v2) {
+        v1 = v2 - 1;
+        $("#month_circle1").val(v1);
+    }
+    if (v1 > 12 || v2 > 12) {
+        return;
+    }
+    if (v1 > v2) {
+        return;
+    }
+    $("#v_month").val(v1 + "-" + v2);
+    gen_cron();
+}
+
+function change_month_per() {
+    var v1 = $("#month_per1").val();
+    var v2 = $("#month_per2").val();
+    if (v1 == null || v1 == '' || v2 == null || v2 == '') {
+        return;
+    }
+    if (v1 < 1) {
+        v1 = 1;
+        $("#month_per1").val(v1);
+    }
+    if (v1 > 12) {
+        v1 = 12;
+        $("#month_per1").val(v1);
+    }
+    if (v2 < 1) {
+        v2 = 1;
+        $("#month_per2").val(v2);
+    }
+    if (v2 > 12) {
+        v2 = 12;
+        $("#month_per2").val(v2);
+    }
+
+    $("#v_month").val(v1 + "/" + v2);
+    gen_cron()
+}
+
+function change_week_assign() {
+    var sec_array = new Array();
+    $("input[name='zd_week']:checked").each(function () {
+        sec_array[sec_array.length] = $(this).val();
+    });
+    sec_array = sec_array.join(",");
+    if (sec_array == null || sec_array == '') {
+        $("#v_week").val("*");
+    } else {
+        $("#v_week").val(sec_array);
+    }
+    gen_cron();
+}
+
+function change_week_circle() {
+    var v1 = $("#week_circle1").val();
+    var v2 = $("#week_circle2").val();
+    if (v1 == null || v1 == '' || v2 == null || v2 == '') {
+        return;
+    }
+    if (v1 < 1) {
+        v1 = 1;
+        $("#week_circle1").val(v1);
+    }
+    if (v2 < 2) {
+        v2 = 2;
+        $("#week_circle2").val(v2);
+    }
+    if (v2 > 7) {
+        v2 = 7;
+        $("#week_circle2").val(v2);
+    }
+    if (v1 > 7) {
+        v1 = 7;
+        $("#week_circle1").val(v1);
+    }
+    if (v1 >= v2) {
+        v1 = v2 - 1;
+        $("#week_circle1").val(v1);
+    }
+    if (v1 > 7 || v2 > 7) {
+        return;
+    }
+    if (v1 > v2) {
+        return;
+    }
+    $("#v_week").val(v1 + "-" + v2);
+    gen_cron();
+}
+
+function change_week_last() {
+    var v1 = $("#week_last1").val();
+
+    if (v1 == null || v1 == '') {
+        return;
+    }
+    if (v1 < 1) {
+        v1 = 1;
+        $("#week_last1").val(v1);
+    }
+    if (v1 > 7) {
+        v1 = 7;
+        $("#week_last1").val(v1);
+    }
+    $("#v_week").val(v1 + "L");
+    gen_cron()
+}
+
+function change_week_num() {
+    var v1 = $("#week_num1").val();
+    var v2 = $("#week_num2").val();
+    if (v1 == null || v1 == '' || v2 == null || v2 == '') {
+        return;
+    }
+    if (v1 < 1) {
+        v1 = 1;
+        $("#week_num1").val(v1);
+    }
+    if (v2 < 1) {
+        v2 = 1;
+        $("#week_num2").val(v2);
+    }
+    if (v2 > 7) {
+        v2 = 7;
+        $("#week_num2").val(v2);
+    }
+    if (v1 > 4) {
+        v1 = 4;
+        $("#week_num1").val(v1);
+    }
+
+    $("#v_week").val(v1 + "#" + v2);
+    gen_cron();
+}
+
+function change_year_circle() {
+    var v1 = $("#year_circle1").val();
+    var v2 = $("#year_circle2").val();
+    if (v1 == null || v1 == '' || v2 == null || v2 == '') {
+        return;
+    }
+    if (v1 < 2000) {
+        v1 = 2000;
+        $("#year_circle1").val(v1);
+    }
+    if (v2 < 2000) {
+        v2 = 2000;
+        $("#year_circle2").val(v2);
+    }
+    if (v2 > 3000) {
+        v2 = 3000;
+        $("#year_circle2").val(v2);
+    }
+    if (v1 > 3000) {
+        v1 = 3000;
+        $("#year_circle1").val(v1);
+    }
+    if (v1 >= v2) {
+        v1 = v2 - 1;
+        $("#year_circle1").val(v1);
+    }
+    if (v1 > 3000 || v2 > 3000) {
+        return;
+    }
+    if (v1 > v2) {
+        return;
+    }
+    $("#v_year").val(v1 + "-" + v2);
+    gen_cron();
+}
+
+function gen_cron() {
+    var str = $("#v_second").val() + " "
+        + $("#v_min").val() + " "
+        + $("#v_hour").val() + " "
+        + $("#v_day").val() + " "
+        + $("#v_month").val() + " "
+        + $("#v_week").val() + " "
+        + $("#v_year").val();
+    $("#cron").val(str);
+}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/js/jquery-ui-1.10.4.min.js b/ruoyi-admin/src/main/resources/static/js/jquery-ui-1.10.4.min.js
new file mode 100644
index 0000000..d28154b
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/js/jquery-ui-1.10.4.min.js
@@ -0,0 +1,12 @@
+/*! jQuery UI - v1.10.4 - 2014-01-17
+* http://jqueryui.com
+* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.draggable.js, jquery.ui.droppable.js, jquery.ui.resizable.js, jquery.ui.selectable.js, jquery.ui.sortable.js, jquery.ui.effect.js, jquery.ui.accordion.js, jquery.ui.autocomplete.js, jquery.ui.button.js, jquery.ui.datepicker.js, jquery.ui.dialog.js, jquery.ui.effect-blind.js, jquery.ui.effect-bounce.js, jquery.ui.effect-clip.js, jquery.ui.effect-drop.js, jquery.ui.effect-explode.js, jquery.ui.effect-fade.js, jquery.ui.effect-fold.js, jquery.ui.effect-highlight.js, jquery.ui.effect-pulsate.js, jquery.ui.effect-scale.js, jquery.ui.effect-shake.js, jquery.ui.effect-slide.js, jquery.ui.effect-transfer.js, jquery.ui.menu.js, jquery.ui.position.js, jquery.ui.progressbar.js, jquery.ui.slider.js, jquery.ui.spinner.js, jquery.ui.tabs.js, jquery.ui.tooltip.js
+* Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */
+(function(t,e){function i(e,i){var n,o,a,r=e.nodeName.toLowerCase();return"area"===r?(n=e.parentNode,o=n.name,e.href&&o&&"map"===n.nodeName.toLowerCase()?(a=t("img[usemap=#"+o+"]")[0],!!a&&s(a)):!1):(/input|select|textarea|button|object/.test(r)?!e.disabled:"a"===r?e.href||i:i)&&s(e)}function s(e){return t.expr.filters.visible(e)&&!t(e).parents().addBack().filter(function(){return"hidden"===t.css(this,"visibility")}).length}var n=0,o=/^ui-id-\d+$/;t.ui=t.ui||{},t.extend(t.ui,{version:"1.10.4",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),t.fn.extend({focus:function(e){return function(i,s){return"number"==typeof i?this.each(function(){var e=this;setTimeout(function(){t(e).focus(),s&&s.call(e)},i)}):e.apply(this,arguments)}}(t.fn.focus),scrollParent:function(){var e;return e=t.ui.ie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(t.css(this,"position"))&&/(auto|scroll)/.test(t.css(this,"overflow")+t.css(this,"overflow-y")+t.css(this,"overflow-x"))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(t.css(this,"overflow")+t.css(this,"overflow-y")+t.css(this,"overflow-x"))}).eq(0),/fixed/.test(this.css("position"))||!e.length?t(document):e},zIndex:function(i){if(i!==e)return this.css("zIndex",i);if(this.length)for(var s,n,o=t(this[0]);o.length&&o[0]!==document;){if(s=o.css("position"),("absolute"===s||"relative"===s||"fixed"===s)&&(n=parseInt(o.css("zIndex"),10),!isNaN(n)&&0!==n))return n;o=o.parent()}return 0},uniqueId:function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++n)})},removeUniqueId:function(){return this.each(function(){o.test(this.id)&&t(this).removeAttr("id")})}}),t.extend(t.expr[":"],{data:t.expr.createPseudo?t.expr.createPseudo(function(e){return function(i){return!!t.data(i,e)}}):function(e,i,s){return!!t.data(e,s[3])},focusable:function(e){return i(e,!isNaN(t.attr(e,"tabindex")))},tabbable:function(e){var s=t.attr(e,"tabindex"),n=isNaN(s);return(n||s>=0)&&i(e,!n)}}),t("<a>").outerWidth(1).jquery||t.each(["Width","Height"],function(i,s){function n(e,i,s,n){return t.each(o,function(){i-=parseFloat(t.css(e,"padding"+this))||0,s&&(i-=parseFloat(t.css(e,"border"+this+"Width"))||0),n&&(i-=parseFloat(t.css(e,"margin"+this))||0)}),i}var o="Width"===s?["Left","Right"]:["Top","Bottom"],a=s.toLowerCase(),r={innerWidth:t.fn.innerWidth,innerHeight:t.fn.innerHeight,outerWidth:t.fn.outerWidth,outerHeight:t.fn.outerHeight};t.fn["inner"+s]=function(i){return i===e?r["inner"+s].call(this):this.each(function(){t(this).css(a,n(this,i)+"px")})},t.fn["outer"+s]=function(e,i){return"number"!=typeof e?r["outer"+s].call(this,e):this.each(function(){t(this).css(a,n(this,e,!0,i)+"px")})}}),t.fn.addBack||(t.fn.addBack=function(t){return this.add(null==t?this.prevObject:this.prevObject.filter(t))}),t("<a>").data("a-b","a").removeData("a-b").data("a-b")&&(t.fn.removeData=function(e){return function(i){return arguments.length?e.call(this,t.camelCase(i)):e.call(this)}}(t.fn.removeData)),t.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),t.support.selectstart="onselectstart"in document.createElement("div"),t.fn.extend({disableSelection:function(){return this.bind((t.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(t){t.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),t.extend(t.ui,{plugin:{add:function(e,i,s){var n,o=t.ui[e].prototype;for(n in s)o.plugins[n]=o.plugins[n]||[],o.plugins[n].push([i,s[n]])},call:function(t,e,i){var s,n=t.plugins[e];if(n&&t.element[0].parentNode&&11!==t.element[0].parentNode.nodeType)for(s=0;n.length>s;s++)t.options[n[s][0]]&&n[s][1].apply(t.element,i)}},hasScroll:function(e,i){if("hidden"===t(e).css("overflow"))return!1;var s=i&&"left"===i?"scrollLeft":"scrollTop",n=!1;return e[s]>0?!0:(e[s]=1,n=e[s]>0,e[s]=0,n)}})})(jQuery),function(t,e){var i=0,s=Array.prototype.slice,n=t.cleanData;t.cleanData=function(e){for(var i,s=0;null!=(i=e[s]);s++)try{t(i).triggerHandler("remove")}catch(o){}n(e)},t.widget=function(i,s,n){var o,a,r,h,l={},c=i.split(".")[0];i=i.split(".")[1],o=c+"-"+i,n||(n=s,s=t.Widget),t.expr[":"][o.toLowerCase()]=function(e){return!!t.data(e,o)},t[c]=t[c]||{},a=t[c][i],r=t[c][i]=function(t,i){return this._createWidget?(arguments.length&&this._createWidget(t,i),e):new r(t,i)},t.extend(r,a,{version:n.version,_proto:t.extend({},n),_childConstructors:[]}),h=new s,h.options=t.widget.extend({},h.options),t.each(n,function(i,n){return t.isFunction(n)?(l[i]=function(){var t=function(){return s.prototype[i].apply(this,arguments)},e=function(t){return s.prototype[i].apply(this,t)};return function(){var i,s=this._super,o=this._superApply;return this._super=t,this._superApply=e,i=n.apply(this,arguments),this._super=s,this._superApply=o,i}}(),e):(l[i]=n,e)}),r.prototype=t.widget.extend(h,{widgetEventPrefix:a?h.widgetEventPrefix||i:i},l,{constructor:r,namespace:c,widgetName:i,widgetFullName:o}),a?(t.each(a._childConstructors,function(e,i){var s=i.prototype;t.widget(s.namespace+"."+s.widgetName,r,i._proto)}),delete a._childConstructors):s._childConstructors.push(r),t.widget.bridge(i,r)},t.widget.extend=function(i){for(var n,o,a=s.call(arguments,1),r=0,h=a.length;h>r;r++)for(n in a[r])o=a[r][n],a[r].hasOwnProperty(n)&&o!==e&&(i[n]=t.isPlainObject(o)?t.isPlainObject(i[n])?t.widget.extend({},i[n],o):t.widget.extend({},o):o);return i},t.widget.bridge=function(i,n){var o=n.prototype.widgetFullName||i;t.fn[i]=function(a){var r="string"==typeof a,h=s.call(arguments,1),l=this;return a=!r&&h.length?t.widget.extend.apply(null,[a].concat(h)):a,r?this.each(function(){var s,n=t.data(this,o);return n?t.isFunction(n[a])&&"_"!==a.charAt(0)?(s=n[a].apply(n,h),s!==n&&s!==e?(l=s&&s.jquery?l.pushStack(s.get()):s,!1):e):t.error("no such method '"+a+"' for "+i+" widget instance"):t.error("cannot call methods on "+i+" prior to initialization; "+"attempted to call method '"+a+"'")}):this.each(function(){var e=t.data(this,o);e?e.option(a||{})._init():t.data(this,o,new n(a,this))}),l}},t.Widget=function(){},t.Widget._childConstructors=[],t.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{disabled:!1,create:null},_createWidget:function(e,s){s=t(s||this.defaultElement||this)[0],this.element=t(s),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=t.widget.extend({},this.options,this._getCreateOptions(),e),this.bindings=t(),this.hoverable=t(),this.focusable=t(),s!==this&&(t.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t){t.target===s&&this.destroy()}}),this.document=t(s.style?s.ownerDocument:s.document||s),this.window=t(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:t.noop,_getCreateEventData:t.noop,_create:t.noop,_init:t.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(t.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:t.noop,widget:function(){return this.element},option:function(i,s){var n,o,a,r=i;if(0===arguments.length)return t.widget.extend({},this.options);if("string"==typeof i)if(r={},n=i.split("."),i=n.shift(),n.length){for(o=r[i]=t.widget.extend({},this.options[i]),a=0;n.length-1>a;a++)o[n[a]]=o[n[a]]||{},o=o[n[a]];if(i=n.pop(),1===arguments.length)return o[i]===e?null:o[i];o[i]=s}else{if(1===arguments.length)return this.options[i]===e?null:this.options[i];r[i]=s}return this._setOptions(r),this},_setOptions:function(t){var e;for(e in t)this._setOption(e,t[e]);return this},_setOption:function(t,e){return this.options[t]=e,"disabled"===t&&(this.widget().toggleClass(this.widgetFullName+"-disabled ui-state-disabled",!!e).attr("aria-disabled",e),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")),this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_on:function(i,s,n){var o,a=this;"boolean"!=typeof i&&(n=s,s=i,i=!1),n?(s=o=t(s),this.bindings=this.bindings.add(s)):(n=s,s=this.element,o=this.widget()),t.each(n,function(n,r){function h(){return i||a.options.disabled!==!0&&!t(this).hasClass("ui-state-disabled")?("string"==typeof r?a[r]:r).apply(a,arguments):e}"string"!=typeof r&&(h.guid=r.guid=r.guid||h.guid||t.guid++);var l=n.match(/^(\w+)\s*(.*)$/),c=l[1]+a.eventNamespace,u=l[2];u?o.delegate(u,c,h):s.bind(c,h)})},_off:function(t,e){e=(e||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,t.unbind(e).undelegate(e)},_delay:function(t,e){function i(){return("string"==typeof t?s[t]:t).apply(s,arguments)}var s=this;return setTimeout(i,e||0)},_hoverable:function(e){this.hoverable=this.hoverable.add(e),this._on(e,{mouseenter:function(e){t(e.currentTarget).addClass("ui-state-hover")},mouseleave:function(e){t(e.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(e){this.focusable=this.focusable.add(e),this._on(e,{focusin:function(e){t(e.currentTarget).addClass("ui-state-focus")},focusout:function(e){t(e.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(e,i,s){var n,o,a=this.options[e];if(s=s||{},i=t.Event(i),i.type=(e===this.widgetEventPrefix?e:this.widgetEventPrefix+e).toLowerCase(),i.target=this.element[0],o=i.originalEvent)for(n in o)n in i||(i[n]=o[n]);return this.element.trigger(i,s),!(t.isFunction(a)&&a.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},t.each({show:"fadeIn",hide:"fadeOut"},function(e,i){t.Widget.prototype["_"+e]=function(s,n,o){"string"==typeof n&&(n={effect:n});var a,r=n?n===!0||"number"==typeof n?i:n.effect||i:e;n=n||{},"number"==typeof n&&(n={duration:n}),a=!t.isEmptyObject(n),n.complete=o,n.delay&&s.delay(n.delay),a&&t.effects&&t.effects.effect[r]?s[e](n):r!==e&&s[r]?s[r](n.duration,n.easing,o):s.queue(function(i){t(this)[e](),o&&o.call(s[0]),i()})}})}(jQuery),function(t){var e=!1;t(document).mouseup(function(){e=!1}),t.widget("ui.mouse",{version:"1.10.4",options:{cancel:"input,textarea,button,select,option",distance:1,delay:0},_mouseInit:function(){var e=this;this.element.bind("mousedown."+this.widgetName,function(t){return e._mouseDown(t)}).bind("click."+this.widgetName,function(i){return!0===t.data(i.target,e.widgetName+".preventClickEvent")?(t.removeData(i.target,e.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):undefined}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&t(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(i){if(!e){this._mouseStarted&&this._mouseUp(i),this._mouseDownEvent=i;var s=this,n=1===i.which,o="string"==typeof this.options.cancel&&i.target.nodeName?t(i.target).closest(this.options.cancel).length:!1;return n&&!o&&this._mouseCapture(i)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){s.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(i)&&this._mouseDelayMet(i)&&(this._mouseStarted=this._mouseStart(i)!==!1,!this._mouseStarted)?(i.preventDefault(),!0):(!0===t.data(i.target,this.widgetName+".preventClickEvent")&&t.removeData(i.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(t){return s._mouseMove(t)},this._mouseUpDelegate=function(t){return s._mouseUp(t)},t(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),i.preventDefault(),e=!0,!0)):!0}},_mouseMove:function(e){return t.ui.ie&&(!document.documentMode||9>document.documentMode)&&!e.button?this._mouseUp(e):this._mouseStarted?(this._mouseDrag(e),e.preventDefault()):(this._mouseDistanceMet(e)&&this._mouseDelayMet(e)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,e)!==!1,this._mouseStarted?this._mouseDrag(e):this._mouseUp(e)),!this._mouseStarted)},_mouseUp:function(e){return t(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,e.target===this._mouseDownEvent.target&&t.data(e.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(e)),!1},_mouseDistanceMet:function(t){return Math.max(Math.abs(this._mouseDownEvent.pageX-t.pageX),Math.abs(this._mouseDownEvent.pageY-t.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}})}(jQuery),function(t){t.widget("ui.draggable",t.ui.mouse,{version:"1.10.4",widgetEventPrefix:"drag",options:{addClasses:!0,appendTo:"parent",axis:!1,connectToSortable:!1,containment:!1,cursor:"auto",cursorAt:!1,grid:!1,handle:!1,helper:"original",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:"default",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:"both",snapTolerance:20,stack:!1,zIndex:!1,drag:null,start:null,stop:null},_create:function(){"original"!==this.options.helper||/^(?:r|a|f)/.test(this.element.css("position"))||(this.element[0].style.position="relative"),this.options.addClasses&&this.element.addClass("ui-draggable"),this.options.disabled&&this.element.addClass("ui-draggable-disabled"),this._mouseInit()},_destroy:function(){this.element.removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled"),this._mouseDestroy()},_mouseCapture:function(e){var i=this.options;return this.helper||i.disabled||t(e.target).closest(".ui-resizable-handle").length>0?!1:(this.handle=this._getHandle(e),this.handle?(t(i.iframeFix===!0?"iframe":i.iframeFix).each(function(){t("<div class='ui-draggable-iframeFix' style='background: #fff;'></div>").css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1e3}).css(t(this).offset()).appendTo("body")}),!0):!1)},_mouseStart:function(e){var i=this.options;return this.helper=this._createHelper(e),this.helper.addClass("ui-draggable-dragging"),this._cacheHelperProportions(),t.ui.ddmanager&&(t.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(),this.offsetParent=this.helper.offsetParent(),this.offsetParentCssPosition=this.offsetParent.css("position"),this.offset=this.positionAbs=this.element.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},this.offset.scroll=!1,t.extend(this.offset,{click:{left:e.pageX-this.offset.left,top:e.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.originalPosition=this.position=this._generatePosition(e),this.originalPageX=e.pageX,this.originalPageY=e.pageY,i.cursorAt&&this._adjustOffsetFromHelper(i.cursorAt),this._setContainment(),this._trigger("start",e)===!1?(this._clear(),!1):(this._cacheHelperProportions(),t.ui.ddmanager&&!i.dropBehaviour&&t.ui.ddmanager.prepareOffsets(this,e),this._mouseDrag(e,!0),t.ui.ddmanager&&t.ui.ddmanager.dragStart(this,e),!0)},_mouseDrag:function(e,i){if("fixed"===this.offsetParentCssPosition&&(this.offset.parent=this._getParentOffset()),this.position=this._generatePosition(e),this.positionAbs=this._convertPositionTo("absolute"),!i){var s=this._uiHash();if(this._trigger("drag",e,s)===!1)return this._mouseUp({}),!1;this.position=s.position}return this.options.axis&&"y"===this.options.axis||(this.helper[0].style.left=this.position.left+"px"),this.options.axis&&"x"===this.options.axis||(this.helper[0].style.top=this.position.top+"px"),t.ui.ddmanager&&t.ui.ddmanager.drag(this,e),!1},_mouseStop:function(e){var i=this,s=!1;return t.ui.ddmanager&&!this.options.dropBehaviour&&(s=t.ui.ddmanager.drop(this,e)),this.dropped&&(s=this.dropped,this.dropped=!1),"original"!==this.options.helper||t.contains(this.element[0].ownerDocument,this.element[0])?("invalid"===this.options.revert&&!s||"valid"===this.options.revert&&s||this.options.revert===!0||t.isFunction(this.options.revert)&&this.options.revert.call(this.element,s)?t(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){i._trigger("stop",e)!==!1&&i._clear()}):this._trigger("stop",e)!==!1&&this._clear(),!1):!1},_mouseUp:function(e){return t("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)}),t.ui.ddmanager&&t.ui.ddmanager.dragStop(this,e),t.ui.mouse.prototype._mouseUp.call(this,e)},cancel:function(){return this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear(),this},_getHandle:function(e){return this.options.handle?!!t(e.target).closest(this.element.find(this.options.handle)).length:!0},_createHelper:function(e){var i=this.options,s=t.isFunction(i.helper)?t(i.helper.apply(this.element[0],[e])):"clone"===i.helper?this.element.clone().removeAttr("id"):this.element;return s.parents("body").length||s.appendTo("parent"===i.appendTo?this.element[0].parentNode:i.appendTo),s[0]===this.element[0]||/(fixed|absolute)/.test(s.css("position"))||s.css("position","absolute"),s},_adjustOffsetFromHelper:function(e){"string"==typeof e&&(e=e.split(" ")),t.isArray(e)&&(e={left:+e[0],top:+e[1]||0}),"left"in e&&(this.offset.click.left=e.left+this.margins.left),"right"in e&&(this.offset.click.left=this.helperProportions.width-e.right+this.margins.left),"top"in e&&(this.offset.click.top=e.top+this.margins.top),"bottom"in e&&(this.offset.click.top=this.helperProportions.height-e.bottom+this.margins.top)},_getParentOffset:function(){var e=this.offsetParent.offset();return"absolute"===this.cssPosition&&this.scrollParent[0]!==document&&t.contains(this.scrollParent[0],this.offsetParent[0])&&(e.left+=this.scrollParent.scrollLeft(),e.top+=this.scrollParent.scrollTop()),(this.offsetParent[0]===document.body||this.offsetParent[0].tagName&&"html"===this.offsetParent[0].tagName.toLowerCase()&&t.ui.ie)&&(e={top:0,left:0}),{top:e.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:e.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"===this.cssPosition){var t=this.element.position();return{top:t.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:t.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var e,i,s,n=this.options;return n.containment?"window"===n.containment?(this.containment=[t(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,t(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,t(window).scrollLeft()+t(window).width()-this.helperProportions.width-this.margins.left,t(window).scrollTop()+(t(window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],undefined):"document"===n.containment?(this.containment=[0,0,t(document).width()-this.helperProportions.width-this.margins.left,(t(document).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],undefined):n.containment.constructor===Array?(this.containment=n.containment,undefined):("parent"===n.containment&&(n.containment=this.helper[0].parentNode),i=t(n.containment),s=i[0],s&&(e="hidden"!==i.css("overflow"),this.containment=[(parseInt(i.css("borderLeftWidth"),10)||0)+(parseInt(i.css("paddingLeft"),10)||0),(parseInt(i.css("borderTopWidth"),10)||0)+(parseInt(i.css("paddingTop"),10)||0),(e?Math.max(s.scrollWidth,s.offsetWidth):s.offsetWidth)-(parseInt(i.css("borderRightWidth"),10)||0)-(parseInt(i.css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(e?Math.max(s.scrollHeight,s.offsetHeight):s.offsetHeight)-(parseInt(i.css("borderBottomWidth"),10)||0)-(parseInt(i.css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relative_container=i),undefined):(this.containment=null,undefined)},_convertPositionTo:function(e,i){i||(i=this.position);var s="absolute"===e?1:-1,n="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent;return this.offset.scroll||(this.offset.scroll={top:n.scrollTop(),left:n.scrollLeft()}),{top:i.top+this.offset.relative.top*s+this.offset.parent.top*s-("fixed"===this.cssPosition?-this.scrollParent.scrollTop():this.offset.scroll.top)*s,left:i.left+this.offset.relative.left*s+this.offset.parent.left*s-("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():this.offset.scroll.left)*s}},_generatePosition:function(e){var i,s,n,o,a=this.options,r="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,h=e.pageX,l=e.pageY;return this.offset.scroll||(this.offset.scroll={top:r.scrollTop(),left:r.scrollLeft()}),this.originalPosition&&(this.containment&&(this.relative_container?(s=this.relative_container.offset(),i=[this.containment[0]+s.left,this.containment[1]+s.top,this.containment[2]+s.left,this.containment[3]+s.top]):i=this.containment,e.pageX-this.offset.click.left<i[0]&&(h=i[0]+this.offset.click.left),e.pageY-this.offset.click.top<i[1]&&(l=i[1]+this.offset.click.top),e.pageX-this.offset.click.left>i[2]&&(h=i[2]+this.offset.click.left),e.pageY-this.offset.click.top>i[3]&&(l=i[3]+this.offset.click.top)),a.grid&&(n=a.grid[1]?this.originalPageY+Math.round((l-this.originalPageY)/a.grid[1])*a.grid[1]:this.originalPageY,l=i?n-this.offset.click.top>=i[1]||n-this.offset.click.top>i[3]?n:n-this.offset.click.top>=i[1]?n-a.grid[1]:n+a.grid[1]:n,o=a.grid[0]?this.originalPageX+Math.round((h-this.originalPageX)/a.grid[0])*a.grid[0]:this.originalPageX,h=i?o-this.offset.click.left>=i[0]||o-this.offset.click.left>i[2]?o:o-this.offset.click.left>=i[0]?o-a.grid[0]:o+a.grid[0]:o)),{top:l-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.scrollParent.scrollTop():this.offset.scroll.top),left:h-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():this.offset.scroll.left)}},_clear:function(){this.helper.removeClass("ui-draggable-dragging"),this.helper[0]===this.element[0]||this.cancelHelperRemoval||this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1},_trigger:function(e,i,s){return s=s||this._uiHash(),t.ui.plugin.call(this,e,[i,s]),"drag"===e&&(this.positionAbs=this._convertPositionTo("absolute")),t.Widget.prototype._trigger.call(this,e,i,s)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),t.ui.plugin.add("draggable","connectToSortable",{start:function(e,i){var s=t(this).data("ui-draggable"),n=s.options,o=t.extend({},i,{item:s.element});s.sortables=[],t(n.connectToSortable).each(function(){var i=t.data(this,"ui-sortable");i&&!i.options.disabled&&(s.sortables.push({instance:i,shouldRevert:i.options.revert}),i.refreshPositions(),i._trigger("activate",e,o))})},stop:function(e,i){var s=t(this).data("ui-draggable"),n=t.extend({},i,{item:s.element});t.each(s.sortables,function(){this.instance.isOver?(this.instance.isOver=0,s.cancelHelperRemoval=!0,this.instance.cancelHelperRemoval=!1,this.shouldRevert&&(this.instance.options.revert=this.shouldRevert),this.instance._mouseStop(e),this.instance.options.helper=this.instance.options._helper,"original"===s.options.helper&&this.instance.currentItem.css({top:"auto",left:"auto"})):(this.instance.cancelHelperRemoval=!1,this.instance._trigger("deactivate",e,n))})},drag:function(e,i){var s=t(this).data("ui-draggable"),n=this;t.each(s.sortables,function(){var o=!1,a=this;this.instance.positionAbs=s.positionAbs,this.instance.helperProportions=s.helperProportions,this.instance.offset.click=s.offset.click,this.instance._intersectsWith(this.instance.containerCache)&&(o=!0,t.each(s.sortables,function(){return this.instance.positionAbs=s.positionAbs,this.instance.helperProportions=s.helperProportions,this.instance.offset.click=s.offset.click,this!==a&&this.instance._intersectsWith(this.instance.containerCache)&&t.contains(a.instance.element[0],this.instance.element[0])&&(o=!1),o})),o?(this.instance.isOver||(this.instance.isOver=1,this.instance.currentItem=t(n).clone().removeAttr("id").appendTo(this.instance.element).data("ui-sortable-item",!0),this.instance.options._helper=this.instance.options.helper,this.instance.options.helper=function(){return i.helper[0]},e.target=this.instance.currentItem[0],this.instance._mouseCapture(e,!0),this.instance._mouseStart(e,!0,!0),this.instance.offset.click.top=s.offset.click.top,this.instance.offset.click.left=s.offset.click.left,this.instance.offset.parent.left-=s.offset.parent.left-this.instance.offset.parent.left,this.instance.offset.parent.top-=s.offset.parent.top-this.instance.offset.parent.top,s._trigger("toSortable",e),s.dropped=this.instance.element,s.currentItem=s.element,this.instance.fromOutside=s),this.instance.currentItem&&this.instance._mouseDrag(e)):this.instance.isOver&&(this.instance.isOver=0,this.instance.cancelHelperRemoval=!0,this.instance.options.revert=!1,this.instance._trigger("out",e,this.instance._uiHash(this.instance)),this.instance._mouseStop(e,!0),this.instance.options.helper=this.instance.options._helper,this.instance.currentItem.remove(),this.instance.placeholder&&this.instance.placeholder.remove(),s._trigger("fromSortable",e),s.dropped=!1)})}}),t.ui.plugin.add("draggable","cursor",{start:function(){var e=t("body"),i=t(this).data("ui-draggable").options;e.css("cursor")&&(i._cursor=e.css("cursor")),e.css("cursor",i.cursor)},stop:function(){var e=t(this).data("ui-draggable").options;e._cursor&&t("body").css("cursor",e._cursor)}}),t.ui.plugin.add("draggable","opacity",{start:function(e,i){var s=t(i.helper),n=t(this).data("ui-draggable").options;s.css("opacity")&&(n._opacity=s.css("opacity")),s.css("opacity",n.opacity)},stop:function(e,i){var s=t(this).data("ui-draggable").options;s._opacity&&t(i.helper).css("opacity",s._opacity)}}),t.ui.plugin.add("draggable","scroll",{start:function(){var e=t(this).data("ui-draggable");e.scrollParent[0]!==document&&"HTML"!==e.scrollParent[0].tagName&&(e.overflowOffset=e.scrollParent.offset())},drag:function(e){var i=t(this).data("ui-draggable"),s=i.options,n=!1;i.scrollParent[0]!==document&&"HTML"!==i.scrollParent[0].tagName?(s.axis&&"x"===s.axis||(i.overflowOffset.top+i.scrollParent[0].offsetHeight-e.pageY<s.scrollSensitivity?i.scrollParent[0].scrollTop=n=i.scrollParent[0].scrollTop+s.scrollSpeed:e.pageY-i.overflowOffset.top<s.scrollSensitivity&&(i.scrollParent[0].scrollTop=n=i.scrollParent[0].scrollTop-s.scrollSpeed)),s.axis&&"y"===s.axis||(i.overflowOffset.left+i.scrollParent[0].offsetWidth-e.pageX<s.scrollSensitivity?i.scrollParent[0].scrollLeft=n=i.scrollParent[0].scrollLeft+s.scrollSpeed:e.pageX-i.overflowOffset.left<s.scrollSensitivity&&(i.scrollParent[0].scrollLeft=n=i.scrollParent[0].scrollLeft-s.scrollSpeed))):(s.axis&&"x"===s.axis||(e.pageY-t(document).scrollTop()<s.scrollSensitivity?n=t(document).scrollTop(t(document).scrollTop()-s.scrollSpeed):t(window).height()-(e.pageY-t(document).scrollTop())<s.scrollSensitivity&&(n=t(document).scrollTop(t(document).scrollTop()+s.scrollSpeed))),s.axis&&"y"===s.axis||(e.pageX-t(document).scrollLeft()<s.scrollSensitivity?n=t(document).scrollLeft(t(document).scrollLeft()-s.scrollSpeed):t(window).width()-(e.pageX-t(document).scrollLeft())<s.scrollSensitivity&&(n=t(document).scrollLeft(t(document).scrollLeft()+s.scrollSpeed)))),n!==!1&&t.ui.ddmanager&&!s.dropBehaviour&&t.ui.ddmanager.prepareOffsets(i,e)}}),t.ui.plugin.add("draggable","snap",{start:function(){var e=t(this).data("ui-draggable"),i=e.options;e.snapElements=[],t(i.snap.constructor!==String?i.snap.items||":data(ui-draggable)":i.snap).each(function(){var i=t(this),s=i.offset();this!==e.element[0]&&e.snapElements.push({item:this,width:i.outerWidth(),height:i.outerHeight(),top:s.top,left:s.left})})},drag:function(e,i){var s,n,o,a,r,h,l,c,u,d,p=t(this).data("ui-draggable"),f=p.options,g=f.snapTolerance,m=i.offset.left,v=m+p.helperProportions.width,_=i.offset.top,b=_+p.helperProportions.height;for(u=p.snapElements.length-1;u>=0;u--)r=p.snapElements[u].left,h=r+p.snapElements[u].width,l=p.snapElements[u].top,c=l+p.snapElements[u].height,r-g>v||m>h+g||l-g>b||_>c+g||!t.contains(p.snapElements[u].item.ownerDocument,p.snapElements[u].item)?(p.snapElements[u].snapping&&p.options.snap.release&&p.options.snap.release.call(p.element,e,t.extend(p._uiHash(),{snapItem:p.snapElements[u].item})),p.snapElements[u].snapping=!1):("inner"!==f.snapMode&&(s=g>=Math.abs(l-b),n=g>=Math.abs(c-_),o=g>=Math.abs(r-v),a=g>=Math.abs(h-m),s&&(i.position.top=p._convertPositionTo("relative",{top:l-p.helperProportions.height,left:0}).top-p.margins.top),n&&(i.position.top=p._convertPositionTo("relative",{top:c,left:0}).top-p.margins.top),o&&(i.position.left=p._convertPositionTo("relative",{top:0,left:r-p.helperProportions.width}).left-p.margins.left),a&&(i.position.left=p._convertPositionTo("relative",{top:0,left:h}).left-p.margins.left)),d=s||n||o||a,"outer"!==f.snapMode&&(s=g>=Math.abs(l-_),n=g>=Math.abs(c-b),o=g>=Math.abs(r-m),a=g>=Math.abs(h-v),s&&(i.position.top=p._convertPositionTo("relative",{top:l,left:0}).top-p.margins.top),n&&(i.position.top=p._convertPositionTo("relative",{top:c-p.helperProportions.height,left:0}).top-p.margins.top),o&&(i.position.left=p._convertPositionTo("relative",{top:0,left:r}).left-p.margins.left),a&&(i.position.left=p._convertPositionTo("relative",{top:0,left:h-p.helperProportions.width}).left-p.margins.left)),!p.snapElements[u].snapping&&(s||n||o||a||d)&&p.options.snap.snap&&p.options.snap.snap.call(p.element,e,t.extend(p._uiHash(),{snapItem:p.snapElements[u].item})),p.snapElements[u].snapping=s||n||o||a||d)}}),t.ui.plugin.add("draggable","stack",{start:function(){var e,i=this.data("ui-draggable").options,s=t.makeArray(t(i.stack)).sort(function(e,i){return(parseInt(t(e).css("zIndex"),10)||0)-(parseInt(t(i).css("zIndex"),10)||0)});s.length&&(e=parseInt(t(s[0]).css("zIndex"),10)||0,t(s).each(function(i){t(this).css("zIndex",e+i)}),this.css("zIndex",e+s.length))}}),t.ui.plugin.add("draggable","zIndex",{start:function(e,i){var s=t(i.helper),n=t(this).data("ui-draggable").options;s.css("zIndex")&&(n._zIndex=s.css("zIndex")),s.css("zIndex",n.zIndex)},stop:function(e,i){var s=t(this).data("ui-draggable").options;s._zIndex&&t(i.helper).css("zIndex",s._zIndex)}})}(jQuery),function(t){function e(t,e,i){return t>e&&e+i>t}t.widget("ui.droppable",{version:"1.10.4",widgetEventPrefix:"drop",options:{accept:"*",activeClass:!1,addClasses:!0,greedy:!1,hoverClass:!1,scope:"default",tolerance:"intersect",activate:null,deactivate:null,drop:null,out:null,over:null},_create:function(){var e,i=this.options,s=i.accept;
+this.isover=!1,this.isout=!0,this.accept=t.isFunction(s)?s:function(t){return t.is(s)},this.proportions=function(){return arguments.length?(e=arguments[0],undefined):e?e:e={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight}},t.ui.ddmanager.droppables[i.scope]=t.ui.ddmanager.droppables[i.scope]||[],t.ui.ddmanager.droppables[i.scope].push(this),i.addClasses&&this.element.addClass("ui-droppable")},_destroy:function(){for(var e=0,i=t.ui.ddmanager.droppables[this.options.scope];i.length>e;e++)i[e]===this&&i.splice(e,1);this.element.removeClass("ui-droppable ui-droppable-disabled")},_setOption:function(e,i){"accept"===e&&(this.accept=t.isFunction(i)?i:function(t){return t.is(i)}),t.Widget.prototype._setOption.apply(this,arguments)},_activate:function(e){var i=t.ui.ddmanager.current;this.options.activeClass&&this.element.addClass(this.options.activeClass),i&&this._trigger("activate",e,this.ui(i))},_deactivate:function(e){var i=t.ui.ddmanager.current;this.options.activeClass&&this.element.removeClass(this.options.activeClass),i&&this._trigger("deactivate",e,this.ui(i))},_over:function(e){var i=t.ui.ddmanager.current;i&&(i.currentItem||i.element)[0]!==this.element[0]&&this.accept.call(this.element[0],i.currentItem||i.element)&&(this.options.hoverClass&&this.element.addClass(this.options.hoverClass),this._trigger("over",e,this.ui(i)))},_out:function(e){var i=t.ui.ddmanager.current;i&&(i.currentItem||i.element)[0]!==this.element[0]&&this.accept.call(this.element[0],i.currentItem||i.element)&&(this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("out",e,this.ui(i)))},_drop:function(e,i){var s=i||t.ui.ddmanager.current,n=!1;return s&&(s.currentItem||s.element)[0]!==this.element[0]?(this.element.find(":data(ui-droppable)").not(".ui-draggable-dragging").each(function(){var e=t.data(this,"ui-droppable");return e.options.greedy&&!e.options.disabled&&e.options.scope===s.options.scope&&e.accept.call(e.element[0],s.currentItem||s.element)&&t.ui.intersect(s,t.extend(e,{offset:e.element.offset()}),e.options.tolerance)?(n=!0,!1):undefined}),n?!1:this.accept.call(this.element[0],s.currentItem||s.element)?(this.options.activeClass&&this.element.removeClass(this.options.activeClass),this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("drop",e,this.ui(s)),this.element):!1):!1},ui:function(t){return{draggable:t.currentItem||t.element,helper:t.helper,position:t.position,offset:t.positionAbs}}}),t.ui.intersect=function(t,i,s){if(!i.offset)return!1;var n,o,a=(t.positionAbs||t.position.absolute).left,r=(t.positionAbs||t.position.absolute).top,h=a+t.helperProportions.width,l=r+t.helperProportions.height,c=i.offset.left,u=i.offset.top,d=c+i.proportions().width,p=u+i.proportions().height;switch(s){case"fit":return a>=c&&d>=h&&r>=u&&p>=l;case"intersect":return a+t.helperProportions.width/2>c&&d>h-t.helperProportions.width/2&&r+t.helperProportions.height/2>u&&p>l-t.helperProportions.height/2;case"pointer":return n=(t.positionAbs||t.position.absolute).left+(t.clickOffset||t.offset.click).left,o=(t.positionAbs||t.position.absolute).top+(t.clickOffset||t.offset.click).top,e(o,u,i.proportions().height)&&e(n,c,i.proportions().width);case"touch":return(r>=u&&p>=r||l>=u&&p>=l||u>r&&l>p)&&(a>=c&&d>=a||h>=c&&d>=h||c>a&&h>d);default:return!1}},t.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(e,i){var s,n,o=t.ui.ddmanager.droppables[e.options.scope]||[],a=i?i.type:null,r=(e.currentItem||e.element).find(":data(ui-droppable)").addBack();t:for(s=0;o.length>s;s++)if(!(o[s].options.disabled||e&&!o[s].accept.call(o[s].element[0],e.currentItem||e.element))){for(n=0;r.length>n;n++)if(r[n]===o[s].element[0]){o[s].proportions().height=0;continue t}o[s].visible="none"!==o[s].element.css("display"),o[s].visible&&("mousedown"===a&&o[s]._activate.call(o[s],i),o[s].offset=o[s].element.offset(),o[s].proportions({width:o[s].element[0].offsetWidth,height:o[s].element[0].offsetHeight}))}},drop:function(e,i){var s=!1;return t.each((t.ui.ddmanager.droppables[e.options.scope]||[]).slice(),function(){this.options&&(!this.options.disabled&&this.visible&&t.ui.intersect(e,this,this.options.tolerance)&&(s=this._drop.call(this,i)||s),!this.options.disabled&&this.visible&&this.accept.call(this.element[0],e.currentItem||e.element)&&(this.isout=!0,this.isover=!1,this._deactivate.call(this,i)))}),s},dragStart:function(e,i){e.element.parentsUntil("body").bind("scroll.droppable",function(){e.options.refreshPositions||t.ui.ddmanager.prepareOffsets(e,i)})},drag:function(e,i){e.options.refreshPositions&&t.ui.ddmanager.prepareOffsets(e,i),t.each(t.ui.ddmanager.droppables[e.options.scope]||[],function(){if(!this.options.disabled&&!this.greedyChild&&this.visible){var s,n,o,a=t.ui.intersect(e,this,this.options.tolerance),r=!a&&this.isover?"isout":a&&!this.isover?"isover":null;r&&(this.options.greedy&&(n=this.options.scope,o=this.element.parents(":data(ui-droppable)").filter(function(){return t.data(this,"ui-droppable").options.scope===n}),o.length&&(s=t.data(o[0],"ui-droppable"),s.greedyChild="isover"===r)),s&&"isover"===r&&(s.isover=!1,s.isout=!0,s._out.call(s,i)),this[r]=!0,this["isout"===r?"isover":"isout"]=!1,this["isover"===r?"_over":"_out"].call(this,i),s&&"isout"===r&&(s.isout=!1,s.isover=!0,s._over.call(s,i)))}})},dragStop:function(e,i){e.element.parentsUntil("body").unbind("scroll.droppable"),e.options.refreshPositions||t.ui.ddmanager.prepareOffsets(e,i)}}}(jQuery),function(t){function e(t){return parseInt(t,10)||0}function i(t){return!isNaN(parseInt(t,10))}t.widget("ui.resizable",t.ui.mouse,{version:"1.10.4",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:90,resize:null,start:null,stop:null},_create:function(){var e,i,s,n,o,a=this,r=this.options;if(this.element.addClass("ui-resizable"),t.extend(this,{_aspectRatio:!!r.aspectRatio,aspectRatio:r.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:r.helper||r.ghost||r.animate?r.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)&&(this.element.wrap(t("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("ui-resizable",this.element.data("ui-resizable")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=r.handles||(t(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se"),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,sw,ne,nw"),e=this.handles.split(","),this.handles={},i=0;e.length>i;i++)s=t.trim(e[i]),o="ui-resizable-"+s,n=t("<div class='ui-resizable-handle "+o+"'></div>"),n.css({zIndex:r.zIndex}),"se"===s&&n.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[s]=".ui-resizable-"+s,this.element.append(n);this._renderAxis=function(e){var i,s,n,o;e=e||this.element;for(i in this.handles)this.handles[i].constructor===String&&(this.handles[i]=t(this.handles[i],this.element).show()),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)&&(s=t(this.handles[i],this.element),o=/sw|ne|nw|se|n|s/.test(i)?s.outerHeight():s.outerWidth(),n=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join(""),e.css(n,o),this._proportionallyResize()),t(this.handles[i]).length},this._renderAxis(this.element),this._handles=t(".ui-resizable-handle",this.element).disableSelection(),this._handles.mouseover(function(){a.resizing||(this.className&&(n=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),a.axis=n&&n[1]?n[1]:"se")}),r.autoHide&&(this._handles.hide(),t(this.element).addClass("ui-resizable-autohide").mouseenter(function(){r.disabled||(t(this).removeClass("ui-resizable-autohide"),a._handles.show())}).mouseleave(function(){r.disabled||a.resizing||(t(this).addClass("ui-resizable-autohide"),a._handles.hide())})),this._mouseInit()},_destroy:function(){this._mouseDestroy();var e,i=function(e){t(e).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};return this.elementIsWrapper&&(i(this.element),e=this.element,this.originalElement.css({position:e.css("position"),width:e.outerWidth(),height:e.outerHeight(),top:e.css("top"),left:e.css("left")}).insertAfter(e),e.remove()),this.originalElement.css("resize",this.originalResizeStyle),i(this.originalElement),this},_mouseCapture:function(e){var i,s,n=!1;for(i in this.handles)s=t(this.handles[i])[0],(s===e.target||t.contains(s,e.target))&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(i){var s,n,o,a=this.options,r=this.element.position(),h=this.element;return this.resizing=!0,/absolute/.test(h.css("position"))?h.css({position:"absolute",top:h.css("top"),left:h.css("left")}):h.is(".ui-draggable")&&h.css({position:"absolute",top:r.top,left:r.left}),this._renderProxy(),s=e(this.helper.css("left")),n=e(this.helper.css("top")),a.containment&&(s+=t(a.containment).scrollLeft()||0,n+=t(a.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:s,top:n},this.size=this._helper?{width:this.helper.width(),height:this.helper.height()}:{width:h.width(),height:h.height()},this.originalSize=this._helper?{width:h.outerWidth(),height:h.outerHeight()}:{width:h.width(),height:h.height()},this.originalPosition={left:s,top:n},this.sizeDiff={width:h.outerWidth()-h.width(),height:h.outerHeight()-h.height()},this.originalMousePosition={left:i.pageX,top:i.pageY},this.aspectRatio="number"==typeof a.aspectRatio?a.aspectRatio:this.originalSize.width/this.originalSize.height||1,o=t(".ui-resizable-"+this.axis).css("cursor"),t("body").css("cursor","auto"===o?this.axis+"-resize":o),h.addClass("ui-resizable-resizing"),this._propagate("start",i),!0},_mouseDrag:function(e){var i,s=this.helper,n={},o=this.originalMousePosition,a=this.axis,r=this.position.top,h=this.position.left,l=this.size.width,c=this.size.height,u=e.pageX-o.left||0,d=e.pageY-o.top||0,p=this._change[a];return p?(i=p.apply(this,[e,u,d]),this._updateVirtualBoundaries(e.shiftKey),(this._aspectRatio||e.shiftKey)&&(i=this._updateRatio(i,e)),i=this._respectSize(i,e),this._updateCache(i),this._propagate("resize",e),this.position.top!==r&&(n.top=this.position.top+"px"),this.position.left!==h&&(n.left=this.position.left+"px"),this.size.width!==l&&(n.width=this.size.width+"px"),this.size.height!==c&&(n.height=this.size.height+"px"),s.css(n),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),t.isEmptyObject(n)||this._trigger("resize",e,this.ui()),!1):!1},_mouseStop:function(e){this.resizing=!1;var i,s,n,o,a,r,h,l=this.options,c=this;return this._helper&&(i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),n=s&&t.ui.hasScroll(i[0],"left")?0:c.sizeDiff.height,o=s?0:c.sizeDiff.width,a={width:c.helper.width()-o,height:c.helper.height()-n},r=parseInt(c.element.css("left"),10)+(c.position.left-c.originalPosition.left)||null,h=parseInt(c.element.css("top"),10)+(c.position.top-c.originalPosition.top)||null,l.animate||this.element.css(t.extend(a,{top:h,left:r})),c.helper.height(c.size.height),c.helper.width(c.size.width),this._helper&&!l.animate&&this._proportionallyResize()),t("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",e),this._helper&&this.helper.remove(),!1},_updateVirtualBoundaries:function(t){var e,s,n,o,a,r=this.options;a={minWidth:i(r.minWidth)?r.minWidth:0,maxWidth:i(r.maxWidth)?r.maxWidth:1/0,minHeight:i(r.minHeight)?r.minHeight:0,maxHeight:i(r.maxHeight)?r.maxHeight:1/0},(this._aspectRatio||t)&&(e=a.minHeight*this.aspectRatio,n=a.minWidth/this.aspectRatio,s=a.maxHeight*this.aspectRatio,o=a.maxWidth/this.aspectRatio,e>a.minWidth&&(a.minWidth=e),n>a.minHeight&&(a.minHeight=n),a.maxWidth>s&&(a.maxWidth=s),a.maxHeight>o&&(a.maxHeight=o)),this._vBoundaries=a},_updateCache:function(t){this.offset=this.helper.offset(),i(t.left)&&(this.position.left=t.left),i(t.top)&&(this.position.top=t.top),i(t.height)&&(this.size.height=t.height),i(t.width)&&(this.size.width=t.width)},_updateRatio:function(t){var e=this.position,s=this.size,n=this.axis;return i(t.height)?t.width=t.height*this.aspectRatio:i(t.width)&&(t.height=t.width/this.aspectRatio),"sw"===n&&(t.left=e.left+(s.width-t.width),t.top=null),"nw"===n&&(t.top=e.top+(s.height-t.height),t.left=e.left+(s.width-t.width)),t},_respectSize:function(t){var e=this._vBoundaries,s=this.axis,n=i(t.width)&&e.maxWidth&&e.maxWidth<t.width,o=i(t.height)&&e.maxHeight&&e.maxHeight<t.height,a=i(t.width)&&e.minWidth&&e.minWidth>t.width,r=i(t.height)&&e.minHeight&&e.minHeight>t.height,h=this.originalPosition.left+this.originalSize.width,l=this.position.top+this.size.height,c=/sw|nw|w/.test(s),u=/nw|ne|n/.test(s);return a&&(t.width=e.minWidth),r&&(t.height=e.minHeight),n&&(t.width=e.maxWidth),o&&(t.height=e.maxHeight),a&&c&&(t.left=h-e.minWidth),n&&c&&(t.left=h-e.maxWidth),r&&u&&(t.top=l-e.minHeight),o&&u&&(t.top=l-e.maxHeight),t.width||t.height||t.left||!t.top?t.width||t.height||t.top||!t.left||(t.left=null):t.top=null,t},_proportionallyResize:function(){if(this._proportionallyResizeElements.length){var t,e,i,s,n,o=this.helper||this.element;for(t=0;this._proportionallyResizeElements.length>t;t++){if(n=this._proportionallyResizeElements[t],!this.borderDif)for(this.borderDif=[],i=[n.css("borderTopWidth"),n.css("borderRightWidth"),n.css("borderBottomWidth"),n.css("borderLeftWidth")],s=[n.css("paddingTop"),n.css("paddingRight"),n.css("paddingBottom"),n.css("paddingLeft")],e=0;i.length>e;e++)this.borderDif[e]=(parseInt(i[e],10)||0)+(parseInt(s[e],10)||0);n.css({height:o.height()-this.borderDif[0]-this.borderDif[2]||0,width:o.width()-this.borderDif[1]-this.borderDif[3]||0})}}},_renderProxy:function(){var e=this.element,i=this.options;this.elementOffset=e.offset(),this._helper?(this.helper=this.helper||t("<div style='overflow:hidden;'></div>"),this.helper.addClass(this._helper).css({width:this.element.outerWidth()-1,height:this.element.outerHeight()-1,position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++i.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element},_change:{e:function(t,e){return{width:this.originalSize.width+e}},w:function(t,e){var i=this.originalSize,s=this.originalPosition;return{left:s.left+e,width:i.width-e}},n:function(t,e,i){var s=this.originalSize,n=this.originalPosition;return{top:n.top+i,height:s.height-i}},s:function(t,e,i){return{height:this.originalSize.height+i}},se:function(e,i,s){return t.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[e,i,s]))},sw:function(e,i,s){return t.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[e,i,s]))},ne:function(e,i,s){return t.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[e,i,s]))},nw:function(e,i,s){return t.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[e,i,s]))}},_propagate:function(e,i){t.ui.plugin.call(this,e,[i,this.ui()]),"resize"!==e&&this._trigger(e,i,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),t.ui.plugin.add("resizable","animate",{stop:function(e){var i=t(this).data("ui-resizable"),s=i.options,n=i._proportionallyResizeElements,o=n.length&&/textarea/i.test(n[0].nodeName),a=o&&t.ui.hasScroll(n[0],"left")?0:i.sizeDiff.height,r=o?0:i.sizeDiff.width,h={width:i.size.width-r,height:i.size.height-a},l=parseInt(i.element.css("left"),10)+(i.position.left-i.originalPosition.left)||null,c=parseInt(i.element.css("top"),10)+(i.position.top-i.originalPosition.top)||null;i.element.animate(t.extend(h,c&&l?{top:c,left:l}:{}),{duration:s.animateDuration,easing:s.animateEasing,step:function(){var s={width:parseInt(i.element.css("width"),10),height:parseInt(i.element.css("height"),10),top:parseInt(i.element.css("top"),10),left:parseInt(i.element.css("left"),10)};n&&n.length&&t(n[0]).css({width:s.width,height:s.height}),i._updateCache(s),i._propagate("resize",e)}})}}),t.ui.plugin.add("resizable","containment",{start:function(){var i,s,n,o,a,r,h,l=t(this).data("ui-resizable"),c=l.options,u=l.element,d=c.containment,p=d instanceof t?d.get(0):/parent/.test(d)?u.parent().get(0):d;p&&(l.containerElement=t(p),/document/.test(d)||d===document?(l.containerOffset={left:0,top:0},l.containerPosition={left:0,top:0},l.parentData={element:t(document),left:0,top:0,width:t(document).width(),height:t(document).height()||document.body.parentNode.scrollHeight}):(i=t(p),s=[],t(["Top","Right","Left","Bottom"]).each(function(t,n){s[t]=e(i.css("padding"+n))}),l.containerOffset=i.offset(),l.containerPosition=i.position(),l.containerSize={height:i.innerHeight()-s[3],width:i.innerWidth()-s[1]},n=l.containerOffset,o=l.containerSize.height,a=l.containerSize.width,r=t.ui.hasScroll(p,"left")?p.scrollWidth:a,h=t.ui.hasScroll(p)?p.scrollHeight:o,l.parentData={element:p,left:n.left,top:n.top,width:r,height:h}))},resize:function(e){var i,s,n,o,a=t(this).data("ui-resizable"),r=a.options,h=a.containerOffset,l=a.position,c=a._aspectRatio||e.shiftKey,u={top:0,left:0},d=a.containerElement;d[0]!==document&&/static/.test(d.css("position"))&&(u=h),l.left<(a._helper?h.left:0)&&(a.size.width=a.size.width+(a._helper?a.position.left-h.left:a.position.left-u.left),c&&(a.size.height=a.size.width/a.aspectRatio),a.position.left=r.helper?h.left:0),l.top<(a._helper?h.top:0)&&(a.size.height=a.size.height+(a._helper?a.position.top-h.top:a.position.top),c&&(a.size.width=a.size.height*a.aspectRatio),a.position.top=a._helper?h.top:0),a.offset.left=a.parentData.left+a.position.left,a.offset.top=a.parentData.top+a.position.top,i=Math.abs((a._helper?a.offset.left-u.left:a.offset.left-u.left)+a.sizeDiff.width),s=Math.abs((a._helper?a.offset.top-u.top:a.offset.top-h.top)+a.sizeDiff.height),n=a.containerElement.get(0)===a.element.parent().get(0),o=/relative|absolute/.test(a.containerElement.css("position")),n&&o&&(i-=Math.abs(a.parentData.left)),i+a.size.width>=a.parentData.width&&(a.size.width=a.parentData.width-i,c&&(a.size.height=a.size.width/a.aspectRatio)),s+a.size.height>=a.parentData.height&&(a.size.height=a.parentData.height-s,c&&(a.size.width=a.size.height*a.aspectRatio))},stop:function(){var e=t(this).data("ui-resizable"),i=e.options,s=e.containerOffset,n=e.containerPosition,o=e.containerElement,a=t(e.helper),r=a.offset(),h=a.outerWidth()-e.sizeDiff.width,l=a.outerHeight()-e.sizeDiff.height;e._helper&&!i.animate&&/relative/.test(o.css("position"))&&t(this).css({left:r.left-n.left-s.left,width:h,height:l}),e._helper&&!i.animate&&/static/.test(o.css("position"))&&t(this).css({left:r.left-n.left-s.left,width:h,height:l})}}),t.ui.plugin.add("resizable","alsoResize",{start:function(){var e=t(this).data("ui-resizable"),i=e.options,s=function(e){t(e).each(function(){var e=t(this);e.data("ui-resizable-alsoresize",{width:parseInt(e.width(),10),height:parseInt(e.height(),10),left:parseInt(e.css("left"),10),top:parseInt(e.css("top"),10)})})};"object"!=typeof i.alsoResize||i.alsoResize.parentNode?s(i.alsoResize):i.alsoResize.length?(i.alsoResize=i.alsoResize[0],s(i.alsoResize)):t.each(i.alsoResize,function(t){s(t)})},resize:function(e,i){var s=t(this).data("ui-resizable"),n=s.options,o=s.originalSize,a=s.originalPosition,r={height:s.size.height-o.height||0,width:s.size.width-o.width||0,top:s.position.top-a.top||0,left:s.position.left-a.left||0},h=function(e,s){t(e).each(function(){var e=t(this),n=t(this).data("ui-resizable-alsoresize"),o={},a=s&&s.length?s:e.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];t.each(a,function(t,e){var i=(n[e]||0)+(r[e]||0);i&&i>=0&&(o[e]=i||null)}),e.css(o)})};"object"!=typeof n.alsoResize||n.alsoResize.nodeType?h(n.alsoResize):t.each(n.alsoResize,function(t,e){h(t,e)})},stop:function(){t(this).removeData("resizable-alsoresize")}}),t.ui.plugin.add("resizable","ghost",{start:function(){var e=t(this).data("ui-resizable"),i=e.options,s=e.size;e.ghost=e.originalElement.clone(),e.ghost.css({opacity:.25,display:"block",position:"relative",height:s.height,width:s.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass("string"==typeof i.ghost?i.ghost:""),e.ghost.appendTo(e.helper)},resize:function(){var e=t(this).data("ui-resizable");e.ghost&&e.ghost.css({position:"relative",height:e.size.height,width:e.size.width})},stop:function(){var e=t(this).data("ui-resizable");e.ghost&&e.helper&&e.helper.get(0).removeChild(e.ghost.get(0))}}),t.ui.plugin.add("resizable","grid",{resize:function(){var e=t(this).data("ui-resizable"),i=e.options,s=e.size,n=e.originalSize,o=e.originalPosition,a=e.axis,r="number"==typeof i.grid?[i.grid,i.grid]:i.grid,h=r[0]||1,l=r[1]||1,c=Math.round((s.width-n.width)/h)*h,u=Math.round((s.height-n.height)/l)*l,d=n.width+c,p=n.height+u,f=i.maxWidth&&d>i.maxWidth,g=i.maxHeight&&p>i.maxHeight,m=i.minWidth&&i.minWidth>d,v=i.minHeight&&i.minHeight>p;i.grid=r,m&&(d+=h),v&&(p+=l),f&&(d-=h),g&&(p-=l),/^(se|s|e)$/.test(a)?(e.size.width=d,e.size.height=p):/^(ne)$/.test(a)?(e.size.width=d,e.size.height=p,e.position.top=o.top-u):/^(sw)$/.test(a)?(e.size.width=d,e.size.height=p,e.position.left=o.left-c):(p-l>0?(e.size.height=p,e.position.top=o.top-u):(e.size.height=l,e.position.top=o.top+n.height-l),d-h>0?(e.size.width=d,e.position.left=o.left-c):(e.size.width=h,e.position.left=o.left+n.width-h))}})}(jQuery),function(t){t.widget("ui.selectable",t.ui.mouse,{version:"1.10.4",options:{appendTo:"body",autoRefresh:!0,distance:0,filter:"*",tolerance:"touch",selected:null,selecting:null,start:null,stop:null,unselected:null,unselecting:null},_create:function(){var e,i=this;this.element.addClass("ui-selectable"),this.dragged=!1,this.refresh=function(){e=t(i.options.filter,i.element[0]),e.addClass("ui-selectee"),e.each(function(){var e=t(this),i=e.offset();t.data(this,"selectable-item",{element:this,$element:e,left:i.left,top:i.top,right:i.left+e.outerWidth(),bottom:i.top+e.outerHeight(),startselected:!1,selected:e.hasClass("ui-selected"),selecting:e.hasClass("ui-selecting"),unselecting:e.hasClass("ui-unselecting")})})},this.refresh(),this.selectees=e.addClass("ui-selectee"),this._mouseInit(),this.helper=t("<div class='ui-selectable-helper'></div>")},_destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item"),this.element.removeClass("ui-selectable ui-selectable-disabled"),this._mouseDestroy()},_mouseStart:function(e){var i=this,s=this.options;this.opos=[e.pageX,e.pageY],this.options.disabled||(this.selectees=t(s.filter,this.element[0]),this._trigger("start",e),t(s.appendTo).append(this.helper),this.helper.css({left:e.pageX,top:e.pageY,width:0,height:0}),s.autoRefresh&&this.refresh(),this.selectees.filter(".ui-selected").each(function(){var s=t.data(this,"selectable-item");s.startselected=!0,e.metaKey||e.ctrlKey||(s.$element.removeClass("ui-selected"),s.selected=!1,s.$element.addClass("ui-unselecting"),s.unselecting=!0,i._trigger("unselecting",e,{unselecting:s.element}))}),t(e.target).parents().addBack().each(function(){var s,n=t.data(this,"selectable-item");return n?(s=!e.metaKey&&!e.ctrlKey||!n.$element.hasClass("ui-selected"),n.$element.removeClass(s?"ui-unselecting":"ui-selected").addClass(s?"ui-selecting":"ui-unselecting"),n.unselecting=!s,n.selecting=s,n.selected=s,s?i._trigger("selecting",e,{selecting:n.element}):i._trigger("unselecting",e,{unselecting:n.element}),!1):undefined}))},_mouseDrag:function(e){if(this.dragged=!0,!this.options.disabled){var i,s=this,n=this.options,o=this.opos[0],a=this.opos[1],r=e.pageX,h=e.pageY;return o>r&&(i=r,r=o,o=i),a>h&&(i=h,h=a,a=i),this.helper.css({left:o,top:a,width:r-o,height:h-a}),this.selectees.each(function(){var i=t.data(this,"selectable-item"),l=!1;i&&i.element!==s.element[0]&&("touch"===n.tolerance?l=!(i.left>r||o>i.right||i.top>h||a>i.bottom):"fit"===n.tolerance&&(l=i.left>o&&r>i.right&&i.top>a&&h>i.bottom),l?(i.selected&&(i.$element.removeClass("ui-selected"),i.selected=!1),i.unselecting&&(i.$element.removeClass("ui-unselecting"),i.unselecting=!1),i.selecting||(i.$element.addClass("ui-selecting"),i.selecting=!0,s._trigger("selecting",e,{selecting:i.element}))):(i.selecting&&((e.metaKey||e.ctrlKey)&&i.startselected?(i.$element.removeClass("ui-selecting"),i.selecting=!1,i.$element.addClass("ui-selected"),i.selected=!0):(i.$element.removeClass("ui-selecting"),i.selecting=!1,i.startselected&&(i.$element.addClass("ui-unselecting"),i.unselecting=!0),s._trigger("unselecting",e,{unselecting:i.element}))),i.selected&&(e.metaKey||e.ctrlKey||i.startselected||(i.$element.removeClass("ui-selected"),i.selected=!1,i.$element.addClass("ui-unselecting"),i.unselecting=!0,s._trigger("unselecting",e,{unselecting:i.element})))))}),!1}},_mouseStop:function(e){var i=this;return this.dragged=!1,t(".ui-unselecting",this.element[0]).each(function(){var s=t.data(this,"selectable-item");s.$element.removeClass("ui-unselecting"),s.unselecting=!1,s.startselected=!1,i._trigger("unselected",e,{unselected:s.element})}),t(".ui-selecting",this.element[0]).each(function(){var s=t.data(this,"selectable-item");s.$element.removeClass("ui-selecting").addClass("ui-selected"),s.selecting=!1,s.selected=!0,s.startselected=!0,i._trigger("selected",e,{selected:s.element})}),this._trigger("stop",e),this.helper.remove(),!1}})}(jQuery),function(t){function e(t,e,i){return t>e&&e+i>t}function i(t){return/left|right/.test(t.css("float"))||/inline|table-cell/.test(t.css("display"))}t.widget("ui.sortable",t.ui.mouse,{version:"1.10.4",widgetEventPrefix:"sort",ready:!1,options:{appendTo:"parent",axis:!1,connectWith:!1,containment:!1,cursor:"auto",cursorAt:!1,dropOnEmpty:!0,forcePlaceholderSize:!1,forceHelperSize:!1,grid:!1,handle:!1,helper:"original",items:"> *",opacity:!1,placeholder:!1,revert:!1,scroll:!0,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1e3,activate:null,beforeStop:null,change:null,deactivate:null,out:null,over:null,receive:null,remove:null,sort:null,start:null,stop:null,update:null},_create:function(){var t=this.options;this.containerCache={},this.element.addClass("ui-sortable"),this.refresh(),this.floating=this.items.length?"x"===t.axis||i(this.items[0].item):!1,this.offset=this.element.offset(),this._mouseInit(),this.ready=!0},_destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled"),this._mouseDestroy();for(var t=this.items.length-1;t>=0;t--)this.items[t].item.removeData(this.widgetName+"-item");return this},_setOption:function(e,i){"disabled"===e?(this.options[e]=i,this.widget().toggleClass("ui-sortable-disabled",!!i)):t.Widget.prototype._setOption.apply(this,arguments)},_mouseCapture:function(e,i){var s=null,n=!1,o=this;return this.reverting?!1:this.options.disabled||"static"===this.options.type?!1:(this._refreshItems(e),t(e.target).parents().each(function(){return t.data(this,o.widgetName+"-item")===o?(s=t(this),!1):undefined}),t.data(e.target,o.widgetName+"-item")===o&&(s=t(e.target)),s?!this.options.handle||i||(t(this.options.handle,s).find("*").addBack().each(function(){this===e.target&&(n=!0)}),n)?(this.currentItem=s,this._removeCurrentsFromItems(),!0):!1:!1)},_mouseStart:function(e,i,s){var n,o,a=this.options;if(this.currentContainer=this,this.refreshPositions(),this.helper=this._createHelper(e),this._cacheHelperProportions(),this._cacheMargins(),this.scrollParent=this.helper.scrollParent(),this.offset=this.currentItem.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},t.extend(this.offset,{click:{left:e.pageX-this.offset.left,top:e.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.helper.css("position","absolute"),this.cssPosition=this.helper.css("position"),this.originalPosition=this._generatePosition(e),this.originalPageX=e.pageX,this.originalPageY=e.pageY,a.cursorAt&&this._adjustOffsetFromHelper(a.cursorAt),this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]},this.helper[0]!==this.currentItem[0]&&this.currentItem.hide(),this._createPlaceholder(),a.containment&&this._setContainment(),a.cursor&&"auto"!==a.cursor&&(o=this.document.find("body"),this.storedCursor=o.css("cursor"),o.css("cursor",a.cursor),this.storedStylesheet=t("<style>*{ cursor: "+a.cursor+" !important; }</style>").appendTo(o)),a.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),this.helper.css("opacity",a.opacity)),a.zIndex&&(this.helper.css("zIndex")&&(this._storedZIndex=this.helper.css("zIndex")),this.helper.css("zIndex",a.zIndex)),this.scrollParent[0]!==document&&"HTML"!==this.scrollParent[0].tagName&&(this.overflowOffset=this.scrollParent.offset()),this._trigger("start",e,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions(),!s)for(n=this.containers.length-1;n>=0;n--)this.containers[n]._trigger("activate",e,this._uiHash(this));return t.ui.ddmanager&&(t.ui.ddmanager.current=this),t.ui.ddmanager&&!a.dropBehaviour&&t.ui.ddmanager.prepareOffsets(this,e),this.dragging=!0,this.helper.addClass("ui-sortable-helper"),this._mouseDrag(e),!0},_mouseDrag:function(e){var i,s,n,o,a=this.options,r=!1;for(this.position=this._generatePosition(e),this.positionAbs=this._convertPositionTo("absolute"),this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs),this.options.scroll&&(this.scrollParent[0]!==document&&"HTML"!==this.scrollParent[0].tagName?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-e.pageY<a.scrollSensitivity?this.scrollParent[0].scrollTop=r=this.scrollParent[0].scrollTop+a.scrollSpeed:e.pageY-this.overflowOffset.top<a.scrollSensitivity&&(this.scrollParent[0].scrollTop=r=this.scrollParent[0].scrollTop-a.scrollSpeed),this.overflowOffset.left+this.scrollParent[0].offsetWidth-e.pageX<a.scrollSensitivity?this.scrollParent[0].scrollLeft=r=this.scrollParent[0].scrollLeft+a.scrollSpeed:e.pageX-this.overflowOffset.left<a.scrollSensitivity&&(this.scrollParent[0].scrollLeft=r=this.scrollParent[0].scrollLeft-a.scrollSpeed)):(e.pageY-t(document).scrollTop()<a.scrollSensitivity?r=t(document).scrollTop(t(document).scrollTop()-a.scrollSpeed):t(window).height()-(e.pageY-t(document).scrollTop())<a.scrollSensitivity&&(r=t(document).scrollTop(t(document).scrollTop()+a.scrollSpeed)),e.pageX-t(document).scrollLeft()<a.scrollSensitivity?r=t(document).scrollLeft(t(document).scrollLeft()-a.scrollSpeed):t(window).width()-(e.pageX-t(document).scrollLeft())<a.scrollSensitivity&&(r=t(document).scrollLeft(t(document).scrollLeft()+a.scrollSpeed))),r!==!1&&t.ui.ddmanager&&!a.dropBehaviour&&t.ui.ddmanager.prepareOffsets(this,e)),this.positionAbs=this._convertPositionTo("absolute"),this.options.axis&&"y"===this.options.axis||(this.helper[0].style.left=this.position.left+"px"),this.options.axis&&"x"===this.options.axis||(this.helper[0].style.top=this.position.top+"px"),i=this.items.length-1;i>=0;i--)if(s=this.items[i],n=s.item[0],o=this._intersectsWithPointer(s),o&&s.instance===this.currentContainer&&n!==this.currentItem[0]&&this.placeholder[1===o?"next":"prev"]()[0]!==n&&!t.contains(this.placeholder[0],n)&&("semi-dynamic"===this.options.type?!t.contains(this.element[0],n):!0)){if(this.direction=1===o?"down":"up","pointer"!==this.options.tolerance&&!this._intersectsWithSides(s))break;
+this._rearrange(e,s),this._trigger("change",e,this._uiHash());break}return this._contactContainers(e),t.ui.ddmanager&&t.ui.ddmanager.drag(this,e),this._trigger("sort",e,this._uiHash()),this.lastPositionAbs=this.positionAbs,!1},_mouseStop:function(e,i){if(e){if(t.ui.ddmanager&&!this.options.dropBehaviour&&t.ui.ddmanager.drop(this,e),this.options.revert){var s=this,n=this.placeholder.offset(),o=this.options.axis,a={};o&&"x"!==o||(a.left=n.left-this.offset.parent.left-this.margins.left+(this.offsetParent[0]===document.body?0:this.offsetParent[0].scrollLeft)),o&&"y"!==o||(a.top=n.top-this.offset.parent.top-this.margins.top+(this.offsetParent[0]===document.body?0:this.offsetParent[0].scrollTop)),this.reverting=!0,t(this.helper).animate(a,parseInt(this.options.revert,10)||500,function(){s._clear(e)})}else this._clear(e,i);return!1}},cancel:function(){if(this.dragging){this._mouseUp({target:null}),"original"===this.options.helper?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var e=this.containers.length-1;e>=0;e--)this.containers[e]._trigger("deactivate",null,this._uiHash(this)),this.containers[e].containerCache.over&&(this.containers[e]._trigger("out",null,this._uiHash(this)),this.containers[e].containerCache.over=0)}return this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),"original"!==this.options.helper&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),t.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?t(this.domPosition.prev).after(this.currentItem):t(this.domPosition.parent).prepend(this.currentItem)),this},serialize:function(e){var i=this._getItemsAsjQuery(e&&e.connected),s=[];return e=e||{},t(i).each(function(){var i=(t(e.item||this).attr(e.attribute||"id")||"").match(e.expression||/(.+)[\-=_](.+)/);i&&s.push((e.key||i[1]+"[]")+"="+(e.key&&e.expression?i[1]:i[2]))}),!s.length&&e.key&&s.push(e.key+"="),s.join("&")},toArray:function(e){var i=this._getItemsAsjQuery(e&&e.connected),s=[];return e=e||{},i.each(function(){s.push(t(e.item||this).attr(e.attribute||"id")||"")}),s},_intersectsWith:function(t){var e=this.positionAbs.left,i=e+this.helperProportions.width,s=this.positionAbs.top,n=s+this.helperProportions.height,o=t.left,a=o+t.width,r=t.top,h=r+t.height,l=this.offset.click.top,c=this.offset.click.left,u="x"===this.options.axis||s+l>r&&h>s+l,d="y"===this.options.axis||e+c>o&&a>e+c,p=u&&d;return"pointer"===this.options.tolerance||this.options.forcePointerForContainers||"pointer"!==this.options.tolerance&&this.helperProportions[this.floating?"width":"height"]>t[this.floating?"width":"height"]?p:e+this.helperProportions.width/2>o&&a>i-this.helperProportions.width/2&&s+this.helperProportions.height/2>r&&h>n-this.helperProportions.height/2},_intersectsWithPointer:function(t){var i="x"===this.options.axis||e(this.positionAbs.top+this.offset.click.top,t.top,t.height),s="y"===this.options.axis||e(this.positionAbs.left+this.offset.click.left,t.left,t.width),n=i&&s,o=this._getDragVerticalDirection(),a=this._getDragHorizontalDirection();return n?this.floating?a&&"right"===a||"down"===o?2:1:o&&("down"===o?2:1):!1},_intersectsWithSides:function(t){var i=e(this.positionAbs.top+this.offset.click.top,t.top+t.height/2,t.height),s=e(this.positionAbs.left+this.offset.click.left,t.left+t.width/2,t.width),n=this._getDragVerticalDirection(),o=this._getDragHorizontalDirection();return this.floating&&o?"right"===o&&s||"left"===o&&!s:n&&("down"===n&&i||"up"===n&&!i)},_getDragVerticalDirection:function(){var t=this.positionAbs.top-this.lastPositionAbs.top;return 0!==t&&(t>0?"down":"up")},_getDragHorizontalDirection:function(){var t=this.positionAbs.left-this.lastPositionAbs.left;return 0!==t&&(t>0?"right":"left")},refresh:function(t){return this._refreshItems(t),this.refreshPositions(),this},_connectWith:function(){var t=this.options;return t.connectWith.constructor===String?[t.connectWith]:t.connectWith},_getItemsAsjQuery:function(e){function i(){r.push(this)}var s,n,o,a,r=[],h=[],l=this._connectWith();if(l&&e)for(s=l.length-1;s>=0;s--)for(o=t(l[s]),n=o.length-1;n>=0;n--)a=t.data(o[n],this.widgetFullName),a&&a!==this&&!a.options.disabled&&h.push([t.isFunction(a.options.items)?a.options.items.call(a.element):t(a.options.items,a.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),a]);for(h.push([t.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):t(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]),s=h.length-1;s>=0;s--)h[s][0].each(i);return t(r)},_removeCurrentsFromItems:function(){var e=this.currentItem.find(":data("+this.widgetName+"-item)");this.items=t.grep(this.items,function(t){for(var i=0;e.length>i;i++)if(e[i]===t.item[0])return!1;return!0})},_refreshItems:function(e){this.items=[],this.containers=[this];var i,s,n,o,a,r,h,l,c=this.items,u=[[t.isFunction(this.options.items)?this.options.items.call(this.element[0],e,{item:this.currentItem}):t(this.options.items,this.element),this]],d=this._connectWith();if(d&&this.ready)for(i=d.length-1;i>=0;i--)for(n=t(d[i]),s=n.length-1;s>=0;s--)o=t.data(n[s],this.widgetFullName),o&&o!==this&&!o.options.disabled&&(u.push([t.isFunction(o.options.items)?o.options.items.call(o.element[0],e,{item:this.currentItem}):t(o.options.items,o.element),o]),this.containers.push(o));for(i=u.length-1;i>=0;i--)for(a=u[i][1],r=u[i][0],s=0,l=r.length;l>s;s++)h=t(r[s]),h.data(this.widgetName+"-item",a),c.push({item:h,instance:a,width:0,height:0,left:0,top:0})},refreshPositions:function(e){this.offsetParent&&this.helper&&(this.offset.parent=this._getParentOffset());var i,s,n,o;for(i=this.items.length-1;i>=0;i--)s=this.items[i],s.instance!==this.currentContainer&&this.currentContainer&&s.item[0]!==this.currentItem[0]||(n=this.options.toleranceElement?t(this.options.toleranceElement,s.item):s.item,e||(s.width=n.outerWidth(),s.height=n.outerHeight()),o=n.offset(),s.left=o.left,s.top=o.top);if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(i=this.containers.length-1;i>=0;i--)o=this.containers[i].element.offset(),this.containers[i].containerCache.left=o.left,this.containers[i].containerCache.top=o.top,this.containers[i].containerCache.width=this.containers[i].element.outerWidth(),this.containers[i].containerCache.height=this.containers[i].element.outerHeight();return this},_createPlaceholder:function(e){e=e||this;var i,s=e.options;s.placeholder&&s.placeholder.constructor!==String||(i=s.placeholder,s.placeholder={element:function(){var s=e.currentItem[0].nodeName.toLowerCase(),n=t("<"+s+">",e.document[0]).addClass(i||e.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper");return"tr"===s?e.currentItem.children().each(function(){t("<td>&#160;</td>",e.document[0]).attr("colspan",t(this).attr("colspan")||1).appendTo(n)}):"img"===s&&n.attr("src",e.currentItem.attr("src")),i||n.css("visibility","hidden"),n},update:function(t,n){(!i||s.forcePlaceholderSize)&&(n.height()||n.height(e.currentItem.innerHeight()-parseInt(e.currentItem.css("paddingTop")||0,10)-parseInt(e.currentItem.css("paddingBottom")||0,10)),n.width()||n.width(e.currentItem.innerWidth()-parseInt(e.currentItem.css("paddingLeft")||0,10)-parseInt(e.currentItem.css("paddingRight")||0,10)))}}),e.placeholder=t(s.placeholder.element.call(e.element,e.currentItem)),e.currentItem.after(e.placeholder),s.placeholder.update(e,e.placeholder)},_contactContainers:function(s){var n,o,a,r,h,l,c,u,d,p,f=null,g=null;for(n=this.containers.length-1;n>=0;n--)if(!t.contains(this.currentItem[0],this.containers[n].element[0]))if(this._intersectsWith(this.containers[n].containerCache)){if(f&&t.contains(this.containers[n].element[0],f.element[0]))continue;f=this.containers[n],g=n}else this.containers[n].containerCache.over&&(this.containers[n]._trigger("out",s,this._uiHash(this)),this.containers[n].containerCache.over=0);if(f)if(1===this.containers.length)this.containers[g].containerCache.over||(this.containers[g]._trigger("over",s,this._uiHash(this)),this.containers[g].containerCache.over=1);else{for(a=1e4,r=null,p=f.floating||i(this.currentItem),h=p?"left":"top",l=p?"width":"height",c=this.positionAbs[h]+this.offset.click[h],o=this.items.length-1;o>=0;o--)t.contains(this.containers[g].element[0],this.items[o].item[0])&&this.items[o].item[0]!==this.currentItem[0]&&(!p||e(this.positionAbs.top+this.offset.click.top,this.items[o].top,this.items[o].height))&&(u=this.items[o].item.offset()[h],d=!1,Math.abs(u-c)>Math.abs(u+this.items[o][l]-c)&&(d=!0,u+=this.items[o][l]),a>Math.abs(u-c)&&(a=Math.abs(u-c),r=this.items[o],this.direction=d?"up":"down"));if(!r&&!this.options.dropOnEmpty)return;if(this.currentContainer===this.containers[g])return;r?this._rearrange(s,r,null,!0):this._rearrange(s,null,this.containers[g].element,!0),this._trigger("change",s,this._uiHash()),this.containers[g]._trigger("change",s,this._uiHash(this)),this.currentContainer=this.containers[g],this.options.placeholder.update(this.currentContainer,this.placeholder),this.containers[g]._trigger("over",s,this._uiHash(this)),this.containers[g].containerCache.over=1}},_createHelper:function(e){var i=this.options,s=t.isFunction(i.helper)?t(i.helper.apply(this.element[0],[e,this.currentItem])):"clone"===i.helper?this.currentItem.clone():this.currentItem;return s.parents("body").length||t("parent"!==i.appendTo?i.appendTo:this.currentItem[0].parentNode)[0].appendChild(s[0]),s[0]===this.currentItem[0]&&(this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")}),(!s[0].style.width||i.forceHelperSize)&&s.width(this.currentItem.width()),(!s[0].style.height||i.forceHelperSize)&&s.height(this.currentItem.height()),s},_adjustOffsetFromHelper:function(e){"string"==typeof e&&(e=e.split(" ")),t.isArray(e)&&(e={left:+e[0],top:+e[1]||0}),"left"in e&&(this.offset.click.left=e.left+this.margins.left),"right"in e&&(this.offset.click.left=this.helperProportions.width-e.right+this.margins.left),"top"in e&&(this.offset.click.top=e.top+this.margins.top),"bottom"in e&&(this.offset.click.top=this.helperProportions.height-e.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var e=this.offsetParent.offset();return"absolute"===this.cssPosition&&this.scrollParent[0]!==document&&t.contains(this.scrollParent[0],this.offsetParent[0])&&(e.left+=this.scrollParent.scrollLeft(),e.top+=this.scrollParent.scrollTop()),(this.offsetParent[0]===document.body||this.offsetParent[0].tagName&&"html"===this.offsetParent[0].tagName.toLowerCase()&&t.ui.ie)&&(e={top:0,left:0}),{top:e.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:e.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"===this.cssPosition){var t=this.currentItem.position();return{top:t.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:t.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var e,i,s,n=this.options;"parent"===n.containment&&(n.containment=this.helper[0].parentNode),("document"===n.containment||"window"===n.containment)&&(this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,t("document"===n.containment?document:window).width()-this.helperProportions.width-this.margins.left,(t("document"===n.containment?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top]),/^(document|window|parent)$/.test(n.containment)||(e=t(n.containment)[0],i=t(n.containment).offset(),s="hidden"!==t(e).css("overflow"),this.containment=[i.left+(parseInt(t(e).css("borderLeftWidth"),10)||0)+(parseInt(t(e).css("paddingLeft"),10)||0)-this.margins.left,i.top+(parseInt(t(e).css("borderTopWidth"),10)||0)+(parseInt(t(e).css("paddingTop"),10)||0)-this.margins.top,i.left+(s?Math.max(e.scrollWidth,e.offsetWidth):e.offsetWidth)-(parseInt(t(e).css("borderLeftWidth"),10)||0)-(parseInt(t(e).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,i.top+(s?Math.max(e.scrollHeight,e.offsetHeight):e.offsetHeight)-(parseInt(t(e).css("borderTopWidth"),10)||0)-(parseInt(t(e).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top])},_convertPositionTo:function(e,i){i||(i=this.position);var s="absolute"===e?1:-1,n="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,o=/(html|body)/i.test(n[0].tagName);return{top:i.top+this.offset.relative.top*s+this.offset.parent.top*s-("fixed"===this.cssPosition?-this.scrollParent.scrollTop():o?0:n.scrollTop())*s,left:i.left+this.offset.relative.left*s+this.offset.parent.left*s-("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():o?0:n.scrollLeft())*s}},_generatePosition:function(e){var i,s,n=this.options,o=e.pageX,a=e.pageY,r="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,h=/(html|body)/i.test(r[0].tagName);return"relative"!==this.cssPosition||this.scrollParent[0]!==document&&this.scrollParent[0]!==this.offsetParent[0]||(this.offset.relative=this._getRelativeOffset()),this.originalPosition&&(this.containment&&(e.pageX-this.offset.click.left<this.containment[0]&&(o=this.containment[0]+this.offset.click.left),e.pageY-this.offset.click.top<this.containment[1]&&(a=this.containment[1]+this.offset.click.top),e.pageX-this.offset.click.left>this.containment[2]&&(o=this.containment[2]+this.offset.click.left),e.pageY-this.offset.click.top>this.containment[3]&&(a=this.containment[3]+this.offset.click.top)),n.grid&&(i=this.originalPageY+Math.round((a-this.originalPageY)/n.grid[1])*n.grid[1],a=this.containment?i-this.offset.click.top>=this.containment[1]&&i-this.offset.click.top<=this.containment[3]?i:i-this.offset.click.top>=this.containment[1]?i-n.grid[1]:i+n.grid[1]:i,s=this.originalPageX+Math.round((o-this.originalPageX)/n.grid[0])*n.grid[0],o=this.containment?s-this.offset.click.left>=this.containment[0]&&s-this.offset.click.left<=this.containment[2]?s:s-this.offset.click.left>=this.containment[0]?s-n.grid[0]:s+n.grid[0]:s)),{top:a-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.scrollParent.scrollTop():h?0:r.scrollTop()),left:o-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():h?0:r.scrollLeft())}},_rearrange:function(t,e,i,s){i?i[0].appendChild(this.placeholder[0]):e.item[0].parentNode.insertBefore(this.placeholder[0],"down"===this.direction?e.item[0]:e.item[0].nextSibling),this.counter=this.counter?++this.counter:1;var n=this.counter;this._delay(function(){n===this.counter&&this.refreshPositions(!s)})},_clear:function(t,e){function i(t,e,i){return function(s){i._trigger(t,s,e._uiHash(e))}}this.reverting=!1;var s,n=[];if(!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem),this._noFinalSort=null,this.helper[0]===this.currentItem[0]){for(s in this._storedCSS)("auto"===this._storedCSS[s]||"static"===this._storedCSS[s])&&(this._storedCSS[s]="");this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else this.currentItem.show();for(this.fromOutside&&!e&&n.push(function(t){this._trigger("receive",t,this._uiHash(this.fromOutside))}),!this.fromOutside&&this.domPosition.prev===this.currentItem.prev().not(".ui-sortable-helper")[0]&&this.domPosition.parent===this.currentItem.parent()[0]||e||n.push(function(t){this._trigger("update",t,this._uiHash())}),this!==this.currentContainer&&(e||(n.push(function(t){this._trigger("remove",t,this._uiHash())}),n.push(function(t){return function(e){t._trigger("receive",e,this._uiHash(this))}}.call(this,this.currentContainer)),n.push(function(t){return function(e){t._trigger("update",e,this._uiHash(this))}}.call(this,this.currentContainer)))),s=this.containers.length-1;s>=0;s--)e||n.push(i("deactivate",this,this.containers[s])),this.containers[s].containerCache.over&&(n.push(i("out",this,this.containers[s])),this.containers[s].containerCache.over=0);if(this.storedCursor&&(this.document.find("body").css("cursor",this.storedCursor),this.storedStylesheet.remove()),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex","auto"===this._storedZIndex?"":this._storedZIndex),this.dragging=!1,this.cancelHelperRemoval){if(!e){for(this._trigger("beforeStop",t,this._uiHash()),s=0;n.length>s;s++)n[s].call(this,t);this._trigger("stop",t,this._uiHash())}return this.fromOutside=!1,!1}if(e||this._trigger("beforeStop",t,this._uiHash()),this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.helper[0]!==this.currentItem[0]&&this.helper.remove(),this.helper=null,!e){for(s=0;n.length>s;s++)n[s].call(this,t);this._trigger("stop",t,this._uiHash())}return this.fromOutside=!1,!0},_trigger:function(){t.Widget.prototype._trigger.apply(this,arguments)===!1&&this.cancel()},_uiHash:function(e){var i=e||this;return{helper:i.helper,placeholder:i.placeholder||t([]),position:i.position,originalPosition:i.originalPosition,offset:i.positionAbs,item:i.currentItem,sender:e?e.element:null}}})}(jQuery),function(t,e){var i="ui-effects-";t.effects={effect:{}},function(t,e){function i(t,e,i){var s=u[e.type]||{};return null==t?i||!e.def?null:e.def:(t=s.floor?~~t:parseFloat(t),isNaN(t)?e.def:s.mod?(t+s.mod)%s.mod:0>t?0:t>s.max?s.max:t)}function s(i){var s=l(),n=s._rgba=[];return i=i.toLowerCase(),f(h,function(t,o){var a,r=o.re.exec(i),h=r&&o.parse(r),l=o.space||"rgba";return h?(a=s[l](h),s[c[l].cache]=a[c[l].cache],n=s._rgba=a._rgba,!1):e}),n.length?("0,0,0,0"===n.join()&&t.extend(n,o.transparent),s):o[i]}function n(t,e,i){return i=(i+1)%1,1>6*i?t+6*(e-t)*i:1>2*i?e:2>3*i?t+6*(e-t)*(2/3-i):t}var o,a="backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",r=/^([\-+])=\s*(\d+\.?\d*)/,h=[{re:/rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,parse:function(t){return[t[1],t[2],t[3],t[4]]}},{re:/rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,parse:function(t){return[2.55*t[1],2.55*t[2],2.55*t[3],t[4]]}},{re:/#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,parse:function(t){return[parseInt(t[1],16),parseInt(t[2],16),parseInt(t[3],16)]}},{re:/#([a-f0-9])([a-f0-9])([a-f0-9])/,parse:function(t){return[parseInt(t[1]+t[1],16),parseInt(t[2]+t[2],16),parseInt(t[3]+t[3],16)]}},{re:/hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,space:"hsla",parse:function(t){return[t[1],t[2]/100,t[3]/100,t[4]]}}],l=t.Color=function(e,i,s,n){return new t.Color.fn.parse(e,i,s,n)},c={rgba:{props:{red:{idx:0,type:"byte"},green:{idx:1,type:"byte"},blue:{idx:2,type:"byte"}}},hsla:{props:{hue:{idx:0,type:"degrees"},saturation:{idx:1,type:"percent"},lightness:{idx:2,type:"percent"}}}},u={"byte":{floor:!0,max:255},percent:{max:1},degrees:{mod:360,floor:!0}},d=l.support={},p=t("<p>")[0],f=t.each;p.style.cssText="background-color:rgba(1,1,1,.5)",d.rgba=p.style.backgroundColor.indexOf("rgba")>-1,f(c,function(t,e){e.cache="_"+t,e.props.alpha={idx:3,type:"percent",def:1}}),l.fn=t.extend(l.prototype,{parse:function(n,a,r,h){if(n===e)return this._rgba=[null,null,null,null],this;(n.jquery||n.nodeType)&&(n=t(n).css(a),a=e);var u=this,d=t.type(n),p=this._rgba=[];return a!==e&&(n=[n,a,r,h],d="array"),"string"===d?this.parse(s(n)||o._default):"array"===d?(f(c.rgba.props,function(t,e){p[e.idx]=i(n[e.idx],e)}),this):"object"===d?(n instanceof l?f(c,function(t,e){n[e.cache]&&(u[e.cache]=n[e.cache].slice())}):f(c,function(e,s){var o=s.cache;f(s.props,function(t,e){if(!u[o]&&s.to){if("alpha"===t||null==n[t])return;u[o]=s.to(u._rgba)}u[o][e.idx]=i(n[t],e,!0)}),u[o]&&0>t.inArray(null,u[o].slice(0,3))&&(u[o][3]=1,s.from&&(u._rgba=s.from(u[o])))}),this):e},is:function(t){var i=l(t),s=!0,n=this;return f(c,function(t,o){var a,r=i[o.cache];return r&&(a=n[o.cache]||o.to&&o.to(n._rgba)||[],f(o.props,function(t,i){return null!=r[i.idx]?s=r[i.idx]===a[i.idx]:e})),s}),s},_space:function(){var t=[],e=this;return f(c,function(i,s){e[s.cache]&&t.push(i)}),t.pop()},transition:function(t,e){var s=l(t),n=s._space(),o=c[n],a=0===this.alpha()?l("transparent"):this,r=a[o.cache]||o.to(a._rgba),h=r.slice();return s=s[o.cache],f(o.props,function(t,n){var o=n.idx,a=r[o],l=s[o],c=u[n.type]||{};null!==l&&(null===a?h[o]=l:(c.mod&&(l-a>c.mod/2?a+=c.mod:a-l>c.mod/2&&(a-=c.mod)),h[o]=i((l-a)*e+a,n)))}),this[n](h)},blend:function(e){if(1===this._rgba[3])return this;var i=this._rgba.slice(),s=i.pop(),n=l(e)._rgba;return l(t.map(i,function(t,e){return(1-s)*n[e]+s*t}))},toRgbaString:function(){var e="rgba(",i=t.map(this._rgba,function(t,e){return null==t?e>2?1:0:t});return 1===i[3]&&(i.pop(),e="rgb("),e+i.join()+")"},toHslaString:function(){var e="hsla(",i=t.map(this.hsla(),function(t,e){return null==t&&(t=e>2?1:0),e&&3>e&&(t=Math.round(100*t)+"%"),t});return 1===i[3]&&(i.pop(),e="hsl("),e+i.join()+")"},toHexString:function(e){var i=this._rgba.slice(),s=i.pop();return e&&i.push(~~(255*s)),"#"+t.map(i,function(t){return t=(t||0).toString(16),1===t.length?"0"+t:t}).join("")},toString:function(){return 0===this._rgba[3]?"transparent":this.toRgbaString()}}),l.fn.parse.prototype=l.fn,c.hsla.to=function(t){if(null==t[0]||null==t[1]||null==t[2])return[null,null,null,t[3]];var e,i,s=t[0]/255,n=t[1]/255,o=t[2]/255,a=t[3],r=Math.max(s,n,o),h=Math.min(s,n,o),l=r-h,c=r+h,u=.5*c;return e=h===r?0:s===r?60*(n-o)/l+360:n===r?60*(o-s)/l+120:60*(s-n)/l+240,i=0===l?0:.5>=u?l/c:l/(2-c),[Math.round(e)%360,i,u,null==a?1:a]},c.hsla.from=function(t){if(null==t[0]||null==t[1]||null==t[2])return[null,null,null,t[3]];var e=t[0]/360,i=t[1],s=t[2],o=t[3],a=.5>=s?s*(1+i):s+i-s*i,r=2*s-a;return[Math.round(255*n(r,a,e+1/3)),Math.round(255*n(r,a,e)),Math.round(255*n(r,a,e-1/3)),o]},f(c,function(s,n){var o=n.props,a=n.cache,h=n.to,c=n.from;l.fn[s]=function(s){if(h&&!this[a]&&(this[a]=h(this._rgba)),s===e)return this[a].slice();var n,r=t.type(s),u="array"===r||"object"===r?s:arguments,d=this[a].slice();return f(o,function(t,e){var s=u["object"===r?t:e.idx];null==s&&(s=d[e.idx]),d[e.idx]=i(s,e)}),c?(n=l(c(d)),n[a]=d,n):l(d)},f(o,function(e,i){l.fn[e]||(l.fn[e]=function(n){var o,a=t.type(n),h="alpha"===e?this._hsla?"hsla":"rgba":s,l=this[h](),c=l[i.idx];return"undefined"===a?c:("function"===a&&(n=n.call(this,c),a=t.type(n)),null==n&&i.empty?this:("string"===a&&(o=r.exec(n),o&&(n=c+parseFloat(o[2])*("+"===o[1]?1:-1))),l[i.idx]=n,this[h](l)))})})}),l.hook=function(e){var i=e.split(" ");f(i,function(e,i){t.cssHooks[i]={set:function(e,n){var o,a,r="";if("transparent"!==n&&("string"!==t.type(n)||(o=s(n)))){if(n=l(o||n),!d.rgba&&1!==n._rgba[3]){for(a="backgroundColor"===i?e.parentNode:e;(""===r||"transparent"===r)&&a&&a.style;)try{r=t.css(a,"backgroundColor"),a=a.parentNode}catch(h){}n=n.blend(r&&"transparent"!==r?r:"_default")}n=n.toRgbaString()}try{e.style[i]=n}catch(h){}}},t.fx.step[i]=function(e){e.colorInit||(e.start=l(e.elem,i),e.end=l(e.end),e.colorInit=!0),t.cssHooks[i].set(e.elem,e.start.transition(e.end,e.pos))}})},l.hook(a),t.cssHooks.borderColor={expand:function(t){var e={};return f(["Top","Right","Bottom","Left"],function(i,s){e["border"+s+"Color"]=t}),e}},o=t.Color.names={aqua:"#00ffff",black:"#000000",blue:"#0000ff",fuchsia:"#ff00ff",gray:"#808080",green:"#008000",lime:"#00ff00",maroon:"#800000",navy:"#000080",olive:"#808000",purple:"#800080",red:"#ff0000",silver:"#c0c0c0",teal:"#008080",white:"#ffffff",yellow:"#ffff00",transparent:[null,null,null,0],_default:"#ffffff"}}(jQuery),function(){function i(e){var i,s,n=e.ownerDocument.defaultView?e.ownerDocument.defaultView.getComputedStyle(e,null):e.currentStyle,o={};if(n&&n.length&&n[0]&&n[n[0]])for(s=n.length;s--;)i=n[s],"string"==typeof n[i]&&(o[t.camelCase(i)]=n[i]);else for(i in n)"string"==typeof n[i]&&(o[i]=n[i]);return o}function s(e,i){var s,n,a={};for(s in i)n=i[s],e[s]!==n&&(o[s]||(t.fx.step[s]||!isNaN(parseFloat(n)))&&(a[s]=n));return a}var n=["add","remove","toggle"],o={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};t.each(["borderLeftStyle","borderRightStyle","borderBottomStyle","borderTopStyle"],function(e,i){t.fx.step[i]=function(t){("none"!==t.end&&!t.setAttr||1===t.pos&&!t.setAttr)&&(jQuery.style(t.elem,i,t.end),t.setAttr=!0)}}),t.fn.addBack||(t.fn.addBack=function(t){return this.add(null==t?this.prevObject:this.prevObject.filter(t))}),t.effects.animateClass=function(e,o,a,r){var h=t.speed(o,a,r);return this.queue(function(){var o,a=t(this),r=a.attr("class")||"",l=h.children?a.find("*").addBack():a;l=l.map(function(){var e=t(this);return{el:e,start:i(this)}}),o=function(){t.each(n,function(t,i){e[i]&&a[i+"Class"](e[i])})},o(),l=l.map(function(){return this.end=i(this.el[0]),this.diff=s(this.start,this.end),this}),a.attr("class",r),l=l.map(function(){var e=this,i=t.Deferred(),s=t.extend({},h,{queue:!1,complete:function(){i.resolve(e)}});return this.el.animate(this.diff,s),i.promise()}),t.when.apply(t,l.get()).done(function(){o(),t.each(arguments,function(){var e=this.el;t.each(this.diff,function(t){e.css(t,"")})}),h.complete.call(a[0])})})},t.fn.extend({addClass:function(e){return function(i,s,n,o){return s?t.effects.animateClass.call(this,{add:i},s,n,o):e.apply(this,arguments)}}(t.fn.addClass),removeClass:function(e){return function(i,s,n,o){return arguments.length>1?t.effects.animateClass.call(this,{remove:i},s,n,o):e.apply(this,arguments)}}(t.fn.removeClass),toggleClass:function(i){return function(s,n,o,a,r){return"boolean"==typeof n||n===e?o?t.effects.animateClass.call(this,n?{add:s}:{remove:s},o,a,r):i.apply(this,arguments):t.effects.animateClass.call(this,{toggle:s},n,o,a)}}(t.fn.toggleClass),switchClass:function(e,i,s,n,o){return t.effects.animateClass.call(this,{add:i,remove:e},s,n,o)}})}(),function(){function s(e,i,s,n){return t.isPlainObject(e)&&(i=e,e=e.effect),e={effect:e},null==i&&(i={}),t.isFunction(i)&&(n=i,s=null,i={}),("number"==typeof i||t.fx.speeds[i])&&(n=s,s=i,i={}),t.isFunction(s)&&(n=s,s=null),i&&t.extend(e,i),s=s||i.duration,e.duration=t.fx.off?0:"number"==typeof s?s:s in t.fx.speeds?t.fx.speeds[s]:t.fx.speeds._default,e.complete=n||i.complete,e}function n(e){return!e||"number"==typeof e||t.fx.speeds[e]?!0:"string"!=typeof e||t.effects.effect[e]?t.isFunction(e)?!0:"object"!=typeof e||e.effect?!1:!0:!0}t.extend(t.effects,{version:"1.10.4",save:function(t,e){for(var s=0;e.length>s;s++)null!==e[s]&&t.data(i+e[s],t[0].style[e[s]])},restore:function(t,s){var n,o;for(o=0;s.length>o;o++)null!==s[o]&&(n=t.data(i+s[o]),n===e&&(n=""),t.css(s[o],n))},setMode:function(t,e){return"toggle"===e&&(e=t.is(":hidden")?"show":"hide"),e},getBaseline:function(t,e){var i,s;switch(t[0]){case"top":i=0;break;case"middle":i=.5;break;case"bottom":i=1;break;default:i=t[0]/e.height}switch(t[1]){case"left":s=0;break;case"center":s=.5;break;case"right":s=1;break;default:s=t[1]/e.width}return{x:s,y:i}},createWrapper:function(e){if(e.parent().is(".ui-effects-wrapper"))return e.parent();var i={width:e.outerWidth(!0),height:e.outerHeight(!0),"float":e.css("float")},s=t("<div></div>").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),n={width:e.width(),height:e.height()},o=document.activeElement;try{o.id}catch(a){o=document.body}return e.wrap(s),(e[0]===o||t.contains(e[0],o))&&t(o).focus(),s=e.parent(),"static"===e.css("position")?(s.css({position:"relative"}),e.css({position:"relative"})):(t.extend(i,{position:e.css("position"),zIndex:e.css("z-index")}),t.each(["top","left","bottom","right"],function(t,s){i[s]=e.css(s),isNaN(parseInt(i[s],10))&&(i[s]="auto")}),e.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})),e.css(n),s.css(i).show()},removeWrapper:function(e){var i=document.activeElement;return e.parent().is(".ui-effects-wrapper")&&(e.parent().replaceWith(e),(e[0]===i||t.contains(e[0],i))&&t(i).focus()),e},setTransition:function(e,i,s,n){return n=n||{},t.each(i,function(t,i){var o=e.cssUnit(i);o[0]>0&&(n[i]=o[0]*s+o[1])}),n}}),t.fn.extend({effect:function(){function e(e){function s(){t.isFunction(o)&&o.call(n[0]),t.isFunction(e)&&e()}var n=t(this),o=i.complete,r=i.mode;(n.is(":hidden")?"hide"===r:"show"===r)?(n[r](),s()):a.call(n[0],i,s)}var i=s.apply(this,arguments),n=i.mode,o=i.queue,a=t.effects.effect[i.effect];return t.fx.off||!a?n?this[n](i.duration,i.complete):this.each(function(){i.complete&&i.complete.call(this)}):o===!1?this.each(e):this.queue(o||"fx",e)},show:function(t){return function(e){if(n(e))return t.apply(this,arguments);var i=s.apply(this,arguments);return i.mode="show",this.effect.call(this,i)}}(t.fn.show),hide:function(t){return function(e){if(n(e))return t.apply(this,arguments);var i=s.apply(this,arguments);return i.mode="hide",this.effect.call(this,i)}}(t.fn.hide),toggle:function(t){return function(e){if(n(e)||"boolean"==typeof e)return t.apply(this,arguments);var i=s.apply(this,arguments);return i.mode="toggle",this.effect.call(this,i)}}(t.fn.toggle),cssUnit:function(e){var i=this.css(e),s=[];return t.each(["em","px","%","pt"],function(t,e){i.indexOf(e)>0&&(s=[parseFloat(i),e])}),s}})}(),function(){var e={};t.each(["Quad","Cubic","Quart","Quint","Expo"],function(t,i){e[i]=function(e){return Math.pow(e,t+2)}}),t.extend(e,{Sine:function(t){return 1-Math.cos(t*Math.PI/2)},Circ:function(t){return 1-Math.sqrt(1-t*t)},Elastic:function(t){return 0===t||1===t?t:-Math.pow(2,8*(t-1))*Math.sin((80*(t-1)-7.5)*Math.PI/15)},Back:function(t){return t*t*(3*t-2)},Bounce:function(t){for(var e,i=4;((e=Math.pow(2,--i))-1)/11>t;);return 1/Math.pow(4,3-i)-7.5625*Math.pow((3*e-2)/22-t,2)}}),t.each(e,function(e,i){t.easing["easeIn"+e]=i,t.easing["easeOut"+e]=function(t){return 1-i(1-t)},t.easing["easeInOut"+e]=function(t){return.5>t?i(2*t)/2:1-i(-2*t+2)/2}})}()}(jQuery),function(t){var e=0,i={},s={};i.height=i.paddingTop=i.paddingBottom=i.borderTopWidth=i.borderBottomWidth="hide",s.height=s.paddingTop=s.paddingBottom=s.borderTopWidth=s.borderBottomWidth="show",t.widget("ui.accordion",{version:"1.10.4",options:{active:0,animate:{},collapsible:!1,event:"click",header:"> li > :first-child,> :not(li):even",heightStyle:"auto",icons:{activeHeader:"ui-icon-triangle-1-s",header:"ui-icon-triangle-1-e"},activate:null,beforeActivate:null},_create:function(){var e=this.options;this.prevShow=this.prevHide=t(),this.element.addClass("ui-accordion ui-widget ui-helper-reset").attr("role","tablist"),e.collapsible||e.active!==!1&&null!=e.active||(e.active=0),this._processPanels(),0>e.active&&(e.active+=this.headers.length),this._refresh()},_getCreateEventData:function(){return{header:this.active,panel:this.active.length?this.active.next():t(),content:this.active.length?this.active.next():t()}},_createIcons:function(){var e=this.options.icons;e&&(t("<span>").addClass("ui-accordion-header-icon ui-icon "+e.header).prependTo(this.headers),this.active.children(".ui-accordion-header-icon").removeClass(e.header).addClass(e.activeHeader),this.headers.addClass("ui-accordion-icons"))
+},_destroyIcons:function(){this.headers.removeClass("ui-accordion-icons").children(".ui-accordion-header-icon").remove()},_destroy:function(){var t;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role"),this.headers.removeClass("ui-accordion-header ui-accordion-header-active ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top").removeAttr("role").removeAttr("aria-expanded").removeAttr("aria-selected").removeAttr("aria-controls").removeAttr("tabIndex").each(function(){/^ui-accordion/.test(this.id)&&this.removeAttribute("id")}),this._destroyIcons(),t=this.headers.next().css("display","").removeAttr("role").removeAttr("aria-hidden").removeAttr("aria-labelledby").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled").each(function(){/^ui-accordion/.test(this.id)&&this.removeAttribute("id")}),"content"!==this.options.heightStyle&&t.css("height","")},_setOption:function(t,e){return"active"===t?(this._activate(e),undefined):("event"===t&&(this.options.event&&this._off(this.headers,this.options.event),this._setupEvents(e)),this._super(t,e),"collapsible"!==t||e||this.options.active!==!1||this._activate(0),"icons"===t&&(this._destroyIcons(),e&&this._createIcons()),"disabled"===t&&this.headers.add(this.headers.next()).toggleClass("ui-state-disabled",!!e),undefined)},_keydown:function(e){if(!e.altKey&&!e.ctrlKey){var i=t.ui.keyCode,s=this.headers.length,n=this.headers.index(e.target),o=!1;switch(e.keyCode){case i.RIGHT:case i.DOWN:o=this.headers[(n+1)%s];break;case i.LEFT:case i.UP:o=this.headers[(n-1+s)%s];break;case i.SPACE:case i.ENTER:this._eventHandler(e);break;case i.HOME:o=this.headers[0];break;case i.END:o=this.headers[s-1]}o&&(t(e.target).attr("tabIndex",-1),t(o).attr("tabIndex",0),o.focus(),e.preventDefault())}},_panelKeyDown:function(e){e.keyCode===t.ui.keyCode.UP&&e.ctrlKey&&t(e.currentTarget).prev().focus()},refresh:function(){var e=this.options;this._processPanels(),e.active===!1&&e.collapsible===!0||!this.headers.length?(e.active=!1,this.active=t()):e.active===!1?this._activate(0):this.active.length&&!t.contains(this.element[0],this.active[0])?this.headers.length===this.headers.find(".ui-state-disabled").length?(e.active=!1,this.active=t()):this._activate(Math.max(0,e.active-1)):e.active=this.headers.index(this.active),this._destroyIcons(),this._refresh()},_processPanels:function(){this.headers=this.element.find(this.options.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all"),this.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom").filter(":not(.ui-accordion-content-active)").hide()},_refresh:function(){var i,s=this.options,n=s.heightStyle,o=this.element.parent(),a=this.accordionId="ui-accordion-"+(this.element.attr("id")||++e);this.active=this._findActive(s.active).addClass("ui-accordion-header-active ui-state-active ui-corner-top").removeClass("ui-corner-all"),this.active.next().addClass("ui-accordion-content-active").show(),this.headers.attr("role","tab").each(function(e){var i=t(this),s=i.attr("id"),n=i.next(),o=n.attr("id");s||(s=a+"-header-"+e,i.attr("id",s)),o||(o=a+"-panel-"+e,n.attr("id",o)),i.attr("aria-controls",o),n.attr("aria-labelledby",s)}).next().attr("role","tabpanel"),this.headers.not(this.active).attr({"aria-selected":"false","aria-expanded":"false",tabIndex:-1}).next().attr({"aria-hidden":"true"}).hide(),this.active.length?this.active.attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0}).next().attr({"aria-hidden":"false"}):this.headers.eq(0).attr("tabIndex",0),this._createIcons(),this._setupEvents(s.event),"fill"===n?(i=o.height(),this.element.siblings(":visible").each(function(){var e=t(this),s=e.css("position");"absolute"!==s&&"fixed"!==s&&(i-=e.outerHeight(!0))}),this.headers.each(function(){i-=t(this).outerHeight(!0)}),this.headers.next().each(function(){t(this).height(Math.max(0,i-t(this).innerHeight()+t(this).height()))}).css("overflow","auto")):"auto"===n&&(i=0,this.headers.next().each(function(){i=Math.max(i,t(this).css("height","").height())}).height(i))},_activate:function(e){var i=this._findActive(e)[0];i!==this.active[0]&&(i=i||this.active[0],this._eventHandler({target:i,currentTarget:i,preventDefault:t.noop}))},_findActive:function(e){return"number"==typeof e?this.headers.eq(e):t()},_setupEvents:function(e){var i={keydown:"_keydown"};e&&t.each(e.split(" "),function(t,e){i[e]="_eventHandler"}),this._off(this.headers.add(this.headers.next())),this._on(this.headers,i),this._on(this.headers.next(),{keydown:"_panelKeyDown"}),this._hoverable(this.headers),this._focusable(this.headers)},_eventHandler:function(e){var i=this.options,s=this.active,n=t(e.currentTarget),o=n[0]===s[0],a=o&&i.collapsible,r=a?t():n.next(),h=s.next(),l={oldHeader:s,oldPanel:h,newHeader:a?t():n,newPanel:r};e.preventDefault(),o&&!i.collapsible||this._trigger("beforeActivate",e,l)===!1||(i.active=a?!1:this.headers.index(n),this.active=o?t():n,this._toggle(l),s.removeClass("ui-accordion-header-active ui-state-active"),i.icons&&s.children(".ui-accordion-header-icon").removeClass(i.icons.activeHeader).addClass(i.icons.header),o||(n.removeClass("ui-corner-all").addClass("ui-accordion-header-active ui-state-active ui-corner-top"),i.icons&&n.children(".ui-accordion-header-icon").removeClass(i.icons.header).addClass(i.icons.activeHeader),n.next().addClass("ui-accordion-content-active")))},_toggle:function(e){var i=e.newPanel,s=this.prevShow.length?this.prevShow:e.oldPanel;this.prevShow.add(this.prevHide).stop(!0,!0),this.prevShow=i,this.prevHide=s,this.options.animate?this._animate(i,s,e):(s.hide(),i.show(),this._toggleComplete(e)),s.attr({"aria-hidden":"true"}),s.prev().attr("aria-selected","false"),i.length&&s.length?s.prev().attr({tabIndex:-1,"aria-expanded":"false"}):i.length&&this.headers.filter(function(){return 0===t(this).attr("tabIndex")}).attr("tabIndex",-1),i.attr("aria-hidden","false").prev().attr({"aria-selected":"true",tabIndex:0,"aria-expanded":"true"})},_animate:function(t,e,n){var o,a,r,h=this,l=0,c=t.length&&(!e.length||t.index()<e.index()),u=this.options.animate||{},d=c&&u.down||u,p=function(){h._toggleComplete(n)};return"number"==typeof d&&(r=d),"string"==typeof d&&(a=d),a=a||d.easing||u.easing,r=r||d.duration||u.duration,e.length?t.length?(o=t.show().outerHeight(),e.animate(i,{duration:r,easing:a,step:function(t,e){e.now=Math.round(t)}}),t.hide().animate(s,{duration:r,easing:a,complete:p,step:function(t,i){i.now=Math.round(t),"height"!==i.prop?l+=i.now:"content"!==h.options.heightStyle&&(i.now=Math.round(o-e.outerHeight()-l),l=0)}}),undefined):e.animate(i,r,a,p):t.animate(s,r,a,p)},_toggleComplete:function(t){var e=t.oldPanel;e.removeClass("ui-accordion-content-active").prev().removeClass("ui-corner-top").addClass("ui-corner-all"),e.length&&(e.parent()[0].className=e.parent()[0].className),this._trigger("activate",null,t)}})}(jQuery),function(t){t.widget("ui.autocomplete",{version:"1.10.4",defaultElement:"<input>",options:{appendTo:null,autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null,change:null,close:null,focus:null,open:null,response:null,search:null,select:null},requestIndex:0,pending:0,_create:function(){var e,i,s,n=this.element[0].nodeName.toLowerCase(),o="textarea"===n,a="input"===n;this.isMultiLine=o?!0:a?!1:this.element.prop("isContentEditable"),this.valueMethod=this.element[o||a?"val":"text"],this.isNewMenu=!0,this.element.addClass("ui-autocomplete-input").attr("autocomplete","off"),this._on(this.element,{keydown:function(n){if(this.element.prop("readOnly"))return e=!0,s=!0,i=!0,undefined;e=!1,s=!1,i=!1;var o=t.ui.keyCode;switch(n.keyCode){case o.PAGE_UP:e=!0,this._move("previousPage",n);break;case o.PAGE_DOWN:e=!0,this._move("nextPage",n);break;case o.UP:e=!0,this._keyEvent("previous",n);break;case o.DOWN:e=!0,this._keyEvent("next",n);break;case o.ENTER:case o.NUMPAD_ENTER:this.menu.active&&(e=!0,n.preventDefault(),this.menu.select(n));break;case o.TAB:this.menu.active&&this.menu.select(n);break;case o.ESCAPE:this.menu.element.is(":visible")&&(this._value(this.term),this.close(n),n.preventDefault());break;default:i=!0,this._searchTimeout(n)}},keypress:function(s){if(e)return e=!1,(!this.isMultiLine||this.menu.element.is(":visible"))&&s.preventDefault(),undefined;if(!i){var n=t.ui.keyCode;switch(s.keyCode){case n.PAGE_UP:this._move("previousPage",s);break;case n.PAGE_DOWN:this._move("nextPage",s);break;case n.UP:this._keyEvent("previous",s);break;case n.DOWN:this._keyEvent("next",s)}}},input:function(t){return s?(s=!1,t.preventDefault(),undefined):(this._searchTimeout(t),undefined)},focus:function(){this.selectedItem=null,this.previous=this._value()},blur:function(t){return this.cancelBlur?(delete this.cancelBlur,undefined):(clearTimeout(this.searching),this.close(t),this._change(t),undefined)}}),this._initSource(),this.menu=t("<ul>").addClass("ui-autocomplete ui-front").appendTo(this._appendTo()).menu({role:null}).hide().data("ui-menu"),this._on(this.menu.element,{mousedown:function(e){e.preventDefault(),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur});var i=this.menu.element[0];t(e.target).closest(".ui-menu-item").length||this._delay(function(){var e=this;this.document.one("mousedown",function(s){s.target===e.element[0]||s.target===i||t.contains(i,s.target)||e.close()})})},menufocus:function(e,i){if(this.isNewMenu&&(this.isNewMenu=!1,e.originalEvent&&/^mouse/.test(e.originalEvent.type)))return this.menu.blur(),this.document.one("mousemove",function(){t(e.target).trigger(e.originalEvent)}),undefined;var s=i.item.data("ui-autocomplete-item");!1!==this._trigger("focus",e,{item:s})?e.originalEvent&&/^key/.test(e.originalEvent.type)&&this._value(s.value):this.liveRegion.text(s.value)},menuselect:function(t,e){var i=e.item.data("ui-autocomplete-item"),s=this.previous;this.element[0]!==this.document[0].activeElement&&(this.element.focus(),this.previous=s,this._delay(function(){this.previous=s,this.selectedItem=i})),!1!==this._trigger("select",t,{item:i})&&this._value(i.value),this.term=this._value(),this.close(t),this.selectedItem=i}}),this.liveRegion=t("<span>",{role:"status","aria-live":"polite"}).addClass("ui-helper-hidden-accessible").insertBefore(this.element),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_destroy:function(){clearTimeout(this.searching),this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete"),this.menu.element.remove(),this.liveRegion.remove()},_setOption:function(t,e){this._super(t,e),"source"===t&&this._initSource(),"appendTo"===t&&this.menu.element.appendTo(this._appendTo()),"disabled"===t&&e&&this.xhr&&this.xhr.abort()},_appendTo:function(){var e=this.options.appendTo;return e&&(e=e.jquery||e.nodeType?t(e):this.document.find(e).eq(0)),e||(e=this.element.closest(".ui-front")),e.length||(e=this.document[0].body),e},_initSource:function(){var e,i,s=this;t.isArray(this.options.source)?(e=this.options.source,this.source=function(i,s){s(t.ui.autocomplete.filter(e,i.term))}):"string"==typeof this.options.source?(i=this.options.source,this.source=function(e,n){s.xhr&&s.xhr.abort(),s.xhr=t.ajax({url:i,data:e,dataType:"json",success:function(t){n(t)},error:function(){n([])}})}):this.source=this.options.source},_searchTimeout:function(t){clearTimeout(this.searching),this.searching=this._delay(function(){this.term!==this._value()&&(this.selectedItem=null,this.search(null,t))},this.options.delay)},search:function(t,e){return t=null!=t?t:this._value(),this.term=this._value(),t.length<this.options.minLength?this.close(e):this._trigger("search",e)!==!1?this._search(t):undefined},_search:function(t){this.pending++,this.element.addClass("ui-autocomplete-loading"),this.cancelSearch=!1,this.source({term:t},this._response())},_response:function(){var e=++this.requestIndex;return t.proxy(function(t){e===this.requestIndex&&this.__response(t),this.pending--,this.pending||this.element.removeClass("ui-autocomplete-loading")},this)},__response:function(t){t&&(t=this._normalize(t)),this._trigger("response",null,{content:t}),!this.options.disabled&&t&&t.length&&!this.cancelSearch?(this._suggest(t),this._trigger("open")):this._close()},close:function(t){this.cancelSearch=!0,this._close(t)},_close:function(t){this.menu.element.is(":visible")&&(this.menu.element.hide(),this.menu.blur(),this.isNewMenu=!0,this._trigger("close",t))},_change:function(t){this.previous!==this._value()&&this._trigger("change",t,{item:this.selectedItem})},_normalize:function(e){return e.length&&e[0].label&&e[0].value?e:t.map(e,function(e){return"string"==typeof e?{label:e,value:e}:t.extend({label:e.label||e.value,value:e.value||e.label},e)})},_suggest:function(e){var i=this.menu.element.empty();this._renderMenu(i,e),this.isNewMenu=!0,this.menu.refresh(),i.show(),this._resizeMenu(),i.position(t.extend({of:this.element},this.options.position)),this.options.autoFocus&&this.menu.next()},_resizeMenu:function(){var t=this.menu.element;t.outerWidth(Math.max(t.width("").outerWidth()+1,this.element.outerWidth()))},_renderMenu:function(e,i){var s=this;t.each(i,function(t,i){s._renderItemData(e,i)})},_renderItemData:function(t,e){return this._renderItem(t,e).data("ui-autocomplete-item",e)},_renderItem:function(e,i){return t("<li>").append(t("<a>").text(i.label)).appendTo(e)},_move:function(t,e){return this.menu.element.is(":visible")?this.menu.isFirstItem()&&/^previous/.test(t)||this.menu.isLastItem()&&/^next/.test(t)?(this._value(this.term),this.menu.blur(),undefined):(this.menu[t](e),undefined):(this.search(null,e),undefined)},widget:function(){return this.menu.element},_value:function(){return this.valueMethod.apply(this.element,arguments)},_keyEvent:function(t,e){(!this.isMultiLine||this.menu.element.is(":visible"))&&(this._move(t,e),e.preventDefault())}}),t.extend(t.ui.autocomplete,{escapeRegex:function(t){return t.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")},filter:function(e,i){var s=RegExp(t.ui.autocomplete.escapeRegex(i),"i");return t.grep(e,function(t){return s.test(t.label||t.value||t)})}}),t.widget("ui.autocomplete",t.ui.autocomplete,{options:{messages:{noResults:"No search results.",results:function(t){return t+(t>1?" results are":" result is")+" available, use up and down arrow keys to navigate."}}},__response:function(t){var e;this._superApply(arguments),this.options.disabled||this.cancelSearch||(e=t&&t.length?this.options.messages.results(t.length):this.options.messages.noResults,this.liveRegion.text(e))}})}(jQuery),function(t){var e,i="ui-button ui-widget ui-state-default ui-corner-all",s="ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",n=function(){var e=t(this);setTimeout(function(){e.find(":ui-button").button("refresh")},1)},o=function(e){var i=e.name,s=e.form,n=t([]);return i&&(i=i.replace(/'/g,"\\'"),n=s?t(s).find("[name='"+i+"']"):t("[name='"+i+"']",e.ownerDocument).filter(function(){return!this.form})),n};t.widget("ui.button",{version:"1.10.4",defaultElement:"<button>",options:{disabled:null,text:!0,label:null,icons:{primary:null,secondary:null}},_create:function(){this.element.closest("form").unbind("reset"+this.eventNamespace).bind("reset"+this.eventNamespace,n),"boolean"!=typeof this.options.disabled?this.options.disabled=!!this.element.prop("disabled"):this.element.prop("disabled",this.options.disabled),this._determineButtonType(),this.hasTitle=!!this.buttonElement.attr("title");var s=this,a=this.options,r="checkbox"===this.type||"radio"===this.type,h=r?"":"ui-state-active";null===a.label&&(a.label="input"===this.type?this.buttonElement.val():this.buttonElement.html()),this._hoverable(this.buttonElement),this.buttonElement.addClass(i).attr("role","button").bind("mouseenter"+this.eventNamespace,function(){a.disabled||this===e&&t(this).addClass("ui-state-active")}).bind("mouseleave"+this.eventNamespace,function(){a.disabled||t(this).removeClass(h)}).bind("click"+this.eventNamespace,function(t){a.disabled&&(t.preventDefault(),t.stopImmediatePropagation())}),this._on({focus:function(){this.buttonElement.addClass("ui-state-focus")},blur:function(){this.buttonElement.removeClass("ui-state-focus")}}),r&&this.element.bind("change"+this.eventNamespace,function(){s.refresh()}),"checkbox"===this.type?this.buttonElement.bind("click"+this.eventNamespace,function(){return a.disabled?!1:undefined}):"radio"===this.type?this.buttonElement.bind("click"+this.eventNamespace,function(){if(a.disabled)return!1;t(this).addClass("ui-state-active"),s.buttonElement.attr("aria-pressed","true");var e=s.element[0];o(e).not(e).map(function(){return t(this).button("widget")[0]}).removeClass("ui-state-active").attr("aria-pressed","false")}):(this.buttonElement.bind("mousedown"+this.eventNamespace,function(){return a.disabled?!1:(t(this).addClass("ui-state-active"),e=this,s.document.one("mouseup",function(){e=null}),undefined)}).bind("mouseup"+this.eventNamespace,function(){return a.disabled?!1:(t(this).removeClass("ui-state-active"),undefined)}).bind("keydown"+this.eventNamespace,function(e){return a.disabled?!1:((e.keyCode===t.ui.keyCode.SPACE||e.keyCode===t.ui.keyCode.ENTER)&&t(this).addClass("ui-state-active"),undefined)}).bind("keyup"+this.eventNamespace+" blur"+this.eventNamespace,function(){t(this).removeClass("ui-state-active")}),this.buttonElement.is("a")&&this.buttonElement.keyup(function(e){e.keyCode===t.ui.keyCode.SPACE&&t(this).click()})),this._setOption("disabled",a.disabled),this._resetButton()},_determineButtonType:function(){var t,e,i;this.type=this.element.is("[type=checkbox]")?"checkbox":this.element.is("[type=radio]")?"radio":this.element.is("input")?"input":"button","checkbox"===this.type||"radio"===this.type?(t=this.element.parents().last(),e="label[for='"+this.element.attr("id")+"']",this.buttonElement=t.find(e),this.buttonElement.length||(t=t.length?t.siblings():this.element.siblings(),this.buttonElement=t.filter(e),this.buttonElement.length||(this.buttonElement=t.find(e))),this.element.addClass("ui-helper-hidden-accessible"),i=this.element.is(":checked"),i&&this.buttonElement.addClass("ui-state-active"),this.buttonElement.prop("aria-pressed",i)):this.buttonElement=this.element},widget:function(){return this.buttonElement},_destroy:function(){this.element.removeClass("ui-helper-hidden-accessible"),this.buttonElement.removeClass(i+" ui-state-active "+s).removeAttr("role").removeAttr("aria-pressed").html(this.buttonElement.find(".ui-button-text").html()),this.hasTitle||this.buttonElement.removeAttr("title")},_setOption:function(t,e){return this._super(t,e),"disabled"===t?(this.element.prop("disabled",!!e),e&&this.buttonElement.removeClass("ui-state-focus"),undefined):(this._resetButton(),undefined)},refresh:function(){var e=this.element.is("input, button")?this.element.is(":disabled"):this.element.hasClass("ui-button-disabled");e!==this.options.disabled&&this._setOption("disabled",e),"radio"===this.type?o(this.element[0]).each(function(){t(this).is(":checked")?t(this).button("widget").addClass("ui-state-active").attr("aria-pressed","true"):t(this).button("widget").removeClass("ui-state-active").attr("aria-pressed","false")}):"checkbox"===this.type&&(this.element.is(":checked")?this.buttonElement.addClass("ui-state-active").attr("aria-pressed","true"):this.buttonElement.removeClass("ui-state-active").attr("aria-pressed","false"))},_resetButton:function(){if("input"===this.type)return this.options.label&&this.element.val(this.options.label),undefined;var e=this.buttonElement.removeClass(s),i=t("<span></span>",this.document[0]).addClass("ui-button-text").html(this.options.label).appendTo(e.empty()).text(),n=this.options.icons,o=n.primary&&n.secondary,a=[];n.primary||n.secondary?(this.options.text&&a.push("ui-button-text-icon"+(o?"s":n.primary?"-primary":"-secondary")),n.primary&&e.prepend("<span class='ui-button-icon-primary ui-icon "+n.primary+"'></span>"),n.secondary&&e.append("<span class='ui-button-icon-secondary ui-icon "+n.secondary+"'></span>"),this.options.text||(a.push(o?"ui-button-icons-only":"ui-button-icon-only"),this.hasTitle||e.attr("title",t.trim(i)))):a.push("ui-button-text-only"),e.addClass(a.join(" "))}}),t.widget("ui.buttonset",{version:"1.10.4",options:{items:"button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)"},_create:function(){this.element.addClass("ui-buttonset")},_init:function(){this.refresh()},_setOption:function(t,e){"disabled"===t&&this.buttons.button("option",t,e),this._super(t,e)},refresh:function(){var e="rtl"===this.element.css("direction");this.buttons=this.element.find(this.options.items).filter(":ui-button").button("refresh").end().not(":ui-button").button().end().map(function(){return t(this).button("widget")[0]}).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":first").addClass(e?"ui-corner-right":"ui-corner-left").end().filter(":last").addClass(e?"ui-corner-left":"ui-corner-right").end().end()},_destroy:function(){this.element.removeClass("ui-buttonset"),this.buttons.map(function(){return t(this).button("widget")[0]}).removeClass("ui-corner-left ui-corner-right").end().button("destroy")}})}(jQuery),function(t,e){function i(){this._curInst=null,this._keyEvent=!1,this._disabledInputs=[],this._datepickerShowing=!1,this._inDialog=!1,this._mainDivId="ui-datepicker-div",this._inlineClass="ui-datepicker-inline",this._appendClass="ui-datepicker-append",this._triggerClass="ui-datepicker-trigger",this._dialogClass="ui-datepicker-dialog",this._disableClass="ui-datepicker-disabled",this._unselectableClass="ui-datepicker-unselectable",this._currentClass="ui-datepicker-current-day",this._dayOverClass="ui-datepicker-days-cell-over",this.regional=[],this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"mm/dd/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""},this._defaults={showOn:"focus",showAnim:"fadeIn",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:!1,hideIfNoPrevNext:!1,navigationAsDateFormat:!1,gotoCurrent:!1,changeMonth:!1,changeYear:!1,yearRange:"c-10:c+10",showOtherMonths:!1,selectOtherMonths:!1,showWeek:!1,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",minDate:null,maxDate:null,duration:"fast",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:!0,showButtonPanel:!1,autoSize:!1,disabled:!1},t.extend(this._defaults,this.regional[""]),this.dpDiv=s(t("<div id='"+this._mainDivId+"' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"))}function s(e){var i="button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";return e.delegate(i,"mouseout",function(){t(this).removeClass("ui-state-hover"),-1!==this.className.indexOf("ui-datepicker-prev")&&t(this).removeClass("ui-datepicker-prev-hover"),-1!==this.className.indexOf("ui-datepicker-next")&&t(this).removeClass("ui-datepicker-next-hover")}).delegate(i,"mouseover",function(){t.datepicker._isDisabledDatepicker(o.inline?e.parent()[0]:o.input[0])||(t(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"),t(this).addClass("ui-state-hover"),-1!==this.className.indexOf("ui-datepicker-prev")&&t(this).addClass("ui-datepicker-prev-hover"),-1!==this.className.indexOf("ui-datepicker-next")&&t(this).addClass("ui-datepicker-next-hover"))})}function n(e,i){t.extend(e,i);for(var s in i)null==i[s]&&(e[s]=i[s]);return e}t.extend(t.ui,{datepicker:{version:"1.10.4"}});var o,a="datepicker";t.extend(i.prototype,{markerClassName:"hasDatepicker",maxRows:4,_widgetDatepicker:function(){return this.dpDiv},setDefaults:function(t){return n(this._defaults,t||{}),this},_attachDatepicker:function(e,i){var s,n,o;s=e.nodeName.toLowerCase(),n="div"===s||"span"===s,e.id||(this.uuid+=1,e.id="dp"+this.uuid),o=this._newInst(t(e),n),o.settings=t.extend({},i||{}),"input"===s?this._connectDatepicker(e,o):n&&this._inlineDatepicker(e,o)},_newInst:function(e,i){var n=e[0].id.replace(/([^A-Za-z0-9_\-])/g,"\\\\$1");return{id:n,input:e,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:i,dpDiv:i?s(t("<div class='"+this._inlineClass+" ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")):this.dpDiv}},_connectDatepicker:function(e,i){var s=t(e);i.append=t([]),i.trigger=t([]),s.hasClass(this.markerClassName)||(this._attachments(s,i),s.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).keyup(this._doKeyUp),this._autoSize(i),t.data(e,a,i),i.settings.disabled&&this._disableDatepicker(e))},_attachments:function(e,i){var s,n,o,a=this._get(i,"appendText"),r=this._get(i,"isRTL");i.append&&i.append.remove(),a&&(i.append=t("<span class='"+this._appendClass+"'>"+a+"</span>"),e[r?"before":"after"](i.append)),e.unbind("focus",this._showDatepicker),i.trigger&&i.trigger.remove(),s=this._get(i,"showOn"),("focus"===s||"both"===s)&&e.focus(this._showDatepicker),("button"===s||"both"===s)&&(n=this._get(i,"buttonText"),o=this._get(i,"buttonImage"),i.trigger=t(this._get(i,"buttonImageOnly")?t("<img/>").addClass(this._triggerClass).attr({src:o,alt:n,title:n}):t("<button type='button'></button>").addClass(this._triggerClass).html(o?t("<img/>").attr({src:o,alt:n,title:n}):n)),e[r?"before":"after"](i.trigger),i.trigger.click(function(){return t.datepicker._datepickerShowing&&t.datepicker._lastInput===e[0]?t.datepicker._hideDatepicker():t.datepicker._datepickerShowing&&t.datepicker._lastInput!==e[0]?(t.datepicker._hideDatepicker(),t.datepicker._showDatepicker(e[0])):t.datepicker._showDatepicker(e[0]),!1}))},_autoSize:function(t){if(this._get(t,"autoSize")&&!t.inline){var e,i,s,n,o=new Date(2009,11,20),a=this._get(t,"dateFormat");a.match(/[DM]/)&&(e=function(t){for(i=0,s=0,n=0;t.length>n;n++)t[n].length>i&&(i=t[n].length,s=n);return s},o.setMonth(e(this._get(t,a.match(/MM/)?"monthNames":"monthNamesShort"))),o.setDate(e(this._get(t,a.match(/DD/)?"dayNames":"dayNamesShort"))+20-o.getDay())),t.input.attr("size",this._formatDate(t,o).length)}},_inlineDatepicker:function(e,i){var s=t(e);s.hasClass(this.markerClassName)||(s.addClass(this.markerClassName).append(i.dpDiv),t.data(e,a,i),this._setDate(i,this._getDefaultDate(i),!0),this._updateDatepicker(i),this._updateAlternate(i),i.settings.disabled&&this._disableDatepicker(e),i.dpDiv.css("display","block"))},_dialogDatepicker:function(e,i,s,o,r){var h,l,c,u,d,p=this._dialogInst;return p||(this.uuid+=1,h="dp"+this.uuid,this._dialogInput=t("<input type='text' id='"+h+"' style='position: absolute; top: -100px; width: 0px;'/>"),this._dialogInput.keydown(this._doKeyDown),t("body").append(this._dialogInput),p=this._dialogInst=this._newInst(this._dialogInput,!1),p.settings={},t.data(this._dialogInput[0],a,p)),n(p.settings,o||{}),i=i&&i.constructor===Date?this._formatDate(p,i):i,this._dialogInput.val(i),this._pos=r?r.length?r:[r.pageX,r.pageY]:null,this._pos||(l=document.documentElement.clientWidth,c=document.documentElement.clientHeight,u=document.documentElement.scrollLeft||document.body.scrollLeft,d=document.documentElement.scrollTop||document.body.scrollTop,this._pos=[l/2-100+u,c/2-150+d]),this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px"),p.settings.onSelect=s,this._inDialog=!0,this.dpDiv.addClass(this._dialogClass),this._showDatepicker(this._dialogInput[0]),t.blockUI&&t.blockUI(this.dpDiv),t.data(this._dialogInput[0],a,p),this},_destroyDatepicker:function(e){var i,s=t(e),n=t.data(e,a);s.hasClass(this.markerClassName)&&(i=e.nodeName.toLowerCase(),t.removeData(e,a),"input"===i?(n.append.remove(),n.trigger.remove(),s.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",this._doKeyUp)):("div"===i||"span"===i)&&s.removeClass(this.markerClassName).empty())},_enableDatepicker:function(e){var i,s,n=t(e),o=t.data(e,a);n.hasClass(this.markerClassName)&&(i=e.nodeName.toLowerCase(),"input"===i?(e.disabled=!1,o.trigger.filter("button").each(function(){this.disabled=!1}).end().filter("img").css({opacity:"1.0",cursor:""})):("div"===i||"span"===i)&&(s=n.children("."+this._inlineClass),s.children().removeClass("ui-state-disabled"),s.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!1)),this._disabledInputs=t.map(this._disabledInputs,function(t){return t===e?null:t}))},_disableDatepicker:function(e){var i,s,n=t(e),o=t.data(e,a);n.hasClass(this.markerClassName)&&(i=e.nodeName.toLowerCase(),"input"===i?(e.disabled=!0,o.trigger.filter("button").each(function(){this.disabled=!0}).end().filter("img").css({opacity:"0.5",cursor:"default"})):("div"===i||"span"===i)&&(s=n.children("."+this._inlineClass),s.children().addClass("ui-state-disabled"),s.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!0)),this._disabledInputs=t.map(this._disabledInputs,function(t){return t===e?null:t}),this._disabledInputs[this._disabledInputs.length]=e)},_isDisabledDatepicker:function(t){if(!t)return!1;for(var e=0;this._disabledInputs.length>e;e++)if(this._disabledInputs[e]===t)return!0;return!1},_getInst:function(e){try{return t.data(e,a)}catch(i){throw"Missing instance data for this datepicker"}},_optionDatepicker:function(i,s,o){var a,r,h,l,c=this._getInst(i);return 2===arguments.length&&"string"==typeof s?"defaults"===s?t.extend({},t.datepicker._defaults):c?"all"===s?t.extend({},c.settings):this._get(c,s):null:(a=s||{},"string"==typeof s&&(a={},a[s]=o),c&&(this._curInst===c&&this._hideDatepicker(),r=this._getDateDatepicker(i,!0),h=this._getMinMaxDate(c,"min"),l=this._getMinMaxDate(c,"max"),n(c.settings,a),null!==h&&a.dateFormat!==e&&a.minDate===e&&(c.settings.minDate=this._formatDate(c,h)),null!==l&&a.dateFormat!==e&&a.maxDate===e&&(c.settings.maxDate=this._formatDate(c,l)),"disabled"in a&&(a.disabled?this._disableDatepicker(i):this._enableDatepicker(i)),this._attachments(t(i),c),this._autoSize(c),this._setDate(c,r),this._updateAlternate(c),this._updateDatepicker(c)),e)},_changeDatepicker:function(t,e,i){this._optionDatepicker(t,e,i)},_refreshDatepicker:function(t){var e=this._getInst(t);e&&this._updateDatepicker(e)},_setDateDatepicker:function(t,e){var i=this._getInst(t);i&&(this._setDate(i,e),this._updateDatepicker(i),this._updateAlternate(i))},_getDateDatepicker:function(t,e){var i=this._getInst(t);return i&&!i.inline&&this._setDateFromField(i,e),i?this._getDate(i):null},_doKeyDown:function(e){var i,s,n,o=t.datepicker._getInst(e.target),a=!0,r=o.dpDiv.is(".ui-datepicker-rtl");if(o._keyEvent=!0,t.datepicker._datepickerShowing)switch(e.keyCode){case 9:t.datepicker._hideDatepicker(),a=!1;break;case 13:return n=t("td."+t.datepicker._dayOverClass+":not(."+t.datepicker._currentClass+")",o.dpDiv),n[0]&&t.datepicker._selectDay(e.target,o.selectedMonth,o.selectedYear,n[0]),i=t.datepicker._get(o,"onSelect"),i?(s=t.datepicker._formatDate(o),i.apply(o.input?o.input[0]:null,[s,o])):t.datepicker._hideDatepicker(),!1;case 27:t.datepicker._hideDatepicker();break;case 33:t.datepicker._adjustDate(e.target,e.ctrlKey?-t.datepicker._get(o,"stepBigMonths"):-t.datepicker._get(o,"stepMonths"),"M");break;case 34:t.datepicker._adjustDate(e.target,e.ctrlKey?+t.datepicker._get(o,"stepBigMonths"):+t.datepicker._get(o,"stepMonths"),"M");
+break;case 35:(e.ctrlKey||e.metaKey)&&t.datepicker._clearDate(e.target),a=e.ctrlKey||e.metaKey;break;case 36:(e.ctrlKey||e.metaKey)&&t.datepicker._gotoToday(e.target),a=e.ctrlKey||e.metaKey;break;case 37:(e.ctrlKey||e.metaKey)&&t.datepicker._adjustDate(e.target,r?1:-1,"D"),a=e.ctrlKey||e.metaKey,e.originalEvent.altKey&&t.datepicker._adjustDate(e.target,e.ctrlKey?-t.datepicker._get(o,"stepBigMonths"):-t.datepicker._get(o,"stepMonths"),"M");break;case 38:(e.ctrlKey||e.metaKey)&&t.datepicker._adjustDate(e.target,-7,"D"),a=e.ctrlKey||e.metaKey;break;case 39:(e.ctrlKey||e.metaKey)&&t.datepicker._adjustDate(e.target,r?-1:1,"D"),a=e.ctrlKey||e.metaKey,e.originalEvent.altKey&&t.datepicker._adjustDate(e.target,e.ctrlKey?+t.datepicker._get(o,"stepBigMonths"):+t.datepicker._get(o,"stepMonths"),"M");break;case 40:(e.ctrlKey||e.metaKey)&&t.datepicker._adjustDate(e.target,7,"D"),a=e.ctrlKey||e.metaKey;break;default:a=!1}else 36===e.keyCode&&e.ctrlKey?t.datepicker._showDatepicker(this):a=!1;a&&(e.preventDefault(),e.stopPropagation())},_doKeyPress:function(i){var s,n,o=t.datepicker._getInst(i.target);return t.datepicker._get(o,"constrainInput")?(s=t.datepicker._possibleChars(t.datepicker._get(o,"dateFormat")),n=String.fromCharCode(null==i.charCode?i.keyCode:i.charCode),i.ctrlKey||i.metaKey||" ">n||!s||s.indexOf(n)>-1):e},_doKeyUp:function(e){var i,s=t.datepicker._getInst(e.target);if(s.input.val()!==s.lastVal)try{i=t.datepicker.parseDate(t.datepicker._get(s,"dateFormat"),s.input?s.input.val():null,t.datepicker._getFormatConfig(s)),i&&(t.datepicker._setDateFromField(s),t.datepicker._updateAlternate(s),t.datepicker._updateDatepicker(s))}catch(n){}return!0},_showDatepicker:function(e){if(e=e.target||e,"input"!==e.nodeName.toLowerCase()&&(e=t("input",e.parentNode)[0]),!t.datepicker._isDisabledDatepicker(e)&&t.datepicker._lastInput!==e){var i,s,o,a,r,h,l;i=t.datepicker._getInst(e),t.datepicker._curInst&&t.datepicker._curInst!==i&&(t.datepicker._curInst.dpDiv.stop(!0,!0),i&&t.datepicker._datepickerShowing&&t.datepicker._hideDatepicker(t.datepicker._curInst.input[0])),s=t.datepicker._get(i,"beforeShow"),o=s?s.apply(e,[e,i]):{},o!==!1&&(n(i.settings,o),i.lastVal=null,t.datepicker._lastInput=e,t.datepicker._setDateFromField(i),t.datepicker._inDialog&&(e.value=""),t.datepicker._pos||(t.datepicker._pos=t.datepicker._findPos(e),t.datepicker._pos[1]+=e.offsetHeight),a=!1,t(e).parents().each(function(){return a|="fixed"===t(this).css("position"),!a}),r={left:t.datepicker._pos[0],top:t.datepicker._pos[1]},t.datepicker._pos=null,i.dpDiv.empty(),i.dpDiv.css({position:"absolute",display:"block",top:"-1000px"}),t.datepicker._updateDatepicker(i),r=t.datepicker._checkOffset(i,r,a),i.dpDiv.css({position:t.datepicker._inDialog&&t.blockUI?"static":a?"fixed":"absolute",display:"none",left:r.left+"px",top:r.top+"px"}),i.inline||(h=t.datepicker._get(i,"showAnim"),l=t.datepicker._get(i,"duration"),i.dpDiv.zIndex(t(e).zIndex()+1),t.datepicker._datepickerShowing=!0,t.effects&&t.effects.effect[h]?i.dpDiv.show(h,t.datepicker._get(i,"showOptions"),l):i.dpDiv[h||"show"](h?l:null),t.datepicker._shouldFocusInput(i)&&i.input.focus(),t.datepicker._curInst=i))}},_updateDatepicker:function(e){this.maxRows=4,o=e,e.dpDiv.empty().append(this._generateHTML(e)),this._attachHandlers(e),e.dpDiv.find("."+this._dayOverClass+" a").mouseover();var i,s=this._getNumberOfMonths(e),n=s[1],a=17;e.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""),n>1&&e.dpDiv.addClass("ui-datepicker-multi-"+n).css("width",a*n+"em"),e.dpDiv[(1!==s[0]||1!==s[1]?"add":"remove")+"Class"]("ui-datepicker-multi"),e.dpDiv[(this._get(e,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl"),e===t.datepicker._curInst&&t.datepicker._datepickerShowing&&t.datepicker._shouldFocusInput(e)&&e.input.focus(),e.yearshtml&&(i=e.yearshtml,setTimeout(function(){i===e.yearshtml&&e.yearshtml&&e.dpDiv.find("select.ui-datepicker-year:first").replaceWith(e.yearshtml),i=e.yearshtml=null},0))},_shouldFocusInput:function(t){return t.input&&t.input.is(":visible")&&!t.input.is(":disabled")&&!t.input.is(":focus")},_checkOffset:function(e,i,s){var n=e.dpDiv.outerWidth(),o=e.dpDiv.outerHeight(),a=e.input?e.input.outerWidth():0,r=e.input?e.input.outerHeight():0,h=document.documentElement.clientWidth+(s?0:t(document).scrollLeft()),l=document.documentElement.clientHeight+(s?0:t(document).scrollTop());return i.left-=this._get(e,"isRTL")?n-a:0,i.left-=s&&i.left===e.input.offset().left?t(document).scrollLeft():0,i.top-=s&&i.top===e.input.offset().top+r?t(document).scrollTop():0,i.left-=Math.min(i.left,i.left+n>h&&h>n?Math.abs(i.left+n-h):0),i.top-=Math.min(i.top,i.top+o>l&&l>o?Math.abs(o+r):0),i},_findPos:function(e){for(var i,s=this._getInst(e),n=this._get(s,"isRTL");e&&("hidden"===e.type||1!==e.nodeType||t.expr.filters.hidden(e));)e=e[n?"previousSibling":"nextSibling"];return i=t(e).offset(),[i.left,i.top]},_hideDatepicker:function(e){var i,s,n,o,r=this._curInst;!r||e&&r!==t.data(e,a)||this._datepickerShowing&&(i=this._get(r,"showAnim"),s=this._get(r,"duration"),n=function(){t.datepicker._tidyDialog(r)},t.effects&&(t.effects.effect[i]||t.effects[i])?r.dpDiv.hide(i,t.datepicker._get(r,"showOptions"),s,n):r.dpDiv["slideDown"===i?"slideUp":"fadeIn"===i?"fadeOut":"hide"](i?s:null,n),i||n(),this._datepickerShowing=!1,o=this._get(r,"onClose"),o&&o.apply(r.input?r.input[0]:null,[r.input?r.input.val():"",r]),this._lastInput=null,this._inDialog&&(this._dialogInput.css({position:"absolute",left:"0",top:"-100px"}),t.blockUI&&(t.unblockUI(),t("body").append(this.dpDiv))),this._inDialog=!1)},_tidyDialog:function(t){t.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(e){if(t.datepicker._curInst){var i=t(e.target),s=t.datepicker._getInst(i[0]);(i[0].id!==t.datepicker._mainDivId&&0===i.parents("#"+t.datepicker._mainDivId).length&&!i.hasClass(t.datepicker.markerClassName)&&!i.closest("."+t.datepicker._triggerClass).length&&t.datepicker._datepickerShowing&&(!t.datepicker._inDialog||!t.blockUI)||i.hasClass(t.datepicker.markerClassName)&&t.datepicker._curInst!==s)&&t.datepicker._hideDatepicker()}},_adjustDate:function(e,i,s){var n=t(e),o=this._getInst(n[0]);this._isDisabledDatepicker(n[0])||(this._adjustInstDate(o,i+("M"===s?this._get(o,"showCurrentAtPos"):0),s),this._updateDatepicker(o))},_gotoToday:function(e){var i,s=t(e),n=this._getInst(s[0]);this._get(n,"gotoCurrent")&&n.currentDay?(n.selectedDay=n.currentDay,n.drawMonth=n.selectedMonth=n.currentMonth,n.drawYear=n.selectedYear=n.currentYear):(i=new Date,n.selectedDay=i.getDate(),n.drawMonth=n.selectedMonth=i.getMonth(),n.drawYear=n.selectedYear=i.getFullYear()),this._notifyChange(n),this._adjustDate(s)},_selectMonthYear:function(e,i,s){var n=t(e),o=this._getInst(n[0]);o["selected"+("M"===s?"Month":"Year")]=o["draw"+("M"===s?"Month":"Year")]=parseInt(i.options[i.selectedIndex].value,10),this._notifyChange(o),this._adjustDate(n)},_selectDay:function(e,i,s,n){var o,a=t(e);t(n).hasClass(this._unselectableClass)||this._isDisabledDatepicker(a[0])||(o=this._getInst(a[0]),o.selectedDay=o.currentDay=t("a",n).html(),o.selectedMonth=o.currentMonth=i,o.selectedYear=o.currentYear=s,this._selectDate(e,this._formatDate(o,o.currentDay,o.currentMonth,o.currentYear)))},_clearDate:function(e){var i=t(e);this._selectDate(i,"")},_selectDate:function(e,i){var s,n=t(e),o=this._getInst(n[0]);i=null!=i?i:this._formatDate(o),o.input&&o.input.val(i),this._updateAlternate(o),s=this._get(o,"onSelect"),s?s.apply(o.input?o.input[0]:null,[i,o]):o.input&&o.input.trigger("change"),o.inline?this._updateDatepicker(o):(this._hideDatepicker(),this._lastInput=o.input[0],"object"!=typeof o.input[0]&&o.input.focus(),this._lastInput=null)},_updateAlternate:function(e){var i,s,n,o=this._get(e,"altField");o&&(i=this._get(e,"altFormat")||this._get(e,"dateFormat"),s=this._getDate(e),n=this.formatDate(i,s,this._getFormatConfig(e)),t(o).each(function(){t(this).val(n)}))},noWeekends:function(t){var e=t.getDay();return[e>0&&6>e,""]},iso8601Week:function(t){var e,i=new Date(t.getTime());return i.setDate(i.getDate()+4-(i.getDay()||7)),e=i.getTime(),i.setMonth(0),i.setDate(1),Math.floor(Math.round((e-i)/864e5)/7)+1},parseDate:function(i,s,n){if(null==i||null==s)throw"Invalid arguments";if(s="object"==typeof s?""+s:s+"",""===s)return null;var o,a,r,h,l=0,c=(n?n.shortYearCutoff:null)||this._defaults.shortYearCutoff,u="string"!=typeof c?c:(new Date).getFullYear()%100+parseInt(c,10),d=(n?n.dayNamesShort:null)||this._defaults.dayNamesShort,p=(n?n.dayNames:null)||this._defaults.dayNames,f=(n?n.monthNamesShort:null)||this._defaults.monthNamesShort,g=(n?n.monthNames:null)||this._defaults.monthNames,m=-1,v=-1,_=-1,b=-1,y=!1,w=function(t){var e=i.length>o+1&&i.charAt(o+1)===t;return e&&o++,e},x=function(t){var e=w(t),i="@"===t?14:"!"===t?20:"y"===t&&e?4:"o"===t?3:2,n=RegExp("^\\d{1,"+i+"}"),o=s.substring(l).match(n);if(!o)throw"Missing number at position "+l;return l+=o[0].length,parseInt(o[0],10)},k=function(i,n,o){var a=-1,r=t.map(w(i)?o:n,function(t,e){return[[e,t]]}).sort(function(t,e){return-(t[1].length-e[1].length)});if(t.each(r,function(t,i){var n=i[1];return s.substr(l,n.length).toLowerCase()===n.toLowerCase()?(a=i[0],l+=n.length,!1):e}),-1!==a)return a+1;throw"Unknown name at position "+l},D=function(){if(s.charAt(l)!==i.charAt(o))throw"Unexpected literal at position "+l;l++};for(o=0;i.length>o;o++)if(y)"'"!==i.charAt(o)||w("'")?D():y=!1;else switch(i.charAt(o)){case"d":_=x("d");break;case"D":k("D",d,p);break;case"o":b=x("o");break;case"m":v=x("m");break;case"M":v=k("M",f,g);break;case"y":m=x("y");break;case"@":h=new Date(x("@")),m=h.getFullYear(),v=h.getMonth()+1,_=h.getDate();break;case"!":h=new Date((x("!")-this._ticksTo1970)/1e4),m=h.getFullYear(),v=h.getMonth()+1,_=h.getDate();break;case"'":w("'")?D():y=!0;break;default:D()}if(s.length>l&&(r=s.substr(l),!/^\s+/.test(r)))throw"Extra/unparsed characters found in date: "+r;if(-1===m?m=(new Date).getFullYear():100>m&&(m+=(new Date).getFullYear()-(new Date).getFullYear()%100+(u>=m?0:-100)),b>-1)for(v=1,_=b;;){if(a=this._getDaysInMonth(m,v-1),a>=_)break;v++,_-=a}if(h=this._daylightSavingAdjust(new Date(m,v-1,_)),h.getFullYear()!==m||h.getMonth()+1!==v||h.getDate()!==_)throw"Invalid date";return h},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:1e7*60*60*24*(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925)),formatDate:function(t,e,i){if(!e)return"";var s,n=(i?i.dayNamesShort:null)||this._defaults.dayNamesShort,o=(i?i.dayNames:null)||this._defaults.dayNames,a=(i?i.monthNamesShort:null)||this._defaults.monthNamesShort,r=(i?i.monthNames:null)||this._defaults.monthNames,h=function(e){var i=t.length>s+1&&t.charAt(s+1)===e;return i&&s++,i},l=function(t,e,i){var s=""+e;if(h(t))for(;i>s.length;)s="0"+s;return s},c=function(t,e,i,s){return h(t)?s[e]:i[e]},u="",d=!1;if(e)for(s=0;t.length>s;s++)if(d)"'"!==t.charAt(s)||h("'")?u+=t.charAt(s):d=!1;else switch(t.charAt(s)){case"d":u+=l("d",e.getDate(),2);break;case"D":u+=c("D",e.getDay(),n,o);break;case"o":u+=l("o",Math.round((new Date(e.getFullYear(),e.getMonth(),e.getDate()).getTime()-new Date(e.getFullYear(),0,0).getTime())/864e5),3);break;case"m":u+=l("m",e.getMonth()+1,2);break;case"M":u+=c("M",e.getMonth(),a,r);break;case"y":u+=h("y")?e.getFullYear():(10>e.getYear()%100?"0":"")+e.getYear()%100;break;case"@":u+=e.getTime();break;case"!":u+=1e4*e.getTime()+this._ticksTo1970;break;case"'":h("'")?u+="'":d=!0;break;default:u+=t.charAt(s)}return u},_possibleChars:function(t){var e,i="",s=!1,n=function(i){var s=t.length>e+1&&t.charAt(e+1)===i;return s&&e++,s};for(e=0;t.length>e;e++)if(s)"'"!==t.charAt(e)||n("'")?i+=t.charAt(e):s=!1;else switch(t.charAt(e)){case"d":case"m":case"y":case"@":i+="0123456789";break;case"D":case"M":return null;case"'":n("'")?i+="'":s=!0;break;default:i+=t.charAt(e)}return i},_get:function(t,i){return t.settings[i]!==e?t.settings[i]:this._defaults[i]},_setDateFromField:function(t,e){if(t.input.val()!==t.lastVal){var i=this._get(t,"dateFormat"),s=t.lastVal=t.input?t.input.val():null,n=this._getDefaultDate(t),o=n,a=this._getFormatConfig(t);try{o=this.parseDate(i,s,a)||n}catch(r){s=e?"":s}t.selectedDay=o.getDate(),t.drawMonth=t.selectedMonth=o.getMonth(),t.drawYear=t.selectedYear=o.getFullYear(),t.currentDay=s?o.getDate():0,t.currentMonth=s?o.getMonth():0,t.currentYear=s?o.getFullYear():0,this._adjustInstDate(t)}},_getDefaultDate:function(t){return this._restrictMinMax(t,this._determineDate(t,this._get(t,"defaultDate"),new Date))},_determineDate:function(e,i,s){var n=function(t){var e=new Date;return e.setDate(e.getDate()+t),e},o=function(i){try{return t.datepicker.parseDate(t.datepicker._get(e,"dateFormat"),i,t.datepicker._getFormatConfig(e))}catch(s){}for(var n=(i.toLowerCase().match(/^c/)?t.datepicker._getDate(e):null)||new Date,o=n.getFullYear(),a=n.getMonth(),r=n.getDate(),h=/([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,l=h.exec(i);l;){switch(l[2]||"d"){case"d":case"D":r+=parseInt(l[1],10);break;case"w":case"W":r+=7*parseInt(l[1],10);break;case"m":case"M":a+=parseInt(l[1],10),r=Math.min(r,t.datepicker._getDaysInMonth(o,a));break;case"y":case"Y":o+=parseInt(l[1],10),r=Math.min(r,t.datepicker._getDaysInMonth(o,a))}l=h.exec(i)}return new Date(o,a,r)},a=null==i||""===i?s:"string"==typeof i?o(i):"number"==typeof i?isNaN(i)?s:n(i):new Date(i.getTime());return a=a&&"Invalid Date"==""+a?s:a,a&&(a.setHours(0),a.setMinutes(0),a.setSeconds(0),a.setMilliseconds(0)),this._daylightSavingAdjust(a)},_daylightSavingAdjust:function(t){return t?(t.setHours(t.getHours()>12?t.getHours()+2:0),t):null},_setDate:function(t,e,i){var s=!e,n=t.selectedMonth,o=t.selectedYear,a=this._restrictMinMax(t,this._determineDate(t,e,new Date));t.selectedDay=t.currentDay=a.getDate(),t.drawMonth=t.selectedMonth=t.currentMonth=a.getMonth(),t.drawYear=t.selectedYear=t.currentYear=a.getFullYear(),n===t.selectedMonth&&o===t.selectedYear||i||this._notifyChange(t),this._adjustInstDate(t),t.input&&t.input.val(s?"":this._formatDate(t))},_getDate:function(t){var e=!t.currentYear||t.input&&""===t.input.val()?null:this._daylightSavingAdjust(new Date(t.currentYear,t.currentMonth,t.currentDay));return e},_attachHandlers:function(e){var i=this._get(e,"stepMonths"),s="#"+e.id.replace(/\\\\/g,"\\");e.dpDiv.find("[data-handler]").map(function(){var e={prev:function(){t.datepicker._adjustDate(s,-i,"M")},next:function(){t.datepicker._adjustDate(s,+i,"M")},hide:function(){t.datepicker._hideDatepicker()},today:function(){t.datepicker._gotoToday(s)},selectDay:function(){return t.datepicker._selectDay(s,+this.getAttribute("data-month"),+this.getAttribute("data-year"),this),!1},selectMonth:function(){return t.datepicker._selectMonthYear(s,this,"M"),!1},selectYear:function(){return t.datepicker._selectMonthYear(s,this,"Y"),!1}};t(this).bind(this.getAttribute("data-event"),e[this.getAttribute("data-handler")])})},_generateHTML:function(t){var e,i,s,n,o,a,r,h,l,c,u,d,p,f,g,m,v,_,b,y,w,x,k,D,C,I,P,T,M,S,z,A,E,H,N,W,O,F,R,L=new Date,j=this._daylightSavingAdjust(new Date(L.getFullYear(),L.getMonth(),L.getDate())),Y=this._get(t,"isRTL"),B=this._get(t,"showButtonPanel"),V=this._get(t,"hideIfNoPrevNext"),K=this._get(t,"navigationAsDateFormat"),q=this._getNumberOfMonths(t),U=this._get(t,"showCurrentAtPos"),Q=this._get(t,"stepMonths"),X=1!==q[0]||1!==q[1],$=this._daylightSavingAdjust(t.currentDay?new Date(t.currentYear,t.currentMonth,t.currentDay):new Date(9999,9,9)),G=this._getMinMaxDate(t,"min"),J=this._getMinMaxDate(t,"max"),Z=t.drawMonth-U,te=t.drawYear;if(0>Z&&(Z+=12,te--),J)for(e=this._daylightSavingAdjust(new Date(J.getFullYear(),J.getMonth()-q[0]*q[1]+1,J.getDate())),e=G&&G>e?G:e;this._daylightSavingAdjust(new Date(te,Z,1))>e;)Z--,0>Z&&(Z=11,te--);for(t.drawMonth=Z,t.drawYear=te,i=this._get(t,"prevText"),i=K?this.formatDate(i,this._daylightSavingAdjust(new Date(te,Z-Q,1)),this._getFormatConfig(t)):i,s=this._canAdjustMonth(t,-1,te,Z)?"<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click' title='"+i+"'><span class='ui-icon ui-icon-circle-triangle-"+(Y?"e":"w")+"'>"+i+"</span></a>":V?"":"<a class='ui-datepicker-prev ui-corner-all ui-state-disabled' title='"+i+"'><span class='ui-icon ui-icon-circle-triangle-"+(Y?"e":"w")+"'>"+i+"</span></a>",n=this._get(t,"nextText"),n=K?this.formatDate(n,this._daylightSavingAdjust(new Date(te,Z+Q,1)),this._getFormatConfig(t)):n,o=this._canAdjustMonth(t,1,te,Z)?"<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click' title='"+n+"'><span class='ui-icon ui-icon-circle-triangle-"+(Y?"w":"e")+"'>"+n+"</span></a>":V?"":"<a class='ui-datepicker-next ui-corner-all ui-state-disabled' title='"+n+"'><span class='ui-icon ui-icon-circle-triangle-"+(Y?"w":"e")+"'>"+n+"</span></a>",a=this._get(t,"currentText"),r=this._get(t,"gotoCurrent")&&t.currentDay?$:j,a=K?this.formatDate(a,r,this._getFormatConfig(t)):a,h=t.inline?"":"<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>"+this._get(t,"closeText")+"</button>",l=B?"<div class='ui-datepicker-buttonpane ui-widget-content'>"+(Y?h:"")+(this._isInRange(t,r)?"<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'>"+a+"</button>":"")+(Y?"":h)+"</div>":"",c=parseInt(this._get(t,"firstDay"),10),c=isNaN(c)?0:c,u=this._get(t,"showWeek"),d=this._get(t,"dayNames"),p=this._get(t,"dayNamesMin"),f=this._get(t,"monthNames"),g=this._get(t,"monthNamesShort"),m=this._get(t,"beforeShowDay"),v=this._get(t,"showOtherMonths"),_=this._get(t,"selectOtherMonths"),b=this._getDefaultDate(t),y="",x=0;q[0]>x;x++){for(k="",this.maxRows=4,D=0;q[1]>D;D++){if(C=this._daylightSavingAdjust(new Date(te,Z,t.selectedDay)),I=" ui-corner-all",P="",X){if(P+="<div class='ui-datepicker-group",q[1]>1)switch(D){case 0:P+=" ui-datepicker-group-first",I=" ui-corner-"+(Y?"right":"left");break;case q[1]-1:P+=" ui-datepicker-group-last",I=" ui-corner-"+(Y?"left":"right");break;default:P+=" ui-datepicker-group-middle",I=""}P+="'>"}for(P+="<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix"+I+"'>"+(/all|left/.test(I)&&0===x?Y?o:s:"")+(/all|right/.test(I)&&0===x?Y?s:o:"")+this._generateMonthYearHeader(t,Z,te,G,J,x>0||D>0,f,g)+"</div><table class='ui-datepicker-calendar'><thead>"+"<tr>",T=u?"<th class='ui-datepicker-week-col'>"+this._get(t,"weekHeader")+"</th>":"",w=0;7>w;w++)M=(w+c)%7,T+="<th"+((w+c+6)%7>=5?" class='ui-datepicker-week-end'":"")+">"+"<span title='"+d[M]+"'>"+p[M]+"</span></th>";for(P+=T+"</tr></thead><tbody>",S=this._getDaysInMonth(te,Z),te===t.selectedYear&&Z===t.selectedMonth&&(t.selectedDay=Math.min(t.selectedDay,S)),z=(this._getFirstDayOfMonth(te,Z)-c+7)%7,A=Math.ceil((z+S)/7),E=X?this.maxRows>A?this.maxRows:A:A,this.maxRows=E,H=this._daylightSavingAdjust(new Date(te,Z,1-z)),N=0;E>N;N++){for(P+="<tr>",W=u?"<td class='ui-datepicker-week-col'>"+this._get(t,"calculateWeek")(H)+"</td>":"",w=0;7>w;w++)O=m?m.apply(t.input?t.input[0]:null,[H]):[!0,""],F=H.getMonth()!==Z,R=F&&!_||!O[0]||G&&G>H||J&&H>J,W+="<td class='"+((w+c+6)%7>=5?" ui-datepicker-week-end":"")+(F?" ui-datepicker-other-month":"")+(H.getTime()===C.getTime()&&Z===t.selectedMonth&&t._keyEvent||b.getTime()===H.getTime()&&b.getTime()===C.getTime()?" "+this._dayOverClass:"")+(R?" "+this._unselectableClass+" ui-state-disabled":"")+(F&&!v?"":" "+O[1]+(H.getTime()===$.getTime()?" "+this._currentClass:"")+(H.getTime()===j.getTime()?" ui-datepicker-today":""))+"'"+(F&&!v||!O[2]?"":" title='"+O[2].replace(/'/g,"&#39;")+"'")+(R?"":" data-handler='selectDay' data-event='click' data-month='"+H.getMonth()+"' data-year='"+H.getFullYear()+"'")+">"+(F&&!v?"&#xa0;":R?"<span class='ui-state-default'>"+H.getDate()+"</span>":"<a class='ui-state-default"+(H.getTime()===j.getTime()?" ui-state-highlight":"")+(H.getTime()===$.getTime()?" ui-state-active":"")+(F?" ui-priority-secondary":"")+"' href='#'>"+H.getDate()+"</a>")+"</td>",H.setDate(H.getDate()+1),H=this._daylightSavingAdjust(H);P+=W+"</tr>"}Z++,Z>11&&(Z=0,te++),P+="</tbody></table>"+(X?"</div>"+(q[0]>0&&D===q[1]-1?"<div class='ui-datepicker-row-break'></div>":""):""),k+=P}y+=k}return y+=l,t._keyEvent=!1,y},_generateMonthYearHeader:function(t,e,i,s,n,o,a,r){var h,l,c,u,d,p,f,g,m=this._get(t,"changeMonth"),v=this._get(t,"changeYear"),_=this._get(t,"showMonthAfterYear"),b="<div class='ui-datepicker-title'>",y="";if(o||!m)y+="<span class='ui-datepicker-month'>"+a[e]+"</span>";else{for(h=s&&s.getFullYear()===i,l=n&&n.getFullYear()===i,y+="<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>",c=0;12>c;c++)(!h||c>=s.getMonth())&&(!l||n.getMonth()>=c)&&(y+="<option value='"+c+"'"+(c===e?" selected='selected'":"")+">"+r[c]+"</option>");y+="</select>"}if(_||(b+=y+(!o&&m&&v?"":"&#xa0;")),!t.yearshtml)if(t.yearshtml="",o||!v)b+="<span class='ui-datepicker-year'>"+i+"</span>";else{for(u=this._get(t,"yearRange").split(":"),d=(new Date).getFullYear(),p=function(t){var e=t.match(/c[+\-].*/)?i+parseInt(t.substring(1),10):t.match(/[+\-].*/)?d+parseInt(t,10):parseInt(t,10);return isNaN(e)?d:e},f=p(u[0]),g=Math.max(f,p(u[1]||"")),f=s?Math.max(f,s.getFullYear()):f,g=n?Math.min(g,n.getFullYear()):g,t.yearshtml+="<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";g>=f;f++)t.yearshtml+="<option value='"+f+"'"+(f===i?" selected='selected'":"")+">"+f+"</option>";t.yearshtml+="</select>",b+=t.yearshtml,t.yearshtml=null}return b+=this._get(t,"yearSuffix"),_&&(b+=(!o&&m&&v?"":"&#xa0;")+y),b+="</div>"},_adjustInstDate:function(t,e,i){var s=t.drawYear+("Y"===i?e:0),n=t.drawMonth+("M"===i?e:0),o=Math.min(t.selectedDay,this._getDaysInMonth(s,n))+("D"===i?e:0),a=this._restrictMinMax(t,this._daylightSavingAdjust(new Date(s,n,o)));t.selectedDay=a.getDate(),t.drawMonth=t.selectedMonth=a.getMonth(),t.drawYear=t.selectedYear=a.getFullYear(),("M"===i||"Y"===i)&&this._notifyChange(t)},_restrictMinMax:function(t,e){var i=this._getMinMaxDate(t,"min"),s=this._getMinMaxDate(t,"max"),n=i&&i>e?i:e;return s&&n>s?s:n},_notifyChange:function(t){var e=this._get(t,"onChangeMonthYear");e&&e.apply(t.input?t.input[0]:null,[t.selectedYear,t.selectedMonth+1,t])},_getNumberOfMonths:function(t){var e=this._get(t,"numberOfMonths");return null==e?[1,1]:"number"==typeof e?[1,e]:e},_getMinMaxDate:function(t,e){return this._determineDate(t,this._get(t,e+"Date"),null)},_getDaysInMonth:function(t,e){return 32-this._daylightSavingAdjust(new Date(t,e,32)).getDate()},_getFirstDayOfMonth:function(t,e){return new Date(t,e,1).getDay()},_canAdjustMonth:function(t,e,i,s){var n=this._getNumberOfMonths(t),o=this._daylightSavingAdjust(new Date(i,s+(0>e?e:n[0]*n[1]),1));return 0>e&&o.setDate(this._getDaysInMonth(o.getFullYear(),o.getMonth())),this._isInRange(t,o)},_isInRange:function(t,e){var i,s,n=this._getMinMaxDate(t,"min"),o=this._getMinMaxDate(t,"max"),a=null,r=null,h=this._get(t,"yearRange");return h&&(i=h.split(":"),s=(new Date).getFullYear(),a=parseInt(i[0],10),r=parseInt(i[1],10),i[0].match(/[+\-].*/)&&(a+=s),i[1].match(/[+\-].*/)&&(r+=s)),(!n||e.getTime()>=n.getTime())&&(!o||e.getTime()<=o.getTime())&&(!a||e.getFullYear()>=a)&&(!r||r>=e.getFullYear())},_getFormatConfig:function(t){var e=this._get(t,"shortYearCutoff");return e="string"!=typeof e?e:(new Date).getFullYear()%100+parseInt(e,10),{shortYearCutoff:e,dayNamesShort:this._get(t,"dayNamesShort"),dayNames:this._get(t,"dayNames"),monthNamesShort:this._get(t,"monthNamesShort"),monthNames:this._get(t,"monthNames")}},_formatDate:function(t,e,i,s){e||(t.currentDay=t.selectedDay,t.currentMonth=t.selectedMonth,t.currentYear=t.selectedYear);var n=e?"object"==typeof e?e:this._daylightSavingAdjust(new Date(s,i,e)):this._daylightSavingAdjust(new Date(t.currentYear,t.currentMonth,t.currentDay));return this.formatDate(this._get(t,"dateFormat"),n,this._getFormatConfig(t))}}),t.fn.datepicker=function(e){if(!this.length)return this;t.datepicker.initialized||(t(document).mousedown(t.datepicker._checkExternalClick),t.datepicker.initialized=!0),0===t("#"+t.datepicker._mainDivId).length&&t("body").append(t.datepicker.dpDiv);var i=Array.prototype.slice.call(arguments,1);return"string"!=typeof e||"isDisabled"!==e&&"getDate"!==e&&"widget"!==e?"option"===e&&2===arguments.length&&"string"==typeof arguments[1]?t.datepicker["_"+e+"Datepicker"].apply(t.datepicker,[this[0]].concat(i)):this.each(function(){"string"==typeof e?t.datepicker["_"+e+"Datepicker"].apply(t.datepicker,[this].concat(i)):t.datepicker._attachDatepicker(this,e)}):t.datepicker["_"+e+"Datepicker"].apply(t.datepicker,[this[0]].concat(i))},t.datepicker=new i,t.datepicker.initialized=!1,t.datepicker.uuid=(new Date).getTime(),t.datepicker.version="1.10.4"}(jQuery),function(t){var e={buttons:!0,height:!0,maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0,width:!0},i={maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0};t.widget("ui.dialog",{version:"1.10.4",options:{appendTo:"body",autoOpen:!0,buttons:[],closeOnEscape:!0,closeText:"close",dialogClass:"",draggable:!0,hide:null,height:"auto",maxHeight:null,maxWidth:null,minHeight:150,minWidth:150,modal:!1,position:{my:"center",at:"center",of:window,collision:"fit",using:function(e){var i=t(this).css(e).offset().top;0>i&&t(this).css("top",e.top-i)}},resizable:!0,show:null,title:null,width:300,beforeClose:null,close:null,drag:null,dragStart:null,dragStop:null,focus:null,open:null,resize:null,resizeStart:null,resizeStop:null},_create:function(){this.originalCss={display:this.element[0].style.display,width:this.element[0].style.width,minHeight:this.element[0].style.minHeight,maxHeight:this.element[0].style.maxHeight,height:this.element[0].style.height},this.originalPosition={parent:this.element.parent(),index:this.element.parent().children().index(this.element)},this.originalTitle=this.element.attr("title"),this.options.title=this.options.title||this.originalTitle,this._createWrapper(),this.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(this.uiDialog),this._createTitlebar(),this._createButtonPane(),this.options.draggable&&t.fn.draggable&&this._makeDraggable(),this.options.resizable&&t.fn.resizable&&this._makeResizable(),this._isOpen=!1},_init:function(){this.options.autoOpen&&this.open()},_appendTo:function(){var e=this.options.appendTo;return e&&(e.jquery||e.nodeType)?t(e):this.document.find(e||"body").eq(0)},_destroy:function(){var t,e=this.originalPosition;this._destroyOverlay(),this.element.removeUniqueId().removeClass("ui-dialog-content ui-widget-content").css(this.originalCss).detach(),this.uiDialog.stop(!0,!0).remove(),this.originalTitle&&this.element.attr("title",this.originalTitle),t=e.parent.children().eq(e.index),t.length&&t[0]!==this.element[0]?t.before(this.element):e.parent.append(this.element)},widget:function(){return this.uiDialog},disable:t.noop,enable:t.noop,close:function(e){var i,s=this;if(this._isOpen&&this._trigger("beforeClose",e)!==!1){if(this._isOpen=!1,this._destroyOverlay(),!this.opener.filter(":focusable").focus().length)try{i=this.document[0].activeElement,i&&"body"!==i.nodeName.toLowerCase()&&t(i).blur()}catch(n){}this._hide(this.uiDialog,this.options.hide,function(){s._trigger("close",e)})}},isOpen:function(){return this._isOpen},moveToTop:function(){this._moveToTop()},_moveToTop:function(t,e){var i=!!this.uiDialog.nextAll(":visible").insertBefore(this.uiDialog).length;return i&&!e&&this._trigger("focus",t),i},open:function(){var e=this;return this._isOpen?(this._moveToTop()&&this._focusTabbable(),undefined):(this._isOpen=!0,this.opener=t(this.document[0].activeElement),this._size(),this._position(),this._createOverlay(),this._moveToTop(null,!0),this._show(this.uiDialog,this.options.show,function(){e._focusTabbable(),e._trigger("focus")}),this._trigger("open"),undefined)},_focusTabbable:function(){var t=this.element.find("[autofocus]");t.length||(t=this.element.find(":tabbable")),t.length||(t=this.uiDialogButtonPane.find(":tabbable")),t.length||(t=this.uiDialogTitlebarClose.filter(":tabbable")),t.length||(t=this.uiDialog),t.eq(0).focus()},_keepFocus:function(e){function i(){var e=this.document[0].activeElement,i=this.uiDialog[0]===e||t.contains(this.uiDialog[0],e);i||this._focusTabbable()}e.preventDefault(),i.call(this),this._delay(i)},_createWrapper:function(){this.uiDialog=t("<div>").addClass("ui-dialog ui-widget ui-widget-content ui-corner-all ui-front "+this.options.dialogClass).hide().attr({tabIndex:-1,role:"dialog"}).appendTo(this._appendTo()),this._on(this.uiDialog,{keydown:function(e){if(this.options.closeOnEscape&&!e.isDefaultPrevented()&&e.keyCode&&e.keyCode===t.ui.keyCode.ESCAPE)return e.preventDefault(),this.close(e),undefined;if(e.keyCode===t.ui.keyCode.TAB){var i=this.uiDialog.find(":tabbable"),s=i.filter(":first"),n=i.filter(":last");e.target!==n[0]&&e.target!==this.uiDialog[0]||e.shiftKey?e.target!==s[0]&&e.target!==this.uiDialog[0]||!e.shiftKey||(n.focus(1),e.preventDefault()):(s.focus(1),e.preventDefault())}},mousedown:function(t){this._moveToTop(t)&&this._focusTabbable()}}),this.element.find("[aria-describedby]").length||this.uiDialog.attr({"aria-describedby":this.element.uniqueId().attr("id")})},_createTitlebar:function(){var e;this.uiDialogTitlebar=t("<div>").addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(this.uiDialog),this._on(this.uiDialogTitlebar,{mousedown:function(e){t(e.target).closest(".ui-dialog-titlebar-close")||this.uiDialog.focus()}}),this.uiDialogTitlebarClose=t("<button type='button'></button>").button({label:this.options.closeText,icons:{primary:"ui-icon-closethick"},text:!1}).addClass("ui-dialog-titlebar-close").appendTo(this.uiDialogTitlebar),this._on(this.uiDialogTitlebarClose,{click:function(t){t.preventDefault(),this.close(t)}}),e=t("<span>").uniqueId().addClass("ui-dialog-title").prependTo(this.uiDialogTitlebar),this._title(e),this.uiDialog.attr({"aria-labelledby":e.attr("id")})},_title:function(t){this.options.title||t.html("&#160;"),t.text(this.options.title)},_createButtonPane:function(){this.uiDialogButtonPane=t("<div>").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),this.uiButtonSet=t("<div>").addClass("ui-dialog-buttonset").appendTo(this.uiDialogButtonPane),this._createButtons()},_createButtons:function(){var e=this,i=this.options.buttons;return this.uiDialogButtonPane.remove(),this.uiButtonSet.empty(),t.isEmptyObject(i)||t.isArray(i)&&!i.length?(this.uiDialog.removeClass("ui-dialog-buttons"),undefined):(t.each(i,function(i,s){var n,o;s=t.isFunction(s)?{click:s,text:i}:s,s=t.extend({type:"button"},s),n=s.click,s.click=function(){n.apply(e.element[0],arguments)},o={icons:s.icons,text:s.showText},delete s.icons,delete s.showText,t("<button></button>",s).button(o).appendTo(e.uiButtonSet)}),this.uiDialog.addClass("ui-dialog-buttons"),this.uiDialogButtonPane.appendTo(this.uiDialog),undefined)},_makeDraggable:function(){function e(t){return{position:t.position,offset:t.offset}}var i=this,s=this.options;this.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(s,n){t(this).addClass("ui-dialog-dragging"),i._blockFrames(),i._trigger("dragStart",s,e(n))},drag:function(t,s){i._trigger("drag",t,e(s))},stop:function(n,o){s.position=[o.position.left-i.document.scrollLeft(),o.position.top-i.document.scrollTop()],t(this).removeClass("ui-dialog-dragging"),i._unblockFrames(),i._trigger("dragStop",n,e(o))}})},_makeResizable:function(){function e(t){return{originalPosition:t.originalPosition,originalSize:t.originalSize,position:t.position,size:t.size}}var i=this,s=this.options,n=s.resizable,o=this.uiDialog.css("position"),a="string"==typeof n?n:"n,e,s,w,se,sw,ne,nw";
+this.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:this.element,maxWidth:s.maxWidth,maxHeight:s.maxHeight,minWidth:s.minWidth,minHeight:this._minHeight(),handles:a,start:function(s,n){t(this).addClass("ui-dialog-resizing"),i._blockFrames(),i._trigger("resizeStart",s,e(n))},resize:function(t,s){i._trigger("resize",t,e(s))},stop:function(n,o){s.height=t(this).height(),s.width=t(this).width(),t(this).removeClass("ui-dialog-resizing"),i._unblockFrames(),i._trigger("resizeStop",n,e(o))}}).css("position",o)},_minHeight:function(){var t=this.options;return"auto"===t.height?t.minHeight:Math.min(t.minHeight,t.height)},_position:function(){var t=this.uiDialog.is(":visible");t||this.uiDialog.show(),this.uiDialog.position(this.options.position),t||this.uiDialog.hide()},_setOptions:function(s){var n=this,o=!1,a={};t.each(s,function(t,s){n._setOption(t,s),t in e&&(o=!0),t in i&&(a[t]=s)}),o&&(this._size(),this._position()),this.uiDialog.is(":data(ui-resizable)")&&this.uiDialog.resizable("option",a)},_setOption:function(t,e){var i,s,n=this.uiDialog;"dialogClass"===t&&n.removeClass(this.options.dialogClass).addClass(e),"disabled"!==t&&(this._super(t,e),"appendTo"===t&&this.uiDialog.appendTo(this._appendTo()),"buttons"===t&&this._createButtons(),"closeText"===t&&this.uiDialogTitlebarClose.button({label:""+e}),"draggable"===t&&(i=n.is(":data(ui-draggable)"),i&&!e&&n.draggable("destroy"),!i&&e&&this._makeDraggable()),"position"===t&&this._position(),"resizable"===t&&(s=n.is(":data(ui-resizable)"),s&&!e&&n.resizable("destroy"),s&&"string"==typeof e&&n.resizable("option","handles",e),s||e===!1||this._makeResizable()),"title"===t&&this._title(this.uiDialogTitlebar.find(".ui-dialog-title")))},_size:function(){var t,e,i,s=this.options;this.element.show().css({width:"auto",minHeight:0,maxHeight:"none",height:0}),s.minWidth>s.width&&(s.width=s.minWidth),t=this.uiDialog.css({height:"auto",width:s.width}).outerHeight(),e=Math.max(0,s.minHeight-t),i="number"==typeof s.maxHeight?Math.max(0,s.maxHeight-t):"none","auto"===s.height?this.element.css({minHeight:e,maxHeight:i,height:"auto"}):this.element.height(Math.max(0,s.height-t)),this.uiDialog.is(":data(ui-resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())},_blockFrames:function(){this.iframeBlocks=this.document.find("iframe").map(function(){var e=t(this);return t("<div>").css({position:"absolute",width:e.outerWidth(),height:e.outerHeight()}).appendTo(e.parent()).offset(e.offset())[0]})},_unblockFrames:function(){this.iframeBlocks&&(this.iframeBlocks.remove(),delete this.iframeBlocks)},_allowInteraction:function(e){return t(e.target).closest(".ui-dialog").length?!0:!!t(e.target).closest(".ui-datepicker").length},_createOverlay:function(){if(this.options.modal){var e=this,i=this.widgetFullName;t.ui.dialog.overlayInstances||this._delay(function(){t.ui.dialog.overlayInstances&&this.document.bind("focusin.dialog",function(s){e._allowInteraction(s)||(s.preventDefault(),t(".ui-dialog:visible:last .ui-dialog-content").data(i)._focusTabbable())})}),this.overlay=t("<div>").addClass("ui-widget-overlay ui-front").appendTo(this._appendTo()),this._on(this.overlay,{mousedown:"_keepFocus"}),t.ui.dialog.overlayInstances++}},_destroyOverlay:function(){this.options.modal&&this.overlay&&(t.ui.dialog.overlayInstances--,t.ui.dialog.overlayInstances||this.document.unbind("focusin.dialog"),this.overlay.remove(),this.overlay=null)}}),t.ui.dialog.overlayInstances=0,t.uiBackCompat!==!1&&t.widget("ui.dialog",t.ui.dialog,{_position:function(){var e,i=this.options.position,s=[],n=[0,0];i?(("string"==typeof i||"object"==typeof i&&"0"in i)&&(s=i.split?i.split(" "):[i[0],i[1]],1===s.length&&(s[1]=s[0]),t.each(["left","top"],function(t,e){+s[t]===s[t]&&(n[t]=s[t],s[t]=e)}),i={my:s[0]+(0>n[0]?n[0]:"+"+n[0])+" "+s[1]+(0>n[1]?n[1]:"+"+n[1]),at:s.join(" ")}),i=t.extend({},t.ui.dialog.prototype.options.position,i)):i=t.ui.dialog.prototype.options.position,e=this.uiDialog.is(":visible"),e||this.uiDialog.show(),this.uiDialog.position(i),e||this.uiDialog.hide()}})}(jQuery),function(t){var e=/up|down|vertical/,i=/up|left|vertical|horizontal/;t.effects.effect.blind=function(s,n){var o,a,r,h=t(this),l=["position","top","bottom","left","right","height","width"],c=t.effects.setMode(h,s.mode||"hide"),u=s.direction||"up",d=e.test(u),p=d?"height":"width",f=d?"top":"left",g=i.test(u),m={},v="show"===c;h.parent().is(".ui-effects-wrapper")?t.effects.save(h.parent(),l):t.effects.save(h,l),h.show(),o=t.effects.createWrapper(h).css({overflow:"hidden"}),a=o[p](),r=parseFloat(o.css(f))||0,m[p]=v?a:0,g||(h.css(d?"bottom":"right",0).css(d?"top":"left","auto").css({position:"absolute"}),m[f]=v?r:a+r),v&&(o.css(p,0),g||o.css(f,r+a)),o.animate(m,{duration:s.duration,easing:s.easing,queue:!1,complete:function(){"hide"===c&&h.hide(),t.effects.restore(h,l),t.effects.removeWrapper(h),n()}})}}(jQuery),function(t){t.effects.effect.bounce=function(e,i){var s,n,o,a=t(this),r=["position","top","bottom","left","right","height","width"],h=t.effects.setMode(a,e.mode||"effect"),l="hide"===h,c="show"===h,u=e.direction||"up",d=e.distance,p=e.times||5,f=2*p+(c||l?1:0),g=e.duration/f,m=e.easing,v="up"===u||"down"===u?"top":"left",_="up"===u||"left"===u,b=a.queue(),y=b.length;for((c||l)&&r.push("opacity"),t.effects.save(a,r),a.show(),t.effects.createWrapper(a),d||(d=a["top"===v?"outerHeight":"outerWidth"]()/3),c&&(o={opacity:1},o[v]=0,a.css("opacity",0).css(v,_?2*-d:2*d).animate(o,g,m)),l&&(d/=Math.pow(2,p-1)),o={},o[v]=0,s=0;p>s;s++)n={},n[v]=(_?"-=":"+=")+d,a.animate(n,g,m).animate(o,g,m),d=l?2*d:d/2;l&&(n={opacity:0},n[v]=(_?"-=":"+=")+d,a.animate(n,g,m)),a.queue(function(){l&&a.hide(),t.effects.restore(a,r),t.effects.removeWrapper(a),i()}),y>1&&b.splice.apply(b,[1,0].concat(b.splice(y,f+1))),a.dequeue()}}(jQuery),function(t){t.effects.effect.clip=function(e,i){var s,n,o,a=t(this),r=["position","top","bottom","left","right","height","width"],h=t.effects.setMode(a,e.mode||"hide"),l="show"===h,c=e.direction||"vertical",u="vertical"===c,d=u?"height":"width",p=u?"top":"left",f={};t.effects.save(a,r),a.show(),s=t.effects.createWrapper(a).css({overflow:"hidden"}),n="IMG"===a[0].tagName?s:a,o=n[d](),l&&(n.css(d,0),n.css(p,o/2)),f[d]=l?o:0,f[p]=l?0:o/2,n.animate(f,{queue:!1,duration:e.duration,easing:e.easing,complete:function(){l||a.hide(),t.effects.restore(a,r),t.effects.removeWrapper(a),i()}})}}(jQuery),function(t){t.effects.effect.drop=function(e,i){var s,n=t(this),o=["position","top","bottom","left","right","opacity","height","width"],a=t.effects.setMode(n,e.mode||"hide"),r="show"===a,h=e.direction||"left",l="up"===h||"down"===h?"top":"left",c="up"===h||"left"===h?"pos":"neg",u={opacity:r?1:0};t.effects.save(n,o),n.show(),t.effects.createWrapper(n),s=e.distance||n["top"===l?"outerHeight":"outerWidth"](!0)/2,r&&n.css("opacity",0).css(l,"pos"===c?-s:s),u[l]=(r?"pos"===c?"+=":"-=":"pos"===c?"-=":"+=")+s,n.animate(u,{queue:!1,duration:e.duration,easing:e.easing,complete:function(){"hide"===a&&n.hide(),t.effects.restore(n,o),t.effects.removeWrapper(n),i()}})}}(jQuery),function(t){t.effects.effect.explode=function(e,i){function s(){b.push(this),b.length===u*d&&n()}function n(){p.css({visibility:"visible"}),t(b).remove(),g||p.hide(),i()}var o,a,r,h,l,c,u=e.pieces?Math.round(Math.sqrt(e.pieces)):3,d=u,p=t(this),f=t.effects.setMode(p,e.mode||"hide"),g="show"===f,m=p.show().css("visibility","hidden").offset(),v=Math.ceil(p.outerWidth()/d),_=Math.ceil(p.outerHeight()/u),b=[];for(o=0;u>o;o++)for(h=m.top+o*_,c=o-(u-1)/2,a=0;d>a;a++)r=m.left+a*v,l=a-(d-1)/2,p.clone().appendTo("body").wrap("<div></div>").css({position:"absolute",visibility:"visible",left:-a*v,top:-o*_}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:v,height:_,left:r+(g?l*v:0),top:h+(g?c*_:0),opacity:g?0:1}).animate({left:r+(g?0:l*v),top:h+(g?0:c*_),opacity:g?1:0},e.duration||500,e.easing,s)}}(jQuery),function(t){t.effects.effect.fade=function(e,i){var s=t(this),n=t.effects.setMode(s,e.mode||"toggle");s.animate({opacity:n},{queue:!1,duration:e.duration,easing:e.easing,complete:i})}}(jQuery),function(t){t.effects.effect.fold=function(e,i){var s,n,o=t(this),a=["position","top","bottom","left","right","height","width"],r=t.effects.setMode(o,e.mode||"hide"),h="show"===r,l="hide"===r,c=e.size||15,u=/([0-9]+)%/.exec(c),d=!!e.horizFirst,p=h!==d,f=p?["width","height"]:["height","width"],g=e.duration/2,m={},v={};t.effects.save(o,a),o.show(),s=t.effects.createWrapper(o).css({overflow:"hidden"}),n=p?[s.width(),s.height()]:[s.height(),s.width()],u&&(c=parseInt(u[1],10)/100*n[l?0:1]),h&&s.css(d?{height:0,width:c}:{height:c,width:0}),m[f[0]]=h?n[0]:c,v[f[1]]=h?n[1]:0,s.animate(m,g,e.easing).animate(v,g,e.easing,function(){l&&o.hide(),t.effects.restore(o,a),t.effects.removeWrapper(o),i()})}}(jQuery),function(t){t.effects.effect.highlight=function(e,i){var s=t(this),n=["backgroundImage","backgroundColor","opacity"],o=t.effects.setMode(s,e.mode||"show"),a={backgroundColor:s.css("backgroundColor")};"hide"===o&&(a.opacity=0),t.effects.save(s,n),s.show().css({backgroundImage:"none",backgroundColor:e.color||"#ffff99"}).animate(a,{queue:!1,duration:e.duration,easing:e.easing,complete:function(){"hide"===o&&s.hide(),t.effects.restore(s,n),i()}})}}(jQuery),function(t){t.effects.effect.pulsate=function(e,i){var s,n=t(this),o=t.effects.setMode(n,e.mode||"show"),a="show"===o,r="hide"===o,h=a||"hide"===o,l=2*(e.times||5)+(h?1:0),c=e.duration/l,u=0,d=n.queue(),p=d.length;for((a||!n.is(":visible"))&&(n.css("opacity",0).show(),u=1),s=1;l>s;s++)n.animate({opacity:u},c,e.easing),u=1-u;n.animate({opacity:u},c,e.easing),n.queue(function(){r&&n.hide(),i()}),p>1&&d.splice.apply(d,[1,0].concat(d.splice(p,l+1))),n.dequeue()}}(jQuery),function(t){t.effects.effect.puff=function(e,i){var s=t(this),n=t.effects.setMode(s,e.mode||"hide"),o="hide"===n,a=parseInt(e.percent,10)||150,r=a/100,h={height:s.height(),width:s.width(),outerHeight:s.outerHeight(),outerWidth:s.outerWidth()};t.extend(e,{effect:"scale",queue:!1,fade:!0,mode:n,complete:i,percent:o?a:100,from:o?h:{height:h.height*r,width:h.width*r,outerHeight:h.outerHeight*r,outerWidth:h.outerWidth*r}}),s.effect(e)},t.effects.effect.scale=function(e,i){var s=t(this),n=t.extend(!0,{},e),o=t.effects.setMode(s,e.mode||"effect"),a=parseInt(e.percent,10)||(0===parseInt(e.percent,10)?0:"hide"===o?0:100),r=e.direction||"both",h=e.origin,l={height:s.height(),width:s.width(),outerHeight:s.outerHeight(),outerWidth:s.outerWidth()},c={y:"horizontal"!==r?a/100:1,x:"vertical"!==r?a/100:1};n.effect="size",n.queue=!1,n.complete=i,"effect"!==o&&(n.origin=h||["middle","center"],n.restore=!0),n.from=e.from||("show"===o?{height:0,width:0,outerHeight:0,outerWidth:0}:l),n.to={height:l.height*c.y,width:l.width*c.x,outerHeight:l.outerHeight*c.y,outerWidth:l.outerWidth*c.x},n.fade&&("show"===o&&(n.from.opacity=0,n.to.opacity=1),"hide"===o&&(n.from.opacity=1,n.to.opacity=0)),s.effect(n)},t.effects.effect.size=function(e,i){var s,n,o,a=t(this),r=["position","top","bottom","left","right","width","height","overflow","opacity"],h=["position","top","bottom","left","right","overflow","opacity"],l=["width","height","overflow"],c=["fontSize"],u=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"],d=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"],p=t.effects.setMode(a,e.mode||"effect"),f=e.restore||"effect"!==p,g=e.scale||"both",m=e.origin||["middle","center"],v=a.css("position"),_=f?r:h,b={height:0,width:0,outerHeight:0,outerWidth:0};"show"===p&&a.show(),s={height:a.height(),width:a.width(),outerHeight:a.outerHeight(),outerWidth:a.outerWidth()},"toggle"===e.mode&&"show"===p?(a.from=e.to||b,a.to=e.from||s):(a.from=e.from||("show"===p?b:s),a.to=e.to||("hide"===p?b:s)),o={from:{y:a.from.height/s.height,x:a.from.width/s.width},to:{y:a.to.height/s.height,x:a.to.width/s.width}},("box"===g||"both"===g)&&(o.from.y!==o.to.y&&(_=_.concat(u),a.from=t.effects.setTransition(a,u,o.from.y,a.from),a.to=t.effects.setTransition(a,u,o.to.y,a.to)),o.from.x!==o.to.x&&(_=_.concat(d),a.from=t.effects.setTransition(a,d,o.from.x,a.from),a.to=t.effects.setTransition(a,d,o.to.x,a.to))),("content"===g||"both"===g)&&o.from.y!==o.to.y&&(_=_.concat(c).concat(l),a.from=t.effects.setTransition(a,c,o.from.y,a.from),a.to=t.effects.setTransition(a,c,o.to.y,a.to)),t.effects.save(a,_),a.show(),t.effects.createWrapper(a),a.css("overflow","hidden").css(a.from),m&&(n=t.effects.getBaseline(m,s),a.from.top=(s.outerHeight-a.outerHeight())*n.y,a.from.left=(s.outerWidth-a.outerWidth())*n.x,a.to.top=(s.outerHeight-a.to.outerHeight)*n.y,a.to.left=(s.outerWidth-a.to.outerWidth)*n.x),a.css(a.from),("content"===g||"both"===g)&&(u=u.concat(["marginTop","marginBottom"]).concat(c),d=d.concat(["marginLeft","marginRight"]),l=r.concat(u).concat(d),a.find("*[width]").each(function(){var i=t(this),s={height:i.height(),width:i.width(),outerHeight:i.outerHeight(),outerWidth:i.outerWidth()};f&&t.effects.save(i,l),i.from={height:s.height*o.from.y,width:s.width*o.from.x,outerHeight:s.outerHeight*o.from.y,outerWidth:s.outerWidth*o.from.x},i.to={height:s.height*o.to.y,width:s.width*o.to.x,outerHeight:s.height*o.to.y,outerWidth:s.width*o.to.x},o.from.y!==o.to.y&&(i.from=t.effects.setTransition(i,u,o.from.y,i.from),i.to=t.effects.setTransition(i,u,o.to.y,i.to)),o.from.x!==o.to.x&&(i.from=t.effects.setTransition(i,d,o.from.x,i.from),i.to=t.effects.setTransition(i,d,o.to.x,i.to)),i.css(i.from),i.animate(i.to,e.duration,e.easing,function(){f&&t.effects.restore(i,l)})})),a.animate(a.to,{queue:!1,duration:e.duration,easing:e.easing,complete:function(){0===a.to.opacity&&a.css("opacity",a.from.opacity),"hide"===p&&a.hide(),t.effects.restore(a,_),f||("static"===v?a.css({position:"relative",top:a.to.top,left:a.to.left}):t.each(["top","left"],function(t,e){a.css(e,function(e,i){var s=parseInt(i,10),n=t?a.to.left:a.to.top;return"auto"===i?n+"px":s+n+"px"})})),t.effects.removeWrapper(a),i()}})}}(jQuery),function(t){t.effects.effect.shake=function(e,i){var s,n=t(this),o=["position","top","bottom","left","right","height","width"],a=t.effects.setMode(n,e.mode||"effect"),r=e.direction||"left",h=e.distance||20,l=e.times||3,c=2*l+1,u=Math.round(e.duration/c),d="up"===r||"down"===r?"top":"left",p="up"===r||"left"===r,f={},g={},m={},v=n.queue(),_=v.length;for(t.effects.save(n,o),n.show(),t.effects.createWrapper(n),f[d]=(p?"-=":"+=")+h,g[d]=(p?"+=":"-=")+2*h,m[d]=(p?"-=":"+=")+2*h,n.animate(f,u,e.easing),s=1;l>s;s++)n.animate(g,u,e.easing).animate(m,u,e.easing);n.animate(g,u,e.easing).animate(f,u/2,e.easing).queue(function(){"hide"===a&&n.hide(),t.effects.restore(n,o),t.effects.removeWrapper(n),i()}),_>1&&v.splice.apply(v,[1,0].concat(v.splice(_,c+1))),n.dequeue()}}(jQuery),function(t){t.effects.effect.slide=function(e,i){var s,n=t(this),o=["position","top","bottom","left","right","width","height"],a=t.effects.setMode(n,e.mode||"show"),r="show"===a,h=e.direction||"left",l="up"===h||"down"===h?"top":"left",c="up"===h||"left"===h,u={};t.effects.save(n,o),n.show(),s=e.distance||n["top"===l?"outerHeight":"outerWidth"](!0),t.effects.createWrapper(n).css({overflow:"hidden"}),r&&n.css(l,c?isNaN(s)?"-"+s:-s:s),u[l]=(r?c?"+=":"-=":c?"-=":"+=")+s,n.animate(u,{queue:!1,duration:e.duration,easing:e.easing,complete:function(){"hide"===a&&n.hide(),t.effects.restore(n,o),t.effects.removeWrapper(n),i()}})}}(jQuery),function(t){t.effects.effect.transfer=function(e,i){var s=t(this),n=t(e.to),o="fixed"===n.css("position"),a=t("body"),r=o?a.scrollTop():0,h=o?a.scrollLeft():0,l=n.offset(),c={top:l.top-r,left:l.left-h,height:n.innerHeight(),width:n.innerWidth()},u=s.offset(),d=t("<div class='ui-effects-transfer'></div>").appendTo(document.body).addClass(e.className).css({top:u.top-r,left:u.left-h,height:s.innerHeight(),width:s.innerWidth(),position:o?"fixed":"absolute"}).animate(c,e.duration,e.easing,function(){d.remove(),i()})}}(jQuery),function(t){t.widget("ui.menu",{version:"1.10.4",defaultElement:"<ul>",delay:300,options:{icons:{submenu:"ui-icon-carat-1-e"},menus:"ul",position:{my:"left top",at:"right top"},role:"menu",blur:null,focus:null,select:null},_create:function(){this.activeMenu=this.element,this.mouseHandled=!1,this.element.uniqueId().addClass("ui-menu ui-widget ui-widget-content ui-corner-all").toggleClass("ui-menu-icons",!!this.element.find(".ui-icon").length).attr({role:this.options.role,tabIndex:0}).bind("click"+this.eventNamespace,t.proxy(function(t){this.options.disabled&&t.preventDefault()},this)),this.options.disabled&&this.element.addClass("ui-state-disabled").attr("aria-disabled","true"),this._on({"mousedown .ui-menu-item > a":function(t){t.preventDefault()},"click .ui-state-disabled > a":function(t){t.preventDefault()},"click .ui-menu-item:has(a)":function(e){var i=t(e.target).closest(".ui-menu-item");!this.mouseHandled&&i.not(".ui-state-disabled").length&&(this.select(e),e.isPropagationStopped()||(this.mouseHandled=!0),i.has(".ui-menu").length?this.expand(e):!this.element.is(":focus")&&t(this.document[0].activeElement).closest(".ui-menu").length&&(this.element.trigger("focus",[!0]),this.active&&1===this.active.parents(".ui-menu").length&&clearTimeout(this.timer)))},"mouseenter .ui-menu-item":function(e){var i=t(e.currentTarget);i.siblings().children(".ui-state-active").removeClass("ui-state-active"),this.focus(e,i)},mouseleave:"collapseAll","mouseleave .ui-menu":"collapseAll",focus:function(t,e){var i=this.active||this.element.children(".ui-menu-item").eq(0);e||this.focus(t,i)},blur:function(e){this._delay(function(){t.contains(this.element[0],this.document[0].activeElement)||this.collapseAll(e)})},keydown:"_keydown"}),this.refresh(),this._on(this.document,{click:function(e){t(e.target).closest(".ui-menu").length||this.collapseAll(e),this.mouseHandled=!1}})},_destroy:function(){this.element.removeAttr("aria-activedescendant").find(".ui-menu").addBack().removeClass("ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons").removeAttr("role").removeAttr("tabIndex").removeAttr("aria-labelledby").removeAttr("aria-expanded").removeAttr("aria-hidden").removeAttr("aria-disabled").removeUniqueId().show(),this.element.find(".ui-menu-item").removeClass("ui-menu-item").removeAttr("role").removeAttr("aria-disabled").children("a").removeUniqueId().removeClass("ui-corner-all ui-state-hover").removeAttr("tabIndex").removeAttr("role").removeAttr("aria-haspopup").children().each(function(){var e=t(this);e.data("ui-menu-submenu-carat")&&e.remove()}),this.element.find(".ui-menu-divider").removeClass("ui-menu-divider ui-widget-content")},_keydown:function(e){function i(t){return t.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}var s,n,o,a,r,h=!0;switch(e.keyCode){case t.ui.keyCode.PAGE_UP:this.previousPage(e);break;case t.ui.keyCode.PAGE_DOWN:this.nextPage(e);break;case t.ui.keyCode.HOME:this._move("first","first",e);break;case t.ui.keyCode.END:this._move("last","last",e);break;case t.ui.keyCode.UP:this.previous(e);break;case t.ui.keyCode.DOWN:this.next(e);break;case t.ui.keyCode.LEFT:this.collapse(e);break;case t.ui.keyCode.RIGHT:this.active&&!this.active.is(".ui-state-disabled")&&this.expand(e);break;case t.ui.keyCode.ENTER:case t.ui.keyCode.SPACE:this._activate(e);break;case t.ui.keyCode.ESCAPE:this.collapse(e);break;default:h=!1,n=this.previousFilter||"",o=String.fromCharCode(e.keyCode),a=!1,clearTimeout(this.filterTimer),o===n?a=!0:o=n+o,r=RegExp("^"+i(o),"i"),s=this.activeMenu.children(".ui-menu-item").filter(function(){return r.test(t(this).children("a").text())}),s=a&&-1!==s.index(this.active.next())?this.active.nextAll(".ui-menu-item"):s,s.length||(o=String.fromCharCode(e.keyCode),r=RegExp("^"+i(o),"i"),s=this.activeMenu.children(".ui-menu-item").filter(function(){return r.test(t(this).children("a").text())})),s.length?(this.focus(e,s),s.length>1?(this.previousFilter=o,this.filterTimer=this._delay(function(){delete this.previousFilter},1e3)):delete this.previousFilter):delete this.previousFilter}h&&e.preventDefault()},_activate:function(t){this.active.is(".ui-state-disabled")||(this.active.children("a[aria-haspopup='true']").length?this.expand(t):this.select(t))},refresh:function(){var e,i=this.options.icons.submenu,s=this.element.find(this.options.menus);this.element.toggleClass("ui-menu-icons",!!this.element.find(".ui-icon").length),s.filter(":not(.ui-menu)").addClass("ui-menu ui-widget ui-widget-content ui-corner-all").hide().attr({role:this.options.role,"aria-hidden":"true","aria-expanded":"false"}).each(function(){var e=t(this),s=e.prev("a"),n=t("<span>").addClass("ui-menu-icon ui-icon "+i).data("ui-menu-submenu-carat",!0);s.attr("aria-haspopup","true").prepend(n),e.attr("aria-labelledby",s.attr("id"))}),e=s.add(this.element),e.children(":not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role","presentation").children("a").uniqueId().addClass("ui-corner-all").attr({tabIndex:-1,role:this._itemRole()}),e.children(":not(.ui-menu-item)").each(function(){var e=t(this);/[^\-\u2014\u2013\s]/.test(e.text())||e.addClass("ui-widget-content ui-menu-divider")}),e.children(".ui-state-disabled").attr("aria-disabled","true"),this.active&&!t.contains(this.element[0],this.active[0])&&this.blur()},_itemRole:function(){return{menu:"menuitem",listbox:"option"}[this.options.role]},_setOption:function(t,e){"icons"===t&&this.element.find(".ui-menu-icon").removeClass(this.options.icons.submenu).addClass(e.submenu),this._super(t,e)},focus:function(t,e){var i,s;this.blur(t,t&&"focus"===t.type),this._scrollIntoView(e),this.active=e.first(),s=this.active.children("a").addClass("ui-state-focus"),this.options.role&&this.element.attr("aria-activedescendant",s.attr("id")),this.active.parent().closest(".ui-menu-item").children("a:first").addClass("ui-state-active"),t&&"keydown"===t.type?this._close():this.timer=this._delay(function(){this._close()},this.delay),i=e.children(".ui-menu"),i.length&&t&&/^mouse/.test(t.type)&&this._startOpening(i),this.activeMenu=e.parent(),this._trigger("focus",t,{item:e})},_scrollIntoView:function(e){var i,s,n,o,a,r;this._hasScroll()&&(i=parseFloat(t.css(this.activeMenu[0],"borderTopWidth"))||0,s=parseFloat(t.css(this.activeMenu[0],"paddingTop"))||0,n=e.offset().top-this.activeMenu.offset().top-i-s,o=this.activeMenu.scrollTop(),a=this.activeMenu.height(),r=e.height(),0>n?this.activeMenu.scrollTop(o+n):n+r>a&&this.activeMenu.scrollTop(o+n-a+r))},blur:function(t,e){e||clearTimeout(this.timer),this.active&&(this.active.children("a").removeClass("ui-state-focus"),this.active=null,this._trigger("blur",t,{item:this.active}))},_startOpening:function(t){clearTimeout(this.timer),"true"===t.attr("aria-hidden")&&(this.timer=this._delay(function(){this._close(),this._open(t)},this.delay))},_open:function(e){var i=t.extend({of:this.active},this.options.position);clearTimeout(this.timer),this.element.find(".ui-menu").not(e.parents(".ui-menu")).hide().attr("aria-hidden","true"),e.show().removeAttr("aria-hidden").attr("aria-expanded","true").position(i)},collapseAll:function(e,i){clearTimeout(this.timer),this.timer=this._delay(function(){var s=i?this.element:t(e&&e.target).closest(this.element.find(".ui-menu"));s.length||(s=this.element),this._close(s),this.blur(e),this.activeMenu=s},this.delay)},_close:function(t){t||(t=this.active?this.active.parent():this.element),t.find(".ui-menu").hide().attr("aria-hidden","true").attr("aria-expanded","false").end().find("a.ui-state-active").removeClass("ui-state-active")},collapse:function(t){var e=this.active&&this.active.parent().closest(".ui-menu-item",this.element);e&&e.length&&(this._close(),this.focus(t,e))},expand:function(t){var e=this.active&&this.active.children(".ui-menu ").children(".ui-menu-item").first();e&&e.length&&(this._open(e.parent()),this._delay(function(){this.focus(t,e)}))},next:function(t){this._move("next","first",t)},previous:function(t){this._move("prev","last",t)},isFirstItem:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},isLastItem:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},_move:function(t,e,i){var s;this.active&&(s="first"===t||"last"===t?this.active["first"===t?"prevAll":"nextAll"](".ui-menu-item").eq(-1):this.active[t+"All"](".ui-menu-item").eq(0)),s&&s.length&&this.active||(s=this.activeMenu.children(".ui-menu-item")[e]()),this.focus(i,s)},nextPage:function(e){var i,s,n;return this.active?(this.isLastItem()||(this._hasScroll()?(s=this.active.offset().top,n=this.element.height(),this.active.nextAll(".ui-menu-item").each(function(){return i=t(this),0>i.offset().top-s-n}),this.focus(e,i)):this.focus(e,this.activeMenu.children(".ui-menu-item")[this.active?"last":"first"]())),undefined):(this.next(e),undefined)},previousPage:function(e){var i,s,n;return this.active?(this.isFirstItem()||(this._hasScroll()?(s=this.active.offset().top,n=this.element.height(),this.active.prevAll(".ui-menu-item").each(function(){return i=t(this),i.offset().top-s+n>0}),this.focus(e,i)):this.focus(e,this.activeMenu.children(".ui-menu-item").first())),undefined):(this.next(e),undefined)},_hasScroll:function(){return this.element.outerHeight()<this.element.prop("scrollHeight")},select:function(e){this.active=this.active||t(e.target).closest(".ui-menu-item");var i={item:this.active};this.active.has(".ui-menu").length||this.collapseAll(e,!0),this._trigger("select",e,i)}})}(jQuery),function(t,e){function i(t,e,i){return[parseFloat(t[0])*(p.test(t[0])?e/100:1),parseFloat(t[1])*(p.test(t[1])?i/100:1)]}function s(e,i){return parseInt(t.css(e,i),10)||0}function n(e){var i=e[0];return 9===i.nodeType?{width:e.width(),height:e.height(),offset:{top:0,left:0}}:t.isWindow(i)?{width:e.width(),height:e.height(),offset:{top:e.scrollTop(),left:e.scrollLeft()}}:i.preventDefault?{width:0,height:0,offset:{top:i.pageY,left:i.pageX}}:{width:e.outerWidth(),height:e.outerHeight(),offset:e.offset()}}t.ui=t.ui||{};var o,a=Math.max,r=Math.abs,h=Math.round,l=/left|center|right/,c=/top|center|bottom/,u=/[\+\-]\d+(\.[\d]+)?%?/,d=/^\w+/,p=/%$/,f=t.fn.position;t.position={scrollbarWidth:function(){if(o!==e)return o;var i,s,n=t("<div style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>"),a=n.children()[0];return t("body").append(n),i=a.offsetWidth,n.css("overflow","scroll"),s=a.offsetWidth,i===s&&(s=n[0].clientWidth),n.remove(),o=i-s},getScrollInfo:function(e){var i=e.isWindow||e.isDocument?"":e.element.css("overflow-x"),s=e.isWindow||e.isDocument?"":e.element.css("overflow-y"),n="scroll"===i||"auto"===i&&e.width<e.element[0].scrollWidth,o="scroll"===s||"auto"===s&&e.height<e.element[0].scrollHeight;return{width:o?t.position.scrollbarWidth():0,height:n?t.position.scrollbarWidth():0}},getWithinInfo:function(e){var i=t(e||window),s=t.isWindow(i[0]),n=!!i[0]&&9===i[0].nodeType;return{element:i,isWindow:s,isDocument:n,offset:i.offset()||{left:0,top:0},scrollLeft:i.scrollLeft(),scrollTop:i.scrollTop(),width:s?i.width():i.outerWidth(),height:s?i.height():i.outerHeight()}}},t.fn.position=function(e){if(!e||!e.of)return f.apply(this,arguments);e=t.extend({},e);var o,p,g,m,v,_,b=t(e.of),y=t.position.getWithinInfo(e.within),w=t.position.getScrollInfo(y),x=(e.collision||"flip").split(" "),k={};return _=n(b),b[0].preventDefault&&(e.at="left top"),p=_.width,g=_.height,m=_.offset,v=t.extend({},m),t.each(["my","at"],function(){var t,i,s=(e[this]||"").split(" ");1===s.length&&(s=l.test(s[0])?s.concat(["center"]):c.test(s[0])?["center"].concat(s):["center","center"]),s[0]=l.test(s[0])?s[0]:"center",s[1]=c.test(s[1])?s[1]:"center",t=u.exec(s[0]),i=u.exec(s[1]),k[this]=[t?t[0]:0,i?i[0]:0],e[this]=[d.exec(s[0])[0],d.exec(s[1])[0]]}),1===x.length&&(x[1]=x[0]),"right"===e.at[0]?v.left+=p:"center"===e.at[0]&&(v.left+=p/2),"bottom"===e.at[1]?v.top+=g:"center"===e.at[1]&&(v.top+=g/2),o=i(k.at,p,g),v.left+=o[0],v.top+=o[1],this.each(function(){var n,l,c=t(this),u=c.outerWidth(),d=c.outerHeight(),f=s(this,"marginLeft"),_=s(this,"marginTop"),D=u+f+s(this,"marginRight")+w.width,C=d+_+s(this,"marginBottom")+w.height,I=t.extend({},v),P=i(k.my,c.outerWidth(),c.outerHeight());"right"===e.my[0]?I.left-=u:"center"===e.my[0]&&(I.left-=u/2),"bottom"===e.my[1]?I.top-=d:"center"===e.my[1]&&(I.top-=d/2),I.left+=P[0],I.top+=P[1],t.support.offsetFractions||(I.left=h(I.left),I.top=h(I.top)),n={marginLeft:f,marginTop:_},t.each(["left","top"],function(i,s){t.ui.position[x[i]]&&t.ui.position[x[i]][s](I,{targetWidth:p,targetHeight:g,elemWidth:u,elemHeight:d,collisionPosition:n,collisionWidth:D,collisionHeight:C,offset:[o[0]+P[0],o[1]+P[1]],my:e.my,at:e.at,within:y,elem:c})}),e.using&&(l=function(t){var i=m.left-I.left,s=i+p-u,n=m.top-I.top,o=n+g-d,h={target:{element:b,left:m.left,top:m.top,width:p,height:g},element:{element:c,left:I.left,top:I.top,width:u,height:d},horizontal:0>s?"left":i>0?"right":"center",vertical:0>o?"top":n>0?"bottom":"middle"};u>p&&p>r(i+s)&&(h.horizontal="center"),d>g&&g>r(n+o)&&(h.vertical="middle"),h.important=a(r(i),r(s))>a(r(n),r(o))?"horizontal":"vertical",e.using.call(this,t,h)}),c.offset(t.extend(I,{using:l}))})},t.ui.position={fit:{left:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollLeft:s.offset.left,o=s.width,r=t.left-e.collisionPosition.marginLeft,h=n-r,l=r+e.collisionWidth-o-n;e.collisionWidth>o?h>0&&0>=l?(i=t.left+h+e.collisionWidth-o-n,t.left+=h-i):t.left=l>0&&0>=h?n:h>l?n+o-e.collisionWidth:n:h>0?t.left+=h:l>0?t.left-=l:t.left=a(t.left-r,t.left)},top:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollTop:s.offset.top,o=e.within.height,r=t.top-e.collisionPosition.marginTop,h=n-r,l=r+e.collisionHeight-o-n;e.collisionHeight>o?h>0&&0>=l?(i=t.top+h+e.collisionHeight-o-n,t.top+=h-i):t.top=l>0&&0>=h?n:h>l?n+o-e.collisionHeight:n:h>0?t.top+=h:l>0?t.top-=l:t.top=a(t.top-r,t.top)}},flip:{left:function(t,e){var i,s,n=e.within,o=n.offset.left+n.scrollLeft,a=n.width,h=n.isWindow?n.scrollLeft:n.offset.left,l=t.left-e.collisionPosition.marginLeft,c=l-h,u=l+e.collisionWidth-a-h,d="left"===e.my[0]?-e.elemWidth:"right"===e.my[0]?e.elemWidth:0,p="left"===e.at[0]?e.targetWidth:"right"===e.at[0]?-e.targetWidth:0,f=-2*e.offset[0];0>c?(i=t.left+d+p+f+e.collisionWidth-a-o,(0>i||r(c)>i)&&(t.left+=d+p+f)):u>0&&(s=t.left-e.collisionPosition.marginLeft+d+p+f-h,(s>0||u>r(s))&&(t.left+=d+p+f))},top:function(t,e){var i,s,n=e.within,o=n.offset.top+n.scrollTop,a=n.height,h=n.isWindow?n.scrollTop:n.offset.top,l=t.top-e.collisionPosition.marginTop,c=l-h,u=l+e.collisionHeight-a-h,d="top"===e.my[1],p=d?-e.elemHeight:"bottom"===e.my[1]?e.elemHeight:0,f="top"===e.at[1]?e.targetHeight:"bottom"===e.at[1]?-e.targetHeight:0,g=-2*e.offset[1];0>c?(s=t.top+p+f+g+e.collisionHeight-a-o,t.top+p+f+g>c&&(0>s||r(c)>s)&&(t.top+=p+f+g)):u>0&&(i=t.top-e.collisionPosition.marginTop+p+f+g-h,t.top+p+f+g>u&&(i>0||u>r(i))&&(t.top+=p+f+g))}},flipfit:{left:function(){t.ui.position.flip.left.apply(this,arguments),t.ui.position.fit.left.apply(this,arguments)},top:function(){t.ui.position.flip.top.apply(this,arguments),t.ui.position.fit.top.apply(this,arguments)}}},function(){var e,i,s,n,o,a=document.getElementsByTagName("body")[0],r=document.createElement("div");e=document.createElement(a?"div":"body"),s={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},a&&t.extend(s,{position:"absolute",left:"-1000px",top:"-1000px"});for(o in s)e.style[o]=s[o];e.appendChild(r),i=a||document.documentElement,i.insertBefore(e,i.firstChild),r.style.cssText="position: absolute; left: 10.7432222px;",n=t(r).offset().left,t.support.offsetFractions=n>10&&11>n,e.innerHTML="",i.removeChild(e)}()}(jQuery),function(t,e){t.widget("ui.progressbar",{version:"1.10.4",options:{max:100,value:0,change:null,complete:null},min:0,_create:function(){this.oldValue=this.options.value=this._constrainedValue(),this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this.min}),this.valueDiv=t("<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>").appendTo(this.element),this._refreshValue()
+},_destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.valueDiv.remove()},value:function(t){return t===e?this.options.value:(this.options.value=this._constrainedValue(t),this._refreshValue(),e)},_constrainedValue:function(t){return t===e&&(t=this.options.value),this.indeterminate=t===!1,"number"!=typeof t&&(t=0),this.indeterminate?!1:Math.min(this.options.max,Math.max(this.min,t))},_setOptions:function(t){var e=t.value;delete t.value,this._super(t),this.options.value=this._constrainedValue(e),this._refreshValue()},_setOption:function(t,e){"max"===t&&(e=Math.max(this.min,e)),this._super(t,e)},_percentage:function(){return this.indeterminate?100:100*(this.options.value-this.min)/(this.options.max-this.min)},_refreshValue:function(){var e=this.options.value,i=this._percentage();this.valueDiv.toggle(this.indeterminate||e>this.min).toggleClass("ui-corner-right",e===this.options.max).width(i.toFixed(0)+"%"),this.element.toggleClass("ui-progressbar-indeterminate",this.indeterminate),this.indeterminate?(this.element.removeAttr("aria-valuenow"),this.overlayDiv||(this.overlayDiv=t("<div class='ui-progressbar-overlay'></div>").appendTo(this.valueDiv))):(this.element.attr({"aria-valuemax":this.options.max,"aria-valuenow":e}),this.overlayDiv&&(this.overlayDiv.remove(),this.overlayDiv=null)),this.oldValue!==e&&(this.oldValue=e,this._trigger("change")),e===this.options.max&&this._trigger("complete")}})}(jQuery),function(t){var e=5;t.widget("ui.slider",t.ui.mouse,{version:"1.10.4",widgetEventPrefix:"slide",options:{animate:!1,distance:0,max:100,min:0,orientation:"horizontal",range:!1,step:1,value:0,values:null,change:null,slide:null,start:null,stop:null},_create:function(){this._keySliding=!1,this._mouseSliding=!1,this._animateOff=!0,this._handleIndex=null,this._detectOrientation(),this._mouseInit(),this.element.addClass("ui-slider ui-slider-"+this.orientation+" ui-widget"+" ui-widget-content"+" ui-corner-all"),this._refresh(),this._setOption("disabled",this.options.disabled),this._animateOff=!1},_refresh:function(){this._createRange(),this._createHandles(),this._setupEvents(),this._refreshValue()},_createHandles:function(){var e,i,s=this.options,n=this.element.find(".ui-slider-handle").addClass("ui-state-default ui-corner-all"),o="<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",a=[];for(i=s.values&&s.values.length||1,n.length>i&&(n.slice(i).remove(),n=n.slice(0,i)),e=n.length;i>e;e++)a.push(o);this.handles=n.add(t(a.join("")).appendTo(this.element)),this.handle=this.handles.eq(0),this.handles.each(function(e){t(this).data("ui-slider-handle-index",e)})},_createRange:function(){var e=this.options,i="";e.range?(e.range===!0&&(e.values?e.values.length&&2!==e.values.length?e.values=[e.values[0],e.values[0]]:t.isArray(e.values)&&(e.values=e.values.slice(0)):e.values=[this._valueMin(),this._valueMin()]),this.range&&this.range.length?this.range.removeClass("ui-slider-range-min ui-slider-range-max").css({left:"",bottom:""}):(this.range=t("<div></div>").appendTo(this.element),i="ui-slider-range ui-widget-header ui-corner-all"),this.range.addClass(i+("min"===e.range||"max"===e.range?" ui-slider-range-"+e.range:""))):(this.range&&this.range.remove(),this.range=null)},_setupEvents:function(){var t=this.handles.add(this.range).filter("a");this._off(t),this._on(t,this._handleEvents),this._hoverable(t),this._focusable(t)},_destroy:function(){this.handles.remove(),this.range&&this.range.remove(),this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-widget ui-widget-content ui-corner-all"),this._mouseDestroy()},_mouseCapture:function(e){var i,s,n,o,a,r,h,l,c=this,u=this.options;return u.disabled?!1:(this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()},this.elementOffset=this.element.offset(),i={x:e.pageX,y:e.pageY},s=this._normValueFromMouse(i),n=this._valueMax()-this._valueMin()+1,this.handles.each(function(e){var i=Math.abs(s-c.values(e));(n>i||n===i&&(e===c._lastChangedValue||c.values(e)===u.min))&&(n=i,o=t(this),a=e)}),r=this._start(e,a),r===!1?!1:(this._mouseSliding=!0,this._handleIndex=a,o.addClass("ui-state-active").focus(),h=o.offset(),l=!t(e.target).parents().addBack().is(".ui-slider-handle"),this._clickOffset=l?{left:0,top:0}:{left:e.pageX-h.left-o.width()/2,top:e.pageY-h.top-o.height()/2-(parseInt(o.css("borderTopWidth"),10)||0)-(parseInt(o.css("borderBottomWidth"),10)||0)+(parseInt(o.css("marginTop"),10)||0)},this.handles.hasClass("ui-state-hover")||this._slide(e,a,s),this._animateOff=!0,!0))},_mouseStart:function(){return!0},_mouseDrag:function(t){var e={x:t.pageX,y:t.pageY},i=this._normValueFromMouse(e);return this._slide(t,this._handleIndex,i),!1},_mouseStop:function(t){return this.handles.removeClass("ui-state-active"),this._mouseSliding=!1,this._stop(t,this._handleIndex),this._change(t,this._handleIndex),this._handleIndex=null,this._clickOffset=null,this._animateOff=!1,!1},_detectOrientation:function(){this.orientation="vertical"===this.options.orientation?"vertical":"horizontal"},_normValueFromMouse:function(t){var e,i,s,n,o;return"horizontal"===this.orientation?(e=this.elementSize.width,i=t.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)):(e=this.elementSize.height,i=t.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)),s=i/e,s>1&&(s=1),0>s&&(s=0),"vertical"===this.orientation&&(s=1-s),n=this._valueMax()-this._valueMin(),o=this._valueMin()+s*n,this._trimAlignValue(o)},_start:function(t,e){var i={handle:this.handles[e],value:this.value()};return this.options.values&&this.options.values.length&&(i.value=this.values(e),i.values=this.values()),this._trigger("start",t,i)},_slide:function(t,e,i){var s,n,o;this.options.values&&this.options.values.length?(s=this.values(e?0:1),2===this.options.values.length&&this.options.range===!0&&(0===e&&i>s||1===e&&s>i)&&(i=s),i!==this.values(e)&&(n=this.values(),n[e]=i,o=this._trigger("slide",t,{handle:this.handles[e],value:i,values:n}),s=this.values(e?0:1),o!==!1&&this.values(e,i))):i!==this.value()&&(o=this._trigger("slide",t,{handle:this.handles[e],value:i}),o!==!1&&this.value(i))},_stop:function(t,e){var i={handle:this.handles[e],value:this.value()};this.options.values&&this.options.values.length&&(i.value=this.values(e),i.values=this.values()),this._trigger("stop",t,i)},_change:function(t,e){if(!this._keySliding&&!this._mouseSliding){var i={handle:this.handles[e],value:this.value()};this.options.values&&this.options.values.length&&(i.value=this.values(e),i.values=this.values()),this._lastChangedValue=e,this._trigger("change",t,i)}},value:function(t){return arguments.length?(this.options.value=this._trimAlignValue(t),this._refreshValue(),this._change(null,0),undefined):this._value()},values:function(e,i){var s,n,o;if(arguments.length>1)return this.options.values[e]=this._trimAlignValue(i),this._refreshValue(),this._change(null,e),undefined;if(!arguments.length)return this._values();if(!t.isArray(arguments[0]))return this.options.values&&this.options.values.length?this._values(e):this.value();for(s=this.options.values,n=arguments[0],o=0;s.length>o;o+=1)s[o]=this._trimAlignValue(n[o]),this._change(null,o);this._refreshValue()},_setOption:function(e,i){var s,n=0;switch("range"===e&&this.options.range===!0&&("min"===i?(this.options.value=this._values(0),this.options.values=null):"max"===i&&(this.options.value=this._values(this.options.values.length-1),this.options.values=null)),t.isArray(this.options.values)&&(n=this.options.values.length),t.Widget.prototype._setOption.apply(this,arguments),e){case"orientation":this._detectOrientation(),this.element.removeClass("ui-slider-horizontal ui-slider-vertical").addClass("ui-slider-"+this.orientation),this._refreshValue();break;case"value":this._animateOff=!0,this._refreshValue(),this._change(null,0),this._animateOff=!1;break;case"values":for(this._animateOff=!0,this._refreshValue(),s=0;n>s;s+=1)this._change(null,s);this._animateOff=!1;break;case"min":case"max":this._animateOff=!0,this._refreshValue(),this._animateOff=!1;break;case"range":this._animateOff=!0,this._refresh(),this._animateOff=!1}},_value:function(){var t=this.options.value;return t=this._trimAlignValue(t)},_values:function(t){var e,i,s;if(arguments.length)return e=this.options.values[t],e=this._trimAlignValue(e);if(this.options.values&&this.options.values.length){for(i=this.options.values.slice(),s=0;i.length>s;s+=1)i[s]=this._trimAlignValue(i[s]);return i}return[]},_trimAlignValue:function(t){if(this._valueMin()>=t)return this._valueMin();if(t>=this._valueMax())return this._valueMax();var e=this.options.step>0?this.options.step:1,i=(t-this._valueMin())%e,s=t-i;return 2*Math.abs(i)>=e&&(s+=i>0?e:-e),parseFloat(s.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var e,i,s,n,o,a=this.options.range,r=this.options,h=this,l=this._animateOff?!1:r.animate,c={};this.options.values&&this.options.values.length?this.handles.each(function(s){i=100*((h.values(s)-h._valueMin())/(h._valueMax()-h._valueMin())),c["horizontal"===h.orientation?"left":"bottom"]=i+"%",t(this).stop(1,1)[l?"animate":"css"](c,r.animate),h.options.range===!0&&("horizontal"===h.orientation?(0===s&&h.range.stop(1,1)[l?"animate":"css"]({left:i+"%"},r.animate),1===s&&h.range[l?"animate":"css"]({width:i-e+"%"},{queue:!1,duration:r.animate})):(0===s&&h.range.stop(1,1)[l?"animate":"css"]({bottom:i+"%"},r.animate),1===s&&h.range[l?"animate":"css"]({height:i-e+"%"},{queue:!1,duration:r.animate}))),e=i}):(s=this.value(),n=this._valueMin(),o=this._valueMax(),i=o!==n?100*((s-n)/(o-n)):0,c["horizontal"===this.orientation?"left":"bottom"]=i+"%",this.handle.stop(1,1)[l?"animate":"css"](c,r.animate),"min"===a&&"horizontal"===this.orientation&&this.range.stop(1,1)[l?"animate":"css"]({width:i+"%"},r.animate),"max"===a&&"horizontal"===this.orientation&&this.range[l?"animate":"css"]({width:100-i+"%"},{queue:!1,duration:r.animate}),"min"===a&&"vertical"===this.orientation&&this.range.stop(1,1)[l?"animate":"css"]({height:i+"%"},r.animate),"max"===a&&"vertical"===this.orientation&&this.range[l?"animate":"css"]({height:100-i+"%"},{queue:!1,duration:r.animate}))},_handleEvents:{keydown:function(i){var s,n,o,a,r=t(i.target).data("ui-slider-handle-index");switch(i.keyCode){case t.ui.keyCode.HOME:case t.ui.keyCode.END:case t.ui.keyCode.PAGE_UP:case t.ui.keyCode.PAGE_DOWN:case t.ui.keyCode.UP:case t.ui.keyCode.RIGHT:case t.ui.keyCode.DOWN:case t.ui.keyCode.LEFT:if(i.preventDefault(),!this._keySliding&&(this._keySliding=!0,t(i.target).addClass("ui-state-active"),s=this._start(i,r),s===!1))return}switch(a=this.options.step,n=o=this.options.values&&this.options.values.length?this.values(r):this.value(),i.keyCode){case t.ui.keyCode.HOME:o=this._valueMin();break;case t.ui.keyCode.END:o=this._valueMax();break;case t.ui.keyCode.PAGE_UP:o=this._trimAlignValue(n+(this._valueMax()-this._valueMin())/e);break;case t.ui.keyCode.PAGE_DOWN:o=this._trimAlignValue(n-(this._valueMax()-this._valueMin())/e);break;case t.ui.keyCode.UP:case t.ui.keyCode.RIGHT:if(n===this._valueMax())return;o=this._trimAlignValue(n+a);break;case t.ui.keyCode.DOWN:case t.ui.keyCode.LEFT:if(n===this._valueMin())return;o=this._trimAlignValue(n-a)}this._slide(i,r,o)},click:function(t){t.preventDefault()},keyup:function(e){var i=t(e.target).data("ui-slider-handle-index");this._keySliding&&(this._keySliding=!1,this._stop(e,i),this._change(e,i),t(e.target).removeClass("ui-state-active"))}}})}(jQuery),function(t){function e(t){return function(){var e=this.element.val();t.apply(this,arguments),this._refresh(),e!==this.element.val()&&this._trigger("change")}}t.widget("ui.spinner",{version:"1.10.4",defaultElement:"<input>",widgetEventPrefix:"spin",options:{culture:null,icons:{down:"ui-icon-triangle-1-s",up:"ui-icon-triangle-1-n"},incremental:!0,max:null,min:null,numberFormat:null,page:10,step:1,change:null,spin:null,start:null,stop:null},_create:function(){this._setOption("max",this.options.max),this._setOption("min",this.options.min),this._setOption("step",this.options.step),""!==this.value()&&this._value(this.element.val(),!0),this._draw(),this._on(this._events),this._refresh(),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_getCreateOptions:function(){var e={},i=this.element;return t.each(["min","max","step"],function(t,s){var n=i.attr(s);void 0!==n&&n.length&&(e[s]=n)}),e},_events:{keydown:function(t){this._start(t)&&this._keydown(t)&&t.preventDefault()},keyup:"_stop",focus:function(){this.previous=this.element.val()},blur:function(t){return this.cancelBlur?(delete this.cancelBlur,void 0):(this._stop(),this._refresh(),this.previous!==this.element.val()&&this._trigger("change",t),void 0)},mousewheel:function(t,e){if(e){if(!this.spinning&&!this._start(t))return!1;this._spin((e>0?1:-1)*this.options.step,t),clearTimeout(this.mousewheelTimer),this.mousewheelTimer=this._delay(function(){this.spinning&&this._stop(t)},100),t.preventDefault()}},"mousedown .ui-spinner-button":function(e){function i(){var t=this.element[0]===this.document[0].activeElement;t||(this.element.focus(),this.previous=s,this._delay(function(){this.previous=s}))}var s;s=this.element[0]===this.document[0].activeElement?this.previous:this.element.val(),e.preventDefault(),i.call(this),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur,i.call(this)}),this._start(e)!==!1&&this._repeat(null,t(e.currentTarget).hasClass("ui-spinner-up")?1:-1,e)},"mouseup .ui-spinner-button":"_stop","mouseenter .ui-spinner-button":function(e){return t(e.currentTarget).hasClass("ui-state-active")?this._start(e)===!1?!1:(this._repeat(null,t(e.currentTarget).hasClass("ui-spinner-up")?1:-1,e),void 0):void 0},"mouseleave .ui-spinner-button":"_stop"},_draw:function(){var t=this.uiSpinner=this.element.addClass("ui-spinner-input").attr("autocomplete","off").wrap(this._uiSpinnerHtml()).parent().append(this._buttonHtml());this.element.attr("role","spinbutton"),this.buttons=t.find(".ui-spinner-button").attr("tabIndex",-1).button().removeClass("ui-corner-all"),this.buttons.height()>Math.ceil(.5*t.height())&&t.height()>0&&t.height(t.height()),this.options.disabled&&this.disable()},_keydown:function(e){var i=this.options,s=t.ui.keyCode;switch(e.keyCode){case s.UP:return this._repeat(null,1,e),!0;case s.DOWN:return this._repeat(null,-1,e),!0;case s.PAGE_UP:return this._repeat(null,i.page,e),!0;case s.PAGE_DOWN:return this._repeat(null,-i.page,e),!0}return!1},_uiSpinnerHtml:function(){return"<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>"},_buttonHtml:function(){return"<a class='ui-spinner-button ui-spinner-up ui-corner-tr'><span class='ui-icon "+this.options.icons.up+"'>&#9650;</span>"+"</a>"+"<a class='ui-spinner-button ui-spinner-down ui-corner-br'>"+"<span class='ui-icon "+this.options.icons.down+"'>&#9660;</span>"+"</a>"},_start:function(t){return this.spinning||this._trigger("start",t)!==!1?(this.counter||(this.counter=1),this.spinning=!0,!0):!1},_repeat:function(t,e,i){t=t||500,clearTimeout(this.timer),this.timer=this._delay(function(){this._repeat(40,e,i)},t),this._spin(e*this.options.step,i)},_spin:function(t,e){var i=this.value()||0;this.counter||(this.counter=1),i=this._adjustValue(i+t*this._increment(this.counter)),this.spinning&&this._trigger("spin",e,{value:i})===!1||(this._value(i),this.counter++)},_increment:function(e){var i=this.options.incremental;return i?t.isFunction(i)?i(e):Math.floor(e*e*e/5e4-e*e/500+17*e/200+1):1},_precision:function(){var t=this._precisionOf(this.options.step);return null!==this.options.min&&(t=Math.max(t,this._precisionOf(this.options.min))),t},_precisionOf:function(t){var e=""+t,i=e.indexOf(".");return-1===i?0:e.length-i-1},_adjustValue:function(t){var e,i,s=this.options;return e=null!==s.min?s.min:0,i=t-e,i=Math.round(i/s.step)*s.step,t=e+i,t=parseFloat(t.toFixed(this._precision())),null!==s.max&&t>s.max?s.max:null!==s.min&&s.min>t?s.min:t},_stop:function(t){this.spinning&&(clearTimeout(this.timer),clearTimeout(this.mousewheelTimer),this.counter=0,this.spinning=!1,this._trigger("stop",t))},_setOption:function(t,e){if("culture"===t||"numberFormat"===t){var i=this._parse(this.element.val());return this.options[t]=e,this.element.val(this._format(i)),void 0}("max"===t||"min"===t||"step"===t)&&"string"==typeof e&&(e=this._parse(e)),"icons"===t&&(this.buttons.first().find(".ui-icon").removeClass(this.options.icons.up).addClass(e.up),this.buttons.last().find(".ui-icon").removeClass(this.options.icons.down).addClass(e.down)),this._super(t,e),"disabled"===t&&(e?(this.element.prop("disabled",!0),this.buttons.button("disable")):(this.element.prop("disabled",!1),this.buttons.button("enable")))},_setOptions:e(function(t){this._super(t),this._value(this.element.val())}),_parse:function(t){return"string"==typeof t&&""!==t&&(t=window.Globalize&&this.options.numberFormat?Globalize.parseFloat(t,10,this.options.culture):+t),""===t||isNaN(t)?null:t},_format:function(t){return""===t?"":window.Globalize&&this.options.numberFormat?Globalize.format(t,this.options.numberFormat,this.options.culture):t},_refresh:function(){this.element.attr({"aria-valuemin":this.options.min,"aria-valuemax":this.options.max,"aria-valuenow":this._parse(this.element.val())})},_value:function(t,e){var i;""!==t&&(i=this._parse(t),null!==i&&(e||(i=this._adjustValue(i)),t=this._format(i))),this.element.val(t),this._refresh()},_destroy:function(){this.element.removeClass("ui-spinner-input").prop("disabled",!1).removeAttr("autocomplete").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.uiSpinner.replaceWith(this.element)},stepUp:e(function(t){this._stepUp(t)}),_stepUp:function(t){this._start()&&(this._spin((t||1)*this.options.step),this._stop())},stepDown:e(function(t){this._stepDown(t)}),_stepDown:function(t){this._start()&&(this._spin((t||1)*-this.options.step),this._stop())},pageUp:e(function(t){this._stepUp((t||1)*this.options.page)}),pageDown:e(function(t){this._stepDown((t||1)*this.options.page)}),value:function(t){return arguments.length?(e(this._value).call(this,t),void 0):this._parse(this.element.val())},widget:function(){return this.uiSpinner}})}(jQuery),function(t,e){function i(){return++n}function s(t){return t=t.cloneNode(!1),t.hash.length>1&&decodeURIComponent(t.href.replace(o,""))===decodeURIComponent(location.href.replace(o,""))}var n=0,o=/#.*$/;t.widget("ui.tabs",{version:"1.10.4",delay:300,options:{active:null,collapsible:!1,event:"click",heightStyle:"content",hide:null,show:null,activate:null,beforeActivate:null,beforeLoad:null,load:null},_create:function(){var e=this,i=this.options;this.running=!1,this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all").toggleClass("ui-tabs-collapsible",i.collapsible).delegate(".ui-tabs-nav > li","mousedown"+this.eventNamespace,function(e){t(this).is(".ui-state-disabled")&&e.preventDefault()}).delegate(".ui-tabs-anchor","focus"+this.eventNamespace,function(){t(this).closest("li").is(".ui-state-disabled")&&this.blur()}),this._processTabs(),i.active=this._initialActive(),t.isArray(i.disabled)&&(i.disabled=t.unique(i.disabled.concat(t.map(this.tabs.filter(".ui-state-disabled"),function(t){return e.tabs.index(t)}))).sort()),this.active=this.options.active!==!1&&this.anchors.length?this._findActive(i.active):t(),this._refresh(),this.active.length&&this.load(i.active)},_initialActive:function(){var i=this.options.active,s=this.options.collapsible,n=location.hash.substring(1);return null===i&&(n&&this.tabs.each(function(s,o){return t(o).attr("aria-controls")===n?(i=s,!1):e}),null===i&&(i=this.tabs.index(this.tabs.filter(".ui-tabs-active"))),(null===i||-1===i)&&(i=this.tabs.length?0:!1)),i!==!1&&(i=this.tabs.index(this.tabs.eq(i)),-1===i&&(i=s?!1:0)),!s&&i===!1&&this.anchors.length&&(i=0),i},_getCreateEventData:function(){return{tab:this.active,panel:this.active.length?this._getPanelForTab(this.active):t()}},_tabKeydown:function(i){var s=t(this.document[0].activeElement).closest("li"),n=this.tabs.index(s),o=!0;if(!this._handlePageNav(i)){switch(i.keyCode){case t.ui.keyCode.RIGHT:case t.ui.keyCode.DOWN:n++;break;case t.ui.keyCode.UP:case t.ui.keyCode.LEFT:o=!1,n--;break;case t.ui.keyCode.END:n=this.anchors.length-1;break;case t.ui.keyCode.HOME:n=0;break;case t.ui.keyCode.SPACE:return i.preventDefault(),clearTimeout(this.activating),this._activate(n),e;case t.ui.keyCode.ENTER:return i.preventDefault(),clearTimeout(this.activating),this._activate(n===this.options.active?!1:n),e;default:return}i.preventDefault(),clearTimeout(this.activating),n=this._focusNextTab(n,o),i.ctrlKey||(s.attr("aria-selected","false"),this.tabs.eq(n).attr("aria-selected","true"),this.activating=this._delay(function(){this.option("active",n)},this.delay))}},_panelKeydown:function(e){this._handlePageNav(e)||e.ctrlKey&&e.keyCode===t.ui.keyCode.UP&&(e.preventDefault(),this.active.focus())},_handlePageNav:function(i){return i.altKey&&i.keyCode===t.ui.keyCode.PAGE_UP?(this._activate(this._focusNextTab(this.options.active-1,!1)),!0):i.altKey&&i.keyCode===t.ui.keyCode.PAGE_DOWN?(this._activate(this._focusNextTab(this.options.active+1,!0)),!0):e},_findNextTab:function(e,i){function s(){return e>n&&(e=0),0>e&&(e=n),e}for(var n=this.tabs.length-1;-1!==t.inArray(s(),this.options.disabled);)e=i?e+1:e-1;return e},_focusNextTab:function(t,e){return t=this._findNextTab(t,e),this.tabs.eq(t).focus(),t},_setOption:function(t,i){return"active"===t?(this._activate(i),e):"disabled"===t?(this._setupDisabled(i),e):(this._super(t,i),"collapsible"===t&&(this.element.toggleClass("ui-tabs-collapsible",i),i||this.options.active!==!1||this._activate(0)),"event"===t&&this._setupEvents(i),"heightStyle"===t&&this._setupHeightStyle(i),e)},_tabId:function(t){return t.attr("aria-controls")||"ui-tabs-"+i()},_sanitizeSelector:function(t){return t?t.replace(/[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g,"\\$&"):""},refresh:function(){var e=this.options,i=this.tablist.children(":has(a[href])");e.disabled=t.map(i.filter(".ui-state-disabled"),function(t){return i.index(t)}),this._processTabs(),e.active!==!1&&this.anchors.length?this.active.length&&!t.contains(this.tablist[0],this.active[0])?this.tabs.length===e.disabled.length?(e.active=!1,this.active=t()):this._activate(this._findNextTab(Math.max(0,e.active-1),!1)):e.active=this.tabs.index(this.active):(e.active=!1,this.active=t()),this._refresh()},_refresh:function(){this._setupDisabled(this.options.disabled),this._setupEvents(this.options.event),this._setupHeightStyle(this.options.heightStyle),this.tabs.not(this.active).attr({"aria-selected":"false",tabIndex:-1}),this.panels.not(this._getPanelForTab(this.active)).hide().attr({"aria-expanded":"false","aria-hidden":"true"}),this.active.length?(this.active.addClass("ui-tabs-active ui-state-active").attr({"aria-selected":"true",tabIndex:0}),this._getPanelForTab(this.active).show().attr({"aria-expanded":"true","aria-hidden":"false"})):this.tabs.eq(0).attr("tabIndex",0)},_processTabs:function(){var e=this;this.tablist=this._getList().addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").attr("role","tablist"),this.tabs=this.tablist.find("> li:has(a[href])").addClass("ui-state-default ui-corner-top").attr({role:"tab",tabIndex:-1}),this.anchors=this.tabs.map(function(){return t("a",this)[0]}).addClass("ui-tabs-anchor").attr({role:"presentation",tabIndex:-1}),this.panels=t(),this.anchors.each(function(i,n){var o,a,r,h=t(n).uniqueId().attr("id"),l=t(n).closest("li"),c=l.attr("aria-controls");s(n)?(o=n.hash,a=e.element.find(e._sanitizeSelector(o))):(r=e._tabId(l),o="#"+r,a=e.element.find(o),a.length||(a=e._createPanel(r),a.insertAfter(e.panels[i-1]||e.tablist)),a.attr("aria-live","polite")),a.length&&(e.panels=e.panels.add(a)),c&&l.data("ui-tabs-aria-controls",c),l.attr({"aria-controls":o.substring(1),"aria-labelledby":h}),a.attr("aria-labelledby",h)}),this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").attr("role","tabpanel")},_getList:function(){return this.tablist||this.element.find("ol,ul").eq(0)},_createPanel:function(e){return t("<div>").attr("id",e).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").data("ui-tabs-destroy",!0)},_setupDisabled:function(e){t.isArray(e)&&(e.length?e.length===this.anchors.length&&(e=!0):e=!1);for(var i,s=0;i=this.tabs[s];s++)e===!0||-1!==t.inArray(s,e)?t(i).addClass("ui-state-disabled").attr("aria-disabled","true"):t(i).removeClass("ui-state-disabled").removeAttr("aria-disabled");this.options.disabled=e},_setupEvents:function(e){var i={click:function(t){t.preventDefault()}};e&&t.each(e.split(" "),function(t,e){i[e]="_eventHandler"}),this._off(this.anchors.add(this.tabs).add(this.panels)),this._on(this.anchors,i),this._on(this.tabs,{keydown:"_tabKeydown"}),this._on(this.panels,{keydown:"_panelKeydown"}),this._focusable(this.tabs),this._hoverable(this.tabs)},_setupHeightStyle:function(e){var i,s=this.element.parent();"fill"===e?(i=s.height(),i-=this.element.outerHeight()-this.element.height(),this.element.siblings(":visible").each(function(){var e=t(this),s=e.css("position");"absolute"!==s&&"fixed"!==s&&(i-=e.outerHeight(!0))}),this.element.children().not(this.panels).each(function(){i-=t(this).outerHeight(!0)}),this.panels.each(function(){t(this).height(Math.max(0,i-t(this).innerHeight()+t(this).height()))}).css("overflow","auto")):"auto"===e&&(i=0,this.panels.each(function(){i=Math.max(i,t(this).height("").height())}).height(i))},_eventHandler:function(e){var i=this.options,s=this.active,n=t(e.currentTarget),o=n.closest("li"),a=o[0]===s[0],r=a&&i.collapsible,h=r?t():this._getPanelForTab(o),l=s.length?this._getPanelForTab(s):t(),c={oldTab:s,oldPanel:l,newTab:r?t():o,newPanel:h};e.preventDefault(),o.hasClass("ui-state-disabled")||o.hasClass("ui-tabs-loading")||this.running||a&&!i.collapsible||this._trigger("beforeActivate",e,c)===!1||(i.active=r?!1:this.tabs.index(o),this.active=a?t():o,this.xhr&&this.xhr.abort(),l.length||h.length||t.error("jQuery UI Tabs: Mismatching fragment identifier."),h.length&&this.load(this.tabs.index(o),e),this._toggle(e,c))},_toggle:function(e,i){function s(){o.running=!1,o._trigger("activate",e,i)}function n(){i.newTab.closest("li").addClass("ui-tabs-active ui-state-active"),a.length&&o.options.show?o._show(a,o.options.show,s):(a.show(),s())}var o=this,a=i.newPanel,r=i.oldPanel;this.running=!0,r.length&&this.options.hide?this._hide(r,this.options.hide,function(){i.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),n()}):(i.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),r.hide(),n()),r.attr({"aria-expanded":"false","aria-hidden":"true"}),i.oldTab.attr("aria-selected","false"),a.length&&r.length?i.oldTab.attr("tabIndex",-1):a.length&&this.tabs.filter(function(){return 0===t(this).attr("tabIndex")}).attr("tabIndex",-1),a.attr({"aria-expanded":"true","aria-hidden":"false"}),i.newTab.attr({"aria-selected":"true",tabIndex:0})},_activate:function(e){var i,s=this._findActive(e);s[0]!==this.active[0]&&(s.length||(s=this.active),i=s.find(".ui-tabs-anchor")[0],this._eventHandler({target:i,currentTarget:i,preventDefault:t.noop}))},_findActive:function(e){return e===!1?t():this.tabs.eq(e)},_getIndex:function(t){return"string"==typeof t&&(t=this.anchors.index(this.anchors.filter("[href$='"+t+"']"))),t},_destroy:function(){this.xhr&&this.xhr.abort(),this.element.removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible"),this.tablist.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").removeAttr("role"),this.anchors.removeClass("ui-tabs-anchor").removeAttr("role").removeAttr("tabIndex").removeUniqueId(),this.tabs.add(this.panels).each(function(){t.data(this,"ui-tabs-destroy")?t(this).remove():t(this).removeClass("ui-state-default ui-state-active ui-state-disabled ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel").removeAttr("tabIndex").removeAttr("aria-live").removeAttr("aria-busy").removeAttr("aria-selected").removeAttr("aria-labelledby").removeAttr("aria-hidden").removeAttr("aria-expanded").removeAttr("role")}),this.tabs.each(function(){var e=t(this),i=e.data("ui-tabs-aria-controls");i?e.attr("aria-controls",i).removeData("ui-tabs-aria-controls"):e.removeAttr("aria-controls")}),this.panels.show(),"content"!==this.options.heightStyle&&this.panels.css("height","")},enable:function(i){var s=this.options.disabled;s!==!1&&(i===e?s=!1:(i=this._getIndex(i),s=t.isArray(s)?t.map(s,function(t){return t!==i?t:null}):t.map(this.tabs,function(t,e){return e!==i?e:null})),this._setupDisabled(s))},disable:function(i){var s=this.options.disabled;if(s!==!0){if(i===e)s=!0;else{if(i=this._getIndex(i),-1!==t.inArray(i,s))return;s=t.isArray(s)?t.merge([i],s).sort():[i]}this._setupDisabled(s)}},load:function(e,i){e=this._getIndex(e);var n=this,o=this.tabs.eq(e),a=o.find(".ui-tabs-anchor"),r=this._getPanelForTab(o),h={tab:o,panel:r};s(a[0])||(this.xhr=t.ajax(this._ajaxSettings(a,i,h)),this.xhr&&"canceled"!==this.xhr.statusText&&(o.addClass("ui-tabs-loading"),r.attr("aria-busy","true"),this.xhr.success(function(t){setTimeout(function(){r.html(t),n._trigger("load",i,h)},1)}).complete(function(t,e){setTimeout(function(){"abort"===e&&n.panels.stop(!1,!0),o.removeClass("ui-tabs-loading"),r.removeAttr("aria-busy"),t===n.xhr&&delete n.xhr},1)})))},_ajaxSettings:function(e,i,s){var n=this;return{url:e.attr("href"),beforeSend:function(e,o){return n._trigger("beforeLoad",i,t.extend({jqXHR:e,ajaxSettings:o},s))}}},_getPanelForTab:function(e){var i=t(e).attr("aria-controls");return this.element.find(this._sanitizeSelector("#"+i))}})}(jQuery),function(t){function e(e,i){var s=(e.attr("aria-describedby")||"").split(/\s+/);s.push(i),e.data("ui-tooltip-id",i).attr("aria-describedby",t.trim(s.join(" ")))}function i(e){var i=e.data("ui-tooltip-id"),s=(e.attr("aria-describedby")||"").split(/\s+/),n=t.inArray(i,s);-1!==n&&s.splice(n,1),e.removeData("ui-tooltip-id"),s=t.trim(s.join(" ")),s?e.attr("aria-describedby",s):e.removeAttr("aria-describedby")}var s=0;t.widget("ui.tooltip",{version:"1.10.4",options:{content:function(){var e=t(this).attr("title")||"";return t("<a>").text(e).html()},hide:!0,items:"[title]:not([disabled])",position:{my:"left top+15",at:"left bottom",collision:"flipfit flip"},show:!0,tooltipClass:null,track:!1,close:null,open:null},_create:function(){this._on({mouseover:"open",focusin:"open"}),this.tooltips={},this.parents={},this.options.disabled&&this._disable()},_setOption:function(e,i){var s=this;return"disabled"===e?(this[i?"_disable":"_enable"](),this.options[e]=i,void 0):(this._super(e,i),"content"===e&&t.each(this.tooltips,function(t,e){s._updateContent(e)}),void 0)},_disable:function(){var e=this;t.each(this.tooltips,function(i,s){var n=t.Event("blur");n.target=n.currentTarget=s[0],e.close(n,!0)}),this.element.find(this.options.items).addBack().each(function(){var e=t(this);e.is("[title]")&&e.data("ui-tooltip-title",e.attr("title")).attr("title","")})},_enable:function(){this.element.find(this.options.items).addBack().each(function(){var e=t(this);e.data("ui-tooltip-title")&&e.attr("title",e.data("ui-tooltip-title"))})},open:function(e){var i=this,s=t(e?e.target:this.element).closest(this.options.items);s.length&&!s.data("ui-tooltip-id")&&(s.attr("title")&&s.data("ui-tooltip-title",s.attr("title")),s.data("ui-tooltip-open",!0),e&&"mouseover"===e.type&&s.parents().each(function(){var e,s=t(this);s.data("ui-tooltip-open")&&(e=t.Event("blur"),e.target=e.currentTarget=this,i.close(e,!0)),s.attr("title")&&(s.uniqueId(),i.parents[this.id]={element:this,title:s.attr("title")},s.attr("title",""))}),this._updateContent(s,e))},_updateContent:function(t,e){var i,s=this.options.content,n=this,o=e?e.type:null;
+return"string"==typeof s?this._open(e,t,s):(i=s.call(t[0],function(i){t.data("ui-tooltip-open")&&n._delay(function(){e&&(e.type=o),this._open(e,t,i)})}),i&&this._open(e,t,i),void 0)},_open:function(i,s,n){function o(t){l.of=t,a.is(":hidden")||a.position(l)}var a,r,h,l=t.extend({},this.options.position);if(n){if(a=this._find(s),a.length)return a.find(".ui-tooltip-content").html(n),void 0;s.is("[title]")&&(i&&"mouseover"===i.type?s.attr("title",""):s.removeAttr("title")),a=this._tooltip(s),e(s,a.attr("id")),a.find(".ui-tooltip-content").html(n),this.options.track&&i&&/^mouse/.test(i.type)?(this._on(this.document,{mousemove:o}),o(i)):a.position(t.extend({of:s},this.options.position)),a.hide(),this._show(a,this.options.show),this.options.show&&this.options.show.delay&&(h=this.delayedShow=setInterval(function(){a.is(":visible")&&(o(l.of),clearInterval(h))},t.fx.interval)),this._trigger("open",i,{tooltip:a}),r={keyup:function(e){if(e.keyCode===t.ui.keyCode.ESCAPE){var i=t.Event(e);i.currentTarget=s[0],this.close(i,!0)}},remove:function(){this._removeTooltip(a)}},i&&"mouseover"!==i.type||(r.mouseleave="close"),i&&"focusin"!==i.type||(r.focusout="close"),this._on(!0,s,r)}},close:function(e){var s=this,n=t(e?e.currentTarget:this.element),o=this._find(n);this.closing||(clearInterval(this.delayedShow),n.data("ui-tooltip-title")&&n.attr("title",n.data("ui-tooltip-title")),i(n),o.stop(!0),this._hide(o,this.options.hide,function(){s._removeTooltip(t(this))}),n.removeData("ui-tooltip-open"),this._off(n,"mouseleave focusout keyup"),n[0]!==this.element[0]&&this._off(n,"remove"),this._off(this.document,"mousemove"),e&&"mouseleave"===e.type&&t.each(this.parents,function(e,i){t(i.element).attr("title",i.title),delete s.parents[e]}),this.closing=!0,this._trigger("close",e,{tooltip:o}),this.closing=!1)},_tooltip:function(e){var i="ui-tooltip-"+s++,n=t("<div>").attr({id:i,role:"tooltip"}).addClass("ui-tooltip ui-widget ui-corner-all ui-widget-content "+(this.options.tooltipClass||""));return t("<div>").addClass("ui-tooltip-content").appendTo(n),n.appendTo(this.document[0].body),this.tooltips[i]=e,n},_find:function(e){var i=e.data("ui-tooltip-id");return i?t("#"+i):t()},_removeTooltip:function(t){t.remove(),delete this.tooltips[t.attr("id")]},_destroy:function(){var e=this;t.each(this.tooltips,function(i,s){var n=t.Event("blur");n.target=n.currentTarget=s[0],e.close(n,!0),t("#"+i).remove(),s.data("ui-tooltip-title")&&(s.attr("title",s.data("ui-tooltip-title")),s.removeData("ui-tooltip-title"))})}})}(jQuery);
diff --git a/ruoyi-admin/src/main/resources/static/js/jquery.contextMenu.min.js b/ruoyi-admin/src/main/resources/static/js/jquery.contextMenu.min.js
new file mode 100644
index 0000000..48bd6c4
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/js/jquery.contextMenu.min.js
@@ -0,0 +1 @@
+!function(e){"function"==typeof define&&define.amd?define(["jquery"],e):"object"==typeof exports?e(require("jquery")):e(jQuery)}(function(m){"use strict";var a;m.support.htmlMenuitem="HTMLMenuItemElement"in window,m.support.htmlCommand="HTMLCommandElement"in window,m.support.eventSelectstart="onselectstart"in document.documentElement,m.ui&&m.widget||(m.cleanData=(a=m.cleanData,function(e){var t,n,o;for(o=0;null!=e[o];o++){n=e[o];try{(t=m._data(n,"events"))&&t.remove&&m(n).triggerHandler("remove")}catch(e){}}a(e)}));var c=null,d=!1,p=m(window),f=0,h={},x={},v={},g={selector:null,appendTo:null,trigger:"right",autoHide:!1,delay:200,reposition:!0,hideOnSecondTrigger:!1,selectableSubMenu:!1,classNames:{hover:"context-menu-hover",disabled:"context-menu-disabled",visible:"context-menu-visible",notSelectable:"context-menu-not-selectable",icon:"context-menu-icon",iconEdit:"context-menu-icon-edit",iconCut:"context-menu-icon-cut",iconCopy:"context-menu-icon-copy",iconPaste:"context-menu-icon-paste",iconDelete:"context-menu-icon-delete",iconAdd:"context-menu-icon-add",iconQuit:"context-menu-icon-quit",iconLoadingClass:"context-menu-icon-loading"},determinePosition:function(e){if(m.ui&&m.ui.position)e.css("display","block").position({my:"center top",at:"center bottom",of:this,offset:"0 5",collision:"fit"}).css("display","none");else{var t=this.offset();t.top+=this.outerHeight(),t.left+=this.outerWidth()/2-e.outerWidth()/2,e.css(t)}},position:function(e,t,n){var o;if(t||n){if("maintain"===t&&"maintain"===n)o=e.$menu.position();else{var a=e.$menu.offsetParent().offset();o={top:n-a.top,left:t-a.left}}var s=p.scrollTop()+p.height(),i=p.scrollLeft()+p.width(),c=e.$menu.outerHeight(),l=e.$menu.outerWidth();o.top+c>s&&(o.top-=c),o.top<0&&(o.top=0),o.left+l>i&&(o.left-=l),o.left<0&&(o.left=0),e.$menu.css(o)}else e.determinePosition.call(this,e.$menu)},positionSubmenu:function(e){if(void 0!==e)if(m.ui&&m.ui.position)e.css("display","block").position({my:"left top-5",at:"right top",of:this,collision:"flipfit fit"}).css("display","");else{var t={top:-9,left:this.outerWidth()-5};e.css(t)}},zIndex:1,animation:{duration:50,show:"slideDown",hide:"slideUp"},events:{preShow:m.noop,show:m.noop,hide:m.noop,activated:m.noop},callback:null,items:{}},s={timer:null,pageX:null,pageY:null},b={abortevent:function(e){e.preventDefault(),e.stopImmediatePropagation()},contextmenu:function(e){var t=m(this);if(!1!==e.data.events.preShow(t,e)&&("right"===e.data.trigger&&(e.preventDefault(),e.stopImmediatePropagation()),!("right"!==e.data.trigger&&"demand"!==e.data.trigger&&e.originalEvent||!(void 0===e.mouseButton||!e.data||"left"===e.data.trigger&&0===e.mouseButton||"right"===e.data.trigger&&2===e.mouseButton)||t.hasClass("context-menu-active")||t.hasClass("context-menu-disabled")))){if(c=t,e.data.build){var n=e.data.build(c,e);if(!1===n)return;if(e.data=m.extend(!0,{},g,e.data,n||{}),!e.data.items||m.isEmptyObject(e.data.items))throw window.console&&(console.error||console.log).call(console,"No items specified to show in contextMenu"),new Error("No Items specified");e.data.$trigger=c,$.create(e.data)}$.show.call(t,e.data,e.pageX,e.pageY)}},click:function(e){e.preventDefault(),e.stopImmediatePropagation(),m(this).trigger(m.Event("contextmenu",{data:e.data,pageX:e.pageX,pageY:e.pageY}))},mousedown:function(e){var t=m(this);c&&c.length&&!c.is(t)&&c.data("contextMenu").$menu.trigger("contextmenu:hide"),2===e.button&&(c=t.data("contextMenuActive",!0))},mouseup:function(e){var t=m(this);t.data("contextMenuActive")&&c&&c.length&&c.is(t)&&!t.hasClass("context-menu-disabled")&&(e.preventDefault(),e.stopImmediatePropagation(),(c=t).trigger(m.Event("contextmenu",{data:e.data,pageX:e.pageX,pageY:e.pageY}))),t.removeData("contextMenuActive")},mouseenter:function(e){var t=m(this),n=m(e.relatedTarget),o=m(document);n.is(".context-menu-list")||n.closest(".context-menu-list").length||c&&c.length||(s.pageX=e.pageX,s.pageY=e.pageY,s.data=e.data,o.on("mousemove.contextMenuShow",b.mousemove),s.timer=setTimeout(function(){s.timer=null,o.off("mousemove.contextMenuShow"),(c=t).trigger(m.Event("contextmenu",{data:s.data,pageX:s.pageX,pageY:s.pageY}))},e.data.delay))},mousemove:function(e){s.pageX=e.pageX,s.pageY=e.pageY},mouseleave:function(e){var t=m(e.relatedTarget);if(!t.is(".context-menu-list")&&!t.closest(".context-menu-list").length){try{clearTimeout(s.timer)}catch(e){}s.timer=null}},layerClick:function(a){var s,i,c=m(this).data("contextMenuRoot"),l=a.button,r=a.pageX,u=a.pageY,d=void 0===r;a.preventDefault(),setTimeout(function(){if(d)null!=c&&null!==c.$menu&&void 0!==c.$menu&&c.$menu.trigger("contextmenu:hide");else{var e,t="left"===c.trigger&&0===l||"right"===c.trigger&&2===l;if(document.elementFromPoint&&c.$layer){if(c.$layer.hide(),(s=document.elementFromPoint(r-p.scrollLeft(),u-p.scrollTop())).isContentEditable){var n=document.createRange(),o=window.getSelection();n.selectNode(s),n.collapse(!0),o.removeAllRanges(),o.addRange(n)}m(s).trigger(a),c.$layer.show()}if(c.hideOnSecondTrigger&&t&&null!==c.$menu&&void 0!==c.$menu)c.$menu.trigger("contextmenu:hide");else{if(c.reposition&&t)if(document.elementFromPoint){if(c.$trigger.is(s))return void c.position.call(c.$trigger,c,r,u)}else if(i=c.$trigger.offset(),e=m(window),i.top+=e.scrollTop(),i.top<=a.pageY&&(i.left+=e.scrollLeft(),i.left<=a.pageX&&(i.bottom=i.top+c.$trigger.outerHeight(),i.bottom>=a.pageY&&(i.right=i.left+c.$trigger.outerWidth(),i.right>=a.pageX))))return void c.position.call(c.$trigger,c,r,u);s&&t&&c.$trigger.one("contextmenu:hidden",function(){m(s).contextMenu({x:r,y:u,button:l})}),null!=c&&null!==c.$menu&&void 0!==c.$menu&&c.$menu.trigger("contextmenu:hide")}}},50)},keyStop:function(e,t){t.isInput||e.preventDefault(),e.stopPropagation()},key:function(e){var t={};c&&(t=c.data("contextMenu")||{}),void 0===t.zIndex&&(t.zIndex=0);var n=0,o=function(e){""!==e.style.zIndex?n=e.style.zIndex:null!==e.offsetParent&&void 0!==e.offsetParent?o(e.offsetParent):null!==e.parentElement&&void 0!==e.parentElement&&o(e.parentElement)};if(o(e.target),!(t.$menu&&parseInt(n,10)>parseInt(t.$menu.css("zIndex"),10))){switch(e.keyCode){case 9:case 38:if(b.keyStop(e,t),t.isInput){if(9===e.keyCode&&e.shiftKey)return e.preventDefault(),t.$selected&&t.$selected.find("input, textarea, select").blur(),void(null!==t.$menu&&void 0!==t.$menu&&t.$menu.trigger("prevcommand"));if(38===e.keyCode&&"checkbox"===t.$selected.find("input, textarea, select").prop("type"))return void e.preventDefault()}else if(9!==e.keyCode||e.shiftKey)return void(null!==t.$menu&&void 0!==t.$menu&&t.$menu.trigger("prevcommand"));break;case 40:if(b.keyStop(e,t),!t.isInput)return void(null!==t.$menu&&void 0!==t.$menu&&t.$menu.trigger("nextcommand"));if(9===e.keyCode)return e.preventDefault(),t.$selected&&t.$selected.find("input, textarea, select").blur(),void(null!==t.$menu&&void 0!==t.$menu&&t.$menu.trigger("nextcommand"));if(40===e.keyCode&&"checkbox"===t.$selected.find("input, textarea, select").prop("type"))return void e.preventDefault();break;case 37:if(b.keyStop(e,t),t.isInput||!t.$selected||!t.$selected.length)break;if(t.$selected.parent().hasClass("context-menu-root"))break;var a=t.$selected.parent().parent();return t.$selected.trigger("contextmenu:blur"),void(t.$selected=a);case 39:if(b.keyStop(e,t),t.isInput||!t.$selected||!t.$selected.length)break;var s=t.$selected.data("contextMenu")||{};if(s.$menu&&t.$selected.hasClass("context-menu-submenu"))return t.$selected=null,s.$selected=null,void s.$menu.trigger("nextcommand");break;case 35:case 36:return t.$selected&&t.$selected.find("input, textarea, select").length?void 0:((t.$selected&&t.$selected.parent()||t.$menu).children(":not(."+t.classNames.disabled+", ."+t.classNames.notSelectable+")")[36===e.keyCode?"first":"last"]().trigger("contextmenu:focus"),void e.preventDefault());case 13:if(b.keyStop(e,t),t.isInput){if(t.$selected&&!t.$selected.is("textarea, select"))return void e.preventDefault();break}return void(void 0!==t.$selected&&null!==t.$selected&&t.$selected.trigger("mouseup"));case 32:case 33:case 34:return void b.keyStop(e,t);case 27:return b.keyStop(e,t),void(null!==t.$menu&&void 0!==t.$menu&&t.$menu.trigger("contextmenu:hide"));default:var i=String.fromCharCode(e.keyCode).toUpperCase();if(t.accesskeys&&t.accesskeys[i])return void t.accesskeys[i].$node.trigger(t.accesskeys[i].$menu?"contextmenu:focus":"mouseup")}e.stopPropagation(),void 0!==t.$selected&&null!==t.$selected&&t.$selected.trigger(e)}},prevItem:function(e){e.stopPropagation();var t=m(this).data("contextMenu")||{},n=m(this).data("contextMenuRoot")||{};if(t.$selected){var o=t.$selected;(t=t.$selected.parent().data("contextMenu")||{}).$selected=o}for(var a=t.$menu.children(),s=t.$selected&&t.$selected.prev().length?t.$selected.prev():a.last(),i=s;s.hasClass(n.classNames.disabled)||s.hasClass(n.classNames.notSelectable)||s.is(":hidden");)if((s=s.prev().length?s.prev():a.last()).is(i))return;t.$selected&&b.itemMouseleave.call(t.$selected.get(0),e),b.itemMouseenter.call(s.get(0),e);var c=s.find("input, textarea, select");c.length&&c.focus()},nextItem:function(e){e.stopPropagation();var t=m(this).data("contextMenu")||{},n=m(this).data("contextMenuRoot")||{};if(t.$selected){var o=t.$selected;(t=t.$selected.parent().data("contextMenu")||{}).$selected=o}for(var a=t.$menu.children(),s=t.$selected&&t.$selected.next().length?t.$selected.next():a.first(),i=s;s.hasClass(n.classNames.disabled)||s.hasClass(n.classNames.notSelectable)||s.is(":hidden");)if((s=s.next().length?s.next():a.first()).is(i))return;t.$selected&&b.itemMouseleave.call(t.$selected.get(0),e),b.itemMouseenter.call(s.get(0),e);var c=s.find("input, textarea, select");c.length&&c.focus()},focusInput:function(){var e=m(this).closest(".context-menu-item"),t=e.data(),n=t.contextMenu,o=t.contextMenuRoot;o.$selected=n.$selected=e,o.isInput=n.isInput=!0},blurInput:function(){var e=m(this).closest(".context-menu-item").data(),t=e.contextMenu;e.contextMenuRoot.isInput=t.isInput=!1},menuMouseenter:function(){m(this).data().contextMenuRoot.hovering=!0},menuMouseleave:function(e){var t=m(this).data().contextMenuRoot;t.$layer&&t.$layer.is(e.relatedTarget)&&(t.hovering=!1)},itemMouseenter:function(e){var t=m(this),n=t.data(),o=n.contextMenu,a=n.contextMenuRoot;a.hovering=!0,e&&a.$layer&&a.$layer.is(e.relatedTarget)&&(e.preventDefault(),e.stopImmediatePropagation()),(o.$menu?o:a).$menu.children("."+a.classNames.hover).trigger("contextmenu:blur").children(".hover").trigger("contextmenu:blur"),t.hasClass(a.classNames.disabled)||t.hasClass(a.classNames.notSelectable)?o.$selected=null:t.trigger("contextmenu:focus")},itemMouseleave:function(e){var t=m(this),n=t.data(),o=n.contextMenu,a=n.contextMenuRoot;if(a!==o&&a.$layer&&a.$layer.is(e.relatedTarget))return void 0!==a.$selected&&null!==a.$selected&&a.$selected.trigger("contextmenu:blur"),e.preventDefault(),e.stopImmediatePropagation(),void(a.$selected=o.$selected=o.$node);o&&o.$menu&&o.$menu.hasClass("context-menu-visible")||t.trigger("contextmenu:blur")},itemClick:function(e){var t,n=m(this),o=n.data(),a=o.contextMenu,s=o.contextMenuRoot,i=o.contextMenuKey;if(!(!a.items[i]||n.is("."+s.classNames.disabled+", .context-menu-separator, ."+s.classNames.notSelectable)||n.is(".context-menu-submenu")&&!1===s.selectableSubMenu)){if(e.preventDefault(),e.stopImmediatePropagation(),m.isFunction(a.callbacks[i])&&Object.prototype.hasOwnProperty.call(a.callbacks,i))t=a.callbacks[i];else{if(!m.isFunction(s.callback))return;t=s.callback}!1!==t.call(s.$trigger,i,s,e)?s.$menu.trigger("contextmenu:hide"):s.$menu.parent().length&&$.update.call(s.$trigger,s)}},inputClick:function(e){e.stopImmediatePropagation()},hideMenu:function(e,t){var n=m(this).data("contextMenuRoot");$.hide.call(n.$trigger,n,t&&t.force)},focusItem:function(e){e.stopPropagation();var t=m(this),n=t.data(),o=n.contextMenu,a=n.contextMenuRoot;t.hasClass(a.classNames.disabled)||t.hasClass(a.classNames.notSelectable)||(t.addClass([a.classNames.hover,a.classNames.visible].join(" ")).parent().find(".context-menu-item").not(t).removeClass(a.classNames.visible).filter("."+a.classNames.hover).trigger("contextmenu:blur"),o.$selected=a.$selected=t,o&&o.$node&&o.$node.hasClass("context-menu-submenu")&&o.$node.addClass(a.classNames.hover),o.$node&&a.positionSubmenu.call(o.$node,o.$menu))},blurItem:function(e){e.stopPropagation();var t=m(this),n=t.data(),o=n.contextMenu,a=n.contextMenuRoot;o.autoHide&&t.removeClass(a.classNames.visible),t.removeClass(a.classNames.hover),o.$selected=null}},$={show:function(n,e,t){var o=m(this),a={};if(m("#context-menu-layer").trigger("mousedown"),n.$trigger=o,!1!==n.events.show.call(o,n))if(!1!==$.update.call(o,n)){if(n.position.call(o,n,e,t),n.zIndex){var s=n.zIndex;"function"==typeof n.zIndex&&(s=n.zIndex.call(o,n)),a.zIndex=function(e){for(var t=0,n=e;t=Math.max(t,parseInt(n.css("z-index"),10)||0),(n=n.parent())&&n.length&&!(-1<"html body".indexOf(n.prop("nodeName").toLowerCase())););return t}(o)+s}$.layer.call(n.$menu,n,a.zIndex),n.$menu.find("ul").css("zIndex",a.zIndex+1),n.$menu.css(a)[n.animation.show](n.animation.duration,function(){o.trigger("contextmenu:visible"),$.activated(n),n.events.activated(n)}),o.data("contextMenu",n).addClass("context-menu-active"),m(document).off("keydown.contextMenu").on("keydown.contextMenu",b.key),n.autoHide&&m(document).on("mousemove.contextMenuAutoHide",function(e){var t=o.offset();t.right=t.left+o.outerWidth(),t.bottom=t.top+o.outerHeight(),!n.$layer||n.hovering||e.pageX>=t.left&&e.pageX<=t.right&&e.pageY>=t.top&&e.pageY<=t.bottom||setTimeout(function(){n.hovering||null===n.$menu||void 0===n.$menu||n.$menu.trigger("contextmenu:hide")},50)})}else c=null;else c=null},hide:function(t,e){var n=m(this);if(t||(t=n.data("contextMenu")||{}),e||!t.events||!1!==t.events.hide.call(n,t)){if(n.removeData("contextMenu").removeClass("context-menu-active"),t.$layer){setTimeout((o=t.$layer,function(){o.remove()}),10);try{delete t.$layer}catch(e){t.$layer=null}}var o;c=null,t.$menu.find("."+t.classNames.hover).trigger("contextmenu:blur"),t.$selected=null,t.$menu.find("."+t.classNames.visible).removeClass(t.classNames.visible),m(document).off(".contextMenuAutoHide").off("keydown.contextMenu"),t.$menu&&t.$menu[t.animation.hide](t.animation.duration,function(){t.build&&(t.$menu.remove(),m.each(t,function(e){switch(e){case"ns":case"selector":case"build":case"trigger":return!0;default:t[e]=void 0;try{delete t[e]}catch(e){}return!0}})),setTimeout(function(){n.trigger("contextmenu:hidden")},10)})}},create:function(r,u){function d(e){var t=m("<span></span>");if(e._accesskey)e._beforeAccesskey&&t.append(document.createTextNode(e._beforeAccesskey)),m("<span></span>").addClass("context-menu-accesskey").text(e._accesskey).appendTo(t),e._afterAccesskey&&t.append(document.createTextNode(e._afterAccesskey));else if(e.isHtmlName){if(void 0!==e.accesskey)throw new Error("accesskeys are not compatible with HTML names and cannot be used together in the same item");t.html(e.name)}else t.text(e.name);return t}void 0===u&&(u=r),r.$menu=m('<ul class="context-menu-list"></ul>').addClass(r.className||"").data({contextMenu:r,contextMenuRoot:u}),m.each(["callbacks","commands","inputs"],function(e,t){r[t]={},u[t]||(u[t]={})}),u.accesskeys||(u.accesskeys={}),m.each(r.items,function(n,o){var e=m('<li class="context-menu-item"></li>').addClass(o.className||""),t=null,a=null;if(e.on("click",m.noop),"string"!=typeof o&&"cm_separator"!==o.type||(o={type:"cm_seperator"}),o.$node=e.data({contextMenu:r,contextMenuRoot:u,contextMenuKey:n}),void 0!==o.accesskey)for(var s,i=function(e){for(var t,n=e.split(/\s+/),o=[],a=0;t=n[a];a++)t=t.charAt(0).toUpperCase(),o.push(t);return o}(o.accesskey),c=0;s=i[c];c++)if(!u.accesskeys[s]){var l=(u.accesskeys[s]=o).name.match(new RegExp("^(.*?)("+s+")(.*)$","i"));l&&(o._beforeAccesskey=l[1],o._accesskey=l[2],o._afterAccesskey=l[3]);break}if(o.type&&v[o.type])v[o.type].call(e,o,r,u),m.each([r,u],function(e,t){t.commands[n]=o,!m.isFunction(o.callback)||void 0!==t.callbacks[n]&&void 0!==r.type||(t.callbacks[n]=o.callback)});else{switch("cm_seperator"===o.type?e.addClass("context-menu-separator "+u.classNames.notSelectable):"html"===o.type?e.addClass("context-menu-html "+u.classNames.notSelectable):"sub"!==o.type&&o.type?(t=m("<label></label>").appendTo(e),d(o).appendTo(t),e.addClass("context-menu-input"),r.hasTypes=!0,m.each([r,u],function(e,t){t.commands[n]=o,t.inputs[n]=o})):o.items&&(o.type="sub"),o.type){case"cm_seperator":break;case"text":a=m('<input type="text" value="1" name="" />').attr("name","context-menu-input-"+n).val(o.value||"").appendTo(t);break;case"textarea":a=m('<textarea name=""></textarea>').attr("name","context-menu-input-"+n).val(o.value||"").appendTo(t),o.height&&a.height(o.height);break;case"checkbox":a=m('<input type="checkbox" value="1" name="" />').attr("name","context-menu-input-"+n).val(o.value||"").prop("checked",!!o.selected).prependTo(t);break;case"radio":a=m('<input type="radio" value="1" name="" />').attr("name","context-menu-input-"+o.radio).val(o.value||"").prop("checked",!!o.selected).prependTo(t);break;case"select":a=m('<select name=""></select>').attr("name","context-menu-input-"+n).appendTo(t),o.options&&(m.each(o.options,function(e,t){m("<option></option>").val(e).text(t).appendTo(a)}),a.val(o.selected));break;case"sub":d(o).appendTo(e),o.appendTo=o.$node,e.data("contextMenu",o).addClass("context-menu-submenu"),o.callback=null,"function"==typeof o.items.then?$.processPromises(o,u,o.items):$.create(o,u);break;case"html":m(o.html).appendTo(e);break;default:m.each([r,u],function(e,t){t.commands[n]=o,!m.isFunction(o.callback)||void 0!==t.callbacks[n]&&void 0!==r.type||(t.callbacks[n]=o.callback)}),d(o).appendTo(e)}o.type&&"sub"!==o.type&&"html"!==o.type&&"cm_seperator"!==o.type&&(a.on("focus",b.focusInput).on("blur",b.blurInput),o.events&&a.on(o.events,r)),o.icon&&(m.isFunction(o.icon)?o._icon=o.icon.call(this,this,e,n,o):"string"!=typeof o.icon||"fab "!==o.icon.substring(0,4)&&"fas "!==o.icon.substring(0,4)&&"far "!==o.icon.substring(0,4)&&"fal "!==o.icon.substring(0,4)?"string"==typeof o.icon&&"fa-"===o.icon.substring(0,3)?o._icon=u.classNames.icon+" "+u.classNames.icon+"--fa fa "+o.icon:o._icon=u.classNames.icon+" "+u.classNames.icon+"-"+o.icon:(e.addClass(u.classNames.icon+" "+u.classNames.icon+"--fa5"),o._icon=m('<i class="'+o.icon+'"></i>')),"string"==typeof o._icon?e.addClass(o._icon):e.prepend(o._icon))}o.$input=a,o.$label=t,e.appendTo(r.$menu),!r.hasTypes&&m.support.eventSelectstart&&e.on("selectstart.disableTextSelect",b.abortevent)}),r.$node||r.$menu.css("display","none").addClass("context-menu-root"),r.$menu.appendTo(r.appendTo||document.body)},resize:function(e,t){var n;e.css({position:"absolute",display:"block"}),e.data("width",(n=e.get(0)).getBoundingClientRect?Math.ceil(n.getBoundingClientRect().width):e.outerWidth()+1),e.css({position:"static",minWidth:"0px",maxWidth:"100000px"}),e.find("> li > ul").each(function(){$.resize(m(this),!0)}),t||e.find("ul").addBack().css({position:"",display:"",minWidth:"",maxWidth:""}).outerWidth(function(){return m(this).data("width")})},update:function(i,c){var l=this;void 0===c&&(c=i,$.resize(i.$menu));var r=!1;return i.$menu.children().each(function(){var e,t=m(this),n=t.data("contextMenuKey"),o=i.items[n],a=m.isFunction(o.disabled)&&o.disabled.call(l,n,c)||!0===o.disabled;if((e=m.isFunction(o.visible)?o.visible.call(l,n,c):void 0===o.visible||!0===o.visible)&&(r=!0),t[e?"show":"hide"](),t[a?"addClass":"removeClass"](c.classNames.disabled),m.isFunction(o.icon)){t.removeClass(o._icon);var s=o.icon.call(this,l,t,n,o);"string"==typeof s?t.addClass(s):t.prepend(s)}if(o.type)switch(t.find("input, select, textarea").prop("disabled",a),o.type){case"text":case"textarea":o.$input.val(o.value||"");break;case"checkbox":case"radio":o.$input.val(o.value||"").prop("checked",!!o.selected);break;case"select":o.$input.val((0===o.selected?"0":o.selected)||"")}o.$menu&&($.update.call(l,o,c)&&(r=!0))}),r},layer:function(e,t){var n=e.$layer=m('<div id="context-menu-layer"></div>').css({height:p.height(),width:p.width(),display:"block",position:"fixed","z-index":t,top:0,left:0,opacity:0,filter:"alpha(opacity=0)","background-color":"#000"}).data("contextMenuRoot",e).insertBefore(this).on("contextmenu",b.abortevent).on("mousedown",b.layerClick);return void 0===document.body.style.maxWidth&&n.css({position:"absolute",height:m(document).height()}),n},processPromises:function(e,t,n){function o(e,t,n){void 0===n?(n={error:{name:"No items and no error item",icon:"context-menu-icon context-menu-icon-quit"}},window.console&&(console.error||console.log).call(console,'When you reject a promise, provide an "items" object, equal to normal sub-menu items')):"string"==typeof n&&(n={error:{name:n}}),a(e,t,n)}function a(e,t,n){void 0!==t.$menu&&t.$menu.is(":visible")&&(e.$node.removeClass(t.classNames.iconLoadingClass),e.items=n,$.create(e,t,!0),$.update(e,t),t.positionSubmenu.call(e.$node,e.$menu))}e.$node.addClass(t.classNames.iconLoadingClass),n.then(function(e,t,n){void 0===n&&o(void 0),a(e,t,n)}.bind(this,e,t),o.bind(this,e,t))},activated:function(e){var t=e.$menu,n=t.offset(),o=m(window).height(),a=m(window).scrollTop(),s=t.height();o<s?t.css({height:o+"px","overflow-x":"hidden","overflow-y":"auto",top:a+"px"}):(n.top<a||n.top+s>a+o)&&t.css({top:a+"px"})}};function l(e){return e.id&&m('label[for="'+e.id+'"]').val()||e.name}m.fn.contextMenu=function(e){var t=this,n=e;if(0<this.length)if(void 0===e)this.first().trigger("contextmenu");else if(void 0!==e.x&&void 0!==e.y)this.first().trigger(m.Event("contextmenu",{pageX:e.x,pageY:e.y,mouseButton:e.button}));else if("hide"===e){var o=this.first().data("contextMenu")?this.first().data("contextMenu").$menu:null;o&&o.trigger("contextmenu:hide")}else"destroy"===e?m.contextMenu("destroy",{context:this}):m.isPlainObject(e)?(e.context=this,m.contextMenu("create",e)):e?this.removeClass("context-menu-disabled"):e||this.addClass("context-menu-disabled");else m.each(x,function(){this.selector===t.selector&&(n.data=this,m.extend(n.data,{trigger:"demand"}))}),b.contextmenu.call(n.target,n);return this},m.contextMenu=function(e,t){"string"!=typeof e&&(t=e,e="create"),"string"==typeof t?t={selector:t}:void 0===t&&(t={});var n=m.extend(!0,{},g,t||{}),o=m(document),a=o,s=!1;switch(n.context&&n.context.length?(a=m(n.context).first(),n.context=a.get(0),s=!m(n.context).is(document)):n.context=document,e){case"update":if(s)$.update(a);else for(var i in x)x.hasOwnProperty(i)&&$.update(x[i]);break;case"create":if(!n.selector)throw new Error("No selector specified");if(n.selector.match(/.context-menu-(list|item|input)($|\s)/))throw new Error('Cannot bind to selector "'+n.selector+'" as it contains a reserved className');if(!n.build&&(!n.items||m.isEmptyObject(n.items)))throw new Error("No Items specified");if(f++,n.ns=".contextMenu"+f,s||(h[n.selector]=n.ns),(x[n.ns]=n).trigger||(n.trigger="right"),!d){var c="click"===n.itemClickEvent?"click.contextMenu":"mouseup.contextMenu",l={"contextmenu:focus.contextMenu":b.focusItem,"contextmenu:blur.contextMenu":b.blurItem,"contextmenu.contextMenu":b.abortevent,"mouseenter.contextMenu":b.itemMouseenter,"mouseleave.contextMenu":b.itemMouseleave};l[c]=b.itemClick,o.on({"contextmenu:hide.contextMenu":b.hideMenu,"prevcommand.contextMenu":b.prevItem,"nextcommand.contextMenu":b.nextItem,"contextmenu.contextMenu":b.abortevent,"mouseenter.contextMenu":b.menuMouseenter,"mouseleave.contextMenu":b.menuMouseleave},".context-menu-list").on("mouseup.contextMenu",".context-menu-input",b.inputClick).on(l,".context-menu-item"),d=!0}switch(a.on("contextmenu"+n.ns,n.selector,n,b.contextmenu),s&&a.on("remove"+n.ns,function(){m(this).contextMenu("destroy")}),n.trigger){case"hover":a.on("mouseenter"+n.ns,n.selector,n,b.mouseenter).on("mouseleave"+n.ns,n.selector,n,b.mouseleave);break;case"left":a.on("click"+n.ns,n.selector,n,b.click);break;case"touchstart":a.on("touchstart"+n.ns,n.selector,n,b.click)}n.build||$.create(n);break;case"destroy":var r;if(s){var u=n.context;m.each(x,function(e,t){if(!t)return!0;if(!m(u).is(t.selector))return!0;(r=m(".context-menu-list").filter(":visible")).length&&r.data().contextMenuRoot.$trigger.is(m(t.context).find(t.selector))&&r.trigger("contextmenu:hide",{force:!0});try{x[t.ns].$menu&&x[t.ns].$menu.remove(),delete x[t.ns]}catch(e){x[t.ns]=null}return m(t.context).off(t.ns),!0})}else if(n.selector){if(h[n.selector]){(r=m(".context-menu-list").filter(":visible")).length&&r.data().contextMenuRoot.$trigger.is(n.selector)&&r.trigger("contextmenu:hide",{force:!0});try{x[h[n.selector]].$menu&&x[h[n.selector]].$menu.remove(),delete x[h[n.selector]]}catch(e){x[h[n.selector]]=null}o.off(h[n.selector])}}else o.off(".contextMenu .contextMenuAutoHide"),m.each(x,function(e,t){m(t.context).off(t.ns)}),h={},f=0,d=!(x={}),m("#context-menu-layer, .context-menu-list").remove();break;case"html5":(!m.support.htmlCommand&&!m.support.htmlMenuitem||"boolean"==typeof t&&t)&&m('menu[type="context"]').each(function(){this.id&&m.contextMenu({selector:"[contextmenu="+this.id+"]",items:m.contextMenu.fromMenu(this)})}).css("display","none");break;default:throw new Error('Unknown operation "'+e+'"')}return this},m.contextMenu.setInputValues=function(e,n){void 0===n&&(n={}),m.each(e.inputs,function(e,t){switch(t.type){case"text":case"textarea":t.value=n[e]||"";break;case"checkbox":t.selected=!!n[e];break;case"radio":t.selected=(n[t.radio]||"")===t.value;break;case"select":t.selected=n[e]||""}})},m.contextMenu.getInputValues=function(e,n){return void 0===n&&(n={}),m.each(e.inputs,function(e,t){switch(t.type){case"text":case"textarea":case"select":n[e]=t.$input.val();break;case"checkbox":n[e]=t.$input.prop("checked");break;case"radio":t.$input.prop("checked")&&(n[t.radio]=t.value)}}),n},m.contextMenu.fromMenu=function(e){var t={};return function s(i,e,c){return c||(c=0),e.each(function(){var e,t,n=m(this),o=this,a=this.nodeName.toLowerCase();switch("label"===a&&n.find("input, textarea, select").length&&(e=n.text(),a=(o=(n=n.children().first()).get(0)).nodeName.toLowerCase()),a){case"menu":t={name:n.attr("label"),items:{}},c=s(t.items,n.children(),c);break;case"a":case"button":t={name:n.text(),disabled:!!n.attr("disabled"),callback:function(){n.get(0).click()}};break;case"menuitem":case"command":switch(n.attr("type")){case void 0:case"command":case"menuitem":t={name:n.attr("label"),disabled:!!n.attr("disabled"),icon:n.attr("icon"),callback:function(){n.get(0).click()}};break;case"checkbox":t={type:"checkbox",disabled:!!n.attr("disabled"),name:n.attr("label"),selected:!!n.attr("checked")};break;case"radio":t={type:"radio",disabled:!!n.attr("disabled"),name:n.attr("label"),radio:n.attr("radiogroup"),value:n.attr("id"),selected:!!n.attr("checked")};break;default:t=void 0}break;case"hr":t="-------";break;case"input":switch(n.attr("type")){case"text":t={type:"text",name:e||l(o),disabled:!!n.attr("disabled"),value:n.val()};break;case"checkbox":t={type:"checkbox",name:e||l(o),disabled:!!n.attr("disabled"),selected:!!n.attr("checked")};break;case"radio":t={type:"radio",name:e||l(o),disabled:!!n.attr("disabled"),radio:!!n.attr("name"),value:n.val(),selected:!!n.attr("checked")};break;default:t=void 0}break;case"select":t={type:"select",name:e||l(o),disabled:!!n.attr("disabled"),selected:n.val(),options:{}},n.children().each(function(){t.options[this.value]=m(this).text()});break;case"textarea":t={type:"textarea",name:e||l(o),disabled:!!n.attr("disabled"),value:n.val()};break;case"label":break;default:t={type:"html",html:n.clone(!0)}}t&&(i["key"+ ++c]=t)}),c}(t,m(e).children()),t},m.contextMenu.defaults=g,m.contextMenu.types=v,m.contextMenu.handle=b,m.contextMenu.op=$,m.contextMenu.menus=x});
diff --git a/ruoyi-admin/src/main/resources/static/js/jquery.i18n.properties.min.js b/ruoyi-admin/src/main/resources/static/js/jquery.i18n.properties.min.js
new file mode 100644
index 0000000..b6cf345
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/js/jquery.i18n.properties.min.js
@@ -0,0 +1,13 @@
+/******************************************************************************
+ * jquery.i18n.properties
+ *
+ * Dual licensed under the GPL (http://dev.jquery.com/browser/trunk/jquery/GPL-LICENSE.txt) and
+ * MIT (http://dev.jquery.com/browser/trunk/jquery/MIT-LICENSE.txt) licenses.
+ *
+ * @version     1.2.7
+ * @url         https://github.com/jquery-i18n-properties/jquery-i18n-properties
+ * @inspiration Localisation assistance for jQuery (http://keith-wood.name/localisation.html)
+ *              by Keith Wood (kbwood{at}iinet.com.au) June 2007
+ *
+ *****************************************************************************/
+(function($){$.i18n={};$.i18n.map={};var debug=function(message){window.console&&console.log("i18n::"+message)};$.i18n.properties=function(settings){var defaults={name:"Messages",language:"",path:"",namespace:null,mode:"vars",cache:false,debug:false,encoding:"UTF-8",async:false,callback:null};settings=$.extend(defaults,settings);if(settings.namespace&&typeof settings.namespace=="string"){if(settings.namespace.match(/^[a-z]*$/)){$.i18n.map[settings.namespace]={}}else{debug("Namespaces can only be lower case letters, a - z");settings.namespace=null}}if(!settings.path.match(/\/$/)){settings.path+="/"}settings.language=this.normaliseLanguageCode(settings);var files=(settings.name&&settings.name.constructor===Array)?settings.name:[settings.name];settings.totalFiles=(files.length*2)+((settings.language.length>=5)?files.length:0);if(settings.debug){debug("totalFiles: "+settings.totalFiles)}settings.filesLoaded=0;files.forEach(function(file){var defaultFileName,shortFileName,longFileName,fileNames;defaultFileName=settings.path+file+".properties";var shortCode=settings.language.substring(0,2);shortFileName=settings.path+file+"_"+shortCode+".properties";if(settings.language.length>=5){var longCode=settings.language.substring(0,5);longFileName=settings.path+file+"_"+longCode+".properties";fileNames=[defaultFileName,shortFileName,longFileName]}else{fileNames=[defaultFileName,shortFileName]}fileNames=[longFileName];loadAndParseFiles(fileNames,settings)});if(settings.callback&&!settings.async){settings.callback()}};$.i18n.prop=function(key){var args=[].slice.call(arguments);var phvList,namespace;if(args.length==2){if($.isArray(args[1])){phvList=args[1]}else{if(typeof args[1]==="object"){namespace=args[1].namespace;var replacements=args[1].replacements;args.splice(-1,1);if(replacements){Array.prototype.push.apply(args,replacements)}}}}var value=(namespace)?$.i18n.map[namespace][key]:$.i18n.map[key];if(value===null){return"["+((namespace)?namespace+"#"+key:key)+"]"}var i;if(typeof(value)=="string"){i=0;while((i=value.indexOf("\\",i))!=-1){if(value.charAt(i+1)=="t"){value=value.substring(0,i)+"\t"+value.substring((i++)+2)}else{if(value.charAt(i+1)=="r"){value=value.substring(0,i)+"\r"+value.substring((i++)+2)}else{if(value.charAt(i+1)=="n"){value=value.substring(0,i)+"\n"+value.substring((i++)+2)}else{if(value.charAt(i+1)=="f"){value=value.substring(0,i)+"\f"+value.substring((i++)+2)}else{if(value.charAt(i+1)=="\\"){value=value.substring(0,i)+"\\"+value.substring((i++)+2)}else{value=value.substring(0,i)+value.substring(i+1)}}}}}}var arr=[],j,index;i=0;while(i<value.length){if(value.charAt(i)=="'"){if(i==value.length-1){value=value.substring(0,i)}else{if(value.charAt(i+1)=="'"){value=value.substring(0,i)+value.substring(++i)}else{j=i+2;while((j=value.indexOf("'",j))!=-1){if(j==value.length-1||value.charAt(j+1)!="'"){value=value.substring(0,i)+value.substring(i+1,j)+value.substring(j+1);i=j-1;break}else{value=value.substring(0,j)+value.substring(++j)}}if(j==-1){value=value.substring(0,i)+value.substring(i+1)}}}}else{if(value.charAt(i)=="{"){j=value.indexOf("}",i+1);if(j==-1){i++}else{index=parseInt(value.substring(i+1,j));if(!isNaN(index)&&index>=0){var s=value.substring(0,i);if(s!==""){arr.push(s)}arr.push(index);i=0;value=value.substring(j+1)}else{i=j+1}}}else{i++}}}if(value!==""){arr.push(value)}value=arr;if(namespace){$.i18n.map[settings.namespace][key]=arr}else{$.i18n.map[key]=arr}}if(typeof(value)=="undefined"||value.length===0){return key}if(value.length==1&&typeof(value[0])=="string"){return value[0]}var str="";for(i=0,j=value.length;i<j;i++){if(typeof(value[i])=="string"){str+=value[i]}else{if(phvList&&value[i]<phvList.length){str+=phvList[value[i]]}else{if(!phvList&&value[i]+1<args.length){str+=args[value[i]+1]}else{str+="{"+value[i]+"}"}}}}return str};function callbackIfComplete(settings){if(settings.debug){debug("callbackIfComplete()");debug("totalFiles: "+settings.totalFiles);debug("filesLoaded: "+settings.filesLoaded)}if(settings.async){if(settings.filesLoaded===settings.totalFiles){if(settings.callback){settings.callback()}}}}function loadAndParseFiles(fileNames,settings){if(settings.debug){debug("loadAndParseFiles")}if(fileNames!==null&&fileNames.length>0){loadAndParseFile(fileNames[0],settings,function(){fileNames.shift();loadAndParseFiles(fileNames,settings)})}else{callbackIfComplete(settings)}}function loadAndParseFile(filename,settings,nextFile){if(settings.debug){debug("loadAndParseFile('"+filename+"')");debug("totalFiles: "+settings.totalFiles);debug("filesLoaded: "+settings.filesLoaded)}if(filename!==null&&typeof filename!=="undefined"){$.ajax({url:filename,async:settings.async,cache:settings.cache,dataType:"text",success:function(data,status){if(settings.debug){debug("Succeeded in downloading "+filename+".");debug(data)}parseData(data,settings);nextFile()},error:function(jqXHR,textStatus,errorThrown){if(settings.debug){debug("Failed to download or parse "+filename+". errorThrown: "+errorThrown)}if(jqXHR.status===404){settings.totalFiles-=1}nextFile()}})}}function parseData(data,settings){var parsed="";var lines=data.split(/\n/);var regPlaceHolder=/(\{\d+})/g;var regRepPlaceHolder=/\{(\d+)}/g;var unicodeRE=/(\\u.{4})/ig;for(var i=0,j=lines.length;i<j;i++){var line=lines[i];line=line.trim();if(line.length>0&&line.match("^#")!="#"){var pair=line.split("=");if(pair.length>0){var name=decodeURI(pair[0]).trim();var value=pair.length==1?"":pair[1];while(value.search(/\\$/)!=-1){value=value.substring(0,value.length-1);value+=lines[++i].trimRight()}for(var s=2;s<pair.length;s++){value+="="+pair[s]}value=value.trim();if(settings.mode=="map"||settings.mode=="both"){var unicodeMatches=value.match(unicodeRE);if(unicodeMatches){unicodeMatches.forEach(function(match){value=value.replace(match,unescapeUnicode(match))})}if(settings.namespace){$.i18n.map[settings.namespace][name]=value}else{$.i18n.map[name]=value}}if(settings.mode=="vars"||settings.mode=="both"){value=value.replace(/"/g,'\\"');checkKeyNamespace(name);if(regPlaceHolder.test(value)){var parts=value.split(regPlaceHolder);var first=true;var fnArgs="";var usedArgs=[];parts.forEach(function(part){if(regPlaceHolder.test(part)&&(usedArgs.length===0||usedArgs.indexOf(part)==-1)){if(!first){fnArgs+=","}fnArgs+=part.replace(regRepPlaceHolder,"v$1");usedArgs.push(part);first=false}});parsed+=name+"=function("+fnArgs+"){";var fnExpr='"'+value.replace(regRepPlaceHolder,'"+v$1+"')+'"';parsed+="return "+fnExpr+";"+"};"}else{parsed+=name+'="'+value+'";'}}}}}eval(parsed);settings.filesLoaded+=1}function checkKeyNamespace(key){var regDot=/\./;if(regDot.test(key)){var fullname="";var names=key.split(/\./);for(var i=0,j=names.length;i<j;i++){var name=names[i];if(i>0){fullname+="."}fullname+=name;if(eval("typeof "+fullname+' == "undefined"')){eval(fullname+"={};")}}}}$.i18n.normaliseLanguageCode=function(settings){var lang=settings.language;if(!lang||lang.length<2){if(settings.debug){debug("No language supplied. Pulling it from the browser ...")}lang=(navigator.languages&&navigator.languages.length>0)?navigator.languages[0]:(navigator.language||navigator.userLanguage||"en");if(settings.debug){debug("Language from browser: "+lang)}}lang=lang.toLowerCase();lang=lang.replace(/-/,"_");if(lang.length>3){lang=lang.substring(0,3)+lang.substring(3).toUpperCase()}return lang};function unescapeUnicode(str){var codes=[];var code=parseInt(str.substr(2),16);if(code>=0&&code<Math.pow(2,16)){codes.push(code)}return codes.reduce(function(acc,val){return acc+String.fromCharCode(val)},"")}})(jQuery);
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/js/jquery.min.js b/ruoyi-admin/src/main/resources/static/js/jquery.min.js
new file mode 100644
index 0000000..4477e65
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/js/jquery.min.js
@@ -0,0 +1,2 @@
+/*! jQuery v3.7.1 | (c) OpenJS Foundation and other contributors | jquery.org/license */
+!function(e,t){"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document){throw Error("jQuery requires a window with a document")}return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(e,t){function n(e,t,n){n=n||Te;var r,i,o=n.createElement("script");if(o.text=e,t){for(r in we){i=t[r]||t.getAttribute&&t.getAttribute(r),i&&o.setAttribute(r,i)}}n.head.appendChild(o).parentNode.removeChild(o)}function r(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?de[he.call(e)]||"object":typeof e}function i(e){var t=!!e&&"length" in e&&e.length,n=r(e);return xe(e)||be(e)?!1:"array"===n||0===t||"number"==typeof t&&t>0&&t-1 in e}function o(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}function a(e,t){return t?"\x00"===e?"�":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e}function s(e,t,n){return xe(t)?ke.grep(e,function(e,r){return !!t.call(e,r,e)!==n}):t.nodeType?ke.grep(e,function(e){return e===t!==n}):"string"!=typeof t?ke.grep(e,function(e){return pe.call(t,e)>-1!==n}):ke.filter(t,e,n)}function u(e,t){for(;(e=e[t])&&1!==e.nodeType;){}return e}function l(e){var t={};return ke.each(e.match(_e)||[],function(e,n){t[n]=!0}),t}function c(e){return e}function f(e){throw e}function p(e,t,n,r){var i;try{e&&xe(i=e.promise)?i.call(e).done(t).fail(n):e&&xe(i=e.then)?i.call(e,t,n):t.apply(void 0,[e].slice(r))}catch(e){n.apply(void 0,[e])}}function d(){Te.removeEventListener("DOMContentLoaded",d),e.removeEventListener("load",d),ke.ready()}function h(e,t){return t.toUpperCase()}function g(e){return e.replace(Ve,"ms-").replace(Ge,h)}function v(){this.expando=ke.expando+v.uid++}function m(e){return"true"===e?!0:"false"===e?!1:"null"===e?null:e===+e+""?+e:Ke.test(e)?JSON.parse(e):e}function y(e,t,n){var r;if(void 0===n&&1===e.nodeType){if(r="data-"+t.replace(Ze,"-$&").toLowerCase(),n=e.getAttribute(r),"string"==typeof n){try{n=m(n)}catch(i){}Je.set(e,t,n)}else{n=void 0}}return n}function x(e,t,n,r){var i,o,a=20,s=r?function(){return r.cur()}:function(){return ke.css(e,t,"")},u=s(),l=n&&n[3]||(ke.cssNumber[t]?"":"px"),c=e.nodeType&&(ke.cssNumber[t]||"px"!==l&&+u)&&tt.exec(ke.css(e,t));if(c&&c[3]!==l){for(u/=2,l=l||c[3],c=+u||1;a--;){ke.style(e,t,c+l),(1-o)*(1-(o=s()/u||0.5))<=0&&(a=0),c/=o}c=2*c,ke.style(e,t,c+l),n=n||[]}return n&&(c=+c||+u||0,i=n[1]?c+(n[1]+1)*n[2]:+n[2],r&&(r.unit=l,r.start=c,r.end=i)),i}function b(e){var t,n=e.ownerDocument,r=e.nodeName,i=st[r];return i?i:(t=n.body.appendChild(n.createElement(r)),i=ke.css(t,"display"),t.parentNode.removeChild(t),"none"===i&&(i="block"),st[r]=i,i)}function T(e,t){for(var n,r,i=[],o=0,a=e.length;a>o;o++){r=e[o],r.style&&(n=r.style.display,t?("none"===n&&(i[o]=Qe.get(r,"display")||null,i[o]||(r.style.display="")),""===r.style.display&&at(r)&&(i[o]=b(r))):"none"!==n&&(i[o]="none",Qe.set(r,"display",n)))}for(o=0;a>o;o++){null!=i[o]&&(e[o].style.display=i[o])}return e}function w(e,t){var n;return n=void 0!==e.getElementsByTagName?e.getElementsByTagName(t||"*"):void 0!==e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&o(e,t)?ke.merge([e],n):n}function C(e,t){for(var n=0,r=e.length;r>n;n++){Qe.set(e[n],"globalEval",!t||Qe.get(t[n],"globalEval"))}}function S(e,t,n,i,o){for(var a,s,u,l,c,f,p=t.createDocumentFragment(),d=[],h=0,g=e.length;g>h;h++){if(a=e[h],a||0===a){if("object"===r(a)){ke.merge(d,a.nodeType?[a]:a)}else{if(pt.test(a)){for(s=s||p.appendChild(t.createElement("div")),u=(lt.exec(a)||["",""])[1].toLowerCase(),l=ft[u]||ft._default,s.innerHTML=l[1]+ke.htmlPrefilter(a)+l[2],f=l[0];f--;){s=s.lastChild}ke.merge(d,s.childNodes),s=p.firstChild,s.textContent=""}else{d.push(t.createTextNode(a))}}}}for(p.textContent="",h=0;a=d[h++];){if(i&&ke.inArray(a,i)>-1){o&&o.push(a)}else{if(c=it(a),s=w(p.appendChild(a),"script"),c&&C(s),n){for(f=0;a=s[f++];){ct.test(a.type||"")&&n.push(a)}}}}return p}function k(){return !0}function E(){return !1}function j(e,t,n,r,i,o){var a,s;if("object"==typeof t){"string"!=typeof n&&(r=r||n,n=void 0);for(s in t){j(e,s,n,r,t[s],o)}return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),i===!1){i=E}else{if(!i){return e}}return 1===o&&(a=i,i=function(e){return ke().off(e),a.apply(this,arguments)},i.guid=a.guid||(a.guid=ke.guid++)),e.each(function(){ke.event.add(this,t,i,r,n)})}function A(e,t,n){return n?(Qe.set(e,t,!1),void ke.event.add(e,t,{namespace:!1,handler:function(e){var n,r=Qe.get(this,t);if(1&e.isTrigger&&this[t]){if(r){(ke.event.special[t]||{}).delegateType&&e.stopPropagation()}else{if(r=le.call(arguments),Qe.set(this,t,r),this[t](),n=Qe.get(this,t),Qe.set(this,t,!1),r!==n){return e.stopImmediatePropagation(),e.preventDefault(),n}}}else{r&&(Qe.set(this,t,ke.event.trigger(r[0],r.slice(1),this)),e.stopPropagation(),e.isImmediatePropagationStopped=k)}}})):void (void 0===Qe.get(e,t)&&ke.event.add(e,t,k))}function D(e,t){return o(e,"table")&&o(11!==t.nodeType?t:t.firstChild,"tr")?ke(e).children("tbody")[0]||e:e}function N(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function q(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function L(e,t){var n,r,i,o,a,s,u;if(1===t.nodeType){if(Qe.hasData(e)&&(o=Qe.get(e),u=o.events)){Qe.remove(t,"handle events");for(i in u){for(n=0,r=u[i].length;r>n;n++){ke.event.add(t,i,u[i][n])}}}Je.hasData(e)&&(a=Je.access(e),s=ke.extend({},a),Je.set(t,s))}}function H(e,t){var n=t.nodeName.toLowerCase();"input"===n&&ut.test(e.type)?t.checked=e.checked:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}function O(e,t,r,i){t=ce(t);var o,a,s,u,l,c,f=0,p=e.length,d=p-1,h=t[0],g=xe(h);if(g||p>1&&"string"==typeof h&&!ye.checkClone&&gt.test(h)){return e.each(function(n){var o=e.eq(n);g&&(t[0]=h.call(this,n,o.html())),O(o,t,r,i)})}if(p&&(o=S(t,e[0].ownerDocument,!1,e,i),a=o.firstChild,1===o.childNodes.length&&(o=a),a||i)){for(s=ke.map(w(o,"script"),N),u=s.length;p>f;f++){l=o,f!==d&&(l=ke.clone(l,!0,!0),u&&ke.merge(s,w(l,"script"))),r.call(e[f],l,f)}if(u){for(c=s[s.length-1].ownerDocument,ke.map(s,q),f=0;u>f;f++){l=s[f],ct.test(l.type||"")&&!Qe.access(l,"globalEval")&&ke.contains(c,l)&&(l.src&&"module"!==(l.type||"").toLowerCase()?ke._evalUrl&&!l.noModule&&ke._evalUrl(l.src,{nonce:l.nonce||l.getAttribute("nonce")},c):n(l.textContent.replace(vt,""),l,c))}}}return e}function P(e,t,n){for(var r,i=t?ke.filter(t,e):e,o=0;null!=(r=i[o]);o++){n||1!==r.nodeType||ke.cleanData(w(r)),r.parentNode&&(n&&it(r)&&C(w(r,"script")),r.parentNode.removeChild(r))}return e}function M(e,t,n){var r,i,o,a,s=yt.test(t),u=e.style;return n=n||xt(e),n&&(a=n.getPropertyValue(t)||n[t],s&&a&&(a=a.replace(Ne,"$1")||void 0),""!==a||it(e)||(a=ke.style(e,t)),!ye.pixelBoxStyles()&&mt.test(a)&&Tt.test(t)&&(r=u.width,i=u.minWidth,o=u.maxWidth,u.minWidth=u.maxWidth=u.width=a,a=n.width,u.width=r,u.minWidth=i,u.maxWidth=o)),void 0!==a?a+"":a}function R(e,t){return{get:function(){return e()?void delete this.get:(this.get=t).apply(this,arguments)}}}function I(e){for(var t=e[0].toUpperCase()+e.slice(1),n=wt.length;n--;){if(e=wt[n]+t,e in Ct){return e}}}function W(e){var t=ke.cssProps[e]||St[e];return t?t:e in Ct?e:St[e]=I(e)||e}function F(e,t,n){var r=tt.exec(t);return r?Math.max(0,r[2]-(n||0))+(r[3]||"px"):t}function B(e,t,n,r,i,o){var a="width"===t?1:0,s=0,u=0,l=0;if(n===(r?"border":"content")){return 0}for(;4>a;a+=2){"margin"===n&&(l+=ke.css(e,n+nt[a],!0,i)),r?("content"===n&&(u-=ke.css(e,"padding"+nt[a],!0,i)),"margin"!==n&&(u-=ke.css(e,"border"+nt[a]+"Width",!0,i))):(u+=ke.css(e,"padding"+nt[a],!0,i),"padding"!==n?u+=ke.css(e,"border"+nt[a]+"Width",!0,i):s+=ke.css(e,"border"+nt[a]+"Width",!0,i))}return !r&&o>=0&&(u+=Math.max(0,Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-o-u-s-0.5))||0),u+l}function _(e,t,n){var r=xt(e),i=!ye.boxSizingReliable()||n,a=i&&"border-box"===ke.css(e,"boxSizing",!1,r),s=a,u=M(e,t,r),l="offset"+t[0].toUpperCase()+t.slice(1);if(mt.test(u)){if(!n){return u}u="auto"}return(!ye.boxSizingReliable()&&a||!ye.reliableTrDimensions()&&o(e,"tr")||"auto"===u||!parseFloat(u)&&"inline"===ke.css(e,"display",!1,r))&&e.getClientRects().length&&(a="border-box"===ke.css(e,"boxSizing",!1,r),s=l in e,s&&(u=e[l])),u=parseFloat(u)||0,u+B(e,t,n||(a?"border":"content"),s,r,u)+"px"}function z(e,t,n,r,i){return new z.prototype.init(e,t,n,r,i)}function X(){Dt&&(Te.hidden===!1&&e.requestAnimationFrame?e.requestAnimationFrame(X):e.setTimeout(X,ke.fx.interval),ke.fx.tick())}function U(){return e.setTimeout(function(){At=void 0}),At=Date.now()}function V(e,t){var n,r=0,i={height:e};for(t=t?1:0;4>r;r+=2-t){n=nt[r],i["margin"+n]=i["padding"+n]=e}return t&&(i.opacity=i.width=e),i}function G(e,t,n){for(var r,i=(J.tweeners[t]||[]).concat(J.tweeners["*"]),o=0,a=i.length;a>o;o++){if(r=i[o].call(n,t,e)){return r}}}function Y(e,t,n){var r,i,o,a,s,u,l,c,f="width" in t||"height" in t,p=this,d={},h=e.style,g=e.nodeType&&at(e),v=Qe.get(e,"fxshow");n.queue||(a=ke._queueHooks(e,"fx"),null==a.unqueued&&(a.unqueued=0,s=a.empty.fire,a.empty.fire=function(){a.unqueued||s()}),a.unqueued++,p.always(function(){p.always(function(){a.unqueued--,ke.queue(e,"fx").length||a.empty.fire()})}));for(r in t){if(i=t[r],Nt.test(i)){if(delete t[r],o=o||"toggle"===i,i===(g?"hide":"show")){if("show"!==i||!v||void 0===v[r]){continue}g=!0}d[r]=v&&v[r]||ke.style(e,r)}}if(u=!ke.isEmptyObject(t),u||!ke.isEmptyObject(d)){f&&1===e.nodeType&&(n.overflow=[h.overflow,h.overflowX,h.overflowY],l=v&&v.display,null==l&&(l=Qe.get(e,"display")),c=ke.css(e,"display"),"none"===c&&(l?c=l:(T([e],!0),l=e.style.display||l,c=ke.css(e,"display"),T([e]))),("inline"===c||"inline-block"===c&&null!=l)&&"none"===ke.css(e,"float")&&(u||(p.done(function(){h.display=l}),null==l&&(c=h.display,l="none"===c?"":c)),h.display="inline-block")),n.overflow&&(h.overflow="hidden",p.always(function(){h.overflow=n.overflow[0],h.overflowX=n.overflow[1],h.overflowY=n.overflow[2]})),u=!1;for(r in d){u||(v?"hidden" in v&&(g=v.hidden):v=Qe.access(e,"fxshow",{display:l}),o&&(v.hidden=!g),g&&T([e],!0),p.done(function(){g||T([e]),Qe.remove(e,"fxshow");for(r in d){ke.style(e,r,d[r])}})),u=G(g?v[r]:0,r,p),r in v||(v[r]=u.start,g&&(u.end=u.start,u.start=0))}}}function Q(e,t){var n,r,i,o,a;for(n in e){if(r=g(n),i=t[r],o=e[n],Array.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),a=ke.cssHooks[r],a&&"expand" in a){o=a.expand(o),delete e[r];for(n in o){n in e||(e[n]=o[n],t[n]=i)}}else{t[r]=i}}}function J(e,t,n){var r,i,o=0,a=J.prefilters.length,s=ke.Deferred().always(function(){delete u.elem}),u=function(){if(i){return !1}for(var t=At||U(),n=Math.max(0,l.startTime+l.duration-t),r=n/l.duration||0,o=1-r,a=0,u=l.tweens.length;u>a;a++){l.tweens[a].run(o)}return s.notifyWith(e,[l,o,n]),1>o&&u?n:(u||s.notifyWith(e,[l,1,0]),s.resolveWith(e,[l]),!1)},l=s.promise({elem:e,props:ke.extend({},t),opts:ke.extend(!0,{specialEasing:{},easing:ke.easing._default},n),originalProperties:t,originalOptions:n,startTime:At||U(),duration:n.duration,tweens:[],createTween:function(t,n){var r=ke.Tween(e,l.opts,t,n,l.opts.specialEasing[t]||l.opts.easing);return l.tweens.push(r),r},stop:function(t){var n=0,r=t?l.tweens.length:0;if(i){return this}for(i=!0;r>n;n++){l.tweens[n].run(1)}return t?(s.notifyWith(e,[l,1,0]),s.resolveWith(e,[l,t])):s.rejectWith(e,[l,t]),this}}),c=l.props;for(Q(c,l.opts.specialEasing);a>o;o++){if(r=J.prefilters[o].call(l,e,c,l.opts)){return xe(r.stop)&&(ke._queueHooks(l.elem,l.opts.queue).stop=r.stop.bind(r)),r}}return ke.map(c,G,l),xe(l.opts.start)&&l.opts.start.call(e,l),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always),ke.fx.timer(ke.extend(u,{elem:e,anim:l,queue:l.opts.queue})),l}function K(e){var t=e.match(_e)||[];return t.join(" ")}function Z(e){return e.getAttribute&&e.getAttribute("class")||""}function ee(e){return Array.isArray(e)?e:"string"==typeof e?e.match(_e)||[]:[]}function te(e,t,n,i){var o;if(Array.isArray(t)){ke.each(t,function(t,r){n||Bt.test(e)?i(e,r):te(e+"["+("object"==typeof r&&null!=r?t:"")+"]",r,n,i)})}else{if(n||"object"!==r(t)){i(e,t)}else{for(o in t){te(e+"["+o+"]",t[o],n,i)}}}}function ne(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(_e)||[];if(xe(n)){for(;r=o[i++];){"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}}}function re(e,t,n,r){function i(s){var u;return o[s]=!0,ke.each(e[s]||[],function(e,s){var l=s(t,n,r);return"string"!=typeof l||a||o[l]?a?!(u=l):void 0:(t.dataTypes.unshift(l),i(l),!1)}),u}var o={},a=e===en;return i(t.dataTypes[0])||!o["*"]&&i("*")}function ie(e,t){var n,r,i=ke.ajaxSettings.flatOptions||{};for(n in t){void 0!==t[n]&&((i[n]?e:r||(r={}))[n]=t[n])}return r&&ke.extend(!0,e,r),e}function oe(e,t,n){for(var r,i,o,a,s=e.contents,u=e.dataTypes;"*"===u[0];){u.shift(),void 0===r&&(r=e.mimeType||t.getResponseHeader("Content-Type"))}if(r){for(i in s){if(s[i]&&s[i].test(r)){u.unshift(i);break}}}if(u[0] in n){o=u[0]}else{for(i in n){if(!u[0]||e.converters[i+" "+u[0]]){o=i;break}a||(a=i)}o=o||a}return o?(o!==u[0]&&u.unshift(o),n[o]):void 0}function ae(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1]){for(a in e.converters){l[a.toLowerCase()]=e.converters[a]}}for(o=c.shift();o;){if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift()){if("*"===o){o=u}else{if("*"!==u&&u!==o){if(a=l[u+" "+o]||l["* "+o],!a){for(i in l){if(s=i.split(" "),s[1]===o&&(a=l[u+" "+s[0]]||l["* "+s[0]])){a===!0?a=l[i]:l[i]!==!0&&(o=s[0],c.unshift(s[1]));break}}}if(a!==!0){if(a&&e["throws"]){t=a(t)}else{try{t=a(t)}catch(f){return{state:"parsererror",error:a?f:"No conversion from "+u+" to "+o}}}}}}}}return{state:"success",data:t}}var se=[],ue=Object.getPrototypeOf,le=se.slice,ce=se.flat?function(e){return se.flat.call(e)}:function(e){return se.concat.apply([],e)},fe=se.push,pe=se.indexOf,de={},he=de.toString,ge=de.hasOwnProperty,ve=ge.toString,me=ve.call(Object),ye={},xe=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},be=function(e){return null!=e&&e===e.window},Te=e.document,we={type:!0,src:!0,nonce:!0,noModule:!0},Ce="3.7.1",Se=/HTML$/i,ke=function(e,t){return new ke.fn.init(e,t)};ke.fn=ke.prototype={jquery:Ce,constructor:ke,length:0,toArray:function(){return le.call(this)},get:function(e){return null==e?le.call(this):0>e?this[e+this.length]:this[e]},pushStack:function(e){var t=ke.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return ke.each(this,e)},map:function(e){return this.pushStack(ke.map(this,function(t,n){return e.call(t,n,t)}))},slice:function(){return this.pushStack(le.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},even:function(){return this.pushStack(ke.grep(this,function(e,t){return(t+1)%2}))},odd:function(){return this.pushStack(ke.grep(this,function(e,t){return t%2}))},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:fe,sort:se.sort,splice:se.splice},ke.extend=ke.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for("boolean"==typeof a&&(l=a,a=arguments[s]||{},s++),"object"==typeof a||xe(a)||(a={}),s===u&&(a=this,s--);u>s;s++){if(null!=(e=arguments[s])){for(t in e){r=e[t],"__proto__"!==t&&a!==r&&(l&&r&&(ke.isPlainObject(r)||(i=Array.isArray(r)))?(n=a[t],o=i&&!Array.isArray(n)?[]:i||ke.isPlainObject(n)?n:{},i=!1,a[t]=ke.extend(l,o,r)):void 0!==r&&(a[t]=r))}}}return a},ke.extend({expando:"jQuery"+(Ce+Math.random()).replace(/\D/g,""),isReady:!0,error:function(e){throw Error(e)},noop:function(){},isPlainObject:function(e){var t,n;return e&&"[object Object]"===he.call(e)?(t=ue(e))?(n=ge.call(t,"constructor")&&t.constructor,"function"==typeof n&&ve.call(n)===me):!0:!1},isEmptyObject:function(e){var t;for(t in e){return !1}return !0},globalEval:function(e,t,r){n(e,{nonce:t&&t.nonce},r)},each:function(e,t){var n,r=0;if(i(e)){for(n=e.length;n>r&&t.call(e[r],r,e[r])!==!1;r++){}}else{for(r in e){if(t.call(e[r],r,e[r])===!1){break}}}return e},text:function(e){var t,n="",r=0,i=e.nodeType;if(!i){for(;t=e[r++];){n+=ke.text(t)}}return 1===i||11===i?e.textContent:9===i?e.documentElement.textContent:3===i||4===i?e.nodeValue:n},makeArray:function(e,t){var n=t||[];return null!=e&&(i(Object(e))?ke.merge(n,"string"==typeof e?[e]:e):fe.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:pe.call(t,e,n)},isXMLDoc:function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return !Se.test(t||n&&n.nodeName||"HTML")},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;n>r;r++){e[i++]=t[r]}return e.length=i,e},grep:function(e,t,n){for(var r,i=[],o=0,a=e.length,s=!n;a>o;o++){r=!t(e[o],o),r!==s&&i.push(e[o])}return i},map:function(e,t,n){var r,o,a=0,s=[];if(i(e)){for(r=e.length;r>a;a++){o=t(e[a],a,n),null!=o&&s.push(o)}}else{for(a in e){o=t(e[a],a,n),null!=o&&s.push(o)}}return ce(s)},guid:1,support:ye}),"function"==typeof Symbol&&(ke.fn[Symbol.iterator]=se[Symbol.iterator]),ke.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(e,t){de["[object "+t+"]"]=t.toLowerCase()});var Ee=se.pop,je=se.sort,Ae=se.splice,De="[\\x20\\t\\r\\n\\f]",Ne=RegExp("^"+De+"+|((?:^|[^\\\\])(?:\\\\.)*)"+De+"+$","g");ke.contains=function(e,t){var n=t&&t.parentNode;return e===n||!(!n||1!==n.nodeType||!(e.contains?e.contains(n):e.compareDocumentPosition&&16&e.compareDocumentPosition(n)))};var qe=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g;ke.escapeSelector=function(e){return(e+"").replace(qe,a)};var Le=Te,He=fe;!function(){function t(){try{return N.activeElement}catch(e){}}function n(e,t,r,i){var o,a,s,u,l,c,d,v=t&&t.ownerDocument,m=t?t.nodeType:9;if(r=r||[],"string"!=typeof e||!e||1!==m&&9!==m&&11!==m){return r}if(!i&&(p(t),t=t||N,L)){if(11!==m&&(l=re.exec(e))){if(o=l[1]){if(9===m){if(!(s=t.getElementById(o))){return r}if(s.id===o){return P.call(r,s),r}}else{if(v&&(s=v.getElementById(o))&&n.contains(t,s)&&s.id===o){return P.call(r,s),r}}}else{if(l[2]){return P.apply(r,t.getElementsByTagName(e)),r}if((o=l[3])&&t.getElementsByClassName){return P.apply(r,t.getElementsByClassName(o)),r}}}if(!(B[e+" "]||H&&H.test(e))){if(d=e,v=t,1===m&&(J.test(e)||Q.test(e))){for(v=ie.test(e)&&f(t.parentNode)||t,v==t&&ye.scope||((u=t.getAttribute("id"))?u=ke.escapeSelector(u):t.setAttribute("id",u=M)),c=h(e),a=c.length;a--;){c[a]=(u?"#"+u:":scope")+" "+g(c[a])}d=c.join(",")}try{return P.apply(r,v.querySelectorAll(d)),r}catch(y){B(e,!0)}finally{u===M&&t.removeAttribute("id")}}}return S(e.replace(Ne,"$1"),t,r,i)}function r(){function e(n,r){return t.push(n+" ")>E.cacheLength&&delete e[t.shift()],e[n+" "]=r}var t=[];return e}function i(e){return e[M]=!0,e}function a(e){var t=N.createElement("fieldset");try{return !!e(t)}catch(n){return !1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function s(e){return function(t){return o(t,"input")&&t.type===e}}function u(e){return function(t){return(o(t,"input")||o(t,"button"))&&t.type===e}}function l(e){return function(t){return"form" in t?t.parentNode&&t.disabled===!1?"label" in t?"label" in t.parentNode?t.parentNode.disabled===e:t.disabled===e:t.isDisabled===e||t.isDisabled!==!e&&ce(t)===e:t.disabled===e:"label" in t?t.disabled===e:!1}}function c(e){return i(function(t){return t=+t,i(function(n,r){for(var i,o=e([],n.length,t),a=o.length;a--;){n[i=o[a]]&&(n[i]=!(r[i]=n[i]))}})})}function f(e){return e&&void 0!==e.getElementsByTagName&&e}function p(e){var t,r=e?e.ownerDocument||e:Le;return r!=N&&9===r.nodeType&&r.documentElement?(N=r,q=N.documentElement,L=!ke.isXMLDoc(N),O=q.matches||q.webkitMatchesSelector||q.msMatchesSelector,q.msMatchesSelector&&Le!=N&&(t=N.defaultView)&&t.top!==t&&t.addEventListener("unload",ue),ye.getById=a(function(e){return q.appendChild(e).id=ke.expando,!N.getElementsByName||!N.getElementsByName(ke.expando).length}),ye.disconnectedMatch=a(function(e){return O.call(e,"*")}),ye.scope=a(function(){return N.querySelectorAll(":scope")}),ye.cssHas=a(function(){try{return N.querySelector(":has(*,:jqfake)"),!1}catch(e){return !0}}),ye.getById?(E.filter.ID=function(e){var t=e.replace(oe,ae);return function(e){return e.getAttribute("id")===t}},E.find.ID=function(e,t){if(void 0!==t.getElementById&&L){var n=t.getElementById(e);return n?[n]:[]}}):(E.filter.ID=function(e){var t=e.replace(oe,ae);return function(e){var n=void 0!==e.getAttributeNode&&e.getAttributeNode("id");return n&&n.value===t}},E.find.ID=function(e,t){if(void 0!==t.getElementById&&L){var n,r,i,o=t.getElementById(e);if(o){if(n=o.getAttributeNode("id"),n&&n.value===e){return[o]}for(i=t.getElementsByName(e),r=0;o=i[r++];){if(n=o.getAttributeNode("id"),n&&n.value===e){return[o]}}}return[]}}),E.find.TAG=function(e,t){return void 0!==t.getElementsByTagName?t.getElementsByTagName(e):t.querySelectorAll(e)},E.find.CLASS=function(e,t){return void 0!==t.getElementsByClassName&&L?t.getElementsByClassName(e):void 0},H=[],a(function(e){var t;q.appendChild(e).innerHTML="<a id='"+M+"' href='' disabled='disabled'></a><select id='"+M+"-\r\\' disabled='disabled'><option selected=''></option></select>",e.querySelectorAll("[selected]").length||H.push("\\["+De+"*(?:value|"+z+")"),e.querySelectorAll("[id~="+M+"-]").length||H.push("~="),e.querySelectorAll("a#"+M+"+*").length||H.push(".#.+[+~]"),e.querySelectorAll(":checked").length||H.push(":checked"),t=N.createElement("input"),t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),q.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&H.push(":enabled",":disabled"),t=N.createElement("input"),t.setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||H.push("\\["+De+"*name"+De+"*="+De+"*(?:''|\"\")")}),ye.cssHas||H.push(":has"),H=H.length&&RegExp(H.join("|")),_=function(e,t){if(e===t){return D=!0,0}var r=!e.compareDocumentPosition-!t.compareDocumentPosition;return r?r:(r=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1,1&r||!ye.sortDetached&&t.compareDocumentPosition(e)===r?e===N||e.ownerDocument==Le&&n.contains(Le,e)?-1:t===N||t.ownerDocument==Le&&n.contains(Le,t)?1:A?pe.call(A,e)-pe.call(A,t):0:4&r?-1:1)},N):N}function d(){}function h(e,t){var r,i,o,a,s,u,l,c=F[e+" "];if(c){return t?0:c.slice(0)}for(s=e,u=[],l=E.preFilter;s;){(!r||(i=Y.exec(s)))&&(i&&(s=s.slice(i[0].length)||s),u.push(o=[])),r=!1,(i=Q.exec(s))&&(r=i.shift(),o.push({value:r,type:i[0].replace(Ne," ")}),s=s.slice(r.length));for(a in E.filter){!(i=ee[a].exec(s))||l[a]&&!(i=l[a](i))||(r=i.shift(),o.push({value:r,type:a,matches:i}),s=s.slice(r.length))}if(!r){break}}return t?s.length:s?n.error(e):F(e,u).slice(0)}function g(e){for(var t=0,n=e.length,r="";n>t;t++){r+=e[t].value}return r}function v(e,t,n){var r=t.dir,i=t.next,a=i||r,s=n&&"parentNode"===a,u=I++;return t.first?function(t,n,i){for(;t=t[r];){if(1===t.nodeType||s){return e(t,n,i)}}return !1}:function(t,n,l){var c,f,p=[R,u];if(l){for(;t=t[r];){if((1===t.nodeType||s)&&e(t,n,l)){return !0}}}else{for(;t=t[r];){if(1===t.nodeType||s){if(f=t[M]||(t[M]={}),i&&o(t,i)){t=t[r]||t}else{if((c=f[a])&&c[0]===R&&c[1]===u){return p[2]=c[2]}if(f[a]=p,p[2]=e(t,n,l)){return !0}}}}}return !1}}function m(e){return e.length>1?function(t,n,r){for(var i=e.length;i--;){if(!e[i](t,n,r)){return !1}}return !0}:e[0]}function y(e,t,r){for(var i=0,o=t.length;o>i;i++){n(e,t[i],r)}return r}function x(e,t,n,r,i){for(var o,a=[],s=0,u=e.length,l=null!=t;u>s;s++){(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),l&&t.push(s))}return a}function b(e,t,n,r,o,a){return r&&!r[M]&&(r=b(r)),o&&!o[M]&&(o=b(o,a)),i(function(i,a,s,u){var l,c,f,p,d=[],h=[],g=a.length,v=i||y(t||"*",s.nodeType?[s]:s,[]),m=!e||!i&&t?v:x(v,d,e,s,u);if(n?(p=o||(i?e:g||r)?[]:a,n(m,p,s,u)):p=m,r){for(l=x(p,h),r(l,[],s,u),c=l.length;c--;){(f=l[c])&&(p[h[c]]=!(m[h[c]]=f))}}if(i){if(o||e){if(o){for(l=[],c=p.length;c--;){(f=p[c])&&l.push(m[c]=f)}o(null,p=[],l,u)}for(c=p.length;c--;){(f=p[c])&&(l=o?pe.call(i,f):d[c])>-1&&(i[l]=!(a[l]=f))}}}else{p=x(p===a?p.splice(g,p.length):p),o?o(null,a,p,u):P.apply(a,p)}})}function T(e){for(var t,n,r,i=e.length,o=E.relative[e[0].type],a=o||E.relative[" "],s=o?1:0,u=v(function(e){return e===t},a,!0),l=v(function(e){return pe.call(t,e)>-1},a,!0),c=[function(e,n,r){var i=!o&&(r||n!=j)||((t=n).nodeType?u(e,n,r):l(e,n,r));return t=null,i}];i>s;s++){if(n=E.relative[e[s].type]){c=[v(m(c),n)]}else{if(n=E.filter[e[s].type].apply(null,e[s].matches),n[M]){for(r=++s;i>r&&!E.relative[e[r].type];r++){}return b(s>1&&m(c),s>1&&g(e.slice(0,s-1).concat({value:" "===e[s-2].type?"*":""})).replace(Ne,"$1"),n,r>s&&T(e.slice(s,r)),i>r&&T(e=e.slice(r)),i>r&&g(e))}c.push(n)}}return m(c)}function w(e,t){var n=t.length>0,r=e.length>0,o=function(i,o,a,s,u){var l,c,f,d=0,h="0",g=i&&[],v=[],m=j,y=i||r&&E.find.TAG("*",u),b=R+=null==m?1:Math.random()||0.1,T=y.length;for(u&&(j=o==N||o||u);h!==T&&null!=(l=y[h]);h++){if(r&&l){for(c=0,o||l.ownerDocument==N||(p(l),a=!L);f=e[c++];){if(f(l,o||N,a)){P.call(s,l);break}}u&&(R=b)}n&&((l=!f&&l)&&d--,i&&g.push(l))}if(d+=h,n&&h!==d){for(c=0;f=t[c++];){f(g,v,o,a)}if(i){if(d>0){for(;h--;){g[h]||v[h]||(v[h]=Ee.call(s))}}v=x(v)}P.apply(s,v),u&&!i&&v.length>0&&d+t.length>1&&ke.uniqueSort(s)}return u&&(R=b,j=m),g};return n?i(o):o}function C(e,t){var n,r=[],i=[],o=$[e+" "];if(!o){for(t||(t=h(e)),n=t.length;n--;){o=T(t[n]),o[M]?r.push(o):i.push(o)}o=$(e,w(i,r)),o.selector=e}return o}function S(e,t,n,r){var i,o,a,s,u,l="function"==typeof e&&e,c=!r&&h(e=l.selector||e);if(n=n||[],1===c.length){if(o=c[0]=c[0].slice(0),o.length>2&&"ID"===(a=o[0]).type&&9===t.nodeType&&L&&E.relative[o[1].type]){if(t=(E.find.ID(a.matches[0].replace(oe,ae),t)||[])[0],!t){return n}l&&(t=t.parentNode),e=e.slice(o.shift().value.length)}for(i=ee.needsContext.test(e)?0:o.length;i--&&(a=o[i],!E.relative[s=a.type]);){if((u=E.find[s])&&(r=u(a.matches[0].replace(oe,ae),ie.test(o[0].type)&&f(t.parentNode)||t))){if(o.splice(i,1),e=r.length&&g(o),!e){return P.apply(n,r),n}break}}}return(l||C(e,c))(r,t,!L,n,!t||ie.test(e)&&f(t.parentNode)||t),n}var k,E,j,A,D,N,q,L,H,O,P=He,M=ke.expando,R=0,I=0,W=r(),F=r(),$=r(),B=r(),_=function(e,t){return e===t&&(D=!0),0},z="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",X="(?:\\\\[\\da-fA-F]{1,6}"+De+"?|\\\\[^\\r\\n\\f]|[\\w-]|[^\x00-\\x7f])+",U="\\["+De+"*("+X+")(?:"+De+"*([*^$|!~]?=)"+De+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+X+"))|)"+De+"*\\]",V=":("+X+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+U+")*)|.*)\\)|)",G=RegExp(De+"+","g"),Y=RegExp("^"+De+"*,"+De+"*"),Q=RegExp("^"+De+"*([>+~]|"+De+")"+De+"*"),J=RegExp(De+"|>"),K=RegExp(V),Z=RegExp("^"+X+"$"),ee={ID:RegExp("^#("+X+")"),CLASS:RegExp("^\\.("+X+")"),TAG:RegExp("^("+X+"|[*])"),ATTR:RegExp("^"+U),PSEUDO:RegExp("^"+V),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+De+"*(even|odd|(([+-]|)(\\d*)n|)"+De+"*(?:([+-]|)"+De+"*(\\d+)|))"+De+"*\\)|)","i"),bool:RegExp("^(?:"+z+")$","i"),needsContext:RegExp("^"+De+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+De+"*((?:-\\d)?\\d*)"+De+"*\\)|)(?=[^-]|$)","i")},te=/^(?:input|select|textarea|button)$/i,ne=/^h\d$/i,re=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ie=/[+~]/,oe=RegExp("\\\\[\\da-fA-F]{1,6}"+De+"?|\\\\([^\\r\\n\\f])","g"),ae=function(e,t){var n="0x"+e.slice(1)-65536;return t?t:0>n?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320)},ue=function(){p()},ce=v(function(e){return e.disabled===!0&&o(e,"fieldset")},{dir:"parentNode",next:"legend"});try{P.apply(se=le.call(Le.childNodes),Le.childNodes),se[Le.childNodes.length].nodeType}catch(fe){P={apply:function(e,t){He.apply(e,le.call(t))},call:function(e){He.apply(e,le.call(arguments,1))}}}n.matches=function(e,t){return n(e,null,null,t)},n.matchesSelector=function(e,t){if(p(e),L&&!B[t+" "]&&(!H||!H.test(t))){try{var r=O.call(e,t);if(r||ye.disconnectedMatch||e.document&&11!==e.document.nodeType){return r}}catch(i){B(t,!0)}}return n(t,N,null,[e]).length>0},n.contains=function(e,t){return(e.ownerDocument||e)!=N&&p(e),ke.contains(e,t)},n.attr=function(e,t){(e.ownerDocument||e)!=N&&p(e);var n=E.attrHandle[t.toLowerCase()],r=n&&ge.call(E.attrHandle,t.toLowerCase())?n(e,t,!L):void 0;return void 0!==r?r:e.getAttribute(t)},n.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},ke.uniqueSort=function(e){var t,n=[],r=0,i=0;if(D=!ye.sortStable,A=!ye.sortStable&&le.call(e,0),je.call(e,_),D){for(;t=e[i++];){t===e[i]&&(r=n.push(i))}for(;r--;){Ae.call(e,n[r],1)}}return A=null,e},ke.fn.uniqueSort=function(){return this.pushStack(ke.uniqueSort(le.apply(this)))},E=ke.expr={cacheLength:50,createPseudo:i,match:ee,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(oe,ae),e[3]=(e[3]||e[4]||e[5]||"").replace(oe,ae),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||n.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&n.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return ee.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&K.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(oe,ae).toLowerCase();return"*"===e?function(){return !0}:function(e){return o(e,t)}},CLASS:function(e){var t=W[e+" "];return t||(t=RegExp("(^|"+De+")"+e+"("+De+"|$)"))&&W(e,function(e){return t.test("string"==typeof e.className&&e.className||void 0!==e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(e,t,r){return function(i){var o=n.attr(i,e);return null==o?"!="===t:t?(o+="","="===t?o===r:"!="===t?o!==r:"^="===t?r&&0===o.indexOf(r):"*="===t?r&&o.indexOf(r)>-1:"$="===t?r&&o.slice(-r.length)===r:"~="===t?(" "+o.replace(G," ")+" ").indexOf(r)>-1:"|="===t?o===r||o.slice(0,r.length+1)===r+"-":!1):!0}},CHILD:function(e,t,n,r,i){var a="nth"!==e.slice(0,3),s="last"!==e.slice(-4),u="of-type"===t;return 1===r&&0===i?function(e){return !!e.parentNode}:function(t,n,l){var c,f,p,d,h,g=a!==s?"nextSibling":"previousSibling",v=t.parentNode,m=u&&t.nodeName.toLowerCase(),y=!l&&!u,x=!1;if(v){if(a){for(;g;){for(p=t;p=p[g];){if(u?o(p,m):1===p.nodeType){return !1}}h=g="only"===e&&!h&&"nextSibling"}return !0}if(h=[s?v.firstChild:v.lastChild],s&&y){for(f=v[M]||(v[M]={}),c=f[e]||[],d=c[0]===R&&c[1],x=d&&c[2],p=d&&v.childNodes[d];p=++d&&p&&p[g]||(x=d=0)||h.pop();){if(1===p.nodeType&&++x&&p===t){f[e]=[R,d,x];break}}}else{if(y&&(f=t[M]||(t[M]={}),c=f[e]||[],d=c[0]===R&&c[1],x=d),x===!1){for(;(p=++d&&p&&p[g]||(x=d=0)||h.pop())&&((u?!o(p,m):1!==p.nodeType)||!++x||(y&&(f=p[M]||(p[M]={}),f[e]=[R,x]),p!==t));){}}}return x-=i,x===r||x%r===0&&x/r>=0}}},PSEUDO:function(e,t){var r,o=E.pseudos[e]||E.setFilters[e.toLowerCase()]||n.error("unsupported pseudo: "+e);return o[M]?o(t):o.length>1?(r=[e,e,"",t],E.setFilters.hasOwnProperty(e.toLowerCase())?i(function(e,n){for(var r,i=o(e,t),a=i.length;a--;){r=pe.call(e,i[a]),e[r]=!(n[r]=i[a])}}):function(e){return o(e,0,r)}):o}},pseudos:{not:i(function(e){var t=[],n=[],r=C(e.replace(Ne,"$1"));return r[M]?i(function(e,t,n,i){for(var o,a=r(e,null,i,[]),s=e.length;s--;){(o=a[s])&&(e[s]=!(t[s]=o))}}):function(e,i,o){return t[0]=e,r(t,null,o,n),t[0]=null,!n.pop()}}),has:i(function(e){return function(t){return n(e,t).length>0}}),contains:i(function(e){return e=e.replace(oe,ae),function(t){return(t.textContent||ke.text(t)).indexOf(e)>-1}}),lang:i(function(e){return Z.test(e||"")||n.error("unsupported lang: "+e),e=e.replace(oe,ae).toLowerCase(),function(t){var n;do{if(n=L?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang")){return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-")}}while((t=t.parentNode)&&1===t.nodeType);return !1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===q},focus:function(e){return e===t()&&N.hasFocus()&&!!(e.type||e.href||~e.tabIndex)},enabled:l(!1),disabled:l(!0),checked:function(e){return o(e,"input")&&!!e.checked||o(e,"option")&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling){if(e.nodeType<6){return !1}}return !0},parent:function(e){return !E.pseudos.empty(e)},header:function(e){return ne.test(e.nodeName)},input:function(e){return te.test(e.nodeName)},button:function(e){return o(e,"input")&&"button"===e.type||o(e,"button")},text:function(e){var t;return o(e,"input")&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:c(function(){return[0]}),last:c(function(e,t){return[t-1]}),eq:c(function(e,t,n){return[0>n?n+t:n]}),even:c(function(e,t){for(var n=0;t>n;n+=2){e.push(n)}return e}),odd:c(function(e,t){for(var n=1;t>n;n+=2){e.push(n)}return e}),lt:c(function(e,t,n){var r;for(r=0>n?n+t:n>t?t:n;--r>=0;){e.push(r)}return e}),gt:c(function(e,t,n){for(var r=0>n?n+t:n;++r<t;){e.push(r)}return e})}},E.pseudos.nth=E.pseudos.eq;for(k in {radio:!0,checkbox:!0,file:!0,password:!0,image:!0}){E.pseudos[k]=s(k)}for(k in {submit:!0,reset:!0}){E.pseudos[k]=u(k)}d.prototype=E.filters=E.pseudos,E.setFilters=new d,ye.sortStable=M.split("").sort(_).join("")===M,p(),ye.sortDetached=a(function(e){return 1&e.compareDocumentPosition(N.createElement("fieldset"))}),ke.find=n,ke.expr[":"]=ke.expr.pseudos,ke.unique=ke.uniqueSort,n.compile=C,n.select=S,n.setDocument=p,n.tokenize=h,n.escape=ke.escapeSelector,n.getText=ke.text,n.isXML=ke.isXMLDoc,n.selectors=ke.expr,n.support=ke.support,n.uniqueSort=ke.uniqueSort}();var Oe=function(e,t,n){for(var r=[],i=void 0!==n;(e=e[t])&&9!==e.nodeType;){if(1===e.nodeType){if(i&&ke(e).is(n)){break}r.push(e)}}return r},Pe=function(e,t){for(var n=[];e;e=e.nextSibling){1===e.nodeType&&e!==t&&n.push(e)}return n},Me=ke.expr.match.needsContext,Re=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;ke.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?ke.find.matchesSelector(r,e)?[r]:[]:ke.find.matches(e,ke.grep(t,function(e){return 1===e.nodeType}))},ke.fn.extend({find:function(e){var t,n,r=this.length,i=this;if("string"!=typeof e){return this.pushStack(ke(e).filter(function(){for(t=0;r>t;t++){if(ke.contains(i[t],this)){return !0}}}))}for(n=this.pushStack([]),t=0;r>t;t++){ke.find(e,i[t],n)}return r>1?ke.uniqueSort(n):n},filter:function(e){return this.pushStack(s(this,e||[],!1))},not:function(e){return this.pushStack(s(this,e||[],!0))},is:function(e){return !!s(this,"string"==typeof e&&Me.test(e)?ke(e):e||[],!1).length}});var Ie,We=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,Fe=ke.fn.init=function(e,t,n){var r,i;if(!e){return this}if(n=n||Ie,"string"==typeof e){if(r="<"===e[0]&&">"===e[e.length-1]&&e.length>=3?[null,e,null]:We.exec(e),!r||!r[1]&&t){return !t||t.jquery?(t||n).find(e):this.constructor(t).find(e)}if(r[1]){if(t=t instanceof ke?t[0]:t,ke.merge(this,ke.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:Te,!0)),Re.test(r[1])&&ke.isPlainObject(t)){for(r in t){xe(this[r])?this[r](t[r]):this.attr(r,t[r])}}return this}return i=Te.getElementById(r[2]),i&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):xe(e)?void 0!==n.ready?n.ready(e):e(ke):ke.makeArray(e,this)};Fe.prototype=ke.fn,Ie=ke(Te);var $e=/^(?:parents|prev(?:Until|All))/,Be={children:!0,contents:!0,next:!0,prev:!0};ke.fn.extend({has:function(e){var t=ke(e,this),n=t.length;return this.filter(function(){for(var e=0;n>e;e++){if(ke.contains(this,t[e])){return !0}}})},closest:function(e,t){var n,r=0,i=this.length,o=[],a="string"!=typeof e&&ke(e);if(!Me.test(e)){for(;i>r;r++){for(n=this[r];n&&n!==t;n=n.parentNode){if(n.nodeType<11&&(a?a.index(n)>-1:1===n.nodeType&&ke.find.matchesSelector(n,e))){o.push(n);break}}}}return this.pushStack(o.length>1?ke.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?pe.call(ke(e),this[0]):pe.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(ke.uniqueSort(ke.merge(this.get(),ke(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),ke.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return Oe(e,"parentNode")},parentsUntil:function(e,t,n){return Oe(e,"parentNode",n)},next:function(e){return u(e,"nextSibling")},prev:function(e){return u(e,"previousSibling")},nextAll:function(e){return Oe(e,"nextSibling")},prevAll:function(e){return Oe(e,"previousSibling")},nextUntil:function(e,t,n){return Oe(e,"nextSibling",n)},prevUntil:function(e,t,n){return Oe(e,"previousSibling",n)},siblings:function(e){return Pe((e.parentNode||{}).firstChild,e)},children:function(e){return Pe(e.firstChild)},contents:function(e){return null!=e.contentDocument&&ue(e.contentDocument)?e.contentDocument:(o(e,"template")&&(e=e.content||e),ke.merge([],e.childNodes))}},function(e,t){ke.fn[e]=function(n,r){var i=ke.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=ke.filter(r,i)),this.length>1&&(Be[e]||ke.uniqueSort(i),$e.test(e)&&i.reverse()),this.pushStack(i)}});var _e=/[^\x20\t\r\n\f]+/g;ke.Callbacks=function(e){e="string"==typeof e?l(e):ke.extend({},e);var t,n,i,o,a=[],s=[],u=-1,c=function(){for(o=o||e.once,i=t=!0;s.length;u=-1){for(n=s.shift();++u<a.length;){a[u].apply(n[0],n[1])===!1&&e.stopOnFalse&&(u=a.length,n=!1)}}e.memory||(n=!1),t=!1,o&&(a=n?[]:"")},f={add:function(){return a&&(n&&!t&&(u=a.length-1,s.push(n)),function i(t){ke.each(t,function(t,n){xe(n)?e.unique&&f.has(n)||a.push(n):n&&n.length&&"string"!==r(n)&&i(n)})}(arguments),n&&!t&&c()),this},remove:function(){return ke.each(arguments,function(e,t){for(var n;(n=ke.inArray(t,a,n))>-1;){a.splice(n,1),u>=n&&u--}}),this},has:function(e){return e?ke.inArray(e,a)>-1:a.length>0},empty:function(){return a&&(a=[]),this},disable:function(){return o=s=[],a=n="",this},disabled:function(){return !a},lock:function(){return o=s=[],n||t||(a=n=""),this},locked:function(){return !!o},fireWith:function(e,n){return o||(n=n||[],n=[e,n.slice?n.slice():n],s.push(n),t||c()),this},fire:function(){return f.fireWith(this,arguments),this},fired:function(){return !!i}};return f},ke.extend({Deferred:function(t){var n=[["notify","progress",ke.Callbacks("memory"),ke.Callbacks("memory"),2],["resolve","done",ke.Callbacks("once memory"),ke.Callbacks("once memory"),0,"resolved"],["reject","fail",ke.Callbacks("once memory"),ke.Callbacks("once memory"),1,"rejected"]],r="pending",i={state:function(){return r},always:function(){return o.done(arguments).fail(arguments),this},"catch":function(e){return i.then(null,e)},pipe:function(){var e=arguments;return ke.Deferred(function(t){ke.each(n,function(n,r){var i=xe(e[r[4]])&&e[r[4]];o[r[1]](function(){var e=i&&i.apply(this,arguments);e&&xe(e.promise)?e.promise().progress(t.notify).done(t.resolve).fail(t.reject):t[r[0]+"With"](this,i?[e]:arguments)})}),e=null}).promise()},then:function(t,r,i){function o(t,n,r,i){return function(){var s=this,u=arguments,l=function(){var e,l;if(!(a>t)){if(e=r.apply(s,u),e===n.promise()){throw new TypeError("Thenable self-resolution")}l=e&&("object"==typeof e||"function"==typeof e)&&e.then,xe(l)?i?l.call(e,o(a,n,c,i),o(a,n,f,i)):(a++,l.call(e,o(a,n,c,i),o(a,n,f,i),o(a,n,c,n.notifyWith))):(r!==c&&(s=void 0,u=[e]),(i||n.resolveWith)(s,u))}},p=i?l:function(){try{l()}catch(e){ke.Deferred.exceptionHook&&ke.Deferred.exceptionHook(e,p.error),t+1>=a&&(r!==f&&(s=void 0,u=[e]),n.rejectWith(s,u))}};t?p():(ke.Deferred.getErrorHook?p.error=ke.Deferred.getErrorHook():ke.Deferred.getStackHook&&(p.error=ke.Deferred.getStackHook()),e.setTimeout(p))}}var a=0;return ke.Deferred(function(e){n[0][3].add(o(0,e,xe(i)?i:c,e.notifyWith)),n[1][3].add(o(0,e,xe(t)?t:c)),n[2][3].add(o(0,e,xe(r)?r:f))}).promise()},promise:function(e){return null!=e?ke.extend(e,i):i}},o={};return ke.each(n,function(e,t){var a=t[2],s=t[5];i[t[1]]=a.add,s&&a.add(function(){r=s},n[3-e][2].disable,n[3-e][3].disable,n[0][2].lock,n[0][3].lock),a.add(t[3].fire),o[t[0]]=function(){return o[t[0]+"With"](this===o?void 0:this,arguments),this},o[t[0]+"With"]=a.fireWith}),i.promise(o),t&&t.call(o,o),o},when:function(e){var t=arguments.length,n=t,r=Array(n),i=le.call(arguments),o=ke.Deferred(),a=function(e){return function(n){r[e]=this,i[e]=arguments.length>1?le.call(arguments):n,--t||o.resolveWith(r,i)}};if(1>=t&&(p(e,o.done(a(n)).resolve,o.reject,!t),"pending"===o.state()||xe(i[n]&&i[n].then))){return o.then()}for(;n--;){p(i[n],a(n),o.reject)}return o.promise()}});var ze=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;ke.Deferred.exceptionHook=function(t,n){e.console&&e.console.warn&&t&&ze.test(t.name)&&e.console.warn("jQuery.Deferred exception: "+t.message,t.stack,n)},ke.readyException=function(t){e.setTimeout(function(){throw t})};var Xe=ke.Deferred();ke.fn.ready=function(e){return Xe.then(e)["catch"](function(e){ke.readyException(e)}),this},ke.extend({isReady:!1,readyWait:1,ready:function(e){(e===!0?--ke.readyWait:ke.isReady)||(ke.isReady=!0,e!==!0&&--ke.readyWait>0||Xe.resolveWith(Te,[ke]))}}),ke.ready.then=Xe.then,"complete"===Te.readyState||"loading"!==Te.readyState&&!Te.documentElement.doScroll?e.setTimeout(ke.ready):(Te.addEventListener("DOMContentLoaded",d),e.addEventListener("load",d));var Ue=function(e,t,n,i,o,a,s){var u=0,l=e.length,c=null==n;if("object"===r(n)){o=!0;for(u in n){Ue(e,t,u,n[u],!0,a,s)}}else{if(void 0!==i&&(o=!0,xe(i)||(s=!0),c&&(s?(t.call(e,i),t=null):(c=t,t=function(e,t,n){return c.call(ke(e),n)})),t)){for(;l>u;u++){t(e[u],n,s?i:i.call(e[u],u,t(e[u],n)))}}}return o?e:c?t.call(e):l?t(e[0],n):a},Ve=/^-ms-/,Ge=/-([a-z])/g,Ye=function(e){return 1===e.nodeType||9===e.nodeType||!+e.nodeType};v.uid=1,v.prototype={cache:function(e){var t=e[this.expando];return t||(t={},Ye(e)&&(e.nodeType?e[this.expando]=t:Object.defineProperty(e,this.expando,{value:t,configurable:!0}))),t},set:function(e,t,n){var r,i=this.cache(e);if("string"==typeof t){i[g(t)]=n}else{for(r in t){i[g(r)]=t[r]}}return i},get:function(e,t){return void 0===t?this.cache(e):e[this.expando]&&e[this.expando][g(t)]},access:function(e,t,n){return void 0===t||t&&"string"==typeof t&&void 0===n?this.get(e,t):(this.set(e,t,n),void 0!==n?n:t)},remove:function(e,t){var n,r=e[this.expando];if(void 0!==r){if(void 0!==t){Array.isArray(t)?t=t.map(g):(t=g(t),t=t in r?[t]:t.match(_e)||[]),n=t.length;for(;n--;){delete r[t[n]]}}(void 0===t||ke.isEmptyObject(r))&&(e.nodeType?e[this.expando]=void 0:delete e[this.expando])}},hasData:function(e){var t=e[this.expando];return void 0!==t&&!ke.isEmptyObject(t)}};var Qe=new v,Je=new v,Ke=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,Ze=/[A-Z]/g;ke.extend({hasData:function(e){return Je.hasData(e)||Qe.hasData(e)},data:function(e,t,n){return Je.access(e,t,n)},removeData:function(e,t){Je.remove(e,t)},_data:function(e,t,n){return Qe.access(e,t,n)},_removeData:function(e,t){Qe.remove(e,t)}}),ke.fn.extend({data:function(e,t){var n,r,i,o=this[0],a=o&&o.attributes;if(void 0===e){if(this.length&&(i=Je.get(o),1===o.nodeType&&!Qe.get(o,"hasDataAttrs"))){for(n=a.length;n--;){a[n]&&(r=a[n].name,0===r.indexOf("data-")&&(r=g(r.slice(5)),y(o,r,i[r])))}Qe.set(o,"hasDataAttrs",!0)}return i}return"object"==typeof e?this.each(function(){Je.set(this,e)}):Ue(this,function(t){var n;if(o&&void 0===t){if(n=Je.get(o,e),void 0!==n){return n}if(n=y(o,e),void 0!==n){return n}}else{this.each(function(){Je.set(this,e,t)})}},null,t,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){Je.remove(this,e)})}}),ke.extend({queue:function(e,t,n){var r;return e?(t=(t||"fx")+"queue",r=Qe.get(e,t),n&&(!r||Array.isArray(n)?r=Qe.access(e,t,ke.makeArray(n)):r.push(n)),r||[]):void 0},dequeue:function(e,t){t=t||"fx";var n=ke.queue(e,t),r=n.length,i=n.shift(),o=ke._queueHooks(e,t),a=function(){ke.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return Qe.get(e,n)||Qe.access(e,n,{empty:ke.Callbacks("once memory").add(function(){Qe.remove(e,[t+"queue",n])})})}}),ke.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),arguments.length<n?ke.queue(this[0],e):void 0===t?this:this.each(function(){var n=ke.queue(this,e,t);ke._queueHooks(this,e),"fx"===e&&"inprogress"!==n[0]&&ke.dequeue(this,e)})},dequeue:function(e){return this.each(function(){ke.dequeue(this,e)})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,t){var n,r=1,i=ke.Deferred(),o=this,a=this.length,s=function(){--r||i.resolveWith(o,[o])};for("string"!=typeof e&&(t=e,e=void 0),e=e||"fx";a--;){n=Qe.get(o[a],e+"queueHooks"),n&&n.empty&&(r++,n.empty.add(s))}return s(),i.promise(t)}});var et=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,tt=RegExp("^(?:([+-])=|)("+et+")([a-z%]*)$","i"),nt=["Top","Right","Bottom","Left"],rt=Te.documentElement,it=function(e){return ke.contains(e.ownerDocument,e)},ot={composed:!0};rt.getRootNode&&(it=function(e){return ke.contains(e.ownerDocument,e)||e.getRootNode(ot)===e.ownerDocument});var at=function(e,t){return e=t||e,"none"===e.style.display||""===e.style.display&&it(e)&&"none"===ke.css(e,"display")},st={};ke.fn.extend({show:function(){return T(this,!0)},hide:function(){return T(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){at(this)?ke(this).show():ke(this).hide()})}});var ut=/^(?:checkbox|radio)$/i,lt=/<([a-z][^\/\0>\x20\t\r\n\f]*)/i,ct=/^$|^module$|\/(?:java|ecma)script/i;!function(){var e=Te.createDocumentFragment(),t=e.appendChild(Te.createElement("div")),n=Te.createElement("input");n.setAttribute("type","radio"),n.setAttribute("checked","checked"),n.setAttribute("name","t"),t.appendChild(n),ye.checkClone=t.cloneNode(!0).cloneNode(!0).lastChild.checked,t.innerHTML="<textarea>x</textarea>",ye.noCloneChecked=!!t.cloneNode(!0).lastChild.defaultValue,t.innerHTML="<option></option>",ye.option=!!t.lastChild}();var ft={thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};ft.tbody=ft.tfoot=ft.colgroup=ft.caption=ft.thead,ft.th=ft.td,ye.option||(ft.optgroup=ft.option=[1,"<select multiple='multiple'>","</select>"]);var pt=/<|&#?\w+;/,dt=/^([^.]*)(?:\.(.+)|)/;ke.event={global:{},add:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Qe.get(e);if(Ye(e)){for(n.handler&&(o=n,n=o.handler,i=o.selector),i&&ke.find.matchesSelector(rt,i),n.guid||(n.guid=ke.guid++),(u=v.events)||(u=v.events=Object.create(null)),(a=v.handle)||(a=v.handle=function(t){return void 0!==ke&&ke.event.triggered!==t.type?ke.event.dispatch.apply(e,arguments):void 0}),t=(t||"").match(_e)||[""],l=t.length;l--;){s=dt.exec(t[l])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d&&(f=ke.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=ke.event.special[d]||{},c=ke.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&ke.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||(p=u[d]=[],p.delegateCount=0,f.setup&&f.setup.call(e,r,h,a)!==!1||e.addEventListener&&e.addEventListener(d,a)),f.add&&(f.add.call(e,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),ke.event.global[d]=!0)}}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Qe.hasData(e)&&Qe.get(e);if(v&&(u=v.events)){for(t=(t||"").match(_e)||[""],l=t.length;l--;){if(s=dt.exec(t[l])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){for(f=ke.event.special[d]||{},d=(r?f.delegateType:f.bindType)||d,p=u[d]||[],s=s[2]&&RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;o--;){c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c))}a&&!p.length&&(f.teardown&&f.teardown.call(e,h,v.handle)!==!1||ke.removeEvent(e,d,v.handle),delete u[d])}else{for(d in u){ke.event.remove(e,d+t[l],n,r,!0)}}}ke.isEmptyObject(u)&&Qe.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,a,s=Array(arguments.length),u=ke.event.fix(e),l=(Qe.get(this,"events")||Object.create(null))[u.type]||[],c=ke.event.special[u.type]||{};for(s[0]=u,t=1;t<arguments.length;t++){s[t]=arguments[t]}if(u.delegateTarget=this,!c.preDispatch||c.preDispatch.call(this,u)!==!1){for(a=ke.event.handlers.call(this,u,l),t=0;(i=a[t++])&&!u.isPropagationStopped();){for(u.currentTarget=i.elem,n=0;(o=i.handlers[n++])&&!u.isImmediatePropagationStopped();){(!u.rnamespace||o.namespace===!1||u.rnamespace.test(o.namespace))&&(u.handleObj=o,u.data=o.data,r=((ke.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,s),void 0!==r&&(u.result=r)===!1&&(u.preventDefault(),u.stopPropagation()))}}return c.postDispatch&&c.postDispatch.call(this,u),u.result}},handlers:function(e,t){var n,r,i,o,a,s=[],u=t.delegateCount,l=e.target;if(u&&l.nodeType&&!("click"===e.type&&e.button>=1)){for(;l!==this;l=l.parentNode||this){if(1===l.nodeType&&("click"!==e.type||l.disabled!==!0)){for(o=[],a={},n=0;u>n;n++){r=t[n],i=r.selector+" ",void 0===a[i]&&(a[i]=r.needsContext?ke(i,this).index(l)>-1:ke.find(i,this,null,[l]).length),a[i]&&o.push(r)}o.length&&s.push({elem:l,handlers:o})}}}return l=this,u<t.length&&s.push({elem:l,handlers:t.slice(u)}),s},addProp:function(e,t){Object.defineProperty(ke.Event.prototype,e,{enumerable:!0,configurable:!0,get:xe(t)?function(){return this.originalEvent?t(this.originalEvent):void 0}:function(){return this.originalEvent?this.originalEvent[e]:void 0},set:function(t){Object.defineProperty(this,e,{enumerable:!0,configurable:!0,writable:!0,value:t})}})},fix:function(e){return e[ke.expando]?e:new ke.Event(e)},special:{load:{noBubble:!0},click:{setup:function(e){var t=this||e;return ut.test(t.type)&&t.click&&o(t,"input")&&A(t,"click",!0),!1},trigger:function(e){var t=this||e;return ut.test(t.type)&&t.click&&o(t,"input")&&A(t,"click"),!0},_default:function(e){var t=e.target;return ut.test(t.type)&&t.click&&o(t,"input")&&Qe.get(t,"click")||o(t,"a")}},beforeunload:{postDispatch:function(e){void 0!==e.result&&e.originalEvent&&(e.originalEvent.returnValue=e.result)}}}},ke.removeEvent=function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n)},ke.Event=function(e,t){return this instanceof ke.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||void 0===e.defaultPrevented&&e.returnValue===!1?k:E,this.target=e.target&&3===e.target.nodeType?e.target.parentNode:e.target,this.currentTarget=e.currentTarget,this.relatedTarget=e.relatedTarget):this.type=e,t&&ke.extend(this,t),this.timeStamp=e&&e.timeStamp||Date.now(),void (this[ke.expando]=!0)):new ke.Event(e,t)},ke.Event.prototype={constructor:ke.Event,isDefaultPrevented:E,isPropagationStopped:E,isImmediatePropagationStopped:E,isSimulated:!1,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=k,e&&!this.isSimulated&&e.preventDefault()},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=k,e&&!this.isSimulated&&e.stopPropagation()},stopImmediatePropagation:function(){var e=this.originalEvent;this.isImmediatePropagationStopped=k,e&&!this.isSimulated&&e.stopImmediatePropagation(),this.stopPropagation()}},ke.each({altKey:!0,bubbles:!0,cancelable:!0,changedTouches:!0,ctrlKey:!0,detail:!0,eventPhase:!0,metaKey:!0,pageX:!0,pageY:!0,shiftKey:!0,view:!0,"char":!0,code:!0,charCode:!0,key:!0,keyCode:!0,button:!0,buttons:!0,clientX:!0,clientY:!0,offsetX:!0,offsetY:!0,pointerId:!0,pointerType:!0,screenX:!0,screenY:!0,targetTouches:!0,toElement:!0,touches:!0,which:!0},ke.event.addProp),ke.each({focus:"focusin",blur:"focusout"},function(e,t){function n(e){if(Te.documentMode){var n=Qe.get(this,"handle"),r=ke.event.fix(e);r.type="focusin"===e.type?"focus":"blur",r.isSimulated=!0,n(e),r.target===r.currentTarget&&n(r)}else{ke.event.simulate(t,e.target,ke.event.fix(e))}}ke.event.special[e]={setup:function(){var r;return A(this,e,!0),Te.documentMode?(r=Qe.get(this,t),r||this.addEventListener(t,n),Qe.set(this,t,(r||0)+1),void 0):!1},trigger:function(){return A(this,e),!0},teardown:function(){var e;return Te.documentMode?(e=Qe.get(this,t)-1,void (e?Qe.set(this,t,e):(this.removeEventListener(t,n),Qe.remove(this,t)))):!1},_default:function(t){return Qe.get(t.target,e)},delegateType:t},ke.event.special[t]={setup:function(){var r=this.ownerDocument||this.document||this,i=Te.documentMode?this:r,o=Qe.get(i,t);o||(Te.documentMode?this.addEventListener(t,n):r.addEventListener(e,n,!0)),Qe.set(i,t,(o||0)+1)},teardown:function(){var r=this.ownerDocument||this.document||this,i=Te.documentMode?this:r,o=Qe.get(i,t)-1;o?Qe.set(i,t,o):(Te.documentMode?this.removeEventListener(t,n):r.removeEventListener(e,n,!0),Qe.remove(i,t))}}}),ke.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(e,t){ke.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return(!i||i!==r&&!ke.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),ke.fn.extend({on:function(e,t,n,r){return j(this,e,t,n,r)},one:function(e,t,n,r){return j(this,e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj){return r=e.handleObj,ke(e.delegateTarget).off(r.namespace?r.origType+"."+r.namespace:r.origType,r.selector,r.handler),this}if("object"==typeof e){for(i in e){this.off(i,t,e[i])}return this}return(t===!1||"function"==typeof t)&&(n=t,t=void 0),n===!1&&(n=E),this.each(function(){ke.event.remove(this,e,n,t)})}});var ht=/<script|<style|<link/i,gt=/checked\s*(?:[^=]|=\s*.checked.)/i,vt=/^\s*<!\[CDATA\[|\]\]>\s*$/g;ke.extend({htmlPrefilter:function(e){return e},clone:function(e,t,n){var r,i,o,a,s=e.cloneNode(!0),u=it(e);if(!(ye.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||ke.isXMLDoc(e))){for(a=w(s),o=w(e),r=0,i=o.length;i>r;r++){H(o[r],a[r])}}if(t){if(n){for(o=o||w(e),a=a||w(s),r=0,i=o.length;i>r;r++){L(o[r],a[r])}}else{L(e,s)}}return a=w(s,"script"),a.length>0&&C(a,!u&&w(e,"script")),s},cleanData:function(e){for(var t,n,r,i=ke.event.special,o=0;void 0!==(n=e[o]);o++){if(Ye(n)){if(t=n[Qe.expando]){if(t.events){for(r in t.events){i[r]?ke.event.remove(n,r):ke.removeEvent(n,r,t.handle)}}n[Qe.expando]=void 0}n[Je.expando]&&(n[Je.expando]=void 0)}}}}),ke.fn.extend({detach:function(e){return P(this,e,!0)},remove:function(e){return P(this,e)},text:function(e){return Ue(this,function(e){return void 0===e?ke.text(this):this.empty().each(function(){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&(this.textContent=e)})},null,e,arguments.length)},append:function(){return O(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=D(this,e);t.appendChild(e)}})},prepend:function(){return O(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=D(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return O(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return O(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++){1===e.nodeType&&(ke.cleanData(w(e,!1)),e.textContent="")}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return ke.clone(this,e,t)})},html:function(e){return Ue(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType){return t.innerHTML}if("string"==typeof e&&!ht.test(e)&&!ft[(lt.exec(e)||["",""])[1].toLowerCase()]){e=ke.htmlPrefilter(e);try{for(;r>n;n++){t=this[n]||{},1===t.nodeType&&(ke.cleanData(w(t,!1)),t.innerHTML=e)}t=0}catch(i){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=[];return O(this,arguments,function(t){var n=this.parentNode;ke.inArray(this,e)<0&&(ke.cleanData(w(this)),n&&n.replaceChild(t,this))},e)}}),ke.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){ke.fn[e]=function(e){for(var n,r=[],i=ke(e),o=i.length-1,a=0;o>=a;a++){n=a===o?this:this.clone(!0),ke(i[a])[t](n),fe.apply(r,n.get())}return this.pushStack(r)}});var mt=RegExp("^("+et+")(?!px)[a-z%]+$","i"),yt=/^--/,xt=function(t){var n=t.ownerDocument.defaultView;return n&&n.opener||(n=e),n.getComputedStyle(t)},bt=function(e,t,n){var r,i,o={};for(i in t){o[i]=e.style[i],e.style[i]=t[i]}r=n.call(e);for(i in t){e.style[i]=o[i]}return r},Tt=RegExp(nt.join("|"),"i");!function(){function t(){if(c){l.style.cssText="position:absolute;left:-11111px;width:60px;margin-top:1px;padding:0;border:0",c.style.cssText="position:relative;display:block;box-sizing:border-box;overflow:scroll;margin:auto;border:1px;padding:1px;width:60%;top:1%",rt.appendChild(l).appendChild(c);var t=e.getComputedStyle(c);r="1%"!==t.top,u=12===n(t.marginLeft),c.style.right="60%",a=36===n(t.right),i=36===n(t.width),c.style.position="absolute",o=12===n(c.offsetWidth/3),rt.removeChild(l),c=null}}function n(e){return Math.round(parseFloat(e))}var r,i,o,a,s,u,l=Te.createElement("div"),c=Te.createElement("div");c.style&&(c.style.backgroundClip="content-box",c.cloneNode(!0).style.backgroundClip="",ye.clearCloneStyle="content-box"===c.style.backgroundClip,ke.extend(ye,{boxSizingReliable:function(){return t(),i},pixelBoxStyles:function(){return t(),a},pixelPosition:function(){return t(),r},reliableMarginLeft:function(){return t(),u},scrollboxSize:function(){return t(),o},reliableTrDimensions:function(){var t,n,r,i;return null==s&&(t=Te.createElement("table"),n=Te.createElement("tr"),r=Te.createElement("div"),t.style.cssText="position:absolute;left:-11111px;border-collapse:separate",n.style.cssText="box-sizing:content-box;border:1px solid",n.style.height="1px",r.style.height="9px",r.style.display="block",rt.appendChild(t).appendChild(n).appendChild(r),i=e.getComputedStyle(n),s=parseInt(i.height,10)+parseInt(i.borderTopWidth,10)+parseInt(i.borderBottomWidth,10)===n.offsetHeight,rt.removeChild(t)),s}}))}();var wt=["Webkit","Moz","ms"],Ct=Te.createElement("div").style,St={},kt=/^(none|table(?!-c[ea]).+)/,Et={position:"absolute",visibility:"hidden",display:"block"},jt={letterSpacing:"0",fontWeight:"400"};ke.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=M(e,"opacity");return""===n?"1":n}}}},cssNumber:{animationIterationCount:!0,aspectRatio:!0,borderImageSlice:!0,columnCount:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,gridArea:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnStart:!0,gridRow:!0,gridRowEnd:!0,gridRowStart:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,scale:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeMiterlimit:!0,strokeOpacity:!0},cssProps:{},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=g(t),u=yt.test(t),l=e.style;return u||(t=W(s)),a=ke.cssHooks[t]||ke.cssHooks[s],void 0===n?a&&"get" in a&&void 0!==(i=a.get(e,!1,r))?i:l[t]:(o=typeof n,"string"===o&&(i=tt.exec(n))&&i[1]&&(n=x(e,t,i),o="number"),null!=n&&n===n&&("number"!==o||u||(n+=i&&i[3]||(ke.cssNumber[s]?"":"px")),ye.clearCloneStyle||""!==n||0!==t.indexOf("background")||(l[t]="inherit"),a&&"set" in a&&void 0===(n=a.set(e,n,r))||(u?l.setProperty(t,n):l[t]=n)),void 0)}},css:function(e,t,n,r){var i,o,a,s=g(t),u=yt.test(t);return u||(t=W(s)),a=ke.cssHooks[t]||ke.cssHooks[s],a&&"get" in a&&(i=a.get(e,!0,n)),void 0===i&&(i=M(e,t,r)),"normal"===i&&t in jt&&(i=jt[t]),""===n||n?(o=parseFloat(i),n===!0||isFinite(o)?o||0:i):i}}),ke.each(["height","width"],function(e,t){ke.cssHooks[t]={get:function(e,n,r){return n?!kt.test(ke.css(e,"display"))||e.getClientRects().length&&e.getBoundingClientRect().width?_(e,t,r):bt(e,Et,function(){return _(e,t,r)}):void 0},set:function(e,n,r){var i,o=xt(e),a=!ye.scrollboxSize()&&"absolute"===o.position,s=a||r,u=s&&"border-box"===ke.css(e,"boxSizing",!1,o),l=r?B(e,t,r,u,o):0;return u&&a&&(l-=Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-parseFloat(o[t])-B(e,t,"border",!1,o)-0.5)),l&&(i=tt.exec(n))&&"px"!==(i[3]||"px")&&(e.style[t]=n,n=ke.css(e,t)),F(e,n,l)}}}),ke.cssHooks.marginLeft=R(ye.reliableMarginLeft,function(e,t){return t?(parseFloat(M(e,"marginLeft"))||e.getBoundingClientRect().left-bt(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}))+"px":void 0}),ke.each({margin:"",padding:"",border:"Width"},function(e,t){ke.cssHooks[e+t]={expand:function(n){for(var r=0,i={},o="string"==typeof n?n.split(" "):[n];4>r;r++){i[e+nt[r]+t]=o[r]||o[r-2]||o[0]}return i}},"margin"!==e&&(ke.cssHooks[e+t].set=F)}),ke.fn.extend({css:function(e,t){return Ue(this,function(e,t,n){var r,i,o={},a=0;if(Array.isArray(t)){for(r=xt(e),i=t.length;i>a;a++){o[t[a]]=ke.css(e,t[a],!1,r)}return o}return void 0!==n?ke.style(e,t,n):ke.css(e,t)},e,t,arguments.length>1)}}),ke.Tween=z,z.prototype={constructor:z,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||ke.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(ke.cssNumber[n]?"":"px")},cur:function(){var e=z.propHooks[this.prop];return e&&e.get?e.get(this):z.propHooks._default.get(this)},run:function(e){var t,n=z.propHooks[this.prop];return this.options.duration?this.pos=t=ke.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):z.propHooks._default.set(this),this}},z.prototype.init.prototype=z.prototype,z.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=ke.css(e.elem,e.prop,""),t&&"auto"!==t?t:0)},set:function(e){ke.fx.step[e.prop]?ke.fx.step[e.prop](e):1!==e.elem.nodeType||!ke.cssHooks[e.prop]&&null==e.elem.style[W(e.prop)]?e.elem[e.prop]=e.now:ke.style(e.elem,e.prop,e.now+e.unit)}}},z.propHooks.scrollTop=z.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},ke.easing={linear:function(e){return e},swing:function(e){return 0.5-Math.cos(e*Math.PI)/2},_default:"swing"},ke.fx=z.prototype.init,ke.fx.step={};var At,Dt,Nt=/^(?:toggle|show|hide)$/,qt=/queueHooks$/;ke.Animation=ke.extend(J,{tweeners:{"*":[function(e,t){var n=this.createTween(e,t);return x(n.elem,e,tt.exec(t),n),n}]},tweener:function(e,t){xe(e)?(t=e,e=["*"]):e=e.match(_e);for(var n,r=0,i=e.length;i>r;r++){n=e[r],J.tweeners[n]=J.tweeners[n]||[],J.tweeners[n].unshift(t)}},prefilters:[Y],prefilter:function(e,t){t?J.prefilters.unshift(e):J.prefilters.push(e)}}),ke.speed=function(e,t,n){var r=e&&"object"==typeof e?ke.extend({},e):{complete:n||!n&&t||xe(e)&&e,duration:e,easing:n&&t||t&&!xe(t)&&t};return ke.fx.off?r.duration=0:"number"!=typeof r.duration&&(r.duration in ke.fx.speeds?r.duration=ke.fx.speeds[r.duration]:r.duration=ke.fx.speeds._default),(null==r.queue||r.queue===!0)&&(r.queue="fx"),r.old=r.complete,r.complete=function(){xe(r.old)&&r.old.call(this),r.queue&&ke.dequeue(this,r.queue)},r},ke.fn.extend({fadeTo:function(e,t,n,r){return this.filter(at).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=ke.isEmptyObject(e),o=ke.speed(t,n,r),a=function(){var t=J(this,ke.extend({},e),o);(i||Qe.get(this,"finish"))&&t.stop(!0)};return a.finish=a,i||o.queue===!1?this.each(a):this.queue(o.queue,a)},stop:function(e,t,n){var r=function(e){var t=e.stop;delete e.stop,t(n)};return"string"!=typeof e&&(n=t,t=e,e=void 0),t&&this.queue(e||"fx",[]),this.each(function(){var t=!0,i=null!=e&&e+"queueHooks",o=ke.timers,a=Qe.get(this);if(i){a[i]&&a[i].stop&&r(a[i])}else{for(i in a){a[i]&&a[i].stop&&qt.test(i)&&r(a[i])}}for(i=o.length;i--;){o[i].elem!==this||null!=e&&o[i].queue!==e||(o[i].anim.stop(n),t=!1,o.splice(i,1))}(t||!n)&&ke.dequeue(this,e)})},finish:function(e){return e!==!1&&(e=e||"fx"),this.each(function(){var t,n=Qe.get(this),r=n[e+"queue"],i=n[e+"queueHooks"],o=ke.timers,a=r?r.length:0;for(n.finish=!0,ke.queue(this,e,[]),i&&i.stop&&i.stop.call(this,!0),t=o.length;t--;){o[t].elem===this&&o[t].queue===e&&(o[t].anim.stop(!0),o.splice(t,1))}for(t=0;a>t;t++){r[t]&&r[t].finish&&r[t].finish.call(this)}delete n.finish})}}),ke.each(["toggle","show","hide"],function(e,t){var n=ke.fn[t];ke.fn[t]=function(e,r,i){return null==e||"boolean"==typeof e?n.apply(this,arguments):this.animate(V(t,!0),e,r,i)}}),ke.each({slideDown:V("show"),slideUp:V("hide"),slideToggle:V("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,t){ke.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),ke.timers=[],ke.fx.tick=function(){var e,t=0,n=ke.timers;for(At=Date.now();t<n.length;t++){e=n[t],e()||n[t]!==e||n.splice(t--,1)}n.length||ke.fx.stop(),At=void 0},ke.fx.timer=function(e){ke.timers.push(e),ke.fx.start()},ke.fx.interval=13,ke.fx.start=function(){Dt||(Dt=!0,X())},ke.fx.stop=function(){Dt=null},ke.fx.speeds={slow:600,fast:200,_default:400},ke.fn.delay=function(t,n){return t=ke.fx?ke.fx.speeds[t]||t:t,n=n||"fx",this.queue(n,function(n,r){var i=e.setTimeout(n,t);r.stop=function(){e.clearTimeout(i)}})},function(){var e=Te.createElement("input"),t=Te.createElement("select"),n=t.appendChild(Te.createElement("option"));e.type="checkbox",ye.checkOn=""!==e.value,ye.optSelected=n.selected,e=Te.createElement("input"),e.value="t",e.type="radio",ye.radioValue="t"===e.value}();var Lt,Ht=ke.expr.attrHandle;ke.fn.extend({attr:function(e,t){return Ue(this,ke.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){ke.removeAttr(this,e)})}}),ke.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o){return void 0===e.getAttribute?ke.prop(e,t,n):(1===o&&ke.isXMLDoc(e)||(i=ke.attrHooks[t.toLowerCase()]||(ke.expr.match.bool.test(t)?Lt:void 0)),void 0!==n?null===n?void ke.removeAttr(e,t):i&&"set" in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+""),n):i&&"get" in i&&null!==(r=i.get(e,t))?r:(r=ke.find.attr(e,t),null==r?void 0:r))}},attrHooks:{type:{set:function(e,t){if(!ye.radioValue&&"radio"===t&&o(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r=0,i=t&&t.match(_e);if(i&&1===e.nodeType){for(;n=i[r++];){e.removeAttribute(n)}}}}),Lt={set:function(e,t,n){return t===!1?ke.removeAttr(e,n):e.setAttribute(n,n),n}},ke.each(ke.expr.match.bool.source.match(/\w+/g),function(e,t){var n=Ht[t]||ke.find.attr;Ht[t]=function(e,t,r){var i,o,a=t.toLowerCase();return r||(o=Ht[a],Ht[a]=i,i=null!=n(e,t,r)?a:null,Ht[a]=o),i}});var Ot=/^(?:input|select|textarea|button)$/i,Pt=/^(?:a|area)$/i;ke.fn.extend({prop:function(e,t){return Ue(this,ke.prop,e,t,arguments.length>1)},removeProp:function(e){return this.each(function(){delete this[ke.propFix[e]||e]})}}),ke.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o){return 1===o&&ke.isXMLDoc(e)||(t=ke.propFix[t]||t,i=ke.propHooks[t]),void 0!==n?i&&"set" in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get" in i&&null!==(r=i.get(e,t))?r:e[t]}},propHooks:{tabIndex:{get:function(e){var t=ke.find.attr(e,"tabindex");return t?parseInt(t,10):Ot.test(e.nodeName)||Pt.test(e.nodeName)&&e.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),ye.optSelected||(ke.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),ke.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){ke.propFix[this.toLowerCase()]=this}),ke.fn.extend({addClass:function(e){var t,n,r,i,o,a;return xe(e)?this.each(function(t){ke(this).addClass(e.call(this,t,Z(this)))}):(t=ee(e),t.length?this.each(function(){if(r=Z(this),n=1===this.nodeType&&" "+K(r)+" "){for(o=0;o<t.length;o++){i=t[o],n.indexOf(" "+i+" ")<0&&(n+=i+" ")}a=K(n),r!==a&&this.setAttribute("class",a)}}):this)},removeClass:function(e){var t,n,r,i,o,a;return xe(e)?this.each(function(t){ke(this).removeClass(e.call(this,t,Z(this)))}):arguments.length?(t=ee(e),t.length?this.each(function(){if(r=Z(this),n=1===this.nodeType&&" "+K(r)+" "){for(o=0;o<t.length;o++){for(i=t[o];n.indexOf(" "+i+" ")>-1;){n=n.replace(" "+i+" "," ")}}a=K(n),r!==a&&this.setAttribute("class",a)}}):this):this.attr("class","")},toggleClass:function(e,t){var n,r,i,o,a=typeof e,s="string"===a||Array.isArray(e);return xe(e)?this.each(function(n){ke(this).toggleClass(e.call(this,n,Z(this),t),t)}):"boolean"==typeof t&&s?t?this.addClass(e):this.removeClass(e):(n=ee(e),this.each(function(){if(s){for(o=ke(this),i=0;i<n.length;i++){r=n[i],o.hasClass(r)?o.removeClass(r):o.addClass(r)}}else{(void 0===e||"boolean"===a)&&(r=Z(this),r&&Qe.set(this,"__className__",r),this.setAttribute&&this.setAttribute("class",r||e===!1?"":Qe.get(this,"__className__")||""))}}))},hasClass:function(e){var t,n,r=0;for(t=" "+e+" ";n=this[r++];){if(1===n.nodeType&&(" "+K(Z(n))+" ").indexOf(t)>-1){return !0}}return !1}});var Mt=/\r/g;ke.fn.extend({val:function(e){var t,n,r,i=this[0];if(arguments.length){return r=xe(e),this.each(function(n){var i;1===this.nodeType&&(i=r?e.call(this,n,ke(this).val()):e,null==i?i="":"number"==typeof i?i+="":Array.isArray(i)&&(i=ke.map(i,function(e){return null==e?"":e+""})),t=ke.valHooks[this.type]||ke.valHooks[this.nodeName.toLowerCase()],t&&"set" in t&&void 0!==t.set(this,i,"value")||(this.value=i))})}if(i){return t=ke.valHooks[i.type]||ke.valHooks[i.nodeName.toLowerCase()],t&&"get" in t&&void 0!==(n=t.get(i,"value"))?n:(n=i.value,"string"==typeof n?n.replace(Mt,""):null==n?"":n)}}}),ke.extend({valHooks:{option:{get:function(e){var t=ke.find.attr(e,"value");return null!=t?t:K(ke.text(e))}},select:{get:function(e){var t,n,r,i=e.options,a=e.selectedIndex,s="select-one"===e.type,u=s?null:[],l=s?a+1:i.length;for(r=0>a?l:s?a:0;l>r;r++){if(n=i[r],(n.selected||r===a)&&!n.disabled&&(!n.parentNode.disabled||!o(n.parentNode,"optgroup"))){if(t=ke(n).val(),s){return t}u.push(t)}}return u},set:function(e,t){for(var n,r,i=e.options,o=ke.makeArray(t),a=i.length;a--;){r=i[a],(r.selected=ke.inArray(ke.valHooks.option.get(r),o)>-1)&&(n=!0)}return n||(e.selectedIndex=-1),o}}}}),ke.each(["radio","checkbox"],function(){ke.valHooks[this]={set:function(e,t){return Array.isArray(t)?e.checked=ke.inArray(ke(e).val(),t)>-1:void 0}},ye.checkOn||(ke.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var Rt=e.location,It={guid:Date.now()},Wt=/\?/;ke.parseXML=function(t){var n,r;if(!t||"string"!=typeof t){return null}try{n=(new e.DOMParser).parseFromString(t,"text/xml")}catch(i){}return r=n&&n.getElementsByTagName("parsererror")[0],(!n||r)&&ke.error("Invalid XML: "+(r?ke.map(r.childNodes,function(e){return e.textContent}).join("\n"):t)),n};var Ft=/^(?:focusinfocus|focusoutblur)$/,$t=function(e){e.stopPropagation()};ke.extend(ke.event,{trigger:function(t,n,r,i){var o,a,s,u,l,c,f,p,d=[r||Te],h=ge.call(t,"type")?t.type:t,g=ge.call(t,"namespace")?t.namespace.split("."):[];if(a=p=s=r=r||Te,3!==r.nodeType&&8!==r.nodeType&&!Ft.test(h+ke.event.triggered)&&(h.indexOf(".")>-1&&(g=h.split("."),h=g.shift(),g.sort()),l=h.indexOf(":")<0&&"on"+h,t=t[ke.expando]?t:new ke.Event(h,"object"==typeof t&&t),t.isTrigger=i?2:3,t.namespace=g.join("."),t.rnamespace=t.namespace?RegExp("(^|\\.)"+g.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=void 0,t.target||(t.target=r),n=null==n?[t]:ke.makeArray(n,[t]),f=ke.event.special[h]||{},i||!f.trigger||f.trigger.apply(r,n)!==!1)){if(!i&&!f.noBubble&&!be(r)){for(u=f.delegateType||h,Ft.test(u+h)||(a=a.parentNode);a;a=a.parentNode){d.push(a),s=a}s===(r.ownerDocument||Te)&&d.push(s.defaultView||s.parentWindow||e)}for(o=0;(a=d[o++])&&!t.isPropagationStopped();){p=a,t.type=o>1?u:f.bindType||h,c=(Qe.get(a,"events")||Object.create(null))[t.type]&&Qe.get(a,"handle"),c&&c.apply(a,n),c=l&&a[l],c&&c.apply&&Ye(a)&&(t.result=c.apply(a,n),t.result===!1&&t.preventDefault())}return t.type=h,i||t.isDefaultPrevented()||f._default&&f._default.apply(d.pop(),n)!==!1||!Ye(r)||l&&xe(r[h])&&!be(r)&&(s=r[l],s&&(r[l]=null),ke.event.triggered=h,t.isPropagationStopped()&&p.addEventListener(h,$t),r[h](),t.isPropagationStopped()&&p.removeEventListener(h,$t),ke.event.triggered=void 0,s&&(r[l]=s)),t.result}},simulate:function(e,t,n){var r=ke.extend(new ke.Event,n,{type:e,isSimulated:!0});ke.event.trigger(r,null,t)}}),ke.fn.extend({trigger:function(e,t){return this.each(function(){ke.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];return n?ke.event.trigger(e,t,n,!0):void 0}});var Bt=/\[\]$/,_t=/\r?\n/g,zt=/^(?:submit|button|image|reset|file)$/i,Xt=/^(?:input|select|textarea|keygen)/i;ke.param=function(e,t){var n,r=[],i=function(e,t){var n=xe(t)?t():t;r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(null==n?"":n)};if(null==e){return""}if(Array.isArray(e)||e.jquery&&!ke.isPlainObject(e)){ke.each(e,function(){i(this.name,this.value)})}else{for(n in e){te(n,e[n],t,i)}}return r.join("&")},ke.fn.extend({serialize:function(){var e=this.serializeArray(),t=$("input[type=radio],input[type=checkbox]",this),n={};return $.each(t,function(){n.hasOwnProperty(this.name)||0==$("input[name='"+this.name+"']:checked").length&&(n[this.name]="",e.push({name:this.name,value:""}))}),ke.param(e)},serializeArray:function(){return this.map(function(){var e=ke.prop(this,"elements");return e?ke.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!ke(this).is(":disabled")&&Xt.test(this.nodeName)&&!zt.test(e)&&(this.checked||!ut.test(e))}).map(function(e,t){var n=ke(this).val();return null==n?null:Array.isArray(n)?ke.map(n,function(e){return{name:t.name,value:e.replace(_t,"\r\n")}}):{name:t.name,value:n.replace(_t,"\r\n")}}).get()}});var Ut=/%20/g,Vt=/#.*$/,Gt=/([?&])_=[^&]*/,Yt=/^(.*?):[ \t]*([^\r\n]*)$/gm,Qt=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Jt=/^(?:GET|HEAD)$/,Kt=/^\/\//,Zt={},en={},tn="*/".concat("*"),nn=Te.createElement("a");nn.href=Rt.href,ke.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Rt.href,type:"GET",isLocal:Qt.test(Rt.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":tn,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":ke.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?ie(ie(e,ke.ajaxSettings),t):ie(ke.ajaxSettings,e)},ajaxPrefilter:ne(Zt),ajaxTransport:ne(en),ajax:function(t,n){function r(t,n,r,s){var l,p,d,b,T,w=n;c||(c=!0,u&&e.clearTimeout(u),i=void 0,a=s||"",C.readyState=t>0?4:0,l=t>=200&&300>t||304===t,r&&(b=oe(h,C,r)),!l&&ke.inArray("script",h.dataTypes)>-1&&ke.inArray("json",h.dataTypes)<0&&(h.converters["text script"]=function(){}),b=ae(h,b,C,l),l?(h.ifModified&&(T=C.getResponseHeader("Last-Modified"),T&&(ke.lastModified[o]=T),T=C.getResponseHeader("etag"),T&&(ke.etag[o]=T)),204===t||"HEAD"===h.type?w="nocontent":304===t?w="notmodified":(w=b.state,p=b.data,d=b.error,l=!d)):(d=w,(t||!w)&&(w="error",0>t&&(t=0))),C.status=t,C.statusText=(n||w)+"",l?m.resolveWith(g,[p,w,C]):m.rejectWith(g,[C,w,d]),C.statusCode(x),x=void 0,f&&v.trigger(l?"ajaxSuccess":"ajaxError",[C,h,l?p:d]),y.fireWith(g,[C,w]),f&&(v.trigger("ajaxComplete",[C,h]),--ke.active||ke.event.trigger("ajaxStop")))}"object"==typeof t&&(n=t,t=void 0),n=n||{};var i,o,a,s,u,l,c,f,p,d,h=ke.ajaxSetup({},n),g=h.context||h,v=h.context&&(g.nodeType||g.jquery)?ke(g):ke.event,m=ke.Deferred(),y=ke.Callbacks("once memory"),x=h.statusCode||{},b={},T={},w="canceled",C={readyState:0,getResponseHeader:function(e){var t;if(c){if(!s){for(s={};t=Yt.exec(a);){s[t[1].toLowerCase()+" "]=(s[t[1].toLowerCase()+" "]||[]).concat(t[2])}}t=s[e.toLowerCase()+" "]}return null==t?null:t.join(", ")},getAllResponseHeaders:function(){return c?a:null},setRequestHeader:function(e,t){return null==c&&(e=T[e.toLowerCase()]=T[e.toLowerCase()]||e,b[e]=t),this},overrideMimeType:function(e){return null==c&&(h.mimeType=e),this},statusCode:function(e){var t;if(e){if(c){C.always(e[C.status])}else{for(t in e){x[t]=[x[t],e[t]]}}}return this},abort:function(e){var t=e||w;return i&&i.abort(t),r(0,t),this}};if(m.promise(C),h.url=((t||h.url||Rt.href)+"").replace(Kt,Rt.protocol+"//"),h.type=n.method||n.type||h.method||h.type,h.dataTypes=(h.dataType||"*").toLowerCase().match(_e)||[""],null==h.crossDomain){l=Te.createElement("a");try{l.href=h.url,l.href=l.href,h.crossDomain=nn.protocol+"//"+nn.host!=l.protocol+"//"+l.host}catch(S){h.crossDomain=!0}}if(h.data&&h.processData&&"string"!=typeof h.data&&(h.data=ke.param(h.data,h.traditional)),re(Zt,h,n,C),c){return C}f=ke.event&&h.global,f&&0===ke.active++&&ke.event.trigger("ajaxStart"),h.type=h.type.toUpperCase(),h.hasContent=!Jt.test(h.type),o=h.url.replace(Vt,""),h.hasContent?h.data&&h.processData&&0===(h.contentType||"").indexOf("application/x-www-form-urlencoded")&&(h.data=h.data.replace(Ut,"+")):(d=h.url.slice(o.length),h.data&&(h.processData||"string"==typeof h.data)&&(o+=(Wt.test(o)?"&":"?")+h.data,delete h.data),h.cache===!1&&(o=o.replace(Gt,"$1"),d=(Wt.test(o)?"&":"?")+"_="+It.guid+++d),h.url=o+d),h.ifModified&&(ke.lastModified[o]&&C.setRequestHeader("If-Modified-Since",ke.lastModified[o]),ke.etag[o]&&C.setRequestHeader("If-None-Match",ke.etag[o])),(h.data&&h.hasContent&&h.contentType!==!1||n.contentType)&&C.setRequestHeader("Content-Type",h.contentType),C.setRequestHeader("Accept",h.dataTypes[0]&&h.accepts[h.dataTypes[0]]?h.accepts[h.dataTypes[0]]+("*"!==h.dataTypes[0]?", "+tn+"; q=0.01":""):h.accepts["*"]);for(p in h.headers){C.setRequestHeader(p,h.headers[p])}if(h.beforeSend&&(h.beforeSend.call(g,C,h)===!1||c)){return C.abort()}if(w="abort",y.add(h.complete),C.done(h.success),C.fail(h.error),i=re(en,h,n,C)){if(C.readyState=1,f&&v.trigger("ajaxSend",[C,h]),c){return C}h.async&&h.timeout>0&&(u=e.setTimeout(function(){C.abort("timeout")},h.timeout));try{c=!1,i.send(b,r)}catch(S){if(c){throw S}r(-1,S)}}else{r(-1,"No Transport")}return C},getJSON:function(e,t,n){return ke.get(e,t,n,"json")},getScript:function(e,t){return ke.get(e,void 0,t,"script")}}),ke.each(["get","post"],function(e,t){ke[t]=function(e,n,r,i){return xe(n)&&(i=i||r,r=n,n=void 0),ke.ajax(ke.extend({url:e,type:t,dataType:i,data:n,success:r},ke.isPlainObject(e)&&e))}}),ke.ajaxPrefilter(function(e){var t;for(t in e.headers){"content-type"===t.toLowerCase()&&(e.contentType=e.headers[t]||"")}}),ke._evalUrl=function(e,t,n){return ke.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,converters:{"text script":function(){}},dataFilter:function(e){ke.globalEval(e,t,n)}})},ke.fn.extend({wrapAll:function(e){var t;return this[0]&&(xe(e)&&(e=e.call(this[0])),t=ke(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){for(var e=this;e.firstElementChild;){e=e.firstElementChild}return e}).append(this)),this},wrapInner:function(e){return xe(e)?this.each(function(t){ke(this).wrapInner(e.call(this,t))}):this.each(function(){var t=ke(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=xe(e);return this.each(function(n){ke(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(e){return this.parent(e).not("body").each(function(){ke(this).replaceWith(this.childNodes)}),this}}),ke.expr.pseudos.hidden=function(e){return !ke.expr.pseudos.visible(e)},ke.expr.pseudos.visible=function(e){return !!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},ke.ajaxSettings.xhr=function(){try{return new e.XMLHttpRequest}catch(t){}};var rn={0:200,1223:204},on=ke.ajaxSettings.xhr();ye.cors=!!on&&"withCredentials" in on,ye.ajax=on=!!on,ke.ajaxTransport(function(t){var n,r;return ye.cors||on&&!t.crossDomain?{send:function(i,o){var a,s=t.xhr();if(s.open(t.type,t.url,t.async,t.username,t.password),t.xhrFields){for(a in t.xhrFields){s[a]=t.xhrFields[a]}}t.mimeType&&s.overrideMimeType&&s.overrideMimeType(t.mimeType),t.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");for(a in i){s.setRequestHeader(a,i[a])}n=function(e){return function(){n&&(n=r=s.onload=s.onerror=s.onabort=s.ontimeout=s.onreadystatechange=null,"abort"===e?s.abort():"error"===e?"number"!=typeof s.status?o(0,"error"):o(s.status,s.statusText):o(rn[s.status]||s.status,s.statusText,"text"!==(s.responseType||"text")||"string"!=typeof s.responseText?{binary:s.response}:{text:s.responseText},s.getAllResponseHeaders()))}},s.onload=n(),r=s.onerror=s.ontimeout=n("error"),void 0!==s.onabort?s.onabort=r:s.onreadystatechange=function(){4===s.readyState&&e.setTimeout(function(){n&&r()})},n=n("abort");try{s.send(t.hasContent&&t.data||null)}catch(u){if(n){throw u}}},abort:function(){n&&n()}}:void 0}),ke.ajaxPrefilter(function(e){e.crossDomain&&(e.contents.script=!1)}),ke.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return ke.globalEval(e),e}}}),ke.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),ke.ajaxTransport("script",function(e){if(e.crossDomain||e.scriptAttrs){var t,n;return{send:function(r,i){t=ke("<script>").attr(e.scriptAttrs||{}).prop({charset:e.scriptCharset,src:e.url}).on("load error",n=function(e){t.remove(),n=null,e&&i("error"===e.type?404:200,e.type)}),Te.head.appendChild(t[0])},abort:function(){n&&n()}}}});var an=[],sn=/(=)\?(?=&|$)|\?\?/;ke.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=an.pop()||ke.expando+"_"+It.guid++;return this[e]=!0,e}}),ke.ajaxPrefilter("json jsonp",function(t,n,r){var i,o,a,s=t.jsonp!==!1&&(sn.test(t.url)?"url":"string"==typeof t.data&&0===(t.contentType||"").indexOf("application/x-www-form-urlencoded")&&sn.test(t.data)&&"data");return s||"jsonp"===t.dataTypes[0]?(i=t.jsonpCallback=xe(t.jsonpCallback)?t.jsonpCallback():t.jsonpCallback,s?t[s]=t[s].replace(sn,"$1"+i):t.jsonp!==!1&&(t.url+=(Wt.test(t.url)?"&":"?")+t.jsonp+"="+i),t.converters["script json"]=function(){return a||ke.error(i+" was not called"),a[0]},t.dataTypes[0]="json",o=e[i],e[i]=function(){a=arguments},r.always(function(){void 0===o?ke(e).removeProp(i):e[i]=o,t[i]&&(t.jsonpCallback=n.jsonpCallback,an.push(i)),a&&xe(o)&&o(a[0]),a=o=void 0}),"script"):void 0}),ye.createHTMLDocument=function(){var e=Te.implementation.createHTMLDocument("").body;return e.innerHTML="<form></form><form></form>",2===e.childNodes.length}(),ke.parseHTML=function(e,t,n){if("string"!=typeof e){return[]}"boolean"==typeof t&&(n=t,t=!1);var r,i,o;return t||(ye.createHTMLDocument?(t=Te.implementation.createHTMLDocument(""),r=t.createElement("base"),r.href=Te.location.href,t.head.appendChild(r)):t=Te),i=Re.exec(e),o=!n&&[],i?[t.createElement(i[1])]:(i=S([e],t,o),o&&o.length&&ke(o).remove(),ke.merge([],i.childNodes))},ke.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return s>-1&&(r=K(e.slice(s)),e=e.slice(0,s)),xe(t)?(n=t,t=void 0):t&&"object"==typeof t&&(i="POST"),a.length>0&&ke.ajax({url:e,type:i||"GET",dataType:"html",data:t}).done(function(e){o=arguments,a.html(r?ke("<div>").append(ke.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},ke.expr.pseudos.animated=function(e){return ke.grep(ke.timers,function(t){return e===t.elem}).length},ke.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l,c=ke.css(e,"position"),f=ke(e),p={};"static"===c&&(e.style.position="relative"),s=f.offset(),o=ke.css(e,"top"),u=ke.css(e,"left"),l=("absolute"===c||"fixed"===c)&&(o+u).indexOf("auto")>-1,l?(r=f.position(),a=r.top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),xe(t)&&(t=t.call(e,n,ke.extend({},s))),null!=t.top&&(p.top=t.top-s.top+a),null!=t.left&&(p.left=t.left-s.left+i),"using" in t?t.using.call(e,p):f.css(p)}},ke.fn.extend({offset:function(e){if(arguments.length){return void 0===e?this:this.each(function(t){ke.offset.setOffset(this,e,t)})}var t,n,r=this[0];if(r){return r.getClientRects().length?(t=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:t.top+n.pageYOffset,left:t.left+n.pageXOffset}):{top:0,left:0}}},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===ke.css(r,"position")){t=r.getBoundingClientRect()}else{for(t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;e&&(e===n.body||e===n.documentElement)&&"static"===ke.css(e,"position");){e=e.parentNode}e&&e!==r&&1===e.nodeType&&(i=ke(e).offset(),i.top+=ke.css(e,"borderTopWidth",!0),i.left+=ke.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-ke.css(r,"marginTop",!0),left:t.left-i.left-ke.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){for(var e=this.offsetParent;e&&"static"===ke.css(e,"position");){e=e.offsetParent}return e||rt})}}),ke.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,t){var n="pageYOffset"===t;ke.fn[e]=function(r){return Ue(this,function(e,r,i){var o;return be(e)?o=e:9===e.nodeType&&(o=e.defaultView),void 0===i?o?o[t]:e[r]:void (o?o.scrollTo(n?o.pageXOffset:i,n?i:o.pageYOffset):e[r]=i)},e,r,arguments.length)}}),ke.each(["top","left"],function(e,t){ke.cssHooks[t]=R(ye.pixelPosition,function(e,n){return n?(n=M(e,t),mt.test(n)?ke(e).position()[t]+"px":n):void 0})}),ke.each({Height:"height",Width:"width"},function(e,t){ke.each({padding:"inner"+e,content:t,"":"outer"+e},function(n,r){ke.fn[r]=function(i,o){var a=arguments.length&&(n||"boolean"!=typeof i),s=n||(i===!0||o===!0?"margin":"border");return Ue(this,function(t,n,i){var o;return be(t)?0===r.indexOf("outer")?t["inner"+e]:t.document.documentElement["client"+e]:9===t.nodeType?(o=t.documentElement,Math.max(t.body["scroll"+e],o["scroll"+e],t.body["offset"+e],o["offset"+e],o["client"+e])):void 0===i?ke.css(t,n,s):ke.style(t,n,i,s)},t,a?i:void 0,a)}})}),ke.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){ke.fn[t]=function(e){return this.on(t,e)}}),ke.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.on("mouseenter",e).on("mouseleave",t||e)}}),ke.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,t){ke.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}});var un=/^[\s\uFEFF\xA0]+|([^\s\uFEFF\xA0])[\s\uFEFF\xA0]+$/g;ke.proxy=function(e,t){var n,r,i;return"string"==typeof t&&(n=e[t],t=e,e=n),xe(e)?(r=le.call(arguments,2),i=function(){return e.apply(t||this,r.concat(le.call(arguments)))},i.guid=e.guid=e.guid||ke.guid++,i):void 0},ke.holdReady=function(e){e?ke.readyWait++:ke.ready(!0)},ke.isArray=Array.isArray,ke.parseJSON=JSON.parse,ke.nodeName=o,ke.isFunction=xe,ke.isWindow=be,ke.camelCase=g,ke.type=r,ke.now=Date.now,ke.isNumeric=function(e){var t=ke.type(e);return("number"===t||"string"===t)&&!isNaN(e-parseFloat(e))},ke.trim=function(e){return null==e?"":(e+"").replace(un,"$1")},"function"==typeof define&&define.amd&&define("jquery",[],function(){return ke});var ln=e.jQuery,cn=e.$;return ke.noConflict=function(t){return e.$===ke&&(e.$=cn),t&&e.jQuery===ke&&(e.jQuery=ln),ke},void 0===t&&(e.jQuery=e.$=ke),ke});
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/js/jquery.tmpl.js b/ruoyi-admin/src/main/resources/static/js/jquery.tmpl.js
new file mode 100644
index 0000000..7d130d2
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/js/jquery.tmpl.js
@@ -0,0 +1,492 @@
+/*!
+ * jQuery Templates Plugin 1.0.0pre
+ * http://github.com/jquery/jquery-tmpl
+ * Requires jQuery 1.4.2
+ *
+ * Copyright 2011, Software Freedom Conservancy, Inc.
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ */
+(function( factory ) {
+	if (typeof define === 'function' && define.amd) {
+		// Loading from AMD script loader. Register as an anonymous module.
+		define( ['jquery'], factory );
+	} else {
+		// Browser using plain <script> tag
+		factory( jQuery );
+	}
+}(function( jQuery ){
+	var oldManip = jQuery.fn.domManip, tmplItmAtt = "_tmplitem", htmlExpr = /^[^<]*(<[\w\W]+>)[^>]*$|\{\{\! /,
+		newTmplItems = {}, wrappedItems = {}, appendToTmplItems, topTmplItem = { key: 0, data: {} }, itemKey = 0, cloneIndex = 0, stack = [];
+
+	function newTmplItem( options, parentItem, fn, data ) {
+		// Returns a template item data structure for a new rendered instance of a template (a 'template item').
+		// The content field is a hierarchical array of strings and nested items (to be
+		// removed and replaced by nodes field of dom elements, once inserted in DOM).
+		var newItem = {
+			data: data || (data === 0 || data === false) ? data : (parentItem ? parentItem.data : {}),
+			_wrap: parentItem ? parentItem._wrap : null,
+			tmpl: null,
+			parent: parentItem || null,
+			nodes: [],
+			calls: tiCalls,
+			nest: tiNest,
+			wrap: tiWrap,
+			html: tiHtml,
+			update: tiUpdate
+		};
+		if ( options ) {
+			jQuery.extend( newItem, options, { nodes: [], parent: parentItem });
+		}
+		if ( fn ) {
+			// Build the hierarchical content to be used during insertion into DOM
+			newItem.tmpl = fn;
+			newItem._ctnt = newItem._ctnt || newItem.tmpl( jQuery, newItem );
+			newItem.key = ++itemKey;
+			// Keep track of new template item, until it is stored as jQuery Data on DOM element
+			(stack.length ? wrappedItems : newTmplItems)[itemKey] = newItem;
+		}
+		return newItem;
+	}
+
+	// Override appendTo etc., in order to provide support for targeting multiple elements. (This code would disappear if integrated in jquery core).
+	jQuery.each({
+		appendTo: "append",
+		prependTo: "prepend",
+		insertBefore: "before",
+		insertAfter: "after",
+		replaceAll: "replaceWith"
+	}, function( name, original ) {
+		jQuery.fn[ name ] = function( selector ) {
+			var ret = [], insert = jQuery( selector ), elems, i, l, tmplItems,
+				parent = this.length === 1 && this[0].parentNode;
+
+			appendToTmplItems = newTmplItems || {};
+			if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {
+				insert[ original ]( this[0] );
+				ret = this;
+			} else {
+				for ( i = 0, l = insert.length; i < l; i++ ) {
+					cloneIndex = i;
+					elems = (i > 0 ? this.clone(true) : this).get();
+					jQuery( insert[i] )[ original ]( elems );
+					ret = ret.concat( elems );
+				}
+				cloneIndex = 0;
+				ret = this.pushStack( ret, name, insert.selector );
+			}
+			tmplItems = appendToTmplItems;
+			appendToTmplItems = null;
+			jQuery.tmpl.complete( tmplItems );
+			return ret;
+		};
+	});
+
+	jQuery.fn.extend({
+		// Use first wrapped element as template markup.
+		// Return wrapped set of template items, obtained by rendering template against data.
+		tmpl: function( data, options, parentItem ) {
+			return jQuery.tmpl( this[0], data, options, parentItem );
+		},
+
+		// Find which rendered template item the first wrapped DOM element belongs to
+		tmplItem: function() {
+			return jQuery.tmplItem( this[0] );
+		},
+
+		// Consider the first wrapped element as a template declaration, and get the compiled template or store it as a named template.
+		template: function( name ) {
+			return jQuery.template( name, this[0] );
+		},
+
+		domManip: function( args, table, callback, options ) {
+			if ( args[0] && jQuery.isArray( args[0] )) {
+				var dmArgs = jQuery.makeArray( arguments ), elems = args[0], elemsLength = elems.length, i = 0, tmplItem;
+				while ( i < elemsLength && !(tmplItem = jQuery.data( elems[i++], "tmplItem" ))) {}
+				if ( tmplItem && cloneIndex ) {
+					dmArgs[2] = function( fragClone ) {
+						// Handler called by oldManip when rendered template has been inserted into DOM.
+						jQuery.tmpl.afterManip( this, fragClone, callback );
+					};
+				}
+				oldManip.apply( this, dmArgs );
+			} else {
+				oldManip.apply( this, arguments );
+			}
+			cloneIndex = 0;
+			if ( !appendToTmplItems ) {
+				jQuery.tmpl.complete( newTmplItems );
+			}
+			return this;
+		}
+	});
+
+	jQuery.extend({
+		// Return wrapped set of template items, obtained by rendering template against data.
+		tmpl: function( tmpl, data, options, parentItem ) {
+			var ret, topLevel = !parentItem;
+			if ( topLevel ) {
+				// This is a top-level tmpl call (not from a nested template using {{tmpl}})
+				parentItem = topTmplItem;
+				tmpl = jQuery.template[tmpl] || jQuery.template( null, tmpl );
+				wrappedItems = {}; // Any wrapped items will be rebuilt, since this is top level
+			} else if ( !tmpl ) {
+				// The template item is already associated with DOM - this is a refresh.
+				// Re-evaluate rendered template for the parentItem
+				tmpl = parentItem.tmpl;
+				newTmplItems[parentItem.key] = parentItem;
+				parentItem.nodes = [];
+				if ( parentItem.wrapped ) {
+					updateWrapped( parentItem, parentItem.wrapped );
+				}
+				// Rebuild, without creating a new template item
+				return jQuery( build( parentItem, null, parentItem.tmpl( jQuery, parentItem ) ));
+			}
+			if ( !tmpl ) {
+				return []; // Could throw...
+			}
+			if ( typeof data === "function" ) {
+				data = data.call( parentItem || {} );
+			}
+			if ( options && options.wrapped ) {
+				updateWrapped( options, options.wrapped );
+			}
+			ret = jQuery.isArray( data ) ?
+				jQuery.map( data, function( dataItem ) {
+					return dataItem ? newTmplItem( options, parentItem, tmpl, dataItem ) : null;
+				}) :
+				[ newTmplItem( options, parentItem, tmpl, data ) ];
+			return topLevel ? jQuery( build( parentItem, null, ret ) ) : ret;
+		},
+
+		// Return rendered template item for an element.
+		tmplItem: function( elem ) {
+			var tmplItem;
+			if ( elem instanceof jQuery ) {
+				elem = elem[0];
+			}
+			while ( elem && elem.nodeType === 1 && !(tmplItem = jQuery.data( elem, "tmplItem" )) && (elem = elem.parentNode) ) {}
+			return tmplItem || topTmplItem;
+		},
+
+		// Set:
+		// Use $.template( name, tmpl ) to cache a named template,
+		// where tmpl is a template string, a script element or a jQuery instance wrapping a script element, etc.
+		// Use $( "selector" ).template( name ) to provide access by name to a script block template declaration.
+
+		// Get:
+		// Use $.template( name ) to access a cached template.
+		// Also $( selectorToScriptBlock ).template(), or $.template( null, templateString )
+		// will return the compiled template, without adding a name reference.
+		// If templateString includes at least one HTML tag, $.template( templateString ) is equivalent
+		// to $.template( null, templateString )
+		template: function( name, tmpl ) {
+			if (tmpl) {
+				// Compile template and associate with name
+				if ( typeof tmpl === "string" ) {
+					// This is an HTML string being passed directly in.
+					tmpl = buildTmplFn( tmpl );
+				} else if ( tmpl instanceof jQuery ) {
+					tmpl = tmpl[0] || {};
+				}
+				if ( tmpl.nodeType ) {
+					// If this is a template block, use cached copy, or generate tmpl function and cache.
+					tmpl = jQuery.data( tmpl, "tmpl" ) || jQuery.data( tmpl, "tmpl", buildTmplFn( tmpl.innerHTML ));
+					// Issue: In IE, if the container element is not a script block, the innerHTML will remove quotes from attribute values whenever the value does not include white space.
+					// This means that foo="${x}" will not work if the value of x includes white space: foo="${x}" -> foo=value of x.
+					// To correct this, include space in tag: foo="${ x }" -> foo="value of x"
+				}
+				return typeof name === "string" ? (jQuery.template[name] = tmpl) : tmpl;
+			}
+			// Return named compiled template
+			return name ? (typeof name !== "string" ? jQuery.template( null, name ):
+				(jQuery.template[name] ||
+					// If not in map, and not containing at least on HTML tag, treat as a selector.
+					// (If integrated with core, use quickExpr.exec)
+					jQuery.template( null, htmlExpr.test( name ) ? name : jQuery( name )))) : null;
+		},
+
+		encode: function( text ) {
+			// Do HTML encoding replacing < > & and ' and " by corresponding entities.
+			return ("" + text).split("<").join("&lt;").split(">").join("&gt;").split('"').join("&#34;").split("'").join("&#39;");
+		}
+	});
+
+	jQuery.extend( jQuery.tmpl, {
+		tag: {
+			"tmpl": {
+				_default: { $2: "null" },
+				open: "if($notnull_1){__=__.concat($item.nest($1,$2));}"
+				// tmpl target parameter can be of type function, so use $1, not $1a (so not auto detection of functions)
+				// This means that {{tmpl foo}} treats foo as a template (which IS a function).
+				// Explicit parens can be used if foo is a function that returns a template: {{tmpl foo()}}.
+			},
+			"wrap": {
+				_default: { $2: "null" },
+				open: "$item.calls(__,$1,$2);__=[];",
+				close: "call=$item.calls();__=call._.concat($item.wrap(call,__));"
+			},
+			"each": {
+				_default: { $2: "$index, $value" },
+				open: "if($notnull_1){$.each($1a,function($2){with(this){",
+				close: "}});}"
+			},
+			"if": {
+				open: "if(($notnull_1) && $1a){",
+				close: "}"
+			},
+			"else": {
+				_default: { $1: "true" },
+				open: "}else if(($notnull_1) && $1a){"
+			},
+			"html": {
+				// Unecoded expression evaluation.
+				open: "if($notnull_1){__.push($1a);}"
+			},
+			"=": {
+				// Encoded expression evaluation. Abbreviated form is ${}.
+				_default: { $1: "$data" },
+				open: "if($notnull_1){__.push($.encode($1a));}"
+			},
+			"!": {
+				// Comment tag. Skipped by parser
+				open: ""
+			}
+		},
+
+		// This stub can be overridden, e.g. in jquery.tmplPlus for providing rendered events
+		complete: function( items ) {
+			newTmplItems = {};
+		},
+
+		// Call this from code which overrides domManip, or equivalent
+		// Manage cloning/storing template items etc.
+		afterManip: function afterManip( elem, fragClone, callback ) {
+			// Provides cloned fragment ready for fixup prior to and after insertion into DOM
+			var content = fragClone.nodeType === 11 ?
+				jQuery.makeArray(fragClone.childNodes) :
+				fragClone.nodeType === 1 ? [fragClone] : [];
+
+			// Return fragment to original caller (e.g. append) for DOM insertion
+			callback.call( elem, fragClone );
+
+			// Fragment has been inserted:- Add inserted nodes to tmplItem data structure. Replace inserted element annotations by jQuery.data.
+			storeTmplItems( content );
+			cloneIndex++;
+		}
+	});
+
+	//========================== Private helper functions, used by code above ==========================
+
+	function build( tmplItem, nested, content ) {
+		// Convert hierarchical content into flat string array
+		// and finally return array of fragments ready for DOM insertion
+		var frag, ret = content ? jQuery.map( content, function( item ) {
+			return (typeof item === "string") ?
+				// Insert template item annotations, to be converted to jQuery.data( "tmplItem" ) when elems are inserted into DOM.
+				(tmplItem.key ? item.replace( /(<\w+)(?=[\s>])(?![^>]*_tmplitem)([^>]*)/g, "$1 " + tmplItmAtt + "=\"" + tmplItem.key + "\" $2" ) : item) :
+				// This is a child template item. Build nested template.
+				build( item, tmplItem, item._ctnt );
+		}) :
+		// If content is not defined, insert tmplItem directly. Not a template item. May be a string, or a string array, e.g. from {{html $item.html()}}.
+		tmplItem;
+		if ( nested ) {
+			return ret;
+		}
+
+		// top-level template
+		ret = ret.join("");
+
+		// Support templates which have initial or final text nodes, or consist only of text
+		// Also support HTML entities within the HTML markup.
+		ret.replace( /^\s*([^<\s][^<]*)?(<[\w\W]+>)([^>]*[^>\s])?\s*$/, function( all, before, middle, after) {
+			frag = jQuery( middle ).get();
+
+			storeTmplItems( frag );
+			if ( before ) {
+				frag = unencode( before ).concat(frag);
+			}
+			if ( after ) {
+				frag = frag.concat(unencode( after ));
+			}
+		});
+		return frag ? frag : unencode( ret );
+	}
+
+	function unencode( text ) {
+		// Use createElement, since createTextNode will not render HTML entities correctly
+		var el = document.createElement( "div" );
+		el.innerHTML = text;
+		return jQuery.makeArray(el.childNodes);
+	}
+
+	// Generate a reusable function that will serve to render a template against data
+	function buildTmplFn( markup ) {
+		return new Function("jQuery","$item",
+			// Use the variable __ to hold a string array while building the compiled template. (See https://github.com/jquery/jquery-tmpl/issues#issue/10).
+			"var $=jQuery,call,__=[],$data=$item.data;" +
+
+			// Introduce the data as local variables using with(){}
+			"with($data){__.push('" +
+
+			// Convert the template into pure JavaScript
+			jQuery.trim(markup)
+				.replace( /([\\'])/g, "\\$1" )
+				.replace( /[\r\t\n]/g, " " )
+				.replace( /\$\{([^\}]*)\}/g, "{{= $1}}" )
+				.replace( /\{\{(\/?)(\w+|.)(?:\(((?:[^\}]|\}(?!\}))*?)?\))?(?:\s+(.*?)?)?(\(((?:[^\}]|\}(?!\}))*?)\))?\s*\}\}/g,
+				function( all, slash, type, fnargs, target, parens, args ) {
+					var tag = jQuery.tmpl.tag[ type ], def, expr, exprAutoFnDetect;
+					if ( !tag ) {
+						throw "Unknown template tag: " + type;
+					}
+					def = tag._default || [];
+					if ( parens && !/\w$/.test(target)) {
+						target += parens;
+						parens = "";
+					}
+					if ( target ) {
+						target = unescape( target );
+						args = args ? ("," + unescape( args ) + ")") : (parens ? ")" : "");
+						// Support for target being things like a.toLowerCase();
+						// In that case don't call with template item as 'this' pointer. Just evaluate...
+						expr = parens ? (target.indexOf(".") > -1 ? target + unescape( parens ) : ("(" + target + ").call($item" + args)) : target;
+						exprAutoFnDetect = parens ? expr : "(typeof(" + target + ")==='function'?(" + target + ").call($item):(" + target + "))";
+					} else {
+						exprAutoFnDetect = expr = def.$1 || "null";
+					}
+					fnargs = unescape( fnargs );
+					return "');" +
+						tag[ slash ? "close" : "open" ]
+							.split( "$notnull_1" ).join( target ? "typeof(" + target + ")!=='undefined' && (" + target + ")!=null" : "true" )
+							.split( "$1a" ).join( exprAutoFnDetect )
+							.split( "$1" ).join( expr )
+							.split( "$2" ).join( fnargs || def.$2 || "" ) +
+						"__.push('";
+				}) +
+			"');}return __;"
+		);
+	}
+	function updateWrapped( options, wrapped ) {
+		// Build the wrapped content.
+		options._wrap = build( options, true,
+			// Suport imperative scenario in which options.wrapped can be set to a selector or an HTML string.
+			jQuery.isArray( wrapped ) ? wrapped : [htmlExpr.test( wrapped ) ? wrapped : jQuery( wrapped ).html()]
+		).join("");
+	}
+
+	function unescape( args ) {
+		return args ? args.replace( /\\'/g, "'").replace(/\\\\/g, "\\" ) : null;
+	}
+	function outerHtml( elem ) {
+		var div = document.createElement("div");
+		div.appendChild( elem.cloneNode(true) );
+		return div.innerHTML;
+	}
+
+	// Store template items in jQuery.data(), ensuring a unique tmplItem data data structure for each rendered template instance.
+	function storeTmplItems( content ) {
+		var keySuffix = "_" + cloneIndex, elem, elems, newClonedItems = {}, i, l, m;
+		for ( i = 0, l = content.length; i < l; i++ ) {
+			if ( (elem = content[i]).nodeType !== 1 ) {
+				continue;
+			}
+			elems = elem.getElementsByTagName("*");
+			for ( m = elems.length - 1; m >= 0; m-- ) {
+				processItemKey( elems[m] );
+			}
+			processItemKey( elem );
+		}
+		function processItemKey( el ) {
+			var pntKey, pntNode = el, pntItem, tmplItem, key;
+			// Ensure that each rendered template inserted into the DOM has its own template item,
+			if ( (key = el.getAttribute( tmplItmAtt ))) {
+				while ( pntNode.parentNode && (pntNode = pntNode.parentNode).nodeType === 1 && !(pntKey = pntNode.getAttribute( tmplItmAtt ))) { }
+				if ( pntKey !== key ) {
+					// The next ancestor with a _tmplitem expando is on a different key than this one.
+					// So this is a top-level element within this template item
+					// Set pntNode to the key of the parentNode, or to 0 if pntNode.parentNode is null, or pntNode is a fragment.
+					pntNode = pntNode.parentNode ? (pntNode.nodeType === 11 ? 0 : (pntNode.getAttribute( tmplItmAtt ) || 0)) : 0;
+					if ( !(tmplItem = newTmplItems[key]) ) {
+						// The item is for wrapped content, and was copied from the temporary parent wrappedItem.
+						tmplItem = wrappedItems[key];
+						tmplItem = newTmplItem( tmplItem, newTmplItems[pntNode]||wrappedItems[pntNode] );
+						tmplItem.key = ++itemKey;
+						newTmplItems[itemKey] = tmplItem;
+					}
+					if ( cloneIndex ) {
+						cloneTmplItem( key );
+					}
+				}
+				el.removeAttribute( tmplItmAtt );
+			} else if ( cloneIndex && (tmplItem = jQuery.data( el, "tmplItem" )) ) {
+				// This was a rendered element, cloned during append or appendTo etc.
+				// TmplItem stored in jQuery data has already been cloned in cloneCopyEvent. We must replace it with a fresh cloned tmplItem.
+				cloneTmplItem( tmplItem.key );
+				newTmplItems[tmplItem.key] = tmplItem;
+				pntNode = jQuery.data( el.parentNode, "tmplItem" );
+				pntNode = pntNode ? pntNode.key : 0;
+			}
+			if ( tmplItem ) {
+				pntItem = tmplItem;
+				// Find the template item of the parent element.
+				// (Using !=, not !==, since pntItem.key is number, and pntNode may be a string)
+				while ( pntItem && pntItem.key != pntNode ) {
+					// Add this element as a top-level node for this rendered template item, as well as for any
+					// ancestor items between this item and the item of its parent element
+					pntItem.nodes.push( el );
+					pntItem = pntItem.parent;
+				}
+				// Delete content built during rendering - reduce API surface area and memory use, and avoid exposing of stale data after rendering...
+				delete tmplItem._ctnt;
+				delete tmplItem._wrap;
+				// Store template item as jQuery data on the element
+				jQuery.data( el, "tmplItem", tmplItem );
+			}
+			function cloneTmplItem( key ) {
+				key = key + keySuffix;
+				tmplItem = newClonedItems[key] =
+					(newClonedItems[key] || newTmplItem( tmplItem, newTmplItems[tmplItem.parent.key + keySuffix] || tmplItem.parent ));
+			}
+		}
+	}
+
+	//---- Helper functions for template item ----
+
+	function tiCalls( content, tmpl, data, options ) {
+		if ( !content ) {
+			return stack.pop();
+		}
+		stack.push({ _: content, tmpl: tmpl, item:this, data: data, options: options });
+	}
+
+	function tiNest( tmpl, data, options ) {
+		// nested template, using {{tmpl}} tag
+		return jQuery.tmpl( jQuery.template( tmpl ), data, options, this );
+	}
+
+	function tiWrap( call, wrapped ) {
+		// nested template, using {{wrap}} tag
+		var options = call.options || {};
+		options.wrapped = wrapped;
+		// Apply the template, which may incorporate wrapped content,
+		return jQuery.tmpl( jQuery.template( call.tmpl ), call.data, options, call.item );
+	}
+
+	function tiHtml( filter, textOnly ) {
+		var wrapped = this._wrap;
+		return jQuery.map(
+			jQuery( jQuery.isArray( wrapped ) ? wrapped.join("") : wrapped ).filter( filter || "*" ),
+			function(e) {
+				return textOnly ?
+					e.innerText || e.textContent :
+					e.outerHTML || outerHtml(e);
+			});
+	}
+
+	function tiUpdate() {
+		var coll = this.nodes;
+		jQuery.tmpl( null, null, null, this).insertBefore( coll[0] );
+		jQuery( coll ).remove();
+	}
+}));
diff --git a/ruoyi-admin/src/main/resources/static/js/plugins/metisMenu/jquery.metisMenu.js b/ruoyi-admin/src/main/resources/static/js/plugins/metisMenu/jquery.metisMenu.js
new file mode 100644
index 0000000..6f22eff
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/js/plugins/metisMenu/jquery.metisMenu.js
@@ -0,0 +1,10 @@
+/*
+ * metismenu - v2.0.2
+ * A jQuery menu plugin
+ * https://github.com/onokumus/metisMenu
+ *
+ * Made by Osman Nuri Okumus
+ * Under MIT License
+ */
+
+!function(a){"use strict";function b(){var a=document.createElement("mm"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}function c(b){return this.each(function(){var c=a(this),d=c.data("mm"),f=a.extend({},e.DEFAULTS,c.data(),"object"==typeof b&&b);d||c.data("mm",d=new e(this,f)),"string"==typeof b&&d[b]()})}a.fn.emulateTransitionEnd=function(b){var c=!1,e=this;a(this).one("mmTransitionEnd",function(){c=!0});var f=function(){c||a(e).trigger(d.end)};return setTimeout(f,b),this};var d=b();d&&(a.event.special.mmTransitionEnd={bindType:d.end,delegateType:d.end,handle:function(b){return a(b.target).is(this)?b.handleObj.handler.apply(this,arguments):void 0}});var e=function(b,c){this.$element=a(b),this.options=a.extend({},e.DEFAULTS,c),this.transitioning=null,this.init()};e.TRANSITION_DURATION=350,e.DEFAULTS={toggle:!0,doubleTapToGo:!1,activeClass:"active"},e.prototype.init=function(){var b=this,c=this.options.activeClass;this.$element.find("li."+c).has("ul").children("ul").addClass("collapse in"),this.$element.find("li").not("."+c).has("ul").children("ul").addClass("collapse"),this.options.doubleTapToGo&&this.$element.find("li."+c).has("ul").children("a").addClass("doubleTapToGo"),this.$element.find("li").has("ul").children("a").on("click.metisMenu",function(d){var e=a(this),f=e.parent("li"),g=f.children("ul");return d.preventDefault(),f.hasClass(c)?b.hide(g):b.show(g),b.options.doubleTapToGo&&b.doubleTapToGo(e)&&"#"!==e.attr("href")&&""!==e.attr("href")?(d.stopPropagation(),void(document.location=e.attr("href"))):void 0})},e.prototype.doubleTapToGo=function(a){var b=this.$element;return a.hasClass("doubleTapToGo")?(a.removeClass("doubleTapToGo"),!0):a.parent().children("ul").length?(b.find(".doubleTapToGo").removeClass("doubleTapToGo"),a.addClass("doubleTapToGo"),!1):void 0},e.prototype.show=function(b){var c=this.options.activeClass,f=a(b),g=f.parent("li");if(!this.transitioning&&!f.hasClass("in")){g.addClass(c),this.options.toggle&&this.hide(g.siblings().children("ul.in")),f.removeClass("collapse").addClass("collapsing").height(0),this.transitioning=1;var h=function(){f.removeClass("collapsing").addClass("collapse in").height(""),this.transitioning=0};return d?void f.one("mmTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(e.TRANSITION_DURATION).height(f[0].scrollHeight):h.call(this)}},e.prototype.hide=function(b){var c=this.options.activeClass,f=a(b);if(!this.transitioning&&f.hasClass("in")){f.parent("li").removeClass(c),f.height(f.height())[0].offsetHeight,f.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var g=function(){this.transitioning=0,f.removeClass("collapsing").addClass("collapse")};return d?void f.height(0).one("mmTransitionEnd",a.proxy(g,this)).emulateTransitionEnd(e.TRANSITION_DURATION):g.call(this)}};var f=a.fn.metisMenu;a.fn.metisMenu=c,a.fn.metisMenu.Constructor=e,a.fn.metisMenu.noConflict=function(){return a.fn.metisMenu=f,this}}(jQuery);
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/js/plugins/slimscroll/jquery.slimscroll.min.js b/ruoyi-admin/src/main/resources/static/js/plugins/slimscroll/jquery.slimscroll.min.js
new file mode 100644
index 0000000..be56f0a
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/js/plugins/slimscroll/jquery.slimscroll.min.js
@@ -0,0 +1,8 @@
+/*! Copyright (c) 2011 Piotr Rochala (http://rocha.la)
+ * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
+ * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
+ *
+ * Version: 1.3.8
+ *
+ */
+(function($){$.fn.extend({slimScroll:function(options){var defaults={width:"auto",height:"250px",size:"5px",color:"#99a9bf",position:"right",distance:"1px",start:"top",opacity:0.4,alwaysVisible:false,disableFadeOut:false,railVisible:false,railColor:"#333",railOpacity:0.2,railDraggable:true,railClass:"slimScrollRail",barClass:"slimScrollBar",wrapperClass:"slimScrollDiv",allowPageScroll:false,wheelStep:20,touchScrollStep:200,borderRadius:"7px",railBorderRadius:"7px"};var o=$.extend(defaults,options);this.each(function(){var isOverPanel,isOverBar,isDragg,queueHide,touchDif,barHeight,percentScroll,lastScroll,divS="<div></div>",minBarHeight=30,releaseScroll=false;var me=$(this);if(me.parent().hasClass(o.wrapperClass)){var offset=me.scrollTop();bar=me.siblings("."+o.barClass);rail=me.siblings("."+o.railClass);getBarHeight();if($.isPlainObject(options)){if("height" in options&&options.height=="auto"){me.parent().css("height","auto");me.css("height","auto");var height=me.parent().parent().height();me.parent().css("height",height);me.css("height",height)}else{if("height" in options){var h=options.height;me.parent().css("height",h);me.css("height",h)}}if("scrollTo" in options){offset=parseInt(o.scrollTo)}else{if("scrollBy" in options){offset+=parseInt(o.scrollBy)}else{if("destroy" in options){bar.remove();rail.remove();me.unwrap();return}}}scrollContent(offset,false,true)}return}else{if($.isPlainObject(options)){if("destroy" in options){return}}}o.height=(o.height=="auto")?me.parent().height():o.height;var wrapper=$(divS).addClass(o.wrapperClass).css({position:"relative",width:o.width,height:o.height});me.css({width:o.width,height:o.height});var rail=$(divS).addClass(o.railClass).css({width:o.size,height:"100%",position:"absolute",top:0,display:(o.alwaysVisible&&o.railVisible)?"block":"none","border-radius":o.railBorderRadius,background:o.railColor,opacity:o.railOpacity,zIndex:90});var bar=$(divS).addClass(o.barClass).css({background:o.color,width:o.size,position:"absolute",top:0,opacity:o.opacity,display:o.alwaysVisible?"block":"none","border-radius":o.borderRadius,BorderRadius:o.borderRadius,MozBorderRadius:o.borderRadius,WebkitBorderRadius:o.borderRadius,zIndex:99});var posCss=(o.position=="right")?{right:o.distance}:{left:o.distance};rail.css(posCss);bar.css(posCss);me.wrap(wrapper);me.parent().append(bar);me.parent().append(rail);if(o.railDraggable){bar.bind("mousedown",function(e){var $doc=$(document);isDragg=true;t=parseFloat(bar.css("top"));pageY=e.pageY;$doc.bind("mousemove.slimscroll",function(e){currTop=t+e.pageY-pageY;bar.css("top",currTop);scrollContent(0,bar.position().top,false)});$doc.bind("mouseup.slimscroll",function(e){isDragg=false;hideBar();$doc.unbind(".slimscroll")});return false}).bind("selectstart.slimscroll",function(e){e.stopPropagation();e.preventDefault();return false})}rail.hover(function(){showBar()},function(){hideBar()});bar.hover(function(){isOverBar=true},function(){isOverBar=false});me.hover(function(){isOverPanel=true;showBar();hideBar()},function(){isOverPanel=false;hideBar()});me.bind("touchstart",function(e,b){if(e.originalEvent.touches.length){touchDif=e.originalEvent.touches[0].pageY}});me.bind("touchmove",function(e){if(!releaseScroll){e.originalEvent.preventDefault()}if(e.originalEvent.touches.length){var diff=(touchDif-e.originalEvent.touches[0].pageY)/o.touchScrollStep;scrollContent(diff,true);touchDif=e.originalEvent.touches[0].pageY}});getBarHeight();if(o.start==="bottom"){bar.css({top:me.outerHeight()-bar.outerHeight()});scrollContent(0,true)}else{if(o.start!=="top"){scrollContent($(o.start).position().top,null,true);if(!o.alwaysVisible){bar.hide()}}}attachWheel(this);function _onWheel(e){if(!isOverPanel){return}var e=e||window.event;var delta=0;if(e.wheelDelta){delta=-e.wheelDelta/120}if(e.detail){delta=e.detail/3}var target=e.target||e.srcTarget||e.srcElement;if($(target).closest("."+o.wrapperClass).is(me.parent())){scrollContent(delta,true)}if(e.preventDefault&&!releaseScroll){e.preventDefault()}if(!releaseScroll){e.returnValue=false}}function scrollContent(y,isWheel,isJump){releaseScroll=false;var delta=y;var maxTop=me.outerHeight()-bar.outerHeight();if(isWheel){delta=parseInt(bar.css("top"))+y*parseInt(o.wheelStep)/100*bar.outerHeight();delta=Math.min(Math.max(delta,0),maxTop);delta=(y>0)?Math.ceil(delta):Math.floor(delta);bar.css({top:delta+"px"})}percentScroll=parseInt(bar.css("top"))/(me.outerHeight()-bar.outerHeight());delta=percentScroll*(me[0].scrollHeight-me.outerHeight());if(isJump){delta=y;var offsetTop=delta/me[0].scrollHeight*me.outerHeight();offsetTop=Math.min(Math.max(offsetTop,0),maxTop);bar.css({top:offsetTop+"px"})}me.scrollTop(delta);me.trigger("slimscrolling",~~delta);showBar();hideBar()}function attachWheel(target){if(window.addEventListener){target.addEventListener("DOMMouseScroll",_onWheel,{capture:false,passive:false});target.addEventListener("mousewheel",_onWheel,{capture:false,passive:false})}else{document.attachEvent("onmousewheel",_onWheel)}}function getBarHeight(){barHeight=Math.max((me.outerHeight()/me[0].scrollHeight)*me.outerHeight(),minBarHeight);bar.css({height:barHeight+"px"});var display=barHeight==me.outerHeight()?"none":"block";bar.css({display:display})}function showBar(){getBarHeight();clearTimeout(queueHide);if(percentScroll==~~percentScroll){releaseScroll=o.allowPageScroll;if(lastScroll!=percentScroll){var msg=(~~percentScroll==0)?"top":"bottom";me.trigger("slimscroll",msg)}}else{releaseScroll=false}lastScroll=percentScroll;if(barHeight>=me.outerHeight()){releaseScroll=true;return}bar.stop(true,true).fadeIn("fast");if(o.railVisible){rail.stop(true,true).fadeIn("fast")}}function hideBar(){if(!o.alwaysVisible){queueHide=setTimeout(function(){if(!(o.disableFadeOut&&isOverPanel)&&!isOverBar&&!isDragg){bar.fadeOut("slow");rail.fadeOut("slow")}},1000)}}});return this}});$.fn.extend({slimscroll:$.fn.slimScroll})})(jQuery);
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/js/resize-tabs.js b/ruoyi-admin/src/main/resources/static/js/resize-tabs.js
new file mode 100644
index 0000000..992f7d2
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/js/resize-tabs.js
@@ -0,0 +1 @@
+(function(c,a,e){var b,d="resizeTabs",f={navSelector:".nav-tabs",itemSelector:">li",dropdownSelector:">.dropdown",dropdownItemSelector:"li",tabParentSelector:"",tabSelector:".tab-pane",activeClassName:"active",noNavClassName:".no-menu",fnCallback:""};b=function(j,i){var h=this.$tabs=e(j),k=this.options=e.extend(true,{},f,i),g=this.$nav=h.find(k.navSelector),l=this.$dropdown=g.find(k.dropdownSelector);this.$items=g.find(k.itemSelector).filter(function(){return !e(this).is(l)});this.$dropdownItems=l.find(k.dropdownItemSelector);if(k.tabParentSelector!==""){this.$tabPanel=e(k.tabParentSelector).find(k.tabSelector)}else{this.$tabPanel=h.find(k.tabSelector)}this.init()};b.prototype={init:function(){var j=this.itemsLenth=this.$items.length,h;if(j===0){throw"There should be some tags here "}if(this.$dropdown.length===0){this.flag=true;this.$nav.append('<li class="dropdown" role="presentation">'+'<a class="dropdown-toggle" data-toggle="dropdown" href="#" aria-expanded="false">'+'<i class="glyphicon glyphicon-align-justify"></i> <b class="caret"></b></a><ul class="dropdown-menu" role="menu"></ul></li>');this.$dropdown=this.$nav.find(this.options.dropdownSelector);this.$dropdown.css("opacity",0);h=this.$dropdown.width();h=h===0?90:h;this.$dropdown.addClass("hidden").css("opacity",1)}else{h=this.$dropdown.width()}this.breakpoints=[];for(var g=0;g<j+1;g++){var k=this.$items.eq(g).width(),l=0;switch(g){case 0:l=k+h;break;case j-1:l=this.breakpoints[g-1]+k-h;break;case j:l=this.breakpoints[g-1]+h;break;default:l=this.breakpoints[g-1]+k}this.breakpoints.push(l)}if(typeof this.options.fnCallback==="function"){this.options.fnCallback(this.$tabs)}this.bind();this.layout()},layout:function(){if(this.breakpoints.length<=0){return}var l=this.$tabs.width()-500,j=0,h=this,g=this.options.activeClassName,m=this.$tabPanel.filter("."+g).index(),k=function(p){var o=p;if(p===h.itemsLenth){o=p-1}for(;o<h.itemsLenth;o++){if(h.flag){h.$dropdown.find("ul").append(h.$items.eq(o).prop("outerHTML"))}else{h.$dropdown.find("ul>li"+h.options.noNavClassName+":first").before(h.$items.eq(o).prop("outerHTML"))}h.$items.eq(o).hide()}},n=function(p){for(var o=0;o<h.itemsLenth+1;o++){if(o<p){h.$items.eq(o).show()}else{k(p);h.$dropdown.find("ul>li").show();break}}h.$dropdownItems=h.$dropdown.find(h.options.dropdownItemSelector)};for(;j<this.breakpoints.length;j++){if(this.breakpoints[j]>l){break}}this.$items.removeClass(g);this.$dropdownItems.removeClass(g);this.$dropdown.removeClass(g);if(j===this.breakpoints.length){if(this.flag){this.$dropdown.addClass("hidden")}else{this.$dropdown.find("ul>li:not(li"+this.options.noNavClassName+")").remove()}this.$items.show();if(m!=-1){this.$items.eq(m-1).addClass(g)}}else{this.$dropdown.removeClass("hidden");if(this.flag){this.$dropdown.find("ul>li").remove()}else{this.$dropdown.find("ul>li:not(li"+this.options.noNavClassName+")").remove()}n(j);if(m<j){if(m!=-1){this.$items.eq(m-1).addClass(g)}}else{this.$dropdown.addClass(g);this.$dropdownItems.eq(m-j).addClass(g)}}},throttle:function(h,g){var k=h,j,i=true;return function(){var m=arguments,l=this;if(i){k.apply(l,m);i=false}if(j){return false}j=setInterval(function(){clearInterval(j);j=null;k.apply(l,m)},g||500)}},bind:function(){var g=this;e(c).resize(function(){g.throttle(function(){g.layout()},1000)()})}};e.fn[d]=function(g){if(typeof g==="string"){var i=g,h=Array.prototype.slice.call(arguments,1);if(/^_/.test(i)){console.error("No such method : "+g)}else{return this.each(function(){var j=e.data(this,d);if(j&&typeof j[i]==="function"){j[i].apply(j,h)}})}}else{return this.each(function(){if(!e.data(this,d)){e.data(this,d,new b(this,g))}else{e.data(this,d).init()}})}}})(window,document,jQuery);$("#navMenu").resizeTabs({tabParentSelector:"#side-menu"});
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/js/three.min.js b/ruoyi-admin/src/main/resources/static/js/three.min.js
new file mode 100644
index 0000000..103e921
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/js/three.min.js
@@ -0,0 +1,767 @@
+// three.js - http://github.com/mrdoob/three.js
+'use strict';var THREE=THREE||{REVISION:"53"};self.console=self.console||{info:function(){},log:function(){},debug:function(){},warn:function(){},error:function(){}};self.Int32Array=self.Int32Array||Array;self.Float32Array=self.Float32Array||Array;String.prototype.startsWith=String.prototype.startsWith||function(a){return this.slice(0,a.length)===a};String.prototype.endsWith=String.prototype.endsWith||function(a){var a=String(a),b=this.lastIndexOf(a);return(-1<b&&b)===this.length-a.length};
+String.prototype.trim=String.prototype.trim||function(){return this.replace(/^\s+|\s+$/g,"")};
+(function(){for(var a=0,b=["ms","moz","webkit","o"],c=0;c<b.length&&!window.requestAnimationFrame;++c)window.requestAnimationFrame=window[b[c]+"RequestAnimationFrame"],window.cancelAnimationFrame=window[b[c]+"CancelAnimationFrame"]||window[b[c]+"CancelRequestAnimationFrame"];void 0===window.requestAnimationFrame&&(window.requestAnimationFrame=function(b){var c=Date.now(),f=Math.max(0,16-(c-a)),g=window.setTimeout(function(){b(c+f)},f);a=c+f;return g});window.cancelAnimationFrame=window.cancelAnimationFrame||
+function(a){window.clearTimeout(a)}})();THREE.FrontSide=0;THREE.BackSide=1;THREE.DoubleSide=2;THREE.NoShading=0;THREE.FlatShading=1;THREE.SmoothShading=2;THREE.NoColors=0;THREE.FaceColors=1;THREE.VertexColors=2;THREE.NoBlending=0;THREE.NormalBlending=1;THREE.AdditiveBlending=2;THREE.SubtractiveBlending=3;THREE.MultiplyBlending=4;THREE.CustomBlending=5;THREE.AddEquation=100;THREE.SubtractEquation=101;THREE.ReverseSubtractEquation=102;THREE.ZeroFactor=200;THREE.OneFactor=201;THREE.SrcColorFactor=202;
+THREE.OneMinusSrcColorFactor=203;THREE.SrcAlphaFactor=204;THREE.OneMinusSrcAlphaFactor=205;THREE.DstAlphaFactor=206;THREE.OneMinusDstAlphaFactor=207;THREE.DstColorFactor=208;THREE.OneMinusDstColorFactor=209;THREE.SrcAlphaSaturateFactor=210;THREE.MultiplyOperation=0;THREE.MixOperation=1;THREE.AddOperation=2;THREE.UVMapping=function(){};THREE.CubeReflectionMapping=function(){};THREE.CubeRefractionMapping=function(){};THREE.SphericalReflectionMapping=function(){};THREE.SphericalRefractionMapping=function(){};
+THREE.RepeatWrapping=1E3;THREE.ClampToEdgeWrapping=1001;THREE.MirroredRepeatWrapping=1002;THREE.NearestFilter=1003;THREE.NearestMipMapNearestFilter=1004;THREE.NearestMipMapLinearFilter=1005;THREE.LinearFilter=1006;THREE.LinearMipMapNearestFilter=1007;THREE.LinearMipMapLinearFilter=1008;THREE.UnsignedByteType=1009;THREE.ByteType=1010;THREE.ShortType=1011;THREE.UnsignedShortType=1012;THREE.IntType=1013;THREE.UnsignedIntType=1014;THREE.FloatType=1015;THREE.UnsignedShort4444Type=1016;
+THREE.UnsignedShort5551Type=1017;THREE.UnsignedShort565Type=1018;THREE.AlphaFormat=1019;THREE.RGBFormat=1020;THREE.RGBAFormat=1021;THREE.LuminanceFormat=1022;THREE.LuminanceAlphaFormat=1023;THREE.RGB_S3TC_DXT1_Format=2001;THREE.RGBA_S3TC_DXT1_Format=2002;THREE.RGBA_S3TC_DXT3_Format=2003;THREE.RGBA_S3TC_DXT5_Format=2004;THREE.Clock=function(a){this.autoStart=void 0!==a?a:!0;this.elapsedTime=this.oldTime=this.startTime=0;this.running=!1};
+THREE.Clock.prototype.start=function(){this.oldTime=this.startTime=Date.now();this.running=!0};THREE.Clock.prototype.stop=function(){this.getElapsedTime();this.running=!1};THREE.Clock.prototype.getElapsedTime=function(){return this.elapsedTime+=this.getDelta()};THREE.Clock.prototype.getDelta=function(){var a=0;this.autoStart&&!this.running&&this.start();if(this.running){var b=Date.now(),a=0.001*(b-this.oldTime);this.oldTime=b;this.elapsedTime+=a}return a};
+THREE.Color=function(a){void 0!==a&&this.setHex(a);return this};
+THREE.Color.prototype={constructor:THREE.Color,r:1,g:1,b:1,copy:function(a){this.r=a.r;this.g=a.g;this.b=a.b;return this},copyGammaToLinear:function(a){this.r=a.r*a.r;this.g=a.g*a.g;this.b=a.b*a.b;return this},copyLinearToGamma:function(a){this.r=Math.sqrt(a.r);this.g=Math.sqrt(a.g);this.b=Math.sqrt(a.b);return this},convertGammaToLinear:function(){var a=this.r,b=this.g,c=this.b;this.r=a*a;this.g=b*b;this.b=c*c;return this},convertLinearToGamma:function(){this.r=Math.sqrt(this.r);this.g=Math.sqrt(this.g);
+this.b=Math.sqrt(this.b);return this},setRGB:function(a,b,c){this.r=a;this.g=b;this.b=c;return this},setHSV:function(a,b,c){var d,e,f;0===c?this.r=this.g=this.b=0:(d=Math.floor(6*a),e=6*a-d,a=c*(1-b),f=c*(1-b*e),b=c*(1-b*(1-e)),0===d?(this.r=c,this.g=b,this.b=a):1===d?(this.r=f,this.g=c,this.b=a):2===d?(this.r=a,this.g=c,this.b=b):3===d?(this.r=a,this.g=f,this.b=c):4===d?(this.r=b,this.g=a,this.b=c):5===d&&(this.r=c,this.g=a,this.b=f));return this},getHex:function(){return 255*this.r<<16^255*this.g<<
+8^255*this.b<<0},setHex:function(a){a=Math.floor(a);this.r=(a>>16&255)/255;this.g=(a>>8&255)/255;this.b=(a&255)/255;return this},getHexString:function(){return("000000"+this.getHex().toString(16)).slice(-6)},getContextStyle:function(){return"rgb("+(255*this.r|0)+","+(255*this.g|0)+","+(255*this.b|0)+")"},setContextStyle:function(a){a=/^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/i.exec(a);this.r=parseInt(a[1],10)/255;this.g=parseInt(a[2],10)/255;this.b=parseInt(a[3],10)/255;return this},getHSV:function(a){var b=
+this.r,c=this.g,d=this.b,e=Math.max(Math.max(b,c),d),f=Math.min(Math.min(b,c),d);if(f===e)f=b=0;else{var g=e-f,f=g/e,b=(b===e?(c-d)/g:c===e?2+(d-b)/g:4+(b-c)/g)/6;0>b&&(b+=1);1<b&&(b-=1)}void 0===a&&(a={h:0,s:0,v:0});a.h=b;a.s=f;a.v=e;return a},lerpSelf:function(a,b){this.r+=(a.r-this.r)*b;this.g+=(a.g-this.g)*b;this.b+=(a.b-this.b)*b;return this},clone:function(){return(new THREE.Color).setRGB(this.r,this.g,this.b)}};THREE.Vector2=function(a,b){this.x=a||0;this.y=b||0};
+THREE.Vector2.prototype={constructor:THREE.Vector2,set:function(a,b){this.x=a;this.y=b;return this},copy:function(a){this.x=a.x;this.y=a.y;return this},add:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;return this},addSelf:function(a){this.x+=a.x;this.y+=a.y;return this},sub:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;return this},subSelf:function(a){this.x-=a.x;this.y-=a.y;return this},multiplyScalar:function(a){this.x*=a;this.y*=a;return this},divideScalar:function(a){a?(this.x/=a,this.y/=a):this.set(0,
+0);return this},negate:function(){return this.multiplyScalar(-1)},dot:function(a){return this.x*a.x+this.y*a.y},lengthSq:function(){return this.x*this.x+this.y*this.y},length:function(){return Math.sqrt(this.lengthSq())},normalize:function(){return this.divideScalar(this.length())},distanceTo:function(a){return Math.sqrt(this.distanceToSquared(a))},distanceToSquared:function(a){var b=this.x-a.x,a=this.y-a.y;return b*b+a*a},setLength:function(a){return this.normalize().multiplyScalar(a)},lerpSelf:function(a,
+b){this.x+=(a.x-this.x)*b;this.y+=(a.y-this.y)*b;return this},equals:function(a){return a.x===this.x&&a.y===this.y},clone:function(){return new THREE.Vector2(this.x,this.y)}};THREE.Vector3=function(a,b,c){this.x=a||0;this.y=b||0;this.z=c||0};
+THREE.Vector3.prototype={constructor:THREE.Vector3,set:function(a,b,c){this.x=a;this.y=b;this.z=c;return this},setX:function(a){this.x=a;return this},setY:function(a){this.y=a;return this},setZ:function(a){this.z=a;return this},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;return this},add:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;this.z=a.z+b.z;return this},addSelf:function(a){this.x+=a.x;this.y+=a.y;this.z+=a.z;return this},addScalar:function(a){this.x+=a;this.y+=a;this.z+=a;return this},
+sub:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;this.z=a.z-b.z;return this},subSelf:function(a){this.x-=a.x;this.y-=a.y;this.z-=a.z;return this},multiply:function(a,b){this.x=a.x*b.x;this.y=a.y*b.y;this.z=a.z*b.z;return this},multiplySelf:function(a){this.x*=a.x;this.y*=a.y;this.z*=a.z;return this},multiplyScalar:function(a){this.x*=a;this.y*=a;this.z*=a;return this},divideSelf:function(a){this.x/=a.x;this.y/=a.y;this.z/=a.z;return this},divideScalar:function(a){a?(this.x/=a,this.y/=a,this.z/=a):
+this.z=this.y=this.x=0;return this},negate:function(){return this.multiplyScalar(-1)},dot:function(a){return this.x*a.x+this.y*a.y+this.z*a.z},lengthSq:function(){return this.x*this.x+this.y*this.y+this.z*this.z},length:function(){return Math.sqrt(this.lengthSq())},lengthManhattan:function(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)},normalize:function(){return this.divideScalar(this.length())},setLength:function(a){return this.normalize().multiplyScalar(a)},lerpSelf:function(a,b){this.x+=
+(a.x-this.x)*b;this.y+=(a.y-this.y)*b;this.z+=(a.z-this.z)*b;return this},cross:function(a,b){this.x=a.y*b.z-a.z*b.y;this.y=a.z*b.x-a.x*b.z;this.z=a.x*b.y-a.y*b.x;return this},crossSelf:function(a){var b=this.x,c=this.y,d=this.z;this.x=c*a.z-d*a.y;this.y=d*a.x-b*a.z;this.z=b*a.y-c*a.x;return this},angleTo:function(a){return Math.acos(this.dot(a)/this.length()/a.length())},distanceTo:function(a){return Math.sqrt(this.distanceToSquared(a))},distanceToSquared:function(a){return(new THREE.Vector3).sub(this,
+a).lengthSq()},getPositionFromMatrix:function(a){this.x=a.elements[12];this.y=a.elements[13];this.z=a.elements[14];return this},setEulerFromRotationMatrix:function(a,b){function c(a){return Math.min(Math.max(a,-1),1)}var d=a.elements,e=d[0],f=d[4],g=d[8],h=d[1],i=d[5],j=d[9],l=d[2],m=d[6],d=d[10];void 0===b||"XYZ"===b?(this.y=Math.asin(c(g)),0.99999>Math.abs(g)?(this.x=Math.atan2(-j,d),this.z=Math.atan2(-f,e)):(this.x=Math.atan2(m,i),this.z=0)):"YXZ"===b?(this.x=Math.asin(-c(j)),0.99999>Math.abs(j)?
+(this.y=Math.atan2(g,d),this.z=Math.atan2(h,i)):(this.y=Math.atan2(-l,e),this.z=0)):"ZXY"===b?(this.x=Math.asin(c(m)),0.99999>Math.abs(m)?(this.y=Math.atan2(-l,d),this.z=Math.atan2(-f,i)):(this.y=0,this.z=Math.atan2(h,e))):"ZYX"===b?(this.y=Math.asin(-c(l)),0.99999>Math.abs(l)?(this.x=Math.atan2(m,d),this.z=Math.atan2(h,e)):(this.x=0,this.z=Math.atan2(-f,i))):"YZX"===b?(this.z=Math.asin(c(h)),0.99999>Math.abs(h)?(this.x=Math.atan2(-j,i),this.y=Math.atan2(-l,e)):(this.x=0,this.y=Math.atan2(g,d))):
+"XZY"===b&&(this.z=Math.asin(-c(f)),0.99999>Math.abs(f)?(this.x=Math.atan2(m,i),this.y=Math.atan2(g,e)):(this.x=Math.atan2(-j,d),this.y=0));return this},setEulerFromQuaternion:function(a,b){function c(a){return Math.min(Math.max(a,-1),1)}var d=a.x*a.x,e=a.y*a.y,f=a.z*a.z,g=a.w*a.w;void 0===b||"XYZ"===b?(this.x=Math.atan2(2*(a.x*a.w-a.y*a.z),g-d-e+f),this.y=Math.asin(c(2*(a.x*a.z+a.y*a.w))),this.z=Math.atan2(2*(a.z*a.w-a.x*a.y),g+d-e-f)):"YXZ"===b?(this.x=Math.asin(c(2*(a.x*a.w-a.y*a.z))),this.y=Math.atan2(2*
+(a.x*a.z+a.y*a.w),g-d-e+f),this.z=Math.atan2(2*(a.x*a.y+a.z*a.w),g-d+e-f)):"ZXY"===b?(this.x=Math.asin(c(2*(a.x*a.w+a.y*a.z))),this.y=Math.atan2(2*(a.y*a.w-a.z*a.x),g-d-e+f),this.z=Math.atan2(2*(a.z*a.w-a.x*a.y),g-d+e-f)):"ZYX"===b?(this.x=Math.atan2(2*(a.x*a.w+a.z*a.y),g-d-e+f),this.y=Math.asin(c(2*(a.y*a.w-a.x*a.z))),this.z=Math.atan2(2*(a.x*a.y+a.z*a.w),g+d-e-f)):"YZX"===b?(this.x=Math.atan2(2*(a.x*a.w-a.z*a.y),g-d+e-f),this.y=Math.atan2(2*(a.y*a.w-a.x*a.z),g+d-e-f),this.z=Math.asin(c(2*(a.x*a.y+
+a.z*a.w)))):"XZY"===b&&(this.x=Math.atan2(2*(a.x*a.w+a.y*a.z),g-d+e-f),this.y=Math.atan2(2*(a.x*a.z+a.y*a.w),g+d-e-f),this.z=Math.asin(c(2*(a.z*a.w-a.x*a.y))));return this},getScaleFromMatrix:function(a){var b=this.set(a.elements[0],a.elements[1],a.elements[2]).length(),c=this.set(a.elements[4],a.elements[5],a.elements[6]).length(),a=this.set(a.elements[8],a.elements[9],a.elements[10]).length();this.x=b;this.y=c;this.z=a;return this},equals:function(a){return a.x===this.x&&a.y===this.y&&a.z===this.z},
+clone:function(){return new THREE.Vector3(this.x,this.y,this.z)}};THREE.Vector4=function(a,b,c,d){this.x=a||0;this.y=b||0;this.z=c||0;this.w=void 0!==d?d:1};
+THREE.Vector4.prototype={constructor:THREE.Vector4,set:function(a,b,c,d){this.x=a;this.y=b;this.z=c;this.w=d;return this},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;this.w=void 0!==a.w?a.w:1;return this},add:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;this.z=a.z+b.z;this.w=a.w+b.w;return this},addSelf:function(a){this.x+=a.x;this.y+=a.y;this.z+=a.z;this.w+=a.w;return this},sub:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;this.z=a.z-b.z;this.w=a.w-b.w;return this},subSelf:function(a){this.x-=
+a.x;this.y-=a.y;this.z-=a.z;this.w-=a.w;return this},multiplyScalar:function(a){this.x*=a;this.y*=a;this.z*=a;this.w*=a;return this},divideScalar:function(a){a?(this.x/=a,this.y/=a,this.z/=a,this.w/=a):(this.z=this.y=this.x=0,this.w=1);return this},negate:function(){return this.multiplyScalar(-1)},dot:function(a){return this.x*a.x+this.y*a.y+this.z*a.z+this.w*a.w},lengthSq:function(){return this.dot(this)},length:function(){return Math.sqrt(this.lengthSq())},lengthManhattan:function(){return Math.abs(this.x)+
+Math.abs(this.y)+Math.abs(this.z)+Math.abs(this.w)},normalize:function(){return this.divideScalar(this.length())},setLength:function(a){return this.normalize().multiplyScalar(a)},lerpSelf:function(a,b){this.x+=(a.x-this.x)*b;this.y+=(a.y-this.y)*b;this.z+=(a.z-this.z)*b;this.w+=(a.w-this.w)*b;return this},clone:function(){return new THREE.Vector4(this.x,this.y,this.z,this.w)},setAxisAngleFromQuaternion:function(a){this.w=2*Math.acos(a.w);var b=Math.sqrt(1-a.w*a.w);1E-4>b?(this.x=1,this.z=this.y=0):
+(this.x=a.x/b,this.y=a.y/b,this.z=a.z/b);return this},setAxisAngleFromRotationMatrix:function(a){var b,c,d,a=a.elements,e=a[0];d=a[4];var f=a[8],g=a[1],h=a[5],i=a[9];c=a[2];b=a[6];var j=a[10];if(0.01>Math.abs(d-g)&&0.01>Math.abs(f-c)&&0.01>Math.abs(i-b)){if(0.1>Math.abs(d+g)&&0.1>Math.abs(f+c)&&0.1>Math.abs(i+b)&&0.1>Math.abs(e+h+j-3))return this.set(1,0,0,0),this;a=Math.PI;e=(e+1)/2;h=(h+1)/2;j=(j+1)/2;d=(d+g)/4;f=(f+c)/4;i=(i+b)/4;e>h&&e>j?0.01>e?(b=0,d=c=0.707106781):(b=Math.sqrt(e),c=d/b,d=f/
+b):h>j?0.01>h?(b=0.707106781,c=0,d=0.707106781):(c=Math.sqrt(h),b=d/c,d=i/c):0.01>j?(c=b=0.707106781,d=0):(d=Math.sqrt(j),b=f/d,c=i/d);this.set(b,c,d,a);return this}a=Math.sqrt((b-i)*(b-i)+(f-c)*(f-c)+(g-d)*(g-d));0.001>Math.abs(a)&&(a=1);this.x=(b-i)/a;this.y=(f-c)/a;this.z=(g-d)/a;this.w=Math.acos((e+h+j-1)/2);return this}};THREE.Matrix3=function(){this.elements=new Float32Array(9)};
+THREE.Matrix3.prototype={constructor:THREE.Matrix3,multiplyVector3:function(a){var b=this.elements,c=a.x,d=a.y,e=a.z;a.x=b[0]*c+b[3]*d+b[6]*e;a.y=b[1]*c+b[4]*d+b[7]*e;a.z=b[2]*c+b[5]*d+b[8]*e;return a},multiplyVector3Array:function(a){for(var b=THREE.Matrix3.__v1,c=0,d=a.length;c<d;c+=3)b.x=a[c],b.y=a[c+1],b.z=a[c+2],this.multiplyVector3(b),a[c]=b.x,a[c+1]=b.y,a[c+2]=b.z;return a},getInverse:function(a){var b=a.elements,a=b[10]*b[5]-b[6]*b[9],c=-b[10]*b[1]+b[2]*b[9],d=b[6]*b[1]-b[2]*b[5],e=-b[10]*
+b[4]+b[6]*b[8],f=b[10]*b[0]-b[2]*b[8],g=-b[6]*b[0]+b[2]*b[4],h=b[9]*b[4]-b[5]*b[8],i=-b[9]*b[0]+b[1]*b[8],j=b[5]*b[0]-b[1]*b[4],b=b[0]*a+b[1]*e+b[2]*h;0===b&&console.warn("Matrix3.getInverse(): determinant == 0");var b=1/b,l=this.elements;l[0]=b*a;l[1]=b*c;l[2]=b*d;l[3]=b*e;l[4]=b*f;l[5]=b*g;l[6]=b*h;l[7]=b*i;l[8]=b*j;return this},transpose:function(){var a,b=this.elements;a=b[1];b[1]=b[3];b[3]=a;a=b[2];b[2]=b[6];b[6]=a;a=b[5];b[5]=b[7];b[7]=a;return this},transposeIntoArray:function(a){var b=this.m;
+a[0]=b[0];a[1]=b[3];a[2]=b[6];a[3]=b[1];a[4]=b[4];a[5]=b[7];a[6]=b[2];a[7]=b[5];a[8]=b[8];return this}};THREE.Matrix3.__v1=new THREE.Vector3;THREE.Matrix4=function(a,b,c,d,e,f,g,h,i,j,l,m,n,p,o,s){this.elements=new Float32Array(16);this.set(void 0!==a?a:1,b||0,c||0,d||0,e||0,void 0!==f?f:1,g||0,h||0,i||0,j||0,void 0!==l?l:1,m||0,n||0,p||0,o||0,void 0!==s?s:1)};
+THREE.Matrix4.prototype={constructor:THREE.Matrix4,set:function(a,b,c,d,e,f,g,h,i,j,l,m,n,p,o,s){var t=this.elements;t[0]=a;t[4]=b;t[8]=c;t[12]=d;t[1]=e;t[5]=f;t[9]=g;t[13]=h;t[2]=i;t[6]=j;t[10]=l;t[14]=m;t[3]=n;t[7]=p;t[11]=o;t[15]=s;return this},identity:function(){this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1);return this},copy:function(a){a=a.elements;this.set(a[0],a[4],a[8],a[12],a[1],a[5],a[9],a[13],a[2],a[6],a[10],a[14],a[3],a[7],a[11],a[15]);return this},lookAt:function(a,b,c){var d=this.elements,
+e=THREE.Matrix4.__v1,f=THREE.Matrix4.__v2,g=THREE.Matrix4.__v3;g.sub(a,b).normalize();0===g.length()&&(g.z=1);e.cross(c,g).normalize();0===e.length()&&(g.x+=1E-4,e.cross(c,g).normalize());f.cross(g,e);d[0]=e.x;d[4]=f.x;d[8]=g.x;d[1]=e.y;d[5]=f.y;d[9]=g.y;d[2]=e.z;d[6]=f.z;d[10]=g.z;return this},multiply:function(a,b){var c=a.elements,d=b.elements,e=this.elements,f=c[0],g=c[4],h=c[8],i=c[12],j=c[1],l=c[5],m=c[9],n=c[13],p=c[2],o=c[6],s=c[10],t=c[14],r=c[3],z=c[7],w=c[11],c=c[15],q=d[0],E=d[4],A=d[8],
+v=d[12],u=d[1],D=d[5],C=d[9],G=d[13],P=d[2],B=d[6],K=d[10],H=d[14],I=d[3],N=d[7],O=d[11],d=d[15];e[0]=f*q+g*u+h*P+i*I;e[4]=f*E+g*D+h*B+i*N;e[8]=f*A+g*C+h*K+i*O;e[12]=f*v+g*G+h*H+i*d;e[1]=j*q+l*u+m*P+n*I;e[5]=j*E+l*D+m*B+n*N;e[9]=j*A+l*C+m*K+n*O;e[13]=j*v+l*G+m*H+n*d;e[2]=p*q+o*u+s*P+t*I;e[6]=p*E+o*D+s*B+t*N;e[10]=p*A+o*C+s*K+t*O;e[14]=p*v+o*G+s*H+t*d;e[3]=r*q+z*u+w*P+c*I;e[7]=r*E+z*D+w*B+c*N;e[11]=r*A+z*C+w*K+c*O;e[15]=r*v+z*G+w*H+c*d;return this},multiplySelf:function(a){return this.multiply(this,
+a)},multiplyToArray:function(a,b,c){var d=this.elements;this.multiply(a,b);c[0]=d[0];c[1]=d[1];c[2]=d[2];c[3]=d[3];c[4]=d[4];c[5]=d[5];c[6]=d[6];c[7]=d[7];c[8]=d[8];c[9]=d[9];c[10]=d[10];c[11]=d[11];c[12]=d[12];c[13]=d[13];c[14]=d[14];c[15]=d[15];return this},multiplyScalar:function(a){var b=this.elements;b[0]*=a;b[4]*=a;b[8]*=a;b[12]*=a;b[1]*=a;b[5]*=a;b[9]*=a;b[13]*=a;b[2]*=a;b[6]*=a;b[10]*=a;b[14]*=a;b[3]*=a;b[7]*=a;b[11]*=a;b[15]*=a;return this},multiplyVector3:function(a){var b=this.elements,
+c=a.x,d=a.y,e=a.z,f=1/(b[3]*c+b[7]*d+b[11]*e+b[15]);a.x=(b[0]*c+b[4]*d+b[8]*e+b[12])*f;a.y=(b[1]*c+b[5]*d+b[9]*e+b[13])*f;a.z=(b[2]*c+b[6]*d+b[10]*e+b[14])*f;return a},multiplyVector4:function(a){var b=this.elements,c=a.x,d=a.y,e=a.z,f=a.w;a.x=b[0]*c+b[4]*d+b[8]*e+b[12]*f;a.y=b[1]*c+b[5]*d+b[9]*e+b[13]*f;a.z=b[2]*c+b[6]*d+b[10]*e+b[14]*f;a.w=b[3]*c+b[7]*d+b[11]*e+b[15]*f;return a},multiplyVector3Array:function(a){for(var b=THREE.Matrix4.__v1,c=0,d=a.length;c<d;c+=3)b.x=a[c],b.y=a[c+1],b.z=a[c+2],
+this.multiplyVector3(b),a[c]=b.x,a[c+1]=b.y,a[c+2]=b.z;return a},rotateAxis:function(a){var b=this.elements,c=a.x,d=a.y,e=a.z;a.x=c*b[0]+d*b[4]+e*b[8];a.y=c*b[1]+d*b[5]+e*b[9];a.z=c*b[2]+d*b[6]+e*b[10];a.normalize();return a},crossVector:function(a){var b=this.elements,c=new THREE.Vector4;c.x=b[0]*a.x+b[4]*a.y+b[8]*a.z+b[12]*a.w;c.y=b[1]*a.x+b[5]*a.y+b[9]*a.z+b[13]*a.w;c.z=b[2]*a.x+b[6]*a.y+b[10]*a.z+b[14]*a.w;c.w=a.w?b[3]*a.x+b[7]*a.y+b[11]*a.z+b[15]*a.w:1;return c},determinant:function(){var a=
+this.elements,b=a[0],c=a[4],d=a[8],e=a[12],f=a[1],g=a[5],h=a[9],i=a[13],j=a[2],l=a[6],m=a[10],n=a[14],p=a[3],o=a[7],s=a[11],a=a[15];return e*h*l*p-d*i*l*p-e*g*m*p+c*i*m*p+d*g*n*p-c*h*n*p-e*h*j*o+d*i*j*o+e*f*m*o-b*i*m*o-d*f*n*o+b*h*n*o+e*g*j*s-c*i*j*s-e*f*l*s+b*i*l*s+c*f*n*s-b*g*n*s-d*g*j*a+c*h*j*a+d*f*l*a-b*h*l*a-c*f*m*a+b*g*m*a},transpose:function(){var a=this.elements,b;b=a[1];a[1]=a[4];a[4]=b;b=a[2];a[2]=a[8];a[8]=b;b=a[6];a[6]=a[9];a[9]=b;b=a[3];a[3]=a[12];a[12]=b;b=a[7];a[7]=a[13];a[13]=b;b=
+a[11];a[11]=a[14];a[14]=b;return this},flattenToArray:function(a){var b=this.elements;a[0]=b[0];a[1]=b[1];a[2]=b[2];a[3]=b[3];a[4]=b[4];a[5]=b[5];a[6]=b[6];a[7]=b[7];a[8]=b[8];a[9]=b[9];a[10]=b[10];a[11]=b[11];a[12]=b[12];a[13]=b[13];a[14]=b[14];a[15]=b[15];return a},flattenToArrayOffset:function(a,b){var c=this.elements;a[b]=c[0];a[b+1]=c[1];a[b+2]=c[2];a[b+3]=c[3];a[b+4]=c[4];a[b+5]=c[5];a[b+6]=c[6];a[b+7]=c[7];a[b+8]=c[8];a[b+9]=c[9];a[b+10]=c[10];a[b+11]=c[11];a[b+12]=c[12];a[b+13]=c[13];a[b+
+14]=c[14];a[b+15]=c[15];return a},getPosition:function(){var a=this.elements;return THREE.Matrix4.__v1.set(a[12],a[13],a[14])},setPosition:function(a){var b=this.elements;b[12]=a.x;b[13]=a.y;b[14]=a.z;return this},getColumnX:function(){var a=this.elements;return THREE.Matrix4.__v1.set(a[0],a[1],a[2])},getColumnY:function(){var a=this.elements;return THREE.Matrix4.__v1.set(a[4],a[5],a[6])},getColumnZ:function(){var a=this.elements;return THREE.Matrix4.__v1.set(a[8],a[9],a[10])},getInverse:function(a){var b=
+this.elements,c=a.elements,d=c[0],e=c[4],f=c[8],g=c[12],h=c[1],i=c[5],j=c[9],l=c[13],m=c[2],n=c[6],p=c[10],o=c[14],s=c[3],t=c[7],r=c[11],c=c[15];b[0]=j*o*t-l*p*t+l*n*r-i*o*r-j*n*c+i*p*c;b[4]=g*p*t-f*o*t-g*n*r+e*o*r+f*n*c-e*p*c;b[8]=f*l*t-g*j*t+g*i*r-e*l*r-f*i*c+e*j*c;b[12]=g*j*n-f*l*n-g*i*p+e*l*p+f*i*o-e*j*o;b[1]=l*p*s-j*o*s-l*m*r+h*o*r+j*m*c-h*p*c;b[5]=f*o*s-g*p*s+g*m*r-d*o*r-f*m*c+d*p*c;b[9]=g*j*s-f*l*s-g*h*r+d*l*r+f*h*c-d*j*c;b[13]=f*l*m-g*j*m+g*h*p-d*l*p-f*h*o+d*j*o;b[2]=i*o*s-l*n*s+l*m*t-h*o*
+t-i*m*c+h*n*c;b[6]=g*n*s-e*o*s-g*m*t+d*o*t+e*m*c-d*n*c;b[10]=e*l*s-g*i*s+g*h*t-d*l*t-e*h*c+d*i*c;b[14]=g*i*m-e*l*m-g*h*n+d*l*n+e*h*o-d*i*o;b[3]=j*n*s-i*p*s-j*m*t+h*p*t+i*m*r-h*n*r;b[7]=e*p*s-f*n*s+f*m*t-d*p*t-e*m*r+d*n*r;b[11]=f*i*s-e*j*s-f*h*t+d*j*t+e*h*r-d*i*r;b[15]=e*j*m-f*i*m+f*h*n-d*j*n-e*h*p+d*i*p;this.multiplyScalar(1/a.determinant());return this},setRotationFromEuler:function(a,b){var c=this.elements,d=a.x,e=a.y,f=a.z,g=Math.cos(d),d=Math.sin(d),h=Math.cos(e),e=Math.sin(e),i=Math.cos(f),f=
+Math.sin(f);if(void 0===b||"XYZ"===b){var j=g*i,l=g*f,m=d*i,n=d*f;c[0]=h*i;c[4]=-h*f;c[8]=e;c[1]=l+m*e;c[5]=j-n*e;c[9]=-d*h;c[2]=n-j*e;c[6]=m+l*e;c[10]=g*h}else"YXZ"===b?(j=h*i,l=h*f,m=e*i,n=e*f,c[0]=j+n*d,c[4]=m*d-l,c[8]=g*e,c[1]=g*f,c[5]=g*i,c[9]=-d,c[2]=l*d-m,c[6]=n+j*d,c[10]=g*h):"ZXY"===b?(j=h*i,l=h*f,m=e*i,n=e*f,c[0]=j-n*d,c[4]=-g*f,c[8]=m+l*d,c[1]=l+m*d,c[5]=g*i,c[9]=n-j*d,c[2]=-g*e,c[6]=d,c[10]=g*h):"ZYX"===b?(j=g*i,l=g*f,m=d*i,n=d*f,c[0]=h*i,c[4]=m*e-l,c[8]=j*e+n,c[1]=h*f,c[5]=n*e+j,c[9]=
+l*e-m,c[2]=-e,c[6]=d*h,c[10]=g*h):"YZX"===b?(j=g*h,l=g*e,m=d*h,n=d*e,c[0]=h*i,c[4]=n-j*f,c[8]=m*f+l,c[1]=f,c[5]=g*i,c[9]=-d*i,c[2]=-e*i,c[6]=l*f+m,c[10]=j-n*f):"XZY"===b&&(j=g*h,l=g*e,m=d*h,n=d*e,c[0]=h*i,c[4]=-f,c[8]=e*i,c[1]=j*f+n,c[5]=g*i,c[9]=l*f-m,c[2]=m*f-l,c[6]=d*i,c[10]=n*f+j);return this},setRotationFromQuaternion:function(a){var b=this.elements,c=a.x,d=a.y,e=a.z,f=a.w,g=c+c,h=d+d,i=e+e,a=c*g,j=c*h,c=c*i,l=d*h,d=d*i,e=e*i,g=f*g,h=f*h,f=f*i;b[0]=1-(l+e);b[4]=j-f;b[8]=c+h;b[1]=j+f;b[5]=1-(a+
+e);b[9]=d-g;b[2]=c-h;b[6]=d+g;b[10]=1-(a+l);return this},compose:function(a,b,c){var d=this.elements,e=THREE.Matrix4.__m1,f=THREE.Matrix4.__m2;e.identity();e.setRotationFromQuaternion(b);f.makeScale(c.x,c.y,c.z);this.multiply(e,f);d[12]=a.x;d[13]=a.y;d[14]=a.z;return this},decompose:function(a,b,c){var d=this.elements,e=THREE.Matrix4.__v1,f=THREE.Matrix4.__v2,g=THREE.Matrix4.__v3;e.set(d[0],d[1],d[2]);f.set(d[4],d[5],d[6]);g.set(d[8],d[9],d[10]);a=a instanceof THREE.Vector3?a:new THREE.Vector3;b=
+b instanceof THREE.Quaternion?b:new THREE.Quaternion;c=c instanceof THREE.Vector3?c:new THREE.Vector3;c.x=e.length();c.y=f.length();c.z=g.length();a.x=d[12];a.y=d[13];a.z=d[14];d=THREE.Matrix4.__m1;d.copy(this);d.elements[0]/=c.x;d.elements[1]/=c.x;d.elements[2]/=c.x;d.elements[4]/=c.y;d.elements[5]/=c.y;d.elements[6]/=c.y;d.elements[8]/=c.z;d.elements[9]/=c.z;d.elements[10]/=c.z;b.setFromRotationMatrix(d);return[a,b,c]},extractPosition:function(a){var b=this.elements,a=a.elements;b[12]=a[12];b[13]=
+a[13];b[14]=a[14];return this},extractRotation:function(a){var b=this.elements,a=a.elements,c=THREE.Matrix4.__v1,d=1/c.set(a[0],a[1],a[2]).length(),e=1/c.set(a[4],a[5],a[6]).length(),c=1/c.set(a[8],a[9],a[10]).length();b[0]=a[0]*d;b[1]=a[1]*d;b[2]=a[2]*d;b[4]=a[4]*e;b[5]=a[5]*e;b[6]=a[6]*e;b[8]=a[8]*c;b[9]=a[9]*c;b[10]=a[10]*c;return this},translate:function(a){var b=this.elements,c=a.x,d=a.y,a=a.z;b[12]=b[0]*c+b[4]*d+b[8]*a+b[12];b[13]=b[1]*c+b[5]*d+b[9]*a+b[13];b[14]=b[2]*c+b[6]*d+b[10]*a+b[14];
+b[15]=b[3]*c+b[7]*d+b[11]*a+b[15];return this},rotateX:function(a){var b=this.elements,c=b[4],d=b[5],e=b[6],f=b[7],g=b[8],h=b[9],i=b[10],j=b[11],l=Math.cos(a),a=Math.sin(a);b[4]=l*c+a*g;b[5]=l*d+a*h;b[6]=l*e+a*i;b[7]=l*f+a*j;b[8]=l*g-a*c;b[9]=l*h-a*d;b[10]=l*i-a*e;b[11]=l*j-a*f;return this},rotateY:function(a){var b=this.elements,c=b[0],d=b[1],e=b[2],f=b[3],g=b[8],h=b[9],i=b[10],j=b[11],l=Math.cos(a),a=Math.sin(a);b[0]=l*c-a*g;b[1]=l*d-a*h;b[2]=l*e-a*i;b[3]=l*f-a*j;b[8]=l*g+a*c;b[9]=l*h+a*d;b[10]=
+l*i+a*e;b[11]=l*j+a*f;return this},rotateZ:function(a){var b=this.elements,c=b[0],d=b[1],e=b[2],f=b[3],g=b[4],h=b[5],i=b[6],j=b[7],l=Math.cos(a),a=Math.sin(a);b[0]=l*c+a*g;b[1]=l*d+a*h;b[2]=l*e+a*i;b[3]=l*f+a*j;b[4]=l*g-a*c;b[5]=l*h-a*d;b[6]=l*i-a*e;b[7]=l*j-a*f;return this},rotateByAxis:function(a,b){var c=this.elements;if(1===a.x&&0===a.y&&0===a.z)return this.rotateX(b);if(0===a.x&&1===a.y&&0===a.z)return this.rotateY(b);if(0===a.x&&0===a.y&&1===a.z)return this.rotateZ(b);var d=a.x,e=a.y,f=a.z,
+g=Math.sqrt(d*d+e*e+f*f),d=d/g,e=e/g,f=f/g,g=d*d,h=e*e,i=f*f,j=Math.cos(b),l=Math.sin(b),m=1-j,n=d*e*m,p=d*f*m,m=e*f*m,d=d*l,o=e*l,l=f*l,f=g+(1-g)*j,g=n+l,e=p-o,n=n-l,h=h+(1-h)*j,l=m+d,p=p+o,m=m-d,i=i+(1-i)*j,j=c[0],d=c[1],o=c[2],s=c[3],t=c[4],r=c[5],z=c[6],w=c[7],q=c[8],E=c[9],A=c[10],v=c[11];c[0]=f*j+g*t+e*q;c[1]=f*d+g*r+e*E;c[2]=f*o+g*z+e*A;c[3]=f*s+g*w+e*v;c[4]=n*j+h*t+l*q;c[5]=n*d+h*r+l*E;c[6]=n*o+h*z+l*A;c[7]=n*s+h*w+l*v;c[8]=p*j+m*t+i*q;c[9]=p*d+m*r+i*E;c[10]=p*o+m*z+i*A;c[11]=p*s+m*w+i*v;
+return this},scale:function(a){var b=this.elements,c=a.x,d=a.y,a=a.z;b[0]*=c;b[4]*=d;b[8]*=a;b[1]*=c;b[5]*=d;b[9]*=a;b[2]*=c;b[6]*=d;b[10]*=a;b[3]*=c;b[7]*=d;b[11]*=a;return this},getMaxScaleOnAxis:function(){var a=this.elements;return Math.sqrt(Math.max(a[0]*a[0]+a[1]*a[1]+a[2]*a[2],Math.max(a[4]*a[4]+a[5]*a[5]+a[6]*a[6],a[8]*a[8]+a[9]*a[9]+a[10]*a[10])))},makeTranslation:function(a,b,c){this.set(1,0,0,a,0,1,0,b,0,0,1,c,0,0,0,1);return this},makeRotationX:function(a){var b=Math.cos(a),a=Math.sin(a);
+this.set(1,0,0,0,0,b,-a,0,0,a,b,0,0,0,0,1);return this},makeRotationY:function(a){var b=Math.cos(a),a=Math.sin(a);this.set(b,0,a,0,0,1,0,0,-a,0,b,0,0,0,0,1);return this},makeRotationZ:function(a){var b=Math.cos(a),a=Math.sin(a);this.set(b,-a,0,0,a,b,0,0,0,0,1,0,0,0,0,1);return this},makeRotationAxis:function(a,b){var c=Math.cos(b),d=Math.sin(b),e=1-c,f=a.x,g=a.y,h=a.z,i=e*f,j=e*g;this.set(i*f+c,i*g-d*h,i*h+d*g,0,i*g+d*h,j*g+c,j*h-d*f,0,i*h-d*g,j*h+d*f,e*h*h+c,0,0,0,0,1);return this},makeScale:function(a,
+b,c){this.set(a,0,0,0,0,b,0,0,0,0,c,0,0,0,0,1);return this},makeFrustum:function(a,b,c,d,e,f){var g=this.elements;g[0]=2*e/(b-a);g[4]=0;g[8]=(b+a)/(b-a);g[12]=0;g[1]=0;g[5]=2*e/(d-c);g[9]=(d+c)/(d-c);g[13]=0;g[2]=0;g[6]=0;g[10]=-(f+e)/(f-e);g[14]=-2*f*e/(f-e);g[3]=0;g[7]=0;g[11]=-1;g[15]=0;return this},makePerspective:function(a,b,c,d){var a=c*Math.tan(a*Math.PI/360),e=-a;return this.makeFrustum(e*b,a*b,e,a,c,d)},makeOrthographic:function(a,b,c,d,e,f){var g=this.elements,h=b-a,i=c-d,j=f-e;g[0]=2/
+h;g[4]=0;g[8]=0;g[12]=-((b+a)/h);g[1]=0;g[5]=2/i;g[9]=0;g[13]=-((c+d)/i);g[2]=0;g[6]=0;g[10]=-2/j;g[14]=-((f+e)/j);g[3]=0;g[7]=0;g[11]=0;g[15]=1;return this},clone:function(){var a=this.elements;return new THREE.Matrix4(a[0],a[4],a[8],a[12],a[1],a[5],a[9],a[13],a[2],a[6],a[10],a[14],a[3],a[7],a[11],a[15])}};THREE.Matrix4.__v1=new THREE.Vector3;THREE.Matrix4.__v2=new THREE.Vector3;THREE.Matrix4.__v3=new THREE.Vector3;THREE.Matrix4.__m1=new THREE.Matrix4;THREE.Matrix4.__m2=new THREE.Matrix4;
+THREE.EventTarget=function(){var a={};this.addEventListener=function(b,c){void 0===a[b]&&(a[b]=[]);-1===a[b].indexOf(c)&&a[b].push(c)};this.dispatchEvent=function(b){for(var c in a[b.type])a[b.type][c](b)};this.removeEventListener=function(b,c){var d=a[b].indexOf(c);-1!==d&&a[b].splice(d,1)}};THREE.Frustum=function(){this.planes=[new THREE.Vector4,new THREE.Vector4,new THREE.Vector4,new THREE.Vector4,new THREE.Vector4,new THREE.Vector4]};
+THREE.Frustum.prototype.setFromMatrix=function(a){var b=this.planes,c=a.elements,a=c[0],d=c[1],e=c[2],f=c[3],g=c[4],h=c[5],i=c[6],j=c[7],l=c[8],m=c[9],n=c[10],p=c[11],o=c[12],s=c[13],t=c[14],c=c[15];b[0].set(f-a,j-g,p-l,c-o);b[1].set(f+a,j+g,p+l,c+o);b[2].set(f+d,j+h,p+m,c+s);b[3].set(f-d,j-h,p-m,c-s);b[4].set(f-e,j-i,p-n,c-t);b[5].set(f+e,j+i,p+n,c+t);for(d=0;6>d;d++)a=b[d],a.divideScalar(Math.sqrt(a.x*a.x+a.y*a.y+a.z*a.z))};
+THREE.Frustum.prototype.contains=function(a){for(var b=0,c=this.planes,b=a.matrixWorld,d=b.elements,a=-a.geometry.boundingSphere.radius*b.getMaxScaleOnAxis(),e=0;6>e;e++)if(b=c[e].x*d[12]+c[e].y*d[13]+c[e].z*d[14]+c[e].w,b<=a)return!1;return!0};THREE.Frustum.__v1=new THREE.Vector3;
+(function(a){a.Ray=function(b,c,d,e){this.origin=b||new a.Vector3;this.direction=c||new a.Vector3;this.near=d||0;this.far=e||Infinity};var b=new a.Vector3,c=new a.Vector3,d=new a.Vector3,e=new a.Vector3;new a.Vector3;var f=new a.Vector3,g=new a.Matrix4,h=function(a,b){return a.distance-b.distance},i=new a.Vector3,j=new a.Vector3,l=new a.Vector3,m=function(a,b,c){i.sub(c,a);var d=i.dot(b),a=j.add(a,l.copy(b).multiplyScalar(d));return c.distanceTo(a)},n=function(a,b,c,d){i.sub(d,b);j.sub(c,b);l.sub(a,
+b);var a=i.dot(i),b=i.dot(j),c=i.dot(l),e=j.dot(j),d=j.dot(l),f=1/(a*e-b*b),e=(e*c-b*d)*f,a=(a*d-b*c)*f;return 0<=e&&0<=a&&1>e+a},p=function(h,i,j){if(h instanceof a.Particle){var l=m(i.origin,i.direction,h.matrixWorld.getPosition());if(l>h.scale.x)return j;j.push({distance:l,point:h.position,face:null,object:h})}else if(h instanceof a.Mesh){var o=h.geometry.boundingSphere.radius*h.matrixWorld.getMaxScaleOnAxis(),l=m(i.origin,i.direction,h.matrixWorld.getPosition());if(l>o)return j;var o=h.geometry,
+p=o.vertices,E=h.material instanceof a.MeshFaceMaterial,A=!0===E?h.material.materials:null,l=h.material.side,v,u,D,C=i.precision;h.matrixRotationWorld.extractRotation(h.matrixWorld);b.copy(i.origin);g.getInverse(h.matrixWorld);c.copy(b);g.multiplyVector3(c);d.copy(i.direction);g.rotateAxis(d).normalize();for(var G=0,P=o.faces.length;G<P;G++){var B=o.faces[G],l=!0===E?A[B.materialIndex]:h.material;if(void 0!==l&&(l=l.side,e.sub(B.centroid,c),u=B.normal,v=d.dot(u),!(Math.abs(v)<C)&&(u=u.dot(e)/v,!(0>
+u)&&(l===a.DoubleSide||(l===a.FrontSide?0>v:0<v)))))if(f.add(c,d.multiplyScalar(u)),B instanceof a.Face3)l=p[B.a],v=p[B.b],u=p[B.c],n(f,l,v,u)&&(v=h.matrixWorld.multiplyVector3(f.clone()),l=b.distanceTo(v),l<i.near||l>i.far||j.push({distance:l,point:v,face:B,faceIndex:G,object:h}));else if(B instanceof a.Face4&&(l=p[B.a],v=p[B.b],u=p[B.c],D=p[B.d],n(f,l,v,D)||n(f,v,u,D)))v=h.matrixWorld.multiplyVector3(f.clone()),l=b.distanceTo(v),l<i.near||l>i.far||j.push({distance:l,point:v,face:B,faceIndex:G,object:h})}}},
+o=function(a,b,c){for(var a=a.getDescendants(),d=0,e=a.length;d<e;d++)p(a[d],b,c)};a.Ray.prototype.precision=1E-4;a.Ray.prototype.set=function(a,b){this.origin=a;this.direction=b};a.Ray.prototype.intersectObject=function(a,b){var c=[];!0===b&&o(a,this,c);p(a,this,c);c.sort(h);return c};a.Ray.prototype.intersectObjects=function(a,b){for(var c=[],d=0,e=a.length;d<e;d++)p(a[d],this,c),!0===b&&o(a[d],this,c);c.sort(h);return c}})(THREE);
+THREE.Rectangle=function(){function a(){f=d-b;g=e-c}var b=0,c=0,d=0,e=0,f=0,g=0,h=!0;this.getX=function(){return b};this.getY=function(){return c};this.getWidth=function(){return f};this.getHeight=function(){return g};this.getLeft=function(){return b};this.getTop=function(){return c};this.getRight=function(){return d};this.getBottom=function(){return e};this.set=function(f,g,l,m){h=!1;b=f;c=g;d=l;e=m;a()};this.addPoint=function(f,g){!0===h?(h=!1,b=f,c=g,d=f,e=g):(b=b<f?b:f,c=c<g?c:g,d=d>f?d:f,e=e>
+g?e:g);a()};this.add3Points=function(f,g,l,m,n,p){!0===h?(h=!1,b=f<l?f<n?f:n:l<n?l:n,c=g<m?g<p?g:p:m<p?m:p,d=f>l?f>n?f:n:l>n?l:n,e=g>m?g>p?g:p:m>p?m:p):(b=f<l?f<n?f<b?f:b:n<b?n:b:l<n?l<b?l:b:n<b?n:b,c=g<m?g<p?g<c?g:c:p<c?p:c:m<p?m<c?m:c:p<c?p:c,d=f>l?f>n?f>d?f:d:n>d?n:d:l>n?l>d?l:d:n>d?n:d,e=g>m?g>p?g>e?g:e:p>e?p:e:m>p?m>e?m:e:p>e?p:e);a()};this.addRectangle=function(f){!0===h?(h=!1,b=f.getLeft(),c=f.getTop(),d=f.getRight(),e=f.getBottom()):(b=b<f.getLeft()?b:f.getLeft(),c=c<f.getTop()?c:f.getTop(),
+d=d>f.getRight()?d:f.getRight(),e=e>f.getBottom()?e:f.getBottom());a()};this.inflate=function(f){b-=f;c-=f;d+=f;e+=f;a()};this.minSelf=function(f){b=b>f.getLeft()?b:f.getLeft();c=c>f.getTop()?c:f.getTop();d=d<f.getRight()?d:f.getRight();e=e<f.getBottom()?e:f.getBottom();a()};this.intersects=function(a){return d<a.getLeft()||b>a.getRight()||e<a.getTop()||c>a.getBottom()?!1:!0};this.empty=function(){h=!0;e=d=c=b=0;a()};this.isEmpty=function(){return h}};
+THREE.Math={clamp:function(a,b,c){return a<b?b:a>c?c:a},clampBottom:function(a,b){return a<b?b:a},mapLinear:function(a,b,c,d,e){return d+(a-b)*(e-d)/(c-b)},random16:function(){return(65280*Math.random()+255*Math.random())/65535},randInt:function(a,b){return a+Math.floor(Math.random()*(b-a+1))},randFloat:function(a,b){return a+Math.random()*(b-a)},randFloatSpread:function(a){return a*(0.5-Math.random())},sign:function(a){return 0>a?-1:0<a?1:0}};
+THREE.Object3D=function(){THREE.Object3DLibrary.push(this);this.id=THREE.Object3DIdCount++;this.name="";this.properties={};this.parent=void 0;this.children=[];this.up=new THREE.Vector3(0,1,0);this.position=new THREE.Vector3;this.rotation=new THREE.Vector3;this.eulerOrder=THREE.Object3D.defaultEulerOrder;this.scale=new THREE.Vector3(1,1,1);this.renderDepth=null;this.rotationAutoUpdate=!0;this.matrix=new THREE.Matrix4;this.matrixWorld=new THREE.Matrix4;this.matrixRotationWorld=new THREE.Matrix4;this.matrixWorldNeedsUpdate=
+this.matrixAutoUpdate=!0;this.quaternion=new THREE.Quaternion;this.useQuaternion=!1;this.boundRadius=0;this.boundRadiusScale=1;this.visible=!0;this.receiveShadow=this.castShadow=!1;this.frustumCulled=!0;this._vector=new THREE.Vector3};
+THREE.Object3D.prototype={constructor:THREE.Object3D,applyMatrix:function(a){this.matrix.multiply(a,this.matrix);this.scale.getScaleFromMatrix(this.matrix);a=(new THREE.Matrix4).extractRotation(this.matrix);this.rotation.setEulerFromRotationMatrix(a,this.eulerOrder);this.position.getPositionFromMatrix(this.matrix)},translate:function(a,b){this.matrix.rotateAxis(b);this.position.addSelf(b.multiplyScalar(a))},translateX:function(a){this.translate(a,this._vector.set(1,0,0))},translateY:function(a){this.translate(a,
+this._vector.set(0,1,0))},translateZ:function(a){this.translate(a,this._vector.set(0,0,1))},localToWorld:function(a){return this.matrixWorld.multiplyVector3(a)},worldToLocal:function(a){return THREE.Object3D.__m1.getInverse(this.matrixWorld).multiplyVector3(a)},lookAt:function(a){this.matrix.lookAt(a,this.position,this.up);this.rotationAutoUpdate&&(!1===this.useQuaternion?this.rotation.setEulerFromRotationMatrix(this.matrix,this.eulerOrder):this.quaternion.copy(this.matrix.decompose()[1]))},add:function(a){if(a===
+this)console.warn("THREE.Object3D.add: An object can't be added as a child of itself.");else if(a instanceof THREE.Object3D){void 0!==a.parent&&a.parent.remove(a);a.parent=this;this.children.push(a);for(var b=this;void 0!==b.parent;)b=b.parent;void 0!==b&&b instanceof THREE.Scene&&b.__addObject(a)}},remove:function(a){var b=this.children.indexOf(a);if(-1!==b){a.parent=void 0;this.children.splice(b,1);for(b=this;void 0!==b.parent;)b=b.parent;void 0!==b&&b instanceof THREE.Scene&&b.__removeObject(a)}},
+traverse:function(a){a(this);for(var b=0,c=this.children.length;b<c;b++)this.children[b].traverse(a)},getChildByName:function(a,b){for(var c=0,d=this.children.length;c<d;c++){var e=this.children[c];if(e.name===a||!0===b&&(e=e.getChildByName(a,b),void 0!==e))return e}},getDescendants:function(a){void 0===a&&(a=[]);Array.prototype.push.apply(a,this.children);for(var b=0,c=this.children.length;b<c;b++)this.children[b].getDescendants(a);return a},updateMatrix:function(){this.matrix.setPosition(this.position);
+!1===this.useQuaternion?this.matrix.setRotationFromEuler(this.rotation,this.eulerOrder):this.matrix.setRotationFromQuaternion(this.quaternion);if(1!==this.scale.x||1!==this.scale.y||1!==this.scale.z)this.matrix.scale(this.scale),this.boundRadiusScale=Math.max(this.scale.x,Math.max(this.scale.y,this.scale.z));this.matrixWorldNeedsUpdate=!0},updateMatrixWorld:function(a){!0===this.matrixAutoUpdate&&this.updateMatrix();if(!0===this.matrixWorldNeedsUpdate||!0===a)void 0===this.parent?this.matrixWorld.copy(this.matrix):
+this.matrixWorld.multiply(this.parent.matrixWorld,this.matrix),this.matrixWorldNeedsUpdate=!1,a=!0;for(var b=0,c=this.children.length;b<c;b++)this.children[b].updateMatrixWorld(a)},clone:function(a){void 0===a&&(a=new THREE.Object3D);a.name=this.name;a.up.copy(this.up);a.position.copy(this.position);a.rotation instanceof THREE.Vector3&&a.rotation.copy(this.rotation);a.eulerOrder=this.eulerOrder;a.scale.copy(this.scale);a.renderDepth=this.renderDepth;a.rotationAutoUpdate=this.rotationAutoUpdate;a.matrix.copy(this.matrix);
+a.matrixWorld.copy(this.matrixWorld);a.matrixRotationWorld.copy(this.matrixRotationWorld);a.matrixAutoUpdate=this.matrixAutoUpdate;a.matrixWorldNeedsUpdate=this.matrixWorldNeedsUpdate;a.quaternion.copy(this.quaternion);a.useQuaternion=this.useQuaternion;a.boundRadius=this.boundRadius;a.boundRadiusScale=this.boundRadiusScale;a.visible=this.visible;a.castShadow=this.castShadow;a.receiveShadow=this.receiveShadow;a.frustumCulled=this.frustumCulled;for(var b=0;b<this.children.length;b++)a.add(this.children[b].clone());
+return a},deallocate:function(){var a=THREE.Object3DLibrary.indexOf(this);-1!==a&&THREE.Object3DLibrary.splice(a,1)}};THREE.Object3D.__m1=new THREE.Matrix4;THREE.Object3D.defaultEulerOrder="XYZ";THREE.Object3DIdCount=0;THREE.Object3DLibrary=[];
+THREE.Projector=function(){function a(){if(f===h){var a=new THREE.RenderableObject;g.push(a);h++;f++;return a}return g[f++]}function b(){if(j===m){var a=new THREE.RenderableVertex;l.push(a);m++;j++;return a}return l[j++]}function c(a,b){return b.z-a.z}function d(a,b){var c=0,d=1,e=a.z+a.w,f=b.z+b.w,g=-a.z+a.w,h=-b.z+b.w;if(0<=e&&0<=f&&0<=g&&0<=h)return!0;if(0>e&&0>f||0>g&&0>h)return!1;0>e?c=Math.max(c,e/(e-f)):0>f&&(d=Math.min(d,e/(e-f)));0>g?c=Math.max(c,g/(g-h)):0>h&&(d=Math.min(d,g/(g-h)));if(d<
+c)return!1;a.lerpSelf(b,c);b.lerpSelf(a,1-d);return!0}var e,f,g=[],h=0,i,j,l=[],m=0,n,p,o=[],s=0,t,r=[],z=0,w,q,E=[],A=0,v,u,D=[],C=0,G={objects:[],sprites:[],lights:[],elements:[]},P=new THREE.Vector3,B=new THREE.Vector4,K=new THREE.Matrix4,H=new THREE.Matrix4,I=new THREE.Matrix3,N=new THREE.Frustum,O=new THREE.Vector4,R=new THREE.Vector4;this.projectVector=function(a,b){b.matrixWorldInverse.getInverse(b.matrixWorld);K.multiply(b.projectionMatrix,b.matrixWorldInverse);K.multiplyVector3(a);return a};
+this.unprojectVector=function(a,b){b.projectionMatrixInverse.getInverse(b.projectionMatrix);K.multiply(b.matrixWorld,b.projectionMatrixInverse);K.multiplyVector3(a);return a};this.pickingRay=function(a,b){var c;a.z=-1;c=new THREE.Vector3(a.x,a.y,1);this.unprojectVector(a,b);this.unprojectVector(c,b);c.subSelf(a).normalize();return new THREE.Ray(a,c)};this.projectScene=function(g,h,m,Q){var Z=h.near,L=h.far,oa=!1,X,fa,ca,Y,ba,aa,ia,Aa,Na,Ja,ma,sa,Ea,rb,ib;u=q=t=p=0;G.elements.length=0;g.updateMatrixWorld();
+void 0===h.parent&&h.updateMatrixWorld();h.matrixWorldInverse.getInverse(h.matrixWorld);K.multiply(h.projectionMatrix,h.matrixWorldInverse);N.setFromMatrix(K);f=0;G.objects.length=0;G.sprites.length=0;G.lights.length=0;var ob=function(b){for(var c=0,d=b.children.length;c<d;c++){var f=b.children[c];if(!1!==f.visible){if(f instanceof THREE.Light)G.lights.push(f);else if(f instanceof THREE.Mesh||f instanceof THREE.Line){if(!1===f.frustumCulled||!0===N.contains(f))e=a(),e.object=f,null!==f.renderDepth?
+e.z=f.renderDepth:(P.copy(f.matrixWorld.getPosition()),K.multiplyVector3(P),e.z=P.z),G.objects.push(e)}else f instanceof THREE.Sprite||f instanceof THREE.Particle?(e=a(),e.object=f,null!==f.renderDepth?e.z=f.renderDepth:(P.copy(f.matrixWorld.getPosition()),K.multiplyVector3(P),e.z=P.z),G.sprites.push(e)):(e=a(),e.object=f,null!==f.renderDepth?e.z=f.renderDepth:(P.copy(f.matrixWorld.getPosition()),K.multiplyVector3(P),e.z=P.z),G.objects.push(e));ob(f)}}};ob(g);!0===m&&G.objects.sort(c);g=0;for(m=G.objects.length;g<
+m;g++)if(Aa=G.objects[g].object,Na=Aa.matrixWorld,j=0,Aa instanceof THREE.Mesh){Ja=Aa.geometry;ca=Ja.vertices;ma=Ja.faces;Ja=Ja.faceVertexUvs;I.getInverse(Na);I.transpose();Ea=Aa.material instanceof THREE.MeshFaceMaterial;rb=!0===Ea?Aa.material:null;X=0;for(fa=ca.length;X<fa;X++)i=b(),i.positionWorld.copy(ca[X]),Na.multiplyVector3(i.positionWorld),i.positionScreen.copy(i.positionWorld),K.multiplyVector4(i.positionScreen),i.positionScreen.x/=i.positionScreen.w,i.positionScreen.y/=i.positionScreen.w,
+i.visible=i.positionScreen.z>Z&&i.positionScreen.z<L;ca=0;for(X=ma.length;ca<X;ca++)if(fa=ma[ca],ib=!0===Ea?rb.materials[fa.materialIndex]:Aa.material,void 0!==ib){aa=ib.side;if(fa instanceof THREE.Face3)if(Y=l[fa.a],ba=l[fa.b],ia=l[fa.c],!0===Y.visible&&!0===ba.visible&&!0===ia.visible)if(oa=0>(ia.positionScreen.x-Y.positionScreen.x)*(ba.positionScreen.y-Y.positionScreen.y)-(ia.positionScreen.y-Y.positionScreen.y)*(ba.positionScreen.x-Y.positionScreen.x),aa===THREE.DoubleSide||oa===(aa===THREE.FrontSide))p===
+s?(sa=new THREE.RenderableFace3,o.push(sa),s++,p++,n=sa):n=o[p++],n.v1.copy(Y),n.v2.copy(ba),n.v3.copy(ia);else continue;else continue;else if(fa instanceof THREE.Face4)if(Y=l[fa.a],ba=l[fa.b],ia=l[fa.c],sa=l[fa.d],!0===Y.visible&&!0===ba.visible&&!0===ia.visible&&!0===sa.visible)if(oa=0>(sa.positionScreen.x-Y.positionScreen.x)*(ba.positionScreen.y-Y.positionScreen.y)-(sa.positionScreen.y-Y.positionScreen.y)*(ba.positionScreen.x-Y.positionScreen.x)||0>(ba.positionScreen.x-ia.positionScreen.x)*(sa.positionScreen.y-
+ia.positionScreen.y)-(ba.positionScreen.y-ia.positionScreen.y)*(sa.positionScreen.x-ia.positionScreen.x),aa===THREE.DoubleSide||oa===(aa===THREE.FrontSide)){if(t===z){var jb=new THREE.RenderableFace4;r.push(jb);z++;t++;n=jb}else n=r[t++];n.v1.copy(Y);n.v2.copy(ba);n.v3.copy(ia);n.v4.copy(sa)}else continue;else continue;n.normalWorld.copy(fa.normal);!1===oa&&(aa===THREE.BackSide||aa===THREE.DoubleSide)&&n.normalWorld.negate();I.multiplyVector3(n.normalWorld).normalize();n.centroidWorld.copy(fa.centroid);
+Na.multiplyVector3(n.centroidWorld);n.centroidScreen.copy(n.centroidWorld);K.multiplyVector3(n.centroidScreen);ia=fa.vertexNormals;Y=0;for(ba=ia.length;Y<ba;Y++)sa=n.vertexNormalsWorld[Y],sa.copy(ia[Y]),!1===oa&&(aa===THREE.BackSide||aa===THREE.DoubleSide)&&sa.negate(),I.multiplyVector3(sa).normalize();n.vertexNormalsLength=ia.length;Y=0;for(ba=Ja.length;Y<ba;Y++)if(sa=Ja[Y][ca],void 0!==sa){aa=0;for(ia=sa.length;aa<ia;aa++)n.uvs[Y][aa]=sa[aa]}n.color=fa.color;n.material=ib;n.z=n.centroidScreen.z;
+G.elements.push(n)}}else if(Aa instanceof THREE.Line){H.multiply(K,Na);ca=Aa.geometry.vertices;Y=b();Y.positionScreen.copy(ca[0]);H.multiplyVector4(Y.positionScreen);Na=Aa.type===THREE.LinePieces?2:1;X=1;for(fa=ca.length;X<fa;X++)Y=b(),Y.positionScreen.copy(ca[X]),H.multiplyVector4(Y.positionScreen),0<(X+1)%Na||(ba=l[j-2],O.copy(Y.positionScreen),R.copy(ba.positionScreen),!0===d(O,R)&&(O.multiplyScalar(1/O.w),R.multiplyScalar(1/R.w),q===A?(ma=new THREE.RenderableLine,E.push(ma),A++,q++,w=ma):w=E[q++],
+w.v1.positionScreen.copy(O),w.v2.positionScreen.copy(R),w.z=Math.max(O.z,R.z),w.material=Aa.material,G.elements.push(w)))}g=0;for(m=G.sprites.length;g<m;g++)Aa=G.sprites[g].object,Na=Aa.matrixWorld,Aa instanceof THREE.Particle&&(B.set(Na.elements[12],Na.elements[13],Na.elements[14],1),K.multiplyVector4(B),B.z/=B.w,0<B.z&&1>B.z&&(u===C?(Z=new THREE.RenderableParticle,D.push(Z),C++,u++,v=Z):v=D[u++],v.object=Aa,v.x=B.x/B.w,v.y=B.y/B.w,v.z=B.z,v.rotation=Aa.rotation.z,v.scale.x=Aa.scale.x*Math.abs(v.x-
+(B.x+h.projectionMatrix.elements[0])/(B.w+h.projectionMatrix.elements[12])),v.scale.y=Aa.scale.y*Math.abs(v.y-(B.y+h.projectionMatrix.elements[5])/(B.w+h.projectionMatrix.elements[13])),v.material=Aa.material,G.elements.push(v)));!0===Q&&G.elements.sort(c);return G}};THREE.Quaternion=function(a,b,c,d){this.x=a||0;this.y=b||0;this.z=c||0;this.w=void 0!==d?d:1};
+THREE.Quaternion.prototype={constructor:THREE.Quaternion,set:function(a,b,c,d){this.x=a;this.y=b;this.z=c;this.w=d;return this},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;this.w=a.w;return this},setFromEuler:function(a,b){var c=Math.cos(a.x/2),d=Math.cos(a.y/2),e=Math.cos(a.z/2),f=Math.sin(a.x/2),g=Math.sin(a.y/2),h=Math.sin(a.z/2);void 0===b||"XYZ"===b?(this.x=f*d*e+c*g*h,this.y=c*g*e-f*d*h,this.z=c*d*h+f*g*e,this.w=c*d*e-f*g*h):"YXZ"===b?(this.x=f*d*e+c*g*h,this.y=c*g*e-f*d*h,this.z=c*d*
+h-f*g*e,this.w=c*d*e+f*g*h):"ZXY"===b?(this.x=f*d*e-c*g*h,this.y=c*g*e+f*d*h,this.z=c*d*h+f*g*e,this.w=c*d*e-f*g*h):"ZYX"===b?(this.x=f*d*e-c*g*h,this.y=c*g*e+f*d*h,this.z=c*d*h-f*g*e,this.w=c*d*e+f*g*h):"YZX"===b?(this.x=f*d*e+c*g*h,this.y=c*g*e+f*d*h,this.z=c*d*h-f*g*e,this.w=c*d*e-f*g*h):"XZY"===b&&(this.x=f*d*e-c*g*h,this.y=c*g*e-f*d*h,this.z=c*d*h+f*g*e,this.w=c*d*e+f*g*h);return this},setFromAxisAngle:function(a,b){var c=b/2,d=Math.sin(c);this.x=a.x*d;this.y=a.y*d;this.z=a.z*d;this.w=Math.cos(c);
+return this},setFromRotationMatrix:function(a){var b=a.elements,c=b[0],a=b[4],d=b[8],e=b[1],f=b[5],g=b[9],h=b[2],i=b[6],b=b[10],j=c+f+b;0<j?(c=0.5/Math.sqrt(j+1),this.w=0.25/c,this.x=(i-g)*c,this.y=(d-h)*c,this.z=(e-a)*c):c>f&&c>b?(c=2*Math.sqrt(1+c-f-b),this.w=(i-g)/c,this.x=0.25*c,this.y=(a+e)/c,this.z=(d+h)/c):f>b?(c=2*Math.sqrt(1+f-c-b),this.w=(d-h)/c,this.x=(a+e)/c,this.y=0.25*c,this.z=(g+i)/c):(c=2*Math.sqrt(1+b-c-f),this.w=(e-a)/c,this.x=(d+h)/c,this.y=(g+i)/c,this.z=0.25*c);return this},inverse:function(){this.conjugate().normalize();
+return this},conjugate:function(){this.x*=-1;this.y*=-1;this.z*=-1;return this},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w)},normalize:function(){var a=Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w);0===a?(this.z=this.y=this.x=0,this.w=1):(a=1/a,this.x*=a,this.y*=a,this.z*=a,this.w*=a);return this},multiply:function(a,b){var c=a.x,d=a.y,e=a.z,f=a.w,g=b.x,h=b.y,i=b.z,j=b.w;this.x=c*j+d*i-e*h+f*g;this.y=-c*i+d*j+e*g+f*h;this.z=c*h-
+d*g+e*j+f*i;this.w=-c*g-d*h-e*i+f*j;return this},multiplySelf:function(a){var b=this.x,c=this.y,d=this.z,e=this.w,f=a.x,g=a.y,h=a.z,a=a.w;this.x=b*a+e*f+c*h-d*g;this.y=c*a+e*g+d*f-b*h;this.z=d*a+e*h+b*g-c*f;this.w=e*a-b*f-c*g-d*h;return this},multiplyVector3:function(a,b){b||(b=a);var c=a.x,d=a.y,e=a.z,f=this.x,g=this.y,h=this.z,i=this.w,j=i*c+g*e-h*d,l=i*d+h*c-f*e,m=i*e+f*d-g*c,c=-f*c-g*d-h*e;b.x=j*i+c*-f+l*-h-m*-g;b.y=l*i+c*-g+m*-f-j*-h;b.z=m*i+c*-h+j*-g-l*-f;return b},slerpSelf:function(a,b){var c=
+this.x,d=this.y,e=this.z,f=this.w,g=f*a.w+c*a.x+d*a.y+e*a.z;0>g?(this.w=-a.w,this.x=-a.x,this.y=-a.y,this.z=-a.z,g=-g):this.copy(a);if(1<=g)return this.w=f,this.x=c,this.y=d,this.z=e,this;var h=Math.acos(g),i=Math.sqrt(1-g*g);if(0.001>Math.abs(i))return this.w=0.5*(f+this.w),this.x=0.5*(c+this.x),this.y=0.5*(d+this.y),this.z=0.5*(e+this.z),this;g=Math.sin((1-b)*h)/i;h=Math.sin(b*h)/i;this.w=f*g+this.w*h;this.x=c*g+this.x*h;this.y=d*g+this.y*h;this.z=e*g+this.z*h;return this},clone:function(){return new THREE.Quaternion(this.x,
+this.y,this.z,this.w)}};THREE.Quaternion.slerp=function(a,b,c,d){var e=a.w*b.w+a.x*b.x+a.y*b.y+a.z*b.z;0>e?(c.w=-b.w,c.x=-b.x,c.y=-b.y,c.z=-b.z,e=-e):c.copy(b);if(1<=Math.abs(e))return c.w=a.w,c.x=a.x,c.y=a.y,c.z=a.z,c;var b=Math.acos(e),f=Math.sqrt(1-e*e);if(0.001>Math.abs(f))return c.w=0.5*(a.w+c.w),c.x=0.5*(a.x+c.x),c.y=0.5*(a.y+c.y),c.z=0.5*(a.z+c.z),c;e=Math.sin((1-d)*b)/f;d=Math.sin(d*b)/f;c.w=a.w*e+c.w*d;c.x=a.x*e+c.x*d;c.y=a.y*e+c.y*d;c.z=a.z*e+c.z*d;return c};
+THREE.Vertex=function(a){console.warn("THREE.Vertex has been DEPRECATED. Use THREE.Vector3 instead.");return a};THREE.Face3=function(a,b,c,d,e,f){this.a=a;this.b=b;this.c=c;this.normal=d instanceof THREE.Vector3?d:new THREE.Vector3;this.vertexNormals=d instanceof Array?d:[];this.color=e instanceof THREE.Color?e:new THREE.Color;this.vertexColors=e instanceof Array?e:[];this.vertexTangents=[];this.materialIndex=f;this.centroid=new THREE.Vector3};
+THREE.Face3.prototype={constructor:THREE.Face3,clone:function(){var a=new THREE.Face3(this.a,this.b,this.c);a.normal.copy(this.normal);a.color.copy(this.color);a.centroid.copy(this.centroid);a.materialIndex=this.materialIndex;var b,c;b=0;for(c=this.vertexNormals.length;b<c;b++)a.vertexNormals[b]=this.vertexNormals[b].clone();b=0;for(c=this.vertexColors.length;b<c;b++)a.vertexColors[b]=this.vertexColors[b].clone();b=0;for(c=this.vertexTangents.length;b<c;b++)a.vertexTangents[b]=this.vertexTangents[b].clone();
+return a}};THREE.Face4=function(a,b,c,d,e,f,g){this.a=a;this.b=b;this.c=c;this.d=d;this.normal=e instanceof THREE.Vector3?e:new THREE.Vector3;this.vertexNormals=e instanceof Array?e:[];this.color=f instanceof THREE.Color?f:new THREE.Color;this.vertexColors=f instanceof Array?f:[];this.vertexTangents=[];this.materialIndex=g;this.centroid=new THREE.Vector3};
+THREE.Face4.prototype={constructor:THREE.Face4,clone:function(){var a=new THREE.Face4(this.a,this.b,this.c,this.d);a.normal.copy(this.normal);a.color.copy(this.color);a.centroid.copy(this.centroid);a.materialIndex=this.materialIndex;var b,c;b=0;for(c=this.vertexNormals.length;b<c;b++)a.vertexNormals[b]=this.vertexNormals[b].clone();b=0;for(c=this.vertexColors.length;b<c;b++)a.vertexColors[b]=this.vertexColors[b].clone();b=0;for(c=this.vertexTangents.length;b<c;b++)a.vertexTangents[b]=this.vertexTangents[b].clone();
+return a}};THREE.UV=function(a,b){this.u=a||0;this.v=b||0};THREE.UV.prototype={constructor:THREE.UV,set:function(a,b){this.u=a;this.v=b;return this},copy:function(a){this.u=a.u;this.v=a.v;return this},lerpSelf:function(a,b){this.u+=(a.u-this.u)*b;this.v+=(a.v-this.v)*b;return this},clone:function(){return new THREE.UV(this.u,this.v)}};
+THREE.Geometry=function(){THREE.GeometryLibrary.push(this);this.id=THREE.GeometryIdCount++;this.name="";this.vertices=[];this.colors=[];this.normals=[];this.faces=[];this.faceUvs=[[]];this.faceVertexUvs=[[]];this.morphTargets=[];this.morphColors=[];this.morphNormals=[];this.skinWeights=[];this.skinIndices=[];this.lineDistances=[];this.boundingSphere=this.boundingBox=null;this.hasTangents=!1;this.dynamic=!0;this.buffersNeedUpdate=this.lineDistancesNeedUpdate=this.colorsNeedUpdate=this.tangentsNeedUpdate=
+this.normalsNeedUpdate=this.uvsNeedUpdate=this.elementsNeedUpdate=this.verticesNeedUpdate=!1};
+THREE.Geometry.prototype={constructor:THREE.Geometry,applyMatrix:function(a){var b=new THREE.Matrix3;b.getInverse(a).transpose();for(var c=0,d=this.vertices.length;c<d;c++)a.multiplyVector3(this.vertices[c]);c=0;for(d=this.faces.length;c<d;c++){var e=this.faces[c];b.multiplyVector3(e.normal).normalize();for(var f=0,g=e.vertexNormals.length;f<g;f++)b.multiplyVector3(e.vertexNormals[f]).normalize();a.multiplyVector3(e.centroid)}},computeCentroids:function(){var a,b,c;a=0;for(b=this.faces.length;a<b;a++)c=
+this.faces[a],c.centroid.set(0,0,0),c instanceof THREE.Face3?(c.centroid.addSelf(this.vertices[c.a]),c.centroid.addSelf(this.vertices[c.b]),c.centroid.addSelf(this.vertices[c.c]),c.centroid.divideScalar(3)):c instanceof THREE.Face4&&(c.centroid.addSelf(this.vertices[c.a]),c.centroid.addSelf(this.vertices[c.b]),c.centroid.addSelf(this.vertices[c.c]),c.centroid.addSelf(this.vertices[c.d]),c.centroid.divideScalar(4))},computeFaceNormals:function(){var a,b,c,d,e,f,g=new THREE.Vector3,h=new THREE.Vector3;
+a=0;for(b=this.faces.length;a<b;a++)c=this.faces[a],d=this.vertices[c.a],e=this.vertices[c.b],f=this.vertices[c.c],g.sub(f,e),h.sub(d,e),g.crossSelf(h),g.normalize(),c.normal.copy(g)},computeVertexNormals:function(a){var b,c,d,e;if(void 0===this.__tmpVertices){e=this.__tmpVertices=Array(this.vertices.length);b=0;for(c=this.vertices.length;b<c;b++)e[b]=new THREE.Vector3;b=0;for(c=this.faces.length;b<c;b++)d=this.faces[b],d instanceof THREE.Face3?d.vertexNormals=[new THREE.Vector3,new THREE.Vector3,
+new THREE.Vector3]:d instanceof THREE.Face4&&(d.vertexNormals=[new THREE.Vector3,new THREE.Vector3,new THREE.Vector3,new THREE.Vector3])}else{e=this.__tmpVertices;b=0;for(c=this.vertices.length;b<c;b++)e[b].set(0,0,0)}if(a){var f,g,h,i=new THREE.Vector3,j=new THREE.Vector3,l=new THREE.Vector3,m=new THREE.Vector3,n=new THREE.Vector3;b=0;for(c=this.faces.length;b<c;b++)d=this.faces[b],d instanceof THREE.Face3?(a=this.vertices[d.a],f=this.vertices[d.b],g=this.vertices[d.c],i.sub(g,f),j.sub(a,f),i.crossSelf(j),
+e[d.a].addSelf(i),e[d.b].addSelf(i),e[d.c].addSelf(i)):d instanceof THREE.Face4&&(a=this.vertices[d.a],f=this.vertices[d.b],g=this.vertices[d.c],h=this.vertices[d.d],l.sub(h,f),j.sub(a,f),l.crossSelf(j),e[d.a].addSelf(l),e[d.b].addSelf(l),e[d.d].addSelf(l),m.sub(h,g),n.sub(f,g),m.crossSelf(n),e[d.b].addSelf(m),e[d.c].addSelf(m),e[d.d].addSelf(m))}else{b=0;for(c=this.faces.length;b<c;b++)d=this.faces[b],d instanceof THREE.Face3?(e[d.a].addSelf(d.normal),e[d.b].addSelf(d.normal),e[d.c].addSelf(d.normal)):
+d instanceof THREE.Face4&&(e[d.a].addSelf(d.normal),e[d.b].addSelf(d.normal),e[d.c].addSelf(d.normal),e[d.d].addSelf(d.normal))}b=0;for(c=this.vertices.length;b<c;b++)e[b].normalize();b=0;for(c=this.faces.length;b<c;b++)d=this.faces[b],d instanceof THREE.Face3?(d.vertexNormals[0].copy(e[d.a]),d.vertexNormals[1].copy(e[d.b]),d.vertexNormals[2].copy(e[d.c])):d instanceof THREE.Face4&&(d.vertexNormals[0].copy(e[d.a]),d.vertexNormals[1].copy(e[d.b]),d.vertexNormals[2].copy(e[d.c]),d.vertexNormals[3].copy(e[d.d]))},
+computeMorphNormals:function(){var a,b,c,d,e;c=0;for(d=this.faces.length;c<d;c++){e=this.faces[c];e.__originalFaceNormal?e.__originalFaceNormal.copy(e.normal):e.__originalFaceNormal=e.normal.clone();e.__originalVertexNormals||(e.__originalVertexNormals=[]);a=0;for(b=e.vertexNormals.length;a<b;a++)e.__originalVertexNormals[a]?e.__originalVertexNormals[a].copy(e.vertexNormals[a]):e.__originalVertexNormals[a]=e.vertexNormals[a].clone()}var f=new THREE.Geometry;f.faces=this.faces;a=0;for(b=this.morphTargets.length;a<
+b;a++){if(!this.morphNormals[a]){this.morphNormals[a]={};this.morphNormals[a].faceNormals=[];this.morphNormals[a].vertexNormals=[];var g=this.morphNormals[a].faceNormals,h=this.morphNormals[a].vertexNormals,i,j;c=0;for(d=this.faces.length;c<d;c++)e=this.faces[c],i=new THREE.Vector3,j=e instanceof THREE.Face3?{a:new THREE.Vector3,b:new THREE.Vector3,c:new THREE.Vector3}:{a:new THREE.Vector3,b:new THREE.Vector3,c:new THREE.Vector3,d:new THREE.Vector3},g.push(i),h.push(j)}g=this.morphNormals[a];f.vertices=
+this.morphTargets[a].vertices;f.computeFaceNormals();f.computeVertexNormals();c=0;for(d=this.faces.length;c<d;c++)e=this.faces[c],i=g.faceNormals[c],j=g.vertexNormals[c],i.copy(e.normal),e instanceof THREE.Face3?(j.a.copy(e.vertexNormals[0]),j.b.copy(e.vertexNormals[1]),j.c.copy(e.vertexNormals[2])):(j.a.copy(e.vertexNormals[0]),j.b.copy(e.vertexNormals[1]),j.c.copy(e.vertexNormals[2]),j.d.copy(e.vertexNormals[3]))}c=0;for(d=this.faces.length;c<d;c++)e=this.faces[c],e.normal=e.__originalFaceNormal,
+e.vertexNormals=e.__originalVertexNormals},computeTangents:function(){function a(a,b,c,d,e,f,u){h=a.vertices[b];i=a.vertices[c];j=a.vertices[d];l=g[e];m=g[f];n=g[u];p=i.x-h.x;o=j.x-h.x;s=i.y-h.y;t=j.y-h.y;r=i.z-h.z;z=j.z-h.z;w=m.u-l.u;q=n.u-l.u;E=m.v-l.v;A=n.v-l.v;v=1/(w*A-q*E);G.set((A*p-E*o)*v,(A*s-E*t)*v,(A*r-E*z)*v);P.set((w*o-q*p)*v,(w*t-q*s)*v,(w*z-q*r)*v);D[b].addSelf(G);D[c].addSelf(G);D[d].addSelf(G);C[b].addSelf(P);C[c].addSelf(P);C[d].addSelf(P)}var b,c,d,e,f,g,h,i,j,l,m,n,p,o,s,t,r,z,
+w,q,E,A,v,u,D=[],C=[],G=new THREE.Vector3,P=new THREE.Vector3,B=new THREE.Vector3,K=new THREE.Vector3,H=new THREE.Vector3;b=0;for(c=this.vertices.length;b<c;b++)D[b]=new THREE.Vector3,C[b]=new THREE.Vector3;b=0;for(c=this.faces.length;b<c;b++)f=this.faces[b],g=this.faceVertexUvs[0][b],f instanceof THREE.Face3?a(this,f.a,f.b,f.c,0,1,2):f instanceof THREE.Face4&&(a(this,f.a,f.b,f.d,0,1,3),a(this,f.b,f.c,f.d,1,2,3));var I=["a","b","c","d"];b=0;for(c=this.faces.length;b<c;b++){f=this.faces[b];for(d=0;d<
+f.vertexNormals.length;d++)H.copy(f.vertexNormals[d]),e=f[I[d]],u=D[e],B.copy(u),B.subSelf(H.multiplyScalar(H.dot(u))).normalize(),K.cross(f.vertexNormals[d],u),e=K.dot(C[e]),e=0>e?-1:1,f.vertexTangents[d]=new THREE.Vector4(B.x,B.y,B.z,e)}this.hasTangents=!0},computeLineDistances:function(){for(var a=0,b=this.vertices,c=0,d=b.length;c<d;c++)0<c&&(a+=b[c].distanceTo(b[c-1])),this.lineDistances[c]=a},computeBoundingBox:function(){this.boundingBox||(this.boundingBox={min:new THREE.Vector3,max:new THREE.Vector3});
+if(0<this.vertices.length){var a;a=this.vertices[0];this.boundingBox.min.copy(a);this.boundingBox.max.copy(a);for(var b=this.boundingBox.min,c=this.boundingBox.max,d=1,e=this.vertices.length;d<e;d++)(a=this.vertices[d],a.x<b.x?b.x=a.x:a.x>c.x&&(c.x=a.x),a.y<b.y?b.y=a.y:a.y>c.y&&(c.y=a.y),a.z<b.z)?b.z=a.z:a.z>c.z&&(c.z=a.z)}else this.boundingBox.min.set(0,0,0),this.boundingBox.max.set(0,0,0)},computeBoundingSphere:function(){var a=0;null===this.boundingSphere&&(this.boundingSphere={radius:0});for(var b=
+0,c=this.vertices.length;b<c;b++){var d=this.vertices[b].lengthSq();d>a&&(a=d)}this.boundingSphere.radius=Math.sqrt(a)},mergeVertices:function(){var a={},b=[],c=[],d,e=Math.pow(10,4),f,g,h,i;f=0;for(g=this.vertices.length;f<g;f++)d=this.vertices[f],d=[Math.round(d.x*e),Math.round(d.y*e),Math.round(d.z*e)].join("_"),void 0===a[d]?(a[d]=f,b.push(this.vertices[f]),c[f]=b.length-1):c[f]=c[a[d]];f=0;for(g=this.faces.length;f<g;f++)if(a=this.faces[f],a instanceof THREE.Face3)a.a=c[a.a],a.b=c[a.b],a.c=c[a.c];
+else if(a instanceof THREE.Face4){a.a=c[a.a];a.b=c[a.b];a.c=c[a.c];a.d=c[a.d];d=[a.a,a.b,a.c,a.d];for(e=3;0<e;e--)if(d.indexOf(a["abcd"[e]])!==e){d.splice(e,1);this.faces[f]=new THREE.Face3(d[0],d[1],d[2],a.normal,a.color,a.materialIndex);d=0;for(h=this.faceVertexUvs.length;d<h;d++)(i=this.faceVertexUvs[d][f])&&i.splice(e,1);this.faces[f].vertexColors=a.vertexColors;break}}c=this.vertices.length-b.length;this.vertices=b;return c},clone:function(){for(var a=new THREE.Geometry,b=this.vertices,c=0,d=
+b.length;c<d;c++)a.vertices.push(b[c].clone());b=this.faces;c=0;for(d=b.length;c<d;c++)a.faces.push(b[c].clone());b=this.faceVertexUvs[0];c=0;for(d=b.length;c<d;c++){for(var e=b[c],f=[],g=0,h=e.length;g<h;g++)f.push(new THREE.UV(e[g].u,e[g].v));a.faceVertexUvs[0].push(f)}return a},deallocate:function(){var a=THREE.GeometryLibrary.indexOf(this);-1!==a&&THREE.GeometryLibrary.splice(a,1)}};THREE.GeometryIdCount=0;THREE.GeometryLibrary=[];
+THREE.BufferGeometry=function(){THREE.GeometryLibrary.push(this);this.id=THREE.GeometryIdCount++;this.attributes={};this.dynamic=!1;this.boundingSphere=this.boundingBox=null;this.hasTangents=!1;this.morphTargets=[]};
+THREE.BufferGeometry.prototype={constructor:THREE.BufferGeometry,applyMatrix:function(a){var b,c;this.attributes.position&&(b=this.attributes.position.array);this.attributes.normal&&(c=this.attributes.normal.array);void 0!==b&&(a.multiplyVector3Array(b),this.verticesNeedUpdate=!0);void 0!==c&&(b=new THREE.Matrix3,b.getInverse(a).transpose(),b.multiplyVector3Array(c),this.normalizeNormals(),this.normalsNeedUpdate=!0)},computeBoundingBox:function(){this.boundingBox||(this.boundingBox={min:new THREE.Vector3(Infinity,
+Infinity,Infinity),max:new THREE.Vector3(-Infinity,-Infinity,-Infinity)});var a=this.attributes.position.array;if(a)for(var b=this.boundingBox,c,d,e,f=0,g=a.length;f<g;f+=3)(c=a[f],d=a[f+1],e=a[f+2],c<b.min.x?b.min.x=c:c>b.max.x&&(b.max.x=c),d<b.min.y?b.min.y=d:d>b.max.y&&(b.max.y=d),e<b.min.z)?b.min.z=e:e>b.max.z&&(b.max.z=e);if(void 0===a||0===a.length)this.boundingBox.min.set(0,0,0),this.boundingBox.max.set(0,0,0)},computeBoundingSphere:function(){this.boundingSphere||(this.boundingSphere={radius:0});
+var a=this.attributes.position.array;if(a){for(var b,c=0,d,e,f=0,g=a.length;f<g;f+=3)b=a[f],d=a[f+1],e=a[f+2],b=b*b+d*d+e*e,b>c&&(c=b);this.boundingSphere.radius=Math.sqrt(c)}},computeVertexNormals:function(){if(this.attributes.position&&this.attributes.index){var a,b,c,d;a=this.attributes.position.array.length;if(void 0===this.attributes.normal)this.attributes.normal={itemSize:3,array:new Float32Array(a),numItems:a};else{a=0;for(b=this.attributes.normal.array.length;a<b;a++)this.attributes.normal.array[a]=
+0}var e=this.offsets,f=this.attributes.index.array,g=this.attributes.position.array,h=this.attributes.normal.array,i,j,l,m,n,p,o=new THREE.Vector3,s=new THREE.Vector3,t=new THREE.Vector3,r=new THREE.Vector3,z=new THREE.Vector3;c=0;for(d=e.length;c<d;++c){b=e[c].start;i=e[c].count;var w=e[c].index;a=b;for(b+=i;a<b;a+=3)i=w+f[a],j=w+f[a+1],l=w+f[a+2],m=g[3*i],n=g[3*i+1],p=g[3*i+2],o.set(m,n,p),m=g[3*j],n=g[3*j+1],p=g[3*j+2],s.set(m,n,p),m=g[3*l],n=g[3*l+1],p=g[3*l+2],t.set(m,n,p),r.sub(t,s),z.sub(o,
+s),r.crossSelf(z),h[3*i]+=r.x,h[3*i+1]+=r.y,h[3*i+2]+=r.z,h[3*j]+=r.x,h[3*j+1]+=r.y,h[3*j+2]+=r.z,h[3*l]+=r.x,h[3*l+1]+=r.y,h[3*l+2]+=r.z}this.normalizeNormals();this.normalsNeedUpdate=!0}},normalizeNormals:function(){for(var a=this.attributes.normal.array,b,c,d,e=0,f=a.length;e<f;e+=3)b=a[e],c=a[e+1],d=a[e+2],b=1/Math.sqrt(b*b+c*c+d*d),a[e]*=b,a[e+1]*=b,a[e+2]*=b},computeTangents:function(){function a(a){ga.x=d[3*a];ga.y=d[3*a+1];ga.z=d[3*a+2];M.copy(ga);Q=i[a];O.copy(Q);O.subSelf(ga.multiplyScalar(ga.dot(Q))).normalize();
+R.cross(M,Q);Z=R.dot(j[a]);J=0>Z?-1:1;h[4*a]=O.x;h[4*a+1]=O.y;h[4*a+2]=O.z;h[4*a+3]=J}if(void 0===this.attributes.index||void 0===this.attributes.position||void 0===this.attributes.normal||void 0===this.attributes.uv)console.warn("Missing required attributes (index, position, normal or uv) in BufferGeometry.computeTangents()");else{var b=this.attributes.index.array,c=this.attributes.position.array,d=this.attributes.normal.array,e=this.attributes.uv.array,f=c.length/3;if(void 0===this.attributes.tangent){var g=
+4*f;this.attributes.tangent={itemSize:4,array:new Float32Array(g),numItems:g}}for(var h=this.attributes.tangent.array,i=[],j=[],g=0;g<f;g++)i[g]=new THREE.Vector3,j[g]=new THREE.Vector3;var l,m,n,p,o,s,t,r,z,w,q,E,A,v,u,f=new THREE.Vector3,g=new THREE.Vector3,D,C,G,P,B,K,H,I=this.offsets;G=0;for(P=I.length;G<P;++G){C=I[G].start;B=I[G].count;var N=I[G].index;D=C;for(C+=B;D<C;D+=3)B=N+b[D],K=N+b[D+1],H=N+b[D+2],l=c[3*B],m=c[3*B+1],n=c[3*B+2],p=c[3*K],o=c[3*K+1],s=c[3*K+2],t=c[3*H],r=c[3*H+1],z=c[3*
+H+2],w=e[2*B],q=e[2*B+1],E=e[2*K],A=e[2*K+1],v=e[2*H],u=e[2*H+1],p-=l,l=t-l,o-=m,m=r-m,s-=n,n=z-n,E-=w,w=v-w,A-=q,q=u-q,u=1/(E*q-w*A),f.set((q*p-A*l)*u,(q*o-A*m)*u,(q*s-A*n)*u),g.set((E*l-w*p)*u,(E*m-w*o)*u,(E*n-w*s)*u),i[B].addSelf(f),i[K].addSelf(f),i[H].addSelf(f),j[B].addSelf(g),j[K].addSelf(g),j[H].addSelf(g)}var O=new THREE.Vector3,R=new THREE.Vector3,ga=new THREE.Vector3,M=new THREE.Vector3,J,Q,Z;G=0;for(P=I.length;G<P;++G){C=I[G].start;B=I[G].count;N=I[G].index;D=C;for(C+=B;D<C;D+=3)B=N+b[D],
+K=N+b[D+1],H=N+b[D+2],a(B),a(K),a(H)}this.tangentsNeedUpdate=this.hasTangents=!0}},deallocate:function(){var a=THREE.GeometryLibrary.indexOf(this);-1!==a&&THREE.GeometryLibrary.splice(a,1)}};
+THREE.Spline=function(a){function b(a,b,c,d,e,f,g){a=0.5*(c-a);d=0.5*(d-b);return(2*(b-c)+a+d)*g+(-3*(b-c)-2*a-d)*f+a*e+b}this.points=a;var c=[],d={x:0,y:0,z:0},e,f,g,h,i,j,l,m,n;this.initFromArray=function(a){this.points=[];for(var b=0;b<a.length;b++)this.points[b]={x:a[b][0],y:a[b][1],z:a[b][2]}};this.getPoint=function(a){e=(this.points.length-1)*a;f=Math.floor(e);g=e-f;c[0]=0===f?f:f-1;c[1]=f;c[2]=f>this.points.length-2?this.points.length-1:f+1;c[3]=f>this.points.length-3?this.points.length-1:
+f+2;j=this.points[c[0]];l=this.points[c[1]];m=this.points[c[2]];n=this.points[c[3]];h=g*g;i=g*h;d.x=b(j.x,l.x,m.x,n.x,g,h,i);d.y=b(j.y,l.y,m.y,n.y,g,h,i);d.z=b(j.z,l.z,m.z,n.z,g,h,i);return d};this.getControlPointsArray=function(){var a,b,c=this.points.length,d=[];for(a=0;a<c;a++)b=this.points[a],d[a]=[b.x,b.y,b.z];return d};this.getLength=function(a){var b,c,d,e=b=b=0,f=new THREE.Vector3,g=new THREE.Vector3,h=[],i=0;h[0]=0;a||(a=100);c=this.points.length*a;f.copy(this.points[0]);for(a=1;a<c;a++)b=
+a/c,d=this.getPoint(b),g.copy(d),i+=g.distanceTo(f),f.copy(d),b*=this.points.length-1,b=Math.floor(b),b!=e&&(h[b]=i,e=b);h[h.length]=i;return{chunks:h,total:i}};this.reparametrizeByArcLength=function(a){var b,c,d,e,f,g,h=[],i=new THREE.Vector3,j=this.getLength();h.push(i.copy(this.points[0]).clone());for(b=1;b<this.points.length;b++){c=j.chunks[b]-j.chunks[b-1];g=Math.ceil(a*c/j.total);e=(b-1)/(this.points.length-1);f=b/(this.points.length-1);for(c=1;c<g-1;c++)d=e+c*(1/g)*(f-e),d=this.getPoint(d),
+h.push(i.copy(d).clone());h.push(i.copy(this.points[b]).clone())}this.points=h}};THREE.Camera=function(){THREE.Object3D.call(this);this.matrixWorldInverse=new THREE.Matrix4;this.projectionMatrix=new THREE.Matrix4;this.projectionMatrixInverse=new THREE.Matrix4};THREE.Camera.prototype=Object.create(THREE.Object3D.prototype);
+THREE.Camera.prototype.lookAt=function(a){this.matrix.lookAt(this.position,a,this.up);!0===this.rotationAutoUpdate&&(!1===this.useQuaternion?this.rotation.setEulerFromRotationMatrix(this.matrix,this.eulerOrder):this.quaternion.copy(this.matrix.decompose()[1]))};THREE.OrthographicCamera=function(a,b,c,d,e,f){THREE.Camera.call(this);this.left=a;this.right=b;this.top=c;this.bottom=d;this.near=void 0!==e?e:0.1;this.far=void 0!==f?f:2E3;this.updateProjectionMatrix()};
+THREE.OrthographicCamera.prototype=Object.create(THREE.Camera.prototype);THREE.OrthographicCamera.prototype.updateProjectionMatrix=function(){this.projectionMatrix.makeOrthographic(this.left,this.right,this.top,this.bottom,this.near,this.far)};THREE.PerspectiveCamera=function(a,b,c,d){THREE.Camera.call(this);this.fov=void 0!==a?a:50;this.aspect=void 0!==b?b:1;this.near=void 0!==c?c:0.1;this.far=void 0!==d?d:2E3;this.updateProjectionMatrix()};THREE.PerspectiveCamera.prototype=Object.create(THREE.Camera.prototype);
+THREE.PerspectiveCamera.prototype.setLens=function(a,b){void 0===b&&(b=24);this.fov=2*Math.atan(b/(2*a))*(180/Math.PI);this.updateProjectionMatrix()};THREE.PerspectiveCamera.prototype.setViewOffset=function(a,b,c,d,e,f){this.fullWidth=a;this.fullHeight=b;this.x=c;this.y=d;this.width=e;this.height=f;this.updateProjectionMatrix()};
+THREE.PerspectiveCamera.prototype.updateProjectionMatrix=function(){if(this.fullWidth){var a=this.fullWidth/this.fullHeight,b=Math.tan(this.fov*Math.PI/360)*this.near,c=-b,d=a*c,a=Math.abs(a*b-d),c=Math.abs(b-c);this.projectionMatrix.makeFrustum(d+this.x*a/this.fullWidth,d+(this.x+this.width)*a/this.fullWidth,b-(this.y+this.height)*c/this.fullHeight,b-this.y*c/this.fullHeight,this.near,this.far)}else this.projectionMatrix.makePerspective(this.fov,this.aspect,this.near,this.far)};
+THREE.Light=function(a){THREE.Object3D.call(this);this.color=new THREE.Color(a)};THREE.Light.prototype=Object.create(THREE.Object3D.prototype);THREE.AmbientLight=function(a){THREE.Light.call(this,a)};THREE.AmbientLight.prototype=Object.create(THREE.Light.prototype);
+THREE.DirectionalLight=function(a,b){THREE.Light.call(this,a);this.position=new THREE.Vector3(0,1,0);this.target=new THREE.Object3D;this.intensity=void 0!==b?b:1;this.onlyShadow=this.castShadow=!1;this.shadowCameraNear=50;this.shadowCameraFar=5E3;this.shadowCameraLeft=-500;this.shadowCameraTop=this.shadowCameraRight=500;this.shadowCameraBottom=-500;this.shadowCameraVisible=!1;this.shadowBias=0;this.shadowDarkness=0.5;this.shadowMapHeight=this.shadowMapWidth=512;this.shadowCascade=!1;this.shadowCascadeOffset=
+new THREE.Vector3(0,0,-1E3);this.shadowCascadeCount=2;this.shadowCascadeBias=[0,0,0];this.shadowCascadeWidth=[512,512,512];this.shadowCascadeHeight=[512,512,512];this.shadowCascadeNearZ=[-1,0.99,0.998];this.shadowCascadeFarZ=[0.99,0.998,1];this.shadowCascadeArray=[];this.shadowMatrix=this.shadowCamera=this.shadowMapSize=this.shadowMap=null};THREE.DirectionalLight.prototype=Object.create(THREE.Light.prototype);
+THREE.HemisphereLight=function(a,b,c){THREE.Light.call(this,a);this.groundColor=new THREE.Color(b);this.position=new THREE.Vector3(0,100,0);this.intensity=void 0!==c?c:1};THREE.HemisphereLight.prototype=Object.create(THREE.Light.prototype);THREE.PointLight=function(a,b,c){THREE.Light.call(this,a);this.position=new THREE.Vector3(0,0,0);this.intensity=void 0!==b?b:1;this.distance=void 0!==c?c:0};THREE.PointLight.prototype=Object.create(THREE.Light.prototype);
+THREE.SpotLight=function(a,b,c,d,e){THREE.Light.call(this,a);this.position=new THREE.Vector3(0,1,0);this.target=new THREE.Object3D;this.intensity=void 0!==b?b:1;this.distance=void 0!==c?c:0;this.angle=void 0!==d?d:Math.PI/2;this.exponent=void 0!==e?e:10;this.onlyShadow=this.castShadow=!1;this.shadowCameraNear=50;this.shadowCameraFar=5E3;this.shadowCameraFov=50;this.shadowCameraVisible=!1;this.shadowBias=0;this.shadowDarkness=0.5;this.shadowMapHeight=this.shadowMapWidth=512;this.shadowMatrix=this.shadowCamera=
+this.shadowMapSize=this.shadowMap=null};THREE.SpotLight.prototype=Object.create(THREE.Light.prototype);THREE.Loader=function(a){this.statusDomElement=(this.showStatus=a)?THREE.Loader.prototype.addStatusElement():null;this.onLoadStart=function(){};this.onLoadProgress=function(){};this.onLoadComplete=function(){}};
+THREE.Loader.prototype={constructor:THREE.Loader,crossOrigin:"anonymous",addStatusElement:function(){var a=document.createElement("div");a.style.position="absolute";a.style.right="0px";a.style.top="0px";a.style.fontSize="0.8em";a.style.textAlign="left";a.style.background="rgba(0,0,0,0.25)";a.style.color="#fff";a.style.width="120px";a.style.padding="0.5em 0.5em 0.5em 0.5em";a.style.zIndex=1E3;a.innerHTML="Loading ...";return a},updateProgress:function(a){var b="Loaded ",b=a.total?b+((100*a.loaded/
+a.total).toFixed(0)+"%"):b+((a.loaded/1E3).toFixed(2)+" KB");this.statusDomElement.innerHTML=b},extractUrlBase:function(a){a=a.split("/");a.pop();return(1>a.length?".":a.join("/"))+"/"},initMaterials:function(a,b){for(var c=[],d=0;d<a.length;++d)c[d]=THREE.Loader.prototype.createMaterial(a[d],b);return c},needsTangents:function(a){for(var b=0,c=a.length;b<c;b++)if(a[b]instanceof THREE.ShaderMaterial)return!0;return!1},createMaterial:function(a,b){function c(a){a=Math.log(a)/Math.LN2;return Math.floor(a)==
+a}function d(a){a=Math.log(a)/Math.LN2;return Math.pow(2,Math.round(a))}function e(a,e,f,h,i,j,t){var r=f.toLowerCase().endsWith(".dds"),z=b+"/"+f;if(r){var w=THREE.ImageUtils.loadCompressedTexture(z);a[e]=w}else w=document.createElement("canvas"),a[e]=new THREE.Texture(w);a[e].sourceFile=f;if(h&&(a[e].repeat.set(h[0],h[1]),1!==h[0]&&(a[e].wrapS=THREE.RepeatWrapping),1!==h[1]))a[e].wrapT=THREE.RepeatWrapping;i&&a[e].offset.set(i[0],i[1]);if(j&&(f={repeat:THREE.RepeatWrapping,mirror:THREE.MirroredRepeatWrapping},
+void 0!==f[j[0]]&&(a[e].wrapS=f[j[0]]),void 0!==f[j[1]]))a[e].wrapT=f[j[1]];t&&(a[e].anisotropy=t);if(!r){var q=a[e],a=new Image;a.onload=function(){if(!c(this.width)||!c(this.height)){var a=d(this.width),b=d(this.height);q.image.width=a;q.image.height=b;q.image.getContext("2d").drawImage(this,0,0,a,b)}else q.image=this;q.needsUpdate=true};a.crossOrigin=g.crossOrigin;a.src=z}}function f(a){return(255*a[0]<<16)+(255*a[1]<<8)+255*a[2]}var g=this,h="MeshLambertMaterial",i={color:15658734,opacity:1,map:null,
+lightMap:null,normalMap:null,bumpMap:null,wireframe:!1};if(a.shading){var j=a.shading.toLowerCase();"phong"===j?h="MeshPhongMaterial":"basic"===j&&(h="MeshBasicMaterial")}void 0!==a.blending&&void 0!==THREE[a.blending]&&(i.blending=THREE[a.blending]);if(void 0!==a.transparent||1>a.opacity)i.transparent=a.transparent;void 0!==a.depthTest&&(i.depthTest=a.depthTest);void 0!==a.depthWrite&&(i.depthWrite=a.depthWrite);void 0!==a.visible&&(i.visible=a.visible);void 0!==a.flipSided&&(i.side=THREE.BackSide);
+void 0!==a.doubleSided&&(i.side=THREE.DoubleSide);void 0!==a.wireframe&&(i.wireframe=a.wireframe);void 0!==a.vertexColors&&("face"===a.vertexColors?i.vertexColors=THREE.FaceColors:a.vertexColors&&(i.vertexColors=THREE.VertexColors));a.colorDiffuse?i.color=f(a.colorDiffuse):a.DbgColor&&(i.color=a.DbgColor);a.colorSpecular&&(i.specular=f(a.colorSpecular));a.colorAmbient&&(i.ambient=f(a.colorAmbient));a.transparency&&(i.opacity=a.transparency);a.specularCoef&&(i.shininess=a.specularCoef);a.mapDiffuse&&
+b&&e(i,"map",a.mapDiffuse,a.mapDiffuseRepeat,a.mapDiffuseOffset,a.mapDiffuseWrap,a.mapDiffuseAnisotropy);a.mapLight&&b&&e(i,"lightMap",a.mapLight,a.mapLightRepeat,a.mapLightOffset,a.mapLightWrap,a.mapLightAnisotropy);a.mapBump&&b&&e(i,"bumpMap",a.mapBump,a.mapBumpRepeat,a.mapBumpOffset,a.mapBumpWrap,a.mapBumpAnisotropy);a.mapNormal&&b&&e(i,"normalMap",a.mapNormal,a.mapNormalRepeat,a.mapNormalOffset,a.mapNormalWrap,a.mapNormalAnisotropy);a.mapSpecular&&b&&e(i,"specularMap",a.mapSpecular,a.mapSpecularRepeat,
+a.mapSpecularOffset,a.mapSpecularWrap,a.mapSpecularAnisotropy);a.mapBumpScale&&(i.bumpScale=a.mapBumpScale);a.mapNormal?(h=THREE.ShaderUtils.lib.normal,j=THREE.UniformsUtils.clone(h.uniforms),j.tNormal.value=i.normalMap,a.mapNormalFactor&&j.uNormalScale.value.set(a.mapNormalFactor,a.mapNormalFactor),i.map&&(j.tDiffuse.value=i.map,j.enableDiffuse.value=!0),i.specularMap&&(j.tSpecular.value=i.specularMap,j.enableSpecular.value=!0),i.lightMap&&(j.tAO.value=i.lightMap,j.enableAO.value=!0),j.uDiffuseColor.value.setHex(i.color),
+j.uSpecularColor.value.setHex(i.specular),j.uAmbientColor.value.setHex(i.ambient),j.uShininess.value=i.shininess,void 0!==i.opacity&&(j.uOpacity.value=i.opacity),i=new THREE.ShaderMaterial({fragmentShader:h.fragmentShader,vertexShader:h.vertexShader,uniforms:j,lights:!0,fog:!0})):i=new THREE[h](i);void 0!==a.DbgName&&(i.name=a.DbgName);return i}};THREE.BinaryLoader=function(a){THREE.Loader.call(this,a)};THREE.BinaryLoader.prototype=Object.create(THREE.Loader.prototype);
+THREE.BinaryLoader.prototype.load=function(a,b,c,d){var c=c&&"string"===typeof c?c:this.extractUrlBase(a),d=d&&"string"===typeof d?d:this.extractUrlBase(a),e=this.showProgress?THREE.Loader.prototype.updateProgress:null;this.onLoadStart();this.loadAjaxJSON(this,a,b,c,d,e)};
+THREE.BinaryLoader.prototype.loadAjaxJSON=function(a,b,c,d,e,f){var g=new XMLHttpRequest;g.onreadystatechange=function(){if(4==g.readyState)if(200==g.status||0==g.status){var h=JSON.parse(g.responseText);a.loadAjaxBuffers(h,c,e,d,f)}else console.error("THREE.BinaryLoader: Couldn't load ["+b+"] ["+g.status+"]")};g.open("GET",b,!0);g.send(null)};
+THREE.BinaryLoader.prototype.loadAjaxBuffers=function(a,b,c,d,e){var f=new XMLHttpRequest,g=c+"/"+a.buffers,h=0;f.onreadystatechange=function(){if(4==f.readyState)if(200==f.status||0==f.status){var c=f.response;void 0===c&&(c=(new Uint8Array(f.responseBody)).buffer);THREE.BinaryLoader.prototype.createBinModel(c,b,d,a.materials)}else console.error("THREE.BinaryLoader: Couldn't load ["+g+"] ["+f.status+"]");else 3==f.readyState?e&&(0==h&&(h=f.getResponseHeader("Content-Length")),e({total:h,loaded:f.responseText.length})):
+2==f.readyState&&(h=f.getResponseHeader("Content-Length"))};f.open("GET",g,!0);f.responseType="arraybuffer";f.send(null)};
+THREE.BinaryLoader.prototype.createBinModel=function(a,b,c,d){var e=function(){var b,c,d,e,j,l,m,n,p,o,s,t,r,z,w,q;function E(a){return a%4?4-a%4:0}function A(a,b){return(new Uint8Array(a,b,1))[0]}function v(a,b){return(new Uint32Array(a,b,1))[0]}function u(b,c){var d,e,f,g,h,i,j,l=new Uint32Array(a,c,3*b);for(d=0;d<b;d++)e=l[3*d],f=l[3*d+1],g=l[3*d+2],h=N[2*e],e=N[2*e+1],i=N[2*f],j=N[2*f+1],f=N[2*g],g=N[2*g+1],K.faceVertexUvs[0].push([new THREE.UV(h,e),new THREE.UV(i,j),new THREE.UV(f,g)])}function D(b,
+c){var d,e,f,g,h,i,j,l,n,m=new Uint32Array(a,c,4*b);for(d=0;d<b;d++)e=m[4*d],f=m[4*d+1],g=m[4*d+2],h=m[4*d+3],i=N[2*e],e=N[2*e+1],j=N[2*f],l=N[2*f+1],f=N[2*g],n=N[2*g+1],g=N[2*h],h=N[2*h+1],K.faceVertexUvs[0].push([new THREE.UV(i,e),new THREE.UV(j,l),new THREE.UV(f,n),new THREE.UV(g,h)])}function C(b,c,d){for(var e,f,g,h,c=new Uint32Array(a,c,3*b),i=new Uint16Array(a,d,b),d=0;d<b;d++)e=c[3*d],f=c[3*d+1],g=c[3*d+2],h=i[d],K.faces.push(new THREE.Face3(e,f,g,null,null,h))}function G(b,c,d){for(var e,
+f,g,h,i,c=new Uint32Array(a,c,4*b),j=new Uint16Array(a,d,b),d=0;d<b;d++)e=c[4*d],f=c[4*d+1],g=c[4*d+2],h=c[4*d+3],i=j[d],K.faces.push(new THREE.Face4(e,f,g,h,null,null,i))}function P(b,c,d,e){for(var f,g,h,i,j,l,n,c=new Uint32Array(a,c,3*b),d=new Uint32Array(a,d,3*b),m=new Uint16Array(a,e,b),e=0;e<b;e++){f=c[3*e];g=c[3*e+1];h=c[3*e+2];j=d[3*e];l=d[3*e+1];n=d[3*e+2];i=m[e];var o=I[3*l],p=I[3*l+1];l=I[3*l+2];var s=I[3*n],r=I[3*n+1];n=I[3*n+2];K.faces.push(new THREE.Face3(f,g,h,[new THREE.Vector3(I[3*
+j],I[3*j+1],I[3*j+2]),new THREE.Vector3(o,p,l),new THREE.Vector3(s,r,n)],null,i))}}function B(b,c,d,e){for(var f,g,h,i,j,l,n,m,o,c=new Uint32Array(a,c,4*b),d=new Uint32Array(a,d,4*b),p=new Uint16Array(a,e,b),e=0;e<b;e++){f=c[4*e];g=c[4*e+1];h=c[4*e+2];i=c[4*e+3];l=d[4*e];n=d[4*e+1];m=d[4*e+2];o=d[4*e+3];j=p[e];var s=I[3*n],r=I[3*n+1];n=I[3*n+2];var q=I[3*m],t=I[3*m+1];m=I[3*m+2];var u=I[3*o],v=I[3*o+1];o=I[3*o+2];K.faces.push(new THREE.Face4(f,g,h,i,[new THREE.Vector3(I[3*l],I[3*l+1],I[3*l+2]),new THREE.Vector3(s,
+r,n),new THREE.Vector3(q,t,m),new THREE.Vector3(u,v,o)],null,j))}}var K=this,H=0,I=[],N=[],O,R,ga;THREE.Geometry.call(this);q=a;R=H;z=new Uint8Array(q,R,12);o="";for(r=0;12>r;r++)o+=String.fromCharCode(z[R+r]);b=A(q,R+12);A(q,R+13);A(q,R+14);A(q,R+15);c=A(q,R+16);d=A(q,R+17);e=A(q,R+18);j=A(q,R+19);l=v(q,R+20);m=v(q,R+20+4);n=v(q,R+20+8);p=v(q,R+20+12);o=v(q,R+20+16);s=v(q,R+20+20);t=v(q,R+20+24);r=v(q,R+20+28);z=v(q,R+20+32);w=v(q,R+20+36);q=v(q,R+20+40);H+=b;R=3*c+j;ga=4*c+j;O=p*R;b=o*(R+3*d);c=
+s*(R+3*e);j=t*(R+3*d+3*e);R=r*ga;d=z*(ga+4*d);e=w*(ga+4*e);ga=H;var H=new Float32Array(a,H,3*l),M,J,Q,Z;for(M=0;M<l;M++)J=H[3*M],Q=H[3*M+1],Z=H[3*M+2],K.vertices.push(new THREE.Vector3(J,Q,Z));l=H=ga+3*l*Float32Array.BYTES_PER_ELEMENT;if(m){H=new Int8Array(a,H,3*m);for(ga=0;ga<m;ga++)M=H[3*ga],J=H[3*ga+1],Q=H[3*ga+2],I.push(M/127,J/127,Q/127)}H=l+3*m*Int8Array.BYTES_PER_ELEMENT;m=H+=E(3*m);if(n){l=new Float32Array(a,H,2*n);for(H=0;H<n;H++)ga=l[2*H],M=l[2*H+1],N.push(ga,M)}n=H=m+2*n*Float32Array.BYTES_PER_ELEMENT;
+O=n+O+E(2*p);m=O+b+E(2*o);b=m+c+E(2*s);c=b+j+E(2*t);R=c+R+E(2*r);j=R+d+E(2*z);d=j+e+E(2*w);s&&(e=m+3*s*Uint32Array.BYTES_PER_ELEMENT,C(s,m,e+3*s*Uint32Array.BYTES_PER_ELEMENT),u(s,e));t&&(s=b+3*t*Uint32Array.BYTES_PER_ELEMENT,e=s+3*t*Uint32Array.BYTES_PER_ELEMENT,P(t,b,s,e+3*t*Uint32Array.BYTES_PER_ELEMENT),u(t,e));w&&(t=j+4*w*Uint32Array.BYTES_PER_ELEMENT,G(w,j,t+4*w*Uint32Array.BYTES_PER_ELEMENT),D(w,t));q&&(w=d+4*q*Uint32Array.BYTES_PER_ELEMENT,t=w+4*q*Uint32Array.BYTES_PER_ELEMENT,B(q,d,w,t+4*
+q*Uint32Array.BYTES_PER_ELEMENT),D(q,t));p&&C(p,n,n+3*p*Uint32Array.BYTES_PER_ELEMENT);o&&(p=O+3*o*Uint32Array.BYTES_PER_ELEMENT,P(o,O,p,p+3*o*Uint32Array.BYTES_PER_ELEMENT));r&&G(r,c,c+4*r*Uint32Array.BYTES_PER_ELEMENT);z&&(o=R+4*z*Uint32Array.BYTES_PER_ELEMENT,B(z,R,o,o+4*z*Uint32Array.BYTES_PER_ELEMENT));this.computeCentroids();this.computeFaceNormals()};e.prototype=Object.create(THREE.Geometry.prototype);e=new e(c);c=this.initMaterials(d,c);this.needsTangents(c)&&e.computeTangents();b(e,c)};
+THREE.ImageLoader=function(){THREE.EventTarget.call(this);this.crossOrigin=null};THREE.ImageLoader.prototype={constructor:THREE.ImageLoader,load:function(a,b){var c=this;void 0===b&&(b=new Image);b.addEventListener("load",function(){c.dispatchEvent({type:"load",content:b})},!1);b.addEventListener("error",function(){c.dispatchEvent({type:"error",message:"Couldn't load URL ["+a+"]"})},!1);c.crossOrigin&&(b.crossOrigin=c.crossOrigin);b.src=a}};
+THREE.JSONLoader=function(a){THREE.Loader.call(this,a);this.withCredentials=!1};THREE.JSONLoader.prototype=Object.create(THREE.Loader.prototype);THREE.JSONLoader.prototype.load=function(a,b,c){c=c&&"string"===typeof c?c:this.extractUrlBase(a);this.onLoadStart();this.loadAjaxJSON(this,a,b,c)};
+THREE.JSONLoader.prototype.loadAjaxJSON=function(a,b,c,d,e){var f=new XMLHttpRequest,g=0;f.withCredentials=this.withCredentials;f.onreadystatechange=function(){if(f.readyState===f.DONE)if(200===f.status||0===f.status){if(f.responseText){var h=JSON.parse(f.responseText);a.createModel(h,c,d)}else console.warn("THREE.JSONLoader: ["+b+"] seems to be unreachable or file there is empty");a.onLoadComplete()}else console.error("THREE.JSONLoader: Couldn't load ["+b+"] ["+f.status+"]");else f.readyState===
+f.LOADING?e&&(0===g&&(g=f.getResponseHeader("Content-Length")),e({total:g,loaded:f.responseText.length})):f.readyState===f.HEADERS_RECEIVED&&(g=f.getResponseHeader("Content-Length"))};f.open("GET",b,!0);f.send(null)};
+THREE.JSONLoader.prototype.createModel=function(a,b,c){var d=new THREE.Geometry,e=void 0!==a.scale?1/a.scale:1,f,g,h,i,j,l,m,n,p,o,s,t,r,z,w,q=a.faces;o=a.vertices;var E=a.normals,A=a.colors,v=0;for(f=0;f<a.uvs.length;f++)a.uvs[f].length&&v++;for(f=0;f<v;f++)d.faceUvs[f]=[],d.faceVertexUvs[f]=[];i=0;for(j=o.length;i<j;)l=new THREE.Vector3,l.x=o[i++]*e,l.y=o[i++]*e,l.z=o[i++]*e,d.vertices.push(l);i=0;for(j=q.length;i<j;){o=q[i++];l=o&1;h=o&2;f=o&4;g=o&8;n=o&16;m=o&32;s=o&64;o&=128;l?(t=new THREE.Face4,
+t.a=q[i++],t.b=q[i++],t.c=q[i++],t.d=q[i++],l=4):(t=new THREE.Face3,t.a=q[i++],t.b=q[i++],t.c=q[i++],l=3);h&&(h=q[i++],t.materialIndex=h);h=d.faces.length;if(f)for(f=0;f<v;f++)r=a.uvs[f],p=q[i++],w=r[2*p],p=r[2*p+1],d.faceUvs[f][h]=new THREE.UV(w,p);if(g)for(f=0;f<v;f++){r=a.uvs[f];z=[];for(g=0;g<l;g++)p=q[i++],w=r[2*p],p=r[2*p+1],z[g]=new THREE.UV(w,p);d.faceVertexUvs[f][h]=z}n&&(n=3*q[i++],g=new THREE.Vector3,g.x=E[n++],g.y=E[n++],g.z=E[n],t.normal=g);if(m)for(f=0;f<l;f++)n=3*q[i++],g=new THREE.Vector3,
+g.x=E[n++],g.y=E[n++],g.z=E[n],t.vertexNormals.push(g);s&&(m=q[i++],m=new THREE.Color(A[m]),t.color=m);if(o)for(f=0;f<l;f++)m=q[i++],m=new THREE.Color(A[m]),t.vertexColors.push(m);d.faces.push(t)}if(a.skinWeights){i=0;for(j=a.skinWeights.length;i<j;i+=2)q=a.skinWeights[i],E=a.skinWeights[i+1],d.skinWeights.push(new THREE.Vector4(q,E,0,0))}if(a.skinIndices){i=0;for(j=a.skinIndices.length;i<j;i+=2)q=a.skinIndices[i],E=a.skinIndices[i+1],d.skinIndices.push(new THREE.Vector4(q,E,0,0))}d.bones=a.bones;
+d.animation=a.animation;if(void 0!==a.morphTargets){i=0;for(j=a.morphTargets.length;i<j;i++){d.morphTargets[i]={};d.morphTargets[i].name=a.morphTargets[i].name;d.morphTargets[i].vertices=[];A=d.morphTargets[i].vertices;v=a.morphTargets[i].vertices;q=0;for(E=v.length;q<E;q+=3)o=new THREE.Vector3,o.x=v[q]*e,o.y=v[q+1]*e,o.z=v[q+2]*e,A.push(o)}}if(void 0!==a.morphColors){i=0;for(j=a.morphColors.length;i<j;i++){d.morphColors[i]={};d.morphColors[i].name=a.morphColors[i].name;d.morphColors[i].colors=[];
+E=d.morphColors[i].colors;A=a.morphColors[i].colors;e=0;for(q=A.length;e<q;e+=3)v=new THREE.Color(16755200),v.setRGB(A[e],A[e+1],A[e+2]),E.push(v)}}d.computeCentroids();d.computeFaceNormals();a=this.initMaterials(a.materials,c);this.needsTangents(a)&&d.computeTangents();b(d,a)};
+THREE.LoadingMonitor=function(){THREE.EventTarget.call(this);var a=this,b=0,c=0,d=function(){b++;a.dispatchEvent({type:"progress",loaded:b,total:c});b===c&&a.dispatchEvent({type:"load"})};this.add=function(a){c++;a.addEventListener("load",d,!1)}};
+THREE.SceneLoader=function(){this.onLoadStart=function(){};this.onLoadProgress=function(){};this.onLoadComplete=function(){};this.callbackSync=function(){};this.callbackProgress=function(){};this.geometryHandlerMap={};this.hierarchyHandlerMap={};this.addGeometryHandler("ascii",THREE.JSONLoader);this.addGeometryHandler("binary",THREE.BinaryLoader)};THREE.SceneLoader.prototype.constructor=THREE.SceneLoader;
+THREE.SceneLoader.prototype.load=function(a,b){var c=this,d=new XMLHttpRequest;d.onreadystatechange=function(){if(4===d.readyState)if(200===d.status||0===d.status){var e=JSON.parse(d.responseText);c.parse(e,b,a)}else console.error("THREE.SceneLoader: Couldn't load ["+a+"] ["+d.status+"]")};d.open("GET",a,!0);d.send(null)};THREE.SceneLoader.prototype.addGeometryHandler=function(a,b){this.geometryHandlerMap[a]={loaderClass:b}};
+THREE.SceneLoader.prototype.addHierarchyHandler=function(a,b){this.hierarchyHandlerMap[a]={loaderClass:b}};
+THREE.SceneLoader.prototype.parse=function(a,b,c){function d(a,b){return"relativeToHTML"==b?a:m+"/"+a}function e(){f(M.scene,Q.objects)}function f(a,b){for(var c in b)if(void 0===M.objects[c]){var e=b[c],g=null;if(e.type&&e.type in l.hierarchyHandlerMap&&void 0===e.loading){var i={},j;for(j in t)"type"!==j&&"url"!==j&&(i[j]=t[j]);C=M.materials[e.material];e.loading=!0;var n=l.hierarchyHandlerMap[e.type].loaderObject;n.addEventListener?(n.addEventListener("load",h(c,a,C,e)),n.load(d(e.url,Q.urlBaseType))):
+n.options?n.load(d(e.url,Q.urlBaseType),h(c,a,C,e)):n.load(d(e.url,Q.urlBaseType),h(c,a,C,e),i)}else if(void 0!==e.geometry){if(D=M.geometries[e.geometry]){g=!1;C=M.materials[e.material];g=C instanceof THREE.ShaderMaterial;w=e.position;q=e.rotation;E=e.quaternion;A=e.scale;r=e.matrix;E=0;e.material||(C=new THREE.MeshFaceMaterial(M.face_materials[e.geometry]));C instanceof THREE.MeshFaceMaterial&&0===C.materials.length&&(C=new THREE.MeshFaceMaterial(M.face_materials[e.geometry]));if(C instanceof THREE.MeshFaceMaterial)for(i=
+0;i<C.materials.length;i++)g=g||C.materials[i]instanceof THREE.ShaderMaterial;g&&D.computeTangents();e.skin?g=new THREE.SkinnedMesh(D,C):e.morph?(g=new THREE.MorphAnimMesh(D,C),void 0!==e.duration&&(g.duration=e.duration),void 0!==e.time&&(g.time=e.time),void 0!==e.mirroredLoop&&(g.mirroredLoop=e.mirroredLoop),C.morphNormals&&D.computeMorphNormals()):g=new THREE.Mesh(D,C);g.name=c;r?(g.matrixAutoUpdate=!1,g.matrix.set(r[0],r[1],r[2],r[3],r[4],r[5],r[6],r[7],r[8],r[9],r[10],r[11],r[12],r[13],r[14],
+r[15])):(g.position.set(w[0],w[1],w[2]),E?(g.quaternion.set(E[0],E[1],E[2],E[3]),g.useQuaternion=!0):g.rotation.set(q[0],q[1],q[2]),g.scale.set(A[0],A[1],A[2]));g.visible=e.visible;g.castShadow=e.castShadow;g.receiveShadow=e.receiveShadow;a.add(g);M.objects[c]=g}}else"DirectionalLight"===e.type||"PointLight"===e.type||"AmbientLight"===e.type?(H=void 0!==e.color?e.color:16777215,I=void 0!==e.intensity?e.intensity:1,"DirectionalLight"===e.type?(w=e.direction,K=new THREE.DirectionalLight(H,I),K.position.set(w[0],
+w[1],w[2]),e.target&&(J.push({object:K,targetName:e.target}),K.target=null)):"PointLight"===e.type?(w=e.position,z=e.distance,K=new THREE.PointLight(H,I,z),K.position.set(w[0],w[1],w[2])):"AmbientLight"===e.type&&(K=new THREE.AmbientLight(H)),a.add(K),K.name=c,M.lights[c]=K,M.objects[c]=K):"PerspectiveCamera"===e.type||"OrthographicCamera"===e.type?("PerspectiveCamera"===e.type?G=new THREE.PerspectiveCamera(e.fov,e.aspect,e.near,e.far):"OrthographicCamera"===e.type&&(G=new THREE.OrthographicCamera(v.left,
+v.right,v.top,v.bottom,v.near,v.far)),w=e.position,G.position.set(w[0],w[1],w[2]),a.add(G),G.name=c,M.cameras[c]=G,M.objects[c]=G):(w=e.position,q=e.rotation,E=e.quaternion,A=e.scale,E=0,g=new THREE.Object3D,g.name=c,g.position.set(w[0],w[1],w[2]),E?(g.quaternion.set(E[0],E[1],E[2],E[3]),g.useQuaternion=!0):g.rotation.set(q[0],q[1],q[2]),g.scale.set(A[0],A[1],A[2]),g.visible=void 0!==e.visible?e.visible:!1,a.add(g),M.objects[c]=g,M.empties[c]=g);if(g){if(void 0!==e.properties)for(var m in e.properties)g.properties[m]=
+e.properties[m];void 0!==e.children&&f(g,e.children)}}}function g(a){return function(b,c){M.geometries[a]=b;M.face_materials[a]=c;e();N-=1;l.onLoadComplete();j()}}function h(a,b,c,d){return function(f){var f=f.content?f.content:f.dae?f.scene:f,g=d.position,h=d.rotation,i=d.quaternion,n=d.scale;f.position.set(g[0],g[1],g[2]);i?(f.quaternion.set(i[0],i[1],i[2],i[3]),f.useQuaternion=!0):f.rotation.set(h[0],h[1],h[2]);f.scale.set(n[0],n[1],n[2]);c&&f.traverse(function(a){a.material=c});b.add(f);M.objects[a]=
+f;e();N-=1;l.onLoadComplete();j()}}function i(a){return function(b,c){M.geometries[a]=b;M.face_materials[a]=c}}function j(){l.callbackProgress({totalModels:R,totalTextures:ga,loadedModels:R-N,loadedTextures:ga-O},M);l.onLoadProgress();if(0===N&&0===O){for(var a=0;a<J.length;a++){var c=J[a],d=M.objects[c.targetName];d?c.object.target=d:(c.object.target=new THREE.Object3D,M.scene.add(c.object.target));c.object.target.properties.targetInverse=c.object}b(M)}}var l=this,m=THREE.Loader.prototype.extractUrlBase(c),
+n,p,o,s,t,r,z,w,q,E,A,v,u,D,C,G,P,B,K,H,I,N,O,R,ga,M,J=[],Q=a,Z;for(Z in this.geometryHandlerMap)a=this.geometryHandlerMap[Z].loaderClass,this.geometryHandlerMap[Z].loaderObject=new a;for(Z in this.hierarchyHandlerMap)a=this.hierarchyHandlerMap[Z].loaderClass,this.hierarchyHandlerMap[Z].loaderObject=new a;O=N=0;M={scene:new THREE.Scene,geometries:{},face_materials:{},materials:{},textures:{},objects:{},cameras:{},lights:{},fogs:{},empties:{}};if(Q.transform&&(Z=Q.transform.position,a=Q.transform.rotation,
+c=Q.transform.scale,Z&&M.scene.position.set(Z[0],Z[1],Z[2]),a&&M.scene.rotation.set(a[0],a[1],a[2]),c&&M.scene.scale.set(c[0],c[1],c[2]),Z||a||c))M.scene.updateMatrix(),M.scene.updateMatrixWorld();Z=function(a){return function(){O-=a;j();l.onLoadComplete()}};for(o in Q.fogs)a=Q.fogs[o],"linear"===a.type?P=new THREE.Fog(0,a.near,a.far):"exp2"===a.type&&(P=new THREE.FogExp2(0,a.density)),v=a.color,P.color.setRGB(v[0],v[1],v[2]),M.fogs[o]=P;for(n in Q.geometries)t=Q.geometries[n],t.type in this.geometryHandlerMap&&
+(N+=1,l.onLoadStart());for(var L in Q.objects)o=Q.objects[L],o.type&&o.type in this.hierarchyHandlerMap&&(N+=1,l.onLoadStart());R=N;for(n in Q.geometries)if(t=Q.geometries[n],"cube"===t.type)D=new THREE.CubeGeometry(t.width,t.height,t.depth,t.widthSegments,t.heightSegments,t.depthSegments),M.geometries[n]=D;else if("plane"===t.type)D=new THREE.PlaneGeometry(t.width,t.height,t.widthSegments,t.heightSegments),M.geometries[n]=D;else if("sphere"===t.type)D=new THREE.SphereGeometry(t.radius,t.widthSegments,
+t.heightSegments),M.geometries[n]=D;else if("cylinder"===t.type)D=new THREE.CylinderGeometry(t.topRad,t.botRad,t.height,t.radSegs,t.heightSegs),M.geometries[n]=D;else if("torus"===t.type)D=new THREE.TorusGeometry(t.radius,t.tube,t.segmentsR,t.segmentsT),M.geometries[n]=D;else if("icosahedron"===t.type)D=new THREE.IcosahedronGeometry(t.radius,t.subdivisions),M.geometries[n]=D;else if(t.type in this.geometryHandlerMap){L={};for(B in t)"type"!==B&&"url"!==B&&(L[B]=t[B]);this.geometryHandlerMap[t.type].loaderObject.load(d(t.url,
+Q.urlBaseType),g(n),L)}else"embedded"===t.type&&(L=Q.embeds[t.id],L.metadata=Q.metadata,L&&this.geometryHandlerMap.ascii.loaderObject.createModel(L,i(n),""));for(s in Q.textures)if(n=Q.textures[s],n.url instanceof Array){O+=n.url.length;for(B=0;B<n.url.length;B++)l.onLoadStart()}else O+=1,l.onLoadStart();ga=O;for(s in Q.textures){n=Q.textures[s];void 0!==n.mapping&&void 0!==THREE[n.mapping]&&(n.mapping=new THREE[n.mapping]);if(n.url instanceof Array){L=n.url.length;o=[];for(B=0;B<L;B++)o[B]=d(n.url[B],
+Q.urlBaseType);B=(B=o[0].endsWith(".dds"))?THREE.ImageUtils.loadCompressedTextureCube(o,n.mapping,Z(L)):THREE.ImageUtils.loadTextureCube(o,n.mapping,Z(L))}else{B=n.url.toLowerCase().endsWith(".dds");L=d(n.url,Q.urlBaseType);o=Z(1);B=B?THREE.ImageUtils.loadCompressedTexture(L,n.mapping,o):THREE.ImageUtils.loadTexture(L,n.mapping,o);void 0!==THREE[n.minFilter]&&(B.minFilter=THREE[n.minFilter]);void 0!==THREE[n.magFilter]&&(B.magFilter=THREE[n.magFilter]);n.anisotropy&&(B.anisotropy=n.anisotropy);if(n.repeat&&
+(B.repeat.set(n.repeat[0],n.repeat[1]),1!==n.repeat[0]&&(B.wrapS=THREE.RepeatWrapping),1!==n.repeat[1]))B.wrapT=THREE.RepeatWrapping;n.offset&&B.offset.set(n.offset[0],n.offset[1]);if(n.wrap&&(L={repeat:THREE.RepeatWrapping,mirror:THREE.MirroredRepeatWrapping},void 0!==L[n.wrap[0]]&&(B.wrapS=L[n.wrap[0]]),void 0!==L[n.wrap[1]]))B.wrapT=L[n.wrap[1]]}M.textures[s]=B}for(p in Q.materials){r=Q.materials[p];for(u in r.parameters)"envMap"===u||"map"===u||"lightMap"===u||"bumpMap"===u?r.parameters[u]=M.textures[r.parameters[u]]:
+"shading"===u?r.parameters[u]="flat"===r.parameters[u]?THREE.FlatShading:THREE.SmoothShading:"side"===u?r.parameters[u]="double"==r.parameters[u]?THREE.DoubleSide:"back"==r.parameters[u]?THREE.BackSide:THREE.FrontSide:"blending"===u?r.parameters[u]=r.parameters[u]in THREE?THREE[r.parameters[u]]:THREE.NormalBlending:"combine"===u?r.parameters[u]="MixOperation"==r.parameters[u]?THREE.MixOperation:THREE.MultiplyOperation:"vertexColors"===u?"face"==r.parameters[u]?r.parameters[u]=THREE.FaceColors:r.parameters[u]&&
+(r.parameters[u]=THREE.VertexColors):"wrapRGB"===u&&(s=r.parameters[u],r.parameters[u]=new THREE.Vector3(s[0],s[1],s[2]));void 0!==r.parameters.opacity&&1>r.parameters.opacity&&(r.parameters.transparent=!0);r.parameters.normalMap?(s=THREE.ShaderUtils.lib.normal,Z=THREE.UniformsUtils.clone(s.uniforms),n=r.parameters.color,B=r.parameters.specular,L=r.parameters.ambient,o=r.parameters.shininess,Z.tNormal.value=M.textures[r.parameters.normalMap],r.parameters.normalScale&&Z.uNormalScale.value.set(r.parameters.normalScale[0],
+r.parameters.normalScale[1]),r.parameters.map&&(Z.tDiffuse.value=r.parameters.map,Z.enableDiffuse.value=!0),r.parameters.envMap&&(Z.tCube.value=r.parameters.envMap,Z.enableReflection.value=!0,Z.uReflectivity.value=r.parameters.reflectivity),r.parameters.lightMap&&(Z.tAO.value=r.parameters.lightMap,Z.enableAO.value=!0),r.parameters.specularMap&&(Z.tSpecular.value=M.textures[r.parameters.specularMap],Z.enableSpecular.value=!0),r.parameters.displacementMap&&(Z.tDisplacement.value=M.textures[r.parameters.displacementMap],
+Z.enableDisplacement.value=!0,Z.uDisplacementBias.value=r.parameters.displacementBias,Z.uDisplacementScale.value=r.parameters.displacementScale),Z.uDiffuseColor.value.setHex(n),Z.uSpecularColor.value.setHex(B),Z.uAmbientColor.value.setHex(L),Z.uShininess.value=o,r.parameters.opacity&&(Z.uOpacity.value=r.parameters.opacity),C=new THREE.ShaderMaterial({fragmentShader:s.fragmentShader,vertexShader:s.vertexShader,uniforms:Z,lights:!0,fog:!0})):C=new THREE[r.type](r.parameters);M.materials[p]=C}for(p in Q.materials)if(r=
+Q.materials[p],r.parameters.materials){u=[];for(B=0;B<r.parameters.materials.length;B++)u.push(M.materials[r.parameters.materials[B]]);M.materials[p].materials=u}e();M.cameras&&Q.defaults.camera&&(M.currentCamera=M.cameras[Q.defaults.camera]);M.fogs&&Q.defaults.fog&&(M.scene.fog=M.fogs[Q.defaults.fog]);v=Q.defaults.bgcolor;M.bgColor=new THREE.Color;M.bgColor.setRGB(v[0],v[1],v[2]);M.bgColorAlpha=Q.defaults.bgalpha;l.callbackSync(M);j()};
+THREE.TextureLoader=function(){THREE.EventTarget.call(this);this.crossOrigin=null};THREE.TextureLoader.prototype={constructor:THREE.TextureLoader,load:function(a){var b=this,c=new Image;c.addEventListener("load",function(){var a=new THREE.Texture(c);a.needsUpdate=!0;b.dispatchEvent({type:"load",content:a})},!1);c.addEventListener("error",function(){b.dispatchEvent({type:"error",message:"Couldn't load URL ["+a+"]"})},!1);b.crossOrigin&&(c.crossOrigin=b.crossOrigin);c.src=a}};
+THREE.Material=function(){THREE.MaterialLibrary.push(this);this.id=THREE.MaterialIdCount++;this.name="";this.side=THREE.FrontSide;this.opacity=1;this.transparent=!1;this.blending=THREE.NormalBlending;this.blendSrc=THREE.SrcAlphaFactor;this.blendDst=THREE.OneMinusSrcAlphaFactor;this.blendEquation=THREE.AddEquation;this.depthWrite=this.depthTest=!0;this.polygonOffset=!1;this.alphaTest=this.polygonOffsetUnits=this.polygonOffsetFactor=0;this.overdraw=!1;this.needsUpdate=this.visible=!0};
+THREE.Material.prototype.setValues=function(a){if(void 0!==a)for(var b in a){var c=a[b];if(void 0===c)console.warn("THREE.Material: '"+b+"' parameter is undefined.");else if(b in this){var d=this[b];d instanceof THREE.Color&&c instanceof THREE.Color?d.copy(c):d instanceof THREE.Color&&"number"===typeof c?d.setHex(c):d instanceof THREE.Vector3&&c instanceof THREE.Vector3?d.copy(c):this[b]=c}}};
+THREE.Material.prototype.clone=function(a){void 0===a&&(a=new THREE.Material);a.name=this.name;a.side=this.side;a.opacity=this.opacity;a.transparent=this.transparent;a.blending=this.blending;a.blendSrc=this.blendSrc;a.blendDst=this.blendDst;a.blendEquation=this.blendEquation;a.depthTest=this.depthTest;a.depthWrite=this.depthWrite;a.polygonOffset=this.polygonOffset;a.polygonOffsetFactor=this.polygonOffsetFactor;a.polygonOffsetUnits=this.polygonOffsetUnits;a.alphaTest=this.alphaTest;a.overdraw=this.overdraw;
+a.visible=this.visible;return a};THREE.Material.prototype.deallocate=function(){var a=THREE.MaterialLibrary.indexOf(this);-1!==a&&THREE.MaterialLibrary.splice(a,1)};THREE.MaterialIdCount=0;THREE.MaterialLibrary=[];THREE.LineBasicMaterial=function(a){THREE.Material.call(this);this.color=new THREE.Color(16777215);this.linewidth=1;this.linejoin=this.linecap="round";this.vertexColors=!1;this.fog=!0;this.setValues(a)};THREE.LineBasicMaterial.prototype=Object.create(THREE.Material.prototype);
+THREE.LineBasicMaterial.prototype.clone=function(){var a=new THREE.LineBasicMaterial;THREE.Material.prototype.clone.call(this,a);a.color.copy(this.color);a.linewidth=this.linewidth;a.linecap=this.linecap;a.linejoin=this.linejoin;a.vertexColors=this.vertexColors;a.fog=this.fog;return a};THREE.LineDashedMaterial=function(a){THREE.Material.call(this);this.color=new THREE.Color(16777215);this.scale=this.linewidth=1;this.dashSize=3;this.gapSize=1;this.vertexColors=!1;this.fog=!0;this.setValues(a)};
+THREE.LineDashedMaterial.prototype=Object.create(THREE.Material.prototype);THREE.LineDashedMaterial.prototype.clone=function(){var a=new THREE.LineDashedMaterial;THREE.Material.prototype.clone.call(this,a);a.color.copy(this.color);a.linewidth=this.linewidth;a.scale=this.scale;a.dashSize=this.dashSize;a.gapSize=this.gapSize;a.vertexColors=this.vertexColors;a.fog=this.fog;return a};
+THREE.MeshBasicMaterial=function(a){THREE.Material.call(this);this.color=new THREE.Color(16777215);this.envMap=this.specularMap=this.lightMap=this.map=null;this.combine=THREE.MultiplyOperation;this.reflectivity=1;this.refractionRatio=0.98;this.fog=!0;this.shading=THREE.SmoothShading;this.wireframe=!1;this.wireframeLinewidth=1;this.wireframeLinejoin=this.wireframeLinecap="round";this.vertexColors=THREE.NoColors;this.morphTargets=this.skinning=!1;this.setValues(a)};
+THREE.MeshBasicMaterial.prototype=Object.create(THREE.Material.prototype);
+THREE.MeshBasicMaterial.prototype.clone=function(){var a=new THREE.MeshBasicMaterial;THREE.Material.prototype.clone.call(this,a);a.color.copy(this.color);a.map=this.map;a.lightMap=this.lightMap;a.specularMap=this.specularMap;a.envMap=this.envMap;a.combine=this.combine;a.reflectivity=this.reflectivity;a.refractionRatio=this.refractionRatio;a.fog=this.fog;a.shading=this.shading;a.wireframe=this.wireframe;a.wireframeLinewidth=this.wireframeLinewidth;a.wireframeLinecap=this.wireframeLinecap;a.wireframeLinejoin=
+this.wireframeLinejoin;a.vertexColors=this.vertexColors;a.skinning=this.skinning;a.morphTargets=this.morphTargets;return a};
+THREE.MeshLambertMaterial=function(a){THREE.Material.call(this);this.color=new THREE.Color(16777215);this.ambient=new THREE.Color(16777215);this.emissive=new THREE.Color(0);this.wrapAround=!1;this.wrapRGB=new THREE.Vector3(1,1,1);this.envMap=this.specularMap=this.lightMap=this.map=null;this.combine=THREE.MultiplyOperation;this.reflectivity=1;this.refractionRatio=0.98;this.fog=!0;this.shading=THREE.SmoothShading;this.wireframe=!1;this.wireframeLinewidth=1;this.wireframeLinejoin=this.wireframeLinecap=
+"round";this.vertexColors=THREE.NoColors;this.morphNormals=this.morphTargets=this.skinning=!1;this.setValues(a)};THREE.MeshLambertMaterial.prototype=Object.create(THREE.Material.prototype);
+THREE.MeshLambertMaterial.prototype.clone=function(){var a=new THREE.MeshLambertMaterial;THREE.Material.prototype.clone.call(this,a);a.color.copy(this.color);a.ambient.copy(this.ambient);a.emissive.copy(this.emissive);a.wrapAround=this.wrapAround;a.wrapRGB.copy(this.wrapRGB);a.map=this.map;a.lightMap=this.lightMap;a.specularMap=this.specularMap;a.envMap=this.envMap;a.combine=this.combine;a.reflectivity=this.reflectivity;a.refractionRatio=this.refractionRatio;a.fog=this.fog;a.shading=this.shading;
+a.wireframe=this.wireframe;a.wireframeLinewidth=this.wireframeLinewidth;a.wireframeLinecap=this.wireframeLinecap;a.wireframeLinejoin=this.wireframeLinejoin;a.vertexColors=this.vertexColors;a.skinning=this.skinning;a.morphTargets=this.morphTargets;a.morphNormals=this.morphNormals;return a};
+THREE.MeshPhongMaterial=function(a){THREE.Material.call(this);this.color=new THREE.Color(16777215);this.ambient=new THREE.Color(16777215);this.emissive=new THREE.Color(0);this.specular=new THREE.Color(1118481);this.shininess=30;this.metal=!1;this.perPixel=!0;this.wrapAround=!1;this.wrapRGB=new THREE.Vector3(1,1,1);this.bumpMap=this.lightMap=this.map=null;this.bumpScale=1;this.normalMap=null;this.normalScale=new THREE.Vector2(1,1);this.envMap=this.specularMap=null;this.combine=THREE.MultiplyOperation;
+this.reflectivity=1;this.refractionRatio=0.98;this.fog=!0;this.shading=THREE.SmoothShading;this.wireframe=!1;this.wireframeLinewidth=1;this.wireframeLinejoin=this.wireframeLinecap="round";this.vertexColors=THREE.NoColors;this.morphNormals=this.morphTargets=this.skinning=!1;this.setValues(a)};THREE.MeshPhongMaterial.prototype=Object.create(THREE.Material.prototype);
+THREE.MeshPhongMaterial.prototype.clone=function(){var a=new THREE.MeshPhongMaterial;THREE.Material.prototype.clone.call(this,a);a.color.copy(this.color);a.ambient.copy(this.ambient);a.emissive.copy(this.emissive);a.specular.copy(this.specular);a.shininess=this.shininess;a.metal=this.metal;a.perPixel=this.perPixel;a.wrapAround=this.wrapAround;a.wrapRGB.copy(this.wrapRGB);a.map=this.map;a.lightMap=this.lightMap;a.bumpMap=this.bumpMap;a.bumpScale=this.bumpScale;a.normalMap=this.normalMap;a.normalScale.copy(this.normalScale);
+a.specularMap=this.specularMap;a.envMap=this.envMap;a.combine=this.combine;a.reflectivity=this.reflectivity;a.refractionRatio=this.refractionRatio;a.fog=this.fog;a.shading=this.shading;a.wireframe=this.wireframe;a.wireframeLinewidth=this.wireframeLinewidth;a.wireframeLinecap=this.wireframeLinecap;a.wireframeLinejoin=this.wireframeLinejoin;a.vertexColors=this.vertexColors;a.skinning=this.skinning;a.morphTargets=this.morphTargets;a.morphNormals=this.morphNormals;return a};
+THREE.MeshDepthMaterial=function(a){THREE.Material.call(this);this.wireframe=!1;this.wireframeLinewidth=1;this.setValues(a)};THREE.MeshDepthMaterial.prototype=Object.create(THREE.Material.prototype);THREE.MeshDepthMaterial.prototype.clone=function(){var a=new THREE.LineBasicMaterial;THREE.Material.prototype.clone.call(this,a);a.wireframe=this.wireframe;a.wireframeLinewidth=this.wireframeLinewidth;return a};
+THREE.MeshNormalMaterial=function(a){THREE.Material.call(this,a);this.shading=THREE.FlatShading;this.wireframe=!1;this.wireframeLinewidth=1;this.setValues(a)};THREE.MeshNormalMaterial.prototype=Object.create(THREE.Material.prototype);THREE.MeshNormalMaterial.prototype.clone=function(){var a=new THREE.MeshNormalMaterial;THREE.Material.prototype.clone.call(this,a);a.shading=this.shading;a.wireframe=this.wireframe;a.wireframeLinewidth=this.wireframeLinewidth;return a};
+THREE.MeshFaceMaterial=function(a){this.materials=a instanceof Array?a:[]};THREE.MeshFaceMaterial.prototype.clone=function(){return new THREE.MeshFaceMaterial(this.materials.slice(0))};THREE.ParticleBasicMaterial=function(a){THREE.Material.call(this);this.color=new THREE.Color(16777215);this.map=null;this.size=1;this.sizeAttenuation=!0;this.vertexColors=!1;this.fog=!0;this.setValues(a)};THREE.ParticleBasicMaterial.prototype=Object.create(THREE.Material.prototype);
+THREE.ParticleBasicMaterial.prototype.clone=function(){var a=new THREE.ParticleBasicMaterial;THREE.Material.prototype.clone.call(this,a);a.color.copy(this.color);a.map=this.map;a.size=this.size;a.sizeAttenuation=this.sizeAttenuation;a.vertexColors=this.vertexColors;a.fog=this.fog;return a};THREE.ParticleCanvasMaterial=function(a){THREE.Material.call(this);this.color=new THREE.Color(16777215);this.program=function(){};this.setValues(a)};THREE.ParticleCanvasMaterial.prototype=Object.create(THREE.Material.prototype);
+THREE.ParticleCanvasMaterial.prototype.clone=function(){var a=new THREE.ParticleCanvasMaterial;THREE.Material.prototype.clone.call(this,a);a.color.copy(this.color);a.program=this.program;return a};THREE.ParticleDOMMaterial=function(a){this.element=a};THREE.ParticleDOMMaterial.prototype.clone=function(){return new THREE.ParticleDOMMaterial(this.element)};
+THREE.ShaderMaterial=function(a){THREE.Material.call(this);this.vertexShader=this.fragmentShader="void main() {}";this.uniforms={};this.defines={};this.attributes=null;this.shading=THREE.SmoothShading;this.wireframe=!1;this.wireframeLinewidth=1;this.lights=this.fog=!1;this.vertexColors=THREE.NoColors;this.morphNormals=this.morphTargets=this.skinning=!1;this.setValues(a)};THREE.ShaderMaterial.prototype=Object.create(THREE.Material.prototype);
+THREE.ShaderMaterial.prototype.clone=function(){var a=new THREE.ShaderMaterial;THREE.Material.prototype.clone.call(this,a);a.fragmentShader=this.fragmentShader;a.vertexShader=this.vertexShader;a.uniforms=THREE.UniformsUtils.clone(this.uniforms);a.attributes=this.attributes;a.defines=this.defines;a.shading=this.shading;a.wireframe=this.wireframe;a.wireframeLinewidth=this.wireframeLinewidth;a.fog=this.fog;a.lights=this.lights;a.vertexColors=this.vertexColors;a.skinning=this.skinning;a.morphTargets=
+this.morphTargets;a.morphNormals=this.morphNormals;return a};
+THREE.Texture=function(a,b,c,d,e,f,g,h,i){THREE.TextureLibrary.push(this);this.id=THREE.TextureIdCount++;this.name="";this.image=a;this.mapping=void 0!==b?b:new THREE.UVMapping;this.wrapS=void 0!==c?c:THREE.ClampToEdgeWrapping;this.wrapT=void 0!==d?d:THREE.ClampToEdgeWrapping;this.magFilter=void 0!==e?e:THREE.LinearFilter;this.minFilter=void 0!==f?f:THREE.LinearMipMapLinearFilter;this.anisotropy=void 0!==i?i:1;this.format=void 0!==g?g:THREE.RGBAFormat;this.type=void 0!==h?h:THREE.UnsignedByteType;
+this.offset=new THREE.Vector2(0,0);this.repeat=new THREE.Vector2(1,1);this.generateMipmaps=!0;this.premultiplyAlpha=!1;this.flipY=!0;this.needsUpdate=!1;this.onUpdate=null};
+THREE.Texture.prototype={constructor:THREE.Texture,clone:function(){var a=new THREE.Texture;a.image=this.image;a.mapping=this.mapping;a.wrapS=this.wrapS;a.wrapT=this.wrapT;a.magFilter=this.magFilter;a.minFilter=this.minFilter;a.anisotropy=this.anisotropy;a.format=this.format;a.type=this.type;a.offset.copy(this.offset);a.repeat.copy(this.repeat);a.generateMipmaps=this.generateMipmaps;a.premultiplyAlpha=this.premultiplyAlpha;a.flipY=this.flipY;return a},deallocate:function(){var a=THREE.TextureLibrary.indexOf(this);
+-1!==a&&THREE.TextureLibrary.splice(a,1)}};THREE.TextureIdCount=0;THREE.TextureLibrary=[];THREE.CompressedTexture=function(a,b,c,d,e,f,g,h,i,j){THREE.Texture.call(this,null,f,g,h,i,j,d,e);this.image={width:b,height:c};this.mipmaps=a};THREE.CompressedTexture.prototype=Object.create(THREE.Texture.prototype);
+THREE.CompressedTexture.prototype.clone=function(){var a=new THREE.CompressedTexture;a.image=this.image;a.mipmaps=this.mipmaps;a.format=this.format;a.type=this.type;a.mapping=this.mapping;a.wrapS=this.wrapS;a.wrapT=this.wrapT;a.magFilter=this.magFilter;a.minFilter=this.minFilter;a.anisotropy=this.anisotropy;a.offset.copy(this.offset);a.repeat.copy(this.repeat);return a};THREE.DataTexture=function(a,b,c,d,e,f,g,h,i,j){THREE.Texture.call(this,null,f,g,h,i,j,d,e);this.image={data:a,width:b,height:c}};
+THREE.DataTexture.prototype=Object.create(THREE.Texture.prototype);THREE.DataTexture.prototype.clone=function(){var a=new THREE.DataTexture(this.image.data,this.image.width,this.image.height,this.format,this.type,this.mapping,this.wrapS,this.wrapT,this.magFilter,this.minFilter);a.offset.copy(this.offset);a.repeat.copy(this.repeat);return a};THREE.Particle=function(a){THREE.Object3D.call(this);this.material=a};THREE.Particle.prototype=Object.create(THREE.Object3D.prototype);
+THREE.Particle.prototype.clone=function(a){void 0===a&&(a=new THREE.Particle(this.material));THREE.Object3D.prototype.clone.call(this,a);return a};THREE.ParticleSystem=function(a,b){THREE.Object3D.call(this);this.geometry=a;this.material=void 0!==b?b:new THREE.ParticleBasicMaterial({color:16777215*Math.random()});this.sortParticles=!1;this.geometry&&(null===this.geometry.boundingSphere&&this.geometry.computeBoundingSphere(),this.boundRadius=a.boundingSphere.radius);this.frustumCulled=!1};
+THREE.ParticleSystem.prototype=Object.create(THREE.Object3D.prototype);THREE.ParticleSystem.prototype.clone=function(a){void 0===a&&(a=new THREE.ParticleSystem(this.geometry,this.material));a.sortParticles=this.sortParticles;THREE.Object3D.prototype.clone.call(this,a);return a};
+THREE.Line=function(a,b,c){THREE.Object3D.call(this);this.geometry=a;this.material=void 0!==b?b:new THREE.LineBasicMaterial({color:16777215*Math.random()});this.type=void 0!==c?c:THREE.LineStrip;this.geometry&&(this.geometry.boundingSphere||this.geometry.computeBoundingSphere())};THREE.LineStrip=0;THREE.LinePieces=1;THREE.Line.prototype=Object.create(THREE.Object3D.prototype);
+THREE.Line.prototype.clone=function(a){void 0===a&&(a=new THREE.Line(this.geometry,this.material,this.type));THREE.Object3D.prototype.clone.call(this,a);return a};
+THREE.Mesh=function(a,b){THREE.Object3D.call(this);this.geometry=a;this.material=void 0!==b?b:new THREE.MeshBasicMaterial({color:16777215*Math.random(),wireframe:!0});if(this.geometry&&(null===this.geometry.boundingSphere&&this.geometry.computeBoundingSphere(),this.boundRadius=a.boundingSphere.radius,this.geometry.morphTargets.length)){this.morphTargetBase=-1;this.morphTargetForcedOrder=[];this.morphTargetInfluences=[];this.morphTargetDictionary={};for(var c=0;c<this.geometry.morphTargets.length;c++)this.morphTargetInfluences.push(0),
+this.morphTargetDictionary[this.geometry.morphTargets[c].name]=c}};THREE.Mesh.prototype=Object.create(THREE.Object3D.prototype);THREE.Mesh.prototype.getMorphTargetIndexByName=function(a){if(void 0!==this.morphTargetDictionary[a])return this.morphTargetDictionary[a];console.log("THREE.Mesh.getMorphTargetIndexByName: morph target "+a+" does not exist. Returning 0.");return 0};
+THREE.Mesh.prototype.clone=function(a){void 0===a&&(a=new THREE.Mesh(this.geometry,this.material));THREE.Object3D.prototype.clone.call(this,a);return a};THREE.Bone=function(a){THREE.Object3D.call(this);this.skin=a;this.skinMatrix=new THREE.Matrix4};THREE.Bone.prototype=Object.create(THREE.Object3D.prototype);
+THREE.Bone.prototype.update=function(a,b){this.matrixAutoUpdate&&(b|=this.updateMatrix());if(b||this.matrixWorldNeedsUpdate)a?this.skinMatrix.multiply(a,this.matrix):this.skinMatrix.copy(this.matrix),this.matrixWorldNeedsUpdate=!1,b=!0;var c,d=this.children.length;for(c=0;c<d;c++)this.children[c].update(this.skinMatrix,b)};
+THREE.SkinnedMesh=function(a,b,c){THREE.Mesh.call(this,a,b);this.useVertexTexture=void 0!==c?c:!0;this.identityMatrix=new THREE.Matrix4;this.bones=[];this.boneMatrices=[];var d,e,f;if(this.geometry&&void 0!==this.geometry.bones){for(a=0;a<this.geometry.bones.length;a++)c=this.geometry.bones[a],d=c.pos,e=c.rotq,f=c.scl,b=this.addBone(),b.name=c.name,b.position.set(d[0],d[1],d[2]),b.quaternion.set(e[0],e[1],e[2],e[3]),b.useQuaternion=!0,void 0!==f?b.scale.set(f[0],f[1],f[2]):b.scale.set(1,1,1);for(a=
+0;a<this.bones.length;a++)c=this.geometry.bones[a],b=this.bones[a],-1===c.parent?this.add(b):this.bones[c.parent].add(b);a=this.bones.length;this.useVertexTexture?(this.boneTextureHeight=this.boneTextureWidth=a=256<a?64:64<a?32:16<a?16:8,this.boneMatrices=new Float32Array(4*this.boneTextureWidth*this.boneTextureHeight),this.boneTexture=new THREE.DataTexture(this.boneMatrices,this.boneTextureWidth,this.boneTextureHeight,THREE.RGBAFormat,THREE.FloatType),this.boneTexture.minFilter=THREE.NearestFilter,
+this.boneTexture.magFilter=THREE.NearestFilter,this.boneTexture.generateMipmaps=!1,this.boneTexture.flipY=!1):this.boneMatrices=new Float32Array(16*a);this.pose()}};THREE.SkinnedMesh.prototype=Object.create(THREE.Mesh.prototype);THREE.SkinnedMesh.prototype.addBone=function(a){void 0===a&&(a=new THREE.Bone(this));this.bones.push(a);return a};
+THREE.SkinnedMesh.prototype.updateMatrixWorld=function(a){this.matrixAutoUpdate&&this.updateMatrix();if(this.matrixWorldNeedsUpdate||a)this.parent?this.matrixWorld.multiply(this.parent.matrixWorld,this.matrix):this.matrixWorld.copy(this.matrix),this.matrixWorldNeedsUpdate=!1;for(var a=0,b=this.children.length;a<b;a++){var c=this.children[a];c instanceof THREE.Bone?c.update(this.identityMatrix,!1):c.updateMatrixWorld(!0)}if(void 0==this.boneInverses){this.boneInverses=[];a=0;for(b=this.bones.length;a<
+b;a++)c=new THREE.Matrix4,c.getInverse(this.bones[a].skinMatrix),this.boneInverses.push(c)}a=0;for(b=this.bones.length;a<b;a++)THREE.SkinnedMesh.offsetMatrix.multiply(this.bones[a].skinMatrix,this.boneInverses[a]),THREE.SkinnedMesh.offsetMatrix.flattenToArrayOffset(this.boneMatrices,16*a);this.useVertexTexture&&(this.boneTexture.needsUpdate=!0)};
+THREE.SkinnedMesh.prototype.pose=function(){this.updateMatrixWorld(!0);for(var a=0;a<this.geometry.skinIndices.length;a++){var b=this.geometry.skinWeights[a],c=1/b.lengthManhattan();Infinity!==c?b.multiplyScalar(c):b.set(1)}};THREE.SkinnedMesh.prototype.clone=function(a){void 0===a&&(a=new THREE.SkinnedMesh(this.geometry,this.material,this.useVertexTexture));THREE.Mesh.prototype.clone.call(this,a);return a};THREE.SkinnedMesh.offsetMatrix=new THREE.Matrix4;
+THREE.MorphAnimMesh=function(a,b){THREE.Mesh.call(this,a,b);this.duration=1E3;this.mirroredLoop=!1;this.currentKeyframe=this.lastKeyframe=this.time=0;this.direction=1;this.directionBackwards=!1;this.setFrameRange(0,this.geometry.morphTargets.length-1)};THREE.MorphAnimMesh.prototype=Object.create(THREE.Mesh.prototype);THREE.MorphAnimMesh.prototype.setFrameRange=function(a,b){this.startKeyframe=a;this.endKeyframe=b;this.length=this.endKeyframe-this.startKeyframe+1};
+THREE.MorphAnimMesh.prototype.setDirectionForward=function(){this.direction=1;this.directionBackwards=!1};THREE.MorphAnimMesh.prototype.setDirectionBackward=function(){this.direction=-1;this.directionBackwards=!0};
+THREE.MorphAnimMesh.prototype.parseAnimations=function(){var a=this.geometry;a.animations||(a.animations={});for(var b,c=a.animations,d=/([a-z]+)(\d+)/,e=0,f=a.morphTargets.length;e<f;e++){var g=a.morphTargets[e].name.match(d);if(g&&1<g.length){g=g[1];c[g]||(c[g]={start:Infinity,end:-Infinity});var h=c[g];e<h.start&&(h.start=e);e>h.end&&(h.end=e);b||(b=g)}}a.firstAnimation=b};
+THREE.MorphAnimMesh.prototype.setAnimationLabel=function(a,b,c){this.geometry.animations||(this.geometry.animations={});this.geometry.animations[a]={start:b,end:c}};THREE.MorphAnimMesh.prototype.playAnimation=function(a,b){var c=this.geometry.animations[a];c?(this.setFrameRange(c.start,c.end),this.duration=1E3*((c.end-c.start)/b),this.time=0):console.warn("animation["+a+"] undefined")};
+THREE.MorphAnimMesh.prototype.updateAnimation=function(a){var b=this.duration/this.length;this.time+=this.direction*a;if(this.mirroredLoop){if(this.time>this.duration||0>this.time)if(this.direction*=-1,this.time>this.duration&&(this.time=this.duration,this.directionBackwards=!0),0>this.time)this.time=0,this.directionBackwards=!1}else this.time%=this.duration,0>this.time&&(this.time+=this.duration);a=this.startKeyframe+THREE.Math.clamp(Math.floor(this.time/b),0,this.length-1);a!==this.currentKeyframe&&
+(this.morphTargetInfluences[this.lastKeyframe]=0,this.morphTargetInfluences[this.currentKeyframe]=1,this.morphTargetInfluences[a]=0,this.lastKeyframe=this.currentKeyframe,this.currentKeyframe=a);b=this.time%b/b;this.directionBackwards&&(b=1-b);this.morphTargetInfluences[this.currentKeyframe]=b;this.morphTargetInfluences[this.lastKeyframe]=1-b};
+THREE.MorphAnimMesh.prototype.clone=function(a){void 0===a&&(a=new THREE.MorphAnimMesh(this.geometry,this.material));a.duration=this.duration;a.mirroredLoop=this.mirroredLoop;a.time=this.time;a.lastKeyframe=this.lastKeyframe;a.currentKeyframe=this.currentKeyframe;a.direction=this.direction;a.directionBackwards=this.directionBackwards;THREE.Mesh.prototype.clone.call(this,a);return a};THREE.Ribbon=function(a,b){THREE.Object3D.call(this);this.geometry=a;this.material=b};THREE.Ribbon.prototype=Object.create(THREE.Object3D.prototype);
+THREE.Ribbon.prototype.clone=function(a){void 0===a&&(a=new THREE.Ribbon(this.geometry,this.material));THREE.Object3D.prototype.clone.call(this,a);return a};THREE.LOD=function(){THREE.Object3D.call(this);this.LODs=[]};THREE.LOD.prototype=Object.create(THREE.Object3D.prototype);THREE.LOD.prototype.addLevel=function(a,b){void 0===b&&(b=0);for(var b=Math.abs(b),c=0;c<this.LODs.length&&!(b<this.LODs[c].visibleAtDistance);c++);this.LODs.splice(c,0,{visibleAtDistance:b,object3D:a});this.add(a)};
+THREE.LOD.prototype.update=function(a){if(1<this.LODs.length){a.matrixWorldInverse.getInverse(a.matrixWorld);a=a.matrixWorldInverse;a=-(a.elements[2]*this.matrixWorld.elements[12]+a.elements[6]*this.matrixWorld.elements[13]+a.elements[10]*this.matrixWorld.elements[14]+a.elements[14]);this.LODs[0].object3D.visible=!0;for(var b=1;b<this.LODs.length;b++)if(a>=this.LODs[b].visibleAtDistance)this.LODs[b-1].object3D.visible=!1,this.LODs[b].object3D.visible=!0;else break;for(;b<this.LODs.length;b++)this.LODs[b].object3D.visible=
+!1}};THREE.LOD.prototype.clone=function(){};
+THREE.Sprite=function(a){THREE.Object3D.call(this);a=a||{};this.color=void 0!==a.color?new THREE.Color(a.color):new THREE.Color(16777215);this.map=void 0!==a.map?a.map:new THREE.Texture;this.blending=void 0!==a.blending?a.blending:THREE.NormalBlending;this.blendSrc=void 0!==a.blendSrc?a.blendSrc:THREE.SrcAlphaFactor;this.blendDst=void 0!==a.blendDst?a.blendDst:THREE.OneMinusSrcAlphaFactor;this.blendEquation=void 0!==a.blendEquation?a.blendEquation:THREE.AddEquation;this.useScreenCoordinates=void 0!==
+a.useScreenCoordinates?a.useScreenCoordinates:!0;this.mergeWith3D=void 0!==a.mergeWith3D?a.mergeWith3D:!this.useScreenCoordinates;this.affectedByDistance=void 0!==a.affectedByDistance?a.affectedByDistance:!this.useScreenCoordinates;this.scaleByViewport=void 0!==a.scaleByViewport?a.scaleByViewport:!this.affectedByDistance;this.alignment=a.alignment instanceof THREE.Vector2?a.alignment:THREE.SpriteAlignment.center.clone();this.fog=void 0!==a.fog?a.fog:!1;this.rotation3d=this.rotation;this.rotation=
+0;this.opacity=1;this.uvOffset=new THREE.Vector2(0,0);this.uvScale=new THREE.Vector2(1,1)};THREE.Sprite.prototype=Object.create(THREE.Object3D.prototype);THREE.Sprite.prototype.updateMatrix=function(){this.matrix.setPosition(this.position);this.rotation3d.set(0,0,this.rotation);this.matrix.setRotationFromEuler(this.rotation3d);if(1!==this.scale.x||1!==this.scale.y)this.matrix.scale(this.scale),this.boundRadiusScale=Math.max(this.scale.x,this.scale.y);this.matrixWorldNeedsUpdate=!0};
+THREE.Sprite.prototype.clone=function(a){void 0===a&&(a=new THREE.Sprite({}));a.color.copy(this.color);a.map=this.map;a.blending=this.blending;a.useScreenCoordinates=this.useScreenCoordinates;a.mergeWith3D=this.mergeWith3D;a.affectedByDistance=this.affectedByDistance;a.scaleByViewport=this.scaleByViewport;a.alignment=this.alignment;a.fog=this.fog;a.rotation3d.copy(this.rotation3d);a.rotation=this.rotation;a.opacity=this.opacity;a.uvOffset.copy(this.uvOffset);a.uvScale.copy(this.uvScale);THREE.Object3D.prototype.clone.call(this,
+a);return a};THREE.SpriteAlignment={};THREE.SpriteAlignment.topLeft=new THREE.Vector2(1,-1);THREE.SpriteAlignment.topCenter=new THREE.Vector2(0,-1);THREE.SpriteAlignment.topRight=new THREE.Vector2(-1,-1);THREE.SpriteAlignment.centerLeft=new THREE.Vector2(1,0);THREE.SpriteAlignment.center=new THREE.Vector2(0,0);THREE.SpriteAlignment.centerRight=new THREE.Vector2(-1,0);THREE.SpriteAlignment.bottomLeft=new THREE.Vector2(1,1);THREE.SpriteAlignment.bottomCenter=new THREE.Vector2(0,1);
+THREE.SpriteAlignment.bottomRight=new THREE.Vector2(-1,1);THREE.Scene=function(){THREE.Object3D.call(this);this.overrideMaterial=this.fog=null;this.matrixAutoUpdate=!1;this.__objects=[];this.__lights=[];this.__objectsAdded=[];this.__objectsRemoved=[]};THREE.Scene.prototype=Object.create(THREE.Object3D.prototype);
+THREE.Scene.prototype.__addObject=function(a){if(a instanceof THREE.Light)-1===this.__lights.indexOf(a)&&this.__lights.push(a),a.target&&void 0===a.target.parent&&this.add(a.target);else if(!(a instanceof THREE.Camera||a instanceof THREE.Bone)&&-1===this.__objects.indexOf(a)){this.__objects.push(a);this.__objectsAdded.push(a);var b=this.__objectsRemoved.indexOf(a);-1!==b&&this.__objectsRemoved.splice(b,1)}for(b=0;b<a.children.length;b++)this.__addObject(a.children[b])};
+THREE.Scene.prototype.__removeObject=function(a){if(a instanceof THREE.Light){var b=this.__lights.indexOf(a);-1!==b&&this.__lights.splice(b,1)}else a instanceof THREE.Camera||(b=this.__objects.indexOf(a),-1!==b&&(this.__objects.splice(b,1),this.__objectsRemoved.push(a),b=this.__objectsAdded.indexOf(a),-1!==b&&this.__objectsAdded.splice(b,1)));for(b=0;b<a.children.length;b++)this.__removeObject(a.children[b])};
+THREE.Fog=function(a,b,c){this.name="";this.color=new THREE.Color(a);this.near=void 0!==b?b:1;this.far=void 0!==c?c:1E3};THREE.Fog.prototype.clone=function(){return new THREE.Fog(this.color.getHex(),this.near,this.far)};THREE.FogExp2=function(a,b){this.name="";this.color=new THREE.Color(a);this.density=void 0!==b?b:2.5E-4};THREE.FogExp2.prototype.clone=function(){return new THREE.FogExp2(this.color.getHex(),this.density)};
+THREE.CanvasRenderer=function(a){function b(a){z!==a&&(z=s.globalAlpha=a)}function c(a){w!==a&&(a===THREE.NormalBlending?s.globalCompositeOperation="source-over":a===THREE.AdditiveBlending?s.globalCompositeOperation="lighter":a===THREE.SubtractiveBlending&&(s.globalCompositeOperation="darker"),w=a)}function d(a){q!==a&&(q=s.strokeStyle=a)}function e(a){E!==a&&(E=s.fillStyle=a)}console.log("THREE.CanvasRenderer",THREE.REVISION);var a=a||{},f=this,g,h,i,j=new THREE.Projector,l=void 0!==a.canvas?a.canvas:
+document.createElement("canvas"),m,n,p,o,s=l.getContext("2d"),t=new THREE.Color(0),r=0,z=1,w=0,q=null,E=null,A=null,v=null,u=null,D,C,G,P,B=new THREE.RenderableVertex,K=new THREE.RenderableVertex,H,I,N,O,R,ga,M,J,Q,Z,L,oa,X=new THREE.Color,fa=new THREE.Color,ca=new THREE.Color,Y=new THREE.Color,ba=new THREE.Color,aa=new THREE.Color,ia=new THREE.Color,Aa={},Na={},Ja,ma,sa,Ea,rb,ib,ob,jb,Bb,Cb,Wa=new THREE.Rectangle,Sa=new THREE.Rectangle,Ka=new THREE.Rectangle,kb=!1,Oa=new THREE.Color,lb=new THREE.Color,
+ab=new THREE.Color,va=new THREE.Vector3,eb,pb,bb,xa,mb,sb,a=16;eb=document.createElement("canvas");eb.width=eb.height=2;pb=eb.getContext("2d");pb.fillStyle="rgba(0,0,0,1)";pb.fillRect(0,0,2,2);bb=pb.getImageData(0,0,2,2);xa=bb.data;mb=document.createElement("canvas");mb.width=mb.height=a;sb=mb.getContext("2d");sb.translate(-a/2,-a/2);sb.scale(a,a);a--;this.domElement=l;this.sortElements=this.sortObjects=this.autoClear=!0;this.info={render:{vertices:0,faces:0}};this.setSize=function(a,b){m=a;n=b;p=
+Math.floor(m/2);o=Math.floor(n/2);l.width=m;l.height=n;Wa.set(-p,-o,p,o);Sa.set(-p,-o,p,o);z=1;w=0;u=v=A=E=q=null};this.setClearColor=function(a,b){t.copy(a);r=void 0!==b?b:1;Sa.set(-p,-o,p,o)};this.setClearColorHex=function(a,b){t.setHex(a);r=void 0!==b?b:1;Sa.set(-p,-o,p,o)};this.getMaxAnisotropy=function(){return 0};this.clear=function(){s.setTransform(1,0,0,-1,p,o);!1===Sa.isEmpty()&&(Sa.minSelf(Wa),Sa.inflate(2),1>r&&s.clearRect(Math.floor(Sa.getX()),Math.floor(Sa.getY()),Math.floor(Sa.getWidth()),
+Math.floor(Sa.getHeight())),0<r&&(c(THREE.NormalBlending),b(1),e("rgba("+Math.floor(255*t.r)+","+Math.floor(255*t.g)+","+Math.floor(255*t.b)+","+r+")"),s.fillRect(Math.floor(Sa.getX()),Math.floor(Sa.getY()),Math.floor(Sa.getWidth()),Math.floor(Sa.getHeight()))),Sa.empty())};this.render=function(a,l){function n(a,b,c){for(var d=0,e=i.length;d<e;d++){var f=i[d],g=f.color;if(f instanceof THREE.DirectionalLight){var h=f.matrixWorld.getPosition().normalize(),k=b.dot(h);0>=k||(k*=f.intensity,c.r+=g.r*k,
+c.g+=g.g*k,c.b+=g.b*k)}else f instanceof THREE.PointLight&&(h=f.matrixWorld.getPosition(),k=b.dot(va.sub(h,a).normalize()),0>=k||(k*=0==f.distance?1:1-Math.min(a.distanceTo(h)/f.distance,1),0!=k&&(k*=f.intensity,c.r+=g.r*k,c.g+=g.g*k,c.b+=g.b*k)))}}function m(a,d,e,g,h,k,i,j){f.info.render.vertices+=3;f.info.render.faces++;b(j.opacity);c(j.blending);H=a.positionScreen.x;I=a.positionScreen.y;N=d.positionScreen.x;O=d.positionScreen.y;R=e.positionScreen.x;ga=e.positionScreen.y;r(H,I,N,O,R,ga);(j instanceof
+THREE.MeshLambertMaterial||j instanceof THREE.MeshPhongMaterial)&&null===j.map&&null===j.map?(aa.copy(j.color),ia.copy(j.emissive),j.vertexColors===THREE.FaceColors&&(aa.r*=i.color.r,aa.g*=i.color.g,aa.b*=i.color.b),!0===kb)?!1===j.wireframe&&j.shading==THREE.SmoothShading&&3==i.vertexNormalsLength?(fa.r=ca.r=Y.r=Oa.r,fa.g=ca.g=Y.g=Oa.g,fa.b=ca.b=Y.b=Oa.b,n(i.v1.positionWorld,i.vertexNormalsWorld[0],fa),n(i.v2.positionWorld,i.vertexNormalsWorld[1],ca),n(i.v3.positionWorld,i.vertexNormalsWorld[2],
+Y),fa.r=fa.r*aa.r+ia.r,fa.g=fa.g*aa.g+ia.g,fa.b=fa.b*aa.b+ia.b,ca.r=ca.r*aa.r+ia.r,ca.g=ca.g*aa.g+ia.g,ca.b=ca.b*aa.b+ia.b,Y.r=Y.r*aa.r+ia.r,Y.g=Y.g*aa.g+ia.g,Y.b=Y.b*aa.b+ia.b,ba.r=0.5*(ca.r+Y.r),ba.g=0.5*(ca.g+Y.g),ba.b=0.5*(ca.b+Y.b),sa=yc(fa,ca,Y,ba),na(H,I,N,O,R,ga,0,0,1,0,0,1,sa)):(X.r=Oa.r,X.g=Oa.g,X.b=Oa.b,n(i.centroidWorld,i.normalWorld,X),X.r=X.r*aa.r+ia.r,X.g=X.g*aa.g+ia.g,X.b=X.b*aa.b+ia.b,!0===j.wireframe?t(X,j.wireframeLinewidth,j.wireframeLinecap,j.wireframeLinejoin):w(X)):!0===j.wireframe?
+t(j.color,j.wireframeLinewidth,j.wireframeLinecap,j.wireframeLinejoin):w(j.color):j instanceof THREE.MeshBasicMaterial||j instanceof THREE.MeshLambertMaterial||j instanceof THREE.MeshPhongMaterial?null!==j.map?j.map.mapping instanceof THREE.UVMapping&&(Ea=i.uvs[0],z(H,I,N,O,R,ga,Ea[g].u,Ea[g].v,Ea[h].u,Ea[h].v,Ea[k].u,Ea[k].v,j.map)):null!==j.envMap?j.envMap.mapping instanceof THREE.SphericalReflectionMapping&&(a=l.matrixWorldInverse,va.copy(i.vertexNormalsWorld[g]),rb=0.5*(va.x*a.elements[0]+va.y*
+a.elements[4]+va.z*a.elements[8])+0.5,ib=0.5*(va.x*a.elements[1]+va.y*a.elements[5]+va.z*a.elements[9])+0.5,va.copy(i.vertexNormalsWorld[h]),ob=0.5*(va.x*a.elements[0]+va.y*a.elements[4]+va.z*a.elements[8])+0.5,jb=0.5*(va.x*a.elements[1]+va.y*a.elements[5]+va.z*a.elements[9])+0.5,va.copy(i.vertexNormalsWorld[k]),Bb=0.5*(va.x*a.elements[0]+va.y*a.elements[4]+va.z*a.elements[8])+0.5,Cb=0.5*(va.x*a.elements[1]+va.y*a.elements[5]+va.z*a.elements[9])+0.5,z(H,I,N,O,R,ga,rb,ib,ob,jb,Bb,Cb,j.envMap)):(X.copy(j.color),
+j.vertexColors===THREE.FaceColors&&(X.r*=i.color.r,X.g*=i.color.g,X.b*=i.color.b),!0===j.wireframe?t(X,j.wireframeLinewidth,j.wireframeLinecap,j.wireframeLinejoin):w(X)):j instanceof THREE.MeshDepthMaterial?(Ja=l.near,ma=l.far,fa.r=fa.g=fa.b=1-Db(a.positionScreen.z,Ja,ma),ca.r=ca.g=ca.b=1-Db(d.positionScreen.z,Ja,ma),Y.r=Y.g=Y.b=1-Db(e.positionScreen.z,Ja,ma),ba.r=0.5*(ca.r+Y.r),ba.g=0.5*(ca.g+Y.g),ba.b=0.5*(ca.b+Y.b),sa=yc(fa,ca,Y,ba),na(H,I,N,O,R,ga,0,0,1,0,0,1,sa)):j instanceof THREE.MeshNormalMaterial&&
+(X.r=ic(i.normalWorld.x),X.g=ic(i.normalWorld.y),X.b=ic(i.normalWorld.z),!0===j.wireframe?t(X,j.wireframeLinewidth,j.wireframeLinecap,j.wireframeLinejoin):w(X))}function r(a,b,c,d,e,f){s.beginPath();s.moveTo(a,b);s.lineTo(c,d);s.lineTo(e,f);s.closePath()}function q(a,b,c,d,e,f,g,h){s.beginPath();s.moveTo(a,b);s.lineTo(c,d);s.lineTo(e,f);s.lineTo(g,h);s.closePath()}function t(a,b,c,e){A!==b&&(A=s.lineWidth=b);v!==c&&(v=s.lineCap=c);u!==e&&(u=s.lineJoin=e);d(a.getContextStyle());s.stroke();Ka.inflate(2*
+b)}function w(a){e(a.getContextStyle());s.fill()}function z(a,b,c,d,f,g,h,k,i,j,l,n,na){if(!(na instanceof THREE.DataTexture||void 0===na.image||0==na.image.width)){if(!0===na.needsUpdate){var m=na.wrapS==THREE.RepeatWrapping,o=na.wrapT==THREE.RepeatWrapping;Aa[na.id]=s.createPattern(na.image,!0===m&&!0===o?"repeat":!0===m&&!1===o?"repeat-x":!1===m&&!0===o?"repeat-y":"no-repeat");na.needsUpdate=!1}void 0===Aa[na.id]?e("rgba(0,0,0,1)"):e(Aa[na.id]);var m=na.offset.x/na.repeat.x,o=na.offset.y/na.repeat.y,
+Db=na.image.width*na.repeat.x,p=na.image.height*na.repeat.y,h=(h+m)*Db,k=(1-k+o)*p,c=c-a,d=d-b,f=f-a,g=g-b,i=(i+m)*Db-h,j=(1-j+o)*p-k,l=(l+m)*Db-h,n=(1-n+o)*p-k,m=i*n-l*j;0===m?(void 0===Na[na.id]&&(b=document.createElement("canvas"),b.width=na.image.width,b.height=na.image.height,b=b.getContext("2d"),b.drawImage(na.image,0,0),Na[na.id]=b.getImageData(0,0,na.image.width,na.image.height).data),b=Na[na.id],h=4*(Math.floor(h)+Math.floor(k)*na.image.width),X.setRGB(b[h]/255,b[h+1]/255,b[h+2]/255),w(X)):
+(m=1/m,na=(n*c-j*f)*m,j=(n*d-j*g)*m,c=(i*f-l*c)*m,d=(i*g-l*d)*m,a=a-na*h-c*k,h=b-j*h-d*k,s.save(),s.transform(na,j,c,d,a,h),s.fill(),s.restore())}}function na(a,b,c,d,e,f,g,h,k,i,j,l,na){var n,m;n=na.width-1;m=na.height-1;g*=n;h*=m;c-=a;d-=b;e-=a;f-=b;k=k*n-g;i=i*m-h;j=j*n-g;l=l*m-h;m=1/(k*l-j*i);n=(l*c-i*e)*m;i=(l*d-i*f)*m;c=(k*e-j*c)*m;d=(k*f-j*d)*m;a=a-n*g-c*h;b=b-i*g-d*h;s.save();s.transform(n,i,c,d,a,b);s.clip();s.drawImage(na,0,0);s.restore()}function yc(a,b,c,d){xa[0]=255*a.r|0;xa[1]=255*a.g|
+0;xa[2]=255*a.b|0;xa[4]=255*b.r|0;xa[5]=255*b.g|0;xa[6]=255*b.b|0;xa[8]=255*c.r|0;xa[9]=255*c.g|0;xa[10]=255*c.b|0;xa[12]=255*d.r|0;xa[13]=255*d.g|0;xa[14]=255*d.b|0;pb.putImageData(bb,0,0);sb.drawImage(eb,0,0);return mb}function Db(a,b,c){a=(a-b)/(c-b);return a*a*(3-2*a)}function ic(a){a=0.5*(a+1);return 0>a?0:1<a?1:a}function Zb(a,b){var c=b.x-a.x,d=b.y-a.y,e=c*c+d*d;0!==e&&(e=1/Math.sqrt(e),c*=e,d*=e,b.x+=c,b.y+=d,a.x-=c,a.y-=d)}if(!1===l instanceof THREE.Camera)console.error("THREE.CanvasRenderer.render: camera is not an instance of THREE.Camera.");
+else{var $b,zc,ka,da;!0===this.autoClear?this.clear():s.setTransform(1,0,0,-1,p,o);f.info.render.vertices=0;f.info.render.faces=0;g=j.projectScene(a,l,this.sortObjects,this.sortElements);h=g.elements;i=g.lights;kb=0<i.length;if(!0===kb){Oa.setRGB(0,0,0);lb.setRGB(0,0,0);ab.setRGB(0,0,0);$b=0;for(zc=i.length;$b<zc;$b++){da=i[$b];var la=da.color;da instanceof THREE.AmbientLight?(Oa.r+=la.r,Oa.g+=la.g,Oa.b+=la.b):da instanceof THREE.DirectionalLight?(lb.r+=la.r,lb.g+=la.g,lb.b+=la.b):da instanceof THREE.PointLight&&
+(ab.r+=la.r,ab.g+=la.g,ab.b+=la.b)}}$b=0;for(zc=h.length;$b<zc;$b++)if(ka=h[$b],da=ka.material,!(void 0===da||!1===da.visible)){Ka.empty();if(ka instanceof THREE.RenderableParticle){D=ka;D.x*=p;D.y*=o;var la=D,cb=ka;b(da.opacity);c(da.blending);var E=void 0,Ab=void 0,tb=void 0,ub=void 0,jc=ka=void 0,Rc=void 0;da instanceof THREE.ParticleBasicMaterial?null===da.map?(tb=cb.object.scale.x,ub=cb.object.scale.y,tb*=cb.scale.x*p,ub*=cb.scale.y*o,Ka.set(la.x-tb,la.y-ub,la.x+tb,la.y+ub),!1!==Wa.intersects(Ka)&&
+(e(da.color.getContextStyle()),s.save(),s.translate(la.x,la.y),s.rotate(-cb.rotation),s.scale(tb,ub),s.fillRect(-1,-1,2,2),s.restore())):(ka=da.map.image,jc=ka.width>>1,Rc=ka.height>>1,tb=cb.scale.x*p,ub=cb.scale.y*o,E=tb*jc,Ab=ub*Rc,Ka.set(la.x-E,la.y-Ab,la.x+E,la.y+Ab),!1!==Wa.intersects(Ka)&&(s.save(),s.translate(la.x,la.y),s.rotate(-cb.rotation),s.scale(tb,-ub),s.translate(-jc,-Rc),s.drawImage(ka,0,0),s.restore())):da instanceof THREE.ParticleCanvasMaterial&&(E=cb.scale.x*p,Ab=cb.scale.y*o,Ka.set(la.x-
+E,la.y-Ab,la.x+E,la.y+Ab),!1!==Wa.intersects(Ka)&&(d(da.color.getContextStyle()),e(da.color.getContextStyle()),s.save(),s.translate(la.x,la.y),s.rotate(-cb.rotation),s.scale(E,Ab),da.program(s),s.restore()))}else if(ka instanceof THREE.RenderableLine){if(D=ka.v1,C=ka.v2,D.positionScreen.x*=p,D.positionScreen.y*=o,C.positionScreen.x*=p,C.positionScreen.y*=o,Ka.addPoint(D.positionScreen.x,D.positionScreen.y),Ka.addPoint(C.positionScreen.x,C.positionScreen.y),!0===Wa.intersects(Ka)&&(la=D,cb=C,b(da.opacity),
+c(da.blending),s.beginPath(),s.moveTo(la.positionScreen.x,la.positionScreen.y),s.lineTo(cb.positionScreen.x,cb.positionScreen.y),da instanceof THREE.LineBasicMaterial))la=da.linewidth,A!==la&&(A=s.lineWidth=la),la=da.linecap,v!==la&&(v=s.lineCap=la),la=da.linejoin,u!==la&&(u=s.lineJoin=la),d(da.color.getContextStyle()),s.stroke(),Ka.inflate(2*da.linewidth)}else if(ka instanceof THREE.RenderableFace3)D=ka.v1,C=ka.v2,G=ka.v3,D.positionScreen.x*=p,D.positionScreen.y*=o,C.positionScreen.x*=p,C.positionScreen.y*=
+o,G.positionScreen.x*=p,G.positionScreen.y*=o,!0===da.overdraw&&(Zb(D.positionScreen,C.positionScreen),Zb(C.positionScreen,G.positionScreen),Zb(G.positionScreen,D.positionScreen)),Ka.add3Points(D.positionScreen.x,D.positionScreen.y,C.positionScreen.x,C.positionScreen.y,G.positionScreen.x,G.positionScreen.y),!0===Wa.intersects(Ka)&&m(D,C,G,0,1,2,ka,da,a);else if(ka instanceof THREE.RenderableFace4&&(D=ka.v1,C=ka.v2,G=ka.v3,P=ka.v4,D.positionScreen.x*=p,D.positionScreen.y*=o,C.positionScreen.x*=p,C.positionScreen.y*=
+o,G.positionScreen.x*=p,G.positionScreen.y*=o,P.positionScreen.x*=p,P.positionScreen.y*=o,B.positionScreen.copy(C.positionScreen),K.positionScreen.copy(P.positionScreen),!0===da.overdraw&&(Zb(D.positionScreen,C.positionScreen),Zb(C.positionScreen,P.positionScreen),Zb(P.positionScreen,D.positionScreen),Zb(G.positionScreen,B.positionScreen),Zb(G.positionScreen,K.positionScreen)),Ka.addPoint(D.positionScreen.x,D.positionScreen.y),Ka.addPoint(C.positionScreen.x,C.positionScreen.y),Ka.addPoint(G.positionScreen.x,
+G.positionScreen.y),Ka.addPoint(P.positionScreen.x,P.positionScreen.y),!0===Wa.intersects(Ka)))(la=D,cb=C,E=G,Ab=P,tb=B,ub=K,jc=a,f.info.render.vertices+=4,f.info.render.faces++,b(da.opacity),c(da.blending),void 0!==da.map&&null!==da.map||void 0!==da.envMap&&null!==da.envMap)?(m(la,cb,Ab,0,1,3,ka,da,jc),m(tb,E,ub,1,2,3,ka,da,jc)):(H=la.positionScreen.x,I=la.positionScreen.y,N=cb.positionScreen.x,O=cb.positionScreen.y,R=E.positionScreen.x,ga=E.positionScreen.y,M=Ab.positionScreen.x,J=Ab.positionScreen.y,
+Q=tb.positionScreen.x,Z=tb.positionScreen.y,L=ub.positionScreen.x,oa=ub.positionScreen.y,da instanceof THREE.MeshLambertMaterial||da instanceof THREE.MeshPhongMaterial)?(aa.copy(da.color),ia.copy(da.emissive),da.vertexColors===THREE.FaceColors&&(aa.r*=ka.color.r,aa.g*=ka.color.g,aa.b*=ka.color.b),!0===kb)?!1===da.wireframe&&da.shading==THREE.SmoothShading&&4==ka.vertexNormalsLength?(fa.r=ca.r=Y.r=ba.r=Oa.r,fa.g=ca.g=Y.g=ba.g=Oa.g,fa.b=ca.b=Y.b=ba.b=Oa.b,n(ka.v1.positionWorld,ka.vertexNormalsWorld[0],
+fa),n(ka.v2.positionWorld,ka.vertexNormalsWorld[1],ca),n(ka.v4.positionWorld,ka.vertexNormalsWorld[3],Y),n(ka.v3.positionWorld,ka.vertexNormalsWorld[2],ba),fa.r=fa.r*aa.r+ia.r,fa.g=fa.g*aa.g+ia.g,fa.b=fa.b*aa.b+ia.b,ca.r=ca.r*aa.r+ia.r,ca.g=ca.g*aa.g+ia.g,ca.b=ca.b*aa.b+ia.b,Y.r=Y.r*aa.r+ia.r,Y.g=Y.g*aa.g+ia.g,Y.b=Y.b*aa.b+ia.b,ba.r=ba.r*aa.r+ia.r,ba.g=ba.g*aa.g+ia.g,ba.b=ba.b*aa.b+ia.b,sa=yc(fa,ca,Y,ba),r(H,I,N,O,M,J),na(H,I,N,O,M,J,0,0,1,0,0,1,sa),r(Q,Z,R,ga,L,oa),na(Q,Z,R,ga,L,oa,1,0,1,1,0,1,sa)):
+(X.r=Oa.r,X.g=Oa.g,X.b=Oa.b,n(ka.centroidWorld,ka.normalWorld,X),X.r=X.r*aa.r+ia.r,X.g=X.g*aa.g+ia.g,X.b=X.b*aa.b+ia.b,q(H,I,N,O,R,ga,M,J),!0===da.wireframe?t(X,da.wireframeLinewidth,da.wireframeLinecap,da.wireframeLinejoin):w(X)):(X.r=aa.r+ia.r,X.g=aa.g+ia.g,X.b=aa.b+ia.b,q(H,I,N,O,R,ga,M,J),!0===da.wireframe?t(X,da.wireframeLinewidth,da.wireframeLinecap,da.wireframeLinejoin):w(X)):da instanceof THREE.MeshBasicMaterial?(X.copy(da.color),da.vertexColors===THREE.FaceColors&&(X.r*=ka.color.r,X.g*=ka.color.g,
+X.b*=ka.color.b),q(H,I,N,O,R,ga,M,J),!0===da.wireframe?t(X,da.wireframeLinewidth,da.wireframeLinecap,da.wireframeLinejoin):w(X)):da instanceof THREE.MeshNormalMaterial?(X.r=ic(ka.normalWorld.x),X.g=ic(ka.normalWorld.y),X.b=ic(ka.normalWorld.z),q(H,I,N,O,R,ga,M,J),!0===da.wireframe?t(X,da.wireframeLinewidth,da.wireframeLinecap,da.wireframeLinejoin):w(X)):da instanceof THREE.MeshDepthMaterial&&(Ja=l.near,ma=l.far,fa.r=fa.g=fa.b=1-Db(la.positionScreen.z,Ja,ma),ca.r=ca.g=ca.b=1-Db(cb.positionScreen.z,
+Ja,ma),Y.r=Y.g=Y.b=1-Db(Ab.positionScreen.z,Ja,ma),ba.r=ba.g=ba.b=1-Db(E.positionScreen.z,Ja,ma),sa=yc(fa,ca,Y,ba),r(H,I,N,O,M,J),na(H,I,N,O,M,J,0,0,1,0,0,1,sa),r(Q,Z,R,ga,L,oa),na(Q,Z,R,ga,L,oa,1,0,1,1,0,1,sa));Sa.addRectangle(Ka)}s.setTransform(1,0,0,1,0,0)}}};
+THREE.ShaderChunk={fog_pars_fragment:"#ifdef USE_FOG\nuniform vec3 fogColor;\n#ifdef FOG_EXP2\nuniform float fogDensity;\n#else\nuniform float fogNear;\nuniform float fogFar;\n#endif\n#endif",fog_fragment:"#ifdef USE_FOG\nfloat depth = gl_FragCoord.z / gl_FragCoord.w;\n#ifdef FOG_EXP2\nconst float LOG2 = 1.442695;\nfloat fogFactor = exp2( - fogDensity * fogDensity * depth * depth * LOG2 );\nfogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );\n#else\nfloat fogFactor = smoothstep( fogNear, fogFar, depth );\n#endif\ngl_FragColor = mix( gl_FragColor, vec4( fogColor, gl_FragColor.w ), fogFactor );\n#endif",envmap_pars_fragment:"#ifdef USE_ENVMAP\nuniform float reflectivity;\nuniform samplerCube envMap;\nuniform float flipEnvMap;\nuniform int combine;\n#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\nuniform bool useRefract;\nuniform float refractionRatio;\n#else\nvarying vec3 vReflect;\n#endif\n#endif",
+envmap_fragment:"#ifdef USE_ENVMAP\nvec3 reflectVec;\n#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\nvec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );\nif ( useRefract ) {\nreflectVec = refract( cameraToVertex, normal, refractionRatio );\n} else { \nreflectVec = reflect( cameraToVertex, normal );\n}\n#else\nreflectVec = vReflect;\n#endif\n#ifdef DOUBLE_SIDED\nfloat flipNormal = ( -1.0 + 2.0 * float( gl_FrontFacing ) );\nvec4 cubeColor = textureCube( envMap, flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n#else\nvec4 cubeColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n#endif\n#ifdef GAMMA_INPUT\ncubeColor.xyz *= cubeColor.xyz;\n#endif\nif ( combine == 1 ) {\ngl_FragColor.xyz = mix( gl_FragColor.xyz, cubeColor.xyz, specularStrength * reflectivity );\n} else if ( combine == 2 ) {\ngl_FragColor.xyz += cubeColor.xyz * specularStrength * reflectivity;\n} else {\ngl_FragColor.xyz = mix( gl_FragColor.xyz, gl_FragColor.xyz * cubeColor.xyz, specularStrength * reflectivity );\n}\n#endif",
+envmap_pars_vertex:"#if defined( USE_ENVMAP ) && ! defined( USE_BUMPMAP ) && ! defined( USE_NORMALMAP )\nvarying vec3 vReflect;\nuniform float refractionRatio;\nuniform bool useRefract;\n#endif",worldpos_vertex:"#if defined( USE_ENVMAP ) || defined( PHONG ) || defined( LAMBERT ) || defined ( USE_SHADOWMAP )\n#ifdef USE_SKINNING\nvec4 worldPosition = modelMatrix * skinned;\n#endif\n#if defined( USE_MORPHTARGETS ) && ! defined( USE_SKINNING )\nvec4 worldPosition = modelMatrix * vec4( morphed, 1.0 );\n#endif\n#if ! defined( USE_MORPHTARGETS ) && ! defined( USE_SKINNING )\nvec4 worldPosition = modelMatrix * vec4( position, 1.0 );\n#endif\n#endif",
+envmap_vertex:"#if defined( USE_ENVMAP ) && ! defined( USE_BUMPMAP ) && ! defined( USE_NORMALMAP )\nvec3 worldNormal = mat3( modelMatrix[ 0 ].xyz, modelMatrix[ 1 ].xyz, modelMatrix[ 2 ].xyz ) * objectNormal;\nworldNormal = normalize( worldNormal );\nvec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );\nif ( useRefract ) {\nvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n} else {\nvReflect = reflect( cameraToVertex, worldNormal );\n}\n#endif",map_particle_pars_fragment:"#ifdef USE_MAP\nuniform sampler2D map;\n#endif",
+map_particle_fragment:"#ifdef USE_MAP\ngl_FragColor = gl_FragColor * texture2D( map, vec2( gl_PointCoord.x, 1.0 - gl_PointCoord.y ) );\n#endif",map_pars_vertex:"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP )\nvarying vec2 vUv;\nuniform vec4 offsetRepeat;\n#endif",map_pars_fragment:"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP )\nvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\nuniform sampler2D map;\n#endif",
+map_vertex:"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP )\nvUv = uv * offsetRepeat.zw + offsetRepeat.xy;\n#endif",map_fragment:"#ifdef USE_MAP\n#ifdef GAMMA_INPUT\nvec4 texelColor = texture2D( map, vUv );\ntexelColor.xyz *= texelColor.xyz;\ngl_FragColor = gl_FragColor * texelColor;\n#else\ngl_FragColor = gl_FragColor * texture2D( map, vUv );\n#endif\n#endif",lightmap_pars_fragment:"#ifdef USE_LIGHTMAP\nvarying vec2 vUv2;\nuniform sampler2D lightMap;\n#endif",
+lightmap_pars_vertex:"#ifdef USE_LIGHTMAP\nvarying vec2 vUv2;\n#endif",lightmap_fragment:"#ifdef USE_LIGHTMAP\ngl_FragColor = gl_FragColor * texture2D( lightMap, vUv2 );\n#endif",lightmap_vertex:"#ifdef USE_LIGHTMAP\nvUv2 = uv2;\n#endif",bumpmap_pars_fragment:"#ifdef USE_BUMPMAP\nuniform sampler2D bumpMap;\nuniform float bumpScale;\nvec2 dHdxy_fwd() {\nvec2 dSTdx = dFdx( vUv );\nvec2 dSTdy = dFdy( vUv );\nfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\nfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\nfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\nreturn vec2( dBx, dBy );\n}\nvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\nvec3 vSigmaX = dFdx( surf_pos );\nvec3 vSigmaY = dFdy( surf_pos );\nvec3 vN = surf_norm;\nvec3 R1 = cross( vSigmaY, vN );\nvec3 R2 = cross( vN, vSigmaX );\nfloat fDet = dot( vSigmaX, R1 );\nvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\nreturn normalize( abs( fDet ) * surf_norm - vGrad );\n}\n#endif",
+normalmap_pars_fragment:"#ifdef USE_NORMALMAP\nuniform sampler2D normalMap;\nuniform vec2 normalScale;\nvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {\nvec3 q0 = dFdx( eye_pos.xyz );\nvec3 q1 = dFdy( eye_pos.xyz );\nvec2 st0 = dFdx( vUv.st );\nvec2 st1 = dFdy( vUv.st );\nvec3 S = normalize(  q0 * st1.t - q1 * st0.t );\nvec3 T = normalize( -q0 * st1.s + q1 * st0.s );\nvec3 N = normalize( surf_norm );\nvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\nmapN.xy = normalScale * mapN.xy;\nmat3 tsn = mat3( S, T, N );\nreturn normalize( tsn * mapN );\n}\n#endif",
+specularmap_pars_fragment:"#ifdef USE_SPECULARMAP\nuniform sampler2D specularMap;\n#endif",specularmap_fragment:"float specularStrength;\n#ifdef USE_SPECULARMAP\nvec4 texelSpecular = texture2D( specularMap, vUv );\nspecularStrength = texelSpecular.r;\n#else\nspecularStrength = 1.0;\n#endif",lights_lambert_pars_vertex:"uniform vec3 ambient;\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 ambientLightColor;\n#if MAX_DIR_LIGHTS > 0\nuniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\nuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n#endif\n#if MAX_HEMI_LIGHTS > 0\nuniform vec3 hemisphereLightSkyColor[ MAX_HEMI_LIGHTS ];\nuniform vec3 hemisphereLightGroundColor[ MAX_HEMI_LIGHTS ];\nuniform vec3 hemisphereLightDirection[ MAX_HEMI_LIGHTS ];\n#endif\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\n#endif\n#if MAX_SPOT_LIGHTS > 0\nuniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];\nuniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\nuniform float spotLightAngleCos[ MAX_SPOT_LIGHTS ];\nuniform float spotLightExponent[ MAX_SPOT_LIGHTS ];\n#endif\n#ifdef WRAP_AROUND\nuniform vec3 wrapRGB;\n#endif",
+lights_lambert_vertex:"vLightFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\nvLightBack = vec3( 0.0 );\n#endif\ntransformedNormal = normalize( transformedNormal );\n#if MAX_DIR_LIGHTS > 0\nfor( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {\nvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\nvec3 dirVector = normalize( lDirection.xyz );\nfloat dotProduct = dot( transformedNormal, dirVector );\nvec3 directionalLightWeighting = vec3( max( dotProduct, 0.0 ) );\n#ifdef DOUBLE_SIDED\nvec3 directionalLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n#ifdef WRAP_AROUND\nvec3 directionalLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n#endif\n#endif\n#ifdef WRAP_AROUND\nvec3 directionalLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\ndirectionalLightWeighting = mix( directionalLightWeighting, directionalLightWeightingHalf, wrapRGB );\n#ifdef DOUBLE_SIDED\ndirectionalLightWeightingBack = mix( directionalLightWeightingBack, directionalLightWeightingHalfBack, wrapRGB );\n#endif\n#endif\nvLightFront += directionalLightColor[ i ] * directionalLightWeighting;\n#ifdef DOUBLE_SIDED\nvLightBack += directionalLightColor[ i ] * directionalLightWeightingBack;\n#endif\n}\n#endif\n#if MAX_POINT_LIGHTS > 0\nfor( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\nfloat dotProduct = dot( transformedNormal, lVector );\nvec3 pointLightWeighting = vec3( max( dotProduct, 0.0 ) );\n#ifdef DOUBLE_SIDED\nvec3 pointLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n#ifdef WRAP_AROUND\nvec3 pointLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n#endif\n#endif\n#ifdef WRAP_AROUND\nvec3 pointLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\npointLightWeighting = mix( pointLightWeighting, pointLightWeightingHalf, wrapRGB );\n#ifdef DOUBLE_SIDED\npointLightWeightingBack = mix( pointLightWeightingBack, pointLightWeightingHalfBack, wrapRGB );\n#endif\n#endif\nvLightFront += pointLightColor[ i ] * pointLightWeighting * lDistance;\n#ifdef DOUBLE_SIDED\nvLightBack += pointLightColor[ i ] * pointLightWeightingBack * lDistance;\n#endif\n}\n#endif\n#if MAX_SPOT_LIGHTS > 0\nfor( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - worldPosition.xyz ) );\nif ( spotEffect > spotLightAngleCos[ i ] ) {\nspotEffect = max( pow( spotEffect, spotLightExponent[ i ] ), 0.0 );\nfloat lDistance = 1.0;\nif ( spotLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\nfloat dotProduct = dot( transformedNormal, lVector );\nvec3 spotLightWeighting = vec3( max( dotProduct, 0.0 ) );\n#ifdef DOUBLE_SIDED\nvec3 spotLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n#ifdef WRAP_AROUND\nvec3 spotLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n#endif\n#endif\n#ifdef WRAP_AROUND\nvec3 spotLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\nspotLightWeighting = mix( spotLightWeighting, spotLightWeightingHalf, wrapRGB );\n#ifdef DOUBLE_SIDED\nspotLightWeightingBack = mix( spotLightWeightingBack, spotLightWeightingHalfBack, wrapRGB );\n#endif\n#endif\nvLightFront += spotLightColor[ i ] * spotLightWeighting * lDistance * spotEffect;\n#ifdef DOUBLE_SIDED\nvLightBack += spotLightColor[ i ] * spotLightWeightingBack * lDistance * spotEffect;\n#endif\n}\n}\n#endif\n#if MAX_HEMI_LIGHTS > 0\nfor( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {\nvec4 lDirection = viewMatrix * vec4( hemisphereLightDirection[ i ], 0.0 );\nvec3 lVector = normalize( lDirection.xyz );\nfloat dotProduct = dot( transformedNormal, lVector );\nfloat hemiDiffuseWeight = 0.5 * dotProduct + 0.5;\nfloat hemiDiffuseWeightBack = -0.5 * dotProduct + 0.5;\nvLightFront += mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );\n#ifdef DOUBLE_SIDED\nvLightBack += mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeightBack );\n#endif\n}\n#endif\nvLightFront = vLightFront * diffuse + ambient * ambientLightColor + emissive;\n#ifdef DOUBLE_SIDED\nvLightBack = vLightBack * diffuse + ambient * ambientLightColor + emissive;\n#endif",
+lights_phong_pars_vertex:"#ifndef PHONG_PER_PIXEL\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\n#if MAX_SPOT_LIGHTS > 0\nuniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\nuniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\nvarying vec4 vSpotLight[ MAX_SPOT_LIGHTS ];\n#endif\n#endif\n#if MAX_SPOT_LIGHTS > 0 || defined( USE_BUMPMAP )\nvarying vec3 vWorldPosition;\n#endif",
+lights_phong_vertex:"#ifndef PHONG_PER_PIXEL\n#if MAX_POINT_LIGHTS > 0\nfor( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nvPointLight[ i ] = vec4( lVector, lDistance );\n}\n#endif\n#if MAX_SPOT_LIGHTS > 0\nfor( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( spotLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );\nvSpotLight[ i ] = vec4( lVector, lDistance );\n}\n#endif\n#endif\n#if MAX_SPOT_LIGHTS > 0 || defined( USE_BUMPMAP )\nvWorldPosition = worldPosition.xyz;\n#endif",
+lights_phong_pars_fragment:"uniform vec3 ambientLightColor;\n#if MAX_DIR_LIGHTS > 0\nuniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\nuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n#endif\n#if MAX_HEMI_LIGHTS > 0\nuniform vec3 hemisphereLightSkyColor[ MAX_HEMI_LIGHTS ];\nuniform vec3 hemisphereLightGroundColor[ MAX_HEMI_LIGHTS ];\nuniform vec3 hemisphereLightDirection[ MAX_HEMI_LIGHTS ];\n#endif\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\n#ifdef PHONG_PER_PIXEL\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\n#else\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\n#endif\n#if MAX_SPOT_LIGHTS > 0\nuniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];\nuniform float spotLightAngleCos[ MAX_SPOT_LIGHTS ];\nuniform float spotLightExponent[ MAX_SPOT_LIGHTS ];\n#ifdef PHONG_PER_PIXEL\nuniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\n#else\nvarying vec4 vSpotLight[ MAX_SPOT_LIGHTS ];\n#endif\n#endif\n#if MAX_SPOT_LIGHTS > 0 || defined( USE_BUMPMAP )\nvarying vec3 vWorldPosition;\n#endif\n#ifdef WRAP_AROUND\nuniform vec3 wrapRGB;\n#endif\nvarying vec3 vViewPosition;\nvarying vec3 vNormal;",
+lights_phong_fragment:"vec3 normal = normalize( vNormal );\nvec3 viewPosition = normalize( vViewPosition );\n#ifdef DOUBLE_SIDED\nnormal = normal * ( -1.0 + 2.0 * float( gl_FrontFacing ) );\n#endif\n#ifdef USE_NORMALMAP\nnormal = perturbNormal2Arb( -viewPosition, normal );\n#elif defined( USE_BUMPMAP )\nnormal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n#endif\n#if MAX_POINT_LIGHTS > 0\nvec3 pointDiffuse  = vec3( 0.0 );\nvec3 pointSpecular = vec3( 0.0 );\nfor ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\n#ifdef PHONG_PER_PIXEL\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz + vViewPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\n#else\nvec3 lVector = normalize( vPointLight[ i ].xyz );\nfloat lDistance = vPointLight[ i ].w;\n#endif\nfloat dotProduct = dot( normal, lVector );\n#ifdef WRAP_AROUND\nfloat pointDiffuseWeightFull = max( dotProduct, 0.0 );\nfloat pointDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\nvec3 pointDiffuseWeight = mix( vec3 ( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), wrapRGB );\n#else\nfloat pointDiffuseWeight = max( dotProduct, 0.0 );\n#endif\npointDiffuse  += diffuse * pointLightColor[ i ] * pointDiffuseWeight * lDistance;\nvec3 pointHalfVector = normalize( lVector + viewPosition );\nfloat pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );\nfloat pointSpecularWeight = specularStrength * max( pow( pointDotNormalHalf, shininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( shininess + 2.0001 ) / 8.0;\nvec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( lVector, pointHalfVector ), 5.0 );\npointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * lDistance * specularNormalization;\n#else\npointSpecular += specular * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * lDistance;\n#endif\n}\n#endif\n#if MAX_SPOT_LIGHTS > 0\nvec3 spotDiffuse  = vec3( 0.0 );\nvec3 spotSpecular = vec3( 0.0 );\nfor ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\n#ifdef PHONG_PER_PIXEL\nvec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz + vViewPosition.xyz;\nfloat lDistance = 1.0;\nif ( spotLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\n#else\nvec3 lVector = normalize( vSpotLight[ i ].xyz );\nfloat lDistance = vSpotLight[ i ].w;\n#endif\nfloat spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - vWorldPosition ) );\nif ( spotEffect > spotLightAngleCos[ i ] ) {\nspotEffect = max( pow( spotEffect, spotLightExponent[ i ] ), 0.0 );\nfloat dotProduct = dot( normal, lVector );\n#ifdef WRAP_AROUND\nfloat spotDiffuseWeightFull = max( dotProduct, 0.0 );\nfloat spotDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\nvec3 spotDiffuseWeight = mix( vec3 ( spotDiffuseWeightFull ), vec3( spotDiffuseWeightHalf ), wrapRGB );\n#else\nfloat spotDiffuseWeight = max( dotProduct, 0.0 );\n#endif\nspotDiffuse += diffuse * spotLightColor[ i ] * spotDiffuseWeight * lDistance * spotEffect;\nvec3 spotHalfVector = normalize( lVector + viewPosition );\nfloat spotDotNormalHalf = max( dot( normal, spotHalfVector ), 0.0 );\nfloat spotSpecularWeight = specularStrength * max( pow( spotDotNormalHalf, shininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( shininess + 2.0001 ) / 8.0;\nvec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( lVector, spotHalfVector ), 5.0 );\nspotSpecular += schlick * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * lDistance * specularNormalization * spotEffect;\n#else\nspotSpecular += specular * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * lDistance * spotEffect;\n#endif\n}\n}\n#endif\n#if MAX_DIR_LIGHTS > 0\nvec3 dirDiffuse  = vec3( 0.0 );\nvec3 dirSpecular = vec3( 0.0 );\nfor( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {\nvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\nvec3 dirVector = normalize( lDirection.xyz );\nfloat dotProduct = dot( normal, dirVector );\n#ifdef WRAP_AROUND\nfloat dirDiffuseWeightFull = max( dotProduct, 0.0 );\nfloat dirDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\nvec3 dirDiffuseWeight = mix( vec3( dirDiffuseWeightFull ), vec3( dirDiffuseWeightHalf ), wrapRGB );\n#else\nfloat dirDiffuseWeight = max( dotProduct, 0.0 );\n#endif\ndirDiffuse  += diffuse * directionalLightColor[ i ] * dirDiffuseWeight;\nvec3 dirHalfVector = normalize( dirVector + viewPosition );\nfloat dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );\nfloat dirSpecularWeight = specularStrength * max( pow( dirDotNormalHalf, shininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( shininess + 2.0001 ) / 8.0;\nvec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( dirVector, dirHalfVector ), 5.0 );\ndirSpecular += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;\n#else\ndirSpecular += specular * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight;\n#endif\n}\n#endif\n#if MAX_HEMI_LIGHTS > 0\nvec3 hemiDiffuse  = vec3( 0.0 );\nvec3 hemiSpecular = vec3( 0.0 );\nfor( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {\nvec4 lDirection = viewMatrix * vec4( hemisphereLightDirection[ i ], 0.0 );\nvec3 lVector = normalize( lDirection.xyz );\nfloat dotProduct = dot( normal, lVector );\nfloat hemiDiffuseWeight = 0.5 * dotProduct + 0.5;\nvec3 hemiColor = mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );\nhemiDiffuse += diffuse * hemiColor;\nvec3 hemiHalfVectorSky = normalize( lVector + viewPosition );\nfloat hemiDotNormalHalfSky = 0.5 * dot( normal, hemiHalfVectorSky ) + 0.5;\nfloat hemiSpecularWeightSky = specularStrength * max( pow( hemiDotNormalHalfSky, shininess ), 0.0 );\nvec3 lVectorGround = -lVector;\nvec3 hemiHalfVectorGround = normalize( lVectorGround + viewPosition );\nfloat hemiDotNormalHalfGround = 0.5 * dot( normal, hemiHalfVectorGround ) + 0.5;\nfloat hemiSpecularWeightGround = specularStrength * max( pow( hemiDotNormalHalfGround, shininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat dotProductGround = dot( normal, lVectorGround );\nfloat specularNormalization = ( shininess + 2.0001 ) / 8.0;\nvec3 schlickSky = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( lVector, hemiHalfVectorSky ), 5.0 );\nvec3 schlickGround = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( lVectorGround, hemiHalfVectorGround ), 5.0 );\nhemiSpecular += hemiColor * specularNormalization * ( schlickSky * hemiSpecularWeightSky * max( dotProduct, 0.0 ) + schlickGround * hemiSpecularWeightGround * max( dotProductGround, 0.0 ) );\n#else\nhemiSpecular += specular * hemiColor * ( hemiSpecularWeightSky + hemiSpecularWeightGround ) * hemiDiffuseWeight;\n#endif\n}\n#endif\nvec3 totalDiffuse = vec3( 0.0 );\nvec3 totalSpecular = vec3( 0.0 );\n#if MAX_DIR_LIGHTS > 0\ntotalDiffuse += dirDiffuse;\ntotalSpecular += dirSpecular;\n#endif\n#if MAX_HEMI_LIGHTS > 0\ntotalDiffuse += hemiDiffuse;\ntotalSpecular += hemiSpecular;\n#endif\n#if MAX_POINT_LIGHTS > 0\ntotalDiffuse += pointDiffuse;\ntotalSpecular += pointSpecular;\n#endif\n#if MAX_SPOT_LIGHTS > 0\ntotalDiffuse += spotDiffuse;\ntotalSpecular += spotSpecular;\n#endif\n#ifdef METAL\ngl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * ambient + totalSpecular );\n#else\ngl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * ambient ) + totalSpecular;\n#endif",
+color_pars_fragment:"#ifdef USE_COLOR\nvarying vec3 vColor;\n#endif",color_fragment:"#ifdef USE_COLOR\ngl_FragColor = gl_FragColor * vec4( vColor, opacity );\n#endif",color_pars_vertex:"#ifdef USE_COLOR\nvarying vec3 vColor;\n#endif",color_vertex:"#ifdef USE_COLOR\n#ifdef GAMMA_INPUT\nvColor = color * color;\n#else\nvColor = color;\n#endif\n#endif",skinning_pars_vertex:"#ifdef USE_SKINNING\n#ifdef BONE_TEXTURE\nuniform sampler2D boneTexture;\nmat4 getBoneMatrix( const in float i ) {\nfloat j = i * 4.0;\nfloat x = mod( j, N_BONE_PIXEL_X );\nfloat y = floor( j / N_BONE_PIXEL_X );\nconst float dx = 1.0 / N_BONE_PIXEL_X;\nconst float dy = 1.0 / N_BONE_PIXEL_Y;\ny = dy * ( y + 0.5 );\nvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\nvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\nvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\nvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\nmat4 bone = mat4( v1, v2, v3, v4 );\nreturn bone;\n}\n#else\nuniform mat4 boneGlobalMatrices[ MAX_BONES ];\nmat4 getBoneMatrix( const in float i ) {\nmat4 bone = boneGlobalMatrices[ int(i) ];\nreturn bone;\n}\n#endif\n#endif",
+skinbase_vertex:"#ifdef USE_SKINNING\nmat4 boneMatX = getBoneMatrix( skinIndex.x );\nmat4 boneMatY = getBoneMatrix( skinIndex.y );\n#endif",skinning_vertex:"#ifdef USE_SKINNING\n#ifdef USE_MORPHTARGETS\nvec4 skinVertex = vec4( morphed, 1.0 );\n#else\nvec4 skinVertex = vec4( position, 1.0 );\n#endif\nvec4 skinned  = boneMatX * skinVertex * skinWeight.x;\nskinned \t  += boneMatY * skinVertex * skinWeight.y;\n#endif",morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\n#ifndef USE_MORPHNORMALS\nuniform float morphTargetInfluences[ 8 ];\n#else\nuniform float morphTargetInfluences[ 4 ];\n#endif\n#endif",
+morphtarget_vertex:"#ifdef USE_MORPHTARGETS\nvec3 morphed = vec3( 0.0 );\nmorphed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];\nmorphed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];\nmorphed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];\nmorphed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];\n#ifndef USE_MORPHNORMALS\nmorphed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];\nmorphed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];\nmorphed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];\nmorphed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];\n#endif\nmorphed += position;\n#endif",
+default_vertex:"vec4 mvPosition;\n#ifdef USE_SKINNING\nmvPosition = modelViewMatrix * skinned;\n#endif\n#if !defined( USE_SKINNING ) && defined( USE_MORPHTARGETS )\nmvPosition = modelViewMatrix * vec4( morphed, 1.0 );\n#endif\n#if !defined( USE_SKINNING ) && ! defined( USE_MORPHTARGETS )\nmvPosition = modelViewMatrix * vec4( position, 1.0 );\n#endif\ngl_Position = projectionMatrix * mvPosition;",morphnormal_vertex:"#ifdef USE_MORPHNORMALS\nvec3 morphedNormal = vec3( 0.0 );\nmorphedNormal +=  ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];\nmorphedNormal +=  ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];\nmorphedNormal +=  ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];\nmorphedNormal +=  ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];\nmorphedNormal += normal;\n#endif",
+skinnormal_vertex:"#ifdef USE_SKINNING\nmat4 skinMatrix = skinWeight.x * boneMatX;\nskinMatrix \t+= skinWeight.y * boneMatY;\n#ifdef USE_MORPHNORMALS\nvec4 skinnedNormal = skinMatrix * vec4( morphedNormal, 0.0 );\n#else\nvec4 skinnedNormal = skinMatrix * vec4( normal, 0.0 );\n#endif\n#endif",defaultnormal_vertex:"vec3 objectNormal;\n#ifdef USE_SKINNING\nobjectNormal = skinnedNormal.xyz;\n#endif\n#if !defined( USE_SKINNING ) && defined( USE_MORPHNORMALS )\nobjectNormal = morphedNormal;\n#endif\n#if !defined( USE_SKINNING ) && ! defined( USE_MORPHNORMALS )\nobjectNormal = normal;\n#endif\n#ifdef FLIP_SIDED\nobjectNormal = -objectNormal;\n#endif\nvec3 transformedNormal = normalMatrix * objectNormal;",
+shadowmap_pars_fragment:"#ifdef USE_SHADOWMAP\nuniform sampler2D shadowMap[ MAX_SHADOWS ];\nuniform vec2 shadowMapSize[ MAX_SHADOWS ];\nuniform float shadowDarkness[ MAX_SHADOWS ];\nuniform float shadowBias[ MAX_SHADOWS ];\nvarying vec4 vShadowCoord[ MAX_SHADOWS ];\nfloat unpackDepth( const in vec4 rgba_depth ) {\nconst vec4 bit_shift = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 );\nfloat depth = dot( rgba_depth, bit_shift );\nreturn depth;\n}\n#endif",shadowmap_fragment:"#ifdef USE_SHADOWMAP\n#ifdef SHADOWMAP_DEBUG\nvec3 frustumColors[3];\nfrustumColors[0] = vec3( 1.0, 0.5, 0.0 );\nfrustumColors[1] = vec3( 0.0, 1.0, 0.8 );\nfrustumColors[2] = vec3( 0.0, 0.5, 1.0 );\n#endif\n#ifdef SHADOWMAP_CASCADE\nint inFrustumCount = 0;\n#endif\nfloat fDepth;\nvec3 shadowColor = vec3( 1.0 );\nfor( int i = 0; i < MAX_SHADOWS; i ++ ) {\nvec3 shadowCoord = vShadowCoord[ i ].xyz / vShadowCoord[ i ].w;\nbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\nbool inFrustum = all( inFrustumVec );\n#ifdef SHADOWMAP_CASCADE\ninFrustumCount += int( inFrustum );\nbvec3 frustumTestVec = bvec3( inFrustum, inFrustumCount == 1, shadowCoord.z <= 1.0 );\n#else\nbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n#endif\nbool frustumTest = all( frustumTestVec );\nif ( frustumTest ) {\nshadowCoord.z += shadowBias[ i ];\n#ifdef SHADOWMAP_SOFT\nfloat shadow = 0.0;\nconst float shadowDelta = 1.0 / 9.0;\nfloat xPixelOffset = 1.0 / shadowMapSize[ i ].x;\nfloat yPixelOffset = 1.0 / shadowMapSize[ i ].y;\nfloat dx0 = -1.25 * xPixelOffset;\nfloat dy0 = -1.25 * yPixelOffset;\nfloat dx1 = 1.25 * xPixelOffset;\nfloat dy1 = 1.25 * yPixelOffset;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nshadowColor = shadowColor * vec3( ( 1.0 - shadowDarkness[ i ] * shadow ) );\n#else\nvec4 rgbaDepth = texture2D( shadowMap[ i ], shadowCoord.xy );\nfloat fDepth = unpackDepth( rgbaDepth );\nif ( fDepth < shadowCoord.z )\nshadowColor = shadowColor * vec3( 1.0 - shadowDarkness[ i ] );\n#endif\n}\n#ifdef SHADOWMAP_DEBUG\n#ifdef SHADOWMAP_CASCADE\nif ( inFrustum && inFrustumCount == 1 ) gl_FragColor.xyz *= frustumColors[ i ];\n#else\nif ( inFrustum ) gl_FragColor.xyz *= frustumColors[ i ];\n#endif\n#endif\n}\n#ifdef GAMMA_OUTPUT\nshadowColor *= shadowColor;\n#endif\ngl_FragColor.xyz = gl_FragColor.xyz * shadowColor;\n#endif",
+shadowmap_pars_vertex:"#ifdef USE_SHADOWMAP\nvarying vec4 vShadowCoord[ MAX_SHADOWS ];\nuniform mat4 shadowMatrix[ MAX_SHADOWS ];\n#endif",shadowmap_vertex:"#ifdef USE_SHADOWMAP\nfor( int i = 0; i < MAX_SHADOWS; i ++ ) {\nvShadowCoord[ i ] = shadowMatrix[ i ] * worldPosition;\n}\n#endif",alphatest_fragment:"#ifdef ALPHATEST\nif ( gl_FragColor.a < ALPHATEST ) discard;\n#endif",linear_to_gamma_fragment:"#ifdef GAMMA_OUTPUT\ngl_FragColor.xyz = sqrt( gl_FragColor.xyz );\n#endif"};
+THREE.UniformsUtils={merge:function(a){var b,c,d,e={};for(b=0;b<a.length;b++)for(c in d=this.clone(a[b]),d)e[c]=d[c];return e},clone:function(a){var b,c,d,e={};for(b in a)for(c in e[b]={},a[b])d=a[b][c],e[b][c]=d instanceof THREE.Color||d instanceof THREE.Vector2||d instanceof THREE.Vector3||d instanceof THREE.Vector4||d instanceof THREE.Matrix4||d instanceof THREE.Texture?d.clone():d instanceof Array?d.slice():d;return e}};
+THREE.UniformsLib={common:{diffuse:{type:"c",value:new THREE.Color(15658734)},opacity:{type:"f",value:1},map:{type:"t",value:null},offsetRepeat:{type:"v4",value:new THREE.Vector4(0,0,1,1)},lightMap:{type:"t",value:null},specularMap:{type:"t",value:null},envMap:{type:"t",value:null},flipEnvMap:{type:"f",value:-1},useRefract:{type:"i",value:0},reflectivity:{type:"f",value:1},refractionRatio:{type:"f",value:0.98},combine:{type:"i",value:0},morphTargetInfluences:{type:"f",value:0}},bump:{bumpMap:{type:"t",
+value:null},bumpScale:{type:"f",value:1}},normalmap:{normalMap:{type:"t",value:null},normalScale:{type:"v2",value:new THREE.Vector2(1,1)}},fog:{fogDensity:{type:"f",value:2.5E-4},fogNear:{type:"f",value:1},fogFar:{type:"f",value:2E3},fogColor:{type:"c",value:new THREE.Color(16777215)}},lights:{ambientLightColor:{type:"fv",value:[]},directionalLightDirection:{type:"fv",value:[]},directionalLightColor:{type:"fv",value:[]},hemisphereLightDirection:{type:"fv",value:[]},hemisphereLightSkyColor:{type:"fv",
+value:[]},hemisphereLightGroundColor:{type:"fv",value:[]},pointLightColor:{type:"fv",value:[]},pointLightPosition:{type:"fv",value:[]},pointLightDistance:{type:"fv1",value:[]},spotLightColor:{type:"fv",value:[]},spotLightPosition:{type:"fv",value:[]},spotLightDirection:{type:"fv",value:[]},spotLightDistance:{type:"fv1",value:[]},spotLightAngleCos:{type:"fv1",value:[]},spotLightExponent:{type:"fv1",value:[]}},particle:{psColor:{type:"c",value:new THREE.Color(15658734)},opacity:{type:"f",value:1},size:{type:"f",
+value:1},scale:{type:"f",value:1},map:{type:"t",value:null},fogDensity:{type:"f",value:2.5E-4},fogNear:{type:"f",value:1},fogFar:{type:"f",value:2E3},fogColor:{type:"c",value:new THREE.Color(16777215)}},shadowmap:{shadowMap:{type:"tv",value:[]},shadowMapSize:{type:"v2v",value:[]},shadowBias:{type:"fv1",value:[]},shadowDarkness:{type:"fv1",value:[]},shadowMatrix:{type:"m4v",value:[]}}};
+THREE.ShaderLib={depth:{uniforms:{mNear:{type:"f",value:1},mFar:{type:"f",value:2E3},opacity:{type:"f",value:1}},vertexShader:"void main() {\ngl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}",fragmentShader:"uniform float mNear;\nuniform float mFar;\nuniform float opacity;\nvoid main() {\nfloat depth = gl_FragCoord.z / gl_FragCoord.w;\nfloat color = 1.0 - smoothstep( mNear, mFar, depth );\ngl_FragColor = vec4( vec3( color ), opacity );\n}"},normal:{uniforms:{opacity:{type:"f",
+value:1}},vertexShader:"varying vec3 vNormal;\nvoid main() {\nvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\nvNormal = normalize( normalMatrix * normal );\ngl_Position = projectionMatrix * mvPosition;\n}",fragmentShader:"uniform float opacity;\nvarying vec3 vNormal;\nvoid main() {\ngl_FragColor = vec4( 0.5 * normalize( vNormal ) + 0.5, opacity );\n}"},basic:{uniforms:THREE.UniformsUtils.merge([THREE.UniformsLib.common,THREE.UniformsLib.fog,THREE.UniformsLib.shadowmap]),vertexShader:[THREE.ShaderChunk.map_pars_vertex,
+THREE.ShaderChunk.lightmap_pars_vertex,THREE.ShaderChunk.envmap_pars_vertex,THREE.ShaderChunk.color_pars_vertex,THREE.ShaderChunk.morphtarget_pars_vertex,THREE.ShaderChunk.skinning_pars_vertex,THREE.ShaderChunk.shadowmap_pars_vertex,"void main() {",THREE.ShaderChunk.map_vertex,THREE.ShaderChunk.lightmap_vertex,THREE.ShaderChunk.color_vertex,"#ifdef USE_ENVMAP",THREE.ShaderChunk.morphnormal_vertex,THREE.ShaderChunk.skinbase_vertex,THREE.ShaderChunk.skinnormal_vertex,THREE.ShaderChunk.defaultnormal_vertex,
+"#endif",THREE.ShaderChunk.morphtarget_vertex,THREE.ShaderChunk.skinning_vertex,THREE.ShaderChunk.default_vertex,THREE.ShaderChunk.worldpos_vertex,THREE.ShaderChunk.envmap_vertex,THREE.ShaderChunk.shadowmap_vertex,"}"].join("\n"),fragmentShader:["uniform vec3 diffuse;\nuniform float opacity;",THREE.ShaderChunk.color_pars_fragment,THREE.ShaderChunk.map_pars_fragment,THREE.ShaderChunk.lightmap_pars_fragment,THREE.ShaderChunk.envmap_pars_fragment,THREE.ShaderChunk.fog_pars_fragment,THREE.ShaderChunk.shadowmap_pars_fragment,
+THREE.ShaderChunk.specularmap_pars_fragment,"void main() {\ngl_FragColor = vec4( diffuse, opacity );",THREE.ShaderChunk.map_fragment,THREE.ShaderChunk.alphatest_fragment,THREE.ShaderChunk.specularmap_fragment,THREE.ShaderChunk.lightmap_fragment,THREE.ShaderChunk.color_fragment,THREE.ShaderChunk.envmap_fragment,THREE.ShaderChunk.shadowmap_fragment,THREE.ShaderChunk.linear_to_gamma_fragment,THREE.ShaderChunk.fog_fragment,"}"].join("\n")},lambert:{uniforms:THREE.UniformsUtils.merge([THREE.UniformsLib.common,
+THREE.UniformsLib.fog,THREE.UniformsLib.lights,THREE.UniformsLib.shadowmap,{ambient:{type:"c",value:new THREE.Color(16777215)},emissive:{type:"c",value:new THREE.Color(0)},wrapRGB:{type:"v3",value:new THREE.Vector3(1,1,1)}}]),vertexShader:["#define LAMBERT\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\nvarying vec3 vLightBack;\n#endif",THREE.ShaderChunk.map_pars_vertex,THREE.ShaderChunk.lightmap_pars_vertex,THREE.ShaderChunk.envmap_pars_vertex,THREE.ShaderChunk.lights_lambert_pars_vertex,THREE.ShaderChunk.color_pars_vertex,
+THREE.ShaderChunk.morphtarget_pars_vertex,THREE.ShaderChunk.skinning_pars_vertex,THREE.ShaderChunk.shadowmap_pars_vertex,"void main() {",THREE.ShaderChunk.map_vertex,THREE.ShaderChunk.lightmap_vertex,THREE.ShaderChunk.color_vertex,THREE.ShaderChunk.morphnormal_vertex,THREE.ShaderChunk.skinbase_vertex,THREE.ShaderChunk.skinnormal_vertex,THREE.ShaderChunk.defaultnormal_vertex,THREE.ShaderChunk.morphtarget_vertex,THREE.ShaderChunk.skinning_vertex,THREE.ShaderChunk.default_vertex,THREE.ShaderChunk.worldpos_vertex,
+THREE.ShaderChunk.envmap_vertex,THREE.ShaderChunk.lights_lambert_vertex,THREE.ShaderChunk.shadowmap_vertex,"}"].join("\n"),fragmentShader:["uniform float opacity;\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\nvarying vec3 vLightBack;\n#endif",THREE.ShaderChunk.color_pars_fragment,THREE.ShaderChunk.map_pars_fragment,THREE.ShaderChunk.lightmap_pars_fragment,THREE.ShaderChunk.envmap_pars_fragment,THREE.ShaderChunk.fog_pars_fragment,THREE.ShaderChunk.shadowmap_pars_fragment,THREE.ShaderChunk.specularmap_pars_fragment,
+"void main() {\ngl_FragColor = vec4( vec3 ( 1.0 ), opacity );",THREE.ShaderChunk.map_fragment,THREE.ShaderChunk.alphatest_fragment,THREE.ShaderChunk.specularmap_fragment,"#ifdef DOUBLE_SIDED\nif ( gl_FrontFacing )\ngl_FragColor.xyz *= vLightFront;\nelse\ngl_FragColor.xyz *= vLightBack;\n#else\ngl_FragColor.xyz *= vLightFront;\n#endif",THREE.ShaderChunk.lightmap_fragment,THREE.ShaderChunk.color_fragment,THREE.ShaderChunk.envmap_fragment,THREE.ShaderChunk.shadowmap_fragment,THREE.ShaderChunk.linear_to_gamma_fragment,
+THREE.ShaderChunk.fog_fragment,"}"].join("\n")},phong:{uniforms:THREE.UniformsUtils.merge([THREE.UniformsLib.common,THREE.UniformsLib.bump,THREE.UniformsLib.normalmap,THREE.UniformsLib.fog,THREE.UniformsLib.lights,THREE.UniformsLib.shadowmap,{ambient:{type:"c",value:new THREE.Color(16777215)},emissive:{type:"c",value:new THREE.Color(0)},specular:{type:"c",value:new THREE.Color(1118481)},shininess:{type:"f",value:30},wrapRGB:{type:"v3",value:new THREE.Vector3(1,1,1)}}]),vertexShader:["#define PHONG\nvarying vec3 vViewPosition;\nvarying vec3 vNormal;",
+THREE.ShaderChunk.map_pars_vertex,THREE.ShaderChunk.lightmap_pars_vertex,THREE.ShaderChunk.envmap_pars_vertex,THREE.ShaderChunk.lights_phong_pars_vertex,THREE.ShaderChunk.color_pars_vertex,THREE.ShaderChunk.morphtarget_pars_vertex,THREE.ShaderChunk.skinning_pars_vertex,THREE.ShaderChunk.shadowmap_pars_vertex,"void main() {",THREE.ShaderChunk.map_vertex,THREE.ShaderChunk.lightmap_vertex,THREE.ShaderChunk.color_vertex,THREE.ShaderChunk.morphnormal_vertex,THREE.ShaderChunk.skinbase_vertex,THREE.ShaderChunk.skinnormal_vertex,
+THREE.ShaderChunk.defaultnormal_vertex,"vNormal = normalize( transformedNormal );",THREE.ShaderChunk.morphtarget_vertex,THREE.ShaderChunk.skinning_vertex,THREE.ShaderChunk.default_vertex,"vViewPosition = -mvPosition.xyz;",THREE.ShaderChunk.worldpos_vertex,THREE.ShaderChunk.envmap_vertex,THREE.ShaderChunk.lights_phong_vertex,THREE.ShaderChunk.shadowmap_vertex,"}"].join("\n"),fragmentShader:["uniform vec3 diffuse;\nuniform float opacity;\nuniform vec3 ambient;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;",
+THREE.ShaderChunk.color_pars_fragment,THREE.ShaderChunk.map_pars_fragment,THREE.ShaderChunk.lightmap_pars_fragment,THREE.ShaderChunk.envmap_pars_fragment,THREE.ShaderChunk.fog_pars_fragment,THREE.ShaderChunk.lights_phong_pars_fragment,THREE.ShaderChunk.shadowmap_pars_fragment,THREE.ShaderChunk.bumpmap_pars_fragment,THREE.ShaderChunk.normalmap_pars_fragment,THREE.ShaderChunk.specularmap_pars_fragment,"void main() {\ngl_FragColor = vec4( vec3 ( 1.0 ), opacity );",THREE.ShaderChunk.map_fragment,THREE.ShaderChunk.alphatest_fragment,
+THREE.ShaderChunk.specularmap_fragment,THREE.ShaderChunk.lights_phong_fragment,THREE.ShaderChunk.lightmap_fragment,THREE.ShaderChunk.color_fragment,THREE.ShaderChunk.envmap_fragment,THREE.ShaderChunk.shadowmap_fragment,THREE.ShaderChunk.linear_to_gamma_fragment,THREE.ShaderChunk.fog_fragment,"}"].join("\n")},particle_basic:{uniforms:THREE.UniformsUtils.merge([THREE.UniformsLib.particle,THREE.UniformsLib.shadowmap]),vertexShader:["uniform float size;\nuniform float scale;",THREE.ShaderChunk.color_pars_vertex,
+THREE.ShaderChunk.shadowmap_pars_vertex,"void main() {",THREE.ShaderChunk.color_vertex,"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n#ifdef USE_SIZEATTENUATION\ngl_PointSize = size * ( scale / length( mvPosition.xyz ) );\n#else\ngl_PointSize = size;\n#endif\ngl_Position = projectionMatrix * mvPosition;",THREE.ShaderChunk.worldpos_vertex,THREE.ShaderChunk.shadowmap_vertex,"}"].join("\n"),fragmentShader:["uniform vec3 psColor;\nuniform float opacity;",THREE.ShaderChunk.color_pars_fragment,
+THREE.ShaderChunk.map_particle_pars_fragment,THREE.ShaderChunk.fog_pars_fragment,THREE.ShaderChunk.shadowmap_pars_fragment,"void main() {\ngl_FragColor = vec4( psColor, opacity );",THREE.ShaderChunk.map_particle_fragment,THREE.ShaderChunk.alphatest_fragment,THREE.ShaderChunk.color_fragment,THREE.ShaderChunk.shadowmap_fragment,THREE.ShaderChunk.fog_fragment,"}"].join("\n")},dashed:{uniforms:THREE.UniformsUtils.merge([THREE.UniformsLib.common,THREE.UniformsLib.fog,{scale:{type:"f",value:1},dashSize:{type:"f",
+value:1},totalSize:{type:"f",value:2}}]),vertexShader:["uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;",THREE.ShaderChunk.color_pars_vertex,"void main() {",THREE.ShaderChunk.color_vertex,"vLineDistance = scale * lineDistance;\nvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\ngl_Position = projectionMatrix * mvPosition;\n}"].join("\n"),fragmentShader:["uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;",
+THREE.ShaderChunk.color_pars_fragment,THREE.ShaderChunk.fog_pars_fragment,"void main() {\nif ( mod( vLineDistance, totalSize ) > dashSize ) {\ndiscard;\n}\ngl_FragColor = vec4( diffuse, opacity );",THREE.ShaderChunk.color_fragment,THREE.ShaderChunk.fog_fragment,"}"].join("\n")},depthRGBA:{uniforms:{},vertexShader:[THREE.ShaderChunk.morphtarget_pars_vertex,THREE.ShaderChunk.skinning_pars_vertex,"void main() {",THREE.ShaderChunk.skinbase_vertex,THREE.ShaderChunk.morphtarget_vertex,THREE.ShaderChunk.skinning_vertex,
+THREE.ShaderChunk.default_vertex,"}"].join("\n"),fragmentShader:"vec4 pack_depth( const in float depth ) {\nconst vec4 bit_shift = vec4( 256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0 );\nconst vec4 bit_mask  = vec4( 0.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0 );\nvec4 res = fract( depth * bit_shift );\nres -= res.xxyz * bit_mask;\nreturn res;\n}\nvoid main() {\ngl_FragData[ 0 ] = pack_depth( gl_FragCoord.z );\n}"}};
+THREE.WebGLRenderer=function(a){function b(a){if(a.__webglCustomAttributesList)for(var b in a.__webglCustomAttributesList)k.deleteBuffer(a.__webglCustomAttributesList[b].buffer)}function c(a,b){var c=a.vertices.length,d=b.material;if(d.attributes){void 0===a.__webglCustomAttributesList&&(a.__webglCustomAttributesList=[]);for(var e in d.attributes){var f=d.attributes[e];if(!f.__webglInitialized||f.createUniqueBuffers){f.__webglInitialized=!0;var g=1;"v2"===f.type?g=2:"v3"===f.type?g=3:"v4"===f.type?
+g=4:"c"===f.type&&(g=3);f.size=g;f.array=new Float32Array(c*g);f.buffer=k.createBuffer();f.buffer.belongsToAttribute=e;f.needsUpdate=!0}a.__webglCustomAttributesList.push(f)}}}function d(a,b){var c=b.geometry,d=a.faces3,h=a.faces4,i=3*d.length+4*h.length,j=1*d.length+2*h.length,h=3*d.length+4*h.length,d=e(b,a),l=g(d),n=f(d),m=d.vertexColors?d.vertexColors:!1;a.__vertexArray=new Float32Array(3*i);n&&(a.__normalArray=new Float32Array(3*i));c.hasTangents&&(a.__tangentArray=new Float32Array(4*i));m&&
+(a.__colorArray=new Float32Array(3*i));if(l){if(0<c.faceUvs.length||0<c.faceVertexUvs.length)a.__uvArray=new Float32Array(2*i);if(1<c.faceUvs.length||1<c.faceVertexUvs.length)a.__uv2Array=new Float32Array(2*i)}b.geometry.skinWeights.length&&b.geometry.skinIndices.length&&(a.__skinIndexArray=new Float32Array(4*i),a.__skinWeightArray=new Float32Array(4*i));a.__faceArray=new Uint16Array(3*j);a.__lineArray=new Uint16Array(2*h);if(a.numMorphTargets){a.__morphTargetsArrays=[];c=0;for(l=a.numMorphTargets;c<
+l;c++)a.__morphTargetsArrays.push(new Float32Array(3*i))}if(a.numMorphNormals){a.__morphNormalsArrays=[];c=0;for(l=a.numMorphNormals;c<l;c++)a.__morphNormalsArrays.push(new Float32Array(3*i))}a.__webglFaceCount=3*j;a.__webglLineCount=2*h;if(d.attributes){void 0===a.__webglCustomAttributesList&&(a.__webglCustomAttributesList=[]);for(var o in d.attributes){var j=d.attributes[o],c={},p;for(p in j)c[p]=j[p];if(!c.__webglInitialized||c.createUniqueBuffers)c.__webglInitialized=!0,h=1,"v2"===c.type?h=2:
+"v3"===c.type?h=3:"v4"===c.type?h=4:"c"===c.type&&(h=3),c.size=h,c.array=new Float32Array(i*h),c.buffer=k.createBuffer(),c.buffer.belongsToAttribute=o,j.needsUpdate=!0,c.__original=j;a.__webglCustomAttributesList.push(c)}}a.__inittedArrays=!0}function e(a,b){return a.material instanceof THREE.MeshFaceMaterial?a.material.materials[b.materialIndex]:a.material}function f(a){return a instanceof THREE.MeshBasicMaterial&&!a.envMap||a instanceof THREE.MeshDepthMaterial?!1:a&&void 0!==a.shading&&a.shading===
+THREE.SmoothShading?THREE.SmoothShading:THREE.FlatShading}function g(a){return a.map||a.lightMap||a.bumpMap||a.normalMap||a.specularMap||a instanceof THREE.ShaderMaterial?!0:!1}function h(a){var b,c,d;for(b in a.attributes)d="index"===b?k.ELEMENT_ARRAY_BUFFER:k.ARRAY_BUFFER,c=a.attributes[b],c.buffer=k.createBuffer(),k.bindBuffer(d,c.buffer),k.bufferData(d,c.array,k.STATIC_DRAW)}function i(a,b,c){var d,e,f,g,h=a.vertices;g=h.length;var i=a.colors,j=i.length,l=a.__vertexArray,n=a.__colorArray,m=a.__sortArray,
+o=a.verticesNeedUpdate,p=a.colorsNeedUpdate,s=a.__webglCustomAttributesList;if(c.sortParticles){pb.copy(eb);pb.multiplySelf(c.matrixWorld);for(d=0;d<g;d++)e=h[d],bb.copy(e),pb.multiplyVector3(bb),m[d]=[bb.z,d];m.sort(function(a,b){return b[0]-a[0]});for(d=0;d<g;d++)e=h[m[d][1]],f=3*d,l[f]=e.x,l[f+1]=e.y,l[f+2]=e.z;for(d=0;d<j;d++)f=3*d,e=i[m[d][1]],n[f]=e.r,n[f+1]=e.g,n[f+2]=e.b;if(s){i=0;for(j=s.length;i<j;i++)if(h=s[i],void 0===h.boundTo||"vertices"===h.boundTo)if(f=0,e=h.value.length,1===h.size)for(d=
+0;d<e;d++)g=m[d][1],h.array[d]=h.value[g];else if(2===h.size)for(d=0;d<e;d++)g=m[d][1],g=h.value[g],h.array[f]=g.x,h.array[f+1]=g.y,f+=2;else if(3===h.size)if("c"===h.type)for(d=0;d<e;d++)g=m[d][1],g=h.value[g],h.array[f]=g.r,h.array[f+1]=g.g,h.array[f+2]=g.b,f+=3;else for(d=0;d<e;d++)g=m[d][1],g=h.value[g],h.array[f]=g.x,h.array[f+1]=g.y,h.array[f+2]=g.z,f+=3;else if(4===h.size)for(d=0;d<e;d++)g=m[d][1],g=h.value[g],h.array[f]=g.x,h.array[f+1]=g.y,h.array[f+2]=g.z,h.array[f+3]=g.w,f+=4}}else{if(o)for(d=
+0;d<g;d++)e=h[d],f=3*d,l[f]=e.x,l[f+1]=e.y,l[f+2]=e.z;if(p)for(d=0;d<j;d++)e=i[d],f=3*d,n[f]=e.r,n[f+1]=e.g,n[f+2]=e.b;if(s){i=0;for(j=s.length;i<j;i++)if(h=s[i],h.needsUpdate&&(void 0===h.boundTo||"vertices"===h.boundTo))if(e=h.value.length,f=0,1===h.size)for(d=0;d<e;d++)h.array[d]=h.value[d];else if(2===h.size)for(d=0;d<e;d++)g=h.value[d],h.array[f]=g.x,h.array[f+1]=g.y,f+=2;else if(3===h.size)if("c"===h.type)for(d=0;d<e;d++)g=h.value[d],h.array[f]=g.r,h.array[f+1]=g.g,h.array[f+2]=g.b,f+=3;else for(d=
+0;d<e;d++)g=h.value[d],h.array[f]=g.x,h.array[f+1]=g.y,h.array[f+2]=g.z,f+=3;else if(4===h.size)for(d=0;d<e;d++)g=h.value[d],h.array[f]=g.x,h.array[f+1]=g.y,h.array[f+2]=g.z,h.array[f+3]=g.w,f+=4}}if(o||c.sortParticles)k.bindBuffer(k.ARRAY_BUFFER,a.__webglVertexBuffer),k.bufferData(k.ARRAY_BUFFER,l,b);if(p||c.sortParticles)k.bindBuffer(k.ARRAY_BUFFER,a.__webglColorBuffer),k.bufferData(k.ARRAY_BUFFER,n,b);if(s){i=0;for(j=s.length;i<j;i++)if(h=s[i],h.needsUpdate||c.sortParticles)k.bindBuffer(k.ARRAY_BUFFER,
+h.buffer),k.bufferData(k.ARRAY_BUFFER,h.array,b)}}function j(a,b,c){var d=a.attributes,e=d.index,f=d.position,g=d.normal,h=d.uv,i=d.color,d=d.tangent;a.elementsNeedUpdate&&void 0!==e&&(k.bindBuffer(k.ELEMENT_ARRAY_BUFFER,e.buffer),k.bufferData(k.ELEMENT_ARRAY_BUFFER,e.array,b));a.verticesNeedUpdate&&void 0!==f&&(k.bindBuffer(k.ARRAY_BUFFER,f.buffer),k.bufferData(k.ARRAY_BUFFER,f.array,b));a.normalsNeedUpdate&&void 0!==g&&(k.bindBuffer(k.ARRAY_BUFFER,g.buffer),k.bufferData(k.ARRAY_BUFFER,g.array,b));
+a.uvsNeedUpdate&&void 0!==h&&(k.bindBuffer(k.ARRAY_BUFFER,h.buffer),k.bufferData(k.ARRAY_BUFFER,h.array,b));a.colorsNeedUpdate&&void 0!==i&&(k.bindBuffer(k.ARRAY_BUFFER,i.buffer),k.bufferData(k.ARRAY_BUFFER,i.array,b));a.tangentsNeedUpdate&&void 0!==d&&(k.bindBuffer(k.ARRAY_BUFFER,d.buffer),k.bufferData(k.ARRAY_BUFFER,d.array,b));if(c)for(var j in a.attributes)delete a.attributes[j].array}function l(a,b){return a.z!==b.z?b.z-a.z:b.id-a.id}function m(a,b){return b[1]-a[1]}function n(a,b,c){if(a.length)for(var d=
+0,e=a.length;d<e;d++)aa=fa=null,Y=ba=Ja=Na=ob=ib=ma=-1,mb=!0,a[d].render(b,c,lb,ab),aa=fa=null,Y=ba=Ja=Na=ob=ib=ma=-1,mb=!0}function p(a,b,c,d,e,f,g,h){var i,k,j,l;b?(k=a.length-1,l=b=-1):(k=0,b=a.length,l=1);for(var n=k;n!==b;n+=l)if(i=a[n],i.render){k=i.object;j=i.buffer;if(h)i=h;else{i=i[c];if(!i)continue;g&&L.setBlending(i.blending,i.blendEquation,i.blendSrc,i.blendDst);L.setDepthTest(i.depthTest);L.setDepthWrite(i.depthWrite);D(i.polygonOffset,i.polygonOffsetFactor,i.polygonOffsetUnits)}L.setMaterialFaces(i);
+j instanceof THREE.BufferGeometry?L.renderBufferDirect(d,e,f,i,j,k):L.renderBuffer(d,e,f,i,j,k)}}function o(a,b,c,d,e,f,g){for(var h,i,k=0,j=a.length;k<j;k++)if(h=a[k],i=h.object,i.visible){if(g)h=g;else{h=h[b];if(!h)continue;f&&L.setBlending(h.blending,h.blendEquation,h.blendSrc,h.blendDst);L.setDepthTest(h.depthTest);L.setDepthWrite(h.depthWrite);D(h.polygonOffset,h.polygonOffsetFactor,h.polygonOffsetUnits)}L.renderImmediateObject(c,d,e,h,i)}}function s(a,b,c){a.push({buffer:b,object:c,opaque:null,
+transparent:null})}function t(a){for(var b in a.attributes)if(a.attributes[b].needsUpdate)return!0;return!1}function r(a){for(var b in a.attributes)a.attributes[b].needsUpdate=!1}function z(a,b){for(var c=a.length-1;0<=c;c--)a[c].object===b&&a.splice(c,1)}function w(a,b){for(var c=a.length-1;0<=c;c--)a[c]===b&&a.splice(c,1)}function q(a,b,c,d,e){Aa=0;d.needsUpdate&&(d.program&&L.deallocateMaterial(d),L.initMaterial(d,b,c,e),d.needsUpdate=!1);d.morphTargets&&!e.__webglMorphTargetInfluences&&(e.__webglMorphTargetInfluences=
+new Float32Array(L.maxMorphTargets));var f=!1,g=d.program,h=g.uniforms,i=d.uniforms;g!==fa&&(k.useProgram(g),fa=g,f=!0);d.id!==Y&&(Y=d.id,f=!0);if(f||a!==aa)k.uniformMatrix4fv(h.projectionMatrix,!1,a._projectionMatrixArray),a!==aa&&(aa=a);if(d.skinning)if(hc&&e.useVertexTexture){if(null!==h.boneTexture){var j=E();k.uniform1i(h.boneTexture,j);L.setTexture(e.boneTexture,j)}}else null!==h.boneGlobalMatrices&&k.uniformMatrix4fv(h.boneGlobalMatrices,!1,e.boneMatrices);if(f){c&&d.fog&&(i.fogColor.value=
+c.color,c instanceof THREE.Fog?(i.fogNear.value=c.near,i.fogFar.value=c.far):c instanceof THREE.FogExp2&&(i.fogDensity.value=c.density));if(d instanceof THREE.MeshPhongMaterial||d instanceof THREE.MeshLambertMaterial||d.lights){if(mb){for(var l=0,n=0,m=0,o,p,s,r=sb,q=r.directional.colors,t=r.directional.positions,w=r.point.colors,z=r.point.positions,A=r.point.distances,B=r.spot.colors,C=r.spot.positions,D=r.spot.distances,G=r.spot.directions,X=r.spot.anglesCos,J=r.spot.exponents,K=r.hemi.skyColors,
+Q=r.hemi.groundColors,M=r.hemi.positions,O=0,ca=0,N=0,R=0,ia=0,Z=0,ba=0,ga=0,qa=p=0,c=qa=qa=0,f=b.length;c<f;c++)j=b[c],j.onlyShadow||(o=j.color,s=j.intensity,p=j.distance,j instanceof THREE.AmbientLight?j.visible&&(L.gammaInput?(l+=o.r*o.r,n+=o.g*o.g,m+=o.b*o.b):(l+=o.r,n+=o.g,m+=o.b)):j instanceof THREE.DirectionalLight?(ia+=1,j.visible&&(p=3*O,L.gammaInput?v(q,p,o,s*s):u(q,p,o,s),xa.copy(j.matrixWorld.getPosition()),xa.subSelf(j.target.matrixWorld.getPosition()),xa.normalize(),t[p]=xa.x,t[p+1]=
+xa.y,t[p+2]=xa.z,O+=1)):j instanceof THREE.PointLight?(Z+=1,j.visible&&(qa=3*ca,L.gammaInput?v(w,qa,o,s*s):u(w,qa,o,s),s=j.matrixWorld.getPosition(),z[qa]=s.x,z[qa+1]=s.y,z[qa+2]=s.z,A[ca]=p,ca+=1)):j instanceof THREE.SpotLight?(ba+=1,j.visible&&(qa=3*N,L.gammaInput?v(B,qa,o,s*s):u(B,qa,o,s),s=j.matrixWorld.getPosition(),C[qa]=s.x,C[qa+1]=s.y,C[qa+2]=s.z,D[N]=p,xa.copy(s),xa.subSelf(j.target.matrixWorld.getPosition()),xa.normalize(),G[qa]=xa.x,G[qa+1]=xa.y,G[qa+2]=xa.z,X[N]=Math.cos(j.angle),J[N]=
+j.exponent,N+=1)):j instanceof THREE.HemisphereLight&&(ga+=1,j.visible&&(o=j.color,p=j.groundColor,qa=3*R,L.gammaInput?(s*=s,v(K,qa,o,s),v(Q,qa,p,s)):(u(K,qa,o,s),u(Q,qa,p,s)),xa.copy(j.matrixWorld.getPosition()),xa.normalize(),M[qa]=xa.x,M[qa+1]=xa.y,M[qa+2]=xa.z,R+=1)));c=3*O;for(f=Math.max(q.length,3*ia);c<f;c++)q[c]=0;c=3*O;for(f=Math.max(t.length,3*ia);c<f;c++)t[c]=0;c=3*ca;for(f=Math.max(w.length,3*Z);c<f;c++)w[c]=0;c=3*ca;for(f=Math.max(z.length,3*Z);c<f;c++)z[c]=0;c=ca;for(f=Math.max(A.length,
+Z);c<f;c++)A[c]=0;c=3*N;for(f=Math.max(B.length,3*ba);c<f;c++)B[c]=0;c=3*N;for(f=Math.max(C.length,3*ba);c<f;c++)C[c]=0;c=3*N;for(f=Math.max(G.length,3*ba);c<f;c++)G[c]=0;c=N;for(f=Math.max(X.length,ba);c<f;c++)X[c]=0;c=N;for(f=Math.max(J.length,ba);c<f;c++)J[c]=0;c=N;for(f=Math.max(D.length,ba);c<f;c++)D[c]=0;c=3*R;for(f=Math.max(K.length,3*ga);c<f;c++)K[c]=0;c=3*R;for(f=Math.max(Q.length,3*ga);c<f;c++)Q[c]=0;c=3*R;for(f=Math.max(M.length,3*ga);c<f;c++)M[c]=0;r.directional.length=O;r.point.length=
+ca;r.spot.length=N;r.hemi.length=R;r.ambient[0]=l;r.ambient[1]=n;r.ambient[2]=m;mb=!1}c=sb;i.ambientLightColor.value=c.ambient;i.directionalLightColor.value=c.directional.colors;i.directionalLightDirection.value=c.directional.positions;i.pointLightColor.value=c.point.colors;i.pointLightPosition.value=c.point.positions;i.pointLightDistance.value=c.point.distances;i.spotLightColor.value=c.spot.colors;i.spotLightPosition.value=c.spot.positions;i.spotLightDistance.value=c.spot.distances;i.spotLightDirection.value=
+c.spot.directions;i.spotLightAngleCos.value=c.spot.anglesCos;i.spotLightExponent.value=c.spot.exponents;i.hemisphereLightSkyColor.value=c.hemi.skyColors;i.hemisphereLightGroundColor.value=c.hemi.groundColors;i.hemisphereLightDirection.value=c.hemi.positions}if(d instanceof THREE.MeshBasicMaterial||d instanceof THREE.MeshLambertMaterial||d instanceof THREE.MeshPhongMaterial){i.opacity.value=d.opacity;L.gammaInput?i.diffuse.value.copyGammaToLinear(d.color):i.diffuse.value=d.color;i.map.value=d.map;
+i.lightMap.value=d.lightMap;i.specularMap.value=d.specularMap;d.bumpMap&&(i.bumpMap.value=d.bumpMap,i.bumpScale.value=d.bumpScale);d.normalMap&&(i.normalMap.value=d.normalMap,i.normalScale.value.copy(d.normalScale));var T;d.map?T=d.map:d.specularMap?T=d.specularMap:d.normalMap?T=d.normalMap:d.bumpMap&&(T=d.bumpMap);void 0!==T&&(c=T.offset,T=T.repeat,i.offsetRepeat.value.set(c.x,c.y,T.x,T.y));i.envMap.value=d.envMap;i.flipEnvMap.value=d.envMap instanceof THREE.WebGLRenderTargetCube?1:-1;i.reflectivity.value=
+d.reflectivity;i.refractionRatio.value=d.refractionRatio;i.combine.value=d.combine;i.useRefract.value=d.envMap&&d.envMap.mapping instanceof THREE.CubeRefractionMapping}d instanceof THREE.LineBasicMaterial?(i.diffuse.value=d.color,i.opacity.value=d.opacity):d instanceof THREE.LineDashedMaterial?(i.diffuse.value=d.color,i.opacity.value=d.opacity,i.dashSize.value=d.dashSize,i.totalSize.value=d.dashSize+d.gapSize,i.scale.value=d.scale):d instanceof THREE.ParticleBasicMaterial?(i.psColor.value=d.color,
+i.opacity.value=d.opacity,i.size.value=d.size,i.scale.value=I.height/2,i.map.value=d.map):d instanceof THREE.MeshPhongMaterial?(i.shininess.value=d.shininess,L.gammaInput?(i.ambient.value.copyGammaToLinear(d.ambient),i.emissive.value.copyGammaToLinear(d.emissive),i.specular.value.copyGammaToLinear(d.specular)):(i.ambient.value=d.ambient,i.emissive.value=d.emissive,i.specular.value=d.specular),d.wrapAround&&i.wrapRGB.value.copy(d.wrapRGB)):d instanceof THREE.MeshLambertMaterial?(L.gammaInput?(i.ambient.value.copyGammaToLinear(d.ambient),
+i.emissive.value.copyGammaToLinear(d.emissive)):(i.ambient.value=d.ambient,i.emissive.value=d.emissive),d.wrapAround&&i.wrapRGB.value.copy(d.wrapRGB)):d instanceof THREE.MeshDepthMaterial?(i.mNear.value=a.near,i.mFar.value=a.far,i.opacity.value=d.opacity):d instanceof THREE.MeshNormalMaterial&&(i.opacity.value=d.opacity);if(e.receiveShadow&&!d._shadowPass&&i.shadowMatrix){c=T=0;for(f=b.length;c<f;c++)if(j=b[c],j.castShadow&&(j instanceof THREE.SpotLight||j instanceof THREE.DirectionalLight&&!j.shadowCascade))i.shadowMap.value[T]=
+j.shadowMap,i.shadowMapSize.value[T]=j.shadowMapSize,i.shadowMatrix.value[T]=j.shadowMatrix,i.shadowDarkness.value[T]=j.shadowDarkness,i.shadowBias.value[T]=j.shadowBias,T++}b=d.uniformsList;i=0;for(T=b.length;i<T;i++)if(f=g.uniforms[b[i][1]])if(c=b[i][0],l=c.type,j=c.value,"i"===l)k.uniform1i(f,j);else if("f"===l)k.uniform1f(f,j);else if("v2"===l)k.uniform2f(f,j.x,j.y);else if("v3"===l)k.uniform3f(f,j.x,j.y,j.z);else if("v4"===l)k.uniform4f(f,j.x,j.y,j.z,j.w);else if("c"===l)k.uniform3f(f,j.r,j.g,
+j.b);else if("iv1"===l)k.uniform1iv(f,j);else if("iv"===l)k.uniform3iv(f,j);else if("fv1"===l)k.uniform1fv(f,j);else if("fv"===l)k.uniform3fv(f,j);else if("v2v"===l){void 0===c._array&&(c._array=new Float32Array(2*j.length));l=0;for(n=j.length;l<n;l++)m=2*l,c._array[m]=j[l].x,c._array[m+1]=j[l].y;k.uniform2fv(f,c._array)}else if("v3v"===l){void 0===c._array&&(c._array=new Float32Array(3*j.length));l=0;for(n=j.length;l<n;l++)m=3*l,c._array[m]=j[l].x,c._array[m+1]=j[l].y,c._array[m+2]=j[l].z;k.uniform3fv(f,
+c._array)}else if("v4v"===l){void 0===c._array&&(c._array=new Float32Array(4*j.length));l=0;for(n=j.length;l<n;l++)m=4*l,c._array[m]=j[l].x,c._array[m+1]=j[l].y,c._array[m+2]=j[l].z,c._array[m+3]=j[l].w;k.uniform4fv(f,c._array)}else if("m4"===l)void 0===c._array&&(c._array=new Float32Array(16)),j.flattenToArray(c._array),k.uniformMatrix4fv(f,!1,c._array);else if("m4v"===l){void 0===c._array&&(c._array=new Float32Array(16*j.length));l=0;for(n=j.length;l<n;l++)j[l].flattenToArrayOffset(c._array,16*
+l);k.uniformMatrix4fv(f,!1,c._array)}else if("t"===l){if(m=j,j=E(),k.uniform1i(f,j),m)if(m.image instanceof Array&&6===m.image.length){if(c=m,f=j,6===c.image.length)if(c.needsUpdate){c.image.__webglTextureCube||(c.image.__webglTextureCube=k.createTexture());k.activeTexture(k.TEXTURE0+f);k.bindTexture(k.TEXTURE_CUBE_MAP,c.image.__webglTextureCube);k.pixelStorei(k.UNPACK_FLIP_Y_WEBGL,c.flipY);f=c instanceof THREE.CompressedTexture;j=[];for(l=0;6>l;l++)L.autoScaleCubemaps&&!f?(n=j,m=l,r=c.image[l],t=
+Qc,r.width<=t&&r.height<=t||(w=Math.max(r.width,r.height),q=Math.floor(r.width*t/w),t=Math.floor(r.height*t/w),w=document.createElement("canvas"),w.width=q,w.height=t,w.getContext("2d").drawImage(r,0,0,r.width,r.height,0,0,q,t),r=w),n[m]=r):j[l]=c.image[l];l=j[0];n=0===(l.width&l.width-1)&&0===(l.height&l.height-1);m=H(c.format);r=H(c.type);P(k.TEXTURE_CUBE_MAP,c,n);for(l=0;6>l;l++)if(f){t=j[l].mipmaps;w=0;for(z=t.length;w<z;w++)q=t[w],k.compressedTexImage2D(k.TEXTURE_CUBE_MAP_POSITIVE_X+l,w,m,q.width,
+q.height,0,q.data)}else k.texImage2D(k.TEXTURE_CUBE_MAP_POSITIVE_X+l,0,m,m,r,j[l]);c.generateMipmaps&&n&&k.generateMipmap(k.TEXTURE_CUBE_MAP);c.needsUpdate=!1;if(c.onUpdate)c.onUpdate()}else k.activeTexture(k.TEXTURE0+f),k.bindTexture(k.TEXTURE_CUBE_MAP,c.image.__webglTextureCube)}else m instanceof THREE.WebGLRenderTargetCube?(c=m,k.activeTexture(k.TEXTURE0+j),k.bindTexture(k.TEXTURE_CUBE_MAP,c.__webglTexture)):L.setTexture(m,j)}else if("tv"===l){void 0===c._array&&(c._array=[]);l=0;for(n=c.value.length;l<
+n;l++)c._array[l]=E();k.uniform1iv(f,c._array);l=0;for(n=c.value.length;l<n;l++)m=c.value[l],j=c._array[l],m&&L.setTexture(m,j)}if((d instanceof THREE.ShaderMaterial||d instanceof THREE.MeshPhongMaterial||d.envMap)&&null!==h.cameraPosition)b=a.matrixWorld.getPosition(),k.uniform3f(h.cameraPosition,b.x,b.y,b.z);(d instanceof THREE.MeshPhongMaterial||d instanceof THREE.MeshLambertMaterial||d instanceof THREE.ShaderMaterial||d.skinning)&&null!==h.viewMatrix&&k.uniformMatrix4fv(h.viewMatrix,!1,a._viewMatrixArray)}k.uniformMatrix4fv(h.modelViewMatrix,
+!1,e._modelViewMatrix.elements);h.normalMatrix&&k.uniformMatrix3fv(h.normalMatrix,!1,e._normalMatrix.elements);null!==h.modelMatrix&&k.uniformMatrix4fv(h.modelMatrix,!1,e.matrixWorld.elements);return g}function E(){var a=Aa;a>=xc&&console.warn("Trying to use "+a+" texture units while this GPU supports only "+xc);Aa+=1;return a}function A(a,b){a._modelViewMatrix.multiply(b.matrixWorldInverse,a.matrixWorld);a._normalMatrix.getInverse(a._modelViewMatrix);a._normalMatrix.transpose()}function v(a,b,c,
+d){a[b]=c.r*c.r*d;a[b+1]=c.g*c.g*d;a[b+2]=c.b*c.b*d}function u(a,b,c,d){a[b]=c.r*d;a[b+1]=c.g*d;a[b+2]=c.b*d}function D(a,b,c){jb!==a&&(a?k.enable(k.POLYGON_OFFSET_FILL):k.disable(k.POLYGON_OFFSET_FILL),jb=a);if(a&&(Bb!==b||Cb!==c))k.polygonOffset(b,c),Bb=b,Cb=c}function C(a){for(var a=a.split("\n"),b=0,c=a.length;b<c;b++)a[b]=b+1+": "+a[b];return a.join("\n")}function G(a,b){var c;"fragment"===a?c=k.createShader(k.FRAGMENT_SHADER):"vertex"===a&&(c=k.createShader(k.VERTEX_SHADER));k.shaderSource(c,
+b);k.compileShader(c);return!k.getShaderParameter(c,k.COMPILE_STATUS)?(console.error(k.getShaderInfoLog(c)),console.error(C(b)),null):c}function P(a,b,c){c?(k.texParameteri(a,k.TEXTURE_WRAP_S,H(b.wrapS)),k.texParameteri(a,k.TEXTURE_WRAP_T,H(b.wrapT)),k.texParameteri(a,k.TEXTURE_MAG_FILTER,H(b.magFilter)),k.texParameteri(a,k.TEXTURE_MIN_FILTER,H(b.minFilter))):(k.texParameteri(a,k.TEXTURE_WRAP_S,k.CLAMP_TO_EDGE),k.texParameteri(a,k.TEXTURE_WRAP_T,k.CLAMP_TO_EDGE),k.texParameteri(a,k.TEXTURE_MAG_FILTER,
+K(b.magFilter)),k.texParameteri(a,k.TEXTURE_MIN_FILTER,K(b.minFilter)));if(zb&&b.type!==THREE.FloatType&&(1<b.anisotropy||b.__oldAnisotropy))k.texParameterf(a,zb.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(b.anisotropy,oc)),b.__oldAnisotropy=b.anisotropy}function B(a,b){k.bindRenderbuffer(k.RENDERBUFFER,a);b.depthBuffer&&!b.stencilBuffer?(k.renderbufferStorage(k.RENDERBUFFER,k.DEPTH_COMPONENT16,b.width,b.height),k.framebufferRenderbuffer(k.FRAMEBUFFER,k.DEPTH_ATTACHMENT,k.RENDERBUFFER,a)):b.depthBuffer&&
+b.stencilBuffer?(k.renderbufferStorage(k.RENDERBUFFER,k.DEPTH_STENCIL,b.width,b.height),k.framebufferRenderbuffer(k.FRAMEBUFFER,k.DEPTH_STENCIL_ATTACHMENT,k.RENDERBUFFER,a)):k.renderbufferStorage(k.RENDERBUFFER,k.RGBA4,b.width,b.height)}function K(a){return a===THREE.NearestFilter||a===THREE.NearestMipMapNearestFilter||a===THREE.NearestMipMapLinearFilter?k.NEAREST:k.LINEAR}function H(a){if(a===THREE.RepeatWrapping)return k.REPEAT;if(a===THREE.ClampToEdgeWrapping)return k.CLAMP_TO_EDGE;if(a===THREE.MirroredRepeatWrapping)return k.MIRRORED_REPEAT;
+if(a===THREE.NearestFilter)return k.NEAREST;if(a===THREE.NearestMipMapNearestFilter)return k.NEAREST_MIPMAP_NEAREST;if(a===THREE.NearestMipMapLinearFilter)return k.NEAREST_MIPMAP_LINEAR;if(a===THREE.LinearFilter)return k.LINEAR;if(a===THREE.LinearMipMapNearestFilter)return k.LINEAR_MIPMAP_NEAREST;if(a===THREE.LinearMipMapLinearFilter)return k.LINEAR_MIPMAP_LINEAR;if(a===THREE.UnsignedByteType)return k.UNSIGNED_BYTE;if(a===THREE.UnsignedShort4444Type)return k.UNSIGNED_SHORT_4_4_4_4;if(a===THREE.UnsignedShort5551Type)return k.UNSIGNED_SHORT_5_5_5_1;
+if(a===THREE.UnsignedShort565Type)return k.UNSIGNED_SHORT_5_6_5;if(a===THREE.ByteType)return k.BYTE;if(a===THREE.ShortType)return k.SHORT;if(a===THREE.UnsignedShortType)return k.UNSIGNED_SHORT;if(a===THREE.IntType)return k.INT;if(a===THREE.UnsignedIntType)return k.UNSIGNED_INT;if(a===THREE.FloatType)return k.FLOAT;if(a===THREE.AlphaFormat)return k.ALPHA;if(a===THREE.RGBFormat)return k.RGB;if(a===THREE.RGBAFormat)return k.RGBA;if(a===THREE.LuminanceFormat)return k.LUMINANCE;if(a===THREE.LuminanceAlphaFormat)return k.LUMINANCE_ALPHA;
+if(a===THREE.AddEquation)return k.FUNC_ADD;if(a===THREE.SubtractEquation)return k.FUNC_SUBTRACT;if(a===THREE.ReverseSubtractEquation)return k.FUNC_REVERSE_SUBTRACT;if(a===THREE.ZeroFactor)return k.ZERO;if(a===THREE.OneFactor)return k.ONE;if(a===THREE.SrcColorFactor)return k.SRC_COLOR;if(a===THREE.OneMinusSrcColorFactor)return k.ONE_MINUS_SRC_COLOR;if(a===THREE.SrcAlphaFactor)return k.SRC_ALPHA;if(a===THREE.OneMinusSrcAlphaFactor)return k.ONE_MINUS_SRC_ALPHA;if(a===THREE.DstAlphaFactor)return k.DST_ALPHA;
+if(a===THREE.OneMinusDstAlphaFactor)return k.ONE_MINUS_DST_ALPHA;if(a===THREE.DstColorFactor)return k.DST_COLOR;if(a===THREE.OneMinusDstColorFactor)return k.ONE_MINUS_DST_COLOR;if(a===THREE.SrcAlphaSaturateFactor)return k.SRC_ALPHA_SATURATE;if(void 0!==qb){if(a===THREE.RGB_S3TC_DXT1_Format)return qb.COMPRESSED_RGB_S3TC_DXT1_EXT;if(a===THREE.RGBA_S3TC_DXT1_Format)return qb.COMPRESSED_RGBA_S3TC_DXT1_EXT;if(a===THREE.RGBA_S3TC_DXT3_Format)return qb.COMPRESSED_RGBA_S3TC_DXT3_EXT;if(a===THREE.RGBA_S3TC_DXT5_Format)return qb.COMPRESSED_RGBA_S3TC_DXT5_EXT}return 0}
+console.log("THREE.WebGLRenderer",THREE.REVISION);var a=a||{},I=void 0!==a.canvas?a.canvas:document.createElement("canvas"),N=void 0!==a.precision?a.precision:"highp",O=void 0!==a.alpha?a.alpha:!0,R=void 0!==a.premultipliedAlpha?a.premultipliedAlpha:!0,ga=void 0!==a.antialias?a.antialias:!1,M=void 0!==a.stencil?a.stencil:!0,J=void 0!==a.preserveDrawingBuffer?a.preserveDrawingBuffer:!1,Q=void 0!==a.clearColor?new THREE.Color(a.clearColor):new THREE.Color(0),Z=void 0!==a.clearAlpha?a.clearAlpha:0;this.domElement=
+I;this.context=null;this.autoUpdateScene=this.autoUpdateObjects=this.sortObjects=this.autoClearStencil=this.autoClearDepth=this.autoClearColor=this.autoClear=!0;this.shadowMapEnabled=this.physicallyBasedShading=this.gammaOutput=this.gammaInput=!1;this.shadowMapCullFrontFaces=this.shadowMapSoft=this.shadowMapAutoUpdate=!0;this.shadowMapCascade=this.shadowMapDebug=!1;this.maxMorphTargets=8;this.maxMorphNormals=4;this.autoScaleCubemaps=!0;this.renderPluginsPre=[];this.renderPluginsPost=[];this.info=
+{memory:{programs:0,geometries:0,textures:0},render:{calls:0,vertices:0,faces:0,points:0}};var L=this,oa=[],X=0,fa=null,ca=null,Y=-1,ba=null,aa=null,ia=0,Aa=0,Na=-1,Ja=-1,ma=-1,sa=-1,Ea=-1,rb=-1,ib=-1,ob=-1,jb=null,Bb=null,Cb=null,Wa=null,Sa=0,Ka=0,kb=0,Oa=0,lb=0,ab=0,va=new THREE.Frustum,eb=new THREE.Matrix4,pb=new THREE.Matrix4,bb=new THREE.Vector4,xa=new THREE.Vector3,mb=!0,sb={ambient:[0,0,0],directional:{length:0,colors:[],positions:[]},point:{length:0,colors:[],positions:[],distances:[]},spot:{length:0,
+colors:[],positions:[],distances:[],directions:[],anglesCos:[],exponents:[]},hemi:{length:0,skyColors:[],groundColors:[],positions:[]}},k,zb,qb;try{if(!(k=I.getContext("experimental-webgl",{alpha:O,premultipliedAlpha:R,antialias:ga,stencil:M,preserveDrawingBuffer:J})))throw"Error creating WebGL context.";}catch(Pc){console.error(Pc)}a=k.getExtension("OES_texture_float");O=k.getExtension("OES_standard_derivatives");zb=k.getExtension("EXT_texture_filter_anisotropic")||k.getExtension("MOZ_EXT_texture_filter_anisotropic")||
+k.getExtension("WEBKIT_EXT_texture_filter_anisotropic");qb=k.getExtension("WEBGL_compressed_texture_s3tc")||k.getExtension("MOZ_WEBGL_compressed_texture_s3tc")||k.getExtension("WEBKIT_WEBGL_compressed_texture_s3tc");a||console.log("THREE.WebGLRenderer: Float textures not supported.");O||console.log("THREE.WebGLRenderer: Standard derivatives not supported.");zb||console.log("THREE.WebGLRenderer: Anisotropic texture filtering not supported.");qb||console.log("THREE.WebGLRenderer: S3TC compressed textures not supported.");
+k.clearColor(0,0,0,1);k.clearDepth(1);k.clearStencil(0);k.enable(k.DEPTH_TEST);k.depthFunc(k.LEQUAL);k.frontFace(k.CCW);k.cullFace(k.BACK);k.enable(k.CULL_FACE);k.enable(k.BLEND);k.blendEquation(k.FUNC_ADD);k.blendFunc(k.SRC_ALPHA,k.ONE_MINUS_SRC_ALPHA);k.clearColor(Q.r,Q.g,Q.b,Z);this.context=k;var xc=k.getParameter(k.MAX_TEXTURE_IMAGE_UNITS),O=k.getParameter(k.MAX_VERTEX_TEXTURE_IMAGE_UNITS);k.getParameter(k.MAX_TEXTURE_SIZE);var Qc=k.getParameter(k.MAX_CUBE_MAP_TEXTURE_SIZE),oc=zb?k.getParameter(zb.MAX_TEXTURE_MAX_ANISOTROPY_EXT):
+0,gc=0<O,hc=gc&&a;qb&&k.getParameter(k.COMPRESSED_TEXTURE_FORMATS);this.getContext=function(){return k};this.supportsVertexTextures=function(){return gc};this.getMaxAnisotropy=function(){return oc};this.setSize=function(a,b){I.width=a;I.height=b;this.setViewport(0,0,I.width,I.height)};this.setViewport=function(a,b,c,d){Sa=void 0!==a?a:0;Ka=void 0!==b?b:0;kb=void 0!==c?c:I.width;Oa=void 0!==d?d:I.height;k.viewport(Sa,Ka,kb,Oa)};this.setScissor=function(a,b,c,d){k.scissor(a,b,c,d)};this.enableScissorTest=
+function(a){a?k.enable(k.SCISSOR_TEST):k.disable(k.SCISSOR_TEST)};this.setClearColorHex=function(a,b){Q.setHex(a);Z=b;k.clearColor(Q.r,Q.g,Q.b,Z)};this.setClearColor=function(a,b){Q.copy(a);Z=b;k.clearColor(Q.r,Q.g,Q.b,Z)};this.getClearColor=function(){return Q};this.getClearAlpha=function(){return Z};this.clear=function(a,b,c){var d=0;if(void 0===a||a)d|=k.COLOR_BUFFER_BIT;if(void 0===b||b)d|=k.DEPTH_BUFFER_BIT;if(void 0===c||c)d|=k.STENCIL_BUFFER_BIT;k.clear(d)};this.clearTarget=function(a,b,c,
+d){this.setRenderTarget(a);this.clear(b,c,d)};this.addPostPlugin=function(a){a.init(this);this.renderPluginsPost.push(a)};this.addPrePlugin=function(a){a.init(this);this.renderPluginsPre.push(a)};this.deallocateObject=function(a){if(a.__webglInit)if(a.__webglInit=!1,delete a._modelViewMatrix,delete a._normalMatrix,delete a._normalMatrixArray,delete a._modelViewMatrixArray,delete a._modelMatrixArray,a instanceof THREE.Mesh)for(var c in a.geometry.geometryGroups){var d=a.geometry.geometryGroups[c];
+k.deleteBuffer(d.__webglVertexBuffer);k.deleteBuffer(d.__webglNormalBuffer);k.deleteBuffer(d.__webglTangentBuffer);k.deleteBuffer(d.__webglColorBuffer);k.deleteBuffer(d.__webglUVBuffer);k.deleteBuffer(d.__webglUV2Buffer);k.deleteBuffer(d.__webglSkinIndicesBuffer);k.deleteBuffer(d.__webglSkinWeightsBuffer);k.deleteBuffer(d.__webglFaceBuffer);k.deleteBuffer(d.__webglLineBuffer);var e=void 0,f=void 0;if(d.numMorphTargets){e=0;for(f=d.numMorphTargets;e<f;e++)k.deleteBuffer(d.__webglMorphTargetsBuffers[e])}if(d.numMorphNormals){e=
+0;for(f=d.numMorphNormals;e<f;e++)k.deleteBuffer(d.__webglMorphNormalsBuffers[e])}b(d);L.info.memory.geometries--}else a instanceof THREE.Ribbon?(a=a.geometry,k.deleteBuffer(a.__webglVertexBuffer),k.deleteBuffer(a.__webglColorBuffer),k.deleteBuffer(a.__webglNormalBuffer),b(a),L.info.memory.geometries--):a instanceof THREE.Line?(a=a.geometry,k.deleteBuffer(a.__webglVertexBuffer),k.deleteBuffer(a.__webglColorBuffer),k.deleteBuffer(a.__webglLineDistanceBuffer),b(a),L.info.memory.geometries--):a instanceof
+THREE.ParticleSystem&&(a=a.geometry,k.deleteBuffer(a.__webglVertexBuffer),k.deleteBuffer(a.__webglColorBuffer),b(a),L.info.memory.geometries--)};this.deallocateTexture=function(a){a.__webglInit&&(a.__webglInit=!1,k.deleteTexture(a.__webglTexture),L.info.memory.textures--)};this.deallocateRenderTarget=function(a){if(a&&a.__webglTexture)if(k.deleteTexture(a.__webglTexture),a instanceof THREE.WebGLRenderTargetCube)for(var b=0;6>b;b++)k.deleteFramebuffer(a.__webglFramebuffer[b]),k.deleteRenderbuffer(a.__webglRenderbuffer[b]);
+else k.deleteFramebuffer(a.__webglFramebuffer),k.deleteRenderbuffer(a.__webglRenderbuffer)};this.deallocateMaterial=function(a){var b=a.program;if(b){a.program=void 0;var c,d,e=!1,a=0;for(c=oa.length;a<c;a++)if(d=oa[a],d.program===b){d.usedTimes--;0===d.usedTimes&&(e=!0);break}if(e){e=[];a=0;for(c=oa.length;a<c;a++)d=oa[a],d.program!==b&&e.push(d);oa=e;k.deleteProgram(b);L.info.memory.programs--}}};this.updateShadowMap=function(a,b){fa=null;Y=ba=ob=ib=ma=-1;mb=!0;Ja=Na=-1;this.shadowMapPlugin.update(a,
+b)};this.renderBufferImmediate=function(a,b,c){a.hasPositions&&!a.__webglVertexBuffer&&(a.__webglVertexBuffer=k.createBuffer());a.hasNormals&&!a.__webglNormalBuffer&&(a.__webglNormalBuffer=k.createBuffer());a.hasUvs&&!a.__webglUvBuffer&&(a.__webglUvBuffer=k.createBuffer());a.hasColors&&!a.__webglColorBuffer&&(a.__webglColorBuffer=k.createBuffer());a.hasPositions&&(k.bindBuffer(k.ARRAY_BUFFER,a.__webglVertexBuffer),k.bufferData(k.ARRAY_BUFFER,a.positionArray,k.DYNAMIC_DRAW),k.enableVertexAttribArray(b.attributes.position),
+k.vertexAttribPointer(b.attributes.position,3,k.FLOAT,!1,0,0));if(a.hasNormals){k.bindBuffer(k.ARRAY_BUFFER,a.__webglNormalBuffer);if(c.shading===THREE.FlatShading){var d,e,f,g,h,i,j,l,n,m,o,p=3*a.count;for(o=0;o<p;o+=9)m=a.normalArray,d=m[o],e=m[o+1],f=m[o+2],g=m[o+3],i=m[o+4],l=m[o+5],h=m[o+6],j=m[o+7],n=m[o+8],d=(d+g+h)/3,e=(e+i+j)/3,f=(f+l+n)/3,m[o]=d,m[o+1]=e,m[o+2]=f,m[o+3]=d,m[o+4]=e,m[o+5]=f,m[o+6]=d,m[o+7]=e,m[o+8]=f}k.bufferData(k.ARRAY_BUFFER,a.normalArray,k.DYNAMIC_DRAW);k.enableVertexAttribArray(b.attributes.normal);
+k.vertexAttribPointer(b.attributes.normal,3,k.FLOAT,!1,0,0)}a.hasUvs&&c.map&&(k.bindBuffer(k.ARRAY_BUFFER,a.__webglUvBuffer),k.bufferData(k.ARRAY_BUFFER,a.uvArray,k.DYNAMIC_DRAW),k.enableVertexAttribArray(b.attributes.uv),k.vertexAttribPointer(b.attributes.uv,2,k.FLOAT,!1,0,0));a.hasColors&&c.vertexColors!==THREE.NoColors&&(k.bindBuffer(k.ARRAY_BUFFER,a.__webglColorBuffer),k.bufferData(k.ARRAY_BUFFER,a.colorArray,k.DYNAMIC_DRAW),k.enableVertexAttribArray(b.attributes.color),k.vertexAttribPointer(b.attributes.color,
+3,k.FLOAT,!1,0,0));k.drawArrays(k.TRIANGLES,0,a.count);a.count=0};this.renderBufferDirect=function(a,b,c,d,e,f){if(!1!==d.visible)if(c=q(a,b,c,d,f),a=c.attributes,b=!1,d=16777215*e.id+2*c.id+(d.wireframe?1:0),d!==ba&&(ba=d,b=!0),f instanceof THREE.Mesh){f=e.offsets;1<f.length&&(b=!0);d=0;for(c=f.length;d<c;++d){var g=f[d].index;if(b){var h=e.attributes.position,i=h.itemSize;k.bindBuffer(k.ARRAY_BUFFER,h.buffer);k.vertexAttribPointer(a.position,i,k.FLOAT,!1,0,4*g*i);h=e.attributes.normal;0<=a.normal&&
+h&&(i=h.itemSize,k.bindBuffer(k.ARRAY_BUFFER,h.buffer),k.vertexAttribPointer(a.normal,i,k.FLOAT,!1,0,4*g*i));h=e.attributes.uv;0<=a.uv&&h&&(h.buffer?(i=h.itemSize,k.bindBuffer(k.ARRAY_BUFFER,h.buffer),k.vertexAttribPointer(a.uv,i,k.FLOAT,!1,0,4*g*i),k.enableVertexAttribArray(a.uv)):k.disableVertexAttribArray(a.uv));i=e.attributes.color;if(0<=a.color&&i){var j=i.itemSize;k.bindBuffer(k.ARRAY_BUFFER,i.buffer);k.vertexAttribPointer(a.color,j,k.FLOAT,!1,0,4*g*j)}h=e.attributes.tangent;0<=a.tangent&&h&&
+(i=h.itemSize,k.bindBuffer(k.ARRAY_BUFFER,h.buffer),k.vertexAttribPointer(a.tangent,i,k.FLOAT,!1,0,4*g*i));k.bindBuffer(k.ELEMENT_ARRAY_BUFFER,e.attributes.index.buffer)}k.drawElements(k.TRIANGLES,f[d].count,k.UNSIGNED_SHORT,2*f[d].start);L.info.render.calls++;L.info.render.vertices+=f[d].count;L.info.render.faces+=f[d].count/3}}else f instanceof THREE.ParticleSystem&&b&&(h=e.attributes.position,i=h.itemSize,k.bindBuffer(k.ARRAY_BUFFER,h.buffer),k.vertexAttribPointer(a.position,i,k.FLOAT,!1,0,0),
+i=e.attributes.color,0<=a.color&&i&&(j=i.itemSize,k.bindBuffer(k.ARRAY_BUFFER,i.buffer),k.vertexAttribPointer(a.color,j,k.FLOAT,!1,0,0)),k.drawArrays(k.POINTS,0,h.numItems/3),L.info.render.calls++,L.info.render.points+=h.numItems/3)};this.renderBuffer=function(a,b,c,d,e,f){if(!1!==d.visible){var g,h,c=q(a,b,c,d,f),b=c.attributes,a=!1,c=16777215*e.id+2*c.id+(d.wireframe?1:0);c!==ba&&(ba=c,a=!0);if(!d.morphTargets&&0<=b.position)a&&(k.bindBuffer(k.ARRAY_BUFFER,e.__webglVertexBuffer),k.vertexAttribPointer(b.position,
+3,k.FLOAT,!1,0,0));else if(f.morphTargetBase){c=d.program.attributes;-1!==f.morphTargetBase?(k.bindBuffer(k.ARRAY_BUFFER,e.__webglMorphTargetsBuffers[f.morphTargetBase]),k.vertexAttribPointer(c.position,3,k.FLOAT,!1,0,0)):0<=c.position&&(k.bindBuffer(k.ARRAY_BUFFER,e.__webglVertexBuffer),k.vertexAttribPointer(c.position,3,k.FLOAT,!1,0,0));if(f.morphTargetForcedOrder.length){var i=0;h=f.morphTargetForcedOrder;for(g=f.morphTargetInfluences;i<d.numSupportedMorphTargets&&i<h.length;)k.bindBuffer(k.ARRAY_BUFFER,
+e.__webglMorphTargetsBuffers[h[i]]),k.vertexAttribPointer(c["morphTarget"+i],3,k.FLOAT,!1,0,0),d.morphNormals&&(k.bindBuffer(k.ARRAY_BUFFER,e.__webglMorphNormalsBuffers[h[i]]),k.vertexAttribPointer(c["morphNormal"+i],3,k.FLOAT,!1,0,0)),f.__webglMorphTargetInfluences[i]=g[h[i]],i++}else{h=[];g=f.morphTargetInfluences;var j,l=g.length;for(j=0;j<l;j++)i=g[j],0<i&&h.push([j,i]);h.length>d.numSupportedMorphTargets?(h.sort(m),h.length=d.numSupportedMorphTargets):h.length>d.numSupportedMorphNormals?h.sort(m):
+0===h.length&&h.push([0,0]);for(i=0;i<d.numSupportedMorphTargets;)h[i]?(j=h[i][0],k.bindBuffer(k.ARRAY_BUFFER,e.__webglMorphTargetsBuffers[j]),k.vertexAttribPointer(c["morphTarget"+i],3,k.FLOAT,!1,0,0),d.morphNormals&&(k.bindBuffer(k.ARRAY_BUFFER,e.__webglMorphNormalsBuffers[j]),k.vertexAttribPointer(c["morphNormal"+i],3,k.FLOAT,!1,0,0)),f.__webglMorphTargetInfluences[i]=g[j]):(k.vertexAttribPointer(c["morphTarget"+i],3,k.FLOAT,!1,0,0),d.morphNormals&&k.vertexAttribPointer(c["morphNormal"+i],3,k.FLOAT,
+!1,0,0),f.__webglMorphTargetInfluences[i]=0),i++}null!==d.program.uniforms.morphTargetInfluences&&k.uniform1fv(d.program.uniforms.morphTargetInfluences,f.__webglMorphTargetInfluences)}if(a){if(e.__webglCustomAttributesList){g=0;for(h=e.__webglCustomAttributesList.length;g<h;g++)c=e.__webglCustomAttributesList[g],0<=b[c.buffer.belongsToAttribute]&&(k.bindBuffer(k.ARRAY_BUFFER,c.buffer),k.vertexAttribPointer(b[c.buffer.belongsToAttribute],c.size,k.FLOAT,!1,0,0))}0<=b.color&&(k.bindBuffer(k.ARRAY_BUFFER,
+e.__webglColorBuffer),k.vertexAttribPointer(b.color,3,k.FLOAT,!1,0,0));0<=b.normal&&(k.bindBuffer(k.ARRAY_BUFFER,e.__webglNormalBuffer),k.vertexAttribPointer(b.normal,3,k.FLOAT,!1,0,0));0<=b.tangent&&(k.bindBuffer(k.ARRAY_BUFFER,e.__webglTangentBuffer),k.vertexAttribPointer(b.tangent,4,k.FLOAT,!1,0,0));0<=b.uv&&(e.__webglUVBuffer?(k.bindBuffer(k.ARRAY_BUFFER,e.__webglUVBuffer),k.vertexAttribPointer(b.uv,2,k.FLOAT,!1,0,0),k.enableVertexAttribArray(b.uv)):k.disableVertexAttribArray(b.uv));0<=b.uv2&&
+(e.__webglUV2Buffer?(k.bindBuffer(k.ARRAY_BUFFER,e.__webglUV2Buffer),k.vertexAttribPointer(b.uv2,2,k.FLOAT,!1,0,0),k.enableVertexAttribArray(b.uv2)):k.disableVertexAttribArray(b.uv2));d.skinning&&(0<=b.skinIndex&&0<=b.skinWeight)&&(k.bindBuffer(k.ARRAY_BUFFER,e.__webglSkinIndicesBuffer),k.vertexAttribPointer(b.skinIndex,4,k.FLOAT,!1,0,0),k.bindBuffer(k.ARRAY_BUFFER,e.__webglSkinWeightsBuffer),k.vertexAttribPointer(b.skinWeight,4,k.FLOAT,!1,0,0));0<=b.lineDistance&&(k.bindBuffer(k.ARRAY_BUFFER,e.__webglLineDistanceBuffer),
+k.vertexAttribPointer(b.lineDistance,1,k.FLOAT,!1,0,0))}f instanceof THREE.Mesh?(d.wireframe?(d=d.wireframeLinewidth,d!==Wa&&(k.lineWidth(d),Wa=d),a&&k.bindBuffer(k.ELEMENT_ARRAY_BUFFER,e.__webglLineBuffer),k.drawElements(k.LINES,e.__webglLineCount,k.UNSIGNED_SHORT,0)):(a&&k.bindBuffer(k.ELEMENT_ARRAY_BUFFER,e.__webglFaceBuffer),k.drawElements(k.TRIANGLES,e.__webglFaceCount,k.UNSIGNED_SHORT,0)),L.info.render.calls++,L.info.render.vertices+=e.__webglFaceCount,L.info.render.faces+=e.__webglFaceCount/
+3):f instanceof THREE.Line?(f=f.type===THREE.LineStrip?k.LINE_STRIP:k.LINES,d=d.linewidth,d!==Wa&&(k.lineWidth(d),Wa=d),k.drawArrays(f,0,e.__webglLineCount),L.info.render.calls++):f instanceof THREE.ParticleSystem?(k.drawArrays(k.POINTS,0,e.__webglParticleCount),L.info.render.calls++,L.info.render.points+=e.__webglParticleCount):f instanceof THREE.Ribbon&&(k.drawArrays(k.TRIANGLE_STRIP,0,e.__webglVertexCount),L.info.render.calls++)}};this.render=function(a,b,c,d){if(!1===b instanceof THREE.Camera)console.error("THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.");
+else{var e,f,g,h,i=a.__lights,j=a.fog;Y=-1;mb=!0;this.autoUpdateScene&&a.updateMatrixWorld();void 0===b.parent&&b.updateMatrixWorld();b._viewMatrixArray||(b._viewMatrixArray=new Float32Array(16));b._projectionMatrixArray||(b._projectionMatrixArray=new Float32Array(16));b.matrixWorldInverse.getInverse(b.matrixWorld);b.matrixWorldInverse.flattenToArray(b._viewMatrixArray);b.projectionMatrix.flattenToArray(b._projectionMatrixArray);eb.multiply(b.projectionMatrix,b.matrixWorldInverse);va.setFromMatrix(eb);
+this.autoUpdateObjects&&this.initWebGLObjects(a);n(this.renderPluginsPre,a,b);L.info.render.calls=0;L.info.render.vertices=0;L.info.render.faces=0;L.info.render.points=0;this.setRenderTarget(c);(this.autoClear||d)&&this.clear(this.autoClearColor,this.autoClearDepth,this.autoClearStencil);h=a.__webglObjects;d=0;for(e=h.length;d<e;d++)if(f=h[d],g=f.object,f.render=!1,g.visible&&(!(g instanceof THREE.Mesh||g instanceof THREE.ParticleSystem)||!g.frustumCulled||va.contains(g))){A(g,b);var m=f,s=m.buffer,
+r=void 0,q=r=void 0,q=m.object.material;if(q instanceof THREE.MeshFaceMaterial)r=s.materialIndex,0<=r&&(r=q.materials[r],r.transparent?(m.transparent=r,m.opaque=null):(m.opaque=r,m.transparent=null));else if(r=q)r.transparent?(m.transparent=r,m.opaque=null):(m.opaque=r,m.transparent=null);f.render=!0;!0===this.sortObjects&&(null!==g.renderDepth?f.z=g.renderDepth:(bb.copy(g.matrixWorld.getPosition()),eb.multiplyVector3(bb),f.z=bb.z),f.id=g.id)}this.sortObjects&&h.sort(l);h=a.__webglObjectsImmediate;
+d=0;for(e=h.length;d<e;d++)f=h[d],g=f.object,g.visible&&(A(g,b),g=f.object.material,g.transparent?(f.transparent=g,f.opaque=null):(f.opaque=g,f.transparent=null));a.overrideMaterial?(d=a.overrideMaterial,this.setBlending(d.blending,d.blendEquation,d.blendSrc,d.blendDst),this.setDepthTest(d.depthTest),this.setDepthWrite(d.depthWrite),D(d.polygonOffset,d.polygonOffsetFactor,d.polygonOffsetUnits),p(a.__webglObjects,!1,"",b,i,j,!0,d),o(a.__webglObjectsImmediate,"",b,i,j,!1,d)):(this.setBlending(THREE.NormalBlending),
+p(a.__webglObjects,!0,"opaque",b,i,j,!1),o(a.__webglObjectsImmediate,"opaque",b,i,j,!1),p(a.__webglObjects,!1,"transparent",b,i,j,!0),o(a.__webglObjectsImmediate,"transparent",b,i,j,!0));n(this.renderPluginsPost,a,b);c&&(c.generateMipmaps&&c.minFilter!==THREE.NearestFilter&&c.minFilter!==THREE.LinearFilter)&&(c instanceof THREE.WebGLRenderTargetCube?(k.bindTexture(k.TEXTURE_CUBE_MAP,c.__webglTexture),k.generateMipmap(k.TEXTURE_CUBE_MAP),k.bindTexture(k.TEXTURE_CUBE_MAP,null)):(k.bindTexture(k.TEXTURE_2D,
+c.__webglTexture),k.generateMipmap(k.TEXTURE_2D),k.bindTexture(k.TEXTURE_2D,null)));this.setDepthTest(!0);this.setDepthWrite(!0)}};this.renderImmediateObject=function(a,b,c,d,e){var f=q(a,b,c,d,e);ba=-1;L.setMaterialFaces(d);e.immediateRenderCallback?e.immediateRenderCallback(f,k,va):e.render(function(a){L.renderBufferImmediate(a,f,d)})};this.initWebGLObjects=function(a){a.__webglObjects||(a.__webglObjects=[],a.__webglObjectsImmediate=[],a.__webglSprites=[],a.__webglFlares=[]);for(;a.__objectsAdded.length;){var b=
+a.__objectsAdded[0],l=a,n=void 0,m=void 0,o=void 0,p=void 0;if(!b.__webglInit)if(b.__webglInit=!0,b._modelViewMatrix=new THREE.Matrix4,b._normalMatrix=new THREE.Matrix3,b instanceof THREE.Mesh)if(m=b.geometry,o=b.material,m instanceof THREE.Geometry){if(void 0===m.geometryGroups){var q=m,u=void 0,v=void 0,A=void 0,B=void 0,C=void 0,D=void 0,E=void 0,G={},H=q.morphTargets.length,I=q.morphNormals.length,X=o instanceof THREE.MeshFaceMaterial;q.geometryGroups={};u=0;for(v=q.faces.length;u<v;u++)A=q.faces[u],
+B=X?A.materialIndex:void 0,D=void 0!==B?B:-1,void 0===G[D]&&(G[D]={hash:D,counter:0}),E=G[D].hash+"_"+G[D].counter,void 0===q.geometryGroups[E]&&(q.geometryGroups[E]={faces3:[],faces4:[],materialIndex:B,vertices:0,numMorphTargets:H,numMorphNormals:I}),C=A instanceof THREE.Face3?3:4,65535<q.geometryGroups[E].vertices+C&&(G[D].counter+=1,E=G[D].hash+"_"+G[D].counter,void 0===q.geometryGroups[E]&&(q.geometryGroups[E]={faces3:[],faces4:[],materialIndex:B,vertices:0,numMorphTargets:H,numMorphNormals:I})),
+A instanceof THREE.Face3?q.geometryGroups[E].faces3.push(u):q.geometryGroups[E].faces4.push(u),q.geometryGroups[E].vertices+=C;q.geometryGroupsList=[];var Y=void 0;for(Y in q.geometryGroups)q.geometryGroups[Y].id=ia++,q.geometryGroupsList.push(q.geometryGroups[Y])}for(n in m.geometryGroups)if(p=m.geometryGroups[n],!p.__webglVertexBuffer){var J=p;J.__webglVertexBuffer=k.createBuffer();J.__webglNormalBuffer=k.createBuffer();J.__webglTangentBuffer=k.createBuffer();J.__webglColorBuffer=k.createBuffer();
+J.__webglUVBuffer=k.createBuffer();J.__webglUV2Buffer=k.createBuffer();J.__webglSkinIndicesBuffer=k.createBuffer();J.__webglSkinWeightsBuffer=k.createBuffer();J.__webglFaceBuffer=k.createBuffer();J.__webglLineBuffer=k.createBuffer();var K=void 0,Q=void 0;if(J.numMorphTargets){J.__webglMorphTargetsBuffers=[];K=0;for(Q=J.numMorphTargets;K<Q;K++)J.__webglMorphTargetsBuffers.push(k.createBuffer())}if(J.numMorphNormals){J.__webglMorphNormalsBuffers=[];K=0;for(Q=J.numMorphNormals;K<Q;K++)J.__webglMorphNormalsBuffers.push(k.createBuffer())}L.info.memory.geometries++;
+d(p,b);m.verticesNeedUpdate=!0;m.morphTargetsNeedUpdate=!0;m.elementsNeedUpdate=!0;m.uvsNeedUpdate=!0;m.normalsNeedUpdate=!0;m.tangentsNeedUpdate=!0;m.colorsNeedUpdate=!0}}else m instanceof THREE.BufferGeometry&&h(m);else if(b instanceof THREE.Ribbon){if(m=b.geometry,!m.__webglVertexBuffer){var O=m;O.__webglVertexBuffer=k.createBuffer();O.__webglColorBuffer=k.createBuffer();O.__webglNormalBuffer=k.createBuffer();L.info.memory.geometries++;var M=m,P=b,N=M.vertices.length;M.__vertexArray=new Float32Array(3*
+N);M.__colorArray=new Float32Array(3*N);M.__normalArray=new Float32Array(3*N);M.__webglVertexCount=N;c(M,P);m.verticesNeedUpdate=!0;m.colorsNeedUpdate=!0;m.normalsNeedUpdate=!0}}else if(b instanceof THREE.Line){if(m=b.geometry,!m.__webglVertexBuffer){var ca=m;ca.__webglVertexBuffer=k.createBuffer();ca.__webglColorBuffer=k.createBuffer();ca.__webglLineDistanceBuffer=k.createBuffer();L.info.memory.geometries++;var fa=m,R=b,Z=fa.vertices.length;fa.__vertexArray=new Float32Array(3*Z);fa.__colorArray=
+new Float32Array(3*Z);fa.__lineDistanceArray=new Float32Array(1*Z);fa.__webglLineCount=Z;c(fa,R);m.verticesNeedUpdate=!0;m.colorsNeedUpdate=!0;m.lineDistancesNeedUpdate=!0}}else if(b instanceof THREE.ParticleSystem&&(m=b.geometry,!m.__webglVertexBuffer))if(m instanceof THREE.Geometry){var aa=m;aa.__webglVertexBuffer=k.createBuffer();aa.__webglColorBuffer=k.createBuffer();L.info.memory.geometries++;var ba=m,ga=b,Aa=ba.vertices.length;ba.__vertexArray=new Float32Array(3*Aa);ba.__colorArray=new Float32Array(3*
+Aa);ba.__sortArray=[];ba.__webglParticleCount=Aa;c(ba,ga);m.verticesNeedUpdate=!0;m.colorsNeedUpdate=!0}else m instanceof THREE.BufferGeometry&&h(m);if(!b.__webglActive){if(b instanceof THREE.Mesh)if(m=b.geometry,m instanceof THREE.BufferGeometry)s(l.__webglObjects,m,b);else for(n in m.geometryGroups)p=m.geometryGroups[n],s(l.__webglObjects,p,b);else b instanceof THREE.Ribbon||b instanceof THREE.Line||b instanceof THREE.ParticleSystem?(m=b.geometry,s(l.__webglObjects,m,b)):b instanceof THREE.ImmediateRenderObject||
+b.immediateRenderCallback?l.__webglObjectsImmediate.push({object:b,opaque:null,transparent:null}):b instanceof THREE.Sprite?l.__webglSprites.push(b):b instanceof THREE.LensFlare&&l.__webglFlares.push(b);b.__webglActive=!0}a.__objectsAdded.splice(0,1)}for(;a.__objectsRemoved.length;){var oa=a.__objectsRemoved[0],sa=a;oa instanceof THREE.Mesh||oa instanceof THREE.ParticleSystem||oa instanceof THREE.Ribbon||oa instanceof THREE.Line?z(sa.__webglObjects,oa):oa instanceof THREE.Sprite?w(sa.__webglSprites,
+oa):oa instanceof THREE.LensFlare?w(sa.__webglFlares,oa):(oa instanceof THREE.ImmediateRenderObject||oa.immediateRenderCallback)&&z(sa.__webglObjectsImmediate,oa);oa.__webglActive=!1;a.__objectsRemoved.splice(0,1)}for(var Na=0,xa=a.__webglObjects.length;Na<xa;Na++){var qa=a.__webglObjects[Na].object,T=qa.geometry,Ja=void 0,va=void 0,ma=void 0;if(qa instanceof THREE.Mesh)if(T instanceof THREE.BufferGeometry)(T.verticesNeedUpdate||T.elementsNeedUpdate||T.uvsNeedUpdate||T.normalsNeedUpdate||T.colorsNeedUpdate||
+T.tangentsNeedUpdate)&&j(T,k.DYNAMIC_DRAW,!T.dynamic),T.verticesNeedUpdate=!1,T.elementsNeedUpdate=!1,T.uvsNeedUpdate=!1,T.normalsNeedUpdate=!1,T.colorsNeedUpdate=!1,T.tangentsNeedUpdate=!1;else{for(var Ka=0,Oa=T.geometryGroupsList.length;Ka<Oa;Ka++)if(Ja=T.geometryGroupsList[Ka],ma=e(qa,Ja),T.buffersNeedUpdate&&d(Ja,qa),va=ma.attributes&&t(ma),T.verticesNeedUpdate||T.morphTargetsNeedUpdate||T.elementsNeedUpdate||T.uvsNeedUpdate||T.normalsNeedUpdate||T.colorsNeedUpdate||T.tangentsNeedUpdate||va){var ra=
+Ja,Sa=qa,Ea=k.DYNAMIC_DRAW,ib=!T.dynamic,Wa=ma;if(ra.__inittedArrays){var mb=f(Wa),rb=Wa.vertexColors?Wa.vertexColors:!1,ob=g(Wa),lb=mb===THREE.SmoothShading,F=void 0,$=void 0,ab=void 0,S=void 0,eb=void 0,bb=void 0,Eb=void 0,pb=void 0,Vb=void 0,jb=void 0,kb=void 0,U=void 0,V=void 0,W=void 0,pa=void 0,Fb=void 0,Gb=void 0,Hb=void 0,qb=void 0,Ib=void 0,Jb=void 0,Kb=void 0,sb=void 0,Lb=void 0,Mb=void 0,Nb=void 0,zb=void 0,Ob=void 0,Pb=void 0,Qb=void 0,Bb=void 0,Rb=void 0,Sb=void 0,Tb=void 0,Cb=void 0,
+wa=void 0,gc=void 0,ac=void 0,kc=void 0,lc=void 0,Ta=void 0,hc=void 0,Qa=void 0,Ra=void 0,bc=void 0,Wb=void 0,La=0,Pa=0,Xb=0,Yb=0,vb=0,Za=0,Ba=0,db=0,Ma=0,ha=0,ja=0,y=0,ya=void 0,Ua=ra.__vertexArray,pc=ra.__uvArray,qc=ra.__uv2Array,wb=ra.__normalArray,Fa=ra.__tangentArray,Va=ra.__colorArray,Ga=ra.__skinIndexArray,Ha=ra.__skinWeightArray,Sc=ra.__morphTargetsArrays,Tc=ra.__morphNormalsArrays,Uc=ra.__webglCustomAttributesList,x=void 0,Ub=ra.__faceArray,nb=ra.__lineArray,fb=Sa.geometry,xc=fb.elementsNeedUpdate,
+oc=fb.uvsNeedUpdate,Pc=fb.normalsNeedUpdate,Qc=fb.tangentsNeedUpdate,hd=fb.colorsNeedUpdate,id=fb.morphTargetsNeedUpdate,ec=fb.vertices,ta=ra.faces3,ua=ra.faces4,$a=fb.faces,Vc=fb.faceVertexUvs[0],Wc=fb.faceVertexUvs[1],fc=fb.skinIndices,cc=fb.skinWeights,dc=fb.morphTargets,Ac=fb.morphNormals;if(fb.verticesNeedUpdate){F=0;for($=ta.length;F<$;F++)S=$a[ta[F]],U=ec[S.a],V=ec[S.b],W=ec[S.c],Ua[Pa]=U.x,Ua[Pa+1]=U.y,Ua[Pa+2]=U.z,Ua[Pa+3]=V.x,Ua[Pa+4]=V.y,Ua[Pa+5]=V.z,Ua[Pa+6]=W.x,Ua[Pa+7]=W.y,Ua[Pa+8]=
+W.z,Pa+=9;F=0;for($=ua.length;F<$;F++)S=$a[ua[F]],U=ec[S.a],V=ec[S.b],W=ec[S.c],pa=ec[S.d],Ua[Pa]=U.x,Ua[Pa+1]=U.y,Ua[Pa+2]=U.z,Ua[Pa+3]=V.x,Ua[Pa+4]=V.y,Ua[Pa+5]=V.z,Ua[Pa+6]=W.x,Ua[Pa+7]=W.y,Ua[Pa+8]=W.z,Ua[Pa+9]=pa.x,Ua[Pa+10]=pa.y,Ua[Pa+11]=pa.z,Pa+=12;k.bindBuffer(k.ARRAY_BUFFER,ra.__webglVertexBuffer);k.bufferData(k.ARRAY_BUFFER,Ua,Ea)}if(id){Ta=0;for(hc=dc.length;Ta<hc;Ta++){F=ja=0;for($=ta.length;F<$;F++)bc=ta[F],S=$a[bc],U=dc[Ta].vertices[S.a],V=dc[Ta].vertices[S.b],W=dc[Ta].vertices[S.c],
+Qa=Sc[Ta],Qa[ja]=U.x,Qa[ja+1]=U.y,Qa[ja+2]=U.z,Qa[ja+3]=V.x,Qa[ja+4]=V.y,Qa[ja+5]=V.z,Qa[ja+6]=W.x,Qa[ja+7]=W.y,Qa[ja+8]=W.z,Wa.morphNormals&&(lb?(Wb=Ac[Ta].vertexNormals[bc],Ib=Wb.a,Jb=Wb.b,Kb=Wb.c):Kb=Jb=Ib=Ac[Ta].faceNormals[bc],Ra=Tc[Ta],Ra[ja]=Ib.x,Ra[ja+1]=Ib.y,Ra[ja+2]=Ib.z,Ra[ja+3]=Jb.x,Ra[ja+4]=Jb.y,Ra[ja+5]=Jb.z,Ra[ja+6]=Kb.x,Ra[ja+7]=Kb.y,Ra[ja+8]=Kb.z),ja+=9;F=0;for($=ua.length;F<$;F++)bc=ua[F],S=$a[bc],U=dc[Ta].vertices[S.a],V=dc[Ta].vertices[S.b],W=dc[Ta].vertices[S.c],pa=dc[Ta].vertices[S.d],
+Qa=Sc[Ta],Qa[ja]=U.x,Qa[ja+1]=U.y,Qa[ja+2]=U.z,Qa[ja+3]=V.x,Qa[ja+4]=V.y,Qa[ja+5]=V.z,Qa[ja+6]=W.x,Qa[ja+7]=W.y,Qa[ja+8]=W.z,Qa[ja+9]=pa.x,Qa[ja+10]=pa.y,Qa[ja+11]=pa.z,Wa.morphNormals&&(lb?(Wb=Ac[Ta].vertexNormals[bc],Ib=Wb.a,Jb=Wb.b,Kb=Wb.c,sb=Wb.d):sb=Kb=Jb=Ib=Ac[Ta].faceNormals[bc],Ra=Tc[Ta],Ra[ja]=Ib.x,Ra[ja+1]=Ib.y,Ra[ja+2]=Ib.z,Ra[ja+3]=Jb.x,Ra[ja+4]=Jb.y,Ra[ja+5]=Jb.z,Ra[ja+6]=Kb.x,Ra[ja+7]=Kb.y,Ra[ja+8]=Kb.z,Ra[ja+9]=sb.x,Ra[ja+10]=sb.y,Ra[ja+11]=sb.z),ja+=12;k.bindBuffer(k.ARRAY_BUFFER,
+ra.__webglMorphTargetsBuffers[Ta]);k.bufferData(k.ARRAY_BUFFER,Sc[Ta],Ea);Wa.morphNormals&&(k.bindBuffer(k.ARRAY_BUFFER,ra.__webglMorphNormalsBuffers[Ta]),k.bufferData(k.ARRAY_BUFFER,Tc[Ta],Ea))}}if(cc.length){F=0;for($=ta.length;F<$;F++)S=$a[ta[F]],Ob=cc[S.a],Pb=cc[S.b],Qb=cc[S.c],Ha[ha]=Ob.x,Ha[ha+1]=Ob.y,Ha[ha+2]=Ob.z,Ha[ha+3]=Ob.w,Ha[ha+4]=Pb.x,Ha[ha+5]=Pb.y,Ha[ha+6]=Pb.z,Ha[ha+7]=Pb.w,Ha[ha+8]=Qb.x,Ha[ha+9]=Qb.y,Ha[ha+10]=Qb.z,Ha[ha+11]=Qb.w,Rb=fc[S.a],Sb=fc[S.b],Tb=fc[S.c],Ga[ha]=Rb.x,Ga[ha+
+1]=Rb.y,Ga[ha+2]=Rb.z,Ga[ha+3]=Rb.w,Ga[ha+4]=Sb.x,Ga[ha+5]=Sb.y,Ga[ha+6]=Sb.z,Ga[ha+7]=Sb.w,Ga[ha+8]=Tb.x,Ga[ha+9]=Tb.y,Ga[ha+10]=Tb.z,Ga[ha+11]=Tb.w,ha+=12;F=0;for($=ua.length;F<$;F++)S=$a[ua[F]],Ob=cc[S.a],Pb=cc[S.b],Qb=cc[S.c],Bb=cc[S.d],Ha[ha]=Ob.x,Ha[ha+1]=Ob.y,Ha[ha+2]=Ob.z,Ha[ha+3]=Ob.w,Ha[ha+4]=Pb.x,Ha[ha+5]=Pb.y,Ha[ha+6]=Pb.z,Ha[ha+7]=Pb.w,Ha[ha+8]=Qb.x,Ha[ha+9]=Qb.y,Ha[ha+10]=Qb.z,Ha[ha+11]=Qb.w,Ha[ha+12]=Bb.x,Ha[ha+13]=Bb.y,Ha[ha+14]=Bb.z,Ha[ha+15]=Bb.w,Rb=fc[S.a],Sb=fc[S.b],Tb=fc[S.c],
+Cb=fc[S.d],Ga[ha]=Rb.x,Ga[ha+1]=Rb.y,Ga[ha+2]=Rb.z,Ga[ha+3]=Rb.w,Ga[ha+4]=Sb.x,Ga[ha+5]=Sb.y,Ga[ha+6]=Sb.z,Ga[ha+7]=Sb.w,Ga[ha+8]=Tb.x,Ga[ha+9]=Tb.y,Ga[ha+10]=Tb.z,Ga[ha+11]=Tb.w,Ga[ha+12]=Cb.x,Ga[ha+13]=Cb.y,Ga[ha+14]=Cb.z,Ga[ha+15]=Cb.w,ha+=16;0<ha&&(k.bindBuffer(k.ARRAY_BUFFER,ra.__webglSkinIndicesBuffer),k.bufferData(k.ARRAY_BUFFER,Ga,Ea),k.bindBuffer(k.ARRAY_BUFFER,ra.__webglSkinWeightsBuffer),k.bufferData(k.ARRAY_BUFFER,Ha,Ea))}if(hd&&rb){F=0;for($=ta.length;F<$;F++)S=$a[ta[F]],Eb=S.vertexColors,
+pb=S.color,3===Eb.length&&rb===THREE.VertexColors?(Lb=Eb[0],Mb=Eb[1],Nb=Eb[2]):Nb=Mb=Lb=pb,Va[Ma]=Lb.r,Va[Ma+1]=Lb.g,Va[Ma+2]=Lb.b,Va[Ma+3]=Mb.r,Va[Ma+4]=Mb.g,Va[Ma+5]=Mb.b,Va[Ma+6]=Nb.r,Va[Ma+7]=Nb.g,Va[Ma+8]=Nb.b,Ma+=9;F=0;for($=ua.length;F<$;F++)S=$a[ua[F]],Eb=S.vertexColors,pb=S.color,4===Eb.length&&rb===THREE.VertexColors?(Lb=Eb[0],Mb=Eb[1],Nb=Eb[2],zb=Eb[3]):zb=Nb=Mb=Lb=pb,Va[Ma]=Lb.r,Va[Ma+1]=Lb.g,Va[Ma+2]=Lb.b,Va[Ma+3]=Mb.r,Va[Ma+4]=Mb.g,Va[Ma+5]=Mb.b,Va[Ma+6]=Nb.r,Va[Ma+7]=Nb.g,Va[Ma+8]=
+Nb.b,Va[Ma+9]=zb.r,Va[Ma+10]=zb.g,Va[Ma+11]=zb.b,Ma+=12;0<Ma&&(k.bindBuffer(k.ARRAY_BUFFER,ra.__webglColorBuffer),k.bufferData(k.ARRAY_BUFFER,Va,Ea))}if(Qc&&fb.hasTangents){F=0;for($=ta.length;F<$;F++)S=$a[ta[F]],Vb=S.vertexTangents,Fb=Vb[0],Gb=Vb[1],Hb=Vb[2],Fa[Ba]=Fb.x,Fa[Ba+1]=Fb.y,Fa[Ba+2]=Fb.z,Fa[Ba+3]=Fb.w,Fa[Ba+4]=Gb.x,Fa[Ba+5]=Gb.y,Fa[Ba+6]=Gb.z,Fa[Ba+7]=Gb.w,Fa[Ba+8]=Hb.x,Fa[Ba+9]=Hb.y,Fa[Ba+10]=Hb.z,Fa[Ba+11]=Hb.w,Ba+=12;F=0;for($=ua.length;F<$;F++)S=$a[ua[F]],Vb=S.vertexTangents,Fb=Vb[0],
+Gb=Vb[1],Hb=Vb[2],qb=Vb[3],Fa[Ba]=Fb.x,Fa[Ba+1]=Fb.y,Fa[Ba+2]=Fb.z,Fa[Ba+3]=Fb.w,Fa[Ba+4]=Gb.x,Fa[Ba+5]=Gb.y,Fa[Ba+6]=Gb.z,Fa[Ba+7]=Gb.w,Fa[Ba+8]=Hb.x,Fa[Ba+9]=Hb.y,Fa[Ba+10]=Hb.z,Fa[Ba+11]=Hb.w,Fa[Ba+12]=qb.x,Fa[Ba+13]=qb.y,Fa[Ba+14]=qb.z,Fa[Ba+15]=qb.w,Ba+=16;k.bindBuffer(k.ARRAY_BUFFER,ra.__webglTangentBuffer);k.bufferData(k.ARRAY_BUFFER,Fa,Ea)}if(Pc&&mb){F=0;for($=ta.length;F<$;F++)if(S=$a[ta[F]],eb=S.vertexNormals,bb=S.normal,3===eb.length&&lb)for(wa=0;3>wa;wa++)ac=eb[wa],wb[Za]=ac.x,wb[Za+1]=
+ac.y,wb[Za+2]=ac.z,Za+=3;else for(wa=0;3>wa;wa++)wb[Za]=bb.x,wb[Za+1]=bb.y,wb[Za+2]=bb.z,Za+=3;F=0;for($=ua.length;F<$;F++)if(S=$a[ua[F]],eb=S.vertexNormals,bb=S.normal,4===eb.length&&lb)for(wa=0;4>wa;wa++)ac=eb[wa],wb[Za]=ac.x,wb[Za+1]=ac.y,wb[Za+2]=ac.z,Za+=3;else for(wa=0;4>wa;wa++)wb[Za]=bb.x,wb[Za+1]=bb.y,wb[Za+2]=bb.z,Za+=3;k.bindBuffer(k.ARRAY_BUFFER,ra.__webglNormalBuffer);k.bufferData(k.ARRAY_BUFFER,wb,Ea)}if(oc&&Vc&&ob){F=0;for($=ta.length;F<$;F++)if(ab=ta[F],jb=Vc[ab],void 0!==jb)for(wa=
+0;3>wa;wa++)kc=jb[wa],pc[Xb]=kc.u,pc[Xb+1]=kc.v,Xb+=2;F=0;for($=ua.length;F<$;F++)if(ab=ua[F],jb=Vc[ab],void 0!==jb)for(wa=0;4>wa;wa++)kc=jb[wa],pc[Xb]=kc.u,pc[Xb+1]=kc.v,Xb+=2;0<Xb&&(k.bindBuffer(k.ARRAY_BUFFER,ra.__webglUVBuffer),k.bufferData(k.ARRAY_BUFFER,pc,Ea))}if(oc&&Wc&&ob){F=0;for($=ta.length;F<$;F++)if(ab=ta[F],kb=Wc[ab],void 0!==kb)for(wa=0;3>wa;wa++)lc=kb[wa],qc[Yb]=lc.u,qc[Yb+1]=lc.v,Yb+=2;F=0;for($=ua.length;F<$;F++)if(ab=ua[F],kb=Wc[ab],void 0!==kb)for(wa=0;4>wa;wa++)lc=kb[wa],qc[Yb]=
+lc.u,qc[Yb+1]=lc.v,Yb+=2;0<Yb&&(k.bindBuffer(k.ARRAY_BUFFER,ra.__webglUV2Buffer),k.bufferData(k.ARRAY_BUFFER,qc,Ea))}if(xc){F=0;for($=ta.length;F<$;F++)Ub[vb]=La,Ub[vb+1]=La+1,Ub[vb+2]=La+2,vb+=3,nb[db]=La,nb[db+1]=La+1,nb[db+2]=La,nb[db+3]=La+2,nb[db+4]=La+1,nb[db+5]=La+2,db+=6,La+=3;F=0;for($=ua.length;F<$;F++)Ub[vb]=La,Ub[vb+1]=La+1,Ub[vb+2]=La+3,Ub[vb+3]=La+1,Ub[vb+4]=La+2,Ub[vb+5]=La+3,vb+=6,nb[db]=La,nb[db+1]=La+1,nb[db+2]=La,nb[db+3]=La+3,nb[db+4]=La+1,nb[db+5]=La+2,nb[db+6]=La+2,nb[db+7]=
+La+3,db+=8,La+=4;k.bindBuffer(k.ELEMENT_ARRAY_BUFFER,ra.__webglFaceBuffer);k.bufferData(k.ELEMENT_ARRAY_BUFFER,Ub,Ea);k.bindBuffer(k.ELEMENT_ARRAY_BUFFER,ra.__webglLineBuffer);k.bufferData(k.ELEMENT_ARRAY_BUFFER,nb,Ea)}if(Uc){wa=0;for(gc=Uc.length;wa<gc;wa++)if(x=Uc[wa],x.__original.needsUpdate){y=0;if(1===x.size)if(void 0===x.boundTo||"vertices"===x.boundTo){F=0;for($=ta.length;F<$;F++)S=$a[ta[F]],x.array[y]=x.value[S.a],x.array[y+1]=x.value[S.b],x.array[y+2]=x.value[S.c],y+=3;F=0;for($=ua.length;F<
+$;F++)S=$a[ua[F]],x.array[y]=x.value[S.a],x.array[y+1]=x.value[S.b],x.array[y+2]=x.value[S.c],x.array[y+3]=x.value[S.d],y+=4}else{if("faces"===x.boundTo){F=0;for($=ta.length;F<$;F++)ya=x.value[ta[F]],x.array[y]=ya,x.array[y+1]=ya,x.array[y+2]=ya,y+=3;F=0;for($=ua.length;F<$;F++)ya=x.value[ua[F]],x.array[y]=ya,x.array[y+1]=ya,x.array[y+2]=ya,x.array[y+3]=ya,y+=4}}else if(2===x.size)if(void 0===x.boundTo||"vertices"===x.boundTo){F=0;for($=ta.length;F<$;F++)S=$a[ta[F]],U=x.value[S.a],V=x.value[S.b],
+W=x.value[S.c],x.array[y]=U.x,x.array[y+1]=U.y,x.array[y+2]=V.x,x.array[y+3]=V.y,x.array[y+4]=W.x,x.array[y+5]=W.y,y+=6;F=0;for($=ua.length;F<$;F++)S=$a[ua[F]],U=x.value[S.a],V=x.value[S.b],W=x.value[S.c],pa=x.value[S.d],x.array[y]=U.x,x.array[y+1]=U.y,x.array[y+2]=V.x,x.array[y+3]=V.y,x.array[y+4]=W.x,x.array[y+5]=W.y,x.array[y+6]=pa.x,x.array[y+7]=pa.y,y+=8}else{if("faces"===x.boundTo){F=0;for($=ta.length;F<$;F++)W=V=U=ya=x.value[ta[F]],x.array[y]=U.x,x.array[y+1]=U.y,x.array[y+2]=V.x,x.array[y+
+3]=V.y,x.array[y+4]=W.x,x.array[y+5]=W.y,y+=6;F=0;for($=ua.length;F<$;F++)pa=W=V=U=ya=x.value[ua[F]],x.array[y]=U.x,x.array[y+1]=U.y,x.array[y+2]=V.x,x.array[y+3]=V.y,x.array[y+4]=W.x,x.array[y+5]=W.y,x.array[y+6]=pa.x,x.array[y+7]=pa.y,y+=8}}else if(3===x.size){var ea;ea="c"===x.type?["r","g","b"]:["x","y","z"];if(void 0===x.boundTo||"vertices"===x.boundTo){F=0;for($=ta.length;F<$;F++)S=$a[ta[F]],U=x.value[S.a],V=x.value[S.b],W=x.value[S.c],x.array[y]=U[ea[0]],x.array[y+1]=U[ea[1]],x.array[y+2]=
+U[ea[2]],x.array[y+3]=V[ea[0]],x.array[y+4]=V[ea[1]],x.array[y+5]=V[ea[2]],x.array[y+6]=W[ea[0]],x.array[y+7]=W[ea[1]],x.array[y+8]=W[ea[2]],y+=9;F=0;for($=ua.length;F<$;F++)S=$a[ua[F]],U=x.value[S.a],V=x.value[S.b],W=x.value[S.c],pa=x.value[S.d],x.array[y]=U[ea[0]],x.array[y+1]=U[ea[1]],x.array[y+2]=U[ea[2]],x.array[y+3]=V[ea[0]],x.array[y+4]=V[ea[1]],x.array[y+5]=V[ea[2]],x.array[y+6]=W[ea[0]],x.array[y+7]=W[ea[1]],x.array[y+8]=W[ea[2]],x.array[y+9]=pa[ea[0]],x.array[y+10]=pa[ea[1]],x.array[y+11]=
+pa[ea[2]],y+=12}else if("faces"===x.boundTo){F=0;for($=ta.length;F<$;F++)W=V=U=ya=x.value[ta[F]],x.array[y]=U[ea[0]],x.array[y+1]=U[ea[1]],x.array[y+2]=U[ea[2]],x.array[y+3]=V[ea[0]],x.array[y+4]=V[ea[1]],x.array[y+5]=V[ea[2]],x.array[y+6]=W[ea[0]],x.array[y+7]=W[ea[1]],x.array[y+8]=W[ea[2]],y+=9;F=0;for($=ua.length;F<$;F++)pa=W=V=U=ya=x.value[ua[F]],x.array[y]=U[ea[0]],x.array[y+1]=U[ea[1]],x.array[y+2]=U[ea[2]],x.array[y+3]=V[ea[0]],x.array[y+4]=V[ea[1]],x.array[y+5]=V[ea[2]],x.array[y+6]=W[ea[0]],
+x.array[y+7]=W[ea[1]],x.array[y+8]=W[ea[2]],x.array[y+9]=pa[ea[0]],x.array[y+10]=pa[ea[1]],x.array[y+11]=pa[ea[2]],y+=12}else if("faceVertices"===x.boundTo){F=0;for($=ta.length;F<$;F++)ya=x.value[ta[F]],U=ya[0],V=ya[1],W=ya[2],x.array[y]=U[ea[0]],x.array[y+1]=U[ea[1]],x.array[y+2]=U[ea[2]],x.array[y+3]=V[ea[0]],x.array[y+4]=V[ea[1]],x.array[y+5]=V[ea[2]],x.array[y+6]=W[ea[0]],x.array[y+7]=W[ea[1]],x.array[y+8]=W[ea[2]],y+=9;F=0;for($=ua.length;F<$;F++)ya=x.value[ua[F]],U=ya[0],V=ya[1],W=ya[2],pa=
+ya[3],x.array[y]=U[ea[0]],x.array[y+1]=U[ea[1]],x.array[y+2]=U[ea[2]],x.array[y+3]=V[ea[0]],x.array[y+4]=V[ea[1]],x.array[y+5]=V[ea[2]],x.array[y+6]=W[ea[0]],x.array[y+7]=W[ea[1]],x.array[y+8]=W[ea[2]],x.array[y+9]=pa[ea[0]],x.array[y+10]=pa[ea[1]],x.array[y+11]=pa[ea[2]],y+=12}}else if(4===x.size)if(void 0===x.boundTo||"vertices"===x.boundTo){F=0;for($=ta.length;F<$;F++)S=$a[ta[F]],U=x.value[S.a],V=x.value[S.b],W=x.value[S.c],x.array[y]=U.x,x.array[y+1]=U.y,x.array[y+2]=U.z,x.array[y+3]=U.w,x.array[y+
+4]=V.x,x.array[y+5]=V.y,x.array[y+6]=V.z,x.array[y+7]=V.w,x.array[y+8]=W.x,x.array[y+9]=W.y,x.array[y+10]=W.z,x.array[y+11]=W.w,y+=12;F=0;for($=ua.length;F<$;F++)S=$a[ua[F]],U=x.value[S.a],V=x.value[S.b],W=x.value[S.c],pa=x.value[S.d],x.array[y]=U.x,x.array[y+1]=U.y,x.array[y+2]=U.z,x.array[y+3]=U.w,x.array[y+4]=V.x,x.array[y+5]=V.y,x.array[y+6]=V.z,x.array[y+7]=V.w,x.array[y+8]=W.x,x.array[y+9]=W.y,x.array[y+10]=W.z,x.array[y+11]=W.w,x.array[y+12]=pa.x,x.array[y+13]=pa.y,x.array[y+14]=pa.z,x.array[y+
+15]=pa.w,y+=16}else if("faces"===x.boundTo){F=0;for($=ta.length;F<$;F++)W=V=U=ya=x.value[ta[F]],x.array[y]=U.x,x.array[y+1]=U.y,x.array[y+2]=U.z,x.array[y+3]=U.w,x.array[y+4]=V.x,x.array[y+5]=V.y,x.array[y+6]=V.z,x.array[y+7]=V.w,x.array[y+8]=W.x,x.array[y+9]=W.y,x.array[y+10]=W.z,x.array[y+11]=W.w,y+=12;F=0;for($=ua.length;F<$;F++)pa=W=V=U=ya=x.value[ua[F]],x.array[y]=U.x,x.array[y+1]=U.y,x.array[y+2]=U.z,x.array[y+3]=U.w,x.array[y+4]=V.x,x.array[y+5]=V.y,x.array[y+6]=V.z,x.array[y+7]=V.w,x.array[y+
+8]=W.x,x.array[y+9]=W.y,x.array[y+10]=W.z,x.array[y+11]=W.w,x.array[y+12]=pa.x,x.array[y+13]=pa.y,x.array[y+14]=pa.z,x.array[y+15]=pa.w,y+=16}else if("faceVertices"===x.boundTo){F=0;for($=ta.length;F<$;F++)ya=x.value[ta[F]],U=ya[0],V=ya[1],W=ya[2],x.array[y]=U.x,x.array[y+1]=U.y,x.array[y+2]=U.z,x.array[y+3]=U.w,x.array[y+4]=V.x,x.array[y+5]=V.y,x.array[y+6]=V.z,x.array[y+7]=V.w,x.array[y+8]=W.x,x.array[y+9]=W.y,x.array[y+10]=W.z,x.array[y+11]=W.w,y+=12;F=0;for($=ua.length;F<$;F++)ya=x.value[ua[F]],
+U=ya[0],V=ya[1],W=ya[2],pa=ya[3],x.array[y]=U.x,x.array[y+1]=U.y,x.array[y+2]=U.z,x.array[y+3]=U.w,x.array[y+4]=V.x,x.array[y+5]=V.y,x.array[y+6]=V.z,x.array[y+7]=V.w,x.array[y+8]=W.x,x.array[y+9]=W.y,x.array[y+10]=W.z,x.array[y+11]=W.w,x.array[y+12]=pa.x,x.array[y+13]=pa.y,x.array[y+14]=pa.z,x.array[y+15]=pa.w,y+=16}k.bindBuffer(k.ARRAY_BUFFER,x.buffer);k.bufferData(k.ARRAY_BUFFER,x.array,Ea)}}ib&&(delete ra.__inittedArrays,delete ra.__colorArray,delete ra.__normalArray,delete ra.__tangentArray,
+delete ra.__uvArray,delete ra.__uv2Array,delete ra.__faceArray,delete ra.__vertexArray,delete ra.__lineArray,delete ra.__skinIndexArray,delete ra.__skinWeightArray)}}T.verticesNeedUpdate=!1;T.morphTargetsNeedUpdate=!1;T.elementsNeedUpdate=!1;T.uvsNeedUpdate=!1;T.normalsNeedUpdate=!1;T.colorsNeedUpdate=!1;T.tangentsNeedUpdate=!1;T.buffersNeedUpdate=!1;ma.attributes&&r(ma)}else if(qa instanceof THREE.Ribbon){ma=e(qa,T);va=ma.attributes&&t(ma);if(T.verticesNeedUpdate||T.colorsNeedUpdate||T.normalsNeedUpdate||
+va){var xb=T,Bc=k.DYNAMIC_DRAW,rc=void 0,sc=void 0,tc=void 0,Cc=void 0,za=void 0,Dc=void 0,Ec=void 0,Fc=void 0,Zc=void 0,Xa=void 0,mc=void 0,Ca=void 0,gb=void 0,$c=xb.vertices,ad=xb.colors,bd=xb.normals,jd=$c.length,kd=ad.length,ld=bd.length,Gc=xb.__vertexArray,Hc=xb.__colorArray,Ic=xb.__normalArray,md=xb.colorsNeedUpdate,nd=xb.normalsNeedUpdate,Xc=xb.__webglCustomAttributesList;if(xb.verticesNeedUpdate){for(rc=0;rc<jd;rc++)Cc=$c[rc],za=3*rc,Gc[za]=Cc.x,Gc[za+1]=Cc.y,Gc[za+2]=Cc.z;k.bindBuffer(k.ARRAY_BUFFER,
+xb.__webglVertexBuffer);k.bufferData(k.ARRAY_BUFFER,Gc,Bc)}if(md){for(sc=0;sc<kd;sc++)Dc=ad[sc],za=3*sc,Hc[za]=Dc.r,Hc[za+1]=Dc.g,Hc[za+2]=Dc.b;k.bindBuffer(k.ARRAY_BUFFER,xb.__webglColorBuffer);k.bufferData(k.ARRAY_BUFFER,Hc,Bc)}if(nd){for(tc=0;tc<ld;tc++)Ec=bd[tc],za=3*tc,Ic[za]=Ec.x,Ic[za+1]=Ec.y,Ic[za+2]=Ec.z;k.bindBuffer(k.ARRAY_BUFFER,xb.__webglNormalBuffer);k.bufferData(k.ARRAY_BUFFER,Ic,Bc)}if(Xc){Fc=0;for(Zc=Xc.length;Fc<Zc;Fc++)if(Ca=Xc[Fc],Ca.needsUpdate&&(void 0===Ca.boundTo||"vertices"===
+Ca.boundTo)){za=0;mc=Ca.value.length;if(1===Ca.size)for(Xa=0;Xa<mc;Xa++)Ca.array[Xa]=Ca.value[Xa];else if(2===Ca.size)for(Xa=0;Xa<mc;Xa++)gb=Ca.value[Xa],Ca.array[za]=gb.x,Ca.array[za+1]=gb.y,za+=2;else if(3===Ca.size)if("c"===Ca.type)for(Xa=0;Xa<mc;Xa++)gb=Ca.value[Xa],Ca.array[za]=gb.r,Ca.array[za+1]=gb.g,Ca.array[za+2]=gb.b,za+=3;else for(Xa=0;Xa<mc;Xa++)gb=Ca.value[Xa],Ca.array[za]=gb.x,Ca.array[za+1]=gb.y,Ca.array[za+2]=gb.z,za+=3;else if(4===Ca.size)for(Xa=0;Xa<mc;Xa++)gb=Ca.value[Xa],Ca.array[za]=
+gb.x,Ca.array[za+1]=gb.y,Ca.array[za+2]=gb.z,Ca.array[za+3]=gb.w,za+=4;k.bindBuffer(k.ARRAY_BUFFER,Ca.buffer);k.bufferData(k.ARRAY_BUFFER,Ca.array,Bc)}}}T.verticesNeedUpdate=!1;T.colorsNeedUpdate=!1;T.normalsNeedUpdate=!1;ma.attributes&&r(ma)}else if(qa instanceof THREE.Line){ma=e(qa,T);va=ma.attributes&&t(ma);if(T.verticesNeedUpdate||T.colorsNeedUpdate||T.lineDistancesNeedUpdate||va){var yb=T,Jc=k.DYNAMIC_DRAW,uc=void 0,vc=void 0,wc=void 0,Kc=void 0,Ia=void 0,Lc=void 0,cd=yb.vertices,dd=yb.colors,
+ed=yb.lineDistances,od=cd.length,pd=dd.length,qd=ed.length,Mc=yb.__vertexArray,Nc=yb.__colorArray,fd=yb.__lineDistanceArray,rd=yb.colorsNeedUpdate,sd=yb.lineDistancesNeedUpdate,Yc=yb.__webglCustomAttributesList,Oc=void 0,gd=void 0,Ya=void 0,nc=void 0,hb=void 0,Da=void 0;if(yb.verticesNeedUpdate){for(uc=0;uc<od;uc++)Kc=cd[uc],Ia=3*uc,Mc[Ia]=Kc.x,Mc[Ia+1]=Kc.y,Mc[Ia+2]=Kc.z;k.bindBuffer(k.ARRAY_BUFFER,yb.__webglVertexBuffer);k.bufferData(k.ARRAY_BUFFER,Mc,Jc)}if(rd){for(vc=0;vc<pd;vc++)Lc=dd[vc],Ia=
+3*vc,Nc[Ia]=Lc.r,Nc[Ia+1]=Lc.g,Nc[Ia+2]=Lc.b;k.bindBuffer(k.ARRAY_BUFFER,yb.__webglColorBuffer);k.bufferData(k.ARRAY_BUFFER,Nc,Jc)}if(sd){for(wc=0;wc<qd;wc++)fd[wc]=ed[wc];k.bindBuffer(k.ARRAY_BUFFER,yb.__webglLineDistanceBuffer);k.bufferData(k.ARRAY_BUFFER,fd,Jc)}if(Yc){Oc=0;for(gd=Yc.length;Oc<gd;Oc++)if(Da=Yc[Oc],Da.needsUpdate&&(void 0===Da.boundTo||"vertices"===Da.boundTo)){Ia=0;nc=Da.value.length;if(1===Da.size)for(Ya=0;Ya<nc;Ya++)Da.array[Ya]=Da.value[Ya];else if(2===Da.size)for(Ya=0;Ya<nc;Ya++)hb=
+Da.value[Ya],Da.array[Ia]=hb.x,Da.array[Ia+1]=hb.y,Ia+=2;else if(3===Da.size)if("c"===Da.type)for(Ya=0;Ya<nc;Ya++)hb=Da.value[Ya],Da.array[Ia]=hb.r,Da.array[Ia+1]=hb.g,Da.array[Ia+2]=hb.b,Ia+=3;else for(Ya=0;Ya<nc;Ya++)hb=Da.value[Ya],Da.array[Ia]=hb.x,Da.array[Ia+1]=hb.y,Da.array[Ia+2]=hb.z,Ia+=3;else if(4===Da.size)for(Ya=0;Ya<nc;Ya++)hb=Da.value[Ya],Da.array[Ia]=hb.x,Da.array[Ia+1]=hb.y,Da.array[Ia+2]=hb.z,Da.array[Ia+3]=hb.w,Ia+=4;k.bindBuffer(k.ARRAY_BUFFER,Da.buffer);k.bufferData(k.ARRAY_BUFFER,
+Da.array,Jc)}}}T.verticesNeedUpdate=!1;T.colorsNeedUpdate=!1;T.lineDistancesNeedUpdate=!1;ma.attributes&&r(ma)}else qa instanceof THREE.ParticleSystem&&(T instanceof THREE.BufferGeometry?((T.verticesNeedUpdate||T.colorsNeedUpdate)&&j(T,k.DYNAMIC_DRAW,!T.dynamic),T.verticesNeedUpdate=!1,T.colorsNeedUpdate=!1):(ma=e(qa,T),va=ma.attributes&&t(ma),(T.verticesNeedUpdate||T.colorsNeedUpdate||qa.sortParticles||va)&&i(T,k.DYNAMIC_DRAW,qa),T.verticesNeedUpdate=!1,T.colorsNeedUpdate=!1,ma.attributes&&r(ma)))}};
+this.initMaterial=function(a,b,c,d){var e,f,g,h,i,j,l,m,n;a instanceof THREE.MeshDepthMaterial?n="depth":a instanceof THREE.MeshNormalMaterial?n="normal":a instanceof THREE.MeshBasicMaterial?n="basic":a instanceof THREE.MeshLambertMaterial?n="lambert":a instanceof THREE.MeshPhongMaterial?n="phong":a instanceof THREE.LineBasicMaterial?n="basic":a instanceof THREE.LineDashedMaterial?n="dashed":a instanceof THREE.ParticleBasicMaterial&&(n="particle_basic");if(n){var o=THREE.ShaderLib[n];a.uniforms=THREE.UniformsUtils.clone(o.uniforms);
+a.vertexShader=o.vertexShader;a.fragmentShader=o.fragmentShader}var p,s,r;e=p=s=r=o=0;for(f=b.length;e<f;e++)g=b[e],g.onlyShadow||(g instanceof THREE.DirectionalLight&&p++,g instanceof THREE.PointLight&&s++,g instanceof THREE.SpotLight&&r++,g instanceof THREE.HemisphereLight&&o++);e=p;f=s;g=r;h=o;o=p=0;for(r=b.length;o<r;o++)s=b[o],s.castShadow&&(s instanceof THREE.SpotLight&&p++,s instanceof THREE.DirectionalLight&&!s.shadowCascade&&p++);m=p;hc&&d&&d.useVertexTexture?l=1024:(b=k.getParameter(k.MAX_VERTEX_UNIFORM_VECTORS),
+b=Math.floor((b-20)/4),void 0!==d&&d instanceof THREE.SkinnedMesh&&(b=Math.min(d.bones.length,b),b<d.bones.length&&console.warn("WebGLRenderer: too many bones - "+d.bones.length+", this GPU supports just "+b+" (try OpenGL instead of ANGLE)")),l=b);var q;a:{s=a.fragmentShader;r=a.vertexShader;o=a.uniforms;b=a.attributes;p=a.defines;var c={map:!!a.map,envMap:!!a.envMap,lightMap:!!a.lightMap,bumpMap:!!a.bumpMap,normalMap:!!a.normalMap,specularMap:!!a.specularMap,vertexColors:a.vertexColors,fog:c,useFog:a.fog,
+fogExp:c instanceof THREE.FogExp2,sizeAttenuation:a.sizeAttenuation,skinning:a.skinning,maxBones:l,useVertexTexture:hc&&d&&d.useVertexTexture,boneTextureWidth:d&&d.boneTextureWidth,boneTextureHeight:d&&d.boneTextureHeight,morphTargets:a.morphTargets,morphNormals:a.morphNormals,maxMorphTargets:this.maxMorphTargets,maxMorphNormals:this.maxMorphNormals,maxDirLights:e,maxPointLights:f,maxSpotLights:g,maxHemiLights:h,maxShadows:m,shadowMapEnabled:this.shadowMapEnabled&&d.receiveShadow,shadowMapSoft:this.shadowMapSoft,
+shadowMapDebug:this.shadowMapDebug,shadowMapCascade:this.shadowMapCascade,alphaTest:a.alphaTest,metal:a.metal,perPixel:a.perPixel,wrapAround:a.wrapAround,doubleSided:a.side===THREE.DoubleSide,flipSided:a.side===THREE.BackSide},t,u,v,d=[];n?d.push(n):(d.push(s),d.push(r));for(u in p)d.push(u),d.push(p[u]);for(t in c)d.push(t),d.push(c[t]);n=d.join();t=0;for(u=oa.length;t<u;t++)if(d=oa[t],d.code===n){d.usedTimes++;q=d.program;break a}t=[];for(v in p)u=p[v],!1!==u&&(u="#define "+v+" "+u,t.push(u));u=
+t.join("\n");v=k.createProgram();t=["precision "+N+" float;",u,gc?"#define VERTEX_TEXTURES":"",L.gammaInput?"#define GAMMA_INPUT":"",L.gammaOutput?"#define GAMMA_OUTPUT":"",L.physicallyBasedShading?"#define PHYSICALLY_BASED_SHADING":"","#define MAX_DIR_LIGHTS "+c.maxDirLights,"#define MAX_POINT_LIGHTS "+c.maxPointLights,"#define MAX_SPOT_LIGHTS "+c.maxSpotLights,"#define MAX_HEMI_LIGHTS "+c.maxHemiLights,"#define MAX_SHADOWS "+c.maxShadows,"#define MAX_BONES "+c.maxBones,c.map?"#define USE_MAP":"",
+c.envMap?"#define USE_ENVMAP":"",c.lightMap?"#define USE_LIGHTMAP":"",c.bumpMap?"#define USE_BUMPMAP":"",c.normalMap?"#define USE_NORMALMAP":"",c.specularMap?"#define USE_SPECULARMAP":"",c.vertexColors?"#define USE_COLOR":"",c.skinning?"#define USE_SKINNING":"",c.useVertexTexture?"#define BONE_TEXTURE":"",c.boneTextureWidth?"#define N_BONE_PIXEL_X "+c.boneTextureWidth.toFixed(1):"",c.boneTextureHeight?"#define N_BONE_PIXEL_Y "+c.boneTextureHeight.toFixed(1):"",c.morphTargets?"#define USE_MORPHTARGETS":
+"",c.morphNormals?"#define USE_MORPHNORMALS":"",c.perPixel?"#define PHONG_PER_PIXEL":"",c.wrapAround?"#define WRAP_AROUND":"",c.doubleSided?"#define DOUBLE_SIDED":"",c.flipSided?"#define FLIP_SIDED":"",c.shadowMapEnabled?"#define USE_SHADOWMAP":"",c.shadowMapSoft?"#define SHADOWMAP_SOFT":"",c.shadowMapDebug?"#define SHADOWMAP_DEBUG":"",c.shadowMapCascade?"#define SHADOWMAP_CASCADE":"",c.sizeAttenuation?"#define USE_SIZEATTENUATION":"","uniform mat4 modelMatrix;\nuniform mat4 modelViewMatrix;\nuniform mat4 projectionMatrix;\nuniform mat4 viewMatrix;\nuniform mat3 normalMatrix;\nuniform vec3 cameraPosition;\nattribute vec3 position;\nattribute vec3 normal;\nattribute vec2 uv;\nattribute vec2 uv2;\n#ifdef USE_COLOR\nattribute vec3 color;\n#endif\n#ifdef USE_MORPHTARGETS\nattribute vec3 morphTarget0;\nattribute vec3 morphTarget1;\nattribute vec3 morphTarget2;\nattribute vec3 morphTarget3;\n#ifdef USE_MORPHNORMALS\nattribute vec3 morphNormal0;\nattribute vec3 morphNormal1;\nattribute vec3 morphNormal2;\nattribute vec3 morphNormal3;\n#else\nattribute vec3 morphTarget4;\nattribute vec3 morphTarget5;\nattribute vec3 morphTarget6;\nattribute vec3 morphTarget7;\n#endif\n#endif\n#ifdef USE_SKINNING\nattribute vec4 skinIndex;\nattribute vec4 skinWeight;\n#endif\n"].join("\n");
+u=["precision "+N+" float;",c.bumpMap||c.normalMap?"#extension GL_OES_standard_derivatives : enable":"",u,"#define MAX_DIR_LIGHTS "+c.maxDirLights,"#define MAX_POINT_LIGHTS "+c.maxPointLights,"#define MAX_SPOT_LIGHTS "+c.maxSpotLights,"#define MAX_HEMI_LIGHTS "+c.maxHemiLights,"#define MAX_SHADOWS "+c.maxShadows,c.alphaTest?"#define ALPHATEST "+c.alphaTest:"",L.gammaInput?"#define GAMMA_INPUT":"",L.gammaOutput?"#define GAMMA_OUTPUT":"",L.physicallyBasedShading?"#define PHYSICALLY_BASED_SHADING":"",
+c.useFog&&c.fog?"#define USE_FOG":"",c.useFog&&c.fogExp?"#define FOG_EXP2":"",c.map?"#define USE_MAP":"",c.envMap?"#define USE_ENVMAP":"",c.lightMap?"#define USE_LIGHTMAP":"",c.bumpMap?"#define USE_BUMPMAP":"",c.normalMap?"#define USE_NORMALMAP":"",c.specularMap?"#define USE_SPECULARMAP":"",c.vertexColors?"#define USE_COLOR":"",c.metal?"#define METAL":"",c.perPixel?"#define PHONG_PER_PIXEL":"",c.wrapAround?"#define WRAP_AROUND":"",c.doubleSided?"#define DOUBLE_SIDED":"",c.flipSided?"#define FLIP_SIDED":
+"",c.shadowMapEnabled?"#define USE_SHADOWMAP":"",c.shadowMapSoft?"#define SHADOWMAP_SOFT":"",c.shadowMapDebug?"#define SHADOWMAP_DEBUG":"",c.shadowMapCascade?"#define SHADOWMAP_CASCADE":"","uniform mat4 viewMatrix;\nuniform vec3 cameraPosition;\n"].join("\n");u=G("fragment",u+s);t=G("vertex",t+r);k.attachShader(v,t);k.attachShader(v,u);k.linkProgram(v);k.getProgramParameter(v,k.LINK_STATUS)||console.error("Could not initialise shader\nVALIDATE_STATUS: "+k.getProgramParameter(v,k.VALIDATE_STATUS)+
+", gl error ["+k.getError()+"]");k.deleteShader(u);k.deleteShader(t);v.uniforms={};v.attributes={};var w;t="viewMatrix modelViewMatrix projectionMatrix normalMatrix modelMatrix cameraPosition morphTargetInfluences".split(" ");c.useVertexTexture?t.push("boneTexture"):t.push("boneGlobalMatrices");for(w in o)t.push(w);w=t;t=0;for(u=w.length;t<u;t++)d=w[t],v.uniforms[d]=k.getUniformLocation(v,d);t="position normal uv uv2 tangent color skinIndex skinWeight lineDistance".split(" ");for(w=0;w<c.maxMorphTargets;w++)t.push("morphTarget"+
+w);for(w=0;w<c.maxMorphNormals;w++)t.push("morphNormal"+w);for(q in b)t.push(q);q=t;w=0;for(b=q.length;w<b;w++)t=q[w],v.attributes[t]=k.getAttribLocation(v,t);v.id=X++;oa.push({program:v,code:n,usedTimes:1});L.info.memory.programs=oa.length;q=v}a.program=q;q=a.program.attributes;0<=q.position&&k.enableVertexAttribArray(q.position);0<=q.color&&k.enableVertexAttribArray(q.color);0<=q.normal&&k.enableVertexAttribArray(q.normal);0<=q.tangent&&k.enableVertexAttribArray(q.tangent);0<=q.lineDistance&&k.enableVertexAttribArray(q.lineDistance);
+a.skinning&&(0<=q.skinIndex&&0<=q.skinWeight)&&(k.enableVertexAttribArray(q.skinIndex),k.enableVertexAttribArray(q.skinWeight));if(a.attributes)for(j in a.attributes)void 0!==q[j]&&0<=q[j]&&k.enableVertexAttribArray(q[j]);if(a.morphTargets){a.numSupportedMorphTargets=0;v="morphTarget";for(j=0;j<this.maxMorphTargets;j++)w=v+j,0<=q[w]&&(k.enableVertexAttribArray(q[w]),a.numSupportedMorphTargets++)}if(a.morphNormals){a.numSupportedMorphNormals=0;v="morphNormal";for(j=0;j<this.maxMorphNormals;j++)w=v+
+j,0<=q[w]&&(k.enableVertexAttribArray(q[w]),a.numSupportedMorphNormals++)}a.uniformsList=[];for(i in a.uniforms)a.uniformsList.push([a.uniforms[i],i])};this.setFaceCulling=function(a,b){a?(!b||"ccw"===b?k.frontFace(k.CCW):k.frontFace(k.CW),"back"===a?k.cullFace(k.BACK):"front"===a?k.cullFace(k.FRONT):k.cullFace(k.FRONT_AND_BACK),k.enable(k.CULL_FACE)):k.disable(k.CULL_FACE)};this.setMaterialFaces=function(a){var b=a.side===THREE.DoubleSide,a=a.side===THREE.BackSide;Na!==b&&(b?k.disable(k.CULL_FACE):
+k.enable(k.CULL_FACE),Na=b);Ja!==a&&(a?k.frontFace(k.CW):k.frontFace(k.CCW),Ja=a)};this.setDepthTest=function(a){ib!==a&&(a?k.enable(k.DEPTH_TEST):k.disable(k.DEPTH_TEST),ib=a)};this.setDepthWrite=function(a){ob!==a&&(k.depthMask(a),ob=a)};this.setBlending=function(a,b,c,d){a!==ma&&(a===THREE.NoBlending?k.disable(k.BLEND):a===THREE.AdditiveBlending?(k.enable(k.BLEND),k.blendEquation(k.FUNC_ADD),k.blendFunc(k.SRC_ALPHA,k.ONE)):a===THREE.SubtractiveBlending?(k.enable(k.BLEND),k.blendEquation(k.FUNC_ADD),
+k.blendFunc(k.ZERO,k.ONE_MINUS_SRC_COLOR)):a===THREE.MultiplyBlending?(k.enable(k.BLEND),k.blendEquation(k.FUNC_ADD),k.blendFunc(k.ZERO,k.SRC_COLOR)):a===THREE.CustomBlending?k.enable(k.BLEND):(k.enable(k.BLEND),k.blendEquationSeparate(k.FUNC_ADD,k.FUNC_ADD),k.blendFuncSeparate(k.SRC_ALPHA,k.ONE_MINUS_SRC_ALPHA,k.ONE,k.ONE_MINUS_SRC_ALPHA)),ma=a);if(a===THREE.CustomBlending){if(b!==sa&&(k.blendEquation(H(b)),sa=b),c!==Ea||d!==rb)k.blendFunc(H(c),H(d)),Ea=c,rb=d}else rb=Ea=sa=null};this.setTexture=
+function(a,b){if(a.needsUpdate){a.__webglInit||(a.__webglInit=!0,a.__webglTexture=k.createTexture(),L.info.memory.textures++);k.activeTexture(k.TEXTURE0+b);k.bindTexture(k.TEXTURE_2D,a.__webglTexture);k.pixelStorei(k.UNPACK_FLIP_Y_WEBGL,a.flipY);k.pixelStorei(k.UNPACK_PREMULTIPLY_ALPHA_WEBGL,a.premultiplyAlpha);var c=a.image,d=0===(c.width&c.width-1)&&0===(c.height&c.height-1),e=H(a.format),f=H(a.type);P(k.TEXTURE_2D,a,d);if(a instanceof THREE.CompressedTexture)for(var f=a.mipmaps,g=0,h=f.length;g<
+h;g++)c=f[g],k.compressedTexImage2D(k.TEXTURE_2D,g,e,c.width,c.height,0,c.data);else a instanceof THREE.DataTexture?k.texImage2D(k.TEXTURE_2D,0,e,c.width,c.height,0,e,f,c.data):k.texImage2D(k.TEXTURE_2D,0,e,e,f,a.image);a.generateMipmaps&&d&&k.generateMipmap(k.TEXTURE_2D);a.needsUpdate=!1;if(a.onUpdate)a.onUpdate()}else k.activeTexture(k.TEXTURE0+b),k.bindTexture(k.TEXTURE_2D,a.__webglTexture)};this.setRenderTarget=function(a){var b=a instanceof THREE.WebGLRenderTargetCube;if(a&&!a.__webglFramebuffer){void 0===
+a.depthBuffer&&(a.depthBuffer=!0);void 0===a.stencilBuffer&&(a.stencilBuffer=!0);a.__webglTexture=k.createTexture();var c=0===(a.width&a.width-1)&&0===(a.height&a.height-1),d=H(a.format),e=H(a.type);if(b){a.__webglFramebuffer=[];a.__webglRenderbuffer=[];k.bindTexture(k.TEXTURE_CUBE_MAP,a.__webglTexture);P(k.TEXTURE_CUBE_MAP,a,c);for(var f=0;6>f;f++){a.__webglFramebuffer[f]=k.createFramebuffer();a.__webglRenderbuffer[f]=k.createRenderbuffer();k.texImage2D(k.TEXTURE_CUBE_MAP_POSITIVE_X+f,0,d,a.width,
+a.height,0,d,e,null);var g=a,h=k.TEXTURE_CUBE_MAP_POSITIVE_X+f;k.bindFramebuffer(k.FRAMEBUFFER,a.__webglFramebuffer[f]);k.framebufferTexture2D(k.FRAMEBUFFER,k.COLOR_ATTACHMENT0,h,g.__webglTexture,0);B(a.__webglRenderbuffer[f],a)}c&&k.generateMipmap(k.TEXTURE_CUBE_MAP)}else a.__webglFramebuffer=k.createFramebuffer(),a.__webglRenderbuffer=k.createRenderbuffer(),k.bindTexture(k.TEXTURE_2D,a.__webglTexture),P(k.TEXTURE_2D,a,c),k.texImage2D(k.TEXTURE_2D,0,d,a.width,a.height,0,d,e,null),d=k.TEXTURE_2D,
+k.bindFramebuffer(k.FRAMEBUFFER,a.__webglFramebuffer),k.framebufferTexture2D(k.FRAMEBUFFER,k.COLOR_ATTACHMENT0,d,a.__webglTexture,0),B(a.__webglRenderbuffer,a),c&&k.generateMipmap(k.TEXTURE_2D);b?k.bindTexture(k.TEXTURE_CUBE_MAP,null):k.bindTexture(k.TEXTURE_2D,null);k.bindRenderbuffer(k.RENDERBUFFER,null);k.bindFramebuffer(k.FRAMEBUFFER,null)}a?(b=b?a.__webglFramebuffer[a.activeCubeFace]:a.__webglFramebuffer,c=a.width,a=a.height,e=d=0):(b=null,c=kb,a=Oa,d=Sa,e=Ka);b!==ca&&(k.bindFramebuffer(k.FRAMEBUFFER,
+b),k.viewport(d,e,c,a),ca=b);lb=c;ab=a};this.shadowMapPlugin=new THREE.ShadowMapPlugin;this.addPrePlugin(this.shadowMapPlugin);this.addPostPlugin(new THREE.SpritePlugin);this.addPostPlugin(new THREE.LensFlarePlugin)};
+THREE.WebGLRenderTarget=function(a,b,c){this.width=a;this.height=b;c=c||{};this.wrapS=void 0!==c.wrapS?c.wrapS:THREE.ClampToEdgeWrapping;this.wrapT=void 0!==c.wrapT?c.wrapT:THREE.ClampToEdgeWrapping;this.magFilter=void 0!==c.magFilter?c.magFilter:THREE.LinearFilter;this.minFilter=void 0!==c.minFilter?c.minFilter:THREE.LinearMipMapLinearFilter;this.anisotropy=void 0!==c.anisotropy?c.anisotropy:1;this.offset=new THREE.Vector2(0,0);this.repeat=new THREE.Vector2(1,1);this.format=void 0!==c.format?c.format:
+THREE.RGBAFormat;this.type=void 0!==c.type?c.type:THREE.UnsignedByteType;this.depthBuffer=void 0!==c.depthBuffer?c.depthBuffer:!0;this.stencilBuffer=void 0!==c.stencilBuffer?c.stencilBuffer:!0;this.generateMipmaps=!0};
+THREE.WebGLRenderTarget.prototype.clone=function(){var a=new THREE.WebGLRenderTarget(this.width,this.height);a.wrapS=this.wrapS;a.wrapT=this.wrapT;a.magFilter=this.magFilter;a.anisotropy=this.anisotropy;a.minFilter=this.minFilter;a.offset.copy(this.offset);a.repeat.copy(this.repeat);a.format=this.format;a.type=this.type;a.depthBuffer=this.depthBuffer;a.stencilBuffer=this.stencilBuffer;a.generateMipmaps=this.generateMipmaps;return a};
+THREE.WebGLRenderTargetCube=function(a,b,c){THREE.WebGLRenderTarget.call(this,a,b,c);this.activeCubeFace=0};THREE.WebGLRenderTargetCube.prototype=Object.create(THREE.WebGLRenderTarget.prototype);THREE.RenderableVertex=function(){this.positionWorld=new THREE.Vector3;this.positionScreen=new THREE.Vector4;this.visible=!0};THREE.RenderableVertex.prototype.copy=function(a){this.positionWorld.copy(a.positionWorld);this.positionScreen.copy(a.positionScreen)};
+THREE.RenderableFace3=function(){this.v1=new THREE.RenderableVertex;this.v2=new THREE.RenderableVertex;this.v3=new THREE.RenderableVertex;this.centroidWorld=new THREE.Vector3;this.centroidScreen=new THREE.Vector3;this.normalWorld=new THREE.Vector3;this.vertexNormalsWorld=[new THREE.Vector3,new THREE.Vector3,new THREE.Vector3];this.vertexNormalsLength=0;this.material=this.color=null;this.uvs=[[]];this.z=null};
+THREE.RenderableFace4=function(){this.v1=new THREE.RenderableVertex;this.v2=new THREE.RenderableVertex;this.v3=new THREE.RenderableVertex;this.v4=new THREE.RenderableVertex;this.centroidWorld=new THREE.Vector3;this.centroidScreen=new THREE.Vector3;this.normalWorld=new THREE.Vector3;this.vertexNormalsWorld=[new THREE.Vector3,new THREE.Vector3,new THREE.Vector3,new THREE.Vector3];this.vertexNormalsLength=0;this.material=this.color=null;this.uvs=[[]];this.z=null};
+THREE.RenderableObject=function(){this.z=this.object=null};THREE.RenderableParticle=function(){this.rotation=this.z=this.y=this.x=this.object=null;this.scale=new THREE.Vector2;this.material=null};THREE.RenderableLine=function(){this.z=null;this.v1=new THREE.RenderableVertex;this.v2=new THREE.RenderableVertex;this.material=null};
+THREE.ColorUtils={adjustHSV:function(a,b,c,d){var e=THREE.ColorUtils.__hsv;a.getHSV(e);e.h=THREE.Math.clamp(e.h+b,0,1);e.s=THREE.Math.clamp(e.s+c,0,1);e.v=THREE.Math.clamp(e.v+d,0,1);a.setHSV(e.h,e.s,e.v)}};THREE.ColorUtils.__hsv={h:0,s:0,v:0};
+THREE.GeometryUtils={merge:function(a,b){var c,d,e=a.vertices.length,f=b instanceof THREE.Mesh?b.geometry:b,g=a.vertices,h=f.vertices,i=a.faces,j=f.faces,l=a.faceVertexUvs[0],f=f.faceVertexUvs[0];b instanceof THREE.Mesh&&(b.matrixAutoUpdate&&b.updateMatrix(),c=b.matrix,d=new THREE.Matrix4,d.extractRotation(c,b.scale));for(var m=0,n=h.length;m<n;m++){var p=h[m].clone();c&&c.multiplyVector3(p);g.push(p)}m=0;for(n=j.length;m<n;m++){var p=j[m],o,s,t=p.vertexNormals,r=p.vertexColors;p instanceof THREE.Face3?
+o=new THREE.Face3(p.a+e,p.b+e,p.c+e):p instanceof THREE.Face4&&(o=new THREE.Face4(p.a+e,p.b+e,p.c+e,p.d+e));o.normal.copy(p.normal);d&&d.multiplyVector3(o.normal);g=0;for(h=t.length;g<h;g++)s=t[g].clone(),d&&d.multiplyVector3(s),o.vertexNormals.push(s);o.color.copy(p.color);g=0;for(h=r.length;g<h;g++)s=r[g],o.vertexColors.push(s.clone());o.materialIndex=p.materialIndex;o.centroid.copy(p.centroid);c&&c.multiplyVector3(o.centroid);i.push(o)}m=0;for(n=f.length;m<n;m++){c=f[m];d=[];g=0;for(h=c.length;g<
+h;g++)d.push(new THREE.UV(c[g].u,c[g].v));l.push(d)}},removeMaterials:function(a,b){for(var c={},d=0,e=b.length;d<e;d++)c[b[d]]=!0;for(var f,g=[],d=0,e=a.faces.length;d<e;d++)f=a.faces[d],f.materialIndex in c||g.push(f);a.faces=g},randomPointInTriangle:function(a,b,c){var d,e,f,g=new THREE.Vector3,h=THREE.GeometryUtils.__v1;d=THREE.GeometryUtils.random();e=THREE.GeometryUtils.random();1<d+e&&(d=1-d,e=1-e);f=1-d-e;g.copy(a);g.multiplyScalar(d);h.copy(b);h.multiplyScalar(e);g.addSelf(h);h.copy(c);h.multiplyScalar(f);
+g.addSelf(h);return g},randomPointInFace:function(a,b,c){var d,e,f;if(a instanceof THREE.Face3)return d=b.vertices[a.a],e=b.vertices[a.b],f=b.vertices[a.c],THREE.GeometryUtils.randomPointInTriangle(d,e,f);if(a instanceof THREE.Face4){d=b.vertices[a.a];e=b.vertices[a.b];f=b.vertices[a.c];var b=b.vertices[a.d],g;c?a._area1&&a._area2?(c=a._area1,g=a._area2):(c=THREE.GeometryUtils.triangleArea(d,e,b),g=THREE.GeometryUtils.triangleArea(e,f,b),a._area1=c,a._area2=g):(c=THREE.GeometryUtils.triangleArea(d,
+e,b),g=THREE.GeometryUtils.triangleArea(e,f,b));return THREE.GeometryUtils.random()*(c+g)<c?THREE.GeometryUtils.randomPointInTriangle(d,e,b):THREE.GeometryUtils.randomPointInTriangle(e,f,b)}},randomPointsInGeometry:function(a,b){function c(a){function b(c,d){if(d<c)return c;var e=c+Math.floor((d-c)/2);return j[e]>a?b(c,e-1):j[e]<a?b(e+1,d):e}return b(0,j.length-1)}var d,e,f=a.faces,g=a.vertices,h=f.length,i=0,j=[],l,m,n,p;for(e=0;e<h;e++)d=f[e],d instanceof THREE.Face3?(l=g[d.a],m=g[d.b],n=g[d.c],
+d._area=THREE.GeometryUtils.triangleArea(l,m,n)):d instanceof THREE.Face4&&(l=g[d.a],m=g[d.b],n=g[d.c],p=g[d.d],d._area1=THREE.GeometryUtils.triangleArea(l,m,p),d._area2=THREE.GeometryUtils.triangleArea(m,n,p),d._area=d._area1+d._area2),i+=d._area,j[e]=i;d=[];for(e=0;e<b;e++)g=THREE.GeometryUtils.random()*i,g=c(g),d[e]=THREE.GeometryUtils.randomPointInFace(f[g],a,!0);return d},triangleArea:function(a,b,c){var d,e=THREE.GeometryUtils.__v1;e.sub(a,b);d=e.length();e.sub(a,c);a=e.length();e.sub(b,c);
+c=e.length();b=0.5*(d+a+c);return Math.sqrt(b*(b-d)*(b-a)*(b-c))},center:function(a){a.computeBoundingBox();var b=a.boundingBox,c=new THREE.Vector3;c.add(b.min,b.max);c.multiplyScalar(-0.5);a.applyMatrix((new THREE.Matrix4).makeTranslation(c.x,c.y,c.z));a.computeBoundingBox();return c},normalizeUVs:function(a){for(var a=a.faceVertexUvs[0],b=0,c=a.length;b<c;b++)for(var d=a[b],e=0,f=d.length;e<f;e++)if(1!==d[e].u&&(d[e].u-=Math.floor(d[e].u)),1!==d[e].v)d[e].v-=Math.floor(d[e].v)},triangulateQuads:function(a){var b,
+c,d,e,f=[],g=[],h=[];b=0;for(c=a.faceUvs.length;b<c;b++)g[b]=[];b=0;for(c=a.faceVertexUvs.length;b<c;b++)h[b]=[];b=0;for(c=a.faces.length;b<c;b++)if(d=a.faces[b],d instanceof THREE.Face4){e=d.a;var i=d.b,j=d.c,l=d.d,m=new THREE.Face3,n=new THREE.Face3;m.color.copy(d.color);n.color.copy(d.color);m.materialIndex=d.materialIndex;n.materialIndex=d.materialIndex;m.a=e;m.b=i;m.c=l;n.a=i;n.b=j;n.c=l;4===d.vertexColors.length&&(m.vertexColors[0]=d.vertexColors[0].clone(),m.vertexColors[1]=d.vertexColors[1].clone(),
+m.vertexColors[2]=d.vertexColors[3].clone(),n.vertexColors[0]=d.vertexColors[1].clone(),n.vertexColors[1]=d.vertexColors[2].clone(),n.vertexColors[2]=d.vertexColors[3].clone());f.push(m,n);d=0;for(e=a.faceVertexUvs.length;d<e;d++)a.faceVertexUvs[d].length&&(m=a.faceVertexUvs[d][b],i=m[1],j=m[2],l=m[3],m=[m[0].clone(),i.clone(),l.clone()],i=[i.clone(),j.clone(),l.clone()],h[d].push(m,i));d=0;for(e=a.faceUvs.length;d<e;d++)a.faceUvs[d].length&&(i=a.faceUvs[d][b],g[d].push(i,i))}else{f.push(d);d=0;for(e=
+a.faceUvs.length;d<e;d++)g[d].push(a.faceUvs[d][b]);d=0;for(e=a.faceVertexUvs.length;d<e;d++)h[d].push(a.faceVertexUvs[d][b])}a.faces=f;a.faceUvs=g;a.faceVertexUvs=h;a.computeCentroids();a.computeFaceNormals();a.computeVertexNormals();a.hasTangents&&a.computeTangents()},explode:function(a){for(var b=[],c=0,d=a.faces.length;c<d;c++){var e=b.length,f=a.faces[c];if(f instanceof THREE.Face4){var g=f.a,h=f.b,i=f.c,g=a.vertices[g],h=a.vertices[h],i=a.vertices[i],j=a.vertices[f.d];b.push(g.clone());b.push(h.clone());
+b.push(i.clone());b.push(j.clone());f.a=e;f.b=e+1;f.c=e+2;f.d=e+3}else g=f.a,h=f.b,i=f.c,g=a.vertices[g],h=a.vertices[h],i=a.vertices[i],b.push(g.clone()),b.push(h.clone()),b.push(i.clone()),f.a=e,f.b=e+1,f.c=e+2}a.vertices=b;delete a.__tmpVertices},tessellate:function(a,b){var c,d,e,f,g,h,i,j,l,m,n,p,o,s,t,r,z,w,q,E=[],A=[];c=0;for(d=a.faceVertexUvs.length;c<d;c++)A[c]=[];c=0;for(d=a.faces.length;c<d;c++)if(e=a.faces[c],e instanceof THREE.Face3)if(f=e.a,g=e.b,h=e.c,j=a.vertices[f],l=a.vertices[g],
+m=a.vertices[h],p=j.distanceTo(l),o=l.distanceTo(m),n=j.distanceTo(m),p>b||o>b||n>b){i=a.vertices.length;w=e.clone();q=e.clone();p>=o&&p>=n?(j=j.clone(),j.lerpSelf(l,0.5),w.a=f,w.b=i,w.c=h,q.a=i,q.b=g,q.c=h,3===e.vertexNormals.length&&(f=e.vertexNormals[0].clone(),f.lerpSelf(e.vertexNormals[1],0.5),w.vertexNormals[1].copy(f),q.vertexNormals[0].copy(f)),3===e.vertexColors.length&&(f=e.vertexColors[0].clone(),f.lerpSelf(e.vertexColors[1],0.5),w.vertexColors[1].copy(f),q.vertexColors[0].copy(f)),e=0):
+o>=p&&o>=n?(j=l.clone(),j.lerpSelf(m,0.5),w.a=f,w.b=g,w.c=i,q.a=i,q.b=h,q.c=f,3===e.vertexNormals.length&&(f=e.vertexNormals[1].clone(),f.lerpSelf(e.vertexNormals[2],0.5),w.vertexNormals[2].copy(f),q.vertexNormals[0].copy(f),q.vertexNormals[1].copy(e.vertexNormals[2]),q.vertexNormals[2].copy(e.vertexNormals[0])),3===e.vertexColors.length&&(f=e.vertexColors[1].clone(),f.lerpSelf(e.vertexColors[2],0.5),w.vertexColors[2].copy(f),q.vertexColors[0].copy(f),q.vertexColors[1].copy(e.vertexColors[2]),q.vertexColors[2].copy(e.vertexColors[0])),
+e=1):(j=j.clone(),j.lerpSelf(m,0.5),w.a=f,w.b=g,w.c=i,q.a=i,q.b=g,q.c=h,3===e.vertexNormals.length&&(f=e.vertexNormals[0].clone(),f.lerpSelf(e.vertexNormals[2],0.5),w.vertexNormals[2].copy(f),q.vertexNormals[0].copy(f)),3===e.vertexColors.length&&(f=e.vertexColors[0].clone(),f.lerpSelf(e.vertexColors[2],0.5),w.vertexColors[2].copy(f),q.vertexColors[0].copy(f)),e=2);E.push(w,q);a.vertices.push(j);f=0;for(g=a.faceVertexUvs.length;f<g;f++)a.faceVertexUvs[f].length&&(j=a.faceVertexUvs[f][c],q=j[0],h=
+j[1],w=j[2],0===e?(l=q.clone(),l.lerpSelf(h,0.5),j=[q.clone(),l.clone(),w.clone()],h=[l.clone(),h.clone(),w.clone()]):1===e?(l=h.clone(),l.lerpSelf(w,0.5),j=[q.clone(),h.clone(),l.clone()],h=[l.clone(),w.clone(),q.clone()]):(l=q.clone(),l.lerpSelf(w,0.5),j=[q.clone(),h.clone(),l.clone()],h=[l.clone(),h.clone(),w.clone()]),A[f].push(j,h))}else{E.push(e);f=0;for(g=a.faceVertexUvs.length;f<g;f++)A[f].push(a.faceVertexUvs[f][c])}else if(f=e.a,g=e.b,h=e.c,i=e.d,j=a.vertices[f],l=a.vertices[g],m=a.vertices[h],
+n=a.vertices[i],p=j.distanceTo(l),o=l.distanceTo(m),s=m.distanceTo(n),t=j.distanceTo(n),p>b||o>b||s>b||t>b){r=a.vertices.length;z=a.vertices.length+1;w=e.clone();q=e.clone();p>=o&&p>=s&&p>=t||s>=o&&s>=p&&s>=t?(p=j.clone(),p.lerpSelf(l,0.5),l=m.clone(),l.lerpSelf(n,0.5),w.a=f,w.b=r,w.c=z,w.d=i,q.a=r,q.b=g,q.c=h,q.d=z,4===e.vertexNormals.length&&(f=e.vertexNormals[0].clone(),f.lerpSelf(e.vertexNormals[1],0.5),g=e.vertexNormals[2].clone(),g.lerpSelf(e.vertexNormals[3],0.5),w.vertexNormals[1].copy(f),
+w.vertexNormals[2].copy(g),q.vertexNormals[0].copy(f),q.vertexNormals[3].copy(g)),4===e.vertexColors.length&&(f=e.vertexColors[0].clone(),f.lerpSelf(e.vertexColors[1],0.5),g=e.vertexColors[2].clone(),g.lerpSelf(e.vertexColors[3],0.5),w.vertexColors[1].copy(f),w.vertexColors[2].copy(g),q.vertexColors[0].copy(f),q.vertexColors[3].copy(g)),e=0):(p=l.clone(),p.lerpSelf(m,0.5),l=n.clone(),l.lerpSelf(j,0.5),w.a=f,w.b=g,w.c=r,w.d=z,q.a=z,q.b=r,q.c=h,q.d=i,4===e.vertexNormals.length&&(f=e.vertexNormals[1].clone(),
+f.lerpSelf(e.vertexNormals[2],0.5),g=e.vertexNormals[3].clone(),g.lerpSelf(e.vertexNormals[0],0.5),w.vertexNormals[2].copy(f),w.vertexNormals[3].copy(g),q.vertexNormals[0].copy(g),q.vertexNormals[1].copy(f)),4===e.vertexColors.length&&(f=e.vertexColors[1].clone(),f.lerpSelf(e.vertexColors[2],0.5),g=e.vertexColors[3].clone(),g.lerpSelf(e.vertexColors[0],0.5),w.vertexColors[2].copy(f),w.vertexColors[3].copy(g),q.vertexColors[0].copy(g),q.vertexColors[1].copy(f)),e=1);E.push(w,q);a.vertices.push(p,l);
+f=0;for(g=a.faceVertexUvs.length;f<g;f++)a.faceVertexUvs[f].length&&(j=a.faceVertexUvs[f][c],q=j[0],h=j[1],w=j[2],j=j[3],0===e?(l=q.clone(),l.lerpSelf(h,0.5),m=w.clone(),m.lerpSelf(j,0.5),q=[q.clone(),l.clone(),m.clone(),j.clone()],h=[l.clone(),h.clone(),w.clone(),m.clone()]):(l=h.clone(),l.lerpSelf(w,0.5),m=j.clone(),m.lerpSelf(q,0.5),q=[q.clone(),h.clone(),l.clone(),m.clone()],h=[m.clone(),l.clone(),w.clone(),j.clone()]),A[f].push(q,h))}else{E.push(e);f=0;for(g=a.faceVertexUvs.length;f<g;f++)A[f].push(a.faceVertexUvs[f][c])}a.faces=
+E;a.faceVertexUvs=A}};THREE.GeometryUtils.random=THREE.Math.random16;THREE.GeometryUtils.__v1=new THREE.Vector3;
+THREE.ImageUtils={crossOrigin:"anonymous",loadTexture:function(a,b,c,d){var e=new Image,f=new THREE.Texture(e,b),b=new THREE.ImageLoader;b.addEventListener("load",function(a){f.image=a.content;f.needsUpdate=!0;c&&c(f)});b.addEventListener("error",function(a){d&&d(a.message)});b.crossOrigin=this.crossOrigin;b.load(a,e);f.sourceFile=a;return f},loadCompressedTexture:function(a,b,c,d){var e=new THREE.CompressedTexture;e.mapping=b;var f=new XMLHttpRequest;f.onload=function(){var a=THREE.ImageUtils.parseDDS(f.response,
+!0);e.format=a.format;e.mipmaps=a.mipmaps;e.image.width=a.width;e.image.height=a.height;e.generateMipmaps=!1;e.needsUpdate=!0;c&&c(e)};f.onerror=d;f.open("GET",a,!0);f.responseType="arraybuffer";f.send(null);return e},loadTextureCube:function(a,b,c,d){var e=[];e.loadCount=0;var f=new THREE.Texture;f.image=e;void 0!==b&&(f.mapping=b);f.flipY=!1;for(var b=0,g=a.length;b<g;++b){var h=new Image;e[b]=h;h.onload=function(){e.loadCount=e.loadCount+1;if(e.loadCount===6){f.needsUpdate=true;c&&c()}};h.onerror=
+d;h.crossOrigin=this.crossOrigin;h.src=a[b]}return f},loadCompressedTextureCube:function(a,b,c,d){var e=[];e.loadCount=0;var f=new THREE.CompressedTexture;f.image=e;void 0!==b&&(f.mapping=b);f.flipY=!1;f.generateMipmaps=!1;for(var b=function(a,b){return function(){var d=THREE.ImageUtils.parseDDS(a.response,true);b.format=d.format;b.mipmaps=d.mipmaps;b.width=d.width;b.height=d.height;e.loadCount=e.loadCount+1;if(e.loadCount===6){f.format=d.format;f.needsUpdate=true;c&&c()}}},g=0,h=a.length;g<h;++g){var i=
+{};e[g]=i;var j=new XMLHttpRequest;j.onload=b(j,i);j.onerror=d;j.open("GET",a[g],!0);j.responseType="arraybuffer";j.send(null)}return f},parseDDS:function(a,b){function c(a){return a.charCodeAt(0)+(a.charCodeAt(1)<<8)+(a.charCodeAt(2)<<16)+(a.charCodeAt(3)<<24)}var d={mipmaps:[],width:0,height:0,format:null,mipmapCount:1},e=c("DXT1"),f=c("DXT3"),g=c("DXT5"),h=new Int32Array(a,0,31);if(542327876!==h[0])return console.error("ImageUtils.parseDDS(): Invalid magic number in DDS header"),d;if(!h[20]&4)return console.error("ImageUtils.parseDDS(): Unsupported format, must contain a FourCC code"),
+d;var i=h[21];switch(i){case e:e=8;d.format=THREE.RGB_S3TC_DXT1_Format;break;case f:e=16;d.format=THREE.RGBA_S3TC_DXT3_Format;break;case g:e=16;d.format=THREE.RGBA_S3TC_DXT5_Format;break;default:return console.error("ImageUtils.parseDDS(): Unsupported FourCC code: ",String.fromCharCode(i&255,i>>8&255,i>>16&255,i>>24&255)),d}d.mipmapCount=1;h[2]&131072&&!1!==b&&(d.mipmapCount=Math.max(1,h[7]));d.width=h[4];d.height=h[3];h=h[1]+4;f=d.width;g=d.height;for(i=0;i<d.mipmapCount;i++){var j=Math.max(4,f)/
+4*Math.max(4,g)/4*e,l={data:new Uint8Array(a,h,j),width:f,height:g};d.mipmaps.push(l);h+=j;f=Math.max(0.5*f,1);g=Math.max(0.5*g,1)}return d},getNormalMap:function(a,b){var c=function(a){var b=Math.sqrt(a[0]*a[0]+a[1]*a[1]+a[2]*a[2]);return[a[0]/b,a[1]/b,a[2]/b]},b=b|1,d=a.width,e=a.height,f=document.createElement("canvas");f.width=d;f.height=e;var g=f.getContext("2d");g.drawImage(a,0,0);for(var h=g.getImageData(0,0,d,e).data,i=g.createImageData(d,e),j=i.data,l=0;l<d;l++)for(var m=0;m<e;m++){var n=
+0>m-1?0:m-1,p=m+1>e-1?e-1:m+1,o=0>l-1?0:l-1,s=l+1>d-1?d-1:l+1,t=[],r=[0,0,h[4*(m*d+l)]/255*b];t.push([-1,0,h[4*(m*d+o)]/255*b]);t.push([-1,-1,h[4*(n*d+o)]/255*b]);t.push([0,-1,h[4*(n*d+l)]/255*b]);t.push([1,-1,h[4*(n*d+s)]/255*b]);t.push([1,0,h[4*(m*d+s)]/255*b]);t.push([1,1,h[4*(p*d+s)]/255*b]);t.push([0,1,h[4*(p*d+l)]/255*b]);t.push([-1,1,h[4*(p*d+o)]/255*b]);n=[];o=t.length;for(p=0;p<o;p++){var s=t[p],z=t[(p+1)%o],s=[s[0]-r[0],s[1]-r[1],s[2]-r[2]],z=[z[0]-r[0],z[1]-r[1],z[2]-r[2]];n.push(c([s[1]*
+z[2]-s[2]*z[1],s[2]*z[0]-s[0]*z[2],s[0]*z[1]-s[1]*z[0]]))}t=[0,0,0];for(p=0;p<n.length;p++)t[0]+=n[p][0],t[1]+=n[p][1],t[2]+=n[p][2];t[0]/=n.length;t[1]/=n.length;t[2]/=n.length;r=4*(m*d+l);j[r]=255*((t[0]+1)/2)|0;j[r+1]=255*((t[1]+1)/2)|0;j[r+2]=255*t[2]|0;j[r+3]=255}g.putImageData(i,0,0);return f},generateDataTexture:function(a,b,c){for(var d=a*b,e=new Uint8Array(3*d),f=Math.floor(255*c.r),g=Math.floor(255*c.g),c=Math.floor(255*c.b),h=0;h<d;h++)e[3*h]=f,e[3*h+1]=g,e[3*h+2]=c;a=new THREE.DataTexture(e,
+a,b,THREE.RGBFormat);a.needsUpdate=!0;return a}};THREE.SceneUtils={createMultiMaterialObject:function(a,b){for(var c=new THREE.Object3D,d=0,e=b.length;d<e;d++)c.add(new THREE.Mesh(a,b[d]));return c},detach:function(a,b,c){a.applyMatrix(b.matrixWorld);b.remove(a);c.add(a)},attach:function(a,b,c){var d=new THREE.Matrix4;d.getInverse(c.matrixWorld);a.applyMatrix(d);b.remove(a);c.add(a)}};
+THREE.ShaderUtils={lib:{fresnel:{uniforms:{mRefractionRatio:{type:"f",value:1.02},mFresnelBias:{type:"f",value:0.1},mFresnelPower:{type:"f",value:2},mFresnelScale:{type:"f",value:1},tCube:{type:"t",value:null}},fragmentShader:"uniform samplerCube tCube;\nvarying vec3 vReflect;\nvarying vec3 vRefract[3];\nvarying float vReflectionFactor;\nvoid main() {\nvec4 reflectedColor = textureCube( tCube, vec3( -vReflect.x, vReflect.yz ) );\nvec4 refractedColor = vec4( 1.0 );\nrefractedColor.r = textureCube( tCube, vec3( -vRefract[0].x, vRefract[0].yz ) ).r;\nrefractedColor.g = textureCube( tCube, vec3( -vRefract[1].x, vRefract[1].yz ) ).g;\nrefractedColor.b = textureCube( tCube, vec3( -vRefract[2].x, vRefract[2].yz ) ).b;\ngl_FragColor = mix( refractedColor, reflectedColor, clamp( vReflectionFactor, 0.0, 1.0 ) );\n}",
+vertexShader:"uniform float mRefractionRatio;\nuniform float mFresnelBias;\nuniform float mFresnelScale;\nuniform float mFresnelPower;\nvarying vec3 vReflect;\nvarying vec3 vRefract[3];\nvarying float vReflectionFactor;\nvoid main() {\nvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\nvec4 worldPosition = modelMatrix * vec4( position, 1.0 );\nvec3 worldNormal = normalize( mat3( modelMatrix[0].xyz, modelMatrix[1].xyz, modelMatrix[2].xyz ) * normal );\nvec3 I = worldPosition.xyz - cameraPosition;\nvReflect = reflect( I, worldNormal );\nvRefract[0] = refract( normalize( I ), worldNormal, mRefractionRatio );\nvRefract[1] = refract( normalize( I ), worldNormal, mRefractionRatio * 0.99 );\nvRefract[2] = refract( normalize( I ), worldNormal, mRefractionRatio * 0.98 );\nvReflectionFactor = mFresnelBias + mFresnelScale * pow( 1.0 + dot( normalize( I ), worldNormal ), mFresnelPower );\ngl_Position = projectionMatrix * mvPosition;\n}"},
+normal:{uniforms:THREE.UniformsUtils.merge([THREE.UniformsLib.fog,THREE.UniformsLib.lights,THREE.UniformsLib.shadowmap,{enableAO:{type:"i",value:0},enableDiffuse:{type:"i",value:0},enableSpecular:{type:"i",value:0},enableReflection:{type:"i",value:0},enableDisplacement:{type:"i",value:0},tDisplacement:{type:"t",value:null},tDiffuse:{type:"t",value:null},tCube:{type:"t",value:null},tNormal:{type:"t",value:null},tSpecular:{type:"t",value:null},tAO:{type:"t",value:null},uNormalScale:{type:"v2",value:new THREE.Vector2(1,
+1)},uDisplacementBias:{type:"f",value:0},uDisplacementScale:{type:"f",value:1},uDiffuseColor:{type:"c",value:new THREE.Color(16777215)},uSpecularColor:{type:"c",value:new THREE.Color(1118481)},uAmbientColor:{type:"c",value:new THREE.Color(16777215)},uShininess:{type:"f",value:30},uOpacity:{type:"f",value:1},useRefract:{type:"i",value:0},uRefractionRatio:{type:"f",value:0.98},uReflectivity:{type:"f",value:0.5},uOffset:{type:"v2",value:new THREE.Vector2(0,0)},uRepeat:{type:"v2",value:new THREE.Vector2(1,
+1)},wrapRGB:{type:"v3",value:new THREE.Vector3(1,1,1)}}]),fragmentShader:["uniform vec3 uAmbientColor;\nuniform vec3 uDiffuseColor;\nuniform vec3 uSpecularColor;\nuniform float uShininess;\nuniform float uOpacity;\nuniform bool enableDiffuse;\nuniform bool enableSpecular;\nuniform bool enableAO;\nuniform bool enableReflection;\nuniform sampler2D tDiffuse;\nuniform sampler2D tNormal;\nuniform sampler2D tSpecular;\nuniform sampler2D tAO;\nuniform samplerCube tCube;\nuniform vec2 uNormalScale;\nuniform bool useRefract;\nuniform float uRefractionRatio;\nuniform float uReflectivity;\nvarying vec3 vTangent;\nvarying vec3 vBinormal;\nvarying vec3 vNormal;\nvarying vec2 vUv;\nuniform vec3 ambientLightColor;\n#if MAX_DIR_LIGHTS > 0\nuniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\nuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n#endif\n#if MAX_HEMI_LIGHTS > 0\nuniform vec3 hemisphereLightSkyColor[ MAX_HEMI_LIGHTS ];\nuniform vec3 hemisphereLightGroundColor[ MAX_HEMI_LIGHTS ];\nuniform vec3 hemisphereLightDirection[ MAX_HEMI_LIGHTS ];\n#endif\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\n#endif\n#if MAX_SPOT_LIGHTS > 0\nuniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];\nuniform float spotLightAngleCos[ MAX_SPOT_LIGHTS ];\nuniform float spotLightExponent[ MAX_SPOT_LIGHTS ];\nuniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\n#endif\n#ifdef WRAP_AROUND\nuniform vec3 wrapRGB;\n#endif\nvarying vec3 vWorldPosition;\nvarying vec3 vViewPosition;",
+THREE.ShaderChunk.shadowmap_pars_fragment,THREE.ShaderChunk.fog_pars_fragment,"void main() {\ngl_FragColor = vec4( vec3( 1.0 ), uOpacity );\nvec3 specularTex = vec3( 1.0 );\nvec3 normalTex = texture2D( tNormal, vUv ).xyz * 2.0 - 1.0;\nnormalTex.xy *= uNormalScale;\nnormalTex = normalize( normalTex );\nif( enableDiffuse ) {\n#ifdef GAMMA_INPUT\nvec4 texelColor = texture2D( tDiffuse, vUv );\ntexelColor.xyz *= texelColor.xyz;\ngl_FragColor = gl_FragColor * texelColor;\n#else\ngl_FragColor = gl_FragColor * texture2D( tDiffuse, vUv );\n#endif\n}\nif( enableAO ) {\n#ifdef GAMMA_INPUT\nvec4 aoColor = texture2D( tAO, vUv );\naoColor.xyz *= aoColor.xyz;\ngl_FragColor.xyz = gl_FragColor.xyz * aoColor.xyz;\n#else\ngl_FragColor.xyz = gl_FragColor.xyz * texture2D( tAO, vUv ).xyz;\n#endif\n}\nif( enableSpecular )\nspecularTex = texture2D( tSpecular, vUv ).xyz;\nmat3 tsb = mat3( normalize( vTangent ), normalize( vBinormal ), normalize( vNormal ) );\nvec3 finalNormal = tsb * normalTex;\n#ifdef FLIP_SIDED\nfinalNormal = -finalNormal;\n#endif\nvec3 normal = normalize( finalNormal );\nvec3 viewPosition = normalize( vViewPosition );\n#if MAX_POINT_LIGHTS > 0\nvec3 pointDiffuse = vec3( 0.0 );\nvec3 pointSpecular = vec3( 0.0 );\nfor ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 pointVector = lPosition.xyz + vViewPosition.xyz;\nfloat pointDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\npointDistance = 1.0 - min( ( length( pointVector ) / pointLightDistance[ i ] ), 1.0 );\npointVector = normalize( pointVector );\n#ifdef WRAP_AROUND\nfloat pointDiffuseWeightFull = max( dot( normal, pointVector ), 0.0 );\nfloat pointDiffuseWeightHalf = max( 0.5 * dot( normal, pointVector ) + 0.5, 0.0 );\nvec3 pointDiffuseWeight = mix( vec3 ( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), wrapRGB );\n#else\nfloat pointDiffuseWeight = max( dot( normal, pointVector ), 0.0 );\n#endif\npointDiffuse += pointDistance * pointLightColor[ i ] * uDiffuseColor * pointDiffuseWeight;\nvec3 pointHalfVector = normalize( pointVector + viewPosition );\nfloat pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );\nfloat pointSpecularWeight = specularTex.r * max( pow( pointDotNormalHalf, uShininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( uShininess + 2.0001 ) / 8.0;\nvec3 schlick = uSpecularColor + vec3( 1.0 - uSpecularColor ) * pow( 1.0 - dot( pointVector, pointHalfVector ), 5.0 );\npointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * pointDistance * specularNormalization;\n#else\npointSpecular += pointDistance * pointLightColor[ i ] * uSpecularColor * pointSpecularWeight * pointDiffuseWeight;\n#endif\n}\n#endif\n#if MAX_SPOT_LIGHTS > 0\nvec3 spotDiffuse = vec3( 0.0 );\nvec3 spotSpecular = vec3( 0.0 );\nfor ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\nvec3 spotVector = lPosition.xyz + vViewPosition.xyz;\nfloat spotDistance = 1.0;\nif ( spotLightDistance[ i ] > 0.0 )\nspotDistance = 1.0 - min( ( length( spotVector ) / spotLightDistance[ i ] ), 1.0 );\nspotVector = normalize( spotVector );\nfloat spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - vWorldPosition ) );\nif ( spotEffect > spotLightAngleCos[ i ] ) {\nspotEffect = max( pow( spotEffect, spotLightExponent[ i ] ), 0.0 );\n#ifdef WRAP_AROUND\nfloat spotDiffuseWeightFull = max( dot( normal, spotVector ), 0.0 );\nfloat spotDiffuseWeightHalf = max( 0.5 * dot( normal, spotVector ) + 0.5, 0.0 );\nvec3 spotDiffuseWeight = mix( vec3 ( spotDiffuseWeightFull ), vec3( spotDiffuseWeightHalf ), wrapRGB );\n#else\nfloat spotDiffuseWeight = max( dot( normal, spotVector ), 0.0 );\n#endif\nspotDiffuse += spotDistance * spotLightColor[ i ] * uDiffuseColor * spotDiffuseWeight * spotEffect;\nvec3 spotHalfVector = normalize( spotVector + viewPosition );\nfloat spotDotNormalHalf = max( dot( normal, spotHalfVector ), 0.0 );\nfloat spotSpecularWeight = specularTex.r * max( pow( spotDotNormalHalf, uShininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( uShininess + 2.0001 ) / 8.0;\nvec3 schlick = uSpecularColor + vec3( 1.0 - uSpecularColor ) * pow( 1.0 - dot( spotVector, spotHalfVector ), 5.0 );\nspotSpecular += schlick * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * spotDistance * specularNormalization * spotEffect;\n#else\nspotSpecular += spotDistance * spotLightColor[ i ] * uSpecularColor * spotSpecularWeight * spotDiffuseWeight * spotEffect;\n#endif\n}\n}\n#endif\n#if MAX_DIR_LIGHTS > 0\nvec3 dirDiffuse = vec3( 0.0 );\nvec3 dirSpecular = vec3( 0.0 );\nfor( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {\nvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\nvec3 dirVector = normalize( lDirection.xyz );\n#ifdef WRAP_AROUND\nfloat directionalLightWeightingFull = max( dot( normal, dirVector ), 0.0 );\nfloat directionalLightWeightingHalf = max( 0.5 * dot( normal, dirVector ) + 0.5, 0.0 );\nvec3 dirDiffuseWeight = mix( vec3( directionalLightWeightingFull ), vec3( directionalLightWeightingHalf ), wrapRGB );\n#else\nfloat dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );\n#endif\ndirDiffuse += directionalLightColor[ i ] * uDiffuseColor * dirDiffuseWeight;\nvec3 dirHalfVector = normalize( dirVector + viewPosition );\nfloat dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );\nfloat dirSpecularWeight = specularTex.r * max( pow( dirDotNormalHalf, uShininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( uShininess + 2.0001 ) / 8.0;\nvec3 schlick = uSpecularColor + vec3( 1.0 - uSpecularColor ) * pow( 1.0 - dot( dirVector, dirHalfVector ), 5.0 );\ndirSpecular += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;\n#else\ndirSpecular += directionalLightColor[ i ] * uSpecularColor * dirSpecularWeight * dirDiffuseWeight;\n#endif\n}\n#endif\n#if MAX_HEMI_LIGHTS > 0\nvec3 hemiDiffuse  = vec3( 0.0 );\nvec3 hemiSpecular = vec3( 0.0 );\nfor( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {\nvec4 lDirection = viewMatrix * vec4( hemisphereLightDirection[ i ], 0.0 );\nvec3 lVector = normalize( lDirection.xyz );\nfloat dotProduct = dot( normal, lVector );\nfloat hemiDiffuseWeight = 0.5 * dotProduct + 0.5;\nvec3 hemiColor = mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );\nhemiDiffuse += uDiffuseColor * hemiColor;\nvec3 hemiHalfVectorSky = normalize( lVector + viewPosition );\nfloat hemiDotNormalHalfSky = 0.5 * dot( normal, hemiHalfVectorSky ) + 0.5;\nfloat hemiSpecularWeightSky = specularTex.r * max( pow( hemiDotNormalHalfSky, uShininess ), 0.0 );\nvec3 lVectorGround = -lVector;\nvec3 hemiHalfVectorGround = normalize( lVectorGround + viewPosition );\nfloat hemiDotNormalHalfGround = 0.5 * dot( normal, hemiHalfVectorGround ) + 0.5;\nfloat hemiSpecularWeightGround = specularTex.r * max( pow( hemiDotNormalHalfGround, uShininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat dotProductGround = dot( normal, lVectorGround );\nfloat specularNormalization = ( uShininess + 2.0001 ) / 8.0;\nvec3 schlickSky = uSpecularColor + vec3( 1.0 - uSpecularColor ) * pow( 1.0 - dot( lVector, hemiHalfVectorSky ), 5.0 );\nvec3 schlickGround = uSpecularColor + vec3( 1.0 - uSpecularColor ) * pow( 1.0 - dot( lVectorGround, hemiHalfVectorGround ), 5.0 );\nhemiSpecular += hemiColor * specularNormalization * ( schlickSky * hemiSpecularWeightSky * max( dotProduct, 0.0 ) + schlickGround * hemiSpecularWeightGround * max( dotProductGround, 0.0 ) );\n#else\nhemiSpecular += uSpecularColor * hemiColor * ( hemiSpecularWeightSky + hemiSpecularWeightGround ) * hemiDiffuseWeight;\n#endif\n}\n#endif\nvec3 totalDiffuse = vec3( 0.0 );\nvec3 totalSpecular = vec3( 0.0 );\n#if MAX_DIR_LIGHTS > 0\ntotalDiffuse += dirDiffuse;\ntotalSpecular += dirSpecular;\n#endif\n#if MAX_HEMI_LIGHTS > 0\ntotalDiffuse += hemiDiffuse;\ntotalSpecular += hemiSpecular;\n#endif\n#if MAX_POINT_LIGHTS > 0\ntotalDiffuse += pointDiffuse;\ntotalSpecular += pointSpecular;\n#endif\n#if MAX_SPOT_LIGHTS > 0\ntotalDiffuse += spotDiffuse;\ntotalSpecular += spotSpecular;\n#endif\n#ifdef METAL\ngl_FragColor.xyz = gl_FragColor.xyz * ( totalDiffuse + ambientLightColor * uAmbientColor + totalSpecular );\n#else\ngl_FragColor.xyz = gl_FragColor.xyz * ( totalDiffuse + ambientLightColor * uAmbientColor ) + totalSpecular;\n#endif\nif ( enableReflection ) {\nvec3 vReflect;\nvec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );\nif ( useRefract ) {\nvReflect = refract( cameraToVertex, normal, uRefractionRatio );\n} else {\nvReflect = reflect( cameraToVertex, normal );\n}\nvec4 cubeColor = textureCube( tCube, vec3( -vReflect.x, vReflect.yz ) );\n#ifdef GAMMA_INPUT\ncubeColor.xyz *= cubeColor.xyz;\n#endif\ngl_FragColor.xyz = mix( gl_FragColor.xyz, cubeColor.xyz, specularTex.r * uReflectivity );\n}",
+THREE.ShaderChunk.shadowmap_fragment,THREE.ShaderChunk.linear_to_gamma_fragment,THREE.ShaderChunk.fog_fragment,"}"].join("\n"),vertexShader:["attribute vec4 tangent;\nuniform vec2 uOffset;\nuniform vec2 uRepeat;\nuniform bool enableDisplacement;\n#ifdef VERTEX_TEXTURES\nuniform sampler2D tDisplacement;\nuniform float uDisplacementScale;\nuniform float uDisplacementBias;\n#endif\nvarying vec3 vTangent;\nvarying vec3 vBinormal;\nvarying vec3 vNormal;\nvarying vec2 vUv;\nvarying vec3 vWorldPosition;\nvarying vec3 vViewPosition;",
+THREE.ShaderChunk.skinning_pars_vertex,THREE.ShaderChunk.shadowmap_pars_vertex,"void main() {",THREE.ShaderChunk.skinbase_vertex,THREE.ShaderChunk.skinnormal_vertex,"#ifdef USE_SKINNING\nvNormal = normalize( normalMatrix * skinnedNormal.xyz );\nvec4 skinnedTangent = skinMatrix * vec4( tangent.xyz, 0.0 );\nvTangent = normalize( normalMatrix * skinnedTangent.xyz );\n#else\nvNormal = normalize( normalMatrix * normal );\nvTangent = normalize( normalMatrix * tangent.xyz );\n#endif\nvBinormal = normalize( cross( vNormal, vTangent ) * tangent.w );\nvUv = uv * uRepeat + uOffset;\nvec3 displacedPosition;\n#ifdef VERTEX_TEXTURES\nif ( enableDisplacement ) {\nvec3 dv = texture2D( tDisplacement, uv ).xyz;\nfloat df = uDisplacementScale * dv.x + uDisplacementBias;\ndisplacedPosition = position + normalize( normal ) * df;\n} else {\n#ifdef USE_SKINNING\nvec4 skinVertex = vec4( position, 1.0 );\nvec4 skinned  = boneMatX * skinVertex * skinWeight.x;\nskinned \t  += boneMatY * skinVertex * skinWeight.y;\ndisplacedPosition  = skinned.xyz;\n#else\ndisplacedPosition = position;\n#endif\n}\n#else\n#ifdef USE_SKINNING\nvec4 skinVertex = vec4( position, 1.0 );\nvec4 skinned  = boneMatX * skinVertex * skinWeight.x;\nskinned \t  += boneMatY * skinVertex * skinWeight.y;\ndisplacedPosition  = skinned.xyz;\n#else\ndisplacedPosition = position;\n#endif\n#endif\nvec4 mvPosition = modelViewMatrix * vec4( displacedPosition, 1.0 );\nvec4 worldPosition = modelMatrix * vec4( displacedPosition, 1.0 );\ngl_Position = projectionMatrix * mvPosition;\nvWorldPosition = worldPosition.xyz;\nvViewPosition = -mvPosition.xyz;\n#ifdef USE_SHADOWMAP\nfor( int i = 0; i < MAX_SHADOWS; i ++ ) {\nvShadowCoord[ i ] = shadowMatrix[ i ] * worldPosition;\n}\n#endif\n}"].join("\n")},
+cube:{uniforms:{tCube:{type:"t",value:null},tFlip:{type:"f",value:-1}},vertexShader:"varying vec3 vWorldPosition;\nvoid main() {\nvec4 worldPosition = modelMatrix * vec4( position, 1.0 );\nvWorldPosition = worldPosition.xyz;\ngl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}",fragmentShader:"uniform samplerCube tCube;\nuniform float tFlip;\nvarying vec3 vWorldPosition;\nvoid main() {\ngl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );\n}"}}};
+THREE.FontUtils={faces:{},face:"helvetiker",weight:"normal",style:"normal",size:150,divisions:10,getFace:function(){return this.faces[this.face][this.weight][this.style]},loadFace:function(a){var b=a.familyName.toLowerCase();this.faces[b]=this.faces[b]||{};this.faces[b][a.cssFontWeight]=this.faces[b][a.cssFontWeight]||{};this.faces[b][a.cssFontWeight][a.cssFontStyle]=a;return this.faces[b][a.cssFontWeight][a.cssFontStyle]=a},drawText:function(a){for(var b=this.getFace(),c=this.size/b.resolution,d=
+0,e=String(a).split(""),f=e.length,g=[],a=0;a<f;a++){var h=new THREE.Path,h=this.extractGlyphPoints(e[a],b,c,d,h),d=d+h.offset;g.push(h.path)}return{paths:g,offset:d/2}},extractGlyphPoints:function(a,b,c,d,e){var f=[],g,h,i,j,l,m,n,p,o,s,t,r=b.glyphs[a]||b.glyphs["?"];if(r){if(r.o){b=r._cachedOutline||(r._cachedOutline=r.o.split(" "));j=b.length;for(a=0;a<j;)switch(i=b[a++],i){case "m":i=b[a++]*c+d;l=b[a++]*c;e.moveTo(i,l);break;case "l":i=b[a++]*c+d;l=b[a++]*c;e.lineTo(i,l);break;case "q":i=b[a++]*
+c+d;l=b[a++]*c;p=b[a++]*c+d;o=b[a++]*c;e.quadraticCurveTo(p,o,i,l);if(g=f[f.length-1]){m=g.x;n=g.y;g=1;for(h=this.divisions;g<=h;g++){var z=g/h;THREE.Shape.Utils.b2(z,m,p,i);THREE.Shape.Utils.b2(z,n,o,l)}}break;case "b":if(i=b[a++]*c+d,l=b[a++]*c,p=b[a++]*c+d,o=b[a++]*-c,s=b[a++]*c+d,t=b[a++]*-c,e.bezierCurveTo(i,l,p,o,s,t),g=f[f.length-1]){m=g.x;n=g.y;g=1;for(h=this.divisions;g<=h;g++)z=g/h,THREE.Shape.Utils.b3(z,m,p,s,i),THREE.Shape.Utils.b3(z,n,o,t,l)}}}return{offset:r.ha*c,path:e}}}};
+THREE.FontUtils.generateShapes=function(a,b){var b=b||{},c=void 0!==b.curveSegments?b.curveSegments:4,d=void 0!==b.font?b.font:"helvetiker",e=void 0!==b.weight?b.weight:"normal",f=void 0!==b.style?b.style:"normal";THREE.FontUtils.size=void 0!==b.size?b.size:100;THREE.FontUtils.divisions=c;THREE.FontUtils.face=d;THREE.FontUtils.weight=e;THREE.FontUtils.style=f;c=THREE.FontUtils.drawText(a).paths;d=[];e=0;for(f=c.length;e<f;e++)Array.prototype.push.apply(d,c[e].toShapes());return d};
+(function(a){var b=function(a){for(var b=a.length,e=0,f=b-1,g=0;g<b;f=g++)e+=a[f].x*a[g].y-a[g].x*a[f].y;return 0.5*e};a.Triangulate=function(a,d){var e=a.length;if(3>e)return null;var f=[],g=[],h=[],i,j,l;if(0<b(a))for(j=0;j<e;j++)g[j]=j;else for(j=0;j<e;j++)g[j]=e-1-j;var m=2*e;for(j=e-1;2<e;){if(0>=m--){console.log("Warning, unable to triangulate polygon!");break}i=j;e<=i&&(i=0);j=i+1;e<=j&&(j=0);l=j+1;e<=l&&(l=0);var n;a:{n=a;var p=i,o=j,s=l,t=e,r=g,z=void 0,w=void 0,q=void 0,E=void 0,A=void 0,
+v=void 0,u=void 0,D=void 0,C=void 0,w=n[r[p]].x,q=n[r[p]].y,E=n[r[o]].x,A=n[r[o]].y,v=n[r[s]].x,u=n[r[s]].y;if(1E-10>(E-w)*(u-q)-(A-q)*(v-w))n=!1;else{for(z=0;z<t;z++)if(!(z==p||z==o||z==s)){var D=n[r[z]].x,C=n[r[z]].y,G=void 0,P=void 0,B=void 0,K=void 0,H=void 0,I=void 0,N=void 0,O=void 0,R=void 0,ga=void 0,M=void 0,J=void 0,G=B=H=void 0,G=v-E,P=u-A,B=w-v,K=q-u,H=E-w,I=A-q,N=D-w,O=C-q,R=D-E,ga=C-A,M=D-v,J=C-u,G=G*ga-P*R,H=H*O-I*N,B=B*J-K*M;if(0<=G&&0<=B&&0<=H){n=!1;break a}}n=!0}}if(n){f.push([a[g[i]],
+a[g[j]],a[g[l]]]);h.push([g[i],g[j],g[l]]);i=j;for(l=j+1;l<e;i++,l++)g[i]=g[l];e--;m=2*e}}return d?h:f};a.Triangulate.area=b;return a})(THREE.FontUtils);self._typeface_js={faces:THREE.FontUtils.faces,loadFace:THREE.FontUtils.loadFace};THREE.Curve=function(){};THREE.Curve.prototype.getPoint=function(){console.log("Warning, getPoint() not implemented!");return null};THREE.Curve.prototype.getPointAt=function(a){a=this.getUtoTmapping(a);return this.getPoint(a)};
+THREE.Curve.prototype.getPoints=function(a){a||(a=5);var b,c=[];for(b=0;b<=a;b++)c.push(this.getPoint(b/a));return c};THREE.Curve.prototype.getSpacedPoints=function(a){a||(a=5);var b,c=[];for(b=0;b<=a;b++)c.push(this.getPointAt(b/a));return c};THREE.Curve.prototype.getLength=function(){var a=this.getLengths();return a[a.length-1]};
+THREE.Curve.prototype.getLengths=function(a){a||(a=this.__arcLengthDivisions?this.__arcLengthDivisions:200);if(this.cacheArcLengths&&this.cacheArcLengths.length==a+1&&!this.needsUpdate)return this.cacheArcLengths;this.needsUpdate=!1;var b=[],c,d=this.getPoint(0),e,f=0;b.push(0);for(e=1;e<=a;e++)c=this.getPoint(e/a),f+=c.distanceTo(d),b.push(f),d=c;return this.cacheArcLengths=b};THREE.Curve.prototype.updateArcLengths=function(){this.needsUpdate=!0;this.getLengths()};
+THREE.Curve.prototype.getUtoTmapping=function(a,b){var c=this.getLengths(),d=0,e=c.length,f;f=b?b:a*c[e-1];for(var g=0,h=e-1,i;g<=h;)if(d=Math.floor(g+(h-g)/2),i=c[d]-f,0>i)g=d+1;else if(0<i)h=d-1;else{h=d;break}d=h;if(c[d]==f)return d/(e-1);g=c[d];return c=(d+(f-g)/(c[d+1]-g))/(e-1)};THREE.Curve.prototype.getNormalVector=function(a){a=this.getTangent(a);return new THREE.Vector2(-a.y,a.x)};
+THREE.Curve.prototype.getTangent=function(a){var b=a-1E-4,a=a+1E-4;0>b&&(b=0);1<a&&(a=1);b=this.getPoint(b);return this.getPoint(a).clone().subSelf(b).normalize()};THREE.Curve.prototype.getTangentAt=function(a){a=this.getUtoTmapping(a);return this.getTangent(a)};THREE.LineCurve=function(a,b){this.v1=a;this.v2=b};THREE.LineCurve.prototype=Object.create(THREE.Curve.prototype);THREE.LineCurve.prototype.getPoint=function(a){var b=this.v2.clone().subSelf(this.v1);b.multiplyScalar(a).addSelf(this.v1);return b};
+THREE.LineCurve.prototype.getPointAt=function(a){return this.getPoint(a)};THREE.LineCurve.prototype.getTangent=function(){return this.v2.clone().subSelf(this.v1).normalize()};THREE.QuadraticBezierCurve=function(a,b,c){this.v0=a;this.v1=b;this.v2=c};THREE.QuadraticBezierCurve.prototype=Object.create(THREE.Curve.prototype);
+THREE.QuadraticBezierCurve.prototype.getPoint=function(a){var b;b=THREE.Shape.Utils.b2(a,this.v0.x,this.v1.x,this.v2.x);a=THREE.Shape.Utils.b2(a,this.v0.y,this.v1.y,this.v2.y);return new THREE.Vector2(b,a)};THREE.QuadraticBezierCurve.prototype.getTangent=function(a){var b;b=THREE.Curve.Utils.tangentQuadraticBezier(a,this.v0.x,this.v1.x,this.v2.x);a=THREE.Curve.Utils.tangentQuadraticBezier(a,this.v0.y,this.v1.y,this.v2.y);b=new THREE.Vector2(b,a);b.normalize();return b};
+THREE.CubicBezierCurve=function(a,b,c,d){this.v0=a;this.v1=b;this.v2=c;this.v3=d};THREE.CubicBezierCurve.prototype=Object.create(THREE.Curve.prototype);THREE.CubicBezierCurve.prototype.getPoint=function(a){var b;b=THREE.Shape.Utils.b3(a,this.v0.x,this.v1.x,this.v2.x,this.v3.x);a=THREE.Shape.Utils.b3(a,this.v0.y,this.v1.y,this.v2.y,this.v3.y);return new THREE.Vector2(b,a)};
+THREE.CubicBezierCurve.prototype.getTangent=function(a){var b;b=THREE.Curve.Utils.tangentCubicBezier(a,this.v0.x,this.v1.x,this.v2.x,this.v3.x);a=THREE.Curve.Utils.tangentCubicBezier(a,this.v0.y,this.v1.y,this.v2.y,this.v3.y);b=new THREE.Vector2(b,a);b.normalize();return b};THREE.SplineCurve=function(a){this.points=void 0==a?[]:a};THREE.SplineCurve.prototype=Object.create(THREE.Curve.prototype);
+THREE.SplineCurve.prototype.getPoint=function(a){var b=new THREE.Vector2,c=[],d=this.points,e;e=(d.length-1)*a;a=Math.floor(e);e-=a;c[0]=0==a?a:a-1;c[1]=a;c[2]=a>d.length-2?d.length-1:a+1;c[3]=a>d.length-3?d.length-1:a+2;b.x=THREE.Curve.Utils.interpolate(d[c[0]].x,d[c[1]].x,d[c[2]].x,d[c[3]].x,e);b.y=THREE.Curve.Utils.interpolate(d[c[0]].y,d[c[1]].y,d[c[2]].y,d[c[3]].y,e);return b};
+THREE.EllipseCurve=function(a,b,c,d,e,f,g){this.aX=a;this.aY=b;this.xRadius=c;this.yRadius=d;this.aStartAngle=e;this.aEndAngle=f;this.aClockwise=g};THREE.EllipseCurve.prototype=Object.create(THREE.Curve.prototype);THREE.EllipseCurve.prototype.getPoint=function(a){var b=this.aEndAngle-this.aStartAngle;this.aClockwise||(a=1-a);b=this.aStartAngle+a*b;a=this.aX+this.xRadius*Math.cos(b);b=this.aY+this.yRadius*Math.sin(b);return new THREE.Vector2(a,b)};
+THREE.ArcCurve=function(a,b,c,d,e,f){THREE.EllipseCurve.call(this,a,b,c,c,d,e,f)};THREE.ArcCurve.prototype=Object.create(THREE.EllipseCurve.prototype);
+THREE.Curve.Utils={tangentQuadraticBezier:function(a,b,c,d){return 2*(1-a)*(c-b)+2*a*(d-c)},tangentCubicBezier:function(a,b,c,d,e){return-3*b*(1-a)*(1-a)+3*c*(1-a)*(1-a)-6*a*c*(1-a)+6*a*d*(1-a)-3*a*a*d+3*a*a*e},tangentSpline:function(a){return 6*a*a-6*a+(3*a*a-4*a+1)+(-6*a*a+6*a)+(3*a*a-2*a)},interpolate:function(a,b,c,d,e){var a=0.5*(c-a),d=0.5*(d-b),f=e*e;return(2*b-2*c+a+d)*e*f+(-3*b+3*c-2*a-d)*f+a*e+b}};
+THREE.Curve.create=function(a,b){a.prototype=Object.create(THREE.Curve.prototype);a.prototype.getPoint=b;return a};THREE.LineCurve3=THREE.Curve.create(function(a,b){this.v1=a;this.v2=b},function(a){var b=new THREE.Vector3;b.sub(this.v2,this.v1);b.multiplyScalar(a);b.addSelf(this.v1);return b});
+THREE.QuadraticBezierCurve3=THREE.Curve.create(function(a,b,c){this.v0=a;this.v1=b;this.v2=c},function(a){var b,c;b=THREE.Shape.Utils.b2(a,this.v0.x,this.v1.x,this.v2.x);c=THREE.Shape.Utils.b2(a,this.v0.y,this.v1.y,this.v2.y);a=THREE.Shape.Utils.b2(a,this.v0.z,this.v1.z,this.v2.z);return new THREE.Vector3(b,c,a)});
+THREE.CubicBezierCurve3=THREE.Curve.create(function(a,b,c,d){this.v0=a;this.v1=b;this.v2=c;this.v3=d},function(a){var b,c;b=THREE.Shape.Utils.b3(a,this.v0.x,this.v1.x,this.v2.x,this.v3.x);c=THREE.Shape.Utils.b3(a,this.v0.y,this.v1.y,this.v2.y,this.v3.y);a=THREE.Shape.Utils.b3(a,this.v0.z,this.v1.z,this.v2.z,this.v3.z);return new THREE.Vector3(b,c,a)});
+THREE.SplineCurve3=THREE.Curve.create(function(a){this.points=void 0==a?[]:a},function(a){var b=new THREE.Vector3,c=[],d=this.points,e,a=(d.length-1)*a;e=Math.floor(a);a-=e;c[0]=0==e?e:e-1;c[1]=e;c[2]=e>d.length-2?d.length-1:e+1;c[3]=e>d.length-3?d.length-1:e+2;e=d[c[0]];var f=d[c[1]],g=d[c[2]],c=d[c[3]];b.x=THREE.Curve.Utils.interpolate(e.x,f.x,g.x,c.x,a);b.y=THREE.Curve.Utils.interpolate(e.y,f.y,g.y,c.y,a);b.z=THREE.Curve.Utils.interpolate(e.z,f.z,g.z,c.z,a);return b});
+THREE.ClosedSplineCurve3=THREE.Curve.create(function(a){this.points=void 0==a?[]:a},function(a){var b=new THREE.Vector3,c=[],d=this.points,e;e=(d.length-0)*a;a=Math.floor(e);e-=a;a+=0<a?0:(Math.floor(Math.abs(a)/d.length)+1)*d.length;c[0]=(a-1)%d.length;c[1]=a%d.length;c[2]=(a+1)%d.length;c[3]=(a+2)%d.length;b.x=THREE.Curve.Utils.interpolate(d[c[0]].x,d[c[1]].x,d[c[2]].x,d[c[3]].x,e);b.y=THREE.Curve.Utils.interpolate(d[c[0]].y,d[c[1]].y,d[c[2]].y,d[c[3]].y,e);b.z=THREE.Curve.Utils.interpolate(d[c[0]].z,
+d[c[1]].z,d[c[2]].z,d[c[3]].z,e);return b});THREE.CurvePath=function(){this.curves=[];this.bends=[];this.autoClose=!1};THREE.CurvePath.prototype=Object.create(THREE.Curve.prototype);THREE.CurvePath.prototype.add=function(a){this.curves.push(a)};THREE.CurvePath.prototype.checkConnection=function(){};THREE.CurvePath.prototype.closePath=function(){var a=this.curves[0].getPoint(0),b=this.curves[this.curves.length-1].getPoint(1);a.equals(b)||this.curves.push(new THREE.LineCurve(b,a))};
+THREE.CurvePath.prototype.getPoint=function(a){for(var b=a*this.getLength(),c=this.getCurveLengths(),a=0;a<c.length;){if(c[a]>=b)return b=c[a]-b,a=this.curves[a],b=1-b/a.getLength(),a.getPointAt(b);a++}return null};THREE.CurvePath.prototype.getLength=function(){var a=this.getCurveLengths();return a[a.length-1]};
+THREE.CurvePath.prototype.getCurveLengths=function(){if(this.cacheLengths&&this.cacheLengths.length==this.curves.length)return this.cacheLengths;var a=[],b=0,c,d=this.curves.length;for(c=0;c<d;c++)b+=this.curves[c].getLength(),a.push(b);return this.cacheLengths=a};
+THREE.CurvePath.prototype.getBoundingBox=function(){var a=this.getPoints(),b,c,d,e,f,g;b=c=Number.NEGATIVE_INFINITY;e=f=Number.POSITIVE_INFINITY;var h,i,j,l,m=a[0]instanceof THREE.Vector3;l=m?new THREE.Vector3:new THREE.Vector2;i=0;for(j=a.length;i<j;i++)h=a[i],h.x>b?b=h.x:h.x<e&&(e=h.x),h.y>c?c=h.y:h.y<f&&(f=h.y),m&&(h.z>d?d=h.z:h.z<g&&(g=h.z)),l.addSelf(h);a={minX:e,minY:f,maxX:b,maxY:c,centroid:l.divideScalar(j)};m&&(a.maxZ=d,a.minZ=g);return a};
+THREE.CurvePath.prototype.createPointsGeometry=function(a){a=this.getPoints(a,!0);return this.createGeometry(a)};THREE.CurvePath.prototype.createSpacedPointsGeometry=function(a){a=this.getSpacedPoints(a,!0);return this.createGeometry(a)};THREE.CurvePath.prototype.createGeometry=function(a){for(var b=new THREE.Geometry,c=0;c<a.length;c++)b.vertices.push(new THREE.Vector3(a[c].x,a[c].y,a[c].z||0));return b};THREE.CurvePath.prototype.addWrapPath=function(a){this.bends.push(a)};
+THREE.CurvePath.prototype.getTransformedPoints=function(a,b){var c=this.getPoints(a),d,e;b||(b=this.bends);d=0;for(e=b.length;d<e;d++)c=this.getWrapPoints(c,b[d]);return c};THREE.CurvePath.prototype.getTransformedSpacedPoints=function(a,b){var c=this.getSpacedPoints(a),d,e;b||(b=this.bends);d=0;for(e=b.length;d<e;d++)c=this.getWrapPoints(c,b[d]);return c};
+THREE.CurvePath.prototype.getWrapPoints=function(a,b){var c=this.getBoundingBox(),d,e,f,g,h,i;d=0;for(e=a.length;d<e;d++)f=a[d],g=f.x,h=f.y,i=g/c.maxX,i=b.getUtoTmapping(i,g),g=b.getPoint(i),h=b.getNormalVector(i).multiplyScalar(h),f.x=g.x+h.x,f.y=g.y+h.y;return a};THREE.Gyroscope=function(){THREE.Object3D.call(this)};THREE.Gyroscope.prototype=Object.create(THREE.Object3D.prototype);
+THREE.Gyroscope.prototype.updateMatrixWorld=function(a){this.matrixAutoUpdate&&this.updateMatrix();if(this.matrixWorldNeedsUpdate||a)this.parent?(this.matrixWorld.multiply(this.parent.matrixWorld,this.matrix),this.matrixWorld.decompose(this.translationWorld,this.rotationWorld,this.scaleWorld),this.matrix.decompose(this.translationObject,this.rotationObject,this.scaleObject),this.matrixWorld.compose(this.translationWorld,this.rotationObject,this.scaleWorld)):this.matrixWorld.copy(this.matrix),this.matrixWorldNeedsUpdate=
+!1,a=!0;for(var b=0,c=this.children.length;b<c;b++)this.children[b].updateMatrixWorld(a)};THREE.Gyroscope.prototype.translationWorld=new THREE.Vector3;THREE.Gyroscope.prototype.translationObject=new THREE.Vector3;THREE.Gyroscope.prototype.rotationWorld=new THREE.Quaternion;THREE.Gyroscope.prototype.rotationObject=new THREE.Quaternion;THREE.Gyroscope.prototype.scaleWorld=new THREE.Vector3;THREE.Gyroscope.prototype.scaleObject=new THREE.Vector3;
+THREE.Path=function(a){THREE.CurvePath.call(this);this.actions=[];a&&this.fromPoints(a)};THREE.Path.prototype=Object.create(THREE.CurvePath.prototype);THREE.PathActions={MOVE_TO:"moveTo",LINE_TO:"lineTo",QUADRATIC_CURVE_TO:"quadraticCurveTo",BEZIER_CURVE_TO:"bezierCurveTo",CSPLINE_THRU:"splineThru",ARC:"arc",ELLIPSE:"ellipse"};THREE.Path.prototype.fromPoints=function(a){this.moveTo(a[0].x,a[0].y);for(var b=1,c=a.length;b<c;b++)this.lineTo(a[b].x,a[b].y)};
+THREE.Path.prototype.moveTo=function(a,b){var c=Array.prototype.slice.call(arguments);this.actions.push({action:THREE.PathActions.MOVE_TO,args:c})};THREE.Path.prototype.lineTo=function(a,b){var c=Array.prototype.slice.call(arguments),d=this.actions[this.actions.length-1].args,d=new THREE.LineCurve(new THREE.Vector2(d[d.length-2],d[d.length-1]),new THREE.Vector2(a,b));this.curves.push(d);this.actions.push({action:THREE.PathActions.LINE_TO,args:c})};
+THREE.Path.prototype.quadraticCurveTo=function(a,b,c,d){var e=Array.prototype.slice.call(arguments),f=this.actions[this.actions.length-1].args,f=new THREE.QuadraticBezierCurve(new THREE.Vector2(f[f.length-2],f[f.length-1]),new THREE.Vector2(a,b),new THREE.Vector2(c,d));this.curves.push(f);this.actions.push({action:THREE.PathActions.QUADRATIC_CURVE_TO,args:e})};
+THREE.Path.prototype.bezierCurveTo=function(a,b,c,d,e,f){var g=Array.prototype.slice.call(arguments),h=this.actions[this.actions.length-1].args,h=new THREE.CubicBezierCurve(new THREE.Vector2(h[h.length-2],h[h.length-1]),new THREE.Vector2(a,b),new THREE.Vector2(c,d),new THREE.Vector2(e,f));this.curves.push(h);this.actions.push({action:THREE.PathActions.BEZIER_CURVE_TO,args:g})};
+THREE.Path.prototype.splineThru=function(a){var b=Array.prototype.slice.call(arguments),c=this.actions[this.actions.length-1].args,c=[new THREE.Vector2(c[c.length-2],c[c.length-1])];Array.prototype.push.apply(c,a);c=new THREE.SplineCurve(c);this.curves.push(c);this.actions.push({action:THREE.PathActions.CSPLINE_THRU,args:b})};THREE.Path.prototype.arc=function(a,b,c,d,e,f){var g=this.actions[this.actions.length-1].args;this.absarc(a+g[g.length-2],b+g[g.length-1],c,d,e,f)};
+THREE.Path.prototype.absarc=function(a,b,c,d,e,f){this.absellipse(a,b,c,c,d,e,f)};THREE.Path.prototype.ellipse=function(a,b,c,d,e,f,g){var h=this.actions[this.actions.length-1].args;this.absellipse(a+h[h.length-2],b+h[h.length-1],c,d,e,f,g)};THREE.Path.prototype.absellipse=function(a,b,c,d,e,f,g){var h=Array.prototype.slice.call(arguments),i=new THREE.EllipseCurve(a,b,c,d,e,f,g);this.curves.push(i);i=i.getPoint(g?1:0);h.push(i.x);h.push(i.y);this.actions.push({action:THREE.PathActions.ELLIPSE,args:h})};
+THREE.Path.prototype.getSpacedPoints=function(a){a||(a=40);for(var b=[],c=0;c<a;c++)b.push(this.getPoint(c/a));return b};
+THREE.Path.prototype.getPoints=function(a,b){if(this.useSpacedPoints)return console.log("tata"),this.getSpacedPoints(a,b);var a=a||12,c=[],d,e,f,g,h,i,j,l,m,n,p,o,s;d=0;for(e=this.actions.length;d<e;d++)switch(f=this.actions[d],g=f.action,f=f.args,g){case THREE.PathActions.MOVE_TO:c.push(new THREE.Vector2(f[0],f[1]));break;case THREE.PathActions.LINE_TO:c.push(new THREE.Vector2(f[0],f[1]));break;case THREE.PathActions.QUADRATIC_CURVE_TO:h=f[2];i=f[3];m=f[0];n=f[1];0<c.length?(g=c[c.length-1],p=g.x,
+o=g.y):(g=this.actions[d-1].args,p=g[g.length-2],o=g[g.length-1]);for(f=1;f<=a;f++)s=f/a,g=THREE.Shape.Utils.b2(s,p,m,h),s=THREE.Shape.Utils.b2(s,o,n,i),c.push(new THREE.Vector2(g,s));break;case THREE.PathActions.BEZIER_CURVE_TO:h=f[4];i=f[5];m=f[0];n=f[1];j=f[2];l=f[3];0<c.length?(g=c[c.length-1],p=g.x,o=g.y):(g=this.actions[d-1].args,p=g[g.length-2],o=g[g.length-1]);for(f=1;f<=a;f++)s=f/a,g=THREE.Shape.Utils.b3(s,p,m,j,h),s=THREE.Shape.Utils.b3(s,o,n,l,i),c.push(new THREE.Vector2(g,s));break;case THREE.PathActions.CSPLINE_THRU:g=
+this.actions[d-1].args;s=[new THREE.Vector2(g[g.length-2],g[g.length-1])];g=a*f[0].length;s=s.concat(f[0]);s=new THREE.SplineCurve(s);for(f=1;f<=g;f++)c.push(s.getPointAt(f/g));break;case THREE.PathActions.ARC:h=f[0];i=f[1];n=f[2];j=f[3];g=f[4];m=!!f[5];p=g-j;o=2*a;for(f=1;f<=o;f++)s=f/o,m||(s=1-s),s=j+s*p,g=h+n*Math.cos(s),s=i+n*Math.sin(s),c.push(new THREE.Vector2(g,s));break;case THREE.PathActions.ELLIPSE:h=f[0];i=f[1];n=f[2];l=f[3];j=f[4];g=f[5];m=!!f[6];p=g-j;o=2*a;for(f=1;f<=o;f++)s=f/o,m||
+(s=1-s),s=j+s*p,g=h+n*Math.cos(s),s=i+l*Math.sin(s),c.push(new THREE.Vector2(g,s))}d=c[c.length-1];1E-10>Math.abs(d.x-c[0].x)&&1E-10>Math.abs(d.y-c[0].y)&&c.splice(c.length-1,1);b&&c.push(c[0]);return c};
+THREE.Path.prototype.toShapes=function(){var a,b,c,d,e=[],f=new THREE.Path;a=0;for(b=this.actions.length;a<b;a++)c=this.actions[a],d=c.args,c=c.action,c==THREE.PathActions.MOVE_TO&&0!=f.actions.length&&(e.push(f),f=new THREE.Path),f[c].apply(f,d);0!=f.actions.length&&e.push(f);if(0==e.length)return[];var g;d=[];a=!THREE.Shape.Utils.isClockWise(e[0].getPoints());if(1==e.length)return f=e[0],g=new THREE.Shape,g.actions=f.actions,g.curves=f.curves,d.push(g),d;if(a){g=new THREE.Shape;a=0;for(b=e.length;a<
+b;a++)f=e[a],THREE.Shape.Utils.isClockWise(f.getPoints())?(g.actions=f.actions,g.curves=f.curves,d.push(g),g=new THREE.Shape):g.holes.push(f)}else{a=0;for(b=e.length;a<b;a++)f=e[a],THREE.Shape.Utils.isClockWise(f.getPoints())?(g&&d.push(g),g=new THREE.Shape,g.actions=f.actions,g.curves=f.curves):g.holes.push(f);d.push(g)}return d};THREE.Shape=function(){THREE.Path.apply(this,arguments);this.holes=[]};THREE.Shape.prototype=Object.create(THREE.Path.prototype);
+THREE.Shape.prototype.extrude=function(a){return new THREE.ExtrudeGeometry(this,a)};THREE.Shape.prototype.makeGeometry=function(a){return new THREE.ShapeGeometry(this,a)};THREE.Shape.prototype.getPointsHoles=function(a){var b,c=this.holes.length,d=[];for(b=0;b<c;b++)d[b]=this.holes[b].getTransformedPoints(a,this.bends);return d};THREE.Shape.prototype.getSpacedPointsHoles=function(a){var b,c=this.holes.length,d=[];for(b=0;b<c;b++)d[b]=this.holes[b].getTransformedSpacedPoints(a,this.bends);return d};
+THREE.Shape.prototype.extractAllPoints=function(a){return{shape:this.getTransformedPoints(a),holes:this.getPointsHoles(a)}};THREE.Shape.prototype.extractPoints=function(a){return this.useSpacedPoints?this.extractAllSpacedPoints(a):this.extractAllPoints(a)};THREE.Shape.prototype.extractAllSpacedPoints=function(a){return{shape:this.getTransformedSpacedPoints(a),holes:this.getSpacedPointsHoles(a)}};
+THREE.Shape.Utils={removeHoles:function(a,b){var c=a.concat(),d=c.concat(),e,f,g,h,i,j,l,m,n,p,o=[];for(i=0;i<b.length;i++){j=b[i];Array.prototype.push.apply(d,j);f=Number.POSITIVE_INFINITY;for(e=0;e<j.length;e++){n=j[e];p=[];for(m=0;m<c.length;m++)l=c[m],l=n.distanceToSquared(l),p.push(l),l<f&&(f=l,g=e,h=m)}e=0<=h-1?h-1:c.length-1;f=0<=g-1?g-1:j.length-1;var s=[j[g],c[h],c[e]];m=THREE.FontUtils.Triangulate.area(s);var t=[j[g],j[f],c[h]];n=THREE.FontUtils.Triangulate.area(t);p=h;l=g;h+=1;g+=-1;0>
+h&&(h+=c.length);h%=c.length;0>g&&(g+=j.length);g%=j.length;e=0<=h-1?h-1:c.length-1;f=0<=g-1?g-1:j.length-1;s=[j[g],c[h],c[e]];s=THREE.FontUtils.Triangulate.area(s);t=[j[g],j[f],c[h]];t=THREE.FontUtils.Triangulate.area(t);m+n>s+t&&(h=p,g=l,0>h&&(h+=c.length),h%=c.length,0>g&&(g+=j.length),g%=j.length,e=0<=h-1?h-1:c.length-1,f=0<=g-1?g-1:j.length-1);m=c.slice(0,h);n=c.slice(h);p=j.slice(g);l=j.slice(0,g);f=[j[g],j[f],c[h]];o.push([j[g],c[h],c[e]]);o.push(f);c=m.concat(p).concat(l).concat(n)}return{shape:c,
+isolatedPts:o,allpoints:d}},triangulateShape:function(a,b){var c=THREE.Shape.Utils.removeHoles(a,b),d=c.allpoints,e=c.isolatedPts,c=THREE.FontUtils.Triangulate(c.shape,!1),f,g,h,i,j={};f=0;for(g=d.length;f<g;f++)i=d[f].x+":"+d[f].y,void 0!==j[i]&&console.log("Duplicate point",i),j[i]=f;f=0;for(g=c.length;f<g;f++){h=c[f];for(d=0;3>d;d++)i=h[d].x+":"+h[d].y,i=j[i],void 0!==i&&(h[d]=i)}f=0;for(g=e.length;f<g;f++){h=e[f];for(d=0;3>d;d++)i=h[d].x+":"+h[d].y,i=j[i],void 0!==i&&(h[d]=i)}return c.concat(e)},
+isClockWise:function(a){return 0>THREE.FontUtils.Triangulate.area(a)},b2p0:function(a,b){var c=1-a;return c*c*b},b2p1:function(a,b){return 2*(1-a)*a*b},b2p2:function(a,b){return a*a*b},b2:function(a,b,c,d){return this.b2p0(a,b)+this.b2p1(a,c)+this.b2p2(a,d)},b3p0:function(a,b){var c=1-a;return c*c*c*b},b3p1:function(a,b){var c=1-a;return 3*c*c*a*b},b3p2:function(a,b){return 3*(1-a)*a*a*b},b3p3:function(a,b){return a*a*a*b},b3:function(a,b,c,d,e){return this.b3p0(a,b)+this.b3p1(a,c)+this.b3p2(a,d)+
+this.b3p3(a,e)}};
+THREE.AnimationHandler=function(){var a=[],b={},c={update:function(b){for(var c=0;c<a.length;c++)a[c].update(b)},addToUpdate:function(b){-1===a.indexOf(b)&&a.push(b)},removeFromUpdate:function(b){b=a.indexOf(b);-1!==b&&a.splice(b,1)},add:function(a){void 0!==b[a.name]&&console.log("THREE.AnimationHandler.add: Warning! "+a.name+" already exists in library. Overwriting.");b[a.name]=a;if(!0!==a.initialized){for(var c=0;c<a.hierarchy.length;c++){for(var d=0;d<a.hierarchy[c].keys.length;d++)if(0>a.hierarchy[c].keys[d].time&&
+(a.hierarchy[c].keys[d].time=0),void 0!==a.hierarchy[c].keys[d].rot&&!(a.hierarchy[c].keys[d].rot instanceof THREE.Quaternion)){var h=a.hierarchy[c].keys[d].rot;a.hierarchy[c].keys[d].rot=new THREE.Quaternion(h[0],h[1],h[2],h[3])}if(a.hierarchy[c].keys.length&&void 0!==a.hierarchy[c].keys[0].morphTargets){h={};for(d=0;d<a.hierarchy[c].keys.length;d++)for(var i=0;i<a.hierarchy[c].keys[d].morphTargets.length;i++){var j=a.hierarchy[c].keys[d].morphTargets[i];h[j]=-1}a.hierarchy[c].usedMorphTargets=h;
+for(d=0;d<a.hierarchy[c].keys.length;d++){var l={};for(j in h){for(i=0;i<a.hierarchy[c].keys[d].morphTargets.length;i++)if(a.hierarchy[c].keys[d].morphTargets[i]===j){l[j]=a.hierarchy[c].keys[d].morphTargetsInfluences[i];break}i===a.hierarchy[c].keys[d].morphTargets.length&&(l[j]=0)}a.hierarchy[c].keys[d].morphTargetsInfluences=l}}for(d=1;d<a.hierarchy[c].keys.length;d++)a.hierarchy[c].keys[d].time===a.hierarchy[c].keys[d-1].time&&(a.hierarchy[c].keys.splice(d,1),d--);for(d=0;d<a.hierarchy[c].keys.length;d++)a.hierarchy[c].keys[d].index=
+d}d=parseInt(a.length*a.fps,10);a.JIT={};a.JIT.hierarchy=[];for(c=0;c<a.hierarchy.length;c++)a.JIT.hierarchy.push(Array(d));a.initialized=!0}},get:function(a){if("string"===typeof a){if(b[a])return b[a];console.log("THREE.AnimationHandler.get: Couldn't find animation "+a);return null}},parse:function(a){var b=[];if(a instanceof THREE.SkinnedMesh)for(var c=0;c<a.bones.length;c++)b.push(a.bones[c]);else d(a,b);return b}},d=function(a,b){b.push(a);for(var c=0;c<a.children.length;c++)d(a.children[c],
+b)};c.LINEAR=0;c.CATMULLROM=1;c.CATMULLROM_FORWARD=2;return c}();THREE.Animation=function(a,b,c){this.root=a;this.data=THREE.AnimationHandler.get(b);this.hierarchy=THREE.AnimationHandler.parse(a);this.currentTime=0;this.timeScale=1;this.isPlaying=!1;this.loop=this.isPaused=!0;this.interpolationType=void 0!==c?c:THREE.AnimationHandler.LINEAR;this.points=[];this.target=new THREE.Vector3};
+THREE.Animation.prototype.play=function(a,b){if(!1===this.isPlaying){this.isPlaying=!0;this.loop=void 0!==a?a:!0;this.currentTime=void 0!==b?b:0;var c,d=this.hierarchy.length,e;for(c=0;c<d;c++){e=this.hierarchy[c];this.interpolationType!==THREE.AnimationHandler.CATMULLROM_FORWARD&&(e.useQuaternion=!0);e.matrixAutoUpdate=!0;void 0===e.animationCache&&(e.animationCache={},e.animationCache.prevKey={pos:0,rot:0,scl:0},e.animationCache.nextKey={pos:0,rot:0,scl:0},e.animationCache.originalMatrix=e instanceof
+THREE.Bone?e.skinMatrix:e.matrix);var f=e.animationCache.prevKey;e=e.animationCache.nextKey;f.pos=this.data.hierarchy[c].keys[0];f.rot=this.data.hierarchy[c].keys[0];f.scl=this.data.hierarchy[c].keys[0];e.pos=this.getNextKeyWith("pos",c,1);e.rot=this.getNextKeyWith("rot",c,1);e.scl=this.getNextKeyWith("scl",c,1)}this.update(0)}this.isPaused=!1;THREE.AnimationHandler.addToUpdate(this)};
+THREE.Animation.prototype.pause=function(){!0===this.isPaused?THREE.AnimationHandler.addToUpdate(this):THREE.AnimationHandler.removeFromUpdate(this);this.isPaused=!this.isPaused};THREE.Animation.prototype.stop=function(){this.isPaused=this.isPlaying=!1;THREE.AnimationHandler.removeFromUpdate(this)};
+THREE.Animation.prototype.update=function(a){if(!1!==this.isPlaying){var b=["pos","rot","scl"],c,d,e,f,g,h,i,j,l;l=this.currentTime+=a*this.timeScale;j=this.currentTime%=this.data.length;parseInt(Math.min(j*this.data.fps,this.data.length*this.data.fps),10);for(var m=0,n=this.hierarchy.length;m<n;m++){a=this.hierarchy[m];i=a.animationCache;for(var p=0;3>p;p++){c=b[p];g=i.prevKey[c];h=i.nextKey[c];if(h.time<=l){if(j<l)if(this.loop){g=this.data.hierarchy[m].keys[0];for(h=this.getNextKeyWith(c,m,1);h.time<
+j;)g=h,h=this.getNextKeyWith(c,m,h.index+1)}else{this.stop();return}else{do g=h,h=this.getNextKeyWith(c,m,h.index+1);while(h.time<j)}i.prevKey[c]=g;i.nextKey[c]=h}a.matrixAutoUpdate=!0;a.matrixWorldNeedsUpdate=!0;d=(j-g.time)/(h.time-g.time);e=g[c];f=h[c];if(0>d||1<d)console.log("THREE.Animation.update: Warning! Scale out of bounds:"+d+" on bone "+m),d=0>d?0:1;if("pos"===c)if(c=a.position,this.interpolationType===THREE.AnimationHandler.LINEAR)c.x=e[0]+(f[0]-e[0])*d,c.y=e[1]+(f[1]-e[1])*d,c.z=e[2]+
+(f[2]-e[2])*d;else{if(this.interpolationType===THREE.AnimationHandler.CATMULLROM||this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD)this.points[0]=this.getPrevKeyWith("pos",m,g.index-1).pos,this.points[1]=e,this.points[2]=f,this.points[3]=this.getNextKeyWith("pos",m,h.index+1).pos,d=0.33*d+0.33,e=this.interpolateCatmullRom(this.points,d),c.x=e[0],c.y=e[1],c.z=e[2],this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD&&(d=this.interpolateCatmullRom(this.points,1.01*d),
+this.target.set(d[0],d[1],d[2]),this.target.subSelf(c),this.target.y=0,this.target.normalize(),d=Math.atan2(this.target.x,this.target.z),a.rotation.set(0,d,0))}else"rot"===c?THREE.Quaternion.slerp(e,f,a.quaternion,d):"scl"===c&&(c=a.scale,c.x=e[0]+(f[0]-e[0])*d,c.y=e[1]+(f[1]-e[1])*d,c.z=e[2]+(f[2]-e[2])*d)}}}};
+THREE.Animation.prototype.interpolateCatmullRom=function(a,b){var c=[],d=[],e,f,g,h,i,j;e=(a.length-1)*b;f=Math.floor(e);e-=f;c[0]=0===f?f:f-1;c[1]=f;c[2]=f>a.length-2?f:f+1;c[3]=f>a.length-3?f:f+2;f=a[c[0]];h=a[c[1]];i=a[c[2]];j=a[c[3]];c=e*e;g=e*c;d[0]=this.interpolate(f[0],h[0],i[0],j[0],e,c,g);d[1]=this.interpolate(f[1],h[1],i[1],j[1],e,c,g);d[2]=this.interpolate(f[2],h[2],i[2],j[2],e,c,g);return d};
+THREE.Animation.prototype.interpolate=function(a,b,c,d,e,f,g){a=0.5*(c-a);d=0.5*(d-b);return(2*(b-c)+a+d)*g+(-3*(b-c)-2*a-d)*f+a*e+b};THREE.Animation.prototype.getNextKeyWith=function(a,b,c){for(var d=this.data.hierarchy[b].keys,c=this.interpolationType===THREE.AnimationHandler.CATMULLROM||this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD?c<d.length-1?c:d.length-1:c%d.length;c<d.length;c++)if(void 0!==d[c][a])return d[c];return this.data.hierarchy[b].keys[0]};
+THREE.Animation.prototype.getPrevKeyWith=function(a,b,c){for(var d=this.data.hierarchy[b].keys,c=this.interpolationType===THREE.AnimationHandler.CATMULLROM||this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD?0<c?c:0:0<=c?c:c+d.length;0<=c;c--)if(void 0!==d[c][a])return d[c];return this.data.hierarchy[b].keys[d.length-1]};
+THREE.KeyFrameAnimation=function(a,b,c){this.root=a;this.data=THREE.AnimationHandler.get(b);this.hierarchy=THREE.AnimationHandler.parse(a);this.currentTime=0;this.timeScale=0.001;this.isPlaying=!1;this.loop=this.isPaused=!0;this.JITCompile=void 0!==c?c:!0;a=0;for(b=this.hierarchy.length;a<b;a++){var c=this.data.hierarchy[a].sids,d=this.hierarchy[a];if(this.data.hierarchy[a].keys.length&&c){for(var e=0;e<c.length;e++){var f=c[e],g=this.getNextKeyWith(f,a,0);g&&g.apply(f)}d.matrixAutoUpdate=!1;this.data.hierarchy[a].node.updateMatrix();
+d.matrixWorldNeedsUpdate=!0}}};
+THREE.KeyFrameAnimation.prototype.play=function(a,b){if(!this.isPlaying){this.isPlaying=!0;this.loop=void 0!==a?a:!0;this.currentTime=void 0!==b?b:0;this.startTimeMs=b;this.startTime=1E7;this.endTime=-this.startTime;var c,d=this.hierarchy.length,e,f;for(c=0;c<d;c++)if(e=this.hierarchy[c],f=this.data.hierarchy[c],e.useQuaternion=!0,void 0===f.animationCache&&(f.animationCache={},f.animationCache.prevKey=null,f.animationCache.nextKey=null,f.animationCache.originalMatrix=e instanceof THREE.Bone?e.skinMatrix:
+e.matrix),e=this.data.hierarchy[c].keys,e.length)f.animationCache.prevKey=e[0],f.animationCache.nextKey=e[1],this.startTime=Math.min(e[0].time,this.startTime),this.endTime=Math.max(e[e.length-1].time,this.endTime);this.update(0)}this.isPaused=!1;THREE.AnimationHandler.addToUpdate(this)};THREE.KeyFrameAnimation.prototype.pause=function(){this.isPaused?THREE.AnimationHandler.addToUpdate(this):THREE.AnimationHandler.removeFromUpdate(this);this.isPaused=!this.isPaused};
+THREE.KeyFrameAnimation.prototype.stop=function(){this.isPaused=this.isPlaying=!1;THREE.AnimationHandler.removeFromUpdate(this);for(var a=0;a<this.data.hierarchy.length;a++){var b=this.hierarchy[a],c=this.data.hierarchy[a];if(void 0!==c.animationCache){var d=c.animationCache.originalMatrix;b instanceof THREE.Bone?(d.copy(b.skinMatrix),b.skinMatrix=d):(d.copy(b.matrix),b.matrix=d);delete c.animationCache}}};
+THREE.KeyFrameAnimation.prototype.update=function(a){if(this.isPlaying){var b,c,d,e,f=this.data.JIT.hierarchy,g,h,i;h=this.currentTime+=a*this.timeScale;g=this.currentTime%=this.data.length;g<this.startTimeMs&&(g=this.currentTime=this.startTimeMs+g);e=parseInt(Math.min(g*this.data.fps,this.data.length*this.data.fps),10);if((i=g<h)&&!this.loop){for(var a=0,j=this.hierarchy.length;a<j;a++){var l=this.data.hierarchy[a].keys,f=this.data.hierarchy[a].sids;d=l.length-1;e=this.hierarchy[a];if(l.length){for(l=
+0;l<f.length;l++)g=f[l],(h=this.getPrevKeyWith(g,a,d))&&h.apply(g);this.data.hierarchy[a].node.updateMatrix();e.matrixWorldNeedsUpdate=!0}}this.stop()}else if(!(g<this.startTime)){a=0;for(j=this.hierarchy.length;a<j;a++){d=this.hierarchy[a];b=this.data.hierarchy[a];var l=b.keys,m=b.animationCache;if(this.JITCompile&&void 0!==f[a][e])d instanceof THREE.Bone?(d.skinMatrix=f[a][e],d.matrixWorldNeedsUpdate=!1):(d.matrix=f[a][e],d.matrixWorldNeedsUpdate=!0);else if(l.length){this.JITCompile&&m&&(d instanceof
+THREE.Bone?d.skinMatrix=m.originalMatrix:d.matrix=m.originalMatrix);b=m.prevKey;c=m.nextKey;if(b&&c){if(c.time<=h){if(i&&this.loop){b=l[0];for(c=l[1];c.time<g;)b=c,c=l[b.index+1]}else if(!i)for(var n=l.length-1;c.time<g&&c.index!==n;)b=c,c=l[b.index+1];m.prevKey=b;m.nextKey=c}c.time>=g?b.interpolate(c,g):b.interpolate(c,c.time)}this.data.hierarchy[a].node.updateMatrix();d.matrixWorldNeedsUpdate=!0}}if(this.JITCompile&&void 0===f[0][e]){this.hierarchy[0].updateMatrixWorld(!0);for(a=0;a<this.hierarchy.length;a++)f[a][e]=
+this.hierarchy[a]instanceof THREE.Bone?this.hierarchy[a].skinMatrix.clone():this.hierarchy[a].matrix.clone()}}}};THREE.KeyFrameAnimation.prototype.getNextKeyWith=function(a,b,c){b=this.data.hierarchy[b].keys;for(c%=b.length;c<b.length;c++)if(b[c].hasTarget(a))return b[c];return b[0]};THREE.KeyFrameAnimation.prototype.getPrevKeyWith=function(a,b,c){b=this.data.hierarchy[b].keys;for(c=0<=c?c:c+b.length;0<=c;c--)if(b[c].hasTarget(a))return b[c];return b[b.length-1]};
+THREE.CubeCamera=function(a,b,c){THREE.Object3D.call(this);var d=new THREE.PerspectiveCamera(90,1,a,b);d.up.set(0,-1,0);d.lookAt(new THREE.Vector3(1,0,0));this.add(d);var e=new THREE.PerspectiveCamera(90,1,a,b);e.up.set(0,-1,0);e.lookAt(new THREE.Vector3(-1,0,0));this.add(e);var f=new THREE.PerspectiveCamera(90,1,a,b);f.up.set(0,0,1);f.lookAt(new THREE.Vector3(0,1,0));this.add(f);var g=new THREE.PerspectiveCamera(90,1,a,b);g.up.set(0,0,-1);g.lookAt(new THREE.Vector3(0,-1,0));this.add(g);var h=new THREE.PerspectiveCamera(90,
+1,a,b);h.up.set(0,-1,0);h.lookAt(new THREE.Vector3(0,0,1));this.add(h);var i=new THREE.PerspectiveCamera(90,1,a,b);i.up.set(0,-1,0);i.lookAt(new THREE.Vector3(0,0,-1));this.add(i);this.renderTarget=new THREE.WebGLRenderTargetCube(c,c,{format:THREE.RGBFormat,magFilter:THREE.LinearFilter,minFilter:THREE.LinearFilter});this.updateCubeMap=function(a,b){var c=this.renderTarget,n=c.generateMipmaps;c.generateMipmaps=!1;c.activeCubeFace=0;a.render(b,d,c);c.activeCubeFace=1;a.render(b,e,c);c.activeCubeFace=
+2;a.render(b,f,c);c.activeCubeFace=3;a.render(b,g,c);c.activeCubeFace=4;a.render(b,h,c);c.generateMipmaps=n;c.activeCubeFace=5;a.render(b,i,c)}};THREE.CubeCamera.prototype=Object.create(THREE.Object3D.prototype);THREE.CombinedCamera=function(a,b,c,d,e,f,g){THREE.Camera.call(this);this.fov=c;this.left=-a/2;this.right=a/2;this.top=b/2;this.bottom=-b/2;this.cameraO=new THREE.OrthographicCamera(a/-2,a/2,b/2,b/-2,f,g);this.cameraP=new THREE.PerspectiveCamera(c,a/b,d,e);this.zoom=1;this.toPerspective()};
+THREE.CombinedCamera.prototype=Object.create(THREE.Camera.prototype);THREE.CombinedCamera.prototype.toPerspective=function(){this.near=this.cameraP.near;this.far=this.cameraP.far;this.cameraP.fov=this.fov/this.zoom;this.cameraP.updateProjectionMatrix();this.projectionMatrix=this.cameraP.projectionMatrix;this.inPerspectiveMode=!0;this.inOrthographicMode=!1};
+THREE.CombinedCamera.prototype.toOrthographic=function(){var a=this.cameraP.aspect,b=(this.cameraP.near+this.cameraP.far)/2,b=Math.tan(this.fov/2)*b,a=2*b*a/2,b=b/this.zoom,a=a/this.zoom;this.cameraO.left=-a;this.cameraO.right=a;this.cameraO.top=b;this.cameraO.bottom=-b;this.cameraO.updateProjectionMatrix();this.near=this.cameraO.near;this.far=this.cameraO.far;this.projectionMatrix=this.cameraO.projectionMatrix;this.inPerspectiveMode=!1;this.inOrthographicMode=!0};
+THREE.CombinedCamera.prototype.setSize=function(a,b){this.cameraP.aspect=a/b;this.left=-a/2;this.right=a/2;this.top=b/2;this.bottom=-b/2};THREE.CombinedCamera.prototype.setFov=function(a){this.fov=a;this.inPerspectiveMode?this.toPerspective():this.toOrthographic()};THREE.CombinedCamera.prototype.updateProjectionMatrix=function(){this.inPerspectiveMode?this.toPerspective():(this.toPerspective(),this.toOrthographic())};
+THREE.CombinedCamera.prototype.setLens=function(a,b){void 0===b&&(b=24);var c=2*Math.atan(b/(2*a))*(180/Math.PI);this.setFov(c);return c};THREE.CombinedCamera.prototype.setZoom=function(a){this.zoom=a;this.inPerspectiveMode?this.toPerspective():this.toOrthographic()};THREE.CombinedCamera.prototype.toFrontView=function(){this.rotation.x=0;this.rotation.y=0;this.rotation.z=0;this.rotationAutoUpdate=!1};
+THREE.CombinedCamera.prototype.toBackView=function(){this.rotation.x=0;this.rotation.y=Math.PI;this.rotation.z=0;this.rotationAutoUpdate=!1};THREE.CombinedCamera.prototype.toLeftView=function(){this.rotation.x=0;this.rotation.y=-Math.PI/2;this.rotation.z=0;this.rotationAutoUpdate=!1};THREE.CombinedCamera.prototype.toRightView=function(){this.rotation.x=0;this.rotation.y=Math.PI/2;this.rotation.z=0;this.rotationAutoUpdate=!1};
+THREE.CombinedCamera.prototype.toTopView=function(){this.rotation.x=-Math.PI/2;this.rotation.y=0;this.rotation.z=0;this.rotationAutoUpdate=!1};THREE.CombinedCamera.prototype.toBottomView=function(){this.rotation.x=Math.PI/2;this.rotation.y=0;this.rotation.z=0;this.rotationAutoUpdate=!1};
+THREE.AsteriskGeometry=function(a,b){THREE.Geometry.call(this);for(var c=0.707*a,d=0.707*b,c=[[a,0,0],[b,0,0],[-a,0,0],[-b,0,0],[0,a,0],[0,b,0],[0,-a,0],[0,-b,0],[0,0,a],[0,0,b],[0,0,-a],[0,0,-b],[c,c,0],[d,d,0],[-c,-c,0],[-d,-d,0],[c,-c,0],[d,-d,0],[-c,c,0],[-d,d,0],[c,0,c],[d,0,d],[-c,0,-c],[-d,0,-d],[c,0,-c],[d,0,-d],[-c,0,c],[-d,0,d],[0,c,c],[0,d,d],[0,-c,-c],[0,-d,-d],[0,c,-c],[0,d,-d],[0,-c,c],[0,-d,d]],d=0,e=c.length;d<e;d++)this.vertices.push(new THREE.Vector3(c[d][0],c[d][1],c[d][2]))};
+THREE.AsteriskGeometry.prototype=Object.create(THREE.Geometry.prototype);
+THREE.CircleGeometry=function(a,b,c,d){THREE.Geometry.call(this);var a=a||50,c=void 0!==c?c:0,d=void 0!==d?d:2*Math.PI,b=void 0!==b?Math.max(3,b):8,e,f=[];e=new THREE.Vector3;var g=new THREE.UV(0.5,0.5);this.vertices.push(e);f.push(g);for(e=0;e<=b;e++){var h=new THREE.Vector3;h.x=a*Math.cos(c+e/b*d);h.y=a*Math.sin(c+e/b*d);this.vertices.push(h);f.push(new THREE.UV((h.x/a+1)/2,-(h.y/a+1)/2+1))}c=new THREE.Vector3(0,0,-1);for(e=1;e<=b;e++)this.faces.push(new THREE.Face3(e,e+1,0,[c,c,c])),this.faceVertexUvs[0].push([f[e],
+f[e+1],g]);this.computeCentroids();this.computeFaceNormals();this.boundingSphere={radius:a}};THREE.CircleGeometry.prototype=Object.create(THREE.Geometry.prototype);
+THREE.CubeGeometry=function(a,b,c,d,e,f){function g(a,b,c,d,e,f,g,s){var t,r=h.widthSegments,z=h.heightSegments,w=e/2,q=f/2,E=h.vertices.length;if("x"===a&&"y"===b||"y"===a&&"x"===b)t="z";else if("x"===a&&"z"===b||"z"===a&&"x"===b)t="y",z=h.depthSegments;else if("z"===a&&"y"===b||"y"===a&&"z"===b)t="x",r=h.depthSegments;var A=r+1,v=z+1,u=e/r,D=f/z,C=new THREE.Vector3;C[t]=0<g?1:-1;for(e=0;e<v;e++)for(f=0;f<A;f++){var G=new THREE.Vector3;G[a]=(f*u-w)*c;G[b]=(e*D-q)*d;G[t]=g;h.vertices.push(G)}for(e=
+0;e<z;e++)for(f=0;f<r;f++)a=new THREE.Face4(f+A*e+E,f+A*(e+1)+E,f+1+A*(e+1)+E,f+1+A*e+E),a.normal.copy(C),a.vertexNormals.push(C.clone(),C.clone(),C.clone(),C.clone()),a.materialIndex=s,h.faces.push(a),h.faceVertexUvs[0].push([new THREE.UV(f/r,1-e/z),new THREE.UV(f/r,1-(e+1)/z),new THREE.UV((f+1)/r,1-(e+1)/z),new THREE.UV((f+1)/r,1-e/z)])}THREE.Geometry.call(this);var h=this;this.width=a;this.height=b;this.depth=c;this.widthSegments=d||1;this.heightSegments=e||1;this.depthSegments=f||1;a=this.width/
+2;b=this.height/2;c=this.depth/2;g("z","y",-1,-1,this.depth,this.height,a,0);g("z","y",1,-1,this.depth,this.height,-a,1);g("x","z",1,1,this.width,this.depth,b,2);g("x","z",1,-1,this.width,this.depth,-b,3);g("x","y",1,-1,this.width,this.height,c,4);g("x","y",-1,-1,this.width,this.height,-c,5);this.computeCentroids();this.mergeVertices()};THREE.CubeGeometry.prototype=Object.create(THREE.Geometry.prototype);
+THREE.CylinderGeometry=function(a,b,c,d,e,f){THREE.Geometry.call(this);var a=void 0!==a?a:20,b=void 0!==b?b:20,c=void 0!==c?c:100,g=c/2,d=d||8,e=e||1,h,i,j=[],l=[];for(i=0;i<=e;i++){var m=[],n=[],p=i/e,o=p*(b-a)+a;for(h=0;h<=d;h++){var s=h/d,t=new THREE.Vector3;t.x=o*Math.sin(2*s*Math.PI);t.y=-p*c+g;t.z=o*Math.cos(2*s*Math.PI);this.vertices.push(t);m.push(this.vertices.length-1);n.push(new THREE.UV(s,1-p))}j.push(m);l.push(n)}c=(b-a)/c;for(h=0;h<d;h++){0!==a?(m=this.vertices[j[0][h]].clone(),n=this.vertices[j[0][h+
+1]].clone()):(m=this.vertices[j[1][h]].clone(),n=this.vertices[j[1][h+1]].clone());m.setY(Math.sqrt(m.x*m.x+m.z*m.z)*c).normalize();n.setY(Math.sqrt(n.x*n.x+n.z*n.z)*c).normalize();for(i=0;i<e;i++){var p=j[i][h],o=j[i+1][h],s=j[i+1][h+1],t=j[i][h+1],r=m.clone(),z=m.clone(),w=n.clone(),q=n.clone(),E=l[i][h].clone(),A=l[i+1][h].clone(),v=l[i+1][h+1].clone(),u=l[i][h+1].clone();this.faces.push(new THREE.Face4(p,o,s,t,[r,z,w,q]));this.faceVertexUvs[0].push([E,A,v,u])}}if(!f&&0<a){this.vertices.push(new THREE.Vector3(0,
+g,0));for(h=0;h<d;h++)p=j[0][h],o=j[0][h+1],s=this.vertices.length-1,r=new THREE.Vector3(0,1,0),z=new THREE.Vector3(0,1,0),w=new THREE.Vector3(0,1,0),E=l[0][h].clone(),A=l[0][h+1].clone(),v=new THREE.UV(A.u,0),this.faces.push(new THREE.Face3(p,o,s,[r,z,w])),this.faceVertexUvs[0].push([E,A,v])}if(!f&&0<b){this.vertices.push(new THREE.Vector3(0,-g,0));for(h=0;h<d;h++)p=j[i][h+1],o=j[i][h],s=this.vertices.length-1,r=new THREE.Vector3(0,-1,0),z=new THREE.Vector3(0,-1,0),w=new THREE.Vector3(0,-1,0),E=
+l[i][h+1].clone(),A=l[i][h].clone(),v=new THREE.UV(A.u,1),this.faces.push(new THREE.Face3(p,o,s,[r,z,w])),this.faceVertexUvs[0].push([E,A,v])}this.computeCentroids();this.computeFaceNormals()};THREE.CylinderGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.ExtrudeGeometry=function(a,b){"undefined"!==typeof a&&(THREE.Geometry.call(this),a=a instanceof Array?a:[a],this.shapebb=a[a.length-1].getBoundingBox(),this.addShapeList(a,b),this.computeCentroids(),this.computeFaceNormals())};
+THREE.ExtrudeGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.ExtrudeGeometry.prototype.addShapeList=function(a,b){for(var c=a.length,d=0;d<c;d++)this.addShape(a[d],b)};
+THREE.ExtrudeGeometry.prototype.addShape=function(a,b){function c(a,b,c){b||console.log("die");return b.clone().multiplyScalar(c).addSelf(a)}function d(a,b,c){var d=THREE.ExtrudeGeometry.__v1,e=THREE.ExtrudeGeometry.__v2,f=THREE.ExtrudeGeometry.__v3,g=THREE.ExtrudeGeometry.__v4,h=THREE.ExtrudeGeometry.__v5,i=THREE.ExtrudeGeometry.__v6;d.set(a.x-b.x,a.y-b.y);e.set(a.x-c.x,a.y-c.y);d=d.normalize();e=e.normalize();f.set(-d.y,d.x);g.set(e.y,-e.x);h.copy(a).addSelf(f);i.copy(a).addSelf(g);if(h.equals(i))return g.clone();
+h.copy(b).addSelf(f);i.copy(c).addSelf(g);f=d.dot(g);g=i.subSelf(h).dot(g);0===f&&(console.log("Either infinite or no solutions!"),0===g?console.log("Its finite solutions."):console.log("Too bad, no solutions."));g/=f;return 0>g?(b=Math.atan2(b.y-a.y,b.x-a.x),a=Math.atan2(c.y-a.y,c.x-a.x),b>a&&(a+=2*Math.PI),c=(b+a)/2,a=-Math.cos(c),c=-Math.sin(c),new THREE.Vector2(a,c)):d.multiplyScalar(g).addSelf(h).subSelf(a).clone()}function e(c,d){var e,f;for(J=c.length;0<=--J;){e=J;f=J-1;0>f&&(f=c.length-1);
+for(var g=0,h=n+2*l,g=0;g<h;g++){var i=R*g,j=R*(g+1),m=d+e+i,i=d+f+i,o=d+f+j,j=d+e+j,p=c,s=g,q=h,t=e,u=f,m=m+G,i=i+G,o=o+G,j=j+G;C.faces.push(new THREE.Face4(m,i,o,j,null,null,r));m=z.generateSideWallUV(C,a,p,b,m,i,o,j,s,q,t,u);C.faceVertexUvs[0].push(m)}}}function f(a,b,c){C.vertices.push(new THREE.Vector3(a,b,c))}function g(c,d,e,f){c+=G;d+=G;e+=G;C.faces.push(new THREE.Face3(c,d,e,null,null,t));c=f?z.generateBottomUV(C,a,b,c,d,e):z.generateTopUV(C,a,b,c,d,e);C.faceVertexUvs[0].push(c)}var h=void 0!==
+b.amount?b.amount:100,i=void 0!==b.bevelThickness?b.bevelThickness:6,j=void 0!==b.bevelSize?b.bevelSize:i-2,l=void 0!==b.bevelSegments?b.bevelSegments:3,m=void 0!==b.bevelEnabled?b.bevelEnabled:!0,n=void 0!==b.steps?b.steps:1,p=b.extrudePath,o,s=!1,t=b.material,r=b.extrudeMaterial,z=void 0!==b.UVGenerator?b.UVGenerator:THREE.ExtrudeGeometry.WorldUVGenerator,w,q,E,A;p&&(o=p.getSpacedPoints(n),s=!0,m=!1,w=void 0!==b.frames?b.frames:new THREE.TubeGeometry.FrenetFrames(p,n,!1),q=new THREE.Vector3,E=new THREE.Vector3,
+A=new THREE.Vector3);m||(j=i=l=0);var v,u,D,C=this,G=this.vertices.length,p=a.extractPoints(),P=p.shape,p=p.holes,B=!THREE.Shape.Utils.isClockWise(P);if(B){P=P.reverse();u=0;for(D=p.length;u<D;u++)v=p[u],THREE.Shape.Utils.isClockWise(v)&&(p[u]=v.reverse());B=!1}var K=THREE.Shape.Utils.triangulateShape(P,p),B=P;u=0;for(D=p.length;u<D;u++)v=p[u],P=P.concat(v);var H,I,N,O,R=P.length,ga=K.length,M=[],J=0,Q=B.length;H=Q-1;for(I=J+1;J<Q;J++,H++,I++)H===Q&&(H=0),I===Q&&(I=0),M[J]=d(B[J],B[H],B[I]);var Z=
+[],L,oa=M.concat();u=0;for(D=p.length;u<D;u++){v=p[u];L=[];J=0;Q=v.length;H=Q-1;for(I=J+1;J<Q;J++,H++,I++)H===Q&&(H=0),I===Q&&(I=0),L[J]=d(v[J],v[H],v[I]);Z.push(L);oa=oa.concat(L)}for(H=0;H<l;H++){v=H/l;N=i*(1-v);I=j*Math.sin(v*Math.PI/2);J=0;for(Q=B.length;J<Q;J++)O=c(B[J],M[J],I),f(O.x,O.y,-N);u=0;for(D=p.length;u<D;u++){v=p[u];L=Z[u];J=0;for(Q=v.length;J<Q;J++)O=c(v[J],L[J],I),f(O.x,O.y,-N)}}I=j;for(J=0;J<R;J++)O=m?c(P[J],oa[J],I):P[J],s?(E.copy(w.normals[0]).multiplyScalar(O.x),q.copy(w.binormals[0]).multiplyScalar(O.y),
+A.copy(o[0]).addSelf(E).addSelf(q),f(A.x,A.y,A.z)):f(O.x,O.y,0);for(v=1;v<=n;v++)for(J=0;J<R;J++)O=m?c(P[J],oa[J],I):P[J],s?(E.copy(w.normals[v]).multiplyScalar(O.x),q.copy(w.binormals[v]).multiplyScalar(O.y),A.copy(o[v]).addSelf(E).addSelf(q),f(A.x,A.y,A.z)):f(O.x,O.y,h/n*v);for(H=l-1;0<=H;H--){v=H/l;N=i*(1-v);I=j*Math.sin(v*Math.PI/2);J=0;for(Q=B.length;J<Q;J++)O=c(B[J],M[J],I),f(O.x,O.y,h+N);u=0;for(D=p.length;u<D;u++){v=p[u];L=Z[u];J=0;for(Q=v.length;J<Q;J++)O=c(v[J],L[J],I),s?f(O.x,O.y+o[n-1].y,
+o[n-1].x+N):f(O.x,O.y,h+N)}}if(m){i=0*R;for(J=0;J<ga;J++)h=K[J],g(h[2]+i,h[1]+i,h[0]+i,!0);i=R*(n+2*l);for(J=0;J<ga;J++)h=K[J],g(h[0]+i,h[1]+i,h[2]+i,!1)}else{for(J=0;J<ga;J++)h=K[J],g(h[2],h[1],h[0],!0);for(J=0;J<ga;J++)h=K[J],g(h[0]+R*n,h[1]+R*n,h[2]+R*n,!1)}h=0;e(B,h);h+=B.length;u=0;for(D=p.length;u<D;u++)v=p[u],e(v,h),h+=v.length};
+THREE.ExtrudeGeometry.WorldUVGenerator={generateTopUV:function(a,b,c,d,e,f){b=a.vertices[e].x;e=a.vertices[e].y;c=a.vertices[f].x;f=a.vertices[f].y;return[new THREE.UV(a.vertices[d].x,a.vertices[d].y),new THREE.UV(b,e),new THREE.UV(c,f)]},generateBottomUV:function(a,b,c,d,e,f){return this.generateTopUV(a,b,c,d,e,f)},generateSideWallUV:function(a,b,c,d,e,f,g,h){var b=a.vertices[e].x,c=a.vertices[e].y,e=a.vertices[e].z,d=a.vertices[f].x,i=a.vertices[f].y,f=a.vertices[f].z,j=a.vertices[g].x,l=a.vertices[g].y,
+g=a.vertices[g].z,m=a.vertices[h].x,n=a.vertices[h].y,a=a.vertices[h].z;return 0.01>Math.abs(c-i)?[new THREE.UV(b,1-e),new THREE.UV(d,1-f),new THREE.UV(j,1-g),new THREE.UV(m,1-a)]:[new THREE.UV(c,1-e),new THREE.UV(i,1-f),new THREE.UV(l,1-g),new THREE.UV(n,1-a)]}};THREE.ExtrudeGeometry.__v1=new THREE.Vector2;THREE.ExtrudeGeometry.__v2=new THREE.Vector2;THREE.ExtrudeGeometry.__v3=new THREE.Vector2;THREE.ExtrudeGeometry.__v4=new THREE.Vector2;THREE.ExtrudeGeometry.__v5=new THREE.Vector2;
+THREE.ExtrudeGeometry.__v6=new THREE.Vector2;THREE.ShapeGeometry=function(a,b){THREE.Geometry.call(this);!1===a instanceof Array&&(a=[a]);this.shapebb=a[a.length-1].getBoundingBox();this.addShapeList(a,b);this.computeCentroids();this.computeFaceNormals()};THREE.ShapeGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.ShapeGeometry.prototype.addShapeList=function(a,b){for(var c=0,d=a.length;c<d;c++)this.addShape(a[c],b);return this};
+THREE.ShapeGeometry.prototype.addShape=function(a,b){void 0===b&&(b={});var c=b.material,d=void 0===b.UVGenerator?THREE.ExtrudeGeometry.WorldUVGenerator:b.UVGenerator,e,f,g,h=this.vertices.length;e=a.extractPoints();var i=e.shape,j=e.holes;if(!THREE.Shape.Utils.isClockWise(i)){i=i.reverse();e=0;for(f=j.length;e<f;e++)g=j[e],THREE.Shape.Utils.isClockWise(g)&&(j[e]=g.reverse())}var l=THREE.Shape.Utils.triangulateShape(i,j);e=0;for(f=j.length;e<f;e++)g=j[e],i=i.concat(g);j=i.length;f=l.length;for(e=
+0;e<j;e++)g=i[e],this.vertices.push(new THREE.Vector3(g.x,g.y,0));for(e=0;e<f;e++)j=l[e],i=j[0]+h,g=j[1]+h,j=j[2]+h,this.faces.push(new THREE.Face3(i,g,j,null,null,c)),this.faceVertexUvs[0].push(d.generateBottomUV(this,a,b,i,g,j))};
+THREE.LatheGeometry=function(a,b,c){THREE.Geometry.call(this);for(var b=b||12,c=c||2*Math.PI,d=[],e=(new THREE.Matrix4).makeRotationZ(c/b),f=0;f<a.length;f++)d[f]=a[f].clone(),this.vertices.push(d[f]);for(var g=b+1,c=0;c<g;c++)for(f=0;f<d.length;f++)d[f]=e.multiplyVector3(d[f].clone()),this.vertices.push(d[f]);for(c=0;c<b;c++){d=0;for(e=a.length;d<e-1;d++)this.faces.push(new THREE.Face4(c*e+d,(c+1)%g*e+d,(c+1)%g*e+(d+1)%e,c*e+(d+1)%e)),this.faceVertexUvs[0].push([new THREE.UV(1-c/b,d/e),new THREE.UV(1-
+(c+1)/b,d/e),new THREE.UV(1-(c+1)/b,(d+1)/e),new THREE.UV(1-c/b,(d+1)/e)])}this.computeCentroids();this.computeFaceNormals();this.computeVertexNormals()};THREE.LatheGeometry.prototype=Object.create(THREE.Geometry.prototype);
+THREE.PlaneGeometry=function(a,b,c,d){THREE.Geometry.call(this);this.width=a;this.height=b;this.widthSegments=c||1;this.heightSegments=d||1;for(var c=a/2,e=b/2,d=this.widthSegments,f=this.heightSegments,g=d+1,h=f+1,i=this.width/d,j=this.height/f,l=new THREE.Vector3(0,0,1),a=0;a<h;a++)for(b=0;b<g;b++)this.vertices.push(new THREE.Vector3(b*i-c,-(a*j-e),0));for(a=0;a<f;a++)for(b=0;b<d;b++)c=new THREE.Face4(b+g*a,b+g*(a+1),b+1+g*(a+1),b+1+g*a),c.normal.copy(l),c.vertexNormals.push(l.clone(),l.clone(),
+l.clone(),l.clone()),this.faces.push(c),this.faceVertexUvs[0].push([new THREE.UV(b/d,1-a/f),new THREE.UV(b/d,1-(a+1)/f),new THREE.UV((b+1)/d,1-(a+1)/f),new THREE.UV((b+1)/d,1-a/f)]);this.computeCentroids()};THREE.PlaneGeometry.prototype=Object.create(THREE.Geometry.prototype);
+THREE.SphereGeometry=function(a,b,c,d,e,f,g){THREE.Geometry.call(this);this.radius=a||50;this.widthSegments=Math.max(3,Math.floor(b)||8);this.heightSegments=Math.max(2,Math.floor(c)||6);for(var d=void 0!==d?d:0,e=void 0!==e?e:2*Math.PI,f=void 0!==f?f:0,g=void 0!==g?g:Math.PI,c=[],h=[],b=0;b<=this.heightSegments;b++){for(var i=[],j=[],a=0;a<=this.widthSegments;a++){var l=a/this.widthSegments,m=b/this.heightSegments,n=new THREE.Vector3;n.x=-this.radius*Math.cos(d+l*e)*Math.sin(f+m*g);n.y=this.radius*
+Math.cos(f+m*g);n.z=this.radius*Math.sin(d+l*e)*Math.sin(f+m*g);this.vertices.push(n);i.push(this.vertices.length-1);j.push(new THREE.UV(l,1-m))}c.push(i);h.push(j)}for(b=0;b<this.heightSegments;b++)for(a=0;a<this.widthSegments;a++){var d=c[b][a+1],e=c[b][a],f=c[b+1][a],g=c[b+1][a+1],i=this.vertices[d].clone().normalize(),j=this.vertices[e].clone().normalize(),l=this.vertices[f].clone().normalize(),m=this.vertices[g].clone().normalize(),n=h[b][a+1].clone(),p=h[b][a].clone(),o=h[b+1][a].clone(),s=
+h[b+1][a+1].clone();Math.abs(this.vertices[d].y)===this.radius?(this.faces.push(new THREE.Face3(d,f,g,[i,l,m])),this.faceVertexUvs[0].push([n,o,s])):Math.abs(this.vertices[f].y)===this.radius?(this.faces.push(new THREE.Face3(d,e,f,[i,j,l])),this.faceVertexUvs[0].push([n,p,o])):(this.faces.push(new THREE.Face4(d,e,f,g,[i,j,l,m])),this.faceVertexUvs[0].push([n,p,o,s]))}this.computeCentroids();this.computeFaceNormals();this.boundingSphere={radius:this.radius}};THREE.SphereGeometry.prototype=Object.create(THREE.Geometry.prototype);
+THREE.TextGeometry=function(a,b){var c=THREE.FontUtils.generateShapes(a,b);b.amount=void 0!==b.height?b.height:50;void 0===b.bevelThickness&&(b.bevelThickness=10);void 0===b.bevelSize&&(b.bevelSize=8);void 0===b.bevelEnabled&&(b.bevelEnabled=!1);THREE.ExtrudeGeometry.call(this,c,b)};THREE.TextGeometry.prototype=Object.create(THREE.ExtrudeGeometry.prototype);
+THREE.TorusGeometry=function(a,b,c,d,e){THREE.Geometry.call(this);this.radius=a||100;this.tube=b||40;this.radialSegments=c||8;this.tubularSegments=d||6;this.arc=e||2*Math.PI;e=new THREE.Vector3;a=[];b=[];for(c=0;c<=this.radialSegments;c++)for(d=0;d<=this.tubularSegments;d++){var f=d/this.tubularSegments*this.arc,g=2*c/this.radialSegments*Math.PI;e.x=this.radius*Math.cos(f);e.y=this.radius*Math.sin(f);var h=new THREE.Vector3;h.x=(this.radius+this.tube*Math.cos(g))*Math.cos(f);h.y=(this.radius+this.tube*
+Math.cos(g))*Math.sin(f);h.z=this.tube*Math.sin(g);this.vertices.push(h);a.push(new THREE.UV(d/this.tubularSegments,c/this.radialSegments));b.push(h.clone().subSelf(e).normalize())}for(c=1;c<=this.radialSegments;c++)for(d=1;d<=this.tubularSegments;d++){var e=(this.tubularSegments+1)*c+d-1,f=(this.tubularSegments+1)*(c-1)+d-1,g=(this.tubularSegments+1)*(c-1)+d,h=(this.tubularSegments+1)*c+d,i=new THREE.Face4(e,f,g,h,[b[e],b[f],b[g],b[h]]);i.normal.addSelf(b[e]);i.normal.addSelf(b[f]);i.normal.addSelf(b[g]);
+i.normal.addSelf(b[h]);i.normal.normalize();this.faces.push(i);this.faceVertexUvs[0].push([a[e].clone(),a[f].clone(),a[g].clone(),a[h].clone()])}this.computeCentroids()};THREE.TorusGeometry.prototype=Object.create(THREE.Geometry.prototype);
+THREE.TorusKnotGeometry=function(a,b,c,d,e,f,g){function h(a,b,c,d,e,f){var g=Math.cos(a);Math.cos(b);b=Math.sin(a);a*=c/d;c=Math.cos(a);g*=0.5*e*(2+c);b=0.5*e*(2+c)*b;e=0.5*f*e*Math.sin(a);return new THREE.Vector3(g,b,e)}THREE.Geometry.call(this);this.radius=a||200;this.tube=b||40;this.radialSegments=c||64;this.tubularSegments=d||8;this.p=e||2;this.q=f||3;this.heightScale=g||1;this.grid=Array(this.radialSegments);c=new THREE.Vector3;d=new THREE.Vector3;e=new THREE.Vector3;for(a=0;a<this.radialSegments;++a){this.grid[a]=
+Array(this.tubularSegments);for(b=0;b<this.tubularSegments;++b){var i=2*(a/this.radialSegments)*this.p*Math.PI,g=2*(b/this.tubularSegments)*Math.PI,f=h(i,g,this.q,this.p,this.radius,this.heightScale),i=h(i+0.01,g,this.q,this.p,this.radius,this.heightScale);c.sub(i,f);d.add(i,f);e.cross(c,d);d.cross(e,c);e.normalize();d.normalize();i=-this.tube*Math.cos(g);g=this.tube*Math.sin(g);f.x+=i*d.x+g*e.x;f.y+=i*d.y+g*e.y;f.z+=i*d.z+g*e.z;this.grid[a][b]=this.vertices.push(new THREE.Vector3(f.x,f.y,f.z))-1}}for(a=
+0;a<this.radialSegments;++a)for(b=0;b<this.tubularSegments;++b){var e=(a+1)%this.radialSegments,f=(b+1)%this.tubularSegments,c=this.grid[a][b],d=this.grid[e][b],e=this.grid[e][f],f=this.grid[a][f],g=new THREE.UV(a/this.radialSegments,b/this.tubularSegments),i=new THREE.UV((a+1)/this.radialSegments,b/this.tubularSegments),j=new THREE.UV((a+1)/this.radialSegments,(b+1)/this.tubularSegments),l=new THREE.UV(a/this.radialSegments,(b+1)/this.tubularSegments);this.faces.push(new THREE.Face4(c,d,e,f));this.faceVertexUvs[0].push([g,
+i,j,l])}this.computeCentroids();this.computeFaceNormals();this.computeVertexNormals()};THREE.TorusKnotGeometry.prototype=Object.create(THREE.Geometry.prototype);
+THREE.TubeGeometry=function(a,b,c,d,e,f){THREE.Geometry.call(this);this.path=a;this.segments=b||64;this.radius=c||1;this.radiusSegments=d||8;this.closed=e||!1;f&&(this.debug=new THREE.Object3D);this.grid=[];var g,h,f=this.segments+1,i,j,l,m=new THREE.Vector3,n,p,o,b=new THREE.TubeGeometry.FrenetFrames(a,b,e);n=b.tangents;p=b.normals;o=b.binormals;this.tangents=n;this.normals=p;this.binormals=o;for(b=0;b<f;b++){this.grid[b]=[];d=b/(f-1);l=a.getPointAt(d);d=n[b];g=p[b];h=o[b];this.debug&&(this.debug.add(new THREE.ArrowHelper(d,
+l,c,255)),this.debug.add(new THREE.ArrowHelper(g,l,c,16711680)),this.debug.add(new THREE.ArrowHelper(h,l,c,65280)));for(d=0;d<this.radiusSegments;d++)i=2*(d/this.radiusSegments)*Math.PI,j=-this.radius*Math.cos(i),i=this.radius*Math.sin(i),m.copy(l),m.x+=j*g.x+i*h.x,m.y+=j*g.y+i*h.y,m.z+=j*g.z+i*h.z,this.grid[b][d]=this.vertices.push(new THREE.Vector3(m.x,m.y,m.z))-1}for(b=0;b<this.segments;b++)for(d=0;d<this.radiusSegments;d++)f=e?(b+1)%this.segments:b+1,m=(d+1)%this.radiusSegments,a=this.grid[b][d],
+c=this.grid[f][d],f=this.grid[f][m],m=this.grid[b][m],n=new THREE.UV(b/this.segments,d/this.radiusSegments),p=new THREE.UV((b+1)/this.segments,d/this.radiusSegments),o=new THREE.UV((b+1)/this.segments,(d+1)/this.radiusSegments),g=new THREE.UV(b/this.segments,(d+1)/this.radiusSegments),this.faces.push(new THREE.Face4(a,c,f,m)),this.faceVertexUvs[0].push([n,p,o,g]);this.computeCentroids();this.computeFaceNormals();this.computeVertexNormals()};THREE.TubeGeometry.prototype=Object.create(THREE.Geometry.prototype);
+THREE.TubeGeometry.FrenetFrames=function(a,b,c){new THREE.Vector3;var d=new THREE.Vector3;new THREE.Vector3;var e=[],f=[],g=[],h=new THREE.Vector3,i=new THREE.Matrix4,b=b+1,j,l,m;this.tangents=e;this.normals=f;this.binormals=g;for(j=0;j<b;j++)l=j/(b-1),e[j]=a.getTangentAt(l),e[j].normalize();f[0]=new THREE.Vector3;g[0]=new THREE.Vector3;a=Number.MAX_VALUE;j=Math.abs(e[0].x);l=Math.abs(e[0].y);m=Math.abs(e[0].z);j<=a&&(a=j,d.set(1,0,0));l<=a&&(a=l,d.set(0,1,0));m<=a&&d.set(0,0,1);h.cross(e[0],d).normalize();
+f[0].cross(e[0],h);g[0].cross(e[0],f[0]);for(j=1;j<b;j++)f[j]=f[j-1].clone(),g[j]=g[j-1].clone(),h.cross(e[j-1],e[j]),1E-4<h.length()&&(h.normalize(),d=Math.acos(e[j-1].dot(e[j])),i.makeRotationAxis(h,d).multiplyVector3(f[j])),g[j].cross(e[j],f[j]);if(c){d=Math.acos(f[0].dot(f[b-1]));d/=b-1;0<e[0].dot(h.cross(f[0],f[b-1]))&&(d=-d);for(j=1;j<b;j++)i.makeRotationAxis(e[j],d*j).multiplyVector3(f[j]),g[j].cross(e[j],f[j])}};
+THREE.PolyhedronGeometry=function(a,b,c,d){function e(a){var b=a.normalize().clone();b.index=i.vertices.push(b)-1;var c=Math.atan2(a.z,-a.x)/2/Math.PI+0.5,a=Math.atan2(-a.y,Math.sqrt(a.x*a.x+a.z*a.z))/Math.PI+0.5;b.uv=new THREE.UV(c,1-a);return b}function f(a,b,c,d){1>d?(d=new THREE.Face3(a.index,b.index,c.index,[a.clone(),b.clone(),c.clone()]),d.centroid.addSelf(a).addSelf(b).addSelf(c).divideScalar(3),d.normal=d.centroid.clone().normalize(),i.faces.push(d),d=Math.atan2(d.centroid.z,-d.centroid.x),
+i.faceVertexUvs[0].push([h(a.uv,a,d),h(b.uv,b,d),h(c.uv,c,d)])):(d-=1,f(a,g(a,b),g(a,c),d),f(g(a,b),b,g(b,c),d),f(g(a,c),g(b,c),c,d),f(g(a,b),g(b,c),g(a,c),d))}function g(a,b){m[a.index]||(m[a.index]=[]);m[b.index]||(m[b.index]=[]);var c=m[a.index][b.index];void 0===c&&(m[a.index][b.index]=m[b.index][a.index]=c=e((new THREE.Vector3).add(a,b).divideScalar(2)));return c}function h(a,b,c){0>c&&1===a.u&&(a=new THREE.UV(a.u-1,a.v));0===b.x&&0===b.z&&(a=new THREE.UV(c/2/Math.PI+0.5,a.v));return a}THREE.Geometry.call(this);
+for(var c=c||1,d=d||0,i=this,j=0,l=a.length;j<l;j++)e(new THREE.Vector3(a[j][0],a[j][1],a[j][2]));for(var m=[],a=this.vertices,j=0,l=b.length;j<l;j++)f(a[b[j][0]],a[b[j][1]],a[b[j][2]],d);this.mergeVertices();j=0;for(l=this.vertices.length;j<l;j++)this.vertices[j].multiplyScalar(c);this.computeCentroids();this.boundingSphere={radius:c}};THREE.PolyhedronGeometry.prototype=Object.create(THREE.Geometry.prototype);
+THREE.IcosahedronGeometry=function(a,b){var c=(1+Math.sqrt(5))/2;THREE.PolyhedronGeometry.call(this,[[-1,c,0],[1,c,0],[-1,-c,0],[1,-c,0],[0,-1,c],[0,1,c],[0,-1,-c],[0,1,-c],[c,0,-1],[c,0,1],[-c,0,-1],[-c,0,1]],[[0,11,5],[0,5,1],[0,1,7],[0,7,10],[0,10,11],[1,5,9],[5,11,4],[11,10,2],[10,7,6],[7,1,8],[3,9,4],[3,4,2],[3,2,6],[3,6,8],[3,8,9],[4,9,5],[2,4,11],[6,2,10],[8,6,7],[9,8,1]],a,b)};THREE.IcosahedronGeometry.prototype=Object.create(THREE.Geometry.prototype);
+THREE.OctahedronGeometry=function(a,b){THREE.PolyhedronGeometry.call(this,[[1,0,0],[-1,0,0],[0,1,0],[0,-1,0],[0,0,1],[0,0,-1]],[[0,2,4],[0,4,3],[0,3,5],[0,5,2],[1,2,5],[1,5,3],[1,3,4],[1,4,2]],a,b)};THREE.OctahedronGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.TetrahedronGeometry=function(a,b){THREE.PolyhedronGeometry.call(this,[[1,1,1],[-1,-1,1],[-1,1,-1],[1,-1,-1]],[[2,1,0],[0,3,2],[1,3,0],[2,3,1]],a,b)};THREE.TetrahedronGeometry.prototype=Object.create(THREE.Geometry.prototype);
+THREE.ParametricGeometry=function(a,b,c,d){THREE.Geometry.call(this);var e=this.vertices,f=this.faces,g=this.faceVertexUvs[0],d=void 0===d?!1:d,h,i,j,l,m=b+1;for(h=0;h<=c;h++){l=h/c;for(i=0;i<=b;i++)j=i/b,j=a(j,l),e.push(j)}var n,p,o,s;for(h=0;h<c;h++)for(i=0;i<b;i++)a=h*m+i,e=h*m+i+1,l=(h+1)*m+i,j=(h+1)*m+i+1,n=new THREE.UV(i/b,h/c),p=new THREE.UV((i+1)/b,h/c),o=new THREE.UV(i/b,(h+1)/c),s=new THREE.UV((i+1)/b,(h+1)/c),d?(f.push(new THREE.Face3(a,e,l)),f.push(new THREE.Face3(e,j,l)),g.push([n,p,
+o]),g.push([p,s,o])):(f.push(new THREE.Face4(a,e,j,l)),g.push([n,p,s,o]));this.computeCentroids();this.computeFaceNormals();this.computeVertexNormals()};THREE.ParametricGeometry.prototype=Object.create(THREE.Geometry.prototype);
+THREE.ConvexGeometry=function(a){function b(a){var b=a.length();return new THREE.UV(a.x/b,a.y/b)}THREE.Geometry.call(this);for(var c=[[0,1,2],[0,2,1]],d=3;d<a.length;d++){var e=d,f=a[e].clone(),g=f.length();f.x+=g*2E-6*(Math.random()-0.5);f.y+=g*2E-6*(Math.random()-0.5);f.z+=g*2E-6*(Math.random()-0.5);for(var g=[],h=0;h<c.length;){var i=c[h],j=f,l=a[i[0]],m;m=l;var n=a[i[1]],p=a[i[2]],o=new THREE.Vector3,s=new THREE.Vector3;o.sub(p,n);s.sub(m,n);o.crossSelf(s);o.normalize();m=o;l=m.dot(l);if(m.dot(j)>=
+l){for(j=0;3>j;j++){l=[i[j],i[(j+1)%3]];m=!0;for(n=0;n<g.length;n++)if(g[n][0]===l[1]&&g[n][1]===l[0]){g[n]=g[g.length-1];g.pop();m=!1;break}m&&g.push(l)}c[h]=c[c.length-1];c.pop()}else h++}for(n=0;n<g.length;n++)c.push([g[n][0],g[n][1],e])}e=0;f=Array(a.length);for(d=0;d<c.length;d++){g=c[d];for(h=0;3>h;h++)void 0===f[g[h]]&&(f[g[h]]=e++,this.vertices.push(a[g[h]])),g[h]=f[g[h]]}for(d=0;d<c.length;d++)this.faces.push(new THREE.Face3(c[d][0],c[d][1],c[d][2]));for(d=0;d<this.faces.length;d++)g=this.faces[d],
+this.faceVertexUvs[0].push([b(this.vertices[g.a]),b(this.vertices[g.b]),b(this.vertices[g.c])]);this.computeCentroids();this.computeFaceNormals();this.computeVertexNormals()};THREE.ConvexGeometry.prototype=Object.create(THREE.Geometry.prototype);
+THREE.AxisHelper=function(a){var b=new THREE.Geometry;b.vertices.push(new THREE.Vector3,new THREE.Vector3(a||1,0,0),new THREE.Vector3,new THREE.Vector3(0,a||1,0),new THREE.Vector3,new THREE.Vector3(0,0,a||1));b.colors.push(new THREE.Color(16711680),new THREE.Color(16755200),new THREE.Color(65280),new THREE.Color(11206400),new THREE.Color(255),new THREE.Color(43775));a=new THREE.LineBasicMaterial({vertexColors:THREE.VertexColors});THREE.Line.call(this,b,a,THREE.LinePieces)};
+THREE.AxisHelper.prototype=Object.create(THREE.Line.prototype);
+THREE.ArrowHelper=function(a,b,c,d){THREE.Object3D.call(this);void 0===d&&(d=16776960);void 0===c&&(c=20);var e=new THREE.Geometry;e.vertices.push(new THREE.Vector3(0,0,0));e.vertices.push(new THREE.Vector3(0,1,0));this.line=new THREE.Line(e,new THREE.LineBasicMaterial({color:d}));this.add(this.line);e=new THREE.CylinderGeometry(0,0.05,0.25,5,1);this.cone=new THREE.Mesh(e,new THREE.MeshBasicMaterial({color:d}));this.cone.position.set(0,1,0);this.add(this.cone);b instanceof THREE.Vector3&&(this.position=
+b);this.setDirection(a);this.setLength(c)};THREE.ArrowHelper.prototype=Object.create(THREE.Object3D.prototype);THREE.ArrowHelper.prototype.setDirection=function(a){var b=(new THREE.Vector3(0,1,0)).crossSelf(a),a=Math.acos((new THREE.Vector3(0,1,0)).dot(a.clone().normalize()));this.matrix=(new THREE.Matrix4).makeRotationAxis(b.normalize(),a);this.rotation.setEulerFromRotationMatrix(this.matrix,this.eulerOrder)};THREE.ArrowHelper.prototype.setLength=function(a){this.scale.set(a,a,a)};
+THREE.ArrowHelper.prototype.setColor=function(a){this.line.material.color.setHex(a);this.cone.material.color.setHex(a)};
+THREE.CameraHelper=function(a){function b(a,b,d){c(a,d);c(b,d)}function c(a,b){d.geometry.vertices.push(new THREE.Vector3);d.geometry.colors.push(new THREE.Color(b));void 0===d.pointMap[a]&&(d.pointMap[a]=[]);d.pointMap[a].push(d.geometry.vertices.length-1)}THREE.Line.call(this);var d=this;this.geometry=new THREE.Geometry;this.material=new THREE.LineBasicMaterial({color:16777215,vertexColors:THREE.FaceColors});this.type=THREE.LinePieces;this.matrixWorld=a.matrixWorld;this.matrixAutoUpdate=!1;this.pointMap=
+{};b("n1","n2",16755200);b("n2","n4",16755200);b("n4","n3",16755200);b("n3","n1",16755200);b("f1","f2",16755200);b("f2","f4",16755200);b("f4","f3",16755200);b("f3","f1",16755200);b("n1","f1",16755200);b("n2","f2",16755200);b("n3","f3",16755200);b("n4","f4",16755200);b("p","n1",16711680);b("p","n2",16711680);b("p","n3",16711680);b("p","n4",16711680);b("u1","u2",43775);b("u2","u3",43775);b("u3","u1",43775);b("c","t",16777215);b("p","c",3355443);b("cn1","cn2",3355443);b("cn3","cn4",3355443);b("cf1",
+"cf2",3355443);b("cf3","cf4",3355443);this.camera=a;this.update(a)};THREE.CameraHelper.prototype=Object.create(THREE.Line.prototype);
+THREE.CameraHelper.prototype.update=function(){function a(a,d,e,f){THREE.CameraHelper.__v.set(d,e,f);THREE.CameraHelper.__projector.unprojectVector(THREE.CameraHelper.__v,THREE.CameraHelper.__c);a=b.pointMap[a];if(void 0!==a){d=0;for(e=a.length;d<e;d++)b.geometry.vertices[a[d]].copy(THREE.CameraHelper.__v)}}var b=this;THREE.CameraHelper.__c.projectionMatrix.copy(this.camera.projectionMatrix);a("c",0,0,-1);a("t",0,0,1);a("n1",-1,-1,-1);a("n2",1,-1,-1);a("n3",-1,1,-1);a("n4",1,1,-1);a("f1",-1,-1,1);
+a("f2",1,-1,1);a("f3",-1,1,1);a("f4",1,1,1);a("u1",0.7,1.1,-1);a("u2",-0.7,1.1,-1);a("u3",0,2,-1);a("cf1",-1,0,1);a("cf2",1,0,1);a("cf3",0,-1,1);a("cf4",0,1,1);a("cn1",-1,0,-1);a("cn2",1,0,-1);a("cn3",0,-1,-1);a("cn4",0,1,-1);this.geometry.verticesNeedUpdate=!0};THREE.CameraHelper.__projector=new THREE.Projector;THREE.CameraHelper.__v=new THREE.Vector3;THREE.CameraHelper.__c=new THREE.Camera;
+THREE.DirectionalLightHelper=function(a,b,c){THREE.Object3D.call(this);this.light=a;this.position=a.position;this.direction=new THREE.Vector3;this.direction.sub(a.target.position,a.position);this.color=a.color.clone();var d=THREE.Math.clamp(a.intensity,0,1);this.color.r*=d;this.color.g*=d;this.color.b*=d;var d=this.color.getHex(),e=new THREE.SphereGeometry(b,16,8),f=new THREE.AsteriskGeometry(1.25*b,2.25*b),g=new THREE.MeshBasicMaterial({color:d,fog:!1}),h=new THREE.LineBasicMaterial({color:d,fog:!1});
+this.lightArrow=new THREE.ArrowHelper(this.direction,null,c,d);this.lightSphere=new THREE.Mesh(e,g);this.lightArrow.cone.material.fog=!1;this.lightArrow.line.material.fog=!1;this.lightRays=new THREE.Line(f,h,THREE.LinePieces);this.add(this.lightArrow);this.add(this.lightSphere);this.add(this.lightRays);this.lightSphere.properties.isGizmo=!0;this.lightSphere.properties.gizmoSubject=a;this.lightSphere.properties.gizmoRoot=this;this.targetSphere=null;a.target.properties.targetInverse&&(b=new THREE.SphereGeometry(b,
+8,4),c=new THREE.MeshBasicMaterial({color:d,wireframe:!0,fog:!1}),this.targetSphere=new THREE.Mesh(b,c),this.targetSphere.position=a.target.position,this.targetSphere.properties.isGizmo=!0,this.targetSphere.properties.gizmoSubject=a.target,this.targetSphere.properties.gizmoRoot=this.targetSphere,a=new THREE.LineDashedMaterial({color:d,dashSize:4,gapSize:4,opacity:0.75,transparent:!0,fog:!1}),d=new THREE.Geometry,d.vertices.push(this.position.clone()),d.vertices.push(this.targetSphere.position.clone()),
+d.computeLineDistances(),this.targetLine=new THREE.Line(d,a),this.targetLine.properties.isGizmo=!0);this.properties.isGizmo=!0};THREE.DirectionalLightHelper.prototype=Object.create(THREE.Object3D.prototype);
+THREE.DirectionalLightHelper.prototype.update=function(){this.direction.sub(this.light.target.position,this.light.position);this.lightArrow.setDirection(this.direction);this.color.copy(this.light.color);var a=THREE.Math.clamp(this.light.intensity,0,1);this.color.r*=a;this.color.g*=a;this.color.b*=a;this.lightArrow.setColor(this.color.getHex());this.lightSphere.material.color.copy(this.color);this.lightRays.material.color.copy(this.color);this.targetSphere.material.color.copy(this.color);this.targetLine.material.color.copy(this.color);
+this.targetLine.geometry.vertices[0].copy(this.light.position);this.targetLine.geometry.vertices[1].copy(this.light.target.position);this.targetLine.geometry.computeLineDistances();this.targetLine.geometry.verticesNeedUpdate=!0};
+THREE.HemisphereLightHelper=function(a,b,c){THREE.Object3D.call(this);this.light=a;this.position=a.position;var d=THREE.Math.clamp(a.intensity,0,1);this.color=a.color.clone();this.color.r*=d;this.color.g*=d;this.color.b*=d;var e=this.color.getHex();this.groundColor=a.groundColor.clone();this.groundColor.r*=d;this.groundColor.g*=d;this.groundColor.b*=d;for(var d=this.groundColor.getHex(),f=new THREE.SphereGeometry(b,16,8,0,2*Math.PI,0,0.5*Math.PI),g=new THREE.SphereGeometry(b,16,8,0,2*Math.PI,0.5*
+Math.PI,Math.PI),h=new THREE.MeshBasicMaterial({color:e,fog:!1}),i=new THREE.MeshBasicMaterial({color:d,fog:!1}),j=0,l=f.faces.length;j<l;j++)f.faces[j].materialIndex=0;j=0;for(l=g.faces.length;j<l;j++)g.faces[j].materialIndex=1;THREE.GeometryUtils.merge(f,g);this.lightSphere=new THREE.Mesh(f,new THREE.MeshFaceMaterial([h,i]));this.lightArrow=new THREE.ArrowHelper(new THREE.Vector3(0,1,0),new THREE.Vector3(0,1.1*(b+c),0),c,e);this.lightArrow.rotation.x=Math.PI;this.lightArrowGround=new THREE.ArrowHelper(new THREE.Vector3(0,
+1,0),new THREE.Vector3(0,-1.1*(b+c),0),c,d);b=new THREE.Object3D;b.rotation.x=0.5*-Math.PI;b.add(this.lightSphere);b.add(this.lightArrow);b.add(this.lightArrowGround);this.add(b);this.lightSphere.properties.isGizmo=!0;this.lightSphere.properties.gizmoSubject=a;this.lightSphere.properties.gizmoRoot=this;this.properties.isGizmo=!0;this.target=new THREE.Vector3;this.lookAt(this.target)};THREE.HemisphereLightHelper.prototype=Object.create(THREE.Object3D.prototype);
+THREE.HemisphereLightHelper.prototype.update=function(){var a=THREE.Math.clamp(this.light.intensity,0,1);this.color.copy(this.light.color);this.groundColor.copy(this.light.groundColor);this.color.r*=a;this.color.g*=a;this.color.b*=a;this.groundColor.r*=a;this.groundColor.g*=a;this.groundColor.b*=a;this.lightSphere.material.materials[0].color.copy(this.color);this.lightSphere.material.materials[1].color.copy(this.groundColor);this.lightArrow.setColor(this.color.getHex());this.lightArrowGround.setColor(this.groundColor.getHex());
+this.lookAt(this.target)};
+THREE.PointLightHelper=function(a,b){THREE.Object3D.call(this);this.light=a;this.position=a.position;this.color=a.color.clone();var c=THREE.Math.clamp(a.intensity,0,1);this.color.r*=c;this.color.g*=c;this.color.b*=c;var d=this.color.getHex(),c=new THREE.SphereGeometry(b,16,8),e=new THREE.AsteriskGeometry(1.25*b,2.25*b),f=new THREE.IcosahedronGeometry(1,2),g=new THREE.MeshBasicMaterial({color:d,fog:!1}),h=new THREE.LineBasicMaterial({color:d,fog:!1}),d=new THREE.MeshBasicMaterial({color:d,fog:!1,wireframe:!0,
+opacity:0.1,transparent:!0});this.lightSphere=new THREE.Mesh(c,g);this.lightRays=new THREE.Line(e,h,THREE.LinePieces);this.lightDistance=new THREE.Mesh(f,d);c=a.distance;0===c?this.lightDistance.visible=!1:this.lightDistance.scale.set(c,c,c);this.add(this.lightSphere);this.add(this.lightRays);this.add(this.lightDistance);this.lightSphere.properties.isGizmo=!0;this.lightSphere.properties.gizmoSubject=a;this.lightSphere.properties.gizmoRoot=this;this.properties.isGizmo=!0};
+THREE.PointLightHelper.prototype=Object.create(THREE.Object3D.prototype);
+THREE.PointLightHelper.prototype.update=function(){this.color.copy(this.light.color);var a=THREE.Math.clamp(this.light.intensity,0,1);this.color.r*=a;this.color.g*=a;this.color.b*=a;this.lightSphere.material.color.copy(this.color);this.lightRays.material.color.copy(this.color);this.lightDistance.material.color.copy(this.color);a=this.light.distance;0===a?this.lightDistance.visible=!1:(this.lightDistance.visible=!0,this.lightDistance.scale.set(a,a,a))};
+THREE.SpotLightHelper=function(a,b,c){THREE.Object3D.call(this);this.light=a;this.position=a.position;this.direction=new THREE.Vector3;this.direction.sub(a.target.position,a.position);this.color=a.color.clone();var d=THREE.Math.clamp(a.intensity,0,1);this.color.r*=d;this.color.g*=d;this.color.b*=d;var d=this.color.getHex(),e=new THREE.SphereGeometry(b,16,8),f=new THREE.AsteriskGeometry(1.25*b,2.25*b),g=new THREE.CylinderGeometry(1E-4,1,1,8,1,!0),h=new THREE.Matrix4;h.rotateX(-Math.PI/2);h.translate(new THREE.Vector3(0,
+-0.5,0));g.applyMatrix(h);var i=new THREE.MeshBasicMaterial({color:d,fog:!1}),h=new THREE.LineBasicMaterial({color:d,fog:!1}),j=new THREE.MeshBasicMaterial({color:d,fog:!1,wireframe:!0,opacity:0.3,transparent:!0});this.lightArrow=new THREE.ArrowHelper(this.direction,null,c,d);this.lightSphere=new THREE.Mesh(e,i);this.lightCone=new THREE.Mesh(g,j);c=a.distance?a.distance:1E4;e=2*c*Math.tan(0.5*a.angle);this.lightCone.scale.set(e,e,c);this.lightArrow.cone.material.fog=!1;this.lightArrow.line.material.fog=
+!1;this.lightRays=new THREE.Line(f,h,THREE.LinePieces);this.gyroscope=new THREE.Gyroscope;this.gyroscope.add(this.lightArrow);this.gyroscope.add(this.lightSphere);this.gyroscope.add(this.lightRays);this.add(this.gyroscope);this.add(this.lightCone);this.lookAt(a.target.position);this.lightSphere.properties.isGizmo=!0;this.lightSphere.properties.gizmoSubject=a;this.lightSphere.properties.gizmoRoot=this;this.targetSphere=null;a.target.properties.targetInverse&&(b=new THREE.SphereGeometry(b,8,4),f=new THREE.MeshBasicMaterial({color:d,
+wireframe:!0,fog:!1}),this.targetSphere=new THREE.Mesh(b,f),this.targetSphere.position=a.target.position,this.targetSphere.properties.isGizmo=!0,this.targetSphere.properties.gizmoSubject=a.target,this.targetSphere.properties.gizmoRoot=this.targetSphere,a=new THREE.LineDashedMaterial({color:d,dashSize:4,gapSize:4,opacity:0.75,transparent:!0,fog:!1}),d=new THREE.Geometry,d.vertices.push(this.position.clone()),d.vertices.push(this.targetSphere.position.clone()),d.computeLineDistances(),this.targetLine=
+new THREE.Line(d,a),this.targetLine.properties.isGizmo=!0);this.properties.isGizmo=!0};THREE.SpotLightHelper.prototype=Object.create(THREE.Object3D.prototype);
+THREE.SpotLightHelper.prototype.update=function(){this.direction.sub(this.light.target.position,this.light.position);this.lightArrow.setDirection(this.direction);this.lookAt(this.light.target.position);var a=this.light.distance?this.light.distance:1E4,b=2*a*Math.tan(0.5*this.light.angle);this.lightCone.scale.set(b,b,a);this.color.copy(this.light.color);a=THREE.Math.clamp(this.light.intensity,0,1);this.color.r*=a;this.color.g*=a;this.color.b*=a;this.lightArrow.setColor(this.color.getHex());this.lightSphere.material.color.copy(this.color);
+this.lightRays.material.color.copy(this.color);this.lightCone.material.color.copy(this.color);this.targetSphere.material.color.copy(this.color);this.targetLine.material.color.copy(this.color);this.targetLine.geometry.vertices[0].copy(this.light.position);this.targetLine.geometry.vertices[1].copy(this.light.target.position);this.targetLine.geometry.computeLineDistances();this.targetLine.geometry.verticesNeedUpdate=!0};
+THREE.SubdivisionModifier=function(a){this.subdivisions=void 0===a?1:a;this.useOldVertexColors=!1;this.supportUVs=!0;this.debug=!1};THREE.SubdivisionModifier.prototype.modify=function(a){for(var b=this.subdivisions;0<b--;)this.smooth(a)};THREE.GeometryUtils.orderedKey=function(a,b){return Math.min(a,b)+"_"+Math.max(a,b)};
+THREE.GeometryUtils.computeEdgeFaces=function(a){function b(a,b){void 0===g[a]&&(g[a]=[]);g[a].push(b)}var c,d,e,f,g={},h=THREE.GeometryUtils.orderedKey;c=0;for(d=a.faces.length;c<d;c++)e=a.faces[c],e instanceof THREE.Face3?(f=h(e.a,e.b),b(f,c),f=h(e.b,e.c),b(f,c),f=h(e.c,e.a),b(f,c)):e instanceof THREE.Face4&&(f=h(e.a,e.b),b(f,c),f=h(e.b,e.c),b(f,c),f=h(e.c,e.d),b(f,c),f=h(e.d,e.a),b(f,c));return g};
+THREE.SubdivisionModifier.prototype.smooth=function(a){function b(){l.debug&&(console&&console.assert)&&console.assert.apply(console,arguments)}function c(){l.debug&&console.log.apply(console,arguments)}function d(){console&&console.log.apply(console,arguments)}function e(a,b,d,e,g,h,m){var n=new THREE.Face4(a,b,d,e,null,g.color,g.materialIndex);if(l.useOldVertexColors){n.vertexColors=[];for(var o,p,q,r=0;4>r;r++){q=h[r];o=new THREE.Color;o.setRGB(0,0,0);for(var s=0;s<q.length;s++)p=g.vertexColors[q[s]-
+1],o.r+=p.r,o.g+=p.g,o.b+=p.b;o.r/=q.length;o.g/=q.length;o.b/=q.length;n.vertexColors[r]=o}}i.push(n);l.supportUVs&&(g=[f(a,""),f(b,m),f(d,m),f(e,m)],g[0]?g[1]?g[2]?g[3]?j.push(g):c("d :( ",e+":"+m):c("c :( ",d+":"+m):c("b :( ",b+":"+m):c("a :( ",a+":"+m))}function f(a,b){var e=a+":"+b,f=w[e];return!f?(a>=s&&a<s+o.length?c("face pt"):c("edge pt"),d("warning, UV not found for",e),null):f}function g(a,b,c){var e=a+":"+b;e in w?d("dup vertexNo",a,"oldFaceNo",b,"value",c,"key",e,w[e]):w[e]=c}var h=[],
+i=[],j=[],l=this,m=THREE.GeometryUtils.orderedKey,n=THREE.GeometryUtils.computeEdgeFaces,p=a.vertices,o=a.faces,s=p.length,h=p.concat(),t=[],r={},z={},w={},q,E,A,v,u,D=a.faceVertexUvs[0],C;c("originalFaces, uvs, originalVerticesLength",o.length,D.length,s);if(l.supportUVs){q=0;for(E=D.length;q<E;q++){A=0;for(v=D[q].length;A<v;A++)C=o[q]["abcd".charAt(A)],g(C,q,D[q][A])}}0==D.length&&(l.supportUVs=!1);q=0;for(var G in w)q++;q||(l.supportUVs=!1,c("no uvs"));q=0;for(E=o.length;q<E;q++)u=o[q],t.push(u.centroid),
+h.push(u.centroid),l.supportUVs&&(v=new THREE.UV,u instanceof THREE.Face3?(v.u=f(u.a,q).u+f(u.b,q).u+f(u.c,q).u,v.v=f(u.a,q).v+f(u.b,q).v+f(u.c,q).v,v.u/=3,v.v/=3):u instanceof THREE.Face4&&(v.u=f(u.a,q).u+f(u.b,q).u+f(u.c,q).u+f(u.d,q).u,v.v=f(u.a,q).v+f(u.b,q).v+f(u.c,q).v+f(u.d,q).v,v.u/=4,v.v/=4),g(s+q,"",v));var n=n(a),P;E=0;var B,K;G={};D={};for(q in n){C=n[q];B=q.split("_");K=B[0];B=B[1];A=K;u=[K,B];void 0===G[A]&&(G[A]=[]);G[A].push(u);A=B;u=[K,B];void 0===G[A]&&(G[A]=[]);G[A].push(u);A=0;
+for(v=C.length;A<v;A++){u=C[A];P=K;var H=u,I=q;void 0===D[P]&&(D[P]={});D[P][H]=I;P=B;H=q;void 0===D[P]&&(D[P]={});D[P][u]=H}2>C.length&&(z[q]=!0)}for(q in n)if(C=n[q],u=C[0],P=C[1],B=q.split("_"),K=B[0],B=B[1],v=new THREE.Vector3,b(0<C.length,"an edge without faces?!"),1==C.length?(v.addSelf(p[K]),v.addSelf(p[B]),v.multiplyScalar(0.5)):(v.addSelf(t[u]),v.addSelf(t[P]),v.addSelf(p[K]),v.addSelf(p[B]),v.multiplyScalar(0.25)),r[q]=s+o.length+E,h.push(v),E++,l.supportUVs)v=new THREE.UV,v.u=f(K,u).u+
+f(B,u).u,v.v=f(K,u).v+f(B,u).v,v.u/=2,v.v/=2,g(r[q],u,v),2<=C.length&&(b(2==C.length,"did we plan for more than 2 edges?"),v=new THREE.UV,v.u=f(K,P).u+f(B,P).u,v.v=f(K,P).v+f(B,P).v,v.u/=2,v.v/=2,g(r[q],P,v));c("-- Step 2 done");var N,O;v=["123","12","2","23"];P=["123","23","3","31"];var H=["123","31","1","12"],I=["1234","12","2","23"],R=["1234","23","3","34"],ga=["1234","34","4","41"],M=["1234","41","1","12"];q=0;for(E=t.length;q<E;q++)u=o[q],C=s+q,u instanceof THREE.Face3?(K=m(u.a,u.b),B=m(u.b,
+u.c),N=m(u.c,u.a),e(C,r[K],u.b,r[B],u,v,q),e(C,r[B],u.c,r[N],u,P,q),e(C,r[N],u.a,r[K],u,H,q)):u instanceof THREE.Face4?(K=m(u.a,u.b),B=m(u.b,u.c),N=m(u.c,u.d),O=m(u.d,u.a),e(C,r[K],u.b,r[B],u,I,q),e(C,r[B],u.c,r[N],u,R,q),e(C,r[N],u.d,r[O],u,ga,q),e(C,r[O],u.a,r[K],u,M,q)):c("face should be a face!",u);r=new THREE.Vector3;u=new THREE.Vector3;q=0;for(E=p.length;q<E;q++)if(void 0!==G[q]){r.set(0,0,0);u.set(0,0,0);B=new THREE.Vector3(0,0,0);C=0;for(A in D[q])r.addSelf(t[A]),C++;P=0;K=G[q].length;v=C!=
+K;for(A=0;A<K;A++)z[m(G[q][A][0],G[q][A][1])]&&P++;r.divideScalar(C);P=0;if(v){for(A=0;A<K;A++)if(C=G[q][A],H=1==n[m(C[0],C[1])].length)C=p[C[0]].clone().addSelf(p[C[1]]).divideScalar(2),u.addSelf(C),P++;u.divideScalar(4);b(2==P,"should have only 2 boundary edges")}else{for(A=0;A<K;A++)C=G[q][A],C=p[C[0]].clone().addSelf(p[C[1]]).divideScalar(2),u.addSelf(C);u.divideScalar(K)}B.addSelf(p[q]);v?(B.divideScalar(2),B.addSelf(u)):(B.multiplyScalar(K-3),B.addSelf(r),B.addSelf(u.multiplyScalar(2)),B.divideScalar(K));
+h[q]=B}a.vertices=h;a.faces=i;a.faceVertexUvs[0]=j;delete a.__tmpVertices;a.computeCentroids();a.computeFaceNormals();a.computeVertexNormals()};THREE.ImmediateRenderObject=function(){THREE.Object3D.call(this);this.render=function(){}};THREE.ImmediateRenderObject.prototype=Object.create(THREE.Object3D.prototype);THREE.LensFlare=function(a,b,c,d,e){THREE.Object3D.call(this);this.lensFlares=[];this.positionScreen=new THREE.Vector3;this.customUpdateCallback=void 0;void 0!==a&&this.add(a,b,c,d,e)};
+THREE.LensFlare.prototype=Object.create(THREE.Object3D.prototype);THREE.LensFlare.prototype.add=function(a,b,c,d,e,f){void 0===b&&(b=-1);void 0===c&&(c=0);void 0===f&&(f=1);void 0===e&&(e=new THREE.Color(16777215));void 0===d&&(d=THREE.NormalBlending);c=Math.min(c,Math.max(0,c));this.lensFlares.push({texture:a,size:b,distance:c,x:0,y:0,z:0,scale:1,rotation:1,opacity:f,color:e,blending:d})};
+THREE.LensFlare.prototype.updateLensFlares=function(){var a,b=this.lensFlares.length,c,d=2*-this.positionScreen.x,e=2*-this.positionScreen.y;for(a=0;a<b;a++)c=this.lensFlares[a],c.x=this.positionScreen.x+d*c.distance,c.y=this.positionScreen.y+e*c.distance,c.wantedRotation=0.25*c.x*Math.PI,c.rotation+=0.25*(c.wantedRotation-c.rotation)};
+THREE.MorphBlendMesh=function(a,b){THREE.Mesh.call(this,a,b);this.animationsMap={};this.animationsList=[];var c=this.geometry.morphTargets.length;this.createAnimation("__default",0,c-1,c/1);this.setAnimationWeight("__default",1)};THREE.MorphBlendMesh.prototype=Object.create(THREE.Mesh.prototype);
+THREE.MorphBlendMesh.prototype.createAnimation=function(a,b,c,d){b={startFrame:b,endFrame:c,length:c-b+1,fps:d,duration:(c-b)/d,lastFrame:0,currentFrame:0,active:!1,time:0,direction:1,weight:1,directionBackwards:!1,mirroredLoop:!1};this.animationsMap[a]=b;this.animationsList.push(b)};
+THREE.MorphBlendMesh.prototype.autoCreateAnimations=function(a){for(var b=/([a-z]+)(\d+)/,c,d={},e=this.geometry,f=0,g=e.morphTargets.length;f<g;f++){var h=e.morphTargets[f].name.match(b);if(h&&1<h.length){var i=h[1];d[i]||(d[i]={start:Infinity,end:-Infinity});h=d[i];f<h.start&&(h.start=f);f>h.end&&(h.end=f);c||(c=i)}}for(i in d)h=d[i],this.createAnimation(i,h.start,h.end,a);this.firstAnimation=c};
+THREE.MorphBlendMesh.prototype.setAnimationDirectionForward=function(a){if(a=this.animationsMap[a])a.direction=1,a.directionBackwards=!1};THREE.MorphBlendMesh.prototype.setAnimationDirectionBackward=function(a){if(a=this.animationsMap[a])a.direction=-1,a.directionBackwards=!0};THREE.MorphBlendMesh.prototype.setAnimationFPS=function(a,b){var c=this.animationsMap[a];c&&(c.fps=b,c.duration=(c.end-c.start)/c.fps)};
+THREE.MorphBlendMesh.prototype.setAnimationDuration=function(a,b){var c=this.animationsMap[a];c&&(c.duration=b,c.fps=(c.end-c.start)/c.duration)};THREE.MorphBlendMesh.prototype.setAnimationWeight=function(a,b){var c=this.animationsMap[a];c&&(c.weight=b)};THREE.MorphBlendMesh.prototype.setAnimationTime=function(a,b){var c=this.animationsMap[a];c&&(c.time=b)};THREE.MorphBlendMesh.prototype.getAnimationTime=function(a){var b=0;if(a=this.animationsMap[a])b=a.time;return b};
+THREE.MorphBlendMesh.prototype.getAnimationDuration=function(a){var b=-1;if(a=this.animationsMap[a])b=a.duration;return b};THREE.MorphBlendMesh.prototype.playAnimation=function(a){var b=this.animationsMap[a];b?(b.time=0,b.active=!0):console.warn("animation["+a+"] undefined")};THREE.MorphBlendMesh.prototype.stopAnimation=function(a){if(a=this.animationsMap[a])a.active=!1};
+THREE.MorphBlendMesh.prototype.update=function(a){for(var b=0,c=this.animationsList.length;b<c;b++){var d=this.animationsList[b];if(d.active){var e=d.duration/d.length;d.time+=d.direction*a;if(d.mirroredLoop){if(d.time>d.duration||0>d.time)if(d.direction*=-1,d.time>d.duration&&(d.time=d.duration,d.directionBackwards=!0),0>d.time)d.time=0,d.directionBackwards=!1}else d.time%=d.duration,0>d.time&&(d.time+=d.duration);var f=d.startFrame+THREE.Math.clamp(Math.floor(d.time/e),0,d.length-1),g=d.weight;
+f!==d.currentFrame&&(this.morphTargetInfluences[d.lastFrame]=0,this.morphTargetInfluences[d.currentFrame]=1*g,this.morphTargetInfluences[f]=0,d.lastFrame=d.currentFrame,d.currentFrame=f);e=d.time%e/e;d.directionBackwards&&(e=1-e);this.morphTargetInfluences[d.currentFrame]=e*g;this.morphTargetInfluences[d.lastFrame]=(1-e)*g}}};
+THREE.LensFlarePlugin=function(){function a(a){var c=b.createProgram(),d=b.createShader(b.FRAGMENT_SHADER),e=b.createShader(b.VERTEX_SHADER);b.shaderSource(d,a.fragmentShader);b.shaderSource(e,a.vertexShader);b.compileShader(d);b.compileShader(e);b.attachShader(c,d);b.attachShader(c,e);b.linkProgram(c);return c}var b,c,d,e,f,g,h,i,j,l,m,n,p;this.init=function(o){b=o.context;c=o;d=new Float32Array(16);e=new Uint16Array(6);o=0;d[o++]=-1;d[o++]=-1;d[o++]=0;d[o++]=0;d[o++]=1;d[o++]=-1;d[o++]=1;d[o++]=
+0;d[o++]=1;d[o++]=1;d[o++]=1;d[o++]=1;d[o++]=-1;d[o++]=1;d[o++]=0;d[o++]=1;o=0;e[o++]=0;e[o++]=1;e[o++]=2;e[o++]=0;e[o++]=2;e[o++]=3;f=b.createBuffer();g=b.createBuffer();b.bindBuffer(b.ARRAY_BUFFER,f);b.bufferData(b.ARRAY_BUFFER,d,b.STATIC_DRAW);b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,g);b.bufferData(b.ELEMENT_ARRAY_BUFFER,e,b.STATIC_DRAW);h=b.createTexture();i=b.createTexture();b.bindTexture(b.TEXTURE_2D,h);b.texImage2D(b.TEXTURE_2D,0,b.RGB,16,16,0,b.RGB,b.UNSIGNED_BYTE,null);b.texParameteri(b.TEXTURE_2D,
+b.TEXTURE_WRAP_S,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MAG_FILTER,b.NEAREST);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MIN_FILTER,b.NEAREST);b.bindTexture(b.TEXTURE_2D,i);b.texImage2D(b.TEXTURE_2D,0,b.RGBA,16,16,0,b.RGBA,b.UNSIGNED_BYTE,null);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MAG_FILTER,b.NEAREST);
+b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MIN_FILTER,b.NEAREST);0>=b.getParameter(b.MAX_VERTEX_TEXTURE_IMAGE_UNITS)?(j=!1,l=a(THREE.ShaderFlares.lensFlare)):(j=!0,l=a(THREE.ShaderFlares.lensFlareVertexTexture));m={};n={};m.vertex=b.getAttribLocation(l,"position");m.uv=b.getAttribLocation(l,"uv");n.renderType=b.getUniformLocation(l,"renderType");n.map=b.getUniformLocation(l,"map");n.occlusionMap=b.getUniformLocation(l,"occlusionMap");n.opacity=b.getUniformLocation(l,"opacity");n.color=b.getUniformLocation(l,
+"color");n.scale=b.getUniformLocation(l,"scale");n.rotation=b.getUniformLocation(l,"rotation");n.screenPosition=b.getUniformLocation(l,"screenPosition");p=!1};this.render=function(a,d,e,r){var a=a.__webglFlares,z=a.length;if(z){var w=new THREE.Vector3,q=r/e,E=0.5*e,A=0.5*r,v=16/r,u=new THREE.Vector2(v*q,v),D=new THREE.Vector3(1,1,0),C=new THREE.Vector2(1,1),G=n,v=m;b.useProgram(l);p||(b.enableVertexAttribArray(m.vertex),b.enableVertexAttribArray(m.uv),p=!0);b.uniform1i(G.occlusionMap,0);b.uniform1i(G.map,
+1);b.bindBuffer(b.ARRAY_BUFFER,f);b.vertexAttribPointer(v.vertex,2,b.FLOAT,!1,16,0);b.vertexAttribPointer(v.uv,2,b.FLOAT,!1,16,8);b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,g);b.disable(b.CULL_FACE);b.depthMask(!1);var P,B,K,H,I;for(P=0;P<z;P++)if(v=16/r,u.set(v*q,v),H=a[P],w.set(H.matrixWorld.elements[12],H.matrixWorld.elements[13],H.matrixWorld.elements[14]),d.matrixWorldInverse.multiplyVector3(w),d.projectionMatrix.multiplyVector3(w),D.copy(w),C.x=D.x*E+E,C.y=D.y*A+A,j||0<C.x&&C.x<e&&0<C.y&&C.y<r){b.activeTexture(b.TEXTURE1);
+b.bindTexture(b.TEXTURE_2D,h);b.copyTexImage2D(b.TEXTURE_2D,0,b.RGB,C.x-8,C.y-8,16,16,0);b.uniform1i(G.renderType,0);b.uniform2f(G.scale,u.x,u.y);b.uniform3f(G.screenPosition,D.x,D.y,D.z);b.disable(b.BLEND);b.enable(b.DEPTH_TEST);b.drawElements(b.TRIANGLES,6,b.UNSIGNED_SHORT,0);b.activeTexture(b.TEXTURE0);b.bindTexture(b.TEXTURE_2D,i);b.copyTexImage2D(b.TEXTURE_2D,0,b.RGBA,C.x-8,C.y-8,16,16,0);b.uniform1i(G.renderType,1);b.disable(b.DEPTH_TEST);b.activeTexture(b.TEXTURE1);b.bindTexture(b.TEXTURE_2D,
+h);b.drawElements(b.TRIANGLES,6,b.UNSIGNED_SHORT,0);H.positionScreen.copy(D);H.customUpdateCallback?H.customUpdateCallback(H):H.updateLensFlares();b.uniform1i(G.renderType,2);b.enable(b.BLEND);B=0;for(K=H.lensFlares.length;B<K;B++)I=H.lensFlares[B],0.001<I.opacity&&0.001<I.scale&&(D.x=I.x,D.y=I.y,D.z=I.z,v=I.size*I.scale/r,u.x=v*q,u.y=v,b.uniform3f(G.screenPosition,D.x,D.y,D.z),b.uniform2f(G.scale,u.x,u.y),b.uniform1f(G.rotation,I.rotation),b.uniform1f(G.opacity,I.opacity),b.uniform3f(G.color,I.color.r,
+I.color.g,I.color.b),c.setBlending(I.blending,I.blendEquation,I.blendSrc,I.blendDst),c.setTexture(I.texture,1),b.drawElements(b.TRIANGLES,6,b.UNSIGNED_SHORT,0))}b.enable(b.CULL_FACE);b.enable(b.DEPTH_TEST);b.depthMask(!0)}}};
+THREE.ShadowMapPlugin=function(){var a,b,c,d,e,f,g=new THREE.Frustum,h=new THREE.Matrix4,i=new THREE.Vector3,j=new THREE.Vector3;this.init=function(g){a=g.context;b=g;var g=THREE.ShaderLib.depthRGBA,h=THREE.UniformsUtils.clone(g.uniforms);c=new THREE.ShaderMaterial({fragmentShader:g.fragmentShader,vertexShader:g.vertexShader,uniforms:h});d=new THREE.ShaderMaterial({fragmentShader:g.fragmentShader,vertexShader:g.vertexShader,uniforms:h,morphTargets:!0});e=new THREE.ShaderMaterial({fragmentShader:g.fragmentShader,
+vertexShader:g.vertexShader,uniforms:h,skinning:!0});f=new THREE.ShaderMaterial({fragmentShader:g.fragmentShader,vertexShader:g.vertexShader,uniforms:h,morphTargets:!0,skinning:!0});c._shadowPass=!0;d._shadowPass=!0;e._shadowPass=!0;f._shadowPass=!0};this.render=function(a,c){b.shadowMapEnabled&&b.shadowMapAutoUpdate&&this.update(a,c)};this.update=function(l,m){var n,p,o,s,t,r,z,w,q,E=[];s=0;a.clearColor(1,1,1,1);a.disable(a.BLEND);a.enable(a.CULL_FACE);a.frontFace(a.CCW);b.shadowMapCullFrontFaces?
+a.cullFace(a.FRONT):a.cullFace(a.BACK);b.setDepthTest(!0);n=0;for(p=l.__lights.length;n<p;n++)if(o=l.__lights[n],o.castShadow)if(o instanceof THREE.DirectionalLight&&o.shadowCascade)for(t=0;t<o.shadowCascadeCount;t++){var A;if(o.shadowCascadeArray[t])A=o.shadowCascadeArray[t];else{q=o;z=t;A=new THREE.DirectionalLight;A.isVirtual=!0;A.onlyShadow=!0;A.castShadow=!0;A.shadowCameraNear=q.shadowCameraNear;A.shadowCameraFar=q.shadowCameraFar;A.shadowCameraLeft=q.shadowCameraLeft;A.shadowCameraRight=q.shadowCameraRight;
+A.shadowCameraBottom=q.shadowCameraBottom;A.shadowCameraTop=q.shadowCameraTop;A.shadowCameraVisible=q.shadowCameraVisible;A.shadowDarkness=q.shadowDarkness;A.shadowBias=q.shadowCascadeBias[z];A.shadowMapWidth=q.shadowCascadeWidth[z];A.shadowMapHeight=q.shadowCascadeHeight[z];A.pointsWorld=[];A.pointsFrustum=[];w=A.pointsWorld;r=A.pointsFrustum;for(var v=0;8>v;v++)w[v]=new THREE.Vector3,r[v]=new THREE.Vector3;w=q.shadowCascadeNearZ[z];q=q.shadowCascadeFarZ[z];r[0].set(-1,-1,w);r[1].set(1,-1,w);r[2].set(-1,
+1,w);r[3].set(1,1,w);r[4].set(-1,-1,q);r[5].set(1,-1,q);r[6].set(-1,1,q);r[7].set(1,1,q);A.originalCamera=m;r=new THREE.Gyroscope;r.position=o.shadowCascadeOffset;r.add(A);r.add(A.target);m.add(r);o.shadowCascadeArray[t]=A;console.log("Created virtualLight",A)}z=o;w=t;q=z.shadowCascadeArray[w];q.position.copy(z.position);q.target.position.copy(z.target.position);q.lookAt(q.target);q.shadowCameraVisible=z.shadowCameraVisible;q.shadowDarkness=z.shadowDarkness;q.shadowBias=z.shadowCascadeBias[w];r=z.shadowCascadeNearZ[w];
+z=z.shadowCascadeFarZ[w];q=q.pointsFrustum;q[0].z=r;q[1].z=r;q[2].z=r;q[3].z=r;q[4].z=z;q[5].z=z;q[6].z=z;q[7].z=z;E[s]=A;s++}else E[s]=o,s++;n=0;for(p=E.length;n<p;n++){o=E[n];o.shadowMap||(o.shadowMap=new THREE.WebGLRenderTarget(o.shadowMapWidth,o.shadowMapHeight,{minFilter:THREE.LinearFilter,magFilter:THREE.LinearFilter,format:THREE.RGBAFormat}),o.shadowMapSize=new THREE.Vector2(o.shadowMapWidth,o.shadowMapHeight),o.shadowMatrix=new THREE.Matrix4);if(!o.shadowCamera){if(o instanceof THREE.SpotLight)o.shadowCamera=
+new THREE.PerspectiveCamera(o.shadowCameraFov,o.shadowMapWidth/o.shadowMapHeight,o.shadowCameraNear,o.shadowCameraFar);else if(o instanceof THREE.DirectionalLight)o.shadowCamera=new THREE.OrthographicCamera(o.shadowCameraLeft,o.shadowCameraRight,o.shadowCameraTop,o.shadowCameraBottom,o.shadowCameraNear,o.shadowCameraFar);else{console.error("Unsupported light type for shadow");continue}l.add(o.shadowCamera);b.autoUpdateScene&&l.updateMatrixWorld()}o.shadowCameraVisible&&!o.cameraHelper&&(o.cameraHelper=
+new THREE.CameraHelper(o.shadowCamera),o.shadowCamera.add(o.cameraHelper));if(o.isVirtual&&A.originalCamera==m){t=m;s=o.shadowCamera;r=o.pointsFrustum;q=o.pointsWorld;i.set(Infinity,Infinity,Infinity);j.set(-Infinity,-Infinity,-Infinity);for(z=0;8>z;z++)if(w=q[z],w.copy(r[z]),THREE.ShadowMapPlugin.__projector.unprojectVector(w,t),s.matrixWorldInverse.multiplyVector3(w),w.x<i.x&&(i.x=w.x),w.x>j.x&&(j.x=w.x),w.y<i.y&&(i.y=w.y),w.y>j.y&&(j.y=w.y),w.z<i.z&&(i.z=w.z),w.z>j.z)j.z=w.z;s.left=i.x;s.right=
+j.x;s.top=j.y;s.bottom=i.y;s.updateProjectionMatrix()}s=o.shadowMap;r=o.shadowMatrix;t=o.shadowCamera;t.position.copy(o.matrixWorld.getPosition());t.lookAt(o.target.matrixWorld.getPosition());t.updateMatrixWorld();t.matrixWorldInverse.getInverse(t.matrixWorld);o.cameraHelper&&(o.cameraHelper.visible=o.shadowCameraVisible);o.shadowCameraVisible&&o.cameraHelper.update();r.set(0.5,0,0,0.5,0,0.5,0,0.5,0,0,0.5,0.5,0,0,0,1);r.multiplySelf(t.projectionMatrix);r.multiplySelf(t.matrixWorldInverse);t._viewMatrixArray||
+(t._viewMatrixArray=new Float32Array(16));t._projectionMatrixArray||(t._projectionMatrixArray=new Float32Array(16));t.matrixWorldInverse.flattenToArray(t._viewMatrixArray);t.projectionMatrix.flattenToArray(t._projectionMatrixArray);h.multiply(t.projectionMatrix,t.matrixWorldInverse);g.setFromMatrix(h);b.setRenderTarget(s);b.clear();q=l.__webglObjects;o=0;for(s=q.length;o<s;o++)if(z=q[o],r=z.object,z.render=!1,r.visible&&r.castShadow&&(!(r instanceof THREE.Mesh||r instanceof THREE.ParticleSystem)||
+!r.frustumCulled||g.contains(r)))r._modelViewMatrix.multiply(t.matrixWorldInverse,r.matrixWorld),z.render=!0;o=0;for(s=q.length;o<s;o++)z=q[o],z.render&&(r=z.object,z=z.buffer,v=r.material instanceof THREE.MeshFaceMaterial?r.material.materials[0]:r.material,w=0<r.geometry.morphTargets.length&&v.morphTargets,v=r instanceof THREE.SkinnedMesh&&v.skinning,w=r.customDepthMaterial?r.customDepthMaterial:v?w?f:e:w?d:c,z instanceof THREE.BufferGeometry?b.renderBufferDirect(t,l.__lights,null,w,z,r):b.renderBuffer(t,
+l.__lights,null,w,z,r));q=l.__webglObjectsImmediate;o=0;for(s=q.length;o<s;o++)z=q[o],r=z.object,r.visible&&r.castShadow&&(r._modelViewMatrix.multiply(t.matrixWorldInverse,r.matrixWorld),b.renderImmediateObject(t,l.__lights,null,c,r))}n=b.getClearColor();p=b.getClearAlpha();a.clearColor(n.r,n.g,n.b,p);a.enable(a.BLEND);b.shadowMapCullFrontFaces&&a.cullFace(a.BACK)}};THREE.ShadowMapPlugin.__projector=new THREE.Projector;
+THREE.SpritePlugin=function(){function a(a,b){return a.z!==b.z?b.z-a.z:b.id-a.id}var b,c,d,e,f,g,h,i,j,l;this.init=function(a){b=a.context;c=a;d=new Float32Array(16);e=new Uint16Array(6);a=0;d[a++]=-1;d[a++]=-1;d[a++]=0;d[a++]=0;d[a++]=1;d[a++]=-1;d[a++]=1;d[a++]=0;d[a++]=1;d[a++]=1;d[a++]=1;d[a++]=1;d[a++]=-1;d[a++]=1;d[a++]=0;d[a++]=1;a=0;e[a++]=0;e[a++]=1;e[a++]=2;e[a++]=0;e[a++]=2;e[a++]=3;f=b.createBuffer();g=b.createBuffer();b.bindBuffer(b.ARRAY_BUFFER,f);b.bufferData(b.ARRAY_BUFFER,d,b.STATIC_DRAW);
+b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,g);b.bufferData(b.ELEMENT_ARRAY_BUFFER,e,b.STATIC_DRAW);var a=THREE.ShaderSprite.sprite,n=b.createProgram(),p=b.createShader(b.FRAGMENT_SHADER),o=b.createShader(b.VERTEX_SHADER);b.shaderSource(p,a.fragmentShader);b.shaderSource(o,a.vertexShader);b.compileShader(p);b.compileShader(o);b.attachShader(n,p);b.attachShader(n,o);b.linkProgram(n);h=n;i={};j={};i.position=b.getAttribLocation(h,"position");i.uv=b.getAttribLocation(h,"uv");j.uvOffset=b.getUniformLocation(h,
+"uvOffset");j.uvScale=b.getUniformLocation(h,"uvScale");j.rotation=b.getUniformLocation(h,"rotation");j.scale=b.getUniformLocation(h,"scale");j.alignment=b.getUniformLocation(h,"alignment");j.color=b.getUniformLocation(h,"color");j.map=b.getUniformLocation(h,"map");j.opacity=b.getUniformLocation(h,"opacity");j.useScreenCoordinates=b.getUniformLocation(h,"useScreenCoordinates");j.affectedByDistance=b.getUniformLocation(h,"affectedByDistance");j.screenPosition=b.getUniformLocation(h,"screenPosition");
+j.modelViewMatrix=b.getUniformLocation(h,"modelViewMatrix");j.projectionMatrix=b.getUniformLocation(h,"projectionMatrix");j.fogType=b.getUniformLocation(h,"fogType");j.fogDensity=b.getUniformLocation(h,"fogDensity");j.fogNear=b.getUniformLocation(h,"fogNear");j.fogFar=b.getUniformLocation(h,"fogFar");j.fogColor=b.getUniformLocation(h,"fogColor");l=!1};this.render=function(d,e,p,o){var s=d.__webglSprites,t=s.length;if(t){var r=i,z=j,w=o/p,p=0.5*p,q=0.5*o,E=!0;b.useProgram(h);l||(b.enableVertexAttribArray(r.position),
+b.enableVertexAttribArray(r.uv),l=!0);b.disable(b.CULL_FACE);b.enable(b.BLEND);b.depthMask(!0);b.bindBuffer(b.ARRAY_BUFFER,f);b.vertexAttribPointer(r.position,2,b.FLOAT,!1,16,0);b.vertexAttribPointer(r.uv,2,b.FLOAT,!1,16,8);b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,g);b.uniformMatrix4fv(z.projectionMatrix,!1,e._projectionMatrixArray);b.activeTexture(b.TEXTURE0);b.uniform1i(z.map,0);var A=r=0,v=d.fog;v?(b.uniform3f(z.fogColor,v.color.r,v.color.g,v.color.b),v instanceof THREE.Fog?(b.uniform1f(z.fogNear,v.near),
+b.uniform1f(z.fogFar,v.far),b.uniform1i(z.fogType,1),A=r=1):v instanceof THREE.FogExp2&&(b.uniform1f(z.fogDensity,v.density),b.uniform1i(z.fogType,2),A=r=2)):(b.uniform1i(z.fogType,0),A=r=0);for(var u,D=[],v=0;v<t;v++)u=s[v],u.visible&&0!==u.opacity&&(u.useScreenCoordinates?u.z=-u.position.z:(u._modelViewMatrix.multiply(e.matrixWorldInverse,u.matrixWorld),u.z=-u._modelViewMatrix.elements[14]));s.sort(a);for(v=0;v<t;v++)if(u=s[v],u.visible&&0!==u.opacity&&u.map&&u.map.image&&u.map.image.width)u.useScreenCoordinates?
+(b.uniform1i(z.useScreenCoordinates,1),b.uniform3f(z.screenPosition,(u.position.x-p)/p,(q-u.position.y)/q,Math.max(0,Math.min(1,u.position.z)))):(b.uniform1i(z.useScreenCoordinates,0),b.uniform1i(z.affectedByDistance,u.affectedByDistance?1:0),b.uniformMatrix4fv(z.modelViewMatrix,!1,u._modelViewMatrix.elements)),e=d.fog&&u.fog?A:0,r!==e&&(b.uniform1i(z.fogType,e),r=e),e=1/(u.scaleByViewport?o:1),D[0]=e*w*u.scale.x,D[1]=e*u.scale.y,b.uniform2f(z.uvScale,u.uvScale.x,u.uvScale.y),b.uniform2f(z.uvOffset,
+u.uvOffset.x,u.uvOffset.y),b.uniform2f(z.alignment,u.alignment.x,u.alignment.y),b.uniform1f(z.opacity,u.opacity),b.uniform3f(z.color,u.color.r,u.color.g,u.color.b),b.uniform1f(z.rotation,u.rotation),b.uniform2fv(z.scale,D),u.mergeWith3D&&!E?(b.enable(b.DEPTH_TEST),E=!0):!u.mergeWith3D&&E&&(b.disable(b.DEPTH_TEST),E=!1),c.setBlending(u.blending,u.blendEquation,u.blendSrc,u.blendDst),c.setTexture(u.map,0),b.drawElements(b.TRIANGLES,6,b.UNSIGNED_SHORT,0);b.enable(b.CULL_FACE);b.enable(b.DEPTH_TEST);
+b.depthMask(!0)}}};
+THREE.DepthPassPlugin=function(){this.enabled=!1;this.renderTarget=null;var a,b,c,d,e,f,g=new THREE.Frustum,h=new THREE.Matrix4;this.init=function(g){a=g.context;b=g;var g=THREE.ShaderLib.depthRGBA,h=THREE.UniformsUtils.clone(g.uniforms);c=new THREE.ShaderMaterial({fragmentShader:g.fragmentShader,vertexShader:g.vertexShader,uniforms:h});d=new THREE.ShaderMaterial({fragmentShader:g.fragmentShader,vertexShader:g.vertexShader,uniforms:h,morphTargets:!0});e=new THREE.ShaderMaterial({fragmentShader:g.fragmentShader,vertexShader:g.vertexShader,
+uniforms:h,skinning:!0});f=new THREE.ShaderMaterial({fragmentShader:g.fragmentShader,vertexShader:g.vertexShader,uniforms:h,morphTargets:!0,skinning:!0});c._shadowPass=!0;d._shadowPass=!0;e._shadowPass=!0;f._shadowPass=!0};this.render=function(a,b){this.enabled&&this.update(a,b)};this.update=function(i,j){var l,m,n,p,o,s;a.clearColor(1,1,1,1);a.disable(a.BLEND);b.setDepthTest(!0);b.autoUpdateScene&&i.updateMatrixWorld();j._viewMatrixArray||(j._viewMatrixArray=new Float32Array(16));j._projectionMatrixArray||
+(j._projectionMatrixArray=new Float32Array(16));j.matrixWorldInverse.getInverse(j.matrixWorld);j.matrixWorldInverse.flattenToArray(j._viewMatrixArray);j.projectionMatrix.flattenToArray(j._projectionMatrixArray);h.multiply(j.projectionMatrix,j.matrixWorldInverse);g.setFromMatrix(h);b.setRenderTarget(this.renderTarget);b.clear();s=i.__webglObjects;l=0;for(m=s.length;l<m;l++)if(n=s[l],o=n.object,n.render=!1,o.visible&&(!(o instanceof THREE.Mesh||o instanceof THREE.ParticleSystem)||!o.frustumCulled||
+g.contains(o)))o._modelViewMatrix.multiply(j.matrixWorldInverse,o.matrixWorld),n.render=!0;var t;l=0;for(m=s.length;l<m;l++)if(n=s[l],n.render&&(o=n.object,n=n.buffer,!(o instanceof THREE.ParticleSystem)||o.customDepthMaterial))(t=o.material instanceof THREE.MeshFaceMaterial?o.material.materials[0]:o.material)&&b.setMaterialFaces(o.material),p=0<o.geometry.morphTargets.length&&t.morphTargets,t=o instanceof THREE.SkinnedMesh&&t.skinning,p=o.customDepthMaterial?o.customDepthMaterial:t?p?f:e:p?d:c,n instanceof
+THREE.BufferGeometry?b.renderBufferDirect(j,i.__lights,null,p,n,o):b.renderBuffer(j,i.__lights,null,p,n,o);s=i.__webglObjectsImmediate;l=0;for(m=s.length;l<m;l++)n=s[l],o=n.object,o.visible&&(o._modelViewMatrix.multiply(j.matrixWorldInverse,o.matrixWorld),b.renderImmediateObject(j,i.__lights,null,c,o));l=b.getClearColor();m=b.getClearAlpha();a.clearColor(l.r,l.g,l.b,m);a.enable(a.BLEND)}};
+THREE.ShaderFlares={lensFlareVertexTexture:{vertexShader:"uniform vec3 screenPosition;\nuniform vec2 scale;\nuniform float rotation;\nuniform int renderType;\nuniform sampler2D occlusionMap;\nattribute vec2 position;\nattribute vec2 uv;\nvarying vec2 vUV;\nvarying float vVisibility;\nvoid main() {\nvUV = uv;\nvec2 pos = position;\nif( renderType == 2 ) {\nvec4 visibility = texture2D( occlusionMap, vec2( 0.1, 0.1 ) ) +\ntexture2D( occlusionMap, vec2( 0.5, 0.1 ) ) +\ntexture2D( occlusionMap, vec2( 0.9, 0.1 ) ) +\ntexture2D( occlusionMap, vec2( 0.9, 0.5 ) ) +\ntexture2D( occlusionMap, vec2( 0.9, 0.9 ) ) +\ntexture2D( occlusionMap, vec2( 0.5, 0.9 ) ) +\ntexture2D( occlusionMap, vec2( 0.1, 0.9 ) ) +\ntexture2D( occlusionMap, vec2( 0.1, 0.5 ) ) +\ntexture2D( occlusionMap, vec2( 0.5, 0.5 ) );\nvVisibility = (       visibility.r / 9.0 ) *\n( 1.0 - visibility.g / 9.0 ) *\n(       visibility.b / 9.0 ) *\n( 1.0 - visibility.a / 9.0 );\npos.x = cos( rotation ) * position.x - sin( rotation ) * position.y;\npos.y = sin( rotation ) * position.x + cos( rotation ) * position.y;\n}\ngl_Position = vec4( ( pos * scale + screenPosition.xy ).xy, screenPosition.z, 1.0 );\n}",fragmentShader:"precision mediump float;\nuniform sampler2D map;\nuniform float opacity;\nuniform int renderType;\nuniform vec3 color;\nvarying vec2 vUV;\nvarying float vVisibility;\nvoid main() {\nif( renderType == 0 ) {\ngl_FragColor = vec4( 1.0, 0.0, 1.0, 0.0 );\n} else if( renderType == 1 ) {\ngl_FragColor = texture2D( map, vUV );\n} else {\nvec4 texture = texture2D( map, vUV );\ntexture.a *= opacity * vVisibility;\ngl_FragColor = texture;\ngl_FragColor.rgb *= color;\n}\n}"},
+lensFlare:{vertexShader:"uniform vec3 screenPosition;\nuniform vec2 scale;\nuniform float rotation;\nuniform int renderType;\nattribute vec2 position;\nattribute vec2 uv;\nvarying vec2 vUV;\nvoid main() {\nvUV = uv;\nvec2 pos = position;\nif( renderType == 2 ) {\npos.x = cos( rotation ) * position.x - sin( rotation ) * position.y;\npos.y = sin( rotation ) * position.x + cos( rotation ) * position.y;\n}\ngl_Position = vec4( ( pos * scale + screenPosition.xy ).xy, screenPosition.z, 1.0 );\n}",fragmentShader:"precision mediump float;\nuniform sampler2D map;\nuniform sampler2D occlusionMap;\nuniform float opacity;\nuniform int renderType;\nuniform vec3 color;\nvarying vec2 vUV;\nvoid main() {\nif( renderType == 0 ) {\ngl_FragColor = vec4( texture2D( map, vUV ).rgb, 0.0 );\n} else if( renderType == 1 ) {\ngl_FragColor = texture2D( map, vUV );\n} else {\nfloat visibility = texture2D( occlusionMap, vec2( 0.5, 0.1 ) ).a +\ntexture2D( occlusionMap, vec2( 0.9, 0.5 ) ).a +\ntexture2D( occlusionMap, vec2( 0.5, 0.9 ) ).a +\ntexture2D( occlusionMap, vec2( 0.1, 0.5 ) ).a;\nvisibility = ( 1.0 - visibility / 4.0 );\nvec4 texture = texture2D( map, vUV );\ntexture.a *= opacity * visibility;\ngl_FragColor = texture;\ngl_FragColor.rgb *= color;\n}\n}"}};
+THREE.ShaderSprite={sprite:{vertexShader:"uniform int useScreenCoordinates;\nuniform int affectedByDistance;\nuniform vec3 screenPosition;\nuniform mat4 modelViewMatrix;\nuniform mat4 projectionMatrix;\nuniform float rotation;\nuniform vec2 scale;\nuniform vec2 alignment;\nuniform vec2 uvOffset;\nuniform vec2 uvScale;\nattribute vec2 position;\nattribute vec2 uv;\nvarying vec2 vUV;\nvoid main() {\nvUV = uvOffset + uv * uvScale;\nvec2 alignedPosition = position + alignment;\nvec2 rotatedPosition;\nrotatedPosition.x = ( cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y ) * scale.x;\nrotatedPosition.y = ( sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y ) * scale.y;\nvec4 finalPosition;\nif( useScreenCoordinates != 0 ) {\nfinalPosition = vec4( screenPosition.xy + rotatedPosition, screenPosition.z, 1.0 );\n} else {\nfinalPosition = projectionMatrix * modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\nfinalPosition.xy += rotatedPosition * ( affectedByDistance == 1 ? 1.0 : finalPosition.z );\n}\ngl_Position = finalPosition;\n}",
+fragmentShader:"precision mediump float;\nuniform vec3 color;\nuniform sampler2D map;\nuniform float opacity;\nuniform int fogType;\nuniform vec3 fogColor;\nuniform float fogDensity;\nuniform float fogNear;\nuniform float fogFar;\nvarying vec2 vUV;\nvoid main() {\nvec4 texture = texture2D( map, vUV );\ngl_FragColor = vec4( color * texture.xyz, texture.a * opacity );\nif ( fogType > 0 ) {\nfloat depth = gl_FragCoord.z / gl_FragCoord.w;\nfloat fogFactor = 0.0;\nif ( fogType == 1 ) {\nfogFactor = smoothstep( fogNear, fogFar, depth );\n} else {\nconst float LOG2 = 1.442695;\nfloat fogFactor = exp2( - fogDensity * fogDensity * depth * depth * LOG2 );\nfogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );\n}\ngl_FragColor = mix( gl_FragColor, vec4( fogColor, gl_FragColor.w ), fogFactor );\n}\n}"}};
diff --git a/ruoyi-admin/src/main/resources/static/ruoyi.png b/ruoyi-admin/src/main/resources/static/ruoyi.png
new file mode 100644
index 0000000..b0af01f
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ruoyi.png
Binary files differ
diff --git a/ruoyi-admin/src/main/resources/static/ruoyi/css/ry-ui.css b/ruoyi-admin/src/main/resources/static/ruoyi/css/ry-ui.css
new file mode 100644
index 0000000..6aa1bc1
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ruoyi/css/ry-ui.css
@@ -0,0 +1,1218 @@
+/**
+ * 通用css样式布局处理
+ * Copyright (c) 2019 ruoyi
+ */
+
+/** 基础通用 **/
+.pt5 {
+	padding-top: 5px;
+}
+.pr5 {
+	padding-right: 5px;
+}
+.pb5 {
+	padding-bottom: 5px;
+}
+.mt5 {
+	margin-top: 5px;
+}
+.mr5 {
+	margin-right: 5px;
+}
+.mb5 {
+	margin-bottom: 5px;
+}
+.ml5 {
+	margin-left: 5px;
+}
+.mt10 {
+	margin-top: 10px;
+}
+.mr10 {
+	margin-right: 10px;
+}
+.mb10 {
+	margin-bottom: 10px;
+}
+.ml0 {
+	margin-left: 10px;
+}
+.mt20 {
+	margin-top: 20px;
+}
+.mr20 {
+	margin-right: 20px;
+}
+.mb20 {
+	margin-bottom: 20px;
+}
+.m20 {
+	margin-left: 20px;
+}
+.m50 {
+	margin-left: 50px;
+}
+.img-xs {
+  width: 32px;
+  height: 32px;
+}
+.img-sm {
+  width: 64px;
+  height: 64px;
+}
+.img-md {
+  width: 96px;
+  height: 96px;
+}
+.img-lg {
+  width: 120px;
+  height: 120px;
+}
+.section-content {
+    min-height: 250px;
+    margin-right: auto;
+    margin-left: auto;
+    padding: 5px 5px 5px 5px;
+    width: 100%;
+    height: 100%;
+    position: absolute;
+}
+
+.ibox {
+    margin-bottom: 25px;
+    background-color: #fff;
+    border: 1px solid #ddd;
+    border-radius: 4px;
+    height: 100%;
+    -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05);
+}
+
+.list-group-striped > .list-group-item {
+	border-left: 0;
+	border-right: 0;
+	border-radius: 0;
+	padding-left: 0;
+	padding-right: 0
+}
+
+.ibox-title-gray {
+    height: 41px;
+    background-color: #f0f3f4;
+    color: #333;
+    font-weight: 700;
+    border-radius: 2px 2px 0 0;
+    padding: 13px !important;
+    border-bottom: 1px solid #eee;
+    display: block;
+    clear: both;
+}
+
+.dashboard-header h5 {
+    padding: 8px 0 0 0;
+    display: inline-block;
+    font-size: 14px;
+    text-overflow: ellipsis;
+    float: left;
+    font-weight: 400;
+}
+
+.ibox-title-gray h5 {
+    display: inline-block;
+    font-size: 14px;
+    margin: 0 0 7px;
+    padding: 0;
+    text-overflow: ellipsis;
+    float: left;
+}
+
+/* 导航页签 */
+.nav-tabs-custom {
+	margin-bottom: 20px;
+	background: #fff;
+	box-shadow: 0 1px 1px rgba(0,0,0,0.1);
+	border-radius: 3px
+}
+
+.nav-tabs-custom>.nav-tabs {
+	margin: 0;
+	border-bottom-color: #f4f4f4;
+	border-top-right-radius: 3px;
+	border-top-left-radius: 3px
+}
+
+.nav-tabs-custom>.nav-tabs>li {
+	border-top: 3px solid transparent;
+	margin-bottom: -2px;
+	margin-right: 5px
+}
+
+.nav-tabs-custom>.nav-tabs>li.header {
+	padding-left: 5px;
+	font-size: 16px;
+	line-height: 30px;
+}
+
+.nav-tabs-custom>.nav-tabs>li.disabled>a {
+	color: #777
+}
+
+.nav-tabs-custom>.nav-tabs>li>a {
+	color: #444;
+	font-weight: normal;
+	border-radius: 0
+}
+
+.nav-tabs-custom>.nav-tabs>li>a,.nav-tabs-custom>.nav-tabs>li>a:hover {
+	background: transparent;
+	margin: 0
+}
+
+.nav-tabs-custom>.nav-tabs>li>a:hover {
+	color: #999
+}
+
+.nav-tabs-custom>.nav-tabs>li:not(.active)>a:hover,.nav-tabs-custom>.nav-tabs>li:not(.active)>a:focus,.nav-tabs-custom>.nav-tabs>li:not(.active)>a:active {
+	border-color: transparent
+}
+
+.nav-tabs-custom>.nav-tabs>li.active {
+	border-top-color: #1890ff
+}
+
+.nav-tabs-custom>.nav-tabs>li.active>a,.nav-tabs-custom>.nav-tabs>li.active:hover>a {
+	background-color: #fff;
+	color: #444
+}
+
+.nav-tabs-custom>.nav-tabs>li.active>a {
+	border-top-color: transparent;
+	border-bottom-color: transparent;
+	border-left-color: #f4f4f4;
+	border-right-color: #f4f4f4
+}
+
+.nav-tabs-custom>.tab-content {
+	background: #fff;
+	padding: 10px;
+	border-bottom-right-radius: 3px;
+	border-bottom-left-radius: 3px
+}
+
+/** 弹层组件 禁用样式 **/
+.layer-disabled {
+	border: 1px #dedede solid !important;
+	background-color: #f1f1f1 !important;
+	color: #333 !important;
+	pointer-events: none;
+}
+
+/** 用户管理 样式布局 **/
+.box {
+	position: relative;
+	border-radius: 3px;
+	background: #ffffff;
+	border-top: 3px solid #d2d6de;
+	margin-bottom: 20px;
+	width: 100%;
+	box-shadow: 0 1px 1px rgba(0,0,0,0.1)
+}
+
+.box-header:before,.box-body:before,.box-footer:before,.box-header:after,.box-body:after,.box-footer:after {
+	content: " ";
+	display: table
+}
+
+.box-header:after,.box-body:after,.box-footer:after {
+	clear: both
+}
+
+.btn-box-tool {
+	padding: 5px;
+	font-size: 12px;
+	background: transparent;
+	color: #97a0b3;
+}
+
+.open .btn-box-tool,
+.btn-box-tool:hover {
+	color: #606c84;
+}
+
+.box-main {
+	margin: 0;
+	border: 0;
+	padding-top: 2px;
+	border-radius: 0;
+	box-shadow: none
+}
+
+.box-main>.box-header {
+	border-bottom: 1px solid #eee;
+	padding: 12px 10px 2px 15px
+}
+
+.box-header .box-title {
+	display: inline-block;
+	font-size: 18px;
+	margin: 0;
+	line-height: 1;
+}
+
+.box-main>.box-header .box-title {
+	font-size: 16px;
+	margin-bottom: 13px;
+	float: left
+}
+
+.box-main>.box-header .box-title .fa {
+	font-size: 14px;
+	padding-right: 3px;
+	margin-top: -2px
+}
+
+.box-main>.box-header .box-tools {
+	position: relative;
+	top: -5px;
+	right: 0
+}
+
+.box-main>.box-header .box-tools .btn {
+	padding: 3px 10px 5px 10px;
+	font-size: 14px;
+	margin-bottom: 2px
+}
+
+.box-main>.box-header .box-tools .btn-box-tool {
+	padding: 4px 2px
+}
+
+.box-main form>.box-footer,.nav-main form>.box-footer {
+	background: #fafafa
+}
+
+.box-main form>.box-footer .row,.nav-main form>.box-footer .row {
+	margin: 5px 0 5px -25px
+}
+
+@media ( min-width : 768px) {
+	.section-content .about {
+		padding-left: 0px
+	}
+}
+
+/** select2 样式修改 **/
+.select2-container--default .select2-selection--multiple .select2-selection__choice {
+	background-color: #1AB394;
+	border-color: #1AB394;
+	padding: 1px 10px;
+	color: #fff
+}
+
+.select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
+	margin-right: 5px;
+	color: rgba(255,255,255,0.7)
+}
+
+.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover {
+	color: #fff
+}
+
+.select2-container .select2-selection--single .select2-selection__rendered {
+	padding-right: 10px
+}
+
+/** 表单验证 样式布局 **/
+.control-label.is-required:before {
+  content: '* ';
+  color: red;
+}
+
+label.error {
+	position: absolute;
+	right: 18px;
+	top: 6px;
+	color: #ef392b;
+	font-size: 12px;
+	z-index:99;
+}
+
+.input-group label.error {
+	z-index:99;
+	right: 42px;
+}
+
+.input-group input.error + label.error + .input-group-addon>i {
+	color: #ed5565;
+}
+
+.input-group.date label.error {
+	z-index:99;
+	right: 42px;
+}
+
+.select2-hidden-accessible + label.error, select.error + label.error {
+	right: 38px;
+}
+
+.Validform_error,input.error,textarea.error,select.error,select.error+label.error+.select2-container--bootstrap .select2-selection--single {
+	background-color: #fbe2e2;
+	border-color: #c66161;
+	color: #c00
+}
+
+.Validform_wrong,.Validform_right,.Validform_warning {
+	display: inline-block;
+	height: 20px;
+	font-size: 12px;
+	vertical-align: middle;
+	padding-left: 25px
+}
+
+.i-checks label.error, .check-box label.error, .radio-box label.error {
+	right: auto;
+	width: 150px;
+	left: 210px;
+	top: 1px;
+	max-width: none;
+}
+
+/** 复选框&单选框  **/
+.check-box,.radio-box {
+	display: inline-block;
+	box-sizing: border-box;
+	cursor: pointer;
+	position: relative;
+	padding-left: 25px;
+	padding-right: 15px;
+	padding-top: 7px;
+}
+
+.icheckbox, .icheckbox-blue, .iradio, .iradio-blue, .iradio-purple {
+	position: absolute;
+	top: 7px;
+	left: 0
+}
+
+/** iCheck **/
+.icheckbox-blue,.iradio-blue {
+	display: block;
+	margin: 0;
+	padding: 0;
+	width: 18px;
+	height: 18px;
+	background: url(../../img/blue.png) no-repeat;
+	border: none;
+	cursor: pointer
+}
+
+.icheckbox-blue,.icheckbox-blue.static:hover {
+	background-position: 0 0
+}
+
+.icheckbox-blue.hover,.icheckbox-blue:hover {
+	background-position: -20px 0
+}
+
+.icheckbox-blue.checked {
+	background-position: -40px 0
+}
+
+.icheckbox-blue.disabled {
+	background-position: -60px 0;
+	cursor: default
+}
+
+.icheckbox-blue.checked.disabled {
+	background-position: -80px 0
+}
+
+.iradio-blue,.iradio-blue.static:hover {
+	background-position: -100px 0
+}
+
+.iradio-blue.hover,.iradio-blue:hover {
+	background-position: -120px 0
+}
+
+.iradio-blue.checked {
+	background-position: -140px 0
+}
+
+.iradio-blue.disabled {
+	background-position: -160px 0;
+	cursor: default
+}
+
+.iradio-blue.checked.disabled {
+	background-position: -180px 0
+}
+
+/* ztree */
+div.ztree-border {
+    margin-top: 10px;
+    border: 1px solid #e5e6e7;
+    background: #FFFFFF none;
+    border-radius:4px;
+}
+
+/* 切换开关 */
+.toggle-switch {
+	display: -webkit-inline-box;
+	display: -webkit-inline-flex;
+	display: -ms-inline-flexbox;
+	display: inline-flex;
+	-webkit-box-align: center;
+	-webkit-align-items: center;
+	-ms-flex-align: center;
+	align-items: center;
+	margin-bottom: 0;
+	padding-top: 8px;
+}
+.toggle-switch input {
+    height: 0;
+    width: 0;
+    position: absolute;
+    opacity: 0;
+}
+.toggle-switch span {
+	display: inline-block;
+	position: relative;
+	width: 40px;
+	height: 10px;
+	-webkit-border-radius: 10px;
+	border-radius: 10px;
+	background-color: #ebebeb;
+	border: 2px solid #ebebeb;
+	cursor: pointer;
+	-webkit-transition: all .1s ease;
+	-o-transition: all .1s ease;
+	transition: all .1s ease
+}
+.toggle-switch span:after {
+	content: '';
+	height: 20px;
+	width: 20px;
+	-webkit-border-radius: 50%;
+	border-radius: 50%;
+	position: absolute;
+	left: 1px;
+	top: -7px;
+	color: #aaa;
+	-webkit-transition: all .1s ease;
+	-o-transition: all .1s ease;
+	transition: all .1s ease;
+	text-align: center;
+	font-size: 13px;
+	background-color: #fff;
+	-webkit-box-shadow: rgba(0,0,0,.12) 0 1px 6px,rgba(0,0,0,.12) 0 1px 4px;
+	box-shadow: rgba(0,0,0,.12) 0 1px 6px,rgba(0,0,0,.12) 0 1px 4px
+}
+.toggle-switch input:checked~span:after {
+	left: -webkit-calc(100% - 20px);
+	left: calc(100% - 20px);
+	background-color: #33cabb
+}
+
+.toggle-switch.switch-solid span  {
+    height: 20px;
+}
+.toggle-switch.switch-solid span:after {
+    top: -2px;
+}
+.switch-solid input:checked~span {
+	background-color: #33cabb;
+	border-color: #33cabb
+}
+.switch-solid input:checked~span:after {
+	background-color: #fff;
+	color: #33cabb
+}
+
+/** 遮罩层 **/
+.loaderbox {
+	display: inline-block;
+	min-width: 125px;
+	padding: 10px;
+	margin: 0 auto;
+	color: #000 !important;
+	font-size: 13px;
+	font-weight: 400;
+	text-align: center;
+	vertical-align: middle;
+	border: 1px solid #ddd;
+	background-color: #eee;
+	-webkit-border-radius: 2px;
+	-moz-border-radius: 2px;
+	-ms-border-radius: 2px;
+	-o-border-radius: 2px;
+	border-radius: 2px;
+	-webkit-box-shadow: 0 1px 8px rgba(0, 0, 0, 0.1);
+	-moz-box-shadow: 0 1px 8px rgba(0, 0, 0, 0.1);
+	box-shadow: 0 1px 8px rgba(0, 0, 0, 0.1);
+}
+
+.loaderbox .loading-activity {
+	float: left;
+	width: 18px;
+	height: 18px;
+	border: solid 2px transparent;
+	border-top-color: #000;
+	border-left-color: #000;
+	border-radius: 10px;
+	-webkit-animation: pace-spinner 400ms linear infinite;
+	-moz-animation: pace-spinner 400ms linear infinite;
+	-ms-animation: pace-spinner 400ms linear infinite;
+	-o-animation: pace-spinner 400ms linear infinite;
+	animation: pace-spinner 400ms linear infinite;
+}
+
+@media (max-width: 767px) {
+	.loading-activity {
+		width: 18px;
+		height: 18px;
+	}
+}
+
+@-ms-keyframes pace-spinner {
+	0% {
+		-ms-transform: rotate(0deg);
+		transform: rotate(0deg);
+	}
+
+	100% {
+		-ms-transform: rotate(360deg);
+		transform: rotate(360deg);
+	}
+}
+
+@keyframes pace-spinner {
+	0% {
+		transform: rotate(0deg);
+	}
+
+	100% {
+		transform: rotate(360deg);
+	}
+}
+
+/** 表单查询条件  **/
+.select-list ul, .layui-layer-content ul {
+	margin: 0;
+	padding: 0;
+	-webkit-tap-highlight-color: rgba(0,0,0,0);
+}
+
+.select-list li, .layui-layer-content li {
+	list-style: none;
+}
+
+.select-time .time-input {
+	display: block;
+	width: 100%;
+	padding-left: 10px;
+}
+
+label {
+	font-weight: normal;
+}
+
+.container-div {
+	padding: 0px 28px;
+	height: 100%;
+}
+
+.container-div .row {
+	height: 100%;
+}
+
+.search-collapse,.select-table {
+	width: 100%;
+	background: #fff;
+	border-radius: 6px;
+	margin-top: 10px;
+	padding-top: 5px;
+	padding-bottom: 13px;
+	box-shadow: 1px 1px 3px rgba(0,0,0,.2);
+}
+
+.search-collapse {
+	position: relative;
+}
+
+.search-collapse .col-sm-6 .control-label {
+	color: #333;
+}
+
+@media ( max-width : 768px) {
+	.search-collapse {
+		display: none;
+	}
+}
+
+@media ( min-width : 768px) {
+	.select-list li {
+		float: left;
+	}
+}
+
+.select-list li {
+	color: #333;
+	margin: 5px 15px 5px 0px;
+}
+
+.select-list li p, .select-list li label:not(.radio-box){
+	float: left;
+	width: 65px;
+	margin: 5px 0px 0px 0px;
+	text-align:right;
+}
+
+.select-list li input {
+	border: 1px solid #ddd;
+	border-radius: 4px;
+	background: transparent;
+	outline: none;
+	height: 30px;
+	width: 200px;
+	padding-left: 5px;
+}
+
+.select-list li .submit-btn {
+	border: 0px;
+	border-radius: 4px;
+	background: transparent;
+	outline: none;
+	width: 40px;
+	height: 23px;
+}
+
+.select-list li select {
+	border: 1px solid #ddd;
+	border-radius: 4px;
+	background: transparent;
+	outline: none;
+	height: 30px;
+    width: 200px;
+}
+
+.bootstrap-select.form-control .btn-default {
+    color: inherit;
+    padding: 4px 6px 4px;
+    border-radius: 4px;
+    border: 1px solid #e5e6e7;
+	outline: none;
+	height: 31px;
+	background: #FFFFFF none
+}
+
+.file-input .btn-default {
+    color: inherit;
+    background: white;
+    border: 1px solid #e7eaec;
+}
+
+.select-list .btn-default {
+    color: #555;
+    padding: 5px 5px;
+    border: 1px solid #ddd;
+	border-radius: 4px;
+	background: transparent;
+	outline: none;
+	height: 30px;
+	width: 200px;
+}
+
+.select-list .btn-default:hover,.select-list .btn-default:focus,.select-list .btn-default:active,.select-list .btn-default.active,.open .dropdown-toggle.btn-default {
+	color: #555;
+	background-color: #e4e4e4;
+	border-color: #b2b2b2
+}
+
+.select-list .bootstrap-select:not([class*="col-"]):not([class*="form-control"]):not(.input-group-btn) {
+  height: 30px;
+  width: 200px;
+}
+
+.select-list .bootstrap-select > .dropdown-toggle.bs-placeholder,
+.select-list .bootstrap-select > .dropdown-toggle.bs-placeholder:hover,
+.select-list .bootstrap-select > .dropdown-toggle.bs-placeholder:focus,
+.select-list .bootstrap-select > .dropdown-toggle.bs-placeholder:active {
+  color: inherit;
+  font-size: 13px;
+}
+
+.select-list .bootstrap-select .dropdown-toggle .caret {
+  position: inherit;
+}
+
+.select-list .select-selectpicker li {
+	float: none;
+}
+
+.select-list .dropdown-menu>li>a,.bootstrap-select.form-control .dropdown-menu>li>a {
+    line-height: inherit;
+}
+
+.select-list .dropdown-menu li>a:hover,.dropdown-menu li>a:focus,.dropdown-submenu:hover>a,.bootstrap-select.form-control .dropdown-menu li>a:hover,.dropdown-menu li>a:focus,.dropdown-submenu:hover>a{
+	color: #fff;
+	text-decoration: none;
+	background-color: #12889a
+}
+
+.select-list .select2-container--bootstrap {
+	width: 200px!important;
+	display: inline-block;
+}
+
+.select-list .select2-container--bootstrap .select2-selection {
+	border-radius: 6px;
+}
+
+.select-list .select2-container--bootstrap .select2-selection--single {
+	height: 30px!important;
+	padding: 5px 10px;
+}
+
+.select-list .select-time input {
+	width: 93px;
+}
+
+.select-time label,.select-time span,.select-time input {
+	float: left;
+}
+
+@media (max-width:767px) {
+    .select-time label,.select-time span,.select-time input {
+	    float: none;
+    }
+    .select-list .select-time input {
+	    width: 200px;
+    }
+}
+
+.select-time label {
+	margin-top: 5px;
+}
+
+.select-time span {
+	display: block;
+	margin: 5px 5px;
+}
+
+.search-btn {
+	background-color: #1ab394;
+	border-color: #1ab394;
+	color: #FFF;
+	margin-bottom: 5px;
+	display: inline-block;
+	padding: 6px 12px;
+	margin-bottom: 0;
+	font-size: 14px;
+	font-weight: 400;
+	line-height: 1.42857143;
+	text-align: center;
+	white-space: nowrap;
+	border-radius: 3px;
+	vertical-align: middle;
+	cursor: pointer;
+}
+
+.select-title{
+	color:#3d5266;
+	font-size:15px;
+	padding:10px 0px;
+	font-weight: normal;
+}
+
+/** 表格查询数据 **/
+.table-striped {
+	min-height: 75%;
+}
+
+.table-striped .bootstrap-table, .table-striped .table-bordered {
+	border: 0px!important;
+}
+
+.table-bordered .table>thead>tr>th, .table-bordered .table>tbody>tr>th {
+	font-weight: normal;
+	font-size: 13px
+}
+
+.table-striped table>thead>tr>th, .table-striped table>tbody>tr>th, .table-striped table>tfoot>tr>th, .table-striped table>thead>tr>td, .table-striped table>tbody>tr>td, .table-striped table>tfoot>tr>td {
+	border-bottom: 1px solid #e7eaec!important;
+	background-color: transparent;
+	border: 0px;
+}
+
+.table-bordered table>thead>tr>th:first-child, .table-bordered table>tbody>tr>td:first-child {
+    border-left: 1px solid #ddd;
+}
+
+.table-bordered table>thead>tr>th:last-child, .table-bordered table>tbody>tr>td:last-child {
+	border-right: 1px solid #ddd;
+}
+
+.table-bordered table>thead>tr>th, .table-bordered table>tbody>tr>td {
+    border-top: 1px solid #ddd!important;
+    border-bottom: 1px solid #ddd;
+}
+
+.fixed-table-footer {
+	border-top: 0px solid #ddd;
+}
+
+.fixed-table-container {
+	border: 0px solid #ddd;
+}
+
+.table-striped .table>thead>tr>th, .table-striped .table>tbody>tr>th {
+	border-bottom: 1px solid #ccc!important;
+	border-top: 0px!important;
+	font-weight: normal;
+	font-size: 13px
+}
+
+.table-striped table thead {
+    background-color: #eff3f8;
+}
+
+.fixed-table-container thead th  >.both{
+    display: inline-block
+}
+
+.editable-input .input-sm {
+	height: 32px!important;
+}
+
+/** 表格列宽拖动样式 **/
+.rc-handle-container {
+  position: relative;
+}
+.rc-handle {
+  position: absolute;
+  width: 7px;
+  cursor: ew-resize;
+  margin-left: -3px;
+  z-index: 2;
+}
+table.rc-table-resizing {
+  cursor: ew-resize;
+}
+table.rc-table-resizing thead,
+table.rc-table-resizing thead > th,
+table.rc-table-resizing thead > th > a {
+  cursor: ew-resize;
+}
+
+/** 表格冻结列样式 **/
+.fixed-columns, .fixed-columns-right {
+  position: absolute;
+  top: 0;
+  height: 100%;
+  background-color: #fff;
+  box-sizing: border-box;
+  z-index: 1;
+  border-width: 0 0 0 1px;
+  -webkit-box-shadow: 0 0 10px rgba(0,0,0,.12);
+  box-shadow: 0 0 10px rgba(0,0,0,.12);
+}
+
+.fixed-columns {
+  left: 0;
+}
+
+.fixed-columns .fixed-table-body {
+  overflow: hidden !important;
+}
+
+.fixed-columns-right {
+  right: 0;
+}
+
+.fixed-columns-right .fixed-table-body {
+  overflow-x: hidden !important;
+}
+
+.bootstrap-table .table-hover > tbody > tr.hover > td {
+    background-color: #f5f5f5;
+}
+
+/** 表格树样式 **/
+.bootstrap-tree-table .treetable-indent {width:16px; height: 16px; display: inline-block; position: relative;}
+.bootstrap-tree-table .treetable-expander {width:16px; height: 16px; display: inline-block; position: relative; cursor: pointer;}
+.bootstrap-tree-table .treetable-selected{background: #f5f5f5 !important;}
+.bootstrap-tree-table .treetable-table{border:0 !important;margin-bottom:0}
+.bootstrap-tree-table .treetable-table tbody {display:block;height:auto;overflow-y:auto;}
+.bootstrap-tree-table .treetable-table thead, .treetable-table tbody tr {display:table;width:100%;table-layout:fixed;}
+.bootstrap-tree-table .treetable-thead th{line-height:24px;border: 0 !important;border-radius: 4px;border-left:0px solid #e7eaec !important;border-bottom:1px solid #ccc!important;text-align: left;}
+.bootstrap-tree-table .treetable-thead tr :first-child{border-left:0 !important}
+.bootstrap-tree-table .treetable-tbody td{border: 0 !important;border-left:0px solid #e7eaec !important;border-bottom:1px solid #e7eaec!important;white-space: nowrap; text-overflow: ellipsis;}
+.bootstrap-tree-table .treetable-tbody tr :first-child{border-left:0 !important}
+.bootstrap-tree-table .treetable-bars .tool-left, .bootstrap-tree-table .treetable-bars .tool-right{margin-top: 10px; margin-bottom: 10px;}
+.bootstrap-tree-table .treetable-bars .tool-left{float: left;}
+.bootstrap-tree-table .treetable-bars .tool-right{float: right;}
+.bootstrap-tree-table .treetable-bars .columns li label{display: block;padding: 3px 20px;clear: both;font-weight: 400;line-height: 1.428571429;max-width: 100%;margin-bottom: 5px;cursor:pointer;}
+.bootstrap-tree-table .table{border-bottom: 0px solid #e7eaec!important;}
+.bootstrap-tree-table .table-bordered .treetable-thead th {border-left: 1px solid #e7eaec!important;}
+.bootstrap-tree-table .table-bordered .treetable-tbody td {border-right: 1px solid #e7eaec!important;}
+.bootstrap-tree-table .fixed-table-pagination .pagination-detail {margin-top: 10px;margin-bottom: 10px;}
+
+/** 首页样式 **/
+.ax_close_max {
+	position: fixed;
+	top: 5px;
+	left: 5px;
+	z-index: 9999;
+	display: none;
+	color: #ccc;
+}
+.navbar-right > .user-menu > .dropdown-menu {
+	border-top-right-radius:0;
+	border-top-left-radius:0;
+	padding:1px 0 0 0;
+	border-top-width:0;
+	width:138px;
+}
+.navbar-right > .user-menu .user-image {
+	float:left;
+	width:27px;
+	height:27px;
+	border-radius:50%;
+	margin-right:8px;
+	margin-top:-3px;
+}
+@media (max-width:767px) {
+	.navbar-right > .user-menu .user-image {
+	float:none;
+	margin-right:0;
+	margin-top:-8px;
+	line-height:10px;
+}
+}.dropdown-menu > li > a > .glyphicon,.dropdown-menu > li > a > .fa,.dropdown-menu > li > a > .ion {
+	margin-right:10px;
+}
+.dropdown-menu > li > a:hover {
+	background-color:#e1e3e9;
+	color:#333;
+}
+.dropdown-menu > .divider {
+	background-color:#eee;
+}
+
+/** 表单布局 **/
+.form-header {
+    font-size:15px;
+	color:#6379bb;
+	border-bottom:1px solid #ddd;
+	margin:8px 10px 25px 10px;
+	padding-bottom:5px
+}
+
+.form-control-plaintext {
+    display: block;
+    width: 100%;
+    padding-top: .286rem;
+    padding-bottom: .286rem;
+    margin-bottom: 0;
+    line-height: 1.57142857;
+    color: #212529;
+    background-color: transparent;
+    border: solid transparent;
+    border-width: 1px 0;
+    font-weight: 500;
+    border-bottom: 1px dashed #ccd5db;
+    min-height: 25px
+}
+
+.form-control-plaintext-no-content {
+    display: block;
+    width: 100%;
+    padding-top: .286rem;
+    padding-bottom: .286rem;
+    margin-bottom: 0;
+    line-height: 1.57142857;
+    color: #ddd !important;
+    background-color: transparent;
+    border: solid transparent;
+    border-width: 1px 0;
+    border-bottom: 1px dashed #ccd5db;
+    min-height: 25px
+}
+
+.main-content {
+    background-color: #ffffff;
+    color: inherit;
+    padding: 10px 15px 15px 15px;
+    border-color: #e7eaec;
+    -webkit-border-image: none;
+    -o-border-image: none;
+    border-image: none;
+    border-width: 1px 0px;
+}
+
+/** 表格跳转样式 **/
+.pageGo input {
+    height: 32px;
+    width: 50px;
+    margin-left: 5px;
+    margin-right: 5px;
+    text-align: center;
+    display: block;
+    float:left;
+}
+.pageGo button {
+    height: 32px;
+    display: block;
+    float:left;
+}
+
+/** 表格行拖拽样式 **/
+.reorder-rows-on-drag-class td {
+    color:yellow!important;
+	background-color:#999!important;
+	text-shadow:0 0 10px black,0 0 10px black,0 0 8px black,0 0 6px black,0 0 6px black;
+	box-shadow:0 12px 14px -12px #111 inset,0 -2px 2px -1px #333 inset
+}
+
+/** 表格列拖拽样式 **/
+.dragtable-sortable {
+    list-style-type: none; margin: 0; padding: 0; -moz-user-select: none;
+}
+
+.dragtable-sortable li {
+    margin: 0; padding: 0; float: left; font-size: 1em; background: white;
+}
+
+.dragtable-sortable th, .dragtable-sortable td{
+    border-left: 0px;
+}
+
+.dragtable-sortable li:first-child th, .dragtable-sortable li:first-child td {
+    border-left: 1px solid #CCC;
+}
+
+.ui-sortable-helper {
+    opacity: 0.7;filter: alpha(opacity=70);
+}
+
+.ui-sortable-placeholder {
+    -moz-box-shadow: 4px 5px 4px #C6C6C6 inset;
+    -webkit-box-shadow: 4px 5px 4px #C6C6C6 inset;
+    box-shadow: 4px 5px 4px #C6C6C6 inset;
+    border-bottom: 1px solid #CCCCCC;
+    border-top: 1px solid #CCCCCC;
+    visibility: visible !important;
+    background: #EFEFEF !important;
+    visibility: visible !important;
+}
+
+.ui-sortable-placeholder * {
+    opacity: 0.0; visibility: hidden;
+}
+
+/** 表格选中样式 **/
+.bootstrap-table .fixed-table-container .table tbody tr.selected td {
+    background-color: #E8F7FD;
+    color: #1890ff;
+}
+
+/** 滚动条样式 **/
+::-webkit-scrollbar-track {
+    background-color: #F5F5F5;
+}
+
+/** 气泡弹出框样式 **/
+.popover {
+	font-size: 13px;
+	max-width: unset;
+}
+
+.popover-title {
+	padding: 8px 14px;
+	margin: 0 !important;
+	font-size: 14px;
+	background-color: #f7f7f7;
+	border-bottom: 1px solid #ebebeb;
+	border-radius: 5px 5px 0 0;
+}
+
+.popover-content {
+	padding: 5px;
+}
+
+/** 向上滚动样式 **/
+#scroll-up {
+	border-width: 0;
+	position: fixed;
+	right: 2px;
+	z-index: 99;
+	-webkit-transition-duration: .3s;
+	transition-duration: .3s;
+	opacity: 0;
+	filter: alpha(opacity=0);
+	bottom: -24px;
+	visibility: hidden;
+	background-color: #aaa;
+	color: #fff;
+	font-size: 14px;
+	display: none;
+}
+
+#scroll-up.display {
+	opacity: .7;
+	filter: alpha(opacity=70);
+	bottom: 2px;
+	visibility: visible;
+}
+
+/* 设置菜单样式 */
+.menu-content {
+	padding: 10px 10px 10px 25px !important;
+}
+
+.tab-content > .tab-pane {
+    display: none;
+}
+
+.tab-content > .active {
+    display: block;
+}
+
+.height-full {
+    height: 100% !important;
+}
+
+/* 设置滚动条样式 */
+::-webkit-scrollbar {
+   width:10px!important;
+   height:10px!important;
+   -webkit-appearance:none;
+   background:#f1f1f1
+}
+
+::-webkit-scrollbar-thumb {
+    height:5px;
+    border:1px solid transparent;
+    border-top:0;
+    border-bottom:0;
+    border-radius:6px;
+    background-color:#ccc;
+    background-clip:padding-box
+}
+
+/* 设置placeholder样式 */
+::-webkit-input-placeholder {
+	color: #b3b3b3!important;
+}
+
+:-moz-placeholder {
+	color: #b3b3b3!important;
+}
+
+::-moz-placeholder {
+	color: #b3b3b3!important;
+}
+
+:-ms-input-placeholder {
+	color: #b3b3b3!important;
+}
diff --git a/ruoyi-admin/src/main/resources/static/ruoyi/index.js b/ruoyi-admin/src/main/resources/static/ruoyi/index.js
new file mode 100644
index 0000000..360d1c0
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ruoyi/index.js
@@ -0,0 +1,667 @@
+/**
+ * 首页方法封装处理
+ * Copyright (c) 2019 ruoyi
+ */
+var isMobile = false;
+var sidebarHeight = isMobile ? '100%' : '96%';
+
+$(function() {
+    // MetsiMenu
+    $('#side-menu').metisMenu();
+
+    // 固定菜单栏
+    $('.sidebar-collapse').slimScroll({
+        height: sidebarHeight,
+        railOpacity: 0.9,
+        alwaysVisible: false
+    });
+
+    // 菜单切换
+    $('.navbar-minimalize').click(function() {
+    	if (isMobile) {
+    	    $("body").toggleClass("canvas-menu");
+    	} else {
+    	    $("body").toggleClass("mini-navbar");
+    	}
+        SmoothlyMenu();
+    });
+
+    $('#side-menu>li').click(function() {
+    	if ($('body').hasClass('canvas-menu mini-navbar')) {
+            NavToggle();
+        }
+
+    });
+    $('#side-menu>li li a:not(:has(span))').click(function() {
+        if ($(window).width() < 769) {
+            NavToggle();
+        }
+    });
+
+    $('.nav-close').click(NavToggle);
+
+    //ios浏览器兼容性处理
+    if (/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)) {
+        $('#content-main').css('overflow-y', 'auto');
+    }
+
+});
+
+$(window).bind("load resize", function() {
+    isMobile = $.common.isMobile() || $(window).width() < 769;
+    if (isMobile) {
+        $('body').addClass('canvas-menu');
+        $("body").removeClass("mini-navbar");
+        $("nav .logo").addClass("hide");
+        $(".slimScrollDiv").css({ "overflow": "hidden" });
+        $('.navbar-static-side').fadeOut();
+    } else {
+    	if ($('body').hasClass('canvas-menu')) {
+    	    $('body').addClass('fixed-sidebar');
+    	    $('body').removeClass('canvas-menu');
+    	    $("body").removeClass("mini-navbar");
+    	    $("nav .logo").removeClass("hide");
+    	    $(".slimScrollDiv").css({ "overflow": "visible" });
+    	    $('.navbar-static-side').fadeIn();
+    	}
+    }
+});
+
+function openToCurrentTab(obj) {
+    if (isScrollToTop) {
+        $(obj).show().siblings('.RuoYi_iframe').hide();
+    } else {
+        $(obj).css({"visibility": "visible", "position": "static"}).siblings('.RuoYi_iframe').css({"visibility": "hidden", "position": "absolute", "left": "0", "top": "0"});
+    }
+}
+
+function syncMenuTab(dataId) {
+    if (isLinkage) {
+        var $dataObj = $('a[href$="' + decodeURI(dataId) + '"]');
+        if ($dataObj.attr("class") != null && !$dataObj.hasClass("noactive")) {
+            $('.tab-pane li').removeClass("active");
+            $('.nav ul').removeClass("in");
+            $dataObj.parents("ul").addClass("in")
+            $dataObj.parents("li").addClass("active").siblings().removeClass("active").find('li').removeClass("active");
+            $dataObj.parents("ul").css('height', 'auto').height();
+            $(".nav ul li, .nav li").removeClass("selected");
+            $dataObj.parent("li").addClass("selected");
+            setIframeUrl(dataId);
+            
+            // 顶部菜单同步处理
+            var tabStr = $dataObj.parents(".tab-pane").attr("id");
+            if ($.common.isNotEmpty(tabStr)) {
+                var sepIndex = tabStr.lastIndexOf('_');
+                var menuId = tabStr.substring(sepIndex + 1, tabStr.length);
+                $("#tab_" + menuId + " a").click();
+            }
+        }
+    }
+}
+
+function NavToggle() {
+    $('.navbar-minimalize').trigger('click');
+}
+
+function fixedSidebar() {
+    $('#side-menu').hide();
+    $("nav .logo").addClass("hide");
+    setTimeout(function() {
+        $('#side-menu').fadeIn(500);
+    }, 100);
+}
+
+// 设置锚点
+function setIframeUrl(href) {
+	if ($.common.equals("history", mode)) {
+	    storage.set('publicPath', href);
+	} else {
+	    var nowUrl = window.location.href;
+	    var newUrl = nowUrl.substring(0, nowUrl.indexOf("#"));
+	    window.location.href = newUrl + "#" + href;
+	}
+}
+
+function SmoothlyMenu() {
+    if (isMobile && !$('body').hasClass('canvas-menu')) {
+    	$('.navbar-static-side').fadeIn();
+    	fixedSidebar();
+    } else if (!isMobile &&!$('body').hasClass('mini-navbar')) {
+    	fixedSidebar();
+    	$("nav .logo").removeClass("hide");
+    } else if (isMobile && $('body').hasClass('fixed-sidebar')) {
+    	$('.navbar-static-side').fadeOut();
+    	fixedSidebar();
+    } else if (!isMobile && $('body').hasClass('fixed-sidebar')) {
+    	fixedSidebar();
+    } else {
+        $('#side-menu').removeAttr('style');
+    }
+}
+
+/**
+ * iframe处理
+ */
+$(function() {
+    //计算元素集合的总宽度
+    function calSumWidth(elements) {
+        var width = 0;
+        $(elements).each(function() {
+            width += $(this).outerWidth(true);
+        });
+        return width;
+    }
+
+    // 激活指定选项卡
+    function setActiveTab(element) {
+        if (!$(element).hasClass('active')) {
+            var currentId = $(element).data('id');
+            syncMenuTab(currentId);
+            // 显示tab对应的内容区
+            $('.RuoYi_iframe').each(function() {
+                if ($(this).data('id') == currentId) {
+                    openToCurrentTab(this);
+                }
+            });
+            $(element).addClass('active').siblings('.menuTab').removeClass('active');
+            scrollToTab(element);
+        }
+    }
+
+    //滚动到指定选项卡
+    function scrollToTab(element) {
+        var marginLeftVal = calSumWidth($(element).prevAll()),
+        marginRightVal = calSumWidth($(element).nextAll());
+        // 可视区域非tab宽度
+        var tabOuterWidth = calSumWidth($(".content-tabs").children().not(".menuTabs"));
+        //可视区域tab宽度
+        var visibleWidth = $(".content-tabs").outerWidth(true) - tabOuterWidth;
+        //实际滚动宽度
+        var scrollVal = 0;
+        if ($(".page-tabs-content").outerWidth() < visibleWidth) {
+            scrollVal = 0;
+        } else if (marginRightVal <= (visibleWidth - $(element).outerWidth(true) - $(element).next().outerWidth(true))) {
+            if ((visibleWidth - $(element).next().outerWidth(true)) > marginRightVal) {
+                scrollVal = marginLeftVal;
+                var tabElement = element;
+                while ((scrollVal - $(tabElement).outerWidth()) > ($(".page-tabs-content").outerWidth() - visibleWidth)) {
+                    scrollVal -= $(tabElement).prev().outerWidth();
+                    tabElement = $(tabElement).prev();
+                }
+            }
+        } else if (marginLeftVal > (visibleWidth - $(element).outerWidth(true) - $(element).prev().outerWidth(true))) {
+            scrollVal = marginLeftVal - $(element).prev().outerWidth(true);
+        }
+        $('.page-tabs-content').animate({ marginLeft: 0 - scrollVal + 'px' }, "fast");
+    }
+
+    //查看左侧隐藏的选项卡
+    function scrollTabLeft() {
+        var marginLeftVal = Math.abs(parseInt($('.page-tabs-content').css('margin-left')));
+        // 可视区域非tab宽度
+        var tabOuterWidth = calSumWidth($(".content-tabs").children().not(".menuTabs"));
+        //可视区域tab宽度
+        var visibleWidth = $(".content-tabs").outerWidth(true) - tabOuterWidth;
+        //实际滚动宽度
+        var scrollVal = 0;
+        if (($(".page-tabs-content").width()) < visibleWidth) {
+            return false;
+        } else {
+            var tabElement = $(".menuTab:first");
+            var offsetVal = 0;
+            while ((offsetVal + $(tabElement).outerWidth(true)) <= marginLeftVal) { //找到离当前tab最近的元素
+                offsetVal += $(tabElement).outerWidth(true);
+                tabElement = $(tabElement).next();
+            }
+            offsetVal = 0;
+            if (calSumWidth($(tabElement).prevAll()) > visibleWidth) {
+                while ((offsetVal + $(tabElement).outerWidth(true)) < (visibleWidth) && tabElement.length > 0) {
+                    offsetVal += $(tabElement).outerWidth(true);
+                    tabElement = $(tabElement).prev();
+                }
+                scrollVal = calSumWidth($(tabElement).prevAll());
+            }
+        }
+        $('.page-tabs-content').animate({ marginLeft: 0 - scrollVal + 'px' }, "fast");
+    }
+
+    //查看右侧隐藏的选项卡
+    function scrollTabRight() {
+        var marginLeftVal = Math.abs(parseInt($('.page-tabs-content').css('margin-left')));
+        // 可视区域非tab宽度
+        var tabOuterWidth = calSumWidth($(".content-tabs").children().not(".menuTabs"));
+        //可视区域tab宽度
+        var visibleWidth = $(".content-tabs").outerWidth(true) - tabOuterWidth;
+        //实际滚动宽度
+        var scrollVal = 0;
+        if ($(".page-tabs-content").width() < visibleWidth) {
+            return false;
+        } else {
+            var tabElement = $(".menuTab:first");
+            var offsetVal = 0;
+            while ((offsetVal + $(tabElement).outerWidth(true)) <= marginLeftVal) { //找到离当前tab最近的元素
+                offsetVal += $(tabElement).outerWidth(true);
+                tabElement = $(tabElement).next();
+            }
+            offsetVal = 0;
+            while ((offsetVal + $(tabElement).outerWidth(true)) < (visibleWidth) && tabElement.length > 0) {
+                offsetVal += $(tabElement).outerWidth(true);
+                tabElement = $(tabElement).next();
+            }
+            scrollVal = calSumWidth($(tabElement).prevAll());
+            if (scrollVal > 0) {
+                $('.page-tabs-content').animate({ marginLeft: 0 - scrollVal + 'px' }, "fast");
+            }
+        }
+    }
+
+    //通过遍历给菜单项加上data-index属性
+    $(".menuItem").each(function(index) {
+        if (!$(this).attr('data-index')) {
+            $(this).attr('data-index', index);
+        }
+    });
+
+    function menuItem() {
+        // 获取标识数据
+        var dataUrl = $(this).attr('href'),
+        dataIndex = $(this).data('index'),
+        menuName = $(this).data('title') || $.trim($(this).text()),
+        isRefresh = $(this).data("refresh"),
+        flag = true;
+
+        var $dataObj = $('a[href$="' + decodeURI(dataUrl) + '"]');
+        if (!$dataObj.hasClass("noactive")) {
+            $('.tab-pane li').removeClass("active");
+            $('.nav ul').removeClass("in");
+            $dataObj.parents("ul").addClass("in")
+            $dataObj.parents("li").addClass("active").siblings().removeClass("active").find('li').removeClass("active");
+            $dataObj.parents("ul").css('height', 'auto').height();
+            $(".nav ul li, .nav li").removeClass("selected");
+            $(this).parent("li").addClass("selected");
+        }
+        setIframeUrl(dataUrl);
+        if (dataUrl == undefined || $.trim(dataUrl).length == 0) return false;
+
+        // 选项卡菜单已存在
+        $('.menuTab').each(function() {
+            if ($(this).data('id') == dataUrl) {
+                if (!$(this).hasClass('active')) {
+                    $(this).addClass('active').siblings('.menuTab').removeClass('active');
+                    scrollToTab(this);
+                    // 显示tab对应的内容区
+                    $('.mainContent .RuoYi_iframe').each(function() {
+                        if ($(this).data('id') == dataUrl) {
+                            openToCurrentTab(this);
+                            return false;
+                        }
+                    });
+                }
+                if (isRefresh) {
+                    refreshTab();
+                }
+                flag = false;
+                return false;
+            }
+        });
+        // 选项卡菜单不存在
+        if (flag) {
+            var str = '<a href="javascript:;" class="active menuTab" data-id="' + dataUrl + '">' + menuName + ' <i class="fa fa-times-circle"></i></a>';
+            $('.menuTab').removeClass('active');
+
+            // 添加选项卡对应的iframe
+            var str1 = '<iframe class="RuoYi_iframe" name="iframe' + dataIndex + '" width="100%" height="100%" src="' + dataUrl + '" frameborder="0" data-id="' + dataUrl + '" data-refresh="' + isRefresh + '" seamless></iframe>';
+            if (isScrollToTop) {
+                $('.mainContent').find('iframe.RuoYi_iframe').hide();
+            } else {
+                $('.mainContent').find('iframe.RuoYi_iframe').css({"visibility": "hidden", "position": "absolute", "left": "0", "top": "0"});
+            }
+            $('.mainContent').append(str1);
+            
+            $.modal.loading("数据加载中,请稍候...");
+
+            $('.mainContent iframe:visible').on('load', function() {
+            	$.modal.closeLoading();
+            });
+
+            // 添加选项卡
+            $('.menuTabs .page-tabs-content').append(str);
+            scrollToTab($('.menuTab.active'));
+        }
+        return false;
+    }
+
+    function menuBlank() {
+    	// 新窗口打开外网以http://开头,如http://ruoyi.vip
+    	var dataUrl = $(this).attr('href');
+    	window.open(dataUrl);
+    	return false;
+    }
+
+    $('.menuItem').on('click', menuItem);
+
+    $('.menuBlank').on('click', menuBlank);
+
+    // 关闭选项卡菜单
+    function closeTab() {
+        var closeTabId = $(this).parents('.menuTab').data('id');
+        var currentWidth = $(this).parents('.menuTab').width();
+        var panelUrl = $(this).parents('.menuTab').data('panel');
+        // 当前元素处于活动状态
+        if ($(this).parents('.menuTab').hasClass('active')) {
+
+            // 当前元素后面有同辈元素,使后面的一个元素处于活动状态
+            if ($(this).parents('.menuTab').next('.menuTab').length) {
+
+                var activeId = $(this).parents('.menuTab').next('.menuTab:eq(0)').data('id');
+                $(this).parents('.menuTab').next('.menuTab:eq(0)').addClass('active');
+
+                $('.mainContent .RuoYi_iframe').each(function() {
+                    if ($(this).data('id') == activeId) {
+                        openToCurrentTab(this);
+                        return false;
+                    }
+                });
+
+                var marginLeftVal = parseInt($('.page-tabs-content').css('margin-left'));
+                if (marginLeftVal < 0) {
+                    $('.page-tabs-content').animate({ marginLeft: (marginLeftVal + currentWidth) + 'px' }, "fast");
+                }
+
+                //  移除当前选项卡
+                $(this).parents('.menuTab').remove();
+
+                // 移除tab对应的内容区
+                $('.mainContent .RuoYi_iframe').each(function() {
+                    if ($(this).data('id') == closeTabId) {
+                        $(this).remove();
+                        return false;
+                    }
+                });
+            }
+
+            // 当前元素后面没有同辈元素,使当前元素的上一个元素处于活动状态
+            if ($(this).parents('.menuTab').prev('.menuTab').length) {
+                var activeId = $(this).parents('.menuTab').prev('.menuTab:last').data('id');
+                $(this).parents('.menuTab').prev('.menuTab:last').addClass('active');
+                $('.mainContent .RuoYi_iframe').each(function() {
+                    if ($(this).data('id') == activeId) {
+                        openToCurrentTab(this);
+                        return false;
+                    }
+                });
+
+                //  移除当前选项卡
+                $(this).parents('.menuTab').remove();
+
+                // 移除tab对应的内容区
+                $('.mainContent .RuoYi_iframe').each(function() {
+                    if ($(this).data('id') == closeTabId) {
+                        $(this).remove();
+                        return false;
+                    }
+                });
+
+                if ($.common.isNotEmpty(panelUrl)) {
+            		$('.menuTab[data-id="' + panelUrl + '"]').addClass('active').siblings('.menuTab').removeClass('active');
+            		$('.mainContent .RuoYi_iframe').each(function() {
+                        if ($(this).data('id') == panelUrl) {
+                            openToCurrentTab(this);
+                            return false;
+                        }
+                    });
+            	}
+            }
+        }
+        // 当前元素不处于活动状态
+        else {
+            //  移除当前选项卡
+            $(this).parents('.menuTab').remove();
+
+            // 移除相应tab对应的内容区
+            $('.mainContent .RuoYi_iframe').each(function() {
+                if ($(this).data('id') == closeTabId) {
+                    $(this).remove();
+                    return false;
+                }
+            });
+        }
+        scrollToTab($('.menuTab.active'));
+        syncMenuTab($.common.isNotEmpty(panelUrl) ? panelUrl : $('.page-tabs-content').find('.active').attr('data-id'));
+        return false;
+    }
+
+    $('.menuTabs').on('click', '.menuTab i', closeTab);
+
+    //滚动到已激活的选项卡
+    function showActiveTab() {
+        scrollToTab($('.menuTab.active'));
+    }
+    $('.tabShowActive').on('click', showActiveTab);
+
+    // 点击选项卡菜单
+    function activeTab() {
+        if (!$(this).hasClass('active')) {
+            var currentId = $(this).data('id');
+            var isRefresh = false;
+            syncMenuTab(currentId);
+            // 显示tab对应的内容区
+            $('.mainContent .RuoYi_iframe').each(function() {
+                if ($(this).data('id') == currentId) {
+                    openToCurrentTab(this);
+                    isRefresh = $.common.nullToDefault($(this).data('refresh'), false);
+                    return false;
+                }
+            });
+            $(this).addClass('active').siblings('.menuTab').removeClass('active');
+            if (isRefresh) {
+                refreshTab();
+            }
+            scrollToTab(this);
+        }
+    }
+
+    // 点击选项卡菜单
+    $('.menuTabs').on('click', '.menuTab', activeTab);
+
+    // 刷新iframe
+    function refreshTab() {
+    	var currentId = $('.page-tabs-content').find('.active').attr('data-id');
+    	var target = $('.RuoYi_iframe[data-id="' + currentId + '"]');
+        var url = target.attr('src');
+    	target.attr('src', url).ready();
+    }
+
+    // 页签全屏
+    function fullScreenTab() {
+    	var currentId = $('.page-tabs-content').find('.active').attr('data-id');
+    	var target = $('.RuoYi_iframe[data-id="' + currentId + '"]');
+    	target.fullScreen(true);
+    }
+
+    // 关闭当前选项卡
+    function tabCloseCurrent() {
+    	$('.page-tabs-content').find('.active i').trigger("click");
+    }
+
+    //关闭其他选项卡
+    function tabCloseOther() {
+        $('.page-tabs-content').children("[data-id]").not(":first").not(".active").each(function() {
+            $('.RuoYi_iframe[data-id="' + $(this).data('id') + '"]').remove();
+            $(this).remove();
+        });
+        $('.page-tabs-content').animate({ marginLeft: '0px' }, "fast");
+    }
+
+    // 关闭全部选项卡
+    function tabCloseAll() {
+    	$('.page-tabs-content').children("[data-id]").not(":first").each(function() {
+            $('.RuoYi_iframe[data-id="' + $(this).data('id') + '"]').remove();
+            $(this).remove();
+        });
+        $('.page-tabs-content').children("[data-id]:first").each(function() {
+            if (isScrollToTop) {
+                $('.RuoYi_iframe[data-id="' + $(this).data('id') + '"]').show();
+            } else {
+                $('.RuoYi_iframe[data-id="' + $(this).data('id') + '"]').css({"visibility": "visible", "position": "static"});
+            }
+            $(this).addClass("active");
+        });
+        $('.page-tabs-content').css("margin-left", "0");
+        syncMenuTab($('.page-tabs-content').find('.active').attr('data-id'));
+    }
+
+
+    // 全屏显示
+    $('#fullScreen').on('click', function () {
+    	$(document).toggleFullScreen();
+    });
+    
+    // 锁定屏幕
+    $('#lockScreen').on('click', function () {
+    	storage.set('lockPath', $('.page-tabs-content').find('.active').attr('data-id'));
+    	location.href  = ctx + "lockscreen";
+    });
+
+    // 页签刷新按钮
+    $('.tabReload').on('click', refreshTab);
+
+    // 页签全屏按钮
+    $('.tabFullScreen').on('click', fullScreenTab);
+
+    // 双击选项卡全屏显示
+    $('.menuTabs').on('dblclick', '.menuTab', activeTabMax);
+
+    // 左移按扭
+    $('.tabLeft').on('click', scrollTabLeft);
+
+    // 右移按扭
+    $('.tabRight').on('click', scrollTabRight);
+
+    // 关闭当前
+    $('.tabCloseCurrent').on('click', tabCloseCurrent);
+
+    // 关闭其他
+    $('.tabCloseOther').on('click', tabCloseOther);
+
+    // 关闭全部
+    $('.tabCloseAll').on('click', tabCloseAll);
+
+    // tab全屏显示
+    $('.tabMaxCurrent').on('click', function () {
+        $('.page-tabs-content').find('.active').trigger("dblclick");
+    });
+
+    // 关闭全屏
+    $('#ax_close_max').click(function(){
+    	$('#content-main').toggleClass('max');
+    	$('#ax_close_max').hide();
+    })
+
+    // 双击选项卡全屏显示
+    function activeTabMax() {
+        $('#content-main').toggleClass('max');
+        $('#ax_close_max').show();
+    }
+
+    $(window).keydown(function(event) {
+        if (event.keyCode == 27) {
+            $('#content-main').removeClass('max');
+            $('#ax_close_max').hide();
+        }
+    });
+
+    window.onhashchange = function() {
+        var hash = location.hash;
+        var url = hash.substring(1, hash.length);
+        $('a[href$="' + url + '"]').click();
+    };
+
+    // 右键菜单实现
+    $.contextMenu({
+        selector: ".menuTab",
+        trigger: 'right',
+        autoHide: true,
+        items: {
+            "close_current": {
+                name: "关闭当前",
+                icon: "fa-close",
+                callback: function(key, opt) {
+                    opt.$trigger.find('i').trigger("click");
+                }
+            },
+            "close_other": {
+                name: "关闭其他",
+                icon: "fa-window-close-o",
+                callback: function(key, opt) {
+                    setActiveTab(this);
+                    tabCloseOther();
+                }
+            },
+            "close_left": {
+                name: "关闭左侧",
+                icon: "fa-reply",
+                callback: function(key, opt) {
+                    setActiveTab(this);
+                    this.prevAll('.menuTab').not(":last").each(function() {
+                        if ($(this).hasClass('active')) {
+                            setActiveTab(this);
+                        }
+                        $('.RuoYi_iframe[data-id="' + $(this).data('id') + '"]').remove();
+                        $(this).remove();
+                    });
+                    $('.page-tabs-content').animate({ marginLeft: '0px' }, "fast");
+                }
+            },
+            "close_right": {
+                name: "关闭右侧",
+                icon: "fa-share",
+                callback: function(key, opt) {
+                    setActiveTab(this);
+                    this.nextAll('.menuTab').each(function() {
+                        $('.RuoYi_iframe[data-id="' + $(this).data('id') + '"]').remove();
+                        $(this).remove();
+                    });
+                }
+            },
+            "close_all": {
+                name: "全部关闭",
+                icon: "fa-window-close",
+                callback: function(key, opt) {
+                    tabCloseAll();
+                }
+            },
+            "step": "---------",
+            "full": {
+                name: "全屏显示",
+                icon: "fa-arrows-alt",
+                callback: function(key, opt) {
+                    setActiveTab(this);
+                    var target = $('.RuoYi_iframe[data-id="' + this.data('id') + '"]');
+                    target.fullScreen(true);
+                }
+            },
+            "refresh": {
+                name: "刷新页面",
+                icon: "fa-refresh",
+                callback: function(key, opt) {
+                    setActiveTab(this);
+                    var target = $('.RuoYi_iframe[data-id="' + this.data('id') + '"]');
+                    var url = target.attr('src');
+                    $.modal.loading("数据加载中,请稍候...");
+                    target.attr('src', url).on('load', function() {
+                    	$.modal.closeLoading();
+                    });
+                }
+            },
+            "open": {
+                name: "新窗口打开",
+                icon: "fa-link",
+                callback: function(key, opt) {
+                    var target = $('.RuoYi_iframe[data-id="' + this.data('id') + '"]');
+                    window.open(target.attr('src'));
+                }
+            },
+        }
+    });
+});
diff --git a/ruoyi-admin/src/main/resources/static/ruoyi/js/common.js b/ruoyi-admin/src/main/resources/static/ruoyi/js/common.js
new file mode 100644
index 0000000..e551514
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ruoyi/js/common.js
@@ -0,0 +1,587 @@
+/**
+ * 通用方法封装处理
+ * Copyright (c) 2019 ruoyi 
+ */
+
+var startLayDate;
+var endLayDate;
+var isScrollToTop = parent.isScrollToTop;
+
+$(function() {
+	
+    // 回到顶部绑定
+    if ($.fn.toTop !== undefined) {
+        $('#scroll-up').toTop();
+    }
+	
+    // select2复选框事件绑定
+    if ($.fn.select2 !== undefined) {
+        $.fn.select2.defaults.set( "theme", "bootstrap" );
+        $("select.form-control:not(.noselect2)").each(function () {
+            $(this).select2().on("change", function () {
+                $(this).valid();
+            })
+        })
+    }
+	
+    // iCheck单选框及复选框事件绑定
+    if ($.fn.iCheck !== undefined) {
+        $(".check-box:not(.noicheck),.radio-box:not(.noicheck)").each(function() {
+            $(this).iCheck({
+                checkboxClass: 'icheckbox-blue',
+                radioClass: 'iradio-blue',
+            })
+        })
+    }
+	
+    // 取消回车自动提交表单
+    $(document).on("keypress", ":input:not(textarea):not([type=submit])", function(event) {
+        if (event.keyCode == 13) {
+            event.preventDefault();
+        }
+    });
+	 
+    // laydate 时间控件绑定
+    if ($(".select-time").length > 0 && $('#startTime').length > 0 && $('#endTime').length > 0) {
+       layui.use('laydate', function() {
+            var laydate = layui.laydate;
+            startLayDate = laydate.render({
+                elem: '#startTime',
+                max: $('#endTime').val(),
+                theme: 'molv',
+                type: $('#startTime').attr("data-type") || 'date',
+                trigger: 'click',
+                done: function(value, date) {
+                    // 结束时间大于开始时间
+                    if (value !== '') {
+                        endLayDate.config.min.year = date.year;
+                        endLayDate.config.min.month = date.month - 1;
+                        endLayDate.config.min.date = date.date;
+                    } else {
+                        endLayDate.config.min.year = '';
+                        endLayDate.config.min.month = '';
+                        endLayDate.config.min.date = '';
+                    }
+                    $('#endTime').trigger('click');
+                }
+            });
+            endLayDate = laydate.render({
+                elem: '#endTime',
+                min: $('#startTime').val(),
+                theme: 'molv',
+                type: $('#endTime').attr("data-type") || 'date',
+                trigger: 'click',
+                done: function(value, date) {
+                    // 开始时间小于结束时间
+                    if (value !== '') {
+                        startLayDate.config.max.year = date.year;
+                        startLayDate.config.max.month = date.month - 1;
+                        startLayDate.config.max.date = date.date;
+                    } else {
+                        startLayDate.config.max.year = '2099';
+                        startLayDate.config.max.month = '12';
+                        startLayDate.config.max.date = '31';
+                    }
+                }
+            });
+        });
+    }
+	
+    // laydate time-input 时间控件绑定
+    if ($(".time-input").length > 0) {
+        layui.use('laydate', function () {
+            var com = layui.laydate;
+            $(".time-input").each(function (index, item) {
+                var time = $(item);
+                // 控制控件外观
+                var type = time.attr("data-type") || 'date';
+                // 控制回显格式
+                var format = time.attr("data-format") || 'yyyy-MM-dd';
+                // 控制日期控件按钮
+                var buttons = time.attr("data-btn") || 'clear|now|confirm', newBtnArr = [];
+                // 日期控件选择完成后回调处理
+                var callback = time.attr("data-callback") || {};
+                if (buttons) {
+                    if (buttons.indexOf("|") > 0) {
+                        var btnArr = buttons.split("|"), btnLen = btnArr.length;
+                        for (var j = 0; j < btnLen; j++) {
+                            if ("clear" === btnArr[j] || "now" === btnArr[j] || "confirm" === btnArr[j]) {
+                                newBtnArr.push(btnArr[j]);
+                            }
+                        }
+                    } else {
+                        if ("clear" === buttons || "now" === buttons || "confirm" === buttons) {
+                            newBtnArr.push(buttons);
+                        }
+                    }
+                } else {
+                    newBtnArr = ['clear', 'now', 'confirm'];
+                }
+                com.render({
+                    elem: item,
+                    theme: 'molv',
+                    trigger: 'click',
+                    type: type,
+                    format: format,
+                    btns: newBtnArr,
+                    done: function (value, data) {
+                        if (typeof window[callback] != 'undefined'
+                            && window[callback] instanceof Function) {
+                            window[callback](value, data);
+                        }
+                    }
+                });
+            });
+        });
+    }
+	
+    // tree 关键字搜索绑定
+    if ($("#keyword").length > 0) {
+        $("#keyword").bind("focus", function focusKey(e) {
+            if ($("#keyword").hasClass("empty")) {
+                $("#keyword").removeClass("empty");
+            }
+        }).bind("blur", function blurKey(e) {
+            if ($("#keyword").val() === "") {
+                $("#keyword").addClass("empty");
+            }
+            $.tree.searchNode(e);
+        }).bind("input propertychange", $.tree.searchNode);
+    }
+	
+    // tree表格树 展开/折叠
+    var expandFlag;
+    $("#expandAllBtn").click(function() {
+        var dataExpand = $.common.isEmpty(table.options.expandAll) ? true : table.options.expandAll;
+        expandFlag = $.common.isEmpty(expandFlag) ? dataExpand : expandFlag;
+        if (!expandFlag) {
+            $.bttTable.bootstrapTreeTable('expandAll');
+        } else {
+            $.bttTable.bootstrapTreeTable('collapseAll');
+        }
+        expandFlag = expandFlag ? false: true;
+    })
+	
+    // 按下ESC按钮关闭弹层
+    $('body', document).on('keyup', function(e) {
+        if (e.which === 27) {
+            $.modal.closeAll();
+        }
+    });
+});
+
+(function ($) {
+    'use strict';
+    $.fn.toTop = function(opt) {
+        var elem = this;
+        var win = (opt && opt.hasOwnProperty('win')) ? opt.win : $(window);
+        var doc = (opt && opt.hasOwnProperty('doc')) ? opt.doc : $('html, body');
+        var options = $.extend({
+            autohide: true,
+            offset: 50,
+            speed: 500,
+            position: true,
+            right: 15,
+            bottom: 5
+        }, opt);
+        elem.css({
+            'cursor': 'pointer'
+        });
+        if (options.autohide) {
+            elem.css('display', 'none');
+        }
+        if (options.position) {
+            elem.css({
+                'position': 'fixed',
+                'right': options.right,
+                'bottom': options.bottom,
+            });
+        }
+        elem.click(function() {
+            doc.animate({
+                scrollTop: 0
+            }, options.speed);
+        });
+        win.scroll(function() {
+            var scrolling = win.scrollTop();
+            if (options.autohide) {
+                if (scrolling > options.offset) {
+                    elem.fadeIn(options.speed);
+                } else elem.fadeOut(options.speed);
+            }
+        });
+    };
+})(jQuery);
+
+/** 刷新选项卡 */
+var refreshItem = function(){
+    var topWindow = $(window.parent.document);
+    var currentId = $('.page-tabs-content', topWindow).find('.active').attr('data-id');
+    var target = $('.RuoYi_iframe[data-id="' + currentId + '"]', topWindow);
+    var url = target.attr('src');
+    target.attr('src', url).ready();
+}
+
+/** 关闭选项卡 */
+var closeItem = function(dataId){
+	var topWindow = $(window.parent.document);
+	if ($.common.isNotEmpty(dataId)) {
+	    window.parent.$.modal.closeLoading();
+	    // 根据dataId关闭指定选项卡
+	    $('.menuTab[data-id="' + dataId + '"]', topWindow).remove();
+	    // 移除相应tab对应的内容区
+	    $('.mainContent .RuoYi_iframe[data-id="' + dataId + '"]', topWindow).remove();
+	    return;
+	}
+	var panelUrl = window.frameElement.getAttribute('data-panel');
+	$('.page-tabs-content .active i', topWindow).click();
+	if ($.common.isNotEmpty(panelUrl)) {
+	    $('.menuTab[data-id="' + panelUrl + '"]', topWindow).addClass('active').siblings('.menuTab').removeClass('active');
+	    $('.mainContent .RuoYi_iframe', topWindow).each(function() {
+	        if ($(this).data('id') == panelUrl) {
+	            openToCurrentTab(this);
+	            return false;
+            }
+        });
+    }
+}
+
+/** 创建选项卡 */
+function createMenuItem(dataUrl, menuName, isRefresh) {
+    var panelUrl = window.frameElement.getAttribute('data-id'),
+    dataIndex = $.common.random(1, 100),
+    flag = true;
+    if (dataUrl == undefined || $.trim(dataUrl).length == 0) return false;
+    var topWindow = $(window.parent.document);
+    // 选项卡菜单已存在
+    $('.menuTab', topWindow).each(function() {
+        if ($(this).data('id') == dataUrl) {
+            if (!$(this).hasClass('active')) {
+                $(this).addClass('active').siblings('.menuTab').removeClass('active');
+                scrollToTab(this);
+                $('.page-tabs-content').animate({ marginLeft: ""}, "fast");
+                // 显示tab对应的内容区
+                $('.mainContent .RuoYi_iframe', topWindow).each(function() {
+                    if ($(this).data('id') == dataUrl) {
+                        openToCurrentTab(this);
+                        return false;
+                    }
+                });
+            }
+            if (isRefresh) {
+                refreshTab();
+            }
+            flag = false;
+            return false;
+        }
+    });
+    // 选项卡菜单不存在
+    if (flag) {
+        var str = '<a href="javascript:;" class="active menuTab noactive" data-id="' + dataUrl + '" data-panel="' + panelUrl + '">' + menuName + ' <i class="fa fa-times-circle"></i></a>';
+        $('.menuTab', topWindow).removeClass('active');
+
+        // 添加选项卡对应的iframe
+        var str1 = '<iframe class="RuoYi_iframe" name="iframe' + dataIndex + '" width="100%" height="100%" src="' + dataUrl + '" frameborder="0" data-id="' + dataUrl + '" data-panel="' + panelUrl + '" seamless></iframe>';
+        if (isScrollToTop) {
+            $('.mainContent', topWindow).find('iframe.RuoYi_iframe').hide();
+        } else {
+            $('.mainContent', topWindow).find('iframe.RuoYi_iframe').css({"visibility": "hidden", "position": "absolute", "left": "0", "top": "0"});
+        }
+        $('.mainContent', topWindow).append(str1);
+        
+        window.parent.$.modal.loading("数据加载中,请稍候...");
+        $('.mainContent iframe:visible', topWindow).on('load', function() {
+            window.parent.$.modal.closeLoading();
+        });
+
+        // 添加选项卡
+        $('.menuTabs .page-tabs-content', topWindow).append(str);
+        scrollToTab($('.menuTab.active', topWindow));
+    }
+    return false;
+}
+
+// 刷新iframe
+function refreshTab() {
+	var topWindow = $(window.parent.document);
+	var currentId = $('.page-tabs-content', topWindow).find('.active').attr('data-id');
+	var target = $('.RuoYi_iframe[data-id="' + currentId + '"]', topWindow);
+    var url = target.attr('src');
+	target.attr('src', url).ready();
+}
+
+// 滚动到指定选项卡
+function scrollToTab(element) {
+    var topWindow = $(window.parent.document);
+    var marginLeftVal = calSumWidth($(element).prevAll()),
+    marginRightVal = calSumWidth($(element).nextAll());
+    // 可视区域非tab宽度
+    var tabOuterWidth = calSumWidth($(".content-tabs", topWindow).children().not(".menuTabs"));
+    //可视区域tab宽度
+    var visibleWidth = $(".content-tabs", topWindow).outerWidth(true) - tabOuterWidth;
+    //实际滚动宽度
+    var scrollVal = 0;
+    if ($(".page-tabs-content", topWindow).outerWidth() < visibleWidth) {
+        scrollVal = 0;
+    } else if (marginRightVal <= (visibleWidth - $(element).outerWidth(true) - $(element).next().outerWidth(true))) {
+        if ((visibleWidth - $(element).next().outerWidth(true)) > marginRightVal) {
+            scrollVal = marginLeftVal;
+            var tabElement = element;
+            while ((scrollVal - $(tabElement).outerWidth()) > ($(".page-tabs-content", topWindow).outerWidth() - visibleWidth)) {
+                scrollVal -= $(tabElement).prev().outerWidth();
+                tabElement = $(tabElement).prev();
+            }
+        }
+    } else if (marginLeftVal > (visibleWidth - $(element).outerWidth(true) - $(element).prev().outerWidth(true))) {
+        scrollVal = marginLeftVal - $(element).prev().outerWidth(true);
+    }
+    $('.page-tabs-content', topWindow).animate({ marginLeft: 0 - scrollVal + 'px' }, "fast");
+}
+
+// 计算元素集合的总宽度
+function calSumWidth(elements) {
+    var width = 0;
+    $(elements).each(function() {
+        width += $(this).outerWidth(true);
+    });
+    return width;
+}
+
+// 返回当前激活的Tab页面关联的iframe的Windows对象
+function activeWindow() {
+	var topWindow = $(window.parent.document);
+	var currentId = $('.page-tabs-content', topWindow).find('.active').attr('data-id');
+	if (!currentId) {
+		return window.parent;
+	}
+    return $('.RuoYi_iframe[data-id="' + currentId + '"]', topWindow)[0].contentWindow;
+}
+
+function openToCurrentTab(obj) {
+    if (isScrollToTop) {
+        $(obj).show().siblings('.RuoYi_iframe').hide();
+    } else {
+        $(obj).css({"visibility": "visible", "position": "static"}).siblings('.RuoYi_iframe').css({"visibility": "hidden", "position": "absolute", "left": "0", "top": "0"});
+    }
+}
+
+/** 密码规则范围验证 */
+function checkpwd(chrtype, password) {
+    if (chrtype == 1) {
+        if (!$.common.numValid(password)) {
+            $.modal.alertWarning("密码只能为0-9数字");
+            return false;
+        }
+    } else if (chrtype == 2) {
+        if (!$.common.enValid(password)) {
+            $.modal.alertWarning("密码只能为a-z和A-Z字母");
+            return false;
+        }
+    } else if (chrtype == 3) {
+        if (!$.common.enNumValid(password)) {
+            $.modal.alertWarning("密码必须包含字母以及数字");
+            return false;
+        }
+    } else if (chrtype == 4) {
+        if (!$.common.charValid(password)) {
+            $.modal.alertWarning("密码必须包含字母、数字、以及特殊符号<font color='red'>~!@#$%^&*()-=_+</font>");
+            return false;
+        }
+    }
+    return true;
+}
+
+/** 开始时间/时分秒 */
+function beginOfTime(date) {
+    if ($.common.isNotEmpty(date)) {
+        return $.common.sprintf("%s 00:00:00", date);
+    }
+}
+
+/** 结束时间/时分秒 */
+function endOfTime(date) {
+    if ($.common.isNotEmpty(date)) {
+        return $.common.sprintf("%s 23:59:59", date);
+    }
+}
+
+/** 重置日期/年月日 */
+function resetDate() {
+	if ($.common.isNotEmpty(startLayDate) && $.common.isNotEmpty(endLayDate)) {
+	    endLayDate.config.min.year = '';
+	    endLayDate.config.min.month = '';
+	    endLayDate.config.min.date = '';
+	    startLayDate.config.max.year = '2099';
+	    startLayDate.config.max.month = '12';
+	    startLayDate.config.max.date = '31';
+	}
+}
+
+// 日志打印封装处理
+var log = {
+    log: function(msg) {
+        console.log(msg);
+    },
+    info: function(msg) {
+        console.info(msg);
+    },
+    warn: function(msg) {
+        console.warn(msg);
+    },
+    error: function(msg) {
+        console.error(msg);
+    }
+};
+
+// 本地缓存处理
+var storage = {
+    set: function(key, value) {
+        window.localStorage.setItem(key, value);
+    },
+    get: function(key) {
+        return window.localStorage.getItem(key);
+    },
+    remove: function(key) {
+        window.localStorage.removeItem(key);
+    },
+    clear: function() {
+        window.localStorage.clear();
+    }
+};
+
+// 主子表操作封装处理
+var sub = {
+    editRow: function() {
+    	var dataColumns = [];
+		for (var columnIndex = 0; columnIndex < table.options.columns.length; columnIndex++) {
+    		if (table.options.columns[columnIndex].visible != false) {
+    			dataColumns.push(table.options.columns[columnIndex]);
+    		}
+    	}
+		var params = new Array();
+		var data = $("#" + table.options.id).bootstrapTable('getData');
+    	var count = data.length;
+    	for (var dataIndex = 0; dataIndex < count; dataIndex++) {
+    	    var columns = $('#' + table.options.id + ' tr[data-index="' + dataIndex + '"] td:visible');
+    	    var obj = new Object();
+    	    for (var i = 0; i < columns.length; i++) {
+    	        var inputValue = $(columns[i]).find('input');
+    	        var selectValue = $(columns[i]).find('select');
+    	        var textareaValue = $(columns[i]).find('textarea');
+    	        var key = dataColumns[i].field;
+    	        if ($.common.isNotEmpty(inputValue.val())) {
+    	            obj[key] = inputValue.val();
+    	        } else if ($.common.isNotEmpty(selectValue.val())) {
+    	            obj[key] = selectValue.val();
+    	        } else if ($.common.isNotEmpty(textareaValue.val())) {
+    	            obj[key] = textareaValue.val();
+    	        } else {
+    	            if (key == "index" && $.common.isNotEmpty(data[dataIndex].index)) {
+    	                obj[key] = data[dataIndex].index;
+    	            } else {
+    	                obj[key] = "";
+    	            }
+    	        }
+    	    }
+    	    var item = data[dataIndex];
+    	    var extendObj = $.extend({}, item, obj);
+    	    params.push({ index: dataIndex, row: extendObj });
+    	}
+    	$("#" + table.options.id).bootstrapTable("updateRow", params);
+    },
+    delRow: function(column) {
+    	sub.editRow();
+    	var subColumn = $.common.isEmpty(column) ? "index" : column;
+    	var ids = $.table.selectColumns(subColumn);
+        if (ids.length == 0) {
+            $.modal.alertWarning("请至少选择一条记录");
+            return;
+        }
+        $("#" + table.options.id).bootstrapTable('remove', { field: subColumn, values: ids });
+    },
+    delRowByIndex: function(value, tableId) {
+    	var currentId = $.common.isEmpty(tableId) ? table.options.id : tableId;
+    	sub.editRow();
+        $("#" + currentId).bootstrapTable('remove', { field: "index", values: [value] });
+        sub.editRow();
+    },
+    addRow: function(row, tableId) {
+    	var currentId = $.common.isEmpty(tableId) ? table.options.id : tableId;
+    	table.set(currentId);
+    	var count = $("#" + currentId).bootstrapTable('getData').length;
+    	sub.editRow();
+    	$("#" + currentId).bootstrapTable('insertRow', { index: count + 1, row: row });
+    }
+};
+
+// 动态加载css文件
+function loadCss(file, headElem) {
+    var link = document.createElement('link');
+    link.href = file;
+    link.rel = 'stylesheet';
+    link.type = 'text/css';
+    if (headElem) headElem.appendChild(link);
+    else document.getElementsByTagName('head')[0].appendChild(link);
+}
+
+// 动态加载js文件
+function loadJs(file, headElem) {
+    var script = document.createElement('script');
+    script.src = file;
+    script.type = 'text/javascript';
+    if (headElem) headElem.appendChild(script);
+    else document.getElementsByTagName('head')[0].appendChild(script);
+}
+
+// 禁止后退键(Backspace)
+window.onload = function() {
+	document.getElementsByTagName("body")[0].onkeydown = function() {
+		// 获取事件对象  
+		var elem = event.relatedTarget || event.srcElement || event.target || event.currentTarget;
+		// 判断按键为backSpace键  
+		if (event.keyCode == 8) {
+			// 判断是否需要阻止按下键盘的事件默认传递  
+			var name = elem.nodeName;
+			var className = elem.className;
+			// 屏蔽特定的样式名称
+			if (className.indexOf('note-editable') != -1)
+			{
+				return true;
+			}
+			if (name != 'INPUT' && name != 'TEXTAREA') {
+				return _stopIt(event);
+			}
+			var type_e = elem.type.toUpperCase();
+			if (name == 'INPUT' && (type_e != 'TEXT' && type_e != 'TEXTAREA' && type_e != 'PASSWORD' && type_e != 'FILE' && type_e != 'SEARCH' && type_e != 'NUMBER' && type_e != 'EMAIL' && type_e != 'URL')) {
+				return _stopIt(event);
+			}
+			if (name == 'INPUT' && (elem.readOnly == true || elem.disabled == true)) {
+				return _stopIt(event);
+			}
+		}
+	};
+};
+function _stopIt(e) {
+	if (e.returnValue) {
+		e.returnValue = false;
+	}
+	if (e.preventDefault) {
+		e.preventDefault();
+	}
+	return false;
+}
+
+/** 设置全局ajax处理 */
+$.ajaxSetup({
+    complete: function(XMLHttpRequest, textStatus) {
+        if (textStatus == 'timeout') {
+            $.modal.alertWarning("服务器超时,请稍后再试!");
+            $.modal.enable();
+            $.modal.closeLoading();
+        } else if (textStatus == "parsererror" || textStatus == "error") {
+            $.modal.alertWarning("服务器错误,请联系管理员!");
+            $.modal.enable();
+            $.modal.closeLoading();
+        }
+    }
+});
diff --git a/ruoyi-admin/src/main/resources/static/ruoyi/js/ry-ui.js b/ruoyi-admin/src/main/resources/static/ruoyi/js/ry-ui.js
new file mode 100644
index 0000000..8dcfc90
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ruoyi/js/ry-ui.js
@@ -0,0 +1,1793 @@
+/**
+ * 通用js方法封装处理
+ * Copyright (c) 2019 ruoyi
+ */
+
+// 当前table相关信息
+var table = {
+    config: {},
+    // 当前实例配置
+    options: {},
+    // 设置实例配置
+    set: function(id) {
+        if ($.common.getLength(table.config) > 1 && $.common.isNotEmpty(event)) {
+            var tableId = $.common.isEmpty(id) ? $(event.currentTarget).parents(".bootstrap-table").find("table.table").attr("id") || $(event.currentTarget).parents(".bootstrap-tree-table").find("table.table").attr("id") : id;
+            if ($.common.isNotEmpty(tableId)) {
+                table.options = table.get(tableId);
+            }
+        }
+    },
+    // 获取实例配置
+    get: function(id) {
+        return table.config[id];
+    },
+    // 记住选择实例组
+    rememberSelecteds: {},
+    // 记住选择ID组
+    rememberSelectedIds: {}
+};
+
+(function ($) {
+    $.extend({
+        _tree: {},
+        bttTable: {},
+        // 表格封装处理
+        table: {
+            // 初始化表格参数
+            init: function(options) {
+                var defaults = {
+                    id: "bootstrap-table",
+                    type: 0, // 0 代表bootstrapTable 1代表bootstrapTreeTable
+                    method: 'post',
+                    height: undefined,
+                    sidePagination: "server",
+                    undefinedText: '-',
+                    sortName: undefined,
+                    sortOrder: "asc",
+                    pagination: true,
+                    paginationLoop: false,
+                    pageSize: 10,
+                    pageNumber: 1,
+                    pageList: [10, 25, 50, 100],
+                    toolbar: "toolbar",
+                    loadingFontSize: 13,
+                    striped: false,
+                    escape: true,
+                    firstLoad: true,
+                    showFooter: false,
+                    search: false,
+                    showSearch: true,
+                    showPageGo: false,
+                    showRefresh: true,
+                    showColumns: true,
+                    showToggle: true,
+                    showExport: false,
+                    showPrint: false,
+                    exportDataType: 'all',
+                    exportTypes: ['csv', 'txt', 'doc', 'excel'],
+                    clickToSelect: false,
+                    singleSelect: false,
+                    mobileResponsive: true,
+                    maintainSelected: false,
+                    rememberSelected: false,
+                    fixedColumns: false,
+                    fixedNumber: 0,
+                    fixedRightNumber: 0,
+                    queryParams: $.table.queryParams,
+                    rowStyle: undefined
+                };
+                var options = $.extend(defaults, options);
+                table.options = options;
+                table.config[options.id] = options;
+                $.table.initEvent();
+                $('#' + options.id).bootstrapTable({
+                    id: options.id,
+                    url: options.url,                                   // 请求后台的URL(*)
+                    contentType: "application/x-www-form-urlencoded",   // 编码类型
+                    method: options.method,                             // 请求方式(*)
+                    cache: false,                                       // 是否使用缓存
+                    height: options.height,                             // 表格的高度
+                    striped: options.striped,                           // 是否显示行间隔色
+                    undefinedText: options.undefinedText,               // 数据值为空时显示的内容
+                    sortable: true,                                     // 是否启用排序
+                    sortStable: true,                                   // 设置为 true 将获得稳定的排序
+                    sortName: options.sortName,                         // 排序列名称
+                    sortOrder: options.sortOrder,                       // 排序方式  asc 或者 desc
+                    pagination: options.pagination,                     // 是否显示分页(*)
+                    paginationLoop: options.paginationLoop,             // 是否启用分页条无限循环的功能
+                    pageNumber: 1,                                      // 初始化加载第一页,默认第一页
+                    pageSize: options.pageSize,                         // 每页的记录行数(*) 
+                    pageList: options.pageList,                         // 可供选择的每页的行数(*)
+                    firstLoad: options.firstLoad,                       // 是否首次请求加载数据,对于数据较大可以配置false
+                    escape: options.escape,                             // 转义HTML字符串
+                    showFooter: options.showFooter,                     // 是否显示表尾
+                    iconSize: 'outline',                                // 图标大小:undefined默认的按钮尺寸 xs超小按钮sm小按钮lg大按钮
+                    toolbar: '#' + options.toolbar,                     // 指定工作栏
+                    virtualScroll: options.virtualScroll,               // 是否启动虚拟滚动(大量数据纯展示时使用)
+                    loadingFontSize: options.loadingFontSize,           // 自定义加载文本的字体大小
+                    sidePagination: options.sidePagination,             // server启用服务端分页client客户端分页
+                    search: options.search,                             // 是否显示搜索框功能
+                    searchText: options.searchText,                     // 搜索框初始显示的内容,默认为空
+                    showSearch: options.showSearch,                     // 是否显示检索信息
+                    showPageGo: options.showPageGo,                     // 是否显示跳转页
+                    showRefresh: options.showRefresh,                   // 是否显示刷新按钮
+                    showColumns: options.showColumns,                   // 是否显示隐藏某列下拉框
+                    showToggle: options.showToggle,                     // 是否显示详细视图和列表视图的切换按钮
+                    showExport: options.showExport,                     // 是否支持导出文件
+                    showPrint: options.showPrint,                       // 是否支持打印页面
+                    showHeader: options.showHeader,                     // 是否显示表头
+                    showFullscreen: options.showFullscreen,             // 是否显示全屏按钮
+                    uniqueId: options.uniqueId,                         // 唯一的标识符
+                    clickToSelect: options.clickToSelect,               // 是否启用点击选中行
+                    singleSelect: options.singleSelect,                 // 是否单选checkbox
+                    mobileResponsive: options.mobileResponsive,         // 是否支持移动端适配
+                    cardView: options.cardView,                         // 是否启用显示卡片视图
+                    detailView: options.detailView,                     // 是否启用显示细节视图
+                    onCheck: options.onCheck,                           // 当选择此行时触发
+                    onUncheck: options.onUncheck,                       // 当取消此行时触发
+                    onCheckAll: options.onCheckAll,                     // 当全选行时触发
+                    onUncheckAll: options.onUncheckAll,                 // 当取消全选行时触发
+                    onClickRow: options.onClickRow,                     // 点击某行触发的事件
+                    onDblClickRow: options.onDblClickRow,               // 双击某行触发的事件
+                    onClickCell: options.onClickCell,                   // 单击某格触发的事件
+                    onDblClickCell: options.onDblClickCell,             // 双击某格触发的事件
+                    onEditableSave: options.onEditableSave,             // 行内编辑保存的事件
+                    onExpandRow: options.onExpandRow,                   // 点击详细视图的事件
+                    onPostBody: options.onPostBody,                     // 渲染完成后执行的事件
+                    maintainSelected: options.maintainSelected,         // 前端翻页时保留所选行
+                    rememberSelected: options.rememberSelected,         // 启用翻页记住前面的选择
+                    fixedColumns: options.fixedColumns,                 // 是否启用冻结列(左侧)
+                    fixedNumber: options.fixedNumber,                   // 列冻结的个数(左侧)
+                    fixedRightNumber: options.fixedRightNumber,         // 列冻结的个数(右侧)
+                    onReorderRow: options.onReorderRow,                 // 当拖拽结束后处理函数
+                    queryParams: options.queryParams,                   // 传递参数(*)
+                    rowStyle: options.rowStyle,                         // 通过自定义函数设置行样式
+                    footerStyle: options.footerStyle,                   // 通过自定义函数设置页脚样式
+                    headerStyle: options.headerStyle,                   // 通过自定义函数设置标题样式
+                    columns: options.columns,                           // 显示列信息(*)
+                    data: options.data,                                 // 被加载的数据
+                    responseHandler: $.table.responseHandler,           // 在加载服务器发送来的数据之前处理函数
+                    onLoadSuccess: $.table.onLoadSuccess,               // 当所有数据被加载时触发处理函数
+                    exportOptions: options.exportOptions,               // 前端导出忽略列索引
+                    exportDataType: options.exportDataType,             // 导出方式(默认all:导出所有数据;basic:导出当前页的数据;selected:导出选中的数据)
+                    exportTypes: options.exportTypes,                   // 导出文件类型 (json、xml、png、csv、txt、sql、doc、excel、xlsx、powerpoint、pdf)
+                    printPageBuilder: options.printPageBuilder,         // 自定义打印页面模板
+                    detailFormatter: options.detailFormatter,           // 在行下面展示其他数据列表
+                });
+            },
+            // 获取实例ID,如存在多个返回#id1,#id2 delimeter分隔符
+            getOptionsIds: function(separator) {
+                var _separator = $.common.isEmpty(separator) ? "," : separator;
+                var optionsIds = "";  
+                $.each(table.config, function(key, value){
+                    optionsIds += "#" + key + _separator;
+                });
+                return optionsIds.substring(0, optionsIds.length - 1);
+            },
+            // 查询条件
+            queryParams: function(params) {
+                table.set();
+                var curParams = {
+                    // 传递参数查询参数
+                    pageSize:       params.limit,
+                    pageNum:        params.offset / params.limit + 1,
+                    searchValue:    params.search,
+                    orderByColumn:  params.sort,
+                    isAsc:          params.order
+                };
+                var currentId = $.common.isEmpty(table.options.formId) ? $('form').attr('id') : table.options.formId;
+                return $.extend(curParams, $.common.formToJSON(currentId)); 
+            },
+            // 请求获取数据后处理回调函数
+            responseHandler: function(res) {
+                if (typeof table.get(this.id).responseHandler == "function") {
+                    table.get(this.id).responseHandler(res);
+                }
+                var thisOptions = table.config[this.id];
+                if (res.code == web_status.SUCCESS) {
+                    if ($.common.isNotEmpty(thisOptions.sidePagination) && thisOptions.sidePagination == 'client') {
+                        return res.rows;
+                    } else {
+                        if ($.common.isNotEmpty(thisOptions.rememberSelected) && thisOptions.rememberSelected) {
+                            var column = $.common.isEmpty(thisOptions.uniqueId) ? thisOptions.columns[1].field : thisOptions.uniqueId;
+                            $.each(res.rows, function(i, row) {
+                                row.state = $.inArray(row[column], table.rememberSelectedIds[thisOptions.id]) !== -1;
+                            })
+                        }
+                        return { rows: res.rows, total: res.total };
+                    }
+                } else {
+                    $.modal.alertWarning(res.msg);
+                    return { rows: [], total: 0 };
+                }
+            },
+            // 初始化事件
+            initEvent: function() {
+                // 实例ID信息
+                var optionsIds = $.table.getOptionsIds();
+                // 监听事件处理
+                $(optionsIds).on(TABLE_EVENTS, function () {
+                    table.set($(this).attr("id"));
+                });
+                // 在表格体渲染完成,并在 DOM 中可见后触发(事件)
+                $(optionsIds).on("post-body.bs.table", function (e, args) {
+                    // 浮动提示框特效
+                    $(".table [data-toggle='tooltip']").tooltip();
+                    // 气泡弹出框特效
+                    $('.table [data-toggle="popover"]').popover();
+                });
+                // 选中、取消、全部选中、全部取消(事件)
+                $(optionsIds).on("check.bs.table check-all.bs.table uncheck.bs.table uncheck-all.bs.table", function (e, rowsAfter, rowsBefore) {
+                    // 复选框分页保留保存选中数组
+                    var rows = $.common.equals("uncheck-all", e.type) ? rowsBefore : rowsAfter;
+                    var rowIds = $.table.affectedRowIds(rows);
+                    if ($.common.isNotEmpty(table.options.rememberSelected) && table.options.rememberSelected) {
+                        func = $.inArray(e.type, ['check', 'check-all']) > -1 ? 'union' : 'difference';
+                        var selectedIds = table.rememberSelectedIds[table.options.id];
+                        if ($.common.isNotEmpty(selectedIds)) {
+                            table.rememberSelectedIds[table.options.id] = _[func](selectedIds, rowIds);
+                        } else {
+                            table.rememberSelectedIds[table.options.id] = _[func]([], rowIds);
+                        }
+                        var selectedRows = table.rememberSelecteds[table.options.id];
+                        if ($.common.isNotEmpty(selectedRows)) {
+                            table.rememberSelecteds[table.options.id] = _[func](selectedRows, rows);
+                        } else {
+                            table.rememberSelecteds[table.options.id] = _[func]([], rows);
+                        }
+                    }
+                });
+                // 加载成功、选中、取消、全部选中、全部取消(事件)
+                $(optionsIds).on("check.bs.table uncheck.bs.table check-all.bs.table uncheck-all.bs.table load-success.bs.table", function () {
+                    var toolbar = table.options.toolbar;
+                    var uniqueId = table.options.uniqueId;
+                    // 工具栏按钮控制
+                    var rows = $.common.isEmpty(uniqueId) ? $.table.selectFirstColumns() : $.table.selectColumns(uniqueId);
+                    // 非多个禁用
+                    $('#' + toolbar + ' .multiple').toggleClass('disabled', !rows.length);
+                    // 非单个禁用
+                    $('#' + toolbar + ' .single').toggleClass('disabled', rows.length!=1);
+                });
+                // 图片预览事件
+                $(optionsIds).off("click").on("click", '.img-circle', function() {
+                    var src = $(this).attr('src');
+                    var target = $(this).data('target');
+                    if ($.common.equals("self", target)) {
+                        var height = $(this).data('height');
+                        var width = $(this).data('width');
+                        top.layer.open({
+                            title: false,
+                            type: 1,
+                            closeBtn: true,
+                            shadeClose: true,
+                            content: "<img src='" + src + "' height='" + height + "' width='" + width + "'/>"
+                        });
+                    } else if ($.common.equals("blank", target)) {
+                        window.open(src);
+                    }
+                });
+                // 单击tooltip事件
+                $(optionsIds).on("click", '.tooltip-show', function() {
+                    var target = $(this).data('target');
+                    var input = $(this).prev();
+                    if ($.common.equals("copy", target)) {
+                        input.select();
+                        document.execCommand("copy");
+                    } else if ($.common.equals("open", target)) {
+                        top.layer.alert(input.val(), {
+                            title: "信息内容",
+                            shadeClose: true,
+                            btn: ['确认'],
+                            btnclass: ['btn btn-primary'],
+                        });
+                    }
+                });
+            },
+            // 当所有数据被加载时触发
+            onLoadSuccess: function(data) {
+                if (typeof table.options.onLoadSuccess == "function") {
+                    table.options.onLoadSuccess(data);
+                }
+            },
+            // 表格销毁
+            destroy: function (tableId) {
+                var currentId = $.common.isEmpty(tableId) ? table.options.id : tableId;
+                $("#" + currentId).bootstrapTable('destroy');
+                delete table.rememberSelectedIds[currentId];
+                delete table.rememberSelecteds[currentId];
+            },
+            // 序列号生成
+            serialNumber: function (index, tableId) {
+                var currentId = $.common.isEmpty(tableId) ? table.options.id : tableId;
+                var tableParams = $("#" + currentId).bootstrapTable('getOptions');
+                var pageSize = $.common.isNotEmpty(tableParams.pageSize) ? tableParams.pageSize: table.options.pageSize;
+                var pageNumber = $.common.isNotEmpty(tableParams.pageNumber) ? tableParams.pageNumber: table.options.pageNumber;
+                if (table.options.sidePagination == 'client') {
+                    return index + 1;
+                }
+                return pageSize * (pageNumber - 1) + index + 1;
+            },
+            // 列超出指定长度浮动提示 target(copy单击复制文本 open弹窗打开文本)
+            tooltip: function (value, length, target) {
+                var _length = $.common.isEmpty(length) ? 20 : length;
+                var _text = "";
+                var _value = $.common.nullToStr(value);
+                var _target = $.common.isEmpty(target) ? 'copy' : target;
+                if (_value.length > _length) {
+                    _text = _value.substr(0, _length) + "...";
+                    _value = _value.replace(/\'/g,"&apos;");
+                    _value = _value.replace(/\"/g,"&quot;");
+                    var actions = [];
+                    actions.push($.common.sprintf('<input style="opacity: 0;position: absolute;z-index:-1" type="text" value="%s"/>', _value));
+                    actions.push($.common.sprintf('<a href="###" class="tooltip-show" data-toggle="tooltip" data-target="%s" title="%s">%s</a>', _target, _value, _text));
+                    return actions.join('');
+                } else {
+                    _text = _value;
+                    return _text;
+                }
+            },
+            // 下拉按钮切换
+            dropdownToggle: function (value) {
+                var actions = [];
+                actions.push('<div class="btn-group">');
+                actions.push('<button type="button" class="btn btn-xs dropdown-toggle" data-toggle="dropdown" aria-expanded="false">');
+                actions.push('<i class="fa fa-cog"></i>&nbsp;<span class="fa fa-chevron-down"></span></button>');
+                actions.push('<ul class="dropdown-menu">');
+                actions.push(value.replace(/<a/g,"<li><a").replace(/<\/a>/g,"</a></li>"));
+                actions.push('</ul>');
+                actions.push('</div>');
+                return actions.join('');
+            },
+            // 图片预览
+            imageView: function (value, height, width, target) {
+                if ($.common.isEmpty(width)) {
+                    width = 'auto';
+                }
+                if ($.common.isEmpty(height)) {
+                    height = 'auto';
+                }
+                // blank or self
+                var _target = $.common.isEmpty(target) ? 'self' : target;
+                if ($.common.isNotEmpty(value)) {
+                    return $.common.sprintf("<img class='img-circle img-xs' data-height='%s' data-width='%s' data-target='%s' src='%s'/>", height, width, _target, value);
+                } else {
+                    return $.common.nullToStr(value);
+                }
+            },
+            // 搜索-默认第一个form
+            search: function(formId, tableId, pageNumber, pageSize) {
+                table.set(tableId);
+                table.options.formId = $.common.isEmpty(formId) ? $('form').attr('id') : formId;
+                var params = $.common.isEmpty(tableId) ? $("#" + table.options.id).bootstrapTable('getOptions') : $("#" + tableId).bootstrapTable('getOptions');
+                if ($.common.isNotEmpty(pageNumber)) {
+                    params.pageNumber = pageNumber;
+                }
+                if ($.common.isNotEmpty(pageSize)) {
+                    params.pageSize = pageSize;
+                }
+                if ($.common.isNotEmpty(tableId)) {
+                    $("#" + tableId).bootstrapTable('refresh', params);
+                } else{
+                    $("#" + table.options.id).bootstrapTable('refresh', params);
+                }
+            },
+            // 导出数据
+            exportExcel: function(formId) {
+                table.set();
+                $.modal.confirm("确定导出所有" + table.options.modalName + "吗?", function() {
+                    var currentId = $.common.isEmpty(formId) ? $('form').attr('id') : formId;
+                    var params = $("#" + table.options.id).bootstrapTable('getOptions');
+                    var dataParam = $("#" + currentId).serializeArray();
+                    dataParam.push({ "name": "orderByColumn", "value": params.sortName });
+                    dataParam.push({ "name": "isAsc", "value": params.sortOrder });
+                    $.modal.loading("正在导出数据,请稍候...");
+                    $.post(table.options.exportUrl, dataParam, function(result) {
+                        if (result.code == web_status.SUCCESS) {
+                            window.location.href = ctx + "common/download?fileName=" + encodeURI(result.msg) + "&delete=" + true;
+                        } else if (result.code == web_status.WARNING) {
+                            $.modal.alertWarning(result.msg)
+                        } else {
+                            $.modal.alertError(result.msg);
+                        }
+                        $.modal.closeLoading();
+                    });
+                });
+            },
+            // 下载模板
+            importTemplate: function() {
+                $.get(activeWindow().table.options.importTemplateUrl, function(result) {
+                    if (result.code == web_status.SUCCESS) {
+                        window.location.href = ctx + "common/download?fileName=" + encodeURI(result.msg) + "&delete=" + true;
+                    } else if (result.code == web_status.WARNING) {
+                        $.modal.alertWarning(result.msg)
+                    } else {
+                        $.modal.alertError(result.msg);
+                    }
+                });
+            },
+            // 导入数据
+            importExcel: function(formId, width, height) {
+                table.set();
+                var currentId = $.common.isEmpty(formId) ? 'importTpl' : formId;
+                var _width = $.common.isEmpty(width) ? "400" : width;
+                var _height = $.common.isEmpty(height) ? "230" : height;
+                top.layer.open({
+                    type: 1,
+                    area: [_width + 'px', _height + 'px'],
+                    fix: false,
+                    //不固定
+                    maxmin: true,
+                    shade: 0.3,
+                    title: '导入' + table.options.modalName + '数据',
+                    content: $('#' + currentId).html(),
+                    btn: ['<i class="fa fa-check"></i> 导入', '<i class="fa fa-remove"></i> 取消'],
+                    // 弹层外区域关闭
+                    shadeClose: true,
+                    btn1: function(index, layero){
+                        var file = layero.find('#file').val();
+                        if (file == '' || (!$.common.endWith(file, '.xls') && !$.common.endWith(file, '.xlsx'))) {
+                            $.modal.msgWarning("请选择后缀为 “xls”或“xlsx”的文件。");
+                            return false;
+                        }
+                        var index = top.layer.load(2, {shade: false});
+                        $.modal.disable();
+                        var formData = new FormData(layero.find('form')[0]);
+                        $.ajax({
+                            url: table.options.importUrl,
+                            data: formData,
+                            cache: false,
+                            contentType: false,
+                            processData: false,
+                            type: 'POST',
+                            success: function (result) {
+                                if (result.code == web_status.SUCCESS) {
+                                	$.modal.close(index);
+                                    $.modal.closeAll();
+                                    $.modal.alertSuccess(result.msg);
+                                    $.table.refresh();
+                                } else if (result.code == web_status.WARNING) {
+                                	$.modal.close(index);
+                                    $.modal.enable();
+                                    $.modal.alertWarning(result.msg)
+                                } else {
+                                    $.modal.close(index);
+                                    $.modal.enable();
+                                    $.modal.alertError(result.msg);
+                                }
+                            },
+                            complete: function () {
+                            	layero.find('#file').val('');
+                            }
+                        });
+                    }
+                });
+            },
+            // 刷新表格
+            refresh: function(tableId, pageNumber, pageSize, url) {
+                var currentId = $.common.isEmpty(tableId) ? table.options.id : tableId;
+                var params = $("#" + currentId).bootstrapTable('getOptions');
+                if ($.common.isEmpty(pageNumber)) {
+                    pageNumber = params.pageNumber;
+                }
+                if ($.common.isEmpty(pageSize)) {
+                    pageSize = params.pageSize;
+                }
+                if ($.common.isEmpty(url)) {
+                    url = $.common.isEmpty(url) ? params.url : url;
+                }
+                $("#" + currentId).bootstrapTable('refresh', {
+                    silent: true,
+                    url: url,
+                    pageNumber: pageNumber,
+                    pageSize: pageSize
+                });
+            },
+            // 刷新options配置
+            refreshOptions: function(options, tableId) {
+                var currentId = $.common.isEmpty(tableId) ? table.options.id : tableId;
+                $("#" + currentId).bootstrapTable('refreshOptions', options);
+            },
+            // 查询表格指定列值 deDuplication( true去重、false不去重)
+            selectColumns: function(column, deDuplication) {
+                var distinct = $.common.isEmpty(deDuplication) ? true : deDuplication;
+                var rows = $.map($("#" + table.options.id).bootstrapTable('getSelections'), function (row) {
+                    return $.common.getItemField(row, column);
+                });
+                if ($.common.isNotEmpty(table.options.rememberSelected) && table.options.rememberSelected) {
+                    var selectedRows = table.rememberSelecteds[table.options.id];
+                    if ($.common.isNotEmpty(selectedRows)) {
+                        rows = $.map(table.rememberSelecteds[table.options.id], function (row) {
+                            return $.common.getItemField(row, column);
+                        });
+                    }
+                }
+                return distinct ? $.common.uniqueFn(rows) : rows;
+            },
+            // 获取当前页选中或者取消的行ID
+            affectedRowIds: function(rows) {
+                var column = $.common.isEmpty(table.options.uniqueId) ? table.options.columns[1].field : table.options.uniqueId;
+                var rowIds;
+                if ($.isArray(rows)) {
+                    rowIds = $.map(rows, function(row) {
+                        return $.common.getItemField(row, column);
+                    });
+                } else {
+                    rowIds = [rows[column]];
+                }
+                return rowIds;
+            },
+            // 查询表格首列值deDuplication( true去重、false不去重)
+            selectFirstColumns: function(deDuplication) {
+                var distinct = $.common.isEmpty(deDuplication) ? true : deDuplication;
+                var rows = $.map($("#" + table.options.id).bootstrapTable('getSelections'), function (row) {
+                    return $.common.getItemField(row, table.options.columns[1].field);
+                });
+                if ($.common.isNotEmpty(table.options.rememberSelected) && table.options.rememberSelected) {
+                    var selectedRows = table.rememberSelecteds[table.options.id];
+                    if ($.common.isNotEmpty(selectedRows)) {
+                        rows = $.map(selectedRows, function (row) {
+                            return $.common.getItemField(row, table.options.columns[1].field);
+                        });
+                    }
+                }
+                return distinct ? $.common.uniqueFn(rows) : rows;
+            },
+            // 回显数据字典
+            selectDictLabel: function(datas, value) {
+                if ($.common.isEmpty(datas) || $.common.isEmpty(value)) {
+                    return '';
+                }
+                var actions = [];
+                $.each(datas, function(index, dict) {
+                    if (dict.dictValue == ('' + value)) {
+                        var listClass = $.common.equals("default", dict.listClass) || $.common.isEmpty(dict.listClass) ? "" : "badge badge-" + dict.listClass;
+                        var cssClass = $.common.isNotEmpty(dict.cssClass) ? dict.cssClass : listClass;
+                        actions.push($.common.sprintf("<span class='%s'>%s</span>", cssClass, dict.dictLabel));
+                        return false;
+                    }
+                });
+                if (actions.length === 0) {
+                    actions.push($.common.sprintf("<span>%s</span>", value))
+                }
+                return actions.join('');
+            },
+            // 回显数据字典(字符串数组)
+            selectDictLabels: function(datas, value, separator) {
+                if ($.common.isEmpty(datas) || $.common.isEmpty(value)) {
+                    return '';
+                }
+                var currentSeparator = $.common.isEmpty(separator) ? "," : separator;
+                var actions = [];
+                $.each(value.split(currentSeparator), function(i, val) {
+                    var match = false
+                    $.each(datas, function(index, dict) {
+                        if (dict.dictValue == ('' + val)) {
+                            var listClass = $.common.equals("default", dict.listClass) || $.common.isEmpty(dict.listClass) ? "" : "badge badge-" + dict.listClass;
+                            actions.push($.common.sprintf("<span class='%s'>%s</span>", listClass, dict.dictLabel));
+                            match = true
+                            return false;
+                        }
+                    });
+                    if (!match) {
+                        actions.push($.common.sprintf("<span> %s </span>", val));
+                    }
+                });
+                return actions.join('');
+            },
+            // 显示表格指定列
+            showColumn: function(column, tableId) {
+                var currentId = $.common.isEmpty(tableId) ? table.options.id : tableId;
+                $("#" + currentId).bootstrapTable('showColumn', column);
+            },
+            // 隐藏表格指定列
+            hideColumn: function(column, tableId) {
+                var currentId = $.common.isEmpty(tableId) ? table.options.id : tableId;
+                $("#" + currentId).bootstrapTable('hideColumn', column);
+            },
+            // 显示所有表格列
+            showAllColumns: function(tableId) {
+                var currentId = $.common.isEmpty(tableId) ? table.options.id : tableId;
+                $("#" + currentId).bootstrapTable('showAllColumns');
+            },
+            // 隐藏所有表格列
+            hideAllColumns: function(tableId) {
+                var currentId = $.common.isEmpty(tableId) ? table.options.id : tableId;
+                $("#" + currentId).bootstrapTable('hideAllColumns');
+            }
+        },
+        // 表格树封装处理
+        treeTable: {
+            // 初始化表格
+            init: function(options) {
+                var defaults = {
+                    id: "bootstrap-tree-table",
+                    type: 1, // 0 代表bootstrapTable 1代表bootstrapTreeTable
+                    height: 0,
+                    rootIdValue: 0,
+                    ajaxParams: {},
+                    toolbar: "toolbar",
+                    striped: false,
+                    pagination: false,
+                    pageSize: 10,
+                    pageList: [10, 25, 50],
+                    expandColumn: 1,
+                    showSearch: true,
+                    showRefresh: true,
+                    showColumns: true,
+                    expandAll: true,
+                    expandFirst: true
+                };
+                var options = $.extend(defaults, options);
+                table.options = options;
+                table.config[options.id] = options;
+                $.table.initEvent();
+                $.bttTable = $('#' + options.id).bootstrapTreeTable({
+                    code: options.code,                                 // 用于设置父子关系
+                    parentCode: options.parentCode,                     // 用于设置父子关系
+                    type: 'post',                                       // 请求方式(*)
+                    url: options.url,                                   // 请求后台的URL(*)
+                    data: options.data,                                 // 无url时用于渲染的数据
+                    ajaxParams: options.ajaxParams,                     // 请求数据的ajax的data属性
+                    rootIdValue: options.rootIdValue,                   // 设置指定根节点id值
+                    height: options.height,                             // 表格树的高度
+                    pagination: options.pagination,                     // 是否显示分页
+                    dataUrl: options.dataUrl,                           // 加载子节点异步请求数据url
+                    pageSize: options.pageSize,                         // 每页的记录行数
+                    pageList: options.pageList,                         // 可供选择的每页的行数
+                    expandColumn: options.expandColumn,                 // 在哪一列上面显示展开按钮
+                    striped: options.striped,                           // 是否显示行间隔色
+                    bordered: options.bordered,                         // 是否显示边框
+                    toolbar: '#' + options.toolbar,                     // 指定工作栏
+                    showSearch: options.showSearch,                     // 是否显示检索信息
+                    showRefresh: options.showRefresh,                   // 是否显示刷新按钮
+                    showColumns: options.showColumns,                   // 是否显示隐藏某列下拉框
+                    expandAll: options.expandAll,                       // 是否全部展开
+                    expandFirst: options.expandFirst,                   // 是否默认第一级展开--expandAll为false时生效
+                    columns: options.columns,                           // 显示列信息(*)
+                    onClickRow: options.onClickRow,                     // 单击某行事件
+                    responseHandler: $.treeTable.responseHandler,       // 在加载服务器发送来的数据之前处理函数
+                    onLoadSuccess: $.treeTable.onLoadSuccess            // 当所有数据被加载时触发处理函数
+                });
+            },
+            // 条件查询
+            search: function(formId) {
+                var currentId = $.common.isEmpty(formId) ? $('form').attr('id') : formId;
+                var params = $.common.formToJSON(currentId);
+                $.bttTable.bootstrapTreeTable('refresh', $.extend(params, table.options.ajaxParams));
+            },
+            // 刷新
+            refresh: function() {
+                $.bttTable.bootstrapTreeTable('refresh');
+            },
+            // 查询表格树指定列值deDuplication( true去重、false不去重)
+            selectColumns: function(column, deDuplication) {
+                var distinct = $.common.isEmpty(deDuplication) ? true : deDuplication;
+                var rows = $.map($.bttTable.bootstrapTreeTable('getSelections'), function (row) {
+                    return $.common.getItemField(row, column);
+                });
+                return distinct ? $.common.uniqueFn(rows) : rows;
+            },
+            // 请求获取数据后处理回调函数,校验异常状态提醒
+            responseHandler: function(res) {
+                if (typeof table.options.responseHandler == "function") {
+                    table.options.responseHandler(res);
+                }
+                if (res.code != undefined && res.code != web_status.SUCCESS) {
+                    $.modal.alertWarning(res.msg);
+                    return [];
+                } else {
+                    return res;
+                }
+            },
+            // 当所有数据被加载时触发
+            onLoadSuccess: function(data) {
+                if (typeof table.options.onLoadSuccess == "function") {
+                    table.options.onLoadSuccess(data);
+                }
+                $(".table [data-toggle='tooltip']").tooltip();
+            },
+        },
+        // 表单封装处理
+        form: {
+            // 表单重置
+            reset: function(formId, tableId, pageNumber, pageSize) {
+                table.set(tableId);
+                formId = $.common.isEmpty(formId) ? $('form').attr('id') : formId;
+                $("#" + formId)[0].reset();
+                var tableId = $.common.isEmpty(tableId) ? table.options.id : tableId;
+                if (table.options.type == table_type.bootstrapTable) {
+                    var params = $("#" + tableId).bootstrapTable('getOptions');
+                    params.pageNumber = 1;
+                    if ($.common.isNotEmpty(pageSize)) {
+                        params.pageSize = pageSize;
+                    }
+                    $("#" + tableId).bootstrapTable('refresh', params);
+                } else if (table.options.type == table_type.bootstrapTreeTable) {
+                    $("#" + tableId).bootstrapTreeTable('refresh', table.options.ajaxParams);
+                }
+                resetDate();
+            },
+            // 获取选中复选框项
+            selectCheckeds: function(name) {
+                var checkeds = "";
+                $('input:checkbox[name="' + name + '"]:checked').each(function(i) {
+                    if (0 == i) {
+                        checkeds = $(this).val();
+                    } else {
+                        checkeds += ("," + $(this).val());
+                    }
+                });
+                return checkeds;
+            },
+            // 获取选中下拉框项
+            selectSelects: function(name) {
+                var selects = "";
+                $('#' + name + ' option:selected').each(function (i) {
+                    if (0 == i) {
+                        selects = $(this).val();
+                    } else {
+                        selects += ("," + $(this).val());
+                    }
+                });
+                return selects;
+            }
+        },
+        // 弹出层封装处理
+        modal: {
+            // 显示图标
+            icon: function(type) {
+                var icon = "";
+                if (type == modal_status.WARNING) {
+                    icon = 0;
+                } else if (type == modal_status.SUCCESS) {
+                    icon = 1;
+                } else if (type == modal_status.FAIL) {
+                    icon = 2;
+                } else {
+                    icon = 3;
+                }
+                return icon;
+            },
+            // 消息提示
+            msg: function(content, type) {
+                if (type != undefined) {
+                	top.layer.msg(content, { icon: $.modal.icon(type), time: 1000, shift: 5 });
+                } else {
+                	top.layer.msg(content);
+                }
+            },
+            // 错误消息
+            msgError: function(content) {
+                $.modal.msg(content, modal_status.FAIL);
+            },
+            // 成功消息
+            msgSuccess: function(content) {
+                $.modal.msg(content, modal_status.SUCCESS);
+            },
+            // 警告消息
+            msgWarning: function(content) {
+                $.modal.msg(content, modal_status.WARNING);
+            },
+            // 弹出提示
+            alert: function(content, type) {
+                top.layer.alert(content, {
+                    icon: $.modal.icon(type),
+                    title: "系统提示",
+                    btn: ['确认'],
+                    btnclass: ['btn btn-primary'],
+                });
+            },
+            // 错误提示
+            alertError: function(content) {
+                $.modal.alert(content, modal_status.FAIL);
+            },
+            // 成功提示
+            alertSuccess: function(content) {
+                $.modal.alert(content, modal_status.SUCCESS);
+            },
+            // 警告提示
+            alertWarning: function(content) {
+                $.modal.alert(content, modal_status.WARNING);
+            },
+            // 消息提示,重新加载页面
+            msgReload: function(msg, type) {
+                top.layer.msg(msg, {
+                    icon: $.modal.icon(type),
+                    time: 500,
+                    shade: [0.1, '#8F8F8F']
+                },
+                function() {
+                    $.modal.reload();
+                });
+            },
+            // 消息提示成功并刷新父窗体
+            msgSuccessReload: function(msg) {
+            	$.modal.msgReload(msg, modal_status.SUCCESS);
+            },
+            // 获取iframe页的DOM
+            getChildFrame: function (index) {
+                if ($.common.isEmpty(index)) {
+                    var index = parent.layer.getFrameIndex(window.name);
+                    return parent.layer.getChildFrame('body', index);
+                } else {
+                    return top.layer.getChildFrame('body', index);
+                }
+            },
+            // 关闭窗体
+            close: function (index) {
+                if ($.common.isEmpty(index)) {
+                    var index = parent.layer.getFrameIndex(window.name);
+                    parent.layer.close(index);
+                } else {
+                    top.layer.close(index);
+                }
+            },
+            // 关闭全部窗体
+            closeAll: function () {
+                top.layer.closeAll();
+            },
+            // 确认窗体
+            confirm: function (content, callBack) {
+                top.layer.confirm(content, {
+                    icon: 3,
+                    title: "系统提示",
+                    btn: ['确认', '取消']
+                }, function (index) {
+                    $.modal.close(index);
+                    callBack(true);
+                });
+            },
+            // 弹出层指定宽度
+            open: function (title, url, width, height, callback) {
+                // 如果是移动端,就使用自适应大小弹窗
+                if ($.common.isMobile()) {
+                    width = 'auto';
+                    height = 'auto';
+                }
+                if ($.common.isEmpty(title)) {
+                    title = false;
+                }
+                if ($.common.isEmpty(url)) {
+                    url = "/404.html";
+                }
+                if ($.common.isEmpty(width)) {
+                    width = 800;
+                }
+                if ($.common.isEmpty(height)) {
+                    height = ($(window).height() - 50);
+                }
+                if ($.common.isEmpty(callback)) {
+                    callback = function(index, layero) {
+                        var iframeWin = layero.find('iframe')[0];
+                        iframeWin.contentWindow.submitHandler(index, layero);
+                    }
+                }
+                top.layer.open({
+                    type: 2,
+                    area: [width + 'px', height + 'px'],
+                    fix: false,
+                    //不固定
+                    maxmin: true,
+                    shade: 0.3,
+                    title: title,
+                    content: url,
+                    btn: ['确定', '关闭'],
+                    // 弹层外区域关闭
+                    shadeClose: true,
+                    yes: callback,
+                    cancel: function(index) {
+                        return true;
+                    },
+                    success: function () {
+                        $(':focus').blur();
+                    }
+                });
+            },
+            // 弹出层指定参数选项
+            openOptions: function (options) {
+                var _url = $.common.isEmpty(options.url) ? "/404.html" : options.url; 
+                var _title = $.common.isEmpty(options.title) ? "系统窗口" : options.title; 
+                var _width = $.common.isEmpty(options.width) ? "800" : options.width; 
+                var _height = $.common.isEmpty(options.height) ? ($(window).height() - 50) : options.height;
+                var _btn = ['<i class="fa fa-check"></i> 确认', '<i class="fa fa-close"></i> 关闭'];
+                // 如果是移动端,就使用自适应大小弹窗
+                if ($.common.isMobile()) {
+                    _width = 'auto';
+                    _height = 'auto';
+                }
+                if ($.common.isEmpty(options.yes)) {
+                    options.yes = function(index, layero) {
+                        options.callBack(index, layero);
+                    }
+                }
+                var btnCallback = {};
+                if (options.btn instanceof Array){
+                    for (var i = 1, len = options.btn.length; i < len; i++) {
+                        var btn = options["btn" + (i + 1)];
+                        if (btn) {
+                            btnCallback["btn" + (i + 1)] = btn;
+                        }
+                    }
+                }
+                var index = top.layer.open($.extend({
+                    id: options.id,       // 唯一id
+                    anim: options.anim,   // 弹出动画 0-6
+                    type: 2,
+                    maxmin: $.common.isEmpty(options.maxmin) ? true : options.maxmin,
+                    shade: 0.3,
+                    title: _title,
+                    fix: false,
+                    area: [_width + 'px', _height + 'px'],
+                    content: _url,
+                    closeBtn: $.common.isEmpty(options.closeBtn) ? 1 : options.closeBtn,
+                    shadeClose: $.common.isEmpty(options.shadeClose) ? true : options.shadeClose,
+                    skin: options.skin,
+                    // options.btn设置为0表示不显示按钮
+                    btn: $.common.isEmpty(options.btn) ? _btn : options.btn,
+                    yes: options.yes,
+                    cancel: function () {
+                        return true;
+                    },
+                    success: function () {
+                        $(':focus').blur();
+                    }
+                }, btnCallback));
+                if ($.common.isNotEmpty(options.full) && options.full === true) {
+                    top.layer.full(index);
+                }
+            },
+            // 弹出层全屏
+            openFull: function (title, url, width, height) {
+                // 如果是移动端,就使用自适应大小弹窗
+                if ($.common.isMobile()) {
+                    width = 'auto';
+                    height = 'auto';
+                }
+                if ($.common.isEmpty(title)) {
+                    title = false;
+                }
+                if ($.common.isEmpty(url)) {
+                    url = "/404.html";
+                }
+                if ($.common.isEmpty(width)) {
+                    width = 800;
+                }
+                if ($.common.isEmpty(height)) {
+                    height = ($(window).height() - 50);
+                }
+                var index = top.layer.open({
+                    type: 2,
+                    area: [width + 'px', height + 'px'],
+                    fix: false,
+                    //不固定
+                    maxmin: true,
+                    shade: 0.3,
+                    title: title,
+                    content: url,
+                    btn: ['确定', '关闭'],
+                    // 弹层外区域关闭
+                    shadeClose: true,
+                    yes: function(index, layero) {
+                        var iframeWin = layero.find('iframe')[0];
+                        iframeWin.contentWindow.submitHandler(index, layero);
+                    },
+                    cancel: function(index) {
+                        return true;
+                    },
+                    success: function () {
+                        $(':focus').blur();
+                    }
+                });
+                top.layer.full(index);
+            },
+            // 选卡页方式打开
+            openTab: function (title, url, isRefresh) {
+                createMenuItem(url, title, isRefresh);
+            },
+            // 选卡页同一页签打开
+            parentTab: function (title, url) {
+                var dataId = window.frameElement.getAttribute('data-id');
+                createMenuItem(url, title);
+                closeItem(dataId);
+            },
+            // 右侧弹出窗口打开
+            popupRight: function(title, url){
+                var width = 150;
+                if (top.location !== self.location) {
+                    if ($(top.window).outerWidth() < 400) {
+                        width = 50;
+                    }
+                }
+                top.layer.open({
+                    type: 2,
+                    offset: 'r',
+                    anim: 'slideLeft',
+                    move: false,
+                    title: title,
+                    shade: 0.3,
+                    shadeClose: true,
+                    area: [($(window).outerWidth() - width) + 'px', '100%'],
+                    content: url
+                });
+            },
+            // 关闭选项卡
+            closeTab: function (dataId) {
+                closeItem(dataId);
+            },
+            // 禁用按钮
+            disable: function() {
+                var doc = window.top == window.parent ? top.window.document : window.parent.document;
+                $("a[class*=layui-layer-btn]", doc).addClass("layer-disabled");
+            },
+            // 启用按钮
+            enable: function() {
+                var doc = window.top == window.parent ? top.window.document : window.parent.document;
+                $("a[class*=layui-layer-btn]", doc).removeClass("layer-disabled");
+            },
+            // 打开遮罩层
+            loading: function (message) {
+                $.blockUI({ message: '<div class="loaderbox"><div class="loading-activity"></div> ' + message + '</div>' });
+            },
+            // 关闭遮罩层
+            closeLoading: function () {
+                setTimeout(function(){
+                    $.unblockUI();
+                }, 50);
+            },
+            // 重新加载
+            reload: function () {
+                parent.location.reload();
+            }
+        },
+        // 操作封装处理
+        operate: {
+            // 提交数据
+            submit: function(url, type, dataType, data, callback) {
+                var config = {
+                    url: url,
+                    type: type,
+                    dataType: dataType,
+                    data: data,
+                    beforeSend: function () {
+                        $.modal.loading("正在处理中,请稍候...");
+                    },
+                    success: function(result) {
+                        if (typeof callback == "function") {
+                            callback(result);
+                        }
+                        $.operate.ajaxSuccess(result);
+                    }
+                };
+                $.ajax(config)
+            },
+            // post请求传输
+            post: function(url, data, callback) {
+                $.operate.submit(url, "post", "json", data, callback);
+            },
+            // get请求传输
+            get: function(url, callback) {
+                $.operate.submit(url, "get", "json", "", callback);
+            },
+            // 详细信息
+            detail: function(id, width, height) {
+                table.set();
+                var _url = $.operate.detailUrl(id);
+                var options = {
+                    title: table.options.modalName + "详细",
+                    width: width,
+                    height: height,
+                    url: _url,
+                    btn: 0,
+                    yes: function (index, layero) {
+                        $.modal.close(index);
+                    }
+                };
+                $.modal.openOptions(options);
+            },
+            // 详细信息,以tab页展现
+            detailTab: function(id) {
+                table.set();
+                $.modal.openTab("详细" + table.options.modalName, $.operate.detailUrl(id));
+            },
+            // 详细访问地址
+            detailUrl: function(id) {
+                var url = "/404.html";
+                if ($.common.isNotEmpty(id)) {
+                    url = table.options.detailUrl.replace("{id}", id);
+                } else {
+                    var id = $.common.isEmpty(table.options.uniqueId) ? $.table.selectFirstColumns() : $.table.selectColumns(table.options.uniqueId);
+                    if (id.length == 0) {
+                        $.modal.alertWarning("请至少选择一条记录");
+                        return;
+                    }
+                    url = table.options.detailUrl.replace("{id}", id);
+                }
+                return url;
+            },
+            // 删除信息
+            remove: function(id) {
+                table.set();
+                $.modal.confirm("确定删除该条" + table.options.modalName + "信息吗?", function() {
+                    var url = $.common.isEmpty(id) ? table.options.removeUrl : table.options.removeUrl.replace("{id}", id);
+                    if (table.options.type == table_type.bootstrapTreeTable) {
+                        $.operate.get(url);
+                    } else {
+                        var data = { "ids": id };
+                        $.operate.submit(url, "post", "json", data);
+                    }
+                });
+            },
+            // 批量删除信息
+            removeAll: function() {
+                table.set();
+                var rows = $.common.isEmpty(table.options.uniqueId) ? $.table.selectFirstColumns() : $.table.selectColumns(table.options.uniqueId);
+                if (rows.length == 0) {
+                    $.modal.alertWarning("请至少选择一条记录");
+                    return;
+                }
+                $.modal.confirm("确认要删除选中的" + rows.length + "条数据吗?", function() {
+                    var url = table.options.removeUrl;
+                    var data = { "ids": rows.join() };
+                    $.operate.submit(url, "post", "json", data);
+                });
+            },
+            // 清空信息
+            clean: function() {
+                table.set();
+                $.modal.confirm("确定清空所有" + table.options.modalName + "吗?", function() {
+                    var url = table.options.cleanUrl;
+                    $.operate.submit(url, "post", "json", "");
+                });
+            },
+            // 添加信息
+            add: function(id) {
+                table.set();
+                $.modal.open("添加" + table.options.modalName, $.operate.addUrl(id));
+            },
+            // 添加信息,以tab页展现
+            addTab: function (id) {
+                table.set();
+                $.modal.openTab("添加" + table.options.modalName, $.operate.addUrl(id));
+            },
+            // 添加信息 全屏
+            addFull: function(id) {
+                table.set();
+                $.modal.openFull("添加" + table.options.modalName, $.operate.addUrl(id));
+            },
+            // 添加访问地址
+            addUrl: function(id) {
+                var url = $.common.isEmpty(id) ? table.options.createUrl.replace("{id}", "") : table.options.createUrl.replace("{id}", id);
+                return url;
+            },
+            // 修改信息
+            edit: function(id) {
+                table.set();
+                if ($.common.isEmpty(id) && table.options.type == table_type.bootstrapTreeTable) {
+                    var row = $("#" + table.options.id).bootstrapTreeTable('getSelections')[0];
+                    if ($.common.isEmpty(row)) {
+                        $.modal.alertWarning("请至少选择一条记录");
+                        return;
+                    }
+                    var url = table.options.updateUrl.replace("{id}", row[table.options.uniqueId]);
+                    $.modal.open("修改" + table.options.modalName, url);
+                } else {
+                    $.modal.open("修改" + table.options.modalName, $.operate.editUrl(id));
+                }
+            },
+            // 修改信息,以tab页展现
+            editTab: function(id) {
+                table.set();
+                $.modal.openTab("修改" + table.options.modalName, $.operate.editUrl(id));
+            },
+            // 修改信息 全屏
+            editFull: function(id) {
+                table.set();
+                var url = "/404.html";
+                if ($.common.isNotEmpty(id)) {
+                    url = table.options.updateUrl.replace("{id}", id);
+                } else {
+                    if (table.options.type == table_type.bootstrapTreeTable) {
+                        var row = $("#" + table.options.id).bootstrapTreeTable('getSelections')[0];
+                        if ($.common.isEmpty(row)) {
+                            $.modal.alertWarning("请至少选择一条记录");
+                            return;
+                        }
+                        url = table.options.updateUrl.replace("{id}", row[table.options.uniqueId]);
+                    } else {
+                        var row = $.common.isEmpty(table.options.uniqueId) ? $.table.selectFirstColumns() : $.table.selectColumns(table.options.uniqueId);
+                        url = table.options.updateUrl.replace("{id}", row);
+                    }
+                }
+                $.modal.openFull("修改" + table.options.modalName, url);
+            },
+            // 修改访问地址
+            editUrl: function(id) {
+                var url = "/404.html";
+                if ($.common.isNotEmpty(id)) {
+                    url = table.options.updateUrl.replace("{id}", id);
+                } else {
+                    var id = $.common.isEmpty(table.options.uniqueId) ? $.table.selectFirstColumns() : $.table.selectColumns(table.options.uniqueId);
+                    if (id.length == 0) {
+                        $.modal.alertWarning("请至少选择一条记录");
+                        return;
+                    }
+                    url = table.options.updateUrl.replace("{id}", id);
+                }
+                return url;
+            },
+            // 右侧弹出详情
+            view: function(id){
+                table.set();
+                var url = table.options.viewUrl.replace("{id}", id);
+                $.modal.popupRight(table.options.modalName + "信息详情", url);
+            },
+            // 保存信息 刷新表格
+            save: function(url, data, callback) {
+                var config = {
+                    url: url,
+                    type: "post",
+                    dataType: "json",
+                    data: data,
+                    beforeSend: function () {
+                        $.modal.loading("正在处理中,请稍候...");
+                        $.modal.disable();
+                    },
+                    success: function(result) {
+                        if (typeof callback == "function") {
+                            callback(result);
+                        }
+                        $.operate.successCallback(result);
+                    }
+                };
+                $.ajax(config)
+            },
+            // 保存信息 弹出结果提示框
+            saveModal: function(url, data, callback) {
+                var config = {
+                    url: url,
+                    type: "post",
+                    dataType: "json",
+                    data: data,
+                    beforeSend: function () {
+                        $.modal.loading("正在处理中,请稍候...");
+                    },
+                    success: function(result) {
+                        if (typeof callback == "function") {
+                            callback(result);
+                        }
+                        if (result.code == web_status.SUCCESS) {
+                            $.modal.alertSuccess(result.msg)
+                        } else if (result.code == web_status.WARNING) {
+                            $.modal.alertWarning(result.msg)
+                        } else {
+                            $.modal.alertError(result.msg);
+                        }
+                        $.modal.closeLoading();
+                    }
+                };
+                $.ajax(config)
+            },
+            // 保存选项卡信息
+            saveTab: function(url, data, callback) {
+                var config = {
+                    url: url,
+                    type: "post",
+                    dataType: "json",
+                    data: data,
+                    beforeSend: function () {
+                        $.modal.loading("正在处理中,请稍候...");
+                    },
+                    success: function(result) {
+                        if (typeof callback == "function") {
+                            callback(result);
+                        }
+                        $.operate.successTabCallback(result);
+                    }
+                };
+                $.ajax(config)
+            },
+            // 保存结果弹出msg刷新table表格
+            ajaxSuccess: function (result) {
+                if (result.code == web_status.SUCCESS && table.options.type == table_type.bootstrapTable) {
+                    $.modal.msgSuccess(result.msg);
+                    $.table.refresh();
+                } else if (result.code == web_status.SUCCESS && table.options.type == table_type.bootstrapTreeTable) {
+                    $.modal.msgSuccess(result.msg);
+                    $.treeTable.refresh();
+                } else if (result.code == web_status.SUCCESS && $.common.isEmpty(table.options.type)) {
+                    $.modal.msgSuccess(result.msg)
+                }  else if (result.code == web_status.WARNING) {
+                    $.modal.alertWarning(result.msg)
+                }  else {
+                    $.modal.alertError(result.msg);
+                }
+                $.modal.closeLoading();
+            },
+            // 保存结果重新加载页面
+            saveReload: function (result) {
+                if (result.code == web_status.SUCCESS) {
+                    $.modal.msgSuccessReload(result.msg);
+                } else if (result.code == web_status.WARNING) {
+                    $.modal.alertWarning(result.msg)
+                }  else {
+                    $.modal.alertError(result.msg);
+                }
+                $.modal.closeLoading();
+            },
+            // 成功回调执行事件(父窗体静默更新)
+            successCallback: function(result) {
+                if (result.code == web_status.SUCCESS) {
+                    var parent = activeWindow();
+                    if ($.common.isEmpty(parent.table)) {
+                    	$.modal.msgSuccessReload(result.msg);
+                    } else if (parent.table.options.type == table_type.bootstrapTable) {
+                        $.modal.close();
+                        parent.$.modal.msgSuccess(result.msg);
+                        parent.$.table.refresh();
+                    } else if (parent.table.options.type == table_type.bootstrapTreeTable) {
+                        $.modal.close();
+                        parent.$.modal.msgSuccess(result.msg);
+                        parent.$.treeTable.refresh();
+                    }
+                } else if (result.code == web_status.WARNING) {
+                    $.modal.alertWarning(result.msg)
+                }  else {
+                    $.modal.alertError(result.msg);
+                }
+                $.modal.closeLoading();
+                $.modal.enable();
+            },
+            // 选项卡成功回调执行事件(父窗体静默更新)
+            successTabCallback: function(result) {
+                if (result.code == web_status.SUCCESS) {
+                    var topWindow = $(window.parent.document);
+                    var currentId = $('.page-tabs-content', topWindow).find('.active').attr('data-panel');
+                    var topWindow = $('.RuoYi_iframe[data-id="' + currentId + '"]', topWindow)[0];
+                    if ($.common.isNotEmpty(topWindow) && $.common.isNotEmpty(currentId)) {
+                    	var $contentWindow = topWindow.contentWindow;
+                    	$contentWindow.$.modal.msgSuccess(result.msg);
+                        $contentWindow.$(".layui-layer-padding").removeAttr("style");
+                        if ($contentWindow.table.options.type == table_type.bootstrapTable) {
+                            $contentWindow.$.table.refresh();
+                        } else if ($contentWindow.table.options.type == table_type.bootstrapTreeTable) {
+                            $contentWindow.$.treeTable.refresh();
+                        }
+                    } else {
+                        $.modal.msgSuccess(result.msg);
+                    }
+                    $.modal.close();
+                    $.modal.closeTab();
+                } else if (result.code == web_status.WARNING) {
+                    $.modal.alertWarning(result.msg)
+                } else {
+                    $.modal.alertError(result.msg);
+                }
+                $.modal.closeLoading();
+            }
+        },
+        // 校验封装处理
+        validate: {
+            // 表单验证
+            form: function (formId) {
+                var currentId = $.common.isEmpty(formId) ? $('form').attr('id') : formId;
+                return $("#" + currentId).validate().form();
+            },
+            // 重置表单验证(清除提示信息)
+            reset: function (formId) {
+                var currentId = $.common.isEmpty(formId) ? $('form').attr('id') : formId;
+                return $("#" + currentId).validate().resetForm();
+            }
+        },
+        // 树插件封装处理
+        tree: {
+            _option: {},
+            _lastValue: {},
+            // 初始化树结构
+            init: function(options) {
+                var defaults = {
+                    id: "tree",                    // 属性ID
+                    expandLevel: 0,                // 展开等级节点
+                    view: {
+                        selectedMulti: false,      // 设置是否允许同时选中多个节点
+                        nameIsHTML: true           // 设置 name 属性是否支持 HTML 脚本
+                    },
+                    check: {
+                        enable: false,             // 置 zTree 的节点上是否显示 checkbox / radio
+                        nocheckInherit: true,      // 设置子节点是否自动继承
+                        chkboxType: { "Y": "ps", "N": "ps" } // 父子节点的关联关系
+                    },
+                    data: {
+                        key: {
+                            title: "title"         // 节点数据保存节点提示信息的属性名称
+                        },
+                        simpleData: {
+                            enable: true           // true / false 分别表示 使用 / 不使用 简单数据模式
+                        }
+                    },
+                };
+                var options = $.extend(defaults, options);
+                $.tree._option = options;
+                // 树结构初始化加载
+                var setting = {
+                    callback: {
+                        onClick: options.onClick,                      // 用于捕获节点被点击的事件回调函数
+                        onCheck: options.onCheck,                      // 用于捕获 checkbox / radio 被勾选 或 取消勾选的事件回调函数
+                        onDblClick: options.onDblClick                 // 用于捕获鼠标双击之后的事件回调函数
+                    },
+                    check: options.check,
+                    view: options.view,
+                    data: options.data
+                };
+                $.get(options.url, function(data) {
+                    var treeId = $("#treeId").val();
+                    tree = $.fn.zTree.init($("#" + options.id), setting, data);
+                    $._tree = tree;
+                    for (var i = 0; i < options.expandLevel; i++) {
+                        var nodes = tree.getNodesByParam("level", i);
+                        for (var j = 0; j < nodes.length; j++) {
+                            tree.expandNode(nodes[j], true, false, false);
+                        }
+                    }
+                    var node = tree.getNodesByParam("id", treeId, null)[0];
+                    $.tree.selectByIdName(treeId, node);
+                    // 回调tree方法
+                    if (typeof(options.callBack) === "function"){
+                        options.callBack(tree);
+                    }
+                });
+            },
+            // 搜索节点
+            searchNode: function() {
+                // 取得输入的关键字的值
+                var value = $.common.trim($("#keyword").val());
+                if ($.tree._lastValue == value) {
+                    return;
+                }
+                // 保存最后一次搜索名称
+                $.tree._lastValue = value;
+                var nodes = $._tree.getNodes();
+                // 如果要查空字串,就退出不查了。
+                if (value == "") {
+                    $.tree.showAllNode(nodes);
+                    return;
+                }
+                $.tree.hideAllNode(nodes);
+                // 根据搜索值模糊匹配
+                $.tree.updateNodes($._tree.getNodesByParamFuzzy("name", value));
+            },
+            // 根据Id和Name选中指定节点
+            selectByIdName: function(treeId, node) {
+                if ($.common.isNotEmpty(treeId) && node && treeId == node.id) {
+                    $._tree.selectNode(node, true);
+                }
+            },
+            // 显示所有节点
+            showAllNode: function(nodes) {
+                nodes = $._tree.transformToArray(nodes);
+                for (var i = nodes.length - 1; i >= 0; i--) {
+                    if (nodes[i].getParentNode() != null) {
+                        $._tree.expandNode(nodes[i], true, false, false, false);
+                    } else {
+                        $._tree.expandNode(nodes[i], true, true, false, false);
+                    }
+                    $._tree.showNode(nodes[i]);
+                    $.tree.showAllNode(nodes[i].children);
+                }
+            },
+            // 隐藏所有节点
+            hideAllNode: function(nodes) {
+                var nodes = $._tree.transformToArray(nodes);
+                for (var i = nodes.length - 1; i >= 0; i--) {
+                    $._tree.hideNode(nodes[i]);
+                }
+            },
+            // 显示所有父节点
+            showParent: function(treeNode) {
+                var parentNode;
+                while ((parentNode = treeNode.getParentNode()) != null) {
+                    $._tree.showNode(parentNode);
+                    $._tree.expandNode(parentNode, true, false, false);
+                    treeNode = parentNode;
+                }
+            },
+            // 显示所有孩子节点
+            showChildren: function(treeNode) {
+                if (treeNode.isParent) {
+                    for (var idx in treeNode.children) {
+                        var node = treeNode.children[idx];
+                        $._tree.showNode(node);
+                        $.tree.showChildren(node);
+                    }
+                }
+            },
+            // 更新节点状态
+            updateNodes: function(nodeList) {
+                $._tree.showNodes(nodeList);
+                for (var i = 0, l = nodeList.length; i < l; i++) {
+                    var treeNode = nodeList[i];
+                    $.tree.showChildren(treeNode);
+                    $.tree.showParent(treeNode)
+                }
+            },
+            // 获取当前被勾选集合
+            getCheckedNodes: function(column) {
+                var _column = $.common.isEmpty(column) ? "id" : column;
+                var nodes = $._tree.getCheckedNodes(true);
+                return $.map(nodes, function (row) {
+                    return row[_column];
+                }).join();
+            },
+            // 不允许根父节点选择
+            notAllowParents: function(_tree) {
+                var nodes = _tree.getSelectedNodes();
+                if (nodes.length == 0){
+                    $.modal.msgError("请选择节点后提交");
+                    return false;
+                }
+                for (var i = 0; i < nodes.length; i++) {
+                    if (nodes[i].level == 0) {
+                        $.modal.msgError("不能选择根节点(" + nodes[i].name + ")");
+                        return false;
+                    }
+                    if (nodes[i].isParent) {
+                        $.modal.msgError("不能选择父节点(" + nodes[i].name + ")");
+                        return false;
+                    }
+                }
+                return true;
+            },
+            // 不允许最后层级节点选择
+            notAllowLastLevel: function(_tree) {
+                var nodes = _tree.getSelectedNodes();
+                for (var i = 0; i < nodes.length; i++) {
+                    if (!nodes[i].isParent) {
+                        $.modal.msgError("不能选择最后层级节点(" + nodes[i].name + ")");
+                        return false;
+                    }
+                }
+                return true;
+            },
+            // 隐藏/显示搜索栏
+            toggleSearch: function() {
+                $('#search').slideToggle(200);
+                $('#btnShow').toggle();
+                $('#btnHide').toggle();
+                $('#keyword').focus();
+            },
+            // 折叠
+            collapse: function() {
+                $._tree.expandAll(false);
+            },
+            // 展开
+            expand: function() {
+                $._tree.expandAll(true);
+            }
+        },
+        // 通用方法封装处理
+        common: {
+            // 判断字符串是否为空
+            isEmpty: function (value) {
+                if (value == null || this.trim(value) == "" || value == undefined || value == "undefined") {
+                    return true;
+                }
+                return false;
+            },
+            // 判断一个字符串是否为非空串
+            isNotEmpty: function (value) {
+                return !$.common.isEmpty(value);
+            },
+            // 如果值是空,则返回指定默认字符串,否则返回字符串本身
+            nullToDefault: function (value, defaultValue) {
+                return $.common.isEmpty(value) ? defaultValue : value;
+            },
+            // 空对象转字符串
+            nullToStr: function(value) {
+                if ($.common.isEmpty(value)) {
+                    return "-";
+                }
+                return value;
+            },
+            // 是否显示数据 为空默认为显示
+            visible: function (value) {
+                if ($.common.isEmpty(value) || value == true) {
+                    return true;
+                }
+                return false;
+            },
+            // 空格截取
+            trim: function (value) {
+                if (value == null) {
+                    return "";
+                }
+                return value.toString().replace(/(^\s*)|(\s*$)|\r|\n/g, "");
+            },
+            // 比较两个字符串(大小写敏感)
+            equals: function (str, that) {
+                return str == that;
+            },
+            // 比较两个字符串(大小写不敏感)
+            equalsIgnoreCase: function (str, that) {
+                return String(str).toUpperCase() === String(that).toUpperCase();
+            },
+            // 将字符串按指定字符分割
+            split: function (str, sep, maxLen) {
+                if ($.common.isEmpty(str)) {
+                    return null;
+                }
+                var value = String(str).split(sep);
+                return maxLen ? value.slice(0, maxLen - 1) : value;
+            },
+            // 字符串格式化(%s )
+            sprintf: function (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 == null ? '' : arg;
+                });
+                return flag ? str : '';
+            },
+            // 日期格式化 时间戳  -> yyyy-MM-dd HH-mm-ss
+            dateFormat: function(date, format) {
+                var that = this;
+                if (that.isEmpty(date)) return "";
+                if (!date) return;
+                if (!format) format = "yyyy-MM-dd";
+                switch (typeof date) {
+                case "string":
+                    date = new Date(date.replace(/-/g, "/"));
+                    break;
+                case "number":
+                    date = new Date(date);
+                    break;
+                }
+                if (!date instanceof Date) return;
+                var dict = {
+                    "yyyy": date.getFullYear(),
+                    "M": date.getMonth() + 1,
+                    "d": date.getDate(),
+                    "H": date.getHours(),
+                    "m": date.getMinutes(),
+                    "s": date.getSeconds(),
+                    "MM": ("" + (date.getMonth() + 101)).substr(1),
+                    "dd": ("" + (date.getDate() + 100)).substr(1),
+                    "HH": ("" + (date.getHours() + 100)).substr(1),
+                    "mm": ("" + (date.getMinutes() + 100)).substr(1),
+                    "ss": ("" + (date.getSeconds() + 100)).substr(1)
+                };
+                return format.replace(/(yyyy|MM?|dd?|HH?|ss?|mm?)/g,
+                function() {
+                    return dict[arguments[0]];
+                });
+            },
+            // 获取节点数据,支持多层级访问
+            getItemField: function (item, field) {
+                var value = item;
+                if (typeof field !== 'string' || item.hasOwnProperty(field)) {
+                    return item[field];
+                }
+                var props = field.split('.');
+                for (var p in props) {
+                    value = value && value[props[p]];
+                }
+                return value;
+            },
+            // 指定随机数返回
+            random: function (min, max) {
+                return Math.floor((Math.random() * max) + min);
+            },
+            // 判断字符串是否是以start开头
+            startWith: function(value, start) {
+                var reg = new RegExp("^" + start);
+                return reg.test(value)
+            },
+            // 判断字符串是否是以end结尾
+            endWith: function(value, end) {
+                var reg = new RegExp(end + "$");
+                return reg.test(value)
+            },
+            // 数组去重
+            uniqueFn: function(array) {
+                var result = [];
+                var hashObj = {};
+                for (var i = 0; i < array.length; i++) {
+                    if (!hashObj[array[i]]) {
+                        hashObj[array[i]] = true;
+                        result.push(array[i]);
+                    }
+                }
+                return result;
+            },
+            // 数组中的所有元素放入一个字符串
+            join: function(array, separator) {
+                if ($.common.isEmpty(array)) {
+                    return null;
+                }
+                return array.join(separator);
+            },
+            // 获取form下所有的字段并转换为json对象
+            formToJSON: function(formId) {
+                var json = {};
+                $.each($("#" + formId).serializeArray(), function(i, field) {
+                    if (json[field.name]) {
+                        json[field.name] += ("," + field.value);
+                    } else {
+                        json[field.name] = field.value;
+                    }
+                });
+                return json;
+            },
+            // 数据字典转下拉框
+            dictToSelect: function(datas, value, name) {
+                var actions = [];
+                actions.push($.common.sprintf("<select class='form-control' name='%s'>", name));
+                $.each(datas, function(index, dict) {
+                    actions.push($.common.sprintf("<option value='%s'", dict.dictValue));
+                    if (dict.dictValue == ('' + value)) {
+                        actions.push(' selected');
+                    }
+                    actions.push($.common.sprintf(">%s</option>", dict.dictLabel));
+                });
+                actions.push('</select>');
+                return actions.join('');
+            },
+            // 获取obj对象长度
+            getLength: function(obj) {
+                var count = 0;  
+                for (var i in obj) {
+                    if (obj.hasOwnProperty(i)) {
+                        count++;
+                    }  
+                }
+                return count;
+            },
+            // 判断移动端
+            isMobile: function () {
+                return navigator.userAgent.match(/(Android|iPhone|SymbianOS|Windows Phone|iPad|iPod)/i);
+            },
+            // 数字正则表达式,只能为0-9数字
+            numValid : function(text){
+                var patten = new RegExp(/^[0-9]+$/);
+                return patten.test(text);
+            },
+            // 英文正则表达式,只能为a-z和A-Z字母
+            enValid : function(text){
+                var patten = new RegExp(/^[a-zA-Z]+$/);
+                return patten.test(text);
+            },
+            // 英文、数字正则表达式,必须包含(字母,数字)
+            enNumValid : function(text){
+                var patten = new RegExp(/^(?=.*[a-zA-Z]+)(?=.*[0-9]+)[a-zA-Z0-9]+$/);
+                return patten.test(text);
+            },
+            // 英文、数字、特殊字符正则表达式,必须包含(字母,数字,特殊字符!@#$%^&*()-=_+)
+            charValid : function(text){
+                var patten = new RegExp(/^(?=.*[A-Za-z])(?=.*\d)(?=.*[~!@#\$%\^&\*\(\)\-=_\+])[A-Za-z\d~!@#\$%\^&\*\(\)\-=_\+]{6,}$/);
+                return patten.test(text);
+            },
+        }
+    });
+})(jQuery);
+
+/** 表格类型 */
+table_type = {
+    bootstrapTable: 0,
+    bootstrapTreeTable: 1
+};
+
+/** 消息状态码 */
+web_status = {
+    SUCCESS: 0,
+    FAIL: 500,
+    WARNING: 301
+};
+
+/** 弹窗状态码 */
+modal_status = {
+    SUCCESS: "success",
+    FAIL: "error",
+    WARNING: "warning"
+};
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ruoyi/login.js b/ruoyi-admin/src/main/resources/static/ruoyi/login.js
new file mode 100644
index 0000000..1b26531
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ruoyi/login.js
@@ -0,0 +1,98 @@
+
+$(function() {
+    validateKickout();
+    validateRule();
+    $('.imgcode').click(function() {
+        var url = ctx + "captcha/captchaImage?type=" + captchaType + "&s=" + Math.random();
+        $(".imgcode").attr("src", url);
+    });
+});
+
+function login() {
+    var username = $.common.trim($("input[name='username']").val());
+    var password = $.common.trim($("input[name='password']").val());
+    var validateCode = $("input[name='validateCode']").val();
+    var rememberMe = $("input[name='rememberme']").is(':checked');
+    if($.common.isEmpty(validateCode) && captchaEnabled) {
+        $.modal.msg("请输入验证码");
+        return false;
+    }
+    $.ajax({
+        type: "post",
+        url: ctx + "login",
+        data: {
+            "username": username,
+            "password": password,
+            "validateCode": validateCode,
+            "rememberMe": rememberMe
+        },
+        beforeSend: function () {
+            $.modal.loading($("#btnSubmit").data("loading"));
+        },
+        success: function(r) {
+            if (r.code == web_status.SUCCESS) {
+                location.href = ctx + 'index';
+            } else {
+                $('.imgcode').click();
+                $(".code").val("");
+                $.modal.msg(r.msg);
+            }
+            $.modal.closeLoading();
+        }
+    });
+}
+
+function validateRule() {
+    var icon = "<i class='fa fa-times-circle'></i> ";
+    $("#signupForm").validate({
+        rules: {
+            username: {
+                required: true
+            },
+            password: {
+                required: true
+            }
+        },
+        messages: {
+            username: {
+                required: icon + "请输入您的用户名",
+            },
+            password: {
+                required: icon + "请输入您的密码",
+            }
+        },
+        submitHandler: function(form) {
+            login();
+        }
+    })
+}
+
+function validateKickout() {
+    if (getParam("kickout") == 1) {
+        layer.alert("<font color='red'>您已在别处登录,请您修改密码或重新登录</font>", {
+            icon: 0,
+            title: "系统提示"
+        },
+        function(index) {
+            //关闭弹窗
+            layer.close(index);
+            if (top != self) {
+                top.location = self.location;
+            } else {
+                var url = location.search;
+                if (url) {
+                    var oldUrl = window.location.href;
+                    var newUrl = oldUrl.substring(0, oldUrl.indexOf('?'));
+                    self.location = newUrl;
+                }
+            }
+        });
+    }
+}
+
+function getParam(paramName) {
+    var reg = new RegExp("(^|&)" + paramName + "=([^&]*)(&|$)");
+    var r = window.location.search.substr(1).match(reg);
+    if (r != null) return decodeURI(r[2]);
+    return null;
+}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ruoyi/register.js b/ruoyi-admin/src/main/resources/static/ruoyi/register.js
new file mode 100644
index 0000000..886a55f
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/static/ruoyi/register.js
@@ -0,0 +1,86 @@
+
+$(function() {
+    validateRule();
+    $('.imgcode').click(function() {
+        var url = ctx + "captcha/captchaImage?type=" + captchaType + "&s=" + Math.random();
+        $(".imgcode").attr("src", url);
+    });
+});
+
+function register() {
+    var username = $.common.trim($("input[name='username']").val());
+    var password = $.common.trim($("input[name='password']").val());
+    var validateCode = $("input[name='validateCode']").val();
+    if($.common.isEmpty(validateCode) && captchaEnabled) {
+        $.modal.msg("请输入验证码");
+        return false;
+    }
+    $.ajax({
+        type: "post",
+        url: ctx + "register",
+        data: {
+            "loginName": username,
+            "password": password,
+            "validateCode": validateCode
+        },
+        beforeSend: function () {
+            $.modal.loading($("#btnSubmit").data("loading"));
+        },
+        success: function(r) {
+            if (r.code == web_status.SUCCESS) {
+            	layer.alert("<font color='red'>恭喜你,您的账号 " + username + " 注册成功!</font>", {
+            	    icon: 1,
+            	    title: "系统提示"
+            	},
+            	function(index) {
+            	    //关闭弹窗
+            	    layer.close(index);
+            	    location.href = ctx + 'login';
+            	});
+            } else {
+            	$.modal.closeLoading();
+            	$('.imgcode').click();
+            	$(".code").val("");
+            	$.modal.msg(r.msg);
+            }
+        }
+    });
+}
+
+function validateRule() {
+    var icon = "<i class='fa fa-times-circle'></i> ";
+    $("#registerForm").validate({
+        rules: {
+            username: {
+                required: true,
+                minlength: 2
+            },
+            password: {
+                required: true,
+                minlength: 5,
+                specialSign: true
+            },
+            confirmPassword: {
+                required: true,
+                equalTo: "[name='password']"
+            }
+        },
+        messages: {
+            username: {
+                required: icon + "请输入您的用户名",
+                minlength: icon + "用户名不能小于2个字符"
+            },
+            password: {
+            	required: icon + "请输入您的密码",
+                minlength: icon + "密码不能小于5个字符",
+            },
+            confirmPassword: {
+                required: icon + "请再次输入您的密码",
+                equalTo: icon + "两次密码输入不一致"
+            }
+        },
+        submitHandler: function(form) {
+            register();
+        }
+    })
+}
diff --git a/ruoyi-admin/src/main/resources/templates/demo/form/autocomplete.html b/ruoyi-admin/src/main/resources/templates/demo/form/autocomplete.html
new file mode 100644
index 0000000..42f91c4
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/form/autocomplete.html
@@ -0,0 +1,323 @@
+<!DOCTYPE html>
+<html lang="zh">
+<head>
+	<th:block th:include="include :: header('搜索自动补全')" />
+</head>
+<body class="gray-bg">
+      <div class="wrapper wrapper-content animated fadeInRight">
+        <div class="row">
+            <div class="col-sm-6">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>搜索自动补全<small>https://github.com/lzwme/bootstrap-suggest-plugin</small></h5>
+                    </div>  
+                    <div class="ibox-content">
+                        <p>展示下拉菜单按钮。</p>
+                        <div class="row">
+                            <div class="col-lg-6">
+                                <div class="input-group">
+                                    <input type="text" class="form-control" id="suggest-demo-1">
+                                    <div class="input-group-btn">
+                                        <button type="button" class="btn btn-white dropdown-toggle" style="height: 31px" data-toggle="dropdown">
+                                            <span class="caret"></span>
+                                        </button>
+                                        <ul class="dropdown-menu dropdown-menu-right" role="menu">
+                                        </ul>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                        
+                        <p>不展示下拉菜单按钮。</p>
+                        <div class="row">
+                            <div class="col-lg-6">
+                                <div class="input-group">
+                                    <input type="text" class="form-control" id="suggest-demo-2">
+                                    <div class="input-group-btn">
+                                        <button type="button" class="btn btn-white dropdown-toggle" data-toggle="dropdown">
+                                            <span class="caret"></span>
+                                        </button>
+                                        <ul class="dropdown-menu dropdown-menu-right" role="menu">
+                                        </ul>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                        
+                        <p>前端json中获取数据</p>
+                        <div class="row">
+                            <div class="col-lg-6">
+                                <div class="input-group">
+                                    <input type="text" class="form-control" id="suggest-demo-3">
+                                    <div class="input-group-btn">
+                                        <button type="button" class="btn btn-white dropdown-toggle" style="height: 31px" data-toggle="dropdown">
+                                            <span class="caret"></span>
+                                        </button>
+                                        <ul class="dropdown-menu dropdown-menu-right" role="menu">
+                                        </ul>
+                                    </div>
+                                    <!-- /btn-group -->
+                                </div>
+                            </div>
+                        </div>
+                        
+                        <h3>百度搜索</h3>
+                        <p>支持逗号分隔多关键字</p>
+                        <div class="row">
+                            <div class="col-lg-6">
+                                <div class="input-group" style="width: 300px;">
+                                    <input type="text" class="form-control" id="baidu">
+                                    <div class="input-group-btn">
+                                        <button type="button" class="btn btn-white dropdown-toggle" style="height: 31px" data-toggle="dropdown">
+                                            <span class="caret"></span>
+                                        </button>
+                                        <ul class="dropdown-menu dropdown-menu-right" role="menu">
+                                        </ul>
+                                    </div>
+                                    <!-- /btn-group -->
+                                </div>
+                            </div>
+                        </div>
+                        
+                        <h3>淘宝搜索</h3>
+                        <p>支持逗号分隔多关键字</p>
+                        <div class="row">
+                            <div class="col-lg-6">
+                                <div class="input-group" style="width: 400px;">
+                                    <input type="text" class="form-control" id="taobao">
+                                    <div class="input-group-btn">
+                                        <button type="button" class="btn btn-white dropdown-toggle" style="height: 31px" data-toggle="dropdown">
+                                            <span class="caret"></span>
+                                        </button>
+                                        <ul class="dropdown-menu dropdown-menu-right" role="menu">
+                                        </ul>
+                                    </div>
+                                    <!-- /btn-group -->
+                                </div>
+                            </div>
+                        </div>
+                        <hr>
+                        <div class="form-group">
+                            <label class="font-noraml">相关参数详细信息</label>
+                            <div><a href="http://doc.ruoyi.vip/ruoyi/document/zjwd.html#bootstrap-suggest" target="_blank">http://doc.ruoyi.vip/ruoyi/document/zjwd.html#bootstrap-suggest</a></div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            
+            <div class="col-sm-6">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>搜索自动补全<small>https://github.com/bassjobsen/Bootstrap-3-Typeahead</small></h5>
+                    </div>  
+                    <div class="ibox-content">
+                        <p>通过数据属性的基本示例。</p>
+                        <div class="row">
+                            <div class="col-lg-6">
+                           	    <input type="text" placeholder="ruoyi..." data-provide="typeahead" data-source='["ruoyi 1","ruoyi 2","ruoyi 3"]' class="form-control" />
+                            </div>
+                        </div>
+                        <hr>
+                        
+                        <p>通过javascript的基本示例。</p>
+                        <div class="row">
+                            <div class="col-lg-6">
+                                <input type="text" placeholder="ruoyi..." class="form-control" id="typeahead-demo-1"/>
+                            </div>
+                        </div>
+                        
+                        <hr>
+                        <p>通过javascript的复杂示例。</p>
+                        <div class="row">
+                            <div class="col-lg-6">
+                                <input type="text" placeholder="ruoyi..." class="form-control" id="typeahead-demo-2"/>
+                            </div>
+                        </div>
+                        
+                        <hr>
+                        <p>后台url中获取简单数据</p>
+                        <div class="row">
+                            <div class="col-lg-6">
+                                <input type="text" placeholder="ruoyi..." class="form-control" id="typeahead-demo-3"/>
+                            </div>
+                        </div>
+                        
+                        <hr>
+                        <div class="form-group">
+                            <label class="font-noraml">相关参数详细信息</label>
+                            <div><a href="http://doc.ruoyi.vip/ruoyi/document/zjwd.html#bootstrap-typeahead" target="_blank">http://doc.ruoyi.vip/ruoyi/document/zjwd.html#bootstrap-typeahead</a></div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <th:block th:include="include :: footer" />
+    <th:block th:include="include :: bootstrap-suggest-js" />
+    <th:block th:include="include :: bootstrap-typeahead-js" />
+    <script type="text/javascript">
+        
+	    var testBsSuggest = $("#suggest-demo-1").bsSuggest({
+	        url: ctx + "demo/form/userModel",
+	        idField: "userId",
+	        keyField: "userName"
+	    }).on('onDataRequestSuccess', function (e, result) {
+	        console.log('onDataRequestSuccess: ', result);
+	    }).on('onSetSelectValue', function (e, keyword) {
+	        console.log('onSetSelectValue: ', keyword);
+	    }).on('onUnsetSelectValue', function (e) {
+	        console.log("onUnsetSelectValue");
+	    });
+	    
+	    var testBsSuggest = $("#suggest-demo-2").bsSuggest({
+	        url: ctx + "demo/form/userModel",
+	        showBtn: false,
+	        idField: "userId",
+	        keyField: "userName"
+	    }).on('onDataRequestSuccess', function (e, result) {
+	        console.log('onDataRequestSuccess: ', result);
+	    }).on('onSetSelectValue', function (e, keyword) {
+	        console.log('onSetSelectValue: ', keyword);
+	    }).on('onUnsetSelectValue', function (e) {
+	        console.log("onUnsetSelectValue");
+	    });
+	
+	    //data 数据中获取
+	    var testdataBsSuggest = $("#suggest-demo-3").bsSuggest({
+	        indexId: 1,
+	        indexKey: 2,
+	        data: {
+	            'value': [
+	                {
+	                    'userId': '1',
+	                    'userCode': '1000001',
+	                    'userName': '测试1',
+	                    'userPhone': '15888888888'
+	                },
+	                {
+	                    'userId': '2',
+	                    'userCode': '1000002',
+	                    'userName': '测试2',
+	                    'userPhone': '15888888888'
+	                },
+	                {
+	                    'userId': '3',
+	                    'userCode': '1000003',
+	                    'userName': '测试3',
+	                    'userPhone': '15888888888'
+	                },
+	                {
+	                    'userId': '4',
+	                    'userCode': '1000004',
+	                    'userName': '测试4',
+	                    'userPhone': '15888888888'
+	                },
+	                {
+	                    'userId': '5',
+	                    'userCode': '1000005',
+	                    'userName': '测试5',
+	                    'userPhone': '15888888888'
+	                }
+				],
+	            'defaults': 'http://ruoyi.vip'
+	        }
+	    });
+	    
+	    //百度搜索测试
+	    var baiduBsSuggest = $("#baidu").bsSuggest({
+	        allowNoKeyword: false, //是否允许无关键字时请求数据
+	        multiWord: true, //以分隔符号分割的多关键字支持
+	        separator: ",", //多关键字支持时的分隔符,默认为空格
+	        getDataMethod: "url", //获取数据的方式,总是从 URL 获取
+	        url: 'http://unionsug.baidu.com/su?p=3&t=' + (new Date()).getTime() + '&wd=',
+	        /*优先从url ajax 请求 json 帮助数据,注意最后一个参数为关键字请求参数*/
+	        jsonp: 'cb',
+	        /*如果从 url 获取数据,并且需要跨域,则该参数必须设置*/
+	        processData: function (json) { // url 获取数据时,对数据的处理,作为 getData 的回调函数
+	            var i, len, data = {
+	                value: []
+	            };
+	            if (!json || !json.s || json.s.length === 0) {
+	                return false;
+	            }
+	
+	            console.log(json);
+	            len = json.s.length;
+	
+	            jsonStr = "{'value':[";
+	            for (i = 0; i < len; i++) {
+	                data.value.push({
+	                    word: json.s[i]
+	                });
+	            }
+	            data.defaults = 'baidu';
+	
+	            //字符串转化为 js 对象
+	            return data;
+	        }
+	    });
+	    
+	    //淘宝搜索建议测试
+	    var taobaoBsSuggest = $("#taobao").bsSuggest({
+	        indexId: 2,                 // data.value 的第几个数据,作为input输入框的内容
+	        indexKey: 1,                // data.value 的第几个数据,作为input输入框的内容
+	        allowNoKeyword: false,      // 是否允许无关键字时请求数据
+	        hideOnSelect: true,         // 鼠标从列表单击选择了值时,是否隐藏选择列表
+	        multiWord: true,            // 以分隔符号分割的多关键字支持
+	        separator: ",",             // 多关键字支持时的分隔符,默认为空格
+	        getDataMethod: "url",       // 获取数据的方式,总是从 URL 获取
+	        effectiveFieldsAlias: {
+	            Id: "序号",
+	            Keyword: "关键字",
+	            Count: "数量"
+	        },
+	        showHeader: true,
+	        url: 'http://suggest.taobao.com/sug?code=utf-8&extras=1&q=',
+	        /*优先从url ajax 请求 json 帮助数据,注意最后一个参数为关键字请求参数*/
+	        jsonp: 'callback',
+	        /*如果从 url 获取数据,并且需要跨域,则该参数必须设置*/
+	        processData: function (json) { // url 获取数据时,对数据的处理,作为 getData 的回调函数
+	            var i, len, data = {
+	                value: []
+	            };
+	
+	            if (!json || !json.result || json.result.length == 0) {
+	                return false;
+	            }
+	
+	            console.log(json);
+	            len = json.result.length;
+	
+	            for (i = 0; i < len; i++) {
+	                data.value.push({
+	                    "Id": (i + 1),
+	                    "Keyword": json.result[i][0],
+	                    "Count": json.result[i][1]
+	                });
+	            }
+	            console.log(data);
+	            return data;
+	        }
+	    });
+	    
+	    $('#typeahead-demo-1').typeahead({
+            source: ["ruoyi 1","ruoyi 2","ruoyi 3"]
+        });
+	    
+	    $('#typeahead-demo-2').typeahead({
+            source: [
+                {"name": "Afghanistan", "code": "AF", "ccn0": "040"},
+                {"name": "Land Islands", "code": "AX", "ccn0": "050"},
+                {"name": "Albania", "code": "AL","ccn0": "060"},
+                {"name": "Algeria", "code": "DZ","ccn0": "070"}
+            ]
+        });
+	    
+	    $.get(ctx + "demo/form/collection", function(data){
+	    	$("#typeahead-demo-3").typeahead({
+		        source: data.value
+		    });
+        },'json');
+    </script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/demo/form/basic.html b/ruoyi-admin/src/main/resources/templates/demo/form/basic.html
new file mode 100644
index 0000000..7f19621
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/form/basic.html
@@ -0,0 +1,593 @@
+<!DOCTYPE html>
+<html lang="zh">
+<head>
+	<th:block th:include="include :: header('基本表单')" />
+</head>
+<body class="gray-bg">
+    <div class="wrapper wrapper-content animated fadeInRight">
+        <div class="row">
+            <div class="col-sm-7">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>基本表单 <small>简单登录表单示例</small></h5>
+                        <div class="ibox-tools">
+                            <a class="collapse-link">
+                                <i class="fa fa-chevron-up"></i>
+                            </a>
+                            <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                                <i class="fa fa-wrench"></i>
+                            </a>
+                            <ul class="dropdown-menu dropdown-user">
+                                <li><a href="javascript:;">选项1</a>
+                                </li>
+                                <li><a href="javascript:;">选项2</a>
+                                </li>
+                            </ul>
+                            <a class="close-link">
+                                <i class="fa fa-times"></i>
+                            </a>
+                        </div>
+                    </div>
+                    <div class="ibox-content">
+                        <div class="row">
+                            <div class="col-sm-6 b-r">
+                                <h3 class="m-t-none m-b">登录</h3>
+                                <p>欢迎登录本站(⊙o⊙)</p>
+                                <form role="form">
+                                    <div class="form-group">
+                                        <label>用户名</label>
+                                        <input type="email" placeholder="请输入您注册的E-mail" class="form-control">
+                                    </div>
+                                    <div class="form-group">
+                                        <label>密码</label>
+                                        <input type="password" placeholder="请输入密码" class="form-control">
+                                    </div>
+                                    <div>
+                                        <button class="btn btn-sm btn-primary pull-right m-t-n-xs" type="submit"><strong>登 录</strong>
+                                        </button>
+                                        <label>
+                                            <input type="checkbox">自动登录</label>
+                                    </div>
+                                </form>
+                            </div>
+                            <div class="col-sm-6">
+                                <h4>还不是会员?</h4>
+                                <p>您可以注册一个新账户</p>
+                                <p class="text-center">
+                                    <a href="javascript:;"><i class="fa fa-sign-in big-icon"></i></a>
+                                </p>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-5">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>横向表单</h5>
+                        <div class="ibox-tools">
+                            <a class="collapse-link">
+                                <i class="fa fa-chevron-up"></i>
+                            </a>
+                            <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                                <i class="fa fa-wrench"></i>
+                            </a>
+                            <ul class="dropdown-menu dropdown-user">
+                                <li><a href="javascript:;">选项1</a>
+                                </li>
+                                <li><a href="javascript:;">选项2</a>
+                                </li>
+                            </ul>
+                            <a class="close-link">
+                                <i class="fa fa-times"></i>
+                            </a>
+                        </div>
+                    </div>
+                    <div class="ibox-content">
+                        <form class="form-horizontal">
+                            <p>欢迎登录本站(⊙o⊙)</p>
+                            <div class="form-group">
+                                <label class="col-sm-3 control-label">用户名:</label>
+
+                                <div class="col-sm-8">
+                                    <input type="email" placeholder="用户名" class="form-control"> <span class="help-block m-b-none">请输入您注册时所填的E-mail</span>
+                                </div>
+                            </div>
+                            <div class="form-group">
+                                <label class="col-sm-3 control-label">密码:</label>
+
+                                <div class="col-sm-8">
+                                    <input type="password" placeholder="密码" class="form-control">
+                                </div>
+                            </div>
+                            <div class="form-group">
+                                <div class="col-sm-offset-3 col-sm-8">
+                                    <button class="btn btn-sm btn-white" type="submit">登 录</button>
+                                </div>
+                            </div>
+                        </form>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div class="row">
+            <div class="col-sm-8">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>内联表单</h5>
+                        <div class="ibox-tools">
+                            <a class="collapse-link">
+                                <i class="fa fa-chevron-up"></i>
+                            </a>
+                            <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                                <i class="fa fa-wrench"></i>
+                            </a>
+                            <ul class="dropdown-menu dropdown-user">
+                                <li><a href="javascript:;">选项1</a>
+                                </li>
+                                <li><a href="javascript:;">选项2</a>
+                                </li>
+                            </ul>
+                            <a class="close-link">
+                                <i class="fa fa-times"></i>
+                            </a>
+                        </div>
+                    </div>
+                    <div class="ibox-content">
+                        <form role="form" class="form-inline">
+                            <div class="form-group">
+                                <label for="exampleInputEmail2" class="sr-only">用户名</label>
+                                <input type="email" placeholder="请输入用户名" id="exampleInputEmail2" class="form-control">
+                            </div>
+                            <div class="form-group">
+                                <label for="exampleInputPassword2" class="sr-only">密码</label>
+                                <input type="password" placeholder="请输入密码" id="exampleInputPassword2" class="form-control">
+                            </div>
+                            <div class="checkbox m-l m-r-xs">
+                                <label>
+                                    <input type="checkbox"><i></i> 自动登录</label>
+                            </div>
+                            <button class="btn btn-white" type="submit">登录</button>
+                        </form>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-4">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>弹出表单 <small>弹出框登录示例</small></h5>
+                        <div class="ibox-tools">
+                            <a class="collapse-link">
+                                <i class="fa fa-chevron-up"></i>
+                            </a>
+                            <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                                <i class="fa fa-wrench"></i>
+                            </a>
+                            <ul class="dropdown-menu dropdown-user">
+                                <li><a href="javascript:;">选项1</a>
+                                </li>
+                                <li><a href="javascript:;">选项2</a>
+                                </li>
+                            </ul>
+                            <a class="close-link">
+                                <i class="fa fa-times"></i>
+                            </a>
+                        </div>
+                    </div>
+                    <div class="ibox-content">
+                        <div class="text-center">
+                            <a data-toggle="modal" class="btn btn-primary" href="#modal-form">打开登录窗口</a>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div class="row">
+            <div class="col-sm-12">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>所有表单元素 <small>包括自定义样式的复选和单选按钮</small></h5>
+                        <div class="ibox-tools">
+                            <a class="collapse-link">
+                                <i class="fa fa-chevron-up"></i>
+                            </a>
+                            <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                                <i class="fa fa-wrench"></i>
+                            </a>
+                            <ul class="dropdown-menu dropdown-user">
+                                <li><a href="javascript:;">选项1</a>
+                                </li>
+                                <li><a href="javascript:;">选项2</a>
+                                </li>
+                            </ul>
+                            <a class="close-link">
+                                <i class="fa fa-times"></i>
+                            </a>
+                        </div>
+                    </div>
+                    <div class="ibox-content">
+                        <form method="get" class="form-horizontal">
+                            <div class="form-group">
+                                <label class="col-sm-2 control-label">普通</label>
+
+                                <div class="col-sm-10">
+                                    <input type="text" class="form-control">
+                                </div>
+                            </div>
+                            <div class="hr-line-dashed"></div>
+                            <div class="form-group">
+                                <label class="col-sm-2 control-label">带说明信息</label>
+                                <div class="col-sm-10">
+                                    <input type="text" class="form-control"> <span class="help-block m-b-none">帮助文本,可能会超过一行,以块级元素显示</span>
+                                </div>
+                            </div>
+                            <div class="hr-line-dashed"></div>
+                            <div class="form-group">
+                                <label class="col-sm-2 control-label">密码</label>
+
+                                <div class="col-sm-10">
+                                    <input type="password" class="form-control" name="password">
+                                </div>
+                            </div>
+                            <div class="hr-line-dashed"></div>
+                            <div class="form-group">
+                                <label class="col-sm-2 control-label">提示</label>
+
+                                <div class="col-sm-10">
+                                    <input type="text" placeholder="提示信息" class="form-control">
+                                </div>
+                            </div>
+                            <div class="hr-line-dashed"></div>
+                            <div class="form-group">
+                                <label class="col-sm-2 control-label">禁用</label>
+
+                                <div class="col-sm-10">
+                                    <input type="text" disabled="" placeholder="已被禁用" class="form-control">
+                                </div>
+                            </div>
+                            <div class="hr-line-dashed"></div>
+                            <div class="form-group">
+                                <label class="col-sm-2 control-label">静态控制</label>
+
+                                <div class="col-sm-10">
+                                    <p class="form-control-static">ruoyi.vip</p>
+                                </div>
+                            </div>
+                            <div class="hr-line-dashed"></div>
+                            <div class="form-group">
+                                <label class="col-sm-2 control-label">复选框&amp;单选框
+                                    <br/>
+                                    <small class="text-navy">普通Bootstrap元素</small>
+                                </label>
+
+                                <div class="col-sm-10">
+                                    <div class="checkbox">
+                                        <label>
+                                            <input type="checkbox" value="">选项1</label>
+                                    </div>
+                                    <div class="radio">
+                                        <label>
+                                            <input type="radio" checked="" value="option1" id="optionsRadios1" name="optionsRadios">选项1</label>
+                                    </div>
+                                    <div class="radio">
+                                        <label>
+                                            <input type="radio" value="option2" id="optionsRadios2" name="optionsRadios">选项2</label>
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="hr-line-dashed"></div>
+                            <div class="form-group">
+                                <label class="col-sm-2 control-label">内联复选框</label>
+
+                                <div class="col-sm-10">
+                                    <label class="checkbox-inline">
+                                        <input type="checkbox" value="option1" id="inlineCheckbox1">a</label>
+                                    <label class="checkbox-inline">
+                                        <input type="checkbox" value="option2" id="inlineCheckbox2">b</label>
+                                    <label class="checkbox-inline">
+                                        <input type="checkbox" value="option3" id="inlineCheckbox3">c</label>
+                                </div>
+                            </div>
+                            <div class="hr-line-dashed"></div>
+                            <div class="form-group">
+                                <label class="col-sm-2 control-label">复选框&amp;单选框
+                                    <br/><small class="text-navy">自定义样式</small>
+                                </label>
+
+                                <div class="col-sm-10">
+                                    <div class="checkbox check-box">
+                                        <label>
+                                            <input type="checkbox" value=""> <i></i> 选项1</label>
+                                    </div>
+                                    <div class="checkbox check-box">
+                                        <label>
+                                            <input type="checkbox" value="" checked=""> <i></i> 选项2(选中)</label>
+                                    </div>
+                                    <div class="checkbox check-box">
+                                        <label>
+                                            <input type="checkbox" value="" disabled="" checked=""> <i></i> 选项3(选中并禁用)</label>
+                                    </div>
+                                    <div class="checkbox check-box">
+                                        <label>
+                                            <input type="checkbox" value="" disabled=""> <i></i> 选项4(禁用)</label>
+                                    </div>
+                                    <div class="radio check-box">
+                                        <label>
+                                            <input type="radio" value="option1" name="a"> <i></i> 选项1</label>
+                                    </div>
+                                    <div class="radio check-box">
+                                        <label>
+                                            <input type="radio" checked="" value="option2" name="a"> <i></i> 选项2(选中)</label>
+                                    </div>
+                                    <div class="radio check-box">
+                                        <label>
+                                            <input type="radio" disabled="" checked="" value="option2"> <i></i> 选项3(选中并禁用)</label>
+                                    </div>
+                                    <div class="radio check-box">
+                                        <label>
+                                            <input type="radio" disabled="" name="a"> <i></i> 选项4(禁用)</label>
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="hr-line-dashed"></div>
+                            <div class="form-group">
+                                <label class="col-sm-2 control-label">内联复选框</label>
+
+                                <div class="col-sm-10">
+                                    <label class="checkbox-inline check-box">
+                                        <input type="checkbox" value="option1">a</label>
+                                    <label class="checkbox-inline check-box">
+                                        <input type="checkbox" value="option2">b</label>
+                                    <label class="checkbox-inline check-box">
+                                        <input type="checkbox" value="option3">c</label>
+                                </div>
+                            </div>
+                            <div class="hr-line-dashed"></div>
+                            <div class="form-group">
+                                <label class="col-sm-2 control-label">Select</label>
+
+                                <div class="col-sm-10">
+                                    <select class="form-control m-b" name="account">
+                                        <option>选项 1</option>
+                                        <option>选项 2</option>
+                                        <option>选项 3</option>
+                                        <option>选项 4</option>
+                                    </select>
+
+                                    <div class="col-sm-4 m-l-n">
+                                        <select class="form-control" multiple="">
+                                            <option>选项 1</option>
+                                            <option>选项 2</option>
+                                            <option>选项 3</option>
+                                            <option>选项 4</option>
+                                        </select>
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="hr-line-dashed"></div>
+                            <div class="form-group has-success">
+                                <label class="col-sm-2 control-label">验证通过</label>
+
+                                <div class="col-sm-10">
+                                    <input type="text" class="form-control">
+                                </div>
+                            </div>
+                            <div class="hr-line-dashed"></div>
+                            <div class="form-group has-warning">
+                                <label class="col-sm-2 control-label">未填写</label>
+
+                                <div class="col-sm-10">
+                                    <input type="text" class="form-control">
+                                </div>
+                            </div>
+                            <div class="hr-line-dashed"></div>
+                            <div class="form-group has-error">
+                                <label class="col-sm-2 control-label">验证未通过</label>
+
+                                <div class="col-sm-10">
+                                    <input type="text" class="form-control">
+                                </div>
+                            </div>
+                            <div class="hr-line-dashed"></div>
+                            <div class="form-group">
+                                <label class="col-sm-2 control-label">自定义尺寸</label>
+
+                                <div class="col-sm-10">
+                                    <input type="text" placeholder=".input-lg" class="form-control input-lg m-b">
+                                    <input type="text" placeholder="Default input" class="form-control m-b">
+                                    <input type="text" placeholder=".input-sm" class="form-control input-sm">
+                                </div>
+                            </div>
+                            <div class="hr-line-dashed"></div>
+                            <div class="form-group">
+                                <label class="col-sm-2 control-label">列尺寸</label>
+
+                                <div class="col-sm-10">
+                                    <div class="row">
+                                        <div class="col-md-2">
+                                            <input type="text" placeholder=".col-md-2" class="form-control">
+                                        </div>
+                                        <div class="col-md-3">
+                                            <input type="text" placeholder=".col-md-3" class="form-control">
+                                        </div>
+                                        <div class="col-md-4">
+                                            <input type="text" placeholder=".col-md-4" class="form-control">
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="hr-line-dashed"></div>
+                            <div class="form-group">
+                                <label class="col-sm-2 control-label">文本框组</label>
+
+                                <div class="col-sm-10">
+                                    <div class="input-group m-b"><span class="input-group-addon">@</span>
+                                        <input type="text" placeholder="用户名" class="form-control">
+                                    </div>
+                                    <div class="input-group m-b">
+                                        <input type="text" class="form-control"> <span class="input-group-addon">.00</span>
+                                    </div>
+                                    <div class="input-group m-b"><span class="input-group-addon">&yen;</span>
+                                        <input type="text" class="form-control"> <span class="input-group-addon">.00</span>
+                                    </div>
+                                    <div class="input-group m-b"><span class="input-group-addon"> <input type="checkbox"> </span>
+                                        <input type="text" class="form-control">
+                                    </div>
+                                    <div class="input-group"><span class="input-group-addon"> <input type="radio"> </span>
+                                        <input type="text" class="form-control">
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="hr-line-dashed"></div>
+                            <div class="form-group">
+                                <label class="col-sm-2 control-label">按钮插件</label>
+
+                                <div class="col-sm-10">
+                                    <div class="input-group m-b"><span class="input-group-btn">
+                                            <button type="button" class="btn btn-primary">搜</button> </span>
+                                        <input type="text" class="form-control">
+                                    </div>
+                                    <div class="input-group">
+                                        <input type="text" class="form-control"> <span class="input-group-btn"> <button type="button" class="btn btn-primary">搜索
+                                        </button> </span>
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="hr-line-dashed"></div>
+                            <div class="form-group">
+                                <label class="col-sm-2 control-label">带下拉框</label>
+
+                                <div class="col-sm-10">
+                                    <div class="input-group m-b">
+                                        <div class="input-group-btn">
+                                            <button data-toggle="dropdown" class="btn btn-white dropdown-toggle" type="button">操作 <span class="caret"></span>
+                                            </button>
+                                            <ul class="dropdown-menu">
+                                                <li><a href="javascript:;">选项1</a>
+                                                </li>
+                                                <li><a href="javascript:;">选项2</a>
+                                                </li>
+                                                <li><a href="javascript:;">选项3</a>
+                                                </li>
+                                                <li class="divider"></li>
+                                                <li><a href="javascript:;">选项4</a>
+                                                </li>
+                                            </ul>
+                                        </div>
+                                        <input type="text" class="form-control">
+                                    </div>
+                                    <div class="input-group">
+                                        <input type="text" class="form-control">
+
+                                        <div class="input-group-btn">
+                                            <button data-toggle="dropdown" class="btn btn-white dropdown-toggle" type="button">操作 <span class="caret"></span>
+                                            </button>
+                                            <ul class="dropdown-menu pull-right">
+                                                <li><a href="javascript:;">选项1</a>
+                                                </li>
+                                                <li><a href="javascript:;">选项2</a>
+                                                </li>
+                                                <li><a href="javascript:;">选项3</a>
+                                                </li>
+                                                <li class="divider"></li>
+                                                <li><a href="javascript:;">选项4</a>
+                                                </li>
+                                            </ul>
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="hr-line-dashed"></div>
+                            <div class="form-group">
+                                <label class="col-sm-2 control-label">分段</label>
+
+                                <div class="col-sm-10">
+                                    <div class="input-group m-b">
+                                        <div class="input-group-btn">
+                                            <button tabindex="-1" class="btn btn-white" type="button">操作</button>
+                                            <button data-toggle="dropdown" class="btn btn-white dropdown-toggle" type="button"><span class="caret"></span>
+                                            </button>
+                                            <ul class="dropdown-menu">
+                                                <li><a href="javascript:;">选项1</a>
+                                                </li>
+                                                <li><a href="javascript:;">选项2</a>
+                                                </li>
+                                                <li><a href="javascript:;">选项3</a>
+                                                </li>
+                                                <li class="divider"></li>
+                                                <li><a href="javascript:;">选项4</a>
+                                                </li>
+                                            </ul>
+                                        </div>
+                                        <input type="text" class="form-control">
+                                    </div>
+                                    <div class="input-group">
+                                        <input type="text" class="form-control">
+
+                                        <div class="input-group-btn">
+                                            <button tabindex="-1" class="btn btn-white" type="button">操作</button>
+                                            <button data-toggle="dropdown" class="btn btn-white dropdown-toggle" type="button"><span class="caret"></span>
+                                            </button>
+                                            <ul class="dropdown-menu pull-right">
+                                                	分段
+                                            </ul>
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="hr-line-dashed"></div>
+                            <div class="form-group">
+                                <div class="col-sm-4 col-sm-offset-2">
+                                    <button class="btn btn-primary" type="submit">保存内容</button>
+                                    <button class="btn btn-white" type="submit">取消</button>
+                                </div>
+                            </div>
+                        </form>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+
+    <div id="modal-form" class="modal fade" aria-hidden="true">
+        <div class="modal-dialog">
+            <div class="modal-content">
+                <div class="modal-body">
+                    <div class="row">
+                        <div class="col-sm-6 b-r">
+                            <h3 class="m-t-none m-b">登录</h3>
+
+                            <p>欢迎登录本站(⊙o⊙)</p>
+
+                            <form role="form">
+                                <div class="form-group">
+                                    <label>用户名:</label>
+                                    <input type="email" placeholder="请输入用户名" class="form-control">
+                                </div>
+                                <div class="form-group">
+                                    <label>密码:</label>
+                                    <input type="password" placeholder="请输入密码" class="form-control">
+                                </div>
+                                <div>
+                                    <button class="btn btn-sm btn-primary pull-right m-t-n-xs" type="submit"><strong>登录</strong>
+                                    </button>
+                                    <label>
+                                        <input type="checkbox" class="i-checks">自动登录</label>
+                                </div>
+                            </form>
+                        </div>
+                        <div class="col-sm-6">
+                            <h4>还不是会员?</h4>
+                            <p>您可以注册一个账户</p>
+                            <p class="text-center">
+                                <a href="javascript:;"><i class="fa fa-sign-in big-icon"></i></a>
+                            </p>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <th:block th:include="include :: footer" />
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/demo/form/button.html b/ruoyi-admin/src/main/resources/templates/demo/form/button.html
new file mode 100644
index 0000000..6b69c87
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/form/button.html
@@ -0,0 +1,620 @@
+<!DOCTYPE html>
+<html lang="zh">
+<head>
+	<th:block th:include="include :: header('按钮')" />
+</head>
+<body class="gray-bg">
+     <div class="row wrapper wrapper-content animated fadeInRight">
+        <div class="col-sm-4">
+            <div class="ibox float-e-margins">
+                <div class="ibox-title">
+                    <h5>按钮颜色</h5>
+                    <div class="ibox-tools">
+                        <a class="collapse-link">
+                            <i class="fa fa-chevron-up"></i>
+                        </a>
+                        <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                            <i class="fa fa-wrench"></i>
+                        </a>
+                        <ul class="dropdown-menu dropdown-user">
+                            <li><a href="javascript:;">选项1</a>
+                            </li>
+                            <li><a href="javascript:;">选项2</a>
+                            </li>
+                        </ul>
+                        <a class="close-link">
+                            <i class="fa fa-times"></i>
+                        </a>
+                    </div>
+                </div>
+                <div class="ibox-content">
+                    <p>
+                        可使用class来快速改变按钮的颜色,如<code>.btn-primary</code>
+                    </p>
+
+                    <h3 class="font-bold">
+                            普通按钮
+                        </h3>
+                    <p>
+                        <button type="button" class="btn btn-w-m btn-default">btn-default</button>
+                        <button type="button" class="btn btn-w-m btn-primary">btn-primary</button>
+                        <button type="button" class="btn btn-w-m btn-success">btn-success</button>
+                        <button type="button" class="btn btn-w-m btn-info">btn-info</button>
+                        <button type="button" class="btn btn-w-m btn-warning">btn-warning</button>
+                        <button type="button" class="btn btn-w-m btn-danger">btn-danger</button>
+                        <button type="button" class="btn btn-w-m btn-white">btn-white</button>
+                        <button type="button" class="btn btn-w-m btn-link">btn-link</button>
+                    </p>
+                </div>
+            </div>
+        </div>
+        <div class="col-sm-4">
+            <div class="ibox float-e-margins">
+                <div class="ibox-title">
+                    <h5>按钮大小</h5>
+                    <div class="ibox-tools">
+                        <a class="collapse-link">
+                            <i class="fa fa-chevron-up"></i>
+                        </a>
+                        <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                            <i class="fa fa-wrench"></i>
+                        </a>
+                        <ul class="dropdown-menu dropdown-user">
+                            <li><a href="javascript:;">选项1</a>
+                            </li>
+                            <li><a href="javascript:;">选项2</a>
+                            </li>
+                        </ul>
+                        <a class="close-link">
+                            <i class="fa fa-times"></i>
+                        </a>
+                    </div>
+                </div>
+                <div class="ibox-content">
+                    <p>
+                        可以通过添加class的值为<code>.btn-lg</code>, <code>.btn-sm</code>, or <code>.btn-xs</code>来修改按钮的大小
+                    </p>
+                    <h3 class="font-bold">按钮尺寸</h3>
+                    <p>
+                        <button type="button" class="btn btn-primary btn-lg">大按钮</button>
+                        <button type="button" class="btn btn-default btn-lg">大按钮</button>
+                        <br/>
+                        <button type="button" class="btn btn-primary">默认按钮</button>
+                        <button type="button" class="btn btn-default">默认按钮</button>
+                        <br/>
+                        <button type="button" class="btn btn-primary btn-sm">小按钮</button>
+                        <button type="button" class="btn btn-default btn-sm">小按钮</button>
+                        <br/>
+                        <button type="button" class="btn btn-primary btn-xs">Mini按钮</button>
+                        <button type="button" class="btn btn-default btn-xs">Mini按钮</button>
+                    </p>
+                </div>
+            </div>
+        </div>
+        <div class="col-sm-4">
+            <div class="ibox float-e-margins">
+                <div class="ibox-title">
+                    <h5>线性按钮</h5>
+                    <div class="ibox-tools">
+                        <a class="collapse-link">
+                            <i class="fa fa-chevron-up"></i>
+                        </a>
+                        <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                            <i class="fa fa-wrench"></i>
+                        </a>
+                        <ul class="dropdown-menu dropdown-user">
+                            <li><a href="javascript:;">选项1</a>
+                            </li>
+                            <li><a href="javascript:;">选项2</a>
+                            </li>
+                        </ul>
+                        <a class="close-link">
+                            <i class="fa fa-times"></i>
+                        </a>
+                    </div>
+                </div>
+                <div class="ibox-content">
+                    <p>
+                        要使用线性按钮,可添加class<code>.btn-block</code>或<code>.btn-outline</code>
+                    </p>
+
+                    <h3 class="font-bold">线性按钮</h3>
+                    <p>
+                        <button type="button" class="btn btn-outline btn-default">默认</button>
+                        <button type="button" class="btn btn-outline btn-primary">主要</button>
+                        <button type="button" class="btn btn-outline btn-success">成功</button>
+                        <button type="button" class="btn btn-outline btn-info">信息</button>
+                        <button type="button" class="btn btn-outline btn-warning">警告</button>
+                        <button type="button" class="btn btn-outline btn-danger">危险</button>
+                        <button type="button" class="btn btn-outline btn-link">链接</button>
+                    </p>
+                    <h3 class="font-bold">块级按钮</h3>
+                    <p>
+                        <button type="button" class="btn btn-block btn-outline btn-primary">这是一个块级按钮</button>
+                    </p>
+                </div>
+            </div>
+        </div>
+        <div class="col-sm-12">
+            <div class="ibox float-e-margins">
+                <div class="ibox-title">
+                    <h5>3D按钮</h5>
+                    <div class="ibox-tools">
+                        <a class="collapse-link">
+                            <i class="fa fa-chevron-up"></i>
+                        </a>
+                        <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                            <i class="fa fa-wrench"></i>
+                        </a>
+                        <ul class="dropdown-menu dropdown-user">
+                            <li><a href="javascript:;">选项1</a>
+                            </li>
+                            <li><a href="javascript:;">选项2</a>
+                            </li>
+                        </ul>
+                        <a class="close-link">
+                            <i class="fa fa-times"></i>
+                        </a>
+                    </div>
+                </div>
+                <div class="ibox-content">
+                    <p>
+                        可以通过添加<code>.dim</code>class来使用3D按钮.
+                    </p>
+                    <h3 class="font-bold">3D按钮</h3>
+
+                    <button class="btn btn-primary dim btn-large-dim" type="button"><i class="fa fa-money"></i>
+                    </button>
+                    <button class="btn btn-warning dim btn-large-dim" type="button"><i class="fa fa-warning"></i>
+                    </button>
+                    <button class="btn btn-danger  dim btn-large-dim" type="button"><i class="fa fa-heart"></i>
+                    </button>
+                    <button class="btn btn-primary  dim btn-large-dim" type="button"><i class="fa fa-dollar"></i>6</button>
+                    <button class="btn btn-info  dim btn-large-dim btn-outline" type="button"><i class="fa fa-ruble"></i>
+                    </button>
+                    <button class="btn btn-primary dim" type="button"><i class="fa fa-money"></i>
+                    </button>
+                    <button class="btn btn-warning dim" type="button"><i class="fa fa-warning"></i>
+                    </button>
+                    <button class="btn btn-primary dim" type="button"><i class="fa fa-check"></i>
+                    </button>
+                    <button class="btn btn-success  dim" type="button"><i class="fa fa-upload"></i>
+                    </button>
+                    <button class="btn btn-info  dim" type="button"><i class="fa fa-paste"></i>
+                    </button>
+                    <button class="btn btn-warning  dim" type="button"><i class="fa fa-warning"></i>
+                    </button>
+                    <button class="btn btn-default  dim " type="button"><i class="fa fa-star"></i>
+                    </button>
+                    <button class="btn btn-danger  dim " type="button"><i class="fa fa-heart"></i>
+                    </button>
+
+                    <button class="btn btn-outline btn-primary dim" type="button"><i class="fa fa-money"></i>
+                    </button>
+                    <button class="btn btn-outline btn-warning dim" type="button"><i class="fa fa-warning"></i>
+                    </button>
+                    <button class="btn btn-outline btn-primary dim" type="button"><i class="fa fa-check"></i>
+                    </button>
+                    <button class="btn btn-outline btn-success  dim" type="button"><i class="fa fa-upload"></i>
+                    </button>
+                    <button class="btn btn-outline btn-info  dim" type="button"><i class="fa fa-paste"></i>
+                    </button>
+                    <button class="btn btn-outline btn-warning  dim" type="button"><i class="fa fa-warning"></i>
+                    </button>
+                    <button class="btn btn-outline btn-danger  dim " type="button"><i class="fa fa-heart"></i>
+                    </button>
+
+                </div>
+            </div>
+        </div>
+        <div class="col-sm-12">
+            <div class="row">
+                <div class="col-sm-6">
+                    <div class="ibox float-e-margins">
+                        <div class="ibox-title">
+                            <h5>下拉按钮</h5>
+                            <div class="ibox-tools">
+                                <a class="collapse-link">
+                                    <i class="fa fa-chevron-up"></i>
+                                </a>
+                                <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                                    <i class="fa fa-wrench"></i>
+                                </a>
+                                <ul class="dropdown-menu dropdown-user">
+                                    <li><a href="javascript:;">选项1</a>
+                                    </li>
+                                    <li><a href="javascript:;">选项2</a>
+                                    </li>
+                                </ul>
+                                <a class="close-link">
+                                    <i class="fa fa-times"></i>
+                                </a>
+                            </div>
+                        </div>
+                        <div class="ibox-content">
+                            <p>
+                                下拉按钮可使用任何颜色任何大小
+                            </p>
+
+                            <h3 class="font-bold">下拉按钮</h3>
+                            <div class="btn-group">
+                                <button data-toggle="dropdown" class="btn btn-primary dropdown-toggle">操作 <span class="caret"></span>
+                                </button>
+                                <ul class="dropdown-menu">
+                                    <li><a href="javascript:;">置顶</a>
+                                    </li>
+                                    <li><a href="javascript:;" class="font-bold">修改</a>
+                                    </li>
+                                    <li><a href="javascript:;">禁用</a>
+                                    </li>
+                                    <li class="divider"></li>
+                                    <li><a href="javascript:;">删除</a>
+                                    </li>
+                                </ul>
+                            </div>
+                            <div class="btn-group">
+                                <button data-toggle="dropdown" class="btn btn-warning dropdown-toggle">操作 <span class="caret"></span>
+                                </button>
+                                <ul class="dropdown-menu">
+                                    <li><a href="javascript:;">置顶</a>
+                                    </li>
+                                    <li><a href="javascript:;">修改</a>
+                                    </li>
+                                    <li><a href="javascript:;">禁用</a>
+                                    </li>
+                                    <li class="divider"></li>
+                                    <li><a href="javascript:;">删除</a>
+                                    </li>
+                                </ul>
+                            </div>
+                            <div class="btn-group">
+                                <button data-toggle="dropdown" class="btn btn-default dropdown-toggle">操作 <span class="caret"></span>
+                                </button>
+                                <ul class="dropdown-menu">
+                                    <li><a href="javascript:;">置顶</a>
+                                    </li>
+                                    <li><a href="javascript:;" class="font-bold">修改</a>
+                                    </li>
+                                    <li><a href="javascript:;">禁用</a>
+                                    </li>
+                                    <li class="divider"></li>
+                                    <li><a href="javascript:;">删除</a>
+                                    </li>
+                                </ul>
+                            </div>
+
+                            <br/>
+                            <div class="btn-group">
+                                <button data-toggle="dropdown" class="btn btn-primary btn-sm dropdown-toggle">操作 <span class="caret"></span>
+                                </button>
+                                <ul class="dropdown-menu">
+                                    <li><a href="javascript:;">置顶</a>
+                                    </li>
+                                    <li><a href="javascript:;" class="font-bold">修改</a>
+                                    </li>
+                                    <li><a href="javascript:;">禁用</a>
+                                    </li>
+                                    <li class="divider"></li>
+                                    <li><a href="javascript:;">删除</a>
+                                    </li>
+                                </ul>
+                            </div>
+                            <div class="btn-group">
+                                <button data-toggle="dropdown" class="btn btn-warning btn-sm dropdown-toggle">操作 <span class="caret"></span>
+                                </button>
+                                <ul class="dropdown-menu">
+                                    <li><a href="javascript:;">置顶</a>
+                                    </li>
+                                    <li><a href="javascript:;" class="font-bold">修改</a>
+                                    </li>
+                                    <li><a href="javascript:;">禁用</a>
+                                    </li>
+                                    <li class="divider"></li>
+                                    <li><a href="javascript:;">删除</a>
+                                    </li>
+                                </ul>
+                            </div>
+                            <div class="btn-group">
+                                <button data-toggle="dropdown" class="btn btn-default btn-sm dropdown-toggle">操作 <span class="caret"></span>
+                                </button>
+                                <ul class="dropdown-menu">
+                                    <li><a href="javascript:;">置顶</a>
+                                    </li>
+                                    <li><a href="javascript:;" class="font-bold">修改</a>
+                                    </li>
+                                    <li><a href="javascript:;">禁用</a>
+                                    </li>
+                                    <li class="divider"></li>
+                                    <li><a href="javascript:;">删除</a>
+                                    </li>
+                                </ul>
+                            </div>
+                            <br/>
+                            <div class="btn-group">
+                                <button data-toggle="dropdown" class="btn btn-primary btn-xs dropdown-toggle">操作 <span class="caret"></span>
+                                </button>
+                                <ul class="dropdown-menu">
+                                    <li><a href="javascript:;">置顶</a>
+                                    </li>
+                                    <li><a href="javascript:;" class="font-bold">修改</a>
+                                    </li>
+                                    <li><a href="javascript:;">禁用</a>
+                                    </li>
+                                    <li class="divider"></li>
+                                    <li><a href="javascript:;">删除</a>
+                                    </li>
+                                </ul>
+                            </div>
+                            <div class="btn-group">
+                                <button data-toggle="dropdown" class="btn btn-warning btn-xs dropdown-toggle">操作 <span class="caret"></span>
+                                </button>
+                                <ul class="dropdown-menu">
+                                    <li><a href="javascript:;">置顶</a>
+                                    </li>
+                                    <li><a href="javascript:;" class="font-bold">修改</a>
+                                    </li>
+                                    <li><a href="javascript:;">禁用</a>
+                                    </li>
+                                    <li class="divider"></li>
+                                    <li><a href="javascript:;">删除</a>
+                                    </li>
+                                </ul>
+                            </div>
+                            <div class="btn-group">
+                                <button data-toggle="dropdown" class="btn btn-default btn-xs dropdown-toggle">操作 <span class="caret"></span>
+                                </button>
+                                <ul class="dropdown-menu">
+                                    <li><a href="javascript:;">置顶</a>
+                                    </li>
+                                    <li><a href="javascript:;" class="font-bold">修改</a>
+                                    </li>
+                                    <li><a href="javascript:;">禁用</a>
+                                    </li>
+                                    <li class="divider"></li>
+                                    <li><a href="javascript:;">删除</a>
+                                    </li>
+                                </ul>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+                <div class="col-sm-6">
+                    <div class="ibox float-e-margins">
+                        <div class="ibox-title">
+                            <h5>按钮组</h5>
+                            <div class="ibox-tools">
+                                <a class="collapse-link">
+                                    <i class="fa fa-chevron-up"></i>
+                                </a>
+                                <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                                    <i class="fa fa-wrench"></i>
+                                </a>
+                                <ul class="dropdown-menu dropdown-user">
+                                    <li><a href="javascript:;">选项1</a>
+                                    </li>
+                                    <li><a href="javascript:;">选项2</a>
+                                    </li>
+                                </ul>
+                                <a class="close-link">
+                                    <i class="fa fa-times"></i>
+                                </a>
+                            </div>
+                        </div>
+                        <div class="ibox-content">
+
+                            <h3 class="font-bold">按钮组</h3>
+                            <div class="btn-group">
+                                <button class="btn btn-white" type="button">左</button>
+                                <button class="btn btn-primary" type="button">中</button>
+                                <button class="btn btn-white" type="button">右</button>
+                            </div>
+                            <br/>
+                            <br/>
+                            <div class="btn-group">
+                                <button type="button" class="btn btn-white"><i class="fa fa-chevron-left"></i>
+                                </button>
+                                <button class="btn btn-white">1</button>
+                                <button class="btn btn-white  active">2</button>
+                                <button class="btn btn-white">3</button>
+                                <button class="btn btn-white">4</button>
+                                <button type="button" class="btn btn-white"><i class="fa fa-chevron-right"></i>
+                                </button>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="ibox float-e-margins">
+                <div class="ibox-title">
+                    <h5>图标按钮 </h5>
+                    <div class="ibox-tools">
+                        <a class="collapse-link">
+                            <i class="fa fa-chevron-up"></i>
+                        </a>
+                        <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                            <i class="fa fa-wrench"></i>
+                        </a>
+                        <ul class="dropdown-menu dropdown-user">
+                            <li><a href="javascript:;">选项1</a>
+                            </li>
+                            <li><a href="javascript:;">选项2</a>
+                            </li>
+                        </ul>
+                        <a class="close-link">
+                            <i class="fa fa-times"></i>
+                        </a>
+                    </div>
+                </div>
+                <div class="ibox-content">
+                    <p>
+                        任何按钮都可以在左侧或右侧添加图标
+                    </p>
+
+                    <h3 class="font-bold">图标按钮</h3>
+                    <p>
+                        <button class="btn btn-primary " type="button"><i class="fa fa-check"></i>&nbsp;提交</button>
+                        <button class="btn btn-success " type="button"><i class="fa fa-upload"></i>&nbsp;&nbsp;<span class="bold">上传</span>
+                        </button>
+                        <button class="btn btn-info " type="button"><i class="fa fa-paste"></i> 编辑</button>
+                        <button class="btn btn-warning " type="button"><i class="fa fa-warning"></i> <span class="bold">警告</span>
+                        </button>
+                        <button class="btn btn-default " type="button"><i class="fa fa-map-marker"></i>&nbsp;&nbsp;百度地图</button>
+
+                        <a class="btn btn-success">
+                            <i class="fa fa-weixin"> </i> 分享到微信
+                        </a>
+                        <a class="btn btn-success btn-outline">
+                            <i class="fa fa-qq"> </i> 使用QQ账号登录
+                        </a>
+                        <a class="btn btn-white btn-bitbucket">
+                            <i class="fa fa-user-md"></i>
+                        </a>
+                        <a class="btn btn-white btn-bitbucket">
+                            <i class="fa fa-group"></i>
+                        </a>
+                        <a class="btn btn-white btn-bitbucket">
+                            <i class="fa fa-wrench"></i>
+                        </a>
+                        <a class="btn btn-white btn-bitbucket">
+                            <i class="fa fa-exchange"></i>
+                        </a>
+                        <a class="btn btn-white btn-bitbucket">
+                            <i class="fa fa-check-circle-o"></i>
+                        </a>
+                        <a class="btn btn-white btn-bitbucket">
+                            <i class="fa fa-road"></i>
+                        </a>
+                        <a class="btn btn-white btn-bitbucket">
+                            <i class="fa fa-ambulance"></i>
+                        </a>
+                        <a class="btn btn-white btn-bitbucket">
+                            <i class="fa fa-star"></i> 收藏
+                        </a>
+                    </p>
+
+                    <h3 class="font-bold">按钮切换</h3>
+                    <button data-toggle="button" class="btn btn-primary btn-outline" type="button">按钮1</button>
+                    <button data-toggle="button" class="btn btn-primary" type="button">按钮2</button>
+                    <div data-toggle="buttons-checkbox" class="btn-group">
+                        <button class="btn btn-primary active" type="button"><i class="fa fa-bold"></i> 粗体</button>
+                        <button class="btn btn-primary" type="button"><i class="fa fa-underline"></i> 下划线</button>
+                        <button class="btn btn-primary active" type="button"><i class="fa fa-italic"></i> 斜体</button>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div class="col-sm-12">
+            <div class="row">
+                <div class="col-sm-6">
+                    <div class="ibox float-e-margins">
+                        <div class="ibox-title">
+                            <h5>圆形图标按钮</h5>
+                            <div class="ibox-tools">
+                                <a class="collapse-link">
+                                    <i class="fa fa-chevron-up"></i>
+                                </a>
+                                <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                                    <i class="fa fa-wrench"></i>
+                                </a>
+                                <ul class="dropdown-menu dropdown-user">
+                                    <li><a href="javascript:;">选项1</a>
+                                    </li>
+                                    <li><a href="javascript:;">选项2</a>
+                                    </li>
+                                </ul>
+                                <a class="close-link">
+                                    <i class="fa fa-times"></i>
+                                </a>
+                            </div>
+                        </div>
+                        <div class="ibox-content">
+                            <p>
+                                要使用圆形图标按钮,可以通过添加class为<code>.btn-circle</code>实现
+                            </p>
+
+                            <h3 class="font-bold">圆形按钮</h3>
+                            <br/>
+                            <button class="btn btn-default btn-circle" type="button"><i class="fa fa-check"></i>
+                            </button>
+                            <button class="btn btn-primary btn-circle" type="button"><i class="fa fa-list"></i>
+                            </button>
+                            <button class="btn btn-success btn-circle" type="button"><i class="fa fa-link"></i>
+                            </button>
+                            <button class="btn btn-info btn-circle" type="button"><i class="fa fa-check"></i>
+                            </button>
+                            <button class="btn btn-warning btn-circle" type="button"><i class="fa fa-times"></i>
+                            </button>
+                            <button class="btn btn-danger btn-circle" type="button"><i class="fa fa-heart"></i>
+                            </button>
+                            <button class="btn btn-danger btn-circle btn-outline" type="button"><i class="fa fa-heart"></i>
+                            </button>
+                            <br/>
+                            <br/>
+                            <button class="btn btn-default btn-circle btn-lg" type="button"><i class="fa fa-check"></i>
+                            </button>
+                            <button class="btn btn-primary btn-circle btn-lg" type="button"><i class="fa fa-list"></i>
+                            </button>
+                            <button class="btn btn-success btn-circle btn-lg" type="button"><i class="fa fa-link"></i>
+                            </button>
+                            <button class="btn btn-info btn-circle btn-lg" type="button"><i class="fa fa-check"></i>
+                            </button>
+                            <button class="btn btn-warning btn-circle btn-lg" type="button"><i class="fa fa-times"></i>
+                            </button>
+                            <button class="btn btn-danger btn-circle btn-lg" type="button"><i class="fa fa-heart"></i>
+                            </button>
+                            <button class="btn btn-danger btn-circle btn-lg btn-outline" type="button"><i class="fa fa-heart"></i>
+                            </button>
+
+                        </div>
+                    </div>
+                </div>
+                <div class="col-sm-6">
+                    <div class="ibox float-e-margins">
+                        <div class="ibox-title">
+                            <h5>圆角按钮</h5>
+                            <div class="ibox-tools">
+                                <a class="collapse-link">
+                                    <i class="fa fa-chevron-up"></i>
+                                </a>
+                                <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                                    <i class="fa fa-wrench"></i>
+                                </a>
+                                <ul class="dropdown-menu dropdown-user">
+                                    <li><a href="javascript:;">选项1</a>
+                                    </li>
+                                    <li><a href="javascript:;">选项2</a>
+                                    </li>
+                                </ul>
+                                <a class="close-link">
+                                    <i class="fa fa-times"></i>
+                                </a>
+                            </div>
+                        </div>
+                        <div class="ibox-content">
+                            <p>
+                                可以通过添加class的值微<code>.btn-rounded</code>来实现圆角按钮
+                            </p>
+
+                            <h3 class="font-bold">按钮组</h3>
+                            <p>
+                                <a class="btn btn-default btn-rounded" href="javascript:;">默认</a>
+                                <a class="btn btn-primary btn-rounded" href="javascript:;">主要</a>
+                                <a class="btn btn-success btn-rounded" href="javascript:;">成果</a>
+                                <a class="btn btn-info btn-rounded" href="javascript:;">信息</a>
+                                <a class="btn btn-warning btn-rounded" href="javascript:;">警告</a>
+                                <a class="btn btn-danger btn-rounded" href="javascript:;">危险</a>
+                                <a class="btn btn-danger btn-rounded btn-outline" href="javascript:;">危险</a>
+                                <br/>
+                                <br/>
+                                <a class="btn btn-primary btn-rounded btn-block" href="javascript:;"><i class="fa fa-info-circle"></i> 圆角块级带图标按钮</a>
+                            </p>
+                        </div>
+                    </div>
+                </div>
+
+            </div>
+        </div>
+    </div>
+    <th:block th:include="include :: footer" />
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/demo/form/cards.html b/ruoyi-admin/src/main/resources/templates/demo/form/cards.html
new file mode 100644
index 0000000..35a7f68
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/form/cards.html
@@ -0,0 +1,319 @@
+<!DOCTYPE html>
+<html lang="zh">
+<head>
+	<th:block th:include="include :: header('卡片列表')" />
+</head>
+<body class="gray-bg">
+    <div class="wrapper wrapper-content animated fadeInRight">
+        <div class="row">
+            <div class="col-sm-4">
+                <div class="ibox">
+                    <div class="ibox-title">
+                        <span class="label label-primary pull-right">NEW</span>
+                        <h5>IT-01 - 设计部</h5>
+                    </div>
+                    <div class="ibox-content">
+                        <h4>部门简介</h4>
+                        <p>
+                                                                           平面设计(graphic design),也称为视觉传达设计,是以“视觉”作为沟通和表现的方式,透过多种方式来创造和结合符号、图片和文字,借此作出用来传达想法或讯息的视觉表现。
+                        </p>
+                        <div>
+                            <span>当前项目进度:</span>
+                            <div class="stat-percent">48%</div>
+                            <div class="progress progress-mini">
+                                <div style="width: 48%;" class="progress-bar"></div>
+                            </div>
+                        </div>
+                        <div class="row  m-t-sm">
+                            <div class="col-sm-4">
+                                <div class="font-bold">项目</div>
+                                12
+                            </div>
+                            <div class="col-sm-4">
+                                <div class="font-bold">周期</div>
+                                4个月
+                            </div>
+                            <div class="col-sm-4 text-right">
+                                <div class="font-bold">预算</div>
+                                &yen;200,913 <i class="fa fa-level-up text-navy"></i>
+                            </div>
+                        </div>
+
+                    </div>
+                </div>
+                <div class="ibox">
+                    <div class="ibox-title">
+                        <h5>IT-04 - 市场部</h5>
+                    </div>
+                    <div class="ibox-content">
+                        <h4>部门简介</h4>
+                        <p>
+                                                                           平面设计(graphic design),也称为视觉传达设计,是以“视觉”作为沟通和表现的方式,透过多种方式来创造和结合符号、图片和文字,借此作出用来传达想法或讯息的视觉表现。
+                        </p>
+                        <div>
+                            <span>当前项目进度:</span>
+                            <div class="stat-percent">32%</div>
+                            <div class="progress progress-mini">
+                                <div style="width: 32%;" class="progress-bar"></div>
+                            </div>
+                        </div>
+                        <div class="row  m-t-sm">
+                            <div class="col-sm-4">
+                                <div class="font-bold">项目</div>
+                                24
+                            </div>
+                            <div class="col-sm-4">
+                                <div class="font-bold">周期</div>
+                                3个月
+                            </div>
+                            <div class="col-sm-4 text-right">
+                                <div class="font-bold">预算</div>
+                                &yen;190,325 <i class="fa fa-level-up text-navy"></i>
+                            </div>
+                        </div>
+
+                    </div>
+                </div>
+                <div class="ibox">
+                    <div class="ibox-title">
+                        <h5>IT-07 - 财务部</h5>
+                    </div>
+                    <div class="ibox-content">
+                        <h4>部门简介</h4>
+                        <p>
+                                                                           平面设计(graphic design),也称为视觉传达设计,是以“视觉”作为沟通和表现的方式,透过多种方式来创造和结合符号、图片和文字,借此作出用来传达想法或讯息的视觉表现。
+                        </p>
+                        <div>
+                            <span>当前项目进度:</span>
+                            <div class="stat-percent">73%</div>
+                            <div class="progress progress-mini">
+                                <div style="width: 73%;" class="progress-bar"></div>
+                            </div>
+                        </div>
+                        <div class="row  m-t-sm">
+                            <div class="col-sm-4">
+                                <div class="font-bold">项目</div>
+                                11
+                            </div>
+                            <div class="col-sm-4">
+                                <div class="font-bold">周期</div>
+                                6个月
+                            </div>
+                            <div class="col-sm-4 text-right">
+                                <div class="font-bold">预算</div>
+                                &yen;560,105 <i class="fa fa-level-up text-navy"></i>
+                            </div>
+                        </div>
+
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-4">
+                <div class="ibox">
+                    <div class="ibox-title">
+                        <h5>IT-02 - 开发部</h5>
+                    </div>
+                    <div class="ibox-content">
+                        <h4>部门简介</h4>
+                        <p>
+                                                                           平面设计(graphic design),也称为视觉传达设计,是以“视觉”作为沟通和表现的方式,透过多种方式来创造和结合符号、图片和文字,借此作出用来传达想法或讯息的视觉表现。
+                        </p>
+                        <div>
+                            <span>当前项目进度:</span>
+                            <div class="stat-percent">61%</div>
+                            <div class="progress progress-mini">
+                                <div style="width: 61%;" class="progress-bar"></div>
+                            </div>
+                        </div>
+                        <div class="row  m-t-sm">
+                            <div class="col-sm-4">
+                                <div class="font-bold">项目</div>
+                                43
+                            </div>
+                            <div class="col-sm-4">
+                                <div class="font-bold">周期</div>
+                                1个月
+                            </div>
+                            <div class="col-sm-4 text-right">
+                                <div class="font-bold">预算</div>
+                                &yen;705,913 <i class="fa fa-level-up text-navy"></i>
+                            </div>
+                        </div>
+
+                    </div>
+                </div>
+                <div class="ibox">
+                    <div class="ibox-title">
+                        <span class="label label-warning pull-right">截止</span>
+                        <h5>IT-05 - 管理层</h5>
+                    </div>
+                    <div class="ibox-content">
+                        <h4>部门简介</h4>
+                        <p>
+                                                                           平面设计(graphic design),也称为视觉传达设计,是以“视觉”作为沟通和表现的方式,透过多种方式来创造和结合符号、图片和文字,借此作出用来传达想法或讯息的视觉表现。
+                        </p>
+                        <div>
+                            <span>当前项目进度:</span>
+                            <div class="stat-percent">14%</div>
+                            <div class="progress progress-mini">
+                                <div style="width: 14%;" class="progress-bar"></div>
+                            </div>
+                        </div>
+                        <div class="row  m-t-sm">
+                            <div class="col-sm-4">
+                                <div class="font-bold">项目</div>
+                                8
+                            </div>
+                            <div class="col-sm-4">
+                                <div class="font-bold">周期</div>
+                                7个月
+                            </div>
+                            <div class="col-sm-4 text-right">
+                                <div class="font-bold">预算</div>
+                                &yen;40,200 <i class="fa fa-level-up text-navy"></i>
+                            </div>
+                        </div>
+
+                    </div>
+                </div>
+                <div class="ibox">
+                    <div class="ibox-title">
+                        <h5>IT-08 - 销售部</h5>
+                    </div>
+                    <div class="ibox-content">
+                        <h4>部门简介</h4>
+                        <p>
+                                                                           平面设计(graphic design),也称为视觉传达设计,是以“视觉”作为沟通和表现的方式,透过多种方式来创造和结合符号、图片和文字,借此作出用来传达想法或讯息的视觉表现。
+                        </p>
+                        <div>
+                            <span>当前项目进度:</span>
+                            <div class="stat-percent">25%</div>
+                            <div class="progress progress-mini">
+                                <div style="width: 25%;" class="progress-bar"></div>
+                            </div>
+                        </div>
+                        <div class="row  m-t-sm">
+                            <div class="col-sm-4">
+                                <div class="font-bold">项目</div>
+                                25
+                            </div>
+                            <div class="col-sm-4">
+                                <div class="font-bold">周期</div>
+                                4个月
+                            </div>
+                            <div class="col-sm-4 text-right">
+                                <div class="font-bold">预算</div>
+                                &yen;140,105 <i class="fa fa-level-up text-navy"></i>
+                            </div>
+                        </div>
+
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-4">
+                <div class="ibox">
+                    <div class="ibox-title">
+
+                        <h5>IT-02 - 销售部</h5>
+                    </div>
+                    <div class="ibox-content">
+                        <h4>部门简介</h4>
+                        <p>
+                                                                           平面设计(graphic design),也称为视觉传达设计,是以“视觉”作为沟通和表现的方式,透过多种方式来创造和结合符号、图片和文字,借此作出用来传达想法或讯息的视觉表现。
+                        </p>
+                        <div>
+                            <span>当前项目进度:</span>
+                            <div class="stat-percent">82%</div>
+                            <div class="progress progress-mini">
+                                <div style="width: 82%;" class="progress-bar"></div>
+                            </div>
+                        </div>
+                        <div class="row  m-t-sm">
+                            <div class="col-sm-4">
+                                <div class="font-bold">项目</div>
+                                68
+                            </div>
+                            <div class="col-sm-4">
+                                <div class="font-bold">周期</div>
+                                2个月
+                            </div>
+                            <div class="col-sm-4 text-right">
+                                <div class="font-bold">预算</div>
+                                &yen;701,400 <i class="fa fa-level-up text-navy"></i>
+                            </div>
+                        </div>
+
+                    </div>
+                </div>
+                <div class="ibox">
+                    <div class="ibox-title">
+                        <h5>IT-06 - 销售部</h5>
+                    </div>
+                    <div class="ibox-content">
+                        <h4>部门简介</h4>
+                        <p>
+                                                                           平面设计(graphic design),也称为视觉传达设计,是以“视觉”作为沟通和表现的方式,透过多种方式来创造和结合符号、图片和文字,借此作出用来传达想法或讯息的视觉表现。
+                        </p>
+                        <div>
+                            <span>当前项目进度:</span>
+                            <div class="stat-percent">26%</div>
+                            <div class="progress progress-mini">
+                                <div style="width: 26%;" class="progress-bar"></div>
+                            </div>
+                        </div>
+                        <div class="row  m-t-sm">
+                            <div class="col-sm-4">
+                                <div class="font-bold">项目</div>
+                                16
+                            </div>
+                            <div class="col-sm-4">
+                                <div class="font-bold">周期</div>
+                                8个月
+                            </div>
+                            <div class="col-sm-4 text-right">
+                                <div class="font-bold">预算</div>
+                                &yen;160,100 <i class="fa fa-level-up text-navy"></i>
+                            </div>
+                        </div>
+
+                    </div>
+                </div>
+                <div class="ibox">
+                    <div class="ibox-title">
+                        <h5>IT-09 - 销售部</h5>
+                    </div>
+                    <div class="ibox-content">
+                        <h4>部门简介</h4>
+                        <p>
+                                                                           平面设计(graphic design),也称为视觉传达设计,是以“视觉”作为沟通和表现的方式,透过多种方式来创造和结合符号、图片和文字,借此作出用来传达想法或讯息的视觉表现。
+                        </p>
+                        <div>
+                            <span>当前项目进度:</span>
+                            <div class="stat-percent">18%</div>
+                            <div class="progress progress-mini">
+                                <div style="width: 18%;" class="progress-bar"></div>
+                            </div>
+                        </div>
+                        <div class="row  m-t-sm">
+                            <div class="col-sm-4">
+                                <div class="font-bold">项目</div>
+                                53
+                            </div>
+                            <div class="col-sm-4">
+                                <div class="font-bold">周期</div>
+                                9个月
+                            </div>
+                            <div class="col-sm-4 text-right">
+                                <div class="font-bold">预算</div>
+                                &yen;60,140 <i class="fa fa-level-up text-navy"></i>
+                            </div>
+                        </div>
+
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <th:block th:include="include :: footer" />
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/demo/form/cxselect.html b/ruoyi-admin/src/main/resources/templates/demo/form/cxselect.html
new file mode 100644
index 0000000..9b2ab07
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/form/cxselect.html
@@ -0,0 +1,161 @@
+<!DOCTYPE html>
+<html lang="zh">
+<head>
+	<th:block th:include="include :: header('多级联动下拉')" />
+</head>
+<body class="gray-bg">
+      <div class="wrapper wrapper-content animated fadeInRight">
+        <div class="row">
+            <div class="col-sm-12">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>多级联动下拉<small>https://github.com/ciaoca/cxSelect</small></h5>
+                    </div>  
+                    <div class="ibox-content">
+                        <p>简单联动示例。</p>
+                        <div id="element" class="row">
+                            <div class="col-sm-2">
+	                            <select class="type form-control m-b" data-first-title="请选择">
+				                  <option value="">请选择</option>
+				                </select>
+			                </div>
+			                <div class="col-sm-2">
+				                <select class="router form-control m-b" data-first-title="请选择">
+				                  <option value="">请选择</option>
+				                </select>
+			                </div>
+                        </div>
+                        <hr>
+                        
+                        <p>国内省市区联动。</p>
+                        <div id="element1" class="row">
+                            <div class="col-sm-2">
+	                            <select class="province form-control m-b" data-first-title="选择省">
+				                  <option value="">请选择</option>
+				                  <option value="广东省" selected>广东省</option>
+				                </select>
+			                </div>
+			                <div class="col-sm-2">
+				                <select class="city form-control m-b" data-first-title="选择市">
+				                  <option value="">请选择</option>
+				                  <option value="深圳市" selected>深圳市</option>
+				                </select>
+			                </div>
+			                <div class="col-sm-2">
+				                <select class="area form-control m-b" data-first-title="选择地区">
+				                  <option value="">请选择</option>
+				                  <option value="南山区" selected>南山区</option>
+				                </select>
+			                </div>
+                        </div>
+                        <hr>
+                        
+                        <p>自定义选项。</p>
+                        <div id="element2" class="row">
+                            <div class="col-sm-2">
+	                            <select class="first form-control m-b"></select>
+			                </div>
+			                <div class="col-sm-2">
+				                <select class="second form-control m-b"></select>
+			                </div>
+			                <div class="col-sm-2">
+				                <select class="third form-control m-b"></select>
+			                </div>
+			                <div class="col-sm-2">
+				                <select class="fourth form-control m-b"></select>
+			                </div>
+			                <div class="col-sm-2">
+			                    <select class="fifth form-control m-b"></select>
+			                </div>
+                        </div>
+                        <hr>
+                        <div class="form-group">
+                            <label class="font-noraml">相关参数详细信息</label>
+                            <div><a href="http://doc.ruoyi.vip/ruoyi/document/zjwd.html#jquery-cxselect" target="_blank">http://doc.ruoyi.vip/ruoyi/document/zjwd.html#jquery-cxselect</a></div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <th:block th:include="include :: footer" />
+    <th:block th:include="include :: jquery-cxselect-js" />
+    <script th:inline="javascript">
+        // 直接返回获取
+   		var data = [[${data}]];
+    	$('#element').cxSelect({
+    	  selects: ['type', 'router'],
+    	  jsonValue: 'v',
+    	  data: data
+    	});
+    	
+    	// 通过默认url获取
+    	var urlChina = 'cityData';
+    	$.cxSelect.defaults.url = urlChina;
+    	$('#element1').cxSelect({
+   		  selects: ['province', 'city', 'area'],
+   		  nodata: 'none'
+   		});
+    	
+    	// 固定值获取
+    	$('#element2').cxSelect({
+   		  selects: ['first', 'second', 'third', 'fourth', 'fifth'],
+   		  required: true,
+   		  jsonValue: 'v',
+   		  data: [
+   			{'v': '1', 'n': '第一级 >', 's': [
+   			  {'v': '2', 'n': '第二级 >', 's': [
+   				{'v': '3', 'n': '第三级 >', 's': [
+   				  {'v': '4', 'n': '第四级 >', 's': [
+   					{'v': '5', 'n': '第五级 >', 's': [
+   					  {'v': '6', 'n': '第六级 >'}
+   					]}
+   				  ]}
+   				]}
+   			  ]}
+   			]},
+   			{'v': 'test number', 'n': '测试数字', 's': [
+   			  {'v': 'text', 'n': '文本类型', 's': [
+   				{'v': '4', 'n': '4'},
+   				{'v': '5', 'n': '5'},
+   				{'v': '6', 'n': '6'},
+   				{'v': '7', 'n': '7'},
+   				{'v': '8', 'n': '8'},
+   				{'v': '9', 'n': '9'},
+   				{'v': '10', 'n': '10'}
+   			  ]},
+   			  {'v': 'number', 'n': '数值类型', 's': [
+   				{'v': 11, 'n': 11},
+   				{'v': 12, 'n': 12},
+   				{'v': 13, 'n': 13},
+   				{'v': 14, 'n': 14},
+   				{'v': 15, 'n': 15},
+   				{'v': 16, 'n': 16},
+   				{'v': 17, 'n': 17}
+   			  ]}
+   			]},
+   			{'v': 'test boolean','n': '测试 Boolean 类型', 's': [
+   			  {'v': true ,'n': true},
+   			  {'v': false ,'n': false}
+   			]},
+   			{v: 'test quotes', n: '测试属性不加引号', s: [
+   			  {v: 'quotes', n: '引号'}
+   			]},
+   			{v: 'test other', n: '测试奇怪的值', s: [
+   			  {v: '[]', n: '数组(空)'},
+   			  {v: [1,2,3], n: '数组(数值)'},
+   			  {v: ['a','b','c'], n: '数组(文字)'},
+   			  {v: new Date(), n: '日期'},
+   			  {v: new RegExp('\\d+'), n: '正则对象'},
+   			  {v: /\d+/, n: '正则直接量'},
+   			  {v: {}, n: '对象'},
+   			  {v: document.getElementById('custom_data'), n: 'DOM'},
+   			  {v: null, n: 'Null'},
+   			  {n: '未设置 value'}
+   			]},
+   			{'v': '' , 'n': '无子级'}
+   		  ]
+   		});
+    </script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/demo/form/datetime.html b/ruoyi-admin/src/main/resources/templates/demo/form/datetime.html
new file mode 100644
index 0000000..3444cf8
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/form/datetime.html
@@ -0,0 +1,237 @@
+<!DOCTYPE html>
+<html lang="zh">
+<head>
+	<th:block th:include="include :: header('日期和时间')" />
+	<th:block th:include="include :: datetimepicker-css" />
+</head>
+<body class="gray-bg">
+      <div class="wrapper wrapper-content animated fadeInRight">
+        <div class="row">
+            <div class="col-sm-6">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>日期选择器 <small>https://github.com/smalot/bootstrap-datetimepicker</small></h5>
+                    </div>
+                    <div class="ibox-content">
+                        <div class="form-group">
+                            <label class="font-noraml">简单示例</label>
+                            <div class="input-group date">
+                                <span class="input-group-addon"><i class="fa fa-calendar"></i></span>
+                                <input type="text" class="form-control" id="datetimepicker-demo-1" placeholder="yyyy-MM-dd HH:mm">
+                            </div>
+                        </div>
+                        
+                        <div class="form-group">
+                            <label class="font-noraml">显示年月日</label>
+                            <div class="input-group date">
+                                <span class="input-group-addon"><i class="fa fa-calendar"></i></span>
+                                <input type="text" class="form-control" id="datetimepicker-demo-2" placeholder="yyyy-MM-dd">
+                            </div>
+                        </div>
+                        
+                        <div class="form-group">
+                            <label class="font-noraml">显示年月日时分秒</label>
+                            <div class="input-group date">
+                                <span class="input-group-addon"><i class="fa fa-calendar"></i></span>
+                                <input type="text" class="form-control" id="datetimepicker-demo-3" placeholder="yyyy-MM-dd HH:mm:ss">
+                            </div>
+                        </div>
+                        
+                        <div class="form-group">
+			                <label class="font-noraml">带清空的按钮</label>
+			                <div class="input-group date form_date">
+			                    <span class="input-group-addon"><i class="fa fa-calendar"></i></span>
+			                    <input class="form-control" size="16" type="text" readonly>
+			                    <span class="input-group-addon"><span class="glyphicon glyphicon-remove"></span></span>
+			                </div>
+			            </div>
+                        
+                        <div class="form-group">
+                            <label class="font-noraml">日期范围选择</label>
+                            <div class="input-daterange input-group">
+                                <input type="text" class="input-sm form-control" id="datetimepicker-startTime" placeholder="yyyy-MM-dd"/>
+                                <span class="input-group-addon">到</span>
+                                <input type="text" class="input-sm form-control" id="datetimepicker-endTime" placeholder="yyyy-MM-dd"/>
+                            </div>
+                        </div>
+                        <hr>
+                        <div class="form-group">
+                            <label class="font-noraml">相关参数详细信息</label>
+                            <div><a href="http://doc.ruoyi.vip/ruoyi/document/zjwd.html#bootstrap-datetimepicker" target="_blank">http://doc.ruoyi.vip/ruoyi/document/zjwd.html#bootstrap-datetimepicker</a></div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-6">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>日期选择器 <small>https://github.com/sentsin/laydate</small></h5>
+                    </div>
+                    <div class="ibox-content">
+                        <div class="form-group">
+                            <label class="font-noraml">简单示例</label>
+                            <div class="input-group date">
+                                <span class="input-group-addon"><i class="fa fa-calendar"></i></span>
+                                <input type="text" class="form-control" id="laydate-demo-1" placeholder="yyyy-MM-dd">
+                            </div>
+                        </div>
+                        
+                        <div class="form-group">
+                            <label class="font-noraml">显示年月日</label>
+                            <div class="input-group date">
+                                <span class="input-group-addon"><i class="fa fa-calendar"></i></span>
+                                <input type="text" class="form-control" id="laydate-demo-2" placeholder="yyyy-MM-dd">
+                            </div>
+                        </div>
+                        
+                        <div class="form-group">
+                            <label class="font-noraml">显示年月日时分秒</label>
+                            <div class="input-group date">
+                                <span class="input-group-addon"><i class="fa fa-calendar"></i></span>
+                                <input type="text" class="form-control" id="laydate-demo-3" placeholder="yyyy-MM-dd HH:mm:ss">
+                            </div>
+                        </div>
+                        
+                        <div class="form-group">
+                            <label class="font-noraml">单框范围选择</label>
+                            <div class="input-group date">
+                                <span class="input-group-addon"><i class="fa fa-calendar"></i></span>
+                                <input type="text" class="form-control" id="laydate-demo-4" placeholder="yyyy-MM-dd - yyyy-MM-dd">
+                            </div>
+                        </div>
+                        
+                        <div class="form-group">
+                            <label class="font-noraml">日期范围选择</label>
+                            <div class="input-daterange input-group">
+                                <input type="text" class="input-sm form-control" id="laydate-startTime" placeholder="yyyy-MM-dd"/>
+                                <span class="input-group-addon">到</span>
+                                <input type="text" class="input-sm form-control" id="laydate-endTime" placeholder="yyyy-MM-dd"/>
+                            </div>
+                        </div>
+                        <hr>
+                        <div class="form-group">
+                            <label class="font-noraml">相关参数详细信息</label>
+                            <div><a href="http://doc.ruoyi.vip/ruoyi/document/zjwd.html#laydate" target="_blank">http://doc.ruoyi.vip/ruoyi/document/zjwd.html#laydate</a></div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <th:block th:include="include :: footer" />
+    <th:block th:include="include :: datetimepicker-js" />
+    <script type="text/javascript">
+        $(function(){
+        	<!-- datetimepicker示例 -->
+        	$("#datetimepicker-demo-1").datetimepicker();
+        	
+        	$("#datetimepicker-demo-2").datetimepicker({
+       		    format: "yyyy-mm-dd",
+       		    minView: "month",
+       		    autoclose: true,
+       		    clearBtn:true
+       		});
+        	
+        	$("#datetimepicker-demo-3").datetimepicker({
+       		    format: "yyyy-mm-dd hh:ii:ss",
+       		    autoclose: true
+       		});
+        	
+        	$('.form_date').datetimepicker({
+        		format: "yyyy-mm-dd",
+       		    minView: "month",
+       		    autoclose: true
+            });
+        	
+        	$("#datetimepicker-startTime").datetimepicker({
+        		format: 'yyyy-mm-dd',
+        		minView: "month",
+        	    todayBtn:  true,
+        	    autoclose: true,
+        		endDate : new Date(),
+        	}).on('changeDate', function(event) {
+        		event.preventDefault();
+        		event.stopPropagation();
+        		var startTime = event.date;
+        		$('#datetimepicker-endTime').datetimepicker('setStartDate', startTime);
+        	});
+        	
+        	$("#datetimepicker-endTime").datetimepicker({
+        		format: 'yyyy-mm-dd',
+        		minView: "month",
+        		todayBtn:  true,
+        		autoclose: true,
+        		endDate : new Date(),
+        	}).on('changeDate', function(event) {
+        		event.preventDefault();
+        		event.stopPropagation();
+        		var endTime = event.date;
+        		$("#datetimepicker-startTime").datetimepicker('setEndDate', endTime);
+        	});
+        	
+        	<!-- laydate示例 -->
+        	layui.use('laydate', function(){
+       		  var laydate = layui.laydate;
+       		  
+       		  laydate.render({
+       		    elem: '#laydate-demo-1'
+       		  });
+       		  
+       		  laydate.render({ 
+       		    elem: '#laydate-demo-2',
+       		    type: 'date'
+       		  });
+       		  
+       		  laydate.render({ 
+       		    elem: '#laydate-demo-3',
+       		    type: 'datetime',
+       		    trigger: 'click'
+       		  });
+       		  
+       		  laydate.render({
+       		    elem: '#laydate-demo-4',
+       		    range: true
+       		  });
+       		  
+       		  var startDate = laydate.render({
+		        elem: '#laydate-startTime',
+		        max: $('#laydate-endTime').val(),
+		        theme: 'molv',
+		        trigger: 'click',
+		        done: function(value, date) {
+		            // 结束时间大于开始时间
+		            if (value !== '') {
+		                endDate.config.min.year = date.year;
+		                endDate.config.min.month = date.month - 1;
+		                endDate.config.min.date = date.date;
+		            } else {
+		                endDate.config.min.year = '';
+		                endDate.config.min.month = '';
+		                endDate.config.min.date = '';
+		            }
+		        }
+		      });
+       		
+		      var endDate = laydate.render({
+		        elem: '#laydate-endTime',
+		        min: $('#laydate-startTime').val(),
+		        theme: 'molv',
+		        trigger: 'click',
+		        done: function(value, date) {
+		            // 开始时间小于结束时间
+		            if (value !== '') {
+		                startDate.config.max.year = date.year;
+		                startDate.config.max.month = date.month - 1;
+		                startDate.config.max.date = date.date;
+		            } else {
+		                startDate.config.max.year = '';
+		                startDate.config.max.month = '';
+		                startDate.config.max.date = '';
+		            }
+		        }
+		      });
+       	   });
+        });
+    </script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/demo/form/duallistbox.html b/ruoyi-admin/src/main/resources/templates/demo/form/duallistbox.html
new file mode 100644
index 0000000..d9f7246
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/form/duallistbox.html
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<html lang="zh">
+<head>
+	<th:block th:include="include :: header('左右互选组件')" />
+	<th:block th:include="include :: bootstrap-duallistbox-css" />
+</head>
+<body class="gray-bg">
+	<div class="wrapper wrapper-content animated fadeInRight">
+        <div class="row">
+            <div class="col-lg-12">
+                <div class="ibox">
+                    <div class="ibox-title">
+                        <h5>双重列表框 <small>https://github.com/istvan-ujjmeszaros/bootstrap-duallistbox</small></h5>
+                    </div>  
+                    <div class="ibox-content">
+                        <p>
+                            Bootstrap Dual Listbox是针对Twitter Bootstrap进行了优化的响应式双列表框。它适用于所有现代浏览器和触摸设备。
+                        </p>
+
+                        <form id="form" action="#" class="wizard-big">
+                            <select class="form-control dual_select" multiple>
+                                <option value="1">若依1</option>
+                                <option value="2">若依2</option>
+                                <option value="3">若依3</option>
+                                <option selected value="4">若依4</option>
+                                <option selected value="5">若依5</option>
+                                <option value="6">若依6</option>
+                                <option value="7">若依7</option>
+                                <option value="8">若依8</option>
+                                <option value="9">若依9</option>
+                                <option value="10">若依10</option>
+                                <option value="11">若依11</option>
+                                <option value="12">若依12</option>
+                            </select>
+                        </form>
+                        <hr>
+                        <div class="form-group">
+                            <label class="font-noraml">相关参数详细信息</label>
+                            <div><a href="http://doc.ruoyi.vip/ruoyi/document/zjwd.html#bootstrap-duallistbox" target="_blank">http://doc.ruoyi.vip/ruoyi/document/zjwd.html#bootstrap-duallistbox</a></div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <th:block th:include="include :: footer" />
+    <th:block th:include="include :: bootstrap-duallistbox-js" />
+    <script type="text/javascript">
+	    $('.dual_select').bootstrapDualListbox({
+	    	nonSelectedListLabel: '未有用户',
+            selectedListLabel: '已有用户',
+            preserveSelectionOnMove: 'moved',
+            moveOnSelect: false,           // 出现一个剪头,表示可以一次选择一个
+            filterTextClear: '展示所有',
+            moveSelectedLabel: "添加",
+            moveAllLabel: '添加所有',
+            removeSelectedLabel: "移除",
+            removeAllLabel: '移除所有',
+            infoText: '共{0}个',
+            showFilterInputs: false,       // 是否带搜索
+	        selectorMinimalHeight: 160
+	    });
+    </script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/demo/form/grid.html b/ruoyi-admin/src/main/resources/templates/demo/form/grid.html
new file mode 100644
index 0000000..3dc6a09
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/form/grid.html
@@ -0,0 +1,432 @@
+<!DOCTYPE html>
+<html lang="zh">
+<head>
+	<th:block th:include="include :: header('栅格')" />
+</head>
+<body class="gray-bg">
+    <div class="wrapper wrapper-content">
+        <div class="row">
+            <div class="col-sm-12">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>栅格设置</h5>
+                        <div class="ibox-tools">
+                            <a class="collapse-link">
+                                <i class="fa fa-chevron-up"></i>
+                            </a>
+                            <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                                <i class="fa fa-wrench"></i>
+                            </a>
+                            <ul class="dropdown-menu dropdown-user">
+                                <li><a href="javascript:;">选项1</a>
+                                </li>
+                                <li><a href="javascript:;">选项2</a>
+                                </li>
+                            </ul>
+                            <a class="close-link">
+                                <i class="fa fa-times"></i>
+                            </a>
+                        </div>
+                    </div>
+                    <div class="ibox-content">
+
+                        <p>通过下表可以详细查看 Bootstrap 的栅格系统是如何在多种屏幕设备上工作的。</p>
+                        <div class="table-responsive">
+                            <table class="table table-bordered table-striped">
+                                <thead>
+                                    <tr>
+                                        <th></th>
+                                        <th>
+                                            超小屏幕
+                                            <small>手机 (&lt;768px)</small>
+                                        </th>
+                                        <th>
+                                            小屏幕
+                                            <small>平板 (≥768px)</small>
+                                        </th>
+                                        <th>
+                                            中等屏幕
+                                            <small>桌面显示器 (≥992px)</small>
+                                        </th>
+                                        <th>
+                                            大屏幕
+                                            <small>大桌面显示器 (≥1200px)</small>
+                                        </th>
+                                    </tr>
+                                </thead>
+                                <tbody>
+                                    <tr>
+                                        <th class="text-nowrap">栅格系统行为</th>
+                                        <td>总是水平排列</td>
+                                        <td colspan="3">开始是堆叠在一起的,当大于这些阈值时将变为水平排列C</td>
+                                    </tr>
+                                    <tr>
+                                        <th class="text-nowrap"><code>.container</code> 最大宽度</th>
+                                        <td>None (自动)</td>
+                                        <td>750px</td>
+                                        <td>970px</td>
+                                        <td>1170px</td>
+                                    </tr>
+                                    <tr>
+                                        <th class="text-nowrap">类前缀</th>
+                                        <td><code>.col-xs-</code>
+                                        </td>
+                                        <td><code>.col-sm-</code>
+                                        </td>
+                                        <td><code>.col-md-</code>
+                                        </td>
+                                        <td><code>.col-lg-</code>
+                                        </td>
+                                    </tr>
+                                    <tr>
+                                        <th class="text-nowrap">列(column)数</th>
+                                        <td colspan="4">12</td>
+                                    </tr>
+                                    <tr>
+                                        <th class="text-nowrap">最大列(column)宽</th>
+                                        <td class="text-muted">自动</td>
+                                        <td>~62px</td>
+                                        <td>~81px</td>
+                                        <td>~97px</td>
+                                    </tr>
+                                    <tr>
+                                        <th class="text-nowrap">槽(gutter)宽</th>
+                                        <td colspan="4">30px (每列左右均有 15px)</td>
+                                    </tr>
+                                    <tr>
+                                        <th class="text-nowrap">可嵌套</th>
+                                        <td colspan="4">是</td>
+                                    </tr>
+                                    <tr>
+                                        <th class="text-nowrap">偏移(Offsets)</th>
+                                        <td colspan="4">是</td>
+                                    </tr>
+                                    <tr>
+                                        <th class="text-nowrap">列排序</th>
+                                        <td colspan="4">是</td>
+                                    </tr>
+                                </tbody>
+                            </table>
+                        </div>
+
+
+                    </div>
+                </div>
+            </div>
+
+        </div>
+        <div class="row">
+            <div class="col-sm-12">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>从堆叠到水平排列</h5>
+                        <div class="ibox-tools">
+                            <a class="collapse-link">
+                                <i class="fa fa-chevron-up"></i>
+                            </a>
+                            <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                                <i class="fa fa-wrench"></i>
+                            </a>
+                            <ul class="dropdown-menu dropdown-user">
+                                <li><a href="javascript:;">选项1</a>
+                                </li>
+                                <li><a href="javascript:;">选项2</a>
+                                </li>
+                            </ul>
+                            <a class="close-link">
+                                <i class="fa fa-times"></i>
+                            </a>
+                        </div>
+                    </div>
+                    <div class="ibox-content">
+
+                        <p>使用单一的一组 <code>.col-md-*</code> 栅格类,就可以创建一个基本的栅格系统,在手机和平板设备上一开始是堆叠在一起的(超小屏幕到小屏幕这一范围),在桌面(中等)屏幕设备上变为水平排列。所有“列(column)必须放在 ” <code>.row</code> 内。</p>
+                        <div class="row show-grid">
+                            <div class="col-md-1">.col-md-1</div>
+                            <div class="col-md-1">.col-md-1</div>
+                            <div class="col-md-1">.col-md-1</div>
+                            <div class="col-md-1">.col-md-1</div>
+                            <div class="col-md-1">.col-md-1</div>
+                            <div class="col-md-1">.col-md-1</div>
+                            <div class="col-md-1">.col-md-1</div>
+                            <div class="col-md-1">.col-md-1</div>
+                            <div class="col-md-1">.col-md-1</div>
+                            <div class="col-md-1">.col-md-1</div>
+                            <div class="col-md-1">.col-md-1</div>
+                            <div class="col-md-1">.col-md-1</div>
+                        </div>
+                        <div class="row show-grid">
+                            <div class="col-md-8">.col-md-8</div>
+                            <div class="col-md-4">.col-md-4</div>
+                        </div>
+                        <div class="row show-grid">
+                            <div class="col-md-4">.col-md-4</div>
+                            <div class="col-md-4">.col-md-4</div>
+                            <div class="col-md-4">.col-md-4</div>
+                        </div>
+                        <div class="row show-grid">
+                            <div class="col-md-6">.col-md-6</div>
+                            <div class="col-md-6">.col-md-6</div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+
+        </div>
+
+        <div class="row">
+            <div class="col-sm-12">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>移动设备和桌面屏幕</h5>
+                        <div class="ibox-tools">
+                            <a class="collapse-link">
+                                <i class="fa fa-chevron-up"></i>
+                            </a>
+                            <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                                <i class="fa fa-wrench"></i>
+                            </a>
+                            <ul class="dropdown-menu dropdown-user">
+                                <li><a href="javascript:;">选项1</a>
+                                </li>
+                                <li><a href="javascript:;">选项2</a>
+                                </li>
+                            </ul>
+                            <a class="close-link">
+                                <i class="fa fa-times"></i>
+                            </a>
+                        </div>
+                    </div>
+                    <div class="ibox-content">
+
+                        <p>是否不希望在小屏幕设备上所有列都堆叠在一起?那就使用针对超小屏幕和中等屏幕设备所定义的类吧,即 <code>.col-xs-*</code> 和 <code>.col-md-*</code>。请看下面的实例,研究一下这些是如何工作的。</p>
+                        <div class="row show-grid">
+                            <div class="col-xs-12 col-md-8">.col-xs-12 .col-md-8</div>
+                            <div class="col-xs-6 col-md-4">.col-xs-6 .col-md-4</div>
+                        </div>
+                        <div class="row show-grid">
+                            <div class="col-xs-6 col-md-4">.col-xs-6 .col-md-4</div>
+                            <div class="col-xs-6 col-md-4">.col-xs-6 .col-md-4</div>
+                            <div class="col-xs-6 col-md-4">.col-xs-6 .col-md-4</div>
+                        </div>
+                        <div class="row show-grid">
+                            <div class="col-xs-6">.col-xs-6</div>
+                            <div class="col-xs-6">.col-xs-6</div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+
+        </div>
+        <div class="row">
+            <div class="col-sm-12">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>手机、平板、桌面</h5>
+                        <div class="ibox-tools">
+                            <a class="collapse-link">
+                                <i class="fa fa-chevron-up"></i>
+                            </a>
+                            <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                                <i class="fa fa-wrench"></i>
+                            </a>
+                            <ul class="dropdown-menu dropdown-user">
+                                <li><a href="javascript:;">选项1</a>
+                                </li>
+                                <li><a href="javascript:;">选项2</a>
+                                </li>
+                            </ul>
+                            <a class="close-link">
+                                <i class="fa fa-times"></i>
+                            </a>
+                        </div>
+                    </div>
+                    <div class="ibox-content">
+
+                        <p>在上面案例的基础上,通过使用针对平板设备的 <code>.col-sm-*</code> 类,我们来创建更加动态和强大的布局吧。</p>
+                        <div class="row show-grid">
+                            <div class="col-xs-12 col-sm-6 col-md-8">.col-xs-12 .col-sm-6 .col-md-8</div>
+                            <div class="col-xs-6 col-md-4">.col-xs-6 .col-md-4</div>
+                        </div>
+                        <div class="row show-grid">
+                            <div class="col-xs-6 col-sm-4">.col-xs-6 .col-sm-4</div>
+                            <div class="col-xs-6 col-sm-4">.col-xs-6 .col-sm-4</div>
+                            <!-- Optional: clear the XS cols if their content doesn't match in height -->
+                            <div class="clearfix visible-xs"></div>
+                            <div class="col-xs-6 col-sm-4">.col-xs-6 .col-sm-4</div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+
+        </div>
+        <div class="row">
+            <div class="col-sm-12">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>多余的列(column)将另起一行排列</h5>
+
+                        <div class="ibox-tools">
+                            <a class="collapse-link">
+                                <i class="fa fa-chevron-up"></i>
+                            </a>
+                            <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                                <i class="fa fa-wrench"></i>
+                            </a>
+                            <ul class="dropdown-menu dropdown-user">
+                                <li><a href="javascript:;">选项1</a>
+                                </li>
+                                <li><a href="javascript:;">选项2</a>
+                                </li>
+                            </ul>
+                            <a class="close-link">
+                                <i class="fa fa-times"></i>
+                            </a>
+                        </div>
+                    </div>
+                    <div class="ibox-content">
+                        <p>在等宽的4网格中,网格不等高会碰到问题,为了解决这个问题,可使用<code>.clearfix</code>。<a href="#responsive-utilities">响应实用工具类</a>
+                        </p>
+                        <div class="row show-grid">
+                            <div class="col-xs-6 col-sm-3">
+                                .col-xs-6 .col-sm-3
+                                <br>调整窗口大小或者在手机上查看本示例
+                            </div>
+                            <div class="col-xs-6 col-sm-3">.col-xs-6 .col-sm-3</div>
+
+                            <!-- Add the extra clearfix for only the required viewport -->
+                            <div class="clearfix visible-xs"></div>
+
+                            <div class="col-xs-6 col-sm-3">.col-xs-6 .col-sm-3</div>
+                            <div class="col-xs-6 col-sm-3">.col-xs-6 .col-sm-3</div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+
+        </div>
+        <div class="row">
+            <div class="col-sm-12">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>列偏移</h5>
+
+                        <div class="ibox-tools">
+                            <a class="collapse-link">
+                                <i class="fa fa-chevron-up"></i>
+                            </a>
+                            <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                                <i class="fa fa-wrench"></i>
+                            </a>
+                            <ul class="dropdown-menu dropdown-user">
+                                <li><a href="javascript:;">选项1</a>
+                                </li>
+                                <li><a href="javascript:;">选项2</a>
+                                </li>
+                            </ul>
+                            <a class="close-link">
+                                <i class="fa fa-times"></i>
+                            </a>
+                        </div>
+                    </div>
+                    <div class="ibox-content">
+
+                        <p>使用 <code>.col-md-offset-*</code> 类可以将列向右侧偏移。这些类实际是通过使用 <code>*</code> 选择器为当前元素增加了左侧的边距(margin)。例如,<code>.col-md-offset-4</code> 类将 <code>.col-md-4</code> 元素向右侧偏移了4个列(column)的宽度。</p>
+                        <div class="row show-grid">
+                            <div class="col-md-4">.col-md-4</div>
+                            <div class="col-md-4 col-md-offset-4">.col-md-4 .col-md-offset-4</div>
+                        </div>
+                        <div class="row show-grid">
+                            <div class="col-md-3 col-md-offset-3">.col-md-3 .col-md-offset-3</div>
+                            <div class="col-md-3 col-md-offset-3">.col-md-3 .col-md-offset-3</div>
+                        </div>
+                        <div class="row show-grid">
+                            <div class="col-md-6 col-md-offset-3">.col-md-6 .col-md-offset-3</div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+
+        </div>
+        <div class="row">
+            <div class="col-sm-12">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>嵌套列</h5>
+
+                        <div class="ibox-tools">
+                            <a class="collapse-link">
+                                <i class="fa fa-chevron-up"></i>
+                            </a>
+                            <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                                <i class="fa fa-wrench"></i>
+                            </a>
+                            <ul class="dropdown-menu dropdown-user">
+                                <li><a href="javascript:;">选项1</a>
+                                </li>
+                                <li><a href="javascript:;">选项2</a>
+                                </li>
+                            </ul>
+                            <a class="close-link">
+                                <i class="fa fa-times"></i>
+                            </a>
+                        </div>
+                    </div>
+                    <div class="ibox-content">
+                        <p>为了使用内置的栅格系统将内容再次嵌套,可以通过添加一个新的 <code>.row</code> 元素和一系列 <code>.col-sm-*</code> 元素到已经存在的 <code>.col-sm-*</code> 元素内。被嵌套的行(row)所包含的列(column)的个数不能超过12(其实,没有要求你必须占满12列)。</p>
+                        <div class="row show-grid">
+                            <div class="col-md-9">
+                                第一级: .col-md-9
+                                <div class="row show-grid">
+                                    <div class="col-md-6">
+                                        第二级: .col-md-6
+                                    </div>
+                                    <div class="col-md-6">
+                                        第二级: .col-md-6
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+
+        </div>
+        <div class="row">
+            <div class="col-sm-12">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>列排序</h5>
+                        <div class="ibox-tools">
+                            <a class="collapse-link">
+                                <i class="fa fa-chevron-up"></i>
+                            </a>
+                            <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                                <i class="fa fa-wrench"></i>
+                            </a>
+                            <ul class="dropdown-menu dropdown-user">
+                                <li><a href="javascript:;">选项1</a>
+                                </li>
+                                <li><a href="javascript:;">选项2</a>
+                                </li>
+                            </ul>
+                            <a class="close-link">
+                                <i class="fa fa-times"></i>
+                            </a>
+                        </div>
+                    </div>
+                    <div class="ibox-content">
+                        <p>通过使用 <code>.col-md-push-*</code> 和 <code>.col-md-pull-*</code> 类就可以很容易的改变列(column)的顺序。</p>
+                        <div class="row show-grid">
+                            <div class="col-md-9 col-md-push-3">.col-md-9 .col-md-push-3</div>
+                            <div class="col-md-3 col-md-pull-9">.col-md-3 .col-md-pull-9</div>
+                        </div>
+                    </div>
+                </div>
+
+            </div>
+        </div>
+    </div>
+    <th:block th:include="include :: footer" />
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/demo/form/invoice.html b/ruoyi-admin/src/main/resources/templates/demo/form/invoice.html
new file mode 100644
index 0000000..42b4e80
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/form/invoice.html
@@ -0,0 +1,122 @@
+<!DOCTYPE html>
+<html lang="zh">
+<head>
+	<th:block th:include="include :: header('单据打印')" />
+</head>
+<body class="gray-bg">
+    <div class="wrapper wrapper-content animated fadeInRight">
+
+        <div class="row">
+            <div class="col-sm-12">
+                <div class="ibox-content p-xl">
+                    <div class="row">
+                        <div class="col-sm-6">
+                            <address>
+                                        <strong>北京百度在线网络技术有限公司</strong><br>
+                                        北京市海淀区上地十街10号<br>
+                                        <abbr title="Phone">总机:</abbr> (+86 10) 5992 8888
+                                    </address>
+                        </div>
+
+                        <div class="col-sm-6 text-right">
+                            <h4>单据编号:</h4>
+                            <h4 class="text-navy">H+-000567F7-00</h4>
+                            <address>
+                                        <strong>阿里巴巴集团</strong><br>
+                                        中国杭州市华星路99号东部软件园创业大厦6层(310099)<br>
+                                        <abbr title="Phone">总机:</abbr> (86) 571-8502-2088
+                                    </address>
+                            <p>
+                                <span><strong>日期:</strong> 2014-11-11</span>
+                            </p>
+                        </div>
+                    </div>
+
+                    <div class="table-responsive m-t">
+                        <table class="table invoice-table">
+                            <thead>
+                                <tr>
+                                    <th>清单</th>
+                                    <th>数量</th>
+                                    <th>单价</th>
+                                    <th>税率</th>
+                                    <th>总价</th>
+                                </tr>
+                            </thead>
+                            <tbody>
+                                <tr>
+                                    <td>
+                                        <div><strong>尚都比拉2013冬装新款女装 韩版修身呢子大衣 秋冬气质羊毛呢外套</strong>
+                                        </div>
+                                    </td>
+                                    <td>1</td>
+                                    <td>&yen;26.00</td>
+                                    <td>&yen;1.20</td>
+                                    <td>&yen;31,98</td>
+                                </tr>
+                                <tr>
+                                    <td>
+                                        <div><strong>11*11夏娜 新款斗篷毛呢外套 女秋冬呢子大衣 韩版大码宽松呢大衣</strong>
+                                        </div>
+                                        <small>双十一特价
+                                            </small>
+                                    </td>
+                                    <td>2</td>
+                                    <td>&yen;80.00</td>
+                                    <td>&yen;1.20</td>
+                                    <td>&yen;196.80</td>
+                                </tr>
+                                <tr>
+                                    <td>
+                                        <div><strong>2013秋装 新款女装韩版学生秋冬加厚加绒保暖开衫卫衣 百搭女外套</strong>
+                                        </div>
+                                    </td>
+                                    <td>3</td>
+                                    <td>&yen;420.00</td>
+                                    <td>&yen;1.20</td>
+                                    <td>&yen;1033.20</td>
+                                </tr>
+
+                            </tbody>
+                        </table>
+                    </div>
+                    <!-- /table-responsive -->
+
+                    <table class="table invoice-total">
+                        <tbody>
+                            <tr>
+                                <td><strong>总价:</strong>
+                                </td>
+                                <td>&yen;1026.00</td>
+                            </tr>
+                            <tr>
+                                <td><strong>税:</strong>
+                                </td>
+                                <td>&yen;235.98</td>
+                            </tr>
+                            <tr>
+                                <td><strong>总计</strong>
+                                </td>
+                                <td>&yen;1261.98</td>
+                            </tr>
+                        </tbody>
+                    </table>
+                    <!-- 打印网页时通过hidden-print隐藏元素 -->
+                    <div class="text-right hidden-print">
+                        <button class="btn btn-primary" onclick="printPage()"><i class="fa fa-print"></i> 打印</button>
+                    </div>
+
+                    <div class="well m-t"><strong>注意:</strong> 请在30日内完成付款,否则订单会自动取消。
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <th:block th:include="include :: footer" />
+    <script type="text/javascript">
+        function printPage() {
+            window.print();
+        }
+    </script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/demo/form/jasny.html b/ruoyi-admin/src/main/resources/templates/demo/form/jasny.html
new file mode 100644
index 0000000..07d7fae
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/form/jasny.html
@@ -0,0 +1,118 @@
+<!DOCTYPE html>
+<html lang="zh">
+<head>
+	<th:block th:include="include :: header('功能扩展')" />
+	<th:block th:include="include :: jasny-bootstrap-css" />
+</head>
+<body class="gray-bg">
+<div class="wrapper wrapper-content animated fadeInRight">
+        <div class="row">
+            <div class="col-sm-6">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>文件上传控件 <small>https://github.com/jasny/bootstrap</small></h5>
+                    </div>
+                    <div class="ibox-content">
+                    	<div class="form-group">
+                            <label class="font-noraml">输入组示例</label>
+                            
+	                        <div class="fileinput fileinput-new input-group" data-provides="fileinput">
+	                            <div class="form-control" data-trigger="fileinput"><i class="glyphicon glyphicon-file fileinput-exists"></i> <span class="fileinput-filename"></span></div>
+	                            <span class="input-group-addon btn btn-white btn-file"><span class="fileinput-new">选择文件</span><span class="fileinput-exists">更改</span><input type="file"></span>
+	                            <a href="javascript:;" class="input-group-addon btn btn-white fileinput-exists" data-dismiss="fileinput">清除</a>
+	                        </div>
+                        </div>
+                        
+                        <div class="form-group">
+                            <label class="font-noraml">按钮示例</label>
+                            <br/>
+	                        <div class="fileinput fileinput-new" data-provides="fileinput">
+	                            <span class="btn btn-white btn-file"><span class="fileinput-new">选择文件</span><span class="fileinput-exists">更改</span><input type="file" name="..."></span>
+	                            <span class="fileinput-filename"></span>
+	                            <a href="javascript:;" class="close fileinput-exists" data-dismiss="fileinput" style="float: none">&times;</a>
+	                        </div>
+                        </div>
+                        
+                        <div class="form-group">
+                            <label class="font-noraml">图片上传示例</label>
+                            <br/>
+	                        <div class="fileinput fileinput-new" data-provides="fileinput">
+					            <div class="fileinput-preview thumbnail" data-trigger="fileinput" style="width: 200px; height: 150px;"></div>
+					            <div>
+					                <span class="btn btn-white btn-file"><span class="fileinput-new">选择图片</span><span class="fileinput-exists">更改</span><input type="file"></span>
+					                <a href="javascript:;" class="btn btn-white fileinput-exists" data-dismiss="fileinput">清除</a>
+					            </div>
+					        </div>
+                        </div>
+                        
+                        <div class="form-group">
+                            <label class="font-noraml">图片预览示例</label>
+                            <br/>
+	                        <div class="fileinput fileinput-new" data-provides="fileinput">
+						        <div class="fileinput-new thumbnail" style="width: 140px; height: 140px;">
+						          <img th:src="@{/img/profile.jpg}">
+						        </div>
+						        <div class="fileinput-preview fileinput-exists thumbnail" style="max-width: 200px; max-height: 150px;"></div>
+						        <div>
+						          <span class="btn btn-white btn-file"><span class="fileinput-new">选择图片</span><span class="fileinput-exists">更改</span><input type="file"></span>
+						          <a href="javascript:;" class="btn btn-white fileinput-exists" data-dismiss="fileinput">清除</a>
+						        </div>
+						      </div>
+                        </div>
+                        <hr>
+                        <div class="form-group">
+                            <label class="font-noraml">相关参数详细信息</label>
+                            <div><a href="http://doc.ruoyi.vip/ruoyi/document/zjwd.html#jasny-bootstrap" target="_blank">http://doc.ruoyi.vip/ruoyi/document/zjwd.html#jasny-bootstrap</a></div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-6">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>固定格式文本 <small>https://github.com/jasny/bootstrap</small></h5>
+                    </div>
+                    <div class="ibox-content">
+                        <div class="form-group">
+                            <label class="font-noraml">手机号码格式</label>
+                             <input type="text" class="form-control" data-mask="999-9999-9999" placeholder="请输入手机号码">
+                             <span class="help-block">158-8888-88888</span>
+                       	 </div>
+                        
+                        <div class="form-group">
+                            <label class="font-noraml">电话号码格式</label>
+                            <input type="text" class="form-control" data-mask="9999-9999999" placeholder="请输入电话号码">
+                            <span class="help-block">0730-8888888</span>
+                        </div>
+                        
+                        <div class="form-group">
+                            <label class="font-noraml">日期格式</label>
+                            <input type="text" class="form-control" data-mask="9999-99-99" placeholder="请输入日期格式">
+                            <span class="help-block">yyyy-mm-dd</span>
+                        </div>
+                        
+                        <div class="form-group">
+                            <label class="font-noraml">IPV4格式</label>
+                            <input type="text" class="form-control" data-mask="999.999.999.999" placeholder="请输入IP地址">
+                            <span class="help-block">192.168.100.200</span>
+                        </div>
+                        
+                        <div class="form-group">
+                            <label class="font-noraml">税务代码格式</label>
+                            <input type="text" class="form-control" data-mask="99-9999999" placeholder="请输入税务代码">
+                            <span class="help-block">99-9999999</span>
+                        </div>
+                        <hr>
+                        <div class="form-group">
+                            <label class="font-noraml">相关参数详细信息</label>
+                            <div><a href="http://doc.ruoyi.vip/ruoyi/document/zjwd.html#jasny-bootstrap" target="_blank">http://doc.ruoyi.vip/ruoyi/document/zjwd.html#jasny-bootstrap</a></div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <th:block th:include="include :: footer" />
+    <th:block th:include="include :: jasny-bootstrap-js" />
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/demo/form/labels_tips.html b/ruoyi-admin/src/main/resources/templates/demo/form/labels_tips.html
new file mode 100644
index 0000000..220ce7d
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/form/labels_tips.html
@@ -0,0 +1,237 @@
+<!DOCTYPE html>
+<html lang="zh">
+<head>
+	<th:block th:include="include :: header('标签 & 提示')" />
+</head>
+<body class="gray-bg">
+    <div class="wrapper wrapper-content animated fadeIn">
+        <div class="row">
+            <div class="col-sm-6">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>徽章 (Badges)</h5>
+                        <div class="ibox-tools">
+                            <a class="collapse-link">
+                                <i class="fa fa-chevron-up"></i>
+                            </a>
+                            <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                                <i class="fa fa-wrench"></i>
+                            </a>
+                            <ul class="dropdown-menu dropdown-user">
+                                <li><a href="javascript:;">选项1</a>
+                                </li>
+                                <li><a href="javascript:;">选项2</a>
+                                </li>
+                            </ul>
+                            <a class="close-link">
+                                <i class="fa fa-times"></i>
+                            </a>
+                        </div>
+                    </div>
+                    <div class="ibox-content">
+                        <p>
+                            要添加徽章,只需要在元素上添加<code>.badge</code>即可,改变徽章的颜色可使用如下class,如<code>.badge-primary</code>。
+                        </p>
+                        <p><span class="badge">空</span>
+                        </p>
+                        <p><span class="badge badge-primary">badge-primary</span>
+                        </p>
+                        <p><span class="badge badge-info">badge-info</span>
+                        </p>
+                        <p><span class="badge badge-success">badge-success</span>
+                        </p>
+                        <p><span class="badge badge-warning">badge-warning</span>
+                        </p>
+                        <p><span class="badge badge-danger">badge-danger</span>
+                        </p>
+                    </div>
+                </div>
+            </div>
+
+            <div class="col-sm-6">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>标签 (Labels)</h5>
+                        <div class="ibox-tools">
+                            <a class="collapse-link">
+                                <i class="fa fa-chevron-up"></i>
+                            </a>
+                            <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                                <i class="fa fa-wrench"></i>
+                            </a>
+                            <ul class="dropdown-menu dropdown-user">
+                                <li><a href="javascript:;">选项1</a>
+                                </li>
+                                <li><a href="javascript:;">选项2</a>
+                                </li>
+                            </ul>
+                            <a class="close-link">
+                                <i class="fa fa-times"></i>
+                            </a>
+                        </div>
+                    </div>
+                    <div class="ibox-content">
+                        <p>
+                            要添加徽章,只需要在元素上添加class<code>.label</code>即可,如果需要修改颜色,添加如下class,如<code>.label-primary</code>
+                        </p>
+                        <p><span class="label">空</span>
+                        </p>
+                        <p><span class="label label-primary">label-primary</span>
+                        </p>
+                        <p><span class="label label-info">label-info</span>
+                        </p>
+                        <p><span class="label label-success">label-success</span>
+                        </p>
+                        <p><span class="label label-warning">label-warning</span>
+                        </p>
+                        <p><span class="label label-danger">label-danger</span>
+                        </p>
+                    </div>
+                </div>
+            </div>
+        </div>
+        
+        <div class="row">
+            <div class="col-sm-6">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>通知样式</h5>
+                        <div class="ibox-tools">
+                            <a class="collapse-link">
+                                <i class="fa fa-chevron-up"></i>
+                            </a>
+                            <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                                <i class="fa fa-wrench"></i>
+                            </a>
+                            <ul class="dropdown-menu dropdown-user">
+                                <li><a href="javascript:;">选项1</a>
+                                </li>
+                                <li><a href="javascript:;">选项2</a>
+                                </li>
+                            </ul>
+                            <a class="close-link">
+                                <i class="fa fa-times"></i>
+                            </a>
+                        </div>
+                    </div>
+                    <div class="ibox-content">
+                        <div class="alert alert-success">
+                            RuoYi是一个很棒的后台UI框架 <a class="alert-link" href="javascript:;">了解更多</a>.
+                        </div>
+                        <div class="alert alert-info">
+                            RuoYi是一个很棒的后台UI框架 <a class="alert-link" href="javascript:;">了解更多</a>.
+                        </div>
+                        <div class="alert alert-warning">
+                            RuoYi是一个很棒的后台UI框架 <a class="alert-link" href="javascript:;">了解更多</a>.
+                        </div>
+                        <div class="alert alert-danger">
+                            RuoYi是一个很棒的后台UI框架 <a class="alert-link" href="javascript:;">了解更多</a>.
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-6">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>带关闭按钮的通知样式</h5>
+                        <div class="ibox-tools">
+                            <a class="collapse-link">
+                                <i class="fa fa-chevron-up"></i>
+                            </a>
+                            <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                                <i class="fa fa-wrench"></i>
+                            </a>
+                            <ul class="dropdown-menu dropdown-user">
+                                <li><a href="javascript:;">选项1</a>
+                                </li>
+                                <li><a href="javascript:;">选项2</a>
+                                </li>
+                            </ul>
+                            <a class="close-link">
+                                <i class="fa fa-times"></i>
+                            </a>
+                        </div>
+                    </div>
+                    <div class="ibox-content">
+                        <div class="alert alert-success alert-dismissable">
+                            <button aria-hidden="true" data-dismiss="alert" class="close" type="button">×</button>
+                            RuoYi是一个很棒的后台UI框架 <a class="alert-link" href="javascript:;">了解更多</a>.
+                        </div>
+                        <div class="alert alert-info alert-dismissable">
+                            <button aria-hidden="true" data-dismiss="alert" class="close" type="button">×</button>
+                            RuoYi是一个很棒的后台UI框架 <a class="alert-link" href="javascript:;">了解更多</a>.
+                        </div>
+                        <div class="alert alert-warning alert-dismissable">
+                            <button aria-hidden="true" data-dismiss="alert" class="close" type="button">×</button>
+                            RuoYi是一个很棒的后台UI框架 <a class="alert-link" href="javascript:;">了解更多</a>.
+                        </div>
+                        <div class="alert alert-danger alert-dismissable">
+                            <button aria-hidden="true" data-dismiss="alert" class="close" type="button">×</button>
+                            RuoYi是一个很棒的后台UI框架 <a class="alert-link" href="javascript:;">了解更多</a>.
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+        
+        <div class="row">
+            <div class="col-sm-12">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>工具提示</h5>
+                        <div class="ibox-tools">
+                            <a class="collapse-link">
+                                <i class="fa fa-chevron-up"></i>
+                            </a>
+                            <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                                <i class="fa fa-wrench"></i>
+                            </a>
+                            <ul class="dropdown-menu dropdown-user">
+                                <li><a href="javascript:;">选项1</a>
+                                </li>
+                                <li><a href="javascript:;">选项2</a>
+                                </li>
+                            </ul>
+                            <a class="close-link">
+                                <i class="fa fa-times"></i>
+                            </a>
+                        </div>
+                    </div>
+                    <div class="text-center">
+                        <h4>工具提示示例 <small>深色背景</small></h4>
+                        <div>
+                            <button type="button" class="btn btn-default" data-toggle="tooltip" data-placement="left" title="这里是提示内容">左侧提示</button>
+                            <button type="button" class="btn btn-default" data-toggle="tooltip" data-placement="top" title="这里是提示内容">顶部提示</button>
+                            <button type="button" class="btn btn-default" data-toggle="tooltip" data-placement="bottom" title="这里是提示内容">底部提示</button>
+                            <button type="button" class="btn btn-default" data-toggle="tooltip" data-placement="right" title="这里是提示内容">右侧提示</button>
+                        </div>
+                        <br>
+                        <h4>工具提示 - 单击提示</h4>
+                        <div class="text-center" >
+                            <button type="button" class="btn btn-primary"  data-toggle="popover" data-placement="auto left" data-content="气泡提示">
+                                气泡提示左
+                            </button>
+                            <button type="button" class="btn btn-primary"  data-toggle="popover" data-placement="auto top" data-content="气泡提示">
+                                气泡提示顶部
+                            </button>
+                            <button type="button" class="btn btn-primary"  data-toggle="popover" data-placement="auto bottom" data-content="气泡提示">
+                                气泡提示底部
+                            </button>
+                            <button type="button" class="btn btn-primary" data-toggle="popover" data-placement="auto right" data-content="气泡提示">
+                                气泡提示右
+                            </button>
+                        </div>
+                    </div>
+                </div>
+            </div>
+
+        </div>
+        
+    </div>
+    <th:block th:include="include :: footer" />
+    <script type="text/javascript">
+	    $("[data-toggle='tooltip']").tooltip();
+	    $("[data-toggle=popover]").popover();
+    </script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/demo/form/localrefresh.html b/ruoyi-admin/src/main/resources/templates/demo/form/localrefresh.html
new file mode 100644
index 0000000..ed70a84
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/form/localrefresh.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html lang="zh">
+<head>
+<th:block th:include="include :: header('局部刷新')" />
+</head>
+<body class="gray-bg">
+	<div class="wrapper wrapper-content animated fadeInRight">
+		<div class="row">
+			<div class="col-sm-4">
+				<div class="ibox">
+					<div class="ibox-content">
+						<h3>任务列表</h3>
+						<p class="small">
+							<i class="fa fa-hand-o-up"></i>
+							点击刷新按钮刷新数据到列表中
+						</p>
+
+						<div class="input-group">
+							<input id="task-name" type="text" placeholder="任务名称" class="input input-sm form-control">
+							<span class="input-group-btn">
+								<button type="button" class="btn btn-sm btn-white" onclick="refresh()">
+									<i class="fa fa-refresh"></i>
+									刷新
+								</button>
+							</span>
+						</div>
+						<div id="tasklist">
+							<ul class="sortable-list connectList agile-list" th:fragment="fragment-tasklist">
+								<li th:if="${tasks != null}" th:each="item : ${tasks}" class="warning-element">
+									[[${item.name}]]
+									<div class="agile-detail">
+										<a href="javascript:;" class="pull-right btn btn-xs btn-white">[[${item.type}]]</a>
+										<i class="fa fa-clock-o"></i>
+										[[${item.date}]]
+									</div>
+								</li>
+							</ul>
+						</div>
+					</div>
+				</div>
+			</div>
+		</div>
+	</div>
+	<th:block th:include="include :: footer" />
+	<script>
+		function refresh(){
+			$.ajax({
+				type: "post",
+				url: ctx + "demo/form/localrefresh/task",
+				data: {
+					"taskName": $("#task-name").val(),
+					"fragment":'fragment-tasklist'
+				},
+				success: function(data) {
+					$("#tasklist").html(data);
+				}
+			});
+		}
+	</script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/demo/form/progress_bars.html b/ruoyi-admin/src/main/resources/templates/demo/form/progress_bars.html
new file mode 100644
index 0000000..78f3b4e
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/form/progress_bars.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<html lang="zh">
+<head>
+	<th:block th:include="include :: header('进度条')" />
+</head>
+<body class="gray-bg">
+    <div class="wrapper wrapper-content animated fadeInRight">
+        <div class="row">
+            <div class="col-sm-12">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>进度条 (Progress Bars)</h5>
+                        <div class="ibox-tools">
+                            <a class="collapse-link">
+                                <i class="fa fa-chevron-up"></i>
+                            </a>
+                            <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                                <i class="fa fa-wrench"></i>
+                            </a>
+                            <ul class="dropdown-menu dropdown-user">
+                                <li><a href="javascript:;">选项1</a>
+                                </li>
+                                <li><a href="javascript:;">选项2</a>
+                                </li>
+                            </ul>
+                            <a class="close-link">
+                                <i class="fa fa-times"></i>
+                            </a>
+                        </div>
+                    </div>
+                    <div class="ibox-content">
+                        <!-- style: progress-bar-success/progress-bar-info/progress-bar-warning/progress-bar-danger -->
+                        <h5>基本</h5>
+                        <div class="progress">
+                            <div style="width: 35%" aria-valuemax="100" aria-valuemin="0" aria-valuenow="35" role="progressbar" class="progress-bar progress-bar-success">
+                                <span class="sr-only">35% Complete (success)</span>
+                            </div>
+                        </div>
+
+                        <div class="progress progress-bar-default">
+                            <div style="width: 43%" aria-valuemax="100" aria-valuemin="0" aria-valuenow="43" role="progressbar" class="progress-bar">
+                                <span class="sr-only">43% Complete (success)</span>
+                            </div>
+                        </div>
+
+                        <h5>条纹效果</h5>
+                        <div class="progress progress-striped">
+                            <div style="width: 50%" aria-valuemax="100" aria-valuemin="0" aria-valuenow="50" role="progressbar" class="progress-bar progress-bar-warning">
+                                <span class="sr-only">50% Complete (success)</span>
+                            </div>
+                        </div>
+
+                        <h5>动画效果</h5>
+                        <div class="progress progress-striped active">
+                            <div style="width: 75%" aria-valuemax="100" aria-valuemin="0" aria-valuenow="75" role="progressbar" class="progress-bar progress-bar-danger">
+                                <span class="sr-only">75% Complete (success)</span>
+                            </div>
+                        </div>
+
+                        <h5>堆叠效果</h5>
+                        <div class="progress progress-striped active">
+                            <div style="width: 30%" class="progress-bar progress-bar-success">
+                                <span class="sr-only">30% Complete (success)</span>
+                            </div>
+                            <div style="width: 20%" class="progress-bar progress-bar-warning">
+                                <span class="sr-only">20% Complete (warning)</span>
+                            </div>
+                            <div style="width: 40%" class="progress-bar progress-bar-danger">
+                                <span class="sr-only">40% Complete (danger)</span>
+                            </div>
+                        </div>
+                        
+                        <h5>带有提示标签的进度条</h5>
+                        <div class="progress">
+                            <div class="progress-bar" role="progressbar" aria-valuenow="95" aria-valuemin="0" aria-valuemax="100" style="width: 95%;">
+                                95%
+                            </div>
+                        </div>
+
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <th:block th:include="include :: footer" />
+    <script type="text/javascript">
+	    $("[data-toggle='tooltip']").tooltip();
+	    $("[data-toggle=popover]").popover();
+    </script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/demo/form/select.html b/ruoyi-admin/src/main/resources/templates/demo/form/select.html
new file mode 100644
index 0000000..bc3e8b3
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/form/select.html
@@ -0,0 +1,148 @@
+<!DOCTYPE html>
+<html lang="zh">
+<head>
+	<th:block th:include="include :: header('下拉框')" />
+	<th:block th:include="include :: select2-css" />
+	<th:block th:include="include :: bootstrap-select-css" />
+</head>
+<body class="gray-bg">
+     <form>
+      <div class="wrapper wrapper-content animated fadeInRight">
+        <div class="row">
+            <div class="col-sm-6">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>下拉框 <small>https://github.com/select2/select2</small></h5>
+                    </div>  
+                    <div class="ibox-content">
+                        <div class="form-group">
+                            <label class="font-noraml">单选</label>
+                            <select class="form-control">
+                            	<option value="">--请选择开发语言--</option>
+                            	<option value="Java">Java</option>
+                            	<option value="PHP">PHP</option>
+                            	<option value=".NET">.NET</option>
+                            </select>
+                        </div>
+                        
+                        <div class="form-group">
+                             <label class="font-noraml">分组单选</label>
+                             <select class="form-control">
+                               <optgroup label="--请选择开发语言--">
+								 <option value="Java">Java</option>
+                                 <option value="PHP">PHP</option>
+                                 <option value=".NET">.NET</option>
+							   </optgroup>
+							   <optgroup label="--请选择数据库--">
+							     <option value="Oracle">Oracle</option>
+                                 <option value="Mysql">Mysql</option>
+                                 <option value="Sysbase">Sysbase</option>
+						       </optgroup>
+                             </select>
+                        </div>
+						  
+                        <div class="form-group">
+                            <label class="font-noraml">多选</label>
+                            <select class="form-control select2-multiple" multiple>
+                            	<option value="">请选择开发语言</option>
+                            	<option value="Java">Java</option>
+                            	<option value="PHP">PHP</option>
+                            	<option value=".NET">.NET</option>
+                            </select>
+                        </div>
+                        
+                        <div class="form-group">
+                             <label class="font-noraml">分组多选</label>
+                             <select class="form-control select2-multiple" multiple>
+                               <optgroup label="--请选择开发语言--">
+								 <option value="Java">Java</option>
+                                 <option value="PHP">PHP</option>
+                                 <option value=".NET">.NET</option>
+							   </optgroup>
+							   <optgroup label="--请选择数据库--">
+							     <option value="Oracle">Oracle</option>
+                                 <option value="Mysql">Mysql</option>
+                                 <option value="Sysbase">Sysbase</option>
+						       </optgroup>
+                             </select>
+                        </div>
+                        <hr>
+                        <div class="form-group">
+                            <label class="font-noraml">相关参数详细信息</label>
+                            <div><a href="http://doc.ruoyi.vip/ruoyi/document/zjwd.html#select2" target="_blank">http://doc.ruoyi.vip/ruoyi/document/zjwd.html#select2</a></div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-6">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>下拉框 <small>https://github.com/snapappointments/bootstrap-select</small></h5>
+                    </div>
+                     <div class="ibox-content">
+                        <div class="form-group">
+                            <label class="font-noraml">单选</label>
+                            <select class="form-control noselect2 selectpicker">
+                            	<option value="">--请选择开发语言--</option>
+                            	<option value="Java">Java</option>
+                            	<option value="PHP">PHP</option>
+                            	<option value=".NET">.NET</option>
+                            </select>
+                        </div>
+                        
+                        <div class="form-group">
+                             <label class="font-noraml">分组单选</label>
+                             <select class="form-control noselect2 selectpicker">
+                               <optgroup label="--请选择开发语言--">
+								 <option value="Java">Java</option>
+                                 <option value="PHP">PHP</option>
+                                 <option value=".NET">.NET</option>
+							   </optgroup>
+							   <optgroup label="--请选择数据库--">
+							     <option value="Oracle">Oracle</option>
+                                 <option value="Mysql">Mysql</option>
+                                 <option value="Sysbase">Sysbase</option>
+						       </optgroup>
+                             </select>
+                        </div>
+						  
+                        <div class="form-group">
+                            <label class="font-noraml">多选</label>
+                            <select class="form-control noselect2 selectpicker" data-none-selected-text="请选择开发语言" multiple>
+                            	<option value="Java">Java</option>
+                            	<option value="PHP">PHP</option>
+                            	<option value=".NET">.NET</option>
+                            </select>
+                        </div>
+                        
+                        <div class="form-group">
+                             <label class="font-noraml">分组多选</label>
+                             <select class="form-control noselect2 selectpicker" data-none-selected-text="请选择" multiple>
+                               <optgroup label="--请选择开发语言--">
+								 <option value="Java">Java</option>
+                                 <option value="PHP">PHP</option>
+                                 <option value=".NET">.NET</option>
+							   </optgroup>
+							   <optgroup label="--请选择数据库--">
+							     <option value="Oracle">Oracle</option>
+                                 <option value="Mysql">Mysql</option>
+                                 <option value="Sysbase">Sysbase</option>
+						       </optgroup>
+                             </select>
+                        </div>
+                        <hr>
+                        <div class="form-group">
+                            <label class="font-noraml">相关参数详细信息</label>
+                            <div><a href="http://doc.ruoyi.vip/ruoyi/document/zjwd.html#bootstrap-select" target="_blank">http://doc.ruoyi.vip/ruoyi/document/zjwd.html#bootstrap-select</a></div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+   </form>
+    <th:block th:include="include :: footer" />
+    <th:block th:include="include :: select2-js" />
+    <th:block th:include="include :: bootstrap-select-js" />
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/demo/form/sortable.html b/ruoyi-admin/src/main/resources/templates/demo/form/sortable.html
new file mode 100644
index 0000000..2ca4ac7
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/form/sortable.html
@@ -0,0 +1,198 @@
+<!DOCTYPE html>
+<html lang="zh">
+<head>
+	<th:block th:include="include :: header('拖动排序')" />
+</head>
+<body class="gray-bg">
+    <div class="wrapper wrapper-content  animated fadeInRight">
+        <div class="row">
+            <div class="col-sm-4">
+                <div class="ibox">
+                    <div class="ibox-content">
+                        <h3>任务列表</h3>
+                        <p class="small"><i class="fa fa-hand-o-up"></i> 在列表之间拖动任务面板</p>
+
+                        <div class="input-group">
+                            <input type="text" placeholder="添加新任务" class="input input-sm form-control">
+                            <span class="input-group-btn">
+                                        <button type="button" class="btn btn-sm btn-white"> <i class="fa fa-plus"></i> 添加</button>
+                                </span>
+                        </div>
+
+                        <ul class="sortable-list connectList agile-list">
+                            <li class="warning-element">
+                                加强过程管理,及时统计教育经费使用情况,做到底码清楚,
+                                <div class="agile-detail">
+                                    <a href="javascript:;" class="pull-right btn btn-xs btn-white">标签</a>
+                                    <i class="fa fa-clock-o"></i> 2018.09.01
+                                </div>
+                            </li>
+                            <li class="success-element">
+                                支持财会人员的继续培训工作。
+                                <div class="agile-detail">
+                                    <a href="javascript:;" class="pull-right btn btn-xs btn-white">标记</a>
+                                    <i class="fa fa-clock-o"></i> 2018.05.12
+                                </div>
+                            </li>
+                            <li class="info-element">
+                                协同教导处搞好助学金、减免教科书费的工作。
+                                <div class="agile-detail">
+                                    <a href="javascript:;" class="pull-right btn btn-xs btn-white">标记</a>
+                                    <i class="fa fa-clock-o"></i> 2018.09.10
+                                </div>
+                            </li>
+                            <li class="danger-element">
+                                要求会计、出纳人员严格执行财务制度,遵守岗位职责,按时上报各种资料。
+                                <div class="agile-detail">
+                                    <a href="javascript:;" class="pull-right btn btn-xs btn-primary">确定</a>
+                                    <i class="fa fa-clock-o"></i> 2018.06.10
+                                </div>
+                            </li>
+                            <li class="warning-element">
+                                做好职工公费医疗工作,按时发放门诊费。
+                                <div class="agile-detail">
+                                    <a href="javascript:;" class="pull-right btn btn-xs btn-white">标签</a>
+                                    <i class="fa fa-clock-o"></i> 2018.09.09
+                                </div>
+                            </li>
+                            <li class="warning-element">
+                                有计划地把课本复习三至五遍。
+                                <div class="agile-detail">
+                                    <a href="javascript:;" class="pull-right btn btn-xs btn-primary">确定</a>
+                                    <i class="fa fa-clock-o"></i> 2018.08.04
+                                </div>
+                            </li>
+                            <li class="success-element">
+                                看一本高质量的高中语法书
+                                <div class="agile-detail">
+                                    <a href="javascript:;" class="pull-right btn btn-xs btn-white">标记</a>
+                                    <i class="fa fa-clock-o"></i> 2018.05.12
+                                </div>
+                            </li>
+                            <li class="info-element">
+                                选择一份较好的英语报纸,通过阅读提高英语学习效果。
+                                <div class="agile-detail">
+                                    <a href="javascript:;" class="pull-right btn btn-xs btn-white">标记</a>
+                                    <i class="fa fa-clock-o"></i> 2018.09.10
+                                </div>
+                            </li>
+                        </ul>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-4">
+                <div class="ibox">
+                    <div class="ibox-content">
+                        <h3>进行中</h3>
+                        <p class="small"><i class="fa fa-hand-o-up"></i> 在列表之间拖动任务面板</p>
+                        <ul class="sortable-list connectList agile-list">
+                            <li class="success-element">
+                                全面、较深入地掌握我们“产品”的功能、特色和优势并做到应用自如。
+                                <div class="agile-detail">
+                                    <a href="javascript:;" class="pull-right btn btn-xs btn-white">标签</a>
+                                    <i class="fa fa-clock-o"></i> 2018.09.01
+                                </div>
+                            </li>
+                            <li class="success-element">
+                                根据自己以前所了解的和从其他途径搜索到的信息,录入客户资料150家。
+                                <div class="agile-detail">
+                                    <a href="javascript:;" class="pull-right btn btn-xs btn-white">标记</a>
+                                    <i class="fa fa-clock-o"></i> 2018.05.12
+                                </div>
+                            </li>
+                            <li class="warning-element">
+                                锁定有意向客户20家。
+                                <div class="agile-detail">
+                                    <a href="javascript:;" class="pull-right btn btn-xs btn-white">标记</a>
+                                    <i class="fa fa-clock-o"></i> 2018.09.10
+                                </div>
+                            </li>
+                            <li class="warning-element">
+                                力争完成销售指标。
+                                <div class="agile-detail">
+                                    <a href="javascript:;" class="pull-right btn btn-xs btn-white">标签</a>
+                                    <i class="fa fa-clock-o"></i> 2018.09.09
+                                </div>
+                            </li>
+                            <li class="info-element">
+                                在总结和摸索中前进。
+                                <div class="agile-detail">
+                                    <a href="javascript:;" class="pull-right btn btn-xs btn-primary">确定</a>
+                                    <i class="fa fa-clock-o"></i> 2018.08.04
+                                </div>
+                            </li>
+                            <li class="success-element">
+                                不断学习行业知识、产品知识,为客户带来实用介绍内容
+                                <div class="agile-detail">
+                                    <a href="javascript:;" class="pull-right btn btn-xs btn-white">标记</a>
+                                    <i class="fa fa-clock-o"></i> 2018.05.12
+                                </div>
+                            </li>
+                            <li class="danger-element">
+                                先友后单:与客户发展良好友谊,转换销售员角色,处处为客户着想
+                                <div class="agile-detail">
+                                    <a href="javascript:;" class="pull-right btn btn-xs btn-white">标记</a>
+                                    <i class="fa fa-clock-o"></i> 2018.11.04
+                                </div>
+                            </li>
+                        </ul>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-4">
+                <div class="ibox">
+                    <div class="ibox-content">
+                        <h3>已完成</h3>
+                        <p class="small"><i class="fa fa-hand-o-up"></i> 在列表之间拖动任务面板</p>
+                        <ul class="sortable-list connectList agile-list">
+                            <li class="info-element">
+                                制定工作日程表
+                                <div class="agile-detail">
+                                    <a href="javascript:;" class="pull-right btn btn-xs btn-white">标记</a>
+                                    <i class="fa fa-clock-o"></i> 2018.09.10
+                                </div>
+                            </li>
+                            <li class="warning-element">
+                                每天坚持打40个有效电话,挖掘潜在客户
+                                <div class="agile-detail">
+                                    <a href="javascript:;" class="pull-right btn btn-xs btn-white">标签</a>
+                                    <i class="fa fa-clock-o"></i> 2018.09.09
+                                </div>
+                            </li>
+                            <li class="warning-element">
+                                拜访客户之前要对该客户做全面的了解(客户的潜在需求、职位、权限以及个人性格和爱好)
+                                <div class="agile-detail">
+                                    <a href="javascript:;" class="pull-right btn btn-xs btn-white">标签</a>
+                                    <i class="fa fa-clock-o"></i> 2018.09.09
+                                </div>
+                            </li>
+                            <li class="warning-element">
+                                提高自己电话营销技巧,灵活专业地与客户进行电话交流
+                                <div class="agile-detail">
+                                    <a href="javascript:;" class="pull-right btn btn-xs btn-primary">确定</a>
+                                    <i class="fa fa-clock-o"></i> 2018.08.04
+                                </div>
+                            </li>
+                            <li class="success-element">
+                                通过电话销售过程中了解各盛市的设备仪器使用、采购情况及相关重要追踪人
+                                <div class="agile-detail">
+                                    <a href="javascript:;" class="pull-right btn btn-xs btn-white">标记</a>
+                                    <i class="fa fa-clock-o"></i> 2018.05.12
+                                </div>
+                            </li>
+
+                        </ul>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <th:block th:include="include :: footer" />
+    <script th:src="@{/js/jquery-ui-1.10.4.min.js}"></script>
+    <script>
+	    $(document).ready(function () {
+	        $(".sortable-list").sortable({connectWith: ".connectList"}).disableSelection()
+	    });
+    </script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/demo/form/summernote.html b/ruoyi-admin/src/main/resources/templates/demo/form/summernote.html
new file mode 100644
index 0000000..d4fb248
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/form/summernote.html
@@ -0,0 +1,93 @@
+<!DOCTYPE html>
+<html lang="zh">
+<head>
+	<th:block th:include="include :: header('Summernote富文本编辑器')" />
+	<th:block th:include="include :: summernote-css" />
+</head>
+<body class="gray-bg">
+    <div class="wrapper wrapper-content">
+        <div class="row">
+            <div class="col-sm-12">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>Summernote 富文本编辑器</h5>
+                    </div>
+                    <div class="ibox-content no-padding">
+                        <div class="summernote">
+                            <h2>若依后台管理系统</h2>
+                            <p>ruoyi是一个完全响应式,基于Bootstrap3.3.7最新版本开发的扁平化主题,她采用了主流的左右两栏式布局,使用了Html5+CSS3等现代技术,她提供了诸多的强大的可以重新组合的UI组件,并集成了最新的jQuery版本(v2.1.1),当然,也集成了很多功能强大,用途广泛的就jQuery插件,她可以用于所有的Web应用程序,如<b>网站管理后台</b>,<b>网站会员中心</b>,<b>CMS</b>,<b>CRM</b>,<b>OA</b>等等,当然,您也可以对她进行深度定制,以做出更强系统。</p>
+                            <p>
+                                <b>当前版本:</b>v4.8.0
+                            </p>
+                            <p>
+                                <span class="label label-warning">免费开源</span>
+                            </p>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div class="row">
+            <div class="col-sm-12">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-content">
+                        <h2>Summernote</h2>
+                        <p>
+                            Summernote是一个简单的基于Bootstrap的WYSIWYG富文本编辑器
+                        </p>
+                        <div class="alert alert-warning"> 官方文档请参考:
+                            <a href="https://github.com/summernote/summernote">https://github.com/summernote/summernote</a>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div class="row">
+            <div class="col-sm-12">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>编辑/保存为html代码示例</h5>
+                        <button id="edit" class="btn btn-primary btn-xs m-l-sm" onclick="edit()" type="button">编辑</button>
+                        <button id="save" class="btn btn-primary  btn-xs" onclick="save()" type="button">保存</button>
+                    </div>
+                    <div class="ibox-content" id="eg">
+
+                        <div class="click2edit wrapper">
+                            <h3>你好,若依 </h3>
+                            <p>H+是一个完全响应式,基于Bootstrap3.3.7最新版本开发的扁平化主题,她采用了主流的左右两栏式布局,使用了Html5+CSS3等现代技术,她提供了诸多的强大的可以重新组合的UI组件,并集成了最新的jQuery版本(v2.1.1),当然,也集成了很多功能强大,用途广泛的就jQuery插件,她可以用于所有的Web应用程序,如<b>网站管理后台</b>,<b>网站会员中心</b>,<b>CMS</b>,<b>CRM</b>,<b>OA</b>等等,当然,您也可以对她进行深度定制,以做出更强系统。</p>
+                            <p>
+                                <b>当前版本:</b>v4.8.0
+                            </p>
+                            <p>
+                                <span class="label label-warning">开源免费</span>
+                            </p>
+                        </div>
+
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <th:block th:include="include :: footer" />
+    <th:block th:include="include :: summernote-js" />
+    <script>
+        $(document).ready(function () {
+            $('.summernote').summernote({
+                lang: 'zh-CN'
+            });
+        });
+        var edit = function () {
+            $("#eg").addClass("no-padding");
+            $('.click2edit').summernote({
+                lang: 'zh-CN',
+                focus: true
+            });
+        };
+        var save = function () {
+            $("#eg").removeClass("no-padding");
+            var aHTML = $('.click2edit').summernote('code');
+            $('.click2edit').summernote('destroy');
+        };
+    </script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/demo/form/tabs_panels.html b/ruoyi-admin/src/main/resources/templates/demo/form/tabs_panels.html
new file mode 100644
index 0000000..26e4fc5
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/form/tabs_panels.html
@@ -0,0 +1,353 @@
+<!DOCTYPE html>
+<html lang="zh">
+<head>
+	<th:block th:include="include :: header('选项卡 & 面板')" />
+</head>
+<body class="gray-bg">
+    <div class="wrapper wrapper-content animated fadeIn">
+        <div class="row">
+            <div class="col-sm-12">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>基本面板 <small class="m-l-sm">这是一个自定义面板</small></h5>
+                        <div class="ibox-tools">
+                            <a class="collapse-link">
+                                <i class="fa fa-chevron-up"></i>
+                            </a>
+                            <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                                <i class="fa fa-wrench"></i>
+                            </a>
+                            <ul class="dropdown-menu dropdown-user">
+                                <li><a href="javascript:;">选项1</a>
+                                </li>
+                                <li><a href="javascript:;">选项2</a>
+                                </li>
+                            </ul>
+                            <a class="close-link">
+                                <i class="fa fa-times"></i>
+                            </a>
+                        </div>
+                    </div>
+                    <div class="ibox-content">
+                        <h2>
+                            Bootstrap<br/>
+                        </h2>
+                        <p>
+                            简洁、直观、强悍的前端开发框架,让web开发更迅速、简单。</p>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div class="row">
+            <div class="col-sm-6">
+                <div class="tabs-container">
+                    <ul class="nav nav-tabs">
+                        <li class="active"><a data-toggle="tab" href="#tab-1" aria-expanded="true"> 第一个选项卡</a>
+                        </li>
+                        <li class=""><a data-toggle="tab" href="#tab-2" aria-expanded="false">第二个选项卡</a>
+                        </li>
+                    </ul>
+                    <div class="tab-content">
+                        <div id="tab-1" class="tab-pane active">
+                            <div class="panel-body">
+                                <strong>HTML5 文档类型</strong>
+                                <p>Bootstrap 使用到的某些 HTML 元素和 CSS 属性需要将页面设置为 HTML5 文档类型。在你项目中的每个页面都要参照下面的格式进行设置。</p>
+                            </div>
+                        </div>
+                        <div id="tab-2" class="tab-pane">
+                            <div class="panel-body">
+                                <strong>移动设备优先</strong>
+                                <p>在 Bootstrap 2 中,我们对框架中的某些关键部分增加了对移动设备友好的样式。而在 Bootstrap 3 中,我们重写了整个框架,使其一开始就是对移动设备友好的。这次不是简单的增加一些可选的针对移动设备的样式,而是直接融合进了框架的内核中。也就是说,Bootstrap 是移动设备优先的。针对移动设备的样式融合进了框架的每个角落,而不是增加一个额外的文件。</p>
+                            </div>
+                        </div>
+                    </div>
+
+
+                </div>
+            </div>
+
+            <div class="col-sm-6">
+                <div class="panel blank-panel">
+
+                    <div class="panel-heading">
+                        <div class="panel-title m-b-md">
+                            <h4>图标选项卡</h4>
+                        </div>
+                        <div class="panel-options">
+
+                            <ul class="nav nav-tabs">
+                                <li class="active"><a data-toggle="tab" href="#tab-4"><i class="fa fa-laptop"></i></a>
+                                </li>
+                                <li class=""><a data-toggle="tab" href="#tab-5"><i class="fa fa-desktop"></i></a>
+                                </li>
+                                <li class=""><a data-toggle="tab" href="#tab-6"><i class="fa fa-signal"></i></a>
+                                </li>
+                                <li class=""><a data-toggle="tab" href="#tab-7"><i class="fa fa-bar-chart-o"></i></a>
+                                </li>
+                            </ul>
+                        </div>
+                    </div>
+
+                    <div class="panel-body">
+                        <div class="tab-content">
+                            <div id="tab-4" class="tab-pane active">
+                                <strong>排版与链接</strong>
+
+                                <p>Bootstrap 排版、链接样式设置了基本的全局样式。分别是: 为 body 元素设置 background-color: #fff; 使用 @font-family-base、@font-size-base 和 @line-height-base a变量作为排版的基本参数 为所有链接设置了基本颜色 @link-color ,并且当链接处于 :hover 状态时才添加下划线 这些样式都能在 scaffolding.less 文件中找到对应的源码。</p>
+                            </div>
+
+                            <div id="tab-5" class="tab-pane">
+                                <strong>Normalize.css</strong>
+
+                                <p>为了增强跨浏览器表现的一致性,我们使用了 Normalize.css,这是由 Nicolas Gallagher 和 Jonathan Neal 维护的一个CSS 重置样式库。</p>
+                            </div>
+                            <div id="tab-6" class="tab-pane">
+                                <strong>布局容器</strong>
+
+                                <p>Bootstrap 需要为页面内容和栅格系统包裹一个 .container 容器。我们提供了两个作此用处的类。注意,由于 padding 等属性的原因,这两种 容器类不能互相嵌套。</p>
+                            </div>
+                            <div id="tab-7" class="tab-pane">
+                                <strong>栅格系统</strong>
+
+                                <p>Bootstrap 提供了一套响应式、移动设备优先的流式栅格系统,随着屏幕或视口(viewport)尺寸的增加,系统会自动分为最多12列。它包含了易于使用的预定义类,还有强大的mixin 用于生成更具语义的布局。</p>
+                            </div>
+                        </div>
+
+                    </div>
+
+                </div>
+            </div>
+        </div>
+        <div class="row m-b-lg">
+            <div class="col-sm-6">
+                <div class="tabs-container">
+
+                    <div class="tabs-left">
+                        <ul class="nav nav-tabs">
+                            <li class="active"><a data-toggle="tab" href="#tab-8"> 第一个选项卡</a>
+                            </li>
+                            <li class=""><a data-toggle="tab" href="#tab-9"> 第二个选项卡</a>
+                            </li>
+                        </ul>
+                        <div class="tab-content ">
+                            <div id="tab-8" class="tab-pane active">
+                                <div class="panel-body">
+                                    <strong>排版与链接</strong>
+
+                                    <p>Bootstrap 排版、链接样式设置了基本的全局样式。分别是: 为 body 元素设置 background-color: #fff; 使用 @font-family-base、@font-size-base 和 @line-height-base a变量作为排版的基本参数 为所有链接设置了基本颜色 @link-color ,并且当链接处于 :hover 状态时才添加下划线 这些样式都能在 scaffolding.less 文件中找到对应的源码。</p>
+                                </div>
+                            </div>
+                            <div id="tab-9" class="tab-pane">
+                                <div class="panel-body">
+                                    <strong>栅格系统</strong>
+
+                                    <p>Bootstrap 提供了一套响应式、移动设备优先的流式栅格系统,随着屏幕或视口(viewport)尺寸的增加,系统会自动分为最多12列。它包含了易于使用的预定义类,还有强大的mixin 用于生成更具语义的布局。</p>
+                                </div>
+                            </div>
+                        </div>
+
+                    </div>
+
+                </div>
+            </div>
+            <div class="col-sm-6">
+                <div class="tabs-container">
+                    <div class="tabs-right">
+                        <ul class="nav nav-tabs">
+                            <li class="active"><a data-toggle="tab" href="#tab-10">第一个选项卡</a>
+                            </li>
+                            <li class=""><a data-toggle="tab" href="#tab-11"> 第二个选项卡</a>
+                            </li>
+                        </ul>
+                        <div class="tab-content ">
+                            <div id="tab-10" class="tab-pane active">
+                                <div class="panel-body">
+                                    <strong>排版与链接</strong>
+
+                                    <p>Bootstrap 排版、链接样式设置了基本的全局样式。分别是: 为 body 元素设置 background-color: #fff; 使用 @font-family-base、@font-size-base 和 @line-height-base a变量作为排版的基本参数 为所有链接设置了基本颜色 @link-color ,并且当链接处于 :hover 状态时才添加下划线 这些样式都能在 scaffolding.less 文件中找到对应的源码。</p>
+                                </div>
+                            </div>
+                            <div id="tab-11" class="tab-pane">
+                                <div class="panel-body">
+                                    <strong>栅格系统</strong>
+
+                                    <p>Bootstrap 提供了一套响应式、移动设备优先的流式栅格系统,随着屏幕或视口(viewport)尺寸的增加,系统会自动分为最多12列。它包含了易于使用的预定义类,还有强大的mixin 用于生成更具语义的布局。</p>
+                                </div>
+                            </div>
+                        </div>
+
+                    </div>
+                </div>
+            </div>
+        </div>
+
+        <div class="row">
+            <div class="col-sm-12">
+                <div class="ibox">
+                    <div class="ibox-title">
+                        <h5>Bootstrap面板 <small>自定义背景</small></h5>
+                    </div>
+                    <div class="ibox-content">
+
+                        <div class="row">
+                            <div class="col-sm-4">
+                                <div class="panel panel-default">
+                                    <div class="panel-heading">
+                                        默认面板
+                                    </div>
+                                    <div class="panel-body">
+                                        <p>通过 .panel-heading 可以很简单地为面板加入一个标题容器。你也可以通过添加设置了 .panel-title 类的标签,添加一个预定义样式的标题。 为了给链接设置合适的颜色,务必将链接放到带有 .panel-title 类的标题标签内。</p>
+                                    </div>
+
+                                </div>
+                            </div>
+                            <div class="col-sm-4">
+                                <div class="panel panel-primary">
+                                    <div class="panel-heading">
+                                        主要
+                                    </div>
+                                    <div class="panel-body">
+                                        <p>通过 .panel-heading 可以很简单地为面板加入一个标题容器。你也可以通过添加设置了 .panel-title 类的标签,添加一个预定义样式的标题。 为了给链接设置合适的颜色,务必将链接放到带有 .panel-title 类的标题标签内。</p>
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="col-sm-4">
+                                <div class="panel panel-success">
+                                    <div class="panel-heading">
+                                        成功
+                                    </div>
+                                    <div class="panel-body">
+                                        <p>通过 .panel-heading 可以很简单地为面板加入一个标题容器。你也可以通过添加设置了 .panel-title 类的标签,添加一个预定义样式的标题。 为了给链接设置合适的颜色,务必将链接放到带有 .panel-title 类的标题标签内。</p>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="row">
+                            <div class="col-sm-4">
+                                <div class="panel panel-info">
+                                    <div class="panel-heading">
+                                        <i class="fa fa-info-circle"></i> 信息
+                                    </div>
+                                    <div class="panel-body">
+                                        <p>通过 .panel-heading 可以很简单地为面板加入一个标题容器。你也可以通过添加设置了 .panel-title 类的标签,添加一个预定义样式的标题。 为了给链接设置合适的颜色,务必将链接放到带有 .panel-title 类的标题标签内。</p>
+                                    </div>
+
+                                </div>
+                            </div>
+                            <div class="col-sm-4">
+                                <div class="panel panel-warning">
+                                    <div class="panel-heading">
+                                        <i class="fa fa-warning"></i> 警告
+                                    </div>
+                                    <div class="panel-body">
+                                        <p>通过 .panel-heading 可以很简单地为面板加入一个标题容器。你也可以通过添加设置了 .panel-title 类的标签,添加一个预定义样式的标题。 为了给链接设置合适的颜色,务必将链接放到带有 .panel-title 类的标题标签内。</p>
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="col-sm-4">
+                                <div class="panel panel-danger">
+                                    <div class="panel-heading">
+                                        危险
+                                    </div>
+                                    <div class="panel-body">
+                                        <p>通过 .panel-heading 可以很简单地为面板加入一个标题容器。你也可以通过添加设置了 .panel-title 类的标签,添加一个预定义样式的标题。 为了给链接设置合适的颜色,务必将链接放到带有 .panel-title 类的标题标签内。</p>
+                                    </div>
+                                    <div class="panel-footer">
+                                        面板Footer
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+
+                    </div>
+                </div>
+            </div>
+        </div>
+
+        <div class="row">
+            <div class="col-sm-6">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>折叠面板</h5>
+                        <div class="ibox-tools">
+                            <a class="collapse-link">
+                                <i class="fa fa-chevron-up"></i>
+                            </a>
+                            <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                                <i class="fa fa-wrench"></i>
+                            </a>
+                            <ul class="dropdown-menu dropdown-user">
+                                <li><a href="javascript:;">选项1</a>
+                                </li>
+                                <li><a href="javascript:;">选项2</a>
+                                </li>
+                            </ul>
+                            <a class="close-link">
+                                <i class="fa fa-times"></i>
+                            </a>
+                        </div>
+                    </div>
+                    <div class="ibox-content">
+                        <div class="panel-body">
+                            <div class="panel-group" id="accordion">
+                                <div class="panel panel-default">
+                                    <div class="panel-heading">
+                                        <h5 class="panel-title">
+                                                <a data-toggle="collapse" data-parent="#accordion" href="#collapseOne">标题 #1</a>
+                                            </h5>
+                                    </div>
+                                    <div id="collapseOne" class="panel-collapse collapse in">
+                                        <div class="panel-body">
+                                            Bootstrap相关优质项目推荐 这些项目或者是对Bootstrap进行了有益的补充,或者是基于Bootstrap开发的
+                                        </div>
+                                    </div>
+                                </div>
+                                <div class="panel panel-default">
+                                    <div class="panel-heading">
+                                        <h4 class="panel-title">
+                                                <a data-toggle="collapse" data-parent="#accordion" href="#collapseTwo">标题 #2</a>
+                                            </h4>
+                                    </div>
+                                    <div id="collapseTwo" class="panel-collapse collapse">
+                                        <div class="panel-body">
+                                            Bootstrap相关优质项目推荐 这些项目或者是对Bootstrap进行了有益的补充,或者是基于Bootstrap开发的
+                                        </div>
+                                    </div>
+                                </div>
+                                <div class="panel panel-default">
+                                    <div class="panel-heading">
+                                        <h4 class="panel-title">
+                                                <a data-toggle="collapse" data-parent="#accordion" href="#collapseThree">标题 #3</a>
+                                            </h4>
+                                    </div>
+                                    <div id="collapseThree" class="panel-collapse collapse">
+                                        <div class="panel-body">
+                                            Bootstrap相关优质项目推荐 这些项目或者是对Bootstrap进行了有益的补充,或者是基于Bootstrap开发的
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-6">
+                <div class="jumbotron">
+                    <h1>超大屏幕</h1>
+                    <p>Bootstrap 支持的另一个特性,超大屏幕(Jumbotron)。顾名思义该组件可以增加标题的大小,并为登录页面内容添加更多的外边距(margin)。使用超大屏幕(Jumbotron)的步骤如下:</p>
+                    <div class="alert alert-warning">
+                        <ol>
+                            <li>创建一个带有 class .jumbotron. 的容器</li>
+                            <li>除了更大的 &lt;h1&gt;,字体粗细 font-weight 被减为 200px。</li>
+                        </ol>
+                    </div>
+
+                    <p><a role="button" class="btn btn-primary btn-lg">了解更多</a>
+                    </p>
+                </div>
+            </div>
+        </div>
+    </div>
+    <th:block th:include="include :: footer" />
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/demo/form/timeline.html b/ruoyi-admin/src/main/resources/templates/demo/form/timeline.html
new file mode 100644
index 0000000..132977e
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/form/timeline.html
@@ -0,0 +1,113 @@
+<!DOCTYPE html>
+<html lang="zh">
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>时间轴</title>
+	<link href="../static/css/bootstrap.min.css" th:href="@{/css/bootstrap.min.css}" rel="stylesheet"/>
+    <link href="../static/css/font-awesome.min.css" th:href="@{/css/font-awesome.min.css}" rel="stylesheet"/>
+    <link href="../static/css/animate.min.css" th:href="@{/css/animate.min.css}" rel="stylesheet"/>
+    <link href="../static/css/style.min.css" th:href="@{/css/style.min.css}" rel="stylesheet"/>
+</head>
+<body class="gray-bg">
+    <div class="row animated fadeInRight">
+        <div class="ibox float-e-margins">
+            <div class="text-center float-e-margins p-md">
+                <span>打开/关闭颜色/背景或方向版本: </span>
+                <a href="javascript:;" class="btn btn-xs btn-primary" id="lightVersion">轻型版本 </a>
+                <a href="javascript:;" class="btn btn-xs btn-primary" id="darkVersion">黑色版本 </a>
+            </div>
+            <div id="ibox-content">
+                 <div id="vertical-timeline" class="vertical-container light-timeline">
+                     <div class="vertical-timeline-block">
+                         <div class="vertical-timeline-icon navy-bg">
+                             <i class="fa fa-briefcase"></i>
+                         </div>
+
+                         <div class="vertical-timeline-content">
+                             <h2>会议</h2>
+                             <p>上一年的销售业绩发布会。总结产品营销和销售趋势及销售的现状。
+                             </p>
+                             <a href="javascript:;" class="btn btn-sm btn-primary"> 更多信息</a>
+                             <span class="vertical-date">
+                         	今天 <br>
+                         <small>2月3日</small>
+                     </span>
+                         </div>
+                     </div>
+
+                     <div class="vertical-timeline-block">
+                         <div class="vertical-timeline-icon blue-bg">
+                             <i class="fa fa-file-text"></i>
+                         </div>
+
+                         <div class="vertical-timeline-content">
+                             <h2>给张三发送文档</h2>
+                             <p>发送上年度《销售业绩报告》</p>
+                             <a href="javascript:;" class="btn btn-sm btn-success"> 下载文档 </a>
+                             <span class="vertical-date">
+                         	今天 <br>
+                         <small>2月3日</small>
+                     </span>
+                         </div>
+                     </div>
+
+                     <div class="vertical-timeline-block">
+                         <div class="vertical-timeline-icon lazur-bg">
+                             <i class="fa fa-coffee"></i>
+                         </div>
+
+                         <div class="vertical-timeline-content">
+                             <h2>喝咖啡休息</h2>
+                             <p>喝咖啡啦,啦啦啦~~</p>
+                             <a href="javascript:;" class="btn btn-sm btn-info">更多</a>
+                             <span class="vertical-date"> 昨天 <br><small>2月2日</small></span>
+                         </div>
+                     </div>
+
+                     <div class="vertical-timeline-block">
+                         <div class="vertical-timeline-icon yellow-bg">
+                             <i class="fa fa-phone"></i>
+                         </div>
+
+                         <div class="vertical-timeline-content">
+                             <h2>给李四打电话</h2>
+                             <p>给李四打电话分配本月工作任务</p>
+                             <span class="vertical-date">昨天 <br><small>2月2日</small></span>
+                         </div>
+                     </div>
+
+                     <div class="vertical-timeline-block">
+                         <div class="vertical-timeline-icon lazur-bg">
+                             <i class="fa fa-user-md"></i>
+                         </div>
+
+                         <div class="vertical-timeline-content">
+                             <h2>公司年会</h2>
+                             <p>发年终奖啦,啦啦啦~~</p>
+                             <span class="vertical-date">前天 <br><small>2月1日</small></span>
+                         </div>
+                     </div>
+                 </div>
+             </div>
+        </div>
+    </div>
+    <th:block th:include="include :: footer" />
+    <script>
+        $(document).ready(function(){
+            $('#lightVersion').click(function(event) {
+                event.preventDefault()
+                $('#ibox-content').removeClass('ibox-content');
+                $('#vertical-timeline').removeClass('dark-timeline');
+                $('#vertical-timeline').addClass('light-timeline');
+            });
+            $('#darkVersion').click(function(event) {
+                event.preventDefault()
+                $('#ibox-content').addClass('ibox-content');
+                $('#vertical-timeline').removeClass('light-timeline');
+                $('#vertical-timeline').addClass('dark-timeline');
+            });
+        });
+    </script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/demo/form/upload.html b/ruoyi-admin/src/main/resources/templates/demo/form/upload.html
new file mode 100644
index 0000000..9b8b4a2
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/form/upload.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<html lang="zh">
+<head>
+	<th:block th:include="include :: header('文件上传')" />
+	<th:block th:include="include :: bootstrap-fileinput-css" />
+</head>
+<body class="gray-bg">
+<div class="wrapper wrapper-content animated fadeInRight">
+        <div class="row">
+            <div class="col-sm-12">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>文件上传控件 <small>https://github.com/kartik-v/bootstrap-fileinput</small></h5>
+                    </div>
+                    <div class="ibox-content">
+                    	<div class="form-group">
+                            <label class="font-noraml">单文件上传</label>
+	                        <div class="file-loading">
+					            <input id="singleFile" name="file" type="file">
+					        </div>
+                        </div>
+                        
+                        <div class="form-group">
+                            <label class="font-noraml">多文件上传</label>
+	                        <div class="file-loading">
+					            <input id="multipleFile" name="files" type="file" multiple>
+					        </div>
+                        </div>
+                        <hr>
+                        <div class="form-group">
+                            <label class="font-noraml">相关参数详细信息</label>
+                            <div><a href="http://doc.ruoyi.vip/ruoyi/document/zjwd.html#bootstrap-fileinput" target="_blank">http://doc.ruoyi.vip/ruoyi/document/zjwd.html#bootstrap-fileinput</a></div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <th:block th:include="include :: footer" />
+    <th:block th:include="include :: bootstrap-fileinput-js" />
+    <script th:inline="javascript">
+    
+    $(document).ready(function () {
+    	// 单图上传
+    	$("#singleFile").fileinput({
+            uploadUrl: ctx + 'common/upload',
+            maxFileCount: 1,
+            autoReplace: true
+        }).on('fileuploaded', function (event, data, previewId, index) {
+        	var rsp = data.response;
+            log.info("return url:" + rsp.url)
+            log.info("reutrn fileName:" + rsp.fileName)
+            log.info("reutrn newFileName:" + rsp.newFileName)
+            log.info("return originalFilename:" + rsp.originalFilename)
+        }).on('fileremoved', function (event, id, index) {
+            $("input[name='" + event.currentTarget.id + "']").val('')
+        })
+        
+        // 多图上传
+        $("#multipleFile").fileinput({
+            uploadUrl: ctx + 'common/uploads',
+            uploadAsync: false
+        }).on('filebatchuploadsuccess', function (event, data, previewId, index) {
+        	var rsp = data.response;
+        	log.info("return urls:" + rsp.urls)
+            log.info("reutrn fileNames:" + rsp.fileNames)
+            log.info("reutrn newFileNames:" + rsp.newFileNames)
+            log.info("return originalFilenames:" + rsp.originalFilenames)
+        }).on('fileremoved', function (event, id, index) {
+            $("input[name='" + event.currentTarget.id + "']").val('')
+        })
+    });
+    </script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/demo/form/validate.html b/ruoyi-admin/src/main/resources/templates/demo/form/validate.html
new file mode 100644
index 0000000..31c0872
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/form/validate.html
@@ -0,0 +1,193 @@
+<!DOCTYPE html>
+<html lang="zh">
+<head>
+	<th:block th:include="include :: header('表单校验')" />
+</head>
+<body class="gray-bg">
+<div class="wrapper wrapper-content animated fadeInRight">
+        <div class="row">
+            <div class="col-sm-12">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>jQuery Validate 简介</h5>
+                    </div>
+                    <div class="ibox-content">
+                        <p>jquery.validate.js 是一款优秀的jQuery表单验证插件。它具有如下特点:</p>
+                        <ul>
+                            <li>安装简单</li>
+                            <li>内置超过20种数据验证方法</li>
+                            <li>直列错误提示信息</li>
+                            <li>可扩展的数据验证方法</li>
+                            <li>使用内置的元数据或插件选项来指定您的验证规则</li>
+                            <li>优雅的交互设计</li>
+                        </ul>
+                        <p>官网:<a href="http://jqueryvalidation.org/" target="_blank">http://jqueryvalidation.org/</a>
+                        </p>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div class="row">
+            <div class="col-sm-6">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>简单示例</h5>
+                    </div>
+                    <div class="ibox-content">
+                        <form class="form-horizontal m-t" id="commentForm">
+                            <div class="form-group">
+                                <label class="col-sm-3 control-label">姓名:</label>
+                                <div class="col-sm-8">
+                                    <input id="cname" name="name" minlength="2" type="text" class="form-control" required>
+                                </div>
+                            </div>
+                            <div class="form-group">
+                                <label class="col-sm-3 control-label">E-mail:</label>
+                                <div class="col-sm-8">
+                                    <input id="cemail" type="email" class="form-control" name="email" required>
+                                </div>
+                            </div>
+                            <div class="form-group">
+                                <label class="col-sm-3 control-label">网站:</label>
+                                <div class="col-sm-8">
+                                    <input id="curl" type="url" class="form-control" name="url">
+                                </div>
+                            </div>
+                            <div class="form-group">
+                                <label class="col-sm-3 control-label">说明:</label>
+                                <div class="col-sm-8">
+                                    <textarea id="ccomment" name="comment" class="form-control" required></textarea>
+                                </div>
+                            </div>
+                            <div class="form-group">
+                                <div class="col-sm-4 col-sm-offset-3">
+                                    <button class="btn btn-primary" type="submit">提交</button>
+                                </div>
+                            </div>
+                        </form>
+                    </div>
+                </div>
+                <div class="ibox float-e-margins">
+                    <div class="ibox-content">
+                        <p class="m-t">更多示例请访问官方示例页面:<a href="http://jqueryvalidation.org/files/demo/" target="_blank">查看</a>
+                        </p>
+                        <p>中文API可参考:<a href="http://doc.ruoyi.vip/ruoyi/document/zjwd.html#jquery-validate" target="_blank">http://doc.ruoyi.vip/ruoyi/document/zjwd.html#jquery-validate</a>
+                        </p>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-6">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>完整验证表单</h5>
+                    </div>
+                    <div class="ibox-content">
+                        <form class="form-horizontal m-t" id="signupForm">
+                            <div class="form-group">
+                                <label class="col-sm-3 control-label">姓氏:</label>
+                                <div class="col-sm-8">
+                                    <input id="firstname" name="firstname" class="form-control" type="text">
+                                    <span class="help-block m-b-none"><i class="fa fa-info-circle"></i> 这里写点提示的内容</span>
+                                </div>
+                            </div>
+                            <div class="form-group">
+                                <label class="col-sm-3 control-label">名字:</label>
+                                <div class="col-sm-8">
+                                    <input id="lastname" name="lastname" class="form-control" type="text" required>
+                                </div>
+                            </div>
+                            <div class="form-group">
+                                <label class="col-sm-3 control-label">用户名:</label>
+                                <div class="col-sm-8">
+                                    <input id="username" name="username" class="form-control" type="text" required>
+                                </div>
+                            </div>
+                            <div class="form-group">
+                                <label class="col-sm-3 control-label">密码:</label>
+                                <div class="col-sm-8">
+                                    <input id="password" name="password" class="form-control" type="password">
+                                </div>
+                            </div>
+                            <div class="form-group">
+                                <label class="col-sm-3 control-label">确认密码:</label>
+                                <div class="col-sm-8">
+                                    <input id="confirm_password" name="confirm_password" class="form-control" type="password">
+                                    <span class="help-block m-b-none"><i class="fa fa-info-circle"></i> 请再次输入您的密码</span>
+                                </div>
+                            </div>
+                            <div class="form-group">
+                                <label class="col-sm-3 control-label">E-mail:</label>
+                                <div class="col-sm-8">
+                                    <input id="email" name="email" class="form-control" type="email">
+                                </div>
+                            </div>
+                            <div class="form-group">
+                                <div class="col-sm-8 col-sm-offset-3">
+                                    <button class="btn btn-primary" type="submit">提交</button>
+                                </div>
+                            </div>
+                        </form>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <th:block th:include="include :: footer" />
+    <script type="text/javascript">
+    $(function(){
+        $("#commentForm").validate();
+
+        var icon = "<i class='fa fa-times-circle'></i> ";
+        $("#signupForm").validate({
+            rules: {
+                firstname: "required",
+                lastname: "required",
+                username: {
+                    required: true,
+                    minlength: 2
+                },
+                password: {
+                    required: true,
+                    minlength: 5
+                },
+                confirm_password: {
+                    required: true,
+                    minlength: 5,
+                    equalTo: "#password"
+                },
+                email: {
+                    required: true,
+                    email: true
+                }
+            },
+            messages: {
+                firstname: icon + "请输入你的姓",
+                lastname: icon + "请输入您的名字",
+                username: {
+                    required: icon + "请输入您的用户名",
+                    minlength: icon + "用户名必须两个字符以上"
+                },
+                password: {
+                    required: icon + "请输入您的密码",
+                    minlength: icon + "密码必须5个字符以上"
+                },
+                confirm_password: {
+                    required: icon + "请再次输入密码",
+                    minlength: icon + "密码必须5个字符以上",
+                    equalTo: icon + "两次输入的密码不一致"
+                },
+                email: icon + "请输入您的E-mail"
+            }
+        });
+
+        $("#username").focus(function () {
+            var firstname = $("#firstname").val();
+            var lastname = $("#lastname").val();
+            if (firstname && lastname && !this.value) {
+                this.value = firstname + "." + lastname;
+            }
+        });
+    });
+    </script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/demo/form/wizard.html b/ruoyi-admin/src/main/resources/templates/demo/form/wizard.html
new file mode 100644
index 0000000..d0b5ee8
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/form/wizard.html
@@ -0,0 +1,339 @@
+<!DOCTYPE html>
+<html lang="zh">
+<head>
+<th:block th:include="include :: header('表单向导')" />
+<th:block th:include="include :: jquery-smartwizard-css" />
+<style type="text/css">
+/* 如果要让工具栏固定在页面底部,使用下面的样式,不需要的可以注释 */
+.sw>.toolbar-bottom{
+	z-index: 100;
+    bottom: 0px;
+    left: 0;
+    width: 100%;
+    position: fixed;
+    text-align: right;
+    background: #fff;
+    box-shadow: 0 -2px 6px 1px hsla(223,8%,83%,.5);
+    border-top: 1px solid #e3e4e8;
+}
+/* 如果设置了是否自动调节高度为false,需要加滚动条 */
+.sw>.tab-content{
+	overflow-x: hidden;
+    overflow-y: auto;
+}
+/* 解决工具栏无法固定底部的问题(如果页面没有animated类可以不写这部分代码) */
+.animated {
+    animation-fill-mode: none;
+    -webkit-animation-fill-mode: none;
+    -moz-animation-fill-mode: none;
+    -o-animation-fill-mode: none;
+}
+</style>
+</head>
+<body class="gray-bg">
+	<div class="wrapper wrapper-content animated fadeInRight" style="height: 100%;">
+		<div class="row">
+			<div class="col-sm-12">
+				<div class="ibox">
+					<div class="ibox-title">
+						<h5>
+							表单向导
+							<small>https://github.com/techlab/jquery-smartwizard</small>
+						</h5>
+					</div>
+					<div class="ibox-content">
+						<div class="row select-list" style="padding-left: 15px; margin-bottom: 10px;">
+							<ul>
+								<li>
+									选择样式:
+									<select id="theme-selector">
+										<option value="default">Default</option>
+										<option value="arrows" selected>Arrows</option>
+										<option value="dots">Dots</option>
+										<option value="progress">Progress</option>
+									</select>
+								</li>
+								<!-- 快速操作栏按钮 -->
+								<li>
+									<div class="btn-group-sm" role="group">
+										<a class="btn btn-info" id="prev-btn"> 上一步 </a>
+										<a class="btn btn-success" id="next-btn"> 下一步 </a>
+										<a class="btn btn-danger" id="reset-btn"> 重置 </a>
+									</div>
+								</li>
+							</ul>
+
+						</div>
+						<div id="smartwizard">
+							<ul class="nav">
+								<li class="nav-item">
+									<a class="nav-link" href="#step-1"> 第一步 </a>
+								</li>
+								<li class="nav-item">
+									<a class="nav-link" href="#step-2"> 第二步 </a>
+								</li>
+								<li class="nav-item">
+									<a class="nav-link" href="#step-3"> 第三步 </a>
+								</li>
+								<li class="nav-item">
+									<a class="nav-link" href="#step-4"> 第四步 </a>
+								</li>
+							</ul>
+							<div class="tab-content">
+								<div id="step-1" class="tab-pane" role="tabpanel" aria-labelledby="step-1">
+									<div>
+										<form class="form form-horizontal m-t">
+											<div class="form-group">
+												<label class="col-sm-3 control-label">姓氏:</label>
+												<div class="col-sm-8">
+													<input id="firstname" name="firstname" class="form-control" type="text">
+													<span class="help-block m-b-none">
+														<i class="fa fa-info-circle"></i>
+														这里写点提示的内容
+													</span>
+												</div>
+											</div>
+											<div class="form-group">
+												<label class="col-sm-3 control-label is-required">名字:</label>
+												<div class="col-sm-8">
+													<input id="lastname" name="lastname" class="form-control" type="text" required>
+												</div>
+											</div>
+											<div class="form-group">
+												<label class="col-sm-3 control-label is-required">用户名:</label>
+												<div class="col-sm-8">
+													<input id="username" name="username" class="form-control" type="text" required>
+												</div>
+											</div>
+											<div class="form-group">
+												<label class="col-sm-3 control-label">密码:</label>
+												<div class="col-sm-8">
+													<input id="password" name="password" class="form-control" type="password">
+												</div>
+											</div>
+											<div class="form-group">
+												<label class="col-sm-3 control-label">确认密码:</label>
+												<div class="col-sm-8">
+													<input id="confirm_password" name="confirm_password" class="form-control" type="password">
+													<span class="help-block m-b-none">
+														<i class="fa fa-info-circle"></i>
+														请再次输入您的密码
+													</span>
+												</div>
+											</div>
+											<div class="form-group">
+												<label class="col-sm-3 control-label">E-mail:</label>
+												<div class="col-sm-8">
+													<input id="email" name="email" class="form-control" type="email">
+												</div>
+											</div>
+										</form>
+									</div>
+								</div>
+								<div id="step-2" class="tab-pane" role="tabpanel" aria-labelledby="step-2">
+									<div>
+										<form class="form form-horizontal m-t">
+											<div class="form-group">
+												<label class="col-sm-3 control-label">性别:</label>
+												<div class="col-sm-8">
+													<select name="sex" class="form-control m-b" th:with="type=${@dict.getType('sys_user_sex')}">
+				                						<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
+				            						</select>
+												</div>
+											</div>
+											<div class="form-group">
+												<label class="col-sm-3 control-label">时间:</label>
+												<div class="col-sm-8">
+													<input id="time" name="time" class="form-control time-input" type="text">
+												</div>
+											</div>
+											<div class="form-group">
+												<label class="col-sm-3 control-label">状态:</label>
+												<div class="col-sm-8">
+													<div class="radio-box" th:each="dict : ${@dict.getType('sys_normal_disable')}">
+														<input type="radio" th:id="${dict.dictCode}" name="status" th:value="${dict.dictValue}" th:checked="${dict.default}">
+														<label th:for="${dict.dictCode}" th:text="${dict.dictLabel}"></label>
+													</div>
+												</div>
+											</div>
+										</form>
+									</div>
+								</div>
+								<div id="step-3" class="tab-pane" role="tabpanel" aria-labelledby="step-3">
+									<div class="m-t-md">
+										<p>1、如果不需要工具栏固定在页面底部, 将style中下面的部分取消注释<blockquote>.sw>.toolbar-bottom </blockquote></p>
+										<p>2、如果设置了自动调节高度(autoAdjustHeight)为true, 将style中下面的部分取消注释<blockquote>.sw>.tab-content </blockquote></p>
+										<p>3、工具栏的按钮样式会被表单插件中.btn样式覆盖导致bootstrap中的按钮样式无效, 如果需要改变按钮样式可以自己定义并提高优先级</blockquote></p>
+									</div>
+								</div>
+								<div id="step-4" class="tab-pane" role="tabpanel" aria-labelledby="step-4">
+									<div class="m-t-md">
+										<h3>测试多行显示</h3>
+										<pre style="overflow-x: hidden;">
+$('#smartwizard').smartWizard({
+  selected: 0, // Initial selected step, 0 = first step
+  theme: 'default', // theme for the wizard, related css need to include for other than default theme
+  justified: true, // Nav menu justification. true/false
+  darkMode:false, // Enable/disable Dark Mode if the theme supports. true/false
+  autoAdjustHeight: true, // Automatically adjust content height
+  cycleSteps: false, // Allows to cycle the navigation of steps
+  backButtonSupport: true, // Enable the back button support
+  enableURLhash: true, // Enable selection of the step based on url hash
+  transition: {
+      animation: 'none', // Effect on navigation, none/fade/slide-horizontal/slide-vertical/slide-swing
+      speed: '400', // Transition animation speed
+      easing:'' // Transition animation easing. Not supported without a jQuery easing plugin
+  },
+  toolbarSettings: {
+      toolbarPosition: 'bottom', // none, top, bottom, both
+      toolbarButtonPosition: 'right', // left, right, center
+      showNextButton: true, // show/hide a Next button
+      showPreviousButton: true, // show/hide a Previous button
+      toolbarExtraButtons: [] // Extra buttons to show on toolbar, array of jQuery input/buttons elements
+  },
+  anchorSettings: {
+      anchorClickable: true, // Enable/Disable anchor navigation
+      enableAllAnchors: false, // Activates all anchors clickable all times
+      markDoneStep: true, // Add done state on navigation
+      markAllPreviousStepsAsDone: true, // When a step selected by url hash, all previous steps are marked done
+      removeDoneStepOnNavigateBack: false, // While navigate back done step after active step will be cleared
+      enableAnchorOnDoneStep: true // Enable/Disable the done steps navigation
+  },
+  keyboardSettings: {
+      keyNavigation: true, // Enable/Disable keyboard navigation(left and right keys are used if enabled)
+      keyLeft: [37], // Left key code
+      keyRight: [39] // Right key code
+  },
+  lang: { // Language variables for button
+      next: 'Next',
+      previous: 'Previous'
+  },
+  disabledSteps: [], // Array Steps disabled
+  errorSteps: [], // Highlight step with errors
+  hiddenSteps: [] // Hidden steps
+});
+										</pre>
+									</div>
+								</div>
+							</div>
+						</div>
+					</div>
+				</div>
+			</div>
+
+		</div>
+	</div>
+	<th:block th:include="include :: footer" />
+	<th:block th:include="include :: jquery-smartwizard-js" />
+	<script>
+		$(document).ready(function() {
+			// 工具栏按钮
+            var btnFinish = $('<a id="btn-finish"></a>').text('完成')
+                                             .addClass('btn btn-info')
+                                             .on('click', function(){ submit(); });
+            var btnCancel = $('<a id="btn-cancel"></a>').text('取消')
+                                             .addClass('btn btn-danger')
+                                             .on('click', function(){ $('#smartwizard').smartWizard("reset"); });
+           	// 下面两个按钮是为了因为插件默认的是botton,这里换成<a>,也可以选择用样式替换,或者不替换
+            var btnNext = $('<a id="btn-next"></a>').text('下一步')
+											 .addClass('btn btn-info')
+											 .on('click', function(){ $('#smartwizard').smartWizard("next");});
+			var btnPrev = $('<a id="btn-prev"></a>').text('上一步')
+											 .addClass('btn btn-success disabled')
+											 .on('click', function(){ $('#smartwizard').smartWizard("prev"); });
+            // 初始化表单向导组件
+            $('#smartwizard').smartWizard({
+                theme: 'arrows', // default, arrows, dots, progress
+                autoAdjustHeight : false, // 自动调整高度, 默认true
+                enableURLhash:false, //开启URL hash,开启后点击浏览器前进后退按钮会执行下一步和上一步操作
+                transition: {
+                    animation: 'slide-horizontal', // Effect on navigation, none/fade/slide-horizontal/slide-vertical/slide-swing
+                },
+                toolbarSettings: {
+                	showNextButton: false,// 因为上面自定义了下一步按钮, 所以隐藏掉插件自带的按钮, 如果不使用自定义按钮, 需要改为true或者去掉该属性
+    				showPreviousButton: false,// 因为上面自定义了上一步按钮, 所以隐藏掉插件自带的按钮, 如果不使用自定义按钮, 需要改为true或者去掉该属性
+                    toolbarExtraButtons: [btnCancel,btnPrev,btnNext,btnFinish]// 扩展的按钮集合
+                }
+            });
+		});
+		
+		function submit(){
+			var data = {};
+			$('.form').each(function (index, form){
+				// 这里可以使用$.common.formToJSON(formId);  需要在form上加id
+                $.each($(form).serializeArray(), function(i, field) {
+                 	 if(data[field.name]) {
+                 		data[field.name] += ("," + field.value);
+					 } else {
+						data[field.name] = field.value;
+                     }
+                });
+			});
+			alert(JSON.stringify(data))
+		}
+		// 显示步骤时将触发事件
+        $("#smartwizard").on("showStep", function(e, anchorObject, stepNumber, stepDirection, stepPosition) {
+        	// 下面按钮是快速操作栏的
+        	$("#prev-btn").removeClass('disabled');
+            $("#next-btn").removeClass('disabled');
+        	// 下面按钮是工具栏的
+        	$("#btn-prev").removeClass('disabled');
+            $("#btn-next").removeClass('disabled');
+            $("#btn-finish").removeClass('disabled');
+            if(stepPosition === 'first') {
+            	$("#prev-btn").addClass('disabled');// 快速操作栏(演示用)
+            	$("#btn-prev").addClass('disabled');
+				$("#btn-finish").addClass('disabled');
+            } else if(stepPosition === 'last') {
+            	$("#next-btn").addClass('disabled');// 快速操作栏(演示用)
+                $("#btn-next").addClass('disabled');
+            } else {
+            	$("#prev-btn").removeClass('disabled');// 快速操作栏(演示用)
+                $("#next-btn").removeClass('disabled');// 快速操作栏(演示用)
+                $("#btn-prev").removeClass('disabled');
+                $("#btn-next").removeClass('disabled');
+                $("#btn-finish").addClass('disabled');
+            }
+        });
+		
+		// 该事件在离开某个步骤之前触发
+		$("#smartwizard").on("leaveStep", function(e, anchorObject, currentStepNumber, nextStepNumber, stepDirection) {
+			if(stepDirection == 'forward'){
+				var form = $("#step-" + (currentStepNumber + 1)).find('.form');
+				if(form.length > 0){
+					return form.validate().form();
+				}
+				return true;
+			}
+			return true;
+		});
+		
+		$("#theme-selector").on("change", function() {
+			// Change theme
+			var options = {
+				theme : $(this).val()
+			};
+			$('#smartwizard').smartWizard("setOptions", options);
+			return true;
+		});
+
+		$("#reset-btn").on("click", function() {
+            // Reset wizard
+            $('#smartwizard').smartWizard("reset");
+            return true;
+        });
+
+        $("#prev-btn").on("click", function() {
+            // Navigate previous
+            $('#smartwizard').smartWizard("prev");
+            return true;
+        });
+
+        $("#next-btn").on("click", function() {
+            // Navigate next
+            $('#smartwizard').smartWizard("next");
+            return true;
+        });
+	</script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/demo/icon/fontawesome.html b/ruoyi-admin/src/main/resources/templates/demo/icon/fontawesome.html
new file mode 100644
index 0000000..cac5b72
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/icon/fontawesome.html
@@ -0,0 +1,1054 @@
+<!DOCTYPE html>
+<html lang="zh">
+<head>
+	<th:block th:include="include :: header('fontawesome图标')" />
+	<style type="text/css">
+		.fontawesome-icon-list .fa-hover{cursor:pointer;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block;color:#222222;line-height:32px;height:32px;padding-left:10px;border-radius:4px;}
+		.fontawesome-icon-list .fa-hover .fa{width:32px;font-size:14px;display:inline-block;text-align:right;margin-right:10px}
+		.fontawesome-icon-list .fa-hover:hover{background-color:#1d9d74;color:#fff;text-decoration:none}
+		.fontawesome-icon-list .fa-hover:hover .fa{font-size:30px !important;vertical-align:-6px}
+		.fontawesome-icon-list .fa-hover .text-muted{color:#bbe2d5}
+	</style>
+</head>
+<body class="gray-bg">
+    <div class="wrapper wrapper-content animated fadeInRight">
+        <div class="row">
+            <div class="col-sm-12">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>所有图标 <small class="m-l-sm">所有图标集合 - <a target="_blank" href="http://fortawesome.github.io/Font-Awesome/icons/">Font Awesome</a> </small></h5>
+                        <div class="ibox-tools">
+                            <a class="collapse-link">
+                                <i class="fa fa-chevron-up"></i>
+                            </a>
+                            <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                                <i class="fa fa-wrench"></i>
+                            </a>
+                            <ul class="dropdown-menu dropdown-user">
+                                <li><a href="javascript:;">选项1</a>
+                                </li>
+                                <li><a href="javascript:;">选项2</a>
+                                </li>
+                            </ul>
+                            <a class="close-link">
+                                <i class="fa fa-times"></i>
+                            </a>
+                        </div>
+                    </div>
+                    <div class="ibox-content icons-box">
+	                    <section id="web-application">
+	                        <h2 class="page-header">Web应用程序图标</h2>
+	                        <div class="row fontawesome-icon-list">
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-address-book" aria-hidden="true"></i>address-book</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-address-book-o" aria-hidden="true"></i>address-book-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-address-card" aria-hidden="true"></i>address-card</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-address-card-o" aria-hidden="true"></i>address-card-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-adjust" aria-hidden="true"></i>adjust</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-american-sign-language-interpreting" aria-hidden="true"></i>american-sign-language-interpreting</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-anchor" aria-hidden="true"></i>anchor</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-archive" aria-hidden="true"></i>archive</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-area-chart" aria-hidden="true"></i>area-chart</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-arrows" aria-hidden="true"></i>arrows</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-arrows-h" aria-hidden="true"></i>arrows-h</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-arrows-v" aria-hidden="true"></i>arrows-v</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-asl-interpreting" aria-hidden="true"></i>asl-interpreting <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-assistive-listening-systems" aria-hidden="true"></i>assistive-listening-systems</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-asterisk" aria-hidden="true"></i>asterisk</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-at" aria-hidden="true"></i>at</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-audio-description" aria-hidden="true"></i>audio-description</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-automobile" aria-hidden="true"></i>automobile <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-balance-scale" aria-hidden="true"></i>balance-scale</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-ban" aria-hidden="true"></i>ban</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-bank" aria-hidden="true"></i>bank <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-bar-chart" aria-hidden="true"></i>bar-chart</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-bar-chart-o" aria-hidden="true"></i>bar-chart-o <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-barcode" aria-hidden="true"></i>barcode</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-bars" aria-hidden="true"></i>bars</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-bath" aria-hidden="true"></i>bath</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-bathtub" aria-hidden="true"></i>bathtub <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-battery" aria-hidden="true"></i>battery <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-battery-0" aria-hidden="true"></i>battery-0 <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-battery-1" aria-hidden="true"></i>battery-1 <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-battery-2" aria-hidden="true"></i>battery-2 <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-battery-3" aria-hidden="true"></i>battery-3 <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-battery-4" aria-hidden="true"></i>battery-4 <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-battery-empty" aria-hidden="true"></i>battery-empty</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-battery-full" aria-hidden="true"></i>battery-full</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-battery-half" aria-hidden="true"></i>battery-half</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-battery-quarter" aria-hidden="true"></i>battery-quarter</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-battery-three-quarters" aria-hidden="true"></i>battery-three-quarters</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-bed" aria-hidden="true"></i>bed</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-beer" aria-hidden="true"></i>beer</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-bell" aria-hidden="true"></i>bell</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-bell-o" aria-hidden="true"></i>bell-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-bell-slash" aria-hidden="true"></i>bell-slash</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-bell-slash-o" aria-hidden="true"></i>bell-slash-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-bicycle" aria-hidden="true"></i>bicycle</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-binoculars" aria-hidden="true"></i>binoculars</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-birthday-cake" aria-hidden="true"></i> birthday-cake</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-blind" aria-hidden="true"></i> blind</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-bluetooth" aria-hidden="true"></i> bluetooth</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-bluetooth-b" aria-hidden="true"></i> bluetooth-b</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-bolt" aria-hidden="true"></i> bolt</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-bomb" aria-hidden="true"></i> bomb</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-book" aria-hidden="true"></i> book</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-bookmark" aria-hidden="true"></i> bookmark</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-bookmark-o" aria-hidden="true"></i> bookmark-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-braille" aria-hidden="true"></i> braille</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-briefcase" aria-hidden="true"></i> briefcase</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-bug" aria-hidden="true"></i> bug</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-building" aria-hidden="true"></i> building</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-building-o" aria-hidden="true"></i> building-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-bullhorn" aria-hidden="true"></i> bullhorn</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-bullseye" aria-hidden="true"></i> bullseye</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-bus" aria-hidden="true"></i> bus</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-cab" aria-hidden="true"></i> cab <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-calculator" aria-hidden="true"></i> calculator</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-calendar" aria-hidden="true"></i> calendar</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-calendar-check-o" aria-hidden="true"></i> calendar-check-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-calendar-minus-o" aria-hidden="true"></i> calendar-minus-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-calendar-o" aria-hidden="true"></i> calendar-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-calendar-plus-o" aria-hidden="true"></i> calendar-plus-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-calendar-times-o" aria-hidden="true"></i> calendar-times-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-camera" aria-hidden="true"></i> camera</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-camera-retro" aria-hidden="true"></i> camera-retro</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-car" aria-hidden="true"></i> car</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-caret-square-o-down" aria-hidden="true"></i> caret-square-o-down</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-caret-square-o-left" aria-hidden="true"></i> caret-square-o-left</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-caret-square-o-right" aria-hidden="true"></i> caret-square-o-right</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-caret-square-o-up" aria-hidden="true"></i> caret-square-o-up</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-cart-arrow-down" aria-hidden="true"></i> cart-arrow-down</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-cart-plus" aria-hidden="true"></i> cart-plus</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-cc" aria-hidden="true"></i> cc</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-certificate" aria-hidden="true"></i> certificate</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-check" aria-hidden="true"></i> check</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-check-circle" aria-hidden="true"></i> check-circle</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-check-circle-o" aria-hidden="true"></i> check-circle-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-check-square" aria-hidden="true"></i> check-square</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-check-square-o" aria-hidden="true"></i> check-square-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-child" aria-hidden="true"></i> child</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-circle" aria-hidden="true"></i> circle</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-circle-o" aria-hidden="true"></i> circle-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-circle-o-notch" aria-hidden="true"></i> circle-o-notch</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-circle-thin" aria-hidden="true"></i> circle-thin</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-clock-o" aria-hidden="true"></i> clock-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-clone" aria-hidden="true"></i> clone</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-close" aria-hidden="true"></i> close <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-cloud" aria-hidden="true"></i> cloud</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-cloud-download" aria-hidden="true"></i> cloud-download</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-cloud-upload" aria-hidden="true"></i> cloud-upload</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-code" aria-hidden="true"></i> code</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-code-fork" aria-hidden="true"></i> code-fork</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-coffee" aria-hidden="true"></i> coffee</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-cog" aria-hidden="true"></i> cog</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-cogs" aria-hidden="true"></i> cogs</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-comment" aria-hidden="true"></i> comment</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-comment-o" aria-hidden="true"></i> comment-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-commenting" aria-hidden="true"></i> commenting</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-commenting-o" aria-hidden="true"></i> commenting-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-comments" aria-hidden="true"></i> comments</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-comments-o" aria-hidden="true"></i> comments-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-compass" aria-hidden="true"></i> compass</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-copyright" aria-hidden="true"></i> copyright</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-creative-commons" aria-hidden="true"></i> creative-commons</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-credit-card" aria-hidden="true"></i> credit-card</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-credit-card-alt" aria-hidden="true"></i> credit-card-alt</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-crop" aria-hidden="true"></i> crop</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-crosshairs" aria-hidden="true"></i> crosshairs</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-cube" aria-hidden="true"></i> cube</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-cubes" aria-hidden="true"></i> cubes</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-cutlery" aria-hidden="true"></i> cutlery</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-dashboard" aria-hidden="true"></i> dashboard <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-database" aria-hidden="true"></i> database</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-deaf" aria-hidden="true"></i> deaf</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-deafness" aria-hidden="true"></i> deafness <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-desktop" aria-hidden="true"></i> desktop</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-diamond" aria-hidden="true"></i> diamond</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-dot-circle-o" aria-hidden="true"></i> dot-circle-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-download" aria-hidden="true"></i> download</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-drivers-license" aria-hidden="true"></i> drivers-license <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-drivers-license-o" aria-hidden="true"></i> drivers-license-o <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-edit" aria-hidden="true"></i> edit <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-ellipsis-h" aria-hidden="true"></i> ellipsis-h</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-ellipsis-v" aria-hidden="true"></i> ellipsis-v</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-envelope" aria-hidden="true"></i> envelope</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-envelope-o" aria-hidden="true"></i> envelope-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-envelope-open" aria-hidden="true"></i> envelope-open</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-envelope-open-o" aria-hidden="true"></i> envelope-open-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-envelope-square" aria-hidden="true"></i> envelope-square</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-eraser" aria-hidden="true"></i> eraser</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-exchange" aria-hidden="true"></i> exchange</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-exclamation" aria-hidden="true"></i> exclamation</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-exclamation-circle" aria-hidden="true"></i> exclamation-circle</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-exclamation-triangle" aria-hidden="true"></i> exclamation-triangle</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-external-link" aria-hidden="true"></i> external-link</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-external-link-square" aria-hidden="true"></i> external-link-square</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-eye" aria-hidden="true"></i> eye</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-eye-slash" aria-hidden="true"></i> eye-slash</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-eyedropper" aria-hidden="true"></i> eyedropper</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-fax" aria-hidden="true"></i> fax</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-feed" aria-hidden="true"></i> feed <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-female" aria-hidden="true"></i> female</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-fighter-jet" aria-hidden="true"></i> fighter-jet</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-file-archive-o" aria-hidden="true"></i> file-archive-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-file-audio-o" aria-hidden="true"></i> file-audio-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-file-code-o" aria-hidden="true"></i> file-code-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-file-excel-o" aria-hidden="true"></i> file-excel-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-file-image-o" aria-hidden="true"></i> file-image-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-file-movie-o" aria-hidden="true"></i> file-movie-o <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-file-pdf-o" aria-hidden="true"></i> file-pdf-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-file-photo-o" aria-hidden="true"></i> file-photo-o <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-file-picture-o" aria-hidden="true"></i> file-picture-o <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-file-powerpoint-o" aria-hidden="true"></i> file-powerpoint-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-file-sound-o" aria-hidden="true"></i> file-sound-o <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-file-video-o" aria-hidden="true"></i> file-video-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-file-word-o" aria-hidden="true"></i> file-word-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-file-zip-o" aria-hidden="true"></i> file-zip-o <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-film" aria-hidden="true"></i> film</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-filter" aria-hidden="true"></i> filter</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-fire" aria-hidden="true"></i> fire</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-fire-extinguisher" aria-hidden="true"></i> fire-extinguisher</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-flag" aria-hidden="true"></i> flag</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-flag-checkered" aria-hidden="true"></i> flag-checkered</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-flag-o" aria-hidden="true"></i> flag-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-flash" aria-hidden="true"></i> flash <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-flask" aria-hidden="true"></i> flask</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-folder" aria-hidden="true"></i> folder</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-folder-o" aria-hidden="true"></i> folder-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-folder-open" aria-hidden="true"></i> folder-open</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-folder-open-o" aria-hidden="true"></i> folder-open-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-frown-o" aria-hidden="true"></i> frown-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-futbol-o" aria-hidden="true"></i> futbol-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-gamepad" aria-hidden="true"></i> gamepad</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-gavel" aria-hidden="true"></i> gavel</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-gear" aria-hidden="true"></i> gear <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-gears" aria-hidden="true"></i> gears <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-gift" aria-hidden="true"></i> gift</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-glass" aria-hidden="true"></i> glass</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-globe" aria-hidden="true"></i> globe</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-graduation-cap" aria-hidden="true"></i> graduation-cap</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-group" aria-hidden="true"></i> group <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-hand-grab-o" aria-hidden="true"></i> hand-grab-o <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-hand-lizard-o" aria-hidden="true"></i> hand-lizard-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-hand-paper-o" aria-hidden="true"></i> hand-paper-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-hand-peace-o" aria-hidden="true"></i> hand-peace-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-hand-pointer-o" aria-hidden="true"></i> hand-pointer-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-hand-rock-o" aria-hidden="true"></i> hand-rock-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-hand-scissors-o" aria-hidden="true"></i> hand-scissors-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-hand-spock-o" aria-hidden="true"></i> hand-spock-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-hand-stop-o" aria-hidden="true"></i> hand-stop-o <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-handshake-o" aria-hidden="true"></i> handshake-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-hard-of-hearing" aria-hidden="true"></i> hard-of-hearing <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-hashtag" aria-hidden="true"></i> hashtag</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-hdd-o" aria-hidden="true"></i> hdd-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-headphones" aria-hidden="true"></i> headphones</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-heart" aria-hidden="true"></i> heart</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-heart-o" aria-hidden="true"></i> heart-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-heartbeat" aria-hidden="true"></i> heartbeat</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-history" aria-hidden="true"></i> history</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-home" aria-hidden="true"></i> home</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-hotel" aria-hidden="true"></i> hotel <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-hourglass" aria-hidden="true"></i> hourglass</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-hourglass-1" aria-hidden="true"></i> hourglass-1 <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-hourglass-2" aria-hidden="true"></i> hourglass-2 <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-hourglass-3" aria-hidden="true"></i> hourglass-3 <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-hourglass-end" aria-hidden="true"></i> hourglass-end</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-hourglass-half" aria-hidden="true"></i> hourglass-half</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-hourglass-o" aria-hidden="true"></i> hourglass-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-hourglass-start" aria-hidden="true"></i> hourglass-start</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-i-cursor" aria-hidden="true"></i> i-cursor</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-id-badge" aria-hidden="true"></i> id-badge</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-id-card" aria-hidden="true"></i> id-card</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-id-card-o" aria-hidden="true"></i> id-card-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-image" aria-hidden="true"></i> image <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-inbox" aria-hidden="true"></i> inbox</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-industry" aria-hidden="true"></i> industry</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-info" aria-hidden="true"></i> info</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-info-circle" aria-hidden="true"></i> info-circle</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-institution" aria-hidden="true"></i> institution <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-key" aria-hidden="true"></i> key</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-keyboard-o" aria-hidden="true"></i> keyboard-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-language" aria-hidden="true"></i> language</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-laptop" aria-hidden="true"></i> laptop</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-leaf" aria-hidden="true"></i> leaf</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-legal" aria-hidden="true"></i> legal <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-lemon-o" aria-hidden="true"></i> lemon-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-level-down" aria-hidden="true"></i> level-down</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-level-up" aria-hidden="true"></i> level-up</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-life-bouy" aria-hidden="true"></i> life-bouy <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-life-buoy" aria-hidden="true"></i> life-buoy <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-life-ring" aria-hidden="true"></i> life-ring</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-life-saver" aria-hidden="true"></i> life-saver <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-lightbulb-o" aria-hidden="true"></i> lightbulb-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-line-chart" aria-hidden="true"></i> line-chart</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-location-arrow" aria-hidden="true"></i> location-arrow</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-lock" aria-hidden="true"></i> lock</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-low-vision" aria-hidden="true"></i> low-vision</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-magic" aria-hidden="true"></i> magic</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-magnet" aria-hidden="true"></i> magnet</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-mail-forward" aria-hidden="true"></i> mail-forward <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-mail-reply" aria-hidden="true"></i> mail-reply <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-mail-reply-all" aria-hidden="true"></i> mail-reply-all <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-male" aria-hidden="true"></i> male</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-map" aria-hidden="true"></i> map</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-map-marker" aria-hidden="true"></i> map-marker</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-map-o" aria-hidden="true"></i> map-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-map-pin" aria-hidden="true"></i> map-pin</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-map-signs" aria-hidden="true"></i> map-signs</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-meh-o" aria-hidden="true"></i> meh-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-microchip" aria-hidden="true"></i> microchip</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-microphone" aria-hidden="true"></i> microphone</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-microphone-slash" aria-hidden="true"></i> microphone-slash</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-minus" aria-hidden="true"></i> minus</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-minus-circle" aria-hidden="true"></i> minus-circle</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-minus-square" aria-hidden="true"></i> minus-square</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-minus-square-o" aria-hidden="true"></i> minus-square-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-mobile" aria-hidden="true"></i> mobile</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-mobile-phone" aria-hidden="true"></i> mobile-phone <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-money" aria-hidden="true"></i> money</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-moon-o" aria-hidden="true"></i> moon-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-mortar-board" aria-hidden="true"></i> mortar-board <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-motorcycle" aria-hidden="true"></i> motorcycle</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-mouse-pointer" aria-hidden="true"></i> mouse-pointer</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-music" aria-hidden="true"></i> music</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-navicon" aria-hidden="true"></i> navicon <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-newspaper-o" aria-hidden="true"></i> newspaper-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-object-group" aria-hidden="true"></i> object-group</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-object-ungroup" aria-hidden="true"></i> object-ungroup</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-paint-brush" aria-hidden="true"></i> paint-brush</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-paper-plane" aria-hidden="true"></i> paper-plane</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-paper-plane-o" aria-hidden="true"></i> paper-plane-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-paw" aria-hidden="true"></i> paw</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-pencil" aria-hidden="true"></i> pencil</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-pencil-square" aria-hidden="true"></i> pencil-square</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-pencil-square-o" aria-hidden="true"></i> pencil-square-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-percent" aria-hidden="true"></i> percent</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-phone" aria-hidden="true"></i> phone</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-phone-square" aria-hidden="true"></i> phone-square</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-photo" aria-hidden="true"></i> photo <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-picture-o" aria-hidden="true"></i> picture-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-pie-chart" aria-hidden="true"></i> pie-chart</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-plane" aria-hidden="true"></i> plane</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-plug" aria-hidden="true"></i> plug</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-plus" aria-hidden="true"></i> plus</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-plus-circle" aria-hidden="true"></i> plus-circle</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-plus-square" aria-hidden="true"></i> plus-square</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-plus-square-o" aria-hidden="true"></i> plus-square-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-podcast" aria-hidden="true"></i> podcast</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-power-off" aria-hidden="true"></i> power-off</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-print" aria-hidden="true"></i> print</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-puzzle-piece" aria-hidden="true"></i> puzzle-piece</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-qrcode" aria-hidden="true"></i> qrcode</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-question" aria-hidden="true"></i> question</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-question-circle" aria-hidden="true"></i> question-circle</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-question-circle-o" aria-hidden="true"></i> question-circle-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-quote-left" aria-hidden="true"></i> quote-left</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-quote-right" aria-hidden="true"></i> quote-right</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-random" aria-hidden="true"></i> random</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-recycle" aria-hidden="true"></i> recycle</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-refresh" aria-hidden="true"></i> refresh</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-registered" aria-hidden="true"></i> registered</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-remove" aria-hidden="true"></i> remove <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-reorder" aria-hidden="true"></i> reorder <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-reply" aria-hidden="true"></i> reply</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-reply-all" aria-hidden="true"></i> reply-all</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-retweet" aria-hidden="true"></i> retweet</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-road" aria-hidden="true"></i> road</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-rocket" aria-hidden="true"></i> rocket</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-rss" aria-hidden="true"></i> rss</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-rss-square" aria-hidden="true"></i> rss-square</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-s15" aria-hidden="true"></i> s15 <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-search" aria-hidden="true"></i> search</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-search-minus" aria-hidden="true"></i> search-minus</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-search-plus" aria-hidden="true"></i> search-plus</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-send" aria-hidden="true"></i> send <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-send-o" aria-hidden="true"></i> send-o <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-server" aria-hidden="true"></i> server</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-share" aria-hidden="true"></i> share</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-share-alt" aria-hidden="true"></i> share-alt</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-share-alt-square" aria-hidden="true"></i> share-alt-square</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-share-square" aria-hidden="true"></i> share-square</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-share-square-o" aria-hidden="true"></i> share-square-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-shield" aria-hidden="true"></i> shield</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-ship" aria-hidden="true"></i> ship</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-shopping-bag" aria-hidden="true"></i> shopping-bag</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-shopping-basket" aria-hidden="true"></i> shopping-basket</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-shopping-cart" aria-hidden="true"></i> shopping-cart</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-shower" aria-hidden="true"></i> shower</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-sign-in" aria-hidden="true"></i> sign-in</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-sign-language" aria-hidden="true"></i> sign-language</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-sign-out" aria-hidden="true"></i> sign-out</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-signal" aria-hidden="true"></i> signal</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-signing" aria-hidden="true"></i> signing <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-sitemap" aria-hidden="true"></i> sitemap</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-sliders" aria-hidden="true"></i> sliders</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-smile-o" aria-hidden="true"></i> smile-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-snowflake-o" aria-hidden="true"></i> snowflake-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-soccer-ball-o" aria-hidden="true"></i> soccer-ball-o <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-sort" aria-hidden="true"></i> sort</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-sort-alpha-asc" aria-hidden="true"></i> sort-alpha-asc</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-sort-alpha-desc" aria-hidden="true"></i> sort-alpha-desc</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-sort-amount-asc" aria-hidden="true"></i> sort-amount-asc</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-sort-amount-desc" aria-hidden="true"></i> sort-amount-desc</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-sort-asc" aria-hidden="true"></i> sort-asc</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-sort-desc" aria-hidden="true"></i> sort-desc</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-sort-down" aria-hidden="true"></i> sort-down <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-sort-numeric-asc" aria-hidden="true"></i> sort-numeric-asc</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-sort-numeric-desc" aria-hidden="true"></i> sort-numeric-desc</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-sort-up" aria-hidden="true"></i> sort-up <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-space-shuttle" aria-hidden="true"></i> space-shuttle</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-spinner" aria-hidden="true"></i> spinner</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-spoon" aria-hidden="true"></i> spoon</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-square" aria-hidden="true"></i> square</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-square-o" aria-hidden="true"></i> square-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-star" aria-hidden="true"></i> star</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-star-half" aria-hidden="true"></i> star-half</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-star-half-empty" aria-hidden="true"></i> star-half-empty <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-star-half-full" aria-hidden="true"></i> star-half-full <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-star-half-o" aria-hidden="true"></i> star-half-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-star-o" aria-hidden="true"></i> star-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-sticky-note" aria-hidden="true"></i> sticky-note</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-sticky-note-o" aria-hidden="true"></i> sticky-note-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-street-view" aria-hidden="true"></i> street-view</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-suitcase" aria-hidden="true"></i> suitcase</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-sun-o" aria-hidden="true"></i> sun-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-support" aria-hidden="true"></i> support <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-tablet" aria-hidden="true"></i> tablet</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-tachometer" aria-hidden="true"></i> tachometer</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-tag" aria-hidden="true"></i> tag</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-tags" aria-hidden="true"></i> tags</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-tasks" aria-hidden="true"></i> tasks</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-taxi" aria-hidden="true"></i> taxi</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-television" aria-hidden="true"></i> television</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-terminal" aria-hidden="true"></i> terminal</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-thermometer" aria-hidden="true"></i> thermometer <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-thermometer-0" aria-hidden="true"></i> thermometer-0 <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-thermometer-1" aria-hidden="true"></i> thermometer-1 <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-thermometer-2" aria-hidden="true"></i> thermometer-2 <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-thermometer-3" aria-hidden="true"></i> thermometer-3 <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-thermometer-4" aria-hidden="true"></i> thermometer-4 <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-thermometer-empty" aria-hidden="true"></i> thermometer-empty</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-thermometer-full" aria-hidden="true"></i> thermometer-full</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-thermometer-half" aria-hidden="true"></i> thermometer-half</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-thermometer-quarter" aria-hidden="true"></i> thermometer-quarter</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-thermometer-three-quarters" aria-hidden="true"></i> thermometer-three-quarters</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-thumb-tack" aria-hidden="true"></i> thumb-tack</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-thumbs-down" aria-hidden="true"></i> thumbs-down</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-thumbs-o-down" aria-hidden="true"></i> thumbs-o-down</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-thumbs-o-up" aria-hidden="true"></i> thumbs-o-up</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-thumbs-up" aria-hidden="true"></i> thumbs-up</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-ticket" aria-hidden="true"></i> ticket</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-times" aria-hidden="true"></i> times</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-times-circle" aria-hidden="true"></i> times-circle</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-times-circle-o" aria-hidden="true"></i> times-circle-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-times-rectangle" aria-hidden="true"></i> times-rectangle <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-times-rectangle-o" aria-hidden="true"></i> times-rectangle-o <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-tint" aria-hidden="true"></i> tint</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-toggle-down" aria-hidden="true"></i> toggle-down <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-toggle-left" aria-hidden="true"></i> toggle-left <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-toggle-off" aria-hidden="true"></i> toggle-off</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-toggle-on" aria-hidden="true"></i> toggle-on</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-toggle-right" aria-hidden="true"></i> toggle-right <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-toggle-up" aria-hidden="true"></i> toggle-up <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-trademark" aria-hidden="true"></i> trademark</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-trash" aria-hidden="true"></i> trash</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-trash-o" aria-hidden="true"></i> trash-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-tree" aria-hidden="true"></i> tree</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-trophy" aria-hidden="true"></i> trophy</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-truck" aria-hidden="true"></i> truck</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-tty" aria-hidden="true"></i> tty</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-tv" aria-hidden="true"></i> tv <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-umbrella" aria-hidden="true"></i> umbrella</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-universal-access" aria-hidden="true"></i> universal-access</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-university" aria-hidden="true"></i> university</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-unlock" aria-hidden="true"></i> unlock</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-unlock-alt" aria-hidden="true"></i> unlock-alt</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-unsorted" aria-hidden="true"></i> unsorted <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-upload" aria-hidden="true"></i> upload</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-user" aria-hidden="true"></i> user</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-user-circle" aria-hidden="true"></i> user-circle</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-user-circle-o" aria-hidden="true"></i> user-circle-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-user-o" aria-hidden="true"></i> user-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-user-plus" aria-hidden="true"></i> user-plus</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-user-secret" aria-hidden="true"></i> user-secret</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-user-times" aria-hidden="true"></i> user-times</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-users" aria-hidden="true"></i> users</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-vcard" aria-hidden="true"></i> vcard <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-vcard-o" aria-hidden="true"></i> vcard-o <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-video-camera" aria-hidden="true"></i> video-camera</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-volume-control-phone" aria-hidden="true"></i> volume-control-phone</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-volume-down" aria-hidden="true"></i> volume-down</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-volume-off" aria-hidden="true"></i> volume-off</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-volume-up" aria-hidden="true"></i> volume-up</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-warning" aria-hidden="true"></i> warning <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-wheelchair" aria-hidden="true"></i> wheelchair</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-wheelchair-alt" aria-hidden="true"></i> wheelchair-alt</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-wifi" aria-hidden="true"></i> wifi</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-window-close" aria-hidden="true"></i> window-close</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-window-close-o" aria-hidden="true"></i> window-close-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-window-maximize" aria-hidden="true"></i> window-maximize</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-window-minimize" aria-hidden="true"></i> window-minimize</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-window-restore" aria-hidden="true"></i> window-restore</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-wrench" aria-hidden="true"></i> wrench</div>
+	                        </div>
+	                    </section>
+	                    <section id="accessibility">
+	                        <h2 class="page-header">辅助图标</h2>
+	                        <div class="row fontawesome-icon-list">
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-american-sign-language-interpreting" aria-hidden="true"></i> american-sign-language-interpreting</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-asl-interpreting" aria-hidden="true"></i> asl-interpreting <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-assistive-listening-systems" aria-hidden="true"></i> assistive-listening-systems</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-audio-description" aria-hidden="true"></i> audio-description</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-blind" aria-hidden="true"></i> blind</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-braille" aria-hidden="true"></i> braille</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-cc" aria-hidden="true"></i> cc</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-deaf" aria-hidden="true"></i> deaf</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-deafness" copyright="J2eeFAST" aria-hidden="true"></i> deafness <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-hard-of-hearing" aria-hidden="true"></i> hard-of-hearing <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-low-vision" aria-hidden="true"></i> low-vision</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-question-circle-o" aria-hidden="true"></i> question-circle-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-sign-language" aria-hidden="true"></i> sign-language</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-signing" aria-hidden="true"></i> signing <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-tty" aria-hidden="true"></i> tty</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-universal-access" aria-hidden="true"></i> universal-access</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-volume-control-phone" aria-hidden="true"></i> volume-control-phone</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-wheelchair" aria-hidden="true"></i> wheelchair</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-wheelchair-alt" aria-hidden="true"></i> wheelchair-alt</div>
+	                        </div>
+	                    </section>
+	                    <section id="hand">
+	                        <h2 class="page-header">手型图标</h2>
+	                        <div class="row fontawesome-icon-list">
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-hand-grab-o" aria-hidden="true"></i> hand-grab-o <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-hand-lizard-o" aria-hidden="true"></i> hand-lizard-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-hand-o-down" aria-hidden="true"></i> hand-o-down</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-hand-o-left" aria-hidden="true"></i> hand-o-left</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-hand-o-right" aria-hidden="true"></i> hand-o-right</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-hand-o-up" aria-hidden="true"></i> hand-o-up</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-hand-paper-o" aria-hidden="true"></i> hand-paper-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-hand-peace-o" aria-hidden="true"></i> hand-peace-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-hand-pointer-o" aria-hidden="true"></i> hand-pointer-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-hand-rock-o" aria-hidden="true"></i> hand-rock-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-hand-scissors-o" aria-hidden="true"></i> hand-scissors-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-hand-spock-o" aria-hidden="true"></i> hand-spock-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-hand-stop-o" aria-hidden="true"></i> hand-stop-o <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-thumbs-down" aria-hidden="true"></i> thumbs-down</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-thumbs-o-down" aria-hidden="true"></i> thumbs-o-down</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-thumbs-o-up" aria-hidden="true"></i> thumbs-o-up</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-thumbs-up" aria-hidden="true"></i> thumbs-up</div>
+	                        </div>
+	                    </section>
+	                    <section id="transportation">
+	                        <h2 class="page-header">交通运输图标</h2>
+	                        <div class="row fontawesome-icon-list">
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-ambulance" aria-hidden="true"></i> ambulance</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-automobile" aria-hidden="true"></i> automobile <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-bicycle" aria-hidden="true"></i> bicycle</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-bus" aria-hidden="true"></i> bus</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-cab" aria-hidden="true"></i> cab <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-car" aria-hidden="true"></i> car</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-fighter-jet" aria-hidden="true"></i> fighter-jet</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-motorcycle" aria-hidden="true"></i> motorcycle</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-plane" aria-hidden="true"></i> plane</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-rocket" aria-hidden="true"></i> rocket</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-ship" aria-hidden="true"></i> ship</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-space-shuttle" aria-hidden="true"></i> space-shuttle</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-subway" aria-hidden="true"></i> subway</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-taxi" aria-hidden="true"></i> taxi</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-train" aria-hidden="true"></i> train</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-truck" aria-hidden="true"></i> truck</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-wheelchair" aria-hidden="true"></i> wheelchair</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-wheelchair-alt" aria-hidden="true"></i> wheelchair-alt</div>
+	                        </div>
+	                    </section>
+	                    <section id="gender">
+	                        <h2 class="page-header">性别图标</h2>
+	                        <div class="row fontawesome-icon-list">
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-genderless" aria-hidden="true"></i> genderless</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-intersex" aria-hidden="true"></i> intersex <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-mars" aria-hidden="true"></i> mars</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-mars-double" aria-hidden="true"></i> mars-double</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-mars-stroke" aria-hidden="true"></i> mars-stroke</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-mars-stroke-h" aria-hidden="true"></i> mars-stroke-h</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-mars-stroke-v" aria-hidden="true"></i> mars-stroke-v</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-mercury" aria-hidden="true"></i> mercury</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-neuter" aria-hidden="true"></i> neuter</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-transgender" aria-hidden="true"></i> transgender</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-transgender-alt" aria-hidden="true"></i> transgender-alt</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-venus" aria-hidden="true"></i> venus</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-venus-double" aria-hidden="true"></i> venus-double</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-venus-mars" aria-hidden="true"></i> venus-mars</div>
+	                        </div>
+	                    </section>
+	                    <section id="file-type">
+	                        <h2 class="page-header">文件类型图标</h2>
+	                        <div class="row fontawesome-icon-list">
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-file" aria-hidden="true"></i> file</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-file-archive-o" aria-hidden="true"></i> file-archive-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-file-audio-o" aria-hidden="true"></i> file-audio-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-file-code-o" aria-hidden="true"></i> file-code-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-file-excel-o" aria-hidden="true"></i> file-excel-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-file-image-o" aria-hidden="true"></i> file-image-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-file-movie-o" aria-hidden="true"></i> file-movie-o <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-file-o" aria-hidden="true"></i> file-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-file-pdf-o" aria-hidden="true"></i> file-pdf-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-file-photo-o" aria-hidden="true"></i> file-photo-o <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-file-picture-o" aria-hidden="true"></i> file-picture-o <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-file-powerpoint-o" aria-hidden="true"></i> file-powerpoint-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-file-sound-o" aria-hidden="true"></i> file-sound-o <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-file-text" aria-hidden="true"></i> file-text</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-file-text-o" aria-hidden="true"></i> file-text-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-file-video-o" aria-hidden="true"></i> file-video-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-file-word-o" aria-hidden="true"></i> file-word-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-file-zip-o" aria-hidden="true"></i> file-zip-o <span class="text-muted">(alias)</span></div>
+	                        </div>
+	                    </section>
+	                    <section id="spinner">
+	                        <h2 class="page-header">加载动画图标</h2>
+	                        <div class="alert alert-success">
+	                            <ul class="fa-ul">
+	                                <li>
+                                        <i class="fa fa-info-circle fa-lg fa-li"></i> 给这些图标加上
+                                        <code>fa-spin</code> class,就可以表现出加载动画了
+                                    </li>
+	                            </ul>
+	                        </div>
+	                        <div class="row fontawesome-icon-list">
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-circle-o-notch" aria-hidden="true"></i> circle-o-notch</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-cog" aria-hidden="true"></i> cog</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-gear" aria-hidden="true"></i> gear <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-refresh" aria-hidden="true"></i> refresh</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-spinner" aria-hidden="true"></i> spinner</div>
+	                        </div>
+	                    </section>
+	                    <section id="form-control">
+	                        <h2 class="page-header">表单图标</h2>
+	                        <div class="row fontawesome-icon-list">
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-check-square" aria-hidden="true"></i> check-square</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-check-square-o" aria-hidden="true"></i> check-square-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-circle" aria-hidden="true"></i> circle</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-circle-o" aria-hidden="true"></i> circle-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-dot-circle-o" aria-hidden="true"></i> dot-circle-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-minus-square" aria-hidden="true"></i> minus-square</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-minus-square-o" aria-hidden="true"></i> minus-square-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-plus-square" aria-hidden="true"></i> plus-square</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-plus-square-o" aria-hidden="true"></i> plus-square-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-square" aria-hidden="true"></i> square</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-square-o" aria-hidden="true"></i> square-o</div>
+	                        </div>
+	                    </section>
+	                    <section id="payment">
+	                        <h2 class="page-header">支付图标</h2>
+	                        <div class="row fontawesome-icon-list">
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-cc-amex" aria-hidden="true"></i> cc-amex</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-cc-diners-club" aria-hidden="true"></i> cc-diners-club</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-cc-discover" aria-hidden="true"></i> cc-discover</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-cc-jcb" aria-hidden="true"></i> cc-jcb</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-cc-mastercard" aria-hidden="true"></i> cc-mastercard</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-cc-paypal" aria-hidden="true"></i> cc-paypal</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-cc-stripe" aria-hidden="true"></i> cc-stripe</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-cc-visa" aria-hidden="true"></i> cc-visa</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-credit-card" aria-hidden="true"></i> credit-card</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-credit-card-alt" aria-hidden="true"></i> credit-card-alt</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-google-wallet" aria-hidden="true"></i> google-wallet</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-paypal" aria-hidden="true"></i> paypal</div>
+	                        </div>
+	                    </section>
+	                    <section id="chart">
+	                        <h2 class="page-header">统计图标</h2>
+	                        <div class="row fontawesome-icon-list">
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-area-chart" aria-hidden="true"></i> area-chart</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-bar-chart" aria-hidden="true"></i> bar-chart</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-bar-chart-o" aria-hidden="true"></i> bar-chart-o <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-line-chart" aria-hidden="true"></i> line-chart</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-pie-chart" aria-hidden="true"></i> pie-chart</div>
+	                        </div>
+	                    </section>
+	                    <section id="currency">
+	                        <h2 class="page-header">货币图标</h2>
+	                        <div class="row fontawesome-icon-list">
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-bitcoin" aria-hidden="true"></i> bitcoin <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-btc" aria-hidden="true"></i> btc</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-cny" aria-hidden="true"></i> cny <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-dollar" aria-hidden="true"></i> dollar <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-eur" aria-hidden="true"></i> eur</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-euro" aria-hidden="true"></i> euro <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-gbp" aria-hidden="true"></i> gbp</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-gg" aria-hidden="true"></i> gg</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-gg-circle" aria-hidden="true"></i> gg-circle</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-ils" aria-hidden="true"></i> ils</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-inr" aria-hidden="true"></i> inr</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-jpy" aria-hidden="true"></i> jpy</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-krw" aria-hidden="true"></i> krw</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-money" aria-hidden="true"></i> money</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-rmb" aria-hidden="true"></i> rmb <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-rouble" aria-hidden="true"></i> rouble <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-rub" aria-hidden="true"></i> rub</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-ruble" aria-hidden="true"></i> ruble <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-rupee" aria-hidden="true"></i> rupee <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-shekel" aria-hidden="true"></i> shekel <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-sheqel" aria-hidden="true"></i> sheqel <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-try" aria-hidden="true"></i> try</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-turkish-lira" aria-hidden="true"></i> turkish-lira <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-usd" aria-hidden="true"></i> usd</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-won" aria-hidden="true"></i> won <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-yen" aria-hidden="true"></i> yen <span class="text-muted">(alias)</span></div>
+	                        </div>
+	                    </section>
+	                    <section id="text-editor">
+	                        <h2 class="page-header">文本编辑器图标</h2>
+	                        <div class="row fontawesome-icon-list">
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-align-center" aria-hidden="true"></i> align-center</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-align-justify" aria-hidden="true"></i> align-justify</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-align-left" aria-hidden="true"></i> align-left</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-align-right" aria-hidden="true"></i> align-right</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-bold" aria-hidden="true"></i> bold</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-chain" aria-hidden="true"></i> chain <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-chain-broken" aria-hidden="true"></i> chain-broken</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-clipboard" aria-hidden="true"></i> clipboard</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-columns" aria-hidden="true"></i> columns</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-copy" aria-hidden="true"></i> copy <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-cut" aria-hidden="true"></i> cut <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-dedent" aria-hidden="true"></i> dedent <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-eraser" aria-hidden="true"></i> eraser</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-file" aria-hidden="true"></i> file</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-file-o" aria-hidden="true"></i> file-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-file-text" copyright="J2eeFAST" aria-hidden="true"></i> file-text</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-file-text-o" aria-hidden="true"></i> file-text-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-files-o" aria-hidden="true"></i> files-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-floppy-o" aria-hidden="true"></i> floppy-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-font" aria-hidden="true"></i> font</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-header" aria-hidden="true"></i> header</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-indent" aria-hidden="true"></i> indent</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-italic" aria-hidden="true"></i> italic</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-link" aria-hidden="true"></i> link</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-list" aria-hidden="true"></i> list</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-list-alt" aria-hidden="true"></i> list-alt</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-list-ol" aria-hidden="true"></i> list-ol</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-list-ul" aria-hidden="true"></i> list-ul</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-outdent" aria-hidden="true"></i> outdent</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-paperclip" aria-hidden="true"></i> paperclip</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-paragraph" aria-hidden="true"></i> paragraph</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-paste" aria-hidden="true"></i> paste <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-repeat" aria-hidden="true"></i> repeat</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-rotate-left" aria-hidden="true"></i> rotate-left <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-rotate-right" aria-hidden="true"></i> rotate-right <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-save" aria-hidden="true"></i> save <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-scissors" aria-hidden="true"></i> scissors</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-strikethrough" aria-hidden="true"></i> strikethrough</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-subscript" aria-hidden="true"></i> subscript</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-superscript" aria-hidden="true"></i> superscript</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-table" aria-hidden="true"></i> table</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-text-height" aria-hidden="true"></i> text-height</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-text-width" aria-hidden="true"></i> text-width</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-th" aria-hidden="true"></i> th</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-th-large" aria-hidden="true"></i> th-large</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-th-list" aria-hidden="true"></i> th-list</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-underline" aria-hidden="true"></i> underline</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-undo" aria-hidden="true"></i> undo</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-unlink" aria-hidden="true"></i> unlink <span class="text-muted">(alias)</span></div>
+	                        </div>
+	                    </section>
+	                    <section id="directional">
+	                        <h2 class="page-header">方向图标</h2>
+	                        <div class="row fontawesome-icon-list">
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-angle-double-down" aria-hidden="true"></i> angle-double-down</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-angle-double-left" aria-hidden="true"></i> angle-double-left</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-angle-double-right" aria-hidden="true"></i> angle-double-right</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-angle-double-up" aria-hidden="true"></i> angle-double-up</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-angle-down" aria-hidden="true"></i> angle-down</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-angle-left" aria-hidden="true"></i> angle-left</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-angle-right" aria-hidden="true"></i> angle-right</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-angle-up" aria-hidden="true"></i> angle-up</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-arrow-circle-down" aria-hidden="true"></i> arrow-circle-down</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-arrow-circle-left" aria-hidden="true"></i> arrow-circle-left</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-arrow-circle-o-down" aria-hidden="true"></i> arrow-circle-o-down</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-arrow-circle-o-left" aria-hidden="true"></i> arrow-circle-o-left</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-arrow-circle-o-right" aria-hidden="true"></i> arrow-circle-o-right</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-arrow-circle-o-up" aria-hidden="true"></i> arrow-circle-o-up</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> arrow-circle-right</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-arrow-circle-up" aria-hidden="true"></i> arrow-circle-up</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-arrow-down" aria-hidden="true"></i> arrow-down</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-arrow-left" aria-hidden="true"></i> arrow-left</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-arrow-right" aria-hidden="true"></i> arrow-right</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-arrow-up" aria-hidden="true"></i> arrow-up</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-arrows" aria-hidden="true"></i> arrows</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-arrows-alt" aria-hidden="true"></i> arrows-alt</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-arrows-h" aria-hidden="true"></i> arrows-h</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-arrows-v" aria-hidden="true"></i> arrows-v</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-caret-down" aria-hidden="true"></i> caret-down</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-caret-left" aria-hidden="true"></i> caret-left</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-caret-right" aria-hidden="true"></i> caret-right</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-caret-square-o-down" aria-hidden="true"></i> caret-square-o-down</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-caret-square-o-left" aria-hidden="true"></i> caret-square-o-left</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-caret-square-o-right" aria-hidden="true"></i> caret-square-o-right</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-caret-square-o-up" aria-hidden="true"></i> caret-square-o-up</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-caret-up" aria-hidden="true"></i> caret-up</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-chevron-circle-down" aria-hidden="true"></i> chevron-circle-down</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-chevron-circle-left" aria-hidden="true"></i> chevron-circle-left</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-chevron-circle-right" aria-hidden="true"></i> chevron-circle-right</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-chevron-circle-up" aria-hidden="true"></i> chevron-circle-up</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-chevron-down" aria-hidden="true"></i> chevron-down</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-chevron-left" aria-hidden="true"></i> chevron-left</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-chevron-right" aria-hidden="true"></i> chevron-right</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-chevron-up" aria-hidden="true"></i> chevron-up</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-exchange" aria-hidden="true"></i> exchange</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-hand-o-down" aria-hidden="true"></i> hand-o-down</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-hand-o-left" aria-hidden="true"></i> hand-o-left</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-hand-o-right" aria-hidden="true"></i> hand-o-right</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-hand-o-up" aria-hidden="true"></i> hand-o-up</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-long-arrow-down" aria-hidden="true"></i> long-arrow-down</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-long-arrow-left" aria-hidden="true"></i> long-arrow-left</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-long-arrow-right" aria-hidden="true"></i> long-arrow-right</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-long-arrow-up" aria-hidden="true"></i> long-arrow-up</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-toggle-down" aria-hidden="true"></i> toggle-down <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-toggle-left" aria-hidden="true"></i> toggle-left <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-toggle-right" aria-hidden="true"></i> toggle-right <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-toggle-up" aria-hidden="true"></i> toggle-up <span class="text-muted">(alias)</span></div>
+	                        </div>
+	                    </section>
+	                    <section id="video-player">
+	                        <h2 class="page-header">视频播放图标</h2>
+	                        <div class="row fontawesome-icon-list">
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-arrows-alt" aria-hidden="true"></i> arrows-alt</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-backward" aria-hidden="true"></i> backward</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-compress" aria-hidden="true"></i> compress</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-eject" aria-hidden="true"></i> eject</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-expand" aria-hidden="true"></i> expand</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-fast-backward" aria-hidden="true"></i> fast-backward</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-fast-forward" aria-hidden="true"></i> fast-forward</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-forward" aria-hidden="true"></i> forward</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-pause" aria-hidden="true"></i> pause</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-pause-circle" aria-hidden="true"></i> pause-circle</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-pause-circle-o" aria-hidden="true"></i> pause-circle-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-play" aria-hidden="true"></i> play</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-play-circle" aria-hidden="true"></i> play-circle</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-play-circle-o" aria-hidden="true"></i> play-circle-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-random" aria-hidden="true"></i> random</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-step-backward" aria-hidden="true"></i> step-backward</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-step-forward" aria-hidden="true"></i> step-forward</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-stop" aria-hidden="true"></i> stop</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-stop-circle" aria-hidden="true"></i> stop-circle</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-stop-circle-o" aria-hidden="true"></i> stop-circle-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-youtube-play" aria-hidden="true"></i> youtube-play</div>
+	                        </div>
+	                    </section>
+	                    <section id="brand">
+	                        <h2 class="page-header">品牌图标</h2>
+	                        <div class="row fontawesome-icon-list margin-bottom-lg">
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-500px" aria-hidden="true"></i> 500px</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-adn" aria-hidden="true"></i> adn</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-amazon" aria-hidden="true"></i> amazon</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-android" aria-hidden="true"></i> android</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-angellist" aria-hidden="true"></i> angellist</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-apple" aria-hidden="true"></i> apple</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-bandcamp" aria-hidden="true"></i> bandcamp</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-behance" aria-hidden="true"></i> behance</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-behance-square" aria-hidden="true"></i> behance-square</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-bitbucket" aria-hidden="true"></i> bitbucket</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-bitbucket-square" aria-hidden="true"></i> bitbucket-square</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-bitcoin" aria-hidden="true"></i> bitcoin <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-black-tie" aria-hidden="true"></i> black-tie</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-bluetooth" aria-hidden="true"></i> bluetooth</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-bluetooth-b" aria-hidden="true"></i> bluetooth-b</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-btc" aria-hidden="true"></i> btc</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-buysellads" aria-hidden="true"></i> buysellads</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-cc-amex" aria-hidden="true"></i> cc-amex</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-cc-diners-club" aria-hidden="true"></i> cc-diners-club</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-cc-discover" aria-hidden="true"></i> cc-discover</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-cc-jcb" aria-hidden="true"></i> cc-jcb</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-cc-mastercard" aria-hidden="true"></i> cc-mastercard</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-cc-paypal" aria-hidden="true"></i> cc-paypal</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-cc-stripe" aria-hidden="true"></i> cc-stripe</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-cc-visa" aria-hidden="true"></i> cc-visa</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-chrome" aria-hidden="true"></i> chrome</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-codepen" aria-hidden="true"></i> codepen</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-codiepie" aria-hidden="true"></i> codiepie</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-connectdevelop" aria-hidden="true"></i> connectdevelop</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-contao" aria-hidden="true"></i> contao</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-css3" aria-hidden="true"></i> css3</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-dashcube" aria-hidden="true"></i> dashcube</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-delicious" aria-hidden="true"></i> delicious</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-deviantart" aria-hidden="true"></i> deviantart</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-digg" aria-hidden="true"></i> digg</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-dribbble" aria-hidden="true"></i> dribbble</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-dropbox" aria-hidden="true"></i> dropbox</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-drupal" aria-hidden="true"></i> drupal</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-edge" aria-hidden="true"></i> edge</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-eercast" aria-hidden="true"></i> eercast</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-empire" aria-hidden="true"></i> empire</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-envira" aria-hidden="true"></i> envira</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-etsy" aria-hidden="true"></i> etsy</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-expeditedssl" aria-hidden="true"></i> expeditedssl</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-fa" aria-hidden="true"></i> fa <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-facebook" aria-hidden="true"></i> facebook</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-facebook-f" aria-hidden="true"></i> facebook-f <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-facebook-official" aria-hidden="true"></i> facebook-official</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-facebook-square" aria-hidden="true"></i> facebook-square</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-firefox" aria-hidden="true"></i> firefox</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-first-order" aria-hidden="true"></i> first-order</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-flickr" aria-hidden="true"></i> flickr</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-font-awesome" aria-hidden="true"></i> font-awesome</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-fonticons" aria-hidden="true"></i> fonticons</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-fort-awesome" aria-hidden="true"></i> fort-awesome</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-forumbee" aria-hidden="true"></i> forumbee</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-foursquare" aria-hidden="true"></i> foursquare</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-free-code-camp" aria-hidden="true"></i> free-code-camp</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-ge" aria-hidden="true"></i> ge <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-get-pocket" aria-hidden="true"></i> get-pocket</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-gg" aria-hidden="true"></i> gg</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-gg-circle" aria-hidden="true"></i> gg-circle</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-git" aria-hidden="true"></i> git</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-git-square" aria-hidden="true"></i> git-square</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-github" aria-hidden="true"></i> github</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-github-alt" aria-hidden="true"></i> github-alt</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-github-square" aria-hidden="true"></i> github-square</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-gitlab" aria-hidden="true"></i> gitlab</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-gittip" aria-hidden="true"></i> gittip <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-glide" aria-hidden="true"></i> glide</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-glide-g" aria-hidden="true"></i> glide-g</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-google" aria-hidden="true"></i> google</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-google-plus" aria-hidden="true"></i> google-plus</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-google-plus-circle" aria-hidden="true"></i> google-plus-circle <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-google-plus-official" aria-hidden="true"></i> google-plus-official</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-google-plus-square" aria-hidden="true"></i> google-plus-square</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-google-wallet" aria-hidden="true"></i> google-wallet</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-gratipay" aria-hidden="true"></i> gratipay</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-grav" aria-hidden="true"></i> grav</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-hacker-news" aria-hidden="true"></i> hacker-news</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-houzz" aria-hidden="true"></i> houzz</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-html5" aria-hidden="true"></i> html5</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-imdb" aria-hidden="true"></i> imdb</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-instagram" aria-hidden="true"></i> instagram</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-internet-explorer" aria-hidden="true"></i> internet-explorer</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-ioxhost" aria-hidden="true"></i> ioxhost</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-joomla" aria-hidden="true"></i> joomla</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-jsfiddle" aria-hidden="true"></i> jsfiddle</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-lastfm" aria-hidden="true"></i> lastfm</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-lastfm-square" aria-hidden="true"></i> lastfm-square</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-leanpub" aria-hidden="true"></i> leanpub</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-linkedin" aria-hidden="true"></i> linkedin</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-linkedin-square" aria-hidden="true"></i> linkedin-square</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-linode" aria-hidden="true"></i> linode</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-linux" aria-hidden="true"></i> linux</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-maxcdn" aria-hidden="true"></i> maxcdn</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-meanpath" aria-hidden="true"></i> meanpath</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-medium" aria-hidden="true"></i> medium</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-meetup" aria-hidden="true"></i> meetup</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-mixcloud" aria-hidden="true"></i> mixcloud</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-modx" aria-hidden="true"></i> modx</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-odnoklassniki" aria-hidden="true"></i> odnoklassniki</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-odnoklassniki-square" aria-hidden="true"></i> odnoklassniki-square</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-opencart" aria-hidden="true"></i> opencart</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-openid" aria-hidden="true"></i> openid</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-opera" aria-hidden="true"></i> opera</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-optin-monster" aria-hidden="true"></i> optin-monster</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-pagelines" copyright="J2eeFAST" aria-hidden="true"></i> pagelines</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-paypal" aria-hidden="true"></i> paypal</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-pied-piper" aria-hidden="true"></i> pied-piper</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-pied-piper-alt" aria-hidden="true"></i> pied-piper-alt</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-pied-piper-pp" aria-hidden="true"></i> pied-piper-pp</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-pinterest" aria-hidden="true"></i> pinterest</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-pinterest-p" aria-hidden="true"></i> pinterest-p</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-pinterest-square" aria-hidden="true"></i> pinterest-square</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-product-hunt" aria-hidden="true"></i> product-hunt</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-qq" aria-hidden="true"></i> qq</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-quora" aria-hidden="true"></i> quora</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-ra" aria-hidden="true"></i> ra <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-ravelry" aria-hidden="true"></i> ravelry</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-rebel" aria-hidden="true"></i> rebel</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-reddit" aria-hidden="true"></i> reddit</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-reddit-alien" aria-hidden="true"></i> reddit-alien</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-reddit-square" aria-hidden="true"></i> reddit-square</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-renren" aria-hidden="true"></i> renren</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-resistance" aria-hidden="true"></i> resistance <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-safari" aria-hidden="true"></i> safari</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-scribd" aria-hidden="true"></i> scribd</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-sellsy" aria-hidden="true"></i> sellsy</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-share-alt" aria-hidden="true"></i> share-alt</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-share-alt-square" aria-hidden="true"></i> share-alt-square</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-shirtsinbulk" aria-hidden="true"></i> shirtsinbulk</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-simplybuilt" aria-hidden="true"></i> simplybuilt</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-skyatlas" aria-hidden="true"></i> skyatlas</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-skype" aria-hidden="true"></i> skype</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-slack" aria-hidden="true"></i> slack</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-slideshare" aria-hidden="true"></i> slideshare</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-snapchat" aria-hidden="true"></i> snapchat</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-snapchat-ghost" aria-hidden="true"></i> snapchat-ghost</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-snapchat-square" aria-hidden="true"></i> snapchat-square</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-soundcloud" aria-hidden="true"></i> soundcloud</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-spotify" aria-hidden="true"></i> spotify</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-stack-exchange" aria-hidden="true"></i> stack-exchange</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-stack-overflow" aria-hidden="true"></i> stack-overflow</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-steam" aria-hidden="true"></i> steam</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-steam-square" aria-hidden="true"></i> steam-square</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-stumbleupon" copyright="J2eeFAST" aria-hidden="true"></i> stumbleupon</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-stumbleupon-circle" aria-hidden="true"></i> stumbleupon-circle</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-superpowers" aria-hidden="true"></i> superpowers</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-telegram" aria-hidden="true"></i> telegram</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-tencent-weibo" aria-hidden="true"></i> tencent-weibo</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-themeisle" aria-hidden="true"></i> themeisle</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-trello" aria-hidden="true"></i> trello</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-tripadvisor" aria-hidden="true"></i> tripadvisor</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-tumblr" aria-hidden="true"></i> tumblr</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-tumblr-square" aria-hidden="true"></i> tumblr-square</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-twitch" aria-hidden="true"></i> twitch</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-twitter" aria-hidden="true"></i> twitter</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-twitter-square" aria-hidden="true"></i> twitter-square</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-usb" aria-hidden="true"></i> usb</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-viacoin" aria-hidden="true"></i> viacoin</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-viadeo" aria-hidden="true"></i> viadeo</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-viadeo-square" aria-hidden="true"></i> viadeo-square</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-vimeo" aria-hidden="true"></i> vimeo</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-vimeo-square" aria-hidden="true"></i> vimeo-square</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-vine" aria-hidden="true"></i> vine</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-vk" aria-hidden="true"></i> vk</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-wechat" aria-hidden="true"></i> wechat <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-weibo" aria-hidden="true"></i> weibo</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-weixin" aria-hidden="true"></i> weixin</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-whatsapp" aria-hidden="true"></i> whatsapp</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-wikipedia-w" aria-hidden="true"></i> wikipedia-w</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-windows" aria-hidden="true"></i> windows</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-wordpress" aria-hidden="true"></i> wordpress</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-wpbeginner" aria-hidden="true"></i> wpbeginner</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-wpexplorer" aria-hidden="true"></i> wpexplorer</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-wpforms" aria-hidden="true"></i> wpforms</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-xing" aria-hidden="true"></i> xing</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-xing-square" aria-hidden="true"></i> xing-square</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-y-combinator" aria-hidden="true"></i> y-combinator</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-y-combinator-square" aria-hidden="true"></i> y-combinator-square <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-yahoo" aria-hidden="true"></i> yahoo</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-yc" aria-hidden="true"></i> yc <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-yc-square" aria-hidden="true"></i> yc-square <span class="text-muted">(alias)</span></div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-yelp" aria-hidden="true"></i> yelp</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-yoast" aria-hidden="true"></i> yoast</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-youtube" aria-hidden="true"></i> youtube</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-youtube-play" aria-hidden="true"></i> youtube-play</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-youtube-square" aria-hidden="true"></i> youtube-square</div>
+	                        </div>
+	                    </section>
+	                    <section id="medical">
+	                        <h2 class="page-header">医疗图标</h2>
+	                        <div class="row fontawesome-icon-list">
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-ambulance" aria-hidden="true"></i> ambulance</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-h-square" aria-hidden="true"></i> h-square</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-heart" aria-hidden="true"></i> heart</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-heart-o" aria-hidden="true"></i> heart-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-heartbeat" aria-hidden="true"></i> heartbeat</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-hospital-o" aria-hidden="true"></i> hospital-o</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-medkit" copyright="J2eeFAST" aria-hidden="true"></i> medkit</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-plus-square" aria-hidden="true"></i> plus-square</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-stethoscope" aria-hidden="true"></i> stethoscope</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-user-md" aria-hidden="true"></i> user-md</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-wheelchair" aria-hidden="true"></i> wheelchair</div>
+	                            <div class="fa-hover col-md-3 col-sm-4"><i class="fa fa-wheelchair-alt" aria-hidden="true"></i> wheelchair-alt</div>
+	                        </div>
+	                    </section>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <th:block th:include="include :: footer" />
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/demo/icon/glyphicons.html b/ruoyi-admin/src/main/resources/templates/demo/icon/glyphicons.html
new file mode 100644
index 0000000..bbdd20a
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/icon/glyphicons.html
@@ -0,0 +1,1364 @@
+<!DOCTYPE html>
+<html lang="zh">
+<head>
+	<th:block th:include="include :: header('glyphicons图标')" />
+</head>
+<body class="gray-bg">
+    <div class="wrapper wrapper-content animated fadeInRight">
+        <div class="row">
+            <div class="col-sm-3">
+                <div class="float-e-margins">
+                    <h2>Glyphicons 字体图标</h2> 包括250多个来自 Glyphicon Halflings 的字体图标。Glyphicons Halflings 一般是收费的,但是他们的作者允许 Bootstrap 免费使用。为了表示感谢,希望你在使用时尽量为 Glyphicons 添加一个友情链接。
+                </div>
+            </div>
+            <div class="col-sm-9">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>所有图标 <small class="m-l-sm">所有图标集合 - <a href="http://glyphicons.com/" target="_blank">Glyphicons</a> </small></h5>
+                        <div class="ibox-tools">
+                            <a class="collapse-link">
+                                <i class="fa fa-chevron-up"></i>
+                            </a>
+                            <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                                <i class="fa fa-wrench"></i>
+                            </a>
+                            <ul class="dropdown-menu dropdown-user">
+                                <li><a href="javascript:;">选项1</a>
+                                </li>
+                                <li><a href="javascript:;">选项2</a>
+                                </li>
+                            </ul>
+                            <a class="close-link">
+                                <i class="fa fa-times"></i>
+                            </a>
+                        </div>
+                    </div>
+                    <div class="ibox-content icons-box">
+                        <div class="bs-glyphicons">
+                            <ul class="bs-glyphicons-list">
+
+                                <li>
+                                    <span class="glyphicon glyphicon-asterisk" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-asterisk</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-plus</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-euro" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-euro</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-eur" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-eur</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-minus" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-minus</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-cloud" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-cloud</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-envelope" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-envelope</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-pencil</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-glass" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-glass</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-music" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-music</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-search" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-search</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-heart" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-heart</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-star" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-star</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-star-empty" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-star-empty</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-user" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-user</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-film" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-film</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-th-large" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-th-large</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-th" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-th</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-th-list" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-th-list</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-ok</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-remove</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-zoom-in" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-zoom-in</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-zoom-out" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-zoom-out</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-off" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-off</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-signal" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-signal</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-cog" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-cog</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-trash" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-trash</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-home" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-home</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-file" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-file</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-time" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-time</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-road" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-road</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-download-alt" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-download-alt</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-download" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-download</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-upload" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-upload</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-inbox" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-inbox</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-play-circle" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-play-circle</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-repeat" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-repeat</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-refresh" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-refresh</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-list-alt" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-list-alt</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-lock" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-lock</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-flag" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-flag</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-headphones" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-headphones</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-volume-off" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-volume-off</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-volume-down" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-volume-down</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-volume-up" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-volume-up</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-qrcode" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-qrcode</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-barcode" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-barcode</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-tag" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-tag</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-tags" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-tags</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-book" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-book</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-bookmark" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-bookmark</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-print" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-print</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-camera" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-camera</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-font" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-font</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-bold" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-bold</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-italic" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-italic</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-text-height" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-text-height</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-text-width" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-text-width</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-align-left" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-align-left</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-align-center" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-align-center</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-align-right" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-align-right</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-align-justify" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-align-justify</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-list" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-list</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-indent-left" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-indent-left</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-indent-right" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-indent-right</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-facetime-video" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-facetime-video</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-picture" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-picture</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-map-marker" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-map-marker</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-adjust" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-adjust</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-tint" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-tint</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-edit" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-edit</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-share" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-share</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-check" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-check</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-move" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-move</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-step-backward" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-step-backward</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-fast-backward" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-fast-backward</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-backward" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-backward</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-play" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-play</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-pause" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-pause</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-stop" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-stop</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-forward" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-forward</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-fast-forward" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-fast-forward</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-step-forward" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-step-forward</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-eject" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-eject</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-chevron-left</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-chevron-right</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-plus-sign" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-plus-sign</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-minus-sign" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-minus-sign</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-remove-sign" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-remove-sign</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-ok-sign" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-ok-sign</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-question-sign" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-question-sign</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-info-sign</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-screenshot" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-screenshot</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-remove-circle" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-remove-circle</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-ok-circle" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-ok-circle</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-ban-circle" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-ban-circle</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-arrow-left" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-arrow-left</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-arrow-right" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-arrow-right</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-arrow-up" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-arrow-up</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-arrow-down" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-arrow-down</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-share-alt" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-share-alt</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-resize-full" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-resize-full</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-resize-small" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-resize-small</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-exclamation-sign</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-gift" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-gift</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-leaf" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-leaf</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-fire" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-fire</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-eye-open" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-eye-open</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-eye-close" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-eye-close</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-warning-sign" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-warning-sign</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-plane" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-plane</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-calendar" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-calendar</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-random" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-random</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-comment" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-comment</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-magnet" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-magnet</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-chevron-up" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-chevron-up</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-chevron-down" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-chevron-down</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-retweet" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-retweet</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-shopping-cart" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-shopping-cart</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-folder-close" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-folder-close</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-folder-open" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-folder-open</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-resize-vertical" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-resize-vertical</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-resize-horizontal" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-resize-horizontal</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-hdd" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-hdd</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-bullhorn" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-bullhorn</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-bell" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-bell</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-certificate" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-certificate</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-thumbs-up" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-thumbs-up</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-thumbs-down" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-thumbs-down</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-hand-right" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-hand-right</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-hand-left" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-hand-left</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-hand-up" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-hand-up</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-hand-down" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-hand-down</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-circle-arrow-right" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-circle-arrow-right</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-circle-arrow-left" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-circle-arrow-left</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-circle-arrow-up" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-circle-arrow-up</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-circle-arrow-down" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-circle-arrow-down</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-globe" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-globe</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-wrench" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-wrench</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-tasks" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-tasks</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-filter" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-filter</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-briefcase" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-briefcase</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-fullscreen" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-fullscreen</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-dashboard" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-dashboard</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-paperclip" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-paperclip</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-heart-empty" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-heart-empty</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-link" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-link</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-phone" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-phone</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-pushpin" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-pushpin</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-usd" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-usd</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-gbp" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-gbp</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-sort" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-sort</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-sort-by-alphabet" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-sort-by-alphabet</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-sort-by-alphabet-alt" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-sort-by-alphabet-alt</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-sort-by-order" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-sort-by-order</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-sort-by-order-alt" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-sort-by-order-alt</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-sort-by-attributes" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-sort-by-attributes</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-sort-by-attributes-alt" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-sort-by-attributes-alt</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-unchecked" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-unchecked</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-expand" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-expand</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-collapse-down" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-collapse-down</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-collapse-up" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-collapse-up</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-log-in" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-log-in</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-flash" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-flash</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-log-out" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-log-out</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-new-window" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-new-window</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-record" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-record</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-save" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-save</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-open" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-open</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-saved" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-saved</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-import" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-import</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-export" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-export</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-send" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-send</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-floppy-disk" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-floppy-disk</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-floppy-saved" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-floppy-saved</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-floppy-remove" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-floppy-remove</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-floppy-save" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-floppy-save</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-floppy-open" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-floppy-open</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-credit-card" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-credit-card</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-transfer" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-transfer</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-cutlery" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-cutlery</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-header" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-header</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-compressed" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-compressed</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-earphone" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-earphone</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-phone-alt" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-phone-alt</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-tower" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-tower</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-stats" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-stats</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-sd-video" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-sd-video</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-hd-video" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-hd-video</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-subtitles" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-subtitles</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-sound-stereo" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-sound-stereo</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-sound-dolby" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-sound-dolby</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-sound-5-1" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-sound-5-1</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-sound-6-1" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-sound-6-1</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-sound-7-1" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-sound-7-1</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-copyright-mark" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-copyright-mark</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-registration-mark" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-registration-mark</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-cloud-download" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-cloud-download</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-cloud-upload" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-cloud-upload</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-tree-conifer" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-tree-conifer</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-tree-deciduous" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-tree-deciduous</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-cd" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-cd</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-save-file" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-save-file</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-open-file" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-open-file</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-level-up" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-level-up</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-copy" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-copy</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-paste" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-paste</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-alert</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-equalizer" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-equalizer</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-king" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-king</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-queen" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-queen</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-pawn" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-pawn</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-bishop" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-bishop</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-knight" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-knight</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-baby-formula" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-baby-formula</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-tent" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-tent</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-blackboard" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-blackboard</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-bed" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-bed</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-apple" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-apple</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-erase" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-erase</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-hourglass" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-hourglass</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-lamp" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-lamp</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-duplicate" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-duplicate</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-piggy-bank" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-piggy-bank</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-scissors" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-scissors</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-bitcoin" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-bitcoin</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-btc" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-btc</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-xbt" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-xbt</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-yen" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-yen</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-jpy" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-jpy</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-ruble" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-ruble</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-rub" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-rub</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-scale" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-scale</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-ice-lolly" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-ice-lolly</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-ice-lolly-tasted" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-ice-lolly-tasted</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-education" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-education</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-option-horizontal" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-option-horizontal</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-option-vertical" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-option-vertical</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-menu-hamburger" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-menu-hamburger</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-modal-window" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-modal-window</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-oil" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-oil</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-grain" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-grain</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-sunglasses" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-sunglasses</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-text-size" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-text-size</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-text-color" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-text-color</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-text-background" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-text-background</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-object-align-top" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-object-align-top</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-object-align-bottom" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-object-align-bottom</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-object-align-horizontal" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-object-align-horizontal</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-object-align-left" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-object-align-left</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-object-align-vertical" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-object-align-vertical</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-object-align-right" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-object-align-right</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-triangle-right" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-triangle-right</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-triangle-left" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-triangle-left</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-triangle-bottom" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-triangle-bottom</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-triangle-top" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-triangle-top</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-console" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-console</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-superscript" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-superscript</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-subscript" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-subscript</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-menu-left" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-menu-left</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-menu-right" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-menu-right</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-menu-down" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-menu-down</span>
+                                </li>
+
+                                <li>
+                                    <span class="glyphicon glyphicon-menu-up" aria-hidden="true"></span>
+                                    <span class="glyphicon-class">glyphicon glyphicon-menu-up</span>
+                                </li>
+
+                            </ul>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <th:block th:include="include :: footer" />
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/demo/modal/dialog.html b/ruoyi-admin/src/main/resources/templates/demo/modal/dialog.html
new file mode 100644
index 0000000..de0fd32
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/modal/dialog.html
@@ -0,0 +1,215 @@
+<!DOCTYPE html>
+<html lang="zh">
+<head>
+	<th:block th:include="include :: header('模态窗口')" />
+</head>
+<body class="gray-bg">
+<div class="wrapper wrapper-content fadeInRight">
+    <div class="row">
+        <div class="col-sm-4">
+            <div class="ibox ">
+                <div class="ibox-title">
+                    <h5>模态窗口</h5>
+
+                </div>
+                <div class="ibox-content">
+                    <p>创建自定义的RuoYi模态窗口可通过添加<code>.inmodal</code>类来实现。 </p>
+                    <div class="text-center">
+                        <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#myModal">打开示例窗口</button>
+                    </div>
+                    <div class="modal inmodal" id="myModal" tabindex="-1" role="dialog" aria-hidden="true">
+                        <div class="modal-dialog">
+                            <div class="modal-content animated bounceInRight">
+                                <div class="modal-header">
+                                    <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">关闭</span>
+                                    </button>
+                                    <i class="fa fa-laptop modal-icon"></i>
+                                    <h4 class="modal-title">窗口标题</h4>
+                                    <small class="font-bold">这里可以显示副标题。
+                                </div>
+                                <div class="modal-body">
+                                    <p><strong>RuoYi</strong>是一个完全响应式,基于Bootstrap3.3.7最新版本开发的扁平化主题,她采用了主流的左右两栏式布局,使用了Html5+CSS3等现代技术,她提供了诸多的强大的可以重新组合的UI组件,并集成了最新的jQuery版本(v2.1.1),当然,也集成了很多功能强大,用途广泛的jQuery插件,她可以用于所有的Web应用程序,如网站管理后台,网站会员中心,CMS,CRM,OA等等,当然,您也可以对她进行深度定制,以做出更强系统。</p>
+                                    <div class="form-group">
+                                        <label>Email</label>
+                                        <input type="email" placeholder="请输入您的Email" class="form-control">
+                                    </div>
+                                </div>
+                                <div class="modal-footer">
+                                    <button type="button" class="btn btn-white" data-dismiss="modal">关闭</button>
+                                    <button type="button" class="btn btn-primary">保存</button>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+
+                </div>
+            </div>
+            <div class="ibox float-e-margins">
+                <div class="ibox-title">
+                    <h5>大小设置</h5>
+
+                </div>
+                <div class="ibox-content">
+                    <p>模态窗口提供两种大小尺寸,可以通过为模态窗口的<code>.modal-dialog</code>添加类来实现 </p>
+
+                    <div class="text-center">
+                        <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#myModal5">大模态窗口</button>
+                        <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#myModal6">小模态窗口</button>
+                    </div>
+                    <div class="modal inmodal fade" id="myModal5" tabindex="-1" role="dialog" aria-hidden="true">
+                        <div class="modal-dialog modal-lg">
+                            <div class="modal-content">
+                                <div class="modal-header">
+                                    <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span>
+                                    </button>
+                                    <h4 class="modal-title">窗口标题</h4>
+                                    <small class="font-bold">这里可以显示副标题。
+                                </div>
+                                <div class="modal-body">
+                                    <p><strong>RuoYi</strong>是一个完全响应式,基于Bootstrap3.3.7最新版本开发的扁平化主题,她采用了主流的左右两栏式布局,使用了Html5+CSS3等现代技术,她提供了诸多的强大的可以重新组合的UI组件,并集成了最新的jQuery版本(v2.1.1),当然,也集成了很多功能强大,用途广泛的jQuery插件,她可以用于所有的Web应用程序,如网站管理后台,网站会员中心,CMS,CRM,OA等等,当然,您也可以对她进行深度定制,以做出更强系统。</p>
+                                </div>
+
+                                <div class="modal-footer">
+                                    <button type="button" class="btn btn-white" data-dismiss="modal">关闭</button>
+                                    <button type="button" class="btn btn-primary">保存</button>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="modal inmodal fade" id="myModal6" tabindex="-1" role="dialog" aria-hidden="true">
+                        <div class="modal-dialog modal-sm">
+                            <div class="modal-content">
+                                <div class="modal-header">
+                                    <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span>
+                                    </button>
+                                    <h4 class="modal-title">窗口标题</h4>
+                                </div>
+                                <div class="modal-body">
+                                    <p><strong>RuoYi</strong>是一个完全响应式,基于Bootstrap3.3.7最新版本开发的扁平化主题,她采用了主流的左右两栏式布局,使用了Html5+CSS3等现代技术,她提供了诸多的强大的可以重新组合的UI组件,并集成了最新的jQuery版本(v2.1.1),当然,也集成了很多功能强大,用途广泛的jQuery插件,她可以用于所有的Web应用程序,如网站管理后台,网站会员中心,CMS,CRM,OA等等,当然,您也可以对她进行深度定制,以做出更强系统。</p>
+                                </div>
+                                <div class="modal-footer">
+                                    <button type="button" class="btn btn-white" data-dismiss="modal">关闭</button>
+                                    <button type="button" class="btn btn-primary">保存</button>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+
+                </div>
+            </div>
+        </div>
+        <div class="col-sm-8">
+            <div class="ibox ">
+                <div class="ibox-title">
+                    <h5>动画窗口</h5>
+
+                </div>
+                <div class="ibox-content">
+                    <p>您可以通过为模态窗口的<code>.modal-content</code>添加类来实现动画效果 </p>
+
+                    <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#myModal2">沿X轴转动</button>
+                    <div class="modal inmodal" id="myModal2" tabindex="-1" role="dialog" aria-hidden="true">
+                        <div class="modal-dialog">
+                            <div class="modal-content animated flipInY">
+                                <div class="modal-header">
+                                    <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span>
+                                    </button>
+                                    <h4 class="modal-title">窗口标题</h4>
+                                    <small class="font-bold">这里可以显示副标题。
+                                </div>
+                                <div class="modal-body">
+                                    <p><strong>RuoYi</strong>是一个完全响应式,基于Bootstrap3.3.7最新版本开发的扁平化主题,她采用了主流的左右两栏式布局,使用了Html5+CSS3等现代技术,她提供了诸多的强大的可以重新组合的UI组件,并集成了最新的jQuery版本(v2.1.1),当然,也集成了很多功能强大,用途广泛的jQuery插件,她可以用于所有的Web应用程序,如网站管理后台,网站会员中心,CMS,CRM,OA等等,当然,您也可以对她进行深度定制,以做出更强系统。</p>
+                                </div>
+                                <div class="modal-footer">
+                                    <button type="button" class="btn btn-white" data-dismiss="modal">关闭</button>
+                                    <button type="button" class="btn btn-primary">保存</button>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+
+                    <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#myModal4">基本动画</button>
+                    <div class="modal inmodal" id="myModal4" tabindex="-1" role="dialog" aria-hidden="true">
+                        <div class="modal-dialog">
+                            <div class="modal-content animated fadeIn">
+                                <div class="modal-header">
+                                    <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span>
+                                    </button>
+                                    <i class="fa fa-clock-o modal-icon"></i>
+                                    <h4 class="modal-title">窗口标题</h4>
+                                    <small>这里可以显示副标题。
+                                </div>
+                                <div class="modal-body">
+                                    <p><strong>RuoYi</strong>是一个完全响应式,基于Bootstrap3.3.7最新版本开发的扁平化主题,她采用了主流的左右两栏式布局,使用了Html5+CSS3等现代技术,她提供了诸多的强大的可以重新组合的UI组件,并集成了最新的jQuery版本(v2.1.1),当然,也集成了很多功能强大,用途广泛的jQuery插件,她可以用于所有的Web应用程序,如网站管理后台,网站会员中心,CMS,CRM,OA等等,当然,您也可以对她进行深度定制,以做出更强系统。</p>
+                                </div>
+                                <div class="modal-footer">
+                                    <button type="button" class="btn btn-white" data-dismiss="modal">关闭</button>
+                                    <button type="button" class="btn btn-primary">保存</button>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+
+                </div>
+            </div>
+            <div class="ibox ">
+                <div class="ibox-title">
+                    <h5>设置选项</h5>
+
+                </div>
+                <div class="ibox-content">
+                    <p>可以通过数据绑定或者Javascript来实现模态窗口的相关功能,如果使用数据绑定,可以为元素添加<code>data-</code>,如<code>data-backdrop=""</code>。</p>
+
+                    <div class="table-responsive">
+                        <table class="table table-bordered table-striped">
+                            <thead>
+                            <tr>
+                                <th style="width: 100px;">名称</th>
+                                <th style="width: 50px;">类型</th>
+                                <th style="width: 50px;">默认值</th>
+                                <th>说明</th>
+                            </tr>
+                            </thead>
+                            <tbody>
+                            <tr>
+                                <td>backdrop</td>
+                                <td>boolean 或 string <code>'static'</code></td>
+                                <td>true</td>
+                                <td>遮罩层,或使用<code>'static'</code>指定遮罩层与关闭模态窗口不关联</td>
+                            </tr>
+                            <tr>
+                                <td>keyboard</td>
+                                <td>boolean</td>
+                                <td>true</td>
+                                <td>按Esc键时退出模态窗口</td>
+                            </tr>
+                            <tr>
+                                <td>show</td>
+                                <td>boolean</td>
+                                <td>true</td>
+                                <td>初始化完成后显示模态窗口</td>
+                            </tr>
+                            <tr>
+                                <td>remote</td>
+                                <td>path</td>
+                                <td>false</td>
+                                <td>
+                                    <p><strong class="text-danger">推荐使用数据绑定方式,或使用
+                                        <a href="http://api.jquery.com/load/">jQuery.load</a></p>
+                                    <p>远程URL示例:</p>
+                                    <div class="highlight">
+                                        <pre><code class="language-html" data-lang="html"><span class="nt">&lt;a</span> <span class="na">data-toggle=</span><span class="s">"modal"</span> <span class="na">href=</span><span class="s">"remote.html"</span> <span class="na">data-target=</span><span class="s">"#modal"</span><span class="nt">&gt;</span>Click me<span class="nt">&lt;/a&gt;</span></code></pre>
+                                    </div>
+                                </td>
+                            </tr>
+                            </tbody>
+                        </table>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+    <th:block th:include="include :: footer" />
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/demo/modal/form.html b/ruoyi-admin/src/main/resources/templates/demo/modal/form.html
new file mode 100644
index 0000000..de6e628
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/modal/form.html
@@ -0,0 +1,102 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+	<th:block th:include="include :: header('新增用户')" />
+</head>
+<body>
+    <div class="main-content">
+        <form id="form-user-add" class="form-horizontal">
+            <div class="row">
+            	<div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label is-required">用户名称:</label>
+                        <div class="col-sm-8">
+                            <input name="userName" placeholder="请输入用户名称" class="form-control" type="text">
+                        </div>
+                    </div>
+                </div>
+                <div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label is-required">归属部门:</label>
+                        <div class="col-sm-8">
+                            <div class="input-group">
+                            	<input name="deptName" type="text" placeholder="请选择归属部门" class="form-control">
+                                <span class="input-group-addon"><i class="fa fa-search"></i></span>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="row">
+                <div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label is-required">手机号码:</label>
+                        <div class="col-sm-8">
+                            <input name="phonenumber" placeholder="请输入手机号码" class="form-control" type="text">
+                        </div>
+                    </div>
+                </div>
+                <div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label is-required">邮箱:</label>
+                        <div class="col-sm-8">
+                            <input name="email" class="form-control" type="text" placeholder="请输入邮箱">
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="row">
+                <div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label is-required">登录账号:</label>
+                        <div class="col-sm-8">
+                            <input name="loginName" placeholder="请输入登录账号" class="form-control" type="text">
+                        </div>
+                    </div>
+                </div>
+                <div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label is-required">登录密码:</label>
+                        <div class="col-sm-8">
+                            <input name="password" placeholder="请输入登录密码" class="form-control" type="password">
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="row">
+                <div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label">用户性别:</label>
+                        <div class="col-sm-8">
+                            <div class="input-group" style="width: 100%">
+                                <select name="sex" class="form-control m-b" th:with="type=${@dict.getType('sys_user_sex')}">
+				                    <option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
+				                </select>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+                <div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label">用户状态:</label>
+                        <div class="col-sm-8">
+                            <label class="toggle-switch switch-solid">
+	                            <input type="checkbox" id="status" checked>
+	                            <span></span>
+	                        </label>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </form>
+    </div>
+	<th:block th:include="include :: footer" />
+    <script type="text/javascript">
+        function submitHandler() {
+        	if ($.validate.form()) {
+        		$.modal.msgSuccess('保存成功!');
+            }
+        }
+    </script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/demo/modal/layer.html b/ruoyi-admin/src/main/resources/templates/demo/modal/layer.html
new file mode 100644
index 0000000..74807f7
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/modal/layer.html
@@ -0,0 +1,288 @@
+<!DOCTYPE html>
+<html lang="zh">
+<head>
+	<th:block th:include="include :: header('弹层组件')" />
+	<style>
+        /* 解决layer相册层弹出时导致页面自动滚动 */
+        html {height: auto;}
+    </style>
+</head>
+<body class="gray-bg">
+	<div class="wrapper wrapper-content fadeInRight">
+	    <div class="row">
+	        <div class="col-sm-6">
+	            <div class="ibox">
+	                <div class="ibox-title">
+	                <h5>信息框</h5>
+	                </div>
+	                <div class="ibox-content" id="test">
+	                    <p>通过调用<code>$.modal.alert()</code>实现。 </p>
+	                    <button type="button" class="btn btn-primary" onclick="$.modal.alert('Hi,你好!')">普通</button>
+	                    <button type="button" class="btn btn-success" onclick="$.modal.alertSuccess('Hi,你好!')">成功</button>
+	                    <button type="button" class="btn btn-warning" onclick="$.modal.alertWarning('Hi,你好!')">警告</button>
+	                    <button type="button" class="btn btn-danger" onclick="$.modal.alertError('Hi,你好!')">失败</button>
+	                </div>
+	            </div>
+	        </div>
+	        
+	        <div class="col-sm-6">
+	            <div class="ibox">
+	                <div class="ibox-title">
+	                <h5>提示框</h5>
+	                </div>
+	                <div class="ibox-content">
+	                    <p>通过调用<code>$.modal.msg()</code>实现。 </p>
+	                    <button type="button" class="btn btn-primary" onclick="$.modal.msg('Hi,你好!')">普通</button>
+	                    <button type="button" class="btn btn-success" onclick="$.modal.msgSuccess('Hi,你好!')">成功</button>
+	                    <button type="button" class="btn btn-warning" onclick="$.modal.msgWarning('Hi,你好!')">警告</button>
+	                    <button type="button" class="btn btn-danger" onclick="$.modal.msgError('Hi,你好!')">失败</button>
+	                </div>
+	            </div>
+	        </div>
+	    </div>
+	
+	    <div class="row">
+	        <div class="col-sm-6">
+	            <div class="ibox">
+	                <div class="ibox-title">
+	                <h5>询问框</h5>
+	                </div>
+	                <div class="ibox-content">
+	                    <p>通过调用<code>$.modal.confirm()</code>实现。 </p>
+	                    <button type="button" class="btn btn-primary" id="button-confirm">询问按钮</button>
+	                </div>
+	            </div>
+	        </div>
+	        
+	        <div class="col-sm-6">
+	            <div class="ibox ">
+	                <div class="ibox-title">
+	                <h5>消息提示并刷新父窗体</h5>
+	                </div>
+	                <div class="ibox-content">
+	                    <p>通过调用<code>$.modal.msgReload()</code>实现。 </p>
+	                    <button type="button" class="btn btn-primary" id="button-msgReload">提示刷新按钮</button>
+	                </div>
+	            </div>
+	        </div>
+	        
+	        <div class="col-sm-6">
+	            <div class="ibox">
+	                <div class="ibox-title">
+	                <h5>普通弹出层</h5>
+	                </div>
+	                <div class="ibox-content">
+	                    <p>通过调用<code>$.modal.open()</code>实现。 </p>
+	                    <button type="button" class="btn btn-primary" id="button-open-1">默认</button>
+	                    <button type="button" class="btn btn-success" id="button-open-2">设置宽高</button>
+	                    <button type="button" class="btn btn-warning" id="button-open-3">回调函数</button>
+	                    <button type="button" class="btn btn-danger" id="button-open-4">自定义选项</button>
+	                    <button type="button" class="btn btn-primary" id="button-open-5">全屏弹出</button>
+	                </div>
+	            </div>
+	        </div>
+	        
+	        <div class="col-sm-6">
+	            <div class="ibox">
+	                <div class="ibox-title">
+	                <h5>选卡页方式</h5>
+	                </div>
+	                <div class="ibox-content">
+	                    <p>通过调用<code>$.modal.openTab()</code>实现。 </p>
+	                    <button type="button" class="btn btn-primary" id="button-open-6">新窗口打开</button>
+	                    <button type="button" class="btn btn-warning" id="button-open-7">关闭当前</button>
+	                    <button type="button" class="btn btn-primary" id="button-open-14">选卡页同一页签打开</button>
+	                    <button type="button" class="btn btn-warning" id="button-open-15">关闭指定</button>
+	                </div>
+	            </div>
+	        </div>
+	        
+	        <div class="col-sm-6">
+	            <div class="ibox">
+	                <div class="ibox-title">
+	                <h5>其他内容</h5>
+	                </div>
+	                <div class="ibox-content">
+	                    <p>通过调用<code>layer</code>实现。 </p>
+	                    <button type="button" class="btn btn-primary" id="button-open-8">tab层</button>
+	                    <button type="button" class="btn btn-primary" id="button-open-9">prompt层</button>
+	                    <button type="button" class="btn btn-primary" id="button-open-10">捕获页</button>
+	                    <button type="button" class="btn btn-primary" id="button-open-16">相册层</button>
+	                </div>
+	            </div>
+	        </div>
+	        
+	        <div class="col-sm-6">
+	            <div class="ibox">
+	                <div class="ibox-title">
+	                <h5>遮罩层</h5>
+	                </div>
+	                <div class="ibox-content">
+	                    <p>通过调用<code>blockUI</code>实现。 </p>
+	                    <button type="button" class="btn btn-primary" id="button-open-11">打开</button>
+	                    <button type="button" class="btn btn-warning" id="button-open-12">关闭</button>
+	                    <button type="button" class="btn btn-primary" id="button-open-13">layer遮罩</button>
+	                </div>
+	            </div>
+	        </div>
+	        
+	        <div class="col-sm-12">
+	            <div class="ibox">
+	                <div class="ibox-title">
+                        <label class="font-noraml">相关参数详细信息</label>
+                        <div><a href="http://doc.ruoyi.vip/#/standard/zjwd?id=layer" target="_blank">http://doc.ruoyi.vip/#/standard/zjwd?id=layer</a></div>
+	            </div>
+	        </div>
+	        
+	    </div>
+	</div>
+    <th:block th:include="include :: footer" />
+    <script th:inline="javascript">
+        var prefix = ctx + "demo/modal";
+        
+	    $("#button-confirm").click(function(){
+	    	$.modal.confirm("确认要点击确定吗?", function() {
+	    		$.modal.alert("ok");
+	    	});
+	    })
+	    
+	    $("#button-msgReload").click(function(){
+	        $.modal.msgReload("保存成功,正在刷新数据请稍候……", modal_status.SUCCESS);
+	    })
+	    
+	    $("#button-open-1").click(function(){
+	    	$.modal.open('添加用户', prefix + "/form");
+	    })
+	    
+	    $("#button-open-2").click(function(){
+	    	$.modal.open('添加用户', prefix + "/form", '900', '320');
+	    })
+	    
+	    $("#button-open-3").click(function(){
+	    	$.modal.open('添加用户', prefix + "/form", '900', '320', callback);
+	    })
+	    
+	    $("#button-open-4").click(function(){
+	    	var btn = ['<i class="fa fa-check"></i> 点我回调', '<i class="fa fa-close"></i> 点我关闭'];
+			var options = {
+				title: '添加用户',
+				width: "900",
+				height: "320",
+				url: prefix + "/form",
+				btn: btn,
+				callBack: doSubmit
+			};
+			$.modal.openOptions(options);
+	    })
+	    
+	    function doSubmit(index, layero) {
+	    	alert("进入了自定义选项提交方法");
+	    }
+	    
+	    function callback(index, layero) {
+	    	alert("进入了回调函数提交方法");
+	    }
+	    
+	    $("#button-open-5").click(function(){
+	    	$.modal.openFull('添加用户', prefix + "/form");
+	    })
+	    
+	    $("#button-open-6").click(function(){
+	    	$.modal.openTab('添加用户', prefix + "/form");
+	    })
+	    
+	    $("#button-open-7").click(function(){
+	    	$.modal.closeTab();
+	    })
+	    
+	     $("#button-open-8").click(function(){
+	    	//tab层
+	    	 layer.tab({
+	    	     area: ['600px', '300px'],
+	    	     tab: [{
+	    	         title: 'TAB1',
+	    	         content: '内容1'
+	    	     },
+	    	     {
+	    	         title: 'TAB2',
+	    	         content: '内容2'
+	    	     },
+	    	     {
+	    	         title: 'TAB3',
+	    	         content: '内容3'
+	    	     }]
+	    	 });
+	    })
+	    
+	    $("#button-open-9").click(function(){
+	    	layer.prompt({title: '输入任何口令,并确认', formType: 1}, function(pass, index){
+	    	  layer.close(index);
+	    	  layer.prompt({title: '随便写点啥,并确认', formType: 2}, function(text, index){
+	    	    layer.close(index);
+	    	    layer.msg('演示完毕!您的口令:'+ pass +'<br>您最后写下了:'+text);
+	    	  });
+	    	});
+	    })
+	    
+	    $("#button-open-10").click(function(){
+	    	layer.open({
+    		  type: 1,
+    		  shade: false,
+    		  title: false, //不显示标题
+    		  content: $('#test'), //捕获的元素,注意:最好该指定的元素要存放在body最外层,否则可能被其它的相对元素所影响
+    		  cancel: function(){
+    		    layer.msg('捕获就是从页面已经存在的元素上,包裹layer的结构', {time: 5000, icon:6});
+    		  }
+    		});
+	    })
+	    
+	    $("#button-open-11").click(function(){
+	    	$.modal.loading("数据加载中");
+	    })
+	    
+	    $("#button-open-12").click(function(){
+	    	$.modal.closeLoading();
+	    })
+	    
+	    $("#button-open-13").click(function(){
+	    	layer.load(0, {shade: false}); // 0代表加载的风格,支持0-2
+	    })
+	    
+	    $("#button-open-14").click(function(){
+	    	$.modal.parentTab('添加用户', prefix + "/form");
+	    })
+	    
+	    $("#button-open-15").click(function(){
+	    	// 需要关闭窗口的url
+	    	$.modal.closeTab(prefix + "/form");
+	    })
+	    
+	    $("#button-open-16").click(function(){
+            var json = {
+            		"title": "若依相册", //相册标题
+            		"id": 123, //相册id
+            		"start": 0, //初始显示的图片序号,默认0
+            		"data": [   //相册包含的图片,数组格式
+            		    {
+            		        "alt": "默认头像",
+            		        "pid": 1, //图片id
+            		        "src": ctx + "img/profile.jpg", //原图地址
+            		        "thumb": ctx + "img/profile.jpg" //缩略图地址
+            		    },
+            		    {
+                            "alt": "打赏",
+                            "pid": 2, //图片id
+                            "src": ctx + "img/pay.png", //原图地址
+                            "thumb": ctx + "img/pay.png" //缩略图地址
+                        }
+            		 ]
+            };
+            layer.photos({
+                photos: json,
+                closeBtn: 0, //右上角按钮,可通过配置1和2来展示,如果不显示,则closeBtn: 0
+                anim: 5 //0-6的选择,指定弹出图片动画类型,默认随机(请注意,3.0之前的版本用shift参数)
+            });
+        })
+	</script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/demo/modal/table.html b/ruoyi-admin/src/main/resources/templates/demo/modal/table.html
new file mode 100644
index 0000000..fc17215
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/modal/table.html
@@ -0,0 +1,124 @@
+<!DOCTYPE html>
+<html lang="zh">
+<head>
+	<th:block th:include="include :: header('弹层表格')" />
+</head>
+<body class="gray-bg">
+	<div class="wrapper wrapper-content fadeInRight">
+	    <div class="row">
+	        <div class="col-sm-12">
+	            <div class="ibox">
+	                <div class="ibox-title">
+	                <h5>弹层框</h5>
+	                </div>
+	                <div class="ibox-content" id="test">
+	                    <p>弹出复选框表格及单选框表格(点击提交后得到数据)。 </p>
+	                    <button type="button" class="btn btn-primary" onclick="selectCheckUser()">弹出表格(复选框)</button>
+	                    <button type="button" class="btn btn-success" onclick="selectRadioUser()">弹出表格(单选框)</button>
+	                </div>
+	            </div>
+	        </div>
+	        <div class="col-sm-12">
+	            <div class="ibox">
+	                <div class="ibox-title">
+	                <h5>弹层框</h5>
+	                </div>
+	                <div class="ibox-content" id="test">
+	                    <p>弹出层,点击提交后得到数据并回显到父窗体。 </p>
+	                    <button type="button" class="btn btn-primary" onclick="selectUsersToParent()">弹出表格(方式一)</button>
+	                    <button type="button" class="btn btn-success" onclick="selectUsersToParentCallBack2()">弹出表格(方式二)</button>
+	                    <button type="button" class="btn btn-info" onclick="selectUsersToParentCallBack3()">弹出表格(方式三)</button>
+	                    <p id="userids"> </p>
+	                </div>
+	            </div>
+	        </div>
+	        <div class="col-sm-12">
+	            <div class="ibox">
+	                <div class="ibox-title">
+	                <h5>弹层框</h5>
+	                </div>
+	                <div class="ibox-content" id="test">
+	                    <p>多层弹出,点击提交后得到数据并回显到父窗体。 </p>
+	                    <button type="button" class="btn btn-primary" onclick="selectUsersToParent4()">弹出窗口(方式四)</button>
+	                    <p id="username"> </p>
+	                </div>
+	            </div>
+	        </div>
+	    </div>
+	</div>
+    <th:block th:include="include :: footer" />
+    <script type="text/javascript">
+        var prefix = ctx + "demo/modal";
+
+        function selectCheckUser(){
+        	$.modal.open("选择用户", prefix + "/check");
+        }
+
+		function selectRadioUser(){
+			$.modal.open("选择用户", prefix + "/radio");
+        }
+
+		// 根据当前激活的选项卡获取(方式一)
+		function selectUsersToParent(){
+			$.modal.open("选择用户", prefix + "/parent");
+        }
+		
+		// callBack获取父窗口方法(方式二)
+		function selectUsersToParentCallBack2(){
+            var options = {
+                title: '选择用户',
+                url: prefix + "/parent",
+                callBack: doSubmit2
+             };
+             $.modal.openOptions(options);
+        }
+
+		// callBack获取父窗口值(方式三)
+		function selectUsersToParentCallBack3(){
+            var options = {
+                title: '选择用户',
+                url: prefix + "/parent",
+                callBack: doSubmit3
+             };
+             $.modal.openOptions(options);
+        }
+		
+		// callBack获取父窗口值(方式四)
+		function selectUsersToParent4(){
+			var prefix = ctx + "demo/modal";
+            var options = {
+                title: '多层窗口A',
+                url: prefix + "/frame1",
+                callBack: doSubmit4
+            };
+            $.modal.openOptions(options);
+        }
+		
+		function doSubmit2(index, layero){
+		    var rows = layero.find("iframe")[0].contentWindow.getSelections();
+		    if (rows.length == 0) {
+                $.modal.alertWarning("请至少选择一条记录");
+                return;
+            }
+		    $('#userids').html('我是通过方式二来的:' + rows.join())
+		    $.modal.close(index);
+		}
+
+		function doSubmit3(index, layero){
+			var body = $.modal.getChildFrame(index);
+   			$("#userids").html('我是通过方式三来的:' + body.find('#rowIds').val());
+   			$.modal.close(index);
+		}
+		
+		function doSubmit4(index, layero){
+			var body = $.modal.getChildFrame(index);
+   			$("#username").html('我是通过方式四来的:' + body.find('#name').val());
+   			$.modal.close(index);
+		}
+		
+		function selectUsers(){
+			alert(1);
+		}
+	</script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/demo/modal/table/check.html b/ruoyi-admin/src/main/resources/templates/demo/modal/table/check.html
new file mode 100644
index 0000000..e2f463e
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/modal/table/check.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('check表格页')" />
+</head>
+<body class="gray-bg">
+     <div class="container-div">
+		<div class="row">
+			<div class="col-sm-12 select-table table-striped">
+				<table id="bootstrap-table"></table>
+			</div>
+		</div>
+	</div>
+    <div th:include="include :: footer"></div>
+    <script th:inline="javascript">
+        var prefix = ctx + "demo/table";
+        var datas = [[${@dict.getType('sys_normal_disable')}]];
+
+        $(function() {
+            var options = {
+                url: prefix + "/list",
+		        showSearch: false,
+		        showRefresh: false,
+		        showToggle: false,
+		        showColumns: false,
+                columns: [{
+		            checkbox: true
+		        },
+				{
+					field : 'userId', 
+					title : '用户ID'
+				},
+				{
+					field : 'userCode', 
+					title : '用户编号'
+				},
+				{
+					field : 'userName', 
+					title : '用户姓名'
+				},
+				{
+					field : 'userPhone', 
+					title : '用户手机'
+				},
+				{
+					field : 'userEmail', 
+					title : '用户邮箱'
+				},
+				{
+				    field : 'userBalance',
+				    title : '用户余额'
+				},
+				{
+                    field: 'status',
+                    title: '用户状态',
+                    align: 'center',
+                    formatter: function(value, row, index) {
+                    	return $.table.selectDictLabel(datas, value);
+                    }
+                },
+		        {
+		            title: '操作',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		            	var actions = [];
+		            	actions.push('<a class="btn btn-success btn-xs" href="javascript:;"><i class="fa fa-edit"></i>编辑</a> ');
+                        actions.push('<a class="btn btn-danger btn-xs" href="javascript:;"><i class="fa fa-remove"></i>删除</a>');
+						return actions.join('');
+		            }
+		        }]
+            };
+            $.table.init(options);
+        });
+        
+        /* 添加用户-选择用户-提交 */
+		function submitHandler() {
+			var rows = $.table.selectFirstColumns();
+			if (rows.length == 0) {
+       			$.modal.alertWarning("请至少选择一条记录");
+       			return;
+       		}
+			alert(rows.join());
+		}
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/demo/modal/table/frame1.html b/ruoyi-admin/src/main/resources/templates/demo/modal/table/frame1.html
new file mode 100644
index 0000000..af5fe62
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/modal/table/frame1.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('多层窗口A')" />
+</head>
+<body class="gray-bg">
+     <div class="container-div">
+		<div class="row">
+			<form id="form-user-add" class="form-horizontal">
+	            <div class="row">
+	            	<div class="col-sm-12" style="margin-top: 50px">
+	                    <div class="form-group">
+	                        <label class="col-sm-4 control-label">用户名称:</label>
+	                        <div class="col-sm-4">
+	                            <input id="name" placeholder="请输入用户名称" class="form-control" type="text">
+	                        </div>
+	                        <button type="button" class="btn btn-primary" onclick="selectUserToParentId()">选择</button>
+	                    </div>
+	                </div>
+	           </div>
+			</form>
+		</div>
+	</div>
+    <div th:include="include :: footer"></div>
+    <script th:inline="javascript">
+        /* 提交 */
+		function submitHandler() {
+        	var name = $("#name").val();
+			activeWindow().$('#username').html(name);
+			$.modal.close();
+		}
+        
+		// 根据父窗口ID获取
+		function selectUserToParentId(){
+			var prefix = ctx + "demo/modal";
+            var options = {
+                width: '100px',
+                height: '100px',
+                title: '多层窗口B',
+                url: prefix + "/frame2",
+                callBack: doSubmit
+            };
+            $.modal.openOptions(options);
+        }
+		
+		function doSubmit(index, layero){
+			var body = $.modal.getChildFrame(index);
+   			$("#name").val(body.find('#name').val());
+   			$.modal.close(index);
+		}
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/demo/modal/table/frame2.html b/ruoyi-admin/src/main/resources/templates/demo/modal/table/frame2.html
new file mode 100644
index 0000000..b4940fe
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/modal/table/frame2.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('多层窗口B')" />
+</head>
+<body class="gray-bg">
+     <div class="container-div">
+		<div class="row">
+			<form id="form-user-add" class="form-horizontal">
+	            <div class="row">
+	            	<div class="col-sm-12" style="margin-top: 20px">
+	                    <div class="form-group">
+	                        <label class="col-sm-4 control-label">用户名称:</label>
+	                        <div class="col-sm-4">
+	                            <input id="name" placeholder="请输入用户名称" class="form-control" type="text">
+	                        </div>
+	                    </div>
+	                </div>
+	           </div>
+			</form>
+		</div>
+	</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/demo/modal/table/parent.html b/ruoyi-admin/src/main/resources/templates/demo/modal/table/parent.html
new file mode 100644
index 0000000..21b810a
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/modal/table/parent.html
@@ -0,0 +1,102 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('表格传值给父页面')" />
+</head>
+<body class="gray-bg">
+     <input type="hidden" id="rowIds">
+     <div class="container-div">
+		<div class="row">
+			<div class="col-sm-12 select-table table-striped">
+				<table id="bootstrap-table"></table>
+			</div>
+		</div>
+	</div>
+    <div th:include="include :: footer"></div>
+    <script th:inline="javascript">
+        var prefix = ctx + "demo/table";
+        var datas = [[${@dict.getType('sys_normal_disable')}]];
+
+        $(function() {
+            var options = {
+                url: prefix + "/list",
+		        showSearch: false,
+		        showRefresh: false,
+		        showToggle: false,
+		        showColumns: false,
+                columns: [{
+		            checkbox: true
+		        },
+				{
+					field : 'userId', 
+					title : '用户ID'
+				},
+				{
+					field : 'userCode', 
+					title : '用户编号'
+				},
+				{
+					field : 'userName', 
+					title : '用户姓名'
+				},
+				{
+					field : 'userPhone', 
+					title : '用户手机'
+				},
+				{
+					field : 'userEmail', 
+					title : '用户邮箱'
+				},
+				{
+				    field : 'userBalance',
+				    title : '用户余额'
+				},
+				{
+                    field: 'status',
+                    title: '用户状态',
+                    align: 'center',
+                    formatter: function(value, row, index) {
+                    	return $.table.selectDictLabel(datas, value);
+                    }
+                },
+		        {
+		            title: '操作',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		            	var actions = [];
+		            	actions.push('<a class="btn btn-success btn-xs" href="javascript:;"><i class="fa fa-edit"></i>编辑</a> ');
+                        actions.push('<a class="btn btn-danger btn-xs" href="javascript:;"><i class="fa fa-remove"></i>删除</a>');
+						return actions.join('');
+		            }
+		        }]
+            };
+            $.table.init(options);
+        });
+        
+        /* 添加用户-选择用户-提交(子页面调用父页面形式) */
+		function submitHandler(index, layero) {
+			var rows = $.table.selectFirstColumns();
+			if (rows.length == 0) {
+       			$.modal.alertWarning("请至少选择一条记录");
+       			return;
+       		}
+			$.modal.close();
+			// 父页面的方法
+			// activeWindow().selectUsers();
+			// 父页面的变量
+			activeWindow().$('#userids').html('我是通过方式一来的:' + rows.join());
+		}
+        
+		/* 添加用户-选择用户-提交(回调形式-父页面调用子页面) */
+		function getSelections() {
+			return $.table.selectFirstColumns();
+		}
+
+		$("#bootstrap-table").on("check.bs.table check-all.bs.table uncheck.bs.table uncheck-all.bs.table", function (e, rowsAfter, rowsBefore) {
+            var rows = $.common.equals("uncheck-all", e.type) ? rowsBefore : rowsAfter;
+            var rowIds = $.table.affectedRowIds(rows);
+            $("#rowIds").val(rowIds);
+        });
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/demo/modal/table/radio.html b/ruoyi-admin/src/main/resources/templates/demo/modal/table/radio.html
new file mode 100644
index 0000000..6df154c
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/modal/table/radio.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('radio表格页')" />
+</head>
+<body class="gray-bg">
+     <div class="container-div">
+		<div class="row">
+			<div class="col-sm-12 select-table table-striped">
+				<table id="bootstrap-table"></table>
+			</div>
+		</div>
+	</div>
+    <div th:include="include :: footer"></div>
+    <script th:inline="javascript">
+        var prefix = ctx + "demo/table";
+        var datas = [[${@dict.getType('sys_normal_disable')}]];
+
+        $(function() {
+            var options = {
+                url: prefix + "/list",
+		        showSearch: false,
+		        showRefresh: false,
+		        showToggle: false,
+		        showColumns: false,
+                columns: [{
+		            radio: true
+		        },
+				{
+					field : 'userId', 
+					title : '用户ID'
+				},
+				{
+					field : 'userCode', 
+					title : '用户编号'
+				},
+				{
+					field : 'userName', 
+					title : '用户姓名'
+				},
+				{
+					field : 'userPhone', 
+					title : '用户手机'
+				},
+				{
+					field : 'userEmail', 
+					title : '用户邮箱'
+				},
+				{
+				    field : 'userBalance',
+				    title : '用户余额'
+				},
+				{
+                    field: 'status',
+                    title: '用户状态',
+                    align: 'center',
+                    formatter: function(value, row, index) {
+                    	return $.table.selectDictLabel(datas, value);
+                    }
+                },
+		        {
+		            title: '操作',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		            	var actions = [];
+		            	actions.push('<a class="btn btn-success btn-xs" href="javascript:;"><i class="fa fa-edit"></i>编辑</a> ');
+                        actions.push('<a class="btn btn-danger btn-xs" href="javascript:;"><i class="fa fa-remove"></i>删除</a>');
+						return actions.join('');
+		            }
+		        }]
+            };
+            $.table.init(options);
+        });
+        
+        /* 添加用户-选择用户-提交 */
+		function submitHandler() {
+			var rows = $.table.selectFirstColumns();
+			if (rows.length == 0) {
+       			$.modal.alertWarning("请至少选择一条记录");
+       			return;
+       		}
+			alert(rows.join());
+		}
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/demo/operate/add.html b/ruoyi-admin/src/main/resources/templates/demo/operate/add.html
new file mode 100644
index 0000000..ee8e332
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/operate/add.html
@@ -0,0 +1,78 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+	<th:block th:include="include :: header('新增用户')" />
+</head>
+<body class="white-bg">
+	<div class="wrapper wrapper-content animated fadeInRight ibox-content">
+		<form class="form-horizontal m" id="form-user-add">
+			<div class="form-group">
+				<label class="col-sm-3 control-label">用户编号:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="userCode" id="userCode" required>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">用户姓名:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="userName" id="userName" required>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">用户性别:</label>
+                <div class="col-sm-8">
+                    <div class="input-group" style="width: 100%">
+                        <select name="userSex" class="form-control m-b" th:with="type=${@dict.getType('sys_user_sex')}">
+			                <option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
+			            </select>
+                    </div>
+                </div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">用户手机:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="userPhone" id="userPhone">
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">用户邮箱:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="userEmail" id="userEmail">
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">用户状态:</label>
+				<div class="col-sm-8">
+				    <div class="radio-box" th:each="dict : ${@dict.getType('sys_normal_disable')}">
+						<input type="radio" th:id="${dict.dictCode}" name="status" th:value="${dict.dictValue}" th:checked="${dict.default}">
+						<label th:for="${dict.dictCode}" th:text="${dict.dictLabel}"></label>
+					</div>
+				</div>
+			</div>
+		</form>
+	</div>
+	<th:block th:include="include :: footer" />
+	<script type="text/javascript">
+		var prefix = ctx + "demo/operate";
+		
+		$("#form-user-add").validate({
+			onkeyup: false,
+			rules:{
+				userPhone:{
+					isPhone:true
+				},
+				userEmail:{
+					email:true
+				},
+			},
+		    focusCleanup: true
+		});
+		
+		function submitHandler() {
+	        if ($.validate.form()) {
+	        	$.operate.save(prefix + "/add", $('#form-user-add').serialize());
+	        }
+	    }
+	</script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/demo/operate/detail.html b/ruoyi-admin/src/main/resources/templates/demo/operate/detail.html
new file mode 100644
index 0000000..8e10c0f
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/operate/detail.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+	<th:block th:include="include :: header('用户详细')" />
+</head>
+<body class="white-bg">
+	<div class="wrapper wrapper-content animated fadeInRight ibox-content">
+		<form class="form-horizontal m" id="form-user-edit">
+			<div class="form-group">
+				<label class="col-sm-3 control-label">用户编号:</label>
+				<div class="col-sm-8">
+					<div class="form-control-static" th:text="${user.userCode}"></div>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">用户姓名:</label>
+				<div class="col-sm-8">
+				    <div class="form-control-static" th:text="${user.userName}"></div>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">用户性别:</label>
+                <div class="col-sm-8">
+                    <div class="form-control-static" th:text="${@dict.getLabel('sys_user_sex', user.status)}"></div>
+                </div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">用户手机:</label>
+				<div class="col-sm-8">
+				    <div class="form-control-static" th:text="${user.userPhone}"></div>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">用户邮箱:</label>
+				<div class="col-sm-8">
+				    <div class="form-control-static" th:text="${user.userEmail}"></div>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">用户状态:</label>
+				<div class="col-sm-8">
+				    <div class="form-control-static" th:text="${@dict.getLabel('sys_normal_disable', user.status)}"></div>
+				</div>
+			</div>
+		</form>
+	</div>
+	<th:block th:include="include :: footer" />
+	<script type="text/javascript">
+		var prefix = ctx + "demo/operate";
+
+		$("#form-user-add").validate({
+			onkeyup: false,
+			rules:{
+				userPhone:{
+					isPhone:true
+				},
+				userEmail:{
+					email:true
+				},
+			},
+		    focusCleanup: true
+		});
+
+		function submitHandler() {
+	        if ($.validate.form()) {
+	        	$.operate.save(prefix + "/edit", $('#form-user-edit').serialize());
+	        }
+	    }
+	</script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/demo/operate/edit.html b/ruoyi-admin/src/main/resources/templates/demo/operate/edit.html
new file mode 100644
index 0000000..94ed965
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/operate/edit.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+	<th:block th:include="include :: header('修改用户')" />
+</head>
+<body class="white-bg">
+	<div class="wrapper wrapper-content animated fadeInRight ibox-content">
+		<form class="form-horizontal m" id="form-user-edit" th:object="${user}">
+		    <input name="userId" type="hidden"  th:field="*{userId}" />
+			<div class="form-group">
+				<label class="col-sm-3 control-label">用户编号:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="userCode" id="userCode" th:field="*{userCode}" required>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">用户姓名:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="userName" id="userName" th:field="*{userName}" required>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">用户性别:</label>
+                <div class="col-sm-8">
+                    <div class="input-group" style="width: 100%">
+                        <select name="userSex" class="form-control m-b" th:with="type=${@dict.getType('sys_user_sex')}">
+			                <option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}" th:field="*{userSex}"></option>
+			            </select>
+                    </div>
+                </div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">用户手机:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="userPhone" th:field="*{userPhone}" id="userPhone">
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">用户邮箱:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="userEmail" th:field="*{userEmail}" id="userEmail">
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">用户状态:</label>
+				<div class="col-sm-8">
+				    <div class="radio-box" th:each="dict : ${@dict.getType('sys_normal_disable')}">
+						<input type="radio" th:id="${dict.dictCode}" name="status" th:value="${dict.dictValue}" th:field="*{status}">
+						<label th:for="${dict.dictCode}" th:text="${dict.dictLabel}"></label>
+					</div>
+				</div>
+			</div>
+		</form>
+	</div>
+	<th:block th:include="include :: footer" />
+	<script type="text/javascript">
+		var prefix = ctx + "demo/operate";
+		
+		$("#form-user-add").validate({
+			onkeyup: false,
+			rules:{
+				userPhone:{
+					isPhone:true
+				},
+				userEmail:{
+					email:true
+				},
+			},
+		    focusCleanup: true
+		});
+		
+		function submitHandler() {
+	        if ($.validate.form()) {
+	        	$.operate.save(prefix + "/edit", $('#form-user-edit').serialize());
+	        }
+	    }
+	</script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/demo/operate/other.html b/ruoyi-admin/src/main/resources/templates/demo/operate/other.html
new file mode 100644
index 0000000..2c44685
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/operate/other.html
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('其他操作')" />
+</head>
+<body class="white-bg">
+	<div class="wrapper wrapper-content animated fadeInRight ibox-content">
+	    <form class="form-horizontal" id="form-demo-1">
+	        <div class="form-group">
+	            <label class="col-sm-2 control-label">用户名称:</label>
+	            <div class="col-sm-10">
+	                <input type="text" class="form-control" name="userName" placeholder="请输入用户名称">
+	            </div>
+	        </div>
+	        <div class="form-group">
+	            <label class="col-sm-2 control-label">手机号码:</label>
+	            <div class="col-sm-10">
+	                <input type="text" class="form-control" name="phonenumber" maxlength="11" placeholder="请输入手机号码">
+	            </div>
+	        </div>
+	        <div class="form-group">
+	            <div class="col-sm-offset-2 col-sm-10">
+	                <button type="button" class="btn btn-sm btn-primary" onclick="submit1()"><i class="fa fa-check"></i>保 存(不刷新当前页)</button>&nbsp;
+	            </div>
+	        </div>
+	    </form>
+	    <hr/>
+	    <form class="form-horizontal" id="form-demo-2">
+	        <div class="form-group">
+	            <label class="col-sm-2 control-label">用户名称:</label>
+	            <div class="col-sm-10">
+	                <input type="text" class="form-control" name="userName" placeholder="请输入用户名称">
+	            </div>
+	        </div>
+	        <div class="form-group">
+	            <label class="col-sm-2 control-label">手机号码:</label>
+	            <div class="col-sm-10">
+	                <input type="text" class="form-control" name="phonenumber" maxlength="11" placeholder="请输入手机号码">
+	            </div>
+	        </div>
+	        <div class="form-group">
+	            <div class="col-sm-offset-2 col-sm-10">
+	                <button type="button" class="btn btn-sm btn-primary" onclick="submit2()"><i class="fa fa-check"></i>保 存(刷新当前页)</button>&nbsp;
+	            </div>
+	        </div>
+	    </form>
+    </div>
+    <th:block th:include="include :: footer" />
+	<script type="text/javascript">
+	    var prefix = ctx + "demo/operate";
+	    function submit1(){
+	    	$.operate.saveModal(prefix + "/edit", $('#form-demo-1').serialize());
+	    }
+	    
+	    function submit2(){
+	    	$.ajax({
+	            url: prefix + "/edit",
+	            data: $('#form-demo-2').serialize(),
+	            type: "post",
+	            success: function(result) {
+	            	if (result.code == web_status.SUCCESS) {
+	            		layer.msg("保存成功,正在刷新数据请稍候……", {
+		            	    icon: 1,
+		            	    time: 500,
+		            	    shade: [0.1, '#8F8F8F']
+		            	},function() {
+		            		location.reload();
+		            	});
+	            	} else {
+	            		alert(result.msg);
+	            	}
+	            }
+	        })
+	    }
+	</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/demo/operate/table.html b/ruoyi-admin/src/main/resources/templates/demo/operate/table.html
new file mode 100644
index 0000000..d5642bb
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/operate/table.html
@@ -0,0 +1,125 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('其他操作')" />
+</head>
+<body class="gray-bg">
+     <div class="container-div">
+     	<div class="btn-group-sm" id="toolbar" role="group">
+	        <a class="btn btn-success" onclick="$.operate.add()">
+	            <i class="fa fa-plus"></i> 新增
+	        </a>
+	        <a class="btn btn-primary single disabled" onclick="$.operate.edit()">
+	            <i class="fa fa-edit"></i> 修改
+	        </a>
+	        <a class="btn btn-danger multiple disabled" onclick="$.operate.removeAll()">
+	            <i class="fa fa-remove"></i> 删除
+	        </a>
+	        <a class="btn btn-info" onclick="$.table.importExcel()">
+	            <i class="fa fa-upload"></i> 导入
+	        </a>
+	        <a class="btn btn-warning" onclick="$.table.exportExcel()">
+	            <i class="fa fa-download"></i> 导出
+	        </a>
+	        <a class="btn btn-info single disabled" onclick="$.operate.detail()">
+	            <i class="fa fa-search"></i> 详细
+	        </a>
+	        <a class="btn btn-danger" onclick="$.operate.clean()">
+	            <i class="fa fa-trash"></i> 清空
+	        </a>
+        </div>
+		<div class="row">
+			<div class="col-sm-12 select-table table-striped">
+				<table id="bootstrap-table"></table>
+			</div>
+		</div>
+	</div>
+    <div th:include="include :: footer"></div>
+    <script th:inline="javascript">
+        var prefix = ctx + "demo/operate";
+        var datas = [[${@dict.getType('sys_normal_disable')}]];
+
+        $(function() {
+            var options = {
+                url: prefix + "/list",
+                createUrl: prefix + "/add",
+                updateUrl: prefix + "/edit/{id}",
+                removeUrl: prefix + "/remove",
+                exportUrl: prefix + "/export",
+                importUrl: prefix + "/importData",
+                importTemplateUrl: prefix + "/importTemplate",
+                detailUrl: prefix + "/detail/{id}",
+                cleanUrl: prefix + "/clean",
+		        showSearch: false,
+		        showRefresh: false,
+		        showToggle: false,
+		        showColumns: false,
+		        search: true,
+		        modalName: "用户",
+                columns: [{
+		            checkbox: true
+		        },
+				{
+					field : 'userId', 
+					title : '用户ID'
+				},
+				{
+					field : 'userCode', 
+					title : '用户编号'
+				},
+				{
+					field : 'userName', 
+					title : '用户姓名'
+				},
+				{
+					field : 'userPhone', 
+					title : '用户手机'
+				},
+				{
+					field : 'userEmail', 
+					title : '用户邮箱'
+				},
+				{
+				    field : 'userBalance',
+				    title : '用户余额'
+				},
+				{
+                    field: 'status',
+                    title: '用户状态',
+                    align: 'center',
+                    formatter: function(value, row, index) {
+                    	return $.table.selectDictLabel(datas, value);
+                    }
+                },
+		        {
+		            title: '操作',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		            	var actions = [];
+		            	actions.push('<a class="btn btn-success btn-xs" href="javascript:;" onclick="$.operate.edit(\'' + row.userId + '\')"><i class="fa fa-edit"></i>编辑</a> ');
+                        actions.push('<a class="btn btn-info btn-xs" href="javascript:;" onclick="$.operate.detail(\'' + row.userId + '\')"><i class="fa fa-search"></i>详细</a> ');
+                        actions.push('<a class="btn btn-danger btn-xs" href="javascript:;" onclick="$.operate.remove(\'' + row.userId + '\')"><i class="fa fa-remove"></i>删除</a>');
+						return actions.join('');
+		            }
+		        }]
+            };
+            $.table.init(options);
+        });
+    </script>
+</body>
+<!-- 导入区域 -->
+<script id="importTpl" type="text/template">
+<form enctype="multipart/form-data" class="mt20 mb10">
+	<div class="col-xs-offset-1">
+		<input type="file" id="file" name="file"/>
+		<div class="mt10 pt5">
+			<input type="checkbox" id="updateSupport" name="updateSupport" title="如果登录账户已经存在,更新这条数据。"> 是否更新已经存在的用户数据
+			 &nbsp;	<a onclick="$.table.importTemplate()" class="btn btn-default btn-xs"><i class="fa fa-file-excel-o"></i> 下载模板</a>
+		</div>
+		<font color="red" class="pull-left mt10">
+			提示:仅允许导入“xls”或“xlsx”格式文件!
+		</font>
+	</div>
+</form>
+</script>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/demo/report/echarts.html b/ruoyi-admin/src/main/resources/templates/demo/report/echarts.html
new file mode 100644
index 0000000..b8c9ed6
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/report/echarts.html
@@ -0,0 +1,1264 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('百度ECharts')" />
+</head>
+<body class="gray-bg">
+	<div class="row  border-bottom white-bg dashboard-header">
+        <div class="col-sm-12">
+            <p>ECharts开源来自百度商业前端数据可视化团队,基于html5 Canvas,是一个纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据可视化图表。创新的拖拽重计算、数据视图、值域漫游等特性大大增强了用户体验,赋予了用户对数据进行挖掘、整合的能力。 <a href="https://echarts.apache.org/handbook/zh/get-started/" target="_blank">了解更多</a>
+            </p>
+            <p>ECharts官网:<a href="https://echarts.apache.org/" target="_blank">https://echarts.apache.org/</a>
+            </p>
+
+        </div>
+    </div>
+    <div class="wrapper wrapper-content animated fadeInRight">
+        <div class="row">
+            <div class="col-sm-6">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>折线图</h5>
+                        <div class="ibox-tools">
+                            <a class="collapse-link">
+                                <i class="fa fa-chevron-up"></i>
+                            </a>
+                            <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                                <i class="fa fa-wrench"></i>
+                            </a>
+                            <ul class="dropdown-menu dropdown-user">
+                                <li><a href="javascript:;">选项1</a>
+                                </li>
+                                <li><a href="javascript:;">选项2</a>
+                                </li>
+                            </ul>
+                            <a class="close-link">
+                                <i class="fa fa-times"></i>
+                            </a>
+                        </div>
+                    </div>
+                    <div class="ibox-content">
+                        <div class="echarts" id="echarts-line-chart"></div>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-6">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>柱状图</h5>
+                        <div class="ibox-tools">
+                            <a class="collapse-link">
+                                <i class="fa fa-chevron-up"></i>
+                            </a>
+                            <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                                <i class="fa fa-wrench"></i>
+                            </a>
+                            <ul class="dropdown-menu dropdown-user">
+                                <li><a href="javascript:;">选项1</a>
+                                </li>
+                                <li><a href="javascript:;">选项2</a>
+                                </li>
+                            </ul>
+                            <a class="close-link">
+                                <i class="fa fa-times"></i>
+                            </a>
+                        </div>
+                    </div>
+                    <div class="ibox-content">
+
+                        <div class="echarts" id="echarts-bar-chart"></div>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div class="row">
+            <div class="col-sm-6">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>散点图</h5>
+                        <div class="ibox-tools">
+                            <a class="collapse-link">
+                                <i class="fa fa-chevron-up"></i>
+                            </a>
+                            <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                                <i class="fa fa-wrench"></i>
+                            </a>
+                            <ul class="dropdown-menu dropdown-user">
+                                <li><a href="javascript:;">选项1</a>
+                                </li>
+                                <li><a href="javascript:;">选项2</a>
+                                </li>
+                            </ul>
+                            <a class="close-link">
+                                <i class="fa fa-times"></i>
+                            </a>
+                        </div>
+                    </div>
+                    <div class="ibox-content">
+                        <div class="echarts" id="echarts-scatter-chart"></div>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-6">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>K线图</h5>
+                        <div class="ibox-tools">
+                            <a class="collapse-link">
+                                <i class="fa fa-chevron-up"></i>
+                            </a>
+                            <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                                <i class="fa fa-wrench"></i>
+                            </a>
+                            <ul class="dropdown-menu dropdown-user">
+                                <li><a href="javascript:;">选项1</a>
+                                </li>
+                                <li><a href="javascript:;">选项2</a>
+                                </li>
+                            </ul>
+                            <a class="close-link">
+                                <i class="fa fa-times"></i>
+                            </a>
+                        </div>
+                    </div>
+                    <div class="ibox-content">
+                        <div class="echarts" id="echarts-k-chart"></div>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-6">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>饼状图</h5>
+                        <div class="ibox-tools">
+                            <a class="collapse-link">
+                                <i class="fa fa-chevron-up"></i>
+                            </a>
+                            <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                                <i class="fa fa-wrench"></i>
+                            </a>
+                            <ul class="dropdown-menu dropdown-user">
+                                <li><a href="javascript:;">选项1</a>
+                                </li>
+                                <li><a href="javascript:;">选项2</a>
+                                </li>
+                            </ul>
+                            <a class="close-link">
+                                <i class="fa fa-times"></i>
+                            </a>
+                        </div>
+                    </div>
+                    <div class="ibox-content">
+                        <div class="echarts" id="echarts-pie-chart"></div>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-6">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>雷达图</h5>
+                        <div class="ibox-tools">
+                            <a class="collapse-link">
+                                <i class="fa fa-chevron-up"></i>
+                            </a>
+                            <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                                <i class="fa fa-wrench"></i>
+                            </a>
+                            <ul class="dropdown-menu dropdown-user">
+                                <li><a href="javascript:;">选项1</a>
+                                </li>
+                                <li><a href="javascript:;">选项2</a>
+                                </li>
+                            </ul>
+                            <a class="close-link">
+                                <i class="fa fa-times"></i>
+                            </a>
+                        </div>
+                    </div>
+                    <div class="ibox-content">
+                        <div class="echarts" id="echarts-radar-chart"></div>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-6">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>仪表盘</h5>
+                        <div class="ibox-tools">
+                            <a class="collapse-link">
+                                <i class="fa fa-chevron-up"></i>
+                            </a>
+                            <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                                <i class="fa fa-wrench"></i>
+                            </a>
+                            <ul class="dropdown-menu dropdown-user">
+                                <li><a href="javascript:;">选项1</a>
+                                </li>
+                                <li><a href="javascript:;">选项2</a>
+                                </li>
+                            </ul>
+                            <a class="close-link">
+                                <i class="fa fa-times"></i>
+                            </a>
+                        </div>
+                    </div>
+                    <div class="ibox-content">
+                        <div class="echarts" id="echarts-gauge-chart"></div>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-6">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>漏斗图</h5>
+                        <div class="ibox-tools">
+                            <a class="collapse-link">
+                                <i class="fa fa-chevron-up"></i>
+                            </a>
+                            <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                                <i class="fa fa-wrench"></i>
+                            </a>
+                            <ul class="dropdown-menu dropdown-user">
+                                <li><a href="javascript:;">选项1</a>
+                                </li>
+                                <li><a href="javascript:;">选项2</a>
+                                </li>
+                            </ul>
+                            <a class="close-link">
+                                <i class="fa fa-times"></i>
+                            </a>
+                        </div>
+                    </div>
+                    <div class="ibox-content">
+                        <div class="echarts" id="echarts-funnel-chart"></div>
+                    </div>
+                </div>
+            </div>
+        </div>
+
+        <div class="row">
+            <div class="col-sm-12">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>中国地图</h5>
+                        <div class="ibox-tools">
+                            <a class="collapse-link">
+                                <i class="fa fa-chevron-up"></i>
+                            </a>
+                            <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                                <i class="fa fa-wrench"></i>
+                            </a>
+                            <ul class="dropdown-menu dropdown-user">
+                                <li><a href="javascript:;">选项1</a>
+                                </li>
+                                <li><a href="javascript:;">选项2</a>
+                                </li>
+                            </ul>
+                            <a class="close-link">
+                                <i class="fa fa-times"></i>
+                            </a>
+                        </div>
+                    </div>
+                    <div class="ibox-content">
+                        <div style="height:600px" id="echarts-map-chart"></div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <th:block th:include="include :: footer" />
+    <th:block th:include="include :: echarts-js" />
+    <script type="text/javascript">
+	    $(function () {
+	        var lineChart = echarts.init(document.getElementById("echarts-line-chart"));
+	        var lineoption = {
+	            title : {
+	                text: '未来一周气温变化'
+	            },
+	            tooltip : {
+	                trigger: 'axis'
+	            },
+	            legend: {
+	                data:['最高气温','最低气温']
+	            },
+	            grid:{
+	                x:40,
+	                x2:40,
+	                y2:24
+	            },
+	            calculable : true,
+	            xAxis : [
+	                {
+	                    type : 'category',
+	                    boundaryGap : false,
+	                    data : ['周一','周二','周三','周四','周五','周六','周日']
+	                }
+	            ],
+	            yAxis : [
+	                {
+	                    type : 'value',
+	                    axisLabel : {
+	                        formatter: '{value} °C'
+	                    }
+	                }
+	            ],
+	            series : [
+	                {
+	                    name:'最高气温',
+	                    type:'line',
+	                    data:[11, 11, 15, 13, 12, 13, 10],
+	                    markPoint : {
+	                        data : [
+	                            {type : 'max', name: '最大值'},
+	                            {type : 'min', name: '最小值'}
+	                        ]
+	                    },
+	                    markLine : {
+	                        data : [
+	                            {type : 'average', name: '平均值'}
+	                        ]
+	                    }
+	                },
+	                {
+	                    name:'最低气温',
+	                    type:'line',
+	                    data:[1, -2, 2, 5, 3, 2, 0],
+	                    markPoint : {
+	                        data : [
+	                            {name : '周最低', value : -2, xAxis: 1, yAxis: -1.5}
+	                        ]
+	                    },
+	                    markLine : {
+	                        data : [
+	                            {type : 'average', name : '平均值'}
+	                        ]
+	                    }
+	                }
+	            ]
+	        };
+	        lineChart.setOption(lineoption);
+	        $(window).resize(lineChart.resize);
+	
+	        var barChart = echarts.init(document.getElementById("echarts-bar-chart"));
+	        var baroption = {
+	            title : {
+	                text: '某地区蒸发量和降水量'
+	            },
+	            tooltip : {
+	                trigger: 'axis'
+	            },
+	            legend: {
+	                data:['蒸发量','降水量']
+	            },
+	            grid:{
+	                x:30,
+	                x2:40,
+	                y2:24
+	            },
+	            calculable : true,
+	            xAxis : [
+	                {
+	                    type : 'category',
+	                    data : ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月']
+	                }
+	            ],
+	            yAxis : [
+	                {
+	                    type : 'value'
+	                }
+	            ],
+	            series : [
+	                {
+	                    name:'蒸发量',
+	                    type:'bar',
+	                    data:[2.0, 4.9, 7.0, 23.2, 25.6, 76.7, 135.6, 162.2, 32.6, 20.0, 6.4, 3.3],
+	                    markPoint : {
+	                        data : [
+	                            {type : 'max', name: '最大值'},
+	                            {type : 'min', name: '最小值'}
+	                        ]
+	                    },
+	                    markLine : {
+	                        data : [
+	                            {type : 'average', name: '平均值'}
+	                        ]
+	                    }
+	                },
+	                {
+	                    name:'降水量',
+	                    type:'bar',
+	                    data:[2.6, 5.9, 9.0, 26.4, 28.7, 70.7, 175.6, 182.2, 48.7, 18.8, 6.0, 2.3],
+	                    markPoint : {
+	                        data : [
+	                            {name : '年最高', value : 182.2, xAxis: 7, yAxis: 183, symbolSize:18},
+	                            {name : '年最低', value : 2.3, xAxis: 11, yAxis: 3}
+	                        ]
+	                    },
+	                    markLine : {
+	                        data : [
+	                            {type : 'average', name : '平均值'}
+	                        ]
+	                    }
+	                }
+	            ]
+	        };
+	        barChart.setOption(baroption);
+	
+	        window.onresize = barChart.resize;
+	
+	        var scatterChart = echarts.init(document.getElementById("echarts-scatter-chart"));
+	        var scatteroption = {
+	            title : {
+	                text: '男性女性身高体重分布',
+	                subtext: '抽样调查来自: Heinz  2003'
+	            },
+	            tooltip : {
+	                trigger: 'axis',
+	                showDelay : 0,
+	                axisPointer:{
+	                    type : 'cross',
+	                    lineStyle: {
+	                        type : 'dashed',
+	                        width : 1
+	                    }
+	                }
+	            },
+	            legend: {
+	                data:['女性','男性']
+	            },
+	            grid:{
+	                x:45,
+	                x2:40,
+	                y2:24
+	            },
+	            xAxis : [
+	                {
+	                    type : 'value',
+	                    scale:true,
+	                    axisLabel : {
+	                        formatter: '{value} cm'
+	                    }
+	                }
+	            ],
+	            yAxis : [
+	                {
+	                    type : 'value',
+	                    scale:true,
+	                    axisLabel : {
+	                        formatter: '{value} kg'
+	                    }
+	                }
+	            ],
+	            series : [
+	                {
+	                    name:'女性',
+	                    type:'scatter',
+	                    tooltip : {
+	                        trigger: 'item',
+	                        formatter : function (params) {
+	                            if (params.value.length > 1) {
+	                                return params.seriesName + ' :<br/>'
+	                                   + params.value[0] + 'cm '
+	                                   + params.value[1] + 'kg ';
+	                            }
+	                            else {
+	                                return params.seriesName + ' :<br/>'
+	                                   + params.name + ' : '
+	                                   + params.value + 'kg ';
+	                            }
+	                        }
+	                    },
+	                    data: [
+	                        [161.2, 51.6], [167.5, 59.0], [159.5, 49.2], [157.0, 63.0], [155.8, 53.6],
+	                        [170.0, 59.0], [159.1, 47.6], [166.0, 69.8], [176.2, 66.8], [160.2, 75.2],
+	                        [172.5, 55.2], [170.9, 54.2], [172.9, 62.5], [153.4, 42.0], [160.0, 50.0],
+	                        [147.2, 49.8], [168.2, 49.2], [175.0, 73.2], [157.0, 47.8], [167.6, 68.8],
+	                        [159.5, 50.6], [175.0, 82.5], [166.8, 57.2], [176.5, 87.8], [170.2, 72.8],
+	                        [174.0, 54.5], [173.0, 59.8], [179.9, 67.3], [170.5, 67.8], [160.0, 47.0],
+	                        [154.4, 46.2], [162.0, 55.0], [176.5, 83.0], [160.0, 54.4], [152.0, 45.8],
+	                        [162.1, 53.6], [170.0, 73.2], [160.2, 52.1], [161.3, 67.9], [166.4, 56.6],
+	                        [168.9, 62.3], [163.8, 58.5], [167.6, 54.5], [160.0, 50.2], [161.3, 60.3],
+	                        [167.6, 58.3], [165.1, 56.2], [160.0, 50.2], [170.0, 72.9], [157.5, 59.8],
+	                        [167.6, 61.0], [160.7, 69.1], [163.2, 55.9], [152.4, 46.5], [157.5, 54.3],
+	                        [168.3, 54.8], [180.3, 60.7], [165.5, 60.0], [165.0, 62.0], [164.5, 60.3],
+	                        [156.0, 52.7], [160.0, 74.3], [163.0, 62.0], [165.7, 73.1], [161.0, 80.0],
+	                        [162.0, 54.7], [166.0, 53.2], [174.0, 75.7], [172.7, 61.1], [167.6, 55.7],
+	                        [151.1, 48.7], [164.5, 52.3], [163.5, 50.0], [152.0, 59.3], [169.0, 62.5],
+	                        [164.0, 55.7], [161.2, 54.8], [155.0, 45.9], [170.0, 70.6], [176.2, 67.2],
+	                        [170.0, 69.4], [162.5, 58.2], [170.3, 64.8], [164.1, 71.6], [169.5, 52.8],
+	                        [163.2, 59.8], [154.5, 49.0], [159.8, 50.0], [173.2, 69.2], [170.0, 55.9],
+	                        [161.4, 63.4], [169.0, 58.2], [166.2, 58.6], [159.4, 45.7], [162.5, 52.2],
+	                        [159.0, 48.6], [162.8, 57.8], [159.0, 55.6], [179.8, 66.8], [162.9, 59.4],
+	                        [161.0, 53.6], [151.1, 73.2], [168.2, 53.4], [168.9, 69.0], [173.2, 58.4],
+	                        [171.8, 56.2], [178.0, 70.6], [164.3, 59.8], [163.0, 72.0], [168.5, 65.2],
+	                        [166.8, 56.6], [172.7, 105.2], [163.5, 51.8], [169.4, 63.4], [167.8, 59.0],
+	                        [159.5, 47.6], [167.6, 63.0], [161.2, 55.2], [160.0, 45.0], [163.2, 54.0],
+	                        [162.2, 50.2], [161.3, 60.2], [149.5, 44.8], [157.5, 58.8], [163.2, 56.4],
+	                        [172.7, 62.0], [155.0, 49.2], [156.5, 67.2], [164.0, 53.8], [160.9, 54.4],
+	                        [162.8, 58.0], [167.0, 59.8], [160.0, 54.8], [160.0, 43.2], [168.9, 60.5],
+	                        [158.2, 46.4], [156.0, 64.4], [160.0, 48.8], [167.1, 62.2], [158.0, 55.5],
+	                        [167.6, 57.8], [156.0, 54.6], [162.1, 59.2], [173.4, 52.7], [159.8, 53.2],
+	                        [170.5, 64.5], [159.2, 51.8], [157.5, 56.0], [161.3, 63.6], [162.6, 63.2],
+	                        [160.0, 59.5], [168.9, 56.8], [165.1, 64.1], [162.6, 50.0], [165.1, 72.3],
+	                        [166.4, 55.0], [160.0, 55.9], [152.4, 60.4], [170.2, 69.1], [162.6, 84.5],
+	                        [170.2, 55.9], [158.8, 55.5], [172.7, 69.5], [167.6, 76.4], [162.6, 61.4],
+	                        [167.6, 65.9], [156.2, 58.6], [175.2, 66.8], [172.1, 56.6], [162.6, 58.6],
+	                        [160.0, 55.9], [165.1, 59.1], [182.9, 81.8], [166.4, 70.7], [165.1, 56.8],
+	                        [177.8, 60.0], [165.1, 58.2], [175.3, 72.7], [154.9, 54.1], [158.8, 49.1],
+	                        [172.7, 75.9], [168.9, 55.0], [161.3, 57.3], [167.6, 55.0], [165.1, 65.5],
+	                        [175.3, 65.5], [157.5, 48.6], [163.8, 58.6], [167.6, 63.6], [165.1, 55.2],
+	                        [165.1, 62.7], [168.9, 56.6], [162.6, 53.9], [164.5, 63.2], [176.5, 73.6],
+	                        [168.9, 62.0], [175.3, 63.6], [159.4, 53.2], [160.0, 53.4], [170.2, 55.0],
+	                        [162.6, 70.5], [167.6, 54.5], [162.6, 54.5], [160.7, 55.9], [160.0, 59.0],
+	                        [157.5, 63.6], [162.6, 54.5], [152.4, 47.3], [170.2, 67.7], [165.1, 80.9],
+	                        [172.7, 70.5], [165.1, 60.9], [170.2, 63.6], [170.2, 54.5], [170.2, 59.1],
+	                        [161.3, 70.5], [167.6, 52.7], [167.6, 62.7], [165.1, 86.3], [162.6, 66.4],
+	                        [152.4, 67.3], [168.9, 63.0], [170.2, 73.6], [175.2, 62.3], [175.2, 57.7],
+	                        [160.0, 55.4], [165.1, 104.1], [174.0, 55.5], [170.2, 77.3], [160.0, 80.5],
+	                        [167.6, 64.5], [167.6, 72.3], [167.6, 61.4], [154.9, 58.2], [162.6, 81.8],
+	                        [175.3, 63.6], [171.4, 53.4], [157.5, 54.5], [165.1, 53.6], [160.0, 60.0],
+	                        [174.0, 73.6], [162.6, 61.4], [174.0, 55.5], [162.6, 63.6], [161.3, 60.9],
+	                        [156.2, 60.0], [149.9, 46.8], [169.5, 57.3], [160.0, 64.1], [175.3, 63.6],
+	                        [169.5, 67.3], [160.0, 75.5], [172.7, 68.2], [162.6, 61.4], [157.5, 76.8],
+	                        [176.5, 71.8], [164.4, 55.5], [160.7, 48.6], [174.0, 66.4], [163.8, 67.3]
+	                    ],
+	                    markPoint : {
+	                        data : [
+	                            {type : 'max', name: '最大值'},
+	                            {type : 'min', name: '最小值'}
+	                        ]
+	                    },
+	                    markLine : {
+	                        data : [
+	                            {type : 'average', name: '平均值'}
+	                        ]
+	                    }
+	                },
+	                {
+	                    name:'男性',
+	                    type:'scatter',
+	                    tooltip : {
+	                        trigger: 'item',
+	                        formatter : function (params) {
+	                            if (params.value.length > 1) {
+	                                return params.seriesName + ' :<br/>'
+	                                   + params.value[0] + 'cm '
+	                                   + params.value[1] + 'kg ';
+	                            }
+	                            else {
+	                                return params.seriesName + ' :<br/>'
+	                                   + params.name + ' : '
+	                                   + params.value + 'kg ';
+	                            }
+	                        }
+	                    },
+	                    data: [
+	                        [174.0, 65.6], [175.3, 71.8], [193.5, 80.7], [186.5, 72.6], [187.2, 78.8],
+	                        [181.5, 74.8], [184.0, 86.4], [184.5, 78.4], [175.0, 62.0], [184.0, 81.6],
+	                        [180.0, 76.6], [177.8, 83.6], [192.0, 90.0], [176.0, 74.6], [174.0, 71.0],
+	                        [184.0, 79.6], [192.7, 93.8], [171.5, 70.0], [173.0, 72.4], [176.0, 85.9],
+	                        [176.0, 78.8], [180.5, 77.8], [172.7, 66.2], [176.0, 86.4], [173.5, 81.8],
+	                        [178.0, 89.6], [180.3, 82.8], [180.3, 76.4], [164.5, 63.2], [173.0, 60.9],
+	                        [183.5, 74.8], [175.5, 70.0], [188.0, 72.4], [189.2, 84.1], [172.8, 69.1],
+	                        [170.0, 59.5], [182.0, 67.2], [170.0, 61.3], [177.8, 68.6], [184.2, 80.1],
+	                        [186.7, 87.8], [171.4, 84.7], [172.7, 73.4], [175.3, 72.1], [180.3, 82.6],
+	                        [182.9, 88.7], [188.0, 84.1], [177.2, 94.1], [172.1, 74.9], [167.0, 59.1],
+	                        [169.5, 75.6], [174.0, 86.2], [172.7, 75.3], [182.2, 87.1], [164.1, 55.2],
+	                        [163.0, 57.0], [171.5, 61.4], [184.2, 76.8], [174.0, 86.8], [174.0, 72.2],
+	                        [177.0, 71.6], [186.0, 84.8], [167.0, 68.2], [171.8, 66.1], [182.0, 72.0],
+	                        [167.0, 64.6], [177.8, 74.8], [164.5, 70.0], [192.0, 101.6], [175.5, 63.2],
+	                        [171.2, 79.1], [181.6, 78.9], [167.4, 67.7], [181.1, 66.0], [177.0, 68.2],
+	                        [174.5, 63.9], [177.5, 72.0], [170.5, 56.8], [182.4, 74.5], [197.1, 90.9],
+	                        [180.1, 93.0], [175.5, 80.9], [180.6, 72.7], [184.4, 68.0], [175.5, 70.9],
+	                        [180.6, 72.5], [177.0, 72.5], [177.1, 83.4], [181.6, 75.5], [176.5, 73.0],
+	                        [175.0, 70.2], [174.0, 73.4], [165.1, 70.5], [177.0, 68.9], [192.0, 102.3],
+	                        [176.5, 68.4], [169.4, 65.9], [182.1, 75.7], [179.8, 84.5], [175.3, 87.7],
+	                        [184.9, 86.4], [177.3, 73.2], [167.4, 53.9], [178.1, 72.0], [168.9, 55.5],
+	                        [157.2, 58.4], [180.3, 83.2], [170.2, 72.7], [177.8, 64.1], [172.7, 72.3],
+	                        [165.1, 65.0], [186.7, 86.4], [165.1, 65.0], [174.0, 88.6], [175.3, 84.1],
+	                        [185.4, 66.8], [177.8, 75.5], [180.3, 93.2], [180.3, 82.7], [177.8, 58.0],
+	                        [177.8, 79.5], [177.8, 78.6], [177.8, 71.8], [177.8, 116.4], [163.8, 72.2],
+	                        [188.0, 83.6], [198.1, 85.5], [175.3, 90.9], [166.4, 85.9], [190.5, 89.1],
+	                        [166.4, 75.0], [177.8, 77.7], [179.7, 86.4], [172.7, 90.9], [190.5, 73.6],
+	                        [185.4, 76.4], [168.9, 69.1], [167.6, 84.5], [175.3, 64.5], [170.2, 69.1],
+	                        [190.5, 108.6], [177.8, 86.4], [190.5, 80.9], [177.8, 87.7], [184.2, 94.5],
+	                        [176.5, 80.2], [177.8, 72.0], [180.3, 71.4], [171.4, 72.7], [172.7, 84.1],
+	                        [172.7, 76.8], [177.8, 63.6], [177.8, 80.9], [182.9, 80.9], [170.2, 85.5],
+	                        [167.6, 68.6], [175.3, 67.7], [165.1, 66.4], [185.4, 102.3], [181.6, 70.5],
+	                        [172.7, 95.9], [190.5, 84.1], [179.1, 87.3], [175.3, 71.8], [170.2, 65.9],
+	                        [193.0, 95.9], [171.4, 91.4], [177.8, 81.8], [177.8, 96.8], [167.6, 69.1],
+	                        [167.6, 82.7], [180.3, 75.5], [182.9, 79.5], [176.5, 73.6], [186.7, 91.8],
+	                        [188.0, 84.1], [188.0, 85.9], [177.8, 81.8], [174.0, 82.5], [177.8, 80.5],
+	                        [171.4, 70.0], [185.4, 81.8], [185.4, 84.1], [188.0, 90.5], [188.0, 91.4],
+	                        [182.9, 89.1], [176.5, 85.0], [175.3, 69.1], [175.3, 73.6], [188.0, 80.5],
+	                        [188.0, 82.7], [175.3, 86.4], [170.5, 67.7], [179.1, 92.7], [177.8, 93.6],
+	                        [175.3, 70.9], [182.9, 75.0], [170.8, 93.2], [188.0, 93.2], [180.3, 77.7],
+	                        [177.8, 61.4], [185.4, 94.1], [168.9, 75.0], [185.4, 83.6], [180.3, 85.5],
+	                        [174.0, 73.9], [167.6, 66.8], [182.9, 87.3], [160.0, 72.3], [180.3, 88.6],
+	                        [167.6, 75.5], [186.7, 101.4], [175.3, 91.1], [175.3, 67.3], [175.9, 77.7],
+	                        [175.3, 81.8], [179.1, 75.5], [181.6, 84.5], [177.8, 76.6], [182.9, 85.0],
+	                        [177.8, 102.5], [184.2, 77.3], [179.1, 71.8], [176.5, 87.9], [188.0, 94.3],
+	                        [174.0, 70.9], [167.6, 64.5], [170.2, 77.3], [167.6, 72.3], [188.0, 87.3],
+	                        [174.0, 80.0], [176.5, 82.3], [180.3, 73.6], [167.6, 74.1], [188.0, 85.9],
+	                        [180.3, 73.2], [167.6, 76.3], [183.0, 65.9], [183.0, 90.9], [179.1, 89.1],
+	                        [170.2, 62.3], [177.8, 82.7], [179.1, 79.1], [190.5, 98.2], [177.8, 84.1],
+	                        [180.3, 83.2], [180.3, 83.2]
+	                    ],
+	                    markPoint : {
+	                        data : [
+	                            {type : 'max', name: '最大值'},
+	                            {type : 'min', name: '最小值'}
+	                        ]
+	                    },
+	                    markLine : {
+	                        data : [
+	                            {type : 'average', name: '平均值'}
+	                        ]
+	                    }
+	                }
+	            ]
+	        };
+	        scatterChart.setOption(scatteroption);
+	        $(window).resize(scatterChart.resize);
+	
+	
+	        var kChart = echarts.init(document.getElementById("echarts-k-chart"));
+	        var koption = {
+	            title : {
+	                text: '2013年上半年上证指数'
+	            },
+	            tooltip : {
+	                trigger: 'axis',
+	                formatter: function (params) {
+	                    var res = params[0].seriesName + ' ' + params[0].name;
+	                    res += '<br/>  开盘 : ' + params[0].value[0] + '  最高 : ' + params[0].value[3];
+	                    res += '<br/>  收盘 : ' + params[0].value[1] + '  最低 : ' + params[0].value[2];
+	                    return res;
+	                }
+	            },
+	            legend: {
+	                data:['上证指数']
+	            },
+	            grid:{
+	                x:40,
+	                x2:2
+	            },
+	            dataZoom : {
+	                show : true,
+	                realtime: true,
+	                start : 50,
+	                end : 100
+	            },
+	            xAxis : [
+	                {
+	                    type : 'category',
+	                    boundaryGap : true,
+	                    axisTick: {onGap:false},
+	                    splitLine: {show:false},
+	                    data : [
+	                        "2013/1/24", "2013/1/25", "2013/1/28", "2013/1/29", "2013/1/30",
+	                        "2013/1/31", "2013/2/1", "2013/2/4", "2013/2/5", "2013/2/6",
+	                        "2013/2/7", "2013/2/8", "2013/2/18", "2013/2/19", "2013/2/20",
+	                        "2013/2/21", "2013/2/22", "2013/2/25", "2013/2/26", "2013/2/27",
+	                        "2013/2/28", "2013/3/1", "2013/3/4", "2013/3/5", "2013/3/6",
+	                        "2013/3/7", "2013/3/8", "2013/3/11", "2013/3/12", "2013/3/13",
+	                        "2013/3/14", "2013/3/15", "2013/3/18", "2013/3/19", "2013/3/20",
+	                        "2013/3/21", "2013/3/22", "2013/3/25", "2013/3/26", "2013/3/27",
+	                        "2013/3/28", "2013/3/29", "2013/4/1", "2013/4/2", "2013/4/3",
+	                        "2013/4/8", "2013/4/9", "2013/4/10", "2013/4/11", "2013/4/12",
+	                        "2013/4/15", "2013/4/16", "2013/4/17", "2013/4/18", "2013/4/19",
+	                        "2013/4/22", "2013/4/23", "2013/4/24", "2013/4/25", "2013/4/26",
+	                        "2013/5/2", "2013/5/3", "2013/5/6", "2013/5/7", "2013/5/8",
+	                        "2013/5/9", "2013/5/10", "2013/5/13", "2013/5/14", "2013/5/15",
+	                        "2013/5/16", "2013/5/17", "2013/5/20", "2013/5/21", "2013/5/22",
+	                        "2013/5/23", "2013/5/24", "2013/5/27", "2013/5/28", "2013/5/29",
+	                        "2013/5/30", "2013/5/31", "2013/6/3", "2013/6/4", "2013/6/5",
+	                        "2013/6/6", "2013/6/7", "2013/6/13"
+	                    ]
+	                }
+	            ],
+	            yAxis : [
+	                {
+	                    type : 'value',
+	                    scale:true,
+	                    boundaryGap: [0.01, 0.01]
+	                }
+	            ],
+	            series : [
+	                {
+	                    name:'上证指数',
+	                    type:'k',
+	                    data:[ // 开盘,收盘,最低,最高
+	                        [2320.26,2302.6,2287.3,2362.94],
+	                        [2300,2291.3,2288.26,2308.38],
+	                        [2295.35,2346.5,2295.35,2346.92],
+	                        [2347.22,2358.98,2337.35,2363.8],
+	                        [2360.75,2382.48,2347.89,2383.76],
+	                        [2383.43,2385.42,2371.23,2391.82],
+	                        [2377.41,2419.02,2369.57,2421.15],
+	                        [2425.92,2428.15,2417.58,2440.38],
+	                        [2411,2433.13,2403.3,2437.42],
+	                        [2432.68,2434.48,2427.7,2441.73],
+	                        [2430.69,2418.53,2394.22,2433.89],
+	                        [2416.62,2432.4,2414.4,2443.03],
+	                        [2441.91,2421.56,2415.43,2444.8],
+	                        [2420.26,2382.91,2373.53,2427.07],
+	                        [2383.49,2397.18,2370.61,2397.94],
+	                        [2378.82,2325.95,2309.17,2378.82],
+	                        [2322.94,2314.16,2308.76,2330.88],
+	                        [2320.62,2325.82,2315.01,2338.78],
+	                        [2313.74,2293.34,2289.89,2340.71],
+	                        [2297.77,2313.22,2292.03,2324.63],
+	                        [2322.32,2365.59,2308.92,2366.16],
+	                        [2364.54,2359.51,2330.86,2369.65],
+	                        [2332.08,2273.4,2259.25,2333.54],
+	                        [2274.81,2326.31,2270.1,2328.14],
+	                        [2333.61,2347.18,2321.6,2351.44],
+	                        [2340.44,2324.29,2304.27,2352.02],
+	                        [2326.42,2318.61,2314.59,2333.67],
+	                        [2314.68,2310.59,2296.58,2320.96],
+	                        [2309.16,2286.6,2264.83,2333.29],
+	                        [2282.17,2263.97,2253.25,2286.33],
+	                        [2255.77,2270.28,2253.31,2276.22],
+	                        [2269.31,2278.4,2250,2312.08],
+	                        [2267.29,2240.02,2239.21,2276.05],
+	                        [2244.26,2257.43,2232.02,2261.31],
+	                        [2257.74,2317.37,2257.42,2317.86],
+	                        [2318.21,2324.24,2311.6,2330.81],
+	                        [2321.4,2328.28,2314.97,2332],
+	                        [2334.74,2326.72,2319.91,2344.89],
+	                        [2318.58,2297.67,2281.12,2319.99],
+	                        [2299.38,2301.26,2289,2323.48],
+	                        [2273.55,2236.3,2232.91,2273.55],
+	                        [2238.49,2236.62,2228.81,2246.87],
+	                        [2229.46,2234.4,2227.31,2243.95],
+	                        [2234.9,2227.74,2220.44,2253.42],
+	                        [2232.69,2225.29,2217.25,2241.34],
+	                        [2196.24,2211.59,2180.67,2212.59],
+	                        [2215.47,2225.77,2215.47,2234.73],
+	                        [2224.93,2226.13,2212.56,2233.04],
+	                        [2236.98,2219.55,2217.26,2242.48],
+	                        [2218.09,2206.78,2204.44,2226.26],
+	                        [2199.91,2181.94,2177.39,2204.99],
+	                        [2169.63,2194.85,2165.78,2196.43],
+	                        [2195.03,2193.8,2178.47,2197.51],
+	                        [2181.82,2197.6,2175.44,2206.03],
+	                        [2201.12,2244.64,2200.58,2250.11],
+	                        [2236.4,2242.17,2232.26,2245.12],
+	                        [2242.62,2184.54,2182.81,2242.62],
+	                        [2187.35,2218.32,2184.11,2226.12],
+	                        [2213.19,2199.31,2191.85,2224.63],
+	                        [2203.89,2177.91,2173.86,2210.58],
+	                        [2170.78,2174.12,2161.14,2179.65],
+	                        [2179.05,2205.5,2179.05,2222.81],
+	                        [2212.5,2231.17,2212.5,2236.07],
+	                        [2227.86,2235.57,2219.44,2240.26],
+	                        [2242.39,2246.3,2235.42,2255.21],
+	                        [2246.96,2232.97,2221.38,2247.86],
+	                        [2228.82,2246.83,2225.81,2247.67],
+	                        [2247.68,2241.92,2231.36,2250.85],
+	                        [2238.9,2217.01,2205.87,2239.93],
+	                        [2217.09,2224.8,2213.58,2225.19],
+	                        [2221.34,2251.81,2210.77,2252.87],
+	                        [2249.81,2282.87,2248.41,2288.09],
+	                        [2286.33,2299.99,2281.9,2309.39],
+	                        [2297.11,2305.11,2290.12,2305.3],
+	                        [2303.75,2302.4,2292.43,2314.18],
+	                        [2293.81,2275.67,2274.1,2304.95],
+	                        [2281.45,2288.53,2270.25,2292.59],
+	                        [2286.66,2293.08,2283.94,2301.7],
+	                        [2293.4,2321.32,2281.47,2322.1],
+	                        [2323.54,2324.02,2321.17,2334.33],
+	                        [2316.25,2317.75,2310.49,2325.72],
+	                        [2320.74,2300.59,2299.37,2325.53],
+	                        [2300.21,2299.25,2294.11,2313.43],
+	                        [2297.1,2272.42,2264.76,2297.1],
+	                        [2270.71,2270.93,2260.87,2276.86],
+	                        [2264.43,2242.11,2240.07,2266.69],
+	                        [2242.26,2210.9,2205.07,2250.63],
+	                        [2190.1,2148.35,2126.22,2190.1]
+	                    ]
+	                }
+	            ]
+	        };
+	        kChart.setOption(koption);
+	        $(window).resize(kChart.resize);
+	
+	        var pieChart = echarts.init(document.getElementById("echarts-pie-chart"));
+	        var pieoption = {
+	            title : {
+	                text: '某站点用户访问来源',
+	                subtext: '纯属虚构',
+	                x:'center'
+	            },
+	            tooltip : {
+	                trigger: 'item',
+	                formatter: "{a} <br/>{b} : {c} ({d}%)"
+	            },
+	            legend: {
+	                orient : 'vertical',
+	                x : 'left',
+	                data:['直接访问','邮件营销','联盟广告','视频广告','搜索引擎']
+	            },
+	            calculable : true,
+	            series : [
+	                {
+	                    name:'访问来源',
+	                    type:'pie',
+	                    radius : '55%',
+	                    center: ['50%', '60%'],
+	                    data:[
+	                        {value:335, name:'直接访问'},
+	                        {value:310, name:'邮件营销'},
+	                        {value:234, name:'联盟广告'},
+	                        {value:135, name:'视频广告'},
+	                        {value:1548, name:'搜索引擎'}
+	                    ]
+	                }
+	            ]
+	        };
+	        pieChart.setOption(pieoption);
+	        $(window).resize(pieChart.resize);
+	
+	        var radarChart = echarts.init(document.getElementById("echarts-radar-chart"));
+	        var radaroption = {
+	            title : {
+	                text: '预算 vs 开销',
+	                subtext: '纯属虚构'
+	            },
+	            tooltip : {
+	                trigger: 'axis'
+	            },
+	            legend: {
+	                orient : 'vertical',
+	                x : 'right',
+	                y : 'bottom',
+	                data:['预算分配','实际开销']
+	            },
+	            polar : [
+	               {
+	                   indicator : [
+	                       { text: '销售', max: 6000},
+	                       { text: '管理', max: 16000},
+	                       { text: '信息技术', max: 30000},
+	                       { text: '客服', max: 38000},
+	                       { text: '研发', max: 52000},
+	                       { text: '市场', max: 25000}
+	                    ]
+	                }
+	            ],
+	            calculable : true,
+	            series : [
+	                {
+	                    name: '预算 vs 开销',
+	                    type: 'radar',
+	                    data : [
+	                        {
+	                            value : [4300, 10000, 28000, 35000, 50000, 19000],
+	                            name : '预算分配'
+	                        },
+	                         {
+	                            value : [5000, 14000, 28000, 31000, 42000, 21000],
+	                            name : '实际开销'
+	                        }
+	                    ]
+	                }
+	            ]
+	        };
+	
+	        radarChart.setOption(radaroption);
+	        $(window).resize(radarChart.resize);
+	
+	        var mapChart = echarts.init(document.getElementById("echarts-map-chart"));
+	        var mapoption = {
+	            title : {
+	                text: 'iphone销量',
+	                subtext: '纯属虚构',
+	                x:'center'
+	            },
+	            tooltip : {
+	                trigger: 'item'
+	            },
+	            legend: {
+	                orient: 'vertical',
+	                x:'left',
+	                data:['iphone3','iphone4','iphone5']
+	            },
+	            dataRange: {
+	                min: 0,
+	                max: 2500,
+	                x: 'left',
+	                y: 'bottom',
+	                text:['高','低'],           // 文本,默认为数值文本
+	                calculable : true
+	            },
+	            toolbox: {
+	                show: true,
+	                orient : 'vertical',
+	                x: 'right',
+	                y: 'center',
+	                feature : {
+	                    mark : {show: true},
+	                    dataView : {show: true, readOnly: false},
+	                    restore : {show: true},
+	                    saveAsImage : {show: true}
+	                }
+	            },
+	            roamController: {
+	                show: true,
+	                x: 'right',
+	                mapTypeControl: {
+	                    'china': true
+	                }
+	            },
+	            series : [
+	                {
+	                    name: 'iphone3',
+	                    type: 'map',
+	                    mapType: 'china',
+	                    roam: false,
+	                    itemStyle:{
+	                        normal:{label:{show:true}},
+	                        emphasis:{label:{show:true}}
+	                    },
+	                    data:[
+	                        {name: '北京',value: Math.round(Math.random()*1000)},
+	                        {name: '天津',value: Math.round(Math.random()*1000)},
+	                        {name: '上海',value: Math.round(Math.random()*1000)},
+	                        {name: '重庆',value: Math.round(Math.random()*1000)},
+	                        {name: '河北',value: Math.round(Math.random()*1000)},
+	                        {name: '河南',value: Math.round(Math.random()*1000)},
+	                        {name: '云南',value: Math.round(Math.random()*1000)},
+	                        {name: '辽宁',value: Math.round(Math.random()*1000)},
+	                        {name: '黑龙江',value: Math.round(Math.random()*1000)},
+	                        {name: '湖南',value: Math.round(Math.random()*1000)},
+	                        {name: '安徽',value: Math.round(Math.random()*1000)},
+	                        {name: '山东',value: Math.round(Math.random()*1000)},
+	                        {name: '新疆',value: Math.round(Math.random()*1000)},
+	                        {name: '江苏',value: Math.round(Math.random()*1000)},
+	                        {name: '浙江',value: Math.round(Math.random()*1000)},
+	                        {name: '江西',value: Math.round(Math.random()*1000)},
+	                        {name: '湖北',value: Math.round(Math.random()*1000)},
+	                        {name: '广西',value: Math.round(Math.random()*1000)},
+	                        {name: '甘肃',value: Math.round(Math.random()*1000)},
+	                        {name: '山西',value: Math.round(Math.random()*1000)},
+	                        {name: '内蒙古',value: Math.round(Math.random()*1000)},
+	                        {name: '陕西',value: Math.round(Math.random()*1000)},
+	                        {name: '吉林',value: Math.round(Math.random()*1000)},
+	                        {name: '福建',value: Math.round(Math.random()*1000)},
+	                        {name: '贵州',value: Math.round(Math.random()*1000)},
+	                        {name: '广东',value: Math.round(Math.random()*1000)},
+	                        {name: '青海',value: Math.round(Math.random()*1000)},
+	                        {name: '西藏',value: Math.round(Math.random()*1000)},
+	                        {name: '四川',value: Math.round(Math.random()*1000)},
+	                        {name: '宁夏',value: Math.round(Math.random()*1000)},
+	                        {name: '海南',value: Math.round(Math.random()*1000)},
+	                        {name: '台湾',value: Math.round(Math.random()*1000)},
+	                        {name: '香港',value: Math.round(Math.random()*1000)},
+	                        {name: '澳门',value: Math.round(Math.random()*1000)}
+	                    ]
+	                },
+	                {
+	                    name: 'iphone4',
+	                    type: 'map',
+	                    mapType: 'china',
+	                    itemStyle:{
+	                        normal:{label:{show:true}},
+	                        emphasis:{label:{show:true}}
+	                    },
+	                    data:[
+	                        {name: '北京',value: Math.round(Math.random()*1000)},
+	                        {name: '天津',value: Math.round(Math.random()*1000)},
+	                        {name: '上海',value: Math.round(Math.random()*1000)},
+	                        {name: '重庆',value: Math.round(Math.random()*1000)},
+	                        {name: '河北',value: Math.round(Math.random()*1000)},
+	                        {name: '安徽',value: Math.round(Math.random()*1000)},
+	                        {name: '新疆',value: Math.round(Math.random()*1000)},
+	                        {name: '浙江',value: Math.round(Math.random()*1000)},
+	                        {name: '江西',value: Math.round(Math.random()*1000)},
+	                        {name: '山西',value: Math.round(Math.random()*1000)},
+	                        {name: '内蒙古',value: Math.round(Math.random()*1000)},
+	                        {name: '吉林',value: Math.round(Math.random()*1000)},
+	                        {name: '福建',value: Math.round(Math.random()*1000)},
+	                        {name: '广东',value: Math.round(Math.random()*1000)},
+	                        {name: '西藏',value: Math.round(Math.random()*1000)},
+	                        {name: '四川',value: Math.round(Math.random()*1000)},
+	                        {name: '宁夏',value: Math.round(Math.random()*1000)},
+	                        {name: '香港',value: Math.round(Math.random()*1000)},
+	                        {name: '澳门',value: Math.round(Math.random()*1000)}
+	                    ]
+	                },
+	                {
+	                    name: 'iphone5',
+	                    type: 'map',
+	                    mapType: 'china',
+	                    itemStyle:{
+	                        normal:{label:{show:true}},
+	                        emphasis:{label:{show:true}}
+	                    },
+	                    data:[
+	                        {name: '北京',value: Math.round(Math.random()*1000)},
+	                        {name: '天津',value: Math.round(Math.random()*1000)},
+	                        {name: '上海',value: Math.round(Math.random()*1000)},
+	                        {name: '广东',value: Math.round(Math.random()*1000)},
+	                        {name: '台湾',value: Math.round(Math.random()*1000)},
+	                        {name: '香港',value: Math.round(Math.random()*1000)},
+	                        {name: '澳门',value: Math.round(Math.random()*1000)}
+	                    ]
+	                }
+	            ]
+	        };
+	        mapChart.setOption(mapoption);
+	        $(window).resize(mapChart.resize);
+	
+	        var gaugeChart = echarts.init(document.getElementById("echarts-gauge-chart"));
+	        var gaugeoption = {
+	            tooltip : {
+	                formatter: "{a} <br/>{c} {b}"
+	            },
+	            toolbox: {
+	                show : true,
+	                feature : {
+	                    mark : {show: true},
+	                    restore : {show: true},
+	                    saveAsImage : {show: true}
+	                }
+	            },
+	            series : [
+	                {
+	                    name:'速度',
+	                    type:'gauge',
+	                    min:0,
+	                    max:220,
+	                    splitNumber:11,
+	                    axisLine: {            // 坐标轴线
+	                        lineStyle: {       // 属性lineStyle控制线条样式
+	                            width: 10
+	                        }
+	                    },
+	                    axisTick: {            // 坐标轴小标记
+	                        length :15,        // 属性length控制线长
+	                        lineStyle: {       // 属性lineStyle控制线条样式
+	                            color: 'auto'
+	                        }
+	                    },
+	                    splitLine: {           // 分隔线
+	                        length :20,         // 属性length控制线长
+	                        lineStyle: {       // 属性lineStyle(详见lineStyle)控制线条样式
+	                            color: 'auto'
+	                        }
+	                    },
+	                    title : {
+	                        textStyle: {       // 其余属性默认使用全局文本样式,详见TEXTSTYLE
+	                            fontWeight: 'bolder',
+	                            fontSize: 20,
+	                            fontStyle: 'italic'
+	                        }
+	                    },
+	                    detail : {
+	                        textStyle: {       // 其余属性默认使用全局文本样式,详见TEXTSTYLE
+	                            fontWeight: 'bolder'
+	                        }
+	                    },
+	                    data:[{value: 40, name: 'km/h'}]
+	                },
+	                {
+	                    name:'转速',
+	                    type:'gauge',
+	                    center : ['25%', '55%'],    // 默认全局居中
+	                    radius : '50%',
+	                    min:0,
+	                    max:7,
+	                    endAngle:45,
+	                    splitNumber:7,
+	                    axisLine: {            // 坐标轴线
+	                        lineStyle: {       // 属性lineStyle控制线条样式
+	                            width: 8
+	                        }
+	                    },
+	                    axisTick: {            // 坐标轴小标记
+	                        length :12,        // 属性length控制线长
+	                        lineStyle: {       // 属性lineStyle控制线条样式
+	                            color: 'auto'
+	                        }
+	                    },
+	                    splitLine: {           // 分隔线
+	                        length :20,         // 属性length控制线长
+	                        lineStyle: {       // 属性lineStyle(详见lineStyle)控制线条样式
+	                            color: 'auto'
+	                        }
+	                    },
+	                    pointer: {
+	                        width:5
+	                    },
+	                    title : {
+	                        offsetCenter: [0, '-30%'],       // x, y,单位px
+	                    },
+	                    detail : {
+	                        textStyle: {       // 其余属性默认使用全局文本样式,详见TEXTSTYLE
+	                            fontWeight: 'bolder'
+	                        }
+	                    },
+	                    data:[{value: 1.5, name: 'x1000 r/min'}]
+	                },
+	                {
+	                    name:'油表',
+	                    type:'gauge',
+	                    center : ['75%', '50%'],    // 默认全局居中
+	                    radius : '50%',
+	                    min:0,
+	                    max:2,
+	                    startAngle:135,
+	                    endAngle:45,
+	                    splitNumber:2,
+	                    axisLine: {            // 坐标轴线
+	                        lineStyle: {       // 属性lineStyle控制线条样式
+	                            color: [
+	                                     [0.2, '#ff4500'],[0.8, '#48b'],[1, '#228b22']
+	                                   ],
+	                            width: 8
+	                        }
+	                    },
+	                    axisTick: {            // 坐标轴小标记
+	                        splitNumber:5,
+	                        length :10,        // 属性length控制线长
+	                        lineStyle: {       // 属性lineStyle控制线条样式
+	                            color: 'auto'
+	                        }
+	                    },
+	                    axisLabel: {
+	                        formatter:function(v){
+	                            switch (v + '') {
+	                                case '0' : return 'E';
+	                                case '1' : return 'Gas';
+	                                case '2' : return 'F';
+	                            }
+	                        }
+	                    },
+	                    splitLine: {           // 分隔线
+	                        length :15,         // 属性length控制线长
+	                        lineStyle: {       // 属性lineStyle(详见lineStyle)控制线条样式
+	                            color: 'auto'
+	                        }
+	                    },
+	                    pointer: {
+	                        width:2
+	                    },
+	                    title : {
+	                        show: false
+	                    },
+	                    detail : {
+	                        show: false
+	                    },
+	                    data:[{value: 0.5, name: 'gas'}]
+	                },
+	                {
+	                    name:'水表',
+	                    type:'gauge',
+	                    center : ['75%', '50%'],    // 默认全局居中
+	                    radius : '50%',
+	                    min:0,
+	                    max:2,
+	                    startAngle:315,
+	                    endAngle:225,
+	                    splitNumber:2,
+	                    axisLine: {            // 坐标轴线
+	                        lineStyle: {       // 属性lineStyle控制线条样式
+	                            color: [
+	                                     [0.2, '#ff4500'],[0.8, '#48b'],[1, '#228b22']
+	                                   ],
+	                            width: 8
+	                        }
+	                    },
+	                    axisTick: {            // 坐标轴小标记
+	                        show: false
+	                    },
+	                    axisLabel: {
+	                        formatter:function(v){
+	                            switch (v + '') {
+	                                case '0' : return 'H';
+	                                case '1' : return 'Water';
+	                                case '2' : return 'C';
+	                            }
+	                        }
+	                    },
+	                    splitLine: {           // 分隔线
+	                        length :15,         // 属性length控制线长
+	                        lineStyle: {       // 属性lineStyle(详见lineStyle)控制线条样式
+	                            color: 'auto'
+	                        }
+	                    },
+	                    pointer: {
+	                        width:2
+	                    },
+	                    title : {
+	                        show: false
+	                    },
+	                    detail : {
+	                        show: false
+	                    },
+	                    data:[{value: 0.5, name: 'gas'}]
+	                }
+	            ]
+	        };
+	        gaugeChart.setOption(gaugeoption);
+	        $(window).resize(gaugeChart.resize);
+	
+	        var funnelChart = echarts.init(document.getElementById("echarts-funnel-chart"));
+	        var funneloption = {
+	            title : {
+	                text: '漏斗图',
+	                subtext: '纯属虚构'
+	            },
+	            tooltip : {
+	                trigger: 'item',
+	                formatter: "{a} <br/>{b} : {c}%"
+	            },
+	            legend: {
+	                data : ['展现','点击','访问','咨询','订单']
+	            },
+	            calculable : true,
+	            series : [
+	                {
+	                    name:'漏斗图',
+	                    type:'funnel',
+	                    width: '40%',
+	                    data:[
+	                        {value:60, name:'访问'},
+	                        {value:40, name:'咨询'},
+	                        {value:20, name:'订单'},
+	                        {value:80, name:'点击'},
+	                        {value:100, name:'展现'}
+	                    ]
+	                },
+	                {
+	                    name:'金字塔',
+	                    type:'funnel',
+	                    x : '50%',
+	                    sort : 'ascending',
+	                    itemStyle: {
+	                        normal: {
+	                            // color: 各异,
+	                            label: {
+	                                position: 'left'
+	                            }
+	                        }
+	                    },
+	                    data:[
+	                        {value:60, name:'访问'},
+	                        {value:40, name:'咨询'},
+	                        {value:20, name:'订单'},
+	                        {value:80, name:'点击'},
+	                        {value:100, name:'展现'}
+	                    ]
+	                }
+	            ]
+	        };
+	
+	        funnelChart.setOption(funneloption);
+	        $(window).resize(funnelChart.resize);
+	
+	    });
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/demo/report/metrics.html b/ruoyi-admin/src/main/resources/templates/demo/report/metrics.html
new file mode 100644
index 0000000..853f672
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/report/metrics.html
@@ -0,0 +1,478 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('图表组合')" />
+</head>
+<body class="gray-bg">
+    <div class="wrapper wrapper-content animated fadeInRight">
+        <div class="row">
+            <div class="col-sm-3">
+                <div class="ibox">
+                    <div class="ibox-content">
+                        <h5 class="m-b-md">Q1 销量</h5>
+                        <h2 class="text-navy">
+                                    <i class="fa fa-play fa-rotate-270"></i> 上升
+                                </h2>
+                        <small>更新时间:12天以前</small>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-3">
+                <div class="ibox">
+                    <div class="ibox-content ">
+                        <h5 class="m-b-md">Q2 销量</h5>
+                        <h2 class="text-navy">
+                                    <i class="fa fa-play fa-rotate-270"></i> 上升
+                                </h2>
+                        <small>更新时间:12天以前</small>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-3">
+                <div class="ibox">
+                    <div class="ibox-content">
+                        <h5 class="m-b-md">Q3 销量</h5>
+                        <h2 class="text-danger">
+                                    <i class="fa fa-play fa-rotate-90"></i> 下降
+                                </h2>
+                        <small>更新时间:12天以前</small>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-3">
+                <div class="ibox">
+                    <div class="ibox-content">
+                        <h5 class="m-b-md">Q4 销量</h5>
+                        <h2 class="text-danger">
+                                    <i class="fa fa-play fa-rotate-90"></i> 下降
+                                </h2>
+                        <small>更新时间:12天以前</small>
+                    </div>
+                </div>
+            </div>
+
+        </div>
+        <div class="row">
+            <div class="col-sm-3">
+                <div class="ibox">
+                    <div class="ibox-content">
+                        <h5>本日访问量</h5>
+                        <h2>198 009</h2>
+                        <div id="sparkline1"></div>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-3">
+                <div class="ibox">
+                    <div class="ibox-content">
+                        <h5>本周访问量</h5>
+                        <h2>65 000</h2>
+                        <div id="sparkline2"></div>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-3">
+                <div class="ibox">
+                    <div class="ibox-content">
+                        <h5>本月访问量</h5>
+                        <h2>680 900</h2>
+                        <div id="sparkline3"></div>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-3">
+                <div class="ibox">
+                    <div class="ibox-content">
+                        <h5>平均停留时间</h5>
+                        <h2>00:06:40</h2>
+                        <div id="sparkline4"></div>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div class="row">
+            <div class="col-sm-3">
+                <div class="ibox">
+                    <div class="ibox-content">
+                        <h5>使用率</h5>
+                        <h2>65%</h2>
+                        <div class="progress progress-mini">
+                            <div style="width: 68%;" class="progress-bar"></div>
+                        </div>
+
+                        <div class="m-t-sm small">4:32更新</div>
+                    </div>
+                </div>
+            </div>
+
+            <div class="col-sm-3">
+                <div class="ibox">
+                    <div class="ibox-content">
+                        <h5>使用率</h5>
+                        <h2>50%</h2>
+                        <div class="progress progress-mini">
+                            <div style="width: 78%;" class="progress-bar"></div>
+                        </div>
+
+                        <div class="m-t-sm small">4:32更新</div>
+                    </div>
+                </div>
+            </div>
+
+            <div class="col-sm-3">
+                <div class="ibox">
+                    <div class="ibox-content">
+                        <h5>使用率</h5>
+                        <h2>14%</h2>
+                        <div class="progress progress-mini">
+                            <div style="width: 38%;" class="progress-bar progress-bar-danger"></div>
+                        </div>
+
+                        <div class="m-t-sm small">4:32更新</div>
+                    </div>
+                </div>
+            </div>
+
+            <div class="col-sm-3">
+                <div class="ibox">
+                    <div class="ibox-content">
+                        <h5>使用率</h5>
+                        <h2>20%</h2>
+                        <div class="progress progress-mini">
+                            <div style="width: 28%;" class="progress-bar progress-bar-danger"></div>
+                        </div>
+
+                        <div class="m-t-sm small">4:32更新</div>
+                    </div>
+                </div>
+            </div>
+        </div>
+
+        <div class="row">
+            <div class="col-sm-3">
+                <div class="ibox">
+                    <div class="ibox-content">
+                        <h5>百分比</h5>
+                        <h2>42/20</h2>
+                        <div class="text-center">
+                            <div id="sparkline5"></div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-3">
+                <div class="ibox">
+                    <div class="ibox-content">
+                        <h5>百分比</h5>
+                        <h2>100/54</h2>
+                        <div class="text-center">
+                            <div id="sparkline6"></div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-3">
+                <div class="ibox">
+                    <div class="ibox-content">
+                        <h5>百分比</h5>
+                        <h2>685/211</h2>
+                        <div class="text-center">
+                            <div id="sparkline7"></div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-3">
+                <div class="ibox">
+                    <div class="ibox-content">
+                        <h5>百分比</h5>
+                        <h2>240/32</h2>
+                        <div class="text-center">
+                            <div id="sparkline8"></div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div class="row">
+            <div class="col-sm-3">
+                <div class="ibox">
+                    <div class="ibox-content">
+                        <h5>收入</h5>
+                        <h1 class="no-margins">886,200</h1>
+                        <div class="stat-percent font-bold text-navy">98% <i class="fa fa-bolt"></i></div>
+                        <small>总收入</small>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-3">
+                <div class="ibox">
+                    <div class="ibox-content">
+                        <h5>本月收入</h5>
+                        <h1 class="no-margins">1 738,200</h1>
+                        <div class="stat-percent font-bold text-navy">98% <i class="fa fa-bolt"></i></div>
+                        <small>总收入</small>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-3">
+                <div class="ibox">
+                    <div class="ibox-content">
+                        <h5>本日收入</h5>
+                        <h1 class="no-margins">-200,100</h1>
+                        <div class="stat-percent font-bold text-danger">12% <i class="fa fa-level-down"></i></div>
+                        <small>总收入</small>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-3">
+                <div class="ibox">
+                    <div class="ibox-content">
+                        <h5>搜索有收入</h5>
+                        <h1 class="no-margins">54,200</h1>
+                        <div class="stat-percent font-bold text-danger">24% <i class="fa fa-level-down"></i></div>
+                        <small>总收入</small>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div class="row">
+            <div class="col-sm-3">
+                <div class="ibox">
+                    <div class="ibox-content">
+                        <h5>预警</h5>
+                        <table class="table table-stripped small m-t-md">
+                            <tbody>
+                                <tr>
+                                    <td class="no-borders">
+                                        <i class="fa fa-circle text-navy"></i>
+                                    </td>
+                                    <td class="no-borders">
+                                        示例 01
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td>
+                                        <i class="fa fa-circle text-navy"></i>
+                                    </td>
+                                    <td>
+                                        示例 02
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td>
+                                        <i class="fa fa-circle text-navy"></i>
+                                    </td>
+                                    <td>
+                                        示例 03
+                                    </td>
+                                </tr>
+                            </tbody>
+                        </table>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-3">
+                <div class="ibox">
+                    <div class="ibox-content">
+                        <h5>项目</h5>
+                        <table class="table table-stripped small m-t-md">
+                            <tbody>
+                                <tr>
+                                    <td class="no-borders">
+                                        <i class="fa fa-circle text-navy"></i>
+                                    </td>
+                                    <td class="no-borders">
+                                        示例 01
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td>
+                                        <i class="fa fa-circle text-navy"></i>
+                                    </td>
+                                    <td>
+                                        示例 02
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td>
+                                        <i class="fa fa-circle text-navy"></i>
+                                    </td>
+                                    <td>
+                                        示例 03
+                                    </td>
+                                </tr>
+                            </tbody>
+                        </table>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-3">
+                <div class="ibox">
+                    <div class="ibox-content">
+                        <h5>消息</h5>
+                        <table class="table table-stripped small m-t-md">
+                            <tbody>
+                                <tr>
+                                    <td class="no-borders">
+                                        <i class="fa fa-circle text-danger"></i>
+                                    </td>
+                                    <td class="no-borders">
+                                        示例 01
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td>
+                                        <i class="fa fa-circle text-danger"></i>
+                                    </td>
+                                    <td>
+                                        示例 02
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td>
+                                        <i class="fa fa-circle text-danger"></i>
+                                    </td>
+                                    <td>
+                                        示例 03
+                                    </td>
+                                </tr>
+                            </tbody>
+                        </table>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-3">
+                <div class="ibox">
+                    <div class="ibox-content">
+                        <h5>通知</h5>
+                        <table class="table table-stripped small m-t-md">
+                            <tbody>
+                                <tr>
+                                    <td class="no-borders">
+                                        <i class="fa fa-circle text-danger"></i>
+                                    </td>
+                                    <td class="no-borders">
+                                        示例 01
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td>
+                                        <i class="fa fa-circle text-danger"></i>
+                                    </td>
+                                    <td>
+                                        示例 02
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td>
+                                        <i class="fa fa-circle text-danger"></i>
+                                    </td>
+                                    <td>
+                                        示例 03
+                                    </td>
+                                </tr>
+                            </tbody>
+                        </table>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <th:block th:include="include :: footer" />
+    <th:block th:include="include :: peity-js" />
+    <th:block th:include="include :: sparkline-js" />
+    <script type="text/javascript">
+	    $(document).ready(function () {
+	        $("#sparkline1").sparkline([34, 43, 43, 35, 44, 32, 44, 52], {
+	            type: 'line',
+	            width: '100%',
+	            height: '60',
+	            lineColor: '#1ab394',
+	            fillColor: "#ffffff"
+	        });
+	
+	        $("#sparkline2").sparkline([24, 43, 43, 55, 44, 62, 44, 72], {
+	            type: 'line',
+	            width: '100%',
+	            height: '60',
+	            lineColor: '#1ab394',
+	            fillColor: "#ffffff"
+	        });
+	
+	        $("#sparkline3").sparkline([74, 43, 23, 55, 54, 32, 24, 12], {
+	            type: 'line',
+	            width: '100%',
+	            height: '60',
+	            lineColor: '#ed5565',
+	            fillColor: "#ffffff"
+	        });
+	
+	        $("#sparkline4").sparkline([24, 43, 33, 55, 64, 72, 44, 22], {
+	            type: 'line',
+	            width: '100%',
+	            height: '60',
+	            lineColor: '#ed5565',
+	            fillColor: "#ffffff"
+	        });
+	
+	        $("#sparkline5").sparkline([1, 4], {
+	            type: 'pie',
+	            height: '140',
+	            sliceColors: ['#1ab394', '#F5F5F5']
+	        });
+	
+	        $("#sparkline6").sparkline([5, 3], {
+	            type: 'pie',
+	            height: '140',
+	            sliceColors: ['#1ab394', '#F5F5F5']
+	        });
+	
+	        $("#sparkline7").sparkline([2, 2], {
+	            type: 'pie',
+	            height: '140',
+	            sliceColors: ['#ed5565', '#F5F5F5']
+	        });
+	
+	        $("#sparkline8").sparkline([2, 3], {
+	            type: 'pie',
+	            height: '140',
+	            sliceColors: ['#ed5565', '#F5F5F5']
+	        });
+	    });
+	    
+	    $(function() {
+	        $("span.pie").peity("pie", {
+	            fill: ['#1ab394', '#d7d7d7', '#ffffff']
+	        })
+	
+	        $(".line").peity("line",{
+	            fill: '#1ab394',
+	            stroke:'#169c81',
+	        })
+	
+	        $(".bar").peity("bar", {
+	            fill: ["#1ab394", "#d7d7d7"]
+	        })
+	
+	        $(".bar_dashboard").peity("bar", {
+	            fill: ["#1ab394", "#d7d7d7"],
+	            width:100
+	        })
+	
+	        var updatingChart = $(".updating-chart").peity("line", { fill: '#1ab394',stroke:'#169c81', width: 64 })
+	
+	        setInterval(function() {
+	            var random = Math.round(Math.random() * 10)
+	            var values = updatingChart.text().split(",")
+	            values.shift()
+	            values.push(random)
+	
+	            updatingChart
+	                .text(values.join(","))
+	                .change()
+	        }, 1000);
+	    });
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/demo/report/peity.html b/ruoyi-admin/src/main/resources/templates/demo/report/peity.html
new file mode 100644
index 0000000..93c5194
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/report/peity.html
@@ -0,0 +1,206 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('图表')" />
+</head>
+<body class="gray-bg">
+    <div class="wrapper wrapper-content animated fadeInDown">
+
+        <div class="row">
+            <div class="col-sm-5">
+                <div class="jumbotron">
+                    <h1>Peity图表</h1>
+                    <p>是一个内嵌数据图形可视化的图表库</p>
+                    <p><a href="http://benpickles.github.io/peity/" target="_blank" class="btn btn-primary btn-lg" role="button">了解 Peity</a>
+                    </p>
+                </div>
+            </div>
+            <div class="col-sm-7">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>饼状图 <small>自定义颜色</small></h5>
+                        <div class="ibox-tools">
+                            <a class="close-link">
+                                <i class="fa fa-times"></i>
+                            </a>
+                        </div>
+                    </div>
+                    <div>
+                        <table class="table table-bordered white-bg">
+                            <thead>
+                                <tr>
+                                    <th>图表</th>
+                                    <th>代码</th>
+                                </tr>
+                            </thead>
+
+                            <tbody>
+                                <tr>
+                                    <td>
+                                        <span class="pie">1/5</span>
+                                    </td>
+                                    <td>
+                                        <code>&lt;span class="pie"&gt;1/5&lt;/span&gt;</code>
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td>
+                                        <span class="pie">226/360</span>
+                                    </td>
+                                    <td>
+                                        <code>&lt;span class="pie"&gt;226/360&lt;/span&gt;</code>
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td>
+                                        <span class="pie">0.52/1.561</span>
+                                    </td>
+                                    <td>
+                                        <code>&lt;span class="pie"&gt;0.52/1.561&lt;/span&gt;</code>
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td>
+                                        <span class="pie">1,4</span>
+                                    </td>
+                                    <td>
+                                        <code>&lt;span class="pie"&gt;1,4&lt;/span&gt;</code>
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td>
+                                        <span class="pie">226,134</span>
+                                    </td>
+                                    <td>
+                                        <code>&lt;span class="pie"&gt;226,134&lt;/span&gt;</code>
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td>
+                                        <span class="pie">0.52,1.041</span>
+                                    </td>
+                                    <td>
+                                        <code>&lt;span class="pie"&gt;0.52,1.041&lt;/span&gt;</code>
+                                    </td>
+                                </tr>
+                            </tbody>
+                        </table>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div class="row">
+            <div class="col-sm-12">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>线性图</h5>
+                        <div class="ibox-tools">
+                            <a class="close-link">
+                                <i class="fa fa-times"></i>
+                            </a>
+                        </div>
+                    </div>
+                    <div>
+                        <table class="table table-bordered white-bg">
+                            <thead>
+                                <tr>
+                                    <th>图表</th>
+                                    <th>代码</th>
+                                </tr>
+                            </thead>
+                            <tbody>
+                                <tr>
+                                    <td>
+                                        <span data-diameter="40" class="updating-chart">5,3,9,6,5,9,7,3,5,2,5,3,9,6,5,9,7,3,5,2</span>
+                                    </td>
+                                    <td>
+                                        <code>&lt;span class="line"&gt;5,3,9,6,5,9,7,3,5,2&lt;/span&gt;</code>
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td>
+                                        <span class="line">5,3,9,6,5,9,7,3,5,2</span>
+                                    </td>
+                                    <td>
+                                        <code>&lt;span class="line"&gt;5,3,9,6,5,9,7,3,5,2&lt;/span&gt;</code>
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td>
+                                        <span class="line">5,3,2,-1,-3,-2,2,3,5,2</span>
+                                    </td>
+                                    <td>
+                                        <code>&lt;span class="line"&gt;5,3,2,-1,-3,-2,2,3,5,2&lt;/span&gt;</code>
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td>
+                                        <span class="line">0,-3,-6,-4,-5,-4,-7,-3,-5,-2</span>
+                                    </td>
+                                    <td>
+                                        <code>&lt;span class="line"&gt;0,-3,-6,-4,-5,-4,-7,-3,-5,-2&lt;/span&gt;</code>
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td>
+                                        <span class="bar">5,3,9,6,5,9,7,3,5,2</span>
+                                    </td>
+                                    <td>
+                                        <code>&lt;span class="bar"&gt;5,3,9,6,5,9,7,3,5,2&lt;/span&gt;</code>
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td>
+                                        <span class="bar">5,3,2,-1,-3,-2,2,3,5,2</span>
+                                    </td>
+                                    <td>
+                                        <code>&lt;span class="bar"&gt;5,3,2,-1,-3,-2,2,3,5,2&lt;/span&gt;</code>
+                                    </td>
+                                </tr>
+                            </tbody>
+                        </table>
+                    </div>
+                </div>
+            </div>
+
+        </div>
+    </div>
+    <th:block th:include="include :: footer" />
+    <th:block th:include="include :: peity-js" />
+    <script type="text/javascript">
+	    $(function() {
+	        $("span.pie").peity("pie", {
+	            fill: ['#1ab394', '#d7d7d7', '#ffffff']
+	        })
+	
+	        $(".line").peity("line",{
+	            fill: '#1ab394',
+	            stroke:'#169c81',
+	        })
+	
+	        $(".bar").peity("bar", {
+	            fill: ["#1ab394", "#d7d7d7"]
+	        })
+	
+	        $(".bar_dashboard").peity("bar", {
+	            fill: ["#1ab394", "#d7d7d7"],
+	            width:100
+	        })
+	
+	        var updatingChart = $(".updating-chart").peity("line", { fill: '#1ab394',stroke:'#169c81', width: 64 })
+	
+	        setInterval(function() {
+	            var random = Math.round(Math.random() * 10)
+	            var values = updatingChart.text().split(",")
+	            values.shift()
+	            values.push(random)
+	
+	            updatingChart
+	                .text(values.join(","))
+	                .change()
+	        }, 1000);
+	
+	    });
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/demo/report/sparkline.html b/ruoyi-admin/src/main/resources/templates/demo/report/sparkline.html
new file mode 100644
index 0000000..e081cdf
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/report/sparkline.html
@@ -0,0 +1,232 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('线状图')" />
+</head>
+<body class="gray-bg">
+    <div class="wrapper wrapper-content animated fadeInDown">
+
+        <div class="row">
+            <div class="col-sm-5">
+                <div class="jumbotron">
+                    <h1>Sparkline</h1>
+                    <p>这是另一个可视化图表库</p>
+                    <p><a href="http://omnipotent.net/jquery.sparkline" target="_blank" class="btn btn-primary btn-lg" role="button">了解 Sparkline</a>
+                    </p>
+                </div>
+            </div>
+            <div class="col-sm-7">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>Sparkline图表 <small>自定义颜色</small></h5>
+                        <div class="ibox-tools">
+                            <a class="close-link">
+                                <i class="fa fa-times"></i>
+                            </a>
+                        </div>
+                    </div>
+                    <div>
+                        <table class="table table-bordered white-bg">
+                            <thead>
+                                <tr>
+                                    <th>图表</th>
+                                    <th>类型</th>
+                                </tr>
+                            </thead>
+
+                            <tbody>
+                                <tr>
+                                    <td>
+                                        <span id="sparkline1"></span>
+                                    </td>
+                                    <td>
+                                        内联线性图
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td>
+                                        <span id="sparkline2"></span>
+                                    </td>
+                                    <td>
+                                        柱状图
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td>
+                                        <span id="sparkline3"></span>
+                                    </td>
+                                    <td>
+                                        饼状图
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td>
+                                        <span id="sparkline4"></span>
+                                    </td>
+                                    <td>
+                                        长线性图
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td>
+                                        <span id="sparkline5"></span>
+                                    </td>
+                                    <td>
+                                        三态图
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td>
+                                        <span id="sparkline6"></span>
+                                    </td>
+                                    <td>
+                                        散点图
+                                    </td>
+                                </tr>
+                            </tbody>
+                        </table>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div class="row">
+            <div class="col-sm-4">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>自定义饼状图尺寸</h5>
+                        <div class="ibox-tools">
+                            <a class="collapse-link">
+                                <i class="fa fa-chevron-up"></i>
+                            </a>
+                            <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                                <i class="fa fa-wrench"></i>
+                            </a>
+                            <ul class="dropdown-menu dropdown-user">
+                                <li><a href="javascript:;">选项1</a>
+                                </li>
+                                <li><a href="javascript:;">选项2</a>
+                                </li>
+                            </ul>
+                            <a class="close-link">
+                                <i class="fa fa-times"></i>
+                            </a>
+                        </div>
+                    </div>
+                    <div class="ibox-content text-center h-200">
+                        <span id="sparkline7"></span>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-4">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>自定义柱状图尺寸</h5>
+                        <div class="ibox-tools">
+                            <a class="collapse-link">
+                                <i class="fa fa-chevron-up"></i>
+                            </a>
+                            <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                                <i class="fa fa-wrench"></i>
+                            </a>
+                            <ul class="dropdown-menu dropdown-user">
+                                <li><a href="javascript:;">选项1</a>
+                                </li>
+                                <li><a href="javascript:;">选项2</a>
+                                </li>
+                            </ul>
+                            <a class="close-link">
+                                <i class="fa fa-times"></i>
+                            </a>
+                        </div>
+                    </div>
+                    <div class="ibox-content text-center h-200">
+                        <span id="sparkline8"></span>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-4">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>自定义线性图尺寸</h5>
+                        <div class="ibox-tools">
+                            <a class="collapse-link">
+                                <i class="fa fa-chevron-up"></i>
+                            </a>
+                            <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                                <i class="fa fa-wrench"></i>
+                            </a>
+                            <ul class="dropdown-menu dropdown-user">
+                                <li><a href="javascript:;">选项1</a>
+                                </li>
+                                <li><a href="javascript:;">选项2</a>
+                                </li>
+                            </ul>
+                            <a class="close-link">
+                                <i class="fa fa-times"></i>
+                            </a>
+                        </div>
+                    </div>
+                    <div class="ibox-content text-center h-200">
+                        <span id="sparkline9"></span>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <th:block th:include="include :: footer" />
+    <th:block th:include="include :: sparkline-js" />
+    <script type="text/javascript">
+	    $(function () {
+	        $("#sparkline1").sparkline([34, 43, 43, 35, 44, 32, 44, 52, 25], {
+	            type: 'line',
+	            lineColor: '#17997f',
+	            fillColor: '#1ab394',
+	        });
+	        $("#sparkline2").sparkline([5, 6, 7, 2, 0, -4, -2, 4], {
+	            type: 'bar',
+	            barColor: '#1ab394',
+	            negBarColor: '#c6c6c6'});
+	
+	        $("#sparkline3").sparkline([1, 1, 2], {
+	            type: 'pie',
+	            sliceColors: ['#1ab394', '#b3b3b3', '#e4f0fb']});
+	
+	        $("#sparkline4").sparkline([34, 43, 43, 35, 44, 32, 15, 22, 46, 33, 86, 54, 73, 53, 12, 53, 23, 65, 23, 63, 53, 42, 34, 56, 76, 15, 54, 23, 44], {
+	            type: 'line',
+	            lineColor: '#17997f',
+	            fillColor: '#ffffff',
+	        });
+	
+	        $("#sparkline5").sparkline([1, 1, 0, 1, -1, -1, 1, -1, 0, 0, 1, 1], {
+	            type: 'tristate',
+	            posBarColor: '#1ab394',
+	            negBarColor: '#bfbfbf'});
+	
+	
+	        $("#sparkline6").sparkline([4, 6, 7, 7, 4, 3, 2, 1, 4, 4, 5, 6, 3, 4, 5, 8, 7, 6, 9, 3, 2, 4, 1, 5, 6, 4, 3, 7, ], {
+	            type: 'discrete',
+	            lineColor: '#1ab394'});
+	
+	        $("#sparkline7").sparkline([52, 12, 44], {
+	            type: 'pie',
+	            height: '150px',
+	            sliceColors: ['#1ab394', '#b3b3b3', '#e4f0fb']});
+	
+	        $("#sparkline8").sparkline([5, 6, 7, 2, 0, 4, 2, 4, 5, 7, 2, 4, 12, 14, 4, 2, 14, 12, 7], {
+	            type: 'bar',
+	            barWidth: 8,
+	            height: '150px',
+	            barColor: '#1ab394',
+	            negBarColor: '#c6c6c6'});
+	
+	        $("#sparkline9").sparkline([34, 43, 43, 35, 44, 32, 15, 22, 46, 33, 86, 54, 73, 53, 12, 53, 23, 65, 23, 63, 53, 42, 34, 56, 76, 15, 54, 23, 44], {
+	            type: 'line',
+	            lineWidth: 1,
+	            height: '150px',
+	            lineColor: '#17997f',
+	            fillColor: '#ffffff',
+	        });
+	    });
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/demo/table/asynTree.html b/ruoyi-admin/src/main/resources/templates/demo/table/asynTree.html
new file mode 100644
index 0000000..c5af5c0
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/table/asynTree.html
@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+    <th:block th:include="include :: header('异步加载表格树')" />
+</head>
+<body class="gray-bg">
+     <div class="container-div">
+        <div class="row">
+            <div class="col-sm-12 search-collapse">
+                <form id="formId">
+                    <div class="select-list">
+                        <ul>
+                            <li>
+                                <label>区域名称:</label>
+                                <input type="text" name="areaName"/>
+                            </li>
+                            <li>
+                                <a class="btn btn-primary btn-rounded btn-sm" onclick="$.treeTable.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
+                                <a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
+                            </li>
+                        </ul>
+                    </div>
+                </form>
+            </div>
+
+            <div class="btn-group-sm" id="toolbar" role="group">
+                <a class="btn btn-info" id="expandAllBtn">
+                    <i class="fa fa-exchange"></i> 展开/折叠
+                </a>
+            </div>
+            <div class="col-sm-12 select-table table-striped">
+                <table id="bootstrap-tree-table"></table>
+            </div>
+        </div>
+    </div>
+    <th:block th:include="include :: footer" />
+    <script th:inline="javascript">
+        var prefix = ctx + "demo/table";
+
+        $(function() {
+            var options = {
+                code: "id",
+                parentCode: "parentId",
+                uniqueId: "id",
+                expandAll: false,
+		        expandFirst: false,
+		        expandColumn: 1,
+                pagination: true,                      // 开启分页
+                url: prefix + "/tree/list",            // 列表请求
+                dataUrl: prefix + "/tree/listChild",   // 子节点异步请求
+                onClickRow: onClickRow,
+                columns: [{
+                    field: 'selectItem',
+                    radio: true
+                },
+                {
+                    field: 'areaName',
+                    title: '区域名称',
+                    align: 'left',
+                },
+                {
+                    field: 'areaCode',
+                    title: '区域代码',
+                    align: 'left'
+                },
+                {
+                    field: 'simplePy',
+                    title: '首字母简拼',
+                    align: 'left'
+                },
+                {
+                    field: 'pinYin',
+                    title: '名称全拼',
+                    align: 'left'
+                }]
+            };
+            $.treeTable.init(options);
+        });
+        
+        function onClickRow(row, $element){
+//         	alert("单击行id:" + row.id + " name:" + row.name);
+        }
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/demo/table/button.html b/ruoyi-admin/src/main/resources/templates/demo/table/button.html
new file mode 100644
index 0000000..b14f874
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/table/button.html
@@ -0,0 +1,92 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('点击按钮加载表格')" />
+</head>
+<body class="gray-bg">
+     <div class="container-div">
+		<div class="row">
+			<div class="col-sm-12 search-collapse">
+				<form id="ordinary-form">
+					<div class="select-list">
+						<ul>
+							<li>
+								用户名称:<input type="text" name="userName"/>
+							</li>
+							<li>
+								<a class="btn btn-primary btn-rounded btn-sm" onclick="query()"><i class="fa fa-search"></i>&nbsp;搜索</a>
+							    <a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
+							</li>
+						</ul>
+					</div>
+				</form>
+			</div>
+			
+			<div class="col-sm-12 select-table table-striped">
+				<table id="bootstrap-table"></table>
+			</div>
+		</div>
+	</div>
+    <div th:include="include :: footer"></div>
+    <script th:inline="javascript">
+        var prefix = ctx + "demo/table";
+        var datas = [[${@dict.getType('sys_normal_disable')}]];
+
+        function query() {
+            var options = {
+                url: prefix + "/list",
+		        showSearch: false,
+		        showRefresh: false,
+		        showToggle: false,
+		        showColumns: false,
+                columns: [{
+		            checkbox: true
+		        },
+				{
+					field : 'userId', 
+					title : '用户ID'
+				},
+				{
+					field : 'userCode', 
+					title : '用户编号'
+				},
+				{
+					field : 'userName', 
+					title : '用户姓名'
+				},
+				{
+					field : 'userPhone', 
+					title : '用户手机'
+				},
+				{
+					field : 'userEmail', 
+					title : '用户邮箱'
+				},
+				{
+				    field : 'userBalance',
+				    title : '用户余额'
+				},
+				{
+                    field: 'status',
+                    title: '用户状态',
+                    align: 'center',
+                    formatter: function(value, row, index) {
+                    	return $.table.selectDictLabel(datas, value);
+                    }
+                },
+		        {
+		            title: '操作',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		            	var actions = [];
+		            	actions.push('<a class="btn btn-success btn-xs" href="javascript:;"><i class="fa fa-edit"></i>编辑</a> ');
+                        actions.push('<a class="btn btn-danger btn-xs" href="javascript:;"><i class="fa fa-remove"></i>删除</a>');
+						return actions.join('');
+		            }
+		        }]
+            };
+            $.table.init(options);
+        }
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/demo/table/child.html b/ruoyi-admin/src/main/resources/templates/demo/table/child.html
new file mode 100644
index 0000000..44448ba
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/table/child.html
@@ -0,0 +1,116 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('表格父子视图')" />
+</head>
+<body class="gray-bg">
+     <div class="container-div">
+		<div class="row">
+			<div class="col-sm-12 select-table table-striped">
+			    <!-- 点击事件的方式打开使用 detailViewIcon: false and detailViewByClick: true
+			         data-detail-view-icon="false" 
+			         data-detail-view-by-click="true" -->
+				<table id="bootstrap-table"></table>
+			</div>
+		</div>
+	</div>
+    <div th:include="include :: footer"></div>
+    <script th:inline="javascript">
+        var prefix = ctx + "demo/table";
+        var datas = [[${@dict.getType('sys_normal_disable')}]];
+
+        $(function() {
+            var options = {
+                url: prefix + "/list",
+		        showSearch: false,
+		        showRefresh: false,
+		        showToggle: false,
+		        showColumns: false,
+		        detailView: true,
+				onExpandRow : function(index, row, $detail) {
+					initChildTable(index, row, $detail);
+				},
+                columns: [{
+		            checkbox: true
+		        },
+				{
+					field : 'userId', 
+					title : '用户ID'
+				},
+				{
+					field : 'userCode', 
+					title : '用户编号'
+				},
+				{
+					field : 'userName', 
+					title : '用户姓名'
+				},
+				{
+					field : 'userPhone', 
+					title : '用户手机'
+				},
+				{
+					field : 'userEmail', 
+					title : '用户邮箱'
+				},
+				{
+				    field : 'userBalance',
+				    title : '用户余额'
+				},
+				{
+                    field: 'status',
+                    title: '用户状态',
+                    align: 'center',
+                    formatter: function(value, row, index) {
+                    	return $.table.selectDictLabel(datas, value);
+                    }
+                },
+		        {
+		            title: '操作',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		            	var actions = [];
+		            	actions.push('<a class="btn btn-success btn-xs" href="javascript:;"><i class="fa fa-edit"></i>编辑</a> ');
+                        actions.push('<a class="btn btn-danger btn-xs" href="javascript:;"><i class="fa fa-remove"></i>删除</a>');
+						return actions.join('');
+		            }
+		        }]
+            };
+            $.table.init(options);
+        });
+        
+		initChildTable = function(index, row, $detail) {
+			var childTable = $detail.html('<table style="table-layout:fixed"></table>').find('table');
+    	    $(childTable).bootstrapTable({
+    	        url: prefix + "/list",
+    	        method: 'post',
+    	        sidePagination: "server",
+    	        contentType: "application/x-www-form-urlencoded",
+    	        queryParams : {
+                    userName: '测试8'
+				},
+    	        columns: [{
+					field : 'userId', 
+					title : '子表ID'
+				},
+				{
+					field : 'userCode', 
+					title : '子表编号'
+				},
+				{
+					field : 'userName', 
+					title : '子表姓名'
+				},
+				{
+                    field: 'status',
+                    title: '子表状态',
+                    align: 'center',
+                    formatter: function(value, row, index) {
+                    	return $.table.selectDictLabel(datas, value);
+                    }
+                }]
+    	    });
+		};
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/demo/table/cookie.html b/ruoyi-admin/src/main/resources/templates/demo/table/cookie.html
new file mode 100644
index 0000000..3ff2983
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/table/cookie.html
@@ -0,0 +1,78 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('表格保存状态')" />
+</head>
+<body class="gray-bg">
+     <div class="container-div">
+		<div class="row">
+			<div class="col-sm-12 select-table table-striped">
+				<table id="bootstrap-table" data-cookie="true" data-cookie-id-table="userTableId"></table>
+			</div>
+		</div>
+	</div>
+    <div th:include="include :: footer"></div>
+    <th:block th:include="include :: bootstrap-table-cookie-js" />
+    <script th:inline="javascript">
+        var prefix = ctx + "demo/table";
+        var datas = [[${@dict.getType('sys_normal_disable')}]];
+
+        $(function() {
+            var options = {
+                url: prefix + "/list",
+                search: true,
+                showSearch: false,
+                showRefresh: false,
+		        showToggle: false,
+                columns: [{
+                	field: 'state',
+		            checkbox: true
+		        },
+				{
+					field : 'userId', 
+					title : '用户ID'
+				},
+				{
+					field : 'userCode', 
+					title : '用户编号'
+				},
+				{
+					field : 'userName', 
+					title : '用户姓名'
+				},
+				{
+					field : 'userPhone', 
+					title : '用户手机'
+				},
+				{
+					field : 'userEmail', 
+					title : '用户邮箱'
+				},
+				{
+				    field : 'userBalance',
+				    title : '用户余额'
+				},
+				{
+                    field: 'status',
+                    title: '用户状态',
+                    align: 'center',
+                    formatter: function(value, row, index) {
+                    	return $.table.selectDictLabel(datas, value);
+                    }
+                },
+		        {
+		            title: '操作',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		            	var actions = [];
+		            	actions.push('<a class="btn btn-success btn-xs" href="javascript:;"><i class="fa fa-edit"></i>编辑</a> ');
+                        actions.push('<a class="btn btn-danger btn-xs" href="javascript:;"><i class="fa fa-remove"></i>删除</a>');
+						return actions.join('');
+		            }
+		        }]
+            };
+            $.table.init(options);
+        });
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/demo/table/curd.html b/ruoyi-admin/src/main/resources/templates/demo/table/curd.html
new file mode 100644
index 0000000..ee76177
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/table/curd.html
@@ -0,0 +1,178 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('动态增删改查')" />
+</head>
+<body class="gray-bg">
+     <div class="container-div">
+        <div class="btn-group-sm" id="toolbar" role="group">
+	        <a class="btn btn-success" onclick="insertRow()">
+	            <i class="fa fa-plus"></i> 新增行
+	        </a>
+	        <a class="btn btn-danger multiple disabled" onclick="removeRow()">
+	            <i class="fa fa-remove"></i> 删除选择行
+	        </a>
+	        <a class="btn btn-danger" onclick="removeRowByUniqueId()">
+	            <i class="fa fa-remove"></i> 根据值删除行
+	        </a>
+	        <a class="btn btn-danger" onclick="removeRowAll()">
+	            <i class="fa fa-remove"></i> 删除所有行
+	        </a>
+	        <a class="btn btn-info" onclick="updateRow()">
+	            <i class="fa fa-edit"></i> 修改行
+	        </a>
+	        <a class="btn btn-info" onclick="updateRowByUniqueId()">
+	            <i class="fa fa-edit"></i> 根据值修改行
+	        </a>
+	        <a class="btn btn-info" onclick="getSelections()">
+	            <i class="fa fa-search"></i> 查询选择数据
+	        </a>
+	        <a class="btn btn-info" onclick="getRowByUniqueId()">
+	            <i class="fa fa-search"></i> 根据值查询行
+	        </a>
+	        <a class="btn btn-primary" onclick="getData()">
+	            <i class="fa fa-search"></i> 查询所有数据
+	        </a>
+        </div>
+		<div class="row">
+			<div class="col-sm-12 select-table table-striped">
+				<table id="bootstrap-table"></table>
+			</div>
+		</div>
+	</div>
+    <div th:include="include :: footer"></div>
+    <script th:inline="javascript">
+        var prefix = ctx + "demo/table";
+        
+        $(function() {
+            var options = {
+                url: prefix + "/list",
+		        showSearch: false,
+		        showRefresh: false,
+		        showToggle: false,
+		        showColumns: false,
+		        pagination: false,
+		        uniqueId: "userId",
+		        height: 400,
+                columns: [{
+		            checkbox: true
+		        },
+				{
+					field : 'userId', 
+					title : '用户ID'
+				},
+				{
+					field : 'userCode', 
+					title : '用户编号'
+				},
+				{
+					field : 'userName', 
+					title : '用户姓名'
+				},
+				{
+					field : 'userPhone', 
+					title : '用户手机'
+				},
+				{
+					field : 'userEmail', 
+					title : '用户邮箱'
+				},
+				{
+				    field : 'userBalance',
+				    title : '用户余额'
+				}]
+            };
+            $.table.init(options);
+        });
+        
+        /* 新增表格行 */
+        function insertRow(){
+        	var randomId = 100 + ~~(Math.random() * 100)
+        	$("#" + table.options.id).bootstrapTable('insertRow', {
+        		index: 0, // 你想插入到哪,0表示第一行
+                row: {
+                	userId: randomId,
+                	userCode: 2000000 + randomId,
+                	userName: '测试' + randomId,
+                	userPhone: '1588888888',
+                	userEmail: 'ry1@qq.com',
+                	userBalance: 10 + randomId,
+                }
+        	})
+        }
+        
+        /* 删除指定表格行 */
+        function removeRow(){
+        	var ids = $.table.selectColumns("userId");
+        	if (ids.length == 0) {
+    			$.modal.alertWarning("请至少选择一条记录");
+    			return;
+    		}
+        	$("#" + table.options.id).bootstrapTable('remove', {
+        	    field: 'userId',
+        	    values: ids
+        	})
+        }
+        
+        /* 删除行ID值为1的数据 */
+        function removeRowByUniqueId(){
+        	$("#" + table.options.id).bootstrapTable('removeByUniqueId', 1)
+        }
+        
+        /* 删除所有表格行 */
+        function removeRowAll(){
+        	$("#" + table.options.id).bootstrapTable('removeAll')
+        }
+        
+        /* 修改表格行 */
+        function updateRow(){
+        	var randomId = 100 + ~~(Math.random() * 100)
+        	$("#" + table.options.id).bootstrapTable('updateRow', {
+        		index: 0, // 你想修改哪行,0表示第一行
+                row: {
+                	userId: randomId,
+                	userCode: 3000000 + randomId,
+                	userName: '测试' + randomId,
+                	userPhone: '1599999999',
+                	userEmail: 'ry2@qq.com',
+                	userBalance: 50 + randomId,
+                }
+        	})
+        }
+        
+        /* 修改行ID值为1的数据 */
+        function updateRowByUniqueId(){
+        	var randomId = 100 + ~~(Math.random() * 100)
+        	$("#" + table.options.id).bootstrapTable('updateByUniqueId', {
+        		id: 1,
+                row: {
+                	userId: randomId,
+                	userCode: 3000000 + randomId,
+                	userName: '测试' + randomId,
+                	userPhone: '1599999999',
+                	userEmail: 'ry2@qq.com',
+                	userBalance: 50 + randomId,
+                }
+        	})
+        }
+        
+        /* 查询表格所有数据值 */
+        function getData(){
+        	var data = $("#" + table.options.id).bootstrapTable('getData');
+            alert(JSON.stringify(data))
+        }
+        
+        /* 查询行ID值为1的数据 */
+        function getRowByUniqueId(){
+        	var data = $("#" + table.options.id).bootstrapTable('getRowByUniqueId', 1);
+            alert(JSON.stringify(data))
+        }
+        
+        /* 查询表格选择行数据值 */
+        function getSelections(){
+        	var data = $("#" + table.options.id).bootstrapTable('getSelections');
+        	alert(JSON.stringify(data))
+        }
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/demo/table/customView.html b/ruoyi-admin/src/main/resources/templates/demo/table/customView.html
new file mode 100644
index 0000000..63b0999
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/table/customView.html
@@ -0,0 +1,122 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('自定义视图分页')" />
+</head>
+<body class="gray-bg">
+     <div class="container-div">
+		<div class="row">
+			<div class="col-sm-12 select-table table-striped">
+				<table id="bootstrap-table" data-page-size="10" 
+				       data-show-custom-view="true" data-custom-view="customViewFormatter"
+                       data-custom-view-default-view="true">
+                </table>
+			</div>
+		</div>
+	</div>
+	
+    <template id="profileTemplate">
+        <div class="col-sm-4">
+            <div class="contact-box">
+                <a href="profile.html">
+                    <div class="col-sm-4">
+                        <div class="text-center">
+                            <img alt="image" class="img-circle m-t-xs img-responsive" src="%IMAGE%">
+                            <div class="m-t-xs font-bold">%userName%</div>
+                        </div>
+                    </div>
+                    <div class="col-sm-8">
+                        <h3><strong>%userCode%</strong></h3>
+                        <p><i class="fa fa-jpy"></i> %userBalance%</p>
+                        <address>
+                        <strong>RuoYi, Inc.</strong><br>
+                        E-mail: %userEmail%<br>
+                        <abbr title="Phone">Tel:</abbr> %userPhone%
+                       </address>
+                    </div>
+                    <div class="clearfix"></div>
+                 </a>
+             </div>
+        </div>
+    </template>
+
+    <div th:include="include :: footer"></div>
+    <th:block th:include="include :: bootstrap-table-custom-view-js" />
+    <script th:inline="javascript">
+        var prefix = ctx + "demo/table";
+        var datas = [[${@dict.getType('sys_normal_disable')}]];
+
+        $(function() {
+            var options = {
+                url: prefix + "/list",
+		        showSearch: false,
+		        showRefresh: false,
+		        showToggle: false,
+		        showColumns: false,
+		        showExport: true,
+                columns: [{
+		            checkbox: true
+		        },
+				{
+					field : 'userId', 
+					title : '用户ID'
+				},
+				{
+					field : 'userCode', 
+					title : '用户编号'
+				},
+				{
+					field : 'userName', 
+					title : '用户姓名'
+				},
+				{
+					field : 'userPhone', 
+					title : '用户手机'
+				},
+				{
+					field : 'userEmail', 
+					title : '用户邮箱'
+				},
+				{
+				    field : 'userBalance',
+				    title : '用户余额'
+				},
+				{
+                    field: 'status',
+                    title: '用户状态',
+                    align: 'center',
+                    formatter: function(value, row, index) {
+                    	return $.table.selectDictLabel(datas, value);
+                    }
+                },
+		        {
+		            title: '操作',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		            	var actions = [];
+		            	actions.push('<a class="btn btn-success btn-xs" href="javascript:;"><i class="fa fa-edit"></i>编辑</a> ');
+                        actions.push('<a class="btn btn-danger btn-xs" href="javascript:;"><i class="fa fa-remove"></i>删除</a>');
+						return actions.join('');
+		            }
+		        }]
+            };
+            $.table.init(options);
+        });
+        
+        function customViewFormatter (data) {
+            var template = $('#profileTemplate').html()
+            var view = ''
+            $.each(data, function (i, row) {
+              view += template.replace('%userCode%', row.userCode)
+                .replace('%IMAGE%', "http://demo.ruoyi.vip/img/profile.jpg")
+                .replace('%userName%', row.userName)
+                .replace('%userEmail%', row.userEmail)
+                .replace('%userPhone%', row.userPhone)
+                .replace('%userBalance%', row.userBalance);
+            })
+
+            return `<div class="row mx-0">${view}</div>`
+          }
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/demo/table/data.html b/ruoyi-admin/src/main/resources/templates/demo/table/data.html
new file mode 100644
index 0000000..bf4cb66
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/table/data.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('加载data数据')" />
+</head>
+<body class="gray-bg">
+     <div class="container-div">
+		<div class="row">
+			<div class="col-sm-12 select-table table-striped">
+				<table id="bootstrap-table"></table>
+			</div>
+		</div>
+	</div>
+    <div th:include="include :: footer"></div>
+    <script th:inline="javascript">
+        var datas = [[${@dict.getType('sys_normal_disable')}]];
+
+        $(function() {
+            var options = {
+                data: [[${users}]],
+                sidePagination: "client",
+		        showSearch: false,
+		        showRefresh: false,
+		        showToggle: false,
+		        showColumns: false,
+                columns: [{
+		            checkbox: true
+		        },
+				{
+					field : 'userId', 
+					title : '用户ID'
+				},
+				{
+					field : 'userCode', 
+					title : '用户编号'
+				},
+				{
+					field : 'userName', 
+					title : '用户姓名'
+				},
+				{
+					field : 'userPhone', 
+					title : '用户手机'
+				},
+				{
+					field : 'userEmail', 
+					title : '用户邮箱'
+				},
+				{
+				    field : 'userBalance',
+				    title : '用户余额'
+				},
+				{
+                    field: 'status',
+                    title: '用户状态',
+                    align: 'center',
+                    formatter: function(value, row, index) {
+                    	return $.table.selectDictLabel(datas, value);
+                    }
+                },
+		        {
+		            title: '操作',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		            	var actions = [];
+		            	actions.push('<a class="btn btn-success btn-xs" href="javascript:;"><i class="fa fa-edit"></i>编辑</a> ');
+                        actions.push('<a class="btn btn-danger btn-xs" href="javascript:;"><i class="fa fa-remove"></i>删除</a>');
+						return actions.join('');
+		            }
+		        }]
+            };
+            $.table.init(options);
+        });
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/demo/table/detail.html b/ruoyi-admin/src/main/resources/templates/demo/table/detail.html
new file mode 100644
index 0000000..1f13039
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/table/detail.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('表格细节视图')" />
+</head>
+<body class="gray-bg">
+     <div class="container-div">
+		<div class="row">
+			<div class="col-sm-12 select-table table-striped">
+				<table id="bootstrap-table"></table>
+			</div>
+		</div>
+	</div>
+    <div th:include="include :: footer"></div>
+    <script th:inline="javascript">
+        var prefix = ctx + "demo/table";
+        var datas = [[${@dict.getType('sys_normal_disable')}]];
+
+        $(function() {
+            var options = {
+                url: prefix + "/list",
+		        showSearch: false,
+		        showRefresh: false,
+		        showToggle: false,
+		        showColumns: false,
+		        detailView: true,
+		        detailFormatter: detailFormatter,
+                columns: [{
+		            checkbox: true
+		        },
+				{
+					field : 'userId', 
+					title : '用户ID'
+				},
+				{
+					field : 'userCode', 
+					title : '用户编号'
+				},
+				{
+					field : 'userName', 
+					title : '用户姓名'
+				},
+				{
+					field : 'userPhone', 
+					title : '用户手机'
+				},
+				{
+					field : 'userEmail', 
+					title : '用户邮箱'
+				},
+				{
+				    field : 'userBalance',
+				    title : '用户余额'
+				},
+				{
+                    field: 'status',
+                    title: '用户状态',
+                    align: 'center',
+                    formatter: function(value, row, index) {
+                    	return $.table.selectDictLabel(datas, value);
+                    }
+                },
+		        {
+		            title: '操作',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		            	var actions = [];
+		            	actions.push('<a class="btn btn-success btn-xs" href="javascript:;"><i class="fa fa-edit"></i>编辑</a> ');
+                        actions.push('<a class="btn btn-danger btn-xs" href="javascript:;"><i class="fa fa-remove"></i>删除</a>');
+						return actions.join('');
+		            }
+		        }]
+            };
+            $.table.init(options);
+        });
+        
+        function detailFormatter(index, row) {
+        	var html = [];
+        	$.each(row, function(key, value) {
+        		html.push('<p><b>' + key + ':</b> ' + value + '</p>');
+        	});
+        	return html.join('');
+       	}
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/demo/table/dynamicColumns.html b/ruoyi-admin/src/main/resources/templates/demo/table/dynamicColumns.html
new file mode 100644
index 0000000..09fb258
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/table/dynamicColumns.html
@@ -0,0 +1,123 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+<th:block th:include="include :: header('动态列')" />
+</head>
+<body class="gray-bg">
+	<div class="container-div">
+		<div class="row">
+			<div class="col-sm-12 search-collapse">
+				<form id="table-form">
+					<div class="select-list">
+						<ul>
+							<li>
+								要增加的列:
+								<select name="field">
+									<option value="">默认</option>
+									<option value="userBalance">用户余额</option>
+								</select>
+							</li>
+							<li>
+								<a class="btn btn-primary btn-rounded btn-sm" onclick="tableSearch()"><i class="fa fa-search"></i>&nbsp;搜索</a>
+								<a class="btn btn-warning btn-rounded btn-sm" onclick="reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
+							</li>
+						</ul>
+					</div>
+				</form>
+			</div>
+			<div class="col-sm-12 select-table table-striped">
+				<table id="bootstrap-table"></table>
+			</div>
+		</div>
+	</div>
+	<div th:include="include :: footer"></div>
+	<script th:inline="javascript">
+        var prefix = ctx + "demo/table";
+        var datas = [[${@dict.getType('sys_normal_disable')}]];
+
+        $(function() {
+        	ajaxColumns();
+        });
+        // 动态获取列
+        function ajaxColumns() {
+        	var url = prefix + "/ajaxColumns";
+        	var dataParam = $.common.formToJSON("table-form");
+            $.modal.loading("正在查询中,请稍候...");
+            $.post(url, dataParam, function(result) {
+                if (result.code == web_status.SUCCESS) {
+                	setColumns(result.data);
+                } else if (result.code == web_status.WARNING) {
+                    $.modal.alertWarning(result.msg)
+                } else {
+                    $.modal.alertError(result.msg);
+                }
+                $.modal.closeLoading();
+            });
+        }
+      	// 设置列
+        function setColumns(list) {
+        	var columns = [];
+        	list.forEach(function(item) {
+        	    if($.common.equals('status',item.field)){
+        	    	columns.push({
+        	    		field : item.field, 
+    					title : item.title,
+                        align: 'center',
+                        formatter: function(value, row, index) {
+                        	return $.table.selectDictLabel(datas, value);
+                        }
+        	    	})
+        	    } else {
+        	    	columns.push({
+        	    		field : item.field, 
+    					title : item.title
+        	    	})
+        	    }
+        	});
+        	columns.push({
+	            title: '操作',
+	            align: 'center',
+	            formatter: function(value, row, index) {
+	            	var actions = [];
+	            	actions.push('<a class="btn btn-success btn-xs" href="javascript:;"><i class="fa fa-edit"></i>编辑</a> ');
+                    actions.push('<a class="btn btn-danger btn-xs" href="javascript:;"><i class="fa fa-remove"></i>删除</a>');
+					return actions.join('');
+	            }
+	        });
+        	if(!table.get(table.options.id)){
+        		initTable(columns);
+        	} else {
+        		refreshTable(columns);
+        	}
+        }
+      	// 刷新表格
+        function refreshTable(columns) {
+        	var options = {
+        		columns: columns
+        	};
+        	$("#" + table.options.id).bootstrapTable('refreshOptions',options);
+        }
+      	// 初始化表格
+        function initTable(columns){
+        	var options = {
+        		url: prefix + "/list",
+            	showSearch: false,
+            	showRefresh: false,
+            	showToggle: false,
+            	showColumns: false,
+            	columns: columns
+            };
+            $.table.init(options);
+        }
+      	// 搜索
+        function tableSearch(){
+        	ajaxColumns();
+        }
+      	// 重置
+		function reset(){
+			$("#table-form")[0].reset();
+			ajaxColumns();
+        }
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/demo/table/editable.html b/ruoyi-admin/src/main/resources/templates/demo/table/editable.html
new file mode 100644
index 0000000..f7df50f
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/table/editable.html
@@ -0,0 +1,128 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('表格行内编辑')" />
+	<th:block th:include="include :: bootstrap-editable-css" />
+</head>
+<body class="gray-bg">
+     <div class="container-div">
+        <div class="btn-group-sm" id="toolbar" role="group">
+             <a class="btn btn-info" onclick="getSelections()">
+	            <i class="fa fa-search"></i> 查询选择数据
+	        </a>
+	        <a class="btn btn-primary" onclick="getData()">
+	            <i class="fa fa-search"></i> 获取所有数据
+	        </a>
+        </div>
+		<div class="row">
+			<div class="col-sm-12 select-table table-striped">
+				<table id="bootstrap-table"></table>
+			</div>
+		</div>
+	</div>
+	
+	<th:block th:include="include :: footer" />
+	<th:block th:include="include :: bootstrap-table-editable-js" />
+	
+    <script th:inline="javascript">
+        var prefix = ctx + "demo/table";
+        var datas = [[${@dict.getType('sys_normal_disable')}]];
+
+        $(function() {
+            var options = {
+                url: prefix + "/list",
+		        showSearch: false,
+		        showRefresh: false,
+		        showToggle: false,
+		        showColumns: false,
+		        showPageGo: true,
+		        onEditableSave: onEditableSave,
+                columns: [{
+		            checkbox: true
+		        },
+				{
+					field : 'userId', 
+					title : '用户ID'
+				},
+				{
+					field : 'userCode', 
+					title : '用户编号',
+					editable: true
+				},
+				{
+					field : 'userName', 
+					title : '用户姓名',
+					editable : {
+						type : 'text',
+						title : '名称',
+						emptytext : "【名称】为空",
+						validate : function(value) {
+							if (value.length > 30) {
+								return '名称不能超过30个字符';
+							}
+							if (value.length == 0) {
+								return '名称不能为空';
+							}
+						}
+					}
+				},
+				{
+					field : 'userPhone', 
+					title : '用户手机'
+				},
+				{
+					field : 'userEmail', 
+					title : '用户邮箱'
+				},
+				{
+				    field : 'userBalance',
+				    title : '用户余额'
+				},
+				{
+                    field: 'status',
+                    title: '用户状态',
+                    align: 'center',
+                    editable : {
+						type : 'select',
+						title : '状态',
+						source : [{
+							value : 0,
+							text : "正常"
+						}, {
+							value : 1,
+							text : "停用"
+						}]
+					}
+                },
+		        {
+		            title: '操作',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		            	var actions = [];
+		            	actions.push('<a class="btn btn-success btn-xs" href="javascript:;"><i class="fa fa-edit"></i>编辑</a> ');
+                        actions.push('<a class="btn btn-danger btn-xs" href="javascript:;"><i class="fa fa-remove"></i>删除</a>');
+						return actions.join('');
+		            }
+		        }]
+            };
+            $.table.init(options);
+        });
+        
+        function onEditableSave (field, row, rowIndex, oldValue, $el) {
+        	alert("字段名:" + field + ",当前值:" + row[field]  + ",旧值:" + oldValue);
+        }
+        
+        /* 查询表格所有数据值 */
+        function getData(){
+        	var data = $("#" + table.options.id).bootstrapTable('getData');
+            alert(JSON.stringify(data))
+        }
+        
+        /* 查询表格选择行数据值 */
+        function getSelections(){
+        	var data = $("#" + table.options.id).bootstrapTable('getSelections');
+        	alert(JSON.stringify(data))
+        }
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/demo/table/event.html b/ruoyi-admin/src/main/resources/templates/demo/table/event.html
new file mode 100644
index 0000000..aebb722
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/table/event.html
@@ -0,0 +1,133 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('自定义触发事件')" />
+</head>
+<body class="gray-bg">
+     <div class="container-div">
+		<div class="row">
+			<div class="col-sm-12 select-table table-striped">
+			    <p class="select-title">自定义触发事件(点击某行/双击某行/单击某格/双击某格/服务器发送数据前触发/数据被加载时触发)</p>
+				<table id="bootstrap-table"></table>
+			</div>
+		</div>
+	</div>
+    <div th:include="include :: footer"></div>
+    <script th:inline="javascript">
+        var prefix = ctx + "demo/table";
+        var datas = [[${@dict.getType('sys_normal_disable')}]];
+
+        $(function() {
+            var options = {
+                url: prefix + "/list",
+		        showSearch: false,
+		        showRefresh: false,
+		        showToggle: false,
+		        showColumns: false,
+		        onCheck: onCheck,
+		        onUncheck: onUncheck,
+		        onCheckAll: onCheckAll,
+		        onUncheckAll: onUncheckAll,
+		        onClickRow: onClickRow,
+		        onDblClickRow: onDblClickRow,
+		        onClickCell: onClickCell,
+		        onDblClickCell: onDblClickCell,
+		        responseHandler: responseHandler,
+		        onLoadSuccess: onLoadSuccess,
+                columns: [{
+		            checkbox: true
+		        },
+				{
+					field : 'userId', 
+					title : '用户ID'
+				},
+				{
+					field : 'userCode', 
+					title : '用户编号'
+				},
+				{
+					field : 'userName', 
+					title : '用户姓名'
+				},
+				{
+					field : 'userPhone', 
+					title : '用户手机'
+				},
+				{
+					field : 'userEmail', 
+					title : '用户邮箱'
+				},
+				{
+				    field : 'userBalance',
+				    title : '用户余额'
+				},
+				{
+                    field: 'status',
+                    title: '用户状态',
+                    align: 'center',
+                    formatter: function(value, row, index) {
+                    	return $.table.selectDictLabel(datas, value);
+                    }
+                },
+		        {
+		            title: '操作',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		            	var actions = [];
+		            	actions.push('<a class="btn btn-success btn-xs" href="javascript:;"><i class="fa fa-edit"></i>编辑</a> ');
+                        actions.push('<a class="btn btn-danger btn-xs" href="javascript:;"><i class="fa fa-remove"></i>删除</a>');
+						return actions.join('');
+		            }
+		        }]
+            };
+            $.table.init(options);
+        });
+        
+        function onClickRow(row, $element){
+        	alert("单击行userId:" + row.userId + " userName:" + row.userName);
+        }
+        
+        function onDblClickRow(row, $element){
+        	alert("双击行userId:" + row.userId + " userName:" + row.userName);
+        }
+        
+        function onClickCell(field, value, row, $element){
+        	alert("单击格name:" + field + " value:" + value);
+        }
+        
+        function onDblClickCell(field, value, row, $element){
+        	alert("双击格name:" + field + " value:" + value);
+        }
+        
+        function onCheck(row, $element){
+        	alert("选中行userId:" + row.userId + " userName:" + row.userName);
+        }
+        
+        function onUncheck(row, $element){
+        	alert("取消行userId:" + row.userId + " userName:" + row.userName);
+        }
+        
+        function onCheckAll(rowsAfter, rowsBefore){
+        	var rows = $.map(rowsAfter, function(row) {
+    	        return $.common.getItemField(row, "userId");
+    	    });
+        	alert("全选行:" + rows);
+        }
+        
+        function onUncheckAll(rowsAfter, rowsBefore){
+        	var rows = $.map(rowsBefore, function(row) {
+    	        return $.common.getItemField(row, "userId");
+    	    });
+        	alert("取消行:" + rows);
+        }
+        
+        function responseHandler(res){
+        	alert("请求获取数据后处理回调函数");
+        }
+        
+        function onLoadSuccess(data){
+        	alert("当所有数据被加载时触发");
+        }
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/demo/table/export.html b/ruoyi-admin/src/main/resources/templates/demo/table/export.html
new file mode 100644
index 0000000..1abd772
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/table/export.html
@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('导出')" />
+</head>
+<body class="gray-bg">
+     <div class="container-div">
+		<div class="row">
+			<div class="col-sm-12 select-table table-striped">
+				<table id="bootstrap-table"></table>
+			</div>
+		</div>
+	</div>
+    <div th:include="include :: footer"></div>
+    <th:block th:include="include :: bootstrap-table-export-js" />
+    <script th:inline="javascript">
+        var prefix = ctx + "demo/table";
+        var datas = [[${@dict.getType('sys_normal_disable')}]];
+
+        $(function() {
+            var options = {
+                url: prefix + "/list",
+		        showSearch: false,
+		        showRefresh: false,
+		        showToggle: false,
+		        showColumns: false,
+		        showExport: true,
+		        exportDataType: 'selected', // 导出选择数据
+		        exportTypes: ['json', 'xml', 'csv', 'txt', 'sql', 'excel'], // 导出的文件类型
+		        exportOptions: {
+		        	fileName: '用户数据',    // 文件名称设置
+		        	ignoreColumn: [0, 8]    // 忽略第一列和最后一列
+		        },
+		        clickToSelect: true,
+                columns: [{
+		            checkbox: true
+		        },
+				{
+					field : 'userId', 
+					title : '用户ID'
+				},
+				{
+					field : 'userCode', 
+					title : '用户编号'
+				},
+				{
+					field : 'userName', 
+					title : '用户姓名'
+				},
+				{
+					field : 'userPhone', 
+					title : '用户手机'
+				},
+				{
+					field : 'userEmail', 
+					title : '用户邮箱'
+				},
+				{
+				    field : 'userBalance',
+				    title : '用户余额'
+				},
+				{
+                    field: 'status',
+                    title: '用户状态',
+                    align: 'center',
+                    formatter: function(value, row, index) {
+                    	return $.table.selectDictLabel(datas, value);
+                    }
+                },
+		        {
+		            title: '操作',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		            	var actions = [];
+		            	actions.push('<a class="btn btn-success btn-xs" href="javascript:;"><i class="fa fa-edit"></i>编辑</a> ');
+                        actions.push('<a class="btn btn-danger btn-xs" href="javascript:;"><i class="fa fa-remove"></i>删除</a>');
+						return actions.join('');
+		            }
+		        }]
+            };
+            $.table.init(options);
+        });
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/demo/table/exportSelected.html b/ruoyi-admin/src/main/resources/templates/demo/table/exportSelected.html
new file mode 100644
index 0000000..53e89ec
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/table/exportSelected.html
@@ -0,0 +1,120 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('导出选择列')" />
+</head>
+<body class="gray-bg">
+     <div class="container-div">
+		<div class="row">
+		    <div class="col-sm-12 search-collapse">
+				<form id="export-form">
+					<div class="select-list">
+						<ul>
+							<li>
+								用户姓名:<input type="text" name="userName" value=""/>
+							</li>
+							<li>
+								<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
+								<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
+							</li>
+						</ul>
+					</div>
+				</form>
+			</div>
+			<div class="btn-group-sm" id="toolbar" role="group">
+		        <i class="fa fa-info-circle" style="color: red;"></i>  勾选数据导出指定列,否则为全部   
+		        <a class="btn btn-warning" onclick="exportSelected()">
+		            <i class="fa fa-download"></i> 导出
+		        </a>
+            </div>
+			<div class="col-sm-12 select-table table-striped">
+				<table id="bootstrap-table"></table>
+			</div>
+		</div>
+	</div>
+    <div th:include="include :: footer"></div>
+    <script th:inline="javascript">
+        var prefix = ctx + "demo/table";
+        var datas = [[${@dict.getType('sys_normal_disable')}]];
+
+        $(function() {
+            var options = {
+                url: prefix + "/list",
+		        showSearch: false,
+		        showRefresh: false,
+		        showToggle: false,
+		        showColumns: false,
+		        clickToSelect: true,
+		        rememberSelected: true,
+                columns: [{
+                	field: 'state',
+		            checkbox: true
+		        },
+				{
+					field : 'userId', 
+					title : '用户ID'
+				},
+				{
+					field : 'userCode', 
+					title : '用户编号'
+				},
+				{
+					field : 'userName', 
+					title : '用户姓名'
+				},
+				{
+					field : 'userPhone', 
+					title : '用户手机'
+				},
+				{
+					field : 'userEmail', 
+					title : '用户邮箱'
+				},
+				{
+				    field : 'userBalance',
+				    title : '用户余额'
+				},
+				{
+                    field: 'status',
+                    title: '用户状态',
+                    align: 'center',
+                    formatter: function(value, row, index) {
+                    	return $.table.selectDictLabel(datas, value);
+                    }
+                },
+		        {
+		            title: '操作',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		            	var actions = [];
+		            	actions.push('<a class="btn btn-success btn-xs" href="javascript:;"><i class="fa fa-edit"></i>编辑</a> ');
+                        actions.push('<a class="btn btn-danger btn-xs" href="javascript:;"><i class="fa fa-remove"></i>删除</a>');
+						return actions.join('');
+		            }
+		        }]
+            };
+            $.table.init(options);
+        });
+        
+        // 导出数据
+        function exportSelected() {
+        	var userIds = $.table.selectColumns("userId");
+        	var dataParam = $("#export-form").serializeArray();
+        	var tipMsg = "确定导出所有数据吗?";
+        	if($.common.isNotEmpty(userIds)){
+        		tipMsg = "确定导出勾选" + userIds.length + "条数据吗?";
+        		dataParam.push({ "name": "userIds", "value": userIds });
+        	}
+        	$.modal.confirm(tipMsg, function() {
+    			$.post(prefix + "/exportData", dataParam, function(result) {
+                    if (result.code == web_status.SUCCESS) {
+                        window.location.href = ctx + "common/download?fileName=" + encodeURI(result.msg) + "&delete=" + true;
+                    } else {
+                        $.modal.alertError(result.msg);
+                    }
+                });
+        	});
+        }
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/demo/table/fixedColumns.html b/ruoyi-admin/src/main/resources/templates/demo/table/fixedColumns.html
new file mode 100644
index 0000000..c79dc6c
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/table/fixedColumns.html
@@ -0,0 +1,145 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('冻结列')" />
+</head>
+<body class="gray-bg">
+     <div class="container-div">
+		<div class="row">
+			<div class="btn-group-sm" id="toolbar" role="group">
+				<a class="btn btn-success">
+	                <i class="fa fa-plus"></i> 新增
+	            </a>
+				<a class="btn btn-primary single disabled">
+		            <i class="fa fa-edit"></i> 修改
+		        </a>
+				<a class="btn btn-danger multiple disabled">
+		            <i class="fa fa-remove"></i> 删除
+		        </a>
+	        </div>
+			<div class="col-sm-12 select-table table-striped">
+				<table id="bootstrap-table"></table>
+			</div>
+		</div>
+	</div>
+    <div th:include="include :: footer"></div>
+    <th:block th:include="include :: bootstrap-table-fixed-columns-js" />
+    <script th:inline="javascript">
+        var prefix = ctx + "demo/table";
+        var datas = [[${@dict.getType('sys_normal_disable')}]];
+
+        $(function() {
+            var options = {
+                url: prefix + "/list",
+		        showSearch: false,
+		        showRefresh: false,
+		        showToggle: false,
+		        showColumns: false,
+		        fixedColumns: true,
+    		    fixedNumber: 3,
+    		    fixedRightNumber: 3,
+                columns: [{
+		            checkbox: true
+		        },
+				{
+					field : 'userId', 
+					title : '用户ID'
+				},
+				{
+					field : 'userCode', 
+					title : '用户编号'
+				},
+				{
+					field : 'userName', 
+					title : '用户姓名'
+				},
+				{
+					field : 'userPhone', 
+					title : '用户手机'
+				},
+				{
+					field : 'userEmail', 
+					title : '用户邮箱'
+				},
+				{
+				    field : 'userBalance',
+				    title : '用户余额'
+				},
+				{
+                    field: 'status',
+                    title: '用户状态',
+                    align: 'center',
+                    formatter: function(value, row, index) {
+                    	return $.table.selectDictLabel(datas, value);
+                    }
+                },
+				{
+				    field : 'userBalance',
+				    title : '测试1'
+				},
+				{
+				    field : 'userBalance',
+				    title : '测试2'
+				},
+				{
+				    field : 'userBalance',
+				    title : '测试3'
+				},
+				{
+				    field : 'userBalance',
+				    title : '测试4'
+				},
+				{
+				    field : 'userBalance',
+				    title : '测试5'
+				},
+				{
+				    field : 'userBalance',
+				    title : '测试6'
+				},
+				{
+				    field : 'userBalance',
+				    title : '测试7'
+				},
+				{
+				    field : 'userBalance',
+				    title : '测试8'
+				},
+				{
+				    field : 'userBalance',
+				    title : '测试9'
+				},
+				{
+				    field : 'userBalance',
+				    title : '测试10'
+				},
+				{
+				    field : 'userBalance',
+				    title : '测试11'
+				},
+				{
+				    field : 'userBalance',
+				    title : '测试12'
+				},
+				{
+				    field : 'userBalance',
+				    title : '测试13'
+				},
+				{
+				    field : 'userBalance',
+				    title : '测试14'
+				},
+				{
+				    field : 'userBalance',
+				    title : '测试15'
+				},
+				{
+				    field : 'userBalance',
+				    title : '测试16'
+				}]
+            };
+            $.table.init(options);
+        });
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/demo/table/footer.html b/ruoyi-admin/src/main/resources/templates/demo/table/footer.html
new file mode 100644
index 0000000..d90467a
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/table/footer.html
@@ -0,0 +1,95 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('表格数据汇总')" />
+</head>
+<body class="gray-bg">
+     <div class="container-div">
+		<div class="row">
+			<div class="col-sm-12 select-table table-striped">
+				<table id="bootstrap-table"></table>
+			</div>
+		</div>
+	</div>
+    <div th:include="include :: footer"></div>
+    <script th:inline="javascript">
+        var prefix = ctx + "demo/table";
+        var datas = [[${@dict.getType('sys_normal_disable')}]];
+
+        $(function() {
+            var options = {
+                url: prefix + "/list",
+		        showFooter: true,
+		        showSearch: false,
+		        showRefresh: false,
+		        showToggle: false,
+		        showColumns: false,
+		        footerStyle: footerStyle,
+                columns: [{
+		            checkbox: true
+		        },
+				{
+					field : 'userId', 
+					title : '用户ID'
+				},
+				{
+					field : 'userCode', 
+					title : '用户编号'
+				},
+				{
+					field : 'userName', 
+					title : '用户姓名'
+				},
+				{
+					field : 'userPhone', 
+					title : '用户手机'
+				},
+				{
+					field : 'userEmail', 
+					title : '用户邮箱'
+				},
+				{
+				    field : 'userBalance',
+				    title : '用户余额',
+				    footerFormatter:function (value) {
+				    	var sumBalance = 0;
+				        for (var i in value) {
+				        	sumBalance += parseFloat(value[i].userBalance);
+				        }
+				        return "总金额:" + sumBalance;
+				    }
+				},
+				{
+                    field: 'status',
+                    title: '用户状态',
+                    formatter: function(value, row, index) {
+                    	return $.table.selectDictLabel(datas, value);
+                    }
+                },
+		        {
+		            title: '操作',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		            	var actions = [];
+		            	actions.push('<a class="btn btn-success btn-xs" href="javascript:;"><i class="fa fa-edit"></i>编辑</a> ');
+                        actions.push('<a class="btn btn-danger btn-xs" href="javascript:;"><i class="fa fa-remove"></i>删除</a>');
+						return actions.join('');
+		            }
+		        }]
+            };
+            $.table.init(options);
+        });
+        
+        function footerStyle(column) {
+        	return {
+//         	    userBalance: {
+//         	        classes: 'class'
+//         	    },
+        	    userBalance: {
+        	        css: { color: 'red', 'font-weight': 'normal' }
+        	    }
+        	}[column.field]
+          }
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/demo/table/groupHeader.html b/ruoyi-admin/src/main/resources/templates/demo/table/groupHeader.html
new file mode 100644
index 0000000..e7976c3
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/table/groupHeader.html
@@ -0,0 +1,80 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('组合表头')" />
+</head>
+<body class="gray-bg">
+     <div class="container-div">
+		<div class="row">
+			<div class="col-sm-12 select-table table-bordered">
+				<table id="bootstrap-table"></table>
+			</div>
+		</div>
+	</div>
+    <div th:include="include :: footer"></div>
+    <script th:inline="javascript">
+        var prefix = ctx + "demo/table";
+        var datas = [[${@dict.getType('sys_normal_disable')}]];
+
+        $(function() {
+            var options = {
+                url: prefix + "/list",
+		        showSearch: false,
+		        showRefresh: false,
+		        showToggle: false,
+		        showColumns: false,
+		        columns : [
+        				[{
+        					title : '基本信息',
+        					align : 'center',
+        					colspan : 6
+        				}, {
+        					title : '其他信息',
+        					align : 'center',
+        					colspan : 3
+        				}
+        			],
+        			[{
+        					checkbox : true
+        				}, {
+        					field : 'userId',
+        					title : '用户ID'
+        				}, {
+        					field : 'userCode',
+        					title : '用户编号'
+        				}, {
+        					field : 'userName',
+        					title : '用户姓名'
+        				}, {
+        					field : 'userPhone',
+        					title : '用户手机'
+        				}, {
+        					field : 'userEmail',
+        					title : '用户邮箱'
+        				}, {
+        					field : 'userBalance',
+        					title : '用户余额'
+        				}, {
+        					field : 'status',
+        					title : '用户状态',
+        					formatter : function (value, row, index) {
+        						return $.table.selectDictLabel(datas, value);
+        					}
+        				}, {
+        					title : '操作',
+        					align : 'center',
+        					formatter : function (value, row, index) {
+        						var actions = [];
+        						actions.push('<a class="btn btn-success btn-xs" href="javascript:;"><i class="fa fa-edit"></i>编辑</a> ');
+        						actions.push('<a class="btn btn-danger btn-xs" href="javascript:;"><i class="fa fa-remove"></i>删除</a>');
+        						return actions.join('');
+        					}
+        				}
+        			]
+        		]
+            };
+            $.table.init(options);
+        });
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/demo/table/headerStyle.html b/ruoyi-admin/src/main/resources/templates/demo/table/headerStyle.html
new file mode 100644
index 0000000..caaf4b8
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/table/headerStyle.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('表格标题格式化')" />
+</head>
+<body class="gray-bg">
+     <div class="container-div">
+		<div class="row">
+			<div class="col-sm-12 select-table table-striped">
+				<table id="bootstrap-table"></table>
+			</div>
+		</div>
+	</div>
+    <div th:include="include :: footer"></div>
+    <script th:inline="javascript">
+        var prefix = ctx + "demo/table";
+        var datas = [[${@dict.getType('sys_normal_disable')}]];
+
+        $(function() {
+            var options = {
+                url: prefix + "/list",
+		        showSearch: false,
+		        showRefresh: false,
+		        showToggle: false,
+		        showColumns: false,
+		        headerStyle: headerStyle,
+                columns: [{
+		            checkbox: true
+		        },
+				{
+					field : 'userId', 
+					title : '用户ID'
+				},
+				{
+					field : 'userCode', 
+					title : '用户编号'
+				},
+				{
+					field : 'userName', 
+					title : '用户姓名'
+				},
+				{
+					field : 'userPhone', 
+					title : '用户手机'
+				},
+				{
+					field : 'userEmail', 
+					title : '用户邮箱'
+				},
+				{
+				    field : 'userBalance',
+				    title : '用户余额'
+				},
+				{
+                    field: 'status',
+                    title: '用户状态',
+                    align: 'center',
+                    formatter: function(value, row, index) {
+                    	return $.table.selectDictLabel(datas, value);
+                    }
+                },
+		        {
+		            title: '操作',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		            	var actions = [];
+		            	actions.push('<a class="btn btn-success btn-xs" href="javascript:;"><i class="fa fa-edit"></i>编辑</a> ');
+                        actions.push('<a class="btn btn-danger btn-xs" href="javascript:;"><i class="fa fa-remove"></i>删除</a>');
+						return actions.join('');
+		            }
+		        }]
+            };
+            $.table.init(options);
+        });
+        
+        function headerStyle(column) {
+            return {
+                userId: {
+                    classes: 'uppercase'
+                },
+                userName: {
+                    css: { background: 'yellow' }
+                },
+                userBalance: {
+                    css: { color: 'red' }
+                }
+            } [column.field]
+        }
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/demo/table/image.html b/ruoyi-admin/src/main/resources/templates/demo/table/image.html
new file mode 100644
index 0000000..4ab96d7
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/table/image.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('表格图片预览')" />
+</head>
+<body class="gray-bg">
+     <div class="container-div">
+		<div class="row">
+			<div class="col-sm-12 select-table table-striped">
+				<table id="bootstrap-table"></table>
+			</div>
+		</div>
+	</div>
+    <div th:include="include :: footer"></div>
+    <script th:inline="javascript">
+        var prefix = ctx + "demo/table";
+
+        $(function() {
+            var options = {
+                url: prefix + "/list",
+		        showSearch: false,
+		        showRefresh: false,
+		        showToggle: false,
+		        showColumns: false,
+                columns: [{
+		            checkbox: true
+		        },
+				{
+					field : 'userId', 
+					title : '用户ID'
+				},
+				{
+					field : 'userCode', 
+					title : '用户编号'
+				},
+				{
+					field : 'userName', 
+					title : '用户姓名'
+				},
+				{
+				    title: '图片',
+				    formatter: function(value, row, index) {
+				    	// 图片预览(注意:如存储在本地直接获取数据库路径,如有配置context-path需要使用ctx+路径)
+				    	// 如:/profile/upload/2019/08/08/3b7a839aced67397bac694d77611ce72.png
+				    	if(index % 2 == 0){
+				    		return $.table.imageView('http://demo.ruoyi.vip/img/profile.jpg');
+				    	}else {
+				    		return $.table.imageView('http://demo.ruoyi.vip/ruoyi.png');
+				    	}
+				    }
+				},
+				{
+					field : 'userPhone', 
+					title : '用户手机'
+				},
+				{
+					field : 'userEmail', 
+					title : '用户邮箱'
+				},
+				{
+				    field : 'userBalance',
+				    title : '用户余额'
+				},
+		        {
+		            title: '操作',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		            	var actions = [];
+		            	actions.push('<a class="btn btn-success btn-xs" href="javascript:;"><i class="fa fa-edit"></i>编辑</a> ');
+                        actions.push('<a class="btn btn-danger btn-xs" href="javascript:;"><i class="fa fa-remove"></i>删除</a>');
+						return actions.join('');
+		            }
+		        }]
+            };
+            $.table.init(options);
+        });
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/demo/table/multi.html b/ruoyi-admin/src/main/resources/templates/demo/table/multi.html
new file mode 100644
index 0000000..e5fd480
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/table/multi.html
@@ -0,0 +1,224 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('初始多表格')" />
+</head>
+<body class="gray-bg">
+    <div class="container-div">
+        <div class="row">
+            <div class="col-sm-12 search-collapse">
+                <form id="form1">
+                    <div class="select-list">
+                        <ul>
+						    <li>
+								用户名称:<input type="text" name="userName"/>
+							</li>
+							<li>
+								<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search('form1', 'bootstrap-table1')"><i class="fa fa-search"></i>&nbsp;搜索</a>
+							    <a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset('form1', 'bootstrap-table1')"><i class="fa fa-refresh"></i>&nbsp;重置</a>
+							</li>
+						</ul>
+					</div>
+				</form>
+			</div>
+            <div class="btn-group-sm" id="toolbar1" role="group">
+                <a class="btn btn-success" onclick="options1()">
+	                <i class="fa fa-search"></i> options
+	            </a>
+	            <a class="btn btn-success" onclick="$.operate.add()">
+	                <i class="fa fa-plus"></i> 新增
+	            </a>
+	            <a class="btn btn-primary single disabled" onclick="$.operate.edit()">
+	                <i class="fa fa-edit"></i> 修改
+	            </a>
+	            <a class="btn btn-danger multiple disabled" onclick="$.operate.removeAll()">
+	                <i class="fa fa-remove"></i> 删除
+	            </a>
+            </div>
+			<div class="col-xs-12 select-table table-striped">
+				<table id="bootstrap-table1"></table>
+			</div>
+		</div>
+	</div>
+	
+	<div class="container-div">
+        <div class="row">
+            <div class="col-sm-12 search-collapse">
+                <form id="form2">
+                    <div class="select-list">
+                        <ul>
+                            <li>
+								用户名称:<input type="text" name="userName"/>
+							</li>
+							<li>
+								<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search('form2', 'bootstrap-table2')"><i class="fa fa-search"></i>&nbsp;搜索</a>
+							    <a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset('form2', 'bootstrap-table2')"><i class="fa fa-refresh"></i>&nbsp;重置</a>
+							</li>
+						</ul>
+					</div>
+				</form>
+			</div>
+			
+            <div class="btn-group-sm" id="toolbar2" role="group">
+                <a class="btn btn-success" onclick="options2()">
+	                <i class="fa fa-search"></i> options
+	            </a>
+	            <a class="btn btn-success" onclick="$.operate.add()">
+	                <i class="fa fa-plus"></i> 新增
+	            </a>
+	            <a class="btn btn-primary single disabled" onclick="$.operate.edit()">
+	                <i class="fa fa-edit"></i> 修改
+	            </a>
+	            <a class="btn btn-danger multiple disabled" onclick="$.operate.removeAll()">
+	                <i class="fa fa-remove"></i> 删除
+	            </a>
+            </div>
+			<div class="col-xs-12 select-table table-striped">
+				<table id="bootstrap-table2"></table>
+			</div>
+		</div>
+	</div>
+    <div th:include="include :: footer"></div>
+    <script th:inline="javascript">
+        var prefix = ctx + "demo/operate";
+        var datas = [[${@dict.getType('sys_normal_disable')}]];
+
+        $(function() {
+            var options = {
+            	id: "bootstrap-table1",
+            	formId: "form1",
+            	toolbar: "toolbar1",
+                url: prefix + "/list",
+                createUrl: prefix + "/add",
+                removeUrl: prefix + "/remove",
+                updateUrl: prefix + "/edit/{id}",
+		        modalName: "用户",
+                columns: [{
+		            checkbox: true
+		        },
+				{
+					field : 'userId', 
+					title : '用户ID'
+				},
+				{
+					field : 'userCode', 
+					title : '用户编号'
+				},
+				{
+					field : 'userName', 
+					title : '用户姓名'
+				},
+				{
+					field : 'userPhone', 
+					title : '用户手机'
+				},
+				{
+					field : 'userEmail', 
+					title : '用户邮箱'
+				},
+				{
+				    field : 'userBalance',
+				    title : '用户余额'
+				},
+				{
+                    field: 'status',
+                    title: '用户状态',
+                    align: 'center',
+                    formatter: function(value, row, index) {
+                    	return $.table.selectDictLabel(datas, value);
+                    }
+                },
+		        {
+		            title: '操作',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		            	var actions = [];
+		            	actions.push('<a class="btn btn-success btn-xs" href="###" onclick="$.operate.edit(\'' + row.userId + '\')"><i class="fa fa-edit"></i>编辑</a> ');
+                        actions.push('<a class="btn btn-danger btn-xs" href="###" onclick="$.operate.remove(\'' + row.userId + '\')"><i class="fa fa-remove"></i>删除</a>');
+						return actions.join('');
+		            }
+		        }]
+            };
+            $.table.init(options);
+        });
+        
+        
+        $(function() {
+            var options = {
+            	id: "bootstrap-table2",
+            	formId: "form2",
+            	toolbar: "toolbar2",
+                url: prefix + "/list",
+                createUrl: prefix + "/add",
+                removeUrl: prefix + "/remove",
+                updateUrl: prefix + "/edit/{id}",
+		        modalName: "用户",
+                columns: [{
+		            checkbox: true
+		        },
+				{
+					field : 'userId', 
+					title : '用户ID'
+				},
+				{
+					field : 'userCode', 
+					title : '用户编号'
+				},
+				{
+					field : 'userName', 
+					title : '用户姓名'
+				},
+				{
+					field : 'userPhone', 
+					title : '用户手机'
+				},
+				{
+					field : 'userEmail', 
+					title : '用户邮箱'
+				},
+				{
+				    field : 'userBalance',
+				    title : '用户余额'
+				},
+				{
+                    field: 'status',
+                    title: '用户状态',
+                    align: 'center',
+                    formatter: function(value, row, index) {
+                    	return $.table.selectDictLabel(datas, value);
+                    }
+                },
+		        {
+		            title: '操作',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		            	var actions = [];
+		            	actions.push('<a class="btn btn-success btn-xs" href="###" onclick="$.operate.edit(\'' + row.userId + '\')"><i class="fa fa-edit"></i>编辑</a> ');
+		            	actions.push('<a class="btn btn-danger btn-xs" href="###" onclick="$.operate.remove(\'' + row.userId + '\')"><i class="fa fa-remove"></i>删除</a>');
+						return actions.join('');
+		            }
+		        }]
+            };
+            $.table.init(options);
+        });
+        
+        function options1() {
+        	var temp = "";
+        	var obj = table.config['bootstrap-table1'];
+        	for (var i in obj) {
+        	    temp += i + ":" + obj[i] + "<br/>";
+        	}
+        	$.modal.alert(temp);
+        }
+        
+        function options2() {
+        	var temp = "";
+        	var obj = table.config['bootstrap-table2'];
+        	for (var i in obj) {
+        	    temp += i + ":" + obj[i] + "<br/>";
+        	}
+        	$.modal.alert(temp);
+        }
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/demo/table/other.html b/ruoyi-admin/src/main/resources/templates/demo/table/other.html
new file mode 100644
index 0000000..fd6c40c
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/table/other.html
@@ -0,0 +1,106 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('其他操作')" />
+</head>
+<body class="gray-bg">
+     <div class="container-div">
+     	<div class="btn-group-sm" id="toolbar" role="group">
+	        <a class="btn btn-success" onclick="$.table.showColumn('userName')">
+	            <i class="fa fa-check"></i> 显示姓名
+	        </a>
+	        <a class="btn btn-danger" onclick="$.table.hideColumn('userName')">
+	            <i class="fa fa-close"></i> 隐藏姓名
+	        </a>
+	        <a class="btn btn-info" onclick="selectColumns()">
+	            <i class="fa fa-search"></i> 获取选中姓名
+	        </a>
+	        <a class="btn btn-warning" onclick="$.table.refresh()">
+	            <i class="fa fa-refresh"></i> 刷新
+	        </a>
+	        <a class="btn btn-danger" onclick="$.table.destroy()">
+	            <i class="fa fa-refresh"></i> 销毁
+	        </a>
+	        <a class="btn btn-primary" onclick="selectFirstColumns()">
+	            <i class="fa fa-search"></i> 获取选中首列值
+	        </a>
+        </div>
+		<div class="row">
+			<div class="col-sm-12 select-table table-striped">
+				<table id="bootstrap-table"></table>
+			</div>
+		</div>
+	</div>
+    <div th:include="include :: footer"></div>
+    <script th:inline="javascript">
+        var prefix = ctx + "demo/table";
+        var datas = [[${@dict.getType('sys_normal_disable')}]];
+
+        $(function() {
+            var options = {
+                url: prefix + "/list",
+		        showSearch: false,
+		        showRefresh: false,
+		        showToggle: false,
+		        showColumns: false,
+                columns: [{
+		            checkbox: true
+		        },
+				{
+					field : 'userId', 
+					title : '用户ID'
+				},
+				{
+					field : 'userCode', 
+					title : '用户编号'
+				},
+				{
+					field : 'userName', 
+					title : '用户姓名'
+				},
+				{
+					field : 'userPhone', 
+					title : '用户手机'
+				},
+				{
+					field : 'userEmail', 
+					title : '用户邮箱'
+				},
+				{
+				    field : 'userBalance',
+				    title : '用户余额'
+				},
+				{
+                    field: 'status',
+                    title: '用户状态',
+                    align: 'center',
+                    formatter: function(value, row, index) {
+                    	return $.table.selectDictLabel(datas, value);
+                    }
+                },
+		        {
+		            title: '操作',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		            	var actions = [];
+		            	actions.push('<a class="btn btn-success btn-xs" href="javascript:;"><i class="fa fa-edit"></i>编辑</a> ');
+                        actions.push('<a class="btn btn-danger btn-xs" href="javascript:;"><i class="fa fa-remove"></i>删除</a>');
+						return actions.join('');
+		            }
+		        }]
+            };
+            $.table.init(options);
+        });
+        
+        function selectColumns() {
+        	var column = $.table.selectColumns('userName');
+        	alert(column);
+        }
+        
+        function selectFirstColumns() {
+        	var column = $.table.selectFirstColumns();
+        	alert(column);
+        }
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/demo/table/pageGo.html b/ruoyi-admin/src/main/resources/templates/demo/table/pageGo.html
new file mode 100644
index 0000000..9cbdaa9
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/table/pageGo.html
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('跳转至指定页')" />
+</head>
+<body class="gray-bg">
+     <div class="container-div">
+		<div class="row">
+			<div class="col-sm-12 select-table table-striped">
+				<table id="bootstrap-table"></table>
+			</div>
+		</div>
+	</div>
+    <div th:include="include :: footer"></div>
+    <script th:inline="javascript">
+        var prefix = ctx + "demo/table";
+        var datas = [[${@dict.getType('sys_normal_disable')}]];
+
+        $(function() {
+            var options = {
+                url: prefix + "/list",
+		        showSearch: false,
+		        showRefresh: false,
+		        showToggle: false,
+		        showColumns: false,
+		        showPageGo: true,
+                columns: [{
+		            checkbox: true
+		        },
+				{
+					field : 'userId', 
+					title : '用户ID'
+				},
+				{
+					field : 'userCode', 
+					title : '用户编号'
+				},
+				{
+					field : 'userName', 
+					title : '用户姓名'
+				},
+				{
+					field : 'userPhone', 
+					title : '用户手机'
+				},
+				{
+					field : 'userEmail', 
+					title : '用户邮箱'
+				},
+				{
+				    field : 'userBalance',
+				    title : '用户余额'
+				},
+				{
+                    field: 'status',
+                    title: '用户状态',
+                    align: 'center',
+                    formatter: function(value, row, index) {
+                    	return $.table.selectDictLabel(datas, value);
+                    }
+                },
+		        {
+		            title: '操作',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		            	var actions = [];
+		            	actions.push('<a class="btn btn-success btn-xs" href="javascript:;"><i class="fa fa-edit"></i>编辑</a> ');
+                        actions.push('<a class="btn btn-danger btn-xs" href="javascript:;"><i class="fa fa-remove"></i>删除</a>');
+						return actions.join('');
+		            }
+		        }]
+            };
+            $.table.init(options);
+        });
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/demo/table/params.html b/ruoyi-admin/src/main/resources/templates/demo/table/params.html
new file mode 100644
index 0000000..d57f53d
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/table/params.html
@@ -0,0 +1,158 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('自定义查询参数')" />
+</head>
+<body class="gray-bg">
+     <div class="container-div">
+		<div class="row">
+			<div class="col-sm-12 select-table table-striped">
+				<p class="select-title">通过queryParams方法设置</p>
+				<table id="bootstrap-table"></table>
+			</div>
+			
+			<div class="col-sm-12 search-collapse">
+				<form id="post-form">
+					<div class="select-list">
+						<ul>
+							<li>
+								用户姓名:<input type="text" name="userName" value="测试6"/>
+							</li>
+						</ul>
+					</div>
+				</form>
+			</div>
+			<div class="col-sm-12 select-table table-striped">
+				<p class="select-title">通过form自动填充</p>
+				<table id="bootstrap-table-form"></table>
+			</div>
+		</div>
+	</div>
+    <div th:include="include :: footer"></div>
+    <script th:inline="javascript">
+        var prefix = ctx + "demo/table";
+        var datas = [[${@dict.getType('sys_normal_disable')}]];
+
+        $(function() {
+            var options = {
+                url: prefix + "/list",
+		        showSearch: false,
+		        showRefresh: false,
+		        showToggle: false,
+		        showColumns: false,
+		        queryParams: queryParams,
+                columns: [{
+		            checkbox: true
+		        },
+				{
+					field : 'userId', 
+					title : '用户ID'
+				},
+				{
+					field : 'userCode', 
+					title : '用户编号'
+				},
+				{
+					field : 'userName', 
+					title : '用户姓名'
+				},
+				{
+					field : 'userPhone', 
+					title : '用户手机'
+				},
+				{
+					field : 'userEmail', 
+					title : '用户邮箱'
+				},
+				{
+				    field : 'userBalance',
+				    title : '用户余额'
+				},
+				{
+                    field: 'status',
+                    title: '用户状态',
+                    align: 'center',
+                    formatter: function(value, row, index) {
+                    	return $.table.selectDictLabel(datas, value);
+                    }
+                },
+		        {
+		            title: '操作',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		            	var actions = [];
+		            	actions.push('<a class="btn btn-success btn-xs" href="javascript:;"><i class="fa fa-edit"></i>编辑</a> ');
+                        actions.push('<a class="btn btn-danger btn-xs" href="javascript:;"><i class="fa fa-remove"></i>删除</a>');
+						return actions.join('');
+		            }
+		        }]
+            };
+            $.table.init(options);
+        });
+        
+        function queryParams(params) {
+            var search = $.table.queryParams(params);
+            search.userName = '测试1';
+            return search;
+        }
+        
+        
+        $(function() {
+            var options = {
+            	id: "bootstrap-table-form",
+                url: prefix + "/list",
+		        showSearch: false,
+		        showRefresh: false,
+		        showToggle: false,
+		        showColumns: false,
+                columns: [{
+		            checkbox: true
+		        },
+				{
+					field : 'userId', 
+					title : '用户ID'
+				},
+				{
+					field : 'userCode', 
+					title : '用户编号'
+				},
+				{
+					field : 'userName', 
+					title : '用户姓名'
+				},
+				{
+					field : 'userPhone', 
+					title : '用户手机'
+				},
+				{
+					field : 'userEmail', 
+					title : '用户邮箱'
+				},
+				{
+				    field : 'userBalance',
+				    title : '用户余额'
+				},
+				{
+                    field: 'status',
+                    title: '用户状态',
+                    align: 'center',
+                    formatter: function(value, row, index) {
+                    	return $.table.selectDictLabel(datas, value);
+                    }
+                },
+		        {
+		            title: '操作',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		            	var actions = [];
+		            	actions.push('<a class="btn btn-success btn-xs" href="javascript:;"><i class="fa fa-edit"></i>编辑</a> ');
+                        actions.push('<a class="btn btn-danger btn-xs" href="javascript:;"><i class="fa fa-remove"></i>删除</a>');
+						return actions.join('');
+		            }
+		        }]
+            };
+            $.table.init(options);
+        });
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/demo/table/print.html b/ruoyi-admin/src/main/resources/templates/demo/table/print.html
new file mode 100644
index 0000000..8695376
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/table/print.html
@@ -0,0 +1,131 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('表格打印配置')" />
+</head>
+<body class="gray-bg">
+     <div class="container-div">
+		<div class="row">
+			<div class="col-sm-12 select-table table-striped">
+			    <!-- data-show-print设置为true为显示工具栏上的“打印”按钮。
+			         data-print-as-filtered-and-sorted-on-ui为true时-在用户界面上按排序和过滤条件打印表格。请注意,如果设置为true以及用于过滤和排序的显式预定义打印选项(printFilter,printSortOrder,printSortColumn),则它们将应用于已由UI控件过滤和排序的数据。对于在UI上按过滤和排序方式打印数据-请勿设置以下3个选项:printFilter,printSortOrder,printSortColumn
+			         data-print-page-builder 接收html <table>元素作为字符串参数,返回html字符串进行打印。用于样式和添加页眉或页脚。
+			         data-print-sort-column 设置列字段名称以对打印表进行排序
+			         data-print-sort-order 有效值:“ asc”,“ desc”。仅当设置了printSortColumn时相关
+			         data-print-filter 设置值以按此列过滤打印的数据。
+			         data-print-formatter 函数(值,行,索引)-返回字符串。格式化打印表中此列的单元格值。函数行为类似于“ formatter”列选项
+			         printIgnore 设置为true可以在打印页面中隐藏此列。 -->
+				<table id="bootstrap-table"></table>
+			</div>
+		</div>
+	</div>
+    <div th:include="include :: footer"></div>
+    <th:block th:include="include :: bootstrap-table-print-js" />
+    <script th:inline="javascript">
+        var prefix = ctx + "demo/table";
+
+        $(function() {
+            var options = {
+                url: prefix + "/list",
+                showPrint: true,
+		        showSearch: false,
+		        showRefresh: false,
+		        showToggle: false,
+		        showColumns: false,
+		        printPageBuilder: printPageBuilder,
+                columns: [{
+		            checkbox: true,
+		            printIgnore: true
+		        },
+				{
+					field : 'userId', 
+					title : '用户ID'
+				},
+				{
+					field : 'userCode', 
+					title : '用户编号'
+				},
+				{
+					field : 'userName', 
+					title : '用户姓名'
+				},
+				{
+					field : 'userPhone', 
+					title : '用户手机'
+				},
+				{
+					field : 'userEmail', 
+					title : '用户邮箱'
+				},
+				{
+				    field : 'userBalance',
+				    title : '用户余额'
+				},
+		        {
+		            title: '操作',
+		            align: 'center',
+		            printIgnore: true,
+		            formatter: function(value, row, index) {
+		            	var actions = [];
+                        actions.push('<a class="btn btn-danger btn-xs" href="javascript:;" onclick="remove(this)"><i class="fa fa-remove"></i>删除</a>');
+						return actions.join('');
+		            }
+		        }]
+            };
+            $.table.init(options);
+        });
+        
+        // 假删除操作
+        function remove(obj) {
+        	$.modal.confirm("确认要删除吗?", function() {
+        	    $(obj).parents("tr").remove();
+        	    $.modal.msgSuccess('已删除!');
+        	});
+        }
+        
+        // 自定义打印页面模板
+        function printPageBuilder(table) {
+        	return `
+        	<html>
+        	  <head>
+        	  <style type="text/css" media="print">
+        	  @page {
+        	    size: auto;
+        	    margin: 25px 0 25px 0;
+        	  }
+        	  </style>
+        	  <style type="text/css" media="all">
+        	  table {
+        	    border-collapse: collapse;
+        	    font-size: 12px;
+        	  }
+        	  table, th, td {
+        	    border: 1px solid grey;
+        	  }
+        	  th, td {
+        	    text-align: center;
+        	    vertical-align: middle;
+        	  }
+        	  p {
+        	    font-weight: bold;
+        	    margin-left:20px;
+        	  }
+        	  table {
+        	    width:94%;
+        	    margin-left:3%;
+        	    margin-right:3%;
+        	  }
+        	  div.bs-table-print {
+        	    text-align:center;
+        	  }
+        	  </style>
+        	  </head>
+        	  <title>Print Table</title>
+        	  <body>
+        	  <div class="bs-table-print">${table}</div>
+        	  </body>
+        	</html>`
+        }
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/demo/table/refresh.html b/ruoyi-admin/src/main/resources/templates/demo/table/refresh.html
new file mode 100644
index 0000000..5917bff
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/table/refresh.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('表格自动刷新')" />
+</head>
+<body class="gray-bg">
+     <div class="container-div">
+		<div class="row">
+			<div class="col-sm-12 select-table table-striped">
+			    <!-- data-auto-refresh设置true为启用自动刷新插件 
+			         data-auto-refresh-interval为每次自动刷新发生的时间(以秒为单位)默认60。
+				     data-auto-refresh-silent设置为true可以自动无提示刷新。默认: true
+				     data-auto-refresh-status 设置true为启用自动刷新。这是表加载时自动刷新的状态。单击按钮切换此属性。这只是自动刷新的默认状态,因为用户始终可以通过单击按钮来更改它。 默认: true  -->
+				<table id="bootstrap-table" data-auto-refresh="true" data-auto-refresh-interval="30"></table>
+			</div>
+		</div>
+	</div>
+    <div th:include="include :: footer"></div>
+    <th:block th:include="include :: bootstrap-table-auto-refresh-js" />
+    <script th:inline="javascript">
+        var prefix = ctx + "demo/table";
+
+        $(function() {
+            var options = {
+                url: prefix + "/list",
+		        showSearch: false,
+		        showRefresh: false,
+		        showToggle: false,
+		        showColumns: false,
+                columns: [{
+		            checkbox: true
+		        },
+				{
+					field : 'userId', 
+					title : '用户ID'
+				},
+				{
+					field : 'userCode', 
+					title : '用户编号'
+				},
+				{
+					field : 'userName', 
+					title : '用户姓名'
+				},
+				{
+					field : 'userPhone', 
+					title : '用户手机'
+				},
+				{
+					field : 'userEmail', 
+					title : '用户邮箱'
+				},
+				{
+				    field : 'userBalance',
+				    title : '用户余额'
+				},
+		        {
+		            title: '操作',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		            	var actions = [];
+                        actions.push('<a class="btn btn-danger btn-xs" href="javascript:;" onclick="remove(this)"><i class="fa fa-remove"></i>删除</a>');
+						return actions.join('');
+		            }
+		        }]
+            };
+            $.table.init(options);
+        });
+        
+        // 假删除操作
+        function remove(obj) {
+        	$.modal.confirm("确认要删除吗?", function() {
+        	    $(obj).parents("tr").remove();
+        	    $.modal.msgSuccess('已删除!');
+        	});
+        }
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/demo/table/remember.html b/ruoyi-admin/src/main/resources/templates/demo/table/remember.html
new file mode 100644
index 0000000..65f2dec
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/table/remember.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('翻页记住选择')" />
+</head>
+<body class="gray-bg">
+     <div class="container-div">
+     	<div class="btn-group-sm" id="toolbar" role="group">
+	        <a class="btn btn-success" onclick="checkItem()">
+	            <i class="fa fa-check"></i> 选中项
+	        </a>
+        </div>
+		<div class="row">
+			<div class="col-sm-12 select-table table-striped">
+				<table id="bootstrap-table"></table>
+			</div>
+		</div>
+	</div>
+    <div th:include="include :: footer"></div>
+    <script th:inline="javascript">
+        var prefix = ctx + "demo/table";
+        var datas = [[${@dict.getType('sys_normal_disable')}]];
+
+        $(function() {
+            var options = {
+                url: prefix + "/list",
+		        rememberSelected: true,
+                columns: [{
+                	field: 'state',
+		            checkbox: true
+		        },
+				{
+					field : 'userId', 
+					title : '用户ID'
+				},
+				{
+					field : 'userCode', 
+					title : '用户编号'
+				},
+				{
+					field : 'userName', 
+					title : '用户姓名'
+				},
+				{
+					field : 'userPhone', 
+					title : '用户手机'
+				},
+				{
+					field : 'userEmail', 
+					title : '用户邮箱'
+				},
+				{
+				    field : 'userBalance',
+				    title : '用户余额'
+				},
+				{
+                    field: 'status',
+                    title: '用户状态',
+                    align: 'center',
+                    formatter: function(value, row, index) {
+                    	return $.table.selectDictLabel(datas, value);
+                    }
+                },
+		        {
+		            title: '操作',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		            	var actions = [];
+		            	actions.push('<a class="btn btn-success btn-xs" href="javascript:;"><i class="fa fa-edit"></i>编辑</a> ');
+                        actions.push('<a class="btn btn-danger btn-xs" href="javascript:;"><i class="fa fa-remove"></i>删除</a>');
+						return actions.join('');
+		            }
+		        }]
+            };
+            $.table.init(options);
+        });
+        
+        // 选中数据
+        function checkItem(){
+        	// var arrays = $.table.selectColumns("userId");
+        	var arrays = $.table.selectColumns("userCode");
+        	alert(arrays);
+        }
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/demo/table/reorderColumns.html b/ruoyi-admin/src/main/resources/templates/demo/table/reorderColumns.html
new file mode 100644
index 0000000..a461d60
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/table/reorderColumns.html
@@ -0,0 +1,84 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('表格列拖拽操作')" />
+</head>
+<body class="gray-bg">
+     <div class="container-div">
+        <div class="btn-group-sm" id="toolbar" role="group">
+	        <a class="btn btn-success" onclick="orderColumns()">
+	            <i class="fa fa-refresh"></i> 恢复顺序
+	        </a>
+        </div>
+		<div class="row">
+			<div class="col-sm-12 select-table table-bordered">
+			    <p class="select-title">按住表格列拖拽</p>
+				<table id="bootstrap-table"
+				 data-reorderable-columns="true"></table>
+			</div>
+		</div>
+	</div>
+    <div th:include="include :: footer"></div>
+    <script th:src="@{/js/jquery-ui-1.10.4.min.js}"></script>
+    <th:block th:include="include :: bootstrap-table-reorder-columns-js" />
+    <script th:inline="javascript">
+        var prefix = ctx + "demo/table";
+        var datas = [[${@dict.getType('sys_normal_disable')}]];
+
+        $(function() {
+            var options = {
+                url: prefix + "/list",
+		        showSearch: false,
+		        showRefresh: false,
+		        showToggle: false,
+		        showColumns: false,
+                columns: [{
+					field : 'userId', 
+					title : '用户ID'
+				},
+				{
+					field : 'userCode', 
+					title : '用户编号'
+				},
+				{
+					field : 'userName', 
+					title : '用户姓名'
+				},
+				{
+					field : 'userPhone', 
+					title : '用户手机'
+				},
+				{
+					field : 'userEmail', 
+					title : '用户邮箱'
+				},
+				{
+				    field : 'userBalance',
+				    title : '用户余额'
+				},
+				{
+                    field: 'status',
+                    title: '用户状态',
+                    align: 'center',
+                    formatter: function(value, row, index) {
+                    	return $.table.selectDictLabel(datas, value);
+                    }
+                }]
+            };
+            $.table.init(options);
+        });
+        
+        function orderColumns() {
+            $('#bootstrap-table').bootstrapTable('orderColumns', {
+            	userId: 0,
+            	userCode: 1,
+            	userName: 2,
+            	userPhone: 3,
+            	userEmail: 4,
+            	userBalance: 5,
+            	status: 6
+            })
+        }
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/demo/table/reorderRows.html b/ruoyi-admin/src/main/resources/templates/demo/table/reorderRows.html
new file mode 100644
index 0000000..ded9ece
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/table/reorderRows.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('表格行拖拽操作')" />
+</head>
+<body class="gray-bg">
+     <div class="container-div">
+        <div class="btn-group-sm" id="toolbar" role="group">
+            <a class="btn btn-primary" onclick="getData()">
+                <i class="fa fa-search"></i> 查询所有数据
+            </a>
+        </div>
+		<div class="row">
+			<div class="col-sm-12 select-table table-striped">
+			    <p class="select-title">按住表格行拖拽</p>
+				<table id="bootstrap-table"
+				 data-use-row-attr-func="true"
+				 data-reorderable-rows="true"></table>
+			</div>
+		</div>
+	</div>
+    <div th:include="include :: footer"></div>
+    <th:block th:include="include :: bootstrap-table-reorder-rows-js" />
+    <script th:inline="javascript">
+        var prefix = ctx + "demo/table";
+        var datas = [[${@dict.getType('sys_normal_disable')}]];
+
+        $(function() {
+            var options = {
+                url: prefix + "/list",
+		        showSearch: false,
+		        showRefresh: false,
+		        showToggle: false,
+		        showColumns: false,
+		        onReorderRow: function (data, newRow, oldRow, el) {
+			        // 当拖拽结束后,data为整个表格的数据
+		            console.table(data)
+		            // 当sidePagination: "server"时,拖拽行后顺序错乱,需要重新调用加载数据方法
+		            $("#" + table.options.id).bootstrapTable('load', {
+			            total: el._xhr.responseJSON.total,
+			            rows: data
+			        });
+		            return false;
+		        },
+                columns: [{
+		            checkbox: true
+		        },
+				{
+					field : 'userId', 
+					title : '用户ID'
+				},
+				{
+					field : 'userCode', 
+					title : '用户编号'
+				},
+				{
+					field : 'userName', 
+					title : '用户姓名'
+				},
+				{
+					field : 'userPhone', 
+					title : '用户手机'
+				},
+				{
+					field : 'userEmail', 
+					title : '用户邮箱'
+				},
+				{
+				    field : 'userBalance',
+				    title : '用户余额'
+				},
+				{
+                    field: 'status',
+                    title: '用户状态',
+                    align: 'center',
+                    formatter: function(value, row, index) {
+                    	return $.table.selectDictLabel(datas, value);
+                    }
+                }]
+            };
+            $.table.init(options);
+        });
+        
+        /* 查询表格所有数据值 */
+        function getData(){
+            var data = $("#" + table.options.id).bootstrapTable('getData');
+            alert(JSON.stringify(data.map( item => { return item.userId })))
+        }
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/demo/table/resizable.html b/ruoyi-admin/src/main/resources/templates/demo/table/resizable.html
new file mode 100644
index 0000000..c99d66e
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/table/resizable.html
@@ -0,0 +1,87 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('表格列宽拖动')" />
+</head>
+<body class="gray-bg">
+     <div class="container-div">
+		<div class="row">
+			<div class="col-sm-12 select-table table-bordered">
+				<table id="bootstrap-table" data-resizable="true"></table>
+			</div>
+		</div>
+	</div>
+    <div th:include="include :: footer"></div>
+    <th:block th:include="include :: bootstrap-table-resizable-js" />
+    
+    <script th:inline="javascript">
+        var prefix = ctx + "demo/table";
+        var datas = [[${@dict.getType('sys_normal_disable')}]];
+
+        $(function() {
+            var options = {
+                url: prefix + "/list",
+		        showSearch: false,
+		        showRefresh: false,
+		        showToggle: false,
+		        showColumns: false,
+                columns: [{
+		            checkbox: true
+		        },
+				{
+					field : 'userId', 
+					title : '用户ID'
+				},
+				{
+					field : 'userCode', 
+					title : '用户编号'
+				},
+				{
+					field : 'userName', 
+					title : '用户姓名',
+					cellStyle: function (value, row, index) {
+                        return { css: { "min-width": "100px", "white-space": "nowrap", "text-overflow": "ellipsis", "overflow": "hidden", "max-width": "200px" } }
+                    },
+                    formatter: function(value, row, index) {
+                        if (index == 0) {
+                            value = value + ",测试用户姓名,这是一条长文本,可以通过拖拽自适应内容显示。。。。";
+                        }
+                        return $.table.tooltip(value, 30, "open");
+                    }
+				},
+				{
+					field : 'userPhone', 
+					title : '用户手机'
+				},
+				{
+					field : 'userEmail', 
+					title : '用户邮箱'
+				},
+				{
+				    field : 'userBalance',
+				    title : '用户余额'
+				},
+				{
+                    field: 'status',
+                    title: '用户状态',
+                    align: 'center',
+                    formatter: function(value, row, index) {
+                    	return $.table.selectDictLabel(datas, value);
+                    }
+                },
+		        {
+		            title: '操作',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		            	var actions = [];
+		            	actions.push('<a class="btn btn-success btn-xs" href="javascript:;"><i class="fa fa-edit"></i>编辑</a> ');
+                        actions.push('<a class="btn btn-danger btn-xs" href="javascript:;"><i class="fa fa-remove"></i>删除</a>');
+						return actions.join('');
+		            }
+		        }]
+            };
+            $.table.init(options);
+        });
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/demo/table/search.html b/ruoyi-admin/src/main/resources/templates/demo/table/search.html
new file mode 100644
index 0000000..e6781b1
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/table/search.html
@@ -0,0 +1,202 @@
+<!DOCTYPE html>
+<html lang="zh">
+<head>
+	<th:block th:include="include :: header('表格搜索')" />
+	<th:block th:include="include :: bootstrap-select-css" />
+</head>
+<body class="gray-bg">
+    <div class="container-div">
+		<div class="row">
+			<div class="col-sm-12 search-collapse">
+			    <p class="select-title">普通条件查询</p>
+				<form id="ordinary-form">
+					<div class="select-list">
+						<ul>
+							<li>
+								商户编号:<input type="text" name="userId"/>
+							</li>
+							<li>
+								终端编号:<input type="text" name="termId"/>
+							</li>
+							<li>
+								处理状态:<select name="status">
+									<option value="">所有</option>
+									<option value="0">初始</option>
+									<option value="1">处理中</option>
+									<option value="2">交易成功</option>
+									<option value="3">交易失败</option>
+								</select>
+							</li>
+							<li>
+								<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
+							    <a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
+							</li>
+						</ul>
+					</div>
+				</form>
+			</div>
+
+			<div class="col-sm-12 search-collapse">
+			    <p class="select-title">时间条件查询</p>
+				<form id="time-form">
+					<div class="select-list">
+						<ul>
+							<li>
+								商户编号:<input type="text" name="userId"/>
+							</li>
+							<li>
+								终端编号:<input type="text" name="termId"/>
+							</li>
+							<li class="select-time">
+								<label>创建时间: </label>
+								<input type="text" class="time-input" id="startTime" placeholder="开始时间" name="params[beginTime]"/>
+								<span>-</span>
+								<input type="text" class="time-input" id="endTime" placeholder="结束时间" name="params[endTime]"/>
+							</li>
+							<li>
+								<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
+							    <a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset('time-form')"><i class="fa fa-refresh"></i>&nbsp;重置</a>
+							</li>
+						</ul>
+					</div>
+				</form>
+			</div>
+
+			<div class="col-sm-12 search-collapse">
+			    <p class="select-title">多级联动下拉查询</p>
+				<form id="cxselect-form">
+					<div class="select-list">
+						<ul id="element">
+						    <li>
+								商户编号:<input type="text" name="userId"/>
+							</li>
+							<li>
+								充值类型:<select class="type"></select>
+							</li>
+							<li>
+								充值路由:<select class="router"></select>
+							</li>
+							<li>
+								<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
+							    <a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset('cxselect-form')"><i class="fa fa-refresh"></i>&nbsp;重置</a>
+							</li>
+						</ul>
+					</div>
+				</form>
+			</div>
+
+			<div class="col-sm-12 search-collapse">
+			    <p class="select-title">下拉多选条件查询</p>
+				<form id="select-form">
+					<div class="select-list">
+						<ul>
+							<li>
+								商户编号:<input type="text" name="userId"/>
+							</li>
+							<li>
+								终端编号:<input type="text" name="termId"/>
+							</li>
+							<li class="select-selectpicker">
+								<label>操作类型: </label><select class="selectpicker" data-none-selected-text="请选择" multiple>
+									<option value="">所有</option>
+									<option value="0">初始</option>
+									<option value="1">处理中</option>
+									<option value="2">交易成功</option>
+									<option value="3">交易失败</option>
+								</select>
+							</li>
+							<li>
+								<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
+							    <a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset('select-form')"><i class="fa fa-refresh"></i>&nbsp;重置</a>
+							</li>
+						</ul>
+					</div>
+				</form>
+			</div>
+
+			<div class="col-sm-12 search-collapse">
+			    <p class="select-title">复杂条件查询</p>
+				<form id="complex-form">
+					<div class="select-list">
+						<ul>
+							<li>
+								<label style="width: 80px">商户编号:</label>
+								<input type="text" name="userId"/>
+							</li>
+							<li>
+								<label style="width: 80px">订单号:</label>
+								<input type="text" name="orderNo"/>
+							</li>
+							<li>
+								<label style="width: 80px">日期:</label>
+								<input type="text" class="time-input" placeholder="日期"/>
+							</li>
+							<li class="select-selectpicker">
+								<label style="width: 80px">状态:</label>
+								<select class="selectpicker" data-none-selected-text="请选择" multiple>
+									<option value="">所有</option>
+									<option value="0">初始</option>
+									<option value="1">处理中</option>
+									<option value="2">交易成功</option>
+									<option value="3">交易失败</option>
+								</select>
+							</li>
+							<li>
+								<label style="width: 80px">供货商通道:</label>
+								<select>
+									<option value="">所有</option>
+									<option value="0">腾讯</option>
+									<option value="1">天猫</option>
+									<option value="2">京东</option>
+								</select>
+							</li>
+							<li>
+								<label style="width: 80px">来源:</label>
+								<select>
+									<option value="">所有</option>
+									<option value="0">手机</option>
+									<option value="1">电脑</option>
+									<option value="2">第三方</option>
+								</select>
+							</li>
+							<li>
+								<label style="width: 80px">运营商:</label>
+								<select>
+									<option value="">所有</option>
+									<option value="0">移动</option>
+									<option value="1">电信</option>
+									<option value="2">联通</option>
+								</select>
+							</li>
+							<li class="select-time">
+								<label style="width: 80px">回调时间:</label>
+								<input type="text" class="time-input" placeholder="开始时间"/>
+								<span>-</span>
+								<input type="text" class="time-input" placeholder="结束时间"/>
+							</li>
+
+							<li>
+								<a class="btn btn-primary btn-rounded btn-sm m50" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
+							    <a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset('complex-form')"><i class="fa fa-refresh"></i>&nbsp;重置</a>
+							</li>
+						</ul>
+					</div>
+				</form>
+			</div>
+		</div>
+	</div>
+	<th:block th:include="include :: footer" />
+	<th:block th:include="include :: bootstrap-select-js" />
+	<th:block th:include="include :: jquery-cxselect-js" />
+
+	<script th:inline="javascript">
+	    // 直接返回获取
+   		var data = [{"v":"taobao","n":"淘宝","s":[{"v":"tm","n":"天猫"},{"v":"jhs","n":"聚划算"}]},{"v":"jd","n":"京东","s":[{"v":"jdcs","n":"京东超市"},{"v":"jdsx","n":"京东生鲜"}]}];
+    	$('#element').cxSelect({
+    	  selects: ['type', 'router'],
+    	  jsonValue: 'v',
+    	  data: data
+    	});
+    </script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/demo/table/subdata.html b/ruoyi-admin/src/main/resources/templates/demo/table/subdata.html
new file mode 100644
index 0000000..72ee6e9
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/table/subdata.html
@@ -0,0 +1,242 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+    <th:block th:include="include :: header('主子表提交')" />
+    <th:block th:include="include :: datetimepicker-css" />
+    <style type="text/css">
+        table label.error{position: inherit;}select + label.error{z-index:1;right:40px;}
+    </style>
+</head>
+<body class="gray-bg">
+    <div class="main-content">
+        <form id="form-add" class="form-horizontal">
+            <h4 class="form-header h4">客户信息</h4>
+            <div class="row">
+            	<div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label is-required">客户名称:</label>
+                        <div class="col-sm-8">
+                            <input name="name" placeholder="请输入客户名称" class="form-control" type="text" maxlength="30" required>
+                        </div>
+                    </div>
+                </div>
+                <div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label is-required">用户性别:</label>
+                        <div class="col-sm-8">
+                            <select name="sex" class="form-control" th:with="type=${@dict.getType('sys_user_sex')}">
+				                <option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
+				            </select>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="row">
+                <div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label">手机号码:</label>
+                        <div class="col-sm-8">
+                            <input id="phonenumber" name="phonenumber" placeholder="请输入手机号码" class="form-control isPhone" type="text" maxlength="11">
+                        </div>
+                    </div>
+                </div>
+                <div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label is-required">生日:</label>
+                        <div class="col-sm-8">
+                            <div class="input-group date">
+		                        <input name="birthday" class="form-control" placeholder="yyyy-MM-dd" type="text">
+		                        <span class="input-group-addon"><i class="fa fa-calendar"></i></span>
+		                    </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="row">
+                <div class="col-sm-12">
+                    <div class="form-group">
+                        <label class="col-xs-2 control-label">备注:</label>
+                        <div class="col-xs-10">
+                            <textarea name="remark" maxlength="500" class="form-control" rows="3"></textarea>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <h4 class="form-header h4">商品数据</h4>
+            <div class="row">
+                <div class="col-sm-12">
+                    <button type="button" class="btn btn-white btn-sm" onclick="addRow()"><i class="fa fa-plus"> 增加</i></button>
+                    <button type="button" class="btn btn-white btn-sm" onclick="sub.delRow()"><i class="fa fa-minus"> 删除</i></button>
+                    <div class="col-sm-12 select-table table-striped">
+					    <table id="bootstrap-table"></table>
+					</div>
+                </div>
+            </div>
+        </form>
+    </div>
+      
+    <div class="row">
+        <div class="col-sm-offset-5 col-sm-10">
+            <button type="button" class="btn btn-sm btn-primary" onclick="submitHandler()"><i class="fa fa-check"></i>保 存</button>&nbsp;
+            <button type="button" class="btn btn-sm btn-danger" onclick="closeItem()"><i class="fa fa-reply-all"></i>关 闭 </button>
+        </div>
+    </div>
+    <th:block th:include="include :: footer" />
+    <th:block th:include="include :: datetimepicker-js" />
+    <script th:src="@{/js/jquery.tmpl.js}"></script>
+	<script th:inline="javascript">
+	    $(function() {
+	    	// 初始化数据, 可以由后台传过来
+	    	var data = [
+	    	{
+	    		id: "100",
+	    		name: "商品名称",
+            	weight: "100",
+            	price: "12.5",
+            	date: "2021-02-01",
+            	type: "1",
+	    	},
+	    	{
+	    		id: "101",
+	    		name: "商品名称2",
+            	weight: "50",
+            	price: "10.8",
+            	date: "2021-02-01",
+            	type: "0",
+	    	}];
+		    var options = {
+		    	data: data,
+                pagination: false,
+		        showSearch: false,
+                showRefresh: false,
+                showToggle: false,
+                showColumns: false,
+                sidePagination: "client",
+		        columns: [{
+		            checkbox: true
+		        },
+		        {
+		        	field: 'index',
+		        	align: 'center',
+		        	title: "序号",
+                    formatter: function (value, row, index) {
+                    	var columnIndex = $.common.sprintf("<input type='hidden' name='index' value='%s'>", $.table.serialNumber(index));
+                    	var columnId = $.common.sprintf("<input type='hidden' name='goods[%s].id' value='%s'>", index, row.id);
+                    	return columnIndex + $.table.serialNumber(index) + columnId;
+                    }
+                },
+		        {
+		            field: 'name',
+		            align: 'center',
+		            title: '商品名称',
+		            formatter: function(value, row, index) {
+		            	var html = $.common.sprintf("<input class='form-control goodsName' type='text' name='goods[%s].name' value='%s'>", index, value);
+		        		return html;
+                    }
+		        },
+		        {
+		            field: 'weight',
+		            align: 'center',
+		            title: '商品重量',
+		            formatter: function(value, row, index) {
+		            	var html = $.common.sprintf("<input class='form-control goodsWeight' type='text' name='goods[%s].weight' value='%s'>", index, value);
+		        		return html;
+                    }
+		        },
+		        {
+		            field: 'date',
+		            align: 'center',
+		            title: '商品日期',
+		            formatter: function(value, row, index) {
+		            	var html = $.common.sprintf("<input class='form-control' type='text' name='goods[%s].date' value='%s' placeholder='yyyy-MM-dd'>", index, value);
+		        		return html;
+                    }
+		        },
+		        {
+		            field: 'price',
+		            align: 'center',
+		            title: '商品价格',
+		            formatter: function(value, row, index) {
+		            	var html = $.common.sprintf("<input class='form-control' type='text' name='goods[%s].price' value='%s'>", index, value);
+		        		return html;
+                    }
+		        },
+		        {
+		            field: 'type',
+		            align: 'center',
+		            title: '商品种类',
+		            formatter: function(value, row, index) {
+		        		var data = [{ index: index, type: value }];
+		                return $("#goodsTypeTpl").tmpl(data).html();
+                    }
+		        },
+		        {
+                    title: '操作',
+                    align: 'center',
+                    formatter: function(value, row, index) {
+                    	var value = $.common.isNotEmpty(row.index) ? row.index : $.table.serialNumber(index);
+                        return '<a class="btn btn-danger btn-xs" href="javascript:void(0)" onclick="sub.delRowByIndex(\'' + value + '\')"><i class="fa fa-remove"></i>删除</a>';
+                    }
+                }]
+		    };
+		    $.table.init(options);
+		});
+	    
+        $.validator.addMethod("goodsName", function(value, element) {
+            return !this.optional(element);
+        }, "商品名称必填。");
+        
+        $.validator.addMethod("goodsWeight", function(value, element) {
+            return !this.optional(element) && (value <= 100 && value >= 0);
+        }, "商品重量长度区间0-100。");
+        
+        /* 主子表-提交 */
+        function submitHandler(index, layero){
+            if ($.validate.form()) {
+                var data = $("#form-add").serializeArray();
+                alert(JSON.stringify(data))
+                $.operate.saveModal("/demo/operate/customer/add", data);
+            }
+        }
+	    
+        $("input[name='birthday']").datetimepicker({
+            format: "yyyy-mm-dd",
+            minView: "month",
+            autoclose: true
+        });
+        
+        function addRow() {
+        	var count = $("#" + table.options.id).bootstrapTable('getData').length;
+        	var row = {
+                index: $.table.serialNumber(count),
+            	name: "",
+            	weight: "",
+            	price: "",
+            	date: "",
+            	type: "",
+            }
+        	sub.addRow(row);
+        }
+        
+        $("#bootstrap-table").on("post-body.bs.table", function (e, args) {
+        	$("input[name$='date']").datetimepicker({
+	            format: "yyyy-mm-dd",
+	            minView: "month",
+	            autoclose: true,
+	            pickerPosition:'top-right'
+	        });
+    	});
+    </script>
+</body>
+</html>
+
+<!-- 商品类型 -->
+<script id="goodsTypeTpl" type="text/x-jquery-tmpl">
+<div>
+<select class='form-control' name='goods[${index}].type'>
+    <option value="">所有</option>
+    <option value="0" {{if type==="0"}}selected{{/if}}>寒性</option>
+    <option value="1" {{if type==="1"}}selected{{/if}}>热性</option>
+</select>
+</div>
+</script>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/demo/table/textSearch.html b/ruoyi-admin/src/main/resources/templates/demo/table/textSearch.html
new file mode 100644
index 0000000..8457e61
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/table/textSearch.html
@@ -0,0 +1,112 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('全文搜索')" />
+</head>
+<body class="gray-bg">
+     <div class="container-div">
+		<div class="row">
+			<div class="col-sm-12 select-table table-striped">
+				<table id="bootstrap-table" data-page-size="10" data-search-align="left"
+				       data-show-custom-view="true" data-custom-view="customViewFormatter"
+                       data-custom-view-default-view="true">
+                </table>
+			</div>
+		</div>
+	</div>
+	
+    <template id="textSearchTemplate">
+        <div class="col-sm-12">
+            <p style="margin-top:10px;line-height:1.5;">
+             <span style="color:blue;font-size:medium">%title%</span><br>
+             <span style="color:#000000;font-size:medium">%content%</span><br>
+             <span style="color:#008000;font-size:medium">
+                                        档号:<a href="javascript:void(0)" onclick="handleView('%tableId%', '%archiveNo%')">%archiveNo%</a>
+               &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;%docNo%
+              </span>
+            </p>
+        </div>
+    </template>
+
+    <div th:include="include :: footer"></div>
+    <th:block th:include="include :: bootstrap-table-custom-view-js" />
+    <script th:inline="javascript">
+        var prefix = ctx + "demo/table";
+
+        $(function() {
+            var options = {
+                url: prefix + "/text/list",
+                search: true,
+		        showSearch: false,
+		        showRefresh: false,
+		        showToggle: false,
+		        showColumns: false,
+		        showExport: true,
+                columns: [{
+		            checkbox: true
+		        },
+		        {
+					field : 'tableId', 
+					title : '编号',
+					visible: false
+				},
+		        {
+					field : 'archiveNo', 
+					title : '档号'
+				},
+				{
+					field : 'docNo', 
+					title : '文件编号'
+				},
+				{
+					field : 'title', 
+					title : '标题',
+					formatter: function(value, row, index) {
+                        return $.table.tooltip(value, 20, "open");
+                    }
+				},
+				{
+					field : 'content', 
+					title : '内容',
+					formatter: function(value, row, index) {
+                        return $.table.tooltip(value, 30, "open");
+                    }
+				}]
+            };
+            $.table.init(options);
+        });
+        
+        function customViewFormatter (data) {
+            var template = $('#textSearchTemplate').html()
+            var view = ''
+	        if(data.length > 0) {
+	            $.each(data, function (i, row) {
+	                view += template.replace('%tableId%', row.tableId)
+	                .replaceAll('%archiveNo%', row.archiveNo)
+	                .replace('%title%', row.title)
+	                .replace('%docNo%', row.docNo)
+	                .replace('%content%', truncateString(row.content, 500))
+	            })
+	            return `<div class="row mx-0">${view}</div>`;
+            } else {
+                return `<div class="row mx-0"><div class="col-sm-12"><p style="margin-top:10px;line-height:1.5;"><span style="font-size:medium">没有找到记录。请检查过滤条件。</span></p></div></div>`
+            }
+          }
+        
+        function handleView(tableId, archiveNo) {
+        	alert("tableId:" + tableId + ",archiveNo:" + archiveNo);
+        }
+        
+        function truncateString(str, maxLength) {
+       	    if (str.length > maxLength) {
+       	        return str.slice(0, maxLength) + '...';
+       	    }
+       	    return str;
+       	}
+        
+        $(document).ready(function() {
+            $('.search-input').css('width', '320px');
+        });
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/demo/table/virtualScroll.html b/ruoyi-admin/src/main/resources/templates/demo/table/virtualScroll.html
new file mode 100644
index 0000000..5c0fa83
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/demo/table/virtualScroll.html
@@ -0,0 +1,98 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('表格虚拟滚动')" />
+</head>
+<body class="gray-bg">
+     <div class="container-div">
+        <div class="btn-group-sm" id="toolbar" role="group">
+	        <a class="btn btn-success" onclick="loadRows()">
+	            <i class="fa fa-plus"></i> 加载10000行数据
+	        </a>
+	        <a class="btn btn-info" onclick="appendRows()">
+	            <i class="fa fa-edit"></i> 追加10000行数据
+	        </a>
+	        &nbsp;&nbsp;<span id="total" class="badge badge-success"></span>
+        </div>
+        <div class="row">
+			<div class="col-sm-12 select-table table-striped">
+				<table id="bootstrap-table"></table>
+			</div>
+		</div>
+	</div>
+    <div th:include="include :: footer"></div>
+    <script>
+        var total = 0
+
+        $(function() {
+		    var options = {
+	    		data: getData(20),
+	    		height: 400,
+		        sidePagination: "client",
+		        pagination: false,
+		        showSearch: false,
+		        virtualScroll: true,
+                columns: [{
+					field : 'userId', 
+					title : '用户ID'
+				},
+				{
+					field : 'userCode', 
+					title : '用户编号'
+				},
+				{
+					field : 'userName', 
+					title : '用户姓名'
+				},
+				{
+					field : 'userPhone', 
+					title : '用户手机'
+				},
+				{
+					field : 'userEmail', 
+					title : '用户邮箱'
+				},
+				{
+				    field : 'userBalance',
+				    title : '用户余额'
+				}]
+		    };
+		    $.table.init(options);
+		});
+
+        function getData(number, isAppend) {
+            if (!isAppend) {
+                total = 0
+            }
+            var data = []
+            for (var i = total; i < total + number; i++) {
+                var randomId = 100 + ~~ (Math.random() * 100);
+                data.push({
+                    userId: i + 1,
+                    userCode: 2000000 + randomId,
+                    userName: '测试' + randomId,
+                    userPhone: '1588888888',
+                    userEmail: 'ry1@qq.com',
+                    userBalance: 10 + randomId,
+                })
+            }
+            if (isAppend) {
+                total += number
+            } else {
+                total = number
+            }
+            $('#total').text(total);
+            return data;
+        }
+
+        function loadRows() {
+            $('#bootstrap-table').bootstrapTable('load', getData(10000))
+        }
+
+        function appendRows() {
+            $('#bootstrap-table').bootstrapTable('append', getData(10000, true))
+        }
+</script>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/error/404.html b/ruoyi-admin/src/main/resources/templates/error/404.html
new file mode 100644
index 0000000..8c41e27
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/error/404.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html lang="zh">
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>RuoYi - 404</title>
+    <link th:href="@{/css/bootstrap.min.css}" rel="stylesheet"/>
+    <link th:href="@{/css/animate.min.css}" rel="stylesheet"/>
+    <link th:href="@{/css/style.min.css}" rel="stylesheet"/>
+</head>
+<body class="gray-bg">
+    <div class="middle-box text-center animated fadeInDown">
+        <h1>404</h1>
+        <h3 class="font-bold">找不到网页!</h3>
+        <div class="error-desc">
+                                对不起,您正在寻找的页面不存在。尝试检查URL的错误,然后按浏览器上的刷新按钮或尝试在我们的应用程序中找到其他内容。
+            <a href="javascript:index()" class="btn btn-primary m-t">主页</a>
+        </div>
+    </div>
+    <script th:inline="javascript">
+      var ctx = [[@{/}]];
+      function index() {
+    	  window.top.location = ctx + "index";
+      }
+    </script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/error/500.html b/ruoyi-admin/src/main/resources/templates/error/500.html
new file mode 100644
index 0000000..918e965
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/error/500.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html lang="zh">
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>RuoYi - 500</title>
+	<link th:href="@{/css/bootstrap.min.css}" rel="stylesheet"/>
+    <link th:href="@{/css/animate.min.css}" rel="stylesheet"/>
+    <link th:href="@{/css/style.min.css}" rel="stylesheet"/>
+</head>
+<body class="gray-bg">
+    <div class="middle-box text-center animated fadeInDown">
+        <h1>500</h1>
+        <h3 class="font-bold">内部服务器错误!</h3>
+
+        <div class="error-desc">
+                                服务器遇到意外事件,不允许完成请求。我们抱歉。您可以返回主页面。
+            <a href="javascript:index()" class="btn btn-primary m-t">主页</a>
+        </div>
+    </div>
+    <script th:inline="javascript">
+      var ctx = [[@{/}]];
+      function index() {
+    	  window.top.location = ctx + "index";
+      }
+    </script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/error/service.html b/ruoyi-admin/src/main/resources/templates/error/service.html
new file mode 100644
index 0000000..b64341d
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/error/service.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html lang="zh">
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>RuoYi - 500</title>
+	<link th:href="@{/css/bootstrap.min.css}" rel="stylesheet"/>
+    <link th:href="@{/css/animate.min.css}" rel="stylesheet"/>
+    <link th:href="@{/css/style.min.css}" rel="stylesheet"/>
+</head>
+<body class="gray-bg">
+    <div class="middle-box text-center animated fadeInDown">
+        <h3 class="font-bold">操作异常!</h3>
+
+        <div class="error-desc">
+            [[${errorMessage}]]
+        </div>
+    </div>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/error/unauth.html b/ruoyi-admin/src/main/resources/templates/error/unauth.html
new file mode 100644
index 0000000..74053c7
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/error/unauth.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html lang="zh">
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>RuoYi - 403</title>
+	<link th:href="@{/css/bootstrap.min.css}" rel="stylesheet"/>
+    <link th:href="@{/css/animate.min.css}" rel="stylesheet"/>
+    <link th:href="@{/css/style.min.css}" rel="stylesheet"/>
+</head>
+<body class="gray-bg">
+    <div class="middle-box text-center animated fadeInDown">
+        <h1>403</h1>
+        <h3 class="font-bold">您没有访问权限!</h3>
+
+        <div class="error-desc">
+                                对不起,您没有访问权限,请不要进行非法操作!您可以返回主页面
+            <a href="javascript:index()" class="btn btn-outline btn-primary btn-xs">返回主页</a>
+        </div>
+    </div>
+    <script th:inline="javascript">
+      var ctx = [[@{/}]];
+      function index() {
+    	  window.top.location = ctx + "index";
+      }
+    </script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/include.html b/ruoyi-admin/src/main/resources/templates/include.html
new file mode 100644
index 0000000..12c0573
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/include.html
@@ -0,0 +1,227 @@
+<!-- 通用CSS -->
+<head th:fragment=header(title)>
+	<meta charset="utf-8">
+	<meta name="viewport" content="width=device-width, initial-scale=1.0">
+	<meta http-equiv="X-UA-Compatible" content="IE=edge">
+	<meta name="keywords" content="">
+	<meta name="description" content="">
+	<title th:text="${title}"></title>
+	<link th:href="@{/css/bootstrap.min.css?v=3.3.7}" rel="stylesheet"/>
+	<link th:href="@{/css/font-awesome.min.css?v=4.7.0}" rel="stylesheet"/>
+	<!-- bootstrap-table 表格插件样式 -->
+	<link th:href="@{/ajax/libs/bootstrap-table/bootstrap-table.min.css?v=1.22.6}" rel="stylesheet"/>
+	<link th:href="@{/css/animate.min.css?v=20210831}" rel="stylesheet"/>
+	<link th:href="@{/css/style.min.css?v=20210831}" rel="stylesheet"/>
+	<link th:href="@{/ruoyi/css/ry-ui.css?v=4.8.0}" rel="stylesheet"/>
+</head>
+
+<!-- 通用JS -->
+<div th:fragment="footer">
+    <script th:inline="javascript"> var ctx = [[@{/}]]; var lockscreen = [[${session.lockscreen}]]; if(lockscreen){window.top.location=ctx+"lockscreen";} </script>
+    <a id="scroll-up" href="javascript:;" class="btn btn-sm display"><i class="fa fa-angle-double-up"></i></a>
+	<script th:src="@{/js/jquery.min.js?v=3.6.3}"></script>
+	<script th:src="@{/js/bootstrap.min.js?v=3.3.7}"></script>
+	<!-- bootstrap-table 表格插件 -->
+	<script th:src="@{/ajax/libs/bootstrap-table/bootstrap-table.min.js?v=1.22.6}"></script>
+	<script th:src="@{/ajax/libs/bootstrap-table/locale/bootstrap-table-zh-CN.min.js?v=1.22.6}"></script>
+	<script th:src="@{/ajax/libs/bootstrap-table/extensions/mobile/bootstrap-table-mobile.js?v=1.22.6}"></script>
+	<!-- jquery-validate 表单验证插件 -->
+	<script th:src="@{/ajax/libs/validate/jquery.validate.min.js?v=1.21.0}"></script>
+	<script th:src="@{/ajax/libs/validate/jquery.validate.extend.js?v=1.21.0}"></script>
+	<script th:src="@{/ajax/libs/validate/messages_zh.js?v=1.21.0}"></script>
+	<!-- bootstrap-table 表格树插件 -->
+	<script th:src="@{/ajax/libs/bootstrap-table/extensions/tree/bootstrap-table-tree.min.js?v=1.22.6}"></script>
+	<!-- 遮罩层 -->
+	<script th:src="@{/ajax/libs/blockUI/jquery.blockUI.js?v=2.70.0}"></script>
+    <script th:src="@{/ajax/libs/iCheck/icheck.min.js?v=1.0.3}"></script>
+	<script th:src="@{/ajax/libs/layer/layer.min.js?v=3.7.0}"></script>
+	<script th:src="@{/ajax/libs/layui/layui.min.js?v=2.8.18}"></script>
+	<script th:src="@{/ruoyi/js/common.js?v=4.8.0}"></script>
+	<script th:src="@{/ruoyi/js/ry-ui.js?v=4.8.0}"></script>
+</div>
+
+<!-- ztree树插件 -->
+<div th:fragment="ztree-css">
+    <link th:href="@{/ajax/libs/jquery-ztree/3.5/css/metro/zTreeStyle.css}" rel="stylesheet"/>
+</div>
+<div th:fragment="ztree-js">
+    <script th:src="@{/ajax/libs/jquery-ztree/3.5/js/jquery.ztree.all-3.5.js}"></script>
+</div>
+
+<!-- select2下拉框插件 -->
+<div th:fragment="select2-css">
+    <link th:href="@{/ajax/libs/select2/select2.min.css?v=4.0.13}" rel="stylesheet"/>
+    <link th:href="@{/ajax/libs/select2/select2-bootstrap.min.css?v=4.0.13}" rel="stylesheet"/>
+</div>
+<div th:fragment="select2-js">
+    <script th:src="@{/ajax/libs/select2/select2.min.js?v=4.0.13}"></script>
+</div>
+
+<!-- bootstrap-select下拉框插件 -->
+<div th:fragment="bootstrap-select-css">
+    <link th:href="@{/ajax/libs/bootstrap-select/bootstrap-select.min.css?v=1.13.18}" rel="stylesheet"/>
+</div>
+<div th:fragment="bootstrap-select-js">
+    <script th:src="@{/ajax/libs/bootstrap-select/bootstrap-select.min.js?v=1.13.18}"></script>
+</div>
+
+<!-- datetimepicker日期和时间插件 -->
+<div th:fragment="datetimepicker-css">
+    <link th:href="@{/ajax/libs/datapicker/bootstrap-datetimepicker.min.css?v=2.4.4}" rel="stylesheet"/>
+</div>
+<div th:fragment="datetimepicker-js">
+    <script th:src="@{/ajax/libs/datapicker/bootstrap-datetimepicker.min.js?v=2.4.4}"></script>
+</div>
+
+<!-- ui布局插件 -->
+<div th:fragment="layout-latest-css">
+    <link th:href="@{/ajax/libs/jquery-layout/jquery.layout-latest.css?v=1.4.4}" rel="stylesheet"/>
+</div>
+<div th:fragment="layout-latest-js">
+    <script th:src="@{/ajax/libs/jquery-layout/jquery.layout-latest.js?v=1.4.4}"></script>
+</div>
+
+<!-- summernote富文本编辑器插件 -->
+<div th:fragment="summernote-css">
+    <link th:href="@{/ajax/libs/summernote/summernote.css?v=0.8.18}" rel="stylesheet"/>
+</div>
+<div th:fragment="summernote-js">
+    <script th:src="@{/ajax/libs/summernote/summernote.min.js?v=0.8.18}"></script>
+	<script th:src="@{/ajax/libs/summernote/summernote-zh-CN.js?v=0.8.18}"></script>
+</div>
+
+<!-- cropper图像裁剪插件 -->
+<div th:fragment="cropper-css">
+    <link th:href="@{/ajax/libs/cropper/cropper.min.css?v=1.5.12}" rel="stylesheet"/>
+</div>
+<div th:fragment="cropper-js">
+    <script th:src="@{/ajax/libs/cropper/cropper.min.js?v=1.5.12}"></script>
+</div>
+
+<!-- jasny功能扩展插件 -->
+<div th:fragment="jasny-bootstrap-css">
+    <link th:href="@{/ajax/libs/jasny/jasny-bootstrap.min.css?v=3.1.3}" rel="stylesheet"/>
+</div>
+<div th:fragment="jasny-bootstrap-js">
+    <script th:src="@{/ajax/libs/jasny/jasny-bootstrap.min.js?v=3.1.3}"></script>
+</div>
+
+<!-- fileinput文件上传插件 -->
+<div th:fragment="bootstrap-fileinput-css">
+    <link th:href="@{/ajax/libs/bootstrap-fileinput/fileinput.min.css?v=5.5.2}" rel="stylesheet"/>
+</div>
+<div th:fragment="bootstrap-fileinput-js">
+    <script th:src="@{/ajax/libs/bootstrap-fileinput/fileinput.min.js?v=5.5.2}"></script>
+</div>
+
+<!-- duallistbox双列表框插件 -->
+<div th:fragment="bootstrap-duallistbox-css">
+    <link th:href="@{/ajax/libs/duallistbox/bootstrap-duallistbox.min.css?v=3.0.9}" rel="stylesheet"/>
+</div>
+<div th:fragment="bootstrap-duallistbox-js">
+    <script th:src="@{/ajax/libs/duallistbox/bootstrap-duallistbox.min.js?v=3.0.9}"></script>
+</div>
+
+<!-- suggest搜索自动补全 -->
+<div th:fragment="bootstrap-suggest-js">
+    <script th:src="@{/ajax/libs/suggest/bootstrap-suggest.min.js?v=0.1.29}"></script>
+</div>
+
+<!-- typeahead搜索自动补全 -->
+<div th:fragment="bootstrap-typeahead-js">
+    <script th:src="@{/ajax/libs/typeahead/bootstrap-typeahead.min.js?v=4.0.2}"></script>
+</div>
+
+<!-- 多级联动下拉 -->
+<div th:fragment="jquery-cxselect-js">
+    <script th:src="@{/ajax/libs/cxselect/jquery.cxselect.min.js?v=1.4.2}"></script>
+</div>
+
+<!-- jsonview格式化和语法高亮JSON格式数据查看插件 -->
+<div th:fragment="jsonview-css">
+    <link th:href="@{/ajax/libs/jsonview/jquery.jsonview.css?v=1.2.0}" rel="stylesheet"/>
+</div>
+<div th:fragment="jsonview-js">
+    <script th:src="@{/ajax/libs/jsonview/jquery.jsonview.js?v=1.2.0}"></script>
+</div>
+
+<!-- jquery.smartwizard表单向导插件 -->
+<div th:fragment="jquery-smartwizard-css">
+    <link th:href="@{/ajax/libs/smartwizard/smart_wizard_all.min.css?v=5.1.1}" rel="stylesheet"/>
+</div>
+<div th:fragment="jquery-smartwizard-js">
+    <script th:src="@{/ajax/libs/smartwizard/jquery.smartWizard.min.js?v=5.1.1}"></script>
+</div>
+
+<!-- ECharts百度统计图表插件 -->
+<div th:fragment="echarts-js">
+    <script th:src="@{/ajax/libs/report/echarts/echarts-all.min.js?v=4.2.1}"></script>
+</div>
+
+<!-- peity图表组合插件 -->
+<div th:fragment="peity-js">
+    <script th:src="@{/ajax/libs/report/peity/jquery.peity.min.js?v=2.0.3}"></script>
+</div>
+
+<!-- sparkline线状图插件 -->
+<div th:fragment="sparkline-js">
+    <script th:src="@{/ajax/libs/report/sparkline/jquery.sparkline.min.js?v=2.1.2}"></script>
+</div>
+
+<!-- 表格行拖拽插件 -->
+<div th:fragment="bootstrap-table-reorder-rows-js">
+	<script th:src="@{/ajax/libs/bootstrap-table/extensions/reorder-rows/bootstrap-table-reorder-rows.js?v=1.22.6}"></script>
+	<script th:src="@{/ajax/libs/bootstrap-table/extensions/reorder-rows/jquery.tablednd.js?v=1.0.3}"></script>
+</div>
+
+<!-- 表格列拖拽插件 -->
+<div th:fragment="bootstrap-table-reorder-columns-js">
+	<script th:src="@{/ajax/libs/bootstrap-table/extensions/reorder-columns/jquery.dragtable.js?v=5.3.5}"></script>
+	<script th:src="@{/ajax/libs/bootstrap-table/extensions/reorder-columns/bootstrap-table-reorder-columns.js?v=1.22.6}"></script>
+</div>
+
+<!-- 表格列宽拖动插件 -->
+<div th:fragment="bootstrap-table-resizable-js">
+	<script th:src="@{/ajax/libs/bootstrap-table/extensions/resizable/jquery.resizableColumns.min.js?v=0.1.0}"></script>
+    <script th:src="@{/ajax/libs/bootstrap-table/extensions/resizable/bootstrap-table-resizable.js?v=1.22.6}"></script>
+</div>
+
+<!-- 表格行内编辑插件 -->
+<div th:fragment="bootstrap-editable-css">
+    <link th:href="@{/ajax/libs/bootstrap-table/extensions/editable/bootstrap-editable.css?v=1.5.1}" rel="stylesheet"/>
+</div>
+<div th:fragment="bootstrap-table-editable-js">
+	<script th:src="@{/ajax/libs/bootstrap-table/extensions/editable/bootstrap-editable.min.js?v=1.5.1}"></script>
+    <script th:src="@{/ajax/libs/bootstrap-table/extensions/editable/bootstrap-table-editable.js?v=1.22.6}"></script>
+</div>
+
+<!-- 表格导出插件 -->
+<div th:fragment="bootstrap-table-export-js">
+	<script th:src="@{/ajax/libs/bootstrap-table/extensions/export/bootstrap-table-export.js?v=1.22.6}"></script>
+	<script th:src="@{/ajax/libs/bootstrap-table/extensions/export/tableExport.min.js?v=1.10.24}"></script>
+</div>
+
+<!-- 表格冻结列插件 -->
+<div th:fragment="bootstrap-table-fixed-columns-js">
+	<script th:src="@{/ajax/libs/bootstrap-table/extensions/columns/bootstrap-table-fixed-columns.js?v=1.22.6}"></script>
+</div>
+
+<!-- 表格自动刷新插件 -->
+<div th:fragment="bootstrap-table-auto-refresh-js">
+	<script th:src="@{/ajax/libs/bootstrap-table/extensions/auto-refresh/bootstrap-table-auto-refresh.js?v=1.22.6}"></script>
+</div>
+
+<!-- 表格打印插件 -->
+<div th:fragment="bootstrap-table-print-js">
+	<script th:src="@{/ajax/libs/bootstrap-table/extensions/print/bootstrap-table-print.js?v=1.22.6}"></script>
+</div>
+
+<!-- 表格视图分页插件 -->
+<div th:fragment="bootstrap-table-custom-view-js">
+	<script th:src="@{/ajax/libs/bootstrap-table/extensions/custom-view/bootstrap-table-custom-view.js?v=1.22.6}"></script>
+</div>
+
+<!-- 表格保存状态插件 -->
+<div th:fragment="bootstrap-table-cookie-js">
+	<script th:src="@{/ajax/libs/bootstrap-table/extensions/cookie/bootstrap-table-cookie.js?v=1.22.6}"></script>
+</div>
diff --git a/ruoyi-admin/src/main/resources/templates/index-topnav.html b/ruoyi-admin/src/main/resources/templates/index-topnav.html
new file mode 100644
index 0000000..74ecb15
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/index-topnav.html
@@ -0,0 +1,450 @@
+<!DOCTYPE html>
+<html  lang="zh" xmlns:th="http://www.thymeleaf.org">
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta name="renderer" content="webkit">
+    <title>若依系统首页</title>
+    <!-- 避免IE使用兼容模式 -->
+ 	<meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <link th:href="@{favicon.ico}" rel="shortcut icon"/>
+    <link th:href="@{/css/bootstrap.min.css}" rel="stylesheet"/>
+    <link th:href="@{/css/jquery.contextMenu.min.css}" rel="stylesheet"/>
+    <link th:href="@{/css/font-awesome.min.css}" rel="stylesheet"/>
+    <link th:href="@{/css/animate.min.css}" rel="stylesheet"/>
+    <link th:href="@{/css/style.min.css}" rel="stylesheet"/>
+    <link th:href="@{/css/skins.css?v=20200902}" rel="stylesheet"/>
+    <link th:href="@{/ruoyi/css/ry-ui.css?v=4.8.0}" rel="stylesheet"/>
+    <style type="text/css">.fixed-sidebar .nav:not(.navbar-toolbar)>li.active{border-left:0px!important;}</style>
+</head>
+<body class="fixed-sidebar full-height-layout gray-bg" th:classappend="${isMobile} ? 'canvas-menu'" style="overflow: hidden">
+<div id="wrapper">
+
+    <!--左侧导航开始-->
+    <nav class="navbar-default navbar-static-side" role="navigation">
+        <div class="nav-close">
+            <i class="fa fa-times-circle"></i>
+        </div>
+        <a th:href="@{/index}">
+            <li class="logo hidden-xs">
+                <span class="logo-lg">RuoYi</span>
+            </li>
+         </a>
+        <div class="sidebar-collapse tab-content" id="side-menu">
+			<div class="user-panel">
+				<a class="menuItem noactive" title="个人中心" th:href="@{/system/user/profile}">
+					<div class="hide" th:text="个人中心"></div>
+					<div class="pull-left image">
+						<img th:src="(${#strings.isEmpty(user.avatar)}) ? @{/img/profile.jpg} : @{${user.avatar}}" th:onerror="this.src='img/profile.jpg'" class="img-circle" alt="User Image">
+					</div>
+				</a>
+				<div class="pull-left info">
+				  <p>[[${user.loginName}]]</p>
+				  <a href="javascript:;"><i class="fa fa-circle text-success"></i> 在线</a>
+				  <a th:href="@{logout}" style="padding-left:5px;"><i class="fa fa-sign-out text-danger"></i> 注销</a>
+				</div>
+			</div>
+			
+            <!-- 左侧菜单 -->
+			<th:block th:each="menu : ${menus}">
+			<div class="tab-pane fade height-full" th:id="|menu_${menu.menuId}|">
+			  <ul class="nav">
+                <li th:each="cmenu : ${menu.children}">
+			      <a class="menu-content" th:if="${#lists.isEmpty(cmenu.children)}" th:href="@{${cmenu.url}}" th:classappend="${#strings.isEmpty(cmenu.target)} ? |menuItem| : ${cmenu.target}" th:data-refresh="${cmenu.isRefresh == '0'}">
+			        <i th:class="${cmenu.icon} + ' fa-fw'"></i> <span class="nav-label">[[${cmenu.menuName}]]</span>
+			      </a>
+			      <a class="menu-content" th:if="${not #lists.isEmpty(cmenu.children)}" href="javascript:;">
+			        <i th:class="${cmenu.icon} + ' fa-fw'"></i>
+			        <span class="nav-label">[[${cmenu.menuName}]]</span>
+			        <span class="fa arrow"></span>
+                  </a>
+				  <ul th:if="${not #lists.isEmpty(cmenu.children)}" class="nav nav-second-level collapse">
+				    <li th:each="emenu : ${cmenu.children}">
+				      <a th:if="${#lists.isEmpty(emenu.children)}" th:href="@{${emenu.url}}" th:class="${#strings.isEmpty(emenu.target)} ? |menuItem| : ${emenu.target}" th:data-refresh="${emenu.isRefresh == '0'}">
+				        <i th:class="${emenu.icon} + ' fa-fw'"></i> 
+				        [[${emenu.menuName}]]
+				      </a>
+				      <a th:if="${not #lists.isEmpty(emenu.children)}" href="javascript:;">
+				        <i th:class="${emenu.icon} + ' fa-fw'"></i> 
+				        [[${emenu.menuName}]]
+				        <span class="fa arrow"></span>
+				      </a>
+				      <ul th:if="${not #lists.isEmpty(emenu.children)}" class="nav nav-third-level collapse">
+				        <li th:each="fmenu : ${emenu.children}"><a th:if="${#lists.isEmpty(fmenu.children)}" th:class="${#strings.isEmpty(fmenu.target)} ? |menuItem| : ${fmenu.target}" th:href="@{${fmenu.url}}" th:data-refresh="${fmenu.isRefresh == '0'}">[[${fmenu.menuName}]]</a></li>
+				      </ul>
+				    </li>
+				  </ul>
+                </li>
+			  </ul>
+			</div>
+			</th:block>
+			
+			<!-- 首页菜单 -->
+			<div class="tab-pane fade height-full" id="index">
+			  <ul class="nav">
+			    <li>
+			      <a class="menuItem" th:href="@{/system/main}">
+			      <i class="fa fa-home"></i> <span class="nav-label">首页</span></a>
+			    </li>
+			  </ul>
+			</div>
+			
+            <!-- 实例演示菜单 -->
+			<div class="tab-pane fade height-full" id="demo" th:if="${demoEnabled}">
+			  <ul class="nav">
+			    <li>
+			      <a href="javascript:;"><i class="fa fa-edit"></i> <span class="nav-label">表单</span><span class="fa arrow"></span></a>
+			      <ul class="nav nav-second-level collapse">
+					<li><a class="menuItem" th:href="@{/demo/form/button}">按钮</a></li>
+					<li><a class="menuItem" th:href="@{/demo/form/grid}">栅格</a></li>
+					<li><a class="menuItem" th:href="@{/demo/form/select}">下拉框</a></li>
+					<li><a class="menuItem" th:href="@{/demo/form/timeline}">时间轴</a></li>
+					<li><a class="menuItem" th:href="@{/demo/form/progress_bars}">进度条</a></li>
+					<li><a class="menuItem" th:href="@{/demo/form/basic}">基本表单</a></li>
+					<li><a class="menuItem" th:href="@{/demo/form/cards}">卡片列表</a></li>
+					<li><a class="menuItem" th:href="@{/demo/form/jasny}">功能扩展</a></li>
+					<li><a class="menuItem" th:href="@{/demo/form/sortable}">拖动排序</a></li>
+					<li><a class="menuItem" th:href="@{/demo/form/invoice}">单据打印</a></li>
+					<li><a class="menuItem" th:href="@{/demo/form/labels_tips}">标签 & 提示</a></li>
+					<li><a class="menuItem" th:href="@{/demo/form/tabs_panels}">选项卡 & 面板</a></li>
+					<li><a class="menuItem" th:href="@{/demo/form/validate}">表单校验</a></li>
+					<li><a class="menuItem" th:href="@{/demo/form/wizard}">表单向导</a></li>
+					<li><a class="menuItem" th:href="@{/demo/form/upload}">文件上传</a></li>
+					<li><a class="menuItem" th:href="@{/demo/form/datetime}">日期和时间</a></li>
+					<li><a class="menuItem" th:href="@{/demo/form/summernote}">富文本编辑器</a></li>
+					<li><a class="menuItem" th:href="@{/demo/form/duallistbox}">左右互选组件</a></li>
+					<li><a class="menuItem" th:href="@{/demo/form/autocomplete}">搜索自动补全</a></li>
+					<li><a class="menuItem" th:href="@{/demo/form/cxselect}">多级联动下拉</a></li>
+					<li><a class="menuItem" th:href="@{/demo/form/localrefresh}">Ajax局部刷新</a></li>
+			      </ul>
+			    </li>
+			    <li>
+			      <a href="javascript:;"><i class="fa fa-table"></i> <span class="nav-label">表格</span><span class="fa arrow"></span></a>
+			      <ul class="nav nav-second-level collapse">
+					<li><a class="menuItem" th:href="@{/demo/table/search}">查询条件</a></li>
+					<li><a class="menuItem" th:href="@{/demo/table/footer}">数据汇总</a></li>
+					<li><a class="menuItem" th:href="@{/demo/table/groupHeader}">组合表头</a></li>
+					<li><a class="menuItem" th:href="@{/demo/table/export}">表格导出</a></li>
+					<li><a class="menuItem" th:href="@{/demo/table/textSearch}">全文索引</a></li>
+					<li><a class="menuItem" th:href="@{/demo/table/exportSelected}">导出选择列</a></li>
+					<li><a class="menuItem" th:href="@{/demo/table/remember}">翻页记住选择</a></li>
+					<li><a class="menuItem" th:href="@{/demo/table/cookie}">表格保存状态</a></li>
+					<li><a class="menuItem" th:href="@{/demo/table/pageGo}">跳转至指定页</a></li>
+					<li><a class="menuItem" th:href="@{/demo/table/params}">自定义查询参数</a></li>
+					<li><a class="menuItem" th:href="@{/demo/table/multi}">初始多表格</a></li>
+					<li><a class="menuItem" th:href="@{/demo/table/button}">点击按钮加载表格</a></li>
+					<li><a class="menuItem" th:href="@{/demo/table/data}">直接加载表格数据</a></li>
+					<li><a class="menuItem" th:href="@{/demo/table/fixedColumns}">表格冻结列</a></li>
+					<li><a class="menuItem" th:href="@{/demo/table/event}">自定义触发事件</a></li>
+					<li><a class="menuItem" th:href="@{/demo/table/headerStyle}">表格标题格式化</a></li>
+					<li><a class="menuItem" th:href="@{/demo/table/detail}">表格细节视图</a></li>
+					<li><a class="menuItem" th:href="@{/demo/table/child}">表格父子视图</a></li>
+					<li><a class="menuItem" th:href="@{/demo/table/image}">表格图片预览</a></li>
+					<li><a class="menuItem" th:href="@{/demo/table/curd}">动态增删改查</a></li>
+					<li><a class="menuItem" th:href="@{/demo/table/reorderRows}">表格行拖拽操作</a></li>
+					<li><a class="menuItem" th:href="@{/demo/table/reorderColumns}">表格列拖拽操作</a></li>
+					<li><a class="menuItem" th:href="@{/demo/table/resizable}">表格列宽拖动</a></li>
+					<li><a class="menuItem" th:href="@{/demo/table/editable}">表格行内编辑</a></li>
+					<li><a class="menuItem" th:href="@{/demo/table/subdata}">主子表提交</a></li>
+					<li><a class="menuItem" th:href="@{/demo/table/refresh}">表格自动刷新</a></li>
+					<li><a class="menuItem" th:href="@{/demo/table/print}">表格打印配置</a></li>
+					<li><a class="menuItem" th:href="@{/demo/table/dynamicColumns}">表格动态列</a></li>
+					<li><a class="menuItem" th:href="@{/demo/table/virtualScroll}">表格虚拟滚动</a></li>
+					<li><a class="menuItem" th:href="@{/demo/table/customView}">自定义视图分页</a></li>
+					<li><a class="menuItem" th:href="@{/demo/table/asynTree}">异步加载表格树</a></li>
+					<li><a class="menuItem" th:href="@{/demo/table/other}">表格其他操作</a></li>
+			      </ul>
+			    </li>
+			    <li>
+			      <a href="javascript:;"><i class="fa fa-flask"></i> <span class="nav-label">弹框</span><span class="fa arrow"></span></a>
+			      <ul class="nav nav-second-level collapse">
+					<li><a class="menuItem" th:href="@{/demo/modal/dialog}">模态窗口</a></li>
+					<li><a class="menuItem" th:href="@{/demo/modal/layer}">弹层组件</a></li>
+					<li><a class="menuItem" th:href="@{/demo/modal/table}">弹层表格</a></li>
+			      </ul>
+			    </li>
+			    <li>
+			      <a href="javascript:;"><i class="fa fa-wpforms"></i> <span class="nav-label">操作</span><span class="fa arrow"></span></a>
+			      <ul class="nav nav-second-level collapse">
+					<li><a class="menuItem" th:href="@{/demo/operate/table}">表格</a></li>
+					<li><a class="menuItem" th:href="@{/demo/operate/other}">其他</a></li>
+			      </ul>
+			    </li>
+			    <li>
+			      <a href="javascript:;"><i class="fa fa-bar-chart-o"></i> <span class="nav-label">报表</span><span class="fa arrow"></span></a>
+			      <ul class="nav nav-second-level collapse">
+					<li><a class="menuItem" th:href="@{/demo/report/echarts}">百度ECharts</a></li>
+					<li><a class="menuItem" th:href="@{/demo/report/peity}">peity</a></li>
+					<li><a class="menuItem" th:href="@{/demo/report/sparkline}">sparkline</a></li>
+					<li><a class="menuItem" th:href="@{/demo/report/metrics}">图表组合</a></li>
+			      </ul>
+			    </li>
+			    <li>
+			      <a href="javascript:;"><i class="fa fa-book"></i> <span class="nav-label">图标</span><span class="fa arrow"></span></a>
+			      <ul class="nav nav-second-level collapse">
+					<li><a class="menuItem" th:href="@{/demo/icon/fontawesome}">Font Awesome</a></li>
+					<li><a class="menuItem" th:href="@{/demo/icon/glyphicons}">Glyphicons</a></li>
+			      </ul>
+			    </li>
+			    <li>
+			      <a href="javascript:;"><i class="fa fa-navicon"></i> <span class="nav-label">四层菜单</span><span class="fa arrow"></span></a>
+			      <ul class="nav nav-second-level collapse">
+					<li>
+						<a href="javascript:;" id="damian">三级菜单1<span class="fa arrow"></span></a>
+						<ul class="nav nav-third-level collapse">
+							<li>
+								<a href="javascript:;">四级菜单1</a>
+							</li>
+							<li>
+								<a href="javascript:;">四级菜单2</a>
+							</li>
+						</ul>
+					</li>
+					<li><a href="javascript:;">三级菜单2</a></li>
+			      </ul>
+			    </li>
+			  </ul>
+			</div>
+        </div>
+    </nav>
+    <!--左侧导航结束-->
+
+    <!--右侧部分开始-->
+    <div id="page-wrapper" class="gray-bg dashbard-1">
+        <div class="row border-bottom">
+            <nav class="navbar navbar-static-top" role="navigation" style="margin-bottom: 0">
+                <div class="navbar-header">
+                    <a class="navbar-minimalize minimalize-styl-2" style="color:#FFF;" href="javascript:;" title="收起菜单">
+                    	<i class="fa fa-bars"></i>
+                    </a>
+                </div>
+                <!-- 顶部栏 -->
+                <div id="navMenu">
+                  <ul class="nav navbar-toolbar nav-tabs navbar-left hidden-xs">
+                    
+                    <!-- 顶部菜单列表 -->
+	                <th:block th:each="menu : ${menus}">
+               	    <li role="presentation" th:id="|tab_${menu.menuId}|">
+               	        <a th:if="${#lists.isEmpty(menu.children)}" data-toggle="tab" th:class="@{${!#strings.isEmpty(menu.target) && menu.target == 'menuBlank'} ? 'menuBlank' : 'menuItem noactive'}" th:href="@{${menu.url}}">
+                            <i th:class="${menu.icon}"></i> <span>[[${menu.menuName}]]</span>
+                        </a>	
+                        <a th:if="${not #lists.isEmpty(menu.children)}" data-toggle="tab" th:class="@{${!#strings.isEmpty(menu.target) && menu.target == 'menuBlank'} ? 'menuBlank'}" th:href="@{${!#strings.isEmpty(menu.target) && menu.target == 'menuBlank'} ? @{${menu.url}} : |#menu_${menu.menuId}|}">
+                            <i th:class="${menu.icon}"></i> <span>[[${menu.menuName}]]</span>
+                        </a>
+                    </li>
+	                </th:block>
+	                
+	                <li role="presentation" id="tab_index">
+                      <a data-toggle="tab" href="#index">
+                        <i class="fa fa-area-chart"></i> <span>统计报表</span>
+                      </a>
+                    </li>
+                    
+                    <li role="presentation" id="tab_demo" th:if="${demoEnabled}">
+                      <a data-toggle="tab" href="#demo">
+                        <i class="fa fa-desktop"></i> <span>实例演示</span>
+                      </a>
+                    </li>
+				  </ul>
+				</div>
+                <!-- 右侧栏 -->
+                <ul class="nav navbar-top-links navbar-right welcome-message">
+                    <li><a data-toggle="tooltip" data-trigger="hover" data-placement="bottom" title="开发文档" href="http://doc.ruoyi.vip/ruoyi" target="_blank"><i class="fa fa-question-circle"></i> 文档</a></li>
+                    <li><a data-toggle="tooltip" data-trigger="hover" data-placement="bottom" title="锁定屏幕" href="javascript:;" id="lockScreen"><i class="fa fa-lock"></i> 锁屏</a></li>
+	                <li><a data-toggle="tooltip" data-trigger="hover" data-placement="bottom" title="全屏显示" href="javascript:;" id="fullScreen"><i class="fa fa-arrows-alt"></i> 全屏</a></li>
+                
+                    <li class="dropdown user-menu">
+						<a href="javascript:void(0)" class="dropdown-toggle" data-hover="dropdown">
+							<img th:src="(${#strings.isEmpty(user.avatar)}) ? @{/img/profile.jpg} : @{${user.avatar}}" th:onerror="this.src='img/profile.jpg'" class="user-image">
+							<span class="hidden-xs">[[${#strings.defaultString(user.userName, '-')}]]</span>
+						</a>
+						<ul class="dropdown-menu">
+							<li class="mt5">
+								<a th:href="@{/system/user/profile}" class="menuItem noactive">
+								<i class="fa fa-user"></i> 个人中心</a>
+							</li>
+							<li>
+								<a onclick="resetPwd()">
+								<i class="fa fa-key"></i> 修改密码</a>
+							</li>
+							<li>
+								<a onclick="switchSkin()">
+								<i class="fa fa-dashboard"></i> 切换主题</a>
+							</li>
+							<li>
+								<a onclick="toggleMenu()">
+								<i class="fa fa-toggle-off"></i> 左侧菜单</a>
+							</li>
+							<li class="divider"></li>
+							<li>
+								<a th:href="@{logout}">
+								<i class="fa fa-sign-out"></i> 退出登录</a>
+							</li>
+						</ul>
+					</li>
+                </ul>
+            </nav>
+        </div>
+        <div class="row content-tabs" th:classappend="${#bools.isFalse(tagsView)} ? |hide|">
+            <button class="roll-nav roll-left tabLeft">
+                <i class="fa fa-backward"></i>
+            </button>
+            <nav class="page-tabs menuTabs">
+                <div class="page-tabs-content">
+                    <a href="javascript:;" class="active menuTab" th:data-id="@{/system/main}">首页</a>
+                </div>
+            </nav>
+            <button class="roll-nav roll-right tabRight">
+                <i class="fa fa-forward"></i>
+            </button>
+            <a href="javascript:void(0);" class="roll-nav roll-right tabReload"><i class="fa fa-refresh"></i> 刷新</a>
+        </div>
+
+        <a id="ax_close_max" class="ax_close_max" href="javascript:;" title="关闭全屏"> <i class="fa fa-times-circle-o"></i> </a>
+
+        <div class="row mainContent" id="content-main" th:classappend="${mainClass}">
+            <iframe class="RuoYi_iframe" name="iframe0" width="100%" height="100%" th:data-id="@{/system/main}"
+                th:src="@{/system/main}" frameborder="0" seamless></iframe>
+        </div>
+        
+        <div th:if="${footer}" class="footer">
+            <div class="pull-right">© [[${copyrightYear}]] RuoYi Copyright </div>
+        </div>
+    </div>
+    <!--右侧部分结束-->
+</div>
+<!-- 全局js -->
+<script th:src="@{/js/jquery.min.js}"></script>
+<script th:src="@{/js/bootstrap.min.js}"></script>
+<script th:src="@{/js/plugins/metisMenu/jquery.metisMenu.js}"></script>
+<script th:src="@{/js/plugins/slimscroll/jquery.slimscroll.min.js}"></script>
+<script th:src="@{/js/jquery.contextMenu.min.js}"></script>
+<script th:src="@{/ajax/libs/blockUI/jquery.blockUI.js}"></script>
+<script th:src="@{/ajax/libs/layer/layer.min.js}"></script>
+<script th:src="@{/ruoyi/js/ry-ui.js?v=4.8.0}"></script>
+<script th:src="@{/ruoyi/js/common.js?v=4.8.0}"></script>
+<script th:src="@{/ruoyi/index.js?v=20201208}"></script>
+<script th:src="@{/ajax/libs/fullscreen/jquery.fullscreen.js}"></script>
+<script th:src="@{/js/resize-tabs.js}"></script>
+<script th:inline="javascript">
+window.history.forward(1);
+var ctx = [[@{/}]]; 
+var lockscreen = [[${session.lockscreen}]]; 
+if(lockscreen){window.top.location=ctx+"lockscreen";}
+// 皮肤缓存
+var skin = storage.get("skin");
+// history(表示去掉地址的#)否则地址以"#"形式展示
+var mode = "history";
+// 历史访问路径缓存
+var historyPath = storage.get("historyPath");
+// 是否页签与菜单联动
+var isLinkage = true;
+// 是否页签切换滚动到顶部
+var isScrollToTop = true;
+
+// 本地主题优先,未设置取系统配置
+if($.common.isNotEmpty(skin)){
+	$("body").addClass(skin.split('|')[0]);
+	$("body").addClass(skin.split('|')[1]);
+} else {
+	$("body").addClass([[${sideTheme}]]);
+	$("body").addClass([[${skinName}]]);
+}
+
+/* 用户管理-重置密码 */
+function resetPwd() {
+    var url = ctx + 'system/user/profile/resetPwd';
+    $.modal.open("重置密码", url, '770', '380');
+}
+/* 切换主题 */
+function switchSkin() {
+    layer.open({
+		type : 2,
+		shadeClose : true,
+		title : "切换主题",
+		area : ["530px", "386px"],
+		content : [ctx + "system/switchSkin", 'no']
+	})
+}
+
+/* 切换菜单 */
+function toggleMenu() {
+	$.modal.confirm("确认要切换成左侧菜单吗?", function() {
+		$.get(ctx + 'system/menuStyle/default', function(result) {
+            window.location.reload();
+	    });
+	})
+}
+
+/** 刷新时访问路径页签 */
+function applyPath(url) {
+	var $dataObj = $('a[href$="' + decodeURI(url) + '"]');
+	$dataObj.click();
+	if (!$dataObj.hasClass("noactive")) {
+	    $dataObj.parent("li").addClass("selected").parents("li").addClass("active").end().parents("ul").addClass("in");
+	}
+	// 顶部菜单同步处理
+    var tabStr = $dataObj.parents(".tab-pane").attr("id");
+    if ($.common.isNotEmpty(tabStr)) {
+        var sepIndex = tabStr.lastIndexOf('_');
+        var menuId = tabStr.substring(sepIndex + 1, tabStr.length);
+        $("#tab_" + menuId + " a").click();
+    }
+}
+
+$(function() {
+	var lockPath = storage.get('lockPath');
+	if($.common.equals("history", mode) && window.performance.navigation.type == 1) {
+		var url = storage.get('publicPath');
+	    if ($.common.isNotEmpty(url)) {
+	    	applyPath(url);
+	    } else {
+	    	$(".navbar-toolbar li a").eq(0).click();
+	    }
+	} else if($.common.isNotEmpty(lockPath)) {
+	    applyPath(lockPath);
+	    storage.remove('lockPath');
+	} else {
+		var hash = location.hash;
+	    if ($.common.isNotEmpty(hash)) {
+	        var url = hash.substring(1, hash.length);
+	        applyPath(url);
+	    } else {
+	    	if($.common.equals("history", mode)) {
+	    		storage.set('publicPath', "");
+	    	}
+	    	$(".navbar-toolbar li a").eq(0).click();
+	    }
+	}
+	
+	/* 初始密码提示 */
+	if([[${isDefaultModifyPwd}]]) {
+		layer.confirm("您的密码还是初始密码,请修改密码!", {
+			icon: 0,
+			title: "安全提示",
+			btn: ['确认'	, '取消'],
+			offset: ['30%']
+		}, function (index) {
+			resetPwd();
+			layer.close(index);
+		});
+	}
+	
+	/* 过期密码提示 */
+	if([[${isPasswordExpired}]]) {
+		layer.confirm("您的密码已过期,请尽快修改密码!", {
+			icon: 0,
+			title: "安全提示",
+			btn: ['确认'	, '取消'],
+			offset: ['30%']
+		}, function (index) {
+			resetPwd();
+			layer.close(index);
+		});
+	}
+	
+	$("[data-toggle='tooltip']").tooltip();
+});
+</script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/index.html b/ruoyi-admin/src/main/resources/templates/index.html
new file mode 100644
index 0000000..cc50de8
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/index.html
@@ -0,0 +1,384 @@
+<!DOCTYPE html>
+<html  lang="zh" xmlns:th="http://www.thymeleaf.org">
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta name="renderer" content="webkit">
+    <title>若依系统首页</title>
+    <!-- 避免IE使用兼容模式 -->
+ 	<meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <link th:href="@{favicon.ico}" rel="shortcut icon"/>
+    <link th:href="@{/css/bootstrap.min.css}" rel="stylesheet"/>
+    <link th:href="@{/css/jquery.contextMenu.min.css}" rel="stylesheet"/>
+    <link th:href="@{/css/font-awesome.min.css}" rel="stylesheet"/>
+    <link th:href="@{/css/animate.min.css}" rel="stylesheet"/>
+    <link th:href="@{/css/style.min.css}" rel="stylesheet"/>
+    <link th:href="@{/css/skins.css}" rel="stylesheet"/>
+    <link th:href="@{/ruoyi/css/ry-ui.css?v=4.8.0}" rel="stylesheet"/>
+</head>
+<body class="fixed-sidebar full-height-layout gray-bg" th:classappend="${isMobile} ? 'canvas-menu'" style="overflow: hidden">
+<div id="wrapper">
+
+    <!--左侧导航开始-->
+    <nav class="navbar-default navbar-static-side" role="navigation">
+        <div class="nav-close">
+            <i class="fa fa-times-circle"></i>
+        </div>
+        <a th:href="@{/index}">
+            <li class="logo hidden-xs">
+                <span class="logo-lg">RuoYi</span>
+            </li>
+         </a>
+        <div class="sidebar-collapse">
+            <ul class="nav" id="side-menu">
+            	<li>
+            		<div class="user-panel">
+            			<a class="menuItem noactive" title="个人中心" th:href="@{/system/user/profile}">
+            				<div class="hide" th:text="个人中心"></div>
+					        <div class="pull-left image">
+		                    	<img th:src="(${#strings.isEmpty(user.avatar)}) ? @{/img/profile.jpg} : @{${user.avatar}}" th:onerror="this.src='img/profile.jpg'" class="img-circle" alt="User Image">
+					        </div>
+				        </a>
+				        <div class="pull-left info">
+				          <p>[[${user.loginName}]]</p>
+				          <a href="javascript:;"><i class="fa fa-circle text-success"></i> 在线</a>
+				          <a th:href="@{logout}" style="padding-left:5px;"><i class="fa fa-sign-out text-danger"></i> 注销</a>
+				        </div>
+				    </div>
+            	</li>
+                <li>
+                    <a class="menuItem" th:href="@{/system/main}"><i class="fa fa-home"></i> <span class="nav-label">首页</span> </a>
+                </li>
+                <li th:each="menu : ${menus}">
+                	<a th:class="@{${!#strings.isEmpty(menu.url) && menu.url != '#'} ? ${menu.target}}" th:href="@{${#strings.isEmpty(menu.url)} ? |#| : ${menu.url}}" th:data-refresh="${menu.isRefresh == '0'}">
+                		<i class="fa fa-bar-chart-o" th:class="${menu.icon}"></i>
+                    	<span class="nav-label" th:text="${menu.menuName}">一级菜单</span>
+                    	<span th:class="${#strings.isEmpty(menu.url) || menu.url == '#'} ? |fa arrow|"></span>
+                	</a>
+                    <ul class="nav nav-second-level collapse">
+						<li th:each="cmenu : ${menu.children}">
+							<a th:if="${#lists.isEmpty(cmenu.children)}" th:class="${#strings.isEmpty(cmenu.target)} ? |menuItem| : ${cmenu.target}" th:utext="${cmenu.menuName}" th:href="@{${cmenu.url}}" th:data-refresh="${cmenu.isRefresh == '0'}">二级菜单</a>
+							<a th:if="${not #lists.isEmpty(cmenu.children)}" href="javascript:;">[[${cmenu.menuName}]]<span class="fa arrow"></span></a>
+							<ul th:if="${not #lists.isEmpty(cmenu.children)}" class="nav nav-third-level">
+								<li th:each="emenu : ${cmenu.children}">
+								    <a th:if="${#lists.isEmpty(emenu.children)}" th:class="${#strings.isEmpty(emenu.target)} ? |menuItem| : ${emenu.target}" th:text="${emenu.menuName}" th:href="@{${emenu.url}}" th:data-refresh="${emenu.isRefresh == '0'}">三级菜单</a>
+								    <a th:if="${not #lists.isEmpty(emenu.children)}" href="javascript:;">[[${emenu.menuName}]]<span class="fa arrow"></span></a>
+								    <ul th:if="${not #lists.isEmpty(emenu.children)}" class="nav nav-four-level">
+								      	<li th:each="fmenu : ${emenu.children}"><a th:if="${#lists.isEmpty(fmenu.children)}" th:class="${#strings.isEmpty(fmenu.target)} ? |menuItem| : ${fmenu.target}" th:text="${fmenu.menuName}" th:href="@{${fmenu.url}}" th:data-refresh="${fmenu.isRefresh == '0'}">四级菜单</a></li>
+								    </ul>
+								</li>
+							</ul>
+						</li>
+					</ul>
+                </li>
+                <li th:if="${demoEnabled}">
+                    <a href="javascript:;"><i class="fa fa-desktop"></i><span class="nav-label">实例演示</span><span class="fa arrow"></span></a>
+                    <ul class="nav nav-second-level collapse">
+                        <li> <a>表单<span class="fa arrow"></span></a>
+                            <ul class="nav nav-third-level">
+								<li><a class="menuItem" th:href="@{/demo/form/button}">按钮</a></li>
+								<li><a class="menuItem" th:href="@{/demo/form/grid}">栅格</a></li>
+								<li><a class="menuItem" th:href="@{/demo/form/select}">下拉框</a></li>
+								<li><a class="menuItem" th:href="@{/demo/form/timeline}">时间轴</a></li>
+								<li><a class="menuItem" th:href="@{/demo/form/progress_bars}">进度条</a></li>
+								<li><a class="menuItem" th:href="@{/demo/form/basic}">基本表单</a></li>
+								<li><a class="menuItem" th:href="@{/demo/form/cards}">卡片列表</a></li>
+								<li><a class="menuItem" th:href="@{/demo/form/jasny}">功能扩展</a></li>
+								<li><a class="menuItem" th:href="@{/demo/form/sortable}">拖动排序</a></li>
+								<li><a class="menuItem" th:href="@{/demo/form/invoice}">单据打印</a></li>
+								<li><a class="menuItem" th:href="@{/demo/form/labels_tips}">标签 & 提示</a></li>
+								<li><a class="menuItem" th:href="@{/demo/form/tabs_panels}">选项卡 & 面板</a></li>
+								<li><a class="menuItem" th:href="@{/demo/form/validate}">表单校验</a></li>
+								<li><a class="menuItem" th:href="@{/demo/form/wizard}">表单向导</a></li>
+								<li><a class="menuItem" th:href="@{/demo/form/upload}">文件上传</a></li>
+								<li><a class="menuItem" th:href="@{/demo/form/datetime}">日期和时间</a></li>
+								<li><a class="menuItem" th:href="@{/demo/form/summernote}">富文本编辑器</a></li>
+								<li><a class="menuItem" th:href="@{/demo/form/duallistbox}">左右互选组件</a></li>
+								<li><a class="menuItem" th:href="@{/demo/form/autocomplete}">搜索自动补全</a></li>
+								<li><a class="menuItem" th:href="@{/demo/form/cxselect}">多级联动下拉</a></li>
+								<li><a class="menuItem" th:href="@{/demo/form/localrefresh}">Ajax局部刷新</a></li>
+							</ul>
+                        </li>
+                        <li> <a>表格<span class="fa arrow"></span></a>
+                            <ul class="nav nav-third-level">
+								<li><a class="menuItem" th:href="@{/demo/table/search}">查询条件</a></li>
+								<li><a class="menuItem" th:href="@{/demo/table/footer}">数据汇总</a></li>
+								<li><a class="menuItem" th:href="@{/demo/table/groupHeader}">组合表头</a></li>
+								<li><a class="menuItem" th:href="@{/demo/table/export}">表格导出</a></li>
+								<li><a class="menuItem" th:href="@{/demo/table/textSearch}">全文索引</a></li>
+								<li><a class="menuItem" th:href="@{/demo/table/exportSelected}">导出选择列</a></li>
+								<li><a class="menuItem" th:href="@{/demo/table/remember}">翻页记住选择</a></li>
+								<li><a class="menuItem" th:href="@{/demo/table/cookie}">表格保存状态</a></li>
+								<li><a class="menuItem" th:href="@{/demo/table/pageGo}">跳转至指定页</a></li>
+								<li><a class="menuItem" th:href="@{/demo/table/params}">自定义查询参数</a></li>
+								<li><a class="menuItem" th:href="@{/demo/table/multi}">初始多表格</a></li>
+								<li><a class="menuItem" th:href="@{/demo/table/button}">点击按钮加载表格</a></li>
+								<li><a class="menuItem" th:href="@{/demo/table/data}">直接加载表格数据</a></li>
+								<li><a class="menuItem" th:href="@{/demo/table/fixedColumns}">表格冻结列</a></li>
+								<li><a class="menuItem" th:href="@{/demo/table/event}">自定义触发事件</a></li>
+								<li><a class="menuItem" th:href="@{/demo/table/headerStyle}">表格标题格式化</a></li>
+								<li><a class="menuItem" th:href="@{/demo/table/detail}">表格细节视图</a></li>
+								<li><a class="menuItem" th:href="@{/demo/table/child}">表格父子视图</a></li>
+								<li><a class="menuItem" th:href="@{/demo/table/image}">表格图片预览</a></li>
+								<li><a class="menuItem" th:href="@{/demo/table/curd}">动态增删改查</a></li>
+								<li><a class="menuItem" th:href="@{/demo/table/reorderRows}">表格行拖拽操作</a></li>
+								<li><a class="menuItem" th:href="@{/demo/table/reorderColumns}">表格列拖拽操作</a></li>
+								<li><a class="menuItem" th:href="@{/demo/table/resizable}">表格列宽拖动</a></li>
+								<li><a class="menuItem" th:href="@{/demo/table/editable}">表格行内编辑</a></li>
+								<li><a class="menuItem" th:href="@{/demo/table/subdata}">主子表提交</a></li>
+								<li><a class="menuItem" th:href="@{/demo/table/refresh}">表格自动刷新</a></li>
+								<li><a class="menuItem" th:href="@{/demo/table/print}">表格打印配置</a></li>
+								<li><a class="menuItem" th:href="@{/demo/table/dynamicColumns}">表格动态列</a></li>
+								<li><a class="menuItem" th:href="@{/demo/table/virtualScroll}">表格虚拟滚动</a></li>
+								<li><a class="menuItem" th:href="@{/demo/table/customView}">自定义视图分页</a></li>
+								<li><a class="menuItem" th:href="@{/demo/table/asynTree}">异步加载表格树</a></li>
+								<li><a class="menuItem" th:href="@{/demo/table/other}">表格其他操作</a></li>
+							</ul>
+                        </li>
+                        <li> <a>弹框<span class="fa arrow"></span></a>
+                            <ul class="nav nav-third-level">
+								<li><a class="menuItem" th:href="@{/demo/modal/dialog}">模态窗口</a></li>
+								<li><a class="menuItem" th:href="@{/demo/modal/layer}">弹层组件</a></li>
+								<li><a class="menuItem" th:href="@{/demo/modal/table}">弹层表格</a></li>
+							</ul>
+                        </li>
+                        <li> <a>操作<span class="fa arrow"></span></a>
+                            <ul class="nav nav-third-level">
+								<li><a class="menuItem" th:href="@{/demo/operate/table}">表格</a></li>
+								<li><a class="menuItem" th:href="@{/demo/operate/other}">其他</a></li>
+							</ul>
+                        </li>
+                        <li> <a>报表<span class="fa arrow"></span></a>
+                            <ul class="nav nav-third-level">
+								<li><a class="menuItem" th:href="@{/demo/report/echarts}">百度ECharts</a></li>
+								<li><a class="menuItem" th:href="@{/demo/report/peity}">peity</a></li>
+								<li><a class="menuItem" th:href="@{/demo/report/sparkline}">sparkline</a></li>
+								<li><a class="menuItem" th:href="@{/demo/report/metrics}">图表组合</a></li>
+							</ul>
+                        </li>
+                        <li> <a>图标<span class="fa arrow"></span></a>
+                            <ul class="nav nav-third-level">
+								<li><a class="menuItem" th:href="@{/demo/icon/fontawesome}">Font Awesome</a></li>
+								<li><a class="menuItem" th:href="@{/demo/icon/glyphicons}">Glyphicons</a></li>
+							</ul>
+                        </li>
+                        <li>
+	                        <a href="javascript:;"><i class="fa fa-sitemap"></i>四层菜单<span class="fa arrow"></span></a>
+	                        <ul class="nav nav-third-level collapse">
+	                            <li>
+	                                <a href="javascript:;" id="damian">三级菜单1<span class="fa arrow"></span></a>
+	                                <ul class="nav nav-third-level">
+	                                    <li>
+	                                        <a href="javascript:;">四级菜单1</a>
+	                                    </li>
+	                                    <li>
+	                                        <a href="javascript:;">四级菜单2</a>
+	                                    </li>
+	                                </ul>
+	                            </li>
+	                            <li><a href="javascript:;">三级菜单2</a></li>
+	                        </ul>
+	                    </li>
+                    </ul>
+                </li>
+            </ul>
+        </div>
+    </nav>
+    <!--左侧导航结束-->
+
+    <!--右侧部分开始-->
+    <div id="page-wrapper" class="gray-bg dashbard-1">
+        <div class="row border-bottom">
+            <nav class="navbar navbar-static-top" role="navigation" style="margin-bottom: 0">
+                <div class="navbar-header">
+                    <a class="navbar-minimalize minimalize-styl-2" style="color:#FFF;" href="javascript:;" title="收起菜单">
+                    	<i class="fa fa-bars"></i>
+                    </a>
+                </div>
+                <ul class="nav navbar-top-links navbar-right welcome-message">
+                    <li><a data-toggle="tooltip" data-trigger="hover" data-placement="bottom" title="开发文档" href="http://doc.ruoyi.vip/ruoyi" target="_blank"><i class="fa fa-question-circle"></i> 文档</a></li>
+                    <li><a data-toggle="tooltip" data-trigger="hover" data-placement="bottom" title="锁定屏幕" href="javascript:;" id="lockScreen"><i class="fa fa-lock"></i> 锁屏</a></li>
+	                <li><a data-toggle="tooltip" data-trigger="hover" data-placement="bottom" title="全屏显示" href="javascript:;" id="fullScreen"><i class="fa fa-arrows-alt"></i> 全屏</a></li>
+                    <li class="dropdown user-menu">
+						<a href="javascript:void(0)" class="dropdown-toggle" data-hover="dropdown">
+							<img th:src="(${#strings.isEmpty(user.avatar)}) ? @{/img/profile.jpg} : @{${user.avatar}}" th:onerror="this.src='img/profile.jpg'" class="user-image">
+							<span class="hidden-xs">[[${#strings.defaultString(user.userName, '-')}]]</span>
+						</a>
+						<ul class="dropdown-menu">
+							<li class="mt5">
+								<a th:href="@{/system/user/profile}" class="menuItem noactive">
+								<i class="fa fa-user"></i> 个人中心</a>
+							</li>
+							<li>
+								<a onclick="resetPwd()">
+								<i class="fa fa-key"></i> 修改密码</a>
+							</li>
+							<li>
+								<a onclick="switchSkin()">
+								<i class="fa fa-dashboard"></i> 切换主题</a>
+							</li>
+							<li>
+								<a onclick="toggleMenu()">
+								<i class="fa fa-toggle-off"></i> 横向菜单</a>
+							</li>
+							<li class="divider"></li>
+							<li>
+								<a th:href="@{logout}">
+								<i class="fa fa-sign-out"></i> 退出登录</a>
+							</li>
+						</ul>
+					</li>
+                </ul>
+            </nav>
+        </div>
+        <div class="row content-tabs" th:classappend="${#bools.isFalse(tagsView)} ? |hide|">
+            <button class="roll-nav roll-left tabLeft">
+                <i class="fa fa-backward"></i>
+            </button>
+            <nav class="page-tabs menuTabs">
+                <div class="page-tabs-content">
+                    <a href="javascript:;" class="active menuTab" th:data-id="@{/system/main}">首页</a>
+                </div>
+            </nav>
+            <button class="roll-nav roll-right tabRight">
+                <i class="fa fa-forward"></i>
+            </button>
+            <a href="javascript:void(0);" class="roll-nav roll-right tabReload"><i class="fa fa-refresh"></i> 刷新</a>
+        </div>
+
+        <a id="ax_close_max" class="ax_close_max" href="javascript:;" title="关闭全屏"> <i class="fa fa-times-circle-o"></i> </a>
+
+        <div class="row mainContent" id="content-main" th:classappend="${mainClass}">
+            <iframe class="RuoYi_iframe" name="iframe0" width="100%" height="100%" th:data-id="@{/system/main}"
+                th:src="@{/system/main}" frameborder="0" seamless></iframe>
+        </div>
+
+        <div th:if="${footer}" class="footer">
+            <div class="pull-right">© [[${copyrightYear}]] RuoYi Copyright </div>
+        </div>
+    </div>
+    <!--右侧部分结束-->
+</div>
+<!-- 全局js -->
+<script th:src="@{/js/jquery.min.js}"></script>
+<script th:src="@{/js/bootstrap.min.js}"></script>
+<script th:src="@{/js/plugins/metisMenu/jquery.metisMenu.js}"></script>
+<script th:src="@{/js/plugins/slimscroll/jquery.slimscroll.min.js}"></script>
+<script th:src="@{/js/jquery.contextMenu.min.js}"></script>
+<script th:src="@{/ajax/libs/blockUI/jquery.blockUI.js}"></script>
+<script th:src="@{/ajax/libs/layer/layer.min.js}"></script>
+<script th:src="@{/ruoyi/js/ry-ui.js?v=4.8.0}"></script>
+<script th:src="@{/ruoyi/js/common.js?v=4.8.0}"></script>
+<script th:src="@{/ruoyi/index.js?v=20201208}"></script>
+<script th:src="@{/ajax/libs/fullscreen/jquery.fullscreen.js}"></script>
+<script th:inline="javascript">
+window.history.forward(1);
+var ctx = [[@{/}]]; 
+var lockscreen = [[${session.lockscreen}]]; 
+if(lockscreen){window.top.location=ctx+"lockscreen";}
+// 皮肤缓存
+var skin = storage.get("skin");
+// history(表示去掉地址的#)否则地址以"#"形式展示
+var mode = "history";
+// 历史访问路径缓存
+var historyPath = storage.get("historyPath");
+// 是否页签与菜单联动
+var isLinkage = true;
+// 是否页签切换滚动到顶部
+var isScrollToTop = true;
+
+// 本地主题优先,未设置取系统配置
+if($.common.isNotEmpty(skin)){
+	$("body").addClass(skin.split('|')[0]);
+	$("body").addClass(skin.split('|')[1]);
+} else {
+	$("body").addClass([[${sideTheme}]]);
+	$("body").addClass([[${skinName}]]);
+}
+
+/* 用户管理-重置密码 */
+function resetPwd() {
+    var url = ctx + 'system/user/profile/resetPwd';
+    $.modal.open("重置密码", url, '770', '380');
+}
+
+/* 切换主题 */
+function switchSkin() {
+    layer.open({
+		type : 2,
+		shadeClose : true,
+		title : "切换主题",
+		area : ["530px", "386px"],
+		content : [ctx + "system/switchSkin", 'no']
+	})
+}
+
+/* 切换菜单 */
+function toggleMenu() {
+	$.modal.confirm("确认要切换成横向菜单吗?", function() {
+		$.get(ctx + 'system/menuStyle/topnav', function(result) {
+            window.location.reload();
+	    });
+	})
+}
+
+/** 刷新时访问路径页签 */
+function applyPath(url) {
+	$('a[href$="' + decodeURI(url) + '"]').click();
+	if (!$('a[href$="' + url + '"]').hasClass("noactive")) {
+	    $('a[href$="' + url + '"]').parent("li").addClass("selected").parents("li").addClass("active").end().parents("ul").addClass("in");
+	}
+}
+
+$(function() {
+	var lockPath = storage.get('lockPath');
+	if($.common.equals("history", mode) && window.performance.navigation.type == 1) {
+		var url = storage.get('publicPath');
+	    if ($.common.isNotEmpty(url)) {
+	    	applyPath(url);
+	    }
+	} else if($.common.isNotEmpty(lockPath)) {
+	    applyPath(lockPath);
+	    storage.remove('lockPath');
+	} else {
+		var hash = location.hash;
+	    if ($.common.isNotEmpty(hash)) {
+	        var url = hash.substring(1, hash.length);
+	        applyPath(url);
+	    } else {
+	    	if($.common.equals("history", mode)) {
+	    		storage.set('publicPath', "");
+	    	}
+	    }
+	}
+	
+	/* 初始密码提示 */
+	if([[${isDefaultModifyPwd}]]) {
+		layer.confirm("您的密码还是初始密码,请修改密码!", {
+			icon: 0,
+			title: "安全提示",
+			btn: ['确认'	, '取消'],
+			offset: ['30%']
+		}, function (index) {
+			resetPwd();
+			layer.close(index);
+		});
+	}
+	
+	/* 过期密码提示 */
+	if([[${isPasswordExpired}]]) {
+		layer.confirm("您的密码已过期,请尽快修改密码!", {
+			icon: 0,
+			title: "安全提示",
+			btn: ['确认'	, '取消'],
+			offset: ['30%']
+		}, function (index) {
+			resetPwd();
+			layer.close(index);
+		});
+	}
+	$("[data-toggle='tooltip']").tooltip();
+});
+</script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/lock.html b/ruoyi-admin/src/main/resources/templates/lock.html
new file mode 100644
index 0000000..86753b0
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/lock.html
@@ -0,0 +1,208 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org">
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <!--360浏览器优先以webkit内核解析-->
+    <title>锁定屏幕</title>
+    <link th:href="@{favicon.ico}" rel="shortcut icon"/>
+    <link href="../static/css/bootstrap.min.css" th:href="@{/css/bootstrap.min.css}" rel="stylesheet"/>
+    <link href="../static/css/font-awesome.min.css" th:href="@{/css/font-awesome.min.css}" rel="stylesheet"/>
+	<style>.lockscreen{background:#d2d6de;height:auto;}.lockscreen .lockscreen-name{text-align:center;font-weight:600;margin-top:50px;margin-bottom:30px;}.lockscreen-wrapper{max-width:400px;margin:10% auto;z-index:800;position:relative;}.lockscreen .lockscreen-name{text-align:center;font-weight:600;margin-top:50px;margin-bottom:30px;}.lockscreen-item{border-radius:4px;padding:0;background:#fff;position:relative;margin:10px auto 30px auto;width:290px}.lockscreen-image{border-radius:50%;position:absolute;left:-10px;top:-25px;background:#fff;padding:5px;z-index:10}.lockscreen-image>img{border-radius:50%;width:70px;height:70px}.lockscreen-credentials{margin-left:70px}.lockscreen-credentials .form-control{border:0}.lockscreen-credentials .btn{background-color:#fff;border:0;padding:0 10px}.lockscreen-footer{margin-top:150px}.lockscreen-time{width:100%;color:#fff;font-size:60px;display:inline-block;text-align:center;font-family:'Open Sans',sans-serif;font-weight:300;}</style>
+</head>
+<body class="lockscreen">
+<div class="lockscreen-wrapper">
+    <div class="lockscreen-time"></div>
+    <div class="lockscreen-name">[[ ${user.loginName} ]] / [[${#strings.defaultString(user.userName, '-')}]]</div>
+
+    <div class="lockscreen-item">
+        <div class="lockscreen-image">
+            <img th:src="(${#strings.isEmpty(user.avatar)}) ? @{/img/profile.jpg} : @{${user.avatar}}" th:onerror="this.src='img/profile.jpg'" class="img-circle" alt="User Image">
+        </div>
+        <form class="lockscreen-credentials" method="post" action="#" onsubmit="return false;">
+            <div class="input-group">
+                <input type="password" name="password" autocomplete="off" class="form-control" placeholder="密码">
+                <div class="input-group-btn">
+                    <button type="button" class="btn" onclick="unlock()"><i class="fa fa-arrow-right text-muted"></i></button>
+                </div>
+            </div>
+        </form>
+    </div>
+    
+    <div class="help-block text-center" style="margin-top: 50px;">系统锁屏,请输入密码登录!</div>
+    <div class="text-center">
+        <a th:href="@{logout}">退出重新登录</a>
+    </div>
+</div>
+<script src="../static/js/jquery.min.js" th:src="@{/js/jquery.min.js}"></script>
+<script src="../static/js/bootstrap.min.js" th:src="@{/js/bootstrap.min.js}"></script>
+<script src="../static/js/three.min.js" th:src="@{/js/three.min.js}"></script>
+<script src="../static/ajax/libs/layer/layer.min.js" th:src="@{/ajax/libs/layer/layer.min.js}"></script>
+<script src="../static/ruoyi/js/ry-ui.js" th:src="@{/ruoyi/js/ry-ui.js?v=4.8.0}"></script>
+</body>
+<script th:inline="javascript">
+    var ctx = [[@{/}]];
+    Date.prototype.format = function(fmt) {
+	  var o = {
+	    "M+" : this.getMonth()+1,                 //月份
+	    "d+" : this.getDate(),                    //日
+	    "h+" : this.getHours(),                   //小时
+	    "m+" : this.getMinutes(),                 //分
+	    "s+" : this.getSeconds(),                 //秒
+	    "q+" : Math.floor((this.getMonth()+3)/3), //季度
+	    "S"  : this.getMilliseconds()             //毫秒
+	  };
+
+	  if (/(y+)/.test(fmt)) {
+          fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
+	  }
+
+	  for (var k in o) {
+		  if (new RegExp("(" + k + ")").test(fmt)) {
+		      fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
+		  }
+      }
+	  return fmt;
+	}
+    
+    $(function() {
+        $('.lockscreen-time').text((new Date()).format('hh:mm:ss'));
+        setInterval(function() {
+            $('.lockscreen-time').text((new Date()).format('hh:mm:ss'));
+        }, 500);
+        init();
+        animate();
+    });
+
+    $(document).keydown(function(event) {
+   	    if (event.keyCode == 13) {
+   	    	unlock();
+   	    }
+   	});
+     
+    function unlock() {
+        var username = $("input[name='username']").val();
+        var password = $("input[name='password']").val();
+        if ($.common.isEmpty(password)) {
+        	$.modal.msg("请输入密码");
+            return;
+        }
+        
+        var index = "";
+        var config = {
+            url: ctx + "unlockscreen",
+            type: "post",
+            dataType: "json",
+            data: { password: password },
+            beforeSend: function() {
+            	index = layer.load(2, {shade: false});
+            },
+            success: function(result) {
+                if (result.code == web_status.SUCCESS) {
+                    location.href = ctx + 'index';
+                } else {
+                    $.modal.msg(result.msg);
+                    $("input[name='password']").val("");
+                }
+                layer.close(index);
+            }
+        };
+        $.ajax(config);
+    };
+
+    var container;
+    var camera, scene, projector, renderer;
+    var PI2 = Math.PI * 2;
+
+    var programFill = function(context) {
+        context.beginPath();
+        context.arc(0, 0, 1, 0, PI2, true);
+        context.closePath();
+        context.fill();
+    };
+
+    var programStroke = function(context) {
+        context.lineWidth = 0.05;
+        context.beginPath();
+        context.arc(0, 0, 1, 0, PI2, true);
+        context.closePath();
+        context.stroke();
+    };
+
+    var mouse = { x: 0, y: 0 }, INTERSECTED;
+    function init() {
+    	container = document.createElement('div');
+    	container.id = 'bgc';
+    	container.style.position = 'absolute';
+    	container.style.zIndex = '0';
+    	container.style.top = '0px';
+    	$(".lockscreen-wrapper").before(container);
+
+        camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 10000);
+        camera.position.set(0, 300, 500);
+        scene = new THREE.Scene();
+
+        for (var i = 0; i < 100; i++) {
+            var particle = new THREE.Particle(new THREE.ParticleCanvasMaterial({ color: Math.random() * 0x808080 + 0x808080, program: programStroke }));
+            particle.position.x = Math.random() * 800 - 400;
+            particle.position.y = Math.random() * 800 - 400;
+            particle.position.z = Math.random() * 800 - 400;
+            particle.scale.x = particle.scale.y = Math.random() * 10 + 10;
+            scene.add(particle);
+        }
+        projector = new THREE.Projector();
+        renderer = new THREE.CanvasRenderer();
+        renderer.setSize(window.innerWidth, window.innerHeight - 10);
+        container.appendChild(renderer.domElement);
+        document.addEventListener('mousemove', onDocumentMouseMove, false);
+        window.addEventListener('resize', onWindowResize, false);
+    };
+
+    function onWindowResize() {
+        camera.aspect = window.innerWidth / window.innerHeight;
+        camera.updateProjectionMatrix();
+        renderer.setSize(window.innerWidth, window.innerHeight - 10);
+    };
+
+    function onDocumentMouseMove(event) {
+        event.preventDefault();
+        mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
+        mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
+    };
+
+    function animate() {
+        requestAnimationFrame(animate);
+        render();
+    };
+
+    var radius = 600;
+    var theta = 0;
+
+    function render() {
+    	theta += 0.2;
+    	camera.position.x = radius * Math.sin(theta * Math.PI / 360);
+    	camera.position.y = radius * Math.sin(theta * Math.PI / 360);
+    	camera.position.z = radius * Math.cos(theta * Math.PI / 360);
+    	camera.lookAt(scene.position);
+    	camera.updateMatrixWorld();
+
+    	var vector = new THREE.Vector3(mouse.x, mouse.y, 0.5);
+    	projector.unprojectVector(vector, camera);
+
+    	var ray = new THREE.Ray(camera.position, vector.subSelf(camera.position).normalize());
+    	var intersects = ray.intersectObjects(scene.children);
+
+        if (intersects.length > 0) {
+            if (INTERSECTED != intersects[0].object) {
+                if (INTERSECTED) INTERSECTED.material.program = programStroke;
+                INTERSECTED = intersects[0].object;
+                INTERSECTED.material.program = programFill;
+            }
+        } else {
+            if (INTERSECTED) INTERSECTED.material.program = programStroke;
+            INTERSECTED = null;
+        }
+        renderer.render(scene, camera);
+    }
+</script>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/login.html b/ruoyi-admin/src/main/resources/templates/login.html
new file mode 100644
index 0000000..72f44bb
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/login.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org">
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
+    <title>登录若依系统</title>
+    <meta name="description" content="若依后台管理框架">
+    <link href="../static/css/bootstrap.min.css" th:href="@{/css/bootstrap.min.css}" rel="stylesheet"/>
+    <link href="../static/css/font-awesome.min.css" th:href="@{/css/font-awesome.min.css}" rel="stylesheet"/>
+    <link href="../static/css/style.min.css" th:href="@{/css/style.min.css}" rel="stylesheet"/>
+    <link href="../static/css/login.min.css" th:href="@{/css/login.min.css}" rel="stylesheet"/>
+    <link href="../static/ruoyi/css/ry-ui.css" th:href="@{/ruoyi/css/ry-ui.css?v=4.8.0}" rel="stylesheet"/>
+    <!-- 360浏览器急速模式 -->
+    <meta name="renderer" content="webkit">
+    <!-- 避免IE使用兼容模式 -->
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <link rel="shortcut icon" href="../static/favicon.ico" th:href="@{favicon.ico}"/>
+    <style type="text/css">label.error { position:inherit;  }</style>
+    <script>
+        if(window.top!==window.self){alert('未登录或登录超时。请重新登录');window.top.location=window.location};
+    </script>
+</head>
+<body class="signin">
+    <div class="signinpanel">
+        <div class="row">
+            <div class="col-sm-7">
+                <div class="signin-info">
+                    <div class="logopanel m-b">
+                        <h1><img alt="[ 若依 ]" src="../static/ruoyi.png" th:src="@{/ruoyi.png}"></h1>
+                    </div>
+                    <div class="m-b"></div>
+                    <h4>欢迎使用 <strong>若依 后台管理系统</strong></h4>
+                    <ul class="m-b">
+                        <li><i class="fa fa-arrow-circle-o-right m-r-xs"></i> SpringBoot</li>
+                        <li><i class="fa fa-arrow-circle-o-right m-r-xs"></i> Mybatis</li>
+                        <li><i class="fa fa-arrow-circle-o-right m-r-xs"></i> Shiro</li>
+                        <li><i class="fa fa-arrow-circle-o-right m-r-xs"></i> Thymeleaf</li>
+                        <li><i class="fa fa-arrow-circle-o-right m-r-xs"></i> Bootstrap</li>
+                    </ul>
+                    <strong th:if="${isAllowRegister}">还没有账号? <a th:href="@{/register}">立即注册&raquo;</a></strong>
+                </div>
+            </div>
+            <div class="col-sm-5">
+                <form id="signupForm" autocomplete="off">
+                    <h4 class="no-margins">登录:</h4>
+                    <p class="m-t-md">你若不离不弃,我必生死相依</p>
+                    <input type="text"     name="username" class="form-control uname"     placeholder="用户名" value="admin"    />
+                    <input type="password" name="password" class="form-control pword"     placeholder="密码"   value="admin123" />
+					<div class="row m-t" th:if="${captchaEnabled==true}">
+						<div class="col-xs-6">
+						    <input type="text" name="validateCode" class="form-control code" placeholder="验证码" maxlength="5" />
+						</div>
+						<div class="col-xs-6">
+							<a href="javascript:void(0);" title="点击更换验证码">
+								<img th:src="@{/captcha/captchaImage(type=${captchaType})}" class="imgcode" width="85%"/>
+							</a>
+						</div>
+					</div>
+                    <div class="checkbox-custom" th:if="${isRemembered}" th:classappend="${captchaEnabled==false} ? 'm-t'">
+				        <input type="checkbox" id="rememberme" name="rememberme"> <label for="rememberme">记住我</label>
+				    </div>
+                    <button class="btn btn-success btn-block" id="btnSubmit" data-loading="正在验证登录,请稍候...">登录</button>
+                </form>
+            </div>
+        </div>
+        <div class="signup-footer">
+            <div class="pull-left">
+                Copyright © 2018-2025 ruoyi.vip All Rights Reserved. <br>
+            </div>
+        </div>
+    </div>
+<script th:inline="javascript"> var ctx = [[@{/}]]; var captchaType = [[${captchaType}]]; var captchaEnabled = [[${captchaEnabled}]];</script>
+<!--[if lte IE 8]><script>window.location.href=ctx+'html/ie.html';</script><![endif]-->
+<!-- 全局js -->
+<script src="../static/js/jquery.min.js" th:src="@{/js/jquery.min.js}"></script>
+<script src="../static/ajax/libs/validate/jquery.validate.min.js" th:src="@{/ajax/libs/validate/jquery.validate.min.js}"></script>
+<script src="../static/ajax/libs/layer/layer.min.js" th:src="@{/ajax/libs/layer/layer.min.js}"></script>
+<script src="../static/ajax/libs/blockUI/jquery.blockUI.js" th:src="@{/ajax/libs/blockUI/jquery.blockUI.js}"></script>
+<script src="../static/ruoyi/js/ry-ui.js" th:src="@{/ruoyi/js/ry-ui.js?v=4.8.0}"></script>
+<script src="../static/ruoyi/login.js" th:src="@{/ruoyi/login.js}"></script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/main.html b/ruoyi-admin/src/main/resources/templates/main.html
new file mode 100644
index 0000000..e68e9d5
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/main.html
@@ -0,0 +1,1793 @@
+<!DOCTYPE html>
+<html  lang="zh" xmlns:th="http://www.thymeleaf.org">
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <!--360浏览器优先以webkit内核解析-->
+    <title>若依介绍</title>
+    <link rel="shortcut icon" href="favicon.ico">
+    <link href="../static/css/bootstrap.min.css" th:href="@{/css/bootstrap.min.css}" rel="stylesheet"/>
+    <link href="../static/css/font-awesome.min.css" th:href="@{/css/font-awesome.min.css}" rel="stylesheet"/>
+    <link href="../static/css/style.min.css" th:href="@{/css/style.min.css}" rel="stylesheet"/>
+</head>
+
+<body class="gray-bg">
+    <div class="row border-bottom white-bg dashboard-header">
+        <div class="col-sm-12">
+            <blockquote class="text-warning" style="font-size:14px">
+                                           阿里云服务器折扣区 <a target="_blank" href="http://aly.ruoyi.vip">☛☛点我进入☚☚</a> &nbsp;&nbsp;&nbsp; 腾讯云服务器秒杀区 <a target="_blank" href="http://txy.ruoyi.vip">☛☛点我进入☚☚</a><br>
+            </blockquote>
+
+            <hr>
+        </div>
+        <div class="col-sm-3">
+            <h2>Hello,Guest</h2>
+            <small>移动设备访问请扫描以下二维码:</small>
+            <br>
+            <br>
+            <img th:src="@{/img/qr_code.png}" width="100%" style="max-width:264px;">
+            <br>
+        </div>
+        <div class="col-sm-5">
+            <h2>若依后台管理框架</h2>
+            <p>一直想做一款后台管理系统,看了很多优秀的开源项目但是发现没有合适自己的。于是利用空闲休息时间开始自己写一套后台系统。如此有了若依管理系统。,她可以用于所有的Web应用程序,如<b>网站管理后台</b>,<b>网站会员中心</b>,<b>CMS</b>,<b>CRM</b>,<b>OA</b>等等,当然,您也可以对她进行深度定制,以做出更强系统。所有前端后台代码封装过后十分精简易上手,出错概率低。同时支持移动客户端访问。系统会陆续更新一些实用功能。</p>
+            <p>
+                <b>当前版本:</b><span>v[[${version}]]</span>
+            </p>
+            <p>
+                <span class="label label-warning">&yen;免费开源</span>
+            </p>
+            <br>
+            <p>
+                <a class="btn btn-success btn-outline" href="https://gitee.com/y_project/RuoYi" target="_blank">
+                    <i class="fa fa-cloud"> </i> 访问码云
+                </a>
+                <a class="btn btn-white btn-bitbucket" href="http://ruoyi.vip" target="_blank">
+                    <i class="fa fa-home"></i> 访问主页
+                </a>
+            </p>
+        </div>
+        <div class="col-sm-4">
+            <h4>技术选型:</h4>
+            <ol>
+                <li>核心框架:Spring Boot。</li>
+                <li>安全框架:Apache Shiro。</li>
+                <li>模板引擎:Thymeleaf。</li>
+                <li>持久层框架:MyBatis。</li>
+                <li>定时任务:Quartz。</li>
+                <li>数据库连接池:Druid。</li>
+                <li>工具类:Fastjson。</li>
+                <li>更多……</li>
+            </ol>
+        </div>
+
+    </div>
+    <div class="wrapper wrapper-content">
+        <div class="row">
+            <div class="col-sm-4">
+
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>联系信息</h5>
+
+                    </div>
+                    <div class="ibox-content">
+                        <p><i class="fa fa-send-o"></i> 官网:<a href="http://www.ruoyi.vip" target="_blank">http://www.ruoyi.vip</a>
+                        </p>
+                        <p><i class="fa fa-qq"></i> QQ群:<s>满1389287</s> <s>满1679294</s> <s>满1529866</s> <s>满1772718</s> <s>满1366522</s> <s>满1382251</s> <s>满1145125</s> <s>满86752435</s> <s>满134072510</s> <s>满210336300</s> <s>满339522636</s> <s>满130035985</s> <s>满143151071</s> <s>满158781320</s> <s>满201531282</s> <s>满101526938</s> <s>满264355400</s> <s>满298522656</s> <s>满139845794</s>  <s>满185760789</s> <s>满175104288</s> <s>满174942938</s> <s>满287843737</s> <a href="http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=KTVAIhggR3rR3uZWK9A8kR4yYNREQ4jo&authKey=An4DUV9e7uK8I8VgBbp949z0ypQoDrOoqvVg%2FWOr2vuNNDMZUAMPvqHor6TFMIgz&noverify=0&group_code=232896766" target="_blank">232896766</a>
+                        </p>
+                        <p><i class="fa fa-weixin"></i> 微信:<a href="javascript:;">/ *若依</a>
+                        </p>
+                        <p><i class="fa fa-credit-card"></i> 支付宝:<a href="javascript:;" class="支付宝信息">/ *若依</a>
+                        </p>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-4">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>更新日志</h5>
+                    </div>
+                    <div class="ibox-content no-padding">
+                        <div class="panel-body">
+                            <div class="panel-group" id="version">
+                            <div class="panel panel-default">
+								<div class="panel-heading">
+								   <h5 class="panel-title">
+									   <a data-toggle="collapse" data-parent="#version" href="#v480">v4.8.0</a><code class="pull-right">2024.12.26</code>
+								   </h5>
+								</div>
+								<div id="v480" class="panel-collapse collapse in">
+									<div class="panel-body">
+									   <ol>
+									        <li>支持自定义显示Excel属性列</li>
+									        <li>表格默认转义HTML字符串</li>
+									        <li>新增列宽拖动长内容自适应显示示例</li>
+									        <li>Excel注解支持wrapText是否允许内容换行</li>
+									        <li>代码生成新增配置是否允许文件覆盖到本地</li>
+									        <li>升级oshi到最新版本6.6.5</li>
+									        <li>升级tomcat到最新版本9.0.96</li>
+									        <li>升级logback到最新版本1.2.13</li>
+									        <li>升级commons.io到最新版本2.16.1</li>
+									        <li>升级spring-framework到最新版本5.3.39</li>
+									        <li>升级jquery.validate到最新版本v1.21.0</li>
+									        <li>优化导入带标题文件关闭清理</li>
+									        <li>代码生成创建表屏蔽违规的字符</li>
+									        <li>修复主子表数据显示问题</li>
+									        <li>修复记住我请求头过大的问题</li>
+									        <li>修复角色禁用权限不失效问题</li>
+									        <li>修复类匿名注解访问失效问题</li>
+									        <li>修复导出子列表对象只能在最后的问题</li>
+									        <li>修复多选下拉框open导致页签空白问题</li>
+									        <li>优化身份证脱敏正则</li>
+									        <li>优化查询时间范围日期格式</li>
+									        <li>优化异步树表格折叠同步子状态</li>
+									        <li>优化时间控件清除按钮样式问题</li>
+									        <li>优化表格图片预览动态路径显示问题</li>
+									        <li>优化select2下拉框必填背景色无法清空问题</li>
+									        <li>其他细节优化</li>
+										</ol>
+									</div>
+								</div>
+							</div>
+                            <div class="panel panel-default">
+								<div class="panel-heading">
+								   <h5 class="panel-title">
+									   <a data-toggle="collapse" data-parent="#version" href="#v479">v4.7.9</a><code class="pull-right">2024.06.06</code>
+								   </h5>
+								</div>
+								<div id="v479" class="panel-collapse collapse">
+									<div class="panel-body">
+									   <ol>
+									        <li>通知公告新增详细显示</li>
+									        <li>新增数据脱敏过滤注解</li>
+									        <li>新增表格示例(虚拟滚动)</li>
+									        <li>新增表格示例(全文检索)</li>
+									        <li>新增表格示例(保存状态)</li>
+									        <li>代码生成支持表单布局选项</li>
+									        <li>限制用户操作数据权限范围</li>
+									        <li>用户密码新增非法字符验证</li>
+									        <li>默认加载layer扩展皮肤</li>
+									        <li>未修改初始密码弹框提醒</li>
+									        <li>定时任务白名单配置范围缩小</li>
+									        <li>操作日志列表重置回第一页</li>
+									        <li>定时任务日志默认按时间排序</li>
+									        <li>Excel注解ColumnType类型新增文本</li>
+									        <li>Excel注解新增属性comboReadDict</li>
+									        <li>新增Anonymous匿名访问不鉴权注解</li>
+									        <li>升级oshi到最新版本6.6.1</li>
+									        <li>升级druid到最新版本1.2.23</li>
+									        <li>升级commons.io到最新版本2.13.0</li>
+									        <li>升级spring-framework到安全版本</li>
+									        <li>升级bootstrap-table到最新版本1.22.6</li>
+									        <li>修复重置日期时出现的异常问题</li>
+									        <li>修复页签关闭后存在的跳转问题</li>
+									        <li>修复tooltip单击复制文本不生效的问题</li>
+									        <li>更新缓存管理键名排序方式</li>
+									        <li>更新HttpUtils中的User-Agent</li>
+									        <li>优化自定义XSS注解匹配方式</li>
+									        <li>优化登录注册页面验证码验证</li>
+									        <li>优化数据权限自定义匹配方式</li>
+									        <li>优化高频率定时任务不执行问题</li>
+									        <li>优化树表格align属性在标题生效</li>
+									        <li>优化代码生成主子表关联查询方式</li>
+									        <li>优化导入Excel时设置dictType属性重复查缓存问题</li>
+									        <li>其他细节优化</li>
+										</ol>
+									</div>
+								</div>
+							</div>
+                            <div class="panel panel-default">
+								<div class="panel-heading">
+								   <h5 class="panel-title">
+									   <a data-toggle="collapse" data-parent="#version" href="#v478">v4.7.8</a><code class="pull-right">2023.11.23</code>
+								   </h5>
+								</div>
+								<div id="v478" class="panel-collapse collapse">
+									<div class="panel-body">
+									   <ol>
+									        <li>用户列表新增抽屉效果详细信息</li>
+									        <li>操作日志列表新增IP地址查询</li>
+									        <li>定时任务新增页去除状态选项</li>
+									        <li>系统管理角色列表显示数据权限</li>
+									        <li>通用排序属性orderBy参数限制长度</li>
+									        <li>新增isScrollToTop页签切换滚动到顶部</li>
+									        <li>Excel自定义数据处理器增加单元格/工作簿对象</li>
+									        <li>新增表格参数(数据值为空时显示的内容undefinedText)</li>
+									        <li>升级oshi到最新版本6.4.7</li>
+									        <li>升级shiro到最新版本1.13.0</li>
+									        <li>升级druid到最新版本1.2.20</li>
+									        <li>升级pagehelper到最新版1.4.7</li>
+									        <li>升级spring-boot到最新版本2.5.15</li>
+									        <li>升级jquery到最新版v3.7.1</li>
+									        <li>升级layer到最新版本v3.7.0</li>
+									        <li>升级layui到最新版本v2.8.18</li>
+									        <li>升级x-editable到最新版本1.5.3</li>
+									        <li>修复自定义字典样式不生效的问题</li>
+									        <li>修复弹窗按钮启用禁用方法无效问题</li>
+									        <li>修复横向菜单关闭最后一个页签状态问题</li>
+									        <li>修复Excel导入数据临时文件无法删除问题</li>
+									        <li>修复表格行内编辑启用翻页记住选择无效问题</li>
+									        <li>修复Excels导入时无法获取到dictType字典值问题</li>
+									        <li>优化重置密码鼠标按下显示密码</li>
+									        <li>优化参数键值文本框改为文本域</li>
+									        <li>优化表格重置默认返回到第一页</li>
+									        <li>优化菜单管理类型为按钮状态可选</li>
+									        <li>优化数字金额大写转换精度丢失问题</li>
+									        <li>优化树表查询无数据时清除分页信息</li>
+									        <li>优化通用detail详细信息弹窗不显示按钮</li>
+									        <li>其他细节优化</li>
+										</ol>
+									</div>
+								</div>
+							</div>
+                            <div class="panel panel-default">
+								<div class="panel-heading">
+								   <h5 class="panel-title">
+									   <a data-toggle="collapse" data-parent="#version" href="#v477">v4.7.7</a><code class="pull-right">2023.04.14</code>
+								   </h5>
+								</div>
+								<div id="v477" class="panel-collapse collapse">
+									<div class="panel-body">
+									   <ol>
+									        <li>操作日志新增消耗时间属性</li>
+									        <li>日志管理使用索引提升查询性能</li>
+									        <li>日志注解支持排除指定的请求参数</li>
+									        <li>新增监控页面图标显示</li>
+									        <li>新增支持登录IP黑名单限制</li>
+									        <li>更新fontawesome图标示例</li>
+									        <li>屏蔽定时任务bean违规的字符</li>
+									        <li>支持自定义隐藏属性列过滤子对象</li>
+									        <li>连接池Druid支持新的配置connectTimeout和socketTimeout</li>
+									        <li>升级jquery到最新版v3.6.3</li>
+									        <li>升级layui到最新版本2.7.6</li>
+									        <li>升级jasny-bootstrap到最新版4.0.0</li>
+									        <li>升级oshi到最新版本6.4.1</li>
+									        <li>升级druid到最新版本1.2.16</li>
+									        <li>修复异步表格树子项排序问题</li>
+									        <li>修复冻结列不支持IE浏览器的问题</li>
+									        <li>修复主子表使用suggest插件无法新增问题</li>
+									        <li>修复菜单栏快速点击导致展开折叠样式问题</li>
+									        <li>修复用户多角色数据权限可能出现权限抬升的情况</li>
+									        <li>修复异步加载表格树重置列表父节点展开异常问题</li>
+									        <li>修复页签属性refresh为undefined时页面被刷新问题</li>
+									        <li>移除apache/commons-fileupload依赖</li>
+									        <li>优化前端属性提醒说明</li>
+									        <li>优化用户导入更新时需获取用户编号问题</li>
+									        <li>优化主子表根据序号删除方法加入表格ID参数</li>
+									        <li>优化导出Excel时设置dictType属性重复查缓存问题</li>
+									        <li>优化在线用户服务缓存改为从Bean容器获取不使用自动装配</li>
+									        <li>优化表格示例行拖拽后列表底部总记录条数变成了undefined问题</li>
+									        <li>其他细节优化</li>
+										</ol>
+									</div>
+								</div>
+							</div>
+                            <div class="panel panel-default">
+								<div class="panel-heading">
+								   <h5 class="panel-title">
+									   <a data-toggle="collapse" data-parent="#version" href="#v476">v4.7.6</a><code class="pull-right">2022.12.16</code>
+								   </h5>
+								</div>
+								<div id="v476" class="panel-collapse collapse">
+									<div class="panel-body">
+									   <ol>
+									        <li>定时任务违规的字符</li>
+									        <li>忽略不必要的属性数据返回</li>
+									        <li>导入更新用户数据前校验数据权限</li>
+									        <li>修改参数键名时移除前缓存配置</li>
+									        <li>修改用户登录账号进行重复验证</li>
+									        <li>兼容Excel下拉框内容过多无法显示</li>
+									        <li>升级oshi到最新版本6.4.0</li>
+									        <li>升级kaptcha到最新版2.3.3</li>
+									        <li>升级druid到最新版本1.2.15</li>
+									        <li>升级shiro到最新版本1.10.1</li>
+									        <li>升级pagehelper到最新版1.4.6</li>
+									        <li>升级bootstrap-fileinput到最新版本5.5.2</li>
+									        <li>修复sheet超出最大行数异常问题</li>
+									        <li>修复关闭父页签后提交无法跳转的问题</li>
+									        <li>修复操作日志类型多选导出不生效问题</li>
+									        <li>修复导出包含空子列表数据异常的问题</li>
+									        <li>优化树形表格层级显示</li>
+									        <li>优化SQL关键字检查防止注入</li>
+									        <li>优化用户管理重置时取消部门选择</li>
+									        <li>优化代码生成同步后字典值NULL问题</li>
+									        <li>优化导出对象的子列表为空会出现[]问题</li>
+									        <li>优化select2搜索下拉后校验必填样式问题</li>
+									        <li>其他细节优化</li>
+										</ol>
+									</div>
+								</div>
+							</div>
+                            <div class="panel panel-default">
+								<div class="panel-heading">
+								   <h5 class="panel-title">
+									   <a data-toggle="collapse" data-parent="#version" href="#v475">v4.7.5</a><code class="pull-right">2022.09.05</code>
+								   </h5>
+								</div>
+								<div id="v475" class="panel-collapse collapse">
+									<div class="panel-body">
+									   <ol>
+									        <li>Excel支持导出对象的子列表方法</li>
+									        <li>数据逻辑删除不进行唯一验证</li>
+									        <li>优化多角色数据权限匹配规则</li>
+									        <li>新增主子表提交校验示例</li>
+									        <li>支持自定义隐藏Excel属性列</li>
+									        <li>Excel注解支持backgroundColor属性设置背景颜色</li>
+									        <li>菜单配置刷新时Tab页签切换时刷新</li>
+									        <li>增加对AjaxResult消息结果类型的判断</li>
+									        <li>新增示例(进度条)</li>
+									        <li>新增内容编码/解码方便插件集成使用</li>
+									        <li>升级jquery到最新版3.6.1</li>
+									        <li>升级layui到最新版本2.7.5</li>
+									        <li>升级shiro到最新版本1.9.1</li>
+									        <li>升级druid到最新版本1.2.11</li>
+									        <li>升级pagehelper到最新版1.4.3</li>
+									        <li>升级oshi到最新版本6.2.2</li>
+									        <li>修复树表onLoadSuccess不生效的问题</li>
+											<li>修复用户分配角色大于默认页数丢失问题</li>
+									        <li>定时任务支持执行父类方法</li>
+									        <li>自动设置切换多个树表格实例配置</li>
+									        <li>页签创建标题优先data-title属性</li>
+									        <li>优化任务过期不执行调度</li>
+									        <li>优化横向菜单下激活菜单样式</li>
+									        <li>优化按钮打开窗口后按回车反复弹出</li>
+									        <li>优化excel/scale属性导出单元格数值类型</li>
+									        <li>优化druid开启wall过滤器出现的异常问题</li>
+									        <li>优化多个相同角色数据导致权限SQL重复问题</li>
+									        <li>其他细节优化</li>
+										</ol>
+									</div>
+								</div>
+							</div>
+                            <div class="panel panel-default">
+								<div class="panel-heading">
+								   <h5 class="panel-title">
+									   <a data-toggle="collapse" data-parent="#version" href="#v474">v4.7.4</a><code class="pull-right">2022.06.01</code>
+								   </h5>
+								</div>
+								<div id="v474" class="panel-collapse collapse">
+									<div class="panel-body">
+									   <ol>
+									        <li>用户头像上传图片格式限制</li>
+									        <li>Excel注解支持color属性设置字体颜色</li>
+									        <li>设置分页参数默认值</li>
+									        <li>主子表操作列新增单个删除</li>
+									        <li>定时任务检查Bean包名是否为白名单配置</li>
+									        <li>升级spring-boot到最新版本2.5.14</li>
+									        <li>升级shiro到最新版本1.9.0</li>
+									        <li>升级oshi到最新版本6.1.6</li>
+									        <li>升级fastjson到最新版1.2.83 安全修复版本</li>
+									        <li>文件上传兼容Weblogic环境</li>
+									        <li>新增清理分页的线程变量方法</li>
+									        <li>新增获取不带后缀文件名称方法</li>
+									        <li>用户缓存信息添加部门ancestors祖级列表</li>
+									        <li>自定义ShiroFilterFactoryBean防止中文请求被拦截</li>
+									        <li>字典类型必须以字母开头,且只能为(小写字母,数字,下滑线)</li>
+									        <li>优化IP地址获取到多个的问题</li>
+									        <li>优化表格冻结列阴影效果显示</li>
+									        <li>优化菜单侧边栏滚动条尺寸及颜色</li>
+									        <li>优化显示顺序orderNum类型为整型</li>
+									        <li>优化接口使用泛型使其看到响应属性字段</li>
+									        <li>优化导出数据LocalDateTime类型无数据问题</li>
+									        <li>修复导入Excel时字典字段类型为Long转义为空问题</li>
+									        <li>优化导出excel单元格验证,包含变更为开头.防止正常内容被替换</li>
+									        <li>修复URL类型回退键被禁止问题</li>
+									        <li>修复表格客户端分页序号显示错误问题</li>
+									        <li>修复代码生成拖拽多次出现的排序不正确问题</li>
+									        <li>修复表格打印组件不识别多层对象属性值问题</li>
+									        <li>修复操作日志查询类型条件为0时会查到所有数据</li>
+									        <li>修复Excel注解prompt/combo同时使用不生效问题</li>
+									        <li>修复初始化多表格处理回调函数时获取的表格配置不一致问题</li>
+									        <li>其他细节优化</li>
+										</ol>
+									</div>
+								</div>
+							</div>
+                            <div class="panel panel-default">
+								<div class="panel-heading">
+								   <h5 class="panel-title">
+									   <a data-toggle="collapse" data-parent="#version" href="#v473">v4.7.3</a><code class="pull-right">2022.03.01</code>
+								   </h5>
+								</div>
+								<div id="v473" class="panel-collapse collapse">
+									<div class="panel-body">
+									   <ol>
+									        <li>表格树支持分页/异步加载</li>
+									        <li>代码生成预览支持复制内容</li>
+									        <li>定时任务默认保存到内存中执行</li>
+									        <li>代码生成同步保留必填/类型选项</li>
+									        <li>页面若未匹配到字典标签则返回原字典值</li>
+									        <li>用户访问控制时校验数据权限,防止越权</li>
+									        <li>导出Excel时屏蔽公式,防止CSV注入风险</li>
+									        <li>升级spring-boot到最新版本2.5.10</li>
+									        <li>升级spring-boot-mybatis到最新版2.2.2</li>
+									        <li>升级pagehelper到最新版1.4.1</li>
+									        <li>升级oshi到最新版本6.1.2</li>
+									        <li>升级bootstrap-table到最新版本1.19.1</li>
+									        <li>服务监控新增运行参数信息显示</li>
+									        <li>定时任务目标字符串验证包名白名单</li>
+									        <li>文件上传接口新增原/新文件名返回参数</li>
+									        <li>定时任务屏蔽违规的字符</li>
+									        <li>分页数据新增分页参数合理化参数</li>
+									        <li>表格父子视图添加点击事件打开示例</li>
+									        <li>优化上传文件名称命名规则</li>
+									        <li>优化加载字典缓存数据</li>
+									        <li>优化任务队列满时任务拒绝策略</li>
+									        <li>优化IE11上传预览不显示的问题</li>
+									        <li>优化Excel格式化不同类型的日期对象</li>
+									        <li>优化国际化配置多余的zh请求问题</li>
+									        <li>优化新版Chrome浏览器回退出现的遮罩层</li>
+									        <li>修复EMAIL类型回退键被禁止问题</li>
+									        <li>修复Xss注解字段值为空时的异常问题</li>
+									        <li>其他细节优化</li>
+										</ol>
+									</div>
+								</div>
+							</div>
+                            <div class="panel panel-default">
+								<div class="panel-heading">
+								   <h5 class="panel-title">
+									   <a data-toggle="collapse" data-parent="#version" href="#v472">v4.7.2</a><code class="pull-right">2021.12.23</code>
+								   </h5>
+								</div>
+								<div id="v472" class="panel-collapse collapse">
+									<div class="panel-body">
+									   <ol>
+									        <li>自定义xss校验注解实现</li>
+									        <li>进入修改页面方法添加权限标识</li>
+									        <li>代码生成创建按钮添加超级管理员权限</li>
+									        <li>代码生成创建表检查关键字,防止注入风险</li>
+									        <li>修复定时任务多参数逗号分隔的问题</li>
+									        <li>修复表格插件一起使用出现的声明报错问题</li>
+									        <li>修复代码生成主子表模板删除方法缺少事务</li>
+									        <li>升级oshi到最新版本v5.8.6</li>
+									        <li>升级velocity到最新版本2.3</li>
+									        <li>升级fastjson到最新版1.2.79</li>
+									        <li>升级log4j2到最新版2.17.0 防止漏洞风险</li>
+									        <li>升级thymeleaf到最新版3.0.14 阻止远程代码执行漏洞</li>
+									        <li>优化修改/授权角色实时生效</li>
+									        <li>修整tomcat配置参数已过期问题</li>
+									        <li>前端添加单独的二代身份证校验</li>
+									        <li>优化新增部门时验证用户所属部门</li>
+									        <li>优化查询用户的角色组&岗位组代码</li>
+									        <li>请求分页方法设置成通用方便灵活调用</li>
+									        <li>优化日期类型错误提示与图标重叠问题</li>
+									        <li>其他细节优化</li>
+										</ol>
+									</div>
+								</div>
+							</div>
+                            <div class="panel panel-default">
+								<div class="panel-heading">
+								   <h5 class="panel-title">
+									   <a data-toggle="collapse" data-parent="#version" href="#v471">v4.7.1</a><code class="pull-right">2021.11.10</code>
+								   </h5>
+								</div>
+								<div id="v471" class="panel-collapse collapse">
+									<div class="panel-body">
+									   <ol>
+									        <li>新增是否开启页签功能</li>
+									        <li>代码生成的模块增加创建表功能</li>
+									        <li>Excel导入支持@Excels注解</li>
+									        <li>Excel注解支持导入导出标题信息</li>
+									        <li>Excel注解支持自定义数据处理器</li>
+									        <li>日志注解新增是否保存响应参数</li>
+									        <li>防重提交注解支持配置间隔时间/提示消息</li>
+									        <li>网页部分操作禁止使用后退键(Backspace)</li>
+									        <li>实例演示中增加多层窗口获取值</li>
+									        <li>弹出层openOptions增加动画属性</li>
+									        <li>升级spring-boot到最新版本2.5.6</li>
+									        <li>升级spring-boot-mybatis到最新版2.2.0</li>
+									        <li>升级pagehelper到最新版1.4.0</li>
+									        <li>升级oshi到最新版本v5.8.2</li>
+									        <li>升级druid到最新版1.2.8</li>
+									        <li>升级fastjson到最新版1.2.78</li>
+									        <li>升级thymeleaf-extras-shiro到最新版本v2.1.0</li>
+									        <li>升级bootstrap-fileinput到最新版本v5.2.4</li>
+									        <li>修改阿里云maven仓库地址为新版地址</li>
+									        <li>定时任务屏蔽违规字符</li>
+									        <li>增加sendGet无参请求方法</li>
+									        <li>代码生成去掉多余的排序字段</li>
+									        <li>优化启动脚本参数优化</li>
+									        <li>优化页签关闭右侧清除iframe元素</li>
+									        <li>优化多表格切换表单查询参数</li>
+									        <li>优化表格实例切换event不能为空</li>
+									        <li>优化mybatis全局默认的执行器</li>
+									        <li>优化导入Excel数据关闭时清理file</li>
+									        <li>优化Excel导入图片可能出现的异常</li>
+									        <li>优化记录登录信息,防止不必要的修改</li>
+									        <li>优化aop语法,使用spring自动注入注解</li>
+									        <li>修复无法被反转义问题</li>
+									        <li>修复拖拽行数据错位问题</li>
+									        <li>修复新窗口打开页面关闭弹窗报错</li>
+									        <li>修复富文本回退键被禁止&控制台报错问题</li>
+									        <li>修复自定义弹出层全屏参数无效问题</li>
+									        <li>修复树表代码生成短字段无法识别问题</li>
+									        <li>修复apple/webkit浏览器时间无法格式化</li>
+									        <li>修复后端主子表代码模板方法名生成错误问题</li>
+									        <li>修复swagger没有指定dataTypeClass导致启动出现warn日志</li>
+									        <li>其他细节优化</li>
+										</ol>
+									</div>
+								</div>
+							</div>
+                            <div class="panel panel-default">
+								<div class="panel-heading">
+								   <h5 class="panel-title">
+									   <a data-toggle="collapse" data-parent="#version" href="#v470">v4.7.0</a><code class="pull-right">2021.09.01</code>
+								   </h5>
+								</div>
+								<div id="v470" class="panel-collapse collapse">
+									<div class="panel-body">
+									   <ol>
+									        <li>优化弹出层显示在顶层窗口</li>
+									        <li>定时任务支持在线生成cron表达式</li>
+									        <li>Excel注解支持Image图片导入</li>
+									        <li>支持配置是否开启记住我功能</li>
+									        <li>修改时检查用户数据权限范围</li>
+									        <li>表单重置开始/结束时间控件</li>
+									        <li>新增多图上传示例</li>
+									        <li>启用父部门状态排除顶级节点</li>
+									        <li>富文本默认dialogsInBody属性</li>
+									        <li>去除默认分页合理化参数</li>
+									        <li>顶部菜单跳转添加绝对路径</li>
+									        <li>升级oshi到最新版本v5.8.0</li>
+									        <li>升级shiro到最新版本v1.8.0</li>
+									        <li>升级commons.io到最新版本v2.11.0</li>
+									        <li>升级jquery到最新版v3.6.0</li>
+									        <li>升级icheck到最新版v1.0.3</li>
+									        <li>升级layer到最新版本v3.5.1</li>
+									        <li>升级layui到最新版本v2.6.8</li>
+									        <li>升级laydate到最新版本v5.3.1</li>
+									        <li>升级select2到最新版v4.0.13</li>
+									        <li>升级cropper到最新版本v1.5.12</li>
+									        <li>升级summernote到最新版本v0.8.18</li>
+									        <li>升级duallistbox到最新版本v3.0.9</li>
+									        <li>升级jquery.validate到最新版本v1.19.3</li>
+									        <li>升级bootstrap-suggest到最新版本v0.1.29</li>
+									        <li>升级bootstrap-select到最新版本v1.13.18</li>
+									        <li>升级bootstrap-fileinput到最新版本v5.2.3</li>
+									        <li>查询表格指定列值增加是否去重属性</li>
+									        <li>删除sourceMappingURL源映射</li>
+									        <li>去除多余的favicon.ico引入</li>
+									        <li>优化代码生成模板</li>
+									        <li>优化XSS跨站脚本过滤</li>
+									        <li>补充定时任务表字段注释</li>
+									        <li>定时任务屏蔽ldap远程调用</li>
+									        <li>定时任务屏蔽http(s)远程调用</li>
+									        <li>定时任务对检查异常进行事务回滚</li>
+									        <li>调度日志详细页添加关闭按钮</li>
+									        <li>优化异常打印输出信息</li>
+									        <li>优化移动端进入首页样式</li>
+									        <li>优化用户操作不能删除自己</li>
+									        <li>默认开始/结束时间绑定控件选择类型</li>
+									        <li>其他细节优化</li>
+										</ol>
+									</div>
+								</div>
+							</div>
+                            <div class="panel panel-default">
+								<div class="panel-heading">
+								   <h5 class="panel-title">
+									   <a data-toggle="collapse" data-parent="#version" href="#v462">v4.6.2</a><code class="pull-right">2021.07.01</code>
+								   </h5>
+								</div>
+								<div id="v462" class="panel-collapse collapse">
+									<div class="panel-body">
+									   <ol>
+									        <li>优化参数&字典缓存操作</li>
+									        <li>新增表格参数(导出方式&导出文件类型)</li>
+									        <li>新增表格示例(自定义视图分页)</li>
+									        <li>新增示例(表格列拖拽)</li>
+									        <li>集成yuicompressor实现(CSS/JS压缩)</li>
+									        <li>新增表格参数(是否支持打印页面showPrint)</li>
+									        <li>支持bat脚本执行应用</li>
+									        <li>修复存在的SQL注入漏洞问题</li>
+									        <li>定时任务屏蔽rmi远程调用</li>
+									        <li>导出Excel文件支持数据流下载方式</li>
+									        <li>实例演示弹层组件增加相册层示例</li>
+									        <li>删除操作日志记录信息</li>
+									        <li>增加表格重置分页的参数</li>
+									        <li>限制超级管理员不允许操作</li>
+									        <li>树级结构更新子节点使用replaceFirst</li>
+									        <li>支持动态生成密匙,防止默认密钥泄露</li>
+									        <li>升级pagehelper到最新版1.3.1</li>
+									        <li>升级oshi到最新版本v5.7.4</li>
+									        <li>升级swagger到最新版本v3.0.0</li>
+									        <li>升级commons.io到最新版本v2.10.0</li>
+									        <li>升级commons.fileupload到最新版本v1.4</li>
+									        <li>升级bootstrap-table到最新版本v1.18.3</li>
+									        <li>升级druid到最新版本v1.2.6</li>
+									        <li>升级fastjson到最新版1.2.76</li>
+									        <li>升级layui到最新版本v2.6.6</li>
+									        <li>升级layer到最新版本v3.5.0</li>
+									        <li>升级laydate到最新版本v5.3.0</li>
+									        <li>优化表格树移动端&边框显示</li>
+									        <li>新增表格刷新options配置方法</li>
+									        <li>优化图片工具类读取文件,防止异常</li>
+									        <li>修复表格图片预览移动端宽高无效问题</li>
+									        <li>主子表通用操作封装处理增加文本域类型</li>
+									        <li>日志注解兼容获取json类型的参数</li>
+									        <li>修复表单向导插件有滚动条时底部工具栏无法固定问题</li>
+									        <li>修复导出角色数据范围翻译缺少仅本人</li>
+									        <li>修正Velocity模板初始字符集</li>
+									        <li>升级mybatis到最新版3.5.6 阻止远程代码执行漏洞</li>
+									        <li>优化代码生成导出模板名称</li>
+									        <li>修改个人中心密码长度提醒</li>
+									        <li>实例演示中弹出表格增加以回调形式回显到父窗体</li>
+									        <li>修复登录页面弹窗文字不显示的问题</li>
+									        <li>其他细节优化</li>
+										</ol>
+									</div>
+								</div>
+							</div>
+                            <div class="panel panel-default">
+								<div class="panel-heading">
+								   <h5 class="panel-title">
+									   <a data-toggle="collapse" data-parent="#version" href="#v461">v4.6.1</a><code class="pull-right">2021.04.12</code>
+								   </h5>
+								</div>
+								<div id="v461" class="panel-collapse collapse">
+									<div class="panel-body">
+									   <ol>
+									        <li>新增IE浏览器版本过低提示页面</li>
+									        <li>新增详细信息tab页签方式</li>
+									        <li>新增解锁屏幕打开上次页签</li>
+									        <li>数据监控默认账户密码防止越权访问</li>
+									        <li>新增表格示例(导出选择列)</li>
+									        <li>个人信息添加手机&邮箱重复验证</li>
+									        <li>个人中心刷新后样式问题</li>
+									        <li>操作日志返回参数添加非空验证</li>
+									        <li>velocity剔除commons-collections版本,防止3.2.1版本的反序列化漏洞</li>
+									        <li>子表模板默认日期格式化</li>
+									        <li>代码生成预览语言根据后缀名高亮显示</li>
+									        <li>代码生成主子表相同字段导致数据问题</li>
+									        <li>升级SpringBoot到最新版本2.2.13</li>
+									        <li>升级shiro到最新版1.7.1 阻止身份认证绕过漏洞</li>
+									        <li>升级bootstrapTable到最新版本v1.18.2</li>
+									        <li>升级bootstrapTable相关组件到最新版本v1.18.2</li>
+									        <li>升级fastjson到最新版1.2.75</li>
+									        <li>升级druid到最新版本v1.2.4</li>
+									        <li>升级oshi到最新版本v5.6.0</li>
+									        <li>修改ip字段长度防止ipv6地址长度不够</li>
+									        <li>搜索建议示例选择后隐藏列表</li>
+									        <li>主子表示例增加初始化数据</li>
+									        <li>优化Excel导入增加空行判断</li>
+									        <li>修复横向菜单无法打开页签问题</li>
+									        <li>修复导入数据为负浮点数时,导入结果会丢失精度问题</li>
+									        <li>优化更多操作按钮左侧移入内容闪现消失情况</li>
+									        <li>修复主子表提交中列隐藏后出现列偏移问题</li>
+									        <li>单据打印网页时通过hidden-print隐藏元素</li>
+									        <li>表格销毁清除记住选择数据</li>
+									        <li>增加表格动态列示例</li>
+									        <li>代码生成选择主子表关联元素必填</li>
+									        <li>tree根据Id和Name选中指定节点增加空判断</li>
+									        <li>其他细节优化</li>
+										</ol>
+									</div>
+								</div>
+							</div>
+                            <div class="panel panel-default">
+								<div class="panel-heading">
+								   <h5 class="panel-title">
+									   <a data-toggle="collapse" data-parent="#version" href="#v46">v4.6.0</a><code class="pull-right">2021.01.01</code>
+								   </h5>
+								</div>
+								<div id="v46" class="panel-collapse collapse">
+									<div class="panel-body">
+									   <ol>
+									        <li>新增缓存监控管理</li>
+									        <li>新增锁定屏幕功能</li>
+									        <li>菜单新增是否刷新页面</li>
+									        <li>删除用户和角色解绑关联</li>
+									        <li>新增密码强度字符范围提示</li>
+									        <li>防止匿名访问进行过滤</li>
+									        <li>升级SpringBoot到最新版本2.2.12</li>
+									        <li>升级poi到最新版本4.1.2</li>
+									        <li>升级bitwalker到最新版本1.21</li>
+									        <li>升级bootstrap-fileinput到最新版本5.1.3</li>
+									        <li>升级bootstrapTable到最新版本v1.18.0</li>
+									        <li>升级bootstrapTable相关组件到最新版本v1.18.0</li>
+									        <li>升级oshi到最新版本v5.3.6</li>
+									        <li>新增示例(标签 & 提示)</li>
+									        <li>添加单据打印示例</li>
+									        <li>修改表格初始参数sortName默认值为undefined</li>
+									        <li>新增表格参数(自定义打印页面模板printPageBuilder)</li>
+									        <li>新增表格参数(是否显示行间隔色striped)</li>
+									        <li>新增表格参数(渲染完成后执行的事件onPostBody)</li>
+									        <li>Excel注解支持Image图片导出</li>
+									        <li>Excel支持注解align对齐方式</li>
+									        <li>Excel支持导入Boolean型数据</li>
+									        <li>主子表操作添加通用addColumn方法</li>
+									        <li>代码生成日期控件区分范围</li>
+									        <li>代码生成数据库文本类型生成表单文本域</li>
+									        <li>修复生成主子表外键名错误</li>
+									        <li>选项卡新增是否刷新属性</li>
+									        <li>修复树表格表头跟表格宽度不同步的问题</li>
+									        <li>表格树加载完成触发tooltip方法</li>
+									        <li>使用widthUnit定义树表格选项单位</li>
+									        <li>修复主子表editColumn序列问题</li>
+									        <li>修复添加全屏在无参数时没有替换url参数问题</li>
+									        <li>弹出层openOptions移动端自适应</li>
+									        <li>防止错误页返回主页出现嵌套问题</li>
+									        <li>设置回显数据字典验证防止空值</li>
+									        <li>其他细节优化</li>
+										</ol>
+									</div>
+								</div>
+							</div>
+                            <div class="panel panel-default">
+								<div class="panel-heading">
+								   <h5 class="panel-title">
+									   <a data-toggle="collapse" data-parent="#version" href="#v451">v4.5.1</a><code class="pull-right">2020.11.18</code>
+								   </h5>
+								</div>
+								<div id="v451" class="panel-collapse collapse">
+									<div class="panel-body">
+									   <ol>
+									        <li>阻止任意文件下载漏洞</li>
+									        <li>升级shiro到最新版1.7.0 阻止权限绕过漏洞</li>
+									        <li>升级druid到最新版本v1.2.2</li>
+									        <li>新增表格行触发事件(onCheck、onUncheck、onCheckAll、onUncheckAll)</li>
+									        <li>修复多页签关闭非当前选项出现空白问题</li>
+									        <li>代码生成预览支持高亮显示</li>
+									        <li>mapperLocations配置支持分隔符</li>
+									        <li>权限信息调整</li>
+									        <li>个人中心头像和上传头像增加默认图片</li>
+									        <li>全局配置类保持和其他应用命名相同</li>
+										</ol>
+									</div>
+								</div>
+							</div>
+                            <div class="panel panel-default">
+								<div class="panel-heading">
+								   <h5 class="panel-title">
+									   <a data-toggle="collapse" data-parent="#version" href="#v45">v4.5.0</a><code class="pull-right">2020.10.20</code>
+								   </h5>
+								</div>
+								<div id="v45" class="panel-collapse collapse">
+									<div class="panel-body">
+									   <ol>
+									        <li>新增菜单导航显示风格(default为左侧导航菜单,topnav为顶部导航菜单)</li>
+									        <li>菜单&数据权限新增(展开/折叠 全选/全不选 父子联动)</li>
+									        <li>账号密码支持自定义更新周期</li>
+									        <li>初始密码支持自定义修改策略</li>
+									        <li>新增校验用户修改新密码不能与旧密码相同</li>
+									        <li>添加检查密码范围支持的特殊字符包括:~!@#$%^&*()-=_+</li>
+									        <li>注册账号设置默认用户名称及密码最后更新时间</li>
+									        <li>去除用户手机邮箱部门必填验证</li>
+									        <li>新增日期格式化方法</li>
+									        <li>代码生成添加bit类型</li>
+									        <li>树结构加载添加callBack回调方法</li>
+									        <li>修复用户管理页面滚动返回顶部条失效</li>
+									        <li>修复代码生成模板文件上传组件缺少ctx的问题</li>
+									        <li>限制系统内置参数不允许删除</li>
+									        <li>新增表格列宽拖动插件</li>
+									        <li>新增Ajax局部刷新demo</li>
+									        <li>新增是否开启页脚功能</li>
+									        <li>新增表格参数(通过自定义函数设置标题样式headerStyle)</li>
+									        <li>新增表格参数(通过自定义函数设置页脚样式footerStyle)</li>
+									        <li>修复窗体大小改变后浮动提示框失效问题</li>
+									        <li>生成代码补充必填样式</li>
+									        <li>生成页面时不忽略remark属性</li>
+									        <li>字典数据列表页添加关闭按钮</li>
+									        <li>Excel注解支持自动统计数据总和</li>
+									        <li>升级springboot到2.1.17 提升安全性</li>
+									        <li>升级pagehelper到最新版1.3.0</li>
+									        <li>升级druid到最新版本v1.2.1</li>
+									        <li>升级fastjson到最新版1.2.74</li>
+									        <li>升级bootstrap-fileinput到最新版本5.1.2</li>
+									        <li>升级oshi到最新版本v5.2.5</li>
+									        <li>表单向导插件更换为jquery-smartwizard</li>
+									        <li>修改主子表提交示例代码防止渲染失效</li>
+									        <li>添加导入数据弹出窗体自定义宽高</li>
+									        <li>用户信息参数返回忽略掉密码字段</li>
+									        <li>优化关闭窗体添加index参数</li>
+									        <li>回显数据字典(字符串数组)增加空值判断</li>
+									        <li>修改前端密码长度校验和错误提示不符问题</li>
+									        <li>AjaxResult重写put方法,以方便链式调用</li>
+									        <li>增强验证码校验的语义,更易懂</li>
+									        <li>导入excel整形值校验优化</li>
+									        <li>Excel导出类型NUMERIC支持精度浮点类型</li>
+									        <li>导出Excel调整targetAttr获取值方法,防止get方法不规范</li>
+									        <li>输入框组验证错误后置图标提示颜色</li>
+									        <li>上传媒体类型添加视频格式</li>
+									        <li>数据权限判断参数类型</li>
+									        <li>修正数据库字符串类型nvarchar</li>
+									        <li>优化递归子节点</li>
+									        <li>修复多表格搜索formId无效</li>
+									        <li>其他细节优化</li>
+										</ol>
+									</div>
+								</div>
+							</div>
+                            <div class="panel panel-default">
+								<div class="panel-heading">
+								   <h5 class="panel-title">
+									   <a data-toggle="collapse" data-parent="#version" href="#v44">v4.4.0</a><code class="pull-right">2020.08.24</code>
+								   </h5>
+								</div>
+								<div id="v44" class="panel-collapse collapse">
+									<div class="panel-body">
+									   <ol>
+									        <li>升级bootstrapTable到最新版本1.17.1</li>
+									        <li>升级shiro到最新版1.6.0 阻止权限绕过漏洞</li>
+									        <li>升级fastjson到最新版1.2.73</li>
+									        <li>代码生成支持同步数据库</li>
+									        <li>代码生成支持富文本控件</li>
+									        <li>用户密码支持自定义配置规则</li>
+									        <li>新增表格自动刷新插件</li>
+									        <li>新增表格打印配置插件</li>
+									        <li>更换图片裁剪工具为cropper</li>
+									        <li>Excel支持sort导出排序</li>
+									        <li>代码生成支持自定义路径</li>
+									        <li>代码生成支持选择上级菜单</li>
+									        <li>代码生成支持上传控件</li>
+									        <li>新增表格参数(自定义加载文本的字体大小loadingFontSize)</li>
+									        <li>Excel注解支持设置BigDecimal精度&舍入规则</li>
+									        <li>操作日志记录排除敏感属性字段</li>
+									        <li>修复不同浏览器附件下载中文名乱码的问题</li>
+									        <li>用户分配角色不允许选择超级管理员角色</li>
+									        <li>更换表格冻结列插件</li>
+									        <li>添加右侧冻结列示例</li>
+									        <li>升级表格行编辑&移动端适应插件</li>
+									        <li>修复更新表格插件后无法设置实例配置问题</li>
+									        <li>修复更新表格插件后导致的主子表错误</li>
+									        <li>修复页面存在多表格,回调函数res数据不正确问题</li>
+									        <li>强退&过期清理登录帐号缓存会话</li>
+									        <li>表格树标题内容支持html语义化标签</li>
+									        <li>修复配置应用的访问路径首页页签重复问题</li>
+									        <li>优化openTab打开时滚动到当前页签</li>
+									        <li>表格请求方式method支持自定义配置</li>
+									        <li>菜单页签联动优化</li>
+									        <li>用户邮箱长度限制修改为50</li>
+									        <li>主子表示例添加日期格式案例</li>
+									        <li>修改表格行内编辑示例旧值参数</li>
+									        <li>操作日志查询方式调整</li>
+									        <li>唯一限制条件只返回单条数据</li>
+									        <li>修改Excel设置STRING单元格类型</li>
+									        <li>添加获取当前的环境配置方法</li>
+									        <li>截取返回参数长度,防止超出异常</li>
+									        <li>定时任务cron表达式验证</li>
+									        <li>拆分表格插件,按需引入</li>
+									        <li>多行文本框补齐必填错误提示背景</li>
+									        <li>其他细节优化</li>
+										</ol>
+									</div>
+								</div>
+							</div>
+                            <div class="panel panel-default">
+								<div class="panel-heading">
+								   <h5 class="panel-title">
+									   <a data-toggle="collapse" data-parent="#version" href="#v431">v4.3.1</a><code class="pull-right">2020.07.05</code>
+								   </h5>
+								</div>
+								<div id="v431" class="panel-collapse collapse">
+									<div class="panel-body">
+									   <ol>
+									        <li>国家信息安全漏洞(请务必保持cipherKey密钥唯一性)</li>
+									        <li>升级shiro到最新版1.5.3 阻止权限绕过漏洞</li>
+									        <li>修改验证码在使用后清除,防止多次使用</li>
+									        <li>检查字符支持小数点&降级改成异常提醒</li>
+									        <li>openOptions函数中加入自定义maxmin属性</li>
+									        <li>支持openOptions方法最大化</li>
+									        <li>支持openOptions方法多个按钮回调</li>
+									        <li>新增isLinkage支持页签与菜单联动</li>
+									        <li>修改代码生成导入表结构出现异常页面不提醒问题</li>
+									        <li>优化用户头像发生错误,则显示一个默认头像</li>
+									        <li>Excel导出支持字典类型</li>
+										</ol>
+									</div>
+								</div>
+							</div>
+                            <div class="panel panel-default">
+								<div class="panel-heading">
+								   <h5 class="panel-title">
+									   <a data-toggle="collapse" data-parent="#version" href="#v43">v4.3.0</a><code class="pull-right">2020.06.22</code>
+								   </h5>
+								</div>
+								<div id="v43" class="panel-collapse collapse">
+									<div class="panel-body">
+									   <ol>
+									        <li>代码生成模板支持主子表</li>
+									        <li>代码生成显示类型支持复选框</li>
+									        <li>前端表单样式修改成圆角</li>
+									        <li>新增回显数据字典(字符串数组)</li>
+									        <li>修复浏览器手动缩放比例后菜单无法自适应问题</li>
+									        <li>限制用户不允许选择系统管理员角色</li>
+									        <li>用户信息添加输入框组图标&鼠标按下显示密码</li>
+									        <li>升级fastjson到最新版1.2.70 修复高危安全漏洞</li>
+									        <li>升级Bootstrap版本到v3.3.7</li>
+									        <li>修复selectColumns方法获取子对象数据无效问题</li>
+									        <li>修改数据源类型优先级,先根据方法,再根据类</li>
+									        <li>修改上级部门(选择项排除本身和下级)</li>
+									        <li>首页菜单显示调整</li>
+									        <li>添加是否开启swagger配置</li>
+									        <li>新增示例(主子表提交)</li>
+									        <li>新增示例(多级联动下拉示例)</li>
+									        <li>新增示例(表格属性data数据加载)</li>
+									        <li>新增表格列参数(是否列选项可见ignore)</li>
+									        <li>新增表格参数(是否启用显示卡片视图cardView)</li>
+									        <li>新增表格参数(是否显示全屏按钮showFullscreen)</li>
+									        <li>新增表格参数(是否启用分页条无限循环的功能paginationLoop)</li>
+									        <li>新增表格参数(是否显示表头showHeader)</li>
+									        <li>表格添加显示/隐藏所有列方法 showAllColumns/hideAllColumns</li>
+									        <li>修复部分情况节点不展开问题</li>
+									        <li>修复关闭标签页后刷新还是上次地址问题</li>
+									        <li>修复选择菜单后刷新页面,菜单箭头显示不对问题</li>
+											<li>修复jquery表单序列化时复选框未选中不会序列化到对象中问题</li>
+											<li>Excel支持readConverterExp读取字符串组内容</li>
+									        <li>更换IP地址查询接口</li>
+									        <li>默认关闭获取ip地址</li>
+									        <li>操作处理ajaxSuccess判断修正</li>
+									        <li>HttpUtils.sendPost()方法,参数无需拼接参数到url</li>
+									        <li>通用http发送方法增加参数 contentType 编码类型</li>
+									        <li>HTML过滤器不替换&实体</li>
+									        <li>代码生成浮点型改用BigDecimal</li>
+									        <li>修复表单构建单选和多选框渲染问题</li>
+									        <li>代码生成模板调整,字段为String并且必填则加空串条件</li>
+									        <li>字典数据查询列表根据dictSort升序排序</li>
+									        <li>修复树表对imageView和tooltip方法无效问题</li>
+									        <li>修复Long类型比较相等问题调整</li>
+									        <li>示例demo页面清除html链接,防止点击后跳转出现404</li>
+									        <li>在线用户强退方法合并</li>
+									        <li>添加校验部门包含未停用的子部门</li>
+									        <li>取消回车自动提交表单</li>
+									        <li>'A','I','BUTTON' 标签忽略clickToSelect事件,防止点击操作按钮时选中</li>
+									        <li>邮箱显示截取部分字符串,防止低分辨率错位</li>
+									        <li>代码生成列属性根据sort排序</li>
+									        <li>修复更多操作部分浏览器不兼容情况</li>
+									        <li>图片预览事件属性修正</li>
+									        <li>修复冻结列排序样式无效问题</li>
+									        <li>修复context-path的情况下个人中心刷新导致样式问题</li>
+									        <li>全屏editFull打开适配表树</li>
+									        <li>其他细节优化</li>
+										</ol>
+									</div>
+								</div>
+							</div>
+                            <div class="panel panel-default">
+								<div class="panel-heading">
+								   <h5 class="panel-title">
+									   <a data-toggle="collapse" data-parent="#version" href="#v42">v4.2.0</a><code class="pull-right">2020.03.23</code>
+								   </h5>
+								</div>
+								<div id="v42" class="panel-collapse collapse">
+									<div class="panel-body">
+									   <ol>
+									        <li>用户管理添加分配角色页面</li>
+									        <li>定时任务添加调度日志按钮</li>
+									        <li>新增是否开启用户注册功能</li>
+											<li>新增页面滚动显示返回顶部按钮</li>
+											<li>用户&角色&任务添加更多操作按钮</li>
+											<li>iframe框架页会话过期弹出超时提示</li>
+											<li>移动端登录不显示左侧菜单</li>
+											<li>侧边栏添加一套深蓝色主题</li>
+											<li>首页logo固定,不随菜单滚动</li>
+											<li>支持mode配置history(表示去掉地址栏的#)</li>
+											<li>任务分组字典翻译(调度日志详细)</li>
+											<li>字典管理添加缓存读取</li>
+											<li>字典数据列表标签显示样式</li>
+											<li>参数管理支持缓存操作</li>
+											<li>日期控件清空结束时间设置开始默认值为2099-12-31</li>
+											<li>表格树添加获取数据后响应回调处理</li>
+											<li>批量替换表前缀调整</li>
+											<li>支持表格导入模板的弹窗表单加入其它输入控件</li>
+											<li>表单重置刷新表格树</li>
+											<li>新增支持导出数据字段排序</li>
+											<li>新增表格参数(是否单选checkbox)</li>
+											<li>druid未授权不允许访问</li>
+											<li>表格树父节点兼容0,'0','',null</li>
+											<li>表单必填的项添加星号</li>
+											<li>修复select2不显示校验错误信息</li>
+											<li>添加自定义HTML过滤器</li>
+											<li>修复多数据源下开关关闭出现异常问题</li>
+											<li>修复翻页记住选择项数据问题</li>
+											<li>用户邮箱长度限制20</li>
+											<li>修改错误页面返回主页出现嵌套问题</li>
+											<li>表格浮动提示单双引号转义</li>
+											<li>支持配置四级菜单</li>
+											<li>升级shiro到最新版1.4.2 阻止rememberMe漏洞攻击</li>
+											<li>升级summernote到最新版本v0.8.12</li>
+											<li>导入Excel根据dateFormat属性格式处理</li>
+											<li>修复War部署无法正常shutdown,ehcache内存泄漏</li>
+											<li>修复代码生成短字段无法识别问题</li>
+											<li>修复serviceImpl模版,修改方法判断日期错误</li>
+											<li>代码生成模板增加导出功能日志记录</li>
+											<li>代码生成唯一编号调整为tableId</li>
+											<li>代码生成查询时忽略大小写</li>
+											<li>代码生成支持翻页记住选中</li>
+											<li>代码生成表注释未填写也允许导入</li>
+											<li>Global全局配置类修改为注解,防止多环境配置下读取问题</li>
+											<li>修复多表格情况下,firstLoad只对第一个表格生效</li>
+											<li>处理Maven打包出现警告问题</li>
+											<li>默认主题样式,防止网速慢情况下出现空白</li>
+											<li>修复文件上传多级目录识别问题</li>
+											<li>锚链接解码url,防止中文导致页面不能加载问题</li>
+											<li>修复右键Tab页刷新事件重复请求问题</li>
+											<li>角色禁用&菜单隐藏不查询权限</li>
+											<li>其他细节优化</li>
+										</ol>
+									</div>
+								</div>
+							</div>
+                            <div class="panel panel-default">
+								<div class="panel-heading">
+								   <h5 class="panel-title">
+									   <a data-toggle="collapse" data-parent="#version" href="#v41">v4.1.0</a><code class="pull-right">2019.10.22</code>
+								   </h5>
+								</div>
+								<div id="v41" class="panel-collapse collapse">
+									<div class="panel-body">
+									   <ol>
+									        <li>支持多表格实例操作</li>
+									        <li>浮动提示方法tooltip支持弹窗</li>
+											<li>代码生成&字典数据支持模糊条件查询</li>
+											<li>增加页签全屏方法</li>
+											<li>增加清除表单验证错误信息方法</li>
+											<li>支持iframe局部刷新页面</li>
+											<li>支持在线切换主题</li>
+											<li>修改图片预览设置的高宽参数颠倒问题</li>
+											<li>操作日志新增解锁账户功能</li>
+											<li>管理员用户&角色不允许操作</li>
+											<li>去掉jsoup包调用自定义转义工具</li>
+											<li>添加时间轴示例</li>
+											<li>修复翻页记住选择时获取指定列值的问题</li>
+											<li>代码生成sql脚本添加导出按钮</li>
+											<li>添加表格父子视图示例</li>
+											<li>添加表格行内编辑示例</li>
+											<li>升级fastjson到最新版1.2.60 阻止漏洞攻击</li>
+											<li>升级echarts到最新版4.2.1</li>
+											<li>操作日志新增返回参数</li>
+											<li>支持mybatis通配符扫描任意多个包</li>
+											<li>权限验证多种情况处理</li>
+											<li>修复树形类型的代码生成的部分必要属性无法显示</li>
+											<li>修复非表格插件情况下重置出现异常</li>
+											<li>修复富文本编辑器有序列表冲突</li>
+											<li>代码生成表前缀配置支持多个</li>
+											<li>修复自动去除表前缀配置无效问题</li>
+											<li>菜单列表按钮数据可见不显示(权限标识控制)</li>
+											<li>修复设置会话超时时间无效问题</li>
+											<li>新增本地资源通用下载方法</li>
+											<li>操作日志记录新增请求方式</li>
+											<li>代码生成单选按钮属性重名修复</li>
+											<li>优化select2下拉框宽度不会随浏览器改变</li>
+											<li>修复代码生成树表异常</li>
+											<li>其他细节优化</li>
+										</ol>
+									</div>
+								</div>
+							</div>
+                            <div class="panel panel-default">
+								<div class="panel-heading">
+								   <h5 class="panel-title">
+									   <a data-toggle="collapse" data-parent="#version" href="#v40">v4.0.0</a><code class="pull-right">2019.08.08</code>
+								   </h5>
+								</div>
+								<div id="v40" class="panel-collapse collapse">
+									<div class="panel-body">
+									   <ol>
+									        <li>代码生成支持预览、编辑,保存方案</li>
+									        <li>新增防止表单重复提交注解</li>
+											<li>新增后端校验(和前端保持一致)</li>
+											<li>新增同一个用户最大会话数控制</li>
+											<li>Excel导出子对象支持多个字段</li>
+											<li>定时任务支持静态调用和多参数</li>
+											<li>定时任务增加分组条件查询</li>
+											<li>字典类型增加任务分组数据</li>
+											<li>新增表格是否首次加载数据</li>
+											<li>新增parentTab选项卡可在同一页签打开</li>
+											<li>多数据源支持类注解(允许继承父类的注解)</li>
+											<li>部门及以下数据权限(调整为以下及所有子节点)</li>
+											<li>新增角色数据权限配(仅本人数据权限)</li>
+											<li>修改菜单权限显示问题</li>
+											<li>上传文件修改路径及返回名称</li>
+											<li>添加报表插件及示例</li>
+											<li>添加首页统计模板</li>
+											<li>添加表格拖拽示例</li>
+											<li>添加卡片列表示例</li>
+											<li>添加富文本编辑器示例</li>
+											<li>添加表格动态增删改查示例</li>
+											<li>添加用户页面岗位选择框提示</li>
+											<li>点击菜单操作添加背景高亮显示</li>
+											<li>表格树新增showSearch是否显示检索信息</li>
+											<li>解决表格列设置sortName无效问题</li>
+											<li>表格图片预览支持自定义设置宽高</li>
+											<li>添加表格列浮动提示(单击文本复制)</li>
+											<li>PC端收起菜单后支持浮动显示</li>
+											<li>详细操作样式调整</li>
+											<li>修改用户更新描述空串不更新问题</li>
+											<li>导入修改为模板渲染</li>
+											<li>修改菜单及部门排序规则</li>
+											<li>角色导出数据范围表达式翻译</li>
+											<li>添加summernote富文本字体大小</li>
+											<li>优化表格底部下边框防重叠&汇总像素问题</li>
+											<li>树表格支持属性多层级访问</li>
+											<li>修复IE浏览器用户管理界面右侧留白问题</li>
+											<li>重置按钮刷新表格</li>
+											<li>重置密码更新用户缓存</li>
+											<li>优化验证码属性参数</li>
+											<li>支持数据监控配置用户名和密码</li>
+											<li>文件上传修改按钮背景及加载动画</li>
+											<li>支持配置一级菜单href跳转</li>
+											<li>侧边栏添加一套浅色主题</li>
+											<li>树表格添加回调函数(校验异常状态)</li>
+											<li>用户个人中心适配手机端显示</li>
+											<li>Excel支持设置导出类型&更换样式</li>
+											<li>检查属性改变修改为克隆方式(防止热部署强转异常)</li>
+											<li>其他细节优化</li>
+										</ol>
+									</div>
+							    </div>
+							</div>
+                            <div class="panel panel-default">
+								<div class="panel-heading">
+								   <h5 class="panel-title">
+									   <a data-toggle="collapse" data-parent="#version" href="#v34">v3.4.0</a><code class="pull-right">2019.06.03</code>
+								   </h5>
+								</div>
+								<div id="v34" class="panel-collapse collapse">
+									<div class="panel-body">
+									   <ol>
+									        <li>新增实例演示菜单及demo</li>
+											<li>新增页签右键操作</li>
+											<li>菜单管理新增打开方式</li>
+											<li>新增点击某行触发的事件</li>
+											<li>新增双击某行触发的事件</li>
+											<li>新增单击某格触发的事件</li>
+											<li>新增双击某格触发的事件</li>
+											<li>新增是否启用显示细节视图</li>
+											<li>支持上传任意格式文件</li>
+											<li>修复角色权限注解失效问题</li>
+											<li>左侧的菜单栏宽度调整</li>
+											<li>新增响应完成后自定义回调函数</li>
+											<li>支持前端及其他模块直接获取用户信息</li>
+											<li>升级swagger到最新版2.9.2</li>
+											<li>升级jquery.slimscroll到最新版1.3.8</li>
+											<li>升级select2到最新版4.0.7</li>
+											<li>新增角色配置本部门数据权限</li>
+											<li>新增角色配置本部门及以下数据权限</li>
+											<li>优化底部操作防止跳到页面顶端</li>
+											<li>修改冻结列选框无效及样式问题</li>
+											<li>修复部门四层级修改祖级无效问题</li>
+											<li>更换开关切换按钮样式</li>
+											<li>新增select2-bootstrap美化下拉框</li>
+											<li>添加表格内图片预览方法</li>
+											<li>修复权限校验失败跳转页面路径错误</li>
+											<li>国际化资源文件调整</li>
+											<li>通知公告布局调整</li>
+											<li>删除页签操作功能</li>
+											<li>表格树新增查询指定列值</li>
+											<li>更改系统接口扫描方式及完善测试案例</li>
+											<li>表格列浮动提示及字典回显默认去背景</li>
+											<li>修复启用翻页记住前面的选择check没选中问题</li>
+											<li>去除监控页面底部的广告</li>
+											<li>日期控件功问题修复及data功能增强</li>
+											<li>新增角色权限可见性(前端直接调用)</li>
+											<li>新增获取当前登录用户方法(前端及子模块调用)</li>
+											<li>修复热部署重启导致菜单丢失问题</li>
+											<li>优化业务校验失败普通请求跳转页面</li>
+											<li>操作日志新增状态条件查询</li>
+											<li>操作类型支持多选条件查询</li>
+											<li>通知公告防止滚动触底回弹优化</li>
+											<li>其他细节优化</li>
+										</ol>
+									</div>
+								</div>
+							 </div>
+                             <div class="panel panel-default">
+								<div class="panel-heading">
+								   <h5 class="panel-title">
+									   <a data-toggle="collapse" data-parent="#version" href="#v33">v3.3.0</a><code class="pull-right">2019.04.01</code>
+								   </h5>
+								</div>
+								<div id="v33" class="panel-collapse collapse">
+									<div class="panel-body">
+									   <ol>
+											<li>新增线程池统一管理</li>
+											<li>新增支持左右冻结列</li>
+											<li>新增表格字符超长浮动提示</li>
+											<li>升级datepicker拓展并汉化</li>
+											<li>升级druid到最新版本v1.1.14</li>
+											<li>修复个人头像为图片服务器跨域问题</li>
+											<li>修改上传文件按日期存储</li>
+											<li>新增表格客户端分页选项</li>
+											<li>新增表格的高度参数</li>
+											<li>新增表格销毁方法</li>
+											<li>新增表格下拉按钮切换方法</li>
+											<li>新增表格分页跳转到指定页码</li>
+											<li>新增表格启用点击选中行参数</li>
+											<li>修复表格数据重新加载未触发部分按钮禁用</li>
+											<li>使用jsonview展示操作日志参数</li>
+											<li>新增方法(addTab、editTab)</li>
+											<li>修改用户管理界面为Tab打开方式</li>
+											<li>表单验证代码优化</li>
+											<li>修复@Excel注解 prompt 属性使用报错</li>
+											<li>修复combo属性Excel兼容性问题</li>
+											<li>新增@Excel导入导出支持父类字段</li>
+											<li>修复关闭最后选项卡无法激活滚动问题</li>
+											<li>增加日期控件显示类型及回显格式扩展选项</li>
+											<li>修复定时任务执行失败后入库状态为成功状态</li>
+											<li>支持定时任务并发开关控制</li>
+											<li>优化权限校验失败普通请求跳转页面</li>
+											<li>捕获线程池执行任务抛出的异常</li>
+											<li>修复IE浏览器导出功能报错</li>
+											<li>新增角色管理分配用户功能</li>
+											<li>新增表格翻页记住前面的选择</li>
+											<li>调整用户个人中心页面</li>
+											<li>修复界面存在的一些安全问题</li>
+											<li>其他细节优化</li>
+										</ol>
+									</div>
+								</div>
+							</div>
+                            <div class="panel panel-default">
+								<div class="panel-heading">
+								   <h5 class="panel-title">
+									   <a data-toggle="collapse" data-parent="#version" href="#v32">v3.2.0</a><code class="pull-right">2019.01.18</code>
+								   </h5>
+								</div>
+								<div id="v32" class="panel-collapse collapse">
+									<div class="panel-body">
+									   <ol>
+											<li>部门修改时不允许选择最后节点</li>
+											<li>修复部门菜单排序字段无效</li>
+											<li>修复光驱磁盘导致服务监控异常</li>
+											<li>登录界面去除check插件</li>
+											<li>验证码文本字符间距修正</li>
+											<li>升级SpringBoot到最新版本2.1.1</li>
+											<li>升级MYSQL驱动</li>
+											<li>修正登录必填项位置偏移</li>
+											<li>Session会话检查优化</li>
+											<li>Excel注解支持多级获取</li>
+											<li>新增序列号生成方法</li>
+											<li>修复WAR部署tomcat退出线程异常</li>
+											<li>全屏操作增加默认确认/关闭</li>
+											<li>修复个人信息可能导致漏洞</li>
+											<li>字典数据根据下拉选择新增类型</li>
+											<li>升级Summernote到最新版本v0.8.11</li>
+											<li>新增用户数据导入</li>
+											<li>首页主题样式更换</li>
+											<li>layer扩展主题更换</li>
+											<li>用户管理移动端默认隐藏左侧布局</li>
+											<li>详细信息弹出层显示在顶层</li>
+											<li>表格支持切换状态(用户/角色/定时任务)</li>
+											<li>Druid数据源支持配置继承</li>
+											<li>修正部分iPhone手机端表格适配问题</li>
+											<li>新增防止重复提交表单方法</li>
+											<li>新增表格数据统计汇总方法</li>
+											<li>支持富文本上传图片文件</li>
+										</ol>
+									</div>
+								</div>
+							</div>
+                            <div class="panel panel-default">
+								<div class="panel-heading">
+								   <h5 class="panel-title">
+									   <a data-toggle="collapse" data-parent="#version" href="#v31">v3.1.0</a><code class="pull-right">2018.12.03</code>
+								   </h5>
+								</div>
+								<div id="v31" class="panel-collapse collapse">
+									<div class="panel-body">
+									   <ol>
+											<li>新增内网不获取IP地址</li>
+											<li>新增cron表达式有效校验</li>
+											<li>定时任务新增详细信息</li>
+											<li>定时任务默认策略修改(不触发立即执行)</li>
+											<li>定时任务显示下一个执行周期</li>
+											<li>支持前端任意日期格式处理</li>
+											<li>上传头像删除多余提交按钮</li>
+											<li>表格增加行间隔色配置项</li>
+											<li>表格增加转义HTML字符串配置项</li>
+											<li>表格增加显示/隐藏指定列</li>
+											<li>代码生成优化</li>
+											<li>操作日志参数格式化显示</li>
+											<li>页签新增新增全屏显示</li>
+											<li>新增一键打包部署</li>
+											<li>Excel注解新增多个参数</li>
+											<li>新增提交静默更新表格方法</li>
+											<li>新增服务监控菜单</li>
+										</ol>
+									</div>
+								</div>
+							</div>
+							<div class="panel panel-default">
+								<div class="panel-heading">
+								   <h5 class="panel-title">
+									   <a data-toggle="collapse" data-parent="#version" href="#v30">v3.0.0</a><code class="pull-right">2018.10.08</code>
+								   </h5>
+								</div>
+								<div id="v30" class="panel-collapse collapse">
+									<div class="panel-body">
+									   <ol>
+											<li>升级poi到最新版3.17</li>
+											<li>导出修改临时目录绝对路径</li>
+											<li>升级laydate到最新版5.0.9</li>
+											<li>升级SpringBoot到最新版本2.0.5</li>
+											<li>优化开始/结束时间校验限制</li>
+											<li>重置密码参数表中获取默认值</li>
+											<li>修复头像修改显示问题</li>
+											<li>新增数据权限过滤注解</li>
+											<li>新增表格检索折叠按钮</li>
+											<li>新增清空(登录、操作、调度)日志</li>
+											<li>固定按钮位置(提交/关闭)</li>
+											<li>部门/菜单支持(展开/折叠)</li>
+											<li>部分细节调整优化</li>
+											<li>项目采用分模块</li>
+										</ol>
+									</div>
+								</div>
+							</div>
+							<div class="panel panel-default">
+								<div class="panel-heading">
+								   <h5 class="panel-title">
+									   <a data-toggle="collapse" data-parent="#version" href="#v24">v2.4.0</a><code class="pull-right">2018.09.03</code>
+								   </h5>
+								</div>
+								<div id="v24" class="panel-collapse collapse">
+									<div class="panel-body">
+									   <ol>
+											<li>支持部门多级查询</li>
+											<li>修复菜单状态查询无效</li>
+											<li>支持IP地址开关</li>
+											<li>支持XSS开关</li>
+											<li>记录日志异步处理</li>
+											<li>字典回显样式更改为下拉框</li>
+											<li>菜单类型必填校验</li>
+											<li>修复在线用户排序报错</li>
+											<li>增加重置按钮</li>
+											<li>支持注解导入数据</li>
+											<li>支持弹层外区域关闭</li>
+											<li>备注更换为文本区域</li>
+											<li>新增角色逻辑删除</li>
+											<li>新增部门逻辑删除</li>
+											<li>支持部门数据权限</li>
+											<li>管理员默认拥有所有授权</li>
+											<li>字典数据采用分页</li>
+											<li>部分细节调整优化</li>
+										</ol>
+									</div>
+								</div>
+							</div>
+                            <div class="panel panel-default">
+									<div class="panel-heading">
+									   <h5 class="panel-title">
+										   <a data-toggle="collapse" data-parent="#version" href="#v23">v2.3.0</a><code class="pull-right">2018.08.06</code>
+									   </h5>
+									</div>
+									<div id="v23" class="panel-collapse collapse">
+										<div class="panel-body">
+										   <ol>
+										        <li>支持表格不分页开关控制</li>
+										        <li>修改字典类型同步修改字典数据</li>
+										        <li>代码生成新增修改后缀处理</li>
+										        <li>代码生成新增实体toString</li>
+										        <li>代码生成非字符串去除!=''</li>
+												<li>导出数据前加载遮罩层</li>
+												<li>部门删除校验条件修改</li>
+												<li>搜索查询下载优化</li>
+												<li>手机打开弹出层自适应</li>
+												<li>角色岗位禁用显示置灰</li>
+												<li>角色禁用不显示菜单</li>
+												<li>新增导出权限</li>
+												<li>角色权限唯一校验</li>
+												<li>岗位名称编码唯一校验</li>
+                                                <li>TreeTable优化</li>
+                                                <li>支持多数据源</li>
+												<li>其他细节优化</li>
+											</ol>
+										</div>
+									</div>
+								</div>
+                                <div class="panel panel-default">
+									<div class="panel-heading">
+									   <h5 class="panel-title">
+										   <a data-toggle="collapse" data-parent="#version" href="#v22">v2.2.0</a><code class="pull-right">2018.07.23</code>
+									   </h5>
+									</div>
+									<div id="v22" class="panel-collapse collapse">
+										<div class="panel-body">
+										   <ol>
+										        <li>修复批量生成代码异常问题</li>
+										        <li>修复定时器保存失败问题</li>
+										        <li>修复热部署转换问题</li>
+												<li>支持查询菜单管理,部门管理</li>
+												<li>大多数功能支持时间查询</li>
+												<li>自定义导出注解自动匹配column</li>
+												<li>新增任务执行策略</li>
+												<li>操作详细动态显示类型</li>
+												<li>支持动态回显字典数据</li>
+												<li>后台代码优化调整</li>
+												<li>其他细节优化</li>
+											</ol>
+										</div>
+									</div>
+								</div>
+                                <div class="panel panel-default">
+									<div class="panel-heading">
+									   <h5 class="panel-title">
+										   <a data-toggle="collapse" data-parent="#version" href="#v21">v2.1.0</a><code class="pull-right">2018.07.10</code>
+									   </h5>
+									</div>
+									<div id="v21" class="panel-collapse collapse">
+										<div class="panel-body">
+										   <ol>
+										        <li>新增登录超时提醒</li>
+										        <li>修复定时器热部署转换问题</li>
+										        <li>修复登录验证码校验无效问题</li>
+												<li>定时任务新增立即执行一次</li>
+												<li>存在字典数据不允许删除字典</li>
+												<li>字典数据支持按名称查询</li>
+												<li>代码生成增加日志注解&表格优化</li>
+												<li>修复用户逻辑删除后能登录问题</li>
+												<li>表格支持多字段动态排序</li>
+												<li>支持三级菜单显示</li>
+												<li>新增ry.sh启动程序脚本</li>
+												<li>其他细节优化</li>
+											</ol>
+										</div>
+									</div>
+								</div>
+                            	<div class="panel panel-default">
+									<div class="panel-heading">
+									   <h5 class="panel-title">
+										   <a data-toggle="collapse" data-parent="#version" href="#v20">v2.0.0</a><code class="pull-right">2018.07.02</code>
+									   </h5>
+									</div>
+									<div id="v20" class="panel-collapse collapse">
+										<div class="panel-body">
+										   <ol>
+										        <li>升级SpringBoot到最新版本2.0.3</li>
+										        <li>新增公告管理</li>
+												<li>表单校验示提体验优化</li>
+												<li>前端通用方法封装调整</li>
+												<li>前端去除js文件,合并到html</li>
+												<li>操作加载遮罩层</li>
+												<li>支持全屏模式操作</li>
+												<li>支持注解导出数据</li>
+												<li>系统支持多查询&下载</li>
+												<li>系统样式调整</li>
+											</ol>
+										</div>
+									</div>
+								</div>
+                                <div class="panel panel-default">
+									<div class="panel-heading">
+									   <h5 class="panel-title">
+										   <a data-toggle="collapse" data-parent="#version" href="#v16">v1.1.6</a><code class="pull-right">2018.06.04</code>
+									   </h5>
+									</div>
+									<div id="v16" class="panel-collapse collapse">
+										<div class="panel-body">
+										   <ol>
+												<li>新增用户列表部门列</li>
+												<li>新增登录地点</li>
+												<li>新增swagger</li>
+												<li>修复排序数字校验</li>
+												<li>优化头像上传文件类型限定为图片</li>
+												<li>新增XSS过滤</li>
+												<li>新增热部署提高开发效率</li>
+												<li>修复treegrid居中无效</li>
+												<li>角色多条件查询</li>
+											</ol>
+										</div>
+									</div>
+								</div>
+                            	<div class="panel panel-default">
+									<div class="panel-heading">
+									   <h5 class="panel-title">
+										   <a data-toggle="collapse" data-parent="#version" href="#v15">v1.1.5</a><code class="pull-right">2018.05.28</code>
+									   </h5>
+									</div>
+									<div id="v15" class="panel-collapse collapse">
+										<div class="panel-body">
+										   <ol>
+												<li>优化登录失败刷新验证码</li>
+												<li>新增用户登录地址时间</li>
+												<li>修复ajax超时退出问题</li>
+												<li>新增html调用数据字典(若依首创)</li>
+												<li>调整系统部分样式</li>
+												<li>新增用户逻辑删除</li>
+												<li>新增管理员不允许删除修改</li>
+												<li>升级bootstrapTable到最新版本1.12.1</li>
+												<li>升级layer到最新版本3.1.1</li>
+											</ol>
+										</div>
+									</div>
+								</div>
+							    <div class="panel panel-default">
+									<div class="panel-heading">
+									   <h5 class="panel-title">
+										   <a data-toggle="collapse" data-parent="#version" href="#v14">v1.1.4</a><code class="pull-right">2018.05.20</code>
+									   </h5>
+									</div>
+									<div id="v14" class="panel-collapse collapse">
+										<div class="panel-body">
+										   <ol>
+												<li>新增参数管理</li>
+												<li>修复头像上传bug</li>
+												<li>手机邮箱唯一校验</li>
+												<li>支持手机邮箱登录</li>
+												<li>代码生成优化</li>
+												<li>支持模糊查询</li>
+												<li>支持切换主题皮肤</li>
+												<li>修改权限即时生效</li>
+												<li>修复页签Tab关闭问题</li>
+											</ol>
+										</div>
+									</div>
+								</div>
+								<div class="panel panel-default">
+									<div class="panel-heading">
+									   <h5 class="panel-title">
+										   <a data-toggle="collapse" data-parent="#version" href="#v13">v1.1.3</a><code class="pull-right">2018.05.14</code>
+									   </h5>
+									</div>
+									<div id="v13" class="panel-collapse collapse">
+										<div class="panel-body">
+										   <ol>
+												<li>新增验证码(数组计算、字符验证)</li>
+												<li>新增cookie记住我</li>
+												<li>新增头像上传</li>
+												<li>用户名密码长度限制</li>
+												<li>通用字段提取</li>
+												<li>支持自定义条件查询</li>
+												<li>部门名称必填、时间格式调整</li>
+												<li>其他细节优化</li>
+											</ol>
+										</div>
+									</div>
+								</div>
+								<div class="panel panel-default">
+									<div class="panel-heading">
+                                        <h5 class="panel-title">
+											<a data-toggle="collapse" data-parent="#version" href="#v12">v1.1.2</a><code class="pull-right">2018.05.07</code>
+										</h5>
+                                    </div>
+                                    <div id="v12" class="panel-collapse collapse">
+                                        <div class="panel-body">
+                                            <ol>
+                                            	<li>新增个人信息修改</li>
+												<li>菜单存在子菜单不允许删除</li>
+												<li>菜单分配角色不允许删除</li>
+												<li>角色分配人员不允许删除</li>
+												<li>岗位使用后不允许删除</li>
+												<li>保证用户的数据完整性加入事物</li>
+												<li>新增环境使用手册、数据建模</li>
+												<li>Thymeleaf升级到3.0</li>
+												<li>支持非ROOT部署</li>
+                                            </ol>
+                                        </div>
+                                    </div>
+                                </div>
+                                <div class="panel panel-default">
+									<div class="panel-heading">
+                                        <h5 class="panel-title">
+											<a data-toggle="collapse" data-parent="#version" href="#v11">v1.1.1</a><code class="pull-right">2018.04.23</code>
+										</h5>
+                                    </div>
+                                    <div id="v11" class="panel-collapse collapse">
+                                        <div class="panel-body">
+                                            <ol>
+                                            	<li>新增表单构建器</li>
+												<li>代码生成优化</li>
+												<li>支持新增主部门</li>
+												<li>支持选择上级部门、上级菜单</li>
+												<li>新增字典管理单条删除</li>
+												<li>优化一些其他细节</li>
+                                            </ol>
+                                        </div>
+                                    </div>
+                                </div>
+                                <div class="panel panel-default">
+									<div class="panel-heading">
+                                        <h5 class="panel-title">
+											<a data-toggle="collapse" data-parent="#version" href="#v10">v1.1.0</a><code class="pull-right">2018.04.20</code>
+										</h5>
+                                    </div>
+                                    <div id="v10" class="panel-collapse collapse">
+                                        <div class="panel-body">
+                                            <ol>
+                                            	<li>支持密码盐</li>
+												<li>支持新增主目录</li>
+												<li>支持批量生成代码</li>
+												<li>支持表格导出(csv、txt、doc、excel)</li>
+												<li>自动适应宽高模式窗体</li>
+												<li>重复校验(角色名、菜单名、部门名)</li>
+												<li>优化一些其他细节</li>
+                                            </ol>
+                                        </div>
+                                    </div>
+                                </div>
+                                <div class="panel panel-default">
+									<div class="panel-heading">
+                                        <h5 class="panel-title">
+											<a data-toggle="collapse" data-parent="#version" href="#v09">v1.0.9</a><code class="pull-right">2018.04.14</code>
+										</h5>
+                                    </div>
+                                    <div id="v09" class="panel-collapse collapse">
+                                        <div class="panel-body">
+                                            <ol>
+                                            	<li>新增代码生成(生成包括 java、html、js、xml、sql)</li>
+												<li>新增按钮权限控制隐藏(若依首创)</li>
+                                            </ol>
+                                        </div>
+                                    </div>
+                                </div>
+								<div class="panel panel-default">
+									<div class="panel-heading">
+                                        <h5 class="panel-title">
+											<a data-toggle="collapse" data-parent="#version" href="#v08">v1.0.8</a><code class="pull-right">2018.04.08</code>
+										</h5>
+                                    </div>
+                                    <div id="v08" class="panel-collapse collapse">
+                                        <div class="panel-body">
+                                            <ol>
+                                            	<li>新增定时任务(新增、修改、删除、查询、启动/暂停)</li>
+												<li>新增调度日志(查询、删除)</li>
+                                            </ol>
+                                        </div>
+                                    </div>
+                                </div>
+                            	<div class="panel panel-default">
+									<div class="panel-heading">
+                                        <h5 class="panel-title">
+											<a data-toggle="collapse" data-parent="#version" href="#v07">v1.0.7</a><code class="pull-right">2018.04.04</code>
+										</h5>
+                                    </div>
+                                    <div id="v07" class="panel-collapse collapse">
+                                        <div class="panel-body">
+                                            <ol>
+                                            	<li>新增岗位管理(新增、修改、删除、查询)</li>
+												<li>优化用户管理,菜单管理部分细节</li>
+                                            </ol>
+                                        </div>
+                                    </div>
+                                </div>
+								<div class="panel panel-default">
+									<div class="panel-heading">
+                                        <h5 class="panel-title">
+											<a data-toggle="collapse" data-parent="#version" href="#v06">v1.0.6</a><code class="pull-right">2018.03.15</code>
+										</h5>
+                                    </div>
+                                    <div id="v06" class="panel-collapse collapse">
+                                        <div class="panel-body">
+                                            <ol>
+                                            	<li>新增字典管理(新增、删除、修改、查询、数据选择)</li>
+												<li>新增用户密码重置</li>
+												<li>优化一些其他细节</li>
+                                            </ol>
+                                        </div>
+                                    </div>
+                                </div>
+								<div class="panel panel-default">
+									<div class="panel-heading">
+                                        <h5 class="panel-title">
+											<a data-toggle="collapse" data-parent="#version" href="#v05">v1.0.5</a><code class="pull-right">2018.03.12</code>
+										</h5>
+                                    </div>
+                                    <div id="v05" class="panel-collapse collapse">
+                                        <div class="panel-body">
+                                            <ol>
+                                            	<li>新增菜单管理(新增、删除、修改、查询、图标选择)</li>
+												<li>部门管理优化(添加责任人、联系电话、邮箱、修改者)</li>
+                                            </ol>
+                                        </div>
+                                    </div>
+                                </div>
+								<div class="panel panel-default">
+									<div class="panel-heading">
+                                        <h5 class="panel-title">
+											<a data-toggle="collapse" data-parent="#version" href="#v04">v1.0.4</a><code class="pull-right">2018.03.11</code>
+										</h5>
+                                    </div>
+                                    <div id="v04" class="panel-collapse collapse">
+                                        <div class="panel-body">
+                                            <ol>
+                                            	<li>新增角色管理(新增、删除、修改、查询、菜单选择)</li>
+                                            </ol>
+                                        </div>
+                                    </div>
+                                </div>
+								<div class="panel panel-default">
+									<div class="panel-heading">
+                                        <h5 class="panel-title">
+											<a data-toggle="collapse" data-parent="#version" href="#v03">v1.0.3</a><code class="pull-right">2018.03.08</code>
+										</h5>
+                                    </div>
+                                    <div id="v03" class="panel-collapse collapse">
+                                        <div class="panel-body">
+                                            <ol>
+                                            	<li>新增用户管理(新增、删除、修改、查询、部门选择)</li>
+                                            </ol>
+                                        </div>
+                                    </div>
+                                </div>
+                            	<div class="panel panel-default">
+									<div class="panel-heading">
+                                        <h5 class="panel-title">
+											<a data-toggle="collapse" data-parent="#version" href="#v02">v1.0.2</a><code class="pull-right">2018.03.04</code>
+										</h5>
+                                    </div>
+                                    <div id="v02" class="panel-collapse collapse">
+                                        <div class="panel-body">
+                                            <ol>
+                                            	<li>新增部门管理 (新增、删除、修改、查询)</li>
+                                            </ol>
+                                        </div>
+                                    </div>
+                                </div>
+                                <div class="panel panel-default">
+                                    <div class="panel-heading">
+                                        <h5 class="panel-title">
+											<a data-toggle="collapse" data-parent="#version" href="#v01">v1.0.1</a><code class="pull-right">2018.03.03</code>
+										</h5>
+                                    </div>
+                                    <div id="v01" class="panel-collapse collapse">
+                                        <div class="panel-body">
+                                            <ol>
+                                            	<li>新增在线用户 (批量强退、单条强退、查询)</li>
+                                                <li>新增登录日志 (批量删除、查询)</li>
+												<li>新增操作日志 (批量删除、查询、详细)</li>
+												<li>新增数据监控 (监控DB池连接和SQL的执行)</li>
+                                            </ol>
+                                        </div>
+                                    </div>
+                                </div>
+                                <div class="panel panel-default">
+                                    <div class="panel-heading">
+                                        <h4 class="panel-title">
+                                            <a data-toggle="collapse" data-parent="#version" href="#v00">v1.0.0</a><code class="pull-right">2018.03.01</code>
+                                        </h4>
+                                    </div>
+                                    <div id="v00" class="panel-collapse collapse">
+                                        <div class="panel-body">
+                                            <ol>
+                                                <li>若依管理系统正式发布。</li>
+                                            </ol>
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-4">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>捐赠</h5>
+                    </div>
+                    <div class="ibox-content">
+                        <div class="alert alert-warning">
+                            	请作者喝杯咖啡(点击图片放大)
+                        </div>
+                        <p id="pay-qrcode">
+                            <a href="javascript:;"><img th:src="@{/img/pay.png}" width="100%" alt="请使用手机支付宝或者微信扫码支付">
+                            </a>
+                        </p>
+
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <script th:src="@{/js/jquery.min.js}"></script>
+    <script th:src="@{/js/bootstrap.min.js}"></script>
+    <script th:src="@{/ajax/libs/layer/layer.min.js}"></script>
+    <script type="text/javascript">
+	    $('#pay-qrcode').click(function(){
+	        var html=$(this).html();
+	        parent.layer.open({
+	            title: false,
+	            type: 1,
+	            closeBtn:false,
+	            shadeClose:true,
+	            area: ['600px', '360px'],
+	            content: html
+	        });
+	    });
+    </script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/main_v1.html b/ruoyi-admin/src/main/resources/templates/main_v1.html
new file mode 100644
index 0000000..e9bf06d
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/main_v1.html
@@ -0,0 +1,336 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org">
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>统计</title>
+    <link rel="shortcut icon" href="favicon.ico">
+    <link href="../static/css/bootstrap.min.css" th:href="@{/css/bootstrap.min.css}" rel="stylesheet"/>
+    <link href="../static/css/font-awesome.min.css" th:href="@{/css/font-awesome.min.css}" rel="stylesheet"/>
+    <link href="../static/css/animate.min.css" th:href="@{/css/animate.min.css}" rel="stylesheet"/>
+    <link href="../static/css/style.min.css" th:href="@{/css/style.min.css}" rel="stylesheet"/>
+</head>
+
+<body class="gray-bg">
+    <div class="wrapper wrapper-content">
+
+        <div class="row">
+            <div class="col-sm-3">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <span class="label label-success pull-right">月</span>
+                        <h5>收入</h5>
+                    </div>
+                    <div class="ibox-content">
+                        <h1 class="no-margins">40 886,200</h1>
+                        <div class="stat-percent font-bold text-success">98% <i class="fa fa-bolt"></i>
+                        </div>
+                        <small>总收入</small>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-3">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <span class="label label-info pull-right">全年</span>
+                        <h5>订单</h5>
+                    </div>
+                    <div class="ibox-content">
+                        <h1 class="no-margins">275,800</h1>
+                        <div class="stat-percent font-bold text-info">20% <i class="fa fa-level-up"></i>
+                        </div>
+                        <small>新订单</small>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-3">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <span class="label label-primary pull-right">今天</span>
+                        <h5>访客</h5>
+                    </div>
+                    <div class="ibox-content">
+                        <h1 class="no-margins">106,120</h1>
+                        <div class="stat-percent font-bold text-navy">44% <i class="fa fa-level-up"></i>
+                        </div>
+                        <small>新访客</small>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-3">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <span class="label label-danger pull-right">最近一个月</span>
+                        <h5>活跃用户</h5>
+                    </div>
+                    <div class="ibox-content">
+                        <h1 class="no-margins">80,600</h1>
+                        <div class="stat-percent font-bold text-danger">38% <i class="fa fa-level-down"></i>
+                        </div>
+                        <small>12月</small>
+                    </div>
+                </div>
+            </div>
+        </div>
+        
+        <div class="row">
+            <div class="col-sm-12">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>订单</h5>
+                        <div class="pull-right">
+                            <div class="btn-group">
+                                <button type="button" class="btn btn-xs btn-white active">天</button>
+                                <button type="button" class="btn btn-xs btn-white">月</button>
+                                <button type="button" class="btn btn-xs btn-white">年</button>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="ibox-content">
+                        <div class="row">
+                            <div class="col-sm-9">
+                                <div class="flot-chart">
+                                    <div class="flot-chart-content" id="flot-dashboard-chart"></div>
+                                </div>
+                            </div>
+                            <div class="col-sm-3">
+                                <ul class="stat-list">
+                                    <li>
+                                        <h2 class="no-margins">2,346</h2>
+                                        <small>订单总数</small>
+                                        <div class="stat-percent">48% <i class="fa fa-level-up text-navy"></i>
+                                        </div>
+                                        <div class="progress progress-mini">
+                                            <div style="width: 48%;" class="progress-bar"></div>
+                                        </div>
+                                    </li>
+                                    <li>
+                                        <h2 class="no-margins ">4,422</h2>
+                                        <small>最近一个月订单</small>
+                                        <div class="stat-percent">60% <i class="fa fa-level-down text-navy"></i>
+                                        </div>
+                                        <div class="progress progress-mini">
+                                            <div style="width: 60%;" class="progress-bar"></div>
+                                        </div>
+                                    </li>
+                                    <li>
+                                        <h2 class="no-margins ">9,180</h2>
+                                        <small>最近一个月销售额</small>
+                                        <div class="stat-percent">22% <i class="fa fa-bolt text-navy"></i>
+                                        </div>
+                                        <div class="progress progress-mini">
+                                            <div style="width: 22%;" class="progress-bar"></div>
+                                        </div>
+                                    </li>
+                                 </ul>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+        
+        <div class="row">
+            <div class="col-sm-12">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>用户项目列表</h5>
+                        <div class="ibox-tools">
+                            <a class="collapse-link">
+                                <i class="fa fa-chevron-up"></i>
+                            </a>
+                            <a class="close-link">
+                                <i class="fa fa-times"></i>
+                            </a>
+                        </div>
+                    </div>
+                    <div class="ibox-content">
+                        <table class="table table-hover no-margins">
+                            <thead>
+                                <tr>
+                                    <th>状态</th>
+                                    <th>日期</th>
+                                    <th>用户</th>
+                                    <th>值</th>
+                                </tr>
+                            </thead>
+                            <tbody>
+                                <tr>
+                                    <td><small>进行中...</small>
+                                    </td>
+                                    <td><i class="fa fa-clock-o"></i> 11:20</td>
+                                    <td>青衣5858</td>
+                                    <td class="text-navy"> <i class="fa fa-level-up"></i> 24%</td>
+                                </tr>
+                                <tr>
+                                    <td><span class="label label-warning">已取消</span>
+                                    </td>
+                                    <td><i class="fa fa-clock-o"></i> 10:40</td>
+                                    <td>徐子崴</td>
+                                    <td class="text-navy"> <i class="fa fa-level-up"></i> 66%</td>
+                                </tr>
+                                <tr>
+                                    <td><small>进行中...</small>
+                                    </td>
+                                    <td><i class="fa fa-clock-o"></i> 01:30</td>
+                                    <td>姜岚昕</td>
+                                    <td class="text-navy"> <i class="fa fa-level-up"></i> 54%</td>
+                                </tr>
+                                <tr>
+                                    <td><small>进行中...</small>
+                                    </td>
+                                    <td><i class="fa fa-clock-o"></i> 02:20</td>
+                                    <td>武汉大兵哥</td>
+                                    <td class="text-navy"> <i class="fa fa-level-up"></i> 12%</td>
+                                </tr>
+                                <tr>
+                                    <td><small>进行中...</small>
+                                    </td>
+                                    <td><i class="fa fa-clock-o"></i> 09:40</td>
+                                    <td>荆莹儿</td>
+                                    <td class="text-navy"> <i class="fa fa-level-up"></i> 22%</td>
+                                </tr>
+                                <tr>
+                                    <td><span class="label label-primary">已完成</span>
+                                    </td>
+                                    <td><i class="fa fa-clock-o"></i> 04:10</td>
+                                    <td>栾某某</td>
+                                    <td class="text-navy"> <i class="fa fa-level-up"></i> 66%</td>
+                                </tr>
+                                <tr>
+                                    <td><small>进行中...</small>
+                                    </td>
+                                    <td><i class="fa fa-clock-o"></i> 12:08</td>
+                                    <td>范范范二妮</td>
+                                    <td class="text-navy"> <i class="fa fa-level-up"></i> 23%</td>
+                                </tr>
+                            </tbody>
+                        </table>
+                    </div>
+                </div>
+            </div>
+         </div>
+      </div>
+    </div>
+    <script th:src="@{/js/jquery.min.js}"></script>
+    <script th:src="@{/js/bootstrap.min.js}"></script>
+    <script th:src="@{/ajax/libs/flot/jquery.flot.js}"></script>
+    
+    <th:block th:include="include :: sparkline-js" />
+    <script type="text/javascript">
+	    $(document).ready(function () {
+	        var data2 = [
+	            [gd(2012, 1, 1), 7], [gd(2012, 1, 2), 6], [gd(2012, 1, 3), 4], [gd(2012, 1, 4), 8],
+	            [gd(2012, 1, 5), 9], [gd(2012, 1, 6), 7], [gd(2012, 1, 7), 5], [gd(2012, 1, 8), 4],
+	            [gd(2012, 1, 9), 7], [gd(2012, 1, 10), 8], [gd(2012, 1, 11), 9], [gd(2012, 1, 12), 6],
+	            [gd(2012, 1, 13), 4], [gd(2012, 1, 14), 5], [gd(2012, 1, 15), 11], [gd(2012, 1, 16), 8],
+	            [gd(2012, 1, 17), 8], [gd(2012, 1, 18), 11], [gd(2012, 1, 19), 11], [gd(2012, 1, 20), 6],
+	            [gd(2012, 1, 21), 6], [gd(2012, 1, 22), 8], [gd(2012, 1, 23), 11], [gd(2012, 1, 24), 13],
+	            [gd(2012, 1, 25), 7], [gd(2012, 1, 26), 9], [gd(2012, 1, 27), 9], [gd(2012, 1, 28), 8],
+	            [gd(2012, 1, 29), 5], [gd(2012, 1, 30), 8], [gd(2012, 1, 31), 25]
+	        ];
+	
+	        var data3 = [
+	            [gd(2012, 1, 1), 800], [gd(2012, 1, 2), 500], [gd(2012, 1, 3), 600], [gd(2012, 1, 4), 700],
+	            [gd(2012, 1, 5), 500], [gd(2012, 1, 6), 456], [gd(2012, 1, 7), 800], [gd(2012, 1, 8), 589],
+	            [gd(2012, 1, 9), 467], [gd(2012, 1, 10), 876], [gd(2012, 1, 11), 689], [gd(2012, 1, 12), 700],
+	            [gd(2012, 1, 13), 500], [gd(2012, 1, 14), 600], [gd(2012, 1, 15), 700], [gd(2012, 1, 16), 786],
+	            [gd(2012, 1, 17), 345], [gd(2012, 1, 18), 888], [gd(2012, 1, 19), 888], [gd(2012, 1, 20), 888],
+	            [gd(2012, 1, 21), 987], [gd(2012, 1, 22), 444], [gd(2012, 1, 23), 999], [gd(2012, 1, 24), 567],
+	            [gd(2012, 1, 25), 786], [gd(2012, 1, 26), 666], [gd(2012, 1, 27), 888], [gd(2012, 1, 28), 900],
+	            [gd(2012, 1, 29), 178], [gd(2012, 1, 30), 555], [gd(2012, 1, 31), 993]
+	        ];
+	
+	
+	        var dataset = [
+	            {
+	                label: "订单数",
+	                data: data3,
+	                color: "#1ab394",
+	                bars: {
+	                    show: true,
+	                    align: "center",
+	                    barWidth: 24 * 60 * 60 * 600,
+	                    lineWidth: 0
+	                }
+	
+	            }, {
+	                label: "付款数",
+	                data: data2,
+	                yaxis: 2,
+	                color: "#464f88",
+	                lines: {
+	                    lineWidth: 1,
+	                    show: true,
+	                    fill: true,
+	                    fillColor: {
+	                        colors: [{
+	                            opacity: 0.2
+	                        }, {
+	                            opacity: 0.2
+	                        }]
+	                    }
+	                },
+	                splines: {
+	                    show: false,
+	                    tension: 0.6,
+	                    lineWidth: 1,
+	                    fill: 0.1
+	                },
+	            }
+	        ];
+	
+	
+	        var options = {
+	            xaxis: {
+	                mode: "time",
+	                tickSize: [3, "day"],
+	                tickLength: 0,
+	                axisLabel: "Date",
+	                axisLabelUseCanvas: true,
+	                axisLabelFontSizePixels: 12,
+	                axisLabelFontFamily: 'Arial',
+	                axisLabelPadding: 10,
+	                color: "#838383"
+	            },
+	            yaxes: [{
+	                    position: "left",
+	                    max: 1070,
+	                    color: "#838383",
+	                    axisLabelUseCanvas: true,
+	                    axisLabelFontSizePixels: 12,
+	                    axisLabelFontFamily: 'Arial',
+	                    axisLabelPadding: 3
+	            }, {
+	                    position: "right",
+	                    clolor: "#838383",
+	                    axisLabelUseCanvas: true,
+	                    axisLabelFontSizePixels: 12,
+	                    axisLabelFontFamily: ' Arial',
+	                    axisLabelPadding: 67
+	            }
+	            ],
+	            legend: {
+	                noColumns: 1,
+	                labelBoxBorderColor: "#000000",
+	                position: "nw"
+	            },
+	            grid: {
+	                hoverable: false,
+	                borderWidth: 0,
+	                color: '#838383'
+	            }
+	        };
+	
+	        function gd(year, month, day) {
+	            return new Date(year, month - 1, day).getTime();
+	        }
+	
+	        var previousPoint = null,
+	            previousLabel = null;
+	
+	        $.plot($("#flot-dashboard-chart"), dataset, options);
+	    });
+    </script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/monitor/cache/cache.html b/ruoyi-admin/src/main/resources/templates/monitor/cache/cache.html
new file mode 100644
index 0000000..5e2bae3
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/monitor/cache/cache.html
@@ -0,0 +1,184 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+	<th:block th:include="include :: header('缓存监控')" />
+</head>
+<body class="gray-bg">
+    <div class="wrapper wrapper-content">
+        <input type="hidden" id="cacheName">
+        <div class="col-sm-12">
+            <div class="row">
+                <div class="col-sm-4">
+                    <div class="ibox float-e-margins">
+                        <div class="ibox-title">
+                            <h5><i class="fa fa-bars"></i> 缓存列表</h5>
+                            <div class="ibox-tools">
+                                <a href="javascript:getCacheNames()"><i class="fa fa-refresh"></i></a>
+                            </div>
+                        </div>
+                        <div class="ibox-content">
+                            <table class="table table-hover no-margins">
+                                <thead>
+                                    <tr>
+                                        <th></th>
+                                        <th>缓存名称</th>
+                                        <th>操作</th>
+                                    </tr>
+                                </thead>
+                                <tbody id="cacheNames">
+                                    <tr th:fragment="fragment-cache-names" th:each="cacheName, stat : ${cacheNames}">
+                                        <td>[[${stat.index + 1}]]</td>
+                                        <td style="word-wrap:break-word;word-break:break-all;" th:onclick="getCacheKeys([[${cacheName}]])">[[${cacheName}]]</td>
+                                        <td style="width: 50px"><a href="javascript:;" th:onclick="clearCacheName([[${cacheName}]])" title="清空"><i class="fa fa-trash-o text-danger"></i></a></td>
+                                    </tr>
+                                </tbody>
+                            </table>
+                        </div>
+                    </div>
+                </div>
+                <div class="col-sm-4">
+                    <div class="ibox float-e-margins">
+                        <div class="ibox-title">
+                            <h5><i class="fa fa-key"></i> 键名列表</h5>
+                            <div class="ibox-tools">
+                                <a href="javascript:getCacheKeys('', true)"><i class="fa fa-refresh"></i></a>
+                            </div>
+                        </div>
+                        <div class="ibox-content">
+                            <table class="table table-hover no-margins">
+                                <thead>
+                                    <tr>
+                                        <th></th>
+                                        <th>缓存键名</th>
+                                        <th>操作</th>
+                                    </tr>
+                                </thead>
+                                <tbody id="cacheKeys">
+                                    <tr th:fragment="fragment-cache-kyes" th:each="cacheKey, stat : ${cacheKeys}">
+                                        <td>[[${stat.index + 1}]]</td>
+                                        <td style="word-wrap:break-word;word-break:break-all;" th:onclick="getCacheValue([[${cacheName}]], [[${cacheKey}]])">[[${cacheKey}]]</td>
+                                        <td style="width: 50px"><a href="javascript:;" th:onclick="clearCacheKey([[${cacheName}]], [[${cacheKey}]])" title="清空"><i class="fa fa-trash-o text-danger"></i></a></td>
+                                    </tr>
+                                </tbody>
+                                </div>
+                            </table>
+                        </div>
+                    </div>
+                </div>
+                <div class="col-sm-4">
+                    <div class="ibox float-e-margins">
+                        <div class="ibox-title">
+                            <h5><i class="fa fa-file-text"></i> 缓存内容</h5>
+                            <div class="ibox-tools">
+                                <a href="javascript:clearAll()"><i class="fa fa-refresh"></i> 清理全部</a>
+                            </div>
+                        </div>
+                        <div class="ibox-content">
+	                        <div class="row" id="cacheValue">
+	                            <div class="col-sm-12" th:fragment="fragment-cache-value">
+	                                <div class="form-group">
+	                                    <label>缓存名称:</label>
+	                                    <input type="text" class="form-control" th:value="${cacheName}">
+	                                </div>
+	                                <div class="form-group">
+	                                    <label>缓存键名:</label>
+	                                    <input type="text"class="form-control" th:value="${cacheKey}">
+	                                </div>
+	                                <div class="form-group">
+	                                    <label>缓存内容:</label>
+	                                    <textarea class="form-control" style="height: 100px">[[${cacheValue}]]</textarea>
+	                                </div>
+	                            </div>
+	                        </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</body>
+<th:block th:include="include :: footer" />
+<script th:inline="javascript">
+var prefix = ctx + "monitor/cache";
+
+function getCacheNames() {
+    $.ajax({
+        type: "post",
+        url: prefix + "/getNames",
+        data: {
+            "fragment": 'fragment-cache-names'
+        },
+        success: function(data) {
+            $("#cacheNames").html(data);
+            $.modal.msgSuccess("刷新缓存列表成功");
+        }
+    });
+}
+
+function getCacheKeys(cacheName, isMsg) {
+	var _cacheName = $.common.isNotEmpty(cacheName) ? cacheName : $("#cacheName").val();
+    $.ajax({
+        type: "post",
+        url: prefix + "/getKeys",
+        data: {
+            "cacheName": _cacheName,
+            "fragment": 'fragment-cache-kyes'
+        },
+        success: function(data) {
+            $("#cacheKeys").html(data);
+            $("#cacheName").val(_cacheName);
+            if (isMsg) {
+                $.modal.msgSuccess("刷新键名列表成功");
+            }
+        }
+    });
+}
+
+function getCacheValue(cacheName, cacheKey) {
+    $.ajax({
+        type: "post",
+        url: prefix + "/getValue",
+        data: {
+            "cacheName": cacheName,
+            "cacheKey": cacheKey,
+            "fragment": 'fragment-cache-value'
+        },
+        success: function(data) {
+            $("#cacheValue").html(data);
+        }
+    });
+}
+
+function clearCacheName(cacheName){
+	$.post(prefix + "/clearCacheName", {cacheName: cacheName}, function(result) {
+		if (result.code == web_status.SUCCESS) {
+			$.modal.msgSuccess("清理缓存[" + cacheName + "]成功")
+			getCacheKeys(cacheName);
+        } else {
+            $.modal.msgError(result.msg);
+        }
+	});
+}
+
+function clearCacheKey(cacheName, cacheKey) {
+	$.post(prefix + "/clearCacheKey", {cacheName: cacheName, cacheKey: cacheKey}, function(result) {
+		if (result.code == web_status.SUCCESS) {
+			$.modal.msgSuccess("清理缓存[" + cacheKey + "]成功")
+			getCacheKeys(cacheName);
+        } else {
+            $.modal.msgError(result.msg);
+        }
+	});
+}
+
+function clearAll(){
+	$.get(prefix + "/clearAll", function(result) {
+		if (result.code == web_status.SUCCESS) {
+			$.modal.msgSuccess("清理全部缓存成功")
+        } else {
+            $.modal.msgError(result.msg);
+        }
+	});
+}
+</script>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/monitor/logininfor/logininfor.html b/ruoyi-admin/src/main/resources/templates/monitor/logininfor/logininfor.html
new file mode 100644
index 0000000..b484163
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/monitor/logininfor/logininfor.html
@@ -0,0 +1,146 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('登录日志列表')" />
+</head>
+<body class="gray-bg">
+	<div class="container-div">
+		<div class="row">
+			<div class="col-sm-12 search-collapse">
+				<form id="logininfor-form">
+					<div class="select-list">
+						<ul>
+							<li>
+								<label>登录地址:</label><input type="text" name="ipaddr"/>
+							</li>
+							<li>
+								<label>登录名称:</label><input type="text" name="loginName"/>
+							</li>
+							<li>
+								<label>登录状态:</label><select name="status" th:with="type=${@dict.getType('sys_common_status')}">
+									<option value="">所有</option>
+									<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
+								</select>
+							</li>
+							<li class="select-time">
+								<label>登录时间: </label>
+								<input type="text" class="time-input" id="startTime" placeholder="开始时间"/>
+								<span>-</span>
+								<input type="text" class="time-input" id="endTime" placeholder="结束时间"/>
+							</li>
+							<li>
+								<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
+								<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
+							</li>
+						</ul>
+					</div>
+				</form>
+			</div>
+			
+			<div class="btn-group-sm" id="toolbar" role="group">
+				<a class="btn btn-danger multiple disabled" onclick="$.operate.removeAll()" shiro:hasPermission="monitor:logininfor:remove">
+		            <i class="fa fa-remove"></i> 删除
+		        </a>
+		        <a class="btn btn-danger" onclick="$.operate.clean()" shiro:hasPermission="monitor:logininfor:remove">
+	                <i class="fa fa-trash"></i> 清空
+	            </a>
+	            <a class="btn btn-primary single disabled" onclick="unlock()" shiro:hasPermission="monitor:logininfor:unlock">
+					<i class="fa fa-unlock"></i> 解锁
+				</a>
+	            <a class="btn btn-warning" onclick="$.table.exportExcel()" shiro:hasPermission="monitor:logininfor:export">
+		            <i class="fa fa-download"></i> 导出
+		        </a>
+	        </div>
+        
+	        <div class="col-sm-12 select-table table-striped">
+			    <table id="bootstrap-table"></table>
+			</div>
+		</div>
+	</div>
+	
+	<th:block th:include="include :: footer" />
+	<script th:inline="javascript">
+	    var datas = [[${@dict.getType('sys_common_status')}]];
+		var prefix = ctx + "monitor/logininfor";
+	
+		$(function() {
+		    var options = {
+		        url: prefix + "/list",
+		        cleanUrl: prefix + "/clean",
+		        removeUrl: prefix + "/remove",
+		        exportUrl: prefix + "/export",
+		        queryParams: queryParams,
+		        sortName: "loginTime",
+		        sortOrder: "desc",
+		        modalName: "登录日志",
+		        escape: true,
+		        showPageGo: true,
+		        rememberSelected: true,
+		        columns: [{
+		        	field: 'state',
+		            checkbox: true
+		        },
+		        {
+		            field: 'infoId',
+		            title: '访问编号'
+		        },
+		        {
+		            field: 'loginName',
+		            title: '登录名称',
+		            sortable: true
+		        },
+		        {
+		            field: 'ipaddr',
+		            title: '登录地址',
+		            formatter: function(value, row, index) {
+                    	return $.table.tooltip(value);
+                    }
+		        },
+		        {
+		            field: 'loginLocation',
+		            title: '登录地点'
+		        },
+		        {
+		            field: 'browser',
+		            title: '浏览器'
+		        },
+		        {
+		            field: 'os',
+		            title: '操作系统'
+		        },
+		        {
+		            field: 'status',
+		            title: '登录状态',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		            	return $.table.selectDictLabel(datas, value);
+		            }
+		        },
+		        {
+		            field: 'msg',
+		            title: '操作信息'
+		        },
+		        {
+		            field: 'loginTime',
+		            title: '登录时间',
+		            sortable: true
+		        }]
+		    };
+		    $.table.init(options);
+		});
+		
+		function queryParams(params) {
+			var search = $.table.queryParams(params);
+			search.params = {
+			    beginTime : beginOfTime($("#startTime").val()),
+			    endTime : endOfTime($("#endTime").val())
+			};
+			return search;
+		}
+		
+		function unlock() {
+            $.operate.post(prefix + "/unlock?loginName=" + $.table.selectColumns("loginName"));
+        }
+	</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/monitor/online/online.html b/ruoyi-admin/src/main/resources/templates/monitor/online/online.html
new file mode 100644
index 0000000..158126e
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/monitor/online/online.html
@@ -0,0 +1,152 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('在线用户列表')" />
+</head>
+<body class="gray-bg">
+    <div class="container-div">
+		<div class="row">
+			<div class="col-sm-12 search-collapse">
+				<form id="online-form">
+					<div class="select-list">
+						<ul>
+							<li>
+								登录地址:<input type="text" name="ipaddr"/>
+							</li>
+							<li>
+								登录名称:<input type="text" name="loginName"/>
+							</li>
+							<li>
+								<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
+								<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
+							</li>
+						</ul>
+					</div>
+				</form>
+			</div>
+			
+	        <div class="btn-group-sm" id="toolbar" role="group">
+	            <a class="btn btn-danger multiple disabled" onclick="javascript:batchForceLogout()" shiro:hasPermission="monitor:online:batchForceLogout">
+	                <i class="fa fa-sign-out"></i> 强退
+	            </a>
+	        </div>
+	        
+	        <div class="col-sm-12 select-table table-striped">
+			    <table id="bootstrap-table"></table>
+			</div>
+		</div>
+	</div>
+	<th:block th:include="include :: footer" />
+	<th:block th:include="include :: bootstrap-table-export-js" />
+	<script th:inline="javascript">
+		var forceFlag = [[${@permission.hasPermi('monitor:online:forceLogout')}]];
+		var prefix = ctx + "monitor/online";
+
+		$(function() {
+		    var options = {
+		    	uniqueId: "sessionId",
+		        url: prefix + "/list",
+		        exportUrl: prefix + "/export",
+		        sortName: "lastAccessTime",
+		        sortOrder: "desc",
+		        showExport: true,
+		        escape: true,
+		        columns: [{
+		            checkbox: true
+		        },
+		        {
+                    title: "序号",
+                    formatter: function (value, row, index) {
+                 	    return $.table.serialNumber(index);
+                    }
+                },
+		        {
+		            field: 'sessionId',
+		            title: '会话编号',
+		            formatter: function(value, row, index) {
+                    	return $.table.tooltip(value);
+                    }
+		        },
+		        {
+		            field: 'loginName',
+		            title: '登录名称',
+		            sortable: true
+		        },
+		        {
+		            field: 'deptName',
+		            title: '部门名称'
+		        },
+		        {
+		            field: 'ipaddr',
+		            title: '主机'
+		        },
+		        {
+		            field: 'loginLocation',
+		            title: '登录地点'
+		        },
+		        {
+		            field: 'browser',
+		            title: '浏览器'
+		        },
+		        {
+		            field: 'os',
+		            title: '操作系统'
+		        },
+		        {
+		            field: 'status',
+		            title: '会话状态',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		                if (value == 'on_line') {
+		                    return '<span class="badge badge-primary">在线</span>';
+		                } else if (value == 'off_line') {
+		                    return '<span class="badge badge-danger">离线</span>';
+		                }
+		            }
+		        },
+		        {
+		            field: 'startTimestamp',
+		            title: '登录时间',
+		            sortable: true
+		        },
+		        {
+		            field: 'lastAccessTime',
+		            title: '最后访问时间',
+		            sortable: true
+		        },
+		        {
+		            title: '操作',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		                var msg = '<a class="btn btn-danger btn-xs ' + forceFlag + '" href="javascript:void(0)" onclick="forceLogout(\'' + row.sessionId + '\')"><i class="fa fa-sign-out"></i>强退</a> ';
+		                return msg;
+		            }
+		        }]
+		    };
+		    $.table.init(options);
+		});
+
+		// 单条强退
+		function forceLogout(sessionId) {
+		    $.modal.confirm("确定要强制选中用户下线吗?", function() {
+		    	var data = { "ids": sessionId };
+		        $.operate.post(prefix + "/batchForceLogout", data);
+		    })
+		}
+
+		// 批量强退
+		function batchForceLogout() {
+		    var rows = $.table.selectColumns("sessionId");
+		    if (rows.length == 0) {
+		        $.modal.alertWarning("请选择要强退的用户");
+		        return;
+		    }
+		    $.modal.confirm("确认要强退选中的" + rows.length + "条数据吗?", function() {
+		        var url = prefix + "/batchForceLogout";
+		        var data = { "ids": rows.join() };
+		        $.operate.post(url, data);
+		    });
+		}
+	</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/monitor/operlog/detail.html b/ruoyi-admin/src/main/resources/templates/monitor/operlog/detail.html
new file mode 100644
index 0000000..7d9306c
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/monitor/operlog/detail.html
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+	<th:block th:include="include :: header('操作日志详细')" />
+	<th:block th:include="include :: jsonview-css" />
+</head>
+<body class="white-bg">
+	<div class="wrapper wrapper-content animated fadeInRight ibox-content">
+	<form class="form-horizontal m-t" id="signupForm">
+		<div class="form-group">
+			<label class="col-sm-2 control-label">操作模块:</label>
+			<div class="form-control-static" th:text="${operLog.title} + ' / ' + ${@dict.getLabel('sys_oper_type',operLog.businessType)}">
+			</div>
+		</div>
+		<div class="form-group">
+			<label class="col-sm-2 control-label">登录信息:</label>
+			<div class="form-control-static" th:text="${operLog.operName} + ' / ' + ${operLog.deptName} + ' / ' + ${operLog.operIp}+ ' / ' + ${operLog.operLocation}">
+			</div>
+		</div>
+		<div class="form-group">
+			<label class="col-sm-2 control-label">请求地址:</label>
+			<div class="form-control-static" th:text="${operLog.requestMethod} + ' - ' + ${operLog.operUrl} + '  ' + '(' + '耗时' + ${operLog.costTime} + '毫秒)'">
+			</div>
+		</div>
+		<div class="form-group">
+			<label class="col-sm-2 control-label">操作方法:</label>
+			<div class="form-control-static" th:text="${operLog.method}">
+			</div>
+		</div>
+		<div class="form-group">
+			<label class="col-sm-2 control-label">请求参数:</label>
+			<div class="form-control-static"><pre id="operParam"></pre></div>
+		</div>
+		<div class="form-group">
+			<label class="col-sm-2 control-label">返回参数:</label>
+			<div class="form-control-static"><pre id="jsonResult"></pre></div>
+		</div>
+		<div class="form-group">
+			<label class="col-sm-2 control-label">状态:</label>
+			<div class="form-control-static" th:class="${operLog.status == 0 ? 'label label-primary' : 'label label-danger'}" th:text="${operLog.status == 0 ? '正常' : '异常'}">
+			</div>
+		</div>
+		<div class="form-group" th:style="'display:' + ${operLog.status == 0 ? 'none' : 'block'}">
+			<label class="col-sm-2 control-label">异常信息:</label>
+			<div class="form-control-static" th:text="${operLog.errorMsg}">
+			</div>
+		</div>
+	</form>
+    </div>
+    <th:block th:include="include :: footer" />
+    <th:block th:include="include :: jsonview-js" />
+    <script th:inline="javascript">
+	    $(function() {
+	    	var operParam = [[${operLog.operParam}]];
+	    	if ($.common.isNotEmpty(operParam) && operParam.length < 2000) {
+	    		$("#operParam").JSONView(operParam);
+	    	} else {
+	    		$("#operParam").text(operParam);
+	    	}
+	    	var jsonResult = [[${operLog.jsonResult}]];
+	    	if ($.common.isNotEmpty(jsonResult) && jsonResult.length < 2000) {
+	    		$("#jsonResult").JSONView(jsonResult);
+	    	} else {
+	    		$("#jsonResult").text(jsonResult);
+	    	}
+	    });
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/monitor/operlog/operlog.html b/ruoyi-admin/src/main/resources/templates/monitor/operlog/operlog.html
new file mode 100644
index 0000000..0736f09
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/monitor/operlog/operlog.html
@@ -0,0 +1,188 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('操作日志列表')" />
+	<th:block th:include="include :: bootstrap-select-css" />
+</head>
+<body class="gray-bg">
+	<div class="container-div">
+		<div class="row">
+			<div class="col-sm-12 search-collapse">
+				<form id="operlog-form">
+					<div class="select-list">
+						<ul>
+							<li>
+								<label>操作地址:</label><input type="text" name="operIp"/>
+							</li>
+							<li>
+								<label>系统模块: </label><input type="text" name="title"/>
+							</li>
+							<li>
+								<label>操作人员: </label><input type="text" name="operName"/>
+							</li>
+							<li class="select-selectpicker">
+								<label>操作类型: </label><select id="businessTypes" name="businessTypes" th:with="type=${@dict.getType('sys_oper_type')}" class="selectpicker" data-none-selected-text="请选择" multiple>
+									<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
+								</select>
+							</li>
+							<li>
+								<label>操作状态:</label><select name="status" th:with="type=${@dict.getType('sys_common_status')}">
+									<option value="">所有</option>
+									<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
+								</select>
+							</li>
+							<li class="select-time">
+								<label>操作时间: </label>
+								<input type="text" class="time-input" id="startTime" placeholder="开始时间"/>
+								<span>-</span>
+								<input type="text" class="time-input" id="endTime" placeholder="结束时间"/>
+							</li>
+							<li>
+								<a class="btn btn-primary btn-rounded btn-sm" onclick="searchPre()"><i class="fa fa-search"></i>&nbsp;搜索</a>
+								<a class="btn btn-warning btn-rounded btn-sm" onclick="resetPre()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
+							</li>
+						</ul>
+					</div>
+				</form>
+			</div>
+			
+			<div class="btn-group-sm" id="toolbar" role="group">
+				<a class="btn btn-danger multiple disabled" onclick="$.operate.removeAll()" shiro:hasPermission="monitor:operlog:remove">
+		            <i class="fa fa-remove"></i> 删除
+		        </a>
+		        <a class="btn btn-danger" onclick="$.operate.clean()" shiro:hasPermission="monitor:operlog:remove">
+	                <i class="fa fa-trash"></i> 清空
+	            </a>
+	            <a class="btn btn-warning" onclick="$.table.exportExcel()" shiro:hasPermission="monitor:operlog:export">
+		            <i class="fa fa-download"></i> 导出
+		        </a>
+	        </div>
+	        
+			<div class="col-sm-12 select-table table-striped">
+				<table id="bootstrap-table"></table>
+			</div>
+		</div>
+	</div>
+	
+	<th:block th:include="include :: footer" />
+	<th:block th:include="include :: bootstrap-select-js" />
+	<script th:inline="javascript">
+		var detailFlag = [[${@permission.hasPermi('monitor:operlog:detail')}]];
+		var datas = [[${@dict.getType('sys_oper_type')}]];
+		var prefix = ctx + "monitor/operlog";
+
+		$(function() {
+		    var options = {
+		        url: prefix + "/list",
+		        cleanUrl: prefix + "/clean",
+		        detailUrl: prefix + "/detail/{id}",
+		        removeUrl: prefix + "/remove",
+		        exportUrl: prefix + "/export",
+		        queryParams: queryParams,
+		        sortName: "operTime",
+		        sortOrder: "desc",
+		        modalName: "操作日志",
+		        escape: true,
+		        showPageGo: true,
+		        rememberSelected: true,
+		        columns: [{
+		        	field: 'state',
+		            checkbox: true
+		        },
+		        {
+		            field: 'operId',
+		            title: '日志编号'
+		        },
+		        {
+		            field: 'title',
+		            title: '系统模块',
+                    formatter: function(value, row, index) {
+                        return $.table.tooltip(value);
+                    }
+                },
+		        {
+		            field: 'businessType',
+		            title: '操作类型',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		                return $.table.selectDictLabel(datas, value);
+		            }
+		        },
+		        {
+		            field: 'operName',
+		            title: '操作人员',
+		            sortable: true
+		        },
+		        {
+		            field: 'deptName',
+		            title: '部门名称'
+		        },
+		        {
+		            field: 'operIp',
+		            title: '操作地址'
+		        },
+		        {
+		            field: 'operLocation',
+		            title: '操作地点'
+		        },
+		        {
+		            field: 'status',
+		            title: '操作状态',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		                if (value == 0) {
+		                    return '<span class="badge badge-primary">成功</span>';
+		                } else if (value == 1) {
+		                    return '<span class="badge badge-danger">失败</span>';
+		                }
+		            }
+		        },
+		        {
+		            field: 'operTime',
+		            title: '操作时间',
+		            sortable: true
+		        },
+		        {
+		            field: 'costTime',
+		            title: '消耗时间',
+		            sortable: true,
+		            formatter: function(value, row, index) {
+		                return $.common.sprintf("%s毫秒", value);
+		            }
+		        },
+		        {
+		            title: '操作',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		                var actions = [];
+		                actions.push('<a class="btn btn-warning btn-xs ' + detailFlag + '" href="javascript:void(0)" onclick="$.operate.detail(\'' + row.operId + '\')"><i class="fa fa-search"></i>详细</a>');
+		                return actions.join('');
+		            }
+		        }]
+		    };
+		    $.table.init(options);
+		});
+		
+		function queryParams(params) {
+			var search = $.table.queryParams(params);
+			search.params = {
+			    beginTime : beginOfTime($("#startTime").val()),
+			    endTime : endOfTime($("#endTime").val())
+			};
+			search.businessTypes = $.common.join($('#businessTypes').selectpicker('val'));
+			return search;
+		}
+		
+		function searchPre() {
+		    $.table.search('operlog-form', 'bootstrap-table');
+		}
+		
+		function resetPre() {
+			resetDate();
+			$("#operlog-form")[0].reset();
+			$("#businessTypes").selectpicker('refresh');
+			$.table.search('operlog-form', 'bootstrap-table', 1);
+		}
+	</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/monitor/server/server.html b/ruoyi-admin/src/main/resources/templates/monitor/server/server.html
new file mode 100644
index 0000000..00dbe80
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/monitor/server/server.html
@@ -0,0 +1,258 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+	<th:block th:include="include :: header('服务器监控')" />
+</head>
+<body class="gray-bg">
+    <div class="wrapper wrapper-content">
+        <div class="col-sm-12">
+            <div class="row">
+                <div class="col-sm-6">
+                    <div class="ibox float-e-margins">
+                        <div class="ibox-title">
+                            <h5><i class="fa fa-microchip"></i> CPU</h5>
+                            <div class="ibox-tools">
+                                <a class="collapse-link"><i class="fa fa-chevron-up"></i>
+                                </a>
+                                <a class="close-link"><i class="fa fa-times"></i></a>
+                            </div>
+                        </div>
+                        <div class="ibox-content">
+                            <table class="table table-hover no-margins">
+                                <thead>
+                                    <tr>
+                                        <th>属性</th>
+                                        <th>值</th>
+                                    </tr>
+                                </thead>
+                                <tbody>
+                                    <tr>
+                                        <td>核心数</td>
+                                        <td th:text="${server.cpu.cpuNum}">0个</td>
+                                    </tr>
+                                    <tr>
+                                        <td>用户使用率</td>
+                                        <td th:text="${server.cpu.used + '%'}">0%</td>
+                                    </tr>
+                                    <tr>
+                                        <td>系统使用率</td>
+                                        <td th:text="${server.cpu.sys + '%'}">0%</td>
+                                    </tr>
+                                    <tr>
+                                        <td>当前空闲率</td>
+                                        <td th:text="${server.cpu.free + '%'}">0%</td>
+                                    </tr>
+                                </tbody>
+                            </table>
+                        </div>
+                    </div>
+                </div>
+                
+                <div class="col-sm-6">
+                    <div class="ibox float-e-margins">
+                        <div class="ibox-title">
+                            <h5><i class="fa fa-ticket"></i> 内存</h5>
+                            <div class="ibox-tools">
+                                <a class="collapse-link"><i class="fa fa-chevron-up"></i></a>
+                                <a class="close-link"><i class="fa fa-times"></i></a>
+                            </div>
+                        </div>
+                        <div class="ibox-content">
+                            <table class="table table-hover no-margins">
+                                <thead>
+                                    <tr>
+                                        <th>属性</th>
+                                        <th>内存</th>
+                                        <th>JVM</th>
+                                    </tr>
+                                </thead>
+                                <tbody>
+                                    <tr>
+                                        <td>总内存</td>
+                                        <td th:text="${server.mem.total + 'G'}">0GB</td>
+                                        <td th:text="${server.jvm.total + 'M'}">0MB</td>
+                                    </tr>
+                                    <tr>
+                                        <td>已用内存</td>
+                                        <td th:text="${server.mem.used + 'G'}">0GB</td>
+                                        <td th:text="${server.jvm.used + 'M'}">0MB</td>
+                                    </tr>
+                                    <tr>
+                                        <td>剩余内存</td>
+                                        <td th:text="${server.mem.free + 'G'}">0GB</td>
+                                        <td th:text="${server.jvm.free + 'M'}">0MB</td>
+                                    </tr>
+                                    <tr>
+                                        <td>使用率</td>
+                                        <td th:class="${server.mem.usage gt 80} ? 'text-danger'">[[${server.mem.usage}]]%</td>
+                                        <td th:class="${server.jvm.usage gt 80} ? 'text-danger'">[[${server.jvm.usage}]]%</td>
+                                    </tr>
+                                </tbody>
+                            </table>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            
+            <div class="row">
+                <div class="col-sm-12">
+                    <div class="ibox float-e-margins">
+                        <div class="ibox-title">
+                            <h5><i class="fa fa-windows"></i> 服务器信息</h5>
+                            <div class="ibox-tools">
+                                <a class="collapse-link">
+                                    <i class="fa fa-chevron-up"></i>
+                                </a>
+                                <a class="close-link">
+                                    <i class="fa fa-times"></i>
+                                </a>
+                            </div>
+                        </div>
+                        <div class="ibox-content">
+                            <div class="row">
+                                <div class="col-sm-12">
+                                    <table class="table table-hover margin bottom">
+                                        <tbody>
+                                            <tr>
+                                                <td>服务器名称</td>
+                                                <td th:text="${server.sys.computerName}">RuoYi</td>
+                                                <td>操作系统</td>
+                                                <td th:text="${server.sys.osName}">Linux</td>
+                                            </tr>
+                                            <tr>
+                                                <td>服务器IP</td>
+                                                <td th:text="${server.sys.computerIp}">127.0.0.1</td>
+                                                <td>系统架构</td>
+                                                <td th:text="${server.sys.osArch}">amd64</td>
+                                            </tr>
+                                        </tbody>
+                                    </table>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            
+            <div class="row">
+                <div class="col-sm-12">
+                    <div class="ibox float-e-margins">
+                        <div class="ibox-title">
+                            <h5><i class="fa fa-coffee"></i> Java虚拟机信息</h5>
+                            <div class="ibox-tools">
+                                <a class="collapse-link">
+                                    <i class="fa fa-chevron-up"></i>
+                                </a>
+                                <a class="close-link">
+                                    <i class="fa fa-times"></i>
+                                </a>
+                            </div>
+                        </div>
+                        <div class="ibox-content">
+
+                            <div class="row">
+                                <div class="col-sm-12">
+                                    <table class="table table-hover margin bottom" style="table-layout:fixed;">
+                                        <tbody>
+                                            <tr>
+                                                <td>Java名称</td>
+                                                <td th:text="${server.jvm.name}">Java</td>
+                                                <td>Java版本</td>
+                                                <td th:text="${server.jvm.version}">1.8.0</td>
+                                            </tr>
+                                            <tr>
+                                                <td>启动时间</td>
+                                                <td th:text="${server.jvm.startTime}">2018-12-31 00:00:00</td>
+                                                <td>运行时长</td>
+                                                <td th:text="${server.jvm.runTime}">0天0时0分0秒</td>
+                                            </tr>
+                                            <tr>
+                                                <td colspan="1">安装路径</td>
+                                                <td colspan="3" th:text="${server.jvm.home}"></td>
+                                            </tr>
+                                             <tr>
+                                                <td colspan="1">项目路径</td>
+                                                <td colspan="3" th:text="${server.sys.userDir}"></td>
+                                            </tr>
+                                            <tr>
+                                                <td colspan="1">运行参数</td>
+                                                <td colspan="3" th:text="${server.jvm.inputArgs}"></td>
+                                            </tr>
+                                        </tbody>
+                                    </table>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            
+            <div class="row">
+                <div class="col-sm-12">
+                    <div class="ibox float-e-margins">
+                        <div class="ibox-title">
+                            <h5><i class="fa fa-hdd-o"></i> 磁盘状态</h5>
+                            <div class="ibox-tools">
+                                <a class="collapse-link">
+                                    <i class="fa fa-chevron-up"></i>
+                                </a>
+                                <a class="close-link">
+                                    <i class="fa fa-times"></i>
+                                </a>
+                            </div>
+                        </div>
+                        <div class="ibox-content">
+
+                            <div class="row">
+                                <div class="col-sm-12">
+                                    <table class="table table-hover margin bottom">
+                                        <thead>
+                                            <tr>
+                                                <th>盘符路径</th>
+                                                <th>文件系统</th>
+                                                <th>盘符类型</th>
+                                                <th>总大小</th>
+                                                <th>可用大小</th>
+                                                <th>已用大小</th>
+                                                <th>已用百分比</th>
+                                            </tr>
+                                        </thead>
+                                        <tbody>
+                                            <tr th:each="sysFile : ${server.sysFiles}">
+                                                <td th:text="${sysFile.dirName}">C:\</td>
+                                                <td th:text="${sysFile.sysTypeName}">NTFS</td>
+                                                <td th:text="${sysFile.typeName}">local</td>
+                                                <td th:text="${sysFile.total}">0GB</td>
+                                                <td th:text="${sysFile.free}">0GB</td>
+                                                <td th:text="${sysFile.used}">0GB</td>
+                                                <td th:class="${sysFile.usage gt 80} ? 'text-danger'">[[${sysFile.usage}]]%</td>
+                                            </tr>
+                                        </tbody>
+                                    </table>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</body>
+<th:block th:include="include :: footer" />
+<script>
+    $(".modal").appendTo("body"), $("[data-toggle=popover]").popover(), $(".collapse-link").click(function() {
+        var div_ibox = $(this).closest("div.ibox"),
+        e = $(this).find("i"),
+        i = div_ibox.find("div.ibox-content");
+        i.slideToggle(200),
+        e.toggleClass("fa-chevron-up").toggleClass("fa-chevron-down"),
+        div_ibox.toggleClass("").toggleClass("border-bottom"),
+        setTimeout(function() {
+        	div_ibox.resize();
+        }, 50);
+    }), $(".close-link").click(function () {
+		var div_ibox = $(this).closest("div.ibox");
+		div_ibox.remove()
+	});
+</script>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/register.html b/ruoyi-admin/src/main/resources/templates/register.html
new file mode 100644
index 0000000..f9dad26
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/register.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<html  lang="zh" xmlns:th="http://www.thymeleaf.org">
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
+    <title>注册若依系统</title>
+    <meta name="description" content="若依后台管理框架">
+    <link href="../static/css/bootstrap.min.css" th:href="@{/css/bootstrap.min.css}" rel="stylesheet"/>
+    <link href="../static/css/font-awesome.min.css" th:href="@{/css/font-awesome.min.css}" rel="stylesheet"/>
+    <link href="../static/css/style.min.css" th:href="@{/css/style.min.css}" rel="stylesheet"/>
+    <link href="../static/css/login.min.css" th:href="@{/css/login.min.css}" rel="stylesheet"/>
+    <link href="../static/ruoyi/css/ry-ui.css" th:href="@{/ruoyi/css/ry-ui.css?v=4.8.0}" rel="stylesheet"/>
+    <!-- 360浏览器急速模式 -->
+    <meta name="renderer" content="webkit">
+    <!-- 避免IE使用兼容模式 -->
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <link rel="shortcut icon" href="../static/favicon.ico" th:href="@{favicon.ico}"/>
+    <style type="text/css">label.error { position:inherit;  }</style>
+</head>
+<body class="signin">
+    <div class="signinpanel">
+        <div class="row">
+            <div class="col-sm-7">
+                <div class="signin-info">
+                    <div class="logopanel m-b">
+                        <h1><img alt="[ 若依 ]" src="../static/ruoyi.png" th:src="@{/ruoyi.png}"></h1>
+                    </div>
+                    <div class="m-b"></div>
+                    <h4>欢迎使用 <strong>若依 后台管理系统</strong></h4>
+                    <ul class="m-b">
+                        <li><i class="fa fa-arrow-circle-o-right m-r-xs"></i> SpringBoot</li>
+                        <li><i class="fa fa-arrow-circle-o-right m-r-xs"></i> Mybatis</li>
+                        <li><i class="fa fa-arrow-circle-o-right m-r-xs"></i> Shiro</li>
+                        <li><i class="fa fa-arrow-circle-o-right m-r-xs"></i> Thymeleaf</li>
+                        <li><i class="fa fa-arrow-circle-o-right m-r-xs"></i> Bootstrap</li>
+                    </ul>
+                    <strong>已经注册过? <a th:href="@{/login}">直接登录&raquo;</a></strong>
+                </div>
+            </div>
+            <div class="col-sm-5">
+                <form id="registerForm" autocomplete="off">
+                    <h4 class="no-margins">注册:</h4>
+                    <p class="m-t-md">你若不离不弃,我必生死相依</p>
+                    <input type="text"     name="username" class="form-control uname"         placeholder="用户名"   maxlength="20" />
+                    <input type="password" name="password" class="form-control pword"         placeholder="密码"     maxlength="20" />
+                    <input type="password" name="confirmPassword" class="form-control pword"  placeholder="确认密码" maxlength="20" />
+					<div class="row m-t" th:if="${captchaEnabled==true}">
+						<div class="col-xs-6">
+						    <input type="text" name="validateCode" class="form-control code"  placeholder="验证码"   maxlength="5" >
+						</div>
+						<div class="col-xs-6">
+							<a href="javascript:void(0);" title="点击更换验证码">
+								<img th:src="@{/captcha/captchaImage(type=${captchaType})}" class="imgcode" width="85%"/>
+							</a>
+						</div>
+					</div>
+                    <div class="checkbox-custom" th:classappend="${captchaEnabled==false} ? 'm-t'">
+				        <input type="checkbox" id="acceptTerm" name="acceptTerm"> <label for="acceptTerm">我已阅读并同意</label>
+				        <a href="https://gitee.com/y_project/RuoYi/blob/master/README.md" target="_blank">使用条款</a>
+				    </div>
+                    <button class="btn btn-success btn-block" id="btnSubmit" data-loading="正在验证注册,请稍候...">注册</button>
+                </form>
+            </div>
+        </div>
+        <div class="signup-footer">
+            <div class="pull-left">
+                &copy; 2018-2025 All Rights Reserved. RuoYi <br>
+            </div>
+        </div>
+    </div>
+<script th:inline="javascript"> var ctx = [[@{/}]]; var captchaType = [[${captchaType}]]; var captchaEnabled = [[${captchaEnabled}]];</script>
+<!-- 全局js -->
+<script src="../static/js/jquery.min.js" th:src="@{/js/jquery.min.js}"></script>
+<script src="../static/ajax/libs/validate/jquery.validate.min.js" th:src="@{/ajax/libs/validate/jquery.validate.min.js}"></script>
+<script src="../static/ajax/libs/validate/jquery.validate.extend.js" th:src="@{/ajax/libs/validate/jquery.validate.extend.js}"></script>
+<script src="../static/ajax/libs/layer/layer.min.js" th:src="@{/ajax/libs/layer/layer.min.js}"></script>
+<script src="../static/ajax/libs/blockUI/jquery.blockUI.js" th:src="@{/ajax/libs/blockUI/jquery.blockUI.js}"></script>
+<script src="../static/ruoyi/js/ry-ui.js" th:src="@{/ruoyi/js/ry-ui.js?v=4.8.0}"></script>
+<script src="../static/ruoyi/register.js" th:src="@{/ruoyi/register.js}"></script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/skin.html b/ruoyi-admin/src/main/resources/templates/skin.html
new file mode 100644
index 0000000..27ea41d
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/skin.html
@@ -0,0 +1,165 @@
+<!DOCTYPE html>
+<html  lang="zh" xmlns:th="http://www.thymeleaf.org">
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta name="renderer" content="webkit">
+    <title>主题选择</title>
+    <!--[if lt IE 9]>
+    <meta http-equiv="refresh" content="0;ie.html"/>
+    <![endif]-->
+    <link rel="shortcut icon" href="../static/favicon.ico" th:href="@{favicon.ico}"/>
+    <link th:href="@{/css/bootstrap.min.css}" rel="stylesheet"/>
+    <link th:href="@{/css/style.min.css}" rel="stylesheet"/>
+    <style type="text/css">
+		.list-unstyled{margin:10px;}
+		.full-opacity-hover{opacity:1;filter:alpha(opacity=1);border:1px solid #fff}
+		.full-opacity-hover:hover{border:1px solid #f00;}
+	</style>
+</head>
+<body class="gray-bg">
+<ul class="list-unstyled clearfix">
+	<li style="float:left; width: 33.33333%; padding: 5px;">
+		<a href="javascript:" data-skin="skin-blue|theme-dark" style="display: block; box-shadow: 0 0 3px rgba(0,0,0,0.4)" class="clearfix full-opacity-hover">
+			<span style="width: 20%; float: left; height: 13px; background: #367fa9"></span>
+			<span style="width: 80%; float: left; height: 13px; background: #3c8dbc"></span>
+			<span style="width: 20%; float: left; height: 30px; background: #2f4050"></span>
+			<span style="width: 80%; float: left; height: 30px; background: #f4f5f7"></span>
+		</a>
+		<p class="text-center">蓝</p>
+	</li>
+	
+	<li style="float:left; width: 33.33333%; padding: 5px;">
+		<a href="javascript:" data-skin="skin-green|theme-dark" style="display: block; box-shadow: 0 0 3px rgba(0,0,0,0.4)" class="clearfix full-opacity-hover">
+			<span style="width: 20%; float: left; height: 13px; background: #008d4c"></span>
+			<span style="width: 80%; float: left; height: 13px; background: #00a65a"></span>
+			<span style="width: 20%; float: left; height: 30px; background: #222d32"></span>
+			<span style="width: 80%; float: left; height: 30px; background: #f4f5f7"></span>
+		</a>
+		<p class="text-center">绿</p>
+	</li>
+	
+	<li style="float:left; width: 33.33333%; padding: 5px;">
+		<a href="javascript:" data-skin="skin-purple|theme-dark" style="display: block; box-shadow: 0 0 3px rgba(0,0,0,0.4)" class="clearfix full-opacity-hover">
+			<span style="width: 20%; float: left; height: 13px; background: #555299"></span>
+			<span style="width: 80%; float: left; height: 13px; background: #605ca8"></span>
+			<span style="width: 20%; float: left; height: 30px; background: #222d32"></span>
+			<span style="width: 80%; float: left; height: 30px; background: #f4f5f7"></span>
+		</a>
+		<p class="text-center">紫</p>
+	</li>
+	
+	<li style="float:left; width: 33.33333%; padding: 5px;">
+		<a href="javascript:" data-skin="skin-red|theme-dark" style="display: block; box-shadow: 0 0 3px rgba(0,0,0,0.4)" class="clearfix full-opacity-hover">
+			<span style="width: 20%; float: left; height: 13px; background: #dd4b39"></span>
+			<span style="width: 80%; float: left; height: 13px; background: #d73925"></span>
+			<span style="width: 20%; float: left; height: 30px; background: #222d32"></span>
+			<span style="width: 80%; float: left; height: 30px; background: #f4f5f7"></span>
+		</a>
+		<p class="text-center">红</p>
+	</li>
+	
+	<li style="float:left; width: 33.33333%; padding: 5px;">
+		<a href="javascript:" data-skin="skin-yellow|theme-dark" style="display: block; box-shadow: 0 0 3px rgba(0,0,0,0.4)" class="clearfix full-opacity-hover">
+			<span style="width: 20%; float: left; height: 13px; background: #f39c12"></span>
+			<span style="width: 80%; float: left; height: 13px; background: #e08e0b"></span>
+			<span style="width: 20%; float: left; height: 30px; background: #222d32"></span>
+			<span style="width: 80%; float: left; height: 30px; background: #f4f5f7"></span>
+		</a>
+		<p class="text-center">黄</p>
+	</li>
+	
+	<li style="float:left; width: 33.33333%; padding: 5px;">
+		<a href="javascript:" data-skin="skin-blue|theme-light" style="display: block; box-shadow: 0 0 3px rgba(0,0,0,0.4)" class="clearfix full-opacity-hover">
+			<span style="width: 20%; float: left; height: 13px; background: #367fa9"></span>
+			<span style="width: 80%; float: left; height: 13px; background: #3c8dbc"></span>
+			<span style="width: 20%; float: left; height: 30px; background: #f9fafc"></span>
+			<span style="width: 80%; float: left; height: 30px; background: #f4f5f7"></span>
+		</a>
+		<p class="text-center">蓝灰</p>
+	</li>
+	
+	<li style="float:left; width: 33.33333%; padding: 5px;">
+		<a href="javascript:" data-skin="skin-green|theme-light" style="display: block; box-shadow: 0 0 3px rgba(0,0,0,0.4)" class="clearfix full-opacity-hover">
+			<span style="width: 20%; float: left; height: 13px; background: #008d4c"></span>
+			<span style="width: 80%; float: left; height: 13px; background: #00a65a"></span>
+			<span style="width: 20%; float: left; height: 30px; background: #f9fafc"></span>
+			<span style="width: 80%; float: left; height: 30px; background: #f4f5f7"></span>
+		</a>
+		<p class="text-center">绿灰</p>
+	</li>
+	
+	<li style="float:left; width: 33.33333%; padding: 5px;">
+		<a href="javascript:" data-skin="skin-purple|theme-light" style="display: block; box-shadow: 0 0 3px rgba(0,0,0,0.4)" class="clearfix full-opacity-hover">
+			<span style="width: 20%; float: left; height: 13px; background: #555299"></span>
+			<span style="width: 80%; float: left; height: 13px; background: #605ca8"></span>
+			<span style="width: 20%; float: left; height: 30px; background: #f9fafc"></span>
+			<span style="width: 80%; float: left; height: 30px; background: #f4f5f7"></span>
+		</a>
+		<p class="text-center">紫灰</p>
+	</li>
+	
+	<li style="float:left; width: 33.33333%; padding: 5px;">
+		<a href="javascript:" data-skin="skin-red|theme-light" style="display: block; box-shadow: 0 0 3px rgba(0,0,0,0.4)" class="clearfix full-opacity-hover">
+			<span style="width: 20%; float: left; height: 13px; background: #dd4b39"></span>
+			<span style="width: 80%; float: left; height: 13px; background: #d73925"></span>
+			<span style="width: 20%; float: left; height: 30px; background: #f9fafc"></span>
+			<span style="width: 80%; float: left; height: 30px; background: #f4f5f7"></span>
+		</a>
+		<p class="text-center">红灰</p>
+	</li>
+	
+	<li style="float:left; width: 33.33333%; padding: 5px;">
+		<a href="javascript:" data-skin="skin-yellow|theme-light" style="display: block; box-shadow: 0 0 3px rgba(0,0,0,0.4)" class="clearfix full-opacity-hover">
+			<span style="width: 20%; float: left; height: 13px; background: #f39c12"></span>
+			<span style="width: 80%; float: left; height: 13px; background: #e08e0b"></span>
+			<span style="width: 20%; float: left; height: 30px; background: #f9fafc"></span>
+			<span style="width: 80%; float: left; height: 30px; background: #f4f5f7"></span>
+		</a>
+		<p class="text-center">黄灰</p>
+	</li>
+	
+	<li style="float:left; width: 33.33333%; padding: 5px;">
+		<a href="javascript:" data-skin="skin-blue|theme-blue" style="display: block; box-shadow: 0 0 3px rgba(0,0,0,0.4)" class="clearfix full-opacity-hover">
+			<span style="width: 20%; float: left; height: 13px; background: #367fa9"></span>
+			<span style="width: 80%; float: left; height: 13px; background: #3c8dbc"></span>
+			<span style="width: 20%; float: left; height: 30px; background: rgba(15,41,80,1)"></span>
+			<span style="width: 80%; float: left; height: 30px; background: #f4f5f7"></span>
+		</a>
+		<p class="text-center">蓝浅(新)</p>
+	</li>
+	<li style="float:left; width: 33.33333%; padding: 5px;">
+		<a href="javascript:" data-skin="skin-green|theme-blue" style="display: block; box-shadow: 0 0 3px rgba(0,0,0,0.4)" class="clearfix full-opacity-hover">
+			<span style="width: 20%; float: left; height: 13px; background: #008d4c"></span>
+			<span style="width: 80%; float: left; height: 13px; background: #00a65a"></span>
+			<span style="width: 20%; float: left; height: 30px; background: rgba(15,41,80,1)"></span>
+			<span style="width: 80%; float: left; height: 30px; background: #f4f5f7"></span>
+		</a>
+		<p class="text-center">绿浅(新)</p>
+	</li>
+</ul>
+</body>
+<script th:src="@{/js/jquery.min.js}"></script>
+<script th:src="@{/ruoyi/js/common.js?v=4.8.0}"></script>
+<script type="text/javascript">
+//皮肤样式列表
+var skins = ["skin-blue", "skin-green", "skin-purple", "skin-red", "skin-yellow"];
+
+// 主题样式列表
+var themes = ["theme-dark", "theme-light", "theme-blue"];
+
+$("[data-skin]").on('click',
+function(e) {
+    var skin = $(this).data('skin');
+    $.each(skins, function(i) {
+        parent.$("body").removeClass(skins[i]);
+    });
+    $.each(themes, function(i) {
+        parent.$("body").removeClass(themes[i]);
+    });
+    parent.$("body").addClass(skin.split('|')[0]);
+    parent.$("body").addClass(skin.split('|')[1]);
+    storage.set('skin', skin);
+});
+</script>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/system/config/add.html b/ruoyi-admin/src/main/resources/templates/system/config/add.html
new file mode 100644
index 0000000..406958b
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/system/config/add.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+	<th:block th:include="include :: header('新增参数')" />
+</head>
+<body class="white-bg">
+    <div class="wrapper wrapper-content animated fadeInRight ibox-content">
+        <form class="form-horizontal m" id="form-config-add" name="form-config-add">
+        <div class="form-group">	
+            <label class="col-sm-3 control-label is-required">参数名称:</label>
+            <div class="col-sm-8">
+                <input id="configName" name="configName" class="form-control" type="text" required>
+            </div>
+        </div>
+        <div class="form-group">	
+            <label class="col-sm-3 control-label is-required">参数键名:</label>
+            <div class="col-sm-8">
+                <input id="configKey" name="configKey" class="form-control" type="text" required>
+            </div>
+        </div>
+        <div class="form-group">	
+            <label class="col-sm-3 control-label is-required">参数键值:</label>
+            <div class="col-sm-8">
+                <textarea id="configValue" name="configValue" class="form-control" rows="4" required></textarea>
+            </div>
+        </div>
+        <div class="form-group">
+			<label class="col-sm-3 control-label">系统内置:</label>
+			<div class="col-sm-8">
+			    <div class="radio-box" th:each="dict : ${@dict.getType('sys_yes_no')}">
+					<input type="radio" th:id="${dict.dictCode}" name="configType" th:value="${dict.dictValue}" th:checked="${dict.default}">
+					<label th:for="${dict.dictCode}" th:text="${dict.dictLabel}"></label>
+				</div>
+			</div>
+		</div>
+		<div class="form-group">	
+            <label class="col-sm-3 control-label">备注:</label>
+            <div class="col-sm-8">
+                <textarea id="remark" name="remark" class="form-control"></textarea>
+            </div>
+        </div>
+    </form>
+    </div>
+    <th:block th:include="include :: footer" />
+    <script type="text/javascript">
+	    var prefix = ctx + "system/config";
+	
+	    $("#form-config-add").validate({
+	    	onkeyup: false,
+	        rules: {
+	            configKey: {
+	                remote: {
+	                    url: prefix + "/checkConfigKeyUnique",
+	                    type: "post",
+	                    dataType: "json",
+	                    data: {
+	                        "configKey": function() {
+	                            return $.common.trim($("#configKey").val());
+	                        }
+	                    }
+	                }
+	            },
+	        },
+	        messages: {
+	            "configKey": {
+	                remote: "参数键名已经存在"
+	            }
+	        },
+	        focusCleanup: true
+	    });
+	    
+	    function submitHandler() {
+	        if ($.validate.form()) {
+	            $.operate.save(prefix + "/add", $('#form-config-add').serialize());
+	        }
+	    }
+    </script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/system/config/config.html b/ruoyi-admin/src/main/resources/templates/system/config/config.html
new file mode 100644
index 0000000..1ba0c0b
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/system/config/config.html
@@ -0,0 +1,148 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('参数列表')" />
+</head>
+<body class="gray-bg">
+     <div class="container-div">
+		<div class="row">
+			<div class="col-sm-12 search-collapse">
+				<form id="config-form">
+					<div class="select-list">
+						<ul>
+							<li>
+								参数名称:<input type="text" name="configName"/>
+							</li>
+							<li>
+								参数键名:<input type="text" name="configKey"/>
+							</li>
+							<li>
+								系统内置:<select name="configType" th:with="type=${@dict.getType('sys_yes_no')}">
+									<option value="">所有</option>
+									<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
+								</select>
+							</li>
+							<li class="select-time">
+								<label>创建时间: </label>
+								<input type="text" class="time-input" id="startTime" placeholder="开始时间" name="params[beginTime]"/>
+								<span>-</span>
+								<input type="text" class="time-input" id="endTime" placeholder="结束时间" name="params[endTime]"/>
+							</li>
+							<li>
+								<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
+								<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
+							</li>
+						</ul>
+					</div>
+				</form>
+			</div>
+			
+	        <div class="btn-group-sm" id="toolbar" role="group">
+		        <a class="btn btn-success" onclick="$.operate.add()" shiro:hasPermission="system:config:add">
+		            <i class="fa fa-plus"></i> 新增
+		        </a>
+		        <a class="btn btn-primary single disabled" onclick="$.operate.edit()" shiro:hasPermission="system:config:edit">
+		            <i class="fa fa-edit"></i> 修改
+		        </a>
+		        <a class="btn btn-danger multiple disabled" onclick="$.operate.removeAll()" shiro:hasPermission="system:config:remove">
+		            <i class="fa fa-remove"></i> 删除
+		        </a>
+		        <a class="btn btn-warning" onclick="$.table.exportExcel()" shiro:hasPermission="system:config:export">
+		            <i class="fa fa-download"></i> 导出
+		        </a>
+		        <a class="btn btn-danger" onclick="refreshCache()" shiro:hasPermission="system:config:remove">
+		            <i class="fa fa-refresh"></i> 刷新缓存
+		        </a>
+	        </div>
+	        <div class="col-sm-12 select-table table-striped">
+	            <table id="bootstrap-table"></table>
+	        </div>
+	    </div>
+	</div>
+    <th:block th:include="include :: footer" />
+    <script th:inline="javascript">
+        var editFlag = [[${@permission.hasPermi('system:config:edit')}]];
+        var removeFlag = [[${@permission.hasPermi('system:config:remove')}]];
+        var datas = [[${@dict.getType('sys_yes_no')}]];
+        var prefix = ctx + "system/config";
+
+        $(function() {
+            var options = {
+                url: prefix + "/list",
+                createUrl: prefix + "/add",
+                updateUrl: prefix + "/edit/{id}",
+                removeUrl: prefix + "/remove",
+                exportUrl: prefix + "/export",
+                sortName: "configId",
+		        sortOrder: "asc",
+                modalName: "参数",
+                columns: [{
+                    checkbox: true
+                },
+                {
+                    field: 'configId',
+                    title: '参数主键'
+                },
+                {
+                    field: 'configName',
+                    title: '参数名称',
+                    formatter: function(value, row, index) {
+                        return $.table.tooltip(value);
+                    }
+                },
+                {
+                    field: 'configKey',
+                    title: '参数键名',
+                    formatter: function(value, row, index) {
+                        return $.table.tooltip(value);
+                    }
+                },
+                {
+                    field: 'configValue',
+                    title: '参数键值',
+                    align: 'center',
+                    formatter: function(value, row, index) {
+                        return $.table.tooltip(value, 10, "open");
+                    }
+                },
+                {
+                    field: 'configType',
+                    title: '系统内置',
+                    align: 'center',
+                    formatter: function(value, row, index) {
+                        return $.table.selectDictLabel(datas, value);
+                    }
+                },
+                {
+                    field: 'remark',
+                    title: '备注',
+                    align: 'center',
+                    formatter: function(value, row, index) {
+                        return $.table.tooltip(value, 10, "open");
+                    }
+                },
+                {
+                    field: 'createTime',
+                    title: '创建时间'
+                },
+                {
+                    title: '操作',
+                    align: 'center',
+                    formatter: function(value, row, index) {
+                        var actions = [];
+                        actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.configId + '\')"><i class="fa fa-edit"></i>编辑</a> ');
+                        actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.configId + '\')"><i class="fa fa-remove"></i>删除</a>');
+                        return actions.join('');
+                    }
+                }]
+            };
+            $.table.init(options);
+        });
+        
+        /** 刷新参数缓存 */
+        function refreshCache() {
+            $.operate.get(prefix + "/refreshCache");
+        }
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/system/config/edit.html b/ruoyi-admin/src/main/resources/templates/system/config/edit.html
new file mode 100644
index 0000000..764fe44
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/system/config/edit.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+	<th:block th:include="include :: header('修改参数')" />
+</head>
+<body class="white-bg">
+    <div class="wrapper wrapper-content animated fadeInRight ibox-content">
+        <form class="form-horizontal m" id="form-config-edit" th:object="${config}">
+            <input id="configId" name="configId" th:field="*{configId}"  type="hidden">
+            <div class="form-group">	
+                <label class="col-sm-3 control-label is-required">参数名称:</label>
+                <div class="col-sm-8">
+                    <input id="configName" name="configName" th:field="*{configName}" class="form-control" type="text" required>
+                </div>
+            </div>
+            <div class="form-group">	
+                <label class="col-sm-3 control-label is-required">参数键名:</label>
+                <div class="col-sm-8">
+                    <input id="configKey" name="configKey" th:field="*{configKey}" class="form-control" type="text" required>
+                </div>
+            </div>
+            <div class="form-group">	
+                <label class="col-sm-3 control-label is-required">参数键值:</label>
+                <div class="col-sm-8">
+                    <textarea id="configValue" name="configValue" class="form-control" rows="4" required>[[*{configValue}]]</textarea>
+                </div>
+            </div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">系统内置:</label>
+				<div class="col-sm-8">
+				    <div class="radio-box" th:each="dict : ${@dict.getType('sys_yes_no')}">
+						<input type="radio" th:id="${dict.dictCode}" name="configType" th:value="${dict.dictValue}" th:field="*{configType}">
+						<label th:for="${dict.dictCode}" th:text="${dict.dictLabel}"></label>
+					</div>
+				</div>
+			</div>
+			<div class="form-group">	
+	            <label class="col-sm-3 control-label">备注:</label>
+	            <div class="col-sm-8">
+	                <textarea id="remark" name="remark" class="form-control">[[*{remark}]]</textarea>
+	            </div>
+	        </div>
+    	</form>
+    </div>
+    <th:block th:include="include :: footer" />
+    <script type="text/javascript">
+	    var prefix = ctx + "system/config";
+	    
+	    $("#form-config-edit").validate({
+	    	onkeyup: false,
+	        rules: {
+	            configKey: {
+	                remote: {
+	                    url: prefix + "/checkConfigKeyUnique",
+	                    type: "post",
+	                    dataType: "json",
+	                    data: {
+	                        "configId": function() {
+	                        	return $("#configId").val();
+	                        },
+	                        "configKey": function() {
+	                        	return $.common.trim($("#configKey").val());
+	                        }
+	                    }
+	                }
+	            },
+	        },
+	        messages: {
+	            "configKey": {
+	                remote: "参数键名已经存在"
+	            }
+	        },
+	        focusCleanup: true
+	    });
+	    
+	    function submitHandler() {
+	        if ($.validate.form()) {
+	        	$.operate.save(prefix + "/edit", $('#form-config-edit').serialize());
+	        }
+	    }
+    </script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/system/dept/add.html b/ruoyi-admin/src/main/resources/templates/system/dept/add.html
new file mode 100644
index 0000000..ef15245
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/system/dept/add.html
@@ -0,0 +1,130 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+	<th:block th:include="include :: header('新增部门')" />
+</head>
+<body class="white-bg">
+	<div class="wrapper wrapper-content animated fadeInRight ibox-content">
+		<form class="form-horizontal m" id="form-dept-add">
+			<input id="treeId" name="parentId" type="hidden" th:value="${dept?.deptId}"   />
+			<div class="form-group">
+				<label class="col-sm-3 control-label is-required">上级部门:</label>
+				<div class="col-sm-8">
+				    <div class="input-group">
+						<input class="form-control" type="text" onclick="selectDeptTree()" id="treeName" readonly="true" th:value="${dept?.deptName}" required>
+					    <span class="input-group-addon"><i class="fa fa-search"></i></span>
+				    </div>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label is-required">部门名称:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="deptName" id="deptName" required>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label is-required">显示排序:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="orderNum" required>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">负责人:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="leader">
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">联系电话:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="phone">
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">邮箱:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="email">
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">部门状态:</label>
+				<div class="col-sm-8">
+				    <div class="radio-box" th:each="dict : ${@dict.getType('sys_normal_disable')}">
+						<input type="radio" th:id="${dict.dictCode}" name="status" th:value="${dict.dictValue}" th:checked="${dict.default}">
+						<label th:for="${dict.dictCode}" th:text="${dict.dictLabel}"></label>
+					</div>
+				</div>
+			</div>
+		</form>
+	</div>
+	<th:block th:include="include :: footer" />
+	<script type="text/javascript">
+		var prefix = ctx + "system/dept";
+		
+		$("#form-dept-add").validate({
+			onkeyup: false,
+			rules:{
+				deptName:{
+					remote: {
+		                url: prefix + "/checkDeptNameUnique",
+		                type: "post",
+		                dataType: "json",
+		                data: {
+		                	"parentId": function() {
+		                		return $("input[name='parentId']").val();
+		                    },
+		                	"deptName" : function() {
+		                        return $.common.trim($("#deptName").val());
+		                    }
+		                }
+		            }
+				},
+				orderNum:{
+					digits:true
+				},
+				email:{
+                    email:true,
+        		},
+        		phone:{
+        			isPhone:true,
+        		},
+			},
+			messages: {
+		        "deptName": {
+		            remote: "部门已经存在"
+		        }
+		    },
+		    focusCleanup: true
+		});
+		
+		function submitHandler() {
+	        if ($.validate.form()) {
+	        	$.operate.save(prefix + "/add", $('#form-dept-add').serialize());
+	        }
+	    }
+	
+		/*部门管理-新增-选择父部门树*/
+		function selectDeptTree() {
+			var treeId = $("#treeId").val();
+			if ($.common.isEmpty(treeId)) {
+       			$.modal.alertWarning("请先添加用户所属的部门!");
+       			return;
+       		}
+			var options = {
+				title: '部门选择',
+				width: "380",
+				url: prefix + "/selectDeptTree/" + treeId + "/0",
+				callBack: doSubmit
+			};
+			$.modal.openOptions(options);
+		}
+		
+		function doSubmit(index, layero){
+			var body = $.modal.getChildFrame(index);
+   			$("#treeId").val(body.find('#treeId').val());
+   			$("#treeName").val(body.find('#treeName').val());
+   			$.modal.close(index);
+		}
+	</script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/system/dept/dept.html b/ruoyi-admin/src/main/resources/templates/system/dept/dept.html
new file mode 100644
index 0000000..56d94e3
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/system/dept/dept.html
@@ -0,0 +1,112 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('部门列表')" />
+</head>
+<body class="gray-bg">
+	<div class="container-div">
+		<div class="row">
+			<div class="col-sm-12 search-collapse">
+				<form id="dept-form">
+					<div class="select-list">
+						<ul>
+							<li>
+								部门名称:<input type="text" name="deptName"/>
+							</li>
+							<li>
+								部门状态:<select name="status" th:with="type=${@dict.getType('sys_normal_disable')}">
+									<option value="">所有</option>
+									<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
+								</select>
+							</li>
+							<li>
+								<a class="btn btn-primary btn-rounded btn-sm" onclick="$.treeTable.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
+								<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
+							</li>
+						</ul>
+					</div>
+				</form>
+			</div>
+                
+            <div class="btn-group-sm" id="toolbar" role="group">
+		        <a class="btn btn-success" onclick="$.operate.add(100)" shiro:hasPermission="system:dept:add">
+                    <i class="fa fa-plus"></i> 新增
+                </a>
+                <a class="btn btn-primary" onclick="$.operate.edit()" shiro:hasPermission="system:dept:edit">
+		            <i class="fa fa-edit"></i> 修改
+		        </a>
+                <a class="btn btn-info" id="expandAllBtn">
+                    <i class="fa fa-exchange"></i> 展开/折叠
+                </a>
+	        </div>
+       		 <div class="col-sm-12 select-table table-striped">
+	            <table id="bootstrap-tree-table"></table>
+	        </div>
+	    </div>
+	</div>
+	<th:block th:include="include :: footer" />
+	<script th:inline="javascript">
+		var addFlag = [[${@permission.hasPermi('system:dept:add')}]];
+		var editFlag = [[${@permission.hasPermi('system:dept:edit')}]];
+		var removeFlag = [[${@permission.hasPermi('system:dept:remove')}]];
+		var datas = [[${@dict.getType('sys_normal_disable')}]];
+		var prefix = ctx + "system/dept"
+
+		$(function() {
+		    var options = {
+		        code: "deptId",
+		        parentCode: "parentId",
+		        uniqueId: "deptId",
+		        url: prefix + "/list",
+		        createUrl: prefix + "/add/{id}",
+		        updateUrl: prefix + "/edit/{id}",
+		        removeUrl: prefix + "/remove/{id}",
+		        modalName: "部门",
+		        columns: [{
+                    field: 'selectItem', 
+                    radio: true
+                 },
+                 {
+		            field: 'deptName',
+		            title: '部门名称',
+		            align: "left"
+		        },
+		        {
+		            field: 'orderNum',
+		            title: '排序',
+		            align: "left"
+		        },
+		        {
+		            field: 'status',
+		            title: '状态',
+		            align: "left",
+		            formatter: function(value, item, index) {
+		            	return $.table.selectDictLabel(datas, item.status);
+		            }
+		        },
+		        {
+		            field: 'createTime',
+		            title: '创建时间',
+		            align: "left"
+		        },
+		        {
+		            title: '操作',
+		            align: 'left',
+		            formatter: function(value, row, index) {
+		                if (row.parentId != 0) {
+		                    var actions = [];
+		                    actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.deptId + '\')"><i class="fa fa-edit"></i>编辑</a> ');
+		                    actions.push('<a class="btn btn-info  btn-xs ' + addFlag + '" href="javascript:void(0)" onclick="$.operate.add(\'' + row.deptId + '\')"><i class="fa fa-plus"></i>新增</a> ');
+		                    actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.deptId + '\')"><i class="fa fa-trash"></i>删除</a>');
+		                    return actions.join('');
+		                } else {
+		                    return "";
+		                }
+		            }
+		        }]
+		    };
+		    $.treeTable.init(options);
+		});
+	</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/system/dept/edit.html b/ruoyi-admin/src/main/resources/templates/system/dept/edit.html
new file mode 100644
index 0000000..3469b32
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/system/dept/edit.html
@@ -0,0 +1,138 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+	<th:block th:include="include :: header('修改部门')" />
+</head>
+<body class="white-bg">
+	<div class="wrapper wrapper-content animated fadeInRight ibox-content">
+		<form class="form-horizontal m" id="form-dept-edit" th:object="${dept}">
+			<input name="deptId" type="hidden" th:field="*{deptId}" />
+			<input id="treeId" name="parentId" type="hidden" th:field="*{parentId}" />
+			<div class="form-group">
+				<label class="col-sm-3 control-label">上级部门:</label>
+				<div class="col-sm-8">
+				    <div class="input-group">
+						<input class="form-control" type="text" id="treeName" onclick="selectDeptTree()" readonly="true" th:field="*{parentName}">
+					    <span class="input-group-addon"><i class="fa fa-search"></i></span>
+				    </div>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label is-required">部门名称:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="deptName" th:field="*{deptName}" id="deptName" required>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label is-required">显示排序:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="orderNum" th:field="*{orderNum}" required>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">负责人:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="leader" th:field="*{leader}">
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">联系电话:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="phone" th:field="*{phone}">
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">邮箱:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="email" th:field="*{email}">
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">部门状态:</label>
+				<div class="col-sm-8">
+					<div class="radio-box" th:each="dict : ${@dict.getType('sys_normal_disable')}">
+						<input type="radio" th:id="${dict.dictCode}" name="status" th:value="${dict.dictValue}" th:field="*{status}">
+						<label th:for="${dict.dictCode}" th:text="${dict.dictLabel}"></label>
+					</div>
+				</div>
+			</div>
+		</form>
+	</div>
+	<th:block th:include="include :: footer" />
+	<script type="text/javascript">
+		var prefix = ctx + "system/dept";
+		
+		$("#form-dept-edit").validate({
+			onkeyup: false,
+			rules:{
+				deptName:{
+					remote: {
+		                url: prefix + "/checkDeptNameUnique",
+		                type: "post",
+		                dataType: "json",
+		                data: {
+		                	"deptId": function() {
+		                        return $("#deptId").val();
+		                    },
+		                    "parentId": function() {
+		                        return $("input[name='parentId']").val();
+		                    },
+		        			"deptName": function() {
+		                        return $.common.trim($("#deptName").val());
+		                    }
+		                }
+		            }
+				},
+				orderNum:{
+					digits:true
+				},
+				email:{
+                    email:true,
+        		},
+        		phone:{
+        			isPhone:true,
+        		},
+			},
+			messages: {
+		        "deptName": {
+		            remote: "部门已经存在"
+		        }
+		    },
+		    focusCleanup: true
+		});
+		
+		function submitHandler() {
+	        if ($.validate.form()) {
+	        	$.operate.save(prefix + "/edit", $('#form-dept-edit').serialize());
+	        }
+	    }
+	
+		/*部门管理-修改-选择部门树*/
+		function selectDeptTree() {
+			var deptId = $("#treeId").val();
+			var excludeId = $("input[name='deptId']").val();
+			if(deptId > 0) {
+			    var options = {
+					title: '部门选择',
+					width: "380",
+					url: prefix + "/selectDeptTree/" + $("#treeId").val() + "/" + excludeId,
+					callBack: doSubmit
+				};
+				$.modal.openOptions(options);
+			} else {
+        		$.modal.alertError("父部门不能选择");
+        	}
+		}
+		
+		function doSubmit(index, layero){
+			var tree = layero.find("iframe")[0].contentWindow.$._tree;
+			if ($.tree.notAllowLastLevel(tree)) {
+	   			var body = $.modal.getChildFrame(index);
+	   			$("#treeId").val(body.find('#treeId').val());
+	   			$("#treeName").val(body.find('#treeName').val());
+	   			$.modal.close(index);
+			}
+		}
+	</script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/system/dept/tree.html b/ruoyi-admin/src/main/resources/templates/system/dept/tree.html
new file mode 100644
index 0000000..4c32182
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/system/dept/tree.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+	<th:block th:include="include :: header('部门树选择')" />
+	<th:block th:include="include :: ztree-css" />
+</head>
+<style>
+	body{height:auto;font-family: "Microsoft YaHei";}
+	button{font-family: "SimSun","Helvetica Neue",Helvetica,Arial;}
+</style>
+<body class="hold-transition box box-main">
+	<input id="treeId"   name="treeId"    type="hidden" th:value="${dept.deptId}"/>
+	<input id="treeName" name="treeName"  type="hidden" th:value="${dept.deptName}"/>
+	<div class="wrapper"><div class="treeShowHideButton" onclick="$.tree.toggleSearch();">
+		<label id="btnShow" title="显示搜索" style="display:none;">︾</label>
+		<label id="btnHide" title="隐藏搜索">︽</label>
+	</div>
+	<div class="treeSearchInput" id="search">
+		<label for="keyword">关键字:</label><input type="text" class="empty" id="keyword" maxlength="50">
+		<button class="btn" id="btn" onclick="$.tree.searchNode()"> 搜索 </button>
+	</div>
+	<div class="treeExpandCollapse">
+		<a href="javascript:;" onclick="$.tree.expand()">展开</a> /
+		<a href="javascript:;" onclick="$.tree.collapse()">折叠</a>
+	</div>
+	<div id="tree" class="ztree treeselect"></div>
+	</div>
+	<th:block th:include="include :: footer" />
+	<th:block th:include="include :: ztree-js" />
+	<script th:inline="javascript">
+	    var prefix = ctx + "system/dept"
+	    var deptId = [[${deptId}]];
+	    var excludeId = [[${excludeId}]];
+		$(function() {
+			var url = prefix + "/treeData/" + excludeId;
+			var options = {
+		        url: url,
+		        expandLevel: 2,
+		        onClick : zOnClick
+		    };
+			$.tree.init(options);
+		});
+		
+		function zOnClick(event, treeId, treeNode) {
+		    var treeId = treeNode.id;
+		    var treeName = treeNode.name;
+		    $("#treeId").val(treeId);
+		    $("#treeName").val(treeName);
+		}
+	</script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/system/dict/data/add.html b/ruoyi-admin/src/main/resources/templates/system/dict/data/add.html
new file mode 100644
index 0000000..a050762
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/system/dict/data/add.html
@@ -0,0 +1,100 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+	<th:block th:include="include :: header('新增字典数据')" />
+</head>
+<body class="white-bg">
+	<div class="wrapper wrapper-content animated fadeInRight ibox-content">
+		<form class="form-horizontal m" id="form-dict-add">
+			<div class="form-group">
+				<label class="col-sm-3 control-label is-required">字典标签:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="dictLabel" id="dictLabel" required>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label is-required">字典键值:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="dictValue" id="dictValue" required>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">字典类型:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" id="dictType" name="dictType" readonly="true" th:value="${dictType}">
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">样式属性:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" id="cssClass" name="cssClass">
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label is-required">字典排序:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="dictSort" required>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">回显样式:</label>
+				<div class="col-sm-8">
+					<select name="listClass" class="form-control m-b">
+					    <option value="">---请选择---</option>
+	                    <option value="default">默认</option>
+	                    <option value="primary">主要</option>
+	                    <option value="success">成功</option>
+	                    <option value="info">   信息</option>
+	                    <option value="warning">警告</option>
+	                    <option value="danger"> 危险</option>
+	                </select>
+	                <span class="help-block m-b-none"><i class="fa fa-info-circle"></i> table表格字典列显示样式属性</span>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">系统默认:</label>
+				<div class="col-sm-8">
+				    <div class="radio-box" th:each="dict : ${@dict.getType('sys_yes_no')}">
+						<input type="radio" th:id="${dict.dictCode}" name="isDefault" th:value="${dict.dictValue}" th:checked="${dict.default}">
+						<label th:for="${dict.dictCode}" th:text="${dict.dictLabel}"></label>
+					</div>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">状态:</label>
+				<div class="col-sm-8">
+				    <div class="radio-box" th:each="dict : ${@dict.getType('sys_normal_disable')}">
+						<input type="radio" th:id="${dict.dictCode}" name="status" th:value="${dict.dictValue}" th:checked="${dict.default}">
+						<label th:for="${dict.dictCode}" th:text="${dict.dictLabel}"></label>
+					</div>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">备注:</label>
+				<div class="col-sm-8">
+					<textarea id="remark" name="remark" class="form-control"></textarea>
+				</div>
+			</div>
+		</form>
+	</div>
+	<th:block th:include="include :: footer" />
+	<script type="text/javascript">
+		var prefix = ctx + "system/dict/data";
+	
+		$("#form-dict-add").validate({
+			rules:{
+				dictSort:{
+					digits:true
+				},
+			},
+			focusCleanup: true
+		});
+		
+		function submitHandler() {
+	        if ($.validate.form()) {
+	        	$.operate.save(prefix + "/add", $('#form-dict-add').serialize());
+	        }
+	    }
+	</script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/system/dict/data/data.html b/ruoyi-admin/src/main/resources/templates/system/dict/data/data.html
new file mode 100644
index 0000000..d272bef
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/system/dict/data/data.html
@@ -0,0 +1,152 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('字典数据列表')" />
+	<th:block th:include="include :: select2-css" />
+</head>
+<body class="gray-bg">
+	<div class="container-div">
+		<div class="row">
+			<div class="col-sm-12 search-collapse">
+				<form id="data-form">
+					<div class="select-list">
+						<ul>
+						    <li>
+								字典名称:<select id="dictType" name="dictType" class="form-control">
+					                <option th:each="dict : ${dictList}" th:text="${dict['dictName']}" th:value="${dict['dictType']}" th:field="*{dict.dictType}"></option>
+								</select>
+							</li>
+							<li>
+								字典标签:<input type="text" name="dictLabel"/>
+							</li>
+							<li>
+								数据状态:<select name="status" th:with="type=${@dict.getType('sys_normal_disable')}">
+									      <option value="">所有</option>
+									      <option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
+								      </select>
+							</li>
+							<li>
+								<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
+							    <a class="btn btn-warning btn-rounded btn-sm" onclick="resetPre()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
+							</li>
+						</ul>
+					</div>
+				</form>
+			</div>
+			
+	       <div class="btn-group-sm" id="toolbar" role="group">
+	            <a class="btn btn-success" onclick="add()" shiro:hasPermission="system:dict:add">
+	                <i class="fa fa-plus"></i> 新增
+	            </a>
+	            <a class="btn btn-primary single disabled" onclick="$.operate.edit()" shiro:hasPermission="system:dict:edit">
+		            <i class="fa fa-edit"></i> 修改
+		        </a>
+				<a class="btn btn-danger multiple disabled" onclick="$.operate.removeAll()" shiro:hasPermission="system:dict:remove">
+		            <i class="fa fa-remove"></i> 删除
+		        </a>
+		        <a class="btn btn-warning" onclick="$.table.exportExcel()" shiro:hasPermission="system:dict:export">
+		            <i class="fa fa-download"></i> 导出
+		        </a>
+		        <a class="btn btn-danger" onclick="closeItem()">
+		            <i class="fa fa-reply-all"></i> 关闭
+		        </a>
+	        </div>
+	        
+	        <div class="col-sm-12 select-table table-striped">
+			    <table id="bootstrap-table"></table>
+			</div>
+		</div>
+	</div>
+	<th:block th:include="include :: footer" />
+	<th:block th:include="include :: select2-js" />
+	<script th:inline="javascript">
+		var editFlag = [[${@permission.hasPermi('system:dict:edit')}]];
+		var removeFlag = [[${@permission.hasPermi('system:dict:remove')}]];
+		var datas = [[${@dict.getType('sys_normal_disable')}]];
+		var prefix = ctx + "system/dict/data";
+
+		$(function() {
+			var options = {
+				url: prefix + "/list",
+				createUrl: prefix + "/add/{id}",
+				updateUrl: prefix + "/edit/{id}",
+				removeUrl: prefix + "/remove",
+				exportUrl: prefix + "/export",
+				queryParams: queryParams,
+				sortName: "dictSort",
+		        sortOrder: "asc",
+				modalName: "数据",
+				columns: [{
+						checkbox: true
+					},
+					{
+						field: 'dictCode',
+						title: '字典编码'
+					},
+					{
+						field: 'dictLabel',
+						title: '字典标签',
+						formatter: function(value, row, index) {
+							var listClass = $.common.equals("default", row.listClass) || $.common.isEmpty(row.listClass) ? "" : "badge badge-" + row.listClass;
+							var cssClass = $.common.isNotEmpty(row.cssClass) ? row.cssClass : listClass;
+							return $.common.sprintf("<span class='%s'>%s</span>", cssClass, value);
+						}
+					},
+					{
+						field: 'dictValue',
+						title: '字典键值'
+					},
+					{
+						field: 'dictSort',
+						title: '字典排序'
+					},
+					{
+						field: 'status',
+						title: '状态',
+						align: 'center',
+						formatter: function(value, row, index) {
+							return $.table.selectDictLabel(datas, value);
+						}
+					},
+					{
+						field: 'remark',
+						title: '备注'
+					},
+					{
+						field: 'createTime',
+						title: '创建时间',
+						sortable: true
+					},
+					{
+						title: '操作',
+						align: 'center',
+						formatter: function(value, row, index) {
+							var actions = [];
+							actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.dictCode + '\')"><i class="fa fa-edit"></i>编辑</a> ');
+							actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.dictCode + '\')"><i class="fa fa-remove"></i>删除</a>');
+							return actions.join('');
+						}
+					}]
+				};
+			$.table.init(options);
+		});
+		
+		function queryParams(params) {
+			var search = $.table.queryParams(params);
+			search.dictType = $("#dictType").val();
+			return search;
+		}
+		
+		/*字典数据-新增字典*/
+		function add() {
+		    var dictType = $("#dictType option:selected").val();
+		    $.operate.add(dictType);
+		}
+		
+		function resetPre() {
+			$.form.reset();
+			$("#dictType").val($("#dictType").val()).trigger("change");
+		}
+	</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/system/dict/data/edit.html b/ruoyi-admin/src/main/resources/templates/system/dict/data/edit.html
new file mode 100644
index 0000000..0855513
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/system/dict/data/edit.html
@@ -0,0 +1,101 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+	<th:block th:include="include :: header('修改字典数据')" />
+</head>
+<body class="white-bg">
+	<div class="wrapper wrapper-content animated fadeInRight ibox-content">
+		<form class="form-horizontal m" id="form-dict-edit" th:object="${dict}">
+			<input name="dictCode"  type="hidden"  th:field="*{dictCode}" />
+			<div class="form-group">
+				<label class="col-sm-3 control-label is-required">字典标签:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="dictLabel" id="dictLabel" th:field="*{dictLabel}" required>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label is-required">字典键值:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="dictValue" id="dictValue" th:field="*{dictValue}" required>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">字典类型:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" readonly="true" th:field="*{dictType}">
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">样式属性:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" id="cssClass" name="cssClass" th:field="*{cssClass}">
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label is-required">字典排序:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="dictSort" th:field="*{dictSort}" required>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">回显样式:</label>
+				<div class="col-sm-8">
+					<select name="listClass" class="form-control m-b">
+					    <option value=""        th:field="*{listClass}">---请选择---</option>
+	                    <option value="default" th:field="*{listClass}">默认</option>
+	                    <option value="primary" th:field="*{listClass}">主要</option>
+	                    <option value="success" th:field="*{listClass}">成功</option>
+	                    <option value="info"    th:field="*{listClass}">信息</option>
+	                    <option value="warning" th:field="*{listClass}">警告</option>
+	                    <option value="danger"  th:field="*{listClass}">危险</option>
+	                </select>
+	                <span class="help-block m-b-none"><i class="fa fa-info-circle"></i> table表格字典列显示样式属性</span>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">系统默认:</label>
+				<div class="col-sm-8">
+					<div class="radio-box" th:each="dict : ${@dict.getType('sys_yes_no')}">
+						<input type="radio" th:id="${dict.dictCode}" name="isDefault" th:value="${dict.dictValue}" th:field="*{isDefault}">
+						<label th:for="${dict.dictCode}" th:text="${dict.dictLabel}"></label>
+					</div>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">状态:</label>
+				<div class="col-sm-8">
+					<div class="radio-box" th:each="dict : ${@dict.getType('sys_normal_disable')}">
+						<input type="radio" th:id="${dict.dictCode}" name="status" th:value="${dict.dictValue}" th:field="*{status}">
+						<label th:for="${dict.dictCode}" th:text="${dict.dictLabel}"></label>
+					</div>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">备注:</label>
+				<div class="col-sm-8">
+					<textarea id="remark" name="remark" class="form-control">[[*{remark}]]</textarea>
+				</div>
+			</div>
+		</form>
+	</div>
+	<th:block th:include="include :: footer" />
+	<script type="text/javascript">
+		var prefix = ctx + "system/dict/data";
+	
+		$("#form-dict-edit").validate({
+			rules:{
+				dictSort:{
+					digits:true
+				},
+			},
+			focusCleanup: true
+		});
+		
+		function submitHandler() {
+	        if ($.validate.form()) {
+	        	$.operate.save(prefix + "/edit", $('#form-dict-edit').serialize());
+	        }
+	    }
+	</script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/system/dict/type/add.html b/ruoyi-admin/src/main/resources/templates/system/dict/type/add.html
new file mode 100644
index 0000000..ee3e439
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/system/dict/type/add.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+	<th:block th:include="include :: header('新增字典类型')" />
+</head>
+<body class="white-bg">
+	<div class="wrapper wrapper-content animated fadeInRight ibox-content">
+		<form class="form-horizontal m" id="form-dict-add">
+			<div class="form-group">
+				<label class="col-sm-3 control-label is-required">字典名称:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="dictName" id="dictName" required>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label is-required">字典类型:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="dictType" id="dictType" required>
+					<span class="help-block m-b-none"><i class="fa fa-info-circle"></i> 数据存储中的Key值,如:sys_user_sex</span>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">状态:</label>
+				<div class="col-sm-8">
+				    <div class="radio-box" th:each="dict : ${@dict.getType('sys_normal_disable')}">
+						<input type="radio" th:id="${dict.dictCode}" name="status" th:value="${dict.dictValue}" th:checked="${dict.default}">
+						<label th:for="${dict.dictCode}" th:text="${dict.dictLabel}"></label>
+					</div>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">备注:</label>
+				<div class="col-sm-8">
+					<textarea id="remark" name="remark" class="form-control"></textarea>
+				</div>
+			</div>
+		</form>
+	</div>
+	<th:block th:include="include :: footer" />
+	<script type="text/javascript">
+		var prefix = ctx + "system/dict";
+	
+		$("#form-dict-add").validate({
+			onkeyup: false,
+			rules:{
+				dictType:{
+					minlength: 5,
+					remote: {
+		                url: prefix + "/checkDictTypeUnique",
+		                type: "post",
+		                dataType: "json",
+		                data: {
+		                	name : function() {
+		                        return $.common.trim($("#dictType").val());
+		                    }
+		                }
+		            }
+				},
+			},
+			messages: {
+		        "dictType": {
+		            remote: "该字典类型已经存在"
+		        }
+		    },
+		    focusCleanup: true
+		});
+		
+		function submitHandler() {
+	        if ($.validate.form()) {
+	        	$.operate.save(prefix + "/add", $('#form-dict-add').serialize());
+	        }
+	    }
+	</script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/system/dict/type/edit.html b/ruoyi-admin/src/main/resources/templates/system/dict/type/edit.html
new file mode 100644
index 0000000..af7523f
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/system/dict/type/edit.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+	<th:block th:include="include :: header('修改字典类型')" />
+</head>
+<body class="white-bg">
+	<div class="wrapper wrapper-content animated fadeInRight ibox-content">
+		<form class="form-horizontal m" id="form-dict-edit" th:object="${dict}">
+			<input id="dictId" name="dictId"  type="hidden" th:field="*{dictId}" />
+			<div class="form-group">
+				<label class="col-sm-3 control-label is-required">字典名称:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="dictName" id="dictName" th:field="*{dictName}" required>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label is-required">字典类型:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="dictType" id="dictType" th:field="*{dictType}" required>
+					<span class="help-block m-b-none"><i class="fa fa-info-circle"></i> 数据存储中的Key值,如:sys_user_sex</span>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">状态:</label>
+				<div class="col-sm-8">
+					<div class="radio-box" th:each="dict : ${@dict.getType('sys_normal_disable')}">
+						<input type="radio" th:id="${dict.dictCode}" name="status" th:value="${dict.dictValue}" th:field="*{status}">
+						<label th:for="${dict.dictCode}" th:text="${dict.dictLabel}"></label>
+					</div>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">备注:</label>
+				<div class="col-sm-8">
+					<textarea id="remark" name="remark" class="form-control">[[*{remark}]]</textarea>
+				</div>
+			</div>
+		</form>
+	</div>
+	<th:block th:include="include :: footer" />
+	<script type="text/javascript">
+		var prefix = ctx + "system/dict";
+	
+		$("#form-dict-edit").validate({
+			onkeyup: false,
+			rules:{
+				dictType:{
+					minlength: 5,
+					remote: {
+		                url: prefix + "/checkDictTypeUnique",
+		                type: "post",
+		                dataType: "json",
+		                data: {
+		                	dictId : function() {
+		                        return $("#dictId").val();
+		                    },
+		                	dictType : function() {
+		                		return $.common.trim($("#dictType").val());
+		                    }
+		                }
+		            }
+				},
+			},
+			messages: {
+		        "dictType": {
+		            remote: "该字典类型已经存在"
+		        }
+		    },
+		    focusCleanup: true
+		});
+		
+		function submitHandler() {
+	        if ($.validate.form()) {
+	        	$.operate.save(prefix + "/edit", $('#form-dict-edit').serialize());
+	        }
+	    }
+	</script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/system/dict/type/tree.html b/ruoyi-admin/src/main/resources/templates/system/dict/type/tree.html
new file mode 100644
index 0000000..88ea049
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/system/dict/type/tree.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+	<th:block th:include="include :: header('字典树选择')" />
+	<th:block th:include="include :: ztree-css" />
+</head>
+<style>
+	body{height:auto;font-family: "Microsoft YaHei";}
+	button{font-family: "SimSun","Helvetica Neue",Helvetica,Arial;}
+</style>
+<body class="hold-transition box box-main">
+	<input id="columnId" type="hidden" th:value="${columnId}"/>
+	<input id="treeId"   type="hidden" th:value="${dict?.dictId}"/>
+	<input id="dictType" type="hidden" th:value="${dict?.dictType}"/>
+	<div class="wrapper"><div class="treeShowHideButton" onclick="$.tree.toggleSearch();">
+		<label id="btnShow" title="显示搜索" style="display:none;">︾</label>
+		<label id="btnHide" title="隐藏搜索">︽</label>
+	</div>
+	<div class="treeSearchInput" id="search">
+		<label for="keyword">关键字:</label><input type="text" class="empty" id="keyword" maxlength="50">
+		<button class="btn" id="btn" onclick="$.tree.searchNode()"> 搜索 </button>
+	</div>
+	<div id="tree" class="ztree treeselect"></div>
+	</div>
+	<th:block th:include="include :: footer" />
+	<th:block th:include="include :: ztree-js" />
+	<script th:inline="javascript">
+		$(function() {
+			var url = ctx + "system/dict/treeData";
+			var options = {
+		        url: url,
+		        onClick : zOnClick
+		    };
+			$.tree.init(options);
+		});
+		
+		function zOnClick(event, treeId, treeNode) {
+		    $("#dictType").val(treeNode.title);
+		}
+	</script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/system/dict/type/type.html b/ruoyi-admin/src/main/resources/templates/system/dict/type/type.html
new file mode 100644
index 0000000..27646f2
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/system/dict/type/type.html
@@ -0,0 +1,148 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('字典类型列表')" />
+</head>
+<body class="gray-bg">
+	<div class="container-div">
+		<div class="row">
+			<div class="col-sm-12 search-collapse">
+				<form id="type-form">
+					<div class="select-list">
+						<ul>
+							<li>
+								字典名称:<input type="text" name="dictName"/>
+							</li>
+							<li>
+								字典类型:<input type="text" name="dictType"/>
+							</li>
+							<li>
+								字典状态:<select name="status" th:with="type=${@dict.getType('sys_normal_disable')}">
+									<option value="">所有</option>
+									<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
+								</select>
+							</li>
+							<li class="select-time">
+								<label>创建时间: </label>
+								<input type="text" class="time-input" id="startTime" placeholder="开始时间" name="params[beginTime]"/>
+								<span>-</span>
+								<input type="text" class="time-input" id="endTime" placeholder="结束时间" name="params[endTime]"/>
+							</li>
+							<li>
+								<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
+							    <a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
+							</li>
+						</ul>
+					</div>
+				</form>
+			</div>
+			
+	       <div class="btn-group-sm" id="toolbar" role="group">
+	            <a class="btn btn-success" onclick="$.operate.add()" shiro:hasPermission="system:dict:add">
+	                <i class="fa fa-plus"></i> 新增
+	            </a>
+	            <a class="btn btn-primary single disabled" onclick="$.operate.edit()" shiro:hasPermission="system:dict:edit">
+		            <i class="fa fa-edit"></i> 修改
+		        </a>
+				<a class="btn btn-danger multiple disabled" onclick="$.operate.removeAll()" shiro:hasPermission="system:dict:remove">
+		            <i class="fa fa-remove"></i> 删除
+		        </a>
+		        <a class="btn btn-warning" onclick="$.table.exportExcel()" shiro:hasPermission="system:dict:export">
+		            <i class="fa fa-download"></i> 导出
+		        </a>
+		        <a class="btn btn-danger" onclick="refreshCache()" shiro:hasPermission="system:dict:remove">
+		            <i class="fa fa-refresh"></i> 刷新缓存
+		        </a>
+	        </div>
+	        
+	        <div class="col-sm-12 select-table table-striped">
+			    <table id="bootstrap-table"></table>
+			</div>
+		</div>
+	</div>
+	<th:block th:include="include :: footer" />
+	<script th:inline="javascript">
+		var editFlag = [[${@permission.hasPermi('system:dict:edit')}]];
+		var listFlag = [[${@permission.hasPermi('system:dict:list')}]];
+		var removeFlag = [[${@permission.hasPermi('system:dict:remove')}]];
+		var datas = [[${@dict.getType('sys_normal_disable')}]];
+		var prefix = ctx + "system/dict";
+
+		$(function() {
+		    var options = {
+		        url: prefix + "/list",
+		        createUrl: prefix + "/add",
+		        updateUrl: prefix + "/edit/{id}",
+		        removeUrl: prefix + "/remove",
+		        exportUrl: prefix + "/export",
+		        sortName: "dictId",
+		        sortOrder: "asc",
+		        modalName: "类型",
+		        columns: [{
+		            checkbox: true
+		        },
+		        {
+		            field: 'dictId',
+		            title: '字典主键'
+		        },
+		        {
+		            field: 'dictName',
+		            title: '字典名称',
+		            sortable: true
+		        },
+		        {
+		            field: 'dictType',
+		            title: '字典类型',
+		            sortable: true,
+		            formatter: function(value, row, index) {
+		                return '<a href="javascript:void(0)" onclick="detail(\'' + row.dictId + '\')">' + value + '</a>';
+		            }
+		        },
+		        {
+		            field: 'status',
+		            title: '状态',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		            	return $.table.selectDictLabel(datas, value);
+		            }
+		        },
+		        {
+		            field: 'remark',
+		            title: '备注',
+		            formatter: function(value, row, index) {
+                        return $.table.tooltip(value);
+			        }
+		        },
+		        {
+		            field: 'createTime',
+		            title: '创建时间',
+		            sortable: true
+		        },
+		        {
+		            title: '操作',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		                var actions = [];
+		                actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.dictId + '\')"><i class="fa fa-edit"></i>编辑</a> ');
+		                actions.push('<a class="btn btn-info btn-xs ' + listFlag + '" href="javascript:void(0)" onclick="detail(\'' + row.dictId + '\')"><i class="fa fa-list-ul"></i>列表</a> ');
+		                actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.dictId + '\')"><i class="fa fa-remove"></i>删除</a>');
+		                return actions.join('');
+		            }
+		        }]
+		    };
+		    $.table.init(options);
+		});
+
+		/*字典列表-详细*/
+		function detail(dictId) {
+		    var url = prefix + '/detail/' + dictId;
+		    $.modal.openTab("字典数据", url);
+		}
+		
+		/** 刷新字典缓存 */
+        function refreshCache() {
+            $.operate.get(prefix + "/refreshCache");
+        }
+	</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/system/menu/add.html b/ruoyi-admin/src/main/resources/templates/system/menu/add.html
new file mode 100644
index 0000000..10b32b6
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/system/menu/add.html
@@ -0,0 +1,196 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+	<th:block th:include="include :: header('新增菜单')" />
+</head>
+<body class="white-bg">
+	<div class="wrapper wrapper-content animated fadeInRight ibox-content">
+		<form class="form-horizontal m" id="form-menu-add">
+			<input id="treeId" name="parentId" type="hidden" th:value="${menu.menuId}" />
+			<div class="form-group">
+				<label class="col-sm-3 control-label">上级菜单:</label>
+				<div class="col-sm-8">
+				    <div class="input-group">
+					    <input class="form-control" type="text" onclick="selectMenuTree()" id="treeName" readonly="true" th:value="${menu.menuName}">
+				        <span class="input-group-addon"><i class="fa fa-search"></i></span>
+				    </div>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label is-required">菜单类型:</label>
+				<div class="col-sm-8">
+					<label class="radio-box"> <input type="radio" name="menuType" value="M" /> 目录 </label> 
+					<label class="radio-box"> <input type="radio" name="menuType" value="C" /> 菜单 </label> 
+					<label class="radio-box"> <input type="radio" name="menuType" value="F" /> 按钮 </label>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label is-required">菜单名称:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="menuName" id="menuName" required>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label" title="访问的请求地址,如:`/system/user`,如外网地址需内链访问则以`http(s)://`开头">请求地址:<i class="fa fa-question-circle-o"></i></label>
+				<div class="col-sm-8">
+					<input id="url" name="url" class="form-control" type="text">
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">打开方式:</label>
+				<div class="col-sm-8">
+					<select id="target" name="target" class="form-control m-b">
+	                    <option value="menuItem">页签</option>
+	                    <option value="menuBlank">新窗口</option>
+	                </select>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">权限标识:</label>
+				<div class="col-sm-8">
+					<input id="perms" name="perms" class="form-control" type="text">
+					<span class="help-block m-b-none"><i class="fa fa-info-circle"></i> 控制器中定义的权限标识,如:@RequiresPermissions("")</span>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label is-required" title="数字越小越靠前">显示排序:<i class="fa fa-question-circle-o"></i></label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="orderNum" required>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label" title="单击选择需要使用的FontAwesome图标">图标:<i class="fa fa-question-circle-o"></i></label>
+				<div class="col-sm-8">
+					<input id="icon" name="icon" class="form-control" type="text" placeholder="选择图标">
+                    <div class="ms-parent" style="width: 100%;">
+                        <div class="icon-drop animated flipInX" style="display: none;max-height:200px;overflow-y:auto">
+                            <div data-th-include="system/menu/icon"></div>
+                        </div>
+                    </div>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label" title="选择隐藏则菜单将不会出现在侧边栏,也没有权限被访问">菜单状态:<i class="fa fa-question-circle-o"></i></label>
+				<div class="col-sm-3">
+				    <div class="radio-box" th:each="dict : ${@dict.getType('sys_show_hide')}">
+						<input type="radio" th:id="${dict.dictCode}" name="visible" th:value="${dict.dictValue}" th:checked="${dict.default}">
+						<label th:for="${dict.dictCode}" th:text="${dict.dictLabel}"></label>
+					</div>
+				</div>
+				<label class="col-sm-2 control-label is-refresh" title="打开菜单选项卡是否刷新页面">是否刷新:<i class="fa fa-question-circle-o"></i></label>
+				<div class="col-sm-3 is-refresh">
+				    <div class="radio-box">
+						<input type="radio" id="refresh-no" name="isRefresh" value="1" checked>
+						<label for="refresh-no">否</label>
+					</div>
+					<div class="radio-box">
+						<input type="radio" id="refresh-yes" name="isRefresh" value="0">
+						<label for="refresh-yes">是</label>
+					</div>
+				</div>
+			</div>
+		</form>
+	</div>
+	<th:block th:include="include :: footer" />
+	 <script>
+        var prefix = ctx + "system/menu";
+        
+        $("#form-menu-add").validate({
+        	onkeyup: false,
+        	rules:{
+        		menuType:{
+        			required:true,
+        		},
+        		menuName:{
+        			remote: {
+                        url: prefix + "/checkMenuNameUnique",
+                        type: "post",
+                        dataType: "json",
+                        data: {
+                        	"parentId": function() {
+		                		return $("input[name='parentId']").val();
+		                    },
+                        	"menuName" : function() {
+                                return $.common.trim($("#menuName").val());
+                            }
+                        }
+                    }
+        		},
+        		orderNum:{
+        			digits:true
+        		},
+        	},
+        	messages: {
+                "menuName": {
+                    remote: "菜单已经存在"
+                }
+            },
+            focusCleanup: true
+        });
+        
+        function submitHandler() {
+	        if ($.validate.form()) {
+	            $.operate.save(prefix + "/add", $('#form-menu-add').serialize());
+	        }
+	    }
+
+        $(function() {
+        	$("input[name='icon']").focus(function() {
+                $(".icon-drop").show();
+            });
+        	$("#form-menu-add").click(function(event) {
+        	    var obj = event.srcElement || event.target;
+        	    if (!$(obj).is("input[name='icon']")) {
+        	    	$(".icon-drop").hide();
+        	    }
+        	});
+        	$(".icon-drop").find(".ico-list i").on("click", function() {
+        		$('#icon').val($(this).attr('class'));
+            });
+        	$('input').on('ifChecked', function(event){  
+        		var menuType = $(event.target).val();
+        		if (menuType == "M") {
+                    $("#url").parents(".form-group").hide();
+                    $("#perms").parents(".form-group").hide();
+                    $("#icon").parents(".form-group").show();
+                    $("#target").parents(".form-group").hide();
+                    $(".is-refresh").hide();
+                } else if (menuType == "C") {
+                	$("#url").parents(".form-group").show();
+                    $("#perms").parents(".form-group").show();
+                    $("#icon").parents(".form-group").show();
+                    $("#target").parents(".form-group").show();
+                    $(".is-refresh").show();
+                } else if (menuType == "F") {
+                	$("#url").parents(".form-group").hide();
+                    $("#perms").parents(".form-group").show();
+                    $("#icon").parents(".form-group").hide();
+                    $("#target").parents(".form-group").hide();
+                    $(".is-refresh").hide();
+                }
+        	});  
+        });
+
+        /*菜单管理-新增-选择菜单树*/
+        function selectMenuTree() {
+        	var treeId = $("#treeId").val();
+        	var menuId = treeId > 0 ? treeId : 1;
+        	var url = prefix + "/selectMenuTree/" + menuId;
+			var options = {
+				title: '菜单选择',
+				width: "380",
+				url: url,
+				callBack: doSubmit
+			};
+			$.modal.openOptions(options);
+		}
+		
+		function doSubmit(index, layero){
+			var body = $.modal.getChildFrame(index);
+   			$("#treeId").val(body.find('#treeId').val());
+   			$("#treeName").val(body.find('#treeName').val());
+   			$.modal.close(index);
+		}
+    </script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/system/menu/edit.html b/ruoyi-admin/src/main/resources/templates/system/menu/edit.html
new file mode 100644
index 0000000..b60380f
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/system/menu/edit.html
@@ -0,0 +1,224 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+	<th:block th:include="include :: header('修改菜单')" />
+</head>
+<body class="white-bg">
+	<div class="wrapper wrapper-content animated fadeInRight ibox-content">
+		<form class="form-horizontal m" id="form-menu-edit" th:object="${menu}">
+			<input name="menuId"   type="hidden" th:field="*{menuId}"   />
+			<input id="treeId" name="parentId" type="hidden" th:field="*{parentId}" />
+			<div class="form-group">
+				<label class="col-sm-3 control-label">上级菜单:</label>
+				<div class="col-sm-8">
+				    <div class="input-group">
+						<input class="form-control" type="text" onclick="selectMenuTree()" id="treeName" readonly="true" th:value="${menu.parentName == null ? '无' : menu.parentName}">
+					    <span class="input-group-addon"><i class="fa fa-search"></i></span>
+				    </div>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label is-required">菜单类型:</label>
+				<div class="col-sm-8">
+					<label class="radio-box"> <input type="radio" th:field="*{menuType}" name="menuType" value="M" /> 目录 </label> 
+					<label class="radio-box"> <input type="radio" th:field="*{menuType}" name="menuType" value="C" /> 菜单 </label> 
+					<label class="radio-box"> <input type="radio" th:field="*{menuType}" name="menuType" value="F" /> 按钮 </label>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label is-required">菜单名称:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="menuName" id="menuName" th:field="*{menuName}" required>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label" title="访问的请求地址,如:`/system/user`,如外网地址需内链访问则以`http(s)://`开头">请求地址:<i class="fa fa-question-circle-o"></i></label>
+				<div class="col-sm-8">
+					<input id="url" name="url" class="form-control" type="text" th:field="*{url}">
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">打开方式:</label>
+				<div class="col-sm-8">
+					<select id="target" name="target" class="form-control m-b">
+	                    <option value="menuItem" th:field="*{target}">页签</option>
+	                    <option value="menuBlank" th:selected="*{target == 'menuBlank'}">新窗口</option>
+	                </select>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">权限标识:</label>
+				<div class="col-sm-8">
+					<input id="perms" name="perms" class="form-control" type="text" th:field="*{perms}">
+				    <span class="help-block m-b-none"><i class="fa fa-info-circle"></i> 控制器中定义的权限标识,如:@RequiresPermissions("")</span>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label is-required" title="数字越小越靠前">显示排序:<i class="fa fa-question-circle-o"></i></label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="orderNum" th:field="*{orderNum}" required>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label" title="单击选择需要使用的FontAwesome图标">图标:<i class="fa fa-question-circle-o"></i></label>
+				<div class="col-sm-8">
+					<input id="icon" name="icon" class="form-control" type="text" placeholder="选择图标" th:field="*{icon}">
+                    <div class="ms-parent" style="width: 100%;">
+                        <div class="icon-drop animated flipInX" style="display: none;max-height:200px;overflow-y:auto">
+                            <div data-th-include="system/menu/icon"></div>
+                        </div>
+                    </div>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label" title="选择隐藏则菜单将不会出现在侧边栏,也没有权限被访问">菜单状态:<i class="fa fa-question-circle-o"></i></label>
+				<div class="col-sm-3">
+					<div class="radio-box" th:each="dict : ${@dict.getType('sys_show_hide')}">
+						<input type="radio" th:id="${dict.dictCode}" name="visible" th:value="${dict.dictValue}" th:field="*{visible}">
+						<label th:for="${dict.dictCode}" th:text="${dict.dictLabel}"></label>
+					</div>
+				</div>
+				<label class="col-sm-2 control-label is-refresh" title="打开菜单选项卡是否刷新页面">是否刷新:<i class="fa fa-question-circle-o"></i></label>
+				<div class="col-sm-3 is-refresh">
+				    <div class="radio-box">
+						<input type="radio" id="refresh-no" name="isRefresh" value="1" th:field="*{isRefresh}">
+						<label for="refresh-no">否</label>
+					</div>
+					<div class="radio-box">
+						<input type="radio" id="refresh-yes" name="isRefresh" value="0" th:field="*{isRefresh}">
+						<label for="refresh-yes">是</label>
+					</div>
+				</div>
+			</div>
+		</form>
+	</div>
+	<th:block th:include="include :: footer" />
+	 <script>
+        var prefix = ctx + "system/menu";
+
+        $(function() {
+            var menuType = $('input[name="menuType"]:checked').val();
+            menuVisible(menuType);
+        });
+
+        $("#form-menu-edit").validate({
+        	onkeyup: false,
+        	rules:{
+        		menuType:{
+        			required:true,
+        		},
+        		menuName:{
+        			remote: {
+                        url: prefix + "/checkMenuNameUnique",
+                        type: "post",
+                        dataType: "json",
+                        data: {
+                        	"menuId": function() {
+                                return $("#menuId").val();
+                            },
+                            "parentId": function() {
+		                		return $("input[name='parentId']").val();
+		                    },
+                			"menuName": function() {
+                                return $.common.trim($("#menuName").val());
+                            }
+                        }
+                    }
+        		},
+        		orderNum:{
+        			digits:true
+        		},
+        	},
+        	messages: {
+                "menuName": {
+                    remote: "菜单已经存在"
+                }
+            },
+            focusCleanup: true
+        });
+        
+        function submitHandler() {
+	        if ($.validate.form()) {
+	            $.operate.save(prefix + "/edit", $('#form-menu-edit').serialize());
+	        }
+	    }
+
+        $(function() {
+            $("input[name='icon']").focus(function() {
+                $(".icon-drop").show();
+            });
+            $("#form-menu-edit").click(function(event) {
+                var obj = event.srcElement || event.target;
+                if (!$(obj).is("input[name='icon']")) {
+                    $(".icon-drop").hide();
+                }
+            });
+            $(".icon-drop").find(".ico-list i").on("click",
+            function() {
+                $('#icon').val($(this).attr('class'));
+            });
+            $('input').on('ifChecked',
+            function(event) {
+                var menuType = $(event.target).val();
+                menuVisible(menuType);
+            });
+        });
+
+        function menuVisible(menuType) {
+            if (menuType == "M") {
+                $("#url").parents(".form-group").hide();
+                $("#perms").parents(".form-group").hide();
+                $("#icon").parents(".form-group").show();
+                $("#target").parents(".form-group").hide();
+                $(".is-refresh").hide();
+            } else if (menuType == "C") {
+                $("#url").parents(".form-group").show();
+                $("#perms").parents(".form-group").show();
+                $("#icon").parents(".form-group").show();
+                $("#target").parents(".form-group").show();
+                $(".is-refresh").show();
+            } else if (menuType == "F") {
+                $("#url").parents(".form-group").hide();
+                $("#perms").parents(".form-group").show();
+                $("#icon").parents(".form-group").hide();
+                $("#target").parents(".form-group").hide();
+                $(".is-refresh").hide();
+            }
+        }
+
+        /*菜单管理-修改-选择菜单树*/
+        function selectMenuTree() {
+        	var menuId = $("#treeId").val();
+        	if(menuId > 0) {
+        		var url = prefix + "/selectMenuTree/" + menuId;
+        		$.modal.open("选择菜单", url, '380', '380');
+        	} else {
+        		$.modal.alertError("主菜单不能选择");
+        	}
+        }
+        
+        function selectMenuTree() {
+        	var menuId = $("#treeId").val();
+        	if(menuId > 0) {
+        		var url = prefix + "/selectMenuTree/" + menuId;
+        		var options = {
+       				title: '菜单选择',
+       				width: "380",
+       				url: url,
+       				callBack: doSubmit
+       			};
+       			$.modal.openOptions(options);
+        	} else {
+        		$.modal.alertError("主菜单不能选择");
+        	}
+		}
+		
+		function doSubmit(index, layero){
+			var body = $.modal.getChildFrame(index);
+   			$("#treeId").val(body.find('#treeId').val());
+   			$("#treeName").val(body.find('#treeName').val());
+   			$.modal.close(index);
+		}
+    </script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/system/menu/icon.html b/ruoyi-admin/src/main/resources/templates/system/menu/icon.html
new file mode 100644
index 0000000..f9f7f19
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/system/menu/icon.html
@@ -0,0 +1,928 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+    <meta charset="UTF-8">
+    <title>Font Awesome Ico list</title>
+    <link href="/css/font-awesome.min.css" th:href="@{/css/font-awesome.min.css}" rel="stylesheet"/>
+    <script src="/js/jquery.min.js"></script>
+    <style type="text/css">
+        .ico-list .fa{
+            margin: 5px;
+            padding: 5px;
+            cursor:pointer;
+            font-size: 18px;
+            width: 28px;
+            border-radius: 3px;
+        }
+        .ico-list .fa:hover {
+            background-color: #1d9d74;
+            color: #ffffff;}
+    </style>
+</head>
+<body>
+<div class="ico-list">
+     <i class="fa fa-address-book" aria-hidden="true"></i>
+
+     <i class="fa fa-address-book-o" aria-hidden="true"></i>
+
+     <i class="fa fa-address-card" aria-hidden="true"></i>
+
+     <i class="fa fa-address-card-o" aria-hidden="true"></i>
+
+     <i class="fa fa-adjust" aria-hidden="true"></i>
+
+     <i class="fa fa-american-sign-language-interpreting" aria-hidden="true"></i>
+
+     <i class="fa fa-anchor" aria-hidden="true"></i>
+
+     <i class="fa fa-archive" aria-hidden="true"></i>
+
+     <i class="fa fa-area-chart" aria-hidden="true"></i>
+
+     <i class="fa fa-arrows" aria-hidden="true"></i>
+
+     <i class="fa fa-arrows-h" aria-hidden="true"></i>
+
+     <i class="fa fa-arrows-v" aria-hidden="true"></i>
+
+     <i class="fa fa-asl-interpreting" aria-hidden="true"></i>
+
+     <i class="fa fa-assistive-listening-systems" aria-hidden="true"></i>
+
+     <i class="fa fa-asterisk" aria-hidden="true"></i>
+
+     <i class="fa fa-at" aria-hidden="true"></i>
+
+     <i class="fa fa-audio-description" aria-hidden="true"></i>
+
+     <i class="fa fa-automobile" aria-hidden="true"></i>
+
+     <i class="fa fa-balance-scale" aria-hidden="true"></i>
+
+     <i class="fa fa-ban" aria-hidden="true"></i>
+
+     <i class="fa fa-bank" aria-hidden="true"></i>
+
+     <i class="fa fa-bar-chart" aria-hidden="true"></i>
+
+     <i class="fa fa-bar-chart-o" aria-hidden="true"></i>
+
+     <i class="fa fa-barcode" aria-hidden="true"></i>
+
+     <i class="fa fa-bars" aria-hidden="true"></i>
+
+     <i class="fa fa-bath" aria-hidden="true"></i>
+
+     <i class="fa fa-bathtub" aria-hidden="true"></i>
+
+     <i class="fa fa-battery" aria-hidden="true"></i>
+
+     <i class="fa fa-battery-0" aria-hidden="true"></i>
+
+     <i class="fa fa-battery-1" aria-hidden="true"></i>
+
+     <i class="fa fa-battery-2" aria-hidden="true"></i>
+
+     <i class="fa fa-battery-3" aria-hidden="true"></i>
+
+     <i class="fa fa-battery-4" aria-hidden="true"></i>
+
+     <i class="fa fa-battery-empty" aria-hidden="true"></i>
+
+     <i class="fa fa-battery-full" aria-hidden="true"></i>
+
+     <i class="fa fa-battery-half" aria-hidden="true"></i>
+
+     <i class="fa fa-battery-quarter" aria-hidden="true"></i>
+
+     <i class="fa fa-battery-three-quarters" aria-hidden="true"></i>
+
+     <i class="fa fa-bed" aria-hidden="true"></i>
+
+     <i class="fa fa-beer" aria-hidden="true"></i>
+
+     <i class="fa fa-bell" aria-hidden="true"></i>
+
+     <i class="fa fa-bell-o" aria-hidden="true"></i>
+
+     <i class="fa fa-bell-slash" aria-hidden="true"></i>
+
+     <i class="fa fa-bell-slash-o" aria-hidden="true"></i>
+
+     <i class="fa fa-bicycle" aria-hidden="true"></i>
+
+     <i class="fa fa-binoculars" aria-hidden="true"></i>
+
+     <i class="fa fa-birthday-cake" aria-hidden="true"></i>
+
+     <i class="fa fa-blind" aria-hidden="true"></i>
+
+     <i class="fa fa-bluetooth" aria-hidden="true"></i>
+
+     <i class="fa fa-bluetooth-b" aria-hidden="true"></i>
+
+     <i class="fa fa-bolt" aria-hidden="true"></i>
+
+     <i class="fa fa-bomb" aria-hidden="true"></i>
+
+     <i class="fa fa-book" aria-hidden="true"></i>
+
+     <i class="fa fa-bookmark" aria-hidden="true"></i>
+
+     <i class="fa fa-bookmark-o" aria-hidden="true"></i>
+
+     <i class="fa fa-braille" aria-hidden="true"></i>
+
+     <i class="fa fa-briefcase" aria-hidden="true"></i>
+
+     <i class="fa fa-bug" aria-hidden="true"></i>
+
+     <i class="fa fa-building" aria-hidden="true"></i>
+
+     <i class="fa fa-building-o" aria-hidden="true"></i>
+
+     <i class="fa fa-bullhorn" aria-hidden="true"></i>
+
+     <i class="fa fa-bullseye" aria-hidden="true"></i>
+
+     <i class="fa fa-bus" aria-hidden="true"></i>
+
+     <i class="fa fa-cab" aria-hidden="true"></i>
+
+     <i class="fa fa-calculator" aria-hidden="true"></i>
+
+     <i class="fa fa-calendar" aria-hidden="true"></i>
+
+     <i class="fa fa-calendar-check-o" aria-hidden="true"></i>
+
+     <i class="fa fa-calendar-minus-o" aria-hidden="true"></i>
+
+     <i class="fa fa-calendar-o" aria-hidden="true"></i>
+
+     <i class="fa fa-calendar-plus-o" aria-hidden="true"></i>
+
+     <i class="fa fa-calendar-times-o" aria-hidden="true"></i>
+
+     <i class="fa fa-camera" aria-hidden="true"></i>
+
+     <i class="fa fa-camera-retro" aria-hidden="true"></i>
+
+     <i class="fa fa-car" aria-hidden="true"></i>
+
+     <i class="fa fa-caret-square-o-down" aria-hidden="true"></i>
+
+     <i class="fa fa-caret-square-o-left" aria-hidden="true"></i>
+
+     <i class="fa fa-caret-square-o-right" aria-hidden="true"></i>
+
+     <i class="fa fa-caret-square-o-up" aria-hidden="true"></i>
+
+     <i class="fa fa-cart-arrow-down" aria-hidden="true"></i>
+
+     <i class="fa fa-cart-plus" aria-hidden="true"></i>
+
+     <i class="fa fa-cc" aria-hidden="true"></i>
+
+     <i class="fa fa-certificate" aria-hidden="true"></i>
+
+     <i class="fa fa-check" aria-hidden="true"></i>
+
+     <i class="fa fa-check-circle" aria-hidden="true"></i>
+
+     <i class="fa fa-check-circle-o" aria-hidden="true"></i>
+
+     <i class="fa fa-check-square" aria-hidden="true"></i>
+
+     <i class="fa fa-check-square-o" aria-hidden="true"></i>
+
+     <i class="fa fa-child" aria-hidden="true"></i>
+
+     <i class="fa fa-circle" aria-hidden="true"></i>
+
+     <i class="fa fa-circle-o" aria-hidden="true"></i>
+
+     <i class="fa fa-circle-o-notch" aria-hidden="true"></i>
+
+     <i class="fa fa-circle-thin" aria-hidden="true"></i>
+
+     <i class="fa fa-clock-o" aria-hidden="true"></i>
+
+     <i class="fa fa-clone" aria-hidden="true"></i>
+
+     <i class="fa fa-close" aria-hidden="true"></i>
+
+     <i class="fa fa-cloud" aria-hidden="true"></i>
+
+     <i class="fa fa-cloud-download" aria-hidden="true"></i>
+
+     <i class="fa fa-cloud-upload" aria-hidden="true"></i>
+
+     <i class="fa fa-code" aria-hidden="true"></i>
+
+     <i class="fa fa-code-fork" aria-hidden="true"></i>
+
+     <i class="fa fa-coffee" aria-hidden="true"></i>
+
+     <i class="fa fa-cog" aria-hidden="true"></i>
+
+     <i class="fa fa-cogs" aria-hidden="true"></i>
+
+     <i class="fa fa-comment" aria-hidden="true"></i>
+
+     <i class="fa fa-comment-o" aria-hidden="true"></i>
+
+     <i class="fa fa-commenting" aria-hidden="true"></i>
+
+     <i class="fa fa-commenting-o" aria-hidden="true"></i>
+
+     <i class="fa fa-comments" aria-hidden="true"></i>
+
+     <i class="fa fa-comments-o" aria-hidden="true"></i>
+
+     <i class="fa fa-compass" aria-hidden="true"></i>
+
+     <i class="fa fa-copyright" aria-hidden="true"></i>
+
+     <i class="fa fa-creative-commons" aria-hidden="true"></i>
+
+     <i class="fa fa-credit-card" aria-hidden="true"></i>
+
+     <i class="fa fa-credit-card-alt" aria-hidden="true"></i>
+
+     <i class="fa fa-crop" aria-hidden="true"></i>
+
+     <i class="fa fa-crosshairs" aria-hidden="true"></i>
+
+     <i class="fa fa-cube" aria-hidden="true"></i>
+
+     <i class="fa fa-cubes" aria-hidden="true"></i>
+
+     <i class="fa fa-cutlery" aria-hidden="true"></i>
+
+     <i class="fa fa-dashboard" aria-hidden="true"></i>
+
+     <i class="fa fa-database" aria-hidden="true"></i>
+
+     <i class="fa fa-deaf" aria-hidden="true"></i>
+
+     <i class="fa fa-deafness" aria-hidden="true"></i>
+
+     <i class="fa fa-desktop" aria-hidden="true"></i>
+
+     <i class="fa fa-diamond" aria-hidden="true"></i>
+
+     <i class="fa fa-dot-circle-o" aria-hidden="true"></i>
+
+     <i class="fa fa-download" aria-hidden="true"></i>
+
+     <i class="fa fa-drivers-license" aria-hidden="true"></i>
+
+     <i class="fa fa-drivers-license-o" aria-hidden="true"></i>
+
+     <i class="fa fa-edit" aria-hidden="true"></i>
+
+     <i class="fa fa-ellipsis-h" aria-hidden="true"></i>
+
+     <i class="fa fa-ellipsis-v" aria-hidden="true"></i>
+
+     <i class="fa fa-envelope" aria-hidden="true"></i>
+
+     <i class="fa fa-envelope-o" aria-hidden="true"></i>
+
+     <i class="fa fa-envelope-open" aria-hidden="true"></i>
+
+     <i class="fa fa-envelope-open-o" aria-hidden="true"></i>
+
+     <i class="fa fa-envelope-square" aria-hidden="true"></i>
+
+     <i class="fa fa-eraser" aria-hidden="true"></i>
+
+     <i class="fa fa-exchange" aria-hidden="true"></i>
+
+     <i class="fa fa-exclamation" aria-hidden="true"></i>
+
+     <i class="fa fa-exclamation-circle" aria-hidden="true"></i>
+
+     <i class="fa fa-exclamation-triangle" aria-hidden="true"></i>
+
+     <i class="fa fa-external-link" aria-hidden="true"></i>
+
+     <i class="fa fa-external-link-square" aria-hidden="true"></i>
+
+     <i class="fa fa-eye" aria-hidden="true"></i>
+
+     <i class="fa fa-eye-slash" aria-hidden="true"></i>
+
+     <i class="fa fa-eyedropper" aria-hidden="true"></i>
+
+     <i class="fa fa-fax" aria-hidden="true"></i>
+
+     <i class="fa fa-feed" aria-hidden="true"></i>
+
+     <i class="fa fa-female" aria-hidden="true"></i>
+
+     <i class="fa fa-fighter-jet" aria-hidden="true"></i>
+
+     <i class="fa fa-file-archive-o" aria-hidden="true"></i>
+
+     <i class="fa fa-file-audio-o" aria-hidden="true"></i>
+
+     <i class="fa fa-file-code-o" aria-hidden="true"></i>
+
+     <i class="fa fa-file-excel-o" aria-hidden="true"></i>
+
+     <i class="fa fa-file-image-o" aria-hidden="true"></i>
+
+     <i class="fa fa-file-movie-o" aria-hidden="true"></i>
+
+     <i class="fa fa-file-pdf-o" aria-hidden="true"></i>
+
+     <i class="fa fa-file-photo-o" aria-hidden="true"></i>
+
+     <i class="fa fa-file-picture-o" aria-hidden="true"></i>
+
+     <i class="fa fa-file-powerpoint-o" aria-hidden="true"></i>
+
+     <i class="fa fa-file-sound-o" aria-hidden="true"></i>
+
+     <i class="fa fa-file-video-o" aria-hidden="true"></i>
+
+     <i class="fa fa-file-word-o" aria-hidden="true"></i>
+
+     <i class="fa fa-file-zip-o" aria-hidden="true"></i>
+
+     <i class="fa fa-film" aria-hidden="true"></i>
+
+     <i class="fa fa-filter" aria-hidden="true"></i>
+
+     <i class="fa fa-fire" aria-hidden="true"></i>
+
+     <i class="fa fa-fire-extinguisher" aria-hidden="true"></i>
+
+     <i class="fa fa-flag" aria-hidden="true"></i>
+
+     <i class="fa fa-flag-checkered" aria-hidden="true"></i>
+
+     <i class="fa fa-flag-o" aria-hidden="true"></i>
+
+     <i class="fa fa-flash" aria-hidden="true"></i>
+
+     <i class="fa fa-flask" aria-hidden="true"></i>
+
+     <i class="fa fa-folder" aria-hidden="true"></i>
+
+     <i class="fa fa-folder-o" aria-hidden="true"></i>
+
+     <i class="fa fa-folder-open" aria-hidden="true"></i>
+
+     <i class="fa fa-folder-open-o" aria-hidden="true"></i>
+
+     <i class="fa fa-frown-o" aria-hidden="true"></i>
+
+     <i class="fa fa-futbol-o" aria-hidden="true"></i>
+
+     <i class="fa fa-gamepad" aria-hidden="true"></i>
+
+     <i class="fa fa-gavel" aria-hidden="true"></i>
+
+     <i class="fa fa-gear" aria-hidden="true"></i>
+
+     <i class="fa fa-gears" aria-hidden="true"></i>
+
+     <i class="fa fa-gift" aria-hidden="true"></i>
+
+     <i class="fa fa-glass" aria-hidden="true"></i>
+
+     <i class="fa fa-globe" aria-hidden="true"></i>
+
+     <i class="fa fa-graduation-cap" aria-hidden="true"></i>
+
+     <i class="fa fa-group" aria-hidden="true"></i>
+
+     <i class="fa fa-hand-grab-o" aria-hidden="true"></i>
+
+     <i class="fa fa-hand-lizard-o" aria-hidden="true"></i>
+
+     <i class="fa fa-hand-paper-o" aria-hidden="true"></i>
+
+     <i class="fa fa-hand-peace-o" aria-hidden="true"></i>
+
+     <i class="fa fa-hand-pointer-o" aria-hidden="true"></i>
+
+     <i class="fa fa-hand-rock-o" aria-hidden="true"></i>
+
+     <i class="fa fa-hand-scissors-o" aria-hidden="true"></i>
+
+     <i class="fa fa-hand-spock-o" aria-hidden="true"></i>
+
+     <i class="fa fa-hand-stop-o" aria-hidden="true"></i>
+
+     <i class="fa fa-handshake-o" aria-hidden="true"></i>
+
+     <i class="fa fa-hard-of-hearing" aria-hidden="true"></i>
+
+     <i class="fa fa-hashtag" aria-hidden="true"></i>
+
+     <i class="fa fa-hdd-o" aria-hidden="true"></i>
+
+     <i class="fa fa-headphones" aria-hidden="true"></i>
+
+     <i class="fa fa-heart" aria-hidden="true"></i>
+
+     <i class="fa fa-heart-o" aria-hidden="true"></i>
+
+     <i class="fa fa-heartbeat" aria-hidden="true"></i>
+
+     <i class="fa fa-history" aria-hidden="true"></i>
+
+     <i class="fa fa-home" aria-hidden="true"></i>
+
+     <i class="fa fa-hotel" aria-hidden="true"></i>
+
+     <i class="fa fa-hourglass" aria-hidden="true"></i>
+
+     <i class="fa fa-hourglass-1" aria-hidden="true"></i>
+
+     <i class="fa fa-hourglass-2" aria-hidden="true"></i>
+
+     <i class="fa fa-hourglass-3" aria-hidden="true"></i>
+
+     <i class="fa fa-hourglass-end" aria-hidden="true"></i>
+
+     <i class="fa fa-hourglass-half" aria-hidden="true"></i>
+
+     <i class="fa fa-hourglass-o" aria-hidden="true"></i>
+
+     <i class="fa fa-hourglass-start" aria-hidden="true"></i>
+
+     <i class="fa fa-i-cursor" aria-hidden="true"></i>
+
+     <i class="fa fa-id-badge" aria-hidden="true"></i>
+
+     <i class="fa fa-id-card" aria-hidden="true"></i>
+
+     <i class="fa fa-id-card-o" aria-hidden="true"></i>
+
+     <i class="fa fa-image" aria-hidden="true"></i>
+
+     <i class="fa fa-inbox" aria-hidden="true"></i>
+
+     <i class="fa fa-industry" aria-hidden="true"></i>
+
+     <i class="fa fa-info" aria-hidden="true"></i>
+
+     <i class="fa fa-info-circle" aria-hidden="true"></i>
+
+     <i class="fa fa-institution" aria-hidden="true"></i>
+
+     <i class="fa fa-key" aria-hidden="true"></i>
+
+     <i class="fa fa-keyboard-o" aria-hidden="true"></i>
+
+     <i class="fa fa-language" aria-hidden="true"></i>
+
+     <i class="fa fa-laptop" aria-hidden="true"></i>
+
+     <i class="fa fa-leaf" aria-hidden="true"></i>
+
+     <i class="fa fa-legal" aria-hidden="true"></i>
+
+     <i class="fa fa-lemon-o" aria-hidden="true"></i>
+
+     <i class="fa fa-level-down" aria-hidden="true"></i>
+
+     <i class="fa fa-level-up" aria-hidden="true"></i>
+
+     <i class="fa fa-life-bouy" aria-hidden="true"></i>
+
+     <i class="fa fa-life-buoy" aria-hidden="true"></i>
+
+     <i class="fa fa-life-ring" aria-hidden="true"></i>
+
+     <i class="fa fa-life-saver" aria-hidden="true"></i>
+
+     <i class="fa fa-lightbulb-o" aria-hidden="true"></i>
+
+     <i class="fa fa-line-chart" aria-hidden="true"></i>
+
+     <i class="fa fa-location-arrow" aria-hidden="true"></i>
+
+     <i class="fa fa-lock" aria-hidden="true"></i>
+
+     <i class="fa fa-low-vision" aria-hidden="true"></i>
+
+     <i class="fa fa-magic" aria-hidden="true"></i>
+
+     <i class="fa fa-magnet" aria-hidden="true"></i>
+
+     <i class="fa fa-mail-forward" aria-hidden="true"></i>
+
+     <i class="fa fa-mail-reply" aria-hidden="true"></i>
+
+     <i class="fa fa-mail-reply-all" aria-hidden="true"></i>
+
+     <i class="fa fa-male" aria-hidden="true"></i>
+
+     <i class="fa fa-map" aria-hidden="true"></i>
+
+     <i class="fa fa-map-marker" aria-hidden="true"></i>
+
+     <i class="fa fa-map-o" aria-hidden="true"></i>
+
+     <i class="fa fa-map-pin" aria-hidden="true"></i>
+
+     <i class="fa fa-map-signs" aria-hidden="true"></i>
+
+     <i class="fa fa-meh-o" aria-hidden="true"></i>
+
+     <i class="fa fa-microchip" aria-hidden="true"></i>
+
+     <i class="fa fa-microphone" aria-hidden="true"></i>
+
+     <i class="fa fa-microphone-slash" aria-hidden="true"></i>
+
+     <i class="fa fa-minus" aria-hidden="true"></i>
+
+     <i class="fa fa-minus-circle" aria-hidden="true"></i>
+
+     <i class="fa fa-minus-square" aria-hidden="true"></i>
+
+     <i class="fa fa-minus-square-o" aria-hidden="true"></i>
+
+     <i class="fa fa-mobile" aria-hidden="true"></i>
+
+     <i class="fa fa-mobile-phone" aria-hidden="true"></i>
+
+     <i class="fa fa-money" aria-hidden="true"></i>
+
+     <i class="fa fa-moon-o" aria-hidden="true"></i>
+
+     <i class="fa fa-mortar-board" aria-hidden="true"></i>
+
+     <i class="fa fa-motorcycle" aria-hidden="true"></i>
+
+     <i class="fa fa-mouse-pointer" aria-hidden="true"></i>
+
+     <i class="fa fa-music" aria-hidden="true"></i>
+
+     <i class="fa fa-navicon" aria-hidden="true"></i>
+
+     <i class="fa fa-newspaper-o" aria-hidden="true"></i>
+
+     <i class="fa fa-object-group" aria-hidden="true"></i>
+
+     <i class="fa fa-object-ungroup" aria-hidden="true"></i>
+
+     <i class="fa fa-paint-brush" aria-hidden="true"></i>
+
+     <i class="fa fa-paper-plane" aria-hidden="true"></i>
+
+     <i class="fa fa-paper-plane-o" aria-hidden="true"></i>
+
+     <i class="fa fa-paw" aria-hidden="true"></i>
+
+     <i class="fa fa-pencil" aria-hidden="true"></i>
+
+     <i class="fa fa-pencil-square" aria-hidden="true"></i>
+
+     <i class="fa fa-pencil-square-o" aria-hidden="true"></i>
+
+     <i class="fa fa-percent" aria-hidden="true"></i>
+
+     <i class="fa fa-phone" aria-hidden="true"></i>
+
+     <i class="fa fa-phone-square" aria-hidden="true"></i>
+
+     <i class="fa fa-photo" aria-hidden="true"></i>
+
+     <i class="fa fa-picture-o" aria-hidden="true"></i>
+
+     <i class="fa fa-pie-chart" aria-hidden="true"></i>
+
+     <i class="fa fa-plane" aria-hidden="true"></i>
+
+     <i class="fa fa-plug" aria-hidden="true"></i>
+
+     <i class="fa fa-plus" aria-hidden="true"></i>
+
+     <i class="fa fa-plus-circle" aria-hidden="true"></i>
+
+     <i class="fa fa-plus-square" aria-hidden="true"></i>
+
+     <i class="fa fa-plus-square-o" aria-hidden="true"></i>
+
+     <i class="fa fa-podcast" aria-hidden="true"></i>
+
+     <i class="fa fa-power-off" aria-hidden="true"></i>
+
+     <i class="fa fa-print" aria-hidden="true"></i>
+
+     <i class="fa fa-puzzle-piece" aria-hidden="true"></i>
+
+     <i class="fa fa-qrcode" aria-hidden="true"></i>
+
+     <i class="fa fa-question" aria-hidden="true"></i>
+
+     <i class="fa fa-question-circle" aria-hidden="true"></i>
+
+     <i class="fa fa-question-circle-o" aria-hidden="true"></i>
+
+     <i class="fa fa-quote-left" aria-hidden="true"></i>
+
+     <i class="fa fa-quote-right" aria-hidden="true"></i>
+
+     <i class="fa fa-random" aria-hidden="true"></i>
+
+     <i class="fa fa-recycle" aria-hidden="true"></i>
+
+     <i class="fa fa-refresh" aria-hidden="true"></i>
+
+     <i class="fa fa-registered" aria-hidden="true"></i>
+
+     <i class="fa fa-remove" aria-hidden="true"></i>
+
+     <i class="fa fa-reorder" aria-hidden="true"></i>
+
+     <i class="fa fa-reply" aria-hidden="true"></i>
+
+     <i class="fa fa-reply-all" aria-hidden="true"></i>
+
+     <i class="fa fa-retweet" aria-hidden="true"></i>
+
+     <i class="fa fa-road" aria-hidden="true"></i>
+
+     <i class="fa fa-rocket" aria-hidden="true"></i>
+
+     <i class="fa fa-rss" aria-hidden="true"></i>
+
+     <i class="fa fa-rss-square" aria-hidden="true"></i>
+
+     <i class="fa fa-s15" aria-hidden="true"></i>
+
+     <i class="fa fa-search" aria-hidden="true"></i>
+
+     <i class="fa fa-search-minus" aria-hidden="true"></i>
+
+     <i class="fa fa-search-plus" aria-hidden="true"></i>
+
+     <i class="fa fa-send" aria-hidden="true"></i>
+
+     <i class="fa fa-send-o" aria-hidden="true"></i>
+
+     <i class="fa fa-server" aria-hidden="true"></i>
+
+     <i class="fa fa-share" aria-hidden="true"></i>
+
+     <i class="fa fa-share-alt" aria-hidden="true"></i>
+
+     <i class="fa fa-share-alt-square" aria-hidden="true"></i>
+
+     <i class="fa fa-share-square" aria-hidden="true"></i>
+
+     <i class="fa fa-share-square-o" aria-hidden="true"></i>
+
+     <i class="fa fa-shield" aria-hidden="true"></i>
+
+     <i class="fa fa-ship" aria-hidden="true"></i>
+
+     <i class="fa fa-shopping-bag" aria-hidden="true"></i>
+
+     <i class="fa fa-shopping-basket" aria-hidden="true"></i>
+
+     <i class="fa fa-shopping-cart" aria-hidden="true"></i>
+
+     <i class="fa fa-shower" aria-hidden="true"></i>
+
+     <i class="fa fa-sign-in" aria-hidden="true"></i>
+
+     <i class="fa fa-sign-language" aria-hidden="true"></i>
+
+     <i class="fa fa-sign-out" aria-hidden="true"></i>
+
+     <i class="fa fa-signal" aria-hidden="true"></i>
+
+     <i class="fa fa-signing" aria-hidden="true"></i>
+
+     <i class="fa fa-sitemap" aria-hidden="true"></i>
+
+     <i class="fa fa-sliders" aria-hidden="true"></i>
+
+     <i class="fa fa-smile-o" aria-hidden="true"></i>
+
+     <i class="fa fa-snowflake-o" aria-hidden="true"></i>
+
+     <i class="fa fa-soccer-ball-o" aria-hidden="true"></i>
+
+     <i class="fa fa-sort" aria-hidden="true"></i>
+
+     <i class="fa fa-sort-alpha-asc" aria-hidden="true"></i>
+
+     <i class="fa fa-sort-alpha-desc" aria-hidden="true"></i>
+
+     <i class="fa fa-sort-amount-asc" aria-hidden="true"></i>
+
+     <i class="fa fa-sort-amount-desc" aria-hidden="true"></i>
+
+     <i class="fa fa-sort-asc" aria-hidden="true"></i>
+
+     <i class="fa fa-sort-desc" aria-hidden="true"></i>
+
+     <i class="fa fa-sort-down" aria-hidden="true"></i>
+
+     <i class="fa fa-sort-numeric-asc" aria-hidden="true"></i>
+
+     <i class="fa fa-sort-numeric-desc" aria-hidden="true"></i>
+
+     <i class="fa fa-sort-up" aria-hidden="true"></i>
+
+     <i class="fa fa-space-shuttle" aria-hidden="true"></i>
+
+     <i class="fa fa-spinner" aria-hidden="true"></i>
+
+     <i class="fa fa-spoon" aria-hidden="true"></i>
+
+     <i class="fa fa-square" aria-hidden="true"></i>
+
+     <i class="fa fa-square-o" aria-hidden="true"></i>
+
+     <i class="fa fa-star" aria-hidden="true"></i>
+
+     <i class="fa fa-star-half" aria-hidden="true"></i>
+
+     <i class="fa fa-star-half-empty" aria-hidden="true"></i>
+
+     <i class="fa fa-star-half-full" aria-hidden="true"></i>
+
+     <i class="fa fa-star-half-o" aria-hidden="true"></i>
+
+     <i class="fa fa-star-o" aria-hidden="true"></i>
+
+     <i class="fa fa-sticky-note" aria-hidden="true"></i>
+
+     <i class="fa fa-sticky-note-o" aria-hidden="true"></i>
+
+     <i class="fa fa-street-view" aria-hidden="true"></i>
+
+     <i class="fa fa-suitcase" aria-hidden="true"></i>
+
+     <i class="fa fa-sun-o" aria-hidden="true"></i>
+
+     <i class="fa fa-support" aria-hidden="true"></i>
+
+     <i class="fa fa-tablet" aria-hidden="true"></i>
+
+     <i class="fa fa-tachometer" aria-hidden="true"></i>
+
+     <i class="fa fa-tag" aria-hidden="true"></i>
+
+     <i class="fa fa-tags" aria-hidden="true"></i>
+
+     <i class="fa fa-tasks" aria-hidden="true"></i>
+
+     <i class="fa fa-taxi" aria-hidden="true"></i>
+
+     <i class="fa fa-television" aria-hidden="true"></i>
+
+     <i class="fa fa-terminal" aria-hidden="true"></i>
+
+     <i class="fa fa-thermometer" aria-hidden="true"></i>
+
+     <i class="fa fa-thermometer-0" aria-hidden="true"></i>
+
+     <i class="fa fa-thermometer-1" aria-hidden="true"></i>
+
+     <i class="fa fa-thermometer-2" aria-hidden="true"></i>
+
+     <i class="fa fa-thermometer-3" aria-hidden="true"></i>
+
+     <i class="fa fa-thermometer-4" aria-hidden="true"></i>
+
+     <i class="fa fa-thermometer-empty" aria-hidden="true"></i>
+
+     <i class="fa fa-thermometer-full" aria-hidden="true"></i>
+
+     <i class="fa fa-thermometer-half" aria-hidden="true"></i>
+
+     <i class="fa fa-thermometer-quarter" aria-hidden="true"></i>
+
+     <i class="fa fa-thermometer-three-quarters" aria-hidden="true"></i>
+
+     <i class="fa fa-thumb-tack" aria-hidden="true"></i>
+
+     <i class="fa fa-thumbs-down" aria-hidden="true"></i>
+
+     <i class="fa fa-thumbs-o-down" aria-hidden="true"></i>
+
+     <i class="fa fa-thumbs-o-up" aria-hidden="true"></i>
+
+     <i class="fa fa-thumbs-up" aria-hidden="true"></i>
+
+     <i class="fa fa-ticket" aria-hidden="true"></i>
+
+     <i class="fa fa-times" aria-hidden="true"></i>
+
+     <i class="fa fa-times-circle" aria-hidden="true"></i>
+
+     <i class="fa fa-times-circle-o" aria-hidden="true"></i>
+
+     <i class="fa fa-times-rectangle" aria-hidden="true"></i>
+
+     <i class="fa fa-times-rectangle-o" aria-hidden="true"></i>
+
+     <i class="fa fa-tint" aria-hidden="true"></i>
+
+     <i class="fa fa-toggle-down" aria-hidden="true"></i>
+
+     <i class="fa fa-toggle-left" aria-hidden="true"></i>
+
+     <i class="fa fa-toggle-off" aria-hidden="true"></i>
+
+     <i class="fa fa-toggle-on" aria-hidden="true"></i>
+
+     <i class="fa fa-toggle-right" aria-hidden="true"></i>
+
+     <i class="fa fa-toggle-up" aria-hidden="true"></i>
+
+     <i class="fa fa-trademark" aria-hidden="true"></i>
+
+     <i class="fa fa-trash" aria-hidden="true"></i>
+
+     <i class="fa fa-trash-o" aria-hidden="true"></i>
+
+     <i class="fa fa-tree" aria-hidden="true"></i>
+
+     <i class="fa fa-trophy" aria-hidden="true"></i>
+
+     <i class="fa fa-truck" aria-hidden="true"></i>
+
+     <i class="fa fa-tty" aria-hidden="true"></i>
+
+     <i class="fa fa-tv" aria-hidden="true"></i>
+
+     <i class="fa fa-umbrella" aria-hidden="true"></i>
+
+     <i class="fa fa-universal-access" aria-hidden="true"></i>
+
+     <i class="fa fa-university" aria-hidden="true"></i>
+
+     <i class="fa fa-unlock" aria-hidden="true"></i>
+
+     <i class="fa fa-unlock-alt" aria-hidden="true"></i>
+
+     <i class="fa fa-unsorted" aria-hidden="true"></i>
+
+     <i class="fa fa-upload" aria-hidden="true"></i>
+
+     <i class="fa fa-user" aria-hidden="true"></i>
+
+     <i class="fa fa-user-circle" aria-hidden="true"></i>
+
+     <i class="fa fa-user-circle-o" aria-hidden="true"></i>
+
+     <i class="fa fa-user-o" aria-hidden="true"></i>
+
+     <i class="fa fa-user-plus" aria-hidden="true"></i>
+
+     <i class="fa fa-user-secret" aria-hidden="true"></i>
+
+     <i class="fa fa-user-times" aria-hidden="true"></i>
+
+     <i class="fa fa-users" aria-hidden="true"></i>
+
+     <i class="fa fa-vcard" aria-hidden="true"></i>
+
+     <i class="fa fa-vcard-o" aria-hidden="true"></i>
+
+     <i class="fa fa-video-camera" aria-hidden="true"></i>
+
+     <i class="fa fa-volume-control-phone" aria-hidden="true"></i>
+
+     <i class="fa fa-volume-down" aria-hidden="true"></i>
+
+     <i class="fa fa-volume-off" aria-hidden="true"></i>
+
+     <i class="fa fa-volume-up" aria-hidden="true"></i>
+
+     <i class="fa fa-warning" aria-hidden="true"></i>
+
+     <i class="fa fa-wheelchair" aria-hidden="true"></i>
+
+     <i class="fa fa-wheelchair-alt" aria-hidden="true"></i>
+
+     <i class="fa fa-wifi" aria-hidden="true"></i>
+
+     <i class="fa fa-window-close" aria-hidden="true"></i>
+
+     <i class="fa fa-window-close-o" aria-hidden="true"></i>
+
+     <i class="fa fa-window-maximize" aria-hidden="true"></i>
+
+     <i class="fa fa-window-minimize" aria-hidden="true"></i>
+
+     <i class="fa fa-window-restore" aria-hidden="true"></i>
+
+     <i class="fa fa-wrench" aria-hidden="true"></i>
+
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/system/menu/menu.html b/ruoyi-admin/src/main/resources/templates/system/menu/menu.html
new file mode 100644
index 0000000..3b7c2c1
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/system/menu/menu.html
@@ -0,0 +1,161 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('菜单列表')" />
+</head>
+<body class="gray-bg">
+    <div class="container-div">
+		<div class="row">
+			<div class="col-sm-12 search-collapse">
+				<form id="menu-form">
+					<div class="select-list">
+						<ul>
+							<li>
+								菜单名称:<input type="text" name="menuName"/>
+							</li>
+							<li>
+								菜单状态:<select name="visible" th:with="type=${@dict.getType('sys_show_hide')}">
+									<option value="">所有</option>
+									<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
+								</select>
+							</li>
+							<li>
+								<a class="btn btn-primary btn-rounded btn-sm" onclick="$.treeTable.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
+								<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
+							</li>
+						</ul>
+					</div>
+				</form>
+			</div>
+                
+            <div class="btn-group-sm" id="toolbar" role="group">
+		        <a class="btn btn-success" onclick="$.operate.add(0)" shiro:hasPermission="system:menu:add">
+                    <i class="fa fa-plus"></i> 新增
+                </a>
+                <a class="btn btn-primary" onclick="$.operate.edit()" shiro:hasPermission="system:menu:edit">
+		            <i class="fa fa-edit"></i> 修改
+		        </a>
+                <a class="btn btn-info" id="expandAllBtn">
+                    <i class="fa fa-exchange"></i> 展开/折叠
+                </a>
+	        </div>
+       		 <div class="col-sm-12 select-table table-striped">
+	            <table id="bootstrap-tree-table"></table>
+	        </div>
+	    </div>
+	</div>
+	
+	<th:block th:include="include :: footer" />
+	<script th:inline="javascript">
+		var addFlag = [[${@permission.hasPermi('system:menu:add')}]];
+		var editFlag = [[${@permission.hasPermi('system:menu:edit')}]];
+		var removeFlag = [[${@permission.hasPermi('system:menu:remove')}]];
+		var datas = [[${@dict.getType('sys_show_hide')}]];
+		var prefix = ctx + "system/menu";
+
+		$(function() {
+		    var options = {
+		        code: "menuId",
+		        parentCode: "parentId",
+		        uniqueId: "menuId",
+		        expandAll: false,
+		        expandFirst: false,
+		        url: prefix + "/list",
+		        createUrl: prefix + "/add/{id}",
+		        updateUrl: prefix + "/edit/{id}",
+		        removeUrl: prefix + "/remove/{id}",
+		        modalName: "菜单",
+		        columns: [{
+                    field: 'selectItem', 
+                    radio: true
+                 },
+                 {
+		            title: '菜单名称',
+		            field: 'menuName',
+		            width: '20',
+		            widthUnit: '%',
+		            formatter: function(value, row, index) {
+		                if ($.common.isEmpty(row.icon)) {
+		                    return row.menuName;
+		                } else {
+		                    return '<i class="' + row.icon + '"></i> <span class="nav-label">' + row.menuName + '</span>';
+		                }
+		            }
+		        },
+		        {
+		            field: 'orderNum',
+		            title: '排序',
+		            width: '10',
+		            widthUnit: '%',
+		            align: "left"
+		        },
+		        {
+		            field: 'url',
+		            title: '请求地址',
+		            width: '15',
+		            widthUnit: '%',
+		            align: "left",
+		            formatter: function(value, row, index) {
+                    	return $.table.tooltip(value);
+                    }
+		        },
+		        {
+		            title: '类型',
+		            field: 'menuType',
+		            width: '10',
+		            widthUnit: '%',
+		            align: "left",
+		            formatter: function(value, item, index) {
+		                if (item.menuType == 'M') {
+		                    return '<span class="label label-success">目录</span>';
+		                }
+		                else if (item.menuType == 'C') {
+		                    return '<span class="label label-primary">菜单</span>';
+		                }
+		                else if (item.menuType == 'F') {
+		                    return '<span class="label label-warning">按钮</span>';
+		                }
+		            }
+		        },
+		        {
+		            field: 'visible',
+		            title: '可见',
+		            width: '10',
+		            widthUnit: '%',
+		            align: "left",
+		            formatter: function(value, row, index) {
+		            	if (row.menuType == 'F') {
+		                    return '-';
+		                }
+		            	return $.table.selectDictLabel(datas, row.visible);
+		            }
+		        },
+		        {
+		            field: 'perms',
+		            title: '权限标识',
+		            width: '15',
+		            widthUnit: '%',
+		            align: "left",
+		            formatter: function(value, row, index) {
+                    	return $.table.tooltip(value);
+                    }
+		        },
+		        {
+		            title: '操作',
+		            width: '20',
+		            widthUnit: '%',
+		            align: "left",
+		            formatter: function(value, row, index) {
+		                var actions = [];
+		                actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.menuId + '\')"><i class="fa fa-edit"></i>编辑</a> ');
+		                actions.push('<a class="btn btn-info btn-xs ' + addFlag + '" href="javascript:void(0)" onclick="$.operate.add(\'' + row.menuId + '\')"><i class="fa fa-plus"></i>新增</a> ');
+		                actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.menuId + '\')"><i class="fa fa-trash"></i>删除</a>');
+		                return actions.join('');
+		            }
+		        }]
+		    };
+		    $.treeTable.init(options);
+		});
+	</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/system/menu/tree.html b/ruoyi-admin/src/main/resources/templates/system/menu/tree.html
new file mode 100644
index 0000000..7c9dd00
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/system/menu/tree.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+	<th:block th:include="include :: header('菜单树选择')" />
+	<th:block th:include="include :: ztree-css" />
+</head>
+<style>
+	body{height:auto;font-family: "Microsoft YaHei";}
+	button{font-family: "SimSun","Helvetica Neue",Helvetica,Arial;}
+</style>
+<body class="hold-transition box box-main">
+	<input id="treeId"   name="treeId"    type="hidden" th:value="${menu.menuId}"/>
+	<input id="treeName" name="treeName"  type="hidden" th:value="${menu.menuName}"/>
+	<div class="wrapper"><div class="treeShowHideButton" onclick="$.tree.toggleSearch();">
+		<label id="btnShow" title="显示搜索" style="display:none;">︾</label>
+		<label id="btnHide" title="隐藏搜索">︽</label>
+	</div>
+	<div class="treeSearchInput" id="search">
+		<label for="keyword">关键字:</label><input type="text" class="empty" id="keyword" maxlength="50">
+		<button class="btn" id="btn" onclick="$.tree.searchNode()"> 搜索 </button>
+	</div>
+	<div class="treeExpandCollapse">
+		<a href="javascript:;" onclick="$.tree.expand()">展开</a> /
+		<a href="javascript:;" onclick="$.tree.collapse()">折叠</a>
+	</div>
+	<div id="tree" class="ztree treeselect"></div>
+	</div>
+	<th:block th:include="include :: footer" />
+	<th:block th:include="include :: ztree-js" />
+	<script th:inline="javascript">
+		$(function() {
+			var url = ctx + "system/menu/menuTreeData";
+			var options = {
+		        url: url,
+		        expandLevel: 1,
+		        onClick : zOnClick
+		    };
+			$.tree.init(options);
+		});
+		
+		function zOnClick(event, treeId, treeNode) {
+		    var treeId = treeNode.id;
+		    var treeName = treeNode.name;
+		    $("#treeId").val(treeId);
+		    $("#treeName").val(treeName);
+		}
+	</script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/system/notice/add.html b/ruoyi-admin/src/main/resources/templates/system/notice/add.html
new file mode 100644
index 0000000..ae8febf
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/system/notice/add.html
@@ -0,0 +1,98 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+	<th:block th:include="include :: header('新增通知公告')" />
+	<th:block th:include="include :: summernote-css" />
+</head>
+<body class="white-bg">
+    <div class="wrapper wrapper-content animated fadeInRight ibox-content">
+        <form class="form-horizontal m" id="form-notice-add">
+			<div class="form-group">	
+				<label class="col-sm-2 control-label is-required">公告标题:</label>
+				<div class="col-sm-10">
+					<input id="noticeTitle" name="noticeTitle" class="form-control" type="text" required>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-2 control-label">公告类型:</label>
+				<div class="col-sm-10">
+					<select name="noticeType" class="form-control m-b" th:with="type=${@dict.getType('sys_notice_type')}">
+	                    <option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
+	                </select>
+				</div>
+			</div>
+			<div class="form-group">	
+				<label class="col-sm-2 control-label">公告内容:</label>
+				<div class="col-sm-10">
+				    <input id="noticeContent" name="noticeContent" type="hidden">
+				    <div class="summernote"></div>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-2 control-label">公告状态:</label>
+				<div class="col-sm-10">
+				    <div class="radio-box" th:each="dict : ${@dict.getType('sys_notice_status')}">
+						<input type="radio" th:id="${dict.dictCode}" name="status" th:value="${dict.dictValue}" th:checked="${dict.default}">
+						<label th:for="${dict.dictCode}" th:text="${dict.dictLabel}"></label>
+					</div>
+				</div>
+			</div>
+		</form>
+	</div>
+    <th:block th:include="include :: footer" />
+    <th:block th:include="include :: summernote-js" />
+    <script type="text/javascript">
+        var prefix = ctx + "system/notice";
+
+	    $('.summernote').summernote({
+	    	placeholder: '请输入公告内容',
+			height : 192,
+			lang : 'zh-CN',
+			followingToolbar: false,
+			dialogsInBody: true,
+			callbacks: {
+                onImageUpload: function (files) {
+                    sendFile(files[0], this);
+                }
+            }
+		});
+	    
+	    // 上传文件
+	    function sendFile(file, obj) {
+	        var data = new FormData();
+	        data.append("file", file);
+	        $.ajax({
+	            type: "POST",
+	            url: ctx + "common/upload",
+	            data: data,
+	            cache: false,
+	            contentType: false,
+	            processData: false,
+	            dataType: 'json',
+	            success: function(result) {
+	                if (result.code == web_status.SUCCESS) {
+	                	$(obj).summernote('editor.insertImage', result.url, result.fileName);
+					} else {
+						$.modal.alertError(result.msg);
+					}
+	            },
+	            error: function(error) {
+	                $.modal.alertWarning("图片上传失败。");
+	            }
+	        });
+	    }
+		
+		$("#form-notice-add").validate({
+			focusCleanup: true
+		});
+		
+		function submitHandler() {
+	        if ($.validate.form()) {
+	        	var sHTML = $('.summernote').summernote('code');
+				$("#noticeContent").val(sHTML);
+				$.operate.save(prefix + "/add", $('#form-notice-add').serialize());
+	        }
+	    }
+	</script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/system/notice/edit.html b/ruoyi-admin/src/main/resources/templates/system/notice/edit.html
new file mode 100644
index 0000000..6facae9
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/system/notice/edit.html
@@ -0,0 +1,103 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+	<th:block th:include="include :: header('修改通知公告')" />
+	<th:block th:include="include :: summernote-css" />
+</head>
+<body class="white-bg">
+    <div class="wrapper wrapper-content animated fadeInRight ibox-content">
+        <form class="form-horizontal m" id="form-notice-edit" th:object="${notice}">
+            <input id="noticeId" name="noticeId" th:field="*{noticeId}"  type="hidden">
+            <div class="form-group">	
+                <label class="col-sm-2 control-label is-required">公告标题:</label>
+                <div class="col-sm-10">
+                    <input id="noticeTitle" name="noticeTitle" th:field="*{noticeTitle}" class="form-control" type="text" required>
+                </div>
+            </div>
+            <div class="form-group">
+				<label class="col-sm-2 control-label">公告类型:</label>
+				<div class="col-sm-10">
+					<select name="noticeType" class="form-control m-b" th:with="type=${@dict.getType('sys_notice_type')}">
+	                    <option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}" th:field="*{noticeType}"></option>
+	                </select>
+				</div>
+			</div>
+            <div class="form-group">	
+                <label class="col-sm-2 control-label">公告内容:</label>
+                <div class="col-sm-10">
+                    <input id="noticeContent" name="noticeContent" th:field="*{noticeContent}" type="hidden">
+                    <div id="editor" class="summernote"></div>
+                </div>
+            </div>
+            <div class="form-group">
+				<label class="col-sm-2 control-label">公告状态:</label>
+				<div class="col-sm-10">
+					<div class="radio-box" th:each="dict : ${@dict.getType('sys_notice_status')}">
+						<input type="radio" th:id="${dict.dictCode}" name="status" th:value="${dict.dictValue}" th:field="*{status}">
+						<label th:for="${dict.dictCode}" th:text="${dict.dictLabel}"></label>
+					</div>
+				</div>
+			</div>
+		</form>
+    </div>
+    <th:block th:include="include :: footer" />
+    <th:block th:include="include :: summernote-js" />
+    <script type="text/javascript">
+        var prefix = ctx + "system/notice";
+    
+	    $(function() {
+		    $('.summernote').summernote({
+		    	placeholder: '请输入公告内容',
+		    	height : 192,
+				lang : 'zh-CN',
+				followingToolbar: false,
+				dialogsInBody: true,
+				callbacks: {
+	                onImageUpload: function (files) {
+	                    sendFile(files[0], this);
+	                }
+	            }
+		    });
+			var content = $("#noticeContent").val();
+		    $('#editor').summernote('code', content);
+	    });
+	    
+	    // 上传文件
+	    function sendFile(file, obj) {
+	        var data = new FormData();
+	        data.append("file", file);
+	        $.ajax({
+	            type: "POST",
+	            url: ctx + "common/upload",
+	            data: data,
+	            cache: false,
+	            contentType: false,
+	            processData: false,
+	            dataType: 'json',
+	            success: function(result) {
+	                if (result.code == web_status.SUCCESS) {
+	                	$(obj).summernote('editor.insertImage', result.url, result.fileName);
+					} else {
+						$.modal.alertError(result.msg);
+					}
+	            },
+	            error: function(error) {
+	                $.modal.alertWarning("图片上传失败。");
+	            }
+	        });
+	    }
+	    
+		$("#form-notice-edit").validate({
+			focusCleanup: true
+		});
+		
+		function submitHandler() {
+	        if ($.validate.form()) {
+	        	var sHTML = $('.summernote').summernote('code');
+				$("#noticeContent").val(sHTML);
+				$.operate.save(prefix + "/edit", $('#form-notice-edit').serialize());
+	        }
+	    }
+	</script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/system/notice/notice.html b/ruoyi-admin/src/main/resources/templates/system/notice/notice.html
new file mode 100644
index 0000000..30f4a09
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/system/notice/notice.html
@@ -0,0 +1,121 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('通知公告列表')" />
+</head>
+<body class="gray-bg">
+    <div class="container-div">
+		<div class="row">
+			<div class="col-sm-12 search-collapse">
+				<form id="notice-form">
+					<div class="select-list">
+						<ul>
+							<li>
+								公告标题:<input type="text" name="noticeTitle"/>
+							</li>
+							<li>
+								操作人员:<input type="text" name="createBy"/>
+							</li>
+							<li>
+								公告类型:<select name="noticeType" th:with="type=${@dict.getType('sys_notice_type')}">
+									<option value="">所有</option>
+									<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
+								</select>
+							</li>
+							<li>
+								<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
+								<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
+							</li>
+						</ul>
+					</div>
+				</form>
+			</div>
+			
+	        <div class="btn-group-sm" id="toolbar" role="group">
+		        <a class="btn btn-success" onclick="$.operate.addFull()" shiro:hasPermission="system:notice:add">
+		            <i class="fa fa-plus"></i> 新增
+		        </a>
+		        <a class="btn btn-primary single disabled" onclick="$.operate.editFull()" shiro:hasPermission="system:notice:edit">
+		            <i class="fa fa-edit"></i> 修改
+		        </a>
+		        <a class="btn btn-danger multiple disabled" onclick="$.operate.removeAll()" shiro:hasPermission="system:notice:remove">
+		            <i class="fa fa-remove"></i> 删除
+		        </a>
+	        </div>
+	        
+	        <div class="col-sm-12 select-table table-striped">
+	            <table id="bootstrap-table"></table>
+	        </div>
+    	</div>
+    </div>
+    <th:block th:include="include :: footer" />
+    <script th:inline="javascript">
+        var editFlag = [[${@permission.hasPermi('system:notice:edit')}]];
+        var removeFlag = [[${@permission.hasPermi('system:notice:remove')}]];
+        var types = [[${@dict.getType('sys_notice_type')}]];
+        var datas = [[${@dict.getType('sys_notice_status')}]];
+        var prefix = ctx + "system/notice";
+
+        $(function() {
+            var options = {
+                url: prefix + "/list",
+                viewUrl: prefix + "/view/{id}",
+                createUrl: prefix + "/add",
+                updateUrl: prefix + "/edit/{id}",
+                removeUrl: prefix + "/remove",
+                modalName: "公告",
+                columns: [{
+		            checkbox: true
+		        },
+				{
+					field : 'noticeId', 
+					title : '序号' 
+				},
+				{
+		            field: 'noticeTitle',
+		            title: '公告标题',
+		            formatter: function (value, row, index) {
+		                return '<a href="javascript:void(0)" onclick="$.operate.view(\'' + row.noticeId + '\')">' + value + '</a>';
+		            }
+		        },
+				{
+		            field: 'noticeType',
+		            title: '公告类型',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		            	return $.table.selectDictLabel(types, value);
+		            }
+		        },
+				{
+		            field: 'status',
+		            title: '状态',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		            	return $.table.selectDictLabel(datas, value);
+		            }
+		        },
+				{
+					field : 'createBy', 
+					title : '创建者' 
+				},
+				{
+		            field: 'createTime',
+		            title: '创建时间',
+		            sortable: true
+		        },
+		        {
+		            title: '操作',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		            	var actions = [];
+		            	actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.editFull(\'' + row.noticeId + '\')"><i class="fa fa-edit"></i>编辑</a> ');
+                        actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.noticeId + '\')"><i class="fa fa-remove"></i>删除</a>');
+						return actions.join('');
+		            }
+		        }]
+            };
+            $.table.init(options);
+        });
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/system/notice/view.html b/ruoyi-admin/src/main/resources/templates/system/notice/view.html
new file mode 100644
index 0000000..38791c6
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/system/notice/view.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+    <th:block th:include="include :: header('公告详细')" />
+</head>
+<body>
+    <div class="main-content">
+        <div class="row">
+            <div class="col-sm-12">
+                <div class="mail-box-header">
+                    <div class="mail-tools tooltip-demo m-t-md">
+                        <h3 style="text-align: center">[[${notice.noticeTitle}]]</h3>
+                        <h5>
+                          <span class="pull-right font-noraml">发送时间:[[${#dates.format(notice.createTime, 'yyyy-MM-dd HH:mm:ss')}]] </span>
+                          <span class="font-noraml">发件人: </span>[[${notice.createBy}]]
+                        </h5>
+                    </div>
+                </div>
+                <div class="mail-box">
+                    <div class="mail-body" th:utext="${notice.noticeContent}"></div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <th:block th:include="include :: footer" />
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/system/post/add.html b/ruoyi-admin/src/main/resources/templates/system/post/add.html
new file mode 100644
index 0000000..4bbcb67
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/system/post/add.html
@@ -0,0 +1,97 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+	<th:block th:include="include :: header('新增岗位')" />
+</head>
+<body class="white-bg">
+	<div class="wrapper wrapper-content animated fadeInRight ibox-content">
+		<form class="form-horizontal m" id="form-post-add">
+			<div class="form-group">
+				<label class="col-sm-3 control-label is-required">岗位名称:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="postName" id="postName" required>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label is-required">岗位编码:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="postCode" id="postCode" required>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label is-required">显示顺序:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="postSort" id="postSort" required>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">岗位状态:</label>
+				<div class="col-sm-8">
+				    <div class="radio-box" th:each="dict : ${@dict.getType('sys_normal_disable')}">
+						<input type="radio" th:id="${dict.dictCode}" name="status" th:value="${dict.dictValue}" th:checked="${dict.default}">
+						<label th:for="${dict.dictCode}" th:text="${dict.dictLabel}"></label>
+					</div>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">备注:</label>
+				<div class="col-sm-8">
+					<textarea id="remark" name="remark" class="form-control"></textarea>
+				</div>
+			</div>
+		</form>
+	</div>
+	<th:block th:include="include :: footer" />
+	<script type="text/javascript">
+		var prefix = ctx + "system/post";
+	    
+		$("#form-post-add").validate({
+			onkeyup: false,
+			rules:{
+				postName:{
+					remote: {
+		                url: ctx + "system/post/checkPostNameUnique",
+		                type: "post",
+		                dataType: "json",
+		                data: {
+		                	"postName" : function() {
+		                        return $.common.trim($("#postName").val());
+		                    }
+		                }
+		            }
+				},
+				postCode:{
+					remote: {
+		                url: ctx + "system/post/checkPostCodeUnique",
+		                type: "post",
+		                dataType: "json",
+		                data: {
+		                	"postCode" : function() {
+		                        return $.common.trim($("#postCode").val());
+		                    }
+		                }
+		            }
+				},
+				postSort:{
+					digits:true
+				},
+			},
+			messages: {
+		        "postCode": {
+		            remote: "岗位编码已经存在"
+		        },
+		        "postName": {
+		            remote: "岗位名称已经存在"
+		        }
+		    },
+		    focusCleanup: true
+		});
+		
+		function submitHandler() {
+	        if ($.validate.form()) {
+	        	$.operate.save(prefix + "/add", $('#form-post-add').serialize());
+	        }
+	    }
+	</script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/system/post/edit.html b/ruoyi-admin/src/main/resources/templates/system/post/edit.html
new file mode 100644
index 0000000..b2e5dcb
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/system/post/edit.html
@@ -0,0 +1,104 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+	<th:block th:include="include :: header('修改岗位')" />
+</head>
+<body class="white-bg">
+	<div class="wrapper wrapper-content animated fadeInRight ibox-content">
+		<form class="form-horizontal m" id="form-post-edit" th:object="${post}">
+			<input id="postId" name="postId" type="hidden" th:field="*{postId}"/>
+			<div class="form-group">
+				<label class="col-sm-3 control-label is-required">岗位名称:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="postName" id="postName" th:field="*{postName}" required>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label is-required">岗位编码:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="postCode" id="postCode" th:field="*{postCode}" required>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label is-required">显示顺序:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="postSort" id="postSort" th:field="*{postSort}" required>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">岗位状态:</label>
+				<div class="col-sm-8">
+					<div class="radio-box" th:each="dict : ${@dict.getType('sys_normal_disable')}">
+						<input type="radio" th:id="${dict.dictCode}" name="status" th:value="${dict.dictValue}" th:field="*{status}">
+						<label th:for="${dict.dictCode}" th:text="${dict.dictLabel}"></label>
+					</div>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">备注:</label>
+				<div class="col-sm-8">
+					<textarea id="remark" name="remark" class="form-control">[[*{remark}]]</textarea>
+				</div>
+			</div>
+		</form>
+	</div>
+	<th:block th:include="include :: footer" />
+	<script type="text/javascript">
+		var prefix = ctx + "system/post";
+		
+		$("#form-post-edit").validate({
+			onkeyup: false,
+			rules:{
+				postName:{
+					remote: {
+		                url: ctx + "system/post/checkPostNameUnique",
+		                type: "post",
+		                dataType: "json",
+		                data: {
+		                	"postId": function() {
+							    return $("input[name='postId']").val();
+							},
+		                	"postName" : function() {
+		                        return $.common.trim($("#postName").val());
+		                    }
+		                }
+		            }
+				},
+				postCode:{
+					remote: {
+		                url: ctx + "system/post/checkPostCodeUnique",
+		                type: "post",
+		                dataType: "json",
+		                data: {
+		                	"postId": function() {
+							    return $("input[name='postId']").val();
+							},
+		                	"postCode" : function() {
+		                		return $.common.trim($("#postCode").val());
+		                    }
+		                }
+		            }
+				},
+				postSort:{
+					digits:true
+				},
+			},
+			messages: {
+		        "postCode": {
+		            remote: "岗位编码已经存在"
+		        },
+		        "postName": {
+		            remote: "岗位名称已经存在"
+		        }
+		    },
+		    focusCleanup: true
+		});
+		
+		function submitHandler() {
+	        if ($.validate.form()) {
+	        	$.operate.save(prefix + "/edit", $('#form-post-edit').serialize());
+	        }
+	    }
+	</script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/system/post/post.html b/ruoyi-admin/src/main/resources/templates/system/post/post.html
new file mode 100644
index 0000000..3c3fc42
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/system/post/post.html
@@ -0,0 +1,120 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('岗位列表')" />
+</head>
+<body class="gray-bg">
+	<div class="container-div">
+		<div class="row">
+			<div class="col-sm-12 search-collapse">
+				<form id="post-form">
+					<div class="select-list">
+						<ul>
+							<li>
+								岗位编码:<input type="text" name="postCode"/>
+							</li>
+							<li>
+								岗位名称:<input type="text" name="postName"/>
+							</li>
+							<li>
+								岗位状态:<select name="status" th:with="type=${@dict.getType('sys_normal_disable')}">
+									<option value="">所有</option>
+									<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
+								</select>
+							</li>
+							<li>
+								<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
+							    <a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
+							</li>
+						</ul>
+					</div>
+				</form>
+			</div>
+			
+			<div class="btn-group-sm" id="toolbar" role="group">
+				<a class="btn btn-success" onclick="$.operate.add()" shiro:hasPermission="system:post:add">
+	                <i class="fa fa-plus"></i> 新增
+	            </a>
+				<a class="btn btn-primary single disabled" onclick="$.operate.edit()" shiro:hasPermission="system:post:edit">
+		            <i class="fa fa-edit"></i> 修改
+		        </a>
+				<a class="btn btn-danger multiple disabled" onclick="$.operate.removeAll()" shiro:hasPermission="system:post:remove">
+		            <i class="fa fa-remove"></i> 删除
+		        </a>
+				<a class="btn btn-warning" onclick="$.table.exportExcel()" shiro:hasPermission="system:post:export">
+		            <i class="fa fa-download"></i> 导出
+		        </a>
+	        </div>
+	        
+	        <div class="col-sm-12 select-table table-striped">
+			    <table id="bootstrap-table"></table>
+			</div>
+		</div>
+	</div>
+	<th:block th:include="include :: footer" />
+	<script th:inline="javascript">
+		var editFlag = [[${@permission.hasPermi('system:post:edit')}]];
+		var removeFlag = [[${@permission.hasPermi('system:post:remove')}]];
+		var datas = [[${@dict.getType('sys_normal_disable')}]];
+		var prefix = ctx + "system/post";
+
+		$(function() {
+		    var options = {
+		        url: prefix + "/list",
+		        createUrl: prefix + "/add",
+		        updateUrl: prefix + "/edit/{id}",
+		        removeUrl: prefix + "/remove",
+		        exportUrl: prefix + "/export",
+		        sortName: "postSort",
+		        modalName: "岗位",
+		        columns: [{
+		            checkbox: true
+		        },
+		        {
+		            field: 'postId',
+		            title: '岗位编号'
+		        },
+		        {
+		            field: 'postCode',
+		            title: '岗位编码',
+		            sortable: true
+		        },
+		        {
+		            field: 'postName',
+		            title: '岗位名称',
+		            sortable: true
+		        },
+		        {
+		            field: 'postSort',
+		            title: '显示顺序',
+		            sortable: true
+		        },
+		        {
+		            field: 'status',
+		            title: '状态',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		            	return $.table.selectDictLabel(datas, value);
+		            }
+		        },
+		        {
+		            field: 'createTime',
+		            title: '创建时间',
+		            sortable: true
+		        },
+		        {
+		            title: '操作',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		                var actions = [];
+		                actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.postId + '\')"><i class="fa fa-edit"></i>编辑</a> ');
+		                actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.postId + '\')"><i class="fa fa-remove"></i>删除</a>');
+		                return actions.join('');
+		            }
+		        }]
+		    };
+		    $.table.init(options);
+		});
+	</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/system/role/add.html b/ruoyi-admin/src/main/resources/templates/system/role/add.html
new file mode 100644
index 0000000..2990c6d
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/system/role/add.html
@@ -0,0 +1,174 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+	<th:block th:include="include :: header('新增角色')" />
+	<th:block th:include="include :: ztree-css" />
+</head>
+<body class="white-bg">
+	<div class="wrapper wrapper-content animated fadeInRight ibox-content">
+		<form class="form-horizontal m" id="form-role-add">
+			<div class="form-group">
+				<label class="col-sm-3 control-label is-required">角色名称:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="roleName" id="roleName" required>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label is-required">权限字符:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="roleKey" id="roleKey" required>
+					<span class="help-block m-b-none"><i class="fa fa-info-circle"></i> 控制器中定义的权限字符,如:@RequiresRoles("")</span>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label is-required">显示顺序:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="roleSort" id="roleSort" required>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">状态:</label>
+				<div class="col-sm-8">
+			        <label class="toggle-switch switch-solid">
+                        <input type="checkbox" id="status" checked>
+                        <span></span>
+                    </label>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">备注:</label>
+				<div class="col-sm-8">
+					<input id="remark" name="remark" class="form-control" type="text">
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">菜单权限:</label>
+				<div class="col-sm-8">
+				    <label class="check-box">
+				        <input type="checkbox" value="1">展开/折叠</label>
+				    <label class="check-box">
+				        <input type="checkbox" value="2">全选/全不选</label>
+				    <label class="check-box">
+				        <input type="checkbox" value="3" checked>父子联动</label>
+				    <div id="menuTrees" class="ztree ztree-border"></div>
+				</div>
+			</div>
+		</form>
+	</div>
+	<th:block th:include="include :: footer" />
+	<th:block th:include="include :: ztree-js" />
+	<script type="text/javascript">
+	    $(function() {
+			var url = ctx + "system/menu/roleMenuTreeData";
+			var options = {
+				id: "menuTrees",
+		        url: url,
+		        check: { enable: true },
+		        expandLevel: 0
+		    };
+			$.tree.init(options);
+		});
+		
+		$("#form-role-add").validate({
+			rules:{
+				onkeyup: false,
+				roleName:{
+					remote: {
+		                url: ctx + "system/role/checkRoleNameUnique",
+		                type: "post",
+		                dataType: "json",
+		                data: {
+		                	"roleName" : function() {
+		                		return $.common.trim($("#roleName").val());
+		                    }
+		                }
+		            }
+				},
+				roleKey:{
+					remote: {
+		                url: ctx + "system/role/checkRoleKeyUnique",
+		                type: "post",
+		                dataType: "json",
+		                data: {
+		                	"roleKey" : function() {
+		                        return $.common.trim($("#roleKey").val());
+		                    }
+		                }
+		            }
+				},
+				roleSort:{
+					digits:true
+				},
+			},
+			messages: {
+		        "roleName": {
+		            remote: "角色名称已经存在"
+		        },
+		        "roleKey": {
+		            remote: "角色权限已经存在"
+		        }
+		    },
+		    focusCleanup: true
+		});
+		
+		$('input').on('ifChanged', function(obj){
+			var type = $(this).val();
+			var checked = obj.currentTarget.checked;
+			if (type == 1) {
+			    if (checked) {
+			        $._tree.expandAll(true);
+			    } else {
+			        $._tree.expandAll(false);
+			    }
+			} else if (type == "2") {
+			    if (checked) {
+			        $._tree.checkAllNodes(true);
+			    } else {
+			        $._tree.checkAllNodes(false);
+			    }
+			} else if (type == "3") {
+			    if (checked) {
+			        $._tree.setting.check.chkboxType = { "Y": "ps", "N": "ps" };
+			    } else {
+			        $._tree.setting.check.chkboxType = { "Y": "", "N": "" };
+			    }
+			}
+		})
+		
+		function submitHandler() {
+	        if ($.validate.form()) {
+	        	add();
+	        }
+	    }
+	
+		function add() {
+			var roleName = $("input[name='roleName']").val();
+			var roleKey = $("input[name='roleKey']").val();
+			var roleSort = $("input[name='roleSort']").val();
+			var status = $("input[id='status']").is(':checked') == true ? 0 : 1;
+			var remark = $("input[name='remark']").val();
+			var menuIds = $.tree.getCheckedNodes();
+			$.ajax({
+				cache : true,
+				type : "POST",
+				url : ctx + "system/role/add",
+				data : {
+					"roleName": roleName,
+					"roleKey": roleKey,
+					"roleSort": roleSort,
+					"status": status,
+					"remark": remark,
+					"menuIds": menuIds
+				},
+				async : false,
+				error : function(request) {
+					$.modal.alertError("系统错误");
+				},
+				success : function(data) {
+					$.operate.successCallback(data);
+				}
+			});
+		}
+	</script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/system/role/authUser.html b/ruoyi-admin/src/main/resources/templates/system/role/authUser.html
new file mode 100644
index 0000000..0bce407
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/system/role/authUser.html
@@ -0,0 +1,142 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('角色分配用户')" />
+</head>
+<body class="gray-bg">
+	<div class="container-div">
+		<div class="row">
+			<div class="col-sm-12 search-collapse">
+				<form id="role-form">
+				    <input type="hidden" id="roleId" name="roleId" th:value="${role.roleId}">
+					<div class="select-list">
+						<ul>
+							<li>
+								登录名称:<input type="text" name="loginName"/>
+							</li>
+							<li>
+								手机号码:<input type="text" name="phonenumber"/>
+							</li>
+							<li>
+								<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
+							    <a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
+							</li>
+						</ul>
+					</div>
+				</form>
+			</div>
+	        
+	        <div class="btn-group-sm" id="toolbar" role="group">
+				<a class="btn btn-success" onclick="selectUser()" shiro:hasPermission="system:role:add">
+	                <i class="fa fa-plus"></i> 添加用户
+	            </a>
+				<a class="btn btn-danger multiple disabled" onclick="cancelAuthUserAll()" shiro:hasPermission="system:role:remove">
+		            <i class="fa fa-remove"></i> 批量取消授权
+		        </a>
+		        <a class="btn btn-warning" onclick="closeItem()">
+		            <i class="fa fa-reply-all"></i> 关闭
+		        </a>
+	        </div>
+	        
+	        <div class="col-sm-12 select-table table-striped">
+			    <table id="bootstrap-table"></table>
+			</div>
+		</div>
+	</div>
+	<th:block th:include="include :: footer" />
+	<script th:inline="javascript">
+		var removeFlag = [[${@permission.hasPermi('system:role:remove')}]];
+		var datas = [[${@dict.getType('sys_normal_disable')}]];
+		var prefix = ctx + "system/role/authUser";
+
+		$(function() {
+			var options = {
+		        url: prefix + "/allocatedList",
+		        queryParams: queryParams,
+		        sortName: "createTime",
+		        sortOrder: "desc",
+		        columns: [{
+		            checkbox: true
+		        },
+		        {
+		            field: 'userId',
+		            title: '用户ID',
+		            visible: false
+		        },
+		        {
+		            field: 'loginName',
+		            title: '登录名称',
+		            sortable: true
+		        },
+		        {
+		            field: 'userName',
+		            title: '用户名称'
+		        },
+		        {
+		            field: 'email',
+		            title: '邮箱'
+		        },
+		        {
+		            field: 'phonenumber',
+		            title: '手机'
+		        },
+		        {
+		        	field: 'status',
+		        	title: '用户状态',
+		        	align: 'center',
+		        	formatter: function (value, row, index) {
+		        		return $.table.selectDictLabel(datas, value);
+		        	}
+		        },
+		        {
+		            field: 'createTime',
+		            title: '创建时间',
+		            sortable: true
+		        },
+		        {
+		            title: '操作',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		                var actions = [];
+		                actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="cancelAuthUser(\'' + row.userId + '\')"><i class="fa fa-remove"></i>取消授权</a> ');
+		                return actions.join('');
+		            }
+		        }]
+		    };
+		    $.table.init(options);
+		});
+		
+		function queryParams(params) {
+			var search = $.table.queryParams(params);
+			search.roleId = $("#roleId").val();
+			return search;
+		}
+		
+		/* 分配用户-选择用户 */
+		function selectUser() {
+			var url = prefix + '/selectUser/' + $("#roleId").val();
+		    $.modal.open("选择用户", url);
+		}
+		
+		/* 分配用户-批量取消授权 */
+		function cancelAuthUserAll(userId) {
+		    var rows = $.table.selectFirstColumns();
+       		if (rows.length == 0) {
+       			$.modal.alertWarning("请至少选择一条记录");
+       			return;
+       		}
+       		$.modal.confirm("确认要删除选中的" + rows.length + "条数据吗?", function() {
+    			var data = { "roleId": $("#roleId").val(), "userIds": rows.join() };
+    			$.operate.submit(prefix + "/cancelAll", "post", "json", data);
+    		});
+		}
+		
+		/* 分配用户-取消授权 */
+		function cancelAuthUser(userId) {
+			$.modal.confirm("确认要取消该用户角色吗?", function() {
+				$.operate.post(prefix + "/cancel", { "roleId": $("#roleId").val(), "userId": userId });
+		    })
+		}
+	</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/system/role/dataScope.html b/ruoyi-admin/src/main/resources/templates/system/role/dataScope.html
new file mode 100644
index 0000000..c36624b
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/system/role/dataScope.html
@@ -0,0 +1,137 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+	<th:block th:include="include :: header('角色数据权限')" />
+	<th:block th:include="include :: ztree-css" />
+</head>
+<body class="white-bg">
+	<div class="wrapper wrapper-content animated fadeInRight ibox-content">
+		<form class="form-horizontal m" id="form-role-edit" th:object="${role}">
+			<input id="roleId" name="roleId" type="hidden" th:field="*{roleId}"/>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">角色名称:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="roleName" id="roleName" th:field="*{roleName}" readonly="true"/>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">权限字符:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="roleKey" id="roleKey" th:field="*{roleKey}" readonly="true">
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">数据范围:</label>
+				<div class="col-sm-8">
+					<select id="dataScope" name="dataScope" class="form-control m-b">
+						<option value="1" th:field="*{dataScope}">全部数据权限</option>
+						<option value="2" th:field="*{dataScope}">自定义数据权限</option>
+						<option value="3" th:field="*{dataScope}">本部门数据权限</option>
+						<option value="4" th:field="*{dataScope}">本部门及以下数据权限</option>
+						<option value="5" th:field="*{dataScope}">仅本人数据权限</option>
+					</select>
+					<span class="help-block m-b-none"><i class="fa fa-info-circle"></i> 特殊情况下,设置为“自定数据权限”</span>
+				</div>
+			</div>
+			<div class="form-group" id="authDataScope" th:style="'display:' + @{(*{dataScope=='2'} ? 'block' : 'none')} + ''">
+				<label class="col-sm-3 control-label">数据权限:</label>
+				<div class="col-sm-8">
+				    <label class="check-box">
+				        <input type="checkbox" value="1" checked>展开/折叠</label>
+				    <label class="check-box">
+				        <input type="checkbox" value="2">全选/全不选</label>
+				    <label class="check-box">
+				        <input type="checkbox" value="3" checked>父子联动</label>
+				    <div id="deptTrees" class="ztree ztree-border"></div>
+				</div>
+			</div>
+		</form>
+	</div>
+	<th:block th:include="include :: footer" />
+	<th:block th:include="include :: ztree-js" />
+	<script type="text/javascript">
+	
+	    $(function() {
+			var url = ctx + "system/role/deptTreeData?roleId=" + $("#roleId").val();
+			var options = {
+				id: "deptTrees",
+		        url: url,
+		        check: { enable: true, nocheckInherit: true, chkboxType: { "Y": "ps", "N": "ps" } },
+		        expandLevel: 2
+		    };
+			$.tree.init(options);
+	    });
+	    
+	    $('input').on('ifChanged', function(obj){
+			var type = $(this).val();
+			var checked = obj.currentTarget.checked;
+			if (type == 1) {
+			    if (checked) {
+			        $._tree.expandAll(true);
+			    } else {
+			        $._tree.expandAll(false);
+			    }
+			} else if (type == "2") {
+			    if (checked) {
+			        $._tree.checkAllNodes(true);
+			    } else {
+			        $._tree.checkAllNodes(false);
+			    }
+			} else if (type == "3") {
+			    if (checked) {
+			        $._tree.setting.check.chkboxType = { "Y": "ps", "N": "ps" };
+			    } else {
+			        $._tree.setting.check.chkboxType = { "Y": "", "N": "" };
+			    }
+			}
+		})
+
+		function submitHandler() {
+	        if ($.validate.form()) {
+	        	edit();
+	        }
+	    }
+		
+		function edit() {
+			var roleId = $("input[name='roleId']").val();
+			var roleName = $("input[name='roleName']").val();
+			var roleKey = $("input[name='roleKey']").val();
+			var dataScope = $("#dataScope").val();
+            var deptIds = $.tree.getCheckedNodes();
+			$.ajax({
+				cache : true,
+				type : "POST",
+				url : ctx + "system/role/authDataScope",
+				data : {
+					"roleId": roleId,
+					"roleName": roleName,
+					"roleKey": roleKey,
+					"dataScope": dataScope,
+			        "deptIds": deptIds
+				},
+				async : false,
+				error : function(request) {
+					$.modal.alertError("系统错误");
+				},
+				success : function(data) {
+					$.operate.successCallback(data);
+				}
+			});
+		}
+		
+		$("#dataScope").change(function(event){
+        	var dataScope = $(event.target).val();
+        	dataScopeVisible(dataScope);
+        });
+		
+		function dataScopeVisible(dataScope) {
+			if (dataScope == 2) {
+	    		$("#authDataScope").show();
+	    	} else {
+	    		$._tree.checkAllNodes(false);
+	    		$("#authDataScope").hide();
+	    	}
+		}
+	</script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/system/role/edit.html b/ruoyi-admin/src/main/resources/templates/system/role/edit.html
new file mode 100644
index 0000000..d2e75b3
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/system/role/edit.html
@@ -0,0 +1,183 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+	<th:block th:include="include :: header('修改角色')" />
+	<th:block th:include="include :: ztree-css" />
+</head>
+<body class="white-bg">
+	<div class="wrapper wrapper-content animated fadeInRight ibox-content">
+		<form class="form-horizontal m" id="form-role-edit" th:object="${role}">
+			<input id="roleId" name="roleId" type="hidden" th:field="*{roleId}"/>
+			<div class="form-group">
+				<label class="col-sm-3 control-label is-required">角色名称:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="roleName" id="roleName" th:field="*{roleName}" required>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label is-required">权限字符:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="roleKey" id="roleKey" th:field="*{roleKey}" required>
+					<span class="help-block m-b-none"><i class="fa fa-info-circle"></i> 控制器中定义的权限字符,如:@RequiresRoles("")</span>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label is-required">显示顺序:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="roleSort" id="roleSort" th:field="*{roleSort}" required>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">状态:</label>
+				<div class="col-sm-8">
+					<label class="toggle-switch switch-solid">
+                        <input type="checkbox" id="status" th:checked="${role.status == '0' ? true : false}">
+                        <span></span>
+                    </label>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">备注:</label>
+				<div class="col-sm-8">
+					<input id="remark" name="remark" class="form-control" type="text" th:field="*{remark}">
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">菜单权限:</label>
+				<div class="col-sm-8">
+				    <label class="check-box">
+				        <input type="checkbox" value="1">展开/折叠</label>
+				    <label class="check-box">
+				        <input type="checkbox" value="2">全选/全不选</label>
+				    <label class="check-box">
+				        <input type="checkbox" value="3" checked>父子联动</label>
+				    <div id="menuTrees" class="ztree ztree-border"></div>
+				</div>
+			</div>
+		</form>
+	</div>
+	<th:block th:include="include :: footer" />
+	<th:block th:include="include :: ztree-js" />
+	<script type="text/javascript">
+	     $(function() {
+			var url = ctx + "system/menu/roleMenuTreeData?roleId=" + $("#roleId").val();
+			var options = {
+				id: "menuTrees",
+		        url: url,
+		        check: { enable: true },
+		        expandLevel: 0
+		    };
+			$.tree.init(options);
+		});
+	
+		$("#form-role-edit").validate({
+			onkeyup: false,
+			rules:{
+				roleName:{
+					remote: {
+		                url: ctx + "system/role/checkRoleNameUnique",
+		                type: "post",
+		                dataType: "json",
+		                data: {
+							"roleId": function() {
+							    return $("#roleId").val();
+							},
+							"roleName": function() {
+							    return $.common.trim($("#roleName").val());
+							}
+		                }
+		            }
+				},
+				roleKey:{
+					remote: {
+		                url: ctx + "system/role/checkRoleKeyUnique",
+		                type: "post",
+		                dataType: "json",
+		                data: {
+							"roleId": function() {
+								return $("#roleId").val();
+							},
+							"roleKey": function() {
+							    return $.common.trim($("#roleKey").val());
+							}
+		                }
+		            }
+				},
+				roleSort:{
+					digits:true
+				},
+			},
+			messages: {
+		        "roleName": {
+		            remote: "角色名称已经存在"
+		        },
+		        "roleKey": {
+		            remote: "角色权限已经存在"
+		        }
+		    },
+		    focusCleanup: true
+		});
+		
+		$('input').on('ifChanged', function(obj){
+			var type = $(this).val();
+			var checked = obj.currentTarget.checked;
+			if (type == 1) {
+			    if (checked) {
+			        $._tree.expandAll(true);
+			    } else {
+			        $._tree.expandAll(false);
+			    }
+			} else if (type == "2") {
+			    if (checked) {
+			        $._tree.checkAllNodes(true);
+			    } else {
+			        $._tree.checkAllNodes(false);
+			    }
+			} else if (type == "3") {
+			    if (checked) {
+			        $._tree.setting.check.chkboxType = { "Y": "ps", "N": "ps" };
+			    } else {
+			        $._tree.setting.check.chkboxType = { "Y": "", "N": "" };
+			    }
+			}
+		})
+
+		function edit() {
+			var roleId = $("input[name='roleId']").val();
+			var roleName = $("input[name='roleName']").val();
+			var roleKey = $("input[name='roleKey']").val();
+			var roleSort = $("input[name='roleSort']").val();
+			var status = $("input[id='status']").is(':checked') == true ? 0 : 1;
+			var remark = $("input[name='remark']").val();
+			var menuIds = $.tree.getCheckedNodes();
+			$.ajax({
+				cache : true,
+				type : "POST",
+				url : ctx + "system/role/edit",
+				data : {
+					"roleId": roleId,
+					"roleName": roleName,
+					"roleKey": roleKey,
+					"roleSort": roleSort,
+					"status": status,
+					"remark": remark,
+					"menuIds": menuIds
+				},
+				async : false,
+				error : function(request) {
+					$.modal.alertError("系统错误");
+				},
+				success : function(data) {
+					$.operate.successCallback(data);
+				}
+			});
+		}
+		
+		function submitHandler() {
+	        if ($.validate.form()) {
+	        	edit();
+	        }
+	    }
+	</script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/system/role/role.html b/ruoyi-admin/src/main/resources/templates/system/role/role.html
new file mode 100644
index 0000000..991cfa9
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/system/role/role.html
@@ -0,0 +1,190 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('角色列表')" />
+</head>
+<body class="gray-bg">
+	<div class="container-div">
+		<div class="row">
+			<div class="col-sm-12 search-collapse">
+				<form id="role-form">
+					<div class="select-list">
+						<ul>
+							<li>
+								角色名称:<input type="text" name="roleName"/>
+							</li>
+							<li>
+								权限字符:<input type="text" name="roleKey"/>
+							</li>
+							<li>
+								角色状态:<select name="status" th:with="type=${@dict.getType('sys_normal_disable')}">
+									<option value="">所有</option>
+									<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
+								</select>
+							</li>
+							<li class="select-time">
+								<label>创建时间: </label>
+								<input type="text" class="time-input" id="startTime" placeholder="开始时间" name="params[beginTime]"/>
+								<span>-</span>
+								<input type="text" class="time-input" id="endTime" placeholder="结束时间" name="params[endTime]"/>
+							</li>
+							<li>
+								<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
+							    <a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
+							</li>
+						</ul>
+					</div>
+				</form>
+			</div>
+		
+			<div class="btn-group-sm" id="toolbar" role="group">
+				<a class="btn btn-success" onclick="$.operate.add()" shiro:hasPermission="system:role:add">
+	                <i class="fa fa-plus"></i> 新增
+	            </a>
+	            <a class="btn btn-primary single disabled" onclick="$.operate.edit()" shiro:hasPermission="system:role:edit">
+		            <i class="fa fa-edit"></i> 修改
+		        </a>
+				<a class="btn btn-danger multiple disabled" onclick="$.operate.removeAll()" shiro:hasPermission="system:role:remove">
+		            <i class="fa fa-remove"></i> 删除
+		        </a>
+		        <a class="btn btn-warning" onclick="$.table.exportExcel()" shiro:hasPermission="system:role:export">
+		            <i class="fa fa-download"></i> 导出
+		        </a>
+	        </div>
+	        
+	        <div class="col-sm-12 select-table table-striped">
+			    <table id="bootstrap-table"></table>
+			</div>
+		</div>
+	</div>
+	<th:block th:include="include :: footer" />
+	<script th:inline="javascript">
+		var editFlag = [[${@permission.hasPermi('system:role:edit')}]];
+		var removeFlag = [[${@permission.hasPermi('system:role:remove')}]];
+		var prefix = ctx + "system/role";
+		
+
+		$(function() {
+		    var options = {
+		        url: prefix + "/list",
+		        createUrl: prefix + "/add",
+		        updateUrl: prefix + "/edit/{id}",
+		        removeUrl: prefix + "/remove",
+		        exportUrl: prefix + "/export",
+		        sortName: "roleSort",
+		        modalName: "角色",
+		        columns: [{
+		            checkbox: true
+		        },
+		        {
+		            field: 'roleId',
+		            title: '角色编号'
+		        },
+		        {
+		            field: 'roleName',
+		            title: '角色名称',
+		            sortable: true
+		        },
+		        {
+		            field: 'roleKey',
+		            title: '权限字符',
+		            sortable: true
+		        },
+		        {
+		            field: 'dataScope',
+		            title: '数据权限',
+		            formatter: function(value, item, index) {
+		                if (item.dataScope == '1') {
+		                    return '<span class="badge badge-primary">全部数据权限</span>';
+		                }
+		                else if (item.dataScope == '2') {
+		                    return '<span class="badge badge-success">自定义数据权限</span>';
+		                }
+		                else if (item.dataScope == '3') {
+		                    return '<span class="badge badge-info">本部门数据权限</span>';
+		                }
+		                else if (item.dataScope == '4') {
+		                    return '<span class="badge badge-warning">本部门及以下数据权限</span>';
+		                }
+		                else if (item.dataScope == '5') {
+		                    return '<span class="badge badge-danger">仅本人数据权限</span>';
+		                }
+		            }
+		        },
+		        {
+		            field: 'roleSort',
+		            title: '显示顺序',
+		            sortable: true
+		        },
+		        {
+		        	visible: editFlag == 'hidden' ? false : true,
+		        	title: '角色状态',
+		        	align: 'center',
+		        	formatter: function (value, row, index) {
+		        		return statusTools(row);
+		        	}
+		        },
+		        {
+		            field: 'createTime',
+		            title: '创建时间',
+		            sortable: true
+		        },
+		        {
+		            title: '操作',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		            	if (row.roleId != 1) {
+		                    var actions = [];
+		                    actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.roleId + '\')"><i class="fa fa-edit"></i>编辑</a> ');
+		                    actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.roleId + '\')"><i class="fa fa-remove"></i>删除</a> ');
+		                    var more = [];
+		                    more.push("<a class='btn btn-default btn-xs " + editFlag + "' href='javascript:void(0)' onclick='authDataScope(" + row.roleId + ")'><i class='fa fa-check-square-o'></i>数据权限</a> ");
+		                    more.push("<a class='btn btn-default btn-xs " + editFlag + "' href='javascript:void(0)' onclick='authUser(" + row.roleId + ")'><i class='fa fa-user'></i>分配用户</a>");
+		                    actions.push('<a tabindex="0" class="btn btn-info btn-xs" role="button" data-container="body" data-placement="left" data-toggle="popover" data-html="true" data-trigger="hover" data-content="' + more.join('') + '"><i class="fa fa-chevron-circle-right"></i>更多操作</a>');
+		                    return actions.join('');
+		            	} else {
+		                    return "";
+		                }
+		            }
+		        }]
+		    };
+		    $.table.init(options);
+		});
+		
+		/* 角色管理-分配数据权限 */
+		function authDataScope(roleId) {
+		    var url = prefix + '/authDataScope/' + roleId;
+		    $.modal.open("分配数据权限", url);
+		}
+		
+		/* 角色管理-分配用户 */
+		function authUser(roleId) {
+		    var url = prefix + '/authUser/' + roleId;
+		    $.modal.openTab("分配用户", url);
+		}
+		
+		/* 角色状态显示 */
+		function statusTools(row) {
+		    if (row.status == 1) {
+    			return '<i class=\"fa fa-toggle-off text-info fa-2x\" onclick="enable(\'' + row.roleId + '\')"></i> ';
+    		} else {
+    			return '<i class=\"fa fa-toggle-on text-info fa-2x\" onclick="disable(\'' + row.roleId + '\')"></i> ';
+    		}
+		}
+		
+		/* 角色管理-停用 */
+		function disable(roleId) {
+			$.modal.confirm("确认要停用角色吗?", function() {
+				$.operate.post(prefix + "/changeStatus", { "roleId": roleId, "status": 1 });
+		    })
+		}
+
+		/* 角色管理启用 */
+		function enable(roleId) {
+			$.modal.confirm("确认要启用角色吗?", function() {
+				$.operate.post(prefix + "/changeStatus", { "roleId": roleId, "status": 0 });
+		    })
+		}
+	</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/system/role/selectUser.html b/ruoyi-admin/src/main/resources/templates/system/role/selectUser.html
new file mode 100644
index 0000000..e964062
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/system/role/selectUser.html
@@ -0,0 +1,113 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+	<th:block th:include="include :: header('分配角色选择用户')" />
+</head>
+
+<body class="gray-bg">
+	<div class="container-div">
+		<div class="row">
+			<div class="col-sm-12 search-collapse">
+				<form id="role-form">
+				    <input type="hidden" id="roleId" name="roleId" th:value="${role.roleId}">
+					<div class="select-list">
+						<ul>
+							<li>
+								登录名称:<input type="text" name="loginName"/>
+							</li>
+							<li>
+								手机号码:<input type="text" name="phonenumber"/>
+							</li>
+							<li>
+								<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
+							    <a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
+							</li>
+						</ul>
+					</div>
+				</form>
+			</div>
+	        
+	        <div class="col-sm-12 select-table table-striped">
+			    <table id="bootstrap-table"></table>
+			</div>
+		</div>
+	</div>
+	<th:block th:include="include :: footer" />
+	<script th:inline="javascript">
+		var datas = [[${@dict.getType('sys_normal_disable')}]];
+		var prefix = ctx + "system/role/authUser";
+
+		$(function() {
+			var options = {
+		        url: prefix + "/unallocatedList",
+		        queryParams: queryParams,
+		        sortName: "createTime",
+		        sortOrder: "desc",
+		        showSearch: false,
+		        showRefresh: false,
+		        showToggle: false,
+		        showColumns: false,
+		        clickToSelect: true,
+		        rememberSelected: true,
+		        columns: [{
+		        	field: 'state',
+		            checkbox: true
+		        },
+		        {
+		            field: 'userId',
+		            title: '用户ID',
+		            visible: false
+		        },
+		        {
+		            field: 'loginName',
+		            title: '登录名称',
+		            sortable: true
+		        },
+		        {
+		            field: 'userName',
+		            title: '用户名称'
+		        },
+		        {
+		            field: 'email',
+		            title: '邮箱'
+		        },
+		        {
+		            field: 'phonenumber',
+		            title: '手机'
+		        },
+		        {
+		        	field: 'status',
+		        	title: '用户状态',
+		        	align: 'center',
+		        	formatter: function (value, row, index) {
+		        		return $.table.selectDictLabel(datas, value);
+		        	}
+		        },
+		        {
+		            field: 'createTime',
+		            title: '创建时间',
+		            sortable: true
+		        }]
+		    };
+		    $.table.init(options);
+		});
+		
+		function queryParams(params) {
+			var search = $.table.queryParams(params);
+			search.roleId = $("#roleId").val();
+			return search;
+		}
+		
+		/* 添加用户-选择用户-提交 */
+		function submitHandler() {
+			var rows = $.table.selectFirstColumns();
+			if (rows.length == 0) {
+       			$.modal.alertWarning("请至少选择一条记录");
+       			return;
+       		}
+			var data = { "roleId": $("#roleId").val(), "userIds": rows.join() };
+			$.operate.save(prefix + "/selectAll", data);
+		}
+	</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/system/user/add.html b/ruoyi-admin/src/main/resources/templates/system/user/add.html
new file mode 100644
index 0000000..680dff1
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/system/user/add.html
@@ -0,0 +1,259 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+	<th:block th:include="include :: header('新增用户')" />
+	<th:block th:include="include :: select2-css" />
+</head>
+<body>
+    <div class="main-content">
+        <form id="form-user-add" class="form-horizontal">
+            <input name="deptId" type="hidden" id="treeId"/>
+            <h4 class="form-header h4">基本信息</h4>
+            <div class="row">
+            	<div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label is-required">用户名称:</label>
+                        <div class="col-sm-8">
+                            <input name="userName" placeholder="请输入用户名称" class="form-control" type="text" maxlength="30" required>
+                        </div>
+                    </div>
+                </div>
+                <div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label">归属部门:</label>
+                        <div class="col-sm-8">
+                            <div class="input-group">
+                            	<input name="deptName" onclick="selectDeptTree()" id="treeName" type="text" placeholder="请选择归属部门" class="form-control">
+                                <span class="input-group-addon"><i class="fa fa-search"></i></span>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="row">
+                <div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label">手机号码:</label>
+                        <div class="col-sm-8">
+                            <div class="input-group">
+                                <input id="phonenumber" name="phonenumber" placeholder="请输入手机号码" class="form-control" type="text" maxlength="11">
+                                <span class="input-group-addon"><i class="fa fa-mobile"></i></span>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+                <div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label">邮箱:</label>
+                        <div class="col-sm-8">
+                            <div class="input-group">
+                                <input id="email" name="email" class="form-control email" type="text" maxlength="50" placeholder="请输入邮箱">
+                                <span class="input-group-addon"><i class="fa fa-envelope"></i></span>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="row">
+                <div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label is-required">登录账号:</label>
+                        <div class="col-sm-8">
+                            <input id="loginName" name="loginName" placeholder="请输入登录账号" class="form-control" type="text" maxlength="30" required>
+                        </div>
+                    </div>
+                </div>
+                <div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label is-required">登录密码:</label>
+                        <div class="col-sm-8">
+                            <div class="input-group">
+                                <input id="password" name="password" placeholder="请输入登录密码" class="form-control" type="password" th:value="${@config.getKey('sys.user.initPassword')}" required>
+                                <span class="input-group-addon" title="登录密码,鼠标按下显示密码"
+                                    onmousedown="$('#password').attr('type','text')"
+                                    onmouseup="$('#password').attr('type','password')"><i class="fa fa-key"></i></span>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="row">
+                <div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label">用户性别:</label>
+                        <div class="col-sm-8">
+                            <select name="sex" class="form-control m-b" th:with="type=${@dict.getType('sys_user_sex')}">
+				                <option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
+				            </select>
+                        </div>
+                    </div>
+                </div>
+                <div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label">用户状态:</label>
+                        <div class="col-sm-8">
+                            <label class="toggle-switch switch-solid">
+	                            <input type="checkbox" id="status" checked>
+	                            <span></span>
+	                        </label>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="row">
+            	<div class="col-sm-12">
+                    <div class="form-group">
+                        <label class="col-xs-2 control-label">岗位:</label>
+                        <div class="col-xs-4">
+                            <select id="post" class="form-control select2-multiple" multiple>
+								<option th:each="post:${posts}" th:value="${post.postId}" th:text="${post.postName}" th:disabled="${post.status == '1'}"></option>
+							</select>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="row">
+            	<div class="col-sm-12">
+                    <div class="form-group">
+                        <label class="col-xs-2 control-label">角色:</label>
+                        <div class="col-xs-10">
+                            <label th:each="role:${roles}" class="check-box">
+								<input name="role" type="checkbox" th:value="${role.roleId}" th:text="${role.roleName}" th:disabled="${role.status == '1'}">
+							</label>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <h4 class="form-header h4">其他信息</h4>
+            <div class="row">
+                <div class="col-sm-12">
+                    <div class="form-group">
+                        <label class="col-xs-2 control-label">备注:</label>
+                        <div class="col-xs-10">
+                            <textarea name="remark" maxlength="500" class="form-control" rows="3"></textarea>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </form>
+    </div>
+      
+    <div class="row">
+        <div class="col-sm-offset-5 col-sm-10">
+            <button type="button" class="btn btn-sm btn-primary" onclick="submitHandler()"><i class="fa fa-check"></i>保 存</button>&nbsp;
+            <button type="button" class="btn btn-sm btn-danger" onclick="closeItem()"><i class="fa fa-reply-all"></i>关 闭 </button>
+        </div>
+    </div>
+	<th:block th:include="include :: footer" />
+	<th:block th:include="include :: select2-js" />
+	<script>
+	    var prefix = ctx + "system/user";
+	
+        $("#form-user-add").validate({
+        	onkeyup: false,
+        	rules:{
+        		loginName:{
+        			minlength: 2,
+        			maxlength: 20,
+        			remote: {
+                        url: prefix + "/checkLoginNameUnique",
+                        type: "post",
+                        dataType: "json",
+                        data: {
+                        	"loginName": function() {
+                                return $.common.trim($("#loginName").val());
+                            }
+                        }
+                    }
+        		},
+        		password:{
+        			minlength: 5,
+        			maxlength: 20,
+        			specialSign: true
+        		},
+        		email:{
+                    email:true,
+                    remote: {
+                        url: prefix + "/checkEmailUnique",
+                        type: "post",
+                        dataType: "json",
+                        data: {
+                            "email": function () {
+                                return $.common.trim($("#email").val());
+                            }
+                        }
+                    }
+        		},
+        		phonenumber:{
+        			isPhone:true,
+                    remote: {
+                        url: prefix + "/checkPhoneUnique",
+                        type: "post",
+                        dataType: "json",
+                        data: {
+                            "phonenumber": function () {
+                                return $.common.trim($("#phonenumber").val());
+                            }
+                        }
+                    }
+        		},
+        	},
+        	messages: {
+                "loginName": {
+                    remote: "用户已经存在"
+                },
+        		"email": {
+                    remote: "Email已经存在"
+                },
+        		"phonenumber":{
+                	remote: "手机号码已经存在"
+        		}
+            },
+            focusCleanup: true
+        });
+        
+        function submitHandler() {
+        	var chrtype = [[${#strings.defaultString(@config.getKey('sys.account.chrtype'), 0)}]];
+			var password = $("#password").val();
+	        if ($.validate.form() && checkpwd(chrtype, password)) {
+	        	var data = $("#form-user-add").serializeArray();
+	        	var status = $("input[id='status']").is(':checked') == true ? 0 : 1;
+	        	var roleIds = $.form.selectCheckeds("role");
+	        	var postIds = $.form.selectSelects("post");
+	        	data.push({"name": "status", "value": status});
+	        	data.push({"name": "roleIds", "value": roleIds});
+	        	data.push({"name": "postIds", "value": postIds});
+	        	$.operate.saveTab(prefix + "/add", data);
+	        }
+	    }
+         
+        /* 用户管理-新增-选择部门树 */
+        function selectDeptTree() {
+        	var treeId = $("#treeId").val();
+        	var deptId = $.common.isEmpty(treeId) ? "100" : $("#treeId").val();
+        	var url = ctx + "system/user/selectDeptTree/" + deptId;
+			var options = {
+				title: '选择部门',
+				width: "380",
+				url: url,
+				callBack: doSubmit
+			};
+			$.modal.openOptions(options);
+		}
+		
+		function doSubmit(index, layero){
+			var body = $.modal.getChildFrame(index);
+   			$("#treeId").val(body.find('#treeId').val());
+   			$("#treeName").val(body.find('#treeName').val());
+   			$.modal.close(index);
+		}
+
+		$(function() {
+            $('#post').select2({
+                placeholder: "请选择岗位",
+                allowClear: true
+            });
+        })
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/system/user/authRole.html b/ruoyi-admin/src/main/resources/templates/system/user/authRole.html
new file mode 100644
index 0000000..a2a131d
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/system/user/authRole.html
@@ -0,0 +1,114 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+	<th:block th:include="include :: header('用户分配角色')" />
+</head>
+<body>
+    <div class="main-content">
+        <form id="form-user-add" class="form-horizontal">
+            <input type="hidden" id="userId" name="userId" th:value="${user.userId}">
+            <h4 class="form-header h4">基本信息</h4>
+            <div class="row">
+            	<div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label is-required">用户名称:</label>
+                        <div class="col-sm-8">
+                            <input name="userName" class="form-control" type="text" disabled th:value="${user.userName}">
+                        </div>
+                    </div>
+                </div>
+                <div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label is-required">登录账号:</label>
+                        <div class="col-sm-8">
+                            <input name="loginName" class="form-control" type="text" disabled th:value="${user.loginName}">
+                        </div>
+                    </div>
+                </div> 
+            </div>
+           
+            <h4 class="form-header h4">分配角色</h4>
+            <div class="row">
+                <div class="col-sm-12">
+                    <div class="col-sm-12 select-table table-striped">
+					    <table id="bootstrap-table"></table>
+					</div>
+                </div>
+            </div>
+        </form>
+    </div>
+      
+    <div class="row">
+        <div class="col-sm-offset-5 col-sm-10">
+            <button type="button" class="btn btn-sm btn-primary" onclick="submitHandler()"><i class="fa fa-check"></i>保 存</button>&nbsp;
+            <button type="button" class="btn btn-sm btn-danger" onclick="closeItem()"><i class="fa fa-reply-all"></i>关 闭 </button>
+        </div>
+    </div>
+	<th:block th:include="include :: footer" />
+	<script th:inline="javascript">
+	    var prefix = ctx + "system/user/authRole";
+	    var roles = [[${roles}]]
+	    
+	    $(function() {
+		    var options = {
+		        data: roles,
+		        sidePagination: "client",
+		        sortName: "roleSort",
+		        showSearch: false,
+                showRefresh: false,
+                showToggle: false,
+                showColumns: false,
+                clickToSelect: true,
+                maintainSelected: true,
+		        columns: [{
+		            checkbox: true,
+		            formatter:function (value, row, index) {
+		            	if($.common.isEmpty(value)) {
+		            		return { checked: row.flag };
+		            	} else {
+		            		return { checked: value }
+		            	}
+		            }
+		        },
+		        {
+		            field: 'roleId',
+		            title: '角色编号'
+		        },
+		        {
+		            field: 'roleSort',
+		            title: '排序',
+		            sortable: true,
+		            visible: false
+		        },
+		        {
+		            field: 'roleName',
+		            title: '角色名称'
+		        },
+		        {
+		            field: 'roleKey',
+		            title: '权限字符',
+		            sortable: true
+		        },
+		        {
+		            field: 'createTime',
+		            title: '创建时间',
+		            sortable: true
+		        }]
+		    };
+		    $.table.init(options);
+		});
+	    
+	    /* 添加角色-提交 */
+        function submitHandler(index, layero){
+            var roleIds = [];
+        	var data = $('#bootstrap-table').bootstrapTable('getData');
+        	for (var i = 0; i < data.length; i++) {
+        		if (data[i][0] || ($.common.isEmpty(data[i][0]) && data[i].flag)) {
+        		    roleIds.push(data[i].roleId)
+        		}
+			}
+        	$.operate.saveTab(prefix + "/insertAuthRole", { "userId": $("#userId").val(), "roleIds": roleIds.join() });
+        }
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/system/user/deptTree.html b/ruoyi-admin/src/main/resources/templates/system/user/deptTree.html
new file mode 100644
index 0000000..1286ba3
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/system/user/deptTree.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+	<th:block th:include="include :: header('部门树选择')" />
+	<th:block th:include="include :: ztree-css" />
+</head>
+<style>
+	body{height:auto;font-family: "Microsoft YaHei";}
+	button{font-family: "SimSun","Helvetica Neue",Helvetica,Arial;}
+</style>
+<body class="hold-transition box box-main">
+	<input id="treeId"   name="treeId"    type="hidden" th:value="${dept.deptId}"/>
+	<input id="treeName" name="treeName"  type="hidden" th:value="${dept.deptName}"/>
+	<div class="wrapper"><div class="treeShowHideButton" onclick="$.tree.toggleSearch();">
+		<label id="btnShow" title="显示搜索" style="display:none;">︾</label>
+		<label id="btnHide" title="隐藏搜索">︽</label>
+	</div>
+	<div class="treeSearchInput" id="search">
+		<label for="keyword">关键字:</label><input type="text" class="empty" id="keyword" maxlength="50">
+		<button class="btn" id="btn" onclick="$.tree.searchNode()"> 搜索 </button>
+	</div>
+	<div class="treeExpandCollapse">
+		<a href="javascript:;" onclick="$.tree.expand()">展开</a> /
+		<a href="javascript:;" onclick="$.tree.collapse()">折叠</a>
+	</div>
+	<div id="tree" class="ztree treeselect"></div>
+	</div>
+	<th:block th:include="include :: footer" />
+	<th:block th:include="include :: ztree-js" />
+	<script th:inline="javascript">
+	    var prefix = ctx + "system/user"
+	    var deptId = [[${deptId}]];
+		$(function() {
+			var url = prefix + "/deptTreeData";
+			var options = {
+		        url: url,
+		        expandLevel: 2,
+		        onClick : zOnClick
+		    };
+			$.tree.init(options);
+		});
+		
+		function zOnClick(event, treeId, treeNode) {
+		    var treeId = treeNode.id;
+		    var treeName = treeNode.name;
+		    $("#treeId").val(treeId);
+		    $("#treeName").val(treeName);
+		}
+	</script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/system/user/edit.html b/ruoyi-admin/src/main/resources/templates/system/user/edit.html
new file mode 100644
index 0000000..255239e
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/system/user/edit.html
@@ -0,0 +1,225 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+	<th:block th:include="include :: header('修改用户')" />
+	<th:block th:include="include :: select2-css" />
+</head>
+<body>
+    <div class="main-content">
+        <form class="form-horizontal" id="form-user-edit" th:object="${user}">
+            <input name="userId"  type="hidden"  th:field="*{userId}" />
+			<input name="deptId"  type="hidden"  th:field="*{deptId}" id="treeId"/>
+            <h4 class="form-header h4">基本信息</h4>
+            <div class="row">
+            	<div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label is-required">用户名称:</label>
+                        <div class="col-sm-8">
+                            <input name="userName" placeholder="请输入用户名称" class="form-control" type="text" maxlength="30" th:field="*{userName}" required>
+                        </div>
+                    </div>
+                </div>
+                <div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label">归属部门:</label>
+                        <div class="col-sm-8">
+                            <div class="input-group">
+                                <input class="form-control" type="text" name="deptName" onclick="selectDeptTree()" id="treeName" th:field="*{dept.deptName}">
+                            	<span class="input-group-addon"><i class="fa fa-search"></i></span>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="row">
+                <div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label">手机号码:</label>
+                        <div class="col-sm-8">
+                            <div class="input-group">
+                                <input name="phonenumber" placeholder="请输入手机号码" class="form-control" type="text" maxlength="11" th:field="*{phonenumber}">
+                                <span class="input-group-addon"><i class="fa fa-mobile"></i></span>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+                <div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label">邮箱:</label>
+                        <div class="col-sm-8">
+                            <div class="input-group">
+                                <input name="email" class="form-control email" type="text" maxlength="50" placeholder="请输入邮箱" th:field="*{email}">
+                                <span class="input-group-addon"><i class="fa fa-envelope"></i></span>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="row">
+                <div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label is-required">登录账号:</label>
+                        <div class="col-sm-8">
+                            <input class="form-control" type="text" readonly="true" th:field="*{loginName}"/>
+                        </div>
+                    </div>
+                </div>
+                <div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label">用户状态:</label>
+                        <div class="col-sm-8">
+                            <label class="toggle-switch switch-solid">
+	                            <input type="checkbox" id="status" th:checked="${user.status == '0' ? true : false}">
+	                            <span></span>
+	                        </label>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="row">
+                <div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label">岗位:</label>
+                        <div class="col-sm-8">
+                            <select id="post" class="form-control select2-multiple" multiple>
+								<option th:each="post:${posts}" th:value="${post.postId}" th:text="${post.postName}" th:selected="${post.flag}" th:disabled="${post.status == '1'}"></option>
+							</select>
+                        </div>
+                    </div>
+                </div>
+                <div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label">用户性别:</label>
+                        <div class="col-sm-8">
+                            <select name="sex" class="form-control m-b" th:with="type=${@dict.getType('sys_user_sex')}">
+				                <option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}" th:field="*{sex}"></option>
+				            </select>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="row">
+            	<div class="col-sm-12">
+                    <div class="form-group">
+                        <label class="col-xs-2 control-label">角色:</label>
+                        <div class="col-xs-10">
+                            <label th:each="role:${roles}" class="check-box">
+								<input name="role" type="checkbox" th:value="${role.roleId}" th:text="${role.roleName}" th:checked="${role.flag}" th:disabled="${role.status == '1'}">
+							</label>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <h4 class="form-header h4">其他信息</h4>
+            <div class="row">
+                <div class="col-sm-12">
+                    <div class="form-group">
+                        <label class="col-xs-2 control-label">备注:</label>
+                        <div class="col-xs-10">
+                            <textarea name="remark" maxlength="500" class="form-control" rows="3">[[*{remark}]]</textarea>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </form>
+    </div>
+    <div class="row">
+        <div class="col-sm-offset-5 col-sm-10">
+            <button type="button" class="btn btn-sm btn-primary" onclick="submitHandler()"><i class="fa fa-check"></i>保 存</button>&nbsp;
+            <button type="button" class="btn btn-sm btn-danger" onclick="closeItem()"><i class="fa fa-reply-all"></i>关 闭 </button>
+        </div>
+    </div>
+	<th:block th:include="include :: footer" />
+	<th:block th:include="include :: select2-js" />
+	<script type="text/javascript">
+        var prefix = ctx + "system/user";
+        
+        $("#form-user-edit").validate({
+        	onkeyup: false,
+        	rules:{
+        		email:{
+                    email:true,
+                    remote: {
+                        url: prefix + "/checkEmailUnique",
+                        type: "post",
+                        dataType: "json",
+                        data: {
+                        	"userId": function() {
+                                return $("#userId").val();
+                            },
+                			"email": function() {
+                                return $.common.trim($("#email").val());
+                            }
+                        }
+                    }
+        		},
+        		phonenumber:{
+        			isPhone:true,
+                    remote: {
+                        url: prefix + "/checkPhoneUnique",
+                        type: "post",
+                        dataType: "json",
+                        data: {
+                        	"userId": function() {
+                        		return $("#userId").val();
+                            },
+                			"phonenumber": function() {
+                                return $.common.trim($("#phonenumber").val());
+                            }
+                        }
+                    }
+        		},
+        	},
+        	messages: {
+        		"email": {
+                    remote: "Email已经存在"
+                },
+        		"phonenumber":{
+                	remote: "手机号码已经存在"
+        		}
+            },
+            focusCleanup: true
+        });
+        
+        function submitHandler() {
+	        if ($.validate.form()) {
+	        	var data = $("#form-user-edit").serializeArray();
+	        	var status = $("input[id='status']").is(':checked') == true ? 0 : 1;
+	        	var roleIds = $.form.selectCheckeds("role");
+	        	var postIds = $.form.selectSelects("post");
+	        	data.push({"name": "status", "value": status});
+	        	data.push({"name": "roleIds", "value": roleIds});
+	        	data.push({"name": "postIds", "value": postIds});
+	        	$.operate.saveTab(prefix + "/edit", data);
+	        }
+	    }
+
+        /* 用户管理-修改-选择部门树 */
+        function selectDeptTree() {
+        	var deptId = $.common.isEmpty($("#treeId").val()) ? "100" : $("#treeId").val();
+            var url = ctx + "system/user/selectDeptTree/" + deptId;
+		    var options = {
+				title: '选择部门',
+				width: "380",
+				url: url,
+				callBack: doSubmit
+			};
+			$.modal.openOptions(options);
+		}
+		
+		function doSubmit(index, layero){
+			var body = $.modal.getChildFrame(index);
+   			$("#treeId").val(body.find('#treeId').val());
+   			$("#treeName").val(body.find('#treeName').val());
+   			$.modal.close(index);
+		}
+
+		$(function() {
+            $('#post').select2({
+                placeholder: "请选择岗位",
+                allowClear: true
+            });
+        })
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/system/user/profile/avatar.html b/ruoyi-admin/src/main/resources/templates/system/user/profile/avatar.html
new file mode 100644
index 0000000..e473ff1
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/system/user/profile/avatar.html
@@ -0,0 +1,261 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+	<th:block th:include="include :: header('修改用户头像')" />
+	<th:block th:include="include :: cropper-css" />
+	<style type='text/css'>
+	/* avator css start */
+	.container {
+		margin: 10px 5px 5px 5px;
+	}
+	
+	.action {
+		padding: 5px 0px;
+	}
+	
+	.cropped {
+		width: 200px;
+		border: 1px #ddd solid;
+		box-shadow: 0px 0px 12px #ddd;
+	}
+	
+	.img-preview {
+		border-radius: 50%;
+		box-shadow: 0px 0px 12px #7e7e7e;
+		display: inline-block;
+	}
+	
+	.preview-box {
+		text-align: center;
+		margin: 0px auto;
+		margin-top: 10px;
+		color: #bbb;
+	}
+	
+	.preview-md {
+		width: 128px;
+		height: 128px;
+	}
+	
+	.preview-sm {
+		width: 96px;
+		height: 96px;
+	}
+	
+	.preview-xs {
+		width: 64px;
+		height: 64px;
+	}
+	
+	.imageBox {
+		border: 1px solid #aaa;
+		overflow: hidden;
+		cursor: move;
+		box-shadow: 4px 4px 12px #B0B0B0;
+		margin: 0px auto;
+	}
+	
+	.btn-custom {
+		float: right;
+		width: 46px;
+		display: inline-block;
+		margin-bottom: 10px;
+		height: 37px;
+		line-height: 37px;
+		font-size: 14px;
+		color: #FFFFFF;
+		margin: 0px 2px;
+		background-color: #f38e81;
+		border-radius: 3px;
+		text-decoration: none;
+		cursor: pointer;
+		box-shadow: 0px 0px 5px #B0B0B0;
+		border: 0px #fff solid;
+	}
+    /*选择文件上传*/
+	.new-contentarea {
+		width: 165px;
+		overflow: hidden;
+		margin: 0 auto;
+		position: relative;
+		float: left;
+	}
+	
+	.new-contentarea label {
+		width: 100%;
+		height: 100%;
+		display: block;
+	}
+	
+	.new-contentarea input[type=file] {
+		width: 188px;
+		height: 60px;
+		background: #333;
+		margin: 0 auto;
+		position: absolute;
+		right: 50%;
+		margin-right: -94px;
+		top: 0;
+		right/*\**/: 0px\9;
+		margin-right/*\**/: 0px\9;
+		width/*\**/: 10px\9;
+		opacity: 0;
+		filter: alpha(opacity=0);
+		z-index: 2;
+	}
+	
+	a.upload-img {
+		width: 165px;
+		display: inline-block;
+		margin-bottom: 10px;
+		height: 37px;
+		line-height: 37px;
+		font-size: 14px;
+		color: #FFFFFF;
+		background-color: #f38e81;
+		border-radius: 3px;
+		text-decoration: none;
+		cursor: pointer;
+		border: 0px #fff solid;
+		box-shadow: 0px 0px 5px #B0B0B0;
+	}
+	
+	a.upload-img:hover {
+		background-color: #ec7e70;
+	}
+	
+	.tc {
+		text-align: center;
+	}
+    /* avator css end */
+	</style>
+</head>
+<body class="white-bg">
+	<div class="row container">
+		<div class="col-md-10">
+			<div class="imageBox">
+				<img id="avatar" th:src="(${#strings.isEmpty(user.avatar)}) ? @{/img/profile.jpg} : @{${user.avatar}}" th:onerror="'this.src=\'' + @{'/img/profile.jpg'} + '\''">
+			</div>
+			<div class="action">
+				<div class="new-contentarea tc">
+					<a href="javascript:void(0)" class="upload-img"><label for="inputImage">上传图像</label> </a>
+					<input type="file" name="avatar" id="inputImage" accept="image/*"/>
+				</div>
+				<button type="button" class="btn-custom" data-method="zoom" data-option="0.1"><i class="fa fa-search-plus"></i></button>
+				<button type="button" class="btn-custom" data-method="zoom" data-option="-0.1"><i class="fa fa-search-minus"></i></button>
+				<button type="button" class="btn-custom" data-method="rotate" data-option="-45"><i class="fa fa-rotate-left"></i></button>
+				<button type="button" class="btn-custom" data-method="rotate" data-option="45"><i class="fa fa-rotate-right"></i></button>
+				<button type="button" class="btn-custom" data-method="scaleX" data-option="-1"><i class="fa fa-arrows-h"></i></button>
+				<button type="button" class="btn-custom" data-method="scaleY" data-option="-1"><i class="fa fa-arrows-v"></i></button>
+				<button type="button" class="btn-custom" data-method="reset"><i class="fa fa-refresh"></i></button>
+			</div>
+		</div>
+		<div class="col-md-2">
+			<div class="cropped">
+				<div class="preview-box">
+					<div class="img-preview preview-xs"></div>
+				</div>
+				<div class="preview-box">
+					<div class="img-preview preview-sm"></div>
+				</div>
+				<div class="preview-box">
+					<div class="img-preview preview-md"></div>
+				</div>
+			</div>
+		</div>
+	</div>
+<th:block th:include="include :: footer" />
+<th:block th:include="include :: cropper-js" />
+<script type="text/javascript">
+var cropper;
+var croppable = false;
+$(window).on('load', function() {
+	var image = document.getElementById('avatar');
+	cropper = new Cropper(image, {
+		aspectRatio: 1,
+		viewMode: 1,
+		autoCropArea: 0.9,
+		preview: '.img-preview',
+		ready: function () {
+			croppable = true;
+		}
+	})
+
+	$('#inputImage').on('change', function() {
+		var reader = new FileReader();
+		var file = $('#inputImage')[0].files[0];
+		if (/^image\/\w+$/.test(file.type)) {
+			reader.onload = function(e) {
+				if(croppable){
+					cropper.replace(e.target.result)
+				}
+			}
+			reader.readAsDataURL(this.files[0]);
+		} else {
+			$.modal.alertWarning('请选择一个图片文件。');
+		}
+	});
+
+	$('.btn-custom').on('click',function (e) {
+		if (!croppable) {
+			$.modal.alertWarning("裁剪框加载中,请稍候...");
+			return;
+		}
+		var data = {
+			method: $(this).data('method'),
+			option: $(this).data('option') || undefined,
+		};
+		var result = cropper[data.method](data.option, data.secondOption);
+		if(['scaleX','scaleY'].indexOf(data.method) !== -1){
+			$(this).data('option', -data.option)
+		}
+	})
+});
+
+function submitHandler() {
+    if (!croppable) {
+        $.modal.alertWarning("裁剪框加载中,请稍候...");
+        return
+    }
+    cropper.getCroppedCanvas().toBlob(function(img) {
+        var formdata = new FormData();
+        formdata.append("avatarfile", img);
+        $.ajax({
+            url: ctx + "system/user/profile/updateAvatar",
+            data: formdata,
+            type: "post",
+            processData: false,
+            contentType: false,
+            success: function(result) {
+                $.operate.saveReload(result);
+            }
+        })
+    });
+}
+
+$(window).resize(function() {
+    $('.imageBox').height($(window).height() - 80);
+    $('.cropped').height($(window).height() - 40);
+}).resize();
+
+if (!HTMLCanvasElement.prototype.toBlob) {
+    Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', {
+        value: function(callback, type, quality) {
+            var canvas = this;
+            setTimeout(function() {
+                var binStr = atob(canvas.toDataURL(type, quality).split(',')[1]);
+                var len = binStr.length;
+                var arr = new Uint8Array(len);
+                for (var i = 0; i < len; i++) {
+                    arr[i] = binStr.charCodeAt(i);
+                }
+                callback(new Blob([arr], {
+                    type: type || 'image/png'
+                }));
+            });
+        }
+    });
+}
+</script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/system/user/profile/profile.html b/ruoyi-admin/src/main/resources/templates/system/user/profile/profile.html
new file mode 100644
index 0000000..761c5f0
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/system/user/profile/profile.html
@@ -0,0 +1,299 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+	<th:block th:include="include :: header('用户个人信息')" />
+    <style type="text/css">.user-info-head{position:relative;display:inline-block;}.user-info-head:hover:after{content:'\f030';position:absolute;left:0;right:0;top:0;bottom:0;color:#eee;background:rgba(0,0,0,0.5);font-family:FontAwesome;font-size:24px;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;cursor:pointer;line-height:110px;border-radius:50%;}</style>
+</head>
+
+<body class="gray-bg" style="font: 14px Helvetica Neue, Helvetica, PingFang SC, 微软雅黑, Tahoma, Arial, sans-serif !important;">
+    <input id="userId" name="userId" type="hidden" th:value="${user.userId}" />
+    <section class="section-content">
+    <div class="row">
+        <div class="col-sm-3 pr5">
+            <div class="ibox float-e-margins">
+                <div class="ibox-title ibox-title-gray dashboard-header gray-bg">
+                    <h5>个人资料</h5>
+                </div>
+                <div class="ibox-content">
+                    <div class="text-center">
+                        <p class="user-info-head" onclick="avatar()"><img class="img-circle img-lg" th:src="(${#strings.isEmpty(user.avatar)}) ? @{/img/profile.jpg} : @{${user.avatar}}" th:onerror="'this.src=\'' + @{'/img/profile.jpg'} + '\''"></p>
+                        <p><a href="javascript:avatar()">修改头像</a></p>
+                    </div>
+                    <ul class="list-group list-group-striped">
+                        <li class="list-group-item"><i class="fa fa-user"></i>
+                            <b class="font-noraml">登录名称:</b>
+                            <p class="pull-right">[[${user.loginName}]]</p>
+                        </li>
+                        <li class="list-group-item"><i class="fa fa-phone"></i>
+                            <b  class="font-noraml">手机号码:</b>
+                            <p class="pull-right">[[${user.phonenumber}]]</p>
+                        </li>
+                        <li class="list-group-item" th:if="${user.dept?.deptName != null}"><i class="fa fa-group"></i>
+                            <b  class="font-noraml">所属部门:</b>
+                            <p class="pull-right" style="overflow: hidden; white-space: nowrap; text-overflow: ellipsis;width:120px;">[[${user.dept?.deptName}]] / [[${#strings.defaultString(postGroup,'无岗位')}]]</p>
+                        </li>
+                        <li class="list-group-item"><i class="fa fa-envelope-o"></i>
+                            <b  class="font-noraml">邮箱地址:</b>
+                            <p class="pull-right" th:title="${user.email}">[[${#strings.abbreviate(user.email, 16)}]]</p>
+                        </li>
+                        <li class="list-group-item"><i class="fa fa-calendar"></i>
+                            <b  class="font-noraml">创建时间:</b>
+                            <p class="pull-right">[[${#dates.format(user.createTime, 'yyyy-MM-dd')}]]</p>
+                        </li>
+                    </ul>
+                </div>
+            </div>
+        </div>
+        
+        <div class="col-sm-9 about">
+            <div class="ibox float-e-margins">
+                <div class="ibox-title ibox-title-gray dashboard-header">
+                    <h5>基本资料</h5>
+                </div>
+                <div class="ibox-content">
+                    <div class="nav-tabs-custom">
+                        <ul class="nav nav-tabs">
+                            <li class="active"><a href="#user_info" data-toggle="tab" aria-expanded="true">基本资料</a></li>
+                            <li><a href="#modify_password" data-toggle="tab" aria-expanded="false">修改密码</a></li>
+                        </ul>
+                        <div class="tab-content">
+                            <!--用户信息-->
+                            <div class="tab-pane active" id="user_info" th:object="${user}">
+                                <form class="form-horizontal" id="form-user-edit">
+                                    <!--隐藏ID-->
+                                    <input name="id" id="id" type="hidden">
+                                    <div class="form-group">
+                                        <label class="col-sm-2 control-label">用户名称:</label>
+                                        <div class="col-sm-10">
+                                            <input type="text" class="form-control" name="userName" th:field="*{userName}" placeholder="请输入用户名称">
+                                        </div>
+                                    </div>
+                                    <div class="form-group">
+                                        <label class="col-sm-2 control-label">手机号码:</label>
+                                        <div class="col-sm-10">
+                                            <input type="text" class="form-control" name="phonenumber" maxlength="11" th:field="*{phonenumber}" placeholder="请输入手机号码">
+                                        </div>
+                                    </div>
+                                    <div class="form-group">
+                                        <label class="col-sm-2 control-label">邮箱:</label>
+                                        <div class="col-sm-10">
+                                            <input type="text" maxlength="50" class="form-control" name="email" th:field="*{email}" placeholder="请输入邮箱">
+                                        </div>
+                                    </div>
+                                    <div class="form-group">
+                                        <label class="col-sm-2 control-label">性别:</label>
+                                        <div class="col-sm-10">
+                                            <div class="radio-box">
+												<input type="radio" id="radio1" th:field="*{sex}" name="sex" value="0">
+												<label for="radio1">男</label>
+											</div>
+											<div class="radio-box">
+												<input type="radio" id="radio2" th:field="*{sex}" name="sex" value="1">
+												<label for="radio2">女</label>
+											</div>
+                                        </div>
+                                    </div>
+                                    <div class="form-group">
+                                        <div class="col-sm-offset-2 col-sm-10">
+                                            <button type="button" class="btn btn-sm btn-primary" onclick="submitUserInfo()"><i class="fa fa-check"></i>保 存</button>&nbsp;
+                                            <button type="button" class="btn btn-sm btn-danger" onclick="closeItem()"><i class="fa fa-reply-all"></i>关 闭 </button>
+                                        </div>
+                                    </div>
+                                </form>
+                            </div>
+                            
+                            <!--修改密码-->
+                            <div class="tab-pane" id="modify_password">
+                                <form class="form-horizontal" id="form-user-resetPwd">
+                                    <div class="form-group">
+                                        <label class="col-sm-2 control-label">旧密码:</label>
+                                        <div class="col-sm-10">
+                                            <input type="password" class="form-control" name="oldPassword" placeholder="请输入旧密码">
+                                        </div>
+                                    </div>
+                                    <div class="form-group">
+                                        <label class="col-sm-2 control-label">新密码:</label>
+                                        <div class="col-sm-10">
+                                            <input type="password" class="form-control" name="newPassword" id="newPassword" placeholder="请输入新密码">
+                                            <th:block th:with="chrtype=${@config.getKey('sys.account.chrtype')}"> 
+						                        <th:block th:if="${chrtype != '0'}">
+						                            <span class="help-block m-b-none">
+								                        <th:block th:if="${chrtype == '1'}"><i class="fa fa-info-circle" style="color: red;"></i>  密码只能为0-9数字 </th:block>
+								                        <th:block th:if="${chrtype == '2'}"><i class="fa fa-info-circle" style="color: red;"></i>  密码只能为a-z和A-Z字母</th:block>
+								                        <th:block th:if="${chrtype == '3'}"><i class="fa fa-info-circle" style="color: red;"></i>  密码必须包含(字母,数字)</th:block>
+								                        <th:block th:if="${chrtype == '4'}"><i class="fa fa-info-circle" style="color: red;"></i>  密码必须包含(字母,数字,特殊字符!@#$%^&*()-=_+)</th:block>
+						                            </span>
+                                                </th:block>
+						                    </th:block>
+                                        </div>
+                                    </div>
+                                    <div class="form-group">
+                                        <label class="col-sm-2 control-label">确认密码:</label>
+                                        <div class="col-sm-10">
+                                            <input type="password" class="form-control" name="confirmPassword" placeholder="请确认密码">
+                                        </div>
+                                    </div>
+                                    <div class="form-group">
+                                        <div class="col-sm-offset-2 col-sm-10">
+                                            <button type="button" class="btn btn-sm btn-primary" onclick="submitChangPassword()"><i class="fa fa-check"></i>保 存</button>&nbsp;
+                                            <button type="button" class="btn btn-sm btn-danger" onclick="closeItem()"><i class="fa fa-reply-all"></i>关 闭 </button>
+                                        </div>
+                                    </div>
+                                </form>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+	</section>
+    
+    <th:block th:include="include :: footer" />
+    <script>
+	    /*用户管理-头像*/
+	    function avatar() {
+	        var url = ctx + 'system/user/profile/avatar';
+	        top.layer.open({
+        		type: 2,
+        		area: [$(window).width() + 'px', $(window).height() + 'px'],
+        		fix: false,
+        		//不固定
+        		maxmin: true,
+        		shade: 0.3,
+        		title: "修改头像",
+        		content: url,
+        		btn: ['确定', '关闭'],
+        	    // 弹层外区域关闭
+        		shadeClose: true,
+        		yes: function(index, layero) {
+                    var iframeWin = layero.find('iframe')[0];
+                    iframeWin.contentWindow.submitHandler(index, layero);
+                },
+        	    cancel: function(index) {
+        	        return true;
+        	    }
+        	});
+	    }
+
+	    /*用户信息-修改*/
+	    $("#form-user-edit").validate({
+			onkeyup: false,
+			rules:{
+				userName:{
+					required:true,
+				},
+				email:{
+					required:true,
+		            email:true,
+		            remote: {
+		                url: ctx + "system/user/checkEmailUnique",
+		                type: "post",
+		                dataType: "json",
+		                data: {
+		                	"userId": function() {
+		                        return $("#userId").val();
+		                    },
+		        			"email": function() {
+		                        return $.common.trim($("#email").val());
+		                    }
+		                }
+		            }
+				},
+				phonenumber:{
+					required:true,
+					isPhone:true,
+		            remote: {
+		                url: ctx + "system/user/checkPhoneUnique",
+		                type: "post",
+		                dataType: "json",
+		                data: {
+		                	"userId": function() {
+		                		return $("#userId").val();
+		                    },
+		        			"phonenumber": function() {
+		                        return $.common.trim($("#phonenumber").val());
+		                    }
+		                }
+		            }
+				},
+			},
+			messages: {
+				"userName": {
+	                required: "请输入用户名称",
+	            },
+				"email": {
+					required: "请输入邮箱",
+		            remote: "Email已经存在"
+		        },
+				"phonenumber":{
+					required: "请输入手机号码",
+		        	remote: "手机号码已经存在"
+				}
+		    },
+		    focusCleanup: true
+		});
+		
+		function submitUserInfo() {
+	        if ($.validate.form()) {
+	        	$.operate.saveModal(ctx + "system/user/profile/update", $('#form-user-edit').serialize());
+	        }
+	    }
+	    
+	    /*用户管理-修改密码*/
+	    $("#form-user-resetPwd").validate({
+	    	onkeyup: false,
+			rules:{
+				oldPassword:{
+					required:true,
+					remote: {
+	                    url: ctx + "system/user/profile/checkPassword",
+	                    type: "get",
+	                    dataType: "json",
+	                    data: {
+	                        password: function() {
+	                            return $("input[name='oldPassword']").val();
+	                        }
+	                    }
+	                }
+				},
+				newPassword: {
+	                required: true,
+	                minlength: 6,
+	                maxlength: 20,
+	                specialSign: true
+	            },
+	            confirmPassword: {
+	                required: true,
+	                equalTo: "#newPassword"
+	            }
+			},
+			messages: {
+	            oldPassword: {
+	                required: "请输入原密码",
+	                remote: "原密码错误"
+	            },
+	            newPassword: {
+	                required: "请输入新密码",
+	                minlength: "密码不能小于6个字符",
+	                maxlength: "密码不能大于20个字符"
+	            },
+	            confirmPassword: {
+	                required: "请再次输入新密码",
+	                equalTo: "两次密码输入不一致"
+	            }
+
+	        },
+	        focusCleanup: true
+		});
+		
+		function submitChangPassword () {
+			var chrtype = [[${#strings.defaultString(@config.getKey('sys.account.chrtype'), 0)}]];
+			var password = $("#newPassword").val();
+	        if ($.validate.form("form-user-resetPwd") && checkpwd(chrtype, password)) {
+	        	$.operate.saveModal(ctx + "system/user/profile/resetPwd", $('#form-user-resetPwd').serialize());
+	        }
+	    }
+	</script>
+</body>
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/system/user/profile/resetPwd.html b/ruoyi-admin/src/main/resources/templates/system/user/profile/resetPwd.html
new file mode 100644
index 0000000..3987ee0
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/system/user/profile/resetPwd.html
@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+    <th:block th:include="include :: header('修改用户密码')" />
+</head>
+<body class="white-bg">
+    <div class="wrapper wrapper-content animated fadeInRight ibox-content">
+        <form class="form-horizontal m" id="form-user-resetPwd">
+            <input name="userId"  type="hidden"  th:value="${user.userId}" />
+            <div class="form-group">
+                <label class="col-sm-3 control-label">登录名称:</label>
+                <div class="col-sm-8">
+                    <input class="form-control" type="text" readonly="true" name="loginName" th:value="${user.loginName}"/>
+                </div>
+            </div>
+            <div class="form-group">
+                <label class="col-sm-3 control-label">旧密码:</label>
+                <div class="col-sm-8">
+                    <input class="form-control" type="password" name="oldPassword" id="oldPassword">
+                </div>
+            </div>
+            <div class="form-group">
+                <label class="col-sm-3 control-label">新密码:</label>
+                <div class="col-sm-8">
+                    <input class="form-control" type="password" name="newPassword" id="newPassword">
+                    <th:block th:with="chrtype=${@config.getKey('sys.account.chrtype')}"> 
+                        <th:block th:if="${chrtype != '0'}">
+                            <span class="help-block m-b-none">
+                                <th:block th:if="${chrtype == '1'}"><i class="fa fa-info-circle" style="color: red;"></i>  密码只能为0-9数字 </th:block>
+                                <th:block th:if="${chrtype == '2'}"><i class="fa fa-info-circle" style="color: red;"></i>  密码只能为a-z和A-Z字母</th:block>
+                                <th:block th:if="${chrtype == '3'}"><i class="fa fa-info-circle" style="color: red;"></i>  密码必须包含(字母,数字)</th:block>
+                                <th:block th:if="${chrtype == '4'}"><i class="fa fa-info-circle" style="color: red;"></i>  密码必须包含(字母,数字,特殊字符!@#$%^&*()-=_+)</th:block>
+                            </span>
+                        </th:block>
+                    </th:block>
+                </div>
+            </div>
+            <div class="form-group">
+                <label class="col-sm-3 control-label">再次确认:</label>
+                <div class="col-sm-8">
+                    <input class="form-control" type="password" name="confirmPassword" id="confirmPassword">
+                    <span class="help-block m-b-none"><i class="fa fa-info-circle"></i> 请再次输入您的密码</span>
+                </div>
+            </div>
+        </form>
+    </div>
+    <th:block th:include="include :: footer" />
+
+    <script>
+        $("#form-user-resetPwd").validate({
+            rules:{
+                oldPassword:{
+                    required:true,
+                    remote: {
+                        url: ctx + "system/user/profile/checkPassword",
+                        type: "get",
+                        dataType: "json",
+                        data: {
+                            password: function() {
+                                return $("input[name='oldPassword']").val();
+                            }
+                        }
+                    }
+                },
+                newPassword: {
+                    required: true,
+                    minlength: 5,
+                    maxlength: 20,
+                    specialSign: true
+                },
+                confirmPassword: {
+                    required: true,
+                    equalTo: "#newPassword"
+                }
+            },
+            messages: {
+                oldPassword: {
+                    required: "请输入原密码",
+                    remote: "原密码错误"
+                },
+                newPassword: {
+                    required: "请输入新密码",
+                    minlength: "密码不能小于5个字符",
+                    maxlength: "密码不能大于20个字符"
+                },
+                confirmPassword: {
+                    required: "请再次输入新密码",
+                    equalTo: "两次密码输入不一致"
+                }
+
+            },
+            focusCleanup: true
+        });
+        
+        function submitHandler() {
+            var chrtype = [[${#strings.defaultString(@config.getKey('sys.account.chrtype'), 0)}]];
+            var password = $("#newPassword").val();
+            if ($.validate.form() && checkpwd(chrtype, password)) {
+                $.operate.save(ctx + "system/user/profile/resetPwd", $('#form-user-resetPwd').serialize());
+            }
+        }
+    </script>
+</body>
+
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/system/user/resetPwd.html b/ruoyi-admin/src/main/resources/templates/system/user/resetPwd.html
new file mode 100644
index 0000000..49639f7
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/system/user/resetPwd.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+	<th:block th:include="include :: header('修改密码')" />
+</head>
+<body class="white-bg">
+	<div class="wrapper wrapper-content animated fadeInRight ibox-content">
+		<form class="form-horizontal m" id="form-user-resetPwd">
+			<input name="userId"  type="hidden"  th:value="${user.userId}" />
+			<div class="form-group">
+				<label class="col-sm-3 control-label">登录名称:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" readonly="true" name="loginName" th:value="${user.loginName}"/>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">输入密码:</label>
+				<div class="col-sm-8">
+					<div class="input-group">
+                        <input class="form-control" type="password" name="password" id="password" placeholder="请输入重置密码" th:value="${@config.getKey('sys.user.initPassword')}">
+                        <span class="input-group-addon" title="重置密码,鼠标按下显示密码"
+                            onmousedown="$('#password').attr('type','text')"
+                            onmouseup="$('#password').attr('type','password')"><i class="fa fa-key"></i></span>
+                    </div>
+				</div>
+			</div>
+		</form>
+	</div>
+	<th:block th:include="include :: footer" />
+	<script type="text/javascript">
+		$("#form-user-resetPwd").validate({
+			rules:{
+				password:{
+					required: true,
+					minlength: 5,
+					maxlength: 20,
+					specialSign: true
+				},
+			},
+			focusCleanup: true
+		});
+		
+		function submitHandler() {
+	        if ($.validate.form()) {
+	        	$.operate.save(ctx + "system/user/resetPwd", $('#form-user-resetPwd').serialize());
+	        }
+	    }
+	</script>
+</body>
+
+</html>
diff --git a/ruoyi-admin/src/main/resources/templates/system/user/user.html b/ruoyi-admin/src/main/resources/templates/system/user/user.html
new file mode 100644
index 0000000..014325d
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/system/user/user.html
@@ -0,0 +1,296 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('用户列表')" />
+	<th:block th:include="include :: layout-latest-css" />
+	<th:block th:include="include :: ztree-css" />
+</head>
+<body class="gray-bg">
+	<div class="ui-layout-west">
+		<div class="box box-main">
+			<div class="box-header">
+				<div class="box-title">
+					<i class="fa fa-sitemap"></i> 组织机构
+				</div>
+				<div class="box-tools pull-right">
+				    <a type="button" class="btn btn-box-tool" href="javascript:void(0)" onclick="dept()" title="管理部门"><i class="fa fa-edit"></i></a>
+					<button type="button" class="btn btn-box-tool" id="btnExpand" title="展开" style="display:none;"><i class="fa fa-chevron-up"></i></button>
+					<button type="button" class="btn btn-box-tool" id="btnCollapse" title="折叠"><i class="fa fa-chevron-down"></i></button>
+					<button type="button" class="btn btn-box-tool" id="btnRefresh" title="刷新部门"><i class="fa fa-refresh"></i></button>
+				</div>
+			</div>
+			<div class="ui-layout-content">
+				<div id="tree" class="ztree"></div>
+			</div>
+		</div>
+	</div>
+	
+	<div class="ui-layout-center">
+		<div class="container-div">
+			<div class="row">
+				<div class="col-sm-12 search-collapse">
+					<form id="user-form">
+						<input type="hidden" id="deptId" name="deptId">
+		                <input type="hidden" id="parentId" name="parentId">
+						<div class="select-list">
+							<ul>
+								<li>
+									登录名称:<input type="text" name="loginName"/>
+								</li>
+								<li>
+									手机号码:<input type="text" name="phonenumber"/>
+								</li>
+								<li>
+									用户状态:<select name="status" th:with="type=${@dict.getType('sys_normal_disable')}">
+										<option value="">所有</option>
+										<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
+									</select>
+								</li>
+								<li class="select-time">
+									<label>创建时间: </label>
+									<input type="text" class="time-input" id="startTime" placeholder="开始时间" name="params[beginTime]"/>
+									<span>-</span>
+									<input type="text" class="time-input" id="endTime" placeholder="结束时间" name="params[endTime]"/>
+								</li>
+								<li>
+									<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
+								    <a class="btn btn-warning btn-rounded btn-sm" onclick="resetPre()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
+								</li>
+							</ul>
+						</div>
+					</form>
+				</div>
+				
+		        <div class="btn-group-sm" id="toolbar" role="group">
+		        	<a class="btn btn-success" onclick="$.operate.addTab()" shiro:hasPermission="system:user:add">
+		                <i class="fa fa-plus"></i> 新增
+		            </a>
+		             <a class="btn btn-primary single disabled" onclick="$.operate.editTab()" shiro:hasPermission="system:user:edit">
+			            <i class="fa fa-edit"></i> 修改
+			        </a>
+		            <a class="btn btn-danger multiple disabled" onclick="$.operate.removeAll()" shiro:hasPermission="system:user:remove">
+		                <i class="fa fa-remove"></i> 删除
+		            </a>
+		            <a class="btn btn-info" onclick="$.table.importExcel()" shiro:hasPermission="system:user:import">
+			            <i class="fa fa-upload"></i> 导入
+			        </a>
+		            <a class="btn btn-warning" onclick="$.table.exportExcel()" shiro:hasPermission="system:user:export">
+			            <i class="fa fa-download"></i> 导出
+			        </a>
+		        </div>
+		        
+		        <div class="col-sm-12 select-table table-striped">
+				    <table id="bootstrap-table"></table>
+				</div>
+			</div>
+		</div>
+	</div>
+	
+	<th:block th:include="include :: footer" />
+	<th:block th:include="include :: layout-latest-js" />
+	<th:block th:include="include :: ztree-js" />
+	<script th:inline="javascript">
+		var editFlag = [[${@permission.hasPermi('system:user:edit')}]];
+		var removeFlag = [[${@permission.hasPermi('system:user:remove')}]];
+		var resetPwdFlag = [[${@permission.hasPermi('system:user:resetPwd')}]];
+		var prefix = ctx + "system/user";
+
+		$(function() {
+		    var panehHidden = false;
+		    if ($(this).width() < 769) {
+		        panehHidden = true;
+		    }
+		    $('body').layout({ initClosed: panehHidden, west__size: 185, resizeWithWindow: false });
+	     	// 回到顶部绑定
+	    	if ($.fn.toTop !== undefined) {
+	    		var opt = {
+	    			win:$('.ui-layout-center'),
+	    			doc:$('.ui-layout-center')
+	    		};
+	    		$('#scroll-up').toTop(opt);
+	    	}
+		    queryUserList();
+		    queryDeptTree();
+		});
+
+		function queryUserList() {
+		    var options = {
+		        url: prefix + "/list",
+		        viewUrl: prefix + "/view/{id}",
+		        createUrl: prefix + "/add",
+		        updateUrl: prefix + "/edit/{id}",
+		        removeUrl: prefix + "/remove",
+		        exportUrl: prefix + "/export",
+		        importUrl: prefix + "/importData",
+		        importTemplateUrl: prefix + "/importTemplate",
+		        sortName: "createTime",
+		        sortOrder: "desc",
+		        modalName: "用户",
+		        columns: [{
+		            checkbox: true
+		        },
+		        {
+		            field: 'userId',
+		            title: '用户ID'
+		        },
+		        {
+		            field: 'loginName',
+		            title: '登录名称',
+		            sortable: true,
+		            formatter: function (value, row, index) {
+		                return '<a href="javascript:void(0)" onclick="$.operate.view(\'' + row.userId + '\')">' + value + '</a>';
+		            }
+		        },
+		        {
+		            field: 'userName',
+		            title: '用户名称'
+		        },
+		        {
+		            field: 'dept.deptName',
+		            title: '部门'
+		        },
+		        {
+		            field: 'email',
+		            title: '邮箱',
+		            visible: false
+		        },
+		        {
+		            field: 'phonenumber',
+		            title: '手机'
+		        },
+		        {
+		        	visible: editFlag == 'hidden' ? false : true,
+		        	title: '用户状态',
+		        	align: 'center',
+		        	formatter: function (value, row, index) {
+		        		return statusTools(row);
+		        	}
+		        },
+		        {
+		            field: 'createTime',
+		            title: '创建时间',
+		            sortable: true
+		        },
+		        {
+		            title: '操作',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		                if (row.userId != 1) {
+		                	var actions = [];
+			                actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.editTab(\'' + row.userId + '\')"><i class="fa fa-edit"></i>编辑</a> ');
+			                actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.userId + '\')"><i class="fa fa-remove"></i>删除</a> ');
+			                var more = [];
+			                more.push("<a class='btn btn-default btn-xs " + resetPwdFlag + "' href='javascript:void(0)' onclick='resetPwd(" + row.userId + ")'><i class='fa fa-key'></i>重置密码</a> ");
+			                more.push("<a class='btn btn-default btn-xs " + editFlag + "' href='javascript:void(0)' onclick='authRole(" + row.userId + ")'><i class='fa fa-check-square-o'></i>分配角色</a>");
+			                actions.push('<a tabindex="0" class="btn btn-info btn-xs" role="button" data-container="body" data-placement="left" data-toggle="popover" data-html="true" data-trigger="hover" data-content="' + more.join('') + '"><i class="fa fa-chevron-circle-right"></i>更多操作</a>');
+			                return actions.join('');
+		            	} else {
+		                    return "";
+		                }
+		            }
+		        }]
+		    };
+		    $.table.init(options);
+		}
+		
+		function queryDeptTree()
+		{
+			var url = ctx + "system/user/deptTreeData";
+			var options = {
+		        url: url,
+		        expandLevel: 2,
+		        onClick : zOnClick
+		    };
+			$.tree.init(options);
+			
+			function zOnClick(event, treeId, treeNode) {
+				$("#deptId").val(treeNode.id);
+				$("#parentId").val(treeNode.pId);
+				$.table.search();
+			}
+		}
+		
+		$('#btnExpand').click(function() {
+			$._tree.expandAll(true);
+		    $(this).hide();
+		    $('#btnCollapse').show();
+		});
+		
+		$('#btnCollapse').click(function() {
+			$._tree.expandAll(false);
+		    $(this).hide();
+		    $('#btnExpand').show();
+		});
+		
+		$('#btnRefresh').click(function() {
+			queryDeptTree();
+		});
+		
+		/* 自定义重置-表单重置/隐藏框/树节点选择色/搜索 */
+		function resetPre() {
+			resetDate();
+			$("#user-form")[0].reset();
+			$("#deptId").val("");
+			$("#parentId").val("");
+			$(".curSelectedNode").removeClass("curSelectedNode");
+			$.table.search();
+		}
+
+		/* 用户管理-部门 */
+		function dept() {
+			var url = ctx + "system/dept";
+			$.modal.openTab("部门管理", url);
+		}
+
+		/* 用户管理-重置密码 */
+		function resetPwd(userId) {
+		    var url = prefix + '/resetPwd/' + userId;
+		    $.modal.open("重置密码", url, '800', '300');
+		}
+		
+		/* 用户管理-分配角色 */
+		function authRole(userId) {
+		    var url = prefix + '/authRole/' + userId;
+		    $.modal.openTab("用户分配角色", url);
+		}
+		
+		/* 用户状态显示 */
+		function statusTools(row) {
+		    if (row.status == 1) {
+    			return '<i class=\"fa fa-toggle-off text-info fa-2x\" onclick="enable(\'' + row.userId + '\')"></i> ';
+    		} else {
+    			return '<i class=\"fa fa-toggle-on text-info fa-2x\" onclick="disable(\'' + row.userId + '\')"></i> ';
+    		}
+		}
+		
+		/* 用户管理-停用 */
+		function disable(userId) {
+			$.modal.confirm("确认要停用用户吗?", function() {
+				$.operate.post(prefix + "/changeStatus", { "userId": userId, "status": 1 });
+		    })
+		}
+
+		/* 用户管理启用 */
+		function enable(userId) {
+			$.modal.confirm("确认要启用用户吗?", function() {
+				$.operate.post(prefix + "/changeStatus", { "userId": userId, "status": 0 });
+		    })
+		}
+	</script>
+</body>
+<!-- 导入区域 -->
+<script id="importTpl" type="text/template">
+<form enctype="multipart/form-data" class="mt20 mb10">
+	<div class="col-xs-offset-1">
+		<input type="file" id="file" name="file"/>
+		<div class="mt10 pt5">
+			<input type="checkbox" id="updateSupport" name="updateSupport" title="如果登录账户已经存在,更新这条数据。"> 是否更新已经存在的用户数据
+			 &nbsp;	<a onclick="$.table.importTemplate()" class="btn btn-default btn-xs"><i class="fa fa-file-excel-o"></i> 下载模板</a>
+		</div>
+		<font color="red" class="pull-left mt10">
+			提示:仅允许导入“xls”或“xlsx”格式文件!
+		</font>
+	</div>
+</form>
+</script>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/system/user/view.html b/ruoyi-admin/src/main/resources/templates/system/user/view.html
new file mode 100644
index 0000000..d3d1771
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/system/user/view.html
@@ -0,0 +1,161 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+    <th:block th:include="include :: header('用户详细')" />
+</head>
+<body>
+    <div class="main-content">
+        <form class="form-horizontal" th:object="${user}">
+            <h4 class="form-header h4">基本信息</h4>
+            <div class="row">
+            	<div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label">用户名称:</label>
+                        <div class="col-sm-8">
+                            <p class="form-control-plaintext" th:text="*{userName}"></p>
+                        </div>
+                    </div>
+                </div>
+                <div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label">归属部门:</label>
+                        <div class="col-sm-8">
+                            <p class="form-control-plaintext" th:text="*{dept.deptName}"></p>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="row">
+                <div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label">手机号码:</label>
+                        <div class="col-sm-8">
+                            <p class="form-control-plaintext" th:text="*{phonenumber}"></p>
+                        </div>
+                    </div>
+                </div>
+                <div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label">邮箱:</label>
+                        <div class="col-sm-8">
+                            <p class="form-control-plaintext" th:text="*{email}"></p>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="row">
+                <div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label">登录账号:</label>
+                        <div class="col-sm-8">
+                            <p class="form-control-plaintext" th:text="*{loginName}"></p>
+                        </div>
+                    </div>
+                </div>
+                <div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label">用户状态:</label>
+                        <div class="col-sm-8">
+                            <p class="form-control-plaintext" th:text="*{status == '0' ? '正常' : '停用'}"></p>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="row">
+                <div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label">岗位:</label>
+                        <div class="col-sm-8">
+                            <p class="form-control-plaintext">[[${#strings.defaultString(postGroup, '无岗位')}]]</p>
+                        </div>
+                    </div>
+                </div>
+                <div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label">用户性别:</label>
+                        <div class="col-sm-8">
+                            <p class="form-control-plaintext" th:text="*{@dict.getLabel('sys_user_sex', sex)}"></p>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="row">
+            	<div class="col-sm-12">
+                    <div class="form-group">
+                        <label class="col-xs-2 control-label">角色:</label>
+                        <div class="col-xs-10">
+                            <p class="form-control-plaintext">[[${#strings.defaultString(roleGroup, '无角色')}]]</p>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <h4 class="form-header h4">其他信息</h4>
+            <div class="row">
+                <div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label">创建者:</label>
+                        <div class="col-sm-8">
+                            <p class="form-control-plaintext" th:text="*{createBy}"></p>
+                        </div>
+                    </div>
+                </div>
+                <div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label">创建时间:</label>
+                        <div class="col-sm-8">
+                            <p class="form-control-plaintext" th:text="*{#dates.format(createTime, 'yyyy-MM-dd HH:mm:ss')}"></p>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="row">
+                <div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label">更新者:</label>
+                        <div class="col-sm-8">
+                            <p class="form-control-plaintext" th:text="*{updateBy}"></p>
+                        </div>
+                    </div>
+                </div>
+                <div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label">更新时间:</label>
+                        <div class="col-sm-8">
+                            <p class="form-control-plaintext" th:text="*{#dates.format(updateTime, 'yyyy-MM-dd HH:mm:ss')}"></p>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="row">
+                <div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label">最后登录IP:</label>
+                        <div class="col-sm-8">
+                            <p class="form-control-plaintext" th:text="*{loginIp}"></p>
+                        </div>
+                    </div>
+                </div>
+                <div class="col-sm-6">
+                    <div class="form-group">
+                        <label class="col-sm-4 control-label">最后登录时间:</label>
+                        <div class="col-sm-8">
+                            <p class="form-control-plaintext" th:text="*{#dates.format(loginDate, 'yyyy-MM-dd HH:mm:ss')}"></p>
+                        </div>
+                    </div>
+                </div>
+            </div>
+	        <div class="row">
+                <div class="col-sm-12">
+                    <div class="form-group">
+                        <label class="col-xs-2 control-label">备注:</label>
+                        <div class="col-xs-10">
+                            <p class="form-control-plaintext" th:text="*{remark}"></p>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </form>
+    </div>
+	<th:block th:include="include :: footer" />
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/templates/tool/build/build.html b/ruoyi-admin/src/main/resources/templates/tool/build/build.html
new file mode 100644
index 0000000..8e4321d
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/templates/tool/build/build.html
@@ -0,0 +1,168 @@
+<!DOCTYPE html>
+<html lang="zh">
+<head>
+	<th:block th:include="include :: header('表单构建器')" />
+	<th:block th:include="include :: datetimepicker-css" />
+</head>
+<style>
+    .droppable-active{background-color:#ffe!important}.tools a{cursor:pointer;font-size:80%}.form-body .col-md-6,.form-body .col-md-12{min-height:400px}.draggable{cursor:move}
+</style>
+<body class="gray-bg">
+    <div class="wrapper wrapper-content">
+        <div class="row">
+            <div class="col-sm-5">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>元素</h5>
+                        <div class="ibox-tools">
+                            <a class="collapse-link">
+                                <i class="fa fa-chevron-up"></i>
+                            </a>
+                            <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:;">
+                                <i class="fa fa-wrench"></i>
+                            </a>
+                            <ul class="dropdown-menu dropdown-user">
+                                <li><a href="javascript:;">基本</a>
+                                </li>
+                                <li><a href="javascript:;">其他</a>
+                                </li>
+                            </ul>
+                            <a class="close-link">
+                                <i class="fa fa-times"></i>
+                            </a>
+                        </div>
+                    </div>
+                    <div class="ibox-content">
+                        <div class="alert alert-info">
+                           	 拖拽左侧的表单元素到右侧区域,即可生成相应的HTML代码,表单代码,轻松搞定!
+                        </div>
+                        <form role="form" class="form-horizontal m-t">
+                            <div class="form-group draggable">
+                                <label class="col-sm-3 control-label">文本框:</label>
+                                <div class="col-sm-9">
+                                    <input type="text" name="" class="form-control" placeholder="请输入文本">
+                                </div>
+                            </div>
+
+                            <div class="form-group draggable">
+                                <label class="col-sm-3 control-label">多行文本框:</label>
+                                <div class="col-sm-9">
+                                    <textarea type="text" name="" class="form-control" placeholder="请输入文本"></textarea>
+                                </div>
+                            </div>
+
+                            <div class="form-group draggable">
+                                <label class="col-sm-3 control-label">密码框:</label>
+                                <div class="col-sm-9">
+                                    <input type="password" class="form-control" name="password" placeholder="请输入密码">
+                                </div>
+                            </div>
+                            <div class="form-group draggable">
+                                <label class="col-sm-3 control-label">下拉框:</label>
+                                <div class="col-sm-9">
+                                    <select class="form-control" name="">
+                                        <option>选项 1</option>
+                                        <option>选项 2</option>
+                                        <option>选项 3</option>
+                                        <option>选项 4</option>
+                                    </select>
+                                </div>
+                            </div>
+                            <div class="form-group draggable">
+                                <label class="col-sm-3 control-label">纯文本:</label>
+
+                                <div class="col-sm-9">
+                                    <p class="form-control-static">这里是纯文字信息</p>
+                                </div>
+                            </div>
+                            <div class="form-group draggable">
+                                <label class="col-sm-3 control-label">单选框:
+                                </label>
+
+                                <div class="col-sm-9">
+                                    <label class="radio-box"><input type="radio" checked="" value="option1" id="optionsRadios1" name="optionsRadios">选项1</label>
+                                    <label class="radio-box"><input type="radio" value="option2" id="optionsRadios2" name="optionsRadios">选项2</label>
+                                </div>
+                            </div>
+                            <div class="form-group draggable">
+                                <label class="col-sm-3 control-label">复选框:</label>
+
+                                <div class="col-sm-9">
+                                    <label class="check-box">
+                                        <input type="checkbox" value="option1" id="inlineCheckbox1">选项1</label>
+                                    <label class="check-box">
+                                        <input type="checkbox" value="option2" id="inlineCheckbox2">选项2</label>
+                                    <label class="check-box">
+                                        <input type="checkbox" value="option3" id="inlineCheckbox3">选项3</label>
+                                </div>
+                            </div>
+                            <div class="form-group draggable">
+                                <label class="col-sm-3 control-label">切换按钮:
+                                </label>
+
+                                <div class="col-sm-9">
+                                    <label class="toggle-switch switch-solid">
+			                            <input type="checkbox" id="status" checked>
+			                            <span></span>
+			                        </label>
+                                </div>
+                            </div>
+                            <div class="form-group draggable">
+                                <label class="col-sm-3 control-label">日期选择:</label>
+
+                                <div class="col-sm-9">
+		                            <div class="input-group date">
+		                                <span class="input-group-addon"><i class="fa fa-calendar"></i></span>
+		                                <input type="text" class="form-control" value="2018-04-20">
+		                            </div>
+                                </div>
+                            </div>
+                            <div class="hr-line-dashed"></div>
+                            <div class="form-group draggable">
+                                <div class="col-sm-12 col-sm-offset-3">
+									<button type="submit" class="btn btn-primary">提交</button>
+									<button onclick="$.modal.close()" class="btn btn-danger" type="button">关闭</button>
+                                </div>
+                            </div>
+                        </form>
+                        <div class="clearfix"></div>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-7">
+                <div class="ibox float-e-margins">
+                    <div class="ibox-title">
+                        <h5>拖拽左侧表单元素到此区域</h5>
+                        <div class="ibox-tools">
+                           	 请选择显示的列数:
+                            <select id="n-columns">
+                                <option value="1">显示1列</option>
+                                <option value="2">显示2列</option>
+                            </select>
+                        </div>
+                    </div>
+
+                    <div class="ibox-content">
+                        <div class="row form-body form-horizontal m-t">
+                            <div class="col-md-12 droppable sortable">
+                            </div>
+                            <div class="col-md-6 droppable sortable" style="display: none;">
+                            </div>
+                            <div class="col-md-6 droppable sortable" style="display: none;">
+                            </div>
+                        </div>
+                        <button type="submit" class="btn btn-warning" data-clipboard-text="testing" id="copy-to-clipboard">复制代码</button>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+   <th:block th:include="include :: footer" />
+   <script th:src="@{/js/jquery-ui-1.10.4.min.js}"></script>
+   <th:block th:include="include :: datetimepicker-js" />
+   <script th:src="@{/ajax/libs/beautifyhtml/beautifyhtml.js}"></script>
+   <script type="text/javascript">
+       $(document).ready(function(){setup_draggable();$("#n-columns").on("change",function(){var v=$(this).val();if(v==="1"){var $col=$(".form-body .col-md-12").toggle(true);$(".form-body .col-md-6 .draggable").each(function(i,el){$(this).remove().appendTo($col)});$(".form-body .col-md-6").toggle(false)}else{var $col=$(".form-body .col-md-6").toggle(true);$(".form-body .col-md-12 .draggable").each(function(i,el){$(this).remove().appendTo(i%2?$col[1]:$col[0])});$(".form-body .col-md-12").toggle(false)}});$("#copy-to-clipboard").on("click",function(){var $copy=$(".form-body").clone().appendTo(document.body);$copy.find(".tools, :hidden").remove();$.each(["draggable","droppable","sortable","dropped","ui-sortable","ui-draggable","ui-droppable","form-body"],function(i,c){$copy.find("."+c).removeClass(c).removeAttr("style")});var html=html_beautify($copy.html());$copy.remove();$modal=get_modal(html).modal("show");$modal.find(".btn").remove();$modal.find(".modal-title").html("复制HTML代码");$modal.find(":input:first").select().focus();return false})});var setup_draggable=function(){$(".draggable").draggable({appendTo:"body",helper:"clone"});$(".droppable").droppable({accept:".draggable",helper:"clone",hoverClass:"droppable-active",drop:function(event,ui){$(".empty-form").remove();var $orig=$(ui.draggable);if(!$(ui.draggable).hasClass("dropped")){var $el=$orig.clone().addClass("dropped").css({"position":"static","left":null,"right":null}).appendTo(this);if($el.find("label").hasClass("radio-box")){$el=$el.html('<label class="col-sm-3 control-label">单选框:</label>'+'<div class="col-sm-9">'+'<label class="radio-box"><input type="radio" checked="" value="option1" id="optionsRadios1" name="optionsRadios">选项1</label>'+'<label class="radio-box"><input type="radio" value="option2" id="optionsRadios2" name="optionsRadios">选项2</label>'+"</div>")}else{if($el.find("label").hasClass("check-box")){$el=$el.html('<label class="col-sm-3 control-label">复选框:</label>'+'<div class="col-sm-9">'+'<label class="check-box">'+'<input type="checkbox" value="option1" id="inlineCheckbox1">选项1</label>'+'<label class="check-box">'+'<input type="checkbox" value="option2" id="inlineCheckbox2">选项2</label>'+'<label class="check-box">'+'<input type="checkbox" value="option3" id="inlineCheckbox3">选项3</label>'+"</div>")}}var id=$orig.find(":input").attr("id");if(id){id=id.split("-").slice(0,-1).join("-")+"-"+(parseInt(id.split("-").slice(-1)[0])+1);$orig.find(":input").attr("id",id);$orig.find("label").attr("for",id)}$('<p class="tools col-sm-12 col-sm-offset-3">						<a class="edit-link">编辑HTML<a> | 						<a class="remove-link">移除</a></p>').appendTo($el)}else{if($(this)[0]!=$orig.parent()[0]){var $el=$orig.clone().css({"position":"static","left":null,"right":null}).appendTo(this);$orig.remove()}}}}).sortable()};var get_modal=function(content){var modal=$('<div class="modal" style="overflow: auto;" tabindex="-1">	<div class="modal-dialog"><div class="modal-content"><div class="modal-header"><a type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</a><h4 class="modal-title">编辑HTML</h4></div><div class="modal-body ui-front">	<textarea class="form-control textarea-show-src"  style="min-height: 200px; margin-bottom: 10px;font-family: Monaco, Fixed"></textarea><button class="btn btn-success">更新HTML</button></div></div></div></div>').appendTo(document.body);var doms=document.getElementsByClassName("textarea-show-src");for(var i=0;i<doms.length;i++){doms.item(i).innerHTML=content}return modal};$(document).on("click",".edit-link",function(ev){var $el=$(this).parent().parent();var $el_copy=$el.clone();var $edit_btn=$el_copy.find(".edit-link").parent().remove();var $modal=get_modal(html_beautify($el_copy.html())).modal("show");$modal.find(":input:first").focus();$modal.find(".btn-success").click(function(ev2){var html=$modal.find("textarea").val();if(!html){$el.remove()}else{$el.html(html);$edit_btn.appendTo($el)}$modal.modal("hide");return false})});$(document).on("click",".remove-link",function(ev){$(this).parent().parent().remove()});$(".input-group.date").datetimepicker({format:"yyyy-mm-dd",minView:"month",autoclose:true});
+    </script>
+</body>
+</html>
diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml
new file mode 100644
index 0000000..53598e8
--- /dev/null
+++ b/ruoyi-common/pom.xml
@@ -0,0 +1,100 @@
+<?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>ruoyi</artifactId>
+        <groupId>com.ruoyi</groupId>
+        <version>4.8.0</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>ruoyi-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>
+
+        <!--Shiro核心框架 -->
+        <dependency>
+            <groupId>org.apache.shiro</groupId>
+            <artifactId>shiro-core</artifactId>
+        </dependency>
+        
+        <!-- Shiro使用EhCache缓存框架 -->
+        <dependency>
+            <groupId>org.apache.shiro</groupId>
+            <artifactId>shiro-ehcache</artifactId>
+        </dependency>
+
+        <!-- pagehelper 分页插件 -->
+        <dependency>
+            <groupId>com.github.pagehelper</groupId>
+            <artifactId>pagehelper-spring-boot-starter</artifactId>
+        </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>
+
+        <!-- 阿里JSON解析器 -->
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</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解析器 -->
+        <dependency>
+            <groupId>org.yaml</groupId>
+            <artifactId>snakeyaml</artifactId>
+        </dependency>
+
+        <!-- servlet包 -->
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>javax.servlet-api</artifactId>
+        </dependency>
+
+    </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Anonymous.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Anonymous.java
new file mode 100644
index 0000000..1d6d4f4
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Anonymous.java
@@ -0,0 +1,19 @@
+package com.ruoyi.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 ruoyi
+ */
+@Target({ ElementType.METHOD, ElementType.TYPE })
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface Anonymous
+{
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java
new file mode 100644
index 0000000..bafce5b
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java
@@ -0,0 +1,33 @@
+package com.ruoyi.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 ruoyi
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface DataScope
+{
+    /**
+     * 部门表的别名
+     */
+    public String deptAlias() default "";
+
+    /**
+     * 用户表的别名
+     */
+    public String userAlias() default "";
+
+    /**
+     * 权限字符(用于多个角色匹配符合要求的权限)默认根据权限注解@RequiresPermissions获取,多个权限用逗号分隔开来
+     */
+    public String permission() default "";
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java
new file mode 100644
index 0000000..79cd191
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java
@@ -0,0 +1,28 @@
+package com.ruoyi.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.ruoyi.common.enums.DataSourceType;
+
+/**
+ * 自定义多数据源切换注解
+ *
+ * 优先级:先方法,后类,如果方法覆盖了类上的数据源类型,以方法的为准,否则以类上的为准
+ *
+ * @author ruoyi
+ */
+@Target({ ElementType.METHOD, ElementType.TYPE })
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Inherited
+public @interface DataSource
+{
+    /**
+     * 切换数据源名称
+     */
+    public DataSourceType value() default DataSourceType.MASTER;
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java
new file mode 100644
index 0000000..765d8e3
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java
@@ -0,0 +1,197 @@
+package com.ruoyi.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.ruoyi.common.utils.poi.ExcelHandlerAdapter;
+
+/**
+ * 自定义导出Excel数据注解
+ * 
+ * @author ruoyi
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+public @interface Excel
+{
+    /**
+     * 导出时在excel中排序
+     */
+    public int sort() default Integer.MAX_VALUE;
+
+    /**
+     * 导出到Excel中的名字.
+     */
+    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(默认不开启BigDecimal格式化)
+     */
+    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 boolean wrapText() default false;
+
+    /**
+     * 设置只能选择不能输入的列内容.
+     */
+    public String[] combo() default {};
+
+    /**
+     * 是否从字典读数据到combo,默认不读取,如读取需要设置dictType注解.
+     */
+    public boolean comboReadDict() default false;
+
+    /**
+     * 是否需要纵向合并单元格,应对需求:含有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), TEXT(3);
+        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/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excels.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excels.java
new file mode 100644
index 0000000..8c6870c
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excels.java
@@ -0,0 +1,18 @@
+package com.ruoyi.common.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Excel注解集
+ * 
+ * @author ruoyi
+ */
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Excels
+{
+    Excel[] value();
+}
\ No newline at end of file
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Log.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Log.java
new file mode 100644
index 0000000..e395169
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Log.java
@@ -0,0 +1,50 @@
+package com.ruoyi.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.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.enums.OperatorType;
+
+/**
+ * 自定义操作日志记录注解
+ * 
+ * @author ruoyi
+ */
+@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/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java
new file mode 100644
index 0000000..3e06e95
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java
@@ -0,0 +1,29 @@
+package com.ruoyi.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 ruoyi
+ *
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface RepeatSubmit
+{
+    /**
+     * 间隔时间(ms),小于此时间视为重复提交
+     */
+    public int interval() default 5000;
+
+    /**
+     * 提示消息
+     */
+    public String message() default "不允许重复提交,请稍后再试";
+}
\ No newline at end of file
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Sensitive.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Sensitive.java
new file mode 100644
index 0000000..c0621e9
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Sensitive.java
@@ -0,0 +1,24 @@
+package com.ruoyi.common.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.ruoyi.common.config.serializer.SensitiveJsonSerializer;
+import com.ruoyi.common.enums.DesensitizedType;
+
+/**
+ * 数据脱敏注解
+ *
+ * @author ruoyi
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+@JacksonAnnotationsInside
+@JsonSerialize(using = SensitiveJsonSerializer.class)
+public @interface Sensitive
+{
+    DesensitizedType desensitizedType();
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java b/ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java
new file mode 100644
index 0000000..46a5734
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java
@@ -0,0 +1,124 @@
+package com.ruoyi.common.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * 全局配置类
+ * 
+ * @author ruoyi
+ */
+@Component
+@ConfigurationProperties(prefix = "ruoyi")
+public class RuoYiConfig
+{
+    /** 项目名称 */
+    private static String name;
+
+    /** 版本 */
+    private static String version;
+
+    /** 版权年份 */
+    private static String copyrightYear;
+
+    /** 实例演示开关 */
+    private static boolean demoEnabled;
+
+    /** 上传路径 */
+    private static String profile;
+
+    /** 获取地址开关 */
+    private static boolean addressEnabled;
+
+    public static String getName()
+    {
+        return name;
+    }
+
+    public void setName(String name)
+    {
+        RuoYiConfig.name = name;
+    }
+
+    public static String getVersion()
+    {
+        return version;
+    }
+
+    public void setVersion(String version)
+    {
+        RuoYiConfig.version = version;
+    }
+
+    public static String getCopyrightYear()
+    {
+        return copyrightYear;
+    }
+
+    public void setCopyrightYear(String copyrightYear)
+    {
+        RuoYiConfig.copyrightYear = copyrightYear;
+    }
+
+    public static boolean isDemoEnabled()
+    {
+        return demoEnabled;
+    }
+
+    public void setDemoEnabled(boolean demoEnabled)
+    {
+        RuoYiConfig.demoEnabled = demoEnabled;
+    }
+
+    public static String getProfile()
+    {
+        return profile;
+    }
+
+    public void setProfile(String profile)
+    {
+        RuoYiConfig.profile = profile;
+    }
+
+    public static boolean isAddressEnabled()
+    {
+        return addressEnabled;
+    }
+
+    public void setAddressEnabled(boolean addressEnabled)
+    {
+        RuoYiConfig.addressEnabled = addressEnabled;
+    }
+
+    /**
+     * 获取导入上传路径
+     */
+    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/ruoyi-common/src/main/java/com/ruoyi/common/config/ServerConfig.java b/ruoyi-common/src/main/java/com/ruoyi/common/config/ServerConfig.java
new file mode 100644
index 0000000..b6b35e4
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/config/ServerConfig.java
@@ -0,0 +1,33 @@
+package com.ruoyi.common.config;
+
+import javax.servlet.http.HttpServletRequest;
+import org.springframework.stereotype.Component;
+import com.ruoyi.common.utils.ServletUtils;
+
+/**
+ * 服务相关配置
+ * 
+ * @author ruoyi
+ *
+ */
+@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/ruoyi-common/src/main/java/com/ruoyi/common/config/datasource/DynamicDataSourceContextHolder.java b/ruoyi-common/src/main/java/com/ruoyi/common/config/datasource/DynamicDataSourceContextHolder.java
new file mode 100644
index 0000000..78e5dc4
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/config/datasource/DynamicDataSourceContextHolder.java
@@ -0,0 +1,45 @@
+package com.ruoyi.common.config.datasource;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * 数据源切换处理
+ * 
+ * @author ruoyi
+ */
+public class DynamicDataSourceContextHolder
+{
+    public static final Logger log = LoggerFactory.getLogger(DynamicDataSourceContextHolder.class);
+
+    /**
+     * 使用ThreadLocal维护变量,ThreadLocal为每个使用该变量的线程提供独立的变量副本,
+     * 所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
+     */
+    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/ruoyi-common/src/main/java/com/ruoyi/common/config/serializer/SensitiveJsonSerializer.java b/ruoyi-common/src/main/java/com/ruoyi/common/config/serializer/SensitiveJsonSerializer.java
new file mode 100644
index 0000000..02241c5
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/config/serializer/SensitiveJsonSerializer.java
@@ -0,0 +1,64 @@
+package com.ruoyi.common.config.serializer;
+
+import java.io.IOException;
+import java.util.Objects;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.BeanProperty;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.ser.ContextualSerializer;
+import com.ruoyi.common.annotation.Sensitive;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.enums.DesensitizedType;
+import com.ruoyi.common.utils.ShiroUtils;
+
+/**
+ * 数据脱敏序列化过滤
+ *
+ * @author ruoyi
+ */
+public class SensitiveJsonSerializer extends JsonSerializer<String> implements ContextualSerializer
+{
+    private DesensitizedType desensitizedType;
+
+    @Override
+    public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException
+    {
+        if (desensitization())
+        {
+            gen.writeString(desensitizedType.desensitizer().apply(value));
+        }
+        else
+        {
+            gen.writeString(value);
+        }
+    }
+
+    @Override
+    public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property)
+            throws JsonMappingException
+    {
+        Sensitive annotation = property.getAnnotation(Sensitive.class);
+        if (Objects.nonNull(annotation) && Objects.equals(String.class, property.getType().getRawClass()))
+        {
+            this.desensitizedType = annotation.desensitizedType();
+            return this;
+        }
+        return prov.findValueSerializer(property.getType(), property);
+    }
+
+    /**
+     * 是否需要脱敏处理
+     */
+    private boolean desensitization()
+    {
+        SysUser securityUser = ShiroUtils.getSysUser();
+        if (securityUser == null)
+        {
+            return true;
+        }
+        // 管理员不脱敏
+        return !securityUser.isAdmin();
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/config/thread/ThreadPoolConfig.java b/ruoyi-common/src/main/java/com/ruoyi/common/config/thread/ThreadPoolConfig.java
new file mode 100644
index 0000000..955a4f9
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/config/thread/ThreadPoolConfig.java
@@ -0,0 +1,63 @@
+package com.ruoyi.common.config.thread;
+
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.ThreadPoolExecutor;
+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 com.ruoyi.common.utils.Threads;
+
+/**
+ * 线程池配置
+ *
+ * @author ruoyi
+ **/
+@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/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java
new file mode 100644
index 0000000..2229899
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java
@@ -0,0 +1,122 @@
+package com.ruoyi.common.constant;
+
+import java.util.Locale;
+
+/**
+ * 通用常量信息
+ * 
+ * @author ruoyi
+ */
+public class Constants
+{
+    /**
+     * UTF-8 字符集
+     */
+    public static final String UTF8 = "UTF-8";
+
+    /**
+     * GBK 字符集
+     */
+    public static final String GBK = "GBK";
+
+    /**
+     * 系统语言
+     */
+    public static final Locale DEFAULT_LOCALE = Locale.SIMPLIFIED_CHINESE;
+
+    /**
+     * 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 SYS_AUTH_CACHE = "sys-authCache";
+
+    /**
+     * 参数管理 cache name
+     */
+    public static final String SYS_CONFIG_CACHE = "sys-config";
+
+    /**
+     * 参数管理 cache key
+     */
+    public static final String SYS_CONFIG_KEY = "sys_config:";
+
+    /**
+     * 字典管理 cache name
+     */
+    public static final String SYS_DICT_CACHE = "sys-dict";
+
+    /**
+     * 字典管理 cache key
+     */
+    public static final String SYS_DICT_KEY = "sys_dict:";
+
+    /**
+     * 资源映射路径 前缀
+     */
+    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:";
+
+    /**
+     * 定时任务白名单配置(仅允许访问的包名,如其他需要可以自行添加)
+     */
+    public static final String[] JOB_WHITELIST_STR = { "com.ruoyi.quartz.task" };
+
+    /**
+     * 定时任务违规的字符
+     */
+    public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
+            "org.springframework", "org.apache", "com.ruoyi.common.utils.file", "com.ruoyi.common.config", "com.ruoyi.generator" };
+}
\ No newline at end of file
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java
new file mode 100644
index 0000000..98b4711
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java
@@ -0,0 +1,114 @@
+package com.ruoyi.common.constant;
+
+/**
+ * 代码生成通用常量
+ * 
+ * @author ruoyi
+ */
+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" };
+
+    /** 文本框 */
+    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_UPLOAD = "upload";
+
+    /** 富文本控件 */
+    public static final String HTML_SUMMERNOTE = "summernote";
+
+    /** 字符串类型 */
+    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/ruoyi-common/src/main/java/com/ruoyi/common/constant/PermissionConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/PermissionConstants.java
new file mode 100644
index 0000000..8967214
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/PermissionConstants.java
@@ -0,0 +1,27 @@
+package com.ruoyi.common.constant;
+
+/**
+ * 权限通用常量
+ * 
+ * @author ruoyi
+ */
+public class PermissionConstants
+{
+    /** 新增权限 */
+    public static final String ADD_PERMISSION = "add";
+
+    /** 修改权限 */
+    public static final String EDIT_PERMISSION = "edit";
+
+    /** 删除权限 */
+    public static final String REMOVE_PERMISSION = "remove";
+    
+    /** 导出权限 */
+    public static final String EXPORT_PERMISSION = "export";
+
+    /** 显示权限 */
+    public static final String VIEW_PERMISSION = "view";
+
+    /** 查询权限 */
+    public static final String LIST_PERMISSION = "list";
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/ScheduleConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/ScheduleConstants.java
new file mode 100644
index 0000000..62ad815
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/ScheduleConstants.java
@@ -0,0 +1,50 @@
+package com.ruoyi.common.constant;
+
+/**
+ * 任务调度通用常量
+ * 
+ * @author ruoyi
+ */
+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
+    {
+        /**
+         * 正常
+         */
+        NORMAL("0"),
+        /**
+         * 暂停
+         */
+        PAUSE("1");
+
+        private String value;
+
+        private Status(String value)
+        {
+            this.value = value;
+        }
+
+        public String getValue()
+        {
+            return value;
+        }
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/ShiroConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/ShiroConstants.java
new file mode 100644
index 0000000..684e538
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/ShiroConstants.java
@@ -0,0 +1,79 @@
+package com.ruoyi.common.constant;
+
+/**
+ * Shiro通用常量
+ * 
+ * @author ruoyi
+ */
+public class ShiroConstants
+{
+    /**
+     * 当前登录的用户
+     */
+    public static final String CURRENT_USER = "currentUser";
+
+    /**
+     * 用户名字段
+     */
+    public static final String CURRENT_USERNAME = "username";
+
+    /**
+     * 锁定屏幕字段
+     */
+    public static final String LOCK_SCREEN = "lockscreen";
+
+    /**
+     * 消息key
+     */
+    public static final String MESSAGE = "message";
+
+    /**
+     * 错误key
+     */
+    public static final String ERROR = "errorMsg";
+
+    /**
+     * 编码格式
+     */
+    public static final String ENCODING = "UTF-8";
+
+    /**
+     * 当前在线会话
+     */
+    public static final String ONLINE_SESSION = "online_session";
+
+    /**
+     * 验证码key
+     */
+    public static final String CURRENT_CAPTCHA = "captcha";
+
+    /**
+     * 验证码开关
+     */
+    public static final String CURRENT_ENABLED = "captchaEnabled";
+
+    /**
+     * 验证码类型
+     */
+    public static final String CURRENT_TYPE = "captchaType";
+
+    /**
+     * 验证码
+     */
+    public static final String CURRENT_VALIDATECODE = "validateCode";
+
+    /**
+     * 验证码错误
+     */
+    public static final String CAPTCHA_ERROR = "captchaError";
+
+    /**
+     * 登录记录缓存
+     */
+    public static final String LOGIN_RECORD_CACHE = "loginRecordCache";
+
+    /**
+     * 系统活跃用户缓存
+     */
+    public static final String SYS_USERCACHE = "sys-userCache";
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java
new file mode 100644
index 0000000..5800d20
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java
@@ -0,0 +1,73 @@
+package com.ruoyi.common.constant;
+
+/**
+ * 用户常量信息
+ * 
+ * @author ruoyi
+ */
+public class UserConstants
+{
+    /**
+     * 平台内系统用户的唯一标志
+     */
+    public static final String SYS_USER = "SYS_USER";
+
+    /** 正常状态 */
+    public static final String NORMAL = "0";
+
+    /** 异常状态 */
+    public static final String EXCEPTION = "1";
+
+    /** 用户封禁状态 */
+    public static final String USER_DISABLE = "1";
+
+    /** 角色正常状态 */
+    public static final String ROLE_NORMAL = "0";
+
+    /** 角色封禁状态 */
+    public static final String ROLE_DISABLE = "1";
+
+    /** 部门正常状态 */
+    public static final String DEPT_NORMAL = "0";
+
+    /** 部门停用状态 */
+    public static final String DEPT_DISABLE = "1";
+
+    /** 字典正常状态 */
+    public static final String DICT_NORMAL = "0";
+
+    /** 是否为系统默认(是) */
+    public static final String YES = "Y";
+    
+    /** 是否唯一的返回标识 */
+    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;
+
+    /**
+     * 用户类型
+     */
+    public static final String SYSTEM_USER_TYPE = "00";
+    public static final String REGISTER_USER_TYPE = "01";
+
+    /**
+     * 手机号码格式限制
+     */
+    public static final String MOBILE_PHONE_NUMBER_PATTERN = "^0{0,1}(13[0-9]|15[0-9]|14[0-9]|18[0-9])[0-9]{8}$";
+
+    /**
+     * 邮箱格式限制
+     */
+    public static final String EMAIL_PATTERN = "^((([a-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+(\\.([a-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(\\\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.)+(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.?";
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/context/PermissionContextHolder.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/context/PermissionContextHolder.java
new file mode 100644
index 0000000..f06b8fa
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/context/PermissionContextHolder.java
@@ -0,0 +1,27 @@
+package com.ruoyi.common.core.context;
+
+import org.springframework.web.context.request.RequestAttributes;
+import org.springframework.web.context.request.RequestContextHolder;
+import com.ruoyi.common.core.text.Convert;
+
+/**
+ * 权限信息
+ * 
+ * @author ruoyi
+ */
+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/ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java
new file mode 100644
index 0000000..3f1cb30
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java
@@ -0,0 +1,229 @@
+package com.ruoyi.common.core.controller;
+
+import java.beans.PropertyEditorSupport;
+import java.util.Date;
+import java.util.List;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+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.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.AjaxResult.Type;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.core.page.PageDomain;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.core.page.TableSupport;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.PageUtils;
+import com.ruoyi.common.utils.ServletUtils;
+import com.ruoyi.common.utils.ShiroUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.sql.SqlUtil;
+
+/**
+ * web层通用数据处理
+ * 
+ * @author ruoyi
+ */
+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();
+    }
+
+    /**
+     * 获取request
+     */
+    public HttpServletRequest getRequest()
+    {
+        return ServletUtils.getRequest();
+    }
+
+    /**
+     * 获取response
+     */
+    public HttpServletResponse getResponse()
+    {
+        return ServletUtils.getResponse();
+    }
+
+    /**
+     * 获取session
+     */
+    public HttpSession getSession()
+    {
+        return getRequest().getSession();
+    }
+
+    /**
+     * 响应请求分页数据
+     */
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    protected TableDataInfo getDataTable(List<?> list)
+    {
+        TableDataInfo rspData = new TableDataInfo();
+        rspData.setCode(0);
+        rspData.setRows(list);
+        rspData.setTotal(new PageInfo(list).getTotal());
+        return rspData;
+    }
+
+    /**
+     * 响应返回结果
+     * 
+     * @param rows 影响行数
+     * @return 操作结果
+     */
+    protected AjaxResult toAjax(int rows)
+    {
+        return rows > 0 ? success() : error();
+    }
+
+    /**
+     * 响应返回结果
+     * 
+     * @param result 结果
+     * @return 操作结果
+     */
+    protected AjaxResult toAjax(boolean result)
+    {
+        return result ? success() : error();
+    }
+
+    /**
+     * 返回成功
+     */
+    public AjaxResult success()
+    {
+        return AjaxResult.success();
+    }
+
+    /**
+     * 返回失败消息
+     */
+    public AjaxResult error()
+    {
+        return AjaxResult.error();
+    }
+
+    /**
+     * 返回成功消息
+     */
+    public AjaxResult success(String message)
+    {
+        return AjaxResult.success(message);
+    }
+
+    /**
+     * 返回成功数据
+     */
+    public static AjaxResult success(Object data)
+    {
+        return AjaxResult.success("操作成功", data);
+    }
+
+    /**
+     * 返回失败消息
+     */
+    public AjaxResult error(String message)
+    {
+        return AjaxResult.error(message);
+    }
+
+    /**
+     * 返回错误码消息
+     */
+    public AjaxResult error(Type type, String message)
+    {
+        return new AjaxResult(type, message);
+    }
+
+    /**
+     * 页面跳转
+     */
+    public String redirect(String url)
+    {
+        return StringUtils.format("redirect:{}", url);
+    }
+
+    /**
+     * 获取用户缓存信息
+     */
+    public SysUser getSysUser()
+    {
+        return ShiroUtils.getSysUser();
+    }
+
+    /**
+     * 设置用户缓存信息
+     */
+    public void setSysUser(SysUser user)
+    {
+        ShiroUtils.setSysUser(user);
+    }
+
+    /**
+     * 获取登录用户id
+     */
+    public Long getUserId()
+    {
+        return getSysUser().getUserId();
+    }
+
+    /**
+     * 获取登录用户名
+     */
+    public String getLoginName()
+    {
+        return getSysUser().getLoginName();
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/AjaxResult.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/AjaxResult.java
new file mode 100644
index 0000000..2feaa13
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/AjaxResult.java
@@ -0,0 +1,227 @@
+package com.ruoyi.common.core.domain;
+
+import java.util.HashMap;
+import java.util.Objects;
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * 操作消息提醒
+ *
+ * @author ruoyi
+ */
+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";
+
+    /**
+     * 状态类型
+     */
+    public enum Type
+    {
+        /** 成功 */
+        SUCCESS(0),
+        /** 警告 */
+        WARN(301),
+        /** 错误 */
+        ERROR(500);
+        private final int value;
+
+        Type(int value)
+        {
+            this.value = value;
+        }
+
+        public int value()
+        {
+            return this.value;
+        }
+    }
+
+    /**
+     * 初始化一个新创建的 AjaxResult 对象,使其表示一个空消息。
+     */
+    public AjaxResult()
+    {
+    }
+
+    /**
+     * 初始化一个新创建的 AjaxResult 对象
+     *
+     * @param type 状态类型
+     * @param msg 返回内容
+     */
+    public AjaxResult(Type type, String msg)
+    {
+        super.put(CODE_TAG, type.value);
+        super.put(MSG_TAG, msg);
+    }
+
+    /**
+     * 初始化一个新创建的 AjaxResult 对象
+     *
+     * @param type 状态类型
+     * @param msg 返回内容
+     * @param data 数据对象
+     */
+    public AjaxResult(Type type, String msg, Object data)
+    {
+        super.put(CODE_TAG, type.value);
+        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(Type.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(Type.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(Type.ERROR, msg, data);
+    }
+
+    /**
+     * 是否为成功消息
+     *
+     * @return 结果
+     */
+    public boolean isSuccess()
+    {
+        return Objects.equals(Type.SUCCESS.value, this.get(CODE_TAG));
+    }
+
+    /**
+     * 是否为警告消息
+     *
+     * @return 结果
+     */
+    public boolean isWarn()
+    {
+        return Objects.equals(Type.WARN.value, this.get(CODE_TAG));
+    }
+
+    /**
+     * 是否为错误消息
+     *
+     * @return 结果
+     */
+    public boolean isError()
+    {
+        return Objects.equals(Type.ERROR.value, 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/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java
new file mode 100644
index 0000000..df42296
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java
@@ -0,0 +1,118 @@
+package com.ruoyi.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 ruoyi
+ */
+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", timezone = "GMT+8")
+    private Date createTime;
+
+    /** 更新者 */
+    private String updateBy;
+
+    /** 更新时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    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/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/CxSelect.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/CxSelect.java
new file mode 100644
index 0000000..3cac069
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/CxSelect.java
@@ -0,0 +1,69 @@
+package com.ruoyi.common.core.domain;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * CxSelect树结构实体类
+ * 
+ * @author ruoyi
+ */
+public class CxSelect implements Serializable
+{
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 数据值字段名称
+     */
+    private String v;
+
+    /**
+     * 数据标题字段名称
+     */
+    private String n;
+
+    /**
+     * 子集数据字段名称
+     */
+    private List<CxSelect> s;
+
+    public CxSelect()
+    {
+    }
+
+    public CxSelect(String v, String n)
+    {
+        this.v = v;
+        this.n = n;
+    }
+
+    public List<CxSelect> getS()
+    {
+        return s;
+    }
+
+    public void setN(String n)
+    {
+        this.n = n;
+    }
+
+    public String getN()
+    {
+        return n;
+    }
+
+    public void setS(List<CxSelect> s)
+    {
+        this.s = s;
+    }
+
+    public String getV()
+    {
+        return v;
+    }
+
+    public void setV(String v)
+    {
+        this.v = v;
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/R.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/R.java
new file mode 100644
index 0000000..67337dd
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/R.java
@@ -0,0 +1,114 @@
+package com.ruoyi.common.core.domain;
+
+import java.io.Serializable;
+
+/**
+ * 响应信息主体
+ *
+ * @author ruoyi
+ */
+public class R<T> implements Serializable
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 成功 */
+    public static final int SUCCESS = 0;
+
+    /** 失败 */
+    public static final int FAIL = 500;
+
+    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/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java
new file mode 100644
index 0000000..27da2d5
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java
@@ -0,0 +1,63 @@
+package com.ruoyi.common.core.domain;
+
+/**
+ * Tree基类
+ * 
+ * @author ruoyi
+ */
+public class TreeEntity extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 父菜单名称 */
+    private String parentName;
+
+    /** 父菜单ID */
+    private Long parentId;
+
+    /** 显示顺序 */
+    private Integer orderNum;
+
+    /** 祖级列表 */
+    private String ancestors;
+
+    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;
+    }
+}
\ No newline at end of file
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/Ztree.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/Ztree.java
new file mode 100644
index 0000000..5567a4d
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/Ztree.java
@@ -0,0 +1,104 @@
+package com.ruoyi.common.core.domain;
+
+import java.io.Serializable;
+
+/**
+ * Ztree树结构实体类
+ * 
+ * @author ruoyi
+ */
+public class Ztree implements Serializable
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 节点ID */
+    private Long id;
+
+    /** 节点父ID */
+    private Long pId;
+
+    /** 节点名称 */
+    private String name;
+
+    /** 节点标题 */
+    private String title;
+
+    /** 是否勾选 */
+    private boolean checked = false;
+
+    /** 是否展开 */
+    private boolean open = false;
+
+    /** 是否能勾选 */
+    private boolean nocheck = false;
+
+    public Long getId()
+    {
+        return id;
+    }
+
+    public void setId(Long id)
+    {
+        this.id = id;
+    }
+
+    public Long getpId()
+    {
+        return pId;
+    }
+
+    public void setpId(Long pId)
+    {
+        this.pId = pId;
+    }
+
+    public String getName()
+    {
+        return name;
+    }
+
+    public void setName(String name)
+    {
+        this.name = name;
+    }
+
+    public String getTitle()
+    {
+        return title;
+    }
+
+    public void setTitle(String title)
+    {
+        this.title = title;
+    }
+
+    public boolean isChecked()
+    {
+        return checked;
+    }
+
+    public void setChecked(boolean checked)
+    {
+        this.checked = checked;
+    }
+
+    public boolean isOpen()
+    {
+        return open;
+    }
+
+    public void setOpen(boolean open)
+    {
+        this.open = open;
+    }
+
+    public boolean isNocheck()
+    {
+        return nocheck;
+    }
+
+    public void setNocheck(boolean nocheck)
+    {
+        this.nocheck = nocheck;
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java
new file mode 100644
index 0000000..c62783f
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java
@@ -0,0 +1,203 @@
+package com.ruoyi.common.core.domain.entity;
+
+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.fasterxml.jackson.annotation.JsonIgnore;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * 部门表 sys_dept
+ * 
+ * @author ruoyi
+ */
+public class SysDept extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 部门ID */
+    private Long deptId;
+
+    /** 父部门ID */
+    private Long parentId;
+
+    /** 祖级列表 */
+    private String ancestors;
+
+    /** 部门名称 */
+    private String deptName;
+
+    /** 显示顺序 */
+    private Integer orderNum;
+
+    /** 负责人 */
+    private String leader;
+
+    /** 联系电话 */
+    private String phone;
+
+    /** 邮箱 */
+    private String email;
+
+    /** 部门状态:0正常,1停用 */
+    private String status;
+
+    /** 删除标志(0代表存在 2代表删除) */
+    private String delFlag;
+
+    /** 父部门名称 */
+    private String parentName;
+
+    /** 排除编号 */
+    private Long excludeId;
+
+    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;
+    }
+
+    @JsonIgnore
+    public Long getExcludeId()
+    {
+        return excludeId;
+    }
+
+    public void setExcludeId(Long excludeId)
+    {
+        this.excludeId = excludeId;
+    }
+
+    @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/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java
new file mode 100644
index 0000000..7ef830d
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java
@@ -0,0 +1,176 @@
+package com.ruoyi.common.core.domain.entity;
+
+import javax.validation.constraints.*;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.annotation.Excel.ColumnType;
+import com.ruoyi.common.constant.UserConstants;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * 字典数据表 sys_dict_data
+ * 
+ * @author ruoyi
+ */
+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;
+
+    /** 样式属性(其他样式扩展) */
+    @Excel(name = "字典样式")
+    private String cssClass;
+
+    /** 表格字典样式 */
+    private String listClass;
+
+    /** 是否默认(Y是 N否) */
+    @Excel(name = "是否默认", readConverterExp = "Y=是,N=否")
+    private String isDefault;
+
+    /** 状态(0正常 1停用) */
+    @Excel(name = "状态", readConverterExp = "0=正常,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/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java
new file mode 100644
index 0000000..9697c8e
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java
@@ -0,0 +1,94 @@
+package com.ruoyi.common.core.domain.entity;
+
+import javax.validation.constraints.*;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.annotation.Excel.ColumnType;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * 字典类型表 sys_dict_type
+ * 
+ * @author ruoyi
+ */
+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正常 1停用) */
+    @Excel(name = "状态", readConverterExp = "0=正常,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/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java
new file mode 100644
index 0000000..765c4a7
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java
@@ -0,0 +1,214 @@
+package com.ruoyi.common.core.domain.entity;
+
+import java.util.List;
+import java.util.ArrayList;
+import javax.validation.constraints.*;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * 菜单权限表 sys_menu
+ * 
+ * @author ruoyi
+ */
+public class SysMenu extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 菜单ID */
+    private Long menuId;
+
+    /** 菜单名称 */
+    private String menuName;
+
+    /** 父菜单名称 */
+    private String parentName;
+
+    /** 父菜单ID */
+    private Long parentId;
+
+    /** 显示顺序 */
+    private String orderNum;
+
+    /** 菜单URL */
+    private String url;
+
+    /** 打开方式(menuItem页签 menuBlank新窗口) */
+    private String target;
+
+    /** 类型(M目录 C菜单 F按钮) */
+    private String menuType;
+
+    /** 菜单状态(0显示 1隐藏) */
+    private String visible;
+
+    /** 是否刷新(0刷新 1不刷新) */
+    private String isRefresh;
+
+    /** 权限字符串 */
+    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;
+    }
+
+    @NotBlank(message = "显示顺序不能为空")
+    public String getOrderNum()
+    {
+        return orderNum;
+    }
+
+    public void setOrderNum(String orderNum)
+    {
+        this.orderNum = orderNum;
+    }
+
+    @Size(min = 0, max = 200, message = "请求地址不能超过200个字符")
+    public String getUrl()
+    {
+        return url;
+    }
+
+    public void setUrl(String url)
+    {
+        this.url = url;
+    }
+
+    public String getTarget()
+    {
+        return target;
+    }
+
+    public void setTarget(String target)
+    {
+        this.target = target;
+    }
+
+    @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 getIsRefresh()
+    {
+        return isRefresh;
+    }
+
+    public void setIsRefresh(String isRefresh)
+    {
+        this.isRefresh = isRefresh;
+    }
+
+    @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("url", getUrl())
+            .append("target", getTarget())
+            .append("menuType", getMenuType())
+            .append("visible", getVisible())
+            .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/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java
new file mode 100644
index 0000000..b6ffb5e
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java
@@ -0,0 +1,211 @@
+package com.ruoyi.common.core.domain.entity;
+
+import java.util.Set;
+import javax.validation.constraints.*;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.annotation.Excel.ColumnType;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * 角色表 sys_role
+ * 
+ * @author ruoyi
+ */
+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 = "角色排序", cellType = ColumnType.NUMERIC)
+    private String roleSort;
+
+    /** 数据范围(1:所有数据权限;2:自定义数据权限;3:本部门数据权限;4:本部门及以下数据权限;5:仅本人数据权限) */
+    @Excel(name = "数据范围", readConverterExp = "1=所有数据权限,2=自定义数据权限,3=本部门数据权限,4=本部门及以下数据权限,5=仅本人数据权限")
+    private String dataScope;
+
+    /** 角色状态(0正常 1停用) */
+    @Excel(name = "角色状态", readConverterExp = "0=正常,1=停用")
+    private String status;
+
+    /** 删除标志(0代表存在 2代表删除) */
+    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;
+    }
+
+    public String getDataScope()
+    {
+        return dataScope;
+    }
+
+    public void setDataScope(String dataScope)
+    {
+        this.dataScope = dataScope;
+    }
+
+    @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;
+    }
+
+    @NotBlank(message = "显示顺序不能为空")
+    public String getRoleSort()
+    {
+        return roleSort;
+    }
+
+    public void setRoleSort(String roleSort)
+    {
+        this.roleSort = roleSort;
+    }
+
+    public String getStatus()
+    {
+        return status;
+    }
+
+    public String getDelFlag()
+    {
+        return delFlag;
+    }
+
+    public void setDelFlag(String delFlag)
+    {
+        this.delFlag = delFlag;
+    }
+
+    public void setStatus(String status)
+    {
+        this.status = status;
+    }
+
+    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("status", getStatus())
+            .append("delFlag", getDelFlag())
+            .append("createBy", getCreateBy())
+            .append("createTime", getCreateTime())
+            .append("updateBy", getUpdateBy())
+            .append("updateTime", getUpdateTime())
+            .append("remark", getRemark())
+            .toString();
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java
new file mode 100644
index 0000000..b5eff82
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java
@@ -0,0 +1,385 @@
+package com.ruoyi.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.fasterxml.jackson.annotation.JsonIgnore;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.annotation.Excel.ColumnType;
+import com.ruoyi.common.annotation.Excel.Type;
+import com.ruoyi.common.annotation.Excels;
+import com.ruoyi.common.core.domain.BaseEntity;
+import com.ruoyi.common.xss.Xss;
+
+/**
+ * 用户对象 sys_user
+ * 
+ * @author ruoyi
+ */
+public class SysUser extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 用户ID */
+    @Excel(name = "用户序号", type = Type.EXPORT, cellType = ColumnType.NUMERIC, prompt = "用户编号")
+    private Long userId;
+
+    /** 部门ID */
+    @Excel(name = "部门编号", type = Type.IMPORT)
+    private Long deptId;
+
+    /** 部门父ID */
+    private Long parentId;
+
+    /** 角色ID */
+    private Long roleId;
+
+    /** 登录名称 */
+    @Excel(name = "登录名称")
+    private String loginName;
+
+    /** 用户名称 */
+    @Excel(name = "用户名称")
+    private String userName;
+
+    /** 用户类型 */
+    private String userType;
+
+    /** 用户邮箱 */
+    @Excel(name = "用户邮箱")
+    private String email;
+
+    /** 手机号码 */
+    @Excel(name = "手机号码", cellType = ColumnType.TEXT)
+    private String phonenumber;
+
+    /** 用户性别 */
+    @Excel(name = "用户性别", readConverterExp = "0=男,1=女,2=未知")
+    private String sex;
+
+    /** 用户头像 */
+    private String avatar;
+
+    /** 密码 */
+    private String password;
+
+    /** 盐加密 */
+    private String salt;
+
+    /** 帐号状态(0正常 1停用) */
+    @Excel(name = "帐号状态", readConverterExp = "0=正常,1=停用")
+    private String status;
+
+    /** 删除标志(0代表存在 2代表删除) */
+    private String delFlag;
+
+    /** 最后登录IP */
+    @Excel(name = "最后登录IP", type = Type.EXPORT)
+    private String loginIp;
+
+    /** 最后登录时间 */
+    @Excel(name = "最后登录时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT)
+    private Date loginDate;
+
+    /** 密码最后更新时间 */
+    private Date pwdUpdateDate;
+
+    /** 部门对象 */
+    @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;
+
+    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;
+    }
+
+    public Long getParentId()
+    {
+        return parentId;
+    }
+
+    public void setParentId(Long parentId)
+    {
+        this.parentId = parentId;
+    }
+
+    public Long getRoleId()
+    {
+        return roleId;
+    }
+
+    public void setRoleId(Long roleId)
+    {
+        this.roleId = roleId;
+    }
+
+    @Xss(message = "登录账号不能包含脚本字符")
+    @NotBlank(message = "登录账号不能为空")
+    @Size(min = 0, max = 30, message = "登录账号长度不能超过30个字符")
+    public String getLoginName()
+    {
+        return loginName;
+    }
+
+    public void setLoginName(String loginName)
+    {
+        this.loginName = loginName;
+    }
+
+    @Xss(message = "用户昵称不能包含脚本字符")
+    @Size(min = 0, max = 30, message = "用户昵称长度不能超过30个字符")
+    public String getUserName()
+    {
+        return userName;
+    }
+
+    public void setUserName(String userName)
+    {
+        this.userName = userName;
+    }
+
+    public String getUserType()
+    {
+        return userType;
+    }
+
+    public void setUserType(String userType)
+    {
+        this.userType = userType;
+    }
+
+    @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;
+    }
+
+    @JsonIgnore
+    public String getPassword()
+    {
+        return password;
+    }
+
+    public void setPassword(String password)
+    {
+        this.password = password;
+    }
+
+    @JsonIgnore
+    public String getSalt()
+    {
+        return salt;
+    }
+
+    public void setSalt(String salt)
+    {
+        this.salt = salt;
+    }
+
+    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 Date getPwdUpdateDate()
+    {
+        return pwdUpdateDate;
+    }
+
+    public void setPwdUpdateDate(Date pwdUpdateDate)
+    {
+        this.pwdUpdateDate = pwdUpdateDate;
+    }
+
+    public SysDept getDept()
+    {
+        if (dept == null)
+        {
+            dept = new SysDept();
+        }
+        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;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("userId", getUserId())
+            .append("deptId", getDeptId())
+            .append("loginName", getLoginName())
+            .append("userName", getUserName())
+            .append("userType", getUserType())
+            .append("email", getEmail())
+            .append("phonenumber", getPhonenumber())
+            .append("sex", getSex())
+            .append("avatar", getAvatar())
+            .append("password", getPassword())
+            .append("salt", getSalt())
+            .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())
+			.append("roles", getRoles())
+            .toString();
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java
new file mode 100644
index 0000000..61f6d85
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java
@@ -0,0 +1,89 @@
+package com.ruoyi.common.core.page;
+
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * 分页数据
+ * 
+ * @author ruoyi
+ */
+public class PageDomain
+{
+    /** 当前记录起始索引 */
+    private Integer pageNum;
+
+    /** 每页显示记录数 */
+    private Integer pageSize;
+
+    /** 排序列 */
+    private String orderByColumn;
+
+    /** 排序的方向desc或者asc */
+    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)
+    {
+        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/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java
new file mode 100644
index 0000000..373e592
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java
@@ -0,0 +1,85 @@
+package com.ruoyi.common.core.page;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 表格分页数据对象
+ * 
+ * @author ruoyi
+ */
+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;
+    }
+}
\ No newline at end of file
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableSupport.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableSupport.java
new file mode 100644
index 0000000..a120c30
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableSupport.java
@@ -0,0 +1,56 @@
+package com.ruoyi.common.core.page;
+
+import com.ruoyi.common.core.text.Convert;
+import com.ruoyi.common.utils.ServletUtils;
+
+/**
+ * 表格数据处理
+ * 
+ * @author ruoyi
+ */
+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/ruoyi-common/src/main/java/com/ruoyi/common/core/text/CharsetKit.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/text/CharsetKit.java
new file mode 100644
index 0000000..84124aa
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/text/CharsetKit.java
@@ -0,0 +1,86 @@
+package com.ruoyi.common.core.text;
+
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * 字符集工具类
+ * 
+ * @author ruoyi
+ */
+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);
+
+    /**
+     * 转换为Charset对象
+     * 
+     * @param charset 字符集,为空则返回默认字符集
+     * @return Charset
+     */
+    public static Charset charset(String charset)
+    {
+        return StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset);
+    }
+
+    /**
+     * 转换字符串的字符集编码
+     * 
+     * @param source 字符串
+     * @param srcCharset 源字符集,默认ISO-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 源字符集,默认ISO-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/ruoyi-common/src/main/java/com/ruoyi/common/core/text/Convert.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/text/Convert.java
new file mode 100644
index 0000000..edf9afc
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/text/Convert.java
@@ -0,0 +1,1010 @@
+package com.ruoyi.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.ruoyi.common.utils.StringUtils;
+import org.apache.commons.lang3.ArrayUtils;
+
+/**
+ * 类型转换器
+ *
+ * @author ruoyi
+ */
+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);
+    }
+
+    /**
+     * 转换为byte<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;
+        }
+    }
+
+    /**
+     * 转换为byte<br>
+     * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
+     * 转换失败不会报错
+     *
+     * @param value 被转换的值
+     * @return 结果
+     */
+    public static Byte toByte(Object value)
+    {
+        return toByte(value, null);
+    }
+
+    /**
+     * 转换为Short<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;
+        }
+    }
+
+    /**
+     * 转换为Short<br>
+     * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
+     * 转换失败不会报错
+     *
+     * @param value 被转换的值
+     * @return 结果
+     */
+    public static Short toShort(Object value)
+    {
+        return toShort(value, null);
+    }
+
+    /**
+     * 转换为Number<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;
+        }
+    }
+
+    /**
+     * 转换为Number<br>
+     * 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
+     * 转换失败不会报错
+     *
+     * @param value 被转换的值
+     * @return 结果
+     */
+    public static Number toNumber(Object value)
+    {
+        return toNumber(value, null);
+    }
+
+    /**
+     * 转换为int<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;
+        }
+    }
+
+    /**
+     * 转换为int<br>
+     * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
+     * 转换失败不会报错
+     *
+     * @param value 被转换的值
+     * @return 结果
+     */
+    public static Integer toInt(Object value)
+    {
+        return toInt(value, null);
+    }
+
+    /**
+     * 转换为Integer数组<br>
+     *
+     * @param str 被转换的值
+     * @return 结果
+     */
+    public static Integer[] toIntArray(String str)
+    {
+        return toIntArray(",", str);
+    }
+
+    /**
+     * 转换为Long数组<br>
+     *
+     * @param str 被转换的值
+     * @return 结果
+     */
+    public static Long[] toLongArray(String str)
+    {
+        return toLongArray(",", str);
+    }
+
+    /**
+     * 转换为Integer数组<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;
+    }
+
+    /**
+     * 转换为Long数组<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;
+    }
+
+    /**
+     * 转换为String数组<br>
+     *
+     * @param str 被转换的值
+     * @return 结果
+     */
+    public static String[] toStrArray(String str)
+    {
+        if (StringUtils.isEmpty(str))
+        {
+            return new String[] {};
+        }
+        return toStrArray(",", str);
+    }
+
+    /**
+     * 转换为String数组<br>
+     *
+     * @param split 分隔符
+     * @param split 被转换的值
+     * @return 结果
+     */
+    public static String[] toStrArray(String split, String str)
+    {
+        return str.split(split);
+    }
+
+    /**
+     * 转换为long<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;
+        }
+    }
+
+    /**
+     * 转换为long<br>
+     * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
+     * 转换失败不会报错
+     *
+     * @param value 被转换的值
+     * @return 结果
+     */
+    public static Long toLong(Object value)
+    {
+        return toLong(value, null);
+    }
+
+    /**
+     * 转换为double<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;
+        }
+    }
+
+    /**
+     * 转换为double<br>
+     * 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
+     * 转换失败不会报错
+     *
+     * @param value 被转换的值
+     * @return 结果
+     */
+    public static Double toDouble(Object value)
+    {
+        return toDouble(value, null);
+    }
+
+    /**
+     * 转换为Float<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;
+        }
+    }
+
+    /**
+     * 转换为Float<br>
+     * 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
+     * 转换失败不会报错
+     *
+     * @param value 被转换的值
+     * @return 结果
+     */
+    public static Float toFloat(Object value)
+    {
+        return toFloat(value, null);
+    }
+
+    /**
+     * 转换为boolean<br>
+     * String支持的值为:true、false、yes、ok、no,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;
+        }
+    }
+
+    /**
+     * 转换为boolean<br>
+     * 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
+     * 转换失败不会报错
+     *
+     * @param value 被转换的值
+     * @return 结果
+     */
+    public static Boolean toBool(Object value)
+    {
+        return toBool(value, null);
+    }
+
+    /**
+     * 转换为Enum对象<br>
+     * 如果给定的值为空,或者转换失败,返回默认值<br>
+     *
+     * @param clazz Enum的Class
+     * @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;
+        }
+    }
+
+    /**
+     * 转换为Enum对象<br>
+     * 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
+     *
+     * @param clazz Enum的Class
+     * @param value 值
+     * @return Enum
+     */
+    public static <E extends Enum<E>> E toEnum(Class<E> clazz, Object value)
+    {
+        return toEnum(clazz, value, null);
+    }
+
+    /**
+     * 转换为BigInteger<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;
+        }
+    }
+
+    /**
+     * 转换为BigInteger<br>
+     * 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
+     * 转换失败不会报错
+     *
+     * @param value 被转换的值
+     * @return 结果
+     */
+    public static BigInteger toBigInteger(Object value)
+    {
+        return toBigInteger(value, null);
+    }
+
+    /**
+     * 转换为BigDecimal<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;
+        }
+    }
+
+    /**
+     * 转换为BigDecimal<br>
+     * 如果给定的值为空,或者转换失败,返回默认值<br>
+     * 转换失败不会报错
+     *
+     * @param value 被转换的值
+     * @return 结果
+     */
+    public static BigDecimal toBigDecimal(Object value)
+    {
+        return toBigDecimal(value, null);
+    }
+
+    /**
+     * 将对象转为字符串<br>
+     * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
+     *
+     * @param obj 对象
+     * @return 字符串
+     */
+    public static String utf8Str(Object obj)
+    {
+        return str(obj, CharsetKit.CHARSET_UTF_8);
+    }
+
+    /**
+     * 将对象转为字符串<br>
+     * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
+     *
+     * @param obj 对象
+     * @param charsetName 字符集
+     * @return 字符串
+     */
+    public static String str(Object obj, String charsetName)
+    {
+        return str(obj, Charset.forName(charsetName));
+    }
+
+    /**
+     * 将对象转为字符串<br>
+     * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 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();
+    }
+
+    /**
+     * 将byte数组转为字符串
+     *
+     * @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));
+    }
+
+    /**
+     * 解码字节码
+     *
+     * @param data 字符串
+     * @param charset 字符集,如果此字段为空,则解码的结果取决于平台
+     * @return 解码后的字符串
+     */
+    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/ruoyi-common/src/main/java/com/ruoyi/common/core/text/StrFormatter.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/text/StrFormatter.java
new file mode 100644
index 0000000..c78ac77
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/text/StrFormatter.java
@@ -0,0 +1,92 @@
+package com.ruoyi.common.core.text;
+
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * 字符串格式化
+ * 
+ * @author ruoyi
+ */
+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>
+     * 通常使用:format("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
+                {
+                    // 正常占位符
+                    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/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessStatus.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessStatus.java
new file mode 100644
index 0000000..c6640bb
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessStatus.java
@@ -0,0 +1,19 @@
+package com.ruoyi.common.enums;
+
+/**
+ * 操作状态
+ * 
+ * @author ruoyi
+ */
+public enum BusinessStatus
+{
+    /**
+     * 成功
+     */
+    SUCCESS,
+
+    /**
+     * 失败
+     */
+    FAIL,
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessType.java
new file mode 100644
index 0000000..24d076a
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessType.java
@@ -0,0 +1,59 @@
+package com.ruoyi.common.enums;
+
+/**
+ * 业务操作类型
+ * 
+ * @author ruoyi
+ */
+public enum BusinessType
+{
+    /**
+     * 其它
+     */
+    OTHER,
+
+    /**
+     * 新增
+     */
+    INSERT,
+
+    /**
+     * 修改
+     */
+    UPDATE,
+
+    /**
+     * 删除
+     */
+    DELETE,
+
+    /**
+     * 授权
+     */
+    GRANT,
+
+    /**
+     * 导出
+     */
+    EXPORT,
+
+    /**
+     * 导入
+     */
+    IMPORT,
+
+    /**
+     * 强退
+     */
+    FORCE,
+
+    /**
+     * 生成代码
+     */
+    GENCODE,
+    
+    /**
+     * 清空
+     */
+    CLEAN,
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/DataSourceType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/DataSourceType.java
new file mode 100644
index 0000000..0d945be
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/DataSourceType.java
@@ -0,0 +1,19 @@
+package com.ruoyi.common.enums;
+
+/**
+ * 数据源
+ * 
+ * @author ruoyi
+ */
+public enum DataSourceType
+{
+    /**
+     * 主库
+     */
+    MASTER,
+
+    /**
+     * 从库
+     */
+    SLAVE
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/DesensitizedType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/DesensitizedType.java
new file mode 100644
index 0000000..07f02ee
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/DesensitizedType.java
@@ -0,0 +1,59 @@
+package com.ruoyi.common.enums;
+
+import java.util.function.Function;
+import com.ruoyi.common.utils.DesensitizedUtil;
+
+/**
+ * 脱敏类型
+ *
+ * @author ruoyi
+ */
+public enum DesensitizedType
+{
+    /**
+     * 姓名,第2位星号替换
+     */
+    USERNAME(s -> s.replaceAll("(\\S)\\S(\\S*)", "$1*$2")),
+
+    /**
+     * 密码,全部字符都用*代替
+     */
+    PASSWORD(DesensitizedUtil::password),
+
+    /**
+     * 身份证,中间10位星号替换
+     */
+    ID_CARD(s -> s.replaceAll("(\\d{4})\\d{10}(\\d{3}[Xx]|\\d{4})", "$1** **** ****$2")),
+
+    /**
+     * 手机号,中间4位星号替换
+     */
+    PHONE(s -> s.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2")),
+
+    /**
+     * 电子邮箱,仅显示第一个字母和@后面的地址显示,其他星号替换
+     */
+    EMAIL(s -> s.replaceAll("(^.)[^@]*(@.*$)", "$1****$2")),
+
+    /**
+     * 银行卡号,保留最后4位,其他星号替换
+     */
+    BANK_CARD(s -> s.replaceAll("\\d{15}(\\d{3})", "**** **** **** **** $1")),
+
+    /**
+     * 车牌号码,包含普通车辆、新能源车辆
+     */
+    CAR_LICENSE(DesensitizedUtil::carLicense);
+
+    private final Function<String, String> desensitizer;
+
+    DesensitizedType(Function<String, String> desensitizer)
+    {
+        this.desensitizer = desensitizer;
+    }
+
+    public Function<String, String> desensitizer()
+    {
+        return desensitizer;
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/OnlineStatus.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/OnlineStatus.java
new file mode 100644
index 0000000..a05d5ff
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/OnlineStatus.java
@@ -0,0 +1,24 @@
+package com.ruoyi.common.enums;
+
+/**
+ * 用户会话
+ * 
+ * @author ruoyi
+ */
+public enum OnlineStatus
+{
+    /** 用户状态 */
+    on_line("在线"), off_line("离线");
+
+    private final String info;
+
+    private OnlineStatus(String info)
+    {
+        this.info = info;
+    }
+
+    public String getInfo()
+    {
+        return info;
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/OperatorType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/OperatorType.java
new file mode 100644
index 0000000..bdd143c
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/OperatorType.java
@@ -0,0 +1,24 @@
+package com.ruoyi.common.enums;
+
+/**
+ * 操作人类别
+ * 
+ * @author ruoyi
+ */
+public enum OperatorType
+{
+    /**
+     * 其它
+     */
+    OTHER,
+
+    /**
+     * 后台用户
+     */
+    MANAGE,
+
+    /**
+     * 手机端用户
+     */
+    MOBILE
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/UserStatus.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/UserStatus.java
new file mode 100644
index 0000000..d7ff44a
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/UserStatus.java
@@ -0,0 +1,30 @@
+package com.ruoyi.common.enums;
+
+/**
+ * 用户状态
+ * 
+ * @author ruoyi
+ */
+public enum UserStatus
+{
+    OK("0", "正常"), 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/ruoyi-common/src/main/java/com/ruoyi/common/exception/DemoModeException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/DemoModeException.java
new file mode 100644
index 0000000..f6ad2ab
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/DemoModeException.java
@@ -0,0 +1,15 @@
+package com.ruoyi.common.exception;
+
+/**
+ * 演示模式异常
+ * 
+ * @author ruoyi
+ */
+public class DemoModeException extends RuntimeException
+{
+    private static final long serialVersionUID = 1L;
+
+    public DemoModeException()
+    {
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/GlobalException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/GlobalException.java
new file mode 100644
index 0000000..81a71b5
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/GlobalException.java
@@ -0,0 +1,58 @@
+package com.ruoyi.common.exception;
+
+/**
+ * 全局异常
+ * 
+ * @author ruoyi
+ */
+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/ruoyi-common/src/main/java/com/ruoyi/common/exception/ServiceException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/ServiceException.java
new file mode 100644
index 0000000..7f053a3
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/ServiceException.java
@@ -0,0 +1,58 @@
+package com.ruoyi.common.exception;
+
+/**
+ * 业务异常
+ * 
+ * @author ruoyi
+ */
+public final class ServiceException extends RuntimeException
+{
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 错误提示
+     */
+    private String message;
+
+    /**
+     * 错误明细,内部调试错误
+     *
+     * 和 {@link CommonResult#getDetailMessage()} 一致的设计
+     */
+    private String detailMessage;
+
+    /**
+     * 空构造方法,避免反序列化问题
+     */
+    public ServiceException()
+    {
+    }
+
+    public ServiceException(String message)
+    {
+        this.message = message;
+    }
+
+    public String getDetailMessage()
+    {
+        return detailMessage;
+    }
+
+    public ServiceException setDetailMessage(String detailMessage)
+    {
+        this.detailMessage = detailMessage;
+        return this;
+    }
+
+    @Override
+    public String getMessage()
+    {
+        return message;
+    }
+
+    public ServiceException setMessage(String message)
+    {
+        this.message = message;
+        return this;
+    }
+}
\ No newline at end of file
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/UtilException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/UtilException.java
new file mode 100644
index 0000000..980fa46
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/UtilException.java
@@ -0,0 +1,26 @@
+package com.ruoyi.common.exception;
+
+/**
+ * 工具类异常
+ * 
+ * @author ruoyi
+ */
+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/ruoyi-common/src/main/java/com/ruoyi/common/exception/base/BaseException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/base/BaseException.java
new file mode 100644
index 0000000..b55d72e
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/base/BaseException.java
@@ -0,0 +1,97 @@
+package com.ruoyi.common.exception.base;
+
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * 基础异常
+ * 
+ * @author ruoyi
+ */
+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/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileException.java
new file mode 100644
index 0000000..871f09b
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileException.java
@@ -0,0 +1,19 @@
+package com.ruoyi.common.exception.file;
+
+import com.ruoyi.common.exception.base.BaseException;
+
+/**
+ * 文件信息异常类
+ * 
+ * @author ruoyi
+ */
+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/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileNameLengthLimitExceededException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileNameLengthLimitExceededException.java
new file mode 100644
index 0000000..70e0ec9
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileNameLengthLimitExceededException.java
@@ -0,0 +1,16 @@
+package com.ruoyi.common.exception.file;
+
+/**
+ * 文件名称超长限制异常类
+ * 
+ * @author ruoyi
+ */
+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/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileSizeLimitExceededException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileSizeLimitExceededException.java
new file mode 100644
index 0000000..ec6ab05
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileSizeLimitExceededException.java
@@ -0,0 +1,16 @@
+package com.ruoyi.common.exception.file;
+
+/**
+ * 文件名大小限制异常类
+ * 
+ * @author ruoyi
+ */
+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/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileUploadException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileUploadException.java
new file mode 100644
index 0000000..f45e7ef
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileUploadException.java
@@ -0,0 +1,61 @@
+package com.ruoyi.common.exception.file;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+/**
+ * 文件上传异常类
+ * 
+ * @author ruoyi
+ */
+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/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/InvalidExtensionException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/InvalidExtensionException.java
new file mode 100644
index 0000000..b805fc1
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/InvalidExtensionException.java
@@ -0,0 +1,80 @@
+package com.ruoyi.common.exception.file;
+
+import java.util.Arrays;
+
+/**
+ * 文件上传 误异常类
+ * 
+ * @author ruoyi
+ */
+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/ruoyi-common/src/main/java/com/ruoyi/common/exception/job/TaskException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/job/TaskException.java
new file mode 100644
index 0000000..a567b40
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/job/TaskException.java
@@ -0,0 +1,34 @@
+package com.ruoyi.common.exception.job;
+
+/**
+ * 计划策略异常
+ * 
+ * @author ruoyi
+ */
+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/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/BlackListException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/BlackListException.java
new file mode 100644
index 0000000..2bf5038
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/BlackListException.java
@@ -0,0 +1,16 @@
+package com.ruoyi.common.exception.user;
+
+/**
+ * 黑名单IP异常类
+ * 
+ * @author ruoyi
+ */
+public class BlackListException extends UserException
+{
+    private static final long serialVersionUID = 1L;
+
+    public BlackListException()
+    {
+        super("login.blocked", null);
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaException.java
new file mode 100644
index 0000000..389dbc7
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaException.java
@@ -0,0 +1,16 @@
+package com.ruoyi.common.exception.user;
+
+/**
+ * 验证码错误异常类
+ * 
+ * @author ruoyi
+ */
+public class CaptchaException extends UserException
+{
+    private static final long serialVersionUID = 1L;
+
+    public CaptchaException()
+    {
+        super("user.jcaptcha.error", null);
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/RoleBlockedException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/RoleBlockedException.java
new file mode 100644
index 0000000..1c4fd4a
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/RoleBlockedException.java
@@ -0,0 +1,16 @@
+package com.ruoyi.common.exception.user;
+
+/**
+ * 角色锁定异常类
+ * 
+ * @author ruoyi
+ */
+public class RoleBlockedException extends UserException
+{
+    private static final long serialVersionUID = 1L;
+
+    public RoleBlockedException()
+    {
+        super("role.blocked", null);
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserBlockedException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserBlockedException.java
new file mode 100644
index 0000000..5150f52
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserBlockedException.java
@@ -0,0 +1,16 @@
+package com.ruoyi.common.exception.user;
+
+/**
+ * 用户锁定异常类
+ * 
+ * @author ruoyi
+ */
+public class UserBlockedException extends UserException
+{
+    private static final long serialVersionUID = 1L;
+
+    public UserBlockedException()
+    {
+        super("user.blocked", null);
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserDeleteException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserDeleteException.java
new file mode 100644
index 0000000..3520030
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserDeleteException.java
@@ -0,0 +1,16 @@
+package com.ruoyi.common.exception.user;
+
+/**
+ * 用户账号已被删除
+ * 
+ * @author ruoyi
+ */
+public class UserDeleteException extends UserException
+{
+    private static final long serialVersionUID = 1L;
+
+    public UserDeleteException()
+    {
+        super("user.password.delete", null);
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserException.java
new file mode 100644
index 0000000..c292d70
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserException.java
@@ -0,0 +1,18 @@
+package com.ruoyi.common.exception.user;
+
+import com.ruoyi.common.exception.base.BaseException;
+
+/**
+ * 用户信息异常类
+ * 
+ * @author ruoyi
+ */
+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/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserNotExistsException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserNotExistsException.java
new file mode 100644
index 0000000..eff8181
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserNotExistsException.java
@@ -0,0 +1,16 @@
+package com.ruoyi.common.exception.user;
+
+/**
+ * 用户不存在异常类
+ * 
+ * @author ruoyi
+ */
+public class UserNotExistsException extends UserException
+{
+    private static final long serialVersionUID = 1L;
+
+    public UserNotExistsException()
+    {
+        super("user.not.exists", null);
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordNotMatchException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordNotMatchException.java
new file mode 100644
index 0000000..a7f3e5f
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordNotMatchException.java
@@ -0,0 +1,16 @@
+package com.ruoyi.common.exception.user;
+
+/**
+ * 用户密码不正确或不符合规范异常类
+ * 
+ * @author ruoyi
+ */
+public class UserPasswordNotMatchException extends UserException
+{
+    private static final long serialVersionUID = 1L;
+
+    public UserPasswordNotMatchException()
+    {
+        super("user.password.not.match", null);
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordRetryLimitCountException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordRetryLimitCountException.java
new file mode 100644
index 0000000..7ead89b
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordRetryLimitCountException.java
@@ -0,0 +1,16 @@
+package com.ruoyi.common.exception.user;
+
+/**
+ * 用户错误记数异常类
+ * 
+ * @author ruoyi
+ */
+public class UserPasswordRetryLimitCountException extends UserException
+{
+    private static final long serialVersionUID = 1L;
+
+    public UserPasswordRetryLimitCountException(int retryLimitCount)
+    {
+        super("user.password.retry.limit.count", new Object[] { retryLimitCount });
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordRetryLimitExceedException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordRetryLimitExceedException.java
new file mode 100644
index 0000000..b5ccfb9
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordRetryLimitExceedException.java
@@ -0,0 +1,16 @@
+package com.ruoyi.common.exception.user;
+
+/**
+ * 用户错误最大次数异常类
+ * 
+ * @author ruoyi
+ */
+public class UserPasswordRetryLimitExceedException extends UserException
+{
+    private static final long serialVersionUID = 1L;
+
+    public UserPasswordRetryLimitExceedException(int retryLimitCount)
+    {
+        super("user.password.retry.limit.exceed", new Object[] { retryLimitCount });
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/json/JSON.java b/ruoyi-common/src/main/java/com/ruoyi/common/json/JSON.java
new file mode 100644
index 0000000..1e5b928
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/json/JSON.java
@@ -0,0 +1,187 @@
+package com.ruoyi.common.json;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import com.fasterxml.jackson.core.JsonGenerationException;
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.ObjectWriter;
+
+/**
+ * JSON解析处理
+ * 
+ * @author ruoyi
+ */
+public class JSON
+{
+    public static final String DEFAULT_FAIL = "\"Parse failed\"";
+    private static final ObjectMapper objectMapper = new ObjectMapper();
+    private static final ObjectWriter objectWriter = objectMapper.writerWithDefaultPrettyPrinter();
+
+    public static void marshal(File file, Object value) throws Exception
+    {
+        try
+        {
+            objectWriter.writeValue(file, value);
+        }
+        catch (JsonGenerationException e)
+        {
+            throw new Exception(e);
+        }
+        catch (JsonMappingException e)
+        {
+            throw new Exception(e);
+        }
+        catch (IOException e)
+        {
+            throw new Exception(e);
+        }
+    }
+
+    public static void marshal(OutputStream os, Object value) throws Exception
+    {
+        try
+        {
+            objectWriter.writeValue(os, value);
+        }
+        catch (JsonGenerationException e)
+        {
+            throw new Exception(e);
+        }
+        catch (JsonMappingException e)
+        {
+            throw new Exception(e);
+        }
+        catch (IOException e)
+        {
+            throw new Exception(e);
+        }
+    }
+
+    public static String marshal(Object value) throws Exception
+    {
+        try
+        {
+            return objectWriter.writeValueAsString(value);
+        }
+        catch (JsonGenerationException e)
+        {
+            throw new Exception(e);
+        }
+        catch (JsonMappingException e)
+        {
+            throw new Exception(e);
+        }
+        catch (IOException e)
+        {
+            throw new Exception(e);
+        }
+    }
+
+    public static byte[] marshalBytes(Object value) throws Exception
+    {
+        try
+        {
+            return objectWriter.writeValueAsBytes(value);
+        }
+        catch (JsonGenerationException e)
+        {
+            throw new Exception(e);
+        }
+        catch (JsonMappingException e)
+        {
+            throw new Exception(e);
+        }
+        catch (IOException e)
+        {
+            throw new Exception(e);
+        }
+    }
+
+    public static <T> T unmarshal(File file, Class<T> valueType) throws Exception
+    {
+        try
+        {
+            return objectMapper.readValue(file, valueType);
+        }
+        catch (JsonParseException e)
+        {
+            throw new Exception(e);
+        }
+        catch (JsonMappingException e)
+        {
+            throw new Exception(e);
+        }
+        catch (IOException e)
+        {
+            throw new Exception(e);
+        }
+    }
+
+    public static <T> T unmarshal(InputStream is, Class<T> valueType) throws Exception
+    {
+        try
+        {
+            return objectMapper.readValue(is, valueType);
+        }
+        catch (JsonParseException e)
+        {
+            throw new Exception(e);
+        }
+        catch (JsonMappingException e)
+        {
+            throw new Exception(e);
+        }
+        catch (IOException e)
+        {
+            throw new Exception(e);
+        }
+    }
+
+    public static <T> T unmarshal(String str, Class<T> valueType) throws Exception
+    {
+        try
+        {
+            return objectMapper.readValue(str, valueType);
+        }
+        catch (JsonParseException e)
+        {
+            throw new Exception(e);
+        }
+        catch (JsonMappingException e)
+        {
+            throw new Exception(e);
+        }
+        catch (IOException e)
+        {
+            throw new Exception(e);
+        }
+    }
+
+    public static <T> T unmarshal(byte[] bytes, Class<T> valueType) throws Exception
+    {
+        try
+        {
+            if (bytes == null)
+            {
+                bytes = new byte[0];
+            }
+            return objectMapper.readValue(bytes, 0, bytes.length, valueType);
+        }
+        catch (JsonParseException e)
+        {
+            throw new Exception(e);
+        }
+        catch (JsonMappingException e)
+        {
+            throw new Exception(e);
+        }
+        catch (IOException e)
+        {
+            throw new Exception(e);
+        }
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/json/JSONObject.java b/ruoyi-common/src/main/java/com/ruoyi/common/json/JSONObject.java
new file mode 100644
index 0000000..2f4afe7
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/json/JSONObject.java
@@ -0,0 +1,749 @@
+package com.ruoyi.common.json;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * 通用消息对象,基于Map实现的可嵌套数据结构。 支持JSON数据结构。
+ * 
+ * @author ruoyi
+ */
+public class JSONObject extends LinkedHashMap<String, Object>
+{
+    private static final long serialVersionUID = 1L;
+    private static final Pattern arrayNamePattern = Pattern.compile("(\\w+)((\\[\\d+\\])+)");
+    private static final ObjectMapper objectMapper = new ObjectMapper();
+
+    /**
+     * 数组结构。
+     */
+    public static class JSONArray extends ArrayList<Object>
+    {
+        private static final long serialVersionUID = 1L;
+
+        public JSONArray()
+        {
+            super();
+        }
+
+        public JSONArray(int size)
+        {
+            super(size);
+        }
+
+        @Override
+        public String toString()
+        {
+            try
+            {
+                return JSON.marshal(this);
+            }
+            catch (Exception e)
+            {
+                throw new RuntimeException(e);
+            }
+        }
+
+        @Override
+        public Object set(int index, Object element)
+        {
+            return super.set(index, transfer(element));
+        }
+
+        @Override
+        public boolean add(Object element)
+        {
+            return super.add(transfer(element));
+        }
+
+        @Override
+        public void add(int index, Object element)
+        {
+            super.add(index, transfer(element));
+        }
+    }
+
+    public JSONObject()
+    {
+        super();
+    }
+
+    public JSONObject(final JSONObject other)
+    {
+        super(other);
+    }
+
+    @Override
+    public String toString()
+    {
+        try
+        {
+            return JSON.marshal(this);
+        }
+        catch (Exception e)
+        {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * 转换为紧凑格式的字符串。
+     * 
+     * @return 返回本对象紧凑格式字符串。
+     */
+    public String toCompactString()
+    {
+        try
+        {
+            return objectMapper.writeValueAsString(this);
+        }
+        catch (Exception e)
+        {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * 获取指定字段的整数值。如果字段不存在,或者无法转换为整数,返回null。
+     * 
+     * @param name 字段名,支持多级。
+     * @return 返回指定的整数值,或者null。
+     */
+    public Integer intValue(final String name)
+    {
+        return valueAsInt(value(name));
+    }
+
+    /**
+     * 获取指定字段的整数值。如果字段不存在,或者无法转换为整数,返回defaultValue。
+     * 
+     * @param name 字段名,支持多级。
+     * @param defaultValue 查询失败时,返回的值。
+     * @return 返回指定的整数值,或者defaultValue。
+     */
+    public Integer intValue(final String name, final Integer defaultValue)
+    {
+        return StringUtils.nvl(intValue(name), defaultValue);
+    }
+
+    /**
+     * 获取指定字段的长整数值。如果字段不存在,或者无法转换为长整数,返回null。
+     * 
+     * @param name 字段名,支持多级。
+     * @return 返回指定的长整数值,或者null。
+     */
+    public Long longValue(final String name)
+    {
+        return valueAsLong(value(name));
+    }
+
+    /**
+     * 获取指定字段的长整数值。如果字段不存在,或者无法转换为长整数,返回defaultValue。
+     * 
+     * @param name 字段名,支持多级。
+     * @param defaultValue 查询失败时,返回的值。
+     * @return 返回指定的长整数值,或者defaultValue。
+     */
+    public Long longValue(final String name, final Long defaultValue)
+    {
+        return StringUtils.nvl(longValue(name), defaultValue);
+    }
+
+    /**
+     * 获取指定字段的布尔值。如果字段不存在,或者无法转换为布尔型,返回null。
+     * 
+     * @param name 字段名,支持多级。
+     * @return 返回指定的布尔值,或者null。
+     */
+    public Boolean boolValue(final String name)
+    {
+        return valueAsBool(value(name));
+    }
+
+    /**
+     * 获取指定字段的布尔值。如果字段不存在,或者无法转换为布尔型,返回defaultValue。
+     * 
+     * @param name 字段名,支持多级。
+     * @param defaultValue 查询失败时,返回的值。
+     * @return 返回指定的布尔值,或者defaultValue。
+     */
+    public Boolean boolValue(final String name, final Boolean defaultValue)
+    {
+        return StringUtils.nvl(boolValue(name), defaultValue);
+    }
+
+    /**
+     * 获取指定字段的字符串值。如果字段不存在,返回null。
+     * 
+     * @param name 字段名,支持多级。
+     * @return 返回指定的字符串值,或者null。
+     */
+    public String strValue(final String name)
+    {
+        return valueAsStr(value(name));
+    }
+
+    /**
+     * 获取指定字段的字符串值。如果字段不存在,返回defaultValue。
+     * 
+     * @param name 字段名,支持多级。
+     * @param defaultValue 查询失败时,返回的值。
+     * @return 返回指定的字符串值,或者defaultValue。
+     */
+    public String strValue(final String name, final String defaultValue)
+    {
+        return StringUtils.nvl(strValue(name), defaultValue);
+    }
+
+    /**
+     * 获取指定字段的值。
+     * 
+     * @param name 字段名,支持多级,支持数组下标。
+     * @return 返回指定字段的值。
+     */
+    public Object value(final String name)
+    {
+        final int indexDot = name.indexOf('.');
+        if (indexDot >= 0)
+        {
+            return obj(name.substring(0, indexDot)).value(name.substring(indexDot + 1));
+        }
+        else
+        {
+            final Matcher matcher = arrayNamePattern.matcher(name);
+            if (matcher.find())
+            {
+                return endArray(matcher.group(1), matcher.group(2), new EndArrayCallback<Object>()
+                {
+                    @Override
+                    public Object callback(JSONArray arr, int index)
+                    {
+                        return elementAt(arr, index);
+                    }
+                });
+            }
+            else
+            {
+                return get(name);
+            }
+        }
+    }
+
+    /**
+     * 设置指定字段的值。
+     * 
+     * @param name 字段名,支持多级,支持数组下标。
+     * @param value 字段值。
+     * @return 返回本对象。
+     */
+    public JSONObject value(final String name, final Object value)
+    {
+        final int indexDot = name.indexOf('.');
+        if (indexDot >= 0)
+        {
+            obj(name.substring(0, indexDot)).value(name.substring(indexDot + 1), value);
+        }
+        else
+        {
+            final Matcher matcher = arrayNamePattern.matcher(name);
+            if (matcher.find())
+            {
+                endArray(matcher.group(1), matcher.group(2), new EndArrayCallback<Void>()
+                {
+                    @Override
+                    public Void callback(JSONArray arr, int index)
+                    {
+                        elementAt(arr, index, value);
+                        return null;
+                    }
+                });
+            }
+            else
+            {
+                set(name, value);
+            }
+        }
+        return this;
+    }
+
+    /**
+     * 获取对象(非标量类型)字段。返回的数据是一个结构体。当不存在指定对象时,则为指定的名字创建一个空的MessageObject对象。
+     * 
+     * @param name 字段名。不支持多级名字,支持数组下标。
+     * @return 返回指定的对象。如果对象不存在,则为指定的名字创建一个空的MessageObject对象。
+     */
+    public JSONObject obj(final String name)
+    {
+        final Matcher matcher = arrayNamePattern.matcher(name);
+        if (matcher.find())
+        {
+            return endArray(matcher.group(1), matcher.group(2), new EndArrayCallback<JSONObject>()
+            {
+                @Override
+                public JSONObject callback(JSONArray arr, int index)
+                {
+                    return objAt(arr, index);
+                }
+            });
+        }
+        else
+        {
+            JSONObject obj = getObj(name);
+            if (obj == null)
+            {
+                obj = new JSONObject();
+                put(name, obj);
+            }
+            return obj;
+        }
+    }
+
+    /**
+     * 获取数组字段。将名字对应的对象以数组对象返回,当指定的字段不存在时,创建一个空的数组。
+     * 
+     * @param name 字段名。不支持多级名字,不支持下标。
+     * @return 返回一个数组(List)。
+     */
+    public JSONArray arr(final String name)
+    {
+        JSONArray arr = getArr(name);
+        if (arr == null)
+        {
+            arr = new JSONArray();
+            put(name, arr);
+        }
+        return arr;
+    }
+
+    /**
+     * 获取对象(非标量类型)字段。返回的数据是一个结构体。
+     * 
+     * @param name 字段名。
+     * @return 返回指定的对象字段。
+     */
+    public JSONObject getObj(final String name)
+    {
+        return (JSONObject) get(name);
+    }
+
+    /**
+     * 获取数组类型字段。
+     * 
+     * @param name 字段名。
+     * @return 返回数组类型字段。
+     */
+    public JSONArray getArr(final String name)
+    {
+        return (JSONArray) get(name);
+    }
+
+    /**
+     * 返回字段整数值。如果不存在,返回null。
+     * 
+     * @param name 字段名。
+     * @return 返回指定字段整数值。
+     */
+    public Integer getInt(final String name)
+    {
+        return valueAsInt(get(name));
+    }
+
+    /**
+     * 返回字段整数值。如果不存在,返回defaultValue。
+     * 
+     * @param name 字段名。
+     * @param defaultValue 字段不存在时,返回的值。
+     * @return 返回指定字段整数值。
+     */
+    public Integer getInt(final String name, Integer defaultValue)
+    {
+        return StringUtils.nvl(getInt(name), defaultValue);
+    }
+
+    /**
+     * 返回字段长整数值。如果不存在,返回null。
+     * 
+     * @param name 字段名。
+     * @return 返回指定字段长整数值。
+     */
+    public Long getLong(final String name)
+    {
+        return valueAsLong(get(name));
+    }
+
+    /**
+     * 返回字段长整数值。如果不存在,返回defaultValue。
+     * 
+     * @param name 字段名。
+     * @param defaultValue 字段不存在时,返回的值。
+     * @return 返回指定字段长整数值。
+     */
+    public Long getLong(final String name, Long defaultValue)
+    {
+        return StringUtils.nvl(getLong(name), defaultValue);
+    }
+
+    /**
+     * 返回字段字符串值。如果不存在,返回null。
+     * 
+     * @param name 字段名。
+     * @return 返回指定字段字符串值。
+     */
+    public String getStr(final String name)
+    {
+        return valueAsStr(get(name));
+    }
+
+    /**
+     * 返回字段字符串值。如果不存在,返回defaultValue。
+     * 
+     * @param name 字段名。
+     * @param defaultValue 字段不存在时,返回的值。
+     * @return 返回指定字段字符串值。
+     */
+    public String getStr(final String name, final String defaultValue)
+    {
+        return StringUtils.nvl(getStr(name), defaultValue);
+    }
+
+    /**
+     * 字段值按照布尔类型返回。如果不存在,返回null。
+     * 
+     * @param name 字段名。
+     * @return 字段值。
+     */
+    public Boolean getBool(final String name)
+    {
+        return valueAsBool(get(name));
+    }
+
+    /**
+     * 字段值按照布尔类型返回。如果不存在,返回defaultValue。
+     * 
+     * @param name 字段名。
+     * @param defaultValue 字段不存在时,返回的值。
+     * @return 字段值。
+     */
+    public Boolean getBool(final String name, final Boolean defaultValue)
+    {
+        return StringUtils.nvl(getBool(name), defaultValue);
+    }
+
+    /**
+     * 设置字段值
+     * 
+     * @param name 字段名
+     * @param value 字段值(标量:数字、字符串、布尔型;结构体:MessageObject)。 如果是Map类型同时非MessageObject类型,则自动转换为MessageObject类型再存入
+     *            (此时,再修改Map中的数据,将不会体现到本对象中)。
+     * @return 返回本对象
+     */
+    public JSONObject set(final String name, final Object value)
+    {
+        put(name, value);
+        return this;
+    }
+
+    /**
+     * 将本对象转换为Java Bean。
+     * 
+     * @param beanClass Java Bean的类对象。
+     * @return 返回转换后的Java Bean。
+     */
+    public <T> T asBean(Class<T> beanClass)
+    {
+        try
+        {
+            return JSON.unmarshal(JSON.marshal(this), beanClass);
+        }
+        catch (Exception e)
+        {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * 重载基类的方法。如果 value 是 Map 类型,但不是 MessageObject 类型,则创建一个包含内容等同于原 Map 的 MessageObject 作为 value(注意:此后再更改 Map 的内容,将不会反映到
+     * MessageObject 中)。 重载此方法的目的是为了使JSON能够正确地解析为MessageObject对象。不建议直接调用此方法,请使用 set(name, value)方法设置字段值。
+     */
+    @Override
+    public Object put(String key, Object value)
+    {
+        return super.put(key, transfer(value));
+    }
+
+    public static Integer valueAsInt(Object value)
+    {
+        if (value instanceof Integer)
+        {
+            return (Integer) value;
+        }
+        else if (value instanceof Number)
+        {
+            return ((Number) value).intValue();
+        }
+        else if (value instanceof String)
+        {
+            return Integer.valueOf((String) value);
+        }
+        else if (value instanceof Boolean)
+        {
+            return ((Boolean) value) ? 1 : 0;
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+    public static Long valueAsLong(Object value)
+    {
+        if (value instanceof Long)
+        {
+            return (Long) value;
+        }
+        else if (value instanceof Number)
+        {
+            return ((Number) value).longValue();
+        }
+        else if (value instanceof String)
+        {
+            return Long.valueOf((String) value);
+        }
+        else if (value instanceof Boolean)
+        {
+            return ((Boolean) value) ? 1L : 0L;
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+    public static String valueAsStr(Object value)
+    {
+        if (value instanceof String)
+        {
+            return (String) value;
+        }
+        else if (value != null)
+        {
+            return value.toString();
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+    public static Boolean valueAsBool(Object value)
+    {
+        if (value instanceof Boolean)
+        {
+            return (Boolean) value;
+        }
+        else if (value instanceof Number)
+        {
+            return ((Number) value).doubleValue() != 0.0;
+        }
+        else if (value instanceof String)
+        {
+            return Boolean.valueOf((String) value);
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+    /**
+     * 将所有层次中凡是Map类型同时又不是MessageObject的类型,转换为MessageObject类型。
+     * 
+     * @param value 值。
+     * @return 返回转换后的值。
+     */
+    @SuppressWarnings("unchecked")
+    private static Object transfer(final Object value)
+    {
+        if (!(value instanceof JSONObject) && value instanceof Map)
+        {
+            return toObj((Map<String, Object>) value);
+        }
+        else if (!(value instanceof JSONArray) && value instanceof Collection)
+        {
+            return toArr((Collection<Object>) value);
+        }
+        else
+        {
+            return value;
+        }
+    }
+
+    private static JSONArray toArr(final Collection<Object> list)
+    {
+        final JSONArray arr = new JSONArray(list.size());
+        for (final Object element : list)
+        {
+            arr.add(element);
+        }
+        return arr;
+    }
+
+    private static JSONObject toObj(final Map<String, Object> map)
+    {
+        final JSONObject obj = new JSONObject();
+        for (final Map.Entry<String, Object> ent : map.entrySet())
+        {
+            obj.put(ent.getKey(), transfer(ent.getValue()));
+        }
+        return obj;
+    }
+
+    /**
+     * 将指定下标元素作为数组返回,如果不存在,则在该位置创建一个空的数组。
+     * 
+     * @param arr 当前数组。
+     * @param index 下标。
+     * @return 返回当前数组指定下标的元素,该元素应该是一个数组。
+     */
+    private static JSONArray arrayAt(JSONArray arr, int index)
+    {
+        expand(arr, index);
+        if (arr.get(index) == null)
+        {
+            arr.set(index, new JSONArray());
+        }
+        return (JSONArray) arr.get(index);
+    }
+
+    /**
+     * 将指定下标元素作为结构体返回,如果不存在,则在该位置创建一个空的结构体。
+     * 
+     * @param arr 当前数组。
+     * @param index 下标。
+     * @return 返回当前数组指定下标元素,该元素是一个结构体。
+     */
+    private static JSONObject objAt(final JSONArray arr, int index)
+    {
+        expand(arr, index);
+        if (arr.get(index) == null)
+        {
+            arr.set(index, new JSONObject());
+        }
+        return (JSONObject) arr.get(index);
+    }
+
+    /**
+     * 设置数组指定下标位置的值。
+     * 
+     * @param arr 数组。
+     * @param index 下标。
+     * @param value 值。
+     */
+    private static void elementAt(final JSONArray arr, final int index, final Object value)
+    {
+        expand(arr, index).set(index, value);
+    }
+
+    /**
+     * 获取数组指定下标元素的值。
+     * 
+     * @param arr 数组。
+     * @param index 下标。
+     * @return 值。
+     */
+    private static Object elementAt(final JSONArray arr, final int index)
+    {
+        return expand(arr, index).get(index);
+    }
+
+    /**
+     * 扩展数组到指定下标,以防止访问时下标越界。
+     * 
+     * @param arr 数组
+     * @param index 下标
+     * @return 返回传入的数组
+     */
+    private static JSONArray expand(final JSONArray arr, final int index)
+    {
+        while (arr.size() <= index)
+        {
+            arr.add(null);
+        }
+        return arr;
+    }
+
+    /**
+     * 最后数组回调。
+     * 
+     * @author Mike
+     *
+     * @param <T> 回调返回数据类型。
+     */
+    private interface EndArrayCallback<T>
+    {
+        /**
+         * 当定位到最后一级数组,将调用本方法。
+         * 
+         * @param arr 最后一级数组对象。
+         * @param index 最后一级索引。
+         * @return 返回回调的返回值。
+         */
+        T callback(JSONArray arr, int index);
+    }
+
+    /**
+     * 处理多维数组的工具函数(包括一维数组)。多维数组的名字如:arrary[1][2][3], 则name=array,indexStr=[1][2][3],在callback中,endArr将是
+     * array[1][2]指定的对象,indexe=3。
+     * 
+     * @param name 不带下标的名字,不支持多级名字。
+     * @param indexesStr 索引部分的字符串,如:[1][2][3]
+     * @param callback 回调函数。
+     * @return 返回回调函数的返回值。
+     */
+    private <T> T endArray(final String name, final String indexesStr, final EndArrayCallback<T> callback)
+    {
+        JSONArray endArr = arr(name);
+        final int[] indexes = parseIndexes(indexesStr);
+        int i = 0;
+        while (i < indexes.length - 1)
+        {
+            endArr = arrayAt(endArr, indexes[i++]);
+        }
+        return callback.callback(endArr, indexes[i]);
+    }
+
+    private static int[] parseIndexes(final String s)
+    {
+        int[] indexes = null;
+        List<Integer> list = new ArrayList<Integer>();
+
+        final StringTokenizer st = new StringTokenizer(s, "[]");
+        while (st.hasMoreTokens())
+        {
+            final int index = Integer.valueOf(st.nextToken());
+            if (index < 0)
+            {
+                throw new RuntimeException(String.format("Illegal index %1$d in \"%2$s\"", index, s));
+            }
+
+            list.add(index);
+        }
+
+        indexes = new int[list.size()];
+        int i = 0;
+        for (Integer tmp : list.toArray(new Integer[list.size()]))
+        {
+            indexes[i++] = tmp;
+        }
+
+        return indexes;
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/AddressUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/AddressUtils.java
new file mode 100644
index 0000000..9afafc1
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/AddressUtils.java
@@ -0,0 +1,54 @@
+package com.ruoyi.common.utils;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.alibaba.fastjson.JSONObject;
+import com.ruoyi.common.config.RuoYiConfig;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.utils.http.HttpUtils;
+
+/**
+ * 获取地址类
+ * 
+ * @author ruoyi
+ */
+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 (RuoYiConfig.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 = JSONObject.parseObject(rspStr);
+                String region = obj.getString("pro");
+                String city = obj.getString("city");
+                return String.format("%s %s", region, city);
+            }
+            catch (Exception e)
+            {
+                log.error("获取地理位置异常 {}", e);
+            }
+        }
+        return UNKNOWN;
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/Arith.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/Arith.java
new file mode 100644
index 0000000..b6326c2
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/Arith.java
@@ -0,0 +1,114 @@
+package com.ruoyi.common.utils;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+
+/**
+ * 精确的浮点数运算
+ * 
+ * @author ruoyi
+ */
+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);
+    }
+
+    /**
+     * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
+     * 定精度,以后的数字四舍五入。
+     * @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/ruoyi-common/src/main/java/com/ruoyi/common/utils/CacheUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/CacheUtils.java
new file mode 100644
index 0000000..ae27682
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/CacheUtils.java
@@ -0,0 +1,197 @@
+package com.ruoyi.common.utils;
+
+import java.util.Iterator;
+import java.util.Set;
+import org.apache.shiro.cache.Cache;
+import org.apache.shiro.cache.CacheManager;
+import org.apache.shiro.cache.ehcache.EhCacheManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.ruoyi.common.utils.spring.SpringUtils;
+
+/**
+ * Cache工具类
+ * 
+ * @author ruoyi
+ */
+public class CacheUtils
+{
+    private static Logger logger = LoggerFactory.getLogger(CacheUtils.class);
+
+    private static CacheManager cacheManager = SpringUtils.getBean(CacheManager.class);
+
+    private static final String SYS_CACHE = "sys-cache";
+
+    /**
+     * 获取SYS_CACHE缓存
+     * 
+     * @param key
+     * @return
+     */
+    public static Object get(String key)
+    {
+        return get(SYS_CACHE, key);
+    }
+
+    /**
+     * 获取SYS_CACHE缓存
+     * 
+     * @param key
+     * @param defaultValue
+     * @return
+     */
+    public static Object get(String key, Object defaultValue)
+    {
+        Object value = get(key);
+        return value != null ? value : defaultValue;
+    }
+
+    /**
+     * 写入SYS_CACHE缓存
+     * 
+     * @param key
+     * @return
+     */
+    public static void put(String key, Object value)
+    {
+        put(SYS_CACHE, key, value);
+    }
+
+    /**
+     * 从SYS_CACHE缓存中移除
+     * 
+     * @param key
+     * @return
+     */
+    public static void remove(String key)
+    {
+        remove(SYS_CACHE, key);
+    }
+
+    /**
+     * 获取缓存
+     * 
+     * @param cacheName
+     * @param key
+     * @return
+     */
+    public static Object get(String cacheName, String key)
+    {
+        return getCache(cacheName).get(getKey(key));
+    }
+
+    /**
+     * 获取缓存
+     * 
+     * @param cacheName
+     * @param key
+     * @param defaultValue
+     * @return
+     */
+    public static Object get(String cacheName, String key, Object defaultValue)
+    {
+        Object value = get(cacheName, getKey(key));
+        return value != null ? value : defaultValue;
+    }
+
+    /**
+     * 写入缓存
+     * 
+     * @param cacheName
+     * @param key
+     * @param value
+     */
+    public static void put(String cacheName, String key, Object value)
+    {
+        getCache(cacheName).put(getKey(key), value);
+    }
+
+    /**
+     * 从缓存中移除
+     * 
+     * @param cacheName
+     * @param key
+     */
+    public static void remove(String cacheName, String key)
+    {
+        getCache(cacheName).remove(getKey(key));
+    }
+
+    /**
+     * 从缓存中移除所有
+     * 
+     * @param cacheName
+     */
+    public static void removeAll(String cacheName)
+    {
+        Cache<String, Object> cache = getCache(cacheName);
+        Set<String> keys = cache.keys();
+        for (Iterator<String> it = keys.iterator(); it.hasNext();)
+        {
+            cache.remove(it.next());
+        }
+        logger.info("清理缓存: {} => {}", cacheName, keys);
+    }
+
+    /**
+     * 从缓存中移除指定key
+     * 
+     * @param keys
+     */
+    public static void removeByKeys(Set<String> keys)
+    {
+        removeByKeys(SYS_CACHE, keys);
+    }
+
+    /**
+     * 从缓存中移除指定key
+     * 
+     * @param cacheName
+     * @param keys
+     */
+    public static void removeByKeys(String cacheName, Set<String> keys)
+    {
+        for (Iterator<String> it = keys.iterator(); it.hasNext();)
+        {
+            remove(it.next());
+        }
+        logger.info("清理缓存: {} => {}", cacheName, keys);
+    }
+
+    /**
+     * 获取缓存键名
+     * 
+     * @param key
+     * @return
+     */
+    private static String getKey(String key)
+    {
+        return key;
+    }
+
+    /**
+     * 获得一个Cache,没有则显示日志。
+     * 
+     * @param cacheName
+     * @return
+     */
+    public static Cache<String, Object> getCache(String cacheName)
+    {
+        Cache<String, Object> cache = cacheManager.getCache(cacheName);
+        if (cache == null)
+        {
+            throw new RuntimeException("当前系统中没有定义“" + cacheName + "”这个缓存。");
+        }
+        return cache;
+    }
+
+    /**
+     * 获取所有缓存
+     * 
+     * @return 缓存组
+     */
+    public static String[] getCacheNames()
+    {
+        return ((EhCacheManager) cacheManager).getCacheManager().getCacheNames();
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/CookieUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/CookieUtils.java
new file mode 100644
index 0000000..4fa8339
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/CookieUtils.java
@@ -0,0 +1,138 @@
+package com.ruoyi.common.utils;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Cookie工具类
+ * 
+ * @author ruoyi
+ */
+public class CookieUtils
+{
+    /**
+     * 设置 Cookie(生成时间为1天)
+     * 
+     * @param name 名称
+     * @param value 值
+     */
+    public static void setCookie(HttpServletResponse response, String name, String value)
+    {
+        setCookie(response, name, value, 60 * 60 * 24);
+    }
+
+    /**
+     * 设置 Cookie
+     * 
+     * @param name 名称
+     * @param value 值
+     * @param maxAge 生存时间(单位秒)
+     * @param uri 路径
+     */
+    public static void setCookie(HttpServletResponse response, String name, String value, String path)
+    {
+        setCookie(response, name, value, path, 60 * 60 * 24);
+    }
+
+    /**
+     * 设置 Cookie
+     * 
+     * @param name 名称
+     * @param value 值
+     * @param maxAge 生存时间(单位秒)
+     * @param uri 路径
+     */
+    public static void setCookie(HttpServletResponse response, String name, String value, int maxAge)
+    {
+        setCookie(response, name, value, "/", maxAge);
+    }
+
+    /**
+     * 设置 Cookie
+     * 
+     * @param name 名称
+     * @param value 值
+     * @param maxAge 生存时间(单位秒)
+     * @param uri 路径
+     */
+    public static void setCookie(HttpServletResponse response, String name, String value, String path, int maxAge)
+    {
+        Cookie cookie = new Cookie(name, null);
+        cookie.setPath(path);
+        cookie.setMaxAge(maxAge);
+        try
+        {
+            cookie.setValue(URLEncoder.encode(value, "utf-8"));
+        }
+        catch (UnsupportedEncodingException e)
+        {
+            e.printStackTrace();
+        }
+        response.addCookie(cookie);
+    }
+
+    /**
+     * 获得指定Cookie的值
+     * 
+     * @param name 名称
+     * @return 值
+     */
+    public static String getCookie(HttpServletRequest request, String name)
+    {
+        return getCookie(request, null, name, false);
+    }
+
+    /**
+     * 获得指定Cookie的值,并删除。
+     * 
+     * @param name 名称
+     * @return 值
+     */
+    public static String getCookie(HttpServletRequest request, HttpServletResponse response, String name)
+    {
+        return getCookie(request, response, name, true);
+    }
+
+    /**
+     * 获得指定Cookie的值
+     * 
+     * @param request 请求对象
+     * @param response 响应对象
+     * @param name 名字
+     * @param isRemove 是否移除
+     * @return 值
+     */
+    public static String getCookie(HttpServletRequest request, HttpServletResponse response, String name,
+            boolean isRemove)
+    {
+        String value = null;
+        Cookie[] cookies = request.getCookies();
+        if (cookies != null)
+        {
+            for (Cookie cookie : cookies)
+            {
+                if (cookie.getName().equals(name))
+                {
+                    try
+                    {
+                        value = URLDecoder.decode(cookie.getValue(), "utf-8");
+                    }
+                    catch (UnsupportedEncodingException e)
+                    {
+                        e.printStackTrace();
+                    }
+                    if (isRemove)
+                    {
+                        cookie.setMaxAge(0);
+                        response.addCookie(cookie);
+                    }
+                }
+            }
+        }
+        return value;
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java
new file mode 100644
index 0000000..fb2ae21
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java
@@ -0,0 +1,191 @@
+package com.ruoyi.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 ruoyi
+ */
+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();
+    }
+
+    /**
+     * 获取当前日期, 默认格式为yyyy-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/ruoyi-common/src/main/java/com/ruoyi/common/utils/DesensitizedUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DesensitizedUtil.java
new file mode 100644
index 0000000..f8a4c02
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DesensitizedUtil.java
@@ -0,0 +1,49 @@
+package com.ruoyi.common.utils;
+
+/**
+ * 脱敏工具类
+ *
+ * @author ruoyi
+ */
+public class DesensitizedUtil
+{
+    /**
+     * 密码的全部字符都用*代替,比如:******
+     *
+     * @param password 密码
+     * @return 脱敏后的密码
+     */
+    public static String password(String password)
+    {
+        if (StringUtils.isBlank(password))
+        {
+            return StringUtils.EMPTY;
+        }
+        return StringUtils.repeat('*', password.length());
+    }
+
+    /**
+     * 车牌中间用*代替,如果是错误的车牌,不处理
+     *
+     * @param carLicense 完整的车牌号
+     * @return 脱敏后的车牌
+     */
+    public static String carLicense(String carLicense)
+    {
+        if (StringUtils.isBlank(carLicense))
+        {
+            return StringUtils.EMPTY;
+        }
+        // 普通车牌
+        if (carLicense.length() == 7)
+        {
+            carLicense = StringUtils.hide(carLicense, 3, 6);
+        }
+        else if (carLicense.length() == 8)
+        {
+            // 新能源车牌
+            carLicense = StringUtils.hide(carLicense, 3, 7);
+        }
+        return carLicense;
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java
new file mode 100644
index 0000000..ad0dd54
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java
@@ -0,0 +1,246 @@
+package com.ruoyi.common.utils;
+
+import java.util.List;
+import org.springframework.stereotype.Component;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.core.domain.entity.SysDictData;
+
+/**
+ * 字典工具类
+ * 
+ * @author ruoyi
+ */
+@Component
+public class DictUtils
+{
+    /**
+     * 分隔符
+     */
+    public static final String SEPARATOR = ",";
+
+    /**
+     * 设置字典缓存
+     * 
+     * @param key 参数键
+     * @param dictDatas 字典数据列表
+     */
+    public static void setDictCache(String key, List<SysDictData> dictDatas)
+    {
+        CacheUtils.put(getCacheName(), getCacheKey(key), dictDatas);
+    }
+
+    /**
+     * 获取字典缓存
+     * 
+     * @param key 参数键
+     * @return dictDatas 字典数据列表
+     */
+    public static List<SysDictData> getDictCache(String key)
+    {
+        Object cacheObj = CacheUtils.get(getCacheName(), getCacheKey(key));
+        if (StringUtils.isNotNull(cacheObj))
+        {
+            return StringUtils.cast(cacheObj);
+        }
+        return null;
+    }
+
+    /**
+     * 根据字典类型和字典值获取字典标签
+     * 
+     * @param dictType 字典类型
+     * @param dictValue 字典值
+     * @return 字典标签
+     */
+    public static String getDictLabel(String dictType, String dictValue)
+    {
+        if (StringUtils.isEmpty(dictValue))
+        {
+            return StringUtils.EMPTY;
+        }
+        return getDictLabel(dictType, dictValue, SEPARATOR);
+    }
+
+    /**
+     * 根据字典类型和字典标签获取字典值
+     * 
+     * @param dictType 字典类型
+     * @param dictLabel 字典标签
+     * @return 字典值
+     */
+    public static String getDictValue(String dictType, String dictLabel)
+    {
+        if (StringUtils.isEmpty(dictLabel))
+        {
+            return StringUtils.EMPTY;
+        }
+        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.isNull(datas))
+        {
+            return StringUtils.EMPTY;
+        }
+        if (StringUtils.containsAny(dictValue, separator))
+        {
+            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.isNull(datas))
+        {
+            return StringUtils.EMPTY;
+        }
+        if (StringUtils.containsAny(dictLabel, separator))
+        {
+            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 dictType 字典类型
+     * @return 字典值
+     */
+    public static String getDictValues(String dictType)
+    {
+        StringBuilder propertyString = new StringBuilder();
+        List<SysDictData> datas = getDictCache(dictType);
+        if (StringUtils.isNull(datas))
+        {
+            return StringUtils.EMPTY;
+        }
+        for (SysDictData dict : datas)
+        {
+            propertyString.append(dict.getDictValue()).append(SEPARATOR);
+        }
+        return StringUtils.stripEnd(propertyString.toString(), SEPARATOR);
+    }
+
+    /**
+     * 根据字典类型获取字典所有标签
+     *
+     * @param dictType 字典类型
+     * @return 字典值
+     */
+    public static String getDictLabels(String dictType)
+    {
+        StringBuilder propertyString = new StringBuilder();
+        List<SysDictData> datas = getDictCache(dictType);
+        if (StringUtils.isNull(datas))
+        {
+            return StringUtils.EMPTY;
+        }
+        for (SysDictData dict : datas)
+        {
+            propertyString.append(dict.getDictLabel()).append(SEPARATOR);
+        }
+        return StringUtils.stripEnd(propertyString.toString(), SEPARATOR);
+    }
+
+    /**
+     * 删除指定字典缓存
+     * 
+     * @param key 字典键
+     */
+    public static void removeDictCache(String key)
+    {
+        CacheUtils.remove(getCacheName(), getCacheKey(key));
+    }
+
+    /**
+     * 清空字典缓存
+     */
+    public static void clearDictCache()
+    {
+        CacheUtils.removeAll(getCacheName());
+    }
+
+    /**
+     * 获取cache name
+     * 
+     * @return 缓存名
+     */
+    public static String getCacheName()
+    {
+        return Constants.SYS_DICT_CACHE;
+    }
+
+    /**
+     * 设置cache key
+     * 
+     * @param configKey 参数键
+     * @return 缓存键key
+     */
+    public static String getCacheKey(String configKey)
+    {
+        return Constants.SYS_DICT_KEY + configKey;
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/ExceptionUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ExceptionUtil.java
new file mode 100644
index 0000000..a62600f
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ExceptionUtil.java
@@ -0,0 +1,67 @@
+package com.ruoyi.common.utils;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import org.apache.commons.lang3.exception.ExceptionUtils;
+
+/**
+ * 错误信息处理类。
+ *
+ * @author ruoyi
+ */
+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);
+    }
+
+    /**
+     * 检测异常e被触发的原因是不是因为异常cause。
+     * 
+     * @param e 捕获的异常。
+     * @param cause 异常触发原因。
+     * @return 如果异常e是由cause类异常触发,则返回true;否则返回false。
+     */
+    public static boolean isCausedBy(final Throwable e, final Class<? extends Throwable> cause)
+    {
+        if (cause.isAssignableFrom(e.getClass()))
+        {
+            return true;
+        }
+        else
+        {
+            Throwable t = e.getCause();
+            while (t != null && t != e)
+            {
+                if (cause.isAssignableFrom(t.getClass()))
+                {
+                    return true;
+                }
+                t = t.getCause();
+            }
+            return false;
+        }
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/IpUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/IpUtils.java
new file mode 100644
index 0000000..8fde230
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/IpUtils.java
@@ -0,0 +1,370 @@
+package com.ruoyi.common.utils;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * 获取IP方法
+ * 
+ * @author ruoyi
+ */
+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 + ")";
+
+    /**
+     * 获取客户端IP
+     * 
+     * @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;
+        }
+    }
+
+    /**
+     * 将IPv4地址转换成字节
+     * 
+     * @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 获得的IP地址
+     * @return 第一个非unknown IP地址
+     */
+    public static String getMultistageReverseProxyIp(String ip)
+    {
+        // 多级反向代理检测
+        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);
+    }
+
+    /**
+     * 检测给定字符串是否为未知,多用于检测HTTP请求相关
+     *
+     * @param checkString 被检测的字符串
+     * @return 是否未知
+     */
+    public static boolean isUnknown(String checkString)
+    {
+        return StringUtils.isBlank(checkString) || "unknown".equalsIgnoreCase(checkString);
+    }
+
+    /**
+     * 是否为IP
+     */
+    public static boolean isIP(String ip)
+    {
+        return StringUtils.isNotBlank(ip) && ip.matches(REGX_IP);
+    }
+
+    /**
+     * 是否为IP,或 *为间隔的通配符地址
+     */
+    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/ruoyi-common/src/main/java/com/ruoyi/common/utils/LogUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/LogUtils.java
new file mode 100644
index 0000000..a0e7d6c
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/LogUtils.java
@@ -0,0 +1,135 @@
+package com.ruoyi.common.utils;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Map;
+import javax.servlet.http.HttpServletRequest;
+import org.apache.shiro.SecurityUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.ruoyi.common.json.JSON;
+
+/**
+ * 处理并记录日志文件
+ * 
+ * @author ruoyi
+ */
+public class LogUtils
+{
+    public static final Logger ERROR_LOG = LoggerFactory.getLogger("sys-error");
+    public static final Logger ACCESS_LOG = LoggerFactory.getLogger("sys-access");
+
+    /**
+     * 记录访问日志 [username][jsessionid][ip][accept][UserAgent][url][params][Referer]
+     *
+     * @param request
+     * @throws Exception
+     */
+    public static void logAccess(HttpServletRequest request) throws Exception
+    {
+        String username = getUsername();
+        String jsessionId = request.getRequestedSessionId();
+        String ip = IpUtils.getIpAddr(request);
+        String accept = request.getHeader("accept");
+        String userAgent = request.getHeader("User-Agent");
+        String url = request.getRequestURI();
+        String params = getParams(request);
+
+        StringBuilder s = new StringBuilder();
+        s.append(getBlock(username));
+        s.append(getBlock(jsessionId));
+        s.append(getBlock(ip));
+        s.append(getBlock(accept));
+        s.append(getBlock(userAgent));
+        s.append(getBlock(url));
+        s.append(getBlock(params));
+        s.append(getBlock(request.getHeader("Referer")));
+        getAccessLog().info(s.toString());
+    }
+
+    /**
+     * 记录异常错误 格式 [exception]
+     *
+     * @param message
+     * @param e
+     */
+    public static void logError(String message, Throwable e)
+    {
+        String username = getUsername();
+        StringBuilder s = new StringBuilder();
+        s.append(getBlock("exception"));
+        s.append(getBlock(username));
+        s.append(getBlock(message));
+        ERROR_LOG.error(s.toString(), e);
+    }
+
+    /**
+     * 记录页面错误 错误日志记录 [page/eception][username][statusCode][errorMessage][servletName][uri][exceptionName][ip][exception]
+     *
+     * @param request
+     */
+    public static void logPageError(HttpServletRequest request)
+    {
+        String username = getUsername();
+
+        Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
+        String message = (String) request.getAttribute("javax.servlet.error.message");
+        String uri = (String) request.getAttribute("javax.servlet.error.request_uri");
+        Throwable t = (Throwable) request.getAttribute("javax.servlet.error.exception");
+
+        if (statusCode == null)
+        {
+            statusCode = 0;
+        }
+
+        StringBuilder s = new StringBuilder();
+        s.append(getBlock(t == null ? "page" : "exception"));
+        s.append(getBlock(username));
+        s.append(getBlock(statusCode));
+        s.append(getBlock(message));
+        s.append(getBlock(IpUtils.getIpAddr(request)));
+
+        s.append(getBlock(uri));
+        s.append(getBlock(request.getHeader("Referer")));
+        StringWriter sw = new StringWriter();
+
+        while (t != null)
+        {
+            t.printStackTrace(new PrintWriter(sw));
+            t = t.getCause();
+        }
+        s.append(getBlock(sw.toString()));
+        getErrorLog().error(s.toString());
+
+    }
+
+    public static String getBlock(Object msg)
+    {
+        if (msg == null)
+        {
+            msg = "";
+        }
+        return "[" + msg.toString() + "]";
+    }
+
+    protected static String getParams(HttpServletRequest request) throws Exception
+    {
+        Map<String, String[]> params = request.getParameterMap();
+        return JSON.marshal(params);
+    }
+
+    protected static String getUsername()
+    {
+        return (String) SecurityUtils.getSubject().getPrincipal();
+    }
+
+    public static Logger getAccessLog()
+    {
+        return ACCESS_LOG;
+    }
+
+    public static Logger getErrorLog()
+    {
+        return ERROR_LOG;
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/MapDataUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/MapDataUtil.java
new file mode 100644
index 0000000..d932bfe
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/MapDataUtil.java
@@ -0,0 +1,54 @@
+package com.ruoyi.common.utils;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Map通用处理方法
+ * 
+ * @author ruoyi
+ */
+public class MapDataUtil
+{
+    public static Map<String, Object> convertDataMap(HttpServletRequest request)
+    {
+        Map<String, String[]> properties = request.getParameterMap();
+        Map<String, Object> returnMap = new HashMap<String, Object>();
+        Iterator<?> entries = properties.entrySet().iterator();
+        Map.Entry<?, ?> entry;
+        String name = "";
+        String value = "";
+        while (entries.hasNext())
+        {
+            entry = (Entry<?, ?>) entries.next();
+            name = (String) entry.getKey();
+            Object valueObj = entry.getValue();
+            if (null == valueObj)
+            {
+                value = "";
+            }
+            else if (valueObj instanceof String[])
+            {
+                String[] values = (String[]) valueObj;
+                value = "";
+                for (int i = 0; i < values.length; i++)
+                {
+                    value += values[i] + ",";
+                }
+                if (value.length() > 0)
+                {
+                    value = value.substring(0, value.length() - 1);
+                }
+            }
+            else
+            {
+                value = valueObj.toString();
+            }
+            returnMap.put(name, value);
+        }
+        return returnMap;
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/MessageUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/MessageUtils.java
new file mode 100644
index 0000000..7dac75a
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/MessageUtils.java
@@ -0,0 +1,26 @@
+package com.ruoyi.common.utils;
+
+import org.springframework.context.MessageSource;
+import org.springframework.context.i18n.LocaleContextHolder;
+import com.ruoyi.common.utils.spring.SpringUtils;
+
+/**
+ * 获取i18n资源文件
+ * 
+ * @author ruoyi
+ */
+public class MessageUtils
+{
+    /**
+     * 根据消息键和参数 获取消息 委托给spring 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/ruoyi-common/src/main/java/com/ruoyi/common/utils/PageUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/PageUtils.java
new file mode 100644
index 0000000..70e9b08
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/PageUtils.java
@@ -0,0 +1,35 @@
+package com.ruoyi.common.utils;
+
+import com.github.pagehelper.PageHelper;
+import com.ruoyi.common.core.page.PageDomain;
+import com.ruoyi.common.core.page.TableSupport;
+import com.ruoyi.common.utils.sql.SqlUtil;
+
+/**
+ * 分页工具类
+ * 
+ * @author ruoyi
+ */
+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/ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java
new file mode 100644
index 0000000..1f136ec
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java
@@ -0,0 +1,216 @@
+package com.ruoyi.common.utils;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+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.ruoyi.common.constant.Constants;
+import com.ruoyi.common.core.text.Convert;
+
+/**
+ * 客户端工具类
+ * 
+ * @author ruoyi
+ */
+public class ServletUtils
+{
+    /**
+     * 定义移动端请求的所有可能类型
+     */
+    private final static String[] agent = { "Android", "iPhone", "iPod", "iPad", "Windows Phone", "MQQBrowser" };
+
+    /**
+     * 获取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);
+    }
+
+    /**
+     * 获取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 待渲染的字符串
+     * @return null
+     */
+    public static String renderString(HttpServletResponse response, String string)
+    {
+        try
+        {
+            response.setContentType("application/json");
+            response.setCharacterEncoding("utf-8");
+            response.getWriter().print(string);
+        }
+        catch (IOException e)
+        {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    /**
+     * 是否是Ajax异步请求
+     * 
+     * @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");
+    }
+
+    /**
+     * 判断User-Agent 是不是来自于手机
+     */
+    public static boolean checkAgentIsMobile(String ua)
+    {
+        boolean flag = false;
+        if (!ua.contains("Windows NT") || (ua.contains("Windows NT") && ua.contains("compatible; MSIE 9.0;")))
+        {
+            // 排除 苹果桌面系统
+            if (!ua.contains("Windows NT") && !ua.contains("Macintosh"))
+            {
+                for (String item : agent)
+                {
+                    if (ua.contains(item))
+                    {
+                        flag = true;
+                        break;
+                    }
+                }
+            }
+        }
+        return flag;
+    }
+
+    /**
+     * 内容编码
+     * 
+     * @param str 内容
+     * @return 编码后的内容
+     */
+    public static String urlEncode(String str)
+    {
+        try
+        {
+            return URLEncoder.encode(str, Constants.UTF8);
+        }
+        catch (UnsupportedEncodingException e)
+        {
+            return StringUtils.EMPTY;
+        }
+    }
+
+    /**
+     * 内容解码
+     * 
+     * @param str 内容
+     * @return 解码后的内容
+     */
+    public static String urlDecode(String str)
+    {
+        try
+        {
+            return URLDecoder.decode(str, Constants.UTF8);
+        }
+        catch (UnsupportedEncodingException e)
+        {
+            return StringUtils.EMPTY;
+        }
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/ShiroUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ShiroUtils.java
new file mode 100644
index 0000000..23d266e
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ShiroUtils.java
@@ -0,0 +1,86 @@
+package com.ruoyi.common.utils;
+
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.crypto.SecureRandomNumberGenerator;
+import org.apache.shiro.session.Session;
+import org.apache.shiro.subject.Subject;
+import org.apache.shiro.subject.PrincipalCollection;
+import org.apache.shiro.subject.SimplePrincipalCollection;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.utils.bean.BeanUtils;
+
+/**
+ * shiro 工具类
+ * 
+ * @author ruoyi
+ */
+public class ShiroUtils
+{
+    public static Subject getSubject()
+    {
+        return SecurityUtils.getSubject();
+    }
+
+    public static Session getSession()
+    {
+        return SecurityUtils.getSubject().getSession();
+    }
+
+    public static void logout()
+    {
+        getSubject().logout();
+    }
+
+    public static SysUser getSysUser()
+    {
+        SysUser user = null;
+        Object obj = getSubject().getPrincipal();
+        if (StringUtils.isNotNull(obj))
+        {
+            user = new SysUser();
+            BeanUtils.copyBeanProp(user, obj);
+        }
+        return user;
+    }
+
+    public static void setSysUser(SysUser user)
+    {
+        Subject subject = getSubject();
+        PrincipalCollection principalCollection = subject.getPrincipals();
+        String realmName = principalCollection.getRealmNames().iterator().next();
+        PrincipalCollection newPrincipalCollection = new SimplePrincipalCollection(user, realmName);
+        // 重新加载Principal
+        subject.runAs(newPrincipalCollection);
+    }
+
+    public static Long getUserId()
+    {
+        return getSysUser().getUserId().longValue();
+    }
+
+    public static String getLoginName()
+    {
+        return getSysUser().getLoginName();
+    }
+
+    public static String getIp()
+    {
+        return StringUtils.substring(getSubject().getSession().getHost(), 0, 128);
+    }
+
+    public static String getSessionId()
+    {
+        return String.valueOf(getSubject().getSession().getId());
+    }
+
+    /**
+     * 生成随机盐
+     */
+    public static String randomSalt()
+    {
+        // 一个Byte占两个字节,此处生成的3字节,字符串长度为6
+        SecureRandomNumberGenerator secureRandom = new SecureRandomNumberGenerator();
+        String hex = secureRandom.nextBytes(3).toHex();
+        return hex;
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java
new file mode 100644
index 0000000..942d276
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java
@@ -0,0 +1,676 @@
+package com.ruoyi.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.ruoyi.common.constant.Constants;
+import com.ruoyi.common.core.text.StrFormatter;
+
+/**
+ * 字符串工具类
+ * 
+ * @author ruoyi
+ */
+public class StringUtils extends org.apache.commons.lang3.StringUtils
+{
+    /** 空字符串 */
+    private static final String NULLSTR = "";
+
+    /** 下划线 */
+    private static final char SEPARATOR = '_';
+
+    /** 星号 */
+    private static final char ASTERISK = '*';
+
+    /**
+     * 获取参数不为空值
+     * 
+     * @param value defaultValue 要判断的value
+     * @return value 返回值
+     */
+    public static <T> T nvl(T value, T defaultValue)
+    {
+        return value != null ? value : defaultValue;
+    }
+
+    /**
+     * * 判断一个Collection是否为空, 包含List,Set,Queue
+     * 
+     * @param coll 要判断的Collection
+     * @return true:为空 false:非空
+     */
+    public static boolean isEmpty(Collection<?> coll)
+    {
+        return isNull(coll) || coll.isEmpty();
+    }
+
+    /**
+     * * 判断一个Collection是否非空,包含List,Set,Queue
+     * 
+     * @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);
+    }
+
+    /**
+     * * 判断一个Map是否为空
+     * 
+     * @param map 要判断的Map
+     * @return true:为空 false:非空
+     */
+    public static boolean isEmpty(Map<?, ?> map)
+    {
+        return isNull(map) || map.isEmpty();
+    }
+
+    /**
+     * * 判断一个Map是否为空
+     * 
+     * @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);
+    }
+
+    /**
+     * * 判断一个对象是否是数组类型(Java基本型别的数组)
+     * 
+     * @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 startInclude 开始位置(包含)
+     * @param endExclude 结束位置(不包含)
+     * @return 替换后的字符串
+     */
+    public static String hide(CharSequence str, int startInclude, int endExclude)
+    {
+        if (isEmpty(str))
+        {
+            return NULLSTR;
+        }
+        final int strLength = str.length();
+        if (startInclude > strLength)
+        {
+            return NULLSTR;
+        }
+        if (endExclude > strLength)
+        {
+            endExclude = strLength;
+        }
+        if (startInclude > endExclude)
+        {
+            // 如果起始位置大于结束位置,不替换
+            return NULLSTR;
+        }
+        final char[] chars = new char[strLength];
+        for (int i = 0; i < strLength; i++)
+        {
+            if (i >= startInclude && i < endExclude)
+            {
+                chars[i] = ASTERISK;
+            }
+            else
+            {
+                chars[i] = str.charAt(i);
+            }
+        }
+        return new String(chars);
+    }
+
+    /**
+     * 截取字符串
+     * 
+     * @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);
+    }
+
+    /**
+     * 格式化文本, {} 表示占位符<br>
+     * 此方法只是简单将占位符 {} 按照顺序替换为参数<br>
+     * 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br>
+     * 例:<br>
+     * 通常使用:format("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);
+    }
+
+    /**
+     * 是否为http(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;
+    }
+
+    /**
+     * 判断给定的collection列表中是否包含数组array 判断给定的数组array中是否包含给定的元素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;
+    }
+
+    /**
+     * 删除最后一个字符串
+     *
+     * @param str 输入字符串
+     * @param spit 以什么类型结尾的
+     * @return 截取后的字符串
+     */
+    public static String lastStringDel(String str, String spit)
+    {
+        if (!StringUtils.isEmpty(str) && str.endsWith(spit))
+        {
+            return str.subSequence(0, str.length() - 1).toString();
+        }
+        return str;
+    }
+
+    /**
+     * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 例如:HELLO_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();
+    }
+
+    /**
+     * 驼峰式命名法
+     * 例如:user_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,则只保留 最后size个字符。
+     * 
+     * @param num 数字对象
+     * @param size 字符串指定长度
+     * @return 返回数字的字符串格式,该字符串为指定长度。
+     */
+    public static final String padl(final Number num, final int size)
+    {
+        return padl(num.toString(), size, '0');
+    }
+
+    /**
+     * 字符串左补齐。如果原始字符串s长度大于size,则只保留最后size个字符。
+     * 
+     * @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();
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/Threads.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/Threads.java
new file mode 100644
index 0000000..1934195
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/Threads.java
@@ -0,0 +1,99 @@
+package com.ruoyi.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 ruoyi
+ */
+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;
+        }
+    }
+
+    /**
+     * 停止线程池
+     * 先使用shutdown, 停止接收新任务并尝试完成所有已存在任务.
+     * 如果超时, 则调用shutdownNow, 取消在workQueue中Pending的任务,并中断所有阻塞函数.
+     * 如果仍人超時,則強制退出.
+     * 另对在shutdown时线程本身被调用中断做了处理.
+     */
+    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/ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanUtils.java
new file mode 100644
index 0000000..4463662
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanUtils.java
@@ -0,0 +1,110 @@
+package com.ruoyi.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 ruoyi
+ */
+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();
+        }
+    }
+
+    /**
+     * 获取对象的setter方法。
+     * 
+     * @param obj 对象
+     * @return 对象的setter方法列表
+     */
+    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;
+    }
+
+    /**
+     * 获取对象的getter方法。
+     * 
+     * @param obj 对象
+     * @return 对象的getter方法列表
+     */
+
+    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;
+    }
+
+    /**
+     * 检查Bean方法名中的属性名是否相等。<br>
+     * 如getName()和setName()属性名一样,getName()和setAge()属性名不一样。
+     * 
+     * @param m1 方法名1
+     * @param m2 方法名2
+     * @return 属性名一样返回true,否则返回false
+     */
+
+    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/ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanValidators.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanValidators.java
new file mode 100644
index 0000000..80bfed7
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanValidators.java
@@ -0,0 +1,24 @@
+package com.ruoyi.common.utils.bean;
+
+import java.util.Set;
+import javax.validation.ConstraintViolation;
+import javax.validation.ConstraintViolationException;
+import javax.validation.Validator;
+
+/**
+ * bean对象属性验证
+ * 
+ * @author ruoyi
+ */
+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/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileTypeUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileTypeUtils.java
new file mode 100644
index 0000000..68130b9
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileTypeUtils.java
@@ -0,0 +1,76 @@
+package com.ruoyi.common.utils.file;
+
+import java.io.File;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * 文件类型工具类
+ *
+ * @author ruoyi
+ */
+public class FileTypeUtils
+{
+    /**
+     * 获取文件类型
+     * <p>
+     * 例如: ruoyi.txt, 返回: txt
+     * 
+     * @param file 文件名
+     * @return 后缀(不含".")
+     */
+    public static String getFileType(File file)
+    {
+        if (null == file)
+        {
+            return StringUtils.EMPTY;
+        }
+        return getFileType(file.getName());
+    }
+
+    /**
+     * 获取文件类型
+     * <p>
+     * 例如: ruoyi.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/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java
new file mode 100644
index 0000000..b65418e
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java
@@ -0,0 +1,232 @@
+package com.ruoyi.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.ruoyi.common.config.RuoYiConfig;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.exception.file.FileNameLengthLimitExceededException;
+import com.ruoyi.common.exception.file.FileSizeLimitExceededException;
+import com.ruoyi.common.exception.file.InvalidExtensionException;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.uuid.Seq;
+
+/**
+ * 文件上传工具类
+ * 
+ * @author ruoyi
+ */
+public class FileUploadUtils
+{
+    /**
+     * 默认大小 50M
+     */
+    public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024L;
+
+    /**
+     * 默认的文件名最大长度 100
+     */
+    public static final int DEFAULT_FILE_NAME_LENGTH = 100;
+
+    /**
+     * 默认上传的地址
+     */
+    private static String defaultBaseDir = RuoYiConfig.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 = RuoYiConfig.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;
+    }
+}
\ No newline at end of file
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java
new file mode 100644
index 0000000..62f0c62
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java
@@ -0,0 +1,291 @@
+package com.ruoyi.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.FilenameUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.ArrayUtils;
+import com.ruoyi.common.config.RuoYiConfig;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.uuid.IdUtils;
+
+/**
+ * 文件处理工具类
+ * 
+ * @author ruoyi
+ */
+public class FileUtils
+{
+    public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+";
+
+    /**
+     * 输出指定文件的byte数组
+     * 
+     * @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, RuoYiConfig.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 正常 false 非法
+     */
+    public static boolean isValidFilename(String filename)
+    {
+        return filename.matches(FILENAME_PATTERN);
+    }
+
+    /**
+     * 检查文件是否可下载
+     * 
+     * @param resource 需要下载的文件
+     * @return true 正常 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 真实文件名
+     * @return
+     */
+    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.setHeader("Content-disposition", contentDispositionValue.toString());
+    }
+
+    /**
+     * 百分号编码工具方法
+     *
+     * @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/ruoyi.png -- ruoyi.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/ruoyi.png -- ruoyi
+     * 
+     * @param fileName 路径名称
+     * @return 没有文件路径和后缀的名称
+     */
+    public static String getNameNotSuffix(String fileName)
+    {
+        if (fileName == null)
+        {
+            return null;
+        }
+        String baseName = FilenameUtils.getBaseName(fileName);
+        return baseName;
+    }
+}
+
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/ImageUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/ImageUtils.java
new file mode 100644
index 0000000..432dfda
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/ImageUtils.java
@@ -0,0 +1,98 @@
+package com.ruoyi.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.ruoyi.common.config.RuoYiConfig;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * 图片处理工具类
+ *
+ * @author ruoyi
+ */
+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 = RuoYiConfig.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/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/MimeTypeUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/MimeTypeUtils.java
new file mode 100644
index 0000000..371e823
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/MimeTypeUtils.java
@@ -0,0 +1,59 @@
+package com.ruoyi.common.utils.file;
+
+/**
+ * 媒体类型工具类
+ * 
+ * @author ruoyi
+ */
+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/ruoyi-common/src/main/java/com/ruoyi/common/utils/html/EscapeUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/html/EscapeUtil.java
new file mode 100644
index 0000000..f52e83e
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/html/EscapeUtil.java
@@ -0,0 +1,167 @@
+package com.ruoyi.common.utils.html;
+
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * 转义和反转义工具类
+ * 
+ * @author ruoyi
+ */
+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);
+    }
+
+    /**
+     * 清除所有HTML标签,但是不删除标签内的内容
+     * 
+     * @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解码
+     * 
+     * @param content 被转义的内容
+     * @return 解码后的字符串
+     */
+    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/ruoyi-common/src/main/java/com/ruoyi/common/utils/html/HTMLFilter.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/html/HTMLFilter.java
new file mode 100644
index 0000000..cd8cd4f
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/html/HTMLFilter.java
@@ -0,0 +1,570 @@
+package com.ruoyi.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 ruoyi
+ */
+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 (false == 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;,防止json格式无效 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/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java
new file mode 100644
index 0000000..bd07f7a
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java
@@ -0,0 +1,274 @@
+package com.ruoyi.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.ruoyi.common.constant.Constants;
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * 通用http发送方法
+ * 
+ * @author ruoyi
+ */
+public class HttpUtils
+{
+    private static final Logger log = LoggerFactory.getLogger(HttpUtils.class);
+
+    /**
+     * 向指定 URL 发送GET方法的请求
+     *
+     * @param url 发送请求的 URL
+     * @return 所代表远程资源的响应结果
+     */
+    public static String sendGet(String url)
+    {
+        return sendGet(url, StringUtils.EMPTY);
+    }
+
+    /**
+     * 向指定 URL 发送GET方法的请求
+     *
+     * @param url 发送请求的 URL
+     * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
+     * @return 所代表远程资源的响应结果
+     */
+    public static String sendGet(String url, String param)
+    {
+        return sendGet(url, param, Constants.UTF8);
+    }
+
+    /**
+     * 向指定 URL 发送GET方法的请求
+     *
+     * @param url 发送请求的 URL
+     * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
+     * @param contentType 编码类型
+     * @return 所代表远程资源的响应结果
+     */
+    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/5.0 (Windows NT 10.0; Win64; x64)");
+            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 发送POST方法的请求
+     *
+     * @param url 发送请求的 URL
+     * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
+     * @return 所代表远程资源的响应结果
+     */
+    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/5.0 (Windows NT 10.0; Win64; x64)");
+            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/5.0 (Windows NT 10.0; Win64; x64)");
+            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 && !ret.trim().equals(""))
+                {
+                    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/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelHandlerAdapter.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelHandlerAdapter.java
new file mode 100644
index 0000000..ccab288
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelHandlerAdapter.java
@@ -0,0 +1,24 @@
+package com.ruoyi.common.utils.poi;
+
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.Workbook;
+
+/**
+ * Excel数据格式处理适配器
+ * 
+ * @author ruoyi
+ */
+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/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java
new file mode 100644
index 0000000..1ac9ed9
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java
@@ -0,0 +1,1900 @@
+package com.ruoyi.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.DataFormat;
+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.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.annotation.Excel.ColumnType;
+import com.ruoyi.common.annotation.Excel.Type;
+import com.ruoyi.common.annotation.Excels;
+import com.ruoyi.common.config.RuoYiConfig;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.text.Convert;
+import com.ruoyi.common.exception.UtilException;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.DictUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.file.FileTypeUtils;
+import com.ruoyi.common.utils.file.FileUtils;
+import com.ruoyi.common.utils.file.ImageUtils;
+import com.ruoyi.common.utils.reflect.ReflectUtils;
+
+/**
+ * Excel相关处理
+ * 
+ * @author ruoyi
+ */
+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;
+
+    /**
+     * 导出类型(EXPORT:导出数据;IMPORT:导入模板)
+     */
+    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[] includeFields;
+
+    /**
+     * 需要排除列属性
+     */
+    public String[] excludeFields;
+
+    public ExcelUtil(Class<T> clazz)
+    {
+        this.clazz = clazz;
+    }
+
+    /**
+     * 仅在Excel中显示列属性
+     *
+     * @param fields 列属性名 示例[单个"name"/多个"id","name"]
+     */
+    public void showColumn(String... fields)
+    {
+        this.includeFields = fields;
+    }
+
+    /**
+     * 隐藏Excel中列属性
+     *
+     * @param fields 列属性名 示例[单个"name"/多个"id","name"]
+     */
+    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))
+        {
+            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(), 0, titleLastCol));
+        }
+    }
+
+    /**
+     * 创建对象的子列表名称
+     */
+    public void createSubHead()
+    {
+        if (isSubList())
+        {
+            Row subRow = sheet.createRow(rownum);
+            int column = 0;
+            int subFieldSize = subFields != null ? subFields.size() : 0;
+            for (Object[] objects : fields)
+            {
+                Field field = (Field) objects[0];
+                Excel attr = (Excel) objects[1];
+                if (Collection.class.isAssignableFrom(field.getType()))
+                {
+                    Cell cell = subRow.createCell(column);
+                    cell.setCellValue(attr.name());
+                    cell.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor())));
+                    if (subFieldSize > 1)
+                    {
+                        CellRangeAddress cellAddress = new CellRangeAddress(rownum, rownum, column, column + subFieldSize - 1);
+                        sheet.addMergedRegion(cellAddress);
+                    }
+                    column += subFieldSize;
+                }
+                else
+                {
+                    Cell cell = subRow.createCell(column++);
+                    cell.setCellValue(attr.name());
+                    cell.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor())));
+                }
+            }
+            rownum++;
+        }
+    }
+
+    /**
+     * 对excel表单默认第一个索引名转换成list
+     * 
+     * @param is 输入流
+     * @return 转换后集合
+     */
+    public List<T> importExcel(InputStream is)
+    {
+        return importExcel(is, 0);
+    }
+
+    /**
+     * 对excel表单默认第一个索引名转换成list
+     * 
+     * @param is 输入流
+     * @param titleNum 标题占用行数
+     * @return 转换后集合
+     */
+    public List<T> importExcel(InputStream is, int titleNum)
+    {
+        List<T> list = null;
+        try
+        {
+            list = importExcel(StringUtils.EMPTY, is, titleNum);
+        }
+        catch (Exception e)
+        {
+            log.error("导入Excel异常{}", e.getMessage());
+            throw new UtilException(e.getMessage());
+        }
+        finally
+        {
+            IOUtils.closeQuietly(is);
+        }
+        return list;
+    }
+
+    /**
+     * 对excel表单指定表格索引名转换成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个sheet
+        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)
+        {
+            // 定义一个map用于存放excel列的序号和field.
+            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);
+                }
+            }
+            // 有数据时才处理 得到类的所有field.
+            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);
+                    // 从map中得到对应列的field.
+                    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()))
+                        {
+                            if (!sysDictMap.containsKey(attr.dictType() + val))
+                            {
+                                String dictValue = reverseDictByExp(Convert.toStr(val), attr.dictType(), attr.separator());
+                                sysDictMap.put(attr.dictType() + val, dictValue);
+                            }
+                            val = sysDictMap.get(attr.dictType() + val);
+                        }
+                        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;
+    }
+
+    /**
+     * 对list数据源将其里面的数据导入到excel表单
+     * 
+     * @param list 导出数据集合
+     * @param sheetName 工作表的名称
+     * @return 结果
+     */
+    public AjaxResult exportExcel(List<T> list, String sheetName)
+    {
+        return exportExcel(list, sheetName, StringUtils.EMPTY);
+    }
+
+    /**
+     * 对list数据源将其里面的数据导入到excel表单
+     * 
+     * @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();
+    }
+
+    /**
+     * 对list数据源将其里面的数据导入到excel表单
+     * 
+     * @param response 返回数据
+     * @param list 导出数据集合
+     * @param sheetName 工作表的名称
+     * @return 结果
+     */
+    public void exportExcel(HttpServletResponse response, List<T> list, String sheetName)
+    {
+        exportExcel(response, list, sheetName, StringUtils.EMPTY);
+    }
+
+    /**
+     * 对list数据源将其里面的数据导入到excel表单
+     * 
+     * @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);
+    }
+
+    /**
+     * 对list数据源将其里面的数据导入到excel表单
+     * 
+     * @param sheetName 工作表的名称
+     * @return 结果
+     */
+    public AjaxResult importTemplateExcel(String sheetName)
+    {
+        return importTemplateExcel(sheetName, StringUtils.EMPTY);
+    }
+
+    /**
+     * 对list数据源将其里面的数据导入到excel表单
+     * 
+     * @param sheetName 工作表的名称
+     * @param title 标题
+     * @return 结果
+     */
+    public AjaxResult importTemplateExcel(String sheetName, String title)
+    {
+        this.init(null, sheetName, title, Type.IMPORT);
+        return exportExcel();
+    }
+
+    /**
+     * 对list数据源将其里面的数据导入到excel表单
+     * 
+     * @param sheetName 工作表的名称
+     * @return 结果
+     */
+    public void importTemplateExcel(HttpServletResponse response, String sheetName)
+    {
+        importTemplateExcel(response, sheetName, StringUtils.EMPTY);
+    }
+
+    /**
+     * 对list数据源将其里面的数据导入到excel表单
+     * 
+     * @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);
+    }
+
+    /**
+     * 对list数据源将其里面的数据导入到excel表单
+     * 
+     * @return 结果
+     */
+    public void exportExcel(HttpServletResponse response)
+    {
+        try
+        {
+            writeSheet();
+            wb.write(response.getOutputStream());
+        }
+        catch (Exception e)
+        {
+            log.error("导出Excel异常{}", e.getMessage());
+        }
+        finally
+        {
+            IOUtils.closeQuietly(wb);
+        }
+    }
+
+    /**
+     * 对list数据源将其里面的数据导入到excel表单
+     * 
+     * @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);
+        }
+    }
+
+    /**
+     * 创建写入数据到Sheet
+     */
+    public void writeSheet()
+    {
+        // 取出一共有多少个sheet.
+        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 currentRowNum = rownum + 1; // 从标题行后开始
+
+        for (int i = startNo; i < endNo; i++)
+        {
+            row = sheet.createRow(currentRowNum);
+            T vo = (T) list.get(i);
+            int column = 0;
+            int maxSubListSize = getCurrentMaxSubListSize(vo);
+            for (Object[] os : fields)
+            {
+                Field field = (Field) os[0];
+                Excel excel = (Excel) os[1];
+                if (Collection.class.isAssignableFrom(field.getType()))
+                {
+                    try
+                    {
+                        Collection<?> subList = (Collection<?>) getTargetValue(vo, field, excel);
+                        if (subList != null && !subList.isEmpty())
+                        {
+                            int subIndex = 0;
+                            for (Object subVo : subList)
+                            {
+                                Row subRow = sheet.getRow(currentRowNum + subIndex);
+                                if (subRow == null)
+                                {
+                                    subRow = sheet.createRow(currentRowNum + subIndex);
+                                }
+
+                                int subColumn = column;
+                                for (Field subField : subFields)
+                                {
+                                    Excel subExcel = subField.getAnnotation(Excel.class);
+                                    addCell(subExcel, subRow, (T) subVo, subField, subColumn++);
+                                }
+                                subIndex++;
+                            }
+                            column += subFields.size();
+                        }
+                    }
+                    catch (Exception e)
+                    {
+                        log.error("填充集合数据失败", e);
+                    }
+                }
+                else
+                {
+                    // 创建单元格并设置值
+                    addCell(excel, row, vo, field, column);
+                    if (maxSubListSize > 1 && excel.needMerge())
+                    {
+                        sheet.addMergedRegion(new CellRangeAddress(currentRowNum, currentRowNum + maxSubListSize - 1, column, column));
+                    }
+                    column++;
+                }
+            }
+            currentRowNum += maxSubListSize;
+        }
+    }
+
+    /**
+     * 获取子列表最大数
+     */
+    private int getCurrentMaxSubListSize(T vo)
+    {
+        int maxSubListSize = 1;
+        for (Object[] os : fields)
+        {
+            Field field = (Field) os[0];
+            if (Collection.class.isAssignableFrom(field.getType()))
+            {
+                try
+                {
+                    Collection<?> subList = (Collection<?>) getTargetValue(vo, field, (Excel) os[1]);
+                    if (subList != null && !subList.isEmpty())
+                    {
+                        maxSubListSize = Math.max(maxSubListSize, subList.size());
+                    }
+                }
+                catch (Exception e)
+                {
+                    log.error("获取集合大小失败", e);
+                }
+            }
+        }
+        return maxSubListSize;
+    }
+
+    /**
+     * 创建表格样式
+     * 
+     * @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);
+        DataFormat dataFormat = wb.createDataFormat();
+        style.setDataFormat(dataFormat.getFormat("@"));
+        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);
+                // 设置表格头单元格文本形式
+                DataFormat dataFormat = wb.createDataFormat();
+                style.setDataFormat(dataFormat.getFormat("@"));
+                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)
+        {
+            Field field = (Field) os[0];
+            Excel excel = (Excel) os[1];
+            if (Collection.class.isAssignableFrom(field.getType()))
+            {
+                ParameterizedType pt = (ParameterizedType) field.getGenericType();
+                Class<?> subClass = (Class<?>) pt.getActualTypeArguments()[0];
+                List<Field> subFields = FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class);
+                for (Field subField : subFields)
+                {
+                    Excel subExcel = subField.getAnnotation(Excel.class);
+                    annotationDataStyles(styles, subField, subExcel);
+                }
+            }
+            else
+            {
+                annotationDataStyles(styles, field, excel);
+            }
+        }
+        return styles;
+    }
+
+    /**
+     * 根据Excel注解创建表格列样式
+     * 
+     * @param styles 自定义样式列表
+     * @param field  属性列信息
+     * @param excel  注解信息
+     */
+    public void annotationDataStyles(Map<String, CellStyle> styles, Field field, Excel excel)
+    {
+        String key = StringUtils.format("data_{}_{}_{}_{}_{}", excel.align(), excel.color(), excel.backgroundColor(), excel.cellType(), excel.wrapText());
+        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());
+            style.setWrapText(excel.wrapText());
+            Font dataFont = wb.createFont();
+            dataFont.setFontName("Arial");
+            dataFont.setFontHeightInPoints((short) 10);
+            dataFont.setColor(excel.color().index);
+            style.setFont(dataFont);
+            if (ColumnType.TEXT == excel.cellType())
+            {
+                DataFormat dataFormat = wb.createDataFormat();
+                style.setDataFormat(dataFormat.getFormat("@"));
+            }
+            styles.put(key, style);
+        }
+    }
+
+    /**
+     * 创建单元格
+     */
+    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(), attr.cellType(), attr.wrapText())));
+            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() || ColumnType.TEXT == attr.cellType())
+        {
+            String cellValue = Convert.toStr(value);
+            // 对于任何以表达式触发字符 =-+@开头的单元格,直接使用tab字符作为前缀,防止CSV注入。
+            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 || attr.comboReadDict())
+        {
+            String[] comboArray = attr.combo();
+            if (attr.comboReadDict())
+            {
+                if (!sysDictMap.containsKey("combo_" + attr.dictType()))
+                {
+                    String labels = DictUtils.getDictLabels(attr.dictType());
+                    sysDictMap.put("combo_" + attr.dictType(), labels);
+                }
+                String val = sysDictMap.get("combo_" + attr.dictType());
+                comboArray = StringUtils.split(val, DictUtils.SEPARATOR);
+            }
+            if (comboArray.length > 15 || StringUtils.join(comboArray).length() > 255)
+            {
+                // 如果下拉数大于15或字符串长度大于255,则使用一个新sheet存储,避免生成的模板下拉值获取不到
+                setXSSFValidationWithHidden(sheet, comboArray, attr.prompt(), 1, 100, column, column);
+            }
+            else
+            {
+                // 提示信息或只能选择不能输入的列内容.
+                setPromptOrValidation(sheet, comboArray, 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())
+                {
+                    if (subMergedLastRowNum >= subMergedFirstRowNum)
+                    {
+                        sheet.addMergedRegion(new CellRangeAddress(subMergedFirstRowNum, subMergedLastRowNum, column, column));
+                    }
+                }
+                cell.setCellStyle(styles.get(StringUtils.format("data_{}_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType(), attr.wrapText())));
+
+                // 用于读取对象中的属性
+                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);
+    }
+
+    /**
+     * 解析导出值 0=男,1=女,2=未知
+     * 
+     * @param propertyValue 参数值
+     * @param converterExp 翻译注解
+     * @param separator 分隔符
+     * @return 解析后值
+     */
+    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);
+    }
+
+    /**
+     * 反向解析值 男=0,女=1,未知=2
+     * 
+     * @param propertyValue 参数值
+     * @param converterExp 翻译注解
+     * @param separator 分隔符
+     * @return 解析后值
+     */
+    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);
+    }
+
+    /**
+     * 解析字典值
+     * 
+     * @param dictValue 字典值
+     * @param dictType 字典类型
+     * @param separator 分隔符
+     * @return 字典标签
+     */
+    public static String convertDictByExp(String dictValue, String dictType, String separator)
+    {
+        return DictUtils.getDictLabel(dictType, dictValue, separator);
+    }
+
+    /**
+     * 反向解析值字典值
+     * 
+     * @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 = RuoYiConfig.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
+    {
+        field.setAccessible(true);
+        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()));
+        if (StringUtils.isNotEmpty(includeFields))
+        {
+            for (Field field : tempFields)
+            {
+                if (ArrayUtils.contains(this.includeFields, field.getName()) || field.isAnnotationPresent(Excels.class))
+                {
+                    addField(fields, field);
+                }
+            }
+        }
+        else if (StringUtils.isNotEmpty(excludeFields))
+        {
+            for (Field field : tempFields)
+            {
+                if (!ArrayUtils.contains(this.excludeFields, field.getName()))
+                {
+                    addField(fields, field);
+                }
+            }
+        }
+        else
+        {
+            for (Field field : tempFields)
+            {
+                addField(fields, field);
+            }
+        }
+        return fields;
+    }
+
+    /**
+     * 添加字段信息
+     */
+    public void addField(List<Object[]> fields, Field field)
+    {
+        // 单注解
+        if (field.isAnnotationPresent(Excel.class))
+        {
+            Excel attr = field.getAnnotation(Excel.class);
+            if (attr != null && (attr.type() == Type.ALL || attr.type() == type))
+            {
+                fields.add(new Object[] { field, attr });
+            }
+            if (Collection.class.isAssignableFrom(field.getType()))
+            {
+                subMethod = getSubMethod(field.getName(), clazz);
+                ParameterizedType pt = (ParameterizedType) field.getGenericType();
+                Class<?> subClass = (Class<?>) pt.getActualTypeArguments()[0];
+                this.subFields = FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class);
+            }
+        }
+
+        // 多注解
+        if (field.isAnnotationPresent(Excels.class))
+        {
+            Excels attrs = field.getAnnotation(Excels.class);
+            Excel[] excels = attrs.value();
+            for (Excel attr : excels)
+            {
+                if (StringUtils.isNotEmpty(includeFields))
+                {
+                    if (ArrayUtils.contains(this.includeFields, field.getName() + "." + attr.targetAttr())
+                            && (attr != null && (attr.type() == Type.ALL || attr.type() == type)))
+                    {
+                        fields.add(new Object[] { field, attr });
+                    }
+                }
+                else
+                {
+                    if (!ArrayUtils.contains(this.excludeFields, field.getName() + "." + attr.targetAttr())
+                            && (attr != null && (attr.type() == Type.ALL || attr.type() == type)))
+                    {
+                        fields.add(new Object[] { field, attr });
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * 根据注解获取最大行高
+     */
+    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)String,value:图片流PictureData
+     */
+    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)String,value:图片流PictureData
+     */
+    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/ruoyi-common/src/main/java/com/ruoyi/common/utils/reflect/ReflectUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/reflect/ReflectUtils.java
new file mode 100644
index 0000000..b19953e
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/reflect/ReflectUtils.java
@@ -0,0 +1,410 @@
+package com.ruoyi.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.ruoyi.common.core.text.Convert;
+import com.ruoyi.common.utils.DateUtils;
+
+/**
+ * 反射工具类. 提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class, 被AOP过的真实类等工具函数.
+ * 
+ * @author ruoyi
+ */
+@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修饰符, 不经过getter函数.
+     */
+    @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修饰符, 不经过setter函数.
+     */
+    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);
+        }
+    }
+
+    /**
+     * 循环向上转型, 获取对象的DeclaredField, 并强制设置为可访问.
+     * 如向上转型到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;
+    }
+
+    /**
+     * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.
+     * 如向上转型到Object仍无法找到, 返回null.
+     * 匹配函数名+参数类型。
+     * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用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;
+    }
+
+    /**
+     * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.
+     * 如向上转型到Object仍无法找到, 返回null.
+     * 只匹配函数名。
+     * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用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的SecurityManager抱怨。
+     */
+    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的SecurityManager抱怨。
+     */
+    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定义中声明的泛型参数的类型, 注意泛型必须定义在父类处
+     * 如无法找到, 返回Object.class.
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> Class<T> getClassGenricType(final Class clazz)
+    {
+        return getClassGenricType(clazz, 0);
+    }
+
+    /**
+     * 通过反射, 获得Class定义中声明的父类的泛型参数的类型.
+     * 如无法找到, 返回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;
+
+    }
+
+    /**
+     * 将反射时的checked exception转换为unchecked 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/ruoyi-common/src/main/java/com/ruoyi/common/utils/security/CipherUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/security/CipherUtils.java
new file mode 100644
index 0000000..43b9f24
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/security/CipherUtils.java
@@ -0,0 +1,36 @@
+package com.ruoyi.common.utils.security;
+
+import java.security.Key;
+import java.security.NoSuchAlgorithmException;
+import javax.crypto.KeyGenerator;
+
+/**
+ * 对称密钥密码算法工具类
+ *
+ * @author ruoyi
+ */
+public class CipherUtils
+{
+    /**
+     * 生成随机秘钥
+     *
+     * @param keyBitSize 字节大小
+     * @param algorithmName 算法名称
+     * @return 创建密匙
+     */
+    public static Key generateNewKey(int keyBitSize, String algorithmName)
+    {
+        KeyGenerator kg;
+        try
+        {
+            kg = KeyGenerator.getInstance(algorithmName);
+        }
+        catch (NoSuchAlgorithmException e)
+        {
+            String msg = "Unable to acquire " + algorithmName + " algorithm.  This is required to function.";
+            throw new IllegalStateException(msg, e);
+        }
+        kg.init(keyBitSize);
+        return kg.generateKey();
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/security/Md5Utils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/security/Md5Utils.java
new file mode 100644
index 0000000..ff9937f
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/security/Md5Utils.java
@@ -0,0 +1,67 @@
+package com.ruoyi.common.utils.security;
+
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Md5加密方法
+ * 
+ * @author ruoyi
+ */
+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/ruoyi-common/src/main/java/com/ruoyi/common/utils/security/PermissionUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/security/PermissionUtils.java
new file mode 100644
index 0000000..296f2ca
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/security/PermissionUtils.java
@@ -0,0 +1,118 @@
+package com.ruoyi.common.utils.security;
+
+import java.beans.BeanInfo;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.subject.Subject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.ruoyi.common.constant.PermissionConstants;
+import com.ruoyi.common.utils.MessageUtils;
+
+/**
+ * permission 工具类
+ * 
+ * @author ruoyi
+ */
+public class PermissionUtils
+{
+    private static final Logger log = LoggerFactory.getLogger(PermissionUtils.class);
+
+    /**
+     * 查看数据的权限
+     */
+    public static final String VIEW_PERMISSION = "no.view.permission";
+
+    /**
+     * 创建数据的权限
+     */
+    public static final String CREATE_PERMISSION = "no.create.permission";
+
+    /**
+     * 修改数据的权限
+     */
+    public static final String UPDATE_PERMISSION = "no.update.permission";
+
+    /**
+     * 删除数据的权限
+     */
+    public static final String DELETE_PERMISSION = "no.delete.permission";
+
+    /**
+     * 导出数据的权限
+     */
+    public static final String EXPORT_PERMISSION = "no.export.permission";
+
+    /**
+     * 其他数据的权限
+     */
+    public static final String PERMISSION = "no.permission";
+
+    /**
+     * 权限错误消息提醒
+     * 
+     * @param permissionsStr 错误信息
+     * @return 提示信息
+     */
+    public static String getMsg(String permissionsStr)
+    {
+        String permission = StringUtils.substringBetween(permissionsStr, "[", "]");
+        String msg = MessageUtils.message(PERMISSION, permission);
+        if (StringUtils.endsWithIgnoreCase(permission, PermissionConstants.ADD_PERMISSION))
+        {
+            msg = MessageUtils.message(CREATE_PERMISSION, permission);
+        }
+        else if (StringUtils.endsWithIgnoreCase(permission, PermissionConstants.EDIT_PERMISSION))
+        {
+            msg = MessageUtils.message(UPDATE_PERMISSION, permission);
+        }
+        else if (StringUtils.endsWithIgnoreCase(permission, PermissionConstants.REMOVE_PERMISSION))
+        {
+            msg = MessageUtils.message(DELETE_PERMISSION, permission);
+        }
+        else if (StringUtils.endsWithIgnoreCase(permission, PermissionConstants.EXPORT_PERMISSION))
+        {
+            msg = MessageUtils.message(EXPORT_PERMISSION, permission);
+        }
+        else if (StringUtils.endsWithAny(permission,
+                new String[] { PermissionConstants.VIEW_PERMISSION, PermissionConstants.LIST_PERMISSION }))
+        {
+            msg = MessageUtils.message(VIEW_PERMISSION, permission);
+        }
+        return msg;
+    }
+
+    /**
+     * 返回用户属性值
+     *
+     * @param property 属性名称
+     * @return 用户属性值
+     */
+    public static Object getPrincipalProperty(String property)
+    {
+        Subject subject = SecurityUtils.getSubject();
+        if (subject != null)
+        {
+            Object principal = subject.getPrincipal();
+            try
+            {
+                BeanInfo bi = Introspector.getBeanInfo(principal.getClass());
+                for (PropertyDescriptor pd : bi.getPropertyDescriptors())
+                {
+                    if (pd.getName().equals(property) == true)
+                    {
+                        return pd.getReadMethod().invoke(principal, (Object[]) null);
+                    }
+                }
+            }
+            catch (Exception e)
+            {
+                log.error("Error reading property [{}] from principal of type [{}]", property,
+                        principal.getClass().getName());
+            }
+        }
+        return null;
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/spring/SpringUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/spring/SpringUtils.java
new file mode 100644
index 0000000..c5699ad
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/spring/SpringUtils.java
@@ -0,0 +1,159 @@
+package com.ruoyi.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.ruoyi.common.utils.StringUtils;
+
+/**
+ * spring工具类 方便在非spring管理环境中获取bean
+ * 
+ * @author ruoyi
+ */
+@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);
+    }
+
+    /**
+     * 获取类型为requiredType的对象
+     *
+     * @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定义是一个singleton还是一个prototype。 如果与给定名字相应的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);
+    }
+
+    /**
+     * 如果给定的bean名字在bean定义中有别名,则返回这些别名
+     *
+     * @param name
+     * @return
+     * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
+     *
+     */
+    public static String[] getAliases(String name) throws NoSuchBeanDefinitionException
+    {
+        return beanFactory.getAliases(name);
+    }
+
+    /**
+     * 获取aop代理对象
+     * 
+     * @param invoker
+     * @return
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> T getAopProxy(T invoker)
+    {
+        return (T) AopContext.currentProxy();
+    }
+
+    /**
+     * 获取当前的环境配置,无配置返回null
+     *
+     * @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 配置文件的key
+     * @return 当前的配置文件的值
+     *
+     */
+    public static String getRequiredProperty(String key)
+    {
+        return applicationContext.getEnvironment().getRequiredProperty(key);
+    }
+
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java
new file mode 100644
index 0000000..48720dc
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java
@@ -0,0 +1,70 @@
+package com.ruoyi.common.utils.sql;
+
+import com.ruoyi.common.exception.UtilException;
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * sql操作工具类
+ * 
+ * @author ruoyi
+ */
+public class SqlUtil
+{
+    /**
+     * 定义常用的 sql关键字
+     */
+    public static String SQL_REGEX = "\u000B|and |extractvalue|updatexml|sleep|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |union |like |+|/*|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/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/IdUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/IdUtils.java
new file mode 100644
index 0000000..2c84427
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/IdUtils.java
@@ -0,0 +1,49 @@
+package com.ruoyi.common.utils.uuid;
+
+/**
+ * ID生成器工具类
+ * 
+ * @author ruoyi
+ */
+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,使用性能更好的ThreadLocalRandom生成UUID
+     * 
+     * @return 随机UUID
+     */
+    public static String fastUUID()
+    {
+        return UUID.fastUUID().toString();
+    }
+
+    /**
+     * 简化的UUID,去掉了横线,使用性能更好的ThreadLocalRandom生成UUID
+     * 
+     * @return 简化的UUID,去掉了横线
+     */
+    public static String fastSimpleUUID()
+    {
+        return UUID.fastUUID().toString(true);
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/Seq.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/Seq.java
new file mode 100644
index 0000000..bf99611
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/Seq.java
@@ -0,0 +1,86 @@
+package com.ruoyi.common.utils.uuid;
+
+import java.util.concurrent.atomic.AtomicInteger;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * @author ruoyi 序列生成类
+ */
+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左补齐length位数
+     * 
+     * @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/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/UUID.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/UUID.java
new file mode 100644
index 0000000..acc3a6f
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/UUID.java
@@ -0,0 +1,484 @@
+package com.ruoyi.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.ruoyi.common.exception.UtilException;
+
+/**
+ * 提供通用唯一识别码(universally unique identifier)(UUID)实现
+ *
+ * @author ruoyi
+ */
+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();
+    }
+
+    /** 此UUID的最高64有效位 */
+    private final long mostSigBits;
+
+    /** 此UUID的最低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(基于名称的)UUID 的静态工厂。
+     *
+     * @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、time_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 字段构造。clock_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 是否简单模式,简单模式为不带'-'的UUID字符串
+     * @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 (false == isSimple)
+        {
+            builder.append('-');
+        }
+        // time_mid
+        builder.append(digits(mostSigBits >> 16, 4));
+        if (false == isSimple)
+        {
+            builder.append('-');
+        }
+        // time_high_and_version
+        builder.append(digits(mostSigBits, 4));
+        if (false == isSimple)
+        {
+            builder.append('-');
+        }
+        // variant_and_sequence
+        builder.append(digits(leastSigBits >> 48, 4));
+        if (false == 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
+    /**
+     * 返回指定数字对应的hex值
+     * 
+     * @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是JDK 7之后提供并发产生随机数,能够解决多个线程发生的竞争争夺。
+     * 
+     * @return {@link ThreadLocalRandom}
+     */
+    public static ThreadLocalRandom getRandom()
+    {
+        return ThreadLocalRandom.current();
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/xss/Xss.java b/ruoyi-common/src/main/java/com/ruoyi/common/xss/Xss.java
new file mode 100644
index 0000000..7bfdf04
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/xss/Xss.java
@@ -0,0 +1,27 @@
+package com.ruoyi.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;
+
+/**
+ * 自定义xss校验注解
+ * 
+ * @author ruoyi
+ */
+@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/ruoyi-common/src/main/java/com/ruoyi/common/xss/XssFilter.java b/ruoyi-common/src/main/java/com/ruoyi/common/xss/XssFilter.java
new file mode 100644
index 0000000..5e1921c
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/xss/XssFilter.java
@@ -0,0 +1,74 @@
+package com.ruoyi.common.xss;
+
+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.ruoyi.common.utils.StringUtils;
+
+/**
+ * 防止XSS攻击的过滤器
+ * 
+ * @author ruoyi
+ */
+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[] urls = tempExcludes.split(",");
+            for (String url : urls)
+            {
+                excludes.add(url);
+            }
+        }
+    }
+
+    @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 || method.matches("GET") || method.matches("DELETE"))
+        {
+            return true;
+        }
+        return StringUtils.matches(url, excludes);
+    }
+
+    @Override
+    public void destroy()
+    {
+
+    }
+}
\ No newline at end of file
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/xss/XssHttpServletRequestWrapper.java b/ruoyi-common/src/main/java/com/ruoyi/common/xss/XssHttpServletRequestWrapper.java
new file mode 100644
index 0000000..929de41
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/xss/XssHttpServletRequestWrapper.java
@@ -0,0 +1,39 @@
+package com.ruoyi.common.xss;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import com.ruoyi.common.utils.html.EscapeUtil;
+
+/**
+ * XSS过滤处理
+ * 
+ * @author ruoyi
+ */
+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[] escapseValues = new String[length];
+            for (int i = 0; i < length; i++)
+            {
+                // 防xss攻击和过滤前后空格
+                escapseValues[i] = EscapeUtil.clean(values[i]).trim();
+            }
+            return escapseValues;
+        }
+        return super.getParameterValues(name);
+    }
+}
\ No newline at end of file
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/xss/XssValidator.java b/ruoyi-common/src/main/java/com/ruoyi/common/xss/XssValidator.java
new file mode 100644
index 0000000..42f425c
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/xss/XssValidator.java
@@ -0,0 +1,39 @@
+package com.ruoyi.common.xss;
+
+import com.ruoyi.common.utils.StringUtils;
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * 自定义xss校验注解实现
+ * 
+ * @author ruoyi
+ */
+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)
+    {
+        StringBuilder sHtml = new StringBuilder();
+        Pattern pattern = Pattern.compile(HTML_PATTERN);
+        Matcher matcher = pattern.matcher(value);
+        while (matcher.find())
+        {
+            sHtml.append(matcher.group());
+        }
+        return pattern.matcher(sHtml).matches();
+    }
+}
\ No newline at end of file
diff --git a/ruoyi-framework/pom.xml b/ruoyi-framework/pom.xml
new file mode 100644
index 0000000..9a44ee6
--- /dev/null
+++ b/ruoyi-framework/pom.xml
@@ -0,0 +1,82 @@
+<?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>ruoyi</artifactId>
+        <groupId>com.ruoyi</groupId>
+        <version>4.8.0</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>ruoyi-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>
+
+        <!-- Shiro使用Spring框架 -->
+        <dependency>
+            <groupId>org.apache.shiro</groupId>
+            <artifactId>shiro-spring</artifactId>
+        </dependency>
+
+        <!-- thymeleaf模板引擎和shiro框架的整合 -->
+        <dependency>
+            <groupId>com.github.theborakompanioni</groupId>
+            <artifactId>thymeleaf-extras-shiro</artifactId>
+        </dependency>
+
+        <!-- 解析客户端操作系统、浏览器等 -->
+        <dependency>
+            <groupId>eu.bitwalker</groupId>
+            <artifactId>UserAgentUtils</artifactId>
+        </dependency>
+
+        <!-- 获取系统信息 -->
+        <dependency>
+            <groupId>com.github.oshi</groupId>
+            <artifactId>oshi-core</artifactId>
+        </dependency>
+
+        <!-- 系统模块-->
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-system</artifactId>
+        </dependency>
+
+    </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java
new file mode 100644
index 0000000..df9a85c
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java
@@ -0,0 +1,182 @@
+package com.ruoyi.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.ruoyi.common.annotation.DataScope;
+import com.ruoyi.common.constant.UserConstants;
+import com.ruoyi.common.core.context.PermissionContextHolder;
+import com.ruoyi.common.core.domain.BaseEntity;
+import com.ruoyi.common.core.domain.entity.SysRole;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.core.text.Convert;
+import com.ruoyi.common.utils.ShiroUtils;
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * 数据过滤处理
+ * 
+ * @author ruoyi
+ */
+@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)
+    {
+        // 获取当前的用户
+        SysUser currentUser = ShiroUtils.getSysUser();
+        if (currentUser != null)
+        {
+            // 如果是超级管理员,则不过滤数据
+            if (!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>();
+        List<String> scopeCustomIds = new ArrayList<String>();
+        user.getRoles().forEach(role -> {
+            if (DATA_SCOPE_CUSTOM.equals(role.getDataScope()) && StringUtils.equals(role.getStatus(), UserConstants.ROLE_NORMAL) && StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))
+            {
+                scopeCustomIds.add(Convert.toStr(role.getRoleId()));
+            }
+        });
+
+        for (SysRole role : user.getRoles())
+        {
+            String dataScope = role.getDataScope();
+            if (conditions.contains(dataScope) || StringUtils.equals(role.getStatus(), UserConstants.ROLE_DISABLE))
+            {
+                continue;
+            }
+            if (!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))
+            {
+                if (scopeCustomIds.size() > 1)
+                {
+                    // 多个自定数据权限使用in查询,避免多次拼接。
+                    sqlString.append(StringUtils.format(" OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id in ({}) ) ", deptAlias, String.join(",", scopeCustomIds)));
+                }
+                else
+                {
+                    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
+                {
+                    // 数据权限为仅本人且没有userAlias别名不查询任何数据
+                    sqlString.append(StringUtils.format(" OR {}.dept_id = 0 ", deptAlias));
+                }
+            }
+            conditions.add(dataScope);
+        }
+
+        // 角色都不包含传递过来的权限字符,这个时候sqlString也会为空,所以要限制一下,不查询任何数据
+        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/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java
new file mode 100644
index 0000000..4951bc9
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java
@@ -0,0 +1,72 @@
+package com.ruoyi.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.ruoyi.common.annotation.DataSource;
+import com.ruoyi.common.config.datasource.DynamicDataSourceContextHolder;
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * 多数据源处理
+ * 
+ * @author ruoyi
+ */
+@Aspect
+@Order(1)
+@Component
+public class DataSourceAspect
+{
+    protected Logger logger = LoggerFactory.getLogger(getClass());
+
+    @Pointcut("@annotation(com.ruoyi.common.annotation.DataSource)"
+            + "|| @within(com.ruoyi.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/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java
new file mode 100644
index 0000000..25215b5
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java
@@ -0,0 +1,255 @@
+package com.ruoyi.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.fastjson.JSONObject;
+import com.alibaba.fastjson.support.spring.PropertyPreFilters;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.enums.BusinessStatus;
+import com.ruoyi.common.utils.ServletUtils;
+import com.ruoyi.common.utils.ShiroUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.framework.manager.AsyncManager;
+import com.ruoyi.framework.manager.factory.AsyncFactory;
+import com.ruoyi.system.domain.SysOperLog;
+
+/**
+ * 操作日志记录处理
+ * 
+ * @author ruoyi
+ */
+@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
+        {
+            // 获取当前的用户
+            SysUser currentUser = ShiroUtils.getSysUser();
+
+            // *========数据库日志=========*//
+            SysOperLog operLog = new SysOperLog();
+            operLog.setStatus(BusinessStatus.SUCCESS.ordinal());
+            // 请求的地址
+            String ip = ShiroUtils.getIp();
+            operLog.setOperIp(ip);
+            operLog.setOperUrl(StringUtils.substring(ServletUtils.getRequest().getRequestURI(), 0, 255));
+            if (currentUser != null)
+            {
+                operLog.setOperName(currentUser.getLoginName());
+                if (StringUtils.isNotNull(currentUser.getDept())
+                        && StringUtils.isNotEmpty(currentUser.getDept().getDeptName()))
+                {
+                    operLog.setDeptName(currentUser.getDept().getDeptName());
+                }
+            }
+
+            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());
+        // 是否需要保存request,参数和值
+        if (log.isSaveRequestData())
+        {
+            // 获取参数的信息,传入到数据库中。
+            setRequestValue(joinPoint, operLog, log.excludeParamNames());
+        }
+        // 是否需要保存response,参数和值
+        if (log.isSaveResponseData() && StringUtils.isNotNull(jsonResult))
+        {
+            operLog.setJsonResult(StringUtils.substring(JSONObject.toJSONString(jsonResult), 0, 2000));
+        }
+    }
+
+    /**
+     * 获取请求的参数,放到log中
+     * 
+     * @param operLog 操作日志
+     * @throws Exception 异常
+     */
+    private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog, String[] excludeParamNames) throws Exception
+    {
+        Map<String, String[]> map = ServletUtils.getRequest().getParameterMap();
+        if (StringUtils.isNotEmpty(map))
+        {
+            String params = JSONObject.toJSONString(map, excludePropertyPreFilter(excludeParamNames));
+            operLog.setOperParam(StringUtils.substring(params, 0, 2000));
+        }
+        else
+        {
+            Object args = joinPoint.getArgs();
+            if (StringUtils.isNotNull(args))
+            {
+                String params = argsArrayToString(joinPoint.getArgs(), excludeParamNames);
+                operLog.setOperParam(StringUtils.substring(params, 0, 2000));
+            }
+        }
+    }
+
+    /**
+     * 忽略敏感属性
+     */
+    public PropertyPreFilters.MySimplePropertyPreFilter excludePropertyPreFilter(String[] excludeParamNames)
+    {
+        return new PropertyPreFilters().addFilter().addExcludes(ArrayUtils.addAll(EXCLUDE_PROPERTIES, excludeParamNames));
+    }
+
+    /**
+     * 参数拼装
+     */
+    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
+                    {
+                        Object jsonObj = JSONObject.toJSONString(o, excludePropertyPreFilter(excludeParamNames));
+                        params += jsonObj.toString() + " ";
+                    }
+                    catch (Exception e)
+                    {
+                    }
+                }
+            }
+        }
+        return params.trim();
+    }
+
+    /**
+     * 判断是否需要过滤的对象。
+     * 
+     * @param o 对象信息。
+     * @return 如果是需要过滤的对象,则返回true;否则返回false。
+     */
+    @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/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/PermissionsAspect.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/PermissionsAspect.java
new file mode 100644
index 0000000..9d9831f
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/PermissionsAspect.java
@@ -0,0 +1,30 @@
+package com.ruoyi.framework.aspectj;
+
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.springframework.stereotype.Component;
+import com.ruoyi.common.core.context.PermissionContextHolder;
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * 自定义权限拦截器,将权限字符串放到当前请求中以便用于多个角色匹配符合要求的权限
+ * 
+ * @author ruoyi
+ */
+@Aspect
+@Component
+public class PermissionsAspect
+{
+    @Before("@annotation(controllerRequiresPermissions)")
+    public void doBefore(JoinPoint point, RequiresPermissions controllerRequiresPermissions) throws Throwable
+    {
+        handleRequiresPermissions(point, controllerRequiresPermissions);
+    }
+
+    protected void handleRequiresPermissions(final JoinPoint joinPoint, RequiresPermissions requiresPermissions)
+    {
+        PermissionContextHolder.setContext(StringUtils.join(requiresPermissions.value(), ","));
+    }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java
new file mode 100644
index 0000000..b6b0e88
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java
@@ -0,0 +1,20 @@
+package com.ruoyi.framework.config;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
+
+/**
+ * 程序注解配置
+ *
+ * @author ruoyi
+ */
+@Configuration
+// 表示通过aop框架暴露该代理对象,AopContext能够访问
+@EnableAspectJAutoProxy(exposeProxy = true)
+// 指定要扫描的Mapper类的包的路径
+@MapperScan("com.ruoyi.**.mapper")
+public class ApplicationConfig
+{
+
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/CaptchaConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/CaptchaConfig.java
new file mode 100644
index 0000000..43e78ae
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/CaptchaConfig.java
@@ -0,0 +1,83 @@
+package com.ruoyi.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 ruoyi
+ */
+@Configuration
+public class CaptchaConfig
+{
+    @Bean(name = "captchaProducer")
+    public DefaultKaptcha getKaptchaBean()
+    {
+        DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
+        Properties properties = new Properties();
+        // 是否有边框 默认为true 我们可以自己设置yes,no
+        properties.setProperty(KAPTCHA_BORDER, "yes");
+        // 验证码文本字符颜色 默认为Color.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");
+        // 验证码文本字体样式 默认为new 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();
+        // 是否有边框 默认为true 我们可以自己设置yes,no
+        properties.setProperty(KAPTCHA_BORDER, "yes");
+        // 边框颜色 默认为Color.BLACK
+        properties.setProperty(KAPTCHA_BORDER_COLOR, "105,179,90");
+        // 验证码文本字符颜色 默认为Color.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.ruoyi.framework.config.KaptchaTextCreator");
+        // 验证码文本字符间距 默认为2
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "3");
+        // 验证码文本字符长度 默认为5
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "6");
+        // 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
+        // 验证码噪点颜色 默认为Color.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/ruoyi-framework/src/main/java/com/ruoyi/framework/config/DruidConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/DruidConfig.java
new file mode 100644
index 0000000..1e3ebef
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/DruidConfig.java
@@ -0,0 +1,128 @@
+package com.ruoyi.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.ruoyi.common.enums.DataSourceType;
+import com.ruoyi.common.utils.spring.SpringUtils;
+import com.ruoyi.framework.config.properties.DruidProperties;
+import com.ruoyi.framework.datasource.DynamicDataSource;
+
+/**
+ * druid 配置多数据源
+ * 
+ * @author ruoyi
+ */
+@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);
+                // 正则替换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/ruoyi-framework/src/main/java/com/ruoyi/framework/config/FilterConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/FilterConfig.java
new file mode 100644
index 0000000..6abb9a2
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/FilterConfig.java
@@ -0,0 +1,44 @@
+package com.ruoyi.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.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.xss.XssFilter;
+
+/**
+ * Filter配置
+ *
+ * @author ruoyi
+ */
+@Configuration
+@ConditionalOnProperty(value = "xss.enabled", havingValue = "true")
+public class FilterConfig
+{
+    @Value("${xss.excludes}")
+    private String excludes;
+
+    @Value("${xss.urlPatterns}")
+    private String urlPatterns;
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Bean
+    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;
+    }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/I18nConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/I18nConfig.java
new file mode 100644
index 0000000..6d2382c
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/I18nConfig.java
@@ -0,0 +1,43 @@
+package com.ruoyi.framework.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.LocaleResolver;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
+import org.springframework.web.servlet.i18n.SessionLocaleResolver;
+import com.ruoyi.common.constant.Constants;
+
+/**
+ * 资源文件配置加载
+ * 
+ * @author ruoyi
+ */
+@Configuration
+public class I18nConfig implements WebMvcConfigurer
+{
+    @Bean
+    public LocaleResolver localeResolver()
+    {
+        SessionLocaleResolver slr = new SessionLocaleResolver();
+        // 默认语言
+        slr.setDefaultLocale(Constants.DEFAULT_LOCALE);
+        return slr;
+    }
+
+    @Bean
+    public LocaleChangeInterceptor localeChangeInterceptor()
+    {
+        LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
+        // 参数名
+        lci.setParamName("lang");
+        return lci;
+    }
+
+    @Override
+    public void addInterceptors(InterceptorRegistry registry)
+    {
+        registry.addInterceptor(localeChangeInterceptor());
+    }
+}
\ No newline at end of file
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/KaptchaTextCreator.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/KaptchaTextCreator.java
new file mode 100644
index 0000000..ae89d3c
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/KaptchaTextCreator.java
@@ -0,0 +1,76 @@
+package com.ruoyi.framework.config;
+
+import java.security.SecureRandom;
+import java.util.Random;
+import com.google.code.kaptcha.text.impl.DefaultTextCreator;
+
+/**
+ * 验证码文本生成器
+ * 
+ * @author ruoyi
+ */
+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 SecureRandom();
+        int x = random.nextInt(10);
+        int y = random.nextInt(10);
+        StringBuilder suChinese = new StringBuilder();
+        int randomoperands = (int) Math.round(Math.random() * 2);
+        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 (randomoperands == 2)
+        {
+            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]);
+            }
+        }
+        else
+        {
+            result = x + y;
+            suChinese.append(CNUMBERS[x]);
+            suChinese.append("+");
+            suChinese.append(CNUMBERS[y]);
+        }
+        suChinese.append("=?@" + result);
+        return suChinese.toString();
+    }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/MyBatisConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/MyBatisConfig.java
new file mode 100644
index 0000000..057c941
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/MyBatisConfig.java
@@ -0,0 +1,132 @@
+package com.ruoyi.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.ruoyi.common.utils.StringUtils;
+
+/**
+ * Mybatis支持*匹配扫描包
+ * 
+ * @author ruoyi
+ */
+@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/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java
new file mode 100644
index 0000000..5322ecd
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java
@@ -0,0 +1,58 @@
+package com.ruoyi.framework.config;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+import com.ruoyi.common.config.RuoYiConfig;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.framework.interceptor.RepeatSubmitInterceptor;
+
+/**
+ * 通用配置
+ * 
+ * @author ruoyi
+ */
+@Configuration
+public class ResourcesConfig implements WebMvcConfigurer
+{
+    /**
+     * 首页地址
+     */
+    @Value("${shiro.user.indexUrl}")
+    private String indexUrl;
+
+    @Autowired
+    private RepeatSubmitInterceptor repeatSubmitInterceptor;
+
+    /**
+     * 默认首页的设置,当输入域名是可以自动跳转到默认指定的网页
+     */
+    @Override
+    public void addViewControllers(ViewControllerRegistry registry)
+    {
+        registry.addViewController("/").setViewName("forward:" + indexUrl);
+    }
+
+    @Override
+    public void addResourceHandlers(ResourceHandlerRegistry registry)
+    {
+        /** 本地文件上传路径 */
+        registry.addResourceHandler(Constants.RESOURCE_PREFIX + "/**").addResourceLocations("file:" + RuoYiConfig.getProfile() + "/");
+
+        /** swagger配置 */
+        registry.addResourceHandler("/swagger-ui/**").addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/");
+    }
+
+    /**
+     * 自定义拦截规则
+     */
+    @Override
+    public void addInterceptors(InterceptorRegistry registry)
+    {
+        registry.addInterceptor(repeatSubmitInterceptor).addPathPatterns("/**");
+    }
+}
\ No newline at end of file
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ShiroConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ShiroConfig.java
new file mode 100644
index 0000000..2929403
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ShiroConfig.java
@@ -0,0 +1,424 @@
+package com.ruoyi.framework.config;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import javax.servlet.Filter;
+import org.apache.commons.io.IOUtils;
+import org.apache.shiro.cache.ehcache.EhCacheManager;
+import org.apache.shiro.codec.Base64;
+import org.apache.shiro.config.ConfigurationException;
+import org.apache.shiro.io.ResourceUtils;
+import org.apache.shiro.mgt.SecurityManager;
+import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
+import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
+import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
+import org.apache.shiro.web.servlet.SimpleCookie;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.security.CipherUtils;
+import com.ruoyi.common.utils.spring.SpringUtils;
+import com.ruoyi.framework.config.properties.PermitAllUrlProperties;
+import com.ruoyi.framework.shiro.realm.UserRealm;
+import com.ruoyi.framework.shiro.rememberMe.CustomCookieRememberMeManager;
+import com.ruoyi.framework.shiro.session.OnlineSessionDAO;
+import com.ruoyi.framework.shiro.session.OnlineSessionFactory;
+import com.ruoyi.framework.shiro.web.CustomShiroFilterFactoryBean;
+import com.ruoyi.framework.shiro.web.filter.LogoutFilter;
+import com.ruoyi.framework.shiro.web.filter.captcha.CaptchaValidateFilter;
+import com.ruoyi.framework.shiro.web.filter.kickout.KickoutSessionFilter;
+import com.ruoyi.framework.shiro.web.filter.online.OnlineSessionFilter;
+import com.ruoyi.framework.shiro.web.filter.sync.SyncOnlineSessionFilter;
+import com.ruoyi.framework.shiro.web.session.OnlineWebSessionManager;
+import com.ruoyi.framework.shiro.web.session.SpringSessionValidationScheduler;
+import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
+
+/**
+ * 权限配置加载
+ * 
+ * @author ruoyi
+ */
+@Configuration
+public class ShiroConfig
+{
+    /**
+     * Session超时时间,单位为毫秒(默认30分钟)
+     */
+    @Value("${shiro.session.expireTime}")
+    private int expireTime;
+
+    /**
+     * 相隔多久检查一次session的有效性,单位毫秒,默认就是10分钟
+     */
+    @Value("${shiro.session.validationInterval}")
+    private int validationInterval;
+
+    /**
+     * 同一个用户最大会话数
+     */
+    @Value("${shiro.session.maxSession}")
+    private int maxSession;
+
+    /**
+     * 踢出之前登录的/之后登录的用户,默认踢出之前登录的用户
+     */
+    @Value("${shiro.session.kickoutAfter}")
+    private boolean kickoutAfter;
+
+    /**
+     * 验证码开关
+     */
+    @Value("${shiro.user.captchaEnabled}")
+    private boolean captchaEnabled;
+
+    /**
+     * 验证码类型
+     */
+    @Value("${shiro.user.captchaType}")
+    private String captchaType;
+
+    /**
+     * 设置Cookie的域名
+     */
+    @Value("${shiro.cookie.domain}")
+    private String domain;
+
+    /**
+     * 设置cookie的有效访问路径
+     */
+    @Value("${shiro.cookie.path}")
+    private String path;
+
+    /**
+     * 设置HttpOnly属性
+     */
+    @Value("${shiro.cookie.httpOnly}")
+    private boolean httpOnly;
+
+    /**
+     * 设置Cookie的过期时间,秒为单位
+     */
+    @Value("${shiro.cookie.maxAge}")
+    private int maxAge;
+
+    /**
+     * 设置cipherKey密钥
+     */
+    @Value("${shiro.cookie.cipherKey}")
+    private String cipherKey;
+
+    /**
+     * 登录地址
+     */
+    @Value("${shiro.user.loginUrl}")
+    private String loginUrl;
+
+    /**
+     * 权限认证失败地址
+     */
+    @Value("${shiro.user.unauthorizedUrl}")
+    private String unauthorizedUrl;
+
+    /**
+     * 是否开启记住我功能
+     */
+    @Value("${shiro.rememberMe.enabled: false}")
+    private boolean rememberMe;
+
+    /**
+     * 缓存管理器 使用Ehcache实现
+     */
+    @Bean
+    public EhCacheManager getEhCacheManager()
+    {
+        net.sf.ehcache.CacheManager cacheManager = net.sf.ehcache.CacheManager.getCacheManager("ruoyi");
+        EhCacheManager em = new EhCacheManager();
+        if (StringUtils.isNull(cacheManager))
+        {
+            em.setCacheManager(new net.sf.ehcache.CacheManager(getCacheManagerConfigFileInputStream()));
+            return em;
+        }
+        else
+        {
+            em.setCacheManager(cacheManager);
+            return em;
+        }
+    }
+
+    /**
+     * 返回配置文件流 避免ehcache配置文件一直被占用,无法完全销毁项目重新部署
+     */
+    protected InputStream getCacheManagerConfigFileInputStream()
+    {
+        String configFile = "classpath:ehcache/ehcache-shiro.xml";
+        InputStream inputStream = null;
+        try
+        {
+            inputStream = ResourceUtils.getInputStreamForPath(configFile);
+            byte[] b = IOUtils.toByteArray(inputStream);
+            InputStream in = new ByteArrayInputStream(b);
+            return in;
+        }
+        catch (IOException e)
+        {
+            throw new ConfigurationException(
+                    "Unable to obtain input stream for cacheManagerConfigFile [" + configFile + "]", e);
+        }
+        finally
+        {
+            IOUtils.closeQuietly(inputStream);
+        }
+    }
+
+    /**
+     * 自定义Realm
+     */
+    @Bean
+    public UserRealm userRealm(EhCacheManager cacheManager)
+    {
+        UserRealm userRealm = new UserRealm();
+        userRealm.setAuthorizationCacheName(Constants.SYS_AUTH_CACHE);
+        userRealm.setCacheManager(cacheManager);
+        return userRealm;
+    }
+
+    /**
+     * 自定义sessionDAO会话
+     */
+    @Bean
+    public OnlineSessionDAO sessionDAO()
+    {
+        OnlineSessionDAO sessionDAO = new OnlineSessionDAO();
+        return sessionDAO;
+    }
+
+    /**
+     * 自定义sessionFactory会话
+     */
+    @Bean
+    public OnlineSessionFactory sessionFactory()
+    {
+        OnlineSessionFactory sessionFactory = new OnlineSessionFactory();
+        return sessionFactory;
+    }
+
+    /**
+     * 会话管理器
+     */
+    @Bean
+    public OnlineWebSessionManager sessionManager()
+    {
+        OnlineWebSessionManager manager = new OnlineWebSessionManager();
+        // 加入缓存管理器
+        manager.setCacheManager(getEhCacheManager());
+        // 删除过期的session
+        manager.setDeleteInvalidSessions(true);
+        // 设置全局session超时时间
+        manager.setGlobalSessionTimeout(expireTime * 60 * 1000);
+        // 去掉 JSESSIONID
+        manager.setSessionIdUrlRewritingEnabled(false);
+        // 定义要使用的无效的Session定时调度器
+        manager.setSessionValidationScheduler(SpringUtils.getBean(SpringSessionValidationScheduler.class));
+        // 是否定时检查session
+        manager.setSessionValidationSchedulerEnabled(true);
+        // 自定义SessionDao
+        manager.setSessionDAO(sessionDAO());
+        // 自定义sessionFactory
+        manager.setSessionFactory(sessionFactory());
+        return manager;
+    }
+
+    /**
+     * 安全管理器
+     */
+    @Bean
+    public SecurityManager securityManager(UserRealm userRealm)
+    {
+        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
+        // 设置realm.
+        securityManager.setRealm(userRealm);
+        // 记住我
+        securityManager.setRememberMeManager(rememberMe ? rememberMeManager() : null);
+        // 注入缓存管理器;
+        securityManager.setCacheManager(getEhCacheManager());
+        // session管理器
+        securityManager.setSessionManager(sessionManager());
+        return securityManager;
+    }
+
+    /**
+     * 退出过滤器
+     */
+    public LogoutFilter logoutFilter()
+    {
+        LogoutFilter logoutFilter = new LogoutFilter();
+        logoutFilter.setLoginUrl(loginUrl);
+        return logoutFilter;
+    }
+
+    /**
+     * Shiro过滤器配置
+     */
+    @Bean
+    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager)
+    {
+        CustomShiroFilterFactoryBean shiroFilterFactoryBean = new CustomShiroFilterFactoryBean();
+        // Shiro的核心安全接口,这个属性是必须的
+        shiroFilterFactoryBean.setSecurityManager(securityManager);
+        // 身份认证失败,则跳转到登录页面的配置
+        shiroFilterFactoryBean.setLoginUrl(loginUrl);
+        // 权限认证失败,则跳转到指定页面
+        shiroFilterFactoryBean.setUnauthorizedUrl(unauthorizedUrl);
+        // Shiro连接约束配置,即过滤链的定义
+        LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
+        // 对静态资源设置匿名访问
+        filterChainDefinitionMap.put("/favicon.ico**", "anon");
+        filterChainDefinitionMap.put("/ruoyi.png**", "anon");
+        filterChainDefinitionMap.put("/html/**", "anon");
+        filterChainDefinitionMap.put("/css/**", "anon");
+        filterChainDefinitionMap.put("/docs/**", "anon");
+        filterChainDefinitionMap.put("/fonts/**", "anon");
+        filterChainDefinitionMap.put("/img/**", "anon");
+        filterChainDefinitionMap.put("/ajax/**", "anon");
+        filterChainDefinitionMap.put("/js/**", "anon");
+        filterChainDefinitionMap.put("/ruoyi/**", "anon");
+        filterChainDefinitionMap.put("/captcha/captchaImage**", "anon");
+        // 匿名访问不鉴权注解列表
+        List<String> permitAllUrl = SpringUtils.getBean(PermitAllUrlProperties.class).getUrls();
+        if (StringUtils.isNotEmpty(permitAllUrl))
+        {
+            permitAllUrl.forEach(url -> filterChainDefinitionMap.put(url, "anon"));
+        }
+        // 退出 logout地址,shiro去清除session
+        filterChainDefinitionMap.put("/logout", "logout");
+        // 不需要拦截的访问
+        filterChainDefinitionMap.put("/login", "anon,captchaValidate");
+        // 注册相关
+        filterChainDefinitionMap.put("/register", "anon,captchaValidate");
+        // 系统权限列表
+        // filterChainDefinitionMap.putAll(SpringUtils.getBean(IMenuService.class).selectPermsAll());
+
+        Map<String, Filter> filters = new LinkedHashMap<String, Filter>();
+        filters.put("onlineSession", onlineSessionFilter());
+        filters.put("syncOnlineSession", syncOnlineSessionFilter());
+        filters.put("captchaValidate", captchaValidateFilter());
+        filters.put("kickout", kickoutSessionFilter());
+        // 注销成功,则跳转到指定页面
+        filters.put("logout", logoutFilter());
+        shiroFilterFactoryBean.setFilters(filters);
+
+        // 所有请求需要认证
+        filterChainDefinitionMap.put("/**", "user,kickout,onlineSession,syncOnlineSession");
+        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
+
+        return shiroFilterFactoryBean;
+    }
+
+    /**
+     * 自定义在线用户处理过滤器
+     */
+    public OnlineSessionFilter onlineSessionFilter()
+    {
+        OnlineSessionFilter onlineSessionFilter = new OnlineSessionFilter();
+        onlineSessionFilter.setLoginUrl(loginUrl);
+        onlineSessionFilter.setOnlineSessionDAO(sessionDAO());
+        return onlineSessionFilter;
+    }
+
+    /**
+     * 自定义在线用户同步过滤器
+     */
+    public SyncOnlineSessionFilter syncOnlineSessionFilter()
+    {
+        SyncOnlineSessionFilter syncOnlineSessionFilter = new SyncOnlineSessionFilter();
+        syncOnlineSessionFilter.setOnlineSessionDAO(sessionDAO());
+        return syncOnlineSessionFilter;
+    }
+
+    /**
+     * 自定义验证码过滤器
+     */
+    public CaptchaValidateFilter captchaValidateFilter()
+    {
+        CaptchaValidateFilter captchaValidateFilter = new CaptchaValidateFilter();
+        captchaValidateFilter.setCaptchaEnabled(captchaEnabled);
+        captchaValidateFilter.setCaptchaType(captchaType);
+        return captchaValidateFilter;
+    }
+
+    /**
+     * cookie 属性设置
+     */
+    public SimpleCookie rememberMeCookie()
+    {
+        SimpleCookie cookie = new SimpleCookie("rememberMe");
+        cookie.setDomain(domain);
+        cookie.setPath(path);
+        cookie.setHttpOnly(httpOnly);
+        cookie.setMaxAge(maxAge * 24 * 60 * 60);
+        return cookie;
+    }
+
+    /**
+     * 记住我
+     */
+    public CustomCookieRememberMeManager rememberMeManager()
+    {
+        CustomCookieRememberMeManager cookieRememberMeManager = new CustomCookieRememberMeManager();
+        cookieRememberMeManager.setCookie(rememberMeCookie());
+        if (StringUtils.isNotEmpty(cipherKey))
+        {
+            cookieRememberMeManager.setCipherKey(Base64.decode(cipherKey));
+        }
+        else
+        {
+            cookieRememberMeManager.setCipherKey(CipherUtils.generateNewKey(128, "AES").getEncoded());
+        }
+        return cookieRememberMeManager;
+    }
+
+    /**
+     * 同一个用户多设备登录限制
+     */
+    public KickoutSessionFilter kickoutSessionFilter()
+    {
+        KickoutSessionFilter kickoutSessionFilter = new KickoutSessionFilter();
+        kickoutSessionFilter.setCacheManager(getEhCacheManager());
+        kickoutSessionFilter.setSessionManager(sessionManager());
+        // 同一个用户最大的会话数,默认-1无限制;比如2的意思是同一个用户允许最多同时两个人登录
+        kickoutSessionFilter.setMaxSession(maxSession);
+        // 是否踢出后来登录的,默认是false;即后者登录的用户踢出前者登录的用户;踢出顺序
+        kickoutSessionFilter.setKickoutAfter(kickoutAfter);
+        // 被踢出后重定向到的地址;
+        kickoutSessionFilter.setKickoutUrl("/login?kickout=1");
+        return kickoutSessionFilter;
+    }
+
+    /**
+     * thymeleaf模板引擎和shiro框架的整合
+     */
+    @Bean
+    public ShiroDialect shiroDialect()
+    {
+        return new ShiroDialect();
+    }
+
+    /**
+     * 开启Shiro注解通知器
+     */
+    @Bean
+    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(
+            @Qualifier("securityManager") SecurityManager securityManager)
+    {
+        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
+        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
+        return authorizationAttributeSourceAdvisor;
+    }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/DruidProperties.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/DruidProperties.java
new file mode 100644
index 0000000..c8a5c8a
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/DruidProperties.java
@@ -0,0 +1,89 @@
+package com.ruoyi.framework.config.properties;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+import com.alibaba.druid.pool.DruidDataSource;
+
+/**
+ * druid 配置属性
+ * 
+ * @author ruoyi
+ */
+@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'。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会起作用。
+         */
+        datasource.setValidationQuery(validationQuery);
+        /** 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。 */
+        datasource.setTestWhileIdle(testWhileIdle);
+        /** 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 */
+        datasource.setTestOnBorrow(testOnBorrow);
+        /** 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 */
+        datasource.setTestOnReturn(testOnReturn);
+        return datasource;
+    }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/PermitAllUrlProperties.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/PermitAllUrlProperties.java
new file mode 100644
index 0000000..6faaf21
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/PermitAllUrlProperties.java
@@ -0,0 +1,151 @@
+package com.ruoyi.framework.config.properties;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import org.springframework.aop.framework.Advised;
+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.stereotype.Controller;
+import org.springframework.web.bind.annotation.DeleteMapping;
+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.RequestMapping;
+import com.ruoyi.common.annotation.Anonymous;
+
+/**
+ * 设置Anonymous注解允许匿名访问的url
+ * 
+ * @author ruoyi
+ */
+@Configuration
+public class PermitAllUrlProperties implements InitializingBean, ApplicationContextAware
+{
+    private List<String> urls = new ArrayList<>();
+
+    private ApplicationContext applicationContext;
+
+    @Override
+    public void afterPropertiesSet() throws Exception
+    {
+        Map<String, Object> controllers = applicationContext.getBeansWithAnnotation(Controller.class);
+        for (Object bean : controllers.values())
+        {
+            Class<?> beanClass;
+            if (bean instanceof Advised)
+            {
+                beanClass = ((Advised) bean).getTargetSource().getTarget().getClass();
+            }
+            else
+            {
+                beanClass = bean.getClass();
+            }
+            // 处理类级别的匿名访问注解
+            if (beanClass.isAnnotationPresent(Anonymous.class))
+            {
+                RequestMapping baseMapping = beanClass.getAnnotation(RequestMapping.class);
+                if (Objects.nonNull(baseMapping))
+                {
+                    String[] baseUrl = baseMapping.value();
+                    for (String url : baseUrl)
+                    {
+                        urls.add(prefix(url) + "/*");
+                    }
+                    continue;
+                }
+            }
+
+            // 处理方法级别的匿名访问注解
+            Method[] methods = beanClass.getDeclaredMethods();
+            for (Method method : methods)
+            {
+                if (method.isAnnotationPresent(Anonymous.class))
+                {
+                    RequestMapping baseMapping = beanClass.getAnnotation(RequestMapping.class);
+                    String[] baseUrl = {};
+                    if (Objects.nonNull(baseMapping))
+                    {
+                        baseUrl = baseMapping.value();
+                    }
+                    if (method.isAnnotationPresent(RequestMapping.class))
+                    {
+                        RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
+                        String[] uri = requestMapping.value();
+                        urls.addAll(rebuildUrl(baseUrl, uri));
+                    }
+                    else if (method.isAnnotationPresent(GetMapping.class))
+                    {
+                        GetMapping requestMapping = method.getAnnotation(GetMapping.class);
+                        String[] uri = requestMapping.value();
+                        urls.addAll(rebuildUrl(baseUrl, uri));
+                    }
+                    else if (method.isAnnotationPresent(PostMapping.class))
+                    {
+                        PostMapping requestMapping = method.getAnnotation(PostMapping.class);
+                        String[] uri = requestMapping.value();
+                        urls.addAll(rebuildUrl(baseUrl, uri));
+                    }
+                    else if (method.isAnnotationPresent(PutMapping.class))
+                    {
+                        PutMapping requestMapping = method.getAnnotation(PutMapping.class);
+                        String[] uri = requestMapping.value();
+                        urls.addAll(rebuildUrl(baseUrl, uri));
+                    }
+                    else if (method.isAnnotationPresent(DeleteMapping.class))
+                    {
+                        DeleteMapping requestMapping = method.getAnnotation(DeleteMapping.class);
+                        String[] uri = requestMapping.value();
+                        urls.addAll(rebuildUrl(baseUrl, uri));
+                    }
+                }
+            }
+        }
+    }
+
+    private List<String> rebuildUrl(String[] bases, String[] uris)
+    {
+        List<String> urls = new ArrayList<>();
+        for (String base : bases)
+        {
+            if (uris.length > 0)
+            {
+                for (String uri : uris)
+                {
+                    urls.add(prefix(base) + prefix(uri));
+                }
+            }
+            else
+            {
+                urls.add(prefix(base));
+            }
+        }
+        return urls;
+    }
+
+    private String prefix(String seg)
+    {
+        return seg.startsWith("/") ? seg : "/" + seg;
+    }
+
+    @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/ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSource.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSource.java
new file mode 100644
index 0000000..94b3d0d
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSource.java
@@ -0,0 +1,27 @@
+package com.ruoyi.framework.datasource;
+
+import java.util.Map;
+import javax.sql.DataSource;
+import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
+import com.ruoyi.common.config.datasource.DynamicDataSourceContextHolder;
+
+/**
+ * 动态数据源
+ * 
+ * @author ruoyi
+ */
+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/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java
new file mode 100644
index 0000000..6df2e5e
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java
@@ -0,0 +1,55 @@
+package com.ruoyi.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.ruoyi.common.json.JSON;
+import com.ruoyi.common.annotation.RepeatSubmit;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.utils.ServletUtils;
+
+/**
+ * 防止重复提交拦截器
+ *
+ * @author ruoyi
+ */
+@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.marshal(ajaxResult));
+                    return false;
+                }
+            }
+            return true;
+        }
+        else
+        {
+            return true;
+        }
+    }
+
+    /**
+     * 验证是否重复提交由子类实现具体的防重复提交的规则
+     *
+     * @param request 请求对象
+     * @param annotation 防复注解
+     * @return 结果
+     */
+    public abstract boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation) throws Exception;
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java
new file mode 100644
index 0000000..fc0e1e9
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java
@@ -0,0 +1,83 @@
+package com.ruoyi.framework.interceptor.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+import org.springframework.stereotype.Component;
+import com.ruoyi.common.annotation.RepeatSubmit;
+import com.ruoyi.common.json.JSON;
+import com.ruoyi.framework.interceptor.RepeatSubmitInterceptor;
+
+/**
+ * 判断请求url和数据是否和上一次相同, 
+ * 如果和上次相同,则是重复提交表单。 有效时间为10秒内。
+ * 
+ * @author ruoyi
+ */
+@Component
+public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
+{
+    public final String REPEAT_PARAMS = "repeatParams";
+
+    public final String REPEAT_TIME = "repeatTime";
+
+    public final String SESSION_REPEAT_KEY = "repeatData";
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation) throws Exception
+    {
+        // 本次参数及系统时间
+        String nowParams = JSON.marshal(request.getParameterMap());
+        Map<String, Object> nowDataMap = new HashMap<String, Object>();
+        nowDataMap.put(REPEAT_PARAMS, nowParams);
+        nowDataMap.put(REPEAT_TIME, System.currentTimeMillis());
+
+        // 请求地址(作为存放session的key值)
+        String url = request.getRequestURI();
+
+        HttpSession session = request.getSession();
+        Object sessionObj = session.getAttribute(SESSION_REPEAT_KEY);
+        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> sessionMap = new HashMap<String, Object>();
+        sessionMap.put(url, nowDataMap);
+        session.setAttribute(SESSION_REPEAT_KEY, sessionMap);
+        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/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/AsyncManager.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/AsyncManager.java
new file mode 100644
index 0000000..8f78300
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/AsyncManager.java
@@ -0,0 +1,55 @@
+package com.ruoyi.framework.manager;
+
+import java.util.TimerTask;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import com.ruoyi.common.utils.Threads;
+import com.ruoyi.common.utils.spring.SpringUtils;
+
+/**
+ * 异步任务管理器
+ * 
+ * @author liuhulu
+ */
+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/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/ShutdownManager.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/ShutdownManager.java
new file mode 100644
index 0000000..78a4af3
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/ShutdownManager.java
@@ -0,0 +1,87 @@
+package com.ruoyi.framework.manager;
+
+import com.ruoyi.framework.shiro.web.session.SpringSessionValidationScheduler;
+import net.sf.ehcache.CacheManager;
+import org.apache.shiro.cache.ehcache.EhCacheManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import javax.annotation.PreDestroy;
+
+/**
+ * 确保应用退出时能关闭后台线程
+ *
+ * @author cj
+ */
+@Component
+public class ShutdownManager
+{
+    private static final Logger logger = LoggerFactory.getLogger("sys-user");
+
+    @Autowired(required = false)
+    private SpringSessionValidationScheduler springSessionValidationScheduler;
+
+    @Autowired(required = false)
+    private EhCacheManager ehCacheManager;
+
+    @PreDestroy
+    public void destroy()
+    {
+        shutdownSpringSessionValidationScheduler();
+        shutdownAsyncManager();
+        shutdownEhCacheManager();
+    }
+
+    /**
+     * 停止Seesion会话检查
+     */
+    private void shutdownSpringSessionValidationScheduler()
+    {
+        if (springSessionValidationScheduler != null && springSessionValidationScheduler.isEnabled())
+        {
+            try
+            {
+                logger.info("====关闭会话验证任务====");
+                springSessionValidationScheduler.disableSessionValidation();
+            }
+            catch (Exception e)
+            {
+                logger.error(e.getMessage(), e);
+            }
+        }
+    }
+
+    /**
+     * 停止异步执行任务
+     */
+    private void shutdownAsyncManager()
+    {
+        try
+        {
+            logger.info("====关闭后台任务任务线程池====");
+            AsyncManager.me().shutdown();
+        }
+        catch (Exception e)
+        {
+            logger.error(e.getMessage(), e);
+        }
+    }
+
+    private void shutdownEhCacheManager()
+    {
+        try
+        {
+            logger.info("====关闭缓存====");
+            if (ehCacheManager != null)
+            {
+                CacheManager cacheManager = ehCacheManager.getCacheManager();
+                cacheManager.shutdown();
+            }
+        }
+        catch (Exception e)
+        {
+            logger.error(e.getMessage(), e);
+        }
+    }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/factory/AsyncFactory.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/factory/AsyncFactory.java
new file mode 100644
index 0000000..befa9ca
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/factory/AsyncFactory.java
@@ -0,0 +1,136 @@
+package com.ruoyi.framework.manager.factory;
+
+import java.util.TimerTask;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.utils.AddressUtils;
+import com.ruoyi.common.utils.LogUtils;
+import com.ruoyi.common.utils.ServletUtils;
+import com.ruoyi.common.utils.ShiroUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.spring.SpringUtils;
+import com.ruoyi.framework.shiro.session.OnlineSession;
+import com.ruoyi.system.domain.SysLogininfor;
+import com.ruoyi.system.domain.SysOperLog;
+import com.ruoyi.system.domain.SysUserOnline;
+import com.ruoyi.system.service.ISysOperLogService;
+import com.ruoyi.system.service.ISysUserOnlineService;
+import com.ruoyi.system.service.impl.SysLogininforServiceImpl;
+import eu.bitwalker.useragentutils.UserAgent;
+
+/**
+ * 异步工厂(产生任务用)
+ * 
+ * @author liuhulu
+ *
+ */
+public class AsyncFactory
+{
+    private static final Logger sys_user_logger = LoggerFactory.getLogger("sys-user");
+
+    /**
+     * 同步session到数据库
+     * 
+     * @param session 在线用户会话
+     * @return 任务task
+     */
+    public static TimerTask syncSessionToDb(final OnlineSession session)
+    {
+        return new TimerTask()
+        {
+            @Override
+            public void run()
+            {
+                SysUserOnline online = new SysUserOnline();
+                online.setSessionId(String.valueOf(session.getId()));
+                online.setDeptName(session.getDeptName());
+                online.setLoginName(session.getLoginName());
+                online.setStartTimestamp(session.getStartTimestamp());
+                online.setLastAccessTime(session.getLastAccessTime());
+                online.setExpireTime(session.getTimeout());
+                online.setIpaddr(session.getHost());
+                online.setLoginLocation(AddressUtils.getRealAddressByIP(session.getHost()));
+                online.setBrowser(session.getBrowser());
+                online.setOs(session.getOs());
+                online.setStatus(session.getStatus());
+                SpringUtils.getBean(ISysUserOnlineService.class).saveOnline(online);
+
+            }
+        };
+    }
+
+    /**
+     * 操作日志记录
+     * 
+     * @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);
+            }
+        };
+    }
+
+    /**
+     * 记录登录信息
+     * 
+     * @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 = ShiroUtils.getIp();
+        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.setLoginName(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(SysLogininforServiceImpl.class).insertLogininfor(logininfor);
+            }
+        };
+    }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/realm/UserRealm.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/realm/UserRealm.java
new file mode 100644
index 0000000..e77fafc
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/realm/UserRealm.java
@@ -0,0 +1,158 @@
+package com.ruoyi.framework.shiro.realm;
+
+import java.util.HashSet;
+import java.util.Set;
+import org.apache.shiro.authc.AuthenticationException;
+import org.apache.shiro.authc.AuthenticationInfo;
+import org.apache.shiro.authc.AuthenticationToken;
+import org.apache.shiro.authc.ExcessiveAttemptsException;
+import org.apache.shiro.authc.IncorrectCredentialsException;
+import org.apache.shiro.authc.LockedAccountException;
+import org.apache.shiro.authc.SimpleAuthenticationInfo;
+import org.apache.shiro.authc.UnknownAccountException;
+import org.apache.shiro.authc.UsernamePasswordToken;
+import org.apache.shiro.authz.AuthorizationInfo;
+import org.apache.shiro.authz.SimpleAuthorizationInfo;
+import org.apache.shiro.cache.Cache;
+import org.apache.shiro.realm.AuthorizingRealm;
+import org.apache.shiro.subject.PrincipalCollection;
+import org.apache.shiro.subject.SimplePrincipalCollection;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.exception.user.CaptchaException;
+import com.ruoyi.common.exception.user.RoleBlockedException;
+import com.ruoyi.common.exception.user.UserBlockedException;
+import com.ruoyi.common.exception.user.UserNotExistsException;
+import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
+import com.ruoyi.common.exception.user.UserPasswordRetryLimitExceedException;
+import com.ruoyi.common.utils.ShiroUtils;
+import com.ruoyi.framework.shiro.service.SysLoginService;
+import com.ruoyi.system.service.ISysMenuService;
+import com.ruoyi.system.service.ISysRoleService;
+
+/**
+ * 自定义Realm 处理登录 权限
+ * 
+ * @author ruoyi
+ */
+public class UserRealm extends AuthorizingRealm
+{
+    private static final Logger log = LoggerFactory.getLogger(UserRealm.class);
+
+    @Autowired
+    private ISysMenuService menuService;
+
+    @Autowired
+    private ISysRoleService roleService;
+
+    @Autowired
+    private SysLoginService loginService;
+
+    /**
+     * 授权
+     */
+    @Override
+    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0)
+    {
+        SysUser user = ShiroUtils.getSysUser();
+        // 角色列表
+        Set<String> roles = new HashSet<String>();
+        // 功能列表
+        Set<String> menus = new HashSet<String>();
+        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
+        // 管理员拥有所有权限
+        if (user.isAdmin())
+        {
+            info.addRole("admin");
+            info.addStringPermission("*:*:*");
+        }
+        else
+        {
+            roles = roleService.selectRoleKeys(user.getUserId());
+            menus = menuService.selectPermsByUserId(user.getUserId());
+            // 角色加入AuthorizationInfo认证对象
+            info.setRoles(roles);
+            // 权限加入AuthorizationInfo认证对象
+            info.setStringPermissions(menus);
+        }
+        return info;
+    }
+
+    /**
+     * 登录认证
+     */
+    @Override
+    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException
+    {
+        UsernamePasswordToken upToken = (UsernamePasswordToken) token;
+        String username = upToken.getUsername();
+        String password = "";
+        if (upToken.getPassword() != null)
+        {
+            password = new String(upToken.getPassword());
+        }
+
+        SysUser user = null;
+        try
+        {
+            user = loginService.login(username, password);
+        }
+        catch (CaptchaException e)
+        {
+            throw new AuthenticationException(e.getMessage(), e);
+        }
+        catch (UserNotExistsException e)
+        {
+            throw new UnknownAccountException(e.getMessage(), e);
+        }
+        catch (UserPasswordNotMatchException e)
+        {
+            throw new IncorrectCredentialsException(e.getMessage(), e);
+        }
+        catch (UserPasswordRetryLimitExceedException e)
+        {
+            throw new ExcessiveAttemptsException(e.getMessage(), e);
+        }
+        catch (UserBlockedException e)
+        {
+            throw new LockedAccountException(e.getMessage(), e);
+        }
+        catch (RoleBlockedException e)
+        {
+            throw new LockedAccountException(e.getMessage(), e);
+        }
+        catch (Exception e)
+        {
+            log.info("对用户[" + username + "]进行登录验证..验证未通过{}", e.getMessage());
+            throw new AuthenticationException(e.getMessage(), e);
+        }
+        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password, getName());
+        return info;
+    }
+
+    /**
+     * 清理指定用户授权信息缓存
+     */
+    public void clearCachedAuthorizationInfo(Object principal)
+    {
+        SimplePrincipalCollection principals = new SimplePrincipalCollection(principal, getName());
+        this.clearCachedAuthorizationInfo(principals);
+    }
+
+    /**
+     * 清理所有用户授权信息缓存
+     */
+    public void clearAllCachedAuthorizationInfo()
+    {
+        Cache<Object, AuthorizationInfo> cache = getAuthorizationCache();
+        if (cache != null)
+        {
+            for (Object key : cache.keys())
+            {
+                cache.remove(key);
+            }
+        }
+    }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/rememberMe/CustomCookieRememberMeManager.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/rememberMe/CustomCookieRememberMeManager.java
new file mode 100644
index 0000000..8123092
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/rememberMe/CustomCookieRememberMeManager.java
@@ -0,0 +1,79 @@
+package com.ruoyi.framework.shiro.rememberMe;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.apache.shiro.subject.PrincipalCollection;
+import org.apache.shiro.subject.Subject;
+import org.apache.shiro.subject.SubjectContext;
+import org.apache.shiro.web.mgt.CookieRememberMeManager;
+import com.ruoyi.common.core.domain.entity.SysRole;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.utils.spring.SpringUtils;
+import com.ruoyi.framework.shiro.service.SysLoginService;
+
+/**
+ * 自定义CookieRememberMeManager
+ *
+ * @author ruoyi
+ */
+public class CustomCookieRememberMeManager extends CookieRememberMeManager
+{
+    /**
+     * 记住我时去掉角色的permissions权限字符串,防止http请求头过大。
+     */
+    @Override
+    protected void rememberIdentity(Subject subject, PrincipalCollection principalCollection)
+    {
+        Map<SysRole, Set<String>> rolePermissions = new HashMap<>();
+        // 清除角色的permissions权限字符串
+        for (Object principal : principalCollection)
+        {
+            if (principal instanceof SysUser)
+            {
+                List<SysRole> roles = ((SysUser) principal).getRoles();
+                for (SysRole role : roles)
+                {
+                    rolePermissions.put(role, role.getPermissions());
+                    role.setPermissions(null);
+                }
+            }
+        }
+        byte[] bytes = convertPrincipalsToBytes(principalCollection);
+        // 恢复角色的permissions权限字符串
+        for (Object principal : principalCollection)
+        {
+            if (principal instanceof SysUser)
+            {
+                List<SysRole> roles = ((SysUser) principal).getRoles();
+                for (SysRole role : roles)
+                {
+                    role.setPermissions(rolePermissions.get(role));
+                }
+            }
+        }
+        rememberSerializedIdentity(subject, bytes);
+    }
+
+    /**
+     * 取记住我身份时恢复角色permissions权限字符串。
+     */
+    @Override
+    public PrincipalCollection getRememberedPrincipals(SubjectContext subjectContext)
+    {
+        PrincipalCollection principals = super.getRememberedPrincipals(subjectContext);
+        if (principals == null || principals.isEmpty())
+        {
+            return principals;
+        }
+        for (Object principal : principals)
+        {
+            if (principal instanceof SysUser)
+            {
+                SpringUtils.getBean(SysLoginService.class).setRolePermission((SysUser) principal);
+            }
+        }
+        return principals;
+    }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/service/SysLoginService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/service/SysLoginService.java
new file mode 100644
index 0000000..b3baf1d
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/service/SysLoginService.java
@@ -0,0 +1,188 @@
+package com.ruoyi.framework.shiro.service;
+
+import java.util.List;
+import java.util.Set;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.constant.ShiroConstants;
+import com.ruoyi.common.constant.UserConstants;
+import com.ruoyi.common.core.domain.entity.SysRole;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.enums.UserStatus;
+import com.ruoyi.common.exception.user.BlackListException;
+import com.ruoyi.common.exception.user.CaptchaException;
+import com.ruoyi.common.exception.user.UserBlockedException;
+import com.ruoyi.common.exception.user.UserDeleteException;
+import com.ruoyi.common.exception.user.UserNotExistsException;
+import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.IpUtils;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.ServletUtils;
+import com.ruoyi.common.utils.ShiroUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.framework.manager.AsyncManager;
+import com.ruoyi.framework.manager.factory.AsyncFactory;
+import com.ruoyi.system.service.ISysConfigService;
+import com.ruoyi.system.service.ISysMenuService;
+import com.ruoyi.system.service.ISysUserService;
+
+/**
+ * 登录校验方法
+ * 
+ * @author ruoyi
+ */
+@Component
+public class SysLoginService
+{
+    @Autowired
+    private SysPasswordService passwordService;
+
+    @Autowired
+    private ISysUserService userService;
+
+    @Autowired
+    private ISysMenuService menuService;
+
+    @Autowired
+    private ISysConfigService configService;
+
+    /**
+     * 登录
+     */
+    public SysUser login(String username, String password)
+    {
+        // 验证码校验
+        if (ShiroConstants.CAPTCHA_ERROR.equals(ServletUtils.getRequest().getAttribute(ShiroConstants.CURRENT_CAPTCHA)))
+        {
+            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
+            throw new CaptchaException();
+        }
+        // 用户名或密码为空 错误
+        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, ShiroUtils.getIp()))
+        {
+            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("login.blocked")));
+            throw new BlackListException();
+        }
+
+        // 查询用户信息
+        SysUser user = userService.selectUserByLoginName(username);
+
+        /**
+        if (user == null && maybeMobilePhoneNumber(username))
+        {
+            user = userService.selectUserByPhoneNumber(username);
+        }
+
+        if (user == null && maybeEmail(username))
+        {
+            user = userService.selectUserByEmail(username);
+        }
+        */
+
+        if (user == null)
+        {
+            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.not.exists")));
+            throw new UserNotExistsException();
+        }
+        
+        if (UserStatus.DELETED.getCode().equals(user.getDelFlag()))
+        {
+            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.delete")));
+            throw new UserDeleteException();
+        }
+        
+        if (UserStatus.DISABLE.getCode().equals(user.getStatus()))
+        {
+            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.blocked")));
+            throw new UserBlockedException();
+        }
+
+        passwordService.validate(user, password);
+
+        AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
+        setRolePermission(user);
+        recordLoginInfo(user.getUserId());
+        return user;
+    }
+
+    /**
+    private boolean maybeEmail(String username)
+    {
+        if (!username.matches(UserConstants.EMAIL_PATTERN))
+        {
+            return false;
+        }
+        return true;
+    }
+
+    private boolean maybeMobilePhoneNumber(String username)
+    {
+        if (!username.matches(UserConstants.MOBILE_PHONE_NUMBER_PATTERN))
+        {
+            return false;
+        }
+        return true;
+    }
+    */
+
+    /**
+     * 设置角色权限
+     *
+     * @param user 用户信息
+     */
+    public void setRolePermission(SysUser user)
+    {
+        List<SysRole> roles = user.getRoles();
+        if (!roles.isEmpty())
+        {
+            // 设置permissions属性,以便数据权限匹配权限
+            for (SysRole role : roles)
+            {
+                if (StringUtils.equals(role.getStatus(), UserConstants.ROLE_NORMAL))
+                {
+                    Set<String> rolePerms = menuService.selectPermsByRoleId(role.getRoleId());
+                    role.setPermissions(rolePerms);
+                }
+            }
+        }
+    }
+
+    /**
+     * 记录登录信息
+     *
+     * @param userId 用户ID
+     */
+    public void recordLoginInfo(Long userId)
+    {
+        SysUser user = new SysUser();
+        user.setUserId(userId);
+        user.setLoginIp(ShiroUtils.getIp());
+        user.setLoginDate(DateUtils.getNowDate());
+        userService.updateUserInfo(user);
+    }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/service/SysPasswordService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/service/SysPasswordService.java
new file mode 100644
index 0000000..571d790
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/service/SysPasswordService.java
@@ -0,0 +1,85 @@
+package com.ruoyi.framework.shiro.service;
+
+import java.util.concurrent.atomic.AtomicInteger;
+import javax.annotation.PostConstruct;
+import org.apache.shiro.cache.Cache;
+import org.apache.shiro.cache.CacheManager;
+import org.apache.shiro.crypto.hash.Md5Hash;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.constant.ShiroConstants;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
+import com.ruoyi.common.exception.user.UserPasswordRetryLimitExceedException;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.framework.manager.AsyncManager;
+import com.ruoyi.framework.manager.factory.AsyncFactory;
+
+/**
+ * 登录密码方法
+ * 
+ * @author ruoyi
+ */
+@Component
+public class SysPasswordService
+{
+    @Autowired
+    private CacheManager cacheManager;
+
+    private Cache<String, AtomicInteger> loginRecordCache;
+
+    @Value(value = "${user.password.maxRetryCount}")
+    private String maxRetryCount;
+
+    @PostConstruct
+    public void init()
+    {
+        loginRecordCache = cacheManager.getCache(ShiroConstants.LOGIN_RECORD_CACHE);
+    }
+
+    public void validate(SysUser user, String password)
+    {
+        String loginName = user.getLoginName();
+
+        AtomicInteger retryCount = loginRecordCache.get(loginName);
+
+        if (retryCount == null)
+        {
+            retryCount = new AtomicInteger(0);
+            loginRecordCache.put(loginName, retryCount);
+        }
+        if (retryCount.incrementAndGet() > Integer.valueOf(maxRetryCount).intValue())
+        {
+            AsyncManager.me().execute(AsyncFactory.recordLogininfor(loginName, Constants.LOGIN_FAIL, MessageUtils.message("user.password.retry.limit.exceed", maxRetryCount)));
+            throw new UserPasswordRetryLimitExceedException(Integer.valueOf(maxRetryCount).intValue());
+        }
+
+        if (!matches(user, password))
+        {
+            AsyncManager.me().execute(AsyncFactory.recordLogininfor(loginName, Constants.LOGIN_FAIL, MessageUtils.message("user.password.retry.limit.count", retryCount)));
+            loginRecordCache.put(loginName, retryCount);
+            throw new UserPasswordNotMatchException();
+        }
+        else
+        {
+            clearLoginRecordCache(loginName);
+        }
+    }
+
+    public boolean matches(SysUser user, String newPassword)
+    {
+        return user.getPassword().equals(encryptPassword(user.getLoginName(), newPassword, user.getSalt()));
+    }
+
+    public void clearLoginRecordCache(String loginName)
+    {
+        loginRecordCache.remove(loginName);
+    }
+
+    public String encryptPassword(String loginName, String password, String salt)
+    {
+        return new Md5Hash(loginName + password + salt).toHex();
+    }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/service/SysRegisterService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/service/SysRegisterService.java
new file mode 100644
index 0000000..690fbf2
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/service/SysRegisterService.java
@@ -0,0 +1,83 @@
+package com.ruoyi.framework.shiro.service;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.constant.ShiroConstants;
+import com.ruoyi.common.constant.UserConstants;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.ServletUtils;
+import com.ruoyi.common.utils.ShiroUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.framework.manager.AsyncManager;
+import com.ruoyi.framework.manager.factory.AsyncFactory;
+import com.ruoyi.system.service.ISysUserService;
+
+/**
+ * 注册校验方法
+ * 
+ * @author ruoyi
+ */
+@Component
+public class SysRegisterService
+{
+    @Autowired
+    private ISysUserService userService;
+
+    @Autowired
+    private SysPasswordService passwordService;
+
+    /**
+     * 注册
+     */
+    public String register(SysUser user)
+    {
+        String msg = "", loginName = user.getLoginName(), password = user.getPassword();
+
+        if (ShiroConstants.CAPTCHA_ERROR.equals(ServletUtils.getRequest().getAttribute(ShiroConstants.CURRENT_CAPTCHA)))
+        {
+            msg = "验证码错误";
+        }
+        else if (StringUtils.isEmpty(loginName))
+        {
+            msg = "用户名不能为空";
+        }
+        else if (StringUtils.isEmpty(password))
+        {
+            msg = "用户密码不能为空";
+        }
+        else if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
+                || password.length() > UserConstants.PASSWORD_MAX_LENGTH)
+        {
+            msg = "密码长度必须在5到20个字符之间";
+        }
+        else if (loginName.length() < UserConstants.USERNAME_MIN_LENGTH
+                || loginName.length() > UserConstants.USERNAME_MAX_LENGTH)
+        {
+            msg = "账户长度必须在2到20个字符之间";
+        }
+        else if (!userService.checkLoginNameUnique(user))
+        {
+            msg = "保存用户'" + loginName + "'失败,注册账号已存在";
+        }
+        else
+        {
+            user.setPwdUpdateDate(DateUtils.getNowDate());
+            user.setUserName(loginName);
+            user.setSalt(ShiroUtils.randomSalt());
+            user.setPassword(passwordService.encryptPassword(loginName, password, user.getSalt()));
+            boolean regFlag = userService.registerUser(user);
+            if (!regFlag)
+            {
+                msg = "注册失败,请联系系统管理人员";
+            }
+            else
+            {
+                AsyncManager.me().execute(AsyncFactory.recordLogininfor(loginName, Constants.REGISTER, MessageUtils.message("user.register.success")));
+            }
+        }
+        return msg;
+    }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/service/SysShiroService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/service/SysShiroService.java
new file mode 100644
index 0000000..1fb9c7e
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/service/SysShiroService.java
@@ -0,0 +1,62 @@
+package com.ruoyi.framework.shiro.service;
+
+import java.io.Serializable;
+import org.apache.shiro.session.Session;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.framework.shiro.session.OnlineSession;
+import com.ruoyi.system.domain.SysUserOnline;
+import com.ruoyi.system.service.ISysUserOnlineService;
+
+/**
+ * 会话db操作处理
+ * 
+ * @author ruoyi
+ */
+@Component
+public class SysShiroService
+{
+    @Autowired
+    private ISysUserOnlineService onlineService;
+
+    /**
+     * 删除会话
+     *
+     * @param onlineSession 会话信息
+     */
+    public void deleteSession(OnlineSession onlineSession)
+    {
+        onlineService.deleteOnlineById(String.valueOf(onlineSession.getId()));
+    }
+
+    /**
+     * 获取会话信息
+     *
+     * @param sessionId
+     * @return
+     */
+    public Session getSession(Serializable sessionId)
+    {
+        SysUserOnline userOnline = onlineService.selectOnlineById(String.valueOf(sessionId));
+        return StringUtils.isNull(userOnline) ? null : createSession(userOnline);
+    }
+
+    public Session createSession(SysUserOnline userOnline)
+    {
+        OnlineSession onlineSession = new OnlineSession();
+        if (StringUtils.isNotNull(userOnline))
+        {
+            onlineSession.setId(userOnline.getSessionId());
+            onlineSession.setHost(userOnline.getIpaddr());
+            onlineSession.setBrowser(userOnline.getBrowser());
+            onlineSession.setOs(userOnline.getOs());
+            onlineSession.setDeptName(userOnline.getDeptName());
+            onlineSession.setLoginName(userOnline.getLoginName());
+            onlineSession.setStartTimestamp(userOnline.getStartTimestamp());
+            onlineSession.setLastAccessTime(userOnline.getLastAccessTime());
+            onlineSession.setTimeout(userOnline.getExpireTime());
+        }
+        return onlineSession;
+    }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/session/OnlineSession.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/session/OnlineSession.java
new file mode 100644
index 0000000..f9c417c
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/session/OnlineSession.java
@@ -0,0 +1,165 @@
+package com.ruoyi.framework.shiro.session;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import org.apache.shiro.session.mgt.SimpleSession;
+import com.ruoyi.common.enums.OnlineStatus;
+
+/**
+ * 在线用户会话属性
+ * 
+ * @author ruoyi
+ */
+public class OnlineSession extends SimpleSession
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 用户ID */
+    private Long userId;
+
+    /** 用户名称 */
+    private String loginName;
+
+    /** 部门名称 */
+    private String deptName;
+	
+	/** 用户头像 */
+	private String avatar;
+
+    /** 登录IP地址 */
+    private String host;
+
+    /** 浏览器类型 */
+    private String browser;
+
+    /** 操作系统 */
+    private String os;
+
+    /** 在线状态 */
+    private OnlineStatus status = OnlineStatus.on_line;
+
+    /** 属性是否改变 优化session数据同步 */
+    private transient boolean attributeChanged = false;
+
+    @Override
+    public String getHost()
+    {
+        return host;
+    }
+
+    @Override
+    public void setHost(String host)
+    {
+        this.host = host;
+    }
+
+    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 getUserId()
+    {
+        return userId;
+    }
+
+    public void setUserId(Long userId)
+    {
+        this.userId = userId;
+    }
+
+    public String getLoginName()
+    {
+        return loginName;
+    }
+
+    public void setLoginName(String loginName)
+    {
+        this.loginName = loginName;
+    }
+
+    public String getDeptName()
+    {
+        return deptName;
+    }
+
+    public void setDeptName(String deptName)
+    {
+        this.deptName = deptName;
+    }
+
+    public OnlineStatus getStatus()
+    {
+        return status;
+    }
+
+    public void setStatus(OnlineStatus status)
+    {
+        this.status = status;
+    }
+
+    public void markAttributeChanged()
+    {
+        this.attributeChanged = true;
+    }
+
+    public void resetAttributeChanged()
+    {
+        this.attributeChanged = false;
+    }
+
+    public boolean isAttributeChanged()
+    {
+        return attributeChanged;
+    }
+
+	public String getAvatar() {
+		return avatar;
+	}
+
+	public void setAvatar(String avatar) {
+		this.avatar = avatar;
+	}
+	
+    @Override
+    public void setAttribute(Object key, Object value)
+    {
+        super.setAttribute(key, value);
+    }
+
+    @Override
+    public Object removeAttribute(Object key)
+    {
+        return super.removeAttribute(key);
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("userId", getUserId())
+            .append("loginName", getLoginName())
+            .append("deptName", getDeptName())
+            .append("avatar", getAvatar())
+            .append("host", getHost())
+            .append("browser", getBrowser())
+            .append("os", getOs())
+            .append("status", getStatus())
+            .append("attributeChanged", isAttributeChanged())
+            .toString();
+    }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/session/OnlineSessionDAO.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/session/OnlineSessionDAO.java
new file mode 100644
index 0000000..3ee1862
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/session/OnlineSessionDAO.java
@@ -0,0 +1,117 @@
+package com.ruoyi.framework.shiro.session;
+
+import java.io.Serializable;
+import java.util.Date;
+import org.apache.shiro.session.Session;
+import org.apache.shiro.session.UnknownSessionException;
+import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import com.ruoyi.common.enums.OnlineStatus;
+import com.ruoyi.framework.manager.AsyncManager;
+import com.ruoyi.framework.manager.factory.AsyncFactory;
+import com.ruoyi.framework.shiro.service.SysShiroService;
+
+/**
+ * 针对自定义的ShiroSession的db操作
+ * 
+ * @author ruoyi
+ */
+public class OnlineSessionDAO extends EnterpriseCacheSessionDAO
+{
+    /**
+     * 同步session到数据库的周期 单位为毫秒(默认1分钟)
+     */
+    @Value("${shiro.session.dbSyncPeriod}")
+    private int dbSyncPeriod;
+
+    /**
+     * 上次同步数据库的时间戳
+     */
+    private static final String LAST_SYNC_DB_TIMESTAMP = OnlineSessionDAO.class.getName() + "LAST_SYNC_DB_TIMESTAMP";
+
+    @Autowired
+    private SysShiroService sysShiroService;
+
+    public OnlineSessionDAO()
+    {
+        super();
+    }
+
+    public OnlineSessionDAO(long expireTime)
+    {
+        super();
+    }
+
+    /**
+     * 根据会话ID获取会话
+     *
+     * @param sessionId 会话ID
+     * @return ShiroSession
+     */
+    @Override
+    protected Session doReadSession(Serializable sessionId)
+    {
+        return sysShiroService.getSession(sessionId);
+    }
+
+    @Override
+    public void update(Session session) throws UnknownSessionException
+    {
+        super.update(session);
+    }
+
+    /**
+     * 更新会话;如更新会话最后访问时间/停止会话/设置超时时间/设置移除属性等会调用
+     */
+    public void syncToDb(OnlineSession onlineSession)
+    {
+        Date lastSyncTimestamp = (Date) onlineSession.getAttribute(LAST_SYNC_DB_TIMESTAMP);
+        if (lastSyncTimestamp != null)
+        {
+            boolean needSync = true;
+            long deltaTime = onlineSession.getLastAccessTime().getTime() - lastSyncTimestamp.getTime();
+            if (deltaTime < dbSyncPeriod * 60 * 1000)
+            {
+                // 时间差不足 无需同步
+                needSync = false;
+            }
+            // isGuest = true 访客
+            boolean isGuest = onlineSession.getUserId() == null || onlineSession.getUserId() == 0L;
+
+            // session 数据变更了 同步
+            if (!isGuest && onlineSession.isAttributeChanged())
+            {
+                needSync = true;
+            }
+
+            if (!needSync)
+            {
+                return;
+            }
+        }
+        // 更新上次同步数据库时间
+        onlineSession.setAttribute(LAST_SYNC_DB_TIMESTAMP, onlineSession.getLastAccessTime());
+        // 更新完后 重置标识
+        if (onlineSession.isAttributeChanged())
+        {
+            onlineSession.resetAttributeChanged();
+        }
+        AsyncManager.me().execute(AsyncFactory.syncSessionToDb(onlineSession));
+    }
+
+    /**
+     * 当会话过期/停止(如用户退出时)属性等会调用
+     */
+    @Override
+    protected void doDelete(Session session)
+    {
+        OnlineSession onlineSession = (OnlineSession) session;
+        if (null == onlineSession)
+        {
+            return;
+        }
+        onlineSession.setStatus(OnlineStatus.off_line);
+        sysShiroService.deleteSession(onlineSession);
+    }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/session/OnlineSessionFactory.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/session/OnlineSessionFactory.java
new file mode 100644
index 0000000..24d9d75
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/session/OnlineSessionFactory.java
@@ -0,0 +1,42 @@
+package com.ruoyi.framework.shiro.session;
+
+import javax.servlet.http.HttpServletRequest;
+import org.apache.shiro.session.Session;
+import org.apache.shiro.session.mgt.SessionContext;
+import org.apache.shiro.session.mgt.SessionFactory;
+import org.apache.shiro.web.session.mgt.WebSessionContext;
+import org.springframework.stereotype.Component;
+import com.ruoyi.common.utils.IpUtils;
+import eu.bitwalker.useragentutils.UserAgent;
+
+/**
+ * 自定义sessionFactory会话
+ * 
+ * @author ruoyi
+ */
+@Component
+public class OnlineSessionFactory implements SessionFactory
+{
+    @Override
+    public Session createSession(SessionContext initData)
+    {
+        OnlineSession session = new OnlineSession();
+        if (initData != null && initData instanceof WebSessionContext)
+        {
+            WebSessionContext sessionContext = (WebSessionContext) initData;
+            HttpServletRequest request = (HttpServletRequest) sessionContext.getServletRequest();
+            if (request != null)
+            {
+                UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
+                // 获取客户端操作系统
+                String os = userAgent.getOperatingSystem().getName();
+                // 获取客户端浏览器
+                String browser = userAgent.getBrowser().getName();
+                session.setHost(IpUtils.getIpAddr(request));
+                session.setBrowser(browser);
+                session.setOs(os);
+            }
+        }
+        return session;
+    }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/util/AuthorizationUtils.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/util/AuthorizationUtils.java
new file mode 100644
index 0000000..7ea7e6f
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/util/AuthorizationUtils.java
@@ -0,0 +1,30 @@
+package com.ruoyi.framework.shiro.util;
+
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.mgt.RealmSecurityManager;
+import com.ruoyi.framework.shiro.realm.UserRealm;
+
+/**
+ * 用户授权信息
+ * 
+ * @author ruoyi
+ */
+public class AuthorizationUtils
+{
+    /**
+     * 清理所有用户授权信息缓存
+     */
+    public static void clearAllCachedAuthorizationInfo()
+    {
+        getUserRealm().clearAllCachedAuthorizationInfo();
+    }
+
+    /**
+     * 获取自定义Realm
+     */
+    public static UserRealm getUserRealm()
+    {
+        RealmSecurityManager rsm = (RealmSecurityManager) SecurityUtils.getSecurityManager();
+        return (UserRealm) rsm.getRealms().iterator().next();
+    }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/web/CustomShiroFilterFactoryBean.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/web/CustomShiroFilterFactoryBean.java
new file mode 100644
index 0000000..a859fa1
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/web/CustomShiroFilterFactoryBean.java
@@ -0,0 +1,85 @@
+package com.ruoyi.framework.shiro.web;
+
+import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
+import org.apache.shiro.web.filter.InvalidRequestFilter;
+import org.apache.shiro.web.filter.mgt.DefaultFilter;
+import org.apache.shiro.web.filter.mgt.FilterChainManager;
+import org.apache.shiro.web.filter.mgt.FilterChainResolver;
+import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
+import org.apache.shiro.web.mgt.WebSecurityManager;
+import org.apache.shiro.web.servlet.AbstractShiroFilter;
+import org.apache.shiro.mgt.SecurityManager;
+import org.springframework.beans.factory.BeanInitializationException;
+import javax.servlet.Filter;
+import java.util.Map;
+
+/**
+ * 自定义ShiroFilterFactoryBean解决资源中文路径问题
+ * 
+ * @author ruoyi
+ */
+public class CustomShiroFilterFactoryBean extends ShiroFilterFactoryBean
+{
+    @Override
+    public Class<MySpringShiroFilter> getObjectType()
+    {
+        return MySpringShiroFilter.class;
+    }
+
+    @Override
+    protected AbstractShiroFilter createInstance() throws Exception
+    {
+
+        SecurityManager securityManager = getSecurityManager();
+        if (securityManager == null)
+        {
+            String msg = "SecurityManager property must be set.";
+            throw new BeanInitializationException(msg);
+        }
+
+        if (!(securityManager instanceof WebSecurityManager))
+        {
+            String msg = "The security manager does not implement the WebSecurityManager interface.";
+            throw new BeanInitializationException(msg);
+        }
+
+        FilterChainManager manager = createFilterChainManager();
+        // Expose the constructed FilterChainManager by first wrapping it in a
+        // FilterChainResolver implementation. The AbstractShiroFilter implementations
+        // do not know about FilterChainManagers - only resolvers:
+        PathMatchingFilterChainResolver chainResolver = new PathMatchingFilterChainResolver();
+        chainResolver.setFilterChainManager(manager);
+
+        Map<String, Filter> filterMap = manager.getFilters();
+        Filter invalidRequestFilter = filterMap.get(DefaultFilter.invalidRequest.name());
+        if (invalidRequestFilter instanceof InvalidRequestFilter)
+        {
+            // 此处是关键,设置false跳过URL携带中文400,servletPath中文校验bug
+            ((InvalidRequestFilter) invalidRequestFilter).setBlockNonAscii(false);
+        }
+        // Now create a concrete ShiroFilter instance and apply the acquired SecurityManager and built
+        // FilterChainResolver. It doesn't matter that the instance is an anonymous inner class
+        // here - we're just using it because it is a concrete AbstractShiroFilter instance that accepts
+        // injection of the SecurityManager and FilterChainResolver:
+        return new MySpringShiroFilter((WebSecurityManager) securityManager, chainResolver);
+    }
+
+    private static final class MySpringShiroFilter extends AbstractShiroFilter
+    {
+        protected MySpringShiroFilter(WebSecurityManager webSecurityManager, FilterChainResolver resolver)
+        {
+            if (webSecurityManager == null)
+            {
+                throw new IllegalArgumentException("WebSecurityManager property cannot be null.");
+            }
+            else
+            {
+                this.setSecurityManager(webSecurityManager);
+                if (resolver != null)
+                {
+                    this.setFilterChainResolver(resolver);
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/web/filter/LogoutFilter.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/web/filter/LogoutFilter.java
new file mode 100644
index 0000000..c6dbfa5
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/web/filter/LogoutFilter.java
@@ -0,0 +1,90 @@
+package com.ruoyi.framework.shiro.web.filter;
+
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import org.apache.shiro.session.SessionException;
+import org.apache.shiro.subject.Subject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.ShiroUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.spring.SpringUtils;
+import com.ruoyi.framework.manager.AsyncManager;
+import com.ruoyi.framework.manager.factory.AsyncFactory;
+import com.ruoyi.system.service.ISysUserOnlineService;
+
+/**
+ * 退出过滤器
+ * 
+ * @author ruoyi
+ */
+public class LogoutFilter extends org.apache.shiro.web.filter.authc.LogoutFilter
+{
+    private static final Logger log = LoggerFactory.getLogger(LogoutFilter.class);
+
+    /**
+     * 退出后重定向的地址
+     */
+    private String loginUrl;
+
+    public String getLoginUrl()
+    {
+        return loginUrl;
+    }
+
+    public void setLoginUrl(String loginUrl)
+    {
+        this.loginUrl = loginUrl;
+    }
+
+    @Override
+    protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception
+    {
+        try
+        {
+            Subject subject = getSubject(request, response);
+            String redirectUrl = getRedirectUrl(request, response, subject);
+            try
+            {
+                SysUser user = ShiroUtils.getSysUser();
+                if (StringUtils.isNotNull(user))
+                {
+                    String loginName = user.getLoginName();
+                    // 记录用户退出日志
+                    AsyncManager.me().execute(AsyncFactory.recordLogininfor(loginName, Constants.LOGOUT, MessageUtils.message("user.logout.success")));
+                    // 清理缓存
+                    SpringUtils.getBean(ISysUserOnlineService.class).removeUserCache(loginName, ShiroUtils.getSessionId());
+                }
+                // 退出登录
+                subject.logout();
+            }
+            catch (SessionException ise)
+            {
+                log.error("logout fail.", ise);
+            }
+            issueRedirect(request, response, redirectUrl);
+        }
+        catch (Exception e)
+        {
+            log.error("Encountered session exception during logout.  This can generally safely be ignored.", e);
+        }
+        return false;
+    }
+
+    /**
+     * 退出跳转URL
+     */
+    @Override
+    protected String getRedirectUrl(ServletRequest request, ServletResponse response, Subject subject)
+    {
+        String url = getLoginUrl();
+        if (StringUtils.isNotEmpty(url))
+        {
+            return url;
+        }
+        return super.getRedirectUrl(request, response, subject);
+    }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/web/filter/captcha/CaptchaValidateFilter.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/web/filter/captcha/CaptchaValidateFilter.java
new file mode 100644
index 0000000..22dd339
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/web/filter/captcha/CaptchaValidateFilter.java
@@ -0,0 +1,79 @@
+package com.ruoyi.framework.shiro.web.filter.captcha;
+
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import org.apache.shiro.web.filter.AccessControlFilter;
+import com.google.code.kaptcha.Constants;
+import com.ruoyi.common.constant.ShiroConstants;
+import com.ruoyi.common.utils.ShiroUtils;
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * 验证码过滤器
+ * 
+ * @author ruoyi
+ */
+public class CaptchaValidateFilter extends AccessControlFilter
+{
+    /**
+     * 是否开启验证码
+     */
+    private boolean captchaEnabled = true;
+
+    /**
+     * 验证码类型
+     */
+    private String captchaType = "math";
+
+    public void setCaptchaEnabled(boolean captchaEnabled)
+    {
+        this.captchaEnabled = captchaEnabled;
+    }
+
+    public void setCaptchaType(String captchaType)
+    {
+        this.captchaType = captchaType;
+    }
+
+    @Override
+    public boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception
+    {
+        request.setAttribute(ShiroConstants.CURRENT_ENABLED, captchaEnabled);
+        request.setAttribute(ShiroConstants.CURRENT_TYPE, captchaType);
+        return super.onPreHandle(request, response, mappedValue);
+    }
+
+    @Override
+    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)
+            throws Exception
+    {
+        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
+        // 验证码禁用 或不是表单提交 允许访问
+        if (captchaEnabled == false || !"post".equals(httpServletRequest.getMethod().toLowerCase()))
+        {
+            return true;
+        }
+        return validateResponse(httpServletRequest, httpServletRequest.getParameter(ShiroConstants.CURRENT_VALIDATECODE));
+    }
+
+    public boolean validateResponse(HttpServletRequest request, String validateCode)
+    {
+        Object obj = ShiroUtils.getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY);
+        String code = String.valueOf(obj != null ? obj : "");
+        // 验证码清除,防止多次使用。
+        request.getSession().removeAttribute(Constants.KAPTCHA_SESSION_KEY);
+        if (StringUtils.isEmpty(validateCode) || !validateCode.equalsIgnoreCase(code))
+        {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception
+    {
+        request.setAttribute(ShiroConstants.CURRENT_CAPTCHA, ShiroConstants.CAPTCHA_ERROR);
+        return true;
+    }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/web/filter/kickout/KickoutSessionFilter.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/web/filter/kickout/KickoutSessionFilter.java
new file mode 100644
index 0000000..d92db34
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/web/filter/kickout/KickoutSessionFilter.java
@@ -0,0 +1,176 @@
+package com.ruoyi.framework.shiro.web.filter.kickout;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.ArrayDeque;
+import java.util.Deque;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.shiro.cache.Cache;
+import org.apache.shiro.cache.CacheManager;
+import org.apache.shiro.session.Session;
+import org.apache.shiro.session.mgt.DefaultSessionKey;
+import org.apache.shiro.session.mgt.SessionManager;
+import org.apache.shiro.subject.Subject;
+import org.apache.shiro.web.filter.AccessControlFilter;
+import org.apache.shiro.web.util.WebUtils;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.ruoyi.common.constant.ShiroConstants;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.utils.ServletUtils;
+import com.ruoyi.common.utils.ShiroUtils;
+
+/**
+ * 登录帐号控制过滤器
+ * 
+ * @author ruoyi
+ */
+public class KickoutSessionFilter extends AccessControlFilter
+{
+    private final static ObjectMapper objectMapper = new ObjectMapper();
+
+    /**
+     * 同一个用户最大会话数
+     **/
+    private int maxSession = -1;
+
+    /**
+     * 踢出之前登录的/之后登录的用户 默认false踢出之前登录的用户
+     **/
+    private Boolean kickoutAfter = false;
+
+    /**
+     * 踢出后到的地址
+     **/
+    private String kickoutUrl;
+
+    private SessionManager sessionManager;
+    private Cache<String, Deque<Serializable>> cache;
+
+    @Override
+    protected boolean isAccessAllowed(ServletRequest servletRequest, ServletResponse servletResponse, Object o)
+            throws Exception
+    {
+        return false;
+    }
+
+    @Override
+    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception
+    {
+        Subject subject = getSubject(request, response);
+        if (!subject.isAuthenticated() && !subject.isRemembered() || maxSession == -1)
+        {
+            // 如果没有登录或用户最大会话数为-1,直接进行之后的流程
+            return true;
+        }
+        try
+        {
+            Session session = subject.getSession();
+            // 当前登录用户
+            SysUser user = ShiroUtils.getSysUser();
+            String loginName = user.getLoginName();
+            Serializable sessionId = session.getId();
+
+            // 读取缓存用户 没有就存入
+            Deque<Serializable> deque = cache.get(loginName);
+            if (deque == null)
+            {
+                // 初始化队列
+                deque = new ArrayDeque<Serializable>();
+            }
+
+            // 如果队列里没有此sessionId,且用户没有被踢出;放入队列
+            if (!deque.contains(sessionId) && session.getAttribute("kickout") == null)
+            {
+                // 将sessionId存入队列
+                deque.push(sessionId);
+                // 将用户的sessionId队列缓存
+                cache.put(loginName, deque);
+            }
+
+            // 如果队列里的sessionId数超出最大会话数,开始踢人
+            while (deque.size() > maxSession)
+            {
+                // 是否踢出后来登录的,默认是false;即后者登录的用户踢出前者登录的用户;
+                Serializable kickoutSessionId = kickoutAfter ? deque.removeFirst() : deque.removeLast();
+                // 踢出后再更新下缓存队列
+                cache.put(loginName, deque);
+
+                try
+                {
+                    // 获取被踢出的sessionId的session对象
+                    Session kickoutSession = sessionManager.getSession(new DefaultSessionKey(kickoutSessionId));
+                    if (null != kickoutSession)
+                    {
+                        // 设置会话的kickout属性表示踢出了
+                        kickoutSession.setAttribute("kickout", true);
+                    }
+                }
+                catch (Exception e)
+                {
+                    // 面对异常,我们选择忽略
+                }
+            }
+
+            // 如果被踢出了,(前者或后者)直接退出,重定向到踢出后的地址
+            if (session.getAttribute("kickout") != null && (Boolean) session.getAttribute("kickout") == true)
+            {
+                // 退出登录
+                subject.logout();
+                saveRequest(request);
+                return isAjaxResponse(request, response);
+            }
+            return true;
+        }
+        catch (Exception e)
+        {
+            return isAjaxResponse(request, response);
+        }
+    }
+
+    private boolean isAjaxResponse(ServletRequest request, ServletResponse response) throws IOException
+    {
+        HttpServletRequest req = (HttpServletRequest) request;
+        HttpServletResponse res = (HttpServletResponse) response;
+        if (ServletUtils.isAjaxRequest(req))
+        {
+            AjaxResult ajaxResult = AjaxResult.error("您已在别处登录,请您修改密码或重新登录");
+            ServletUtils.renderString(res, objectMapper.writeValueAsString(ajaxResult));
+        }
+        else
+        {
+            WebUtils.issueRedirect(request, response, kickoutUrl);
+        }
+        return false;
+    }
+
+    public void setMaxSession(int maxSession)
+    {
+        this.maxSession = maxSession;
+    }
+
+    public void setKickoutAfter(boolean kickoutAfter)
+    {
+        this.kickoutAfter = kickoutAfter;
+    }
+
+    public void setKickoutUrl(String kickoutUrl)
+    {
+        this.kickoutUrl = kickoutUrl;
+    }
+
+    public void setSessionManager(SessionManager sessionManager)
+    {
+        this.sessionManager = sessionManager;
+    }
+
+    // 设置Cache的key的前缀
+    public void setCacheManager(CacheManager cacheManager)
+    {
+        // 必须和ehcache缓存配置中的缓存name一致
+        this.cache = cacheManager.getCache(ShiroConstants.SYS_USERCACHE);
+    }
+}
\ No newline at end of file
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/web/filter/online/OnlineSessionFilter.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/web/filter/online/OnlineSessionFilter.java
new file mode 100644
index 0000000..adf5120
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/web/filter/online/OnlineSessionFilter.java
@@ -0,0 +1,99 @@
+package com.ruoyi.framework.shiro.web.filter.online;
+
+import java.io.IOException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import org.apache.shiro.session.Session;
+import org.apache.shiro.subject.Subject;
+import org.apache.shiro.web.filter.AccessControlFilter;
+import org.apache.shiro.web.util.WebUtils;
+import org.springframework.beans.factory.annotation.Value;
+import com.ruoyi.common.constant.ShiroConstants;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.enums.OnlineStatus;
+import com.ruoyi.common.utils.ShiroUtils;
+import com.ruoyi.framework.shiro.session.OnlineSession;
+import com.ruoyi.framework.shiro.session.OnlineSessionDAO;
+
+/**
+ * 自定义访问控制
+ * 
+ * @author ruoyi
+ */
+public class OnlineSessionFilter extends AccessControlFilter
+{
+    /**
+     * 强制退出后重定向的地址
+     */
+    @Value("${shiro.user.loginUrl}")
+    private String loginUrl;
+
+    private OnlineSessionDAO onlineSessionDAO;
+
+    /**
+     * 表示是否允许访问;mappedValue就是[urls]配置中拦截器参数部分,如果允许访问返回true,否则false;
+     */
+    @Override
+    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)
+            throws Exception
+    {
+        Subject subject = getSubject(request, response);
+        if (subject == null || subject.getSession() == null)
+        {
+            return true;
+        }
+        Session session = onlineSessionDAO.readSession(subject.getSession().getId());
+        if (session != null && session instanceof OnlineSession)
+        {
+            OnlineSession onlineSession = (OnlineSession) session;
+            request.setAttribute(ShiroConstants.ONLINE_SESSION, onlineSession);
+            // 把user对象设置进去
+            boolean isGuest = onlineSession.getUserId() == null || onlineSession.getUserId() == 0L;
+            if (isGuest == true)
+            {
+                SysUser user = ShiroUtils.getSysUser();
+                if (user != null)
+                {
+                    onlineSession.setUserId(user.getUserId());
+                    onlineSession.setLoginName(user.getLoginName());
+					onlineSession.setAvatar(user.getAvatar());
+                    onlineSession.setDeptName(user.getDept().getDeptName());
+                    onlineSession.markAttributeChanged();
+                }
+            }
+
+            if (onlineSession.getStatus() == OnlineStatus.off_line)
+            {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * 表示当访问拒绝时是否已经处理了;如果返回true表示需要继续处理;如果返回false表示该拦截器实例已经处理了,将直接返回即可。
+     */
+    @Override
+    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception
+    {
+        Subject subject = getSubject(request, response);
+        if (subject != null)
+        {
+            subject.logout();
+        }
+        saveRequestAndRedirectToLogin(request, response);
+        return false;
+    }
+
+    // 跳转到登录页
+    @Override
+    protected void redirectToLogin(ServletRequest request, ServletResponse response) throws IOException
+    {
+        WebUtils.issueRedirect(request, response, loginUrl);
+    }
+
+    public void setOnlineSessionDAO(OnlineSessionDAO onlineSessionDAO)
+    {
+        this.onlineSessionDAO = onlineSessionDAO;
+    }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/web/filter/sync/SyncOnlineSessionFilter.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/web/filter/sync/SyncOnlineSessionFilter.java
new file mode 100644
index 0000000..db83cbc
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/web/filter/sync/SyncOnlineSessionFilter.java
@@ -0,0 +1,39 @@
+package com.ruoyi.framework.shiro.web.filter.sync;
+
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import org.apache.shiro.web.filter.PathMatchingFilter;
+import com.ruoyi.common.constant.ShiroConstants;
+import com.ruoyi.framework.shiro.session.OnlineSession;
+import com.ruoyi.framework.shiro.session.OnlineSessionDAO;
+
+/**
+ * 同步Session数据到Db
+ * 
+ * @author ruoyi
+ */
+public class SyncOnlineSessionFilter extends PathMatchingFilter
+{
+    private OnlineSessionDAO onlineSessionDAO;
+
+    /**
+     * 同步会话数据到DB 一次请求最多同步一次 防止过多处理 需要放到Shiro过滤器之前
+     */
+    @Override
+    protected boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception
+    {
+        OnlineSession session = (OnlineSession) request.getAttribute(ShiroConstants.ONLINE_SESSION);
+        // 如果session stop了 也不同步
+        // session停止时间,如果stopTimestamp不为null,则代表已停止
+        if (session != null && session.getUserId() != null && session.getStopTimestamp() == null)
+        {
+            onlineSessionDAO.syncToDb(session);
+        }
+        return true;
+    }
+
+    public void setOnlineSessionDAO(OnlineSessionDAO onlineSessionDAO)
+    {
+        this.onlineSessionDAO = onlineSessionDAO;
+    }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/web/session/OnlineWebSessionManager.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/web/session/OnlineWebSessionManager.java
new file mode 100644
index 0000000..7ceebad
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/web/session/OnlineWebSessionManager.java
@@ -0,0 +1,175 @@
+package com.ruoyi.framework.shiro.web.session;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import org.apache.commons.lang3.time.DateUtils;
+import org.apache.shiro.session.ExpiredSessionException;
+import org.apache.shiro.session.InvalidSessionException;
+import org.apache.shiro.session.Session;
+import org.apache.shiro.session.mgt.DefaultSessionKey;
+import org.apache.shiro.session.mgt.SessionKey;
+import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.ruoyi.common.constant.ShiroConstants;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.bean.BeanUtils;
+import com.ruoyi.common.utils.spring.SpringUtils;
+import com.ruoyi.framework.shiro.session.OnlineSession;
+import com.ruoyi.system.domain.SysUserOnline;
+import com.ruoyi.system.service.ISysUserOnlineService;
+
+/**
+ * 主要是在此如果会话的属性修改了 就标识下其修改了 然后方便 OnlineSessionDao同步
+ * 
+ * @author ruoyi
+ */
+public class OnlineWebSessionManager extends DefaultWebSessionManager
+{
+    private static final Logger log = LoggerFactory.getLogger(OnlineWebSessionManager.class);
+
+    @Override
+    public void setAttribute(SessionKey sessionKey, Object attributeKey, Object value) throws InvalidSessionException
+    {
+        super.setAttribute(sessionKey, attributeKey, value);
+        if (value != null && needMarkAttributeChanged(attributeKey))
+        {
+            OnlineSession session = getOnlineSession(sessionKey);
+            session.markAttributeChanged();
+        }
+    }
+
+    private boolean needMarkAttributeChanged(Object attributeKey)
+    {
+        if (attributeKey == null)
+        {
+            return false;
+        }
+        String attributeKeyStr = attributeKey.toString();
+        // 优化 flash属性没必要持久化
+        if (attributeKeyStr.startsWith("org.springframework"))
+        {
+            return false;
+        }
+        if (attributeKeyStr.startsWith("javax.servlet"))
+        {
+            return false;
+        }
+        if (attributeKeyStr.equals(ShiroConstants.CURRENT_USERNAME))
+        {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public Object removeAttribute(SessionKey sessionKey, Object attributeKey) throws InvalidSessionException
+    {
+        Object removed = super.removeAttribute(sessionKey, attributeKey);
+        if (removed != null)
+        {
+            OnlineSession s = getOnlineSession(sessionKey);
+            s.markAttributeChanged();
+        }
+
+        return removed;
+    }
+
+    public OnlineSession getOnlineSession(SessionKey sessionKey)
+    {
+        OnlineSession session = null;
+        Object obj = doGetSession(sessionKey);
+        if (StringUtils.isNotNull(obj))
+        {
+            session = new OnlineSession();
+            BeanUtils.copyBeanProp(session, obj);
+        }
+        return session;
+    }
+
+    /**
+     * 验证session是否有效 用于删除过期session
+     */
+    @Override
+    public void validateSessions()
+    {
+        if (log.isInfoEnabled())
+        {
+            log.info("invalidation sessions...");
+        }
+
+        int invalidCount = 0;
+
+        int timeout = (int) this.getGlobalSessionTimeout();
+        if (timeout < 0)
+        {
+            // 永不过期不进行处理
+            return;
+        }
+        Date expiredDate = DateUtils.addMilliseconds(new Date(), 0 - timeout);
+        ISysUserOnlineService userOnlineService = SpringUtils.getBean(ISysUserOnlineService.class);
+        List<SysUserOnline> userOnlineList = userOnlineService.selectOnlineByExpired(expiredDate);
+        // 批量过期删除
+        List<String> needOfflineIdList = new ArrayList<String>();
+        for (SysUserOnline userOnline : userOnlineList)
+        {
+            try
+            {
+                SessionKey key = new DefaultSessionKey(userOnline.getSessionId());
+                Session session = retrieveSession(key);
+                if (session != null)
+                {
+                    throw new InvalidSessionException();
+                }
+            }
+            catch (InvalidSessionException e)
+            {
+                if (log.isDebugEnabled())
+                {
+                    boolean expired = (e instanceof ExpiredSessionException);
+                    String msg = "Invalidated session with id [" + userOnline.getSessionId() + "]"
+                            + (expired ? " (expired)" : " (stopped)");
+                    log.debug(msg);
+                }
+                invalidCount++;
+                needOfflineIdList.add(userOnline.getSessionId());
+                userOnlineService.removeUserCache(userOnline.getLoginName(), userOnline.getSessionId());
+            }
+
+        }
+        if (needOfflineIdList.size() > 0)
+        {
+            try
+            {
+                userOnlineService.batchDeleteOnline(needOfflineIdList);
+            }
+            catch (Exception e)
+            {
+                log.error("batch delete db session error.", e);
+            }
+        }
+
+        if (log.isInfoEnabled())
+        {
+            String msg = "Finished invalidation session.";
+            if (invalidCount > 0)
+            {
+                msg += " [" + invalidCount + "] sessions were stopped.";
+            }
+            else
+            {
+                msg += " No sessions were stopped.";
+            }
+            log.info(msg);
+        }
+
+    }
+
+    @Override
+    protected Collection<Session> getActiveSessions()
+    {
+        throw new UnsupportedOperationException("getActiveSessions method not supported");
+    }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/web/session/SpringSessionValidationScheduler.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/web/session/SpringSessionValidationScheduler.java
new file mode 100644
index 0000000..60174c0
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/web/session/SpringSessionValidationScheduler.java
@@ -0,0 +1,131 @@
+package com.ruoyi.framework.shiro.web.session;
+
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import org.apache.shiro.session.mgt.DefaultSessionManager;
+import org.apache.shiro.session.mgt.SessionValidationScheduler;
+import org.apache.shiro.session.mgt.ValidatingSessionManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Component;
+import com.ruoyi.common.utils.Threads;
+
+/**
+ * 自定义任务调度器完成
+ * 
+ * @author ruoyi
+ */
+@Component
+public class SpringSessionValidationScheduler implements SessionValidationScheduler
+{
+    private static final Logger log = LoggerFactory.getLogger(SpringSessionValidationScheduler.class);
+
+    public static final long DEFAULT_SESSION_VALIDATION_INTERVAL = DefaultSessionManager.DEFAULT_SESSION_VALIDATION_INTERVAL;
+
+    /**
+     * 定时器,用于处理超时的挂起请求,也用于连接断开时的重连。
+     */
+    @Autowired
+    @Qualifier("scheduledExecutorService")
+    private ScheduledExecutorService executorService;
+
+    private volatile boolean enabled = false;
+
+    /**
+     * 会话验证管理器
+     */
+    @Autowired
+    @Qualifier("sessionManager")
+    @Lazy
+    private ValidatingSessionManager sessionManager;
+
+    // 相隔多久检查一次session的有效性,单位毫秒,默认就是10分钟
+    @Value("${shiro.session.validationInterval}")
+    private long sessionValidationInterval;
+
+    @Override
+    public boolean isEnabled()
+    {
+        return this.enabled;
+    }
+
+    /**
+     * Specifies how frequently (in milliseconds) this Scheduler will call the
+     * {@link org.apache.shiro.session.mgt.ValidatingSessionManager#validateSessions()
+     * ValidatingSessionManager#validateSessions()} method.
+     *
+     * <p>
+     * Unless this method is called, the default value is {@link #DEFAULT_SESSION_VALIDATION_INTERVAL}.
+     *
+     * @param sessionValidationInterval
+     */
+    public void setSessionValidationInterval(long sessionValidationInterval)
+    {
+        this.sessionValidationInterval = sessionValidationInterval;
+    }
+
+    /**
+     * Starts session validation by creating a spring PeriodicTrigger.
+     */
+    @Override
+    public void enableSessionValidation()
+    {
+
+        enabled = true;
+
+        if (log.isDebugEnabled())
+        {
+            log.debug("Scheduling session validation job using Spring Scheduler with "
+                    + "session validation interval of [" + sessionValidationInterval + "]ms...");
+        }
+
+        try
+        {
+            executorService.scheduleAtFixedRate(new Runnable()
+            {
+                @Override
+                public void run()
+                {
+                    if (enabled)
+                    {
+                        sessionManager.validateSessions();
+                    }
+                }
+            }, 1000, sessionValidationInterval * 60 * 1000, TimeUnit.MILLISECONDS);
+
+            this.enabled = true;
+
+            if (log.isDebugEnabled())
+            {
+                log.debug("Session validation job successfully scheduled with Spring Scheduler.");
+            }
+
+        }
+        catch (Exception e)
+        {
+            if (log.isErrorEnabled())
+            {
+                log.error("Error starting the Spring Scheduler session validation job.  Session validation may not occur.", e);
+            }
+        }
+    }
+
+    @Override
+    public void disableSessionValidation()
+    {
+        if (log.isDebugEnabled())
+        {
+            log.debug("Stopping Spring Scheduler session validation job...");
+        }
+
+        if (this.enabled)
+        {
+            Threads.shutdownAndAwaitTermination(executorService);
+        }
+        this.enabled = false;
+    }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/Server.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/Server.java
new file mode 100644
index 0000000..6a549f8
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/Server.java
@@ -0,0 +1,241 @@
+package com.ruoyi.framework.web.domain;
+
+import java.net.UnknownHostException;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Properties;
+import com.ruoyi.common.utils.Arith;
+import com.ruoyi.common.utils.IpUtils;
+import com.ruoyi.framework.web.domain.server.Cpu;
+import com.ruoyi.framework.web.domain.server.Jvm;
+import com.ruoyi.framework.web.domain.server.Mem;
+import com.ruoyi.framework.web.domain.server.Sys;
+import com.ruoyi.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 ruoyi
+ */
+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/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Cpu.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Cpu.java
new file mode 100644
index 0000000..a13a66c
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Cpu.java
@@ -0,0 +1,101 @@
+package com.ruoyi.framework.web.domain.server;
+
+import com.ruoyi.common.utils.Arith;
+
+/**
+ * CPU相关信息
+ * 
+ * @author ruoyi
+ */
+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/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Jvm.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Jvm.java
new file mode 100644
index 0000000..1fdc6ac
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Jvm.java
@@ -0,0 +1,130 @@
+package com.ruoyi.framework.web.domain.server;
+
+import java.lang.management.ManagementFactory;
+import com.ruoyi.common.utils.Arith;
+import com.ruoyi.common.utils.DateUtils;
+
+/**
+ * JVM相关信息
+ * 
+ * @author ruoyi
+ */
+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/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Mem.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Mem.java
new file mode 100644
index 0000000..13eec52
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Mem.java
@@ -0,0 +1,61 @@
+package com.ruoyi.framework.web.domain.server;
+
+import com.ruoyi.common.utils.Arith;
+
+/**
+ * 內存相关信息
+ * 
+ * @author ruoyi
+ */
+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/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Sys.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Sys.java
new file mode 100644
index 0000000..45d64d9
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Sys.java
@@ -0,0 +1,84 @@
+package com.ruoyi.framework.web.domain.server;
+
+/**
+ * 系统相关信息
+ * 
+ * @author ruoyi
+ */
+public class Sys
+{
+    /**
+     * 服务器名称
+     */
+    private String computerName;
+
+    /**
+     * 服务器Ip
+     */
+    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/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/SysFile.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/SysFile.java
new file mode 100644
index 0000000..1320cde
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/SysFile.java
@@ -0,0 +1,114 @@
+package com.ruoyi.framework.web.domain.server;
+
+/**
+ * 系统文件相关信息
+ * 
+ * @author ruoyi
+ */
+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/ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java
new file mode 100644
index 0000000..50aa339
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java
@@ -0,0 +1,149 @@
+package com.ruoyi.framework.web.exception;
+
+import javax.servlet.http.HttpServletRequest;
+import org.apache.shiro.authz.AuthorizationException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.validation.BindException;
+import org.springframework.web.HttpRequestMethodNotSupportedException;
+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 org.springframework.web.servlet.ModelAndView;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.text.Convert;
+import com.ruoyi.common.exception.DemoModeException;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.ServletUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.html.EscapeUtil;
+import com.ruoyi.common.utils.security.PermissionUtils;
+
+/**
+ * 全局异常处理器
+ * 
+ * @author ruoyi
+ */
+@RestControllerAdvice
+public class GlobalExceptionHandler
+{
+    private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
+
+    /**
+     * 权限校验异常(ajax请求返回json,redirect请求跳转页面)
+     */
+    @ExceptionHandler(AuthorizationException.class)
+    public Object handleAuthorizationException(AuthorizationException e, HttpServletRequest request)
+    {
+        String requestURI = request.getRequestURI();
+        log.error("请求地址'{}',权限校验失败'{}'", requestURI, e.getMessage());
+        if (ServletUtils.isAjaxRequest(request))
+        {
+            return AjaxResult.error(PermissionUtils.getMsg(e.getMessage()));
+        }
+        else
+        {
+            return new ModelAndView("error/unauth");
+        }
+    }
+
+    /**
+     * 请求方式不支持
+     */
+    @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(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(ServiceException.class)
+    public Object handleServiceException(ServiceException e, HttpServletRequest request)
+    {
+        log.error(e.getMessage(), e);
+        if (ServletUtils.isAjaxRequest(request))
+        {
+            return AjaxResult.error(e.getMessage());
+        }
+        else
+        {
+            return new ModelAndView("error/service", "errorMessage", 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();
+        String value = Convert.toStr(e.getValue());
+        if (StringUtils.isNotEmpty(value))
+        {
+            value = EscapeUtil.clean(value);
+        }
+        log.error("请求参数类型不匹配'{}',发生系统异常.", requestURI, e);
+        return AjaxResult.error(String.format("请求参数类型不匹配,参数[%s]要求类型为:'%s',但输入值为:'%s'", e.getName(), e.getRequiredType().getName(), value));
+    }
+
+    /**
+     * 自定义验证异常
+     */
+    @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(DemoModeException.class)
+    public AjaxResult handleDemoModeException(DemoModeException e)
+    {
+        return AjaxResult.error("演示模式,不允许操作");
+    }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/CacheService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/CacheService.java
new file mode 100644
index 0000000..a33b3e6
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/CacheService.java
@@ -0,0 +1,84 @@
+package com.ruoyi.framework.web.service;
+
+import java.util.Set;
+import java.util.TreeSet;
+import org.apache.commons.lang3.ArrayUtils;
+import org.springframework.stereotype.Service;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.utils.CacheUtils;
+
+/**
+ * 缓存操作处理
+ * 
+ * @author ruoyi
+ */
+@Service
+public class CacheService
+{
+    /**
+     * 获取所有缓存名称
+     * 
+     * @return 缓存列表
+     */
+    public String[] getCacheNames()
+    {
+        String[] cacheNames = CacheUtils.getCacheNames();
+        return ArrayUtils.removeElement(cacheNames, Constants.SYS_AUTH_CACHE);
+    }
+
+    /**
+     * 根据缓存名称获取所有键名
+     * 
+     * @param cacheName 缓存名称
+     * @return 键名列表
+     */
+    public Set<String> getCacheKeys(String cacheName)
+    {
+        return new TreeSet<>(CacheUtils.getCache(cacheName).keys());
+    }
+
+    /**
+     * 根据缓存名称和键名获取内容值
+     * 
+     * @param cacheName 缓存名称
+     * @param cacheKey 键名
+     * @return 键值
+     */
+    public Object getCacheValue(String cacheName, String cacheKey)
+    {
+        return CacheUtils.get(cacheName, cacheKey);
+    }
+
+    /**
+     * 根据名称删除缓存信息
+     * 
+     * @param cacheName 缓存名称
+     */
+    public void clearCacheName(String cacheName)
+    {
+        CacheUtils.removeAll(cacheName);
+    }
+
+    /**
+     * 根据名称和键名删除缓存信息
+     * 
+     * @param cacheName 缓存名称
+     * @param cacheKey 键名
+     */
+    public void clearCacheKey(String cacheName, String cacheKey)
+    {
+        CacheUtils.remove(cacheName, cacheKey);
+    }
+
+    /**
+     * 清理所有缓存
+     */
+    public void clearAll()
+    {
+        String[] cacheNames = getCacheNames();
+        for (String cacheName : cacheNames)
+        {
+            CacheUtils.removeAll(cacheName);
+        }
+    }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/ConfigService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/ConfigService.java
new file mode 100644
index 0000000..2859588
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/ConfigService.java
@@ -0,0 +1,28 @@
+package com.ruoyi.framework.web.service;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.system.service.ISysConfigService;
+
+/**
+ * RuoYi首创 html调用 thymeleaf 实现参数管理
+ * 
+ * @author ruoyi
+ */
+@Service("config")
+public class ConfigService
+{
+    @Autowired
+    private ISysConfigService configService;
+
+    /**
+     * 根据键名查询参数配置信息
+     * 
+     * @param configKey 参数键名
+     * @return 参数键值
+     */
+    public String getKey(String configKey)
+    {
+        return configService.selectConfigByKey(configKey);
+    }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/DictService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/DictService.java
new file mode 100644
index 0000000..f485811
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/DictService.java
@@ -0,0 +1,46 @@
+package com.ruoyi.framework.web.service;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.common.core.domain.entity.SysDictData;
+import com.ruoyi.system.service.ISysDictDataService;
+import com.ruoyi.system.service.ISysDictTypeService;
+
+/**
+ * RuoYi首创 html调用 thymeleaf 实现字典读取
+ * 
+ * @author ruoyi
+ */
+@Service("dict")
+public class DictService
+{
+    @Autowired
+    private ISysDictTypeService dictTypeService;
+
+    @Autowired
+    private ISysDictDataService dictDataService;
+
+    /**
+     * 根据字典类型查询字典数据信息
+     * 
+     * @param dictType 字典类型
+     * @return 参数键值
+     */
+    public List<SysDictData> getType(String dictType)
+    {
+        return dictTypeService.selectDictDataByType(dictType);
+    }
+
+    /**
+     * 根据字典类型和字典键值查询字典数据信息
+     * 
+     * @param dictType 字典类型
+     * @param dictValue 字典键值
+     * @return 字典标签
+     */
+    public String getLabel(String dictType, String dictValue)
+    {
+        return dictDataService.selectDictLabel(dictType, dictValue);
+    }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/PermissionService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/PermissionService.java
new file mode 100644
index 0000000..0443591
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/PermissionService.java
@@ -0,0 +1,262 @@
+package com.ruoyi.framework.web.service;
+
+import java.beans.BeanInfo;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.subject.Subject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * RuoYi首创 js调用 thymeleaf 实现按钮权限可见性
+ * 
+ * @author ruoyi
+ */
+@Service("permission")
+public class PermissionService
+{
+    private static final Logger log = LoggerFactory.getLogger(PermissionService.class);
+
+    /** 没有权限,hidden用于前端隐藏按钮 */
+    public static final String NOACCESS = "hidden";
+
+    private static final String ROLE_DELIMETER = ",";
+
+    private static final String PERMISSION_DELIMETER = ",";
+
+    /**
+     * 验证用户是否具备某权限,无权限返回hidden用于前端隐藏(如需返回Boolean使用isPermitted)
+     * 
+     * @param permission 权限字符串
+     * @return 用户是否具备某权限
+     */
+    public String hasPermi(String permission)
+    {
+        return isPermitted(permission) ? StringUtils.EMPTY : NOACCESS;
+    }
+
+    /**
+     * 验证用户是否不具备某权限,与 hasPermi逻辑相反。无权限返回hidden用于前端隐藏(如需返回Boolean使用isLacksPermitted)
+     *
+     * @param permission 权限字符串
+     * @return 用户是否不具备某权限
+     */
+    public String lacksPermi(String permission)
+    {
+        return isLacksPermitted(permission) ? StringUtils.EMPTY : NOACCESS;
+    }
+
+    /**
+     * 验证用户是否具有以下任意一个权限,无权限返回hidden用于隐藏(如需返回Boolean使用hasAnyPermissions)
+     *
+     * @param permissions 以 PERMISSION_DELIMETER 为分隔符的权限列表
+     * @return 用户是否具有以下任意一个权限
+     */
+    public String hasAnyPermi(String permissions)
+    {
+        return hasAnyPermissions(permissions, PERMISSION_DELIMETER) ? StringUtils.EMPTY : NOACCESS;
+    }
+
+    /**
+     * 验证用户是否具备某角色,无权限返回hidden用于隐藏(如需返回Boolean使用isRole)
+     * 
+     * @param role 角色字符串
+     * @return 用户是否具备某角色
+     */
+    public String hasRole(String role)
+    {
+        return isRole(role) ? StringUtils.EMPTY : NOACCESS;
+    }
+
+    /**
+     * 验证用户是否不具备某角色,与hasRole逻辑相反。无权限返回hidden用于隐藏(如需返回Boolean使用isLacksRole)
+     * 
+     * @param role 角色字符串
+     * @return 用户是否不具备某角色
+     */
+    public String lacksRole(String role)
+    {
+        return isLacksRole(role) ? StringUtils.EMPTY : NOACCESS;
+    }
+
+    /**
+     * 验证用户是否具有以下任意一个角色,无权限返回hidden用于隐藏(如需返回Boolean使用isAnyRoles)
+     *
+     * @param roles 以 ROLE_NAMES_DELIMETER 为分隔符的角色列表
+     * @return 用户是否具有以下任意一个角色
+     */
+    public String hasAnyRoles(String roles)
+    {
+        return isAnyRoles(roles, ROLE_DELIMETER) ? StringUtils.EMPTY : NOACCESS;
+    }
+
+    /**
+     * 验证用户是否认证通过或已记住的用户。
+     *
+     * @return 用户是否认证通过或已记住的用户
+     */
+    public boolean isUser()
+    {
+        Subject subject = SecurityUtils.getSubject();
+        return subject != null && subject.getPrincipal() != null;
+    }
+
+    /**
+     * 判断用户是否拥有某个权限
+     * 
+     * @param permission 权限字符串
+     * @return 用户是否具备某权限
+     */
+    public boolean isPermitted(String permission)
+    {
+        return SecurityUtils.getSubject().isPermitted(permission);
+    }
+
+    /**
+     * 判断用户是否不具备某权限,与 isPermitted逻辑相反。
+     *
+     * @param permission 权限名称
+     * @return 用户是否不具备某权限
+     */
+    public boolean isLacksPermitted(String permission)
+    {
+        return isPermitted(permission) != true;
+    }
+
+    /**
+     * 验证用户是否具有以下任意一个权限。
+     *
+     * @param permissions 以 PERMISSION_DELIMETER 为分隔符的权限列表
+     * @return 用户是否具有以下任意一个权限
+     */
+    public boolean hasAnyPermissions(String permissions)
+    {
+        return hasAnyPermissions(permissions, PERMISSION_DELIMETER);
+    }
+
+    /**
+     * 验证用户是否具有以下任意一个权限。
+     *
+     * @param permissions 以 delimeter 为分隔符的权限列表
+     * @param delimeter 权限列表分隔符
+     * @return 用户是否具有以下任意一个权限
+     */
+    public boolean hasAnyPermissions(String permissions, String delimeter)
+    {
+        Subject subject = SecurityUtils.getSubject();
+
+        if (subject != null)
+        {
+            if (delimeter == null || delimeter.length() == 0)
+            {
+                delimeter = PERMISSION_DELIMETER;
+            }
+
+            for (String permission : permissions.split(delimeter))
+            {
+                if (permission != null && subject.isPermitted(permission.trim()) == true)
+                {
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * 判断用户是否拥有某个角色
+     * 
+     * @param role 角色字符串
+     * @return 用户是否具备某角色
+     */
+    public boolean isRole(String role)
+    {
+        return SecurityUtils.getSubject().hasRole(role);
+    }
+
+    /**
+     * 验证用户是否不具备某角色,与 isRole逻辑相反。
+     *
+     * @param role 角色名称
+     * @return 用户是否不具备某角色
+     */
+    public boolean isLacksRole(String role)
+    {
+        return isRole(role) != true;
+    }
+
+    /**
+     * 验证用户是否具有以下任意一个角色。
+     *
+     * @param roles 以 ROLE_NAMES_DELIMETER 为分隔符的角色列表
+     * @return 用户是否具有以下任意一个角色
+     */
+    public boolean isAnyRoles(String roles)
+    {
+        return isAnyRoles(roles, ROLE_DELIMETER);
+    }
+
+    /**
+     * 验证用户是否具有以下任意一个角色。
+     *
+     * @param roles 以 delimeter 为分隔符的角色列表
+     * @param delimeter 角色列表分隔符
+     * @return 用户是否具有以下任意一个角色
+     */
+    public boolean isAnyRoles(String roles, String delimeter)
+    {
+        Subject subject = SecurityUtils.getSubject();
+        if (subject != null)
+        {
+            if (delimeter == null || delimeter.length() == 0)
+            {
+                delimeter = ROLE_DELIMETER;
+            }
+
+            for (String role : roles.split(delimeter))
+            {
+                if (subject.hasRole(role.trim()) == true)
+                {
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * 返回用户属性值
+     *
+     * @param property 属性名称
+     * @return 用户属性值
+     */
+    public Object getPrincipalProperty(String property)
+    {
+        Subject subject = SecurityUtils.getSubject();
+        if (subject != null)
+        {
+            Object principal = subject.getPrincipal();
+            try
+            {
+                BeanInfo bi = Introspector.getBeanInfo(principal.getClass());
+                for (PropertyDescriptor pd : bi.getPropertyDescriptors())
+                {
+                    if (pd.getName().equals(property) == true)
+                    {
+                        return pd.getReadMethod().invoke(principal, (Object[]) null);
+                    }
+                }
+            }
+            catch (Exception e)
+            {
+                log.error("Error reading property [{}] from principal of type [{}]", property, principal.getClass().getName());
+            }
+        }
+        return null;
+    }
+}
diff --git a/ruoyi-generator/pom.xml b/ruoyi-generator/pom.xml
new file mode 100644
index 0000000..7b4ddf6
--- /dev/null
+++ b/ruoyi-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>ruoyi</artifactId>
+        <groupId>com.ruoyi</groupId>
+        <version>4.8.0</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>ruoyi-generator</artifactId>
+
+    <description>
+        generator代码生成
+    </description>
+
+    <dependencies>
+
+        <!-- velocity代码生成使用模板 -->
+        <dependency>
+            <groupId>org.apache.velocity</groupId>
+            <artifactId>velocity-engine-core</artifactId>
+        </dependency>
+
+        <!-- 通用工具-->
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common</artifactId>
+        </dependency>
+
+        <!-- 阿里数据库连接池 -->
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>druid-spring-boot-starter</artifactId>
+        </dependency>
+
+    </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/config/GenConfig.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/config/GenConfig.java
new file mode 100644
index 0000000..c01857c
--- /dev/null
+++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/config/GenConfig.java
@@ -0,0 +1,87 @@
+package com.ruoyi.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;
+
+/**
+ * 读取代码生成相关配置
+ * 
+ * @author ruoyi
+ */
+@Component
+@ConfigurationProperties(prefix = "gen")
+@PropertySource(value = { "classpath:generator.yml" })
+public class GenConfig
+{
+    /** 作者 */
+    public static String author;
+
+    /** 生成包路径 */
+    public static String packageName;
+
+    /** 自动去除表前缀 */
+    public static boolean autoRemovePre;
+
+    /** 表前缀 */
+    public static String tablePrefix;
+
+    /** 是否允许生成文件覆盖到本地(自定义路径) */
+    public static boolean allowOverwrite;
+
+    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;
+    }
+
+    public static boolean isAllowOverwrite()
+    {
+        return allowOverwrite;
+    }
+
+    @Value("${allowOverwrite}")
+    public void setAllowOverwrite(boolean allowOverwrite)
+    {
+        GenConfig.allowOverwrite = allowOverwrite;
+    }
+}
diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java
new file mode 100644
index 0000000..02fa6d9
--- /dev/null
+++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java
@@ -0,0 +1,309 @@
+package com.ruoyi.generator.controller;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.io.IOUtils;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.apache.shiro.authz.annotation.RequiresRoles;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+import org.springframework.validation.annotation.Validated;
+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.ResponseBody;
+import com.alibaba.druid.DbType;
+import com.alibaba.druid.sql.SQLUtils;
+import com.alibaba.druid.sql.ast.SQLStatement;
+import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;
+import com.alibaba.fastjson.JSON;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.CxSelect;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.core.text.Convert;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.security.PermissionUtils;
+import com.ruoyi.common.utils.sql.SqlUtil;
+import com.ruoyi.generator.config.GenConfig;
+import com.ruoyi.generator.domain.GenTable;
+import com.ruoyi.generator.domain.GenTableColumn;
+import com.ruoyi.generator.service.IGenTableColumnService;
+import com.ruoyi.generator.service.IGenTableService;
+
+/**
+ * 代码生成 操作处理
+ * 
+ * @author ruoyi
+ */
+@Controller
+@RequestMapping("/tool/gen")
+public class GenController extends BaseController
+{
+    private String prefix = "tool/gen";
+
+    @Autowired
+    private IGenTableService genTableService;
+
+    @Autowired
+    private IGenTableColumnService genTableColumnService;
+
+    @RequiresPermissions("tool:gen:view")
+    @GetMapping()
+    public String gen()
+    {
+        return prefix + "/gen";
+    }
+
+    /**
+     * 查询代码生成列表
+     */
+    @RequiresPermissions("tool:gen:list")
+    @PostMapping("/list")
+    @ResponseBody
+    public TableDataInfo genList(GenTable genTable)
+    {
+        startPage();
+        List<GenTable> list = genTableService.selectGenTableList(genTable);
+        return getDataTable(list);
+    }
+
+    /**
+     * 查询数据库列表
+     */
+    @RequiresPermissions("tool:gen:list")
+    @PostMapping("/db/list")
+    @ResponseBody
+    public TableDataInfo dataList(GenTable genTable)
+    {
+        startPage();
+        List<GenTable> list = genTableService.selectDbTableList(genTable);
+        return getDataTable(list);
+    }
+
+    /**
+     * 查询数据表字段列表
+     */
+    @RequiresPermissions("tool:gen:list")
+    @PostMapping("/column/list")
+    @ResponseBody
+    public TableDataInfo columnList(GenTableColumn genTableColumn)
+    {
+        TableDataInfo dataInfo = new TableDataInfo();
+        List<GenTableColumn> list = genTableColumnService.selectGenTableColumnListByTableId(genTableColumn);
+        dataInfo.setRows(list);
+        dataInfo.setTotal(list.size());
+        return dataInfo;
+    }
+
+    /**
+     * 导入表结构
+     */
+    @RequiresPermissions("tool:gen:list")
+    @GetMapping("/importTable")
+    public String importTable()
+    {
+        return prefix + "/importTable";
+    }
+
+    /**
+     * 创建表结构
+     */
+    @GetMapping("/createTable")
+    public String createTable()
+    {
+        return prefix + "/createTable";
+    }
+
+    /**
+     * 导入表结构(保存)
+     */
+    @RequiresPermissions("tool:gen:list")
+    @Log(title = "代码生成", businessType = BusinessType.IMPORT)
+    @PostMapping("/importTable")
+    @ResponseBody
+    public AjaxResult importTableSave(String tables)
+    {
+        String[] tableNames = Convert.toStrArray(tables);
+        // 查询表信息
+        List<GenTable> tableList = genTableService.selectDbTableListByNames(tableNames);
+        String operName = Convert.toStr(PermissionUtils.getPrincipalProperty("loginName"));
+        genTableService.importGenTable(tableList, operName);
+        return AjaxResult.success();
+    }
+
+    /**
+     * 修改代码生成业务
+     */
+    @RequiresPermissions("tool:gen:edit")
+    @GetMapping("/edit/{tableId}")
+    public String edit(@PathVariable("tableId") Long tableId, ModelMap mmap)
+    {
+        GenTable table = genTableService.selectGenTableById(tableId);
+        List<GenTable> genTables = genTableService.selectGenTableAll();
+        List<CxSelect> cxSelect = new ArrayList<CxSelect>();
+        for (GenTable genTable : genTables)
+        {
+            if (!StringUtils.equals(table.getTableName(), genTable.getTableName()))
+            {
+                CxSelect cxTable = new CxSelect(genTable.getTableName(), genTable.getTableName() + ':' + genTable.getTableComment());
+                List<CxSelect> cxColumns = new ArrayList<CxSelect>();
+                for (GenTableColumn tableColumn : genTable.getColumns())
+                {
+                    cxColumns.add(new CxSelect(tableColumn.getColumnName(), tableColumn.getColumnName() + ':' + tableColumn.getColumnComment()));
+                }
+                cxTable.setS(cxColumns);
+                cxSelect.add(cxTable);
+            }
+        }
+        mmap.put("table", table);
+        mmap.put("data", JSON.toJSON(cxSelect));
+        return prefix + "/edit";
+    }
+
+    /**
+     * 修改保存代码生成业务
+     */
+    @RequiresPermissions("tool:gen:edit")
+    @Log(title = "代码生成", businessType = BusinessType.UPDATE)
+    @PostMapping("/edit")
+    @ResponseBody
+    public AjaxResult editSave(@Validated GenTable genTable)
+    {
+        genTableService.validateEdit(genTable);
+        genTableService.updateGenTable(genTable);
+        return AjaxResult.success();
+    }
+
+    @RequiresPermissions("tool:gen:remove")
+    @Log(title = "代码生成", businessType = BusinessType.DELETE)
+    @PostMapping("/remove")
+    @ResponseBody
+    public AjaxResult remove(String ids)
+    {
+        genTableService.deleteGenTableByIds(ids);
+        return AjaxResult.success();
+    }
+
+    @RequiresRoles("admin")
+    @Log(title = "创建表", businessType = BusinessType.OTHER)
+    @PostMapping("/createTable")
+    @ResponseBody
+    public AjaxResult create(String sql)
+    {
+        try
+        {
+            SqlUtil.filterKeyword(sql);
+            List<SQLStatement> sqlStatements = SQLUtils.parseStatements(sql, DbType.mysql);
+            List<String> tableNames = new ArrayList<>();
+            for (SQLStatement sqlStatement : sqlStatements)
+            {
+                if (sqlStatement instanceof MySqlCreateTableStatement)
+                {
+                    MySqlCreateTableStatement createTableStatement = (MySqlCreateTableStatement) sqlStatement;
+                    if (genTableService.createTable(createTableStatement.toString()))
+                    {
+                        String tableName = createTableStatement.getTableName().replaceAll("`", "");
+                        tableNames.add(tableName);
+                    }
+                }
+            }
+            List<GenTable> tableList = genTableService.selectDbTableListByNames(tableNames.toArray(new String[tableNames.size()]));
+            String operName = Convert.toStr(PermissionUtils.getPrincipalProperty("loginName"));
+            genTableService.importGenTable(tableList, operName);
+            return AjaxResult.success();
+        }
+        catch (Exception e)
+        {
+            logger.error(e.getMessage(), e);
+            return AjaxResult.error("创建表结构异常");
+        }
+    }
+
+    /**
+     * 预览代码
+     */
+    @RequiresPermissions("tool:gen:preview")
+    @GetMapping("/preview/{tableId}")
+    @ResponseBody
+    public AjaxResult preview(@PathVariable("tableId") Long tableId) throws IOException
+    {
+        Map<String, String> dataMap = genTableService.previewCode(tableId);
+        return AjaxResult.success(dataMap);
+    }
+
+    /**
+     * 生成代码(下载方式)
+     */
+    @RequiresPermissions("tool:gen:code")
+    @Log(title = "代码生成", 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);
+    }
+
+    /**
+     * 生成代码(自定义路径)
+     */
+    @RequiresPermissions("tool:gen:code")
+    @Log(title = "代码生成", businessType = BusinessType.GENCODE)
+    @GetMapping("/genCode/{tableName}")
+    @ResponseBody
+    public AjaxResult genCode(@PathVariable("tableName") String tableName)
+    {
+        if (!GenConfig.isAllowOverwrite())
+        {
+            return AjaxResult.error("【系统预设】不允许生成文件覆盖到本地");
+        }
+        genTableService.generatorCode(tableName);
+        return AjaxResult.success();
+    }
+
+    /**
+     * 同步数据库
+     */
+    @RequiresPermissions("tool:gen:edit")
+    @Log(title = "代码生成", businessType = BusinessType.UPDATE)
+    @GetMapping("/synchDb/{tableName}")
+    @ResponseBody
+    public AjaxResult synchDb(@PathVariable("tableName") String tableName)
+    {
+        genTableService.synchDb(tableName);
+        return AjaxResult.success();
+    }
+
+    /**
+     * 批量生成代码
+     */
+    @RequiresPermissions("tool:gen:code")
+    @Log(title = "代码生成", businessType = BusinessType.GENCODE)
+    @GetMapping("/batchGenCode")
+    @ResponseBody
+    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.setHeader("Content-Disposition", "attachment; filename=\"ruoyi.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/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java
new file mode 100644
index 0000000..b6ee19d
--- /dev/null
+++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java
@@ -0,0 +1,385 @@
+package com.ruoyi.generator.domain;
+
+import java.util.List;
+import javax.validation.Valid;
+import javax.validation.constraints.NotBlank;
+import org.apache.commons.lang3.ArrayUtils;
+import com.ruoyi.common.constant.GenConstants;
+import com.ruoyi.common.core.domain.BaseEntity;
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * 业务表 gen_table
+ * 
+ * @author ruoyi
+ */
+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;
+
+    /** 生成包路径 */
+    @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;
+
+    /** 表单布局(单列 双列 三列) */
+    private int formColNum;
+
+    /** 生成代码方式(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 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 int getFormColNum()
+    {
+        return formColNum;
+    }
+
+    public void setFormColNum(int formColNum)
+    {
+        this.formColNum = formColNum;
+    }
+
+    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/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java
new file mode 100644
index 0000000..dbf1837
--- /dev/null
+++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java
@@ -0,0 +1,373 @@
+package com.ruoyi.generator.domain;
+
+import javax.validation.constraints.NotBlank;
+import com.ruoyi.common.core.domain.BaseEntity;
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * 代码生成业务字段表 gen_table_column
+ * 
+ * @author ruoyi
+ */
+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;
+
+    /** 查询方式(EQ等于、NE不等于、GT大于、LT小于、LIKE模糊、BETWEEN范围) */
+    private String queryType;
+
+    /** 显示类型(input文本框、textarea文本域、select下拉框、checkbox复选框、radio单选框、datetime日期控件、upload上传控件、summernote富文本控件) */
+    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;
+        }
+    }
+}
\ No newline at end of file
diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableColumnMapper.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableColumnMapper.java
new file mode 100644
index 0000000..0b7bdb5
--- /dev/null
+++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableColumnMapper.java
@@ -0,0 +1,60 @@
+package com.ruoyi.generator.mapper;
+
+import java.util.List;
+import com.ruoyi.generator.domain.GenTableColumn;
+
+/**
+ * 业务字段 数据层
+ * 
+ * @author ruoyi
+ */
+public interface GenTableColumnMapper
+{
+    /**
+     * 根据表名称查询列信息
+     * 
+     * @param tableName 表名称
+     * @return 列信息
+     */
+    public List<GenTableColumn> selectDbTableColumnsByName(String tableName);
+
+    /**
+     * 查询业务字段列表
+     * 
+     * @param genTableColumn 业务字段信息
+     * @return 业务字段集合
+     */
+    public List<GenTableColumn> selectGenTableColumnListByTableId(GenTableColumn genTableColumn);
+
+    /**
+     * 新增业务字段
+     * 
+     * @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/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java
new file mode 100644
index 0000000..7265d42
--- /dev/null
+++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java
@@ -0,0 +1,91 @@
+package com.ruoyi.generator.mapper;
+
+import java.util.List;
+import com.ruoyi.generator.domain.GenTable;
+
+/**
+ * 业务 数据层
+ * 
+ * @author ruoyi
+ */
+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();
+
+    /**
+     * 查询表ID业务信息
+     * 
+     * @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);
+
+    /**
+     * 创建表
+     *
+     * @param sql
+     * @return 结果
+     */
+    public int createTable(String sql);
+}
\ No newline at end of file
diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableColumnService.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableColumnService.java
new file mode 100644
index 0000000..69a1e21
--- /dev/null
+++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableColumnService.java
@@ -0,0 +1,44 @@
+package com.ruoyi.generator.service;
+
+import java.util.List;
+import com.ruoyi.generator.domain.GenTableColumn;
+
+/**
+ * 业务字段 服务层
+ * 
+ * @author ruoyi
+ */
+public interface IGenTableColumnService
+{
+    /**
+     * 查询业务字段列表
+     * 
+     * @param genTableColumn 业务字段信息
+     * @return 业务字段集合
+     */
+    public List<GenTableColumn> selectGenTableColumnListByTableId(GenTableColumn genTableColumn);
+
+    /**
+     * 新增业务字段
+     * 
+     * @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/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java
new file mode 100644
index 0000000..4af8fea
--- /dev/null
+++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java
@@ -0,0 +1,129 @@
+package com.ruoyi.generator.service;
+
+import java.util.List;
+import java.util.Map;
+import com.ruoyi.generator.domain.GenTable;
+
+/**
+ * 业务 服务层
+ * 
+ * @author ruoyi
+ */
+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 ids 需要删除的数据ID
+     * @return 结果
+     */
+    public void deleteGenTableByIds(String ids);
+
+    /**
+     * 创建表
+     *
+     * @param sql 创建表语句
+     * @return 结果
+     */
+    public boolean createTable(String sql);
+
+    /**
+     * 导入表结构
+     *
+     * @param tableList 导入表列表
+     * @param operName 操作人员
+     */
+    public void importGenTable(List<GenTable> tableList, String operName);
+
+    /**
+     * 预览代码
+     * 
+     * @param tableId 表编号
+     * @return 预览数据列表
+     */
+    public Map<String, String> previewCode(Long tableId);
+
+    /**
+     * 生成代码(下载方式)
+     * 
+     * @param tableName 表名称
+     * @return 数据
+     */
+    public byte[] downloadCode(String tableName);
+
+    /**
+     * 生成代码(自定义路径)
+     * 
+     * @param tableName 表名称
+     */
+    public void generatorCode(String tableName);
+    
+    /**
+     * 同步数据库
+     * 
+     * @param tableName 表名称
+     */
+    public void synchDb(String tableName);
+
+    /**
+     * 批量生成代码(下载方式)
+     * 
+     * @param tableNames 表数组
+     * @return 数据
+     */
+    public byte[] downloadCode(String[] tableNames);
+
+    /**
+     * 修改保存参数校验
+     * 
+     * @param genTable 业务信息
+     */
+    public void validateEdit(GenTable genTable);
+}
diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/service/impl/GenTableColumnServiceImpl.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/impl/GenTableColumnServiceImpl.java
new file mode 100644
index 0000000..bd65ec2
--- /dev/null
+++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/impl/GenTableColumnServiceImpl.java
@@ -0,0 +1,69 @@
+package com.ruoyi.generator.service.impl;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.common.core.text.Convert;
+import com.ruoyi.generator.domain.GenTableColumn;
+import com.ruoyi.generator.mapper.GenTableColumnMapper;
+import com.ruoyi.generator.service.IGenTableColumnService;
+
+/**
+ * 业务字段 服务层实现
+ * 
+ * @author ruoyi
+ */
+@Service
+public class GenTableColumnServiceImpl implements IGenTableColumnService
+{
+    @Autowired
+    private GenTableColumnMapper genTableColumnMapper;
+
+    /**
+     * 查询业务字段列表
+     * 
+     * @param genTableColumn 业务字段信息
+     * @return 业务字段集合
+     */
+    @Override
+    public List<GenTableColumn> selectGenTableColumnListByTableId(GenTableColumn genTableColumn)
+    {
+        return genTableColumnMapper.selectGenTableColumnListByTableId(genTableColumn);
+    }
+
+    /**
+     * 新增业务字段
+     * 
+     * @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));
+    }
+}
\ No newline at end of file
diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/service/impl/GenTableServiceImpl.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/impl/GenTableServiceImpl.java
new file mode 100644
index 0000000..1f25c53
--- /dev/null
+++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/impl/GenTableServiceImpl.java
@@ -0,0 +1,534 @@
+package com.ruoyi.generator.service.impl;
+
+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.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.constant.GenConstants;
+import com.ruoyi.common.core.text.CharsetKit;
+import com.ruoyi.common.core.text.Convert;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.generator.domain.GenTable;
+import com.ruoyi.generator.domain.GenTableColumn;
+import com.ruoyi.generator.mapper.GenTableColumnMapper;
+import com.ruoyi.generator.mapper.GenTableMapper;
+import com.ruoyi.generator.service.IGenTableService;
+import com.ruoyi.generator.util.GenUtils;
+import com.ruoyi.generator.util.VelocityInitializer;
+import com.ruoyi.generator.util.VelocityUtils;
+
+/**
+ * 业务 服务层实现
+ * 
+ * @author ruoyi
+ */
+@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 genTableColumn : genTable.getColumns())
+            {
+                genTableColumnMapper.updateGenTableColumn(genTableColumn);
+            }
+        }
+    }
+
+    /**
+     * 删除业务对象
+     * 
+     * @param ids 需要删除的数据ID
+     * @return 结果
+     */
+    @Override
+    @Transactional
+    public void deleteGenTableByIds(String ids)
+    {
+        genTableMapper.deleteGenTableByIds(Convert.toLongArray(ids));
+        genTableColumnMapper.deleteGenTableColumnByIds(Convert.toLongArray(ids));
+    }
+
+    /**
+     * 创建表
+     *
+     * @param sql 创建表语句
+     * @return 结果
+     */
+    @Override
+    public boolean createTable(String sql)
+    {
+        return genTableMapper.createTable(sql) == 0;
+    }
+
+    /**
+     * 导入表结构
+     *
+     * @param tableList 导入表列表
+     * @param operName 操作人员
+     */
+    @Override
+    @Transactional
+    public void importGenTable(List<GenTable> tableList, String operName)
+    {
+        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());
+        }
+    }
+
+    /**
+     * 预览代码
+     * 
+     * @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());
+        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;
+    }
+
+    /**
+     * 生成代码(下载方式)
+     * 
+     * @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();
+    }
+
+    /**
+     * 生成代码(自定义路径)
+     * 
+     * @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());
+        for (String template : templates)
+        {
+            if (!StringUtils.contains(template, "sql.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);
+        }
+    }
+
+    /**
+     * 批量生成代码(下载方式)
+     * 
+     * @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();
+    }
+
+    /**
+     * 查询表信息并生成代码
+     */
+    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());
+        for (String template : templates)
+        {
+            // 渲染模板
+            StringWriter sw = new StringWriter();
+            Template tpl = Velocity.getTemplate(template, Constants.UTF8);
+            tpl.merge(context, sw);
+            try
+            {
+                // 添加到zip
+                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 = JSONObject.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));
+        }
+    }
+
+    /**
+     * 设置代码生成其他选项值
+     * 
+     * @param genTable 设置后的生成对象
+     */
+    public void setTableFromOptions(GenTable genTable)
+    {
+        JSONObject paramsObj = JSONObject.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);
+        }
+    }
+
+    /**
+     * 获取代码生成地址
+     * 
+     * @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/ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java
new file mode 100644
index 0000000..ece4cd6
--- /dev/null
+++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java
@@ -0,0 +1,252 @@
+package com.ruoyi.generator.util;
+
+import java.util.Arrays;
+import org.apache.commons.lang3.RegExUtils;
+import com.ruoyi.common.constant.GenConstants;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.generator.config.GenConfig;
+import com.ruoyi.generator.domain.GenTable;
+import com.ruoyi.generator.domain.GenTableColumn;
+
+/**
+ * 代码生成器 工具类
+ * 
+ * @author ruoyi
+ */
+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);
+
+            // 如果是浮点型 统一用BigDecimal
+            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, "file"))
+        {
+            column.setHtmlType(GenConstants.HTML_UPLOAD);
+        }
+        // 内容字段设置富文本控件
+        else if (StringUtils.endsWithIgnoreCase(columnName, "content"))
+        {
+            column.setHtmlType(GenConstants.HTML_SUMMERNOTE);
+        }
+    }
+
+    /**
+     * 校验数组是否包含指定值
+     * 
+     * @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);
+    }
+
+    /**
+     * 表名转换成Java类名
+     * 
+     * @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/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java
new file mode 100644
index 0000000..9f69403
--- /dev/null
+++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java
@@ -0,0 +1,34 @@
+package com.ruoyi.generator.util;
+
+import java.util.Properties;
+import org.apache.velocity.app.Velocity;
+import com.ruoyi.common.constant.Constants;
+
+/**
+ * VelocityEngine工厂
+ * 
+ * @author ruoyi
+ */
+public class VelocityInitializer
+{
+    /**
+     * 初始化vm方法
+     */
+    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);
+            // 初始化Velocity引擎,指定配置Properties
+            Velocity.init(p);
+        }
+        catch (Exception e)
+        {
+            throw new RuntimeException(e);
+        }
+    }
+}
diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java
new file mode 100644
index 0000000..f73290e
--- /dev/null
+++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java
@@ -0,0 +1,422 @@
+package com.ruoyi.generator.util;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import org.apache.velocity.VelocityContext;
+import com.alibaba.fastjson.JSONObject;
+import com.ruoyi.common.constant.GenConstants;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.generator.config.GenConfig;
+import com.ruoyi.generator.domain.GenTable;
+import com.ruoyi.generator.domain.GenTableColumn;
+
+public class VelocityUtils
+{
+    /** 项目空间路径 */
+    private static final String PROJECT_PATH = "main/java";
+
+    /** mybatis空间路径 */
+    private static final String MYBATIS_PATH = "main/resources/mapper";
+
+    /** html空间路径 */
+    private static final String TEMPLATES_PATH = "main/resources/templates";
+    
+    /** 默认上级菜单,系统工具 */
+    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", genTable.getBusinessName());
+        velocityContext.put("basePackage", getPackagePrefix(packageName));
+        velocityContext.put("packageName", packageName);
+        velocityContext.put("author", genTable.getFunctionAuthor());
+        velocityContext.put("colXsNum", getColXsNum(genTable.getFormColNum()));
+        velocityContext.put("colSmNum", getColSmNum(genTable.getFormColNum()));
+        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);
+        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 = JSONObject.parseObject(options);
+        String parentMenuId = getParentMenuId(paramsObj);
+        context.put("parentMenuId", parentMenuId);
+    }
+
+    public static void setTreeVelocityContext(VelocityContext context, GenTable genTable)
+    {
+        String options = genTable.getOptions();
+        JSONObject paramsObj = JSONObject.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()));
+    }
+
+    /**
+     * 获取模板信息
+     * 
+     * @return 模板列表
+     */
+    public static List<String> getTemplateList(String tplCategory)
+    {
+        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");
+        if (GenConstants.TPL_CRUD.equals(tplCategory))
+        {
+            templates.add("vm/html/list.html.vm");
+        }
+        else if (GenConstants.TPL_TREE.equals(tplCategory))
+        {
+            templates.add("vm/html/tree.html.vm");
+            templates.add("vm/html/list-tree.html.vm");
+        }
+        else if (GenConstants.TPL_SUB.equals(tplCategory))
+        {
+            templates.add("vm/html/list.html.vm");
+            templates.add("vm/java/sub-domain.java.vm");
+        }
+        templates.add("vm/html/add.html.vm");
+        templates.add("vm/html/edit.html.vm");
+        templates.add("vm/sql/sql.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 htmlPath = TEMPLATES_PATH + "/" + moduleName + "/" + businessName;
+
+        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("list.html.vm"))
+        {
+            fileName = StringUtils.format("{}/{}.html", htmlPath, businessName);
+        }
+        else if (template.contains("list-tree.html.vm"))
+        {
+            fileName = StringUtils.format("{}/{}.html", htmlPath, businessName);
+        }
+        else if (template.contains("tree.html.vm"))
+        {
+            fileName = StringUtils.format("{}/tree.html", htmlPath);
+        }
+        else if (template.contains("add.html.vm"))
+        {
+            fileName = StringUtils.format("{}/add.html", htmlPath);
+        }
+        else if (template.contains("edit.html.vm"))
+        {
+            fileName = StringUtils.format("{}/edit.html", htmlPath);
+        }
+        else if (template.contains("sql.vm"))
+        {
+            fileName = businessName + "Menu.sql";
+        }
+        return fileName;
+    }
+
+    /**
+     * 获取项目文件路径
+     * 
+     * @return 路径
+     */
+    public static String getProjectPath()
+    {
+        String packageName = GenConfig.getPackageName();
+        StringBuffer projectPath = new StringBuffer();
+        projectPath.append("main/java/");
+        projectPath.append(packageName.replace(".", "/"));
+        projectPath.append("/");
+        return projectPath.toString();
+    }
+
+    /**
+     * 获取包前缀
+     * 
+     * @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 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 = JSONObject.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;
+    }
+
+    /**
+     * 获取表单排列网格
+     * 
+     * @param formColNum 表单布局方式
+     * @return 排列类样式
+     */
+    public static String getColXsNum(int formColNum)
+    {
+        String colXsNum = "col-xs-12";
+        if (formColNum == 2)
+        {
+            return "col-xs-6";
+        }
+        else if (formColNum == 3)
+        {
+            return "col-xs-4";
+        }
+        return colXsNum;
+    }
+
+    /**
+     * 获取表单label网格
+     * 
+     * @param formColNum 表单布局方式
+     * @return 网格类样式
+     */
+    public static String getColSmNum(int formColNum)
+    {
+        String colSmNum = "col-sm-3";
+        if (formColNum == 2 || formColNum == 3)
+        {
+            return "col-sm-4";
+        }
+        return colSmNum;
+    }
+}
diff --git a/ruoyi-generator/src/main/resources/generator.yml b/ruoyi-generator/src/main/resources/generator.yml
new file mode 100644
index 0000000..73562c7
--- /dev/null
+++ b/ruoyi-generator/src/main/resources/generator.yml
@@ -0,0 +1,13 @@
+
+# 代码生成
+gen:
+  # 作者
+  author: ruoyi
+  # 默认生成包路径 system 需改成自己的模块名称 如 system monitor tool
+  packageName: com.ruoyi.system
+  # 自动去除表前缀,默认是false
+  autoRemovePre: false
+  # 表前缀(生成类名不会包含表前缀,多个用逗号分隔)
+  tablePrefix: sys_
+  # 是否允许生成文件覆盖到本地(自定义路径),默认不允许
+  allowOverwrite: false
\ No newline at end of file
diff --git a/ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml b/ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml
new file mode 100644
index 0000000..86f62de
--- /dev/null
+++ b/ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml
@@ -0,0 +1,127 @@
+<?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.ruoyi.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="GenTableColumn" resultMap="GenTableColumnResult">
+        <include refid="selectGenTableColumnVo"/>
+        where table_id = #{tableId}
+        order by sort
+    </select>
+    
+    <select id="selectDbTableColumnsByName" parameterType="String" resultMap="GenTableColumnResult">
+		select column_name, (case when (is_nullable = 'no' <![CDATA[ && ]]> column_key != 'PRI') then '1' else null end) as is_required, (case when column_key = 'PRI' then '1' else '0' end) as is_pk, ordinal_position as sort, column_comment, (case when extra = 'auto_increment' then '1' else '0' end) as is_increment, column_type
+		from information_schema.columns where table_schema = (select database()) and table_name = (#{tableName})
+		order by ordinal_position
+	</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>
+			sysdate()
+         )
+    </insert>
+	 
+    <update id="updateGenTableColumn" parameterType="GenTableColumn">
+        update gen_table_column
+        <set>
+            column_comment = #{columnComment},
+            java_type = #{javaType},
+            java_field = #{javaField},
+            is_insert = #{isInsert},
+            is_edit = #{isEdit},
+            is_list = #{isList},
+            is_query = #{isQuery},
+            is_required = #{isRequired},
+            query_type = #{queryType},
+            html_type = #{htmlType},
+            dict_type = #{dictType},
+            sort = #{sort},
+            update_by = #{updateBy},
+            update_time = sysdate()
+        </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/ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml b/ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml
new file mode 100644
index 0000000..675cd0c
--- /dev/null
+++ b/ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml
@@ -0,0 +1,204 @@
+<?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.ruoyi.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="formColNum"     column="form_col_num"      />
+		<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, form_col_num, 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 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="selectDbTableList" parameterType="GenTable" resultMap="GenTableResult">
+		select table_name, table_comment, create_time, update_time from information_schema.tables
+		where table_schema = (select database())
+		AND table_name NOT LIKE 'qrtz\_%' AND table_name NOT LIKE 'gen\_%'
+		AND table_name NOT IN (select table_name from gen_table)
+		<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>
+        order by create_time desc
+	</select>
+	
+	<select id="selectDbTableListByNames" resultMap="GenTableResult">
+		select table_name, table_comment, create_time, update_time from information_schema.tables
+		where table_name NOT LIKE 'qrtz\_%' and table_name NOT LIKE 'gen\_%' and table_schema = (select database())
+		and table_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.form_col_num, 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.form_col_num, 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.form_col_num, 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
+		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="formColNum != null">form_col_num,</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="formColNum != null">#{formColNum},</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>
+			sysdate()
+         )
+    </insert>
+    
+    <update id="createTable">
+        ${sql}
+    </update>
+    
+    <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="formColNum != null">form_col_num = #{formColNum},</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 = sysdate()
+        </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/ruoyi-generator/src/main/resources/templates/tool/gen/createTable.html b/ruoyi-generator/src/main/resources/templates/tool/gen/createTable.html
new file mode 100644
index 0000000..c9b9dcf
--- /dev/null
+++ b/ruoyi-generator/src/main/resources/templates/tool/gen/createTable.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org">
+<head>
+    <th:block th:include="include :: header('创建表结构')"/>
+</head>
+<body>
+<div class="main-content">
+    <label class="col-sm-6 control-label">创建表语句(支持多个建表语句):</label>
+    <div class="col-sm-11 col">
+        <textarea class="form-control" id="text_create" name="" placeholder="请输入文本" rows="12" type="text"></textarea>
+    </div>
+</div>
+<th:block th:include="include :: footer"/>
+
+<script type="text/javascript">
+    var prefix = ctx + "tool/gen";
+
+    /* 创建表结构 */
+    function submitHandler() {
+        var rows = $("#text_create").val();
+        if (rows.length == 0) {
+            $.modal.alertWarning("请输入建表语句");
+            return;
+        }
+        var data = {"sql": rows};
+        $.operate.save(prefix + "/createTable", data);
+    }
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-generator/src/main/resources/templates/tool/gen/edit.html b/ruoyi-generator/src/main/resources/templates/tool/gen/edit.html
new file mode 100644
index 0000000..1d45bab
--- /dev/null
+++ b/ruoyi-generator/src/main/resources/templates/tool/gen/edit.html
@@ -0,0 +1,620 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+	<th:block th:include="include :: header('修改生成信息')" />
+	<th:block th:include="include :: select2-css" />
+	<style type="text/css">
+	    .select-table table{table-layout:fixed;}.table>thead>tr>th{text-align:center;}.select-table .table td{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}.form-control{padding:3px 6px 4px;height:30px;}.icheckbox-blue{top:0px;left:6px;}.form-control.select2-hidden-accessible{position:static!important;}.select-table table label.error{position: inherit;}select + label.error{z-index:1;right:40px;}
+	</style>
+</head>
+<body class="gray-bg" style="font: 14px Helvetica Neue, Helvetica, PingFang SC, 微软雅黑, Tahoma, Arial, sans-serif !important;">
+    <section class="section-content">
+    <div class="row">
+        <div class="col-xs-12">
+            <div class="ibox float-e-margins">
+                <div class="ibox-content" style="border-style:none;">
+                    <div class="nav-tabs-custom">
+                        <ul class="nav nav-tabs">
+                            <li><a href="#tab-basic" data-toggle="tab" aria-expanded="false">基本信息</a></li>
+                            <li class="active"><a href="#tab-field" data-toggle="tab" aria-expanded="true">字段信息</a></li>
+                            <li><a href="#tab-gen" data-toggle="tab" aria-expanded="false">生成信息</a></li>
+                            <li class="pull-right header">
+								<i class="fa fa-code"></i> 生成配置
+							</li>
+                        </ul>
+                        <form id="form-gen-edit" class="form-horizontal" th:object="${table}">
+                        <input name="tableId" type="hidden" th:field="*{tableId}" />
+                        <div class="tab-content">
+                            <!-- 基本信息 -->
+                            <div class="tab-pane" id="tab-basic">
+				            <div class="row mt20">
+				            	<div class="col-sm-6">
+				                    <div class="form-group">
+				                        <label class="col-sm-4 control-label is-required">表名称:</label>
+				                        <div class="col-sm-8">
+				                            <input name="tableName" class="form-control" type="text" placeholder="请输入表名称" maxlength="200" th:field="*{tableName}" required>
+				                        </div>
+				                    </div>
+				                </div>
+				                <div class="col-sm-6">
+				                    <div class="form-group">
+				                        <label class="col-sm-4 control-label is-required">表描述:</label>
+				                        <div class="col-sm-8">
+				                            <input name="tableComment" class="form-control" type="text" placeholder="请输入表描述" maxlength="500" th:field="*{tableComment}" required>
+				                        </div>
+				                    </div>
+				                </div>
+				            </div>
+				            <div class="row">
+				                <div class="col-sm-6">
+				                    <div class="form-group">
+				                        <label class="col-sm-4 control-label is-required">实体类名称:</label>
+				                        <div class="col-sm-8">
+				                            <input name="className" class="form-control" type="text" placeholder="请输入实体类名称" maxlength="100" th:field="*{className}" required>
+				                        </div>
+				                    </div>
+				                </div>
+				                <div class="col-sm-6">
+				                    <div class="form-group">
+				                        <label class="col-sm-4 control-label is-required">作者:</label>
+				                        <div class="col-sm-8">
+				                            <input name="functionAuthor" class="form-control" type="text" placeholder="请输入作者" maxlength="50" th:field="*{functionAuthor}" required>
+				                        </div>
+				                    </div>
+				                </div>
+				            </div>
+				            <div class="row">
+				                <div class="col-sm-12">
+				                    <div class="form-group">
+				                        <label class="col-xs-2 control-label">备注:</label>
+				                        <div class="col-xs-10">
+				                            <textarea name="remark" maxlength="500" class="form-control" rows="3"></textarea>
+				                        </div>
+				                    </div>
+				                </div>
+				            </div>
+                            </div>
+                            
+                            <!-- 字段信息 -->
+                            <div class="tab-pane active" id="tab-field">
+                                <div class="select-table table-striped" style="margin-top: 0px;padding-top: 0px;padding-bottom: 0px;">
+								    <table id="bootstrap-table" data-use-row-attr-func="true" data-reorderable-rows="true"></table>
+								</div>
+                            </div>
+                            
+                            <!-- 生成信息 -->
+                            <div class="tab-pane" id="tab-gen">
+					            <div class="row mt20">
+					            	<div class="col-sm-6">
+					                    <div class="form-group">
+					                        <label class="col-sm-4 control-label is-required">生成模板:</label>
+					                        <div class="col-sm-8">
+					                            <select class='form-control' id="tplCategory" name='tplCategory' style="width: 100%">
+												    <option value="crud" th:field="*{tplCategory}">单表(增删改查)</option>
+												    <option value="tree" th:field="*{tplCategory}">树表(增删改查)</option>
+												    <option value="sub" th:field="*{tplCategory}">主子表(增删改查)</option>
+												</select>
+					                        </div>
+					                    </div>
+					                </div>
+					                <div class="col-sm-6">
+					                    <div class="form-group">
+					                        <label class="col-sm-4 control-label is-required" title="生成在哪个java包下,例如 com.ruoyi.project.system">生成包路径:<i class="fa fa-question-circle-o"></i></label>
+					                        <div class="col-sm-8">
+					                            <input name="packageName" class="form-control" type="text" placeholder="请输入生成包路径" maxlength="100" th:field="*{packageName}" required>
+					                        </div>
+					                    </div>
+					                </div>
+					            </div>
+					            <div class="row">
+					                <div class="col-sm-6">
+					                    <div class="form-group">
+					                        <label class="col-sm-4 control-label is-required" title="可理解为子系统名,例如 system">生成模块名:<i class="fa fa-question-circle-o"></i></label>
+					                        <div class="col-sm-8">
+					                            <input name="moduleName" class="form-control" type="text" placeholder="请输入生成模块名" maxlength="30" th:field="*{moduleName}" required>
+					                        </div>
+					                    </div>
+					                </div>
+					                <div class="col-sm-6">
+					                    <div class="form-group">
+					                        <label class="col-sm-4 control-label is-required" title="可理解为功能英文名,例如 user">生成业务名:<i class="fa fa-question-circle-o"></i></label>
+					                        <div class="col-sm-8">
+					                            <input name="businessName" class="form-control" type="text" placeholder="请输入生成业务名" maxlength="50" th:field="*{businessName}" required>
+					                        </div>
+					                    </div>
+					                </div>
+					            </div>
+					            <div class="row">
+					                <div class="col-sm-6">
+					                    <div class="form-group">
+					                        <label class="col-sm-4 control-label is-required" title="用作类描述,例如 用户">生成功能名:<i class="fa fa-question-circle-o"></i></label>
+					                        <div class="col-sm-8">
+					                            <input name="functionName" class="form-control" type="text" placeholder="请输入生成功能名" maxlength="50" th:field="*{functionName}" required>
+					                        </div>
+					                    </div>
+					                </div>
+					                <div class="col-sm-6">
+					                    <div class="form-group">
+					                        <label class="col-sm-4 control-label is-required" title="选择表单的栅格布局方式">表单布局:<i class="fa fa-question-circle-o"></i></label>
+					                        <div class="col-sm-8">
+					                            <select class='form-control' id="formColNum" name='formColNum' style="width: 100%">
+												    <option value="1" th:field="*{formColNum}">单列</option>
+												    <option value="2" th:field="*{formColNum}">双列</option>
+												    <option value="3" th:field="*{formColNum}">三列</option>
+												</select>
+					                        </div>
+					                    </div>
+					                </div>
+					            </div>
+					            <div class="row">
+					                <div class="col-sm-6">
+					                    <div class="form-group">
+					                        <label class="col-sm-4 control-label" title="默认为zip压缩包下载,也可以自定义生成路径">生成代码方式:<i class="fa fa-question-circle-o"></i></label>
+					                        <div class="col-sm-8">
+                                                <label class="radio-box"> <input type="radio" name="genType" value="0" th:field="*{genType}" /> zip压缩包 </label> 
+                                                <label class="radio-box"> <input type="radio" name="genType" value="1" th:field="*{genType}" /> 自定义路径</label> 
+					                        </div>
+					                    </div>
+					                </div>
+					                <div class="col-sm-6">
+					                    <div class="form-group">
+					                        <label class="col-sm-4 control-label is-required" title="分配到指定菜单下,例如 系统管理">上级菜单:<i class="fa fa-question-circle-o"></i></label>
+					                        <div class="col-sm-8">
+					                            <input id="parentMenuId" name="params[parentMenuId]" type="hidden" th:value="*{parentMenuId}"/>
+					                            <div class="input-group">
+												    <input id="parentMenuName" name="params[parentMenuName]" class="form-control" type="text" onclick="selectMenuTree()" placeholder="请选择上级菜单" maxlength="50" th:value="*{parentMenuName}" required>
+											        <span class="input-group-addon"><i class="fa fa-search"></i></span>
+											    </div>
+					                        </div>
+					                    </div>
+					                </div>
+					            </div>
+					            <div class="hidden row" id="pathinfo">
+					                <div class="col-sm-12">
+					                    <div class="form-group">
+					                        <label class="col-xs-2 control-label" title="填写磁盘绝对路径,若不填写,则生成到当前Web项目下">生成基础路径:<i class="fa fa-question-circle-o"></i></label>
+						                    <div class="col-xs-10">
+						                        <div class="input-group input-group-sm">
+						                            <input id="genPath" name="genPath" class="form-control" type="text" th:field="*{genPath}" placeholder="请输入项目路径" maxlength="200">
+						                            <div class="input-group-btn">
+						                               <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">最近路径快速选择 <span class="caret"></span></button>
+															<ul class="dropdown-menu dropdown-menu-right" role="menu">
+																<li><a href="javascript:$('#genPath').val('/')"><i class="fa fa-refresh"></i>恢复默认的生成基础路径</a></li>
+															</ul>
+														</div>
+													</div>
+						                    </div>
+					                    </div>
+					                </div>
+					            </div>
+					            <div class="hidden" id="subInfo">
+					            <h4 class="form-header h4">关联信息</h4>
+					            <div class="row">
+					                <div class="col-sm-6">
+					                    <div class="form-group">
+					                        <label class="col-sm-4 control-label is-required" title="关联子表的表名, 如:sys_user">关联子表的表名:<i class="fa fa-question-circle-o"></i></label>
+					                        <div class="col-sm-8">
+					                            <select class='type form-control' id="subTableName" name='subTableName' th:attr='data-value=*{subTableName}' style="width: 100%">
+					                                <option value="">---请选择---</option>
+												</select>
+					                        </div>
+					                    </div>
+					                </div>
+					                <div class="col-sm-6">
+					                    <div class="form-group">
+					                        <label class="col-sm-4 control-label is-required" title="子表关联的外键名, 如:user_id">子表关联的外键名:<i class="fa fa-question-circle-o"></i></label>
+					                        <div class="col-sm-8">
+					                            <select class='router form-control' id="subTableFkName" name='subTableFkName' th:attr='data-value=*{subTableFkName}' style="width: 100%">
+					                                <option value="">---请选择---</option>
+												</select>
+					                        </div>
+					                    </div>
+					                </div>
+					            </div>
+					            </div>
+					            <div class="hidden" id="otherInfo">
+					            <h4 class="form-header h4">其他信息</h4>
+					            <div class="row">
+					                <div class="col-sm-6">
+					                    <div class="form-group">
+					                        <label class="col-sm-4 control-label is-required" title="树显示的编码字段名, 如:dept_id">树编码字段:<i class="fa fa-question-circle-o"></i></label>
+					                        <div class="col-sm-8">
+					                            <select class='form-control' id="treeCode" name='params[treeCode]' style="width: 100%">
+					                                <option value="">---请选择---</option>
+												    <option th:each="column : ${table.columns}" th:text="${column.columnName + ':' + column.columnComment}" th:value="${column.columnName}" th:field="*{treeCode}"></option>
+												</select>
+					                        </div>
+					                    </div>
+					                </div>
+					                <div class="col-sm-6">
+					                    <div class="form-group">
+					                        <label class="col-sm-4 control-label is-required" title="树显示的父编码字段名, 如:parent_Id">树父编码字段:<i class="fa fa-question-circle-o"></i></label>
+					                        <div class="col-sm-8">
+					                            <select class='form-control' id="treeParentCode" name='params[treeParentCode]' style="width: 100%">
+												    <option value="">---请选择---</option>
+												    <option th:each="column : ${table.columns}" th:text="${column.columnName + ':' + column.columnComment}" th:value="${column.columnName}" th:field="*{treeParentCode}"></option>
+												</select>
+					                        </div>
+					                    </div>
+					                </div>
+					            </div>
+					            <div class="row">
+					                <div class="col-sm-6">
+					                    <div class="form-group">
+					                        <label class="col-sm-4 control-label is-required" title="树节点的显示名称字段名, 如:dept_name">树名称字段:<i class="fa fa-question-circle-o"></i></label>
+					                        <div class="col-sm-8">
+					                            <select class='form-control' id="treeName" name='params[treeName]' style="width: 100%">
+												    <option value="">---请选择---</option>
+												    <option th:each="column : ${table.columns}" th:text="${column.columnName + ':' + column.columnComment}" th:value="${column.columnName}" th:field="*{treeName}"></option>
+												</select>
+					                        </div>
+					                    </div>
+					                </div>
+					            </div>
+					            </div>
+                            </div>
+                        </div>
+                        </form>
+                    </div>
+                </div>
+               <div class="box-footer">
+			       <div class="col-sm-offset-5 col-sm-6">
+			           <button type="button" class="btn btn-sm btn-primary" onclick="submitHandler()"><i class="fa fa-check"></i>保 存</button>&nbsp;
+			           <button type="button" class="btn btn-sm btn-danger" onclick="closeItem()"><i class="fa fa-reply-all"></i>关 闭 </button>
+			       </div>
+           	   </div>
+            </div>
+        </div>
+    </div>
+	</section>
+    <th:block th:include="include :: footer" />
+    <th:block th:include="include :: select2-js" />
+    <th:block th:include="include :: bootstrap-table-reorder-rows-js" />
+    <script th:src="@{/js/jquery.tmpl.js}"></script>
+    <th:block th:include="include :: jquery-cxselect-js" />
+    <script th:inline="javascript">
+	    /* 用户信息-修改 */
+	    $("#form-table-edit").validate({
+	    	rules: {
+	    	    tableName: {
+	    	        required: true,
+	    	    },
+	    	},
+			focusCleanup: true
+		});
+	    
+	    /* 表级联信息 */
+   		var data = [[${data}]];
+    	$('#subInfo').cxSelect({
+    	  selects: ['type', 'router'],
+    	  jsonValue: 'v',
+    	  data: data
+    	});
+	    
+	    function submitHandler() {
+	        if ($.validate.form()) {
+	        	$.operate.saveTab(prefix + "/edit", $("#form-gen-edit").serializeArray());
+	        }
+	    }
+	    
+	    var prefix = ctx + "tool/gen";
+		$(function() {
+		    var options = {
+		        url: prefix + "/column/list",
+		        sidePagination: "client",
+		        sortName: "sort",
+		        sortOrder: "desc",
+		        height: $(window).height() - 166,
+		        pagination: false,
+		        showSearch: false,
+		        showRefresh: false,
+		        showToggle: false,
+		        showColumns: false,
+		        onLoadSuccess: onLoadSuccess,
+		        onReorderRow: onReorderRow,
+		        columns: [{
+                    title: "序号",
+                    width: "5%",
+                    formatter: function (value, row, index) {
+                    	// 编号隐藏域
+                    	var columnIdHtml = $.common.sprintf("<input type='hidden' name='columns[%s].columnId' value='%s'>", index, row.columnId);
+                    	// 排序隐藏域
+                    	var sortHtml = $.common.sprintf("<input type='hidden' name='columns[%s].sort' value='%s' id='columns_sort_%s'>", index, row.sort, row.columnId);
+                    	return columnIdHtml + sortHtml + $.table.serialNumber(index);
+                    },
+                    cellStyle: function(value, row, index) {
+                        return { css: { "cursor": "move" } };
+                    }
+                },
+		        {
+		            field: 'columnName',
+		            title: '字段列名',
+		            width: "10%",
+		            class: "nodrag",
+		            cellStyle: function(value, row, index) {
+                        return { css: { "cursor": "default" } };
+                    }
+		        },
+		        {
+		            field: 'columnComment',
+		            title: '字段描述',
+		            width: "10%",
+		            formatter: function (value, row, index) {
+		            	var html = $.common.sprintf("<input class='form-control' type='text' name='columns[%s].columnComment' value='%s'>", index, value);
+		        		return html;
+		        	}
+		        },
+		        {
+		            field: 'columnType',
+		            title: '物理类型',
+		            width: "10%",
+		            class: "nodrag",
+		            cellStyle: function(value, row, index) {
+                        return { css: { "cursor": "default" } };
+                    }
+		        },
+		        {
+		            field: 'javaType',
+		            title: 'Java类型',
+		            width: "10%",
+		            formatter: function (value, row, index) {
+		        		var data = [{ index: index, javaType: value }];
+		                return $("#javaTypeTpl").tmpl(data).html();
+		        	}
+		        },
+		        {
+		            field: 'javaField',
+		            title: 'Java属性',
+		            width: "10%",
+		            formatter: function (value, row, index) {
+		        		var html = $.common.sprintf("<input class='form-control' type='text' name='columns[%s].javaField' value='%s' required>", index, value);
+		        		return html;
+		        	}
+		        },
+		        {
+		            field: 'isInsert',
+		            title: '插入',
+		            width: "5%",
+		            formatter: function (value, row, index) {
+		            	var isCheck = value == 1 ? 'checked' : '';
+		            	var html = $.common.sprintf("<label class='check-box'><input type='checkbox' name='columns[%s].isInsert' value='1' %s></label>", index, isCheck);
+		        		return html;
+		        	}
+		        },
+		        {
+		            field: 'isEdit',
+		            title: '编辑',
+		            width: "5%",
+		            formatter: function (value, row, index) {
+		            	var isCheck = value == 1 ? 'checked' : '';
+		            	var html = $.common.sprintf("<label class='check-box'><input type='checkbox' name='columns[%s].isEdit' value='1' %s></label>", index, isCheck);
+		        		return html;
+		        	}
+		        },
+		        {
+		            field: 'isList',
+		            title: '列表',
+		            width: "5%",
+		            formatter: function (value, row, index) {
+		            	var isCheck = value == 1 ? 'checked' : '';
+		            	var html = $.common.sprintf("<label class='check-box'><input type='checkbox' name='columns[%s].isList' value='1' %s></label>", index, isCheck);
+		        		return html;
+		        	}
+		        },
+		        {
+		            field: 'isQuery',
+		            title: '查询',
+		            width: "5%",
+		            formatter: function (value, row, index) {
+		            	var isCheck = value == 1 ? 'checked' : '';
+		            	var html = $.common.sprintf("<label class='check-box'><input type='checkbox' name='columns[%s].isQuery' value='1' %s></label>", index, isCheck);
+		        		return html;
+		        	}
+		        },
+		        {
+		            field: 'queryType',
+		            title: '查询方式',
+		            width: "10%",
+		            formatter: function (value, row, index) {
+		            	var data = [{ index: index, queryType: value }];
+		                return $("#queryTypeTpl").tmpl(data).html();
+		        	}
+		        },
+		        {
+		            field: 'isRequired',
+		            title: '必填',
+		            width: "5%",
+		            formatter: function (value, row, index) {
+		            	var isCheck = value == 1 ? 'checked' : '';
+		            	var html = $.common.sprintf("<label class='check-box'><input type='checkbox' name='columns[%s].isRequired' value='1' %s></label>", index, isCheck);
+		        		return html;
+		        	}
+		        },
+		        {
+		            field: 'htmlType',
+		            title: '显示类型',
+		            width: "12%",
+		            formatter: function (value, row, index) {
+		            	var data = [{ index: index, htmlType: value }];
+		                return $("#htmlTypeTpl").tmpl(data).html();
+		        	}
+		        },
+		        {
+		            field: 'dictType',
+		            title: '字典类型',
+		            width: "13%",
+		            formatter: function (value, row, index) {
+		        		var html = $.common.sprintf("<input class='form-control' type='text' name='columns[%s].dictType' value='%s' id='columns_dict_%s'>", index, (value === undefined ? '' : value), row.columnId);
+		        		return "<div class='input-group'>" + html + "<span class='input-group-addon input-sm' onclick='selectDictTree(" + row.columnId + ", this)'><i class='fa fa-search'></i></span></div>";
+		        	},
+		        	cellStyle: function(value, row, index) {
+                        return { css: { "cursor": "default" } };
+                    }
+		        }]
+		    };
+		    $.table.init(options);
+		});
+		
+		// 当所有数据被加载时触发处理函数
+		function onLoadSuccess(data){
+			$.fn.select2.defaults.set( "theme", "bootstrap" );
+			$("select.form-control").each(function () {
+				$(this).select2().on("change", function () {
+					$(this).valid();
+				})
+			})
+			$(".check-box").each(function() {
+	            $(this).iCheck({
+	                checkboxClass: 'icheckbox-blue'
+            	})
+        	})
+        }
+		
+		// 当拖拽结束后处理函数
+		function onReorderRow(data) {
+	        for (var i = 0; i < data.length; i++) {
+			    $("#columns_sort_" + data[i].columnId).val(i+1);
+			}
+       }
+		
+		$(function() {
+            var tplCategory = $("#tplCategory option:selected").val();
+            tplCategoryVisible(tplCategory);
+            var genType = $('input[name="genType"]:checked').val();
+            pathInfoVisible(genType);
+        });
+		
+		$('#tplCategory').on('select2:select', function (event) {
+			var tplCategory = $(event.target).val();
+			tplCategoryVisible(tplCategory);
+		});
+		
+		function tplCategoryVisible(tplCategory) {
+			if("crud" == tplCategory){
+				$("#treeCode").select2("val", [""]);
+				$("#treeParentCode").select2("val", [""]);
+				$("#treeName").select2("val", [""]);
+				$("#otherInfo").addClass("hidden");
+				$("#subInfo").addClass("hidden");
+			} else if("tree" == tplCategory){
+				$("#otherInfo").removeClass("hidden");
+				$("#treeCode").attr("required", "true");
+				$("#treeParentCode").attr("required", "true");
+				$("#treeName").attr("required", "true");
+				$("#subInfo").addClass("hidden");
+			} else if("sub" == tplCategory){
+				$("#subInfo").removeClass("hidden");
+				$("#treeCode").select2("val", [""]);
+				$("#treeParentCode").select2("val", [""]);
+				$("#treeName").select2("val", [""]);
+				$("#subTableName").attr("required", "true");
+				$("#subTableFkName").attr("required", "true");
+				$("#otherInfo").addClass("hidden");
+			}
+        }
+		
+		$('input').on('ifChecked', function(event){
+			var genType = $(event.target).val();
+			pathInfoVisible(genType);
+		});
+		
+		function pathInfoVisible(genType) {
+			if("0" == genType){
+				$("#genPath").val("/");
+				$("#pathinfo").addClass("hidden");
+			} else if("1" == genType){
+				$("#pathinfo").removeClass("hidden");
+			}
+		}
+		
+		// 选择字典处理函数
+		function selectDictTree(columnId, obj) {
+			var dictType = $.common.nullToStr($(obj).parent().find("input").val());
+        	var url = ctx + "system/dict/selectDictTree/" + columnId + "/" + dictType;
+			var options = {
+				title: '选择字典类型',
+				width: "380",
+				url: url,
+				callBack: doDictSubmit
+			};
+			$.modal.openOptions(options);
+		}
+		
+		// 选择菜单处理函数
+        function selectMenuTree() {
+        	var parentMenuId = $("#parentMenuId").val();
+        	var menuId = parentMenuId > 0 ? parentMenuId : 1;
+        	var url = ctx + "system/menu/selectMenuTree/" + menuId;
+			var options = {
+				title: '菜单选择',
+				width: "380",
+				url: url,
+				callBack: doMenuSubmit
+			};
+			$.modal.openOptions(options);
+		}
+		
+		function doDictSubmit(index, layero){
+			var body = $.modal.getChildFrame(index);
+   			var columnId = body.find('#columnId').val();
+   			var dictType = body.find('#dictType').val();
+   			$.modal.close(index);
+   			$("#columns_dict_" + columnId).val(dictType);
+		}
+		
+		function doMenuSubmit(index, layero){
+			var body = $.modal.getChildFrame(index);
+   			$("#parentMenuId").val(body.find('#treeId').val());
+   			$("#parentMenuName").val(body.find('#treeName').val());
+   			$.modal.close(index);
+		}
+    </script>
+</body>
+</html>
+
+
+<!-- java类型 -->
+<script id="javaTypeTpl" type="text/x-jquery-tmpl">
+<div>
+<select class='form-control' name='columns[${index}].javaType'>
+    <option value="Long" {{if javaType==="Long"}}selected{{/if}}>Long</option>
+    <option value="String" {{if javaType==="String"}}selected{{/if}}>String</option>
+    <option value="Integer" {{if javaType==="Integer"}}selected{{/if}}>Integer</option>
+    <option value="Double" {{if javaType==="Double"}}selected{{/if}}>Double</option>
+    <option value="BigDecimal" {{if javaType==="BigDecimal"}}selected{{/if}}>BigDecimal</option>
+    <option value="Date" {{if javaType==="Date"}}selected{{/if}}>Date</option>
+</select>
+</div>
+</script>
+
+<!-- 查询方式 -->
+<script id="queryTypeTpl" type="text/x-jquery-tmpl">
+<div>
+<select class='form-control' name='columns[${index}].queryType'>
+    <option value="EQ" {{if queryType==="EQ"}}selected{{/if}}>=</option>
+    <option value="NE" {{if queryType==="NE"}}selected{{/if}}>!=</option>
+    <option value="GT" {{if queryType==="GT"}}selected{{/if}}>></option>
+    <option value="GTE" {{if queryType==="GTE"}}selected{{/if}}>>=</option>
+    <option value="LT" {{if queryType==="LT"}}selected{{/if}}><</option>
+    <option value="LTE" {{if queryType==="LTE"}}selected{{/if}}><=</option>
+    <option value="LIKE" {{if queryType==="LIKE"}}selected{{/if}}>Like</option>
+    <option value="BETWEEN" {{if queryType==="BETWEEN"}}selected{{/if}}>Between</option>
+</select>
+</div>
+</script>
+
+<!-- 显示类型 -->
+<script id="htmlTypeTpl" type="text/x-jquery-tmpl">
+<div>
+<select class='form-control' name='columns[${index}].htmlType'>
+    <option value="input" {{if htmlType==="input"}}selected{{/if}}>文本框</option>
+    <option value="textarea" {{if htmlType==="textarea"}}selected{{/if}}>文本域</option>
+    <option value="select" {{if htmlType==="select"}}selected{{/if}}>下拉框</option>
+    <option value="radio" {{if htmlType==="radio"}}selected{{/if}}>单选框</option>
+    <option value="checkbox" {{if htmlType==="checkbox"}}selected{{/if}}>复选框</option>
+    <option value="summernote" {{if htmlType==="summernote"}}selected{{/if}}>富文本</option>
+    <option value="datetime" {{if htmlType==="datetime"}}selected{{/if}}>日期控件</option>
+    <option value="upload" {{if htmlType==="upload"}}selected{{/if}}>上传控件</option>
+</select>
+</div>
+</script>
diff --git a/ruoyi-generator/src/main/resources/templates/tool/gen/gen.html b/ruoyi-generator/src/main/resources/templates/tool/gen/gen.html
new file mode 100644
index 0000000..bf980d9
--- /dev/null
+++ b/ruoyi-generator/src/main/resources/templates/tool/gen/gen.html
@@ -0,0 +1,219 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('代码生成列表')" />
+</head>
+<body class="gray-bg">
+    <div class="container-div">
+		<div class="row">
+			<div class="col-sm-12 search-collapse">
+				<form id="gen-form">
+					<div class="select-list">
+						<ul>
+							<li>
+								表名称:<input type="text" name="tableName"/>
+							</li>
+							<li>
+								表描述:<input type="text" name="tableComment"/>
+							</li>
+							<li class="select-time">
+								<label>表时间: </label>
+								<input type="text" class="time-input" id="startTime" placeholder="开始时间" name="params[beginTime]"/>
+								<span>-</span>
+								<input type="text" class="time-input" id="endTime" placeholder="结束时间" name="params[endTime]"/>
+							</li>
+							<li>
+								<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
+								<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
+							</li>
+						</ul>
+					</div>
+				</form>
+			</div>
+			
+			<div class="btn-group-sm" id="toolbar" role="group">
+			     <a class="btn btn-success multiple disabled" onclick="javascript:batchGenCode()" shiro:hasPermission="tool:gen:code">
+			        <i class="fa fa-download"></i> 生成
+			    </a>
+				<a class="btn btn-success" onclick="createTable()" shiro:hasRole="admin">
+					<i class="fa fa-plus"></i> 创建
+				</a>
+				<a class="btn btn-info" onclick="importTable()">
+			        <i class="fa fa-upload"></i> 导入
+			    </a>
+			    <a class="btn btn-primary single disabled" onclick="$.operate.editTab()" shiro:hasPermission="tool:gen:edit">
+		            <i class="fa fa-edit"></i> 修改
+		        </a>
+			    <a class="btn btn-danger multiple disabled" onclick="$.operate.removeAll()" shiro:hasPermission="tool:gen:remove">
+		            <i class="fa fa-remove"></i> 删除
+		        </a>
+		    </div>
+		
+		    <div class="col-sm-12 select-table table-striped">
+			    <table id="bootstrap-table"></table>
+			</div>
+		</div>
+	</div>
+	<th:block th:include="include :: footer" />
+	<th:block th:include="include :: bootstrap-table-export-js" />
+	<script th:src="@{/ajax/libs/highlight/highlight.min.js}"></script>
+	<script th:inline="javascript">
+		var prefix = ctx + "tool/gen";
+		var editFlag = [[${@permission.hasPermi('tool:gen:edit')}]];
+		var removeFlag = [[${@permission.hasPermi('tool:gen:remove')}]];
+		var previewFlag = [[${@permission.hasPermi('tool:gen:preview')}]];
+		var codeFlag = [[${@permission.hasPermi('tool:gen:code')}]];
+	
+		$(function() {
+		    var options = {
+		        url: prefix + "/list",
+		        updateUrl: prefix + "/edit/{id}",
+		        removeUrl: prefix + "/remove",
+		        sortName: "createTime",
+		        sortOrder: "desc",
+		        showExport: true,
+		        modalName: "生成配置",
+		        rememberSelected: true,
+		        uniqueId: "tableId",
+		        columns: [{
+		        	field: 'state',
+		            checkbox: true
+		        },
+		        {
+		            field: 'tableId',
+		            title: '编号',
+		            visible: false
+		        },
+		        {
+                    title: "序号",
+                    formatter: function (value, row, index) {
+                 	    return $.table.serialNumber(index);
+                    }
+                },
+		        {
+		            field: 'tableName',
+		            title: '表名称',
+		            sortable: true,
+		            formatter: function(value, row, index) {
+                    	return $.table.tooltip(value);
+                    }
+		        },
+		        {
+		            field: 'tableComment',
+		            title: '表描述',
+		            sortable: true,
+		            formatter: function(value, row, index) {
+                    	return $.table.tooltip(value, 15);
+                    }
+		        },
+		        {
+		            field: 'className',
+		            title: '实体类名称',
+		            sortable: true
+		        },
+		        {
+		            field: 'createTime',
+		            title: '创建时间',
+		            sortable: true
+		        },
+		        {
+		            field: 'updateTime',
+		            title: '更新时间',
+		            sortable: true
+		        },
+		        {
+		            title: '操作',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		                var actions = [];
+		                actions.push('<a class="btn btn-info btn-xs ' + previewFlag + '" href="javascript:void(0)" onclick="preview(\'' + row.tableId + '\')"><i class="fa fa-search"></i>预览</a> ');
+		                actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.editTab(\'' + row.tableId + '\')"><i class="fa fa-edit"></i>编辑</a> ');
+		                actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.tableId + '\')"><i class="fa fa-remove"></i>删除</a> ');
+		                actions.push('<a class="btn btn-warning btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="synchDb(\'' + row.tableName + '\')"><i class="fa fa-refresh"></i>同步</a> ');
+		                actions.push('<a class="btn btn-primary btn-xs ' + codeFlag + '" href="javascript:void(0)" onclick="genCode(\'' + row.tableName + '\',\'' + row.genType + '\')"><i class="fa fa-bug"></i>生成代码</a> ');
+		                return actions.join('');
+		            }
+		        }]
+		    };
+		    $.table.init(options);
+		});
+		
+		// 预览代码
+		function preview(tableId) {
+			var preViewUrl = prefix + "/preview/" + tableId;
+			$.modal.loading("正在加载数据,请稍候...");
+			$.get(preViewUrl, function(result) {
+				if (result.code == web_status.SUCCESS) {
+					 var items = [];
+		                $.each(result.data, function(index, value) {
+		                    var templateName = index.substring(index.lastIndexOf("/") + 1, index.length).replace(/\.vm/g, "");
+		                    if(!$.common.equals("sql", templateName) && !$.common.equals("tree.html", templateName) && !$.common.equals("sub-domain.java", templateName)){
+		                        var codeName = templateName.replace(".", "");
+		                        var language = templateName.substring(templateName.lastIndexOf(".") + 1);
+		                        var highCode = hljs.highlight(language, value).value;
+		                        items.push({
+		                            title: templateName , content: "<pre class=\"layui-code\"><a style=\"float:right\" href=\"javascript:copyText('" + codeName + "')\"><i class=\"fa fa-copy\"></i> 复制</a><code id=\"" + codeName + "\">" + highCode + "</code></pre><textarea id=\"t_" + codeName + "\" style='position: absolute;top: 0;left: 0;opacity: 0;z-index: -10;'></textarea><script>function copyText(codeName){var text = document.getElementById(codeName).innerText;var input = document.getElementById(\"t_\"+codeName);input.value = text;input.select();document.execCommand(\"copy\");$.modal.msgSuccess(\"复制成功\");}<\/script>"
+		                        })
+		                    }
+		                });
+		                top.layer.tab({
+                            area: ['90%', '90%'],
+                            shadeClose: true,
+                            success: function(layero, index){
+                                parent.loadCss(ctx + "ajax/libs/highlight/default.min.css");
+                            },
+	                        tab: items
+		                });
+				} else {
+					$.modal.alertError(result.msg);
+				}
+				$.modal.closeLoading();
+			});
+		}
+	
+		// 生成代码
+		function genCode(tableName, genType) {
+		    $.modal.confirm("确定要生成" + tableName + "表代码吗?", function() {
+		    	if(genType === "0") {
+			    	location.href = prefix + "/download/" + tableName;
+			        layer.msg('执行成功,正在生成代码请稍候…', { icon: 1 });
+				} else if(genType === "1") {
+					$.operate.get(prefix + "/genCode/" + tableName);
+				}
+		    })
+		}
+		
+		// 同步数据库
+		function synchDb(tableName){
+			$.modal.confirm("确认要强制同步" + tableName + "表结构吗?", function() {
+			    $.operate.get(prefix + "/synchDb/" + tableName);
+			})
+		}
+	
+		// 批量生成代码
+		function batchGenCode() {
+		    var rows = $.table.selectColumns("tableName");
+		    if (rows.length == 0) {
+		        $.modal.alertWarning("请选择要生成的数据");
+		        return;
+		    }
+		    $.modal.confirm("确认要生成选中的" + rows.length + "条数据吗?", function() {
+		    	location.href = prefix + "/batchGenCode?tables=" + rows;
+		        layer.msg('执行成功,正在生成代码请稍候…', { icon: 1 });
+		    });
+		}
+
+		// 导入表结构
+		function importTable() {
+			var importTableUrl = prefix + "/importTable";
+			$.modal.open("导入表结构", importTableUrl);
+		}
+
+		// 创建表结构
+		function createTable() {
+			var creatTableUrl = prefix + "/createTable";
+			$.modal.open("创建表结构", creatTableUrl);
+		}
+	</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-generator/src/main/resources/templates/tool/gen/importTable.html b/ruoyi-generator/src/main/resources/templates/tool/gen/importTable.html
new file mode 100644
index 0000000..91562e7
--- /dev/null
+++ b/ruoyi-generator/src/main/resources/templates/tool/gen/importTable.html
@@ -0,0 +1,95 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('导入表结构')" />
+</head>
+<body class="gray-bg">
+    <div class="container-div">
+		<div class="row">
+			<div class="col-sm-12 search-collapse">
+				<form id="gen-form">
+					<div class="select-list">
+						<ul>
+							<li>
+								表名称:<input type="text" name="tableName"/>
+							</li>
+							<li>
+								表描述:<input type="text" name="tableComment"/>
+							</li>
+							<li>
+								<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
+								<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
+							</li>
+						</ul>
+					</div>
+				</form>
+			</div>
+			
+		    <div class="col-sm-12 select-table table-striped">
+			    <table id="bootstrap-table"></table>
+			</div>
+		</div>
+	</div>
+	<th:block th:include="include :: footer" />
+	<script type="text/javascript">
+		var prefix = ctx + "tool/gen";
+	
+		$(function() {
+		    var options = {
+		        url: prefix + "/db/list",
+		        showSearch: false,
+		        showRefresh: false,
+		        showToggle: false,
+		        showColumns: false,
+		        clickToSelect: true,
+		        rememberSelected: true,
+		        uniqueId: "tableName",
+		        columns: [{
+		        	field: 'state',
+		            checkbox: true
+		        },
+		        {
+                    title: "序号",
+                    formatter: function (value, row, index) {
+                 	    return $.table.serialNumber(index);
+                    }
+                },
+		        {
+		            field: 'tableName',
+		            title: '表名称',
+		            formatter: function(value, row, index) {
+                    	return $.table.tooltip(value);
+                    }
+		        },
+		        {
+		            field: 'tableComment',
+		            title: '表描述',
+		            formatter: function(value, row, index) {
+                    	return $.table.tooltip(value);
+                    }
+		        },
+		        {
+		            field: 'createTime',
+		            title: '创建时间'
+		        },
+		        {
+		            field: 'updateTime',
+		            title: '更新时间'
+		        }]
+		    };
+		    $.table.init(options);
+		});
+		
+		/* 导入表结构-选择表结构-提交 */
+		function submitHandler() {
+			var rows = $.table.selectColumns("tableName");
+			if (rows.length == 0) {
+       			$.modal.alertWarning("请至少选择一条记录");
+       			return;
+       		}
+			var data = {"tables": rows.join()};
+			$.operate.save(prefix + "/importTable", data);
+		}
+	</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-generator/src/main/resources/vm/html/add.html.vm b/ruoyi-generator/src/main/resources/vm/html/add.html.vm
new file mode 100644
index 0000000..12bfb9b
--- /dev/null
+++ b/ruoyi-generator/src/main/resources/vm/html/add.html.vm
@@ -0,0 +1,403 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+    <th:block th:include="include :: header('新增${functionName}')" />
+#foreach($column in $columns)
+#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "datetime")
+    <th:block th:include="include :: datetimepicker-css" />
+#break
+#end
+#end
+#foreach($column in $columns)
+#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "upload")
+    <th:block th:include="include :: bootstrap-fileinput-css"/>
+#break
+#end
+#end
+#foreach($column in $columns)
+#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "summernote")
+    <th:block th:include="include :: summernote-css" />
+#break
+#end
+#end
+</head>
+<body class="white-bg">
+    <div class="wrapper wrapper-content animated fadeInRight ibox-content">
+        <form class="form-horizontal m" id="form-${businessName}-add">
+#if($table.sub)
+            <h4 class="form-header h4">${functionName}信息</h4>
+#end
+#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)
+            <div class="${colXsNum}">
+                <div class="form-group">
+                    <label class="${colSmNum} control-label#if($column.required) is-required#end">${comment}:</label>
+                    <div class="col-sm-8">
+                        <div class="input-group">
+#set($BusinessName=$businessName.substring(0,1).toUpperCase() + ${businessName.substring(1)})
+#set($treeId = "${className}?.${treeCode}")
+                            <input id="treeId" name="${treeParentCode}" type="hidden" th:value="${${treeId}}"/>
+                            <input class="form-control" type="text" onclick="select${BusinessName}Tree()" id="treeName" readonly="true" th:value="${${treeName}}"#if($column.required) required#end>
+                            <span class="input-group-addon"><i class="fa fa-search"></i></span>
+                        </div>
+                    </div>
+                </div>
+            </div>
+#elseif($column.htmlType == "input")
+            <div class="${colXsNum}">
+                <div class="form-group">
+                    <label class="${colSmNum} control-label#if($column.required) is-required#end">${comment}:</label>
+                    <div class="col-sm-8">
+                        <input name="${field}" class="form-control" type="text"#if($column.required) required#end>
+                    </div>
+                </div>
+            </div>
+#elseif($column.htmlType == "upload")
+            <div class="${colXsNum}">
+                <div class="form-group">
+                    <label class="${colSmNum} control-label#if($column.required) is-required#end">${comment}:</label>
+                    <div class="col-sm-8">
+                        <input type="hidden" name="${field}">
+                        <div class="file-loading">
+                            <input class="form-control file-upload" id="${field}" name="file" type="file">
+                        </div>
+                    </div>
+                </div>
+            </div>
+#elseif($column.htmlType == "summernote")
+            <div class="${colXsNum}">
+                <div class="form-group">
+                    <label class="${colSmNum} control-label#if($column.required) is-required#end">${comment}:</label>
+                    <div class="col-sm-8">
+                        <input type="hidden" class="form-control" name="${field}">
+                        <div class="summernote" id="${field}"></div>
+                    </div>
+                </div>
+            </div>
+#elseif($column.htmlType == "select" && "" != $dictType)
+            <div class="${colXsNum}">
+                <div class="form-group">
+                    <label class="${colSmNum} control-label#if($column.required) is-required#end">${comment}:</label>
+                    <div class="col-sm-8">
+                        <select name="${field}" class="form-control" th:with="type=${@dict.getType('${dictType}')}"#if($column.required) required#end>
+                            <option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
+                        </select>
+                    </div>
+                </div>
+            </div>
+#elseif($column.htmlType == "select" && $dictType)
+            <div class="${colXsNum}">
+                <div class="form-group">
+                    <label class="${colSmNum} control-label#if($column.required) is-required#end">${comment}:</label>
+                    <div class="col-sm-8">
+                       <select name="${field}" class="form-control"#if($column.required) required#end>
+                            <option value="">所有</option>
+                        </select>
+                        <span class="help-block m-b-none"><i class="fa fa-info-circle"></i> 代码生成请选择字典属性</span>
+                    </div>
+                </div>
+            </div>
+#elseif($column.htmlType == "checkbox" && "" != $dictType)
+            <div class="${colXsNum}">
+                <div class="form-group">
+                    <label class="${colSmNum} control-label#if($column.required) is-required#end">${comment}:</label>
+                    <div class="col-sm-8" th:with="type=${@dict.getType('${dictType}')}">
+                        <label th:each="dict : ${type}" class="check-box">
+                            <input name="${field}" type="checkbox" th:value="${dict.dictValue}" th:text="${dict.dictLabel}"#if($column.required) required#end>
+                        </label>
+                    </div>
+                </div>
+            </div>
+#elseif($column.htmlType == "checkbox" && $dictType)
+            <div class="${colXsNum}">
+                <div class="form-group">
+                    <label class="${colSmNum} control-label#if($column.required) is-required#end">${comment}:</label>
+                    <div class="col-sm-8">
+                        <label class="check-box">
+                            <input name="${field}" type="checkbox"#if($column.required) required#end> 无
+                        </label>
+                        <span class="help-block m-b-none"><i class="fa fa-info-circle"></i> 代码生成请选择字典属性</span>
+                    </div>
+                </div>
+            </div>
+#elseif($column.htmlType == "radio" && "" != $dictType)
+            <div class="${colXsNum}">
+                <div class="form-group">
+                    <label class="${colSmNum} control-label#if($column.required) is-required#end">${comment}:</label>
+                    <div class="col-sm-8">
+                        <div class="radio-box" th:each="dict : ${@dict.getType('${dictType}')}">
+                            <input type="radio" th:id="${'${field}_' + dict.dictCode}" name="${field}" th:value="${dict.dictValue}" th:checked="${dict.default}"#if($column.required) required#end>
+                            <label th:for="${'${field}_' + dict.dictCode}" th:text="${dict.dictLabel}"></label>
+                        </div>
+                    </div>
+                </div>
+            </div>
+#elseif($column.htmlType == "radio" && $dictType)
+            <div class="${colXsNum}">
+                <div class="form-group">
+                    <label class="${colSmNum} control-label#if($column.required) is-required#end">${comment}:</label>
+                    <div class="col-sm-8">
+                        <div class="radio-box">
+                            <input type="radio" name="${field}" value=""#if($column.required) required#end>
+                            <label th:for="${field}" th:text="未知"></label>
+                        </div>
+                        <span class="help-block m-b-none"><i class="fa fa-info-circle"></i> 代码生成请选择字典属性</span>
+                    </div>
+                </div>
+            </div>
+#elseif($column.htmlType == "datetime")
+            <div class="${colXsNum}">
+                <div class="form-group">
+                    <label class="${colSmNum} control-label#if($column.required) is-required#end">${comment}:</label>
+                    <div class="col-sm-8">
+                        <div class="input-group date">
+                            <input name="${field}" class="form-control" placeholder="yyyy-MM-dd" type="text"#if($column.required) required#end>
+                            <span class="input-group-addon"><i class="fa fa-calendar"></i></span>
+                        </div>
+                    </div>
+                </div>
+            </div>
+#elseif($column.htmlType == "textarea")
+            <div class="${colXsNum}">
+                <div class="form-group">
+                    <label class="${colSmNum} control-label#if($column.required) is-required#end">${comment}:</label>
+                    <div class="col-sm-8">
+                        <textarea name="${field}" class="form-control"#if($column.required) required#end></textarea>
+                    </div>
+                </div>
+            </div>
+#end
+#end
+#end
+#end
+#if($table.sub)
+            <h4 class="form-header h4">${subTable.functionName}信息</h4>
+            <div class="row">
+                <div class="col-xs-12">
+                    <button type="button" class="btn btn-white btn-sm" onclick="addRow()"><i class="fa fa-plus"> 增加</i></button>
+                    <button type="button" class="btn btn-white btn-sm" onclick="sub.delRow()"><i class="fa fa-minus"> 删除</i></button>
+                    <div class="col-sm-12 select-table table-striped">
+                        <table id="bootstrap-table"></table>
+                    </div>
+                </div>
+            </div>
+#end
+        </form>
+    </div>
+    <th:block th:include="include :: footer" />
+#foreach($column in $columns)
+#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "datetime")
+    <th:block th:include="include :: datetimepicker-js" />
+#break
+#end
+#end
+#foreach($column in $columns)
+#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "upload")
+    <th:block th:include="include :: bootstrap-fileinput-js"/>
+#break
+#end
+#end
+#foreach($column in $columns)
+#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "summernote")
+    <th:block th:include="include :: summernote-js" />
+#break
+#end
+#end
+    <script th:inline="javascript">
+        var prefix = ctx + "${moduleName}/${businessName}"
+#if($table.sub)
+#foreach($column in $subTable.columns)
+#if(${column.dictType} != '')
+        var ${column.javaField}Datas = [[${@dict.getType('${column.dictType}')}]];
+#end
+#end
+#end
+        $("#form-${businessName}-add").validate({
+            focusCleanup: true
+        });
+
+        function submitHandler() {
+            if ($.validate.form()) {
+                $.operate.save(prefix + "/add", $('#form-${businessName}-add').serialize());
+            }
+        }
+#foreach($column in $columns)
+#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "datetime")
+
+        $("input[name='$column.javaField']").datetimepicker({
+            format: "yyyy-mm-dd",
+            minView: "month",
+            autoclose: true
+        });
+#end
+#end
+#foreach($column in $columns)
+#if($column.edit && !$column.superColumn && !$column.pk && $column.htmlType == "upload")
+
+        $(".file-upload").fileinput({
+            uploadUrl: ctx + 'common/upload',
+            maxFileCount: 1,
+            autoReplace: true
+        }).on('fileuploaded', function (event, data, previewId, index) {
+            $("input[name='" + event.currentTarget.id + "']").val(data.response.url)
+        }).on('fileremoved', function (event, id, index) {
+            $("input[name='" + event.currentTarget.id + "']").val('')
+        })
+#break
+#end
+#end
+#foreach($column in $columns)
+#if($column.edit && !$column.superColumn && !$column.pk && $column.htmlType == "summernote")
+
+        $(function() {
+            $('.summernote').summernote({
+                lang: 'zh-CN',
+                dialogsInBody: true,
+                callbacks: {
+                    onChange: function(contents, $edittable) {
+                        $("input[name='" + this.id + "']").val(contents);
+                    },
+                    onImageUpload: function(files) {
+                        var obj = this;
+                    	var data = new FormData();
+                    	data.append("file", files[0]);
+                    	$.ajax({
+                            type: "post",
+                            url: ctx + "common/upload",
+                    		data: data,
+                    		cache: false,
+                    		contentType: false,
+                    		processData: false,
+                    		dataType: 'json',
+                    		success: function(result) {
+                    		    if (result.code == web_status.SUCCESS) {
+                    		        $('#' + obj.id).summernote('insertImage', result.url);
+                    		    } else {
+                    		        $.modal.alertError(result.msg);
+                    		    }
+                    		},
+                    		error: function(error) {
+                    		    $.modal.alertWarning("图片上传失败。");
+                    		}
+                    	});
+                    }
+                }
+            });
+        });
+#break
+#end
+#end
+#if($table.tree)
+
+        /*${functionName}-新增-选择父${functionName}树*/
+        function select${BusinessName}Tree() {
+            var options = {
+                title: '${functionName}选择',
+                width: "380",
+                url: prefix + "/select${BusinessName}Tree/" + $("#treeId").val(),
+                callBack: doSubmit
+            };
+            $.modal.openOptions(options);
+        }
+
+        function doSubmit(index, layero){
+            var body = $.modal.getChildFrame(index);
+            $("#treeId").val(body.find('#treeId').val());
+            $("#treeName").val(body.find('#treeName').val());
+            $.modal.close(index);
+        }
+#end
+#if($table.sub)
+
+        $(function() {
+            var options = {
+                pagination: false,
+                showSearch: false,
+                showRefresh: false,
+                showToggle: false,
+                showColumns: false,
+                sidePagination: "client",
+                columns: [{
+                    checkbox: true
+                },
+                {
+                    field: 'index',
+                    align: 'center',
+                    title: "序号",
+                    formatter: function (value, row, index) {
+                    	var columnIndex = $.common.sprintf("<input type='hidden' name='index' value='%s'>", $.table.serialNumber(index));
+                    	return columnIndex + $.table.serialNumber(index);
+                    }
+                },
+#foreach($column in $subTable.columns)
+#set($dictType=$column.dictType)
+#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 && "" != $dictType)
+                {
+                    field: '${javaField}',
+                    align: 'center',
+                    title: '${comment}',
+                    formatter: function(value, row, index) {
+                        var name = $.common.sprintf("${subclassName}List[%s].${javaField}", index);
+                        return $.common.dictToSelect(${javaField}Datas, value, name);
+                    }
+                },
+#else
+                {
+                    field: '${javaField}',
+                    align: 'center',
+                    title: '${comment}',
+                    formatter: function(value, row, index) {
+                        var html = $.common.sprintf("<input class='form-control' type='text' name='${subclassName}List[%s].${javaField}' value='%s'>", index, value);
+                        return html;
+                    }
+                },
+#end
+#end
+                {
+                    title: '操作',
+                    align: 'center',
+                    formatter: function(value, row, index) {
+                        var value = $.common.isNotEmpty(row.index) ? row.index : $.table.serialNumber(index);
+                        return '<a class="btn btn-danger btn-xs" href="javascript:void(0)" onclick="sub.delRowByIndex(\'' + value + '\')"><i class="fa fa-remove"></i>删除</a>';
+                    }
+                }]
+            };
+            $.table.init(options);
+        });
+
+        function addRow() {
+            var count = $("#" + table.options.id).bootstrapTable('getData').length;
+            var row = {
+                index: $.table.serialNumber(count),
+#foreach($column in $subTable.columns)
+#set($javaField=$column.javaField)
+#if($column.pk || $javaField == ${subTableFkclassName})
+#else
+                ${javaField}: "",
+#end
+#end
+            }
+            sub.addRow(row);
+        }
+#end
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-generator/src/main/resources/vm/html/edit.html.vm b/ruoyi-generator/src/main/resources/vm/html/edit.html.vm
new file mode 100644
index 0000000..7498004
--- /dev/null
+++ b/ruoyi-generator/src/main/resources/vm/html/edit.html.vm
@@ -0,0 +1,416 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+    <th:block th:include="include :: header('修改${functionName}')" />
+#foreach($column in $columns)
+#if($column.edit && !$column.superColumn && !$column.pk && $column.htmlType == "datetime")
+    <th:block th:include="include :: datetimepicker-css" />
+#break
+#end
+#end
+#foreach($column in $columns)
+#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "upload")
+    <th:block th:include="include :: bootstrap-fileinput-css"/>
+#break
+#end
+#end
+#foreach($column in $columns)
+#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "summernote")
+    <th:block th:include="include :: summernote-css" />
+#break
+#end
+#end
+</head>
+<body class="white-bg">
+    <div class="wrapper wrapper-content animated fadeInRight ibox-content">
+        <form class="form-horizontal m" id="form-${businessName}-edit" th:object="${${className}}">
+#if($table.sub)
+            <h4 class="form-header h4">${functionName}信息</h4>
+#end
+            <input name="${pkColumn.javaField}" th:field="*{${pkColumn.javaField}}" type="hidden">
+#foreach($column in $columns)
+#if($column.edit && !$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($field=$column.javaField)
+#set($dictType=$column.dictType)
+#if("" != $treeParentCode && $column.javaField == $treeParentCode)
+            <div class="${colXsNum}">
+                <div class="form-group">
+                    <label class="${colSmNum} control-label#if($column.required) is-required#end">${comment}:</label>
+                    <div class="col-sm-8">
+                        <div class="input-group">
+#set($BusinessName=$businessName.substring(0,1).toUpperCase() + ${businessName.substring(1)})
+                            <input id="treeId" name="${treeParentCode}" type="hidden" th:field="*{${treeParentCode}}" />
+                            <input class="form-control" type="text" onclick="select${BusinessName}Tree()" id="treeName" readonly="true" th:field="*{parentName}"#if($column.required) required#end>
+                            <span class="input-group-addon"><i class="fa fa-search"></i></span>
+                        </div>
+                    </div>
+                </div>
+            </div>
+#elseif($column.htmlType == "input")
+            <div class="${colXsNum}">
+                <div class="form-group">
+                    <label class="${colSmNum} control-label#if($column.required) is-required#end">${comment}:</label>
+                    <div class="col-sm-8">
+                        <input name="${field}" th:field="*{${field}}" class="form-control" type="text"#if($column.required) required#end>
+                    </div>
+                </div>
+            </div>
+#elseif($column.htmlType == "upload")
+            <div class="${colXsNum}">
+                <div class="form-group">
+                    <label class="${colSmNum} control-label#if($column.required) is-required#end">${comment}:</label>
+                    <div class="col-sm-8">
+                        <input type="hidden" name="${field}" th:field="*{${field}}">
+                       <div class="file-loading">
+                            <input class="form-control file-upload" id="${field}" name="file" type="file">
+                        </div>
+                    </div>
+                </div>
+            </div>
+#elseif($column.htmlType == "summernote")
+            <div class="${colXsNum}">
+                <div class="form-group">
+                    <label class="${colSmNum} control-label#if($column.required) is-required#end">${comment}:</label>
+                    <div class="col-sm-8">
+                        <input type="hidden" class="form-control" th:field="*{${field}}">
+                        <div class="summernote" id="${field}"></div>
+                    </div>
+                </div>
+            </div>
+#elseif($column.htmlType == "select" && "" != $dictType)
+            <div class="${colXsNum}">
+                <div class="form-group">
+                    <label class="${colSmNum} control-label#if($column.required) is-required#end">${comment}:</label>
+                    <div class="col-sm-8">
+                        <select name="${field}" class="form-control" th:with="type=${@dict.getType('${dictType}')}"#if($column.required) required#end>
+                            <option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}" th:field="*{${field}}"></option>
+                        </select>
+                    </div>
+                </div>
+            </div>
+#elseif($column.htmlType == "select" && $dictType)
+            <div class="${colXsNum}">
+                <div class="form-group">
+                    <label class="${colSmNum} control-label#if($column.required) is-required#end">${comment}:</label>
+                        <div class="col-sm-8">
+                            <select name="${field}" class="form-control"#if($column.required) required#end>
+                                <option value="">所有</option>
+                            </select>
+                            <span class="help-block m-b-none"><i class="fa fa-info-circle"></i> 代码生成请选择字典属性</span>
+                        </div>
+                    </div>
+                </div>
+            </div>
+#elseif($column.htmlType == "checkbox" && "" != $dictType)
+            <div class="${colXsNum}">
+                <div class="form-group">
+                    <label class="${colSmNum} control-label#if($column.required) is-required#end">${comment}:</label>
+                    <div class="col-sm-8" th:with="type=${@dict.getType('${dictType}')}">
+                        <label th:each="dict : ${type}" class="check-box">
+                            <input name="${field}" type="checkbox" th:value="${dict.dictValue}" th:text="${dict.dictLabel}" th:attr="checked=${${className}.${field}.contains(dict.dictValue)?true:false}"#if($column.required) required#end>
+                        </label>
+                    </div>
+                </div>
+            </div>
+#elseif($column.htmlType == "checkbox" && $dictType)
+            <div class="${colXsNum}">
+                <div class="form-group">
+                    <label class="${colSmNum} control-label#if($column.required) is-required#end">${comment}:</label>
+                    <div class="col-sm-8">
+                        <label class="check-box">
+                            <input name="${field}" type="checkbox"#if($column.required) required#end> 无
+                        </label>
+                        <span class="help-block m-b-none"><i class="fa fa-info-circle"></i> 代码生成请选择字典属性</span>
+                    </div>
+                </div>
+            </div>
+#elseif($column.htmlType == "radio" && "" != $dictType)
+            <div class="${colXsNum}">
+                <div class="form-group">
+                    <label class="${colSmNum} control-label#if($column.required) is-required#end">${comment}:</label>
+                    <div class="col-sm-8">
+                        <div class="radio-box" th:each="dict : ${@dict.getType('${dictType}')}">
+                            <input type="radio" th:id="${'${field}_' + dict.dictCode}" name="${field}" th:value="${dict.dictValue}" th:field="*{${field}}"#if($column.required) required#end>
+                            <label th:for="${'${field}_' + dict.dictCode}" th:text="${dict.dictLabel}"></label>
+                        </div>
+                    </div>
+                </div>
+            </div>
+#elseif($column.htmlType == "radio" && $dictType)
+            <div class="${colXsNum}">
+                <div class="form-group">
+                    <label class="${colSmNum} control-label#if($column.required) is-required#end">${comment}:</label>
+                    <div class="col-sm-8">
+                        <div class="radio-box">
+                            <input type="radio" name="${field}" value=""#if($column.required) required#end>
+                            <label th:for="${field}" th:text="未知"></label>
+                        </div>
+                        <span class="help-block m-b-none"><i class="fa fa-info-circle"></i> 代码生成请选择字典属性</span>
+                    </div>
+                </div>
+            </div>
+#elseif($column.htmlType == "datetime")
+            <div class="${colXsNum}">
+                <div class="form-group">
+                    <label class="${colSmNum} control-label#if($column.required) is-required#end">${comment}:</label>
+                    <div class="col-sm-8">
+                        <div class="input-group date">
+                            <input name="${field}" th:value="${#dates.format(${className}.${field}, 'yyyy-MM-dd')}" class="form-control" placeholder="yyyy-MM-dd" type="text"#if($column.required) required#end>
+                            <span class="input-group-addon"><i class="fa fa-calendar"></i></span>
+                        </div>
+                    </div>
+                </div>
+            </div>
+#elseif($column.htmlType == "textarea")
+            <div class="${colXsNum}">
+                <div class="form-group">
+                    <label class="${colSmNum} control-label#if($column.required) is-required#end">${comment}:</label>
+                    <div class="col-sm-8">
+                        <textarea name="${field}" class="form-control"#if($column.required) required#end>[[*{${field}}]]</textarea>
+                    </div>
+                </div>
+            </div>
+#end
+#end
+#end
+#end
+#if($table.sub)
+            <h4 class="form-header h4">${subTable.functionName}信息</h4>
+            <div class="row">
+                <div class="col-sm-12">
+                    <button type="button" class="btn btn-white btn-sm" onclick="addRow()"><i class="fa fa-plus"> 增加</i></button>
+                    <button type="button" class="btn btn-white btn-sm" onclick="sub.delRow()"><i class="fa fa-minus"> 删除</i></button>
+                    <div class="col-sm-12 select-table table-striped">
+                        <table id="bootstrap-table"></table>
+                    </div>
+                </div>
+            </div>
+#end
+        </form>
+    </div>
+    <th:block th:include="include :: footer" />
+#foreach($column in $columns)
+#if($column.edit && !$column.superColumn && !$column.pk && $column.htmlType == "datetime")
+    <th:block th:include="include :: datetimepicker-js" />
+#break
+#end
+#end
+#foreach($column in $columns)
+#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "upload")
+    <th:block th:include="include :: bootstrap-fileinput-js"/>
+#break
+#end
+#end
+#foreach($column in $columns)
+#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "summernote")
+    <th:block th:include="include :: summernote-js" />
+#break
+#end
+#end
+    <script th:inline="javascript">
+        var prefix = ctx + "${moduleName}/${businessName}";
+#if($table.sub)
+#foreach($column in $subTable.columns)
+#if(${column.dictType} != '')
+        var ${column.javaField}Datas = [[${@dict.getType('${column.dictType}')}]];
+#end
+#end
+#end
+        $("#form-${businessName}-edit").validate({
+            focusCleanup: true
+        });
+
+        function submitHandler() {
+            if ($.validate.form()) {
+                $.operate.save(prefix + "/edit", $('#form-${businessName}-edit').serialize());
+            }
+        }
+#foreach($column in $columns)
+#if($column.edit && !$column.superColumn && !$column.pk && $column.htmlType == "datetime")
+
+        $("input[name='$column.javaField']").datetimepicker({
+            format: "yyyy-mm-dd",
+            minView: "month",
+            autoclose: true
+        });
+#end
+#end
+#foreach($column in $columns)
+#if($column.edit && !$column.superColumn && !$column.pk && $column.htmlType == "upload")
+
+        $(".file-upload").each(function (i) {
+            var val = $("input[name='" + this.id + "']").val()
+            $(this).fileinput({
+                'uploadUrl': ctx + 'common/upload',
+                initialPreviewAsData: true,
+                initialPreview: [val],
+                maxFileCount: 1,
+                autoReplace: true
+            }).on('fileuploaded', function (event, data, previewId, index) {
+                $("input[name='" + event.currentTarget.id + "']").val(data.response.url)
+            }).on('fileremoved', function (event, id, index) {
+                $("input[name='" + event.currentTarget.id + "']").val('')
+            })
+            $(this).fileinput('_initFileActions');
+        });
+#break
+#end
+#end
+#foreach($column in $columns)
+#if($column.edit && !$column.superColumn && !$column.pk && $column.htmlType == "summernote")
+
+        $(function() {
+            $('.summernote').each(function(i) {
+                $('#' + this.id).summernote({
+                    lang: 'zh-CN',
+                    dialogsInBody: true,
+                    callbacks: {
+                        onChange: function(contents, $edittable) {
+                            $("input[name='" + this.id + "']").val(contents);
+                        },
+                        onImageUpload: function(files) {
+                            var obj = this;
+                            var data = new FormData();
+                            data.append("file", files[0]);
+                            $.ajax({
+                                type: "post",
+                                url: ctx + "common/upload",
+                                data: data,
+                                cache: false,
+                                contentType: false,
+                                processData: false,
+                                dataType: 'json',
+                                success: function(result) {
+                                    if (result.code == web_status.SUCCESS) {
+                                        $('#' + obj.id).summernote('insertImage', result.url);
+                                    } else {
+                                        $.modal.alertError(result.msg);
+                                    }
+                                },
+                                error: function(error) {
+                                    $.modal.alertWarning("图片上传失败。");
+                                }
+                            });
+                        }
+                    }
+                });
+                var content = $("input[name='" + this.id + "']").val();
+                $('#' + this.id).summernote('code', content);
+            })
+        });
+#break
+#end
+#end
+#if($table.tree)
+
+        /*${functionName}-编辑-选择父${functionName}树*/
+        function select${BusinessName}Tree() {
+            var options = {
+                title: '${functionName}选择',
+                width: "380",
+                url: prefix + "/select${BusinessName}Tree/" + $("#treeId").val(),
+                callBack: doSubmit
+            };
+            $.modal.openOptions(options);
+        }
+
+        function doSubmit(index, layero){
+            var body = $.modal.getChildFrame(index);
+            $("#treeId").val(body.find('#treeId').val());
+            $("#treeName").val(body.find('#treeName').val());
+            $.modal.close(index);
+        }
+#end
+#if($table.sub)
+
+        $(function() {
+            var options = {
+                data: [[${${className}.${subclassName}List}]],
+                pagination: false,
+                showSearch: false,
+                showRefresh: false,
+                showToggle: false,
+                showColumns: false,
+                sidePagination: "client",
+                columns: [{
+                    checkbox: true
+                },
+                {
+                    field: 'index',
+                    align: 'center',
+                    title: "序号",
+                    formatter: function (value, row, index) {
+                    	var columnIndex = $.common.sprintf("<input type='hidden' name='index' value='%s'>", $.table.serialNumber(index));
+                    	return columnIndex + $.table.serialNumber(index);
+                    }
+                },
+#foreach($column in $subTable.columns)
+#set($dictType=$column.dictType)
+#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 && "" != $dictType)
+                {
+                    field: '${javaField}',
+                    align: 'center',
+                    title: '${comment}',
+                    formatter: function(value, row, index) {
+                        var name = $.common.sprintf("${subclassName}List[%s].${javaField}", index);
+                        return $.common.dictToSelect(${javaField}Datas, value, name);
+                    }
+                },
+#else
+                {
+                    field: '${javaField}',
+                    align: 'center',
+                    title: '${comment}',
+                    formatter: function(value, row, index) {
+                        var html = $.common.sprintf("<input class='form-control' type='text' name='${subclassName}List[%s].${javaField}' value='%s'>", index, value);
+                        return html;
+                    }
+                },
+
+#end
+#end
+                {
+                    title: '操作',
+                    align: 'center',
+                    formatter: function(value, row, index) {
+                        var value = $.common.isNotEmpty(row.index) ? row.index : $.table.serialNumber(index);
+                        return '<a class="btn btn-danger btn-xs" href="javascript:void(0)" onclick="sub.delRowByIndex(\'' + value + '\')"><i class="fa fa-remove"></i>删除</a>';
+                    }
+                }]
+            };
+            $.table.init(options);
+        });
+
+        function addRow() {
+            var count = $("#" + table.options.id).bootstrapTable('getData').length;
+            var row = {
+                index: $.table.serialNumber(count),
+#foreach($column in $subTable.columns)
+#set($javaField=$column.javaField)
+#if($column.pk || $javaField == ${subTableFkclassName})
+#else
+                ${javaField}: "",
+#end
+#end
+            }
+            sub.addRow(row);
+        }
+#end
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-generator/src/main/resources/vm/html/list-tree.html.vm b/ruoyi-generator/src/main/resources/vm/html/list-tree.html.vm
new file mode 100644
index 0000000..9e3734e
--- /dev/null
+++ b/ruoyi-generator/src/main/resources/vm/html/list-tree.html.vm
@@ -0,0 +1,155 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+    <th:block th:include="include :: header('${functionName}列表')" />
+</head>
+<body class="gray-bg">
+     <div class="container-div">
+        <div class="row">
+            <div class="col-sm-12 search-collapse">
+                <form id="formId">
+                    <div class="select-list">
+                        <ul>
+#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")
+                            <li>
+                                <label>${comment}:</label>
+                                <input type="text" name="${column.javaField}"/>
+                            </li>
+#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && "" != $dictType)
+                            <li>
+                                <label>${comment}:</label>
+                                <select name="${column.javaField}" th:with="type=${@dict.getType('${dictType}')}">
+                                    <option value="">所有</option>
+                                    <option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
+                                </select>
+                            </li>
+#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && $dictType)
+                            <li>
+                                <label>${comment}:</label>
+                                <select name="${column.javaField}">
+                                    <option value="">所有</option>
+                                    <option value="-1">代码生成请选择字典属性</option>
+                                </select>
+                            </li>
+#elseif($column.htmlType == "datetime" && $column.queryType != "BETWEEN")
+                            <li>
+                                <label>${comment}:</label>
+                                <input type="text" class="time-input" placeholder="请选择${comment}" name="${column.javaField}"/>
+                            </li>
+#elseif($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+                            <li class="select-time">
+                                <label>${comment}:</label>
+                                <input type="text" class="time-input" id="startTime" placeholder="开始时间" name="params[begin${AttrName}]"/>
+                                <span>-</span>
+                                <input type="text" class="time-input" id="endTime" placeholder="结束时间" name="params[end${AttrName}]"/>
+                            </li>                
+#end
+#end
+#end
+                            <li>
+                                <a class="btn btn-primary btn-rounded btn-sm" onclick="$.treeTable.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
+                                <a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
+                            </li>
+                        </ul>
+                    </div>
+                </form>
+            </div>
+
+            <div class="btn-group-sm" id="toolbar" role="group">
+                <a class="btn btn-success" onclick="$.operate.add()" shiro:hasPermission="${permissionPrefix}:add">
+                    <i class="fa fa-plus"></i> 新增
+                </a>
+                <a class="btn btn-primary" onclick="$.operate.edit()" shiro:hasPermission="${permissionPrefix}:edit">
+                    <i class="fa fa-edit"></i> 修改
+                </a>
+                <a class="btn btn-info" id="expandAllBtn">
+                    <i class="fa fa-exchange"></i> 展开/折叠
+                </a>
+            </div>
+            <div class="col-sm-12 select-table table-striped">
+                <table id="bootstrap-tree-table"></table>
+            </div>
+        </div>
+    </div>
+    <th:block th:include="include :: footer" />
+    <script th:inline="javascript">
+        var addFlag = [[${@permission.hasPermi('${permissionPrefix}:add')}]];
+        var editFlag = [[${@permission.hasPermi('${permissionPrefix}:edit')}]];
+        var removeFlag = [[${@permission.hasPermi('${permissionPrefix}:remove')}]];
+#foreach($column in $columns)
+#if(${column.dictType} != '')
+        var ${column.javaField}Datas = [[${@dict.getType('${column.dictType}')}]];
+#end
+#end
+        var prefix = ctx + "${moduleName}/${businessName}";
+
+        $(function() {
+            var options = {
+                code: "${treeCode}",
+                parentCode: "${treeParentCode}",
+                expandColumn: "${expandColumn}",
+                uniqueId: "${pkColumn.javaField}",
+                url: prefix + "/list",
+                createUrl: prefix + "/add/{id}",
+                updateUrl: prefix + "/edit/{id}",
+                removeUrl: prefix + "/remove/{id}",
+                modalName: "${functionName}",
+                columns: [{
+                    field: 'selectItem',
+                    radio: true
+                },
+#foreach($column in $columns)
+#set($dictType=$column.dictType)
+#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 && "" != $dictType)
+                {
+                    field: '${javaField}',
+                    title: '${comment}',
+                    align: 'left',
+                    formatter: function(value, row, index) {
+                        return $.table.selectDictLabel#if($column.htmlType == "checkbox")s#end(${javaField}Datas, value);
+                    }
+                },
+#elseif($column.list && "" != $javaField)
+                {
+                    field: '${javaField}',
+                    title: '${comment}',
+                    align: 'left'
+                },
+#end                
+#end
+                {
+                    title: '操作',
+                    align: 'center',
+                    align: 'left',
+                    formatter: function(value, row, index) {
+                        var actions = [];
+                        actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.${pkColumn.javaField} + '\')"><i class="fa fa-edit"></i>编辑</a> ');
+                        actions.push('<a class="btn btn-info  btn-xs ' + addFlag + '" href="javascript:void(0)" onclick="$.operate.add(\'' + row.${pkColumn.javaField} + '\')"><i class="fa fa-plus"></i>新增</a> ');
+                        actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.${pkColumn.javaField} + '\')"><i class="fa fa-remove"></i>删除</a>');
+                        return actions.join('');
+                    }
+                }]
+            };
+            $.treeTable.init(options);
+        });
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-generator/src/main/resources/vm/html/list.html.vm b/ruoyi-generator/src/main/resources/vm/html/list.html.vm
new file mode 100644
index 0000000..f2e9c5a
--- /dev/null
+++ b/ruoyi-generator/src/main/resources/vm/html/list.html.vm
@@ -0,0 +1,154 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+    <th:block th:include="include :: header('${functionName}列表')" />
+</head>
+<body class="gray-bg">
+     <div class="container-div">
+        <div class="row">
+            <div class="col-sm-12 search-collapse">
+                <form id="formId">
+                    <div class="select-list">
+                        <ul>
+#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")
+                            <li>
+                                <label>${comment}:</label>
+                                <input type="text" name="${column.javaField}"/>
+                            </li>
+#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && "" != $dictType)
+                            <li>
+                                <label>${comment}:</label>
+                                <select name="${column.javaField}" th:with="type=${@dict.getType('${dictType}')}">
+                                    <option value="">所有</option>
+                                    <option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
+                                </select>
+                            </li>
+#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && $dictType)
+                            <li>
+                                <label>${comment}:</label>
+                                <select name="${column.javaField}">
+                                    <option value="">所有</option>
+                                    <option value="-1">代码生成请选择字典属性</option>
+                                </select>
+                            </li>
+#elseif($column.htmlType == "datetime" && $column.queryType != "BETWEEN")
+                            <li>
+                                <label>${comment}:</label>
+                                <input type="text" class="time-input" placeholder="请选择${comment}" name="${column.javaField}"/>
+                            </li>
+#elseif($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+                            <li class="select-time">
+                                <label>${comment}:</label>
+                                <input type="text" class="time-input" id="startTime" placeholder="开始时间" name="params[begin${AttrName}]"/>
+                                <span>-</span>
+                                <input type="text" class="time-input" id="endTime" placeholder="结束时间" name="params[end${AttrName}]"/>
+                            </li>
+#end
+#end
+#end
+                            <li>
+                                <a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
+                                <a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
+                            </li>
+                        </ul>
+                    </div>
+                </form>
+            </div>
+
+            <div class="btn-group-sm" id="toolbar" role="group">
+                <a class="btn btn-success" onclick="$.operate.add()" shiro:hasPermission="${permissionPrefix}:add">
+                    <i class="fa fa-plus"></i> 添加
+                </a>
+                <a class="btn btn-primary single disabled" onclick="$.operate.edit()" shiro:hasPermission="${permissionPrefix}:edit">
+                    <i class="fa fa-edit"></i> 修改
+                </a>
+                <a class="btn btn-danger multiple disabled" onclick="$.operate.removeAll()" shiro:hasPermission="${permissionPrefix}:remove">
+                    <i class="fa fa-remove"></i> 删除
+                </a>
+                <a class="btn btn-warning" onclick="$.table.exportExcel()" shiro:hasPermission="${permissionPrefix}:export">
+                    <i class="fa fa-download"></i> 导出
+                </a>
+            </div>
+            <div class="col-sm-12 select-table table-striped">
+                <table id="bootstrap-table"></table>
+            </div>
+        </div>
+    </div>
+    <th:block th:include="include :: footer" />
+    <script th:inline="javascript">
+        var editFlag = [[${@permission.hasPermi('${permissionPrefix}:edit')}]];
+        var removeFlag = [[${@permission.hasPermi('${permissionPrefix}:remove')}]];
+#foreach($column in $columns)
+#if(${column.dictType} != '')
+        var ${column.javaField}Datas = [[${@dict.getType('${column.dictType}')}]];
+#end
+#end
+        var prefix = ctx + "${moduleName}/${businessName}";
+
+        $(function() {
+            var options = {
+                url: prefix + "/list",
+                createUrl: prefix + "/add",
+                updateUrl: prefix + "/edit/{id}",
+                removeUrl: prefix + "/remove",
+                exportUrl: prefix + "/export",
+                modalName: "${functionName}",
+                columns: [{
+                    checkbox: true
+                },
+#foreach($column in $columns)
+#set($dictType=$column.dictType)
+#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)
+                {
+                    field: '${javaField}',
+                    title: '${comment}',
+                    visible: false
+                },
+#elseif($column.list && "" != $dictType)
+                {
+                    field: '${javaField}',
+                    title: '${comment}',
+                    formatter: function(value, row, index) {
+                       return $.table.selectDictLabel#if($column.htmlType == "checkbox")s#end(${javaField}Datas, value);
+                    }
+                },
+#elseif($column.list && "" != $javaField)
+                {
+                    field: '${javaField}',
+                    title: '${comment}'
+                },
+#end                
+#end
+                {
+                    title: '操作',
+                    align: 'center',
+                    formatter: function(value, row, index) {
+                        var actions = [];
+                        actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.${pkColumn.javaField} + '\')"><i class="fa fa-edit"></i>编辑</a> ');
+                        actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.${pkColumn.javaField} + '\')"><i class="fa fa-remove"></i>删除</a>');
+                        return actions.join('');
+                    }
+                }]
+            };
+            $.table.init(options);
+        });
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-generator/src/main/resources/vm/html/tree.html.vm b/ruoyi-generator/src/main/resources/vm/html/tree.html.vm
new file mode 100644
index 0000000..8f4660e
--- /dev/null
+++ b/ruoyi-generator/src/main/resources/vm/html/tree.html.vm
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+    <th:block th:include="include :: header('${functionName}树选择')" />
+    <th:block th:include="include :: ztree-css" />
+</head>
+<style>
+    body{height:auto;font-family: "Microsoft YaHei";}
+    button{font-family: "SimSun","Helvetica Neue",Helvetica,Arial;}
+</style>
+<body class="hold-transition box box-main">
+#set($treeId = "${className}?." + $treeCode)
+#set($treeName = "${className}?." + $treeName)
+    <input id="treeId"   name="treeId"    type="hidden" th:value="${${treeId}}"/>
+    <input id="treeName" name="treeName"  type="hidden" th:value="${${treeName}}"/>
+    <div class="wrapper"><div class="treeShowHideButton" onclick="$.tree.toggleSearch();">
+        <label id="btnShow" title="显示搜索" style="display:none;">︾</label>
+        <label id="btnHide" title="隐藏搜索">︽</label>
+    </div>
+    <div class="treeSearchInput" id="search">
+        <label for="keyword">关键字:</label><input type="text" class="empty" id="keyword" maxlength="50">
+        <button class="btn" id="btn" onclick="$.tree.searchNode()"> 搜索 </button>
+    </div>
+    <div class="treeExpandCollapse">
+        <a href="javascript:;" onclick="$.tree.expand()">展开</a> /
+        <a href="javascript:;" onclick="$.tree.collapse()">折叠</a>
+    </div>
+    <div id="tree" class="ztree treeselect"></div>
+    </div>
+    <th:block th:include="include :: footer" />
+    <th:block th:include="include :: ztree-js" />
+    <script th:inline="javascript">
+        $(function() {
+            var url = ctx + "${moduleName}/${businessName}/treeData";
+            var options = {
+                url: url,
+                expandLevel: 2,
+                onClick : zOnClick
+            };
+            $.tree.init(options);
+        });
+
+        function zOnClick(event, treeId, treeNode) {
+            var treeId = treeNode.id;
+            var treeName = treeNode.name;
+            $("#treeId").val(treeId);
+            $("#treeName").val(treeName);
+        }
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-generator/src/main/resources/vm/java/controller.java.vm b/ruoyi-generator/src/main/resources/vm/java/controller.java.vm
new file mode 100644
index 0000000..7fdd56c
--- /dev/null
+++ b/ruoyi-generator/src/main/resources/vm/java/controller.java.vm
@@ -0,0 +1,203 @@
+package ${packageName}.controller;
+
+import java.util.List;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+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.ResponseBody;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.enums.BusinessType;
+import ${packageName}.domain.${ClassName};
+import ${packageName}.service.I${ClassName}Service;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+#if($table.crud || $table.sub)
+import com.ruoyi.common.core.page.TableDataInfo;
+#elseif($table.tree)
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.core.domain.Ztree;
+#end
+
+/**
+ * ${functionName}Controller
+ * 
+ * @author ${author}
+ * @date ${datetime}
+ */
+@Controller
+@RequestMapping("/${moduleName}/${businessName}")
+public class ${ClassName}Controller extends BaseController
+{
+    private String prefix = "${moduleName}/${businessName}";
+
+    @Autowired
+    private I${ClassName}Service ${className}Service;
+
+    @RequiresPermissions("${permissionPrefix}:view")
+    @GetMapping()
+    public String ${businessName}()
+    {
+        return prefix + "/${businessName}";
+    }
+
+#if($table.crud || $table.sub)
+    /**
+     * 查询${functionName}列表
+     */
+    @RequiresPermissions("${permissionPrefix}:list")
+    @PostMapping("/list")
+    @ResponseBody
+    public TableDataInfo list(${ClassName} ${className})
+    {
+        startPage();
+        List<${ClassName}> list = ${className}Service.select${ClassName}List(${className});
+        return getDataTable(list);
+    }
+#elseif($table.tree)
+    /**
+     * 查询${functionName}树列表
+     */
+    @RequiresPermissions("${permissionPrefix}:list")
+    @PostMapping("/list")
+    @ResponseBody
+    public List<${ClassName}> list(${ClassName} ${className})
+    {
+        List<${ClassName}> list = ${className}Service.select${ClassName}List(${className});
+        return list;
+    }
+#end
+
+    /**
+     * 导出${functionName}列表
+     */
+    @RequiresPermissions("${permissionPrefix}:export")
+    @Log(title = "${functionName}", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    @ResponseBody
+    public AjaxResult export(${ClassName} ${className})
+    {
+        List<${ClassName}> list = ${className}Service.select${ClassName}List(${className});
+        ExcelUtil<${ClassName}> util = new ExcelUtil<${ClassName}>(${ClassName}.class);
+        return util.exportExcel(list, "${functionName}数据");
+    }
+
+#if($table.crud || $table.sub)
+    /**
+     * 新增${functionName}
+     */
+    @RequiresPermissions("${permissionPrefix}:add")
+    @GetMapping("/add")
+    public String add()
+    {
+        return prefix + "/add";
+    }
+#elseif($table.tree)
+    /**
+     * 新增${functionName}
+     */
+    @GetMapping(value = { "/add/{${pkColumn.javaField}}", "/add/" })
+    public String add(@PathVariable(value = "${pkColumn.javaField}", required = false) Long ${pkColumn.javaField}, ModelMap mmap)
+    {
+        if (StringUtils.isNotNull(${pkColumn.javaField}))
+        {
+            mmap.put("${className}", ${className}Service.select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaField}));
+        }
+        return prefix + "/add";
+    }
+#end
+
+    /**
+     * 新增保存${functionName}
+     */
+    @RequiresPermissions("${permissionPrefix}:add")
+    @Log(title = "${functionName}", businessType = BusinessType.INSERT)
+    @PostMapping("/add")
+    @ResponseBody
+    public AjaxResult addSave(${ClassName} ${className})
+    {
+        return toAjax(${className}Service.insert${ClassName}(${className}));
+    }
+
+    /**
+     * 修改${functionName}
+     */
+    @RequiresPermissions("${permissionPrefix}:edit")
+    @GetMapping("/edit/{${pkColumn.javaField}}")
+    public String edit(@PathVariable("${pkColumn.javaField}") ${pkColumn.javaType} ${pkColumn.javaField}, ModelMap mmap)
+    {
+        ${ClassName} ${className} = ${className}Service.select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaField});
+        mmap.put("${className}", ${className});
+        return prefix + "/edit";
+    }
+
+    /**
+     * 修改保存${functionName}
+     */
+    @RequiresPermissions("${permissionPrefix}:edit")
+    @Log(title = "${functionName}", businessType = BusinessType.UPDATE)
+    @PostMapping("/edit")
+    @ResponseBody
+    public AjaxResult editSave(${ClassName} ${className})
+    {
+        return toAjax(${className}Service.update${ClassName}(${className}));
+    }
+
+#if($table.crud || $table.sub)
+    /**
+     * 删除${functionName}
+     */
+    @RequiresPermissions("${permissionPrefix}:remove")
+    @Log(title = "${functionName}", businessType = BusinessType.DELETE)
+    @PostMapping( "/remove")
+    @ResponseBody
+    public AjaxResult remove(String ids)
+    {
+        return toAjax(${className}Service.delete${ClassName}By${pkColumn.capJavaField}s(ids));
+    }
+#elseif($table.tree)
+    /**
+     * 删除
+     */
+    @RequiresPermissions("${permissionPrefix}:remove")
+    @Log(title = "${functionName}", businessType = BusinessType.DELETE)
+    @GetMapping("/remove/{${pkColumn.javaField}}")
+    @ResponseBody
+    public AjaxResult remove(@PathVariable("${pkColumn.javaField}") ${pkColumn.javaType} ${pkColumn.javaField})
+    {
+        return toAjax(${className}Service.delete${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaField}));
+    }
+#end
+#if($table.tree)
+
+    /**
+     * 选择${functionName}树
+     */
+#set($BusinessName=$businessName.substring(0,1).toUpperCase() + ${businessName.substring(1)})
+    @GetMapping(value = { "/select${BusinessName}Tree/{${pkColumn.javaField}}", "/select${BusinessName}Tree/" })
+    public String select${BusinessName}Tree(@PathVariable(value = "${pkColumn.javaField}", required = false) Long ${pkColumn.javaField}, ModelMap mmap)
+    {
+        if (StringUtils.isNotNull(${pkColumn.javaField}))
+        {
+            mmap.put("${className}", ${className}Service.select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaField}));
+        }
+        return prefix + "/tree";
+    }
+
+    /**
+     * 加载${functionName}树列表
+     */
+    @GetMapping("/treeData")
+    @ResponseBody
+    public List<Ztree> treeData()
+    {
+        List<Ztree> ztrees = ${className}Service.select${ClassName}Tree();
+        return ztrees;
+    }
+#end
+}
diff --git a/ruoyi-generator/src/main/resources/vm/java/domain.java.vm b/ruoyi-generator/src/main/resources/vm/java/domain.java.vm
new file mode 100644
index 0000000..0bf2c1f
--- /dev/null
+++ b/ruoyi-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.ruoyi.common.annotation.Excel;
+#if($table.crud || $table.sub)
+import com.ruoyi.common.core.domain.BaseEntity;
+#elseif($table.tree)
+import com.ruoyi.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", timezone = "GMT+8")
+    @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/ruoyi-generator/src/main/resources/vm/java/mapper.java.vm b/ruoyi-generator/src/main/resources/vm/java/mapper.java.vm
new file mode 100644
index 0000000..ebee538
--- /dev/null
+++ b/ruoyi-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(String[] ${pkColumn.javaField}s);
+#if($table.sub)
+
+    /**
+     * 批量删除${subTable.functionName}
+     * 
+     * @param ${pkColumn.javaField}s 需要删除的数据主键集合
+     * @return 结果
+     */
+    public int delete${subClassName}By${subTableFkClassName}s(String[] ${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/ruoyi-generator/src/main/resources/vm/java/service.java.vm b/ruoyi-generator/src/main/resources/vm/java/service.java.vm
new file mode 100644
index 0000000..765c9d6
--- /dev/null
+++ b/ruoyi-generator/src/main/resources/vm/java/service.java.vm
@@ -0,0 +1,73 @@
+package ${packageName}.service;
+
+import java.util.List;
+import ${packageName}.domain.${ClassName};
+#if($table.tree)
+import com.ruoyi.common.core.domain.Ztree;
+#end
+
+/**
+ * ${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(String ${pkColumn.javaField}s);
+
+    /**
+     * 删除${functionName}信息
+     * 
+     * @param ${pkColumn.javaField} ${functionName}主键
+     * @return 结果
+     */
+    public int delete${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField});
+#if($table.tree)
+
+    /**
+     * 查询${functionName}树列表
+     * 
+     * @return 所有${functionName}信息
+     */
+    public List<Ztree> select${ClassName}Tree();
+#end
+}
diff --git a/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm b/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm
new file mode 100644
index 0000000..242b1c7
--- /dev/null
+++ b/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm
@@ -0,0 +1,213 @@
+package ${packageName}.service.impl;
+
+import java.util.List;
+#if($table.tree)
+import java.util.ArrayList;
+import com.ruoyi.common.core.domain.Ztree;
+#end
+#foreach ($column in $columns)
+#if($column.javaField == 'createTime' || $column.javaField == 'updateTime')
+import com.ruoyi.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.ruoyi.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;
+import com.ruoyi.common.core.text.Convert;
+
+/**
+ * ${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(String ${pkColumn.javaField}s)
+    {
+#if($table.sub)
+        ${className}Mapper.delete${subClassName}By${subTableFkClassName}s(Convert.toStrArray(${pkColumn.javaField}s));
+#end
+        return ${className}Mapper.delete${ClassName}By${pkColumn.capJavaField}s(Convert.toStrArray(${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.tree)
+
+    /**
+     * 查询${functionName}树列表
+     * 
+     * @return 所有${functionName}信息
+     */
+    @Override
+    public List<Ztree> select${ClassName}Tree()
+    {
+        List<${ClassName}> ${className}List = ${className}Mapper.select${ClassName}List(new ${ClassName}());
+        List<Ztree> ztrees = new ArrayList<Ztree>();
+        for (${ClassName} ${className} : ${className}List)
+        {
+            Ztree ztree = new Ztree();
+#if($treeCode.length() > 2 && $treeCode.substring(1,2).matches("[A-Z]"))
+#set($TreeCode=$treeCode)
+#else
+#set($TreeCode=$treeCode.substring(0,1).toUpperCase() + ${treeCode.substring(1)})
+#end
+#if($treeParentCode.length() > 2 && $treeParentCode.substring(1,2).matches("[A-Z]"))
+#set($TreeParentCode=$treeParentCode)
+#else
+#set($TreeParentCode=$treeParentCode.substring(0,1).toUpperCase() + ${treeParentCode.substring(1)})
+#end
+#if($treeName.length() > 2 && $treeName.substring(1,2).matches("[A-Z]"))
+#set($TreeName=$treeName)
+#else
+#set($TreeName=$treeName.substring(0,1).toUpperCase() + ${treeName.substring(1)})
+#end
+            ztree.setId(${className}.get${TreeCode}());
+            ztree.setpId(${className}.get${TreeParentCode}());
+            ztree.setName(${className}.get${TreeName}());
+            ztree.setTitle(${className}.get${TreeName}());
+            ztrees.add(ztree);
+        }
+        return ztrees;
+    }
+#end
+#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/ruoyi-generator/src/main/resources/vm/java/sub-domain.java.vm b/ruoyi-generator/src/main/resources/vm/java/sub-domain.java.vm
new file mode 100644
index 0000000..6591154
--- /dev/null
+++ b/ruoyi-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.ruoyi.common.annotation.Excel;
+import com.ruoyi.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", timezone = "GMT+8")
+    @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/ruoyi-generator/src/main/resources/vm/sql/sql.vm b/ruoyi-generator/src/main/resources/vm/sql/sql.vm
new file mode 100644
index 0000000..d5121af
--- /dev/null
+++ b/ruoyi-generator/src/main/resources/vm/sql/sql.vm
@@ -0,0 +1,22 @@
+-- 菜单 SQL
+insert into sys_menu (menu_name, parent_id, order_num, url, menu_type, visible, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('${functionName}', '${parentMenuId}', '1', '/${moduleName}/${businessName}', 'C', '0', '${permissionPrefix}:view', '#', 'admin', sysdate(), '', null, '${functionName}菜单');
+
+-- 按钮父菜单ID
+SELECT @parentId := LAST_INSERT_ID();
+
+-- 按钮 SQL
+insert into sys_menu (menu_name, parent_id, order_num, url, menu_type, visible, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('${functionName}查询', @parentId, '1',  '#',  'F', '0', '${permissionPrefix}:list',         '#', 'admin', sysdate(), '', null, '');
+
+insert into sys_menu (menu_name, parent_id, order_num, url, menu_type, visible, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('${functionName}新增', @parentId, '2',  '#',  'F', '0', '${permissionPrefix}:add',          '#', 'admin', sysdate(), '', null, '');
+
+insert into sys_menu (menu_name, parent_id, order_num, url, menu_type, visible, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('${functionName}修改', @parentId, '3',  '#',  'F', '0', '${permissionPrefix}:edit',         '#', 'admin', sysdate(), '', null, '');
+
+insert into sys_menu (menu_name, parent_id, order_num, url, menu_type, visible, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('${functionName}删除', @parentId, '4',  '#',  'F', '0', '${permissionPrefix}:remove',       '#', 'admin', sysdate(), '', null, '');
+
+insert into sys_menu (menu_name, parent_id, order_num, url, menu_type, visible, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('${functionName}导出', @parentId, '5',  '#',  'F', '0', '${permissionPrefix}:export',       '#', 'admin', sysdate(), '', null, '');
diff --git a/ruoyi-generator/src/main/resources/vm/xml/mapper.xml.vm b/ruoyi-generator/src/main/resources/vm/xml/mapper.xml.vm
new file mode 100644
index 0000000..be31a36
--- /dev/null
+++ b/ruoyi-generator/src/main/resources/vm/xml/mapper.xml.vm
@@ -0,0 +1,152 @@
+<?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
+#if($table.tree)
+        <result property="parentName" column="parent_name" />
+#end
+    </resultMap>
+#if($table.sub)
+
+    <resultMap id="${ClassName}${subClassName}Result" type="${ClassName}" extends="${ClassName}Result">
+        <collection property="${subclassName}List" ofType="${subClassName}" column="${pkColumn.columnName}" select="select${subClassName}List" />
+    </resultMap>
+
+    <resultMap type="${subClassName}" id="${subClassName}Result">
+#foreach ($column in $subTable.columns)
+        <result property="${column.javaField}"    column="${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>
+#if($table.tree)
+        order by ${tree_parent_code}
+#end
+    </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)
+        <include refid="select${ClassName}Vo"/>
+        where ${pkColumn.columnName} = #{${pkColumn.javaField}}
+#elseif($table.tree)
+        select#foreach($column in $columns) t.$column.columnName,#end p.${tree_name} as parent_name
+        from ${tableName} t
+        left join ${tableName} p on p.${pkColumn.columnName} = t.${tree_parent_code}
+        where t.${pkColumn.columnName} = #{${pkColumn.javaField}}
+#elseif($table.sub)
+        select#foreach($column in $columns) $column.columnName#if($foreach.count != $columns.size()),#end#end
+        from ${tableName}
+        where ${pkColumn.columnName} = #{${pkColumn.javaField}}
+#end
+    </select>
+#if($table.sub)
+
+    <select id="select${subClassName}List" resultMap="${subClassName}Result">
+        select#foreach ($column in $subTable.columns) $column.columnName#if($foreach.count != $subTable.columns.size()),#end#end
+        from ${subTableName}
+        where ${subTableFkName} = #{${subTableFkName}}
+    </select>
+#end
+
+    <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/ruoyi-quartz/pom.xml b/ruoyi-quartz/pom.xml
new file mode 100644
index 0000000..ed4fe1d
--- /dev/null
+++ b/ruoyi-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>ruoyi</artifactId>
+        <groupId>com.ruoyi</groupId>
+        <version>4.8.0</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>ruoyi-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.ruoyi</groupId>
+            <artifactId>ruoyi-common</artifactId>
+        </dependency>
+
+    </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/config/ScheduleConfig.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/config/ScheduleConfig.java
new file mode 100644
index 0000000..844a630
--- /dev/null
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/config/ScheduleConfig.java
@@ -0,0 +1,57 @@
+//package com.ruoyi.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 ruoyi
+// */
+//@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
+//        // 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了
+//        factory.setOverwriteExistingJobs(true);
+//        // 设置自动启动,默认为true
+//        factory.setAutoStartup(true);
+//
+//        return factory;
+//    }
+//}
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobController.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobController.java
new file mode 100644
index 0000000..b9943e1
--- /dev/null
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobController.java
@@ -0,0 +1,248 @@
+package com.ruoyi.quartz.controller;
+
+import java.util.List;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.quartz.SchedulerException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+import org.springframework.validation.annotation.Validated;
+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.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.exception.job.TaskException;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.quartz.domain.SysJob;
+import com.ruoyi.quartz.service.ISysJobService;
+import com.ruoyi.quartz.util.CronUtils;
+import com.ruoyi.quartz.util.ScheduleUtils;
+
+/**
+ * 调度任务信息操作处理
+ * 
+ * @author ruoyi
+ */
+@Controller
+@RequestMapping("/monitor/job")
+public class SysJobController extends BaseController
+{
+    private String prefix = "monitor/job";
+
+    @Autowired
+    private ISysJobService jobService;
+
+    @RequiresPermissions("monitor:job:view")
+    @GetMapping()
+    public String job()
+    {
+        return prefix + "/job";
+    }
+
+    @RequiresPermissions("monitor:job:list")
+    @PostMapping("/list")
+    @ResponseBody
+    public TableDataInfo list(SysJob job)
+    {
+        startPage();
+        List<SysJob> list = jobService.selectJobList(job);
+        return getDataTable(list);
+    }
+
+    @Log(title = "定时任务", businessType = BusinessType.EXPORT)
+    @RequiresPermissions("monitor:job:export")
+    @PostMapping("/export")
+    @ResponseBody
+    public AjaxResult export(SysJob job)
+    {
+        List<SysJob> list = jobService.selectJobList(job);
+        ExcelUtil<SysJob> util = new ExcelUtil<SysJob>(SysJob.class);
+        return util.exportExcel(list, "定时任务");
+    }
+
+    @Log(title = "定时任务", businessType = BusinessType.DELETE)
+    @RequiresPermissions("monitor:job:remove")
+    @PostMapping("/remove")
+    @ResponseBody
+    public AjaxResult remove(String ids) throws SchedulerException
+    {
+        jobService.deleteJobByIds(ids);
+        return success();
+    }
+
+    @RequiresPermissions("monitor:job:detail")
+    @GetMapping("/detail/{jobId}")
+    public String detail(@PathVariable("jobId") Long jobId, ModelMap mmap)
+    {
+        mmap.put("name", "job");
+        mmap.put("job", jobService.selectJobById(jobId));
+        return prefix + "/detail";
+    }
+
+    /**
+     * 任务调度状态修改
+     */
+    @Log(title = "定时任务", businessType = BusinessType.UPDATE)
+    @RequiresPermissions("monitor:job:changeStatus")
+    @PostMapping("/changeStatus")
+    @ResponseBody
+    public AjaxResult changeStatus(SysJob job) throws SchedulerException
+    {
+        SysJob newJob = jobService.selectJobById(job.getJobId());
+        newJob.setStatus(job.getStatus());
+        return toAjax(jobService.changeStatus(newJob));
+    }
+
+    /**
+     * 任务调度立即执行一次
+     */
+    @Log(title = "定时任务", businessType = BusinessType.UPDATE)
+    @RequiresPermissions("monitor:job:changeStatus")
+    @PostMapping("/run")
+    @ResponseBody
+    public AjaxResult run(SysJob job) throws SchedulerException
+    {
+        boolean result = jobService.run(job);
+        return result ? success() : error("任务不存在或已过期!");
+    }
+
+    /**
+     * 新增调度
+     */
+    @RequiresPermissions("monitor:job:add")
+    @GetMapping("/add")
+    public String add()
+    {
+        return prefix + "/add";
+    }
+
+    /**
+     * 新增保存调度
+     */
+    @Log(title = "定时任务", businessType = BusinessType.INSERT)
+    @RequiresPermissions("monitor:job:add")
+    @PostMapping("/add")
+    @ResponseBody
+    public AjaxResult addSave(@Validated SysJob job) throws SchedulerException, TaskException
+    {
+        if (!CronUtils.isValid(job.getCronExpression()))
+        {
+            return error("新增任务'" + job.getJobName() + "'失败,Cron表达式不正确");
+        }
+        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(getLoginName());
+        return toAjax(jobService.insertJob(job));
+    }
+
+    /**
+     * 修改调度
+     */
+    @RequiresPermissions("monitor:job:edit")
+    @GetMapping("/edit/{jobId}")
+    public String edit(@PathVariable("jobId") Long jobId, ModelMap mmap)
+    {
+        mmap.put("job", jobService.selectJobById(jobId));
+        return prefix + "/edit";
+    }
+
+    /**
+     * 修改保存调度
+     */
+    @Log(title = "定时任务", businessType = BusinessType.UPDATE)
+    @RequiresPermissions("monitor:job:edit")
+    @PostMapping("/edit")
+    @ResponseBody
+    public AjaxResult editSave(@Validated SysJob job) throws SchedulerException, TaskException
+    {
+        if (!CronUtils.isValid(job.getCronExpression()))
+        {
+            return error("修改任务'" + job.getJobName() + "'失败,Cron表达式不正确");
+        }
+        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'调用");
+        }
+        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() + "'失败,目标字符串不在白名单内");
+        }
+        return toAjax(jobService.updateJob(job));
+    }
+
+    /**
+     * 校验cron表达式是否有效
+     */
+    @PostMapping("/checkCronExpressionIsValid")
+    @ResponseBody
+    public boolean checkCronExpressionIsValid(SysJob job)
+    {
+        return jobService.checkCronExpressionIsValid(job.getCronExpression());
+    }
+
+    /**
+     * Cron表达式在线生成
+     */
+    @GetMapping("/cron")
+    public String cron()
+    {
+        return prefix + "/cron";
+    }
+
+    /**
+     * 查询cron表达式近5次的执行时间
+     */
+    @GetMapping("/queryCronExpression")
+    @ResponseBody
+    public AjaxResult queryCronExpression(@RequestParam(value = "cronExpression", required = false) String cronExpression)
+    {
+        if (jobService.checkCronExpressionIsValid(cronExpression))
+        {
+            List<String> dateList = CronUtils.getRecentTriggerTime(cronExpression);
+            return success(dateList);
+        }
+        else
+        {
+            return error("表达式无效");
+        }
+    }
+}
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobLogController.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobLogController.java
new file mode 100644
index 0000000..f44533c
--- /dev/null
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobLogController.java
@@ -0,0 +1,103 @@
+package com.ruoyi.quartz.controller;
+
+import java.util.List;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+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.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.quartz.domain.SysJob;
+import com.ruoyi.quartz.domain.SysJobLog;
+import com.ruoyi.quartz.service.ISysJobLogService;
+import com.ruoyi.quartz.service.ISysJobService;
+
+/**
+ * 调度日志操作处理
+ * 
+ * @author ruoyi
+ */
+@Controller
+@RequestMapping("/monitor/jobLog")
+public class SysJobLogController extends BaseController
+{
+    private String prefix = "monitor/job";
+
+    @Autowired
+    private ISysJobService jobService;
+
+    @Autowired
+    private ISysJobLogService jobLogService;
+
+    @RequiresPermissions("monitor:job:view")
+    @GetMapping()
+    public String jobLog(@RequestParam(value = "jobId", required = false) Long jobId, ModelMap mmap)
+    {
+        if (StringUtils.isNotNull(jobId))
+        {
+            SysJob job = jobService.selectJobById(jobId);
+            mmap.put("job", job);
+        }
+        return prefix + "/jobLog";
+    }
+
+    @RequiresPermissions("monitor:job:list")
+    @PostMapping("/list")
+    @ResponseBody
+    public TableDataInfo list(SysJobLog jobLog)
+    {
+        startPage();
+        List<SysJobLog> list = jobLogService.selectJobLogList(jobLog);
+        return getDataTable(list);
+    }
+
+    @Log(title = "调度日志", businessType = BusinessType.EXPORT)
+    @RequiresPermissions("monitor:job:export")
+    @PostMapping("/export")
+    @ResponseBody
+    public AjaxResult export(SysJobLog jobLog)
+    {
+        List<SysJobLog> list = jobLogService.selectJobLogList(jobLog);
+        ExcelUtil<SysJobLog> util = new ExcelUtil<SysJobLog>(SysJobLog.class);
+        return util.exportExcel(list, "调度日志");
+    }
+
+    @Log(title = "调度日志", businessType = BusinessType.DELETE)
+    @RequiresPermissions("monitor:job:remove")
+    @PostMapping("/remove")
+    @ResponseBody
+    public AjaxResult remove(String ids)
+    {
+        return toAjax(jobLogService.deleteJobLogByIds(ids));
+    }
+
+    @RequiresPermissions("monitor:job:detail")
+    @GetMapping("/detail/{jobLogId}")
+    public String detail(@PathVariable("jobLogId") Long jobLogId, ModelMap mmap)
+    {
+        mmap.put("name", "jobLog");
+        mmap.put("jobLog", jobLogService.selectJobLogById(jobLogId));
+        return prefix + "/detail";
+    }
+
+    @Log(title = "调度日志", businessType = BusinessType.CLEAN)
+    @RequiresPermissions("monitor:job:remove")
+    @PostMapping("/clean")
+    @ResponseBody
+    public AjaxResult clean()
+    {
+        jobLogService.cleanJobLog();
+        return success();
+    }
+}
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJob.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJob.java
new file mode 100644
index 0000000..ea63675
--- /dev/null
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJob.java
@@ -0,0 +1,169 @@
+package com.ruoyi.quartz.domain;
+
+import java.io.Serializable;
+import java.util.Date;
+import javax.validation.constraints.*;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.annotation.Excel.ColumnType;
+import com.ruoyi.common.constant.ScheduleConstants;
+import com.ruoyi.common.core.domain.BaseEntity;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.quartz.util.CronUtils;
+
+/**
+ * 定时任务调度表 sys_job
+ * 
+ * @author ruoyi
+ */
+public class SysJob extends BaseEntity implements Serializable
+{
+    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正常 1暂停) */
+    @Excel(name = "任务状态", readConverterExp = "0=正常,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 = 1000, 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;
+    }
+
+    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();
+    }
+}
\ No newline at end of file
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJobLog.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJobLog.java
new file mode 100644
index 0000000..89602bd
--- /dev/null
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJobLog.java
@@ -0,0 +1,155 @@
+package com.ruoyi.quartz.domain;
+
+import java.util.Date;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * 定时任务调度日志表 sys_job_log
+ * 
+ * @author ruoyi
+ */
+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正常 1失败) */
+    @Excel(name = "执行状态", readConverterExp = "0=正常,1=失败")
+    private String status;
+
+    /** 异常信息 */
+    @Excel(name = "异常信息")
+    private String exceptionInfo;
+
+    /** 开始时间 */
+    private Date startTime;
+
+    /** 结束时间 */
+    private Date endTime;
+
+    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 getEndTime()
+    {
+        return endTime;
+    }
+
+    public void setEndTime(Date endTime)
+    {
+        this.endTime = endTime;
+    }
+
+    @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("endTime", getEndTime())
+            .toString();
+    }
+}
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobLogMapper.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobLogMapper.java
new file mode 100644
index 0000000..c2f79e6
--- /dev/null
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobLogMapper.java
@@ -0,0 +1,64 @@
+package com.ruoyi.quartz.mapper;
+
+import com.ruoyi.quartz.domain.SysJobLog;
+import java.util.List;
+
+/**
+ * 调度任务日志信息 数据层
+ * 
+ * @author ruoyi
+ */
+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 ids 需要删除的数据ID
+     * @return 结果
+     */
+    public int deleteJobLogByIds(String[] ids);
+
+    /**
+     * 删除任务日志
+     * 
+     * @param jobId 调度日志ID
+     * @return 结果
+     */
+    public int deleteJobLogById(Long jobId);
+
+    /**
+     * 清空任务日志
+     */
+    public void cleanJobLog();
+}
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobMapper.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobMapper.java
new file mode 100644
index 0000000..5207c7a
--- /dev/null
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobMapper.java
@@ -0,0 +1,67 @@
+package com.ruoyi.quartz.mapper;
+
+import com.ruoyi.quartz.domain.SysJob;
+import java.util.List;
+
+/**
+ * 调度任务信息 数据层
+ * 
+ * @author ruoyi
+ */
+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/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobLogService.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobLogService.java
new file mode 100644
index 0000000..4e112d5
--- /dev/null
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobLogService.java
@@ -0,0 +1,56 @@
+package com.ruoyi.quartz.service;
+
+import java.util.List;
+import com.ruoyi.quartz.domain.SysJobLog;
+
+/**
+ * 定时任务调度日志信息信息 服务层
+ * 
+ * @author ruoyi
+ */
+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 ids 需要删除的数据ID
+     * @return 结果
+     */
+    public int deleteJobLogByIds(String ids);
+
+    /**
+     * 删除任务日志
+     * 
+     * @param jobId 调度日志ID
+     * @return 结果
+     */
+    public int deleteJobLogById(Long jobId);
+    
+    /**
+     * 清空任务日志
+     */
+    public void cleanJobLog();
+}
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobService.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobService.java
new file mode 100644
index 0000000..c503e3a
--- /dev/null
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobService.java
@@ -0,0 +1,102 @@
+package com.ruoyi.quartz.service;
+
+import java.util.List;
+import org.quartz.SchedulerException;
+import com.ruoyi.common.exception.job.TaskException;
+import com.ruoyi.quartz.domain.SysJob;
+
+/**
+ * 定时任务调度信息信息 服务层
+ * 
+ * @author ruoyi
+ */
+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;
+
+    /**
+     * 删除任务后,所对应的trigger也将被删除
+     * 
+     * @param job 调度信息
+     * @return 结果
+     */
+    public int deleteJob(SysJob job) throws SchedulerException;
+
+    /**
+     * 批量删除调度信息
+     * 
+     * @param ids 需要删除的数据ID
+     * @return 结果
+     */
+    public void deleteJobByIds(String ids) 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);
+}
\ No newline at end of file
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobLogServiceImpl.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobLogServiceImpl.java
new file mode 100644
index 0000000..ccd7379
--- /dev/null
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobLogServiceImpl.java
@@ -0,0 +1,88 @@
+package com.ruoyi.quartz.service.impl;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.common.core.text.Convert;
+import com.ruoyi.quartz.domain.SysJobLog;
+import com.ruoyi.quartz.mapper.SysJobLogMapper;
+import com.ruoyi.quartz.service.ISysJobLogService;
+
+/**
+ * 定时任务调度日志信息 服务层
+ * 
+ * @author ruoyi
+ */
+@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 ids 需要删除的数据ID
+     * @return 结果
+     */
+    @Override
+    public int deleteJobLogByIds(String ids)
+    {
+        return jobLogMapper.deleteJobLogByIds(Convert.toStrArray(ids));
+    }
+
+    /**
+     * 删除任务日志
+     * 
+     * @param jobId 调度日志ID
+     */
+    @Override
+    public int deleteJobLogById(Long jobId)
+    {
+        return jobLogMapper.deleteJobLogById(jobId);
+    }
+
+    /**
+     * 清空任务日志
+     */
+    @Override
+    public void cleanJobLog()
+    {
+        jobLogMapper.cleanJobLog();
+    }
+}
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobServiceImpl.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobServiceImpl.java
new file mode 100644
index 0000000..61ce8bd
--- /dev/null
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobServiceImpl.java
@@ -0,0 +1,263 @@
+package com.ruoyi.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.ruoyi.common.constant.ScheduleConstants;
+import com.ruoyi.common.core.text.Convert;
+import com.ruoyi.common.exception.job.TaskException;
+import com.ruoyi.quartz.domain.SysJob;
+import com.ruoyi.quartz.mapper.SysJobMapper;
+import com.ruoyi.quartz.service.ISysJobService;
+import com.ruoyi.quartz.util.CronUtils;
+import com.ruoyi.quartz.util.ScheduleUtils;
+
+/**
+ * 定时任务调度信息 服务层
+ * 
+ * @author ruoyi
+ */
+@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;
+    }
+
+    /**
+     * 删除任务后,所对应的trigger也将被删除
+     * 
+     * @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 ids 需要删除的数据ID
+     * @return 结果
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void deleteJobByIds(String ids) throws SchedulerException
+    {
+        Long[] jobIds = Convert.toLongArray(ids);
+        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();
+        SysJob tmpObj = selectJobById(job.getJobId());
+        // 参数
+        JobDataMap dataMap = new JobDataMap();
+        dataMap.put(ScheduleConstants.TASK_PROPERTIES, tmpObj);
+        JobKey jobKey = ScheduleUtils.getJobKey(jobId, tmpObj.getJobGroup());
+        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);
+    }
+}
\ No newline at end of file
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java
new file mode 100644
index 0000000..853243b
--- /dev/null
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java
@@ -0,0 +1,28 @@
+package com.ruoyi.quartz.task;
+
+import org.springframework.stereotype.Component;
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * 定时任务调度测试
+ * 
+ * @author ruoyi
+ */
+@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/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/AbstractQuartzJob.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/AbstractQuartzJob.java
new file mode 100644
index 0000000..55eb51f
--- /dev/null
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/AbstractQuartzJob.java
@@ -0,0 +1,107 @@
+package com.ruoyi.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.ruoyi.common.constant.Constants;
+import com.ruoyi.common.constant.ScheduleConstants;
+import com.ruoyi.common.utils.ExceptionUtil;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.bean.BeanUtils;
+import com.ruoyi.common.utils.spring.SpringUtils;
+import com.ruoyi.quartz.domain.SysJob;
+import com.ruoyi.quartz.domain.SysJobLog;
+import com.ruoyi.quartz.service.ISysJobLogService;
+
+/**
+ * 抽象quartz调用
+ *
+ * @author ruoyi
+ */
+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.setEndTime(new Date());
+        long runMs = sysJobLog.getEndTime().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/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/CronUtils.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/CronUtils.java
new file mode 100644
index 0000000..01a84cb
--- /dev/null
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/CronUtils.java
@@ -0,0 +1,94 @@
+package com.ruoyi.quartz.util;
+
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import org.quartz.CronExpression;
+import org.quartz.TriggerUtils;
+import org.quartz.impl.triggers.CronTriggerImpl;
+import com.ruoyi.common.utils.DateUtils;
+
+/**
+ * cron表达式工具类
+ * 
+ * @author ruoyi
+ *
+ */
+public class CronUtils
+{
+    /**
+     * 返回一个布尔值代表一个给定的Cron表达式的有效性
+     *
+     * @param cronExpression Cron表达式
+     * @return boolean 表达式是否有效
+     */
+    public static boolean isValid(String cronExpression)
+    {
+        return CronExpression.isValidExpression(cronExpression);
+    }
+
+    /**
+     * 返回一个字符串值,表示该消息无效Cron表达式给出有效性
+     *
+     * @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());
+        }
+    }
+
+    /**
+     * 通过表达式获取近10次的执行时间
+     * 
+     * @param cron 表达式
+     * @return 时间列表
+     */
+    public static List<String> getRecentTriggerTime(String cron)
+    {
+        List<String> list = new ArrayList<String>();
+        try
+        {
+            CronTriggerImpl cronTriggerImpl = new CronTriggerImpl();
+            cronTriggerImpl.setCronExpression(cron);
+            List<Date> dates = TriggerUtils.computeFireTimes(cronTriggerImpl, null, 10);
+            for (Date date : dates)
+            {
+                list.add(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, date));
+            }
+        }
+        catch (ParseException e)
+        {
+            return null;
+        }
+        return list;
+    }
+}
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/JobInvokeUtil.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/JobInvokeUtil.java
new file mode 100644
index 0000000..e3dc62c
--- /dev/null
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/JobInvokeUtil.java
@@ -0,0 +1,182 @@
+package com.ruoyi.quartz.util;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.LinkedList;
+import java.util.List;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.spring.SpringUtils;
+import com.ruoyi.quartz.domain.SysJob;
+
+/**
+ * 任务执行工具
+ *
+ * @author ruoyi
+ */
+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布尔类型,等于true或者false
+            else if ("true".equalsIgnoreCase(str) || "false".equalsIgnoreCase(str))
+            {
+                classs.add(new Object[] { Boolean.valueOf(str), Boolean.class });
+            }
+            // long长整形,以L结尾
+            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/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzDisallowConcurrentExecution.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzDisallowConcurrentExecution.java
new file mode 100644
index 0000000..5e13558
--- /dev/null
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzDisallowConcurrentExecution.java
@@ -0,0 +1,21 @@
+package com.ruoyi.quartz.util;
+
+import org.quartz.DisallowConcurrentExecution;
+import org.quartz.JobExecutionContext;
+import com.ruoyi.quartz.domain.SysJob;
+
+/**
+ * 定时任务处理(禁止并发执行)
+ * 
+ * @author ruoyi
+ *
+ */
+@DisallowConcurrentExecution
+public class QuartzDisallowConcurrentExecution extends AbstractQuartzJob
+{
+    @Override
+    protected void doExecute(JobExecutionContext context, SysJob sysJob) throws Exception
+    {
+        JobInvokeUtil.invokeMethod(sysJob);
+    }
+}
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzJobExecution.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzJobExecution.java
new file mode 100644
index 0000000..e975326
--- /dev/null
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzJobExecution.java
@@ -0,0 +1,19 @@
+package com.ruoyi.quartz.util;
+
+import org.quartz.JobExecutionContext;
+import com.ruoyi.quartz.domain.SysJob;
+
+/**
+ * 定时任务处理(允许并发执行)
+ * 
+ * @author ruoyi
+ *
+ */
+public class QuartzJobExecution extends AbstractQuartzJob
+{
+    @Override
+    protected void doExecute(JobExecutionContext context, SysJob sysJob) throws Exception
+    {
+        JobInvokeUtil.invokeMethod(sysJob);
+    }
+}
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/ScheduleUtils.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/ScheduleUtils.java
new file mode 100644
index 0000000..206791a
--- /dev/null
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/ScheduleUtils.java
@@ -0,0 +1,141 @@
+package com.ruoyi.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.ruoyi.common.constant.Constants;
+import com.ruoyi.common.constant.ScheduleConstants;
+import com.ruoyi.common.exception.job.TaskException;
+import com.ruoyi.common.exception.job.TaskException.Code;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.spring.SpringUtils;
+import com.ruoyi.quartz.domain.SysJob;
+
+/**
+ * 定时任务工具类
+ * 
+ * @author ruoyi
+ *
+ */
+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);
+
+        // 按新的cronExpression表达式构建一个新的trigger
+        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);
+    }
+}
\ No newline at end of file
diff --git a/ruoyi-quartz/src/main/resources/mapper/quartz/SysJobLogMapper.xml b/ruoyi-quartz/src/main/resources/mapper/quartz/SysJobLogMapper.xml
new file mode 100644
index 0000000..aa9a575
--- /dev/null
+++ b/ruoyi-quartz/src/main/resources/mapper/quartz/SysJobLogMapper.xml
@@ -0,0 +1,94 @@
+<?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.ruoyi.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>
+		order by create_time desc
+	</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="String">
+ 		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>
+ 			sysdate()
+ 		)
+	</insert>
+
+</mapper> 
\ No newline at end of file
diff --git a/ruoyi-quartz/src/main/resources/mapper/quartz/SysJobMapper.xml b/ruoyi-quartz/src/main/resources/mapper/quartz/SysJobMapper.xml
new file mode 100644
index 0000000..5605c44
--- /dev/null
+++ b/ruoyi-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.ruoyi.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 = sysdate()
+ 		</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>
+ 			sysdate()
+ 		)
+	</insert>
+
+</mapper> 
\ No newline at end of file
diff --git a/ruoyi-quartz/src/main/resources/templates/monitor/job/add.html b/ruoyi-quartz/src/main/resources/templates/monitor/job/add.html
new file mode 100644
index 0000000..638b229
--- /dev/null
+++ b/ruoyi-quartz/src/main/resources/templates/monitor/job/add.html
@@ -0,0 +1,100 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+	<th:block th:include="include :: header('新增定时任务')" />
+</head>
+<body class="white-bg">
+	<div class="wrapper wrapper-content animated fadeInRight ibox-content">
+		<form class="form-horizontal m" id="form-job-add">
+		    <input type="hidden" name="createBy" th:value="${@permission.getPrincipalProperty('loginName')}">
+			<div class="form-group">
+				<label class="col-sm-3 control-label is-required">任务名称:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="jobName" id="jobName" required>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">任务分组:</label>
+				<div class="col-sm-8">
+					<select name="jobGroup" class="form-control m-b" th:with="type=${@dict.getType('sys_job_group')}">
+		                <option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
+		            </select>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label is-required">调用目标字符串:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="invokeTarget" id="invokeTarget" required>
+				    <span class="help-block m-b-none"><i class="fa fa-info-circle"></i> Bean调用示例:ryTask.ryParams('ry')</span>
+				    <span class="help-block m-b-none"><i class="fa fa-info-circle"></i> Class类调用示例:com.ruoyi.quartz.task.RyTask.ryParams('ry')</span>
+				    <span class="help-block m-b-none"><i class="fa fa-info-circle"></i> 参数说明:支持字符串,布尔类型,长整型,浮点型,整型</span>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label is-required">cron表达式:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="cronExpression" id="cronExpression" required>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">执行策略:</label>
+				<div class="col-sm-8">
+					<label class="radio-box"> <input type="radio" name="misfirePolicy" value="1" th:checked="true"/> 立即执行 </label> 
+					<label class="radio-box"> <input type="radio" name="misfirePolicy" value="2" /> 执行一次 </label> 
+					<label class="radio-box"> <input type="radio" name="misfirePolicy" value="3" /> 放弃执行 </label>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">并发执行:</label>
+				<div class="col-sm-8">
+					<label class="radio-box"> <input type="radio" name="concurrent" value="0"/> 允许 </label> 
+					<label class="radio-box"> <input type="radio" name="concurrent" value="1" th:checked="true"/> 禁止 </label> 
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">备注:</label>
+				<div class="col-sm-8">
+					<textarea id="remark" name="remark" class="form-control"></textarea>
+				</div>
+			</div>
+		</form>
+	</div>
+	<th:block th:include="include :: footer" />
+	<script type="text/javascript">
+		var prefix = ctx + "monitor/job";
+	
+		$("#form-job-add").validate({
+			onkeyup: false,
+			rules:{
+				cronExpression:{
+					remote: {
+	                    url: prefix + "/checkCronExpressionIsValid",
+	                    type: "post",
+	                    dataType: "json",
+	                    data: {
+	                        "cronExpression": function() {
+	                            return $.common.trim($("#cronExpression").val());
+	                        }
+	                    },
+	                    dataFilter: function(data, type) {
+	                    	return data;
+	                    }
+	                }
+				},
+			},
+			messages: {
+	            "cronExpression": {
+	                remote: "表达式不正确"
+	            }
+	        },
+	        focusCleanup: true
+		});
+		
+		function submitHandler() {
+	        if ($.validate.form()) {
+	        	$.operate.save(prefix + "/add", $('#form-job-add').serialize());
+	        }
+	    }
+	</script>
+</body>
+</html>
diff --git a/ruoyi-quartz/src/main/resources/templates/monitor/job/cron.html b/ruoyi-quartz/src/main/resources/templates/monitor/job/cron.html
new file mode 100644
index 0000000..f2aacb5
--- /dev/null
+++ b/ruoyi-quartz/src/main/resources/templates/monitor/job/cron.html
@@ -0,0 +1,1172 @@
+<!DOCTYPE html>
+<html  lang="zh" xmlns:th="http://www.thymeleaf.org">
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Cron表达式在线生成</title>
+    <link th:href="@{/css/bootstrap.min.css}" rel="stylesheet"/>
+    <link th:href="@{/css/zen-checkbox.css}" rel="stylesheet"/>
+</head>
+<body class="load-indicator">
+    <div class="container t-small-margin">
+      <div class="t-big-margin">
+        <ul class="nav nav-tabs">
+            <li class="active"><a data-toggle="tab" href="#tabSecond">秒</a></li>
+            <li><a data-toggle="tab" href="#tabMinute">分</a></li>
+            <li><a data-toggle="tab" href="#tabHour">时</a></li>
+            <li><a data-toggle="tab" href="#tabDay">日</a></li>
+            <li><a data-toggle="tab" href="#tabMonth">月</a></li>
+            <li><a data-toggle="tab" href="#tabWeek">周</a></li>
+            <li><a data-toggle="tab" href="#tabYear">年</a></li>
+        </ul>
+        <div class="tab-content tab-cron">
+            <div class="tab-pane active" id="tabSecond">
+                <div class="radio">
+                    <label>
+                        <input type="radio" id="sec_all" name="rdoSecond"> 每秒 允许的通配符[, - * /]
+                    </label>
+                </div>
+                <div class="radio">
+                    <label class="custom-radio">
+                        <input type="radio" id="sec_circle" name="rdoSecond">
+                        <div class="input-group">
+                            <span class="input-group-addon">周期从</span>
+                            <input type="number" id="sec_circle1" class="form-control">
+                            <span class="input-group-addon">-</span>
+                            <input type="number" id="sec_circle2" class="form-control">
+                            <span class="input-group-addon">秒</span>
+                        </div>
+                    </label>
+                </div>
+                <div class="radio  ">
+                    <label class="custom-radio">
+                        <input type="radio" id="sec_per" name="rdoSecond">
+                        <div class="input-group">
+                            <span class="input-group-addon">从</span>
+                            <input type="number" id="sec_per1" class="form-control">
+                            <span class="input-group-addon">秒开始,每</span>
+                            <input type="number" id="sec_per2" class="form-control">
+                            <span class="input-group-addon">秒执行一次</span>
+                        </div>
+                    </label>
+                </div>
+                <div class="radio  tabsecondchk">
+                    <label>
+                        <input type="radio" id="sec_assign" name="rdoSecond">指定
+                        <div class="checkbox">
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond0" name="zd_second" value="0">
+                                <label for="zdSecond0">0</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond1" name="zd_second" value="1">
+                                <label for="zdSecond1">1</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond2" name="zd_second" value="2">
+                                <label for="zdSecond2">2</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond3" name="zd_second" value="3">
+                                <label for="zdSecond3">3</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond4" name="zd_second" value="4">
+                                <label for="zdSecond4">4</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond5" name="zd_second" value="5">
+                                <label for="zdSecond5">5</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond6" name="zd_second" value="6">
+                                <label for="zdSecond6">6</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond7" name="zd_second" value="7">
+                                <label for="zdSecond7">7</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond8" name="zd_second" value="8">
+                                <label for="zdSecond8">8</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond9" name="zd_second" value="9">
+                                <label for="zdSecond9">9</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond10" name="zd_second" value="10">
+                                <label for="zdSecond10">10</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond11" name="zd_second" value="11">
+                                <label for="zdSecond11">11</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond12" name="zd_second" value="12">
+                                <label for="zdSecond12">12</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond13" name="zd_second" value="13">
+                                <label for="zdSecond13">13</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond14" name="zd_second" value="14">
+                                <label for="zdSecond14">14</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond15" name="zd_second" value="15">
+                                <label for="zdSecond15">15</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond16" name="zd_second" value="16">
+                                <label for="zdSecond16">16</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond17" name="zd_second" value="17">
+                                <label for="zdSecond17">17</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond18" name="zd_second" value="18">
+                                <label for="zdSecond18">18</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond19" name="zd_second" value="19">
+                                <label for="zdSecond19">19</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond20" name="zd_second" value="20">
+                                <label for="zdSecond20">20</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond21" name="zd_second" value="21">
+                                <label for="zdSecond21">21</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond22" name="zd_second" value="22">
+                                <label for="zdSecond22">22</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond23" name="zd_second" value="23">
+                                <label for="zdSecond23">23</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond24" name="zd_second" value="24">
+                                <label for="zdSecond24">24</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond25" name="zd_second" value="25">
+                                <label for="zdSecond25">25</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond26" name="zd_second" value="26">
+                                <label for="zdSecond26">26</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond27" name="zd_second" value="27">
+                                <label for="zdSecond27">27</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond28" name="zd_second" value="28">
+                                <label for="zdSecond28">28</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond29" name="zd_second" value="29">
+                                <label for="zdSecond29">29</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond30" name="zd_second" value="30">
+                                <label for="zdSecond30">30</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond31" name="zd_second" value="31">
+                                <label for="zdSecond31">31</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond32" name="zd_second" value="32">
+                                <label for="zdSecond32">32</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond33" name="zd_second" value="33">
+                                <label for="zdSecond33">33</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond34" name="zd_second" value="34">
+                                <label for="zdSecond34">34</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond35" name="zd_second" value="35">
+                                <label for="zdSecond35">35</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond36" name="zd_second" value="36">
+                                <label for="zdSecond36">36</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond37" name="zd_second" value="37">
+                                <label for="zdSecond37">37</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond38" name="zd_second" value="38">
+                                <label for="zdSecond38">38</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond39" name="zd_second" value="39">
+                                <label for="zdSecond39">39</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond40" name="zd_second" value="40">
+                                <label for="zdSecond40">40</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond41" name="zd_second" value="41">
+                                <label for="zdSecond41">41</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond42" name="zd_second" value="42">
+                                <label for="zdSecond42">42</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond43" name="zd_second" value="43">
+                                <label for="zdSecond43">43</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond44" name="zd_second" value="44">
+                                <label for="zdSecond44">44</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond45" name="zd_second" value="45">
+                                <label for="zdSecond45">45</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond46" name="zd_second" value="46">
+                                <label for="zdSecond46">46</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond47" name="zd_second" value="47">
+                                <label for="zdSecond47">47</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond48" name="zd_second" value="48">
+                                <label for="zdSecond48">48</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond49" name="zd_second" value="49">
+                                <label for="zdSecond49">49</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond50" name="zd_second" value="50">
+                                <label for="zdSecond50">50</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond51" name="zd_second" value="51">
+                                <label for="zdSecond51">51</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond52" name="zd_second" value="52">
+                                <label for="zdSecond52">52</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond53" name="zd_second" value="53">
+                                <label for="zdSecond53">53</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond54" name="zd_second" value="54">
+                                <label for="zdSecond54">54</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond55" name="zd_second" value="55">
+                                <label for="zdSecond55">55</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond56" name="zd_second" value="56">
+                                <label for="zdSecond56">56</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond57" name="zd_second" value="57">
+                                <label for="zdSecond57">57</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond58" name="zd_second" value="58">
+                                <label for="zdSecond58">58</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdSecond59" name="zd_second" value="59">
+                                <label for="zdSecond59">59</label>
+                            </div>
+                        </div>
+                    </label>
+                </div>
+            </div>
+            <div class="tab-pane" id="tabMinute">
+                <div class="radio">
+                    <label>
+                        <input type="radio" id="min_all" name="rdoMinute"> 每分 允许的通配符[, - * /]
+                    </label>
+                </div>
+                <div class="radio  ">
+                    <label class="custom-radio">
+                        <input type="radio" id="min_circle" name="rdoMinute">
+                        <div class="input-group">
+                            <span class="input-group-addon">周期从</span>
+                            <input type="number" id="min_circle1" class="form-control">
+                            <span class="input-group-addon">-</span>
+                            <input id="min_circle2" type="number" class="form-control">
+                            <span class="input-group-addon">分</span>
+                        </div>
+                    </label>
+                </div>
+                <div class="radio  ">
+                    <label class="custom-radio">
+                        <input type="radio" name="rdoMinute" id="min_per">
+                        <div class="input-group">
+                            <span class="input-group-addon">从</span>
+                            <input type="number" id="min_per1" class="form-control">
+                            <span class="input-group-addon">分开始,每</span>
+                            <input type="number" id="min_per2" class="form-control">
+                            <span class="input-group-addon">分执行一次</span>
+                        </div>
+                    </label>
+                </div>
+                <div class="radio  tabsecondchk">
+                    <label>
+                        <input type="radio" id="min_assign" name="rdoMinute">指定
+                        <div class="checkbox">
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute0" name="zd_minute" value="0">
+                                <label for="zdMinute0">0</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute1" name="zd_minute" value="1">
+                                <label for="zdMinute1">1</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute2" name="zd_minute" value="2">
+                                <label for="zdMinute2">2</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute3" name="zd_minute" value="3">
+                                <label for="zdMinute3">3</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute4" name="zd_minute" value="4">
+                                <label for="zdMinute4">4</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute5" name="zd_minute" value="5">
+                                <label for="zdMinute5">5</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute6" name="zd_minute" value="6">
+                                <label for="zdMinute6">6</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute7" name="zd_minute" value="7">
+                                <label for="zdMinute7">7</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute8" name="zd_minute" value="8">
+                                <label for="zdMinute8">8</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute9" name="zd_minute" value="9">
+                                <label for="zdMinute9">9</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute10" name="zd_minute" value="10">
+                                <label for="zdMinute10">10</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute11" name="zd_minute" value="11">
+                                <label for="zdMinute11">11</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute12" name="zd_minute" value="12">
+                                <label for="zdMinute12">12</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute13" name="zd_minute" value="13">
+                                <label for="zdMinute13">13</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute14" name="zd_minute" value="14">
+                                <label for="zdMinute14">14</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute15" name="zd_minute" value="15">
+                                <label for="zdMinute15">15</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute16" name="zd_minute" value="16">
+                                <label for="zdMinute16">16</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute17" name="zd_minute" value="17">
+                                <label for="zdMinute17">17</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute18" name="zd_minute" value="18">
+                                <label for="zdMinute18">18</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute19" name="zd_minute" value="19">
+                                <label for="zdMinute19">19</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute20" name="zd_minute" value="20">
+                                <label for="zdMinute20">20</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute21" name="zd_minute" value="21">
+                                <label for="zdMinute21">21</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute22" name="zd_minute" value="22">
+                                <label for="zdMinute22">22</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute23" name="zd_minute" value="23">
+                                <label for="zdMinute23">23</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute24" name="zd_minute" value="24">
+                                <label for="zdMinute24">24</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute25" name="zd_minute" value="25">
+                                <label for="zdMinute25">25</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute26" name="zd_minute" value="26">
+                                <label for="zdMinute26">26</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute27" name="zd_minute" value="27">
+                                <label for="zdMinute27">27</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute28" name="zd_minute" value="28">
+                                <label for="zdMinute28">28</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute29" name="zd_minute" value="29">
+                                <label for="zdMinute29">29</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute30" name="zd_minute" value="30">
+                                <label for="zdMinute30">30</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute31" name="zd_minute" value="31">
+                                <label for="zdMinute31">31</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute32" name="zd_minute" value="32">
+                                <label for="zdMinute32">32</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute33" name="zd_minute" value="33">
+                                <label for="zdMinute33">33</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute34" name="zd_minute" value="34">
+                                <label for="zdMinute34">34</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute35" name="zd_minute" value="35">
+                                <label for="zdMinute35">35</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute36" name="zd_minute" value="36">
+                                <label for="zdMinute36">36</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute37" name="zd_minute" value="37">
+                                <label for="zdMinute37">37</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute38" name="zd_minute" value="38">
+                                <label for="zdMinute38">38</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute39" name="zd_minute" value="39">
+                                <label for="zdMinute39">39</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute40" name="zd_minute" value="40">
+                                <label for="zdMinute40">40</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute41" name="zd_minute" value="41">
+                                <label for="zdMinute41">41</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute42" name="zd_minute" value="42">
+                                <label for="zdMinute42">42</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute43" name="zd_minute" value="43">
+                                <label for="zdMinute43">43</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute44" name="zd_minute" value="44">
+                                <label for="zdMinute44">44</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute45" name="zd_minute" value="45">
+                                <label for="zdMinute45">45</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute46" name="zd_minute" value="46">
+                                <label for="zdMinute46">46</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute47" name="zd_minute" value="47">
+                                <label for="zdMinute47">47</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute48" name="zd_minute" value="48">
+                                <label for="zdMinute48">48</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute49" name="zd_minute" value="49">
+                                <label for="zdMinute49">49</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute50" name="zd_minute" value="50">
+                                <label for="zdMinute50">50</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute51" name="zd_minute" value="51">
+                                <label for="zdMinute51">51</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute52" name="zd_minute" value="52">
+                                <label for="zdMinute52">52</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute53" name="zd_minute" value="53">
+                                <label for="zdMinute53">53</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute54" name="zd_minute" value="54">
+                                <label for="zdMinute54">54</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute55" name="zd_minute" value="55">
+                                <label for="zdMinute55">55</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute56" name="zd_minute" value="56">
+                                <label for="zdMinute56">56</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute57" name="zd_minute" value="57">
+                                <label for="zdMinute57">57</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute58" name="zd_minute" value="58">
+                                <label for="zdMinute58">58</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMinute59" name="zd_minute" value="59">
+                                <label for="zdMinute59">59</label>
+                            </div>
+                        </div>
+                    </label>
+                </div>
+            </div>
+            <div class="tab-pane" id="tabHour">
+                <div class="radio">
+                    <label>
+                        <input type="radio" id="hour_all" name="rdoMinute"> 每小时 允许的通配符[, - * /]
+                    </label>
+                </div>
+                <div class="radio">
+                    <label class="custom-radio">
+                        <input type="radio" id="hour_circle" name="rdoMinute">
+                        <div class="input-group">
+                            <span class="input-group-addon">周期从</span>
+                            <input type="number" id="hour_circle1" class="form-control">
+                            <span class="input-group-addon">-</span>
+                            <input type="number" id="hour_circle2" class="form-control">
+                            <span class="input-group-addon">小时</span>
+                        </div>
+                    </label>
+                </div>
+                <div class="radio">
+                    <label class="custom-radio">
+                        <input type="radio" name="rdoMinute" id="hour_per">
+                        <div class="input-group">
+                            <span class="input-group-addon">从</span>
+                            <input type="number" id="hour_per1" class="form-control">
+                            <span class="input-group-addon">小时开始,每</span>
+                            <input type="number" id="hour_per2" class="form-control">
+                            <span class="input-group-addon">小时执行一次</span>
+                        </div>
+                    </label>
+                </div>
+                <div class="radio  tabsecondchk">
+                    <label>
+                        <input type="radio" id="hour_assign" name="rdoMinute">指定
+                        <div class="checkbox">
+                            <label>AM:</label>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdHour0" name="zd_hour" value="0">
+                                <label for="zdHour0">0</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdHour1" name="zd_hour" value="1">
+                                <label for="zdHour1">1</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdHour2" name="zd_hour" value="2">
+                                <label for="zdHour2">2</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdHour3" name="zd_hour" value="3">
+                                <label for="zdHour3">3</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdHour4" name="zd_hour" value="4">
+                                <label for="zdHour4">4</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdHour5" name="zd_hour" value="5">
+                                <label for="zdHour5">5</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdHour6" name="zd_hour" value="6">
+                                <label for="zdHour6">6</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdHour7" name="zd_hour" value="7">
+                                <label for="zdHour7">7</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdHour8" name="zd_hour" value="8">
+                                <label for="zdHour8">8</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdHour9" name="zd_hour" value="9">
+                                <label for="zdHour9">9</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdHour10" name="zd_hour" value="10">
+                                <label for="zdHour10">10</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdHour11" name="zd_hour" value="11">
+                                <label for="zdHour11">11</label>
+                            </div>
+                            <br>
+                            <label>PM:</label>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdHour12" name="zd_hour" value="12">
+                                <label for="zdHour12">12</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdHour13" name="zd_hour" value="13">
+                                <label for="zdHour13">13</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdHour14" name="zd_hour" value="14">
+                                <label for="zdHour14">14</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdHour15" name="zd_hour" value="15">
+                                <label for="zdHour15">15</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdHour16" name="zd_hour" value="16">
+                                <label for="zdHour16">16</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdHour17" name="zd_hour" value="17">
+                                <label for="zdHour17">17</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdHour18" name="zd_hour" value="18">
+                                <label for="zdHour18">18</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdHour19" name="zd_hour" value="19">
+                                <label for="zdHour19">19</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdHour20" name="zd_hour" value="20">
+                                <label for="zdHour20">20</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdHour21" name="zd_hour" value="21">
+                                <label for="zdHour21">21</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdHour22" name="zd_hour" value="22">
+                                <label for="zdHour22">22</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdHour23" name="zd_hour" value="23">
+                                <label for="zdHour23">23</label>
+                            </div>
+                        </div>
+                    </label>
+                </div>
+            </div>
+            <div class="tab-pane" id="tabDay">
+                <div class="radio">
+                    <label>
+                        <input type="radio" name="rdoDay" id="day_all"> 每日 允许的通配符[, - * /]
+                    </label>
+                </div>
+                <div class="radio">
+                    <label>
+                        <input type="radio" name="rdoDay" id="day_no"> 不指定
+                    </label>
+                </div>
+                <div class="radio">
+                    <label class="custom-radio">
+                        <input type="radio" name="rdoDay" id="day_circle">
+                        <div class="input-group">
+                            <span class="input-group-addon">周期从</span>
+                            <input type="number" id="day_circle1" class="form-control">
+                            <span class="input-group-addon">-</span>
+                            <input type="number" id="day_circle2" class="form-control">
+                            <span class="input-group-addon">日</span>
+                        </div>
+                    </label>
+                </div>
+                <div class="radio">
+                    <label class="custom-radio">
+                        <input type="radio" name="rdoDay" id="day_per">
+                        <div class="input-group">
+                            <span class="input-group-addon">从</span>
+                            <input type="number" id="day_per1" class="form-control">
+                            <span class="input-group-addon">日开始,每</span>
+                            <input type="number" id="day_per2" class="form-control">
+                            <span class="input-group-addon">日执行一次</span>
+                        </div>
+                    </label>
+                </div>
+                <div class="radio">
+                    <label class="custom-radio">
+                        <input type="radio" name="rdoDay" id="day_work">
+                        <div class="input-group">
+                            <span class="input-group-addon">每月</span>
+                            <input type="number" id="day_work1" class="form-control">
+                            <span class="input-group-addon">号最近的那个工作日</span>
+                        </div>
+                    </label>
+                </div>
+                <div class="radio">
+                    <label>
+                        <input type="radio" name="rdoDay" id="day_last"> 本月最后一日
+                    </label>
+                </div>
+                <div class="radio  tabsecondchk">
+                    <label>
+                        <input type="radio" id="day_assign" name="rdoDay">指定
+                        <div class="checkbox">
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdDay1" name="zd_day" value="1">
+                                <label for="zdDay1">1</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdDay2" name="zd_day" value="2">
+                                <label for="zdDay2">2</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdDay3" name="zd_day" value="3">
+                                <label for="zdDay3">3</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdDay4" name="zd_day" value="4">
+                                <label for="zdDay4">4</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdDay5" name="zd_day" value="5">
+                                <label for="zdDay5">5</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdDay6" name="zd_day" value="6">
+                                <label for="zdDay6">6</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdDay7" name="zd_day" value="7">
+                                <label for="zdDay7">7</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdDay8" name="zd_day" value="8">
+                                <label for="zdDay8">8</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdDay9" name="zd_day" value="9">
+                                <label for="zdDay9">9</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdDay10" name="zd_day" value="10">
+                                <label for="zdDay10">10</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdDay11" name="zd_day" value="11">
+                                <label for="zdDay11">11</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdDay12" name="zd_day" value="12">
+                                <label for="zdDay12">12</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdDay13" name="zd_day" value="13">
+                                <label for="zdDay13">13</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdDay14" name="zd_day" value="14">
+                                <label for="zdDay14">14</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdDay15" name="zd_day" value="15">
+                                <label for="zdDay15">15</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdDay16" name="zd_day" value="16">
+                                <label for="zdDay16">16</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdDay17" name="zd_day" value="17">
+                                <label for="zdDay17">17</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdDay18" name="zd_day" value="18">
+                                <label for="zdDay18">18</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdDay19" name="zd_day" value="19">
+                                <label for="zdDay19">19</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdDay20" name="zd_day" value="20">
+                                <label for="zdDay20">20</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdDay21" name="zd_day" value="21">
+                                <label for="zdDay21">21</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdDay22" name="zd_day" value="22">
+                                <label for="zdDay22">22</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdDay23" name="zd_day" value="23">
+                                <label for="zdDay23">23</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdDay24" name="zd_day" value="24">
+                                <label for="zdDay24">24</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdDay25" name="zd_day" value="25">
+                                <label for="zdDay25">25</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdDay26" name="zd_day" value="26">
+                                <label for="zdDay26">26</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdDay27" name="zd_day" value="27">
+                                <label for="zdDay27">27</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdDay28" name="zd_day" value="28">
+                                <label for="zdDay28">28</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdDay29" name="zd_day" value="29">
+                                <label for="zdDay29">29</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdDay30" name="zd_day" value="30">
+                                <label for="zdDay30">30</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdDay31" name="zd_day" value="31">
+                                <label for="zdDay31">31</label>
+                            </div>
+                        </div>
+                    </label>
+                </div>
+            </div>
+            <div class="tab-pane" id="tabMonth">
+                <div class="radio">
+                    <label>
+                        <input type="radio" name="rdoMonth" id="month_all"> 每月 允许的通配符[, - * /]
+                    </label>
+                </div>
+                <div class="radio">
+                    <label>
+                        <input type="radio" name="rdoMonth" id="month_no"> 不指定
+                    </label>
+                </div>
+                <div class="radio">
+                    <label class="custom-radio">
+                        <input type="radio" name="rdoMonth" id="month_circle">
+                        <div class="input-group">
+                            <span class="input-group-addon">周期从</span>
+                            <input type="number" id="month_circle1" class="form-control">
+                            <span class="input-group-addon">-</span>
+                            <input type="number" id="month_circle2" class="form-control">
+                            <span class="input-group-addon">月</span>
+                        </div>
+                    </label>
+                </div>
+                <div class="radio">
+                    <label class="custom-radio">
+                        <input type="radio" name="rdoMonth" id="month_per">
+                        <div class="input-group">
+                            <span class="input-group-addon">从</span>
+                            <input type="number" id="month_per1" class="form-control">
+                            <span class="input-group-addon">月开始,每</span>
+                            <input type="number" id="month_per2" class="form-control">
+                            <span class="input-group-addon">月执行一次</span>
+                        </div>
+                    </label>
+                </div>
+                <div class="radio  tabsecondchk">
+                    <label>
+                        <input type="radio" id="month_assign" name="rdoMonth">指定
+                        <div class="checkbox">
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMonth1" name="zd_month" value="1">
+                                <label for="zdMonth1">1</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMonth2" name="zd_month" value="2">
+                                <label for="zdMonth2">2</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMonth3" name="zd_month" value="3">
+                                <label for="zdMonth3">3</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMonth4" name="zd_month" value="4">
+                                <label for="zdMonth4">4</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMonth5" name="zd_month" value="5">
+                                <label for="zdMonth5">5</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMonth6" name="zd_month" value="6">
+                                <label for="zdMonth6">6</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMonth7" name="zd_month" value="7">
+                                <label for="zdMonth7">7</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMonth8" name="zd_month" value="8">
+                                <label for="zdMonth8">8</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMonth9" name="zd_month" value="9">
+                                <label for="zdMonth9">9</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMonth10" name="zd_month" value="10">
+                                <label for="zdMonth10">10</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMonth11" name="zd_month" value="11">
+                                <label for="zdMonth11">11</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdMonth12" name="zd_month" value="12">
+                                <label for="zdMonth12">12</label>
+                            </div>
+                        </div>
+                    </label>
+                </div>
+            </div>
+            <div class="tab-pane" id="tabWeek">
+                <div class="radio">
+                    <label>
+                        <input type="radio" id="week_all" name="rdoWeek"> 周 允许的通配符[, - * /]
+                    </label>
+                </div>
+                <div class="radio">
+                    <label>
+                        <input type="radio" id="week_no" name="rdoWeek"> 不指定
+                    </label>
+                </div>
+                <div class="radio">
+                    <label class="custom-radio">
+                        <input type="radio" name="rdoWeek" id="week_circle">
+                        <div class="input-group">
+                            <span class="input-group-addon">周期从</span>
+                            <input type="number" id="week_circle1" class="form-control">
+                            <span class="input-group-addon">-</span>
+                            <input type="number" id="week_circle2" class="form-control">
+                        </div>
+                    </label>
+                </div>
+                <div class="radio">
+                    <label class="custom-radio">
+                        <input type="radio" name="rdoWeek" id="week_num">
+                        <div class="input-group">
+                            <span class="input-group-addon">第</span>
+                            <input type="number" id="week_num1" class="form-control">
+                            <span class="input-group-addon">星期的星期</span>
+                            <input type="number" id="week_num2" class="form-control">
+                        </div>
+                    </label>
+                </div>
+                <div class="radio">
+                    <label>
+                        <input type="radio" name="rdoWeek" id="week_last">
+                        <div class="input-group">
+                            <span class="input-group-addon">本月最后一个星期</span>
+                            <input type="number" id="week_last1" class="form-control">
+                        </div>
+                    </label>
+                </div>
+                <div class="radio  tabsecondchk">
+                    <label>
+                        <input type="radio" id="week_assign" name="rdoWeek">指定
+                        <div class="checkbox">
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdWeek1" name="zd_week" value="1">
+                                <label for="zdWeek1">1</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdWeek2" name="zd_week" value="2">
+                                <label for="zdWeek2">2</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdWeek3" name="zd_week" value="3">
+                                <label for="zdWeek3">3</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdWeek4" name="zd_week" value="4">
+                                <label for="zdWeek4">4</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdWeek5" name="zd_week" value="5">
+                                <label for="zdWeek5">5</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdWeek6" name="zd_week" value="6">
+                                <label for="zdWeek6">6</label>
+                            </div>
+                            <div class="checkbox-primary">
+                                <input type="checkbox" id="zdWeek7" name="zd_week" value="7">
+                                <label for="zdWeek7">7</label>
+                            </div>
+                        </div>
+                    </label>
+                </div>
+            </div>
+            <div class="tab-pane" id="tabYear">
+                <div class="radio">
+                    <label>
+                        <input type="radio" id="year_no" name="rdoWeek"> 不指定 允许的通配符[, - * /] 非必填
+                    </label>
+                </div>
+                <div class="radio">
+                    <label>
+                        <input type="radio" id="year_all" name="rdoWeek"> 每年
+                    </label>
+                </div>
+                <div class="radio">
+                    <label class="custom-radio">
+                        <input type="radio" name="rdoWeek" id="year_circle">
+                        <div class="input-group">
+                            <span class="input-group-addon">周期从</span>
+                            <input type="number" id="year_circle1" class="form-control">
+                            <span class="input-group-addon">-</span>
+                            <input type="number" id="year_circle2" class="form-control">
+                        </div>
+                    </label>
+                </div>
+            </div>
+        </div>
+        <div class="t-big-margin">
+            <h4>表达式</h4>
+        </div>
+        <table class="table table-hover cron_table table-bordered">
+            <tbody>
+            <tr>
+                <td></td>
+                <td align="center">秒</td>
+                <td align="center">分钟</td>
+                <td align="center">小时</td>
+                <td align="center">日</td>
+                <td align="center">月</td>
+                <td align="center">星期</td>
+                <td align="center">年</td>
+            </tr>
+            <tr>
+                <td>表达式字段</td>
+                <td><input type="text" class="form-control" id="v_second" value="*" readonly=""></td>
+                <td><input type="text" class="form-control" id="v_min" value="*" readonly=""></td>
+                <td><input type="text" class="form-control" id="v_hour" value="*" readonly=""></td>
+                <td><input type="text" class="form-control" id="v_day" value="*" readonly=""></td>
+                <td><input type="text" class="form-control" id="v_month" value="*" readonly=""></td>
+                <td><input type="text" class="form-control" id="v_week" value="?" readonly=""></td>
+                <td><input type="text" class="form-control" id="v_year" readonly=""></td>
+            </tr>
+            <tr>
+                <td>Cron 表达式</td>
+                <td colspan="7"><input type="text" class="form-control" id="cron" value="* * * * * ?"></td>
+            </tr>
+            </tbody>
+        </table>
+        <div class="text-center">
+            <button type="button" class="btn btn-primary" id="runBtn">查询最近10次运行时间</button>
+            <button type="button" class="btn btn-info" id="unrunBtn">Cron表达式转成字段</button>
+            <button type="button" class="btn btn-warning" id="checkCron">Cron表达式验证</button>
+        </div>
+        <br/>
+      </div>
+    </div>
+</div>
+<script th:src="@{/js/jquery.min.js}"></script>
+<script th:src="@{/js/bootstrap.min.js}"></script>
+<script th:src="@{/ajax/libs/layer/layer.min.js}"></script>
+<script th:src="@{/ruoyi/js/ry-ui.js?v=4.8.0}"></script>
+<script th:src="@{/js/cron.js}"></script>
+<script th:inline="javascript">
+var prefix = [[@{/}]] + "monitor/job";
+
+// 查询最近10次运行时间
+$('#runBtn').click(function() {
+    var cronExpression = $("#cron").val();
+    $.get(prefix + "/queryCronExpression", { "cronExpression": cronExpression }, function(result) {
+    	if (result.code == web_status.SUCCESS) {
+    		if (result.data.length > 0) {
+        		var time = "表达式<font color='red'>[" + cronExpression + "]</font>最近10次运行时间<br/>";
+                for (var i = 0; i < result.data.length; i++) {
+                	time += i + 1 +"、" + result.data[i] + "<br/>"
+                }
+                $.modal.alertSuccess(time);
+        	} else {
+                $.modal.alertError("表达式有误,未查询出结果");
+            }
+        } else {
+            $.modal.alertError(result.msg);
+        }
+    });
+});
+
+// Cron表达式验证
+$('#checkCron').click(function() {
+    var cronExpression = $("#cron").val();
+    $.post(prefix + "/checkCronExpressionIsValid", { "cronExpression": cronExpression }, function(result) {
+        if (result) {
+            $.modal.msgSuccess("恭喜你,格式正确");
+        } else {
+            $.modal.msgError("很遗憾,格式错误");
+        }
+    });
+});
+</script>
+</body>
+</html>
diff --git a/ruoyi-quartz/src/main/resources/templates/monitor/job/detail.html b/ruoyi-quartz/src/main/resources/templates/monitor/job/detail.html
new file mode 100644
index 0000000..730fa81
--- /dev/null
+++ b/ruoyi-quartz/src/main/resources/templates/monitor/job/detail.html
@@ -0,0 +1,99 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+	<th:block th:include="include :: header('定时任务详细')" />
+</head>
+<body class="white-bg">
+	<div class="wrapper wrapper-content animated fadeInRight ibox-content">
+	
+	<form class="form-horizontal m-t" id="jobLogForm" th:if="${name == 'jobLog'}">
+	    <div class="form-group">
+			<label class="col-sm-3 control-label">日志序号:</label>
+			<div class="form-control-static" th:text="${jobLog.jobLogId}">
+			</div>
+		</div>
+		<div class="form-group">
+			<label class="col-sm-3 control-label">任务名称:</label>
+			<div class="form-control-static" th:text="${jobLog.jobName}">
+			</div>
+		</div>
+		<div class="form-group">
+			<label class="col-sm-3 control-label">任务分组:</label>
+			<div class="form-control-static" th:text="${@dict.getLabel('sys_job_group', jobLog.jobGroup)}">
+			</div>
+		</div>
+		<div class="form-group">
+			<label class="col-sm-3 control-label">调用目标字符串:</label>
+			<div class="form-control-static" th:text="${jobLog.invokeTarget}">
+			</div>
+		</div>
+		<div class="form-group">
+			<label class="col-sm-3 control-label">日志信息:</label>
+			<div class="form-control-static" th:text="${jobLog.jobMessage}">
+			</div>
+		</div>
+		<div class="form-group">
+			<label class="col-sm-3 control-label">执行状态:</label>
+			<div class="form-control-static" th:class="${jobLog.status == '0' ? 'label label-primary' : 'label label-danger'}" th:text="${jobLog.status == '0' ? '正常' : '失败'}">
+			</div>
+		</div>
+		<div class="form-group" th:style="'display:' + ${jobLog.status == '0' ? 'none' : 'block'}">
+			<label class="col-sm-3 control-label">异常信息:</label>
+			<div class="form-control-static" th:text="${jobLog.exceptionInfo}">
+			</div>
+		</div>
+	</form>
+	
+	<form class="form-horizontal m-t" id="jobForm" th:if="${name == 'job'}">
+	    <div class="form-group">
+			<label class="col-sm-3 control-label">任务序号:</label>
+			<div class="form-control-static" th:text="${job.jobId}">
+			</div>
+		</div>
+		<div class="form-group">
+			<label class="col-sm-3 control-label">任务名称:</label>
+			<div class="form-control-static" th:text="${job.jobName}">
+			</div>
+		</div>
+		<div class="form-group">
+			<label class="col-sm-3 control-label">任务分组:</label>
+			<div class="form-control-static" th:text="${job.jobGroup}">
+			</div>
+		</div>
+		<div class="form-group">
+			<label class="col-sm-3 control-label">调用目标字符串:</label>
+			<div class="form-control-static" th:text="${job.invokeTarget}">
+			</div>
+		</div>
+		<div class="form-group">
+			<label class="col-sm-3 control-label">执行表达式:</label>
+			<div class="form-control-static" th:text="${job.cronExpression}">
+			</div>
+		</div>
+		<div class="form-group">
+			<label class="col-sm-3 control-label">下次执行时间:</label>
+			<div class="form-control-static" th:text="${#dates.format(job.nextValidTime, 'yyyy-MM-dd HH:mm:ss')}">
+			</div>
+		</div>
+		<div class="form-group">
+			<label class="col-sm-3 control-label">执行策略:</label>
+			<div class="form-control-static" th:if="${job.misfirePolicy == '0'}">默认策略</div>
+			<div class="form-control-static" th:if="${job.misfirePolicy == '1'}">立即执行</div>
+			<div class="form-control-static" th:if="${job.misfirePolicy == '2'}">执行一次</div>
+			<div class="form-control-static" th:if="${job.misfirePolicy == '3'}">放弃执行</div>
+		</div>
+		<div class="form-group">
+			<label class="col-sm-3 control-label">并发执行:</label>
+			<div class="form-control-static" th:class="${job.concurrent == '0' ? 'label label-primary' : 'label label-danger'}" th:text="${job.concurrent == '0' ? '允许' : '禁止'}">
+			</div>
+		</div>
+		<div class="form-group">
+			<label class="col-sm-3 control-label">执行状态:</label>
+			<div class="form-control-static" th:class="${job.status == '0' ? 'label label-primary' : 'label label-danger'}" th:text="${job.status == '0' ? '正常' : '暂停'}">
+			</div>
+		</div>
+	</form>
+	
+    </div>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-quartz/src/main/resources/templates/monitor/job/edit.html b/ruoyi-quartz/src/main/resources/templates/monitor/job/edit.html
new file mode 100644
index 0000000..12ae1d7
--- /dev/null
+++ b/ruoyi-quartz/src/main/resources/templates/monitor/job/edit.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+	<th:block th:include="include :: header('修改定时任务')" />
+</head>
+<body class="white-bg">
+	<div class="wrapper wrapper-content animated fadeInRight ibox-content">
+		<form class="form-horizontal m" id="form-job-edit" th:object="${job}">
+			<input id="jobId" name="jobId" type="hidden" th:field="*{jobId}"/>
+			<input type="hidden" name="updateBy" th:value="${@permission.getPrincipalProperty('loginName')}">
+			<div class="form-group">
+				<label class="col-sm-3 control-label is-required">任务名称:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="jobName" id="jobName" th:field="*{jobName}" required>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">任务分组:</label>
+				<div class="col-sm-8">
+					<select name="jobGroup" class="form-control m-b" th:with="type=${@dict.getType('sys_job_group')}">
+		                <option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}" th:field="*{jobGroup}"></option>
+		            </select>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label is-required">调用目标字符串:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="invokeTarget" id="invokeTarget" th:field="*{invokeTarget}" required>
+				    <span class="help-block m-b-none"><i class="fa fa-info-circle"></i> Bean调用示例:ryTask.ryParams('ry')</span>
+				    <span class="help-block m-b-none"><i class="fa fa-info-circle"></i> Class类调用示例:com.ruoyi.quartz.task.RyTask.ryParams('ry')</span>
+				    <span class="help-block m-b-none"><i class="fa fa-info-circle"></i> 参数说明:支持字符串,布尔类型,长整型,浮点型,整型</span>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label is-required">cron表达式:</label>
+				<div class="col-sm-8">
+					<input class="form-control" type="text" name="cronExpression" id="cronExpression" th:field="*{cronExpression}" required>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">执行策略:</label>
+				<div class="col-sm-8">
+					<label class="radio-box"> <input type="radio" th:field="*{misfirePolicy}" name="misfirePolicy" value="1" /> 立即执行 </label> 
+					<label class="radio-box"> <input type="radio" th:field="*{misfirePolicy}" name="misfirePolicy" value="2" /> 执行一次 </label> 
+					<label class="radio-box"> <input type="radio" th:field="*{misfirePolicy}" name="misfirePolicy" value="3" /> 放弃执行 </label>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">并发执行:</label>
+				<div class="col-sm-8">
+					<label class="radio-box"> <input type="radio" th:field="*{concurrent}" name="concurrent" value="0"/> 允许 </label> 
+					<label class="radio-box"> <input type="radio" th:field="*{concurrent}" name="concurrent" value="1"/> 禁止 </label> 
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">状态:</label>
+				<div class="col-sm-8">
+					<div class="radio-box" th:each="dict : ${@dict.getType('sys_job_status')}">
+						<input type="radio" th:id="${dict.dictCode}" name="status" th:value="${dict.dictValue}" th:field="*{status}">
+						<label th:for="${dict.dictCode}" th:text="${dict.dictLabel}"></label>
+					</div>
+				</div>
+			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">备注:</label>
+				<div class="col-sm-8">
+					<textarea id="remark" name="remark" class="form-control">[[*{remark}]]</textarea>
+				</div>
+			</div>
+		</form>
+	</div>
+	<th:block th:include="include :: footer" />
+	<script type="text/javascript">
+		var prefix = ctx + "monitor/job";
+	
+		$("#form-job-edit").validate({
+			onkeyup: false,
+			rules:{
+				cronExpression:{
+					required:true,
+					remote: {
+	                    url: prefix + "/checkCronExpressionIsValid",
+	                    type: "post",
+	                    dataType: "json",
+	                    data: {
+	                        "cronExpression": function() {
+	                            return $.common.trim($("#cronExpression").val());
+	                        }
+	                    },
+	                    dataFilter: function(data, type) {
+	                    	return data;
+	                    }
+	                }
+				},
+			},
+			messages: {
+	            "cronExpression": {
+	                remote: "表达式不正确"
+	            }
+	        },
+	        focusCleanup: true
+		});
+		
+		function submitHandler() {
+	        if ($.validate.form()) {
+	        	$.operate.save(prefix + "/edit", $('#form-job-edit').serialize());
+	        }
+	    }
+	</script>
+</body>
+</html>
diff --git a/ruoyi-quartz/src/main/resources/templates/monitor/job/job.html b/ruoyi-quartz/src/main/resources/templates/monitor/job/job.html
new file mode 100644
index 0000000..de72e01
--- /dev/null
+++ b/ruoyi-quartz/src/main/resources/templates/monitor/job/job.html
@@ -0,0 +1,198 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('定时任务列表')" />
+</head>
+<body class="gray-bg">
+	<div class="container-div">
+		<div class="row">
+			<div class="col-sm-12 search-collapse">
+				<form id="job-form">
+					<div class="select-list">
+						<ul>
+							<li>
+								任务名称:<input type="text" name="jobName"/>
+							</li>
+							<li>
+								任务分组:<select name="jobGroup" th:with="type=${@dict.getType('sys_job_group')}">
+									<option value="">所有</option>
+									<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
+								</select>
+							</li>
+							<li>
+								任务状态:<select name="status" th:with="type=${@dict.getType('sys_job_status')}">
+									<option value="">所有</option>
+									<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
+								</select>
+							</li>
+							<li>
+								<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
+								<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
+							</li>
+						</ul>
+					</div>
+				</form>
+			</div>
+			
+			<div class="btn-group-sm" id="toolbar" role="group">
+				<a class="btn btn-success" onclick="$.operate.add()" shiro:hasPermission="monitor:job:add">
+	                <i class="fa fa-plus"></i> 新增
+	            </a>
+	            <a class="btn btn-primary single disabled" onclick="$.operate.edit()" shiro:hasPermission="monitor:job:edit">
+		            <i class="fa fa-edit"></i> 修改
+		        </a>
+				<a class="btn btn-danger multiple disabled" onclick="$.operate.removeAll()" shiro:hasPermission="monitor:job:remove">
+		            <i class="fa fa-remove"></i> 删除
+		        </a>
+		         <a class="btn btn-warning" onclick="$.table.exportExcel()" shiro:hasPermission="monitor:job:export">
+		            <i class="fa fa-download"></i> 导出
+		        </a>
+		        <a class="btn btn-primary" onclick="javascript:cron()">
+		            <i class="fa fa-code"></i> 生成表达式
+		        </a>
+		        <a class="btn btn-info" onclick="javascript:jobLog()" shiro:hasPermission="monitor:job:detail">
+		            <i class="fa fa-list"></i> 日志
+		        </a>
+	        </div>
+        
+	        <div class="col-sm-12 select-table table-striped">
+			    <table id="bootstrap-table"></table>
+			</div>
+		</div>
+	</div>
+	<th:block th:include="include :: footer" />
+	<script th:inline="javascript">
+        var detailFlag = [[${@permission.hasPermi('monitor:job:detail')}]];
+		var editFlag = [[${@permission.hasPermi('monitor:job:edit')}]];
+		var removeFlag = [[${@permission.hasPermi('monitor:job:remove')}]];
+		var statusFlag = [[${@permission.hasPermi('monitor:job:changeStatus')}]];
+		var datas = [[${@dict.getType('sys_job_group')}]];
+		var prefix = ctx + "monitor/job";
+
+		$(function() {
+		    var options = {
+		        url: prefix + "/list",
+		        detailUrl: prefix + "/detail/{id}",
+		        createUrl: prefix + "/add",
+		        updateUrl: prefix + "/edit/{id}",
+		        removeUrl: prefix + "/remove",
+		        exportUrl: prefix + "/export",
+		        sortName: "createTime",
+		        sortOrder: "desc",
+		        modalName: "任务",
+		        columns: [{
+		            checkbox: true
+		        },
+		        {
+		            field: 'jobId',
+		            title: '任务编号'
+		        },
+		        {
+		            field: 'jobName',
+		            title: '任务名称',
+		        },
+		        {
+		            field: 'jobGroup',
+		            title: '任务分组',
+		            formatter: function(value, row, index) {
+		            	return $.table.selectDictLabel(datas, value);
+		            }
+		        },
+		        {
+		            field: 'invokeTarget',
+		            title: '调用目标字符串',
+		            formatter: function(value, row, index) {
+                    	return $.table.tooltip(value);
+                    }
+		        },
+		        {
+		            field: 'cronExpression',
+		            title: '执行表达式'
+		        },
+		        {
+		        	visible: statusFlag == 'hidden' ? false : true,
+		        	title: '任务状态',
+		        	align: 'center',
+		        	formatter: function (value, row, index) {
+		        		return statusTools(row);
+		        	}
+		        },
+		        {
+		            field: 'createTime',
+		            title: '创建时间',
+		            sortable: true
+		        },
+		        {
+		            title: '操作',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		                var actions = [];
+		                actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:;" onclick="$.operate.edit(\'' + row.jobId + '\')"><i class="fa fa-edit"></i>编辑</a> ');
+		                actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:;" onclick="$.operate.remove(\'' + row.jobId + '\')"><i class="fa fa-remove"></i>删除</a> ');
+		                var more = [];
+		                more.push("<a class='btn btn-default btn-xs " + statusFlag + "' href='javascript:void(0)' onclick='run(" + row.jobId + ")'><i class='fa fa-play-circle-o'></i> 执行一次</a> ");
+		                more.push("<a class='btn btn-default btn-xs " + detailFlag + "' href='javascript:void(0)' onclick='$.operate.detail(" + row.jobId + ")'><i class='fa fa-search'></i>任务详细</a> ");
+		                more.push("<a class='btn btn-default btn-xs " + detailFlag + "' href='javascript:void(0)' onclick='jobLog(" + row.jobId + ")'><i class='fa fa-list'></i>调度日志</a>");
+		                actions.push('<a class="btn btn-info btn-xs" role="button" data-container="body" data-placement="left" data-toggle="popover" data-html="true" data-trigger="hover" data-content="' + more.join('') + '"><i class="fa fa-chevron-circle-right"></i>更多操作</a>');
+		                return actions.join('');
+		            }
+		        }]
+		    };
+		    $.table.init(options);
+		});
+        
+		/* 调度任务状态显示 */
+		function statusTools(row) {
+		    if (row.status == 1) {
+    			return '<i class=\"fa fa-toggle-off text-info fa-2x\" onclick="start(\'' + row.jobId + '\', \'' + row.jobGroup + '\')"></i> ';
+    		} else {
+    			return '<i class=\"fa fa-toggle-on text-info fa-2x\" onclick="stop(\'' + row.jobId + '\', \'' + row.jobGroup + '\')"></i> ';
+    		}
+		}
+		
+		/* 立即执行一次 */
+		function run(jobId) {
+			$.modal.confirm("确认要立即执行一次任务吗?", function() {
+				$.operate.post(prefix + "/run", { "jobId": jobId});
+		    })
+		}
+
+		/* 调度任务-停用 */
+		function stop(jobId, jobGroup) {
+			$.modal.confirm("确认要停用任务吗?", function() {
+				$.operate.post(prefix + "/changeStatus", { "jobId": jobId, "jobGroup": jobGroup, "status": 1 });
+		    })
+		}
+
+		/* 调度任务-启用 */
+		function start(jobId, jobGroup) {
+			$.modal.confirm("确认要启用任务吗?", function() {
+				$.operate.post(prefix + "/changeStatus", { "jobId": jobId, "jobGroup": jobGroup, "status": 0 });
+		    })
+		}
+
+		/* 调度日志查询 */
+		function jobLog(jobId) {
+		    var url = ctx + 'monitor/jobLog';
+		    if ($.common.isNotEmpty(jobId)) {
+		        url += '?jobId=' + jobId;
+		    }
+		    $.modal.openTab("调度日志", url);
+		}
+		
+		/* cron表达式生成 */
+		function cron() {
+		    var url = prefix + '/cron';
+            var height = $(window).height() - 50;
+            top.layer.open({
+                maxmin: true,
+                title: "Cron表达式生成器",
+                type: 2,
+                area: ['800px', height + "px" ], //宽高
+                shadeClose: true,
+                content: url
+            });
+		}
+	</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-quartz/src/main/resources/templates/monitor/job/jobLog.html b/ruoyi-quartz/src/main/resources/templates/monitor/job/jobLog.html
new file mode 100644
index 0000000..71028c6
--- /dev/null
+++ b/ruoyi-quartz/src/main/resources/templates/monitor/job/jobLog.html
@@ -0,0 +1,138 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('定时任务日志列表')" />
+</head>
+<body class="gray-bg">
+
+	<div class="container-div">
+		<div class="row">
+			<div class="col-sm-12 search-collapse">
+				<form id="jobLog-form">
+					<div class="select-list">
+						<ul>
+							<li>
+								任务名称:<input type="text" name="jobName" th:value="${job!=null?job.jobName:''}"/>
+							</li>
+							<li>
+								任务分组:<select name="jobGroup" th:with="type=${@dict.getType('sys_job_group')}">
+									<option value="">所有</option>
+									<th:block th:if="${job==null}"><option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option></th:block>
+									<th:block th:if="${job!=null}"><option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}" th:field="*{job.jobGroup}"></option></th:block>
+								</select>
+							</li>
+							<li>
+								执行状态:<select name="status" th:with="type=${@dict.getType('sys_common_status')}">
+									<option value="">所有</option>
+									<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
+								</select>
+							</li>
+							<li class="select-time">
+								<label>执行时间: </label>
+								<input type="text" class="time-input" id="startTime" placeholder="开始时间" name="params[beginTime]"/>
+								<span>-</span>
+								<input type="text" class="time-input" id="endTime" placeholder="结束时间" name="params[endTime]"/>
+							</li>
+							<li>
+								<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
+								<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
+							</li>
+						</ul>
+					</div>
+				</form>
+			</div>
+			
+			<div class="btn-group-sm" id="toolbar" role="group">
+				 <a class="btn btn-danger multiple disabled" onclick="$.operate.removeAll()" shiro:hasPermission="monitor:job:remove">
+	                <i class="fa fa-remove"></i> 删除
+	            </a>
+	            <a class="btn btn-danger" onclick="$.operate.clean()" shiro:hasPermission="monitor:job:remove">
+	                <i class="fa fa-trash"></i> 清空
+	            </a>
+	            <a class="btn btn-warning" onclick="$.table.exportExcel()" shiro:hasPermission="monitor:job:export">
+		            <i class="fa fa-download"></i> 导出
+		        </a>
+		        <a class="btn btn-danger" onclick="closeItem()">
+		            <i class="fa fa-reply-all"></i> 关闭
+		        </a>
+	        </div>
+	        
+	        <div class="col-sm-12 select-table table-striped">
+			    <table id="bootstrap-table"></table>
+			</div>
+		</div>
+	</div>
+	<th:block th:include="include :: footer" />
+	<script th:inline="javascript">
+		var detailFlag = [[${@permission.hasPermi('monitor:job:detail')}]];
+		var statusDatas = [[${@dict.getType('sys_common_status')}]];
+		var groupDatas = [[${@dict.getType('sys_job_group')}]];
+		var prefix = ctx + "monitor/jobLog";
+
+		$(function() {
+		    var options = {
+		        url: prefix + "/list",
+		        cleanUrl: prefix + "/clean",
+		        detailUrl: prefix + "/detail/{id}",
+		        removeUrl: prefix + "/remove",
+		        exportUrl: prefix + "/export",
+		        sortName: "createTime",
+		        sortOrder: "desc",
+		        modalName: "调度日志",
+		        columns: [{
+		            checkbox: true
+		        },
+		        {
+		            field: 'jobLogId',
+		            title: '日志编号'
+		        },
+		        {
+		            field: 'jobName',
+		            title: '任务名称'
+		        },
+		        {
+		            field: 'jobGroup',
+		            title: '任务分组',
+		            formatter: function(value, row, index) {
+		            	return $.table.selectDictLabel(groupDatas, value);
+		            }
+		        },
+		        {
+		            field: 'invokeTarget',
+		            title: '调用目标字符串',
+		            formatter: function(value, row, index) {
+                    	return $.table.tooltip(value);
+                    }
+		        },
+		        {
+		            field: 'jobMessage',
+		            title: '日志信息'
+		        },
+		        {
+		            field: 'status',
+		            title: '状态',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		            	return $.table.selectDictLabel(statusDatas, value);
+		            }
+		        },
+		        {
+		            field: 'createTime',
+		            title: '创建时间',
+		            sortable: true
+		        },
+		        {
+		            title: '操作',
+		            align: 'center',
+		            formatter: function(value, row, index) {
+		                var actions = [];
+		                actions.push('<a class="btn btn-warning btn-xs ' + detailFlag + '" href="javascript:void(0)" onclick="$.operate.detail(\'' + row.jobLogId + '\')"><i class="fa fa-search"></i>详细</a>');
+		                return actions.join('');
+		            }
+		        }]
+		    };
+		    $.table.init(options);
+		});
+	</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/ruoyi-system/pom.xml b/ruoyi-system/pom.xml
new file mode 100644
index 0000000..ecfe5aa
--- /dev/null
+++ b/ruoyi-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>ruoyi</artifactId>
+        <groupId>com.ruoyi</groupId>
+        <version>4.8.0</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>ruoyi-system</artifactId>
+
+    <description>
+        system系统模块
+    </description>
+
+    <dependencies>
+
+        <!-- 通用工具-->
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common</artifactId>
+        </dependency>
+
+    </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java
new file mode 100644
index 0000000..56f3767
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java
@@ -0,0 +1,110 @@
+package com.ruoyi.system.domain;
+
+import javax.validation.constraints.*;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.annotation.Excel.ColumnType;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * 参数配置表 sys_config
+ * 
+ * @author ruoyi
+ */
+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;
+
+    /** 系统内置(Y是 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/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysLogininfor.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysLogininfor.java
new file mode 100644
index 0000000..29b3af1
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysLogininfor.java
@@ -0,0 +1,159 @@
+package com.ruoyi.system.domain;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import java.util.Date;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.annotation.Excel.ColumnType;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * 系统访问记录表 sys_logininfor
+ * 
+ * @author ruoyi
+ */
+public class SysLogininfor extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** ID */
+    @Excel(name = "序号", cellType = ColumnType.NUMERIC)
+    private Long infoId;
+
+    /** 用户账号 */
+    @Excel(name = "用户账号")
+    private String loginName;
+
+    /** 登录状态 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;
+
+    /** 访问时间 */
+    @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 getLoginName()
+    {
+        return loginName;
+    }
+
+    public void setLoginName(String loginName)
+    {
+        this.loginName = loginName;
+    }
+
+    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;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("infoId", getInfoId())
+            .append("loginName", getLoginName())
+            .append("ipaddr", getIpaddr())
+            .append("loginLocation", getLoginLocation())
+            .append("browser", getBrowser())
+            .append("os", getOs())
+            .append("status", getStatus())
+            .append("msg", getMsg())
+            .append("loginTime", getLoginTime())
+            .toString();
+    }
+}
\ No newline at end of file
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java
new file mode 100644
index 0000000..8c07a54
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java
@@ -0,0 +1,102 @@
+package com.ruoyi.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.ruoyi.common.core.domain.BaseEntity;
+import com.ruoyi.common.xss.Xss;
+
+/**
+ * 通知公告表 sys_notice
+ * 
+ * @author ruoyi
+ */
+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正常 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/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOperLog.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOperLog.java
new file mode 100644
index 0000000..e758412
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOperLog.java
@@ -0,0 +1,292 @@
+package com.ruoyi.system.domain;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import java.util.Date;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.annotation.Excel.ColumnType;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * 操作日志记录表 oper_log
+ * 
+ * @author ruoyi
+ */
+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=生成代码,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正常 1异常) */
+    @Excel(name = "状态", readConverterExp = "0=正常,1=异常")
+    private Integer status;
+
+    /** 错误消息 */
+    @Excel(name = "错误消息")
+    private String errorMsg;
+
+    /** 操作时间 */
+    @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;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("operId", getOperId())
+            .append("title", getTitle())
+            .append("businessType", getBusinessType())
+            .append("businessTypes", getBusinessTypes())
+            .append("method", getMethod())
+            .append("requestMethod", getRequestMethod())
+            .append("operatorType", getOperatorType())
+            .append("operName", getOperName())
+            .append("deptName", getDeptName())
+            .append("operUrl", getOperUrl())
+            .append("operIp", getOperIp())
+            .append("operLocation", getOperLocation())
+            .append("operParam", getOperParam())
+            .append("status", getStatus())
+            .append("errorMsg", getErrorMsg())
+            .append("operTime", getOperTime())
+            .append("costTime", getCostTime())
+            .toString();
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysPost.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysPost.java
new file mode 100644
index 0000000..a172f66
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysPost.java
@@ -0,0 +1,122 @@
+package com.ruoyi.system.domain;
+
+import javax.validation.constraints.*;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.annotation.Excel.ColumnType;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * 岗位表 sys_post
+ * 
+ * @author ruoyi
+ */
+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 = "岗位排序", cellType = ColumnType.NUMERIC)
+    private String postSort;
+
+    /** 状态(0正常 1停用) */
+    @Excel(name = "状态", readConverterExp = "0=正常,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;
+    }
+
+    @NotBlank(message = "显示顺序不能为空")
+    public String getPostSort()
+    {
+        return postSort;
+    }
+
+    public void setPostSort(String 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/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleDept.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleDept.java
new file mode 100644
index 0000000..47b21bf
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleDept.java
@@ -0,0 +1,46 @@
+package com.ruoyi.system.domain;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+/**
+ * 角色和部门关联 sys_role_dept
+ * 
+ * @author ruoyi
+ */
+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/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleMenu.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleMenu.java
new file mode 100644
index 0000000..de10a74
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleMenu.java
@@ -0,0 +1,46 @@
+package com.ruoyi.system.domain;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+/**
+ * 角色和菜单关联 sys_role_menu
+ * 
+ * @author ruoyi
+ */
+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/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnline.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnline.java
new file mode 100644
index 0000000..4ecf07a
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnline.java
@@ -0,0 +1,177 @@
+package com.ruoyi.system.domain;
+
+import java.util.Date;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.core.domain.BaseEntity;
+import com.ruoyi.common.enums.OnlineStatus;
+
+/**
+ * 当前在线会话 sys_user_online
+ * 
+ * @author ruoyi
+ */
+public class SysUserOnline extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+    
+    /** 用户会话id */
+    private String sessionId;
+
+    /** 部门名称 */
+    private String deptName;
+
+    /** 登录名称 */
+    private String loginName;
+
+    /** 登录IP地址 */
+    private String ipaddr;
+
+    /** 登录地址 */
+    private String loginLocation;
+
+    /** 浏览器类型 */
+    private String browser;
+
+    /** 操作系统 */
+    private String os;
+
+    /** session创建时间 */
+    private Date startTimestamp;
+
+    /** session最后访问时间 */
+    private Date lastAccessTime;
+
+    /** 超时时间,单位为毫秒 */
+    private Long expireTime;
+
+    /** 在线状态 */
+    private OnlineStatus status = OnlineStatus.on_line;
+
+    public String getSessionId()
+    {
+        return sessionId;
+    }
+
+    public void setSessionId(String sessionId)
+    {
+        this.sessionId = sessionId;
+    }
+
+    public String getDeptName()
+    {
+        return deptName;
+    }
+
+    public void setDeptName(String deptName)
+    {
+        this.deptName = deptName;
+    }
+
+    public String getLoginName()
+    {
+        return loginName;
+    }
+
+    public void setLoginName(String loginName)
+    {
+        this.loginName = loginName;
+    }
+
+    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 Date getStartTimestamp()
+    {
+        return startTimestamp;
+    }
+
+    public void setStartTimestamp(Date startTimestamp)
+    {
+        this.startTimestamp = startTimestamp;
+    }
+
+    public Date getLastAccessTime()
+    {
+        return lastAccessTime;
+    }
+
+    public void setLastAccessTime(Date lastAccessTime)
+    {
+        this.lastAccessTime = lastAccessTime;
+    }
+
+    public Long getExpireTime()
+    {
+        return expireTime;
+    }
+
+    public void setExpireTime(Long expireTime)
+    {
+        this.expireTime = expireTime;
+    }
+
+    public OnlineStatus getStatus()
+    {
+        return status;
+    }
+
+    public void setStatus(OnlineStatus status)
+    {
+        this.status = status;
+    }
+    
+	@Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("sessionId", getSessionId())
+            .append("loginName", getLoginName())
+            .append("deptName", getDeptName())
+            .append("ipaddr", getIpaddr())
+            .append("loginLocation", getLoginLocation())
+            .append("browser", getBrowser())
+            .append("os", getOs())
+            .append("status", getStatus())
+            .append("startTimestamp", getStartTimestamp())
+            .append("lastAccessTime", getLastAccessTime())
+            .append("expireTime", getExpireTime())
+            .toString();
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserPost.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserPost.java
new file mode 100644
index 0000000..6e8c416
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserPost.java
@@ -0,0 +1,46 @@
+package com.ruoyi.system.domain;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+/**
+ * 用户和岗位关联 sys_user_post
+ * 
+ * @author ruoyi
+ */
+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/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserRole.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserRole.java
new file mode 100644
index 0000000..4d15810
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserRole.java
@@ -0,0 +1,46 @@
+package com.ruoyi.system.domain;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+/**
+ * 用户和角色关联 sys_user_role
+ * 
+ * @author ruoyi
+ */
+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/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysConfigMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysConfigMapper.java
new file mode 100644
index 0000000..84c949c
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysConfigMapper.java
@@ -0,0 +1,76 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import com.ruoyi.system.domain.SysConfig;
+
+/**
+ * 参数配置 数据层
+ * 
+ * @author ruoyi
+ */
+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 参数主键
+     * @return 结果
+     */
+    public int deleteConfigById(Long configId);
+
+    /**
+     * 批量删除参数配置
+     * 
+     * @param configIds 需要删除的数据ID
+     * @return 结果
+     */
+    public int deleteConfigByIds(String[] configIds);
+}
\ No newline at end of file
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java
new file mode 100644
index 0000000..af2b705
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java
@@ -0,0 +1,117 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import org.apache.ibatis.annotations.Param;
+import com.ruoyi.common.core.domain.entity.SysDept;
+
+/**
+ * 部门管理 数据层
+ * 
+ * @author ruoyi
+ */
+public interface SysDeptMapper
+{
+    /**
+     * 查询下级部门数量
+     * 
+     * @param dept 部门信息
+     * @return 结果
+     */
+    public int selectDeptCount(SysDept dept);
+
+    /**
+     * 查询部门是否存在用户
+     * 
+     * @param deptId 部门ID
+     * @return 结果
+     */
+    public int checkDeptExistUser(Long deptId);
+
+    /**
+     * 查询部门管理数据
+     * 
+     * @param dept 部门信息
+     * @return 部门信息集合
+     */
+    public List<SysDept> selectDeptList(SysDept dept);
+
+    /**
+     * 删除部门管理信息
+     * 
+     * @param deptId 部门ID
+     * @return 结果
+     */
+    public int deleteDeptById(Long deptId);
+
+    /**
+     * 新增部门信息
+     * 
+     * @param dept 部门信息
+     * @return 结果
+     */
+    public int insertDept(SysDept dept);
+
+    /**
+     * 修改部门信息
+     * 
+     * @param dept 部门信息
+     * @return 结果
+     */
+    public int updateDept(SysDept dept);
+
+    /**
+     * 修改子元素关系
+     * 
+     * @param depts 子元素
+     * @return 结果
+     */
+    public int updateDeptChildren(@Param("depts") List<SysDept> depts);
+
+    /**
+     * 根据部门ID查询信息
+     * 
+     * @param deptId 部门ID
+     * @return 部门信息
+     */
+    public SysDept selectDeptById(Long deptId);
+
+    /**
+     * 校验部门名称是否唯一
+     * 
+     * @param deptName 部门名称
+     * @param parentId 父部门ID
+     * @return 结果
+     */
+    public SysDept checkDeptNameUnique(@Param("deptName") String deptName, @Param("parentId") Long parentId);
+
+    /**
+     * 根据角色ID查询部门
+     *
+     * @param roleId 角色ID
+     * @return 部门列表
+     */
+    public List<String> selectRoleDeptTree(Long roleId);
+
+    /**
+     * 修改所在部门正常状态
+     * 
+     * @param deptIds 部门ID组
+     */
+    public void updateDeptStatusNormal(Long[] deptIds);
+
+    /**
+     * 根据ID查询所有子部门
+     * 
+     * @param deptId 部门ID
+     * @return 部门列表
+     */
+    public List<SysDept> selectChildrenDeptById(Long deptId);
+
+    /**
+     * 根据ID查询所有子部门(正常状态)
+     * 
+     * @param deptId 部门ID
+     * @return 子部门数
+     */
+    public int selectNormalChildrenDeptById(Long deptId);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictDataMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictDataMapper.java
new file mode 100644
index 0000000..368252a
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictDataMapper.java
@@ -0,0 +1,95 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import org.apache.ibatis.annotations.Param;
+import com.ruoyi.common.core.domain.entity.SysDictData;
+
+/**
+ * 字典表 数据层
+ * 
+ * @author ruoyi
+ */
+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 ids 需要删除的数据
+     * @return 结果
+     */
+    public int deleteDictDataByIds(String[] ids);
+
+    /**
+     * 新增字典数据信息
+     * 
+     * @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/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictTypeMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictTypeMapper.java
new file mode 100644
index 0000000..25be4f4
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictTypeMapper.java
@@ -0,0 +1,83 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import com.ruoyi.common.core.domain.entity.SysDictType;
+
+/**
+ * 字典表 数据层
+ * 
+ * @author ruoyi
+ */
+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 ids 需要删除的数据
+     * @return 结果
+     */
+    public int deleteDictTypeByIds(Long[] ids);
+
+    /**
+     * 新增字典类型信息
+     * 
+     * @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/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysLogininforMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysLogininforMapper.java
new file mode 100644
index 0000000..7ee47dc
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysLogininforMapper.java
@@ -0,0 +1,42 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import com.ruoyi.system.domain.SysLogininfor;
+
+/**
+ * 系统访问日志情况信息 数据层
+ * 
+ * @author ruoyi
+ */
+public interface SysLogininforMapper
+{
+    /**
+     * 新增系统登录日志
+     * 
+     * @param logininfor 访问日志对象
+     */
+    public void insertLogininfor(SysLogininfor logininfor);
+
+    /**
+     * 查询系统登录日志集合
+     * 
+     * @param logininfor 访问日志对象
+     * @return 登录记录集合
+     */
+    public List<SysLogininfor> selectLogininforList(SysLogininfor logininfor);
+
+    /**
+     * 批量删除系统登录日志
+     * 
+     * @param ids 需要删除的数据
+     * @return 结果
+     */
+    public int deleteLogininforByIds(String[] ids);
+
+    /**
+     * 清空系统登录日志
+     * 
+     * @return 结果
+     */
+    public int cleanLogininfor();
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java
new file mode 100644
index 0000000..e07903f
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java
@@ -0,0 +1,132 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import org.apache.ibatis.annotations.Param;
+import com.ruoyi.common.core.domain.entity.SysMenu;
+
+/**
+ * 菜单表 数据层
+ * 
+ * @author ruoyi
+ */
+public interface SysMenuMapper
+{
+    /**
+     * 查询系统所有菜单(含按钮)
+     * 
+     * @return 菜单列表
+     */
+    public List<SysMenu> selectMenuAll();
+
+    /**
+     * 根据用户ID查询菜单
+     * 
+     * @param userId 用户ID
+     * @return 菜单列表
+     */
+    public List<SysMenu> selectMenuAllByUserId(Long userId);
+
+    /**
+     * 查询系统正常显示菜单(不含按钮)
+     * 
+     * @return 菜单列表
+     */
+    public List<SysMenu> selectMenuNormalAll();
+
+    /**
+     * 根据用户ID查询菜单
+     * 
+     * @param userId 用户ID
+     * @return 菜单列表
+     */
+    public List<SysMenu> selectMenusByUserId(Long userId);
+
+    /**
+     * 根据用户ID查询权限
+     * 
+     * @param userId 用户ID
+     * @return 权限列表
+     */
+    public List<String> selectPermsByUserId(Long userId);
+
+    /**
+     * 根据角色ID查询权限
+     * 
+     * @param roleId 角色ID
+     * @return 权限列表
+     */
+    public List<String> selectPermsByRoleId(Long roleId);
+
+    /**
+     * 根据角色ID查询菜单
+     * 
+     * @param roleId 角色ID
+     * @return 菜单列表
+     */
+    public List<String> selectMenuTree(Long roleId);
+
+    /**
+     * 查询系统菜单列表
+     * 
+     * @param menu 菜单信息
+     * @return 菜单列表
+     */
+    public List<SysMenu> selectMenuList(SysMenu menu);
+
+    /**
+     * 查询系统菜单列表
+     * 
+     * @param menu 菜单信息
+     * @return 菜单列表
+     */
+    public List<SysMenu> selectMenuListByUserId(SysMenu menu);
+
+    /**
+     * 删除菜单管理信息
+     * 
+     * @param menuId 菜单ID
+     * @return 结果
+     */
+    public int deleteMenuById(Long menuId);
+
+    /**
+     * 根据菜单ID查询信息
+     * 
+     * @param menuId 菜单ID
+     * @return 菜单信息
+     */
+    public SysMenu selectMenuById(Long menuId);
+
+    /**
+     * 查询菜单数量
+     * 
+     * @param parentId 菜单父ID
+     * @return 结果
+     */
+    public int selectCountMenuByParentId(Long parentId);
+
+    /**
+     * 新增菜单信息
+     * 
+     * @param menu 菜单信息
+     * @return 结果
+     */
+    public int insertMenu(SysMenu menu);
+
+    /**
+     * 修改菜单信息
+     * 
+     * @param menu 菜单信息
+     * @return 结果
+     */
+    public int updateMenu(SysMenu menu);
+
+    /**
+     * 校验菜单名称是否唯一
+     * 
+     * @param menuName 菜单名称
+     * @param parentId 父菜单ID
+     * @return 结果
+     */
+    public SysMenu checkMenuNameUnique(@Param("menuName") String menuName, @Param("parentId") Long parentId);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysNoticeMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysNoticeMapper.java
new file mode 100644
index 0000000..dd402e2
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysNoticeMapper.java
@@ -0,0 +1,52 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import com.ruoyi.system.domain.SysNotice;
+
+/**
+ * 公告 数据层
+ * 
+ * @author ruoyi
+ */
+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 noticeIds 需要删除的数据ID
+     * @return 结果
+     */
+    public int deleteNoticeByIds(String[] noticeIds);
+}
\ No newline at end of file
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOperLogMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOperLogMapper.java
new file mode 100644
index 0000000..b40bd29
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOperLogMapper.java
@@ -0,0 +1,48 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import com.ruoyi.system.domain.SysOperLog;
+
+/**
+ * 操作日志 数据层
+ * 
+ * @author ruoyi
+ */
+public interface SysOperLogMapper
+{
+    /**
+     * 新增操作日志
+     * 
+     * @param operLog 操作日志对象
+     */
+    public void insertOperlog(SysOperLog operLog);
+
+    /**
+     * 查询系统操作日志集合
+     * 
+     * @param operLog 操作日志对象
+     * @return 操作日志集合
+     */
+    public List<SysOperLog> selectOperLogList(SysOperLog operLog);
+    
+    /**
+     * 批量删除系统操作日志
+     * 
+     * @param ids 需要删除的数据
+     * @return 结果
+     */
+    public int deleteOperLogByIds(String[] ids);
+    
+    /**
+     * 查询操作日志详细
+     * 
+     * @param operId 操作ID
+     * @return 操作日志对象
+     */
+    public SysOperLog selectOperLogById(Long operId);
+    
+    /**
+     * 清空操作日志
+     */
+    public void cleanOperLog();
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysPostMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysPostMapper.java
new file mode 100644
index 0000000..188f335
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysPostMapper.java
@@ -0,0 +1,83 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import com.ruoyi.system.domain.SysPost;
+
+/**
+ * 岗位信息 数据层
+ * 
+ * @author ruoyi
+ */
+public interface SysPostMapper
+{
+    /**
+     * 查询岗位数据集合
+     * 
+     * @param post 岗位信息
+     * @return 岗位数据集合
+     */
+    public List<SysPost> selectPostList(SysPost post);
+
+    /**
+     * 查询所有岗位
+     * 
+     * @return 岗位列表
+     */
+    public List<SysPost> selectPostAll();
+
+    /**
+     * 根据用户ID查询岗位
+     * 
+     * @param userId 用户ID
+     * @return 岗位列表
+     */
+    public List<SysPost> selectPostsByUserId(Long userId);
+
+    /**
+     * 通过岗位ID查询岗位信息
+     * 
+     * @param postId 岗位ID
+     * @return 角色对象信息
+     */
+    public SysPost selectPostById(Long postId);
+
+    /**
+     * 批量删除岗位信息
+     * 
+     * @param ids 需要删除的数据ID
+     * @return 结果
+     */
+    public int deletePostByIds(Long[] ids);
+
+    /**
+     * 修改岗位信息
+     * 
+     * @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/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleDeptMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleDeptMapper.java
new file mode 100644
index 0000000..f9d3a2f
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleDeptMapper.java
@@ -0,0 +1,44 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import com.ruoyi.system.domain.SysRoleDept;
+
+/**
+ * 角色与部门关联表 数据层
+ * 
+ * @author ruoyi
+ */
+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/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java
new file mode 100644
index 0000000..78a3ec7
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java
@@ -0,0 +1,84 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import com.ruoyi.common.core.domain.entity.SysRole;
+
+/**
+ * 角色表 数据层
+ * 
+ * @author ruoyi
+ */
+public interface SysRoleMapper
+{
+    /**
+     * 根据条件分页查询角色数据
+     * 
+     * @param role 角色信息
+     * @return 角色数据集合信息
+     */
+    public List<SysRole> selectRoleList(SysRole role);
+
+    /**
+     * 根据用户ID查询角色
+     * 
+     * @param userId 用户ID
+     * @return 角色列表
+     */
+    public List<SysRole> selectRolesByUserId(Long userId);
+
+    /**
+     * 通过角色ID查询角色
+     * 
+     * @param roleId 角色ID
+     * @return 角色对象信息
+     */
+    public SysRole selectRoleById(Long roleId);
+
+    /**
+     * 通过角色ID删除角色
+     * 
+     * @param roleId 角色ID
+     * @return 结果
+     */
+    public int deleteRoleById(Long roleId);
+
+    /**
+     * 批量角色用户信息
+     * 
+     * @param ids 需要删除的数据ID
+     * @return 结果
+     */
+    public int deleteRoleByIds(Long[] ids);
+
+    /**
+     * 修改角色信息
+     * 
+     * @param role 角色信息
+     * @return 结果
+     */
+    public int updateRole(SysRole role);
+
+    /**
+     * 新增角色信息
+     * 
+     * @param role 角色信息
+     * @return 结果
+     */
+    public int insertRole(SysRole role);
+
+    /**
+     * 校验角色名称是否唯一
+     * 
+     * @param roleName 角色名称
+     * @return 角色信息
+     */
+    public SysRole checkRoleNameUnique(String roleName);
+    
+    /**
+     * 校验角色权限是否唯一
+     * 
+     * @param roleKey 角色权限
+     * @return 角色信息
+     */
+    public SysRole checkRoleKeyUnique(String roleKey);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMenuMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMenuMapper.java
new file mode 100644
index 0000000..9b88796
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMenuMapper.java
@@ -0,0 +1,44 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import com.ruoyi.system.domain.SysRoleMenu;
+
+/**
+ * 角色与菜单关联表 数据层
+ * 
+ * @author ruoyi
+ */
+public interface SysRoleMenuMapper
+{
+    /**
+     * 通过角色ID删除角色和菜单关联
+     * 
+     * @param roleId 角色ID
+     * @return 结果
+     */
+    public int deleteRoleMenuByRoleId(Long roleId);
+    
+    /**
+     * 批量删除角色菜单关联信息
+     * 
+     * @param ids 需要删除的数据ID
+     * @return 结果
+     */
+    public int deleteRoleMenu(Long[] ids);
+    
+    /**
+     * 查询菜单使用数量
+     * 
+     * @param menuId 菜单ID
+     * @return 结果
+     */
+    public int selectCountRoleMenuByMenuId(Long menuId);
+    
+    /**
+     * 批量新增角色菜单信息
+     * 
+     * @param roleMenuList 角色菜单列表
+     * @return 结果
+     */
+    public int batchRoleMenu(List<SysRoleMenu> roleMenuList);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java
new file mode 100644
index 0000000..309d88e
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java
@@ -0,0 +1,124 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import com.ruoyi.common.core.domain.entity.SysUser;
+
+/**
+ * 用户表 数据层
+ * 
+ * @author ruoyi
+ */
+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 selectUserByLoginName(String userName);
+
+    /**
+     * 通过手机号码查询用户
+     * 
+     * @param phoneNumber 手机号码
+     * @return 用户对象信息
+     */
+    public SysUser selectUserByPhoneNumber(String phoneNumber);
+
+    /**
+     * 通过邮箱查询用户
+     * 
+     * @param email 邮箱
+     * @return 用户对象信息
+     */
+    public SysUser selectUserByEmail(String email);
+
+    /**
+     * 通过用户ID查询用户
+     * 
+     * @param userId 用户ID
+     * @return 用户对象信息
+     */
+    public SysUser selectUserById(Long userId);
+
+    /**
+     * 通过用户ID删除用户
+     * 
+     * @param userId 用户ID
+     * @return 结果
+     */
+    public int deleteUserById(Long userId);
+
+    /**
+     * 批量删除用户信息
+     * 
+     * @param ids 需要删除的数据ID
+     * @return 结果
+     */
+    public int deleteUserByIds(Long[] ids);
+
+    /**
+     * 修改用户信息
+     * 
+     * @param user 用户信息
+     * @return 结果
+     */
+    public int updateUser(SysUser user);
+
+    /**
+     * 新增用户信息
+     * 
+     * @param user 用户信息
+     * @return 结果
+     */
+    public int insertUser(SysUser user);
+
+    /**
+     * 校验用户名称是否唯一
+     * 
+     * @param loginName 登录名称
+     * @return 结果
+     */
+    public SysUser checkLoginNameUnique(String loginName);
+
+    /**
+     * 校验手机号码是否唯一
+     *
+     * @param phonenumber 手机号码
+     * @return 结果
+     */
+    public SysUser checkPhoneUnique(String phonenumber);
+
+    /**
+     * 校验email是否唯一
+     *
+     * @param email 用户邮箱
+     * @return 结果
+     */
+    public SysUser checkEmailUnique(String email);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserOnlineMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserOnlineMapper.java
new file mode 100644
index 0000000..5bd68ed
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserOnlineMapper.java
@@ -0,0 +1,52 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import com.ruoyi.system.domain.SysUserOnline;
+
+/**
+ * 在线用户 数据层
+ * 
+ * @author ruoyi
+ */
+public interface SysUserOnlineMapper
+{
+    /**
+     * 通过会话序号查询信息
+     * 
+     * @param sessionId 会话ID
+     * @return 在线用户信息
+     */
+    public SysUserOnline selectOnlineById(String sessionId);
+
+    /**
+     * 通过会话序号删除信息
+     * 
+     * @param sessionId 会话ID
+     * @return 在线用户信息
+     */
+    public int deleteOnlineById(String sessionId);
+
+    /**
+     * 保存会话信息
+     * 
+     * @param online 会话信息
+     * @return 结果
+     */
+    public int saveOnline(SysUserOnline online);
+
+    /**
+     * 查询会话集合
+     * 
+     * @param userOnline 会话参数
+     * @return 会话集合
+     */
+    public List<SysUserOnline> selectUserOnlineList(SysUserOnline userOnline);
+
+    /**
+     * 查询过期会话集合
+     * 
+     * @param lastAccessTime 过期时间
+     * @return 会话集合
+     */
+    public List<SysUserOnline> selectOnlineByExpired(String lastAccessTime);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserPostMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserPostMapper.java
new file mode 100644
index 0000000..ec094ca
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserPostMapper.java
@@ -0,0 +1,44 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import com.ruoyi.system.domain.SysUserPost;
+
+/**
+ * 用户与岗位关联表 数据层
+ * 
+ * @author ruoyi
+ */
+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/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java
new file mode 100644
index 0000000..669d1ec
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java
@@ -0,0 +1,70 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import org.apache.ibatis.annotations.Param;
+import com.ruoyi.system.domain.SysUserRole;
+
+/**
+ * 用户与角色关联表 数据层
+ * 
+ * @author ruoyi
+ */
+public interface SysUserRoleMapper
+{
+    /**
+     * 通过用户ID查询用户和角色关联
+     * 
+     * @param userId 用户ID
+     * @return 用户和角色关联列表
+     */
+    public List<SysUserRole> selectUserRoleByUserId(Long userId);
+
+    /**
+     * 通过用户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/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java
new file mode 100644
index 0000000..e1c553c
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java
@@ -0,0 +1,82 @@
+package com.ruoyi.system.service;
+
+import java.util.List;
+import com.ruoyi.system.domain.SysConfig;
+
+/**
+ * 参数配置 服务层
+ * 
+ * @author ruoyi
+ */
+public interface ISysConfigService
+{
+    /**
+     * 查询参数配置信息
+     * 
+     * @param configId 参数配置ID
+     * @return 参数配置信息
+     */
+    public SysConfig selectConfigById(Long configId);
+
+    /**
+     * 根据键名查询参数配置信息
+     * 
+     * @param configKey 参数键名
+     * @return 参数键值
+     */
+    public String selectConfigByKey(String configKey);
+
+    /**
+     * 查询参数配置列表
+     * 
+     * @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 ids 需要删除的数据ID
+     */
+    public void deleteConfigByIds(String ids);
+
+    /**
+     * 加载参数缓存数据
+     */
+    public void loadingConfigCache();
+
+    /**
+     * 清空参数缓存数据
+     */
+    public void clearConfigCache();
+
+    /**
+     * 重置参数缓存数据
+     */
+    public void resetConfigCache();
+
+    /**
+     * 校验参数键名是否唯一
+     * 
+     * @param config 参数信息
+     * @return 结果
+     */
+    public boolean checkConfigKeyUnique(SysConfig config);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java
new file mode 100644
index 0000000..10ce107
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java
@@ -0,0 +1,117 @@
+package com.ruoyi.system.service;
+
+import java.util.List;
+import com.ruoyi.common.core.domain.Ztree;
+import com.ruoyi.common.core.domain.entity.SysDept;
+import com.ruoyi.common.core.domain.entity.SysRole;
+
+/**
+ * 部门管理 服务层
+ * 
+ * @author ruoyi
+ */
+public interface ISysDeptService
+{
+    /**
+     * 查询部门管理数据
+     * 
+     * @param dept 部门信息
+     * @return 部门信息集合
+     */
+    public List<SysDept> selectDeptList(SysDept dept);
+
+    /**
+     * 查询部门管理树
+     * 
+     * @param dept 部门信息
+     * @return 所有部门信息
+     */
+    public List<Ztree> selectDeptTree(SysDept dept);
+
+    /**
+     * 查询部门管理树(排除下级)
+     * 
+     * @param dept 部门信息
+     * @return 所有部门信息
+     */
+    public List<Ztree> selectDeptTreeExcludeChild(SysDept dept);
+
+    /**
+     * 根据角色ID查询菜单
+     *
+     * @param role 角色对象
+     * @return 菜单列表
+     */
+    public List<Ztree> roleDeptTreeData(SysRole role);
+
+    /**
+     * 根据父部门ID查询下级部门数量
+     * 
+     * @param parentId 父部门ID
+     * @return 结果
+     */
+    public int selectDeptCount(Long parentId);
+
+    /**
+     * 查询部门是否存在用户
+     * 
+     * @param deptId 部门ID
+     * @return 结果 true 存在 false 不存在
+     */
+    public boolean checkDeptExistUser(Long deptId);
+
+    /**
+     * 删除部门管理信息
+     * 
+     * @param deptId 部门ID
+     * @return 结果
+     */
+    public int deleteDeptById(Long deptId);
+
+    /**
+     * 新增保存部门信息
+     * 
+     * @param dept 部门信息
+     * @return 结果
+     */
+    public int insertDept(SysDept dept);
+
+    /**
+     * 修改保存部门信息
+     * 
+     * @param dept 部门信息
+     * @return 结果
+     */
+    public int updateDept(SysDept dept);
+
+    /**
+     * 根据部门ID查询信息
+     * 
+     * @param deptId 部门ID
+     * @return 部门信息
+     */
+    public SysDept selectDeptById(Long deptId);
+
+    /**
+     * 根据ID查询所有子部门(正常状态)
+     * 
+     * @param deptId 部门ID
+     * @return 子部门数
+     */
+    public int selectNormalChildrenDeptById(Long deptId);
+
+    /**
+     * 校验部门名称是否唯一
+     * 
+     * @param dept 部门信息
+     * @return 结果
+     */
+    public boolean checkDeptNameUnique(SysDept dept);
+
+    /**
+     * 校验部门是否有数据权限
+     * 
+     * @param deptId 部门id
+     */
+    public void checkDeptDataScope(Long deptId);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictDataService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictDataService.java
new file mode 100644
index 0000000..efb6bdd
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictDataService.java
@@ -0,0 +1,60 @@
+package com.ruoyi.system.service;
+
+import java.util.List;
+import com.ruoyi.common.core.domain.entity.SysDictData;
+
+/**
+ * 字典 业务层
+ * 
+ * @author ruoyi
+ */
+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 ids 需要删除的数据
+     */
+    public void deleteDictDataByIds(String ids);
+
+    /**
+     * 新增保存字典数据信息
+     * 
+     * @param dictData 字典数据信息
+     * @return 结果
+     */
+    public int insertDictData(SysDictData dictData);
+
+    /**
+     * 修改保存字典数据信息
+     * 
+     * @param dictData 字典数据信息
+     * @return 结果
+     */
+    public int updateDictData(SysDictData dictData);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java
new file mode 100644
index 0000000..126d258
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java
@@ -0,0 +1,107 @@
+package com.ruoyi.system.service;
+
+import java.util.List;
+import com.ruoyi.common.core.domain.Ztree;
+import com.ruoyi.common.core.domain.entity.SysDictData;
+import com.ruoyi.common.core.domain.entity.SysDictType;
+
+/**
+ * 字典 业务层
+ * 
+ * @author ruoyi
+ */
+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 ids 需要删除的数据
+     */
+    public void deleteDictTypeByIds(String ids);
+
+    /**
+     * 加载字典缓存数据
+     */
+    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);
+
+    /**
+     * 查询字典类型树
+     * 
+     * @param dictType 字典类型
+     * @return 所有字典类型
+     */
+    public List<Ztree> selectDictTree(SysDictType dictType);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysLogininforService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysLogininforService.java
new file mode 100644
index 0000000..ea99dff
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysLogininforService.java
@@ -0,0 +1,40 @@
+package com.ruoyi.system.service;
+
+import java.util.List;
+import com.ruoyi.system.domain.SysLogininfor;
+
+/**
+ * 系统访问日志情况信息 服务层
+ * 
+ * @author ruoyi
+ */
+public interface ISysLogininforService
+{
+    /**
+     * 新增系统登录日志
+     * 
+     * @param logininfor 访问日志对象
+     */
+    public void insertLogininfor(SysLogininfor logininfor);
+
+    /**
+     * 查询系统登录日志集合
+     * 
+     * @param logininfor 访问日志对象
+     * @return 登录记录集合
+     */
+    public List<SysLogininfor> selectLogininforList(SysLogininfor logininfor);
+
+    /**
+     * 批量删除系统登录日志
+     * 
+     * @param ids 需要删除的数据
+     * @return 结果
+     */
+    public int deleteLogininforByIds(String ids);
+
+    /**
+     * 清空系统登录日志
+     */
+    public void cleanLogininfor();
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java
new file mode 100644
index 0000000..d6db936
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java
@@ -0,0 +1,139 @@
+package com.ruoyi.system.service;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import com.ruoyi.common.core.domain.Ztree;
+import com.ruoyi.common.core.domain.entity.SysMenu;
+import com.ruoyi.common.core.domain.entity.SysRole;
+import com.ruoyi.common.core.domain.entity.SysUser;
+
+/**
+ * 菜单 业务层
+ * 
+ * @author ruoyi
+ */
+public interface ISysMenuService
+{
+    /**
+     * 根据用户ID查询菜单
+     * 
+     * @param user 用户信息
+     * @return 菜单列表
+     */
+    public List<SysMenu> selectMenusByUser(SysUser user);
+
+    /**
+     * 查询系统菜单列表
+     * 
+     * @param menu 菜单信息
+     * @param userId 用户ID
+     * @return 菜单列表
+     */
+    public List<SysMenu> selectMenuList(SysMenu menu, Long userId);
+
+    /**
+     * 查询菜单集合
+     * 
+     * @param userId 用户ID
+     * @return 所有菜单信息
+     */
+    public List<SysMenu> selectMenuAll(Long userId);
+
+    /**
+     * 根据用户ID查询权限
+     * 
+     * @param userId 用户ID
+     * @return 权限列表
+     */
+    public Set<String> selectPermsByUserId(Long userId);
+
+    /**
+     * 根据角色ID查询权限
+     * 
+     * @param roleId 角色ID
+     * @return 权限列表
+     */
+    public Set<String> selectPermsByRoleId(Long roleId);
+
+    /**
+     * 根据角色ID查询菜单
+     * 
+     * @param role 角色对象
+     * @param userId 用户ID
+     * @return 菜单列表
+     */
+    public List<Ztree> roleMenuTreeData(SysRole role, Long userId);
+
+    /**
+     * 查询所有菜单信息
+     * 
+     * @param userId 用户ID
+     * @return 菜单列表
+     */
+    public List<Ztree> menuTreeData(Long userId);
+
+    /**
+     * 查询系统所有权限
+     * 
+     * @param userId 用户ID
+     * @return 权限列表
+     */
+    public Map<String, String> selectPermsAll(Long userId);
+
+    /**
+     * 删除菜单管理信息
+     * 
+     * @param menuId 菜单ID
+     * @return 结果
+     */
+    public int deleteMenuById(Long menuId);
+
+    /**
+     * 根据菜单ID查询信息
+     * 
+     * @param menuId 菜单ID
+     * @return 菜单信息
+     */
+    public SysMenu selectMenuById(Long menuId);
+
+    /**
+     * 查询菜单数量
+     * 
+     * @param parentId 菜单父ID
+     * @return 结果
+     */
+    public int selectCountMenuByParentId(Long parentId);
+
+    /**
+     * 查询菜单使用数量
+     * 
+     * @param menuId 菜单ID
+     * @return 结果
+     */
+    public int selectCountRoleMenuByMenuId(Long menuId);
+
+    /**
+     * 新增保存菜单信息
+     * 
+     * @param menu 菜单信息
+     * @return 结果
+     */
+    public int insertMenu(SysMenu menu);
+
+    /**
+     * 修改保存菜单信息
+     * 
+     * @param menu 菜单信息
+     * @return 结果
+     */
+    public int updateMenu(SysMenu menu);
+
+    /**
+     * 校验菜单名称是否唯一
+     * 
+     * @param menu 菜单信息
+     * @return 结果
+     */
+    public boolean checkMenuNameUnique(SysMenu menu);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysNoticeService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysNoticeService.java
new file mode 100644
index 0000000..6398b5a
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysNoticeService.java
@@ -0,0 +1,52 @@
+package com.ruoyi.system.service;
+
+import java.util.List;
+import com.ruoyi.system.domain.SysNotice;
+
+/**
+ * 公告 服务层
+ * 
+ * @author ruoyi
+ */
+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 ids 需要删除的数据ID
+     * @return 结果
+     */
+    public int deleteNoticeByIds(String ids);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOperLogService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOperLogService.java
new file mode 100644
index 0000000..3cdc5d2
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOperLogService.java
@@ -0,0 +1,48 @@
+package com.ruoyi.system.service;
+
+import java.util.List;
+import com.ruoyi.system.domain.SysOperLog;
+
+/**
+ * 操作日志 服务层
+ * 
+ * @author ruoyi
+ */
+public interface ISysOperLogService
+{
+    /**
+     * 新增操作日志
+     * 
+     * @param operLog 操作日志对象
+     */
+    public void insertOperlog(SysOperLog operLog);
+
+    /**
+     * 查询系统操作日志集合
+     * 
+     * @param operLog 操作日志对象
+     * @return 操作日志集合
+     */
+    public List<SysOperLog> selectOperLogList(SysOperLog operLog);
+
+    /**
+     * 批量删除系统操作日志
+     * 
+     * @param ids 需要删除的数据
+     * @return 结果
+     */
+    public int deleteOperLogByIds(String ids);
+
+    /**
+     * 查询操作日志详细
+     * 
+     * @param operId 操作ID
+     * @return 操作日志对象
+     */
+    public SysOperLog selectOperLogById(Long operId);
+
+    /**
+     * 清空操作日志
+     */
+    public void cleanOperLog();
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysPostService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysPostService.java
new file mode 100644
index 0000000..7f2a189
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysPostService.java
@@ -0,0 +1,91 @@
+package com.ruoyi.system.service;
+
+import java.util.List;
+import com.ruoyi.system.domain.SysPost;
+
+/**
+ * 岗位信息 服务层
+ * 
+ * @author ruoyi
+ */
+public interface ISysPostService
+{
+    /**
+     * 查询岗位信息集合
+     * 
+     * @param post 岗位信息
+     * @return 岗位信息集合
+     */
+    public List<SysPost> selectPostList(SysPost post);
+
+    /**
+     * 查询所有岗位
+     * 
+     * @return 岗位列表
+     */
+    public List<SysPost> selectPostAll();
+
+    /**
+     * 根据用户ID查询岗位
+     * 
+     * @param userId 用户ID
+     * @return 岗位列表
+     */
+    public List<SysPost> selectPostsByUserId(Long userId);
+
+    /**
+     * 通过岗位ID查询岗位信息
+     * 
+     * @param postId 岗位ID
+     * @return 角色对象信息
+     */
+    public SysPost selectPostById(Long postId);
+
+    /**
+     * 批量删除岗位信息
+     * 
+     * @param ids 需要删除的数据ID
+     * @return 结果
+     */
+    public int deletePostByIds(String ids);
+
+    /**
+     * 新增保存岗位信息
+     * 
+     * @param post 岗位信息
+     * @return 结果
+     */
+    public int insertPost(SysPost post);
+
+    /**
+     * 修改保存岗位信息
+     * 
+     * @param post 岗位信息
+     * @return 结果
+     */
+    public int updatePost(SysPost post);
+
+    /**
+     * 通过岗位ID查询岗位使用数量
+     * 
+     * @param postId 岗位ID
+     * @return 结果
+     */
+    public int countUserPostById(Long postId);
+
+    /**
+     * 校验岗位名称
+     * 
+     * @param post 岗位信息
+     * @return 结果
+     */
+    public boolean checkPostNameUnique(SysPost post);
+
+    /**
+     * 校验岗位编码
+     * 
+     * @param post 岗位信息
+     * @return 结果
+     */
+    public boolean checkPostCodeUnique(SysPost post);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java
new file mode 100644
index 0000000..80d6140
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java
@@ -0,0 +1,166 @@
+package com.ruoyi.system.service;
+
+import java.util.List;
+import java.util.Set;
+import com.ruoyi.common.core.domain.entity.SysRole;
+import com.ruoyi.system.domain.SysUserRole;
+
+/**
+ * 角色业务层
+ * 
+ * @author ruoyi
+ */
+public interface ISysRoleService
+{
+    /**
+     * 根据条件分页查询角色数据
+     * 
+     * @param role 角色信息
+     * @return 角色数据集合信息
+     */
+    public List<SysRole> selectRoleList(SysRole role);
+
+    /**
+     * 根据用户ID查询角色列表
+     * 
+     * @param userId 用户ID
+     * @return 权限列表
+     */
+    public Set<String> selectRoleKeys(Long userId);
+
+    /**
+     * 根据用户ID查询角色权限
+     * 
+     * @param userId 用户ID
+     * @return 角色列表
+     */
+    public List<SysRole> selectRolesByUserId(Long userId);
+
+    /**
+     * 查询所有角色
+     * 
+     * @return 角色列表
+     */
+    public List<SysRole> selectRoleAll();
+
+    /**
+     * 通过角色ID查询角色
+     * 
+     * @param roleId 角色ID
+     * @return 角色对象信息
+     */
+    public SysRole selectRoleById(Long roleId);
+
+    /**
+     * 通过角色ID删除角色
+     * 
+     * @param roleId 角色ID
+     * @return 结果
+     */
+    public boolean deleteRoleById(Long roleId);
+
+    /**
+     * 批量删除角色用户信息
+     * 
+     * @param ids 需要删除的数据ID
+     * @return 结果
+     * @throws Exception 异常
+     */
+    public int deleteRoleByIds(String ids);
+
+    /**
+     * 新增保存角色信息
+     * 
+     * @param role 角色信息
+     * @return 结果
+     */
+    public int insertRole(SysRole role);
+
+    /**
+     * 修改保存角色信息
+     * 
+     * @param role 角色信息
+     * @return 结果
+     */
+    public int updateRole(SysRole role);
+
+    /**
+     * 修改数据权限信息
+     * 
+     * @param role 角色信息
+     * @return 结果
+     */
+    public int authDataScope(SysRole role);
+
+    /**
+     * 校验角色名称是否唯一
+     * 
+     * @param role 角色信息
+     * @return 结果
+     */
+    public boolean checkRoleNameUnique(SysRole role);
+
+    /**
+     * 校验角色权限是否唯一
+     * 
+     * @param role 角色信息
+     * @return 结果
+     */
+    public boolean checkRoleKeyUnique(SysRole role);
+
+    /**
+     * 校验角色是否允许操作
+     * 
+     * @param role 角色信息
+     */
+    public void checkRoleAllowed(SysRole role);
+
+    /**
+     * 校验角色是否有数据权限
+     * 
+     * @param roleIds 角色id
+     */
+    public void checkRoleDataScope(Long... roleIds);
+
+    /**
+     * 通过角色ID查询角色使用数量
+     * 
+     * @param roleId 角色ID
+     * @return 结果
+     */
+    public int countUserRoleByRoleId(Long roleId);
+
+    /**
+     * 角色状态修改
+     * 
+     * @param role 角色信息
+     * @return 结果
+     */
+    public int changeStatus(SysRole role);
+
+    /**
+     * 取消授权用户角色
+     * 
+     * @param userRole 用户和角色关联信息
+     * @return 结果
+     */
+    public int deleteAuthUser(SysUserRole userRole);
+
+    /**
+     * 批量取消授权用户角色
+     * 
+     * @param roleId 角色ID
+     * @param userIds 需要删除的用户数据ID
+     * @return 结果
+     */
+    public int deleteAuthUsers(Long roleId, String userIds);
+
+    /**
+     * 批量选择授权用户角色
+     * 
+     * @param roleId 角色ID
+     * @param userIds 需要删除的用户数据ID
+     * @return 结果
+     */
+    public int insertAuthUsers(Long roleId, String userIds);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserOnlineService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserOnlineService.java
new file mode 100644
index 0000000..50c99a1
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserOnlineService.java
@@ -0,0 +1,75 @@
+package com.ruoyi.system.service;
+
+import java.util.Date;
+import java.util.List;
+import com.ruoyi.system.domain.SysUserOnline;
+
+/**
+ * 在线用户 服务层
+ * 
+ * @author ruoyi
+ */
+public interface ISysUserOnlineService
+{
+    /**
+     * 通过会话序号查询信息
+     * 
+     * @param sessionId 会话ID
+     * @return 在线用户信息
+     */
+    public SysUserOnline selectOnlineById(String sessionId);
+
+    /**
+     * 通过会话序号删除信息
+     * 
+     * @param sessionId 会话ID
+     * @return 在线用户信息
+     */
+    public void deleteOnlineById(String sessionId);
+
+    /**
+     * 通过会话序号删除信息
+     * 
+     * @param sessions 会话ID集合
+     * @return 在线用户信息
+     */
+    public void batchDeleteOnline(List<String> sessions);
+
+    /**
+     * 保存会话信息
+     * 
+     * @param online 会话信息
+     */
+    public void saveOnline(SysUserOnline online);
+
+    /**
+     * 查询会话集合
+     * 
+     * @param userOnline 分页参数
+     * @return 会话集合
+     */
+    public List<SysUserOnline> selectUserOnlineList(SysUserOnline userOnline);
+
+    /**
+     * 强退用户
+     * 
+     * @param sessionId 会话ID
+     */
+    public void forceLogout(String sessionId);
+
+    /**
+     * 清理用户缓存
+     * 
+     * @param loginName 登录名称
+     * @param sessionId 会话ID
+     */
+    public void removeUserCache(String loginName, String sessionId);
+
+    /**
+     * 查询会话集合
+     * 
+     * @param expiredDate 有效期
+     * @return 会话集合
+     */
+    public List<SysUserOnline> selectOnlineByExpired(Date expiredDate);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java
new file mode 100644
index 0000000..35ad2e2
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java
@@ -0,0 +1,214 @@
+package com.ruoyi.system.service;
+
+import java.util.List;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.system.domain.SysUserRole;
+
+/**
+ * 用户 业务层
+ * 
+ * @author ruoyi
+ */
+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 selectUserByLoginName(String userName);
+
+    /**
+     * 通过手机号码查询用户
+     * 
+     * @param phoneNumber 手机号码
+     * @return 用户对象信息
+     */
+    public SysUser selectUserByPhoneNumber(String phoneNumber);
+
+    /**
+     * 通过邮箱查询用户
+     * 
+     * @param email 邮箱
+     * @return 用户对象信息
+     */
+    public SysUser selectUserByEmail(String email);
+
+    /**
+     * 通过用户ID查询用户
+     * 
+     * @param userId 用户ID
+     * @return 用户对象信息
+     */
+    public SysUser selectUserById(Long userId);
+
+    /**
+     * 通过用户ID查询用户和角色关联
+     * 
+     * @param userId 用户ID
+     * @return 用户和角色关联列表
+     */
+    public List<SysUserRole> selectUserRoleByUserId(Long userId);
+
+    /**
+     * 通过用户ID删除用户
+     * 
+     * @param userId 用户ID
+     * @return 结果
+     */
+    public int deleteUserById(Long userId);
+
+    /**
+     * 批量删除用户信息
+     * 
+     * @param ids 需要删除的数据ID
+     * @return 结果
+     * @throws Exception 异常
+     */
+    public int deleteUserByIds(String ids);
+
+    /**
+     * 保存用户信息
+     * 
+     * @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 user 用户信息
+     * @return 结果
+     */
+    public int updateUserInfo(SysUser user);
+
+    /**
+     * 用户授权角色
+     * 
+     * @param userId 用户ID
+     * @param roleIds 角色组
+     */
+    public void insertUserAuth(Long userId, Long[] roleIds);
+
+    /**
+     * 修改用户密码信息
+     * 
+     * @param user 用户信息
+     * @return 结果
+     */
+    public int resetUserPwd(SysUser user);
+
+    /**
+     * 校验用户名称是否唯一
+     * 
+     * @param user 用户信息
+     * @return 结果
+     */
+    public boolean checkLoginNameUnique(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);
+
+    /**
+     * 根据用户ID查询用户所属角色组
+     * 
+     * @param userId 用户ID
+     * @return 结果
+     */
+    public String selectUserRoleGroup(Long userId);
+
+    /**
+     * 根据用户ID查询用户所属岗位组
+     * 
+     * @param userId 用户ID
+     * @return 结果
+     */
+    public String selectUserPostGroup(Long userId);
+
+    /**
+     * 导入用户数据
+     * 
+     * @param userList 用户数据列表
+     * @param isUpdateSupport 是否更新支持,如果已存在,则进行更新数据
+     * @param operName 操作用户
+     * @return 结果
+     */
+    public String importUser(List<SysUser> userList, Boolean isUpdateSupport, String operName);
+
+    /**
+     * 用户状态修改
+     * 
+     * @param user 用户信息
+     * @return 结果
+     */
+    public int changeStatus(SysUser user);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java
new file mode 100644
index 0000000..cf164e5
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java
@@ -0,0 +1,219 @@
+package com.ruoyi.system.service.impl;
+
+import java.util.List;
+import javax.annotation.PostConstruct;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.constant.UserConstants;
+import com.ruoyi.common.core.text.Convert;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.CacheUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.system.domain.SysConfig;
+import com.ruoyi.system.mapper.SysConfigMapper;
+import com.ruoyi.system.service.ISysConfigService;
+
+/**
+ * 参数配置 服务层实现
+ * 
+ * @author ruoyi
+ */
+@Service
+public class SysConfigServiceImpl implements ISysConfigService
+{
+    @Autowired
+    private SysConfigMapper configMapper;
+
+    /**
+     * 项目启动时,初始化参数到缓存
+     */
+    @PostConstruct
+    public void init()
+    {
+        loadingConfigCache();
+    }
+
+    /**
+     * 查询参数配置信息
+     * 
+     * @param configId 参数配置ID
+     * @return 参数配置信息
+     */
+    @Override
+    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(CacheUtils.get(getCacheName(), getCacheKey(configKey)));
+        if (StringUtils.isNotEmpty(configValue))
+        {
+            return configValue;
+        }
+        SysConfig config = new SysConfig();
+        config.setConfigKey(configKey);
+        SysConfig retConfig = configMapper.selectConfig(config);
+        if (StringUtils.isNotNull(retConfig))
+        {
+            CacheUtils.put(getCacheName(), getCacheKey(configKey), retConfig.getConfigValue());
+            return retConfig.getConfigValue();
+        }
+        return StringUtils.EMPTY;
+    }
+
+    /**
+     * 查询参数配置列表
+     * 
+     * @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)
+        {
+            CacheUtils.put(getCacheName(), 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()))
+        {
+            CacheUtils.remove(getCacheName(), getCacheKey(temp.getConfigKey()));
+        }
+
+        int row = configMapper.updateConfig(config);
+        if (row > 0)
+        {
+            CacheUtils.put(getCacheName(), getCacheKey(config.getConfigKey()), config.getConfigValue());
+        }
+        return row;
+    }
+
+    /**
+     * 批量删除参数配置对象
+     * 
+     * @param ids 需要删除的数据ID
+     */
+    @Override
+    public void deleteConfigByIds(String ids)
+    {
+        Long[] configIds = Convert.toLongArray(ids);
+        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);
+            CacheUtils.remove(getCacheName(), getCacheKey(config.getConfigKey()));
+        }
+    }
+
+    /**
+     * 加载参数缓存数据
+     */
+    @Override
+    public void loadingConfigCache()
+    {
+        List<SysConfig> configsList = configMapper.selectConfigList(new SysConfig());
+        for (SysConfig config : configsList)
+        {
+            CacheUtils.put(getCacheName(), getCacheKey(config.getConfigKey()), config.getConfigValue());
+        }
+    }
+
+    /**
+     * 清空参数缓存数据
+     */
+    @Override
+    public void clearConfigCache()
+    {
+        CacheUtils.removeAll(getCacheName());
+    }
+
+    /**
+     * 重置参数缓存数据
+     */
+    @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 name
+     * 
+     * @return 缓存名
+     */
+    private String getCacheName()
+    {
+        return Constants.SYS_CONFIG_CACHE;
+    }
+
+    /**
+     * 设置cache key
+     * 
+     * @param configKey 参数键
+     * @return 缓存键key
+     */
+    private String getCacheKey(String configKey)
+    {
+        return Constants.SYS_CONFIG_KEY + configKey;
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java
new file mode 100644
index 0000000..7ada597
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java
@@ -0,0 +1,328 @@
+package com.ruoyi.system.service.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.lang3.ArrayUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import com.ruoyi.common.annotation.DataScope;
+import com.ruoyi.common.constant.UserConstants;
+import com.ruoyi.common.core.domain.Ztree;
+import com.ruoyi.common.core.domain.entity.SysDept;
+import com.ruoyi.common.core.domain.entity.SysRole;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.core.text.Convert;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.ShiroUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.spring.SpringUtils;
+import com.ruoyi.system.mapper.SysDeptMapper;
+import com.ruoyi.system.service.ISysDeptService;
+
+/**
+ * 部门管理 服务实现
+ * 
+ * @author ruoyi
+ */
+@Service
+public class SysDeptServiceImpl implements ISysDeptService
+{
+    @Autowired
+    private SysDeptMapper deptMapper;
+
+    /**
+     * 查询部门管理数据
+     * 
+     * @param dept 部门信息
+     * @return 部门信息集合
+     */
+    @Override
+    @DataScope(deptAlias = "d")
+    public List<SysDept> selectDeptList(SysDept dept)
+    {
+        return deptMapper.selectDeptList(dept);
+    }
+
+    /**
+     * 查询部门管理树
+     * 
+     * @param dept 部门信息
+     * @return 所有部门信息
+     */
+    @Override
+    @DataScope(deptAlias = "d")
+    public List<Ztree> selectDeptTree(SysDept dept)
+    {
+        List<SysDept> deptList = deptMapper.selectDeptList(dept);
+        List<Ztree> ztrees = initZtree(deptList);
+        return ztrees;
+    }
+
+    /**
+     * 查询部门管理树(排除下级)
+     * 
+     * @param deptId 部门ID
+     * @return 所有部门信息
+     */
+    @Override
+    @DataScope(deptAlias = "d")
+    public List<Ztree> selectDeptTreeExcludeChild(SysDept dept)
+    {
+        Long excludeId = dept.getExcludeId();
+        List<SysDept> depts = deptMapper.selectDeptList(dept);
+        if (excludeId.intValue() > 0)
+        {
+            depts.removeIf(d -> d.getDeptId().intValue() == excludeId || ArrayUtils.contains(StringUtils.split(d.getAncestors(), ","), excludeId + ""));
+        }
+        List<Ztree> ztrees = initZtree(depts);
+        return ztrees;
+    }
+
+    /**
+     * 根据角色ID查询部门(数据权限)
+     *
+     * @param role 角色对象
+     * @return 部门列表(数据权限)
+     */
+    @Override
+    public List<Ztree> roleDeptTreeData(SysRole role)
+    {
+        Long roleId = role.getRoleId();
+        List<Ztree> ztrees = new ArrayList<Ztree>();
+        List<SysDept> deptList = SpringUtils.getAopProxy(this).selectDeptList(new SysDept());
+        if (StringUtils.isNotNull(roleId))
+        {
+            List<String> roleDeptList = deptMapper.selectRoleDeptTree(roleId);
+            ztrees = initZtree(deptList, roleDeptList);
+        }
+        else
+        {
+            ztrees = initZtree(deptList);
+        }
+        return ztrees;
+    }
+
+    /**
+     * 对象转部门树
+     *
+     * @param deptList 部门列表
+     * @return 树结构列表
+     */
+    public List<Ztree> initZtree(List<SysDept> deptList)
+    {
+        return initZtree(deptList, null);
+    }
+
+    /**
+     * 对象转部门树
+     *
+     * @param deptList 部门列表
+     * @param roleDeptList 角色已存在菜单列表
+     * @return 树结构列表
+     */
+    public List<Ztree> initZtree(List<SysDept> deptList, List<String> roleDeptList)
+    {
+
+        List<Ztree> ztrees = new ArrayList<Ztree>();
+        boolean isCheck = StringUtils.isNotNull(roleDeptList);
+        for (SysDept dept : deptList)
+        {
+            if (UserConstants.DEPT_NORMAL.equals(dept.getStatus()))
+            {
+                Ztree ztree = new Ztree();
+                ztree.setId(dept.getDeptId());
+                ztree.setpId(dept.getParentId());
+                ztree.setName(dept.getDeptName());
+                ztree.setTitle(dept.getDeptName());
+                if (isCheck)
+                {
+                    ztree.setChecked(roleDeptList.contains(dept.getDeptId() + dept.getDeptName()));
+                }
+                ztrees.add(ztree);
+            }
+        }
+        return ztrees;
+    }
+
+    /**
+     * 根据父部门ID查询下级部门数量
+     * 
+     * @param parentId 部门ID
+     * @return 结果
+     */
+    @Override
+    public int selectDeptCount(Long parentId)
+    {
+        SysDept dept = new SysDept();
+        dept.setParentId(parentId);
+        return deptMapper.selectDeptCount(dept);
+    }
+
+    /**
+     * 查询部门是否存在用户
+     * 
+     * @param deptId 部门ID
+     * @return 结果 true 存在 false 不存在
+     */
+    @Override
+    public boolean checkDeptExistUser(Long deptId)
+    {
+        int result = deptMapper.checkDeptExistUser(deptId);
+        return result > 0;
+    }
+
+    /**
+     * 删除部门管理信息
+     * 
+     * @param deptId 部门ID
+     * @return 结果
+     */
+    @Override
+    public int deleteDeptById(Long deptId)
+    {
+        return deptMapper.deleteDeptById(deptId);
+    }
+
+    /**
+     * 新增保存部门信息
+     * 
+     * @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
+    @Transactional
+    public int updateDept(SysDept dept)
+    {
+        SysDept newParentDept = deptMapper.selectDeptById(dept.getParentId());
+        SysDept oldDept = 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 新的父ID集合
+     * @param oldAncestors 旧的父ID集合
+     */
+    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);
+        }
+    }
+
+    /**
+     * 根据部门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 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(ShiroUtils.getUserId()) && StringUtils.isNotNull(deptId))
+        {
+            SysDept dept = new SysDept();
+            dept.setDeptId(deptId);
+            List<SysDept> depts = SpringUtils.getAopProxy(this).selectDeptList(dept);
+            if (StringUtils.isEmpty(depts))
+            {
+                throw new ServiceException("没有权限访问部门数据!");
+            }
+        }
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java
new file mode 100644
index 0000000..bf9e6e5
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java
@@ -0,0 +1,113 @@
+package com.ruoyi.system.service.impl;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.common.core.domain.entity.SysDictData;
+import com.ruoyi.common.core.text.Convert;
+import com.ruoyi.common.utils.DictUtils;
+import com.ruoyi.system.mapper.SysDictDataMapper;
+import com.ruoyi.system.service.ISysDictDataService;
+
+/**
+ * 字典 业务层处理
+ * 
+ * @author ruoyi
+ */
+@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 ids 需要删除的数据
+     */
+    @Override
+    public void deleteDictDataByIds(String ids)
+    {
+        Long[] dictCodes = Convert.toLongArray(ids);
+        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/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java
new file mode 100644
index 0000000..f5f3a13
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java
@@ -0,0 +1,260 @@
+package com.ruoyi.system.service.impl;
+
+import java.util.ArrayList;
+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.ruoyi.common.constant.UserConstants;
+import com.ruoyi.common.core.domain.Ztree;
+import com.ruoyi.common.core.domain.entity.SysDictData;
+import com.ruoyi.common.core.domain.entity.SysDictType;
+import com.ruoyi.common.core.text.Convert;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.DictUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.system.mapper.SysDictDataMapper;
+import com.ruoyi.system.mapper.SysDictTypeMapper;
+import com.ruoyi.system.service.ISysDictTypeService;
+
+/**
+ * 字典 业务层处理
+ * 
+ * @author ruoyi
+ */
+@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 ids 需要删除的数据
+     */
+    @Override
+    public void deleteDictTypeByIds(String ids)
+    {
+        Long[] dictIds = Convert.toLongArray(ids);
+        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;
+    }
+
+    /**
+     * 查询字典类型树
+     * 
+     * @param dictType 字典类型
+     * @return 所有字典类型
+     */
+    @Override
+    public List<Ztree> selectDictTree(SysDictType dictType)
+    {
+        List<Ztree> ztrees = new ArrayList<Ztree>();
+        List<SysDictType> dictList = dictTypeMapper.selectDictTypeList(dictType);
+        for (SysDictType dict : dictList)
+        {
+            if (UserConstants.DICT_NORMAL.equals(dict.getStatus()))
+            {
+                Ztree ztree = new Ztree();
+                ztree.setId(dict.getDictId());
+                ztree.setName(transDictName(dict));
+                ztree.setTitle(dict.getDictType());
+                ztrees.add(ztree);
+            }
+        }
+        return ztrees;
+    }
+
+    public String transDictName(SysDictType dictType)
+    {
+        StringBuffer sb = new StringBuffer();
+        sb.append("(" + dictType.getDictName() + ")");
+        sb.append("&nbsp;&nbsp;&nbsp;" + dictType.getDictType());
+        return sb.toString();
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java
new file mode 100644
index 0000000..13f5c1a
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java
@@ -0,0 +1,66 @@
+package com.ruoyi.system.service.impl;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.common.core.text.Convert;
+import com.ruoyi.system.domain.SysLogininfor;
+import com.ruoyi.system.mapper.SysLogininforMapper;
+import com.ruoyi.system.service.ISysLogininforService;
+
+/**
+ * 系统访问日志情况信息 服务层处理
+ * 
+ * @author ruoyi
+ */
+@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 ids 需要删除的数据
+     * @return 结果
+     */
+    @Override
+    public int deleteLogininforByIds(String ids)
+    {
+        return logininforMapper.deleteLogininforByIds(Convert.toStrArray(ids));
+    }
+
+    /**
+     * 清空系统登录日志
+     */
+    @Override
+    public void cleanLogininfor()
+    {
+        logininforMapper.cleanLogininfor();
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java
new file mode 100644
index 0000000..4ff052b
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java
@@ -0,0 +1,410 @@
+package com.ruoyi.system.service.impl;
+
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.common.constant.UserConstants;
+import com.ruoyi.common.core.domain.Ztree;
+import com.ruoyi.common.core.domain.entity.SysMenu;
+import com.ruoyi.common.core.domain.entity.SysRole;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.system.mapper.SysMenuMapper;
+import com.ruoyi.system.mapper.SysRoleMenuMapper;
+import com.ruoyi.system.service.ISysMenuService;
+
+/**
+ * 菜单 业务层处理
+ * 
+ * @author ruoyi
+ */
+@Service
+public class SysMenuServiceImpl implements ISysMenuService
+{
+    public static final String PREMISSION_STRING = "perms[\"{0}\"]";
+
+    @Autowired
+    private SysMenuMapper menuMapper;
+
+    @Autowired
+    private SysRoleMenuMapper roleMenuMapper;
+
+    /**
+     * 根据用户查询菜单
+     * 
+     * @param user 用户信息
+     * @return 菜单列表
+     */
+    @Override
+    public List<SysMenu> selectMenusByUser(SysUser user)
+    {
+        List<SysMenu> menus = new LinkedList<SysMenu>();
+        // 管理员显示所有菜单信息
+        if (user.isAdmin())
+        {
+            menus = menuMapper.selectMenuNormalAll();
+        }
+        else
+        {
+            menus = menuMapper.selectMenusByUserId(user.getUserId());
+        }
+        return getChildPerms(menus, 0);
+    }
+
+    /**
+     * 查询菜单集合
+     * 
+     * @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;
+    }
+
+    /**
+     * 查询菜单集合
+     * 
+     * @return 所有菜单信息
+     */
+    @Override
+    public List<SysMenu> selectMenuAll(Long userId)
+    {
+        List<SysMenu> menuList = null;
+        if (SysUser.isAdmin(userId))
+        {
+            menuList = menuMapper.selectMenuAll();
+        }
+        else
+        {
+            menuList = menuMapper.selectMenuAllByUserId(userId);
+        }
+        return menuList;
+    }
+
+    /**
+     * 根据用户ID查询权限
+     * 
+     * @param userId 用户ID
+     * @return 权限列表
+     */
+    @Override
+    public Set<String> selectPermsByUserId(Long userId)
+    {
+        List<String> perms = menuMapper.selectPermsByUserId(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> selectPermsByRoleId(Long roleId)
+    {
+        List<String> perms = menuMapper.selectPermsByRoleId(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 role 角色对象
+     * @return 菜单列表
+     */
+    @Override
+    public List<Ztree> roleMenuTreeData(SysRole role, Long userId)
+    {
+        Long roleId = role.getRoleId();
+        List<Ztree> ztrees = new ArrayList<Ztree>();
+        List<SysMenu> menuList = selectMenuAll(userId);
+        if (StringUtils.isNotNull(roleId))
+        {
+            List<String> roleMenuList = menuMapper.selectMenuTree(roleId);
+            ztrees = initZtree(menuList, roleMenuList, true);
+        }
+        else
+        {
+            ztrees = initZtree(menuList, null, true);
+        }
+        return ztrees;
+    }
+
+    /**
+     * 查询所有菜单
+     * 
+     * @return 菜单列表
+     */
+    @Override
+    public List<Ztree> menuTreeData(Long userId)
+    {
+        List<SysMenu> menuList = selectMenuAll(userId);
+        List<Ztree> ztrees = initZtree(menuList);
+        return ztrees;
+    }
+
+    /**
+     * 查询系统所有权限
+     * 
+     * @return 权限列表
+     */
+    @Override
+    public LinkedHashMap<String, String> selectPermsAll(Long userId)
+    {
+        LinkedHashMap<String, String> section = new LinkedHashMap<>();
+        List<SysMenu> permissions = selectMenuAll(userId);
+        if (StringUtils.isNotEmpty(permissions))
+        {
+            for (SysMenu menu : permissions)
+            {
+                section.put(menu.getUrl(), MessageFormat.format(PREMISSION_STRING, menu.getPerms()));
+            }
+        }
+        return section;
+    }
+
+    /**
+     * 对象转菜单树
+     * 
+     * @param menuList 菜单列表
+     * @return 树结构列表
+     */
+    public List<Ztree> initZtree(List<SysMenu> menuList)
+    {
+        return initZtree(menuList, null, false);
+    }
+
+    /**
+     * 对象转菜单树
+     * 
+     * @param menuList 菜单列表
+     * @param roleMenuList 角色已存在菜单列表
+     * @param permsFlag 是否需要显示权限标识
+     * @return 树结构列表
+     */
+    public List<Ztree> initZtree(List<SysMenu> menuList, List<String> roleMenuList, boolean permsFlag)
+    {
+        List<Ztree> ztrees = new ArrayList<Ztree>();
+        boolean isCheck = StringUtils.isNotNull(roleMenuList);
+        for (SysMenu menu : menuList)
+        {
+            Ztree ztree = new Ztree();
+            ztree.setId(menu.getMenuId());
+            ztree.setpId(menu.getParentId());
+            ztree.setName(transMenuName(menu, permsFlag));
+            ztree.setTitle(menu.getMenuName());
+            if (isCheck)
+            {
+                ztree.setChecked(roleMenuList.contains(menu.getMenuId() + menu.getPerms()));
+            }
+            ztrees.add(ztree);
+        }
+        return ztrees;
+    }
+
+    public String transMenuName(SysMenu menu, boolean permsFlag)
+    {
+        StringBuffer sb = new StringBuffer();
+        sb.append(menu.getMenuName());
+        if (permsFlag)
+        {
+            sb.append("<font color=\"#888\">&nbsp;&nbsp;&nbsp;" + menu.getPerms() + "</font>");
+        }
+        return sb.toString();
+    }
+
+    /**
+     * 删除菜单管理信息
+     * 
+     * @param menuId 菜单ID
+     * @return 结果
+     */
+    @Override
+    public int deleteMenuById(Long menuId)
+    {
+        return menuMapper.deleteMenuById(menuId);
+    }
+
+    /**
+     * 根据菜单ID查询信息
+     * 
+     * @param menuId 菜单ID
+     * @return 菜单信息
+     */
+    @Override
+    public SysMenu selectMenuById(Long menuId)
+    {
+        return menuMapper.selectMenuById(menuId);
+    }
+
+    /**
+     * 查询子菜单数量
+     * 
+     * @param parentId 父级菜单ID
+     * @return 结果
+     */
+    @Override
+    public int selectCountMenuByParentId(Long parentId)
+    {
+        return menuMapper.selectCountMenuByParentId(parentId);
+    }
+
+    /**
+     * 查询菜单使用数量
+     * 
+     * @param menuId 菜单ID
+     * @return 结果
+     */
+    @Override
+    public int selectCountRoleMenuByMenuId(Long menuId)
+    {
+        return roleMenuMapper.selectCountRoleMenuByMenuId(menuId);
+    }
+
+    /**
+     * 新增保存菜单信息
+     * 
+     * @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 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;
+    }
+
+    /**
+     * 根据父节点的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();
+            // 一、根据传入的某个父节点ID,遍历该父节点的所有子节点
+            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;
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysNoticeServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysNoticeServiceImpl.java
new file mode 100644
index 0000000..7968b9a
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysNoticeServiceImpl.java
@@ -0,0 +1,82 @@
+package com.ruoyi.system.service.impl;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.common.core.text.Convert;
+import com.ruoyi.system.domain.SysNotice;
+import com.ruoyi.system.mapper.SysNoticeMapper;
+import com.ruoyi.system.service.ISysNoticeService;
+
+/**
+ * 公告 服务层实现
+ * 
+ * @author ruoyi
+ * @date 2018-06-25
+ */
+@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 ids 需要删除的数据ID
+     * @return 结果
+     */
+    @Override
+    public int deleteNoticeByIds(String ids)
+    {
+        return noticeMapper.deleteNoticeByIds(Convert.toStrArray(ids));
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOperLogServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOperLogServiceImpl.java
new file mode 100644
index 0000000..78ae353
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOperLogServiceImpl.java
@@ -0,0 +1,77 @@
+package com.ruoyi.system.service.impl;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.common.core.text.Convert;
+import com.ruoyi.system.domain.SysOperLog;
+import com.ruoyi.system.mapper.SysOperLogMapper;
+import com.ruoyi.system.service.ISysOperLogService;
+
+/**
+ * 操作日志 服务层处理
+ * 
+ * @author ruoyi
+ */
+@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 ids 需要删除的数据
+     * @return
+     */
+    @Override
+    public int deleteOperLogByIds(String ids)
+    {
+        return operLogMapper.deleteOperLogByIds(Convert.toStrArray(ids));
+    }
+
+    /**
+     * 查询操作日志详细
+     * 
+     * @param operId 操作ID
+     * @return 操作日志对象
+     */
+    @Override
+    public SysOperLog selectOperLogById(Long operId)
+    {
+        return operLogMapper.selectOperLogById(operId);
+    }
+
+    /**
+     * 清空操作日志
+     */
+    @Override
+    public void cleanOperLog()
+    {
+        operLogMapper.cleanOperLog();
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysPostServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysPostServiceImpl.java
new file mode 100644
index 0000000..41a5e71
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysPostServiceImpl.java
@@ -0,0 +1,181 @@
+package com.ruoyi.system.service.impl;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.common.constant.UserConstants;
+import com.ruoyi.common.core.text.Convert;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.system.domain.SysPost;
+import com.ruoyi.system.mapper.SysPostMapper;
+import com.ruoyi.system.mapper.SysUserPostMapper;
+import com.ruoyi.system.service.ISysPostService;
+
+/**
+ * 岗位信息 服务层处理
+ * 
+ * @author ruoyi
+ */
+@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 userId 用户ID
+     * @return 岗位列表
+     */
+    @Override
+    public List<SysPost> selectPostsByUserId(Long userId)
+    {
+        List<SysPost> userPosts = postMapper.selectPostsByUserId(userId);
+        List<SysPost> posts = postMapper.selectPostAll();
+        for (SysPost post : posts)
+        {
+            for (SysPost userRole : userPosts)
+            {
+                if (post.getPostId().longValue() == userRole.getPostId().longValue())
+                {
+                    post.setFlag(true);
+                    break;
+                }
+            }
+        }
+        return posts;
+    }
+
+    /**
+     * 通过岗位ID查询岗位信息
+     * 
+     * @param postId 岗位ID
+     * @return 角色对象信息
+     */
+    @Override
+    public SysPost selectPostById(Long postId)
+    {
+        return postMapper.selectPostById(postId);
+    }
+
+    /**
+     * 批量删除岗位信息
+     * 
+     * @param ids 需要删除的数据ID
+     * @return 结果
+     */
+    @Override
+    public int deletePostByIds(String ids)
+    {
+        Long[] postIds = Convert.toLongArray(ids);
+        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);
+    }
+
+    /**
+     * 通过岗位ID查询岗位使用数量
+     * 
+     * @param postId 岗位ID
+     * @return 结果
+     */
+    @Override
+    public int countUserPostById(Long postId)
+    {
+        return userPostMapper.countUserPostById(postId);
+    }
+
+    /**
+     * 校验岗位名称是否唯一
+     * 
+     * @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;
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java
new file mode 100644
index 0000000..3c57dab
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java
@@ -0,0 +1,418 @@
+package com.ruoyi.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.ruoyi.common.annotation.DataScope;
+import com.ruoyi.common.constant.UserConstants;
+import com.ruoyi.common.core.domain.entity.SysRole;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.core.text.Convert;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.ShiroUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.spring.SpringUtils;
+import com.ruoyi.system.domain.SysRoleDept;
+import com.ruoyi.system.domain.SysRoleMenu;
+import com.ruoyi.system.domain.SysUserRole;
+import com.ruoyi.system.mapper.SysRoleDeptMapper;
+import com.ruoyi.system.mapper.SysRoleMapper;
+import com.ruoyi.system.mapper.SysRoleMenuMapper;
+import com.ruoyi.system.mapper.SysUserRoleMapper;
+import com.ruoyi.system.service.ISysRoleService;
+
+/**
+ * 角色 业务层处理
+ * 
+ * @author ruoyi
+ */
+@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 Set<String> selectRoleKeys(Long userId)
+    {
+        List<SysRole> perms = roleMapper.selectRolesByUserId(userId);
+        Set<String> permsSet = new HashSet<>();
+        for (SysRole perm : perms)
+        {
+            if (StringUtils.isNotNull(perm))
+            {
+                permsSet.addAll(Arrays.asList(perm.getRoleKey().trim().split(",")));
+            }
+        }
+        return permsSet;
+    }
+
+    /**
+     * 根据用户ID查询角色
+     * 
+     * @param userId 用户ID
+     * @return 角色列表
+     */
+    @Override
+    public List<SysRole> selectRolesByUserId(Long userId)
+    {
+        List<SysRole> userRoles = roleMapper.selectRolesByUserId(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;
+    }
+
+    /**
+     * 查询所有角色
+     * 
+     * @return 角色列表
+     */
+    @Override
+    public List<SysRole> selectRoleAll()
+    {
+        return SpringUtils.getAopProxy(this).selectRoleList(new SysRole());
+    }
+
+    /**
+     * 通过角色ID查询角色
+     * 
+     * @param roleId 角色ID
+     * @return 角色对象信息
+     */
+    @Override
+    public SysRole selectRoleById(Long roleId)
+    {
+        return roleMapper.selectRoleById(roleId);
+    }
+
+    /**
+     * 通过角色ID删除角色
+     * 
+     * @param roleId 角色ID
+     * @return 结果
+     */
+    @Override
+    @Transactional
+    public boolean deleteRoleById(Long roleId)
+    {
+        // 删除角色与菜单关联
+        roleMenuMapper.deleteRoleMenuByRoleId(roleId);
+        // 删除角色与部门关联
+        roleDeptMapper.deleteRoleDeptByRoleId(roleId);
+        return roleMapper.deleteRoleById(roleId) > 0 ? true : false;
+    }
+
+    /**
+     * 批量删除角色信息
+     * 
+     * @param ids 需要删除的数据ID
+     * @throws Exception
+     */
+    @Override
+    @Transactional
+    public int deleteRoleByIds(String ids)
+    {
+        Long[] roleIds = Convert.toLongArray(ids);
+        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 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
+    @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;
+    }
+
+    /**
+     * 校验角色名称是否唯一
+     * 
+     * @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 roleIds 角色id
+     */
+    @Override
+    public void checkRoleDataScope(Long... roleIds)
+    {
+        if (!SysUser.isAdmin(ShiroUtils.getUserId()))
+        {
+            for (Long roleId : roleIds)
+            {
+                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
+    public int changeStatus(SysRole role)
+    {
+        return roleMapper.updateRole(role);
+    }
+
+    /**
+     * 取消授权用户角色
+     * 
+     * @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, String userIds)
+    {
+        return userRoleMapper.deleteUserRoleInfos(roleId, Convert.toLongArray(userIds));
+    }
+
+    /**
+     * 批量选择授权用户角色
+     * 
+     * @param roleId 角色ID
+     * @param userIds 需要授权的用户数据ID
+     * @return 结果
+     */
+    @Override
+    public int insertAuthUsers(Long roleId, String userIds)
+    {
+        Long[] users = Convert.toLongArray(userIds);
+        // 新增用户与角色管理
+        List<SysUserRole> list = new ArrayList<SysUserRole>();
+        for (Long userId : users)
+        {
+            SysUserRole ur = new SysUserRole();
+            ur.setUserId(userId);
+            ur.setRoleId(roleId);
+            list.add(ur);
+        }
+        return userRoleMapper.batchUserRole(list);
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserOnlineServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserOnlineServiceImpl.java
new file mode 100644
index 0000000..ae6087a
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserOnlineServiceImpl.java
@@ -0,0 +1,140 @@
+package com.ruoyi.system.service.impl;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.Deque;
+import java.util.List;
+import com.ruoyi.common.utils.spring.SpringUtils;
+import org.apache.shiro.cache.Cache;
+import org.apache.shiro.cache.ehcache.EhCacheManager;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.common.constant.ShiroConstants;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.system.domain.SysUserOnline;
+import com.ruoyi.system.mapper.SysUserOnlineMapper;
+import com.ruoyi.system.service.ISysUserOnlineService;
+
+/**
+ * 在线用户 服务层处理
+ * 
+ * @author ruoyi
+ */
+@Service
+public class SysUserOnlineServiceImpl implements ISysUserOnlineService
+{
+    @Autowired
+    private SysUserOnlineMapper userOnlineDao;
+
+    /**
+     * 通过会话序号查询信息
+     * 
+     * @param sessionId 会话ID
+     * @return 在线用户信息
+     */
+    @Override
+    public SysUserOnline selectOnlineById(String sessionId)
+    {
+        return userOnlineDao.selectOnlineById(sessionId);
+    }
+
+    /**
+     * 通过会话序号删除信息
+     * 
+     * @param sessionId 会话ID
+     * @return 在线用户信息
+     */
+    @Override
+    public void deleteOnlineById(String sessionId)
+    {
+        SysUserOnline userOnline = selectOnlineById(sessionId);
+        if (StringUtils.isNotNull(userOnline))
+        {
+            userOnlineDao.deleteOnlineById(sessionId);
+        }
+    }
+
+    /**
+     * 通过会话序号删除信息
+     * 
+     * @param sessions 会话ID集合
+     * @return 在线用户信息
+     */
+    @Override
+    public void batchDeleteOnline(List<String> sessions)
+    {
+        for (String sessionId : sessions)
+        {
+            SysUserOnline userOnline = selectOnlineById(sessionId);
+            if (StringUtils.isNotNull(userOnline))
+            {
+                userOnlineDao.deleteOnlineById(sessionId);
+            }
+        }
+    }
+
+    /**
+     * 保存会话信息
+     * 
+     * @param online 会话信息
+     */
+    @Override
+    public void saveOnline(SysUserOnline online)
+    {
+        userOnlineDao.saveOnline(online);
+    }
+
+    /**
+     * 查询会话集合
+     * 
+     * @param userOnline 在线用户
+     */
+    @Override
+    public List<SysUserOnline> selectUserOnlineList(SysUserOnline userOnline)
+    {
+        return userOnlineDao.selectUserOnlineList(userOnline);
+    }
+
+    /**
+     * 强退用户
+     * 
+     * @param sessionId 会话ID
+     */
+    @Override
+    public void forceLogout(String sessionId)
+    {
+        userOnlineDao.deleteOnlineById(sessionId);
+    }
+
+    /**
+     * 清理用户缓存
+     * 
+     * @param loginName 登录名称
+     * @param sessionId 会话ID
+     */
+    @Override
+    public void removeUserCache(String loginName, String sessionId)
+    {
+        EhCacheManager ehCacheManager = SpringUtils.getBean(EhCacheManager.class);
+        Cache<String, Deque<Serializable>> cache = ehCacheManager.getCache(ShiroConstants.SYS_USERCACHE);
+        Deque<Serializable> deque = cache.get(loginName);
+        if (StringUtils.isEmpty(deque) || deque.size() == 0)
+        {
+            return;
+        }
+        deque.remove(sessionId);
+    }
+
+    /**
+     * 查询会话集合
+     * 
+     * @param expiredDate 失效日期
+     */
+    @Override
+    public List<SysUserOnline> selectOnlineByExpired(Date expiredDate)
+    {
+        String lastAccessTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, expiredDate);
+        return userOnlineDao.selectOnlineByExpired(lastAccessTime);
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
new file mode 100644
index 0000000..34ae796
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
@@ -0,0 +1,568 @@
+package com.ruoyi.system.service.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+import javax.validation.ConstraintViolationException;
+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.ruoyi.common.annotation.DataScope;
+import com.ruoyi.common.constant.UserConstants;
+import com.ruoyi.common.core.domain.entity.SysRole;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.core.text.Convert;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.ExceptionUtil;
+import com.ruoyi.common.utils.ShiroUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.bean.BeanValidators;
+import com.ruoyi.common.utils.html.EscapeUtil;
+import com.ruoyi.common.utils.security.Md5Utils;
+import com.ruoyi.common.utils.spring.SpringUtils;
+import com.ruoyi.system.domain.SysPost;
+import com.ruoyi.system.domain.SysUserPost;
+import com.ruoyi.system.domain.SysUserRole;
+import com.ruoyi.system.mapper.SysPostMapper;
+import com.ruoyi.system.mapper.SysRoleMapper;
+import com.ruoyi.system.mapper.SysUserMapper;
+import com.ruoyi.system.mapper.SysUserPostMapper;
+import com.ruoyi.system.mapper.SysUserRoleMapper;
+import com.ruoyi.system.service.ISysConfigService;
+import com.ruoyi.system.service.ISysDeptService;
+import com.ruoyi.system.service.ISysUserService;
+
+/**
+ * 用户 业务层处理
+ * 
+ * @author ruoyi
+ */
+@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 SysUserPostMapper userPostMapper;
+
+    @Autowired
+    private SysUserRoleMapper userRoleMapper;
+
+    @Autowired
+    private ISysConfigService configService;
+
+    @Autowired
+    private ISysDeptService deptService;
+
+    @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 selectUserByLoginName(String userName)
+    {
+        return userMapper.selectUserByLoginName(userName);
+    }
+
+    /**
+     * 通过手机号码查询用户
+     * 
+     * @param phoneNumber 手机号码
+     * @return 用户对象信息
+     */
+    @Override
+    public SysUser selectUserByPhoneNumber(String phoneNumber)
+    {
+        return userMapper.selectUserByPhoneNumber(phoneNumber);
+    }
+
+    /**
+     * 通过邮箱查询用户
+     * 
+     * @param email 邮箱
+     * @return 用户对象信息
+     */
+    @Override
+    public SysUser selectUserByEmail(String email)
+    {
+        return userMapper.selectUserByEmail(email);
+    }
+
+    /**
+     * 通过用户ID查询用户
+     * 
+     * @param userId 用户ID
+     * @return 用户对象信息
+     */
+    @Override
+    public SysUser selectUserById(Long userId)
+    {
+        return userMapper.selectUserById(userId);
+    }
+
+    /**
+     * 通过用户ID查询用户和角色关联
+     * 
+     * @param userId 用户ID
+     * @return 用户和角色关联列表
+     */
+    @Override
+    public List<SysUserRole> selectUserRoleByUserId(Long userId)
+    {
+        return userRoleMapper.selectUserRoleByUserId(userId);
+    }
+
+    /**
+     * 通过用户ID删除用户
+     * 
+     * @param userId 用户ID
+     * @return 结果
+     */
+    @Override
+    @Transactional
+    public int deleteUserById(Long userId)
+    {
+        // 删除用户与角色关联
+        userRoleMapper.deleteUserRoleByUserId(userId);
+        // 删除用户与岗位表
+        userPostMapper.deleteUserPostByUserId(userId);
+        return userMapper.deleteUserById(userId);
+    }
+
+    /**
+     * 批量删除用户信息
+     * 
+     * @param ids 需要删除的数据ID
+     * @return 结果
+     */
+    @Override
+    @Transactional
+    public int deleteUserByIds(String ids)
+    {
+        Long[] userIds = Convert.toLongArray(ids);
+        for (Long userId : userIds)
+        {
+            checkUserAllowed(new SysUser(userId));
+            checkUserDataScope(userId);
+        }
+        // 删除用户与角色关联
+        userRoleMapper.deleteUserRole(userIds);
+        // 删除用户与岗位关联
+        userPostMapper.deleteUserPost(userIds);
+        return userMapper.deleteUserByIds(userIds);
+    }
+
+    /**
+     * 新增保存用户信息
+     * 
+     * @param user 用户信息
+     * @return 结果
+     */
+    @Override
+    @Transactional
+    public int insertUser(SysUser user)
+    {
+        // 新增用户信息
+        int rows = userMapper.insertUser(user);
+        // 新增用户岗位关联
+        insertUserPost(user);
+        // 新增用户与角色管理
+        insertUserRole(user.getUserId(), user.getRoleIds());
+        return rows;
+    }
+
+    /**
+     * 注册用户信息
+     * 
+     * @param user 用户信息
+     * @return 结果
+     */
+    @Override
+    public boolean registerUser(SysUser user)
+    {
+        user.setUserType(UserConstants.REGISTER_USER_TYPE);
+        return userMapper.insertUser(user) > 0;
+    }
+
+    /**
+     * 修改保存用户信息
+     * 
+     * @param user 用户信息
+     * @return 结果
+     */
+    @Override
+    @Transactional
+    public int updateUser(SysUser user)
+    {
+        Long userId = user.getUserId();
+        // 删除用户与角色关联
+        userRoleMapper.deleteUserRoleByUserId(userId);
+        // 新增用户与角色管理
+        insertUserRole(user.getUserId(), user.getRoleIds());
+        // 删除用户与岗位关联
+        userPostMapper.deleteUserPostByUserId(userId);
+        // 新增用户与岗位管理
+        insertUserPost(user);
+        return userMapper.updateUser(user);
+    }
+
+    /**
+     * 修改用户个人详细信息
+     * 
+     * @param user 用户信息
+     * @return 结果
+     */
+    @Override
+    public int updateUserInfo(SysUser 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 resetUserPwd(SysUser user)
+    {
+        return updateUserInfo(user);
+    }
+
+    /**
+     * 新增用户角色信息
+     * 
+     * @param userId 用户ID
+     * @param roleIds 角色组
+     */
+    public void insertUserRole(Long userId, Long[] roleIds)
+    {
+        if (StringUtils.isNotNull(roleIds))
+        {
+            // 新增用户与角色管理
+            List<SysUserRole> list = new ArrayList<SysUserRole>();
+            for (Long roleId : roleIds)
+            {
+                SysUserRole ur = new SysUserRole();
+                ur.setUserId(userId);
+                ur.setRoleId(roleId);
+                list.add(ur);
+            }
+            if (list.size() > 0)
+            {
+                userRoleMapper.batchUserRole(list);
+            }
+        }
+    }
+
+    /**
+     * 新增用户岗位信息
+     * 
+     * @param user 用户对象
+     */
+    public void insertUserPost(SysUser user)
+    {
+        Long[] posts = user.getPostIds();
+        if (StringUtils.isNotNull(posts))
+        {
+            // 新增用户与岗位管理
+            List<SysUserPost> list = new ArrayList<SysUserPost>();
+            for (Long postId : posts)
+            {
+                SysUserPost up = new SysUserPost();
+                up.setUserId(user.getUserId());
+                up.setPostId(postId);
+                list.add(up);
+            }
+            if (list.size() > 0)
+            {
+                userPostMapper.batchUserPost(list);
+            }
+        }
+    }
+
+    /**
+     * 校验用户名称是否唯一
+     * 
+     * @param user 用户信息
+     * @return 结果
+     */
+    @Override
+    public boolean checkLoginNameUnique(SysUser user)
+    {
+        Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
+        SysUser info = userMapper.checkLoginNameUnique(user.getLoginName());
+        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(ShiroUtils.getUserId()))
+        {
+            SysUser user = new SysUser();
+            user.setUserId(userId);
+            List<SysUser> users = SpringUtils.getAopProxy(this).selectUserList(user);
+            if (StringUtils.isEmpty(users))
+            {
+                throw new ServiceException("没有权限访问用户数据!");
+            }
+        }
+    }
+
+    /**
+     * 查询用户所属角色组
+     * 
+     * @param userId 用户ID
+     * @return 结果
+     */
+    @Override
+    public String selectUserRoleGroup(Long userId)
+    {
+        List<SysRole> list = roleMapper.selectRolesByUserId(userId);
+        if (CollectionUtils.isEmpty(list))
+        {
+            return StringUtils.EMPTY;
+        }
+        return list.stream().map(SysRole::getRoleName).collect(Collectors.joining(","));
+    }
+
+    /**
+     * 查询用户所属岗位组
+     * 
+     * @param userId 用户ID
+     * @return 结果
+     */
+    @Override
+    public String selectUserPostGroup(Long userId)
+    {
+        List<SysPost> list = postMapper.selectPostsByUserId(userId);
+        if (CollectionUtils.isEmpty(list))
+        {
+            return StringUtils.EMPTY;
+        }
+        return list.stream().map(SysPost::getPostName).collect(Collectors.joining(","));
+    }
+
+    /**
+     * 导入用户数据
+     * 
+     * @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();
+        for (SysUser user : userList)
+        {
+            try
+            {
+                // 验证是否存在这个用户
+                SysUser u = userMapper.selectUserByLoginName(user.getLoginName());
+                if (StringUtils.isNull(u))
+                {
+                    BeanValidators.validateWithException(validator, user);
+                    deptService.checkDeptDataScope(user.getDeptId());
+                    String password = configService.selectConfigByKey("sys.user.initPassword");
+                    user.setPassword(Md5Utils.hash(user.getLoginName() + password));
+                    user.setCreateBy(operName);
+                    userMapper.insertUser(user);
+                    successNum++;
+                    successMsg.append("<br/>" + successNum + "、账号 " + user.getLoginName() + " 导入成功");
+                }
+                else if (isUpdateSupport)
+                {
+                    BeanValidators.validateWithException(validator, user);
+                    checkUserAllowed(u);
+                    checkUserDataScope(u.getUserId());
+                    deptService.checkDeptDataScope(user.getDeptId());
+                    user.setUserId(u.getUserId());
+                    user.setUpdateBy(operName);
+                    userMapper.updateUser(user);
+                    successNum++;
+                    successMsg.append("<br/>" + successNum + "、账号 " + user.getLoginName() + " 更新成功");
+                }
+                else
+                {
+                    failureNum++;
+                    failureMsg.append("<br/>" + failureNum + "、账号 " + user.getLoginName() + " 已存在");
+                }
+            }
+            catch (Exception e)
+            {
+                failureNum++;
+                String loginName = user.getLoginName();
+                if (ExceptionUtil.isCausedBy(e, ConstraintViolationException.class))
+                {
+                    loginName = EscapeUtil.clean(loginName);
+                }
+                String msg = "<br/>" + failureNum + "、账号 " + loginName + " 导入失败:";
+                failureMsg.append(msg + e.getMessage());
+                log.error(msg, e);
+            }
+        }
+        if (failureNum > 0)
+        {
+            failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:");
+            throw new ServiceException(failureMsg.toString());
+        }
+        else
+        {
+            successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:");
+        }
+        return successMsg.toString();
+    }
+
+    /**
+     * 用户状态修改
+     * 
+     * @param user 用户信息
+     * @return 结果
+     */
+    @Override
+    public int changeStatus(SysUser user)
+    {
+        return userMapper.updateUser(user);
+    }
+}
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysConfigMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysConfigMapper.xml
new file mode 100644
index 0000000..bb15593
--- /dev/null
+++ b/ruoyi-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.ruoyi.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>
+ 			sysdate()
+		)
+    </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 = sysdate()
+        </set>
+        where config_id = #{configId}
+    </update>
+	
+	<delete id="deleteConfigById" parameterType="Long">
+		delete from sys_config where config_id = #{configId}
+	</delete>
+	
+    <delete id="deleteConfigByIds" parameterType="String">
+        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/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml
new file mode 100644
index 0000000..8f880f1
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml
@@ -0,0 +1,158 @@
+<?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.ruoyi.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="selectRoleDeptTree" parameterType="Long" resultType="String">
+		select concat(d.dept_id, d.dept_name) as dept_name
+		from sys_dept d
+			left join sys_role_dept rd on d.dept_id = rd.dept_id
+		where d.del_flag = '0' and rd.role_id = #{roleId}
+		order by d.parent_id, d.order_num
+	</select>
+	
+	<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="checkDeptExistUser" parameterType="Long" resultType="int">
+		select count(1) from sys_user where dept_id = #{deptId} and del_flag = '0'
+	</select>
+	
+	<select id="selectDeptCount" parameterType="SysDept" resultType="int">
+		select count(1) from sys_dept
+		where 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>
+	</select>
+	
+	<select id="checkDeptNameUnique" resultMap="SysDeptResult">
+	    <include refid="selectDeptVo"/>
+		where dept_name=#{deptName} and parent_id = #{parentId} and del_flag = '0' limit 1
+	</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="selectChildrenDeptById" parameterType="Long" resultMap="SysDeptResult">
+		select * from sys_dept where find_in_set(#{deptId}, ancestors)
+	</select>
+	
+	<select id="selectNormalChildrenDeptById" parameterType="Long" resultType="int">
+		select count(*) from sys_dept where status = 0 and del_flag = '0' and find_in_set(#{deptId}, ancestors)
+	</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>
+ 			sysdate()
+ 		)
+	</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 = sysdate()
+ 		</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>
+
+	<delete id="deleteDeptById" parameterType="Long">
+		update sys_dept set del_flag = '2' where dept_id = #{deptId}
+	</delete>
+	
+	<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>
+
+</mapper> 
\ No newline at end of file
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysDictDataMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysDictDataMapper.xml
new file mode 100644
index 0000000..deff41d
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/SysDictDataMapper.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.ruoyi.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>
+	</select>
+	
+	<select id="selectDictDataByType" parameterType="String" 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="String">
+ 		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 = sysdate()
+ 		</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>
+ 			sysdate()
+ 		)
+	</insert>
+	
+</mapper> 
\ No newline at end of file
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysDictTypeMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysDictTypeMapper.xml
new file mode 100644
index 0000000..0cd036e
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/SysDictTypeMapper.xml
@@ -0,0 +1,105 @@
+<?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.ruoyi.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 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="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">
+		<include refid="selectDictTypeVo"/>
+		where dict_type = #{dictType} limit 1
+	</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 = sysdate()
+ 		</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>
+ 			sysdate()
+ 		)
+	</insert>
+	
+</mapper> 
\ No newline at end of file
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysLogininforMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysLogininforMapper.xml
new file mode 100644
index 0000000..ac0afb7
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/SysLogininforMapper.xml
@@ -0,0 +1,56 @@
+<?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.ruoyi.system.mapper.SysLogininforMapper">
+
+	<resultMap type="SysLogininfor" id="SysLogininforResult">
+		<id     property="infoId"        column="info_id"           />
+		<result property="loginName"     column="login_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 (login_name, status, ipaddr, login_location, browser, os, msg, login_time)
+		values (#{loginName}, #{status}, #{ipaddr}, #{loginLocation}, #{browser}, #{os}, #{msg}, sysdate())
+	</insert>
+	
+	<select id="selectLogininforList" parameterType="SysLogininfor" resultMap="SysLogininforResult">
+		select info_id,login_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="loginName != null and loginName != ''">
+				AND login_name like concat('%', #{loginName}, '%')
+			</if>
+			<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
+				AND login_time &gt;= #{params.beginTime}
+			</if>
+			<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
+				AND login_time &lt;= #{params.endTime}
+			</if>
+		</where>
+	</select>
+	
+	<delete id="deleteLogininforByIds" parameterType="String">
+ 		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/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml
new file mode 100644
index 0000000..1f08c56
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml
@@ -0,0 +1,191 @@
+<?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.ruoyi.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="url"            column="url"            />
+		<result property="target"         column="target"         />
+		<result property="menuType"       column="menu_type"      />
+		<result property="visible"        column="visible"        />
+		<result property="isRefresh"      column="is_refresh"     />
+		<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, url, target, menu_type, visible, is_refresh, ifnull(perms,'') as perms, icon, create_by, create_time 
+		from sys_menu
+    </sql>
+
+	<select id="selectMenusByUserId" parameterType="Long" resultMap="SysMenuResult">
+		select distinct m.menu_id, m.parent_id, m.menu_name, m.url, m.visible, m.is_refresh, ifnull(m.perms,'') as perms, m.target, 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 = #{userId} and m.menu_type in ('M', 'C') and m.visible = 0  AND ro.status = 0
+		order by m.parent_id, m.order_num
+	</select>
+
+	<select id="selectMenuNormalAll" resultMap="SysMenuResult">
+		select distinct m.menu_id, m.parent_id, m.menu_name, m.url, m.visible, m.is_refresh, ifnull(m.perms,'') as perms, m.target, m.menu_type, m.icon, m.order_num, m.create_time
+		from sys_menu m
+		where m.menu_type in ('M', 'C') and m.visible = 0
+		order by m.parent_id, m.order_num
+	</select>
+
+	<select id="selectMenuAll" resultMap="SysMenuResult">
+		<include refid="selectMenuVo"/>
+		order by parent_id, order_num
+	</select>
+
+	<select id="selectMenuAllByUserId" parameterType="Long" resultMap="SysMenuResult">
+		select distinct m.menu_id, m.parent_id, m.menu_name, m.url, m.visible, m.is_refresh, ifnull(m.perms,'') as perms, m.target, 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 = #{userId}
+		order by m.parent_id, m.order_num
+	</select>
+
+	<select id="selectPermsByUserId" 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.visible = '0' and r.status = '0' and ur.user_id = #{userId}
+	</select>
+
+	<select id="selectPermsByRoleId" 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.visible = '0' and rm.role_id = #{roleId}
+	</select>
+
+	<select id="selectMenuTree" parameterType="Long" resultType="String">
+		select concat(m.menu_id, ifnull(m.perms,'')) as perms
+		from sys_menu m
+			left join sys_role_menu rm on m.menu_id = rm.menu_id
+		where rm.role_id = #{roleId}
+		order by m.parent_id, m.order_num
+	</select>
+
+	<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>
+		</where>
+		order by parent_id, order_num
+	</select>
+
+	<select id="selectMenuListByUserId" parameterType="SysMenu" resultMap="SysMenuResult">
+		select distinct m.menu_id, m.parent_id, m.menu_name, m.url, m.visible, m.is_refresh, ifnull(m.perms,'') as perms, m.target, 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>
+		order by m.parent_id, m.order_num
+	</select>
+
+	<delete id="deleteMenuById" parameterType="Long">
+	    delete from sys_menu where menu_id = #{menuId} or parent_id = #{menuId}
+	</delete>
+
+	<select id="selectMenuById" parameterType="Long" resultMap="SysMenuResult">
+		SELECT t.menu_id, t.parent_id, t.menu_name, t.order_num, t.url, t.target, t.menu_type, t.visible, t.is_refresh, t.perms, t.icon, t.remark,
+			(SELECT menu_name FROM sys_menu WHERE menu_id = t.parent_id) parent_name
+		FROM sys_menu t
+		where t.menu_id = #{menuId}
+	</select>
+
+	<select id="selectCountMenuByParentId" resultType="Integer">
+	    select count(1) from sys_menu where parent_id=#{menuId}  
+	</select>
+
+	<select id="checkMenuNameUnique" parameterType="SysMenu" resultMap="SysMenuResult">
+		<include refid="selectMenuVo"/>
+		where menu_name=#{menuName} and parent_id = #{parentId} limit 1
+	</select>
+
+	<update id="updateMenu" parameterType="SysMenu">
+		update sys_menu
+		<set>
+			<if test="menuName != null and menuName != ''">menu_name = #{menuName},</if>
+			<if test="parentId != null and parentId != 0">parent_id = #{parentId},</if>
+			<if test="orderNum != null">order_num = #{orderNum},</if>
+			<if test="url != null">url = #{url},</if>
+			<if test="target != null and target != ''">target = #{target},</if>
+			<if test="menuType != null and menuType != ''">menu_type = #{menuType},</if>
+			<if test="visible != null">visible = #{visible},</if>
+			<if test="isRefresh != null">is_refresh = #{isRefresh},</if>
+			<if test="perms !=null">perms = #{perms},</if>
+			<if test="icon !=null and icon != ''">icon = #{icon},</if>
+			<if test="remark != null">remark = #{remark},</if>
+			<if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
+			update_time = sysdate()
+		</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="url != null and url != ''">url,</if>
+		<if test="target != null and target != ''">target,</if>
+		<if test="menuType != null and menuType != ''">menu_type,</if>
+		<if test="visible != null">visible,</if>
+		<if test="isRefresh != null">is_refresh,</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="url != null and url != ''">#{url},</if>
+		<if test="target != null and target != ''">#{target},</if>
+		<if test="menuType != null and menuType != ''">#{menuType},</if>
+		<if test="visible != null">#{visible},</if>
+		<if test="isRefresh != null">#{isRefresh},</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>
+		sysdate()
+		)
+	</insert>
+
+</mapper> 
\ No newline at end of file
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysNoticeMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysNoticeMapper.xml
new file mode 100644
index 0000000..a960ff0
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/SysNoticeMapper.xml
@@ -0,0 +1,85 @@
+<?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.ruoyi.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>
+ 			sysdate()
+		)
+    </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 = sysdate()
+        </set>
+        where notice_id = #{noticeId}
+    </update>
+	
+    <delete id="deleteNoticeByIds" parameterType="String">
+        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/ruoyi-system/src/main/resources/mapper/system/SysOperLogMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysOperLogMapper.xml
new file mode 100644
index 0000000..388625e
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/SysOperLogMapper.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.ruoyi.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}, sysdate())
+	</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>
+	</select>
+	
+	<delete id="deleteOperLogByIds" parameterType="String">
+ 		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/ruoyi-system/src/main/resources/mapper/system/SysPostMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysPostMapper.xml
new file mode 100644
index 0000000..86e4751
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/SysPostMapper.xml
@@ -0,0 +1,110 @@
+<?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.ruoyi.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="selectPostsByUserId" parameterType="Long" resultMap="SysPostResult">
+		SELECT p.post_id, p.post_name, p.post_code
+		FROM sys_user u
+			 LEFT JOIN sys_user_post up ON u.user_id = up.user_id
+			 LEFT JOIN sys_post p ON up.post_id = p.post_id
+		WHERE up.user_id = #{userId}
+	</select>
+	
+	<select id="selectPostById" parameterType="Long" resultMap="SysPostResult">
+		<include refid="selectPostVo"/>
+		where post_id = #{postId}
+	</select>
+	
+	<select id="checkPostNameUnique" parameterType="String" resultMap="SysPostResult">
+		<include refid="selectPostVo"/>
+		 where post_name=#{postName} limit 1
+	</select>
+	
+	<select id="checkPostCodeUnique" parameterType="String" resultMap="SysPostResult">
+		<include refid="selectPostVo"/>
+		 where post_code=#{postCode} limit 1
+	</select>
+	
+ 	<delete id="deletePostByIds" parameterType="Long">
+ 		delete from sys_post where post_id in
+ 		<foreach collection="array" item="postId" open="(" separator="," close=")">
+ 			#{postId}
+        </foreach> 
+ 	</delete>
+ 	
+ 	<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 and postSort != ''">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 = sysdate()
+ 		</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 and postSort != ''">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 and postSort != ''">#{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>
+ 			sysdate()
+ 		)
+	</insert>
+
+</mapper> 
\ No newline at end of file
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysRoleDeptMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysRoleDeptMapper.xml
new file mode 100644
index 0000000..7c4139b
--- /dev/null
+++ b/ruoyi-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.ruoyi.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/ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml
new file mode 100644
index 0000000..a168beb
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml
@@ -0,0 +1,134 @@
+<?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.ruoyi.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="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="selectRoleContactVo">
+        select distinct r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope,
+            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>
+    
+    <sql id="selectRoleVo">
+		select r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.status, r.del_flag, r.create_time, r.remark 
+        from sys_role r
+	</sql>
+	
+	<select id="selectRoleList" parameterType="SysRole" resultMap="SysRoleResult">
+		<include refid="selectRoleContactVo"/>
+		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="dataScope != null and dataScope != ''">
+			AND r.data_scope = #{dataScope}
+		</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}
+	</select>
+
+	<select id="selectRolesByUserId" parameterType="Long" resultMap="SysRoleResult">
+		<include refid="selectRoleContactVo"/>
+		WHERE r.del_flag = '0' and ur.user_id = #{userId}
+	</select>
+	
+	<select id="selectRoleById" parameterType="Long" resultMap="SysRoleResult">
+		<include refid="selectRoleVo"/>
+		where r.del_flag = '0' and r.role_id = #{roleId}
+	</select>
+	
+	<select id="checkRoleNameUnique" parameterType="String" resultMap="SysRoleResult">
+		<include refid="selectRoleVo"/>
+		 where r.role_name=#{roleName} and r.del_flag = '0' limit 1
+	</select>
+	
+	<select id="checkRoleKeyUnique" parameterType="String" resultMap="SysRoleResult">
+		<include refid="selectRoleVo"/>
+		 where r.role_key=#{roleKey} and r.del_flag = '0' limit 1
+	</select>
+	
+	<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>
+ 	
+ 	<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 and roleSort != ''">role_sort = #{roleSort},</if>
+ 			<if test="dataScope != null and dataScope != ''">data_scope = #{dataScope},</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 = sysdate()
+ 		</set>
+ 		where role_id = #{roleId}
+	</update>
+ 	
+ 	<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 and roleSort != ''">role_sort,</if>
+ 			<if test="dataScope != null and dataScope != ''">data_scope,</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 and roleSort != ''">#{roleSort},</if>
+ 			<if test="dataScope != null and dataScope != ''">#{dataScope},</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>
+ 			sysdate()
+ 		)
+	</insert>
+	
+</mapper> 
\ No newline at end of file
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml
new file mode 100644
index 0000000..d213bdd
--- /dev/null
+++ b/ruoyi-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.ruoyi.system.mapper.SysRoleMenuMapper">
+
+	<resultMap type="SysRoleMenu" id="SysRoleMenuResult">
+		<result property="roleId"     column="role_id"      />
+		<result property="menuId"     column="menu_id"      />
+	</resultMap>
+
+	<delete id="deleteRoleMenuByRoleId" parameterType="Long">
+		delete from sys_role_menu where role_id=#{roleId}
+	</delete>
+	
+	<select id="selectCountRoleMenuByMenuId" resultType="Integer">
+	    select count(1) from sys_role_menu where menu_id=#{menuId}  
+	</select>
+	
+	<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/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
new file mode 100644
index 0000000..40798d3
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
@@ -0,0 +1,231 @@
+<?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.ruoyi.system.mapper.SysUserMapper">
+
+	<resultMap type="SysUser" id="SysUserResult">
+		<id     property="userId"        column="user_id"         />
+		<result property="deptId"        column="dept_id"         />
+		<result property="loginName"     column="login_name"      />
+		<result property="userName"      column="user_name"       />
+		<result property="userType"      column="user_type"       />
+		<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="salt"          column="salt"            />
+		<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="pwdUpdateDate" column="pwd_update_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.login_name, u.user_name, u.user_type, u.email, u.avatar, u.phonenumber, u.sex, u.password, u.salt, u.status, u.del_flag, u.login_ip, u.login_date, u.pwd_update_date, u.create_by, u.create_time, u.update_by, u.update_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.login_name, u.user_name, u.user_type, u.email, u.avatar, u.phonenumber, u.password, u.sex, u.salt, 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="loginName != null and loginName != ''">
+			AND u.login_name like concat('%', #{loginName}, '%')
+		</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 date_format(u.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(u.create_time,'%Y%m%d') &lt;= date_format(#{params.endTime},'%Y%m%d')
+		</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 FIND_IN_SET (#{deptId},ancestors) ))
+		</if>
+		<!-- 数据范围过滤 -->
+		${params.dataScope}
+	</select>
+	
+	<select id="selectAllocatedList" parameterType="SysUser" resultMap="SysUserResult">
+	    select distinct u.user_id, u.dept_id, u.login_name, u.user_name, u.user_type, u.email, u.avatar, 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="loginName != null and loginName != ''">
+			AND u.login_name like concat('%', #{loginName}, '%')
+		</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.login_name, u.user_name, u.user_type, u.email, u.avatar, 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="loginName != null and loginName != ''">
+			AND u.login_name like concat('%', #{loginName}, '%')
+		</if>
+		<if test="phonenumber != null and phonenumber != ''">
+			AND u.phonenumber like concat('%', #{phonenumber}, '%')
+		</if>
+		<!-- 数据范围过滤 -->
+		${params.dataScope}
+	</select>
+	
+	<select id="selectUserByLoginName" parameterType="String" resultMap="SysUserResult">
+	    <include refid="selectUserVo"/>
+		where u.login_name = #{userName} and u.del_flag = '0'
+	</select>
+	
+	<select id="selectUserByPhoneNumber" parameterType="String" resultMap="SysUserResult">
+		<include refid="selectUserVo"/>
+		where u.phonenumber = #{phonenumber} and u.del_flag = '0'
+	</select>
+	
+	<select id="selectUserByEmail" parameterType="String" resultMap="SysUserResult">
+	    <include refid="selectUserVo"/>
+		where u.email = #{email} and u.del_flag = '0'
+	</select>
+	
+	<select id="checkLoginNameUnique" parameterType="String" resultMap="SysUserResult">
+		select user_id, login_name from sys_user where login_name=#{loginName} and del_flag = '0' limit 1
+	</select>
+	
+	<select id="checkPhoneUnique" parameterType="String" resultMap="SysUserResult">
+		select user_id, phonenumber from sys_user where phonenumber=#{phonenumber} and del_flag = '0' limit 1
+	</select>
+	
+	<select id="checkEmailUnique" parameterType="String" resultMap="SysUserResult">
+		select user_id, email from sys_user where email=#{email} and del_flag = '0' limit 1
+	</select>
+	
+	<select id="selectUserById" parameterType="Long" resultMap="SysUserResult">
+		<include refid="selectUserVo"/>
+		where u.user_id = #{userId}
+	</select>
+	
+	<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>
+ 	
+ 	<update id="updateUser" parameterType="SysUser">
+ 		update sys_user
+ 		<set>
+ 			<if test="deptId != null and deptId != 0">dept_id = #{deptId},</if>
+ 			<if test="loginName != null and loginName != ''">login_name = #{loginName},</if>
+ 			<if test="userName != null and userName != ''">user_name = #{userName},</if>
+ 			<if test="userType != null and userType != ''">user_type = #{userType},</if>
+ 			<if test="email != null and email != ''">email = #{email},</if>
+ 			<if test="phonenumber != null and phonenumber != ''">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="salt != null and salt != ''">salt = #{salt},</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="pwdUpdateDate != null">pwd_update_date = #{pwdUpdateDate},</if>
+ 			<if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
+ 			<if test="remark != null">remark = #{remark},</if>
+ 			update_time = sysdate()
+ 		</set>
+ 		where user_id = #{userId}
+	</update>
+ 	
+ 	<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="loginName != null and loginName != ''">login_name,</if>
+ 			<if test="userName != null and userName != ''">user_name,</if>
+ 			<if test="userType != null and userType != ''">user_type,</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="salt != null and salt != ''">salt,</if>
+ 			<if test="status != null and status != ''">status,</if>
+ 			<if test="pwdUpdateDate != null">pwd_update_date,</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="loginName != null and loginName != ''">#{loginName},</if>
+ 			<if test="userName != null and userName != ''">#{userName},</if>
+ 			<if test="userType != null and userType != ''">#{userType},</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="salt != null and salt != ''">#{salt},</if>
+ 			<if test="status != null and status != ''">#{status},</if>
+ 			<if test="pwdUpdateDate != null">#{pwdUpdateDate},</if>
+ 			<if test="createBy != null and createBy != ''">#{createBy},</if>
+ 			<if test="remark != null and remark != ''">#{remark},</if>
+ 			sysdate()
+ 		)
+	</insert>
+	
+</mapper> 
\ No newline at end of file
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysUserOnlineMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysUserOnlineMapper.xml
new file mode 100644
index 0000000..ff85fd8
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/SysUserOnlineMapper.xml
@@ -0,0 +1,57 @@
+<?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.ruoyi.system.mapper.SysUserOnlineMapper">
+
+	<resultMap type="SysUserOnline" id="SysUserOnlineResult">
+		<id     property="sessionId"         column="sessionId"         />
+		<result property="loginName"         column="login_name"        />
+		<result property="deptName"          column="dept_name"         />
+		<result property="ipaddr"            column="ipaddr"            />
+		<result property="loginLocation"     column="login_location"    />
+		<result property="browser"           column="browser"           />
+		<result property="os"                column="os"                />
+		<result property="status"            column="status"            />
+		<result property="startTimestamp"    column="start_timestamp"   />
+		<result property="lastAccessTime"    column="last_access_time"  />
+		<result property="expireTime"        column="expire_time"       />
+	</resultMap>
+	
+	<sql id="selectOnlineVo">
+       select sessionId, login_name, dept_name, ipaddr, login_location, browser, os, status, start_timestamp, last_access_time, expire_time 
+	   from sys_user_online
+    </sql>
+    
+	<select id="selectOnlineById" parameterType="String" resultMap="SysUserOnlineResult">
+		<include refid="selectOnlineVo"/>
+		where sessionId = #{sessionId}
+	</select>
+
+	<insert id="saveOnline" parameterType="SysUserOnline">
+		replace into sys_user_online(sessionId, login_name, dept_name, ipaddr, login_location, browser, os, status, start_timestamp, last_access_time, expire_time)
+        values (#{sessionId}, #{loginName}, #{deptName}, #{ipaddr}, #{loginLocation}, #{browser}, #{os}, #{status}, #{startTimestamp}, #{lastAccessTime}, #{expireTime})
+	</insert>
+	
+ 	<delete id="deleteOnlineById" parameterType="String">
+ 		delete from sys_user_online where sessionId = #{sessionId}
+ 	</delete>
+ 	
+ 	<select id="selectUserOnlineList" parameterType="SysUserOnline" resultMap="SysUserOnlineResult">
+		<include refid="selectOnlineVo"/>
+		<where>
+			<if test="ipaddr != null and ipaddr != ''">
+				AND ipaddr like concat('%', #{ipaddr}, '%')
+			</if>
+			<if test="loginName != null and loginName != ''">
+				AND login_name like concat('%', #{loginName}, '%')
+			</if>
+		</where>
+	</select>
+	
+	<select id="selectOnlineByExpired" parameterType="String" resultMap="SysUserOnlineResult">
+		<include refid="selectOnlineVo"/> o 
+		WHERE o.last_access_time <![CDATA[ <= ]]> #{lastAccessTime} ORDER BY o.last_access_time ASC
+	</select>
+
+</mapper> 
\ No newline at end of file
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysUserPostMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysUserPostMapper.xml
new file mode 100644
index 0000000..2b90bc4
--- /dev/null
+++ b/ruoyi-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.ruoyi.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/ruoyi-system/src/main/resources/mapper/system/SysUserRoleMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysUserRoleMapper.xml
new file mode 100644
index 0000000..7606692
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/SysUserRoleMapper.xml
@@ -0,0 +1,48 @@
+<?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.ruoyi.system.mapper.SysUserRoleMapper">
+
+	<resultMap type="SysUserRole" id="SysUserRoleResult">
+		<result property="userId"     column="user_id"      />
+		<result property="roleId"     column="role_id"      />
+	</resultMap>
+	
+	<select id="selectUserRoleByUserId" parameterType="Long" resultMap="SysUserRoleResult">
+		select user_id, role_id from sys_user_role where user_id = #{userId}
+	</select>
+
+	<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/ry.bat b/ry.bat
new file mode 100644
index 0000000..ac1e437
--- /dev/null
+++ b/ry.bat
@@ -0,0 +1,67 @@
+@echo off
+
+rem jarƽ��Ŀ¼
+set AppName=ruoyi-admin.jar
+
+rem JVM����
+set JVM_OPTS="-Dname=%AppName%  -Duser.timezone=Asia/Shanghai -Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDateStamps  -XX:+PrintGCDetails -XX:NewRatio=1 -XX:SurvivorRatio=30 -XX:+UseParallelGC -XX:+UseParallelOldGC"
+
+
+ECHO.
+	ECHO.  [1] ����%AppName%
+	ECHO.  [2] �ر�%AppName%
+	ECHO.  [3] ����%AppName%
+	ECHO.  [4] ����״̬ %AppName%
+	ECHO.  [5] �� ��
+ECHO.
+
+ECHO.������ѡ����Ŀ�����:
+set /p ID=
+	IF "%id%"=="1" GOTO start
+	IF "%id%"=="2" GOTO stop
+	IF "%id%"=="3" GOTO restart
+	IF "%id%"=="4" GOTO status
+	IF "%id%"=="5" EXIT
+PAUSE
+:start
+    for /f "usebackq tokens=1-2" %%a in (`jps -l ^| findstr %AppName%`) do (
+		set pid=%%a
+		set image_name=%%b
+	)
+	if  defined pid (
+		echo %%is running
+		PAUSE
+	)
+
+start javaw %JVM_OPTS% -jar %AppName%
+
+echo  starting����
+echo  Start %AppName% success...
+goto:eof
+
+rem ����stopͨ��jps�������pid����������
+:stop
+	for /f "usebackq tokens=1-2" %%a in (`jps -l ^| findstr %AppName%`) do (
+		set pid=%%a
+		set image_name=%%b
+	)
+	if not defined pid (echo process %AppName% does not exists) else (
+		echo prepare to kill %image_name%
+		echo start kill %pid% ...
+		rem ���ݽ���ID��kill����
+		taskkill /f /pid %pid%
+	)
+goto:eof
+:restart
+	call :stop
+    call :start
+goto:eof
+:status
+	for /f "usebackq tokens=1-2" %%a in (`jps -l ^| findstr %AppName%`) do (
+		set pid=%%a
+		set image_name=%%b
+	)
+	if not defined pid (echo process %AppName% is dead ) else (
+		echo %image_name% is running
+	)
+goto:eof
diff --git a/ry.sh b/ry.sh
new file mode 100644
index 0000000..d6a9cf3
--- /dev/null
+++ b/ry.sh
@@ -0,0 +1,86 @@
+#!/bin/sh
+# ./ry.sh start 启动 stop 停止 restart 重启 status 状态
+AppName=ruoyi-admin.jar
+
+# JVM参数
+JVM_OPTS="-Dname=$AppName  -Duser.timezone=Asia/Shanghai -Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDateStamps  -XX:+PrintGCDetails -XX:NewRatio=1 -XX:SurvivorRatio=30 -XX:+UseParallelGC -XX:+UseParallelOldGC"
+APP_HOME=`pwd`
+LOG_PATH=$APP_HOME/logs/$AppName.log
+
+if [ "$1" = "" ];
+then
+    echo -e "\033[0;31m 未输入操作名 \033[0m  \033[0;34m {start|stop|restart|status} \033[0m"
+    exit 1
+fi
+
+if [ "$AppName" = "" ];
+then
+    echo -e "\033[0;31m 未输入应用名 \033[0m"
+    exit 1
+fi
+
+function start()
+{
+    PID=`ps -ef |grep java|grep $AppName|grep -v grep|awk '{print $2}'`
+
+	if [ x"$PID" != x"" ]; then
+	    echo "$AppName is running..."
+	else
+		nohup java $JVM_OPTS -jar $AppName > /dev/null 2>&1 &
+		echo "Start $AppName success..."
+	fi
+}
+
+function stop()
+{
+    echo "Stop $AppName"
+
+	PID=""
+	query(){
+		PID=`ps -ef |grep java|grep $AppName|grep -v grep|awk '{print $2}'`
+	}
+
+	query
+	if [ x"$PID" != x"" ]; then
+		kill -TERM $PID
+		echo "$AppName (pid:$PID) exiting..."
+		while [ x"$PID" != x"" ]
+		do
+			sleep 1
+			query
+		done
+		echo "$AppName exited."
+	else
+		echo "$AppName already stopped."
+	fi
+}
+
+function restart()
+{
+    stop
+    sleep 2
+    start
+}
+
+function status()
+{
+    PID=`ps -ef |grep java|grep $AppName|grep -v grep|wc -l`
+    if [ $PID != 0 ];then
+        echo "$AppName is running..."
+    else
+        echo "$AppName is not running..."
+    fi
+}
+
+case $1 in
+    start)
+    start;;
+    stop)
+    stop;;
+    restart)
+    restart;;
+    status)
+    status;;
+    *)
+
+esac
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 '存放持久化job对象',
+    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表job_name的外键',
+    job_group            varchar(200)    not null            comment 'qrtz_job_details表job_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 '存放持久化job对象',
+    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表trigger_name的外键',
+    trigger_group        varchar(200)    not null            comment 'qrtz_triggers表trigger_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表trigger_name的外键',
+    trigger_group        varchar(200)    not null            comment 'qrtz_triggers表trigger_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 类型,JobStore 并不知道如何存储实例的时候)
+-- ---------------------------- 
+create table QRTZ_BLOB_TRIGGERS (
+    sched_name           varchar(120)    not null            comment '调度名称',
+    trigger_name         varchar(200)    not null            comment 'qrtz_triggers表trigger_name的外键',
+    trigger_group        varchar(200)    not null            comment 'qrtz_triggers表trigger_group的外键',
+    blob_data            blob            null                comment '存放持久化Trigger对象',
+    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 '存放持久化calendar对象',
+    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表trigger_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 '调度器实例id',
+    trigger_name         varchar(200)    not null            comment 'qrtz_triggers表trigger_name的外键',
+    trigger_group        varchar(200)    not null            comment 'qrtz_triggers表trigger_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表trigger_name的外键',
+    trigger_group        varchar(200)    not null            comment 'qrtz_triggers表trigger_group的外键',
+    str_prop_1           varchar(512)    null                comment 'String类型的trigger的第一个参数',
+    str_prop_2           varchar(512)    null                comment 'String类型的trigger的第二个参数',
+    str_prop_3           varchar(512)    null                comment 'String类型的trigger的第三个参数',
+    int_prop_1           int             null                comment 'int类型的trigger的第一个参数',
+    int_prop_2           int             null                comment 'int类型的trigger的第二个参数',
+    long_prop_1          bigint          null                comment 'long类型的trigger的第一个参数',
+    long_prop_2          bigint          null                comment 'long类型的trigger的第二个参数',
+    dec_prop_1           numeric(13,4)   null                comment 'decimal类型的trigger的第一个参数',
+    dec_prop_2           numeric(13,4)   null                comment 'decimal类型的trigger的第二个参数',
+    bool_prop_1          varchar(1)      null                comment 'Boolean类型的trigger的第一个参数',
+    bool_prop_2          varchar(1)      null                comment 'Boolean类型的trigger的第二个参数',
+    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/ruoyi.html b/sql/ruoyi.html
new file mode 100644
index 0000000..abd2596
--- /dev/null
+++ b/sql/ruoyi.html
@@ -0,0 +1,2890 @@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<!DOCTYPE html>
+<html lang='en' xmlns='http://www.w3.org/1999/xhtml' >
+<head>
+<title>RuoYi</title>
+<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'/>
+<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
+<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">
+<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script>
+<!--<script src="https://code.jquery.com/jquery-3.1.1.slim.min.js" integrity="sha384-A7FZj7v+d/sdmMqp/nOQwliLvUsJfDHW+k9Omg/a/EheAdgtzNs3hpfag6Ed950n" crossorigin="anonymous"></script>-->
+<!--<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" crossorigin="anonymous"></script>-->
+<link rel="shortcut icon" href="https://www.dbschema.com/images/favicon.ico">
+<style type='text/css'>
+body {
+    font-family: 'Segoe UI', 'Lucida sans', Dialog;
+    font-size: 13px;
+    background-color:#f5f5f5;
+    margin: 10px;
+}
+</style>
+</head>
+
+<body>
+<div class='svg-container'>
+<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'   width='1890' height='1100' viewBox='0 0 1890 1100' >
+  <script type='text/ecmascript'>
+  <![CDATA[
+  function hghl(el) { for ( var i in el ){ var elem = document.getElementById(el[i]); if ( elem != null ) elem.setAttribute('class','highlight');  }  }
+  function uhghl(el) { for ( var i in el ){ var elem = document.getElementById(el[i]); if ( elem != null ) elem.setAttribute('class','scene'); }  } 
+  ]]>
+  </script> 
+
+<style type='text/css'>
+  text                { fill:#000000; font-family: SimSun, 'Trebuchet MS', Dialog; font-size:11px; }
+  a text:hover        { fill:#94025f; text-shadow: 0px 0px 6px #d0ce00; font-size:13px; }
+  text.highlight      { fill:#94025f; text-shadow: 0px 0px 4px #eac533; font-size:13px; }
+  text.colType        { fill:#b3b3b3; }
+  text.relName        { fill:#b09c7c; }
+  path                { stroke:#5c554f; stroke-width:1.15; fill:none; }
+  path                { stroke:#5c554f; stroke-width:1.15; fill:none;}
+  path.virtual        { stroke:#b7642d; }
+  path.logo           { fill:#fbeac0;fill-opacity:1;stroke-width:0.3;stroke:#222222; }
+  path.dotted         { stroke-dasharray:4,2; }
+  path.scene          { stroke-width:10; opacity:0;}
+  path.highlight      { stroke-width:5; stroke:#c1a662; opacity:0.6;}
+  rect.entity         { fill:#ffffff; stroke:#aaa; stroke-width:1;shape-rendering:crispEdges;filter:url(#shadow); }
+  line.delim          { stroke-width:1; shape-rendering:crispEdges; }
+  text.callout        { fill:#000000; font-family: SimSun, 'Trebuchet MS', Dialog; font-size:12px; }
+  rect.callout        { fill:url(#calloutGradient); stroke:#bebdbd; stroke-width:0.5; filter: url(#shadow);}
+  rect.grp            { stroke:#b1b1b1; stroke-width:1.7; opacity:0.8; }
+  path.st0            { fill:#ececec;fill-opacity:1;stroke-width:0.6;stroke:#aaaaaa; }
+</style>
+<defs>
+  <pattern id='layoutBgA' patternUnits='userSpaceOnUse'  width='10' height='20' x='0' y='0' viewBox='0 0 5 10'>  
+     <line x1='-2' y1='1' x2='7' y2='10' stroke='#f3f3f3' stroke-width='.5'/>  
+     <line x1='-2' y1='6' x2='7' y2='15' stroke='#f3f3f3' stroke-width='.5'/>  
+     <line x1='-2' y1='-4' x2='7' y2='5' stroke='#f3f3f3' stroke-width='.5'/>  
+  </pattern>  
+  <radialGradient id='layoutBgB' gradientUnits='userSpaceOnUse' cx='50%' cy='50%' r='75%' fx='46%' fy='22%'>
+     <stop offset='0%' stop-opacity='.2' stop-color='#f5f5f5' />  
+     <stop offset='100%' stop-color='#efefef' />  
+  </radialGradient>
+  <pattern id='layoutBgTr' patternUnits='userSpaceOnUse'  width='300' height='300' x='0' y='0' viewBox='0 0 300 300'>  
+  <path class='st0' d='m 62.011835,91.267143 c 3.536475,3.175214 2.262669,8.705999 -1.637711,11.015197 -3.594697,5.8423 -6.34682,-2.892623 -9.715478,-4.653898 -5.609222,-2.838926 2.050802,-6.680123 4.77004,-8.319046 2.334696,-0.724067 4.935143,0.312302 6.583149,1.957747 z m -2.720492,2.538595 c -2.698397,-3.517732 -9.282815,1.269287 -3.69635,3.568637 2.765331,5.605665 7.052809,-0.56184 3.69635,-3.568637 z' />
+  <path class='st0' d='m 72.25864,84.624638 c 4.108046,3.143003 -0.737059,6.895259 -1.994918,8.323564 -3.586718,5.561143 -6.495079,-4.197379 -10.07759,-5.582178 -4.443422,-1.088878 1.349298,-7.249213 2.503526,-2.503449 2.464639,4.517161 2.304019,-3.70697 6.291113,-1.995914 1.280083,0.137865 2.410691,0.864819 3.277869,1.757977 z m -2.646109,2.323242 c -4.797162,-3.078383 -2.810517,6.305507 0.515161,1.990646 0.296432,-0.688582 0.01209,-1.493412 -0.515161,-1.990646 z' />
+  <path class='st0' d='m 78.230641,79.436735 c 4.142121,3.027466 -2.020102,10.435276 -3.450543,5.477315 3.306312,-5.248112 -9.186019,-2.220094 -5.805994,-8.77679 -0.544141,-3.93011 6.797826,-2.102227 3.386015,0.245477 -0.181085,2.915838 4.637371,1.019311 5.870522,3.053982 z' />
+  <path class='st0' d='m 82.744502,72.597397 c -4.901605,1.926521 1.146497,6.285555 2.559694,2.225783 6.21817,3.539297 -6.640186,8.416664 -7.590325,1.997457 -2.24365,-2.914883 4.026676,-10.148618 5.030631,-4.22324 z' />
+  <path class='st0' d='m 90.727458,64.259158 c 1.583987,1.690029 3.321317,3.2696 4.81267,5.026353 -2.535706,6.849794 -6.445583,-5.918773 -8.388458,-0.167017 0.782768,2.03426 5.877405,3.752079 2.670979,5.711199 -3.315119,1.519161 -5.782422,-5.157931 -8.858893,-6.780537 -4.229842,-1.139816 1.510134,-7.074128 2.586227,-2.385939 3.141198,5.495193 1.840537,-5.598295 7.177489,-1.404062 z' />
+  <path class='st0' d='m 99.622027,58.374253 c 1.493293,1.9548 -6.281936,7.024659 -0.885258,4.740447 0.386238,-4.434477 6.131941,-1.133173 2.175851,1.618005 -4.421491,6.12739 -13.666659,-3.151506 -7.058299,-7.136537 1.785129,-1.119329 4.348209,-0.743179 5.767706,0.778085 z m -2.900824,1.89746 c -3.608188,-2.208543 -2.280489,5.00803 -0.12563,0.329531 z' />
+  <path class='st0' d='m 115.18023,50.570441 c -1.61703,5.201678 -4.6204,-0.364502 -7.01598,-1.749619 -4.40977,2.122562 4.89641,4.913939 1.89606,7.018157 -2.48061,3.877635 -4.11404,-4.060614 -7.01192,-2.6391 -1.76318,3.107252 7.28394,6.252304 0.87346,7.876177 -1.74515,-2.956649 -9.055498,-5.610518 -3.950378,-8.66062 1.696478,1.897023 1.770418,-5.43503 5.347308,-3.072411 -0.44014,-5.474701 6.11995,-4.950882 7.7846,-0.815355 0.69076,0.682329 1.39587,1.351469 2.07685,2.042771 z' />
+  <path class='st0' d='m 120.54891,39.417125 c 2.50681,1.334124 4.80466,4.941837 0.75044,5.297362 -0.46414,1.89865 -5.25369,5.602652 -8.01742,1.815475 -3.87345,-2.809139 -0.0676,-7.603869 2.3036,-8.133924 1.6795,-3.853018 3.16703,-1.199465 4.96338,1.021087 z m -2.2464,2.175828 c -4.8049,-2.992167 -3.08987,6.380358 0.42374,2.036159 0.33052,-0.677508 0.12099,-1.525836 -0.42374,-2.036159 z' />
+  <path class='st0' d='m 128.50836,24.06821 c -5.10403,3.035506 3.20535,6.383175 5.05938,9.450276 -0.91853,2.95886 -4.06493,3.650723 -5.34691,0.265618 -2.25715,-2.089033 -4.65672,-6.948595 -7.07024,-2.584686 -4.71758,-3.764394 3.81217,-5.812054 5.12382,-9.226328 0.75738,0.677487 1.38637,1.498638 2.23389,2.095175 z' />
+  <path class='st0' d='m 137.14366,22.299812 c -3.09615,2.259885 0.71537,4.412454 1.99042,6.435866 -3.08975,5.080354 -5.91384,-2.98648 -8.92144,-4.094939 1.44369,-3.219573 3.3497,-1.335928 4.27156,-4.41058 0.97822,-0.894325 1.75044,1.871047 2.65946,2.069653 z' />
+  <path class='st0' d='m 136.85093,14.890174 c 2.31562,5.283511 -7.17975,1.771993 -1.29675,-0.475107 l 0.7108,0.08973 z m 4.867,5.317354 c 2.56912,1.439678 4.26517,4.725219 0.30678,5.233637 -1.56592,-3.098864 -9.51683,-5.749448 -3.64502,-8.633714 1.17746,0.325095 2.15375,2.591149 3.33824,3.400077 z' />
+  <path class='st0' d='m 149.95578,11.976423 c 2.50679,1.334142 4.80455,4.94192 0.75041,5.297394 -0.4641,1.898604 -5.25368,5.602645 -8.0174,1.81545 -3.87347,-2.80918 -0.0676,-7.603844 2.30366,-8.133968 1.67949,-3.8530525 3.16695,-1.1993573 4.96333,1.021124 z m -2.24641,2.175828 c -4.80489,-2.992177 -3.08986,6.380343 0.42374,2.036167 0.33055,-0.677518 0.121,-1.52585 -0.42374,-2.036167 z' />
+  <path class='st0' d='m 153.26135,7.538431 c 2.60497,1.5799548 6.03999,5.944272 1.08117,6.050232 -2.53319,-3.231828 -7.20316,-6.4304525 -8.84748,-9.4582682 1.89121,-2.8664883 3.78452,-2.247699 5.38514,0.8929426 0.78017,0.8503859 1.57195,1.6911437 2.38118,2.5150667 z' />
+  </pattern>  
+  <linearGradient id='groupUnderTitleLine' x1='0%' y1='0%' x2='100%' y2='0%' >
+          <stop offset='0%' stop-color='#999999' stop-opacity='0.7'/> 
+          <stop offset='100%' stop-color='#999999' stop-opacity='0' /> 
+   </linearGradient>
+  <radialGradient id='calloutGradient' cx='25%' cy='20%' r='80%' fx='10%' fy='10%'>
+	   <stop offset='0%' stop-color='#ffffff' />
+    <stop offset='100%' stop-color='#f8f6d1' />
+  </radialGradient>
+  <filter id='shadow' width='120%' height='120%'> 
+      <feOffset result='offOut' in='SourceGraphic' dx='1' dy='1' /> 
+      <feColorMatrix result='matrixOut' in='offOut' type='matrix' 
+      values='0.1 0 0 0 0 0 0.4 0 0 0 0 0 0.6 0 0 0 0 0 0.3 0' /> 
+      <feGaussianBlur result='blurOut' in='matrixOut' stdDeviation='3' /> 
+      <feBlend in='SourceGraphic' in2='blurOut' mode='normal' /> 
+    </filter> 
+  <filter id='fkShadow' height='130%'> 
+    <feGaussianBlur in='SourceAlpha' stdDeviation='1.5'/> <!-- stdDeviation is how much to blur -->
+    <feOffset dx='1.2' dy='1.2' result='offsetblur'/> <!-- how much to offset -->
+    <feMerge>
+    <feMergeNode/> <!-- this contains the offset blurred image -->
+    <feMergeNode in='SourceGraphic'/> <!-- this contains the element that the filter is applied to -->
+    </feMerge>
+  </filter>
+  <radialGradient id='legendGradient' fx='5%' fy='5%' r='75%' spreadMethod='pad'>
+          <stop offset='0%' stop-color='#eefbf2' stop-opacity='1'/> 
+          <stop offset='100%' stop-color='#cff9cb' stop-opacity='1' /> 
+   </radialGradient>
+  <symbol id='calloutArrowDown' overflow='visible' >
+      <path d='M 0,0 L 7,11 L 15,0 z' style='fill:#f8f6d1;stroke:none; filter: url(#shadow);' />
+      <path d='M 0,0 L 7,11 L 15,0' style='stroke:#bebdbd; stroke-width:0.5;' />
+  </symbol>
+  <symbol id='calloutArrowUp' overflow='visible' >
+      <path d='M 0,15 L 7,3 L 15,15 z' style='fill:#ffffff; stroke:none; filter: url(#shadow);' />
+      <path d='M 0,15 L 7,3 L 15,15' style='stroke:#bebdbd; stroke-width:0.5;' />
+  </symbol>
+  <symbol id='pk' overflow='visible' >
+    <g transform='scale(0.99)'>
+     <path style='fill:#fffa7d;stroke:#765f03;stroke-width:0.6;stroke-linecap:round;stroke-linejoin:round;'
+        d='M 9.3678877,3.5695485 C 9.1030218,3.2729386 9.0796382,2.7628519 9.3396185,2.4517097 9.5449651,2.1956495 9.9040386,2.0980533 10.199638,2.2169415 10.533525,2.3415459 10.775153,2.706942 10.750675,3.0842709 10.737029,3.3980003 10.541153,3.699122 10.258248,3.8066067 9.966649,3.9250429 9.6169668,3.8418805 9.4008073,3.6062324 9.3894892,3.5943518 9.3785264,3.582104 9.3678886,3.5695487 z M 11.226617,6.9916004 C 11.888137,6.3548946 12.293488,5.4172188 12.311087,4.442353 12.378144,2.7379364 11.248678,1.0541269 9.7322318,0.44767357 8.3887112,-0.1280313 6.7865012,0.26822889 5.8918395,1.4007929 5.080823,2.3839145 4.9336815,3.8452096 5.3635544,5.101615 L 4.3670905,5.315913 C 4.0664984,5.3682645 4.0967703,5.6316724 4.2574957,5.8208829 L 4.9124,6.5655244 4.1543436,7.2512357 3.2136002,7.2163506 3.1674775,8.5586827 2.0406832,8.5086512 1.5965306,8.9299953 1.5471661,10.179833 0.75616674,10.195223 0.2112857,10.758575 0.15354288,11.735988 0.07199052,12.765553 c 0.36440953,0.238225 0.79006967,0.195492 1.44938278,-0.02675 L 6.3033562,8.1282037 6.8217102,8.6765688 C 6.9985465,8.8799427 7.3003699,8.7497574 7.358381,8.5016252 L 7.4938877,7.5084164 c 0.8537488,0.3985387 1.8303125,0.4711541 2.6851793,0.1427713 0.393927,-0.1407258 0.746858,-0.3701772 1.04755,-0.6595873 z'/>
+     <path d='M 6.8014948,6.3102123 0.15369063,13.024481 0.21560535,12.141962 6.0062342,6.2683782 z'
+        style='fill:#ffe5a5;fill-opacity:1;stroke:#854e31;stroke-width:0.06912433;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:3.00300009'/>
+    </g>
+  </symbol>
+  <symbol id='dist' overflow='visible' >
+    <g transform='scale(0.99)'>
+      <path style='fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;' d='M 0.177,11.431 12.28,11.449'/>
+      <path style='fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;' d='m 6.124,3.954 0.066,7.154 v 0'/>
+      <rect width='11.78' height='3.40' x='0.40' y='0.44' style='fill:#fffa7d;stroke:#765f03;stroke-width:0.6;' ry='0.83'/>
+      <rect width='11.78' height='3.40' x='0.40' y='5.609' style='fill:#fffa7d;stroke:#765f03;stroke-width:0.6;' ry='0.832'/>
+    </g>
+  </symbol>
+  <symbol id='unq' overflow='visible' >
+    <g transform='scale(0.99)'>
+      <rect style='fill:#fbea8e;stroke:#7e4d31;stroke-width:0.71934468;stroke-linecap:round;stroke-linejoin:round;'
+         width='2.29' height='8.43' x='7.48' y='-0.76' ry='1.14' transform='matrix(0.701,0.713,-0.727,0.685,0,0)' />
+      <path style='fill:white;stroke:#858585;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;'
+         d='m 26.04,8.64 a 4.13,4.13 0 1 1 -8.26,0 4.13,4.13 0 1 1 8.26,0 z'
+         transform='matrix(1.025,0,0,0.987,-14.690,-3.862)' />
+      <text x='5.8' y='7.4' style='font-size:7px;fill:#8a8a8a;'>1</text>
+    </g>
+  </symbol>
+  <symbol id='idx' overflow='visible' >
+    <g transform='scale(0.99)'>
+      <rect style='fill:#fbea8e;stroke:#7e4d31;stroke-width:0.71934468;stroke-linecap:round;stroke-linejoin:round;'
+         width='2.29' height='8.43' x='7.48' y='-0.76' ry='1.14' transform='matrix(0.701,0.713,-0.727,0.685,0,0)' />
+      <path style='fill:white;stroke:#858585;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;'
+         d='m 26.04,8.64 a 4.13,4.13 0 1 1 -8.26,0 4.13,4.13 0 1 1 8.26,0 z'
+         transform='matrix(1.025,0,0,0.987,-14.690,-3.862)' />
+    </g>
+  </symbol>
+  <symbol id='fk' overflow='visible' >
+    <g transform='scale(0.87)'>
+      <path style='fill:#f3e1b7;stroke:#7e471f;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;'
+      d='M 12.48,0.33 7.07,0.89 9.067,2.974 0.329,11.731 1.073,12.597 9.811,3.841 11.77,5.78 z' />
+    </g>
+  </symbol>
+  <symbol id='ref' overflow='visible' >
+    <g transform='scale(0.87)'>
+      <path style='fill:#f3e1b7;stroke:#7e471f;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;'
+          d='M 0.10,12.70 5.31,12.15 3.40,10.06 11.82,1.32 11.11,0.45 2.68,9.19 0.80,7.24 z'/>
+    </g>
+  </symbol>
+  <symbol id='flag0' overflow='visible' >
+    <g transform='scale(0.92)'>
+      <path style='fill:#b7d0f6;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;'
+          d='M 0.12,12.67 0.16,7.22 C 2.59,7.22 4.13,8.78 9.22,4.22 5.68,4.98 2.53,4.50 0.09,1.80 z'/>
+    </g>
+  </symbol>
+  <symbol id='flag1' overflow='visible' >
+    <g transform='scale(0.92)'>
+      <path style='fill:#f4a393;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;'
+          d='M 0.12,12.67 0.16,7.22 C 2.59,7.22 4.13,8.78 9.22,4.22 5.68,4.98 2.53,4.50 0.09,1.80 z'/>
+    </g>
+  </symbol>
+  <symbol id='flag2' overflow='visible' >
+    <g transform='scale(0.92)'>
+      <path style='fill:#77ec8b;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;'
+          d='M 0.12,12.67 0.16,7.22 C 2.59,7.22 4.13,8.78 9.22,4.22 5.68,4.98 2.53,4.50 0.09,1.80 z'/>
+    </g>
+  </symbol>
+  <symbol id='nn' overflow='visible' >
+  <path style='stroke:#9b3e50;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;'
+          d='M 0,0 3,3 M 0,3 3,0 z'/>
+  </symbol>
+  <symbol id='view' overflow='visible' >
+    <g transform='scale(0.99)'>
+     <line x1='12' y1='6' x2='19' y2='0' stroke='black' stroke-width='0.5' />
+     <line x1='0' y1='6' x2='7' y2='0' stroke='black' stroke-width='0.5' />
+     <circle cx='3' cy='6' r='3' fill='#f9ebbc' stroke='black' stroke-width='0.5'/>
+     <circle cx='10' cy='6' r='3' fill='#f9ebbc' stroke='black' stroke-width='0.5'/>
+    </g>
+  </symbol>
+  <marker id='arrow01' viewBox='0 0 15.00 7.50' refX='7.50' refY='3.75' markerUnits='strokeWidth' markerWidth='15.00' markerHeight='7.50' orient='auto'>
+    <path d='M 7.500,3.750 L 15.000,3.750 L 7.500,0.000 L 15.000,3.750 L 7.500,7.500' />
+  </marker>
+  <marker id='arrow1' viewBox='0 0 15.00 7.50' refX='7.50' refY='3.75' markerUnits='strokeWidth' markerWidth='15.00' markerHeight='7.50' orient='auto'>
+    <path d='M 7.500,3.750 L 15.000,3.750 L 7.500,0.000 L 15.000,3.750 L 7.500,7.500' />
+  </marker>
+  <marker id='foot01' viewBox='0 0 15.00 7.50' refX='7.50' refY='3.75' markerUnits='strokeWidth' markerWidth='15.00' markerHeight='7.50' orient='auto'>
+    <path d='M 0.00,3.75 L 15.00,3.75 z' />
+    <circle cx='11.25' cy='3.75' r='2.50' style='fill:white;stroke:#5e554d;' />
+    <path d='M 3.75,0.00 L 3.75, 7.50 z' />
+  </marker>
+  <marker id='foot0p' viewBox='0 0 15.00 7.50' refX='7.50' refY='3.75' markerUnits='strokeWidth' markerWidth='15.00' markerHeight='7.50' orient='auto'>
+    <path d='M 0.00,3.75 L 15.00,3.75 z' />
+    <circle cx='11.25' cy='3.75' r='2.50' style='fill:white;stroke:#5e554d;' />
+    <path d='M 0.00,0.00 L 7.50,3.75 L 0.00,7.50' />
+  </marker>
+  <marker id='foot1' viewBox='0 0 15.00 7.50' refX='7.50' refY='3.75' markerUnits='strokeWidth' markerWidth='15.00' markerHeight='7.50' orient='auto'>
+    <path d='M 0.00,3.75 L 15.00,3.75 z' />
+    <path d='M 7.50,0.00 L 7.50, 7.50 z' />
+    <path d='M 3.75,0.00 L 3.75, 7.50 z' />
+  </marker>
+  <marker id='foot1p' viewBox='0 0 15.00 7.50' refX='7.50' refY='3.75' markerUnits='strokeWidth' markerWidth='15.00' markerHeight='7.50' orient='auto'>
+    <path d='M 0.00,3.75 L 15.00,3.75 z' />
+    <path d='M 7.50,0.00 L 7.50, 7.50 z' />
+    <path d='M 0.00,0.00 L 7.50,3.75 L 0.00,7.50' />
+  </marker>
+  <linearGradient id='tbg_bfd4f5' x1='0%' y1='0%' x2='0%' y2='100%' >
+     <stop offset='0%' stop-color='#496ba1' /> 
+     <stop offset='100%' stop-color='#1f4682' /> 
+  </linearGradient>
+  <linearGradient id='tbg_c8f5bf' x1='0%' y1='0%' x2='0%' y2='100%' >
+     <stop offset='0%' stop-color='#58a149' /> 
+     <stop offset='100%' stop-color='#30821f' /> 
+  </linearGradient>
+  <linearGradient id='tbg_f5ddbf' x1='0%' y1='0%' x2='0%' y2='100%' >
+     <stop offset='0%' stop-color='#a17a49' /> 
+     <stop offset='100%' stop-color='#82561f' /> 
+  </linearGradient>
+  <linearGradient id='tbg_bfbff5' x1='0%' y1='0%' x2='0%' y2='100%' >
+     <stop offset='0%' stop-color='#4949a1' /> 
+     <stop offset='100%' stop-color='#1f1f82' /> 
+  </linearGradient>
+</defs>
+
+<!-- == Desktop == -->
+<rect x='1' y='1' width='1888' height='1098' rx='7' ry='7' style='fill:url(#layoutBgB); stroke:#777777; stroke-width:0.5;' />
+<rect x='1' y='1' width='1888' height='1098' rx='7' ry='7' style='fill:url(#layoutBgA); stroke:#777777; stroke-width:0.5;' />
+
+<!-- == Legend == -->
+<g transform='translate(10,10)'>
+  <rect x='10' y='10' width='330' height='56' rx='6' ry='6' style='fill:url(#legendGradient);filter:url(#shadow);'/> 
+  <text x='20' y='43'>RuoYi</text> 
+  <text x='20' y='57' style='fill:#aaaaaa; font-size:11px;'><tspan>Move the mouse over tables &amp; columns to read the comments.</tspan></text> 
+<a xlink:href='https://www.dbschema.com'> <path class='logo' d='m 32.309685,20.963194 c 0.411708,4.732616 -4.298055,7.925636 -8.723583,6.970196 -6.616967,1.8448 -2.656457,-6.434594 -3.911969,-10.01566 -2.15469,-5.89407 6.06247,-3.508505 9.167655,-2.863689 2.199228,1.054873 3.389343,3.582089 3.467897,5.909153 z m -3.720955,0.01451 c 0.434195,-4.414565 -7.644142,-5.37533 -5.137307,0.107342 -1.812268,5.992146 5.532698,4.379388 5.137307,-0.107342 z' /> <path class='logo' d='m 44.329732,23.050637 c 0.850982,5.097305 -5.250434,4.558924 -7.144836,4.752415 -6.418993,1.64391 -1.872992,-7.49274 -3.541914,-10.942842 -2.499646,-3.817859 5.939283,-4.402698 3.538545,-0.13612 -1.287874,4.989123 4.215411,-1.154796 5.956717,2.809584 0.840273,0.970849 1.168829,2.272413 1.191488,3.516963 z m -3.519477,-0.09299 c -1.398216,-5.518069 -6.361061,2.717467 -0.984368,1.810718 0.686994,-0.30388 1.029454,-1.087638 0.984368,-1.810718 z' /> <path class='logo' d='m 52.234961,23.301163 c 0.954818,5.035675 -8.606408,6.284861 -6.262292,1.674914 6.000358,-1.604717 -5.188764,-7.870044 1.75972,-10.384908 2.288682,-3.253567 6.399287,3.075831 2.304111,2.48058 -2.124941,2.016587 2.688777,3.89858 2.198472,6.229403 z' /> <path class='logo' d='m 60.204336,21.349224 c -4.894917,-1.916474 -3.458707,5.391212 0.347494,3.37231 2.120589,6.821713 -10.599623,1.664746 -6.906229,-3.691132 0.354172,-3.663246 9.875349,-4.711252 6.558735,0.318822 z' /> <path class='logo' d='m 71.730617,20.654299 c 0.0013,2.316285 0.190131,4.655698 0.07825,6.958009 -6.532419,3.303565 -0.660423,-8.722256 -6.009639,-5.821653 -0.818815,2.024533 1.726403,6.746337 -1.95327,6.005484 -3.458346,-1.137537 -0.696275,-7.713407 -1.833252,-10.994208 -2.308916,-3.710131 5.93704,-4.164951 3.518609,0.0063 -1.462376,6.166445 5.169629,-2.857523 6.19931,3.846079 z' /> <path class='logo' d='m 82.245738,22.378957 c -0.24581,2.448954 -9.386766,0.8867 -3.885979,2.877055 3.312576,-2.99157 5.250902,3.334514 0.482647,2.665545 -7.415384,1.492275 -7.823196,-11.597641 -0.275476,-10.032117 2.068161,0.391458 3.682204,2.408824 3.678808,4.489517 z m -3.414436,-0.578473 c -1.124703,-4.072004 -5.087405,2.125488 -0.316922,0.156453 z' /> <path class='logo' d='m 98.936899,27.222794 c -4.73541,2.718339 -3.1239,-3.406557 -3.92611,-6.050494 -4.66985,-1.438471 0.21621,6.932413 -3.41219,6.438039 -4.46096,1.160054 -0.22824,-5.774711 -3.31526,-6.700429 -3.410722,1.082173 1.04451,9.536575 -4.745091,6.372895 0.746632,-3.355214 -2.776394,-10.269232 3.034971,-9.038963 -0.058,2.544602 5.00686,-2.785359 6.00342,1.37844 3.42021,-4.316316 7.851251,0.524966 6.24018,4.690538 0.0379,0.969988 0.0954,1.940046 0.12008,2.909974 z' /> <path class='logo' d='m 110.47859,22.686058 c 0.91826,2.682088 0.13016,6.890551 -3.0725,4.397004 -1.63641,1.077877 -7.664291,0.541832 -7.09365,-4.114836 -0.907891,-4.692933 5.14729,-5.625578 7.24058,-4.40354 3.85932,-1.686263 3.13176,1.271515 2.92557,4.121372 z m -3.12695,0.0704 c -1.46278,-5.460062 -6.61615,2.5826 -1.08221,1.782003 0.70431,-0.272594 1.13111,-1.037444 1.08221,-1.782003 z' /> </a>
+</g>
+
+<g transform='translate(0,110)'>
+<!-- == Fk 'qrtz_blob_triggers_qrtz_blob_triggers_ibfk_1' == -->
+<path id='qrtz_blob_triggers_qrtz_blob_triggers_ibfk_1'  onmouseover="hghl(['qrtz_blob_triggers_qrtz_blob_triggers_ibfk_1','ry.qrtz_blob_triggers.sched_name','ry.qrtz_blob_triggers.trigger_name','ry.qrtz_blob_triggers.trigger_group','ry.qrtz_triggers.sched_name','ry.qrtz_triggers.trigger_name','ry.qrtz_triggers.trigger_group'])" onmouseout="uhghl(['qrtz_blob_triggers_qrtz_blob_triggers_ibfk_1','ry.qrtz_blob_triggers.sched_name','ry.qrtz_blob_triggers.trigger_name','ry.qrtz_blob_triggers.trigger_group','ry.qrtz_triggers.sched_name','ry.qrtz_triggers.trigger_name','ry.qrtz_triggers.trigger_group'])" transform='translate(7,0)' class='scene' d='M 270 525 L 270,480' >
+	<title>Fk qrtz_blob_triggers_ibfk_1
+qrtz_blob_triggers ref qrtz_triggers ( sched_name, trigger_name, trigger_group )</title>
+</path>
+<path transform='translate(7,0)' marker-start='url(#foot1)' marker-end='url(#arrow1)'    d='M 270 525 L 270,480' ></path>
+<text x='272' y='520' transform='rotate(270 272,520)' title='Fk qrtz_blob_triggers_ibfk_1
+qrtz_blob_triggers ref qrtz_triggers ( sched_name, trigger_name, trigger_group )' class='relName' style='fill:#5f789f'>sched_name,trigger_name,trigger_group</text>
+<!-- == Fk 'qrtz_cron_triggers_qrtz_cron_triggers_ibfk_1' == -->
+<path id='qrtz_cron_triggers_qrtz_cron_triggers_ibfk_1'  onmouseover="hghl(['qrtz_cron_triggers_qrtz_cron_triggers_ibfk_1','ry.qrtz_cron_triggers.sched_name','ry.qrtz_cron_triggers.trigger_name','ry.qrtz_cron_triggers.trigger_group','ry.qrtz_triggers.sched_name','ry.qrtz_triggers.trigger_name','ry.qrtz_triggers.trigger_group'])" onmouseout="uhghl(['qrtz_cron_triggers_qrtz_cron_triggers_ibfk_1','ry.qrtz_cron_triggers.sched_name','ry.qrtz_cron_triggers.trigger_name','ry.qrtz_cron_triggers.trigger_group','ry.qrtz_triggers.sched_name','ry.qrtz_triggers.trigger_name','ry.qrtz_triggers.trigger_group'])" transform='translate(7,0)' class='scene' d='M 420 540 L 397,540 Q 390,540 390,532 L 390,472 Q 390,465 382,465 L 375,465' >
+	<title>Fk qrtz_cron_triggers_ibfk_1
+qrtz_cron_triggers ref qrtz_triggers ( sched_name, trigger_name, trigger_group )</title>
+</path>
+<path transform='translate(7,0)' marker-start='url(#foot1)' marker-end='url(#arrow1)'    d='M 420 540 L 397,540 Q 390,540 390,532 L 390,472 Q 390,465 382,465 L 375,465' ></path>
+<text x='205' y='535' transform='rotate(0 205,535)' title='Fk qrtz_cron_triggers_ibfk_1
+qrtz_cron_triggers ref qrtz_triggers ( sched_name, trigger_name, trigger_group )' class='relName' style='fill:#5f789f'>sched_name,trigger_name,trigger_group</text>
+<!-- == Fk 'qrtz_simple_triggers_qrtz_simple_triggers_ibfk_1' == -->
+<path id='qrtz_simple_triggers_qrtz_simple_triggers_ibfk_1'  onmouseover="hghl(['qrtz_simple_triggers_qrtz_simple_triggers_ibfk_1','ry.qrtz_simple_triggers.sched_name','ry.qrtz_simple_triggers.trigger_name','ry.qrtz_simple_triggers.trigger_group','ry.qrtz_triggers.sched_name','ry.qrtz_triggers.trigger_name','ry.qrtz_triggers.trigger_group'])" onmouseout="uhghl(['qrtz_simple_triggers_qrtz_simple_triggers_ibfk_1','ry.qrtz_simple_triggers.sched_name','ry.qrtz_simple_triggers.trigger_name','ry.qrtz_simple_triggers.trigger_group','ry.qrtz_triggers.sched_name','ry.qrtz_triggers.trigger_name','ry.qrtz_triggers.trigger_group'])" transform='translate(7,0)' class='scene' d='M 180 525 L 180,502 Q 180,495 187,495 L 277,495 Q 285,495 285,487 L 285,480' >
+	<title>Fk qrtz_simple_triggers_ibfk_1
+qrtz_simple_triggers ref qrtz_triggers ( sched_name, trigger_name, trigger_group )</title>
+</path>
+<path transform='translate(7,0)' marker-start='url(#foot1)' marker-end='url(#arrow1)'    d='M 180 525 L 180,502 Q 180,495 187,495 L 277,495 Q 285,495 285,487 L 285,480' ></path>
+<text x='182' y='520' transform='rotate(270 182,520)' title='Fk qrtz_simple_triggers_ibfk_1
+qrtz_simple_triggers ref qrtz_triggers ( sched_name, trigger_name, trigger_group )' class='relName' style='fill:#5f789f'>sched_name,trigger_name,trigger_group</text>
+<!-- == Fk 'qrtz_simprop_triggers_qrtz_simprop_triggers_ibfk_1' == -->
+<path id='qrtz_simprop_triggers_qrtz_simprop_triggers_ibfk_1'  onmouseover="hghl(['qrtz_simprop_triggers_qrtz_simprop_triggers_ibfk_1','ry.qrtz_simprop_triggers.sched_name','ry.qrtz_simprop_triggers.trigger_name','ry.qrtz_simprop_triggers.trigger_group','ry.qrtz_triggers.sched_name','ry.qrtz_triggers.trigger_name','ry.qrtz_triggers.trigger_group'])" onmouseout="uhghl(['qrtz_simprop_triggers_qrtz_simprop_triggers_ibfk_1','ry.qrtz_simprop_triggers.sched_name','ry.qrtz_simprop_triggers.trigger_name','ry.qrtz_simprop_triggers.trigger_group','ry.qrtz_triggers.sched_name','ry.qrtz_triggers.trigger_name','ry.qrtz_triggers.trigger_group'])" transform='translate(7,0)' class='scene' d='M 195 240 L 240,240' >
+	<title>Fk qrtz_simprop_triggers_ibfk_1
+qrtz_simprop_triggers ref qrtz_triggers ( sched_name, trigger_name, trigger_group )</title>
+</path>
+<path transform='translate(7,0)' marker-start='url(#foot1)' marker-end='url(#arrow1)'    d='M 195 240 L 240,240' ></path>
+<text x='202' y='235' transform='rotate(0 202,235)' title='Fk qrtz_simprop_triggers_ibfk_1
+qrtz_simprop_triggers ref qrtz_triggers ( sched_name, trigger_name, trigger_group )' class='relName' style='fill:#5f789f'>sched_name,trigger_name,trigger_group</text>
+<!-- == Fk 'qrtz_triggers_qrtz_triggers_ibfk_1' == -->
+<path id='qrtz_triggers_qrtz_triggers_ibfk_1'  onmouseover="hghl(['qrtz_triggers_qrtz_triggers_ibfk_1','ry.qrtz_triggers.sched_name','ry.qrtz_triggers.job_name','ry.qrtz_triggers.job_group','ry.qrtz_job_details.sched_name','ry.qrtz_job_details.job_name','ry.qrtz_job_details.job_group'])" onmouseout="uhghl(['qrtz_triggers_qrtz_triggers_ibfk_1','ry.qrtz_triggers.sched_name','ry.qrtz_triggers.job_name','ry.qrtz_triggers.job_group','ry.qrtz_job_details.sched_name','ry.qrtz_job_details.job_name','ry.qrtz_job_details.job_group'])" transform='translate(7,0)' class='scene' d='M 375 210 L 420,210' >
+	<title>Fk qrtz_triggers_ibfk_1
+qrtz_triggers ref qrtz_job_details ( sched_name, job_name, job_group )</title>
+</path>
+<path transform='translate(7,0)' marker-start='url(#foot1p)' marker-end='url(#arrow1)'    d='M 375 210 L 420,210' ></path>
+<text x='382' y='205' transform='rotate(0 382,205)' title='Fk qrtz_triggers_ibfk_1
+qrtz_triggers ref qrtz_job_details ( sched_name, job_name, job_group )' class='relName' style='fill:#5f789f'>sched_name,job_name,job_group</text>
+<!-- == Table 'qrtz_blob_triggers' == -->
+<rect class='entity' x='255' y='533' width='120' height='105' rx='7' ry='7' style='stroke:none'/>
+<path d='M 255 559 L 255 540 Q 255 533 262 533 L 368 533 Q 375 533 375 540 L 375 559 L255 559 ' style='fill:url(#tbg_bfd4f5);stroke:1;stroke-opacity:0.1;' />
+<rect class='entity' x='255' y='533' width='120' height='105' rx='7' ry='7' style='fill:none;stroke:#5f656e'/>
+<line class='delim' x1='255' y1='559' x2='375' y2='559' style='stroke:#5f656e'/>
+<line class='delim' x1='270' y1='559' x2='270' y2='638' style='stroke:#5f656e'/>
+<line class='delim' x1='364' y1='559' x2='364' y2='638' style='stroke:#5f656e'/>
+<a xlink:href='#qrtz_blob_triggers'><text x='258' y='551'>qrtz_blob_triggers</text><title>Table ry.qrtz_blob_triggers</title></a>
+  <use id='nn' x='257' y='567' xlink:href='#nn'/><a xlink:href='#qrtz_blob_triggers.sched_name'><use id='pk' x='257' y='566' xlink:href='#pk'/><title>Pk pk_qrtz_blob_triggers ( sched_name, trigger_name, trigger_group ) </title></a>
+<a xlink:href='#qrtz_blob_triggers.sched_name'><text id='ry.qrtz_blob_triggers.sched_name' x='273' y='576' onmouseover="hghl(['qrtz_blob_triggers_qrtz_blob_triggers_ibfk_1','ry.qrtz_triggers.sched_name','ry.qrtz_triggers.trigger_name','ry.qrtz_triggers.trigger_group'])" onmouseout="uhghl(['qrtz_blob_triggers_qrtz_blob_triggers_ibfk_1','ry.qrtz_triggers.sched_name','ry.qrtz_triggers.trigger_name','ry.qrtz_triggers.trigger_group'])">sched_name</text><title>sched_name
+* varchar(120)</title></a>
+<a xlink:href='#qrtz_blob_triggers.sched_name'><use id='fk' x='364' y='566' xlink:href='#fk'/><title>References qrtz_triggers ( sched_name, trigger_name, trigger_group ) </title></a>
+  <use id='nn' x='257' y='582' xlink:href='#nn'/><a xlink:href='#qrtz_blob_triggers.trigger_name'><use id='pk' x='257' y='581' xlink:href='#pk'/><title>Pk pk_qrtz_blob_triggers ( sched_name, trigger_name, trigger_group ) </title></a>
+<a xlink:href='#qrtz_blob_triggers.trigger_name'><text id='ry.qrtz_blob_triggers.trigger_name' x='273' y='591' onmouseover="hghl(['qrtz_blob_triggers_qrtz_blob_triggers_ibfk_1','ry.qrtz_triggers.sched_name','ry.qrtz_triggers.trigger_name','ry.qrtz_triggers.trigger_group'])" onmouseout="uhghl(['qrtz_blob_triggers_qrtz_blob_triggers_ibfk_1','ry.qrtz_triggers.sched_name','ry.qrtz_triggers.trigger_name','ry.qrtz_triggers.trigger_group'])">trigger_name</text><title>trigger_name
+* varchar(200)</title></a>
+<a xlink:href='#qrtz_blob_triggers.trigger_name'><use id='fk' x='364' y='581' xlink:href='#fk'/><title>References qrtz_triggers ( sched_name, trigger_name, trigger_group ) </title></a>
+  <use id='nn' x='257' y='597' xlink:href='#nn'/><a xlink:href='#qrtz_blob_triggers.trigger_group'><use id='pk' x='257' y='596' xlink:href='#pk'/><title>Pk pk_qrtz_blob_triggers ( sched_name, trigger_name, trigger_group ) </title></a>
+<a xlink:href='#qrtz_blob_triggers.trigger_group'><text id='ry.qrtz_blob_triggers.trigger_group' x='273' y='606' onmouseover="hghl(['qrtz_blob_triggers_qrtz_blob_triggers_ibfk_1','ry.qrtz_triggers.sched_name','ry.qrtz_triggers.trigger_name','ry.qrtz_triggers.trigger_group'])" onmouseout="uhghl(['qrtz_blob_triggers_qrtz_blob_triggers_ibfk_1','ry.qrtz_triggers.sched_name','ry.qrtz_triggers.trigger_name','ry.qrtz_triggers.trigger_group'])">trigger_group</text><title>trigger_group
+* varchar(200)</title></a>
+<a xlink:href='#qrtz_blob_triggers.trigger_group'><use id='fk' x='364' y='596' xlink:href='#fk'/><title>References qrtz_triggers ( sched_name, trigger_name, trigger_group ) </title></a>
+  <a xlink:href='#qrtz_blob_triggers.blob_data'><text id='ry.qrtz_blob_triggers.blob_data' x='273' y='621'>blob_data</text><title>blob_data
+blob</title></a>
+<text x='372' y='618' text-anchor='end' class='colType'>~</text>
+<!-- == Table 'qrtz_calendars' == -->
+<rect class='entity' x='75' y='38' width='120' height='90' rx='7' ry='7' style='stroke:none'/>
+<path d='M 75 64 L 75 45 Q 75 38 82 38 L 188 38 Q 195 38 195 45 L 195 64 L75 64 ' style='fill:url(#tbg_bfd4f5);stroke:1;stroke-opacity:0.1;' />
+<rect class='entity' x='75' y='38' width='120' height='90' rx='7' ry='7' style='fill:none;stroke:#5f656e'/>
+<line class='delim' x1='75' y1='64' x2='195' y2='64' style='stroke:#5f656e'/>
+<line class='delim' x1='90' y1='64' x2='90' y2='128' style='stroke:#5f656e'/>
+<line class='delim' x1='184' y1='64' x2='184' y2='128' style='stroke:#5f656e'/>
+<a xlink:href='#qrtz_calendars'><text x='90' y='56'>qrtz_calendars</text><title>Table ry.qrtz_calendars</title></a>
+  <use id='nn' x='77' y='72' xlink:href='#nn'/><a xlink:href='#qrtz_calendars.sched_name'><use id='pk' x='77' y='71' xlink:href='#pk'/><title>Pk pk_qrtz_calendars ( sched_name, calendar_name ) </title></a>
+<a xlink:href='#qrtz_calendars.sched_name'><text id='ry.qrtz_calendars.sched_name' x='93' y='81'>sched_name</text><title>sched_name
+* varchar(120)</title></a>
+<text x='192' y='78' text-anchor='end' class='colType'>t</text>  <use id='nn' x='77' y='87' xlink:href='#nn'/><a xlink:href='#qrtz_calendars.calendar_name'><use id='pk' x='77' y='86' xlink:href='#pk'/><title>Pk pk_qrtz_calendars ( sched_name, calendar_name ) </title></a>
+<a xlink:href='#qrtz_calendars.calendar_name'><text id='ry.qrtz_calendars.calendar_name' x='93' y='96'>calendar_name</text><title>calendar_name
+* varchar(200)</title></a>
+<text x='192' y='93' text-anchor='end' class='colType'>t</text>  <use id='nn' x='77' y='102' xlink:href='#nn'/><a xlink:href='#qrtz_calendars.calendar'><text id='ry.qrtz_calendars.calendar' x='93' y='111'>calendar</text><title>calendar
+* blob</title></a>
+<text x='192' y='108' text-anchor='end' class='colType'>~</text>
+<!-- == Table 'qrtz_cron_triggers' == -->
+<rect class='entity' x='435' y='533' width='135' height='120' rx='7' ry='7' style='stroke:none'/>
+<path d='M 435 559 L 435 540 Q 435 533 442 533 L 563 533 Q 570 533 570 540 L 570 559 L435 559 ' style='fill:url(#tbg_bfd4f5);stroke:1;stroke-opacity:0.1;' />
+<rect class='entity' x='435' y='533' width='135' height='120' rx='7' ry='7' style='fill:none;stroke:#5f656e'/>
+<line class='delim' x1='435' y1='559' x2='570' y2='559' style='stroke:#5f656e'/>
+<line class='delim' x1='450' y1='559' x2='450' y2='653' style='stroke:#5f656e'/>
+<line class='delim' x1='559' y1='559' x2='559' y2='653' style='stroke:#5f656e'/>
+<a xlink:href='#qrtz_cron_triggers'><text x='445' y='551'>qrtz_cron_triggers</text><title>Table ry.qrtz_cron_triggers</title></a>
+  <use id='nn' x='437' y='567' xlink:href='#nn'/><a xlink:href='#qrtz_cron_triggers.sched_name'><use id='pk' x='437' y='566' xlink:href='#pk'/><title>Pk pk_qrtz_cron_triggers ( sched_name, trigger_name, trigger_group ) </title></a>
+<a xlink:href='#qrtz_cron_triggers.sched_name'><text id='ry.qrtz_cron_triggers.sched_name' x='453' y='576' onmouseover="hghl(['qrtz_cron_triggers_qrtz_cron_triggers_ibfk_1','ry.qrtz_triggers.sched_name','ry.qrtz_triggers.trigger_name','ry.qrtz_triggers.trigger_group'])" onmouseout="uhghl(['qrtz_cron_triggers_qrtz_cron_triggers_ibfk_1','ry.qrtz_triggers.sched_name','ry.qrtz_triggers.trigger_name','ry.qrtz_triggers.trigger_group'])">sched_name</text><title>sched_name
+* varchar(120)</title></a>
+<a xlink:href='#qrtz_cron_triggers.sched_name'><use id='fk' x='559' y='566' xlink:href='#fk'/><title>References qrtz_triggers ( sched_name, trigger_name, trigger_group ) </title></a>
+  <use id='nn' x='437' y='582' xlink:href='#nn'/><a xlink:href='#qrtz_cron_triggers.trigger_name'><use id='pk' x='437' y='581' xlink:href='#pk'/><title>Pk pk_qrtz_cron_triggers ( sched_name, trigger_name, trigger_group ) </title></a>
+<a xlink:href='#qrtz_cron_triggers.trigger_name'><text id='ry.qrtz_cron_triggers.trigger_name' x='453' y='591' onmouseover="hghl(['qrtz_cron_triggers_qrtz_cron_triggers_ibfk_1','ry.qrtz_triggers.sched_name','ry.qrtz_triggers.trigger_name','ry.qrtz_triggers.trigger_group'])" onmouseout="uhghl(['qrtz_cron_triggers_qrtz_cron_triggers_ibfk_1','ry.qrtz_triggers.sched_name','ry.qrtz_triggers.trigger_name','ry.qrtz_triggers.trigger_group'])">trigger_name</text><title>trigger_name
+* varchar(200)</title></a>
+<a xlink:href='#qrtz_cron_triggers.trigger_name'><use id='fk' x='559' y='581' xlink:href='#fk'/><title>References qrtz_triggers ( sched_name, trigger_name, trigger_group ) </title></a>
+  <use id='nn' x='437' y='597' xlink:href='#nn'/><a xlink:href='#qrtz_cron_triggers.trigger_group'><use id='pk' x='437' y='596' xlink:href='#pk'/><title>Pk pk_qrtz_cron_triggers ( sched_name, trigger_name, trigger_group ) </title></a>
+<a xlink:href='#qrtz_cron_triggers.trigger_group'><text id='ry.qrtz_cron_triggers.trigger_group' x='453' y='606' onmouseover="hghl(['qrtz_cron_triggers_qrtz_cron_triggers_ibfk_1','ry.qrtz_triggers.sched_name','ry.qrtz_triggers.trigger_name','ry.qrtz_triggers.trigger_group'])" onmouseout="uhghl(['qrtz_cron_triggers_qrtz_cron_triggers_ibfk_1','ry.qrtz_triggers.sched_name','ry.qrtz_triggers.trigger_name','ry.qrtz_triggers.trigger_group'])">trigger_group</text><title>trigger_group
+* varchar(200)</title></a>
+<a xlink:href='#qrtz_cron_triggers.trigger_group'><use id='fk' x='559' y='596' xlink:href='#fk'/><title>References qrtz_triggers ( sched_name, trigger_name, trigger_group ) </title></a>
+  <use id='nn' x='437' y='612' xlink:href='#nn'/><a xlink:href='#qrtz_cron_triggers.cron_expression'><text id='ry.qrtz_cron_triggers.cron_expression' x='453' y='621'>cron_expression</text><title>cron_expression
+* varchar(200)</title></a>
+<text x='567' y='618' text-anchor='end' class='colType'>t</text>  <a xlink:href='#qrtz_cron_triggers.time_zone_id'><text id='ry.qrtz_cron_triggers.time_zone_id' x='453' y='636'>time_zone_id</text><title>time_zone_id
+varchar(80)</title></a>
+<text x='567' y='633' text-anchor='end' class='colType'>t</text>
+<!-- == Table 'qrtz_job_details' == -->
+<rect class='entity' x='435' y='188' width='135' height='195' rx='7' ry='7' style='stroke:none'/>
+<path d='M 435 214 L 435 195 Q 435 188 442 188 L 563 188 Q 570 188 570 195 L 570 214 L435 214 ' style='fill:url(#tbg_bfd4f5);stroke:1;stroke-opacity:0.1;' />
+<rect class='entity' x='435' y='188' width='135' height='195' rx='7' ry='7' style='fill:none;stroke:#5f656e'/>
+<line class='delim' x1='435' y1='214' x2='570' y2='214' style='stroke:#5f656e'/>
+<line class='delim' x1='450' y1='214' x2='450' y2='383' style='stroke:#5f656e'/>
+<line class='delim' x1='559' y1='214' x2='559' y2='383' style='stroke:#5f656e'/>
+<a xlink:href='#qrtz_job_details'><text x='451' y='206'>qrtz_job_details</text><title>Table ry.qrtz_job_details</title></a>
+  <use id='nn' x='437' y='222' xlink:href='#nn'/><a xlink:href='#qrtz_job_details.sched_name'><use id='pk' x='437' y='221' xlink:href='#pk'/><title>Pk pk_qrtz_job_details ( sched_name, job_name, job_group ) </title></a>
+<a xlink:href='#qrtz_job_details.sched_name'><text id='ry.qrtz_job_details.sched_name' x='453' y='231' onmouseover="hghl(['qrtz_triggers_qrtz_triggers_ibfk_1','ry.qrtz_triggers.sched_name','ry.qrtz_triggers.job_name','ry.qrtz_triggers.job_group'])" onmouseout="uhghl(['qrtz_triggers_qrtz_triggers_ibfk_1','ry.qrtz_triggers.sched_name','ry.qrtz_triggers.job_name','ry.qrtz_triggers.job_group'])">sched_name</text><title>sched_name
+* varchar(120)</title></a>
+<a xlink:href='#qrtz_job_details.sched_name'><use id='ref' x='559' y='221' xlink:href='#ref'/><title>Referred by qrtz_triggers ( sched_name, job_name, job_group ) </title></a>
+  <use id='nn' x='437' y='237' xlink:href='#nn'/><a xlink:href='#qrtz_job_details.job_name'><use id='pk' x='437' y='236' xlink:href='#pk'/><title>Pk pk_qrtz_job_details ( sched_name, job_name, job_group ) </title></a>
+<a xlink:href='#qrtz_job_details.job_name'><text id='ry.qrtz_job_details.job_name' x='453' y='246' onmouseover="hghl(['qrtz_triggers_qrtz_triggers_ibfk_1','ry.qrtz_triggers.sched_name','ry.qrtz_triggers.job_name','ry.qrtz_triggers.job_group'])" onmouseout="uhghl(['qrtz_triggers_qrtz_triggers_ibfk_1','ry.qrtz_triggers.sched_name','ry.qrtz_triggers.job_name','ry.qrtz_triggers.job_group'])">job_name</text><title>job_name
+* varchar(200)</title></a>
+<a xlink:href='#qrtz_job_details.job_name'><use id='ref' x='559' y='236' xlink:href='#ref'/><title>Referred by qrtz_triggers ( sched_name, job_name, job_group ) </title></a>
+  <use id='nn' x='437' y='252' xlink:href='#nn'/><a xlink:href='#qrtz_job_details.job_group'><use id='pk' x='437' y='251' xlink:href='#pk'/><title>Pk pk_qrtz_job_details ( sched_name, job_name, job_group ) </title></a>
+<a xlink:href='#qrtz_job_details.job_group'><text id='ry.qrtz_job_details.job_group' x='453' y='261' onmouseover="hghl(['qrtz_triggers_qrtz_triggers_ibfk_1','ry.qrtz_triggers.sched_name','ry.qrtz_triggers.job_name','ry.qrtz_triggers.job_group'])" onmouseout="uhghl(['qrtz_triggers_qrtz_triggers_ibfk_1','ry.qrtz_triggers.sched_name','ry.qrtz_triggers.job_name','ry.qrtz_triggers.job_group'])">job_group</text><title>job_group
+* varchar(200)</title></a>
+<a xlink:href='#qrtz_job_details.job_group'><use id='ref' x='559' y='251' xlink:href='#ref'/><title>Referred by qrtz_triggers ( sched_name, job_name, job_group ) </title></a>
+  <a xlink:href='#qrtz_job_details.description'><text id='ry.qrtz_job_details.description' x='453' y='276'>description</text><title>description
+varchar(250)</title></a>
+<text x='567' y='273' text-anchor='end' class='colType'>t</text>  <use id='nn' x='437' y='282' xlink:href='#nn'/><a xlink:href='#qrtz_job_details.job_class_name'><text id='ry.qrtz_job_details.job_class_name' x='453' y='291'>job_class_name</text><title>job_class_name
+* varchar(250)</title></a>
+<text x='567' y='288' text-anchor='end' class='colType'>t</text>  <use id='nn' x='437' y='297' xlink:href='#nn'/><a xlink:href='#qrtz_job_details.is_durable'><text id='ry.qrtz_job_details.is_durable' x='453' y='306'>is_durable</text><title>is_durable
+* varchar(1)</title></a>
+<text x='567' y='303' text-anchor='end' class='colType'>t</text>  <use id='nn' x='437' y='312' xlink:href='#nn'/><a xlink:href='#qrtz_job_details.is_nonconcurrent'><text id='ry.qrtz_job_details.is_nonconcurrent' x='453' y='321'>is_nonconcurrent</text><title>is_nonconcurrent
+* varchar(1)</title></a>
+<text x='567' y='318' text-anchor='end' class='colType'>t</text>  <use id='nn' x='437' y='327' xlink:href='#nn'/><a xlink:href='#qrtz_job_details.is_update_data'><text id='ry.qrtz_job_details.is_update_data' x='453' y='336'>is_update_data</text><title>is_update_data
+* varchar(1)</title></a>
+<text x='567' y='333' text-anchor='end' class='colType'>t</text>  <use id='nn' x='437' y='342' xlink:href='#nn'/><a xlink:href='#qrtz_job_details.requests_recovery'><text id='ry.qrtz_job_details.requests_recovery' x='453' y='351'>requests_recovery</text><title>requests_recovery
+* varchar(1)</title></a>
+<text x='567' y='348' text-anchor='end' class='colType'>t</text>  <a xlink:href='#qrtz_job_details.job_data'><text id='ry.qrtz_job_details.job_data' x='453' y='366'>job_data</text><title>job_data
+blob</title></a>
+<text x='567' y='363' text-anchor='end' class='colType'>~</text>
+<!-- == Table 'qrtz_locks' == -->
+<rect class='entity' x='255' y='53' width='105' height='75' rx='7' ry='7' style='stroke:none'/>
+<path d='M 255 79 L 255 60 Q 255 53 262 53 L 353 53 Q 360 53 360 60 L 360 79 L255 79 ' style='fill:url(#tbg_bfd4f5);stroke:1;stroke-opacity:0.1;' />
+<rect class='entity' x='255' y='53' width='105' height='75' rx='7' ry='7' style='fill:none;stroke:#5f656e'/>
+<line class='delim' x1='255' y1='79' x2='360' y2='79' style='stroke:#5f656e'/>
+<line class='delim' x1='270' y1='79' x2='270' y2='128' style='stroke:#5f656e'/>
+<line class='delim' x1='349' y1='79' x2='349' y2='128' style='stroke:#5f656e'/>
+<a xlink:href='#qrtz_locks'><text x='274' y='71'>qrtz_locks</text><title>Table ry.qrtz_locks</title></a>
+  <use id='nn' x='257' y='87' xlink:href='#nn'/><a xlink:href='#qrtz_locks.sched_name'><use id='pk' x='257' y='86' xlink:href='#pk'/><title>Pk pk_qrtz_locks ( sched_name, lock_name ) </title></a>
+<a xlink:href='#qrtz_locks.sched_name'><text id='ry.qrtz_locks.sched_name' x='273' y='96'>sched_name</text><title>sched_name
+* varchar(120)</title></a>
+<text x='357' y='93' text-anchor='end' class='colType'>t</text>  <use id='nn' x='257' y='102' xlink:href='#nn'/><a xlink:href='#qrtz_locks.lock_name'><use id='pk' x='257' y='101' xlink:href='#pk'/><title>Pk pk_qrtz_locks ( sched_name, lock_name ) </title></a>
+<a xlink:href='#qrtz_locks.lock_name'><text id='ry.qrtz_locks.lock_name' x='273' y='111'>lock_name</text><title>lock_name
+* varchar(40)</title></a>
+<text x='357' y='108' text-anchor='end' class='colType'>t</text>
+<!-- == Table 'qrtz_scheduler_state' == -->
+<rect class='entity' x='255' y='728' width='135' height='105' rx='7' ry='7' style='stroke:none'/>
+<path d='M 255 754 L 255 735 Q 255 728 262 728 L 383 728 Q 390 728 390 735 L 390 754 L255 754 ' style='fill:url(#tbg_bfd4f5);stroke:1;stroke-opacity:0.1;' />
+<rect class='entity' x='255' y='728' width='135' height='105' rx='7' ry='7' style='fill:none;stroke:#5f656e'/>
+<line class='delim' x1='255' y1='754' x2='390' y2='754' style='stroke:#5f656e'/>
+<line class='delim' x1='270' y1='754' x2='270' y2='833' style='stroke:#5f656e'/>
+<line class='delim' x1='379' y1='754' x2='379' y2='833' style='stroke:#5f656e'/>
+<a xlink:href='#qrtz_scheduler_state'><text x='259' y='746'>qrtz_scheduler_state</text><title>Table ry.qrtz_scheduler_state</title></a>
+  <use id='nn' x='257' y='762' xlink:href='#nn'/><a xlink:href='#qrtz_scheduler_state.sched_name'><use id='pk' x='257' y='761' xlink:href='#pk'/><title>Pk pk_qrtz_scheduler_state ( sched_name, instance_name ) </title></a>
+<a xlink:href='#qrtz_scheduler_state.sched_name'><text id='ry.qrtz_scheduler_state.sched_name' x='273' y='771'>sched_name</text><title>sched_name
+* varchar(120)</title></a>
+<text x='387' y='768' text-anchor='end' class='colType'>t</text>  <use id='nn' x='257' y='777' xlink:href='#nn'/><a xlink:href='#qrtz_scheduler_state.instance_name'><use id='pk' x='257' y='776' xlink:href='#pk'/><title>Pk pk_qrtz_scheduler_state ( sched_name, instance_name ) </title></a>
+<a xlink:href='#qrtz_scheduler_state.instance_name'><text id='ry.qrtz_scheduler_state.instance_name' x='273' y='786'>instance_name</text><title>instance_name
+* varchar(200)</title></a>
+<text x='387' y='783' text-anchor='end' class='colType'>t</text>  <use id='nn' x='257' y='792' xlink:href='#nn'/><a xlink:href='#qrtz_scheduler_state.last_checkin_time'><text id='ry.qrtz_scheduler_state.last_checkin_time' x='273' y='801'>last_checkin_time</text><title>last_checkin_time
+* bigint</title></a>
+<text x='387' y='798' text-anchor='end' class='colType'>#</text>  <use id='nn' x='257' y='807' xlink:href='#nn'/><a xlink:href='#qrtz_scheduler_state.checkin_interval'><text id='ry.qrtz_scheduler_state.checkin_interval' x='273' y='816'>checkin_interval</text><title>checkin_interval
+* bigint</title></a>
+<text x='387' y='813' text-anchor='end' class='colType'>#</text>
+<!-- == Table 'qrtz_simple_triggers' == -->
+<rect class='entity' x='60' y='533' width='135' height='135' rx='7' ry='7' style='stroke:none'/>
+<path d='M 60 559 L 60 540 Q 60 533 67 533 L 188 533 Q 195 533 195 540 L 195 559 L60 559 ' style='fill:url(#tbg_bfd4f5);stroke:1;stroke-opacity:0.1;' />
+<rect class='entity' x='60' y='533' width='135' height='135' rx='7' ry='7' style='fill:none;stroke:#5f656e'/>
+<line class='delim' x1='60' y1='559' x2='195' y2='559' style='stroke:#5f656e'/>
+<line class='delim' x1='75' y1='559' x2='75' y2='668' style='stroke:#5f656e'/>
+<line class='delim' x1='184' y1='559' x2='184' y2='668' style='stroke:#5f656e'/>
+<a xlink:href='#qrtz_simple_triggers'><text x='64' y='551'>qrtz_simple_triggers</text><title>Table ry.qrtz_simple_triggers</title></a>
+  <use id='nn' x='62' y='567' xlink:href='#nn'/><a xlink:href='#qrtz_simple_triggers.sched_name'><use id='pk' x='62' y='566' xlink:href='#pk'/><title>Pk pk_qrtz_simple_triggers ( sched_name, trigger_name, trigger_group ) </title></a>
+<a xlink:href='#qrtz_simple_triggers.sched_name'><text id='ry.qrtz_simple_triggers.sched_name' x='78' y='576' onmouseover="hghl(['qrtz_simple_triggers_qrtz_simple_triggers_ibfk_1','ry.qrtz_triggers.sched_name','ry.qrtz_triggers.trigger_name','ry.qrtz_triggers.trigger_group'])" onmouseout="uhghl(['qrtz_simple_triggers_qrtz_simple_triggers_ibfk_1','ry.qrtz_triggers.sched_name','ry.qrtz_triggers.trigger_name','ry.qrtz_triggers.trigger_group'])">sched_name</text><title>sched_name
+* varchar(120)</title></a>
+<a xlink:href='#qrtz_simple_triggers.sched_name'><use id='fk' x='184' y='566' xlink:href='#fk'/><title>References qrtz_triggers ( sched_name, trigger_name, trigger_group ) </title></a>
+  <use id='nn' x='62' y='582' xlink:href='#nn'/><a xlink:href='#qrtz_simple_triggers.trigger_name'><use id='pk' x='62' y='581' xlink:href='#pk'/><title>Pk pk_qrtz_simple_triggers ( sched_name, trigger_name, trigger_group ) </title></a>
+<a xlink:href='#qrtz_simple_triggers.trigger_name'><text id='ry.qrtz_simple_triggers.trigger_name' x='78' y='591' onmouseover="hghl(['qrtz_simple_triggers_qrtz_simple_triggers_ibfk_1','ry.qrtz_triggers.sched_name','ry.qrtz_triggers.trigger_name','ry.qrtz_triggers.trigger_group'])" onmouseout="uhghl(['qrtz_simple_triggers_qrtz_simple_triggers_ibfk_1','ry.qrtz_triggers.sched_name','ry.qrtz_triggers.trigger_name','ry.qrtz_triggers.trigger_group'])">trigger_name</text><title>trigger_name
+* varchar(200)</title></a>
+<a xlink:href='#qrtz_simple_triggers.trigger_name'><use id='fk' x='184' y='581' xlink:href='#fk'/><title>References qrtz_triggers ( sched_name, trigger_name, trigger_group ) </title></a>
+  <use id='nn' x='62' y='597' xlink:href='#nn'/><a xlink:href='#qrtz_simple_triggers.trigger_group'><use id='pk' x='62' y='596' xlink:href='#pk'/><title>Pk pk_qrtz_simple_triggers ( sched_name, trigger_name, trigger_group ) </title></a>
+<a xlink:href='#qrtz_simple_triggers.trigger_group'><text id='ry.qrtz_simple_triggers.trigger_group' x='78' y='606' onmouseover="hghl(['qrtz_simple_triggers_qrtz_simple_triggers_ibfk_1','ry.qrtz_triggers.sched_name','ry.qrtz_triggers.trigger_name','ry.qrtz_triggers.trigger_group'])" onmouseout="uhghl(['qrtz_simple_triggers_qrtz_simple_triggers_ibfk_1','ry.qrtz_triggers.sched_name','ry.qrtz_triggers.trigger_name','ry.qrtz_triggers.trigger_group'])">trigger_group</text><title>trigger_group
+* varchar(200)</title></a>
+<a xlink:href='#qrtz_simple_triggers.trigger_group'><use id='fk' x='184' y='596' xlink:href='#fk'/><title>References qrtz_triggers ( sched_name, trigger_name, trigger_group ) </title></a>
+  <use id='nn' x='62' y='612' xlink:href='#nn'/><a xlink:href='#qrtz_simple_triggers.repeat_count'><text id='ry.qrtz_simple_triggers.repeat_count' x='78' y='621'>repeat_count</text><title>repeat_count
+* bigint</title></a>
+<text x='192' y='618' text-anchor='end' class='colType'>#</text>  <use id='nn' x='62' y='627' xlink:href='#nn'/><a xlink:href='#qrtz_simple_triggers.repeat_interval'><text id='ry.qrtz_simple_triggers.repeat_interval' x='78' y='636'>repeat_interval</text><title>repeat_interval
+* bigint</title></a>
+<text x='192' y='633' text-anchor='end' class='colType'>#</text>  <use id='nn' x='62' y='642' xlink:href='#nn'/><a xlink:href='#qrtz_simple_triggers.times_triggered'><text id='ry.qrtz_simple_triggers.times_triggered' x='78' y='651'>times_triggered</text><title>times_triggered
+* bigint</title></a>
+<text x='192' y='648' text-anchor='end' class='colType'>#</text>
+<!-- == Table 'qrtz_simprop_triggers' == -->
+<rect class='entity' x='45' y='218' width='150' height='255' rx='7' ry='7' style='stroke:none'/>
+<path d='M 45 244 L 45 225 Q 45 218 52 218 L 188 218 Q 195 218 195 225 L 195 244 L45 244 ' style='fill:url(#tbg_bfd4f5);stroke:1;stroke-opacity:0.1;' />
+<rect class='entity' x='45' y='218' width='150' height='255' rx='7' ry='7' style='fill:none;stroke:#5f656e'/>
+<line class='delim' x1='45' y1='244' x2='195' y2='244' style='stroke:#5f656e'/>
+<line class='delim' x1='60' y1='244' x2='60' y2='473' style='stroke:#5f656e'/>
+<line class='delim' x1='184' y1='244' x2='184' y2='473' style='stroke:#5f656e'/>
+<a xlink:href='#qrtz_simprop_triggers'><text x='54' y='236'>qrtz_simprop_triggers</text><title>Table ry.qrtz_simprop_triggers</title></a>
+  <use id='nn' x='47' y='252' xlink:href='#nn'/><a xlink:href='#qrtz_simprop_triggers.sched_name'><use id='pk' x='47' y='251' xlink:href='#pk'/><title>Pk pk_qrtz_simprop_triggers ( sched_name, trigger_name, trigger_group ) </title></a>
+<a xlink:href='#qrtz_simprop_triggers.sched_name'><text id='ry.qrtz_simprop_triggers.sched_name' x='63' y='261' onmouseover="hghl(['qrtz_simprop_triggers_qrtz_simprop_triggers_ibfk_1','ry.qrtz_triggers.sched_name','ry.qrtz_triggers.trigger_name','ry.qrtz_triggers.trigger_group'])" onmouseout="uhghl(['qrtz_simprop_triggers_qrtz_simprop_triggers_ibfk_1','ry.qrtz_triggers.sched_name','ry.qrtz_triggers.trigger_name','ry.qrtz_triggers.trigger_group'])">sched_name</text><title>sched_name
+* varchar(120)</title></a>
+<a xlink:href='#qrtz_simprop_triggers.sched_name'><use id='fk' x='184' y='251' xlink:href='#fk'/><title>References qrtz_triggers ( sched_name, trigger_name, trigger_group ) </title></a>
+  <use id='nn' x='47' y='267' xlink:href='#nn'/><a xlink:href='#qrtz_simprop_triggers.trigger_name'><use id='pk' x='47' y='266' xlink:href='#pk'/><title>Pk pk_qrtz_simprop_triggers ( sched_name, trigger_name, trigger_group ) </title></a>
+<a xlink:href='#qrtz_simprop_triggers.trigger_name'><text id='ry.qrtz_simprop_triggers.trigger_name' x='63' y='276' onmouseover="hghl(['qrtz_simprop_triggers_qrtz_simprop_triggers_ibfk_1','ry.qrtz_triggers.sched_name','ry.qrtz_triggers.trigger_name','ry.qrtz_triggers.trigger_group'])" onmouseout="uhghl(['qrtz_simprop_triggers_qrtz_simprop_triggers_ibfk_1','ry.qrtz_triggers.sched_name','ry.qrtz_triggers.trigger_name','ry.qrtz_triggers.trigger_group'])">trigger_name</text><title>trigger_name
+* varchar(200)</title></a>
+<a xlink:href='#qrtz_simprop_triggers.trigger_name'><use id='fk' x='184' y='266' xlink:href='#fk'/><title>References qrtz_triggers ( sched_name, trigger_name, trigger_group ) </title></a>
+  <use id='nn' x='47' y='282' xlink:href='#nn'/><a xlink:href='#qrtz_simprop_triggers.trigger_group'><use id='pk' x='47' y='281' xlink:href='#pk'/><title>Pk pk_qrtz_simprop_triggers ( sched_name, trigger_name, trigger_group ) </title></a>
+<a xlink:href='#qrtz_simprop_triggers.trigger_group'><text id='ry.qrtz_simprop_triggers.trigger_group' x='63' y='291' onmouseover="hghl(['qrtz_simprop_triggers_qrtz_simprop_triggers_ibfk_1','ry.qrtz_triggers.sched_name','ry.qrtz_triggers.trigger_name','ry.qrtz_triggers.trigger_group'])" onmouseout="uhghl(['qrtz_simprop_triggers_qrtz_simprop_triggers_ibfk_1','ry.qrtz_triggers.sched_name','ry.qrtz_triggers.trigger_name','ry.qrtz_triggers.trigger_group'])">trigger_group</text><title>trigger_group
+* varchar(200)</title></a>
+<a xlink:href='#qrtz_simprop_triggers.trigger_group'><use id='fk' x='184' y='281' xlink:href='#fk'/><title>References qrtz_triggers ( sched_name, trigger_name, trigger_group ) </title></a>
+  <a xlink:href='#qrtz_simprop_triggers.str_prop_1'><text id='ry.qrtz_simprop_triggers.str_prop_1' x='63' y='306'>str_prop_1</text><title>str_prop_1
+varchar(512)</title></a>
+<text x='192' y='303' text-anchor='end' class='colType'>t</text>  <a xlink:href='#qrtz_simprop_triggers.str_prop_2'><text id='ry.qrtz_simprop_triggers.str_prop_2' x='63' y='321'>str_prop_2</text><title>str_prop_2
+varchar(512)</title></a>
+<text x='192' y='318' text-anchor='end' class='colType'>t</text>  <a xlink:href='#qrtz_simprop_triggers.str_prop_3'><text id='ry.qrtz_simprop_triggers.str_prop_3' x='63' y='336'>str_prop_3</text><title>str_prop_3
+varchar(512)</title></a>
+<text x='192' y='333' text-anchor='end' class='colType'>t</text>  <a xlink:href='#qrtz_simprop_triggers.int_prop_1'><text id='ry.qrtz_simprop_triggers.int_prop_1' x='63' y='351'>int_prop_1</text><title>int_prop_1
+int</title></a>
+<text x='192' y='348' text-anchor='end' class='colType'>#</text>  <a xlink:href='#qrtz_simprop_triggers.int_prop_2'><text id='ry.qrtz_simprop_triggers.int_prop_2' x='63' y='366'>int_prop_2</text><title>int_prop_2
+int</title></a>
+<text x='192' y='363' text-anchor='end' class='colType'>#</text>  <a xlink:href='#qrtz_simprop_triggers.long_prop_1'><text id='ry.qrtz_simprop_triggers.long_prop_1' x='63' y='381'>long_prop_1</text><title>long_prop_1
+bigint</title></a>
+<text x='192' y='378' text-anchor='end' class='colType'>#</text>  <a xlink:href='#qrtz_simprop_triggers.long_prop_2'><text id='ry.qrtz_simprop_triggers.long_prop_2' x='63' y='396'>long_prop_2</text><title>long_prop_2
+bigint</title></a>
+<text x='192' y='393' text-anchor='end' class='colType'>#</text>  <a xlink:href='#qrtz_simprop_triggers.dec_prop_1'><text id='ry.qrtz_simprop_triggers.dec_prop_1' x='63' y='411'>dec_prop_1</text><title>dec_prop_1
+decimal(13,4)</title></a>
+<text x='192' y='408' text-anchor='end' class='colType'>#</text>  <a xlink:href='#qrtz_simprop_triggers.dec_prop_2'><text id='ry.qrtz_simprop_triggers.dec_prop_2' x='63' y='426'>dec_prop_2</text><title>dec_prop_2
+decimal(13,4)</title></a>
+<text x='192' y='423' text-anchor='end' class='colType'>#</text>  <a xlink:href='#qrtz_simprop_triggers.bool_prop_1'><text id='ry.qrtz_simprop_triggers.bool_prop_1' x='63' y='441'>bool_prop_1</text><title>bool_prop_1
+varchar(1)</title></a>
+<text x='192' y='438' text-anchor='end' class='colType'>t</text>  <a xlink:href='#qrtz_simprop_triggers.bool_prop_2'><text id='ry.qrtz_simprop_triggers.bool_prop_2' x='63' y='456'>bool_prop_2</text><title>bool_prop_2
+varchar(1)</title></a>
+<text x='192' y='453' text-anchor='end' class='colType'>t</text>
+<!-- == Table 'qrtz_triggers' == -->
+<rect class='entity' x='255' y='188' width='120' height='285' rx='7' ry='7' style='stroke:none'/>
+<path d='M 255 214 L 255 195 Q 255 188 262 188 L 368 188 Q 375 188 375 195 L 375 214 L255 214 ' style='fill:url(#tbg_bfd4f5);stroke:1;stroke-opacity:0.1;' />
+<rect class='entity' x='255' y='188' width='120' height='285' rx='7' ry='7' style='fill:none;stroke:#5f656e'/>
+<line class='delim' x1='255' y1='214' x2='375' y2='214' style='stroke:#5f656e'/>
+<line class='delim' x1='270' y1='214' x2='270' y2='473' style='stroke:#5f656e'/>
+<line class='delim' x1='364' y1='214' x2='364' y2='473' style='stroke:#5f656e'/>
+<a xlink:href='#qrtz_triggers'><text x='273' y='206'>qrtz_triggers</text><title>Table ry.qrtz_triggers</title></a>
+  <use id='nn' x='257' y='222' xlink:href='#nn'/><a xlink:href='#qrtz_triggers.sched_name'><use id='pk' x='257' y='221' xlink:href='#pk'/><title>Pk pk_qrtz_triggers ( sched_name, trigger_name, trigger_group ) sched_name ( sched_name, job_name, job_group ) </title></a>
+<a xlink:href='#qrtz_triggers.sched_name'><text id='ry.qrtz_triggers.sched_name' x='273' y='231' onmouseover="hghl(['qrtz_triggers_qrtz_triggers_ibfk_1','ry.qrtz_job_details.sched_name','ry.qrtz_job_details.job_name','ry.qrtz_job_details.job_group','qrtz_blob_triggers_qrtz_blob_triggers_ibfk_1','ry.qrtz_blob_triggers.sched_name','ry.qrtz_blob_triggers.trigger_name','ry.qrtz_blob_triggers.trigger_group','qrtz_cron_triggers_qrtz_cron_triggers_ibfk_1','ry.qrtz_cron_triggers.sched_name','ry.qrtz_cron_triggers.trigger_name','ry.qrtz_cron_triggers.trigger_group','qrtz_simple_triggers_qrtz_simple_triggers_ibfk_1','ry.qrtz_simple_triggers.sched_name','ry.qrtz_simple_triggers.trigger_name','ry.qrtz_simple_triggers.trigger_group','qrtz_simprop_triggers_qrtz_simprop_triggers_ibfk_1','ry.qrtz_simprop_triggers.sched_name','ry.qrtz_simprop_triggers.trigger_name','ry.qrtz_simprop_triggers.trigger_group'])" onmouseout="uhghl(['qrtz_triggers_qrtz_triggers_ibfk_1','ry.qrtz_job_details.sched_name','ry.qrtz_job_details.job_name','ry.qrtz_job_details.job_group','qrtz_blob_triggers_qrtz_blob_triggers_ibfk_1','ry.qrtz_blob_triggers.sched_name','ry.qrtz_blob_triggers.trigger_name','ry.qrtz_blob_triggers.trigger_group','qrtz_cron_triggers_qrtz_cron_triggers_ibfk_1','ry.qrtz_cron_triggers.sched_name','ry.qrtz_cron_triggers.trigger_name','ry.qrtz_cron_triggers.trigger_group','qrtz_simple_triggers_qrtz_simple_triggers_ibfk_1','ry.qrtz_simple_triggers.sched_name','ry.qrtz_simple_triggers.trigger_name','ry.qrtz_simple_triggers.trigger_group','qrtz_simprop_triggers_qrtz_simprop_triggers_ibfk_1','ry.qrtz_simprop_triggers.sched_name','ry.qrtz_simprop_triggers.trigger_name','ry.qrtz_simprop_triggers.trigger_group'])">sched_name</text><title>sched_name
+* varchar(120)</title></a>
+<a xlink:href='#qrtz_triggers.sched_name'><use id='fk' x='364' y='221' xlink:href='#fk'/><title>References qrtz_job_details ( sched_name, job_name, job_group ) 
+Referred by qrtz_blob_triggers ( sched_name, trigger_name, trigger_group ) 
+Referred by qrtz_cron_triggers ( sched_name, trigger_name, trigger_group ) 
+Referred by qrtz_simple_triggers ( sched_name, trigger_name, trigger_group ) 
+Referred by qrtz_simprop_triggers ( sched_name, trigger_name, trigger_group ) </title></a>
+  <use id='nn' x='257' y='237' xlink:href='#nn'/><a xlink:href='#qrtz_triggers.trigger_name'><use id='pk' x='257' y='236' xlink:href='#pk'/><title>Pk pk_qrtz_triggers ( sched_name, trigger_name, trigger_group ) </title></a>
+<a xlink:href='#qrtz_triggers.trigger_name'><text id='ry.qrtz_triggers.trigger_name' x='273' y='246' onmouseover="hghl(['qrtz_blob_triggers_qrtz_blob_triggers_ibfk_1','ry.qrtz_blob_triggers.sched_name','ry.qrtz_blob_triggers.trigger_name','ry.qrtz_blob_triggers.trigger_group','qrtz_cron_triggers_qrtz_cron_triggers_ibfk_1','ry.qrtz_cron_triggers.sched_name','ry.qrtz_cron_triggers.trigger_name','ry.qrtz_cron_triggers.trigger_group','qrtz_simple_triggers_qrtz_simple_triggers_ibfk_1','ry.qrtz_simple_triggers.sched_name','ry.qrtz_simple_triggers.trigger_name','ry.qrtz_simple_triggers.trigger_group','qrtz_simprop_triggers_qrtz_simprop_triggers_ibfk_1','ry.qrtz_simprop_triggers.sched_name','ry.qrtz_simprop_triggers.trigger_name','ry.qrtz_simprop_triggers.trigger_group'])" onmouseout="uhghl(['qrtz_blob_triggers_qrtz_blob_triggers_ibfk_1','ry.qrtz_blob_triggers.sched_name','ry.qrtz_blob_triggers.trigger_name','ry.qrtz_blob_triggers.trigger_group','qrtz_cron_triggers_qrtz_cron_triggers_ibfk_1','ry.qrtz_cron_triggers.sched_name','ry.qrtz_cron_triggers.trigger_name','ry.qrtz_cron_triggers.trigger_group','qrtz_simple_triggers_qrtz_simple_triggers_ibfk_1','ry.qrtz_simple_triggers.sched_name','ry.qrtz_simple_triggers.trigger_name','ry.qrtz_simple_triggers.trigger_group','qrtz_simprop_triggers_qrtz_simprop_triggers_ibfk_1','ry.qrtz_simprop_triggers.sched_name','ry.qrtz_simprop_triggers.trigger_name','ry.qrtz_simprop_triggers.trigger_group'])">trigger_name</text><title>trigger_name
+* varchar(200)</title></a>
+<a xlink:href='#qrtz_triggers.trigger_name'><use id='ref' x='364' y='236' xlink:href='#ref'/><title>Referred by qrtz_blob_triggers ( sched_name, trigger_name, trigger_group ) 
+Referred by qrtz_cron_triggers ( sched_name, trigger_name, trigger_group ) 
+Referred by qrtz_simple_triggers ( sched_name, trigger_name, trigger_group ) 
+Referred by qrtz_simprop_triggers ( sched_name, trigger_name, trigger_group ) </title></a>
+  <use id='nn' x='257' y='252' xlink:href='#nn'/><a xlink:href='#qrtz_triggers.trigger_group'><use id='pk' x='257' y='251' xlink:href='#pk'/><title>Pk pk_qrtz_triggers ( sched_name, trigger_name, trigger_group ) </title></a>
+<a xlink:href='#qrtz_triggers.trigger_group'><text id='ry.qrtz_triggers.trigger_group' x='273' y='261' onmouseover="hghl(['qrtz_blob_triggers_qrtz_blob_triggers_ibfk_1','ry.qrtz_blob_triggers.sched_name','ry.qrtz_blob_triggers.trigger_name','ry.qrtz_blob_triggers.trigger_group','qrtz_cron_triggers_qrtz_cron_triggers_ibfk_1','ry.qrtz_cron_triggers.sched_name','ry.qrtz_cron_triggers.trigger_name','ry.qrtz_cron_triggers.trigger_group','qrtz_simple_triggers_qrtz_simple_triggers_ibfk_1','ry.qrtz_simple_triggers.sched_name','ry.qrtz_simple_triggers.trigger_name','ry.qrtz_simple_triggers.trigger_group','qrtz_simprop_triggers_qrtz_simprop_triggers_ibfk_1','ry.qrtz_simprop_triggers.sched_name','ry.qrtz_simprop_triggers.trigger_name','ry.qrtz_simprop_triggers.trigger_group'])" onmouseout="uhghl(['qrtz_blob_triggers_qrtz_blob_triggers_ibfk_1','ry.qrtz_blob_triggers.sched_name','ry.qrtz_blob_triggers.trigger_name','ry.qrtz_blob_triggers.trigger_group','qrtz_cron_triggers_qrtz_cron_triggers_ibfk_1','ry.qrtz_cron_triggers.sched_name','ry.qrtz_cron_triggers.trigger_name','ry.qrtz_cron_triggers.trigger_group','qrtz_simple_triggers_qrtz_simple_triggers_ibfk_1','ry.qrtz_simple_triggers.sched_name','ry.qrtz_simple_triggers.trigger_name','ry.qrtz_simple_triggers.trigger_group','qrtz_simprop_triggers_qrtz_simprop_triggers_ibfk_1','ry.qrtz_simprop_triggers.sched_name','ry.qrtz_simprop_triggers.trigger_name','ry.qrtz_simprop_triggers.trigger_group'])">trigger_group</text><title>trigger_group
+* varchar(200)</title></a>
+<a xlink:href='#qrtz_triggers.trigger_group'><use id='ref' x='364' y='251' xlink:href='#ref'/><title>Referred by qrtz_blob_triggers ( sched_name, trigger_name, trigger_group ) 
+Referred by qrtz_cron_triggers ( sched_name, trigger_name, trigger_group ) 
+Referred by qrtz_simple_triggers ( sched_name, trigger_name, trigger_group ) 
+Referred by qrtz_simprop_triggers ( sched_name, trigger_name, trigger_group ) </title></a>
+  <use id='nn' x='257' y='267' xlink:href='#nn'/><a xlink:href='#qrtz_triggers.job_name'><use id='idx' x='257' y='266' xlink:href='#idx'/><title>sched_name ( sched_name, job_name, job_group ) </title></a>
+<a xlink:href='#qrtz_triggers.job_name'><text id='ry.qrtz_triggers.job_name' x='273' y='276' onmouseover="hghl(['qrtz_triggers_qrtz_triggers_ibfk_1','ry.qrtz_job_details.sched_name','ry.qrtz_job_details.job_name','ry.qrtz_job_details.job_group'])" onmouseout="uhghl(['qrtz_triggers_qrtz_triggers_ibfk_1','ry.qrtz_job_details.sched_name','ry.qrtz_job_details.job_name','ry.qrtz_job_details.job_group'])">job_name</text><title>job_name
+* varchar(200)</title></a>
+<a xlink:href='#qrtz_triggers.job_name'><use id='fk' x='364' y='266' xlink:href='#fk'/><title>References qrtz_job_details ( sched_name, job_name, job_group ) </title></a>
+  <use id='nn' x='257' y='282' xlink:href='#nn'/><a xlink:href='#qrtz_triggers.job_group'><use id='idx' x='257' y='281' xlink:href='#idx'/><title>sched_name ( sched_name, job_name, job_group ) </title></a>
+<a xlink:href='#qrtz_triggers.job_group'><text id='ry.qrtz_triggers.job_group' x='273' y='291' onmouseover="hghl(['qrtz_triggers_qrtz_triggers_ibfk_1','ry.qrtz_job_details.sched_name','ry.qrtz_job_details.job_name','ry.qrtz_job_details.job_group'])" onmouseout="uhghl(['qrtz_triggers_qrtz_triggers_ibfk_1','ry.qrtz_job_details.sched_name','ry.qrtz_job_details.job_name','ry.qrtz_job_details.job_group'])">job_group</text><title>job_group
+* varchar(200)</title></a>
+<a xlink:href='#qrtz_triggers.job_group'><use id='fk' x='364' y='281' xlink:href='#fk'/><title>References qrtz_job_details ( sched_name, job_name, job_group ) </title></a>
+  <a xlink:href='#qrtz_triggers.description'><text id='ry.qrtz_triggers.description' x='273' y='306'>description</text><title>description
+varchar(250)</title></a>
+<text x='372' y='303' text-anchor='end' class='colType'>t</text>  <a xlink:href='#qrtz_triggers.next_fire_time'><text id='ry.qrtz_triggers.next_fire_time' x='273' y='321'>next_fire_time</text><title>next_fire_time
+bigint</title></a>
+<text x='372' y='318' text-anchor='end' class='colType'>#</text>  <a xlink:href='#qrtz_triggers.prev_fire_time'><text id='ry.qrtz_triggers.prev_fire_time' x='273' y='336'>prev_fire_time</text><title>prev_fire_time
+bigint</title></a>
+<text x='372' y='333' text-anchor='end' class='colType'>#</text>  <a xlink:href='#qrtz_triggers.priority'><text id='ry.qrtz_triggers.priority' x='273' y='351'>priority</text><title>priority
+int</title></a>
+<text x='372' y='348' text-anchor='end' class='colType'>#</text>  <use id='nn' x='257' y='357' xlink:href='#nn'/><a xlink:href='#qrtz_triggers.trigger_state'><text id='ry.qrtz_triggers.trigger_state' x='273' y='366'>trigger_state</text><title>trigger_state
+* varchar(16)</title></a>
+<text x='372' y='363' text-anchor='end' class='colType'>t</text>  <use id='nn' x='257' y='372' xlink:href='#nn'/><a xlink:href='#qrtz_triggers.trigger_type'><text id='ry.qrtz_triggers.trigger_type' x='273' y='381'>trigger_type</text><title>trigger_type
+* varchar(8)</title></a>
+<text x='372' y='378' text-anchor='end' class='colType'>t</text>  <use id='nn' x='257' y='387' xlink:href='#nn'/><a xlink:href='#qrtz_triggers.start_time'><text id='ry.qrtz_triggers.start_time' x='273' y='396'>start_time</text><title>start_time
+* bigint</title></a>
+<text x='372' y='393' text-anchor='end' class='colType'>#</text>  <a xlink:href='#qrtz_triggers.end_time'><text id='ry.qrtz_triggers.end_time' x='273' y='411'>end_time</text><title>end_time
+bigint</title></a>
+<text x='372' y='408' text-anchor='end' class='colType'>#</text>  <a xlink:href='#qrtz_triggers.calendar_name'><text id='ry.qrtz_triggers.calendar_name' x='273' y='426'>calendar_name</text><title>calendar_name
+varchar(200)</title></a>
+<text x='372' y='423' text-anchor='end' class='colType'>t</text>  <a xlink:href='#qrtz_triggers.misfire_instr'><text id='ry.qrtz_triggers.misfire_instr' x='273' y='441'>misfire_instr</text><title>misfire_instr
+smallint</title></a>
+<text x='372' y='438' text-anchor='end' class='colType'>#</text>  <a xlink:href='#qrtz_triggers.job_data'><text id='ry.qrtz_triggers.job_data' x='273' y='456'>job_data</text><title>job_data
+blob</title></a>
+<text x='372' y='453' text-anchor='end' class='colType'>~</text>
+<!-- == Table 'sys_dict_data' == -->
+<rect class='entity' x='1170' y='38' width='105' height='210' rx='7' ry='7' style='stroke:none'/>
+<path d='M 1170 64 L 1170 45 Q 1170 38 1177 38 L 1268 38 Q 1275 38 1275 45 L 1275 64 L1170 64 ' style='fill:url(#tbg_c8f5bf);stroke:1;stroke-opacity:0.1;' />
+<rect class='entity' x='1170' y='38' width='105' height='210' rx='7' ry='7' style='fill:none;stroke:#626e5f'/>
+<line class='delim' x1='1170' y1='64' x2='1275' y2='64' style='stroke:#626e5f'/>
+<line class='delim' x1='1185' y1='64' x2='1185' y2='248' style='stroke:#626e5f'/>
+<line class='delim' x1='1264' y1='64' x2='1264' y2='248' style='stroke:#626e5f'/>
+<a xlink:href='#sys_dict_data'><text x='1180' y='56'>sys_dict_data</text><title>Table ry.sys_dict_data</title></a>
+  <use id='nn' x='1172' y='72' xlink:href='#nn'/><a xlink:href='#sys_dict_data.dict_code'><use id='pk' x='1172' y='71' xlink:href='#pk'/><title>Pk pk_sys_dict_data ( dict_code ) </title></a>
+<a xlink:href='#sys_dict_data.dict_code'><text id='ry.sys_dict_data.dict_code' x='1188' y='81'>dict_code</text><title>dict_code
+* int
+字典编码</title></a>
+<text x='1272' y='78' text-anchor='end' class='colType'>#</text>  <a xlink:href='#sys_dict_data.dict_sort'><text id='ry.sys_dict_data.dict_sort' x='1188' y='96'>dict_sort</text><title>dict_sort
+int default 0
+字典排序</title></a>
+<text x='1272' y='93' text-anchor='end' class='colType'>#</text>  <a xlink:href='#sys_dict_data.dict_label'><text id='ry.sys_dict_data.dict_label' x='1188' y='111'>dict_label</text><title>dict_label
+varchar(100) default ''
+字典标签</title></a>
+<text x='1272' y='108' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_dict_data.dict_value'><text id='ry.sys_dict_data.dict_value' x='1188' y='126'>dict_value</text><title>dict_value
+varchar(100) default ''
+字典键值</title></a>
+<text x='1272' y='123' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_dict_data.dict_type'><text id='ry.sys_dict_data.dict_type' x='1188' y='141'>dict_type</text><title>dict_type
+varchar(100) default ''
+字典类型</title></a>
+<text x='1272' y='138' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_dict_data.status'><text id='ry.sys_dict_data.status' x='1188' y='156'>status</text><title>status
+int default 0
+状态(0正常 1禁用)</title></a>
+<text x='1272' y='153' text-anchor='end' class='colType'>#</text>  <a xlink:href='#sys_dict_data.create_by'><text id='ry.sys_dict_data.create_by' x='1188' y='171'>create_by</text><title>create_by
+varchar(64) default ''
+创建者</title></a>
+<text x='1272' y='168' text-anchor='end' class='colType'>t</text>  <use id='nn' x='1172' y='177' xlink:href='#nn'/><a xlink:href='#sys_dict_data.create_time'><text id='ry.sys_dict_data.create_time' x='1188' y='186'>create_time</text><title>create_time
+* timestamp default CURRENT_TIMESTAMP
+创建时间</title></a>
+<text x='1272' y='183' text-anchor='end' class='colType'>d</text>  <a xlink:href='#sys_dict_data.update_by'><text id='ry.sys_dict_data.update_by' x='1188' y='201'>update_by</text><title>update_by
+varchar(64) default ''
+更新者</title></a>
+<text x='1272' y='198' text-anchor='end' class='colType'>t</text>  <use id='nn' x='1172' y='207' xlink:href='#nn'/><a xlink:href='#sys_dict_data.update_time'><text id='ry.sys_dict_data.update_time' x='1188' y='216'>update_time</text><title>update_time
+* timestamp default '0000-00-00 00:00:00'
+更新时间</title></a>
+<text x='1272' y='213' text-anchor='end' class='colType'>d</text>  <a xlink:href='#sys_dict_data.remark'><text id='ry.sys_dict_data.remark' x='1188' y='231'>remark</text><title>remark
+varchar(500) default ''
+备注</title></a>
+<text x='1272' y='228' text-anchor='end' class='colType'>t</text>
+<!-- == Table 'sys_dict_type' == -->
+<rect class='entity' x='1005' y='38' width='105' height='180' rx='7' ry='7' style='stroke:none'/>
+<path d='M 1005 64 L 1005 45 Q 1005 38 1012 38 L 1103 38 Q 1110 38 1110 45 L 1110 64 L1005 64 ' style='fill:url(#tbg_c8f5bf);stroke:1;stroke-opacity:0.1;' />
+<rect class='entity' x='1005' y='38' width='105' height='180' rx='7' ry='7' style='fill:none;stroke:#626e5f'/>
+<line class='delim' x1='1005' y1='64' x2='1110' y2='64' style='stroke:#626e5f'/>
+<line class='delim' x1='1020' y1='64' x2='1020' y2='218' style='stroke:#626e5f'/>
+<line class='delim' x1='1099' y1='64' x2='1099' y2='218' style='stroke:#626e5f'/>
+<a xlink:href='#sys_dict_type'><text x='1015' y='56'>sys_dict_type</text><title>Table ry.sys_dict_type</title></a>
+  <use id='nn' x='1007' y='72' xlink:href='#nn'/><a xlink:href='#sys_dict_type.dict_id'><use id='pk' x='1007' y='71' xlink:href='#pk'/><title>Pk pk_sys_dict_type ( dict_id ) </title></a>
+<a xlink:href='#sys_dict_type.dict_id'><text id='ry.sys_dict_type.dict_id' x='1023' y='81'>dict_id</text><title>dict_id
+* int
+字典主键</title></a>
+<text x='1107' y='78' text-anchor='end' class='colType'>#</text>  <a xlink:href='#sys_dict_type.dict_name'><text id='ry.sys_dict_type.dict_name' x='1023' y='96'>dict_name</text><title>dict_name
+varchar(100) default ''
+字典名称</title></a>
+<text x='1107' y='93' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_dict_type.dict_type'><use id='unq' x='1007' y='101' xlink:href='#unq'/><title>Unq dict_type ( dict_type ) </title></a>
+<a xlink:href='#sys_dict_type.dict_type'><text id='ry.sys_dict_type.dict_type' x='1023' y='111'>dict_type</text><title>dict_type
+varchar(100) default ''
+字典类型</title></a>
+<text x='1107' y='108' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_dict_type.status'><text id='ry.sys_dict_type.status' x='1023' y='126'>status</text><title>status
+int default 0
+状态(0正常 1禁用)</title></a>
+<text x='1107' y='123' text-anchor='end' class='colType'>#</text>  <a xlink:href='#sys_dict_type.create_by'><text id='ry.sys_dict_type.create_by' x='1023' y='141'>create_by</text><title>create_by
+varchar(64) default ''
+创建者</title></a>
+<text x='1107' y='138' text-anchor='end' class='colType'>t</text>  <use id='nn' x='1007' y='147' xlink:href='#nn'/><a xlink:href='#sys_dict_type.create_time'><text id='ry.sys_dict_type.create_time' x='1023' y='156'>create_time</text><title>create_time
+* timestamp default CURRENT_TIMESTAMP
+创建时间</title></a>
+<text x='1107' y='153' text-anchor='end' class='colType'>d</text>  <a xlink:href='#sys_dict_type.update_by'><text id='ry.sys_dict_type.update_by' x='1023' y='171'>update_by</text><title>update_by
+varchar(64) default ''
+更新者</title></a>
+<text x='1107' y='168' text-anchor='end' class='colType'>t</text>  <use id='nn' x='1007' y='177' xlink:href='#nn'/><a xlink:href='#sys_dict_type.update_time'><text id='ry.sys_dict_type.update_time' x='1023' y='186'>update_time</text><title>update_time
+* timestamp default '0000-00-00 00:00:00'
+更新时间</title></a>
+<text x='1107' y='183' text-anchor='end' class='colType'>d</text>  <a xlink:href='#sys_dict_type.remark'><text id='ry.sys_dict_type.remark' x='1023' y='201'>remark</text><title>remark
+varchar(500) default ''
+备注</title></a>
+<text x='1107' y='198' text-anchor='end' class='colType'>t</text>
+<!-- == Table 'sys_job' == -->
+<rect class='entity' x='1545' y='38' width='135' height='225' rx='7' ry='7' style='stroke:none'/>
+<path d='M 1545 64 L 1545 45 Q 1545 38 1552 38 L 1673 38 Q 1680 38 1680 45 L 1680 64 L1545 64 ' style='fill:url(#tbg_f5ddbf);stroke:1;stroke-opacity:0.1;' />
+<rect class='entity' x='1545' y='38' width='135' height='225' rx='7' ry='7' style='fill:none;stroke:#6e675f'/>
+<line class='delim' x1='1545' y1='64' x2='1680' y2='64' style='stroke:#6e675f'/>
+<line class='delim' x1='1560' y1='64' x2='1560' y2='263' style='stroke:#6e675f'/>
+<line class='delim' x1='1669' y1='64' x2='1669' y2='263' style='stroke:#6e675f'/>
+<a xlink:href='#sys_job'><text x='1588' y='56'>sys_job</text><title>Table ry.sys_job</title></a>
+  <use id='nn' x='1547' y='72' xlink:href='#nn'/><a xlink:href='#sys_job.job_id'><use id='pk' x='1547' y='71' xlink:href='#pk'/><title>Pk pk_sys_job ( job_id, job_name, job_group ) </title></a>
+<a xlink:href='#sys_job.job_id'><text id='ry.sys_job.job_id' x='1563' y='81'>job_id</text><title>job_id
+* int
+任务ID</title></a>
+<text x='1677' y='78' text-anchor='end' class='colType'>#</text>  <use id='nn' x='1547' y='87' xlink:href='#nn'/><a xlink:href='#sys_job.job_name'><use id='pk' x='1547' y='86' xlink:href='#pk'/><title>Pk pk_sys_job ( job_id, job_name, job_group ) </title></a>
+<a xlink:href='#sys_job.job_name'><text id='ry.sys_job.job_name' x='1563' y='96'>job_name</text><title>job_name
+* varchar(64) default ''
+任务名称</title></a>
+<text x='1677' y='93' text-anchor='end' class='colType'>t</text>  <use id='nn' x='1547' y='102' xlink:href='#nn'/><a xlink:href='#sys_job.job_group'><use id='pk' x='1547' y='101' xlink:href='#pk'/><title>Pk pk_sys_job ( job_id, job_name, job_group ) </title></a>
+<a xlink:href='#sys_job.job_group'><text id='ry.sys_job.job_group' x='1563' y='111'>job_group</text><title>job_group
+* varchar(64) default ''
+任务组名</title></a>
+<text x='1677' y='108' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_job.method_name'><text id='ry.sys_job.method_name' x='1563' y='126'>method_name</text><title>method_name
+varchar(500) default ''
+任务方法</title></a>
+<text x='1677' y='123' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_job.params'><text id='ry.sys_job.params' x='1563' y='141'>params</text><title>params
+varchar(200) default ''
+方法参数</title></a>
+<text x='1677' y='138' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_job.cron_expression'><text id='ry.sys_job.cron_expression' x='1563' y='156'>cron_expression</text><title>cron_expression
+varchar(255) default ''
+cron执行表达式</title></a>
+<text x='1677' y='153' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_job.status'><text id='ry.sys_job.status' x='1563' y='171'>status</text><title>status
+int default 0
+状态(0正常 1暂停)</title></a>
+<text x='1677' y='168' text-anchor='end' class='colType'>#</text>  <a xlink:href='#sys_job.create_by'><text id='ry.sys_job.create_by' x='1563' y='186'>create_by</text><title>create_by
+varchar(64) default ''
+创建者</title></a>
+<text x='1677' y='183' text-anchor='end' class='colType'>t</text>  <use id='nn' x='1547' y='192' xlink:href='#nn'/><a xlink:href='#sys_job.create_time'><text id='ry.sys_job.create_time' x='1563' y='201'>create_time</text><title>create_time
+* timestamp default CURRENT_TIMESTAMP
+创建时间</title></a>
+<text x='1677' y='198' text-anchor='end' class='colType'>d</text>  <a xlink:href='#sys_job.update_by'><text id='ry.sys_job.update_by' x='1563' y='216'>update_by</text><title>update_by
+varchar(64) default ''
+更新者</title></a>
+<text x='1677' y='213' text-anchor='end' class='colType'>t</text>  <use id='nn' x='1547' y='222' xlink:href='#nn'/><a xlink:href='#sys_job.update_time'><text id='ry.sys_job.update_time' x='1563' y='231'>update_time</text><title>update_time
+* timestamp default '0000-00-00 00:00:00'
+更新时间</title></a>
+<text x='1677' y='228' text-anchor='end' class='colType'>d</text>  <a xlink:href='#sys_job.remark'><text id='ry.sys_job.remark' x='1563' y='246'>remark</text><title>remark
+varchar(500) default ''
+备注信息</title></a>
+<text x='1677' y='243' text-anchor='end' class='colType'>t</text>
+<!-- == Table 'sys_job_log' == -->
+<rect class='entity' x='1365' y='38' width='120' height='180' rx='7' ry='7' style='stroke:none'/>
+<path d='M 1365 64 L 1365 45 Q 1365 38 1372 38 L 1478 38 Q 1485 38 1485 45 L 1485 64 L1365 64 ' style='fill:url(#tbg_f5ddbf);stroke:1;stroke-opacity:0.1;' />
+<rect class='entity' x='1365' y='38' width='120' height='180' rx='7' ry='7' style='fill:none;stroke:#6e675f'/>
+<line class='delim' x1='1365' y1='64' x2='1485' y2='64' style='stroke:#6e675f'/>
+<line class='delim' x1='1380' y1='64' x2='1380' y2='218' style='stroke:#6e675f'/>
+<line class='delim' x1='1474' y1='64' x2='1474' y2='218' style='stroke:#6e675f'/>
+<a xlink:href='#sys_job_log'><text x='1389' y='56'>sys_job_log</text><title>Table ry.sys_job_log</title></a>
+  <use id='nn' x='1367' y='72' xlink:href='#nn'/><a xlink:href='#sys_job_log.job_log_id'><use id='pk' x='1367' y='71' xlink:href='#pk'/><title>Pk pk_sys_job_log ( job_log_id ) </title></a>
+<a xlink:href='#sys_job_log.job_log_id'><text id='ry.sys_job_log.job_log_id' x='1383' y='81'>job_log_id</text><title>job_log_id
+* int
+任务日志ID</title></a>
+<text x='1482' y='78' text-anchor='end' class='colType'>#</text>  <use id='nn' x='1367' y='87' xlink:href='#nn'/><a xlink:href='#sys_job_log.job_name'><text id='ry.sys_job_log.job_name' x='1383' y='96'>job_name</text><title>job_name
+* varchar(64)
+任务名称</title></a>
+<text x='1482' y='93' text-anchor='end' class='colType'>t</text>  <use id='nn' x='1367' y='102' xlink:href='#nn'/><a xlink:href='#sys_job_log.job_group'><text id='ry.sys_job_log.job_group' x='1383' y='111'>job_group</text><title>job_group
+* varchar(64)
+任务组名</title></a>
+<text x='1482' y='108' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_job_log.method_name'><text id='ry.sys_job_log.method_name' x='1383' y='126'>method_name</text><title>method_name
+varchar(500)
+任务方法</title></a>
+<text x='1482' y='123' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_job_log.params'><text id='ry.sys_job_log.params' x='1383' y='141'>params</text><title>params
+varchar(200) default ''
+方法参数</title></a>
+<text x='1482' y='138' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_job_log.job_message'><text id='ry.sys_job_log.job_message' x='1383' y='156'>job_message</text><title>job_message
+varchar(500)
+日志信息</title></a>
+<text x='1482' y='153' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_job_log.is_exception'><text id='ry.sys_job_log.is_exception' x='1383' y='171'>is_exception</text><title>is_exception
+int default 0
+是否异常</title></a>
+<text x='1482' y='168' text-anchor='end' class='colType'>#</text>  <a xlink:href='#sys_job_log.exception_info'><text id='ry.sys_job_log.exception_info' x='1383' y='186'>exception_info</text><title>exception_info
+text
+异常信息</title></a>
+<text x='1482' y='183' text-anchor='end' class='colType'>t</text>  <use id='nn' x='1367' y='192' xlink:href='#nn'/><a xlink:href='#sys_job_log.create_time'><text id='ry.sys_job_log.create_time' x='1383' y='201'>create_time</text><title>create_time
+* timestamp default CURRENT_TIMESTAMP
+创建时间</title></a>
+<text x='1482' y='198' text-anchor='end' class='colType'>d</text>
+<!-- == Table 'sys_logininfor' == -->
+<rect class='entity' x='1740' y='323' width='105' height='165' rx='7' ry='7' style='stroke:none'/>
+<path d='M 1740 349 L 1740 330 Q 1740 323 1747 323 L 1838 323 Q 1845 323 1845 330 L 1845 349 L1740 349 ' style='fill:url(#tbg_f5ddbf);stroke:1;stroke-opacity:0.1;' />
+<rect class='entity' x='1740' y='323' width='105' height='165' rx='7' ry='7' style='fill:none;stroke:#6e675f'/>
+<line class='delim' x1='1740' y1='349' x2='1845' y2='349' style='stroke:#6e675f'/>
+<line class='delim' x1='1755' y1='349' x2='1755' y2='488' style='stroke:#6e675f'/>
+<line class='delim' x1='1834' y1='349' x2='1834' y2='488' style='stroke:#6e675f'/>
+<a xlink:href='#sys_logininfor'><text x='1747' y='341'>sys_logininfor</text><title>Table ry.sys_logininfor</title></a>
+  <use id='nn' x='1742' y='357' xlink:href='#nn'/><a xlink:href='#sys_logininfor.info_id'><use id='pk' x='1742' y='356' xlink:href='#pk'/><title>Pk pk_sys_logininfor ( info_id ) </title></a>
+<a xlink:href='#sys_logininfor.info_id'><text id='ry.sys_logininfor.info_id' x='1758' y='366'>info_id</text><title>info_id
+* int
+访问ID</title></a>
+<text x='1842' y='363' text-anchor='end' class='colType'>#</text>  <a xlink:href='#sys_logininfor.login_name'><text id='ry.sys_logininfor.login_name' x='1758' y='381'>login_name</text><title>login_name
+varchar(50) default ''
+登录账号</title></a>
+<text x='1842' y='378' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_logininfor.ipaddr'><text id='ry.sys_logininfor.ipaddr' x='1758' y='396'>ipaddr</text><title>ipaddr
+varchar(50) default ''
+登录IP地址</title></a>
+<text x='1842' y='393' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_logininfor.browser'><text id='ry.sys_logininfor.browser' x='1758' y='411'>browser</text><title>browser
+varchar(50) default ''
+浏览器类型</title></a>
+<text x='1842' y='408' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_logininfor.os'><text id='ry.sys_logininfor.os' x='1758' y='426'>os</text><title>os
+varchar(50) default ''
+操作系统</title></a>
+<text x='1842' y='423' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_logininfor.status'><text id='ry.sys_logininfor.status' x='1758' y='441'>status</text><title>status
+int default 0
+登录状态 0成功 1失败</title></a>
+<text x='1842' y='438' text-anchor='end' class='colType'>#</text>  <a xlink:href='#sys_logininfor.msg'><text id='ry.sys_logininfor.msg' x='1758' y='456'>msg</text><title>msg
+varchar(255) default ''
+提示消息</title></a>
+<text x='1842' y='453' text-anchor='end' class='colType'>t</text>  <use id='nn' x='1742' y='462' xlink:href='#nn'/><a xlink:href='#sys_logininfor.login_time'><text id='ry.sys_logininfor.login_time' x='1758' y='471'>login_time</text><title>login_time
+* timestamp default CURRENT_TIMESTAMP
+访问时间</title></a>
+<text x='1842' y='468' text-anchor='end' class='colType'>d</text>
+<!-- == Table 'sys_menu' == -->
+<rect class='entity' x='1380' y='323' width='105' height='255' rx='7' ry='7' style='stroke:none'/>
+<path d='M 1380 349 L 1380 330 Q 1380 323 1387 323 L 1478 323 Q 1485 323 1485 330 L 1485 349 L1380 349 ' style='fill:url(#tbg_f5ddbf);stroke:1;stroke-opacity:0.1;' />
+<rect class='entity' x='1380' y='323' width='105' height='255' rx='7' ry='7' style='fill:none;stroke:#6e675f'/>
+<line class='delim' x1='1380' y1='349' x2='1485' y2='349' style='stroke:#6e675f'/>
+<line class='delim' x1='1395' y1='349' x2='1395' y2='578' style='stroke:#6e675f'/>
+<line class='delim' x1='1474' y1='349' x2='1474' y2='578' style='stroke:#6e675f'/>
+<a xlink:href='#sys_menu'><text x='1405' y='341'>sys_menu</text><title>Table ry.sys_menu</title></a>
+  <use id='nn' x='1382' y='357' xlink:href='#nn'/><a xlink:href='#sys_menu.menu_id'><use id='pk' x='1382' y='356' xlink:href='#pk'/><title>Pk pk_sys_menu ( menu_id ) </title></a>
+<a xlink:href='#sys_menu.menu_id'><text id='ry.sys_menu.menu_id' x='1398' y='366'>menu_id</text><title>menu_id
+* int
+菜单ID</title></a>
+<text x='1482' y='363' text-anchor='end' class='colType'>#</text>  <use id='nn' x='1382' y='372' xlink:href='#nn'/><a xlink:href='#sys_menu.menu_name'><text id='ry.sys_menu.menu_name' x='1398' y='381'>menu_name</text><title>menu_name
+* varchar(50)
+菜单名称</title></a>
+<text x='1482' y='378' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_menu.parent_id'><text id='ry.sys_menu.parent_id' x='1398' y='396'>parent_id</text><title>parent_id
+int default 0
+父菜单ID</title></a>
+<text x='1482' y='393' text-anchor='end' class='colType'>#</text>  <a xlink:href='#sys_menu.order_num'><text id='ry.sys_menu.order_num' x='1398' y='411'>order_num</text><title>order_num
+int
+显示顺序</title></a>
+<text x='1482' y='408' text-anchor='end' class='colType'>#</text>  <a xlink:href='#sys_menu.url'><text id='ry.sys_menu.url' x='1398' y='426'>url</text><title>url
+varchar(200) default ''
+请求地址</title></a>
+<text x='1482' y='423' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_menu.menu_type'><text id='ry.sys_menu.menu_type' x='1398' y='441'>menu_type</text><title>menu_type
+char(1) default ''
+类型:M目录,C菜单,F按钮</title></a>
+<text x='1482' y='438' text-anchor='end' class='colType'>c</text>  <a xlink:href='#sys_menu.visible'><text id='ry.sys_menu.visible' x='1398' y='456'>visible</text><title>visible
+int default 0
+菜单状态:0显示,1隐藏</title></a>
+<text x='1482' y='453' text-anchor='end' class='colType'>#</text>  <a xlink:href='#sys_menu.perms'><text id='ry.sys_menu.perms' x='1398' y='471'>perms</text><title>perms
+varchar(100) default ''
+权限标识</title></a>
+<text x='1482' y='468' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_menu.icon'><text id='ry.sys_menu.icon' x='1398' y='486'>icon</text><title>icon
+varchar(100) default ''
+菜单图标</title></a>
+<text x='1482' y='483' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_menu.create_by'><text id='ry.sys_menu.create_by' x='1398' y='501'>create_by</text><title>create_by
+varchar(64) default ''
+创建者</title></a>
+<text x='1482' y='498' text-anchor='end' class='colType'>t</text>  <use id='nn' x='1382' y='507' xlink:href='#nn'/><a xlink:href='#sys_menu.create_time'><text id='ry.sys_menu.create_time' x='1398' y='516'>create_time</text><title>create_time
+* timestamp default CURRENT_TIMESTAMP
+创建时间</title></a>
+<text x='1482' y='513' text-anchor='end' class='colType'>d</text>  <a xlink:href='#sys_menu.update_by'><text id='ry.sys_menu.update_by' x='1398' y='531'>update_by</text><title>update_by
+varchar(64) default ''
+更新者</title></a>
+<text x='1482' y='528' text-anchor='end' class='colType'>t</text>  <use id='nn' x='1382' y='537' xlink:href='#nn'/><a xlink:href='#sys_menu.update_time'><text id='ry.sys_menu.update_time' x='1398' y='546'>update_time</text><title>update_time
+* timestamp default '0000-00-00 00:00:00'
+更新时间</title></a>
+<text x='1482' y='543' text-anchor='end' class='colType'>d</text>  <a xlink:href='#sys_menu.remark'><text id='ry.sys_menu.remark' x='1398' y='561'>remark</text><title>remark
+varchar(500) default ''
+备注</title></a>
+<text x='1482' y='558' text-anchor='end' class='colType'>t</text>
+<!-- == Table 'sys_oper_log' == -->
+<rect class='entity' x='1005' y='278' width='105' height='240' rx='7' ry='7' style='stroke:none'/>
+<path d='M 1005 304 L 1005 285 Q 1005 278 1012 278 L 1103 278 Q 1110 278 1110 285 L 1110 304 L1005 304 ' style='fill:url(#tbg_c8f5bf);stroke:1;stroke-opacity:0.1;' />
+<rect class='entity' x='1005' y='278' width='105' height='240' rx='7' ry='7' style='fill:none;stroke:#626e5f'/>
+<line class='delim' x1='1005' y1='304' x2='1110' y2='304' style='stroke:#626e5f'/>
+<line class='delim' x1='1020' y1='304' x2='1020' y2='518' style='stroke:#626e5f'/>
+<line class='delim' x1='1099' y1='304' x2='1099' y2='518' style='stroke:#626e5f'/>
+<a xlink:href='#sys_oper_log'><text x='1018' y='296'>sys_oper_log</text><title>Table ry.sys_oper_log</title></a>
+  <use id='nn' x='1007' y='312' xlink:href='#nn'/><a xlink:href='#sys_oper_log.oper_id'><use id='pk' x='1007' y='311' xlink:href='#pk'/><title>Pk pk_sys_oper_log ( oper_id ) </title></a>
+<a xlink:href='#sys_oper_log.oper_id'><text id='ry.sys_oper_log.oper_id' x='1023' y='321'>oper_id</text><title>oper_id
+* int
+日志主键</title></a>
+<text x='1107' y='318' text-anchor='end' class='colType'>#</text>  <a xlink:href='#sys_oper_log.title'><text id='ry.sys_oper_log.title' x='1023' y='336'>title</text><title>title
+varchar(50) default ''
+模块标题</title></a>
+<text x='1107' y='333' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_oper_log.action'><text id='ry.sys_oper_log.action' x='1023' y='351'>action</text><title>action
+varchar(100) default ''
+功能请求</title></a>
+<text x='1107' y='348' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_oper_log.method'><text id='ry.sys_oper_log.method' x='1023' y='366'>method</text><title>method
+varchar(100) default ''
+方法名称</title></a>
+<text x='1107' y='363' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_oper_log.channel'><text id='ry.sys_oper_log.channel' x='1023' y='381'>channel</text><title>channel
+varchar(20) default ''
+来源渠道</title></a>
+<text x='1107' y='378' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_oper_log.login_name'><text id='ry.sys_oper_log.login_name' x='1023' y='396'>login_name</text><title>login_name
+varchar(50) default ''
+登录账号</title></a>
+<text x='1107' y='393' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_oper_log.dept_name'><text id='ry.sys_oper_log.dept_name' x='1023' y='411'>dept_name</text><title>dept_name
+varchar(50) default ''
+部门名称</title></a>
+<text x='1107' y='408' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_oper_log.oper_url'><text id='ry.sys_oper_log.oper_url' x='1023' y='426'>oper_url</text><title>oper_url
+varchar(255) default ''
+请求URL</title></a>
+<text x='1107' y='423' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_oper_log.oper_ip'><text id='ry.sys_oper_log.oper_ip' x='1023' y='441'>oper_ip</text><title>oper_ip
+varchar(30) default ''
+主机地址</title></a>
+<text x='1107' y='438' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_oper_log.oper_param'><text id='ry.sys_oper_log.oper_param' x='1023' y='456'>oper_param</text><title>oper_param
+varchar(255) default ''
+请求参数</title></a>
+<text x='1107' y='453' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_oper_log.status'><text id='ry.sys_oper_log.status' x='1023' y='471'>status</text><title>status
+int default 0
+操作状态 0正常 1异常</title></a>
+<text x='1107' y='468' text-anchor='end' class='colType'>#</text>  <a xlink:href='#sys_oper_log.error_msg'><text id='ry.sys_oper_log.error_msg' x='1023' y='486'>error_msg</text><title>error_msg
+varchar(2000) default ''
+错误消息</title></a>
+<text x='1107' y='483' text-anchor='end' class='colType'>t</text>  <use id='nn' x='1007' y='492' xlink:href='#nn'/><a xlink:href='#sys_oper_log.oper_time'><text id='ry.sys_oper_log.oper_time' x='1023' y='501'>oper_time</text><title>oper_time
+* timestamp default CURRENT_TIMESTAMP
+操作时间</title></a>
+<text x='1107' y='498' text-anchor='end' class='colType'>d</text>
+<!-- == Table 'sys_post' == -->
+<rect class='entity' x='1740' y='38' width='105' height='195' rx='7' ry='7' style='stroke:none'/>
+<path d='M 1740 64 L 1740 45 Q 1740 38 1747 38 L 1838 38 Q 1845 38 1845 45 L 1845 64 L1740 64 ' style='fill:url(#tbg_f5ddbf);stroke:1;stroke-opacity:0.1;' />
+<rect class='entity' x='1740' y='38' width='105' height='195' rx='7' ry='7' style='fill:none;stroke:#6e675f'/>
+<line class='delim' x1='1740' y1='64' x2='1845' y2='64' style='stroke:#6e675f'/>
+<line class='delim' x1='1755' y1='64' x2='1755' y2='233' style='stroke:#6e675f'/>
+<line class='delim' x1='1834' y1='64' x2='1834' y2='233' style='stroke:#6e675f'/>
+<a xlink:href='#sys_post'><text x='1765' y='56'>sys_post</text><title>Table ry.sys_post</title></a>
+  <use id='nn' x='1742' y='72' xlink:href='#nn'/><a xlink:href='#sys_post.post_id'><use id='pk' x='1742' y='71' xlink:href='#pk'/><title>Pk pk_sys_post ( post_id ) </title></a>
+<a xlink:href='#sys_post.post_id'><text id='ry.sys_post.post_id' x='1758' y='81'>post_id</text><title>post_id
+* int
+岗位ID</title></a>
+<text x='1842' y='78' text-anchor='end' class='colType'>#</text>  <use id='nn' x='1742' y='87' xlink:href='#nn'/><a xlink:href='#sys_post.post_code'><text id='ry.sys_post.post_code' x='1758' y='96'>post_code</text><title>post_code
+* varchar(64)
+岗位编码</title></a>
+<text x='1842' y='93' text-anchor='end' class='colType'>t</text>  <use id='nn' x='1742' y='102' xlink:href='#nn'/><a xlink:href='#sys_post.post_name'><text id='ry.sys_post.post_name' x='1758' y='111'>post_name</text><title>post_name
+* varchar(100)
+岗位名称</title></a>
+<text x='1842' y='108' text-anchor='end' class='colType'>t</text>  <use id='nn' x='1742' y='117' xlink:href='#nn'/><a xlink:href='#sys_post.post_sort'><text id='ry.sys_post.post_sort' x='1758' y='126'>post_sort</text><title>post_sort
+* int
+显示顺序</title></a>
+<text x='1842' y='123' text-anchor='end' class='colType'>#</text>  <use id='nn' x='1742' y='132' xlink:href='#nn'/><a xlink:href='#sys_post.status'><text id='ry.sys_post.status' x='1758' y='141'>status</text><title>status
+* int
+状态(0正常 1停用)</title></a>
+<text x='1842' y='138' text-anchor='end' class='colType'>#</text>  <a xlink:href='#sys_post.create_by'><text id='ry.sys_post.create_by' x='1758' y='156'>create_by</text><title>create_by
+varchar(64) default ''
+创建者</title></a>
+<text x='1842' y='153' text-anchor='end' class='colType'>t</text>  <use id='nn' x='1742' y='162' xlink:href='#nn'/><a xlink:href='#sys_post.create_time'><text id='ry.sys_post.create_time' x='1758' y='171'>create_time</text><title>create_time
+* timestamp default CURRENT_TIMESTAMP
+创建时间</title></a>
+<text x='1842' y='168' text-anchor='end' class='colType'>d</text>  <a xlink:href='#sys_post.update_by'><text id='ry.sys_post.update_by' x='1758' y='186'>update_by</text><title>update_by
+varchar(64) default ''
+更新者</title></a>
+<text x='1842' y='183' text-anchor='end' class='colType'>t</text>  <use id='nn' x='1742' y='192' xlink:href='#nn'/><a xlink:href='#sys_post.update_time'><text id='ry.sys_post.update_time' x='1758' y='201'>update_time</text><title>update_time
+* timestamp default '0000-00-00 00:00:00'
+更新时间</title></a>
+<text x='1842' y='198' text-anchor='end' class='colType'>d</text>  <a xlink:href='#sys_post.remark'><text id='ry.sys_post.remark' x='1758' y='216'>remark</text><title>remark
+varchar(500) default ''
+备注</title></a>
+<text x='1842' y='213' text-anchor='end' class='colType'>t</text>
+<!-- == Table 'sys_role' == -->
+<rect class='entity' x='1545' y='458' width='105' height='195' rx='7' ry='7' style='stroke:none'/>
+<path d='M 1545 484 L 1545 465 Q 1545 458 1552 458 L 1643 458 Q 1650 458 1650 465 L 1650 484 L1545 484 ' style='fill:url(#tbg_f5ddbf);stroke:1;stroke-opacity:0.1;' />
+<rect class='entity' x='1545' y='458' width='105' height='195' rx='7' ry='7' style='fill:none;stroke:#6e675f'/>
+<line class='delim' x1='1545' y1='484' x2='1650' y2='484' style='stroke:#6e675f'/>
+<line class='delim' x1='1560' y1='484' x2='1560' y2='653' style='stroke:#6e675f'/>
+<line class='delim' x1='1639' y1='484' x2='1639' y2='653' style='stroke:#6e675f'/>
+<a xlink:href='#sys_role'><text x='1570' y='476'>sys_role</text><title>Table ry.sys_role</title></a>
+  <use id='nn' x='1547' y='492' xlink:href='#nn'/><a xlink:href='#sys_role.role_id'><use id='pk' x='1547' y='491' xlink:href='#pk'/><title>Pk pk_sys_role ( role_id ) </title></a>
+<a xlink:href='#sys_role.role_id'><text id='ry.sys_role.role_id' x='1563' y='501'>role_id</text><title>role_id
+* int
+角色ID</title></a>
+<text x='1647' y='498' text-anchor='end' class='colType'>#</text>  <use id='nn' x='1547' y='507' xlink:href='#nn'/><a xlink:href='#sys_role.role_name'><text id='ry.sys_role.role_name' x='1563' y='516'>role_name</text><title>role_name
+* varchar(30)
+角色名称</title></a>
+<text x='1647' y='513' text-anchor='end' class='colType'>t</text>  <use id='nn' x='1547' y='522' xlink:href='#nn'/><a xlink:href='#sys_role.role_key'><text id='ry.sys_role.role_key' x='1563' y='531'>role_key</text><title>role_key
+* varchar(100)
+角色权限字符串</title></a>
+<text x='1647' y='528' text-anchor='end' class='colType'>t</text>  <use id='nn' x='1547' y='537' xlink:href='#nn'/><a xlink:href='#sys_role.role_sort'><text id='ry.sys_role.role_sort' x='1563' y='546'>role_sort</text><title>role_sort
+* int
+显示顺序</title></a>
+<text x='1647' y='543' text-anchor='end' class='colType'>#</text>  <a xlink:href='#sys_role.status'><text id='ry.sys_role.status' x='1563' y='561'>status</text><title>status
+int default 0
+角色状态:0正常,1禁用</title></a>
+<text x='1647' y='558' text-anchor='end' class='colType'>#</text>  <a xlink:href='#sys_role.create_by'><text id='ry.sys_role.create_by' x='1563' y='576'>create_by</text><title>create_by
+varchar(64) default ''
+创建者</title></a>
+<text x='1647' y='573' text-anchor='end' class='colType'>t</text>  <use id='nn' x='1547' y='582' xlink:href='#nn'/><a xlink:href='#sys_role.create_time'><text id='ry.sys_role.create_time' x='1563' y='591'>create_time</text><title>create_time
+* timestamp default CURRENT_TIMESTAMP
+创建时间</title></a>
+<text x='1647' y='588' text-anchor='end' class='colType'>d</text>  <a xlink:href='#sys_role.update_by'><text id='ry.sys_role.update_by' x='1563' y='606'>update_by</text><title>update_by
+varchar(64) default ''
+更新者</title></a>
+<text x='1647' y='603' text-anchor='end' class='colType'>t</text>  <use id='nn' x='1547' y='612' xlink:href='#nn'/><a xlink:href='#sys_role.update_time'><text id='ry.sys_role.update_time' x='1563' y='621'>update_time</text><title>update_time
+* timestamp default '0000-00-00 00:00:00'
+更新时间</title></a>
+<text x='1647' y='618' text-anchor='end' class='colType'>d</text>  <a xlink:href='#sys_role.remark'><text id='ry.sys_role.remark' x='1563' y='636'>remark</text><title>remark
+varchar(500) default ''
+备注</title></a>
+<text x='1647' y='633' text-anchor='end' class='colType'>t</text>
+<!-- == Table 'sys_role_menu' == -->
+<rect class='entity' x='1545' y='323' width='90' height='75' rx='7' ry='7' style='stroke:none'/>
+<path d='M 1545 349 L 1545 330 Q 1545 323 1552 323 L 1628 323 Q 1635 323 1635 330 L 1635 349 L1545 349 ' style='fill:url(#tbg_f5ddbf);stroke:1;stroke-opacity:0.1;' />
+<rect class='entity' x='1545' y='323' width='90' height='75' rx='7' ry='7' style='fill:none;stroke:#6e675f'/>
+<line class='delim' x1='1545' y1='349' x2='1635' y2='349' style='stroke:#6e675f'/>
+<line class='delim' x1='1560' y1='349' x2='1560' y2='398' style='stroke:#6e675f'/>
+<line class='delim' x1='1624' y1='349' x2='1624' y2='398' style='stroke:#6e675f'/>
+<a xlink:href='#sys_role_menu'><text x='1548' y='341'>sys_role_menu</text><title>Table ry.sys_role_menu</title></a>
+  <use id='nn' x='1547' y='357' xlink:href='#nn'/><a xlink:href='#sys_role_menu.role_id'><use id='pk' x='1547' y='356' xlink:href='#pk'/><title>Pk pk_sys_role_menu ( role_id, menu_id ) </title></a>
+<a xlink:href='#sys_role_menu.role_id'><text id='ry.sys_role_menu.role_id' x='1563' y='366'>role_id</text><title>role_id
+* int
+角色ID</title></a>
+<text x='1632' y='363' text-anchor='end' class='colType'>#</text>  <use id='nn' x='1547' y='372' xlink:href='#nn'/><a xlink:href='#sys_role_menu.menu_id'><use id='pk' x='1547' y='371' xlink:href='#pk'/><title>Pk pk_sys_role_menu ( role_id, menu_id ) </title></a>
+<a xlink:href='#sys_role_menu.menu_id'><text id='ry.sys_role_menu.menu_id' x='1563' y='381'>menu_id</text><title>menu_id
+* int
+菜单ID</title></a>
+<text x='1632' y='378' text-anchor='end' class='colType'>#</text>
+<!-- == Table 'sys_user' == -->
+<rect class='entity' x='690' y='83' width='105' height='270' rx='7' ry='7' style='stroke:none'/>
+<path d='M 690 109 L 690 90 Q 690 83 697 83 L 788 83 Q 795 83 795 90 L 795 109 L690 109 ' style='fill:url(#tbg_c8f5bf);stroke:1;stroke-opacity:0.1;' />
+<rect class='entity' x='690' y='83' width='105' height='270' rx='7' ry='7' style='fill:none;stroke:#626e5f'/>
+<line class='delim' x1='690' y1='109' x2='795' y2='109' style='stroke:#626e5f'/>
+<line class='delim' x1='705' y1='109' x2='705' y2='353' style='stroke:#626e5f'/>
+<line class='delim' x1='784' y1='109' x2='784' y2='353' style='stroke:#626e5f'/>
+<a xlink:href='#sys_user'><text x='715' y='101'>sys_user</text><title>Table ry.sys_user</title></a>
+  <use id='nn' x='692' y='117' xlink:href='#nn'/><a xlink:href='#sys_user.user_id'><use id='pk' x='692' y='116' xlink:href='#pk'/><title>Pk pk_sys_user ( user_id ) </title></a>
+<a xlink:href='#sys_user.user_id'><text id='ry.sys_user.user_id' x='708' y='126'>user_id</text><title>user_id
+* int
+用户ID</title></a>
+<text x='792' y='123' text-anchor='end' class='colType'>#</text>  <a xlink:href='#sys_user.dept_id'><text id='ry.sys_user.dept_id' x='708' y='141'>dept_id</text><title>dept_id
+int
+部门ID</title></a>
+<text x='792' y='138' text-anchor='end' class='colType'>#</text>  <a xlink:href='#sys_user.login_name'><text id='ry.sys_user.login_name' x='708' y='156'>login_name</text><title>login_name
+varchar(30) default ''
+登录账号</title></a>
+<text x='792' y='153' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_user.user_name'><text id='ry.sys_user.user_name' x='708' y='171'>user_name</text><title>user_name
+varchar(30) default ''
+用户昵称</title></a>
+<text x='792' y='168' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_user.email'><text id='ry.sys_user.email' x='708' y='186'>email</text><title>email
+varchar(100) default ''
+用户邮箱</title></a>
+<text x='792' y='183' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_user.phonenumber'><text id='ry.sys_user.phonenumber' x='708' y='201'>phonenumber</text><title>phonenumber
+varchar(20) default ''
+手机号码</title></a>
+<text x='792' y='198' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_user.password'><text id='ry.sys_user.password' x='708' y='216'>password</text><title>password
+varchar(100) default ''
+密码</title></a>
+<text x='792' y='213' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_user.salt'><text id='ry.sys_user.salt' x='708' y='231'>salt</text><title>salt
+varchar(100) default ''
+盐加密</title></a>
+<text x='792' y='228' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_user.user_type'><text id='ry.sys_user.user_type' x='708' y='246'>user_type</text><title>user_type
+char(1) default 'N'
+类型:Y默认用户,N非默认用户</title></a>
+<text x='792' y='243' text-anchor='end' class='colType'>c</text>  <a xlink:href='#sys_user.status'><text id='ry.sys_user.status' x='708' y='261'>status</text><title>status
+int default 0
+帐号状态:0正常,1禁用</title></a>
+<text x='792' y='258' text-anchor='end' class='colType'>#</text>  <a xlink:href='#sys_user.refuse_des'><text id='ry.sys_user.refuse_des' x='708' y='276'>refuse_des</text><title>refuse_des
+varchar(500) default ''
+拒绝登录描述</title></a>
+<text x='792' y='273' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_user.create_by'><text id='ry.sys_user.create_by' x='708' y='291'>create_by</text><title>create_by
+varchar(64) default ''
+创建者</title></a>
+<text x='792' y='288' text-anchor='end' class='colType'>t</text>  <use id='nn' x='692' y='297' xlink:href='#nn'/><a xlink:href='#sys_user.create_time'><text id='ry.sys_user.create_time' x='708' y='306'>create_time</text><title>create_time
+* timestamp default CURRENT_TIMESTAMP
+创建时间</title></a>
+<text x='792' y='303' text-anchor='end' class='colType'>d</text>  <a xlink:href='#sys_user.update_by'><text id='ry.sys_user.update_by' x='708' y='321'>update_by</text><title>update_by
+varchar(64) default ''
+更新者</title></a>
+<text x='792' y='318' text-anchor='end' class='colType'>t</text>  <use id='nn' x='692' y='327' xlink:href='#nn'/><a xlink:href='#sys_user.update_time'><text id='ry.sys_user.update_time' x='708' y='336'>update_time</text><title>update_time
+* timestamp default '0000-00-00 00:00:00'
+更新时间</title></a>
+<text x='792' y='333' text-anchor='end' class='colType'>d</text>
+<!-- == Table 'sys_user_online' == -->
+<rect class='entity' x='660' y='413' width='135' height='195' rx='7' ry='7' style='stroke:none'/>
+<path d='M 660 439 L 660 420 Q 660 413 667 413 L 788 413 Q 795 413 795 420 L 795 439 L660 439 ' style='fill:url(#tbg_c8f5bf);stroke:1;stroke-opacity:0.1;' />
+<rect class='entity' x='660' y='413' width='135' height='195' rx='7' ry='7' style='fill:none;stroke:#626e5f'/>
+<line class='delim' x1='660' y1='439' x2='795' y2='439' style='stroke:#626e5f'/>
+<line class='delim' x1='675' y1='439' x2='675' y2='608' style='stroke:#626e5f'/>
+<line class='delim' x1='784' y1='439' x2='784' y2='608' style='stroke:#626e5f'/>
+<a xlink:href='#sys_user_online'><text x='679' y='431'>sys_user_online</text><title>Table ry.sys_user_online</title></a>
+  <use id='nn' x='662' y='447' xlink:href='#nn'/><a xlink:href='#sys_user_online.sessionId'><use id='pk' x='662' y='446' xlink:href='#pk'/><title>Pk pk_sys_user_online ( sessionId ) </title></a>
+<a xlink:href='#sys_user_online.sessionId'><text id='ry.sys_user_online.sessionId' x='678' y='456'>sessionId</text><title>sessionId
+* varchar(50) default ''
+用户会话id</title></a>
+<text x='792' y='453' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_user_online.login_name'><text id='ry.sys_user_online.login_name' x='678' y='471'>login_name</text><title>login_name
+varchar(50) default ''
+登录账号</title></a>
+<text x='792' y='468' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_user_online.dept_name'><text id='ry.sys_user_online.dept_name' x='678' y='486'>dept_name</text><title>dept_name
+varchar(50) default ''
+部门名称</title></a>
+<text x='792' y='483' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_user_online.ipaddr'><text id='ry.sys_user_online.ipaddr' x='678' y='501'>ipaddr</text><title>ipaddr
+varchar(50) default ''
+登录IP地址</title></a>
+<text x='792' y='498' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_user_online.browser'><text id='ry.sys_user_online.browser' x='678' y='516'>browser</text><title>browser
+varchar(50) default ''
+浏览器类型</title></a>
+<text x='792' y='513' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_user_online.os'><text id='ry.sys_user_online.os' x='678' y='531'>os</text><title>os
+varchar(50) default ''
+操作系统</title></a>
+<text x='792' y='528' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_user_online.status'><text id='ry.sys_user_online.status' x='678' y='546'>status</text><title>status
+varchar(10) default ''
+在线状态on_line在线off_line离线</title></a>
+<text x='792' y='543' text-anchor='end' class='colType'>t</text>  <use id='nn' x='662' y='552' xlink:href='#nn'/><a xlink:href='#sys_user_online.start_timestamp'><text id='ry.sys_user_online.start_timestamp' x='678' y='561'>start_timestamp</text><title>start_timestamp
+* timestamp default CURRENT_TIMESTAMP
+session创建时间</title></a>
+<text x='792' y='558' text-anchor='end' class='colType'>d</text>  <use id='nn' x='662' y='567' xlink:href='#nn'/><a xlink:href='#sys_user_online.last_access_time'><text id='ry.sys_user_online.last_access_time' x='678' y='576'>last_access_time</text><title>last_access_time
+* timestamp default '0000-00-00 00:00:00'
+session最后访问时间</title></a>
+<text x='792' y='573' text-anchor='end' class='colType'>d</text>  <a xlink:href='#sys_user_online.expire_time'><text id='ry.sys_user_online.expire_time' x='678' y='591'>expire_time</text><title>expire_time
+int default 0
+超时时间,单位为分钟</title></a>
+<text x='792' y='588' text-anchor='end' class='colType'>#</text>
+<!-- == Table 'sys_user_post' == -->
+<rect class='entity' x='855' y='413' width='90' height='75' rx='7' ry='7' style='stroke:none'/>
+<path d='M 855 439 L 855 420 Q 855 413 862 413 L 938 413 Q 945 413 945 420 L 945 439 L855 439 ' style='fill:url(#tbg_c8f5bf);stroke:1;stroke-opacity:0.1;' />
+<rect class='entity' x='855' y='413' width='90' height='75' rx='7' ry='7' style='fill:none;stroke:#626e5f'/>
+<line class='delim' x1='855' y1='439' x2='945' y2='439' style='stroke:#626e5f'/>
+<line class='delim' x1='870' y1='439' x2='870' y2='488' style='stroke:#626e5f'/>
+<line class='delim' x1='934' y1='439' x2='934' y2='488' style='stroke:#626e5f'/>
+<a xlink:href='#sys_user_post'><text x='858' y='431'>sys_user_post</text><title>Table ry.sys_user_post</title></a>
+  <use id='nn' x='857' y='447' xlink:href='#nn'/><a xlink:href='#sys_user_post.user_id'><use id='pk' x='857' y='446' xlink:href='#pk'/><title>Pk pk_sys_user_post ( user_id, post_id ) </title></a>
+<a xlink:href='#sys_user_post.user_id'><text id='ry.sys_user_post.user_id' x='873' y='456'>user_id</text><title>user_id
+* varchar(64)
+用户ID</title></a>
+<text x='942' y='453' text-anchor='end' class='colType'>t</text>  <use id='nn' x='857' y='462' xlink:href='#nn'/><a xlink:href='#sys_user_post.post_id'><use id='pk' x='857' y='461' xlink:href='#pk'/><title>Pk pk_sys_user_post ( user_id, post_id ) </title></a>
+<a xlink:href='#sys_user_post.post_id'><text id='ry.sys_user_post.post_id' x='873' y='471'>post_id</text><title>post_id
+* varchar(64)
+岗位ID</title></a>
+<text x='942' y='468' text-anchor='end' class='colType'>t</text>
+<!-- == Table 'sys_user_role' == -->
+<rect class='entity' x='855' y='278' width='90' height='75' rx='7' ry='7' style='stroke:none'/>
+<path d='M 855 304 L 855 285 Q 855 278 862 278 L 938 278 Q 945 278 945 285 L 945 304 L855 304 ' style='fill:url(#tbg_c8f5bf);stroke:1;stroke-opacity:0.1;' />
+<rect class='entity' x='855' y='278' width='90' height='75' rx='7' ry='7' style='fill:none;stroke:#626e5f'/>
+<line class='delim' x1='855' y1='304' x2='945' y2='304' style='stroke:#626e5f'/>
+<line class='delim' x1='870' y1='304' x2='870' y2='353' style='stroke:#626e5f'/>
+<line class='delim' x1='934' y1='304' x2='934' y2='353' style='stroke:#626e5f'/>
+<a xlink:href='#sys_user_role'><text x='858' y='296'>sys_user_role</text><title>Table ry.sys_user_role</title></a>
+  <use id='nn' x='857' y='312' xlink:href='#nn'/><a xlink:href='#sys_user_role.user_id'><use id='pk' x='857' y='311' xlink:href='#pk'/><title>Pk pk_sys_user_role ( user_id, role_id ) </title></a>
+<a xlink:href='#sys_user_role.user_id'><text id='ry.sys_user_role.user_id' x='873' y='321'>user_id</text><title>user_id
+* int
+用户ID</title></a>
+<text x='942' y='318' text-anchor='end' class='colType'>#</text>  <use id='nn' x='857' y='327' xlink:href='#nn'/><a xlink:href='#sys_user_role.role_id'><use id='pk' x='857' y='326' xlink:href='#pk'/><title>Pk pk_sys_user_role ( user_id, role_id ) </title></a>
+<a xlink:href='#sys_user_role.role_id'><text id='ry.sys_user_role.role_id' x='873' y='336'>role_id</text><title>role_id
+* int
+角色ID</title></a>
+<text x='942' y='333' text-anchor='end' class='colType'>#</text>
+<!-- == Table 'sys_dept' == -->
+<rect class='entity' x='645' y='713' width='105' height='225' rx='7' ry='7' style='stroke:none'/>
+<path d='M 645 739 L 645 720 Q 645 713 652 713 L 743 713 Q 750 713 750 720 L 750 739 L645 739 ' style='fill:url(#tbg_bfbff5);stroke:1;stroke-opacity:0.1;' />
+<rect class='entity' x='645' y='713' width='105' height='225' rx='7' ry='7' style='fill:none;stroke:#5f5f6e'/>
+<line class='delim' x1='645' y1='739' x2='750' y2='739' style='stroke:#5f5f6e'/>
+<line class='delim' x1='660' y1='739' x2='660' y2='938' style='stroke:#5f5f6e'/>
+<line class='delim' x1='739' y1='739' x2='739' y2='938' style='stroke:#5f5f6e'/>
+<a xlink:href='#sys_dept'><text x='670' y='731'>sys_dept</text><title>Table ry.sys_dept</title></a>
+  <use id='nn' x='647' y='747' xlink:href='#nn'/><a xlink:href='#sys_dept.dept_id'><use id='pk' x='647' y='746' xlink:href='#pk'/><title>Pk pk_sys_dept ( dept_id ) </title></a>
+<a xlink:href='#sys_dept.dept_id'><text id='ry.sys_dept.dept_id' x='663' y='756'>dept_id</text><title>dept_id
+* int
+部门id</title></a>
+<text x='747' y='753' text-anchor='end' class='colType'>#</text>  <a xlink:href='#sys_dept.parent_id'><text id='ry.sys_dept.parent_id' x='663' y='771'>parent_id</text><title>parent_id
+int default 0
+父部门id</title></a>
+<text x='747' y='768' text-anchor='end' class='colType'>#</text>  <a xlink:href='#sys_dept.dept_name'><text id='ry.sys_dept.dept_name' x='663' y='786'>dept_name</text><title>dept_name
+varchar(30) default ''
+部门名称</title></a>
+<text x='747' y='783' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_dept.order_num'><text id='ry.sys_dept.order_num' x='663' y='801'>order_num</text><title>order_num
+int default 0
+显示顺序</title></a>
+<text x='747' y='798' text-anchor='end' class='colType'>#</text>  <a xlink:href='#sys_dept.leader'><text id='ry.sys_dept.leader' x='663' y='816'>leader</text><title>leader
+varchar(20) default ''
+负责人</title></a>
+<text x='747' y='813' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_dept.phone'><text id='ry.sys_dept.phone' x='663' y='831'>phone</text><title>phone
+varchar(20) default ''
+联系电话</title></a>
+<text x='747' y='828' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_dept.email'><text id='ry.sys_dept.email' x='663' y='846'>email</text><title>email
+varchar(20) default ''
+邮箱</title></a>
+<text x='747' y='843' text-anchor='end' class='colType'>t</text>  <a xlink:href='#sys_dept.status'><text id='ry.sys_dept.status' x='663' y='861'>status</text><title>status
+int default 0
+部门状态:0正常,1停用</title></a>
+<text x='747' y='858' text-anchor='end' class='colType'>#</text>  <a xlink:href='#sys_dept.create_by'><text id='ry.sys_dept.create_by' x='663' y='876'>create_by</text><title>create_by
+varchar(64) default ''
+创建者</title></a>
+<text x='747' y='873' text-anchor='end' class='colType'>t</text>  <use id='nn' x='647' y='882' xlink:href='#nn'/><a xlink:href='#sys_dept.create_time'><text id='ry.sys_dept.create_time' x='663' y='891'>create_time</text><title>create_time
+* timestamp default CURRENT_TIMESTAMP
+创建时间</title></a>
+<text x='747' y='888' text-anchor='end' class='colType'>d</text>  <a xlink:href='#sys_dept.update_by'><text id='ry.sys_dept.update_by' x='663' y='906'>update_by</text><title>update_by
+varchar(64) default ''
+更新者</title></a>
+<text x='747' y='903' text-anchor='end' class='colType'>t</text>  <use id='nn' x='647' y='912' xlink:href='#nn'/><a xlink:href='#sys_dept.update_time'><text id='ry.sys_dept.update_time' x='663' y='921'>update_time</text><title>update_time
+* timestamp default '0000-00-00 00:00:00'
+更新时间</title></a>
+<text x='747' y='918' text-anchor='end' class='colType'>d</text>
+<!-- == Table 'qrtz_paused_trigger_grps' == -->
+<rect class='entity' x='1260' y='683' width='165' height='75' rx='7' ry='7' style='stroke:none'/>
+<path d='M 1260 709 L 1260 690 Q 1260 683 1267 683 L 1418 683 Q 1425 683 1425 690 L 1425 709 L1260 709 ' style='fill:url(#tbg_bfbff5);stroke:1;stroke-opacity:0.1;' />
+<rect class='entity' x='1260' y='683' width='165' height='75' rx='7' ry='7' style='fill:none;stroke:#5f5f6e'/>
+<line class='delim' x1='1260' y1='709' x2='1425' y2='709' style='stroke:#5f5f6e'/>
+<line class='delim' x1='1275' y1='709' x2='1275' y2='758' style='stroke:#5f5f6e'/>
+<line class='delim' x1='1414' y1='709' x2='1414' y2='758' style='stroke:#5f5f6e'/>
+<a xlink:href='#qrtz_paused_trigger_grps'><text x='1267' y='701'>qrtz_paused_trigger_grps</text><title>Table ry.qrtz_paused_trigger_grps</title></a>
+  <use id='nn' x='1262' y='717' xlink:href='#nn'/><a xlink:href='#qrtz_paused_trigger_grps.sched_name'><use id='pk' x='1262' y='716' xlink:href='#pk'/><title>Pk pk_qrtz_paused_trigger_grps ( sched_name, trigger_group ) </title></a>
+<a xlink:href='#qrtz_paused_trigger_grps.sched_name'><text id='ry.qrtz_paused_trigger_grps.sched_name' x='1278' y='726'>sched_name</text><title>sched_name
+* varchar(120)</title></a>
+<text x='1422' y='723' text-anchor='end' class='colType'>t</text>  <use id='nn' x='1262' y='732' xlink:href='#nn'/><a xlink:href='#qrtz_paused_trigger_grps.trigger_group'><use id='pk' x='1262' y='731' xlink:href='#pk'/><title>Pk pk_qrtz_paused_trigger_grps ( sched_name, trigger_group ) </title></a>
+<a xlink:href='#qrtz_paused_trigger_grps.trigger_group'><text id='ry.qrtz_paused_trigger_grps.trigger_group' x='1278' y='741'>trigger_group</text><title>trigger_group
+* varchar(200)</title></a>
+<text x='1422' y='738' text-anchor='end' class='colType'>t</text>
+<!-- == Table 'qrtz_fired_triggers' == -->
+<rect class='entity' x='1035' y='668' width='135' height='240' rx='7' ry='7' style='stroke:none'/>
+<path d='M 1035 694 L 1035 675 Q 1035 668 1042 668 L 1163 668 Q 1170 668 1170 675 L 1170 694 L1035 694 ' style='fill:url(#tbg_bfbff5);stroke:1;stroke-opacity:0.1;' />
+<rect class='entity' x='1035' y='668' width='135' height='240' rx='7' ry='7' style='fill:none;stroke:#5f5f6e'/>
+<line class='delim' x1='1035' y1='694' x2='1170' y2='694' style='stroke:#5f5f6e'/>
+<line class='delim' x1='1050' y1='694' x2='1050' y2='908' style='stroke:#5f5f6e'/>
+<line class='delim' x1='1159' y1='694' x2='1159' y2='908' style='stroke:#5f5f6e'/>
+<a xlink:href='#qrtz_fired_triggers'><text x='1042' y='686'>qrtz_fired_triggers</text><title>Table ry.qrtz_fired_triggers</title></a>
+  <use id='nn' x='1037' y='702' xlink:href='#nn'/><a xlink:href='#qrtz_fired_triggers.sched_name'><use id='pk' x='1037' y='701' xlink:href='#pk'/><title>Pk pk_qrtz_fired_triggers ( sched_name, entry_id ) </title></a>
+<a xlink:href='#qrtz_fired_triggers.sched_name'><text id='ry.qrtz_fired_triggers.sched_name' x='1053' y='711'>sched_name</text><title>sched_name
+* varchar(120)</title></a>
+<text x='1167' y='708' text-anchor='end' class='colType'>t</text>  <use id='nn' x='1037' y='717' xlink:href='#nn'/><a xlink:href='#qrtz_fired_triggers.entry_id'><use id='pk' x='1037' y='716' xlink:href='#pk'/><title>Pk pk_qrtz_fired_triggers ( sched_name, entry_id ) </title></a>
+<a xlink:href='#qrtz_fired_triggers.entry_id'><text id='ry.qrtz_fired_triggers.entry_id' x='1053' y='726'>entry_id</text><title>entry_id
+* varchar(95)</title></a>
+<text x='1167' y='723' text-anchor='end' class='colType'>t</text>  <use id='nn' x='1037' y='732' xlink:href='#nn'/><a xlink:href='#qrtz_fired_triggers.trigger_name'><text id='ry.qrtz_fired_triggers.trigger_name' x='1053' y='741'>trigger_name</text><title>trigger_name
+* varchar(200)</title></a>
+<text x='1167' y='738' text-anchor='end' class='colType'>t</text>  <use id='nn' x='1037' y='747' xlink:href='#nn'/><a xlink:href='#qrtz_fired_triggers.trigger_group'><text id='ry.qrtz_fired_triggers.trigger_group' x='1053' y='756'>trigger_group</text><title>trigger_group
+* varchar(200)</title></a>
+<text x='1167' y='753' text-anchor='end' class='colType'>t</text>  <use id='nn' x='1037' y='762' xlink:href='#nn'/><a xlink:href='#qrtz_fired_triggers.instance_name'><text id='ry.qrtz_fired_triggers.instance_name' x='1053' y='771'>instance_name</text><title>instance_name
+* varchar(200)</title></a>
+<text x='1167' y='768' text-anchor='end' class='colType'>t</text>  <use id='nn' x='1037' y='777' xlink:href='#nn'/><a xlink:href='#qrtz_fired_triggers.fired_time'><text id='ry.qrtz_fired_triggers.fired_time' x='1053' y='786'>fired_time</text><title>fired_time
+* bigint</title></a>
+<text x='1167' y='783' text-anchor='end' class='colType'>#</text>  <use id='nn' x='1037' y='792' xlink:href='#nn'/><a xlink:href='#qrtz_fired_triggers.sched_time'><text id='ry.qrtz_fired_triggers.sched_time' x='1053' y='801'>sched_time</text><title>sched_time
+* bigint</title></a>
+<text x='1167' y='798' text-anchor='end' class='colType'>#</text>  <use id='nn' x='1037' y='807' xlink:href='#nn'/><a xlink:href='#qrtz_fired_triggers.priority'><text id='ry.qrtz_fired_triggers.priority' x='1053' y='816'>priority</text><title>priority
+* int</title></a>
+<text x='1167' y='813' text-anchor='end' class='colType'>#</text>  <use id='nn' x='1037' y='822' xlink:href='#nn'/><a xlink:href='#qrtz_fired_triggers.state'><text id='ry.qrtz_fired_triggers.state' x='1053' y='831'>state</text><title>state
+* varchar(16)</title></a>
+<text x='1167' y='828' text-anchor='end' class='colType'>t</text>  <a xlink:href='#qrtz_fired_triggers.job_name'><text id='ry.qrtz_fired_triggers.job_name' x='1053' y='846'>job_name</text><title>job_name
+varchar(200)</title></a>
+<text x='1167' y='843' text-anchor='end' class='colType'>t</text>  <a xlink:href='#qrtz_fired_triggers.job_group'><text id='ry.qrtz_fired_triggers.job_group' x='1053' y='861'>job_group</text><title>job_group
+varchar(200)</title></a>
+<text x='1167' y='858' text-anchor='end' class='colType'>t</text>  <a xlink:href='#qrtz_fired_triggers.is_nonconcurrent'><text id='ry.qrtz_fired_triggers.is_nonconcurrent' x='1053' y='876'>is_nonconcurrent</text><title>is_nonconcurrent
+varchar(1)</title></a>
+<text x='1167' y='873' text-anchor='end' class='colType'>t</text>  <a xlink:href='#qrtz_fired_triggers.requests_recovery'><text id='ry.qrtz_fired_triggers.requests_recovery' x='1053' y='891'>requests_recovery</text><title>requests_recovery
+varchar(1)</title></a>
+<text x='1167' y='888' text-anchor='end' class='colType'>t</text>
+</g></svg></div>
+
+
+<br/><br/>
+<div class='card'><div class='card-block'><a name='qrtz_blob_triggers' onclick='window.scrollTo(60, 540);return false;' style='cursor:pointer;'><h4 class='card-title'>Table qrtz_blob_triggers</h4></a>
+<table class='table-sm table-bordered'>
+<thead>
+<tr><th>Indexes</th><th>Field Name</th><th>Data Type</th><th>Description</th></tr></thead>
+<tbody>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg><svg width='14' height='14'><use xlink:href='#fk'/></svg></td>
+		<td><a name='qrtz_blob_triggers.sched_name'>sched&#95;name</a></td>
+		<td> varchar&#40; 120 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg><svg width='14' height='14'><use xlink:href='#fk'/></svg></td>
+		<td><a name='qrtz_blob_triggers.trigger_name'>trigger&#95;name</a></td>
+		<td> varchar&#40; 200 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg><svg width='14' height='14'><use xlink:href='#fk'/></svg></td>
+		<td><a name='qrtz_blob_triggers.trigger_group'>trigger&#95;group</a></td>
+		<td> varchar&#40; 200 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='qrtz_blob_triggers.blob_data'>blob&#95;data</a></td>
+		<td> blob   </td>
+		<td>  </td>
+	</tr>
+<tr><th colspan='4'>Indexes</th></tr>
+	<tr>		<td><svg width='14' height='14'><use xlink:href='#pk'/></svg></td><td>pk&#95;qrtz&#95;blob&#95;triggers</td>
+		<td> ON sched&#95;name&#44; trigger&#95;name&#44; trigger&#95;group</td>
+		<td>  </td>
+	</tr>
+<tr><th colspan='4'>Foreign Keys</th></tr>
+	<tr>
+		<td><svg width='14' height='14'><use xlink:href='#fk'/></svg></td><td>qrtz_blob_triggers_ibfk_1</td>
+		<td > ( sched&#95;name&#44; trigger&#95;name&#44; trigger&#95;group ) ref <a href='#qrtz&#95;triggers'>qrtz&#95;triggers</a> (sched&#95;name&#44; trigger&#95;name&#44; trigger&#95;group) </td>
+		<td>  </td>
+	</tr>
+</tbody>
+</table></div></div>
+
+<br/><br/>
+<div class='card'><div class='card-block'><a name='qrtz_calendars' onclick='window.scrollTo(60, 45);return false;' style='cursor:pointer;'><h4 class='card-title'>Table qrtz_calendars</h4></a>
+<table class='table-sm table-bordered'>
+<thead>
+<tr><th>Indexes</th><th>Field Name</th><th>Data Type</th><th>Description</th></tr></thead>
+<tbody>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg></td>
+		<td><a name='qrtz_calendars.sched_name'>sched&#95;name</a></td>
+		<td> varchar&#40; 120 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg></td>
+		<td><a name='qrtz_calendars.calendar_name'>calendar&#95;name</a></td>
+		<td> varchar&#40; 200 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='qrtz_calendars.calendar'>calendar</a></td>
+		<td> blob   </td>
+		<td>  </td>
+	</tr>
+<tr><th colspan='4'>Indexes</th></tr>
+	<tr>		<td><svg width='14' height='14'><use xlink:href='#pk'/></svg></td><td>pk&#95;qrtz&#95;calendars</td>
+		<td> ON sched&#95;name&#44; calendar&#95;name</td>
+		<td>  </td>
+	</tr>
+</tbody>
+</table></div></div>
+
+<br/><br/>
+<div class='card'><div class='card-block'><a name='qrtz_cron_triggers' onclick='window.scrollTo(235, 540);return false;' style='cursor:pointer;'><h4 class='card-title'>Table qrtz_cron_triggers</h4></a>
+<table class='table-sm table-bordered'>
+<thead>
+<tr><th>Indexes</th><th>Field Name</th><th>Data Type</th><th>Description</th></tr></thead>
+<tbody>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg><svg width='14' height='14'><use xlink:href='#fk'/></svg></td>
+		<td><a name='qrtz_cron_triggers.sched_name'>sched&#95;name</a></td>
+		<td> varchar&#40; 120 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg><svg width='14' height='14'><use xlink:href='#fk'/></svg></td>
+		<td><a name='qrtz_cron_triggers.trigger_name'>trigger&#95;name</a></td>
+		<td> varchar&#40; 200 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg><svg width='14' height='14'><use xlink:href='#fk'/></svg></td>
+		<td><a name='qrtz_cron_triggers.trigger_group'>trigger&#95;group</a></td>
+		<td> varchar&#40; 200 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='qrtz_cron_triggers.cron_expression'>cron&#95;expression</a></td>
+		<td> varchar&#40; 200 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='qrtz_cron_triggers.time_zone_id'>time&#95;zone&#95;id</a></td>
+		<td> varchar&#40; 80 &#41;   </td>
+		<td>  </td>
+	</tr>
+<tr><th colspan='4'>Indexes</th></tr>
+	<tr>		<td><svg width='14' height='14'><use xlink:href='#pk'/></svg></td><td>pk&#95;qrtz&#95;cron&#95;triggers</td>
+		<td> ON sched&#95;name&#44; trigger&#95;name&#44; trigger&#95;group</td>
+		<td>  </td>
+	</tr>
+<tr><th colspan='4'>Foreign Keys</th></tr>
+	<tr>
+		<td><svg width='14' height='14'><use xlink:href='#fk'/></svg></td><td>qrtz_cron_triggers_ibfk_1</td>
+		<td > ( sched&#95;name&#44; trigger&#95;name&#44; trigger&#95;group ) ref <a href='#qrtz&#95;triggers'>qrtz&#95;triggers</a> (sched&#95;name&#44; trigger&#95;name&#44; trigger&#95;group) </td>
+		<td>  </td>
+	</tr>
+</tbody>
+</table></div></div>
+
+<br/><br/>
+<div class='card'><div class='card-block'><a name='qrtz_fired_triggers' onclick='window.scrollTo(835, 675);return false;' style='cursor:pointer;'><h4 class='card-title'>Table qrtz_fired_triggers</h4></a>
+<table class='table-sm table-bordered'>
+<thead>
+<tr><th>Indexes</th><th>Field Name</th><th>Data Type</th><th>Description</th></tr></thead>
+<tbody>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg></td>
+		<td><a name='qrtz_fired_triggers.sched_name'>sched&#95;name</a></td>
+		<td> varchar&#40; 120 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg></td>
+		<td><a name='qrtz_fired_triggers.entry_id'>entry&#95;id</a></td>
+		<td> varchar&#40; 95 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='qrtz_fired_triggers.trigger_name'>trigger&#95;name</a></td>
+		<td> varchar&#40; 200 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='qrtz_fired_triggers.trigger_group'>trigger&#95;group</a></td>
+		<td> varchar&#40; 200 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='qrtz_fired_triggers.instance_name'>instance&#95;name</a></td>
+		<td> varchar&#40; 200 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='qrtz_fired_triggers.fired_time'>fired&#95;time</a></td>
+		<td> bigint   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='qrtz_fired_triggers.sched_time'>sched&#95;time</a></td>
+		<td> bigint   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='qrtz_fired_triggers.priority'>priority</a></td>
+		<td> int   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='qrtz_fired_triggers.state'>state</a></td>
+		<td> varchar&#40; 16 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='qrtz_fired_triggers.job_name'>job&#95;name</a></td>
+		<td> varchar&#40; 200 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='qrtz_fired_triggers.job_group'>job&#95;group</a></td>
+		<td> varchar&#40; 200 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='qrtz_fired_triggers.is_nonconcurrent'>is&#95;nonconcurrent</a></td>
+		<td> varchar&#40; 1 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='qrtz_fired_triggers.requests_recovery'>requests&#95;recovery</a></td>
+		<td> varchar&#40; 1 &#41;   </td>
+		<td>  </td>
+	</tr>
+<tr><th colspan='4'>Indexes</th></tr>
+	<tr>		<td><svg width='14' height='14'><use xlink:href='#pk'/></svg></td><td>pk&#95;qrtz&#95;fired&#95;triggers</td>
+		<td> ON sched&#95;name&#44; entry&#95;id</td>
+		<td>  </td>
+	</tr>
+</tbody>
+</table></div></div>
+
+<br/><br/>
+<div class='card'><div class='card-block'><a name='qrtz_job_details' onclick='window.scrollTo(235, 195);return false;' style='cursor:pointer;'><h4 class='card-title'>Table qrtz_job_details</h4></a>
+<table class='table-sm table-bordered'>
+<thead>
+<tr><th>Indexes</th><th>Field Name</th><th>Data Type</th><th>Description</th></tr></thead>
+<tbody>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg><svg width='14' height='14'><use xlink:href='#ref'/></svg></td>
+		<td><a name='qrtz_job_details.sched_name'>sched&#95;name</a></td>
+		<td> varchar&#40; 120 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg><svg width='14' height='14'><use xlink:href='#ref'/></svg></td>
+		<td><a name='qrtz_job_details.job_name'>job&#95;name</a></td>
+		<td> varchar&#40; 200 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg><svg width='14' height='14'><use xlink:href='#ref'/></svg></td>
+		<td><a name='qrtz_job_details.job_group'>job&#95;group</a></td>
+		<td> varchar&#40; 200 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='qrtz_job_details.description'>description</a></td>
+		<td> varchar&#40; 250 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='qrtz_job_details.job_class_name'>job&#95;class&#95;name</a></td>
+		<td> varchar&#40; 250 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='qrtz_job_details.is_durable'>is&#95;durable</a></td>
+		<td> varchar&#40; 1 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='qrtz_job_details.is_nonconcurrent'>is&#95;nonconcurrent</a></td>
+		<td> varchar&#40; 1 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='qrtz_job_details.is_update_data'>is&#95;update&#95;data</a></td>
+		<td> varchar&#40; 1 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='qrtz_job_details.requests_recovery'>requests&#95;recovery</a></td>
+		<td> varchar&#40; 1 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='qrtz_job_details.job_data'>job&#95;data</a></td>
+		<td> blob   </td>
+		<td>  </td>
+	</tr>
+<tr><th colspan='4'>Indexes</th></tr>
+	<tr>		<td><svg width='14' height='14'><use xlink:href='#pk'/></svg></td><td>pk&#95;qrtz&#95;job&#95;details</td>
+		<td> ON sched&#95;name&#44; job&#95;name&#44; job&#95;group</td>
+		<td>  </td>
+	</tr>
+</tbody>
+</table></div></div>
+
+<br/><br/>
+<div class='card'><div class='card-block'><a name='qrtz_locks' onclick='window.scrollTo(60, 60);return false;' style='cursor:pointer;'><h4 class='card-title'>Table qrtz_locks</h4></a>
+<table class='table-sm table-bordered'>
+<thead>
+<tr><th>Indexes</th><th>Field Name</th><th>Data Type</th><th>Description</th></tr></thead>
+<tbody>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg></td>
+		<td><a name='qrtz_locks.sched_name'>sched&#95;name</a></td>
+		<td> varchar&#40; 120 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg></td>
+		<td><a name='qrtz_locks.lock_name'>lock&#95;name</a></td>
+		<td> varchar&#40; 40 &#41;   </td>
+		<td>  </td>
+	</tr>
+<tr><th colspan='4'>Indexes</th></tr>
+	<tr>		<td><svg width='14' height='14'><use xlink:href='#pk'/></svg></td><td>pk&#95;qrtz&#95;locks</td>
+		<td> ON sched&#95;name&#44; lock&#95;name</td>
+		<td>  </td>
+	</tr>
+</tbody>
+</table></div></div>
+
+<br/><br/>
+<div class='card'><div class='card-block'><a name='qrtz_paused_trigger_grps' onclick='window.scrollTo(1060, 690);return false;' style='cursor:pointer;'><h4 class='card-title'>Table qrtz_paused_trigger_grps</h4></a>
+<table class='table-sm table-bordered'>
+<thead>
+<tr><th>Indexes</th><th>Field Name</th><th>Data Type</th><th>Description</th></tr></thead>
+<tbody>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg></td>
+		<td><a name='qrtz_paused_trigger_grps.sched_name'>sched&#95;name</a></td>
+		<td> varchar&#40; 120 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg></td>
+		<td><a name='qrtz_paused_trigger_grps.trigger_group'>trigger&#95;group</a></td>
+		<td> varchar&#40; 200 &#41;   </td>
+		<td>  </td>
+	</tr>
+<tr><th colspan='4'>Indexes</th></tr>
+	<tr>		<td><svg width='14' height='14'><use xlink:href='#pk'/></svg></td><td>pk&#95;qrtz&#95;paused&#95;trigger&#95;grps</td>
+		<td> ON sched&#95;name&#44; trigger&#95;group</td>
+		<td>  </td>
+	</tr>
+</tbody>
+</table></div></div>
+
+<br/><br/>
+<div class='card'><div class='card-block'><a name='qrtz_scheduler_state' onclick='window.scrollTo(60, 735);return false;' style='cursor:pointer;'><h4 class='card-title'>Table qrtz_scheduler_state</h4></a>
+<table class='table-sm table-bordered'>
+<thead>
+<tr><th>Indexes</th><th>Field Name</th><th>Data Type</th><th>Description</th></tr></thead>
+<tbody>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg></td>
+		<td><a name='qrtz_scheduler_state.sched_name'>sched&#95;name</a></td>
+		<td> varchar&#40; 120 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg></td>
+		<td><a name='qrtz_scheduler_state.instance_name'>instance&#95;name</a></td>
+		<td> varchar&#40; 200 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='qrtz_scheduler_state.last_checkin_time'>last&#95;checkin&#95;time</a></td>
+		<td> bigint   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='qrtz_scheduler_state.checkin_interval'>checkin&#95;interval</a></td>
+		<td> bigint   </td>
+		<td>  </td>
+	</tr>
+<tr><th colspan='4'>Indexes</th></tr>
+	<tr>		<td><svg width='14' height='14'><use xlink:href='#pk'/></svg></td><td>pk&#95;qrtz&#95;scheduler&#95;state</td>
+		<td> ON sched&#95;name&#44; instance&#95;name</td>
+		<td>  </td>
+	</tr>
+</tbody>
+</table></div></div>
+
+<br/><br/>
+<div class='card'><div class='card-block'><a name='qrtz_simple_triggers' onclick='window.scrollTo(60, 540);return false;' style='cursor:pointer;'><h4 class='card-title'>Table qrtz_simple_triggers</h4></a>
+<table class='table-sm table-bordered'>
+<thead>
+<tr><th>Indexes</th><th>Field Name</th><th>Data Type</th><th>Description</th></tr></thead>
+<tbody>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg><svg width='14' height='14'><use xlink:href='#fk'/></svg></td>
+		<td><a name='qrtz_simple_triggers.sched_name'>sched&#95;name</a></td>
+		<td> varchar&#40; 120 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg><svg width='14' height='14'><use xlink:href='#fk'/></svg></td>
+		<td><a name='qrtz_simple_triggers.trigger_name'>trigger&#95;name</a></td>
+		<td> varchar&#40; 200 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg><svg width='14' height='14'><use xlink:href='#fk'/></svg></td>
+		<td><a name='qrtz_simple_triggers.trigger_group'>trigger&#95;group</a></td>
+		<td> varchar&#40; 200 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='qrtz_simple_triggers.repeat_count'>repeat&#95;count</a></td>
+		<td> bigint   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='qrtz_simple_triggers.repeat_interval'>repeat&#95;interval</a></td>
+		<td> bigint   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='qrtz_simple_triggers.times_triggered'>times&#95;triggered</a></td>
+		<td> bigint   </td>
+		<td>  </td>
+	</tr>
+<tr><th colspan='4'>Indexes</th></tr>
+	<tr>		<td><svg width='14' height='14'><use xlink:href='#pk'/></svg></td><td>pk&#95;qrtz&#95;simple&#95;triggers</td>
+		<td> ON sched&#95;name&#44; trigger&#95;name&#44; trigger&#95;group</td>
+		<td>  </td>
+	</tr>
+<tr><th colspan='4'>Foreign Keys</th></tr>
+	<tr>
+		<td><svg width='14' height='14'><use xlink:href='#fk'/></svg></td><td>qrtz_simple_triggers_ibfk_1</td>
+		<td > ( sched&#95;name&#44; trigger&#95;name&#44; trigger&#95;group ) ref <a href='#qrtz&#95;triggers'>qrtz&#95;triggers</a> (sched&#95;name&#44; trigger&#95;name&#44; trigger&#95;group) </td>
+		<td>  </td>
+	</tr>
+</tbody>
+</table></div></div>
+
+<br/><br/>
+<div class='card'><div class='card-block'><a name='qrtz_simprop_triggers' onclick='window.scrollTo(60, 225);return false;' style='cursor:pointer;'><h4 class='card-title'>Table qrtz_simprop_triggers</h4></a>
+<table class='table-sm table-bordered'>
+<thead>
+<tr><th>Indexes</th><th>Field Name</th><th>Data Type</th><th>Description</th></tr></thead>
+<tbody>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg><svg width='14' height='14'><use xlink:href='#fk'/></svg></td>
+		<td><a name='qrtz_simprop_triggers.sched_name'>sched&#95;name</a></td>
+		<td> varchar&#40; 120 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg><svg width='14' height='14'><use xlink:href='#fk'/></svg></td>
+		<td><a name='qrtz_simprop_triggers.trigger_name'>trigger&#95;name</a></td>
+		<td> varchar&#40; 200 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg><svg width='14' height='14'><use xlink:href='#fk'/></svg></td>
+		<td><a name='qrtz_simprop_triggers.trigger_group'>trigger&#95;group</a></td>
+		<td> varchar&#40; 200 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='qrtz_simprop_triggers.str_prop_1'>str&#95;prop&#95;1</a></td>
+		<td> varchar&#40; 512 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='qrtz_simprop_triggers.str_prop_2'>str&#95;prop&#95;2</a></td>
+		<td> varchar&#40; 512 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='qrtz_simprop_triggers.str_prop_3'>str&#95;prop&#95;3</a></td>
+		<td> varchar&#40; 512 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='qrtz_simprop_triggers.int_prop_1'>int&#95;prop&#95;1</a></td>
+		<td> int   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='qrtz_simprop_triggers.int_prop_2'>int&#95;prop&#95;2</a></td>
+		<td> int   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='qrtz_simprop_triggers.long_prop_1'>long&#95;prop&#95;1</a></td>
+		<td> bigint   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='qrtz_simprop_triggers.long_prop_2'>long&#95;prop&#95;2</a></td>
+		<td> bigint   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='qrtz_simprop_triggers.dec_prop_1'>dec&#95;prop&#95;1</a></td>
+		<td> decimal&#40; 13&#44; 4 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='qrtz_simprop_triggers.dec_prop_2'>dec&#95;prop&#95;2</a></td>
+		<td> decimal&#40; 13&#44; 4 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='qrtz_simprop_triggers.bool_prop_1'>bool&#95;prop&#95;1</a></td>
+		<td> varchar&#40; 1 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='qrtz_simprop_triggers.bool_prop_2'>bool&#95;prop&#95;2</a></td>
+		<td> varchar&#40; 1 &#41;   </td>
+		<td>  </td>
+	</tr>
+<tr><th colspan='4'>Indexes</th></tr>
+	<tr>		<td><svg width='14' height='14'><use xlink:href='#pk'/></svg></td><td>pk&#95;qrtz&#95;simprop&#95;triggers</td>
+		<td> ON sched&#95;name&#44; trigger&#95;name&#44; trigger&#95;group</td>
+		<td>  </td>
+	</tr>
+<tr><th colspan='4'>Foreign Keys</th></tr>
+	<tr>
+		<td><svg width='14' height='14'><use xlink:href='#fk'/></svg></td><td>qrtz_simprop_triggers_ibfk_1</td>
+		<td > ( sched&#95;name&#44; trigger&#95;name&#44; trigger&#95;group ) ref <a href='#qrtz&#95;triggers'>qrtz&#95;triggers</a> (sched&#95;name&#44; trigger&#95;name&#44; trigger&#95;group) </td>
+		<td>  </td>
+	</tr>
+</tbody>
+</table></div></div>
+
+<br/><br/>
+<div class='card'><div class='card-block'><a name='qrtz_triggers' onclick='window.scrollTo(60, 195);return false;' style='cursor:pointer;'><h4 class='card-title'>Table qrtz_triggers</h4></a>
+<table class='table-sm table-bordered'>
+<thead>
+<tr><th>Indexes</th><th>Field Name</th><th>Data Type</th><th>Description</th></tr></thead>
+<tbody>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg><svg width='14' height='14'><use xlink:href='#fk'/></svg></td>
+		<td><a name='qrtz_triggers.sched_name'>sched&#95;name</a></td>
+		<td> varchar&#40; 120 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg><svg width='14' height='14'><use xlink:href='#ref'/></svg></td>
+		<td><a name='qrtz_triggers.trigger_name'>trigger&#95;name</a></td>
+		<td> varchar&#40; 200 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg><svg width='14' height='14'><use xlink:href='#ref'/></svg></td>
+		<td><a name='qrtz_triggers.trigger_group'>trigger&#95;group</a></td>
+		<td> varchar&#40; 200 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#idx'/></svg><svg width='14' height='14'><use xlink:href='#fk'/></svg></td>
+		<td><a name='qrtz_triggers.job_name'>job&#95;name</a></td>
+		<td> varchar&#40; 200 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#idx'/></svg><svg width='14' height='14'><use xlink:href='#fk'/></svg></td>
+		<td><a name='qrtz_triggers.job_group'>job&#95;group</a></td>
+		<td> varchar&#40; 200 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='qrtz_triggers.description'>description</a></td>
+		<td> varchar&#40; 250 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='qrtz_triggers.next_fire_time'>next&#95;fire&#95;time</a></td>
+		<td> bigint   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='qrtz_triggers.prev_fire_time'>prev&#95;fire&#95;time</a></td>
+		<td> bigint   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='qrtz_triggers.priority'>priority</a></td>
+		<td> int   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='qrtz_triggers.trigger_state'>trigger&#95;state</a></td>
+		<td> varchar&#40; 16 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='qrtz_triggers.trigger_type'>trigger&#95;type</a></td>
+		<td> varchar&#40; 8 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='qrtz_triggers.start_time'>start&#95;time</a></td>
+		<td> bigint   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='qrtz_triggers.end_time'>end&#95;time</a></td>
+		<td> bigint   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='qrtz_triggers.calendar_name'>calendar&#95;name</a></td>
+		<td> varchar&#40; 200 &#41;   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='qrtz_triggers.misfire_instr'>misfire&#95;instr</a></td>
+		<td> smallint   </td>
+		<td>  </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='qrtz_triggers.job_data'>job&#95;data</a></td>
+		<td> blob   </td>
+		<td>  </td>
+	</tr>
+<tr><th colspan='4'>Indexes</th></tr>
+	<tr>		<td><svg width='14' height='14'><use xlink:href='#pk'/></svg></td><td>pk&#95;qrtz&#95;triggers</td>
+		<td> ON sched&#95;name&#44; trigger&#95;name&#44; trigger&#95;group</td>
+		<td>  </td>
+	</tr>
+	<tr>		<td><svg width='14' height='14'><use xlink:href='#idx'/></svg></td><td>sched&#95;name</td>
+		<td> ON sched&#95;name&#44; job&#95;name&#44; job&#95;group</td>
+		<td>  </td>
+	</tr>
+<tr><th colspan='4'>Foreign Keys</th></tr>
+	<tr>
+		<td><svg width='14' height='14'><use xlink:href='#fk'/></svg></td><td>qrtz_triggers_ibfk_1</td>
+		<td > ( sched&#95;name&#44; job&#95;name&#44; job&#95;group ) ref <a href='#qrtz&#95;job&#95;details'>qrtz&#95;job&#95;details</a> (sched&#95;name&#44; job&#95;name&#44; job&#95;group) </td>
+		<td>  </td>
+	</tr>
+</tbody>
+</table></div></div>
+
+<br/><br/>
+<div class='card'><div class='card-block'><a name='sys_dept' onclick='window.scrollTo(445, 720);return false;' style='cursor:pointer;'><h4 class='card-title'>Table sys_dept</h4></a>
+<table class='table-sm table-bordered'>
+<thead>
+<tr><th>Indexes</th><th>Field Name</th><th>Data Type</th><th>Description</th></tr></thead>
+<tbody>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg></td>
+		<td><a name='sys_dept.dept_id'>dept&#95;id</a></td>
+		<td> int  AUTOINCREMENT  </td>
+		<td> 部门id </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_dept.parent_id'>parent&#95;id</a></td>
+		<td> int   DEFAULT 0 </td>
+		<td> 父部门id </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_dept.dept_name'>dept&#95;name</a></td>
+		<td> varchar&#40; 30 &#41;   DEFAULT '' </td>
+		<td> 部门名称 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_dept.order_num'>order&#95;num</a></td>
+		<td> int   DEFAULT 0 </td>
+		<td> 显示顺序 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_dept.leader'>leader</a></td>
+		<td> varchar&#40; 20 &#41;   DEFAULT '' </td>
+		<td> 负责人 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_dept.phone'>phone</a></td>
+		<td> varchar&#40; 20 &#41;   DEFAULT '' </td>
+		<td> 联系电话 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_dept.email'>email</a></td>
+		<td> varchar&#40; 20 &#41;   DEFAULT '' </td>
+		<td> 邮箱 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_dept.status'>status</a></td>
+		<td> int   DEFAULT 0 </td>
+		<td> 部门状态&#58;0正常&#44;1停用 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_dept.create_by'>create&#95;by</a></td>
+		<td> varchar&#40; 64 &#41;   DEFAULT '' </td>
+		<td> 创建者 </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='sys_dept.create_time'>create&#95;time</a></td>
+		<td> timestamp   DEFAULT CURRENT_TIMESTAMP </td>
+		<td> 创建时间 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_dept.update_by'>update&#95;by</a></td>
+		<td> varchar&#40; 64 &#41;   DEFAULT '' </td>
+		<td> 更新者 </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='sys_dept.update_time'>update&#95;time</a></td>
+		<td> timestamp   DEFAULT '0000-00-00 00:00:00' </td>
+		<td> 更新时间 </td>
+	</tr>
+<tr><th colspan='4'>Indexes</th></tr>
+	<tr>		<td><svg width='14' height='14'><use xlink:href='#pk'/></svg></td><td>pk&#95;sys&#95;dept</td>
+		<td> ON dept&#95;id</td>
+		<td>  </td>
+	</tr>
+</tbody>
+</table></div></div>
+
+<br/><br/>
+<div class='card'><div class='card-block'><a name='sys_dict_data' onclick='window.scrollTo(970, 45);return false;' style='cursor:pointer;'><h4 class='card-title'>Table sys_dict_data</h4></a>
+<table class='table-sm table-bordered'>
+<thead>
+<tr><th>Indexes</th><th>Field Name</th><th>Data Type</th><th>Description</th></tr></thead>
+<tbody>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg></td>
+		<td><a name='sys_dict_data.dict_code'>dict&#95;code</a></td>
+		<td> int  AUTOINCREMENT  </td>
+		<td> 字典编码 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_dict_data.dict_sort'>dict&#95;sort</a></td>
+		<td> int   DEFAULT 0 </td>
+		<td> 字典排序 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_dict_data.dict_label'>dict&#95;label</a></td>
+		<td> varchar&#40; 100 &#41;   DEFAULT '' </td>
+		<td> 字典标签 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_dict_data.dict_value'>dict&#95;value</a></td>
+		<td> varchar&#40; 100 &#41;   DEFAULT '' </td>
+		<td> 字典键值 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_dict_data.dict_type'>dict&#95;type</a></td>
+		<td> varchar&#40; 100 &#41;   DEFAULT '' </td>
+		<td> 字典类型 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_dict_data.status'>status</a></td>
+		<td> int   DEFAULT 0 </td>
+		<td> 状态(0正常 1禁用) </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_dict_data.create_by'>create&#95;by</a></td>
+		<td> varchar&#40; 64 &#41;   DEFAULT '' </td>
+		<td> 创建者 </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='sys_dict_data.create_time'>create&#95;time</a></td>
+		<td> timestamp   DEFAULT CURRENT_TIMESTAMP </td>
+		<td> 创建时间 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_dict_data.update_by'>update&#95;by</a></td>
+		<td> varchar&#40; 64 &#41;   DEFAULT '' </td>
+		<td> 更新者 </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='sys_dict_data.update_time'>update&#95;time</a></td>
+		<td> timestamp   DEFAULT '0000-00-00 00:00:00' </td>
+		<td> 更新时间 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_dict_data.remark'>remark</a></td>
+		<td> varchar&#40; 500 &#41;   DEFAULT '' </td>
+		<td> 备注 </td>
+	</tr>
+<tr><th colspan='4'>Indexes</th></tr>
+	<tr>		<td><svg width='14' height='14'><use xlink:href='#pk'/></svg></td><td>pk&#95;sys&#95;dict&#95;data</td>
+		<td> ON dict&#95;code</td>
+		<td>  </td>
+	</tr>
+</tbody>
+</table></div></div>
+
+<br/><br/>
+<div class='card'><div class='card-block'><a name='sys_dict_type' onclick='window.scrollTo(805, 45);return false;' style='cursor:pointer;'><h4 class='card-title'>Table sys_dict_type</h4></a>
+<table class='table-sm table-bordered'>
+<thead>
+<tr><th>Indexes</th><th>Field Name</th><th>Data Type</th><th>Description</th></tr></thead>
+<tbody>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg></td>
+		<td><a name='sys_dict_type.dict_id'>dict&#95;id</a></td>
+		<td> int  AUTOINCREMENT  </td>
+		<td> 字典主键 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_dict_type.dict_name'>dict&#95;name</a></td>
+		<td> varchar&#40; 100 &#41;   DEFAULT '' </td>
+		<td> 字典名称 </td>
+	</tr>
+	<tr>
+		<td><svg width='14' height='14'><use xlink:href='#unq'/></svg></td>
+		<td><a name='sys_dict_type.dict_type'>dict&#95;type</a></td>
+		<td> varchar&#40; 100 &#41;   DEFAULT '' </td>
+		<td> 字典类型 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_dict_type.status'>status</a></td>
+		<td> int   DEFAULT 0 </td>
+		<td> 状态(0正常 1禁用) </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_dict_type.create_by'>create&#95;by</a></td>
+		<td> varchar&#40; 64 &#41;   DEFAULT '' </td>
+		<td> 创建者 </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='sys_dict_type.create_time'>create&#95;time</a></td>
+		<td> timestamp   DEFAULT CURRENT_TIMESTAMP </td>
+		<td> 创建时间 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_dict_type.update_by'>update&#95;by</a></td>
+		<td> varchar&#40; 64 &#41;   DEFAULT '' </td>
+		<td> 更新者 </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='sys_dict_type.update_time'>update&#95;time</a></td>
+		<td> timestamp   DEFAULT '0000-00-00 00:00:00' </td>
+		<td> 更新时间 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_dict_type.remark'>remark</a></td>
+		<td> varchar&#40; 500 &#41;   DEFAULT '' </td>
+		<td> 备注 </td>
+	</tr>
+<tr><th colspan='4'>Indexes</th></tr>
+	<tr>		<td><svg width='14' height='14'><use xlink:href='#pk'/></svg></td><td>pk&#95;sys&#95;dict&#95;type</td>
+		<td> ON dict&#95;id</td>
+		<td>  </td>
+	</tr>
+	<tr>		<td><svg width='14' height='14'><use xlink:href='#unq'/></svg></td><td>dict&#95;type</td>
+		<td> ON dict&#95;type</td>
+		<td>  </td>
+	</tr>
+</tbody>
+</table></div></div>
+
+<br/><br/>
+<div class='card'><div class='card-block'><a name='sys_job' onclick='window.scrollTo(1345, 45);return false;' style='cursor:pointer;'><h4 class='card-title'>Table sys_job</h4></a>
+<table class='table-sm table-bordered'>
+<thead>
+<tr><th>Indexes</th><th>Field Name</th><th>Data Type</th><th>Description</th></tr></thead>
+<tbody>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg></td>
+		<td><a name='sys_job.job_id'>job&#95;id</a></td>
+		<td> int  AUTOINCREMENT  </td>
+		<td> 任务ID </td>
+	</tr>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg></td>
+		<td><a name='sys_job.job_name'>job&#95;name</a></td>
+		<td> varchar&#40; 64 &#41;   DEFAULT '' </td>
+		<td> 任务名称 </td>
+	</tr>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg></td>
+		<td><a name='sys_job.job_group'>job&#95;group</a></td>
+		<td> varchar&#40; 64 &#41;   DEFAULT '' </td>
+		<td> 任务组名 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_job.method_name'>method&#95;name</a></td>
+		<td> varchar&#40; 500 &#41;   DEFAULT '' </td>
+		<td> 任务方法 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_job.params'>params</a></td>
+		<td> varchar&#40; 200 &#41;   DEFAULT '' </td>
+		<td> 方法参数 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_job.cron_expression'>cron&#95;expression</a></td>
+		<td> varchar&#40; 255 &#41;   DEFAULT '' </td>
+		<td> cron执行表达式 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_job.status'>status</a></td>
+		<td> int   DEFAULT 0 </td>
+		<td> 状态(0正常 1暂停) </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_job.create_by'>create&#95;by</a></td>
+		<td> varchar&#40; 64 &#41;   DEFAULT '' </td>
+		<td> 创建者 </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='sys_job.create_time'>create&#95;time</a></td>
+		<td> timestamp   DEFAULT CURRENT_TIMESTAMP </td>
+		<td> 创建时间 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_job.update_by'>update&#95;by</a></td>
+		<td> varchar&#40; 64 &#41;   DEFAULT '' </td>
+		<td> 更新者 </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='sys_job.update_time'>update&#95;time</a></td>
+		<td> timestamp   DEFAULT '0000-00-00 00:00:00' </td>
+		<td> 更新时间 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_job.remark'>remark</a></td>
+		<td> varchar&#40; 500 &#41;   DEFAULT '' </td>
+		<td> 备注信息 </td>
+	</tr>
+<tr><th colspan='4'>Indexes</th></tr>
+	<tr>		<td><svg width='14' height='14'><use xlink:href='#pk'/></svg></td><td>pk&#95;sys&#95;job</td>
+		<td> ON job&#95;id&#44; job&#95;name&#44; job&#95;group</td>
+		<td>  </td>
+	</tr>
+</tbody>
+</table></div></div>
+
+<br/><br/>
+<div class='card'><div class='card-block'><a name='sys_job_log' onclick='window.scrollTo(1165, 45);return false;' style='cursor:pointer;'><h4 class='card-title'>Table sys_job_log</h4></a>
+<table class='table-sm table-bordered'>
+<thead>
+<tr><th>Indexes</th><th>Field Name</th><th>Data Type</th><th>Description</th></tr></thead>
+<tbody>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg></td>
+		<td><a name='sys_job_log.job_log_id'>job&#95;log&#95;id</a></td>
+		<td> int  AUTOINCREMENT  </td>
+		<td> 任务日志ID </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='sys_job_log.job_name'>job&#95;name</a></td>
+		<td> varchar&#40; 64 &#41;   </td>
+		<td> 任务名称 </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='sys_job_log.job_group'>job&#95;group</a></td>
+		<td> varchar&#40; 64 &#41;   </td>
+		<td> 任务组名 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_job_log.method_name'>method&#95;name</a></td>
+		<td> varchar&#40; 500 &#41;   </td>
+		<td> 任务方法 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_job_log.params'>params</a></td>
+		<td> varchar&#40; 200 &#41;   DEFAULT '' </td>
+		<td> 方法参数 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_job_log.job_message'>job&#95;message</a></td>
+		<td> varchar&#40; 500 &#41;   </td>
+		<td> 日志信息 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_job_log.is_exception'>is&#95;exception</a></td>
+		<td> int   DEFAULT 0 </td>
+		<td> 是否异常 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_job_log.exception_info'>exception&#95;info</a></td>
+		<td> text   </td>
+		<td> 异常信息 </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='sys_job_log.create_time'>create&#95;time</a></td>
+		<td> timestamp   DEFAULT CURRENT_TIMESTAMP </td>
+		<td> 创建时间 </td>
+	</tr>
+<tr><th colspan='4'>Indexes</th></tr>
+	<tr>		<td><svg width='14' height='14'><use xlink:href='#pk'/></svg></td><td>pk&#95;sys&#95;job&#95;log</td>
+		<td> ON job&#95;log&#95;id</td>
+		<td>  </td>
+	</tr>
+</tbody>
+</table></div></div>
+
+<br/><br/>
+<div class='card'><div class='card-block'><a name='sys_logininfor' onclick='window.scrollTo(1540, 330);return false;' style='cursor:pointer;'><h4 class='card-title'>Table sys_logininfor</h4></a>
+<table class='table-sm table-bordered'>
+<thead>
+<tr><th>Indexes</th><th>Field Name</th><th>Data Type</th><th>Description</th></tr></thead>
+<tbody>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg></td>
+		<td><a name='sys_logininfor.info_id'>info&#95;id</a></td>
+		<td> int  AUTOINCREMENT  </td>
+		<td> 访问ID </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_logininfor.login_name'>login&#95;name</a></td>
+		<td> varchar&#40; 50 &#41;   DEFAULT '' </td>
+		<td> 登录账号 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_logininfor.ipaddr'>ipaddr</a></td>
+		<td> varchar&#40; 50 &#41;   DEFAULT '' </td>
+		<td> 登录IP地址 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_logininfor.browser'>browser</a></td>
+		<td> varchar&#40; 50 &#41;   DEFAULT '' </td>
+		<td> 浏览器类型 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_logininfor.os'>os</a></td>
+		<td> varchar&#40; 50 &#41;   DEFAULT '' </td>
+		<td> 操作系统 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_logininfor.status'>status</a></td>
+		<td> int   DEFAULT 0 </td>
+		<td> 登录状态 0成功 1失败 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_logininfor.msg'>msg</a></td>
+		<td> varchar&#40; 255 &#41;   DEFAULT '' </td>
+		<td> 提示消息 </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='sys_logininfor.login_time'>login&#95;time</a></td>
+		<td> timestamp   DEFAULT CURRENT_TIMESTAMP </td>
+		<td> 访问时间 </td>
+	</tr>
+<tr><th colspan='4'>Indexes</th></tr>
+	<tr>		<td><svg width='14' height='14'><use xlink:href='#pk'/></svg></td><td>pk&#95;sys&#95;logininfor</td>
+		<td> ON info&#95;id</td>
+		<td>  </td>
+	</tr>
+</tbody>
+</table></div></div>
+
+<br/><br/>
+<div class='card'><div class='card-block'><a name='sys_menu' onclick='window.scrollTo(1180, 330);return false;' style='cursor:pointer;'><h4 class='card-title'>Table sys_menu</h4></a>
+<table class='table-sm table-bordered'>
+<thead>
+<tr><th>Indexes</th><th>Field Name</th><th>Data Type</th><th>Description</th></tr></thead>
+<tbody>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg></td>
+		<td><a name='sys_menu.menu_id'>menu&#95;id</a></td>
+		<td> int  AUTOINCREMENT  </td>
+		<td> 菜单ID </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='sys_menu.menu_name'>menu&#95;name</a></td>
+		<td> varchar&#40; 50 &#41;   </td>
+		<td> 菜单名称 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_menu.parent_id'>parent&#95;id</a></td>
+		<td> int   DEFAULT 0 </td>
+		<td> 父菜单ID </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_menu.order_num'>order&#95;num</a></td>
+		<td> int   </td>
+		<td> 显示顺序 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_menu.url'>url</a></td>
+		<td> varchar&#40; 200 &#41;   DEFAULT '' </td>
+		<td> 请求地址 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_menu.menu_type'>menu&#95;type</a></td>
+		<td> char&#40; 1 &#41;   DEFAULT '' </td>
+		<td> 类型&#58;M目录&#44;C菜单&#44;F按钮 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_menu.visible'>visible</a></td>
+		<td> int   DEFAULT 0 </td>
+		<td> 菜单状态&#58;0显示&#44;1隐藏 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_menu.perms'>perms</a></td>
+		<td> varchar&#40; 100 &#41;   DEFAULT '' </td>
+		<td> 权限标识 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_menu.icon'>icon</a></td>
+		<td> varchar&#40; 100 &#41;   DEFAULT '' </td>
+		<td> 菜单图标 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_menu.create_by'>create&#95;by</a></td>
+		<td> varchar&#40; 64 &#41;   DEFAULT '' </td>
+		<td> 创建者 </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='sys_menu.create_time'>create&#95;time</a></td>
+		<td> timestamp   DEFAULT CURRENT_TIMESTAMP </td>
+		<td> 创建时间 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_menu.update_by'>update&#95;by</a></td>
+		<td> varchar&#40; 64 &#41;   DEFAULT '' </td>
+		<td> 更新者 </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='sys_menu.update_time'>update&#95;time</a></td>
+		<td> timestamp   DEFAULT '0000-00-00 00:00:00' </td>
+		<td> 更新时间 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_menu.remark'>remark</a></td>
+		<td> varchar&#40; 500 &#41;   DEFAULT '' </td>
+		<td> 备注 </td>
+	</tr>
+<tr><th colspan='4'>Indexes</th></tr>
+	<tr>		<td><svg width='14' height='14'><use xlink:href='#pk'/></svg></td><td>pk&#95;sys&#95;menu</td>
+		<td> ON menu&#95;id</td>
+		<td>  </td>
+	</tr>
+</tbody>
+</table></div></div>
+
+<br/><br/>
+<div class='card'><div class='card-block'><a name='sys_oper_log' onclick='window.scrollTo(805, 285);return false;' style='cursor:pointer;'><h4 class='card-title'>Table sys_oper_log</h4></a>
+<table class='table-sm table-bordered'>
+<thead>
+<tr><th>Indexes</th><th>Field Name</th><th>Data Type</th><th>Description</th></tr></thead>
+<tbody>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg></td>
+		<td><a name='sys_oper_log.oper_id'>oper&#95;id</a></td>
+		<td> int  AUTOINCREMENT  </td>
+		<td> 日志主键 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_oper_log.title'>title</a></td>
+		<td> varchar&#40; 50 &#41;   DEFAULT '' </td>
+		<td> 模块标题 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_oper_log.action'>action</a></td>
+		<td> varchar&#40; 100 &#41;   DEFAULT '' </td>
+		<td> 功能请求 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_oper_log.method'>method</a></td>
+		<td> varchar&#40; 100 &#41;   DEFAULT '' </td>
+		<td> 方法名称 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_oper_log.channel'>channel</a></td>
+		<td> varchar&#40; 20 &#41;   DEFAULT '' </td>
+		<td> 来源渠道 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_oper_log.login_name'>login&#95;name</a></td>
+		<td> varchar&#40; 50 &#41;   DEFAULT '' </td>
+		<td> 登录账号 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_oper_log.dept_name'>dept&#95;name</a></td>
+		<td> varchar&#40; 50 &#41;   DEFAULT '' </td>
+		<td> 部门名称 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_oper_log.oper_url'>oper&#95;url</a></td>
+		<td> varchar&#40; 255 &#41;   DEFAULT '' </td>
+		<td> 请求URL </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_oper_log.oper_ip'>oper&#95;ip</a></td>
+		<td> varchar&#40; 30 &#41;   DEFAULT '' </td>
+		<td> 主机地址 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_oper_log.oper_param'>oper&#95;param</a></td>
+		<td> varchar&#40; 255 &#41;   DEFAULT '' </td>
+		<td> 请求参数 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_oper_log.status'>status</a></td>
+		<td> int   DEFAULT 0 </td>
+		<td> 操作状态 0正常 1异常 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_oper_log.error_msg'>error&#95;msg</a></td>
+		<td> varchar&#40; 2000 &#41;   DEFAULT '' </td>
+		<td> 错误消息 </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='sys_oper_log.oper_time'>oper&#95;time</a></td>
+		<td> timestamp   DEFAULT CURRENT_TIMESTAMP </td>
+		<td> 操作时间 </td>
+	</tr>
+<tr><th colspan='4'>Indexes</th></tr>
+	<tr>		<td><svg width='14' height='14'><use xlink:href='#pk'/></svg></td><td>pk&#95;sys&#95;oper&#95;log</td>
+		<td> ON oper&#95;id</td>
+		<td>  </td>
+	</tr>
+</tbody>
+</table></div></div>
+
+<br/><br/>
+<div class='card'><div class='card-block'><a name='sys_post' onclick='window.scrollTo(1540, 45);return false;' style='cursor:pointer;'><h4 class='card-title'>Table sys_post</h4></a>
+<table class='table-sm table-bordered'>
+<thead>
+<tr><th>Indexes</th><th>Field Name</th><th>Data Type</th><th>Description</th></tr></thead>
+<tbody>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg></td>
+		<td><a name='sys_post.post_id'>post&#95;id</a></td>
+		<td> int  AUTOINCREMENT  </td>
+		<td> 岗位ID </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='sys_post.post_code'>post&#95;code</a></td>
+		<td> varchar&#40; 64 &#41;   </td>
+		<td> 岗位编码 </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='sys_post.post_name'>post&#95;name</a></td>
+		<td> varchar&#40; 100 &#41;   </td>
+		<td> 岗位名称 </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='sys_post.post_sort'>post&#95;sort</a></td>
+		<td> int   </td>
+		<td> 显示顺序 </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='sys_post.status'>status</a></td>
+		<td> int   </td>
+		<td> 状态(0正常 1停用) </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_post.create_by'>create&#95;by</a></td>
+		<td> varchar&#40; 64 &#41;   DEFAULT '' </td>
+		<td> 创建者 </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='sys_post.create_time'>create&#95;time</a></td>
+		<td> timestamp   DEFAULT CURRENT_TIMESTAMP </td>
+		<td> 创建时间 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_post.update_by'>update&#95;by</a></td>
+		<td> varchar&#40; 64 &#41;   DEFAULT '' </td>
+		<td> 更新者 </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='sys_post.update_time'>update&#95;time</a></td>
+		<td> timestamp   DEFAULT '0000-00-00 00:00:00' </td>
+		<td> 更新时间 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_post.remark'>remark</a></td>
+		<td> varchar&#40; 500 &#41;   DEFAULT '' </td>
+		<td> 备注 </td>
+	</tr>
+<tr><th colspan='4'>Indexes</th></tr>
+	<tr>		<td><svg width='14' height='14'><use xlink:href='#pk'/></svg></td><td>pk&#95;sys&#95;post</td>
+		<td> ON post&#95;id</td>
+		<td>  </td>
+	</tr>
+</tbody>
+</table></div></div>
+
+<br/><br/>
+<div class='card'><div class='card-block'><a name='sys_role' onclick='window.scrollTo(1345, 465);return false;' style='cursor:pointer;'><h4 class='card-title'>Table sys_role</h4></a>
+<table class='table-sm table-bordered'>
+<thead>
+<tr><th>Indexes</th><th>Field Name</th><th>Data Type</th><th>Description</th></tr></thead>
+<tbody>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg></td>
+		<td><a name='sys_role.role_id'>role&#95;id</a></td>
+		<td> int  AUTOINCREMENT  </td>
+		<td> 角色ID </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='sys_role.role_name'>role&#95;name</a></td>
+		<td> varchar&#40; 30 &#41;   </td>
+		<td> 角色名称 </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='sys_role.role_key'>role&#95;key</a></td>
+		<td> varchar&#40; 100 &#41;   </td>
+		<td> 角色权限字符串 </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='sys_role.role_sort'>role&#95;sort</a></td>
+		<td> int   </td>
+		<td> 显示顺序 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_role.status'>status</a></td>
+		<td> int   DEFAULT 0 </td>
+		<td> 角色状态&#58;0正常&#44;1禁用 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_role.create_by'>create&#95;by</a></td>
+		<td> varchar&#40; 64 &#41;   DEFAULT '' </td>
+		<td> 创建者 </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='sys_role.create_time'>create&#95;time</a></td>
+		<td> timestamp   DEFAULT CURRENT_TIMESTAMP </td>
+		<td> 创建时间 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_role.update_by'>update&#95;by</a></td>
+		<td> varchar&#40; 64 &#41;   DEFAULT '' </td>
+		<td> 更新者 </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='sys_role.update_time'>update&#95;time</a></td>
+		<td> timestamp   DEFAULT '0000-00-00 00:00:00' </td>
+		<td> 更新时间 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_role.remark'>remark</a></td>
+		<td> varchar&#40; 500 &#41;   DEFAULT '' </td>
+		<td> 备注 </td>
+	</tr>
+<tr><th colspan='4'>Indexes</th></tr>
+	<tr>		<td><svg width='14' height='14'><use xlink:href='#pk'/></svg></td><td>pk&#95;sys&#95;role</td>
+		<td> ON role&#95;id</td>
+		<td>  </td>
+	</tr>
+</tbody>
+</table></div></div>
+
+<br/><br/>
+<div class='card'><div class='card-block'><a name='sys_role_menu' onclick='window.scrollTo(1345, 330);return false;' style='cursor:pointer;'><h4 class='card-title'>Table sys_role_menu</h4></a>
+<table class='table-sm table-bordered'>
+<thead>
+<tr><th>Indexes</th><th>Field Name</th><th>Data Type</th><th>Description</th></tr></thead>
+<tbody>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg></td>
+		<td><a name='sys_role_menu.role_id'>role&#95;id</a></td>
+		<td> int   </td>
+		<td> 角色ID </td>
+	</tr>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg></td>
+		<td><a name='sys_role_menu.menu_id'>menu&#95;id</a></td>
+		<td> int   </td>
+		<td> 菜单ID </td>
+	</tr>
+<tr><th colspan='4'>Indexes</th></tr>
+	<tr>		<td><svg width='14' height='14'><use xlink:href='#pk'/></svg></td><td>pk&#95;sys&#95;role&#95;menu</td>
+		<td> ON role&#95;id&#44; menu&#95;id</td>
+		<td>  </td>
+	</tr>
+</tbody>
+</table></div></div>
+
+<br/><br/>
+<div class='card'><div class='card-block'><a name='sys_user' onclick='window.scrollTo(490, 90);return false;' style='cursor:pointer;'><h4 class='card-title'>Table sys_user</h4></a>
+<table class='table-sm table-bordered'>
+<thead>
+<tr><th>Indexes</th><th>Field Name</th><th>Data Type</th><th>Description</th></tr></thead>
+<tbody>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg></td>
+		<td><a name='sys_user.user_id'>user&#95;id</a></td>
+		<td> int  AUTOINCREMENT  </td>
+		<td> 用户ID </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_user.dept_id'>dept&#95;id</a></td>
+		<td> int   </td>
+		<td> 部门ID </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_user.login_name'>login&#95;name</a></td>
+		<td> varchar&#40; 30 &#41;   DEFAULT '' </td>
+		<td> 登录账号 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_user.user_name'>user&#95;name</a></td>
+		<td> varchar&#40; 30 &#41;   DEFAULT '' </td>
+		<td> 用户昵称 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_user.email'>email</a></td>
+		<td> varchar&#40; 100 &#41;   DEFAULT '' </td>
+		<td> 用户邮箱 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_user.phonenumber'>phonenumber</a></td>
+		<td> varchar&#40; 20 &#41;   DEFAULT '' </td>
+		<td> 手机号码 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_user.password'>password</a></td>
+		<td> varchar&#40; 100 &#41;   DEFAULT '' </td>
+		<td> 密码 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_user.salt'>salt</a></td>
+		<td> varchar&#40; 100 &#41;   DEFAULT '' </td>
+		<td> 盐加密 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_user.user_type'>user&#95;type</a></td>
+		<td> char&#40; 1 &#41;   DEFAULT 'N' </td>
+		<td> 类型&#58;Y默认用户&#44;N非默认用户 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_user.status'>status</a></td>
+		<td> int   DEFAULT 0 </td>
+		<td> 帐号状态&#58;0正常&#44;1禁用 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_user.refuse_des'>refuse&#95;des</a></td>
+		<td> varchar&#40; 500 &#41;   DEFAULT '' </td>
+		<td> 拒绝登录描述 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_user.create_by'>create&#95;by</a></td>
+		<td> varchar&#40; 64 &#41;   DEFAULT '' </td>
+		<td> 创建者 </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='sys_user.create_time'>create&#95;time</a></td>
+		<td> timestamp   DEFAULT CURRENT_TIMESTAMP </td>
+		<td> 创建时间 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_user.update_by'>update&#95;by</a></td>
+		<td> varchar&#40; 64 &#41;   DEFAULT '' </td>
+		<td> 更新者 </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='sys_user.update_time'>update&#95;time</a></td>
+		<td> timestamp   DEFAULT '0000-00-00 00:00:00' </td>
+		<td> 更新时间 </td>
+	</tr>
+<tr><th colspan='4'>Indexes</th></tr>
+	<tr>		<td><svg width='14' height='14'><use xlink:href='#pk'/></svg></td><td>pk&#95;sys&#95;user</td>
+		<td> ON user&#95;id</td>
+		<td>  </td>
+	</tr>
+</tbody>
+</table></div></div>
+
+<br/><br/>
+<div class='card'><div class='card-block'><a name='sys_user_online' onclick='window.scrollTo(460, 420);return false;' style='cursor:pointer;'><h4 class='card-title'>Table sys_user_online</h4></a>
+<table class='table-sm table-bordered'>
+<thead>
+<tr><th>Indexes</th><th>Field Name</th><th>Data Type</th><th>Description</th></tr></thead>
+<tbody>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg></td>
+		<td><a name='sys_user_online.sessionId'>sessionId</a></td>
+		<td> varchar&#40; 50 &#41;   DEFAULT '' </td>
+		<td> 用户会话id </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_user_online.login_name'>login&#95;name</a></td>
+		<td> varchar&#40; 50 &#41;   DEFAULT '' </td>
+		<td> 登录账号 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_user_online.dept_name'>dept&#95;name</a></td>
+		<td> varchar&#40; 50 &#41;   DEFAULT '' </td>
+		<td> 部门名称 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_user_online.ipaddr'>ipaddr</a></td>
+		<td> varchar&#40; 50 &#41;   DEFAULT '' </td>
+		<td> 登录IP地址 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_user_online.browser'>browser</a></td>
+		<td> varchar&#40; 50 &#41;   DEFAULT '' </td>
+		<td> 浏览器类型 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_user_online.os'>os</a></td>
+		<td> varchar&#40; 50 &#41;   DEFAULT '' </td>
+		<td> 操作系统 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_user_online.status'>status</a></td>
+		<td> varchar&#40; 10 &#41;   DEFAULT '' </td>
+		<td> 在线状态on&#95;line在线off&#95;line离线 </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='sys_user_online.start_timestamp'>start&#95;timestsamp</a></td>
+		<td> timestamp   DEFAULT CURRENT_TIMESTAMP </td>
+		<td> session创建时间 </td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><a name='sys_user_online.last_access_time'>last&#95;access&#95;time</a></td>
+		<td> timestamp   DEFAULT '0000-00-00 00:00:00' </td>
+		<td> session最后访问时间 </td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><a name='sys_user_online.expire_time'>expire&#95;time</a></td>
+		<td> int   DEFAULT 0 </td>
+		<td> 超时时间,单位为分钟 </td>
+	</tr>
+<tr><th colspan='4'>Indexes</th></tr>
+	<tr>		<td><svg width='14' height='14'><use xlink:href='#pk'/></svg></td><td>pk&#95;sys&#95;user&#95;online</td>
+		<td> ON sessionId</td>
+		<td>  </td>
+	</tr>
+</tbody>
+</table></div></div>
+
+<br/><br/>
+<div class='card'><div class='card-block'><a name='sys_user_post' onclick='window.scrollTo(655, 420);return false;' style='cursor:pointer;'><h4 class='card-title'>Table sys_user_post</h4></a>
+<table class='table-sm table-bordered'>
+<thead>
+<tr><th>Indexes</th><th>Field Name</th><th>Data Type</th><th>Description</th></tr></thead>
+<tbody>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg></td>
+		<td><a name='sys_user_post.user_id'>user&#95;id</a></td>
+		<td> varchar&#40; 64 &#41;   </td>
+		<td> 用户ID </td>
+	</tr>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg></td>
+		<td><a name='sys_user_post.post_id'>post&#95;id</a></td>
+		<td> varchar&#40; 64 &#41;   </td>
+		<td> 岗位ID </td>
+	</tr>
+<tr><th colspan='4'>Indexes</th></tr>
+	<tr>		<td><svg width='14' height='14'><use xlink:href='#pk'/></svg></td><td>pk&#95;sys&#95;user&#95;post</td>
+		<td> ON user&#95;id&#44; post&#95;id</td>
+		<td>  </td>
+	</tr>
+</tbody>
+</table></div></div>
+
+<br/><br/>
+<div class='card'><div class='card-block'><a name='sys_user_role' onclick='window.scrollTo(655, 285);return false;' style='cursor:pointer;'><h4 class='card-title'>Table sys_user_role</h4></a>
+<table class='table-sm table-bordered'>
+<thead>
+<tr><th>Indexes</th><th>Field Name</th><th>Data Type</th><th>Description</th></tr></thead>
+<tbody>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg></td>
+		<td><a name='sys_user_role.user_id'>user&#95;id</a></td>
+		<td> int   </td>
+		<td> 用户ID </td>
+	</tr>
+	<tr>
+		<td>*<svg width='14' height='14'><use xlink:href='#pk'/></svg></td>
+		<td><a name='sys_user_role.role_id'>role&#95;id</a></td>
+		<td> int   </td>
+		<td> 角色ID </td>
+	</tr>
+<tr><th colspan='4'>Indexes</th></tr>
+	<tr>		<td><svg width='14' height='14'><use xlink:href='#pk'/></svg></td><td>pk&#95;sys&#95;user&#95;role</td>
+		<td> ON user&#95;id&#44; role&#95;id</td>
+		<td>  </td>
+	</tr>
+</tbody>
+</table></div></div>
+
+<p align='right'><a href='https://www.dbschema.com' style='color:#aaa'>Powered by DbSchema</a></p></body></html>
\ No newline at end of file
diff --git a/sql/ruoyi.pdm b/sql/ruoyi.pdm
new file mode 100644
index 0000000..78d8504
--- /dev/null
+++ b/sql/ruoyi.pdm
@@ -0,0 +1,4851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?PowerDesigner AppLocale="UTF16" ID="{21C20947-ED50-4632-B638-DC1A02BD948A}" Label="" LastModificationDate="1538297772" Name="ruoyi" Objects="216" Symbols="20" Target="MySQL 5.0" Type="{CDE44E21-9669-11D1-9914-006097355D9B}" signature="PDM_DATA_MODEL_XML" version="15.1.0.2850"?>
+<!-- do not edit this file -->
+
+<Model xmlns:a="attribute" xmlns:c="collection" xmlns:o="object">
+
+<o:RootObject Id="o1">
+<c:Children>
+<o:Model Id="o2">
+<a:ObjectID>21C20947-ED50-4632-B638-DC1A02BD948A</a:ObjectID>
+<a:Name>ruoyi</a:Name>
+<a:Code>ruoyi</a:Code>
+<a:CreationDate>1524449337</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1538297587</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:PackageOptionsText>[FolderOptions]
+
+[FolderOptions\Physical Objects]
+GenerationCheckModel=Yes
+GenerationPath=
+GenerationOptions=
+GenerationTasks=
+GenerationTargets=
+GenerationSelections=
+RevPkey=Yes
+RevFkey=Yes
+RevAkey=Yes
+RevCheck=Yes
+RevIndx=Yes
+RevOpts=Yes
+RevViewAsTabl=No
+RevViewOpts=Yes
+RevSystAsTabl=Yes
+RevTablPerm=No
+RevViewPerm=No
+RevProcPerm=No
+RevDbpkPerm=No
+RevSqncPerm=No
+RevAdtPerm=No
+RevUserPriv=No
+RevUserOpts=No
+RevGrpePriv=No
+RevRolePriv=No
+RevDtbsOpts=Yes
+RevDtbsPerm=No
+RevViewIndx=Yes
+RevJidxOpts=Yes
+RevStats=No
+RevTspcPerm=No
+RevCaseSensitive=No
+GenTrgrStdMsg=Yes
+GenTrgrMsgTab=
+GenTrgrMsgNo=
+GenTrgrMsgTxt=
+TrgrPreserve=No
+TrgrIns=Yes
+TrgrUpd=Yes
+TrgrDel=Yes
+TrgrC2Ins=Yes
+TrgrC2Upd=Yes
+TrgrC3=Yes
+TrgrC4=Yes
+TrgrC5=Yes
+TrgrC6=Yes
+TrgrC7=Yes
+TrgrC8=Yes
+TrgrC9=Yes
+TrgrC10=Yes
+TrgrC11=Yes
+TrgrC1=Yes
+TrgrC12Ins=Yes
+TrgrC12Upd=Yes
+TrgrC13=Yes
+UpdateTableStatistics=Yes
+UpdateColumnStatistics=Yes
+
+[FolderOptions\Physical Objects\Database Generation]
+GenScriptName=orders.sql
+GenScriptName0=orders.sql
+GenScriptName1=studentsystem.sql
+GenScriptName2=NetCTOSS.sql
+GenScriptName3=product.sql
+GenScriptName4=voteSystem.sql
+GenScriptName5=.sql
+GenScriptName6=enterpriseManagement.sql
+GenScriptName7=crebas.sql
+GenScriptName8=
+GenScriptName9=
+GenPathName=C:\Users\Administrator\Desktop\
+GenSingleFile=Yes
+GenODBC=No
+GenCheckModel=Yes
+GenScriptPrev=Yes
+GenArchiveModel=No
+GenUseSync=No
+GenSyncChoice=0
+GenSyncArch=
+GenSyncRmg=0
+
+[FolderOptions\Physical Objects\Database Generation\Format]
+GenScriptTitle=Yes
+GenScriptNamLabl=No
+GenScriptQDtbs=No
+GenScriptQOwnr=Yes
+GenScriptCase=0
+GenScriptEncoding=ANSI
+GenScriptNAcct=No
+IdentifierDelimiter=&quot;
+
+[FolderOptions\Physical Objects\Database Generation\Database]
+Create=Yes
+Open=Yes
+Close=Yes
+Drop=Yes
+Permission=No
+
+[FolderOptions\Physical Objects\Database Generation\Database\Create]
+Physical Options=Yes
+Header=Yes
+Footer=Yes
+
+[FolderOptions\Physical Objects\Database Generation\Tablespace]
+Create=Yes
+Drop=Yes
+Comment=Yes
+Permission=No
+
+[FolderOptions\Physical Objects\Database Generation\Tablespace\Create]
+Header=Yes
+Footer=Yes
+
+[FolderOptions\Physical Objects\Database Generation\Storage]
+Create=Yes
+Drop=Yes
+Comment=Yes
+
+[FolderOptions\Physical Objects\Database Generation\User]
+Create=Yes
+Grant=Yes
+Drop=Yes
+Comment=Yes
+Privilege=No
+
+[FolderOptions\Physical Objects\Database Generation\User\Create]
+Physical Options=No
+
+[FolderOptions\Physical Objects\Database Generation\Group]
+Create=Yes
+Drop=Yes
+Comment=Yes
+Privilege=No
+
+[FolderOptions\Physical Objects\Database Generation\Role]
+Create=Yes
+Drop=Yes
+Privilege=No
+
+[FolderOptions\Physical Objects\Database Generation\UserDefinedDataType]
+Create=Yes
+Comment=Yes
+Drop=Yes
+
+[FolderOptions\Physical Objects\Database Generation\UserDefinedDataType\Create]
+Default value=Yes
+Check=Yes
+
+[FolderOptions\Physical Objects\Database Generation\AbstractDataType]
+Create=Yes
+Header=Yes
+Footer=Yes
+Drop=Yes
+Comment=Yes
+Install JAVA class=Yes
+Remove JAVA class=Yes
+Permission=No
+
+[FolderOptions\Physical Objects\Database Generation\Rule]
+Create=Yes
+Drop=Yes
+Comment=Yes
+
+[FolderOptions\Physical Objects\Database Generation\Default]
+Create=Yes
+Comment=Yes
+Drop=Yes
+
+[FolderOptions\Physical Objects\Database Generation\Sequence]
+Create=Yes
+Drop=Yes
+Comment=Yes
+Permission=No
+
+[FolderOptions\Physical Objects\Database Generation\Table&amp;&amp;Column]
+
+[FolderOptions\Physical Objects\Database Generation\Table&amp;&amp;Column\Table]
+Create=Yes
+Drop=Yes
+Comment=Yes
+Permission=No
+
+[FolderOptions\Physical Objects\Database Generation\Table&amp;&amp;Column\Table\Create]
+Check=Yes
+Physical Options=Yes
+Header=Yes
+Footer=Yes
+
+[FolderOptions\Physical Objects\Database Generation\Table&amp;&amp;Column\Table\Create\Check]
+Constraint declaration=No
+
+[FolderOptions\Physical Objects\Database Generation\Table&amp;&amp;Column\Column]
+User datatype=No
+Default value=Yes
+Check=Yes
+Physical Options=Yes
+Comment=Yes
+
+[FolderOptions\Physical Objects\Database Generation\Table&amp;&amp;Column\Column\Check]
+Constraint declaration=No
+
+[FolderOptions\Physical Objects\Database Generation\Table&amp;&amp;Column\Key]
+
+[FolderOptions\Physical Objects\Database Generation\Table&amp;&amp;Column\Key\Primary key]
+Create=Yes
+Drop=Yes
+Comment=Yes
+
+[FolderOptions\Physical Objects\Database Generation\Table&amp;&amp;Column\Key\Primary key\Create]
+Constraint declaration=No
+Physical Options=Yes
+
+[FolderOptions\Physical Objects\Database Generation\Table&amp;&amp;Column\Key\Alternate key]
+Create=Yes
+Drop=Yes
+Comment=Yes
+
+[FolderOptions\Physical Objects\Database Generation\Table&amp;&amp;Column\Key\Alternate key\Create]
+Constraint declaration=No
+Physical Options=Yes
+
+[FolderOptions\Physical Objects\Database Generation\Table&amp;&amp;Column\Foreign key]
+Create=Yes
+Drop=Yes
+Comment=Yes
+
+[FolderOptions\Physical Objects\Database Generation\Table&amp;&amp;Column\Foreign key\Create]
+Constraint declaration=Yes
+
+[FolderOptions\Physical Objects\Database Generation\Table&amp;&amp;Column\Index]
+Create=Yes
+Drop=Yes
+Comment=Yes
+
+[FolderOptions\Physical Objects\Database Generation\Table&amp;&amp;Column\Index\Create]
+Constraint declaration=Yes
+Physical Options=Yes
+
+[FolderOptions\Physical Objects\Database Generation\Table&amp;&amp;Column\Index\Filter]
+Primary key=No
+Foreign key=No
+Alternate key=No
+Cluster=Yes
+Other=Yes
+
+[FolderOptions\Physical Objects\Database Generation\Table&amp;&amp;Column\Trigger]
+Create=Yes
+Drop=Yes
+Comment=Yes
+
+[FolderOptions\Physical Objects\Database Generation\Table&amp;&amp;Column\Trigger\Filter]
+For insert=Yes
+For update=Yes
+For delete=Yes
+For other=Yes
+
+[FolderOptions\Physical Objects\Database Generation\View]
+Create=Yes
+Drop=Yes
+Comment=Yes
+Permission=No
+
+[FolderOptions\Physical Objects\Database Generation\View\Create]
+Force Column list=No
+Physical Options=Yes
+Header=Yes
+Footer=Yes
+
+[FolderOptions\Physical Objects\Database Generation\View\ViewColumn]
+Comment=Yes
+
+[FolderOptions\Physical Objects\Database Generation\View\ViewIndex]
+Create=Yes
+Drop=Yes
+Comment=Yes
+
+[FolderOptions\Physical Objects\Database Generation\View\ViewIndex\Create]
+Physical Options=Yes
+
+[FolderOptions\Physical Objects\Database Generation\View\ViewIndex\Filter]
+Cluster=Yes
+Other=Yes
+
+[FolderOptions\Physical Objects\Database Generation\View\Trigger]
+Create=Yes
+Drop=Yes
+Comment=Yes
+
+[FolderOptions\Physical Objects\Database Generation\View\Trigger\Filter]
+For insert=Yes
+For update=Yes
+For delete=Yes
+For other=Yes
+
+[FolderOptions\Physical Objects\Database Generation\DBMSTrigger]
+Create=Yes
+Drop=Yes
+Comment=Yes
+
+[FolderOptions\Physical Objects\Database Generation\Synonym]
+Create=Yes
+Drop=Yes
+
+[FolderOptions\Physical Objects\Database Generation\Synonym\Filter]
+Table=Yes
+View=Yes
+Proc=Yes
+Synonym=Yes
+Database Package=Yes
+Sequence=Yes
+
+[FolderOptions\Physical Objects\Database Generation\JoinIndex]
+Create=Yes
+Drop=Yes
+Comment=Yes
+
+[FolderOptions\Physical Objects\Database Generation\JoinIndex\Create]
+Physical Options=Yes
+Header=Yes
+Footer=Yes
+
+[FolderOptions\Physical Objects\Database Generation\Procedure]
+Create=Yes
+Drop=Yes
+Comment=Yes
+Permission=No
+
+[FolderOptions\Physical Objects\Database Generation\Procedure\Create]
+Header=Yes
+Footer=Yes
+
+[FolderOptions\Physical Objects\Database Generation\DatabasePackage]
+Create=Yes
+Drop=Yes
+Permission=No
+
+[FolderOptions\Physical Objects\Database Generation\WebService]
+Create=Yes
+Drop=Yes
+Comment=Yes
+
+[FolderOptions\Physical Objects\Database Generation\Dimension]
+Create=Yes
+Drop=Yes
+
+[FolderOptions\Physical Objects\Database Generation\Synchronization]
+GenBackupTabl=1
+GenKeepBackTabl=1
+GenTmpTablDrop=No
+GenKeepTablOpts=No
+
+[FolderOptions\Physical Objects\Test Data]
+GenDataPathName=
+GenDataSinglefile=Yes
+GenDataScriptName=testdata
+GenDataScriptName0=
+GenDataScriptName1=
+GenDataScriptName2=
+GenDataScriptName3=
+GenDataScriptName4=
+GenDataScriptName5=
+GenDataScriptName6=
+GenDataScriptName7=
+GenDataScriptName8=
+GenDataScriptName9=
+GenDataOdbc=0
+GenDataDelOld=No
+GenDataTitle=No
+GenDataDefNumRows=20
+GenDataCommit=0
+GenDataPacket=0
+GenDataOwner=No
+GenDataProfNumb=
+GenDataProfChar=
+GenDataProfDate=
+GenDataCSVSeparator=,
+GenDataFileFormat=CSV
+GenDataUseWizard=No
+
+[FolderOptions\Pdm]
+IndxIQName=%COLUMN%_%INDEXTYPE%
+IndxPK=Yes
+IndxFK=Yes
+IndxAK=Yes
+IndxPKName=%TABLE%_PK
+IndxFKName=%REFR%_FK
+IndxAKName=%AKEY%_AK
+IndxPreserve=No
+IndxThreshold=0
+IndxStats=No
+RefrPreserve=No
+JidxPreserve=No
+RbldMultiFact=Yes
+RbldMultiDim=Yes
+RbldMultiJidx=Yes
+CubePreserve=No
+TablStProcPreserve=No
+ProcDepPreserve=Yes
+TrgrDepPreserve=Yes
+CubeScriptPath=
+CubeScriptCase=0
+CubeScriptEncoding=ANSI
+CubeScriptNacct=No
+CubeScriptHeader=No
+CubeScriptExt=csv
+CubeScriptExt0=txt
+CubeScriptExt1=
+CubeScriptExt2=
+CubeScriptSep=,
+CubeScriptDeli=&quot;
+DfltDomnName=D_%.U:VALUE%
+DfltColnName=D_%.U:VALUE%
+DfltReuse=Yes
+DfltDrop=Yes</a:PackageOptionsText>
+<a:ModelOptionsText>[ModelOptions]
+
+[ModelOptions\Physical Objects]
+CaseSensitive=No
+DisplayName=Yes
+EnableTrans=No
+EnableRequirements=No
+DefaultDttp=
+IgnoreOwner=No
+RebuildTrigger=Yes
+RefrUnique=No
+RefrAutoMigrate=Yes
+RefrMigrateReuse=Yes
+RefrMigrateDomain=Yes
+RefrMigrateCheck=Yes
+RefrMigrateRule=Yes
+RefrMigrateExtd=No
+RefrMigrDefaultLink=No
+RefrDfltImpl=D
+RefrPrgtColn=No
+RefrMigrateToEnd=No
+RebuildTriggerDep=No
+ColnFKName=%.3:PARENT%_%COLUMN%
+ColnFKNameUse=No
+DomnCopyDttp=Yes
+DomnCopyChck=No
+DomnCopyRule=No
+DomnCopyMand=No
+DomnCopyExtd=No
+DomnCopyProf=No
+Notation=0
+DomnDefaultMandatory=No
+ColnDefaultMandatory=No
+TablDefaultOwner=
+ViewDefaultOwner=
+TrgrDefaultOwnerTabl=
+TrgrDefaultOwnerView=
+IdxDefaultOwnerTabl=
+IdxDefaultOwnerView=
+JdxDefaultOwner=
+DBPackDefaultOwner=
+SeqDefaultOwner=
+ProcDefaultOwner=
+DBMSTrgrDefaultOwner=
+Currency=USD
+RefrDeleteConstraint=1
+RefrUpdateConstraint=1
+RefrParentMandatory=No
+RefrParentChangeAllow=Yes
+RefrCheckOnCommit=No
+
+[ModelOptions\Physical Objects\NamingOptionsTemplates]
+
+[ModelOptions\Physical Objects\ClssNamingOptions]
+
+[ModelOptions\Physical Objects\ClssNamingOptions\PDMPCKG]
+
+[ModelOptions\Physical Objects\ClssNamingOptions\PDMPCKG\Name]
+Template=
+MaxLen=254
+Case=M
+ValidChar=
+InvldChar=
+AllValid=Yes
+NoAccent=No
+DefaultChar=
+Script=
+ConvTable=
+ConvTablePath=%_HOME%\Resource Files\Conversion Tables
+
+[ModelOptions\Physical Objects\ClssNamingOptions\PDMPCKG\Code]
+Template=
+MaxLen=254
+Case=M
+ValidChar=
+InvldChar=
+AllValid=Yes
+NoAccent=No
+DefaultChar=
+Script=
+ConvTable=
+ConvTablePath=%_HOME%\Resource Files\Conversion Tables
+
+[ModelOptions\Physical Objects\ClssNamingOptions\PDMDOMN]
+
+[ModelOptions\Physical Objects\ClssNamingOptions\PDMDOMN\Name]
+Template=
+MaxLen=254
+Case=M
+ValidChar=
+InvldChar=
+AllValid=Yes
+NoAccent=No
+DefaultChar=
+Script=
+ConvTable=
+ConvTablePath=%_HOME%\Resource Files\Conversion Tables
+
+[ModelOptions\Physical Objects\ClssNamingOptions\PDMDOMN\Code]
+Template=
+MaxLen=254
+Case=M
+ValidChar=
+InvldChar=
+AllValid=Yes
+NoAccent=No
+DefaultChar=
+Script=
+ConvTable=
+ConvTablePath=%_HOME%\Resource Files\Conversion Tables
+
+[ModelOptions\Physical Objects\ClssNamingOptions\TABL]
+
+[ModelOptions\Physical Objects\ClssNamingOptions\TABL\Name]
+Template=
+MaxLen=254
+Case=M
+ValidChar=
+InvldChar=
+AllValid=Yes
+NoAccent=No
+DefaultChar=
+Script=
+ConvTable=
+ConvTablePath=%_HOME%\Resource Files\Conversion Tables
+
+[ModelOptions\Physical Objects\ClssNamingOptions\TABL\Code]
+Template=
+MaxLen=64
+Case=M
+ValidChar=
+InvldChar=
+AllValid=Yes
+NoAccent=No
+DefaultChar=
+Script=
+ConvTable=
+ConvTablePath=%_HOME%\Resource Files\Conversion Tables
+
+[ModelOptions\Physical Objects\ClssNamingOptions\COLN]
+
+[ModelOptions\Physical Objects\ClssNamingOptions\COLN\Name]
+Template=
+MaxLen=254
+Case=M
+ValidChar=
+InvldChar=
+AllValid=Yes
+NoAccent=No
+DefaultChar=
+Script=
+ConvTable=
+ConvTablePath=%_HOME%\Resource Files\Conversion Tables
+
+[ModelOptions\Physical Objects\ClssNamingOptions\COLN\Code]
+Template=
+MaxLen=64
+Case=M
+ValidChar=
+InvldChar=
+AllValid=Yes
+NoAccent=No
+DefaultChar=
+Script=
+ConvTable=
+ConvTablePath=%_HOME%\Resource Files\Conversion Tables
+
+[ModelOptions\Physical Objects\ClssNamingOptions\INDX]
+
+[ModelOptions\Physical Objects\ClssNamingOptions\INDX\Name]
+Template=
+MaxLen=254
+Case=M
+ValidChar=
+InvldChar=
+AllValid=Yes
+NoAccent=No
+DefaultChar=
+Script=
+ConvTable=
+ConvTablePath=%_HOME%\Resource Files\Conversion Tables
+
+[ModelOptions\Physical Objects\ClssNamingOptions\INDX\Code]
+Template=
+MaxLen=254
+Case=M
+ValidChar=
+InvldChar=
+AllValid=Yes
+NoAccent=No
+DefaultChar=
+Script=
+ConvTable=
+ConvTablePath=%_HOME%\Resource Files\Conversion Tables
+
+[ModelOptions\Physical Objects\ClssNamingOptions\REFR]
+
+[ModelOptions\Physical Objects\ClssNamingOptions\REFR\Name]
+Template=
+MaxLen=254
+Case=M
+ValidChar=
+InvldChar=
+AllValid=Yes
+NoAccent=No
+DefaultChar=
+Script=
+ConvTable=
+ConvTablePath=%_HOME%\Resource Files\Conversion Tables
+
+[ModelOptions\Physical Objects\ClssNamingOptions\REFR\Code]
+Template=
+MaxLen=254
+Case=M
+ValidChar=
+InvldChar=
+AllValid=Yes
+NoAccent=No
+DefaultChar=
+Script=
+ConvTable=
+ConvTablePath=%_HOME%\Resource Files\Conversion Tables
+
+[ModelOptions\Physical Objects\ClssNamingOptions\VREF]
+
+[ModelOptions\Physical Objects\ClssNamingOptions\VREF\Name]
+Template=
+MaxLen=254
+Case=M
+ValidChar=
+InvldChar=
+AllValid=Yes
+NoAccent=No
+DefaultChar=
+Script=
+ConvTable=
+ConvTablePath=%_HOME%\Resource Files\Conversion Tables
+
+[ModelOptions\Physical Objects\ClssNamingOptions\VREF\Code]
+Template=
+MaxLen=254
+Case=M
+ValidChar=
+InvldChar=
+AllValid=Yes
+NoAccent=No
+DefaultChar=
+Script=
+ConvTable=
+ConvTablePath=%_HOME%\Resource Files\Conversion Tables
+
+[ModelOptions\Physical Objects\ClssNamingOptions\VIEW]
+
+[ModelOptions\Physical Objects\ClssNamingOptions\VIEW\Name]
+Template=
+MaxLen=254
+Case=M
+ValidChar=
+InvldChar=
+AllValid=Yes
+NoAccent=No
+DefaultChar=
+Script=
+ConvTable=
+ConvTablePath=%_HOME%\Resource Files\Conversion Tables
+
+[ModelOptions\Physical Objects\ClssNamingOptions\VIEW\Code]
+Template=
+MaxLen=64
+Case=M
+ValidChar=
+InvldChar=
+AllValid=Yes
+NoAccent=No
+DefaultChar=
+Script=
+ConvTable=
+ConvTablePath=%_HOME%\Resource Files\Conversion Tables
+
+[ModelOptions\Physical Objects\ClssNamingOptions\VIEWC]
+
+[ModelOptions\Physical Objects\ClssNamingOptions\VIEWC\Name]
+Template=
+MaxLen=254
+Case=M
+ValidChar=
+InvldChar=
+AllValid=Yes
+NoAccent=No
+DefaultChar=
+Script=
+ConvTable=
+ConvTablePath=%_HOME%\Resource Files\Conversion Tables
+
+[ModelOptions\Physical Objects\ClssNamingOptions\VIEWC\Code]
+Template=
+MaxLen=254
+Case=M
+ValidChar=
+InvldChar=
+AllValid=Yes
+NoAccent=No
+DefaultChar=
+Script=
+ConvTable=
+ConvTablePath=%_HOME%\Resource Files\Conversion Tables
+
+[ModelOptions\Physical Objects\ClssNamingOptions\WEBSERV]
+
+[ModelOptions\Physical Objects\ClssNamingOptions\WEBSERV\Name]
+Template=
+MaxLen=254
+Case=M
+ValidChar=
+InvldChar=
+AllValid=Yes
+NoAccent=No
+DefaultChar=
+Script=
+ConvTable=
+ConvTablePath=%_HOME%\Resource Files\Conversion Tables
+
+[ModelOptions\Physical Objects\ClssNamingOptions\WEBSERV\Code]
+Template=
+MaxLen=254
+Case=M
+ValidChar=&#39;a&#39;-&#39;z&#39;,&#39;A&#39;-&#39;Z&#39;,&#39;0&#39;-&#39;9&#39;,&quot;/-_.!~*&#39;()&quot;
+InvldChar=
+AllValid=Yes
+NoAccent=No
+DefaultChar=
+Script=
+ConvTable=
+ConvTablePath=%_HOME%\Resource Files\Conversion Tables
+
+[ModelOptions\Physical Objects\ClssNamingOptions\WEBOP]
+
+[ModelOptions\Physical Objects\ClssNamingOptions\WEBOP\Name]
+Template=
+MaxLen=254
+Case=M
+ValidChar=
+InvldChar=
+AllValid=Yes
+NoAccent=No
+DefaultChar=
+Script=
+ConvTable=
+ConvTablePath=%_HOME%\Resource Files\Conversion Tables
+
+[ModelOptions\Physical Objects\ClssNamingOptions\WEBOP\Code]
+Template=
+MaxLen=254
+Case=M
+ValidChar=&#39;a&#39;-&#39;z&#39;,&#39;A&#39;-&#39;Z&#39;,&#39;0&#39;-&#39;9&#39;,&quot;/-_.!~*&#39;()&quot;
+InvldChar=
+AllValid=Yes
+NoAccent=No
+DefaultChar=
+Script=
+ConvTable=
+ConvTablePath=%_HOME%\Resource Files\Conversion Tables
+
+[ModelOptions\Physical Objects\ClssNamingOptions\WPARAM]
+
+[ModelOptions\Physical Objects\ClssNamingOptions\WPARAM\Name]
+Template=
+MaxLen=254
+Case=M
+ValidChar=
+InvldChar=
+AllValid=Yes
+NoAccent=No
+DefaultChar=
+Script=
+ConvTable=
+ConvTablePath=%_HOME%\Resource Files\Conversion Tables
+
+[ModelOptions\Physical Objects\ClssNamingOptions\WPARAM\Code]
+Template=
+MaxLen=254
+Case=M
+ValidChar=
+InvldChar=
+AllValid=Yes
+NoAccent=No
+DefaultChar=
+Script=
+ConvTable=
+ConvTablePath=%_HOME%\Resource Files\Conversion Tables
+
+[ModelOptions\Physical Objects\ClssNamingOptions\FACT]
+
+[ModelOptions\Physical Objects\ClssNamingOptions\FACT\Name]
+Template=
+MaxLen=254
+Case=M
+ValidChar=
+InvldChar=
+AllValid=Yes
+NoAccent=No
+DefaultChar=
+Script=
+ConvTable=
+ConvTablePath=%_HOME%\Resource Files\Conversion Tables
+
+[ModelOptions\Physical Objects\ClssNamingOptions\FACT\Code]
+Template=
+MaxLen=254
+Case=M
+ValidChar=
+InvldChar=
+AllValid=Yes
+NoAccent=No
+DefaultChar=
+Script=
+ConvTable=
+ConvTablePath=%_HOME%\Resource Files\Conversion Tables
+
+[ModelOptions\Physical Objects\ClssNamingOptions\DIMN]
+
+[ModelOptions\Physical Objects\ClssNamingOptions\DIMN\Name]
+Template=
+MaxLen=254
+Case=M
+ValidChar=
+InvldChar=
+AllValid=Yes
+NoAccent=No
+DefaultChar=
+Script=
+ConvTable=
+ConvTablePath=%_HOME%\Resource Files\Conversion Tables
+
+[ModelOptions\Physical Objects\ClssNamingOptions\DIMN\Code]
+Template=
+MaxLen=254
+Case=M
+ValidChar=
+InvldChar=
+AllValid=Yes
+NoAccent=No
+DefaultChar=
+Script=
+ConvTable=
+ConvTablePath=%_HOME%\Resource Files\Conversion Tables
+
+[ModelOptions\Physical Objects\ClssNamingOptions\CUBE]
+
+[ModelOptions\Physical Objects\ClssNamingOptions\CUBE\Name]
+Template=
+MaxLen=254
+Case=M
+ValidChar=
+InvldChar=
+AllValid=Yes
+NoAccent=No
+DefaultChar=
+Script=
+ConvTable=
+ConvTablePath=%_HOME%\Resource Files\Conversion Tables
+
+[ModelOptions\Physical Objects\ClssNamingOptions\CUBE\Code]
+Template=
+MaxLen=254
+Case=M
+ValidChar=
+InvldChar=
+AllValid=Yes
+NoAccent=No
+DefaultChar=
+Script=
+ConvTable=
+ConvTablePath=%_HOME%\Resource Files\Conversion Tables
+
+[ModelOptions\Physical Objects\ClssNamingOptions\MEAS]
+
+[ModelOptions\Physical Objects\ClssNamingOptions\MEAS\Name]
+Template=
+MaxLen=254
+Case=M
+ValidChar=
+InvldChar=
+AllValid=Yes
+NoAccent=No
+DefaultChar=
+Script=
+ConvTable=
+ConvTablePath=%_HOME%\Resource Files\Conversion Tables
+
+[ModelOptions\Physical Objects\ClssNamingOptions\MEAS\Code]
+Template=
+MaxLen=254
+Case=M
+ValidChar=
+InvldChar=
+AllValid=Yes
+NoAccent=No
+DefaultChar=
+Script=
+ConvTable=
+ConvTablePath=%_HOME%\Resource Files\Conversion Tables
+
+[ModelOptions\Physical Objects\ClssNamingOptions\DATTR]
+
+[ModelOptions\Physical Objects\ClssNamingOptions\DATTR\Name]
+Template=
+MaxLen=254
+Case=M
+ValidChar=
+InvldChar=
+AllValid=Yes
+NoAccent=No
+DefaultChar=
+Script=
+ConvTable=
+ConvTablePath=%_HOME%\Resource Files\Conversion Tables
+
+[ModelOptions\Physical Objects\ClssNamingOptions\DATTR\Code]
+Template=
+MaxLen=254
+Case=M
+ValidChar=
+InvldChar=
+AllValid=Yes
+NoAccent=No
+DefaultChar=
+Script=
+ConvTable=
+ConvTablePath=%_HOME%\Resource Files\Conversion Tables
+
+[ModelOptions\Physical Objects\ClssNamingOptions\FILO]
+
+[ModelOptions\Physical Objects\ClssNamingOptions\FILO\Name]
+Template=
+MaxLen=254
+Case=M
+ValidChar=
+InvldChar=
+AllValid=Yes
+NoAccent=No
+DefaultChar=
+Script=
+ConvTable=
+ConvTablePath=%_HOME%\Resource Files\Conversion Tables
+
+[ModelOptions\Physical Objects\ClssNamingOptions\FILO\Code]
+Template=
+MaxLen=254
+Case=M
+ValidChar=
+InvldChar=
+AllValid=Yes
+NoAccent=No
+DefaultChar=
+Script=
+ConvTable=
+ConvTablePath=%_HOME%\Resource Files\Conversion Tables
+
+[ModelOptions\Physical Objects\ClssNamingOptions\FRMEOBJ]
+
+[ModelOptions\Physical Objects\ClssNamingOptions\FRMEOBJ\Name]
+Template=
+MaxLen=254
+Case=M
+ValidChar=
+InvldChar=
+AllValid=Yes
+NoAccent=No
+DefaultChar=
+Script=
+ConvTable=
+ConvTablePath=%_HOME%\Resource Files\Conversion Tables
+
+[ModelOptions\Physical Objects\ClssNamingOptions\FRMEOBJ\Code]
+Template=
+MaxLen=254
+Case=M
+ValidChar=
+InvldChar=
+AllValid=Yes
+NoAccent=No
+DefaultChar=
+Script=
+ConvTable=
+ConvTablePath=%_HOME%\Resource Files\Conversion Tables
+
+[ModelOptions\Physical Objects\ClssNamingOptions\FRMELNK]
+
+[ModelOptions\Physical Objects\ClssNamingOptions\FRMELNK\Name]
+Template=
+MaxLen=254
+Case=M
+ValidChar=
+InvldChar=
+AllValid=Yes
+NoAccent=No
+DefaultChar=
+Script=
+ConvTable=
+ConvTablePath=%_HOME%\Resource Files\Conversion Tables
+
+[ModelOptions\Physical Objects\ClssNamingOptions\FRMELNK\Code]
+Template=
+MaxLen=254
+Case=M
+ValidChar=
+InvldChar=
+AllValid=Yes
+NoAccent=No
+DefaultChar=
+Script=
+ConvTable=
+ConvTablePath=%_HOME%\Resource Files\Conversion Tables
+
+[ModelOptions\Physical Objects\ClssNamingOptions\DefaultClass]
+
+[ModelOptions\Physical Objects\ClssNamingOptions\DefaultClass\Name]
+Template=
+MaxLen=254
+Case=M
+ValidChar=
+InvldChar=
+AllValid=Yes
+NoAccent=No
+DefaultChar=
+Script=
+ConvTable=
+ConvTablePath=%_HOME%\Resource Files\Conversion Tables
+
+[ModelOptions\Physical Objects\ClssNamingOptions\DefaultClass\Code]
+Template=
+MaxLen=254
+Case=M
+ValidChar=
+InvldChar=
+AllValid=Yes
+NoAccent=No
+DefaultChar=
+Script=
+ConvTable=
+ConvTablePath=%_HOME%\Resource Files\Conversion Tables
+
+[ModelOptions\Connection]
+
+[ModelOptions\Pdm]
+
+[ModelOptions\Generate]
+
+[ModelOptions\Generate\Pdm]
+RRMapping=No
+
+[ModelOptions\Generate\Cdm]
+CheckModel=Yes
+SaveLinks=Yes
+NameToCode=No
+Notation=2
+
+[ModelOptions\Generate\Oom]
+CheckModel=Yes
+SaveLinks=Yes
+ORMapping=No
+NameToCode=Yes
+ClassPrefix=
+
+[ModelOptions\Generate\Xsm]
+CheckModel=Yes
+SaveLinks=Yes
+ORMapping=No
+NameToCode=No
+
+[ModelOptions\Generate\Ldm]
+CheckModel=Yes
+SaveLinks=Yes
+NameToCode=No
+
+[ModelOptions\Default Opts]
+
+[ModelOptions\Default Opts\TABL]
+PhysOpts=
+
+[ModelOptions\Default Opts\COLN]
+PhysOpts=
+
+[ModelOptions\Default Opts\INDX]
+PhysOpts=
+
+[ModelOptions\Default Opts\AKEY]
+PhysOpts=
+
+[ModelOptions\Default Opts\PKEY]
+PhysOpts=
+
+[ModelOptions\Default Opts\STOR]
+PhysOpts=
+
+[ModelOptions\Default Opts\TSPC]
+PhysOpts=
+
+[ModelOptions\Default Opts\SQNC]
+PhysOpts=
+
+[ModelOptions\Default Opts\DTBS]
+PhysOpts=
+
+[ModelOptions\Default Opts\USER]
+PhysOpts=
+
+[ModelOptions\Default Opts\JIDX]
+PhysOpts=</a:ModelOptionsText>
+<c:DBMS>
+<o:Shortcut Id="o3">
+<a:ObjectID>AFAD9ECF-F417-4FCE-BEA4-884857D4C1A9</a:ObjectID>
+<a:Name>MySQL 5.0</a:Name>
+<a:Code>MYSQL50</a:Code>
+<a:CreationDate>1524449337</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449337</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:TargetStereotype/>
+<a:TargetID>F4F16ECD-F2F1-4006-AF6F-638D5C65F35E</a:TargetID>
+<a:TargetClassID>4BA9F647-DAB1-11D1-9944-006097355D9B</a:TargetClassID>
+</o:Shortcut>
+</c:DBMS>
+<c:PhysicalDiagrams>
+<o:PhysicalDiagram Id="o4">
+<a:ObjectID>B6C2C4A4-6A8A-41F3-909D-C7B514E1EAE2</a:ObjectID>
+<a:Name>PhysicalDiagram_1</a:Name>
+<a:Code>PhysicalDiagram_1</a:Code>
+<a:CreationDate>1524449325</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1538297386</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:DisplayPreferences>[DisplayPreferences]
+
+[DisplayPreferences\PDM]
+
+[DisplayPreferences\General]
+Adjust to text=Yes
+Snap Grid=No
+Constrain Labels=Yes
+Display Grid=No
+Show Page Delimiter=Yes
+Grid size=0
+Graphic unit=2
+Window color=255, 255, 255
+Background image=
+Background mode=8
+Watermark image=
+Watermark mode=8
+Show watermark on screen=No
+Gradient mode=0
+Gradient end color=255, 255, 255
+Show Swimlane=No
+SwimlaneVert=Yes
+TreeVert=No
+CompDark=0
+
+[DisplayPreferences\Object]
+Mode=0
+Trunc Length=80
+Word Length=80
+Word Text=!&quot;&quot;#$%&amp;&#39;()*+,-./:;&lt;=&gt;?@[\]^_`{|}~
+Shortcut IntIcon=Yes
+Shortcut IntLoct=Yes
+Shortcut IntFullPath=No
+Shortcut IntLastPackage=Yes
+Shortcut ExtIcon=Yes
+Shortcut ExtLoct=No
+Shortcut ExtFullPath=No
+Shortcut ExtLastPackage=Yes
+Shortcut ExtIncludeModl=Yes
+EObjShowStrn=Yes
+ExtendedObject.Comment=No
+ExtendedObject.IconPicture=No
+ExtendedObject_SymbolLayout=&lt;Form&gt;[CRLF] &lt;StandardAttribute Name=&quot;Stereotype&quot; Attribute=&quot;Stereotype&quot; Prefix=&quot;&amp;lt;&amp;lt;&quot; Suffix=&quot;&amp;gt;&amp;gt;&quot; Alignment=&quot;CNTR&quot; Caption=&quot;&quot; Mandatory=&quot;No&quot; /&gt;[CRLF] &lt;StandardAttribute Name=&quot;Object Name&quot; Attribute=&quot;DisplayName&quot; Prefix=&quot;&quot; Suffix=&quot;&quot; Alignment=&quot;CNTR&quot; Caption=&quot;&quot; Mandatory=&quot;Yes&quot; /&gt;[CRLF] &lt;Separator Name=&quot;Separator&quot; /&gt;[CRLF] &lt;StandardAttribute Name=&quot;Comment&quot; Attribute=&quot;Comment&quot; Prefix=&quot;&quot; Suffix=&quot;&quot; Alignment=&quot;LEFT&quot; Caption=&quot;&quot; Mandatory=&quot;No&quot; /&gt;[CRLF] &lt;StandardAttribute Name=&quot;Icon&quot; Attribute=&quot;IconPicture&quot; Prefix=&quot;&quot; Suffix=&quot;&quot; Alignment=&quot;CNTR&quot; Caption=&quot;&quot; Mandatory=&quot;Yes&quot; /&gt;[CRLF]&lt;/Form&gt;
+ELnkShowStrn=Yes
+ELnkShowName=Yes
+ExtendedLink_SymbolLayout=&lt;Form&gt;[CRLF] &lt;Form Name=&quot;Center&quot; &gt;[CRLF]  &lt;StandardAttribute Name=&quot;Stereotype&quot; Attribute=&quot;Stereotype&quot; Prefix=&quot;&amp;lt;&amp;lt;&quot; Suffix=&quot;&amp;gt;&amp;gt;&quot; Caption=&quot;&quot; Mandatory=&quot;No&quot; /&gt;[CRLF]  &lt;StandardAttribute Name=&quot;Name&quot; Attribute=&quot;DisplayName&quot; Prefix=&quot;&quot; Suffix=&quot;&quot; Caption=&quot;&quot; Mandatory=&quot;No&quot; /&gt;[CRLF] &lt;/Form&gt;[CRLF] &lt;Form Name=&quot;Source&quot; &gt;[CRLF] &lt;/Form&gt;[CRLF] &lt;Form Name=&quot;Destination&quot; &gt;[CRLF] &lt;/Form&gt;[CRLF]&lt;/Form&gt;
+FileObject.Stereotype=No
+FileObject.DisplayName=Yes
+FileObject.LocationOrName=No
+FileObject.IconPicture=No
+FileObject.IconMode=Yes
+FileObject_SymbolLayout=&lt;Form&gt;[CRLF] &lt;StandardAttribute Name=&quot;Stereotype&quot; Attribute=&quot;Stereotype&quot; Prefix=&quot;&amp;lt;&amp;lt;&quot; Suffix=&quot;&amp;gt;&amp;gt;&quot; Alignment=&quot;CNTR&quot; Caption=&quot;&quot; Mandatory=&quot;No&quot; /&gt;[CRLF] &lt;ExclusiveChoice Name=&quot;Exclusive Choice&quot; Mandatory=&quot;Yes&quot; Display=&quot;HorizontalRadios&quot; &gt;[CRLF]  &lt;StandardAttribute Name=&quot;Name&quot; Attribute=&quot;DisplayName&quot; Prefix=&quot;&quot; Suffix=&quot;&quot; Alignment=&quot;CNTR&quot; Caption=&quot;&quot; Mandatory=&quot;No&quot; /&gt;[CRLF]  &lt;StandardAttribute Name=&quot;Location&quot; Attribute=&quot;LocationOrName&quot; Prefix=&quot;&quot; Suffix=&quot;&quot; Alignment=&quot;CNTR&quot; Caption=&quot;&quot; Mandatory=&quot;No&quot; /&gt;[CRLF] &lt;/ExclusiveChoice&gt;[CRLF] &lt;StandardAttribute Name=&quot;Icon&quot; Attribute=&quot;IconPicture&quot; Prefix=&quot;&quot; Suffix=&quot;&quot; Alignment=&quot;CNTR&quot; Caption=&quot;&quot; Mandatory=&quot;Yes&quot; /&gt;[CRLF]&lt;/Form&gt;
+PckgShowStrn=Yes
+Package.Comment=No
+Package.IconPicture=No
+Package_SymbolLayout=
+Display Model Version=Yes
+Table.Stereotype=Yes
+Table.DisplayName=Yes
+Table.OwnerDisplayName=No
+Table.Columns=Yes
+Table.Columns._Filter=&quot;&quot;PDMCOLNALL
+Table.Columns._Columns=Stereotype DataType KeyIndicator
+Table.Columns._Limit=-5
+Table.Keys=No
+Table.Keys._Columns=Stereotype Indicator
+Table.Indexes=No
+Table.Indexes._Columns=Stereotype
+Table.Triggers=No
+Table.Triggers._Columns=Stereotype
+Table.Comment=No
+Table.IconPicture=No
+Table_SymbolLayout=&lt;Form&gt;[CRLF] &lt;StandardAttribute Name=&quot;Stereotype&quot; Attribute=&quot;Stereotype&quot; Prefix=&quot;&amp;lt;&amp;lt;&quot; Suffix=&quot;&amp;gt;&amp;gt;&quot; Alignment=&quot;CNTR&quot; Caption=&quot;&quot; Mandatory=&quot;No&quot; /&gt;[CRLF] &lt;ExclusiveChoice Name=&quot;Exclusive Choice&quot; Mandatory=&quot;Yes&quot; Display=&quot;HorizontalRadios&quot; &gt;[CRLF]  &lt;StandardAttribute Name=&quot;Name&quot; Attribute=&quot;DisplayName&quot; Prefix=&quot;&quot; Suffix=&quot;&quot; Alignment=&quot;CNTR&quot; Caption=&quot;&quot; Mandatory=&quot;No&quot; /&gt;[CRLF]  &lt;StandardAttribute Name=&quot;Owner and Name&quot; Attribute=&quot;OwnerDisplayName&quot; Prefix=&quot;&quot; Suffix=&quot;&quot; Alignment=&quot;CNTR&quot; Caption=&quot;&quot; Mandatory=&quot;No&quot; /&gt;[CRLF] &lt;/ExclusiveChoice&gt;[CRLF] &lt;Separator Name=&quot;Separator&quot; /&gt;[CRLF] &lt;StandardCollection Name=&quot;Columns&quot; Collection=&quot;Columns&quot; Columns=&quot;Stereotype No\r\nDisplayName Yes\r\nDataType No\r\nSymbolDataType No &amp;quot;Domain or Data type&amp;quot;\r\nDomain No\r\nKeyIndicator No\r\nIndexIndicator No\r\nNullStatus No&quot; Filters=&quot;&amp;quot;All Columns&amp;quot;  PDMCOLNALL &amp;quot;&amp;quot;\r\n&amp;quot;PK Columns&amp;quot;  PDMCOLNPK &amp;quot;PRIM \&amp;quot;TRUE\&amp;quot; TRUE&amp;quot;\r\n&amp;quot;Key Columns&amp;quot;  PDMCOLNKEY &amp;quot;KEYS \&amp;quot;TRUE\&amp;quot; TRUE&amp;quot;&quot; HasLimit=&quot;Yes&quot; Caption=&quot;&quot; Mandatory=&quot;No&quot; /&gt;[CRLF] &lt;StandardCollection Name=&quot;Keys&quot; Collection=&quot;Keys&quot; Columns=&quot;Stereotype No\r\nDisplayName Yes\r\nIndicator No&quot; HasLimit=&quot;No&quot; Caption=&quot;&quot; Mandatory=&quot;No&quot; /&gt;[CRLF] &lt;StandardCollection Name=&quot;Indexes&quot; Collection=&quot;Indexes&quot; Columns=&quot;Stereotype No\r\nDisplayName Yes\r\nIndicator No&quot; HasLimit=&quot;No&quot; Caption=&quot;&quot; Mandatory=&quot;No&quot; /&gt;[CRLF] &lt;StandardCollection Name=&quot;Triggers&quot; Collection=&quot;Triggers&quot; Columns=&quot;Stereotype No\r\nDisplayName Yes&quot; HasLimit=&quot;No&quot; Caption=&quot;&quot; Mandatory=&quot;No&quot; /&gt;[CRLF] &lt;StandardAttribute Name=&quot;Comment&quot; Attribute=&quot;Comment&quot; Prefix=&quot;&quot; Suffix=&quot;&quot; Alignment=&quot;LEFT&quot; Caption=&quot;&quot; Mandatory=&quot;No&quot; /&gt;[CRLF] &lt;StandardAttribute Name=&quot;Icon&quot; Attribute=&quot;IconPicture&quot; Prefix=&quot;&quot; Suffix=&quot;&quot; Alignment=&quot;CNTR&quot; Caption=&quot;&quot; Mandatory=&quot;Yes&quot; /&gt;[CRLF]&lt;/Form&gt;
+View.Stereotype=Yes
+View.DisplayName=Yes
+View.OwnerDisplayName=No
+View.Columns=Yes
+View.Columns._Columns=DisplayName
+View.Columns._Limit=-5
+View.TemporaryVTables=Yes
+View.Indexes=No
+View.Comment=No
+View.IconPicture=No
+View_SymbolLayout=&lt;Form&gt;[CRLF] &lt;StandardAttribute Name=&quot;Stereotype&quot; Attribute=&quot;Stereotype&quot; Prefix=&quot;&amp;lt;&amp;lt;&quot; Suffix=&quot;&amp;gt;&amp;gt;&quot; Alignment=&quot;CNTR&quot; Caption=&quot;&quot; Mandatory=&quot;No&quot; /&gt;[CRLF] &lt;ExclusiveChoice Name=&quot;Exclusive Choice&quot; Mandatory=&quot;Yes&quot; Display=&quot;HorizontalRadios&quot; &gt;[CRLF]  &lt;StandardAttribute Name=&quot;Name&quot; Attribute=&quot;DisplayName&quot; Prefix=&quot;&quot; Suffix=&quot;&quot; Alignment=&quot;CNTR&quot; Caption=&quot;&quot; Mandatory=&quot;No&quot; /&gt;[CRLF]  &lt;StandardAttribute Name=&quot;Owner and Name&quot; Attribute=&quot;OwnerDisplayName&quot; Prefix=&quot;&quot; Suffix=&quot;&quot; Alignment=&quot;CNTR&quot; Caption=&quot;&quot; Mandatory=&quot;No&quot; /&gt;[CRLF] &lt;/ExclusiveChoice&gt;[CRLF] &lt;Separator Name=&quot;Separator&quot; /&gt;[CRLF] &lt;StandardCollection Name=&quot;Columns&quot; Collection=&quot;Columns&quot; Columns=&quot;DisplayName No\r\nExpression No\r\nDataType No\r\nSymbolDataType No &amp;quot;Domain or Data type&amp;quot;\r\nIndexIndicator No&quot; HasLimit=&quot;Yes&quot; Caption=&quot;&quot; Mandatory=&quot;No&quot; /&gt;[CRLF] &lt;StandardCollection Name=&quot;Tables&quot; Collection=&quot;TemporaryVTables&quot; Columns=&quot;Name Yes&quot; HasLimit=&quot;No&quot; Caption=&quot;&quot; Mandatory=&quot;No&quot; /&gt;[CRLF] &lt;StandardCollection Name=&quot;Indexes&quot; Collection=&quot;Indexes&quot; Columns=&quot;DisplayName Yes&quot; HasLimit=&quot;No&quot; Caption=&quot;&quot; Mandatory=&quot;No&quot; /&gt;[CRLF] &lt;StandardAttribute Name=&quot;Comment&quot; Attribute=&quot;Comment&quot; Prefix=&quot;&quot; Suffix=&quot;&quot; Alignment=&quot;LEFT&quot; Caption=&quot;&quot; Mandatory=&quot;No&quot; /&gt;[CRLF] &lt;StandardAttribute Name=&quot;Icon&quot; Attribute=&quot;IconPicture&quot; Prefix=&quot;&quot; Suffix=&quot;&quot; Alignment=&quot;CNTR&quot; Caption=&quot;&quot; Mandatory=&quot;Yes&quot; /&gt;[CRLF]&lt;/Form&gt;
+Procedure.Stereotype=No
+Procedure.DisplayName=Yes
+Procedure.OwnerDisplayName=No
+Procedure.Comment=No
+Procedure.IconPicture=No
+Procedure_SymbolLayout=&lt;Form&gt;[CRLF] &lt;StandardAttribute Name=&quot;Stereotype&quot; Attribute=&quot;Stereotype&quot; Prefix=&quot;&amp;lt;&amp;lt;&quot; Suffix=&quot;&amp;gt;&amp;gt;&quot; Alignment=&quot;CNTR&quot; Caption=&quot;&quot; Mandatory=&quot;No&quot; /&gt;[CRLF] &lt;ExclusiveChoice Name=&quot;Exclusive Choice&quot; Mandatory=&quot;Yes&quot; Display=&quot;HorizontalRadios&quot; &gt;[CRLF]  &lt;StandardAttribute Name=&quot;Name&quot; Attribute=&quot;DisplayName&quot; Prefix=&quot;&quot; Suffix=&quot;&quot; Alignment=&quot;CNTR&quot; Caption=&quot;&quot; Mandatory=&quot;No&quot; /&gt;[CRLF]  &lt;StandardAttribute Name=&quot;Owner and Name&quot; Attribute=&quot;OwnerDisplayName&quot; Prefix=&quot;&quot; Suffix=&quot;&quot; Alignment=&quot;CNTR&quot; Caption=&quot;&quot; Mandatory=&quot;No&quot; /&gt;[CRLF] &lt;/ExclusiveChoice&gt;[CRLF] &lt;Separator Name=&quot;Separator&quot; /&gt;[CRLF] &lt;StandardAttribute Name=&quot;Comment&quot; Attribute=&quot;Comment&quot; Prefix=&quot;&quot; Suffix=&quot;&quot; Alignment=&quot;LEFT&quot; Caption=&quot;&quot; Mandatory=&quot;No&quot; /&gt;[CRLF] &lt;StandardAttribute Name=&quot;Icon&quot; Attribute=&quot;IconPicture&quot; Prefix=&quot;&quot; Suffix=&quot;&quot; Alignment=&quot;CNTR&quot; Caption=&quot;&quot; Mandatory=&quot;Yes&quot; /&gt;[CRLF]&lt;/Form&gt;
+Reference.Cardinality=No
+Reference.ImplementationType=No
+Reference.ChildRole=Yes
+Reference.Stereotype=Yes
+Reference.DisplayName=No
+Reference.ForeignKeyConstraintName=Yes
+Reference.JoinExpression=No
+Reference.Integrity=No
+Reference.ParentRole=Yes
+Reference_SymbolLayout=&lt;Form&gt;[CRLF] &lt;Form Name=&quot;Source&quot; &gt;[CRLF]  &lt;StandardAttribute Name=&quot;Cardinality&quot; Attribute=&quot;Cardinality&quot; Prefix=&quot;&quot; Suffix=&quot;&quot; Caption=&quot;&quot; Mandatory=&quot;No&quot; /&gt;[CRLF]  &lt;StandardAttribute Name=&quot;Implementation&quot; Attribute=&quot;ImplementationType&quot; Prefix=&quot;&quot; Suffix=&quot;&quot; Caption=&quot;&quot; Mandatory=&quot;No&quot; /&gt;[CRLF]  &lt;StandardAttribute Name=&quot;Child Role&quot; Attribute=&quot;ChildRole&quot; Prefix=&quot;&quot; Suffix=&quot;&quot; Caption=&quot;&quot; Mandatory=&quot;No&quot; /&gt;[CRLF] &lt;/Form&gt;[CRLF] &lt;Form Name=&quot;Center&quot; &gt;[CRLF]  &lt;StandardAttribute Name=&quot;Stereotype&quot; Attribute=&quot;Stereotype&quot; Prefix=&quot;&amp;lt;&amp;lt;&quot; Suffix=&quot;&amp;gt;&amp;gt;&quot; Caption=&quot;&quot; Mandatory=&quot;No&quot; /&gt;[CRLF]  &lt;ExclusiveChoice Name=&quot;Exclusive Choice&quot; Mandatory=&quot;No&quot; Display=&quot;HorizontalRadios&quot; &gt;[CRLF]   &lt;StandardAttribute Name=&quot;Name&quot; Attribute=&quot;DisplayName&quot; Prefix=&quot;&quot; Suffix=&quot;&quot; Caption=&quot;&quot; Mandatory=&quot;No&quot; /&gt;[CRLF]   &lt;StandardAttribute Name=&quot;Cons&amp;amp;traint Name&quot; Attribute=&quot;ForeignKeyConstraintName&quot; Prefix=&quot;&quot; Suffix=&quot;&quot; Caption=&quot;Cons&amp;amp;traint Name&quot; Mandatory=&quot;No&quot; /&gt;[CRLF]   &lt;StandardAttribute Name=&quot;Join&quot; Attribute=&quot;JoinExpression&quot; Prefix=&quot;&quot; Suffix=&quot;&quot; Caption=&quot;Join&quot; Mandatory=&quot;No&quot; /&gt;[CRLF]  &lt;/ExclusiveChoice&gt;[CRLF]  &lt;StandardAttribute Name=&quot;Referential integrity&quot; Attribute=&quot;Integrity&quot; Prefix=&quot;&quot; Suffix=&quot;&quot; Caption=&quot;Referential integrity&quot; Mandatory=&quot;No&quot; /&gt;[CRLF] &lt;/Form&gt;[CRLF] &lt;Form Name=&quot;Destination&quot; &gt;[CRLF]  &lt;StandardAttribute Name=&quot;Parent Role&quot; Attribute=&quot;ParentRole&quot; Prefix=&quot;&quot; Suffix=&quot;&quot; Caption=&quot;&quot; Mandatory=&quot;No&quot; /&gt;[CRLF] &lt;/Form&gt;[CRLF]&lt;/Form&gt;
+ViewReference.ChildRole=Yes
+ViewReference.Stereotype=Yes
+ViewReference.DisplayName=No
+ViewReference.JoinExpression=No
+ViewReference.ParentRole=Yes
+ViewReference_SymbolLayout=&lt;Form&gt;[CRLF] &lt;Form Name=&quot;Source&quot; &gt;[CRLF]  &lt;StandardAttribute Name=&quot;Child Role&quot; Attribute=&quot;ChildRole&quot; Prefix=&quot;&quot; Suffix=&quot;&quot; Caption=&quot;&quot; Mandatory=&quot;No&quot; /&gt;[CRLF] &lt;/Form&gt;[CRLF] &lt;Form Name=&quot;Center&quot; &gt;[CRLF]  &lt;StandardAttribute Name=&quot;Stereotype&quot; Attribute=&quot;Stereotype&quot; Prefix=&quot;&amp;lt;&amp;lt;&quot; Suffix=&quot;&amp;gt;&amp;gt;&quot; Caption=&quot;&quot; Mandatory=&quot;No&quot; /&gt;[CRLF]  &lt;ExclusiveChoice Name=&quot;Exclusive Choice&quot; Mandatory=&quot;No&quot; Display=&quot;HorizontalRadios&quot; &gt;[CRLF]   &lt;StandardAttribute Name=&quot;Name&quot; Attribute=&quot;DisplayName&quot; Prefix=&quot;&quot; Suffix=&quot;&quot; Caption=&quot;&quot; Mandatory=&quot;No&quot; /&gt;[CRLF]   &lt;StandardAttribute Name=&quot;Join Expression&quot; Attribute=&quot;JoinExpression&quot; Prefix=&quot;&quot; Suffix=&quot;&quot; Caption=&quot;&quot; Mandatory=&quot;No&quot; /&gt;[CRLF]  &lt;/ExclusiveChoice&gt;[CRLF] &lt;/Form&gt;[CRLF] &lt;Form Name=&quot;Destination&quot; &gt;[CRLF]  &lt;StandardAttribute Name=&quot;Parent Role&quot; Attribute=&quot;ParentRole&quot; Prefix=&quot;&quot; Suffix=&quot;&quot; Caption=&quot;&quot; Mandatory=&quot;No&quot; /&gt;[CRLF] &lt;/Form&gt;[CRLF]&lt;/Form&gt;
+File Location=No
+PckgStrn=Yes
+ColnMode=0
+ColnMax=5
+TablOwnr=No
+ColnDttp=Yes
+ColnDomn=No
+ColnShowDomn=No
+ColnKey=Yes
+ColnIndx=No
+ColnMand=No
+ColnStrn=Yes
+VColName=Yes
+VColExpr=No
+VColDttp=No
+VColIndx=No
+VColCMod=0
+VColCMax=5
+ProcOwnr=No
+KeyStrn=Yes
+IndxStrn=Yes
+TrgrStrn=Yes
+
+[DisplayPreferences\Symbol]
+
+[DisplayPreferences\Symbol\FRMEOBJ]
+STRNFont=新宋体,8,N
+STRNFont color=0, 0, 0
+DISPNAMEFont=新宋体,8,N
+DISPNAMEFont color=0, 0, 0
+LABLFont=新宋体,8,N
+LABLFont color=0, 0, 0
+AutoAdjustToText=Yes
+Keep aspect=No
+Keep center=No
+Keep size=No
+Width=6000
+Height=2000
+Brush color=255 255 255
+Fill Color=Yes
+Brush style=6
+Brush bitmap mode=12
+Brush gradient mode=64
+Brush gradient color=192 192 192
+Brush background image=
+Custom shape=
+Custom text mode=0
+Pen=1 0 255 128 128
+Shadow color=192 192 192
+Shadow=0
+
+[DisplayPreferences\Symbol\FRMELNK]
+CENTERFont=新宋体,8,N
+CENTERFont color=0, 0, 0
+Line style=0
+AutoAdjustToText=Yes
+Keep aspect=No
+Keep center=No
+Keep size=No
+Brush color=255 255 255
+Fill Color=Yes
+Brush style=1
+Brush bitmap mode=12
+Brush gradient mode=0
+Brush gradient color=118 118 118
+Brush background image=
+Custom shape=
+Custom text mode=0
+Pen=1 0 128 128 255
+Shadow color=192 192 192
+Shadow=0
+
+[DisplayPreferences\Symbol\FILO]
+OBJSTRNFont=新宋体,8,N
+OBJSTRNFont color=0, 0, 0
+DISPNAMEFont=新宋体,8,N
+DISPNAMEFont color=0, 0, 0
+LCNMFont=新宋体,8,N
+LCNMFont color=0, 0, 0
+AutoAdjustToText=Yes
+Keep aspect=Yes
+Keep center=Yes
+Keep size=No
+Width=2400
+Height=2400
+Brush color=255 255 255
+Fill Color=No
+Brush style=1
+Brush bitmap mode=12
+Brush gradient mode=0
+Brush gradient color=118 118 118
+Brush background image=
+Custom shape=
+Custom text mode=0
+Pen=1 0 0 0 255
+Shadow color=192 192 192
+Shadow=0
+
+[DisplayPreferences\Symbol\PDMPCKG]
+STRNFont=新宋体,8,N
+STRNFont color=0, 0, 0
+DISPNAMEFont=新宋体,8,N
+DISPNAMEFont color=0, 0, 0
+LABLFont=新宋体,8,N
+LABLFont color=0, 0, 0
+AutoAdjustToText=Yes
+Keep aspect=No
+Keep center=No
+Keep size=No
+Width=4800
+Height=3600
+Brush color=255 255 192
+Fill Color=Yes
+Brush style=6
+Brush bitmap mode=12
+Brush gradient mode=65
+Brush gradient color=255 255 255
+Brush background image=
+Custom shape=
+Custom text mode=0
+Pen=1 0 178 178 178
+Shadow color=192 192 192
+Shadow=0
+
+[DisplayPreferences\Symbol\TABL]
+STRNFont=新宋体,8,N
+STRNFont color=0, 0, 0
+DISPNAMEFont=新宋体,8,N
+DISPNAMEFont color=0, 0, 0
+OWNRDISPNAMEFont=新宋体,8,N
+OWNRDISPNAMEFont color=0, 0, 0
+ColumnsFont=新宋体,8,N
+ColumnsFont color=0, 0, 0
+TablePkColumnsFont=新宋体,8,U
+TablePkColumnsFont color=0, 0, 0
+TableFkColumnsFont=新宋体,8,N
+TableFkColumnsFont color=0, 0, 0
+KeysFont=新宋体,8,N
+KeysFont color=0, 0, 0
+IndexesFont=新宋体,8,N
+IndexesFont color=0, 0, 0
+TriggersFont=新宋体,8,N
+TriggersFont color=0, 0, 0
+LABLFont=新宋体,8,N
+LABLFont color=0, 0, 0
+AutoAdjustToText=Yes
+Keep aspect=No
+Keep center=No
+Keep size=No
+Width=4800
+Height=4000
+Brush color=178 214 252
+Fill Color=Yes
+Brush style=6
+Brush bitmap mode=12
+Brush gradient mode=65
+Brush gradient color=255 255 255
+Brush background image=
+Custom shape=
+Custom text mode=0
+Pen=1 0 0 128 192
+Shadow color=192 192 192
+Shadow=0
+
+[DisplayPreferences\Symbol\VIEW]
+STRNFont=新宋体,8,N
+STRNFont color=0, 0, 0
+DISPNAMEFont=新宋体,8,N
+DISPNAMEFont color=0, 0, 0
+OWNRDISPNAMEFont=新宋体,8,N
+OWNRDISPNAMEFont color=0, 0, 0
+ColumnsFont=新宋体,8,N
+ColumnsFont color=0, 0, 0
+TablePkColumnsFont=新宋体,8,U
+TablePkColumnsFont color=0, 0, 0
+TableFkColumnsFont=新宋体,8,N
+TableFkColumnsFont color=0, 0, 0
+TemporaryVTablesFont=新宋体,8,N
+TemporaryVTablesFont color=0, 0, 0
+IndexesFont=新宋体,8,N
+IndexesFont color=0, 0, 0
+LABLFont=新宋体,8,N
+LABLFont color=0, 0, 0
+AutoAdjustToText=Yes
+Keep aspect=No
+Keep center=No
+Keep size=No
+Width=4800
+Height=4000
+Brush color=208 208 255
+Fill Color=Yes
+Brush style=6
+Brush bitmap mode=12
+Brush gradient mode=65
+Brush gradient color=255 255 255
+Brush background image=
+Custom shape=
+Custom text mode=0
+Pen=1 0 128 128 192
+Shadow color=192 192 192
+Shadow=0
+
+[DisplayPreferences\Symbol\PROC]
+STRNFont=新宋体,8,N
+STRNFont color=0, 0, 0
+DISPNAMEFont=新宋体,8,N
+DISPNAMEFont color=0, 0, 0
+OWNRDISPNAMEFont=新宋体,8,N
+OWNRDISPNAMEFont color=0, 0, 0
+LABLFont=新宋体,8,N
+LABLFont color=0, 0, 0
+AutoAdjustToText=Yes
+Keep aspect=No
+Keep center=No
+Keep size=No
+Width=4000
+Height=1000
+Brush color=255 255 192
+Fill Color=Yes
+Brush style=6
+Brush bitmap mode=12
+Brush gradient mode=65
+Brush gradient color=255 255 255
+Brush background image=
+Custom shape=
+Custom text mode=0
+Pen=1 0 128 108 0
+Shadow color=192 192 192
+Shadow=0
+
+[DisplayPreferences\Symbol\REFR]
+SOURCEFont=新宋体,8,N
+SOURCEFont color=0, 0, 0
+CENTERFont=新宋体,8,N
+CENTERFont color=0, 0, 0
+DESTINATIONFont=新宋体,8,N
+DESTINATIONFont color=0, 0, 0
+Line style=0
+AutoAdjustToText=Yes
+Keep aspect=No
+Keep center=No
+Keep size=No
+Brush color=255 255 255
+Fill Color=Yes
+Brush style=1
+Brush bitmap mode=12
+Brush gradient mode=0
+Brush gradient color=118 118 118
+Brush background image=
+Custom shape=
+Custom text mode=0
+Pen=1 0 0 128 192
+Shadow color=192 192 192
+Shadow=0
+
+[DisplayPreferences\Symbol\VREF]
+SOURCEFont=新宋体,8,N
+SOURCEFont color=0, 0, 0
+CENTERFont=新宋体,8,N
+CENTERFont color=0, 0, 0
+DESTINATIONFont=新宋体,8,N
+DESTINATIONFont color=0, 0, 0
+Line style=0
+AutoAdjustToText=Yes
+Keep aspect=No
+Keep center=No
+Keep size=No
+Brush color=255 255 255
+Fill Color=Yes
+Brush style=1
+Brush bitmap mode=12
+Brush gradient mode=0
+Brush gradient color=118 118 118
+Brush background image=
+Custom shape=
+Custom text mode=0
+Pen=1 0 128 128 192
+Shadow color=192 192 192
+Shadow=0
+
+[DisplayPreferences\Symbol\USRDEPD]
+OBJXSTRFont=新宋体,8,N
+OBJXSTRFont color=0, 0, 0
+Line style=0
+AutoAdjustToText=Yes
+Keep aspect=No
+Keep center=No
+Keep size=No
+Brush color=255 255 255
+Fill Color=Yes
+Brush style=1
+Brush bitmap mode=12
+Brush gradient mode=0
+Brush gradient color=118 118 118
+Brush background image=
+Custom shape=
+Custom text mode=0
+Pen=2 0 128 128 255
+Shadow color=192 192 192
+Shadow=0
+
+[DisplayPreferences\Symbol\Free Symbol]
+Free TextFont=新宋体,8,N
+Free TextFont color=0, 0, 0
+Line style=0
+AutoAdjustToText=Yes
+Keep aspect=No
+Keep center=No
+Keep size=No
+Brush color=255 255 255
+Fill Color=Yes
+Brush style=1
+Brush bitmap mode=12
+Brush gradient mode=0
+Brush gradient color=118 118 118
+Brush background image=
+Custom shape=
+Custom text mode=0
+Pen=1 0 0 0 255
+Shadow color=192 192 192
+Shadow=0</a:DisplayPreferences>
+<a:PaperSize>(8268, 11693)</a:PaperSize>
+<a:PageMargins>((315,354), (433,354))</a:PageMargins>
+<a:PageOrientation>1</a:PageOrientation>
+<a:PaperSource>15</a:PaperSource>
+<c:Symbols>
+<o:TableSymbol Id="o5">
+<a:CreationDate>1524449375</a:CreationDate>
+<a:ModificationDate>1538296407</a:ModificationDate>
+<a:IconMode>-1</a:IconMode>
+<a:Rect>((-38123,15297), (-26435,28269))</a:Rect>
+<a:LineColor>12615680</a:LineColor>
+<a:FillColor>16570034</a:FillColor>
+<a:ShadowColor>12632256</a:ShadowColor>
+<a:FontList>STRN 0 新宋体,8,N
+DISPNAME 0 新宋体,8,N
+OWNRDISPNAME 0 新宋体,8,N
+Columns 0 新宋体,8,N
+TablePkColumns 0 新宋体,8,U
+TableFkColumns 0 新宋体,8,N
+Keys 0 新宋体,8,N
+Indexes 0 新宋体,8,N
+Triggers 0 新宋体,8,N
+LABL 0 新宋体,8,N</a:FontList>
+<a:BrushStyle>6</a:BrushStyle>
+<a:GradientFillMode>65</a:GradientFillMode>
+<a:GradientEndColor>16777215</a:GradientEndColor>
+<c:Object>
+<o:Table Ref="o6"/>
+</c:Object>
+</o:TableSymbol>
+<o:TableSymbol Id="o7">
+<a:CreationDate>1524449375</a:CreationDate>
+<a:ModificationDate>1524449886</a:ModificationDate>
+<a:IconMode>-1</a:IconMode>
+<a:Rect>((-23935,12010), (-11861,28282))</a:Rect>
+<a:LineColor>12615680</a:LineColor>
+<a:FillColor>16570034</a:FillColor>
+<a:ShadowColor>12632256</a:ShadowColor>
+<a:FontList>STRN 0 新宋体,8,N
+DISPNAME 0 新宋体,8,N
+OWNRDISPNAME 0 新宋体,8,N
+Columns 0 新宋体,8,N
+TablePkColumns 0 新宋体,8,U
+TableFkColumns 0 新宋体,8,N
+Keys 0 新宋体,8,N
+Indexes 0 新宋体,8,N
+Triggers 0 新宋体,8,N
+LABL 0 新宋体,8,N</a:FontList>
+<a:BrushStyle>6</a:BrushStyle>
+<a:GradientFillMode>65</a:GradientFillMode>
+<a:GradientEndColor>16777215</a:GradientEndColor>
+<c:Object>
+<o:Table Ref="o8"/>
+</c:Object>
+</o:TableSymbol>
+<o:TableSymbol Id="o9">
+<a:CreationDate>1524449375</a:CreationDate>
+<a:ModificationDate>1538296409</a:ModificationDate>
+<a:IconMode>-1</a:IconMode>
+<a:Rect>((-9361,18172), (2713,27845))</a:Rect>
+<a:LineColor>12615680</a:LineColor>
+<a:FillColor>16570034</a:FillColor>
+<a:ShadowColor>12632256</a:ShadowColor>
+<a:FontList>STRN 0 新宋体,8,N
+DISPNAME 0 新宋体,8,N
+OWNRDISPNAME 0 新宋体,8,N
+Columns 0 新宋体,8,N
+TablePkColumns 0 新宋体,8,U
+TableFkColumns 0 新宋体,8,N
+Keys 0 新宋体,8,N
+Indexes 0 新宋体,8,N
+Triggers 0 新宋体,8,N
+LABL 0 新宋体,8,N</a:FontList>
+<a:BrushStyle>6</a:BrushStyle>
+<a:GradientFillMode>65</a:GradientFillMode>
+<a:GradientEndColor>16777215</a:GradientEndColor>
+<c:Object>
+<o:Table Ref="o10"/>
+</c:Object>
+</o:TableSymbol>
+<o:TableSymbol Id="o11">
+<a:CreationDate>1524449375</a:CreationDate>
+<a:ModificationDate>1524449886</a:ModificationDate>
+<a:IconMode>-1</a:IconMode>
+<a:Rect>((5214,16547), (17288,27869))</a:Rect>
+<a:LineColor>12615680</a:LineColor>
+<a:FillColor>16570034</a:FillColor>
+<a:ShadowColor>12632256</a:ShadowColor>
+<a:FontList>STRN 0 新宋体,8,N
+DISPNAME 0 新宋体,8,N
+OWNRDISPNAME 0 新宋体,8,N
+Columns 0 新宋体,8,N
+TablePkColumns 0 新宋体,8,U
+TableFkColumns 0 新宋体,8,N
+Keys 0 新宋体,8,N
+Indexes 0 新宋体,8,N
+Triggers 0 新宋体,8,N
+LABL 0 新宋体,8,N</a:FontList>
+<a:BrushStyle>6</a:BrushStyle>
+<a:GradientFillMode>65</a:GradientFillMode>
+<a:GradientEndColor>16777215</a:GradientEndColor>
+<c:Object>
+<o:Table Ref="o12"/>
+</c:Object>
+</o:TableSymbol>
+<o:TableSymbol Id="o13">
+<a:CreationDate>1524449375</a:CreationDate>
+<a:ModificationDate>1538296412</a:ModificationDate>
+<a:IconMode>-1</a:IconMode>
+<a:Rect>((19788,14872), (31862,27845))</a:Rect>
+<a:LineColor>12615680</a:LineColor>
+<a:FillColor>16570034</a:FillColor>
+<a:ShadowColor>12632256</a:ShadowColor>
+<a:FontList>STRN 0 新宋体,8,N
+DISPNAME 0 新宋体,8,N
+OWNRDISPNAME 0 新宋体,8,N
+Columns 0 新宋体,8,N
+TablePkColumns 0 新宋体,8,U
+TableFkColumns 0 新宋体,8,N
+Keys 0 新宋体,8,N
+Indexes 0 新宋体,8,N
+Triggers 0 新宋体,8,N
+LABL 0 新宋体,8,N</a:FontList>
+<a:BrushStyle>6</a:BrushStyle>
+<a:GradientFillMode>65</a:GradientFillMode>
+<a:GradientEndColor>16777215</a:GradientEndColor>
+<c:Object>
+<o:Table Ref="o14"/>
+</c:Object>
+</o:TableSymbol>
+<o:TableSymbol Id="o15">
+<a:CreationDate>1524449375</a:CreationDate>
+<a:ModificationDate>1538296204</a:ModificationDate>
+<a:IconMode>-1</a:IconMode>
+<a:Rect>((-37598,8498), (-29000,12497))</a:Rect>
+<a:LineColor>12615680</a:LineColor>
+<a:FillColor>16570034</a:FillColor>
+<a:ShadowColor>12632256</a:ShadowColor>
+<a:FontList>STRN 0 新宋体,8,N
+DISPNAME 0 新宋体,8,N
+OWNRDISPNAME 0 新宋体,8,N
+Columns 0 新宋体,8,N
+TablePkColumns 0 新宋体,8,U
+TableFkColumns 0 新宋体,8,N
+Keys 0 新宋体,8,N
+Indexes 0 新宋体,8,N
+Triggers 0 新宋体,8,N
+LABL 0 新宋体,8,N</a:FontList>
+<a:BrushStyle>6</a:BrushStyle>
+<a:GradientFillMode>65</a:GradientFillMode>
+<a:GradientEndColor>16777215</a:GradientEndColor>
+<c:Object>
+<o:Table Ref="o16"/>
+</c:Object>
+</o:TableSymbol>
+<o:TableSymbol Id="o17">
+<a:CreationDate>1524449375</a:CreationDate>
+<a:ModificationDate>1538296205</a:ModificationDate>
+<a:IconMode>-1</a:IconMode>
+<a:Rect>((-37674,3548), (-29076,7547))</a:Rect>
+<a:LineColor>12615680</a:LineColor>
+<a:FillColor>16570034</a:FillColor>
+<a:ShadowColor>12632256</a:ShadowColor>
+<a:FontList>STRN 0 新宋体,8,N
+DISPNAME 0 新宋体,8,N
+OWNRDISPNAME 0 新宋体,8,N
+Columns 0 新宋体,8,N
+TablePkColumns 0 新宋体,8,U
+TableFkColumns 0 新宋体,8,N
+Keys 0 新宋体,8,N
+Indexes 0 新宋体,8,N
+Triggers 0 新宋体,8,N
+LABL 0 新宋体,8,N</a:FontList>
+<a:BrushStyle>6</a:BrushStyle>
+<a:GradientFillMode>65</a:GradientFillMode>
+<a:GradientEndColor>16777215</a:GradientEndColor>
+<c:Object>
+<o:Table Ref="o18"/>
+</c:Object>
+</o:TableSymbol>
+<o:TableSymbol Id="o19">
+<a:CreationDate>1524449375</a:CreationDate>
+<a:ModificationDate>1538296308</a:ModificationDate>
+<a:IconMode>-1</a:IconMode>
+<a:Rect>((-37528,-6452), (-28929,-2453))</a:Rect>
+<a:LineColor>12615680</a:LineColor>
+<a:FillColor>16570034</a:FillColor>
+<a:ShadowColor>12632256</a:ShadowColor>
+<a:FontList>STRN 0 新宋体,8,N
+DISPNAME 0 新宋体,8,N
+OWNRDISPNAME 0 新宋体,8,N
+Columns 0 新宋体,8,N
+TablePkColumns 0 新宋体,8,U
+TableFkColumns 0 新宋体,8,N
+Keys 0 新宋体,8,N
+Indexes 0 新宋体,8,N
+Triggers 0 新宋体,8,N
+LABL 0 新宋体,8,N</a:FontList>
+<a:BrushStyle>6</a:BrushStyle>
+<a:GradientFillMode>65</a:GradientFillMode>
+<a:GradientEndColor>16777215</a:GradientEndColor>
+<c:Object>
+<o:Table Ref="o20"/>
+</c:Object>
+</o:TableSymbol>
+<o:TableSymbol Id="o21">
+<a:CreationDate>1524449375</a:CreationDate>
+<a:ModificationDate>1538296401</a:ModificationDate>
+<a:IconMode>-1</a:IconMode>
+<a:Rect>((-24280,-1775), (-11048,10373))</a:Rect>
+<a:LineColor>12615680</a:LineColor>
+<a:FillColor>16570034</a:FillColor>
+<a:ShadowColor>12632256</a:ShadowColor>
+<a:FontList>STRN 0 新宋体,8,N
+DISPNAME 0 新宋体,8,N
+OWNRDISPNAME 0 新宋体,8,N
+Columns 0 新宋体,8,N
+TablePkColumns 0 新宋体,8,U
+TableFkColumns 0 新宋体,8,N
+Keys 0 新宋体,8,N
+Indexes 0 新宋体,8,N
+Triggers 0 新宋体,8,N
+LABL 0 新宋体,8,N</a:FontList>
+<a:BrushStyle>6</a:BrushStyle>
+<a:GradientFillMode>65</a:GradientFillMode>
+<a:GradientEndColor>16777215</a:GradientEndColor>
+<c:Object>
+<o:Table Ref="o22"/>
+</c:Object>
+</o:TableSymbol>
+<o:TableSymbol Id="o23">
+<a:CreationDate>1524449375</a:CreationDate>
+<a:ModificationDate>1538296599</a:ModificationDate>
+<a:IconMode>-1</a:IconMode>
+<a:Rect>((-9182,625), (2892,10298))</a:Rect>
+<a:LineColor>12615680</a:LineColor>
+<a:FillColor>16570034</a:FillColor>
+<a:ShadowColor>12632256</a:ShadowColor>
+<a:FontList>STRN 0 新宋体,8,N
+DISPNAME 0 新宋体,8,N
+OWNRDISPNAME 0 新宋体,8,N
+Columns 0 新宋体,8,N
+TablePkColumns 0 新宋体,8,U
+TableFkColumns 0 新宋体,8,N
+Keys 0 新宋体,8,N
+Indexes 0 新宋体,8,N
+Triggers 0 新宋体,8,N
+LABL 0 新宋体,8,N</a:FontList>
+<a:BrushStyle>6</a:BrushStyle>
+<a:GradientFillMode>65</a:GradientFillMode>
+<a:GradientEndColor>16777215</a:GradientEndColor>
+<c:Object>
+<o:Table Ref="o24"/>
+</c:Object>
+</o:TableSymbol>
+<o:TableSymbol Id="o25">
+<a:CreationDate>1524449375</a:CreationDate>
+<a:ModificationDate>1538296612</a:ModificationDate>
+<a:IconMode>-1</a:IconMode>
+<a:Rect>((5017,-2538), (17091,10434))</a:Rect>
+<a:LineColor>12615680</a:LineColor>
+<a:FillColor>16570034</a:FillColor>
+<a:ShadowColor>12632256</a:ShadowColor>
+<a:FontList>STRN 0 新宋体,8,N
+DISPNAME 0 新宋体,8,N
+OWNRDISPNAME 0 新宋体,8,N
+Columns 0 新宋体,8,N
+TablePkColumns 0 新宋体,8,U
+TableFkColumns 0 新宋体,8,N
+Keys 0 新宋体,8,N
+Indexes 0 新宋体,8,N
+Triggers 0 新宋体,8,N
+LABL 0 新宋体,8,N</a:FontList>
+<a:BrushStyle>6</a:BrushStyle>
+<a:GradientFillMode>65</a:GradientFillMode>
+<a:GradientEndColor>16777215</a:GradientEndColor>
+<c:Object>
+<o:Table Ref="o26"/>
+</c:Object>
+</o:TableSymbol>
+<o:TableSymbol Id="o27">
+<a:CreationDate>1524449375</a:CreationDate>
+<a:ModificationDate>1538297772</a:ModificationDate>
+<a:IconMode>-1</a:IconMode>
+<a:Rect>((-39520,-17440), (-26288,-8592))</a:Rect>
+<a:LineColor>12615680</a:LineColor>
+<a:FillColor>16570034</a:FillColor>
+<a:ShadowColor>12632256</a:ShadowColor>
+<a:FontList>STRN 0 新宋体,8,N
+DISPNAME 0 新宋体,8,N
+OWNRDISPNAME 0 新宋体,8,N
+Columns 0 新宋体,8,N
+TablePkColumns 0 新宋体,8,U
+TableFkColumns 0 新宋体,8,N
+Keys 0 新宋体,8,N
+Indexes 0 新宋体,8,N
+Triggers 0 新宋体,8,N
+LABL 0 新宋体,8,N</a:FontList>
+<a:BrushStyle>6</a:BrushStyle>
+<a:GradientFillMode>65</a:GradientFillMode>
+<a:GradientEndColor>16777215</a:GradientEndColor>
+<c:Object>
+<o:Table Ref="o28"/>
+</c:Object>
+</o:TableSymbol>
+<o:TableSymbol Id="o29">
+<a:CreationDate>1524449375</a:CreationDate>
+<a:ModificationDate>1538297770</a:ModificationDate>
+<a:IconMode>-1</a:IconMode>
+<a:Rect>((-24744,-19106), (-10738,-8608))</a:Rect>
+<a:LineColor>12615680</a:LineColor>
+<a:FillColor>16570034</a:FillColor>
+<a:ShadowColor>12632256</a:ShadowColor>
+<a:FontList>STRN 0 新宋体,8,N
+DISPNAME 0 新宋体,8,N
+OWNRDISPNAME 0 新宋体,8,N
+Columns 0 新宋体,8,N
+TablePkColumns 0 新宋体,8,U
+TableFkColumns 0 新宋体,8,N
+Keys 0 新宋体,8,N
+Indexes 0 新宋体,8,N
+Triggers 0 新宋体,8,N
+LABL 0 新宋体,8,N</a:FontList>
+<a:BrushStyle>6</a:BrushStyle>
+<a:GradientFillMode>65</a:GradientFillMode>
+<a:GradientEndColor>16777215</a:GradientEndColor>
+<c:Object>
+<o:Table Ref="o30"/>
+</c:Object>
+</o:TableSymbol>
+<o:TableSymbol Id="o31">
+<a:CreationDate>1524449375</a:CreationDate>
+<a:ModificationDate>1538297380</a:ModificationDate>
+<a:IconMode>-1</a:IconMode>
+<a:Rect>((-9749,-20696), (3870,-8548))</a:Rect>
+<a:LineColor>12615680</a:LineColor>
+<a:FillColor>16570034</a:FillColor>
+<a:ShadowColor>12632256</a:ShadowColor>
+<a:FontList>STRN 0 新宋体,8,N
+DISPNAME 0 新宋体,8,N
+OWNRDISPNAME 0 新宋体,8,N
+Columns 0 新宋体,8,N
+TablePkColumns 0 新宋体,8,U
+TableFkColumns 0 新宋体,8,N
+Keys 0 新宋体,8,N
+Indexes 0 新宋体,8,N
+Triggers 0 新宋体,8,N
+LABL 0 新宋体,8,N</a:FontList>
+<a:BrushStyle>6</a:BrushStyle>
+<a:GradientFillMode>65</a:GradientFillMode>
+<a:GradientEndColor>16777215</a:GradientEndColor>
+<c:Object>
+<o:Table Ref="o32"/>
+</c:Object>
+</o:TableSymbol>
+<o:TableSymbol Id="o33">
+<a:CreationDate>1524449375</a:CreationDate>
+<a:ModificationDate>1538297383</a:ModificationDate>
+<a:IconMode>-1</a:IconMode>
+<a:Rect>((5261,-17623), (18494,-8774))</a:Rect>
+<a:LineColor>12615680</a:LineColor>
+<a:FillColor>16570034</a:FillColor>
+<a:ShadowColor>12632256</a:ShadowColor>
+<a:FontList>STRN 0 新宋体,8,N
+DISPNAME 0 新宋体,8,N
+OWNRDISPNAME 0 新宋体,8,N
+Columns 0 新宋体,8,N
+TablePkColumns 0 新宋体,8,U
+TableFkColumns 0 新宋体,8,N
+Keys 0 新宋体,8,N
+Indexes 0 新宋体,8,N
+Triggers 0 新宋体,8,N
+LABL 0 新宋体,8,N</a:FontList>
+<a:BrushStyle>6</a:BrushStyle>
+<a:GradientFillMode>65</a:GradientFillMode>
+<a:GradientEndColor>16777215</a:GradientEndColor>
+<c:Object>
+<o:Table Ref="o34"/>
+</c:Object>
+</o:TableSymbol>
+<o:TableSymbol Id="o35">
+<a:CreationDate>1538296083</a:CreationDate>
+<a:ModificationDate>1538296211</a:ModificationDate>
+<a:IconMode>-1</a:IconMode>
+<a:Rect>((-37675,-1349), (-29076,2650))</a:Rect>
+<a:LineColor>12615680</a:LineColor>
+<a:FillColor>16570034</a:FillColor>
+<a:ShadowColor>12632256</a:ShadowColor>
+<a:FontList>STRN 0 新宋体,8,N
+DISPNAME 0 新宋体,8,N
+OWNRDISPNAME 0 新宋体,8,N
+Columns 0 新宋体,8,N
+TablePkColumns 0 新宋体,8,U
+TableFkColumns 0 新宋体,8,N
+Keys 0 新宋体,8,N
+Indexes 0 新宋体,8,N
+Triggers 0 新宋体,8,N
+LABL 0 新宋体,8,N</a:FontList>
+<a:BrushStyle>6</a:BrushStyle>
+<a:GradientFillMode>65</a:GradientFillMode>
+<a:GradientEndColor>16777215</a:GradientEndColor>
+<c:Object>
+<o:Table Ref="o36"/>
+</c:Object>
+</o:TableSymbol>
+<o:TableSymbol Id="o37">
+<a:CreationDate>1538296587</a:CreationDate>
+<a:ModificationDate>1538296608</a:ModificationDate>
+<a:IconMode>-1</a:IconMode>
+<a:Rect>((19570,-987), (32030,8687))</a:Rect>
+<a:LineColor>12615680</a:LineColor>
+<a:FillColor>16570034</a:FillColor>
+<a:ShadowColor>12632256</a:ShadowColor>
+<a:FontList>STRN 0 新宋体,8,N
+DISPNAME 0 新宋体,8,N
+OWNRDISPNAME 0 新宋体,8,N
+Columns 0 新宋体,8,N
+TablePkColumns 0 新宋体,8,U
+TableFkColumns 0 新宋体,8,N
+Keys 0 新宋体,8,N
+Indexes 0 新宋体,8,N
+Triggers 0 新宋体,8,N
+LABL 0 新宋体,8,N</a:FontList>
+<a:BrushStyle>6</a:BrushStyle>
+<a:GradientFillMode>65</a:GradientFillMode>
+<a:GradientEndColor>16777215</a:GradientEndColor>
+<c:Object>
+<o:Table Ref="o38"/>
+</c:Object>
+</o:TableSymbol>
+<o:TextSymbol Id="o39">
+<a:Text>config_id</a:Text>
+<a:CreationDate>1538296632</a:CreationDate>
+<a:ModificationDate>1538297253</a:ModificationDate>
+<a:Rect>((-13950,-17175), (73200,19575))</a:Rect>
+<a:TextStyle>4130</a:TextStyle>
+<a:BaseSymbol.Flags>1</a:BaseSymbol.Flags>
+<a:LineColor>0</a:LineColor>
+<a:DashStyle>7</a:DashStyle>
+<a:FillColor>16777215</a:FillColor>
+<a:ShadowColor>16777215</a:ShadowColor>
+<a:FontName>新宋体,8,N</a:FontName>
+</o:TextSymbol>
+<o:TableSymbol Id="o40">
+<a:CreationDate>1538297386</a:CreationDate>
+<a:ModificationDate>1538297498</a:ModificationDate>
+<a:IconMode>-1</a:IconMode>
+<a:Rect>((19859,-18262), (33092,-8589))</a:Rect>
+<a:LineColor>12615680</a:LineColor>
+<a:FillColor>16570034</a:FillColor>
+<a:ShadowColor>12632256</a:ShadowColor>
+<a:FontList>STRN 0 新宋体,8,N
+DISPNAME 0 新宋体,8,N
+OWNRDISPNAME 0 新宋体,8,N
+Columns 0 新宋体,8,N
+TablePkColumns 0 新宋体,8,U
+TableFkColumns 0 新宋体,8,N
+Keys 0 新宋体,8,N
+Indexes 0 新宋体,8,N
+Triggers 0 新宋体,8,N
+LABL 0 新宋体,8,N</a:FontList>
+<a:BrushStyle>6</a:BrushStyle>
+<a:GradientFillMode>65</a:GradientFillMode>
+<a:GradientEndColor>16777215</a:GradientEndColor>
+<c:Object>
+<o:Table Ref="o41"/>
+</c:Object>
+</o:TableSymbol>
+</c:Symbols>
+</o:PhysicalDiagram>
+</c:PhysicalDiagrams>
+<c:DefaultDiagram>
+<o:PhysicalDiagram Ref="o4"/>
+</c:DefaultDiagram>
+<c:Tables>
+<o:Table Id="o6">
+<a:ObjectID>BB11FFF9-9DBB-4648-87AA-9A50E1214549</a:ObjectID>
+<a:Name>sys_dept</a:Name>
+<a:Code>sys_dept</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1538297518</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>部门表</a:Comment>
+<a:TotalSavingCurrency/>
+<c:Columns>
+<o:Column Id="o42">
+<a:ObjectID>00C66282-419A-4915-8509-DFFFE6352DE8</a:ObjectID>
+<a:Name>dept_id</a:Name>
+<a:Code>dept_id</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>部门id</a:Comment>
+<a:DataType>int(11)</a:DataType>
+<a:Length>11</a:Length>
+<a:Identity>1</a:Identity>
+<a:Mandatory>1</a:Mandatory>
+</o:Column>
+<o:Column Id="o43">
+<a:ObjectID>5B6FB0B1-5B1E-4E86-AF2A-72C49EBB315E</a:ObjectID>
+<a:Name>parent_id</a:Name>
+<a:Code>parent_id</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>父部门id</a:Comment>
+<a:DefaultValue>0</a:DefaultValue>
+<a:DataType>int(11)</a:DataType>
+<a:Length>11</a:Length>
+</o:Column>
+<o:Column Id="o44">
+<a:ObjectID>065E33A5-6AB5-44F1-8FEC-A72311EECD66</a:ObjectID>
+<a:Name>ancestors</a:Name>
+<a:Code>ancestors</a:Code>
+<a:CreationDate>1538295690</a:CreationDate>
+<a:Creator>admin</a:Creator>
+<a:ModificationDate>1538295792</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:DataType>varchar(50)</a:DataType>
+<a:Length>50</a:Length>
+</o:Column>
+<o:Column Id="o45">
+<a:ObjectID>EBB59EC8-AFD4-40E3-B811-DD5040728D91</a:ObjectID>
+<a:Name>dept_name</a:Name>
+<a:Code>dept_name</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>部门名称</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(30)</a:DataType>
+<a:Length>30</a:Length>
+</o:Column>
+<o:Column Id="o46">
+<a:ObjectID>2F26C025-82B0-4AC5-AEE0-32BA07B7B529</a:ObjectID>
+<a:Name>order_num</a:Name>
+<a:Code>order_num</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>显示顺序</a:Comment>
+<a:DefaultValue>0</a:DefaultValue>
+<a:DataType>int(4)</a:DataType>
+<a:Length>4</a:Length>
+</o:Column>
+<o:Column Id="o47">
+<a:ObjectID>CA504E09-528C-482E-A0C7-F86C559AA3A6</a:ObjectID>
+<a:Name>leader</a:Name>
+<a:Code>leader</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>负责人</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(20)</a:DataType>
+<a:Length>20</a:Length>
+</o:Column>
+<o:Column Id="o48">
+<a:ObjectID>9CFC55C4-DF2B-4A90-A789-C3839FAA43A8</a:ObjectID>
+<a:Name>phone</a:Name>
+<a:Code>phone</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>联系电话</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(20)</a:DataType>
+<a:Length>20</a:Length>
+</o:Column>
+<o:Column Id="o49">
+<a:ObjectID>1A9407E5-D74E-4CE9-9078-C4EC25393F7B</a:ObjectID>
+<a:Name>email</a:Name>
+<a:Code>email</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>邮箱</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(20)</a:DataType>
+<a:Length>20</a:Length>
+</o:Column>
+<o:Column Id="o50">
+<a:ObjectID>B6772812-4B69-4248-871D-FA1B4BA0E5F7</a:ObjectID>
+<a:Name>status</a:Name>
+<a:Code>status</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1538295792</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>部门状态:0正常,1停用</a:Comment>
+<a:DefaultValue>0</a:DefaultValue>
+<a:DataType>char(1)</a:DataType>
+<a:Length>1</a:Length>
+</o:Column>
+<o:Column Id="o51">
+<a:ObjectID>6EBD2BFF-861E-4247-BAAB-B37CCBAF6F8D</a:ObjectID>
+<a:Name>del_flag</a:Name>
+<a:Code>del_flag</a:Code>
+<a:CreationDate>1538295690</a:CreationDate>
+<a:Creator>admin</a:Creator>
+<a:ModificationDate>1538295792</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:DataType>char(1)</a:DataType>
+<a:Length>1</a:Length>
+</o:Column>
+<o:Column Id="o52">
+<a:ObjectID>2504A090-F6D6-493F-855E-5154E01AF0CA</a:ObjectID>
+<a:Name>create_by</a:Name>
+<a:Code>create_by</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>创建者</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(64)</a:DataType>
+<a:Length>64</a:Length>
+</o:Column>
+<o:Column Id="o53">
+<a:ObjectID>D866AE9E-E7FF-47B2-BF3D-9BC1605A2F39</a:ObjectID>
+<a:Name>create_time</a:Name>
+<a:Code>create_time</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>创建时间</a:Comment>
+<a:DataType>timestamp</a:DataType>
+</o:Column>
+<o:Column Id="o54">
+<a:ObjectID>7C6C9836-FC23-4492-8CF1-A4439E01B57C</a:ObjectID>
+<a:Name>update_by</a:Name>
+<a:Code>update_by</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>更新者</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(64)</a:DataType>
+<a:Length>64</a:Length>
+</o:Column>
+<o:Column Id="o55">
+<a:ObjectID>FCED770D-005C-4531-A9D7-D1FD0A054719</a:ObjectID>
+<a:Name>update_time</a:Name>
+<a:Code>update_time</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>更新时间</a:Comment>
+<a:DataType>timestamp</a:DataType>
+</o:Column>
+</c:Columns>
+<c:Keys>
+<o:Key Id="o56">
+<a:ObjectID>15C1774B-9F17-48B6-A61F-728A25220B30</a:ObjectID>
+<a:Name>Key_1</a:Name>
+<a:Code>Key_1</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<c:Key.Columns>
+<o:Column Ref="o42"/>
+</c:Key.Columns>
+</o:Key>
+</c:Keys>
+<c:PrimaryKey>
+<o:Key Ref="o56"/>
+</c:PrimaryKey>
+</o:Table>
+<o:Table Id="o8">
+<a:ObjectID>AA56FD91-4450-4282-8F31-AE302DF6AFEC</a:ObjectID>
+<a:Name>sys_user</a:Name>
+<a:Code>sys_user</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1538297540</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>用户信息表</a:Comment>
+<a:TotalSavingCurrency/>
+<c:Columns>
+<o:Column Id="o57">
+<a:ObjectID>4A920BCE-4040-4F12-89D2-7DF345B90321</a:ObjectID>
+<a:Name>user_id</a:Name>
+<a:Code>user_id</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>用户ID</a:Comment>
+<a:DataType>int(11)</a:DataType>
+<a:Length>11</a:Length>
+<a:Identity>1</a:Identity>
+<a:Mandatory>1</a:Mandatory>
+</o:Column>
+<o:Column Id="o58">
+<a:ObjectID>174E10B2-4A4D-40FF-80B8-B4D285561E42</a:ObjectID>
+<a:Name>dept_id</a:Name>
+<a:Code>dept_id</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1538297552</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>部门ID</a:Comment>
+<a:DefaultValue>NULL</a:DefaultValue>
+<a:DataType>int(11)</a:DataType>
+<a:Length>11</a:Length>
+</o:Column>
+<o:Column Id="o59">
+<a:ObjectID>1D4908A9-5416-4252-BA09-FA122D0194C3</a:ObjectID>
+<a:Name>login_name</a:Name>
+<a:Code>login_name</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>登录账号</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(30)</a:DataType>
+<a:Length>30</a:Length>
+</o:Column>
+<o:Column Id="o60">
+<a:ObjectID>2EF63346-9E82-4746-81B7-AB67D727446D</a:ObjectID>
+<a:Name>user_name</a:Name>
+<a:Code>user_name</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>用户昵称</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(30)</a:DataType>
+<a:Length>30</a:Length>
+</o:Column>
+<o:Column Id="o61">
+<a:ObjectID>477EA57C-0E0B-4596-9A85-EC91E72F5160</a:ObjectID>
+<a:Name>user_type</a:Name>
+<a:Code>user_type</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>类型:Y默认用户,N非默认用户</a:Comment>
+<a:DefaultValue>N</a:DefaultValue>
+<a:DataType>char(1)</a:DataType>
+<a:Length>1</a:Length>
+</o:Column>
+<o:Column Id="o62">
+<a:ObjectID>CD16FFF4-F214-473B-A9A8-FA30A3E357D1</a:ObjectID>
+<a:Name>email</a:Name>
+<a:Code>email</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>用户邮箱</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(100)</a:DataType>
+<a:Length>100</a:Length>
+</o:Column>
+<o:Column Id="o63">
+<a:ObjectID>61603FA5-3EBC-4389-AED7-1B54D238A563</a:ObjectID>
+<a:Name>phonenumber</a:Name>
+<a:Code>phonenumber</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>手机号码</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(20)</a:DataType>
+<a:Length>20</a:Length>
+</o:Column>
+<o:Column Id="o64">
+<a:ObjectID>65E9DE55-ED58-4BD9-B96C-7C081D1119B2</a:ObjectID>
+<a:Name>sex</a:Name>
+<a:Code>sex</a:Code>
+<a:CreationDate>1538295815</a:CreationDate>
+<a:Creator>admin</a:Creator>
+<a:ModificationDate>1538295948</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:DataType>char(1)</a:DataType>
+<a:Length>1</a:Length>
+</o:Column>
+<o:Column Id="o65">
+<a:ObjectID>E5E35061-221A-4BB9-AA22-3CF20F1FCCF6</a:ObjectID>
+<a:Name>avatar</a:Name>
+<a:Code>avatar</a:Code>
+<a:CreationDate>1538295815</a:CreationDate>
+<a:Creator>admin</a:Creator>
+<a:ModificationDate>1538295948</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:DataType>varchar(100)</a:DataType>
+<a:Length>100</a:Length>
+</o:Column>
+<o:Column Id="o66">
+<a:ObjectID>4ED1C2BF-B826-4A82-9464-EEBF271F4054</a:ObjectID>
+<a:Name>password</a:Name>
+<a:Code>password</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>密码</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(100)</a:DataType>
+<a:Length>100</a:Length>
+</o:Column>
+<o:Column Id="o67">
+<a:ObjectID>53E6BB49-3435-46E0-832F-BCAFE1A021CB</a:ObjectID>
+<a:Name>salt</a:Name>
+<a:Code>salt</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>盐加密</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(100)</a:DataType>
+<a:Length>100</a:Length>
+</o:Column>
+<o:Column Id="o68">
+<a:ObjectID>245CAD53-B33B-4EED-8CFA-7AA10ED943B8</a:ObjectID>
+<a:Name>status</a:Name>
+<a:Code>status</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1538297540</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>帐号状态:0正常,1禁用</a:Comment>
+<a:DefaultValue>0</a:DefaultValue>
+<a:DataType>char(1)</a:DataType>
+<a:Length>1</a:Length>
+</o:Column>
+<o:Column Id="o69">
+<a:ObjectID>7F851464-6CC5-445B-9413-2A89B9CE90CB</a:ObjectID>
+<a:Name>del_flag</a:Name>
+<a:Code>del_flag</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1538295948</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>拒绝登录描述</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>char(1)</a:DataType>
+<a:Length>1</a:Length>
+</o:Column>
+<o:Column Id="o70">
+<a:ObjectID>3DC8EC79-D75A-4BF8-8FBC-152E938AC14F</a:ObjectID>
+<a:Name>create_by</a:Name>
+<a:Code>create_by</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>创建者</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(64)</a:DataType>
+<a:Length>64</a:Length>
+</o:Column>
+<o:Column Id="o71">
+<a:ObjectID>48C8C936-7A34-4A97-AACA-A6F07751FFAD</a:ObjectID>
+<a:Name>create_time</a:Name>
+<a:Code>create_time</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>创建时间</a:Comment>
+<a:DataType>timestamp</a:DataType>
+</o:Column>
+<o:Column Id="o72">
+<a:ObjectID>6050B4F3-9B26-4B40-AB4C-BA483F179958</a:ObjectID>
+<a:Name>update_by</a:Name>
+<a:Code>update_by</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>更新者</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(64)</a:DataType>
+<a:Length>64</a:Length>
+</o:Column>
+<o:Column Id="o73">
+<a:ObjectID>CD1E7E11-8EB6-4C9C-A69C-39CBCF10573E</a:ObjectID>
+<a:Name>update_time</a:Name>
+<a:Code>update_time</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>更新时间</a:Comment>
+<a:DataType>timestamp</a:DataType>
+</o:Column>
+<o:Column Id="o74">
+<a:ObjectID>F9F55D4C-13E6-49A0-BFDB-E0AFE0FA5501</a:ObjectID>
+<a:Name>remark</a:Name>
+<a:Code>remark</a:Code>
+<a:CreationDate>1538295815</a:CreationDate>
+<a:Creator>admin</a:Creator>
+<a:ModificationDate>1538295948</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:DataType>varchar(500)</a:DataType>
+<a:Length>500</a:Length>
+</o:Column>
+</c:Columns>
+<c:Keys>
+<o:Key Id="o75">
+<a:ObjectID>2E35FD67-A7A7-4B10-85E4-85115AD0E143</a:ObjectID>
+<a:Name>Key_1</a:Name>
+<a:Code>Key_1</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<c:Key.Columns>
+<o:Column Ref="o57"/>
+</c:Key.Columns>
+</o:Key>
+</c:Keys>
+<c:PrimaryKey>
+<o:Key Ref="o75"/>
+</c:PrimaryKey>
+</o:Table>
+<o:Table Id="o10">
+<a:ObjectID>2711A520-532C-4F14-A034-BFF047C9CD6B</a:ObjectID>
+<a:Name>sys_post</a:Name>
+<a:Code>sys_post</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1538297571</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>岗位信息表</a:Comment>
+<a:TotalSavingCurrency/>
+<c:Columns>
+<o:Column Id="o76">
+<a:ObjectID>FB04D29E-41F0-49A3-BFDB-58E222843F21</a:ObjectID>
+<a:Name>post_id</a:Name>
+<a:Code>post_id</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>岗位ID</a:Comment>
+<a:DataType>int(11)</a:DataType>
+<a:Length>11</a:Length>
+<a:Identity>1</a:Identity>
+<a:Mandatory>1</a:Mandatory>
+</o:Column>
+<o:Column Id="o77">
+<a:ObjectID>50010C4E-4F59-47B9-8F08-05E8E071E8B1</a:ObjectID>
+<a:Name>post_code</a:Name>
+<a:Code>post_code</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>岗位编码</a:Comment>
+<a:DataType>varchar(64)</a:DataType>
+<a:Length>64</a:Length>
+<a:Mandatory>1</a:Mandatory>
+</o:Column>
+<o:Column Id="o78">
+<a:ObjectID>0F929250-051E-4344-B22A-C30E071A543B</a:ObjectID>
+<a:Name>post_name</a:Name>
+<a:Code>post_name</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>岗位名称</a:Comment>
+<a:DataType>varchar(100)</a:DataType>
+<a:Length>100</a:Length>
+<a:Mandatory>1</a:Mandatory>
+</o:Column>
+<o:Column Id="o79">
+<a:ObjectID>2BC9005E-350F-46BE-98D6-9B13060F1B20</a:ObjectID>
+<a:Name>post_sort</a:Name>
+<a:Code>post_sort</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>显示顺序</a:Comment>
+<a:DataType>int(4)</a:DataType>
+<a:Length>4</a:Length>
+<a:Mandatory>1</a:Mandatory>
+</o:Column>
+<o:Column Id="o80">
+<a:ObjectID>F6D7AD3E-5EA0-4759-B6BF-6334B7105B78</a:ObjectID>
+<a:Name>status</a:Name>
+<a:Code>status</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1538297565</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>状态(0正常 1停用)</a:Comment>
+<a:DataType>char(1)</a:DataType>
+<a:Length>1</a:Length>
+<a:Mandatory>1</a:Mandatory>
+</o:Column>
+<o:Column Id="o81">
+<a:ObjectID>CED01369-5063-479D-A444-32936369A486</a:ObjectID>
+<a:Name>create_by</a:Name>
+<a:Code>create_by</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>创建者</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(64)</a:DataType>
+<a:Length>64</a:Length>
+</o:Column>
+<o:Column Id="o82">
+<a:ObjectID>A29528FF-A2B9-4149-B997-1B0204D42E40</a:ObjectID>
+<a:Name>create_time</a:Name>
+<a:Code>create_time</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>创建时间</a:Comment>
+<a:DataType>timestamp</a:DataType>
+</o:Column>
+<o:Column Id="o83">
+<a:ObjectID>6026A05D-0C1E-497E-8EAF-FDB704BE6A52</a:ObjectID>
+<a:Name>update_by</a:Name>
+<a:Code>update_by</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>更新者</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(64)</a:DataType>
+<a:Length>64</a:Length>
+</o:Column>
+<o:Column Id="o84">
+<a:ObjectID>DF516F5F-CD82-4347-AC57-BDCB4E5DD75E</a:ObjectID>
+<a:Name>update_time</a:Name>
+<a:Code>update_time</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>更新时间</a:Comment>
+<a:DataType>timestamp</a:DataType>
+</o:Column>
+<o:Column Id="o85">
+<a:ObjectID>539CEC34-49F0-49A0-9B7C-B84655FD2233</a:ObjectID>
+<a:Name>remark</a:Name>
+<a:Code>remark</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>备注</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(500)</a:DataType>
+<a:Length>500</a:Length>
+</o:Column>
+</c:Columns>
+<c:Keys>
+<o:Key Id="o86">
+<a:ObjectID>14E893B1-D0BA-46A7-A905-F0FFA089B65A</a:ObjectID>
+<a:Name>Key_1</a:Name>
+<a:Code>Key_1</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<c:Key.Columns>
+<o:Column Ref="o76"/>
+</c:Key.Columns>
+</o:Key>
+</c:Keys>
+<c:PrimaryKey>
+<o:Key Ref="o86"/>
+</c:PrimaryKey>
+</o:Table>
+<o:Table Id="o12">
+<a:ObjectID>11337551-BA45-43CD-9148-92BE60E2F8F5</a:ObjectID>
+<a:Name>sys_role</a:Name>
+<a:Code>sys_role</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1538297608</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>角色信息表</a:Comment>
+<a:TotalSavingCurrency/>
+<c:Columns>
+<o:Column Id="o87">
+<a:ObjectID>A420E2C9-8FE3-452A-9047-C7BEACE8490C</a:ObjectID>
+<a:Name>role_id</a:Name>
+<a:Code>role_id</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>角色ID</a:Comment>
+<a:DataType>int(10)</a:DataType>
+<a:Length>10</a:Length>
+<a:Identity>1</a:Identity>
+<a:Mandatory>1</a:Mandatory>
+</o:Column>
+<o:Column Id="o88">
+<a:ObjectID>9342763D-5B89-4440-965B-2B55DB4ACD86</a:ObjectID>
+<a:Name>role_name</a:Name>
+<a:Code>role_name</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>角色名称</a:Comment>
+<a:DataType>varchar(30)</a:DataType>
+<a:Length>30</a:Length>
+<a:Mandatory>1</a:Mandatory>
+</o:Column>
+<o:Column Id="o89">
+<a:ObjectID>54480009-0C7E-40F2-AA76-CD914A6D66C5</a:ObjectID>
+<a:Name>role_key</a:Name>
+<a:Code>role_key</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>角色权限字符串</a:Comment>
+<a:DataType>varchar(100)</a:DataType>
+<a:Length>100</a:Length>
+<a:Mandatory>1</a:Mandatory>
+</o:Column>
+<o:Column Id="o90">
+<a:ObjectID>E73F4D0E-12A0-42B5-B3CE-B573D499DD6C</a:ObjectID>
+<a:Name>role_sort</a:Name>
+<a:Code>role_sort</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1538296031</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>显示顺序</a:Comment>
+<a:DataType>int(10)</a:DataType>
+<a:Length>10</a:Length>
+</o:Column>
+<o:Column Id="o91">
+<a:ObjectID>5F836F54-9EBD-4768-AA3C-F268F5FAFE8D</a:ObjectID>
+<a:Name>data_scope</a:Name>
+<a:Code>data_scope</a:Code>
+<a:CreationDate>1538295973</a:CreationDate>
+<a:Creator>admin</a:Creator>
+<a:ModificationDate>1538296031</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:DataType>char(1)</a:DataType>
+<a:Length>1</a:Length>
+</o:Column>
+<o:Column Id="o92">
+<a:ObjectID>424ED799-E4C1-44AD-A172-C2B3C405E9C5</a:ObjectID>
+<a:Name>status</a:Name>
+<a:Code>status</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1538297608</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>角色状态:0正常,1禁用</a:Comment>
+<a:DefaultValue>0</a:DefaultValue>
+<a:DataType>char(1)</a:DataType>
+<a:Length>1</a:Length>
+</o:Column>
+<o:Column Id="o93">
+<a:ObjectID>8E034C76-5966-4246-B81B-7B12F37D96A7</a:ObjectID>
+<a:Name>del_flag</a:Name>
+<a:Code>del_flag</a:Code>
+<a:CreationDate>1538295973</a:CreationDate>
+<a:Creator>admin</a:Creator>
+<a:ModificationDate>1538296031</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:DataType>char(1)</a:DataType>
+<a:Length>1</a:Length>
+</o:Column>
+<o:Column Id="o94">
+<a:ObjectID>214F6E1F-28B1-454B-ABF0-D1C43220129D</a:ObjectID>
+<a:Name>create_by</a:Name>
+<a:Code>create_by</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>创建者</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(64)</a:DataType>
+<a:Length>64</a:Length>
+</o:Column>
+<o:Column Id="o95">
+<a:ObjectID>1A6D5791-0353-4ABC-8BC2-921BB87A2E5A</a:ObjectID>
+<a:Name>create_time</a:Name>
+<a:Code>create_time</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>创建时间</a:Comment>
+<a:DataType>timestamp</a:DataType>
+</o:Column>
+<o:Column Id="o96">
+<a:ObjectID>D6394880-A49C-4B83-B43A-5FDBAA918AA3</a:ObjectID>
+<a:Name>update_by</a:Name>
+<a:Code>update_by</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>更新者</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(64)</a:DataType>
+<a:Length>64</a:Length>
+</o:Column>
+<o:Column Id="o97">
+<a:ObjectID>34285DF5-8E36-452B-A3AA-9F4290C20F7E</a:ObjectID>
+<a:Name>update_time</a:Name>
+<a:Code>update_time</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>更新时间</a:Comment>
+<a:DataType>timestamp</a:DataType>
+</o:Column>
+<o:Column Id="o98">
+<a:ObjectID>2FAB98F7-68A2-460B-8A20-5D5DA73F5103</a:ObjectID>
+<a:Name>remark</a:Name>
+<a:Code>remark</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>备注</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(500)</a:DataType>
+<a:Length>500</a:Length>
+</o:Column>
+</c:Columns>
+<c:Keys>
+<o:Key Id="o99">
+<a:ObjectID>4342E67F-D33C-435F-9865-973E053B6075</a:ObjectID>
+<a:Name>Key_1</a:Name>
+<a:Code>Key_1</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<c:Key.Columns>
+<o:Column Ref="o87"/>
+</c:Key.Columns>
+</o:Key>
+</c:Keys>
+<c:PrimaryKey>
+<o:Key Ref="o99"/>
+</c:PrimaryKey>
+</o:Table>
+<o:Table Id="o14">
+<a:ObjectID>FBC2A590-443B-43C9-82D5-687B850C8B3D</a:ObjectID>
+<a:Name>sys_menu</a:Name>
+<a:Code>sys_menu</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1538297627</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>菜单权限表</a:Comment>
+<a:TotalSavingCurrency/>
+<c:Columns>
+<o:Column Id="o100">
+<a:ObjectID>BB061292-3B99-432E-9B96-5362AAD918B9</a:ObjectID>
+<a:Name>menu_id</a:Name>
+<a:Code>menu_id</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>菜单ID</a:Comment>
+<a:DataType>int(11)</a:DataType>
+<a:Length>11</a:Length>
+<a:Identity>1</a:Identity>
+<a:Mandatory>1</a:Mandatory>
+</o:Column>
+<o:Column Id="o101">
+<a:ObjectID>EA8422AB-37B1-4D60-A3C9-A4BF9039A9D4</a:ObjectID>
+<a:Name>menu_name</a:Name>
+<a:Code>menu_name</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>菜单名称</a:Comment>
+<a:DataType>varchar(50)</a:DataType>
+<a:Length>50</a:Length>
+<a:Mandatory>1</a:Mandatory>
+</o:Column>
+<o:Column Id="o102">
+<a:ObjectID>E56E04A8-63F6-4271-92E3-974DC84DD536</a:ObjectID>
+<a:Name>parent_id</a:Name>
+<a:Code>parent_id</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>父菜单ID</a:Comment>
+<a:DefaultValue>0</a:DefaultValue>
+<a:DataType>int(11)</a:DataType>
+<a:Length>11</a:Length>
+</o:Column>
+<o:Column Id="o103">
+<a:ObjectID>1809914E-6B09-4CD2-8916-E603D6717557</a:ObjectID>
+<a:Name>order_num</a:Name>
+<a:Code>order_num</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>显示顺序</a:Comment>
+<a:DefaultValue>NULL</a:DefaultValue>
+<a:DataType>int(4)</a:DataType>
+<a:Length>4</a:Length>
+</o:Column>
+<o:Column Id="o104">
+<a:ObjectID>FCB44D46-3C21-40CB-B942-57823E52E5B1</a:ObjectID>
+<a:Name>url</a:Name>
+<a:Code>url</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>请求地址</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(200)</a:DataType>
+<a:Length>200</a:Length>
+</o:Column>
+<o:Column Id="o105">
+<a:ObjectID>667EE044-6805-4668-BAF4-E78B3052051F</a:ObjectID>
+<a:Name>menu_type</a:Name>
+<a:Code>menu_type</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>类型:M目录,C菜单,F按钮</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>char(1)</a:DataType>
+<a:Length>1</a:Length>
+</o:Column>
+<o:Column Id="o106">
+<a:ObjectID>F7658083-BCAB-46F7-AF31-8A4B1D8749EF</a:ObjectID>
+<a:Name>visible</a:Name>
+<a:Code>visible</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1538297627</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>菜单状态:0显示,1隐藏</a:Comment>
+<a:DefaultValue>0</a:DefaultValue>
+<a:DataType>char(1)</a:DataType>
+<a:Length>1</a:Length>
+</o:Column>
+<o:Column Id="o107">
+<a:ObjectID>528611C8-C319-430F-8F00-68FBA60F310B</a:ObjectID>
+<a:Name>perms</a:Name>
+<a:Code>perms</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>权限标识</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(100)</a:DataType>
+<a:Length>100</a:Length>
+</o:Column>
+<o:Column Id="o108">
+<a:ObjectID>38004CD7-8DD0-43F1-9E59-B50132CB6F1A</a:ObjectID>
+<a:Name>icon</a:Name>
+<a:Code>icon</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>菜单图标</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(100)</a:DataType>
+<a:Length>100</a:Length>
+</o:Column>
+<o:Column Id="o109">
+<a:ObjectID>6927665F-EC42-4E1F-A275-4B27F442B6B8</a:ObjectID>
+<a:Name>create_by</a:Name>
+<a:Code>create_by</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>创建者</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(64)</a:DataType>
+<a:Length>64</a:Length>
+</o:Column>
+<o:Column Id="o110">
+<a:ObjectID>1A6A4D0F-0B0B-4522-B4DA-3F1D592CB889</a:ObjectID>
+<a:Name>create_time</a:Name>
+<a:Code>create_time</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>创建时间</a:Comment>
+<a:DataType>timestamp</a:DataType>
+</o:Column>
+<o:Column Id="o111">
+<a:ObjectID>605D7776-4820-4BA9-91E8-AD837B73AEFB</a:ObjectID>
+<a:Name>update_by</a:Name>
+<a:Code>update_by</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>更新者</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(64)</a:DataType>
+<a:Length>64</a:Length>
+</o:Column>
+<o:Column Id="o112">
+<a:ObjectID>4CFF26BB-8736-4864-855E-C7C1B133370B</a:ObjectID>
+<a:Name>update_time</a:Name>
+<a:Code>update_time</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>更新时间</a:Comment>
+<a:DataType>timestamp</a:DataType>
+</o:Column>
+<o:Column Id="o113">
+<a:ObjectID>67C6E46C-DF06-480A-BC74-E927406E5D26</a:ObjectID>
+<a:Name>remark</a:Name>
+<a:Code>remark</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>备注</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(500)</a:DataType>
+<a:Length>500</a:Length>
+</o:Column>
+</c:Columns>
+<c:Keys>
+<o:Key Id="o114">
+<a:ObjectID>08EBE713-9E4D-4312-AA7D-2E4E439734E5</a:ObjectID>
+<a:Name>Key_1</a:Name>
+<a:Code>Key_1</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<c:Key.Columns>
+<o:Column Ref="o100"/>
+</c:Key.Columns>
+</o:Key>
+</c:Keys>
+<c:PrimaryKey>
+<o:Key Ref="o114"/>
+</c:PrimaryKey>
+</o:Table>
+<o:Table Id="o16">
+<a:ObjectID>F8CB66D1-3632-4509-97C4-17016BE261FC</a:ObjectID>
+<a:Name>sys_user_role</a:Name>
+<a:Code>sys_user_role</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1538297676</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>用户和角色关联表</a:Comment>
+<a:TotalSavingCurrency/>
+<c:Columns>
+<o:Column Id="o115">
+<a:ObjectID>73701F72-C45B-4CA0-8A62-632890E3DEF0</a:ObjectID>
+<a:Name>user_id</a:Name>
+<a:Code>user_id</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>用户ID</a:Comment>
+<a:DataType>int(11)</a:DataType>
+<a:Length>11</a:Length>
+<a:Mandatory>1</a:Mandatory>
+</o:Column>
+<o:Column Id="o116">
+<a:ObjectID>CABD458B-DA59-46A8-99C3-088AD8D34097</a:ObjectID>
+<a:Name>role_id</a:Name>
+<a:Code>role_id</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>角色ID</a:Comment>
+<a:DataType>int(11)</a:DataType>
+<a:Length>11</a:Length>
+<a:Mandatory>1</a:Mandatory>
+</o:Column>
+</c:Columns>
+<c:Keys>
+<o:Key Id="o117">
+<a:ObjectID>37C3213B-EF22-4CD4-A91F-9A9A2503FB2A</a:ObjectID>
+<a:Name>Key_1</a:Name>
+<a:Code>Key_1</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<c:Key.Columns>
+<o:Column Ref="o115"/>
+<o:Column Ref="o116"/>
+</c:Key.Columns>
+</o:Key>
+</c:Keys>
+<c:PrimaryKey>
+<o:Key Ref="o117"/>
+</c:PrimaryKey>
+</o:Table>
+<o:Table Id="o18">
+<a:ObjectID>9F8C6A9F-3221-410E-AEA4-D1A80026397E</a:ObjectID>
+<a:Name>sys_role_menu</a:Name>
+<a:Code>sys_role_menu</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1538297683</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>角色和菜单关联表</a:Comment>
+<a:TotalSavingCurrency/>
+<c:Columns>
+<o:Column Id="o118">
+<a:ObjectID>D2E151A5-6156-46EF-844E-0ADC3070293B</a:ObjectID>
+<a:Name>role_id</a:Name>
+<a:Code>role_id</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>角色ID</a:Comment>
+<a:DataType>int(11)</a:DataType>
+<a:Length>11</a:Length>
+<a:Mandatory>1</a:Mandatory>
+</o:Column>
+<o:Column Id="o119">
+<a:ObjectID>6B8C1E62-FD8B-4504-8FA0-F69917722FBD</a:ObjectID>
+<a:Name>menu_id</a:Name>
+<a:Code>menu_id</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>菜单ID</a:Comment>
+<a:DataType>int(11)</a:DataType>
+<a:Length>11</a:Length>
+<a:Mandatory>1</a:Mandatory>
+</o:Column>
+</c:Columns>
+<c:Keys>
+<o:Key Id="o120">
+<a:ObjectID>2E72304F-91F0-4392-BAE8-BBF7A4346B7D</a:ObjectID>
+<a:Name>Key_1</a:Name>
+<a:Code>Key_1</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<c:Key.Columns>
+<o:Column Ref="o118"/>
+<o:Column Ref="o119"/>
+</c:Key.Columns>
+</o:Key>
+</c:Keys>
+<c:PrimaryKey>
+<o:Key Ref="o120"/>
+</c:PrimaryKey>
+</o:Table>
+<o:Table Id="o20">
+<a:ObjectID>726CB18E-7D5B-4E2E-9CF8-047AD5AF89E3</a:ObjectID>
+<a:Name>sys_user_post</a:Name>
+<a:Code>sys_user_post</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1538297694</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>用户与岗位关联表</a:Comment>
+<a:TotalSavingCurrency/>
+<c:Columns>
+<o:Column Id="o121">
+<a:ObjectID>E4A1CAB6-0F63-4917-ACEF-418DE7F894BA</a:ObjectID>
+<a:Name>user_id</a:Name>
+<a:Code>user_id</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1538296306</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>用户ID</a:Comment>
+<a:DataType>int(11)</a:DataType>
+<a:Length>11</a:Length>
+<a:Mandatory>1</a:Mandatory>
+</o:Column>
+<o:Column Id="o122">
+<a:ObjectID>8E7188D5-B3A5-4F1D-B6CB-D77D652414DE</a:ObjectID>
+<a:Name>post_id</a:Name>
+<a:Code>post_id</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1538296306</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>岗位ID</a:Comment>
+<a:DataType>int(11)</a:DataType>
+<a:Length>11</a:Length>
+<a:Mandatory>1</a:Mandatory>
+</o:Column>
+</c:Columns>
+<c:Keys>
+<o:Key Id="o123">
+<a:ObjectID>4091B7D3-2404-4C20-BBCD-B63E22A5E960</a:ObjectID>
+<a:Name>Key_1</a:Name>
+<a:Code>Key_1</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<c:Key.Columns>
+<o:Column Ref="o121"/>
+<o:Column Ref="o122"/>
+</c:Key.Columns>
+</o:Key>
+</c:Keys>
+<c:PrimaryKey>
+<o:Key Ref="o123"/>
+</c:PrimaryKey>
+</o:Table>
+<o:Table Id="o22">
+<a:ObjectID>FE347A45-D8EC-423B-9B38-4D315A3ABE42</a:ObjectID>
+<a:Name>sys_oper_log</a:Name>
+<a:Code>sys_oper_log</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1538297699</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>操作日志记录</a:Comment>
+<a:TotalSavingCurrency/>
+<c:Columns>
+<o:Column Id="o124">
+<a:ObjectID>F5FC8AC1-7415-4A57-BA2C-EE2E7B9E1EFC</a:ObjectID>
+<a:Name>oper_id</a:Name>
+<a:Code>oper_id</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>日志主键</a:Comment>
+<a:DataType>int(11)</a:DataType>
+<a:Length>11</a:Length>
+<a:Identity>1</a:Identity>
+<a:Mandatory>1</a:Mandatory>
+</o:Column>
+<o:Column Id="o125">
+<a:ObjectID>2103BC5C-E28D-4369-8369-E898B218587A</a:ObjectID>
+<a:Name>title</a:Name>
+<a:Code>title</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>模块标题</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(50)</a:DataType>
+<a:Length>50</a:Length>
+</o:Column>
+<o:Column Id="o126">
+<a:ObjectID>6816377B-3DB6-424A-99ED-1D20FEB30ED4</a:ObjectID>
+<a:Name>business_type</a:Name>
+<a:Code>business_type</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1538296397</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>功能请求</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>int(2)</a:DataType>
+<a:Length>2</a:Length>
+</o:Column>
+<o:Column Id="o127">
+<a:ObjectID>9CA3B7C3-F52C-4E2E-893F-8E6EBA7B2667</a:ObjectID>
+<a:Name>method</a:Name>
+<a:Code>method</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>方法名称</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(100)</a:DataType>
+<a:Length>100</a:Length>
+</o:Column>
+<o:Column Id="o128">
+<a:ObjectID>A5744803-C050-4108-9D15-7A0B95F03642</a:ObjectID>
+<a:Name>operator_type</a:Name>
+<a:Code>operator_type</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1538296397</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>来源渠道</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>int(1)</a:DataType>
+<a:Length>1</a:Length>
+</o:Column>
+<o:Column Id="o129">
+<a:ObjectID>B0DF8235-6BC1-452C-8B30-A56F0430E4F5</a:ObjectID>
+<a:Name>oper_name</a:Name>
+<a:Code>oper_name</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1538296397</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>登录账号</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(50)</a:DataType>
+<a:Length>50</a:Length>
+</o:Column>
+<o:Column Id="o130">
+<a:ObjectID>25315A12-4EB9-4B67-9E2C-9F40F8EF7FAB</a:ObjectID>
+<a:Name>dept_name</a:Name>
+<a:Code>dept_name</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>部门名称</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(50)</a:DataType>
+<a:Length>50</a:Length>
+</o:Column>
+<o:Column Id="o131">
+<a:ObjectID>7AF8602B-A1DA-4EA3-BFB2-7638F96A86C0</a:ObjectID>
+<a:Name>oper_url</a:Name>
+<a:Code>oper_url</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>请求URL</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(255)</a:DataType>
+<a:Length>255</a:Length>
+</o:Column>
+<o:Column Id="o132">
+<a:ObjectID>F2A56B63-7A56-43FA-8099-411F3578B30D</a:ObjectID>
+<a:Name>oper_ip</a:Name>
+<a:Code>oper_ip</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>主机地址</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(30)</a:DataType>
+<a:Length>30</a:Length>
+</o:Column>
+<o:Column Id="o133">
+<a:ObjectID>1EF1BAF6-F5C1-496C-98E0-8B10C37279A1</a:ObjectID>
+<a:Name>oper_param</a:Name>
+<a:Code>oper_param</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>请求参数</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(255)</a:DataType>
+<a:Length>255</a:Length>
+</o:Column>
+<o:Column Id="o134">
+<a:ObjectID>AA3F3A4E-D375-4232-B152-01DCFB8F6B6D</a:ObjectID>
+<a:Name>status</a:Name>
+<a:Code>status</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>操作状态 0正常 1异常</a:Comment>
+<a:DefaultValue>0</a:DefaultValue>
+<a:DataType>int(1)</a:DataType>
+<a:Length>1</a:Length>
+</o:Column>
+<o:Column Id="o135">
+<a:ObjectID>29E44D4A-6AC7-4220-A502-4BFC8746397A</a:ObjectID>
+<a:Name>error_msg</a:Name>
+<a:Code>error_msg</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>错误消息</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(2000)</a:DataType>
+<a:Length>2000</a:Length>
+</o:Column>
+<o:Column Id="o136">
+<a:ObjectID>22343C35-D913-485B-862E-2CEF579AAF22</a:ObjectID>
+<a:Name>oper_time</a:Name>
+<a:Code>oper_time</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>操作时间</a:Comment>
+<a:DataType>timestamp</a:DataType>
+</o:Column>
+</c:Columns>
+<c:Keys>
+<o:Key Id="o137">
+<a:ObjectID>C0561C20-CC22-471B-A764-414C0D378FD6</a:ObjectID>
+<a:Name>Key_1</a:Name>
+<a:Code>Key_1</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<c:Key.Columns>
+<o:Column Ref="o124"/>
+</c:Key.Columns>
+</o:Key>
+</c:Keys>
+<c:PrimaryKey>
+<o:Key Ref="o137"/>
+</c:PrimaryKey>
+</o:Table>
+<o:Table Id="o24">
+<a:ObjectID>AA2CFBA5-FA97-4AF1-92FE-645370B5848D</a:ObjectID>
+<a:Name>sys_dict_type</a:Name>
+<a:Code>sys_dict_type</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1538297703</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>字典类型表</a:Comment>
+<a:TotalSavingCurrency/>
+<c:Columns>
+<o:Column Id="o138">
+<a:ObjectID>79CB7D43-B999-4D92-9477-D3AFEBD94248</a:ObjectID>
+<a:Name>dict_id</a:Name>
+<a:Code>dict_id</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>字典主键</a:Comment>
+<a:DataType>int(11)</a:DataType>
+<a:Length>11</a:Length>
+<a:Identity>1</a:Identity>
+<a:Mandatory>1</a:Mandatory>
+</o:Column>
+<o:Column Id="o139">
+<a:ObjectID>2490B755-3E0A-4935-97F0-2EFDF9A72D05</a:ObjectID>
+<a:Name>dict_name</a:Name>
+<a:Code>dict_name</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>字典名称</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(100)</a:DataType>
+<a:Length>100</a:Length>
+</o:Column>
+<o:Column Id="o140">
+<a:ObjectID>7421238A-82DB-4992-AA28-41726AB6A5D6</a:ObjectID>
+<a:Name>dict_type</a:Name>
+<a:Code>dict_type</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>字典类型</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(100)</a:DataType>
+<a:Length>100</a:Length>
+</o:Column>
+<o:Column Id="o141">
+<a:ObjectID>971D2FBD-1A24-4EE4-B943-9367609C7472</a:ObjectID>
+<a:Name>status</a:Name>
+<a:Code>status</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1538296458</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>状态(0正常 1禁用)</a:Comment>
+<a:DefaultValue>0</a:DefaultValue>
+<a:DataType>char(1)</a:DataType>
+<a:Length>1</a:Length>
+</o:Column>
+<o:Column Id="o142">
+<a:ObjectID>B8876246-5BBA-4A03-86D7-98CA4EBEE342</a:ObjectID>
+<a:Name>create_by</a:Name>
+<a:Code>create_by</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>创建者</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(64)</a:DataType>
+<a:Length>64</a:Length>
+</o:Column>
+<o:Column Id="o143">
+<a:ObjectID>5237CED2-0853-41DE-ACF4-BE442BC9E112</a:ObjectID>
+<a:Name>create_time</a:Name>
+<a:Code>create_time</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>创建时间</a:Comment>
+<a:DataType>timestamp</a:DataType>
+</o:Column>
+<o:Column Id="o144">
+<a:ObjectID>2CACFBC0-8349-4B3A-9183-208B18C9F56F</a:ObjectID>
+<a:Name>update_by</a:Name>
+<a:Code>update_by</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>更新者</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(64)</a:DataType>
+<a:Length>64</a:Length>
+</o:Column>
+<o:Column Id="o145">
+<a:ObjectID>ABEE7806-4F61-4B97-980C-CA081F61CA7C</a:ObjectID>
+<a:Name>update_time</a:Name>
+<a:Code>update_time</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>更新时间</a:Comment>
+<a:DataType>timestamp</a:DataType>
+</o:Column>
+<o:Column Id="o146">
+<a:ObjectID>3966B558-B911-45DE-86C6-57F3DB9267BA</a:ObjectID>
+<a:Name>remark</a:Name>
+<a:Code>remark</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>备注</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(500)</a:DataType>
+<a:Length>500</a:Length>
+</o:Column>
+<o:Column Id="o147">
+<a:ObjectID>AFC0A0ED-A469-40B2-A6C4-4616444830AA</a:ObjectID>
+<a:Name>unique</a:Name>
+<a:Code>unique</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:DataType>(dict_type)</a:DataType>
+</o:Column>
+</c:Columns>
+<c:Keys>
+<o:Key Id="o148">
+<a:ObjectID>BAD40D8E-BC11-44F5-918E-B27CABBCB051</a:ObjectID>
+<a:Name>Key_1</a:Name>
+<a:Code>Key_1</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<c:Key.Columns>
+<o:Column Ref="o138"/>
+</c:Key.Columns>
+</o:Key>
+</c:Keys>
+<c:PrimaryKey>
+<o:Key Ref="o148"/>
+</c:PrimaryKey>
+</o:Table>
+<o:Table Id="o26">
+<a:ObjectID>493D6B25-21D0-45B1-BBA0-764B9C09B57D</a:ObjectID>
+<a:Name>sys_dict_data</a:Name>
+<a:Code>sys_dict_data</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1538297709</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>字典数据表</a:Comment>
+<a:TotalSavingCurrency/>
+<c:Columns>
+<o:Column Id="o149">
+<a:ObjectID>CFDB23A8-AE38-4051-973A-2DABAC8283F9</a:ObjectID>
+<a:Name>dict_code</a:Name>
+<a:Code>dict_code</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>字典编码</a:Comment>
+<a:DataType>int(11)</a:DataType>
+<a:Length>11</a:Length>
+<a:Identity>1</a:Identity>
+<a:Mandatory>1</a:Mandatory>
+</o:Column>
+<o:Column Id="o150">
+<a:ObjectID>EAA405BD-12A8-472F-A42D-CDA6A82E291A</a:ObjectID>
+<a:Name>dict_sort</a:Name>
+<a:Code>dict_sort</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>字典排序</a:Comment>
+<a:DefaultValue>0</a:DefaultValue>
+<a:DataType>int(4)</a:DataType>
+<a:Length>4</a:Length>
+</o:Column>
+<o:Column Id="o151">
+<a:ObjectID>F13017F5-2AA0-4DE9-9DC2-A9A3D73A98E6</a:ObjectID>
+<a:Name>dict_label</a:Name>
+<a:Code>dict_label</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>字典标签</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(100)</a:DataType>
+<a:Length>100</a:Length>
+</o:Column>
+<o:Column Id="o152">
+<a:ObjectID>EEEC4136-823D-4892-9BB9-BB0B4ADD83E3</a:ObjectID>
+<a:Name>dict_value</a:Name>
+<a:Code>dict_value</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>字典键值</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(100)</a:DataType>
+<a:Length>100</a:Length>
+</o:Column>
+<o:Column Id="o153">
+<a:ObjectID>ADF5A383-D055-40BE-BBFC-06E2B93D4E6A</a:ObjectID>
+<a:Name>dict_type</a:Name>
+<a:Code>dict_type</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>字典类型</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(100)</a:DataType>
+<a:Length>100</a:Length>
+</o:Column>
+<o:Column Id="o154">
+<a:ObjectID>A0B2DDF2-251D-4701-9B00-6893C74CC449</a:ObjectID>
+<a:Name>css_class</a:Name>
+<a:Code>css_class</a:Code>
+<a:CreationDate>1538296497</a:CreationDate>
+<a:Creator>admin</a:Creator>
+<a:ModificationDate>1538296556</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:DataType>varchar(100)</a:DataType>
+<a:Length>100</a:Length>
+</o:Column>
+<o:Column Id="o155">
+<a:ObjectID>3CBFBA8E-7609-458D-9E53-A825C3F307A2</a:ObjectID>
+<a:Name>list_class</a:Name>
+<a:Code>list_class</a:Code>
+<a:CreationDate>1538296497</a:CreationDate>
+<a:Creator>admin</a:Creator>
+<a:ModificationDate>1538296556</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:DataType>varchar(100)</a:DataType>
+<a:Length>100</a:Length>
+</o:Column>
+<o:Column Id="o156">
+<a:ObjectID>BA974839-DEE0-4684-BBEF-6D7776C34354</a:ObjectID>
+<a:Name>is_default</a:Name>
+<a:Code>is_default</a:Code>
+<a:CreationDate>1538296497</a:CreationDate>
+<a:Creator>admin</a:Creator>
+<a:ModificationDate>1538296556</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:DataType>char(1)</a:DataType>
+<a:Length>1</a:Length>
+</o:Column>
+<o:Column Id="o157">
+<a:ObjectID>1676CDF5-01CA-4749-BA1D-6E5399257BD0</a:ObjectID>
+<a:Name>status</a:Name>
+<a:Code>status</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>状态(0正常 1禁用)</a:Comment>
+<a:DefaultValue>0</a:DefaultValue>
+<a:DataType>int(1)</a:DataType>
+<a:Length>1</a:Length>
+</o:Column>
+<o:Column Id="o158">
+<a:ObjectID>8798B094-1AAF-4A23-B2F1-4C19DACF1AA3</a:ObjectID>
+<a:Name>create_by</a:Name>
+<a:Code>create_by</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>创建者</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(64)</a:DataType>
+<a:Length>64</a:Length>
+</o:Column>
+<o:Column Id="o159">
+<a:ObjectID>D1CB9293-D762-403C-85CB-4B974ACF7328</a:ObjectID>
+<a:Name>create_time</a:Name>
+<a:Code>create_time</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>创建时间</a:Comment>
+<a:DataType>timestamp</a:DataType>
+</o:Column>
+<o:Column Id="o160">
+<a:ObjectID>5A34AF87-B25E-4349-9713-69DC50F6F5F2</a:ObjectID>
+<a:Name>update_by</a:Name>
+<a:Code>update_by</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>更新者</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(64)</a:DataType>
+<a:Length>64</a:Length>
+</o:Column>
+<o:Column Id="o161">
+<a:ObjectID>3204FBAC-1F61-4571-ADC4-BF1BE9CED85A</a:ObjectID>
+<a:Name>update_time</a:Name>
+<a:Code>update_time</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>更新时间</a:Comment>
+<a:DataType>timestamp</a:DataType>
+</o:Column>
+<o:Column Id="o162">
+<a:ObjectID>B7DE1842-809C-4401-9C80-C9A37DF9B053</a:ObjectID>
+<a:Name>remark</a:Name>
+<a:Code>remark</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>备注</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(500)</a:DataType>
+<a:Length>500</a:Length>
+</o:Column>
+</c:Columns>
+<c:Keys>
+<o:Key Id="o163">
+<a:ObjectID>2809F417-7FA5-48DA-B613-662C7C28061E</a:ObjectID>
+<a:Name>Key_1</a:Name>
+<a:Code>Key_1</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<c:Key.Columns>
+<o:Column Ref="o149"/>
+</c:Key.Columns>
+</o:Key>
+</c:Keys>
+<c:PrimaryKey>
+<o:Key Ref="o163"/>
+</c:PrimaryKey>
+</o:Table>
+<o:Table Id="o28">
+<a:ObjectID>0A7C2F56-6E3B-4E70-A549-0EC60779D180</a:ObjectID>
+<a:Name>sys_logininfor</a:Name>
+<a:Code>sys_logininfor</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1538297756</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>系统访问记录</a:Comment>
+<a:TotalSavingCurrency/>
+<c:Columns>
+<o:Column Id="o164">
+<a:ObjectID>5CB5D942-D52B-487D-BC86-476481B0FB8D</a:ObjectID>
+<a:Name>info_id</a:Name>
+<a:Code>info_id</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>访问ID</a:Comment>
+<a:DataType>int(11)</a:DataType>
+<a:Length>11</a:Length>
+<a:Identity>1</a:Identity>
+<a:Mandatory>1</a:Mandatory>
+</o:Column>
+<o:Column Id="o165">
+<a:ObjectID>A1C66DBC-9DB7-428B-9275-3D014B6CE388</a:ObjectID>
+<a:Name>login_name</a:Name>
+<a:Code>login_name</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>登录账号</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(50)</a:DataType>
+<a:Length>50</a:Length>
+</o:Column>
+<o:Column Id="o166">
+<a:ObjectID>8E0F50A6-F98D-48B0-8D9D-78F3A76ED171</a:ObjectID>
+<a:Name>ipaddr</a:Name>
+<a:Code>ipaddr</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>登录IP地址</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(50)</a:DataType>
+<a:Length>50</a:Length>
+</o:Column>
+<o:Column Id="o167">
+<a:ObjectID>91B70723-1A7E-4277-A100-63B775A504B3</a:ObjectID>
+<a:Name>login_location</a:Name>
+<a:Code>login_location</a:Code>
+<a:CreationDate>1538297350</a:CreationDate>
+<a:Creator>admin</a:Creator>
+<a:ModificationDate>1538297369</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:DataType>varchar(255)</a:DataType>
+<a:Length>255</a:Length>
+</o:Column>
+<o:Column Id="o168">
+<a:ObjectID>AA04F533-A044-428B-80F8-515B6BB1A302</a:ObjectID>
+<a:Name>browser</a:Name>
+<a:Code>browser</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>浏览器类型</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(50)</a:DataType>
+<a:Length>50</a:Length>
+</o:Column>
+<o:Column Id="o169">
+<a:ObjectID>D37570E9-9EEE-4349-B875-494A5415C736</a:ObjectID>
+<a:Name>os</a:Name>
+<a:Code>os</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>操作系统</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(50)</a:DataType>
+<a:Length>50</a:Length>
+</o:Column>
+<o:Column Id="o170">
+<a:ObjectID>CF10A80C-123E-42F3-A2DD-1B770E5F9D86</a:ObjectID>
+<a:Name>status</a:Name>
+<a:Code>status</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>登录状态 0成功 1失败</a:Comment>
+<a:DefaultValue>0</a:DefaultValue>
+<a:DataType>int(1)</a:DataType>
+<a:Length>1</a:Length>
+</o:Column>
+<o:Column Id="o171">
+<a:ObjectID>9113784E-932A-4FAF-82CB-A75B8C827309</a:ObjectID>
+<a:Name>msg</a:Name>
+<a:Code>msg</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>提示消息</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(255)</a:DataType>
+<a:Length>255</a:Length>
+</o:Column>
+<o:Column Id="o172">
+<a:ObjectID>BCA519C6-19C9-45DF-A0B5-F88E9E6D3557</a:ObjectID>
+<a:Name>login_time</a:Name>
+<a:Code>login_time</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>访问时间</a:Comment>
+<a:DataType>timestamp</a:DataType>
+</o:Column>
+</c:Columns>
+<c:Keys>
+<o:Key Id="o173">
+<a:ObjectID>C14E656C-0645-49EB-8B42-AD82232E0416</a:ObjectID>
+<a:Name>Key_1</a:Name>
+<a:Code>Key_1</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<c:Key.Columns>
+<o:Column Ref="o164"/>
+</c:Key.Columns>
+</o:Key>
+</c:Keys>
+<c:PrimaryKey>
+<o:Key Ref="o173"/>
+</c:PrimaryKey>
+</o:Table>
+<o:Table Id="o30">
+<a:ObjectID>4DCA223F-E98B-4D8B-A71C-CFB438C15488</a:ObjectID>
+<a:Name>sys_user_online</a:Name>
+<a:Code>sys_user_online</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1538297754</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>在线用户记录</a:Comment>
+<a:TotalSavingCurrency/>
+<c:Columns>
+<o:Column Id="o174">
+<a:ObjectID>7FCC57CE-47DD-4948-B949-10401B2FC7B1</a:ObjectID>
+<a:Name>sessionId</a:Name>
+<a:Code>sessionId</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>用户会话id</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(50)</a:DataType>
+<a:Length>50</a:Length>
+<a:Mandatory>1</a:Mandatory>
+</o:Column>
+<o:Column Id="o175">
+<a:ObjectID>FDE5B59D-8CF7-4AAE-987F-3FF2AEBE22CB</a:ObjectID>
+<a:Name>login_name</a:Name>
+<a:Code>login_name</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>登录账号</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(50)</a:DataType>
+<a:Length>50</a:Length>
+</o:Column>
+<o:Column Id="o176">
+<a:ObjectID>AB65FF92-33A0-42C8-8B3F-454A1FAD5615</a:ObjectID>
+<a:Name>dept_name</a:Name>
+<a:Code>dept_name</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>部门名称</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(50)</a:DataType>
+<a:Length>50</a:Length>
+</o:Column>
+<o:Column Id="o177">
+<a:ObjectID>C4DAF2D0-9CDC-476B-A011-FF5D302371EB</a:ObjectID>
+<a:Name>ipaddr</a:Name>
+<a:Code>ipaddr</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>登录IP地址</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(50)</a:DataType>
+<a:Length>50</a:Length>
+</o:Column>
+<o:Column Id="o178">
+<a:ObjectID>C8243FB0-425B-4A74-9ADA-C93B15E713EA</a:ObjectID>
+<a:Name>login_location</a:Name>
+<a:Code>login_location</a:Code>
+<a:CreationDate>1538297178</a:CreationDate>
+<a:Creator>admin</a:Creator>
+<a:ModificationDate>1538297216</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:DataType>varchar(255)</a:DataType>
+<a:Length>255</a:Length>
+</o:Column>
+<o:Column Id="o179">
+<a:ObjectID>89EC40B0-0C22-4811-90BB-BEA385ACDF20</a:ObjectID>
+<a:Name>browser</a:Name>
+<a:Code>browser</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>浏览器类型</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(50)</a:DataType>
+<a:Length>50</a:Length>
+</o:Column>
+<o:Column Id="o180">
+<a:ObjectID>AC455631-CFE0-45BB-A0C5-788D695E4B6C</a:ObjectID>
+<a:Name>os</a:Name>
+<a:Code>os</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>操作系统</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(50)</a:DataType>
+<a:Length>50</a:Length>
+</o:Column>
+<o:Column Id="o181">
+<a:ObjectID>5C56E3C9-4591-4762-89E1-C9BBFECB5F11</a:ObjectID>
+<a:Name>status</a:Name>
+<a:Code>status</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>在线状态on_line在线off_line离线</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(10)</a:DataType>
+<a:Length>10</a:Length>
+</o:Column>
+<o:Column Id="o182">
+<a:ObjectID>0CAF2F1F-459F-4F78-9075-D95F924A4FF7</a:ObjectID>
+<a:Name>start_timestamp</a:Name>
+<a:Code>start_timestamp</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>session创建时间</a:Comment>
+<a:DataType>timestamp</a:DataType>
+</o:Column>
+<o:Column Id="o183">
+<a:ObjectID>6AE6BDED-823E-4455-9A9F-338EC6F7BDB9</a:ObjectID>
+<a:Name>last_access_time</a:Name>
+<a:Code>last_access_time</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>session最后访问时间</a:Comment>
+<a:DataType>timestamp</a:DataType>
+</o:Column>
+<o:Column Id="o184">
+<a:ObjectID>CE390924-4628-421C-979F-002C2952E99E</a:ObjectID>
+<a:Name>expire_time</a:Name>
+<a:Code>expire_time</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>超时时间,单位为分钟</a:Comment>
+<a:DefaultValue>0</a:DefaultValue>
+<a:DataType>int(5)</a:DataType>
+<a:Length>5</a:Length>
+</o:Column>
+</c:Columns>
+<c:Keys>
+<o:Key Id="o185">
+<a:ObjectID>365CC94D-6124-42C7-96BD-376B84B709F7</a:ObjectID>
+<a:Name>Key_1</a:Name>
+<a:Code>Key_1</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<c:Key.Columns>
+<o:Column Ref="o174"/>
+</c:Key.Columns>
+</o:Key>
+</c:Keys>
+<c:PrimaryKey>
+<o:Key Ref="o185"/>
+</c:PrimaryKey>
+</o:Table>
+<o:Table Id="o32">
+<a:ObjectID>AFCBF4DB-07EC-42D1-ACA7-56B5038F5AC5</a:ObjectID>
+<a:Name>sys_job</a:Name>
+<a:Code>sys_job</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1538297732</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>定时任务调度表</a:Comment>
+<a:TotalSavingCurrency/>
+<c:Columns>
+<o:Column Id="o186">
+<a:ObjectID>1658CED4-3885-4094-AB70-F35408EBCD5E</a:ObjectID>
+<a:Name>job_id</a:Name>
+<a:Code>job_id</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>任务ID</a:Comment>
+<a:DataType>int(11)</a:DataType>
+<a:Length>11</a:Length>
+<a:Identity>1</a:Identity>
+<a:Mandatory>1</a:Mandatory>
+</o:Column>
+<o:Column Id="o187">
+<a:ObjectID>731E7147-E3A4-4D93-8C7C-BB1C6D94DB9E</a:ObjectID>
+<a:Name>job_name</a:Name>
+<a:Code>job_name</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>任务名称</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(64)</a:DataType>
+<a:Length>64</a:Length>
+<a:Mandatory>1</a:Mandatory>
+</o:Column>
+<o:Column Id="o188">
+<a:ObjectID>C64B3655-C240-44F0-83B4-F42FB76C8BEA</a:ObjectID>
+<a:Name>job_group</a:Name>
+<a:Code>job_group</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>任务组名</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(64)</a:DataType>
+<a:Length>64</a:Length>
+<a:Mandatory>1</a:Mandatory>
+</o:Column>
+<o:Column Id="o189">
+<a:ObjectID>9F7E735D-B823-4ADA-BA3D-8FFFFEC92F5C</a:ObjectID>
+<a:Name>method_name</a:Name>
+<a:Code>method_name</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>任务方法</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(500)</a:DataType>
+<a:Length>500</a:Length>
+</o:Column>
+<o:Column Id="o190">
+<a:ObjectID>28EEE4F4-E8E7-4052-8F10-88D6C74C595D</a:ObjectID>
+<a:Name>method_params</a:Name>
+<a:Code>method_params</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1538297298</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>方法参数</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(200)</a:DataType>
+<a:Length>200</a:Length>
+</o:Column>
+<o:Column Id="o191">
+<a:ObjectID>C8986FAD-E2E7-4364-9E8B-B75366B9A4ED</a:ObjectID>
+<a:Name>cron_expression</a:Name>
+<a:Code>cron_expression</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>cron执行表达式</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(255)</a:DataType>
+<a:Length>255</a:Length>
+</o:Column>
+<o:Column Id="o192">
+<a:ObjectID>FD188167-AC02-4161-BE89-D63E61412313</a:ObjectID>
+<a:Name>misfire_policy</a:Name>
+<a:Code>misfire_policy</a:Code>
+<a:CreationDate>1538297273</a:CreationDate>
+<a:Creator>admin</a:Creator>
+<a:ModificationDate>1538297298</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:DataType>varchar(20)</a:DataType>
+<a:Length>20</a:Length>
+</o:Column>
+<o:Column Id="o193">
+<a:ObjectID>2D4B6C8F-EEE8-4474-9D20-8206A7E80362</a:ObjectID>
+<a:Name>status</a:Name>
+<a:Code>status</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>状态(0正常 1暂停)</a:Comment>
+<a:DefaultValue>0</a:DefaultValue>
+<a:DataType>int(1)</a:DataType>
+<a:Length>1</a:Length>
+</o:Column>
+<o:Column Id="o194">
+<a:ObjectID>CA78AC7F-19E7-47BC-BF7B-9F31EFB02702</a:ObjectID>
+<a:Name>create_by</a:Name>
+<a:Code>create_by</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>创建者</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(64)</a:DataType>
+<a:Length>64</a:Length>
+</o:Column>
+<o:Column Id="o195">
+<a:ObjectID>B8F807AE-9F19-4FCA-BA98-7BF71DD0CA02</a:ObjectID>
+<a:Name>create_time</a:Name>
+<a:Code>create_time</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>创建时间</a:Comment>
+<a:DataType>timestamp</a:DataType>
+</o:Column>
+<o:Column Id="o196">
+<a:ObjectID>3FBB42FA-ED0F-4D7C-99D0-5F7AF7B0F1DD</a:ObjectID>
+<a:Name>update_by</a:Name>
+<a:Code>update_by</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>更新者</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(64)</a:DataType>
+<a:Length>64</a:Length>
+</o:Column>
+<o:Column Id="o197">
+<a:ObjectID>1C5863D2-A8B9-43DB-AA06-F8BE3E01093B</a:ObjectID>
+<a:Name>update_time</a:Name>
+<a:Code>update_time</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>更新时间</a:Comment>
+<a:DataType>timestamp</a:DataType>
+</o:Column>
+<o:Column Id="o198">
+<a:ObjectID>889C3FF9-BB1E-4EB1-AFE9-1D1155984915</a:ObjectID>
+<a:Name>remark</a:Name>
+<a:Code>remark</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>备注信息</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(500)</a:DataType>
+<a:Length>500</a:Length>
+</o:Column>
+</c:Columns>
+<c:Keys>
+<o:Key Id="o199">
+<a:ObjectID>38106F1A-4FFB-4EC0-B979-55BD6C6C6FF7</a:ObjectID>
+<a:Name>Key_1</a:Name>
+<a:Code>Key_1</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<c:Key.Columns>
+<o:Column Ref="o186"/>
+<o:Column Ref="o187"/>
+<o:Column Ref="o188"/>
+</c:Key.Columns>
+</o:Key>
+</c:Keys>
+<c:PrimaryKey>
+<o:Key Ref="o199"/>
+</c:PrimaryKey>
+</o:Table>
+<o:Table Id="o34">
+<a:ObjectID>CF7C8958-5494-48C6-BE05-83F2CF8C7513</a:ObjectID>
+<a:Name>sys_job_log</a:Name>
+<a:Code>sys_job_log</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1538297742</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>定时任务调度日志表</a:Comment>
+<a:TotalSavingCurrency/>
+<c:Columns>
+<o:Column Id="o200">
+<a:ObjectID>308F32A1-A8EC-4002-9993-DF9234A303B7</a:ObjectID>
+<a:Name>job_log_id</a:Name>
+<a:Code>job_log_id</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>任务日志ID</a:Comment>
+<a:DataType>int(11)</a:DataType>
+<a:Length>11</a:Length>
+<a:Identity>1</a:Identity>
+<a:Mandatory>1</a:Mandatory>
+</o:Column>
+<o:Column Id="o201">
+<a:ObjectID>F4D55B65-BB6B-4182-A6D6-F9CAABC19110</a:ObjectID>
+<a:Name>job_name</a:Name>
+<a:Code>job_name</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>任务名称</a:Comment>
+<a:DataType>varchar(64)</a:DataType>
+<a:Length>64</a:Length>
+<a:Mandatory>1</a:Mandatory>
+</o:Column>
+<o:Column Id="o202">
+<a:ObjectID>8AF383A0-01C0-4947-8384-FF0F13AC00AE</a:ObjectID>
+<a:Name>job_group</a:Name>
+<a:Code>job_group</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>任务组名</a:Comment>
+<a:DataType>varchar(64)</a:DataType>
+<a:Length>64</a:Length>
+<a:Mandatory>1</a:Mandatory>
+</o:Column>
+<o:Column Id="o203">
+<a:ObjectID>96582B76-F1E9-4473-BA51-01B87B5F459E</a:ObjectID>
+<a:Name>method_name</a:Name>
+<a:Code>method_name</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>任务方法</a:Comment>
+<a:DataType>varchar(500)</a:DataType>
+<a:Length>500</a:Length>
+</o:Column>
+<o:Column Id="o204">
+<a:ObjectID>2AB02ABA-02E3-4F72-95BA-4261A7F5729A</a:ObjectID>
+<a:Name>method_params</a:Name>
+<a:Code>method_params</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1538297325</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>方法参数</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(200)</a:DataType>
+<a:Length>200</a:Length>
+</o:Column>
+<o:Column Id="o205">
+<a:ObjectID>8EB39444-CBFF-43AA-AA37-49217EF545B6</a:ObjectID>
+<a:Name>job_message</a:Name>
+<a:Code>job_message</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>日志信息</a:Comment>
+<a:DataType>varchar(500)</a:DataType>
+<a:Length>500</a:Length>
+</o:Column>
+<o:Column Id="o206">
+<a:ObjectID>18CD263C-0F57-4EDF-999E-1B5A7EE2BFF9</a:ObjectID>
+<a:Name>is_exception</a:Name>
+<a:Code>is_exception</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1538297325</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>是否异常</a:Comment>
+<a:DefaultValue>0</a:DefaultValue>
+<a:DataType>char(1)</a:DataType>
+<a:Length>1</a:Length>
+</o:Column>
+<o:Column Id="o207">
+<a:ObjectID>634ECD78-2251-43EB-B6CF-DF7FA9DA4354</a:ObjectID>
+<a:Name>exception_info</a:Name>
+<a:Code>exception_info</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>异常信息</a:Comment>
+<a:DataType>text</a:DataType>
+</o:Column>
+<o:Column Id="o208">
+<a:ObjectID>4EC075CC-507B-43D7-860F-34DAAEB1DBBF</a:ObjectID>
+<a:Name>create_time</a:Name>
+<a:Code>create_time</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<a:Comment>创建时间</a:Comment>
+<a:DataType>timestamp</a:DataType>
+</o:Column>
+</c:Columns>
+<c:Keys>
+<o:Key Id="o209">
+<a:ObjectID>A87DCE10-894A-4CF7-B39C-AF18202C7F86</a:ObjectID>
+<a:Name>Key_1</a:Name>
+<a:Code>Key_1</a:Code>
+<a:CreationDate>1524449375</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449375</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+<c:Key.Columns>
+<o:Column Ref="o200"/>
+</c:Key.Columns>
+</o:Key>
+</c:Keys>
+<c:PrimaryKey>
+<o:Key Ref="o209"/>
+</c:PrimaryKey>
+</o:Table>
+<o:Table Id="o36">
+<a:ObjectID>FD6284E8-B6D4-43AF-A038-9C97DCD403DC</a:ObjectID>
+<a:Name>sys_role_dept</a:Name>
+<a:Code>sys_role_dept</a:Code>
+<a:CreationDate>1538296083</a:CreationDate>
+<a:Creator>admin</a:Creator>
+<a:ModificationDate>1538297689</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>角色和部门关联表</a:Comment>
+<a:TotalSavingCurrency/>
+<c:Columns>
+<o:Column Id="o210">
+<a:ObjectID>2BC66204-4193-42E6-BB7B-7AD57C9E5BEF</a:ObjectID>
+<a:Name>role_id</a:Name>
+<a:Code>role_id</a:Code>
+<a:CreationDate>1538296083</a:CreationDate>
+<a:Creator>admin</a:Creator>
+<a:ModificationDate>1538296150</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>用户ID</a:Comment>
+<a:DataType>int(11)</a:DataType>
+<a:Length>11</a:Length>
+<a:Mandatory>1</a:Mandatory>
+</o:Column>
+<o:Column Id="o211">
+<a:ObjectID>A32BC025-6437-41AB-BAA4-3A150E406781</a:ObjectID>
+<a:Name>dept_id</a:Name>
+<a:Code>dept_id</a:Code>
+<a:CreationDate>1538296083</a:CreationDate>
+<a:Creator>admin</a:Creator>
+<a:ModificationDate>1538296150</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>岗位ID</a:Comment>
+<a:DataType>int(11)</a:DataType>
+<a:Length>11</a:Length>
+<a:Mandatory>1</a:Mandatory>
+</o:Column>
+</c:Columns>
+<c:Keys>
+<o:Key Id="o212">
+<a:ObjectID>315FFED5-B0A0-4649-8255-2283896340C9</a:ObjectID>
+<a:Name>Key_1</a:Name>
+<a:Code>Key_1</a:Code>
+<a:CreationDate>1538296083</a:CreationDate>
+<a:Creator>admin</a:Creator>
+<a:ModificationDate>1538296083</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<c:Key.Columns>
+<o:Column Ref="o210"/>
+<o:Column Ref="o211"/>
+</c:Key.Columns>
+</o:Key>
+</c:Keys>
+<c:PrimaryKey>
+<o:Key Ref="o212"/>
+</c:PrimaryKey>
+</o:Table>
+<o:Table Id="o38">
+<a:ObjectID>45EB995C-F5F6-4818-AEB1-2038DEBA9CEE</a:ObjectID>
+<a:Name>sys_config</a:Name>
+<a:Code>sys_config</a:Code>
+<a:CreationDate>1538296587</a:CreationDate>
+<a:Creator>admin</a:Creator>
+<a:ModificationDate>1538297714</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>参数配置表</a:Comment>
+<a:TotalSavingCurrency/>
+<c:Columns>
+<o:Column Id="o213">
+<a:ObjectID>667C4616-146B-475C-8111-4720375D762C</a:ObjectID>
+<a:Name>config_id</a:Name>
+<a:Code>config_id</a:Code>
+<a:CreationDate>1538296587</a:CreationDate>
+<a:Creator>admin</a:Creator>
+<a:ModificationDate>1538296691</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>字典编码</a:Comment>
+<a:DataType>int(5)</a:DataType>
+<a:Length>5</a:Length>
+<a:Identity>1</a:Identity>
+<a:Mandatory>1</a:Mandatory>
+</o:Column>
+<o:Column Id="o214">
+<a:ObjectID>EA798E0B-0CBE-4897-B0AF-1F2D3CD6DEF4</a:ObjectID>
+<a:Name>config_name</a:Name>
+<a:Code>config_name</a:Code>
+<a:CreationDate>1538296587</a:CreationDate>
+<a:Creator>admin</a:Creator>
+<a:ModificationDate>1538296691</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>字典排序</a:Comment>
+<a:DefaultValue>0</a:DefaultValue>
+<a:DataType>varchar(100)</a:DataType>
+<a:Length>100</a:Length>
+</o:Column>
+<o:Column Id="o215">
+<a:ObjectID>A9A2A6E0-C914-4516-AE4C-F33CE71B92E8</a:ObjectID>
+<a:Name>config_key</a:Name>
+<a:Code>config_key</a:Code>
+<a:CreationDate>1538296587</a:CreationDate>
+<a:Creator>admin</a:Creator>
+<a:ModificationDate>1538296691</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>字典标签</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(100)</a:DataType>
+<a:Length>100</a:Length>
+</o:Column>
+<o:Column Id="o216">
+<a:ObjectID>24CCA897-8671-402E-8229-9ED0C80C176A</a:ObjectID>
+<a:Name>config_value</a:Name>
+<a:Code>config_value</a:Code>
+<a:CreationDate>1538296587</a:CreationDate>
+<a:Creator>admin</a:Creator>
+<a:ModificationDate>1538296691</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>字典键值</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(100)</a:DataType>
+<a:Length>100</a:Length>
+</o:Column>
+<o:Column Id="o217">
+<a:ObjectID>B4E76B1D-BFAF-42F3-8CCA-8B5A8CC7CBFF</a:ObjectID>
+<a:Name>config_type</a:Name>
+<a:Code>config_type</a:Code>
+<a:CreationDate>1538296587</a:CreationDate>
+<a:Creator>admin</a:Creator>
+<a:ModificationDate>1538296691</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>字典类型</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>char(1)</a:DataType>
+<a:Length>1</a:Length>
+</o:Column>
+<o:Column Id="o218">
+<a:ObjectID>A6AC1891-F5C4-45B3-8CAB-8F4CE8B8BF08</a:ObjectID>
+<a:Name>create_by</a:Name>
+<a:Code>create_by</a:Code>
+<a:CreationDate>1538296587</a:CreationDate>
+<a:Creator>admin</a:Creator>
+<a:ModificationDate>1538296587</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>创建者</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(64)</a:DataType>
+<a:Length>64</a:Length>
+</o:Column>
+<o:Column Id="o219">
+<a:ObjectID>CC1E0367-A079-49A0-8F0A-FE5F7B3EB6EA</a:ObjectID>
+<a:Name>create_time</a:Name>
+<a:Code>create_time</a:Code>
+<a:CreationDate>1538296587</a:CreationDate>
+<a:Creator>admin</a:Creator>
+<a:ModificationDate>1538296587</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>创建时间</a:Comment>
+<a:DataType>timestamp</a:DataType>
+</o:Column>
+<o:Column Id="o220">
+<a:ObjectID>081CD54E-AE38-4696-A326-F829B8EA5737</a:ObjectID>
+<a:Name>update_by</a:Name>
+<a:Code>update_by</a:Code>
+<a:CreationDate>1538296587</a:CreationDate>
+<a:Creator>admin</a:Creator>
+<a:ModificationDate>1538296587</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>更新者</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(64)</a:DataType>
+<a:Length>64</a:Length>
+</o:Column>
+<o:Column Id="o221">
+<a:ObjectID>E2118ECE-8F52-4FBA-B18A-F30FFB2BDD20</a:ObjectID>
+<a:Name>update_time</a:Name>
+<a:Code>update_time</a:Code>
+<a:CreationDate>1538296587</a:CreationDate>
+<a:Creator>admin</a:Creator>
+<a:ModificationDate>1538296587</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>更新时间</a:Comment>
+<a:DataType>timestamp</a:DataType>
+</o:Column>
+<o:Column Id="o222">
+<a:ObjectID>55A16121-8932-465E-8427-EBDA39B2B900</a:ObjectID>
+<a:Name>remark</a:Name>
+<a:Code>remark</a:Code>
+<a:CreationDate>1538296587</a:CreationDate>
+<a:Creator>admin</a:Creator>
+<a:ModificationDate>1538296587</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>备注</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>varchar(500)</a:DataType>
+<a:Length>500</a:Length>
+</o:Column>
+</c:Columns>
+<c:Keys>
+<o:Key Id="o223">
+<a:ObjectID>0F331278-2804-496A-A87B-B0944C80FB82</a:ObjectID>
+<a:Name>Key_1</a:Name>
+<a:Code>Key_1</a:Code>
+<a:CreationDate>1538296587</a:CreationDate>
+<a:Creator>admin</a:Creator>
+<a:ModificationDate>1538296587</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<c:Key.Columns>
+<o:Column Ref="o213"/>
+</c:Key.Columns>
+</o:Key>
+</c:Keys>
+<c:PrimaryKey>
+<o:Key Ref="o223"/>
+</c:PrimaryKey>
+</o:Table>
+<o:Table Id="o41">
+<a:ObjectID>F33DE1D6-C12D-43DB-A502-83BD1615F081</a:ObjectID>
+<a:Name>sys_notice</a:Name>
+<a:Code>sys_notice</a:Code>
+<a:CreationDate>1538297386</a:CreationDate>
+<a:Creator>admin</a:Creator>
+<a:ModificationDate>1538297746</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>通知公告表</a:Comment>
+<a:TotalSavingCurrency/>
+<c:Columns>
+<o:Column Id="o224">
+<a:ObjectID>FF4A9744-D7CA-450E-8AD7-B3E7E90075CE</a:ObjectID>
+<a:Name>notice_id</a:Name>
+<a:Code>notice_id</a:Code>
+<a:CreationDate>1538297386</a:CreationDate>
+<a:Creator>admin</a:Creator>
+<a:ModificationDate>1538297496</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>任务日志ID</a:Comment>
+<a:DataType>int(4)</a:DataType>
+<a:Length>4</a:Length>
+<a:Identity>1</a:Identity>
+<a:Mandatory>1</a:Mandatory>
+</o:Column>
+<o:Column Id="o225">
+<a:ObjectID>E2B08825-4C94-4209-80B2-21A7AD8CBF2D</a:ObjectID>
+<a:Name>notice_title</a:Name>
+<a:Code>notice_title</a:Code>
+<a:CreationDate>1538297386</a:CreationDate>
+<a:Creator>admin</a:Creator>
+<a:ModificationDate>1538297496</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>任务名称</a:Comment>
+<a:DataType>varchar(50)</a:DataType>
+<a:Length>50</a:Length>
+<a:Mandatory>1</a:Mandatory>
+</o:Column>
+<o:Column Id="o226">
+<a:ObjectID>04414862-9ABC-4431-B1B7-B44ECC08CB6E</a:ObjectID>
+<a:Name>notice_type</a:Name>
+<a:Code>notice_type</a:Code>
+<a:CreationDate>1538297386</a:CreationDate>
+<a:Creator>admin</a:Creator>
+<a:ModificationDate>1538297496</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>任务组名</a:Comment>
+<a:DataType>char(2)</a:DataType>
+<a:Length>2</a:Length>
+<a:Mandatory>1</a:Mandatory>
+</o:Column>
+<o:Column Id="o227">
+<a:ObjectID>E829DAD1-E3F9-4AED-A3DE-59CE4340333E</a:ObjectID>
+<a:Name>notice_content</a:Name>
+<a:Code>notice_content</a:Code>
+<a:CreationDate>1538297386</a:CreationDate>
+<a:Creator>admin</a:Creator>
+<a:ModificationDate>1538297496</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>任务方法</a:Comment>
+<a:DataType>varchar(500)</a:DataType>
+<a:Length>500</a:Length>
+</o:Column>
+<o:Column Id="o228">
+<a:ObjectID>2EABC8DB-6700-4717-89A3-31461C4CB2D5</a:ObjectID>
+<a:Name>status</a:Name>
+<a:Code>status</a:Code>
+<a:CreationDate>1538297386</a:CreationDate>
+<a:Creator>admin</a:Creator>
+<a:ModificationDate>1538297496</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>方法参数</a:Comment>
+<a:DefaultValue>&#39;&#39;</a:DefaultValue>
+<a:DataType>char(1)</a:DataType>
+<a:Length>1</a:Length>
+</o:Column>
+<o:Column Id="o229">
+<a:ObjectID>448D3EB6-DE24-4BE3-9C29-1FC3C71B0E8D</a:ObjectID>
+<a:Name>create_by</a:Name>
+<a:Code>create_by</a:Code>
+<a:CreationDate>1538297386</a:CreationDate>
+<a:Creator>admin</a:Creator>
+<a:ModificationDate>1538297496</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>日志信息</a:Comment>
+<a:DataType>varchar(64)</a:DataType>
+<a:Length>64</a:Length>
+</o:Column>
+<o:Column Id="o230">
+<a:ObjectID>770ED87D-D4D7-499C-A266-7A54051B1A84</a:ObjectID>
+<a:Name>create_time1</a:Name>
+<a:Code>create_time1</a:Code>
+<a:CreationDate>1538297386</a:CreationDate>
+<a:Creator>admin</a:Creator>
+<a:ModificationDate>1538297496</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>是否异常</a:Comment>
+<a:DefaultValue>0</a:DefaultValue>
+<a:DataType>datetime</a:DataType>
+</o:Column>
+<o:Column Id="o231">
+<a:ObjectID>12DDF399-7CCB-4117-8B05-6AA9BEE845E5</a:ObjectID>
+<a:Name>update_by</a:Name>
+<a:Code>update_by</a:Code>
+<a:CreationDate>1538297386</a:CreationDate>
+<a:Creator>admin</a:Creator>
+<a:ModificationDate>1538297496</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>异常信息</a:Comment>
+<a:DataType>varchar(64)</a:DataType>
+<a:Length>64</a:Length>
+</o:Column>
+<o:Column Id="o232">
+<a:ObjectID>FE101CE4-9B66-4097-944D-36B01A9E2219</a:ObjectID>
+<a:Name>update_time1</a:Name>
+<a:Code>update_time1</a:Code>
+<a:CreationDate>1538297400</a:CreationDate>
+<a:Creator>admin</a:Creator>
+<a:ModificationDate>1538297496</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:DataType>datetime</a:DataType>
+</o:Column>
+<o:Column Id="o233">
+<a:ObjectID>D5F1728C-01D0-4C00-9AD6-AAA14228104B</a:ObjectID>
+<a:Name>remark</a:Name>
+<a:Code>remark</a:Code>
+<a:CreationDate>1538297386</a:CreationDate>
+<a:Creator>admin</a:Creator>
+<a:ModificationDate>1538297496</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:Comment>创建时间</a:Comment>
+<a:DataType>varchar(255)</a:DataType>
+<a:Length>255</a:Length>
+</o:Column>
+</c:Columns>
+<c:Keys>
+<o:Key Id="o234">
+<a:ObjectID>43C7AC1D-CE7A-4B55-A474-8CB2376D446F</a:ObjectID>
+<a:Name>Key_1</a:Name>
+<a:Code>Key_1</a:Code>
+<a:CreationDate>1538297386</a:CreationDate>
+<a:Creator>admin</a:Creator>
+<a:ModificationDate>1538297386</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<c:Key.Columns>
+<o:Column Ref="o224"/>
+</c:Key.Columns>
+</o:Key>
+</c:Keys>
+<c:PrimaryKey>
+<o:Key Ref="o234"/>
+</c:PrimaryKey>
+</o:Table>
+</c:Tables>
+<c:DefaultGroups>
+<o:Group Id="o235">
+<a:ObjectID>F2EBEA5B-F352-45CB-B349-39158064CEE8</a:ObjectID>
+<a:Name>PUBLIC</a:Name>
+<a:Code>PUBLIC</a:Code>
+<a:CreationDate>1524449325</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1524449325</a:ModificationDate>
+<a:Modifier>Administrator</a:Modifier>
+</o:Group>
+</c:DefaultGroups>
+<c:TargetModels>
+<o:TargetModel Id="o236">
+<a:ObjectID>41740AEF-D7FB-4738-ABDF-47C3287A6AF6</a:ObjectID>
+<a:Name>MySQL 5.0</a:Name>
+<a:Code>MYSQL50</a:Code>
+<a:CreationDate>1524449337</a:CreationDate>
+<a:Creator>Administrator</a:Creator>
+<a:ModificationDate>1538295558</a:ModificationDate>
+<a:Modifier>admin</a:Modifier>
+<a:TargetModelURL>file:///%_DBMS%/mysql50.xdb</a:TargetModelURL>
+<a:TargetModelID>F4F16ECD-F2F1-4006-AF6F-638D5C65F35E</a:TargetModelID>
+<a:TargetModelClassID>4BA9F647-DAB1-11D1-9944-006097355D9B</a:TargetModelClassID>
+<c:SessionShortcuts>
+<o:Shortcut Ref="o3"/>
+</c:SessionShortcuts>
+</o:TargetModel>
+</c:TargetModels>
+</o:Model>
+</c:Children>
+</o:RootObject>
+
+</Model>
\ No newline at end of file
diff --git a/sql/ry_20240601.sql b/sql/ry_20240601.sql
new file mode 100644
index 0000000..166b5a9
--- /dev/null
+++ b/sql/ry_20240601.sql
@@ -0,0 +1,722 @@
+-- ----------------------------
+-- 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 '父部门id',
+  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正常 1停用)',
+  del_flag          char(1)         default '0'                comment '删除标志(0代表存在 2代表删除)',
+  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', sysdate(), '', null);
+insert into sys_dept values(101,  100, '0,100',      '深圳总公司', 1, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null);
+insert into sys_dept values(102,  100, '0,100',      '长沙分公司', 2, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null);
+insert into sys_dept values(103,  101, '0,100,101',  '研发部门',   1, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null);
+insert into sys_dept values(104,  101, '0,100,101',  '市场部门',   2, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null);
+insert into sys_dept values(105,  101, '0,100,101',  '测试部门',   3, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null);
+insert into sys_dept values(106,  101, '0,100,101',  '财务部门',   4, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null);
+insert into sys_dept values(107,  101, '0,100,101',  '运维部门',   5, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null);
+insert into sys_dept values(108,  102, '0,100,102',  '市场部门',   1, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null);
+insert into sys_dept values(109,  102, '0,100,102',  '财务部门',   2, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', 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',
+  login_name        varchar(30)     not null                   comment '登录账号',
+  user_name         varchar(30)     default ''                 comment '用户昵称',
+  user_type         varchar(2)      default '00'               comment '用户类型(00系统用户 01注册用户)',
+  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(50)     default ''                 comment '密码',
+  salt              varchar(20)     default ''                 comment '盐加密',
+  status            char(1)         default '0'                comment '帐号状态(0正常 1停用)',
+  del_flag          char(1)         default '0'                comment '删除标志(0代表存在 2代表删除)',
+  login_ip          varchar(128)    default ''                 comment '最后登录IP',
+  login_date        datetime                                   comment '最后登录时间',
+  pwd_update_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', '', '29c67a30398638269fe600f73a054934', '111111', '0', '0', '127.0.0.1', null, null, 'admin', sysdate(), '', null, '管理员');
+insert into sys_user values(2,  105, 'ry',    '若依', '00', 'ry@qq.com',  '15666666666', '1', '', '8e6d98b90472783cc73c17047ddccf36', '222222', '0', '0', '127.0.0.1', null, null, '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正常 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',  '董事长',    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:本部门及以下数据权限)',
+  status            char(1)         not null                   comment '角色状态(0正常 1停用)',
+  del_flag          char(1)         default '0'                comment '删除标志(0代表存在 2代表删除)',
+  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, '0', '0', 'admin', sysdate(), '', null, '超级管理员');
+insert into sys_role values('2', '普通角色',   'common', 2, 2, '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 '父菜单ID',
+  order_num         int(4)          default 0                  comment '显示顺序',
+  url               varchar(200)    default '#'                comment '请求地址',
+  target            varchar(20)     default ''                 comment '打开方式(menuItem页签 menuBlank新窗口)',
+  menu_type         char(1)         default ''                 comment '菜单类型(M目录 C菜单 F按钮)',
+  visible           char(1)         default 0                  comment '菜单状态(0显示 1隐藏)',
+  is_refresh        char(1)         default 1                  comment '是否刷新(0刷新 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', '#',                '',          'M', '0', '1', '', 'fa fa-gear',           'admin', sysdate(), '', null, '系统管理目录');
+insert into sys_menu values('2', '系统监控', '0', '2', '#',                '',          'M', '0', '1', '', 'fa fa-video-camera',   'admin', sysdate(), '', null, '系统监控目录');
+insert into sys_menu values('3', '系统工具', '0', '3', '#',                '',          'M', '0', '1', '', 'fa fa-bars',           'admin', sysdate(), '', null, '系统工具目录');
+insert into sys_menu values('4', '若依官网', '0', '4', 'http://ruoyi.vip', 'menuBlank', 'C', '0', '1', '', 'fa fa-location-arrow', 'admin', sysdate(), '', null, '若依官网地址');
+-- 二级菜单
+insert into sys_menu values('100',  '用户管理', '1', '1', '/system/user',          '', 'C', '0', '1', 'system:user:view',         'fa fa-user-o',          'admin', sysdate(), '', null, '用户管理菜单');
+insert into sys_menu values('101',  '角色管理', '1', '2', '/system/role',          '', 'C', '0', '1', 'system:role:view',         'fa fa-user-secret',     'admin', sysdate(), '', null, '角色管理菜单');
+insert into sys_menu values('102',  '菜单管理', '1', '3', '/system/menu',          '', 'C', '0', '1', 'system:menu:view',         'fa fa-th-list',         'admin', sysdate(), '', null, '菜单管理菜单');
+insert into sys_menu values('103',  '部门管理', '1', '4', '/system/dept',          '', 'C', '0', '1', 'system:dept:view',         'fa fa-outdent',         'admin', sysdate(), '', null, '部门管理菜单');
+insert into sys_menu values('104',  '岗位管理', '1', '5', '/system/post',          '', 'C', '0', '1', 'system:post:view',         'fa fa-address-card-o',  'admin', sysdate(), '', null, '岗位管理菜单');
+insert into sys_menu values('105',  '字典管理', '1', '6', '/system/dict',          '', 'C', '0', '1', 'system:dict:view',         'fa fa-bookmark-o',      'admin', sysdate(), '', null, '字典管理菜单');
+insert into sys_menu values('106',  '参数设置', '1', '7', '/system/config',        '', 'C', '0', '1', 'system:config:view',       'fa fa-sun-o',           'admin', sysdate(), '', null, '参数设置菜单');
+insert into sys_menu values('107',  '通知公告', '1', '8', '/system/notice',        '', 'C', '0', '1', 'system:notice:view',       'fa fa-bullhorn',        'admin', sysdate(), '', null, '通知公告菜单');
+insert into sys_menu values('108',  '日志管理', '1', '9', '#',                     '', 'M', '0', '1', '',                         'fa fa-pencil-square-o', 'admin', sysdate(), '', null, '日志管理菜单');
+insert into sys_menu values('109',  '在线用户', '2', '1', '/monitor/online',       '', 'C', '0', '1', 'monitor:online:view',      'fa fa-user-circle',     'admin', sysdate(), '', null, '在线用户菜单');
+insert into sys_menu values('110',  '定时任务', '2', '2', '/monitor/job',          '', 'C', '0', '1', 'monitor:job:view',         'fa fa-tasks',           'admin', sysdate(), '', null, '定时任务菜单');
+insert into sys_menu values('111',  '数据监控', '2', '3', '/monitor/data',         '', 'C', '0', '1', 'monitor:data:view',        'fa fa-bug',             'admin', sysdate(), '', null, '数据监控菜单');
+insert into sys_menu values('112',  '服务监控', '2', '4', '/monitor/server',       '', 'C', '0', '1', 'monitor:server:view',      'fa fa-server',          'admin', sysdate(), '', null, '服务监控菜单');
+insert into sys_menu values('113',  '缓存监控', '2', '5', '/monitor/cache',        '', 'C', '0', '1', 'monitor:cache:view',       'fa fa-cube',            'admin', sysdate(), '', null, '缓存监控菜单');
+insert into sys_menu values('114',  '表单构建', '3', '1', '/tool/build',           '', 'C', '0', '1', 'tool:build:view',          'fa fa-wpforms',         'admin', sysdate(), '', null, '表单构建菜单');
+insert into sys_menu values('115',  '代码生成', '3', '2', '/tool/gen',             '', 'C', '0', '1', 'tool:gen:view',            'fa fa-code',            'admin', sysdate(), '', null, '代码生成菜单');
+insert into sys_menu values('116',  '系统接口', '3', '3', '/tool/swagger',         '', 'C', '0', '1', 'tool:swagger:view',        'fa fa-gg',              'admin', sysdate(), '', null, '系统接口菜单');
+-- 三级菜单
+insert into sys_menu values('500',  '操作日志', '108', '1', '/monitor/operlog',    '', 'C', '0', '1', 'monitor:operlog:view',     'fa fa-address-book',    'admin', sysdate(), '', null, '操作日志菜单');
+insert into sys_menu values('501',  '登录日志', '108', '2', '/monitor/logininfor', '', 'C', '0', '1', 'monitor:logininfor:view',  'fa fa-file-image-o',    'admin', sysdate(), '', null, '登录日志菜单');
+-- 用户管理按钮
+insert into sys_menu values('1000', '用户查询', '100', '1',  '#', '',  'F', '0', '1', 'system:user:list',        '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1001', '用户新增', '100', '2',  '#', '',  'F', '0', '1', 'system:user:add',         '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1002', '用户修改', '100', '3',  '#', '',  'F', '0', '1', 'system:user:edit',        '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1003', '用户删除', '100', '4',  '#', '',  'F', '0', '1', 'system:user:remove',      '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1004', '用户导出', '100', '5',  '#', '',  'F', '0', '1', 'system:user:export',      '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1005', '用户导入', '100', '6',  '#', '',  'F', '0', '1', 'system:user:import',      '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1006', '重置密码', '100', '7',  '#', '',  'F', '0', '1', 'system:user:resetPwd',    '#', 'admin', sysdate(), '', null, '');
+-- 角色管理按钮
+insert into sys_menu values('1007', '角色查询', '101', '1',  '#', '',  'F', '0', '1', 'system:role:list',        '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1008', '角色新增', '101', '2',  '#', '',  'F', '0', '1', 'system:role:add',         '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1009', '角色修改', '101', '3',  '#', '',  'F', '0', '1', 'system:role:edit',        '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1010', '角色删除', '101', '4',  '#', '',  'F', '0', '1', 'system:role:remove',      '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1011', '角色导出', '101', '5',  '#', '',  'F', '0', '1', 'system:role:export',      '#', 'admin', sysdate(), '', null, '');
+-- 菜单管理按钮
+insert into sys_menu values('1012', '菜单查询', '102', '1',  '#', '',  'F', '0', '1', 'system:menu:list',        '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1013', '菜单新增', '102', '2',  '#', '',  'F', '0', '1', 'system:menu:add',         '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1014', '菜单修改', '102', '3',  '#', '',  'F', '0', '1', 'system:menu:edit',        '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1015', '菜单删除', '102', '4',  '#', '',  'F', '0', '1', 'system:menu:remove',      '#', 'admin', sysdate(), '', null, '');
+-- 部门管理按钮
+insert into sys_menu values('1016', '部门查询', '103', '1',  '#', '',  'F', '0', '1', 'system:dept:list',        '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1017', '部门新增', '103', '2',  '#', '',  'F', '0', '1', 'system:dept:add',         '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1018', '部门修改', '103', '3',  '#', '',  'F', '0', '1', 'system:dept:edit',        '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1019', '部门删除', '103', '4',  '#', '',  'F', '0', '1', 'system:dept:remove',      '#', 'admin', sysdate(), '', null, '');
+-- 岗位管理按钮
+insert into sys_menu values('1020', '岗位查询', '104', '1',  '#', '',  'F', '0', '1', 'system:post:list',        '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1021', '岗位新增', '104', '2',  '#', '',  'F', '0', '1', 'system:post:add',         '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1022', '岗位修改', '104', '3',  '#', '',  'F', '0', '1', 'system:post:edit',        '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1023', '岗位删除', '104', '4',  '#', '',  'F', '0', '1', 'system:post:remove',      '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1024', '岗位导出', '104', '5',  '#', '',  'F', '0', '1', 'system:post:export',      '#', 'admin', sysdate(), '', null, '');
+-- 字典管理按钮
+insert into sys_menu values('1025', '字典查询', '105', '1',  '#', '',  'F', '0', '1', 'system:dict:list',        '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1026', '字典新增', '105', '2',  '#', '',  'F', '0', '1', 'system:dict:add',         '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1027', '字典修改', '105', '3',  '#', '',  'F', '0', '1', 'system:dict:edit',        '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1028', '字典删除', '105', '4',  '#', '',  'F', '0', '1', 'system:dict:remove',      '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1029', '字典导出', '105', '5',  '#', '',  'F', '0', '1', 'system:dict:export',      '#', 'admin', sysdate(), '', null, '');
+-- 参数设置按钮
+insert into sys_menu values('1030', '参数查询', '106', '1',  '#', '',  'F', '0', '1', 'system:config:list',      '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1031', '参数新增', '106', '2',  '#', '',  'F', '0', '1', 'system:config:add',       '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1032', '参数修改', '106', '3',  '#', '',  'F', '0', '1', 'system:config:edit',      '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1033', '参数删除', '106', '4',  '#', '',  'F', '0', '1', 'system:config:remove',    '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1034', '参数导出', '106', '5',  '#', '',  'F', '0', '1', 'system:config:export',    '#', 'admin', sysdate(), '', null, '');
+-- 通知公告按钮
+insert into sys_menu values('1035', '公告查询', '107', '1',  '#', '',  'F', '0', '1', 'system:notice:list',      '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1036', '公告新增', '107', '2',  '#', '',  'F', '0', '1', 'system:notice:add',       '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1037', '公告修改', '107', '3',  '#', '',  'F', '0', '1', 'system:notice:edit',      '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1038', '公告删除', '107', '4',  '#', '',  'F', '0', '1', 'system:notice:remove',    '#', 'admin', sysdate(), '', null, '');
+-- 操作日志按钮
+insert into sys_menu values('1039', '操作查询', '500', '1',  '#', '',  'F', '0', '1', 'monitor:operlog:list',    '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1040', '操作删除', '500', '2',  '#', '',  'F', '0', '1', 'monitor:operlog:remove',  '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1041', '详细信息', '500', '3',  '#', '',  'F', '0', '1', 'monitor:operlog:detail',  '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1042', '日志导出', '500', '4',  '#', '',  'F', '0', '1', 'monitor:operlog:export',  '#', 'admin', sysdate(), '', null, '');
+-- 登录日志按钮
+insert into sys_menu values('1043', '登录查询', '501', '1',  '#', '',  'F', '0', '1', 'monitor:logininfor:list',         '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1044', '登录删除', '501', '2',  '#', '',  'F', '0', '1', 'monitor:logininfor:remove',       '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1045', '日志导出', '501', '3',  '#', '',  'F', '0', '1', 'monitor:logininfor:export',       '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1046', '账户解锁', '501', '4',  '#', '',  'F', '0', '1', 'monitor:logininfor:unlock',       '#', 'admin', sysdate(), '', null, '');
+-- 在线用户按钮
+insert into sys_menu values('1047', '在线查询', '109', '1',  '#', '',  'F', '0', '1', 'monitor:online:list',             '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1048', '批量强退', '109', '2',  '#', '',  'F', '0', '1', 'monitor:online:batchForceLogout', '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1049', '单条强退', '109', '3',  '#', '',  'F', '0', '1', 'monitor:online:forceLogout',      '#', 'admin', sysdate(), '', null, '');
+-- 定时任务按钮
+insert into sys_menu values('1050', '任务查询', '110', '1',  '#', '',  'F', '0', '1', 'monitor:job:list',                '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1051', '任务新增', '110', '2',  '#', '',  'F', '0', '1', 'monitor:job:add',                 '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1052', '任务修改', '110', '3',  '#', '',  'F', '0', '1', 'monitor:job:edit',                '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1053', '任务删除', '110', '4',  '#', '',  'F', '0', '1', 'monitor:job:remove',              '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1054', '状态修改', '110', '5',  '#', '',  'F', '0', '1', 'monitor:job:changeStatus',        '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1055', '任务详细', '110', '6',  '#', '',  'F', '0', '1', 'monitor:job:detail',              '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1056', '任务导出', '110', '7',  '#', '',  'F', '0', '1', 'monitor:job:export',              '#', 'admin', sysdate(), '', null, '');
+-- 代码生成按钮
+insert into sys_menu values('1057', '生成查询', '115', '1',  '#', '',  'F', '0', '1', 'tool:gen:list',     '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1058', '生成修改', '115', '2',  '#', '',  'F', '0', '1', 'tool:gen:edit',     '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1059', '生成删除', '115', '3',  '#', '',  'F', '0', '1', 'tool:gen:remove',   '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1060', '预览代码', '115', '4',  '#', '',  'F', '0', '1', 'tool:gen:preview',  '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1061', '生成代码', '115', '5',  '#', '',  'F', '0', '1', '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', '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');
+insert into sys_role_menu values ('2', '1061');
+
+-- ----------------------------
+-- 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(200)    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正常 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正常 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 '是否默认(Y是 N否)',
+  status           char(1)         default '0'                comment '状态(0正常 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,  '正常',     '0',       'sys_normal_disable',  '',   'primary', 'Y', '0', 'admin', sysdate(), '', null, '正常状态');
+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,  '正常',     '0',       'sys_job_status',      '',   'primary', 'Y', '0', 'admin', sysdate(), '', null, '正常状态');
+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,  '正常',     '0',       'sys_notice_status',   '',   'primary', 'Y', '0', 'admin', sysdate(), '', null, '正常状态');
+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,  '生成代码', '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, '正常状态');
+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 '系统内置(Y是 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,浅色主题theme-light,深蓝主题theme-blue');
+insert into sys_config values(4,  '账号自助-是否开启用户注册功能', 'sys.account.registerUser',         'false',         'Y', 'admin', sysdate(), '', null, '是否开启注册用户功能(true开启,false关闭)');
+insert into sys_config values(5,  '用户管理-密码字符范围',         'sys.account.chrtype',              '0',             'Y', 'admin', sysdate(), '', null, '默认任意字符范围,0任意(密码可以输入任意字符),1数字(密码只能为0-9数字),2英文字母(密码只能为a-z和A-Z字母),3字母和数字(密码必须包含字母,数字),4字母数字和特殊字符(目前支持的特殊字符包括:~!@#$%^&*()-=_+)');
+insert into sys_config values(6,  '用户管理-初始密码修改策略',     'sys.account.initPasswordModify',   '1',             'Y', 'admin', sysdate(), '', null, '0:初始密码修改策略关闭,没有任何提示,1:提醒用户,如果未修改初始密码,则在登录时就会提醒修改密码对话框');
+insert into sys_config values(7,  '用户管理-账号密码更新周期',     'sys.account.passwordValidateDays', '0',             'Y', 'admin', sysdate(), '', null, '密码更新周期(填写数字,数据初始化值为0不限制,若修改必须为大于0小于365的正整数),如果超过这个周期登录系统时,则在登录时就会提醒修改密码对话框');
+insert into sys_config values(8,  '主框架页-菜单导航显示风格',     'sys.index.menuStyle',              'default',       'Y', 'admin', sysdate(), '', null, '菜单导航显示风格(default为左侧导航菜单,topnav为顶部导航菜单)');
+insert into sys_config values(9,  '主框架页-是否开启页脚',         'sys.index.footer',                 'true',          'Y', 'admin', sysdate(), '', null, '是否开启底部页脚显示(true显示,false隐藏)');
+insert into sys_config values(10, '主框架页-是否开启页签',         'sys.index.tagsView',               'true',          'Y', 'admin', sysdate(), '', null, '是否开启菜单多页签显示(true显示,false隐藏)');
+insert into sys_config values(11, '用户登录-黑名单列表',           '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',
+  login_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_user_online;
+create table sys_user_online (
+  sessionId         varchar(50)   default ''                comment '用户会话id',
+  login_name        varchar(50)   default ''                comment '登录账号',
+  dept_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            varchar(10)   default ''                comment '在线状态on_line在线off_line离线',
+  start_timestamp   datetime                                comment 'session创建时间',
+  last_access_time  datetime                                comment 'session最后访问时间',
+  expire_time       int(5)        default 0                 comment '超时时间,单位为分钟',
+  primary key (sessionId)
+) engine=innodb comment = '在线用户记录';
+
+
+-- ----------------------------
+-- 16、定时任务调度表
+-- ----------------------------
+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正常 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, '');
+
+
+-- ----------------------------
+-- 17、定时任务调度日志表
+-- ----------------------------
+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正常 1失败)',
+  exception_info      varchar(2000)  default ''                 comment '异常信息',
+  create_time         datetime                                  comment '创建时间',
+  primary key (job_log_id)
+) engine=innodb comment = '定时任务调度日志表';
+
+
+-- ----------------------------
+-- 18、通知公告表
+-- ----------------------------
+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正常 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, '管理员');
+insert into sys_notice values('3', '若依开源框架介绍', '1', '<p><span style=\"color: rgb(230, 0, 0);\">项目介绍</span></p><p><font color=\"#333333\">RuoYi开源项目是为企业用户定制的后台脚手架框架,为企业打造的一站式解决方案,降低企业开发成本,提升开发效率。主要包括用户管理、角色管理、部门管理、菜单管理、参数管理、字典管理、</font><span style=\"color: rgb(51, 51, 51);\">岗位管理</span><span style=\"color: rgb(51, 51, 51);\">、定时任务</span><span style=\"color: rgb(51, 51, 51);\">、</span><span style=\"color: rgb(51, 51, 51);\">服务监控、登录日志、操作日志、代码生成等功能。其中,还支持多数据源、数据权限、国际化、Redis缓存、Docker部署、滑动验证码、第三方认证登录、分布式事务、</span><font color=\"#333333\">分布式文件存储</font><span style=\"color: rgb(51, 51, 51);\">、分库分表处理等技术特点。</span></p><p><img src=\"https://foruda.gitee.com/images/1705030583977401651/5ed5db6a_1151004.png\" style=\"width: 64px;\"><br></p><p><span style=\"color: rgb(230, 0, 0);\">官网及演示</span></p><p><span style=\"color: rgb(51, 51, 51);\">若依官网地址:&nbsp;</span><a href=\"http://ruoyi.vip\" target=\"_blank\">http://ruoyi.vip</a><a href=\"http://ruoyi.vip\" target=\"_blank\"></a></p><p><span style=\"color: rgb(51, 51, 51);\">若依文档地址:&nbsp;</span><a href=\"http://doc.ruoyi.vip\" target=\"_blank\">http://doc.ruoyi.vip</a><br></p><p><span style=\"color: rgb(51, 51, 51);\">演示地址【不分离版】:&nbsp;</span><a href=\"http://demo.ruoyi.vip\" target=\"_blank\">http://demo.ruoyi.vip</a></p><p><span style=\"color: rgb(51, 51, 51);\">演示地址【分离版本】:&nbsp;</span><a href=\"http://vue.ruoyi.vip\" target=\"_blank\">http://vue.ruoyi.vip</a></p><p><span style=\"color: rgb(51, 51, 51);\">演示地址【微服务版】:&nbsp;</span><a href=\"http://cloud.ruoyi.vip\" target=\"_blank\">http://cloud.ruoyi.vip</a></p><p><span style=\"color: rgb(51, 51, 51);\">演示地址【移动端版】:&nbsp;</span><a href=\"http://h5.ruoyi.vip\" target=\"_blank\">http://h5.ruoyi.vip</a></p><p><br style=\"color: rgb(48, 49, 51); font-family: &quot;Helvetica Neue&quot;, Helvetica, Arial, sans-serif; font-size: 12px;\"></p>', '0', 'admin', sysdate(), '', null, '管理员');
+
+
+-- ----------------------------
+-- 19、代码生成业务表
+-- ----------------------------
+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树表操作 sub主子表操作)',
+  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 '生成功能作者',
+  form_col_num         int(1)          default 1                  comment '表单布局(单列 双列 三列)',
+  gen_type             char(1)         default '0'                comment '生成代码方式(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 = '代码生成业务表';
+
+
+-- ----------------------------
+-- 20、代码生成业务表字段
+-- ----------------------------
+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 = '代码生成业务表字段';
\ No newline at end of file

--
Gitblit v1.7.1